[
  {
    "path": "Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project>\n  <Import Project=\"Sdk.props\" Sdk=\"Microsoft.NET.Sdk\" />\n  <PropertyGroup>\n    <AssemblyName>BeeBuildProgramCommon.Data</AssemblyName>\n    <TargetFramework>netstandard2.1</TargetFramework>\n    <GenerateDocumentationFile>false</GenerateDocumentationFile>\n    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>\n    <EnableDefaultItems>false</EnableDefaultItems>\n    <LangVersion>latest</LangVersion>\n    <NoWarn>1701</NoWarn>\n  </PropertyGroup>\n  <ItemGroup>\n    <Compile Include=\"Data.cs\" />\n  </ItemGroup>\n  <Import Project=\"Sdk.targets\" Sdk=\"Microsoft.NET.Sdk\" />\n</Project>\n"
  },
  {
    "path": "Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/Data.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace BeeBuildProgramCommon.Data\n{\n    public class PackageInfo\n    {\n        public string Name;\n        public string ResolvedPath;\n    }\n\n    public struct Version\n    {\n        public int Release, Major, Minor;\n\n        public Version(int release, int major, int minor)\n        {\n            Release = release;\n            Major = major;\n            Minor = minor;\n        }\n    }\n\n    public class ConfigurationData\n    {\n        public string Il2CppDir;\n        public string UnityLinkerPath;\n        public string Il2CppPath;\n        public string NetCoreRunPath;\n        public string DotNetExe;\n        public string EditorContentsPath;\n        public PackageInfo[] Packages;\n        public string UnityVersion;\n        public Version UnityVersionNumeric;\n        public string UnitySourceCodePath;\n        public bool Batchmode;\n        public bool EmitDataForBeeWhy;\n        public string NamedPipeOrUnixSocket;\n    }\n}\n"
  },
  {
    "path": "Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/Data.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace PlayerBuildProgramLibrary.Data\n{\n    public class Plugin\n    {\n        public string AssetPath;\n        public string DestinationPath;\n        public string Architecture;\n        public string CompileFlags;\n        public bool AddToEmbeddedBinaries;\n        public override string ToString()\n        {\n            return $\"'{AssetPath} -> '{DestinationPath}' ({Architecture})\";\n        }\n    }\n\n    public class PluginsData\n    {\n        public Plugin[] Plugins = new Plugin[0];\n    }\n\n    public class GenerateNativePluginsForAssembliesArgs\n    {\n        public string PluginOutputFolder;\n        public string SymbolOutputFolder;\n        public string[] Assemblies;\n    }\n\n    public class GenerateNativePluginsForAssembliesSettings\n    {\n        public bool HasCallback;\n        public string DisplayName;\n        public string[] AdditionalInputFiles = new string[0];\n    }\n\n    public class PlayerBuildConfig\n    {\n        public string DestinationPath;\n        public string StagingArea;\n        public string DataFolder;\n        public string CompanyName;\n        public string ProductName;\n        public string PlayerPackage;\n        public string ApplicationIdentifier;\n        public string Architecture;\n        public ScriptingBackend ScriptingBackend;\n        public bool NoGUID;\n        public bool InstallIntoBuildsFolder;\n        public bool GenerateIdeProject;\n        public bool Development;\n        public bool UseNewInputSystem;\n        public GenerateNativePluginsForAssembliesSettings GenerateNativePluginsForAssembliesSettings;\n        public Services Services;\n        public string[] ManagedAssemblies;\n        public StreamingAssetsFile[] StreamingAssetsFiles;\n    }\n\n    public class BuiltFilesOutput\n    {\n        public string[] Files = new string[0];\n        public string BootConfigArtifact;\n    }\n\n    public class LinkerConfig\n    {\n        public string[] LinkXmlFiles = new string[0];\n        public string[] AssembliesToProcess = new string[0];\n        public string EditorToLinkerData;\n        public string Runtime;\n        public string Profile;\n        public string Ruleset;\n        public string ModulesAssetPath;\n        public string[] AdditionalArgs = new string[0];\n        public bool AllowDebugging;\n        public bool PerformEngineStripping;\n    }\n\n    public class Il2CppConfig\n    {\n        public bool EnableDeepProfilingSupport;\n        public bool EnableFullGenericSharing;\n        public string Profile;\n        public string[] IDEProjectDefines;\n\n        public string ConfigurationName;\n        public bool GcWBarrierValidation;\n        public bool GcIncremental;\n\n        public string[] AdditionalCppFiles = new string[0];\n        public string[] AdditionalArgs = new string[0];\n        public string CompilerFlags;\n        public string[] AdditionalLibraries;\n        public string[] AdditionalDefines;\n        public string[] AdditionalIncludeDirectories;\n        public string[] AdditionalLinkDirectories;\n        public string LinkerFlags;\n        public string LinkerFlagsFile;\n        public string ExtraTypes;\n        public bool CreateSymbolFiles;\n        public bool AllowDebugging;\n        public string SysRootPath;\n        public string ToolChainPath;\n        public string RelativeDataPath;\n        public bool GenerateUsymFile;\n        public string UsymtoolPath;\n    }\n\n    public class Services\n    {\n        public bool EnableUnityConnect;\n        public bool EnablePerformanceReporting;\n        public bool EnableAnalytics;\n        public bool EnableCrashReporting;\n        public bool EnableInsights;\n    }\n\n    public class StreamingAssetsFile\n    {\n        public string File;\n        public string RelativePath;\n    }\n\n    public enum ScriptingBackend\n    {\n        Mono,\n        IL2CPP,\n        CoreCLR,\n    }\n}\n"
  },
  {
    "path": "Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/PlayerBuildProgramLibrary.Data.gen.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project>\n  <Import Project=\"Sdk.props\" Sdk=\"Microsoft.NET.Sdk\" />\n  <PropertyGroup>\n    <AssemblyName>PlayerBuildProgramLibrary.Data</AssemblyName>\n    <TargetFramework>netstandard2.1</TargetFramework>\n    <GenerateDocumentationFile>false</GenerateDocumentationFile>\n    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>\n    <EnableDefaultItems>false</EnableDefaultItems>\n    <LangVersion>latest</LangVersion>\n    <NoWarn>1701</NoWarn>\n    <AssemblyName>PlayerBuildProgramLibrary.Data</AssemblyName>\n  </PropertyGroup>\n  <ItemGroup>\n    <Compile Include=\"Data.cs\" />\n    <ProjectReference Include=\"../BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj\" />\n  </ItemGroup>\n  <Import Project=\"Sdk.targets\" Sdk=\"Microsoft.NET.Sdk\" />\n</Project>\n"
  },
  {
    "path": "Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/Data.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace ScriptCompilationBuildProgram.Data\n{\n    public static class Constants\n    {\n        public const string ScriptAssembliesTarget = \"ScriptAssemblies\";\n        public const string ScriptAssembliesAndTypeDBTarget = \"ScriptAssembliesAndTypeDB\";\n        public const string MovedFromExtension = \"mvfrm\";\n    }\n\n    public class ScriptCompilationData\n    {\n        public AssemblyData[] Assemblies;\n        public AssemblyData[] CodegenAssemblies;\n        public string DotnetRuntimePath;\n        public string DotnetRoslynPath;\n        public string MovedFromExtractorPath;\n        public string OutputDirectory;\n        public bool Debug;\n        public string BuildTarget;\n        public string Localization;\n        public string BuildPlayerDataOutput;\n        public bool ExtractRuntimeInitializeOnLoads;\n        public bool EnableDiagnostics;\n        public bool EmitInfoForScriptUpdater;\n        public string[] AssembliesToScanForTypeDB;\n        public string[] SearchPaths;\n    }\n\n    public class AssemblyData\n    {\n        public string Name;\n        public string[] SourceFiles = new string[0];\n        public string[] Defines = new string[0];\n        public string[] PrebuiltReferences = new string[0];\n        public int[] References = new int[0];\n        public bool AllowUnsafeCode;\n        public string RuleSet;\n        public string AnalyzerConfigPath;\n        public string LanguageVersion;\n        public bool UseDeterministicCompilation;\n        public bool SuppressCompilerWarnings;\n        public string[] Analyzers = new string[0];\n        public string[] AdditionalFiles = new string[0];\n        public string Asmdef;\n        public string[] BclDirectories = new string[0];\n        public string[] CustomCompilerOptions = new string[0];\n        public int DebugIndex;\n        public bool SkipCodeGen;\n        public string Path;\n    }\n\n    public class ScriptCompilationData_Out\n    {\n        public AssemblyData_Out[] Assemblies;\n        public bool LocalizeCompilerMessages;\n    }\n\n    public class AssemblyData_Out\n    {\n        public string Path;\n        public string ScriptUpdaterRsp;\n        public string MovedFromExtractorFile;\n    }\n}\n"
  },
  {
    "path": "Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/ScriptCompilationBuildProgram.Data.gen.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project>\n  <Import Project=\"Sdk.props\" Sdk=\"Microsoft.NET.Sdk\" />\n  <PropertyGroup>\n    <AssemblyName>ScriptCompilationBuildProgram.Data</AssemblyName>\n    <TargetFramework>netstandard2.1</TargetFramework>\n    <GenerateDocumentationFile>false</GenerateDocumentationFile>\n    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>\n    <EnableDefaultItems>false</EnableDefaultItems>\n    <LangVersion>latest</LangVersion>\n    <NoWarn>1701</NoWarn>\n  </PropertyGroup>\n  <ItemGroup>\n    <Compile Include=\"Data.cs\" />\n    <ProjectReference Include=\"../BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj\" />\n  </ItemGroup>\n  <Import Project=\"Sdk.targets\" Sdk=\"Microsoft.NET.Sdk\" />\n</Project>\n"
  },
  {
    "path": "Editor/Mono/2D/Common/ScriptBindings/SpriteEditorExtension.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.U2D;\n\nnamespace UnityEditor.U2D\n{\n    [NativeHeader(\"Editor/Src/2D/SpriteEditorExtension.h\")]\n    public static class SpriteEditorExtension\n    {\n        public static GUID GetSpriteID(this Sprite sprite)\n        {\n            return new GUID(GetSpriteIDScripting(sprite));\n        }\n\n        public static void SetSpriteID(this Sprite sprite, GUID guid)\n        {\n            SetSpriteIDScripting(sprite, guid.ToString());\n        }\n\n        private static extern string GetSpriteIDScripting([NotNull] Sprite sprite);\n        private static extern void SetSpriteIDScripting([NotNull] Sprite sprite, string spriteID);\n        internal static extern SpriteAtlas GetActiveAtlas([NotNull] this Sprite sprite);\n        internal static extern string GetActiveAtlasName([NotNull] this Sprite sprite);\n        internal static extern Texture2D GetActiveAtlasTexture([NotNull] this Sprite sprite);\n        internal static extern Rect GetActiveAtlasTextureRect([NotNull] this Sprite sprite);\n        internal static extern Vector2 GetActiveAtlasTextureRectOffset([NotNull] this Sprite sprite);\n        internal static extern Texture2D GetActiveAtlasAlphaTexture([NotNull] this Sprite sprite);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/2D/Common/SpriteEditorUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEngine;\nusing UnityEngine.Assertions;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditorInternal\n{\n    static internal class SpriteEditorUtility\n    {\n        public static Vector2 GetPivotValue(SpriteAlignment alignment, Vector2 customOffset)\n        {\n            switch (alignment)\n            {\n                case SpriteAlignment.BottomLeft:\n                    return new Vector2(0f, 0f);\n                case SpriteAlignment.BottomCenter:\n                    return new Vector2(0.5f, 0f);\n                case SpriteAlignment.BottomRight:\n                    return new Vector2(1f, 0f);\n\n                case SpriteAlignment.LeftCenter:\n                    return new Vector2(0f, 0.5f);\n                case SpriteAlignment.Center:\n                    return new Vector2(0.5f, 0.5f);\n                case SpriteAlignment.RightCenter:\n                    return new Vector2(1f, 0.5f);\n\n                case SpriteAlignment.TopLeft:\n                    return new Vector2(0f, 1f);\n                case SpriteAlignment.TopCenter:\n                    return new Vector2(0.5f, 1f);\n                case SpriteAlignment.TopRight:\n                    return new Vector2(1f, 1f);\n\n                case SpriteAlignment.Custom:\n                    return customOffset;\n            }\n            return Vector2.zero;\n        }\n\n        public static Rect RoundedRect(Rect rect)\n        {\n            return new Rect(\n                Mathf.RoundToInt(rect.xMin),\n                Mathf.RoundToInt(rect.yMin),\n                Mathf.RoundToInt(rect.width),\n                Mathf.RoundToInt(rect.height)\n            );\n        }\n\n        public static Rect RoundToInt(Rect r)\n        {\n            r.xMin = Mathf.RoundToInt(r.xMin);\n            r.yMin = Mathf.RoundToInt(r.yMin);\n            r.xMax = Mathf.RoundToInt(r.xMax);\n            r.yMax = Mathf.RoundToInt(r.yMax);\n\n            return r;\n        }\n\n        public static Rect ClampedRect(Rect rect, Rect clamp, bool maintainSize)\n        {\n            Rect r = new Rect(rect);\n\n            if (maintainSize)\n            {\n                Vector2 center = rect.center;\n                if (center.x + Mathf.Abs(rect.width) * .5f > clamp.xMax)\n                    center.x = clamp.xMax - rect.width * .5f;\n                if (center.x - Mathf.Abs(rect.width) * .5f < clamp.xMin)\n                    center.x = clamp.xMin + rect.width * .5f;\n                if (center.y + Mathf.Abs(rect.height) * .5f > clamp.yMax)\n                    center.y = clamp.yMax - rect.height * .5f;\n                if (center.y - Mathf.Abs(rect.height) * .5f < clamp.yMin)\n                    center.y = clamp.yMin + rect.height * .5f;\n                r.center = center;\n            }\n            else\n            {\n                if (r.width > 0f)\n                {\n                    r.xMin = Mathf.Max(rect.xMin, clamp.xMin);\n                    r.xMax = Mathf.Min(rect.xMax, clamp.xMax);\n                }\n                else\n                {\n                    r.xMin = Mathf.Min(rect.xMin, clamp.xMax);\n                    r.xMax = Mathf.Max(rect.xMax, clamp.xMin);\n                }\n                if (r.height > 0f)\n                {\n                    r.yMin = Mathf.Max(rect.yMin, clamp.yMin);\n                    r.yMax = Mathf.Min(rect.yMax, clamp.yMax);\n                }\n                else\n                {\n                    r.yMin = Mathf.Min(rect.yMin, clamp.yMax);\n                    r.yMax = Mathf.Max(rect.yMax, clamp.yMin);\n                }\n            }\n\n            r.width = Mathf.Abs(r.width);\n            r.height = Mathf.Abs(r.height);\n\n            return r;\n        }\n\n        public static void DrawBox(Rect position)\n        {\n            Vector3[] points = new Vector3[5];\n            int i = 0;\n            points[i++] = new Vector3(position.xMin, position.yMin, 0f);\n            points[i++] = new Vector3(position.xMax, position.yMin, 0f);\n            points[i++] = new Vector3(position.xMax, position.yMax, 0f);\n            points[i++] = new Vector3(position.xMin, position.yMax, 0f);\n\n            DrawLine(points[0], points[1]);\n            DrawLine(points[1], points[2]);\n            DrawLine(points[2], points[3]);\n            DrawLine(points[3], points[0]);\n        }\n\n        public static void DrawLine(Vector3 p1, Vector3 p2)\n        {\n            Assert.IsTrue(Event.current.type == EventType.Repaint);\n            GL.Vertex(p1);\n            GL.Vertex(p2);\n        }\n\n        public static void BeginLines(Color color)\n        {\n            Assert.IsTrue(Event.current.type == EventType.Repaint);\n            HandleUtility.ApplyWireMaterial();\n            GL.PushMatrix();\n            GL.MultMatrix(Handles.matrix);\n            GL.Begin(GL.LINES);\n            GL.Color(color);\n        }\n\n        public static void EndLines()\n        {\n            Assert.IsTrue(Event.current.type == EventType.Repaint);\n            GL.End();\n            GL.PopMatrix();\n        }\n\n        public static void FourIntFields(Vector2 rectSize, GUIContent label, GUIContent labelX, GUIContent labelY, GUIContent labelZ, GUIContent labelW, ref int x, ref int y, ref int z, ref int w)\n        {\n            Rect rect = GUILayoutUtility.GetRect(rectSize.x, rectSize.y);\n\n            Rect labelRect = rect;\n            labelRect.width = EditorGUIUtility.labelWidth;\n            labelRect.height = EditorGUI.kSingleLineHeight;\n\n            GUI.Label(labelRect, label);\n\n            Rect fieldRect = rect;\n            fieldRect.width -= EditorGUIUtility.labelWidth;\n            fieldRect.height = EditorGUI.kSingleLineHeight;\n            fieldRect.x += EditorGUIUtility.labelWidth;\n            fieldRect.width /= 2;\n            fieldRect.width -= EditorGUI.kSpacingSubLabel;\n\n            float oldLabelWidth = EditorGUIUtility.labelWidth;\n            EditorGUIUtility.labelWidth = EditorGUI.CalcPrefixLabelWidth(labelX);\n\n            GUI.SetNextControlName(\"FourIntFields_x\");\n            x = EditorGUI.IntField(fieldRect, labelX, x);\n            fieldRect.x += fieldRect.width + EditorGUI.kSpacing;\n            GUI.SetNextControlName(\"FourIntFields_y\");\n            y = EditorGUI.IntField(fieldRect, labelY, y);\n            fieldRect.y += EditorGUI.kSingleLineHeight + EditorGUI.kVerticalSpacingMultiField;\n            fieldRect.x -= fieldRect.width + EditorGUI.kSpacing;\n            GUI.SetNextControlName(\"FourIntFields_z\");\n            z = EditorGUI.IntField(fieldRect, labelZ, z);\n            fieldRect.x += fieldRect.width + EditorGUI.kSpacing;\n            GUI.SetNextControlName(\"FourIntFields_w\");\n            w = EditorGUI.IntField(fieldRect, labelW, w);\n\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/2D/Common/TexturePlatformSettingsController.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor.U2D.Interface;\nusing UnityEngine;\nusing UnityEngine.Assertions;\nusing TargetAttributes = UnityEditor.BuildTargetDiscovery.TargetAttributes;\n\nnamespace UnityEditor.U2D.Common\n{\n    internal class TexturePlatformSettingsViewController : ITexturePlatformSettingsController\n    {\n        public bool HandleDefaultSettings(List<TextureImporterPlatformSettings> platformSettings, ITexturePlatformSettingsView view, ITexturePlatformSettingsFormatHelper formatHelper)\n        {\n            Assert.IsTrue(platformSettings.Count > 0, \"At least 1 platform setting is needed to display the texture platform setting UI.\");\n\n            var allSize = platformSettings[0].maxTextureSize;\n            var allFormat = platformSettings[0].format;\n            var allCompression = platformSettings[0].textureCompression;\n            var allUseCrunchedCompression = platformSettings[0].crunchedCompression;\n            var allCompressionQuality = platformSettings[0].compressionQuality;\n\n            var mixedSize = false;\n            var mixedFormat = false;\n            var mixedCompression = false;\n            var mixedUseCrunchedCompression = false;\n            var mixedCompressionQuality = false;\n\n            var sizeChanged = false;\n            var formatChanged = false;\n            var compressionChanged = false;\n            var useCrunchedCompressionChanged = false;\n            var compressionQualityChanged = false;\n\n            for (var i = 1; i < platformSettings.Count; ++i)\n            {\n                var settings = platformSettings[i];\n                if (settings.maxTextureSize != allSize)\n                    mixedSize = true;\n                if (settings.format != allFormat)\n                    mixedFormat = true;\n                if (settings.textureCompression != allCompression)\n                    mixedCompression = true;\n                if (settings.crunchedCompression != allUseCrunchedCompression)\n                    mixedUseCrunchedCompression = true;\n                if (settings.compressionQuality != allCompressionQuality)\n                    mixedCompressionQuality = true;\n            }\n\n            allSize = view.DrawMaxSize(allSize, mixedSize, false, out sizeChanged);\n\n            int[] formatValues = null;\n            string[] formatStrings = null;\n            formatHelper.AcquireDefaultTextureFormatValuesAndStrings(out formatValues, out formatStrings);\n\n            allFormat = view.DrawFormat(allFormat, formatValues, formatStrings, mixedFormat, false, out formatChanged);\n\n            if (allFormat == TextureImporterFormat.Automatic && (!mixedFormat || formatChanged))\n            {\n                allCompression = view.DrawCompression(allCompression, mixedCompression, false, out compressionChanged);\n\n                if (allCompression != TextureImporterCompression.Uncompressed && (!mixedCompression || compressionChanged))\n                {\n                    allUseCrunchedCompression = view.DrawUseCrunchedCompression(allUseCrunchedCompression,\n                        mixedUseCrunchedCompression, false, out useCrunchedCompressionChanged);\n\n                    if (allUseCrunchedCompression && (!mixedUseCrunchedCompression || useCrunchedCompressionChanged))\n                    {\n                        allCompressionQuality = view.DrawCompressionQualitySlider(allCompressionQuality,\n                            mixedCompressionQuality, false, out compressionQualityChanged);\n                    }\n                }\n            }\n\n            if (sizeChanged || compressionChanged || formatChanged || useCrunchedCompressionChanged || compressionQualityChanged)\n            {\n                for (var i = 0; i < platformSettings.Count; ++i)\n                {\n                    if (sizeChanged)\n                        platformSettings[i].maxTextureSize = allSize;\n                    if (formatChanged)\n                        platformSettings[i].format = allFormat;\n                    if (compressionChanged)\n                        platformSettings[i].textureCompression = allCompression;\n                    if (useCrunchedCompressionChanged)\n                        platformSettings[i].crunchedCompression = allUseCrunchedCompression;\n                    if (compressionQualityChanged)\n                        platformSettings[i].compressionQuality = allCompressionQuality;\n                }\n                return true;\n            }\n            else\n                return false;\n        }\n\n        public bool HandlePlatformSettings(BuildTarget buildTarget, List<TextureImporterPlatformSettings> platformSettings, ITexturePlatformSettingsView view, ITexturePlatformSettingsFormatHelper formatHelper)\n        {\n            Assert.IsTrue(platformSettings.Count > 0, \"At least 1 platform setting is needed to display the texture platform setting UI.\");\n\n            var allOverride = platformSettings[0].overridden;\n            var allSize = platformSettings[0].maxTextureSize;\n            var allFormat = platformSettings[0].format;\n            var allCompressionQuality = platformSettings[0].compressionQuality;\n            var allAlphaSplit = platformSettings[0].allowsAlphaSplitting;\n\n            var mixedOverride = false;\n            var mixedSize = false;\n            var mixedFormat = false;\n            var mixedCompression = false;\n            var mixedAlphaSplit = false;\n\n            var overrideChanged = false;\n            var sizeChanged = false;\n            var formatChanged = false;\n            var compressionChanged = false;\n            var alphaSplitChanged = false;\n\n            for (var i = 1; i < platformSettings.Count; ++i)\n            {\n                var settings = platformSettings[i];\n                if (settings.overridden != allOverride)\n                    mixedOverride = true;\n                if (settings.maxTextureSize != allSize)\n                    mixedSize = true;\n                if (settings.format != allFormat)\n                    mixedFormat = true;\n                if (settings.compressionQuality != allCompressionQuality)\n                    mixedCompression = true;\n                if (settings.allowsAlphaSplitting != allAlphaSplit)\n                    mixedAlphaSplit = true;\n            }\n\n            allOverride = view.DrawOverride(allOverride, mixedOverride, out overrideChanged);\n\n            allSize = view.DrawMaxSize(allSize, mixedSize, mixedOverride || !allOverride, out sizeChanged);\n\n            int[] formatValues = null;\n            string[] formatStrings = null;\n\n            formatHelper.AcquireTextureFormatValuesAndStrings(buildTarget, out formatValues, out formatStrings);\n\n            allFormat = view.DrawFormat(allFormat, formatValues, formatStrings, mixedFormat, mixedOverride || !allOverride, out formatChanged);\n\n            if (!mixedFormat && formatHelper.TextureFormatRequireCompressionQualityInput(allFormat))\n            {\n                bool showAsEnum = BuildTargetDiscovery.PlatformHasFlag(buildTarget, TargetAttributes.HasIntegratedGPU);\n\n                if (showAsEnum)\n                {\n                    var compressionMode = 1;\n                    if (allCompressionQuality == (int)TextureCompressionQuality.Fast)\n                        compressionMode = 0;\n                    else if (allCompressionQuality == (int)TextureCompressionQuality.Best)\n                        compressionMode = 2;\n\n                    compressionMode = view.DrawCompressionQualityPopup(compressionMode, mixedCompression, mixedOverride || !allOverride, out compressionChanged);\n\n                    if (compressionChanged)\n                    {\n                        switch (compressionMode)\n                        {\n                            case 0: allCompressionQuality = (int)TextureCompressionQuality.Fast; break;\n                            case 1: allCompressionQuality = (int)TextureCompressionQuality.Normal; break;\n                            case 2: allCompressionQuality = (int)TextureCompressionQuality.Best; break;\n\n                            default:\n                                Assert.IsTrue(false, \"ITexturePlatformSettingsView.DrawCompressionQualityPopup should never return compression option value that's not 0, 1 or 2.\");\n                                break;\n                        }\n                    }\n                }\n                else\n                {\n                    allCompressionQuality = view.DrawCompressionQualitySlider(allCompressionQuality, mixedCompression, mixedOverride || !allOverride, out compressionChanged);\n                }\n\n                // show the ETC1 split option only for sprites on platforms supporting ETC.\n                bool isETCPlatform = TextureImporter.IsETC1SupportedByBuildTarget(buildTarget);\n                bool isETCFormatSelected = TextureImporter.IsTextureFormatETC1Compression((TextureFormat)allFormat);\n                if (isETCPlatform && isETCFormatSelected)\n                {\n                    allAlphaSplit = view.DrawAlphaSplit(allAlphaSplit, mixedAlphaSplit, mixedOverride || !allOverride, out alphaSplitChanged);\n                }\n            }\n\n            if (overrideChanged || sizeChanged || formatChanged || compressionChanged || alphaSplitChanged)\n            {\n                for (var i = 0; i < platformSettings.Count; ++i)\n                {\n                    if (overrideChanged)\n                        platformSettings[i].overridden = allOverride;\n                    if (sizeChanged)\n                        platformSettings[i].maxTextureSize = allSize;\n                    if (formatChanged)\n                        platformSettings[i].format = allFormat;\n                    if (compressionChanged)\n                        platformSettings[i].compressionQuality = allCompressionQuality;\n                    if (alphaSplitChanged)\n                        platformSettings[i].allowsAlphaSplitting = allAlphaSplit;\n                }\n\n                return true;\n            }\n            else\n                return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/2D/Common/TexturePlatformSettingsFormatHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.U2D.Interface;\n\nnamespace UnityEditor.U2D.Common\n{\n    internal class TexturePlatformSettingsFormatHelper : ITexturePlatformSettingsFormatHelper\n    {\n        public void AcquireTextureFormatValuesAndStrings(BuildTarget buildTarget, out int[] formatValues, out string[] formatStrings)\n        {\n            TextureImportValidFormats.GetPlatformTextureFormatValuesAndStrings(TextureImporterType.Sprite, buildTarget,\n                out formatValues, out formatStrings);\n        }\n\n        public void AcquireDefaultTextureFormatValuesAndStrings(out int[] formatValues, out string[] formatStrings)\n        {\n            TextureImportValidFormats.GetDefaultTextureFormatValuesAndStrings(TextureImporterType.Sprite,\n                out formatValues, out formatStrings);\n        }\n\n        public bool TextureFormatRequireCompressionQualityInput(TextureImporterFormat format)\n        {\n            return TextureImporterInspector.IsFormatRequireCompressionSetting(format);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/2D/Common/TexturePlatformSettingsView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor.U2D.Interface;\n\nnamespace UnityEditor.U2D.Common\n{\n    internal class TexturePlatformSettingsView : ITexturePlatformSettingsView\n    {\n        class Styles\n        {\n            public readonly GUIContent textureFormatLabel = EditorGUIUtility.TrTextContent(\"Format\");\n            public readonly GUIContent maxTextureSizeLabel = EditorGUIUtility.TrTextContent(\"Max Texture Size\", \"Maximum size of the packed texture.\");\n            public readonly GUIContent compressionLabel = EditorGUIUtility.TrTextContent(\"Compression\", \"How will this texture be compressed?\");\n            public readonly GUIContent useCrunchedCompressionLabel = EditorGUIUtility.TrTextContent(\"Use Crunch Compression\", \"Texture is crunch-compressed to save space on disk when applicable.\");\n            public readonly GUIContent useAlphaSplitLabel = EditorGUIUtility.TrTextContent(\"Split Alpha Channel\", \"Alpha for this texture will be preserved by splitting the alpha channel to another texture, and both resulting textures will be compressed using ETC1.\");\n            public readonly GUIContent compressionQualityLabel = EditorGUIUtility.TrTextContent(\"Compressor Quality\");\n            public readonly GUIContent compressionQualitySliderLabel = EditorGUIUtility.TrTextContent(\"Compressor Quality\", \"Use the slider to adjust compression quality from 0 (Fastest) to 100 (Best)\");\n\n            public readonly int[] kMaxTextureSizeValues = { 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384 };\n            public readonly GUIContent[] kMaxTextureSizeStrings;\n\n            public readonly GUIContent[] kTextureCompressionOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"None\", \"Texture is not compressed.\"),\n                EditorGUIUtility.TrTextContent(\"Low Quality\", \"Texture compressed with low quality but high performance, high compression format.\"),\n                EditorGUIUtility.TrTextContent(\"Normal Quality\", \"Texture is compressed with a standard format.\"),\n                EditorGUIUtility.TrTextContent(\"High Quality\", \"Texture compressed with a high quality format.\"),\n            };\n\n            public readonly int[] kTextureCompressionValues =\n            {\n                (int)TextureImporterCompression.Uncompressed,\n                (int)TextureImporterCompression.CompressedLQ,\n                (int)TextureImporterCompression.Compressed,\n                (int)TextureImporterCompression.CompressedHQ\n            };\n\n            public readonly GUIContent[] kMobileCompressionQualityOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Fast\"),\n                EditorGUIUtility.TrTextContent(\"Normal\"),\n                EditorGUIUtility.TrTextContent(\"Best\")\n            };\n\n            public Styles()\n            {\n                kMaxTextureSizeStrings = new GUIContent[kMaxTextureSizeValues.Length];\n                for (var i = 0; i < kMaxTextureSizeValues.Length; ++i)\n                    kMaxTextureSizeStrings[i] = EditorGUIUtility.TextContent(string.Format(\"{0}\", kMaxTextureSizeValues[i]));\n            }\n        }\n\n        private static Styles s_Styles;\n\n        public string buildPlatformTitle { get; set; }\n\n        internal TexturePlatformSettingsView()\n        {\n            s_Styles = s_Styles ?? new Styles();\n        }\n\n        public virtual TextureImporterCompression DrawCompression(TextureImporterCompression defaultValue, bool isMixedValue, bool isDisabled, out bool changed)\n        {\n            using (new EditorGUI.DisabledScope(isDisabled))\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = isMixedValue;\n                defaultValue = (TextureImporterCompression)EditorGUILayout.IntPopup(s_Styles.compressionLabel,\n                    (int)defaultValue, s_Styles.kTextureCompressionOptions, s_Styles.kTextureCompressionValues);\n                EditorGUI.showMixedValue = false;\n                changed = EditorGUI.EndChangeCheck();\n                return defaultValue;\n            }\n        }\n\n        public virtual bool DrawUseCrunchedCompression(bool defaultValue, bool isMixedValue, bool isDisabled, out bool changed)\n        {\n            using (new EditorGUI.DisabledScope(isDisabled))\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = isMixedValue;\n                defaultValue = EditorGUILayout.Toggle(s_Styles.useCrunchedCompressionLabel, defaultValue);\n                EditorGUI.showMixedValue = false;\n                changed = EditorGUI.EndChangeCheck();\n                return defaultValue;\n            }\n        }\n\n        public virtual bool DrawOverride(bool defaultValue, bool isMixedValue, out bool changed)\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = isMixedValue;\n            defaultValue = EditorGUILayout.ToggleLeft(EditorGUIUtility.TempContent(\"Override for \" + buildPlatformTitle), defaultValue);\n            EditorGUI.showMixedValue = false;\n            changed = EditorGUI.EndChangeCheck();\n            return defaultValue;\n        }\n\n        public virtual int DrawMaxSize(int defaultValue, bool isMixedValue, bool isDisabled, out bool changed)\n        {\n            using (new EditorGUI.DisabledScope(isDisabled))\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = isMixedValue;\n                defaultValue = EditorGUILayout.IntPopup(s_Styles.maxTextureSizeLabel, defaultValue,\n                    s_Styles.kMaxTextureSizeStrings, s_Styles.kMaxTextureSizeValues);\n                EditorGUI.showMixedValue = false;\n                changed = EditorGUI.EndChangeCheck();\n                return defaultValue;\n            }\n        }\n\n        public virtual TextureImporterFormat DrawFormat(TextureImporterFormat defaultValue, int[] displayValues, string[] displayStrings, bool isMixedValue, bool isDisabled, out bool changed)\n        {\n            using (new EditorGUI.DisabledScope(isDisabled))\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = isMixedValue;\n                defaultValue = (TextureImporterFormat)EditorGUILayout.IntPopup(s_Styles.textureFormatLabel, (int)defaultValue, EditorGUIUtility.TempContent(displayStrings), displayValues);\n                EditorGUI.showMixedValue = false;\n                changed = EditorGUI.EndChangeCheck();\n                return defaultValue;\n            }\n        }\n\n        public virtual int DrawCompressionQualityPopup(int defaultValue, bool isMixedValue, bool isDisabled, out bool changed)\n        {\n            using (new EditorGUI.DisabledScope(isDisabled))\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = isMixedValue;\n                defaultValue = EditorGUILayout.Popup(s_Styles.compressionQualityLabel, defaultValue,\n                    s_Styles.kMobileCompressionQualityOptions);\n                EditorGUI.showMixedValue = false;\n                changed = EditorGUI.EndChangeCheck();\n                return defaultValue;\n            }\n        }\n\n        public virtual int DrawCompressionQualitySlider(int defaultValue, bool isMixedValue, bool isDisabled, out bool changed)\n        {\n            using (new EditorGUI.DisabledScope(isDisabled))\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = isMixedValue;\n                defaultValue = EditorGUILayout.IntSlider(s_Styles.compressionQualitySliderLabel, defaultValue, 0, 100);\n                EditorGUI.showMixedValue = false;\n                changed = EditorGUI.EndChangeCheck();\n                return defaultValue;\n            }\n        }\n\n        public virtual bool DrawAlphaSplit(bool defaultValue, bool isMixedValue, bool isDisabled, out bool changed)\n        {\n            using (new EditorGUI.DisabledScope(isDisabled))\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = isMixedValue;\n                defaultValue = EditorGUILayout.Toggle(s_Styles.useAlphaSplitLabel, defaultValue);\n                EditorGUI.showMixedValue = false;\n                changed = EditorGUI.EndChangeCheck();\n                return defaultValue;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/2D/Interface/IEvent.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEvent = UnityEngine.Event;\n\n// We are putting this in the Editor folder for now since on SpriteEditorWindow et al. are using it\nnamespace UnityEngine.U2D.Interface\n{\n    internal interface IEvent\n    {\n        EventType type { get; }\n        string commandName { get; }\n        bool control { get; }\n        bool alt { get; }\n        bool shift { get; }\n        KeyCode keyCode { get; }\n        Vector2 mousePosition { get; }\n        int button { get; }\n        EventModifiers modifiers { get; }\n        EventType GetTypeForControl(int id);\n\n        void Use();\n    }\n\n    internal class Event : IEvent\n    {\n        UnityEvent m_Event;\n\n        public Event()\n        {\n            m_Event = UnityEvent.current;\n        }\n\n        public EventType type\n        {\n            get { return m_Event.type; }\n        }\n\n        public string commandName\n        {\n            get { return m_Event.commandName; }\n        }\n\n        public bool control\n        {\n            get { return m_Event.control; }\n        }\n\n        public bool alt\n        {\n            get { return m_Event.alt; }\n        }\n\n        public bool shift\n        {\n            get { return m_Event.shift; }\n        }\n\n        public KeyCode keyCode\n        {\n            get { return m_Event.keyCode; }\n        }\n\n        public Vector2 mousePosition\n        {\n            get { return m_Event.mousePosition; }\n        }\n\n        public int button\n        {\n            get { return m_Event.button; }\n        }\n\n        public void Use()\n        {\n            m_Event.Use();\n        }\n\n        public EventModifiers modifiers\n        {\n            get { return m_Event.modifiers; }\n        }\n\n        public EventType GetTypeForControl(int id)\n        {\n            return m_Event.GetTypeForControl(id);\n        }\n    }\n\n    internal interface IEventSystem\n    {\n        IEvent current { get; }\n    }\n\n    internal class EventSystem : IEventSystem\n    {\n        public IEvent current\n        {\n            get { return new Event(); }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/2D/Interface/ITexturePlatformSetting.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor.U2D.Interface\n{\n    internal interface ITexturePlatformSettingsView\n    {\n        string buildPlatformTitle { get; set; }\n        TextureImporterCompression DrawCompression(TextureImporterCompression defaultValue, bool isMixedValue, bool isDisabled, out bool changed);\n        bool DrawUseCrunchedCompression(bool defaultValue, bool isMixedValue, bool isDisabled, out bool changed);\n        bool DrawAlphaSplit(bool defaultValue, bool isMixedValue, bool isDisabled, out bool changed);\n        bool DrawOverride(bool defaultValue, bool isMixedValue, out bool changed);\n        int DrawMaxSize(int defaultValue, bool isMixedValue, bool isDisabled, out bool changed);\n        TextureImporterFormat DrawFormat(TextureImporterFormat defaultValue, int[] displayValues, string[] displayStrings, bool isMixedValue, bool isDisabled, out bool changed);\n        int DrawCompressionQualityPopup(int defaultValue, bool isMixedValue, bool isDisabled, out bool changed);\n        int DrawCompressionQualitySlider(int defaultValue, bool isMixedValue, bool isDisabled, out bool changed);\n    }\n\n    internal interface ITexturePlatformSettingsFormatHelper\n    {\n        void AcquireTextureFormatValuesAndStrings(BuildTarget buildTarget, out int[] displayValues, out string[] displayStrings);\n        void AcquireDefaultTextureFormatValuesAndStrings(out int[] formatValues, out string[] formatStrings);\n\n        bool TextureFormatRequireCompressionQualityInput(TextureImporterFormat format);\n    }\n\n    internal interface ITexturePlatformSettingsController\n    {\n        bool HandleDefaultSettings(List<TextureImporterPlatformSettings> platformSettings, ITexturePlatformSettingsView view, ITexturePlatformSettingsFormatHelper formatHelper);\n        bool HandlePlatformSettings(BuildTarget buildTarget, List<TextureImporterPlatformSettings> platformSettings, ITexturePlatformSettingsView view, ITexturePlatformSettingsFormatHelper formatHelper);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/2D/SpriteAtlas/EditorSpriteAtlas.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.U2D;\nusing UnityEngine.Bindings;\nusing System;\nusing UnityEditor.AssetImporters;\n\nnamespace UnityEditor.U2D\n{\n    [NativeHeader(\"Runtime/2D/SpriteAtlas/SpriteAtlas.h\")]\n    [NativeHeader(\"Editor/Src/2D/SpriteAtlas/SpriteAtlasPackingUtilities.h\")]\n    public class SpriteAtlasUtility\n    {\n        [FreeFunction(\"SpriteAtlasExtensions::EnableV2Import\")]\n        extern internal static void EnableV2Import(bool onOff);\n\n        [FreeFunction(\"SpriteAtlasExtensions::CleanupAtlasPacking\")]\n        extern public static void CleanupAtlasPacking();\n\n        [FreeFunction(\"CollectAllSpriteAtlasesAndPack\")]\n        extern public static void PackAllAtlases(BuildTarget target, bool canCancel = true);\n\n        [FreeFunction(\"PackSpriteAtlases\")]\n        extern internal static void PackAtlasesInternal(SpriteAtlas[] atlases, BuildTarget target, bool canCancel = true, bool invokedFromImporter = false, bool unloadSprites = false);\n\n        public static void PackAtlases(SpriteAtlas[] atlases, BuildTarget target, bool canCancel = true)\n        {\n            if (atlases == null)\n                throw new ArgumentNullException(\"atlases\", \"Value for parameter atlases is null\");\n            foreach (var atlas in atlases)\n                if (atlas == null)\n                    throw new ArgumentNullException(\"atlases\", \"One of the elements in atlases is null. Please check your Inputs.\");\n            PackAtlasesInternal(atlases, target, canCancel, false, true);\n        }\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    public struct SpriteAtlasTextureSettings\n    {\n        [NativeName(\"anisoLevel\")]\n        private int m_AnisoLevel;\n        [NativeName(\"compressionQuality\")]\n        private int m_CompressionQuality;\n        [NativeName(\"maxTextureSize\")]\n        private int m_MaxTextureSize;\n        [NativeName(\"textureCompression\")]\n        private int m_TextureCompression;\n        [NativeName(\"filterMode\")]\n        private int m_FilterMode;\n        [NativeName(\"generateMipMaps\")]\n        private bool m_GenerateMipMaps;\n        [NativeName(\"readable\")]\n        private bool m_Readable;\n        [NativeName(\"crunchedCompression\")]\n        private bool m_CrunchedCompression;\n        [NativeName(\"sRGB\")]\n        private bool m_sRGB;\n\n        public int maxTextureSize { get { return m_MaxTextureSize; } }\n        public int anisoLevel { get { return m_AnisoLevel; } set { m_AnisoLevel = value; } }\n        public FilterMode filterMode { get { return (FilterMode)m_FilterMode; } set { m_FilterMode = (int)value; } }\n        public bool generateMipMaps { get { return m_GenerateMipMaps; } set { m_GenerateMipMaps = value; } }\n        public bool readable { get { return m_Readable; } set { m_Readable = value; } }\n        public bool sRGB { get { return m_sRGB; } set { m_sRGB = value; } }\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    public struct SpriteAtlasPackingSettings\n    {\n        [NativeName(\"blockOffset\")]\n        private int m_BlockOffset;\n        [NativeName(\"padding\")]\n        private int m_Padding;\n        [NativeName(\"allowAlphaSplitting\")]\n        private bool m_AllowAlphaSplitting;\n        [NativeName(\"enableRotation\")]\n        private bool m_EnableRotation;\n        [NativeName(\"enableTightPacking\")]\n        private bool m_EnableTightPacking;\n        [NativeName(\"enableAlphaDilation\")]\n        private bool m_EnableAlphaDilation;\n\n        public int blockOffset { get { return m_BlockOffset; } set { m_BlockOffset = value; } }\n        public int padding { get { return m_Padding; } set { m_Padding = value; } }\n        public bool enableRotation { get { return m_EnableRotation; } set { m_EnableRotation = value; } }\n        public bool enableTightPacking { get { return m_EnableTightPacking; } set { m_EnableTightPacking = value; } }\n        public bool enableAlphaDilation { get { return m_EnableAlphaDilation; } set { m_EnableAlphaDilation = value; } }\n    }\n\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/TextureImporterTypes.h\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/TextureImporter.bindings.h\")]\n    [NativeHeader(\"Editor/Src/2D/SpriteAtlas/SpriteAtlas_EditorTypes.h\")]\n    [NativeHeader(\"Runtime/2D/SpriteAtlas/SpriteAtlas.h\")]\n    public static class SpriteAtlasExtensions\n    {\n        extern public static void Add([NotNull] this SpriteAtlas spriteAtlas, UnityEngine.Object[] objects);\n        extern public static void Remove([NotNull] this SpriteAtlas spriteAtlas, UnityEngine.Object[] objects);\n        extern internal static void RemoveAt([NotNull] this SpriteAtlas spriteAtlas, int index);\n        extern public static UnityEngine.Object[] GetPackables([NotNull] this SpriteAtlas spriteAtlas);\n        extern internal static void SetV2([NotNull] this SpriteAtlas spriteAtlas);\n        internal static void RegisterAndPackAtlas(this SpriteAtlas spriteAtlas, AssetImportContext context, AssetImporter importer, U2D.ScriptablePacker scriptablePacker)\n        {\n            RegisterAndPackAtlasInternal(spriteAtlas, context, importer, scriptablePacker);\n        }\n        extern private static void RegisterAndPackAtlasInternal([NotNull] this SpriteAtlas spriteAtlas, [NotNull] AssetImportContext context, [NotNull] AssetImporter importer, UnityEngine.Object scriptablePacker);\n        extern public static SpriteAtlasTextureSettings GetTextureSettings([NotNull] this SpriteAtlas spriteAtlas);\n        extern public static void SetTextureSettings([NotNull] this SpriteAtlas spriteAtlas, SpriteAtlasTextureSettings src);\n        extern public static SpriteAtlasPackingSettings GetPackingSettings([NotNull] this SpriteAtlas spriteAtlas);\n        extern public static void SetPackingSettings([NotNull] this SpriteAtlas spriteAtlas, SpriteAtlasPackingSettings src);\n\n        [NativeName(\"GetPlatformSettings\")]\n        extern private static TextureImporterPlatformSettings GetPlatformSettings_Internal([NotNull] this SpriteAtlas spriteAtlas, string buildTarget);\n        public static TextureImporterPlatformSettings GetPlatformSettings(this SpriteAtlas spriteAtlas, string buildTarget)\n        {\n            buildTarget = TextureImporter.GetTexturePlatformSerializationName(buildTarget); // String may refer to a platform group: if != \"Standalone\", ensure it refers to a platform instead. E.g.: \"iOS\", not \"iPhone\".\n            return GetPlatformSettings_Internal(spriteAtlas, buildTarget);\n        }\n\n        [NativeName(\"SetPlatformSettings\")]\n        extern private static void SetPlatformSettings_Internal([NotNull] this SpriteAtlas spriteAtlas, TextureImporterPlatformSettings src);\n        public static void SetPlatformSettings(this SpriteAtlas spriteAtlas, TextureImporterPlatformSettings src)\n        {\n            src.name = TextureImporter.GetTexturePlatformSerializationName(src.name); // String may refer to a platform group: if != \"Standalone\", ensure it refers to a platform instead. E.g.: \"iOS\", not \"iPhone\".\n            SetPlatformSettings_Internal(spriteAtlas, src);\n        }\n\n        extern public static void SetIncludeInBuild([NotNull] this SpriteAtlas spriteAtlas, bool value);\n        extern public static void SetIsVariant([NotNull] this SpriteAtlas spriteAtlas, bool value);\n        extern public static void SetMasterAtlas([NotNull] this SpriteAtlas spriteAtlas, SpriteAtlas value);\n        extern public static void SetVariantScale([NotNull] this SpriteAtlas spriteAtlas, float value);\n        extern public static bool IsIncludeInBuild([NotNull] this SpriteAtlas spriteAtlas);\n        extern public static SpriteAtlas GetMasterAtlas([NotNull] this SpriteAtlas spriteAtlas);\n        extern internal static void CopyMasterAtlasSettings([NotNull] this SpriteAtlas spriteAtlas);\n        extern internal static string GetHash([NotNull] this SpriteAtlas spriteAtlas);\n        extern internal static Texture2D[] GetPreviewTextures([NotNull] this SpriteAtlas spriteAtlas);\n        extern internal static Texture2D[] GetPreviewAlphaTextures([NotNull] this SpriteAtlas spriteAtlas);\n        extern internal static TextureFormat GetTextureFormat([NotNull] this SpriteAtlas spriteAtlas, BuildTarget target);\n        extern internal static Sprite[] GetPackedSprites([NotNull] this SpriteAtlas spriteAtlas);\n        extern internal static Hash128 GetStoredHash([NotNull] this SpriteAtlas spriteAtlas);\n\n        [NativeName(\"GetSecondaryPlatformSettings\")]\n        extern private static TextureImporterPlatformSettings GetSecondaryPlatformSettings_Internal([NotNull] this SpriteAtlas spriteAtlas, string buildTarget, string secondaryTextureName);\n        internal static TextureImporterPlatformSettings GetSecondaryPlatformSettings(this SpriteAtlas spriteAtlas, string buildTarget, string secondaryTextureName)\n        {\n            buildTarget = TextureImporter.GetTexturePlatformSerializationName(buildTarget); // String may refer to a platform group: if != \"Standalone\", ensure it refers to a platform instead. E.g.: \"iOS\", not \"iPhone\".\n            return GetSecondaryPlatformSettings_Internal(spriteAtlas, buildTarget, secondaryTextureName);\n        }\n\n        [NativeName(\"SetSecondaryPlatformSettings\")]\n        extern private static void SetSecondaryPlatformSettings_Internal([NotNull] this SpriteAtlas spriteAtlas, TextureImporterPlatformSettings src, string secondaryTextureName);\n        internal static void SetSecondaryPlatformSettings(this SpriteAtlas spriteAtlas, TextureImporterPlatformSettings src, string secondaryTextureName)\n        {\n            src.name = TextureImporter.GetTexturePlatformSerializationName(src.name); // String may refer to a platform group: if != \"Standalone\", ensure it refers to a platform instead. E.g.: \"iOS\", not \"iPhone\".\n            SetSecondaryPlatformSettings_Internal(spriteAtlas, src, secondaryTextureName);\n        }\n\n        extern internal static bool GetSecondaryColorSpace([NotNull] this SpriteAtlas spriteAtlas, string secondaryTextureName);\n        extern internal static void SetSecondaryColorSpace([NotNull] this SpriteAtlas spriteAtlas, string secondaryTextureName, bool srGB);\n        extern internal static void DeleteSecondaryPlatformSettings([NotNull] this SpriteAtlas spriteAtlas, string secondaryTextureName);\n        extern internal static string GetSecondaryTextureNameInAtlas(string atlasTextureName);\n        extern internal static string GetPageNumberInAtlas(string atlasTextureName);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/2D/SpriteAtlas/EditorSpritePacking.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing Unity.Collections;\nusing UnityEngine;\nusing UnityEngine.U2D;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing Unity.Collections.LowLevel.Unsafe;\n\nnamespace UnityEditor.U2D.SpritePacking\n{\n    [RequiredByNativeCode]\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct SpritePackInfoInternal\n    {\n        public int guid;\n        public int texIndex;\n        public int indexCount;\n        public int vertexCount;\n        public RectInt rect;\n        public IntPtr indices;\n        public IntPtr vertices;\n    };\n\n    [RequiredByNativeCode]\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct SpritePackTextureInfoInternal\n    {\n        public int width;\n        public int height;\n        public IntPtr buffer;\n    };\n\n    [RequiredByNativeCode]\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct SpritePackDatasetInternal\n    {\n        public SpritePackInfoInternal spriteData;\n        public SpritePackTextureInfoInternal textureData;\n    };\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct SpritePackInfo\n    {\n        public int guid;\n        public int texIndex;\n        public int indexCount;\n        public int vertexCount;\n        public RectInt rect;\n        public NativeArray<int> indices;\n        public NativeArray<Vector3> vertices;\n    };\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct SpritePackTextureInfo\n    {\n        public int width;\n        public int height;\n        public NativeArray<Color32> buffer;\n    };\n\n    internal struct SpritePackDataset\n    {\n        public List<SpritePackInfo> spriteData;\n        public List<SpritePackTextureInfo> textureData;\n    };\n\n    internal struct SpritePackConfig\n    {\n        public int padding;\n    };\n\n    [NativeHeader(\"Runtime/2D/SpriteAtlas/SpriteAtlas.h\")]\n    [NativeHeader(\"Editor/Src/2D/SpriteAtlas/SpriteAtlasPackingUtilities.h\")]\n    internal class SpritePackUtility\n    {\n        internal unsafe static SpritePackDataset PackCustomSpritesWrapper(SpritePackDataset input, SpritePackConfig packConfig, Allocator alloc)\n        {\n            var output = new SpritePackDataset();\n            var spriteCount = input.spriteData.Count;\n            if (0 == spriteCount)\n                return output;\n\n            var data = new NativeArray<SpritePackDatasetInternal>(spriteCount, Allocator.Temp, NativeArrayOptions.ClearMemory);\n            for (int i = 0; i < spriteCount; ++i)\n            {\n                SpritePackDatasetInternal rawData = data[i];\n                rawData.spriteData.guid = input.spriteData[i].guid;\n                int texIndex = input.spriteData[i].texIndex;\n                if (texIndex >= input.textureData.Count)\n                {\n                    data.Dispose();\n                    throw new ArgumentOutOfRangeException(\"texIndex\", \"texIndex must point to a valid index in textureData list.\");\n                }\n                rawData.spriteData.texIndex = texIndex;\n                rawData.spriteData.indexCount = input.spriteData[i].indexCount;\n                rawData.spriteData.vertexCount = input.spriteData[i].vertexCount;\n                rawData.spriteData.rect = input.spriteData[i].rect;\n                rawData.spriteData.indices = input.spriteData[i].indices.IsCreated ? (IntPtr)input.spriteData[i].indices.GetUnsafePtr() : (IntPtr)0;\n                rawData.spriteData.vertices = input.spriteData[i].vertices.IsCreated  ? (IntPtr)input.spriteData[i].vertices.GetUnsafePtr() : (IntPtr)0;\n                rawData.textureData.width = input.textureData[texIndex].width;\n                rawData.textureData.height = input.textureData[texIndex].height;\n                rawData.textureData.buffer = input.textureData[texIndex].buffer.IsCreated ? (IntPtr)input.textureData[texIndex].buffer.GetUnsafePtr() : (IntPtr)0;\n                data[i] = rawData;\n            }\n\n            var spriteOutput = (SpritePackDatasetInternal*)PackCustomSpritesInternal(spriteCount, (SpritePackDatasetInternal*)data.GetUnsafePtr(), packConfig);\n            if (null != spriteOutput)\n            {\n                var colorBufferArray = new SpritePackTextureInfo[spriteCount];\n                for (int i = 0; i < spriteCount; ++i)\n                {\n                    SpritePackTextureInfoInternal rawBuffer = spriteOutput[i].textureData;\n                    int index = spriteOutput[i].spriteData.texIndex;\n                    SpritePackTextureInfo outputBuffer = colorBufferArray[index];\n                    // New Texture. Copy.\n                    if (!outputBuffer.buffer.IsCreated)\n                    {\n                        outputBuffer.width = rawBuffer.width;\n                        outputBuffer.height = rawBuffer.height;\n                        Color32* rawColor = (Color32*)rawBuffer.buffer;\n                        if (null != rawColor)\n                        {\n                            outputBuffer.buffer = new NativeArray<Color32>(rawBuffer.width * rawBuffer.height, alloc);\n                            UnsafeUtility.MemCpy(outputBuffer.buffer.GetUnsafePtr(), rawColor, rawBuffer.width * rawBuffer.height * sizeof(Color32));\n                        }\n                        UnsafeUtility.Free((void*)rawBuffer.buffer, Allocator.Persistent);\n                    }\n                    colorBufferArray[index] = outputBuffer;\n                }\n                output.textureData = new List<SpritePackTextureInfo>(colorBufferArray);\n\n                var spriteDataArray = new SpritePackInfo[spriteCount];\n                for (int i = 0; i < spriteCount; ++i)\n                {\n                    SpritePackInfo spriteData = spriteDataArray[i];\n                    spriteData.guid = spriteOutput[i].spriteData.guid;\n                    spriteData.indexCount = spriteOutput[i].spriteData.indexCount;\n                    spriteData.vertexCount = spriteOutput[i].spriteData.vertexCount;\n                    spriteData.rect = spriteOutput[i].spriteData.rect;\n                    if (0 != spriteData.indexCount && 0 != spriteData.vertexCount)\n                    {\n                        int* rawIndices = (int*)spriteOutput[i].spriteData.indices;\n                        if (null != rawIndices)\n                        {\n                            spriteData.indices = new NativeArray<int>(spriteOutput[i].spriteData.indexCount, alloc);\n                            UnsafeUtility.MemCpy(spriteData.indices.GetUnsafePtr(), rawIndices, spriteOutput[i].spriteData.indexCount * sizeof(int));\n                        }\n                        Vector3* rawVertices = (Vector3*)spriteOutput[i].spriteData.vertices;\n                        if (null != rawVertices)\n                        {\n                            spriteData.vertices = new NativeArray<Vector3>(spriteOutput[i].spriteData.vertexCount, alloc);\n                            UnsafeUtility.MemCpy(spriteData.vertices.GetUnsafePtr(), rawVertices, spriteOutput[i].spriteData.vertexCount * sizeof(Vector3));\n                        }\n                        UnsafeUtility.Free((void*)spriteOutput[i].spriteData.indices, Allocator.Persistent);\n                        UnsafeUtility.Free((void*)spriteOutput[i].spriteData.vertices, Allocator.Persistent);\n                    }\n                    spriteData.texIndex = spriteOutput[i].spriteData.texIndex;\n                    spriteDataArray[i] = spriteData;\n                }\n                output.spriteData = new List<SpritePackInfo>(spriteDataArray);\n                UnsafeUtility.Free((void*)spriteOutput, Allocator.Persistent);\n            }\n\n            data.Dispose();\n            return output;\n        }\n\n        internal static SpritePackDataset PackCustomSprites(SpritePackDataset spriteDataInput, SpritePackConfig packConfig, Allocator outputAlloc)\n        {\n            return PackCustomSpritesWrapper(spriteDataInput, packConfig, outputAlloc);\n        }\n\n        [NativeThrows]\n        [FreeFunction(\"PackCustomSprites\")]\n        extern internal unsafe static IntPtr PackCustomSpritesInternal(int spriteCount, SpritePackDatasetInternal* data, SpritePackConfig packConfig);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/2D/SpriteAtlas/SpriteAtlasAsset.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEngine.U2D;\nusing Unity.Collections.LowLevel.Unsafe;\nusing Unity.Collections;\n\nnamespace UnityEditor.U2D\n{\n\n    [UsedByNativeCode]\n    public abstract class ScriptablePacker : ScriptableObject\n    {\n\n        public enum PackTransform\n        {\n            None = 0,\n            FlipHorizontal = 1,\n            FlipVertical = 2,\n            Rotate180 = 3,\n        }\n\n        [RequiredByNativeCode]\n        [StructLayout(LayoutKind.Sequential)]\n        public struct SpritePack\n        {\n            public int x;\n            public int y;\n            public int page;\n            public PackTransform rot;\n        };\n\n        [RequiredByNativeCode]\n        [StructLayout(LayoutKind.Sequential)]\n        public struct SpriteData\n        {\n            public int guid;\n            public int texIndex;\n            public int indexCount;\n            public int vertexCount;\n            public int indexOffset;\n            public int vertexOffset;\n            public RectInt rect;\n            public SpritePack output;\n        };\n\n        [RequiredByNativeCode]\n        [StructLayout(LayoutKind.Sequential)]\n        public struct TextureData\n        {\n            public int width;\n            public int height;\n            public int bufferOffset;\n        };\n\n        [RequiredByNativeCode]\n        [StructLayout(LayoutKind.Sequential)]\n        internal struct PackerDataInternal\n        {\n            public int colorCount;\n            public IntPtr colorData;\n            public int spriteCount;\n            public IntPtr spriteData;\n            public int textureCount;\n            public IntPtr textureData;\n            public int indexCount;\n            public IntPtr indexData;\n            public int vertexCount;\n            public IntPtr vertexData;\n        };\n\n        [StructLayout(LayoutKind.Sequential)]\n        public struct PackerData\n        {\n            public NativeArray<Color32> colorData;\n            public NativeArray<SpriteData> spriteData;\n            public NativeArray<TextureData> textureData;\n            public NativeArray<int> indexData;\n            public NativeArray<Vector2> vertexData;\n        };\n\n        // Public function to pack.\n        public abstract bool Pack(SpriteAtlasPackingSettings config, SpriteAtlasTextureSettings setting, PackerData input);\n\n        // Internal Glue function.\n        [RequiredByNativeCode]\n        internal bool PackInternal(SpriteAtlasPackingSettings config, SpriteAtlasTextureSettings setting, PackerDataInternal packerData)\n        {\n            var input = new PackerData();\n            unsafe\n            {\n                input.colorData = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<Color32>((void*)packerData.colorData, packerData.colorCount, Allocator.None);\n                input.spriteData = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<SpriteData>((void*)packerData.spriteData, packerData.spriteCount, Allocator.None);\n                input.textureData = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<TextureData>((void*)packerData.textureData, packerData.textureCount, Allocator.None);\n                input.indexData = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<int>((void*)packerData.indexData, packerData.indexCount, Allocator.None);\n                input.vertexData = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<Vector2>((void*)packerData.vertexData, packerData.vertexCount, Allocator.None);\n\n                NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref input.colorData, AtomicSafetyHandle.GetTempMemoryHandle());\n                NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref input.spriteData, AtomicSafetyHandle.GetTempMemoryHandle());\n                NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref input.textureData, AtomicSafetyHandle.GetTempMemoryHandle());\n                NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref input.indexData, AtomicSafetyHandle.GetTempMemoryHandle());\n                NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref input.vertexData, AtomicSafetyHandle.GetTempMemoryHandle());\n            }\n            return Pack(config, setting, input);\n        }\n\n    };\n\n    // SpriteAtlas Importer lets you modify [[SpriteAtlas]]\n    [NativeHeader(\"Editor/Src/2D/SpriteAtlas/SpriteAtlasAsset.h\")]\n    [NativeType(Header = \"Editor/Src/2D/SpriteAtlas/SpriteAtlasAsset.h\")]\n    public class SpriteAtlasAsset : UnityEngine.Object\n    {\n        public SpriteAtlasAsset() { Internal_Create(this); }\n        extern private static void Internal_Create([Writable] SpriteAtlasAsset self);\n\n        extern public bool isVariant { [NativeMethod(\"GetIsVariant\")] get; }\n        extern public void SetIsVariant(bool value);\n        extern public void SetMasterAtlas(SpriteAtlas atlas);\n        extern public SpriteAtlas GetMasterAtlas();\n        extern internal UnityEngine.Object GetPacker();\n        extern internal void SetPacker(UnityEngine.Object obj);\n        extern public void Add(UnityEngine.Object[] objects);\n        extern public void Remove(UnityEngine.Object[] objects);\n\n        public void SetScriptablePacker(ScriptablePacker obj)\n        {\n            SetPacker(obj);\n        }\n        extern internal void RemoveAt(int index);\n\n        [Obsolete(\"SetVariantScale is no longer supported and will be removed. Use SpriteAtlasImporter.SetVariantScale instead.\")]\n        public void SetVariantScale(float value) { }\n        [Obsolete(\"SetIncludeInBuild is no longer supported and will be removed. Use SpriteAtlasImporter.SetIncludeInBuild instead.\")]\n        public void SetIncludeInBuild(bool value) { }\n        [Obsolete(\"IsIncludeInBuild is no longer supported and will be removed. Use SpriteAtlasImporter.IsIncludeInBuild instead.\")]\n        public bool IsIncludeInBuild() { return true;  }\n        [Obsolete(\"SetPlatformSettings is no longer supported and will be removed. Use SpriteAtlasImporter.SetPlatformSettings instead.\")]\n        public void SetPlatformSettings(TextureImporterPlatformSettings src) { }\n        [Obsolete(\"SetTextureSettings is no longer supported and will be removed. Use SpriteAtlasImporter.SetTextureSettings instead.\")]\n        public void SetTextureSettings(SpriteAtlasTextureSettings src) { }\n        [Obsolete(\"SetPackingSettings is no longer supported and will be removed. Use SpriteAtlasImporter.SetPackingSettings instead.\")]\n        public void SetPackingSettings(SpriteAtlasPackingSettings src) { }\n        [Obsolete(\"GetPackingSettings is no longer supported and will be removed. Use SpriteAtlasImporter.GetPackingSettings instead.\")]\n        public SpriteAtlasPackingSettings GetPackingSettings() { return new SpriteAtlasPackingSettings(); }\n        [Obsolete(\"GetTextureSettings is no longer supported and will be removed. Use SpriteAtlasImporter.GetTextureSettings instead.\")]\n        public SpriteAtlasTextureSettings GetTextureSettings() { return new SpriteAtlasTextureSettings(); }\n        [Obsolete(\"GetPlatformSettings is no longer supported and will be removed. Use SpriteAtlasImporter.GetPlatformSettingss instead.\")]\n        public TextureImporterPlatformSettings GetPlatformSettings(string buildTarget) { return new TextureImporterPlatformSettings(); }\n\n        // Load SpriteAtlasAsset\n        public static SpriteAtlasAsset Load(string assetPath)\n        {\n            var objs = UnityEditorInternal.InternalEditorUtility.LoadSerializedFileAndForget(assetPath);\n            return (objs.Length > 0) ? objs[0] as SpriteAtlasAsset : null;\n        }\n\n        public static void Save(SpriteAtlasAsset asset, string assetPath)\n        {\n            if (asset == null)\n                throw new ArgumentNullException(\"Parameter asset is null\");\n            var objs = new UnityEngine.Object[] { asset };\n            UnityEditorInternal.InternalEditorUtility.SaveToSerializedFileAndForget(objs, assetPath, UnityEditor.EditorSettings.serializationMode != UnityEditor.SerializationMode.ForceBinary);\n        }\n    }\n};\n"
  },
  {
    "path": "Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporter.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing UnityEditor.Build;\nusing UnityEditor.AssetImporters;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEngine.U2D;\n\nnamespace UnityEditor.U2D\n{\n    // SpriteAtlas Importer lets you modify [[SpriteAtlas]]\n    [HelpURL(\"https://docs.unity3d.com/6000.2/Documentation/Manual/sprite/atlas/v2/sprite-atlas-v2.html\")]\n    [NativeHeader(\"Editor/Src/2D/SpriteAtlas/SpriteAtlasImporter.h\")]\n    public sealed partial class SpriteAtlasImporter : AssetImporter\n    {\n        extern internal static void MigrateAllSpriteAtlases();\n        extern public float variantScale { get; set; }\n        extern public bool includeInBuild { get; set; }\n        extern public SpriteAtlasPackingSettings packingSettings { get; set; }\n        extern public SpriteAtlasTextureSettings textureSettings { get; set; }\n\n        [NativeName(\"SetPlatformSettings\")]\n        extern private void SetPlatformSettings_Internal(TextureImporterPlatformSettings src);\n        public void SetPlatformSettings(TextureImporterPlatformSettings src)\n        {\n            src.name = TextureImporter.GetTexturePlatformSerializationName(src.name); // String may refer to a platform group: if != \"Standalone\", ensure it refers to a platform instead. E.g.: \"iOS\", not \"iPhone\".\n            SetPlatformSettings_Internal(src);\n        }\n\n        [NativeName(\"GetPlatformSettings\")]\n        extern private TextureImporterPlatformSettings GetPlatformSettings_Internal(string buildTarget);\n        public TextureImporterPlatformSettings GetPlatformSettings(string buildTarget)\n        {\n            buildTarget = TextureImporter.GetTexturePlatformSerializationName(buildTarget); // String may refer to a platform group: if != \"Standalone\", ensure it refers to a platform instead. E.g.: \"iOS\", not \"iPhone\".\n            return GetPlatformSettings_Internal(buildTarget);\n        }\n\n        extern internal TextureFormat GetTextureFormat(BuildTarget target);\n\n        [NativeName(\"GetSecondaryPlatformSettings\")]\n        extern private TextureImporterPlatformSettings GetSecondaryPlatformSettings_Internal(string buildTarget, string secondaryTextureName);\n        internal TextureImporterPlatformSettings GetSecondaryPlatformSettings(string buildTarget, string secondaryTextureName)\n        {\n            buildTarget = TextureImporter.GetTexturePlatformSerializationName(buildTarget); // String may refer to a platform group: if != \"Standalone\", ensure it refers to a platform instead. E.g.: \"iOS\", not \"iPhone\".\n            return GetSecondaryPlatformSettings_Internal(buildTarget, secondaryTextureName);\n        }\n\n        [NativeName(\"SetSecondaryPlatformSettings\")]\n        extern private void SetSecondaryPlatformSettings_Internal(TextureImporterPlatformSettings src, string secondaryTextureName);\n        internal void SetSecondaryPlatformSettings(TextureImporterPlatformSettings src, string secondaryTextureName)\n        {\n            src.name = TextureImporter.GetTexturePlatformSerializationName(src.name); // String may refer to a platform group: if != \"Standalone\", ensure it refers to a platform instead. E.g.: \"iOS\", not \"iPhone\".\n            SetSecondaryPlatformSettings_Internal(src, secondaryTextureName);\n        }\n\n        extern internal bool GetSecondaryColorSpace(string secondaryTextureName);\n        extern internal void SetSecondaryColorSpace(string secondaryTextureName, bool srGB);\n        extern internal void DeleteSecondaryPlatformSettings(string secondaryTextureName);\n    }\n};\n"
  },
  {
    "path": "Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporterInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.IO;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Experimental.Rendering;\nusing UnityEngine.U2D;\nusing UnityEditor.Build;\nusing UnityEditor.U2D.Common;\nusing UnityEditor.U2D.Interface;\nusing UnityEditorInternal;\nusing UnityEditor.AssetImporters;\n\nnamespace UnityEditor.U2D\n{\n    [CustomEditor(typeof(SpriteAtlasImporter))]\n    internal class SpriteAtlasImporterInspector : AssetImporterEditor\n    {\n        class SpriteAtlasInspectorPlatformSettingView : TexturePlatformSettingsView\n        {\n            private bool m_ShowMaxSizeOption;\n\n            public SpriteAtlasInspectorPlatformSettingView(bool showMaxSizeOption)\n            {\n                m_ShowMaxSizeOption = showMaxSizeOption;\n            }\n\n            public override int DrawMaxSize(int defaultValue, bool isMixedValue, bool isDisabled, out bool changed)\n            {\n                if (m_ShowMaxSizeOption)\n                    return base.DrawMaxSize(defaultValue, isMixedValue, isDisabled, out changed);\n                else\n                    changed = false;\n                return defaultValue;\n            }\n        }\n\n        class Styles\n        {\n            public readonly GUIStyle preDropDown = \"preDropDown\";\n            public readonly GUIStyle previewButton = \"preButton\";\n            public readonly GUIStyle previewSlider = \"preSlider\";\n            public readonly GUIStyle previewSliderThumb = \"preSliderThumb\";\n            public readonly GUIStyle previewLabel = \"preLabel\";\n\n            public readonly GUIContent textureSettingLabel = EditorGUIUtility.TrTextContent(\"Texture\");\n            public readonly GUIContent variantSettingLabel = EditorGUIUtility.TrTextContent(\"Variant\");\n            public readonly GUIContent packingParametersLabel = EditorGUIUtility.TrTextContent(\"Packing\");\n            public readonly GUIContent atlasTypeLabel = EditorGUIUtility.TrTextContent(\"Type\");\n            public readonly GUIContent defaultPlatformLabel = EditorGUIUtility.TrTextContent(\"Default\");\n            public readonly GUIContent masterAtlasLabel = EditorGUIUtility.TrTextContent(\"Master Atlas\", \"Assigning another Sprite Atlas asset will make this atlas a variant of it.\");\n            public readonly GUIContent packerLabel = EditorGUIUtility.TrTextContent(\"Scriptable Packer\", \"Scriptable Object that implements custom packing for Sprite-Atlas.\");\n            public readonly GUIContent bindAsDefaultLabel = EditorGUIUtility.TrTextContent(\"Include in Build\", \"Packed textures will be included in the build by default.\");\n            public readonly GUIContent enableRotationLabel = EditorGUIUtility.TrTextContent(\"Allow Rotation\", \"Try rotating the sprite to fit better during packing.\");\n            public readonly GUIContent enableTightPackingLabel = EditorGUIUtility.TrTextContent(\"Tight Packing\", \"Use the mesh outline to fit instead of the whole texture rect during packing.\");\n            public readonly GUIContent enableAlphaDilationLabel = EditorGUIUtility.TrTextContent(\"Alpha Dilation\", \"Enable Alpha Dilation for SpriteAtlas padding pixels.\");\n            public readonly GUIContent paddingLabel = EditorGUIUtility.TrTextContent(\"Padding\", \"The amount of extra padding between packed sprites.\");\n\n            public readonly GUIContent generateMipMapLabel = EditorGUIUtility.TrTextContent(\"Generate Mip Maps\");\n            public readonly GUIContent packPreviewLabel = EditorGUIUtility.TrTextContent(\"Pack Preview\", \"Save and preview packed Sprite Atlas textures.\");\n            public readonly GUIContent sRGBLabel = EditorGUIUtility.TrTextContent(\"sRGB\", \"Texture content is stored in gamma space.\");\n            public readonly GUIContent readWrite = EditorGUIUtility.TrTextContent(\"Read/Write\", \"Enable to be able to access the raw pixel data from code.\");\n            public readonly GUIContent variantMultiplierLabel = EditorGUIUtility.TrTextContent(\"Scale\", \"Down scale ratio.\");\n            public readonly GUIContent copyMasterButton = EditorGUIUtility.TrTextContent(\"Copy Master's Settings\", \"Copy all master's settings into this variant.\");\n\n            public readonly GUIContent disabledPackLabel = EditorGUIUtility.TrTextContent(\"Sprite Atlas packing is disabled. Enable it in Edit > Project Settings > Editor.\", null, EditorGUIUtility.GetHelpIcon(MessageType.Info));\n            public readonly GUIContent packableListLabel = EditorGUIUtility.TrTextContent(\"Objects for Packing\", \"Only accepts Folders, Sprite Sheet (Texture) and Sprite.\");\n\n            public readonly GUIContent notPowerOfTwoWarning = EditorGUIUtility.TrTextContent(\"This scale will produce a Variant Sprite Atlas with a packed Texture that is NPOT (non - power of two). This may cause visual artifacts in certain compression/Texture formats.\");\n            public readonly GUIContent secondaryTextureNameLabel = EditorGUIUtility.TrTextContent(\"Secondary Texture Name\", \"The name of the Secondary Texture to apply the following settings to.\");\n            public readonly GUIContent platformSettingsDropDownLabel = EditorGUIUtility.TrTextContent(\"Show Platform Settings For\");\n\n            public readonly GUIContent smallZoom = EditorGUIUtility.IconContent(\"PreTextureMipMapLow\");\n            public readonly GUIContent largeZoom = EditorGUIUtility.IconContent(\"PreTextureMipMapHigh\");\n            public readonly GUIContent alphaIcon = EditorGUIUtility.IconContent(\"PreTextureAlpha\");\n            public readonly GUIContent RGBIcon = EditorGUIUtility.IconContent(\"PreTextureRGB\");\n            public readonly GUIContent trashIcon = EditorGUIUtility.TrIconContent(\"TreeEditor.Trash\", \"Delete currently selected settings.\");\n\n            public readonly int packableElementHash = \"PackableElement\".GetHashCode();\n            public readonly int packableSelectorHash = \"PackableSelector\".GetHashCode();\n\n            public readonly string swapObjectRegisterUndo = L10n.Tr(\"Swap Packable\");\n            public readonly string secondaryTextureNameTextControlName = \"secondary_texture_name_text_field\";\n            public readonly string defaultTextForSecondaryTextureName = L10n.Tr(\"(Matches the names of the Secondary Textures in your Sprites.)\");\n            public readonly string nameUniquenessWarning = L10n.Tr(\"Secondary Texture names must be unique within a Sprite or Sprite Atlas.\");\n\n            public readonly int[] atlasTypeValues = { 0, 1 };\n            public readonly GUIContent[] atlasTypeOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Master\"),\n                EditorGUIUtility.TrTextContent(\"Variant\"),\n            };\n\n            public readonly int[] paddingValues = { 2, 4, 8 };\n            public readonly GUIContent[] paddingOptions;\n\n            public Styles()\n            {\n                paddingOptions = new GUIContent[paddingValues.Length];\n                for (var i = 0; i < paddingValues.Length; ++i)\n                    paddingOptions[i] = EditorGUIUtility.TextContent(paddingValues[i].ToString());\n            }\n        }\n\n        private static Styles s_Styles;\n\n        private static Styles styles\n        {\n            get\n            {\n                s_Styles = s_Styles ?? new Styles();\n                return s_Styles;\n            }\n        }\n        private SpriteAtlasAsset spriteAtlasAsset\n        {\n            get { return m_TargetAsset; }\n        }\n        private SpriteAtlasImporter spriteAtlasImporter\n        {\n            get { return target as SpriteAtlasImporter; }\n        }\n        private enum AtlasType { Undefined = -1, Master = 0, Variant = 1 }\n\n        private SerializedProperty m_FilterMode;\n        private SerializedProperty m_AnisoLevel;\n        private SerializedProperty m_GenerateMipMaps;\n        private SerializedProperty m_Readable;\n        private SerializedProperty m_UseSRGB;\n        private SerializedProperty m_EnableTightPacking;\n        private SerializedProperty m_EnableAlphaDilation;\n        private SerializedProperty m_EnableRotation;\n        private SerializedProperty m_Padding;\n        private SerializedProperty m_BindAsDefault;\n        private SerializedProperty m_Packables;\n\n        private SerializedProperty m_MasterAtlas;\n        private SerializedProperty m_VariantScale;\n        private SerializedProperty m_ScriptablePacker;\n\n        private string m_Hash;\n        private int m_PreviewPage = 0;\n        private int m_TotalPages = 0;\n        private int[] m_OptionValues = null;\n        private string[] m_OptionDisplays = null;\n        private Texture2D[] m_PreviewTextures = null;\n        private Texture2D[] m_PreviewAlphaTextures = null;\n\n        private bool m_PackableListExpanded = true;\n        private ReorderableList m_PackableList;\n        private SpriteAtlasAsset m_TargetAsset;\n        private string m_AssetPath;\n\n        private float m_MipLevel = 0;\n        private bool m_ShowAlpha;\n        private bool m_Discard = false;\n\n        private List<string> m_PlatformSettingsOptions;\n        private int m_SelectedPlatformSettings = 0;\n\n        private int m_ContentHash = 0;\n        private List<BuildPlatform> m_ValidPlatforms;\n        private Dictionary<string, List<TextureImporterPlatformSettings>> m_TempPlatformSettings;\n\n        private ITexturePlatformSettingsView m_TexturePlatformSettingsView;\n        private ITexturePlatformSettingsView m_SecondaryTexturePlatformSettingsView;\n        private ITexturePlatformSettingsFormatHelper m_TexturePlatformSettingTextureHelper;\n        private ITexturePlatformSettingsController m_TexturePlatformSettingsController;\n        private SerializedObject m_SerializedAssetObject = null;\n\n        // The first two options are the main texture and a separator while the last two options are another separator and the new settings menu.\n        private bool secondaryTextureSelected { get { return m_SelectedPlatformSettings >= 2 && m_SelectedPlatformSettings <= m_PlatformSettingsOptions.Count - 3; } }\n\n        static bool IsPackable(Object o)\n        {\n            return o != null && (o.GetType() == typeof(Sprite) || o.GetType() == typeof(Texture2D) || (o.GetType() == typeof(DefaultAsset) && ProjectWindowUtil.IsFolder(o.GetInstanceID())));\n        }\n\n        static Object ValidateObjectForPackableFieldAssignment(Object[] references, System.Type objType, SerializedProperty property, EditorGUI.ObjectFieldValidatorOptions options)\n        {\n            // We only validate and care about the first one as this is a object field assignment.\n            if (references.Length > 0 && IsPackable(references[0]))\n                return references[0];\n            return null;\n        }\n\n        bool IsTargetVariant()\n        {\n            return spriteAtlasAsset ? spriteAtlasAsset.isVariant : false;\n        }\n\n        bool IsTargetMaster()\n        {\n            return spriteAtlasAsset ? !spriteAtlasAsset.isVariant : true;\n        }\n\n        protected override bool needsApplyRevert => false;\n\n        internal override string targetTitle\n        {\n            get\n            {\n                return spriteAtlasAsset ? ( Path.GetFileNameWithoutExtension(m_AssetPath) + \" (Sprite Atlas)\" ) : \"SpriteAtlasImporter Settings\";\n            }\n        }\n\n        private string LoadSourceAsset()\n        {\n            var assetPath = AssetDatabase.GetAssetPath(target);\n            var loadedObjects = InternalEditorUtility.LoadSerializedFileAndForget(assetPath);\n            if (loadedObjects.Length > 0)\n                m_TargetAsset = loadedObjects[0] as SpriteAtlasAsset;\n            return assetPath;\n        }\n\n        private SerializedObject serializedAssetObject\n        {\n            get\n            {\n                return GetSerializedAssetObject();\n            }\n        }\n\n        internal static int SpriteAtlasAssetHash(SerializedObject obj)\n        {\n            int hashCode = 0;\n            if (obj == null)\n                return 0;\n            unchecked\n            {\n                hashCode = (int)2166136261 ^ (int) obj.FindProperty(\"m_MasterAtlas\").contentHash;\n                hashCode = hashCode * 16777619 ^ (int) obj.FindProperty(\"m_ImporterData\").contentHash;\n                hashCode = hashCode * 16777619 ^ (int) obj.FindProperty(\"m_IsVariant\").contentHash;\n                hashCode = hashCode * 16777619 ^ (int)obj.FindProperty(\"m_ScriptablePacker\").contentHash;\n            }\n            return hashCode;\n        }\n\n        internal static int SpriteAtlasImporterHash(SerializedObject obj)\n        {\n            int hashCode = 0;\n            if (obj == null)\n                return 0;\n            unchecked\n            {\n                hashCode = (int)2166136261 ^ (int)obj.FindProperty(\"m_PackingSettings\").contentHash;\n                hashCode = hashCode * 16777619 ^ (int)obj.FindProperty(\"m_TextureSettings\").contentHash;\n                hashCode = hashCode * 16777619 ^ (int)obj.FindProperty(\"m_PlatformSettings\").contentHash;\n                hashCode = hashCode * 16777619 ^ (int)obj.FindProperty(\"m_SecondaryTextureSettings\").contentHash;\n                hashCode = hashCode * 16777619 ^ (int)obj.FindProperty(\"m_BindAsDefault\").contentHash;\n                hashCode = hashCode * 16777619 ^ (int)obj.FindProperty(\"m_VariantMultiplier\").contentHash;\n            }\n            return hashCode;\n        }\n\n        internal int GetInspectorHash()\n        {\n            return SpriteAtlasAssetHash(m_SerializedAssetObject) * 16777619 ^ SpriteAtlasImporterHash(m_SerializedObject);\n        }\n\n        private SerializedObject GetSerializedAssetObject()\n        {\n            if (m_SerializedAssetObject == null)\n            {\n                try\n                {\n                    m_SerializedAssetObject = new SerializedObject(spriteAtlasAsset, m_Context);\n                    m_SerializedAssetObject.inspectorMode = inspectorMode;\n                    m_ContentHash = GetInspectorHash();\n                    m_EnabledProperty = m_SerializedAssetObject.FindProperty(\"m_Enabled\");\n                }\n                catch (System.ArgumentException e)\n                {\n                    m_SerializedAssetObject = null;\n                    m_EnabledProperty = null;\n                    throw new SerializedObjectNotCreatableException(e.Message);\n                }\n            }\n            return m_SerializedAssetObject;\n        }\n\n       public override void OnEnable()\n        {\n            base.OnEnable();\n\n            m_FilterMode = serializedObject.FindProperty(\"m_TextureSettings.filterMode\");\n            m_AnisoLevel = serializedObject.FindProperty(\"m_TextureSettings.anisoLevel\");\n            m_GenerateMipMaps = serializedObject.FindProperty(\"m_TextureSettings.generateMipMaps\");\n            m_Readable = serializedObject.FindProperty(\"m_TextureSettings.readable\");\n            m_UseSRGB = serializedObject.FindProperty(\"m_TextureSettings.sRGB\");\n\n            m_EnableTightPacking = serializedObject.FindProperty(\"m_PackingSettings.enableTightPacking\");\n            m_EnableRotation = serializedObject.FindProperty(\"m_PackingSettings.enableRotation\");\n            m_EnableAlphaDilation = serializedObject.FindProperty(\"m_PackingSettings.enableAlphaDilation\");\n            m_Padding = serializedObject.FindProperty(\"m_PackingSettings.padding\");\n            m_BindAsDefault = serializedObject.FindProperty(\"m_BindAsDefault\");\n            m_VariantScale = serializedObject.FindProperty(\"m_VariantMultiplier\");\n            PopulatePlatformSettingsOptions();\n\n            SyncPlatformSettings();\n\n            m_TexturePlatformSettingsView = new SpriteAtlasInspectorPlatformSettingView(IsTargetMaster());\n            m_TexturePlatformSettingTextureHelper = new TexturePlatformSettingsFormatHelper();\n            m_TexturePlatformSettingsController = new TexturePlatformSettingsViewController();\n\n            // Don't show max size option for secondary textures as they must have the same size as the main texture.\n            m_SecondaryTexturePlatformSettingsView = new SpriteAtlasInspectorPlatformSettingView(false);\n\n            m_AssetPath = LoadSourceAsset();\n            if (spriteAtlasAsset == null)\n                return;\n\n            m_MasterAtlas = serializedAssetObject.FindProperty(\"m_MasterAtlas\");\n            m_ScriptablePacker = serializedAssetObject.FindProperty(\"m_ScriptablePacker\");\n            m_Packables = serializedAssetObject.FindProperty(\"m_ImporterData.packables\");\n            m_PackableList = new ReorderableList(serializedAssetObject, m_Packables, true, true, true, true);\n            m_PackableList.onAddCallback = AddPackable;\n            m_PackableList.drawElementCallback = DrawPackableElement;\n            m_PackableList.elementHeight = EditorGUIUtility.singleLineHeight;\n            m_PackableList.headerHeight = 0f;\n        }\n\n        // Populate the platform settings dropdown list with secondary texture names found through serialized properties of the Sprite Atlas assets.\n        private void PopulatePlatformSettingsOptions()\n        {\n            m_PlatformSettingsOptions = new List<string> { L10n.Tr(\"Main Texture\"), \"\", \"\", L10n.Tr(\"New Secondary Texture settings.\") };\n            SerializedProperty secondaryPlatformSettings = serializedObject.FindProperty(\"m_SecondaryTextureSettings\");\n            if (secondaryPlatformSettings != null && !secondaryPlatformSettings.hasMultipleDifferentValues)\n            {\n                int numSecondaryTextures = secondaryPlatformSettings.arraySize;\n                List<string> secondaryTextureNames = new List<string>(numSecondaryTextures);\n\n                for (int i = 0; i < numSecondaryTextures; ++i)\n                    secondaryTextureNames.Add(secondaryPlatformSettings.GetArrayElementAtIndex(i).displayName);\n\n                // Insert after main texture and the separator.\n                m_PlatformSettingsOptions.InsertRange(2, secondaryTextureNames);\n            }\n\n            m_SelectedPlatformSettings = 0;\n        }\n\n        void SyncPlatformSettings()\n        {\n            m_TempPlatformSettings = new Dictionary<string, List<TextureImporterPlatformSettings>>();\n\n            string secondaryTextureName = null;\n            if (secondaryTextureSelected)\n                secondaryTextureName = m_PlatformSettingsOptions[m_SelectedPlatformSettings];\n\n            // Default platform\n            var defaultSettings = new List<TextureImporterPlatformSettings>();\n            m_TempPlatformSettings.Add(TextureImporterInspector.s_DefaultPlatformName, defaultSettings);\n            var settings = secondaryTextureSelected\n                ? spriteAtlasImporter.GetSecondaryPlatformSettings(TextureImporterInspector.s_DefaultPlatformName, secondaryTextureName)\n                : spriteAtlasImporter.GetPlatformSettings(TextureImporterInspector.s_DefaultPlatformName);\n            defaultSettings.Add(settings);\n\n            m_ValidPlatforms = BuildPlatforms.instance.GetValidPlatforms();\n            foreach (var platform in m_ValidPlatforms)\n            {\n                var platformSettings = new List<TextureImporterPlatformSettings>();\n                m_TempPlatformSettings.Add(platform.name, platformSettings);\n                var perPlatformSettings = secondaryTextureSelected ? spriteAtlasImporter.GetSecondaryPlatformSettings(platform.name, secondaryTextureName) : spriteAtlasImporter.GetPlatformSettings(platform.name);\n                // setting will be in default state if copy failed\n                platformSettings.Add(perPlatformSettings);\n            }\n        }\n\n        void RenameSecondaryPlatformSettings(string oldName, string newName)\n        {\n            spriteAtlasImporter.DeleteSecondaryPlatformSettings(oldName);\n\n            var defaultPlatformSettings = m_TempPlatformSettings[TextureImporterInspector.s_DefaultPlatformName];\n            spriteAtlasImporter.SetSecondaryPlatformSettings(defaultPlatformSettings[0], newName);\n\n            foreach (var buildPlatform in m_ValidPlatforms)\n            {\n                var platformSettings = m_TempPlatformSettings[buildPlatform.name];\n                spriteAtlasImporter.SetSecondaryPlatformSettings(platformSettings[0], newName);\n            }\n        }\n\n        void AddPackable(ReorderableList list)\n        {\n            ObjectSelector.get.Show(null, typeof(Object), null, false);\n            ObjectSelector.get.searchFilter = \"t:sprite t:texture2d t:folder\";\n            ObjectSelector.get.objectSelectorID = styles.packableSelectorHash;\n        }\n\n        void DrawPackableElement(Rect rect, int index, bool selected, bool focused)\n        {\n            var property = m_Packables.GetArrayElementAtIndex(index);\n            var controlID = EditorGUIUtility.GetControlID(styles.packableElementHash, FocusType.Passive);\n            var previousObject = property.objectReferenceValue;\n\n            var changedObject = EditorGUI.DoObjectField(rect, rect, controlID, previousObject, target, typeof(Object), ValidateObjectForPackableFieldAssignment, false);\n            if (changedObject != previousObject)\n            {\n                Undo.RegisterCompleteObjectUndo(spriteAtlasAsset, styles.swapObjectRegisterUndo);\n                property.objectReferenceValue = changedObject;\n            }\n\n            if (GUIUtility.keyboardControl == controlID && !selected)\n                m_PackableList.index = index;\n        }\n\n        protected override void Apply()\n        {\n            if (HasModified())\n            {\n                if (spriteAtlasAsset)\n                {\n                    SpriteAtlasAsset.Save(spriteAtlasAsset, m_AssetPath);\n                    AssetDatabase.ImportAsset(m_AssetPath);\n                }\n\n                m_ContentHash = GetInspectorHash();\n            }\n            base.Apply();\n        }\n\n        protected override bool useAssetDrawPreview { get { return false; } }\n\n        protected void PackPreviewGUI()\n        {\n            EditorGUILayout.Space();\n\n            using (new GUILayout.HorizontalScope())\n            {\n                using (new EditorGUI.DisabledScope(!HasModified() || !IsValidAtlas() || Application.isPlaying))\n                {\n                    GUILayout.FlexibleSpace();\n\n                    if (GUILayout.Button(styles.packPreviewLabel))\n                    {\n                        GUI.FocusControl(null);\n                        SpriteAtlasUtility.EnableV2Import(true);\n                        SaveChanges();\n                        SpriteAtlasUtility.EnableV2Import(false);\n                    }\n                }\n            }\n        }\n\n        private bool IsValidAtlas()\n        {\n            if (IsTargetVariant())\n                return m_MasterAtlas.objectReferenceValue != null;\n            else\n                return true;\n        }\n\n        public override bool HasModified()\n        {\n            return !m_Discard && (base.HasModified() || m_ContentHash != GetInspectorHash());\n        }\n\n        private void ValidateMasterAtlas()\n        {\n            if (m_MasterAtlas.objectReferenceValue != null)\n            {\n                var assetPath = AssetDatabase.GetAssetPath(m_MasterAtlas.objectReferenceValue);\n                if (assetPath == m_AssetPath)\n                {\n                    UnityEngine.Debug.LogWarning(\"Cannot set itself as MasterAtlas. Please assign a valid MasterAtlas.\");\n                    m_MasterAtlas.objectReferenceValue = null;\n                }\n            }\n            if (m_MasterAtlas.objectReferenceValue != null)\n            {\n                SpriteAtlas masterAsset = m_MasterAtlas.objectReferenceValue as SpriteAtlas;\n                if (masterAsset != null && masterAsset.isVariant)\n                {\n                    UnityEngine.Debug.LogWarning(\"Cannot set a VariantAtlas as MasterAtlas. Please assign a valid MasterAtlas.\");\n                    m_MasterAtlas.objectReferenceValue = null;\n                }\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            // Ensure changes done through script are reflected immediately in Inspector by Syncing m_TempPlatformSettings with Actual Settings.\n            SyncPlatformSettings();\n\n            serializedObject.Update();\n            if (spriteAtlasAsset)\n            {\n                serializedAssetObject.Update();\n                HandleCommonSettingUI();\n            }\n            EditorGUILayout.PropertyField(m_BindAsDefault, styles.bindAsDefaultLabel);\n\n            GUILayout.Space(EditorGUI.kSpacing);\n\n            bool isTargetMaster = true;\n            if (spriteAtlasAsset)\n                isTargetMaster = IsTargetMaster();\n\n            if (isTargetMaster)\n                HandleMasterSettingUI();\n            if (!spriteAtlasAsset || IsTargetVariant())\n                HandleVariantSettingUI();\n\n            GUILayout.Space(EditorGUI.kSpacing);\n\n            HandleTextureSettingUI();\n\n            GUILayout.Space(EditorGUI.kSpacing);\n\n            // Only show the packable object list when:\n            // - This is a master atlas.\n            if (targets.Length == 1 && IsTargetMaster() && spriteAtlasAsset)\n                HandlePackableListUI();\n\n            serializedObject.ApplyModifiedProperties();\n            if (spriteAtlasAsset)\n            {\n                serializedAssetObject.ApplyModifiedProperties();\n                PackPreviewGUI();\n            }\n\n            ApplyRevertGUI();\n        }\n\n        private void HandleCommonSettingUI()\n        {\n            var atlasType = AtlasType.Undefined;\n            if (IsTargetMaster())\n                atlasType = AtlasType.Master;\n            else if (IsTargetVariant())\n                atlasType = AtlasType.Variant;\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = atlasType == AtlasType.Undefined;\n            atlasType = (AtlasType)EditorGUILayout.IntPopup(styles.atlasTypeLabel, (int)atlasType, styles.atlasTypeOptions, styles.atlasTypeValues);\n            EditorGUI.showMixedValue = false;\n            if (EditorGUI.EndChangeCheck())\n            {\n                bool setToVariant = atlasType == AtlasType.Variant;\n                spriteAtlasAsset.SetIsVariant(setToVariant);\n\n                // Reinit the platform setting view\n                m_TexturePlatformSettingsView = new SpriteAtlasInspectorPlatformSettingView(IsTargetMaster());\n            }\n            m_ScriptablePacker.objectReferenceValue = EditorGUILayout.ObjectField(styles.packerLabel, m_ScriptablePacker.objectReferenceValue, typeof(UnityEditor.U2D.ScriptablePacker), false);\n            if (atlasType == AtlasType.Variant)\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUILayout.PropertyField(m_MasterAtlas, styles.masterAtlasLabel);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    ValidateMasterAtlas();\n                    // Apply modified properties here to have latest master atlas reflected in native codes.\n                    serializedAssetObject.ApplyModifiedPropertiesWithoutUndo();\n                    PopulatePlatformSettingsOptions();\n                    SyncPlatformSettings();\n                }\n            }\n        }\n\n        private void HandleVariantSettingUI()\n        {\n            EditorGUILayout.LabelField(styles.variantSettingLabel, EditorStyles.boldLabel);\n            EditorGUILayout.PropertyField(m_VariantScale, styles.variantMultiplierLabel);\n\n            // Test if the multiplier scale a power of two size (1024) into another power of 2 size.\n            if (!Mathf.IsPowerOfTwo((int)(m_VariantScale.floatValue * 1024)))\n                EditorGUILayout.HelpBox(styles.notPowerOfTwoWarning.text, MessageType.Warning, true);\n        }\n\n        private void HandleBoolToIntPropertyField(SerializedProperty prop, GUIContent content)\n        {\n            Rect rect = EditorGUILayout.GetControlRect();\n            EditorGUI.BeginProperty(rect, content, prop);\n            EditorGUI.BeginChangeCheck();\n            var boolValue = EditorGUI.Toggle(rect, content, prop.boolValue);\n            if (EditorGUI.EndChangeCheck())\n                prop.boolValue = boolValue;\n            EditorGUI.EndProperty();\n        }\n\n        private void HandleMasterSettingUI()\n        {\n            EditorGUILayout.LabelField(styles.packingParametersLabel, EditorStyles.boldLabel);\n\n            HandleBoolToIntPropertyField(m_EnableRotation, styles.enableRotationLabel);\n            HandleBoolToIntPropertyField(m_EnableTightPacking, styles.enableTightPackingLabel);\n            HandleBoolToIntPropertyField(m_EnableAlphaDilation, styles.enableAlphaDilationLabel);\n            EditorGUILayout.IntPopup(m_Padding, styles.paddingOptions, styles.paddingValues, styles.paddingLabel);\n\n            GUILayout.Space(EditorGUI.kSpacing);\n        }\n\n        private void HandleTextureSettingUI()\n        {\n            EditorGUILayout.LabelField(styles.textureSettingLabel, EditorStyles.boldLabel);\n\n            HandleBoolToIntPropertyField(m_Readable, styles.readWrite);\n            HandleBoolToIntPropertyField(m_GenerateMipMaps, styles.generateMipMapLabel);\n            HandleBoolToIntPropertyField(m_UseSRGB, styles.sRGBLabel);\n            EditorGUILayout.PropertyField(m_FilterMode);\n\n            var showAniso = !m_FilterMode.hasMultipleDifferentValues && !m_GenerateMipMaps.hasMultipleDifferentValues\n                && (FilterMode)m_FilterMode.intValue != FilterMode.Point && m_GenerateMipMaps.boolValue;\n            if (showAniso)\n                EditorGUILayout.IntSlider(m_AnisoLevel, 0, 16);\n\n            GUILayout.Space(EditorGUI.kSpacing);\n\n            // \"Show Platform Settings For\" dropdown\n            EditorGUILayout.BeginHorizontal();\n            {\n                EditorGUILayout.PrefixLabel(s_Styles.platformSettingsDropDownLabel);\n\n                EditorGUI.BeginChangeCheck();\n                m_SelectedPlatformSettings = EditorGUILayout.Popup(m_SelectedPlatformSettings, m_PlatformSettingsOptions.ToArray(), GUILayout.MaxWidth(150.0f));\n                if (EditorGUI.EndChangeCheck())\n                {\n                    // New settings option is selected...\n                    if (m_SelectedPlatformSettings == m_PlatformSettingsOptions.Count - 1)\n                    {\n                        m_PlatformSettingsOptions.Insert(m_SelectedPlatformSettings - 1, s_Styles.defaultTextForSecondaryTextureName);\n                        m_SelectedPlatformSettings--;\n                        EditorGUI.FocusTextInControl(s_Styles.secondaryTextureNameTextControlName);\n                    }\n                    SyncPlatformSettings();\n                }\n\n                if (secondaryTextureSelected)\n                {\n                    // trash can button\n                    if (GUILayout.Button(s_Styles.trashIcon, EditorStyles.iconButton, GUILayout.ExpandWidth(false)))\n                    {\n                        EditorGUI.EndEditingActiveTextField();\n\n                        spriteAtlasImporter.DeleteSecondaryPlatformSettings(m_PlatformSettingsOptions[m_SelectedPlatformSettings]);\n\n                        m_PlatformSettingsOptions.RemoveAt(m_SelectedPlatformSettings);\n\n                        m_SelectedPlatformSettings--;\n                        if (m_SelectedPlatformSettings == 1)\n                            m_SelectedPlatformSettings = 0;\n\n                        SyncPlatformSettings();\n                    }\n                }\n            }\n            EditorGUILayout.EndHorizontal();\n\n            // Texture platform settings UI.\n            EditorGUILayout.BeginHorizontal();\n            {\n                EditorGUI.indentLevel++;\n                GUILayout.Space(EditorGUI.indent);\n                EditorGUI.indentLevel--;\n\n                if (m_SelectedPlatformSettings == 0)\n                {\n                    GUILayout.Space(EditorGUI.kSpacing);\n                    HandlePlatformSettingUI(null);\n                }\n                else\n                {\n                    EditorGUILayout.BeginVertical();\n                    {\n                        GUILayout.Space(EditorGUI.kSpacing);\n                        string oldSecondaryTextureName = m_PlatformSettingsOptions[m_SelectedPlatformSettings];\n                        GUI.SetNextControlName(s_Styles.secondaryTextureNameTextControlName);\n\n                        EditorGUI.BeginChangeCheck();\n                        string textFieldText = EditorGUILayout.DelayedTextField(s_Styles.secondaryTextureNameLabel, oldSecondaryTextureName);\n                        if (EditorGUI.EndChangeCheck() && oldSecondaryTextureName != textFieldText)\n                        {\n                            if (!m_PlatformSettingsOptions.Exists(x => x == textFieldText))\n                            {\n                                m_PlatformSettingsOptions[m_SelectedPlatformSettings] = textFieldText;\n                                RenameSecondaryPlatformSettings(oldSecondaryTextureName, textFieldText);\n                            }\n                            else\n                            {\n                                Debug.LogWarning(s_Styles.nameUniquenessWarning);\n                                EditorGUI.FocusTextInControl(s_Styles.secondaryTextureNameTextControlName);\n                            }\n                        }\n\n                        string secondaryTextureName = m_PlatformSettingsOptions[m_SelectedPlatformSettings];\n                        EditorGUI.BeginChangeCheck();\n                        bool value = EditorGUILayout.Toggle(s_Styles.sRGBLabel, spriteAtlasImporter.GetSecondaryColorSpace(secondaryTextureName));\n                        if (EditorGUI.EndChangeCheck())\n                            spriteAtlasImporter.SetSecondaryColorSpace(secondaryTextureName, value);\n\n                        HandlePlatformSettingUI(textFieldText);\n                    }\n                    EditorGUILayout.EndVertical();\n                }\n            }\n            EditorGUILayout.EndHorizontal();\n        }\n\n        private void HandlePlatformSettingUI(string secondaryTextureName)\n        {\n            int shownTextureFormatPage = EditorGUILayout.BeginPlatformGrouping(m_ValidPlatforms.ToArray(), styles.defaultPlatformLabel);\n            var defaultPlatformSettings = m_TempPlatformSettings[TextureImporterInspector.s_DefaultPlatformName];\n            bool isSecondary = secondaryTextureName != null;\n            ITexturePlatformSettingsView view = isSecondary ? m_SecondaryTexturePlatformSettingsView : m_TexturePlatformSettingsView;\n            if (shownTextureFormatPage == -1)\n            {\n                if (m_TexturePlatformSettingsController.HandleDefaultSettings(defaultPlatformSettings, view, m_TexturePlatformSettingTextureHelper))\n                {\n                    for (var i = 0; i < defaultPlatformSettings.Count; ++i)\n                    {\n                        if (isSecondary)\n                            spriteAtlasImporter.SetSecondaryPlatformSettings(defaultPlatformSettings[i], secondaryTextureName);\n                        else\n                            spriteAtlasImporter.SetPlatformSettings(defaultPlatformSettings[i]);\n                    }\n                }\n            }\n            else\n            {\n                var buildPlatform = m_ValidPlatforms[shownTextureFormatPage];\n                var platformSettings = m_TempPlatformSettings[buildPlatform.name];\n\n\n                for (var i = 0; i < platformSettings.Count; ++i)\n                {\n                    var settings = platformSettings[i];\n                    if (!settings.overridden)\n                    {\n                        if (defaultPlatformSettings[0].format == TextureImporterFormat.Automatic)\n                        {\n                            settings.format = (TextureImporterFormat)spriteAtlasImporter.GetTextureFormat(buildPlatform.defaultTarget);\n                        }\n                        else\n                        {\n                            settings.format = defaultPlatformSettings[0].format;\n                        }\n\n                        settings.maxTextureSize = defaultPlatformSettings[0].maxTextureSize;\n                        settings.crunchedCompression = defaultPlatformSettings[0].crunchedCompression;\n                        settings.compressionQuality = defaultPlatformSettings[0].compressionQuality;\n                    }\n                }\n\n                m_TexturePlatformSettingsView.buildPlatformTitle = buildPlatform.title.text;\n                if (m_TexturePlatformSettingsController.HandlePlatformSettings(buildPlatform.defaultTarget, platformSettings, view, m_TexturePlatformSettingTextureHelper))\n                {\n                    for (var i = 0; i < platformSettings.Count; ++i)\n                    {\n                        if (isSecondary)\n                            spriteAtlasImporter.SetSecondaryPlatformSettings(platformSettings[i], secondaryTextureName);\n                        else\n                            spriteAtlasImporter.SetPlatformSettings(platformSettings[i]);\n                    }\n                }\n            }\n\n            EditorGUILayout.EndPlatformGrouping();\n        }\n\n        private void HandlePackableListUI()\n        {\n            var currentEvent = Event.current;\n            var usedEvent = false;\n\n            Rect rect = EditorGUILayout.GetControlRect();\n\n            var controlID = EditorGUIUtility.s_LastControlID;\n            switch (currentEvent.type)\n            {\n                case EventType.DragExited:\n                    if (GUI.enabled)\n                        HandleUtility.Repaint();\n                    break;\n\n                case EventType.DragUpdated:\n                case EventType.DragPerform:\n                    if (rect.Contains(currentEvent.mousePosition) && GUI.enabled)\n                    {\n                        // Check each single object, so we can add multiple objects in a single drag.\n                        var didAcceptDrag = false;\n                        var references = DragAndDrop.objectReferences;\n                        foreach (var obj in references)\n                        {\n                            if (IsPackable(obj))\n                            {\n                                DragAndDrop.visualMode = DragAndDropVisualMode.Copy;\n                                if (currentEvent.type == EventType.DragPerform)\n                                {\n                                    m_Packables.AppendFoldoutPPtrValue(obj);\n                                    didAcceptDrag = true;\n                                    DragAndDrop.activeControlID = 0;\n                                }\n                                else\n                                    DragAndDrop.activeControlID = controlID;\n                            }\n                        }\n                        if (didAcceptDrag)\n                        {\n                            GUI.changed = true;\n                            DragAndDrop.AcceptDrag();\n                            usedEvent = true;\n                        }\n                    }\n                    break;\n                case EventType.ValidateCommand:\n                    if (currentEvent.commandName == ObjectSelector.ObjectSelectorClosedCommand && ObjectSelector.get.objectSelectorID == styles.packableSelectorHash)\n                        usedEvent = true;\n                    break;\n                case EventType.ExecuteCommand:\n                    if (currentEvent.commandName == ObjectSelector.ObjectSelectorClosedCommand && ObjectSelector.get.objectSelectorID == styles.packableSelectorHash)\n                    {\n                        var obj = ObjectSelector.GetCurrentObject();\n                        if (IsPackable(obj))\n                        {\n                            m_Packables.AppendFoldoutPPtrValue(obj);\n                            m_PackableList.index = m_Packables.arraySize - 1;\n                        }\n\n                        usedEvent = true;\n                    }\n                    break;\n            }\n\n            // Handle Foldout after we handle the current event because Foldout might process the drag and drop event and used it.\n            m_PackableListExpanded = EditorGUI.Foldout(rect, m_PackableListExpanded, styles.packableListLabel, true);\n\n            if (usedEvent)\n                currentEvent.Use();\n\n            if (m_PackableListExpanded)\n            {\n                EditorGUI.indentLevel++;\n                m_PackableList.DoLayoutList();\n                EditorGUI.indentLevel--;\n            }\n        }\n\n        public override void SaveChanges()\n        {\n            if (!m_Discard)\n                base.SaveChanges();\n            m_ContentHash = GetInspectorHash();\n        }\n\n        public override void DiscardChanges()\n        {\n            m_Discard = true;\n            base.DiscardChanges();\n            m_ContentHash = GetInspectorHash();\n        }\n\n        void CachePreviewTexture()\n        {\n            var spriteAtlas = AssetDatabase.LoadAssetAtPath<SpriteAtlas>(m_AssetPath);\n            if (spriteAtlas != null)\n            {\n                bool hasPreview = m_PreviewTextures != null && m_PreviewTextures.Length > 0;\n                if (hasPreview)\n                {\n                    foreach (var previewTexture in m_PreviewTextures)\n                        hasPreview = previewTexture != null;\n                }\n                if (!hasPreview || m_Hash != spriteAtlas.GetHash())\n                {\n                    m_PreviewTextures = spriteAtlas.GetPreviewTextures();\n                    m_PreviewAlphaTextures = spriteAtlas.GetPreviewAlphaTextures();\n                    m_Hash = spriteAtlas.GetHash();\n\n                    if (m_PreviewTextures != null\n                        && m_PreviewTextures.Length > 0\n                        && m_TotalPages != m_PreviewTextures.Length)\n                    {\n                        m_TotalPages = m_PreviewTextures.Length;\n                        m_OptionDisplays = new string[m_TotalPages];\n                        m_OptionValues = new int[m_TotalPages];\n                        for (int i = 0; i < m_TotalPages; ++i)\n                        {\n                            string texName = m_PreviewTextures[i].name;\n                            var pageNum = SpriteAtlasExtensions.GetPageNumberInAtlas(texName);\n                            var secondaryName = SpriteAtlasExtensions.GetSecondaryTextureNameInAtlas(texName);\n                            m_OptionDisplays[i] = secondaryName == \"\" ? string.Format(\"MainTex - Page ({0})\", pageNum) : string.Format(\"{0} - Page ({1})\", secondaryName, pageNum);\n                            m_OptionValues[i] = i;\n                        }\n                    }\n                }\n            }\n        }\n\n        public override string GetInfoString()\n        {\n            if (m_PreviewTextures != null && m_PreviewPage < m_PreviewTextures.Length)\n            {\n                Texture2D t = m_PreviewTextures[m_PreviewPage];\n                GraphicsFormat format = GraphicsFormatUtility.GetFormat(t);\n\n                return string.Format(\"{0}x{1} {2}\\n{3}\", t.width, t.height, GraphicsFormatUtility.GetFormatString(format), EditorUtility.FormatBytes(TextureUtil.GetStorageMemorySizeLong(t)));\n            }\n            return \"\";\n        }\n\n        public override bool HasPreviewGUI()\n        {\n            CachePreviewTexture();\n            if (m_PreviewTextures != null && m_PreviewTextures.Length > 0)\n            {\n                Texture2D t = m_PreviewTextures[0];\n                return t != null;\n            }\n            return false;\n        }\n\n        public override void OnPreviewSettings()\n        {\n            // Do not allow changing of pages when multiple atlases is selected.\n            if (targets.Length == 1 && m_OptionDisplays != null && m_OptionValues != null && m_TotalPages > 1)\n                m_PreviewPage = EditorGUILayout.IntPopup(m_PreviewPage, m_OptionDisplays, m_OptionValues, styles.preDropDown, GUILayout.MaxWidth(50));\n            else\n                m_PreviewPage = 0;\n\n            if (m_PreviewTextures != null)\n            {\n                m_PreviewPage = Mathf.Min(m_PreviewPage, m_PreviewTextures.Length - 1);\n\n                Texture2D t = m_PreviewTextures[m_PreviewPage];\n                if (t == null)\n                    return;\n\n                if (GraphicsFormatUtility.HasAlphaChannel(t.format) || (m_PreviewAlphaTextures != null && m_PreviewAlphaTextures.Length > 0))\n                    m_ShowAlpha = GUILayout.Toggle(m_ShowAlpha, m_ShowAlpha ? styles.alphaIcon : styles.RGBIcon, styles.previewButton);\n\n                int mipCount = Mathf.Max(1, TextureUtil.GetMipmapCount(t));\n                if (mipCount > 1)\n                {\n                    GUILayout.Box(styles.smallZoom, styles.previewLabel);\n                    m_MipLevel = Mathf.Round(GUILayout.HorizontalSlider(m_MipLevel, mipCount - 1, 0, styles.previewSlider, styles.previewSliderThumb, GUILayout.MaxWidth(64)));\n                    GUILayout.Box(styles.largeZoom, styles.previewLabel);\n                }\n            }\n        }\n\n        public override void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            CachePreviewTexture();\n\n            if (m_ShowAlpha && m_PreviewAlphaTextures != null && m_PreviewPage < m_PreviewAlphaTextures.Length)\n            {\n                var at = m_PreviewAlphaTextures[m_PreviewPage];\n                var bias = m_MipLevel - (float)(System.Math.Log(at.width / r.width) / System.Math.Log(2));\n\n                EditorGUI.DrawTextureTransparent(r, at, ScaleMode.ScaleToFit, 0, bias);\n            }\n            else if (m_PreviewTextures != null && m_PreviewPage < m_PreviewTextures.Length)\n            {\n                Texture2D t = m_PreviewTextures[m_PreviewPage];\n                if (t == null)\n                    return;\n\n                float bias = m_MipLevel - (float)(System.Math.Log(t.width / r.width) / System.Math.Log(2));\n\n                if (m_ShowAlpha)\n                    EditorGUI.DrawTextureAlpha(r, t, ScaleMode.ScaleToFit, 0, bias);\n                else\n                    EditorGUI.DrawTextureTransparent(r, t, ScaleMode.ScaleToFit, 0, bias);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Experimental.Rendering;\nusing UnityEngine.U2D;\nusing UnityEditor.Build;\nusing UnityEditor.U2D.Common;\nusing UnityEditor.U2D.Interface;\nusing UnityEditorInternal;\n\nnamespace UnityEditor.U2D\n{\n    [CustomEditor(typeof(SpriteAtlas))]\n    [CanEditMultipleObjects]\n    internal class SpriteAtlasInspector : Editor\n    {\n        class SpriteAtlasInspectorPlatformSettingView : TexturePlatformSettingsView\n        {\n            private bool m_ShowMaxSizeOption;\n\n            public SpriteAtlasInspectorPlatformSettingView(bool showMaxSizeOption)\n            {\n                m_ShowMaxSizeOption = showMaxSizeOption;\n            }\n\n            public override int DrawMaxSize(int defaultValue, bool isMixedValue, bool isDisabled, out bool changed)\n            {\n                if (m_ShowMaxSizeOption)\n                    return base.DrawMaxSize(defaultValue, isMixedValue, isDisabled, out changed);\n                else\n                    changed = false;\n                return defaultValue;\n            }\n        }\n\n        class Styles\n        {\n            public readonly GUIStyle preDropDown = \"preDropDown\";\n            public readonly GUIStyle previewButton = \"preButton\";\n            public readonly GUIStyle previewSlider = \"preSlider\";\n            public readonly GUIStyle previewSliderThumb = \"preSliderThumb\";\n            public readonly GUIStyle previewLabel = \"preLabel\";\n\n            public readonly GUIContent textureSettingLabel = EditorGUIUtility.TrTextContent(\"Texture\");\n            public readonly GUIContent variantSettingLabel = EditorGUIUtility.TrTextContent(\"Variant\");\n            public readonly GUIContent packingParametersLabel = EditorGUIUtility.TrTextContent(\"Packing\");\n            public readonly GUIContent atlasTypeLabel = EditorGUIUtility.TrTextContent(\"Type\");\n            public readonly GUIContent defaultPlatformLabel = EditorGUIUtility.TrTextContent(\"Default\");\n            public readonly GUIContent masterAtlasLabel = EditorGUIUtility.TrTextContent(\"Master Atlas\", \"Assigning another Sprite Atlas asset will make this atlas a variant of it.\");\n            public readonly GUIContent bindAsDefaultLabel = EditorGUIUtility.TrTextContent(\"Include in Build\", \"Packed textures will be included in the build by default.\");\n            public readonly GUIContent enableRotationLabel = EditorGUIUtility.TrTextContent(\"Allow Rotation\", \"Try rotating the sprite to fit better during packing.\");\n            public readonly GUIContent enableTightPackingLabel = EditorGUIUtility.TrTextContent(\"Tight Packing\", \"Use the mesh outline to fit instead of the whole texture rect during packing.\");\n            public readonly GUIContent enableAlphaDilationLabel = EditorGUIUtility.TrTextContent(\"Alpha Dilation\", \"Enable Alpha Dilation for SpriteAtlas padding pixels.\");\n            public readonly GUIContent paddingLabel = EditorGUIUtility.TrTextContent(\"Padding\", \"The amount of extra padding between packed sprites.\");\n\n            public readonly GUIContent generateMipMapLabel = EditorGUIUtility.TrTextContent(\"Generate Mip Maps\");\n            public readonly GUIContent sRGBLabel = EditorGUIUtility.TrTextContent(\"sRGB\", \"Texture content is stored in gamma space.\");\n            public readonly GUIContent readWrite = EditorGUIUtility.TrTextContent(\"Read/Write\", \"Enable to be able to access the raw pixel data from code.\");\n            public readonly GUIContent variantMultiplierLabel = EditorGUIUtility.TrTextContent(\"Scale\", \"Down scale ratio.\");\n            public readonly GUIContent packButton = EditorGUIUtility.TrTextContent(\"Pack Preview\", \"Pack this atlas.\");\n\n            public readonly GUIContent disabledPackLabel = EditorGUIUtility.TrTextContent(\"Sprite Atlas packing is disabled. Enable it in Edit > Project Settings > Editor.\", null, EditorGUIUtility.GetHelpIcon(MessageType.Info));\n            public readonly GUIContent packableListLabel = EditorGUIUtility.TrTextContent(\"Objects for Packing\", \"Only accepts Folder, Sprite Sheet (Texture) and Sprite.\");\n\n            public readonly GUIContent notPowerOfTwoWarning = EditorGUIUtility.TrTextContent(\"This scale will produce a Variant Sprite Atlas with a packed Texture that is NPOT (non - power of two). This may cause visual artifacts in certain compression/Texture formats.\");\n            public readonly GUIContent secondaryTextureNameLabel = EditorGUIUtility.TrTextContent(\"Secondary Texture Name\", \"The name of the Secondary Texture to apply the following settings to.\");\n            public readonly GUIContent platformSettingsDropDownLabel = EditorGUIUtility.TrTextContent(\"Show Platform Settings For\");\n\n            public readonly GUIContent smallZoom = EditorGUIUtility.IconContent(\"PreTextureMipMapLow\");\n            public readonly GUIContent largeZoom = EditorGUIUtility.IconContent(\"PreTextureMipMapHigh\");\n            public readonly GUIContent alphaIcon = EditorGUIUtility.IconContent(\"PreTextureAlpha\");\n            public readonly GUIContent RGBIcon = EditorGUIUtility.IconContent(\"PreTextureRGB\");\n            public readonly GUIContent trashIcon = EditorGUIUtility.TrIconContent(\"TreeEditor.Trash\", \"Delete currently selected settings.\");\n\n            public readonly int packableElementHash = \"PackableElement\".GetHashCode();\n            public readonly int packableSelectorHash = \"PackableSelector\".GetHashCode();\n\n            public readonly string swapObjectRegisterUndo = L10n.Tr(\"Swap Packable\");\n            public readonly string secondaryTextureNameTextControlName = \"secondary_texture_name_text_field\";\n            public readonly string defaultTextForSecondaryTextureName = L10n.Tr(\"(Matches the names of the Secondary Textures in your Sprites.)\");\n            public readonly string nameUniquenessWarning = L10n.Tr(\"Secondary Texture names must be unique within a Sprite or Sprite Atlas.\");\n\n            public readonly int[] atlasTypeValues = { 0, 1 };\n            public readonly GUIContent[] atlasTypeOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Master\"),\n                EditorGUIUtility.TrTextContent(\"Variant\"),\n            };\n\n            public readonly int[] paddingValues = { 2, 4, 8 };\n            public readonly GUIContent[] paddingOptions;\n\n            public Styles()\n            {\n                paddingOptions = new GUIContent[paddingValues.Length];\n                for (var i = 0; i < paddingValues.Length; ++i)\n                    paddingOptions[i] = EditorGUIUtility.TextContent(paddingValues[i].ToString());\n            }\n        }\n\n        private static Styles s_Styles;\n\n        private static Styles styles\n        {\n            get\n            {\n                s_Styles = s_Styles ?? new Styles();\n                return s_Styles;\n            }\n        }\n\n        private enum AtlasType { Undefined = -1, Master = 0, Variant = 1 }\n\n        private SerializedProperty m_FilterMode;\n        private SerializedProperty m_AnisoLevel;\n        private SerializedProperty m_GenerateMipMaps;\n        private SerializedProperty m_Readable;\n        private SerializedProperty m_UseSRGB;\n        private SerializedProperty m_EnableTightPacking;\n        private SerializedProperty m_EnableAlphaDilation;\n        private SerializedProperty m_EnableRotation;\n        private SerializedProperty m_Padding;\n        private SerializedProperty m_BindAsDefault;\n        private SerializedProperty m_Packables;\n\n        private SerializedProperty m_MasterAtlas;\n        private SerializedProperty m_VariantScale;\n\n        private string m_Hash;\n        private int m_PreviewPage = 0;\n        private int m_TotalPages = 0;\n        private int[] m_OptionValues = null;\n        private string[] m_OptionDisplays = null;\n        private Texture2D[] m_PreviewTextures = null;\n        private Texture2D[] m_PreviewAlphaTextures = null;\n\n        private bool m_PackableListExpanded = true;\n        private ReorderableList m_PackableList;\n\n        private float m_MipLevel = 0;\n        private bool m_ShowAlpha;\n\n        private List<string> m_PlatformSettingsOptions;\n        private int m_SelectedPlatformSettings = 0;\n\n        private List<BuildPlatform> m_ValidPlatforms;\n        private Dictionary<string, List<TextureImporterPlatformSettings>> m_TempPlatformSettings;\n\n        private ITexturePlatformSettingsView m_TexturePlatformSettingsView;\n        private ITexturePlatformSettingsView m_SecondaryTexturePlatformSettingsView;\n        private ITexturePlatformSettingsFormatHelper m_TexturePlatformSettingTextureHelper;\n        private ITexturePlatformSettingsController m_TexturePlatformSettingsController;\n\n        private SpriteAtlas spriteAtlas { get { return target as SpriteAtlas; } }\n\n        // The first two options are the main texture and a separator while the last two options are another separator and the new settings menu.\n        private bool secondaryTextureSelected { get { return m_SelectedPlatformSettings >= 2 && m_SelectedPlatformSettings <= m_PlatformSettingsOptions.Count - 3; } }\n\n        static bool IsPackable(Object o)\n        {\n            return o != null && (o.GetType() == typeof(Sprite) || o.GetType() == typeof(Texture2D) || (o.GetType() == typeof(DefaultAsset) && ProjectWindowUtil.IsFolder(o.GetInstanceID())));\n        }\n\n        static Object ValidateObjectForPackableFieldAssignment(Object[] references, System.Type objType, SerializedProperty property, EditorGUI.ObjectFieldValidatorOptions options)\n        {\n            // We only validate and care about the first one as this is a object field assignment.\n            if (references.Length > 0 && IsPackable(references[0]))\n                return references[0];\n            return null;\n        }\n\n        bool AllTargetsAreVariant()\n        {\n            foreach (SpriteAtlas sa in targets)\n            {\n                if (!sa.isVariant)\n                    return false;\n            }\n            return true;\n        }\n\n        bool AllTargetsAreMaster()\n        {\n            foreach (SpriteAtlas sa in targets)\n            {\n                if (sa.isVariant)\n                    return false;\n            }\n            return true;\n        }\n\n        void OnEnable()\n        {\n            if (targets == null)\n                return;\n            var validCount = 0;\n            foreach (var so in targets)\n            {\n                if (so != null)\n                    validCount++;\n            }\n            if (validCount == 0)\n                return;\n\n            m_FilterMode = serializedObject.FindProperty(\"m_EditorData.textureSettings.filterMode\");\n            m_AnisoLevel = serializedObject.FindProperty(\"m_EditorData.textureSettings.anisoLevel\");\n            m_GenerateMipMaps = serializedObject.FindProperty(\"m_EditorData.textureSettings.generateMipMaps\");\n            m_Readable = serializedObject.FindProperty(\"m_EditorData.textureSettings.readable\");\n            m_UseSRGB = serializedObject.FindProperty(\"m_EditorData.textureSettings.sRGB\");\n\n            m_EnableTightPacking = serializedObject.FindProperty(\"m_EditorData.packingSettings.enableTightPacking\");\n            m_EnableAlphaDilation = serializedObject.FindProperty(\"m_EditorData.packingSettings.enableAlphaDilation\");\n            m_EnableRotation = serializedObject.FindProperty(\"m_EditorData.packingSettings.enableRotation\");\n            m_Padding = serializedObject.FindProperty(\"m_EditorData.packingSettings.padding\");\n\n            m_MasterAtlas = serializedObject.FindProperty(\"m_MasterAtlas\");\n            m_BindAsDefault = serializedObject.FindProperty(\"m_EditorData.bindAsDefault\");\n            m_VariantScale = serializedObject.FindProperty(\"m_EditorData.variantMultiplier\");\n\n            PopulatePlatformSettingsOptions();\n\n            m_Packables = serializedObject.FindProperty(\"m_EditorData.packables\");\n            m_PackableList = new ReorderableList(serializedObject, m_Packables, true, true, true, true);\n            m_PackableList.drawHeaderCallback = DrawPackablesHeader;\n            m_PackableList.onAddCallback = AddPackable;\n            m_PackableList.onRemoveCallback = RemovePackable;\n            m_PackableList.drawElementCallback = DrawPackableElement;\n            m_PackableList.elementHeight = EditorGUIUtility.singleLineHeight;\n            m_PackableList.headerHeight = 3f + EditorGUIUtility.singleLineHeight;\n\n            SyncPlatformSettings();\n\n            m_TexturePlatformSettingsView = new SpriteAtlasInspectorPlatformSettingView(AllTargetsAreMaster());\n            m_TexturePlatformSettingTextureHelper = new TexturePlatformSettingsFormatHelper();\n            m_TexturePlatformSettingsController = new TexturePlatformSettingsViewController();\n\n            // Don't show max size option for secondary textures as they must have the same size as the main texture.\n            m_SecondaryTexturePlatformSettingsView = new SpriteAtlasInspectorPlatformSettingView(false);\n        }\n\n        // Populate the platform settings dropdown list with secondary texture names found through serialized properties of the Sprite Atlas assets.\n        private void PopulatePlatformSettingsOptions()\n        {\n            m_PlatformSettingsOptions = new List<string> { L10n.Tr(\"Main Texture\"), \"\", \"\", L10n.Tr(\"New Secondary Texture settings.\") };\n            SerializedProperty secondaryPlatformSettings = serializedObject.FindProperty(\"m_EditorData.secondaryTextureSettings\");\n            if (secondaryPlatformSettings != null && !secondaryPlatformSettings.hasMultipleDifferentValues)\n            {\n                int numSecondaryTextures = secondaryPlatformSettings.arraySize;\n                List<string> secondaryTextureNames = new List<string>(numSecondaryTextures);\n\n                for (int i = 0; i < numSecondaryTextures; ++i)\n                    secondaryTextureNames.Add(secondaryPlatformSettings.GetArrayElementAtIndex(i).displayName);\n\n                // Insert after main texture and the separator.\n                m_PlatformSettingsOptions.InsertRange(2, secondaryTextureNames);\n            }\n\n            m_SelectedPlatformSettings = 0;\n        }\n\n        void SyncPlatformSettings()\n        {\n            m_TempPlatformSettings = new Dictionary<string, List<TextureImporterPlatformSettings>>();\n\n            string secondaryTextureName = null;\n            if (secondaryTextureSelected)\n                secondaryTextureName = m_PlatformSettingsOptions[m_SelectedPlatformSettings];\n\n            // Default platform\n            var defaultSettings = new List<TextureImporterPlatformSettings>();\n            m_TempPlatformSettings.Add(TextureImporterInspector.s_DefaultPlatformName, defaultSettings);\n            foreach (SpriteAtlas sa in targets)\n            {\n                var settings = secondaryTextureSelected\n                    ? sa.GetSecondaryPlatformSettings(TextureImporterInspector.s_DefaultPlatformName, secondaryTextureName)\n                    : sa.GetPlatformSettings(TextureImporterInspector.s_DefaultPlatformName);\n\n                defaultSettings.Add(settings);\n            }\n\n            m_ValidPlatforms = BuildPlatforms.instance.GetValidPlatforms();\n            foreach (var platform in m_ValidPlatforms)\n            {\n                var platformSettings = new List<TextureImporterPlatformSettings>();\n                m_TempPlatformSettings.Add(platform.name, platformSettings);\n                foreach (SpriteAtlas sa in targets)\n                {\n                    var settings = secondaryTextureSelected\n                        ? sa.GetSecondaryPlatformSettings(platform.name, secondaryTextureName)\n                        : sa.GetPlatformSettings(platform.name);\n\n                    // setting will be in default state if copy failed\n                    platformSettings.Add(settings);\n                }\n            }\n        }\n\n        void RenameSecondaryPlatformSettings(string oldName, string newName)\n        {\n            for (var i = 0; i < targets.Length; ++i)\n            {\n                SpriteAtlas sa = (SpriteAtlas)targets[i];\n\n                sa.DeleteSecondaryPlatformSettings(oldName);\n\n                var defaultPlatformSettings = m_TempPlatformSettings[TextureImporterInspector.s_DefaultPlatformName];\n                sa.SetSecondaryPlatformSettings(defaultPlatformSettings[i], newName);\n\n                foreach (var buildPlatform in m_ValidPlatforms)\n                {\n                    var platformSettings = m_TempPlatformSettings[buildPlatform.name];\n                    sa.SetSecondaryPlatformSettings(platformSettings[i], newName);\n                }\n            }\n        }\n\n        void DrawPackablesHeader(Rect headerRect)\n        {\n            EditorGUI.LabelField(headerRect, EditorGUIUtility.TempContent(\"Packables\"));\n        }\n\n        void AddPackable(ReorderableList list)\n        {\n            ObjectSelector.get.Show(null, typeof(Object), null, false);\n            ObjectSelector.get.searchFilter = \"t:sprite t:texture2d t:folder\";\n            ObjectSelector.get.objectSelectorID = styles.packableSelectorHash;\n        }\n\n        void RemovePackable(ReorderableList list)\n        {\n            var index = list.index;\n            if (index != -1)\n                spriteAtlas.RemoveAt(index);\n        }\n\n        void DrawPackableElement(Rect rect, int index, bool selected, bool focused)\n        {\n            var property = m_Packables.GetArrayElementAtIndex(index);\n            var controlID = EditorGUIUtility.GetControlID(styles.packableElementHash, FocusType.Passive);\n            var previousObject = property.objectReferenceValue;\n\n            var changedObject = EditorGUI.DoObjectField(rect, rect, controlID, previousObject, target, typeof(Object), ValidateObjectForPackableFieldAssignment, false);\n            if (changedObject != previousObject)\n            {\n                // Always call Remove() on the previous object if we swapping the object field item.\n                // This ensure the Sprites was pack in this atlas will be refreshed of it unbound.\n                Undo.RegisterCompleteObjectUndo(spriteAtlas, styles.swapObjectRegisterUndo);\n                if (previousObject != null)\n                    spriteAtlas.Remove(new Object[] { previousObject });\n                property.objectReferenceValue = changedObject;\n            }\n\n            if (GUIUtility.keyboardControl == controlID && !selected)\n                m_PackableList.index = index;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            // Ensure changes done through script are reflected immediately in Inspector by Syncing m_TempPlatformSettings with Actual Settings.\n            SyncPlatformSettings();\n\n            serializedObject.Update();\n\n            HandleCommonSettingUI();\n\n            GUILayout.Space(EditorGUI.kSpacing);\n\n            if (AllTargetsAreVariant())\n                HandleVariantSettingUI();\n            else if (AllTargetsAreMaster())\n                HandleMasterSettingUI();\n\n            GUILayout.Space(EditorGUI.kSpacing);\n\n            HandleTextureSettingUI();\n\n            GUILayout.Space(EditorGUI.kSpacing);\n\n            // Only show the packable object list when:\n            // - This is a master atlas.\n            // - It is not currently selecting multiple atlases.\n            if (targets.Length == 1 && AllTargetsAreMaster())\n                HandlePackableListUI();\n\n            bool spriteAtlasPackingEnabled = (EditorSettings.spritePackerMode == SpritePackerMode.BuildTimeOnlyAtlas\n                || EditorSettings.spritePackerMode == SpritePackerMode.AlwaysOnAtlas || EditorSettings.spritePackerMode == SpritePackerMode.SpriteAtlasV2);\n            if (spriteAtlasPackingEnabled && !Application.isPlaying)\n            {\n                using (new EditorGUI.DisabledScope(!Editor.IsPersistent(spriteAtlas)))\n                {\n                    if (GUILayout.Button(styles.packButton, GUILayout.ExpandWidth(false)))\n                    {\n                        SpriteAtlas[] spriteAtlases = new SpriteAtlas[targets.Length];\n                        for (int i = 0; i < spriteAtlases.Length; ++i)\n                            spriteAtlases[i] = (SpriteAtlas)targets[i];\n\n                        SpriteAtlasUtility.PackAtlases(spriteAtlases, EditorUserBuildSettings.activeBuildTarget);\n\n                        // Packing an atlas might change platform settings in the process, reinitialize\n                        SyncPlatformSettings();\n\n                        GUIUtility.ExitGUI();\n                    }\n                }\n            }\n            else\n            {\n                if (GUILayout.Button(styles.disabledPackLabel, EditorStyles.helpBox))\n                {\n                    SettingsService.OpenProjectSettings(\"Project/Editor\");\n                }\n            }\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        private void HandleCommonSettingUI()\n        {\n            var atlasType = AtlasType.Undefined;\n            if (AllTargetsAreMaster())\n                atlasType = AtlasType.Master;\n            else if (AllTargetsAreVariant())\n                atlasType = AtlasType.Variant;\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = atlasType == AtlasType.Undefined;\n            using (new EditorGUI.DisabledScope(!Editor.IsPersistent(spriteAtlas)))\n            {\n                atlasType = (AtlasType)EditorGUILayout.IntPopup(styles.atlasTypeLabel, (int)atlasType, styles.atlasTypeOptions, styles.atlasTypeValues);\n            }\n            EditorGUI.showMixedValue = false;\n            if (EditorGUI.EndChangeCheck())\n            {\n                bool setToVariant = atlasType == AtlasType.Variant;\n                foreach (SpriteAtlas sa in targets)\n                    sa.SetIsVariant(setToVariant);\n\n                // Reinit the platform setting view\n                m_TexturePlatformSettingsView = new SpriteAtlasInspectorPlatformSettingView(AllTargetsAreMaster());\n            }\n\n            if (atlasType == AtlasType.Variant)\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUILayout.PropertyField(m_MasterAtlas, styles.masterAtlasLabel);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    // Apply modified properties here to have latest master atlas reflected in native codes.\n                    serializedObject.ApplyModifiedProperties();\n\n                    foreach (SpriteAtlas sa in targets)\n                        sa.CopyMasterAtlasSettings();\n\n                    PopulatePlatformSettingsOptions();\n                    SyncPlatformSettings();\n                }\n            }\n\n            EditorGUILayout.PropertyField(m_BindAsDefault, styles.bindAsDefaultLabel);\n        }\n\n        private void HandleVariantSettingUI()\n        {\n            EditorGUILayout.LabelField(styles.variantSettingLabel, EditorStyles.boldLabel);\n            EditorGUILayout.PropertyField(m_VariantScale, styles.variantMultiplierLabel);\n\n            // Test if the multiplier scale a power of two size (1024) into another power of 2 size.\n            if (!Mathf.IsPowerOfTwo((int)(m_VariantScale.floatValue * 1024)))\n                EditorGUILayout.HelpBox(styles.notPowerOfTwoWarning.text, MessageType.Warning, true);\n        }\n\n        private void HandleBoolToIntPropertyField(SerializedProperty prop, GUIContent content)\n        {\n            Rect rect = EditorGUILayout.GetControlRect();\n            EditorGUI.BeginProperty(rect, content, prop);\n            EditorGUI.BeginChangeCheck();\n            var boolValue = EditorGUI.Toggle(rect, content, prop.boolValue);\n            if (EditorGUI.EndChangeCheck())\n                prop.boolValue = boolValue;\n            EditorGUI.EndProperty();\n        }\n\n        private void HandleMasterSettingUI()\n        {\n            EditorGUILayout.LabelField(styles.packingParametersLabel, EditorStyles.boldLabel);\n\n            HandleBoolToIntPropertyField(m_EnableRotation, styles.enableRotationLabel);\n            HandleBoolToIntPropertyField(m_EnableTightPacking, styles.enableTightPackingLabel);\n            HandleBoolToIntPropertyField(m_EnableAlphaDilation, styles.enableAlphaDilationLabel);\n            EditorGUILayout.IntPopup(m_Padding, styles.paddingOptions, styles.paddingValues, styles.paddingLabel);\n\n            GUILayout.Space(EditorGUI.kSpacing);\n        }\n\n        private void HandleTextureSettingUI()\n        {\n            EditorGUILayout.LabelField(styles.textureSettingLabel, EditorStyles.boldLabel);\n\n            HandleBoolToIntPropertyField(m_Readable, styles.readWrite);\n            HandleBoolToIntPropertyField(m_GenerateMipMaps, styles.generateMipMapLabel);\n            HandleBoolToIntPropertyField(m_UseSRGB, styles.sRGBLabel);\n            EditorGUILayout.PropertyField(m_FilterMode);\n\n            var showAniso = !m_FilterMode.hasMultipleDifferentValues && !m_GenerateMipMaps.hasMultipleDifferentValues\n                && (FilterMode)m_FilterMode.intValue != FilterMode.Point && m_GenerateMipMaps.boolValue;\n            if (showAniso)\n                EditorGUILayout.IntSlider(m_AnisoLevel, 0, 16);\n\n            GUILayout.Space(EditorGUI.kSpacing);\n\n            // \"Show Platform Settings For\" dropdown\n            EditorGUILayout.BeginHorizontal();\n            {\n                EditorGUILayout.PrefixLabel(s_Styles.platformSettingsDropDownLabel);\n\n                EditorGUI.BeginChangeCheck();\n                m_SelectedPlatformSettings = EditorGUILayout.Popup(m_SelectedPlatformSettings, m_PlatformSettingsOptions.ToArray(), GUILayout.MaxWidth(150.0f));\n                if (EditorGUI.EndChangeCheck())\n                {\n                    // New settings option is selected...\n                    if (m_SelectedPlatformSettings == m_PlatformSettingsOptions.Count - 1)\n                    {\n                        m_PlatformSettingsOptions.Insert(m_SelectedPlatformSettings - 1, s_Styles.defaultTextForSecondaryTextureName);\n                        m_SelectedPlatformSettings--;\n                        EditorGUI.FocusTextInControl(s_Styles.secondaryTextureNameTextControlName);\n                    }\n\n                    SyncPlatformSettings();\n                }\n\n                if (secondaryTextureSelected)\n                {\n                    // trash can button\n                    if (GUILayout.Button(s_Styles.trashIcon, EditorStyles.iconButton, GUILayout.ExpandWidth(false)))\n                    {\n                        EditorGUI.EndEditingActiveTextField();\n\n                        foreach (SpriteAtlas sa in targets)\n                            sa.DeleteSecondaryPlatformSettings(m_PlatformSettingsOptions[m_SelectedPlatformSettings]);\n\n                        m_PlatformSettingsOptions.RemoveAt(m_SelectedPlatformSettings);\n\n                        m_SelectedPlatformSettings--;\n                        if (m_SelectedPlatformSettings == 1)\n                            m_SelectedPlatformSettings = 0;\n\n                        SyncPlatformSettings();\n                    }\n                }\n            }\n            EditorGUILayout.EndHorizontal();\n\n            // Texture platform settings UI.\n            EditorGUILayout.BeginHorizontal();\n            {\n                EditorGUI.indentLevel++;\n                GUILayout.Space(EditorGUI.indent);\n                EditorGUI.indentLevel--;\n\n                if (m_SelectedPlatformSettings == 0)\n                {\n                    GUILayout.Space(EditorGUI.kSpacing);\n                    HandlePlatformSettingUI(null);\n                }\n                else\n                {\n                    EditorGUILayout.BeginVertical();\n                    {\n                        GUILayout.Space(EditorGUI.kSpacing);\n                        string oldSecondaryTextureName = m_PlatformSettingsOptions[m_SelectedPlatformSettings];\n                        GUI.SetNextControlName(s_Styles.secondaryTextureNameTextControlName);\n\n                        EditorGUI.BeginChangeCheck();\n                        string textFieldText = EditorGUILayout.DelayedTextField(s_Styles.secondaryTextureNameLabel, oldSecondaryTextureName);\n                        if (EditorGUI.EndChangeCheck() && oldSecondaryTextureName != textFieldText)\n                        {\n                            if (!m_PlatformSettingsOptions.Exists(x => x == textFieldText))\n                            {\n                                m_PlatformSettingsOptions[m_SelectedPlatformSettings] = textFieldText;\n                                RenameSecondaryPlatformSettings(oldSecondaryTextureName, textFieldText);\n                            }\n                            else\n                            {\n                                Debug.LogWarning(s_Styles.nameUniquenessWarning);\n                                EditorGUI.FocusTextInControl(s_Styles.secondaryTextureNameTextControlName);\n                            }\n                        }\n\n                        string secondaryTextureName = m_PlatformSettingsOptions[m_SelectedPlatformSettings];\n                        SpriteAtlas sa = (SpriteAtlas)target;\n                        EditorGUI.BeginChangeCheck();\n                        bool value = EditorGUILayout.Toggle(s_Styles.sRGBLabel, sa.GetSecondaryColorSpace(secondaryTextureName));\n                        if (EditorGUI.EndChangeCheck())\n                            sa.SetSecondaryColorSpace(secondaryTextureName, value);\n\n                        HandlePlatformSettingUI(textFieldText);\n                    }\n                    EditorGUILayout.EndVertical();\n                }\n            }\n            EditorGUILayout.EndHorizontal();\n        }\n\n        private void HandlePlatformSettingUI(string secondaryTextureName)\n        {\n            bool isSecondary = secondaryTextureName != null;\n            ITexturePlatformSettingsView view = isSecondary ? m_SecondaryTexturePlatformSettingsView : m_TexturePlatformSettingsView;\n\n            int shownTextureFormatPage = EditorGUILayout.BeginPlatformGrouping(m_ValidPlatforms.ToArray(), s_Styles.defaultPlatformLabel);\n            var defaultPlatformSettings = m_TempPlatformSettings[TextureImporterInspector.s_DefaultPlatformName];\n\n            if (shownTextureFormatPage == -1)\n            {\n                if (m_TexturePlatformSettingsController.HandleDefaultSettings(defaultPlatformSettings, view, m_TexturePlatformSettingTextureHelper))\n                {\n                    for (var i = 0; i < defaultPlatformSettings.Count; ++i)\n                    {\n                        SpriteAtlas sa = (SpriteAtlas)targets[i];\n\n                        if (isSecondary)\n                            sa.SetSecondaryPlatformSettings(defaultPlatformSettings[i], secondaryTextureName);\n                        else\n                            sa.SetPlatformSettings(defaultPlatformSettings[i]);\n                    }\n                }\n            }\n            else\n            {\n                var buildPlatform = m_ValidPlatforms[shownTextureFormatPage];\n                var platformSettings = m_TempPlatformSettings[buildPlatform.name];\n\n                for (var i = 0; i < platformSettings.Count; ++i)\n                {\n                    var settings = platformSettings[i];\n                    if (!settings.overridden)\n                    {\n                        if (defaultPlatformSettings[0].format == TextureImporterFormat.Automatic)\n                        {\n                            SpriteAtlas sa = (SpriteAtlas)targets[i];\n                            settings.format = (TextureImporterFormat)sa.GetTextureFormat(buildPlatform.defaultTarget);\n                        }\n                        else\n                        {\n                            settings.format = defaultPlatformSettings[0].format;\n                        }\n\n                        settings.maxTextureSize = defaultPlatformSettings[0].maxTextureSize;\n                        settings.crunchedCompression = defaultPlatformSettings[0].crunchedCompression;\n                        settings.compressionQuality = defaultPlatformSettings[0].compressionQuality;\n                    }\n                }\n\n                view.buildPlatformTitle = buildPlatform.title.text;\n                if (m_TexturePlatformSettingsController.HandlePlatformSettings(buildPlatform.defaultTarget, platformSettings, view, m_TexturePlatformSettingTextureHelper))\n                {\n                    for (var i = 0; i < platformSettings.Count; ++i)\n                    {\n                        SpriteAtlas sa = (SpriteAtlas)targets[i];\n                        if (isSecondary)\n                            sa.SetSecondaryPlatformSettings(platformSettings[i], secondaryTextureName);\n                        else\n                            sa.SetPlatformSettings(platformSettings[i]);\n                    }\n                }\n            }\n\n            EditorGUILayout.EndPlatformGrouping();\n        }\n\n        private void HandlePackableListUI()\n        {\n            var currentEvent = Event.current;\n            var usedEvent = false;\n\n            Rect rect = EditorGUILayout.GetControlRect();\n\n            var controlID = EditorGUIUtility.s_LastControlID;\n            switch (currentEvent.type)\n            {\n                case EventType.DragExited:\n                    if (GUI.enabled)\n                        HandleUtility.Repaint();\n                    break;\n\n                case EventType.DragUpdated:\n                case EventType.DragPerform:\n                    if (rect.Contains(currentEvent.mousePosition) && GUI.enabled)\n                    {\n                        // Check each single object, so we can add multiple objects in a single drag.\n                        var didAcceptDrag = false;\n                        var references = DragAndDrop.objectReferences;\n                        foreach (var obj in references)\n                        {\n                            if (IsPackable(obj))\n                            {\n                                DragAndDrop.visualMode = DragAndDropVisualMode.Copy;\n                                if (currentEvent.type == EventType.DragPerform)\n                                {\n                                    m_Packables.AppendFoldoutPPtrValue(obj);\n                                    didAcceptDrag = true;\n                                    DragAndDrop.activeControlID = 0;\n                                }\n                                else\n                                    DragAndDrop.activeControlID = controlID;\n                            }\n                        }\n                        if (didAcceptDrag)\n                        {\n                            GUI.changed = true;\n                            DragAndDrop.AcceptDrag();\n                            usedEvent = true;\n                        }\n                    }\n                    break;\n                case EventType.ValidateCommand:\n                    if (currentEvent.commandName == ObjectSelector.ObjectSelectorClosedCommand && ObjectSelector.get.objectSelectorID == styles.packableSelectorHash)\n                        usedEvent = true;\n                    break;\n                case EventType.ExecuteCommand:\n                    if (currentEvent.commandName == ObjectSelector.ObjectSelectorClosedCommand && ObjectSelector.get.objectSelectorID == styles.packableSelectorHash)\n                    {\n                        var obj = ObjectSelector.GetCurrentObject();\n                        if (IsPackable(obj))\n                        {\n                            m_Packables.AppendFoldoutPPtrValue(obj);\n                            m_PackableList.index = m_Packables.arraySize - 1;\n                        }\n\n                        usedEvent = true;\n                    }\n                    break;\n            }\n\n            // Handle Foldout after we handle the current event because Foldout might process the drag and drop event and used it.\n            m_PackableListExpanded = EditorGUI.Foldout(rect, m_PackableListExpanded, styles.packableListLabel, true);\n\n            if (usedEvent)\n                currentEvent.Use();\n\n            if (m_PackableListExpanded)\n            {\n                EditorGUI.indentLevel++;\n                m_PackableList.DoLayoutList();\n                EditorGUI.indentLevel--;\n            }\n        }\n\n        void CachePreviewTexture()\n        {\n            if (m_PreviewTextures == null || m_Hash != spriteAtlas.GetHash())\n            {\n                m_PreviewTextures = spriteAtlas.GetPreviewTextures();\n                m_PreviewAlphaTextures = spriteAtlas.GetPreviewAlphaTextures();\n                m_Hash = spriteAtlas.GetHash();\n\n                if (m_PreviewTextures != null\n                    && m_PreviewTextures.Length > 0\n                    && m_TotalPages != m_PreviewTextures.Length)\n                {\n                    m_TotalPages = m_PreviewTextures.Length;\n                    m_OptionDisplays = new string[m_TotalPages];\n                    m_OptionValues = new int[m_TotalPages];\n                    for (int i = 0; i < m_TotalPages; ++i)\n                    {\n                        string texName = m_PreviewTextures[i].name;\n                        var pageNum = SpriteAtlasExtensions.GetPageNumberInAtlas(texName);\n                        var secondaryName = SpriteAtlasExtensions.GetSecondaryTextureNameInAtlas(texName);\n                        m_OptionDisplays[i] = secondaryName == \"\" ? string.Format(\"MainTex - Page ({0})\", pageNum) : string.Format(\"{0} - Page ({1})\", secondaryName, pageNum);\n                        m_OptionValues[i] = i;\n                    }\n                }\n            }\n        }\n\n        public override string GetInfoString()\n        {\n            if (m_PreviewTextures != null && m_PreviewPage < m_PreviewTextures.Length)\n            {\n                Texture2D t = m_PreviewTextures[m_PreviewPage];\n                GraphicsFormat format = GraphicsFormatUtility.GetFormat(t);\n\n                return string.Format(\"{0}x{1} {2}\\n{3}\", t.width, t.height, GraphicsFormatUtility.GetFormatString(format), EditorUtility.FormatBytes(TextureUtil.GetStorageMemorySizeLong(t)));\n            }\n            return \"\";\n        }\n\n        public override bool HasPreviewGUI()\n        {\n            CachePreviewTexture();\n            return (m_PreviewTextures != null && m_PreviewTextures.Length > 0);\n        }\n\n        public override void OnPreviewSettings()\n        {\n            // Do not allow changing of pages when multiple atlases is selected.\n            if (targets.Length == 1 && m_OptionDisplays != null && m_OptionValues != null && m_TotalPages > 1)\n                m_PreviewPage = EditorGUILayout.IntPopup(m_PreviewPage, m_OptionDisplays, m_OptionValues, styles.preDropDown, GUILayout.MaxWidth(50));\n            else\n                m_PreviewPage = 0;\n\n            if (m_PreviewTextures != null)\n            {\n                m_PreviewPage = Mathf.Min(m_PreviewPage, m_PreviewTextures.Length - 1);\n\n                Texture2D t = m_PreviewTextures[m_PreviewPage];\n\n                if (GraphicsFormatUtility.HasAlphaChannel(t.format) || (m_PreviewAlphaTextures != null && m_PreviewAlphaTextures.Length > 0))\n                    m_ShowAlpha = GUILayout.Toggle(m_ShowAlpha, m_ShowAlpha ? styles.alphaIcon : styles.RGBIcon, styles.previewButton);\n\n                int mipCount = Mathf.Max(1, TextureUtil.GetMipmapCount(t));\n                if (mipCount > 1)\n                {\n                    GUILayout.Box(styles.smallZoom, styles.previewLabel);\n                    m_MipLevel = Mathf.Round(GUILayout.HorizontalSlider(m_MipLevel, mipCount - 1, 0, styles.previewSlider, styles.previewSliderThumb, GUILayout.MaxWidth(64)));\n                    GUILayout.Box(styles.largeZoom, styles.previewLabel);\n                }\n            }\n        }\n\n        public override void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            CachePreviewTexture();\n\n            if (m_ShowAlpha && m_PreviewAlphaTextures != null && m_PreviewPage < m_PreviewAlphaTextures.Length)\n            {\n                var at = m_PreviewAlphaTextures[m_PreviewPage];\n                var bias = m_MipLevel - (float)(System.Math.Log(at.width / r.width) / System.Math.Log(2));\n\n                EditorGUI.DrawTextureTransparent(r, at, ScaleMode.ScaleToFit, 0, bias);\n            }\n            else if (m_PreviewTextures != null && m_PreviewPage < m_PreviewTextures.Length)\n            {\n                Texture2D t = m_PreviewTextures[m_PreviewPage];\n\n                float bias = m_MipLevel - (float)(System.Math.Log(t.width / r.width) / System.Math.Log(2));\n\n                if (m_ShowAlpha)\n                    EditorGUI.DrawTextureAlpha(r, t, ScaleMode.ScaleToFit, 0, bias);\n                else\n                    EditorGUI.DrawTextureTransparent(r, t, ScaleMode.ScaleToFit, 0, bias);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Accessibility/UserAccessibilitySettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Accessibility\n{\n    internal enum ColorBlindCondition\n    {\n        Default,\n        Deuteranopia,\n        Protanopia,\n        Tritanopia,\n    }\n\n    // NOTE: The preferences in this class are currently only exposed via a context menu in the ProfilerWindow\n    // these toggles need to instead be moved to e.g., the Preferences menu before they are used elsewhere\n    internal static class UserAccessiblitySettings\n    {\n        static UserAccessiblitySettings()\n        {\n            s_ColorBlindCondition = (ColorBlindCondition)EditorPrefs.GetInt(k_ColorBlindConditionPrefKey, (int)ColorBlindCondition.Default);\n        }\n\n        private const string k_ColorBlindConditionPrefKey = \"AccessibilityColorBlindCondition\";\n\n        public static ColorBlindCondition colorBlindCondition\n        {\n            get { return s_ColorBlindCondition; }\n            set\n            {\n                if (s_ColorBlindCondition != value)\n                {\n                    s_ColorBlindCondition = value;\n                    EditorPrefs.SetInt(k_ColorBlindConditionPrefKey, (int)value);\n                    if (colorBlindConditionChanged != null)\n                        colorBlindConditionChanged();\n                }\n            }\n        }\n        private static ColorBlindCondition s_ColorBlindCondition;\n\n        public static Action colorBlindConditionChanged;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationClipSettings.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEngine.Playables;\nusing UnityEngine.Scripting.APIUpdating;\nusing UnityEngine.Internal;\n\nnamespace UnityEditor\n{\n    [NativeType(CodegenOptions.Custom, \"MonoAnimationClipSettings\")]\n    [NativeAsStruct]\n    [StructLayout(LayoutKind.Sequential)]\n    [RequiredByNativeCode]\n    public class AnimationClipSettings\n    {\n        public AnimationClip additiveReferencePoseClip;\n        public float additiveReferencePoseTime;\n        public float startTime;\n        public float stopTime;\n        public float orientationOffsetY;\n        public float level;\n        public float cycleOffset;\n        public bool hasAdditiveReferencePose;\n        public bool loopTime;\n        public bool loopBlend;\n        public bool loopBlendOrientation;\n        public bool loopBlendPositionY;\n        public bool loopBlendPositionXZ;\n        public bool keepOriginalOrientation;\n        public bool keepOriginalPositionY;\n        public bool keepOriginalPositionXZ;\n        public bool heightFromFeet;\n        public bool mirror;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationClipStats.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEngine.Playables;\nusing UnityEngine.Scripting.APIUpdating;\nusing UnityEngine.Internal;\n\nnamespace UnityEditor\n{\n    // Must be kept in sync with AnimationClipStats in AnimationClipStats\n    internal struct AnimationClipStats\n    {\n        public int size;\n        public int clips;\n        public int positionCurves;\n        public int quaternionCurves;\n        public int eulerCurves;\n        public int scaleCurves;\n        public int muscleCurves;\n        public int genericCurves;\n        public int pptrCurves;\n        public int totalCurves;\n        public int constantCurves;\n        public int denseCurves;\n        public int streamCurves;\n\n        public void Reset()\n        {\n            size = 0;\n            clips = 0;\n            positionCurves = 0;\n            quaternionCurves = 0;\n            eulerCurves = 0;\n            scaleCurves = 0;\n            muscleCurves = 0;\n            genericCurves = 0;\n            pptrCurves = 0;\n            totalCurves = 0;\n            constantCurves = 0;\n            denseCurves = 0;\n            streamCurves = 0;\n        }\n\n        public void Combine(AnimationClipStats other)\n        {\n            size += other.size;\n            clips += other.clips;\n            positionCurves += other.positionCurves;\n            quaternionCurves += other.quaternionCurves;\n            eulerCurves += other.eulerCurves;\n            scaleCurves += other.scaleCurves;\n            muscleCurves += other.muscleCurves;\n            genericCurves += other.genericCurves;\n            pptrCurves += other.pptrCurves;\n            totalCurves += other.totalCurves;\n            constantCurves += other.constantCurves;\n            denseCurves += other.denseCurves;\n            streamCurves += other.streamCurves;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationMode.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEngine.Scripting.APIUpdating;\nusing UnityEngine.Playables;\nusing UnityEngine;\n\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    public class AnimationModeDriver : ScriptableObject\n    {\n        internal delegate bool IsKeyCallback(Object target, string propertyPath);\n\n        internal IsKeyCallback isKeyCallback;\n\n        [UsedByNativeCode]\n        internal bool InvokeIsKeyCallback_Internal(Object target, string propertyPath)\n        {\n            if (isKeyCallback == null)\n                return false;\n\n            return isKeyCallback(target, propertyPath);\n        }\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/AnimationMode.bindings.h\")]\n    [NativeHeader(\"Editor/Src/Animation/EditorCurveBinding.bindings.h\")]\n    [NativeHeader(\"Editor/Src/Prefabs/PropertyModification.h\")]\n    public class AnimationMode\n    {\n        static private bool s_InAnimationPlaybackMode = false;\n        static private bool s_InAnimationRecordMode = false;\n\n        static internal event Action onAnimationRecordingStart;\n        static internal event Action onAnimationRecordingStop;\n\n        static private PrefColor s_AnimatedPropertyColor = new PrefColor(\"Animation/Property Animated\", 0.82f, 0.97f, 1.00f, 1.00f, 0.54f, 0.85f, 1.00f, 1.00f);\n        static private PrefColor s_RecordedPropertyColor = new PrefColor(\"Animation/Property Recorded\", 1.00f, 0.60f, 0.60f, 1.00f, 1.00f, 0.50f, 0.50f, 1.00f);\n        static private PrefColor s_CandidatePropertyColor = new PrefColor(\"Animation/Property Candidate\", 1.00f, 0.70f, 0.60f, 1.00f, 1.00f, 0.67f, 0.43f, 1.00f);\n\n        static public Color animatedPropertyColor { get { return s_AnimatedPropertyColor; } }\n        static public Color recordedPropertyColor { get { return s_RecordedPropertyColor; } }\n        static public Color candidatePropertyColor { get { return s_CandidatePropertyColor; } }\n\n        static private AnimationModeDriver s_DummyDriver;\n        static private AnimationModeDriver DummyDriver()\n        {\n            if (s_DummyDriver == null)\n            {\n                s_DummyDriver = ScriptableObject.CreateInstance<AnimationModeDriver>();\n                s_DummyDriver.name = \"DummyDriver\";\n            }\n            return s_DummyDriver;\n        }\n\n        extern public static bool IsPropertyAnimated(Object target, string propertyPath);\n        extern internal static bool IsPropertyCandidate(Object target, string propertyPath);\n\n        // Stops animation mode, as used by the animation editor.\n        public static void StopAnimationMode()\n        {\n            Internal_StopAnimationMode(DummyDriver());\n        }\n\n        // Stops animation mode, as used by the animation editor.\n        public static void StopAnimationMode(AnimationModeDriver driver)\n        {\n            Internal_StopAnimationMode(driver);\n        }\n\n        // Returns true if the editor is currently in animation mode.\n        public static bool InAnimationMode()\n        {\n            return Internal_InAnimationModeNoDriver();\n        }\n\n        // Returns true if the editor is currently in animation mode.\n        public static bool InAnimationMode(AnimationModeDriver driver)\n        {\n            return Internal_InAnimationMode(driver);\n        }\n\n        // Starts animation mode, as used by the animation editor.\n        public static void StartAnimationMode()\n        {\n            Internal_StartAnimationMode(DummyDriver());\n        }\n\n        // Starts animation mode, as used by the animation editor.\n        public static void StartAnimationMode(AnimationModeDriver driver)\n        {\n            Internal_StartAnimationMode(driver);\n        }\n\n        // Stops animation playback mode, as used by the animation editor.\n        internal static void StopAnimationPlaybackMode()\n        {\n            s_InAnimationPlaybackMode = false;\n        }\n\n        // Returns true if the editor is currently in animation playback mode.\n        internal static bool InAnimationPlaybackMode()\n        {\n            return s_InAnimationPlaybackMode;\n        }\n\n        // Starts animation mode, as used by the animation editor playback mode.\n        internal static void StartAnimationPlaybackMode()\n        {\n            s_InAnimationPlaybackMode = true;\n        }\n\n        internal static void StopAnimationRecording()\n        {\n            s_InAnimationRecordMode = false;\n\n            onAnimationRecordingStop?.Invoke();\n        }\n\n        internal static bool InAnimationRecording()\n        {\n            return s_InAnimationRecordMode;\n        }\n\n        internal static void StartAnimationRecording()\n        {\n            s_InAnimationRecordMode = true;\n\n            onAnimationRecordingStart?.Invoke();\n        }\n\n        internal static void StartCandidateRecording(AnimationModeDriver driver)\n        {\n            Internal_StartCandidateRecording(driver);\n        }\n\n        [NativeThrows]\n        extern internal static void AddCandidate(EditorCurveBinding binding, PropertyModification modification, bool keepPrefabOverride);\n\n        [NativeThrows]\n        extern internal static void AddCandidates([NotNull] GameObject gameObject, [NotNull] AnimationClip clip);\n\n        extern internal static void StopCandidateRecording();\n\n        extern internal static bool IsRecordingCandidates();\n\n        [NativeThrows]\n        extern public static void BeginSampling();\n\n        [NativeThrows]\n        extern public static void EndSampling();\n\n        [NativeThrows]\n        extern public static void SampleAnimationClip([NotNull] GameObject gameObject, [NotNull] AnimationClip clip, float time);\n\n        [NativeThrows]\n        extern internal static void SampleCandidateClip([NotNull] GameObject gameObject, [NotNull] AnimationClip clip, float time);\n\n        [NativeThrows]\n        extern public static void SamplePlayableGraph(PlayableGraph graph, int index, float time);\n\n        [NativeThrows]\n        extern public static void AddPropertyModification(EditorCurveBinding binding, PropertyModification modification, bool keepPrefabOverride);\n\n        [NativeThrows]\n        extern public static void AddEditorCurveBinding([NotNull] GameObject gameObject, EditorCurveBinding binding);\n\n        [NativeThrows]\n        extern internal static void AddTransformTR([NotNull] GameObject root, string path);\n\n        [NativeThrows]\n        extern internal static void AddTransformTRS([NotNull] GameObject root, string path);\n\n        [NativeThrows]\n        extern internal static void InitializePropertyModificationForGameObject([NotNull] GameObject gameObject, [NotNull] AnimationClip clip);\n\n        [NativeThrows]\n        extern internal static void InitializePropertyModificationForObject([NotNull] Object target, [NotNull] AnimationClip clip);\n\n        [NativeThrows]\n        extern internal static void RevertPropertyModificationsForGameObject([NotNull] GameObject gameObject);\n\n        [NativeThrows]\n        extern internal static void RevertPropertyModificationsForObject([NotNull] Object target);\n\n        // Returns editor curve bindings for animation clip and animator hierarchy that need to be snapshot for animation mode.\n        extern internal static EditorCurveBinding[] GetAllBindings([NotNull] GameObject root, [NotNull] AnimationClip clip);\n\n        // Returns editor curve bindings for animation clip that need to be snapshot for animation mode.\n        extern internal static EditorCurveBinding[] GetCurveBindings([NotNull] AnimationClip clip);\n\n        // Return editor curve bindings for animator hierarhcy that need to be snapshot for animation mode.\n        extern internal static EditorCurveBinding[] GetAnimatorBindings([NotNull] GameObject root);\n\n        extern private static void Internal_StartAnimationMode(Object driver);\n\n        extern private static void Internal_StopAnimationMode(Object driver);\n\n        extern private static bool Internal_InAnimationMode(Object driver);\n\n        extern private static bool Internal_InAnimationModeNoDriver();\n\n        [NativeThrows]\n        extern private static void Internal_StartCandidateRecording(Object driver);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEngine.Scripting.APIUpdating;\nusing UnityEngine;\nusing UnityEngine.Internal;\n\nusing Object = UnityEngine.Object;\nusing UnityEngine.Animations;\n\nnamespace UnityEditor\n{\n    public struct ObjectReferenceKeyframe\n    {\n        public float time;\n        public UnityEngine.Object value;\n    }\n\n    // An AnimationClipCurveData object contains all the information needed to identify a specific curve in an AnimationClip. The curve animates a specific property of a component / material attached to a game object / animated bone.\n    public class AnimationClipCurveData\n    {\n        // The path of the game object / bone being animated.\n        public string path;\n        // The type of the component / material being animated.\n        public Type   type;\n        // The name of the property being animated.\n        public string propertyName;\n        // The actual animation curve.\n        public AnimationCurve curve;\n\n        // This is only used internally for deleting curves\n        internal int  classID;\n        internal int  scriptInstanceID;\n\n        public AnimationClipCurveData()\n        {\n        }\n\n        public AnimationClipCurveData(EditorCurveBinding binding)\n        {\n            path = binding.path;\n            type = binding.type;\n            propertyName = binding.propertyName;\n            curve = null;\n            classID = binding.m_ClassID;\n            scriptInstanceID = binding.m_ScriptInstanceID;\n        }\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/AnimationUtility.bindings.h\")]\n    [NativeHeader(\"Modules/Animation/ScriptBindings/GenericBinding.bindings.h\")]\n    public partial class AnimationUtility\n    {\n        public enum CurveModifiedType\n        {\n            CurveDeleted = 0,\n            CurveModified = 1,\n            ClipModified = 2\n        }\n\n        public enum TangentMode\n        {\n            Free = 0,\n            Auto = 1,\n            Linear = 2,\n            Constant = 3,\n            ClampedAuto = 4\n        }\n\n        internal enum PolynomialValid\n        {\n            Valid = 0,\n            InvalidPreWrapMode = 1,\n            InvalidPostWrapMode = 2,\n            TooManySegments = 3\n        }\n\n        internal enum DiscreteBindingResult\n        {\n            Valid = 0,\n            InvalidScript = 1,\n            MissingField = 2,\n            IncompatibleFieldType = 3,\n            MissingDiscreteAttribute  = 4\n        }\n\n        public delegate void OnCurveWasModified(AnimationClip clip, EditorCurveBinding binding, CurveModifiedType type);\n        public static OnCurveWasModified onCurveWasModified;\n\n        [RequiredByNativeCode]\n        private static void Internal_CallOnCurveWasModified(AnimationClip clip, EditorCurveBinding binding, CurveModifiedType type)\n        {\n            if (onCurveWasModified != null)\n                onCurveWasModified(clip, binding, type);\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_CallAnimationClipAwake(AnimationClip clip)\n        {\n            if (onCurveWasModified != null)\n                onCurveWasModified(clip, new EditorCurveBinding(), CurveModifiedType.ClipModified);\n        }\n\n        [Obsolete(\"GetAnimationClips(Animation) is deprecated. Use GetAnimationClips(GameObject) instead.\")]\n        public static AnimationClip[] GetAnimationClips(Animation component)\n        {\n            return GetAnimationClipsInAnimationPlayer(component.gameObject);\n        }\n\n        // Returns the array of AnimationClips that are referenced in the Animation component\n        public static AnimationClip[] GetAnimationClips(GameObject gameObject)\n        {\n            if (gameObject == null)\n                throw new ArgumentNullException(\"gameObject\");\n\n            AnimationClip[] clips = GetAnimationClipsInAnimationPlayer(gameObject);\n\n            IAnimationClipSource[] clipSources = gameObject.GetComponents<IAnimationClipSource>();\n            if (clipSources.Length > 0)\n            {\n                var allClips = new List<AnimationClip>(clips);\n                for (int i = 0; i < clipSources.Length; ++i)\n                {\n                    var extraClips = new List<AnimationClip>();\n                    clipSources[i].GetAnimationClips(extraClips);\n\n                    allClips.Capacity = allClips.Count + extraClips.Count;\n                    foreach (var clip in extraClips)\n                    {\n                        if (clip != null)\n                            allClips.Add(clip);\n                    }\n                }\n\n                return allClips.ToArray();\n            }\n\n            return clips;\n        }\n\n        // Returns the array of AnimationClips that are referenced in the Animation component\n        extern internal static AnimationClip[] GetAnimationClipsInAnimationPlayer([NotNull] GameObject gameObject);\n\n        // Sets the array of AnimationClips to be referenced in the Animation component\n        extern public static void SetAnimationClips([NotNull] Animation animation, [Unmarshalled] AnimationClip[] clips);\n\n        public static EditorCurveBinding[] GetAnimatableBindings(GameObject targetObject, GameObject root)\n        {\n            return Internal_GetGameObjectAnimatableBindings(targetObject, root);\n        }\n\n        internal static EditorCurveBinding[] GetAnimatableBindings(ScriptableObject scriptableObject)\n        {\n            return Internal_GetScriptableObjectAnimatableBindings(scriptableObject);\n        }\n\n        internal static EditorCurveBinding[] GetAnimationStreamBindings(GameObject root)\n        {\n            return Internal_GetAnimationStreamBindings(root);\n        }\n\n        extern private static EditorCurveBinding[] Internal_GetGameObjectAnimatableBindings([NotNull] GameObject targetObject, [NotNull] GameObject root);\n        extern private static EditorCurveBinding[] Internal_GetScriptableObjectAnimatableBindings([NotNull] ScriptableObject scriptableObject);\n        extern private static EditorCurveBinding[] Internal_GetAnimationStreamBindings([NotNull] GameObject root);\n\n        // Binds the property and returns the type of the bound value (Can be used to display special UI for it and to enforce correct drag and drop)\n        // null if it can't be bound.\n        public static System.Type GetEditorCurveValueType(GameObject root, EditorCurveBinding binding)\n        {\n            return Internal_GetGameObjectEditorCurveValueType(root, binding);\n        }\n\n        internal static System.Type GetEditorCurveValueType(ScriptableObject scriptableObject, EditorCurveBinding binding)\n        {\n            return Internal_GetScriptableObjectEditorCurveValueType(scriptableObject, binding);\n        }\n\n        extern private static System.Type Internal_GetGameObjectEditorCurveValueType([NotNull] GameObject root, EditorCurveBinding binding);\n        extern private static System.Type Internal_GetScriptableObjectEditorCurveValueType([NotNull] ScriptableObject scriptableObject, EditorCurveBinding binding);\n\n        extern public static bool GetFloatValue([NotNull] GameObject root, EditorCurveBinding binding, out float data);\n        extern public static bool GetDiscreteIntValue([NotNull] GameObject root, EditorCurveBinding binding, out int data);\n        public static bool GetObjectReferenceValue(GameObject root, EditorCurveBinding binding, out Object data)\n        {\n            data = Internal_GetObjectReferenceValue(root, binding, out bool result);\n            return result;\n        }\n\n        extern private static Object Internal_GetObjectReferenceValue([NotNull] GameObject root, EditorCurveBinding binding, out bool result);\n\n        extern public static Object GetAnimatedObject([NotNull] GameObject root, EditorCurveBinding binding);\n\n        public static Type PropertyModificationToEditorCurveBinding(PropertyModification modification, GameObject gameObject, out EditorCurveBinding binding)\n        {\n            binding = new EditorCurveBinding();\n            binding.type = typeof(Object); // dummy type to avoid errors while marshalling.\n\n            if (modification == null)\n                return null;\n\n            return Internal_PropertyModificationToEditorCurveBinding(modification, gameObject, out binding);\n        }\n\n        extern private static Type Internal_PropertyModificationToEditorCurveBinding(PropertyModification modification, [NotNull] GameObject gameObject, out EditorCurveBinding binding);\n        extern internal static PropertyModification EditorCurveBindingToPropertyModification(EditorCurveBinding binding, [NotNull] GameObject gameObject);\n\n        extern public static EditorCurveBinding[] GetCurveBindings([NotNull] AnimationClip clip);\n        extern public static EditorCurveBinding[] GetObjectReferenceCurveBindings([NotNull] AnimationClip clip);\n\n        extern public static ObjectReferenceKeyframe[] GetObjectReferenceCurve([NotNull] AnimationClip clip, EditorCurveBinding binding);\n\n        public static void SetObjectReferenceCurve(AnimationClip clip, EditorCurveBinding binding, [Unmarshalled]ObjectReferenceKeyframe[] keyframes)\n        {\n            Internal_SetObjectReferenceCurve(clip, binding, keyframes, true);\n            Internal_InvokeOnCurveWasModified(clip, binding, keyframes != null ? CurveModifiedType.CurveModified : CurveModifiedType.CurveDeleted);\n        }\n\n        public static void SetObjectReferenceCurves(AnimationClip clip, EditorCurveBinding[] bindings, ObjectReferenceKeyframe[][] keyframes)\n        {\n            if (bindings == null)\n                throw new ArgumentNullException(nameof(bindings), $\"{nameof(bindings)} must be non-null\");\n            if (keyframes == null)\n                throw new ArgumentNullException(nameof(keyframes), $\"{nameof(keyframes)} must be non-null\");\n            if (bindings.Length != keyframes.Length)\n                throw new InvalidOperationException($\"{nameof(bindings)} and {nameof(keyframes)} must be of equal length\");\n\n            int length = bindings.Length;\n            for (int i = 0; i < length; i++)\n            {\n                SetObjectReferenceCurveNoSync(clip, bindings[i], keyframes[i]);\n            }\n            SyncEditorCurves(clip);\n            Internal_InvokeOnCurveWasModified(clip, new EditorCurveBinding(), CurveModifiedType.ClipModified);\n        }\n\n        internal static void SetObjectReferenceCurveNoSync(AnimationClip clip, EditorCurveBinding binding, ObjectReferenceKeyframe[] keyframes)\n        {\n            Internal_SetObjectReferenceCurve(clip, binding, keyframes, false);\n            Internal_InvokeOnCurveWasModified(clip, binding, keyframes != null ? CurveModifiedType.CurveModified : CurveModifiedType.CurveDeleted);\n        }\n\n        [NativeThrows]\n        extern private static void Internal_SetObjectReferenceCurve([NotNull] AnimationClip clip, EditorCurveBinding binding, [Unmarshalled] ObjectReferenceKeyframe[] keyframes, bool updateMuscleClip);\n\n        extern public static AnimationCurve GetEditorCurve([NotNull] AnimationClip clip, EditorCurveBinding binding);\n\n        public static void SetEditorCurve(AnimationClip clip, EditorCurveBinding binding, AnimationCurve curve)\n        {\n            Internal_SetEditorCurve(clip, binding, curve, true);\n            Internal_InvokeOnCurveWasModified(clip, binding, curve != null ? CurveModifiedType.CurveModified : CurveModifiedType.CurveDeleted);\n        }\n\n        public static void SetEditorCurves(AnimationClip clip, EditorCurveBinding[] bindings, AnimationCurve[] curves)\n        {\n            if (bindings == null)\n                throw new ArgumentNullException(nameof(bindings), $\"{nameof(bindings)} must be non-null\");\n            if (curves == null)\n                throw new ArgumentNullException(nameof(curves), $\"{nameof(curves)} must be non-null\");\n            if (bindings.Length != curves.Length)\n                throw new InvalidOperationException($\"{nameof(bindings)} and {nameof(curves)} must be of equal length\");\n\n            int length = bindings.Length;\n            for (int i = 0; i < length; i++)\n            {\n                SetEditorCurveNoSync(clip, bindings[i], curves[i]);\n            }\n            SyncEditorCurves(clip);\n\n            Internal_InvokeOnCurveWasModified(clip, new EditorCurveBinding(), AnimationUtility.CurveModifiedType.ClipModified);\n        }\n\n        internal static void SetEditorCurveNoSync(AnimationClip clip, EditorCurveBinding binding, AnimationCurve curve)\n        {\n            Internal_SetEditorCurve(clip, binding, curve, false);\n            Internal_InvokeOnCurveWasModified(clip, binding, curve != null ? CurveModifiedType.CurveModified : CurveModifiedType.CurveDeleted);\n        }\n\n        [NativeThrows]\n        extern private static void Internal_SetEditorCurve([NotNull] AnimationClip clip, EditorCurveBinding binding, AnimationCurve curve, bool syncEditorCurves);\n\n        extern internal static DiscreteBindingResult IsDiscreteIntBinding(EditorCurveBinding binding);\n\n        extern internal static void SyncEditorCurves([NotNull] AnimationClip clip);\n\n        private static void Internal_InvokeOnCurveWasModified(AnimationClip clip, EditorCurveBinding binding, CurveModifiedType type)\n        {\n            if (onCurveWasModified != null)\n            {\n                onCurveWasModified(clip, binding, type);\n            }\n        }\n\n        [NativeThrows]\n        extern internal static void UpdateTangentsFromModeSurrounding([NotNull] AnimationCurve curve, int index);\n\n        extern internal static void UpdateTangentsFromMode([NotNull] AnimationCurve curve);\n\n        [NativeThrows, ThreadSafe]\n        extern public static TangentMode GetKeyLeftTangentMode([NotNull] AnimationCurve curve, int index);\n\n        [NativeThrows, ThreadSafe]\n        extern public static TangentMode GetKeyRightTangentMode([NotNull] AnimationCurve curve, int index);\n\n        [NativeThrows]\n        extern public static bool GetKeyBroken([NotNull] AnimationCurve curve, int index);\n\n        [NativeThrows, ThreadSafe]\n        extern public static void SetKeyLeftTangentMode([NotNull] AnimationCurve curve, int index, TangentMode tangentMode);\n\n        [NativeThrows, ThreadSafe]\n        extern public static void SetKeyRightTangentMode([NotNull] AnimationCurve curve, int index, TangentMode tangentMode);\n\n        [NativeThrows]\n        extern public static void SetKeyBroken([NotNull] AnimationCurve curve, int index, bool broken);\n\n        internal static TangentMode GetKeyLeftTangentMode(Keyframe key)\n        {\n            return Internal_GetKeyLeftTangentMode(key);\n        }\n\n        internal static TangentMode GetKeyRightTangentMode(Keyframe key)\n        {\n            return Internal_GetKeyRightTangentMode(key);\n        }\n\n        internal static bool GetKeyBroken(Keyframe key)\n        {\n            return Internal_GetKeyBroken(key);\n        }\n\n        extern private static TangentMode Internal_GetKeyLeftTangentMode(Keyframe key);\n        extern private static TangentMode Internal_GetKeyRightTangentMode(Keyframe key);\n        extern private static bool Internal_GetKeyBroken(Keyframe key);\n\n        internal static void SetKeyLeftTangentMode(ref Keyframe key, TangentMode tangentMode)\n        {\n            Internal_SetKeyLeftTangentMode(ref key, tangentMode);\n        }\n\n        internal static void SetKeyRightTangentMode(ref Keyframe key, TangentMode tangentMode)\n        {\n            Internal_SetKeyRightTangentMode(ref key, tangentMode);\n        }\n\n        internal static void SetKeyBroken(ref Keyframe key, bool broken)\n        {\n            Internal_SetKeyBroken(ref key, broken);\n        }\n\n        extern private static void Internal_SetKeyLeftTangentMode(ref Keyframe key, TangentMode tangentMode);\n        extern private static void Internal_SetKeyRightTangentMode(ref Keyframe key, TangentMode tangentMode);\n        extern private static void Internal_SetKeyBroken(ref Keyframe key, bool broken);\n\n        [NativeThrows]\n        extern internal static int AddInbetweenKey(AnimationCurve curve, float time);\n\n        [Obsolete(\"GetAllCurves is deprecated. Use GetCurveBindings and GetObjectReferenceCurveBindings instead.\")]\n        public static AnimationClipCurveData[] GetAllCurves(AnimationClip clip)\n        {\n            bool includeCurveData = true;\n            return GetAllCurves(clip, includeCurveData);\n        }\n\n        [Obsolete(\"GetAllCurves is deprecated. Use GetCurveBindings and GetObjectReferenceCurveBindings instead.\")]\n        public static AnimationClipCurveData[] GetAllCurves(AnimationClip clip, [DefaultValue(\"true\")] bool includeCurveData)\n        {\n            EditorCurveBinding[] bindings = GetCurveBindings(clip);\n\n            AnimationClipCurveData[] curves = new AnimationClipCurveData[bindings.Length];\n            for (int i = 0; i < curves.Length; i++)\n            {\n                curves[i] = new AnimationClipCurveData(bindings[i]);\n\n                if (includeCurveData)\n                    curves[i].curve = GetEditorCurve(clip, bindings[i]);\n            }\n\n            return curves;\n        }\n\n        [Obsolete(\"This overload is deprecated. Use the one with EditorCurveBinding instead.\")]\n        public static bool GetFloatValue(GameObject root, string relativePath, Type type, string propertyName, out float data)\n        {\n            return GetFloatValue(root, EditorCurveBinding.FloatCurve(relativePath, type, propertyName), out data);\n        }\n\n        [Obsolete(\"This overload is deprecated. Use the one with EditorCurveBinding instead.\")]\n        public static void SetEditorCurve(AnimationClip clip, string relativePath, Type type, string propertyName, AnimationCurve curve)\n        {\n            SetEditorCurve(clip, EditorCurveBinding.FloatCurve(relativePath, type, propertyName), curve);\n        }\n\n        [Obsolete(\"This overload is deprecated. Use the one with EditorCurveBinding instead.\")]\n        public static AnimationCurve GetEditorCurve(AnimationClip clip, string relativePath, Type type, string propertyName)\n        {\n            return GetEditorCurve(clip, EditorCurveBinding.FloatCurve(relativePath, type, propertyName));\n        }\n\n        public static AnimationEvent[] GetAnimationEvents(AnimationClip clip)\n        {\n            var blittableEvents = GetAnimationEventsInternal(clip);\n            var animationEvents = blittableEvents.Select(AnimationEventBlittable.ToAnimationEvent).ToArray();\n            foreach (var blittableEvent in blittableEvents)\n                blittableEvent.Dispose();\n            return animationEvents;\n        }\n        [return:Unmarshalled]\n        extern internal static AnimationEventBlittable[] GetAnimationEventsInternal([NotNull] AnimationClip clip);\n        public static void SetAnimationEvents(AnimationClip clip, AnimationEvent[] events)\n        {\n            var blittableEvents = events.Select(AnimationEventBlittable.FromAnimationEvent).ToArray();\n            SetAnimationEventsInternal(clip, blittableEvents);\n            foreach (var blittableEvent in blittableEvents)\n                blittableEvent.Dispose();\n        }\n        extern internal static void SetAnimationEventsInternal([NotNull] AnimationClip clip, [NotNull] AnimationEventBlittable[] events);\n\n        extern public static string CalculateTransformPath([NotNull] Transform targetTransform, Transform root);\n\n        extern public static AnimationClipSettings GetAnimationClipSettings([NotNull] AnimationClip clip);\n        extern internal static void RebuildMecanimData([NotNull] AnimationClip clip);\n        extern public static void SetAnimationClipSettings([NotNull] AnimationClip clip, AnimationClipSettings srcClipInfo);\n        extern internal static void SetAnimationClipSettingsNoDirty([NotNull] AnimationClip clip, AnimationClipSettings srcClipInfo);\n\n        extern public static void SetAdditiveReferencePose(AnimationClip clip, AnimationClip referenceClip, float time);\n\n        extern internal static bool IsValidOptimizedPolynomialCurve(AnimationCurve curve);\n        extern public static void ConstrainToPolynomialCurve(AnimationCurve curve);\n        extern internal static int GetMaxNumPolynomialSegmentsSupported();\n        extern internal static PolynomialValid IsValidPolynomialCurve(AnimationCurve curve);\n\n        extern internal static AnimationClipStats GetAnimationClipStats(AnimationClip clip);\n\n        [Obsolete(\"This is not used anymore.  Root motion curves are automatically generated if applyRootMotion is enabled on Animator component.\")]\n        public static bool GetGenerateMotionCurves(AnimationClip clip)\n        {\n            return true;\n        }\n\n        [Obsolete(\"This is not used anymore.  Root motion curves are automatically generated if applyRootMotion is enabled on Animator component.\")]\n        public static void SetGenerateMotionCurves(AnimationClip clip, bool value)\n        {\n        }\n\n        [Obsolete(\"Use AnimationClip.hasGenericRootTransform instead.\")]\n        extern internal static bool HasGenericRootTransform(AnimationClip clip);\n\n        [Obsolete(\"Use AnimationClip.hasMotionFloatCurves instead.\")]\n        extern internal static bool HasMotionFloatCurves(AnimationClip clip);\n\n        [Obsolete(\"Use AnimationClip.hasMotionCurves instead.\")]\n        extern internal static bool HasMotionCurves(AnimationClip clip);\n\n        [Obsolete(\"Use AnimationClip.hasRootCurves instead.\")]\n        extern internal static bool HasRootCurves(AnimationClip clip);\n\n        extern internal static bool AmbiguousBinding(string path, int classID, Transform root);\n\n        extern internal static Vector3 GetClosestEuler(Quaternion q, Vector3 eulerHint, RotationOrder rotationOrder);\n\n        [NativeHeader(\"Modules/Animation/AnimationUtility.h\")]\n        [FreeFunction]\n        extern internal static void SampleEulerHint([NotNull] GameObject go, [NotNull] AnimationClip clip, float inTime, WrapMode wrapMode);\n\n        [Obsolete(\"Use AnimationMode.InAnimationMode instead.\")]\n        static public bool InAnimationMode()\n        {\n            return AnimationMode.InAnimationMode();\n        }\n\n        [Obsolete(\"Use AnimationMode.StartAnimationmode instead.\")]\n        public static void StartAnimationMode(Object[] objects)\n        {\n            Debug.LogWarning(\"AnimationUtility.StartAnimationMode is deprecated. Use AnimationMode.StartAnimationMode with the new APIs. The objects passed to this function will no longer be reverted automatically. See AnimationMode.AddPropertyModification\");\n            AnimationMode.StartAnimationMode();\n        }\n\n        [Obsolete(\"Use AnimationMode.StopAnimationMode instead.\")]\n        public static void StopAnimationMode()\n        {\n            AnimationMode.StopAnimationMode();\n        }\n\n        [Obsolete(\"SetAnimationType is no longer supported.\")]\n        public static void SetAnimationType(AnimationClip clip, ModelImporterAnimationType type) {}\n\n\n        extern public static GenericBinding[] EditorCurveBindingsToGenericBindings(EditorCurveBinding[] editorCurveBindings);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AddCurvesPopup.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor;\nusing UnityEngine;\nusing System;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditorInternal\n{\n    internal class AddCurvesPopup : EditorWindow\n    {\n        const float k_WindowPadding = 3;\n        const float k_SpaceForSlider = 16;\n\n        const float k_WindowMaxWidth = 450;\n        const float k_WindowMinWidth = 240;\n        const float k_WindowFixedHeight = 250;\n\n        internal static AnimationWindowState s_State;\n\n        private static AddCurvesPopup s_AddCurvesPopup;\n        private static long s_LastClosedTime;\n        private static AddCurvesPopupHierarchy s_Hierarchy;\n\n        public delegate void OnNewCurveAdded(AddCurvesPopupPropertyNode node);\n\n        private static OnNewCurveAdded NewCurveAddedCallback;\n\n        Vector2 GetWindowSize()\n        {\n            float contentWidth = s_Hierarchy.GetContentWidth();\n            float width = Mathf.Clamp(contentWidth + k_SpaceForSlider + k_WindowPadding, k_WindowMinWidth, k_WindowMaxWidth);\n            return new Vector2(width, k_WindowFixedHeight);\n        }\n\n        void Init(Rect buttonRect)\n        {\n            s_Hierarchy = new AddCurvesPopupHierarchy();\n            s_Hierarchy.InitIfNeeded(this, new Rect(0, 0, k_WindowMinWidth, k_WindowFixedHeight));\n\n            buttonRect = GUIUtility.GUIToScreenRect(buttonRect);\n\n            ShowAsDropDown(buttonRect, GetWindowSize(), new[] { PopupLocation.Right });\n        }\n\n        void OnEnable()\n        {\n            AssemblyReloadEvents.beforeAssemblyReload += Close;\n        }\n\n        void OnDisable()\n        {\n            AssemblyReloadEvents.beforeAssemblyReload -= Close;\n            s_LastClosedTime = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond;\n            s_AddCurvesPopup = null;\n            s_Hierarchy = null;\n        }\n\n        internal static void AddNewCurve(AddCurvesPopupPropertyNode node)\n        {\n            AnimationWindowUtility.CreateDefaultCurves(s_State, node.curveBindings);\n            if (NewCurveAddedCallback != null)\n                NewCurveAddedCallback(node);\n        }\n\n        internal static bool ShowAtPosition(Rect buttonRect, AnimationWindowState state, OnNewCurveAdded newCurveCallback)\n        {\n            // We could not use realtimeSinceStartUp since it is set to 0 when entering/exitting playmode, we assume an increasing time when comparing time.\n            long nowMilliSeconds = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond;\n            bool justClosed = nowMilliSeconds < s_LastClosedTime + 50;\n            if (!justClosed)\n            {\n                Event.current.Use();\n                if (s_AddCurvesPopup == null)\n                    s_AddCurvesPopup = ScriptableObject.CreateInstance<AddCurvesPopup>();\n\n                NewCurveAddedCallback = newCurveCallback;\n                s_State = state;\n                s_AddCurvesPopup.Init(buttonRect);\n                return true;\n            }\n            return false;\n        }\n\n        internal void OnGUI()\n        {\n            // We do not use the layout event\n            if (Event.current.type == EventType.Layout)\n                return;\n\n            Vector2 windowSize = GetWindowSize();\n\n            Rect rect = new Rect(1, 1, windowSize.x - k_WindowPadding, windowSize.y - k_WindowPadding);\n            GUI.Box(new Rect(0, 0, windowSize.x, windowSize.y), GUIContent.none, \"grey_border\");\n            s_Hierarchy.OnGUI(rect, this);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchy.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditorInternal\n{\n    internal class AddCurvesPopupHierarchy\n    {\n        private TreeViewController m_TreeView;\n        private TreeViewState m_TreeViewState;\n        private AddCurvesPopupHierarchyDataSource m_TreeViewDataSource;\n\n        private float m_ContentWidth = 0f;\n\n        public float GetContentWidth()\n        {\n            return m_ContentWidth;\n        }\n\n        public void OnGUI(Rect position, EditorWindow owner)\n        {\n            m_TreeView.SetTotalRect(position);\n            m_TreeView.OnEvent();\n            m_TreeView.OnGUI(position, GUIUtility.GetControlID(FocusType.Keyboard));\n        }\n\n        public void InitIfNeeded(EditorWindow owner, Rect rect)\n        {\n            if (m_TreeViewState == null)\n                m_TreeViewState = new TreeViewState();\n            else\n                return;\n\n            m_TreeView = new TreeViewController(owner, m_TreeViewState);\n\n            m_TreeView.deselectOnUnhandledMouseDown = true;\n\n            m_TreeViewDataSource = new AddCurvesPopupHierarchyDataSource(m_TreeView);\n            AddCurvesPopupHierarchyGUI gui = new AddCurvesPopupHierarchyGUI(m_TreeView, owner);\n\n            m_TreeView.Init(rect,\n                m_TreeViewDataSource,\n                gui,\n                null\n            );\n\n            m_TreeViewDataSource.UpdateData();\n\n            m_ContentWidth = gui.GetContentWidth();\n        }\n\n        internal virtual bool IsRenamingNodeAllowed(TreeViewItem node)\n        {\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyBuilder.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor;\nusing UnityEngine;\nusing System;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing Object = UnityEngine.Object;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewUtility = UnityEditor.IMGUI.Controls.TreeViewUtility<int>;\n\nnamespace UnityEditorInternal\n{\n    struct AddCurvesPopupHierarchyBuilder\n    {\n        struct KeyComparer : IComparer<Key>\n        {\n            static readonly Type s_GameObjectType = typeof(GameObject);\n            static readonly Type s_TransformType = typeof(Transform);\n\n            public int Compare(Key x, Key y)\n            {\n                var result = String.Compare(x.path, y.path, StringComparison.Ordinal);\n                if (result == 0 && x.type != y.type)\n                {\n                    // Make sure GameObject properties appear first, then Transform.\n                    if (x.type == s_GameObjectType)\n                        return -1;\n                    if (y.type == s_GameObjectType)\n                        return 1;\n                    if (x.type == typeof(Transform))\n                        return -1;\n                    if (y.type == typeof(Transform))\n                        return 1;\n\n                    return String.Compare(x.type.Name, y.type.Name, StringComparison.Ordinal);\n                }\n\n                return result;\n            }\n        }\n\n        struct Key\n        {\n            public string path;\n            public Type type;\n        }\n\n        SortedDictionary<Key, List<EditorCurveBinding>> m_AccumulatedBindings;\n        AnimationWindowState m_State;\n\n        public AddCurvesPopupHierarchyBuilder(AnimationWindowState state)\n        {\n            m_AccumulatedBindings = new SortedDictionary<Key, List<EditorCurveBinding>>(new KeyComparer());\n            m_State = state;\n        }\n\n        public void Add(EditorCurveBinding binding)\n        {\n            var key = new Key { path = binding.path, type = binding.type };\n\n            if (m_AccumulatedBindings.TryGetValue(key, out var bindings))\n                bindings.Add(binding);\n            else\n                m_AccumulatedBindings[key] = new List<EditorCurveBinding>(new [] {binding});\n        }\n\n        void RemoveUnnecessaryBindings(List<EditorCurveBinding> bindings)\n        {\n            for (int i = bindings.Count - 1; i >= 0; --i)\n            {\n                // Let's not add those that already have a existing curve.\n                if (AnimationWindowUtility.IsCurveCreated(m_State.activeAnimationClip, bindings[i]))\n                    bindings.RemoveAt(i);\n                // Remove animator enabled property which shouldn't be animated.\n                else if (bindings[i].type == typeof(Animator) && bindings[i].propertyName == \"m_Enabled\")\n                    bindings.RemoveAt(i);\n                // For RectTransform.position we only want .z\n                else if (AnimationWindowUtility.IsRectTransformPosition(bindings[i]) && !bindings[i].propertyName.EndsWith(\".z\"))\n                    bindings.RemoveAt(i);\n                // Don't show for the root go\n                else if (bindings[i].type == typeof(GameObject) && string.IsNullOrEmpty(bindings[i].path))\n                    bindings.RemoveAt(i);\n            }\n        }\n\n        public TreeViewItem CreateTreeView()\n        {\n            TreeViewItem rootNode;\n\n            // Bindings of a single Component/ScriptableObject, skip the group node.\n            if (m_AccumulatedBindings.Count == 1)\n            {\n                var bindings = m_AccumulatedBindings.First().Value;\n                RemoveUnnecessaryBindings(bindings);\n\n                if (bindings.Count > 0)\n                {\n                    rootNode = AddAnimatableObjectToHierarchy(bindings, null, \"\");\n                }\n                else\n                {\n                    rootNode = new AddCurvesPopupObjectNode(null, string.Empty, string.Empty);\n                }\n            }\n            else\n            {\n                var groupNodes = new Dictionary<string, TreeViewItem>();\n                var childNodes = new Dictionary<TreeViewItem, List<TreeViewItem>>();\n                var inheritedNodeWeights = new Dictionary<TreeViewItem, int>();\n\n                rootNode = new AddCurvesPopupObjectNode(null, string.Empty, string.Empty);\n\n                TreeViewItem groupNode = rootNode;\n\n                groupNodes.Add(string.Empty, (rootNode));\n                childNodes.Add(groupNode, new List<TreeViewItem>());\n                inheritedNodeWeights.Add(groupNode, 0);\n\n                string currentPath = string.Empty;\n                foreach (var kvp in m_AccumulatedBindings)\n                {\n                    if (!currentPath.Equals(kvp.Key.path))\n                    {\n                        TreeViewItem parentNode = rootNode;\n                        var parentPath = GetParentPath(kvp.Key.path);\n\n                        while (parentPath != null)\n                        {\n                            if (groupNodes.TryGetValue(parentPath, out var node))\n                            {\n                                parentNode = node;\n                                break;\n                            }\n\n                            parentPath = GetParentPath(parentPath);\n                        }\n\n                        groupNode = new AddCurvesPopupObjectNode(parentNode, kvp.Key.path, \"\", GetObjectName(kvp.Key.path));\n                        groupNodes.Add(kvp.Key.path, groupNode);\n                        childNodes.Add(groupNode, new List<TreeViewItem>());\n                        inheritedNodeWeights.Add(groupNode, 0);\n\n                        childNodes[parentNode].Add(groupNode);\n\n                        currentPath = kvp.Key.path;\n                    }\n\n                    var bindings = kvp.Value;\n                    RemoveUnnecessaryBindings(bindings);\n\n                    if (bindings.Count > 0)\n                    {\n                        // Builtin GameObject attributes.\n                        if (kvp.Key.type == typeof(GameObject))\n                        {\n                            TreeViewItem newNode = CreateNode(bindings.ToArray(), groupNode, null);\n                            if (newNode != null)\n                                childNodes[groupNode].Add(newNode);\n                        }\n                        else\n                        {\n                            childNodes[groupNode].Add(AddAnimatableObjectToHierarchy(bindings, groupNode, kvp.Key.path));\n\n                            var parentGroupNode = groupNode;\n                            while (parentGroupNode != null)\n                            {\n                                inheritedNodeWeights[parentGroupNode] += bindings.Count;\n                                parentGroupNode = parentGroupNode.parent;\n                            }\n                        }\n                    }\n                }\n\n                // Remove empty leaves from tree view.\n                foreach (var kvp in inheritedNodeWeights)\n                {\n                    // Remove Leaves nodes without properties.\n                    if (inheritedNodeWeights[kvp.Key] == 0 && kvp.Key.parent != null)\n                    {\n                        childNodes[kvp.Key.parent].Remove(kvp.Key);\n                        kvp.Key.parent = null;\n                    }\n                }\n\n                // Set child parent references.\n                foreach (var kvp in childNodes)\n                {\n                    TreeViewUtility.SetChildParentReferences(kvp.Value, kvp.Key);\n                }\n            }\n\n            m_AccumulatedBindings.Clear();\n\n            return rootNode;\n        }\n\n        private string GetParentPath(string path)\n        {\n            if (String.IsNullOrEmpty(path))\n                return null;\n\n            int index = path.LastIndexOf('/');\n            if (index == -1)\n                return string.Empty;\n\n            return path.Substring(0, index);\n        }\n\n        private string GetObjectName(string path)\n        {\n            if (String.IsNullOrEmpty(path))\n                return null;\n\n            int index = path.LastIndexOf('/');\n            if (index == -1)\n                return path;\n\n            return path.Substring(index + 1);\n        }\n\n        private string GetClassName(EditorCurveBinding binding)\n        {\n            if (m_State.activeRootGameObject != null)\n            {\n                Object target = AnimationUtility.GetAnimatedObject(m_State.activeRootGameObject, binding);\n                if (target != null)\n                    return ObjectNames.GetInspectorTitle(target);\n            }\n\n            return binding.type.Name;\n        }\n\n        private Texture2D GetIcon(EditorCurveBinding binding)\n        {\n            return AssetPreview.GetMiniTypeThumbnail(binding.type);\n        }\n\n        private TreeViewItem AddAnimatableObjectToHierarchy(List<EditorCurveBinding> curveBindings, TreeViewItem parentNode, string path)\n        {\n            TreeViewItem node = new AddCurvesPopupObjectNode(parentNode, path, GetClassName(curveBindings[0]));\n            node.icon = GetIcon(curveBindings[0]);\n\n            List<TreeViewItem> childNodes = new List<TreeViewItem>();\n            List<EditorCurveBinding> singlePropertyBindings = new List<EditorCurveBinding>();\n            SerializedObject so = null;\n\n            for (int i = 0; i < curveBindings.Count; i++)\n            {\n                EditorCurveBinding curveBinding = curveBindings[i];\n                if (m_State.activeRootGameObject && curveBinding.isSerializeReferenceCurve)\n                {\n                    var animatedObject = AnimationUtility.GetAnimatedObject(m_State.activeRootGameObject, curveBinding);\n                    if (animatedObject != null && (so == null || so.targetObject != animatedObject))\n                        so = new SerializedObject(animatedObject);\n                }\n\n                singlePropertyBindings.Add(curveBinding);\n\n                // We expect curveBindings to come sorted by propertyname\n                if (i == curveBindings.Count - 1 || AnimationWindowUtility.GetPropertyGroupName(curveBindings[i + 1].propertyName) != AnimationWindowUtility.GetPropertyGroupName(curveBinding.propertyName))\n                {\n                    TreeViewItem newNode = CreateNode(singlePropertyBindings.ToArray(), node, so);\n                    if (newNode != null)\n                        childNodes.Add(newNode);\n                    singlePropertyBindings.Clear();\n                }\n            }\n\n            childNodes.Sort();\n\n            TreeViewUtility.SetChildParentReferences(childNodes, node);\n            return node;\n        }\n\n        private TreeViewItem CreateNode(EditorCurveBinding[] curveBindings, TreeViewItem parentNode, SerializedObject so)\n        {\n            var node = new AddCurvesPopupPropertyNode(parentNode, curveBindings, AnimationWindowUtility.GetNicePropertyGroupDisplayName(curveBindings[0], so));\n            node.icon = parentNode.icon;\n            return node;\n        }\n    }\n\n    class AddCurvesPopupObjectNode : TreeViewItem\n    {\n        public AddCurvesPopupObjectNode(TreeViewItem parent, string path, string className, string displayName = null)\n            : base((path + className).GetHashCode(), parent != null ? parent.depth + 1 : -1, parent, displayName ?? className)\n        {\n        }\n    }\n\n    class AddCurvesPopupPropertyNode : TreeViewItem\n    {\n        public EditorCurveBinding[] curveBindings;\n\n        public AddCurvesPopupPropertyNode(TreeViewItem parent, EditorCurveBinding[] curveBindings, string displayName)\n            : base(curveBindings[0].GetHashCode(), parent.depth + 1, parent, displayName)\n        {\n            this.curveBindings = curveBindings;\n        }\n\n        public override int CompareTo(TreeViewItem other)\n        {\n            AddCurvesPopupPropertyNode otherNode = other as AddCurvesPopupPropertyNode;\n            if (otherNode != null)\n            {\n                if (displayName.Contains(\"Rotation\") && otherNode.displayName.Contains(\"Position\"))\n                    return 1;\n                if (displayName.Contains(\"Position\") && otherNode.displayName.Contains(\"Rotation\"))\n                    return -1;\n            }\n            return base.CompareTo(other);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEditor.IMGUI.Controls;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewDataSource = UnityEditor.IMGUI.Controls.TreeViewDataSource<int>;\n\nnamespace UnityEditorInternal\n{\n    class AddCurvesPopupHierarchyDataSource : TreeViewDataSource\n    {\n        public AddCurvesPopupHierarchyDataSource(TreeViewController treeView)\n            : base(treeView)\n        {\n            showRootItem = false;\n            rootIsCollapsable = false;\n        }\n\n        private void SetupRootNodeSettings()\n        {\n            showRootItem = false;\n            SetExpanded(root, true);\n        }\n\n        public override void FetchData()\n        {\n            m_RootItem = null;\n            if (AddCurvesPopup.s_State.selection.canAddCurves)\n            {\n                var state = AddCurvesPopup.s_State;\n                AddBindingsToHierarchy(state.controlInterface.GetAnimatableBindings());\n            }\n\n            SetupRootNodeSettings();\n            m_NeedRefreshRows = true;\n        }\n\n        private void AddBindingsToHierarchy(EditorCurveBinding[] bindings)\n        {\n            if (bindings == null || bindings.Length == 0)\n            {\n                m_RootItem = new AddCurvesPopupObjectNode(null, \"\", \"\");\n                return;\n            }\n\n            var builder = new AddCurvesPopupHierarchyBuilder(AddCurvesPopup.s_State);\n            for (int i = 0; i < bindings.Length; i++)\n            {\n                builder.Add(bindings[i]);\n            }\n\n            m_RootItem = builder.CreateTreeView();\n        }\n\n        public void UpdateData()\n        {\n            m_TreeView.ReloadData();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditor.ShortcutManagement;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewGUI = UnityEditor.IMGUI.Controls.TreeViewGUI<int>;\n\nnamespace UnityEditorInternal\n{\n    internal class AddCurvesPopupHierarchyGUI : TreeViewGUI\n    {\n        public EditorWindow owner;\n        public bool showPlusButton { get; set; }\n        private GUIStyle buttonStyle = \"IconButton\";\n        private GUIContent plusIcon = EditorGUIUtility.TrIconContent(\"Toolbar Plus\");\n        private GUIStyle plusButtonBackgroundStyle = \"Tag MenuItem\";\n        private GUIContent addPropertiesContent = EditorGUIUtility.TrTextContent(\"Add Properties\");\n        private const float plusButtonWidth = 17;\n\n        public AddCurvesPopupHierarchyGUI(TreeViewController treeView, EditorWindow owner)\n            : base(treeView, true)\n        {\n            this.owner = owner;\n        }\n\n        public override void OnRowGUI(Rect rowRect, TreeViewItem node, int row, bool selected, bool focused)\n        {\n            base.OnRowGUI(rowRect, node, row, selected, focused);\n            DoAddCurveButton(rowRect, node);\n            HandleContextMenu(rowRect, node);\n        }\n\n        private void DoAddCurveButton(Rect rowRect, TreeViewItem node)\n        {\n            // Is it propertynode. If not, then we don't need plusButton so quit here\n            AddCurvesPopupPropertyNode hierarchyNode = node as AddCurvesPopupPropertyNode;\n            if (hierarchyNode == null || hierarchyNode.curveBindings == null || hierarchyNode.curveBindings.Length == 0)\n                return;\n\n            Rect buttonRect = new Rect(rowRect.width - plusButtonWidth, rowRect.yMin, plusButtonWidth, buttonStyle.fixedHeight);\n\n            // TODO Make a style for add curves popup\n            // Draw background behind plus button to prevent text overlapping\n            GUI.Box(buttonRect, GUIContent.none, plusButtonBackgroundStyle);\n\n            // Check if the curve already exists and remove plus button\n            if (GUI.Button(buttonRect, plusIcon, buttonStyle))\n            {\n                AddCurvesPopup.AddNewCurve(hierarchyNode);\n\n                // Hold shift key to add new curves and keep window opened.\n                if (Event.current.shift)\n                    m_TreeView.ReloadData();\n                else\n                    owner.Close();\n            }\n        }\n\n        private void HandleContextMenu(Rect rowRect, TreeViewItem node)\n        {\n            if (Event.current.type != EventType.ContextClick)\n                return;\n\n            if (rowRect.Contains(Event.current.mousePosition))\n            {\n                // Add current node to selection\n                var ids = new List<int>(m_TreeView.GetSelection());\n                ids.Add(node.id);\n                m_TreeView.SetSelection(ids.ToArray(), false, false);\n\n                GenerateMenu().ShowAsContext();\n                Event.current.Use();\n            }\n        }\n\n        private GenericMenu GenerateMenu()\n        {\n            GenericMenu menu = new GenericMenu();\n            menu.AddItem(addPropertiesContent, false, AddPropertiesFromSelectedNodes);\n\n            return menu;\n        }\n\n        private void AddPropertiesFromSelectedNodes()\n        {\n            int[] ids = m_TreeView.GetSelection();\n            for (int i = 0; i < ids.Length; ++i)\n            {\n                var node = m_TreeView.FindItem(ids[i]);\n                var propertyNode = node as AddCurvesPopupPropertyNode;\n\n                if (propertyNode != null)\n                {\n                    AddCurvesPopup.AddNewCurve(propertyNode);\n                }\n                else if (node.hasChildren)\n                {\n                    foreach (var childNode in node.children)\n                    {\n                        var childPropertyNode = childNode as AddCurvesPopupPropertyNode;\n                        if (childPropertyNode != null)\n                        {\n                            AddCurvesPopup.AddNewCurve(childPropertyNode);\n                        }\n                    }\n                }\n            }\n\n            m_TreeView.ReloadData();\n        }\n\n        public float GetContentWidth()\n        {\n            IList<TreeViewItem> rows = m_TreeView.data.GetRows();\n            List<TreeViewItem> allRows = new List<TreeViewItem>();\n            allRows.AddRange(rows);\n\n            for (int i = 0; i < allRows.Count; ++i)\n            {\n                var row = allRows[i];\n                if (row.hasChildren)\n                    allRows.AddRange(row.children);\n            }\n\n            float rowWidth = GetMaxWidth(allRows);\n            return rowWidth + plusButtonWidth;\n        }\n\n        override protected void SyncFakeItem()\n        {\n            //base.SyncFakeItem();\n        }\n\n        override protected void RenameEnded()\n        {\n            //base.RenameEnded();\n        }\n\n        override protected bool IsRenaming(int id)\n        {\n            return false;\n        }\n\n        public override bool BeginRename(TreeViewItem item, float delay)\n        {\n            return false;\n        }\n\n        override protected Texture GetIconForItem(TreeViewItem item)\n        {\n            if (item != null)\n                return item.icon;\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditor.ShortcutManagement;\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    internal enum WrapModeFixed\n    {\n        Default = (int)WrapMode.Default,\n        Once = (int)WrapMode.Once,\n        Loop = (int)WrapMode.Loop,\n        ClampForever = (int)WrapMode.ClampForever,\n        PingPong = (int)WrapMode.PingPong\n    }\n\n    [Serializable]\n    class AnimEditor : ScriptableObject\n    {\n        // Active Animation windows\n        private static List<AnimEditor> s_AnimationWindows = new List<AnimEditor>();\n        public static List<AnimEditor> GetAllAnimationWindows() { return s_AnimationWindows; }\n        public bool stateDisabled { get { return m_State.disabled; } }\n\n        [SerializeField] private SplitterState m_HorizontalSplitter;\n        [SerializeReference] private AnimationWindowState m_State;\n        [SerializeReference] private DopeSheetEditor m_DopeSheet;\n        [SerializeReference] private CurveEditor m_CurveEditor;\n        [SerializeField] private AnimationWindowHierarchy m_Hierarchy;\n        [SerializeField] private AnimationWindowClipPopup m_ClipPopup;\n        [SerializeField] private AnimationEventTimeLine m_Events;\n        [SerializeField] private AnimEditorOverlay m_Overlay;\n        [SerializeField] private EditorWindow m_OwnerWindow;\n\n        [System.NonSerialized] private Rect m_Position;\n        [System.NonSerialized] private bool m_TriggerFraming;\n        [System.NonSerialized] private bool m_Initialized;\n\n        private float hierarchyWidth { get { return m_HorizontalSplitter.realSizes[0]; } }\n        private float contentWidth { get { return m_HorizontalSplitter.realSizes[1]; } }\n\n        internal static PrefColor kEulerXColor = new PrefColor(\"Animation/EulerX\", 1.0f, 0.0f, 1.0f, 1.0f);\n        internal static PrefColor kEulerYColor = new PrefColor(\"Animation/EulerY\", 1.0f, 1.0f, 0.0f, 1.0f);\n        internal static PrefColor kEulerZColor = new PrefColor(\"Animation/EulerZ\", 0.0f, 1.0f, 1.0f, 1.0f);\n\n        static private Color s_SelectionRangeColorLight = new Color32(255, 255, 255, 90);\n        static private Color s_SelectionRangeColorDark = new Color32(200, 200, 200, 40);\n\n        static private Color selectionRangeColor\n        {\n            get\n            {\n                return EditorGUIUtility.isProSkin ? s_SelectionRangeColorDark : s_SelectionRangeColorLight;\n            }\n        }\n\n        static private Color s_OutOfRangeColorLight = new Color32(160, 160, 160, 127);\n        static private Color s_OutOfRangeColorDark = new Color32(40, 40, 40, 127);\n\n        static private Color outOfRangeColor\n        {\n            get\n            {\n                return EditorGUIUtility.isProSkin ? s_OutOfRangeColorDark : s_OutOfRangeColorLight;\n            }\n        }\n\n        static private Color s_InRangeColorLight = new Color32(211, 211, 211, 255);\n        static private Color s_InRangeColorDark =  new Color32(75, 75, 75, 255);\n\n        static private Color inRangeColor\n        {\n            get\n            {\n                return EditorGUIUtility.isProSkin ? s_InRangeColorDark : s_InRangeColorLight;\n            }\n        }\n\n        static private Color s_FilterBySelectionColorLight = new Color(0.82f, 0.97f, 1.00f, 1.00f);\n        static private Color s_FilterBySelectionColorDark = new Color(0.54f, 0.85f, 1.00f, 1.00f);\n\n        static private Color filterBySelectionColor\n        {\n            get\n            {\n                return EditorGUIUtility.isProSkin ? s_FilterBySelectionColorDark : s_FilterBySelectionColorLight;\n            }\n        }\n\n        internal const int kSliderThickness = 13;\n        internal const int kIntFieldWidth = 35;\n        internal const int kHierarchyMinWidth = 300;\n        internal const int kToggleButtonWidth = 80;\n        internal const float kDisabledRulerAlpha = 0.12f;\n\n        private int layoutRowHeight\n        {\n            get { return (int)EditorGUI.kWindowToolbarHeight; }\n        }\n\n        internal struct FrameRateMenuEntry\n        {\n            public FrameRateMenuEntry(GUIContent content, float value)\n            {\n                this.content = content;\n                this.value = value;\n            }\n\n            public GUIContent content;\n            public float value;\n        }\n\n        internal static FrameRateMenuEntry[] kAvailableFrameRates = new FrameRateMenuEntry[]\n        {\n            new FrameRateMenuEntry(EditorGUIUtility.TextContent(\"Set Sample Rate/24\"), 24f),\n            new FrameRateMenuEntry(EditorGUIUtility.TextContent(\"Set Sample Rate/25\"), 25f),\n            new FrameRateMenuEntry(EditorGUIUtility.TextContent(\"Set Sample Rate/30\"), 30f),\n            new FrameRateMenuEntry(EditorGUIUtility.TextContent(\"Set Sample Rate/50\"), 50f),\n            new FrameRateMenuEntry(EditorGUIUtility.TextContent(\"Set Sample Rate/60\"), 60f)\n        };\n\n        public AnimationWindowState state { get { return m_State; } }\n\n        public AnimationWindowSelectionItem selection\n        {\n            get\n            {\n                return m_State.selection;\n            }\n\n            set\n            {\n                m_State.selection = value;\n            }\n        }\n\n        public IAnimationWindowController controlInterface\n        {\n            get\n            {\n                return state.controlInterface;\n            }\n        }\n\n        public IAnimationWindowController overrideControlInterface\n        {\n            get\n            {\n                return state.overrideControlInterface;\n            }\n\n            set\n            {\n                state.overrideControlInterface = value;\n            }\n        }\n\n        private bool triggerFraming\n        {\n            set\n            {\n                m_TriggerFraming = value;\n            }\n\n            get\n            {\n                return m_TriggerFraming;\n            }\n        }\n\n        internal CurveEditor curveEditor { get { return m_CurveEditor; } }\n        internal DopeSheetEditor dopeSheetEditor { get { return m_DopeSheet; } }\n\n        public void OnAnimEditorGUI(EditorWindow parent, Rect position)\n        {\n            m_DopeSheet.m_Owner = parent;\n            m_OwnerWindow = parent;\n            m_Position = position;\n\n            if (!m_Initialized)\n                Initialize();\n\n            m_State.OnGUI();\n\n            if (m_State.disabled && m_State.recording)\n                m_State.recording = false;\n\n            SynchronizeLayout();\n\n            using (new EditorGUI.DisabledScope(m_State.disabled || m_State.animatorIsOptimized))\n            {\n                int optionsID = GUIUtility.GetControlID(FocusType.Passive);\n                if (Event.current.type != EventType.Repaint)\n                    OptionsOnGUI(optionsID);\n\n                OverlayEventOnGUI();\n\n                GUILayout.BeginHorizontal();\n                SplitterGUILayout.BeginHorizontalSplit(m_HorizontalSplitter);\n\n                // Left side\n                GUILayout.BeginVertical();\n\n                // First row of controls\n                GUILayout.BeginHorizontal(AnimationWindowStyles.animPlayToolBar);\n                PlayControlsOnGUI();\n                GUILayout.EndHorizontal();\n\n                // Second row of controls\n                GUILayout.BeginHorizontal(AnimationWindowStyles.animClipToolBar);\n                LinkOptionsOnGUI();\n                ClipSelectionDropDownOnGUI();\n                GUILayout.FlexibleSpace();\n                FrameRateInputFieldOnGUI();\n                FilterBySelectionButtonOnGUI();\n                AddKeyframeButtonOnGUI();\n                AddEventButtonOnGUI();\n                GUILayout.EndHorizontal();\n\n                HierarchyOnGUI();\n\n                // Bottom row of controls\n                using (new GUILayout.HorizontalScope(AnimationWindowStyles.toolbarBottom))\n                {\n                    TabSelectionOnGUI();\n                }\n\n                GUILayout.EndVertical();\n\n                // Right side\n                GUILayout.BeginVertical();\n\n                // Acquire Rects\n                Rect timerulerRect = GUILayoutUtility.GetRect(contentWidth, layoutRowHeight);\n                Rect eventsRect = GUILayoutUtility.GetRect(contentWidth, layoutRowHeight - 1);\n                Rect contentLayoutRect = GUILayoutUtility.GetRect(contentWidth, contentWidth, 0f, float.MaxValue, GUILayout.ExpandHeight(true));\n\n                // MainContent must be done first since it resizes the Zoomable area.\n                MainContentOnGUI(contentLayoutRect);\n                TimeRulerOnGUI(timerulerRect);\n                EventLineOnGUI(eventsRect);\n                GUILayout.EndVertical();\n\n                SplitterGUILayout.EndHorizontalSplit();\n                GUILayout.EndHorizontal();\n\n                // Overlay\n                OverlayOnGUI(contentLayoutRect);\n\n                if (Event.current.type == EventType.Repaint)\n                {\n                    OptionsOnGUI(optionsID);\n                    AnimationWindowStyles.separator.Draw(new Rect(hierarchyWidth, 0, 1, position.height), false, false, false, false);\n                }\n\n                RenderEventTooltip();\n            }\n        }\n\n        void MainContentOnGUI(Rect contentLayoutRect)\n        {\n            //  Bail out if the hierarchy in animator is optimized.\n            if (m_State.animatorIsOptimized)\n            {\n                GUI.Label(contentLayoutRect, GUIContent.none, AnimationWindowStyles.dopeSheetBackground);\n\n                Vector2 textSize = GUI.skin.label.CalcSize(AnimationWindowStyles.animatorOptimizedText);\n                Rect labelRect = new Rect(contentLayoutRect.x + contentLayoutRect.width * .5f - textSize.x * .5f, contentLayoutRect.y + contentLayoutRect.height * .5f - textSize.y * .5f, textSize.x, textSize.y);\n                GUI.Label(labelRect, AnimationWindowStyles.animatorOptimizedText);\n                return;\n            }\n\n            var mainAreaControlID = 0;\n            if (m_State.disabled)\n            {\n                SetupWizardOnGUI(contentLayoutRect);\n            }\n            else\n            {\n                Event evt = Event.current;\n                if (evt.type == EventType.MouseDown && contentLayoutRect.Contains(evt.mousePosition))\n                    m_Events.ClearSelection();\n\n                if (triggerFraming && evt.type == EventType.Repaint)\n                {\n                    m_DopeSheet.FrameClip();\n                    m_CurveEditor.FrameClip(true, true);\n\n                    triggerFraming = false;\n                }\n\n                if (m_State.showCurveEditor)\n                {\n                    CurveEditorOnGUI(contentLayoutRect);\n                    mainAreaControlID = m_CurveEditor.areaControlID;\n                }\n                else\n                {\n                    DopeSheetOnGUI(contentLayoutRect);\n                    mainAreaControlID = m_DopeSheet.areaControlID;\n                }\n            }\n\n            HandleMainAreaCopyPaste(mainAreaControlID);\n        }\n\n        private void OverlayEventOnGUI()\n        {\n            if (m_State.animatorIsOptimized)\n                return;\n\n            if (m_State.disabled)\n                return;\n\n            Rect overlayRect = new Rect(hierarchyWidth - 1, 0f, contentWidth - kSliderThickness, m_Position.height - kSliderThickness);\n\n            GUI.BeginGroup(overlayRect);\n            m_Overlay.HandleEvents();\n            GUI.EndGroup();\n        }\n\n        private void OverlayOnGUI(Rect contentRect)\n        {\n            if (m_State.animatorIsOptimized)\n                return;\n\n            if (m_State.disabled)\n                return;\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            Rect contentRectNoSliders = new Rect(contentRect.xMin, contentRect.yMin, contentRect.width - kSliderThickness, contentRect.height - kSliderThickness);\n            Rect overlayRectNoSliders = new Rect(hierarchyWidth - 1, 0f, contentWidth - kSliderThickness, m_Position.height - kSliderThickness);\n\n            GUI.BeginGroup(overlayRectNoSliders);\n\n            Rect localRect = new Rect(0, 0, overlayRectNoSliders.width, overlayRectNoSliders.height);\n\n            Rect localContentRect = contentRectNoSliders;\n            localContentRect.position -= overlayRectNoSliders.min;\n\n            m_Overlay.OnGUI(localRect, localContentRect);\n\n            GUI.EndGroup();\n        }\n\n        public void Update()\n        {\n            if (m_State == null)\n                return;\n\n            PlaybackUpdate();\n        }\n\n        public void OnEnable()\n        {\n            s_AnimationWindows.Add(this);\n\n            if (m_State == null)\n            {\n                m_State = new AnimationWindowState();\n                m_State.animEditor = this;\n\n                InitializeHorizontalSplitter();\n                InitializeClipSelection();\n                InitializeDopeSheet();\n                InitializeEvents();\n                InitializeCurveEditor();\n                InitializeOverlay();\n            }\n\n            InitializeNonserializedValues();\n\n            m_State.timeArea = m_State.showCurveEditor ? (TimeArea)m_CurveEditor : m_DopeSheet;\n            m_DopeSheet.state = m_State;\n            m_ClipPopup.state = m_State;\n            m_Overlay.state = m_State;\n\n            m_State.OnEnable();\n\n            m_CurveEditor.curvesUpdated += SaveChangedCurvesFromCurveEditor;\n            m_CurveEditor.OnEnable();\n        }\n\n        public void OnDisable()\n        {\n            s_AnimationWindows.Remove(this);\n\n            if (m_CurveEditor != null)\n            {\n                m_CurveEditor.curvesUpdated -= SaveChangedCurvesFromCurveEditor;\n                m_CurveEditor.OnDisable();\n            }\n\n            m_DopeSheet?.OnDisable();\n            m_State.OnDisable();\n        }\n\n        public void OnDestroy()\n        {\n            m_CurveEditor?.OnDestroy();\n            m_State?.OnDestroy();\n        }\n\n        public void OnSelectionChanged()\n        {\n            triggerFraming = true; // Framing of clip can only be done after Layout. Here we just order it to happen later on.\n            Repaint();\n        }\n\n        public void OnSelectionUpdated()\n        {\n            m_State.OnSelectionUpdated();\n            Repaint();\n        }\n\n        public void OnStartLiveEdit()\n        {\n            SaveCurveEditorKeySelection();\n        }\n\n        public void OnEndLiveEdit()\n        {\n            UpdateSelectedKeysToCurveEditor();\n            m_State.ResampleAnimation();\n        }\n\n        public void OnLostFocus()\n        {\n            // RenameOverlay might still be active, close before switching to another window.\n            if (m_Hierarchy != null)\n                m_Hierarchy.EndNameEditing(true);\n\n            // Stop text editing.  FrameRate ui or Frame ui may still be in edition mode.\n            EditorGUI.EndEditingActiveTextField();\n        }\n\n        private void PlaybackUpdate()\n        {\n            if (m_State.disabled && m_State.playing)\n                m_State.playing = false;\n\n            if (m_State.PlaybackUpdate())\n                Repaint();\n        }\n\n        private void SetupWizardOnGUI(Rect position)\n        {\n            GUI.Label(position, GUIContent.none, AnimationWindowStyles.dopeSheetBackground);\n\n            Rect positionWithoutScrollBar = new Rect(position.x, position.y, position.width - kSliderThickness, position.height - kSliderThickness);\n            GUI.BeginClip(positionWithoutScrollBar);\n            GUI.enabled = true;\n\n            m_State.showCurveEditor = false;\n            m_State.timeArea = m_DopeSheet;\n            m_State.timeArea.SetShownHRangeInsideMargins(0f, 1f);\n\n            bool animatableObject = m_State.activeGameObject && !EditorUtility.IsPersistent(m_State.activeGameObject);\n\n            if (animatableObject)\n            {\n                var missingObjects = (!m_State.activeRootGameObject && !m_State.activeAnimationClip) ? AnimationWindowStyles.animatorAndAnimationClip.text : AnimationWindowStyles.animationClip.text;\n\n                string txt = String.Format(AnimationWindowStyles.formatIsMissing.text, m_State.activeGameObject.name, missingObjects);\n\n                const float buttonWidth = 70f;\n                const float buttonHeight = 20f;\n                const float buttonPadding = 3f;\n\n                GUIContent textContent = GUIContent.Temp(txt);\n                Vector2 textSize = GUI.skin.label.CalcSize(textContent);\n                Rect labelRect = new Rect(positionWithoutScrollBar.width * .5f - textSize.x * .5f, positionWithoutScrollBar.height * .5f - textSize.y * .5f, textSize.x, textSize.y);\n                GUI.Label(labelRect, textContent);\n\n                Rect buttonRect = new Rect(positionWithoutScrollBar.width * .5f - buttonWidth * .5f, labelRect.yMax + buttonPadding, buttonWidth, buttonHeight);\n\n                if (GUI.Button(buttonRect, AnimationWindowStyles.create))\n                {\n                    if (AnimationWindowUtility.InitializeGameobjectForAnimation(m_State.activeGameObject))\n                    {\n                        Component animationPlayer = AnimationWindowUtility.GetClosestAnimationPlayerComponentInParents(m_State.activeGameObject.transform);\n                        m_State.activeAnimationClip = AnimationUtility.GetAnimationClips(animationPlayer.gameObject)[0];\n                    }\n\n                    //  Layout has changed, bail out now.\n                    EditorGUIUtility.ExitGUI();\n                }\n            }\n            else\n            {\n                Color oldColor = GUI.color;\n                GUI.color = Color.gray;\n                Vector2 textSize = GUI.skin.label.CalcSize(AnimationWindowStyles.noAnimatableObjectSelectedText);\n                Rect labelRect = new Rect(positionWithoutScrollBar.width * .5f - textSize.x * .5f, positionWithoutScrollBar.height * .5f - textSize.y * .5f, textSize.x, textSize.y);\n                GUI.Label(labelRect, AnimationWindowStyles.noAnimatableObjectSelectedText);\n                GUI.color = oldColor;\n            }\n            GUI.EndClip();\n            GUI.enabled = false; // Reset state to false. It's always false originally for SetupWizardOnGUI.\n        }\n\n        private void EventLineOnGUI(Rect eventsRect)\n        {\n            eventsRect.width -= kSliderThickness;\n            GUI.Label(eventsRect, GUIContent.none, AnimationWindowStyles.eventBackground);\n\n            using (new EditorGUI.DisabledScope(!selection.animationIsEditable))\n            {\n                m_Events.EventLineGUI(eventsRect, m_State);\n            }\n        }\n\n        private void RenderEventTooltip()\n        {\n            m_Events.DrawInstantTooltip(m_Position);\n        }\n\n        private void TabSelectionOnGUI()\n        {\n            GUILayout.FlexibleSpace();\n            EditorGUI.BeginChangeCheck();\n            GUILayout.Toggle(!m_State.showCurveEditor, AnimationWindowStyles.dopesheet, AnimationWindowStyles.miniToolbarButton, GUILayout.Width(kToggleButtonWidth));\n            GUILayout.Toggle(m_State.showCurveEditor, AnimationWindowStyles.curves, EditorStyles.toolbarButtonRight, GUILayout.Width(kToggleButtonWidth));\n            if (EditorGUI.EndChangeCheck())\n            {\n                SwitchBetweenCurvesAndDopesheet();\n            }\n        }\n\n        private void HierarchyOnGUI()\n        {\n            Rect hierarchyLayoutRect = GUILayoutUtility.GetRect(hierarchyWidth, hierarchyWidth, 0f, float.MaxValue, GUILayout.ExpandHeight(true));\n\n            if (!m_State.showReadOnly && !m_State.selection.animationIsEditable)\n            {\n                Vector2 labelSize = GUI.skin.label.CalcSize(AnimationWindowStyles.readOnlyPropertiesLabel);\n\n                const float buttonWidth = 210f;\n                const float buttonHeight = 20f;\n                const float buttonPadding = 3f;\n\n                Rect labelRect = new Rect(hierarchyLayoutRect.x + hierarchyLayoutRect.width * .5f - labelSize.x * .5f, hierarchyLayoutRect.y + hierarchyLayoutRect.height * .5f - labelSize.y, labelSize.x, labelSize.y);\n\n                Rect buttonRect = new Rect(hierarchyLayoutRect.x + hierarchyLayoutRect.width * .5f - buttonWidth * .5f, labelRect.yMax + buttonPadding, buttonWidth, buttonHeight);\n\n                GUI.Label(labelRect, AnimationWindowStyles.readOnlyPropertiesLabel);\n                if (GUI.Button(buttonRect, AnimationWindowStyles.readOnlyPropertiesButton))\n                {\n                    m_State.showReadOnly = true;\n\n                    //  Layout has changed, bail out now.\n                    EditorGUIUtility.ExitGUI();\n                }\n\n                return;\n            }\n\n            if (!m_State.disabled)\n                m_Hierarchy.OnGUI(hierarchyLayoutRect);\n        }\n\n        private void FrameRateInputFieldOnGUI()\n        {\n            if (!m_State.showFrameRate)\n                return;\n\n            using (new EditorGUI.DisabledScope(!selection.animationIsEditable))\n            {\n                GUILayout.Label(AnimationWindowStyles.samples, EditorStyles.toolbarLabel);\n\n                EditorGUI.BeginChangeCheck();\n                int clipFrameRate = EditorGUILayout.DelayedIntField((int)m_State.clipFrameRate, EditorStyles.toolbarTextField, GUILayout.Width(kIntFieldWidth));\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_State.clipFrameRate = clipFrameRate;\n                    UpdateSelectedKeysToCurveEditor();\n                }\n            }\n        }\n\n        private void ClipSelectionDropDownOnGUI()\n        {\n            m_ClipPopup.OnGUI();\n        }\n\n        private void DopeSheetOnGUI(Rect position)\n        {\n            Rect noVerticalSliderRect = new Rect(position.xMin, position.yMin, position.width - kSliderThickness, position.height);\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                m_DopeSheet.rect = noVerticalSliderRect;\n                m_DopeSheet.SetTickMarkerRanges();\n                m_DopeSheet.RecalculateBounds();\n            }\n\n            if (m_State.showCurveEditor)\n                return;\n\n            Rect noSlidersRect = new Rect(position.xMin, position.yMin, position.width - kSliderThickness, position.height - kSliderThickness);\n\n            m_DopeSheet.BeginViewGUI();\n\n            GUI.Label(position, GUIContent.none, AnimationWindowStyles.dopeSheetBackground);\n\n            if (!m_State.disabled)\n            {\n                m_DopeSheet.TimeRuler(noSlidersRect, m_State.frameRate, false, true, kDisabledRulerAlpha, m_State.timeFormat);  // grid\n            }\n            m_DopeSheet.OnGUI(noSlidersRect, m_State.hierarchyState.scrollPos * -1);\n\n            m_DopeSheet.EndViewGUI();\n\n            Rect verticalScrollBarPosition = new Rect(noVerticalSliderRect.xMax, noVerticalSliderRect.yMin, kSliderThickness, noSlidersRect.height);\n\n            float visibleHeight = m_Hierarchy.GetTotalRect().height;\n            float contentHeight = Mathf.Max(visibleHeight, m_Hierarchy.GetContentSize().y);\n\n            m_State.hierarchyState.scrollPos.y = GUI.VerticalScrollbar(verticalScrollBarPosition, m_State.hierarchyState.scrollPos.y, visibleHeight, 0f, contentHeight);\n\n            if (m_DopeSheet.spritePreviewLoading == true)\n                Repaint();\n        }\n\n        private void CurveEditorOnGUI(Rect position)\n        {\n            if (Event.current.type == EventType.Repaint)\n            {\n                m_CurveEditor.rect = position;\n                m_CurveEditor.SetTickMarkerRanges();\n            }\n\n            Rect noSlidersRect = new Rect(position.xMin, position.yMin, position.width - kSliderThickness, position.height - kSliderThickness);\n\n            m_CurveEditor.vSlider = m_State.showCurveEditor;\n            m_CurveEditor.hSlider = m_State.showCurveEditor;\n\n            // Sync animation curves in curve editor.  Do it only once per frame.\n            if (Event.current.type == EventType.Layout)\n                UpdateCurveEditorData();\n\n            m_CurveEditor.BeginViewGUI();\n\n            if (!m_State.disabled)\n            {\n                GUI.Box(noSlidersRect, GUIContent.none, AnimationWindowStyles.curveEditorBackground);\n                m_CurveEditor.GridGUI();\n            }\n\n            EditorGUI.BeginChangeCheck();\n            m_CurveEditor.CurveGUI();\n            if (EditorGUI.EndChangeCheck())\n            {\n                SaveChangedCurvesFromCurveEditor();\n            }\n            m_CurveEditor.EndViewGUI();\n        }\n\n        private void TimeRulerOnGUI(Rect timeRulerRect)\n        {\n            Rect timeRulerRectNoScrollbar = new Rect(timeRulerRect.xMin, timeRulerRect.yMin, timeRulerRect.width - kSliderThickness, timeRulerRect.height);\n            Rect timeRulerBackgroundRect = timeRulerRectNoScrollbar;\n\n            GUI.Box(timeRulerBackgroundRect, GUIContent.none, AnimationWindowStyles.timeRulerBackground);\n\n            if (!m_State.disabled)\n            {\n                RenderInRangeOverlay(timeRulerRectNoScrollbar);\n                RenderSelectionOverlay(timeRulerRectNoScrollbar);\n            }\n\n            m_State.timeArea.TimeRuler(timeRulerRectNoScrollbar, m_State.frameRate, true, false, 1f, m_State.timeFormat);\n\n            if (!m_State.disabled)\n                RenderOutOfRangeOverlay(timeRulerRectNoScrollbar);\n        }\n\n        private GenericMenu GenerateOptionsMenu()\n        {\n            GenericMenu menu = new GenericMenu();\n\n            menu.AddItem(EditorGUIUtility.TextContent(\"Seconds\"), m_State.timeFormat == TimeArea.TimeFormat.TimeFrame, () => m_State.timeFormat = TimeArea.TimeFormat.TimeFrame);\n            menu.AddItem(EditorGUIUtility.TextContent(\"Frames\"), m_State.timeFormat == TimeArea.TimeFormat.Frame, () => m_State.timeFormat = TimeArea.TimeFormat.Frame);\n\n            menu.AddSeparator(\"\");\n\n            menu.AddItem(EditorGUIUtility.TextContent(\"Ripple\"), m_State.rippleTime, () => m_State.rippleTime = !m_State.rippleTime);\n\n            menu.AddSeparator(\"\");\n\n            menu.AddItem(EditorGUIUtility.TextContent(\"Show Sample Rate\"), m_State.showFrameRate, () => m_State.showFrameRate = !m_State.showFrameRate);\n\n            bool isAnimatable = selection != null && selection.animationIsEditable;\n\n            GenericMenu.MenuFunction2 nullMenuFunction2 = null;\n\n            for (int i = 0; i < kAvailableFrameRates.Length; ++i)\n            {\n                FrameRateMenuEntry entry = kAvailableFrameRates[i];\n\n                bool isActive = m_State.clipFrameRate.Equals(entry.value);\n                menu.AddItem(entry.content, isActive, isAnimatable ? SetFrameRate : nullMenuFunction2, entry.value);\n            }\n\n            menu.AddSeparator(\"\");\n\n            menu.AddItem(EditorGUIUtility.TextContent(\"Show Read-only Properties\"), m_State.showReadOnly, () => m_State.showReadOnly = !m_State.showReadOnly);\n\n            return menu;\n        }\n\n        private void OptionsOnGUI(int controlID)\n        {\n            Rect layoutRect = new Rect(hierarchyWidth, 0f, contentWidth, layoutRowHeight);\n\n            GUI.BeginGroup(layoutRect);\n\n            Vector2 optionsSize = EditorStyles.toolbarButtonRight.CalcSize(AnimationWindowStyles.optionsContent);\n            Rect optionsRect = new Rect(layoutRect.width - kSliderThickness, 0f, optionsSize.x, optionsSize.y);\n            GUI.Box(optionsRect, GUIContent.none, AnimationWindowStyles.animPlayToolBar);\n            if (EditorGUI.DropdownButton(controlID, optionsRect, AnimationWindowStyles.optionsContent, AnimationWindowStyles.optionsButton))\n            {\n                var menu = GenerateOptionsMenu();\n                menu.ShowAsContext();\n            }\n\n            GUI.EndGroup();\n        }\n\n        internal void SetFrameRate(object frameRate)\n        {\n            m_State.clipFrameRate = (float)frameRate;\n            UpdateSelectedKeysToCurveEditor();\n        }\n\n        private void FilterBySelectionButtonOnGUI()\n        {\n            Color backupColor = GUI.color;\n\n            if (m_State.filterBySelection)\n            {\n                Color selectionColor = filterBySelectionColor;\n                selectionColor.a *= GUI.color.a;\n                GUI.color = selectionColor;\n            }\n\n            EditorGUI.BeginChangeCheck();\n            bool filterBySelection = GUILayout.Toggle(m_State.filterBySelection, AnimationWindowStyles.filterBySelectionContent, EditorStyles.toolbarButton);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_State.filterBySelection = filterBySelection;\n            }\n\n            GUI.color = backupColor;\n        }\n\n        private void AddEventButtonOnGUI()\n        {\n            using (new EditorGUI.DisabledScope(!selection.animationIsEditable))\n            {\n                if (GUILayout.Button(AnimationWindowStyles.addEventContent, AnimationWindowStyles.animClipToolbarButton))\n                    m_Events.AddEvent(m_State.currentTime, selection.rootGameObject, selection.animationClip);\n            }\n        }\n\n        private void AddKeyframeButtonOnGUI()\n        {\n            bool canAddKey = selection.animationIsEditable && m_State.filteredCurves.Count != 0;\n            using (new EditorGUI.DisabledScope(!canAddKey))\n            {\n                if (GUILayout.Button(AnimationWindowStyles.addKeyframeContent, AnimationWindowStyles.animClipToolbarButton))\n                {\n                    SaveCurveEditorKeySelection();\n                    var keyTime = AnimationKeyTime.Time(m_State.currentTime, m_State.frameRate);\n                    AnimationWindowUtility.AddSelectedKeyframes(m_State, keyTime);\n                    UpdateSelectedKeysToCurveEditor();\n\n                    // data is scheduled for an update, bail out now to avoid using out of date data.\n                    EditorGUIUtility.ExitGUI();\n                }\n            }\n        }\n\n        private void PlayControlsOnGUI()\n        {\n            using (new EditorGUI.DisabledScope(!m_State.canPreview))\n            {\n                PreviewButtonOnGUI();\n            }\n\n            using (new EditorGUI.DisabledScope(!m_State.canRecord))\n            {\n                RecordButtonOnGUI();\n            }\n\n            if (GUILayout.Button(AnimationWindowStyles.firstKeyContent, EditorStyles.toolbarButton))\n            {\n                state.GoToFirstKeyframe();\n\n                // Stop text editing.  User may be editing frame navigation ui which will not update until we exit text editing.\n                EditorGUI.EndEditingActiveTextField();\n            }\n\n            if (GUILayout.Button(AnimationWindowStyles.prevKeyContent, EditorStyles.toolbarButton))\n            {\n                state.GoToPreviousKeyframe();\n\n                // Stop text editing.  User may be editing frame navigation ui which will not update until we exit text editing.\n                EditorGUI.EndEditingActiveTextField();\n            }\n\n            using (new EditorGUI.DisabledScope(!m_State.canPlay))\n            {\n                PlayButtonOnGUI();\n            }\n\n            if (GUILayout.Button(AnimationWindowStyles.nextKeyContent, EditorStyles.toolbarButton))\n            {\n                state.GoToNextKeyframe();\n\n                // Stop text editing.  User may be editing frame navigation ui which will not update until we exit text editing.\n                EditorGUI.EndEditingActiveTextField();\n            }\n\n            if (GUILayout.Button(AnimationWindowStyles.lastKeyContent, EditorStyles.toolbarButton))\n            {\n                state.GoToLastKeyframe();\n\n                // Stop text editing.  User may be editing frame navigation ui which will not update until we exit text editing.\n                EditorGUI.EndEditingActiveTextField();\n            }\n\n            GUILayout.FlexibleSpace();\n\n            EditorGUI.BeginChangeCheck();\n            int newFrame = EditorGUILayout.DelayedIntField(m_State.currentFrame, EditorStyles.toolbarTextField, GUILayout.Width(kIntFieldWidth));\n            if (EditorGUI.EndChangeCheck())\n            {\n                state.currentFrame = newFrame;\n            }\n        }\n\n        private void LinkOptionsOnGUI()\n        {\n            if (m_State.linkedWithSequencer)\n            {\n                if (GUILayout.Toggle(true, AnimationWindowStyles.sequencerLinkContent, EditorStyles.toolbarButton) == false)\n                {\n                    m_State.linkedWithSequencer = false;\n                    m_State.selection = null;\n                    m_State.overrideControlInterface = null;\n\n                    // Layout has changed, bail out now.\n                    EditorGUIUtility.ExitGUI();\n                }\n            }\n        }\n\n        static void ExecuteShortcut(ShortcutArguments args, Action<AnimEditor> exp)\n        {\n            var animationWindow = (AnimationWindow)args.context;\n            var animEditor = animationWindow.animEditor;\n\n            if (EditorWindow.focusedWindow != animationWindow)\n                return;\n\n            if (animEditor.stateDisabled || animEditor.state.animatorIsOptimized)\n                return;\n\n            exp(animEditor);\n\n            animEditor.Repaint();\n        }\n\n        static void ExecuteShortcut(ShortcutArguments args, Action<AnimationWindowState> exp)\n        {\n            ExecuteShortcut(args, animEditor => exp(animEditor.state));\n        }\n\n        [FormerlyPrefKeyAs(\"Animation/Show Curves\", \"c\")]\n        [Shortcut(\"Animation/Show Curves\", typeof(AnimationWindow), KeyCode.C)]\n        static void ShowCurves(ShortcutArguments args)\n        {\n            ExecuteShortcut(args, animEditor => { animEditor.SwitchBetweenCurvesAndDopesheet(); });\n        }\n\n        [FormerlyPrefKeyAs(\"Animation/Play Animation\", \" \")]\n        [Shortcut(\"Animation/Play Animation\", typeof(AnimationWindow), KeyCode.Space)]\n        static void TogglePlayAnimation(ShortcutArguments args)\n        {\n            ExecuteShortcut(args, state =>\n            {\n                state.playing = !state.playing;\n            });\n        }\n\n        [FormerlyPrefKeyAs(\"Animation/Next Frame\", \".\")]\n        [Shortcut(\"Animation/Next Frame\", typeof(AnimationWindow), KeyCode.Period)]\n        static void NextFrame(ShortcutArguments args)\n        {\n            ExecuteShortcut(args, state => state.GoToNextFrame());\n        }\n\n        [FormerlyPrefKeyAs(\"Animation/Previous Frame\", \",\")]\n        [Shortcut(\"Animation/Previous Frame\", typeof(AnimationWindow), KeyCode.Comma)]\n        static void PreviousFrame(ShortcutArguments args)\n        {\n            ExecuteShortcut(args, state => state.GoToPreviousFrame());\n        }\n\n        [FormerlyPrefKeyAs(\"Animation/Previous Keyframe\", \"&,\")]\n        [Shortcut(\"Animation/Previous Keyframe\", typeof(AnimationWindow), KeyCode.Comma, ShortcutModifiers.Alt)]\n        static void PreviousKeyFrame(ShortcutArguments args)\n        {\n            ExecuteShortcut(args, state => state.GoToPreviousKeyframe());\n        }\n\n        [FormerlyPrefKeyAs(\"Animation/Next Keyframe\", \"&.\")]\n        [Shortcut(\"Animation/Next Keyframe\", typeof(AnimationWindow), KeyCode.Period, ShortcutModifiers.Alt)]\n        static void NextKeyFrame(ShortcutArguments args)\n        {\n            ExecuteShortcut(args, state => state.GoToNextKeyframe());\n        }\n\n        [FormerlyPrefKeyAs(\"Animation/First Keyframe\", \"#,\")]\n        [Shortcut(\"Animation/First Keyframe\", typeof(AnimationWindow), KeyCode.Comma, ShortcutModifiers.Shift)]\n        static void FirstKeyFrame(ShortcutArguments args)\n        {\n            ExecuteShortcut(args, state => state.GoToFirstKeyframe());\n        }\n\n        [FormerlyPrefKeyAs(\"Animation/Last Keyframe\", \"#.\")]\n        [Shortcut(\"Animation/Last Keyframe\", typeof(AnimationWindow), KeyCode.Period, ShortcutModifiers.Shift)]\n        static void LastKeyFrame(ShortcutArguments args)\n        {\n            ExecuteShortcut(args, state => state.GoToLastKeyframe());\n        }\n\n        [FormerlyPrefKeyAs(\"Animation/Key Selected\", \"k\")]\n        [Shortcut(\"Animation/Key Selected\", null, KeyCode.K)]\n        static void KeySelected(ShortcutArguments args)\n        {\n            AnimationWindow animationWindow = AnimationWindow.GetAllAnimationWindows().Find(aw => (aw.state.previewing || aw == EditorWindow.focusedWindow));\n            if (animationWindow == null)\n                return;\n\n            var animEditor = animationWindow.animEditor;\n\n            animEditor.SaveCurveEditorKeySelection();\n            AnimationWindowUtility.AddSelectedKeyframes(animEditor.m_State, AnimationKeyTime.Frame(animEditor.state.currentFrame, animEditor.state.frameRate));\n            animEditor.state.ClearCandidates();\n            animEditor.UpdateSelectedKeysToCurveEditor();\n\n            animEditor.Repaint();\n        }\n\n        [FormerlyPrefKeyAs(\"Animation/Key Modified\", \"#k\")]\n        [Shortcut(\"Animation/Key Modified\", null, KeyCode.K, ShortcutModifiers.Shift)]\n        static void KeyModified(ShortcutArguments args)\n        {\n            AnimationWindow animationWindow = AnimationWindow.GetAllAnimationWindows().Find(aw => (aw.state.previewing || aw == EditorWindow.focusedWindow));\n            if (animationWindow == null)\n                return;\n\n            var animEditor = animationWindow.animEditor;\n\n            animEditor.SaveCurveEditorKeySelection();\n            animEditor.state.ProcessCandidates();\n            animEditor.UpdateSelectedKeysToCurveEditor();\n\n            animEditor.Repaint();\n        }\n\n        [Shortcut(\"Animation/Toggle Ripple\", typeof(AnimationWindow), KeyCode.Alpha2, ShortcutModifiers.Shift)]\n        static void ToggleRipple(ShortcutArguments args)\n        {\n            ExecuteShortcut(args, animEditor => { animEditor.state.rippleTime = !animEditor.state.rippleTime; });\n        }\n\n        [ClutchShortcut(\"Animation/Ripple (Clutch)\", typeof(AnimationWindow), KeyCode.Alpha2)]\n        static void ClutchRipple(ShortcutArguments args)\n        {\n            ExecuteShortcut(args, animEditor => { animEditor.state.rippleTimeClutch = args.stage == ShortcutStage.Begin; });\n        }\n\n        [Shortcut(\"Animation/Frame All\", typeof(AnimationWindow), KeyCode.A)]\n        static void FrameAll(ShortcutArguments args)\n        {\n            ExecuteShortcut(args, animEditor => { animEditor.triggerFraming = true; });\n        }\n\n        private void PlayButtonOnGUI()\n        {\n            EditorGUI.BeginChangeCheck();\n            bool playbackEnabled = GUILayout.Toggle(m_State.playing, AnimationWindowStyles.playContent, EditorStyles.toolbarButton);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_State.playing = playbackEnabled;\n\n                // Stop text editing.  User may be editing frame navigation ui which will not update until we exit text editing.\n                EditorGUI.EndEditingActiveTextField();\n            }\n        }\n\n        private void PreviewButtonOnGUI()\n        {\n            EditorGUI.BeginChangeCheck();\n\n            bool recordingEnabled = GUILayout.Toggle(m_State.previewing, AnimationWindowStyles.previewContent, EditorStyles.toolbarButton);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_State.previewing = recordingEnabled;\n            }\n        }\n\n        private void RecordButtonOnGUI()\n        {\n            EditorGUI.BeginChangeCheck();\n\n            Color backupColor = GUI.color;\n            if (m_State.recording)\n            {\n                Color recordedColor = AnimationMode.recordedPropertyColor;\n                recordedColor.a *= GUI.color.a;\n                GUI.color = recordedColor;\n            }\n\n            bool recordingEnabled = GUILayout.Toggle(m_State.recording, AnimationWindowStyles.recordContent, EditorStyles.toolbarButton);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_State.recording = recordingEnabled;\n\n                if (!recordingEnabled)\n                {\n                    // Force refresh in inspector as stopping recording does not invalidate any data.\n                    InspectorWindow.RepaintAllInspectors();\n                }\n            }\n\n            GUI.color = backupColor;\n        }\n\n        private void SwitchBetweenCurvesAndDopesheet()\n        {\n            if (!m_State.showCurveEditor)\n            {\n                SwitchToCurveEditor();\n            }\n            else\n            {\n                SwitchToDopeSheetEditor();\n            }\n        }\n\n        internal void SwitchToCurveEditor()\n        {\n            m_State.showCurveEditor = true;\n\n            UpdateSelectedKeysToCurveEditor();\n            AnimationWindowUtility.SyncTimeArea(m_DopeSheet, m_CurveEditor);\n            m_State.timeArea = m_CurveEditor;\n        }\n\n        internal void SwitchToDopeSheetEditor()\n        {\n            m_State.showCurveEditor = false;\n\n            UpdateSelectedKeysFromCurveEditor();\n            AnimationWindowUtility.SyncTimeArea(m_CurveEditor, m_DopeSheet);\n            m_State.timeArea = m_DopeSheet;\n        }\n\n        private void RenderSelectionOverlay(Rect rect)\n        {\n            if (m_State.showCurveEditor && !m_CurveEditor.hasSelection)\n                return;\n\n            if (!m_State.showCurveEditor && m_State.selectedKeys.Count == 0)\n                return;\n\n            const int kOverlayMinWidth = 14;\n\n            Bounds bounds = m_State.showCurveEditor ? m_CurveEditor.selectionBounds : m_State.selectionBounds;\n\n            float startPixel = m_State.TimeToPixel(bounds.min.x) + rect.xMin;\n            float endPixel = m_State.TimeToPixel(bounds.max.x) + rect.xMin;\n\n            if ((endPixel - startPixel) < kOverlayMinWidth)\n            {\n                float centerPixel = (startPixel + endPixel) * 0.5f;\n\n                startPixel = centerPixel - kOverlayMinWidth * 0.5f;\n                endPixel = centerPixel + kOverlayMinWidth * 0.5f;\n            }\n\n            AnimationWindowUtility.DrawSelectionOverlay(rect, selectionRangeColor, startPixel, endPixel);\n        }\n\n        private void RenderInRangeOverlay(Rect rect)\n        {\n            Color color = inRangeColor;\n\n            if (m_State.recording)\n                color *= AnimationMode.recordedPropertyColor;\n            else if (m_State.previewing)\n                color *= AnimationMode.animatedPropertyColor;\n            else\n                color = Color.clear;\n\n            Vector2 timeRange = m_State.timeRange;\n            AnimationWindowUtility.DrawInRangeOverlay(rect, color, m_State.TimeToPixel(timeRange.x) + rect.xMin, m_State.TimeToPixel(timeRange.y) + rect.xMin);\n        }\n\n        private void RenderOutOfRangeOverlay(Rect rect)\n        {\n            Color color = outOfRangeColor;\n\n            if (m_State.recording)\n                color *= AnimationMode.recordedPropertyColor;\n            else if (m_State.previewing)\n                color *= AnimationMode.animatedPropertyColor;\n\n            Vector2 timeRange = m_State.timeRange;\n            AnimationWindowUtility.DrawOutOfRangeOverlay(rect, color, m_State.TimeToPixel(timeRange.x) + rect.xMin, m_State.TimeToPixel(timeRange.y) + rect.xMin);\n        }\n\n        private void SynchronizeLayout()\n        {\n            m_HorizontalSplitter.realSizes[1] = (int)Mathf.Max(Mathf.Min(m_Position.width - m_HorizontalSplitter.realSizes[0], m_HorizontalSplitter.realSizes[1]), 0);\n\n            // Synchronize frame rate\n            if (selection.animationClip != null)\n            {\n                m_State.frameRate = selection.animationClip.frameRate;\n            }\n            else\n            {\n                m_State.frameRate = AnimationWindowState.kDefaultFrameRate;\n            }\n        }\n\n        struct ChangedCurvesPerClip\n        {\n            public List<EditorCurveBinding> bindings;\n            public List<AnimationCurve> curves;\n        }\n\n        // Curve editor changes curves, but we are in charge of saving them into the clip\n        private void SaveChangedCurvesFromCurveEditor()\n        {\n            m_State.SaveKeySelection(AnimationWindowState.kEditCurveUndoLabel);\n\n            var curvesToUpdate = new Dictionary<AnimationClip, ChangedCurvesPerClip>();\n            var changedCurves = new ChangedCurvesPerClip();\n\n            for (int i = 0; i < m_CurveEditor.animationCurves.Length; ++i)\n            {\n                CurveWrapper curveWrapper = m_CurveEditor.animationCurves[i];\n                if (curveWrapper.changed)\n                {\n                    if (!curveWrapper.animationIsEditable)\n                        Debug.LogError(\"Curve is not editable and shouldn't be saved.\");\n\n                    if (curveWrapper.animationClip != null)\n                    {\n                        if (curvesToUpdate.TryGetValue(curveWrapper.animationClip, out changedCurves))\n                        {\n                            changedCurves.bindings.Add(curveWrapper.binding);\n                            changedCurves.curves.Add(curveWrapper.curve.length > 0 ? curveWrapper.curve : null);\n                        }\n                        else\n                        {\n                            changedCurves.bindings = new List<EditorCurveBinding>();\n                            changedCurves.curves = new List<AnimationCurve>();\n\n                            changedCurves.bindings.Add(curveWrapper.binding);\n                            changedCurves.curves.Add(curveWrapper.curve.length > 0 ? curveWrapper.curve : null);\n\n                            curvesToUpdate.Add(curveWrapper.animationClip, changedCurves);\n                        }\n                    }\n\n                    curveWrapper.changed = false;\n                }\n            }\n\n            if (curvesToUpdate.Count > 0)\n            {\n                foreach (var kvp in curvesToUpdate)\n                {\n                    Undo.RegisterCompleteObjectUndo(kvp.Key, AnimationWindowState.kEditCurveUndoLabel);\n                    AnimationWindowUtility.SaveCurves(kvp.Key, kvp.Value.bindings, kvp.Value.curves);\n                }\n\n                m_State.ResampleAnimation();\n            }\n        }\n\n        // We sync keyframe selection from curve editor to AnimationWindowState\n        private void UpdateSelectedKeysFromCurveEditor()\n        {\n            m_State.ClearKeySelections();\n            foreach (CurveSelection curveSelection in m_CurveEditor.selectedCurves)\n            {\n                AnimationWindowKeyframe keyFrame = AnimationWindowUtility.CurveSelectionToAnimationWindowKeyframe(curveSelection, m_State.filteredCurves);\n                if (keyFrame != null)\n                    m_State.SelectKey(keyFrame);\n            }\n        }\n\n        // We sync keyframe selection from AnimationWindowState to curve editor\n        private void UpdateSelectedKeysToCurveEditor()\n        {\n            UpdateCurveEditorData();\n\n            m_CurveEditor.ClearSelection();\n            m_CurveEditor.BeginRangeSelection();\n            foreach (AnimationWindowKeyframe keyframe in m_State.selectedKeys)\n            {\n                CurveSelection curveSelection = AnimationWindowUtility.AnimationWindowKeyframeToCurveSelection(keyframe, m_CurveEditor);\n                if (curveSelection != null)\n                    m_CurveEditor.AddSelection(curveSelection);\n            }\n            m_CurveEditor.EndRangeSelection();\n        }\n\n        private void SaveCurveEditorKeySelection()\n        {\n            // Synchronize current selection in curve editor and save selection snapshot in undo redo.\n            if (m_State.showCurveEditor)\n                UpdateSelectedKeysFromCurveEditor();\n            else\n                UpdateSelectedKeysToCurveEditor();\n\n            m_CurveEditor.SaveKeySelection(AnimationWindowState.kEditCurveUndoLabel);\n        }\n\n        public void BeginKeyModification()\n        {\n            SaveCurveEditorKeySelection();\n\n            m_State.SaveKeySelection(AnimationWindowState.kEditCurveUndoLabel);\n            m_State.ClearKeySelections();\n        }\n\n        public void EndKeyModification()\n        {\n            UpdateSelectedKeysToCurveEditor();\n        }\n\n        void HandleMainAreaCopyPaste(int controlID)\n        {\n            var evt = Event.current;\n            var type = evt.GetTypeForControl(controlID);\n            if (type != EventType.ValidateCommand && type != EventType.ExecuteCommand)\n                return;\n\n            if (evt.commandName == EventCommandNames.Copy)\n            {\n                // If events timeline has selected events right now then bail out; copying of\n                // these will get processed later by AnimationEventTimeLine.\n                if (m_Events.HasSelectedEvents)\n                    return;\n\n                if (type == EventType.ExecuteCommand)\n                {\n                    if (m_State.showCurveEditor)\n                        UpdateSelectedKeysFromCurveEditor();\n                    m_State.CopyKeys();\n                }\n                evt.Use();\n            }\n            else if (evt.commandName == EventCommandNames.Paste)\n            {\n                if (type == EventType.ExecuteCommand)\n                {\n                    // If clipboard contains events right now then paste those.\n                    if (AnimationWindowEventsClipboard.CanPaste())\n                    {\n                        m_Events.PasteEvents(m_State.activeRootGameObject, m_State.activeAnimationClip, m_State.currentTime);\n                    }\n                    else\n                    {\n                        SaveCurveEditorKeySelection();\n                        m_State.PasteKeys();\n                        UpdateSelectedKeysToCurveEditor();\n                    }\n\n                    // data is scheduled for an update, bail out now to avoid using out of date data.\n                    EditorGUIUtility.ExitGUI();\n                }\n                evt.Use();\n            }\n        }\n\n        internal void UpdateCurveEditorData()\n        {\n            m_CurveEditor.animationCurves = m_State.activeCurveWrappers;\n        }\n\n        public void Repaint()\n        {\n            if (m_OwnerWindow != null)\n                m_OwnerWindow.Repaint();\n        }\n\n        // Called just-in-time by OnGUI\n        private void Initialize()\n        {\n            AnimationWindowStyles.Initialize();\n            InitializeHierarchy();\n\n            m_CurveEditor.state = m_State;\n\n            // The rect here is only for initialization and will be overriden at layout\n            m_HorizontalSplitter.realSizes[0] = kHierarchyMinWidth;\n            m_HorizontalSplitter.realSizes[1] = (int)Mathf.Max(m_Position.width - kHierarchyMinWidth, kHierarchyMinWidth);\n            m_DopeSheet.rect = new Rect(0, 0, contentWidth, 100);\n\n            m_Initialized = true;\n        }\n\n        // Called once during initialization of m_State\n        private void InitializeClipSelection()\n        {\n            m_ClipPopup = new AnimationWindowClipPopup();\n        }\n\n        // Called once during initialization of m_State\n        private void InitializeHierarchy()\n        {\n            // The rect here is only for initialization and will be overriden at layout\n            m_Hierarchy = new AnimationWindowHierarchy(m_State, m_OwnerWindow, new Rect(0, 0, hierarchyWidth, 100));\n        }\n\n        // Called once during initialization of m_State\n        private void InitializeDopeSheet()\n        {\n            m_DopeSheet = new DopeSheetEditor(m_OwnerWindow);\n            m_DopeSheet.SetTickMarkerRanges();\n            m_DopeSheet.hSlider = true;\n            m_DopeSheet.shownArea = new Rect(1, 1, 1, 1);\n            // The rect here is only for initialization and will be overriden at layout\n            m_DopeSheet.rect = new Rect(0, 0, contentWidth, 100);\n            m_DopeSheet.hTicks.SetTickModulosForFrameRate(m_State.frameRate);\n        }\n\n        // Called once during initialization of m_State\n        private void InitializeEvents()\n        {\n            m_Events = new AnimationEventTimeLine(m_OwnerWindow);\n        }\n\n        // Called once during initialization of m_State\n        private void InitializeCurveEditor()\n        {\n            // The rect here is only for initialization and will be overriden at layout\n            m_CurveEditor = new CurveEditor(new Rect(0, 0, contentWidth, 100), new CurveWrapper[0], false);\n\n            CurveEditorSettings settings = new CurveEditorSettings();\n            settings.hTickStyle.distMin = 30; // min distance between vertical lines before they disappear completely\n            settings.hTickStyle.distFull = 80; // distance between vertical lines where they gain full strength\n            settings.hTickStyle.distLabel = 0; // min distance between vertical lines labels\n            if (EditorGUIUtility.isProSkin)\n            {\n                settings.vTickStyle.tickColor.color = new Color(1, 1, 1, settings.vTickStyle.tickColor.color.a);  // color and opacity of horizontal lines\n                settings.vTickStyle.labelColor.color = new Color(1, 1, 1, settings.vTickStyle.labelColor.color.a);  // color and opacity of horizontal line labels\n            }\n            settings.vTickStyle.distMin = 15; // min distance between horizontal lines before they disappear completely\n            settings.vTickStyle.distFull = 40; // distance between horizontal lines where they gain full strength\n            settings.vTickStyle.distLabel = 30; // min distance between horizontal lines labels\n            settings.vTickStyle.stubs = true;\n            settings.hRangeMin = 0;\n            settings.hRangeLocked = false;\n            settings.vRangeLocked = false;\n            settings.hSlider = true;\n            settings.vSlider = true;\n            settings.allowDeleteLastKeyInCurve = true;\n            settings.rectangleToolFlags = CurveEditorSettings.RectangleToolFlags.FullRectangleTool;\n            settings.undoRedoSelection = true;\n            settings.flushCurveCache = false; // Curve Wrappers are cached in AnimationWindowState.\n\n            m_CurveEditor.shownArea = new Rect(1, 1, 1, 1);\n            m_CurveEditor.settings = settings;\n            m_CurveEditor.state = m_State;\n        }\n\n        // Called once during initialization of m_State\n        private void InitializeHorizontalSplitter()\n        {\n            m_HorizontalSplitter = SplitterState.FromRelative(new float[] { kHierarchyMinWidth, kHierarchyMinWidth * 3 }, new float[] { kHierarchyMinWidth, kHierarchyMinWidth }, null);\n            m_HorizontalSplitter.realSizes[0] = kHierarchyMinWidth;\n            m_HorizontalSplitter.realSizes[1] = kHierarchyMinWidth;\n        }\n\n        // Called once during initialization of m_State\n        private void InitializeOverlay()\n        {\n            m_Overlay = new AnimEditorOverlay();\n        }\n\n        // Called during initialization, even when m_State already exists\n        private void InitializeNonserializedValues()\n        {\n            // Since CurveEditor doesn't know about AnimationWindowState, a delegate allows it to reflect frame rate changes\n            m_State.onFrameRateChange += delegate(float newFrameRate)\n            {\n                m_CurveEditor.invSnap = newFrameRate;\n                m_CurveEditor.hTicks.SetTickModulosForFrameRate(newFrameRate);\n            };\n\n            m_State.onStartLiveEdit += OnStartLiveEdit;\n            m_State.onEndLiveEdit += OnEndLiveEdit;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimEditorOverlay.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditorInternal\n{\n    [System.Serializable]\n    internal class AnimEditorOverlay\n    {\n        [SerializeReference] public AnimationWindowState state;\n\n        private TimeCursorManipulator m_PlayHeadCursor;\n\n        private Rect m_Rect;\n        private Rect m_ContentRect;\n\n        public Rect rect { get { return m_Rect; } }\n        public Rect contentRect { get { return m_ContentRect; } }\n\n        public void Initialize()\n        {\n            if (m_PlayHeadCursor == null)\n            {\n                m_PlayHeadCursor = new TimeCursorManipulator(AnimationWindowStyles.playHead);\n\n                m_PlayHeadCursor.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (evt.mousePosition.y <= (m_Rect.yMin + 20))\n                        return OnStartDragPlayHead(evt);\n\n                    return false;\n                };\n                m_PlayHeadCursor.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    return OnDragPlayHead(evt);\n                };\n                m_PlayHeadCursor.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    return OnEndDragPlayHead(evt);\n                };\n            }\n        }\n\n        public void OnGUI(Rect rect, Rect contentRect)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            m_Rect = rect;\n            m_ContentRect = contentRect;\n\n            Initialize();\n\n            m_PlayHeadCursor.OnGUI(m_Rect, m_Rect.xMin + TimeToPixel(state.currentTime));\n        }\n\n        public void HandleEvents()\n        {\n            Initialize();\n\n            m_PlayHeadCursor.HandleEvents();\n        }\n\n        private bool OnStartDragPlayHead(Event evt)\n        {\n            state.playing = false;\n\n            state.controlInterface.time = MousePositionToTime(evt);\n            return true;\n        }\n\n        private bool OnDragPlayHead(Event evt)\n        {\n            state.controlInterface.time = MousePositionToTime(evt);\n            return true;\n        }\n\n        private bool OnEndDragPlayHead(Event evt)\n        {\n            return true;\n        }\n\n        public float MousePositionToTime(Event evt)\n        {\n            float width = m_ContentRect.width;\n            float time = Mathf.Max(((evt.mousePosition.x / width) * state.visibleTimeSpan + state.minVisibleTime), 0);\n            time = state.SnapToFrame(time, AnimationWindowState.SnapMode.SnapToFrame);\n            return time;\n        }\n\n        public float MousePositionToValue(Event evt)\n        {\n            float height = m_ContentRect.height;\n            float valuePixel = height - evt.mousePosition.y;\n\n            TimeArea timeArea = state.timeArea;\n\n            float pixelPerValue = timeArea.m_Scale.y * -1f;\n            float zeroValuePixel = timeArea.shownArea.yMin * pixelPerValue * -1f;\n\n            float value = (valuePixel - zeroValuePixel) / pixelPerValue;\n\n            return value;\n        }\n\n        public float TimeToPixel(float time)\n        {\n            return state.TimeToPixel(time);\n        }\n\n        public float ValueToPixel(float value)\n        {\n            TimeArea timeArea = state.timeArea;\n\n            float pixelPerValue = timeArea.m_Scale.y * -1f;\n            float zeroValuePixel = timeArea.shownArea.yMin * pixelPerValue * -1f;\n\n            float pixelValue = value * pixelPerValue + zeroValuePixel;\n\n            return pixelValue;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationClipSelectionItem.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\n\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditorInternal\n{\n    [Serializable]\n    internal class AnimationClipSelectionItem : AnimationWindowSelectionItem\n    {\n        public static AnimationClipSelectionItem Create(AnimationClip animationClip, Object sourceObject = null)\n        {\n            var selectionItem = new AnimationClipSelectionItem\n            {\n                gameObject = sourceObject as GameObject,\n                scriptableObject = sourceObject as ScriptableObject,\n                animationClip = animationClip,\n                id = 0\n            };\n\n            return selectionItem;\n        }\n\n        public override bool canPreview { get { return false; } }\n\n        public override bool canRecord { get { return false; } }\n\n        public override bool canChangeAnimationClip { get { return false; } }\n\n        public override bool canSyncSceneSelection { get { return false; } }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationContextualPropertyMenu.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditorInternal\n{\n    class AnimationPropertyContextualMenu\n    {\n        public static AnimationPropertyContextualMenu Instance = new AnimationPropertyContextualMenu();\n\n        IAnimationContextualResponder m_Responder;\n\n        private static GUIContent addKeyContent = EditorGUIUtility.TrTextContent(\"Add Key\");\n        private static GUIContent updateKeyContent = EditorGUIUtility.TrTextContent(\"Update Key\");\n        private static GUIContent removeKeyContent = EditorGUIUtility.TrTextContent(\"Remove Key\");\n        private static GUIContent removeCurveContent = EditorGUIUtility.TrTextContent(\"Remove All Keys\");\n        private static GUIContent goToPreviousKeyContent = EditorGUIUtility.TrTextContent(\"Go to Previous Key\");\n        private static GUIContent goToNextKeyContent = EditorGUIUtility.TrTextContent(\"Go to Next Key\");\n        private static GUIContent addCandidatesContent = EditorGUIUtility.TrTextContent(\"Key All Modified\");\n        private static GUIContent addAnimatedContent = EditorGUIUtility.TrTextContent(\"Key All Animated\");\n\n        public AnimationPropertyContextualMenu()\n        {\n            EditorApplication.contextualPropertyMenu += OnPropertyContextMenu;\n            MaterialEditor.contextualPropertyMenu += OnPropertyContextMenu;\n        }\n\n        public void SetResponder(IAnimationContextualResponder responder)\n        {\n            m_Responder = responder;\n        }\n\n        public bool IsResponder(IAnimationContextualResponder responder)\n        {\n            return responder == m_Responder;\n        }\n\n        void OnPropertyContextMenu(GenericMenu menu, SerializedProperty property)\n        {\n            if (m_Responder == null)\n                return;\n\n            PropertyModification[] modifications = AnimationWindowUtility.SerializedPropertyToPropertyModifications(property);\n\n            bool isPropertyAnimatable = m_Responder.IsAnimatable(modifications);\n            if (isPropertyAnimatable)\n            {\n                var targetObject = property.serializedObject.targetObject;\n                if (m_Responder.IsEditable(targetObject))\n                    OnPropertyContextMenu(menu, modifications);\n                else\n                    OnDisabledPropertyContextMenu(menu);\n            }\n        }\n\n        void OnPropertyContextMenu(GenericMenu menu, MaterialProperty property, Renderer[] renderers)\n        {\n            if (m_Responder == null)\n                return;\n\n            if (property.targets == null || property.targets.Length == 0)\n                return;\n\n            if (renderers == null || renderers.Length == 0)\n                return;\n\n            var modifications = new List<PropertyModification>();\n            foreach (Renderer renderer in renderers)\n            {\n                modifications.AddRange(MaterialAnimationUtility.MaterialPropertyToPropertyModifications(property, renderer));\n            }\n\n            if (m_Responder.IsEditable(renderers[0]))\n                OnPropertyContextMenu(menu, modifications.ToArray());\n            else\n                OnDisabledPropertyContextMenu(menu);\n        }\n\n        void OnPropertyContextMenu(GenericMenu menu, PropertyModification[] modifications)\n        {\n            bool hasKey = m_Responder.KeyExists(modifications);\n            bool hasCandidate = m_Responder.CandidateExists(modifications);\n            bool hasCurve = (hasKey || m_Responder.CurveExists(modifications));\n\n            bool hasAnyCandidate = m_Responder.HasAnyCandidates();\n            bool hasAnyCurve = m_Responder.HasAnyCurves();\n\n            menu.AddItem(((hasKey && hasCandidate) ? updateKeyContent : addKeyContent), false, () =>\n            {\n                m_Responder.AddKey(modifications);\n            });\n\n            if (hasKey)\n            {\n                menu.AddItem(removeKeyContent, false, () =>\n                {\n                    m_Responder.RemoveKey(modifications);\n                });\n            }\n            else\n            {\n                menu.AddDisabledItem(removeKeyContent);\n            }\n\n            if (hasCurve)\n            {\n                menu.AddItem(removeCurveContent, false, () =>\n                {\n                    m_Responder.RemoveCurve(modifications);\n                });\n            }\n            else\n            {\n                menu.AddDisabledItem(removeCurveContent);\n            }\n\n            menu.AddSeparator(string.Empty);\n            if (hasAnyCandidate)\n            {\n                menu.AddItem(addCandidatesContent, false, () =>\n                {\n                    m_Responder.AddCandidateKeys();\n                });\n            }\n            else\n            {\n                menu.AddDisabledItem(addCandidatesContent);\n            }\n\n            if (hasAnyCurve)\n            {\n                menu.AddItem(addAnimatedContent, false, () =>\n                {\n                    m_Responder.AddAnimatedKeys();\n                });\n            }\n            else\n            {\n                menu.AddDisabledItem(addAnimatedContent);\n            }\n\n            menu.AddSeparator(string.Empty);\n            if (hasCurve)\n            {\n                menu.AddItem(goToPreviousKeyContent, false, () =>\n                {\n                    m_Responder.GoToPreviousKeyframe(modifications);\n                });\n                menu.AddItem(goToNextKeyContent, false, () =>\n                {\n                    m_Responder.GoToNextKeyframe(modifications);\n                });\n            }\n            else\n            {\n                menu.AddDisabledItem(goToPreviousKeyContent);\n                menu.AddDisabledItem(goToNextKeyContent);\n            }\n        }\n\n        void OnDisabledPropertyContextMenu(GenericMenu menu)\n        {\n            menu.AddDisabledItem(addKeyContent);\n            menu.AddDisabledItem(removeKeyContent);\n            menu.AddDisabledItem(removeCurveContent);\n            menu.AddSeparator(string.Empty);\n            menu.AddDisabledItem(addCandidatesContent);\n            menu.AddDisabledItem(addAnimatedContent);\n            menu.AddSeparator(string.Empty);\n            menu.AddDisabledItem(goToPreviousKeyContent);\n            menu.AddDisabledItem(goToNextKeyContent);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationKeyTime.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    [System.Serializable]\n    struct AnimationKeyTime\n    {\n        [SerializeField] private float  m_FrameRate;\n        [SerializeField] private int    m_Frame;\n        [SerializeField] private float  m_Time;\n\n        public float    time        { get { return m_Time; } }\n        public int      frame       { get { return m_Frame; } }\n        public float    frameRate   { get { return m_FrameRate; } }\n\n        /// <summary>\n        /// A frame has a range of time. This is the beginning of the frame.\n        /// </summary>\n        public float frameFloor\n        {\n            get\n            {\n                return ((float)frame - 0.5f) / frameRate;\n            }\n        }\n\n        /// <summary>\n        /// A frame has a range of time. This is the end of the frame.\n        /// </summary>\n        public float frameCeiling\n        {\n            get\n            {\n                return ((float)frame + 0.5f) / frameRate;\n            }\n        }\n\n        public float timeRound\n        {\n            get\n            {\n                return (float)frame / frameRate;\n            }\n        }\n\n        public static AnimationKeyTime  Time(float time, float frameRate)\n        {\n            AnimationKeyTime key = new AnimationKeyTime();\n            key.m_Time = Mathf.Max(time, 0f);\n            key.m_FrameRate = frameRate;\n            key.m_Frame = UnityEngine.Mathf.RoundToInt(key.m_Time * frameRate);\n            return key;\n        }\n\n        public static AnimationKeyTime Frame(int frame, float frameRate)\n        {\n            AnimationKeyTime key = new AnimationKeyTime();\n            key.m_Frame = (frame < 0) ? 0 : frame;\n            key.m_Time = key.m_Frame / frameRate;\n            key.m_FrameRate = frameRate;\n            return key;\n        }\n\n        // Check if a time in seconds overlaps with the frame\n        public bool ContainsTime(float time)\n        {\n            return time >= frameFloor && time < frameCeiling;\n        }\n\n        public bool Equals(AnimationKeyTime key)\n        {\n            return m_Frame == key.m_Frame &&\n                m_FrameRate == key.m_FrameRate &&\n                Mathf.Approximately(m_Time, key.m_Time);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditorInternal\n{\n    internal class AnimationRecording\n    {\n        const string kLocalPosition = \"m_LocalPosition\";\n        const string kLocalRotation = \"m_LocalRotation\";\n        const string kLocalScale = \"m_LocalScale\";\n        const string kLocalEulerAnglesHint = \"m_LocalEulerAnglesHint\";\n\n        static bool HasAnyRecordableModifications(GameObject root, UndoPropertyModification[] modifications)\n        {\n            for (int i = 0; i < modifications.Length; i++)\n            {\n                EditorCurveBinding tempBinding;\n                if (AnimationUtility.PropertyModificationToEditorCurveBinding(modifications[i].previousValue, root, out tempBinding) != null)\n                    return true;\n            }\n            return false;\n        }\n\n        static private UndoPropertyModification[] FilterModifications(IAnimationRecordingState state, ref UndoPropertyModification[] modifications)\n        {\n            GameObject rootGameObject = state.activeRootGameObject;\n\n            List<UndoPropertyModification> discardedModifications = new List<UndoPropertyModification>();\n            List<UndoPropertyModification> outModifications = new List<UndoPropertyModification>();\n            for (int i = 0; i < modifications.Length; ++i)\n            {\n                UndoPropertyModification modification = modifications[i];\n                PropertyModification prop = modification.previousValue;\n\n                if (state.DiscardModification(prop))\n                {\n                    discardedModifications.Add(modification);\n                    continue;\n                }\n\n                var binding = new EditorCurveBinding();\n                if (AnimationUtility.PropertyModificationToEditorCurveBinding(prop, rootGameObject, out binding) != null)\n                    outModifications.Add(modification);\n                else\n                    discardedModifications.Add(modification);\n            }\n\n            if (discardedModifications.Count > 0)\n                modifications = outModifications.ToArray();\n\n            return discardedModifications.ToArray();\n        }\n\n        internal class RotationModification\n        {\n            public UndoPropertyModification x;\n            public UndoPropertyModification y;\n            public UndoPropertyModification z;\n            public UndoPropertyModification w;\n\n            public UndoPropertyModification lastQuatModification;\n\n            public bool useEuler = false;\n            public UndoPropertyModification eulerX;\n            public UndoPropertyModification eulerY;\n            public UndoPropertyModification eulerZ;\n        }\n\n        static private void CollectRotationModifications(IAnimationRecordingState state, ref UndoPropertyModification[] modifications,\n            ref Dictionary<object, RotationModification> rotationModifications)\n        {\n            List<UndoPropertyModification> outModifs = new List<UndoPropertyModification>();\n            foreach (var modification in modifications)\n            {\n                PropertyModification prop = modification.previousValue;\n                if (!(prop.target is Transform))\n                {\n                    outModifs.Add(modification);\n                    continue;\n                }\n\n                EditorCurveBinding binding = new EditorCurveBinding();\n                AnimationUtility.PropertyModificationToEditorCurveBinding(prop, state.activeRootGameObject, out binding);\n                if (binding.propertyName.StartsWith(kLocalRotation))\n                {\n                    RotationModification rotationModification;\n\n                    if (!rotationModifications.TryGetValue(prop.target, out rotationModification))\n                    {\n                        rotationModification = new RotationModification();\n                        rotationModifications[prop.target] = rotationModification;\n                    }\n\n                    if (binding.propertyName.EndsWith(\"x\"))\n                        rotationModification.x = modification;\n                    else if (binding.propertyName.EndsWith(\"y\"))\n                        rotationModification.y = modification;\n                    else if (binding.propertyName.EndsWith(\"z\"))\n                        rotationModification.z = modification;\n                    else if (binding.propertyName.EndsWith(\"w\"))\n                        rotationModification.w = modification;\n\n                    rotationModification.lastQuatModification = modification;\n                }\n                else if (prop.propertyPath.StartsWith(kLocalEulerAnglesHint))\n                {\n                    RotationModification rotationModification;\n\n                    if (!rotationModifications.TryGetValue(prop.target, out rotationModification))\n                    {\n                        rotationModification = new RotationModification();\n                        rotationModifications[prop.target] = rotationModification;\n                    }\n\n                    rotationModification.useEuler = true;\n\n                    if (prop.propertyPath.EndsWith(\"x\"))\n                        rotationModification.eulerX = modification;\n                    else if (prop.propertyPath.EndsWith(\"y\"))\n                        rotationModification.eulerY = modification;\n                    else if (prop.propertyPath.EndsWith(\"z\"))\n                        rotationModification.eulerZ = modification;\n                }\n                else\n                {\n                    outModifs.Add(modification);\n                }\n            }\n\n            if (rotationModifications.Count > 0)\n            {\n                modifications = outModifs.ToArray();\n            }\n        }\n\n        static private void DiscardRotationModification(RotationModification rotationModification, ref List<UndoPropertyModification> discardedModifications)\n        {\n            if (rotationModification.x.currentValue != null)\n                discardedModifications.Add(rotationModification.x);\n            if (rotationModification.y.currentValue != null)\n                discardedModifications.Add(rotationModification.y);\n            if (rotationModification.z.currentValue != null)\n                discardedModifications.Add(rotationModification.z);\n            if (rotationModification.w.currentValue != null)\n                discardedModifications.Add(rotationModification.w);\n\n            if (rotationModification.eulerX.currentValue != null)\n                discardedModifications.Add(rotationModification.eulerX);\n            if (rotationModification.eulerY.currentValue != null)\n                discardedModifications.Add(rotationModification.eulerY);\n            if (rotationModification.eulerZ.currentValue != null)\n                discardedModifications.Add(rotationModification.eulerZ);\n        }\n\n        static private UndoPropertyModification[] FilterRotationModifications(IAnimationRecordingState state, ref Dictionary<object, RotationModification> rotationModifications)\n        {\n            GameObject rootGameObject = state.activeRootGameObject;\n\n            List<object> itemsToRemove = new List<object>();\n\n            List<UndoPropertyModification> discardedModifications = new List<UndoPropertyModification>();\n            foreach (KeyValuePair<object, RotationModification> item in rotationModifications)\n            {\n                RotationModification m = item.Value;\n\n                if (state.DiscardModification(m.lastQuatModification.currentValue))\n                {\n                    DiscardRotationModification(m, ref discardedModifications);\n                    itemsToRemove.Add(item.Key);\n                    continue;\n                }\n\n                EditorCurveBinding binding = new EditorCurveBinding();\n                Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.lastQuatModification.currentValue, rootGameObject, out binding);\n                if (type == null)\n                {\n                    DiscardRotationModification(m, ref discardedModifications);\n                    itemsToRemove.Add(item.Key);\n                }\n            }\n\n            foreach (var key in itemsToRemove)\n            {\n                rotationModifications.Remove(key);\n            }\n\n            return discardedModifications.ToArray();\n        }\n\n        static private void AddRotationPropertyModification(IAnimationRecordingState state, EditorCurveBinding baseBinding, UndoPropertyModification modification)\n        {\n            if (modification.previousValue == null)\n                return;\n\n            // case 817356. Reuse baseBinding as basis for rotation binding.\n            // This is needed to register valid bindings for m_LocalEulerAnglesHint\n            // that cannot be converted to EditorCurveBinding otherwise.\n            EditorCurveBinding binding = baseBinding;\n            binding.propertyName = modification.previousValue.propertyPath;\n\n            state.AddPropertyModification(binding, modification.previousValue, modification.keepPrefabOverride);\n        }\n\n        static private void ProcessRotationModifications(IAnimationRecordingState state, ref Dictionary<object, RotationModification> rotationModifications)\n        {\n            foreach (KeyValuePair<object, RotationModification> item in rotationModifications)\n            {\n                RotationModification m = item.Value;\n                Transform target = item.Key as Transform;\n\n                if (target == null)\n                    continue;\n\n                EditorCurveBinding binding = new EditorCurveBinding();\n                Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.lastQuatModification.currentValue, state.activeRootGameObject, out binding);\n                if (type == null)\n                    continue;\n\n                AddRotationPropertyModification(state, binding, m.x);\n                AddRotationPropertyModification(state, binding, m.y);\n                AddRotationPropertyModification(state, binding, m.z);\n                AddRotationPropertyModification(state, binding, m.w);\n\n                Quaternion previousValue = target.localRotation;\n                Quaternion currentValue = target.localRotation;\n\n                object x, y, z, w;\n                if (ValueFromPropertyModification(m.x.previousValue, binding, out x))\n                    previousValue.x = (float)x;\n                if (ValueFromPropertyModification(m.y.previousValue, binding, out y))\n                    previousValue.y = (float)y;\n                if (ValueFromPropertyModification(m.z.previousValue, binding, out z))\n                    previousValue.z = (float)z;\n                if (ValueFromPropertyModification(m.w.previousValue, binding, out w))\n                    previousValue.w = (float)w;\n\n                if (ValueFromPropertyModification(m.x.currentValue, binding, out x))\n                    currentValue.x = (float)x;\n                if (ValueFromPropertyModification(m.y.currentValue, binding, out y))\n                    currentValue.y = (float)y;\n                if (ValueFromPropertyModification(m.z.currentValue, binding, out z))\n                    currentValue.z = (float)z;\n                if (ValueFromPropertyModification(m.w.currentValue, binding, out w))\n                    currentValue.w = (float)w;\n\n                // Favour euler hints if one or more exist on any axis.\n                if (m.useEuler)\n                {\n                    AddRotationPropertyModification(state, binding, m.eulerX);\n                    AddRotationPropertyModification(state, binding, m.eulerY);\n                    AddRotationPropertyModification(state, binding, m.eulerZ);\n\n                    Vector3 previousEulerAngles = target.GetLocalEulerAngles(RotationOrder.OrderZXY);\n                    Vector3 currentEulerAngles = previousEulerAngles;\n\n                    object eulerX, eulerY, eulerZ;\n                    if (ValueFromPropertyModification(m.eulerX.previousValue, binding, out eulerX))\n                        previousEulerAngles.x = (float)eulerX;\n                    if (ValueFromPropertyModification(m.eulerY.previousValue, binding, out eulerY))\n                        previousEulerAngles.y = (float)eulerY;\n                    if (ValueFromPropertyModification(m.eulerZ.previousValue, binding, out eulerZ))\n                        previousEulerAngles.z = (float)eulerZ;\n\n                    if (ValueFromPropertyModification(m.eulerX.currentValue, binding, out eulerX))\n                        currentEulerAngles.x = (float)eulerX;\n                    if (ValueFromPropertyModification(m.eulerY.currentValue, binding, out eulerY))\n                        currentEulerAngles.y = (float)eulerY;\n                    if (ValueFromPropertyModification(m.eulerZ.currentValue, binding, out eulerZ))\n                        currentEulerAngles.z = (float)eulerZ;\n\n                    // Fallback to quaternion euler values if euler hint and quaternion are out of sync.\n                    previousEulerAngles = AnimationUtility.GetClosestEuler(previousValue, previousEulerAngles, RotationOrder.OrderZXY);\n                    currentEulerAngles = AnimationUtility.GetClosestEuler(currentValue, currentEulerAngles, RotationOrder.OrderZXY);\n\n                    AddRotationKey(state, binding, type, previousEulerAngles, currentEulerAngles);\n                }\n                else\n                {\n                    Vector3 eulerAngles = target.GetLocalEulerAngles(RotationOrder.OrderZXY);\n\n                    Vector3 previousEulerAngles = AnimationUtility.GetClosestEuler(previousValue, eulerAngles, RotationOrder.OrderZXY);\n                    Vector3 currentEulerAngles = AnimationUtility.GetClosestEuler(currentValue, eulerAngles, RotationOrder.OrderZXY);\n\n                    AddRotationKey(state, binding, type, previousEulerAngles, currentEulerAngles);\n                }\n            }\n        }\n\n        internal class Vector3Modification\n        {\n            public UndoPropertyModification x;\n            public UndoPropertyModification y;\n            public UndoPropertyModification z;\n\n            public UndoPropertyModification last;\n        }\n\n        static private void CollectVector3Modifications(IAnimationRecordingState state, ref UndoPropertyModification[] modifications,\n            ref Dictionary<object, Vector3Modification> vector3Modifications, string propertyName)\n        {\n            List<UndoPropertyModification> outModifs = new List<UndoPropertyModification>();\n            foreach (var modification in modifications)\n            {\n                PropertyModification prop = modification.previousValue;\n                if (!(prop.target is Transform))\n                {\n                    outModifs.Add(modification);\n                    continue;\n                }\n\n                EditorCurveBinding binding = new EditorCurveBinding();\n                AnimationUtility.PropertyModificationToEditorCurveBinding(prop, state.activeRootGameObject, out binding);\n                if (binding.propertyName.StartsWith(propertyName))\n                {\n                    Vector3Modification vector3Modification;\n\n                    if (!vector3Modifications.TryGetValue(prop.target, out vector3Modification))\n                    {\n                        vector3Modification = new Vector3Modification();\n                        vector3Modifications[prop.target] = vector3Modification;\n                    }\n\n                    if (binding.propertyName.EndsWith(\"x\"))\n                        vector3Modification.x = modification;\n                    else if (binding.propertyName.EndsWith(\"y\"))\n                        vector3Modification.y = modification;\n                    else if (binding.propertyName.EndsWith(\"z\"))\n                        vector3Modification.z = modification;\n\n                    vector3Modification.last = modification;\n                }\n                else\n                {\n                    outModifs.Add(modification);\n                }\n            }\n\n            if (vector3Modifications.Count > 0)\n            {\n                modifications = outModifs.ToArray();\n            }\n        }\n\n        static private void ProcessVector3Modification(IAnimationRecordingState state, EditorCurveBinding baseBinding, UndoPropertyModification modification, Transform target, string axis, float scale = 1.0f)\n        {\n            var binding = baseBinding;\n            binding.propertyName = binding.propertyName.Remove(binding.propertyName.Length - 1, 1) + axis;\n\n            object currentValue = CurveBindingUtility.GetCurrentValue(state.activeRootGameObject, binding);\n\n            var previousModification = modification.previousValue;\n            if (previousModification == null)\n            {\n                // create dummy\n                previousModification = new PropertyModification();\n                previousModification.target = target;\n                previousModification.propertyPath = binding.propertyName;\n                previousModification.value = ((float)currentValue).ToString(CultureInfo.InvariantCulture.NumberFormat);\n            }\n\n            object previousValue = currentValue;\n            ValueFromPropertyModification(previousModification, binding, out previousValue);\n\n            state.AddPropertyModification(binding, previousModification, modification.keepPrefabOverride);\n\n            if (scale != 1.0f)\n            {\n                previousValue = (object)((float)previousValue / scale);\n                currentValue = (object)((float)currentValue / scale);\n            }\n\n            AddKey(state, binding, typeof(float), previousValue, currentValue);\n        }\n\n        static public void ProcessVector3Modifications(IAnimationRecordingState state, ref Dictionary<object, Vector3Modification> vector3Modifications)\n        {\n            foreach (KeyValuePair<object, Vector3Modification> item in vector3Modifications)\n            {\n                Vector3Modification m = item.Value;\n                Transform target = item.Key as Transform;\n\n                if (target == null)\n                    continue;\n\n                EditorCurveBinding binding = new EditorCurveBinding();\n                Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.last.currentValue, state.activeRootGameObject, out binding);\n                if (type == null)\n                    continue;\n\n                ProcessVector3Modification(state, binding, m.x, target, \"x\");\n                ProcessVector3Modification(state, binding, m.y, target, \"y\");\n                ProcessVector3Modification(state, binding, m.z, target, \"z\");\n            }\n        }\n\n        static public void ProcessModifications(IAnimationRecordingState state, UndoPropertyModification[] modifications)\n        {\n            GameObject root = state.activeRootGameObject;\n\n            // Record modified properties\n            for (int i = 0; i < modifications.Length; i++)\n            {\n                EditorCurveBinding binding = new EditorCurveBinding();\n\n                PropertyModification prop = modifications[i].previousValue;\n                Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(prop, root, out binding);\n                if (type != null)\n                {\n                    object currentValue = CurveBindingUtility.GetCurrentValue(root, binding);\n\n                    object previousValue = null;\n                    if (!ValueFromPropertyModification(prop, binding, out previousValue))\n                        previousValue = currentValue;\n\n                    state.AddPropertyModification(binding, prop, modifications[i].keepPrefabOverride);\n                    AddKey(state, binding, type, previousValue, currentValue);\n                }\n            }\n        }\n\n        static public UndoPropertyModification[] Process(IAnimationRecordingState state, UndoPropertyModification[] modifications)\n        {\n            GameObject root = state.activeRootGameObject;\n            if (root == null)\n                return modifications;\n\n            // Fast path detect that nothing recordable has changed.\n            if (!HasAnyRecordableModifications(root, modifications))\n                return modifications;\n\n            Dictionary<object, RotationModification> rotationModifications = new Dictionary<object, RotationModification>();\n            Dictionary<object, Vector3Modification> scaleModifications = new Dictionary<object, Vector3Modification>();\n            Dictionary<object, Vector3Modification> positionModifications = new Dictionary<object, Vector3Modification>();\n\n            //Strip out the rotation modifications from the rest\n            CollectRotationModifications(state, ref modifications, ref rotationModifications);\n            UndoPropertyModification[] discardedRotationModifications = FilterRotationModifications(state, ref rotationModifications);\n            UndoPropertyModification[] discardedModifications = FilterModifications(state, ref modifications);\n            CollectVector3Modifications(state, ref modifications, ref positionModifications, kLocalPosition);\n            CollectVector3Modifications(state, ref modifications, ref scaleModifications, kLocalScale);\n\n            // Process Animator Modifications.\n            ProcessAnimatorModifications(state, ref positionModifications, ref rotationModifications, ref scaleModifications);\n            // Process position modifications.\n            ProcessVector3Modifications(state, ref positionModifications);\n            // Process rotation modifications.\n            ProcessRotationModifications(state, ref rotationModifications);\n            // Process scale modifications.\n            ProcessVector3Modifications(state, ref scaleModifications);\n            // Process what's remaining.\n            ProcessModifications(state, modifications);\n\n            return discardedModifications.Concat(discardedRotationModifications).ToArray();\n        }\n\n        static bool ValueFromPropertyModification(PropertyModification modification, EditorCurveBinding binding, out object outObject)\n        {\n            if (modification == null)\n            {\n                outObject = null;\n                return false;\n            }\n            else if (binding.isPPtrCurve)\n            {\n                outObject = modification.objectReference;\n                return true;\n            }\n            else\n            {\n                if(binding.isDiscreteCurve && int.TryParse(modification.value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int tempInt))\n                {\n                    outObject = tempInt;\n                    return true;\n                }\n                else if (float.TryParse(modification.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float tempFloat))\n                {\n                    outObject = tempFloat;\n                    return true;\n                }\n                else\n                {\n                    outObject = null;\n                    return false;\n                }\n            }\n        }\n\n        static void AddKey(IAnimationRecordingState state, EditorCurveBinding binding, Type type, object previousValue, object currentValue)\n        {\n            AnimationClip clip = state.activeAnimationClip;\n\n            if ((clip.hideFlags & HideFlags.NotEditable) != 0)\n                return;\n\n            AnimationWindowCurve curve = new AnimationWindowCurve(clip, binding, type);\n\n            // Add previous value at first frame on empty curves.\n            if (state.addZeroFrame)\n            {\n                // Is it a new curve?\n                if (curve.length == 0)\n                {\n                    if (state.currentFrame != 0)\n                    {\n                        AnimationWindowUtility.AddKeyframeToCurve(curve, previousValue, type, AnimationKeyTime.Frame(0, clip.frameRate));\n                    }\n                }\n            }\n\n            // Add key at current frame.\n            AnimationWindowUtility.AddKeyframeToCurve(curve, currentValue, type, AnimationKeyTime.Frame(state.currentFrame, clip.frameRate));\n\n            state.SaveCurve(curve);\n        }\n\n        static void AddRotationKey(IAnimationRecordingState state, EditorCurveBinding binding, Type type, Vector3 previousEulerAngles, Vector3 currentEulerAngles)\n        {\n            AnimationClip clip = state.activeAnimationClip;\n\n            if ((clip.hideFlags & HideFlags.NotEditable) != 0)\n                return;\n\n            EditorCurveBinding[] additionalBindings = RotationCurveInterpolation.RemapAnimationBindingForRotationAddKey(binding, clip);\n\n            // Add key at current frame\n            for (int i = 0; i < 3; i++)\n            {\n                AnimationWindowCurve curve = new AnimationWindowCurve(clip, additionalBindings[i], type);\n\n                if (state.addZeroFrame)\n                {\n                    // Is it a new curve?\n                    if (curve.length == 0)\n                    {\n                        if (state.currentFrame != 0)\n                        {\n                            AnimationWindowUtility.AddKeyframeToCurve(curve, previousEulerAngles[i], type, AnimationKeyTime.Frame(0, clip.frameRate));\n                        }\n                    }\n                }\n\n                AnimationWindowUtility.AddKeyframeToCurve(curve, currentEulerAngles[i], type, AnimationKeyTime.Frame(state.currentFrame, clip.frameRate));\n                state.SaveCurve(curve);\n            }\n        }\n\n        internal class RootMotionModification\n        {\n            public UndoPropertyModification px;\n            public UndoPropertyModification py;\n            public UndoPropertyModification pz;\n            public UndoPropertyModification lastP;\n\n            public UndoPropertyModification rx;\n            public UndoPropertyModification ry;\n            public UndoPropertyModification rz;\n            public UndoPropertyModification rw;\n            public UndoPropertyModification lastR;\n        }\n\n        static private void ProcessRootMotionModifications(IAnimationRecordingState state,\n            ref Dictionary<object, RootMotionModification> rootMotionModifications)\n        {\n            GameObject root = state.activeRootGameObject;\n            Animator animator = root.GetComponent<Animator>();\n\n            bool isHuman = animator != null ? animator.isHuman : false;\n\n            foreach (KeyValuePair<object, RootMotionModification> item in rootMotionModifications)\n            {\n                RootMotionModification m = item.Value;\n                Transform target = item.Key as Transform;\n\n                Vector3 scale = target.localScale * (isHuman ? animator.humanScale : 1);\n                Vector3 position = target.localPosition;\n                Quaternion rotation = target.localRotation;\n\n                if (m.lastP.previousValue != null)\n                {\n                    ProcessRootMotionModification(state, animator, m.px, \"MotionT.x\", position.x, scale.x);\n                    ProcessRootMotionModification(state, animator, m.py, \"MotionT.y\", position.y, scale.y);\n                    ProcessRootMotionModification(state, animator, m.pz, \"MotionT.z\", position.z, scale.z);\n                }\n\n                if (m.lastR.previousValue != null)\n                {\n                    ProcessRootMotionModification(state, animator, m.rx, \"MotionQ.x\", rotation.x, 1);\n                    ProcessRootMotionModification(state, animator, m.ry, \"MotionQ.y\", rotation.y, 1);\n                    ProcessRootMotionModification(state, animator, m.rz, \"MotionQ.z\", rotation.z, 1);\n                    ProcessRootMotionModification(state, animator, m.rw, \"MotionQ.w\", rotation.w, 1);\n                }\n            }\n        }\n\n        static private void ProcessAnimatorModifications(IAnimationRecordingState state,\n            ref Dictionary<object, Vector3Modification> positionModifications,\n            ref Dictionary<object, RotationModification> rotationModifications,\n            ref Dictionary<object, Vector3Modification> scaleModifications)\n        {\n            Dictionary<object, RootMotionModification> rootMotionModifications = new Dictionary<object, RootMotionModification>();\n\n            AnimationClip clip = state.activeAnimationClip;\n            GameObject root = state.activeRootGameObject;\n            Animator animator = root.GetComponent<Animator>();\n\n            bool isHuman = animator != null ? animator.isHuman : false;\n            bool hasRootMotion = animator != null ? animator.hasRootMotion : false;\n            bool applyRootMotion = animator != null ? animator.applyRootMotion : false;\n            bool hasRootCurves = clip.hasRootCurves;\n\n            // process animator positions\n            List<object> discardListPos = new List<object>();\n\n            foreach (KeyValuePair<object, Vector3Modification> item in positionModifications)\n            {\n                Vector3Modification m = item.Value;\n                Transform target = item.Key as Transform;\n\n                if (target == null)\n                    continue;\n\n                EditorCurveBinding binding = new EditorCurveBinding();\n                Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.last.currentValue, state.activeRootGameObject, out binding);\n                if (type == null)\n                    continue;\n\n                bool isRootTransform = root.transform == target;\n                bool isRootMotion = isRootTransform && applyRootMotion && hasRootCurves && (isHuman || hasRootMotion);\n                bool isHumanBone = isHuman && !isRootTransform && animator.IsBoneTransform(target);\n\n                if (isHumanBone)\n                {\n                    Debug.LogWarning(\"Keyframing translation on humanoid rig is not supported!\", target);\n                    discardListPos.Add(item.Key);\n                }\n                else if (isRootMotion)\n                {\n                    RootMotionModification rootMotionModification;\n\n                    if (!rootMotionModifications.TryGetValue(target, out rootMotionModification))\n                    {\n                        rootMotionModification = new RootMotionModification();\n                        rootMotionModifications[target] = rootMotionModification;\n                    }\n\n                    rootMotionModification.lastP = m.last;\n                    rootMotionModification.px = m.x;\n                    rootMotionModification.py = m.y;\n                    rootMotionModification.pz = m.z;\n\n                    discardListPos.Add(item.Key);\n                }\n                else if (applyRootMotion && isRootTransform)\n                {\n                    Vector3 scale = root.transform.localScale * (isHuman ? animator.humanScale : 1);\n\n                    ProcessVector3Modification(state, binding, m.x, target, \"x\", scale.x);\n                    ProcessVector3Modification(state, binding, m.y, target, \"y\", scale.y);\n                    ProcessVector3Modification(state, binding, m.z, target, \"z\", scale.z);\n\n                    discardListPos.Add(item.Key);\n                }\n            }\n\n            foreach (object key in discardListPos)\n            {\n                positionModifications.Remove(key);\n            }\n\n            // process animator rotation\n            List<object> discardListRot = new List<object>();\n\n            foreach (KeyValuePair<object, RotationModification> item in rotationModifications)\n            {\n                RotationModification m = item.Value;\n                Transform target = item.Key as Transform;\n\n                if (target == null)\n                    continue;\n\n                EditorCurveBinding binding = new EditorCurveBinding();\n                Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.lastQuatModification.currentValue, state.activeRootGameObject, out binding);\n                if (type == null)\n                    continue;\n\n                bool isRootTransform = root.transform == target;\n                bool isRootMotion = isRootTransform && applyRootMotion && hasRootCurves && (isHuman || hasRootMotion);\n                bool isHumanBone = isHuman && !isRootTransform && animator.IsBoneTransform(target);\n\n                if (isHumanBone)\n                {\n                    Debug.LogWarning(\"Keyframing rotation on humanoid rig is not supported!\", target);\n                    discardListRot.Add(item.Key);\n                }\n                else if (isRootMotion)\n                {\n                    RootMotionModification rootMotionModification;\n\n                    if (!rootMotionModifications.TryGetValue(target, out rootMotionModification))\n                    {\n                        rootMotionModification = new RootMotionModification();\n                        rootMotionModifications[target] = rootMotionModification;\n                    }\n\n                    rootMotionModification.lastR = m.lastQuatModification;\n                    rootMotionModification.rx = m.x;\n                    rootMotionModification.ry = m.y;\n                    rootMotionModification.rz = m.z;\n                    rootMotionModification.rw = m.w;\n\n                    discardListRot.Add(item.Key);\n                }\n            }\n\n            foreach (object key in discardListRot)\n            {\n                rotationModifications.Remove(key);\n            }\n\n            // process animator scales\n            List<object> discardListScale = new List<object>();\n\n            foreach (KeyValuePair<object, Vector3Modification> item in scaleModifications)\n            {\n                Vector3Modification m = item.Value;\n                Transform target = item.Key as Transform;\n\n                if (target == null)\n                    continue;\n\n                EditorCurveBinding binding = new EditorCurveBinding();\n                Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.last.currentValue, state.activeRootGameObject, out binding);\n                if (type == null)\n                    continue;\n\n                bool isRootTransform = root.transform == target;\n                bool isHumanBone = isHuman && !isRootTransform && animator.IsBoneTransform(target);\n                if (isHumanBone)\n                {\n                    Debug.LogWarning(\"Keyframing scale on humanoid rig is not supported!\", target);\n                    discardListScale.Add(item.Key);\n                }\n            }\n\n            foreach (object key in discardListScale)\n            {\n                scaleModifications.Remove(key);\n            }\n\n            ProcessRootMotionModifications(state, ref rootMotionModifications);\n        }\n\n        static void ProcessRootMotionModification(IAnimationRecordingState state, Animator animator, UndoPropertyModification modification, string name, float value, float scale)\n        {\n            AnimationClip clip = state.activeAnimationClip;\n\n            if ((clip.hideFlags & HideFlags.NotEditable) != 0)\n                return;\n\n            float prevValue = value;\n\n            object oValue;\n\n            if (ValueFromPropertyModification(modification.currentValue, new EditorCurveBinding(), out oValue))\n                value = (float)oValue;\n\n            if (ValueFromPropertyModification(modification.previousValue, new EditorCurveBinding(), out oValue))\n                prevValue = (float)oValue;\n\n            value = Mathf.Abs(scale) > Mathf.Epsilon ? value / scale : value;\n            prevValue = Mathf.Abs(scale) > Mathf.Epsilon ? prevValue / scale : prevValue;\n\n            var binding = new EditorCurveBinding();\n            binding.propertyName = name;\n            binding.path = \"\";\n            binding.type = typeof(Animator);\n\n            var prop = new PropertyModification();\n            prop.target = animator;\n            prop.propertyPath = binding.propertyName;\n            prop.value = value.ToString(CultureInfo.InvariantCulture.NumberFormat);\n\n            state.AddPropertyModification(binding, prop, modification.keepPrefabOverride);\n\n            AnimationWindowCurve curve = new AnimationWindowCurve(clip, binding, typeof(float));\n\n            if (state.addZeroFrame && state.currentFrame != 0 && curve.length == 0)\n            {\n                AnimationWindowUtility.AddKeyframeToCurve(curve, prevValue, typeof(float), AnimationKeyTime.Frame(0, clip.frameRate));\n            }\n\n            AnimationWindowUtility.AddKeyframeToCurve(curve, value, typeof(float), AnimationKeyTime.Frame(state.currentFrame, clip.frameRate));\n\n            state.SaveCurve(curve);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEditorInternal;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [EditorWindowTitle(title = \"Animation\", useTypeNameAsIconName = true)]\n    public sealed class AnimationWindow : EditorWindow, IHasCustomMenu\n    {\n        // Active Animation windows\n        private static List<AnimationWindow> s_AnimationWindows = new List<AnimationWindow>();\n        internal static List<AnimationWindow> GetAllAnimationWindows() { return s_AnimationWindows; }\n\n        private static Type[] s_CustomControllerTypes = null;\n\n        private AnimEditor m_AnimEditor;\n\n        [SerializeField]\n        EditorGUIUtility.EditorLockTracker m_LockTracker = new EditorGUIUtility.EditorLockTracker();\n\n        [SerializeField] private int m_LastSelectedObjectID;\n\n        private GUIStyle m_LockButtonStyle;\n        private GUIContent m_DefaultTitleContent;\n        private GUIContent m_RecordTitleContent;\n\n        internal AnimEditor animEditor => m_AnimEditor;\n\n        internal AnimationWindowState state\n        {\n            get\n            {\n                if (m_AnimEditor != null)\n                {\n                    return m_AnimEditor.state;\n                }\n                return null;\n            }\n        }\n\n        public AnimationClip animationClip\n        {\n            get\n            {\n                if (m_AnimEditor != null)\n                {\n                    return m_AnimEditor.state.activeAnimationClip;\n                }\n                return null;\n            }\n            set\n            {\n                if (m_AnimEditor != null)\n                {\n                    m_AnimEditor.state.activeAnimationClip = value;\n                }\n            }\n        }\n\n        public bool previewing\n        {\n            get\n            {\n                if (m_AnimEditor != null)\n                {\n                    return m_AnimEditor.state.previewing;\n                }\n                return false;\n            }\n            set\n            {\n                if (m_AnimEditor != null)\n                {\n                    m_AnimEditor.state.previewing = value;\n                }\n            }\n        }\n\n        public bool canPreview\n        {\n            get\n            {\n                if (m_AnimEditor != null)\n                {\n                    return m_AnimEditor.state.canPreview;\n                }\n\n                return false;\n            }\n        }\n\n        public bool recording\n        {\n            get\n            {\n                if (m_AnimEditor != null)\n                {\n                    return m_AnimEditor.state.recording;\n                }\n                return false;\n            }\n            set\n            {\n                if (m_AnimEditor != null)\n                {\n                    m_AnimEditor.state.recording = value;\n                }\n            }\n        }\n\n        public bool canRecord\n        {\n            get\n            {\n                if (m_AnimEditor != null)\n                {\n                    return m_AnimEditor.state.canRecord;\n                }\n\n                return false;\n            }\n        }\n\n        public bool playing\n        {\n            get\n            {\n                if (m_AnimEditor != null)\n                {\n                    return m_AnimEditor.state.playing;\n                }\n                return false;\n            }\n            set\n            {\n                if (m_AnimEditor != null)\n                {\n                    m_AnimEditor.state.playing = value;\n                }\n            }\n        }\n\n        public float time\n        {\n            get\n            {\n                if (m_AnimEditor != null)\n                {\n                    return m_AnimEditor.state.currentTime;\n                }\n                return 0.0f;\n            }\n            set\n            {\n                if (m_AnimEditor != null)\n                {\n                    m_AnimEditor.state.currentTime = value;\n                }\n            }\n        }\n\n        public int frame\n        {\n            get\n            {\n                if (m_AnimEditor != null)\n                {\n                    return m_AnimEditor.state.currentFrame;\n                }\n                return 0;\n            }\n            set\n            {\n                if (m_AnimEditor != null)\n                {\n                    m_AnimEditor.state.currentFrame = value;\n                }\n            }\n        }\n\n        private AnimationWindow()\n        {}\n\n        internal void ForceRefresh()\n        {\n            if (m_AnimEditor != null)\n            {\n                m_AnimEditor.state.ForceRefresh();\n            }\n        }\n\n        void OnEnable()\n        {\n            if (m_AnimEditor == null)\n            {\n                m_AnimEditor = CreateInstance<AnimEditor>();\n                m_AnimEditor.hideFlags = HideFlags.HideAndDontSave;\n            }\n\n            s_AnimationWindows.Add(this);\n            titleContent = GetLocalizedTitleContent();\n\n            m_DefaultTitleContent = titleContent;\n            m_RecordTitleContent = EditorGUIUtility.TextContentWithIcon(titleContent.text, \"Animation.Record\");\n\n            OnSelectionChange();\n\n            Undo.undoRedoEvent += UndoRedoPerformed;\n        }\n\n        void OnDisable()\n        {\n            s_AnimationWindows.Remove(this);\n            m_AnimEditor.OnDisable();\n\n            Undo.undoRedoEvent -= UndoRedoPerformed;\n        }\n\n        void OnDestroy()\n        {\n            DestroyImmediate(m_AnimEditor);\n        }\n\n        void Update()\n        {\n            if (m_AnimEditor == null)\n                return;\n\n            m_AnimEditor.Update();\n        }\n\n        void OnGUI()\n        {\n            if (m_AnimEditor == null)\n                return;\n\n            titleContent = m_AnimEditor.state.recording ? m_RecordTitleContent : m_DefaultTitleContent;\n            m_AnimEditor.OnAnimEditorGUI(this, position);\n        }\n\n        internal void OnSelectionChange()\n        {\n            if (m_AnimEditor == null)\n                return;\n\n            Object activeObject = Selection.activeObject;\n\n            bool restoringLockedSelection = false;\n            if (m_LockTracker.isLocked && m_AnimEditor.stateDisabled)\n            {\n                activeObject = EditorUtility.InstanceIDToObject(m_LastSelectedObjectID);\n                restoringLockedSelection = true;\n                m_LockTracker.isLocked = false;\n            }\n\n            if (activeObject is GameObject activeGameObject)\n            {\n                EditGameObject(activeGameObject);\n            }\n            else\n            {\n                if (activeObject is Transform activeTransform)\n                {\n                    EditGameObject(activeTransform.gameObject);\n                }\n                else\n                {\n                    if (activeObject is AnimationClip activeAnimationClip)\n                        EditAnimationClip(activeAnimationClip);\n                }\n            }\n\n            if (restoringLockedSelection && !m_AnimEditor.stateDisabled)\n            {\n                m_LockTracker.isLocked = true;\n            }\n        }\n\n        void OnFocus()\n        {\n            OnSelectionChange();\n        }\n\n        internal void OnControllerChange()\n        {\n            // Refresh selectedItem to update selected clips.\n            OnSelectionChange();\n        }\n\n        void OnLostFocus()\n        {\n            if (m_AnimEditor != null)\n                m_AnimEditor.OnLostFocus();\n        }\n\n        [Callbacks.OnOpenAsset]\n        static bool OnOpenAsset(int instanceID, int line)\n        {\n            var clip = EditorUtility.InstanceIDToObject(instanceID) as AnimationClip;\n            if (clip)\n            {\n                EditorWindow.GetWindow<AnimationWindow>();\n                return true;\n            }\n            return false;\n        }\n\n        internal bool EditGameObject(GameObject gameObject)\n        {\n            if (EditorUtility.IsPersistent(gameObject))\n                return false;\n\n            if ((gameObject.hideFlags & HideFlags.NotEditable) != 0)\n                return false;\n\n            var newSelection = GameObjectSelectionItem.Create(gameObject);\n            if (ShouldUpdateGameObjectSelection(newSelection))\n            {\n                m_AnimEditor.selection = newSelection;\n\n                IAnimationWindowController controller = null;\n\n                var rootGameObject = newSelection.rootGameObject;\n                if (rootGameObject != null)\n                    controller = FindCustomController(rootGameObject);\n\n                m_AnimEditor.overrideControlInterface = controller;\n\n                m_LastSelectedObjectID = gameObject != null ? gameObject.GetInstanceID() : 0;\n            }\n            else\n                m_AnimEditor.OnSelectionUpdated();\n\n            return true;\n        }\n\n        internal bool EditAnimationClip(AnimationClip animationClip)\n        {\n            if (state.linkedWithSequencer == true)\n                return false;\n\n            EditAnimationClipInternal(animationClip, (Object)null, (IAnimationWindowController)null);\n            return true;\n        }\n\n        internal bool EditSequencerClip(AnimationClip animationClip, Object sourceObject, IAnimationWindowControl controlInterface)\n        {\n            EditAnimationClipInternal(animationClip, sourceObject, controlInterface);\n            state.linkedWithSequencer = true;\n\n            if (controlInterface != null)\n                controlInterface.Init(state);\n\n            return true;\n        }\n\n        internal void UnlinkSequencer()\n        {\n            if (state.linkedWithSequencer)\n            {\n                state.linkedWithSequencer = false;\n\n                // Selected object could have been changed when unlocking the animation window\n                EditAnimationClip(null);\n                OnSelectionChange();\n            }\n        }\n\n        private IAnimationWindowController FindCustomController(GameObject gameObject)\n        {\n            IAnimationWindowController controller = null;\n\n            if (s_CustomControllerTypes == null)\n            {\n                s_CustomControllerTypes = TypeCache\n                    .GetTypesWithAttribute<AnimationWindowControllerAttribute>()\n                    .Where(type => typeof(IAnimationWindowController).IsAssignableFrom(type))\n                    .ToArray();\n            }\n\n            foreach (var controllerType in s_CustomControllerTypes)\n            {\n                var attribute = controllerType.GetCustomAttribute<AnimationWindowControllerAttribute>();\n                var component = gameObject.GetComponent(attribute.componentType);\n\n                if (component != null)\n                {\n                    controller = (IAnimationWindowController)Activator.CreateInstance(controllerType);\n                    controller.OnCreate(this, component);\n                    break;\n                }\n            }\n\n            return controller;\n        }\n\n        private void EditAnimationClipInternal(AnimationClip animationClip, Object sourceObject, IAnimationWindowController controlInterface)\n        {\n            var newSelection = AnimationClipSelectionItem.Create(animationClip, sourceObject);\n            if (ShouldUpdateSelection(newSelection))\n            {\n                m_AnimEditor.selection = newSelection;\n                m_AnimEditor.overrideControlInterface = controlInterface;\n\n                m_LastSelectedObjectID = animationClip != null ? animationClip.GetInstanceID() : 0;\n            }\n            else\n                m_AnimEditor.OnSelectionUpdated();\n        }\n\n        void ShowButton(Rect r)\n        {\n            if (m_LockButtonStyle == null)\n                m_LockButtonStyle = \"IN LockButton\";\n\n            EditorGUI.BeginChangeCheck();\n\n            m_LockTracker.ShowButton(r, m_LockButtonStyle, m_AnimEditor.stateDisabled);\n\n            // Selected object could have been changed when unlocking the animation window\n            if (EditorGUI.EndChangeCheck())\n                OnSelectionChange();\n        }\n\n        private bool ShouldUpdateGameObjectSelection(GameObjectSelectionItem selectedItem)\n        {\n            if (m_LockTracker.isLocked)\n                return false;\n\n            if (state.linkedWithSequencer)\n                return false;\n\n            // Selected game object with no animation player.\n            if (selectedItem.rootGameObject == null)\n                return true;\n\n            AnimationWindowSelectionItem currentSelection = m_AnimEditor.selection;\n\n            // Game object holding animation player has changed.  Update selection.\n            if (selectedItem.rootGameObject != currentSelection.rootGameObject)\n                return true;\n\n            // No clip in current selection, favour new selection.\n            if (currentSelection.animationClip == null)\n                return true;\n\n            // Make sure that animation clip is still referenced in animation player.\n            if (currentSelection.rootGameObject != null)\n            {\n                AnimationClip[] allClips = AnimationUtility.GetAnimationClips(currentSelection.rootGameObject);\n                if (!Array.Exists(allClips, x => x == currentSelection.animationClip))\n                    return true;\n            }\n\n            return false;\n        }\n\n        private bool ShouldUpdateSelection(AnimationWindowSelectionItem selectedItem)\n        {\n            if (m_LockTracker.isLocked)\n                return false;\n\n            AnimationWindowSelectionItem currentSelection = m_AnimEditor.selection;\n            return (selectedItem.GetRefreshHash() != currentSelection.GetRefreshHash());\n        }\n\n        private void UndoRedoPerformed(in UndoRedoInfo info)\n        {\n            Repaint();\n        }\n\n        public void AddItemsToMenu(GenericMenu menu)\n        {\n            m_LockTracker.AddItemsToMenu(menu, m_AnimEditor.stateDisabled);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowClipPopup.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    class AnimationWindowClipPopup\n    {\n        [SerializeReference] public AnimationWindowState state;\n\n        static int s_ClipPopupHash = \"s_ClipPopupHash\".GetHashCode();\n\n        private const float kMenuOffsetMac = 19;\n\n        internal sealed class ClipPopupCallbackInfo\n        {\n            // The global shared popup state\n            public static ClipPopupCallbackInfo instance = null;\n\n            // Name of the command event sent from the popup menu to OnGUI when user has changed selection\n            private const string kPopupMenuChangedMessage = \"ClipPopupMenuChanged\";\n\n            // The control ID of the popup menu that is currently displayed.\n            // Used to pass selection changes back again...\n            private readonly int m_ControlID = 0;\n\n            // Which item was selected\n            private AnimationClip m_SelectedClip = null;\n\n            // Which view should we send it to.\n            private readonly GUIView m_SourceView;\n\n            public ClipPopupCallbackInfo(int controlID)\n            {\n                m_ControlID = controlID;\n                m_SourceView = GUIView.current;\n            }\n\n            public static AnimationClip GetSelectedClipForControl(int controlID, AnimationClip clip)\n            {\n                Event evt = Event.current;\n                if (evt.type == EventType.ExecuteCommand && evt.commandName == kPopupMenuChangedMessage)\n                {\n                    if (instance == null)\n                    {\n                        Debug.LogError(\"Popup menu has no instance\");\n                        return clip;\n                    }\n                    if (instance.m_ControlID == controlID)\n                    {\n                        clip = instance.m_SelectedClip;\n                        instance = null;\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                }\n                return clip;\n            }\n\n            public static void SetSelectedClip(AnimationClip clip)\n            {\n                if (instance == null)\n                {\n                    Debug.LogError(\"Popup menu has no instance\");\n                    return;\n                }\n\n                instance.m_SelectedClip = clip;\n            }\n\n            public static void SendEvent()\n            {\n                if (instance == null)\n                {\n                    Debug.LogError(\"Popup menu has no instance\");\n                    return;\n                }\n\n                instance.m_SourceView.SendEvent(EditorGUIUtility.CommandEvent(kPopupMenuChangedMessage));\n            }\n        }\n\n\n        private void DisplayClipMenu(Rect position, int controlID, AnimationClip clip)\n        {\n            AnimationClip[] clips = GetOrderedClipList();\n            GUIContent[] menuContent = GetClipMenuContent(clips);\n            int selected = ClipToIndex(clips, clip);\n\n            // Center popup menu around button widget\n            if (Application.platform == RuntimePlatform.OSXEditor)\n            {\n                position.y = position.y - selected * EditorGUI.kSingleLineHeight - kMenuOffsetMac;\n            }\n\n            ClipPopupCallbackInfo.instance = new ClipPopupCallbackInfo(controlID);\n\n            EditorUtility.DisplayCustomMenu(position, menuContent, null, selected, (userData, options, index) =>\n            {\n                if (index < clips.Length)\n                {\n                    ClipPopupCallbackInfo.SetSelectedClip(clips[index]);\n                }\n                else\n                {\n                    AnimationClip newClip = AnimationWindowUtility.CreateNewClip(state.selection.rootGameObject.name);\n                    if (newClip)\n                    {\n                        AnimationWindowUtility.AddClipToAnimationPlayerComponent(state.activeAnimationPlayer, newClip);\n                        ClipPopupCallbackInfo.SetSelectedClip(newClip);\n                    }\n                }\n\n                ClipPopupCallbackInfo.SendEvent();\n            }, null);\n        }\n\n        // (case 1029160) Modified version of EditorGUI.DoPopup to fit large data list query.\n        private AnimationClip DoClipPopup(AnimationClip clip, GUIStyle style)\n        {\n            Rect position = EditorGUILayout.GetControlRect(false, EditorGUI.kSingleLineHeight, style);\n            int controlID = GUIUtility.GetControlID(s_ClipPopupHash, FocusType.Keyboard, position);\n\n            clip = ClipPopupCallbackInfo.GetSelectedClipForControl(controlID, clip);\n\n            Event evt = Event.current;\n            switch (evt.type)\n            {\n                case EventType.Repaint:\n                    Font originalFont = style.font;\n                    if (originalFont && EditorGUIUtility.GetBoldDefaultFont() && originalFont == EditorStyles.miniFont)\n                    {\n                        style.font = EditorStyles.miniBoldFont;\n                    }\n\n                    GUIContent buttonContent = EditorGUIUtility.TempContent(CurveUtility.GetClipName(clip));\n                    buttonContent.tooltip = AssetDatabase.GetAssetPath(clip);\n\n                    style.Draw(position, buttonContent, controlID, false);\n\n                    style.font = originalFont;\n                    break;\n                case EventType.MouseDown:\n                    if (evt.button == 0 && position.Contains(evt.mousePosition))\n                    {\n                        DisplayClipMenu(position, controlID, clip);\n                        GUIUtility.keyboardControl = controlID;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (evt.MainActionKeyForControl(controlID))\n                    {\n                        DisplayClipMenu(position, controlID, clip);\n                        evt.Use();\n                    }\n                    break;\n            }\n\n            return clip;\n        }\n\n        public void OnGUI()\n        {\n            if (state.selection.canChangeAnimationClip)\n            {\n                EditorGUI.BeginChangeCheck();\n                var newClip = DoClipPopup(state.activeAnimationClip, AnimationWindowStyles.animClipToolbarPopup);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    state.activeAnimationClip = newClip;\n\n                    //  Layout has changed, bail out now.\n                    EditorGUIUtility.ExitGUI();\n                }\n            }\n            else if (state.activeAnimationClip != null)\n            {\n                Rect r = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight, AnimationWindowStyles.toolbarLabel);\n                EditorGUI.LabelField(r, CurveUtility.GetClipName(state.activeAnimationClip), AnimationWindowStyles.toolbarLabel);\n            }\n        }\n\n        private GUIContent[] GetClipMenuContent(AnimationClip[] clips)\n        {\n            int size = clips.Length;\n            if (state.selection.canCreateClips)\n                size += 2;\n\n            GUIContent[] content = new GUIContent[size];\n            for (int i = 0; i < clips.Length; i++)\n            {\n                content[i] = new GUIContent(CurveUtility.GetClipName(clips[i]));\n            }\n\n            if (state.selection.canCreateClips)\n            {\n                content[content.Length - 2] = GUIContent.none;\n                content[content.Length - 1] = AnimationWindowStyles.createNewClip;\n            }\n\n            return content;\n        }\n\n        private AnimationClip[] GetOrderedClipList()\n        {\n            AnimationClip[] clips = new AnimationClip[0];\n            if (state.activeRootGameObject != null)\n                clips = AnimationUtility.GetAnimationClips(state.activeRootGameObject);\n\n            //Using AlphaNum/Natural Compare to sort clips\n            Array.Sort(clips, (AnimationClip clip1, AnimationClip clip2) => EditorUtility.NaturalCompareObjectNames(clip1, clip2));\n\n            return clips;\n        }\n\n        private int ClipToIndex(AnimationClip[] clips, AnimationClip clip)\n        {\n            for (int index = 0; index < clips.Length; ++index)\n            {\n                if (clips[index] == clip)\n                    return index;\n            }\n\n            return 0;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowClipboard.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    // Classes for copy/paste support of animation window related things\n\n    [Serializable]\n    internal sealed class AnimationWindowEventClipboard\n    {\n        public float time = 0;\n        public string functionName = \"\";\n        public string stringParam = \"\";\n        public int objectParam = 0;\n        public float floatParam = 0;\n        public int intParam = 0;\n        public SendMessageOptions messageOptions = SendMessageOptions.RequireReceiver;\n\n        public AnimationWindowEventClipboard(AnimationEvent e)\n        {\n            time = e.time;\n            functionName = e.functionName;\n            stringParam = e.stringParameter;\n            objectParam = e.objectReferenceParameter ? e.objectReferenceParameter.GetInstanceID() : 0;\n            floatParam = e.floatParameter;\n            intParam = e.intParameter;\n            messageOptions = e.messageOptions;\n        }\n\n        public static AnimationEvent FromClipboard(AnimationWindowEventClipboard e)\n        {\n            return new AnimationEvent\n            {\n                time = e.time,\n                functionName = e.functionName,\n                stringParameter = e.stringParam,\n                objectReferenceParameter = InternalEditorUtility.GetObjectFromInstanceID(e.objectParam),\n                floatParameter = e.floatParam,\n                intParameter = e.intParam,\n                messageOptions = e.messageOptions\n            };\n        }\n    }\n\n    [Serializable]\n    internal class AnimationWindowEventsClipboard\n    {\n        public AnimationWindowEventClipboard[] events;\n\n        internal static bool CanPaste()\n        {\n            return Clipboard.HasCustomValue<AnimationWindowEventsClipboard>();\n        }\n\n        internal static void CopyEvents(IList<AnimationEvent> allEvents, bool[] selected, int explicitIndex = -1)\n        {\n            var copyEvents = new List<AnimationWindowEventClipboard>();\n            // If a selection already exists, copy selection instead of clicked index\n            if (Array.Exists(selected, s => s))\n            {\n                for (var i = 0; i < selected.Length; ++i)\n                {\n                    if (selected[i])\n                        copyEvents.Add(new AnimationWindowEventClipboard(allEvents[i]));\n                }\n            }\n            // Else, only copy the clicked animation event\n            else if (explicitIndex >= 0)\n            {\n                copyEvents.Add(new AnimationWindowEventClipboard(allEvents[explicitIndex]));\n            }\n            var data = new AnimationWindowEventsClipboard {events = copyEvents.ToArray()};\n\n            // Animation keyframes right now do not go through regular clipboard machinery,\n            // so when copying Events, make sure Keyframes are cleared from the clipboard, or things\n            // get confusing.\n            AnimationWindowState.ClearKeyframeClipboard();\n\n            Clipboard.SetCustomValue(data);\n        }\n\n        internal static AnimationEvent[] AddPastedEvents(AnimationEvent[] events, float time, out bool[] selected)\n        {\n            selected = null;\n            var data = Clipboard.GetCustomValue<AnimationWindowEventsClipboard>();\n            if (data?.events == null || data.events.Length == 0)\n                return null;\n\n            var minTime = data.events.Min(e => e.time);\n\n            var origEventsCount = events.Length;\n            // Append new events to the end first,\n            var newEvents = new List<AnimationEvent>();\n            foreach (var e in data.events)\n            {\n                var t = e.time - minTime + time;\n                var newEvent = AnimationWindowEventClipboard.FromClipboard(e);\n                newEvent.time = t;\n                newEvents.Add(newEvent);\n            }\n            events = events.Concat(newEvents).ToArray();\n\n            // Re-sort events by time\n            var order = new int[events.Length];\n            for (var i = 0; i < order.Length; i++)\n                order[i] = i;\n            Array.Sort(events, order, new AnimationEventTimeLine.EventComparer());\n\n            // Mark pasted ones as selected\n            selected = new bool[events.Length];\n            for (var i = 0; i < order.Length; ++i)\n                selected[i] = order[i] >= origEventsCount;\n\n            return events;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowControl.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing Object = UnityEngine.Object;\n\nusing UnityEngine.Playables;\nusing UnityEngine.Animations;\n\nusing Unity.Profiling;\n\nnamespace UnityEditorInternal\n{\n    [Serializable]\n    class AnimationWindowControl : IAnimationWindowController, IAnimationContextualResponder\n    {\n        class CandidateRecordingState : IAnimationRecordingState\n        {\n            public GameObject activeGameObject { get; private set; }\n            public GameObject activeRootGameObject { get; private set; }\n            public AnimationClip activeAnimationClip { get; private set; }\n            public int currentFrame { get { return 0; } }\n\n            public bool addZeroFrame { get { return false; } }\n\n            public CandidateRecordingState(AnimationWindowState state, AnimationClip candidateClip)\n            {\n                activeGameObject = state.activeGameObject;\n                activeRootGameObject = state.activeRootGameObject;\n                activeAnimationClip = candidateClip;\n            }\n\n            public bool DiscardModification(PropertyModification modification)\n            {\n                return !AnimationMode.IsPropertyAnimated(modification.target, modification.propertyPath);\n            }\n\n            public void SaveCurve(AnimationWindowCurve curve)\n            {\n                Undo.RegisterCompleteObjectUndo(curve.clip, \"Edit Candidate Curve\");\n                AnimationWindowUtility.SaveCurve(curve.clip, curve);\n            }\n\n            public void AddPropertyModification(EditorCurveBinding binding, PropertyModification propertyModification, bool keepPrefabOverride)\n            {\n                AnimationMode.AddCandidate(binding, propertyModification, keepPrefabOverride);\n            }\n        }\n\n        enum RecordingStateMode\n        {\n            ManualKey,\n            AutoKey\n        }\n\n        class RecordingState : IAnimationRecordingState\n        {\n            private AnimationWindowState m_State;\n            private RecordingStateMode m_Mode;\n\n            public GameObject activeGameObject { get { return m_State.activeGameObject; } }\n            public GameObject activeRootGameObject { get { return m_State.activeRootGameObject; } }\n            public AnimationClip activeAnimationClip { get { return m_State.activeAnimationClip; } }\n            public int currentFrame { get { return m_State.currentFrame; } }\n\n            public bool addZeroFrame { get { return (m_Mode == RecordingStateMode.AutoKey); } }\n            public bool addPropertyModification { get { return m_State.previewing; } }\n\n            public RecordingState(AnimationWindowState state, RecordingStateMode mode)\n            {\n                m_State = state;\n                m_Mode = mode;\n            }\n\n            public bool DiscardModification(PropertyModification modification)\n            {\n                return false;\n            }\n\n            public void SaveCurve(AnimationWindowCurve curve)\n            {\n                m_State.SaveCurve(curve.clip, curve);\n            }\n\n            public void AddPropertyModification(EditorCurveBinding binding, PropertyModification propertyModification, bool keepPrefabOverride)\n            {\n                AnimationMode.AddPropertyModification(binding, propertyModification, keepPrefabOverride);\n            }\n        }\n\n        [Flags]\n        enum ResampleFlags\n        {\n            None                = 0,\n\n            RebuildGraph        = 1 << 0,\n            RefreshViews        = 1 << 1,\n            FlushUndos          = 1 << 2,\n\n            Default             = RefreshViews | FlushUndos\n        }\n\n        private static bool HasFlag(ResampleFlags flags, ResampleFlags flag)\n        {\n            return (flags & flag) != 0;\n        }\n\n        [SerializeField] private AnimationKeyTime m_Time;\n\n        [NonSerialized] private float m_PreviousUpdateTime;\n\n        [NonSerialized] public AnimationWindowState state;\n        public AnimEditor animEditor { get { return state.animEditor; } }\n\n        [SerializeField] private AnimationClip m_CandidateClip;\n        [SerializeField] private AnimationClip m_DefaultPose;\n\n        [SerializeField] private AnimationModeDriver m_Driver;\n        [SerializeField] private AnimationModeDriver m_CandidateDriver;\n\n        private PlayableGraph m_Graph;\n        private Playable m_GraphRoot;\n        private AnimationClipPlayable m_ClipPlayable;\n        private AnimationClipPlayable m_CandidateClipPlayable;\n        private AnimationClipPlayable m_DefaultPosePlayable;\n        private bool m_UsesPostProcessComponents = false;\n\n        private static ProfilerMarker s_ResampleAnimationMarker = new ProfilerMarker(\"AnimationWindowControl.ResampleAnimation\");\n\n        public void OnEnable()\n        {\n            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;\n        }\n\n        public void OnDisable()\n        {\n            EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;\n        }\n\n        public void OnCreate(AnimationWindow animationWindow, Component component)\n        {\n            // nothing to do.\n        }\n\n        public void OnDestroy()\n        {\n            if (m_Driver != null)\n                ScriptableObject.DestroyImmediate(m_Driver);\n        }\n\n        public void OnSelectionChanged()\n        {\n            // Set back time at beginning and stop recording.\n            if (state != null)\n                m_Time = AnimationKeyTime.Time(0f, state.frameRate);\n\n            StopPreview();\n        }\n\n        void OnPlayModeStateChanged(PlayModeStateChange state)\n        {\n            if (state == PlayModeStateChange.ExitingPlayMode ||\n                state == PlayModeStateChange.ExitingEditMode)\n            {\n                StopPreview();\n            }\n        }\n\n        public float time\n        {\n            get => m_Time.time;\n            set => SetCurrentTime(value);\n        }\n\n        public int frame\n        {\n            get => m_Time.frame;\n            set => SetCurrentFrame(value);\n        }\n\n        public void GoToTime(float time)\n        {\n            SetCurrentTime(time);\n        }\n\n        public void GoToFrame(int frame)\n        {\n            SetCurrentFrame(frame);\n        }\n\n        public void GoToPreviousKeyframe(PropertyModification[] modifications)\n        {\n            EditorCurveBinding[] bindings = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, state.activeRootGameObject, state.activeAnimationClip);\n            if (bindings.Length == 0)\n                return;\n\n            List<AnimationWindowCurve> curves = new List<AnimationWindowCurve>();\n            for (int i = 0; i < state.filteredCurves.Count; ++i)\n            {\n                AnimationWindowCurve curve = state.filteredCurves[i];\n                if (Array.Exists(bindings, binding => curve.binding.Equals(binding)))\n                    curves.Add(curve);\n            }\n\n            float newTime = AnimationWindowUtility.GetPreviousKeyframeTime(curves.ToArray(), time, state.clipFrameRate);\n            SetCurrentTime(state.SnapToFrame(newTime, AnimationWindowState.SnapMode.SnapToFrame));\n\n            state.Repaint();\n        }\n\n        public void GoToNextKeyframe(PropertyModification[] modifications)\n        {\n            EditorCurveBinding[] bindings = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, state.activeRootGameObject, state.activeAnimationClip);\n            if (bindings.Length == 0)\n                return;\n\n            List<AnimationWindowCurve> curves = new List<AnimationWindowCurve>();\n            for (int i = 0; i < state.filteredCurves.Count; ++i)\n            {\n                AnimationWindowCurve curve = state.filteredCurves[i];\n                if (Array.Exists(bindings, binding => curve.binding.Equals(binding)))\n                    curves.Add(curve);\n            }\n\n            float newTime = AnimationWindowUtility.GetNextKeyframeTime(curves.ToArray(), time, state.clipFrameRate);\n            SetCurrentTime(state.SnapToFrame(newTime, AnimationWindowState.SnapMode.SnapToFrame));\n\n            state.Repaint();\n        }\n\n        private void SnapTimeToFrame()\n        {\n            float newTime = state.FrameToTime(frame);\n            SetCurrentTime(newTime);\n        }\n\n        private void SetCurrentTime(float value)\n        {\n            if (!Mathf.Approximately(value, time))\n            {\n                m_Time = AnimationKeyTime.Time(value, state.frameRate);\n                StartPreview();\n                ClearCandidates();\n                ResampleAnimation();\n            }\n        }\n\n        private void SetCurrentFrame(int value)\n        {\n            if (value != frame)\n            {\n                m_Time = AnimationKeyTime.Frame(value, state.frameRate);\n                StartPreview();\n                ClearCandidates();\n                ResampleAnimation();\n            }\n        }\n\n        public bool canPlay\n        {\n            get\n            {\n                return canPreview;\n            }\n        }\n\n        public bool playing\n        {\n            get\n            {\n                return AnimationMode.InAnimationPlaybackMode() && previewing;\n            }\n            set\n            {\n                if (value)\n                    StartPlayback();\n                else\n                    StopPlayback();\n            }\n        }\n\n        private void StartPlayback()\n        {\n            if (!canPlay || playing)\n                return;\n\n            AnimationMode.StartAnimationPlaybackMode();\n\n            m_PreviousUpdateTime = Time.realtimeSinceStartup;\n\n            // Auto-Preview when start playing\n            ClearCandidates();\n        }\n\n        private void StopPlayback()\n        {\n            if (AnimationMode.InAnimationPlaybackMode())\n            {\n                AnimationMode.StopAnimationPlaybackMode();\n\n                // Snap to frame when playing stops\n                SnapTimeToFrame();\n            }\n        }\n\n        public bool PlaybackUpdate()\n        {\n            float deltaTime = Time.realtimeSinceStartup - m_PreviousUpdateTime;\n            m_PreviousUpdateTime = Time.realtimeSinceStartup;\n\n            float newTime = time + deltaTime;\n\n            // looping\n            if (newTime > state.maxTime)\n                newTime = state.minTime;\n\n            m_Time = AnimationKeyTime.Time(Mathf.Clamp(newTime, state.minTime, state.maxTime), state.frameRate);\n\n            ResampleAnimation();\n\n            return true;\n        }\n\n        public bool canPreview\n        {\n            get\n            {\n                if (!state.selection.canPreview)\n                    return false;\n\n                var driver = GetAnimationModeDriverNoAlloc();\n\n                return (driver != null && AnimationMode.InAnimationMode(driver)) || !AnimationMode.InAnimationMode();\n            }\n        }\n\n        public bool previewing\n        {\n            get\n            {\n                var driver = GetAnimationModeDriverNoAlloc();\n                if (driver == null)\n                    return false;\n\n                return AnimationMode.InAnimationMode(driver);\n            }\n            set\n            {\n                if (value)\n                    StartPreview();\n                else\n                    StopPreview();\n            }\n        }\n\n        private void StartPreview()\n        {\n            if (previewing || !canPreview)\n                return;\n\n            AnimationMode.StartAnimationMode(GetAnimationModeDriver());\n            AnimationPropertyContextualMenu.Instance.SetResponder(this);\n            Undo.postprocessModifications += PostprocessAnimationRecordingModifications;\n            PrefabUtility.allowRecordingPrefabPropertyOverridesFor += AllowRecordingPrefabPropertyOverridesFor;\n            DestroyGraph();\n            CreateCandidateClip();\n\n            //If a hierarchy was created and array reorder happen in the inspector prior\n            //to the preview being started we will need to ensure that the display name\n            //reflects the binding path on an array element.\n            state.UpdateCurvesDisplayName();\n\n            IAnimationWindowPreview[] previewComponents = FetchPostProcessComponents();\n            m_UsesPostProcessComponents = previewComponents != null && previewComponents.Length > 0;\n            if (previewComponents != null)\n            {\n                // Animation preview affects inspector values, so make sure we ignore constrain proportions\n                ConstrainProportionsTransformScale.m_IsAnimationPreview = true;\n                foreach (var component in previewComponents)\n                {\n                    component.StartPreview();\n                }\n            }\n\n            ResampleAnimation();\n        }\n\n        private void StopPreview()\n        {\n            if (!previewing)\n                return;\n\n            OnExitingAnimationMode();\n\n            ConstrainProportionsTransformScale.m_IsAnimationPreview = false;\n\n            ClearCandidates();\n            DestroyGraph();\n            DestroyCandidateClip();\n\n            AnimationMode.StopAnimationMode(GetAnimationModeDriver());\n\n            // reset responder only if we have set it\n            if (AnimationPropertyContextualMenu.Instance.IsResponder(this))\n            {\n                AnimationPropertyContextualMenu.Instance.SetResponder(null);\n            }\n\n            if (m_UsesPostProcessComponents)\n            {\n                IAnimationWindowPreview[] previewComponents = FetchPostProcessComponents();\n                if (previewComponents != null)\n                {\n                    foreach (var component in previewComponents)\n                    {\n                        component.StopPreview();\n                    }\n\n                    if (!Application.isPlaying)\n                    {\n                        var animator = state.activeAnimationPlayer as Animator;\n                        if (animator != null)\n                        {\n                            animator.UnbindAllHandles();\n                        }\n                    }\n                }\n\n                m_UsesPostProcessComponents = false;\n            }\n        }\n\n        public bool canRecord\n        {\n            get\n            {\n                if (!state.selection.canRecord)\n                    return false;\n\n                return canPreview;\n            }\n        }\n\n        public bool recording\n        {\n            get\n            {\n                if (previewing)\n                    return AnimationMode.InAnimationRecording();\n                return false;\n            }\n            set\n            {\n                if (value)\n                    StartRecording();\n                else\n                    StopRecording();\n            }\n        }\n\n        private void StartRecording()\n        {\n            if (!canRecord || recording)\n                return;\n\n            AnimationMode.StartAnimationRecording();\n            ClearCandidates();\n        }\n\n        private void StopRecording()\n        {\n            if (!recording)\n                return;\n\n            AnimationMode.StopAnimationRecording();\n        }\n\n        private void StartCandidateRecording()\n        {\n            AnimationMode.StartCandidateRecording(GetCandidateDriver());\n        }\n\n        private void StopCandidateRecording()\n        {\n            AnimationMode.StopCandidateRecording();\n        }\n\n        private void DestroyGraph()\n        {\n            if (!m_Graph.IsValid())\n                return;\n\n            m_Graph.Destroy();\n            m_GraphRoot = Playable.Null;\n        }\n\n        private void RebuildGraph(Animator animator)\n        {\n            DestroyGraph();\n\n            m_Graph = PlayableGraph.Create(\"PreviewGraph\");\n            m_Graph.SetTimeUpdateMode(DirectorUpdateMode.Manual);\n\n            m_ClipPlayable = AnimationClipPlayable.Create(m_Graph, state.activeAnimationClip);\n            m_ClipPlayable.SetOverrideLoopTime(true);\n            m_ClipPlayable.SetLoopTime(false);\n            m_ClipPlayable.SetApplyFootIK(false);\n\n            m_CandidateClipPlayable = AnimationClipPlayable.Create(m_Graph, m_CandidateClip);\n            m_CandidateClipPlayable.SetApplyFootIK(false);\n\n            IAnimationWindowPreview[] previewComponents = FetchPostProcessComponents();\n            bool requiresDefaultPose = previewComponents != null && previewComponents.Length > 0;\n            int nInputs = requiresDefaultPose ? 3 : 2;\n\n            // Create a layer mixer if necessary, we'll connect playable nodes to it after having populated AnimationStream.\n            AnimationLayerMixerPlayable mixer = AnimationLayerMixerPlayable.Create(m_Graph, nInputs);\n            m_GraphRoot = (Playable)mixer;\n\n            // Populate custom playable preview graph.\n            if (previewComponents != null)\n            {\n                foreach (var component in previewComponents)\n                {\n                    m_GraphRoot = component.BuildPreviewGraph(m_Graph, m_GraphRoot);\n                }\n            }\n\n            // Finish hooking up mixer.\n            int inputIndex = 0;\n\n            if (requiresDefaultPose)\n            {\n                AnimationMode.RevertPropertyModificationsForGameObject(state.activeRootGameObject);\n\n                EditorCurveBinding[] streamBindings = AnimationUtility.GetAnimationStreamBindings(state.activeRootGameObject);\n\n                m_DefaultPose = new AnimationClip() { name = \"DefaultPose\" };\n\n                AnimationWindowUtility.CreateDefaultCurves(state, m_DefaultPose, streamBindings);\n\n                m_DefaultPosePlayable = AnimationClipPlayable.Create(m_Graph, m_DefaultPose);\n                m_DefaultPosePlayable.SetApplyFootIK(false);\n\n                mixer.ConnectInput(inputIndex++, m_DefaultPosePlayable, 0, 1.0f);\n            }\n\n            mixer.ConnectInput(inputIndex++, m_ClipPlayable, 0, 1.0f);\n            mixer.ConnectInput(inputIndex++, m_CandidateClipPlayable, 0, 1.0f);\n\n            if (animator.applyRootMotion)\n            {\n                var motionX = AnimationMotionXToDeltaPlayable.Create(m_Graph);\n                motionX.SetAbsoluteMotion(true);\n                motionX.SetInputWeight(0, 1.0f);\n\n                m_Graph.Connect(m_GraphRoot, 0, motionX, 0);\n\n                m_GraphRoot = (Playable)motionX;\n            }\n\n            var output = AnimationPlayableOutput.Create(m_Graph, \"output\", animator);\n            output.SetSourcePlayable(m_GraphRoot);\n            output.SetWeight(0.0f);\n        }\n\n        private IAnimationWindowPreview[] FetchPostProcessComponents()\n        {\n            if (state.activeRootGameObject != null)\n            {\n                return state.activeRootGameObject.GetComponents<IAnimationWindowPreview>();\n            }\n\n            return null;\n        }\n\n        public void ResampleAnimation()\n        {\n            ResampleAnimation(ResampleFlags.Default);\n        }\n\n        private void ResampleAnimation(ResampleFlags flags)\n        {\n            if (state.disabled)\n                return;\n\n            if (!canPreview || !previewing)\n                return;\n\n            s_ResampleAnimationMarker.Begin();\n            if (state.activeAnimationClip != null)\n            {\n                var animationPlayer = state.activeAnimationPlayer;\n                bool usePlayableGraph = animationPlayer is Animator;\n\n                if (usePlayableGraph)\n                {\n                    var isValidGraph = m_Graph.IsValid();\n                    if (isValidGraph)\n                    {\n                        var playableOutput = (AnimationPlayableOutput)m_Graph.GetOutput(0);\n                        isValidGraph = playableOutput.GetTarget() == (Animator)animationPlayer;\n                    }\n\n                    if (HasFlag(flags, ResampleFlags.RebuildGraph) || !isValidGraph)\n                    {\n                        RebuildGraph((Animator)animationPlayer);\n                    }\n                }\n\n                AnimationMode.BeginSampling();\n\n                if (HasFlag(flags, ResampleFlags.FlushUndos))\n                    Undo.FlushUndoRecordObjects();\n\n                if (usePlayableGraph)\n                {\n                    if (m_UsesPostProcessComponents)\n                    {\n                        IAnimationWindowPreview[] previewComponents = FetchPostProcessComponents();\n                        if (previewComponents != null)\n                        {\n                            foreach (var component in previewComponents)\n                            {\n                                component.UpdatePreviewGraph(m_Graph);\n                            }\n                        }\n                    }\n\n                    if (!m_CandidateClip.empty)\n                    {\n                        StartCandidateRecording();\n                        AnimationMode.AddCandidates(state.activeRootGameObject, m_CandidateClip);\n                    }\n\n                    m_ClipPlayable.SetSampleRate(playing ? -1 : state.activeAnimationClip.frameRate);\n\n                    AnimationMode.SamplePlayableGraph(m_Graph, 0, time);\n\n                    // This will cover euler/quaternion matching in basic playable graphs only (animation clip + candidate clip).\n                    AnimationUtility.SampleEulerHint(state.activeRootGameObject, state.activeAnimationClip, time, WrapMode.Clamp);\n                    if (!m_CandidateClip.empty)\n                        AnimationUtility.SampleEulerHint(state.activeRootGameObject, m_CandidateClip, time, WrapMode.Clamp);\n                }\n                else\n                {\n                    AnimationMode.SampleAnimationClip(state.activeRootGameObject, state.activeAnimationClip, time);\n                    if (!m_CandidateClip.empty)\n                        AnimationMode.SampleCandidateClip(state.activeRootGameObject, m_CandidateClip, 0f);\n                }\n\n                AnimationMode.EndSampling();\n\n                if (HasFlag(flags, ResampleFlags.RefreshViews))\n                {\n                    SceneView.RepaintAll();\n                    InspectorWindow.RepaintAllInspectors();\n\n                    // Particle editor needs to be manually repainted to refresh the animated properties\n                    var particleSystemWindow = ParticleSystemWindow.GetInstance();\n                    if (particleSystemWindow)\n                        particleSystemWindow.Repaint();\n                }\n            }\n            s_ResampleAnimationMarker.End();\n        }\n\n        private AnimationModeDriver GetAnimationModeDriver()\n        {\n            if (m_Driver == null)\n            {\n                m_Driver = ScriptableObject.CreateInstance<AnimationModeDriver>();\n                m_Driver.hideFlags = HideFlags.HideAndDontSave;\n                m_Driver.name = \"AnimationWindowDriver\";\n                m_Driver.isKeyCallback += (Object target, string propertyPath) =>\n                {\n                    if (AnimationMode.IsPropertyAnimated(target, propertyPath))\n                    {\n                        var modification = new PropertyModification();\n                        modification.target = target;\n                        modification.propertyPath = propertyPath;\n\n                        return KeyExists(new PropertyModification[] {modification});\n                    }\n\n                    return false;\n                };\n            }\n\n            return m_Driver;\n        }\n\n        private AnimationModeDriver GetAnimationModeDriverNoAlloc()\n        {\n            return m_Driver;\n        }\n\n        private AnimationModeDriver GetCandidateDriver()\n        {\n            if (m_CandidateDriver == null)\n            {\n                m_CandidateDriver = ScriptableObject.CreateInstance<AnimationModeDriver>();\n                m_CandidateDriver.name = \"AnimationWindowCandidateDriver\";\n            }\n\n            return m_CandidateDriver;\n        }\n\n        private bool AllowRecordingPrefabPropertyOverridesFor(UnityEngine.Object componentOrGameObject)\n        {\n            if (componentOrGameObject == null)\n                throw new ArgumentNullException(nameof(componentOrGameObject));\n\n            if (componentOrGameObject is not Component && componentOrGameObject is not GameObject)\n                return true;\n\n            var rootOfAnimation = state.activeRootGameObject;\n            if (rootOfAnimation == null)\n                return true;\n\n            return false;\n        }\n\n        void OnExitingAnimationMode()\n        {\n            Undo.postprocessModifications -= PostprocessAnimationRecordingModifications;\n            PrefabUtility.allowRecordingPrefabPropertyOverridesFor -= AllowRecordingPrefabPropertyOverridesFor;\n        }\n\n        void RecordPropertyOverridesForNonAnimatedProperties(UndoPropertyModification[] modifications)\n        {\n            PrefabUtility.allowRecordingPrefabPropertyOverridesFor -= AllowRecordingPrefabPropertyOverridesFor;\n            foreach (var mod in modifications)\n            {\n                PrefabUtility.RecordPrefabInstancePropertyModifications(mod.currentValue.target);\n            }\n            PrefabUtility.allowRecordingPrefabPropertyOverridesFor += AllowRecordingPrefabPropertyOverridesFor;\n        }\n\n        private UndoPropertyModification[] PostprocessAnimationRecordingModifications(UndoPropertyModification[] modifications)\n        {\n            //Fix for case 751009: The animationMode can be changed outside the AnimationWindow, and callbacks needs to be unregistered.\n            if (!AnimationMode.InAnimationMode(GetAnimationModeDriver()))\n            {\n                OnExitingAnimationMode();\n                return modifications;\n            }\n\n            if (recording)\n                modifications = ProcessAutoKey(modifications);\n            else if (previewing)\n                modifications = RegisterCandidates(modifications);\n\n            // Fix for UUM-61742: Unrecorded Prefab overloads should be recorded immediately\n            RecordPropertyOverridesForNonAnimatedProperties(modifications);\n\n            RefreshDisplayNamesOnArrayTopologicalChange(modifications);\n\n            // Only resample when playable graph has been customized with post process nodes.\n            if (m_UsesPostProcessComponents)\n                ResampleAnimation(ResampleFlags.None);\n\n            return modifications;\n        }\n\n        private void RefreshDisplayNamesOnArrayTopologicalChange(UndoPropertyModification[] modifications)\n        {\n            if (modifications.Length >= 2)\n            {\n                if (modifications[0].currentValue.propertyPath.EndsWith(\"]\") &&\n                    modifications[0].currentValue.propertyPath.Contains(\".Array.data[\") &&\n                    modifications[1].currentValue.propertyPath.EndsWith(\"]\") &&\n                    modifications[1].currentValue.propertyPath.Contains(\".Array.data[\"))\n                {\n                    //Array reordering might affect curves display name\n                    state.UpdateCurvesDisplayName();\n                }\n                else if (modifications[0].currentValue.propertyPath.EndsWith(\".Array.size\") &&\n                         Convert.ToInt64(modifications[0].currentValue.value) <\n                         Convert.ToInt64(modifications[0].previousValue.value))\n                {\n                    //Array shrinking might affect curves display name\n                    state.UpdateCurvesDisplayName();\n                }\n            }\n        }\n\n        private UndoPropertyModification[] ProcessAutoKey(UndoPropertyModification[] modifications)\n        {\n            BeginKeyModification();\n\n            RecordingState recordingState = new RecordingState(state, RecordingStateMode.AutoKey);\n            UndoPropertyModification[] discardedModifications = AnimationRecording.Process(recordingState, modifications);\n\n            EndKeyModification();\n\n            return discardedModifications;\n        }\n\n        private UndoPropertyModification[] RegisterCandidates(UndoPropertyModification[] modifications)\n        {\n            bool hasCandidates = AnimationMode.IsRecordingCandidates();\n\n            if (!hasCandidates)\n                StartCandidateRecording();\n\n            CandidateRecordingState recordingState = new CandidateRecordingState(state, m_CandidateClip);\n            UndoPropertyModification[] discardedModifications = AnimationRecording.Process(recordingState, modifications);\n\n            // No modifications were added to the candidate clip, stop recording candidates.\n            if (!hasCandidates && discardedModifications.Length == modifications.Length)\n                StopCandidateRecording();\n\n            // Make sure inspector is repainted after adding new candidates to get appropriate feedback.\n            InspectorWindow.RepaintAllInspectors();\n\n            return discardedModifications;\n        }\n\n        private void RemoveFromCandidates(PropertyModification[] modifications)\n        {\n            EditorCurveBinding[] bindings = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, state.activeRootGameObject, m_CandidateClip);\n            if (bindings.Length == 0)\n                return;\n\n            // Remove entry from candidate clip.\n            Undo.RegisterCompleteObjectUndo(m_CandidateClip, \"Edit Candidate Curve\");\n\n            for (int i = 0; i < bindings.Length; ++i)\n            {\n                EditorCurveBinding binding = bindings[i];\n                if (binding.isPPtrCurve)\n                    AnimationUtility.SetObjectReferenceCurve(m_CandidateClip, binding, null);\n                else\n                    AnimationUtility.SetEditorCurve(m_CandidateClip, binding, null);\n            }\n\n            // Clear out candidate clip if it's empty.\n            if (AnimationUtility.GetCurveBindings(m_CandidateClip).Length == 0 && AnimationUtility.GetObjectReferenceCurveBindings(m_CandidateClip).Length == 0)\n                ClearCandidates();\n        }\n\n        private void CreateCandidateClip()\n        {\n            m_CandidateClip = new AnimationClip();\n            m_CandidateClip.legacy = state.activeAnimationClip.legacy;\n            m_CandidateClip.name = \"CandidateClip\";\n        }\n\n        private void DestroyCandidateClip()\n        {\n            m_CandidateClip = null;\n        }\n\n        public void ClearCandidates()\n        {\n            StopCandidateRecording();\n\n            if (m_CandidateClip != null)\n                m_CandidateClip.ClearCurves();\n        }\n\n        public void ProcessCandidates()\n        {\n            BeginKeyModification();\n\n            EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(m_CandidateClip);\n            EditorCurveBinding[] objectCurveBindings = AnimationUtility.GetObjectReferenceCurveBindings(m_CandidateClip);\n\n            List<AnimationWindowCurve> curves = new List<AnimationWindowCurve>();\n\n            for (int i = 0; i < state.filteredCurves.Count; ++i)\n            {\n                AnimationWindowCurve curve = state.filteredCurves[i];\n                EditorCurveBinding remappedBinding = RotationCurveInterpolation.RemapAnimationBindingForRotationCurves(curve.binding, m_CandidateClip);\n                if (Array.Exists(bindings, binding => remappedBinding.Equals(binding)) || Array.Exists(objectCurveBindings, binding => remappedBinding.Equals(binding)))\n                    curves.Add(curve);\n            }\n\n            AnimationWindowUtility.AddKeyframes(state, curves, m_Time);\n\n            EndKeyModification();\n\n            ClearCandidates();\n        }\n\n        private List<AnimationWindowKeyframe> GetKeys(PropertyModification[] modifications)\n        {\n            var keys = new List<AnimationWindowKeyframe>();\n\n            EditorCurveBinding[] bindings = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, state.activeRootGameObject, state.activeAnimationClip);\n            if (bindings.Length == 0)\n                return keys;\n\n            for (int i = 0; i < state.filteredCurves.Count; ++i)\n            {\n                AnimationWindowCurve curve = state.filteredCurves[i];\n                if (Array.Exists(bindings, binding => curve.binding.Equals(binding)))\n                {\n                    int keyIndex = curve.GetKeyframeIndex(state.time);\n                    if (keyIndex >= 0)\n                    {\n                        keys.Add(curve.keyframes[keyIndex]);\n                    }\n                }\n            }\n\n            return keys;\n        }\n\n        public bool IsAnimatable(PropertyModification[] modifications)\n        {\n            for (int i = 0; i < modifications.Length; ++i)\n            {\n                var modification = modifications[i];\n                if (AnimationWindowUtility.PropertyIsAnimatable(modification.target, modification.propertyPath, state.activeRootGameObject))\n                    return true;\n            }\n\n            return false;\n        }\n\n        public bool IsEditable(Object targetObject)\n        {\n            if (state.selection.disabled)\n                return false;\n\n            if (previewing == false)\n                return false;\n\n            GameObject gameObject = null;\n            if (targetObject is Component)\n                gameObject = ((Component)targetObject).gameObject;\n            else if (targetObject is GameObject)\n                gameObject = (GameObject)targetObject;\n\n            if (gameObject != null)\n            {\n                Component animationPlayer = AnimationWindowUtility.GetClosestAnimationPlayerComponentInParents(gameObject.transform);\n                if (state.selection.animationPlayer == animationPlayer)\n                {\n                    return state.selection.animationIsEditable;\n                }\n            }\n\n            return false;\n        }\n\n        public bool KeyExists(PropertyModification[] modifications)\n        {\n            return (GetKeys(modifications).Count > 0);\n        }\n\n        public bool CandidateExists(PropertyModification[] modifications)\n        {\n            if (!HasAnyCandidates())\n                return false;\n\n            for (int i = 0; i < modifications.Length; ++i)\n            {\n                var modification = modifications[i];\n                if (AnimationMode.IsPropertyCandidate(modification.target, modification.propertyPath))\n                    return true;\n            }\n\n            return false;\n        }\n\n        public bool CurveExists(PropertyModification[] modifications)\n        {\n            EditorCurveBinding[] bindings = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, state.activeRootGameObject, state.activeAnimationClip);\n            if (bindings.Length == 0)\n                return false;\n\n            EditorCurveBinding[] clipBindings = AnimationUtility.GetCurveBindings(state.activeAnimationClip);\n            if (clipBindings.Length == 0)\n                return false;\n\n            if (Array.Exists(bindings, binding => Array.Exists(clipBindings, clipBinding => clipBinding.Equals(binding))))\n                return true;\n\n            EditorCurveBinding[] objectCurveBindings = AnimationUtility.GetObjectReferenceCurveBindings(state.activeAnimationClip);\n            if (objectCurveBindings.Length == 0)\n                return false;\n\n            return Array.Exists(objectCurveBindings, binding => Array.Exists(clipBindings, clipBinding => clipBinding.Equals(binding)));\n        }\n\n        public bool HasAnyCandidates()\n        {\n            return !m_CandidateClip.empty;\n        }\n\n        public bool HasAnyCurves()\n        {\n            return (state.filteredCurves.Count > 0);\n        }\n\n        public void AddKey(SerializedProperty property)\n        {\n            AddKey(AnimationWindowUtility.SerializedPropertyToPropertyModifications(property));\n        }\n\n        public void AddKey(PropertyModification[] modifications)\n        {\n            var undoModifications = new UndoPropertyModification[modifications.Length];\n            for (int i = 0; i < modifications.Length; ++i)\n            {\n                var modification = modifications[i];\n                undoModifications[i].previousValue = modification;\n                undoModifications[i].currentValue = modification;\n            }\n\n            BeginKeyModification();\n\n            var recordingState = new RecordingState(state, RecordingStateMode.ManualKey);\n            AnimationRecording.Process(recordingState, undoModifications);\n\n            EndKeyModification();\n\n            RemoveFromCandidates(modifications);\n\n            ResampleAnimation();\n            state.Repaint();\n        }\n\n        public void RemoveKey(SerializedProperty property)\n        {\n            RemoveKey(AnimationWindowUtility.SerializedPropertyToPropertyModifications(property));\n        }\n\n        public void RemoveKey(PropertyModification[] modifications)\n        {\n            BeginKeyModification();\n\n            List<AnimationWindowKeyframe> keys = GetKeys(modifications);\n            state.DeleteKeys(keys);\n\n            RemoveFromCandidates(modifications);\n\n            EndKeyModification();\n\n            ResampleAnimation();\n            state.Repaint();\n        }\n\n        public void RemoveCurve(SerializedProperty property)\n        {\n            RemoveCurve(AnimationWindowUtility.SerializedPropertyToPropertyModifications(property));\n        }\n\n        public void RemoveCurve(PropertyModification[] modifications)\n        {\n            EditorCurveBinding[] bindings = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, state.activeRootGameObject, state.activeAnimationClip);\n            if (bindings.Length == 0)\n                return;\n\n            BeginKeyModification();\n\n            Undo.RegisterCompleteObjectUndo(state.activeAnimationClip, \"Remove Curve\");\n\n            for (int i = 0; i < bindings.Length; ++i)\n            {\n                EditorCurveBinding binding = bindings[i];\n                if (binding.isPPtrCurve)\n                    AnimationUtility.SetObjectReferenceCurve(state.activeAnimationClip, binding, null);\n                else\n                    AnimationUtility.SetEditorCurve(state.activeAnimationClip, binding, null);\n            }\n\n            EndKeyModification();\n\n            RemoveFromCandidates(modifications);\n\n            ResampleAnimation();\n            state.Repaint();\n        }\n\n        public void AddCandidateKeys()\n        {\n            ProcessCandidates();\n\n            ResampleAnimation();\n            state.Repaint();\n        }\n\n        public void AddAnimatedKeys()\n        {\n            BeginKeyModification();\n\n            AnimationWindowUtility.AddKeyframes(state, state.filteredCurves, m_Time);\n            ClearCandidates();\n\n            EndKeyModification();\n\n            ResampleAnimation();\n            state.Repaint();\n        }\n\n        private void BeginKeyModification()\n        {\n            if (animEditor != null)\n                animEditor.BeginKeyModification();\n        }\n\n        private void EndKeyModification()\n        {\n            if (animEditor != null)\n                animEditor.EndKeyModification();\n        }\n\n        public EditorCurveBinding[] GetAnimatableBindings()\n        {\n            var rootGameObject = state.activeRootGameObject;\n            var scriptableObject = state.activeScriptableObject;\n\n            if (rootGameObject != null)\n            {\n                return AnimationWindowUtility.GetAnimatableBindings(rootGameObject);\n            }\n            if (scriptableObject != null)\n            {\n                return AnimationUtility.GetAnimatableBindings(scriptableObject);\n            }\n\n            return Array.Empty<EditorCurveBinding>();\n        }\n\n        public EditorCurveBinding[] GetAnimatableBindings(GameObject gameObject)\n        {\n            var rootGameObject = state.activeRootGameObject;\n            return AnimationUtility.GetAnimatableBindings(gameObject, rootGameObject);\n        }\n\n        public Type GetValueType(EditorCurveBinding binding)\n        {\n            var rootGameObject = state.activeRootGameObject;\n            var scriptableObject = state.activeScriptableObject;\n\n            if (rootGameObject != null)\n            {\n                return AnimationUtility.GetEditorCurveValueType(rootGameObject, binding);\n            }\n            else if (scriptableObject != null)\n            {\n                return AnimationUtility.GetEditorCurveValueType(scriptableObject, binding);\n            }\n            else\n            {\n                if (binding.isPPtrCurve)\n                {\n                    // Cannot extract type of PPtrCurve.\n                    return null;\n                }\n                else\n                {\n                    // Cannot extract type of AnimationCurve.  Default to float.\n                    return typeof(float);\n                }\n            }\n        }\n\n        public float GetFloatValue(EditorCurveBinding binding)\n        {\n            AnimationUtility.GetFloatValue(state.activeRootGameObject, binding, out var value);\n            return value;\n        }\n\n        public int GetIntValue(EditorCurveBinding binding)\n        {\n            AnimationUtility.GetDiscreteIntValue(state.activeRootGameObject, binding, out var value);\n            return value;\n        }\n\n        public Object GetObjectReferenceValue(EditorCurveBinding binding)\n        {\n            AnimationUtility.GetObjectReferenceValue(state.activeRootGameObject, binding, out var value);\n            return value;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowControllerAttribute.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [AttributeUsage(AttributeTargets.Class)]\n    class AnimationWindowControllerAttribute : Attribute\n    {\n        public Type componentType { get; }\n\n        public AnimationWindowControllerAttribute(System.Type type)\n        {\n            if (type == null)\n                Debug.LogError(\"Failed to load AnimationWindowControl component type\");\n            componentType = type;\n        }\n    }\n\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowCurve.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing System.Text.RegularExpressions;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditorInternal\n{\n    internal class AnimationWindowCurve : IComparable<AnimationWindowCurve>, IEquatable<AnimationWindowCurve>\n    {\n        public const float timeEpsilon = 0.00001f;\n\n        private List<AnimationWindowKeyframe> m_Keyframes;\n\n        private EditorCurveBinding m_Binding;\n        private int m_BindingHashCode;\n\n        private AnimationClip m_Clip;\n        private AnimationWindowSelectionItem m_SelectionBinding;\n\n        private System.Type m_ValueType;\n\n        public EditorCurveBinding binding { get { return m_Binding;  } }\n        public bool isPPtrCurve { get { return m_Binding.isPPtrCurve; } }\n        public bool isDiscreteCurve { get { return m_Binding.isDiscreteCurve; } }\n        public bool isSerializeReferenceCurve{ get {return m_Binding.isSerializeReferenceCurve;}}\n        public bool isPhantom { get { return m_Binding.isPhantom; } }\n        public string propertyName { get { return m_Binding.propertyName; } }\n        public string path { get { return m_Binding.path; } }\n        public System.Type type { get { return m_Binding.type; } }\n        public System.Type valueType { get { return m_ValueType; } }\n        public int length { get { return m_Keyframes.Count; } }\n\n        public int depth { get { return path.Length > 0 ? path.Split('/').Length : 0; } }\n\n        public AnimationClip clip { get { return m_Clip; } }\n\n        public GameObject rootGameObject { get { return m_SelectionBinding != null ? m_SelectionBinding.rootGameObject : null; } }\n        public ScriptableObject scriptableObject { get { return m_SelectionBinding != null ? m_SelectionBinding.scriptableObject : null; } }\n        public bool clipIsEditable { get { return m_SelectionBinding != null ? m_SelectionBinding.clipIsEditable : true; } }\n        public bool animationIsEditable { get { return m_SelectionBinding != null ? m_SelectionBinding.animationIsEditable : true; } }\n        public int selectionID { get { return m_SelectionBinding != null ? m_SelectionBinding.id : 0; } }\n\n        public IReadOnlyList<AnimationWindowKeyframe> keyframes => m_Keyframes;\n\n        private object defaultValue\n        {\n            get\n            {\n                if (isPPtrCurve)\n                    return null;\n                if (isDiscreteCurve)\n                    return 0;\n                return 0f;\n            }\n        }\n\n        public AnimationWindowSelectionItem selectionBinding { get { return m_SelectionBinding; } set { m_SelectionBinding = value; } }\n\n        public AnimationWindowCurve(AnimationClip clip, EditorCurveBinding binding, System.Type valueType)\n        {\n            binding = RotationCurveInterpolation.RemapAnimationBindingForRotationCurves(binding, clip);\n\n            m_Binding = binding;\n            m_BindingHashCode = binding.GetHashCode();\n            m_ValueType = valueType;\n            m_Clip = clip;\n\n            LoadKeyframes(clip);\n        }\n\n        public void LoadKeyframes(AnimationCurve curve)\n        {\n            if (curve == null)\n                return;\n\n            for (int i = 0; i < curve.length; i++)\n                m_Keyframes.Add(new AnimationWindowKeyframe(this, curve[i]));\n        }\n\n        public void LoadKeyframes(AnimationClip clip)\n        {\n            m_Keyframes = new List<AnimationWindowKeyframe>();\n\n            if (!m_Binding.isPPtrCurve)\n            {\n                AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, binding);\n                LoadKeyframes(curve);\n            }\n            else\n            {\n                ObjectReferenceKeyframe[] curve = AnimationUtility.GetObjectReferenceCurve(clip, binding);\n                if (curve != null)\n                {\n                    for (int i = 0; i < curve.Length; i++)\n                        m_Keyframes.Add(new AnimationWindowKeyframe(this, curve[i]));\n                }\n            }\n        }\n\n        public override int GetHashCode()\n        {\n            int clipID = (clip == null ? 0 : clip.GetInstanceID());\n            return unchecked(selectionID * 92821 ^ clipID * 19603 ^ GetBindingHashCode());\n        }\n\n        public int GetBindingHashCode()\n        {\n            return m_BindingHashCode;\n        }\n\n        public int CompareTo(AnimationWindowCurve obj)\n        {\n            if (!path.Equals(obj.path))\n            {\n                return ComparePaths(obj.path);\n            }\n\n            bool sameTransformComponent = type == typeof(Transform) && obj.type == typeof(Transform);\n            bool oneIsTransformComponent = (type == typeof(Transform) || obj.type == typeof(Transform));\n\n            // We want to sort position before rotation\n            if (sameTransformComponent)\n            {\n                string propertyGroupA = AnimationWindowUtility.GetPropertyGroupName(propertyName);\n                string propertyGroupB = AnimationWindowUtility.GetPropertyGroupName(obj.propertyName);\n\n                if (propertyGroupA.Equals(\"m_LocalPosition\") && (propertyGroupB.Equals(\"m_LocalRotation\") || propertyGroupB.StartsWith(\"localEulerAngles\")))\n                    return -1;\n                if ((propertyGroupA.Equals(\"m_LocalRotation\") || propertyGroupA.StartsWith(\"localEulerAngles\")) && propertyGroupB.Equals(\"m_LocalPosition\"))\n                    return 1;\n            }\n            // Transform component should always come first.\n            else if (oneIsTransformComponent)\n            {\n                if (type == typeof(Transform))\n                    return -1;\n                else\n                    return 1;\n            }\n\n            // Sort (.r, .g, .b, .a) and (.x, .y, .z, .w)\n            if (obj.type == type)\n            {\n                int lhsIndex = AnimationWindowUtility.GetComponentIndex(obj.propertyName);\n                int rhsIndex = AnimationWindowUtility.GetComponentIndex(propertyName);\n                if (lhsIndex != -1 && rhsIndex != -1 && propertyName.Substring(0, propertyName.Length - 2) == obj.propertyName.Substring(0, obj.propertyName.Length - 2))\n                    return rhsIndex - lhsIndex;\n            }\n\n            return string.Compare((path + type + propertyName), obj.path + obj.type + obj.propertyName, StringComparison.Ordinal);\n        }\n\n        public bool Equals(AnimationWindowCurve other)\n        {\n            return CompareTo(other) == 0;\n        }\n\n        int ComparePaths(string otherPath)\n        {\n            var thisPath = path.Split('/');\n            var objPath = otherPath.Split('/');\n\n            int smallerLength = Math.Min(thisPath.Length, objPath.Length);\n            for (int i = 0; i < smallerLength; ++i)\n            {\n                int compare = string.Compare(thisPath[i], objPath[i], StringComparison.Ordinal);\n                if (compare == 0)\n                {\n                    continue;\n                }\n\n                return compare;\n            }\n\n            if (thisPath.Length < objPath.Length)\n            {\n                return -1;\n            }\n\n            return 1;\n        }\n\n        public AnimationCurve ToAnimationCurve()\n        {\n            int length = m_Keyframes.Count;\n            AnimationCurve animationCurve = new AnimationCurve();\n            List<Keyframe> keys = new List<Keyframe>();\n\n            for (int i = 0; i < length; i++)\n            {\n                Keyframe newKeyframe = m_Keyframes[i].ToKeyframe();\n                keys.Add(newKeyframe);\n            }\n\n            animationCurve.keys = keys.ToArray();\n            return animationCurve;\n        }\n\n        public ObjectReferenceKeyframe[] ToObjectCurve()\n        {\n            int length = m_Keyframes.Count;\n            List<ObjectReferenceKeyframe> keys = new List<ObjectReferenceKeyframe>();\n\n            for (int i = 0; i < length; i++)\n            {\n                ObjectReferenceKeyframe newKeyframe = m_Keyframes[i].ToObjectReferenceKeyframe();\n                keys.Add(newKeyframe);\n            }\n\n            keys.Sort((a, b) => a.time.CompareTo(b.time));\n            return keys.ToArray();\n        }\n\n        public AnimationWindowKeyframe FindKeyAtTime(AnimationKeyTime keyTime)\n        {\n            int index = GetKeyframeIndex(keyTime);\n            if (index == -1)\n                return null;\n\n            return m_Keyframes[index];\n        }\n\n        public object Evaluate(float time)\n        {\n            if (m_Keyframes.Count == 0)\n                return defaultValue;\n\n            AnimationWindowKeyframe firstKey = m_Keyframes[0];\n            if (time <= firstKey.time)\n                return firstKey.value;\n\n            AnimationWindowKeyframe lastKey = m_Keyframes[m_Keyframes.Count - 1];\n            if (time >= lastKey.time)\n                return lastKey.value;\n\n            AnimationWindowKeyframe key = firstKey;\n            for (int i = 1; i < m_Keyframes.Count; ++i)\n            {\n                AnimationWindowKeyframe nextKey = m_Keyframes[i];\n\n                if (key.time <= time && nextKey.time > time)\n                {\n                    if (isPPtrCurve || isDiscreteCurve)\n                    {\n                        return key.value;\n                    }\n                    else\n                    {\n                        //  Create an animation curve stub and evaluate.\n                        Keyframe keyframe = key.ToKeyframe();\n                        Keyframe nextKeyframe = nextKey.ToKeyframe();\n\n                        AnimationCurve animationCurve = new AnimationCurve();\n                        animationCurve.keys = new Keyframe[2] { keyframe, nextKeyframe };\n\n                        return animationCurve.Evaluate(time);\n                    }\n                }\n\n                key = nextKey;\n            }\n\n            // Shouldn't happen...\n            return defaultValue;\n        }\n\n        public void AddKeyframe(AnimationWindowKeyframe key, AnimationKeyTime keyTime)\n        {\n            // If there is already key in this time, we always want to remove it\n            RemoveKeyframe(keyTime);\n\n            m_Keyframes.Add(key);\n            m_Keyframes.Sort((a, b) => a.time.CompareTo(b.time));\n        }\n\n        public void RemoveKeyframe(AnimationKeyTime time)\n        {\n            // Loop backwards so key removals don't mess up order\n            for (int i = m_Keyframes.Count - 1; i >= 0; i--)\n            {\n                if (time.ContainsTime(m_Keyframes[i].time))\n                    m_Keyframes.RemoveAt(i);\n            }\n        }\n\n        public void RemoveKeyframe(AnimationWindowKeyframe keyframe)\n        {\n            m_Keyframes.Remove(keyframe);\n        }\n\n        public bool HasKeyframe(AnimationKeyTime time)\n        {\n            return GetKeyframeIndex(time) != -1;\n        }\n\n        public int GetKeyframeIndex(AnimationKeyTime time)\n        {\n            for (int i = 0; i < m_Keyframes.Count; i++)\n            {\n                if (time.ContainsTime(m_Keyframes[i].time))\n                    return i;\n            }\n            return -1;\n        }\n\n        // Remove keys at range. Start time is exclusive and end time inclusive.\n        public void RemoveKeysAtRange(float startTime, float endTime)\n        {\n            for (int i = m_Keyframes.Count - 1; i >= 0; i--)\n            {\n                if (Mathf.Approximately(endTime, m_Keyframes[i].time) ||\n                    m_Keyframes[i].time > startTime && m_Keyframes[i].time < endTime)\n                    m_Keyframes.RemoveAt(i);\n            }\n        }\n\n        public void Clear()\n        {\n            m_Keyframes.Clear();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowEvent.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    /// <summary>\n    /// Holds the context for AnimationEvent editing.\n    /// </summary>\n    class AnimationEventEditorState\n    {\n        static bool s_ShowOverloadedFunctionsDetails = true;\n        static bool s_ShowDuplicatedFunctionsDetails = true;\n\n        bool m_ShowOverloadedFunctionsDetails = s_ShowOverloadedFunctionsDetails;\n        bool m_ShowDuplicatedFunctionsDetails = s_ShowDuplicatedFunctionsDetails;\n\n        /// <summary>\n        /// Used to track whether or not to show extra details about duplicated function names found in among the potential supported functions\n        /// </summary>\n        public bool ShowOverloadedFunctionsDetails\n        {\n            get => m_ShowOverloadedFunctionsDetails;\n            set\n            {\n                m_ShowOverloadedFunctionsDetails = s_ShowOverloadedFunctionsDetails = value;\n            }\n        }\n\n        /// <summary>\n        /// Used to track whether or not to show extra details about overloaded function names found in among the potential supported functions\n        /// </summary>\n        public bool ShowDuplicatedFunctionsDetails\n        {\n            get => m_ShowDuplicatedFunctionsDetails;\n            set\n            {\n                m_ShowDuplicatedFunctionsDetails = s_ShowDuplicatedFunctionsDetails = value;\n            }\n        }\n\n        public AnimationEventEditorState()\n        {\n            m_ShowOverloadedFunctionsDetails = s_ShowOverloadedFunctionsDetails;\n            m_ShowDuplicatedFunctionsDetails = s_ShowDuplicatedFunctionsDetails;\n        }\n    }\n\n    internal class AnimationWindowEvent : ScriptableObject\n    {\n        public GameObject root;\n        public AnimationClip clip;\n        public AnimationClipInfoProperties clipInfo;\n        public int eventIndex;\n\n        static public AnimationWindowEvent CreateAndEdit(GameObject root, AnimationClip clip, float time)\n        {\n            AnimationEvent animationEvent = new AnimationEvent();\n            animationEvent.time = time;\n\n            // Or add a new one\n            AnimationEvent[] events = AnimationUtility.GetAnimationEvents(clip);\n            int eventIndex = InsertAnimationEvent(ref events, clip, animationEvent);\n\n            AnimationWindowEvent animationWindowEvent = CreateInstance<AnimationWindowEvent>();\n            animationWindowEvent.hideFlags = HideFlags.HideInHierarchy;\n            animationWindowEvent.name = \"Animation Event\";\n\n            animationWindowEvent.root = root;\n            animationWindowEvent.clip = clip;\n            animationWindowEvent.clipInfo = null;\n            animationWindowEvent.eventIndex = eventIndex;\n\n            return animationWindowEvent;\n        }\n\n        static public AnimationWindowEvent Edit(GameObject root, AnimationClip clip, int eventIndex)\n        {\n            AnimationWindowEvent animationWindowEvent = CreateInstance<AnimationWindowEvent>();\n            animationWindowEvent.hideFlags = HideFlags.HideInHierarchy;\n            animationWindowEvent.name = \"Animation Event\";\n\n            animationWindowEvent.root = root;\n            animationWindowEvent.clip = clip;\n            animationWindowEvent.clipInfo = null;\n            animationWindowEvent.eventIndex = eventIndex;\n\n            return animationWindowEvent;\n        }\n\n        static public AnimationWindowEvent Edit(AnimationClipInfoProperties clipInfo, int eventIndex)\n        {\n            AnimationWindowEvent animationWindowEvent = CreateInstance<AnimationWindowEvent>();\n            animationWindowEvent.hideFlags = HideFlags.HideInHierarchy;\n            animationWindowEvent.name = \"Animation Event\";\n\n            animationWindowEvent.root = null;\n            animationWindowEvent.clip = null;\n            animationWindowEvent.clipInfo = clipInfo;\n            animationWindowEvent.eventIndex = eventIndex;\n\n            return animationWindowEvent;\n        }\n\n        static private int InsertAnimationEvent(ref AnimationEvent[] events, AnimationClip clip, AnimationEvent evt)\n        {\n            Undo.RegisterCompleteObjectUndo(clip, \"Add Event\");\n\n            // Or add a new one\n            int insertIndex = events.Length;\n            for (int i = 0; i < events.Length; i++)\n            {\n                if (events[i].time > evt.time)\n                {\n                    insertIndex = i;\n                    break;\n                }\n            }\n\n            ArrayUtility.Insert(ref events, insertIndex, evt);\n            AnimationUtility.SetAnimationEvents(clip, events);\n\n            events = AnimationUtility.GetAnimationEvents(clip);\n            if (events[insertIndex].time != evt.time || events[insertIndex].functionName != evt.functionName)\n                Debug.LogError(\"Failed insertion\");\n\n            return insertIndex;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowEventInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing System;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AnimationWindowEvent))]\n    [CanEditMultipleObjects]\n    internal class AnimationWindowEventInspector : Editor\n    {\n        public static GUIContent s_OverloadWarning = EditorGUIUtility.TrTextContent(\"Some functions were overloaded in MonoBehaviour components and may not work as intended if used with Animation Events!\");\n        public static GUIContent s_DuplicatesWarning = EditorGUIUtility.TrTextContent(\"Some functions have the same name across several Monobehaviour components and may not work as intended if used with Animation Events!\");\n\n        const string kNotSupportedPostFix = \" (Function Not Supported)\";\n        const string kNoneSelected = \"(No Function Selected)\";\n\n        AnimationEventEditorState m_State = new();\n\n        public override void OnInspectorGUI()\n        {\n            var awes = targets.Select(o => o as AnimationWindowEvent).ToArray();\n            OnEditAnimationEvents(awes, m_State);\n        }\n\n        protected override void OnHeaderGUI()\n        {\n            string targetTitle = (targets.Length == 1) ? \"Animation Event\" : targets.Length + \" Animation Events\";\n            DrawHeaderGUI(this, targetTitle);\n        }\n\n        public static void OnEditAnimationEvent(AnimationWindowEvent awe, AnimationEventEditorState state)\n        {\n            OnEditAnimationEvents(new AnimationWindowEvent[] {awe}, state);\n        }\n\n        // These are used so we don't alloc new lists on every call\n        static List<AnimationMethodMap> supportedMethods;\n        static List<AnimationMethodMap> overloads;\n        static List<AnimationMethodMap> duplicates;\n\n        public static void OnEditAnimationEvents(AnimationWindowEvent[] awEvents, AnimationEventEditorState state)\n        {\n            AnimationWindowEventData data = GetData(awEvents);\n            if (data.events == null || data.selectedEvents == null || data.selectedEvents.Length == 0)\n                return;\n\n            AnimationEvent firstEvent = data.selectedEvents[0];\n\n            bool singleFunctionName = Array.TrueForAll(data.selectedEvents, evt => evt.functionName == firstEvent.functionName);\n\n            EditorGUI.BeginChangeCheck();\n\n            if (data.root != null)\n            {\n                supportedMethods ??= new List<AnimationMethodMap>();\n                overloads ??= new List<AnimationMethodMap>();\n                duplicates ??= new List<AnimationMethodMap>();\n\n                supportedMethods.Clear();\n                overloads.Clear();\n                duplicates.Clear();\n                CollectSupportedMethods(data.root, supportedMethods, overloads, duplicates);\n\n                int selected = supportedMethods.FindIndex(method => method.Name == firstEvent.functionName);\n\n                // A non-empty array used for rendering the contents of the popup\n                // It is of size 1 greater than the list of supported methods to account for the \"None\" option\n                string[] methodsFormatted = new string[supportedMethods.Count + 1];\n\n                for (int i = 0; i < supportedMethods.Count; ++i)\n                {\n                    AnimationMethodMap methodMap = supportedMethods[i];\n                    string menuPath = methodMap.methodMenuPath;\n                    methodsFormatted[i] = menuPath;\n                }\n\n                // Add a final option to set the function to no selected function\n                int notSupportedIndex = supportedMethods.Count;\n                if (selected == -1)\n                {\n                    selected = notSupportedIndex;\n\n                    // Display that the current function is not supported if applicable\n                    if (string.IsNullOrEmpty(firstEvent.functionName))\n                        methodsFormatted[notSupportedIndex] = kNoneSelected;\n                    else\n                        methodsFormatted[notSupportedIndex] = firstEvent.functionName + kNotSupportedPostFix;\n\n                    var emptyMethodMap = new AnimationMethodMap();\n                    supportedMethods.Add(emptyMethodMap);\n                }\n\n                EditorGUIUtility.labelWidth = 130;\n\n                EditorGUI.showMixedValue = !singleFunctionName;\n                int wasSelected = singleFunctionName ? selected : -1;\n                selected = EditorGUILayout.Popup(\"Function: \", selected, methodsFormatted);\n                if (wasSelected != selected && selected != -1 && selected != notSupportedIndex)\n                {\n                    foreach (var evt in data.selectedEvents)\n                    {\n                        evt.functionName = supportedMethods[selected].Name;\n                        evt.stringParameter = string.Empty;\n                    }\n                }\n                EditorGUI.showMixedValue = false;\n\n                var selectedParameter = supportedMethods[selected].parameterType;\n\n                if (singleFunctionName && selectedParameter != null)\n                {\n                    EditorGUILayout.Space();\n                    if (selectedParameter == typeof(AnimationEvent))\n                        EditorGUILayout.PrefixLabel(\"Event Data\");\n                    else\n                        EditorGUILayout.PrefixLabel(\"Parameters\");\n\n                    DoEditRegularParameters(data.selectedEvents, selectedParameter);\n                }\n\n                if (overloads.Count > 0)\n                {\n                    EditorGUILayout.Space();\n                    EditorGUILayout.HelpBox(s_OverloadWarning.text, MessageType.Warning, true);\n                    state.ShowOverloadedFunctionsDetails = EditorGUILayout.Foldout(state.ShowOverloadedFunctionsDetails, \"Show Details\");\n                    if (state.ShowOverloadedFunctionsDetails)\n                    {\n                        string overloadedFunctionDetails = \"Overloaded Functions: \\n\" + GetFormattedMethodsText(overloads);\n                        GUILayout.Label(overloadedFunctionDetails, EditorStyles.helpBox);\n                    }\n                }\n\n                if (duplicates.Count > 0)\n                {\n                    EditorGUILayout.Space();\n                    EditorGUILayout.HelpBox(s_DuplicatesWarning.text, MessageType.Warning, true);\n                    state.ShowDuplicatedFunctionsDetails = EditorGUILayout.Foldout(state.ShowDuplicatedFunctionsDetails, \"Show Details\");\n                    if (state.ShowDuplicatedFunctionsDetails)\n                    {\n                        string duplicatedFunctionDetails = \"Duplicated Functions: \\n\" + GetFormattedMethodsText(duplicates);\n                        GUILayout.Label(duplicatedFunctionDetails, EditorStyles.helpBox);\n                    }\n                }\n            }\n            else\n            {\n                EditorGUI.showMixedValue = !singleFunctionName;\n                string oldFunctionName = singleFunctionName ? firstEvent.functionName : \"\";\n                string functionName = EditorGUILayout.TextField(EditorGUIUtility.TrTextContent(\"Function\"), oldFunctionName).Replace(\" \", \"\");\n                if (functionName != oldFunctionName)\n                {\n                    foreach (var evt in data.selectedEvents)\n                    {\n                        evt.functionName = functionName;\n                    }\n                }\n                EditorGUI.showMixedValue = false;\n\n                if (singleFunctionName)\n                {\n                    DoEditRegularParameters(data.selectedEvents, typeof(AnimationEvent));\n                }\n                else\n                {\n                    using (new EditorGUI.DisabledScope(true))\n                    {\n                        AnimationEvent dummyEvent = new AnimationEvent();\n                        DoEditRegularParameters(new AnimationEvent[] { dummyEvent }, typeof(AnimationEvent));\n                    }\n                }\n            }\n\n            if (EditorGUI.EndChangeCheck())\n                SetData(awEvents, data);\n        }\n\n        static string GetFormattedMethodsText(List<AnimationMethodMap> methods)\n        {\n            string text = \"\";\n            foreach (AnimationMethodMap methodMap in methods)\n            {\n                text += string.Format(\"{0}.{1} ( {2} )\\n\", methodMap.sourceBehaviour.GetType().Name, methodMap.Name, GetTypeName(methodMap.parameterType));\n            }\n            text = text.Trim();\n            return text;\n        }\n\n        static string GetTypeName(Type t)\n        {\n            if (t == null)\n                return \"\";\n            if (t == typeof(int))\n                return \"int\";\n            if (t == typeof(float))\n                return \"float\";\n            if (t == typeof(string))\n                return \"string\";\n            if (t == typeof(bool))\n                return \"bool\";\n            return t.Name;\n        }\n\n        static string GetFormattedMethodName(AnimationMethodMap methodMap)\n        {\n            string targetName = methodMap.sourceBehaviour.GetType().Name;\n            string methodName = methodMap.Name;\n            string args = GetTypeName(methodMap.parameterType);\n\n            if (methodName.StartsWith(\"set_\") || methodName.StartsWith(\"get_\"))\n                return string.Format(\"{0}/Properties/{1} ( {2} )\", targetName, methodName, args);\n            else\n                return string.Format(\"{0}/Methods/{1} ( {2} )\", targetName, methodName, args);\n        }\n\n        public static void OnDisabledAnimationEvent()\n        {\n            AnimationEvent dummyEvent = new AnimationEvent();\n\n            using (new EditorGUI.DisabledScope(true))\n            {\n                dummyEvent.functionName = EditorGUILayout.TextField(EditorGUIUtility.TrTextContent(\"Function\"), dummyEvent.functionName);\n                DoEditRegularParameters(new AnimationEvent[] { dummyEvent }, typeof(AnimationEvent));\n            }\n        }\n\n        static Dictionary<Type, IReadOnlyList<AnimationMethodMap>> s_TypeAnimationMethodMapCache = new Dictionary<Type, IReadOnlyList<AnimationMethodMap>>();\n\n        static void CollectSupportedMethods(GameObject gameObject, List<AnimationMethodMap> supportedMethods, List<AnimationMethodMap> overloadedMethods, List<AnimationMethodMap> duplicatedMethods)\n        {\n            if (gameObject == null)\n                return;\n\n            MonoBehaviour[] behaviours = gameObject.GetComponents<MonoBehaviour>();\n\n            foreach (MonoBehaviour behaviour in behaviours)\n            {\n                if (behaviour == null)\n                    continue;\n\n                Type type = behaviour.GetType();\n                while (type != typeof(MonoBehaviour) && type != null)\n                {\n                    if (!s_TypeAnimationMethodMapCache.TryGetValue(type, out IReadOnlyList<AnimationMethodMap> validMethods))\n                    {\n                        var pendingValidMethods = new List<AnimationMethodMap>();\n                        MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly );\n                        for (int i = 0; i < methods.Length; i++)\n                        {\n                            MethodInfo method = methods[i];\n                            string name = method.Name;\n\n                            if (!IsSupportedMethodName(name))\n                                continue;\n\n                            ParameterInfo[] parameters = method.GetParameters();\n                            if (parameters.Length > 1)\n                                continue;\n\n                            Type parameterType = null;\n\n                            if (parameters.Length == 1)\n                            {\n                                parameterType = parameters[0].ParameterType;\n                                if (!(parameterType == typeof(string) ||\n                                      parameterType == typeof(float) ||\n                                      parameterType == typeof(int) ||\n                                      parameterType == typeof(AnimationEvent) ||\n                                      parameterType == typeof(UnityEngine.Object) ||\n                                      parameterType.IsSubclassOf(typeof(UnityEngine.Object)) ||\n                                      parameterType.IsEnum))\n                                    continue;\n                            }\n\n                            AnimationMethodMap newMethodMap = new AnimationMethodMap\n                            {\n                                sourceBehaviour = behaviour,\n                                methodInfo = method,\n                                parameterType = parameterType\n                            };\n\n                            newMethodMap.methodMenuPath = GetFormattedMethodName(newMethodMap);\n\n                            pendingValidMethods.Add(newMethodMap);\n                        }\n\n                        validMethods = pendingValidMethods.AsReadOnly();\n                        s_TypeAnimationMethodMapCache.Add(type, validMethods);\n                    }\n\n                    foreach (var method in validMethods)\n                    {\n                        // Since AnimationEvents only stores method name, it can't handle functions with multiple overloads.\n                        // or functions with the same name across multiple monobehaviours\n                        // Only retrieve first found method, and discard overloads and duplicate names.\n                        int existingMethodIndex = supportedMethods.FindIndex(m => m.Name == method.Name);\n                        if (existingMethodIndex != -1)\n                        {\n                            // The method is only ambiguous if it has a different signature to the one we saw before\n                            if (supportedMethods[existingMethodIndex].parameterType != method.parameterType)\n                            {\n                                overloadedMethods.Add(method);\n                            }\n                            // Otherwise, there is another monobehaviour with the same method name.\n                            else\n                            {\n                                duplicatedMethods.Add(method);\n                            }\n                        }\n                        else\n                        {\n                            supportedMethods.Add(method);\n                        }\n                    }\n\n                    type = type.BaseType;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Maps the methodInfo and paramter type of a considered animation method to a source monobeheaviour.\n        /// Mimics the structure of <see cref=\"UnityEditorInternal.UnityEventDrawer.ValidMethodMap\"/>\n        /// </summary>\n        struct AnimationMethodMap\n        {\n            public Object sourceBehaviour;\n            public MethodInfo methodInfo;\n            public Type parameterType;\n\n            // Used for caching\n            public string methodMenuPath;\n\n            public string Name => methodInfo?.Name ?? \"\";\n        }\n\n        public static string FormatEvent(GameObject root, AnimationEvent evt)\n        {\n            if (string.IsNullOrEmpty(evt.functionName))\n                return kNoneSelected;\n\n            if (!IsSupportedMethodName(evt.functionName))\n                return evt.functionName + kNotSupportedPostFix;\n\n            if (root == null)\n                return evt.functionName + kNotSupportedPostFix;\n\n            foreach (var behaviour in root.GetComponents<MonoBehaviour>())\n            {\n                if (behaviour == null) continue;\n\n                var type = behaviour.GetType();\n                if (type == typeof(MonoBehaviour) ||\n                    (type.BaseType != null && type.BaseType.Name == \"GraphBehaviour\"))\n                    continue;\n\n                MethodInfo method = null;\n                try\n                {\n                    method = type.GetMethod(evt.functionName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);\n                }\n                catch (AmbiguousMatchException)\n                {\n                }\n\n                if (method == null)\n                    continue;\n\n                var parameterTypes = method.GetParameters();\n                return evt.functionName + FormatEventArguments(parameterTypes, evt);\n            }\n\n            return evt.functionName + kNotSupportedPostFix;\n        }\n\n        private static void DoEditRegularParameters(AnimationEvent[] events, Type selectedParameter)\n        {\n            AnimationEvent firstEvent = events[0];\n\n            if (selectedParameter == typeof(AnimationEvent) || selectedParameter == typeof(float))\n            {\n                bool singleParamValue = Array.TrueForAll(events, evt => evt.floatParameter == firstEvent.floatParameter);\n\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = !singleParamValue;\n                float newValue = EditorGUILayout.FloatField(\"Float\", firstEvent.floatParameter);\n                EditorGUI.showMixedValue = false;\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    foreach (var evt in events)\n                        evt.floatParameter = newValue;\n                }\n            }\n\n            if (selectedParameter == typeof(AnimationEvent) || selectedParameter == typeof(int) || selectedParameter.IsEnum)\n            {\n                bool singleParamValue = Array.TrueForAll(events, evt => evt.intParameter == firstEvent.intParameter);\n\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = !singleParamValue;\n                int newValue = 0;\n                if (selectedParameter.IsEnum)\n                    newValue = EnumPopup(\"Enum\", selectedParameter, firstEvent.intParameter);\n                else\n                    newValue = EditorGUILayout.IntField(\"Int\", firstEvent.intParameter);\n                EditorGUI.showMixedValue = false;\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    foreach (var evt in events)\n                        evt.intParameter = newValue;\n                }\n            }\n\n            if (selectedParameter == typeof(AnimationEvent) || selectedParameter == typeof(string))\n            {\n                bool singleParamValue = Array.TrueForAll(events, evt => evt.stringParameter == firstEvent.stringParameter);\n\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = !singleParamValue;\n                string newValue = EditorGUILayout.TextField(\"String\", firstEvent.stringParameter);\n                EditorGUI.showMixedValue = false;\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    foreach (var evt in events)\n                        evt.stringParameter = newValue;\n                }\n            }\n\n            if (selectedParameter == typeof(AnimationEvent) || selectedParameter.IsSubclassOf(typeof(UnityEngine.Object)) || selectedParameter == typeof(UnityEngine.Object))\n            {\n                bool singleParamValue = Array.TrueForAll(events, evt => evt.objectReferenceParameter == firstEvent.objectReferenceParameter);\n\n                EditorGUI.BeginChangeCheck();\n                Type type = typeof(UnityEngine.Object);\n                if (selectedParameter != typeof(AnimationEvent))\n                    type = selectedParameter;\n\n                EditorGUI.showMixedValue = !singleParamValue;\n                bool allowSceneObjects = false;\n                Object newValue = EditorGUILayout.ObjectField(ObjectNames.NicifyVariableName(type.Name), firstEvent.objectReferenceParameter, type, allowSceneObjects);\n                EditorGUI.showMixedValue = false;\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    foreach (var evt in events)\n                        evt.objectReferenceParameter = newValue;\n                }\n            }\n        }\n\n        private static int EnumPopup(string label, Type enumType, int selected)\n        {\n            if (!enumType.IsEnum)\n                throw new Exception(\"parameter _enum must be of type System.Enum\");\n\n            string[] enumStrings = System.Enum.GetNames(enumType);\n            int i = System.Array.IndexOf(enumStrings, Enum.GetName(enumType, selected));\n\n            i = EditorGUILayout.Popup(label, i, enumStrings, EditorStyles.popup);\n\n            if (i == -1)\n                return selected;\n            else\n            {\n                System.Enum res = (System.Enum)Enum.Parse(enumType, enumStrings[i]);\n                return Convert.ToInt32(res);\n            }\n        }\n\n        private static bool IsSupportedMethodName(string name)\n        {\n            return name != \"Main\" && name != \"Start\" && name != \"Awake\" && name != \"Update\";\n        }\n\n        private static string FormatEventArguments(ParameterInfo[] paramTypes, AnimationEvent evt)\n        {\n            if (paramTypes.Length == 0)\n                return \" ( )\";\n\n            if (paramTypes.Length > 1)\n                return kNotSupportedPostFix;\n\n            var paramType = paramTypes[0].ParameterType;\n\n            if (paramType == typeof(string))\n                return \" ( \\\"\" + evt.stringParameter + \"\\\" )\";\n\n            if (paramType == typeof(float))\n                return \" ( \" + evt.floatParameter + \" )\";\n\n            if (paramType == typeof(int))\n                return \" ( \" + evt.intParameter + \" )\";\n\n            if (paramType.IsEnum)\n                return \" ( \" + paramType.Name + \".\" + Enum.GetName(paramType, evt.intParameter) + \" )\";\n\n            if (paramType == typeof(AnimationEvent))\n                return \" ( \"\n                    + evt.floatParameter + \" / \"\n                    + evt.intParameter + \" / \\\"\"\n                    + evt.stringParameter + \"\\\" / \"\n                    + (evt.objectReferenceParameter == null ? \"null\" : evt.objectReferenceParameter.name) + \" )\";\n\n            if (paramType.IsSubclassOf(typeof(UnityEngine.Object)) || paramType == typeof(UnityEngine.Object))\n                return \" ( \" + (evt.objectReferenceParameter == null ? \"null\" : evt.objectReferenceParameter.name) + \" )\";\n\n            return kNotSupportedPostFix;\n        }\n\n        private struct AnimationWindowEventData\n        {\n            public GameObject root;\n            public AnimationClip clip;\n            public AnimationClipInfoProperties clipInfo;\n\n            public AnimationEvent[] events;\n            public AnimationEvent[] selectedEvents;\n        }\n\n\n        // this are used so we don't alloc new lists on every call\n        static List<AnimationEvent> getDataSelectedEvents;\n        private static AnimationWindowEventData GetData(AnimationWindowEvent[] awEvents)\n        {\n            var data = new AnimationWindowEventData();\n            if (awEvents.Length == 0)\n                return data;\n\n            AnimationWindowEvent firstAwEvent = awEvents[0];\n            data.root = firstAwEvent.root;\n            data.clip = firstAwEvent.clip;\n            data.clipInfo = firstAwEvent.clipInfo;\n\n            if (data.clip != null)\n                data.events = AnimationUtility.GetAnimationEvents(data.clip);\n            else if (data.clipInfo != null)\n                data.events = data.clipInfo.GetEvents();\n\n            if (data.events != null)\n            {\n                getDataSelectedEvents ??= new List<AnimationEvent>();\n                getDataSelectedEvents.Clear();\n                foreach (var awEvent in awEvents)\n                {\n                    if (awEvent.eventIndex >= 0 && awEvent.eventIndex < data.events.Length)\n                        getDataSelectedEvents.Add(data.events[awEvent.eventIndex]);\n                }\n\n                data.selectedEvents = getDataSelectedEvents.ToArray();\n            }\n\n            return data;\n        }\n\n        private static void SetData(AnimationWindowEvent[] awEvents, AnimationWindowEventData data)\n        {\n            if (data.events == null)\n                return;\n\n            if (data.clip != null)\n            {\n                Undo.RegisterCompleteObjectUndo(data.clip, \"Animation Event Change\");\n                AnimationUtility.SetAnimationEvents(data.clip, data.events);\n            }\n            else if (data.clipInfo != null)\n            {\n                foreach (var awEvent in awEvents)\n                {\n                    if (awEvent.eventIndex >= 0 && awEvent.eventIndex < data.events.Length)\n                        data.clipInfo.SetEvent(awEvent.eventIndex, data.events[awEvent.eventIndex]);\n                }\n            }\n        }\n\n        [MenuItem(\"CONTEXT/AnimationWindowEvent/Reset\", secondaryPriority = 7)]\n        static void ResetValues(MenuCommand command)\n        {\n            AnimationWindowEvent awEvent = command.context as AnimationWindowEvent;\n            AnimationWindowEvent[] awEvents = new AnimationWindowEvent[] { awEvent };\n\n            AnimationWindowEventData data = GetData(awEvents);\n            if (data.events == null || data.selectedEvents == null || data.selectedEvents.Length == 0)\n                return;\n\n            foreach (var evt in data.selectedEvents)\n            {\n                evt.functionName = \"\";\n                evt.stringParameter = string.Empty;\n                evt.floatParameter = 0f;\n                evt.intParameter = 0;\n                evt.objectReferenceParameter = null;\n            }\n\n            SetData(awEvents, data);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchy.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing UnityEditor.IMGUI.Controls;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditorInternal\n{\n    [System.Serializable]\n    internal class AnimationWindowHierarchyState : TreeViewState\n    {\n        private List<int> m_TallInstanceIDs = new List<int>();\n\n        public bool GetTallMode(AnimationWindowHierarchyNode node)\n        {\n            return m_TallInstanceIDs.Contains(node.id);\n        }\n\n        public void SetTallMode(AnimationWindowHierarchyNode node, bool tallMode)\n        {\n            if (tallMode)\n                m_TallInstanceIDs.Add(node.id);\n            else\n                m_TallInstanceIDs.Remove(node.id);\n        }\n\n        public int GetTallInstancesCount()\n        {\n            return m_TallInstanceIDs.Count;\n        }\n\n        public void AddTallInstance(int id)\n        {\n            if (!m_TallInstanceIDs.Contains(id))\n                m_TallInstanceIDs.Add(id);\n        }\n    }\n\n    internal class AnimationWindowHierarchy\n    {\n        // Animation window shared state\n        private AnimationWindowState m_State;\n        private TreeViewController m_TreeView;\n        private AnimationWindowHierarchyGUI m_HierarchyGUI;\n\n        public Vector2 GetContentSize()\n        {\n            return m_TreeView.GetContentSize();\n        }\n\n        public Rect GetTotalRect()\n        {\n            return m_TreeView.GetTotalRect();\n        }\n\n        public AnimationWindowHierarchy(AnimationWindowState state, EditorWindow owner, Rect position)\n        {\n            m_State = state;\n            Init(owner, position);\n        }\n\n        public void OnGUI(Rect position)\n        {\n            m_TreeView.OnEvent();\n            m_TreeView.OnGUI(position, GUIUtility.GetControlID(FocusType.Keyboard));\n            m_HierarchyGUI.ReclaimPendingFieldFocus();\n        }\n\n        public void Init(EditorWindow owner, Rect rect)\n        {\n            if (m_State.hierarchyState == null)\n                m_State.hierarchyState = new AnimationWindowHierarchyState();\n\n            m_TreeView = new TreeViewController(owner, m_State.hierarchyState);\n            m_State.hierarchyData = new AnimationWindowHierarchyDataSource(m_TreeView, m_State);\n            m_HierarchyGUI = new AnimationWindowHierarchyGUI(m_TreeView, m_State);\n            m_TreeView.Init(rect,\n                m_State.hierarchyData,\n                m_HierarchyGUI,\n                null\n            );\n\n            m_TreeView.deselectOnUnhandledMouseDown = true;\n            m_TreeView.selectionChangedCallback += m_State.OnHierarchySelectionChanged;\n\n            m_TreeView.ReloadData();\n        }\n\n        virtual internal bool IsRenamingNodeAllowed(TreeViewItem node) { return true; }\n\n        public bool IsIDVisible(int id)\n        {\n            if (m_TreeView == null)\n                return false;\n\n            var rows = m_TreeView.data.GetRows();\n            return TreeViewController.GetIndexOfID(rows, id) >= 0;\n        }\n\n        public void EndNameEditing(bool acceptChanges)\n        {\n            m_TreeView.EndNameEditing(acceptChanges);\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing System.Collections.Generic;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewUtility = UnityEditor.IMGUI.Controls.TreeViewUtility<int>;\nusing TreeViewDataSource = UnityEditor.IMGUI.Controls.TreeViewDataSource<int>;\n\n\nnamespace UnityEditorInternal\n{\n    internal class AnimationWindowHierarchyDataSource : TreeViewDataSource\n    {\n        // Animation window shared state\n        private AnimationWindowState state { get; set; }\n        public bool showAll { get; set; }\n\n        public AnimationWindowHierarchyDataSource(TreeViewController treeView, AnimationWindowState animationWindowState)\n            : base(treeView)\n        {\n            state = animationWindowState;\n        }\n\n        private void SetupRootNodeSettings()\n        {\n            showRootItem = false;\n            rootIsCollapsable = false;\n            SetExpanded(m_RootItem, true);\n        }\n\n        private AnimationWindowHierarchyNode GetEmptyRootNode()\n        {\n            return new AnimationWindowHierarchyNode(0, -1, null, null, \"\", \"\", \"root\");\n        }\n\n        public override void FetchData()\n        {\n            m_RootItem = GetEmptyRootNode();\n            SetupRootNodeSettings();\n            m_NeedRefreshRows = true;\n\n            if (state.selection.disabled)\n            {\n                root.children = null;\n                return;\n            }\n\n            List<AnimationWindowHierarchyNode> childNodes = new List<AnimationWindowHierarchyNode>();\n\n            if (state.filteredCurves.Count > 0)\n            {\n                AnimationWindowHierarchyMasterNode masterNode = new AnimationWindowHierarchyMasterNode();\n                masterNode.curves = state.filteredCurves.ToArray();\n\n                childNodes.Add(masterNode);\n            }\n\n            childNodes.AddRange(CreateTreeFromCurves());\n            childNodes.Add(new AnimationWindowHierarchyAddButtonNode());\n\n            TreeViewUtility.SetChildParentReferences(new List<TreeViewItem>(childNodes.ToArray()), root);\n        }\n\n        public override bool IsRenamingItemAllowed(TreeViewItem item)\n        {\n            if (item is AnimationWindowHierarchyAddButtonNode || item is AnimationWindowHierarchyMasterNode || item is AnimationWindowHierarchyClipNode)\n                return false;\n\n            return (item as AnimationWindowHierarchyNode).path.Length != 0;\n        }\n\n        public List<AnimationWindowHierarchyNode> CreateTreeFromCurves()\n        {\n            List<AnimationWindowHierarchyNode> nodes = new List<AnimationWindowHierarchyNode>();\n            List<AnimationWindowCurve> singlePropertyCurves = new List<AnimationWindowCurve>();\n\n            List<AnimationWindowCurve> curves = state.filteredCurves;\n            AnimationWindowHierarchyNode parentNode = (AnimationWindowHierarchyNode)m_RootItem;\n            SerializedObject so = null;\n\n            for (int i = 0; i < curves.Count; i++)\n            {\n                AnimationWindowCurve curve = curves[i];\n\n                if (!state.ShouldShowCurve(curve))\n                    continue;\n\n                AnimationWindowCurve nextCurve = i < curves.Count - 1 ? curves[i + 1] : null;\n\n                if (curve.isSerializeReferenceCurve && state.activeRootGameObject != null)\n                {\n                    var animatedObject = AnimationUtility.GetAnimatedObject(state.activeRootGameObject, curve.binding);\n                    if (animatedObject != null && (so == null || so.targetObject != animatedObject))\n                        so = new SerializedObject(animatedObject);\n                }\n\n                singlePropertyCurves.Add(curve);\n\n                bool areSameGroup = nextCurve != null && AnimationWindowUtility.GetPropertyGroupName(nextCurve.propertyName) == AnimationWindowUtility.GetPropertyGroupName(curve.propertyName);\n                bool areSamePathAndType = nextCurve != null && curve.path.Equals(nextCurve.path) && curve.type == nextCurve.type;\n\n                // We expect curveBindings to come sorted by propertyname\n                // So we compare curve vs nextCurve. If its different path or different group (think \"scale.xyz\" as group), then we know this is the last element of such group.\n                if (i == curves.Count - 1 || !areSameGroup || !areSamePathAndType)\n                {\n                    if (singlePropertyCurves.Count > 1)\n                        nodes.Add(AddPropertyGroupToHierarchy(singlePropertyCurves.ToArray(), parentNode, so));\n                    else\n                        nodes.Add(AddPropertyToHierarchy(singlePropertyCurves[0], parentNode, so));\n                    singlePropertyCurves.Clear();\n                }\n            }\n\n            return nodes;\n        }\n\n        private AnimationWindowHierarchyPropertyGroupNode AddPropertyGroupToHierarchy(AnimationWindowCurve[] curves, AnimationWindowHierarchyNode parentNode, SerializedObject so)\n        {\n            List<AnimationWindowHierarchyNode> childNodes = new List<AnimationWindowHierarchyNode>();\n\n            System.Type animatableObjectType = curves[0].type;\n            AnimationWindowHierarchyPropertyGroupNode node = new AnimationWindowHierarchyPropertyGroupNode(animatableObjectType, 0, AnimationWindowUtility.GetPropertyGroupName(curves[0].propertyName), curves[0].path, parentNode, AnimationWindowUtility.GetNicePropertyGroupDisplayName(curves[0].binding, so));\n\n            node.icon = GetIcon(curves[0].binding);\n\n            node.indent = curves[0].depth;\n            node.curves = curves;\n\n            foreach (AnimationWindowCurve curve in curves)\n            {\n                AnimationWindowHierarchyPropertyNode childNode = AddPropertyToHierarchy(curve, node, so);\n                // For child nodes we do not want to display the type in front (It is already shown by the group node)\n                childNode.displayName = AnimationWindowUtility.GetPropertyDisplayName(childNode.propertyName);\n                childNodes.Add(childNode);\n            }\n\n            TreeViewUtility.SetChildParentReferences(new List<TreeViewItem>(childNodes.ToArray()), node);\n            return node;\n        }\n\n        private AnimationWindowHierarchyPropertyNode AddPropertyToHierarchy(AnimationWindowCurve curve, AnimationWindowHierarchyNode parentNode, SerializedObject so)\n        {\n            AnimationWindowHierarchyPropertyNode node = new AnimationWindowHierarchyPropertyNode(curve.type, 0, curve.propertyName, curve.path, parentNode, curve.binding, curve.isPPtrCurve, AnimationWindowUtility.GetNicePropertyDisplayName(curve.binding, so));\n\n            if (parentNode.icon != null)\n                node.icon = parentNode.icon;\n            else\n                node.icon = GetIcon(curve.binding);\n\n            node.indent = curve.depth;\n            node.curves = new[] { curve };\n            return node;\n        }\n\n        public Texture2D GetIcon(EditorCurveBinding curveBinding)\n        {\n            return AssetPreview.GetMiniTypeThumbnail(curveBinding.type);\n        }\n\n        public void UpdateSerializeReferenceCurvesArrayNiceDisplayName()\n        {\n            if (state.activeRootGameObject == null)\n                return;\n\n            //This is required in the case that there might have been a topological change\n            //leading to a different display name(topological path)\n            SerializedObject so = null;\n            foreach (AnimationWindowHierarchyNode hierarchyNode in GetRows())\n            {\n                if (hierarchyNode.curves != null)\n                {\n                    foreach (var curve in hierarchyNode.curves)\n                    {\n                        if (curve.isSerializeReferenceCurve && hierarchyNode.displayName.Contains(\".Array.data[\"))\n                        {\n                            var animatedObject = AnimationUtility.GetAnimatedObject(state.activeRootGameObject, curve.binding);\n                            if (animatedObject != null && (so == null || so.targetObject != animatedObject))\n                                so = new SerializedObject(animatedObject);\n\n                            hierarchyNode.displayName = AnimationWindowUtility.GetNicePropertyDisplayName(curve.binding, so);\n                        }\n                    }\n                }\n            }\n\n        }\n\n        public void UpdateData()\n        {\n            m_TreeView.ReloadData();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\n\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewGUI = UnityEditor.IMGUI.Controls.TreeViewGUI<int>;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\n\nnamespace UnityEditorInternal\n{\n    internal class AnimationWindowHierarchyGUI : TreeViewGUI\n    {\n        public AnimationWindowState state { get; set; }\n\n        readonly GUIContent k_AnimatePropertyLabel = EditorGUIUtility.TrTextContent(\"Add Property\");\n\n        private GUIStyle m_AnimationRowEvenStyle;\n        private GUIStyle m_AnimationRowOddStyle;\n        private GUIStyle m_AnimationSelectionTextField;\n        private GUIStyle m_AnimationCurveDropdown;\n        private bool m_StyleInitialized;\n        private AnimationWindowHierarchyNode m_RenamedNode;\n        private Color m_LightSkinPropertyTextColor = new Color(.35f, .35f, .35f);\n        private Color m_PhantomCurveColor = new Color(0f, 153f / 255f, 153f / 255f);\n\n        private int[] m_HierarchyItemFoldControlIDs;\n        private int[] m_HierarchyItemValueControlIDs;\n        private int[] m_HierarchyItemButtonControlIDs;\n\n        private bool m_NeedsToReclaimFieldFocus;\n        private int m_FieldToReclaimFocus;\n\n        private const float k_RowRightOffset = 10;\n        private const float k_ValueFieldDragWidth = 15;\n        private const float k_ValueFieldWidth = 80;\n        private const float k_ValueFieldOffsetFromRightSide = 100;\n        private const float k_ColorIndicatorTopMargin = 3;\n        public static readonly float k_DopeSheetRowHeight = EditorGUI.kSingleLineHeight;\n        public static readonly float k_DopeSheetRowHeightTall = k_DopeSheetRowHeight * 2f;\n        public const float k_AddCurveButtonNodeHeight = 40f;\n        public const float k_RowBackgroundColorBrightness = 0.28f;\n        private const float k_SelectedPhantomCurveColorMultiplier = 1.4f;\n        private const float k_CurveColorIndicatorIconSize = 11;\n\n        private readonly static Color k_KeyColorInDopesheetMode = new Color(0.7f, 0.7f, 0.7f, 1);\n        private readonly static Color k_KeyColorForNonCurves = new Color(0.7f, 0.7f, 0.7f, 0.5f);\n        private readonly static Color k_LeftoverCurveColor = Color.yellow;\n\n        private static readonly string k_DefaultValue = L10n.Tr(\" (Default Value)\");\n        private static readonly string k_TransformPosition = L10n.Tr(\"Transform position, rotation and scale can't be partially animated. This value will be animated to the default value\");\n        private static readonly string k_Missing = L10n.Tr(\" (Missing!)\");\n        private static readonly string k_GameObjectComponentMissing = L10n.Tr(\"The GameObject or Component is missing ({0})\");\n        private static readonly string k_DuplicateGameObjectName = L10n.Tr(\" (Duplicate GameObject name!)\");\n        private static readonly string k_TargetForCurveIsAmbigous = L10n.Tr(\"Target for curve is ambiguous since there are multiple GameObjects with same name ({0})\");\n        private static readonly string k_RemoveProperties = L10n.Tr(\"Remove Properties\");\n        private static readonly string k_RemoveProperty = L10n.Tr(\"Remove Property\");\n        private static readonly string k_AddKey = L10n.Tr(\"Add Key\");\n        private static readonly string k_DeleteKey = L10n.Tr(\"Delete Key\");\n        private static readonly string k_RemoveCurve = L10n.Tr(\"Remove Curve\");\n\n        internal static int s_WasInsideValueRectFrame = -1;\n\n        public AnimationWindowHierarchyGUI(TreeViewController treeView, AnimationWindowState state)\n            : base(treeView)\n        {\n            this.state = state;\n            InitStyles();\n        }\n\n        protected void InitStyles()\n        {\n            if (!m_StyleInitialized)\n            {\n                m_AnimationRowEvenStyle = \"AnimationRowEven\";\n                m_AnimationRowOddStyle = \"AnimationRowOdd\";\n                m_AnimationSelectionTextField = \"AnimationSelectionTextField\";\n\n                lineStyle = Styles.lineStyle;\n                lineStyle.padding.left = 0;\n\n                m_AnimationCurveDropdown = \"AnimPropDropdown\";\n\n                m_StyleInitialized = true;\n            }\n        }\n\n        protected void DoNodeGUI(Rect rect, AnimationWindowHierarchyNode node, bool selected, bool focused, int row)\n        {\n            InitStyles();\n\n            if (node is AnimationWindowHierarchyMasterNode)\n                return;\n\n            float indent = k_BaseIndent + (node.depth + node.indent) * k_IndentWidth;\n\n            if (node is AnimationWindowHierarchyAddButtonNode)\n            {\n                if (Event.current.type == EventType.MouseMove && s_WasInsideValueRectFrame >= 0)\n                {\n                    if (s_WasInsideValueRectFrame >= Time.frameCount - 1)\n                        Event.current.Use();\n                    else\n                        s_WasInsideValueRectFrame = -1;\n                }\n\n                using (new EditorGUI.DisabledScope(!state.selection.canAddCurves))\n                {\n                    DoAddCurveButton(rect, node, row);\n                }\n            }\n            else\n            {\n                DoRowBackground(rect, row);\n                DoIconAndName(rect, node, selected, focused, indent);\n                DoFoldout(node, rect, indent, row);\n\n                bool enabled = false;\n                if (node.curves != null)\n                {\n                    enabled = !Array.Exists(node.curves, curve => curve.animationIsEditable == false);\n                }\n\n                using (new EditorGUI.DisabledScope(!enabled))\n                {\n                    DoValueField(rect, node, row);\n                }\n                DoCurveDropdown(rect, node, row, enabled);\n                HandleContextMenu(rect, node, enabled);\n                DoCurveColorIndicator(rect, node);\n            }\n            EditorGUIUtility.SetIconSize(Vector2.zero);\n        }\n\n        public override void BeginRowGUI()\n        {\n            base.BeginRowGUI();\n            HandleDelete();\n\n            // Reserve unique control ids.\n            // This is required to avoid changing control ids mapping as we scroll in the tree view\n            // and change items visibility.  Hopefully, we should be able to remove it entirely if we\n            // isolate the animation window layouts in separate IMGUIContainers...\n            int rowCount = m_TreeView.data.rowCount;\n            m_HierarchyItemFoldControlIDs = new int[rowCount];\n            m_HierarchyItemValueControlIDs = new int[rowCount];\n            m_HierarchyItemButtonControlIDs = new int[rowCount];\n            for (int i = 0; i < rowCount; ++i)\n            {\n                var propertyNode  = m_TreeView.data.GetItem(i) as AnimationWindowHierarchyPropertyNode;\n                if (propertyNode != null && !propertyNode.isPptrNode)\n                    m_HierarchyItemValueControlIDs[i] = GUIUtility.GetControlID(FocusType.Keyboard);\n                else\n                    m_HierarchyItemValueControlIDs[i] = 0; // not needed.\n\n                m_HierarchyItemFoldControlIDs[i] = GUIUtility.GetControlID(FocusType.Passive);\n                m_HierarchyItemButtonControlIDs[i] = GUIUtility.GetControlID(FocusType.Passive);\n            }\n        }\n\n        private void DoAddCurveButton(Rect rect, AnimationWindowHierarchyNode node, int row)\n        {\n            const int k_ButtonWidth = 230;\n            float xMargin = (rect.width - k_ButtonWidth) / 2f;\n            float yMargin = 10f;\n\n            Rect rectWithMargin = new Rect(rect.xMin + xMargin, rect.yMin + yMargin, rect.width - xMargin * 2f, rect.height - yMargin * 2f);\n\n            // case 767863.\n            // This control id is unique to the hierarchy node it refers to.\n            // The tree view only renders the elements that are visible, and will cause\n            // the control id counter to shift when scrolling through the view.\n            if (DoTreeViewButton(m_HierarchyItemButtonControlIDs[row], rectWithMargin, k_AnimatePropertyLabel, GUI.skin.button))\n            {\n                if (AddCurvesPopup.ShowAtPosition(rectWithMargin, state, OnNewCurveAdded))\n                {\n                    GUIUtility.ExitGUI();\n                }\n            }\n        }\n\n        private void OnNewCurveAdded(AddCurvesPopupPropertyNode node)\n        {\n        }\n\n        private void DoRowBackground(Rect rect, int row)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            // Different background for even rows\n            if (row % 2 == 0)\n                m_AnimationRowEvenStyle.Draw(rect, false, false, false, false);\n            else\n                m_AnimationRowOddStyle.Draw(rect, false, false, false, false);\n        }\n\n        // Draw foldout (after text content above to ensure drop down icon is rendered above selection highlight)\n        private void DoFoldout(AnimationWindowHierarchyNode node, Rect rect, float indent, int row)\n        {\n            if (m_TreeView.data.IsExpandable(node))\n            {\n                Rect toggleRect = rect;\n                toggleRect.x = indent;\n                toggleRect.width = foldoutStyleWidth;\n                EditorGUI.BeginChangeCheck();\n                bool newExpandedValue = GUI.Toggle(toggleRect, m_HierarchyItemFoldControlIDs[row], m_TreeView.data.IsExpanded(node), GUIContent.none, foldoutStyle);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    if (Event.current.alt)\n                        m_TreeView.data.SetExpandedWithChildren(node, newExpandedValue);\n                    else\n                        m_TreeView.data.SetExpanded(node, newExpandedValue);\n                }\n            }\n            else\n            {\n                AnimationWindowHierarchyPropertyNode hierarchyPropertyNode = node as AnimationWindowHierarchyPropertyNode;\n                AnimationWindowHierarchyState hierarchyState = m_TreeView.state as AnimationWindowHierarchyState;\n\n                if (hierarchyPropertyNode != null && hierarchyPropertyNode.isPptrNode)\n                {\n                    Rect toggleRect = rect;\n                    toggleRect.x = indent;\n                    toggleRect.width = foldoutStyleWidth;\n\n                    EditorGUI.BeginChangeCheck();\n                    bool tallMode = hierarchyState.GetTallMode(hierarchyPropertyNode);\n                    tallMode = GUI.Toggle(toggleRect, m_HierarchyItemFoldControlIDs[row], tallMode, GUIContent.none, foldoutStyle);\n                    if (EditorGUI.EndChangeCheck())\n                        hierarchyState.SetTallMode(hierarchyPropertyNode, tallMode);\n                }\n            }\n        }\n\n        private void DoIconAndName(Rect rect, AnimationWindowHierarchyNode node, bool selected, bool focused, float indent)\n        {\n            EditorGUIUtility.SetIconSize(new Vector2(13, 13));   // If not set we see icons scaling down if text is being cropped\n\n            // TODO: All this is horrible. SHAME FIX!\n            if (Event.current.type == EventType.Repaint)\n            {\n                if (selected)\n                    selectionStyle.Draw(rect, false, false, true, focused);\n\n                // Leave some space for the value field that comes after.\n                if (node is AnimationWindowHierarchyPropertyNode)\n                    rect.width -= k_ValueFieldOffsetFromRightSide + 2;\n\n                bool isLeftOverCurve = AnimationWindowUtility.IsNodeLeftOverCurve(state, node);\n                bool isAmbiguous = AnimationWindowUtility.IsNodeAmbiguous(node);\n                bool isPhantom = AnimationWindowUtility.IsNodePhantom(node);\n\n                string warningText = \"\";\n                string tooltipText = \"\";\n                if (isPhantom)\n                {\n                    warningText = k_DefaultValue;\n                    tooltipText = k_TransformPosition;\n                }\n                if (isLeftOverCurve)\n                {\n                    warningText = k_Missing;\n                    tooltipText = string.Format(k_GameObjectComponentMissing, node.path);\n                }\n                if (isAmbiguous)\n                {\n                    warningText = k_DuplicateGameObjectName;\n                    tooltipText = string.Format(k_TargetForCurveIsAmbigous, node.path);\n                }\n\n                Color oldColor = lineStyle.normal.textColor;\n                Color textColor = oldColor;\n                if (node.depth == 0)\n                {\n                    string nodePrefix = \"\";\n                    if (node.curves.Length > 0)\n                    {\n                        AnimationWindowSelectionItem selectionBinding = node.curves[0].selectionBinding;\n                        string gameObjectName = GetGameObjectName(selectionBinding != null ? selectionBinding.rootGameObject : null, node.path);\n                        nodePrefix = string.IsNullOrEmpty(gameObjectName) ? \"\" : gameObjectName + \" : \";\n                    }\n\n                    Styles.content = new GUIContent(nodePrefix + node.displayName + warningText, GetIconForItem(node), tooltipText);\n\n                    textColor = EditorGUIUtility.isProSkin ? Color.gray * 1.35f : Color.black;\n                }\n                else\n                {\n                    Styles.content = new GUIContent(node.displayName + warningText, GetIconForItem(node), tooltipText);\n\n                    textColor = EditorGUIUtility.isProSkin ? Color.gray : m_LightSkinPropertyTextColor;\n\n                    var phantomColor = selected ? m_PhantomCurveColor * k_SelectedPhantomCurveColorMultiplier : m_PhantomCurveColor;\n                    textColor = isPhantom ? phantomColor : textColor;\n                }\n                textColor = isLeftOverCurve || isAmbiguous ? k_LeftoverCurveColor : textColor;\n                SetStyleTextColor(lineStyle, textColor);\n\n                rect.xMin += (int)(indent + foldoutStyleWidth + lineStyle.margin.left);\n                rect.yMin = rect.y + (rect.height - EditorGUIUtility.singleLineHeight) / 2;\n                GUI.Label(rect, Styles.content, lineStyle);\n\n                SetStyleTextColor(lineStyle, oldColor);\n            }\n\n            if (IsRenaming(node.id) && Event.current.type != EventType.Layout)\n                GetRenameOverlay().editFieldRect = new Rect(rect.x + k_IndentWidth, rect.y, rect.width - k_IndentWidth - 1, rect.height);\n        }\n\n        private string GetGameObjectName(GameObject rootGameObject, string path)\n        {\n            if (string.IsNullOrEmpty(path))\n                return rootGameObject != null ? rootGameObject.name : \"\";\n\n            string[] splits = path.Split('/');\n            return splits[splits.Length - 1];\n        }\n\n        private void DoValueField(Rect rect, AnimationWindowHierarchyNode node, int row)\n        {\n            bool curvesChanged = false;\n\n            if (node is AnimationWindowHierarchyPropertyNode)\n            {\n                AnimationWindowCurve[] curves = node.curves;\n                if (curves == null || curves.Length == 0)\n                    return;\n\n                // We do valuefields for dopelines that only have single curve\n                AnimationWindowCurve curve = curves[0];\n                object value = CurveBindingUtility.GetCurrentValue(state, curve);\n\n                if (!curve.isPPtrCurve)\n                {\n                    Rect valueFieldDragRect = new Rect(rect.xMax - k_ValueFieldOffsetFromRightSide - k_ValueFieldDragWidth, rect.y, k_ValueFieldDragWidth, rect.height);\n                    Rect valueFieldRect = new Rect(rect.xMax - k_ValueFieldOffsetFromRightSide, rect.y, k_ValueFieldWidth, rect.height);\n\n                    if (Event.current.type == EventType.MouseMove && valueFieldRect.Contains(Event.current.mousePosition))\n                        s_WasInsideValueRectFrame = Time.frameCount;\n\n                    EditorGUI.BeginChangeCheck();\n\n                    if (curve.valueType == typeof(bool))\n                    {\n                        value = GUI.Toggle(valueFieldRect, m_HierarchyItemValueControlIDs[row], Convert.ToSingle(value) != 0f, GUIContent.none, EditorStyles.toggle) ? 1f : 0f;\n                    }\n                    else\n                    {\n                        int id = m_HierarchyItemValueControlIDs[row];\n                        bool enterInTextField = (EditorGUIUtility.keyboardControl == id\n                            && EditorGUIUtility.editingTextField\n                            && Event.current.type == EventType.KeyDown\n                            && (Event.current.character == '\\n' || (int)Event.current.character == 3));\n\n                        // Force back keyboard focus to float field editor when editing it since the TreeView forces keyboard focus on itself at mouse down.\n                        // The focus will be reclaimed after the TreeViewController.OnGUI call.\n                        if (EditorGUI.s_RecycledEditor.controlID == id && Event.current.type == EventType.MouseDown && valueFieldRect.Contains(Event.current.mousePosition))\n                        {\n                            m_NeedsToReclaimFieldFocus = true;\n                            m_FieldToReclaimFocus = id;\n                        }\n\n                        if (curve.isDiscreteCurve)\n                        {\n                            value = EditorGUI.DoIntField(EditorGUI.s_RecycledEditor,\n                                valueFieldRect,\n                                valueFieldDragRect,\n                                id,\n                                Convert.ToInt32(value),\n                                EditorGUI.kIntFieldFormatString,\n                                m_AnimationSelectionTextField,\n                                true,\n                                0);\n                            if (enterInTextField)\n                            {\n                                GUI.changed = true;\n                                Event.current.Use();\n                            }\n                        }\n                        else\n                        {\n                            value = EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor,\n                                valueFieldRect,\n                                valueFieldDragRect,\n                                id,\n                                Convert.ToSingle(value),\n                                \"g5\",\n                                m_AnimationSelectionTextField,\n                                true);\n                            if (enterInTextField)\n                            {\n                                GUI.changed = true;\n                                Event.current.Use();\n                            }\n\n                            var floatValue = Convert.ToSingle(value);\n                            if (float.IsInfinity(floatValue) || float.IsNaN(floatValue))\n                                value = 0f;\n                        }\n                    }\n\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        string undoLabel = \"Edit Key\";\n\n                        AnimationKeyTime newAnimationKeyTime = AnimationKeyTime.Time(state.currentTime, curve.clip.frameRate);\n                        AnimationWindowUtility.AddKeyframeToCurve(curve, value, curve.valueType, newAnimationKeyTime);\n\n                        state.SaveCurve(curve.clip, curve, undoLabel);\n                        curvesChanged = true;\n                    }\n                }\n            }\n\n            if (curvesChanged)\n            {\n                //Fix for case 1382193: Stop recording any candidates if a property value field is modified\n                if (AnimationMode.IsRecordingCandidates())\n                    state.ClearCandidates();\n\n                state.ResampleAnimation();\n            }\n        }\n\n        internal void ReclaimPendingFieldFocus()\n        {\n            if (m_NeedsToReclaimFieldFocus)\n            {\n                GUIUtility.keyboardControl = m_FieldToReclaimFocus;\n                m_NeedsToReclaimFieldFocus = false;\n            }\n        }\n\n        private bool DoTreeViewButton(int id, Rect position, GUIContent content, GUIStyle style)\n        {\n            Event evt = Event.current;\n            EventType type = evt.GetTypeForControl(id);\n            switch (type)\n            {\n                case EventType.Repaint:\n                    style.Draw(position, content, id, false, position.Contains(evt.mousePosition));\n                    break;\n                case EventType.MouseDown:\n                    if (position.Contains(evt.mousePosition) && evt.button == 0)\n                    {\n                        GUIUtility.hotControl = id;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n\n                        if (position.Contains(evt.mousePosition))\n                        {\n                            return true;\n                        }\n                    }\n                    break;\n            }\n            return false;\n        }\n\n        private void DoCurveDropdown(Rect rect, AnimationWindowHierarchyNode node, int row, bool enabled)\n        {\n            rect = new Rect(\n                rect.xMax - k_RowRightOffset - 12,\n                rect.yMin + 2 + (rect.height - EditorGUIUtility.singleLineHeight) / 2,\n                22, 12);\n\n            // case 767863.\n            // This control id is unique to the hierarchy node it refers to.\n            // The tree view only renders the elements that are visible, and will cause\n            // the control id counter to shift when scrolling through the view.\n            if (DoTreeViewButton(m_HierarchyItemButtonControlIDs[row], rect, GUIContent.none, m_AnimationCurveDropdown))\n            {\n                state.SelectHierarchyItem(node.id, false, false);\n                GenericMenu menu = GenerateMenu(new AnimationWindowHierarchyNode[] { node }.ToList(), enabled);\n                menu.DropDown(rect);\n                Event.current.Use();\n            }\n        }\n\n        private void DoCurveColorIndicator(Rect rect, AnimationWindowHierarchyNode node)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            Color originalColor = GUI.color;\n\n            if (!state.showCurveEditor)\n                GUI.color = k_KeyColorInDopesheetMode;\n            else if (node.curves.Length == 1 && !node.curves[0].isPPtrCurve)\n                GUI.color = CurveUtility.GetPropertyColor(node.curves[0].binding.propertyName);\n            else\n                GUI.color = k_KeyColorForNonCurves;\n\n            bool hasKey = false;\n            if (state.previewing)\n            {\n                foreach (var curve in node.curves)\n                {\n                    if (curve.keyframes.Any(key => state.time.ContainsTime(key.time)))\n                    {\n                        hasKey = true;\n                    }\n                }\n            }\n            Texture icon = hasKey ? CurveUtility.GetIconKey() : CurveUtility.GetIconCurve();\n            rect = new Rect(rect.xMax - k_RowRightOffset - (k_CurveColorIndicatorIconSize / 2) - 5, rect.yMin + k_ColorIndicatorTopMargin + (rect.height - EditorGUIUtility.singleLineHeight) / 2, k_CurveColorIndicatorIconSize, k_CurveColorIndicatorIconSize);\n            GUI.DrawTexture(rect, icon, ScaleMode.ScaleToFit, true, 1);\n\n            GUI.color = originalColor;\n        }\n\n        private void HandleDelete()\n        {\n            if (m_TreeView.HasFocus())\n            {\n                switch (Event.current.type)\n                {\n                    case EventType.ExecuteCommand:\n                        if ((Event.current.commandName == EventCommandNames.SoftDelete || Event.current.commandName == EventCommandNames.Delete))\n                        {\n                            if (Event.current.type == EventType.ExecuteCommand)\n                                RemoveCurvesFromSelectedNodes();\n                            Event.current.Use();\n                        }\n                        break;\n\n                    case EventType.KeyDown:\n                        if (Event.current.keyCode == KeyCode.Backspace || Event.current.keyCode == KeyCode.Delete)\n                        {\n                            RemoveCurvesFromSelectedNodes();\n                            Event.current.Use();\n                        }\n                        break;\n                }\n            }\n        }\n\n        private void HandleContextMenu(Rect rect, AnimationWindowHierarchyNode node, bool enabled)\n        {\n            if (Event.current.type != EventType.ContextClick)\n                return;\n\n            if (rect.Contains(Event.current.mousePosition))\n            {\n                state.SelectHierarchyItem(node.id, true, true);\n                //state.animationWindow.RefreshShownCurves (true);\n                GenerateMenu(state.selectedHierarchyNodes, enabled).ShowAsContext();\n                Event.current.Use();\n            }\n        }\n\n        private GenericMenu GenerateMenu(List<AnimationWindowHierarchyNode> interactedNodes, bool enabled)\n        {\n            List<AnimationWindowCurve> curves = GetCurvesAffectedByNodes(interactedNodes, false);\n            // Linked curves are like regular affected curves but always include transform siblings\n            List<AnimationWindowCurve> linkedCurves = GetCurvesAffectedByNodes(interactedNodes, true);\n\n            bool forceGroupRemove = curves.Count == 1 ? AnimationWindowUtility.ForceGrouping(curves[0].binding) : false;\n\n            GenericMenu menu = new GenericMenu();\n\n            // Remove curves\n            GUIContent removePropertyContent = new GUIContent(curves.Count > 1 || forceGroupRemove ? k_RemoveProperties : k_RemoveProperty);\n            if (!enabled)\n                menu.AddDisabledItem(removePropertyContent);\n            else\n                menu.AddItem(removePropertyContent, false, RemoveCurvesFromSelectedNodes);\n\n            // Change rotation interpolation\n            bool showInterpolation = true;\n            EditorCurveBinding[] curveBindings = new EditorCurveBinding[linkedCurves.Count];\n            for (int i = 0; i < linkedCurves.Count; i++)\n                curveBindings[i] = linkedCurves[i].binding;\n            RotationCurveInterpolation.Mode rotationInterpolation = GetRotationInterpolationMode(curveBindings);\n            if (rotationInterpolation == RotationCurveInterpolation.Mode.Undefined)\n            {\n                showInterpolation = false;\n            }\n            else\n            {\n                foreach (var node in interactedNodes)\n                {\n                    if (!(node is AnimationWindowHierarchyPropertyGroupNode))\n                        showInterpolation = false;\n                }\n            }\n            if (showInterpolation)\n            {\n                string legacyWarning = state.activeAnimationClip.legacy ? \" (Not fully supported in Legacy)\" : \"\";\n                GenericMenu.MenuFunction2 nullMenuFunction2 = null;\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Interpolation/Euler Angles\" + legacyWarning), rotationInterpolation == RotationCurveInterpolation.Mode.RawEuler, enabled ? ChangeRotationInterpolation : nullMenuFunction2, RotationCurveInterpolation.Mode.RawEuler);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Interpolation/Euler Angles (Quaternion)\"), rotationInterpolation == RotationCurveInterpolation.Mode.Baked, enabled ? ChangeRotationInterpolation : nullMenuFunction2, RotationCurveInterpolation.Mode.Baked);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Interpolation/Quaternion\"), rotationInterpolation == RotationCurveInterpolation.Mode.NonBaked, enabled ? ChangeRotationInterpolation : nullMenuFunction2, RotationCurveInterpolation.Mode.NonBaked);\n            }\n\n            // Menu items that are only applicaple when in animation mode:\n            if (state.previewing)\n            {\n                menu.AddSeparator(\"\");\n\n                bool allHaveKeys = true;\n                bool noneHaveKeys = true;\n                foreach (AnimationWindowCurve curve in curves)\n                {\n                    bool curveHasKey = curve.HasKeyframe(state.time);\n                    if (!curveHasKey)\n                        allHaveKeys = false;\n                    else\n                        noneHaveKeys = false;\n                }\n\n                string str;\n\n                str = k_AddKey;\n                if (allHaveKeys || !enabled)\n                    menu.AddDisabledItem(new GUIContent(str));\n                else\n                    menu.AddItem(new GUIContent(str), false, AddKeysAtCurrentTime, curves);\n\n                str = k_DeleteKey;\n                if (noneHaveKeys || !enabled)\n                    menu.AddDisabledItem(new GUIContent(str));\n                else\n                    menu.AddItem(new GUIContent(str), false, DeleteKeysAtCurrentTime, curves);\n            }\n\n            return menu;\n        }\n\n        private void AddKeysAtCurrentTime(object obj) { AddKeysAtCurrentTime((List<AnimationWindowCurve>)obj); }\n        private void AddKeysAtCurrentTime(List<AnimationWindowCurve> curves)\n        {\n            AnimationWindowUtility.AddKeyframes(state, curves, state.time);\n        }\n\n        private void DeleteKeysAtCurrentTime(object obj) { DeleteKeysAtCurrentTime((List<AnimationWindowCurve>)obj); }\n        private void DeleteKeysAtCurrentTime(List<AnimationWindowCurve> curves)\n        {\n            AnimationWindowUtility.RemoveKeyframes(state, curves, state.time);\n        }\n\n        private void ChangeRotationInterpolation(System.Object interpolationMode)\n        {\n            RotationCurveInterpolation.Mode mode = (RotationCurveInterpolation.Mode)interpolationMode;\n\n            AnimationWindowCurve[] activeCurves = state.activeCurves.ToArray();\n            EditorCurveBinding[] curveBindings = new EditorCurveBinding[activeCurves.Length];\n\n            for (int i = 0; i < activeCurves.Length; i++)\n            {\n                curveBindings[i] = activeCurves[i].binding;\n            }\n\n            RotationCurveInterpolation.SetInterpolation(state.activeAnimationClip, curveBindings, mode);\n            MaintainTreeviewStateAfterRotationInterpolation(mode);\n            state.hierarchyData.ReloadData();\n        }\n\n        private void RemoveCurvesFromSelectedNodes()\n        {\n            RemoveCurvesFromNodes(state.selectedHierarchyNodes);\n        }\n\n        private void RemoveCurvesFromNodes(List<AnimationWindowHierarchyNode> nodes)\n        {\n            string undoLabel = k_RemoveCurve;\n            state.SaveKeySelection(undoLabel);\n\n            foreach (var node in nodes)\n            {\n                AnimationWindowHierarchyNode hierarchyNode = (AnimationWindowHierarchyNode)node;\n\n                if (hierarchyNode.parent is AnimationWindowHierarchyPropertyGroupNode && hierarchyNode.binding != null && AnimationWindowUtility.ForceGrouping((EditorCurveBinding)hierarchyNode.binding))\n                    hierarchyNode = (AnimationWindowHierarchyNode)hierarchyNode.parent;\n\n                if (hierarchyNode.curves == null)\n                    continue;\n\n                List<AnimationWindowCurve> curves = null;\n\n                // Property or propertygroup\n                if (hierarchyNode is AnimationWindowHierarchyPropertyGroupNode || hierarchyNode is AnimationWindowHierarchyPropertyNode)\n                    curves = AnimationWindowUtility.FilterCurves(hierarchyNode.curves.ToArray(), hierarchyNode.path, hierarchyNode.animatableObjectType, hierarchyNode.propertyName);\n                else\n                    curves = AnimationWindowUtility.FilterCurves(hierarchyNode.curves.ToArray(), hierarchyNode.path, hierarchyNode.animatableObjectType);\n\n                foreach (AnimationWindowCurve animationWindowCurve in curves)\n                    state.RemoveCurve(animationWindowCurve, undoLabel);\n            }\n\n            m_TreeView.ReloadData();\n\n            state.controlInterface.ResampleAnimation();\n        }\n\n        private List<AnimationWindowCurve> GetCurvesAffectedByNodes(List<AnimationWindowHierarchyNode> nodes, bool includeLinkedCurves)\n        {\n            List<AnimationWindowCurve> curves = new List<AnimationWindowCurve>();\n            foreach (var node in nodes)\n            {\n                AnimationWindowHierarchyNode hierarchyNode = node;\n\n                if (hierarchyNode.parent is AnimationWindowHierarchyPropertyGroupNode && includeLinkedCurves)\n                    hierarchyNode = (AnimationWindowHierarchyNode)hierarchyNode.parent;\n\n                if (hierarchyNode.curves == null)\n                    continue;\n\n                if (hierarchyNode.curves.Length > 0)\n                {\n                    // Property or propertygroup\n                    if (hierarchyNode is AnimationWindowHierarchyPropertyGroupNode || hierarchyNode is AnimationWindowHierarchyPropertyNode)\n                        curves.AddRange(AnimationWindowUtility.FilterCurves(hierarchyNode.curves, hierarchyNode.path, hierarchyNode.animatableObjectType, hierarchyNode.propertyName));\n                    else\n                        curves.AddRange(AnimationWindowUtility.FilterCurves(hierarchyNode.curves, hierarchyNode.path, hierarchyNode.animatableObjectType));\n                }\n            }\n            return curves.Distinct().ToList();\n        }\n\n        // Changing rotation interpolation will change the propertynames of the curves\n        // Propertynames are used in treeview node IDs, so we need to anticipate the new IDs by injecting them into treeview state\n        // This way treeview state (selection and expanding) will be preserved once the curve data is eventually reloaded\n        private void MaintainTreeviewStateAfterRotationInterpolation(RotationCurveInterpolation.Mode newMode)\n        {\n            List<int> selectedInstaceIDs = state.hierarchyState.selectedIDs;\n            List<int> expandedInstaceIDs = state.hierarchyState.expandedIDs;\n\n            List<int> oldIDs = new List<int>();\n            List<int> newIds = new List<int>();\n\n            for (int i = 0; i < selectedInstaceIDs.Count; i++)\n            {\n                AnimationWindowHierarchyNode node = state.hierarchyData.FindItem(selectedInstaceIDs[i]) as AnimationWindowHierarchyNode;\n\n                if (node != null && !node.propertyName.Equals(RotationCurveInterpolation.GetPrefixForInterpolation(newMode)))\n                {\n                    string oldPrefix = node.propertyName.Split('.')[0];\n                    string newPropertyName = node.propertyName.Replace(oldPrefix, RotationCurveInterpolation.GetPrefixForInterpolation(newMode));\n\n                    // old treeview node id\n                    oldIDs.Add(selectedInstaceIDs[i]);\n                    // and its new replacement\n                    newIds.Add((node.path + node.animatableObjectType.Name + newPropertyName).GetHashCode());\n                }\n            }\n\n            // Replace old IDs with new ones\n            for (int i = 0; i < oldIDs.Count; i++)\n            {\n                if (selectedInstaceIDs.Contains(oldIDs[i]))\n                {\n                    int index = selectedInstaceIDs.IndexOf(oldIDs[i]);\n                    selectedInstaceIDs[index] = newIds[i];\n                }\n                if (expandedInstaceIDs.Contains(oldIDs[i]))\n                {\n                    int index = expandedInstaceIDs.IndexOf(oldIDs[i]);\n                    expandedInstaceIDs[index] = newIds[i];\n                }\n                if (state.hierarchyState.lastClickedID == oldIDs[i])\n                    state.hierarchyState.lastClickedID = newIds[i];\n            }\n\n            state.hierarchyState.selectedIDs = new List<int>(selectedInstaceIDs);\n            state.hierarchyState.expandedIDs = new List<int>(expandedInstaceIDs);\n        }\n\n        private RotationCurveInterpolation.Mode GetRotationInterpolationMode(EditorCurveBinding[] curves)\n        {\n            if (curves == null || curves.Length == 0)\n                return RotationCurveInterpolation.Mode.Undefined;\n\n            RotationCurveInterpolation.Mode mode = RotationCurveInterpolation.GetModeFromCurveData(curves[0]);\n            for (int i = 1; i < curves.Length; i++)\n            {\n                RotationCurveInterpolation.Mode nextMode = RotationCurveInterpolation.GetModeFromCurveData(curves[i]);\n                if (mode != nextMode)\n                    return RotationCurveInterpolation.Mode.Undefined;\n            }\n\n            return mode;\n        }\n\n        // TODO: Make real styles, not this\n        private void SetStyleTextColor(GUIStyle style, Color color)\n        {\n            style.normal.textColor = color;\n            style.focused.textColor = color;\n            style.active.textColor = color;\n            style.hover.textColor = color;\n        }\n\n        public override void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible)\n        {\n            firstRowVisible = 0;\n            lastRowVisible = m_TreeView.data.rowCount - 1;\n        }\n\n        public float GetNodeHeight(AnimationWindowHierarchyNode node)\n        {\n            if (node is AnimationWindowHierarchyAddButtonNode)\n                return k_AddCurveButtonNodeHeight;\n\n            AnimationWindowHierarchyState hierarchyState = m_TreeView.state as AnimationWindowHierarchyState;\n            return hierarchyState.GetTallMode(node) ? k_DopeSheetRowHeightTall : k_DopeSheetRowHeight;\n        }\n\n        public override Vector2 GetTotalSize()\n        {\n            var rows = m_TreeView.data.GetRows();\n            float height = 0f;\n            for (int i = 0; i < rows.Count; i++)\n            {\n                AnimationWindowHierarchyNode node = rows[i] as AnimationWindowHierarchyNode;\n                height += GetNodeHeight(node);\n            }\n\n            return new Vector2(1, height);\n        }\n\n        float GetTopPixelOfRow(int row, IList<TreeViewItem> rows)\n        {\n            float top = 0f;\n            for (int i = 0; i < row && i < rows.Count; i++)\n            {\n                AnimationWindowHierarchyNode node = rows[i] as AnimationWindowHierarchyNode;\n                top += GetNodeHeight(node);\n            }\n            return top;\n        }\n\n        public override Rect GetRowRect(int row, float rowWidth)\n        {\n            var rows = m_TreeView.data.GetRows();\n            AnimationWindowHierarchyNode hierarchyNode = rows[row] as AnimationWindowHierarchyNode;\n            if (hierarchyNode.topPixel == null)\n                hierarchyNode.topPixel = GetTopPixelOfRow(row, rows);\n\n            float rowHeight = GetNodeHeight(hierarchyNode);\n            return new Rect(0, (float)hierarchyNode.topPixel, rowWidth, rowHeight);\n        }\n\n        public override void OnRowGUI(Rect rowRect, TreeViewItem node, int row, bool selected, bool focused)\n        {\n            AnimationWindowHierarchyNode hierarchyNode = node as AnimationWindowHierarchyNode;\n            DoNodeGUI(rowRect, hierarchyNode, selected, focused, row);\n        }\n\n        override public bool BeginRename(TreeViewItem item, float delay)\n        {\n            m_RenamedNode = item as AnimationWindowHierarchyNode;\n\n            return GetRenameOverlay().BeginRename(m_RenamedNode.path, item.id, delay);\n        }\n\n        override protected void SyncFakeItem()\n        {\n            //base.SyncFakeItem();\n        }\n\n        override protected void RenameEnded()\n        {\n            var renameOverlay = GetRenameOverlay();\n            if (renameOverlay.userAcceptedRename)\n            {\n                string newName = renameOverlay.name;\n                string oldName = renameOverlay.originalName;\n\n                if (newName != oldName)\n                {\n                    Undo.RecordObject(state.activeAnimationClip, \"Rename Curve\");\n\n                    foreach (AnimationWindowCurve curve in m_RenamedNode.curves)\n                    {\n                        EditorCurveBinding newBinding = AnimationWindowUtility.GetRenamedBinding(curve.binding, newName);\n\n                        if (AnimationWindowUtility.CurveExists(newBinding, state.filteredCurves.ToArray()))\n                        {\n                            Debug.LogWarning(\"Curve already exists, renaming cancelled.\");\n                            continue;\n                        }\n\n                        AnimationWindowUtility.RenameCurvePath(curve, newBinding, curve.clip);\n                    }\n                }\n            }\n\n            m_RenamedNode = null;\n        }\n\n        override protected Texture GetIconForItem(TreeViewItem item)\n        {\n            if (item != null)\n                return item.icon;\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyNode.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditor.IMGUI.Controls;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\n\n\nnamespace UnityEditorInternal\n{\n    internal class AnimationWindowHierarchyNode : TreeViewItem\n    {\n        public string path;\n        public System.Type animatableObjectType;\n        public string propertyName;\n\n        public EditorCurveBinding? binding;\n        public AnimationWindowCurve[] curves;\n\n        public float? topPixel = null;\n        public int indent = 0;\n\n        public AnimationWindowHierarchyNode(int instanceID, int depth, TreeViewItem parent, System.Type animatableObjectType, string propertyName, string path, string displayName)\n            : base(instanceID, depth, parent, displayName)\n        {\n            this.displayName = displayName;\n            this.animatableObjectType = animatableObjectType;\n            this.propertyName = propertyName;\n            this.path = path;\n        }\n    }\n\n    internal class AnimationWindowHierarchyPropertyGroupNode : AnimationWindowHierarchyNode\n    {\n        public AnimationWindowHierarchyPropertyGroupNode(System.Type animatableObjectType, int setId, string propertyName, string path, TreeViewItem parent, string displayName)\n            : base(AnimationWindowUtility.GetPropertyNodeID(setId, path, animatableObjectType, propertyName), parent != null ? parent.depth + 1 : -1, parent, animatableObjectType, AnimationWindowUtility.GetPropertyGroupName(propertyName), path, displayName)\n        {}\n    }\n\n    internal class AnimationWindowHierarchyPropertyNode : AnimationWindowHierarchyNode\n    {\n        public bool isPptrNode;\n\n        public AnimationWindowHierarchyPropertyNode(System.Type animatableObjectType, int setId, string propertyName, string path, TreeViewItem parent, EditorCurveBinding binding, bool isPptrNode, string displayName)\n            : base(AnimationWindowUtility.GetPropertyNodeID(setId, path, animatableObjectType, propertyName), parent != null ? parent.depth + 1 : -1, parent, animatableObjectType, propertyName, path, displayName)\n        {\n            this.binding = binding;\n            this.isPptrNode = isPptrNode;\n        }\n    }\n\n    internal class AnimationWindowHierarchyClipNode : AnimationWindowHierarchyNode\n    {\n        public AnimationWindowHierarchyClipNode(TreeViewItem parent, int setId, string name)\n            : base(setId, parent != null ? parent.depth + 1 : -1, parent, null, null, null, name)\n        {}\n    }\n\n    internal class AnimationWindowHierarchyMasterNode : AnimationWindowHierarchyNode\n    {\n        public AnimationWindowHierarchyMasterNode()\n            : base(0, -1, null, null, null, null, \"\")\n        {}\n    }\n\n    // A special node to put \"Add Curve\" button in bottom of the tree\n    internal class AnimationWindowHierarchyAddButtonNode : AnimationWindowHierarchyNode\n    {\n        public AnimationWindowHierarchyAddButtonNode()\n            : base(0, -1, null, null, null, null, \"\")\n        {}\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowKeySelection.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing System.Collections;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditorInternal\n{\n    [System.Serializable]\n    internal class AnimationWindowKeySelection : ScriptableObject, ISerializationCallbackReceiver\n    {\n        private HashSet<int> m_SelectedKeyHashes;\n        [SerializeField] private List<int> m_SelectedKeyHashesSerialized;\n\n        public HashSet<int> selectedKeyHashes\n        {\n            get { return m_SelectedKeyHashes ?? (m_SelectedKeyHashes = new HashSet<int>()); }\n            set { m_SelectedKeyHashes = value; }\n        }\n\n        public void SaveSelection(string undoLabel)\n        {\n            Undo.RegisterCompleteObjectUndo(this, undoLabel);\n        }\n\n        public void OnBeforeSerialize()\n        {\n            m_SelectedKeyHashesSerialized = m_SelectedKeyHashes.ToList();\n        }\n\n        public void OnAfterDeserialize()\n        {\n            m_SelectedKeyHashes = new HashSet<int>(m_SelectedKeyHashesSerialized);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowKeyframe.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditorInternal\n{\n    internal class AnimationWindowKeyframe\n    {\n        public float            m_InTangent;\n        public float            m_OutTangent;\n        public float            m_InWeight;\n        public float            m_OutWeight;\n        public WeightedMode     m_WeightedMode;\n        public int              m_TangentMode;\n        public int              m_TimeHash;\n        int                     m_Hash;\n\n        float                   m_time;\n\n        object                  m_value;\n\n        AnimationWindowCurve    m_curve;\n        public float time\n        {\n            get { return m_time; }\n            set\n            {\n                m_time = value;\n                m_Hash = 0;\n                m_TimeHash = value.GetHashCode();\n            }\n        }\n\n        public object value\n        {\n            get { return m_value; }\n            set { m_value = value; }\n        }\n\n        public float inTangent\n        {\n            get { return m_InTangent; }\n            set { m_InTangent = value; }\n        }\n\n        public float outTangent\n        {\n            get { return m_OutTangent; }\n            set { m_OutTangent = value; }\n        }\n\n        public float inWeight\n        {\n            get { return m_InWeight; }\n            set { m_InWeight = value; }\n        }\n\n        public float outWeight\n        {\n            get { return m_OutWeight; }\n            set { m_OutWeight = value; }\n        }\n\n        public WeightedMode weightedMode\n        {\n            get { return m_WeightedMode; }\n            set { m_WeightedMode = value; }\n        }\n\n        public AnimationWindowCurve curve\n        {\n            get { return m_curve; }\n            set\n            {\n                m_curve = value;\n                m_Hash = 0;\n            }\n        }\n\n        public bool isPPtrCurve { get { return curve.isPPtrCurve; } }\n        public bool isDiscreteCurve { get { return curve.isDiscreteCurve; } }\n\n        public AnimationWindowKeyframe()\n        {\n        }\n\n        public AnimationWindowKeyframe(AnimationWindowKeyframe key)\n        {\n            this.time = key.time;\n            this.value = key.value;\n            this.curve = key.curve;\n            this.m_InTangent = key.m_InTangent;\n            this.m_OutTangent = key.m_OutTangent;\n            this.m_InWeight = key.inWeight;\n            this.m_OutWeight = key.outWeight;\n            this.m_WeightedMode = key.weightedMode;\n            this.m_TangentMode = key.m_TangentMode;\n            this.m_curve = key.m_curve;\n        }\n\n        public AnimationWindowKeyframe(AnimationWindowCurve curve, Keyframe key)\n        {\n            this.time = key.time;\n\n            if (curve.isDiscreteCurve)\n            {\n                this.value = UnityEngine.Animations.DiscreteEvaluationAttributeUtilities.ConvertFloatToDiscreteInt(key.value);\n            }\n            else\n            {\n                this.value = key.value;\n            }\n\n            this.curve = curve;\n            this.m_InTangent = key.inTangent;\n            this.m_OutTangent = key.outTangent;\n            this.m_InWeight = key.inWeight;\n            this.m_OutWeight = key.outWeight;\n            this.m_WeightedMode = key.weightedMode;\n            this.m_TangentMode = key.tangentModeInternal;\n            this.m_curve = curve;\n        }\n\n        public AnimationWindowKeyframe(AnimationWindowCurve curve, ObjectReferenceKeyframe key)\n        {\n            this.time = key.time;\n            this.value = key.value;\n            this.curve = curve;\n        }\n\n        public int GetHash()\n        {\n            if (m_Hash == 0)\n            {\n                // Berstein hash\n                unchecked\n                {\n                    m_Hash = curve.GetHashCode();\n                    m_Hash = 33 * m_Hash + time.GetHashCode();\n                }\n            }\n\n            return m_Hash;\n        }\n\n        public int GetIndex()\n        {\n            for (int i = 0; i < curve.keyframes.Count; i++)\n            {\n                if (curve.keyframes[i] == this)\n                {\n                    return i;\n                }\n            }\n            return -1;\n        }\n\n        public Keyframe ToKeyframe()\n        {\n            float floatValue;\n            if (curve.isDiscreteCurve)\n            {\n                // case 1395978\n                // Negative int values converted to float create NaN values. Limiting discrete int values to only positive values\n                // until we rewrite the animation backend with dedicated int curves.\n                floatValue = UnityEngine.Animations.DiscreteEvaluationAttributeUtilities.ConvertDiscreteIntToFloat(Math.Max(Convert.ToInt32(value), 0));\n            }\n            else\n            {\n                floatValue = Convert.ToSingle(value);\n            }\n\n            var keyframe = new Keyframe(time, floatValue, inTangent, outTangent);\n\n            keyframe.tangentModeInternal = m_TangentMode;\n            keyframe.weightedMode = weightedMode;\n            keyframe.inWeight = inWeight;\n            keyframe.outWeight = outWeight;\n\n            return keyframe;\n        }\n\n        public ObjectReferenceKeyframe ToObjectReferenceKeyframe()\n        {\n            var keyframe = new ObjectReferenceKeyframe();\n\n            keyframe.time = time;\n            keyframe.value = (UnityEngine.Object)value;\n\n            return keyframe;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowManipulator.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class AnimationWindowManipulator\n    {\n        public delegate bool OnStartDragDelegate(AnimationWindowManipulator manipulator, Event evt);\n        public delegate bool OnDragDelegate(AnimationWindowManipulator manipulator, Event evt);\n        public delegate bool OnEndDragDelegate(AnimationWindowManipulator manipulator, Event evt);\n\n        public OnStartDragDelegate onStartDrag;\n        public OnDragDelegate onDrag;\n        public OnEndDragDelegate onEndDrag;\n\n        public Rect rect;\n        public int controlID;\n\n        public AnimationWindowManipulator()\n        {\n            // NoOps...\n            onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => { return false; };\n            onDrag += (AnimationWindowManipulator manipulator, Event evt) => { return false; };\n            onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => { return false; };\n        }\n\n        public virtual void HandleEvents()\n        {\n            controlID = GUIUtility.GetControlID(FocusType.Passive);\n\n            Event evt = Event.current;\n            EventType eventType = evt.GetTypeForControl(controlID);\n\n            bool handled = false;\n            switch (eventType)\n            {\n                case EventType.MouseDown:\n                    if (evt.button == 0)\n                    {\n                        handled = onStartDrag(this, evt);\n\n                        if (handled)\n                            GUIUtility.hotControl = controlID;\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == controlID)\n                    {\n                        handled = onDrag(this, evt);\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == controlID)\n                    {\n                        handled = onEndDrag(this, evt);\n                        GUIUtility.hotControl = 0;\n                    }\n                    break;\n            }\n\n            if (handled)\n                evt.Use();\n        }\n\n        public virtual void IgnoreEvents()\n        {\n            GUIUtility.GetControlID(FocusType.Passive);\n        }\n    }\n\n    internal class AreaManipulator : AnimationWindowManipulator\n    {\n        private GUIStyle m_Style;\n        private MouseCursor m_Cursor;\n\n        public AreaManipulator(GUIStyle style, MouseCursor cursor)\n        {\n            m_Style = style;\n            m_Cursor = cursor;\n        }\n\n        public AreaManipulator(GUIStyle style)\n        {\n            m_Style = style;\n            m_Cursor = MouseCursor.Arrow;\n        }\n\n        public void OnGUI(Rect widgetRect)\n        {\n            if (m_Style == null)\n                return;\n\n            rect = widgetRect;\n\n            if (Mathf.Approximately(widgetRect.width * widgetRect.height, 0f))\n                return;\n\n            GUI.Label(widgetRect, GUIContent.none, m_Style);\n\n            if (GUIUtility.hotControl == 0 && m_Cursor != MouseCursor.Arrow)\n            {\n                EditorGUIUtility.AddCursorRect(widgetRect, m_Cursor);\n            }\n            else if (GUIUtility.hotControl == controlID)\n            {\n                Vector2 mousePosition = Event.current.mousePosition;\n                EditorGUIUtility.AddCursorRect(new Rect(mousePosition.x - 10, mousePosition.y - 10, 20, 20), m_Cursor);\n            }\n        }\n    }\n\n    internal class TimeCursorManipulator : AnimationWindowManipulator\n    {\n        public enum Alignment\n        {\n            Center,\n            Left,\n            Right\n        }\n\n        public Alignment alignment;\n        public Color headColor;\n        public Color lineColor;\n        public bool dottedLine;\n        public bool drawLine;\n        public bool drawHead;\n        public string tooltip;\n\n        private GUIStyle m_Style;\n\n        public TimeCursorManipulator(GUIStyle style)\n        {\n            m_Style = style;\n            dottedLine = false;\n            headColor = Color.white;\n            lineColor = style.normal.textColor;\n            drawLine = true;\n            drawHead = true;\n            tooltip = string.Empty;\n            alignment = Alignment.Center;\n        }\n\n        public void OnGUI(Rect windowRect, float pixelTime)\n        {\n            float widgetWidth = m_Style.fixedWidth;\n            float widgetHeight = m_Style.fixedHeight;\n\n            Vector2 windowCoordinate = new Vector2(pixelTime, windowRect.yMin);\n\n            switch (alignment)\n            {\n                case Alignment.Center:\n                    rect = new Rect((windowCoordinate.x - widgetWidth / 2.0f), windowCoordinate.y, widgetWidth, widgetHeight);\n                    break;\n                case Alignment.Left:\n                    rect = new Rect(windowCoordinate.x - widgetWidth, windowCoordinate.y, widgetWidth, widgetHeight);\n                    break;\n                case Alignment.Right:\n                    rect = new Rect(windowCoordinate.x, windowCoordinate.y, widgetWidth, widgetHeight);\n                    break;\n            }\n\n            Vector3 p1 = new Vector3(windowCoordinate.x, windowCoordinate.y + widgetHeight, 0.0f);\n            Vector3 p2 = new Vector3(windowCoordinate.x, windowRect.height, 0.0f);\n\n            if (drawLine)\n            {\n                Handles.color = lineColor;\n                if (dottedLine)\n                    Handles.DrawDottedLine(p1, p2, 5.0f);\n                else\n                    Handles.DrawLine(p1, p2);\n            }\n\n            if (drawHead)\n            {\n                Color c = GUI.color;\n                GUI.color = headColor;\n                GUI.Box(rect, GUIContent.none, m_Style);\n                GUI.color = c;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowOptions.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    internal static class AnimationWindowOptions\n    {\n        static string kTimeFormat = \"AnimationWindow.TimeFormat\";\n        static string kFilterBySelection = \"AnimationWindow.FilterBySelection\";\n        static string kShowReadOnly = \"AnimationWindow.ShowReadOnly\";\n        static string kShowFrameRate = \"AnimationWindow.ShowFrameRate\";\n\n        private static TimeArea.TimeFormat m_TimeFormat;\n        private static bool m_FilterBySelection;\n        private static bool m_ShowReadOnly;\n        private static bool m_ShowFrameRate;\n\n        static AnimationWindowOptions()\n        {\n            m_TimeFormat = (TimeArea.TimeFormat)EditorPrefs.GetInt(kTimeFormat, (int)TimeArea.TimeFormat.TimeFrame);\n            m_FilterBySelection = EditorPrefs.GetBool(kFilterBySelection, false);\n            m_ShowReadOnly = EditorPrefs.GetBool(kShowReadOnly, false);\n            m_ShowFrameRate = EditorPrefs.GetBool(kShowFrameRate, false);\n        }\n\n        public static TimeArea.TimeFormat timeFormat\n        {\n            get\n            {\n                return m_TimeFormat;\n            }\n            set\n            {\n                m_TimeFormat = value;\n                EditorPrefs.SetInt(kTimeFormat, (int)value);\n            }\n        }\n\n        public static bool filterBySelection\n        {\n            get\n            {\n                return m_FilterBySelection;\n            }\n            set\n            {\n                m_FilterBySelection = value;\n                EditorPrefs.SetBool(kFilterBySelection, value);\n            }\n        }\n\n        public static bool showReadOnly\n        {\n            get\n            {\n                return m_ShowReadOnly;\n            }\n            set\n            {\n                m_ShowReadOnly = value;\n                EditorPrefs.SetBool(kShowReadOnly, value);\n            }\n        }\n\n        public static bool showFrameRate\n        {\n            get\n            {\n                return m_ShowFrameRate;\n            }\n            set\n            {\n                m_ShowFrameRate = value;\n                EditorPrefs.SetBool(kShowFrameRate, value);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowSelectionItem.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing System.Collections;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditorInternal\n{\n    [Serializable]\n    abstract class AnimationWindowSelectionItem : System.IEquatable<AnimationWindowSelectionItem>, ISelectionBinding\n    {\n        [SerializeField] private int m_Id;\n        [SerializeField] private GameObject m_GameObject;\n        [SerializeField] private ScriptableObject m_ScriptableObject;\n        [SerializeField] private AnimationClip m_AnimationClip;\n\n        public virtual int id { get { return m_Id; } set { m_Id = value; } }\n\n        public virtual GameObject gameObject { get { return m_GameObject; } set { m_GameObject = value; } }\n\n        public virtual ScriptableObject scriptableObject { get { return m_ScriptableObject; } set { m_ScriptableObject = value; } }\n\n        public virtual Object sourceObject { get { return (gameObject != null) ? (Object)gameObject : (Object)scriptableObject; } }\n\n        public virtual AnimationClip animationClip { get { return m_AnimationClip; } set { m_AnimationClip = value; } }\n\n        public virtual GameObject rootGameObject\n        {\n            get\n            {\n                Component animationPlayer = this.animationPlayer;\n                if (animationPlayer != null)\n                {\n                    return animationPlayer.gameObject;\n                }\n                return null;\n            }\n        }\n\n        public virtual Component animationPlayer\n        {\n            get\n            {\n                if (gameObject != null)\n                    return AnimationWindowUtility.GetClosestAnimationPlayerComponentInParents(gameObject.transform);\n                return null;\n            }\n        }\n\n        public bool disabled\n        {\n            get\n            {\n                // To be editable, a selection must at least contain an animation clip.\n                return (animationClip == null);\n            }\n        }\n\n        public virtual bool animationIsEditable\n        {\n            get\n            {\n                // Clip is imported and shouldn't be edited\n                if (animationClip && (animationClip.hideFlags & HideFlags.NotEditable) != 0)\n                    return false;\n\n                // Object is a prefab - shouldn't be edited\n                if (objectIsPrefab)\n                    return false;\n\n                return true;\n            }\n        }\n\n        public virtual bool clipIsEditable\n        {\n            get\n            {\n                if (!animationClip)\n                    return false;\n                // Clip is imported and shouldn't be edited\n                if ((animationClip.hideFlags & HideFlags.NotEditable) != 0)\n                    return false;\n                if (!AssetDatabase.IsOpenForEdit(animationClip, StatusQueryOptions.UseCachedIfPossible))\n                    return false;\n\n                return true;\n            }\n        }\n\n        public virtual bool objectIsPrefab\n        {\n            get\n            {\n                // No gameObject selected\n                if (!gameObject)\n                    return false;\n\n                if (EditorUtility.IsPersistent(gameObject))\n                    return true;\n\n                if ((gameObject.hideFlags & HideFlags.NotEditable) != 0)\n                    return true;\n\n                return false;\n            }\n        }\n\n        public virtual bool objectIsOptimized\n        {\n            get\n            {\n                Animator animator = animationPlayer as Animator;\n                if (animator == null)\n                    return false;\n\n                return animator.isOptimizable && !animator.hasTransformHierarchy;\n            }\n        }\n\n        public virtual bool canPreview\n        {\n            get\n            {\n                if (rootGameObject != null)\n                {\n                    return !objectIsOptimized;\n                }\n\n                return false;\n            }\n        }\n\n        public virtual bool canRecord\n        {\n            get\n            {\n                if (!animationIsEditable)\n                    return false;\n\n                return canPreview;\n            }\n        }\n\n        public virtual bool canChangeAnimationClip\n        {\n            get\n            {\n                return rootGameObject != null;\n            }\n        }\n\n        public virtual bool canAddCurves\n        {\n            get\n            {\n                if (gameObject != null)\n                {\n                    return !objectIsPrefab && clipIsEditable;\n                }\n                else if (scriptableObject != null)\n                {\n                    return true;\n                }\n\n                return false;\n            }\n        }\n\n        public virtual bool canCreateClips\n        {\n            get\n            {\n                Component animationPlayer = this.animationPlayer;\n                if (animationPlayer == null)\n                    return false;\n\n                Animator animator = animationPlayer as Animator;\n                if (animator != null)\n                {\n                    // Need a valid state machine to create clips in the Animator.\n                    return (animator.runtimeAnimatorController != null);\n                }\n\n                return true;\n            }\n        }\n\n        public virtual bool canSyncSceneSelection { get { return true; } }\n\n        public int GetRefreshHash()\n        {\n            return unchecked (id * 19603 ^\n                (animationClip != null ? 729 * animationClip.GetHashCode() : 0) ^\n                (rootGameObject != null ? 27 * rootGameObject.GetHashCode() : 0) ^\n                (scriptableObject != null ? scriptableObject.GetHashCode() : 0));\n        }\n\n        virtual public void Synchronize()\n        {\n            // nothing to do.\n        }\n\n        public bool Equals(AnimationWindowSelectionItem other)\n        {\n            return id == other.id &&\n                animationClip == other.animationClip &&\n                gameObject == other.gameObject &&\n                scriptableObject == other.scriptableObject;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing UnityEditor.IMGUI.Controls;\nusing Object = UnityEngine.Object;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\n\nnamespace UnityEditorInternal\n{\n    [System.Serializable]\n    class AnimationWindowState : ICurveEditorState\n    {\n        public enum RefreshType\n        {\n            None = 0,\n            CurvesOnly = 1,\n            Everything = 2\n        }\n\n        public enum SnapMode\n        {\n            Disabled = 0,\n            SnapToFrame = 1,\n            [Obsolete(\"SnapToClipFrame has been made redundant with SnapToFrame, SnapToFrame will behave the same.\")]\n            SnapToClipFrame = 2\n        }\n\n        [SerializeField] public AnimEditor animEditor; // Reference to owner of this state. Used to trigger repaints.\n        [SerializeField] public AnimationWindowHierarchyState hierarchyState = new(); // Persistent state of treeview on the left side of window\n        [NonSerialized] public AnimationWindowHierarchyDataSource hierarchyData;\n\n        [SerializeReference] private TimeArea m_TimeArea; // Either curveeditor or dopesheet depending on which is selected\n        [SerializeReference] private AnimationWindowControl m_ControlInterface;\n        [SerializeReference] private IAnimationWindowController m_OverrideControlInterface;\n\n        [SerializeReference] private AnimationWindowSelectionItem m_EmptySelection;\n        [SerializeReference] private AnimationWindowSelectionItem m_Selection; // Internal selection\n        [SerializeField] private AnimationWindowKeySelection m_KeySelection; // What is selected. Hashes persist cache reload, because they are from keyframe time+value\n\n        [SerializeField] public bool showCurveEditor; // Do we show dopesheet or curves\n        [SerializeField] public bool linkedWithSequencer; // Toggle Sequencer selection mode.\n        [SerializeField] private bool m_RippleTime; // Toggle ripple time option for curve editor and dopesheet.\n        private bool m_RippleTimeClutch; // Toggle ripple time option for curve editor and dopesheet.\n        [SerializeField] private int m_ActiveKeyframeHash; // Which keyframe is active (selected key that user previously interacted with)\n        [SerializeField] private float m_FrameRate = kDefaultFrameRate;\n        [SerializeField] private int[] m_SelectionFilter;\n\n        [NonSerialized] public Action onStartLiveEdit;\n        [NonSerialized] public Action onEndLiveEdit;\n        [NonSerialized] public Action<float> onFrameRateChange;\n\n        private static List<AnimationWindowKeyframe> s_KeyframeClipboard; // For copy-pasting keyframes\n\n        private bool m_AllCurvesCacheDirty = true;\n        private bool m_FilteredCurvesCacheDirty = true;\n        private bool m_ActiveCurvesCacheDirty = true;\n        private List<AnimationWindowCurve> m_AllCurvesCache = new ();\n        private List<AnimationWindowCurve> m_FilteredCurvesCache = new ();\n        private List<AnimationWindowCurve> m_ActiveCurvesCache = new ();\n\n        private List<DopeLine> m_dopelinesCache;\n        private List<AnimationWindowKeyframe> m_SelectedKeysCache;\n        private Bounds? m_SelectionBoundsCache;\n        private CurveWrapper[] m_ActiveCurveWrappersCache;\n        private AnimationWindowKeyframe m_ActiveKeyframeCache;\n        private HashSet<int> m_ModifiedCurves = new HashSet<int>();\n        private EditorCurveBinding? m_lastAddedCurveBinding;\n\n        // Hash of all the things that require animationWindow to refresh if they change\n        private int m_PreviousRefreshHash;\n\n        // Changing m_Refresh means you are ordering a refresh at the next OnGUI().\n        // CurvesOnly means that there is no need to refresh the hierarchy, since only the keyframe data changed.\n        private RefreshType m_Refresh = RefreshType.None;\n\n        private struct LiveEditKeyframe\n        {\n            public AnimationWindowKeyframe keySnapshot;\n            public AnimationWindowKeyframe key;\n        }\n\n        private class LiveEditCurve\n        {\n            public AnimationWindowCurve curve;\n            public List<LiveEditKeyframe> selectedKeys = new List<LiveEditKeyframe>();\n            public List<LiveEditKeyframe> unselectedKeys = new List<LiveEditKeyframe>();\n        }\n\n        private List<LiveEditCurve> m_LiveEditSnapshot;\n\n        public const float kDefaultFrameRate = 60.0f;\n        public const string kEditCurveUndoLabel = \"Edit Curve\";\n\n        public AnimationWindowSelectionItem selection\n        {\n            get\n            {\n                if (m_Selection != null)\n                    return m_Selection;\n\n                if (m_EmptySelection == null)\n                    m_EmptySelection = AnimationClipSelectionItem.Create(null, null);\n\n                return m_EmptySelection;\n            }\n\n            set\n            {\n                m_Selection = value;\n                OnSelectionChanged();\n            }\n        }\n\n        // AnimationClip we are currently editing\n        public AnimationClip activeAnimationClip\n        {\n            get\n            {\n                return selection.animationClip;\n            }\n            set\n            {\n                if (selection.canChangeAnimationClip)\n                {\n                    selection.animationClip = value;\n                    OnSelectionChanged();\n                }\n            }\n        }\n\n\n        // Previously or currently selected gameobject is considered as the active gameobject\n        public GameObject activeGameObject\n        {\n            get\n            {\n                return selection.gameObject;\n            }\n        }\n\n        // Closes parent to activeGameObject that has Animator component\n        public GameObject activeRootGameObject\n        {\n            get\n            {\n                return selection.rootGameObject;\n            }\n        }\n\n        public Component activeAnimationPlayer\n        {\n            get\n            {\n                return selection.animationPlayer;\n            }\n        }\n\n        public ScriptableObject activeScriptableObject\n        {\n            get\n            {\n                return selection.scriptableObject;\n            }\n        }\n\n        // Is the hierarchy in animator optimized\n        public bool animatorIsOptimized\n        {\n            get\n            {\n                return selection.objectIsOptimized;\n            }\n        }\n\n        public bool disabled\n        {\n            get\n            {\n                return selection.disabled;\n            }\n        }\n\n        public IAnimationWindowController controlInterface => m_OverrideControlInterface ?? m_ControlInterface;\n\n        public IAnimationWindowController overrideControlInterface\n        {\n            get => m_OverrideControlInterface;\n            set\n            {\n                if (m_OverrideControlInterface != null)\n                    m_OverrideControlInterface.OnDestroy();\n\n                m_OverrideControlInterface = value;\n            }\n        }\n\n        public bool filterBySelection\n        {\n            get\n            {\n                return AnimationWindowOptions.filterBySelection;\n            }\n            set\n            {\n                AnimationWindowOptions.filterBySelection = value;\n                UpdateSelectionFilter();\n\n                // Refresh everything.\n                refresh = RefreshType.Everything;\n            }\n        }\n\n        public bool showReadOnly\n        {\n            get\n            {\n                return AnimationWindowOptions.showReadOnly;\n            }\n            set\n            {\n                AnimationWindowOptions.showReadOnly = value;\n\n                // Refresh everything.\n                refresh = RefreshType.Everything;\n            }\n        }\n\n        public bool rippleTime\n        {\n            get\n            {\n                return m_RippleTime || m_RippleTimeClutch;\n            }\n            set\n            {\n                m_RippleTime = value;\n            }\n        }\n\n        public bool rippleTimeClutch { get { return m_RippleTimeClutch; } set { m_RippleTimeClutch = value; } }\n\n        public bool showFrameRate { get { return AnimationWindowOptions.showFrameRate; } set { AnimationWindowOptions.showFrameRate = value; } }\n\n        public void OnGUI()\n        {\n            RefreshHashCheck();\n            Refresh();\n        }\n\n        private void RefreshHashCheck()\n        {\n            int newRefreshHash = GetRefreshHash();\n            if (m_PreviousRefreshHash != newRefreshHash)\n            {\n                refresh = RefreshType.Everything;\n                m_PreviousRefreshHash = newRefreshHash;\n            }\n        }\n\n        private void Refresh()\n        {\n            selection.Synchronize();\n\n            if (refresh == RefreshType.Everything)\n            {\n                m_AllCurvesCacheDirty = true;\n                m_FilteredCurvesCacheDirty = true;\n                m_ActiveCurvesCacheDirty = true;\n\n                m_ActiveKeyframeCache = null;\n                m_dopelinesCache = null;\n                m_SelectedKeysCache = null;\n                m_SelectionBoundsCache = null;\n\n                if (animEditor != null && animEditor.curveEditor != null)\n                    animEditor.curveEditor.InvalidateSelectionBounds();\n\n                ClearCurveWrapperCache();\n\n                if (hierarchyData != null)\n                    hierarchyData.UpdateData();\n\n                // If there was new curve added, set it as active selection\n                if (m_lastAddedCurveBinding != null)\n                    OnNewCurveAdded((EditorCurveBinding)m_lastAddedCurveBinding);\n\n                // select top dopeline if there is no selection available\n                if (activeCurves.Count == 0 && dopelines.Count > 0)\n                    SelectHierarchyItem(dopelines[0], false, false);\n\n                m_Refresh = RefreshType.None;\n            }\n            else if (refresh == RefreshType.CurvesOnly)\n            {\n                m_ActiveKeyframeCache = null;\n                m_SelectedKeysCache = null;\n                m_SelectionBoundsCache = null;\n\n                if (animEditor != null && animEditor.curveEditor != null)\n                    animEditor.curveEditor.InvalidateSelectionBounds();\n\n                ReloadModifiedAnimationCurveCache();\n                ReloadModifiedDopelineCache();\n                ReloadModifiedCurveWrapperCache();\n\n                m_Refresh = RefreshType.None;\n                m_ModifiedCurves.Clear();\n            }\n        }\n\n        // Hash for checking if any of these things is changed\n        private int GetRefreshHash()\n        {\n            return\n                selection.GetRefreshHash() ^\n                (hierarchyState != null ? hierarchyState.expandedIDs.Count : 0) ^\n                (hierarchyState != null ? hierarchyState.GetTallInstancesCount() : 0) ^\n                (showCurveEditor ? 1 : 0);\n        }\n\n        public void ForceRefresh()\n        {\n            refresh = RefreshType.Everything;\n        }\n\n        private void PurgeSelection()\n        {\n            linkedWithSequencer = false;\n            m_OverrideControlInterface = null;\n            m_Selection = null;\n        }\n\n        public void OnEnable()\n        {\n            AnimationUtility.onCurveWasModified += CurveWasModified;\n            Undo.undoRedoEvent += UndoRedoPerformed;\n            AssemblyReloadEvents.beforeAssemblyReload += PurgeSelection;\n\n            // NoOps...\n            onStartLiveEdit += () => {};\n            onEndLiveEdit += () => {};\n\n            m_ControlInterface = new AnimationWindowControl\n            {\n                state = this\n            };\n            m_ControlInterface.OnEnable();\n\n            m_AllCurvesCacheDirty = true;\n            m_FilteredCurvesCacheDirty = true;\n            m_ActiveCurvesCacheDirty = true;\n        }\n\n        public void OnDisable()\n        {\n            AnimationUtility.onCurveWasModified -= CurveWasModified;\n            Undo.undoRedoEvent -= UndoRedoPerformed;\n            AssemblyReloadEvents.beforeAssemblyReload -= PurgeSelection;\n\n            m_ControlInterface.OnDisable();\n            previewing = false;\n        }\n\n        public void OnDestroy()\n        {\n            m_ControlInterface.OnDestroy();\n            m_ControlInterface = null;\n\n            if (m_OverrideControlInterface != null)\n            {\n                m_OverrideControlInterface.OnDestroy();\n                m_OverrideControlInterface = null;\n            }\n\n            Object.DestroyImmediate(m_KeySelection);\n        }\n\n        public void OnSelectionChanged()\n        {\n            if (onFrameRateChange != null)\n                onFrameRateChange(frameRate);\n\n            UpdateSelectionFilter();\n\n            // reset back time at 0 upon selection change.\n            controlInterface.OnSelectionChanged();\n\n            if (animEditor != null)\n                animEditor.OnSelectionChanged();\n        }\n\n        public void OnSelectionUpdated()\n        {\n            UpdateSelectionFilter();\n            if (filterBySelection)\n            {\n                // Refresh everything.\n                refresh = RefreshType.Everything;\n            }\n        }\n\n        // Set this property to ask for refresh at the next OnGUI.\n        public RefreshType refresh\n        {\n            get { return m_Refresh; }\n            // Make sure that if full refresh is already ordered, nobody gets to f*** with it\n            set\n            {\n                if ((int)m_Refresh < (int)value)\n                    m_Refresh = value;\n            }\n        }\n\n        public void UndoRedoPerformed(in UndoRedoInfo info)\n        {\n            refresh = RefreshType.Everything;\n            ResampleAnimation();\n        }\n\n        // When curve is modified, we never trigger refresh right away. We order a refresh at later time by setting refresh to appropriate value.\n        void CurveWasModified(AnimationClip clip, EditorCurveBinding binding, AnimationUtility.CurveModifiedType type)\n        {\n            // AnimationWindow doesn't care if some other clip somewhere changed\n            if (activeAnimationClip != clip)\n                return;\n\n            // Refresh curves that already exist.\n            if (type == AnimationUtility.CurveModifiedType.CurveModified)\n            {\n                bool didFind = false;\n                bool hadPhantom = false;\n                int hashCode = binding.GetHashCode();\n\n                var curves = filteredCurves;\n                for (int j = 0; j < curves.Count; ++j)\n                {\n                    var curve = curves[j];\n                    int curveHash = curve.GetBindingHashCode();\n                    if (curveHash == hashCode)\n                    {\n                        m_ModifiedCurves.Add(curve.GetHashCode());\n                        didFind = true;\n                        hadPhantom |= curve.binding.isPhantom;\n                    }\n                }\n\n                if (didFind && !hadPhantom)\n                    refresh = RefreshType.CurvesOnly;\n                else\n                {\n                    // New curve was added, so let's save binding and make it active selection when Refresh is called next time\n                    m_lastAddedCurveBinding = binding;\n                    refresh = RefreshType.Everything;\n                }\n            }\n            else\n            {\n                // Otherwise do a full reload\n                refresh = RefreshType.Everything;\n            }\n            // Force repaint to display live animation curve changes from other editor window (like timeline).\n            Repaint();\n        }\n\n        public void SaveKeySelection(string undoLabel)\n        {\n            if (m_KeySelection != null)\n                Undo.RegisterCompleteObjectUndo(m_KeySelection, undoLabel);\n        }\n\n        public void SaveCurve(AnimationClip clip, AnimationWindowCurve curve)\n        {\n            SaveCurve(clip, curve, kEditCurveUndoLabel);\n        }\n\n        public void SaveCurve(AnimationClip clip, AnimationWindowCurve curve, string undoLabel)\n        {\n            if (!curve.animationIsEditable)\n                Debug.LogError(\"Curve is not editable and shouldn't be saved.\");\n\n            Undo.RegisterCompleteObjectUndo(clip, undoLabel);\n            AnimationWindowUtility.SaveCurve(clip, curve);\n            Repaint();\n        }\n\n        public void SaveCurves(AnimationClip clip, ICollection<AnimationWindowCurve> curves, string undoLabel = kEditCurveUndoLabel)\n        {\n            if (curves.Count == 0)\n                return;\n\n            Undo.RegisterCompleteObjectUndo(clip, undoLabel);\n            AnimationWindowUtility.SaveCurves(clip, curves);\n            Repaint();\n        }\n\n        private void SaveSelectedKeys(string undoLabel)\n        {\n            List<AnimationWindowCurve> saveCurves = new List<AnimationWindowCurve>();\n\n            // Find all curves that need saving\n            foreach (LiveEditCurve snapshot in m_LiveEditSnapshot)\n            {\n                if (!snapshot.curve.animationIsEditable)\n                    continue;\n\n                if (!saveCurves.Contains(snapshot.curve))\n                    saveCurves.Add(snapshot.curve);\n\n                List<AnimationWindowKeyframe> toBeDeleted = new List<AnimationWindowKeyframe>();\n\n                // If selected keys are dragged over non-selected keyframe at exact same time, then delete the unselected ones underneath\n                foreach (AnimationWindowKeyframe other in snapshot.curve.keyframes)\n                {\n                    // Keyframe is in selection, skip.\n                    if (snapshot.selectedKeys.Exists(liveEditKey => liveEditKey.key == other))\n                        continue;\n\n                    // There is already a selected keyframe at that time, delete non-selected keyframe.\n                    if (!snapshot.selectedKeys.Exists(liveEditKey => AnimationKeyTime.Time(liveEditKey.key.time, frameRate).frame == AnimationKeyTime.Time(other.time, frameRate).frame))\n                        continue;\n\n                    toBeDeleted.Add(other);\n                }\n\n                foreach (AnimationWindowKeyframe deletedKey in toBeDeleted)\n                {\n                    snapshot.curve.RemoveKeyframe(deletedKey);\n                }\n            }\n\n            SaveCurves(activeAnimationClip, saveCurves, undoLabel);\n        }\n\n        public void RemoveCurve(AnimationWindowCurve curve, string undoLabel)\n        {\n            if (!curve.animationIsEditable)\n                return;\n\n            Undo.RegisterCompleteObjectUndo(curve.clip, undoLabel);\n\n            if (curve.isPPtrCurve)\n                AnimationUtility.SetObjectReferenceCurve(curve.clip, curve.binding, null);\n            else\n                AnimationUtility.SetEditorCurve(curve.clip, curve.binding, null);\n        }\n\n        public bool previewing\n        {\n            get => controlInterface.previewing;\n            set\n            {\n                if (controlInterface.previewing == value)\n                    return;\n\n                if (value)\n                {\n                    if (canPreview)\n                        controlInterface.previewing = true;\n                }\n                else\n                {\n                    // Automatically stop recording and playback when stopping preview.\n                    controlInterface.playing = false;\n                    controlInterface.recording = false;\n                    controlInterface.previewing = false;\n                }\n            }\n        }\n\n        public bool canPreview => controlInterface.canPreview;\n\n        public void UpdateCurvesDisplayName()\n        {\n            if (hierarchyData != null)\n                hierarchyData.UpdateSerializeReferenceCurvesArrayNiceDisplayName();\n        }\n\n        public bool recording\n        {\n            get => controlInterface.recording;\n            set\n            {\n                if (controlInterface.recording == value)\n                    return;\n\n                if (value)\n                {\n                    if (canRecord)\n                    {\n                        // Auto-Preview when starting recording\n                        controlInterface.previewing = true;\n\n                        if (controlInterface.previewing)\n                            controlInterface.recording = true;\n                    }\n                }\n                else\n                    controlInterface.recording = false;\n            }\n        }\n\n        public bool canRecord => controlInterface.canRecord;\n\n        public bool playing\n        {\n            get => controlInterface.playing;\n            set\n            {\n                if (controlInterface.playing == value)\n                    return;\n\n                if (value)\n                {\n                    if (canPlay)\n                    {\n                        // Auto-Preview when starting playback.\n                        controlInterface.previewing = true;\n\n                        if (controlInterface.previewing)\n                            controlInterface.playing = true;\n                    }\n                }\n                else\n                    controlInterface.playing = false;\n            }\n        }\n\n        public bool canPlay => controlInterface.canPlay;\n\n        public void ResampleAnimation()\n        {\n            if (disabled)\n                return;\n\n            if (controlInterface.previewing == false)\n                return;\n            if (controlInterface.canPreview == false)\n                return;\n\n            controlInterface.ResampleAnimation();\n        }\n\n        public bool PlaybackUpdate()\n        {\n            if (disabled)\n                return false;\n\n            if (!controlInterface.playing)\n                return false;\n\n            return controlInterface.PlaybackUpdate();\n        }\n\n        public void ClearCandidates() => controlInterface.ClearCandidates();\n        public void ProcessCandidates() => controlInterface.ProcessCandidates();\n\n        public bool ShouldShowCurve(AnimationWindowCurve curve)\n        {\n            if (filterBySelection && activeRootGameObject != null)\n            {\n                if (m_SelectionFilter != null)\n                {\n                    Transform t = activeRootGameObject.transform.Find(curve.path);\n                    if (t != null)\n                    {\n                        if (!m_SelectionFilter.Contains(t.gameObject.GetInstanceID()))\n                            return false;\n                    }\n                    else\n                    {\n                        return false;\n                    }\n                }\n            }\n\n            return true;\n        }\n\n        private void UpdateSelectionFilter()\n        {\n            m_SelectionFilter = (filterBySelection) ? (int[])Selection.instanceIDs.Clone() : null;\n        }\n\n        void RebuildAllCurvesCacheIfNecessary()\n        {\n            if (m_AllCurvesCacheDirty == false && m_AllCurvesCache != null)\n                return;\n\n            if (m_AllCurvesCache == null)\n                m_AllCurvesCache = new List<AnimationWindowCurve>();\n            else\n                m_AllCurvesCache.Clear();\n\n            var animationClip = activeAnimationClip;\n            if (animationClip == null || (!selection.animationIsEditable && !showReadOnly))\n                return;\n\n            EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(animationClip);\n            EditorCurveBinding[] objectCurveBindings = AnimationUtility.GetObjectReferenceCurveBindings(animationClip);\n\n            List<AnimationWindowCurve> transformCurves = new List<AnimationWindowCurve>();\n\n            foreach (EditorCurveBinding curveBinding in curveBindings)\n            {\n                if (AnimationWindowUtility.ShouldShowAnimationWindowCurve(curveBinding))\n                {\n                    AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, curveBinding, controlInterface.GetValueType(curveBinding));\n                    curve.selectionBinding = selection;\n\n                    m_AllCurvesCache.Add(curve);\n\n                    if (AnimationWindowUtility.IsActualTransformCurve(curveBinding))\n                    {\n                        transformCurves.Add(curve);\n                    }\n                }\n            }\n\n            foreach (EditorCurveBinding curveBinding in objectCurveBindings)\n            {\n                AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, curveBinding, controlInterface.GetValueType(curveBinding));\n                curve.selectionBinding = selection;\n\n                m_AllCurvesCache.Add(curve);\n            }\n\n            transformCurves.Sort();\n            if (transformCurves.Count > 0)\n            {\n                FillInMissingTransformCurves(animationClip, transformCurves, ref m_AllCurvesCache);\n            }\n\n            // Curves need to be sorted with path/type/property name so it's possible to construct hierarchy from them\n            // Sorting logic in AnimationWindowCurve.CompareTo()\n            m_AllCurvesCache.Sort();\n\n            m_AllCurvesCacheDirty = false;\n        }\n\n        private void RebuildFilteredCurvesCacheIfNecessary()\n        {\n            if (m_FilteredCurvesCacheDirty == false && m_FilteredCurvesCache != null)\n                return;\n\n            if (m_FilteredCurvesCache == null)\n                m_FilteredCurvesCache = new List<AnimationWindowCurve>();\n            else\n                m_FilteredCurvesCache.Clear();\n\n            for (int i = 0; i < m_AllCurvesCache.Count; ++i)\n            {\n                if (ShouldShowCurve(m_AllCurvesCache[i]))\n                    m_FilteredCurvesCache.Add(m_AllCurvesCache[i]);\n            }\n\n            m_FilteredCurvesCacheDirty = false;\n        }\n\n        private void RebuildActiveCurvesCacheIfNecessary()\n        {\n            if (m_ActiveCurvesCacheDirty == false && m_ActiveCurvesCache != null)\n                return;\n\n            if (m_ActiveCurvesCache == null)\n                m_ActiveCurvesCache = new List<AnimationWindowCurve>();\n            else\n                m_ActiveCurvesCache.Clear();\n\n            if (hierarchyState != null && hierarchyData != null)\n            {\n                foreach (int id in hierarchyState.selectedIDs)\n                {\n                    TreeViewItem node = hierarchyData.FindItem(id);\n                    AnimationWindowHierarchyNode hierarchyNode = node as AnimationWindowHierarchyNode;\n\n                    if (hierarchyNode == null)\n                        continue;\n\n                    AnimationWindowCurve[] curves = hierarchyNode.curves;\n                    if (curves == null)\n                        continue;\n\n                    foreach (AnimationWindowCurve curve in curves)\n                        if (!m_ActiveCurvesCache.Contains(curve))\n                            m_ActiveCurvesCache.Add(curve);\n                }\n\n                m_ActiveCurvesCache.Sort();\n            }\n\n            m_ActiveCurvesCacheDirty = false;\n        }\n\n        private void FillInMissingTransformCurves(AnimationClip animationClip, List<AnimationWindowCurve> transformCurves, ref List<AnimationWindowCurve> curvesCache)\n        {\n            EditorCurveBinding lastBinding = transformCurves[0].binding;\n            var propertyGroup = new EditorCurveBinding ? [3];\n            string propertyGroupName;\n            foreach (var transformCurve in transformCurves)\n            {\n                var transformBinding = transformCurve.binding;\n                //if it's a new property group\n                if (transformBinding.path != lastBinding.path\n                    || AnimationWindowUtility.GetPropertyGroupName(transformBinding.propertyName) != AnimationWindowUtility.GetPropertyGroupName(lastBinding.propertyName))\n                {\n                    propertyGroupName = AnimationWindowUtility.GetPropertyGroupName(lastBinding.propertyName);\n\n                    FillPropertyGroup(animationClip, ref propertyGroup, lastBinding, propertyGroupName, ref curvesCache);\n\n                    lastBinding = transformBinding;\n\n                    propertyGroup = new EditorCurveBinding ? [3];\n                }\n\n                AssignBindingToRightSlot(transformBinding, ref propertyGroup);\n            }\n            FillPropertyGroup(animationClip, ref propertyGroup, lastBinding, AnimationWindowUtility.GetPropertyGroupName(lastBinding.propertyName), ref curvesCache);\n        }\n\n        private void FillPropertyGroup(AnimationClip animationClip, ref EditorCurveBinding?[] propertyGroup, EditorCurveBinding lastBinding, string propertyGroupName, ref List<AnimationWindowCurve> curvesCache)\n        {\n            var newBinding = lastBinding;\n            newBinding.isPhantom = true;\n            if (!propertyGroup[0].HasValue)\n            {\n                newBinding.propertyName = propertyGroupName + \".x\";\n                AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, newBinding, controlInterface.GetValueType(newBinding));\n                curve.selectionBinding = selection;\n                curvesCache.Add(curve);\n            }\n\n            if (!propertyGroup[1].HasValue)\n            {\n                newBinding.propertyName = propertyGroupName + \".y\";\n                AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, newBinding, controlInterface.GetValueType(newBinding));\n                curve.selectionBinding = selection;\n                curvesCache.Add(curve);\n            }\n\n            if (!propertyGroup[2].HasValue)\n            {\n                newBinding.propertyName = propertyGroupName + \".z\";\n                AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, newBinding, controlInterface.GetValueType(newBinding));\n                curve.selectionBinding = selection;\n                curvesCache.Add(curve);\n            }\n        }\n\n        private void AssignBindingToRightSlot(EditorCurveBinding transformBinding, ref EditorCurveBinding?[] propertyGroup)\n        {\n            if (transformBinding.propertyName.EndsWith(\".x\"))\n            {\n                propertyGroup[0] = transformBinding;\n            }\n            else if (transformBinding.propertyName.EndsWith(\".y\"))\n            {\n                propertyGroup[1] = transformBinding;\n            }\n            else if (transformBinding.propertyName.EndsWith(\".z\"))\n            {\n                propertyGroup[2] = transformBinding;\n            }\n        }\n\n        public List<AnimationWindowCurve> allCurves\n        {\n            get\n            {\n                RebuildAllCurvesCacheIfNecessary();\n                return m_AllCurvesCache;\n            }\n        }\n\n        public List<AnimationWindowCurve> filteredCurves\n        {\n            get\n            {\n                RebuildAllCurvesCacheIfNecessary();\n                RebuildFilteredCurvesCacheIfNecessary();\n                return m_FilteredCurvesCache;\n            }\n        }\n\n        public List<AnimationWindowCurve> activeCurves\n        {\n            get\n            {\n                RebuildActiveCurvesCacheIfNecessary();\n                return m_ActiveCurvesCache;\n            }\n        }\n\n        public CurveWrapper[] activeCurveWrappers\n        {\n            get\n            {\n                if (m_ActiveCurveWrappersCache == null || m_ActiveCurvesCache == null)\n                {\n                    List<CurveWrapper> activeCurveWrappers = new List<CurveWrapper>();\n                    foreach (AnimationWindowCurve curve in activeCurves)\n                        if (AnimationWindowUtility.GetCurveWrapper(curve, curve.clip) is CurveWrapper wrapper)\n                            activeCurveWrappers.Add(wrapper);\n\n                    // If there are no active curves, we would end up with empty curve editor so we just give all curves insteads\n                    if (!activeCurveWrappers.Any())\n                        foreach (AnimationWindowCurve curve in filteredCurves)\n                            if (AnimationWindowUtility.GetCurveWrapper(curve, curve.clip) is CurveWrapper wrapper)\n                                activeCurveWrappers.Add(wrapper);\n\n                    m_ActiveCurveWrappersCache = activeCurveWrappers.ToArray();\n                }\n\n                return m_ActiveCurveWrappersCache;\n            }\n        }\n\n        public List<DopeLine> dopelines\n        {\n            get\n            {\n                if (m_dopelinesCache == null)\n                {\n                    m_dopelinesCache = new List<DopeLine>();\n\n                    if (hierarchyData != null)\n                    {\n                        foreach (TreeViewItem node in hierarchyData.GetRows())\n                        {\n                            AnimationWindowHierarchyNode hierarchyNode = node as AnimationWindowHierarchyNode;\n\n                            if (hierarchyNode == null || hierarchyNode is AnimationWindowHierarchyAddButtonNode)\n                                continue;\n\n                            AnimationWindowCurve[] curves = hierarchyNode.curves;\n                            if (curves == null)\n                                continue;\n\n                            DopeLine dopeLine = new DopeLine(node.id, curves);\n                            dopeLine.tallMode = hierarchyState.GetTallMode(hierarchyNode);\n                            dopeLine.objectType = hierarchyNode.animatableObjectType;\n                            dopeLine.hasChildren = !(hierarchyNode is AnimationWindowHierarchyPropertyNode);\n                            dopeLine.isMasterDopeline = node is AnimationWindowHierarchyMasterNode;\n                            m_dopelinesCache.Add(dopeLine);\n                        }\n                    }\n                }\n                return m_dopelinesCache;\n            }\n        }\n\n        public List<AnimationWindowHierarchyNode> selectedHierarchyNodes\n        {\n            get\n            {\n                List<AnimationWindowHierarchyNode> selectedHierarchyNodes = new List<AnimationWindowHierarchyNode>();\n\n                if (activeAnimationClip != null && hierarchyData != null)\n                {\n                    foreach (int id in hierarchyState.selectedIDs)\n                    {\n                        AnimationWindowHierarchyNode hierarchyNode = (AnimationWindowHierarchyNode)hierarchyData.FindItem(id);\n\n                        if (hierarchyNode == null || hierarchyNode is AnimationWindowHierarchyAddButtonNode)\n                            continue;\n\n                        selectedHierarchyNodes.Add(hierarchyNode);\n                    }\n                }\n\n                return selectedHierarchyNodes;\n            }\n        }\n\n        public AnimationWindowKeyframe activeKeyframe\n        {\n            get\n            {\n                if (m_ActiveKeyframeCache == null)\n                {\n                    foreach (AnimationWindowCurve curve in filteredCurves)\n                    {\n                        foreach (AnimationWindowKeyframe keyframe in curve.keyframes)\n                        {\n                            if (keyframe.GetHash() == m_ActiveKeyframeHash)\n                                m_ActiveKeyframeCache = keyframe;\n                        }\n                    }\n                }\n                return m_ActiveKeyframeCache;\n            }\n            set\n            {\n                m_ActiveKeyframeCache = null;\n                m_ActiveKeyframeHash = value != null ? value.GetHash() : 0;\n            }\n        }\n\n        public List<AnimationWindowKeyframe> selectedKeys\n        {\n            get\n            {\n                if (m_SelectedKeysCache == null)\n                {\n                    m_SelectedKeysCache = new List<AnimationWindowKeyframe>();\n                    foreach (AnimationWindowCurve curve in filteredCurves)\n                    {\n                        foreach (AnimationWindowKeyframe keyframe in curve.keyframes)\n                        {\n                            if (KeyIsSelected(keyframe))\n                            {\n                                m_SelectedKeysCache.Add(keyframe);\n                            }\n                        }\n                    }\n                }\n                return m_SelectedKeysCache;\n            }\n        }\n\n        public Bounds selectionBounds\n        {\n            get\n            {\n                if (m_SelectionBoundsCache == null)\n                {\n                    List<AnimationWindowKeyframe> keys = selectedKeys;\n                    if (keys.Count > 0)\n                    {\n                        AnimationWindowKeyframe key = keys[0];\n                        float time = key.time;\n                        float val = key.isPPtrCurve || key.isDiscreteCurve ? 0.0f : (float)key.value;\n\n                        Bounds bounds = new Bounds(new Vector2(time, val), Vector2.zero);\n\n                        for (int i = 1; i < keys.Count; ++i)\n                        {\n                            key = keys[i];\n\n                            time = key.time;\n                            val = key.isPPtrCurve || key.isDiscreteCurve ? 0.0f : (float)key.value;\n\n                            bounds.Encapsulate(new Vector2(time, val));\n                        }\n\n                        m_SelectionBoundsCache = bounds;\n                    }\n                    else\n                    {\n                        m_SelectionBoundsCache = new Bounds(Vector2.zero, Vector2.zero);\n                    }\n                }\n\n                return m_SelectionBoundsCache.Value;\n            }\n        }\n\n        private HashSet<int> selectedKeyHashes\n        {\n            get\n            {\n                if (m_KeySelection == null)\n                {\n                    m_KeySelection = ScriptableObject.CreateInstance<AnimationWindowKeySelection>();\n                    m_KeySelection.hideFlags = HideFlags.HideAndDontSave;\n                }\n\n                return m_KeySelection.selectedKeyHashes;\n            }\n            set\n            {\n                if (m_KeySelection == null)\n                {\n                    m_KeySelection = ScriptableObject.CreateInstance<AnimationWindowKeySelection>();\n                    m_KeySelection.hideFlags = HideFlags.HideAndDontSave;\n                }\n\n                m_KeySelection.selectedKeyHashes = value;\n            }\n        }\n\n        public bool AnyKeyIsSelected(DopeLine dopeline)\n        {\n            foreach (AnimationWindowKeyframe keyframe in dopeline.keys)\n                if (KeyIsSelected(keyframe))\n                    return true;\n\n            return false;\n        }\n\n        public bool KeyIsSelected(AnimationWindowKeyframe keyframe)\n        {\n            return selectedKeyHashes.Contains(keyframe.GetHash());\n        }\n\n        public void SelectKey(AnimationWindowKeyframe keyframe)\n        {\n            int hash = keyframe.GetHash();\n            if (!selectedKeyHashes.Contains(hash))\n                selectedKeyHashes.Add(hash);\n\n            m_SelectedKeysCache = null;\n            m_SelectionBoundsCache = null;\n        }\n\n        public void UnselectKey(AnimationWindowKeyframe keyframe)\n        {\n            int hash = keyframe.GetHash();\n            if (selectedKeyHashes.Contains(hash))\n                selectedKeyHashes.Remove(hash);\n\n            m_SelectedKeysCache = null;\n            m_SelectionBoundsCache = null;\n        }\n\n        public void DeleteSelectedKeys()\n        {\n            if (selectedKeys.Count == 0)\n                return;\n\n            DeleteKeys(selectedKeys);\n        }\n\n        public void DeleteKeys(List<AnimationWindowKeyframe> keys)\n        {\n            SaveKeySelection(kEditCurveUndoLabel);\n\n            HashSet<AnimationWindowCurve> curves = new HashSet<AnimationWindowCurve>();\n\n            foreach (AnimationWindowKeyframe keyframe in keys)\n            {\n                if (!keyframe.curve.animationIsEditable)\n                    continue;\n\n                curves.Add(keyframe.curve);\n\n                UnselectKey(keyframe);\n                keyframe.curve.RemoveKeyframe(keyframe);\n            }\n\n            SaveCurves(activeAnimationClip, curves, kEditCurveUndoLabel);\n\n            ResampleAnimation();\n        }\n\n        public void StartLiveEdit()\n        {\n            if (onStartLiveEdit != null)\n                onStartLiveEdit();\n\n            m_LiveEditSnapshot = new List<LiveEditCurve>();\n\n            SaveKeySelection(kEditCurveUndoLabel);\n\n            foreach (AnimationWindowKeyframe selectedKey in selectedKeys)\n            {\n                if (!m_LiveEditSnapshot.Exists(snapshot => snapshot.curve == selectedKey.curve))\n                {\n                    LiveEditCurve snapshot = new LiveEditCurve();\n                    snapshot.curve = selectedKey.curve;\n                    foreach (AnimationWindowKeyframe key in selectedKey.curve.keyframes)\n                    {\n                        LiveEditKeyframe liveEditKey = new LiveEditKeyframe();\n                        liveEditKey.keySnapshot = new AnimationWindowKeyframe(key);\n                        liveEditKey.key = key;\n\n                        if (KeyIsSelected(key))\n                            snapshot.selectedKeys.Add(liveEditKey);\n                        else\n                            snapshot.unselectedKeys.Add(liveEditKey);\n                    }\n\n                    m_LiveEditSnapshot.Add(snapshot);\n                }\n            }\n        }\n\n        public void EndLiveEdit()\n        {\n            SaveSelectedKeys(kEditCurveUndoLabel);\n\n            m_LiveEditSnapshot = null;\n\n            if (onEndLiveEdit != null)\n                onEndLiveEdit();\n        }\n\n        public bool InLiveEdit()\n        {\n            return m_LiveEditSnapshot != null;\n        }\n\n        public void MoveSelectedKeys(float deltaTime, bool snapToFrame)\n        {\n            bool inLiveEdit = InLiveEdit();\n            if (!inLiveEdit)\n                StartLiveEdit();\n\n            // Clear selections since all hashes are now different\n            ClearKeySelections();\n\n            foreach (LiveEditCurve snapshot in m_LiveEditSnapshot)\n            {\n                foreach (LiveEditKeyframe liveEditKey in snapshot.selectedKeys)\n                {\n                    if (snapshot.curve.animationIsEditable)\n                    {\n                        liveEditKey.key.time = Mathf.Max(liveEditKey.keySnapshot.time + deltaTime, 0f);\n\n                        if (snapToFrame)\n                            liveEditKey.key.time = SnapToFrame(liveEditKey.key.time, snapshot.curve.clip.frameRate);\n                    }\n\n                    SelectKey(liveEditKey.key);\n                }\n            }\n\n            if (!inLiveEdit)\n                EndLiveEdit();\n        }\n\n        public void TransformSelectedKeys(Matrix4x4 matrix, bool flipX, bool flipY, bool snapToFrame)\n        {\n            bool inLiveEdit = InLiveEdit();\n            if (!inLiveEdit)\n                StartLiveEdit();\n\n            // Clear selections since all hashes are now different\n            ClearKeySelections();\n\n            foreach (LiveEditCurve snapshot in m_LiveEditSnapshot)\n            {\n                foreach (LiveEditKeyframe liveEditKey in snapshot.selectedKeys)\n                {\n                    if (snapshot.curve.animationIsEditable)\n                    {\n                        // Transform time value.\n                        Vector3 v = new Vector3(liveEditKey.keySnapshot.time, liveEditKey.keySnapshot.isPPtrCurve || liveEditKey.keySnapshot.isDiscreteCurve ? 0f : (float)liveEditKey.keySnapshot.value, 0f);\n                        v = matrix.MultiplyPoint3x4(v);\n\n                        liveEditKey.key.time = Mathf.Max((snapToFrame) ? SnapToFrame(v.x, snapshot.curve.clip.frameRate) : v.x, 0f);\n\n                        if (flipX)\n                        {\n                            liveEditKey.key.inTangent = (liveEditKey.keySnapshot.outTangent != Mathf.Infinity) ? -liveEditKey.keySnapshot.outTangent : Mathf.Infinity;\n                            liveEditKey.key.outTangent = (liveEditKey.keySnapshot.inTangent != Mathf.Infinity) ? -liveEditKey.keySnapshot.inTangent : Mathf.Infinity;\n\n                            if (liveEditKey.keySnapshot.weightedMode == WeightedMode.In)\n                                liveEditKey.key.weightedMode = WeightedMode.Out;\n                            else if (liveEditKey.keySnapshot.weightedMode == WeightedMode.Out)\n                                liveEditKey.key.weightedMode = WeightedMode.In;\n                            else\n                                liveEditKey.key.weightedMode = liveEditKey.keySnapshot.weightedMode;\n\n                            liveEditKey.key.inWeight = liveEditKey.keySnapshot.outWeight;\n                            liveEditKey.key.outWeight = liveEditKey.keySnapshot.inWeight;\n                        }\n\n                        if (!liveEditKey.key.isPPtrCurve && !liveEditKey.key.isDiscreteCurve)\n                        {\n                            liveEditKey.key.value = v.y;\n\n                            if (flipY)\n                            {\n                                liveEditKey.key.inTangent = (liveEditKey.key.inTangent != Mathf.Infinity) ? -liveEditKey.key.inTangent : Mathf.Infinity;\n                                liveEditKey.key.outTangent = (liveEditKey.key.outTangent != Mathf.Infinity) ? -liveEditKey.key.outTangent : Mathf.Infinity;\n                            }\n                        }\n                    }\n\n                    SelectKey(liveEditKey.key);\n                }\n            }\n\n            if (!inLiveEdit)\n                EndLiveEdit();\n        }\n\n        public void TransformRippleKeys(Matrix4x4 matrix, float t1, float t2, bool flipX, bool snapToFrame)\n        {\n            bool inLiveEdit = InLiveEdit();\n            if (!inLiveEdit)\n                StartLiveEdit();\n\n            // Clear selections since all hashes are now different\n            ClearKeySelections();\n\n            foreach (LiveEditCurve snapshot in m_LiveEditSnapshot)\n            {\n                foreach (LiveEditKeyframe liveEditKey in snapshot.selectedKeys)\n                {\n                    if (snapshot.curve.animationIsEditable)\n                    {\n                        Vector3 v = new Vector3(liveEditKey.keySnapshot.time, 0f, 0f);\n                        v = matrix.MultiplyPoint3x4(v);\n\n                        liveEditKey.key.time = Mathf.Max((snapToFrame) ? SnapToFrame(v.x, snapshot.curve.clip.frameRate) : v.x, 0f);\n\n                        if (flipX)\n                        {\n                            liveEditKey.key.inTangent = (liveEditKey.keySnapshot.outTangent != Mathf.Infinity) ? -liveEditKey.keySnapshot.outTangent : Mathf.Infinity;\n                            liveEditKey.key.outTangent = (liveEditKey.keySnapshot.inTangent != Mathf.Infinity) ? -liveEditKey.keySnapshot.inTangent : Mathf.Infinity;\n                        }\n                    }\n\n                    SelectKey(liveEditKey.key);\n                }\n\n                if (!snapshot.curve.animationIsEditable)\n                    continue;\n\n                foreach (LiveEditKeyframe liveEditKey in snapshot.unselectedKeys)\n                {\n                    if (liveEditKey.keySnapshot.time > t2)\n                    {\n                        Vector3 v = new Vector3(flipX ? t1 : t2, 0f, 0f);\n                        v = matrix.MultiplyPoint3x4(v);\n\n                        float dt = v.x - t2;\n                        if (dt > 0f)\n                        {\n                            float newTime = liveEditKey.keySnapshot.time + dt;\n                            liveEditKey.key.time = Mathf.Max((snapToFrame) ? SnapToFrame(newTime, snapshot.curve.clip.frameRate) : newTime, 0f);\n                        }\n                        else\n                        {\n                            liveEditKey.key.time = liveEditKey.keySnapshot.time;\n                        }\n                    }\n                    else if (liveEditKey.keySnapshot.time < t1)\n                    {\n                        Vector3 v = new Vector3(flipX ? t2 : t1, 0f, 0f);\n                        v = matrix.MultiplyPoint3x4(v);\n\n                        float dt = v.x - t1;\n                        if (dt < 0f)\n                        {\n                            float newTime = liveEditKey.keySnapshot.time + dt;\n                            liveEditKey.key.time = Mathf.Max((snapToFrame) ? SnapToFrame(newTime, snapshot.curve.clip.frameRate) : newTime, 0f);\n                        }\n                        else\n                        {\n                            liveEditKey.key.time = liveEditKey.keySnapshot.time;\n                        }\n                    }\n                }\n            }\n\n            if (!inLiveEdit)\n                EndLiveEdit();\n        }\n\n        internal static bool CanPasteKeys()\n        {\n            return s_KeyframeClipboard != null && s_KeyframeClipboard.Count > 0;\n        }\n\n        internal static void ClearKeyframeClipboard()\n        {\n            s_KeyframeClipboard?.Clear();\n        }\n\n        public void CopyKeys()\n        {\n            if (s_KeyframeClipboard == null)\n                s_KeyframeClipboard = new List<AnimationWindowKeyframe>();\n\n            float smallestTime = float.MaxValue;\n            s_KeyframeClipboard.Clear();\n            foreach (AnimationWindowKeyframe keyframe in selectedKeys)\n            {\n                s_KeyframeClipboard.Add(new AnimationWindowKeyframe(keyframe));\n                if (keyframe.time < smallestTime)\n                    smallestTime = keyframe.time;\n            }\n            if (s_KeyframeClipboard.Count > 0) // copying selected keys\n            {\n                foreach (AnimationWindowKeyframe keyframe in s_KeyframeClipboard)\n                {\n                    keyframe.time -= smallestTime;\n                }\n            }\n            else // No selected keys, lets copy entire curves\n            {\n                CopyAllActiveCurves();\n            }\n\n            // Animation keyframes right now do not go through regular clipboard machinery,\n            // so when copying keyframes, make sure regular clipboard is cleared, or things\n            // get confusing.\n            if (s_KeyframeClipboard.Count > 0)\n                Clipboard.stringValue = string.Empty;\n        }\n\n        public void CopyAllActiveCurves()\n        {\n            foreach (AnimationWindowCurve curve in activeCurves)\n            {\n                foreach (AnimationWindowKeyframe keyframe in curve.keyframes)\n                {\n                    s_KeyframeClipboard.Add(new AnimationWindowKeyframe(keyframe));\n                }\n            }\n        }\n\n        public void PasteKeys()\n        {\n            if (s_KeyframeClipboard == null)\n                s_KeyframeClipboard = new List<AnimationWindowKeyframe>();\n\n            SaveKeySelection(kEditCurveUndoLabel);\n\n            HashSet<int> oldSelection = new HashSet<int>(selectedKeyHashes);\n            ClearKeySelections();\n\n            AnimationWindowCurve lastTargetCurve = null;\n            AnimationWindowCurve lastSourceCurve = null;\n            float lastTime = 0f;\n\n            List<AnimationWindowCurve> clipboardCurves = new List<AnimationWindowCurve>();\n            foreach (AnimationWindowKeyframe keyframe in s_KeyframeClipboard)\n                if (!clipboardCurves.Any() || clipboardCurves.Last() != keyframe.curve)\n                    clipboardCurves.Add(keyframe.curve);\n\n            // If we have equal number of target and source curves, then match by index. If not, then try to match with AnimationWindowUtility.BestMatchForPaste.\n            bool matchCurveByIndex = clipboardCurves.Count == activeCurves.Count;\n            int targetIndex = 0;\n\n            foreach (AnimationWindowKeyframe keyframe in s_KeyframeClipboard)\n            {\n                if (lastSourceCurve != null && keyframe.curve != lastSourceCurve)\n                    targetIndex++;\n\n                AnimationWindowKeyframe newKeyframe = new AnimationWindowKeyframe(keyframe);\n\n                if (matchCurveByIndex)\n                    newKeyframe.curve = activeCurves[targetIndex];\n                else\n                    newKeyframe.curve = AnimationWindowUtility.BestMatchForPaste(newKeyframe.curve.binding, clipboardCurves, activeCurves);\n\n                if (newKeyframe.curve == null) // Paste as new curve\n                {\n                    // Curves are selected in the animation window hierarchy.  Since we couldn't find a proper match,\n                    // create a new curve in first selected clip in active curves.\n                    if (activeCurves.Count > 0)\n                    {\n                        AnimationWindowCurve firstCurve = activeCurves[0];\n                        if (firstCurve.animationIsEditable)\n                        {\n                            newKeyframe.curve = new AnimationWindowCurve(firstCurve.clip, keyframe.curve.binding, keyframe.curve.valueType);\n                            newKeyframe.curve.selectionBinding = firstCurve.selectionBinding;\n                            newKeyframe.time = keyframe.time;\n                        }\n                    }\n                    // If nothing is selected, create a new curve in first selected clip.\n                    else\n                    {\n                        if (selection.animationIsEditable)\n                        {\n                            newKeyframe.curve = new AnimationWindowCurve(selection.animationClip, keyframe.curve.binding, keyframe.curve.valueType);\n                            newKeyframe.curve.selectionBinding = selection;\n                            newKeyframe.time = keyframe.time;\n                        }\n                    }\n                }\n\n                if (newKeyframe.curve == null || !newKeyframe.curve.animationIsEditable)\n                    continue;\n\n                newKeyframe.time = AnimationKeyTime.Time(newKeyframe.time + currentTime, newKeyframe.curve.clip.frameRate).timeRound;\n\n                //  Only allow pasting of key frame from numerical curves to numerical curves or from pptr curves to pptr curves.\n                if ((newKeyframe.time >= 0.0f) && (newKeyframe.curve != null) && (newKeyframe.curve.isPPtrCurve == keyframe.curve.isPPtrCurve))\n                {\n                    var keyTime = AnimationKeyTime.Time(newKeyframe.time, newKeyframe.curve.clip.frameRate);\n\n                    if (newKeyframe.curve.HasKeyframe(keyTime))\n                        newKeyframe.curve.RemoveKeyframe(keyTime);\n\n                    // When copy-pasting multiple keyframes (curve), its a continous thing. This is why we delete the existing keyframes in the pasted range.\n                    if (lastTargetCurve == newKeyframe.curve)\n                        newKeyframe.curve.RemoveKeysAtRange(lastTime, newKeyframe.time);\n\n                    newKeyframe.curve.AddKeyframe(newKeyframe, keyTime);\n                    SelectKey(newKeyframe);\n                    // TODO: Optimize to only save curve once instead once per keyframe\n                    SaveCurve(newKeyframe.curve.clip, newKeyframe.curve, kEditCurveUndoLabel);\n\n                    lastTargetCurve = newKeyframe.curve;\n                    lastTime = newKeyframe.time;\n                }\n\n                lastSourceCurve = keyframe.curve;\n            }\n\n            // If nothing is pasted, then we revert to old selection\n            if (selectedKeyHashes.Count == 0)\n                selectedKeyHashes = oldSelection;\n            else\n                ResampleAnimation();\n        }\n\n        public void ClearSelections()\n        {\n            ClearKeySelections();\n            ClearHierarchySelection();\n        }\n\n        public void ClearKeySelections()\n        {\n            selectedKeyHashes.Clear();\n            m_SelectedKeysCache = null;\n            m_SelectionBoundsCache = null;\n        }\n\n        public void ClearHierarchySelection()\n        {\n            hierarchyState.selectedIDs.Clear();\n            m_ActiveCurvesCache = null;\n        }\n\n        private void ClearCurveWrapperCache()\n        {\n            if (m_ActiveCurveWrappersCache == null)\n                return;\n\n            for (int i = 0; i < m_ActiveCurveWrappersCache.Length; ++i)\n            {\n                CurveWrapper curveWrapper = m_ActiveCurveWrappersCache[i];\n                if (curveWrapper.renderer != null)\n                    curveWrapper.renderer.FlushCache();\n            }\n\n            m_ActiveCurveWrappersCache = null;\n        }\n\n        private void ReloadModifiedDopelineCache()\n        {\n            if (m_dopelinesCache == null)\n                return;\n\n            for (int i = 0; i < m_dopelinesCache.Count; ++i)\n            {\n                DopeLine dopeLine = m_dopelinesCache[i];\n                AnimationWindowCurve[] curves = dopeLine.curves;\n                for (int j = 0; j < curves.Length; ++j)\n                {\n                    if (m_ModifiedCurves.Contains(curves[j].GetHashCode()))\n                    {\n                        dopeLine.InvalidateKeyframes();\n                        break;\n                    }\n                }\n            }\n        }\n\n        private void ReloadModifiedCurveWrapperCache()\n        {\n            if (m_ActiveCurveWrappersCache == null)\n                return;\n\n            Dictionary<int, AnimationWindowCurve> updateList = new Dictionary<int, AnimationWindowCurve>();\n\n            for (int i = 0; i < m_ActiveCurveWrappersCache.Length; ++i)\n            {\n                CurveWrapper curveWrapper = m_ActiveCurveWrappersCache[i];\n\n                if (m_ModifiedCurves.Contains(curveWrapper.id))\n                {\n                    AnimationWindowCurve curve = filteredCurves.Find(c => c.GetHashCode() == curveWrapper.id);\n                    if (curve != null)\n                    {\n                        //  Boundaries have changed, invalidate all curves\n                        if (curve.clip.startTime != curveWrapper.renderer.RangeStart() ||\n                            curve.clip.stopTime != curveWrapper.renderer.RangeEnd())\n                        {\n                            ClearCurveWrapperCache();\n                            return;\n                        }\n                        else\n                        {\n                            updateList[i] = curve;\n                        }\n                    }\n                }\n            }\n\n            //  Only update curve wrappers that were modified.\n            for (int i = 0; i < updateList.Count; ++i)\n            {\n                var entry = updateList.ElementAt(i);\n\n                CurveWrapper curveWrapper = m_ActiveCurveWrappersCache[entry.Key];\n                if (curveWrapper.renderer != null)\n                    curveWrapper.renderer.FlushCache();\n\n                // Recreate curve wrapper only if curve has been modified.\n                m_ActiveCurveWrappersCache[entry.Key] = AnimationWindowUtility.GetCurveWrapper(entry.Value, entry.Value.clip);\n            }\n        }\n\n        private void ReloadModifiedAnimationCurveCache()\n        {\n            for (int i = 0; i < filteredCurves.Count; ++i)\n            {\n                AnimationWindowCurve curve = filteredCurves[i];\n                if (m_ModifiedCurves.Contains(curve.GetHashCode()))\n                    curve.LoadKeyframes(curve.clip);\n            }\n        }\n\n        // This is called when there is a new curve, but after the data refresh.\n        // This means that hierarchynodes and dopeline(s) for new curve are already available.\n        private void OnNewCurveAdded(EditorCurveBinding newCurve)\n        {\n            //  Retrieve group property name.\n            //  For example if we got \"position.z\" as our newCurve,\n            //  the property will be \"position\" with three child child nodes x,y,z\n            string propertyName = newCurve.propertyName;\n            string groupPropertyName = AnimationWindowUtility.GetPropertyGroupName(newCurve.propertyName);\n\n            if (hierarchyData == null)\n                return;\n\n            if (HasHierarchySelection())\n            {\n                // Update hierarchy selection with newly created curve.\n                foreach (AnimationWindowHierarchyNode node in hierarchyData.GetRows())\n                {\n                    if (node.path != newCurve.path ||\n                        node.animatableObjectType != newCurve.type ||\n                        (node.propertyName != propertyName && node.propertyName != groupPropertyName))\n                        continue;\n\n                    SelectHierarchyItem(node.id, true, false);\n\n                    // We want the pptr curves to be in tall mode by default\n                    if (newCurve.isPPtrCurve)\n                        hierarchyState.AddTallInstance(node.id);\n                }\n            }\n\n            //  Values do not change whenever a new curve is added, so we force an inspector update here.\n            ResampleAnimation();\n\n            m_lastAddedCurveBinding = null;\n        }\n\n        public void Repaint()\n        {\n            if (animEditor != null)\n                animEditor.Repaint();\n        }\n\n        public List<AnimationWindowKeyframe> GetAggregateKeys(AnimationWindowHierarchyNode hierarchyNode)\n        {\n            DopeLine dopeline = dopelines.FirstOrDefault(e => e.hierarchyNodeID == hierarchyNode.id);\n            if (dopeline == null)\n                return null;\n            return dopeline.keys;\n        }\n\n        public void OnHierarchySelectionChanged(int[] selectedInstanceIDs)\n        {\n            HandleHierarchySelectionChanged(selectedInstanceIDs, true);\n        }\n\n        public void HandleHierarchySelectionChanged(int[] selectedInstanceIDs, bool triggerSceneSelectionSync)\n        {\n            m_ActiveCurvesCache = null;\n\n            if (triggerSceneSelectionSync)\n                SyncSceneSelection(selectedInstanceIDs);\n        }\n\n        public void SelectHierarchyItem(DopeLine dopeline, bool additive)\n        {\n            SelectHierarchyItem(dopeline.hierarchyNodeID, additive, true);\n        }\n\n        public void SelectHierarchyItem(DopeLine dopeline, bool additive, bool triggerSceneSelectionSync)\n        {\n            SelectHierarchyItem(dopeline.hierarchyNodeID, additive, triggerSceneSelectionSync);\n        }\n\n        public void SelectHierarchyItem(int hierarchyNodeID, bool additive, bool triggerSceneSelectionSync)\n        {\n            if (!additive)\n                ClearHierarchySelection();\n\n            hierarchyState.selectedIDs.Add(hierarchyNodeID);\n\n            int[] selectedInstanceIDs = hierarchyState.selectedIDs.ToArray();\n\n            // We need to manually trigger this event, because injecting data to m_SelectedInstanceIDs directly doesn't trigger one via TreeView\n            HandleHierarchySelectionChanged(selectedInstanceIDs, triggerSceneSelectionSync);\n        }\n\n        public void SelectHierarchyItems(IEnumerable<int> hierarchyNodeIDs, bool additive, bool triggerSceneSelectionSync)\n        {\n            if (!additive)\n                ClearHierarchySelection();\n\n            hierarchyState.selectedIDs.AddRange(hierarchyNodeIDs);\n\n            int[] selectedInstanceIDs = hierarchyState.selectedIDs.ToArray();\n\n            // We need to manually trigger this event, because injecting data to m_SelectedInstanceIDs directly doesn't trigger one via TreeView\n            HandleHierarchySelectionChanged(selectedInstanceIDs, triggerSceneSelectionSync);\n        }\n\n        public void UnSelectHierarchyItem(DopeLine dopeline)\n        {\n            UnSelectHierarchyItem(dopeline.hierarchyNodeID);\n        }\n\n        public void UnSelectHierarchyItem(int hierarchyNodeID)\n        {\n            hierarchyState.selectedIDs.Remove(hierarchyNodeID);\n        }\n\n        public bool HasHierarchySelection()\n        {\n            if (hierarchyState.selectedIDs.Count == 0)\n                return false;\n\n            if (hierarchyState.selectedIDs.Count == 1)\n                return (hierarchyState.selectedIDs[0] != 0);\n\n            return true;\n        }\n\n        public HashSet<int> GetAffectedHierarchyIDs(List<AnimationWindowKeyframe> keyframes)\n        {\n            HashSet<int> hierarchyIDs = new HashSet<int>();\n\n            foreach (AnimationWindowKeyframe keyframe in keyframes)\n            {\n                var curve = keyframe.curve;\n\n                int hierarchyID = AnimationWindowUtility.GetPropertyNodeID(0, curve.path, curve.type, curve.propertyName);\n                if (hierarchyIDs.Add(hierarchyID))\n                {\n                    string propertyGroupName = AnimationWindowUtility.GetPropertyGroupName(curve.propertyName);\n                    hierarchyIDs.Add(AnimationWindowUtility.GetPropertyNodeID(0, curve.path, curve.type, propertyGroupName));\n                }\n            }\n\n            return hierarchyIDs;\n        }\n\n        public List<AnimationWindowCurve> GetAffectedCurves(List<AnimationWindowKeyframe> keyframes)\n        {\n            List<AnimationWindowCurve> affectedCurves = new List<AnimationWindowCurve>();\n\n            foreach (AnimationWindowKeyframe keyframe in keyframes)\n                if (!affectedCurves.Contains(keyframe.curve))\n                    affectedCurves.Add(keyframe.curve);\n\n            return affectedCurves;\n        }\n\n        public DopeLine GetDopeline(int selectedInstanceID)\n        {\n            foreach (var dopeline in dopelines)\n            {\n                if (dopeline.hierarchyNodeID == selectedInstanceID)\n                    return dopeline;\n            }\n\n            return null;\n        }\n\n        // Set scene active go to be the same as the one selected from hierarchy\n        private void SyncSceneSelection(int[] selectedNodeIDs)\n        {\n            if (filterBySelection)\n                return;\n\n            if (!selection.canSyncSceneSelection)\n                return;\n\n            GameObject rootGameObject = selection.rootGameObject;\n            if (rootGameObject == null)\n                return;\n\n            List<int> selectedGameObjectIDs = new List<int>(selectedNodeIDs.Length);\n            foreach (var selectedNodeID in selectedNodeIDs)\n            {\n                // Skip nodes without associated curves.\n                if (selectedNodeID == 0)\n                    continue;\n\n                AnimationWindowHierarchyNode node = hierarchyData.FindItem(selectedNodeID) as AnimationWindowHierarchyNode;\n\n                if (node == null)\n                    continue;\n\n                if (node is AnimationWindowHierarchyMasterNode)\n                    continue;\n\n                Transform t = rootGameObject.transform.Find(node.path);\n\n                // In the case of nested animation component, we don't want to sync the scene selection (case 569506)\n                // When selection changes, animation window will always pick nearest animator component in terms of hierarchy depth\n                // Automatically syncinc scene selection in nested scenarios would cause unintuitive clip & animation change for animation window so we check for it and deny sync if necessary\n\n                if (t != null && rootGameObject != null && activeAnimationPlayer == AnimationWindowUtility.GetClosestAnimationPlayerComponentInParents(t))\n                    selectedGameObjectIDs.Add(t.gameObject.GetInstanceID());\n            }\n\n            if (selectedGameObjectIDs.Count > 0)\n                UnityEditor.Selection.instanceIDs = selectedGameObjectIDs.ToArray();\n            else\n                UnityEditor.Selection.activeGameObject = rootGameObject;\n        }\n\n        public float clipFrameRate\n        {\n            get\n            {\n                if (activeAnimationClip == null)\n                    return 60.0f;\n                return activeAnimationClip.frameRate;\n            }\n            set\n            {\n                // @TODO: Changing the clip in AnimationWindowState.frame rate feels a bit intrusive\n                // Should probably be done explicitly from the UI and not go through AnimationWindowState...\n                if (activeAnimationClip != null && value > 0 && value <= 10000)\n                {\n                    // Clear selection and save empty selection snapshot for undo consistency.\n                    ClearKeySelections();\n                    SaveKeySelection(kEditCurveUndoLabel);\n\n                    // Reposition all keyframes to match the new sampling rate\n                    foreach (var curve in allCurves)\n                    {\n                        foreach (var key in curve.keyframes)\n                        {\n                            int frame = AnimationKeyTime.Time(key.time, clipFrameRate).frame;\n                            key.time = AnimationKeyTime.Frame(frame, value).time;\n                        }\n                    }\n\n                    SaveCurves(activeAnimationClip, allCurves, kEditCurveUndoLabel);\n\n                    AnimationEvent[] events = AnimationUtility.GetAnimationEvents(activeAnimationClip);\n                    foreach (AnimationEvent ev in events)\n                    {\n                        int frame = AnimationKeyTime.Time(ev.time, clipFrameRate).frame;\n                        ev.time = AnimationKeyTime.Frame(frame, value).time;\n                    }\n                    AnimationUtility.SetAnimationEvents(activeAnimationClip, events);\n\n                    activeAnimationClip.frameRate = value;\n                }\n            }\n        }\n\n        public float frameRate\n        {\n            get\n            {\n                return m_FrameRate;\n            }\n            set\n            {\n                if (m_FrameRate != value)\n                {\n                    m_FrameRate = value;\n                    if (onFrameRateChange != null)\n                        onFrameRateChange(m_FrameRate);\n                }\n            }\n        }\n\n        public AnimationKeyTime time => AnimationKeyTime.Time(controlInterface.time, frameRate);\n\n        public int currentFrame\n        {\n            get => controlInterface.frame;\n            set => controlInterface.frame = value;\n        }\n\n        public float currentTime\n        {\n            get => controlInterface.time;\n            set => controlInterface.time = value;\n        }\n\n        public TimeArea.TimeFormat timeFormat { get { return AnimationWindowOptions.timeFormat; } set { AnimationWindowOptions.timeFormat = value; } }\n\n        public TimeArea timeArea\n        {\n            get { return m_TimeArea; }\n            set { m_TimeArea = value; }\n        }\n\n        // Pixel to time ratio (used for time-pixel conversions)\n        public float pixelPerSecond\n        {\n            get { return timeArea.m_Scale.x; }\n        }\n\n        // The GUI x-coordinate, where time==0 (used for time-pixel conversions)\n        public float zeroTimePixel\n        {\n            get { return timeArea.shownArea.xMin * timeArea.m_Scale.x * -1f; }\n        }\n\n        public float PixelToTime(float pixel)\n        {\n            return PixelToTime(pixel, SnapMode.Disabled);\n        }\n\n        public float PixelToTime(float pixel, SnapMode snap)\n        {\n            float time = pixel - zeroTimePixel;\n            return SnapToFrame(time / pixelPerSecond, snap);\n        }\n\n        public float TimeToPixel(float time)\n        {\n            return TimeToPixel(time, SnapMode.Disabled);\n        }\n\n        public float TimeToPixel(float time, SnapMode snap)\n        {\n            return SnapToFrame(time, snap) * pixelPerSecond + zeroTimePixel;\n        }\n\n        //@TODO: Move to animatkeytime??\n        public float SnapToFrame(float time, SnapMode snap)\n        {\n            if (snap == SnapMode.Disabled)\n                return time;\n\n            float fps = (snap == SnapMode.SnapToFrame) ? frameRate : clipFrameRate;\n            return SnapToFrame(time, fps);\n        }\n\n        public float SnapToFrame(float time, float fps)\n        {\n            float snapTime = Mathf.Round(time * fps) / fps;\n            return snapTime;\n        }\n\n        public float minVisibleTime { get { return m_TimeArea.shownArea.xMin; } }\n        public float maxVisibleTime { get { return m_TimeArea.shownArea.xMax; } }\n        public float visibleTimeSpan { get { return maxVisibleTime - minVisibleTime; } }\n        public float minVisibleFrame { get { return minVisibleTime * frameRate; } }\n        public float maxVisibleFrame { get { return maxVisibleTime * frameRate; } }\n        public float visibleFrameSpan { get { return visibleTimeSpan * frameRate; } }\n        public float minTime { get { return timeRange.x; } }\n        public float maxTime { get { return timeRange.y; } }\n\n        public Vector2 timeRange\n        {\n            get\n            {\n                if (activeAnimationClip != null)\n                    return new Vector2(activeAnimationClip.startTime, activeAnimationClip.stopTime);\n\n                return Vector2.zero;\n            }\n        }\n\n        public string FormatFrame(int frame, int frameDigits)\n        {\n            return (frame / (int)frameRate) + \":\" + (frame % frameRate).ToString().PadLeft(frameDigits, '0');\n        }\n\n        //@TODO: Remove. Replace with animationkeytime\n        public float TimeToFrame(float time)\n        {\n            return time * frameRate;\n        }\n\n        //@TODO: Remove. Replace with animationkeytime\n        public float FrameToTime(float frame)\n        {\n            return frame / frameRate;\n        }\n\n        public int TimeToFrameFloor(float time)\n        {\n            return Mathf.FloorToInt(TimeToFrame(time));\n        }\n\n        public int TimeToFrameRound(float time)\n        {\n            return Mathf.RoundToInt(TimeToFrame(time));\n        }\n\n        public float FrameToPixel(float i, Rect rect)\n        {\n            return (i - minVisibleFrame) * rect.width / visibleFrameSpan;\n        }\n\n        public float FrameDeltaToPixel(Rect rect)\n        {\n            return rect.width / visibleFrameSpan;\n        }\n\n        public float TimeToPixel(float time, Rect rect)\n        {\n            return FrameToPixel(time * frameRate, rect);\n        }\n\n        public float PixelToTime(float pixelX, Rect rect)\n        {\n            return (pixelX * visibleTimeSpan / rect.width + minVisibleTime);\n        }\n\n        public float PixelDeltaToTime(Rect rect)\n        {\n            return visibleTimeSpan / rect.width;\n        }\n\n        public void GoToPreviousFrame()\n        {\n            controlInterface.frame -= 1;\n        }\n\n        public void GoToNextFrame()\n        {\n            controlInterface.frame += 1;\n        }\n\n        public void GoToPreviousKeyframe()\n        {\n            List<AnimationWindowCurve> curves = (showCurveEditor && activeCurves.Count > 0) ? activeCurves : filteredCurves;\n\n            float newTime = AnimationWindowUtility.GetPreviousKeyframeTime(curves.ToArray(), controlInterface.time, clipFrameRate);\n            controlInterface.time = SnapToFrame(newTime, SnapMode.SnapToFrame);\n        }\n\n        public void GoToNextKeyframe()\n        {\n            List<AnimationWindowCurve> curves = (showCurveEditor && activeCurves.Count > 0) ? activeCurves : filteredCurves;\n\n            float newTime = AnimationWindowUtility.GetNextKeyframeTime(curves.ToArray(), controlInterface.time, clipFrameRate);\n            controlInterface.time = SnapToFrame(newTime, AnimationWindowState.SnapMode.SnapToFrame);\n        }\n\n        public void GoToFirstKeyframe()\n        {\n            if (activeAnimationClip)\n                controlInterface.time = activeAnimationClip.startTime;\n        }\n\n        public void GoToLastKeyframe()\n        {\n            if (activeAnimationClip)\n                controlInterface.time = activeAnimationClip.stopTime;\n        }\n\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowStyles.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    internal class AnimationWindowStyles\n    {\n        public static Texture2D pointIcon = EditorGUIUtility.LoadIcon(\"animationkeyframe\");\n\n        public static GUIContent playContent = EditorGUIUtility.TrIconContent(\"Animation.Play\", \"Play the animation clip.\");\n        public static GUIContent recordContent = EditorGUIUtility.TrIconContent(\"Animation.Record\", \"Enable/disable keyframe recording mode.\");\n        public static GUIContent previewContent = EditorGUIUtility.TrTextContent(\"Preview\", \"Enable/disable scene preview mode.\");\n        public static GUIContent prevKeyContent = EditorGUIUtility.TrIconContent(\"Animation.PrevKey\", \"Go to previous keyframe.\");\n        public static GUIContent nextKeyContent = EditorGUIUtility.TrIconContent(\"Animation.NextKey\", \"Go to next keyframe.\");\n        public static GUIContent firstKeyContent = EditorGUIUtility.TrIconContent(\"Animation.FirstKey\", \"Go to the beginning of the animation clip.\");\n        public static GUIContent lastKeyContent = EditorGUIUtility.TrIconContent(\"Animation.LastKey\", \"Go to the end of the animation clip.\");\n        public static GUIContent addKeyframeContent = EditorGUIUtility.TrIconContent(\"Animation.AddKeyframe\", \"Add keyframe.\");\n        public static GUIContent addEventContent = EditorGUIUtility.TrIconContent(\"Animation.AddEvent\", \"Add event.\");\n        public static GUIContent filterBySelectionContent = EditorGUIUtility.TrIconContent(\"Animation.FilterBySelection\", \"Filter by selection.\");\n        public static GUIContent sequencerLinkContent = EditorGUIUtility.TrIconContent(\"Animation.SequencerLink\", \"Animation Window is linked to Timeline Editor.  Press to Unlink.\");\n\n        public static GUIContent noAnimatableObjectSelectedText = EditorGUIUtility.TrTextContent(\"No animatable object selected.\");\n        public static GUIContent formatIsMissing = EditorGUIUtility.TrTextContent(\"To begin animating {0}, create {1}.\");\n        public static GUIContent animatorAndAnimationClip = EditorGUIUtility.TrTextContent(\"an Animator and an Animation Clip\");\n        public static GUIContent animationClip = EditorGUIUtility.TrTextContent(\"an Animation Clip\");\n        public static GUIContent create = EditorGUIUtility.TrTextContent(\"Create\");\n        public static GUIContent dopesheet = EditorGUIUtility.TrTextContent(\"Dopesheet\");\n        public static GUIContent curves = EditorGUIUtility.TrTextContent(\"Curves\");\n        public static GUIContent samples = EditorGUIUtility.TrTextContent(\"Samples\");\n        public static GUIContent createNewClip = EditorGUIUtility.TrTextContent(\"Create New Clip...\");\n\n        public static GUIContent animatorOptimizedText = EditorGUIUtility.TrTextContent(\"Editing and playback of animations on optimized game object hierarchy is not supported.\\nPlease select a game object that does not have 'Optimize Game Objects' applied.\");\n        public static GUIContent readOnlyPropertiesLabel = EditorGUIUtility.TrTextContent(\"Animation Clip is Read-Only\");\n        public static GUIContent readOnlyPropertiesButton = EditorGUIUtility.TrTextContent(\"Show Read-Only Properties\");\n\n        public static GUIContent optionsContent = EditorGUIUtility.IconContent(\"_Menu\");\n\n        public static GUIStyle playHead = \"AnimationPlayHead\";\n\n        public static GUIStyle animPlayToolBar = \"AnimPlayToolbar\";\n        public static GUIStyle animClipToolBar = \"AnimClipToolbar\";\n        public static GUIStyle animClipToolbarButton = \"AnimClipToolbarButton\";\n        public static GUIStyle animClipToolbarPopup = \"AnimClipToolbarPopup\";\n        public static GUIStyle timeRulerBackground = \"TimeRulerBackground\";\n        public static GUIStyle curveEditorBackground = \"CurveEditorBackground\";\n        public static GUIStyle curveEditorLabelTickmarks = \"CurveEditorLabelTickmarks\";\n        public static GUIStyle eventBackground = \"AnimationEventBackground\";\n        public static GUIStyle eventTooltip = \"AnimationEventTooltip\";\n        public static GUIStyle eventTooltipArrow = \"AnimationEventTooltipArrow\";\n        public static GUIStyle keyframeBackground = \"AnimationKeyframeBackground\";\n        public static GUIStyle timelineTick = \"AnimationTimelineTick\";\n        public static GUIStyle dopeSheetKeyframe = \"Dopesheetkeyframe\";\n        public static GUIStyle dopeSheetBackground = \"DopesheetBackground\";\n        public static GUIStyle popupCurveDropdown = \"PopupCurveDropdown\";\n        public static GUIStyle popupCurveEditorBackground = \"PopupCurveEditorBackground\";\n        public static GUIStyle popupCurveEditorSwatch = \"PopupCurveEditorSwatch\";\n        public static GUIStyle popupCurveSwatchBackground = \"PopupCurveSwatchBackground\";\n        public static GUIStyle separator = new GUIStyle(\"AnimLeftPaneSeparator\");\n\n        public static GUIStyle toolbarBottom = \"ToolbarBottom\";\n        public static GUIStyle optionsButton = new GUIStyle(EditorStyles.toolbarButtonRight);\n        public static GUIStyle miniToolbarButton = new GUIStyle(EditorStyles.toolbarButton);\n        public static GUIStyle toolbarLabel = new GUIStyle(AnimationWindowStyles.animClipToolbarPopup);\n\n        public static void Initialize()\n        {\n            toolbarLabel.normal.background = null;\n            optionsButton.padding = new RectOffset();\n            optionsButton.imagePosition = ImagePosition.ImageOnly;\n            optionsButton.contentOffset = new Vector2(-7, 0);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Globalization;\nusing System.Linq;\nusing System.IO;\nusing System.Collections.Generic;\nusing UnityEditor;\nusing UnityEditor.Animations;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\nusing TangentMode = UnityEditor.AnimationUtility.TangentMode;\n\nnamespace UnityEditorInternal\n{\n    static class AnimationWindowUtility\n    {\n        public static void SaveCurve(AnimationClip clip, AnimationWindowCurve curve)\n        {\n            if (!curve.animationIsEditable)\n                throw new ArgumentException(\"Curve is not editable and shouldn't be saved.\");\n\n            if (curve.isPPtrCurve)\n            {\n                ObjectReferenceKeyframe[] objectCurve = curve.ToObjectCurve();\n\n                if (objectCurve.Length == 0)\n                    objectCurve = null;\n\n                AnimationUtility.SetObjectReferenceCurve(clip, curve.binding, objectCurve);\n            }\n            else\n            {\n                AnimationCurve animationCurve = curve.ToAnimationCurve();\n\n                if (animationCurve.keys.Length == 0)\n                    animationCurve = null;\n                else\n                    AnimationUtility.UpdateTangentsFromMode(animationCurve);\n\n                AnimationUtility.SetEditorCurve(clip, curve.binding, animationCurve);\n            }\n        }\n\n        public static void SaveCurves(AnimationClip clip, IEnumerable<AnimationWindowCurve> curves)\n        {\n            foreach (AnimationWindowCurve curve in curves)\n            {\n                if (!curve.animationIsEditable)\n                    throw new ArgumentException(\"Curve is not editable and shouldn't be saved.\");\n\n                if (curve.isPPtrCurve)\n                {\n                    ObjectReferenceKeyframe[] objectCurve = curve.ToObjectCurve();\n\n                    if (objectCurve.Length == 0)\n                        objectCurve = null;\n\n                    AnimationUtility.SetObjectReferenceCurveNoSync(clip, curve.binding, objectCurve);\n                }\n                else\n                {\n                    AnimationCurve animationCurve = curve.ToAnimationCurve();\n\n                    if (animationCurve.keys.Length == 0)\n                        animationCurve = null;\n                    else\n                        AnimationUtility.UpdateTangentsFromMode(animationCurve);\n\n                    AnimationUtility.SetEditorCurveNoSync(clip, curve.binding, animationCurve);\n                }\n            }\n\n            AnimationUtility.SyncEditorCurves(clip);\n        }\n\n        public static void SaveCurves(AnimationClip clip, IList<EditorCurveBinding> bindings, IList<AnimationCurve> curves)\n        {\n            if (bindings.Count != curves.Count)\n                throw new ArgumentException(\"bindings and curves array sizes do not match\");\n\n            for (int i = 0; i < bindings.Count; ++i)\n            {\n                AnimationUtility.SetEditorCurveNoSync(clip, bindings[i], curves[i]);\n            }\n\n            AnimationUtility.SyncEditorCurves(clip);\n        }\n\n        public static void CreateDefaultCurves(AnimationWindowState state, EditorCurveBinding[] properties)\n        {\n            CreateDefaultCurves(state, state.activeAnimationClip, properties);\n        }\n\n        public static void CreateDefaultCurves(AnimationWindowState state, AnimationClip animationClip, EditorCurveBinding[] properties)\n        {\n            properties = RotationCurveInterpolation.ConvertRotationPropertiesToDefaultInterpolation(animationClip, properties);\n\n            if (properties.Length == 0)\n                return;\n\n            var curves = new List<AnimationWindowCurve>(properties.Length);\n            foreach (EditorCurveBinding prop in properties)\n                curves.Add(CreateDefaultCurve(state, animationClip, prop));\n\n            state.SaveCurves(animationClip, curves);\n        }\n\n        public static AnimationWindowCurve CreateDefaultCurve(AnimationWindowState state, AnimationClip animationClip, EditorCurveBinding binding)\n        {\n            Type type = state.controlInterface.GetValueType(binding);\n\n            AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, binding, type);\n\n            object currentValue = CurveBindingUtility.GetCurrentValue(state, binding);\n            if (animationClip.length == 0.0F)\n            {\n                AddKeyframeToCurve(curve, currentValue, type, AnimationKeyTime.Time(0.0F, animationClip.frameRate));\n            }\n            else\n            {\n                AddKeyframeToCurve(curve, currentValue, type, AnimationKeyTime.Time(0.0F, animationClip.frameRate));\n                AddKeyframeToCurve(curve, currentValue, type, AnimationKeyTime.Time(animationClip.length, animationClip.frameRate));\n            }\n\n            return curve;\n        }\n\n        public static bool ShouldShowAnimationWindowCurve(EditorCurveBinding curveBinding)\n        {\n            // We don't want to convert the w component of rotation curves to be shown in animation window\n            if (IsTransformType(curveBinding.type))\n                return !curveBinding.propertyName.EndsWith(\".w\");\n\n            return true;\n        }\n\n        public static bool IsNodeLeftOverCurve(AnimationWindowState state, AnimationWindowHierarchyNode node)\n        {\n            if (node.binding != null)\n            {\n                if (node.curves.Length > 0)\n                {\n                    AnimationWindowSelectionItem selectionBinding = node.curves[0].selectionBinding;\n                    if (selectionBinding != null)\n                    {\n                        if (selectionBinding.rootGameObject == null && selectionBinding.scriptableObject == null)\n                            return false;\n\n                        return state.controlInterface.GetValueType((EditorCurveBinding)node.binding) == null;\n                    }\n                }\n            }\n\n            // Go through all child nodes recursively\n            if (node.hasChildren)\n            {\n                foreach (var child in node.children)\n                    return IsNodeLeftOverCurve(state, child as AnimationWindowHierarchyNode);\n            }\n\n            return false;\n        }\n\n        public static bool IsNodeAmbiguous(AnimationWindowHierarchyNode node)\n        {\n            if (node.binding != null)\n            {\n                if (node.curves.Length > 0)\n                {\n                    AnimationWindowSelectionItem selectionBinding = node.curves[0].selectionBinding;\n                    if (selectionBinding != null)\n                    {\n                        if (selectionBinding.rootGameObject != null)\n                            return AnimationUtility.AmbiguousBinding(node.binding.Value.path, node.binding.Value.m_ClassID, selectionBinding.rootGameObject.transform);\n                    }\n                }\n            }\n\n            // Go through all child nodes recursively\n            if (node.hasChildren)\n            {\n                foreach (var child in node.children)\n                    return IsNodeAmbiguous(child as AnimationWindowHierarchyNode);\n            }\n\n            return false;\n        }\n\n        public static bool IsNodePhantom(AnimationWindowHierarchyNode node)\n        {\n            if (node.binding != null)\n                return node.binding.Value.isPhantom;\n\n            return false;\n        }\n\n        public static void AddSelectedKeyframes(AnimationWindowState state, AnimationKeyTime time)\n        {\n            List<AnimationWindowCurve> curves = state.activeCurves.Count > 0 ? state.activeCurves : state.filteredCurves;\n            AddKeyframes(state, curves, time);\n        }\n\n        public static void AddKeyframes(AnimationWindowState state, IList<AnimationWindowCurve> curves, AnimationKeyTime time)\n        {\n            string undoLabel = L10n.Tr(\"Add Key\");\n            state.SaveKeySelection(undoLabel);\n\n            state.ClearKeySelections();\n\n            foreach (AnimationWindowCurve curve in curves)\n            {\n                if (!curve.animationIsEditable)\n                    continue;\n\n                AnimationKeyTime shiftedMouseKeyTime = AnimationKeyTime.Time(time.time, time.frameRate);\n\n                object value = CurveBindingUtility.GetCurrentValue(state, curve);\n                AnimationWindowKeyframe keyframe = AnimationWindowUtility.AddKeyframeToCurve(curve, value, curve.valueType, shiftedMouseKeyTime);\n\n                if (keyframe != null)\n                    state.SelectKey(keyframe);\n            }\n\n            state.SaveCurves(state.activeAnimationClip, curves, undoLabel);\n        }\n\n        public static void RemoveKeyframes(AnimationWindowState state, IList<AnimationWindowCurve> curves, AnimationKeyTime time)\n        {\n            string undoLabel = L10n.Tr(\"Remove Key\");\n            state.SaveKeySelection(undoLabel);\n\n            foreach (AnimationWindowCurve curve in curves)\n            {\n                if (!curve.animationIsEditable)\n                    continue;\n\n                curve.RemoveKeyframe(time);\n            }\n\n            state.SaveCurves(state.activeAnimationClip, curves, undoLabel);\n        }\n\n        public static AnimationWindowKeyframe AddKeyframeToCurve(AnimationWindowCurve curve, object value, Type type, AnimationKeyTime time)\n        {\n            // When there is already a key a this time\n            // Make sure that only value is updated but tangents are maintained.\n            AnimationWindowKeyframe previousKey = curve.FindKeyAtTime(time);\n            if (previousKey != null)\n            {\n                previousKey.value = value;\n                return previousKey;\n            }\n\n            AnimationWindowKeyframe keyframe = null;\n\n            if (curve.isPPtrCurve)\n            {\n                keyframe = new AnimationWindowKeyframe();\n\n                keyframe.time = time.time;\n                keyframe.value = value;\n                keyframe.curve = curve;\n                curve.AddKeyframe(keyframe, time);\n            }\n            else if (curve.isDiscreteCurve)\n            {\n                Keyframe tempKey = new Keyframe(time.time, 0f);\n                AnimationUtility.SetKeyLeftTangentMode(ref tempKey, TangentMode.Constant);\n                AnimationUtility.SetKeyRightTangentMode(ref tempKey, TangentMode.Constant);\n                AnimationUtility.SetKeyBroken(ref tempKey, true);\n\n                keyframe = new AnimationWindowKeyframe(curve, tempKey);\n                keyframe.value = Convert.ToInt32(value);\n\n                curve.AddKeyframe(keyframe, time);\n            }\n            else if (type == typeof(bool) || type == typeof(float) || type == typeof(int))\n            {\n                Keyframe tempKey = new Keyframe(time.time, Convert.ToSingle(value));\n                if (type == typeof(bool))\n                {\n                    AnimationUtility.SetKeyLeftTangentMode(ref tempKey, TangentMode.Constant);\n                    AnimationUtility.SetKeyRightTangentMode(ref tempKey, TangentMode.Constant);\n\n                    AnimationUtility.SetKeyBroken(ref tempKey, true);\n                }\n                else if (type == typeof(int))\n                {\n                    // Create temporary curve to get proper tangents\n                    AnimationCurve animationCurve = curve.ToAnimationCurve();\n\n                    if (animationCurve.length <= 1)\n                    {\n                        TangentMode tangentMode = TangentMode.Linear;\n                        AnimationUtility.SetKeyLeftTangentMode(ref tempKey, tangentMode);\n                        AnimationUtility.SetKeyRightTangentMode(ref tempKey, tangentMode);\n                    }\n                    else\n                    {\n                        int keyIndex = animationCurve.AddKey(tempKey);\n                        if (keyIndex != -1)\n                        {\n                            CurveUtility.SetKeyModeFromContext(animationCurve, keyIndex);\n                            tempKey = animationCurve[keyIndex];\n                        }\n                    }\n\n                    AnimationUtility.SetKeyBroken(ref tempKey, true);\n                }\n                else\n                {\n                    // Create temporary curve to get proper tangents\n                    AnimationCurve animationCurve = curve.ToAnimationCurve();\n\n                    int keyIndex = animationCurve.AddKey(tempKey);\n                    if (keyIndex != -1)\n                    {\n                        // Make sure tangent slopes default to ClampedAuto.  Tangent mode will be modified afterwards.\n                        AnimationUtility.SetKeyLeftTangentMode(animationCurve, keyIndex, TangentMode.ClampedAuto);\n                        AnimationUtility.SetKeyRightTangentMode(animationCurve, keyIndex, TangentMode.ClampedAuto);\n                        AnimationUtility.UpdateTangentsFromModeSurrounding(animationCurve, keyIndex);\n\n                        CurveUtility.SetKeyModeFromContext(animationCurve, keyIndex);\n\n                        tempKey = animationCurve[keyIndex];\n                    }\n                }\n\n                keyframe = new AnimationWindowKeyframe(curve, tempKey);\n                curve.AddKeyframe(keyframe, time);\n            }\n\n            return keyframe;\n        }\n\n        public static List<AnimationWindowCurve> FilterCurves(AnimationWindowCurve[] curves, string path, bool entireHierarchy)\n        {\n            List<AnimationWindowCurve> results = new List<AnimationWindowCurve>();\n\n            if (curves != null)\n            {\n                foreach (AnimationWindowCurve curve in curves)\n                    if (curve.path.Equals(path) || (entireHierarchy && curve.path.Contains(path)))\n                        results.Add(curve);\n            }\n\n            return results;\n        }\n\n        public static List<AnimationWindowCurve> FilterCurves(AnimationWindowCurve[] curves, string path, Type animatableObjectType)\n        {\n            List<AnimationWindowCurve> results = new List<AnimationWindowCurve>();\n\n            if (curves != null)\n            {\n                foreach (AnimationWindowCurve curve in curves)\n                    if (curve.path.Equals(path) && curve.type == animatableObjectType)\n                        results.Add(curve);\n            }\n\n            return results;\n        }\n\n        public static bool IsCurveCreated(AnimationClip clip, EditorCurveBinding binding)\n        {\n            if (binding.isPPtrCurve)\n            {\n                return AnimationUtility.GetObjectReferenceCurve(clip, binding) != null;\n            }\n            else\n            {\n                // For RectTransform.position we only want .z\n                if (IsRectTransformPosition(binding))\n                    binding.propertyName = binding.propertyName.Replace(\".x\", \".z\").Replace(\".y\", \".z\");\n                if (IsRotationCurve(binding))\n                {\n                    return AnimationUtility.GetEditorCurve(clip, binding) != null || HasOtherRotationCurve(clip, binding);\n                }\n\n                return AnimationUtility.GetEditorCurve(clip, binding) != null;\n            }\n        }\n\n        internal static bool HasOtherRotationCurve(AnimationClip clip, EditorCurveBinding rotationBinding)\n        {\n            if (rotationBinding.propertyName.StartsWith(\"m_LocalRotation\"))\n            {\n                EditorCurveBinding x = rotationBinding;\n                EditorCurveBinding y = rotationBinding;\n                EditorCurveBinding z = rotationBinding;\n                x.propertyName = \"localEulerAnglesRaw.x\";\n                y.propertyName = \"localEulerAnglesRaw.y\";\n                z.propertyName = \"localEulerAnglesRaw.z\";\n\n                return AnimationUtility.GetEditorCurve(clip, x) != null ||\n                    AnimationUtility.GetEditorCurve(clip, y) != null ||\n                    AnimationUtility.GetEditorCurve(clip, z) != null;\n            }\n            else\n            {\n                EditorCurveBinding x = rotationBinding;\n                EditorCurveBinding y = rotationBinding;\n                EditorCurveBinding z = rotationBinding;\n                EditorCurveBinding w = rotationBinding;\n\n                x.propertyName = \"m_LocalRotation.x\";\n                y.propertyName = \"m_LocalRotation.y\";\n                z.propertyName = \"m_LocalRotation.z\";\n                w.propertyName = \"m_LocalRotation.w\";\n\n                return AnimationUtility.GetEditorCurve(clip, x) != null ||\n                    AnimationUtility.GetEditorCurve(clip, y) != null ||\n                    AnimationUtility.GetEditorCurve(clip, z) != null ||\n                    AnimationUtility.GetEditorCurve(clip, w) != null;\n            }\n        }\n\n        internal static bool IsRotationCurve(EditorCurveBinding curveBinding)\n        {\n            string propertyName = GetPropertyGroupName(curveBinding.propertyName);\n            return propertyName == \"m_LocalRotation\" || propertyName == \"localEulerAnglesRaw\";\n        }\n\n        public static bool IsRectTransformPosition(EditorCurveBinding curveBinding)\n        {\n            return curveBinding.type == typeof(RectTransform) && GetPropertyGroupName(curveBinding.propertyName) == \"m_LocalPosition\";\n        }\n\n        public static bool ContainsFloatKeyframes(List<AnimationWindowKeyframe> keyframes)\n        {\n            if (keyframes == null || keyframes.Count == 0)\n                return false;\n\n            foreach (var key in keyframes)\n            {\n                if (!key.isPPtrCurve)\n                    return true;\n            }\n\n            return false;\n        }\n\n        // Get curves for property or propertygroup (example: x,y,z)\n        public static List<AnimationWindowCurve> FilterCurves(AnimationWindowCurve[] curves, string path, Type animatableObjectType, string propertyName)\n        {\n            List<AnimationWindowCurve> results = new List<AnimationWindowCurve>();\n\n            if (curves != null)\n            {\n                string propertyGroupName = GetPropertyGroupName(propertyName);\n                bool isPropertyGroup = propertyGroupName == propertyName;\n\n                foreach (AnimationWindowCurve curve in curves)\n                {\n                    bool propertyNameMatches = isPropertyGroup ? GetPropertyGroupName(curve.propertyName).Equals(propertyGroupName) : curve.propertyName.Equals(propertyName);\n                    if (curve.path.Equals(path) && curve.type == animatableObjectType && propertyNameMatches)\n                        results.Add(curve);\n                }\n            }\n\n            return results;\n        }\n\n        // Current value of the property that rootGO + curveBinding is pointing to\n        public static object GetCurrentValue(GameObject rootGameObject, EditorCurveBinding curveBinding)\n        {\n            if (curveBinding.isPPtrCurve)\n            {\n                AnimationUtility.GetObjectReferenceValue(rootGameObject, curveBinding, out var value);\n                return value;\n            }\n            else if (curveBinding.isDiscreteCurve)\n            {\n                AnimationUtility.GetDiscreteIntValue(rootGameObject, curveBinding, out var value);\n                return value;\n            }\n            else\n            {\n                AnimationUtility.GetFloatValue(rootGameObject, curveBinding, out var value);\n                return value;\n            }\n        }\n\n        public static EditorCurveBinding[] GetAnimatableBindings(GameObject rootGameObject)\n        {\n            if (rootGameObject != null)\n            {\n                var transforms = rootGameObject.GetComponentsInChildren<Transform>();\n\n                // At least 10 bindings for Transform (m_LocalPosition, m_LocalRotation, m_LocalScale) and 1 binding for GameObject (m_IsActive)\n                const int kMinNumberOfBindingsPerGameObject = 11;\n\n                var bindings = new List<EditorCurveBinding>(transforms.Length * kMinNumberOfBindingsPerGameObject);\n                for (int i = 0; i < transforms.Length; ++i)\n                {\n                    bindings.AddRange(AnimationUtility.GetAnimatableBindings(transforms[i].gameObject, rootGameObject));\n                }\n\n                return bindings.ToArray();\n            }\n\n            return Array.Empty<EditorCurveBinding>();\n        }\n\n        public static bool PropertyIsAnimatable(Object targetObject, string propertyPath, Object rootObject)\n        {\n            if (targetObject is ScriptableObject)\n            {\n                ScriptableObject scriptableObject = (ScriptableObject)targetObject;\n                EditorCurveBinding[] allCurveBindings = AnimationUtility.GetAnimatableBindings(scriptableObject);\n                return Array.Exists(allCurveBindings, binding => binding.propertyName == propertyPath);\n            }\n            else\n            {\n                GameObject gameObject = targetObject as GameObject;\n                if (targetObject is Component)\n                    gameObject = ((Component)targetObject).gameObject;\n\n                if (gameObject != null)\n                {\n                    var dummyModification = new PropertyModification();\n                    dummyModification.propertyPath = propertyPath;\n                    dummyModification.target = targetObject;\n\n                    EditorCurveBinding binding = new EditorCurveBinding();\n                    return AnimationUtility.PropertyModificationToEditorCurveBinding(dummyModification, rootObject == null ? gameObject : (GameObject)rootObject, out binding) != null;\n                }\n            }\n\n            return false;\n        }\n\n        // Given a serialized property, gathers all animateable properties\n        public static PropertyModification[] SerializedPropertyToPropertyModifications(SerializedProperty property)\n        {\n            List<SerializedProperty> properties = new List<SerializedProperty>();\n\n            properties.Add(property);\n\n            // handles child properties (Vector3 is 3 recordable properties)\n            if (property.hasChildren)\n            {\n                var iter = property.Copy();\n                var end = property.GetEndProperty(false);\n\n                // recurse over all children properties\n                while (iter.Next(true) && !SerializedProperty.EqualContents(iter, end) && iter.propertyPath.StartsWith(property.propertyPath))\n                {\n                    properties.Add(iter.Copy());\n                }\n            }\n\n            // Special case for m_LocalRotation...\n            if (property.propertyPath.StartsWith(\"m_LocalRotation\"))\n            {\n                var serializedObject = property.serializedObject;\n                if (serializedObject.targetObject is Transform)\n                {\n                    SerializedProperty eulerHintProperty = serializedObject.FindProperty(\"m_LocalEulerAnglesHint\");\n                    if (eulerHintProperty != null && eulerHintProperty.hasChildren)\n                    {\n                        var iter = eulerHintProperty.Copy();\n                        var end = eulerHintProperty.GetEndProperty(false);\n\n                        // recurse over all children properties\n                        while (iter.Next(true) && !SerializedProperty.EqualContents(iter, end) && iter.propertyPath.StartsWith(eulerHintProperty.propertyPath))\n                        {\n                            properties.Add(iter.Copy());\n                        }\n                    }\n                }\n            }\n\n            List<PropertyModification> modifications = new List<PropertyModification>();\n\n            for (int i = 0; i < properties.Count; ++i)\n            {\n                var propertyIter = properties[i];\n                var isObject = propertyIter.propertyType == SerializedPropertyType.ObjectReference;\n                var isFloat = propertyIter.propertyType == SerializedPropertyType.Float;\n                var isBool = propertyIter.propertyType == SerializedPropertyType.Boolean;\n                var isInt = propertyIter.propertyType == SerializedPropertyType.Integer;\n                var isEnum = propertyIter.propertyType == SerializedPropertyType.Enum;\n\n                if (isObject || isFloat || isBool || isInt || isEnum)\n                {\n                    var serializedObject = propertyIter.serializedObject;\n                    var targetObjects = serializedObject.targetObjects;\n\n                    if (propertyIter.hasMultipleDifferentValues)\n                    {\n                        for (int j = 0; j < targetObjects.Length; ++j)\n                        {\n                            var singleObject = new SerializedObject(targetObjects[j]);\n                            SerializedProperty singleProperty = singleObject.FindProperty(propertyIter.propertyPath);\n\n                            string value = string.Empty;\n                            Object objectReference = null;\n\n                            if (isObject)\n                                objectReference = singleProperty.objectReferenceValue;\n                            else if (isFloat)\n                                value = singleProperty.floatValue.ToString(CultureInfo.InvariantCulture);\n                            else if (isInt)\n                                value = singleProperty.intValue.ToString();\n                            else if (isEnum)\n                                value = singleProperty.enumValueIndex.ToString();\n                            else // if (isBool)\n                                value = singleProperty.boolValue ? \"1\" : \"0\";\n\n                            var modification = new PropertyModification();\n\n                            modification.target = targetObjects[j];\n                            modification.propertyPath = (singleProperty.isReferencingAManagedReferenceField ? singleProperty.managedReferencePropertyPath : singleProperty.propertyPath);\n                            modification.value = value;\n                            modification.objectReference = objectReference;\n                            modifications.Add(modification);\n                        }\n                    }\n                    // fast path\n                    else\n                    {\n                        string value = string.Empty;\n                        Object objectReference = null;\n\n                        if (isObject)\n                            objectReference = propertyIter.objectReferenceValue;\n                        else if (isFloat)\n                            value = propertyIter.floatValue.ToString(CultureInfo.InvariantCulture);\n                        else if (isInt)\n                            value = propertyIter.intValue.ToString();\n                        else if (isEnum)\n                                value = propertyIter.enumValueIndex.ToString();\n                        else // if (isBool)\n                            value = propertyIter.boolValue ? \"1\" : \"0\";\n\n                        for (int j = 0; j < targetObjects.Length; ++j)\n                        {\n                            var modification = new PropertyModification();\n\n                            modification.target = targetObjects[j];\n                            modification.propertyPath = (propertyIter.isReferencingAManagedReferenceField ? propertyIter.managedReferencePropertyPath : propertyIter.propertyPath);\n                            modification.value = value;\n                            modification.objectReference = objectReference;\n                            modifications.Add(modification);\n                        }\n                    }\n                }\n            }\n\n            return modifications.ToArray();\n        }\n\n        public static EditorCurveBinding[] PropertyModificationsToEditorCurveBindings(PropertyModification[] modifications, GameObject rootGameObject, AnimationClip animationClip)\n        {\n            if (modifications == null)\n                return new EditorCurveBinding[] {};\n\n            var bindings = new HashSet<EditorCurveBinding>();\n\n            for (int i = 0; i < modifications.Length; ++i)\n            {\n                var binding = new EditorCurveBinding();\n                if (AnimationUtility.PropertyModificationToEditorCurveBinding(modifications[i], rootGameObject, out binding) != null)\n                {\n                    EditorCurveBinding[] additionalBindings = RotationCurveInterpolation.RemapAnimationBindingForAddKey(binding, animationClip);\n                    if (additionalBindings != null)\n                    {\n                        for (int j = 0; j < additionalBindings.Length; ++j)\n                        {\n                            bindings.Add(additionalBindings[j]);\n                        }\n                    }\n                    else\n                    {\n                        bindings.Add(binding);\n                    }\n                }\n            }\n\n            return bindings.ToArray();\n        }\n\n        public static EditorCurveBinding[] SerializedPropertyToEditorCurveBindings(SerializedProperty property, GameObject rootGameObject, AnimationClip animationClip)\n        {\n            PropertyModification[] modifications = AnimationWindowUtility.SerializedPropertyToPropertyModifications(property);\n            return PropertyModificationsToEditorCurveBindings(modifications, rootGameObject, animationClip);\n        }\n\n        public static bool CurveExists(EditorCurveBinding binding, AnimationWindowCurve[] curves)\n        {\n            foreach (var animationWindowCurve in curves)\n            {\n                if (binding.propertyName == animationWindowCurve.binding.propertyName &&\n                    binding.type == animationWindowCurve.binding.type &&\n                    binding.path == animationWindowCurve.binding.path)\n                    return true;\n            }\n            return false;\n        }\n\n        public static EditorCurveBinding GetRenamedBinding(EditorCurveBinding binding, string newPath)\n        {\n            EditorCurveBinding newBinding = new EditorCurveBinding();\n            newBinding.path = newPath;\n            newBinding.propertyName = binding.propertyName;\n            newBinding.type = binding.type;\n            return newBinding;\n        }\n\n        public static void RenameCurvePath(AnimationWindowCurve curve, EditorCurveBinding newBinding, AnimationClip clip)\n        {\n            if (curve.isPPtrCurve)\n            {\n                // Delete old curve\n                AnimationUtility.SetObjectReferenceCurve(clip, curve.binding, null);\n\n                // Add new curve\n                AnimationUtility.SetObjectReferenceCurve(clip, newBinding, curve.ToObjectCurve());\n            }\n            else\n            {\n                // Delete old curve\n                AnimationUtility.SetEditorCurve(clip, curve.binding, null);\n\n                // Add new curve\n                AnimationUtility.SetEditorCurve(clip, newBinding, curve.ToAnimationCurve());\n            }\n        }\n\n        private static readonly string k_PositionDisplayName = L10n.Tr(\"Position\");\n        private static readonly string k_ScaleDisplayName = L10n.Tr(\"Scale\");\n        private static readonly string k_RotationDisplayName = L10n.Tr(\"Rotation\");\n        private static readonly string k_MaterialReferenceDisplayName = L10n.Tr(\"Material Reference\");\n\n        // Takes raw animation curve propertyname and makes it pretty\n        public static string GetPropertyDisplayName(string propertyName)\n        {\n            propertyName = propertyName.Replace(\"m_LocalPosition\", k_PositionDisplayName);\n            propertyName = propertyName.Replace(\"m_LocalScale\", k_ScaleDisplayName);\n            propertyName = propertyName.Replace(\"m_LocalRotation\", k_RotationDisplayName);\n            propertyName = propertyName.Replace(\"localEulerAnglesBaked\", k_RotationDisplayName);\n            propertyName = propertyName.Replace(\"localEulerAnglesRaw\", k_RotationDisplayName);\n            propertyName = propertyName.Replace(\"localEulerAngles\", k_RotationDisplayName);\n            propertyName = propertyName.Replace(\"m_Materials.Array.data\", k_MaterialReferenceDisplayName);\n            if (propertyName.StartsWith(\"managedReferences[\"))\n                propertyName = propertyName.Remove(0, propertyName.IndexOf('.')+1);\n\n            propertyName = ObjectNames.NicifyVariableName(propertyName);\n            propertyName = propertyName.Replace(\"m_\", \"\");\n\n            return propertyName;\n        }\n\n        // Transform and Sprite: just show Position / Rotation / Scale / Sprite\n        public static bool ShouldPrefixWithTypeName(Type animatableObjectType, string propertyName)\n        {\n            if (animatableObjectType == typeof(Transform) || animatableObjectType == typeof(RectTransform))\n                return false;\n\n            if (animatableObjectType == typeof(SpriteRenderer) && propertyName == \"m_Sprite\")\n                return false;\n\n            return true;\n        }\n\n        public static string GetNicePropertyDisplayName(EditorCurveBinding curveBinding, SerializedObject so)\n        {\n            if (curveBinding.isSerializeReferenceCurve)\n            {\n                if (so != null)\n                {\n                    var displayName = curveBinding.propertyName;\n                    var sp = so.FindFirstPropertyFromManagedReferencePath(displayName);\n                    if (sp != null)\n                        displayName = AnimationWindowUtility.GetPropertyDisplayName(AnimationWindowUtility.GetPropertyGroupName(sp.propertyPath));\n                    if (displayName != \"\")\n                        return displayName;\n                }\n                else\n                {\n                    return ObjectNames.NicifyVariableName(curveBinding.type.Name) + \".\" + curveBinding.propertyName;\n                }\n\n            }\n\n            return AnimationWindowUtility.GetNicePropertyDisplayName(curveBinding.type, AnimationWindowUtility.GetPropertyGroupName(curveBinding.propertyName));\n        }\n\n        public static string GetNicePropertyDisplayName(Type animatableObjectType, string propertyName)\n        {\n            if (ShouldPrefixWithTypeName(animatableObjectType, propertyName))\n                return ObjectNames.NicifyVariableName(animatableObjectType.Name) + \".\" + GetPropertyDisplayName(propertyName);\n            else\n                return GetPropertyDisplayName(propertyName);\n        }\n\n        public static string GetNicePropertyGroupDisplayName(EditorCurveBinding curveBinding, SerializedObject so)\n        {\n            if (curveBinding.isSerializeReferenceCurve )\n            {\n                if (so != null)\n                {\n                    var displayName = curveBinding.propertyName;\n                    var sp = so.FindFirstPropertyFromManagedReferencePath(displayName);\n                    if (sp != null)\n                        displayName = AnimationWindowUtility.GetPropertyDisplayName(AnimationWindowUtility.GetPropertyGroupName(sp.propertyPath));\n                    if (displayName != \"\")\n                        return displayName;\n                }\n                else\n                {\n                    return ObjectNames.NicifyVariableName(curveBinding.type.Name) + \".\" + curveBinding.propertyName;\n                }\n            }\n\n            return NicifyPropertyGroupName(curveBinding.type, AnimationWindowUtility.GetPropertyGroupName(curveBinding.propertyName));\n        }\n\n        public static string GetNicePropertyGroupDisplayName(Type animatableObjectType, string propertyGroupName)\n        {\n            if (ShouldPrefixWithTypeName(animatableObjectType, propertyGroupName))\n                return ObjectNames.NicifyVariableName(animatableObjectType.Name) + \".\" + NicifyPropertyGroupName(animatableObjectType, propertyGroupName);\n            else\n                return NicifyPropertyGroupName(animatableObjectType, propertyGroupName);\n        }\n\n        // Takes raw animation curve propertyname and returns a pretty groupname\n        public static string NicifyPropertyGroupName(Type animatableObjectType, string propertyGroupName)\n        {\n            string result = GetPropertyGroupName(GetPropertyDisplayName(propertyGroupName));\n\n            // Workaround for uGUI RectTransform which only animates position.z\n            if (animatableObjectType == typeof(RectTransform) && result.Equals(\"Position\"))\n                result = \"Position (Z)\";\n\n            return result;\n        }\n\n        // We automatically group Vector4, Vector3 and Color\n        static public int GetComponentIndex(string name)\n        {\n            if (name == null || name.Length < 3 || name[name.Length - 2] != '.')\n                return -1;\n            char lastCharacter = name[name.Length - 1];\n            switch (lastCharacter)\n            {\n                case 'r':\n                    return 0;\n                case 'g':\n                    return 1;\n                case 'b':\n                    return 2;\n                case 'a':\n                    return 3;\n                case 'x':\n                    return 0;\n                case 'y':\n                    return 1;\n                case 'z':\n                    return 2;\n                case 'w':\n                    return 3;\n                default:\n                    return -1;\n            }\n        }\n\n        // If Vector4, Vector3 or Color, return group name instead of full name\n        public static string GetPropertyGroupName(string propertyName)\n        {\n            if (GetComponentIndex(propertyName) != -1)\n                return propertyName.Substring(0, propertyName.Length - 2);\n\n            return propertyName;\n        }\n\n        public static float GetNextKeyframeTime(AnimationWindowCurve[] curves, float currentTime, float frameRate)\n        {\n            AnimationKeyTime candidateKeyTime = AnimationKeyTime.Frame(int.MaxValue, frameRate);\n            AnimationKeyTime time = AnimationKeyTime.Time(currentTime, frameRate);\n            AnimationKeyTime nextTime = AnimationKeyTime.Frame(time.frame + 1, frameRate);\n            bool found = false;\n\n            foreach (AnimationWindowCurve curve in curves)\n            {\n                foreach (AnimationWindowKeyframe keyframe in curve.keyframes)\n                {\n                    AnimationKeyTime keyTime = AnimationKeyTime.Time(keyframe.time, frameRate);\n                    if (keyTime.frame <= candidateKeyTime.frame && keyTime.frame >= nextTime.frame)\n                    {\n                        if (keyframe.time <= candidateKeyTime.time)\n                        {\n                            candidateKeyTime = keyTime;\n                            found = true;\n                        }\n                    }\n                }\n            }\n            return found ? candidateKeyTime.time : time.time;\n        }\n\n        public static float GetPreviousKeyframeTime(AnimationWindowCurve[] curves, float currentTime, float frameRate)\n        {\n            AnimationKeyTime candidateKeyTime = AnimationKeyTime.Time(float.MinValue, frameRate);\n            AnimationKeyTime time = AnimationKeyTime.Time(currentTime, frameRate);\n            AnimationKeyTime previousTime = AnimationKeyTime.Frame(time.frame - 1, frameRate);\n\n            bool found = false;\n\n            foreach (AnimationWindowCurve curve in curves)\n            {\n                foreach (AnimationWindowKeyframe keyframe in curve.keyframes)\n                {\n                    AnimationKeyTime keyTime = AnimationKeyTime.Time(keyframe.time, frameRate);\n                    if (keyTime.frame >= candidateKeyTime.frame && keyTime.frame <= previousTime.frame)\n                    {\n                        if (keyTime.time >= candidateKeyTime.time)\n                        {\n                            candidateKeyTime = keyTime;\n                            found = true;\n                        }\n                    }\n                }\n            }\n\n            return found ? candidateKeyTime.time : time.time;\n        }\n\n        // Add animator, controller and clip to gameobject if they are missing to make this gameobject animatable\n        public static bool InitializeGameobjectForAnimation(GameObject animatedObject)\n        {\n            Component animationPlayer = GetClosestAnimationPlayerComponentInParents(animatedObject.transform);\n            if (animationPlayer == null)\n            {\n                var newClip = CreateNewClip(animatedObject.name);\n\n                if (newClip == null)\n                    return false;\n\n                animationPlayer = EnsureActiveAnimationPlayer(animatedObject);\n                Undo.RecordObject(animationPlayer, \"Add animation clip\");\n                bool success = AddClipToAnimationPlayerComponent(animationPlayer, newClip);\n\n                if (!success)\n                    Object.DestroyImmediate(animationPlayer);\n\n                return success;\n            }\n\n            return EnsureAnimationPlayerHasClip(animationPlayer);\n        }\n\n        // Ensures that the gameobject or it's parents have an animation player component. If not try to create one.\n        public static Component EnsureActiveAnimationPlayer(GameObject animatedObject)\n        {\n            Component closestAnimator = GetClosestAnimationPlayerComponentInParents(animatedObject.transform);\n            if (closestAnimator == null)\n            {\n                return Undo.AddComponent<Animator>(animatedObject);\n            }\n            return closestAnimator;\n        }\n\n        // Ensures that animator has atleast one clip and controller to go with it\n        private static bool EnsureAnimationPlayerHasClip(Component animationPlayer)\n        {\n            if (animationPlayer == null)\n                return false;\n\n            if (AnimationUtility.GetAnimationClips(animationPlayer.gameObject).Length > 0)\n                return true;\n\n            // At this point we know that we can create a clip\n            var newClip = CreateNewClip(animationPlayer.gameObject.name);\n\n            if (newClip == null)\n                return false;\n\n            // End animation mode before adding or changing animation component to object\n            AnimationMode.StopAnimationMode();\n\n            // By default add it the animation to the Animator component.\n            return AddClipToAnimationPlayerComponent(animationPlayer, newClip);\n        }\n\n        public static bool AddClipToAnimationPlayerComponent(Component animationPlayer, AnimationClip newClip)\n        {\n            if (animationPlayer is Animator)\n                return AddClipToAnimatorComponent(animationPlayer as Animator, newClip);\n            else if (animationPlayer is Animation)\n                return AddClipToAnimationComponent(animationPlayer as Animation, newClip);\n            return false;\n        }\n\n        public static bool AddClipToAnimatorComponent(Animator animator, AnimationClip newClip)\n        {\n            UnityEditor.Animations.AnimatorController controller = UnityEditor.Animations.AnimatorController.GetEffectiveAnimatorController(animator);\n            if (controller == null)\n            {\n                controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerForClip(newClip, animator.gameObject);\n\n                Undo.RecordObject(animator, \"Set Controller\");\n                UnityEditor.Animations.AnimatorController.SetAnimatorController(animator, controller);\n\n                if (controller != null)\n                    return true;\n            }\n            else\n            {\n                // Do we already have a state with the clips name?\n                ChildAnimatorState childAnimatorState = controller.layers[0].stateMachine.FindState(newClip.name);\n\n                if (childAnimatorState.Equals(default(ChildAnimatorState)))\n                    controller.AddMotion(newClip);\n\n                // Assign clip if state already present, but without a motion\n                else if (childAnimatorState.state && childAnimatorState.state.motion == null)\n                    childAnimatorState.state.motion = newClip;\n\n                // State present, but with some other clip\n                else if (childAnimatorState.state && childAnimatorState.state.motion != newClip)\n                    controller.AddMotion(newClip);\n\n                return true;\n            }\n            return false;\n        }\n\n        public static bool AddClipToAnimationComponent(Animation animation, AnimationClip newClip)\n        {\n            SetClipAsLegacy(newClip);\n            animation.AddClip(newClip, newClip.name);\n            return true;\n        }\n\n        internal static string s_LastPathUsedForNewClip;\n        internal static AnimationClip CreateNewClip(string gameObjectName)\n        {\n            // Go forward with presenting user a save clip dialog\n            string message = string.Format(L10n.Tr(\"Create a new animation for the game object '{0}':\"), gameObjectName);\n            string newClipDirectory = ProjectWindowUtil.GetActiveFolderPath();\n            if (s_LastPathUsedForNewClip != null)\n            {\n                string directoryPath = Path.GetDirectoryName(s_LastPathUsedForNewClip);\n                if (directoryPath != null && Directory.Exists(directoryPath))\n                {\n                    newClipDirectory = directoryPath;\n                }\n            }\n            string newClipPath = EditorUtility.SaveFilePanelInProject(L10n.Tr(\"Create New Animation\"), \"New Animation\", \"anim\", message, newClipDirectory);\n\n            // If user canceled or save path is invalid, we can't create a clip\n            if (newClipPath == \"\")\n                return null;\n\n            return CreateNewClipAtPath(newClipPath);\n        }\n\n        // Create a new animation clip asset for gameObject at a certain asset path.\n        // The clipPath parameter must be a full asset path ending with '.anim'. e.g. \"Assets/Animations/New Clip.anim\"\n        // This function will overwrite existing .anim files.\n        internal static AnimationClip CreateNewClipAtPath(string clipPath)\n        {\n            s_LastPathUsedForNewClip = clipPath;\n\n            var newClip = new AnimationClip();\n\n            var info = AnimationUtility.GetAnimationClipSettings(newClip);\n            info.loopTime = true;\n            AnimationUtility.SetAnimationClipSettingsNoDirty(newClip, info);\n\n            AnimationClip asset = AssetDatabase.LoadMainAssetAtPath(clipPath) as AnimationClip;\n\n            if (asset)\n            {\n                newClip.name = asset.name;\n                EditorUtility.CopySerialized(newClip, asset);\n                AssetDatabase.SaveAssets();\n                Object.DestroyImmediate(newClip);\n                return asset;\n            }\n\n            AssetDatabase.CreateAsset(newClip, clipPath);\n            return newClip;\n        }\n\n        private static void SetClipAsLegacy(AnimationClip clip)\n        {\n            SerializedObject s = new SerializedObject(clip);\n            s.FindProperty(\"m_Legacy\").boolValue = true;\n            s.ApplyModifiedProperties();\n        }\n\n        internal static AnimationClip AllocateAndSetupClip(bool useAnimator)\n        {\n            // At this point we know that we can create a clip\n            AnimationClip newClip = new AnimationClip();\n            if (useAnimator)\n            {\n                AnimationClipSettings info = AnimationUtility.GetAnimationClipSettings(newClip);\n                info.loopTime = true;\n                AnimationUtility.SetAnimationClipSettingsNoDirty(newClip, info);\n            }\n            return newClip;\n        }\n\n        public static int GetPropertyNodeID(int setId, string path, System.Type type, string propertyName)\n        {\n            return (setId + path + type.Name + propertyName).GetHashCode();\n        }\n\n        // What is the first animation player component (Animator or Animation) when recursing parent tree toward root\n        public static Component GetClosestAnimationPlayerComponentInParents(Transform tr)\n        {\n            while (true)\n            {\n                if (tr.TryGetComponent(out Animator animator))\n                {\n                    return animator;\n                }\n\n                if (tr.TryGetComponent(out Animation animation))\n                {\n                    return animation;\n                }\n\n                if (tr.TryGetComponent(out IAnimationClipSource clipPlayer))\n                {\n                    if (clipPlayer is Component clipPlayerComponent)\n                    {\n                        return clipPlayerComponent;\n                    }\n                }\n\n                if (tr == tr.root)\n                    break;\n\n                tr = tr.parent;\n            }\n            return null;\n        }\n\n        // What is the first animator component when recursing parent tree toward root\n        public static Animator GetClosestAnimatorInParents(Transform tr)\n        {\n            while (true)\n            {\n                if (tr.TryGetComponent(out Animator animator))\n                {\n                    return animator;\n                }\n                if (tr == tr.root) break;\n                tr = tr.parent;\n            }\n            return null;\n        }\n\n        // What is the first animation component when recursing parent tree toward root\n        public static Animation GetClosestAnimationInParents(Transform tr)\n        {\n            while (true)\n            {\n                if (tr.TryGetComponent(out Animation animation))\n                {\n                    return animation;\n                }\n                if (tr == tr.root) break;\n                tr = tr.parent;\n            }\n            return null;\n        }\n\n        public static void SyncTimeArea(TimeArea from, TimeArea to)\n        {\n            to.SetDrawRectHack(from.drawRect);\n            to.m_Scale = new Vector2(from.m_Scale.x, to.m_Scale.y);\n            to.m_Translation = new Vector2(from.m_Translation.x, to.m_Translation.y);\n            to.EnforceScaleAndRange();\n        }\n\n        public static void DrawInRangeOverlay(Rect rect, Color color, float startOfClipPixel, float endOfClipPixel)\n        {\n            // Rect shaded shape drawn inside range\n            if (endOfClipPixel >= rect.xMin)\n            {\n                if (color.a > 0f)\n                {\n                    Rect inRect = Rect.MinMaxRect(Mathf.Max(startOfClipPixel, rect.xMin), rect.yMin, Mathf.Min(endOfClipPixel, rect.xMax), rect.yMax);\n                    DrawRect(inRect, color);\n                }\n            }\n        }\n\n        public static void DrawOutOfRangeOverlay(Rect rect, Color color, float startOfClipPixel, float endOfClipPixel)\n        {\n            Color lineColor = Color.white.RGBMultiplied(0.4f);\n\n            // Rect shaded shape drawn before range\n            if (startOfClipPixel > rect.xMin)\n            {\n                Rect startRect = Rect.MinMaxRect(rect.xMin, rect.yMin, Mathf.Min(startOfClipPixel, rect.xMax), rect.yMax);\n                DrawRect(startRect, color);\n                TimeArea.DrawVerticalLine(startRect.xMax, startRect.yMin, startRect.yMax, lineColor);\n            }\n\n            // Rect shaded shape drawn after range\n            Rect endRect = Rect.MinMaxRect(Mathf.Max(endOfClipPixel, rect.xMin), rect.yMin, rect.xMax, rect.yMax);\n            DrawRect(endRect, color);\n            TimeArea.DrawVerticalLine(endRect.xMin, endRect.yMin, endRect.yMax, lineColor);\n        }\n\n        public static void DrawSelectionOverlay(Rect rect, Color color, float startPixel, float endPixel)\n        {\n            startPixel = Mathf.Max(startPixel, rect.xMin);\n            endPixel = Mathf.Max(endPixel, rect.xMin);\n\n            Rect labelRect = Rect.MinMaxRect(startPixel, rect.yMin, endPixel, rect.yMax);\n            DrawRect(labelRect, color);\n        }\n\n        public static void DrawRect(Rect rect, Color color)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            HandleUtility.ApplyWireMaterial();\n            GL.PushMatrix();\n            GL.MultMatrix(Handles.matrix);\n            GL.Begin(GL.QUADS);\n            GL.Color(color);\n            GL.Vertex(rect.min);\n            GL.Vertex(new Vector2(rect.xMax, rect.yMin));\n            GL.Vertex(rect.max);\n            GL.Vertex(new Vector2(rect.xMin, rect.yMax));\n            GL.End();\n            GL.PopMatrix();\n        }\n\n        private static CurveRenderer CreateRendererForCurve(AnimationWindowCurve curve)\n        {\n            CurveRenderer renderer;\n            switch (System.Type.GetTypeCode(curve.valueType))\n            {\n                case TypeCode.Int32:\n                    renderer = new IntCurveRenderer(curve.ToAnimationCurve());\n                    break;\n                case TypeCode.Boolean:\n                    renderer = new BoolCurveRenderer(curve.ToAnimationCurve());\n                    break;\n                default:\n                    renderer = new NormalCurveRenderer(curve.ToAnimationCurve());\n                    break;\n            }\n            return renderer;\n        }\n\n        private static CurveWrapper.PreProcessKeyMovement CreateKeyPreprocessorForCurve(AnimationWindowCurve curve)\n        {\n            CurveWrapper.PreProcessKeyMovement method;\n            switch (System.Type.GetTypeCode(curve.valueType))\n            {\n                case TypeCode.Int32:\n                    method = (ref Keyframe key) => { key.value = Mathf.Floor(key.value + 0.5f); };\n                    break;\n                case TypeCode.Boolean:\n                    method = (ref Keyframe key) => { key.value = key.value > 0.5f ? 1.0f : 0.0f; };\n                    break;\n                default:\n                    method = null;\n                    break;\n            }\n            return method;\n        }\n\n        public static CurveWrapper GetCurveWrapper(AnimationWindowCurve curve, AnimationClip clip)\n        {\n            //Discrete and PPtr curves are not allowed to create curve wrappers.\n            if (curve.isDiscreteCurve || curve.isPPtrCurve)\n                return null;\n\n            CurveWrapper curveWrapper = new CurveWrapper();\n            curveWrapper.renderer = CreateRendererForCurve(curve);\n            curveWrapper.preProcessKeyMovementDelegate = CreateKeyPreprocessorForCurve(curve);\n            curveWrapper.renderer.SetWrap(WrapMode.Clamp, clip.isLooping ? WrapMode.Loop : WrapMode.Clamp);\n            curveWrapper.renderer.SetCustomRange(clip.startTime, clip.stopTime);\n            curveWrapper.binding = curve.binding;\n            curveWrapper.id = curve.GetHashCode();\n            curveWrapper.color = CurveUtility.GetPropertyColor(curve.propertyName);\n            curveWrapper.hidden = false;\n            curveWrapper.selectionBindingInterface = curve.selectionBinding;\n            return curveWrapper;\n        }\n\n        // Convert keyframe from curve editor representation (CurveSelection) to animation window representation (AnimationWindowKeyframe)\n        public static AnimationWindowKeyframe CurveSelectionToAnimationWindowKeyframe(CurveSelection curveSelection, List<AnimationWindowCurve> allCurves)\n        {\n            foreach (AnimationWindowCurve curve in allCurves)\n            {\n                int curveID = curve.GetHashCode();\n                if (curveID == curveSelection.curveID)\n                    if (curve.keyframes.Count > curveSelection.key)\n                        return curve.keyframes[curveSelection.key];\n            }\n\n            return null;\n        }\n\n        // Convert keyframe from animation window representation (AnimationWindowKeyframe) to curve editor representation (CurveSelection) to animation window representation (AnimationWindowKeyframe)\n        public static CurveSelection AnimationWindowKeyframeToCurveSelection(AnimationWindowKeyframe keyframe, CurveEditor curveEditor)\n        {\n            int curveID = keyframe.curve.GetHashCode();\n            foreach (CurveWrapper curveWrapper in curveEditor.animationCurves)\n                if (curveWrapper.id == curveID && keyframe.GetIndex() >= 0)\n                    return new CurveSelection(curveWrapper.id, keyframe.GetIndex());\n\n            return null;\n        }\n\n        public static AnimationWindowCurve BestMatchForPaste(EditorCurveBinding binding, List<AnimationWindowCurve> clipboardCurves, List<AnimationWindowCurve> targetCurves)\n        {\n            // Exact match\n            foreach (AnimationWindowCurve targetCurve in targetCurves)\n                if (targetCurve.binding == binding)\n                    return targetCurve;\n\n            // Matching propertyname\n            foreach (AnimationWindowCurve targetCurve in targetCurves)\n            {\n                if (targetCurve.binding.propertyName == binding.propertyName)\n                {\n                    // Only match if key in binding is not already being pasted itself in clipboardCurves.\n                    if (!clipboardCurves.Exists(clipboardCurve => clipboardCurve.binding == targetCurve.binding))\n                    {\n                        return targetCurve;\n                    }\n                }\n            }\n\n            // No good match found.\n            return null;\n        }\n\n        // Make a rect from MinMax values and make sure they're positive sizes\n        internal static Rect FromToRect(Vector2 start, Vector2 end)\n        {\n            Rect r = new Rect(start.x, start.y, end.x - start.x, end.y - start.y);\n            if (r.width < 0)\n            {\n                r.x += r.width;\n                r.width = -r.width;\n            }\n            if (r.height < 0)\n            {\n                r.y += r.height;\n                r.height = -r.height;\n            }\n            return r;\n        }\n\n        public static bool IsTransformType(Type type)\n        {\n            return type == typeof(Transform) || type == typeof(RectTransform);\n        }\n\n        public static bool IsActualTransformCurve(EditorCurveBinding curveBinding)\n        {\n            return curveBinding.type == typeof(Transform) || curveBinding.type == typeof(RectTransform) && (curveBinding.propertyName.StartsWith(\"m_LocalScale\") ||\n                curveBinding.propertyName.StartsWith(\"m_LocalRotation\") ||\n                curveBinding.propertyName.StartsWith(\"localEuler\"));\n        }\n\n        public static bool ForceGrouping(EditorCurveBinding binding)\n        {\n            if (binding.type == typeof(Transform))\n                return true;\n\n            if (binding.type == typeof(RectTransform))\n            {\n                string group = GetPropertyGroupName(binding.propertyName);\n                return group == \"m_LocalPosition\" || group == \"m_LocalScale\" || group == \"m_LocalRotation\" || group == \"localEulerAnglesBaked\" || group == \"localEulerAngles\" || group == \"localEulerAnglesRaw\";\n            }\n\n            if (typeof(Renderer).IsAssignableFrom(binding.type))\n            {\n                string group = GetPropertyGroupName(binding.propertyName);\n                return group == \"material._Color\" || group == \"material._BaseColor\";\n            }\n            return false;\n        }\n\n        public static void ControllerChanged()\n        {\n            foreach (AnimationWindow animationWindow in AnimationWindow.GetAllAnimationWindows())\n                animationWindow.OnControllerChange();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/ControlPointRenderer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace UnityEditor\n{\n    //  Control point renderer\n    internal class ControlPointRenderer\n    {\n        private class RenderChunk\n        {\n            public Mesh mesh;\n\n            public List<Vector3> vertices;\n            public List<Color32> colors;\n            public List<Vector2> uvs;\n            public List<int> indices;\n\n            public bool isDirty = true;\n        }\n\n        private int m_RenderChunkIndex = -1;\n        private List<RenderChunk> m_RenderChunks = new List<RenderChunk>();\n\n        private Texture2D m_Icon;\n\n        //  Can hold a maximum of 16250 control points.\n        const int kMaxVertices = 65000;\n        const string kControlPointRendererMeshName = \"ControlPointRendererMesh\";\n\n        private static Material s_Material;\n        public static Material material\n        {\n            get\n            {\n                if (!s_Material)\n                {\n                    Shader shader = (Shader)EditorGUIUtility.LoadRequired(\"Editors/AnimationWindow/ControlPoint.shader\");\n                    s_Material = new Material(shader);\n                    s_Material.hideFlags = HideFlags.HideAndDontSave;\n                }\n\n                return s_Material;\n            }\n        }\n\n        public ControlPointRenderer(Texture2D icon)\n        {\n            m_Icon = icon;\n        }\n\n        public void FlushCache()\n        {\n            for (int i = 0; i < m_RenderChunks.Count; ++i)\n            {\n                Object.DestroyImmediate(m_RenderChunks[i].mesh);\n            }\n\n            m_RenderChunks.Clear();\n        }\n\n        public void Clear()\n        {\n            for (int i = 0; i < m_RenderChunks.Count; ++i)\n            {\n                RenderChunk renderChunk = m_RenderChunks[i];\n\n                renderChunk.mesh.Clear();\n\n                renderChunk.vertices.Clear();\n                renderChunk.colors.Clear();\n                renderChunk.uvs.Clear();\n\n                renderChunk.indices.Clear();\n\n                renderChunk.isDirty = true;\n            }\n\n            m_RenderChunkIndex = 0;\n        }\n\n        public void Render()\n        {\n            Material mat = material;\n            mat.SetTexture(\"_MainTex\", m_Icon);\n            mat.SetPass(0);\n\n            for (int i = 0; i < m_RenderChunks.Count; ++i)\n            {\n                RenderChunk renderChunk = m_RenderChunks[i];\n\n                if (renderChunk.isDirty)\n                {\n                    renderChunk.mesh.SetVertices(renderChunk.vertices);\n                    renderChunk.mesh.SetColors(renderChunk.colors);\n                    renderChunk.mesh.SetUVs(0, renderChunk.uvs);\n\n                    renderChunk.mesh.SetIndices(renderChunk.indices, MeshTopology.Triangles, 0);\n\n                    renderChunk.isDirty = false;\n                }\n\n                // Previous camera may still be active when calling DrawMeshNow.\n                Camera.SetupCurrent(null);\n\n                Graphics.DrawMeshNow(renderChunk.mesh, Handles.matrix);\n            }\n        }\n\n        public void AddPoint(Rect rect, Color color)\n        {\n            RenderChunk renderChunk = GetRenderChunk();\n\n            int baseIndex = renderChunk.vertices.Count;\n\n            renderChunk.vertices.Add(new Vector3(rect.xMin, rect.yMin, 0.0f));\n            renderChunk.vertices.Add(new Vector3(rect.xMax, rect.yMin, 0.0f));\n            renderChunk.vertices.Add(new Vector3(rect.xMax, rect.yMax, 0.0f));\n            renderChunk.vertices.Add(new Vector3(rect.xMin, rect.yMax, 0.0f));\n\n            renderChunk.colors.Add(color);\n            renderChunk.colors.Add(color);\n            renderChunk.colors.Add(color);\n            renderChunk.colors.Add(color);\n\n            renderChunk.uvs.Add(new Vector2(0.0f, 0.0f));\n            renderChunk.uvs.Add(new Vector2(1.0f, 0.0f));\n            renderChunk.uvs.Add(new Vector2(1.0f, 1.0f));\n            renderChunk.uvs.Add(new Vector2(0.0f, 1.0f));\n\n            renderChunk.indices.Add(baseIndex);\n            renderChunk.indices.Add(baseIndex + 1);\n            renderChunk.indices.Add(baseIndex + 2);\n\n            renderChunk.indices.Add(baseIndex);\n            renderChunk.indices.Add(baseIndex + 2);\n            renderChunk.indices.Add(baseIndex + 3);\n\n            renderChunk.isDirty = true;\n        }\n\n        private RenderChunk GetRenderChunk()\n        {\n            RenderChunk renderChunk = null;\n            if (m_RenderChunks.Count > 0)\n            {\n                while (m_RenderChunkIndex < m_RenderChunks.Count)\n                {\n                    renderChunk = m_RenderChunks[m_RenderChunkIndex];\n                    // Dynamically create new render chunks when needed.\n                    if ((renderChunk.vertices.Count + 4) > kMaxVertices)\n                    {\n                        m_RenderChunkIndex++;\n                        renderChunk = null;\n                        continue;\n                    }\n\n                    break;\n                }\n\n                if (renderChunk == null)\n                {\n                    renderChunk = CreateRenderChunk();\n                }\n            }\n            else\n            {\n                renderChunk = CreateRenderChunk();\n            }\n\n            return renderChunk;\n        }\n\n        private RenderChunk CreateRenderChunk()\n        {\n            RenderChunk renderChunk = new RenderChunk();\n\n            renderChunk.mesh = new Mesh();\n            renderChunk.mesh.name = kControlPointRendererMeshName;\n            renderChunk.mesh.hideFlags |= HideFlags.DontSave;\n\n            renderChunk.vertices = new List<Vector3>();\n            renderChunk.colors = new List<Color32>();\n            renderChunk.uvs = new List<Vector2>();\n            renderChunk.indices = new List<int>();\n\n            m_RenderChunks.Add(renderChunk);\n            m_RenderChunkIndex = m_RenderChunks.Count - 1;\n\n            return renderChunk;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/CurveBindingUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    static internal class CurveBindingUtility\n    {\n        // Current value of the property that rootGO + curveBinding is pointing to\n        public static object GetCurrentValue(AnimationWindowState state, EditorCurveBinding binding)\n        {\n            if (binding.isPPtrCurve)\n            {\n                return state.controlInterface.GetObjectReferenceValue(binding);\n            }\n            else if (binding.isDiscreteCurve)\n            {\n                return state.controlInterface.GetIntValue(binding);\n            }\n\n            return state.controlInterface.GetFloatValue(binding);\n        }\n\n\n        // Retrieve current value.  If bindings are available and value is animated, use bindings to get value.\n        // Otherwise, evaluate AnimationWindowCurve at current time.\n        public static object GetCurrentValue(AnimationWindowState state, AnimationWindowCurve curve)\n        {\n            // UUM-66112 - state.linkedWithSequencer - Padding for issue in Timeline where muscle\n            // values are not updated in the editor when previewing in the Animation Window.\n            // Fallback to curve values.\n            if (state.previewing && curve.rootGameObject != null && !state.linkedWithSequencer)\n            {\n                return GetCurrentValue(state, curve.binding);\n            }\n            else\n            {\n                return curve.Evaluate(state.currentTime);\n            }\n        }\n\n        // Retrieve Current Value.  Use specified bindings to do so.\n        public static object GetCurrentValue(GameObject rootGameObject, EditorCurveBinding curveBinding)\n        {\n            if (rootGameObject != null)\n            {\n                return AnimationWindowUtility.GetCurrentValue(rootGameObject, curveBinding);\n            }\n            else\n            {\n                if (curveBinding.isPPtrCurve)\n                {\n                    // Cannot extract type of PPtrCurve.\n                    return null;\n                }\n                else if (curveBinding.isDiscreteCurve)\n                {\n                    return 0;\n                }\n                else\n                {\n                    // Cannot extract type of AnimationCurve.  Default to float.\n                    return 0.0f;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/CurveEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\n\nusing Object = UnityEngine.Object;\nusing TangentMode = UnityEditor.AnimationUtility.TangentMode;\nusing RectangleToolFlags = UnityEditor.CurveEditorSettings.RectangleToolFlags;\n\nnamespace UnityEditor\n{\n    // External selection interface\n    internal interface ISelectionBinding\n    {\n        GameObject rootGameObject { get; }\n        AnimationClip animationClip { get; }\n\n        bool clipIsEditable { get; }\n        bool animationIsEditable { get; }\n\n        int id { get; }\n    }\n\n    // External state interface\n    internal interface ICurveEditorState\n    {\n        TimeArea.TimeFormat timeFormat { get; }\n        Vector2 timeRange { get; }\n\n        bool rippleTime { get; }\n    }\n\n    internal class CurveWrapper\n    {\n        public delegate Vector2 GetAxisScalarsCallback();\n        public delegate void SetAxisScalarsCallback(Vector2 newAxisScalars);\n        public delegate void PreProcessKeyMovement(ref Keyframe key);\n\n        public CurveWrapper()\n        {\n            id = 0;\n            groupId = -1;\n            regionId = -1;\n            hidden = false;\n            readOnly = false;\n            listIndex = -1;\n            getAxisUiScalarsCallback = null;\n            setAxisUiScalarsCallback = null;\n        }\n\n        internal enum SelectionMode\n        {\n            None = 0,\n            Selected = 1,\n            SemiSelected = 2\n        }\n\n        // Curve management\n        private CurveRenderer m_Renderer;\n        private ISelectionBinding m_SelectionBinding;\n\n        public CurveRenderer renderer { get { return m_Renderer; } set { m_Renderer = value; } }\n        public AnimationCurve curve { get { return renderer.GetCurve(); } }\n\n        public GameObject rootGameObjet { get { return m_SelectionBinding != null ? m_SelectionBinding.rootGameObject : null; } }\n        public AnimationClip animationClip { get { return m_SelectionBinding != null ? m_SelectionBinding.animationClip : null; } }\n        public bool clipIsEditable { get { return m_SelectionBinding != null ? m_SelectionBinding.clipIsEditable : true; } }\n        public bool animationIsEditable { get { return m_SelectionBinding != null ? m_SelectionBinding.animationIsEditable : true; } }\n        public int selectionID { get { return m_SelectionBinding != null ? m_SelectionBinding.id : 0; } }\n\n        public ISelectionBinding selectionBindingInterface { get { return m_SelectionBinding; } set { m_SelectionBinding = value; } }\n\n        public Bounds bounds { get { return renderer.GetBounds(); } }\n\n        // Input - should not be changed by curve editor\n        public int id;\n        public EditorCurveBinding binding;\n        public int groupId;\n        public int regionId;                                    // Regions are defined by two curves added after each other with the same regionId.\n        public Color color;\n        public Color wrapColorMultiplier = Color.white;\n        public bool readOnly;\n        public bool hidden;\n        public GetAxisScalarsCallback getAxisUiScalarsCallback; // Delegate used to fetch values that are multiplied on x and y axis ui values\n        public SetAxisScalarsCallback setAxisUiScalarsCallback; // Delegate used to set values back that has been changed by this curve editor\n\n        public PreProcessKeyMovement preProcessKeyMovementDelegate; // Delegate used limit key manipulation to fit curve constraints\n\n        // Should be updated by curve editor as appropriate\n        public SelectionMode selected;\n        public int listIndex;                                       // Index into m_AnimationCurves list\n\n        private bool m_Changed;\n        public bool changed\n        {\n            get\n            {\n                return m_Changed;\n            }\n\n            set\n            {\n                m_Changed = value;\n\n                if (value && renderer != null)\n                    renderer.FlushCache();\n            }\n        }\n\n        public int AddKey(Keyframe key)\n        {\n            PreProcessKey(ref key);\n            return curve.AddKey(key);\n        }\n\n        public void PreProcessKey(ref Keyframe key)\n        {\n            if (preProcessKeyMovementDelegate != null)\n                preProcessKeyMovementDelegate(ref key);\n        }\n\n        public int MoveKey(int index, ref Keyframe key)\n        {\n            PreProcessKey(ref key);\n            return curve.MoveKey(index, key);\n        }\n\n        internal Bounds ComputeBoundsBetweenTime(float start, float end) => renderer.GetBounds(start, end);\n\n        // An additional vertical min / max range clamp when editing multiple curves with different ranges\n        public float vRangeMin = -Mathf.Infinity;\n        public float vRangeMax = Mathf.Infinity;\n\n        public bool useScalingInKeyEditor = false;\n        public string xAxisLabel = null;\n        public string yAxisLabel = null;\n    }\n\n    //  Control point collection renderer\n    class CurveControlPointRenderer\n    {\n        // Control point mesh renderers.\n        private ControlPointRenderer m_UnselectedPointRenderer;\n        private ControlPointRenderer m_SelectedPointRenderer;\n        private ControlPointRenderer m_SelectedPointOverlayRenderer;\n        private ControlPointRenderer m_SemiSelectedPointOverlayRenderer;\n        private ControlPointRenderer m_WeightedPointRenderer;\n\n        public CurveControlPointRenderer()\n        {\n            m_UnselectedPointRenderer = new ControlPointRenderer(CurveEditor.Styles.pointIcon);\n            m_SelectedPointRenderer = new ControlPointRenderer(CurveEditor.Styles.pointIconSelected);\n            m_SelectedPointOverlayRenderer = new ControlPointRenderer(CurveEditor.Styles.pointIconSelectedOverlay);\n            m_SemiSelectedPointOverlayRenderer = new ControlPointRenderer(CurveEditor.Styles.pointIconSemiSelectedOverlay);\n            m_WeightedPointRenderer = new ControlPointRenderer(CurveEditor.Styles.pointIconWeighted);\n        }\n\n        public void FlushCache()\n        {\n            m_UnselectedPointRenderer.FlushCache();\n            m_SelectedPointRenderer.FlushCache();\n            m_SelectedPointOverlayRenderer.FlushCache();\n            m_SemiSelectedPointOverlayRenderer.FlushCache();\n            m_WeightedPointRenderer.FlushCache();\n        }\n\n        public void Clear()\n        {\n            m_UnselectedPointRenderer.Clear();\n            m_SelectedPointRenderer.Clear();\n            m_SelectedPointOverlayRenderer.Clear();\n            m_SemiSelectedPointOverlayRenderer.Clear();\n            m_WeightedPointRenderer.Clear();\n        }\n\n        public void Render()\n        {\n            m_UnselectedPointRenderer.Render();\n            m_SelectedPointRenderer.Render();\n            m_SelectedPointOverlayRenderer.Render();\n            m_SemiSelectedPointOverlayRenderer.Render();\n            m_WeightedPointRenderer.Render();\n        }\n\n        public void AddPoint(Rect rect, Color color)\n        {\n            m_UnselectedPointRenderer.AddPoint(rect, color);\n        }\n\n        public void AddSelectedPoint(Rect rect, Color color)\n        {\n            m_SelectedPointRenderer.AddPoint(rect, color);\n            m_SelectedPointOverlayRenderer.AddPoint(rect, Color.white);\n        }\n\n        public void AddSemiSelectedPoint(Rect rect, Color color)\n        {\n            m_SelectedPointRenderer.AddPoint(rect, color);\n            m_SemiSelectedPointOverlayRenderer.AddPoint(rect, Color.white);\n        }\n\n        public void AddWeightedPoint(Rect rect, Color color)\n        {\n            m_WeightedPointRenderer.AddPoint(rect, color);\n        }\n    }\n\n    [System.Serializable]\n    internal class CurveEditor : TimeArea, CurveUpdater\n    {\n        CurveWrapper[] m_AnimationCurves;\n\n        static int s_SelectKeyHash = \"SelectKeys\".GetHashCode();\n        private static readonly string k_DeleteKeys = L10n.Tr(\"Delete Keys\");\n        private static readonly string k_DeleteKey = L10n.Tr(\"Delete Key\");\n        private static readonly string k_EditKeys = L10n.Tr(\"Edit Keys...\");\n        private static readonly string k_EditKey = L10n.Tr(\"Edit Key...\");\n        private static readonly string k_EditCurve = L10n.Tr(\"Edit Curve\");\n        private static readonly string k_AddKey = L10n.Tr(\"Add Key\");\n\n        public delegate void CallbackFunction();\n\n        public CallbackFunction curvesUpdated;\n\n        public CurveWrapper[] animationCurves\n        {\n            get\n            {\n                if (m_AnimationCurves == null)\n                    m_AnimationCurves = new CurveWrapper[0];\n\n                return m_AnimationCurves;\n            }\n            set\n            {\n                FlushCurvesCache();\n\n                m_AnimationCurves = value;\n\n                curveIDToIndexMap.Clear();\n                m_EnableCurveGroups = false;\n                for (int i = 0; i < m_AnimationCurves.Length; ++i)\n                {\n                    m_AnimationCurves[i].listIndex = i;\n\n                    if (!curveIDToIndexMap.ContainsKey(m_AnimationCurves[i].id))\n                    {\n                        curveIDToIndexMap.Add(m_AnimationCurves[i].id, i);\n                    }\n                    else\n                    {\n                        var binding = m_AnimationCurves[i].binding;\n                        Debug.LogWarning(\"Mismatching curve: '\" + (string.IsNullOrEmpty(binding.path) ? \"\" : binding.path + \" : \") + binding.propertyName + \"'\");\n                    }\n                    m_EnableCurveGroups = m_EnableCurveGroups || (m_AnimationCurves[i].groupId != -1);\n                }\n                SyncDrawOrder();\n                SyncSelection();\n                ValidateCurveList();\n            }\n        }\n\n        public bool GetTopMostCurveID(out int curveID)\n        {\n            if (m_DrawOrder.Count > 0)\n            {\n                curveID = m_DrawOrder[m_DrawOrder.Count - 1];\n                return true;\n            }\n\n            curveID = -1;\n            return false;\n        }\n\n        void FlushCurvesCache()\n        {\n            if (!settings.flushCurveCache)\n                return;\n\n            if (m_AnimationCurves == null)\n                return;\n\n            for (int i = 0; i < m_AnimationCurves.Length; ++i)\n            {\n                CurveWrapper curveWrapper = m_AnimationCurves[i];\n                if (curveWrapper.renderer != null)\n                    curveWrapper.renderer.FlushCache();\n            }\n        }\n\n        private List<int> m_DrawOrder = new List<int>(); // contains curveIds (last element topmost)\n        void SyncDrawOrder()\n        {\n            // Init\n            if (m_DrawOrder.Count == 0)\n            {\n                m_DrawOrder = m_AnimationCurves.Select(cw => cw.id).ToList();\n                return;\n            }\n\n            List<int> newDrawOrder = new List<int>(m_AnimationCurves.Length);\n            // First add known curveIds (same order as before)\n            for (int i = 0; i < m_DrawOrder.Count; ++i)\n            {\n                int curveID = m_DrawOrder[i];\n                for (int j = 0; j < m_AnimationCurves.Length; ++j)\n                {\n                    if (m_AnimationCurves[j].id == curveID)\n                    {\n                        newDrawOrder.Add(curveID);\n                        break;\n                    }\n                }\n            }\n            m_DrawOrder = newDrawOrder;\n\n            // Found them all\n            if (m_DrawOrder.Count == m_AnimationCurves.Length)\n                return;\n\n            // Add nonexisting curveIds (new curves are top most)\n            for (int i = 0; i < m_AnimationCurves.Length; ++i)\n            {\n                int curveID = m_AnimationCurves[i].id;\n                bool found = false;\n                for (int j = 0; j < m_DrawOrder.Count; ++j)\n                {\n                    if (m_DrawOrder[j] == curveID)\n                    {\n                        found = true;\n                        break;\n                    }\n                }\n                if (!found)\n                    m_DrawOrder.Add(curveID);\n            }\n\n            // Fallback if invalid setup with multiple curves with same curveID (see case 482048)\n            if (m_DrawOrder.Count != m_AnimationCurves.Length)\n            {\n                // Ordering can fail if we have a hierarchy like:\n                //\n                // Piston\n                //      Cylinder\n                //          InnerCyl\n                //      Cylinder\n                //          InnerCyl\n                // Since we cannot generate unique curve ids for identical paths like Cylinder and InnerCyl.\n                m_DrawOrder = m_AnimationCurves.Select(cw => cw.id).ToList();\n            }\n        }\n\n        public ICurveEditorState state;\n\n        public TimeArea.TimeFormat timeFormat\n        {\n            get\n            {\n                if (state != null)\n                    return state.timeFormat;\n\n                return TimeArea.TimeFormat.None;\n            }\n        }\n\n        public bool rippleTime\n        {\n            get\n            {\n                if (state != null)\n                    return state.rippleTime;\n\n                return false;\n            }\n        }\n\n        internal Bounds m_DefaultBounds = new Bounds(new Vector3(0.5f, 0.5f, 0), new Vector3(1, 1, 0));\n\n        private CurveEditorSettings m_Settings = new CurveEditorSettings();\n        public CurveEditorSettings settings { get { return m_Settings; } set { if (value != null) { m_Settings = value; ApplySettings(); } } }\n\n        protected void ApplySettings()\n        {\n            hRangeLocked = settings.hRangeLocked;\n            vRangeLocked = settings.vRangeLocked;\n            hRangeMin = settings.hRangeMin;\n            hRangeMax = settings.hRangeMax;\n            vRangeMin = settings.vRangeMin;\n            vRangeMax = settings.vRangeMax;\n            scaleWithWindow = settings.scaleWithWindow;\n            hSlider = settings.hSlider;\n            vSlider = settings.vSlider;\n\n            RecalculateBounds();\n        }\n\n        // Other style settings\n        private Color m_TangentColor = new Color(1, 1, 1, 0.5f);\n        private Color m_WeightedTangentColor = new Color(1, 1, 1, 1f);\n\n        /// 1/time to snap all keyframes to while dragging. Set to 0 for no snap (default)\n        public float invSnap = 0;\n\n        private CurveMenuManager m_MenuManager;\n\n        static int s_TangentControlIDHash = \"s_TangentControlIDHash\".GetHashCode();\n\n        [SerializeField] CurveEditorSelection m_Selection;\n\n        internal CurveEditorSelection selection\n        {\n            get\n            {\n                if (m_Selection == null)\n                {\n                    m_Selection = ScriptableObject.CreateInstance<CurveEditorSelection>();\n                    m_Selection.hideFlags = HideFlags.HideAndDontSave;\n                }\n\n                return m_Selection;\n            }\n        }\n\n        internal List<CurveSelection> selectedCurves\n        {\n            get\n            {\n                return selection.selectedCurves;\n            }\n            set\n            {\n                selection.selectedCurves = value;\n                InvalidateSelectionBounds();\n            }\n        }\n\n        List<CurveSelection> preCurveDragSelection = null;\n\n        public bool hasSelection { get { return selectedCurves.Count != 0; } }\n\n        bool m_InRangeSelection = false;\n\n        internal void BeginRangeSelection()\n        {\n            m_InRangeSelection = true;\n        }\n\n        internal void EndRangeSelection()\n        {\n            m_InRangeSelection = false;\n            selectedCurves.Sort();\n        }\n\n        internal void AddSelection(CurveSelection curveSelection)\n        {\n            selectedCurves.Add(curveSelection);\n\n            if (!m_InRangeSelection)\n                selectedCurves.Sort();\n\n            InvalidateSelectionBounds();\n        }\n\n        internal void RemoveSelection(CurveSelection curveSelection)\n        {\n            selectedCurves.Remove(curveSelection);\n            InvalidateSelectionBounds();\n        }\n\n        internal void ClearSelection()\n        {\n            selectedCurves.Clear();\n            InvalidateSelectionBounds();\n        }\n\n        internal CurveWrapper GetCurveWrapperFromID(int curveID)\n        {\n            if (m_AnimationCurves == null)\n                return null;\n\n            int index;\n            if (curveIDToIndexMap.TryGetValue(curveID, out index))\n                return m_AnimationCurves[index];\n\n            return null;\n        }\n\n        internal CurveWrapper GetCurveWrapperFromSelection(CurveSelection curveSelection)\n        {\n            return GetCurveWrapperFromID(curveSelection.curveID);\n        }\n\n        internal AnimationCurve GetCurveFromSelection(CurveSelection curveSelection)\n        {\n            CurveWrapper curveWrapper = GetCurveWrapperFromSelection(curveSelection);\n            return (curveWrapper != null) ? curveWrapper.curve : null;\n        }\n\n        internal Keyframe GetKeyframeFromSelection(CurveSelection curveSelection)\n        {\n            AnimationCurve curve = GetCurveFromSelection(curveSelection);\n            if (curve != null)\n            {\n                if (curveSelection.key >= 0 && curveSelection.key < curve.length)\n                {\n                    return curve[curveSelection.key];\n                }\n            }\n\n            return new Keyframe();\n        }\n\n        // Array of tangent points that have been revealed\n        CurveSelection m_SelectedTangentPoint;\n\n        // Selection tracking:\n        // What the selection was at the start of a drag\n        List<CurveSelection> s_SelectionBackup;\n        // Time range selection, is it active and what was the mousedown time (start) and the current end time.\n        float s_TimeRangeSelectionStart, s_TimeRangeSelectionEnd;\n        bool s_TimeRangeSelectionActive = false;\n\n        private bool m_BoundsAreDirty = true;\n        private bool m_SelectionBoundsAreDirty = true;\n        private bool m_SelectionWithCurvesBoundsAreDirty = true;\n\n        private bool m_EnableCurveGroups = false;\n\n        Bounds m_SelectionBounds = new Bounds(Vector3.zero, Vector3.zero);\n        public Bounds selectionBounds\n        {\n            get\n            {\n                RecalculateSelectionBounds();\n                return m_SelectionBounds;\n            }\n        }\n\n        Bounds m_SelectionWithCurvesBounds = new Bounds(Vector3.zero, Vector3.zero);\n        public Bounds selectionWithCurvesBounds\n        {\n            get\n            {\n                RecalculateSelectionWithCurvesBounds();\n                return m_SelectionWithCurvesBounds;\n            }\n        }\n\n        Bounds m_CurveBounds = new Bounds(Vector3.zero, Vector3.zero);\n        public Bounds curveBounds\n        {\n            get\n            {\n                RecalculateBounds();\n                return m_CurveBounds;\n            }\n        }\n\n        Bounds m_DrawingBounds = new Bounds(Vector3.zero, Vector3.zero);\n        public override Bounds drawingBounds\n        {\n            get\n            {\n                RecalculateBounds();\n                return m_DrawingBounds;\n            }\n        }\n\n        // Helpers for temporarily saving a bunch of keys.\n        class SavedCurve\n        {\n            public class SavedKeyFrame\n            {\n                public Keyframe key;\n                public CurveWrapper.SelectionMode selected;\n\n                public SavedKeyFrame(Keyframe key, CurveWrapper.SelectionMode selected)\n                {\n                    this.key = key;\n                    this.selected = selected;\n                }\n\n                public SavedKeyFrame Clone()\n                {\n                    SavedKeyFrame duplicate = new SavedKeyFrame(key, selected);\n                    return duplicate;\n                }\n            }\n\n            public class SavedKeyFrameComparer : IComparer<float>\n            {\n                public static SavedKeyFrameComparer Instance = new SavedKeyFrameComparer();\n\n                public int Compare(float time1, float time2)\n                {\n                    float cmp = time1 - time2;\n                    return cmp < -kCurveTimeEpsilon ? -1 : (cmp >= kCurveTimeEpsilon ? 1 : 0);\n                }\n            }\n\n\n            public int curveId;\n            public List<SavedKeyFrame> keys;\n\n            public delegate SavedKeyFrame KeyFrameOperation(SavedKeyFrame keyframe, SavedCurve curve);\n        }\n        List<SavedCurve> m_CurveBackups;\n\n        CurveWrapper m_DraggingKey = null;\n        Vector2 m_DraggedCoord;\n        Vector2 m_MoveCoord;\n\n        private enum AxisLock { None, X, Y }\n        private AxisLock m_AxisLock;\n\n        CurveControlPointRenderer m_PointRenderer;\n        CurveEditorRectangleTool m_RectangleTool;\n\n        // The square of the maximum pick distance in pixels.\n        // The mouse will select a key if it's within this distance from the key point.\n        const float kMaxPickDistSqr = 10 * 10;\n        const float kExactPickDistSqr = 4 * 4;\n\n        const float kCurveTimeEpsilon = 0.00001f;\n\n        public CurveEditor(Rect rect, CurveWrapper[] curves, bool minimalGUI) : base(minimalGUI)\n        {\n            this.rect = rect;\n            animationCurves = curves;\n\n            float[] modulos = new float[]\n            {\n                0.0000001f, 0.0000005f, 0.000001f, 0.000005f, 0.00001f, 0.00005f, 0.0001f, 0.0005f,\n                0.001f, 0.005f, 0.01f, 0.05f, 0.1f, 0.5f, 1, 5, 10, 50, 100, 500,\n                1000, 5000, 10000, 50000, 100000, 500000, 1000000, 5000000, 10000000\n            };\n            hTicks = new TickHandler();\n            hTicks.SetTickModulos(modulos);\n            vTicks = new TickHandler();\n            vTicks.SetTickModulos(modulos);\n            margin = 40.0f;\n\n            OnEnable();\n        }\n\n        public void OnEnable()\n        {\n            // Only add callback once.\n            Undo.undoRedoEvent -= UndoRedoPerformed;\n            Undo.undoRedoEvent += UndoRedoPerformed;\n        }\n\n        public void OnDisable()\n        {\n            Undo.undoRedoEvent -= UndoRedoPerformed;\n\n            if (m_PointRenderer != null)\n                m_PointRenderer.FlushCache();\n\n            FlushCurvesCache();\n        }\n\n        public void OnDestroy()\n        {\n            if (m_Selection != null)\n                ScriptableObject.DestroyImmediate(m_Selection);\n        }\n\n        void UndoRedoPerformed(in UndoRedoInfo info)\n        {\n            if (settings.undoRedoSelection)\n                InvalidateSelectionBounds();\n            else\n                SelectNone();\n        }\n\n        private void ValidateCurveList()\n        {\n            // Validate that regions are valid (they should consist of two curves after each other with same regionId)\n            for (int i = 0; i < m_AnimationCurves.Length; ++i)\n            {\n                CurveWrapper cw = m_AnimationCurves[i];\n                int regId1 = cw.regionId;\n                if (regId1 >= 0)\n                {\n                    if (i == m_AnimationCurves.Length - 1)\n                    {\n                        Debug.LogError(\"Region has only one curve last! Regions should be added as two curves after each other with same regionId\");\n                        return;\n                    }\n\n                    CurveWrapper cw2 = m_AnimationCurves[++i];\n                    int regId2 = cw2.regionId;\n                    if (regId1 != regId2)\n                    {\n                        Debug.LogError(\"Regions should be added as two curves after each other with same regionId: \" + regId1 + \" != \" + regId2);\n                        return;\n                    }\n                }\n            }\n\n            if (m_DrawOrder.Count != m_AnimationCurves.Length)\n            {\n                Debug.LogError(\"DrawOrder and AnimationCurves mismatch: DrawOrder \" + m_DrawOrder.Count + \", AnimationCurves: \" + m_AnimationCurves.Length);\n                return;\n            }\n\n            // Validate draw order regions\n            int numCurves = m_DrawOrder.Count;\n            for (int i = 0; i < numCurves; ++i)\n            {\n                int curveID = m_DrawOrder[i];\n                // If curve is part of a region then find other curve\n                int regionId = GetCurveWrapperFromID(curveID).regionId;\n                if (regionId >= 0)\n                {\n                    if (i == numCurves - 1)\n                    {\n                        Debug.LogError(\"Region has only one curve last! Regions should be added as two curves after each other with same regionId\");\n                        return;\n                    }\n\n                    // Ensure next curve has a matching regionId\n                    int curveId2 = m_DrawOrder[++i];\n                    int regionId2 = GetCurveWrapperFromID(curveId2).regionId;\n                    if (regionId != regionId2)\n                    {\n                        Debug.LogError(\"DrawOrder: Regions not added correctly after each other. RegionIds: \" + regionId + \" , \" + regionId2);\n                        return;\n                    }\n                }\n            }\n\n            // Debug.Log all curves and their state (outcomment if needed)\n            /*\n            string info = \"Count: \" + m_AnimationCurves.Length + \" (Click me for more info)\\n\";\n            foreach (CurveWrapper cw in m_AnimationCurves)\n                info += (\"Curve: id \" + cw.id + \", regionId \" + cw.regionId + \", hidden \" + cw.hidden + \"\\n\");\n            Debug.Log(info);\n            */\n        }\n\n        Dictionary<int, int> m_CurveIDToIndexMap;\n        private Dictionary<int, int> curveIDToIndexMap\n        {\n            get\n            {\n                if (m_CurveIDToIndexMap == null)\n                    m_CurveIDToIndexMap = new Dictionary<int, int>();\n\n                return m_CurveIDToIndexMap;\n            }\n        }\n\n        private void SyncSelection()\n        {\n            Init();\n\n            List<CurveSelection> newSelection = new List<CurveSelection>(selectedCurves.Count);\n\n            foreach (CurveSelection cs in selectedCurves)\n            {\n                CurveWrapper cw = GetCurveWrapperFromSelection(cs);\n                if (cw != null && (!cw.hidden || cw.groupId != -1))\n                {\n                    cw.selected = CurveWrapper.SelectionMode.Selected;\n                    newSelection.Add(cs);\n                }\n            }\n            if (newSelection.Count != selectedCurves.Count)\n            {\n                selectedCurves = newSelection;\n            }\n\n            InvalidateBounds();\n        }\n\n        public void InvalidateBounds()\n        {\n            m_BoundsAreDirty = true;\n        }\n\n        private void RecalculateBounds()\n        {\n            if (InLiveEdit())\n                return;\n\n            if (!m_BoundsAreDirty)\n                return;\n\n            const float kMinRange = 0.1F;\n\n            if (state != null)\n            {\n                m_CurveBounds.SetMinMax(new Vector3(state.timeRange.x, 0f, 0f), new Vector3(state.timeRange.y, 1f, 0f));\n                m_DrawingBounds = m_CurveBounds;\n            }\n            else\n            {\n                m_DrawingBounds = m_CurveBounds = m_DefaultBounds;\n            }\n\n            if (animationCurves != null)\n            {\n                bool assigned = false;\n                for (int i = 0; i < animationCurves.Length; ++i)\n                {\n                    CurveWrapper wrapper = animationCurves[i];\n\n                    if (wrapper.hidden)\n                        continue;\n\n                    if (wrapper.curve.length == 0)\n                        continue;\n\n                    if (!assigned)\n                    {\n                        m_CurveBounds = wrapper.bounds;\n                        assigned = true;\n                    }\n                    else\n                    {\n                        m_CurveBounds.Encapsulate(wrapper.bounds);\n                    }\n                }\n            }\n\n            //  Calculate bounds based on curve bounds if bound is not set by hRangeMin/hRangeMax vRangeMin/vRangeMax.\n            float minx = hRangeMin != Mathf.NegativeInfinity ? hRangeMin : m_CurveBounds.min.x;\n            float miny = vRangeMin != Mathf.NegativeInfinity ? vRangeMin : m_CurveBounds.min.y;\n            float maxx = hRangeMax != Mathf.Infinity ? hRangeMax : m_CurveBounds.max.x;\n            float maxy = vRangeMax != Mathf.Infinity ? vRangeMax : m_CurveBounds.max.y;\n\n            m_DrawingBounds.SetMinMax(new Vector3(minx, miny, m_CurveBounds.min.z), new Vector3(maxx, maxy, m_CurveBounds.max.z));\n\n            // Enforce minimum size of bounds\n            m_DrawingBounds.size = new Vector3(Mathf.Max(m_DrawingBounds.size.x, kMinRange), Mathf.Max(m_DrawingBounds.size.y, kMinRange), 0);\n            m_CurveBounds.size = new Vector3(Mathf.Max(m_CurveBounds.size.x, kMinRange), Mathf.Max(m_CurveBounds.size.y, kMinRange), 0);\n\n            m_BoundsAreDirty = false;\n        }\n\n        public void InvalidateSelectionBounds()\n        {\n            m_SelectionBoundsAreDirty = true;\n            m_SelectionWithCurvesBoundsAreDirty = true;\n        }\n\n        private void RecalculateSelectionBounds()\n        {\n            if (!m_SelectionBoundsAreDirty)\n                return;\n\n            if (hasSelection)\n            {\n                List<CurveSelection> selected = selectedCurves;\n\n                Keyframe keyframe = GetKeyframeFromSelection(selected[0]);\n                m_SelectionBounds = new Bounds(new Vector2(keyframe.time, keyframe.value), Vector2.zero);\n\n                for (int i = 1; i < selected.Count; ++i)\n                {\n                    keyframe = GetKeyframeFromSelection(selected[i]);\n                    m_SelectionBounds.Encapsulate(new Vector2(keyframe.time, keyframe.value));\n                }\n            }\n            else\n            {\n                m_SelectionBounds = new Bounds(Vector3.zero, Vector3.zero);\n            }\n\n            m_SelectionBoundsAreDirty = false;\n        }\n\n        private void RecalculateSelectionWithCurvesBounds()\n        {\n            if (!m_SelectionWithCurvesBoundsAreDirty)\n                return;\n\n            m_SelectionWithCurvesBounds = m_SelectionBounds;\n\n            //Aggregate selected key in between curves.\n            if (hasSelection)\n            {\n                CurveSelection[] selected = selectedCurves.OrderBy(p => p.curveID).ThenBy(p => p.key).ToArray();\n                int currentCurveId = selected.First().curveID;\n                CurveWrapper currentCurveWrapper = GetCurveWrapperFromID(currentCurveId);\n                for (int i = 0; i < selected.Length - 1; i++)\n                {\n                    if (currentCurveId != selected[i + 1].curveID)\n                    {\n                        currentCurveId = selected[i + 1].curveID;\n                        currentCurveWrapper = GetCurveWrapperFromID(currentCurveId);\n                        continue;\n                    }\n                    Keyframe keyframeStart = GetKeyframeFromSelection(selected[i]);\n                    Keyframe keyframeEnd = GetKeyframeFromSelection(selected[i + 1]);\n                    Bounds inBetweenBounds = currentCurveWrapper.ComputeBoundsBetweenTime(keyframeStart.time, keyframeEnd.time);\n                    m_SelectionWithCurvesBounds.Encapsulate(inBetweenBounds);\n                }\n            }\n\n            m_SelectionWithCurvesBoundsAreDirty = false;\n        }\n\n        public Bounds GetClipBounds()\n        {\n            return curveBounds;\n        }\n\n        public Bounds GetSelectionBounds()\n        {\n            if (!hasSelection)\n                return GetClipBounds();\n\n            Bounds frameBounds;\n\n            // Add neighboring keys in bounds if only a single key is selected.\n            if (selectedCurves.Count == 1)\n            {\n                CurveSelection cs = selectedCurves[0];\n                CurveWrapper cw = GetCurveWrapperFromSelection(cs);\n\n                // Encapsulate key in bounds\n                frameBounds = new Bounds(new Vector2(cw.curve[cs.key].time, cw.curve[cs.key].value), Vector2.zero);\n\n                // Include neighboring keys in bounds\n                if (cs.key - 1 >= 0)\n                    frameBounds.Encapsulate(new Vector2(cw.curve[cs.key - 1].time, cw.curve[cs.key - 1].value));\n                if (cs.key + 1 < cw.curve.length)\n                    frameBounds.Encapsulate(new Vector2(cw.curve[cs.key + 1].time, cw.curve[cs.key + 1].value));\n\n                //Include neighboring curves in bounds\n                if (cs.key - 1 >= 0)\n                    frameBounds.Encapsulate(cw.ComputeBoundsBetweenTime(cw.curve[cs.key - 1].time, cw.curve[cs.key].time));\n                if (cs.key + 1 < cw.curve.length)\n                    frameBounds.Encapsulate(cw.ComputeBoundsBetweenTime(cw.curve[cs.key].time, cw.curve[cs.key + 1].time));\n            }\n            else\n            {\n                frameBounds = selectionWithCurvesBounds;\n            }\n\n            // Enforce minimum size of bounds\n            frameBounds.size = new Vector3(Mathf.Max(frameBounds.size.x, 0.1F), Mathf.Max(frameBounds.size.y, 0.1F), 0);\n\n            return frameBounds;\n        }\n\n        // Frame all curves to be visible.\n        public void FrameClip(bool horizontally, bool vertically)\n        {\n            Frame(GetClipBounds(), horizontally, vertically);\n        }\n\n        // Frame selected keys to be visible.\n        public void FrameSelected(bool horizontally, bool vertically)\n        {\n            Frame(GetSelectionBounds(), horizontally, vertically);\n        }\n\n        public void Frame(Bounds frameBounds, bool horizontally, bool vertically)\n        {\n            if (frameBounds.size == Vector3.zero)\n                return;\n\n            if (horizontally)\n                SetShownHRangeInsideMargins(frameBounds.min.x, frameBounds.max.x);\n            if (vertically)\n                SetShownVRangeInsideMargins(frameBounds.min.y, frameBounds.max.y);\n        }\n\n        public void UpdateCurves(List<int> curveIds, string undoText)\n        {\n            foreach (int id in curveIds)\n            {\n                CurveWrapper cw = GetCurveWrapperFromID(id);\n                cw.changed = true;\n            }\n            if (curvesUpdated != null)\n                curvesUpdated();\n        }\n\n        public void UpdateCurves(List<ChangedCurve> changedCurves, string undoText)\n        {\n            UpdateCurves(new List<int>(changedCurves.Select(curve => curve.curveId)), undoText);\n        }\n\n        public void StartLiveEdit()\n        {\n            MakeCurveBackups();\n        }\n\n        public void EndLiveEdit()\n        {\n            m_CurveBackups = null;\n        }\n\n        public bool InLiveEdit()\n        {\n            return m_CurveBackups != null;\n        }\n\n        void Init()\n        {\n        }\n\n        public void OnGUI()\n        {\n            BeginViewGUI();\n            GridGUI();\n            DrawWrapperPopups();\n            CurveGUI();\n            EndViewGUI();\n        }\n\n        public void CurveGUI()\n        {\n            if (m_PointRenderer == null)\n                m_PointRenderer = new CurveControlPointRenderer();\n\n            if (m_RectangleTool == null)\n            {\n                m_RectangleTool = new CurveEditorRectangleTool();\n                m_RectangleTool.Initialize(this);\n            }\n\n            GUI.BeginGroup(drawRect);\n\n            Init();\n            GUIUtility.GetControlID(s_SelectKeyHash, FocusType.Passive);\n            GUI.contentColor = GUI.backgroundColor = Color.white;\n\n            Color oldColor = GUI.color;\n\n            Event evt = Event.current;\n\n            //Because this uses a keyboard input field, it must be allowed to handle events first\n            if (evt.type != EventType.Repaint)\n            {\n                EditSelectedPoints();\n            }\n\n            switch (evt.type)\n            {\n                case EventType.ValidateCommand:\n                case EventType.ExecuteCommand:\n                    bool execute = evt.type == EventType.ExecuteCommand;\n                    switch (evt.commandName)\n                    {\n                        case EventCommandNames.Delete:\n                            if (hasSelection)\n                            {\n                                if (execute)\n                                {\n                                    DeleteSelectedKeys();\n                                }\n                                evt.Use();\n                            }\n                            break;\n                        case EventCommandNames.FrameSelected:\n                            if (execute)\n                                FrameSelected(true, true);\n                            evt.Use();\n                            break;\n                        case EventCommandNames.SelectAll:\n                            if (execute)\n                                SelectAll();\n                            evt.Use();\n                            break;\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if ((evt.keyCode == KeyCode.Backspace || evt.keyCode == KeyCode.Delete) && hasSelection)\n                    {\n                        DeleteSelectedKeys();\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.ContextClick:\n                    CurveSelection mouseKey = FindNearest();\n                    if (mouseKey != null)\n                    {\n                        List<KeyIdentifier> keyList = new List<KeyIdentifier>();\n\n                        // Find out if key under mouse is part of selected keys\n                        bool inSelected = false;\n                        foreach (CurveSelection sel in selectedCurves)\n                        {\n                            keyList.Add(new KeyIdentifier(GetCurveFromSelection(sel), sel.curveID, sel.key));\n                            if (sel.curveID == mouseKey.curveID && sel.key == mouseKey.key)\n                                inSelected = true;\n                        }\n                        if (!inSelected)\n                        {\n                            keyList.Clear();\n                            keyList.Add(new KeyIdentifier(GetCurveFromSelection(mouseKey), mouseKey.curveID, mouseKey.key));\n                            ClearSelection();\n                            AddSelection(mouseKey);\n                        }\n\n                        bool isEditable = !selectedCurves.Exists(sel => !GetCurveWrapperFromSelection(sel).animationIsEditable);\n\n                        m_MenuManager = new CurveMenuManager(this);\n                        GenericMenu menu = new GenericMenu();\n\n                        string deleteKeyLabel = keyList.Count > 1 ? k_DeleteKeys : k_DeleteKey;\n                        string editKeyLabel = keyList.Count > 1 ? k_EditKeys : k_EditKey;\n\n                        if (isEditable)\n                        {\n                            menu.AddItem(new GUIContent(deleteKeyLabel), false, DeleteKeys, keyList);\n                            menu.AddItem(new GUIContent(editKeyLabel), false, StartEditingSelectedPointsContext, mousePositionInDrawing);\n                        }\n                        else\n                        {\n                            menu.AddDisabledItem(new GUIContent(deleteKeyLabel));\n                            menu.AddDisabledItem(new GUIContent(editKeyLabel));\n                        }\n\n                        if (isEditable)\n                        {\n                            menu.AddSeparator(\"\");\n                            m_MenuManager.AddTangentMenuItems(menu, keyList);\n                        }\n\n                        menu.ShowAsContext();\n                        Event.current.Use();\n                    }\n                    break;\n            }\n\n            GUI.color = oldColor;\n\n            m_RectangleTool.HandleOverlayEvents();\n\n            DragTangents();\n\n            m_RectangleTool.HandleEvents();\n\n            EditAxisLabels();\n            SelectPoints();\n\n            EditorGUI.BeginChangeCheck();\n            Vector2 move = MovePoints();\n            if (EditorGUI.EndChangeCheck() && m_DraggingKey != null)\n            {\n                m_MoveCoord = move;\n            }\n\n            if (evt.type == EventType.Repaint)\n            {\n                DrawCurves();\n\n                m_RectangleTool.OnGUI();\n\n                DrawCurvesTangents();\n                DrawCurvesOverlay();\n\n                m_RectangleTool.OverlayOnGUI(rect);\n\n                EditSelectedPoints();\n            }\n\n            GUI.color = oldColor;\n\n            GUI.EndGroup();\n        }\n\n        // Recalculate curve.selected from selected curves\n        void RecalcCurveSelection()\n        {\n            // Reset selection state of all curves\n            foreach (CurveWrapper cw in m_AnimationCurves)\n                cw.selected = CurveWrapper.SelectionMode.None;\n\n            // Now sync with selected curves\n            foreach (CurveSelection cs in selectedCurves)\n            {\n                CurveWrapper cw = GetCurveWrapperFromSelection(cs);\n                if (cw != null)\n                    cw.selected = cs.semiSelected ? CurveWrapper.SelectionMode.SemiSelected : CurveWrapper.SelectionMode.Selected;\n            }\n        }\n\n        void RecalcSecondarySelection()\n        {\n            // No need to recalculate secondary selection if there are no curves with a valid groupId.\n            if (!m_EnableCurveGroups)\n                return;\n\n            // The new list of secondary selections\n            List<CurveSelection> newSelection = new List<CurveSelection>(selectedCurves.Count);\n\n            // Go through selection, find curveselections that need syncing, add those for the sync points.\n            foreach (CurveSelection cs in selectedCurves)\n            {\n                CurveWrapper cw = GetCurveWrapperFromSelection(cs);\n                if (cw == null)\n                    continue;\n\n                int groupId = cw.groupId;\n                if (groupId != -1 && !cs.semiSelected)\n                {\n                    newSelection.Add(cs);\n                    foreach (CurveWrapper cw2 in m_AnimationCurves)\n                    {\n                        if (cw2.groupId == groupId && cw2 != cw)\n                        {\n                            CurveSelection newCS = new CurveSelection(cw2.id, cs.key);\n                            newCS.semiSelected = true;\n                            newSelection.Add(newCS);\n                        }\n                    }\n                }\n                else\n                {\n                    newSelection.Add(cs);\n                }\n            }\n            newSelection.Sort();\n\n            // the selection can contain duplicate keys. We go through the selection and remove any duplicates we find.\n            // Since the selection is already sorted, the duplicates are next to each other.\n            for (int i = 0; i < newSelection.Count - 1;)\n            {\n                CurveSelection cs1 = newSelection[i];\n                CurveSelection cs2 = newSelection[i + 1];\n                if (cs1.curveID == cs2.curveID && cs1.key == cs2.key)\n                {\n                    // If we have a collision, one can be fully selected, while the other can be semiselected. Make sure we always get the most selected one.\n                    if (!cs1.semiSelected || !cs2.semiSelected)\n                        cs1.semiSelected = false;\n                    newSelection.RemoveAt(i + 1);\n                }\n                else\n                {\n                    i++;\n                }\n            }\n\n            // Assign back\n            selectedCurves = newSelection;\n        }\n\n        void DragTangents()\n        {\n            Event evt = Event.current;\n            int tangentId = GUIUtility.GetControlID(s_TangentControlIDHash, FocusType.Passive);\n            switch (evt.GetTypeForControl(tangentId))\n            {\n                case EventType.MouseDown:\n                    if (evt.button == 0 && !evt.alt)\n                    {\n                        m_SelectedTangentPoint = null;\n                        float nearestDist = kMaxPickDistSqr;\n                        Vector2 mousePos = Event.current.mousePosition;\n                        foreach (CurveSelection cs in selectedCurves)\n                        {\n                            AnimationCurve curve = GetCurveFromSelection(cs);\n                            if (curve == null)\n                                continue;\n\n                            if (cs.key < 0 || cs.key >= curve.length)\n                                continue;\n\n                            if (IsLeftTangentEditable(cs))\n                            {\n                                CurveSelection tangent = new CurveSelection(cs.curveID, cs.key, CurveSelection.SelectionType.InTangent);\n                                float d = (DrawingToViewTransformPoint(GetPosition(tangent)) - mousePos).sqrMagnitude;\n                                if (d <= nearestDist)\n                                {\n                                    m_SelectedTangentPoint = tangent;\n                                    nearestDist = d;\n                                }\n                            }\n\n                            if (IsRightTangentEditable(cs))\n                            {\n                                CurveSelection tangent = new CurveSelection(cs.curveID, cs.key, CurveSelection.SelectionType.OutTangent);\n                                float d = (DrawingToViewTransformPoint(GetPosition(tangent)) - mousePos).sqrMagnitude;\n                                if (d <= nearestDist)\n                                {\n                                    m_SelectedTangentPoint = tangent;\n                                    nearestDist = d;\n                                }\n                            }\n                        }\n\n                        if (m_SelectedTangentPoint != null)\n                        {\n                            SaveKeySelection(k_EditCurve);\n\n                            GUIUtility.hotControl = tangentId;\n                            evt.Use();\n                        }\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == tangentId)\n                    {\n                        CurveSelection dragged = m_SelectedTangentPoint;\n                        CurveWrapper curveWrapper = GetCurveWrapperFromSelection(dragged);\n\n                        if ((curveWrapper != null) && curveWrapper.animationIsEditable)\n                        {\n                            Vector2 newPosition = mousePositionInDrawing;\n                            Keyframe key = curveWrapper.curve[dragged.key];\n\n                            if (dragged.type == CurveSelection.SelectionType.InTangent)\n                            {\n                                Keyframe prevKey = curveWrapper.curve[dragged.key - 1];\n                                float dx = key.time - prevKey.time;\n\n                                Vector2 tangentDirection = newPosition - new Vector2(key.time, key.value);\n                                if (tangentDirection.x < -0.0001F)\n                                {\n                                    key.inTangent = tangentDirection.y / tangentDirection.x;\n                                    key.inWeight = Mathf.Clamp(Mathf.Abs(tangentDirection.x / dx), 0f, 1f);\n                                }\n                                else if (tangentDirection.y > 0)\n                                {\n                                    key.inTangent = Mathf.Infinity;\n                                    key.inWeight = 0f;\n                                }\n                                else\n                                {\n                                    key.inTangent = -Mathf.Infinity;\n                                    key.inWeight = 0f;\n                                }\n                                AnimationUtility.SetKeyLeftTangentMode(ref key, TangentMode.Free);\n\n                                if (!AnimationUtility.GetKeyBroken(key))\n                                {\n                                    key.outTangent = key.inTangent;\n                                    AnimationUtility.SetKeyRightTangentMode(ref key, TangentMode.Free);\n                                }\n                            }\n                            else if (dragged.type == CurveSelection.SelectionType.OutTangent)\n                            {\n                                Keyframe nextKey = curveWrapper.curve[dragged.key + 1];\n                                float dx = nextKey.time - key.time;\n\n                                Vector2 tangentDirection = newPosition - new Vector2(key.time, key.value);\n                                if (tangentDirection.x > 0.0001F)\n                                {\n                                    key.outTangent = tangentDirection.y / tangentDirection.x;\n                                    key.outWeight = Mathf.Clamp(Mathf.Abs(tangentDirection.x / dx), 0f, 1f);\n                                }\n                                else if (tangentDirection.y > 0)\n                                {\n                                    key.outTangent = Mathf.Infinity;\n                                    key.outWeight = 0f;\n                                }\n                                else\n                                {\n                                    key.outTangent = -Mathf.Infinity;\n                                    key.outWeight = 0f;\n                                }\n                                AnimationUtility.SetKeyRightTangentMode(ref key, TangentMode.Free);\n\n                                if (!AnimationUtility.GetKeyBroken(key))\n                                {\n                                    key.inTangent = key.outTangent;\n                                    AnimationUtility.SetKeyLeftTangentMode(ref key, TangentMode.Free);\n                                }\n                            }\n\n                            dragged.key = curveWrapper.MoveKey(dragged.key, ref key);\n                            AnimationUtility.UpdateTangentsFromModeSurrounding(curveWrapper.curve, dragged.key);\n\n                            curveWrapper.changed = true;\n                            GUI.changed = true;\n                        }\n                        Event.current.Use();\n                    }\n\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == tangentId)\n                    {\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.Repaint:\n                    if (GUIUtility.hotControl == tangentId)\n                    {\n                        Rect mouseRect = new Rect(evt.mousePosition.x - 10, evt.mousePosition.y - 10, 20, 20);\n                        EditorGUIUtility.AddCursorRect(mouseRect, MouseCursor.MoveArrow);\n                    }\n                    break;\n            }\n        }\n\n        internal void DeleteSelectedKeys()\n        {\n            string undoLabel;\n            if (selectedCurves.Count > 1)\n                undoLabel = k_DeleteKeys;\n            else\n                undoLabel = k_DeleteKey;\n\n            SaveKeySelection(undoLabel);\n\n            // Go over selection backwards and delete (avoids wrecking indices)\n            for (int i = selectedCurves.Count - 1; i >= 0; i--)\n            {\n                CurveSelection k = selectedCurves[i];\n                CurveWrapper cw = GetCurveWrapperFromSelection(k);\n                if (cw == null)\n                    continue;\n\n                if (!cw.animationIsEditable)\n                    continue;\n\n                if (!settings.allowDeleteLastKeyInCurve)\n                    if (cw.curve.length == 1)\n                        continue;\n\n                cw.curve.RemoveKey(k.key);\n                AnimationUtility.UpdateTangentsFromMode(cw.curve);\n                cw.changed = true;\n                GUI.changed = true;\n            }\n            SelectNone();\n\n            GUIUtility.hotControl = 0;\n        }\n\n        private void DeleteKeys(object obj)\n        {\n            List<KeyIdentifier> keyList = (List<KeyIdentifier>)obj;\n\n            string undoLabel;\n            if (keyList.Count > 1)\n                undoLabel = k_DeleteKeys;\n            else\n                undoLabel = k_DeleteKey;\n\n            SaveKeySelection(undoLabel);\n\n            // Go over selection backwards and delete (avoids wrecking indices)\n            List<int> curveIds = new List<int>();\n            for (int i = keyList.Count - 1; i >= 0; i--)\n            {\n                if (!settings.allowDeleteLastKeyInCurve)\n                    if (keyList[i].curve.length == 1)\n                        continue;\n\n                if (!GetCurveWrapperFromID(keyList[i].curveId).animationIsEditable)\n                    continue;\n\n                keyList[i].curve.RemoveKey(keyList[i].key);\n                AnimationUtility.UpdateTangentsFromMode(keyList[i].curve);\n                curveIds.Add(keyList[i].curveId);\n            }\n\n            UpdateCurves(curveIds, undoLabel);\n            SelectNone();\n        }\n\n        float ClampVerticalValue(float value, int curveID)\n        {\n            // Clamp by global value\n            value = Mathf.Clamp(value, vRangeMin, vRangeMax);\n\n            // Clamp with per curve settings.\n            CurveWrapper cw = GetCurveWrapperFromID(curveID);\n            if (cw != null)\n                value = Mathf.Clamp(value, cw.vRangeMin, cw.vRangeMax);\n\n            return value;\n        }\n\n        internal void TranslateSelectedKeys(Vector2 movement)\n        {\n            bool inLiveEdit = InLiveEdit();\n            if (!inLiveEdit)\n                StartLiveEdit();\n\n            UpdateCurvesFromPoints(\n                delegate(SavedCurve.SavedKeyFrame keyframe, SavedCurve curve)\n                {\n                    if (keyframe.selected != CurveWrapper.SelectionMode.None)\n                    {\n                        // Duplicate it - so we don't modify the backup copy\n                        var duplicateKeyframe = keyframe.Clone();\n\n                        // Slide in time.  Clamp key.\n                        duplicateKeyframe.key.time = Mathf.Clamp(duplicateKeyframe.key.time + movement.x, hRangeMin, hRangeMax);\n\n                        // if it's fully selected, also move on Y\n                        if (duplicateKeyframe.selected == CurveWrapper.SelectionMode.Selected)\n                            duplicateKeyframe.key.value = ClampVerticalValue(duplicateKeyframe.key.value + movement.y, curve.curveId);\n\n                        return duplicateKeyframe;\n                    }\n\n                    return keyframe;\n                }\n            );\n\n            if (!inLiveEdit)\n                EndLiveEdit();\n        }\n\n        internal void SetSelectedKeyPositions(float newTime, float newValue, bool updateTime, bool updateValue)\n        {\n            if (!updateTime && !updateValue)\n                return;\n\n            bool inLiveEdit = InLiveEdit();\n            if (!inLiveEdit)\n                StartLiveEdit();\n\n            UpdateCurvesFromPoints(\n                delegate(SavedCurve.SavedKeyFrame keyframe, SavedCurve curve)\n                {\n                    if (keyframe.selected != CurveWrapper.SelectionMode.None)\n                    {\n                        // Duplicate it - so we don't modify the backup copy\n                        var duplicateKeyframe = keyframe.Clone();\n\n                        if (updateTime)\n                        {\n                            duplicateKeyframe.key.time = Mathf.Clamp(newTime, hRangeMin, hRangeMax);\n                        }\n                        if (updateValue)\n                        {\n                            duplicateKeyframe.key.value = ClampVerticalValue(newValue, curve.curveId);\n                        }\n\n                        return duplicateKeyframe;\n                    }\n\n                    return keyframe;\n                }\n            );\n\n            if (!inLiveEdit)\n                EndLiveEdit();\n        }\n\n        internal void TransformSelectedKeys(Matrix4x4 matrix, bool flipX, bool flipY)\n        {\n            bool inLiveEdit = InLiveEdit();\n            if (!inLiveEdit)\n                StartLiveEdit();\n\n            UpdateCurvesFromPoints(\n\n                delegate(SavedCurve.SavedKeyFrame keyframe, SavedCurve curve)\n                {\n                    if (keyframe.selected != CurveWrapper.SelectionMode.None)\n                    {\n                        // Duplicate it - so we don't modify the backup copy\n                        var duplicateKeyframe = keyframe.Clone();\n\n                        Vector3 v = new Vector3(duplicateKeyframe.key.time, duplicateKeyframe.key.value, 0f);\n                        v = matrix.MultiplyPoint3x4(v);\n\n                        v.x = SnapTime(v.x);\n\n                        duplicateKeyframe.key.time = Mathf.Clamp(v.x, hRangeMin, hRangeMax);\n\n                        if (flipX)\n                        {\n                            duplicateKeyframe.key.inTangent = (keyframe.key.outTangent != Mathf.Infinity) ? -keyframe.key.outTangent : Mathf.Infinity;\n                            duplicateKeyframe.key.outTangent = (keyframe.key.inTangent != Mathf.Infinity) ? -keyframe.key.inTangent : Mathf.Infinity;\n\n                            if (keyframe.key.weightedMode == WeightedMode.In)\n                                duplicateKeyframe.key.weightedMode = WeightedMode.Out;\n                            else if (keyframe.key.weightedMode == WeightedMode.Out)\n                                duplicateKeyframe.key.weightedMode = WeightedMode.In;\n                            else\n                                duplicateKeyframe.key.weightedMode = keyframe.key.weightedMode;\n\n                            duplicateKeyframe.key.inWeight = keyframe.key.outWeight;\n                            duplicateKeyframe.key.outWeight = keyframe.key.inWeight;\n                        }\n\n                        // if it's fully selected, also move on Y\n                        if (duplicateKeyframe.selected == CurveWrapper.SelectionMode.Selected)\n                        {\n                            duplicateKeyframe.key.value = ClampVerticalValue(v.y, curve.curveId);\n\n                            if (flipY)\n                            {\n                                duplicateKeyframe.key.inTangent = (duplicateKeyframe.key.inTangent != Mathf.Infinity) ? -duplicateKeyframe.key.inTangent : Mathf.Infinity;\n                                duplicateKeyframe.key.outTangent = (duplicateKeyframe.key.outTangent != Mathf.Infinity) ? -duplicateKeyframe.key.outTangent : Mathf.Infinity;\n                            }\n                        }\n\n                        return duplicateKeyframe;\n                    }\n                    return keyframe;\n                }\n            );\n\n            if (!inLiveEdit)\n                EndLiveEdit();\n        }\n\n        internal void TransformRippleKeys(Matrix4x4 matrix, float t1, float t2, bool flipX, bool flipY)\n        {\n            bool inLiveEdit = InLiveEdit();\n            if (!inLiveEdit)\n                StartLiveEdit();\n\n            UpdateCurvesFromPoints(\n\n                delegate(SavedCurve.SavedKeyFrame keyframe, SavedCurve curve)\n                {\n                    float newTime = keyframe.key.time;\n\n                    if (keyframe.selected != CurveWrapper.SelectionMode.None)\n                    {\n                        Vector3 v = new Vector3(keyframe.key.time, keyframe.key.value, 0f);\n                        v = matrix.MultiplyPoint3x4(v);\n\n                        newTime = v.x;\n\n                        // Duplicate it - so we don't modify the backup copy\n                        var duplicateKeyframe = keyframe.Clone();\n\n                        duplicateKeyframe.key.time = SnapTime(Mathf.Clamp(newTime, hRangeMin, hRangeMax));\n\n                        if (flipX)\n                        {\n                            duplicateKeyframe.key.inTangent = (keyframe.key.outTangent != Mathf.Infinity) ? -keyframe.key.outTangent : Mathf.Infinity;\n                            duplicateKeyframe.key.outTangent = (keyframe.key.inTangent != Mathf.Infinity) ? -keyframe.key.inTangent : Mathf.Infinity;\n                        }\n\n                        // if it's fully selected, also move on Y\n                        if (duplicateKeyframe.selected == CurveWrapper.SelectionMode.Selected)\n                        {\n                            duplicateKeyframe.key.value = ClampVerticalValue(v.y, curve.curveId);\n\n                            if (flipY)\n                            {\n                                duplicateKeyframe.key.inTangent = (duplicateKeyframe.key.inTangent != Mathf.Infinity) ? -duplicateKeyframe.key.inTangent : Mathf.Infinity;\n                                duplicateKeyframe.key.outTangent = (duplicateKeyframe.key.outTangent != Mathf.Infinity) ? -duplicateKeyframe.key.outTangent : Mathf.Infinity;\n                            }\n                        }\n\n                        return duplicateKeyframe;\n                    }\n                    else\n                    {\n                        if (keyframe.key.time > t2)\n                        {\n                            Vector3 v = new Vector3(flipX ? t1 : t2, 0f, 0f);\n                            v = matrix.MultiplyPoint3x4(v);\n\n                            float dt = v.x - t2;\n                            if (dt > 0f)\n                                newTime = keyframe.key.time + dt;\n                        }\n                        else if (keyframe.key.time < t1)\n                        {\n                            Vector3 v = new Vector3(flipX ? t2 : t1, 0f, 0f);\n                            v = matrix.MultiplyPoint3x4(v);\n\n                            float dt = v.x - t1;\n                            if (dt < 0f)\n                                newTime = keyframe.key.time + dt;\n                        }\n\n                        if (!Mathf.Approximately(newTime, keyframe.key.time))\n                        {\n                            // Duplicate it - so we don't modify the backup copy\n                            var duplicateKeyframe = keyframe.Clone();\n                            duplicateKeyframe.key.time = SnapTime(Mathf.Clamp(newTime, hRangeMin, hRangeMax));\n                            return duplicateKeyframe;\n                        }\n                    }\n\n                    return keyframe;\n                }\n            );\n\n            if (!inLiveEdit)\n                EndLiveEdit();\n        }\n\n        void UpdateCurvesFromPoints(SavedCurve.KeyFrameOperation action)\n        {\n            if (m_CurveBackups == null)\n                return;\n\n            // Starting up:\n            var dragSelection = new List<CurveSelection>();\n            // Go over all saved curves - each of these has at least one selected point.\n            foreach (SavedCurve sc in m_CurveBackups)\n            {\n                CurveWrapper cw = GetCurveWrapperFromID(sc.curveId);\n                if (!cw.animationIsEditable)\n                    continue;\n\n                // Go through each curve and build a new working set of points.\n                var working = new SortedList<float, SavedCurve.SavedKeyFrame>(SavedCurve.SavedKeyFrameComparer.Instance);\n\n                //  Add all unselected key frames to the working collection first.\n                foreach (SavedCurve.SavedKeyFrame keyframe in sc.keys)\n                {\n                    if (keyframe.selected == CurveWrapper.SelectionMode.None)\n                    {\n                        var newKeyframe = action(keyframe, sc);\n                        cw.PreProcessKey(ref newKeyframe.key);\n\n                        // We might have moved keys around, let's add new key or replace existing key.\n                        working[newKeyframe.key.time] = newKeyframe;\n                    }\n                }\n\n                //  Add all modified key frames to the working collection and remove duplicates.\n                foreach (SavedCurve.SavedKeyFrame keyframe in sc.keys)\n                {\n                    if (keyframe.selected != CurveWrapper.SelectionMode.None)\n                    {\n                        var newKeyframe = action(keyframe, sc);\n                        cw.PreProcessKey(ref newKeyframe.key);\n                        // We might have moved keys around, let's add new key or replace existing key.\n                        working[newKeyframe.key.time] = newKeyframe;\n                    }\n                }\n\n                // Working now contains a set of points with everything set up correctly.\n                // Each point has it's selection set, but m_DisplayCurves has a more traditional key array.\n                // Go through the working points and sort those for display.\n                int idx = 0;\n                Keyframe[] keysToAssign = new Keyframe[working.Count];\n                foreach (KeyValuePair<float, SavedCurve.SavedKeyFrame> kvp in working)\n                {\n                    SavedCurve.SavedKeyFrame sk = kvp.Value;\n                    keysToAssign[idx] = sk.key;\n                    if (sk.selected != CurveWrapper.SelectionMode.None)\n                    {\n                        CurveSelection cs = new CurveSelection(sc.curveId, idx);\n                        if (sk.selected == CurveWrapper.SelectionMode.SemiSelected)\n                            cs.semiSelected = true;\n                        dragSelection.Add(cs);\n                    }\n\n                    ++idx;\n                }\n\n                // We now have the list of keys to assign - let's get them back into the animation clip\n                cw.curve.keys = keysToAssign;\n                AnimationUtility.UpdateTangentsFromMode(cw.curve);\n                cw.changed = true;\n            }\n\n            selectedCurves = dragSelection;\n        }\n\n        float SnapTime(float t)\n        {\n            if (EditorGUI.actionKey)\n            {\n                int snapLevel = hTicks.GetLevelWithMinSeparation(5);\n                float snap = hTicks.GetPeriodOfLevel(snapLevel);\n                t = Mathf.Round(t / snap) * snap;\n            }\n            else\n            {\n                if (invSnap != 0.0f)\n                    t = Mathf.Round(t * invSnap) / invSnap;\n            }\n            return t;\n        }\n\n        float SnapValue(float v)\n        {\n            if (EditorGUI.actionKey)\n            {\n                int snapLevel = vTicks.GetLevelWithMinSeparation(5);\n                float snap = vTicks.GetPeriodOfLevel(snapLevel);\n                v = Mathf.Round(v / snap) * snap;\n            }\n            return v;\n        }\n\n        /*string DebugSelection ()\n        {\n            string s = \"\";\n            foreach (int i in m_PointSelection)\n                s += i + \", \";\n            s += \"\\n\";\n            foreach (CurveSelection k in selectedCurves)\n                s += \"[\" + k.curveID + \", \" + k.key+ \"], \";\n            return s;\n        }*/\n\n        new internal static class Styles\n        {\n            public const float pointIconCenterOffsetX = 7;\n            public const float pointIconCenterOffsetY = 8;\n            public const float pointIconSize = 16;\n            public static Texture2D pointIcon = EditorGUIUtility.LoadIcon(\"curvekeyframe\");\n            public static Texture2D pointIconWeighted = EditorGUIUtility.LoadIcon(\"curvekeyframeweighted\");\n            public static Texture2D pointIconSelected = EditorGUIUtility.LoadIcon(\"curvekeyframeselected\");\n            public static Texture2D pointIconSelectedOverlay = EditorGUIUtility.LoadIcon(\"curvekeyframeselectedoverlay\");\n            public static Texture2D pointIconSemiSelectedOverlay = EditorGUIUtility.LoadIcon(\"curvekeyframesemiselectedoverlay\");\n            public static GUIContent wrapModeMenuIcon = EditorGUIUtility.IconContent(\"AnimationWrapModeMenu\");\n\n            public static GUIStyle none = new GUIStyle();\n            public static GUIStyle labelTickMarksY = \"CurveEditorLabelTickMarks\";\n            public static GUIStyle labelTickMarksX = \"CurveEditorLabelTickmarksOverflow\";\n            public static GUIStyle selectionRect = \"SelectionRect\";\n\n            public static GUIStyle dragLabel = \"ProfilerBadge\";\n            public static GUIStyle axisLabelNumberField = \"AxisLabelNumberField\";\n            public static GUIStyle rightAlignedLabel = \"CurveEditorRightAlignedLabel\";\n        }\n\n        Vector2 GetGUIPoint(CurveWrapper cw, Vector3 point)\n        {\n            return HandleUtility.WorldToGUIPoint(DrawingToViewTransformPoint(point));\n        }\n\n        Rect GetWorldRect(CurveWrapper cw, Rect rect)\n        {\n            Vector2 min = GetWorldPoint(cw, rect.min);\n            Vector2 max = GetWorldPoint(cw, rect.max);\n\n            // Invert y world coordinates.\n            return Rect.MinMaxRect(min.x, max.y, max.x, min.y);\n        }\n\n        Vector2 GetWorldPoint(CurveWrapper cw, Vector2 point)\n        {\n            return ViewToDrawingTransformPoint(point);\n        }\n\n        Rect GetCurveRect(CurveWrapper cw)\n        {\n            Bounds bounds = cw.bounds;\n            return Rect.MinMaxRect(bounds.min.x, bounds.min.y, bounds.max.x, bounds.max.y);\n        }\n\n        Vector2 s_StartMouseDragPosition, s_EndMouseDragPosition, s_StartKeyDragPosition;\n        PickMode s_PickMode;\n\n        int OnlyOneEditableCurve()\n        {\n            int index = -1;\n            int curves = 0;\n            for (int i = 0; i < m_AnimationCurves.Length; i++)\n            {\n                CurveWrapper wrapper = m_AnimationCurves[i];\n                if (wrapper.hidden || wrapper.readOnly)\n                    continue;\n                curves++;\n                index = i;\n            }\n            if (curves == 1)\n                return index;\n            else\n                return -1;\n        }\n\n        // Returns an index into m_AnimationCurves\n        int GetCurveAtPosition(Vector2 viewPos, out Vector2 closestPointOnCurve)\n        {\n            Vector2 localPos = ViewToDrawingTransformPoint(viewPos);\n\n            // Find the closest curve at the time corresponding to the position\n            int maxPixelDist = (int)Mathf.Sqrt(kMaxPickDistSqr);\n            float smallestDist = kMaxPickDistSqr;\n            int closest = -1;\n            closestPointOnCurve = Vector3.zero;\n\n            // Use drawOrder to ensure we pick the topmost curve\n            for (int i = m_DrawOrder.Count - 1; i >= 0; --i)\n            {\n                CurveWrapper wrapper = GetCurveWrapperFromID(m_DrawOrder[i]);\n\n                if (wrapper.hidden || wrapper.readOnly || wrapper.curve.length == 0)\n                    continue;\n\n                // Sample the curves at pixel intervals in the area around the desired time,\n                // corresponding to the max cursor distance allowed.\n                Vector2 valL;\n                valL.x = localPos.x - maxPixelDist / scale.x;\n                valL.y = wrapper.renderer.EvaluateCurveSlow(valL.x);\n                valL = DrawingToViewTransformPoint(valL);\n                for (int x = -maxPixelDist; x < maxPixelDist; x++)\n                {\n                    Vector2 valR;\n                    valR.x = localPos.x + (x + 1) / scale.x;\n                    valR.y = wrapper.renderer.EvaluateCurveSlow(valR.x);\n                    valR = DrawingToViewTransformPoint(valR);\n\n                    float dist = HandleUtility.DistancePointLine(viewPos, valL, valR);\n                    dist = dist * dist;\n                    if (dist < smallestDist)\n                    {\n                        smallestDist = dist;\n                        closest = wrapper.listIndex;\n                        closestPointOnCurve = HandleUtility.ProjectPointLine(viewPos, valL, valR);\n                    }\n\n                    valL = valR;\n                }\n            }\n\n            if (closest >= 0)\n                closestPointOnCurve = ViewToDrawingTransformPoint(closestPointOnCurve);\n            return closest;\n        }\n\n        void CreateKeyFromClick(object obj)\n        {\n            string undoLabel = k_AddKey;\n            SaveKeySelection(undoLabel);\n\n            List<int> ids = CreateKeyFromClick((Vector2)obj);\n            if (ids.Count > 0)\n                UpdateCurves(ids, undoLabel);\n        }\n\n        List<int> CreateKeyFromClick(Vector2 viewPos)\n        {\n            List<int> curveIds = new List<int>();\n\n            // Check if there is only one curve to edit\n            int singleCurveIndex = OnlyOneEditableCurve();\n            if (singleCurveIndex >= 0)\n            {\n                // If there is only one curve, allow creating keys on it by double/right-clicking anywhere\n                // if the click is to the left or right of the existing keys, or if there are no existing keys.\n                CurveWrapper cw = m_AnimationCurves[singleCurveIndex];\n                Vector2 localPos = ViewToDrawingTransformPoint(viewPos);\n                float time = localPos.x;\n                if (cw.curve.length == 0 || time < cw.curve[0].time || time > cw.curve[cw.curve.length - 1].time)\n                {\n                    if (CreateKeyFromClick(singleCurveIndex, localPos))\n                        curveIds.Add(cw.id);\n                    return curveIds;\n                }\n            }\n\n            // If we didn't create a key above, only allow creating keys\n            // when double/right-clicking on an existing curve\n            Vector2 closestPointOnCurve;\n            int curveIndex = GetCurveAtPosition(viewPos, out closestPointOnCurve);\n            if (CreateKeyFromClick(curveIndex, closestPointOnCurve.x))\n            {\n                if (curveIndex >= 0)\n                    curveIds.Add(m_AnimationCurves[curveIndex].id);\n            }\n            return curveIds;\n        }\n\n        bool CreateKeyFromClick(int curveIndex, float time)\n        {\n            time = Mathf.Clamp(time, settings.hRangeMin, settings.hRangeMax);\n\n            // Add a key on a curve at a specified time\n            if (curveIndex >= 0)\n            {\n                CurveSelection selectedPoint = null;\n                CurveWrapper cw = m_AnimationCurves[curveIndex];\n\n                if (cw.animationIsEditable)\n                {\n                    if (cw.groupId == -1)\n                    {\n                        selectedPoint = AddKeyAtTime(cw, time);\n                    }\n                    else\n                    {\n                        foreach (CurveWrapper cw2 in m_AnimationCurves)\n                        {\n                            if (cw2.groupId == cw.groupId)\n                            {\n                                CurveSelection cs = AddKeyAtTime(cw2, time);\n                                if (cw2.id == cw.id)\n                                    selectedPoint = cs;\n                            }\n                        }\n                    }\n                    if (selectedPoint != null)\n                    {\n                        ClearSelection();\n                        AddSelection(selectedPoint);\n                        RecalcSecondarySelection();\n                    }\n                    else\n                    {\n                        SelectNone();\n                    }\n\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        bool CreateKeyFromClick(int curveIndex, Vector2 localPos)\n        {\n            localPos.x = Mathf.Clamp(localPos.x, settings.hRangeMin, settings.hRangeMax);\n\n            // Add a key on a curve at a specified time\n            if (curveIndex >= 0)\n            {\n                CurveSelection selectedPoint = null;\n                CurveWrapper cw = m_AnimationCurves[curveIndex];\n\n                if (cw.animationIsEditable)\n                {\n                    if (cw.groupId == -1)\n                    {\n                        selectedPoint = AddKeyAtPosition(cw, localPos);\n                    }\n                    else\n                    {\n                        foreach (CurveWrapper cw2 in m_AnimationCurves)\n                        {\n                            if (cw2.groupId == cw.groupId)\n                            {\n                                if (cw2.id == cw.id)\n                                    selectedPoint = AddKeyAtPosition(cw2, localPos);\n                                else\n                                    AddKeyAtTime(cw2, localPos.x);\n                            }\n                        }\n                    }\n                    if (selectedPoint != null)\n                    {\n                        ClearSelection();\n                        AddSelection(selectedPoint);\n                        RecalcSecondarySelection();\n                    }\n                    else\n                    {\n                        SelectNone();\n                    }\n\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        public void AddKey(CurveWrapper cw, Keyframe key)\n        {\n            CurveSelection selectedPoint = AddKeyframeAndSelect(key, cw);\n\n            if (selectedPoint != null)\n            {\n                ClearSelection();\n                AddSelection(selectedPoint);\n                RecalcSecondarySelection();\n            }\n            else\n            {\n                SelectNone();\n            }\n        }\n\n        // Add a key to cw at time.\n        // Returns the inserted key as a curveSelection\n        CurveSelection AddKeyAtTime(CurveWrapper cw, float time)\n        {\n            // Find out if there's already a key there\n            time = SnapTime(time);\n            float halfFrame;\n            if (invSnap != 0.0f)\n                halfFrame = 0.5f / invSnap;\n            else\n                halfFrame = 0.0001f;\n            if (CurveUtility.HaveKeysInRange(cw.curve, time - halfFrame, time + halfFrame))\n                return null;\n\n            // Add the key\n            int keyIndex = AnimationUtility.AddInbetweenKey(cw.curve, time);\n            if (keyIndex >= 0)\n            {\n                CurveUtility.SetKeyModeFromContext(cw.curve, keyIndex);\n                AnimationUtility.UpdateTangentsFromModeSurrounding(cw.curve, keyIndex);\n\n                // Select the key\n                CurveSelection selectedPoint = new CurveSelection(cw.id, keyIndex);\n                cw.selected = CurveWrapper.SelectionMode.Selected;\n                cw.changed = true;\n\n                return selectedPoint;\n            }\n\n            return null;\n        }\n\n        // Add a key to cw at time.\n        // Returns the inserted key as a curveSelection\n        CurveSelection AddKeyAtPosition(CurveWrapper cw, Vector2 position)\n        {\n            // Find out if there's already a key there\n            position.x = SnapTime(position.x);\n            float halfFrame;\n            if (invSnap != 0.0f)\n                halfFrame = 0.5f / invSnap;\n            else\n                halfFrame = 0.0001f;\n            if (CurveUtility.HaveKeysInRange(cw.curve, position.x - halfFrame, position.x + halfFrame))\n                return null;\n\n            // Add the key\n            float slope = 0;\n            Keyframe key = new Keyframe(position.x, SnapValue(position.y), slope, slope);\n            return AddKeyframeAndSelect(key, cw);\n        }\n\n        CurveSelection AddKeyframeAndSelect(Keyframe key, CurveWrapper cw)\n        {\n            if (!cw.animationIsEditable)\n                return null;\n\n            int keyIndex = cw.AddKey(key);\n            CurveUtility.SetKeyModeFromContext(cw.curve, keyIndex);\n            AnimationUtility.UpdateTangentsFromModeSurrounding(cw.curve, keyIndex);\n\n            // Select the key\n            CurveSelection selectedPoint = new CurveSelection(cw.id, keyIndex);\n            cw.selected = CurveWrapper.SelectionMode.Selected;\n            cw.changed = true;\n\n            return selectedPoint;\n        }\n\n        // Find keyframe nearest to the mouse. We use the draw order to ensure to return the\n        // key that is topmost rendered if several keys are overlapping. The user can\n        // click on another curve to bring it to front and hereby be able to better select its keys.\n        // Returns null if nothing is within Sqrt(kMaxPickDistSqr) pixels.\n        CurveSelection FindNearest()\n        {\n            Vector2 mousePos = Event.current.mousePosition;\n\n            bool foundCurve = false;\n            int bestCurveID = -1;\n            int bestKey = -1;\n            float nearestDist = kMaxPickDistSqr;\n\n            // Last element in draw order list is topmost so reverse traverse list\n            for (int index = m_DrawOrder.Count - 1; index >= 0; --index)\n            {\n                CurveWrapper cw = GetCurveWrapperFromID(m_DrawOrder[index]);\n                if (cw.readOnly || cw.hidden)\n                    continue;\n\n                Keyframe[] keys = cw.curve.keys;\n                for (int i = 0; i < cw.curve.length; ++i)\n                {\n                    Keyframe k = keys[i];\n                    float d = (GetGUIPoint(cw, new Vector2(k.time, k.value)) - mousePos).sqrMagnitude;\n                    // If we have an exact hit we just return that key\n                    if (d <= kExactPickDistSqr)\n                        return new CurveSelection(cw.id, i);\n\n                    // Otherwise find closest\n                    if (d < nearestDist)\n                    {\n                        foundCurve = true;\n                        bestCurveID = cw.id;\n                        bestKey = i;\n                        nearestDist = d;\n                    }\n                }\n                // If top curve has key within range make it harder for keys below to get selected\n                if (index == m_DrawOrder.Count - 1 && bestCurveID >= 0)\n                    nearestDist = kExactPickDistSqr;\n            }\n\n            if (foundCurve)\n                return new CurveSelection(bestCurveID, bestKey);\n\n            return null;\n        }\n\n        public void SelectNone()\n        {\n            ClearSelection();\n            foreach (CurveWrapper cw in m_AnimationCurves)\n                cw.selected = CurveWrapper.SelectionMode.None;\n        }\n\n        public void SelectAll()\n        {\n            int totalLength = 0;\n            foreach (CurveWrapper cw in m_AnimationCurves)\n            {\n                if (cw.hidden)\n                    continue;\n                totalLength += cw.curve.length;\n            }\n            var newSelection = new List<CurveSelection>(totalLength);\n\n            foreach (CurveWrapper cw in m_AnimationCurves)\n            {\n                cw.selected = CurveWrapper.SelectionMode.Selected;\n                for (int j = 0; j < cw.curve.length; j++)\n                    newSelection.Add(new CurveSelection(cw.id, j));\n            }\n            selectedCurves = newSelection;\n        }\n\n        public bool IsDraggingKey()\n        {\n            return m_DraggingKey != null;\n        }\n\n        public bool IsDraggingCurveOrRegion()\n        {\n            return m_DraggingCurveOrRegion != null;\n        }\n\n        public bool IsDraggingCurve(CurveWrapper cw)\n        {\n            return (m_DraggingCurveOrRegion != null && m_DraggingCurveOrRegion.Length == 1 && m_DraggingCurveOrRegion[0] == cw);\n        }\n\n        public bool IsDraggingRegion(CurveWrapper cw1, CurveWrapper cw2)\n        {\n            return (m_DraggingCurveOrRegion != null && m_DraggingCurveOrRegion.Length == 2 && (m_DraggingCurveOrRegion[0] == cw1 || m_DraggingCurveOrRegion[0] == cw2));\n        }\n\n        bool HandleCurveAndRegionMoveToFrontOnMouseDown(ref Vector2 timeValue, ref CurveWrapper[] curves)\n        {\n            // Did we click on a curve\n            Vector2 closestPointOnCurve;\n            int clickedCurveIndex = GetCurveAtPosition(Event.current.mousePosition, out closestPointOnCurve);\n            if (clickedCurveIndex >= 0)\n            {\n                MoveCurveToFront(m_AnimationCurves[clickedCurveIndex].id);\n                timeValue = mousePositionInDrawing;\n                curves = new[] { m_AnimationCurves[clickedCurveIndex] };\n                return true;\n            }\n\n            // Did we click in a region\n            for (int i = m_DrawOrder.Count - 1; i >= 0; --i)\n            {\n                CurveWrapper cw = GetCurveWrapperFromID(m_DrawOrder[i]);\n\n                if (cw == null)\n                    continue;\n                if (cw.hidden)\n                    continue;\n                if (cw.curve.length == 0)\n                    continue;\n\n                CurveWrapper cw2 = null;\n                if (i > 0)\n                    cw2 = GetCurveWrapperFromID(m_DrawOrder[i - 1]);\n\n                if (IsRegion(cw, cw2))\n                {\n                    float mouseY = mousePositionInDrawing.y;\n                    float time = mousePositionInDrawing.x;\n                    float v1 = cw.renderer.EvaluateCurveSlow(time);\n                    float v2 = cw2.renderer.EvaluateCurveSlow(time);\n                    if (v1 > v2)\n                    {\n                        float tmp = v1;\n                        v1 = v2; v2 = tmp;\n                    }\n                    if (mouseY >= v1 && mouseY <= v2)\n                    {\n                        timeValue = mousePositionInDrawing;\n                        curves = new[] { cw, cw2 };\n                        MoveCurveToFront(cw.id);\n                        return true;\n                    }\n                    i--; // we handled two curves\n                }\n            }\n            return false; // No curves or regions hit\n        }\n\n        void SelectPoints()\n        {\n            int id = GUIUtility.GetControlID(897560, FocusType.Passive);\n            Event evt = Event.current;\n            bool addToSelection = evt.shift;\n            bool toggleSelection = EditorGUI.actionKey;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.Layout:\n                    float distance = HandleUtility.DistanceToRectangleInternal(drawRect.position, Quaternion.identity, drawRect.size);\n                    HandleUtility.AddControl(id, distance);\n                    break;\n\n                case EventType.ContextClick:\n                    Rect drawRectAtOrigin = drawRect;\n                    drawRectAtOrigin.x = drawRectAtOrigin.y = 0f;\n                    if (drawRectAtOrigin.Contains(Event.current.mousePosition))\n                    {\n                        Vector2 closestPositionOnCurve;\n                        int curveIndex = GetCurveAtPosition(Event.current.mousePosition, out closestPositionOnCurve);\n                        if (curveIndex >= 0)\n                        {\n                            GenericMenu menu = new GenericMenu();\n                            if (m_AnimationCurves[curveIndex].animationIsEditable)\n                                menu.AddItem(EditorGUIUtility.TrTextContent(\"Add Key\"), false, CreateKeyFromClick, Event.current.mousePosition);\n                            else\n                                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Add Key\"));\n\n                            menu.ShowAsContext();\n                            Event.current.Use();\n                        }\n                    }\n                    break;\n\n                case EventType.MouseDown:\n                    if (evt.clickCount == 2 && evt.button == 0)\n                    {\n                        CurveSelection selectedPoint = FindNearest();\n\n                        if (selectedPoint != null)\n                        {\n                            if (!addToSelection)\n                            {\n                                ClearSelection();\n                            }\n\n                            AnimationCurve curve = GetCurveFromSelection(selectedPoint);\n                            if (curve != null)\n                            {\n                                BeginRangeSelection();\n                                for (int keyIndex = 0; keyIndex < curve.length; ++keyIndex)\n                                {\n                                    if (!selectedCurves.Any(x => x.curveID == selectedPoint.curveID && x.key == keyIndex))\n                                    {\n                                        var keySelection = new CurveSelection(selectedPoint.curveID, keyIndex);\n                                        AddSelection(keySelection);\n                                    }\n                                }\n                                EndRangeSelection();\n                            }\n                        }\n                        else\n                        {\n                            SaveKeySelection(k_AddKey);\n\n                            List<int> curveIds = CreateKeyFromClick(Event.current.mousePosition);\n                            if (curveIds.Count > 0)\n                            {\n                                foreach (int curveId in curveIds)\n                                {\n                                    CurveWrapper cw = GetCurveWrapperFromID(curveId);\n                                    cw.changed = true;\n                                }\n                                GUI.changed = true;\n                            }\n                        }\n                        evt.Use();\n                    }\n                    else if (evt.button == 0)\n                    {\n                        CurveSelection selectedPoint = FindNearest();\n                        if (selectedPoint == null || selectedPoint.semiSelected)\n                        {\n                            // If we did not hit a key then check if a curve or region was clicked\n                            Vector2 timeValue = Vector2.zero;\n                            CurveWrapper[] curves = null;\n                            var curveOrRegionClicked = HandleCurveAndRegionMoveToFrontOnMouseDown(ref timeValue, ref curves);\n\n                            if (!addToSelection && !toggleSelection && !curveOrRegionClicked)\n                            {\n                                SelectNone();\n                            }\n\n                            GUIUtility.hotControl = id;\n                            s_EndMouseDragPosition = s_StartMouseDragPosition = evt.mousePosition;\n                            s_PickMode = PickMode.Click;\n\n                            // case 845553 event will be processed afterwards when dragging curve.\n                            if (!curveOrRegionClicked)\n                                evt.Use();\n                        }\n                        else\n                        {\n                            MoveCurveToFront(selectedPoint.curveID);\n\n                            Keyframe selectedKeyframe = GetKeyframeFromSelection(selectedPoint);\n                            s_StartKeyDragPosition = new Vector2(selectedKeyframe.time, selectedKeyframe.value);\n\n                            if (addToSelection)\n                            {\n                                // Isolate range key indices in current selection.\n                                bool addRangeToSelection = false;\n                                int keyMin = selectedPoint.key;\n                                int keyMax = selectedPoint.key;\n                                for (int i = 0; i < selectedCurves.Count; ++i)\n                                {\n                                    CurveSelection cs = selectedCurves[i];\n                                    if (cs.curveID == selectedPoint.curveID)\n                                    {\n                                        addRangeToSelection = true;\n                                        keyMin = Mathf.Min(keyMin, cs.key);\n                                        keyMax = Mathf.Max(keyMax, cs.key);\n                                    }\n                                }\n\n                                if (!addRangeToSelection)\n                                {\n                                    if (!selectedCurves.Contains(selectedPoint))\n                                    {\n                                        AddSelection(selectedPoint);\n                                    }\n                                }\n                                else\n                                {\n                                    // Try and add all keys on the same curve in the range [keyMin, keyMax]\n                                    BeginRangeSelection();\n                                    for (var keyIndex = keyMin; keyIndex <= keyMax; ++keyIndex)\n                                    {\n                                        if (!selectedCurves.Any(x => x.curveID == selectedPoint.curveID && x.key == keyIndex))\n                                        {\n                                            var rangeSelection = new CurveSelection(selectedPoint.curveID, keyIndex);\n                                            AddSelection(rangeSelection);\n                                        }\n                                    }\n                                    EndRangeSelection();\n                                }\n                                Event.current.Use();\n                            }\n                            else if (toggleSelection)\n                            {\n                                if (!selectedCurves.Contains(selectedPoint))\n                                {\n                                    AddSelection(selectedPoint);\n                                }\n                                else\n                                {\n                                    RemoveSelection(selectedPoint);\n                                }\n                                Event.current.Use();\n                            }\n                            else if (!selectedCurves.Contains(selectedPoint))\n                            {\n                                ClearSelection();\n                                AddSelection(selectedPoint);\n                            }\n\n                            RecalcSecondarySelection();\n                            RecalcCurveSelection();\n                        }\n                        HandleUtility.Repaint();\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        s_EndMouseDragPosition = evt.mousePosition;\n                        if (s_PickMode == PickMode.Click)\n                        {\n                            s_PickMode = PickMode.Marquee;\n                            if (addToSelection || toggleSelection)\n                                s_SelectionBackup = new List<CurveSelection>(selectedCurves);\n                            else\n                                s_SelectionBackup = new List<CurveSelection>();\n                        }\n                        else\n                        {\n                            Rect r = EditorGUIExt.FromToRect(s_StartMouseDragPosition, evt.mousePosition);\n\n                            List<CurveSelection> newSelection = new List<CurveSelection>(s_SelectionBackup);\n                            for (int i = 0; i < m_AnimationCurves.Length; ++i)\n                            {\n                                CurveWrapper cw = m_AnimationCurves[i];\n                                if (cw.readOnly || cw.hidden)\n                                    continue;\n\n                                Rect worldRect = GetWorldRect(cw, r);\n                                if (!GetCurveRect(cw).Overlaps(worldRect))\n                                    continue;\n\n                                int keyIndex = 0;\n                                foreach (Keyframe k in cw.curve.keys)\n                                {\n                                    if (worldRect.Contains(new Vector2(k.time, k.value)))\n                                        newSelection.Add(new CurveSelection(cw.id, keyIndex));\n                                    ++keyIndex;\n                                }\n                            }\n                            selectedCurves = newSelection;\n\n                            // We need to sort selection since we're mixing existing selection with new selection.\n                            if (s_SelectionBackup.Count > 0)\n                                selectedCurves.Sort();\n\n                            RecalcSecondarySelection();\n                            RecalcCurveSelection();\n                        }\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        if (s_PickMode != PickMode.Click)\n                        {\n                            // Move selected curves to front.\n                            var processedCurves = new HashSet<int>();\n                            for (int i = 0; i < selectedCurves.Count; ++i)\n                            {\n                                CurveWrapper cw = GetCurveWrapperFromSelection(selectedCurves[i]);\n                                if (!processedCurves.Contains(cw.id))\n                                {\n                                    MoveCurveToFront(cw.id);\n                                    processedCurves.Add(cw.id);\n                                }\n                            }\n                        }\n\n                        GUIUtility.hotControl = 0;\n                        s_PickMode = PickMode.None;\n\n                        Event.current.Use();\n                    }\n                    break;\n            }\n\n            if (s_PickMode == PickMode.Marquee)\n            {\n                GUI.Label(EditorGUIExt.FromToRect(s_StartMouseDragPosition, s_EndMouseDragPosition), GUIContent.none, Styles.selectionRect);\n            }\n        }\n\n        string m_AxisLabelFormat = \"n1\";\n\n        private void EditAxisLabels()\n        {\n            int id = GUIUtility.GetControlID(18975602, FocusType.Keyboard);\n\n            List<CurveWrapper> curvesInSameSpace = new List<CurveWrapper>();\n            Vector2 axisUiScalars = GetAxisUiScalars(curvesInSameSpace);\n            bool isEditable = axisUiScalars.y >= 0 && curvesInSameSpace.Count > 0 && curvesInSameSpace[0].setAxisUiScalarsCallback != null;\n            if (!isEditable)\n                return;\n\n\n            Rect editRect = new Rect(0, topmargin - 8, leftmargin - 4, 16);\n            Rect dragRect = editRect;\n            dragRect.y -= editRect.height;\n\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.Repaint:\n                    if (GUIUtility.hotControl == 0)\n                        EditorGUIUtility.AddCursorRect(dragRect, MouseCursor.SlideArrow);\n                    break;\n\n                case EventType.MouseDown:\n                    if (evt.button == 0)\n                    {\n                        if (dragRect.Contains(Event.current.mousePosition))\n                        {\n                            if (GUIUtility.hotControl == 0)\n                            {\n                                GUIUtility.keyboardControl = 0;\n                                GUIUtility.hotControl = id;\n                                GUI.changed = true;\n                                evt.Use();\n                            }\n                        }\n                        if (!editRect.Contains(Event.current.mousePosition))\n                            GUIUtility.keyboardControl = 0; // If not hitting our FloatField ensure it loses focus\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        float dragSensitity = Mathf.Clamp01(Mathf.Max(axisUiScalars.y, Mathf.Pow(Mathf.Abs(axisUiScalars.y), 0.5f)) * .01f);\n                        axisUiScalars.y += HandleUtility.niceMouseDelta * dragSensitity;\n                        if (axisUiScalars.y < 0.001f)\n                            axisUiScalars.y = 0.001f; // Since the scalar is a magnitude we do not want to drag to 0 and below.. find nicer solution\n                        SetAxisUiScalars(axisUiScalars, curvesInSameSpace);\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        // Reset dragging\n                        GUIUtility.hotControl = 0;\n                    }\n                    break;\n            }\n\n            // Show input text field\n            string orgFormat = EditorGUI.kFloatFieldFormatString;\n            EditorGUI.kFloatFieldFormatString = m_AxisLabelFormat;\n            float newValue = EditorGUI.FloatField(editRect, axisUiScalars.y, Styles.axisLabelNumberField);\n            if (axisUiScalars.y != newValue)\n                SetAxisUiScalars(new Vector2(axisUiScalars.x, newValue), curvesInSameSpace);\n            EditorGUI.kFloatFieldFormatString = orgFormat;\n        }\n\n        public void BeginTimeRangeSelection(float time, bool addToSelection)\n        {\n            if (s_TimeRangeSelectionActive)\n            {\n                Debug.LogError(\"BeginTimeRangeSelection can only be called once\");\n                return;\n            }\n\n            s_TimeRangeSelectionActive = true;\n            s_TimeRangeSelectionStart = s_TimeRangeSelectionEnd = time;\n            if (addToSelection)\n                s_SelectionBackup = new List<CurveSelection>(selectedCurves);\n            else\n                s_SelectionBackup = new List<CurveSelection>();\n        }\n\n        public void TimeRangeSelectTo(float time)\n        {\n            if (!s_TimeRangeSelectionActive)\n            {\n                Debug.LogError(\"TimeRangeSelectTo can only be called after BeginTimeRangeSelection\");\n                return;\n            }\n\n            s_TimeRangeSelectionEnd = time;\n\n            var newSelection = new List<CurveSelection>(s_SelectionBackup);\n            float minTime = Mathf.Min(s_TimeRangeSelectionStart, s_TimeRangeSelectionEnd);\n            float maxTime = Mathf.Max(s_TimeRangeSelectionStart, s_TimeRangeSelectionEnd);\n            foreach (CurveWrapper cw in m_AnimationCurves)\n            {\n                if (cw.readOnly || cw.hidden)\n                    continue;\n                int i = 0;\n                foreach (Keyframe k in cw.curve.keys)\n                {\n                    if (k.time >= minTime && k.time < maxTime)\n                    {\n                        newSelection.Add(new CurveSelection(cw.id, i));\n                    }\n                    i++;\n                }\n            }\n            selectedCurves = newSelection;\n            RecalcSecondarySelection();\n            RecalcCurveSelection();\n        }\n\n        public void EndTimeRangeSelection()\n        {\n            if (!s_TimeRangeSelectionActive)\n            {\n                Debug.LogError(\"EndTimeRangeSelection can only be called after BeginTimeRangeSelection\");\n                return;\n            }\n\n            s_TimeRangeSelectionStart = s_TimeRangeSelectionEnd = 0;\n            s_TimeRangeSelectionActive = false;\n        }\n\n        public void CancelTimeRangeSelection()\n        {\n            if (!s_TimeRangeSelectionActive)\n            {\n                Debug.LogError(\"CancelTimeRangeSelection can only be called after BeginTimeRangeSelection\");\n                return;\n            }\n\n            selectedCurves = s_SelectionBackup;\n            s_TimeRangeSelectionActive = false;\n        }\n\n        bool m_EditingPoints;\n        bool m_TimeWasEdited;\n        bool m_ValueWasEdited;\n        float m_NewTime;\n        float m_NewValue;\n\n        const string kPointValueFieldName = \"pointValueField\";\n        const string kPointTimeFieldName = \"pointTimeField\";\n        string m_FocusedPointField = null;\n        Vector2 m_PointEditingFieldPosition;\n\n        Vector2 GetPointEditionFieldPosition()\n        {\n            var minTime = selectedCurves.Min(x => GetKeyframeFromSelection(x).time);\n            var maxTime = selectedCurves.Max(x => GetKeyframeFromSelection(x).time);\n            var minValue = selectedCurves.Min(x => GetKeyframeFromSelection(x).value);\n            var maxValue = selectedCurves.Max(x => GetKeyframeFromSelection(x).value);\n            return new Vector2(minTime + maxTime, minValue + maxValue) * 0.5f;\n        }\n\n        void StartEditingSelectedPointsContext(object fieldPosition)\n        {\n            StartEditingSelectedPoints((Vector2)fieldPosition);\n        }\n\n        void StartEditingSelectedPoints()\n        {\n            Vector2 centre = GetPointEditionFieldPosition();\n            StartEditingSelectedPoints(centre);\n        }\n\n        void StartEditingSelectedPoints(Vector2 fieldPosition)\n        {\n            m_PointEditingFieldPosition = fieldPosition;\n            m_FocusedPointField = kPointValueFieldName;\n            m_TimeWasEdited = false;\n            m_ValueWasEdited = false;\n\n            // Initialize new values to current selection.\n            m_NewTime = 0.0f;\n            m_NewValue = 0.0f;\n            Keyframe keyframe = GetKeyframeFromSelection(selectedCurves[0]);\n            if (selectedCurves.All(x => GetKeyframeFromSelection(x).time == keyframe.time))\n                m_NewTime = keyframe.time;\n            if (selectedCurves.All(x => GetKeyframeFromSelection(x).value == keyframe.value))\n                m_NewValue = keyframe.value;\n\n            m_EditingPoints = true;\n        }\n\n        void FinishEditingPoints()\n        {\n            m_EditingPoints = false;\n        }\n\n        void EditSelectedPoints()\n        {\n            var evt = Event.current;\n\n            if (m_EditingPoints && !hasSelection)\n            {\n                m_EditingPoints = false;\n            }\n\n            bool gotEscape = false;\n            if (evt.type == EventType.KeyDown)\n            {\n                if (evt.keyCode == KeyCode.KeypadEnter || evt.keyCode == KeyCode.Return)\n                {\n                    if (hasSelection && !m_EditingPoints)\n                    {\n                        StartEditingSelectedPoints();\n                        evt.Use();\n                    }\n                    else if (m_EditingPoints)\n                    {\n                        SetSelectedKeyPositions(m_NewTime, m_NewValue, m_TimeWasEdited, m_ValueWasEdited);\n                        FinishEditingPoints();\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                }\n                else if (evt.keyCode == KeyCode.Escape)\n                {\n                    gotEscape = true;\n                }\n            }\n\n            if (!m_EditingPoints)\n            {\n                return;\n            }\n\n            var fieldPosition = DrawingToViewTransformPoint(m_PointEditingFieldPosition);\n\n            const float kFieldHeight = 18f;\n            const float kFieldWidth = 95f;\n\n            // Keep fields in the drawing margins\n            var drawAreaInMargins = Rect.MinMaxRect(leftmargin, topmargin, rect.width - rightmargin, rect.height - bottommargin);\n            fieldPosition.x = Mathf.Clamp(fieldPosition.x, drawAreaInMargins.xMin, drawAreaInMargins.xMax - kFieldWidth);\n            fieldPosition.y = Mathf.Clamp(fieldPosition.y, drawAreaInMargins.yMin, drawAreaInMargins.yMax - kFieldHeight * 2);\n\n            EditorGUI.BeginChangeCheck();\n            GUI.SetNextControlName(kPointTimeFieldName);\n            CurveWrapper curveWrapper = GetCurveWrapperFromSelection(selectedCurves[0]);\n\n            Vector2 scale = Vector2.one;\n            if (curveWrapper.useScalingInKeyEditor && curveWrapper.getAxisUiScalarsCallback != null)\n            {\n                scale = curveWrapper.getAxisUiScalarsCallback();\n\n                // don't scale if the values are too small or negative\n                if (scale.x < 0.0001)\n                    scale.x = 1;\n                if (scale.y < 0.0001)\n                    scale.y = 1;\n            }\n\n            m_NewTime = PointFieldForSelection(\n                new Rect(fieldPosition.x, fieldPosition.y, kFieldWidth, kFieldHeight),\n                1,\n                m_NewTime * scale.x,\n                x => GetKeyframeFromSelection(x).time,\n                (r, id, time) => TimeField(r, id, time, invSnap, timeFormat),\n                curveWrapper.xAxisLabel == null ? settings.xAxisLabel : curveWrapper.xAxisLabel) / scale.x;\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_TimeWasEdited = true;\n            }\n\n            EditorGUI.BeginChangeCheck();\n            GUI.SetNextControlName(kPointValueFieldName);\n            m_NewValue = PointFieldForSelection(\n                new Rect(fieldPosition.x, fieldPosition.y + kFieldHeight, kFieldWidth, kFieldHeight),\n                2,\n                m_NewValue * scale.y,\n                x => GetKeyframeFromSelection(x).value,\n                (r, id, value) => ValueField(r, id, value),\n                curveWrapper.yAxisLabel == null ? settings.yAxisLabel : curveWrapper.yAxisLabel) / scale.y;\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_ValueWasEdited = true;\n            }\n\n            if (gotEscape)\n            {\n                FinishEditingPoints();\n            }\n\n            // Delay focusing these controls until they've been named\n            if (m_FocusedPointField != null)\n            {\n                EditorGUI.FocusTextInControl(m_FocusedPointField);\n                if (evt.type == EventType.Repaint)\n                {\n                    m_FocusedPointField = null;\n                }\n            }\n\n            if (evt.type == EventType.KeyDown)\n            {\n                const char tabCharacter = '\\t';\n                const char endOfMediumCharacter = (char)25; // ASCII 25: \"End Of Medium\" on pressing shift tab\n\n                // Override Unity's Tab and Shift+Tab handling.\n                if (evt.character == tabCharacter || evt.character == endOfMediumCharacter)\n                {\n                    if (m_TimeWasEdited || m_ValueWasEdited)\n                    {\n                        SetSelectedKeyPositions(m_NewTime, m_NewValue, m_TimeWasEdited, m_ValueWasEdited);\n                        m_PointEditingFieldPosition = GetPointEditionFieldPosition();\n                    }\n\n                    m_FocusedPointField = GUI.GetNameOfFocusedControl() == kPointValueFieldName ? kPointTimeFieldName : kPointValueFieldName;\n                    evt.Use();\n                }\n            }\n\n            // Stop editing if there's an unused click\n            if (evt.type == EventType.MouseDown)\n            {\n                FinishEditingPoints();\n            }\n        }\n\n        // Float editing field for members of selected points\n        float PointFieldForSelection(\n            Rect rect,\n            int customID,\n            float value, System.Func<CurveSelection, float> memberGetter,\n            System.Func<Rect, int, float, float> fieldCreator,\n            string label)\n        {\n            float firstSelectedValue = memberGetter(selectedCurves[0]);\n            bool sameValues = selectedCurves.All(x => memberGetter(x) == firstSelectedValue);\n            if (!sameValues)\n                EditorGUI.showMixedValue = true;\n\n            var labelRect = rect;\n            labelRect.x -= labelRect.width;\n\n            // Use custom IDs to separate event handling from drawing\n            int id = GUIUtility.GetControlID(customID, FocusType.Keyboard, rect);\n            var oldColor = GUI.color;\n            GUI.color = Color.white;\n            GUI.Label(labelRect, label, Styles.rightAlignedLabel);\n\n            value = fieldCreator(rect, id, value);\n\n            GUI.color = oldColor;\n            EditorGUI.showMixedValue = false;\n\n            return value;\n        }\n\n        // m_DraggingCurveOrRegion is null if nothing is being dragged, has one entry if single curve being dragged or has two entries if region is being dragged\n        CurveWrapper[] m_DraggingCurveOrRegion = null;\n\n        void SetupKeyOrCurveDragging(Vector2 timeValue, CurveWrapper cw, int id, Vector2 mousePos)\n        {\n            m_DraggedCoord = timeValue;\n            m_DraggingKey = cw;\n            GUIUtility.hotControl = id;\n\n            s_StartMouseDragPosition = mousePos;\n        }\n\n        public Vector2 MovePoints()\n        {\n            int id = GUIUtility.GetControlID(FocusType.Passive);\n\n            if (!hasSelection && !settings.allowDraggingCurvesAndRegions)\n                return Vector2.zero;\n\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (evt.button == 0)\n                    {\n                        // Key dragging\n                        foreach (CurveSelection cs in selectedCurves)\n                        {\n                            CurveWrapper curveWrapper = GetCurveWrapperFromSelection(cs);\n                            if ((curveWrapper == null) || curveWrapper.hidden)\n                                continue;\n\n                            if ((DrawingToViewTransformPoint(GetPosition(cs)) - evt.mousePosition).sqrMagnitude <= kMaxPickDistSqr)\n                            {\n                                Keyframe keyframe = GetKeyframeFromSelection(cs);\n                                SetupKeyOrCurveDragging(new Vector2(keyframe.time, keyframe.value), curveWrapper, id, evt.mousePosition);\n                                m_RectangleTool.OnStartMove(s_StartMouseDragPosition, rippleTime);\n                                evt.Use();\n                                break;\n                            }\n                        }\n\n                        // Curve dragging. Moving keys has highest priority, therefore we check curve/region dragging AFTER key dragging above\n                        if (evt.shift && settings.allowDraggingCurvesAndRegions && m_DraggingKey == null)\n                        {\n                            // We use the logic as for moving keys when we drag entire curves or regions: We just\n                            // select all keyFrames in a curve or region before dragging and ensure to hide tangents when drawing.\n                            Vector2 timeValue = Vector2.zero;\n                            CurveWrapper[] curves = null;\n                            if (HandleCurveAndRegionMoveToFrontOnMouseDown(ref timeValue, ref curves))\n                            {\n                                var newSelection = new List<CurveSelection>();\n                                // Add all keys of curves to selection to reuse code of key dragging\n                                foreach (CurveWrapper cw in curves)\n                                {\n                                    for (int i = 0; i < cw.curve.keys.Length; ++i)\n                                        newSelection.Add(new CurveSelection(cw.id, i));\n                                    MoveCurveToFront(cw.id);\n                                }\n                                preCurveDragSelection = selectedCurves;\n                                selectedCurves = newSelection;\n\n                                // Call after selection above\n                                SetupKeyOrCurveDragging(timeValue, curves[0], id, evt.mousePosition);\n                                m_DraggingCurveOrRegion = curves;\n                                m_RectangleTool.OnStartMove(s_StartMouseDragPosition, false);\n                                evt.Use();\n                            }\n                        }\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        Vector2 delta = evt.mousePosition - s_StartMouseDragPosition;\n                        Vector2 motion = Vector2.zero;\n\n                        // Only drag along x OR y when shift is held down\n                        if (evt.shift && m_AxisLock == AxisLock.None)\n                            m_AxisLock = Mathf.Abs(delta.x) > Mathf.Abs(delta.y) ? AxisLock.X : AxisLock.Y;\n\n                        if (m_DraggingCurveOrRegion != null)\n                        {\n                            // Curve/Region dragging only in y axis direction (for now)\n                            delta.x = 0;\n                            motion = ViewToDrawingTransformVector(delta);\n                            motion.y = SnapValue(motion.y + s_StartKeyDragPosition.y) - s_StartKeyDragPosition.y;\n                        }\n                        else\n                        {\n                            switch (m_AxisLock)\n                            {\n                                case AxisLock.None:\n                                    motion = ViewToDrawingTransformVector(delta);\n                                    motion.x = SnapTime(motion.x + s_StartKeyDragPosition.x) - s_StartKeyDragPosition.x;\n                                    motion.y = SnapValue(motion.y + s_StartKeyDragPosition.y) - s_StartKeyDragPosition.y;\n                                    break;\n                                case AxisLock.X:\n                                    delta.y = 0;\n                                    motion = ViewToDrawingTransformVector(delta);\n                                    motion.x = SnapTime(motion.x + s_StartKeyDragPosition.x) - s_StartKeyDragPosition.x;\n                                    break;\n                                case AxisLock.Y:\n                                    delta.x = 0;\n                                    motion = ViewToDrawingTransformVector(delta);\n                                    motion.y = SnapValue(motion.y + s_StartKeyDragPosition.y) - s_StartKeyDragPosition.y;\n                                    break;\n                            }\n                        }\n\n                        m_RectangleTool.OnMove(s_StartMouseDragPosition + motion);\n\n                        GUI.changed = true;\n                        evt.Use();\n                        return motion;\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (GUIUtility.hotControl == id && evt.keyCode == KeyCode.Escape)\n                    {\n                        TranslateSelectedKeys(Vector2.zero);\n                        ResetDragging();\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        m_RectangleTool.OnEndMove();\n                        ResetDragging();\n\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.Repaint:\n                    Rect mouseRect = new Rect(evt.mousePosition.x - 10, evt.mousePosition.y - 10, 20, 20);\n                    if (m_DraggingCurveOrRegion != null)\n                        EditorGUIUtility.AddCursorRect(mouseRect, MouseCursor.ResizeVertical);\n                    else if (m_DraggingKey != null)\n                        EditorGUIUtility.AddCursorRect(mouseRect, MouseCursor.MoveArrow);\n                    break;\n            }\n\n            return Vector2.zero;\n        }\n\n        void ResetDragging()\n        {\n            // If we are dragging entire curve we have selected all keys we therefore ensure to deselect them again...\n            if (m_DraggingCurveOrRegion != null)\n            {\n                selectedCurves = preCurveDragSelection;\n                preCurveDragSelection = null;\n            }\n\n            // Cleanup\n            GUIUtility.hotControl = 0;\n            m_DraggingKey = null;\n            m_DraggingCurveOrRegion = null;\n            m_MoveCoord = Vector2.zero;\n\n            m_AxisLock = AxisLock.None;\n        }\n\n        void MakeCurveBackups()\n        {\n            SaveKeySelection(k_EditCurve);\n\n            m_CurveBackups = new List<SavedCurve>();\n            int lastCurveID = -1;\n            SavedCurve sc = null;\n            for (int i = 0; i < selectedCurves.Count; i++)\n            {\n                CurveSelection cs = selectedCurves[i];\n                // if it's a different curve than last point, we need to back up this curve.\n                if (cs.curveID != lastCurveID)\n                {\n                    AnimationCurve curve = GetCurveFromSelection(cs);\n                    if (curve != null)\n                    {\n                        // Make a new saved curve with copy of all keyframes. No need to mark them as selected\n                        sc = new SavedCurve();\n                        lastCurveID = sc.curveId = cs.curveID;\n                        Keyframe[] keys = curve.keys;\n                        sc.keys = new List<SavedCurve.SavedKeyFrame>(keys.Length);\n                        foreach (Keyframe k in keys)\n                            sc.keys.Add(new SavedCurve.SavedKeyFrame(k, CurveWrapper.SelectionMode.None));\n                        m_CurveBackups.Add(sc);\n                    }\n                }\n\n                // Mark them as selected\n                sc.keys[cs.key].selected = cs.semiSelected ? CurveWrapper.SelectionMode.SemiSelected : CurveWrapper.SelectionMode.Selected;\n            }\n        }\n\n        public void SaveKeySelection(string undoLabel)\n        {\n            if (settings.undoRedoSelection)\n                Undo.RegisterCompleteObjectUndo(selection, undoLabel);\n        }\n\n        // Get the position of a CurveSelection. This will correctly offset tangent handles\n        Vector2 GetPosition(CurveSelection selection)\n        {\n            AnimationCurve curve = GetCurveFromSelection(selection);\n            Keyframe key = curve[selection.key];\n\n            Vector2 position = new Vector2(key.time, key.value);\n\n            float tangentLength = 50F;\n\n            if (selection.type == CurveSelection.SelectionType.InTangent)\n            {\n                Vector2 dir = new Vector2(1.0F, key.inTangent);\n                if (key.inTangent == Mathf.Infinity) dir = new Vector2(0, -1);\n                else if (key.inTangent == -Mathf.Infinity) dir = new Vector2(0, 1);\n\n                Vector2 viewDir = NormalizeInViewSpace(dir);\n\n                if ((key.weightedMode & WeightedMode.In) == WeightedMode.In)\n                {\n                    Keyframe prevKey = (selection.key >= 1 && selection.key < curve.length) ? curve[selection.key - 1] : key;\n                    float dx = key.time - prevKey.time;\n\n                    Vector2 bezierDir = dir * dx * key.inWeight;\n                    if (viewDir.magnitude * 10F < bezierDir.magnitude)\n                        return position - bezierDir;\n                    else\n                        return position - viewDir * 10F;\n                }\n                else\n                {\n                    return position - viewDir * tangentLength;\n                }\n            }\n            else if (selection.type == CurveSelection.SelectionType.OutTangent)\n            {\n                Vector2 dir = new Vector2(1.0F, key.outTangent);\n                if (key.outTangent == Mathf.Infinity) dir = new Vector2(0, -1);\n                else if (key.outTangent == -Mathf.Infinity) dir = new Vector2(0, 1);\n\n                Vector2 viewDir = NormalizeInViewSpace(dir);\n\n                if ((key.weightedMode & WeightedMode.Out) == WeightedMode.Out)\n                {\n                    Keyframe nextKey = (selection.key >= 0 && selection.key < (curve.length - 1)) ? curve[selection.key + 1] : key;\n                    float dx = nextKey.time - key.time;\n\n                    Vector2 bezierDir = dir * dx * key.outWeight;\n                    if (viewDir.magnitude * 10F < bezierDir.magnitude)\n                        return position + bezierDir;\n                    else\n                        return position + viewDir * 10F;\n                }\n                else\n                {\n                    return position + viewDir * tangentLength;\n                }\n            }\n            else\n                return position;\n        }\n\n        void MoveCurveToFront(int curveID)\n        {\n            int numCurves = m_DrawOrder.Count;\n            for (int i = 0; i < numCurves; ++i)\n            {\n                // Find curveID in draw order list\n                if (m_DrawOrder[i] == curveID)\n                {\n                    // If curve is part of a region then find other curve\n                    int regionId = GetCurveWrapperFromID(curveID).regionId;\n                    if (regionId >= 0)\n                    {\n                        // The other region curve can be on either side of current\n                        int indexOffset = 0;\n                        int curveID2 = -1;\n\n                        if (i - 1 >= 0)\n                        {\n                            int id = m_DrawOrder[i - 1];\n                            if (regionId == GetCurveWrapperFromID(id).regionId)\n                            {\n                                curveID2 = id;\n                                indexOffset = -1;\n                            }\n                        }\n                        if (i + 1 < numCurves && curveID2 < 0)\n                        {\n                            int id = m_DrawOrder[i + 1];\n                            if (regionId == GetCurveWrapperFromID(id).regionId)\n                            {\n                                curveID2 = id;\n                                indexOffset = 0;\n                            }\n                        }\n\n                        if (curveID2 >= 0)\n                        {\n                            m_DrawOrder.RemoveRange(i + indexOffset, 2);\n                            m_DrawOrder.Add(curveID2);\n                            m_DrawOrder.Add(curveID);       // ensure curveID is topMost (last)\n                            ValidateCurveList();\n                            return;\n                        }\n\n                        Debug.LogError(\"Unhandled region\");\n                    }\n                    else // Single curve\n                    {\n                        if (i == numCurves - 1)\n                            return; // curve already last (topmost)\n\n                        m_DrawOrder.RemoveAt(i);\n                        m_DrawOrder.Add(curveID);\n                        ValidateCurveList();\n                        return;\n                    }\n                }\n            }\n        }\n\n        bool IsCurveSelected(CurveWrapper cw)\n        {\n            if (cw != null)\n                return cw.selected != CurveWrapper.SelectionMode.None;\n            return false;\n        }\n\n        bool IsRegionCurveSelected(CurveWrapper cw1, CurveWrapper cw2)\n        {\n            return IsCurveSelected(cw1) ||\n                IsCurveSelected(cw2);\n        }\n\n        bool IsRegion(CurveWrapper cw1, CurveWrapper cw2)\n        {\n            if (cw1 != null && cw2 != null)\n                if (cw1.regionId >= 0)\n                    return cw1.regionId == cw2.regionId;\n            return false;\n        }\n\n        bool IsLeftTangentEditable(CurveSelection selection)\n        {\n            AnimationCurve curve = GetCurveFromSelection(selection);\n            if (curve == null)\n                return false;\n\n            if (selection.key < 1 || selection.key >= curve.length)\n                return false;\n\n            Keyframe keyframe = curve[selection.key];\n            TangentMode mode = AnimationUtility.GetKeyLeftTangentMode(keyframe);\n\n            // Tangent is already set to Free.\n            if (mode == TangentMode.Free)\n                return true;\n\n            // If tangent is modified, it will be converted to Free.\n            if (mode == TangentMode.ClampedAuto || mode == TangentMode.Auto)\n                return true;\n\n            return false;\n        }\n\n        bool IsRightTangentEditable(CurveSelection selection)\n        {\n            AnimationCurve curve = GetCurveFromSelection(selection);\n            if (curve == null)\n                return false;\n\n            if (selection.key < 0 || selection.key >= (curve.length - 1))\n                return false;\n\n            Keyframe keyframe = curve[selection.key];\n            TangentMode mode = AnimationUtility.GetKeyRightTangentMode(keyframe);\n\n            // Tangent is already set to Free.\n            if (mode == TangentMode.Free)\n                return true;\n\n            // If tangent is modified, it will be converted to Free.\n            if (mode == TangentMode.ClampedAuto || mode == TangentMode.Auto)\n                return true;\n\n            return false;\n        }\n\n        void DrawCurvesAndRegion(CurveWrapper cw1, CurveWrapper cw2, List<CurveSelection> selection, bool hasFocus)\n        {\n            DrawRegion(cw1, cw2, hasFocus);\n            DrawCurveAndPoints(cw1, IsCurveSelected(cw1) ? selection : null, hasFocus);\n            DrawCurveAndPoints(cw2, IsCurveSelected(cw2) ? selection : null, hasFocus);\n        }\n\n        void DrawCurveAndPoints(CurveWrapper cw, List<CurveSelection> selection, bool hasFocus)\n        {\n            DrawCurve(cw, hasFocus);\n            DrawPointsOnCurve(cw, selection, hasFocus);\n        }\n\n        bool ShouldCurveHaveFocus(int indexIntoDrawOrder, CurveWrapper cw1, CurveWrapper cw2)\n        {\n            bool focus = false;\n            if (indexIntoDrawOrder == m_DrawOrder.Count - 1)\n                focus = true;\n            else if (hasSelection)\n                focus = IsCurveSelected(cw1) || IsCurveSelected(cw2);\n            return focus;\n        }\n\n        void DrawCurves()\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            m_PointRenderer.Clear();\n\n            // Draw all curves\n            for (int i = 0; i < m_DrawOrder.Count; ++i)\n            {\n                CurveWrapper cw = GetCurveWrapperFromID(m_DrawOrder[i]);\n\n                if (cw == null)\n                    continue;\n                if (cw.hidden)\n                    continue;\n                if (cw.curve.length == 0)\n                    continue;\n\n\n                CurveWrapper cw2 = null;\n                if (i < m_DrawOrder.Count - 1)\n                    cw2 = GetCurveWrapperFromID(m_DrawOrder[i + 1]);\n\n                if (IsRegion(cw, cw2))\n                {\n                    i++; // we handle two curves\n\n                    bool focus = ShouldCurveHaveFocus(i, cw, cw2);\n                    DrawCurvesAndRegion(cw, cw2, IsRegionCurveSelected(cw, cw2) ? selectedCurves : null, focus);\n                }\n                else\n                {\n                    bool focus = ShouldCurveHaveFocus(i, cw, null);\n                    DrawCurveAndPoints(cw, IsCurveSelected(cw) ? selectedCurves : null, focus);\n                }\n            }\n\n            m_PointRenderer.Render();\n        }\n\n        void DrawCurvesTangents()\n        {\n            if (m_DraggingCurveOrRegion != null)\n                return;\n\n            // Draw left and right tangents lines\n            HandleUtility.ApplyWireMaterial();\n            GL.Begin(GL.LINES);\n            GL.Color(m_TangentColor * new Color(1, 1, 1, 0.75f));\n            for (int i = 0; i < selectedCurves.Count; ++i)\n            {\n                CurveSelection sel = selectedCurves[i];\n\n                if (sel.semiSelected)\n                    continue;\n\n                CurveWrapper curveWrapper = GetCurveWrapperFromSelection(sel);\n                if (curveWrapper == null)\n                    continue;\n\n                AnimationCurve curve = curveWrapper.curve;\n                if (curve == null)\n                    continue;\n\n                if (curve.length == 0)\n                    continue;\n\n                if (sel.key < 0 || sel.key >= curve.length)\n                    continue;\n\n                Vector2 keyPoint = GetPosition(sel);\n\n                if (IsLeftTangentEditable(sel) && GetKeyframeFromSelection(sel).time != curve.keys[0].time)\n                {\n                    Vector2 leftTangent = GetPosition(new CurveSelection(sel.curveID, sel.key, CurveSelection.SelectionType.InTangent));\n                    DrawLine(leftTangent, keyPoint);\n                }\n\n                if (IsRightTangentEditable(sel) && GetKeyframeFromSelection(sel).time != curve.keys[curve.keys.Length - 1].time)\n                {\n                    Vector2 rightTangent = GetPosition(new CurveSelection(sel.curveID, sel.key, CurveSelection.SelectionType.OutTangent));\n                    DrawLine(keyPoint, rightTangent);\n                }\n            }\n            GL.End();\n\n            m_PointRenderer.Clear();\n\n            // Draw left and right tangents handles\n            for (int i = 0; i < selectedCurves.Count; ++i)\n            {\n                CurveSelection sel = selectedCurves[i];\n\n                if (sel.semiSelected)\n                    continue;\n\n                CurveWrapper curveWrapper = GetCurveWrapperFromSelection(sel);\n                if (curveWrapper == null)\n                    continue;\n\n                AnimationCurve curve = curveWrapper.curve;\n                if (curve == null)\n                    continue;\n\n                if (curve.length == 0)\n                    continue;\n\n                if (IsLeftTangentEditable(sel) && GetKeyframeFromSelection(sel).time != curve.keys[0].time)\n                {\n                    Vector2 leftTangent = DrawingToViewTransformPoint(GetPosition(new CurveSelection(sel.curveID, sel.key, CurveSelection.SelectionType.InTangent)));\n                    DrawTangentPoint(leftTangent, (GetKeyframeFromSelection(sel).weightedMode & WeightedMode.In) == WeightedMode.In);\n                }\n\n                if (IsRightTangentEditable(sel) && GetKeyframeFromSelection(sel).time != curve.keys[curve.keys.Length - 1].time)\n                {\n                    Vector2 rightTangent = DrawingToViewTransformPoint(GetPosition(new CurveSelection(sel.curveID, sel.key, CurveSelection.SelectionType.OutTangent)));\n                    DrawTangentPoint(rightTangent, (GetKeyframeFromSelection(sel).weightedMode & WeightedMode.Out) == WeightedMode.Out);\n                }\n            }\n\n            m_PointRenderer.Render();\n        }\n\n        void DrawCurvesOverlay()\n        {\n            if (m_DraggingCurveOrRegion != null)\n                return;\n\n            // Draw label with values while dragging\n            if (m_DraggingKey != null && settings.rectangleToolFlags == RectangleToolFlags.NoRectangleTool)\n            {\n                GUI.color = Color.white;\n\n                // Clamp only using the currently dragged curve (we could have more selected but we only show the coord info for this one).\n                float smallestVRangeMin = vRangeMin;\n                float smallestVRangeMax = vRangeMax;\n                smallestVRangeMin = Mathf.Max(smallestVRangeMin, m_DraggingKey.vRangeMin);\n                smallestVRangeMax = Mathf.Min(smallestVRangeMax, m_DraggingKey.vRangeMax);\n\n                Vector2 newPoint = m_DraggedCoord + m_MoveCoord;\n                newPoint.x = Mathf.Clamp(newPoint.x, hRangeMin, hRangeMax);\n                newPoint.y = Mathf.Clamp(newPoint.y, smallestVRangeMin, smallestVRangeMax);\n                Vector2 p = DrawingToViewTransformPoint(newPoint);\n\n                Vector2 axisUiScalars = m_DraggingKey.getAxisUiScalarsCallback != null ? m_DraggingKey.getAxisUiScalarsCallback() : Vector2.one;\n                if (axisUiScalars.x >= 0f)\n                    newPoint.x *= axisUiScalars.x;\n                if (axisUiScalars.y >= 0f)\n                    newPoint.y *= axisUiScalars.y;\n                GUIContent content = new GUIContent(string.Format(\"{0}, {1}\", FormatTime(newPoint.x, invSnap, timeFormat), FormatValue(newPoint.y)));\n                Vector2 size = Styles.dragLabel.CalcSize(content);\n                EditorGUI.DoDropShadowLabel(\n                    new Rect(p.x, p.y - size.y, size.x, size.y), content, Styles.dragLabel, 0.3f\n                );\n            }\n        }\n\n        List<Vector3> CreateRegion(CurveWrapper minCurve, CurveWrapper maxCurve, float deltaTime)\n        {\n            var range = settings.curveRegionDomain;\n\n            // Create list of triangle points\n            List<Vector3> region = new List<Vector3>();\n\n            List<float> sampleTimes = new List<float>();\n            float sampleTime = range.x + deltaTime;\n            for (; sampleTime <= range.y; sampleTime += deltaTime)\n                sampleTimes.Add(sampleTime);\n\n            if (sampleTime != range.y)\n                sampleTimes.Add(range.y);\n\n            // To handle constant curves (high gradient) we add key time samples on both side of the keys as well\n            // the key time itself.\n\n            Keyframe[] maxKeys = maxCurve.curve.keys;\n            for (int i = 0; i < maxKeys.Length; ++i)\n            {\n                Keyframe key = maxKeys[i];\n                if (key.time > range.x && key.time < range.y)\n                {\n                    sampleTimes.Add(key.time - 0.0001f);\n                    sampleTimes.Add(key.time);\n                    sampleTimes.Add(key.time + 0.0001f);\n                }\n            }\n            Keyframe[] minKeys = minCurve.curve.keys;\n            for (int i = 0; i < minKeys.Length; ++i)\n            {\n                Keyframe key = minKeys[i];\n                if (key.time > range.x && key.time < range.y)\n                {\n                    sampleTimes.Add(key.time - 0.0001f);\n                    sampleTimes.Add(key.time);\n                    sampleTimes.Add(key.time + 0.0001f);\n                }\n            }\n\n            sampleTimes.Sort();\n\n            Vector3 prevA = new Vector3(range.x, maxCurve.renderer.EvaluateCurveSlow(0.0f), 0.0f);\n            Vector3 prevB = new Vector3(range.x, minCurve.renderer.EvaluateCurveSlow(0.0f), 0.0f);\n\n            Vector3 screenPrevA = drawingToViewMatrix.MultiplyPoint(prevA);\n            Vector3 screenPrevB = drawingToViewMatrix.MultiplyPoint(prevB);\n\n            for (int i = 0; i < sampleTimes.Count; ++i)\n            {\n                float time = sampleTimes[i];\n                Vector3 valueA = new Vector3(time, maxCurve.renderer.EvaluateCurveSlow(time), 0.0f);\n                Vector3 valueB = new Vector3(time, minCurve.renderer.EvaluateCurveSlow(time), 0.0f);\n\n                Vector3 screenValueA = drawingToViewMatrix.MultiplyPoint(valueA);\n                Vector3 screenValueB = drawingToViewMatrix.MultiplyPoint(valueB);\n\n                // Add triangles\n                if (prevA.y >= prevB.y && valueA.y >= valueB.y)\n                {\n                    // max is top\n                    region.Add(screenPrevA);\n                    region.Add(screenValueB);\n                    region.Add(screenPrevB);\n\n                    region.Add(screenPrevA);\n                    region.Add(screenValueA);\n                    region.Add(screenValueB);\n                }\n                else if (prevA.y <= prevB.y && valueA.y <= valueB.y)\n                {\n                    // min is top\n                    region.Add(screenPrevB);\n                    region.Add(screenValueA);\n                    region.Add(screenPrevA);\n\n                    region.Add(screenPrevB);\n                    region.Add(screenValueB);\n                    region.Add(screenValueA);\n                }\n                else\n                {\n                    // Find intersection\n                    Vector2 intersection = Vector2.zero;\n                    if (Mathf.LineIntersection(screenPrevA, screenValueA, screenPrevB, screenValueB, ref intersection))\n                    {\n                        region.Add(screenPrevA);\n                        region.Add(intersection);\n                        region.Add(screenPrevB);\n\n                        region.Add(screenValueA);\n                        region.Add(intersection);\n                        region.Add(screenValueB);\n                    }\n                    else\n                    {\n                        Debug.Log(\"Error: No intersection found! There should be one...\");\n                    }\n                }\n\n                prevA = valueA;\n                prevB = valueB;\n\n                screenPrevA = screenValueA;\n                screenPrevB = screenValueB;\n            }\n\n            return region;\n        }\n\n        public void DrawRegion(CurveWrapper curve1, CurveWrapper curve2, bool hasFocus)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            float deltaTime = 1.0f / (rect.width / 10.0f);\n            List<Vector3> points = CreateRegion(curve1, curve2, deltaTime);\n            Color color = curve1.color;\n\n            if (IsDraggingRegion(curve1, curve2))\n            {\n                color = Color.Lerp(color, Color.black, 0.1f);\n                color.a = 0.4f;\n            }\n            else if (settings.useFocusColors && !hasFocus)\n            {\n                color *= 0.4f;\n                color.a = 0.1f;\n            }\n            else\n            {\n                color *= 1.0f;\n                color.a = 0.4f;\n            }\n\n            Shader.SetGlobalColor(\"_HandleColor\", color);\n            HandleUtility.ApplyWireMaterial();\n            GL.Begin(GL.TRIANGLES);\n            int numTriangles = points.Count / 3;\n            for (int i = 0; i < numTriangles; i++)\n            {\n                GL.Color(color);\n                GL.Vertex(points[i * 3]);\n                GL.Vertex(points[i * 3 + 1]);\n                GL.Vertex(points[i * 3 + 2]);\n            }\n            GL.End();\n        }\n\n        void DrawCurve(CurveWrapper cw, bool hasFocus)\n        {\n            CurveRenderer renderer = cw.renderer;\n            Color color = cw.color;\n\n            if (IsDraggingCurve(cw) || cw.selected == CurveWrapper.SelectionMode.Selected)\n            {\n                color = Color.Lerp(color, Color.white, 0.3f);\n            }\n            else if (settings.useFocusColors && !hasFocus)\n            {\n                color *= 0.5f;\n                color.a = 0.8f;\n            }\n\n            Rect framed = shownArea;\n            renderer.DrawCurve(framed.xMin, framed.xMax, color, drawingToViewMatrix, settings.wrapColor * cw.wrapColorMultiplier);\n        }\n\n        void DrawPointsOnCurve(CurveWrapper cw, List<CurveSelection> selected, bool hasFocus)\n        {\n            if (selected == null)\n            {\n                Color color = cw.color;\n                if (settings.useFocusColors && !hasFocus)\n                    color *= 0.5f;\n                GUI.color = color;\n\n                Keyframe[] keys = cw.curve.keys;\n                for (int i = 0; i < keys.Length; ++i)\n                {\n                    Keyframe k = keys[i];\n                    DrawPoint(DrawingToViewTransformPoint(new Vector2(k.time, k.value)), CurveWrapper.SelectionMode.None);\n                }\n            }\n            else\n            {\n                Color keyColor = Color.Lerp(cw.color, Color.white, .2f);\n                GUI.color = keyColor;\n\n                int selectionIdx = 0;\n                // Find the point in selected curves that matches the curve we're about to draw.\n                while (selectionIdx < selected.Count && selected[selectionIdx].curveID != cw.id)\n                    selectionIdx++;\n                // we're now at the right point in the selection.\n                int pointIdx = 0;\n                Keyframe[] keys = cw.curve.keys;\n                for (int i = 0; i < keys.Length; ++i)\n                {\n                    Keyframe k = keys[i];\n                    if (selectionIdx < selected.Count && selected[selectionIdx].key == pointIdx && selected[selectionIdx].curveID == cw.id)\n                    {\n                        if (selected[selectionIdx].semiSelected)\n                            DrawPoint(DrawingToViewTransformPoint(new Vector2(k.time, k.value)), CurveWrapper.SelectionMode.SemiSelected);\n                        else\n                            DrawPoint(DrawingToViewTransformPoint(new Vector2(k.time, k.value)), CurveWrapper.SelectionMode.Selected, settings.rectangleToolFlags == RectangleToolFlags.NoRectangleTool ? MouseCursor.MoveArrow : MouseCursor.Arrow);\n                        selectionIdx++;\n                    }\n                    else\n                        DrawPoint(DrawingToViewTransformPoint(new Vector2(k.time, k.value)), CurveWrapper.SelectionMode.None);\n                    pointIdx++;\n                }\n                GUI.color = Color.white;\n            }\n        }\n\n        void DrawPoint(Vector2 viewPos, CurveWrapper.SelectionMode selected)\n        {\n            DrawPoint(viewPos, selected, MouseCursor.Arrow);\n        }\n\n        void DrawPoint(Vector2 viewPos, CurveWrapper.SelectionMode selected, MouseCursor mouseCursor)\n        {\n            // Important to take floor of positions of GUI stuff to get pixel correct alignment of\n            // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time.\n            var rect = new Rect(Mathf.Floor(viewPos.x) - Styles.pointIconCenterOffsetX, Mathf.Floor(viewPos.y) - Styles.pointIconCenterOffsetY, Styles.pointIconSize, Styles.pointIconSize);\n\n            if (selected == CurveWrapper.SelectionMode.None)\n            {\n                m_PointRenderer.AddPoint(rect, GUI.color);\n            }\n            else\n            {\n                if (selected == CurveWrapper.SelectionMode.Selected)\n                    m_PointRenderer.AddSelectedPoint(rect, GUI.color);\n                else\n                    m_PointRenderer.AddSemiSelectedPoint(rect, GUI.color);\n            }\n\n            // Changing the cursor for every point in the selection can be awfully costly.\n            if (mouseCursor != MouseCursor.Arrow)\n            {\n                if (GUIUtility.hotControl == 0)\n                    EditorGUIUtility.AddCursorRect(rect, mouseCursor);\n            }\n        }\n\n        void DrawTangentPoint(Vector2 viewPos, bool weighted)\n        {\n            // Important to take floor of positions of GUI stuff to get pixel correct alignment of\n            // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time.\n            var rect = new Rect(Mathf.Floor(viewPos.x) - Styles.pointIconCenterOffsetX, Mathf.Floor(viewPos.y) - Styles.pointIconCenterOffsetY, Styles.pointIconSize, Styles.pointIconSize);\n\n            if (weighted)\n            {\n                m_PointRenderer.AddWeightedPoint(rect, m_WeightedTangentColor);\n            }\n            else\n            {\n                m_PointRenderer.AddPoint(rect, m_TangentColor);\n            }\n        }\n\n        // FIXME remove when grid drawing function has been properly rewritten\n        void DrawLine(Vector2 lhs, Vector2 rhs)\n        {\n            GL.Vertex(DrawingToViewTransformPoint(new Vector3(lhs.x, lhs.y, 0)));\n            GL.Vertex(DrawingToViewTransformPoint(new Vector3(rhs.x, rhs.y, 0)));\n        }\n\n        void DrawWrapperPopups()\n        {\n            if (!settings.showWrapperPopups)\n                return;\n\n            int curveId;\n            GetTopMostCurveID(out curveId);\n\n            if (curveId == -1)\n                return;\n\n            CurveWrapper wrapper = GetCurveWrapperFromID(curveId);\n            AnimationCurve curve = wrapper.curve;\n\n            if (curve != null && curve.length >= 2 && curve.preWrapMode != WrapMode.Default)\n            {\n                GUI.BeginGroup(drawRect);\n                Color oldText = GUI.contentColor;\n\n                var preKey = curve.keys[0];\n                var preWrap = curve.preWrapMode;\n                preWrap = WrapModeIconPopup(preKey, preWrap, -1.5f);\n                if (preWrap != curve.preWrapMode)\n                {\n                    curve.preWrapMode = preWrap;\n                    wrapper.changed = true;\n                }\n\n                var postKey = curve.keys[curve.length - 1];\n                var postWrap = curve.postWrapMode;\n                postWrap = WrapModeIconPopup(postKey, postWrap, 0.5f);\n                if (postWrap != curve.postWrapMode)\n                {\n                    curve.postWrapMode = postWrap;\n                    wrapper.changed = true;\n                }\n\n                if (wrapper.changed)\n                {\n                    wrapper.renderer.SetWrap(curve.preWrapMode, curve.postWrapMode);\n                    if (curvesUpdated != null)\n                        curvesUpdated();\n                }\n\n                GUI.contentColor = oldText;\n                GUI.EndGroup();\n            }\n        }\n\n        WrapMode WrapModeIconPopup(Keyframe key, WrapMode oldWrap, float hOffset)\n        {\n            float buttonSize = Styles.wrapModeMenuIcon.image.width;\n            var keyPosition = new Vector3(key.time, key.value);\n            keyPosition = DrawingToViewTransformPoint(keyPosition);\n            var r = new Rect(keyPosition.x + buttonSize * hOffset, keyPosition.y, buttonSize, buttonSize);\n\n            var selectedValue = (WrapModeFixedCurve)oldWrap;\n\n            // EnumPopupInternal begins\n\n            // sa and values are sorted in the same order\n            Enum[] enumValues = Enum.GetValues(typeof(WrapModeFixedCurve)).Cast<Enum>().ToArray();\n            var stringNames = Enum.GetNames(typeof(WrapModeFixedCurve)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray();\n\n            int i = Array.IndexOf(enumValues, selectedValue);\n\n            // PopupInternal begins\n\n            int controlID = GUIUtility.GetControlID(\"WrapModeIconPopup\".GetHashCode(), FocusType.Keyboard, r);\n\n            // DoPopup begins\n\n            var selectedPopupIndex = EditorGUI.PopupCallbackInfo.GetSelectedValueForControl(controlID, i);\n\n            var popupStrings = EditorGUIUtility.TempContent(stringNames);\n\n            Event evt = Event.current;\n            switch (evt.type)\n            {\n                case EventType.Repaint:\n                    GUIStyle.none.Draw(r, Styles.wrapModeMenuIcon, controlID, false);\n                    break;\n                case EventType.MouseDown:\n                    if (evt.button == 0 && r.Contains(evt.mousePosition))\n                    {\n                        if (Application.platform == RuntimePlatform.OSXEditor)\n                        {\n                            r.y = r.y - selectedPopupIndex * 16 - 19;\n                        }\n                        EditorGUI.PopupCallbackInfo.instance = new EditorGUI.PopupCallbackInfo(controlID);\n                        EditorUtility.DisplayCustomMenu(r, popupStrings, selectedPopupIndex, EditorGUI.PopupCallbackInfo.instance.SetEnumValueDelegate, null);\n                        GUIUtility.keyboardControl = controlID;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (evt.MainActionKeyForControl(controlID))\n                    {\n                        if (Application.platform == RuntimePlatform.OSXEditor)\n                        {\n                            r.y = r.y - selectedPopupIndex * 16 - 19;\n                        }\n                        EditorGUI.PopupCallbackInfo.instance = new EditorGUI.PopupCallbackInfo(controlID);\n                        EditorUtility.DisplayCustomMenu(r, popupStrings, selectedPopupIndex, EditorGUI.PopupCallbackInfo.instance.SetEnumValueDelegate, null);\n                        evt.Use();\n                    }\n                    break;\n            }\n\n            return (WrapMode)enumValues[selectedPopupIndex];\n        }\n\n        // The return value for each axis can be -1, if so then we do not have any proper value\n        // to use.\n        private Vector2 GetAxisUiScalars(List<CurveWrapper> curvesWithSameParameterSpace)\n        {\n            // If none or just one selected curve then use top most rendered curve value\n            if (selectedCurves.Count <= 1)\n            {\n                if (m_DrawOrder.Count > 0)\n                {\n                    CurveWrapper cw = GetCurveWrapperFromID(m_DrawOrder[m_DrawOrder.Count - 1]);\n                    if (cw != null && cw.getAxisUiScalarsCallback != null)\n                    {\n                        // Save list\n                        if (curvesWithSameParameterSpace != null)\n                            curvesWithSameParameterSpace.Add(cw);\n                        return cw.getAxisUiScalarsCallback();\n                    }\n                }\n                return Vector2.one;\n            }\n\n            // If multiple curves selected we have to check if they are in the same value space\n            Vector2 axisUiScalars = new Vector2(-1, -1);\n            if (selectedCurves.Count > 1)\n            {\n                // Find common axis scalars if more than one key selected\n                bool xAllSame = true;\n                bool yAllSame = true;\n                Vector2 scalars = Vector2.one;\n                for (int i = 0; i < selectedCurves.Count; ++i)\n                {\n                    CurveWrapper cw = GetCurveWrapperFromSelection(selectedCurves[i]);\n                    if (cw == null)\n                        continue;\n\n                    if (cw.getAxisUiScalarsCallback != null)\n                    {\n                        Vector2 temp = cw.getAxisUiScalarsCallback();\n                        if (i == 0)\n                        {\n                            scalars = temp; // init scalars\n                        }\n                        else\n                        {\n                            if (Mathf.Abs(temp.x - scalars.x) > 0.00001f)\n                                xAllSame = false;\n                            if (Mathf.Abs(temp.y - scalars.y) > 0.00001f)\n                                yAllSame = false;\n                            scalars = temp;\n                        }\n\n                        // Save list\n                        if (curvesWithSameParameterSpace != null)\n                            curvesWithSameParameterSpace.Add(cw);\n                    }\n                }\n                if (xAllSame)\n                    axisUiScalars.x = scalars.x;\n                if (yAllSame)\n                    axisUiScalars.y = scalars.y;\n            }\n\n            return axisUiScalars;\n        }\n\n        private void SetAxisUiScalars(Vector2 newScalars, List<CurveWrapper> curvesInSameSpace)\n        {\n            foreach (CurveWrapper cw in curvesInSameSpace)\n            {\n                // Only set valid values (-1 indicate invalid value, if so use original value)\n                Vector2 scalar = cw.getAxisUiScalarsCallback();\n                if (newScalars.x >= 0)\n                    scalar.x = newScalars.x;\n                if (newScalars.y >= 0)\n                    scalar.y = newScalars.y;\n\n                if (cw.setAxisUiScalarsCallback != null)\n                    cw.setAxisUiScalarsCallback(scalar);\n            }\n        }\n\n        internal enum PickMode { None, Click, Marquee }\n\n        public void GridGUI()\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            GUI.BeginClip(drawRect);\n\n            Color tempCol = GUI.color;\n\n            // Get axis scalars\n            Vector2 axisUiScalars = GetAxisUiScalars(null);\n\n            // Cache framed area rect as fetching the property takes some calculations\n            Rect shownRect = shownArea;\n\n            hTicks.SetRanges(shownRect.xMin * axisUiScalars.x, shownRect.xMax * axisUiScalars.x, drawRect.xMin, drawRect.xMax);\n            vTicks.SetRanges(shownRect.yMin * axisUiScalars.y, shownRect.yMax * axisUiScalars.y, drawRect.yMin, drawRect.yMax);\n\n            // Draw time markers of various strengths\n            HandleUtility.ApplyWireMaterial();\n            GL.Begin(GL.LINES);\n\n            float lineStart, lineEnd;\n\n            hTicks.SetTickStrengths(settings.hTickStyle.distMin, settings.hTickStyle.distFull, false);\n            if (settings.hTickStyle.stubs)\n            {\n                lineStart = shownRect.yMin;\n                lineEnd = shownRect.yMin - 40 / scale.y;\n            }\n            else\n            {\n                lineStart = Mathf.Max(shownRect.yMin, vRangeMin);\n                lineEnd = Mathf.Min(shownRect.yMax, vRangeMax);\n            }\n\n            for (int l = 0; l < hTicks.tickLevels; l++)\n            {\n                float strength = hTicks.GetStrengthOfLevel(l);\n                if (strength > 0f)\n                {\n                    GL.Color(settings.hTickStyle.tickColor * new Color(1, 1, 1, strength) * new Color(1, 1, 1, 0.75f));\n                    float[] ticks = hTicks.GetTicksAtLevel(l, true);\n                    for (int j = 0; j < ticks.Length; j++)\n                    {\n                        ticks[j] /= axisUiScalars.x;\n                        if (ticks[j] > hRangeMin && ticks[j] < hRangeMax)\n                            DrawLine(new Vector2(ticks[j], lineStart), new Vector2(ticks[j], lineEnd));\n                    }\n                }\n            }\n\n            // Draw bounds of allowed range\n            GL.Color(settings.hTickStyle.tickColor * new Color(1, 1, 1, 1) * new Color(1, 1, 1, 0.75f));\n            if (hRangeMin != Mathf.NegativeInfinity)\n                DrawLine(new Vector2(hRangeMin, lineStart), new Vector2(hRangeMin, lineEnd));\n            if (hRangeMax != Mathf.Infinity)\n                DrawLine(new Vector2(hRangeMax, lineStart), new Vector2(hRangeMax, lineEnd));\n\n            vTicks.SetTickStrengths(settings.vTickStyle.distMin, settings.vTickStyle.distFull, false);\n            if (settings.vTickStyle.stubs)\n            {\n                lineStart = shownRect.xMin;\n                lineEnd = shownRect.xMin + 40 / scale.x;\n            }\n            else\n            {\n                lineStart = Mathf.Max(shownRect.xMin, hRangeMin);\n                lineEnd = Mathf.Min(shownRect.xMax, hRangeMax);\n            }\n\n            // Draw value markers of various strengths\n            for (int l = 0; l < vTicks.tickLevels; l++)\n            {\n                float strength = vTicks.GetStrengthOfLevel(l);\n                if (strength > 0f)\n                {\n                    GL.Color(settings.vTickStyle.tickColor * new Color(1, 1, 1, strength) * new Color(1, 1, 1, 0.75f));\n                    float[] ticks = vTicks.GetTicksAtLevel(l, true);\n                    for (int j = 0; j < ticks.Length; j++)\n                    {\n                        ticks[j] /= axisUiScalars.y;\n                        if (ticks[j] > vRangeMin && ticks[j] < vRangeMax)\n                            DrawLine(new Vector2(lineStart, ticks[j]), new Vector2(lineEnd, ticks[j]));\n                    }\n                }\n            }\n            // Draw bounds of allowed range\n            GL.Color(settings.vTickStyle.tickColor * new Color(1, 1, 1, 1) * new Color(1, 1, 1, 0.75f));\n            if (vRangeMin != Mathf.NegativeInfinity)\n                DrawLine(new Vector2(lineStart, vRangeMin), new Vector2(lineEnd, vRangeMin));\n            if (vRangeMax != Mathf.Infinity)\n                DrawLine(new Vector2(lineStart, vRangeMax), new Vector2(lineEnd, vRangeMax));\n\n            GL.End();\n\n\n            if (settings.showAxisLabels)\n            {\n                // X Axis labels\n                if (settings.hTickStyle.distLabel > 0 && axisUiScalars.x > 0f)\n                {\n                    GUI.color = settings.hTickStyle.labelColor;\n                    int labelLevel = hTicks.GetLevelWithMinSeparation(settings.hTickStyle.distLabel);\n\n                    // Calculate how many decimals are needed to show the differences between the labeled ticks\n                    int decimals = MathUtils.GetNumberOfDecimalsForMinimumDifference(hTicks.GetPeriodOfLevel(labelLevel));\n\n                    // now draw\n                    float[] ticks = hTicks.GetTicksAtLevel(labelLevel, false);\n                    float[] ticksPos = (float[])ticks.Clone();\n                    float vpos = Mathf.Floor(drawRect.height);\n                    for (int i = 0; i < ticks.Length; i++)\n                    {\n                        ticksPos[i] /= axisUiScalars.x;\n                        if (ticksPos[i] < hRangeMin || ticksPos[i] > hRangeMax)\n                            continue;\n                        Vector2 pos = DrawingToViewTransformPoint(new Vector2(ticksPos[i], 0));\n                        // Important to take floor of positions of GUI stuff to get pixel correct alignment of\n                        // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time.\n                        pos = new Vector2(Mathf.Floor(pos.x), vpos);\n\n                        float uiValue = ticks[i];\n                        Rect labelRect;\n                        TextAnchor wantedAlignment;\n                        if (settings.hTickStyle.centerLabel)\n                        {\n                            wantedAlignment = TextAnchor.UpperCenter;\n                            labelRect = new Rect(pos.x, pos.y - 16 - settings.hTickLabelOffset, 1, 16);\n                        }\n                        else\n                        {\n                            wantedAlignment = TextAnchor.UpperLeft;\n                            labelRect = new Rect(pos.x, pos.y - 16 - settings.hTickLabelOffset, 50, 16);\n                        }\n\n                        if (Styles.labelTickMarksX.alignment != wantedAlignment)\n                            Styles.labelTickMarksX.alignment = wantedAlignment;\n\n                        GUI.Label(labelRect, uiValue.ToString(\"n\" + decimals) + settings.hTickStyle.unit, Styles.labelTickMarksX);\n                    }\n                }\n\n                // Y Axis labels\n                if (settings.vTickStyle.distLabel > 0 && axisUiScalars.y > 0f)\n                {\n                    // Draw value labels\n                    GUI.color = settings.vTickStyle.labelColor;\n                    int labelLevel = vTicks.GetLevelWithMinSeparation(settings.vTickStyle.distLabel);\n\n                    float[] ticks = vTicks.GetTicksAtLevel(labelLevel, false);\n                    float[] ticksPos = (float[])ticks.Clone();\n\n                    // Calculate how many decimals are needed to show the differences between the labeled ticks\n                    int decimals = MathUtils.GetNumberOfDecimalsForMinimumDifference(vTicks.GetPeriodOfLevel(labelLevel));\n                    string format = \"n\" + decimals;\n                    m_AxisLabelFormat = format;\n\n                    // Calculate the size of the biggest shown label\n                    float labelSize = 35;\n                    if (!settings.vTickStyle.stubs && ticks.Length > 1)\n                    {\n                        float min = ticks[1];\n                        float max = ticks[ticks.Length - 1];\n                        string minNumber = min.ToString(format) + settings.vTickStyle.unit;\n                        string maxNumber = max.ToString(format) + settings.vTickStyle.unit;\n                        labelSize = Mathf.Max(\n                            Styles.labelTickMarksY.CalcSize(new GUIContent(minNumber)).x,\n                            Styles.labelTickMarksY.CalcSize(new GUIContent(maxNumber)).x\n                            ) + 6;\n                    }\n\n                    // Now draw\n                    for (int i = 0; i < ticks.Length; i++)\n                    {\n                        ticksPos[i] /= axisUiScalars.y;\n                        if (ticksPos[i] < vRangeMin || ticksPos[i] > vRangeMax)\n                            continue;\n                        Vector2 pos = DrawingToViewTransformPoint(new Vector2(0, ticksPos[i]));\n                        // Important to take floor of positions of GUI stuff to get pixel correct alignment of\n                        // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time.\n                        pos = new Vector2(pos.x, Mathf.Floor(pos.y));\n\n                        float uiValue = ticks[i];\n                        Rect labelRect;\n                        if (settings.vTickStyle.centerLabel)\n                            labelRect = new Rect(0, pos.y - 8, leftmargin - 4, 16);  // text expands to the left starting from where grid starts (leftmargin size must ensure text is visible)\n                        else\n                            labelRect = new Rect(0, pos.y - 13, labelSize, 16);     // text expands to the right starting from left side of window\n\n\n                        GUI.Label(labelRect, uiValue.ToString(format) + settings.vTickStyle.unit, Styles.labelTickMarksY);\n                    }\n                }\n            }\n            // Cleanup\n            GUI.color = tempCol;\n\n            GUI.EndClip();\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/CurveEditorRectangleTool.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\n\nusing RectangleToolFlags = UnityEditor.CurveEditorSettings.RectangleToolFlags;\n\nnamespace UnityEditor\n{\n    internal class CurveEditorRectangleTool : RectangleTool\n    {\n        const int kHBarMinWidth = 14;\n        const int kHBarHeight = 13;\n\n        const int kHBarLeftWidth = 15;\n        const int kHBarLeftHeight = 13;\n        const int kHBarRightWidth = 15;\n        const int kHBarRightHeight = 13;\n\n        const int kHLabelMarginHorizontal = 3;\n        const int kHLabelMarginVertical = 1;\n\n        const int kVBarMinHeight = 15;\n        const int kVBarWidth = 13;\n\n        const int kVBarBottomWidth = 13;\n        const int kVBarBottomHeight = 15;\n        const int kVBarTopWidth = 13;\n        const int kVBarTopHeight = 15;\n\n        const int kVLabelMarginHorizontal = 1;\n        const int kVLabelMarginVertical = 2;\n\n        const int kScaleLeftWidth = 17;\n        const int kScaleLeftMarginHorizontal = 0;\n        const float kScaleLeftRatio = 0.80f;\n\n        const int kScaleRightWidth = 17;\n        const int kScaleRightMarginHorizontal = 0;\n        const float kScaleRightRatio = 0.80f;\n\n        const int kScaleBottomHeight = 17;\n        const int kScaleBottomMarginVertical = 0;\n        const float kScaleBottomRatio = 0.80f;\n\n        const int kScaleTopHeight = 17;\n        const int kScaleTopMarginVertical = 0;\n        const float kScaleTopRatio = 0.80f;\n\n        static Rect g_EmptyRect = new Rect(0f, 0f, 0f, 0f);\n\n        struct ToolLayout\n        {\n            public Rect selectionRect;\n\n            public Rect hBarRect;\n            public Rect hBarLeftRect;\n            public Rect hBarRightRect;\n\n            public bool displayHScale;\n\n            public Rect vBarRect;\n            public Rect vBarBottomRect;\n            public Rect vBarTopRect;\n\n            public bool displayVScale;\n\n            public Rect selectionLeftRect;\n            public Rect selectionTopRect;\n\n            public Rect underlayTopRect;\n            public Rect underlayLeftRect;\n\n            public Rect scaleLeftRect;\n            public Rect scaleRightRect;\n            public Rect scaleTopRect;\n            public Rect scaleBottomRect;\n\n            public Vector2 leftLabelAnchor;\n            public Vector2 rightLabelAnchor;\n            public Vector2 bottomLabelAnchor;\n            public Vector2 topLabelAnchor;\n        }\n\n        private CurveEditor m_CurveEditor;\n\n        private ToolLayout m_Layout;\n\n        private Vector2 m_Pivot;\n        private Vector2 m_Previous;\n        private Vector2 m_MouseOffset;\n\n        enum DragMode\n        {\n            None = 0,\n            MoveHorizontal = 1 << 0,\n            MoveVertical = 1 << 1,\n            MoveBothAxis = MoveHorizontal | MoveVertical,\n            ScaleHorizontal = 1 << 2,\n            ScaleVertical = 1 << 3,\n            ScaleBothAxis = ScaleHorizontal | ScaleVertical,\n            MoveScaleHorizontal = MoveHorizontal | ScaleHorizontal,\n            MoveScaleVertical = MoveVertical | ScaleVertical\n        }\n\n        private DragMode m_DragMode;\n        private bool m_RippleTime;\n        private float m_RippleTimeStart;\n        private float m_RippleTimeEnd;\n\n        private AreaManipulator m_HBarLeft;\n        private AreaManipulator m_HBarRight;\n        private AreaManipulator m_HBar;\n\n        private AreaManipulator m_VBarBottom;\n        private AreaManipulator m_VBarTop;\n        private AreaManipulator m_VBar;\n\n        private AreaManipulator m_SelectionBox;\n\n        private AreaManipulator m_SelectionScaleLeft;\n        private AreaManipulator m_SelectionScaleRight;\n\n        private AreaManipulator m_SelectionRippleLeft;\n        private AreaManipulator m_SelectionRippleRight;\n\n        private AreaManipulator m_SelectionScaleBottom;\n        private AreaManipulator m_SelectionScaleTop;\n\n        private bool hasSelection { get { return m_CurveEditor.hasSelection && !m_CurveEditor.IsDraggingCurveOrRegion(); } }\n        private Bounds selectionBounds { get { return m_CurveEditor.selectionBounds; } }\n\n        private float frameRate { get { return m_CurveEditor.invSnap; } }\n        private bool rippleTime { get { return m_CurveEditor.rippleTime; } }\n\n        private DragMode dragMode\n        {\n            get\n            {\n                if (m_DragMode != DragMode.None)\n                    return m_DragMode;\n\n                if (m_CurveEditor.IsDraggingKey())\n                    return DragMode.MoveBothAxis;\n\n                return DragMode.None;\n            }\n        }\n\n        public override void Initialize(TimeArea timeArea)\n        {\n            base.Initialize(timeArea);\n            m_CurveEditor = timeArea as CurveEditor;\n\n            if (m_HBarLeft == null)\n            {\n                m_HBarLeft = new AreaManipulator(styles.rectangleToolHBarLeft, MouseCursor.ResizeHorizontal);\n\n                m_HBarLeft.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartScale(ToolCoord.Right, ToolCoord.Left, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), DragMode.ScaleHorizontal, rippleTime);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_HBarLeft.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate));\n                    return true;\n                };\n                m_HBarLeft.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndScale();\n                    return true;\n                };\n            }\n\n            if (m_HBarRight == null)\n            {\n                m_HBarRight = new AreaManipulator(styles.rectangleToolHBarRight, MouseCursor.ResizeHorizontal);\n\n                m_HBarRight.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartScale(ToolCoord.Left, ToolCoord.Right, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), DragMode.ScaleHorizontal, rippleTime);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_HBarRight.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate));\n                    return true;\n                };\n                m_HBarRight.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndScale();\n                    return true;\n                };\n            }\n\n            if (m_HBar == null)\n            {\n                m_HBar = new AreaManipulator(styles.rectangleToolHBar, MouseCursor.MoveArrow);\n\n                m_HBar.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartMove(new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), DragMode.MoveHorizontal, rippleTime);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_HBar.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnMove(new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f));\n                    return true;\n                };\n                m_HBar.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndMove();\n                    return true;\n                };\n            }\n\n            if (m_VBarBottom == null)\n            {\n                m_VBarBottom = new AreaManipulator(styles.rectangleToolVBarBottom, MouseCursor.ResizeVertical);\n\n                m_VBarBottom.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartScale(ToolCoord.Top, ToolCoord.Bottom, new Vector2(0f, PixelToValue(evt.mousePosition.y)), DragMode.ScaleVertical, false);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_VBarBottom.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnScaleValue(PixelToValue(evt.mousePosition.y));\n                    return true;\n                };\n                m_VBarBottom.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndScale();\n                    return true;\n                };\n            }\n\n            if (m_VBarTop == null)\n            {\n                m_VBarTop = new AreaManipulator(styles.rectangleToolVBarTop, MouseCursor.ResizeVertical);\n\n                m_VBarTop.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartScale(ToolCoord.Bottom, ToolCoord.Top, new Vector2(0f, PixelToValue(evt.mousePosition.y)), DragMode.ScaleVertical, false);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_VBarTop.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnScaleValue(PixelToValue(evt.mousePosition.y));\n                    return true;\n                };\n                m_VBarTop.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndScale();\n                    return true;\n                };\n            }\n\n            if (m_VBar == null)\n            {\n                m_VBar = new AreaManipulator(styles.rectangleToolVBar, MouseCursor.MoveArrow);\n\n                m_VBar.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartMove(new Vector2(0f, PixelToValue(evt.mousePosition.y)), DragMode.MoveVertical, false);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_VBar.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnMove(new Vector2(0f, PixelToValue(evt.mousePosition.y)));\n                    return true;\n                };\n                m_VBar.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndMove();\n                    return true;\n                };\n            }\n\n            if (m_SelectionBox == null)\n            {\n                m_SelectionBox = new AreaManipulator(styles.rectangleToolSelection, MouseCursor.MoveArrow);\n\n                m_SelectionBox.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    bool curveEditorOverride = evt.shift || EditorGUI.actionKey;\n                    if (!curveEditorOverride && hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartMove(new Vector2(PixelToTime(evt.mousePosition.x, frameRate), PixelToValue(evt.mousePosition.y)), DragMode.MoveBothAxis, rippleTime);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_SelectionBox.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    // Only drag along x OR y when shift is held down\n                    if (evt.shift && m_DragMode == DragMode.MoveBothAxis)\n                    {\n                        float deltaX = evt.mousePosition.x - TimeToPixel(m_Previous.x);\n                        float deltaY = evt.mousePosition.y - ValueToPixel(m_Previous.y);\n                        m_DragMode = Mathf.Abs(deltaX) > Mathf.Abs(deltaY) ? DragMode.MoveHorizontal : DragMode.MoveVertical;\n                    }\n\n                    float posX = ((m_DragMode & DragMode.MoveHorizontal) != 0) ? PixelToTime(evt.mousePosition.x, frameRate) : m_Previous.x;\n                    float posY = ((m_DragMode & DragMode.MoveVertical) != 0) ? PixelToValue(evt.mousePosition.y) : m_Previous.y;\n\n                    OnMove(new Vector2(posX, posY));\n                    return true;\n                };\n                m_SelectionBox.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndMove();\n                    return true;\n                };\n            }\n\n            if (m_SelectionScaleLeft == null)\n            {\n                m_SelectionScaleLeft = new AreaManipulator(styles.rectangleToolScaleLeft, MouseCursor.ResizeHorizontal);\n\n                m_SelectionScaleLeft.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartScale(ToolCoord.Right, ToolCoord.Left, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), DragMode.ScaleHorizontal, false);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_SelectionScaleLeft.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate));\n                    return true;\n                };\n                m_SelectionScaleLeft.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndScale();\n                    return true;\n                };\n            }\n\n            if (m_SelectionScaleRight == null)\n            {\n                m_SelectionScaleRight = new AreaManipulator(styles.rectangleToolScaleRight, MouseCursor.ResizeHorizontal);\n\n                m_SelectionScaleRight.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartScale(ToolCoord.Left, ToolCoord.Right, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), DragMode.ScaleHorizontal, false);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_SelectionScaleRight.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate));\n                    return true;\n                };\n                m_SelectionScaleRight.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndScale();\n                    return true;\n                };\n            }\n\n            if (m_SelectionRippleLeft == null)\n            {\n                m_SelectionRippleLeft = new AreaManipulator(styles.rectangleToolRippleLeft, MouseCursor.ResizeHorizontal);\n\n                m_SelectionRippleLeft.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartScale(ToolCoord.Right, ToolCoord.Left, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), DragMode.ScaleHorizontal, true);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_SelectionRippleLeft.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate));\n                    return true;\n                };\n                m_SelectionRippleLeft.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndScale();\n                    return true;\n                };\n            }\n\n            if (m_SelectionRippleRight == null)\n            {\n                m_SelectionRippleRight = new AreaManipulator(styles.rectangleToolRippleRight, MouseCursor.ResizeHorizontal);\n\n                m_SelectionRippleRight.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartScale(ToolCoord.Left, ToolCoord.Right, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), DragMode.ScaleHorizontal, true);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_SelectionRippleRight.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate));\n                    return true;\n                };\n                m_SelectionRippleRight.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndScale();\n                    return true;\n                };\n            }\n\n            if (m_SelectionScaleBottom == null)\n            {\n                m_SelectionScaleBottom = new AreaManipulator(styles.rectangleToolScaleBottom, MouseCursor.ResizeVertical);\n\n                m_SelectionScaleBottom.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartScale(ToolCoord.Top, ToolCoord.Bottom, new Vector2(0f, PixelToValue(evt.mousePosition.y)), DragMode.ScaleVertical, false);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_SelectionScaleBottom.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnScaleValue(PixelToValue(evt.mousePosition.y));\n                    return true;\n                };\n                m_SelectionScaleBottom.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndScale();\n                    return true;\n                };\n            }\n\n            if (m_SelectionScaleTop == null)\n            {\n                m_SelectionScaleTop = new AreaManipulator(styles.rectangleToolScaleTop, MouseCursor.ResizeVertical);\n\n                m_SelectionScaleTop.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartScale(ToolCoord.Bottom, ToolCoord.Top, new Vector2(0f, PixelToValue(evt.mousePosition.y)), DragMode.ScaleVertical, false);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_SelectionScaleTop.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnScaleValue(PixelToValue(evt.mousePosition.y));\n                    return true;\n                };\n                m_SelectionScaleTop.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndScale();\n                    return true;\n                };\n            }\n        }\n\n        public void OnGUI()\n        {\n            if (!hasSelection)\n                return;\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            RectangleToolFlags flags = m_CurveEditor.settings.rectangleToolFlags;\n            if (flags == RectangleToolFlags.NoRectangleTool)\n                return;\n\n            Color oldColor = GUI.color;\n            GUI.color = Color.white;\n\n            m_Layout = CalculateLayout();\n\n            if (flags == RectangleToolFlags.FullRectangleTool)\n            {\n                GUI.Label(m_Layout.selectionLeftRect, GUIContent.none, styles.rectangleToolHighlight);\n                GUI.Label(m_Layout.selectionTopRect, GUIContent.none, styles.rectangleToolHighlight);\n                GUI.Label(m_Layout.underlayLeftRect, GUIContent.none, styles.rectangleToolHighlight);\n                GUI.Label(m_Layout.underlayTopRect, GUIContent.none, styles.rectangleToolHighlight);\n            }\n\n            m_SelectionBox.OnGUI(m_Layout.selectionRect);\n\n            m_SelectionScaleTop.OnGUI(m_Layout.scaleTopRect);\n            m_SelectionScaleBottom.OnGUI(m_Layout.scaleBottomRect);\n\n            bool showRippleHandles = (rippleTime && dragMode == DragMode.None) || (m_RippleTime && dragMode != DragMode.None);\n\n            if (showRippleHandles)\n            {\n                m_SelectionRippleLeft.OnGUI(m_Layout.scaleLeftRect);\n                m_SelectionRippleRight.OnGUI(m_Layout.scaleRightRect);\n            }\n            else\n            {\n                m_SelectionScaleLeft.OnGUI(m_Layout.scaleLeftRect);\n                m_SelectionScaleRight.OnGUI(m_Layout.scaleRightRect);\n            }\n\n            GUI.color = oldColor;\n        }\n\n        public void OverlayOnGUI(Rect bounds)\n        {\n            if (!hasSelection)\n                return;\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            Color oldColor = GUI.color;\n\n            RectangleToolFlags flags = m_CurveEditor.settings.rectangleToolFlags;\n            if (flags == RectangleToolFlags.FullRectangleTool)\n            {\n                GUI.color = Color.white;\n\n                m_HBar.OnGUI(m_Layout.hBarRect);\n                m_HBarLeft.OnGUI(m_Layout.hBarLeftRect);\n                m_HBarRight.OnGUI(m_Layout.hBarRightRect);\n\n                m_VBar.OnGUI(m_Layout.vBarRect);\n                m_VBarBottom.OnGUI(m_Layout.vBarBottomRect);\n                m_VBarTop.OnGUI(m_Layout.vBarTopRect);\n            }\n\n            DrawLabels(bounds);\n\n            GUI.color = oldColor;\n        }\n\n        public void HandleEvents()\n        {\n            RectangleToolFlags flags = m_CurveEditor.settings.rectangleToolFlags;\n            if (flags == RectangleToolFlags.NoRectangleTool)\n                return;\n\n            m_SelectionScaleTop.HandleEvents();\n            m_SelectionScaleBottom.HandleEvents();\n\n            if (rippleTime)\n            {\n                m_SelectionRippleLeft.HandleEvents();\n                m_SelectionRippleRight.HandleEvents();\n            }\n            else\n            {\n                m_SelectionScaleLeft.HandleEvents();\n                m_SelectionScaleRight.HandleEvents();\n            }\n\n            m_SelectionBox.HandleEvents();\n        }\n\n        public void HandleOverlayEvents()\n        {\n            RectangleToolFlags flags = m_CurveEditor.settings.rectangleToolFlags;\n            if (flags == RectangleToolFlags.NoRectangleTool)\n                return;\n\n            if (flags == RectangleToolFlags.FullRectangleTool)\n            {\n                m_VBarBottom.HandleEvents();\n                m_VBarTop.HandleEvents();\n                m_VBar.HandleEvents();\n\n                m_HBarLeft.HandleEvents();\n                m_HBarRight.HandleEvents();\n                m_HBar.HandleEvents();\n            }\n        }\n\n        private ToolLayout CalculateLayout()\n        {\n            ToolLayout layout = new ToolLayout();\n\n            bool canScaleX = !Mathf.Approximately(selectionBounds.size.x, 0f);\n            bool canScaleY = !Mathf.Approximately(selectionBounds.size.y, 0f);\n\n            float xMin = TimeToPixel(selectionBounds.min.x);\n            float xMax = TimeToPixel(selectionBounds.max.x);\n\n            float yMin = ValueToPixel(selectionBounds.max.y);\n            float yMax = ValueToPixel(selectionBounds.min.y);\n\n            layout.selectionRect = new Rect(xMin, yMin, xMax - xMin, yMax - yMin);\n\n            // Horizontal layout\n            layout.displayHScale = true;\n            float dragHorizWidth = layout.selectionRect.width - kHBarLeftWidth - kHBarRightWidth;\n\n            if (dragHorizWidth < kHBarMinWidth)\n            {\n                layout.displayHScale = false;\n\n                dragHorizWidth = layout.selectionRect.width;\n                if (dragHorizWidth < kHBarMinWidth)\n                {\n                    layout.selectionRect.x = layout.selectionRect.center.x - kHBarMinWidth * 0.5f;\n                    layout.selectionRect.width = kHBarMinWidth;\n\n                    dragHorizWidth = kHBarMinWidth;\n                }\n            }\n\n            if (layout.displayHScale)\n            {\n                layout.hBarLeftRect = new Rect(layout.selectionRect.xMin, contentRect.yMin, kHBarLeftWidth, kHBarLeftHeight);\n                layout.hBarRect = new Rect(layout.hBarLeftRect.xMax, contentRect.yMin, dragHorizWidth, kHBarHeight);\n                layout.hBarRightRect = new Rect(layout.hBarRect.xMax, contentRect.yMin, kHBarLeftWidth, kHBarRightHeight);\n            }\n            else\n            {\n                layout.hBarRect = new Rect(layout.selectionRect.xMin, contentRect.yMin, dragHorizWidth, kHBarHeight);\n\n                layout.hBarLeftRect = new Rect(0f, 0f, 0f, 0f);\n                layout.hBarRightRect = new Rect(0f, 0f, 0f, 0f);\n            }\n\n            // Vertical layout\n            layout.displayVScale = true;\n            float dragVertHeight = layout.selectionRect.height - kVBarBottomHeight - kVBarTopHeight;\n\n            if (dragVertHeight < kVBarMinHeight)\n            {\n                layout.displayVScale = false;\n\n                dragVertHeight = layout.selectionRect.height;\n                if (dragVertHeight < kVBarMinHeight)\n                {\n                    layout.selectionRect.y = layout.selectionRect.center.y - kVBarMinHeight * 0.5f;\n                    layout.selectionRect.height = kVBarMinHeight;\n\n                    dragVertHeight = kVBarMinHeight;\n                }\n            }\n\n            if (layout.displayVScale)\n            {\n                layout.vBarTopRect = new Rect(contentRect.xMin, layout.selectionRect.yMin, kVBarTopWidth, kVBarTopHeight);\n                layout.vBarRect = new Rect(contentRect.xMin, layout.vBarTopRect.yMax, kVBarWidth, dragVertHeight);\n                layout.vBarBottomRect = new Rect(contentRect.xMin, layout.vBarRect.yMax, kVBarBottomWidth, kVBarBottomHeight);\n            }\n            else\n            {\n                layout.vBarRect = new Rect(contentRect.xMin, layout.selectionRect.yMin, kVBarWidth, dragVertHeight);\n\n                layout.vBarTopRect = g_EmptyRect;\n                layout.vBarBottomRect = g_EmptyRect;\n            }\n\n            // Scale handles.\n            if (canScaleX)\n            {\n                float leftRatio = (1.0f - kScaleLeftRatio) * 0.5f;\n                float rightRatio = (1.0f - kScaleRightRatio) * 0.5f;\n\n                layout.scaleLeftRect = new Rect(layout.selectionRect.xMin - kScaleLeftMarginHorizontal - kScaleLeftWidth, layout.selectionRect.yMin + layout.selectionRect.height * leftRatio, kScaleLeftWidth, layout.selectionRect.height * kScaleLeftRatio);\n                layout.scaleRightRect = new Rect(layout.selectionRect.xMax + kScaleRightMarginHorizontal, layout.selectionRect.yMin + layout.selectionRect.height * rightRatio, kScaleRightWidth, layout.selectionRect.height * kScaleRightRatio);\n            }\n            else\n            {\n                layout.scaleLeftRect = g_EmptyRect;\n                layout.scaleRightRect = g_EmptyRect;\n            }\n\n            if (canScaleY)\n            {\n                float bottomRatio = (1.0f - kScaleBottomRatio) * 0.5f;\n                float topRatio = (1.0f - kScaleTopRatio) * 0.5f;\n\n                layout.scaleTopRect = new Rect(layout.selectionRect.xMin + layout.selectionRect.width * topRatio, layout.selectionRect.yMin - kScaleTopMarginVertical - kScaleTopHeight, layout.selectionRect.width * kScaleTopRatio, kScaleTopHeight);\n                layout.scaleBottomRect = new Rect(layout.selectionRect.xMin + layout.selectionRect.width * bottomRatio, layout.selectionRect.yMax + kScaleBottomMarginVertical, layout.selectionRect.width * kScaleBottomRatio, kScaleBottomHeight);\n            }\n            else\n            {\n                layout.scaleTopRect = g_EmptyRect;\n                layout.scaleBottomRect = g_EmptyRect;\n            }\n\n            // Labels.\n            if (canScaleX)\n            {\n                layout.leftLabelAnchor = new Vector2(layout.selectionRect.xMin - kHLabelMarginHorizontal, contentRect.yMin + kHLabelMarginVertical);\n                layout.rightLabelAnchor = new Vector2(layout.selectionRect.xMax + kHLabelMarginHorizontal, contentRect.yMin + kHLabelMarginVertical);\n            }\n            else\n            {\n                layout.leftLabelAnchor = layout.rightLabelAnchor = new Vector2(layout.selectionRect.xMax + kHLabelMarginHorizontal, contentRect.yMin + kHLabelMarginVertical);\n            }\n\n            if (canScaleY)\n            {\n                layout.bottomLabelAnchor = new Vector2(contentRect.xMin + kVLabelMarginHorizontal, layout.selectionRect.yMax + kVLabelMarginVertical);\n                layout.topLabelAnchor = new Vector2(contentRect.xMin + kVLabelMarginHorizontal, layout.selectionRect.yMin - kVLabelMarginVertical);\n            }\n            else\n            {\n                layout.bottomLabelAnchor = layout.topLabelAnchor = new Vector2(contentRect.xMin + kVLabelMarginHorizontal, layout.selectionRect.yMin - kVLabelMarginVertical);\n            }\n\n            // Extra ui.\n            layout.selectionLeftRect = new Rect(contentRect.xMin + kVBarWidth, layout.selectionRect.yMin, layout.selectionRect.xMin - kVBarWidth, layout.selectionRect.height);\n            layout.selectionTopRect = new Rect(layout.selectionRect.xMin, contentRect.yMin + kHBarHeight, layout.selectionRect.width, layout.selectionRect.yMin - kHBarHeight);\n\n            layout.underlayTopRect = new Rect(contentRect.xMin, contentRect.yMin, contentRect.width, kHBarHeight);\n            layout.underlayLeftRect = new Rect(contentRect.xMin, contentRect.yMin + kHBarHeight, kVBarWidth, contentRect.height - kHBarHeight);\n\n            return layout;\n        }\n\n        private void DrawLabels(Rect bounds)\n        {\n            if (dragMode == DragMode.None)\n                return;\n\n            RectangleToolFlags flags = m_CurveEditor.settings.rectangleToolFlags;\n\n            bool canScaleX = !Mathf.Approximately(selectionBounds.size.x, 0f);\n            bool canScaleY = !Mathf.Approximately(selectionBounds.size.y, 0f);\n\n            if (flags == RectangleToolFlags.FullRectangleTool)\n            {\n                // Horizontal labels\n                if ((dragMode & DragMode.MoveScaleHorizontal) != 0)\n                {\n                    if (canScaleX)\n                    {\n                        GUIContent leftLabelContent = new GUIContent(string.Format(\"{0}\", m_CurveEditor.FormatTime(selectionBounds.min.x, m_CurveEditor.invSnap, m_CurveEditor.timeFormat)));\n                        GUIContent rightLabelContent = new GUIContent(string.Format(\"{0}\", m_CurveEditor.FormatTime(selectionBounds.max.x, m_CurveEditor.invSnap, m_CurveEditor.timeFormat)));\n\n                        Vector2 leftLabelSize = styles.dragLabel.CalcSize(leftLabelContent);\n                        Vector2 rightLabelSize = styles.dragLabel.CalcSize(rightLabelContent);\n\n                        EditorGUI.DoDropShadowLabel(new Rect(m_Layout.leftLabelAnchor.x - leftLabelSize.x, m_Layout.leftLabelAnchor.y, leftLabelSize.x, leftLabelSize.y), leftLabelContent, styles.dragLabel, 0.3f);\n                        EditorGUI.DoDropShadowLabel(new Rect(m_Layout.rightLabelAnchor.x, m_Layout.rightLabelAnchor.y, rightLabelSize.x, rightLabelSize.y), rightLabelContent, styles.dragLabel, 0.3f);\n                    }\n                    else\n                    {\n                        GUIContent labelContent = new GUIContent(string.Format(\"{0}\", m_CurveEditor.FormatTime(selectionBounds.center.x, m_CurveEditor.invSnap, m_CurveEditor.timeFormat)));\n                        Vector2 labelSize = styles.dragLabel.CalcSize(labelContent);\n                        EditorGUI.DoDropShadowLabel(new Rect(m_Layout.leftLabelAnchor.x, m_Layout.leftLabelAnchor.y, labelSize.x, labelSize.y), labelContent, styles.dragLabel, 0.3f);\n                    }\n                }\n\n                // Vertical labels\n                if ((dragMode & DragMode.MoveScaleVertical) != 0)\n                {\n                    if (canScaleY)\n                    {\n                        GUIContent bottomLabelContent = new GUIContent(string.Format(\"{0}\", m_CurveEditor.FormatValue(selectionBounds.min.y)));\n                        GUIContent topLabelContent = new GUIContent(string.Format(\"{0}\", m_CurveEditor.FormatValue(selectionBounds.max.y)));\n\n                        Vector2 bottomLabelSize = styles.dragLabel.CalcSize(bottomLabelContent);\n                        Vector2 topLabelSize = styles.dragLabel.CalcSize(topLabelContent);\n\n                        EditorGUI.DoDropShadowLabel(new Rect(m_Layout.bottomLabelAnchor.x, m_Layout.bottomLabelAnchor.y, bottomLabelSize.x, bottomLabelSize.y), bottomLabelContent, styles.dragLabel, 0.3f);\n                        EditorGUI.DoDropShadowLabel(new Rect(m_Layout.topLabelAnchor.x, m_Layout.topLabelAnchor.y - topLabelSize.y, topLabelSize.x, topLabelSize.y), topLabelContent, styles.dragLabel, 0.3f);\n                    }\n                    else\n                    {\n                        GUIContent labelContent = new GUIContent(string.Format(\"{0}\", m_CurveEditor.FormatValue(selectionBounds.center.y)));\n                        Vector2 labelSize = styles.dragLabel.CalcSize(labelContent);\n\n                        EditorGUI.DoDropShadowLabel(new Rect(m_Layout.topLabelAnchor.x, m_Layout.topLabelAnchor.y - labelSize.y, labelSize.x, labelSize.y), labelContent, styles.dragLabel, 0.3f);\n                    }\n                }\n            }\n            else if (flags == RectangleToolFlags.MiniRectangleTool)\n            {\n                if ((dragMode & DragMode.MoveBothAxis) != 0)\n                {\n                    Vector2 localPosition = (canScaleX || canScaleY) ? new Vector2(PixelToTime(Event.current.mousePosition.x, frameRate), PixelToValue(Event.current.mousePosition.y)) : (Vector2)selectionBounds.center;\n                    Vector2 labelPosition = new Vector2(TimeToPixel(localPosition.x), ValueToPixel(localPosition.y));\n\n                    GUIContent labelContent = new GUIContent(string.Format(\"{0}, {1}\", m_CurveEditor.FormatTime(localPosition.x, m_CurveEditor.invSnap, m_CurveEditor.timeFormat), m_CurveEditor.FormatValue(localPosition.y)));\n                    Vector2 labelSize = styles.dragLabel.CalcSize(labelContent);\n\n                    // Clamp popup to remain inside the curve editor window\n                    var labelRect = new Rect(labelPosition.x, labelPosition.y - labelSize.y, labelSize.x, labelSize.y);\n                    labelRect.x += Mathf.Max(0.0f, bounds.xMin - labelRect.xMin);\n                    labelRect.x -= Mathf.Max(0.0f, labelRect.xMax - bounds.xMax);\n                    labelRect.y += Mathf.Max(0.0f, bounds.yMin - labelRect.yMin);\n                    labelRect.y -= Mathf.Max(0.0f, labelRect.yMax - bounds.yMax);\n\n                    EditorGUI.DoDropShadowLabel(labelRect, labelContent, styles.dragLabel, 0.3f);\n                }\n            }\n        }\n\n        private void OnStartScale(ToolCoord pivotCoord, ToolCoord pickedCoord, Vector2 mousePos, DragMode dragMode, bool rippleTime)\n        {\n            Bounds bounds = selectionBounds;\n            m_DragMode = dragMode;\n            m_Pivot = ToolCoordToPosition(pivotCoord, bounds);\n            m_Previous = ToolCoordToPosition(pickedCoord, bounds);\n            m_MouseOffset = mousePos - m_Previous;\n            m_RippleTime = rippleTime;\n            m_RippleTimeStart = bounds.min.x;\n            m_RippleTimeEnd = bounds.max.x;\n\n            m_CurveEditor.StartLiveEdit();\n        }\n\n        private void OnScaleTime(float time)\n        {\n            Matrix4x4 transform;\n            bool flipX;\n            if (CalculateScaleTimeMatrix(m_Previous.x, time, m_MouseOffset.x, m_Pivot.x, frameRate, out transform, out flipX))\n                TransformKeys(transform, flipX, false);\n        }\n\n        private void OnScaleValue(float val)\n        {\n            Matrix4x4 transform;\n            bool flipY;\n            if (CalculateScaleValueMatrix(m_Previous.y, val, m_MouseOffset.y, m_Pivot.y, out transform, out flipY))\n                TransformKeys(transform, false, flipY);\n        }\n\n        private void OnEndScale()\n        {\n            m_CurveEditor.EndLiveEdit();\n            m_DragMode = DragMode.None;\n            GUI.changed = true;\n        }\n\n        internal void OnStartMove(Vector2 position, bool rippleTime)\n        {\n            OnStartMove(position, DragMode.None, rippleTime);\n        }\n\n        private void OnStartMove(Vector2 position, DragMode dragMode, bool rippleTime)\n        {\n            Bounds bounds = selectionBounds;\n\n            m_DragMode = dragMode;\n            m_Previous = position;\n            m_RippleTime = rippleTime;\n            m_RippleTimeStart = bounds.min.x;\n            m_RippleTimeEnd = bounds.max.x;\n\n            m_CurveEditor.StartLiveEdit();\n        }\n\n        internal void OnMove(Vector2 position)\n        {\n            Vector2 dv = position - m_Previous;\n\n            Matrix4x4 transform = Matrix4x4.identity;\n            transform.SetTRS(new Vector3(dv.x, dv.y, 0f), Quaternion.identity, Vector3.one);\n\n            TransformKeys(transform, false, false);\n        }\n\n        internal void OnEndMove()\n        {\n            m_CurveEditor.EndLiveEdit();\n            m_DragMode = DragMode.None;\n            GUI.changed = true;\n        }\n\n        private void TransformKeys(Matrix4x4 matrix, bool flipX, bool flipY)\n        {\n            if (m_RippleTime)\n            {\n                m_CurveEditor.TransformRippleKeys(matrix, m_RippleTimeStart, m_RippleTimeEnd, flipX, flipY);\n                GUI.changed = true;\n            }\n            else\n            {\n                m_CurveEditor.TransformSelectedKeys(matrix, flipX, flipY);\n                GUI.changed = true;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/CurveEditorSelection.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing System.Collections;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    internal class CurveEditorSelection : ScriptableObject\n    {\n        [SerializeField] private List<CurveSelection> m_SelectedCurves;\n\n        public List<CurveSelection> selectedCurves\n        {\n            get { return m_SelectedCurves ?? (m_SelectedCurves = new List<CurveSelection>()); }\n            set { m_SelectedCurves = value; }\n        }\n    }\n\n    [System.Serializable]\n    internal class CurveSelection : System.IComparable\n    {\n        internal enum SelectionType\n        {\n            Key = 0,\n            InTangent = 1,\n            OutTangent = 2,\n            Count = 3,\n        }\n\n        [SerializeField] public int curveID = 0;\n        [SerializeField] public int key = -1;\n        [SerializeField] public bool semiSelected = false;\n        [SerializeField] public SelectionType type;\n\n        internal CurveSelection(int curveID, int key)\n        {\n            this.curveID = curveID;\n            this.key = key;\n            this.type = SelectionType.Key;\n        }\n\n        internal CurveSelection(int curveID, int key, SelectionType type)\n        {\n            this.curveID = curveID;\n            this.key = key;\n            this.type = type;\n        }\n\n        public int CompareTo(object _other)\n        {\n            CurveSelection other = (CurveSelection)_other;\n            int cmp = curveID - other.curveID;\n            if (cmp != 0)\n                return cmp;\n\n            cmp = key - other.key;\n            if (cmp != 0)\n                return cmp;\n\n            return (int)type - (int)other.type;\n        }\n\n        public override bool Equals(object _other)\n        {\n            CurveSelection other = _other as CurveSelection;\n            if (ReferenceEquals(other, null))\n                return false;\n            if (ReferenceEquals(other, this))\n                return true;\n            return other.curveID == curveID && other.key == key && other.type == type;\n        }\n\n        public override int GetHashCode()\n        {\n            return curveID * 729 + key * 27 + (int)type;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/CurveEditorSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    internal class CurveEditorSettings\n    {\n        // Label settings\n        private TickStyle m_HTickStyle = new TickStyle();\n        private TickStyle m_VTickStyle = new TickStyle();\n\n        internal TickStyle hTickStyle { get { return m_HTickStyle; } set { m_HTickStyle = value; } }\n        internal TickStyle vTickStyle { get { return m_VTickStyle; } set { m_VTickStyle = value; } }\n\n        // Range lock settings\n        private bool m_HRangeLocked;\n        private bool m_VRangeLocked;\n        internal bool hRangeLocked { get { return m_HRangeLocked; } set { m_HRangeLocked = value; } }\n        internal bool vRangeLocked { get { return m_VRangeLocked; } set { m_VRangeLocked = value; } }\n\n        // Range settings\n        private float m_HRangeMin = Mathf.NegativeInfinity;\n        private float m_HRangeMax = Mathf.Infinity;\n        private float m_VRangeMin = Mathf.NegativeInfinity;\n        private float m_VRangeMax = Mathf.Infinity;\n        public float hRangeMin { get { return m_HRangeMin; } set { m_HRangeMin = value; } }\n        public float hRangeMax { get { return m_HRangeMax; } set { m_HRangeMax = value; } }\n        public float vRangeMin { get { return m_VRangeMin; } set { m_VRangeMin = value; } }\n        public float vRangeMax { get { return m_VRangeMax; } set { m_VRangeMax = value; } }\n        public bool hasUnboundedRanges\n        {\n            get\n            {\n                return\n                    m_HRangeMin == Mathf.NegativeInfinity ||\n                    m_HRangeMax == Mathf.Infinity ||\n                    m_VRangeMin == Mathf.NegativeInfinity ||\n                    m_VRangeMax == Mathf.Infinity;\n            }\n        }\n\n        // Offset to move the labels along the horizontal axis to make room for the overlaid scrollbar in the\n        // curve editor popup.\n        public float hTickLabelOffset = 0;\n        public EditorGUIUtility.SkinnedColor wrapColor = new EditorGUIUtility.SkinnedColor(new Color(1.0f, 1.0f, 1.0f, 0.5f), new Color(.65f, .65f, .65f, 0.5f));\n        public bool useFocusColors = false;\n        public bool showAxisLabels = true;\n        public bool showWrapperPopups = false;\n        public bool allowDraggingCurvesAndRegions = true;\n        public bool allowDeleteLastKeyInCurve = false;\n        public bool undoRedoSelection = false;\n        public bool flushCurveCache = true;\n        public string xAxisLabel = L10n.Tr(\"time\");\n        public string yAxisLabel = L10n.Tr(\"value\");\n        public Vector2 curveRegionDomain = new Vector2(0, 1); // X axis range in which to draw the shaded curve region between 2 curves.\n        public bool rippleTime = false;\n\n        // Display options\n        internal enum RectangleToolFlags\n        {\n            NoRectangleTool,\n            MiniRectangleTool,\n            FullRectangleTool\n        }\n\n        internal RectangleToolFlags rectangleToolFlags = RectangleToolFlags.NoRectangleTool;\n\n        // Window resize settings\n        private bool m_ScaleWithWindow = true;\n        internal bool scaleWithWindow { get { return m_ScaleWithWindow; } set { m_ScaleWithWindow = value; } }\n\n        // Slider settings\n        private bool m_HSlider = true;\n        private bool m_VSlider = true;\n        public bool hSlider { get { return m_HSlider; } set { m_HSlider = value; } }\n        public bool vSlider { get { return m_VSlider; } set { m_VSlider = value; } }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/CurveEditorWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditor.ShortcutManagement;\nusing System.Linq;\n\nusing TangentMode = UnityEditor.AnimationUtility.TangentMode;\n\nnamespace UnityEditor\n{\n    internal enum WrapModeFixedCurve\n    {\n        Clamp = (int)WrapMode.ClampForever,\n        Loop = (int)WrapMode.Loop,\n        PingPong = (int)WrapMode.PingPong\n    }\n\n    [Serializable]\n    internal class CurveEditorWindow : EditorWindow\n    {\n        public enum NormalizationMode\n        {\n            None = 0,\n            Normalize = 1,\n            Denormalize = 2,\n        }\n\n        //const int kToolbarHeight = 17;\n        const int kPresetsHeight = 50;\n\n        static CurveEditorWindow s_SharedCurveEditor;\n\n        internal CurveEditor m_CurveEditor;\n\n        Vector2 m_PresetScrollPosition;\n        AnimationCurve m_Curve;\n        Color m_Color;\n\n        CurvePresetsContentsForPopupWindow m_CurvePresets;\n        GUIContent m_GUIContent = new GUIContent();\n\n        [SerializeField]\n        GUIView m_DelegateView;\n\n        public const string CurveChangedCommand = \"CurveChanged\";\n        public const string CurveChangeCompletedCommand = \"CurveChangeCompleted\";\n\n        // Watch out when accessing this, it will create a new curve editor window if none exists yet.\n        // If you don't display the window (call Show()), it will cause an error when validating the layout\n        // (e.g. when the user maximizes a window).\n        public static CurveEditorWindow instance\n        {\n            get\n            {\n                if (!s_SharedCurveEditor)\n                    s_SharedCurveEditor = ScriptableObject.CreateInstance<CurveEditorWindow>();\n                return s_SharedCurveEditor;\n            }\n        }\n\n        public string currentPresetLibrary\n        {\n            get\n            {\n                InitCurvePresets();\n                return m_CurvePresets.currentPresetLibrary;\n            }\n            set\n            {\n                InitCurvePresets();\n                m_CurvePresets.currentPresetLibrary = value;\n            }\n        }\n\n        public static AnimationCurve curve\n        {\n            get { return visible ? CurveEditorWindow.instance.m_Curve : null; }\n            set\n            {\n                if (value == null)\n                {\n                    CurveEditorWindow.instance.m_Curve = null;\n                }\n                else\n                {\n                    CurveEditorWindow.instance.m_Curve = value;\n                    CurveEditorWindow.instance.RefreshShownCurves();\n                }\n            }\n        }\n\n        public static Color color\n        {\n            get { return CurveEditorWindow.instance.m_Color; }\n            set\n            {\n                CurveEditorWindow.instance.m_Color = value;\n                CurveEditorWindow.instance.RefreshShownCurves();\n            }\n        }\n\n        internal static GUIView delegateView\n        {\n            get { return visible ? CurveEditorWindow.instance.m_DelegateView : null; }\n        }\n\n        public static bool visible\n        {\n            get { return s_SharedCurveEditor != null; }\n        }\n\n        void OnEnable()\n        {\n            s_SharedCurveEditor = this;\n            Init(null);\n        }\n\n        // Called by OnEnable to make sure the CurveEditor is not null,\n        // and by Show so we get a fresh CurveEditor when the user clicks a new curve.\n        void Init(CurveEditorSettings settings)\n        {\n            m_CurveEditor = new CurveEditor(GetCurveEditorRect(), GetCurveWrapperArray(), true);\n            m_CurveEditor.curvesUpdated = UpdateCurve;\n            m_CurveEditor.scaleWithWindow = true;\n            m_CurveEditor.margin = 40;\n            if (settings != null)\n                m_CurveEditor.settings = settings;\n            m_CurveEditor.settings.hTickLabelOffset = 10;\n            m_CurveEditor.settings.rectangleToolFlags = CurveEditorSettings.RectangleToolFlags.MiniRectangleTool;\n\n            // As there is no guarantee animation curve changes are recorded in undo redo, we can't really\n            // handle curve selection in undo redo either.\n            m_CurveEditor.settings.undoRedoSelection = false;\n            m_CurveEditor.settings.showWrapperPopups = true;\n\n            // For each of horizontal and vertical axis, if we have a finite range for that axis, use that range,\n            // otherwise use framing logic to determine shown range for that axis.\n            bool frameH = true;\n            bool frameV = true;\n            if (m_CurveEditor.settings.hRangeMin != Mathf.NegativeInfinity && m_CurveEditor.settings.hRangeMax != Mathf.Infinity)\n            {\n                m_CurveEditor.SetShownHRangeInsideMargins(m_CurveEditor.settings.hRangeMin, m_CurveEditor.settings.hRangeMax);\n                frameH = false;\n            }\n            if (m_CurveEditor.settings.vRangeMin != Mathf.NegativeInfinity && m_CurveEditor.settings.vRangeMax != Mathf.Infinity)\n            {\n                m_CurveEditor.SetShownVRangeInsideMargins(m_CurveEditor.settings.vRangeMin, m_CurveEditor.settings.vRangeMax);\n                frameV = false;\n            }\n\n            m_CurveEditor.FrameSelected(frameH, frameV);\n\n            titleContent = EditorGUIUtility.TrTextContent(\"Curve\");\n\n            // deal with window size\n            minSize = new Vector2(240, 240 + kPresetsHeight);\n            maxSize = new Vector2(10000, 10000);\n        }\n\n        CurveLibraryType curveLibraryType\n        {\n            get\n            {\n                if (m_CurveEditor.settings.hasUnboundedRanges)\n                    return CurveLibraryType.Unbounded;\n                return CurveLibraryType.NormalizedZeroToOne;\n            }\n        }\n\n        // Returns true if a valid normalizationRect is returned (ranges are bounded)\n        static bool GetNormalizationRect(out Rect normalizationRect, CurveEditor curveEditor)\n        {\n            normalizationRect = new Rect();\n            if (curveEditor.settings.hasUnboundedRanges)\n                return false;\n\n            normalizationRect = new Rect(\n                curveEditor.settings.hRangeMin,\n                curveEditor.settings.vRangeMin,\n                curveEditor.settings.hRangeMax - curveEditor.settings.hRangeMin,\n                curveEditor.settings.vRangeMax - curveEditor.settings.vRangeMin);\n            return true;\n        }\n\n        static Keyframe[] CopyAndScaleCurveKeys(Keyframe[] orgKeys, Rect rect, NormalizationMode normalization)\n        {\n            Keyframe[] scaledKeys = new Keyframe[orgKeys.Length];\n            orgKeys.CopyTo(scaledKeys, 0);\n            if (normalization == NormalizationMode.None)\n                return scaledKeys;\n\n            if (rect.width == 0f || rect.height == 0f || Single.IsInfinity(rect.width) || Single.IsInfinity(rect.height))\n            {\n                Debug.LogError(\"CopyAndScaleCurve: Invalid scale: \" + rect);\n                return scaledKeys;\n            }\n\n            float tangentMultiplier = rect.height / rect.width;\n            switch (normalization)\n            {\n                case NormalizationMode.Normalize:\n                    for (int i = 0; i < scaledKeys.Length; ++i)\n                    {\n                        scaledKeys[i].time = (orgKeys[i].time - rect.xMin) / rect.width;\n                        scaledKeys[i].value = (orgKeys[i].value - rect.yMin) / rect.height;\n                        if (!Single.IsInfinity(orgKeys[i].inTangent))\n                            scaledKeys[i].inTangent = orgKeys[i].inTangent / tangentMultiplier;\n                        if (!Single.IsInfinity(orgKeys[i].outTangent))\n                            scaledKeys[i].outTangent = orgKeys[i].outTangent / tangentMultiplier;\n                    }\n                    break;\n                case NormalizationMode.Denormalize:\n                    // From normalized to real\n                    for (int i = 0; i < scaledKeys.Length; ++i)\n                    {\n                        scaledKeys[i].time = orgKeys[i].time * rect.width + rect.xMin;\n                        scaledKeys[i].value = orgKeys[i].value * rect.height + rect.yMin;\n                        if (!Single.IsInfinity(orgKeys[i].inTangent))\n                            scaledKeys[i].inTangent = orgKeys[i].inTangent * tangentMultiplier;\n                        if (!Single.IsInfinity(orgKeys[i].outTangent))\n                            scaledKeys[i].outTangent = orgKeys[i].outTangent * tangentMultiplier;\n                    }\n                    break;\n            }\n\n            return scaledKeys;\n        }\n\n        void InitCurvePresets()\n        {\n            if (m_CurvePresets == null)\n            {\n                // Selection callback for library window\n                Action<AnimationCurve> presetSelectedCallback = delegate(AnimationCurve presetCurve)\n                {\n                    ValidateCurveLibraryTypeAndScale();\n\n                    // Scale curve up using ranges\n                    m_Curve.keys = GetDenormalizedKeys(presetCurve.keys);\n                    m_Curve.postWrapMode = presetCurve.postWrapMode;\n                    m_Curve.preWrapMode = presetCurve.preWrapMode;\n\n                    m_CurveEditor.SelectNone();\n                    RefreshShownCurves();\n                    SendEvent(CurveChangedCommand, true);\n                };\n\n                // We set the curve to save when showing the popup to ensure to scale the current state of the curve\n                AnimationCurve curveToSaveAsPreset = null;\n                m_CurvePresets = new CurvePresetsContentsForPopupWindow(curveToSaveAsPreset, curveLibraryType, presetSelectedCallback);\n                m_CurvePresets.InitIfNeeded();\n            }\n        }\n\n        void OnDestroy()\n        {\n            if (m_CurvePresets != null)\n                m_CurvePresets.GetPresetLibraryEditor().UnloadUsedLibraries();\n        }\n\n        void OnDisable()\n        {\n            m_CurveEditor.OnDisable();\n            if (s_SharedCurveEditor == this)\n                s_SharedCurveEditor = null;\n            else if (!this.Equals(s_SharedCurveEditor))\n                throw new ApplicationException(\"s_SharedCurveEditor does not equal this\");\n        }\n\n        private void RefreshShownCurves()\n        {\n            m_CurveEditor.animationCurves = GetCurveWrapperArray();\n        }\n\n        public void Show(GUIView viewToUpdate, CurveEditorSettings settings)\n        {\n            m_DelegateView = viewToUpdate;\n            m_OnCurveChanged = null;\n\n            Init(settings);\n            ShowAuxWindow();\n        }\n\n        Action<AnimationCurve> m_OnCurveChanged;\n\n        public void Show(Action<AnimationCurve> onCurveChanged, CurveEditorSettings settings)\n        {\n            m_OnCurveChanged = onCurveChanged;\n            m_DelegateView = null;\n\n            Init(settings);\n            ShowAuxWindow();\n        }\n\n        public void FrameSelected()\n        {\n            m_CurveEditor.FrameSelected(true, true);\n        }\n\n        public void FrameClip()\n        {\n            m_CurveEditor.FrameClip(true, true);\n        }\n\n        internal class Styles\n        {\n            public GUIStyle curveEditorBackground = \"PopupCurveEditorBackground\";\n            public GUIStyle miniToolbarButton = \"MiniToolbarButtonLeft\";\n            public GUIStyle curveSwatch = \"PopupCurveEditorSwatch\";\n            public GUIStyle curveSwatchArea = \"PopupCurveSwatchBackground\";\n        }\n        internal static Styles ms_Styles;\n\n        CurveWrapper[] GetCurveWrapperArray()\n        {\n            if (m_Curve == null)\n                return new CurveWrapper[] {};\n            CurveWrapper cw = new CurveWrapper();\n            cw.id = \"Curve\".GetHashCode();\n            cw.groupId = -1;\n            cw.color = m_Color;\n            cw.hidden = false;\n            cw.readOnly = false;\n            cw.renderer = new NormalCurveRenderer(m_Curve);\n            cw.renderer.SetWrap(m_Curve.preWrapMode, m_Curve.postWrapMode);\n            return new CurveWrapper[] { cw };\n        }\n\n        Rect GetCurveEditorRect()\n        {\n            //return new Rect(0, kToolbarHeight, position.width, position.height-kToolbarHeight);\n            return new Rect(0, 0, position.width, position.height - kPresetsHeight);\n        }\n\n        static internal Keyframe[] GetLinearKeys()\n        {\n            Keyframe[] keys = new Keyframe[2];\n            keys[0] = new Keyframe(0, 0, 1, 1);\n            keys[1] = new Keyframe(1, 1, 1, 1);\n            SetSmoothEditable(ref keys, TangentMode.Auto);\n            return keys;\n        }\n\n        static internal Keyframe[] GetLinearMirrorKeys()\n        {\n            Keyframe[] keys = new Keyframe[2];\n            keys[0] = new Keyframe(0, 1, -1, -1);\n            keys[1] = new Keyframe(1, 0, -1, -1);\n            SetSmoothEditable(ref keys, TangentMode.Auto);\n            return keys;\n        }\n\n        static internal Keyframe[] GetEaseInKeys()\n        {\n            Keyframe[] keys = new Keyframe[2];\n            keys[0] = new Keyframe(0, 0, 0, 0);\n            keys[1] = new Keyframe(1, 1, 2, 2);\n            SetSmoothEditable(ref keys, TangentMode.Free);\n            return keys;\n        }\n\n        static internal Keyframe[] GetEaseInMirrorKeys()\n        {\n            Keyframe[] keys = new Keyframe[2];\n            keys[0] = new Keyframe(0, 1, -2, -2);\n            keys[1] = new Keyframe(1, 0, 0, 0);\n            SetSmoothEditable(ref keys, TangentMode.Free);\n            return keys;\n        }\n\n        static internal Keyframe[] GetEaseOutKeys()\n        {\n            Keyframe[] keys = new Keyframe[2];\n            keys[0] = new Keyframe(0, 0, 2, 2);\n            keys[1] = new Keyframe(1, 1, 0, 0);\n            SetSmoothEditable(ref keys, TangentMode.Free);\n            return keys;\n        }\n\n        static internal Keyframe[] GetEaseOutMirrorKeys()\n        {\n            Keyframe[] keys = new Keyframe[2];\n            keys[0] = new Keyframe(0, 1, 0, 0);\n            keys[1] = new Keyframe(1, 0, -2, -2);\n            SetSmoothEditable(ref keys, TangentMode.Free);\n            return keys;\n        }\n\n        static internal Keyframe[] GetEaseInOutKeys()\n        {\n            Keyframe[] keys = new Keyframe[2];\n            keys[0] = new Keyframe(0, 0, 0, 0);\n            keys[1] = new Keyframe(1, 1, 0, 0);\n            SetSmoothEditable(ref keys, TangentMode.Free);\n            return keys;\n        }\n\n        static internal Keyframe[] GetEaseInOutMirrorKeys()\n        {\n            Keyframe[] keys = new Keyframe[2];\n            keys[0] = new Keyframe(0, 1, 0, 0);\n            keys[1] = new Keyframe(1, 0, 0, 0);\n            SetSmoothEditable(ref keys, TangentMode.Free);\n            return keys;\n        }\n\n        static internal Keyframe[] GetConstantKeys(float value)\n        {\n            Keyframe[] keys = new Keyframe[2];\n            keys[0] = new Keyframe(0, value, 0, 0);\n            keys[1] = new Keyframe(1, value, 0, 0);\n            SetSmoothEditable(ref keys, TangentMode.Auto);\n            return keys;\n        }\n\n        static internal void SetSmoothEditable(ref Keyframe[] keys, TangentMode tangentMode)\n        {\n            for (int i = 0; i < keys.Length; i++)\n            {\n                AnimationUtility.SetKeyBroken(ref keys[i], false);\n                AnimationUtility.SetKeyLeftTangentMode(ref keys[i], tangentMode);\n                AnimationUtility.SetKeyRightTangentMode(ref keys[i], tangentMode);\n            }\n        }\n\n        public static Keyframe[] NormalizeKeys(Keyframe[] sourceKeys, NormalizationMode normalization, CurveEditor curveEditor)\n        {\n            Rect normalizationRect;\n            if (!GetNormalizationRect(out normalizationRect, curveEditor))\n                // No normalization rect, just return a copy of the source keyframes\n                normalization = NormalizationMode.None;\n            return CopyAndScaleCurveKeys(sourceKeys, normalizationRect, normalization);\n        }\n\n        Keyframe[] GetDenormalizedKeys(Keyframe[] sourceKeys)\n        {\n            return GetDenormalizedKeys(sourceKeys, m_CurveEditor);\n        }\n\n        public static Keyframe[] GetDenormalizedKeys(Keyframe[] sourceKeys, CurveEditor curveEditor)\n        {\n            return NormalizeKeys(sourceKeys, NormalizationMode.Denormalize, curveEditor);\n        }\n\n        Keyframe[] GetNormalizedKeys(Keyframe[] sourceKeys)\n        {\n            return GetNormalizedKeys(sourceKeys, m_CurveEditor);\n        }\n\n        public static Keyframe[] GetNormalizedKeys(Keyframe[] sourceKeys, CurveEditor curveEditor)\n        {\n            return NormalizeKeys(sourceKeys, NormalizationMode.Normalize, curveEditor);\n        }\n\n        void OnGUI()\n        {\n            bool gotMouseUp = (Event.current.type == EventType.MouseUp);\n\n            if (m_DelegateView == null && m_OnCurveChanged == null)\n                m_Curve = null;\n\n            if (ms_Styles == null)\n                ms_Styles = new Styles();\n\n            // Curve Editor\n            m_CurveEditor.rect = GetCurveEditorRect();\n            m_CurveEditor.hRangeLocked = Event.current.shift;\n            m_CurveEditor.vRangeLocked = EditorGUI.actionKey;\n\n            GUI.changed = false;\n\n            GUI.Label(m_CurveEditor.drawRect, GUIContent.none, ms_Styles.curveEditorBackground);\n            m_CurveEditor.OnGUI();\n\n            // Preset swatch area\n            var presetRect = new Rect(0, position.height - kPresetsHeight, position.width, kPresetsHeight);\n            GUI.Box(presetRect, \"\", ms_Styles.curveSwatchArea);\n\n            Color curveColor = m_Color;\n            curveColor.a *= 0.6f;\n            const float width = 40f;\n            const float height = 25f;\n            const float spaceBetweenSwatches = 5f;\n            const float presetDropdownSize = 16f;\n            const float horizontalScrollbarHeight = 15f;\n            const float presetDropdownCenteringOffset = 2f;\n            float yPos = (kPresetsHeight - height) * 0.5f;\n            InitCurvePresets();\n            CurvePresetLibrary curveLibrary = m_CurvePresets.GetPresetLibraryEditor().GetCurrentLib();\n            if (curveLibrary != null)\n            {\n                var numPresets = curveLibrary.Count();\n                var presetDropDownRect = new Rect(spaceBetweenSwatches, yPos + presetDropdownCenteringOffset, presetDropdownSize, presetDropdownSize);\n                Rect contentRect = new Rect(0, 0, numPresets * (width + spaceBetweenSwatches) + presetDropDownRect.xMax, presetRect.height - horizontalScrollbarHeight);\n                m_PresetScrollPosition = GUI.BeginScrollView(\n                    presetRect,               // Rectangle of the visible area\n                    m_PresetScrollPosition,   // Current scroll position\n                    contentRect,              // Rectangle containing all content\n                    false,                    // Always show horizontal scrollbar\n                    false                     // Always show vertical scrollbar\n                );\n\n                PresetDropDown(presetDropDownRect);\n\n                Rect swatchRect = new Rect(presetDropDownRect.xMax + spaceBetweenSwatches, yPos, width, height);\n                for (int i = 0; i < numPresets; i++)\n                {\n                    m_GUIContent.tooltip = curveLibrary.GetName(i);\n                    if (GUI.Button(swatchRect, m_GUIContent, ms_Styles.curveSwatch))\n                    {\n                        AnimationCurve animCurve = curveLibrary.GetPreset(i) as AnimationCurve;\n                        m_Curve.keys = GetDenormalizedKeys(animCurve.keys);\n                        m_Curve.postWrapMode = animCurve.postWrapMode;\n                        m_Curve.preWrapMode = animCurve.preWrapMode;\n                        m_CurveEditor.SelectNone();\n                        SendEvent(CurveChangedCommand, true);\n                    }\n                    if (Event.current.type == EventType.Repaint)\n                        curveLibrary.Draw(swatchRect, i);\n\n                    swatchRect.x += width + spaceBetweenSwatches;\n                }\n                GUI.EndScrollView();\n            }\n\n            // For adding default preset curves\n            //if (EditorGUI.DropdownButton(new Rect (position.width -26, yPos, 20, 20), GUIContent.none, FocusType.Passive, \"OL Plus\"))\n            //  AddDefaultPresetsToCurrentLib ();\n\n            if (Event.current.type == EventType.Used && gotMouseUp)\n            {\n                DoUpdateCurve(false);\n                SendEvent(CurveChangeCompletedCommand, true);\n            }\n            else if (Event.current.type != EventType.Layout && Event.current.type != EventType.Repaint)\n            {\n                DoUpdateCurve(true);\n            }\n        }\n\n        void PresetDropDown(Rect rect)\n        {\n            if (EditorGUI.DropdownButton(rect, EditorGUI.GUIContents.titleSettingsIcon, FocusType.Passive, EditorStyles.inspectorTitlebarText))\n            {\n                if (m_Curve != null)\n                {\n                    if (m_CurvePresets == null)\n                    {\n                        Debug.LogError(\"Curve presets error\");\n                        return;\n                    }\n\n                    ValidateCurveLibraryTypeAndScale();\n\n                    AnimationCurve copy = new AnimationCurve(GetNormalizedKeys(m_Curve.keys));\n                    copy.postWrapMode = m_Curve.postWrapMode;\n                    copy.preWrapMode = m_Curve.preWrapMode;\n\n                    m_CurvePresets.curveToSaveAsPreset = copy;\n                    PopupWindow.Show(rect, m_CurvePresets);\n                }\n            }\n        }\n\n        void ValidateCurveLibraryTypeAndScale()\n        {\n            Rect normalizationRect;\n            if (GetNormalizationRect(out normalizationRect, m_CurveEditor))\n            {\n                if (curveLibraryType != CurveLibraryType.NormalizedZeroToOne)\n                    Debug.LogError(\"When having a normalize rect we should be using curve library type: NormalizedZeroToOne (normalizationRect: \" + normalizationRect + \")\");\n            }\n            else\n            {\n                if (curveLibraryType != CurveLibraryType.Unbounded)\n                    Debug.LogError(\"When NOT having a normalize rect we should be using library type: Unbounded\");\n            }\n        }\n\n        public void UpdateCurve()\n        {\n            DoUpdateCurve(false);\n        }\n\n        private void DoUpdateCurve(bool exitGUI)\n        {\n            if (m_CurveEditor.animationCurves.Length > 0\n                && m_CurveEditor.animationCurves[0] != null\n                && m_CurveEditor.animationCurves[0].changed)\n            {\n                m_CurveEditor.animationCurves[0].changed = false;\n                RefreshShownCurves();\n                SendEvent(CurveChangedCommand, exitGUI);\n            }\n        }\n\n        void SendEvent(string eventName, bool exitGUI)\n        {\n            if (m_DelegateView)\n            {\n                Event e = EditorGUIUtility.CommandEvent(eventName);\n                Repaint();\n                m_DelegateView.SendEvent(e);\n                if (exitGUI)\n                    GUIUtility.ExitGUI();\n            }\n\n            if (m_OnCurveChanged != null)\n            {\n                m_OnCurveChanged(curve);\n            }\n            GUI.changed = true;\n        }\n\n        [Shortcut(\"Curve Editor/Frame All\", typeof(CurveEditorWindow), KeyCode.A)]\n        static void FrameClip(ShortcutArguments args)\n        {\n            var curveEditorWindow = (CurveEditorWindow)args.context;\n\n            if (EditorWindow.focusedWindow != curveEditorWindow)\n                return;\n\n            curveEditorWindow.FrameClip();\n            curveEditorWindow.Repaint();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/CurveMenuManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\n\nusing TangentMode = UnityEditor.AnimationUtility.TangentMode;\n\nnamespace UnityEditor\n{\n    internal class ChangedCurve\n    {\n        public AnimationCurve curve;\n        public int curveId;\n        public EditorCurveBinding binding;\n\n        public ChangedCurve(AnimationCurve curve, int curveId, EditorCurveBinding binding)\n        {\n            this.curve = curve;\n            this.curveId = curveId;\n            this.binding = binding;\n        }\n\n        public override int GetHashCode()\n        {\n            int hash = 0;\n            unchecked\n            {\n                hash = curve.GetHashCode();\n                hash = 33 * hash + binding.GetHashCode();\n            }\n            return hash;\n        }\n    }\n\n    internal class KeyIdentifier\n    {\n        public AnimationCurve curve;\n        public int curveId;\n        public int key;\n\n        // Used by dopesheet\n        public EditorCurveBinding binding;\n\n        public KeyIdentifier(AnimationCurve _curve, int _curveId, int _keyIndex)\n        {\n            curve = _curve;\n            curveId = _curveId;\n            key = _keyIndex;\n        }\n\n        public KeyIdentifier(AnimationCurve _curve, int _curveId, int _keyIndex, EditorCurveBinding _binding)\n        {\n            curve = _curve;\n            curveId = _curveId;\n            key = _keyIndex;\n            binding = _binding;\n        }\n\n        public Keyframe keyframe { get { return curve[key]; } }\n    }\n\n    internal interface CurveUpdater\n    {\n        void UpdateCurves(List<ChangedCurve> curve, string undoText);\n    }\n\n    internal class CurveMenuManager\n    {\n        CurveUpdater updater;\n\n        public CurveMenuManager(CurveUpdater updater)\n        {\n            this.updater = updater;\n        }\n\n        public void AddTangentMenuItems(GenericMenu menu, List<KeyIdentifier> keyList)\n        {\n            bool anyKeys = (keyList.Count > 0);\n            // Find out which qualities apply to all the keys\n            bool allClampedAuto = anyKeys;\n            bool allAuto = anyKeys;\n            bool allFreeSmooth = anyKeys;\n            bool allFlat = anyKeys;\n            bool allBroken = anyKeys;\n            bool allLeftWeighted = anyKeys;\n            bool allLeftFree = anyKeys;\n            bool allLeftLinear = anyKeys;\n            bool allLeftConstant = anyKeys;\n            bool allRightWeighted = anyKeys;\n            bool allRightFree = anyKeys;\n            bool allRightLinear = anyKeys;\n            bool allRightConstant = anyKeys;\n            foreach (KeyIdentifier sel in keyList)\n            {\n                Keyframe key = sel.keyframe;\n                TangentMode leftMode = AnimationUtility.GetKeyLeftTangentMode(key);\n                TangentMode rightMode = AnimationUtility.GetKeyRightTangentMode(key);\n                bool broken = AnimationUtility.GetKeyBroken(key);\n                if (leftMode != TangentMode.ClampedAuto || rightMode != TangentMode.ClampedAuto) allClampedAuto = false;\n                if (leftMode != TangentMode.Auto || rightMode != TangentMode.Auto) allAuto = false;\n                if (broken || leftMode != TangentMode.Free || rightMode != TangentMode.Free) allFreeSmooth = false;\n                if (broken || leftMode != TangentMode.Free || key.inTangent != 0 || rightMode != TangentMode.Free || key.outTangent != 0) allFlat = false;\n                if (!broken) allBroken = false;\n                if (!broken || leftMode  != TangentMode.Free) allLeftFree = false;\n                if (!broken || leftMode  != TangentMode.Linear) allLeftLinear = false;\n                if (!broken || leftMode  != TangentMode.Constant) allLeftConstant = false;\n                if (!broken || rightMode != TangentMode.Free) allRightFree = false;\n                if (!broken || rightMode != TangentMode.Linear) allRightLinear = false;\n                if (!broken || rightMode != TangentMode.Constant) allRightConstant = false;\n\n\n                if ((key.weightedMode & WeightedMode.In) == WeightedMode.None) allLeftWeighted = false;\n                if ((key.weightedMode & WeightedMode.Out) == WeightedMode.None) allRightWeighted = false;\n            }\n            if (anyKeys)\n            {\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Clamped Auto\"),         allClampedAuto, SetClampedAuto, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Auto\"), allAuto, SetAuto, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Free Smooth\"),  allFreeSmooth, SetEditable, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Flat\"),         allFlat, SetFlat, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Broken\"),       allBroken, SetBroken, keyList);\n                menu.AddSeparator(\"\");\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Left Tangent/Free\"),      allLeftFree, SetLeftEditable, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Left Tangent/Linear\"),    allLeftLinear, SetLeftLinear, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Left Tangent/Constant\"),  allLeftConstant, SetLeftConstant, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Left Tangent/Weighted\"),  allLeftWeighted, ToggleLeftWeighted, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Right Tangent/Free\"),     allRightFree, SetRightEditable, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Right Tangent/Linear\"),   allRightLinear, SetRightLinear, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Right Tangent/Constant\"), allRightConstant, SetRightConstant, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Right Tangent/Weighted\"),  allRightWeighted, ToggleRightWeighted, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Both Tangents/Free\"),     allRightFree && allLeftFree, SetBothEditable, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Both Tangents/Linear\"),   allRightLinear && allLeftLinear, SetBothLinear, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Both Tangents/Constant\"), allRightConstant && allLeftConstant, SetBothConstant, keyList);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Both Tangents/Weighted\"), allRightWeighted && allLeftWeighted, ToggleBothWeighted, keyList);\n            }\n            else\n            {\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Weighted\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Auto\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Free Smooth\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Flat\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Broken\"));\n                menu.AddSeparator(\"\");\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Left Tangent/Free\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Left Tangent/Linear\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Left Tangent/Constant\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Left Tangent/Weighted\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Right Tangent/Free\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Right Tangent/Linear\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Right Tangent/Constant\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Right Tangent/Weighted\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Both Tangents/Free\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Both Tangents/Linear\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Both Tangents/Constant\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Both Tangents/Weighted\"));\n            }\n        }\n\n        public void ToggleLeftWeighted(object keysToSet) { ToggleWeighted(WeightedMode.In, (List<KeyIdentifier>)keysToSet); }\n        public void ToggleRightWeighted(object keysToSet) { ToggleWeighted(WeightedMode.Out, (List<KeyIdentifier>)keysToSet); }\n        public void ToggleBothWeighted(object keysToSet) { ToggleWeighted(WeightedMode.Both, (List<KeyIdentifier>)keysToSet); }\n        public void ToggleWeighted(WeightedMode weightedMode, List<KeyIdentifier> keysToSet)\n        {\n            bool allWeighted = keysToSet.TrueForAll(key => (key.keyframe.weightedMode & weightedMode) == weightedMode);\n\n            List<ChangedCurve> changedCurves = new List<ChangedCurve>();\n            foreach (KeyIdentifier keyToSet in keysToSet)\n            {\n                AnimationCurve animationCurve = keyToSet.curve;\n                Keyframe key = keyToSet.keyframe;\n\n                bool weighted = (key.weightedMode & weightedMode) == weightedMode;\n                if (weighted == allWeighted)\n                {\n                    WeightedMode lastWeightedMode = key.weightedMode;\n                    key.weightedMode = weighted ? key.weightedMode & ~weightedMode : key.weightedMode | weightedMode;\n\n                    if (key.weightedMode != WeightedMode.None)\n                    {\n                        TangentMode rightTangentMode = AnimationUtility.GetKeyRightTangentMode(key);\n                        TangentMode leftTangentMode = AnimationUtility.GetKeyLeftTangentMode(key);\n\n                        if ((lastWeightedMode & WeightedMode.Out) == WeightedMode.None && (key.weightedMode & WeightedMode.Out) == WeightedMode.Out)\n                        {\n                            if (rightTangentMode == TangentMode.Linear || rightTangentMode == TangentMode.Constant)\n                                AnimationUtility.SetKeyRightTangentMode(ref key, TangentMode.Free);\n                            if (keyToSet.key < (animationCurve.length - 1))\n                                key.outWeight = 1 / 3.0f;\n                        }\n\n                        if ((lastWeightedMode & WeightedMode.In) == WeightedMode.None && (key.weightedMode & WeightedMode.In) == WeightedMode.In)\n                        {\n                            if (leftTangentMode == TangentMode.Linear || leftTangentMode == TangentMode.Constant)\n                                AnimationUtility.SetKeyLeftTangentMode(ref key, TangentMode.Free);\n                            if (keyToSet.key > 0)\n                                key.inWeight = 1 / 3.0f;\n                        }\n                    }\n\n                    animationCurve.MoveKey(keyToSet.key, key);\n                    AnimationUtility.UpdateTangentsFromModeSurrounding(animationCurve, keyToSet.key);\n\n                    ChangedCurve changedCurve = new ChangedCurve(animationCurve, keyToSet.curveId, keyToSet.binding);\n                    if (!changedCurves.Contains(changedCurve))\n                        changedCurves.Add(changedCurve);\n                }\n            }\n\n            updater.UpdateCurves(changedCurves, \"Toggle Weighted\");\n        }\n\n        public void SetClampedAuto(object keysToSet) { SetBoth(TangentMode.ClampedAuto, (List<KeyIdentifier>)keysToSet); }\n        public void SetAuto(object keysToSet) { SetBoth(TangentMode.Auto, (List<KeyIdentifier>)keysToSet); }\n        public void SetEditable(object keysToSet) { SetBoth(TangentMode.Free, (List<KeyIdentifier>)keysToSet); }\n        public void SetFlat(object keysToSet) { SetBoth(TangentMode.Free, (List<KeyIdentifier>)keysToSet); Flatten((List<KeyIdentifier>)keysToSet); }\n        public void SetBoth(TangentMode mode, List<KeyIdentifier> keysToSet)\n        {\n            List<ChangedCurve> changedCurves = new List<ChangedCurve>();\n            foreach (KeyIdentifier keyToSet in keysToSet)\n            {\n                AnimationCurve animationCurve = keyToSet.curve;\n                Keyframe key = keyToSet.keyframe;\n                AnimationUtility.SetKeyBroken(ref key, false);\n                AnimationUtility.SetKeyRightTangentMode(ref key, mode);\n                AnimationUtility.SetKeyLeftTangentMode(ref key, mode);\n\n                // Smooth Tangents based on neighboring nodes\n                // Note: not needed since the UpdateTangentsFromModeSurrounding call below will handle it\n                //if (mode == TangentMode.ClampedAuto) animationCurve.SmoothTangents(keyToSet.key, 0.0F);\n                // Smooth tangents based on existing tangents\n                if (mode == TangentMode.Free)\n                {\n                    float slope = CurveUtility.CalculateSmoothTangent(key);\n                    key.inTangent = slope;\n                    key.outTangent = slope;\n                }\n                animationCurve.MoveKey(keyToSet.key, key);\n                AnimationUtility.UpdateTangentsFromModeSurrounding(animationCurve, keyToSet.key);\n\n                ChangedCurve changedCurve = new ChangedCurve(animationCurve, keyToSet.curveId, keyToSet.binding);\n                if (!changedCurves.Contains(changedCurve))\n                    changedCurves.Add(changedCurve);\n            }\n\n            updater.UpdateCurves(changedCurves, \"Set Tangents\");\n        }\n\n        public void Flatten(List<KeyIdentifier> keysToSet)\n        {\n            List<ChangedCurve> changedCurves = new List<ChangedCurve>();\n            foreach (KeyIdentifier keyToSet in keysToSet)\n            {\n                AnimationCurve animationCurve = keyToSet.curve;\n                Keyframe key = keyToSet.keyframe;\n                key.inTangent = 0;\n                key.outTangent = 0;\n                animationCurve.MoveKey(keyToSet.key, key);\n                AnimationUtility.UpdateTangentsFromModeSurrounding(animationCurve, keyToSet.key);\n\n                ChangedCurve changedCurve = new ChangedCurve(animationCurve, keyToSet.curveId, keyToSet.binding);\n                if (!changedCurves.Contains(changedCurve))\n                    changedCurves.Add(changedCurve);\n            }\n\n            updater.UpdateCurves(changedCurves, \"Set Tangents\");\n        }\n\n        public void SetBroken(object _keysToSet)\n        {\n            List<ChangedCurve> changedCurves = new List<ChangedCurve>();\n            List<KeyIdentifier> keysToSet = (List<KeyIdentifier>)_keysToSet;\n            foreach (KeyIdentifier keyToSet in keysToSet)\n            {\n                AnimationCurve animationCurve = keyToSet.curve;\n                Keyframe key = keyToSet.keyframe;\n                AnimationUtility.SetKeyBroken(ref key, true);\n                if (AnimationUtility.GetKeyRightTangentMode(key) == TangentMode.ClampedAuto || AnimationUtility.GetKeyRightTangentMode(key) == TangentMode.Auto)\n                    AnimationUtility.SetKeyRightTangentMode(ref key, TangentMode.Free);\n                if (AnimationUtility.GetKeyLeftTangentMode(key) == TangentMode.ClampedAuto || AnimationUtility.GetKeyLeftTangentMode(key) == TangentMode.Auto)\n                    AnimationUtility.SetKeyLeftTangentMode(ref key, TangentMode.Free);\n\n                animationCurve.MoveKey(keyToSet.key, key);\n                AnimationUtility.UpdateTangentsFromModeSurrounding(animationCurve, keyToSet.key);\n\n                ChangedCurve changedCurve = new ChangedCurve(animationCurve, keyToSet.curveId, keyToSet.binding);\n                if (!changedCurves.Contains(changedCurve))\n                    changedCurves.Add(changedCurve);\n            }\n\n            updater.UpdateCurves(changedCurves, \"Set Tangents\");\n        }\n\n        public void SetLeftEditable(object keysToSet) { SetTangent(0, TangentMode.Free, (List<KeyIdentifier>)keysToSet); }\n        public void SetLeftLinear(object keysToSet) { SetTangent(0, TangentMode.Linear, (List<KeyIdentifier>)keysToSet); }\n        public void SetLeftConstant(object keysToSet) { SetTangent(0, TangentMode.Constant, (List<KeyIdentifier>)keysToSet); }\n        public void SetRightEditable(object keysToSet) { SetTangent(1, TangentMode.Free, (List<KeyIdentifier>)keysToSet); }\n        public void SetRightLinear(object keysToSet) { SetTangent(1, TangentMode.Linear, (List<KeyIdentifier>)keysToSet); }\n        public void SetRightConstant(object keysToSet) { SetTangent(1, TangentMode.Constant, (List<KeyIdentifier>)keysToSet); }\n        public void SetBothEditable(object keysToSet) { SetTangent(2, TangentMode.Free, (List<KeyIdentifier>)keysToSet); }\n        public void SetBothLinear(object keysToSet) { SetTangent(2, TangentMode.Linear, (List<KeyIdentifier>)keysToSet); }\n        public void SetBothConstant(object keysToSet) { SetTangent(2, TangentMode.Constant, (List<KeyIdentifier>)keysToSet); }\n        public void SetTangent(int leftRight, TangentMode mode, List<KeyIdentifier> keysToSet)\n        {\n            List<ChangedCurve> changedCurves = new List<ChangedCurve>();\n\n            foreach (KeyIdentifier keyToSet in keysToSet)\n            {\n                AnimationCurve animationCurve = keyToSet.curve;\n                Keyframe key = keyToSet.keyframe;\n                AnimationUtility.SetKeyBroken(ref key, true);\n                if (leftRight == 2)\n                {\n                    AnimationUtility.SetKeyLeftTangentMode(ref key, mode);\n                    AnimationUtility.SetKeyRightTangentMode(ref key, mode);\n                }\n                else\n                {\n                    if (leftRight == 0)\n                    {\n                        AnimationUtility.SetKeyLeftTangentMode(ref key, mode);\n\n                        // Make sure other tangent is handled correctly\n                        if (AnimationUtility.GetKeyRightTangentMode(key) == TangentMode.ClampedAuto || AnimationUtility.GetKeyRightTangentMode(key) == TangentMode.Auto)\n                            AnimationUtility.SetKeyRightTangentMode(ref key, TangentMode.Free);\n                    }\n                    else //if (leftRight == 1)\n                    {\n                        AnimationUtility.SetKeyRightTangentMode(ref key, mode);\n\n                        // Make sure other tangent is handled correctly\n                        if (AnimationUtility.GetKeyLeftTangentMode(key) == TangentMode.ClampedAuto || AnimationUtility.GetKeyLeftTangentMode(key) == TangentMode.Auto)\n                            AnimationUtility.SetKeyLeftTangentMode(ref key, TangentMode.Free);\n                    }\n                }\n\n                if (mode == TangentMode.Constant && (leftRight == 0 || leftRight == 2))\n                    key.inTangent = Mathf.Infinity;\n                if (mode == TangentMode.Constant && (leftRight == 1 || leftRight == 2))\n                    key.outTangent = Mathf.Infinity;\n\n                animationCurve.MoveKey(keyToSet.key, key);\n                AnimationUtility.UpdateTangentsFromModeSurrounding(animationCurve, keyToSet.key);\n                // Debug.Log (\"Before \" + DebKey (key) + \" after: \" + DebKey (animationCurve[keyToSet.key]));\n\n                ChangedCurve changedCurve = new ChangedCurve(animationCurve, keyToSet.curveId, keyToSet.binding);\n                if (!changedCurves.Contains(changedCurve))\n                    changedCurves.Add(changedCurve);\n            }\n\n            updater.UpdateCurves(changedCurves, \"Set Tangents\");\n        }\n\n        /*\n            string DebKey (Keyframe key) {\n                return System.String.Format (\"time:{0} value:{1} inTangent:{2} outTangent{3}\", key.time, key.value, key.inTangent, key.outTangent);\n            }\n        */\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/CurveRenderer/BoolCurveRenderer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class BoolCurveRenderer : NormalCurveRenderer\n    {\n        public BoolCurveRenderer(AnimationCurve curve)\n            : base(curve)\n        {\n        }\n\n        public override float ClampedValue(float value)\n        {\n            return value != 0.0f ? 1.0f : 0.0f;\n        }\n\n        public override float EvaluateCurveSlow(float time)\n        {\n            return ClampedValue(GetCurve().Evaluate(time));\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/CurveRenderer/CurveRenderer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal interface CurveRenderer\n    {\n        void DrawCurve(float minTime, float maxTime, Color color, Matrix4x4 transform, Color wrapColor);\n        AnimationCurve GetCurve();\n        float RangeStart();\n        float RangeEnd();\n        void SetWrap(WrapMode wrap);\n        void SetWrap(WrapMode preWrap, WrapMode postWrap);\n        void SetCustomRange(float start, float end);\n        float EvaluateCurveSlow(float time);\n        float EvaluateCurveDeltaSlow(float time);\n        Bounds GetBounds();\n        Bounds GetBounds(float minTime, float maxTime);\n        float ClampedValue(float value);\n        void FlushCache();\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/CurveRenderer/EulerCurveCombinedRenderer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class EulerCurveCombinedRenderer\n    {\n        const int kSegmentResolution = 40;\n        const float epsilon = 0.001f;\n\n        private AnimationCurve quaternionX;\n        private AnimationCurve quaternionY;\n        private AnimationCurve quaternionZ;\n        private AnimationCurve quaternionW;\n        private AnimationCurve eulerX;\n        private AnimationCurve eulerY;\n        private AnimationCurve eulerZ;\n\n        private SortedDictionary<float, Vector3> points;\n\n        private float cachedEvaluationTime = Mathf.Infinity;\n        private Vector3 cachedEvaluationValue;\n\n        private float cachedRangeStart = Mathf.Infinity;\n        private float cachedRangeEnd = Mathf.NegativeInfinity;\n\n        private Vector3 refEuler;\n\n        private float m_CustomRangeStart = 0;\n        private float m_CustomRangeEnd = 0;\n        private float rangeStart { get { return (m_CustomRangeStart == 0 && m_CustomRangeEnd == 0 && eulerX.length > 0 ? eulerX.keys[0].time : m_CustomRangeStart); } }\n        private float rangeEnd   { get { return (m_CustomRangeStart == 0 && m_CustomRangeEnd == 0 && eulerX.length > 0 ? eulerX.keys[eulerX.length - 1].time : m_CustomRangeEnd); } }\n        private WrapMode preWrapMode = WrapMode.Once;\n        private WrapMode postWrapMode = WrapMode.Once;\n\n        public EulerCurveCombinedRenderer(\n            AnimationCurve quaternionX,\n            AnimationCurve quaternionY,\n            AnimationCurve quaternionZ,\n            AnimationCurve quaternionW,\n            AnimationCurve eulerX,\n            AnimationCurve eulerY,\n            AnimationCurve eulerZ\n        )\n        {\n            this.quaternionX = (quaternionX == null ? new AnimationCurve() : quaternionX);\n            this.quaternionY = (quaternionY == null ? new AnimationCurve() : quaternionY);\n            this.quaternionZ = (quaternionZ == null ? new AnimationCurve() : quaternionZ);\n            this.quaternionW = (quaternionW == null ? new AnimationCurve() : quaternionW);\n            this.eulerX = (eulerX == null ? new AnimationCurve() : eulerX);\n            this.eulerY = (eulerY == null ? new AnimationCurve() : eulerY);\n            this.eulerZ = (eulerZ == null ? new AnimationCurve() : eulerZ);\n        }\n\n        public AnimationCurve GetCurveOfComponent(int component)\n        {\n            switch (component)\n            {\n                case 0: return eulerX;\n                case 1: return eulerY;\n                case 2: return eulerZ;\n                default: return null;\n            }\n        }\n\n        public float RangeStart() { return rangeStart; }\n        public float RangeEnd() { return rangeEnd; }\n        public WrapMode PreWrapMode() { return preWrapMode; }\n        public WrapMode PostWrapMode() { return postWrapMode; }\n        public void SetWrap(WrapMode wrap)\n        {\n            preWrapMode = wrap;\n            postWrapMode = wrap;\n        }\n\n        public void SetWrap(WrapMode preWrap, WrapMode postWrap)\n        {\n            preWrapMode = preWrap;\n            postWrapMode = postWrap;\n        }\n\n        public void SetCustomRange(float start, float end)\n        {\n            m_CustomRangeStart = start;\n            m_CustomRangeEnd = end;\n        }\n\n        private Vector3 GetValues(float time, bool keyReference)\n        {\n            if (quaternionX == null) Debug.LogError(\"X curve is null!\");\n            if (quaternionY == null) Debug.LogError(\"Y curve is null!\");\n            if (quaternionZ == null) Debug.LogError(\"Z curve is null!\");\n            if (quaternionW == null) Debug.LogError(\"W curve is null!\");\n\n            Quaternion q;\n\n            if (quaternionX.length != 0 &&\n                quaternionY.length != 0 &&\n                quaternionZ.length != 0 &&\n                quaternionW.length != 0)\n            {\n                q = EvaluateQuaternionCurvesDirectly(time);\n                if (keyReference)\n                    refEuler = EvaluateEulerCurvesDirectly(time);\n                refEuler = QuaternionCurveTangentCalculation.GetEulerFromQuaternion(q, refEuler);\n            }\n            else //euler curves only\n            {\n                refEuler = EvaluateEulerCurvesDirectly(time);\n            }\n\n            return refEuler;\n        }\n\n        private Quaternion EvaluateQuaternionCurvesDirectly(float time)\n        {\n            return new Quaternion(\n                quaternionX.Evaluate(time),\n                quaternionY.Evaluate(time),\n                quaternionZ.Evaluate(time),\n                quaternionW.Evaluate(time));\n        }\n\n        private Vector3 EvaluateEulerCurvesDirectly(float time)\n        {\n            return new Vector3(\n                eulerX.Evaluate(time),\n                eulerY.Evaluate(time),\n                eulerZ.Evaluate(time));\n        }\n\n        private void CalculateCurves(float minTime, float maxTime)\n        {\n            points = new SortedDictionary<float, Vector3>();\n\n            float[,] ranges = NormalCurveRenderer.CalculateRanges(minTime, maxTime, rangeStart, rangeEnd, preWrapMode, postWrapMode);\n            for (int i = 0; i < ranges.GetLength(0); i++)\n                AddPoints(ranges[i, 0], ranges[i, 1]);\n        }\n\n        private void AddPoints(float minTime, float maxTime)\n        {\n            AnimationCurve refCurve = quaternionX;\n            if (refCurve.length == 0)\n            {\n                refCurve = eulerX;\n            }\n\n            if (refCurve.length == 0)\n                return;\n\n            if (refCurve[0].time >= minTime)\n            {\n                Vector3 val = GetValues(refCurve[0].time, true);\n                points[rangeStart] = val;\n                points[refCurve[0].time] = val;\n            }\n            if (refCurve[refCurve.length - 1].time <= maxTime)\n            {\n                Vector3 val = GetValues(refCurve[refCurve.length - 1].time, true);\n                points[refCurve[refCurve.length - 1].time] = val;\n                points[rangeEnd] = val;\n            }\n\n            for (int i = 0; i < refCurve.length - 1; i++)\n            {\n                // Ignore segments that are outside of the range from minTime to maxTime\n                if (refCurve[i + 1].time < minTime || refCurve[i].time > maxTime)\n                    continue;\n\n                // Get first value from euler curve and move forwards\n                float newTime = refCurve[i].time;\n                points[newTime] = GetValues(newTime, true);\n\n                // Iterate forwards through curve segments\n                for (float j = 1; j <= kSegmentResolution / 2; j++)\n                {\n                    newTime = Mathf.Lerp(refCurve[i].time, refCurve[i + 1].time, (j - 0.001f) / kSegmentResolution);\n                    points[newTime] = GetValues(newTime, false);\n                }\n\n                // Get last value from euler curve and move backwards\n                newTime = refCurve[i + 1].time;\n                points[newTime] = GetValues(newTime, true);\n\n                // Iterate backwards through curve segment\n                for (float j = 1; j <= kSegmentResolution / 2; j++)\n                {\n                    newTime = Mathf.Lerp(refCurve[i].time, refCurve[i + 1].time, 1 - (j - 0.001f) / kSegmentResolution);\n                    points[newTime] = GetValues(newTime, false);\n                }\n            }\n        }\n\n        public float EvaluateCurveDeltaSlow(float time, int component)\n        {\n            if (quaternionX == null)\n                return 0;\n            return (EvaluateCurveSlow(time + epsilon, component) - EvaluateCurveSlow(time - epsilon, component)) / (epsilon * 2);\n        }\n\n        public float EvaluateCurveSlow(float time, int component)\n        {\n            if (GetCurveOfComponent(component).length == 1)\n            {\n                return GetCurveOfComponent(component)[0].value;\n            }\n\n            if (time == cachedEvaluationTime)\n                return cachedEvaluationValue[component];\n\n            if (time < cachedRangeStart || time > cachedRangeEnd)\n            {\n                // if an evaluate call is outside of cached range we might as well calculate whole range\n                CalculateCurves(rangeStart, rangeEnd);\n                cachedRangeStart = Mathf.NegativeInfinity;\n                cachedRangeEnd   = Mathf.Infinity;\n            }\n\n            float[] times = new float[points.Count];\n            Vector3[] values = new Vector3[points.Count];\n            int c = 0;\n            foreach (KeyValuePair<float, Vector3> kvp in points)\n            {\n                times[c] = kvp.Key;\n                values[c] = kvp.Value;\n                c++;\n            }\n\n            for (int i = 0; i < times.Length - 1; i++)\n            {\n                if (time < times[i + 1])\n                {\n                    float lerp = Mathf.InverseLerp(times[i], times[i + 1], time);\n                    cachedEvaluationValue = Vector3.Lerp(values[i], values[i + 1], lerp);\n                    cachedEvaluationTime = time;\n                    return cachedEvaluationValue[component];\n                }\n            }\n\n            if (values.Length > 0)\n                return values[values.Length - 1][component];\n\n            Debug.LogError(\"List of euler curve points is empty, probably caused by lack of euler curve key synching\");\n            return 0;\n        }\n\n        public void DrawCurve(float minTime, float maxTime, Color color, Matrix4x4 transform, int component, Color wrapColor)\n        {\n            if (minTime < cachedRangeStart || maxTime > cachedRangeEnd)\n            {\n                CalculateCurves(minTime, maxTime);\n                if (minTime <= rangeStart && maxTime >= rangeEnd)\n                {\n                    // if we are covering whole range\n                    cachedRangeStart = Mathf.NegativeInfinity;\n                    cachedRangeEnd   = Mathf.Infinity;\n                }\n                else\n                {\n                    cachedRangeStart = minTime;\n                    cachedRangeEnd   = maxTime;\n                }\n            }\n\n            List<Vector3> polyLine = new List<Vector3>();\n\n            foreach (KeyValuePair<float, Vector3> kvp in points)\n            {\n                polyLine.Add(new Vector3(kvp.Key, kvp.Value[component]));\n            }\n\n            NormalCurveRenderer.DrawCurveWrapped(minTime, maxTime, rangeStart, rangeEnd, preWrapMode, postWrapMode, color, transform, polyLine.ToArray(), wrapColor);\n        }\n\n        public Bounds GetBounds(float minTime, float maxTime, int component)\n        {\n            //if (alreadyDrawn[component])\n            //{\n            CalculateCurves(minTime, maxTime);\n            //  for (int i=0; i<alreadyDrawn.Length; i++) alreadyDrawn[i] = false;\n            //}\n            //alreadyDrawn[component] = true;\n\n            float min = Mathf.Infinity;\n            float max = Mathf.NegativeInfinity;\n            foreach (KeyValuePair<float, Vector3> kvp in points)\n            {\n                if (kvp.Value[component] > max)\n                    max = kvp.Value[component];\n                if (kvp.Value[component] < min)\n                    min = kvp.Value[component];\n            }\n            if (min == Mathf.Infinity)\n            {\n                min = 0;\n                max = 0;\n            }\n            return new Bounds(new Vector3((maxTime + minTime) * 0.5f, (max + min) * 0.5f, 0), new Vector3(maxTime - minTime, max - min, 0));\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/CurveRenderer/EulerCurveRenderer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class EulerCurveRenderer : CurveRenderer\n    {\n        private int component;\n        private EulerCurveCombinedRenderer renderer;\n\n        public EulerCurveRenderer(int component, EulerCurveCombinedRenderer renderer)\n        {\n            this.component = component;\n            this.renderer = renderer;\n        }\n\n        public AnimationCurve GetCurve()\n        {\n            return renderer.GetCurveOfComponent(component);\n        }\n\n        public float ClampedValue(float value)\n        {\n            return value;\n        }\n\n        public float RangeStart() { return renderer.RangeStart(); }\n        public float RangeEnd() { return renderer.RangeEnd(); }\n        public void SetWrap(WrapMode wrap)\n        {\n            renderer.SetWrap(wrap);\n        }\n\n        public void SetWrap(WrapMode preWrapMode, WrapMode postWrapMode)\n        {\n            renderer.SetWrap(preWrapMode, postWrapMode);\n        }\n\n        public void SetCustomRange(float start, float end)\n        {\n            renderer.SetCustomRange(start, end);\n        }\n\n        public float EvaluateCurveSlow(float time)\n        {\n            return renderer.EvaluateCurveSlow(time, component);\n        }\n\n        public float EvaluateCurveDeltaSlow(float time)\n        {\n            return renderer.EvaluateCurveDeltaSlow(time, component);\n        }\n\n        public void DrawCurve(float minTime, float maxTime, Color color, Matrix4x4 transform, Color wrapColor)\n        {\n            renderer.DrawCurve(minTime, maxTime, color, transform, component, wrapColor);\n        }\n\n        public Bounds GetBounds()\n        {\n            return GetBounds(renderer.RangeStart(), renderer.RangeEnd());\n        }\n\n        public Bounds GetBounds(float minTime, float maxTime)\n        {\n            return renderer.GetBounds(minTime, maxTime, component);\n        }\n\n        public void FlushCache()\n        {\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/CurveRenderer/IntCurveRenderer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class IntCurveRenderer : NormalCurveRenderer\n    {\n        const float kSegmentWindowResolution = 1000;\n        const int kMaximumSampleCount = 1000;\n        const float kStepHelperOffset = 0.000001f;\n\n\n        public IntCurveRenderer(AnimationCurve curve)\n            : base(curve)\n        {\n        }\n\n        public override float ClampedValue(float value)\n        {\n            return Mathf.Floor(value + 0.5f);\n        }\n\n        public override float EvaluateCurveSlow(float time)\n        {\n            return ClampedValue(GetCurve().Evaluate(time));\n        }\n\n        protected override int GetSegmentResolution(float minTime, float maxTime, float keyTime, float nextKeyTime)\n        {\n            float fullTimeRange = maxTime - minTime;\n            float keyTimeRange = nextKeyTime - keyTime;\n            int count = Mathf.RoundToInt(kSegmentWindowResolution * (keyTimeRange / fullTimeRange));\n            return Mathf.Clamp(count, 1, kMaximumSampleCount);\n        }\n\n        protected override void AddPoint(ref List<Vector3> points, ref float lastTime, float sampleTime, ref float lastValue, float sampleValue)\n        {\n            if (lastValue != sampleValue)\n            {\n                points.Add(new Vector3(lastTime + kStepHelperOffset, sampleValue));\n            }\n\n            points.Add(new Vector3(sampleTime, sampleValue));\n            lastTime = sampleTime;\n            lastValue = sampleValue;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/CurveRenderer/NormalCurveRenderer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class NormalCurveRenderer : CurveRenderer\n    {\n        const float kSegmentWindowResolution = 1000;\n        const int kMaximumSampleCount = 50;\n        const int kMaximumLoops = 100;\n        const string kCurveRendererMeshName = \"NormalCurveRendererMesh\";\n\n        private AnimationCurve m_Curve;\n        private float m_CustomRangeStart = 0;\n        private float m_CustomRangeEnd = 0;\n        private float rangeStart { get { return (m_CustomRangeStart == 0 && m_CustomRangeEnd == 0 && m_Curve.length > 0 ? m_Curve[0].time : m_CustomRangeStart); } }\n        private float rangeEnd   { get { return (m_CustomRangeStart == 0 && m_CustomRangeEnd == 0 && m_Curve.length > 0 ? m_Curve[m_Curve.length - 1].time : m_CustomRangeEnd); } }\n        private WrapMode preWrapMode = WrapMode.Once;\n        private WrapMode postWrapMode = WrapMode.Once;\n\n        private Bounds? m_Bounds;\n        private Mesh m_CurveMesh;\n\n        private static Material s_CurveMaterial;\n        public static Material curveMaterial\n        {\n            get\n            {\n                if (!s_CurveMaterial)\n                {\n                    Shader shader = (Shader)EditorGUIUtility.LoadRequired(\"Editors/AnimationWindow/Curve.shader\");\n                    s_CurveMaterial = new Material(shader);\n                    s_CurveMaterial.hideFlags = HideFlags.HideAndDontSave;\n                }\n\n                return s_CurveMaterial;\n            }\n        }\n\n        public NormalCurveRenderer(AnimationCurve curve)\n        {\n            m_Curve = curve;\n            if (m_Curve == null)\n                m_Curve = new AnimationCurve();\n        }\n\n        public AnimationCurve GetCurve()\n        {\n            return m_Curve;\n        }\n\n        public float RangeStart() { return rangeStart; }\n        public float RangeEnd() { return rangeEnd; }\n        public void SetWrap(WrapMode wrap)\n        {\n            this.preWrapMode = wrap;\n            this.postWrapMode = wrap;\n        }\n\n        public void SetWrap(WrapMode preWrap, WrapMode postWrap)\n        {\n            this.preWrapMode = preWrap;\n            this.postWrapMode = postWrap;\n        }\n\n        public void SetCustomRange(float start, float end)\n        {\n            m_CustomRangeStart = start;\n            m_CustomRangeEnd = end;\n        }\n\n        public virtual float ClampedValue(float value)\n        {\n            return value;\n        }\n\n        public virtual float EvaluateCurveSlow(float time)\n        {\n            return m_Curve.Evaluate(time);\n        }\n\n        // TODO: Implement proper analytic evaluation of curve delta instead of this numeric hack\n        public float EvaluateCurveDeltaSlow(float time)\n        {\n            float epsilon = 0.0001f;\n            return (EvaluateCurveSlow(time + epsilon) - EvaluateCurveSlow(time - epsilon)) / (epsilon * 2);\n        }\n\n        private Vector3[] GetPoints()\n        {\n            return GetPoints(rangeStart, rangeEnd);\n        }\n\n        private Vector3[] GetPoints(float minTime, float maxTime)\n        {\n            List<Vector3> points = new List<Vector3>();\n\n            if (m_Curve.length == 0)\n                return points.ToArray();\n            points.Capacity = 1000 + m_Curve.length;\n\n            float[,] ranges = CalculateRanges(minTime, maxTime, rangeStart, rangeEnd, preWrapMode, postWrapMode);\n            for (int i = 0; i < ranges.GetLength(0); i++)\n                AddPoints(ref points, ranges[i, 0], ranges[i, 1], minTime, maxTime);\n\n            // Remove points that don't go in ascending time order\n            if (points.Count > 0)\n            {\n                for (int i = 1; i < points.Count; i++)\n                {\n                    if (points[i].x < points[i - 1].x)\n                    {\n                        points.RemoveAt(i);\n                        i--;\n                    }\n                }\n            }\n\n            return points.ToArray();\n        }\n\n        public static float[,] CalculateRanges(float minTime, float maxTime, float rangeStart, float rangeEnd, WrapMode preWrapMode, WrapMode postWrapMode)\n        {\n            // Don't want to deal with optimizing for different pre and post wrap mode for now\n            WrapMode wrap = preWrapMode;\n            if (postWrapMode != wrap)\n                return new float[1, 2] {{rangeStart, rangeEnd}};\n\n            if (wrap == WrapMode.Loop)\n            {\n                // If we are covering a range longer than a full loop, just add all points:\n                if (maxTime - minTime > rangeEnd - rangeStart)\n                {\n                    return new float[1, 2] {{rangeStart, rangeEnd}};\n                }\n                // Else, only add the needed range(s)\n                else\n                {\n                    // Find the start and end of needed shown range repeated into the range of the curve\n                    minTime = Mathf.Repeat(minTime - rangeStart, rangeEnd - rangeStart) + rangeStart;\n                    maxTime = Mathf.Repeat(maxTime - rangeStart, rangeEnd - rangeStart) + rangeStart;\n                    if (minTime < maxTime)\n                        return new float[1, 2] {{minTime, maxTime}};\n                    else\n                        return new float[2, 2] {{rangeStart, maxTime}, {minTime, rangeEnd}};\n                }\n            }\n            else if (wrap == WrapMode.PingPong)\n            {\n                // TODO: Maybe optimize so not whole range is calculated if not needed\n                return new float[1, 2] {{rangeStart, rangeEnd}};\n            }\n            else\n                return new float[1, 2] {{minTime, maxTime}};\n        }\n\n        protected virtual int GetSegmentResolution(float minTime, float maxTime, float keyTime, float nextKeyTime)\n        {\n            float fullTimeRange = maxTime - minTime;\n            float keyTimeRange = nextKeyTime - keyTime;\n            int count = Mathf.RoundToInt(kSegmentWindowResolution * (keyTimeRange / fullTimeRange));\n            return Mathf.Clamp(count, 1, kMaximumSampleCount);\n        }\n\n        protected virtual void AddPoint(ref List<Vector3> points, ref float lastTime, float sampleTime, ref float lastValue, float sampleValue)\n        {\n            points.Add(new Vector3(sampleTime, sampleValue));\n            lastTime = sampleTime;\n            lastValue = sampleValue;\n        }\n\n        private void AddPoints(ref List<Vector3> points, float minTime, float maxTime, float visibleMinTime, float visibleMaxTime)\n        {\n            if (m_Curve[0].time >= minTime)\n            {\n                points.Add(new Vector3(rangeStart, ClampedValue(m_Curve[0].value)));\n                points.Add(new Vector3(m_Curve[0].time, ClampedValue(m_Curve[0].value)));\n            }\n\n            for (int i = 0; i < m_Curve.length - 1; i++)\n            {\n                Keyframe key = m_Curve[i];\n                Keyframe nextKey = m_Curve[i + 1];\n\n                // Ignore segments that are outside of the range from minTime to maxTime\n                if (nextKey.time < minTime || key.time > maxTime)\n                    continue;\n\n                // Get first value from actual key rather than evaluating curve (to correctly handle stepped interpolation)\n                points.Add(new Vector3(key.time, key.value));\n\n                // Place second sample very close to first one (to correctly handle stepped interpolation)\n                int segmentResolution = GetSegmentResolution(visibleMinTime, visibleMaxTime, key.time, nextKey.time);\n                float newTime = Mathf.Lerp(key.time, nextKey.time, 0.001f / segmentResolution);\n                float lastTime = key.time;\n                float lastValue = ClampedValue(key.value);\n                float value = EvaluateCurveSlow(newTime);\n                AddPoint(ref points, ref lastTime, newTime, ref lastValue, value);\n\n                // Iterate through curve segment\n                for (float j = 1; j < segmentResolution; j++)\n                {\n                    newTime = Mathf.Lerp(key.time, nextKey.time, j / segmentResolution);\n                    value = EvaluateCurveSlow(newTime);\n                    AddPoint(ref points, ref lastTime, newTime, ref lastValue, value);\n                }\n\n                // Place second last sample very close to last one (to correctly handle stepped interpolation)\n                newTime = Mathf.Lerp(key.time, nextKey.time, 1 - 0.001f / segmentResolution);\n                value = EvaluateCurveSlow(newTime);\n                AddPoint(ref points, ref lastTime, newTime, ref lastValue, value);\n\n                // Get last value from actual key rather than evaluating curve (to correctly handle stepped interpolation)\n                newTime = nextKey.time;\n                AddPoint(ref points, ref lastTime, newTime, ref lastValue, value);\n            }\n\n            if (m_Curve[m_Curve.length - 1].time <= maxTime)\n            {\n                float clampedValue = ClampedValue(m_Curve[m_Curve.length - 1].value);\n                points.Add(new Vector3(m_Curve[m_Curve.length - 1].time, clampedValue));\n                points.Add(new Vector3(rangeEnd, clampedValue));\n            }\n        }\n\n        private void BuildCurveMesh()\n        {\n            if (m_CurveMesh != null)\n                return;\n\n            Vector3[] vertices = GetPoints();\n\n            m_CurveMesh = new Mesh();\n            m_CurveMesh.name = kCurveRendererMeshName;\n            m_CurveMesh.hideFlags |= HideFlags.DontSave;\n            m_CurveMesh.vertices = vertices;\n\n            if (vertices.Length > 0)\n            {\n                int nIndices = vertices.Length - 1;\n                int index = 0;\n\n                List<int> indices = new List<int>(nIndices * 2);\n                while (index < nIndices)\n                {\n                    indices.Add(index);\n                    indices.Add(++index);\n                }\n\n                m_CurveMesh.SetIndices(indices.ToArray(), MeshTopology.Lines, 0);\n            }\n        }\n\n        public void DrawCurve(float minTime, float maxTime, Color color, Matrix4x4 transform, Color wrapColor)\n        {\n            BuildCurveMesh();\n\n            int numKeys = m_Curve.length;\n            int first = 0;\n            int last = Mathf.Max(first, numKeys - 1);\n\n            if (numKeys > 0)\n            {\n                Vector3 firstPoint = new Vector3(rangeStart, m_Curve[first].value);\n                Vector3 lastPoint = new Vector3(rangeEnd, m_Curve[last].value);\n                DrawCurveWrapped(minTime, maxTime, rangeStart, rangeEnd, preWrapMode, postWrapMode, m_CurveMesh, firstPoint, lastPoint, transform, color, wrapColor);\n            }\n        }\n\n        public static void DrawPolyLine(Matrix4x4 transform, float minDistance, params Vector3[] points)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            Color col = Handles.color * new Color(1, 1, 1, 0.75f);\n\n            HandleUtility.ApplyWireMaterial();\n            GL.PushMatrix();\n            GL.MultMatrix(Handles.matrix);\n            GL.Begin(GL.LINES);\n            GL.Color(col);\n\n            Vector3 previous = transform.MultiplyPoint(points[0]);\n            for (int i = 1; i < points.Length; i++)\n            {\n                Vector3 current = transform.MultiplyPoint(points[i]);\n\n                if ((previous - current).magnitude > minDistance)\n                {\n                    GL.Vertex(previous);\n                    GL.Vertex(current);\n\n                    previous = current;\n                }\n            }\n            GL.End();\n            GL.PopMatrix();\n        }\n\n        public static void DrawCurveWrapped(float minTime, float maxTime, float rangeStart, float rangeEnd,\n            WrapMode preWrap, WrapMode postWrap, Mesh mesh, Vector3 firstPoint, Vector3 lastPoint,\n            Matrix4x4 transform, Color color, Color wrapColor)\n        {\n            if (mesh.vertexCount == 0)\n                return;\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            int minRep;\n            int maxRep;\n            if (rangeEnd - rangeStart != 0)\n            {\n                minRep = Mathf.FloorToInt((minTime - rangeStart) / (rangeEnd - rangeStart));\n                maxRep = Mathf.CeilToInt((maxTime - rangeEnd) / (rangeEnd - rangeStart));\n\n                // Prevent too many loops from being rendered at one time.\n                if (minRep < -kMaximumLoops)\n                    preWrap = WrapMode.Clamp;\n                if (maxRep > kMaximumLoops)\n                    postWrap = WrapMode.Clamp;\n            }\n            else\n            {\n                preWrap = WrapMode.Clamp;\n                postWrap = WrapMode.Clamp;\n                minRep = (minTime < rangeStart ? -1 : 0);\n                maxRep = (maxTime > rangeEnd   ?  1 : 0);\n            }\n\n            // Draw curve itself\n            Material mat = curveMaterial;\n            mat.SetColor(\"_Color\", color);\n            Handles.color = color;\n\n            // Previous camera may still be active when calling DrawMeshNow.\n            Camera.SetupCurrent(null);\n\n            mat.SetPass(0);\n            Graphics.DrawMeshNow(mesh, Handles.matrix * transform);\n\n            // Draw wrapping\n            mat.SetColor(\"_Color\", new Color(wrapColor.r, wrapColor.g, wrapColor.b, wrapColor.a * color.a));\n            Handles.color = new Color(wrapColor.r, wrapColor.g, wrapColor.b, wrapColor.a * color.a);\n\n            // Draw pre wrapping\n            if (preWrap == WrapMode.Loop)\n            {\n                Matrix4x4 firstTransform = Handles.matrix * transform * Matrix4x4.TRS(new Vector3(minRep * (rangeEnd - rangeStart), 0.0f, 0.0f), Quaternion.identity, Vector3.one);\n                Matrix4x4 iterTransform = Matrix4x4.TRS(new Vector3(rangeEnd - rangeStart, 0.0f, 0.0f), Quaternion.identity, Vector3.one);\n\n                //  Render loop curve itself.\n                mat.SetPass(0);\n                Matrix4x4 curTransform = firstTransform;\n                for (int r = minRep; r < 0; ++r)\n                {\n                    Graphics.DrawMeshNow(mesh, curTransform);\n                    curTransform = curTransform * iterTransform;\n                }\n\n                //  Render straight lines connecting one loop to another.\n                curTransform = firstTransform;\n                for (int r = minRep; r < 0; ++r)\n                {\n                    Matrix4x4 nextTransform = curTransform * iterTransform;\n\n                    Handles.DrawLine(\n                        curTransform.MultiplyPoint(lastPoint),\n                        nextTransform.MultiplyPoint(firstPoint)\n                    );\n\n                    curTransform = nextTransform;\n                }\n            }\n            else if (preWrap == WrapMode.PingPong)\n            {\n                mat.SetPass(0);\n                for (int r = minRep; r < 0; ++r)\n                {\n                    //  Even loop\n                    if (r % 2 == 0)\n                    {\n                        Matrix4x4 shiftTransform = Matrix4x4.TRS(new Vector3(r * (rangeEnd - rangeStart), 0.0f, 0.0f), Quaternion.identity, Vector3.one);\n                        Graphics.DrawMeshNow(mesh, Handles.matrix * transform * shiftTransform);\n                    }\n                    //  Odd loop\n                    else\n                    {\n                        Matrix4x4 shiftTransform = Matrix4x4.TRS(new Vector3((r + 1) * (rangeEnd - rangeStart) + rangeStart * 2, 0.0f, 0.0f), Quaternion.identity, new Vector3(-1.0f, 1.0f, 1.0f));\n                        Graphics.DrawMeshNow(mesh, Handles.matrix * transform * shiftTransform);\n                    }\n                }\n            }\n            else\n            {\n                if (minRep < 0)\n                {\n                    Handles.DrawLine(\n                        transform.MultiplyPoint(new Vector3(minTime, firstPoint.y, 0)),\n                        transform.MultiplyPoint(new Vector3(Mathf.Min(maxTime, firstPoint.x), firstPoint.y, 0))\n                    );\n                }\n            }\n\n            // Draw post wrapping\n            if (postWrap == WrapMode.Loop)\n            {\n                Matrix4x4 firstTransform = Handles.matrix * transform;\n                Matrix4x4 iterTransform = Matrix4x4.TRS(new Vector3(rangeEnd - rangeStart, 0.0f, 0.0f), Quaternion.identity, Vector3.one);\n\n                //  Render straight lines connecting one loop to another.\n                Matrix4x4 prevTransform = firstTransform;\n                for (int r = 1; r <= maxRep; ++r)\n                {\n                    Matrix4x4 curTransform = prevTransform * iterTransform;\n\n                    Handles.DrawLine(\n                        prevTransform.MultiplyPoint(lastPoint),\n                        curTransform.MultiplyPoint(firstPoint)\n                    );\n\n                    prevTransform = curTransform;\n                }\n\n                //  Render loop curve itself.\n                mat.SetPass(0);\n                prevTransform = firstTransform;\n                for (int r = 1; r <= maxRep; ++r)\n                {\n                    Matrix4x4 curTransform = prevTransform * iterTransform;\n                    Graphics.DrawMeshNow(mesh, curTransform);\n                    prevTransform = curTransform;\n                }\n            }\n            else if (postWrap == WrapMode.PingPong)\n            {\n                mat.SetPass(0);\n                for (int r = 1; r <= maxRep; ++r)\n                {\n                    //  Even loop\n                    if (r % 2 == 0)\n                    {\n                        Matrix4x4 shiftTransform = Matrix4x4.TRS(new Vector3(r * (rangeEnd - rangeStart), 0.0f, 0.0f), Quaternion.identity, Vector3.one);\n                        Graphics.DrawMeshNow(mesh, Handles.matrix * transform * shiftTransform);\n                    }\n                    //  Odd loop\n                    else\n                    {\n                        Matrix4x4 shiftTransform = Matrix4x4.TRS(new Vector3((r + 1) * (rangeEnd - rangeStart) + rangeStart * 2, 0.0f, 0.0f), Quaternion.identity, new Vector3(-1.0f, 1.0f, 1.0f));\n                        Graphics.DrawMeshNow(mesh, Handles.matrix * transform * shiftTransform);\n                    }\n                }\n            }\n            else\n            {\n                if (maxRep > 0)\n                {\n                    Handles.DrawLine(\n                        transform.MultiplyPoint(new Vector3(Mathf.Max(minTime, lastPoint.x), lastPoint.y, 0)),\n                        transform.MultiplyPoint(new Vector3(maxTime, lastPoint.y, 0))\n                    );\n                }\n            }\n        }\n\n        public static void DrawCurveWrapped(float minTime, float maxTime, float rangeStart, float rangeEnd,\n            WrapMode preWrap, WrapMode postWrap, Color color, Matrix4x4 transform, Vector3[] points, Color wrapColor)\n        {\n            if (points.Length == 0)\n                return;\n\n            int minRep;\n            int maxRep;\n            if (rangeEnd - rangeStart != 0)\n            {\n                minRep = Mathf.FloorToInt((minTime - rangeStart) / (rangeEnd - rangeStart));\n                maxRep = Mathf.CeilToInt((maxTime - rangeEnd) / (rangeEnd - rangeStart));\n\n                // Prevent too many loops from being rendered at one time.\n                if (minRep < -kMaximumLoops)\n                    preWrap = WrapMode.Clamp;\n                if (maxRep > kMaximumLoops)\n                    postWrap = WrapMode.Clamp;\n            }\n            else\n            {\n                preWrap = WrapMode.Clamp;\n                postWrap = WrapMode.Clamp;\n                minRep = (minTime < rangeStart ? -1 : 0);\n                maxRep = (maxTime > rangeEnd   ?  1 : 0);\n            }\n            int last = points.Length - 1;\n\n            // Draw curve itself\n            Handles.color = color;\n            List<Vector3> line = new List<Vector3>();\n\n            if (minRep <= 0 && maxRep >= 0)\n            {\n                // Use line drawing with minimum segment length. Faster for large data sets\n                DrawPolyLine(transform, 2, points);\n            }\n            else\n                Handles.DrawPolyLine(points);\n\n            // Draw wrapping\n            Handles.color = new Color(wrapColor.r, wrapColor.g, wrapColor.b, wrapColor.a * color.a);\n\n            // Draw pre wrapping\n            if (preWrap == WrapMode.Loop)\n            {\n                line = new List<Vector3>();\n                for (int r = minRep; r < 0; r++)\n                {\n                    for (int i = 0; i < points.Length; i++)\n                    {\n                        Vector3 point = points[i];\n                        point.x += r * (rangeEnd - rangeStart);\n                        point = transform.MultiplyPoint(point);\n                        line.Add(point);\n                    }\n                }\n                line.Add(transform.MultiplyPoint(points[0]));\n                Handles.DrawPolyLine(line.ToArray());\n            }\n            else if (preWrap == WrapMode.PingPong)\n            {\n                line = new List<Vector3>();\n                for (int r = minRep; r < 0; r++)\n                {\n                    for (int i = 0; i < points.Length; i++)\n                    {\n                        if (r / 2 == r / 2f)\n                        {\n                            Vector3 point = points[i];\n                            point.x += r * (rangeEnd - rangeStart);\n                            point = transform.MultiplyPoint(point);\n                            line.Add(point);\n                        }\n                        else\n                        {\n                            Vector3 point = points[last - i];\n                            point.x = -point.x + (r + 1) * (rangeEnd - rangeStart) + rangeStart * 2;\n                            point = transform.MultiplyPoint(point);\n                            line.Add(point);\n                        }\n                    }\n                }\n                Handles.DrawPolyLine(line.ToArray());\n            }\n            else\n            {\n                if (minRep < 0)\n                {\n                    Handles.DrawPolyLine(new Vector3[]\n                    {\n                        transform.MultiplyPoint(new Vector3(minTime, points[0].y, 0)),\n                        transform.MultiplyPoint(new Vector3(Mathf.Min(maxTime, points[0].x), points[0].y, 0))\n                    });\n                }\n            }\n\n            // Draw post wrapping\n            if (postWrap == WrapMode.Loop)\n            {\n                line = new List<Vector3>();\n                line.Add(transform.MultiplyPoint(points[last]));\n                for (int r = 1; r <= maxRep; r++)\n                {\n                    for (int i = 0; i < points.Length; i++)\n                    {\n                        Vector3 point = points[i];\n                        point.x += r * (rangeEnd - rangeStart);\n                        point = transform.MultiplyPoint(point);\n                        line.Add(point);\n                    }\n                }\n                Handles.DrawPolyLine(line.ToArray());\n            }\n            else if (postWrap == WrapMode.PingPong)\n            {\n                line = new List<Vector3>();\n                for (int r = 1; r <= maxRep; r++)\n                {\n                    for (int i = 0; i < points.Length; i++)\n                    {\n                        if (r / 2 == r / 2f)\n                        {\n                            Vector3 point = points[i];\n                            point.x += r * (rangeEnd - rangeStart);\n                            point = transform.MultiplyPoint(point);\n                            line.Add(point);\n                        }\n                        else\n                        {\n                            Vector3 point = points[last - i];\n                            point.x = -point.x + (r + 1) * (rangeEnd - rangeStart) + rangeStart * 2;\n                            point = transform.MultiplyPoint(point);\n                            line.Add(point);\n                        }\n                    }\n                }\n                Handles.DrawPolyLine(line.ToArray());\n            }\n            else\n            {\n                if (maxRep > 0)\n                {\n                    Handles.DrawPolyLine(new Vector3[]\n                    {\n                        transform.MultiplyPoint(new Vector3(Mathf.Max(minTime, points[last].x), points[last].y, 0)),\n                        transform.MultiplyPoint(new Vector3(maxTime, points[last].y, 0))\n                    });\n                }\n            }\n        }\n\n        public Bounds GetBounds()\n        {\n            BuildCurveMesh();\n            if (m_Bounds == null)\n                m_Bounds = m_CurveMesh.bounds;\n\n            return m_Bounds.Value;\n        }\n\n        public Bounds GetBounds(float minTime, float maxTime)\n        {\n            Vector3[] points = GetPoints(minTime, maxTime);\n            float min = Mathf.Infinity;\n            float max = Mathf.NegativeInfinity;\n            for (int i = 0; i < points.Length; ++i)\n            {\n                Vector3 point = points[i];\n                if (point.y > max)\n                    max = point.y;\n                if (point.y < min)\n                    min = point.y;\n            }\n            if (min == Mathf.Infinity)\n            {\n                min = 0;\n                max = 0;\n            }\n            return new Bounds(new Vector3((maxTime + minTime) * 0.5f, (max + min) * 0.5f, 0), new Vector3(maxTime - minTime, max - min, 0));\n        }\n\n        public void FlushCache()\n        {\n            Object.DestroyImmediate(m_CurveMesh);\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/Deprecated/AnimationEventTimeline.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\nusing System.Linq;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    internal class AnimationEventTimeLine\n    {\n        internal static class Styles\n        {\n            public static GUIContent textAddEvent = EditorGUIUtility.TrTextContent(\"Add Animation Event\");\n            public static GUIContent textDeleteEvents = EditorGUIUtility.TrTextContent(\"Delete Animation Events\");\n            public static GUIContent textDeleteEvent = EditorGUIUtility.TrTextContent(\"Delete Animation Event\");\n            public static GUIContent textCopyEvents = EditorGUIUtility.TrTextContent(\"Copy Animation Events\");\n            public static GUIContent textPasteEvents = EditorGUIUtility.TrTextContent(\"Paste Animation Events\");\n        }\n\n        [System.NonSerialized]\n        private AnimationEvent[] m_EventsAtMouseDown;\n        [System.NonSerialized]\n        private float[] m_EventTimes;\n        private static readonly Vector2 k_EventMarkerSize = new Vector2(16, 16);\n\n        private bool m_DirtyTooltip = false;\n        private int m_HoverEvent = -1;\n        private string m_InstantTooltipText = null;\n        private Vector2 m_InstantTooltipPoint = Vector2.zero;\n        private bool m_HasSelectedEvents;\n\n        public AnimationEventTimeLine(EditorWindow owner)\n        {\n        }\n\n        public class EventComparer : IComparer<AnimationEvent>\n        {\n            public int Compare(AnimationEvent x, AnimationEvent y)\n            {\n                float timeX = x.time;\n                float timeY = y.time;\n                if (timeX != timeY)\n                    return ((int)Mathf.Sign(timeX - timeY));\n\n                int valueX = x.GetHashCode();\n                int valueY = y.GetHashCode();\n                return valueX - valueY;\n            }\n        }\n\n        private struct EventLineContextMenuObject\n        {\n            public GameObject m_Animated;\n            public AnimationClip m_Clip;\n            public float m_Time;\n            public int m_Index;\n            public bool[] m_Selected;\n\n            public EventLineContextMenuObject(GameObject animated, AnimationClip clip, float time, int index, bool[] selected)\n            {\n                m_Animated = animated;\n                m_Clip = clip;\n                m_Time = time;\n                m_Index = index;\n                m_Selected = selected;\n            }\n        }\n\n        internal bool HasSelectedEvents => m_HasSelectedEvents;\n\n        public void AddEvent(float time, GameObject gameObject, AnimationClip animationClip)\n        {\n            AnimationWindowEvent awEvent = AnimationWindowEvent.CreateAndEdit(gameObject, animationClip, time);\n            Selection.activeObject = awEvent;\n        }\n\n        public void EditEvents(GameObject gameObject, AnimationClip clip, bool[] selectedIndices)\n        {\n            List<AnimationWindowEvent> awEvents = new List<AnimationWindowEvent>();\n\n            for (int index = 0; index < selectedIndices.Length; ++index)\n            {\n                if (selectedIndices[index])\n                    awEvents.Add(AnimationWindowEvent.Edit(gameObject, clip, index));\n            }\n\n            if (awEvents.Count > 0)\n            {\n                Selection.objects = awEvents.ToArray();\n            }\n            else\n            {\n                ClearSelection();\n            }\n        }\n\n        public void EditEvent(GameObject gameObject, AnimationClip clip, int index)\n        {\n            AnimationWindowEvent awEvent = AnimationWindowEvent.Edit(gameObject, clip, index);\n            Selection.activeObject = awEvent;\n        }\n\n        public void ClearSelection()\n        {\n            // Do not unecessarily clear selection.  Only clear if selection already is animation window event.\n            if (Selection.activeObject is AnimationWindowEvent)\n                Selection.activeObject = null;\n        }\n\n        public void DeleteEvents(AnimationClip clip, bool[] deleteIndices)\n        {\n            bool deletedAny = false;\n\n            List<AnimationEvent> eventList = new List<AnimationEvent>(AnimationUtility.GetAnimationEvents(clip));\n            for (int i = eventList.Count - 1; i >= 0; i--)\n            {\n                if (deleteIndices[i])\n                {\n                    eventList.RemoveAt(i);\n                    deletedAny = true;\n                }\n            }\n\n            if (deletedAny)\n            {\n                Undo.RegisterCompleteObjectUndo(clip, \"Delete Event\");\n\n                AnimationUtility.SetAnimationEvents(clip, eventList.ToArray());\n                Selection.objects = new AnimationWindowEvent[] {};\n\n                m_DirtyTooltip = true;\n            }\n        }\n\n        void CopyEvents(AnimationClip clip, bool[] selected, int explicitIndex = -1)\n        {\n            var allEvents = new List<AnimationEvent>(AnimationUtility.GetAnimationEvents(clip));\n            AnimationWindowEventsClipboard.CopyEvents(allEvents, selected, explicitIndex);\n        }\n\n        internal void PasteEvents(GameObject animated, AnimationClip clip, float time)\n        {\n            var oldEvents = AnimationUtility.GetAnimationEvents(clip);\n            var newEvents = AnimationWindowEventsClipboard.AddPastedEvents(oldEvents, time, out var selected);\n            if (newEvents == null)\n                return;\n\n            Undo.RegisterCompleteObjectUndo(clip, \"Paste Events\");\n            EditEvents(animated, clip, selected);\n            AnimationUtility.SetAnimationEvents(clip, newEvents);\n            m_DirtyTooltip = true;\n        }\n\n        public void EventLineGUI(Rect rect, AnimationWindowState state)\n        {\n            //  We only display and manipulate animation events from the main\n            //  game object in selection.  If we ever want to update to handle\n            //  a multiple selection, a single timeline might not be sufficient...\n            AnimationClip clip = state.activeAnimationClip;\n            GameObject animated = state.activeRootGameObject;\n\n            GUI.BeginGroup(rect);\n            Color backupCol = GUI.color;\n\n            Rect eventLineRect = new Rect(0, 0, rect.width, rect.height);\n\n            float mousePosTime = Mathf.Max(Mathf.RoundToInt(state.PixelToTime(Event.current.mousePosition.x, rect) * state.frameRate) / state.frameRate, 0.0f);\n\n            // Draw events\n            if (clip != null)\n            {\n                AnimationEvent[] events = AnimationUtility.GetAnimationEvents(clip);\n                Texture eventMarker = EditorGUIUtility.IconContent(\"Animation.EventMarker\").image;\n\n                // Calculate rects\n                Rect[] hitRects = new Rect[events.Length];\n                Rect[] drawRects = new Rect[events.Length];\n                int shared = 1;\n                int sharedLeft = 0;\n                for (int i = 0; i < events.Length; i++)\n                {\n                    AnimationEvent evt = events[i];\n\n                    if (sharedLeft == 0)\n                    {\n                        shared = 1;\n                        while (i + shared < events.Length && events[i + shared].time == evt.time)\n                            shared++;\n                        sharedLeft = shared;\n                    }\n                    sharedLeft--;\n\n                    // Important to take floor of positions of GUI stuff to get pixel correct alignment of\n                    // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time.\n                    float keypos = Mathf.Floor(state.FrameToPixel(evt.time * clip.frameRate, rect));\n                    int sharedOffset = 0;\n                    if (shared > 1)\n                    {\n                        float spread = Mathf.Min((shared - 1) * (k_EventMarkerSize.x - 1), (int)(state.FrameDeltaToPixel(rect) - k_EventMarkerSize.x * 2));\n                        sharedOffset = Mathf.FloorToInt(Mathf.Max(0, spread - (k_EventMarkerSize.x - 1) * (sharedLeft)));\n                    }\n\n                    Rect r = new Rect(\n                        keypos + sharedOffset - k_EventMarkerSize.x / 2,\n                        (rect.height - 10) * (float)(sharedLeft - shared + 1) / Mathf.Max(1, shared - 1),\n                        k_EventMarkerSize.x,\n                        k_EventMarkerSize.y);\n\n                    hitRects[i] = r;\n                    drawRects[i] = r;\n                }\n\n                // Store tooptip info\n                if (m_DirtyTooltip)\n                {\n                    if (m_HoverEvent >= 0 && m_HoverEvent < hitRects.Length)\n                    {\n                        m_InstantTooltipText = AnimationWindowEventInspector.FormatEvent(animated, events[m_HoverEvent]);\n                        m_InstantTooltipPoint = new Vector2(hitRects[m_HoverEvent].xMin + (int)(hitRects[m_HoverEvent].width / 2) + rect.x - 30, rect.yMax);\n                    }\n                    m_DirtyTooltip = false;\n                }\n\n                bool[] selectedEvents = new bool[events.Length];\n                m_HasSelectedEvents = false;\n\n                Object[] selectedObjects = Selection.objects;\n                foreach (Object selectedObject in selectedObjects)\n                {\n                    AnimationWindowEvent awe = selectedObject as AnimationWindowEvent;\n                    if (awe != null)\n                    {\n                        if (awe.eventIndex >= 0 && awe.eventIndex < selectedEvents.Length)\n                        {\n                            selectedEvents[awe.eventIndex] = true;\n                            m_HasSelectedEvents = true;\n                        }\n                    }\n                }\n\n                Vector2 offset = Vector2.zero;\n                int clickedIndex;\n                float startSelection, endSelection;\n\n                // TODO: GUIStyle.none has hopping margins that need to be fixed\n                HighLevelEvent hEvent = EditorGUIExt.MultiSelection(\n                    rect,\n                    drawRects,\n                    new GUIContent(eventMarker),\n                    hitRects,\n                    ref selectedEvents,\n                    null,\n                    out clickedIndex,\n                    out offset,\n                    out startSelection,\n                    out endSelection,\n                    GUIStyle.none\n                );\n\n                if (hEvent != HighLevelEvent.None)\n                {\n                    switch (hEvent)\n                    {\n                        case HighLevelEvent.BeginDrag:\n                            m_EventsAtMouseDown = events;\n                            m_EventTimes = new float[events.Length];\n                            for (int i = 0; i < events.Length; i++)\n                                m_EventTimes[i] = events[i].time;\n                            break;\n                        case HighLevelEvent.SelectionChanged:\n                            state.ClearKeySelections();\n                            EditEvents(animated, clip, selectedEvents);\n                            break;\n                        case HighLevelEvent.Delete:\n                            DeleteEvents(clip, selectedEvents);\n                            break;\n                        case HighLevelEvent.Copy:\n                            CopyEvents(clip, selectedEvents);\n                            break;\n                        case HighLevelEvent.Paste:\n                            PasteEvents(animated, clip, state.currentTime);\n                            break;\n\n                        case HighLevelEvent.DoubleClick:\n\n                            if (clickedIndex != -1)\n                                EditEvents(animated, clip, selectedEvents);\n                            else\n                                EventLineContextMenuAdd(new EventLineContextMenuObject(animated, clip, mousePosTime, -1, selectedEvents));\n                            break;\n                        case HighLevelEvent.Drag:\n                            for (int i = events.Length - 1; i >= 0; i--)\n                            {\n                                if (selectedEvents[i])\n                                {\n                                    AnimationEvent evt = m_EventsAtMouseDown[i];\n                                    evt.time = m_EventTimes[i] + offset.x * state.PixelDeltaToTime(rect);\n                                    evt.time = Mathf.Max(0.0F, evt.time);\n                                    evt.time = Mathf.RoundToInt(evt.time * clip.frameRate) / clip.frameRate;\n                                }\n                            }\n                            int[] order = new int[selectedEvents.Length];\n                            for (int i = 0; i < order.Length; i++)\n                            {\n                                order[i] = i;\n                            }\n                            System.Array.Sort(m_EventsAtMouseDown, order, new EventComparer());\n                            bool[] selectedOld = (bool[])selectedEvents.Clone();\n                            float[] timesOld = (float[])m_EventTimes.Clone();\n                            for (int i = 0; i < order.Length; i++)\n                            {\n                                selectedEvents[i] = selectedOld[order[i]];\n                                m_EventTimes[i] = timesOld[order[i]];\n                            }\n\n                            // Update selection to reflect new order.\n                            EditEvents(animated, clip, selectedEvents);\n\n                            Undo.RegisterCompleteObjectUndo(clip, \"Move Event\");\n                            AnimationUtility.SetAnimationEvents(clip, m_EventsAtMouseDown);\n                            m_DirtyTooltip = true;\n                            break;\n                        case HighLevelEvent.ContextClick:\n                            CreateContextMenu(animated, clip, events[clickedIndex].time, clickedIndex, selectedEvents);\n\n                            // Mouse may move while context menu is open - make sure instant tooltip is handled\n                            m_InstantTooltipText = null;\n                            m_DirtyTooltip = true;\n                            state.Repaint();\n                            break;\n                    }\n                }\n\n                CheckRectsOnMouseMove(rect, events, hitRects);\n\n                // Bring up menu when context-clicking on an empty timeline area (context-clicking on events is handled above)\n                if (Event.current.type == EventType.ContextClick && eventLineRect.Contains(Event.current.mousePosition))\n                {\n                    Event.current.Use();\n                    CreateContextMenu(animated, clip, mousePosTime, -1, selectedEvents);\n                }\n            }\n\n            GUI.color = backupCol;\n            GUI.EndGroup();\n        }\n\n        void CreateContextMenu(GameObject animatedGo, AnimationClip clip, float time, int eventIndex, bool[] selectedEvents)\n        {\n            GenericMenu menu = new GenericMenu();\n            var contextData = new EventLineContextMenuObject(animatedGo, clip, time, eventIndex, selectedEvents);\n            var selectedCount = selectedEvents.Count(selected => selected);\n\n            menu.AddItem(Styles.textAddEvent, false, EventLineContextMenuAdd, contextData);\n            if (selectedCount > 0 || eventIndex != -1)\n            {\n                menu.AddItem(selectedCount > 1 ? Styles.textDeleteEvents : Styles.textDeleteEvent, false, EventLineContextMenuDelete, contextData);\n                menu.AddItem(Styles.textCopyEvents, false, EventLineContextMenuCopy, contextData);\n            }\n            else\n            {\n                menu.AddDisabledItem(Styles.textDeleteEvents);\n                menu.AddDisabledItem(Styles.textCopyEvents);\n            }\n            if (AnimationWindowEventsClipboard.CanPaste())\n                menu.AddItem(Styles.textPasteEvents, false, EventLineContextMenuPaste, contextData);\n            else\n                menu.AddDisabledItem(Styles.textPasteEvents);\n            menu.ShowAsContext();\n        }\n\n        public void DrawInstantTooltip(Rect position)\n        {\n            if (!string.IsNullOrEmpty(m_InstantTooltipText))\n            {\n                // Draw body of tooltip\n                GUIStyle style = (GUIStyle)\"AnimationEventTooltip\";\n\n                // TODO: Move to editor_resources\n                style.contentOffset = new Vector2(0f, 0f);\n                style.overflow = new RectOffset(10, 10, 0, 0);\n\n                Vector2 size = style.CalcSize(new GUIContent(m_InstantTooltipText));\n                Rect rect = new Rect(m_InstantTooltipPoint.x - size.x * .5f, m_InstantTooltipPoint.y + 24, size.x, size.y);\n\n                // Right align tooltip rect if it would otherwise exceed the bounds of the window\n                if (rect.xMax > position.width)\n                    rect.x = position.width - rect.width;\n\n                GUI.Label(rect, m_InstantTooltipText, style);\n\n                // Draw arrow of tooltip\n                rect = new Rect(m_InstantTooltipPoint.x - 33, m_InstantTooltipPoint.y, 7, 25);\n                GUI.Label(rect, \"\", \"AnimationEventTooltipArrow\");\n            }\n        }\n\n        public void EventLineContextMenuAdd(object obj)\n        {\n            EventLineContextMenuObject eventObj = (EventLineContextMenuObject)obj;\n            AddEvent(eventObj.m_Time, eventObj.m_Animated, eventObj.m_Clip);\n        }\n\n        public void EventLineContextMenuEdit(object obj)\n        {\n            EventLineContextMenuObject eventObj = (EventLineContextMenuObject)obj;\n\n            if (Array.Exists(eventObj.m_Selected, selected => selected))\n            {\n                EditEvents(eventObj.m_Animated, eventObj.m_Clip, eventObj.m_Selected);\n            }\n            else if (eventObj.m_Index >= 0)\n            {\n                EditEvent(eventObj.m_Animated, eventObj.m_Clip, eventObj.m_Index);\n            }\n        }\n\n        public void EventLineContextMenuDelete(object obj)\n        {\n            EventLineContextMenuObject eventObj = (EventLineContextMenuObject)obj;\n            AnimationClip clip = eventObj.m_Clip;\n            if (clip == null)\n                return;\n\n            int clickedIndex = eventObj.m_Index;\n\n            // If a selection already exists, delete selection instead of clicked index\n            if (Array.Exists(eventObj.m_Selected, selected => selected))\n            {\n                DeleteEvents(clip, eventObj.m_Selected);\n            }\n            // Else, only delete the clicked animation event\n            else if (clickedIndex >= 0)\n            {\n                bool[] deleteIndices = new bool[eventObj.m_Selected.Length];\n                deleteIndices[clickedIndex] = true;\n                DeleteEvents(clip, deleteIndices);\n            }\n        }\n\n        void EventLineContextMenuCopy(object obj)\n        {\n            var ctx = (EventLineContextMenuObject)obj;\n            var clip = ctx.m_Clip;\n            if (clip != null)\n                CopyEvents(clip, ctx.m_Selected, ctx.m_Index);\n        }\n\n        void EventLineContextMenuPaste(object obj)\n        {\n            var ctx = (EventLineContextMenuObject)obj;\n            AnimationClip clip = ctx.m_Clip;\n            if (clip != null)\n                PasteEvents(ctx.m_Animated, clip, ctx.m_Time);\n        }\n\n        private void CheckRectsOnMouseMove(Rect eventLineRect, AnimationEvent[] events, Rect[] hitRects)\n        {\n            Vector2 mouse = Event.current.mousePosition;\n            bool hasFound = false;\n\n            if (events.Length == hitRects.Length)\n            {\n                for (int i = hitRects.Length - 1; i >= 0; i--)\n                {\n                    if (hitRects[i].Contains(mouse))\n                    {\n                        hasFound = true;\n                        if (m_HoverEvent != i)\n                        {\n                            m_HoverEvent = i;\n                            m_InstantTooltipText = events[m_HoverEvent].functionName;\n                            m_InstantTooltipPoint = new Vector2(hitRects[m_HoverEvent].xMin + (int)(hitRects[m_HoverEvent].width / 2) + eventLineRect.x, eventLineRect.yMax);\n                            m_DirtyTooltip = true;\n                        }\n                    }\n                }\n            }\n            if (!hasFound)\n            {\n                m_HoverEvent = -1;\n                m_InstantTooltipText = \"\";\n            }\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/Deprecated/EditorGUIExt.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class EditorGUIExt\n    {\n        class Styles\n        {\n            public GUIStyle selectionRect = \"SelectionRect\";\n        }\n        static Styles ms_Styles = new Styles();\n\n        // Copied from GUI class and modified slightly to not require\n        // calls to methods that are internal to the GUI class\n        static bool DoRepeatButton(Rect position, GUIContent content, GUIStyle style, FocusType focusType)\n        {\n            //GUIUtility.CheckOnGUI ();\n            int id = GUIUtility.GetControlID(repeatButtonHash, focusType, position);\n            switch (Event.current.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    // If the mouse is inside the button, we say that we're the hot control\n                    if (position.Contains(Event.current.mousePosition))\n                    {\n                        GUIUtility.hotControl = id;\n                        Event.current.Use();\n                    }\n                    return false;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n\n                        // If we got the mousedown, the mouseup is ours as well\n                        // (no matter if the click was in the button or not)\n                        Event.current.Use();\n\n                        // But we only return true if the button was actually clicked\n                        return position.Contains(Event.current.mousePosition);\n                    }\n                    return false;\n                case EventType.Repaint:\n                    style.Draw(position, content, id, false, position.Contains(Event.current.mousePosition));\n                    return id == GUIUtility.hotControl && position.Contains(Event.current.mousePosition);\n            }\n            return false;\n        }\n\n        static int repeatButtonHash = \"repeatButton\".GetHashCode();\n\n        static float nextScrollStepTime = 0;\n        static int firstScrollWait = 250; // ms\n        static int scrollWait = 30; // ms\n\n        /// *undocumented*\n        // Copied from GUI class and modified slightly to not require\n        // calls to methods that are internal to the GUI class\n        static bool ScrollerRepeatButton(int scrollerID, Rect rect, GUIStyle style)\n        {\n            bool changed = false;\n\n            if (DoRepeatButton(rect, GUIContent.none, style, FocusType.Passive))\n            {\n                bool firstClick = scrollControlID != scrollerID;\n                scrollControlID = scrollerID;\n\n                if (firstClick)\n                {\n                    changed = true;\n                    nextScrollStepTime = Time.realtimeSinceStartup + 0.001f * firstScrollWait;\n                }\n                else\n                {\n                    if (Time.realtimeSinceStartup >= nextScrollStepTime)\n                    {\n                        changed = true;\n                        nextScrollStepTime = Time.realtimeSinceStartup + 0.001f * scrollWait;\n                    }\n                }\n\n                if (Event.current.type == EventType.Repaint)\n                    //  GUI.InternalRepaintEditorWindow();\n                    HandleUtility.Repaint();\n            }\n\n            return changed;\n        }\n\n        static int scrollControlID;\n        public static void MinMaxScroller(Rect position, int id, ref float value, ref float size, float visualStart, float visualEnd, float startLimit, float endLimit, GUIStyle slider, GUIStyle thumb, GUIStyle leftButton, GUIStyle rightButton, bool horiz)\n        {\n            //GUIUtility.CheckOnGUI ();\n\n            float scrollStepSize;\n            if (horiz)\n                scrollStepSize = size * 10 / position.width;\n            else\n                scrollStepSize = size * 10 / position.height;\n\n            //\n\n            Rect sliderRect, minRect, maxRect;\n\n            if (horiz)\n            {\n                sliderRect = new Rect(\n                    position.x + leftButton.fixedWidth, position.y,\n                    position.width - leftButton.fixedWidth - rightButton.fixedWidth, position.height\n                );\n                minRect = new Rect(position.x, position.y, leftButton.fixedWidth, position.height);\n                maxRect = new Rect(position.xMax - rightButton.fixedWidth, position.y, rightButton.fixedWidth, position.height);\n            }\n            else\n            {\n                sliderRect = new Rect(\n                    position.x, position.y + leftButton.fixedHeight,\n                    position.width, position.height - leftButton.fixedHeight - rightButton.fixedHeight\n                );\n                minRect = new Rect(position.x, position.y, position.width, leftButton.fixedHeight);\n                maxRect = new Rect(position.x, position.yMax - rightButton.fixedHeight, position.width, rightButton.fixedHeight);\n            }\n\n            float newVisualStart = Mathf.Min(visualStart, value);\n            float newVisualEnd   = Mathf.Max(visualEnd  , value + size);\n\n            MinMaxSlider(sliderRect, ref value, ref size, newVisualStart, newVisualEnd, newVisualStart, newVisualEnd, slider, thumb, horiz);\n\n            if (ScrollerRepeatButton(id, minRect, leftButton))\n                value -= scrollStepSize * (visualStart < visualEnd ? 1f : -1f);\n\n            if (ScrollerRepeatButton(id, maxRect, rightButton))\n                value += scrollStepSize * (visualStart < visualEnd ? 1f : -1f);\n\n            if (Event.current.type == EventType.MouseUp && Event.current.type == EventType.Used) // repeat buttons ate mouse up event - release scrolling\n                scrollControlID = 0;\n\n            if (startLimit < endLimit)\n                value = Mathf.Clamp(value, startLimit, endLimit - size);\n            else\n                value = Mathf.Clamp(value, endLimit, startLimit - size);\n        }\n\n        // State for when we're dragging a MinMax slider.\n        class MinMaxSliderState\n        {\n            public float dragStartPos = 0;      // Start of the drag (mousePosition)\n            public float dragStartValue = 0;        // Value at start of drag.\n            public float dragStartSize = 0;     // Size at start of drag.\n            public float dragStartValuesPerPixel = 0;\n            public float dragStartLimit = 0;        // start limit at start of drag\n            public float dragEndLimit = 0;      // end limit at start of drag\n            public int whereWeDrag = -1;        // which part are we dragging? 0 = middle, 1 = min, 2 = max, 3 = min trough, 4 = max trough\n        }\n\n        static MinMaxSliderState s_MinMaxSliderState;\n        static int kFirstScrollWait = 250; // ms\n        static int kScrollWait = 30; // ms\n        static System.DateTime s_NextScrollStepTime = System.DateTime.Now; // whatever but null\n\n        // Mouse down position for\n        private static Vector2 s_MouseDownPos = Vector2.zero;\n        // Are we doing a drag selection (as opposed to when the mousedown was over a selection rect)\n        enum DragSelectionState\n        {\n            None, DragSelecting, Dragging\n        }\n        static DragSelectionState s_MultiSelectDragSelection = DragSelectionState.None;\n        static Vector2 s_StartSelectPos = Vector2.zero;\n        static List<bool> s_SelectionBackup = null;\n        static List<bool> s_LastFrameSelections = null;\n        internal static int s_MinMaxSliderHash = \"MinMaxSlider\".GetHashCode();\n        /// Make a double-draggable slider that will let you specify a range of values.\n        /// @param position where to draw it\n        /// @param value the current start position\n        /// @param size the size of the covered range\n        /// @param visualStart what is displayed as the start of the range. The user can drag beyond this, but the displays shows this as the limit. Set this to be the start of the relevant data.\n        /// @param visualEnd what is displayed as the end of the range. The user can drag beyond this, but the displays shows this as the limit. Set this to be the end of the relevant data.\n        /// @param startLimit what is the lowest possible value? The user can never slide beyond this in the minimum direction. If you don't want a limit, set it to -Mathf.Infinity\n        /// @param endLimit what is the highes possible value? The user can never slide beyond this in the maximum direction. If you don't want a limit, set it to Mathf.Infinity\n        public static void MinMaxSlider(Rect position, ref float value, ref float size, float visualStart, float visualEnd, float startLimit, float endLimit, GUIStyle slider, GUIStyle thumb, bool horiz)\n        {\n            DoMinMaxSlider(position, GUIUtility.GetControlID(s_MinMaxSliderHash, FocusType.Passive), ref value, ref size, visualStart, visualEnd, startLimit, endLimit, slider, thumb, horiz);\n        }\n\n        private static float ThumbSize(bool horiz, GUIStyle thumb)\n        {\n            if (horiz)\n                return thumb.fixedWidth != 0 ? thumb.fixedWidth : thumb.padding.horizontal;\n            return thumb.fixedHeight != 0 ? thumb.fixedHeight : thumb.padding.vertical;\n        }\n\n        internal static void DoMinMaxSlider(Rect position, int id, ref float value, ref float size, float visualStart, float visualEnd, float startLimit, float endLimit, GUIStyle slider, GUIStyle thumb, bool horiz)\n        {\n            Event evt = Event.current;\n            bool usePageScrollbars = size == 0;\n\n            float minVisual = Mathf.Min(visualStart, visualEnd);\n            float maxVisual = Mathf.Max(visualStart, visualEnd);\n            float minLimit = Mathf.Min(startLimit, endLimit);\n            float maxLimit = Mathf.Max(startLimit, endLimit);\n\n            MinMaxSliderState state = s_MinMaxSliderState;\n\n            if (GUIUtility.hotControl == id && state != null)\n            {\n                minVisual = state.dragStartLimit;\n                minLimit = state.dragStartLimit;\n                maxVisual = state.dragEndLimit;\n                maxLimit = state.dragEndLimit;\n            }\n\n            float minSize = 0;\n\n            float displayValue = Mathf.Clamp(value, minVisual, maxVisual);\n            float displaySize = Mathf.Clamp(value + size, minVisual, maxVisual) - displayValue;\n\n            float sign = visualStart > visualEnd ? -1 : 1;\n\n\n            if (slider == null || thumb == null)\n                return;\n\n            // Figure out the rects\n            float pixelsPerValue;\n            float mousePosition;\n            Rect thumbRect;\n            Rect thumbMinRect, thumbMaxRect;\n            Rect contentRect = thumb.margin.Remove(slider.padding.Remove(position));\n            float thumbSize = ThumbSize(horiz, thumb);\n\n            if (horiz)\n            {\n                float thumbHeight = (thumb.fixedHeight != 0 ? thumb.fixedHeight : contentRect.height);\n\n                pixelsPerValue = (position.width - slider.padding.horizontal - thumbSize) / (maxVisual - minVisual);\n                thumbRect = new Rect(\n                    (displayValue - minVisual) * pixelsPerValue + contentRect.x,\n                    contentRect.y,\n                    displaySize * pixelsPerValue + thumbSize,\n                    thumbHeight);\n                thumbMinRect = new Rect(thumbRect.x, thumbRect.y, thumb.padding.left, thumbRect.height);\n                thumbMaxRect = new Rect(thumbRect.xMax - thumb.padding.right, thumbRect.y, thumb.padding.right, thumbRect.height);\n                mousePosition = evt.mousePosition.x - position.x;\n            }\n            else\n            {\n                float thumbWidth = (thumb.fixedWidth != 0 ? thumb.fixedWidth : contentRect.width);\n\n                pixelsPerValue = (position.height - slider.padding.vertical - thumbSize) / (maxVisual - minVisual);\n                thumbRect = new Rect(\n                    contentRect.x,\n                    (displayValue - minVisual) * pixelsPerValue + contentRect.y,\n                    thumbWidth,\n                    displaySize * pixelsPerValue + thumbSize);\n                thumbMinRect = new Rect(thumbRect.x, thumbRect.y, thumbRect.width, thumb.padding.top);\n                thumbMaxRect = new Rect(thumbRect.x, thumbRect.yMax - thumb.padding.bottom, thumbRect.width, thumb.padding.bottom);\n                mousePosition = evt.mousePosition.y - position.y;\n            }\n\n            float mousePos;\n            float thumbPos;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    // if the click is outside this control, just bail out...\n                    if (evt.button != 0 || !position.Contains(evt.mousePosition) || minVisual - maxVisual == 0)\n                        return;\n                    if (state == null)\n                        state = s_MinMaxSliderState = new MinMaxSliderState();\n\n                    // These are required to be set whenever we grab hotcontrol, regardless of if we actually drag or not. (case 585577)\n                    state.dragStartLimit = startLimit;\n                    state.dragEndLimit = endLimit;\n\n                    if (thumbRect.Contains(evt.mousePosition))\n                    {\n                        // We have a mousedown on the thumb\n                        // Record where we're draging from, so the user can get back.\n                        state.dragStartPos = mousePosition;\n                        state.dragStartValue = value;\n                        state.dragStartSize = size;\n                        state.dragStartValuesPerPixel = pixelsPerValue;\n                        if (thumbMinRect.Contains(evt.mousePosition))\n                            state.whereWeDrag = 1;\n                        else if (thumbMaxRect.Contains(evt.mousePosition))\n                            state.whereWeDrag = 2;\n                        else\n                            state.whereWeDrag = 0;\n\n                        GUIUtility.hotControl = id;\n                        evt.Use();\n                        return;\n                    }\n                    else\n                    {\n                        // We're outside the thumb, but inside the trough.\n                        // If we have no background, we just bail out.\n                        if (slider == GUIStyle.none)\n                            return;\n\n                        // If we have a scrollSize, we do pgup/pgdn style movements\n                        // if not, we just snap to the current position and begin tracking\n                        if (size != 0 && usePageScrollbars)\n                        {\n                            if (horiz)\n                            {\n                                if (mousePosition > thumbRect.xMax - position.x)\n                                    value += size * sign * .9f;\n                                else\n                                    value -= size * sign * .9f;\n                            }\n                            else\n                            {\n                                if (mousePosition > thumbRect.yMax - position.y)\n                                    value += size * sign * .9f;\n                                else\n                                    value -= size * sign * .9f;\n                            }\n                            state.whereWeDrag = 0;\n                            GUI.changed = true;\n                            s_NextScrollStepTime = System.DateTime.Now.AddMilliseconds(kFirstScrollWait);\n\n                            mousePos = horiz ? evt.mousePosition.x : evt.mousePosition.y;\n                            thumbPos = horiz ? thumbRect.x : thumbRect.y;\n\n                            state.whereWeDrag = mousePos > thumbPos ? 4 : 3;\n                        }\n                        else\n                        {\n                            if (horiz)\n                                value = ((float)mousePosition - thumbRect.width * .5f) / pixelsPerValue + minVisual - size * .5f;\n                            else\n                                value = ((float)mousePosition - thumbRect.height * .5f) / pixelsPerValue + minVisual - size * .5f;\n                            state.dragStartPos = mousePosition;\n                            state.dragStartValue = value;\n                            state.dragStartSize = size;\n                            state.dragStartValuesPerPixel = pixelsPerValue;\n                            state.whereWeDrag = 0;\n                            GUI.changed = true;\n                        }\n                        GUIUtility.hotControl = id;\n                        value = Mathf.Clamp(value, minLimit, maxLimit - size);\n                        evt.Use();\n                        return;\n                    }\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl != id)\n                        return;\n\n                    // Recalculate the value from the mouse position. this has the side effect that values are relative to the\n                    // click point - no matter where inside the trough the original value was. Also means user can get back original value\n                    // if he drags back to start position.\n                    float deltaVal = (mousePosition - state.dragStartPos) / state.dragStartValuesPerPixel;\n                    switch (state.whereWeDrag)\n                    {\n                        case 0: // normal drag\n                            value = Mathf.Clamp(state.dragStartValue + deltaVal, minLimit, maxLimit - size);\n                            break;\n                        case 1:// min size drag\n                            value = state.dragStartValue + deltaVal;\n                            size = state.dragStartSize - deltaVal;\n                            if (value < minLimit)\n                            {\n                                size -= minLimit - value;\n                                value = minLimit;\n                            }\n                            if (size < minSize)\n                            {\n                                value -= minSize - size;\n                                size = minSize;\n                            }\n                            break;\n                        case 2:// max size drag\n                            size = state.dragStartSize + deltaVal;\n                            if (value + size > maxLimit)\n                                size = maxLimit - value;\n                            if (size < minSize)\n                                size = minSize;\n                            break;\n                    }\n                    GUI.changed = true;\n                    evt.Use();\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        evt.Use();\n                        GUIUtility.hotControl = 0;\n                    }\n                    break;\n                case EventType.Repaint:\n                    slider.Draw(position, GUIContent.none, id);\n                    thumb.Draw(thumbRect, GUIContent.none, id);\n\n                    EditorGUIUtility.AddCursorRect(thumbMinRect, horiz ? MouseCursor.ResizeHorizontal : MouseCursor.ResizeVertical, state != null && state.whereWeDrag == 1 ? id : -1);\n                    EditorGUIUtility.AddCursorRect(thumbMaxRect, horiz ? MouseCursor.ResizeHorizontal : MouseCursor.ResizeVertical, state != null && state.whereWeDrag == 2 ? id : -1);\n\n                    // if the mouse is outside this control, just bail out...\n                    if (GUIUtility.hotControl != id ||\n                        !position.Contains(evt.mousePosition) || minVisual - maxVisual == 0)\n                    {\n                        return;\n                    }\n\n                    if (thumbRect.Contains(evt.mousePosition))\n                    {\n                        if (state != null && (state.whereWeDrag == 3 || state.whereWeDrag == 4)) // if was scrolling with \"through\" and the thumb reached mouse - sliding action over\n                            GUIUtility.hotControl = 0;\n                        return;\n                    }\n\n\n                    if (System.DateTime.Now < s_NextScrollStepTime)\n                        return;\n\n                    mousePos = horiz ? evt.mousePosition.x : evt.mousePosition.y;\n                    thumbPos = horiz ? thumbRect.x : thumbRect.y;\n\n                    int currentSide = mousePos > thumbPos ? 4 : 3;\n                    if (state != null && currentSide != state.whereWeDrag)\n                        return;\n\n                    // If we have a scrollSize, we do pgup/pgdn style movements\n                    if (size != 0 && usePageScrollbars)\n                    {\n                        if (horiz)\n                        {\n                            if (mousePosition > thumbRect.xMax - position.x)\n                                value += size * sign * .9f;\n                            else\n                                value -= size * sign * .9f;\n                        }\n                        else\n                        {\n                            if (mousePosition > thumbRect.yMax - position.y)\n                                value += size * sign * .9f;\n                            else\n                                value -= size * sign * .9f;\n                        }\n                        if (state != null)\n                            state.whereWeDrag = -1;\n                        GUI.changed = true;\n                    }\n                    value = Mathf.Clamp(value, minLimit, maxLimit - size);\n\n                    s_NextScrollStepTime = System.DateTime.Now.AddMilliseconds(kScrollWait);\n                    break;\n            }\n        }\n\n        private static bool adding = false;\n        private static bool[] initSelections;\n        private static int initIndex = 0;\n\n        // Used for selecting multiple rows on the left in the animation window.\n        public static bool DragSelection(Rect[] positions, ref bool[] selections, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(34553287, FocusType.Keyboard);\n            Event evt = Event.current;\n            int selectedIndex = -1;\n            for (int i = positions.Length - 1; i >= 0; i--)\n                if (positions[i].Contains(evt.mousePosition))\n                {\n                    selectedIndex = i;\n                    break;\n                }\n\n            EventType type = evt.GetTypeForControl(id);\n            switch (type)\n            {\n                case EventType.Repaint:\n                    for (int i = 0; i < positions.Length; i++)\n                        style.Draw(positions[i], GUIContent.none, id, selections[i]);\n                    break;\n                case EventType.MouseDown:\n                    if (evt.button == 0 && selectedIndex >= 0)\n                    {\n                        GUIUtility.keyboardControl = 0;\n\n                        bool deselecting = false;\n                        // If clicking on an already selected item\n                        if (selections[selectedIndex])\n                        {\n                            int counter = 0;\n                            foreach (bool sel in selections)\n                            {\n                                if (sel)\n                                {\n                                    counter++;\n                                    if (counter > 1)\n                                        break;\n                                }\n                            }\n                            // ...and it's the only one selected, then deselect it\n                            if (counter == 1)\n                                deselecting = true;\n                        }\n\n                        // Shift click to add to current selection\n                        if (!evt.shift && !EditorGUI.actionKey)\n                            for (int i = 0; i < positions.Length; i++)\n                                selections[i] = false;\n\n                        initIndex = selectedIndex;\n                        initSelections = (bool[])selections.Clone();\n\n                        // Command click to toggle\n                        adding = true;\n                        if ((evt.shift || EditorGUI.actionKey) && selections[selectedIndex] == true)\n                            adding = false;\n\n                        selections[selectedIndex] = (deselecting ? false : adding);\n                        GUIUtility.hotControl = id;\n                        evt.Use();\n\n                        return true;\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        if (evt.button == 0)\n                        {\n                            if (selectedIndex < 0)\n                            {\n                                // Clamp index to nearest positions if outside of range\n                                // (so that less precision is required for hitting the last rect)\n                                Rect dummyRect = new Rect(positions[0].x, positions[0].y - 200, positions[0].width, 200);\n                                if (dummyRect.Contains(evt.mousePosition))\n                                    selectedIndex = 0;\n                                dummyRect.y = positions[positions.Length - 1].yMax;\n                                if (dummyRect.Contains(evt.mousePosition))\n                                    selectedIndex = selections.Length - 1;\n                            }\n                            if (selectedIndex < 0)\n                                return false;\n\n                            int min = Mathf.Min(initIndex, selectedIndex);\n                            int max = Mathf.Max(initIndex, selectedIndex);\n                            for (int i = 0; i < selections.Length; i++)\n                            {\n                                if (i >= min && i <= max)\n                                    selections[i] = adding;\n                                else\n                                    selections[i] = initSelections[i];\n                            }\n                            evt.Use();\n                            return true;\n                        }\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                        GUIUtility.hotControl = 0;\n                    break;\n            }\n\n            return false;\n        }\n\n        static bool Any(bool[] selections)\n        {\n            for (int i = 0; i < selections.Length; i++)\n            {\n                if (selections[i])\n                    return true;\n            }\n            return false;\n        }\n\n        public static HighLevelEvent MultiSelection(\n            Rect rect,\n            Rect[] positions,\n            GUIContent content,\n            Rect[] hitPositions,\n            ref bool[] selections,\n            bool[] readOnly,\n            out int clickedIndex,\n            out Vector2 offset,\n            out float startSelect,\n            out float endSelect,\n            GUIStyle style\n        )\n        {\n            int id = GUIUtility.GetControlID(41623453, FocusType.Keyboard);\n            Event evt = Event.current;\n\n            offset = Vector2.zero;\n            clickedIndex = -1;\n            startSelect = endSelect = 0f;\n\n            if (evt.type == EventType.Used)\n                return HighLevelEvent.None;\n\n            bool selected = false;\n            if (Event.current.type != EventType.Layout)\n            {\n                if (GUIUtility.keyboardControl == id)\n                    selected = true;\n            }\n\n            int selectedIndex;\n\n            EventType type = evt.GetTypeForControl(id);\n            switch (type)\n            {\n                case EventType.Repaint:\n                    // Draw selection rect\n                    if (GUIUtility.hotControl == id && s_MultiSelectDragSelection == DragSelectionState.DragSelecting)\n                    {\n                        float min = Mathf.Min(s_StartSelectPos.x, evt.mousePosition.x);\n                        float max = Mathf.Max(s_StartSelectPos.x, evt.mousePosition.x);\n                        Rect selRect = new Rect(0, 0, rect.width, rect.height);\n                        selRect.x = min;\n                        selRect.width = max - min;\n                        // Display if bigger than 1 pixel.\n                        if (selRect.width > 1)\n                            GUI.Box(selRect, \"\", ms_Styles.selectionRect);\n                    }\n\n                    // Draw controls\n                    Color tempCol = GUI.color;\n                    for (int i = 0; i < positions.Length; i++)\n                    {\n                        if (readOnly != null && readOnly[i])\n                            GUI.color = tempCol * new Color(0.90f, 0.90f, 0.90f, 0.5f);\n                        else if (selections[i])\n                            GUI.color = tempCol * new Color(0.30f, 0.55f, 0.95f, 1);\n                        else\n                            GUI.color = tempCol * new Color(0.90f, 0.90f, 0.90f, 1);\n                        style.Draw(positions[i], content, id, selections[i]);\n                    }\n                    GUI.color = tempCol;\n                    break;\n                case EventType.MouseDown:\n                    if (evt.button == 0)\n                    {\n                        GUIUtility.hotControl = id;\n                        GUIUtility.keyboardControl = id;\n                        s_StartSelectPos = evt.mousePosition;\n                        selectedIndex = GetIndexUnderMouse(hitPositions, readOnly);\n\n                        if (Event.current.clickCount == 2)\n                        {\n                            if (selectedIndex >= 0)\n                            {\n                                for (int i = 0; i < selections.Length; i++)\n                                    selections[i] = false;\n\n                                selections[selectedIndex] = true;\n\n                                evt.Use();\n                                clickedIndex = selectedIndex;\n                                return HighLevelEvent.DoubleClick;\n                            }\n                        }\n\n                        if (selectedIndex >= 0)\n                        {\n                            // Shift click to add to current selection\n                            if (!evt.shift && !EditorGUI.actionKey && !selections[selectedIndex])\n                                for (int i = 0; i < hitPositions.Length; i++)\n                                    selections[i] = false;\n\n                            if (evt.shift || EditorGUI.actionKey)\n                                selections[selectedIndex] = !selections[selectedIndex];\n                            else\n                                selections[selectedIndex] = true;\n\n                            s_MouseDownPos = evt.mousePosition;\n                            s_MultiSelectDragSelection = DragSelectionState.None;\n                            evt.Use();\n                            clickedIndex = selectedIndex;\n                            return HighLevelEvent.SelectionChanged;\n                        }\n                        else\n                        {\n                            // Shift click to add to current selection\n                            bool changed = false;\n                            if (!evt.shift && !EditorGUI.actionKey)\n                            {\n                                for (int i = 0; i < hitPositions.Length; i++)\n                                    selections[i] = false;\n                                changed = true;\n                            }\n                            else\n                                changed = false;\n\n                            s_SelectionBackup = new List<bool>(selections);\n                            s_LastFrameSelections = new List<bool>(selections);\n\n                            s_MultiSelectDragSelection = DragSelectionState.DragSelecting;\n                            evt.Use();\n                            return changed ? HighLevelEvent.SelectionChanged : HighLevelEvent.None;\n                        }\n                    }\n\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        if (s_MultiSelectDragSelection == DragSelectionState.DragSelecting)\n                        {\n                            float min = Mathf.Min(s_StartSelectPos.x, evt.mousePosition.x);\n                            float max = Mathf.Max(s_StartSelectPos.x, evt.mousePosition.x);\n                            s_SelectionBackup.CopyTo(selections);\n                            for (int i = 0; i < hitPositions.Length; i++)\n                            {\n                                if (selections[i])\n                                    continue;\n\n                                float center = hitPositions[i].x + hitPositions[i].width * .5f;\n                                if (center >= min && center <= max)\n                                    selections[i] = true;\n                            }\n                            evt.Use();\n                            startSelect = min;\n                            endSelect = max;\n\n                            // Check if the selections _actually_ changed from last call\n                            bool changed = false;\n                            for (int i = 0; i < selections.Length; i++)\n                            {\n                                if (selections[i] != s_LastFrameSelections[i])\n                                {\n                                    changed = true;\n                                    s_LastFrameSelections[i] = selections[i];\n                                }\n                            }\n                            return changed ? HighLevelEvent.SelectionChanged : HighLevelEvent.None;\n                        }\n                        else\n                        {\n                            offset = evt.mousePosition - s_MouseDownPos;\n                            evt.Use();\n                            if (s_MultiSelectDragSelection == DragSelectionState.None)\n                            {\n                                s_MultiSelectDragSelection = DragSelectionState.Dragging;\n                                return HighLevelEvent.BeginDrag;\n                            }\n                            else\n                            {\n                                return HighLevelEvent.Drag;\n                            }\n                        }\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n\n                        if (s_StartSelectPos != evt.mousePosition)\n                            evt.Use();\n\n                        // TODO fix magic number for max dragging distance to be ignored\n                        if (s_MultiSelectDragSelection == DragSelectionState.None)\n                        {\n                            clickedIndex = GetIndexUnderMouse(hitPositions, readOnly);\n                            if (evt.clickCount == 1)\n                                return HighLevelEvent.Click;\n                        }\n                        else\n                        {\n                            s_MultiSelectDragSelection = DragSelectionState.None;\n                            s_SelectionBackup = null;\n                            s_LastFrameSelections = null;\n                            return HighLevelEvent.EndDrag;\n                        }\n                    }\n                    break;\n                case EventType.ValidateCommand:\n                case EventType.ExecuteCommand:\n\n                    if (selected)\n                    {\n                        bool execute = evt.type == EventType.ExecuteCommand;\n                        switch (evt.commandName)\n                        {\n                            case EventCommandNames.Delete:\n                                evt.Use();\n                                if (execute)\n                                    return HighLevelEvent.Delete;\n                                break;\n                            case EventCommandNames.Copy:\n                                evt.Use();\n                                if (execute)\n                                    return HighLevelEvent.Copy;\n                                break;\n                            case EventCommandNames.Paste:\n                                evt.Use();\n                                if (execute)\n                                    return HighLevelEvent.Paste;\n                                break;\n                        }\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (selected)\n                    {\n                        if (evt.keyCode == KeyCode.Backspace || evt.keyCode == KeyCode.Delete)\n                        {\n                            evt.Use();\n                            return HighLevelEvent.Delete;\n                        }\n                    }\n                    break;\n                case EventType.ContextClick:\n                    selectedIndex = GetIndexUnderMouse(hitPositions, readOnly);\n                    if (selectedIndex >= 0)\n                    {\n                        clickedIndex = selectedIndex;\n                        GUIUtility.keyboardControl = id;\n                        evt.Use();\n                        return HighLevelEvent.ContextClick;\n                    }\n                    break;\n            }\n\n            return HighLevelEvent.None;\n        }\n\n        // Helper for MultiSelection above.\n        static int GetIndexUnderMouse(Rect[] hitPositions, bool[] readOnly)\n        {\n            Vector2 mousePos = Event.current.mousePosition;\n\n            for (int i = hitPositions.Length - 1; i >= 0; i--)\n                if ((readOnly == null || !readOnly[i]) && hitPositions[i].Contains(mousePos))\n                    return i;\n\n            return -1;\n        }\n\n        // Small helper: Make a rect from MinMax values and make sure they're positive sizes\n        internal static Rect FromToRect(Vector2 start, Vector2 end)\n        {\n            Rect r = new Rect(start.x, start.y, end.x - start.x, end.y - start.y);\n            if (r.width < 0)\n            {\n                r.x += r.width;\n                r.width = -r.width;\n            }\n            if (r.height < 0)\n            {\n                r.y += r.height;\n                r.height = -r.height;\n            }\n            return r;\n        }\n    }\n\n    internal enum HighLevelEvent\n    {\n        None,\n        Click,\n        DoubleClick,\n        ContextClick,\n        BeginDrag,\n        Drag,\n        EndDrag,\n        Delete,\n        SelectionChanged,\n        Copy,\n        Paste\n    }\n} //namespace\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/Deprecated/UtilityClasses.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nusing TangentMode = UnityEditor.AnimationUtility.TangentMode;\n\nnamespace UnityEditor\n{\n    internal static class CurveUtility\n    {\n        private static Texture2D iconKey;\n        private static Texture2D iconCurve;\n\n        public static Texture2D GetIconCurve()\n        {\n            if (iconCurve == null)\n                iconCurve = EditorGUIUtility.LoadIcon(\"animationanimated\");\n            return iconCurve;\n        }\n\n        public static Texture2D GetIconKey()\n        {\n            if (iconKey == null)\n                iconKey = EditorGUIUtility.LoadIcon(\"animationkeyframe\");\n            return iconKey;\n        }\n\n        public static bool HaveKeysInRange(AnimationCurve curve, float beginTime, float endTime)\n        {\n            // Loop backwards\n            for (int i = curve.length - 1; i >= 0; i--)\n            {\n                if (curve[i].time >= beginTime && curve[i].time < endTime)\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public static void RemoveKeysInRange(AnimationCurve curve, float beginTime, float endTime)\n        {\n            // Loop backwards so key removals don't mess up order\n            for (int i = curve.length - 1; i >= 0; i--)\n            {\n                if (curve[i].time >= beginTime && curve[i].time < endTime)\n                {\n                    curve.RemoveKey(i);\n                }\n            }\n        }\n\n        public static float CalculateSmoothTangent(Keyframe key)\n        {\n            if (key.inTangent == Mathf.Infinity) key.inTangent = 0;\n            if (key.outTangent == Mathf.Infinity) key.outTangent = 0;\n            return (key.outTangent + key.inTangent) * 0.5f;\n        }\n\n        // Move me to CurveEditor.cs\n        public static void SetKeyModeFromContext(AnimationCurve curve, int keyIndex)\n        {\n            Keyframe key = curve[keyIndex];\n            bool broken = false;\n            bool smoothTangent = false;\n\n            if (keyIndex > 0)\n            {\n                if (AnimationUtility.GetKeyBroken(curve[keyIndex - 1]))\n                    broken = true;\n                TangentMode prevTangentMode = AnimationUtility.GetKeyRightTangentMode(curve[keyIndex - 1]);\n                if (prevTangentMode == TangentMode.ClampedAuto || prevTangentMode == TangentMode.Auto)\n                    smoothTangent = true;\n            }\n            if (keyIndex < curve.length - 1)\n            {\n                if (AnimationUtility.GetKeyBroken(curve[keyIndex + 1]))\n                    broken = true;\n                TangentMode nextTangentMode = AnimationUtility.GetKeyLeftTangentMode(curve[keyIndex + 1]);\n                if (nextTangentMode == TangentMode.ClampedAuto || nextTangentMode == TangentMode.Auto)\n                    smoothTangent = true;\n            }\n\n            AnimationUtility.SetKeyBroken(ref key, broken);\n\n            if (broken && !smoothTangent)\n            {\n                if (keyIndex > 0) AnimationUtility.SetKeyLeftTangentMode(ref key, AnimationUtility.GetKeyRightTangentMode(curve[keyIndex - 1]));\n                if (keyIndex < curve.length - 1) AnimationUtility.SetKeyRightTangentMode(ref key, AnimationUtility.GetKeyLeftTangentMode(curve[keyIndex + 1]));\n\n                // Keys at boundaries.  Make sure left and right tangent modes are the same.\n                if (keyIndex == 0) AnimationUtility.SetKeyLeftTangentMode(ref key, AnimationUtility.GetKeyRightTangentMode(key));\n                if (keyIndex == curve.length - 1) AnimationUtility.SetKeyRightTangentMode(ref key, AnimationUtility.GetKeyLeftTangentMode(key));\n            }\n            else\n            {\n                // If both neighbors or only neighbor are set to TangentMode.Auto or TangentMode.ClampedAuto, set new key to this mode as well.\n                // If there are no neighbors, set new key to TangentMode.ClampedAuto.\n                // Otherwise, fall back to TangentMode.Free.\n                TangentMode mode = TangentMode.Free;\n                if ((keyIndex == 0 || AnimationUtility.GetKeyRightTangentMode(curve[keyIndex - 1]) == TangentMode.ClampedAuto) &&\n                    (keyIndex == curve.length - 1 || AnimationUtility.GetKeyLeftTangentMode(curve[keyIndex + 1]) == TangentMode.ClampedAuto))\n                {\n                    mode = TangentMode.ClampedAuto;\n                }\n                else if ((keyIndex == 0 || AnimationUtility.GetKeyRightTangentMode(curve[keyIndex - 1]) == TangentMode.Auto) &&\n                         (keyIndex == curve.length - 1 || AnimationUtility.GetKeyLeftTangentMode(curve[keyIndex + 1]) == TangentMode.Auto))\n                {\n                    mode = TangentMode.Auto;\n                }\n\n                AnimationUtility.SetKeyLeftTangentMode(ref key, mode);\n                AnimationUtility.SetKeyRightTangentMode(ref key, mode);\n            }\n\n            curve.MoveKey(keyIndex, key);\n        }\n\n        static public string GetClipName(AnimationClip clip)\n        {\n            if (clip == null)\n                return \"[No Clip]\";\n\n            string name = clip.name;\n\n            if ((clip.hideFlags & HideFlags.NotEditable) != 0)\n                name += \" (Read-Only)\";\n\n            return name;\n        }\n\n        public static Color GetBalancedColor(Color c)\n        {\n            return new Color(\n                0.15f + 0.75f * c.r,\n                0.20f + 0.60f * c.g,\n                0.10f + 0.90f * c.b\n            );\n        }\n\n        public static Color GetPropertyColor(string name)\n        {\n            Color col = Color.white;\n\n            int type = 0;\n            if (name.StartsWith(\"m_LocalPosition\")) type = 1;\n            if (name.StartsWith(\"localEulerAngles\")) type = 2;\n            if (name.StartsWith(\"m_LocalScale\")) type = 3;\n\n            if (type == 1)\n            {\n                if (name.EndsWith(\".x\")) col = Handles.xAxisColor;\n                else if (name.EndsWith(\".y\")) col = Handles.yAxisColor;\n                else if (name.EndsWith(\".z\")) col = Handles.zAxisColor;\n            }\n            else if (type == 2)\n            {\n                if (name.EndsWith(\".x\")) col = AnimEditor.kEulerXColor;\n                else if (name.EndsWith(\".y\")) col = AnimEditor.kEulerYColor;\n                else if (name.EndsWith(\".z\")) col = AnimEditor.kEulerZColor;\n            }\n            else if (type == 3)\n            {\n                if (name.EndsWith(\".x\")) col = GetBalancedColor(new Color(0.7f, 0.4f, 0.4f));\n                else if (name.EndsWith(\".y\")) col = GetBalancedColor(new Color(0.4f, 0.7f, 0.4f));\n                else if (name.EndsWith(\".z\")) col = GetBalancedColor(new Color(0.4f, 0.4f, 0.7f));\n            }\n            else if (name.EndsWith(\".x\")) col = Handles.xAxisColor;\n            else if (name.EndsWith(\".y\")) col = Handles.yAxisColor;\n            else if (name.EndsWith(\".z\")) col = Handles.zAxisColor;\n            else if (name.EndsWith(\".w\")) col = new Color(1.0f, 0.5f, 0.0f);\n            else if (name.EndsWith(\".r\")) col = GetBalancedColor(Color.red);\n            else if (name.EndsWith(\".g\")) col = GetBalancedColor(Color.green);\n            else if (name.EndsWith(\".b\")) col = GetBalancedColor(Color.blue);\n            else if (name.EndsWith(\".a\")) col = GetBalancedColor(Color.yellow);\n            else if (name.EndsWith(\".width\")) col = GetBalancedColor(Color.blue);\n            else if (name.EndsWith(\".height\")) col = GetBalancedColor(Color.yellow);\n            else\n            {\n                float rand = Mathf.PI * 2 * (name.GetHashCode() % 1000);\n                rand = rand - Mathf.Floor(rand);\n                col = GetBalancedColor(Color.HSVToRGB(rand, 1, 1));\n            }\n            col.a = 1; // Some preference colors do not have full alpha\n            return col;\n        }\n    }\n\n    struct QuaternionCurveTangentCalculation\n    {\n        public static Vector3[] GetEquivalentEulerAngles(Quaternion quat)\n        {\n            Vector3 euler = quat.eulerAngles;\n            Vector3[] eulers = new Vector3[2];\n            eulers[0] = euler;\n            eulers[1] = new Vector3(180 - euler.x, euler.y + 180, euler.z + 180);\n            return eulers;\n        }\n\n        public static Vector3 GetEulerFromQuaternion(Quaternion q, Vector3 refEuler)\n        {\n            Vector3[] eulers = GetEquivalentEulerAngles(q);\n            for (int i = 0; i < eulers.Length; i++)\n            {\n                eulers[i] = new Vector3(\n                    Mathf.Repeat(eulers[i].x - refEuler.x + 180, 360) + refEuler.x - 180,\n                    Mathf.Repeat(eulers[i].y - refEuler.y + 180, 360) + refEuler.y - 180,\n                    Mathf.Repeat(eulers[i].z - refEuler.z + 180, 360) + refEuler.z - 180\n                );\n\n                float xRot = Mathf.Repeat(eulers[i].x, 360);\n                if (Mathf.Abs(xRot - 90) < 1.0f)\n                {\n                    float newCombiAngle = eulers[i].z - eulers[i].y;\n                    float refCombiAngle = refEuler.z - refEuler.y;\n                    float angleDiff = newCombiAngle - refCombiAngle;\n                    eulers[i].z = refEuler.z + angleDiff * 0.5f;\n                    eulers[i].y = refEuler.y - angleDiff * 0.5f;\n                }\n                if (Mathf.Abs(xRot - 270) < 1.0f)\n                {\n                    float newCombiAngle = eulers[i].z + eulers[i].y;\n                    float refCombiAngle = refEuler.z + refEuler.y;\n                    float angleDiff = newCombiAngle - refCombiAngle;\n                    eulers[i].z = refEuler.z + angleDiff * 0.5f;\n                    eulers[i].y = refEuler.y + angleDiff * 0.5f;\n                }\n            }\n\n            // Find out which euler is closest to reference\n            Vector3 euler = eulers[0];\n            float dist = (eulers[0] - refEuler).sqrMagnitude;\n            for (int i = 1; i < eulers.Length; i++)\n            {\n                float newDist = (eulers[i] - refEuler).sqrMagnitude;\n                if (newDist < dist)\n                {\n                    dist = newDist;\n                    euler = eulers[i];\n                }\n            }\n\n            return euler;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/DopeLine.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System;\n\nnamespace UnityEditorInternal\n{\n    internal class DopeLine\n    {\n        private int m_HierarchyNodeID;\n        private AnimationWindowCurve[] m_Curves;\n        private List<AnimationWindowKeyframe> m_Keys;\n\n        public static GUIStyle dopekeyStyle = \"Dopesheetkeyframe\";\n\n        public Rect position;\n        public System.Type objectType;\n        public bool tallMode;\n        public bool hasChildren;\n        public bool isMasterDopeline;\n\n        public System.Type valueType\n        {\n            get\n            {\n                if (m_Curves.Length > 0)\n                {\n                    System.Type type = m_Curves[0].valueType;\n                    for (int i = 1; i < m_Curves.Length; i++)\n                    {\n                        if (m_Curves[i].valueType != type)\n                            return null;\n                    }\n                    return type;\n                }\n\n                return null;\n            }\n        }\n\n        public bool isPptrDopeline\n        {\n            get\n            {\n                if (m_Curves.Length > 0)\n                {\n                    for (int i = 0; i < m_Curves.Length; i++)\n                    {\n                        if (!m_Curves[i].isPPtrCurve)\n                            return false;\n                    }\n                    return true;\n                }\n                return false;\n            }\n        }\n\n        public bool isEditable\n        {\n            get\n            {\n                if (m_Curves.Length > 0)\n                {\n                    bool isReadOnly = Array.Exists(m_Curves, curve => !curve.animationIsEditable);\n                    return !isReadOnly;\n                }\n\n                return false;\n            }\n        }\n\n        public int hierarchyNodeID\n        {\n            get\n            {\n                return m_HierarchyNodeID;\n            }\n        }\n\n        public AnimationWindowCurve[] curves\n        {\n            get\n            {\n                return m_Curves;\n            }\n        }\n\n        public List<AnimationWindowKeyframe> keys\n        {\n            get\n            {\n                if (m_Keys == null)\n                {\n                    m_Keys = new List<AnimationWindowKeyframe>();\n                    foreach (AnimationWindowCurve curve in m_Curves)\n                        foreach (AnimationWindowKeyframe key in curve.keyframes)\n                            m_Keys.Add(key);\n\n                    m_Keys.Sort((a, b) => a.time.CompareTo(b.time));\n                }\n\n                return m_Keys;\n            }\n        }\n\n        public void InvalidateKeyframes()\n        {\n            m_Keys = null;\n        }\n\n        public DopeLine(int hierarchyNodeID, AnimationWindowCurve[] curves)\n        {\n            m_HierarchyNodeID = hierarchyNodeID;\n            m_Curves = curves;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/DopeSheetEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing Event = UnityEngine.Event;\nusing Object = UnityEngine.Object;\nusing System.Collections;\nusing System.Linq;\n\nnamespace UnityEditorInternal\n{\n    [System.Serializable]\n    class DopeSheetEditor : TimeArea, CurveUpdater\n    {\n        [SerializeReference] public AnimationWindowState state;\n\n        // How much rendered keyframe left edge is visually offset when compared to the time it represents.\n        // A diamond shape left edge isn't representing the time, the middle part is.\n        private const float k_KeyframeOffset = -6.5f;\n        // Pptr keyframe preview also needs 1px offset so it sits more tightly in the grid\n        private const float k_PptrKeyframeOffset = -1;\n\n        private static readonly Vector2 k_ControlPointSize = new Vector2(16, 16);\n\n        const int kLabelMarginHorizontal = 8;\n        const int kLabelMarginVertical = 2;\n\n        static private Color s_SelectedKeyColor = new Color32(87, 133, 217, 255);\n\n        struct DrawElement\n        {\n            public Rect position;\n            public Color color;\n            public Texture2D texture;\n\n            public DrawElement(Rect position, Color color, Texture2D texture)\n            {\n                this.position = position;\n                this.color = color;\n                this.texture = texture;\n            }\n        }\n\n        //  Control point collection renderer\n        class DopeSheetControlPointRenderer\n        {\n            // Unoptimized control point list.  Rendered through GUI.Label calls.\n            private List<DrawElement> m_UnselectedKeysDrawBuffer = new List<DrawElement>();\n            private List<DrawElement> m_SelectedKeysDrawBuffer = new List<DrawElement>();\n            private List<DrawElement> m_DragDropKeysDrawBuffer = new List<DrawElement>();\n\n            // Control point mesh renderers.\n            private ControlPointRenderer m_UnselectedKeysRenderer;\n            private ControlPointRenderer m_SelectedKeysRenderer;\n            private ControlPointRenderer m_DragDropKeysRenderer;\n\n            private Texture2D m_DefaultDopeKeyIcon;\n\n            public void FlushCache()\n            {\n                m_UnselectedKeysRenderer.FlushCache();\n                m_SelectedKeysRenderer.FlushCache();\n                m_DragDropKeysRenderer.FlushCache();\n            }\n\n            private void DrawElements(List<DrawElement> elements)\n            {\n                if (elements.Count == 0)\n                    return;\n\n                Color oldColor = GUI.color;\n\n                Color color = Color.white;\n                GUI.color = color;\n                Texture icon = m_DefaultDopeKeyIcon;\n\n                for (int i = 0; i < elements.Count; ++i)\n                {\n                    DrawElement element = elements[i];\n\n                    // Change color\n                    if (element.color != color)\n                    {\n                        color = GUI.enabled ? element.color : element.color * 0.8f;\n                        GUI.color = color;\n                    }\n\n                    // Element with specific texture (sprite).\n                    if (element.texture != null)\n                    {\n                        GUI.Label(element.position, element.texture, GUIStyle.none);\n                    }\n                    // Ordinary control point.\n                    else\n                    {\n                        Rect rect = new Rect((element.position.center.x - icon.width / 2),\n                            (element.position.center.y - icon.height / 2),\n                            icon.width,\n                            icon.height);\n                        GUI.Label(rect, icon, GUIStyle.none);\n                    }\n                }\n\n                GUI.color = oldColor;\n            }\n\n            public DopeSheetControlPointRenderer()\n            {\n                m_DefaultDopeKeyIcon = EditorGUIUtility.LoadIcon(\"blendKey\");\n\n                m_UnselectedKeysRenderer = new ControlPointRenderer(m_DefaultDopeKeyIcon);\n                m_SelectedKeysRenderer = new ControlPointRenderer(m_DefaultDopeKeyIcon);\n                m_DragDropKeysRenderer = new ControlPointRenderer(m_DefaultDopeKeyIcon);\n            }\n\n            public void Clear()\n            {\n                m_UnselectedKeysDrawBuffer.Clear();\n                m_SelectedKeysDrawBuffer.Clear();\n                m_DragDropKeysDrawBuffer.Clear();\n\n                m_UnselectedKeysRenderer.Clear();\n                m_SelectedKeysRenderer.Clear();\n                m_DragDropKeysRenderer.Clear();\n            }\n\n            public void Render()\n            {\n                DrawElements(m_UnselectedKeysDrawBuffer);\n                m_UnselectedKeysRenderer.Render();\n\n                DrawElements(m_SelectedKeysDrawBuffer);\n                m_SelectedKeysRenderer.Render();\n\n                DrawElements(m_DragDropKeysDrawBuffer);\n                m_DragDropKeysRenderer.Render();\n            }\n\n            public void AddUnselectedKey(DrawElement element)\n            {\n                // Control point has a specific texture (sprite image).\n                // This will not be batched rendered and must be handled separately.\n                if (element.texture != null)\n                {\n                    m_UnselectedKeysDrawBuffer.Add(element);\n                }\n                else\n                {\n                    Rect rect = element.position;\n                    rect.size = k_ControlPointSize;\n                    m_UnselectedKeysRenderer.AddPoint(rect, element.color);\n                }\n            }\n\n            public void AddSelectedKey(DrawElement element)\n            {\n                // Control point has a specific texture (sprite image).\n                // This will not be batched rendered and must be handled separately.\n                if (element.texture != null)\n                {\n                    m_SelectedKeysDrawBuffer.Add(element);\n                }\n                else\n                {\n                    Rect rect = element.position;\n                    rect.size = k_ControlPointSize;\n                    m_SelectedKeysRenderer.AddPoint(rect, element.color);\n                }\n            }\n\n            public void AddDragDropKey(DrawElement element)\n            {\n                // Control point has a specific texture (sprite image).\n                // This will not be batched rendered and must be handled separately.\n                if (element.texture != null)\n                {\n                    m_DragDropKeysDrawBuffer.Add(element);\n                }\n                else\n                {\n                    Rect rect = element.position;\n                    rect.size = k_ControlPointSize;\n                    m_DragDropKeysRenderer.AddPoint(rect, element.color);\n                }\n            }\n        }\n\n        public float contentHeight\n        {\n            get\n            {\n                float height = 0f;\n\n                foreach (DopeLine dopeline in state.dopelines)\n                    height += dopeline.tallMode ? AnimationWindowHierarchyGUI.k_DopeSheetRowHeightTall : AnimationWindowHierarchyGUI.k_DopeSheetRowHeight;\n\n                height += AnimationWindowHierarchyGUI.k_AddCurveButtonNodeHeight;\n                return height;\n            }\n        }\n\n        [SerializeField] public EditorWindow m_Owner;\n\n        DopeSheetSelectionRect m_SelectionRect;\n\n        float m_DragStartTime;\n        bool m_MousedownOnKeyframe;\n        bool m_IsDragging;\n        bool m_IsDraggingPlayheadStarted;\n        bool m_IsDraggingPlayhead;\n\n        bool m_Initialized;\n\n        bool m_SpritePreviewLoading;\n        int m_SpritePreviewCacheSize;\n\n        public Bounds m_Bounds = new Bounds(Vector3.zero, Vector3.zero);\n        public override Bounds drawingBounds { get { return m_Bounds; } }\n\n        public bool isDragging { get { return m_IsDragging; } }\n\n        DopeSheetControlPointRenderer m_PointRenderer;\n\n        DopeSheetEditorRectangleTool m_RectangleTool;\n\n        internal int assetPreviewManagerID\n        {\n            get { return m_Owner != null ? m_Owner.GetInstanceID() : 0; }\n        }\n\n        public bool spritePreviewLoading { get { return m_SpritePreviewLoading; } }\n\n        public DopeSheetEditor(EditorWindow owner) : base(false)\n        {\n            m_Owner = owner;\n        }\n\n        public void OnDisable()\n        {\n            if (m_PointRenderer != null)\n                m_PointRenderer.FlushCache();\n        }\n\n        internal void OnDestroy()\n        {\n            AssetPreview.DeletePreviewTextureManagerByID(assetPreviewManagerID);\n        }\n\n        public void OnGUI(Rect position, Vector2 scrollPosition)\n        {\n            Init();\n\n            // drag'n'drops outside any dopelines\n            HandleDragAndDropToEmptyArea();\n\n            GUIClip.Push(position, scrollPosition, Vector2.zero, false);\n\n            HandleRectangleToolEvents();\n\n            Rect localRect = new Rect(0, 0, position.width, position.height);\n            Rect dopesheetRect = DopelinesGUI(localRect, scrollPosition);\n\n            HandleKeyboard();\n            HandleDragging();\n            HandleSelectionRect(dopesheetRect);\n            HandleDelete();\n\n            RectangleToolGUI();\n\n            GUIClip.Pop();\n        }\n\n        public void Init()\n        {\n            if (!m_Initialized)\n            {\n                // Set TimeArea constrains\n                hSlider = true;\n                vSlider = false;\n                hRangeLocked = false;\n                vRangeLocked = true;\n                hRangeMin = 0;\n                margin = 40;\n                scaleWithWindow = true;\n                ignoreScrollWheelUntilClicked = false;\n            }\n            m_Initialized = true;\n\n            if (m_PointRenderer == null)\n                m_PointRenderer = new DopeSheetControlPointRenderer();\n\n            if (m_RectangleTool == null)\n            {\n                m_RectangleTool = new DopeSheetEditorRectangleTool();\n                m_RectangleTool.Initialize(this);\n            }\n        }\n\n        public void RecalculateBounds()\n        {\n            if (!state.disabled)\n            {\n                Vector2 timeRange = state.timeRange;\n                m_Bounds.SetMinMax(new Vector3(timeRange.x, 0, 0), new Vector3(timeRange.y, 0, 0));\n            }\n        }\n\n        private Rect DopelinesGUI(Rect position, Vector2 scrollPosition)\n        {\n            Color oldColor = GUI.color;\n            Rect linePosition = position;\n\n            m_PointRenderer.Clear();\n\n            if (Event.current.type == EventType.Repaint)\n                m_SpritePreviewLoading = false;\n\n            // Workaround for cases when mouseup happens outside the window. Apparently the mouseup event is lost (not true on OSX, though).\n            if (Event.current.type == EventType.MouseDown)\n                m_IsDragging = false;\n\n            // Find out how large preview pool is needed for sprite previews\n            UpdateSpritePreviewCacheSize();\n\n            List<DopeLine> dopelines = state.dopelines;\n            for (int i = 0; i < dopelines.Count; ++i)\n            {\n                DopeLine dopeLine = dopelines[i];\n\n                dopeLine.position = linePosition;\n                dopeLine.position.height = (dopeLine.tallMode ? AnimationWindowHierarchyGUI.k_DopeSheetRowHeightTall : AnimationWindowHierarchyGUI.k_DopeSheetRowHeight);\n\n                // Cull out dopelines that are not visible\n                if (dopeLine.position.yMin + scrollPosition.y >= position.yMin && dopeLine.position.yMin + scrollPosition.y <= position.yMax ||\n                    dopeLine.position.yMax + scrollPosition.y >= position.yMin && dopeLine.position.yMax + scrollPosition.y <= position.yMax)\n                {\n                    Event evt = Event.current;\n\n                    switch (evt.type)\n                    {\n                        case EventType.DragUpdated:\n                        case EventType.DragPerform:\n                        {\n                            HandleDragAndDrop(dopeLine);\n                            break;\n                        }\n                        case EventType.ContextClick:\n                        {\n                            if (!m_IsDraggingPlayhead)\n                            {\n                                HandleContextMenu(dopeLine);\n                            }\n\n                            break;\n                        }\n                        case EventType.MouseDown:\n                        {\n                            if (evt.button == 0)\n                            {\n                                HandleMouseDown(dopeLine);\n                            }\n                            break;\n                        }\n                        case EventType.Repaint:\n                        {\n                            DopeLineRepaint(dopeLine);\n                            break;\n                        }\n                    }\n                }\n\n                linePosition.y += dopeLine.position.height;\n            }\n\n            if (Event.current.type == EventType.MouseUp)\n            {\n                m_IsDraggingPlayheadStarted = false;\n                m_IsDraggingPlayhead = false;\n            }\n\n            Rect dopelinesRect = new Rect(position.xMin, position.yMin, position.width, linePosition.yMax - position.yMin);\n\n            if (Event.current.type == EventType.Repaint)\n                m_PointRenderer.Render();\n\n            GUI.color = oldColor;\n\n            return dopelinesRect;\n        }\n\n        private void RectangleToolGUI()\n        {\n            m_RectangleTool.OnGUI();\n        }\n\n        public void DrawMasterDopelineBackground(Rect position)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            AnimationWindowStyles.eventBackground.Draw(position, false, false, false, false);\n        }\n\n        void UpdateSpritePreviewCacheSize()\n        {\n            int newPreviewCacheSize = 1;\n\n            // Add all expanded sprite dopelines\n            foreach (DopeLine dopeLine in state.dopelines)\n            {\n                if (dopeLine.tallMode && dopeLine.isPptrDopeline)\n                {\n                    newPreviewCacheSize += dopeLine.keys.Count;\n                }\n            }\n\n            // Add all drag'n'drop objects\n            newPreviewCacheSize += DragAndDrop.objectReferences.Length;\n\n            if (newPreviewCacheSize > m_SpritePreviewCacheSize)\n            {\n                AssetPreview.SetPreviewTextureCacheSize(newPreviewCacheSize, assetPreviewManagerID);\n                m_SpritePreviewCacheSize = newPreviewCacheSize;\n            }\n        }\n\n        private void DopeLineRepaint(DopeLine dopeline)\n        {\n            Color oldColor = GUI.color;\n\n            AnimationWindowHierarchyNode node = (AnimationWindowHierarchyNode)state.hierarchyData.FindItem(dopeline.hierarchyNodeID);\n            bool isChild = node != null && node.depth > 0;\n            Color color = isChild ? Color.gray.AlphaMultiplied(0.05f) : Color.gray.AlphaMultiplied(0.16f);\n\n            // Draw background\n            if (dopeline.isMasterDopeline)\n                DrawMasterDopelineBackground(dopeline.position);\n            else\n                DrawBox(dopeline.position, color);\n\n            // Draw keys\n            int? previousTimeHash = null;\n            int length = dopeline.keys.Count;\n\n            for (int i = 0; i < length; i++)\n            {\n                AnimationWindowKeyframe keyframe = dopeline.keys[i];\n                // Hash optimizations\n                if (previousTimeHash == keyframe.m_TimeHash)\n                    continue;\n\n                previousTimeHash = keyframe.m_TimeHash;\n\n                // Default values\n                Rect rect = GetKeyframeRect(dopeline, keyframe);\n                color = dopeline.isMasterDopeline ? Color.gray.RGBMultiplied(0.85f) : Color.gray.RGBMultiplied(1.2f);\n                Texture2D texture = null;\n\n                if (keyframe.isPPtrCurve && dopeline.tallMode)\n                    texture = keyframe.value == null ? null : AssetPreview.GetAssetPreview(((Object)keyframe.value).GetInstanceID(), assetPreviewManagerID);\n\n                if (texture != null)\n                {\n                    rect = GetPreviewRectFromKeyFrameRect(rect);\n                    color = Color.white.AlphaMultiplied(0.5f);\n                }\n                else if (keyframe.value != null && keyframe.isPPtrCurve && dopeline.tallMode)\n                {\n                    m_SpritePreviewLoading = true;\n                }\n\n                // TODO: Find out why zero time, and only zero time, is offset from grid\n                if (Mathf.Approximately(keyframe.time, 0f))\n                    rect.xMin -= 0.01f;\n\n                if (AnyKeyIsSelectedAtTime(dopeline, i))\n                {\n                    color = s_SelectedKeyColor;\n                    if (dopeline.tallMode && dopeline.isPptrDopeline)\n                        color = Color.white;\n\n                    if (dopeline.isMasterDopeline)\n                        color = color.RGBMultiplied(0.85f);\n\n                    m_PointRenderer.AddSelectedKey(new DrawElement(rect, color, texture));\n                }\n                else\n                {\n                    m_PointRenderer.AddUnselectedKey(new DrawElement(rect, color, texture));\n                }\n            }\n\n            if (DoDragAndDrop(dopeline, dopeline.position, false))\n            {\n                float time = Mathf.Max(state.PixelToTime(Event.current.mousePosition.x, AnimationWindowState.SnapMode.SnapToFrame), 0f);\n\n                Color keyColor = Color.gray.RGBMultiplied(1.2f);\n                Texture2D texture = null;\n\n                foreach (Object obj in GetSortedDragAndDropObjectReferences())\n                {\n                    Rect rect = GetDragAndDropRect(dopeline, time);\n\n                    if (dopeline.isPptrDopeline && dopeline.tallMode)\n                        texture = AssetPreview.GetAssetPreview(obj.GetInstanceID(), assetPreviewManagerID);\n\n                    if (texture != null)\n                    {\n                        rect = GetPreviewRectFromKeyFrameRect(rect);\n                        keyColor = Color.white.AlphaMultiplied(0.5f);\n                    }\n\n                    m_PointRenderer.AddDragDropKey(new DrawElement(rect, keyColor, texture));\n\n                    time += 1f / state.frameRate;\n                }\n            }\n\n            GUI.color = oldColor;\n        }\n\n        private Rect GetPreviewRectFromKeyFrameRect(Rect keyframeRect)\n        {\n            keyframeRect.width -= 2;\n            keyframeRect.height -= 2;\n            keyframeRect.xMin += 2;\n            keyframeRect.yMin += 2;\n\n            return keyframeRect;\n        }\n\n        private Rect GetDragAndDropRect(DopeLine dopeline, float time)\n        {\n            Rect rect = GetKeyframeRect(dopeline, null);\n            float offsetX = GetKeyframeOffset(dopeline, null);\n            rect.center = new Vector2(state.TimeToPixel(time) + rect.width * .5f + offsetX, rect.center.y);\n            return rect;\n        }\n\n        // TODO: This is just temporary until real styles\n        private static void DrawBox(Rect position, Color color)\n        {\n            Color oldColor = GUI.color;\n            GUI.color = color;\n            DopeLine.dopekeyStyle.Draw(position, GUIContent.none, 0, false);\n            GUI.color = oldColor;\n        }\n\n        private GenericMenu GenerateMenu(DopeLine dopeline)\n        {\n            GenericMenu menu = new GenericMenu();\n\n            // Collect hovering keys.\n            List<AnimationWindowKeyframe> hoveringKeys = new List<AnimationWindowKeyframe>();\n            foreach (var key in dopeline.keys)\n            {\n                Rect rect = GetKeyframeRect(dopeline, key);\n\n                if (rect.Contains(Event.current.mousePosition))\n                    hoveringKeys.Add(key);\n            }\n\n            AnimationKeyTime mouseKeyTime = AnimationKeyTime.Time(state.PixelToTime(Event.current.mousePosition.x, AnimationWindowState.SnapMode.SnapToFrame), state.frameRate);\n\n            string str = L10n.Tr(\"Add Key\");\n            if (dopeline.isEditable && hoveringKeys.Count == 0)\n                menu.AddItem(new GUIContent(str), false, AddKeyToDopeline, new AddKeyToDopelineContext {dopeline = dopeline, time = mouseKeyTime});\n            else\n                menu.AddDisabledItem(new GUIContent(str));\n\n            str = state.selectedKeys.Count > 1 ? L10n.Tr(\"Delete Keys\") : L10n.Tr(\"Delete Key\");\n            if (dopeline.isEditable && (state.selectedKeys.Count > 0 || hoveringKeys.Count > 0))\n                menu.AddItem(new GUIContent(str), false, DeleteKeys, state.selectedKeys.Count > 0 ? state.selectedKeys : hoveringKeys);\n            else\n                menu.AddDisabledItem(new GUIContent(str));\n\n            // Float curve tangents\n            if (dopeline.isEditable && AnimationWindowUtility.ContainsFloatKeyframes(state.selectedKeys))\n            {\n                menu.AddSeparator(string.Empty);\n\n                List<KeyIdentifier> keyList = new List<KeyIdentifier>();\n                Hashtable editorCurves = new Hashtable();\n                foreach (AnimationWindowKeyframe key in state.selectedKeys)\n                {\n                    if (key.isDiscreteCurve)\n                        continue;\n\n                    int index = key.curve.GetKeyframeIndex(AnimationKeyTime.Time(key.time, state.frameRate));\n                    if (index == -1)\n                        continue;\n\n                    int id = key.curve.GetHashCode();\n\n                    AnimationCurve curve = (AnimationCurve)editorCurves[id];\n                    if (curve == null)\n                    {\n                        curve = AnimationUtility.GetEditorCurve(key.curve.clip, key.curve.binding);\n                        if (curve == null)\n                            curve = new AnimationCurve();\n\n                        editorCurves.Add(id, curve);\n                    }\n\n                    keyList.Add(new KeyIdentifier(curve, id, index, key.curve.binding));\n                }\n\n                CurveMenuManager menuManager = new CurveMenuManager(this);\n                menuManager.AddTangentMenuItems(menu, keyList);\n            }\n\n            return menu;\n        }\n\n        private void HandleDragging()\n        {\n            int id = EditorGUIUtility.GetControlID(\"dopesheetdrag\".GetHashCode(), FocusType.Passive, new Rect());\n            EventType eventType = Event.current.GetTypeForControl(id);\n\n            if ((eventType == EventType.MouseDrag || eventType == EventType.MouseUp) && m_MousedownOnKeyframe)\n            {\n                if (eventType == EventType.MouseDrag && !EditorGUI.actionKey && !Event.current.shift)\n                {\n                    if (!m_IsDragging && state.selectedKeys.Count > 0)\n                    {\n                        m_IsDragging = true;\n                        m_IsDraggingPlayheadStarted = true;\n                        GUIUtility.hotControl = id;\n                        m_DragStartTime = state.PixelToTime(Event.current.mousePosition.x);\n                        m_RectangleTool.OnStartMove(new Vector2(m_DragStartTime, 0f), state.rippleTime);\n                        Event.current.Use();\n                    }\n                }\n\n                // What is the distance from first selected key to zero time. We need this in order to make sure no key goes to negative time while dragging.\n                float firstSelectedKeyTime = float.MaxValue;\n                foreach (AnimationWindowKeyframe selectedKey in state.selectedKeys)\n                    firstSelectedKeyTime = Mathf.Min(selectedKey.time, firstSelectedKeyTime);\n\n                float currentTime = state.SnapToFrame(state.PixelToTime(Event.current.mousePosition.x), AnimationWindowState.SnapMode.SnapToFrame);\n\n                if (m_IsDragging)\n                {\n                    if (!Mathf.Approximately(currentTime, m_DragStartTime))\n                    {\n                        m_RectangleTool.OnMove(new Vector2(currentTime, 0f));\n                        Event.current.Use();\n                    }\n                }\n\n                if (eventType == EventType.MouseUp)\n                {\n                    if (m_IsDragging && GUIUtility.hotControl == id)\n                    {\n                        m_RectangleTool.OnEndMove();\n                        Event.current.Use();\n                        m_IsDragging = false;\n                    }\n                    m_MousedownOnKeyframe = false;\n                    GUIUtility.hotControl = 0;\n                }\n            }\n\n            if (m_IsDraggingPlayheadStarted && eventType == EventType.MouseDrag && Event.current.button == 1)\n            {\n                m_IsDraggingPlayhead = true;\n\n                //int frame = state.m_Frame;\n                //if (!m_IsDragging)\n                //  frame = state.TimeToFrameFloor(state.SnapToFrame (state.PixelToTime (Event.current.mousePosition.x)));\n\n                //state.animationWindow.PreviewFrame (frame);\n                Event.current.Use();\n            }\n\n            if (m_IsDragging)\n            {\n                Vector2 mousePosition = Event.current.mousePosition;\n                Rect mouseRect = new Rect(mousePosition.x - 10, mousePosition.y - 10, 20, 20);\n\n                EditorGUIUtility.AddCursorRect(mouseRect, MouseCursor.MoveArrow);\n            }\n        }\n\n        private void HandleKeyboard()\n        {\n            if (Event.current.type == EventType.ValidateCommand || Event.current.type == EventType.ExecuteCommand)\n            {\n                switch (Event.current.commandName)\n                {\n                    case EventCommandNames.SelectAll:\n                        if (Event.current.type == EventType.ExecuteCommand)\n                            HandleSelectAll();\n                        Event.current.Use();\n                        break;\n                    case EventCommandNames.FrameSelected:\n                        if (Event.current.type == EventType.ExecuteCommand)\n                            FrameSelected();\n                        Event.current.Use();\n                        break;\n                }\n            }\n        }\n\n        private void HandleSelectAll()\n        {\n            foreach (DopeLine dopeline in state.dopelines)\n            {\n                foreach (AnimationWindowKeyframe keyframe in dopeline.keys)\n                {\n                    state.SelectKey(keyframe);\n                }\n                state.SelectHierarchyItem(dopeline, true, false);\n            }\n        }\n\n        private void HandleDelete()\n        {\n            if (state.selectedKeys.Count == 0)\n                return;\n\n            switch (Event.current.type)\n            {\n                case EventType.ValidateCommand:\n                case EventType.ExecuteCommand:\n                    if ((Event.current.commandName == EventCommandNames.SoftDelete || Event.current.commandName == EventCommandNames.Delete))\n                    {\n                        if (Event.current.type == EventType.ExecuteCommand)\n                            state.DeleteSelectedKeys();\n                        Event.current.Use();\n                    }\n                    break;\n\n                case EventType.KeyDown:\n                    if (Event.current.keyCode == KeyCode.Backspace || Event.current.keyCode == KeyCode.Delete)\n                    {\n                        state.DeleteSelectedKeys();\n                        Event.current.Use();\n                    }\n                    break;\n            }\n        }\n\n        private void HandleSelectionRect(Rect rect)\n        {\n            if (m_SelectionRect == null)\n                m_SelectionRect = new DopeSheetSelectionRect(this);\n\n            if (!m_MousedownOnKeyframe)\n                m_SelectionRect.OnGUI(rect);\n        }\n\n        // Handles drag and drop into empty area outside dopelines\n        private void HandleDragAndDropToEmptyArea()\n        {\n            Event evt = Event.current;\n\n            if (evt.type != EventType.DragPerform && evt.type != EventType.DragUpdated)\n                return;\n\n            if (!ValidateDragAndDropObjects())\n                return;\n\n            // TODO: handle multidropping of other types than sprites/textures\n            if (DragAndDrop.objectReferences[0].GetType() == typeof(Sprite) || DragAndDrop.objectReferences[0].GetType() == typeof(Texture2D))\n            {\n                if (state.selection.clipIsEditable && state.selection.canAddCurves)\n                {\n                    if (!DopelineForValueTypeExists(typeof(Sprite)))\n                    {\n                        if (evt.type == EventType.DragPerform)\n                        {\n                            EditorCurveBinding? spriteBinding = CreateNewPptrDopeline(state.selection, typeof(Sprite));\n                            if (spriteBinding != null)\n                                DoSpriteDropAfterGeneratingNewDopeline(state.activeAnimationClip, spriteBinding);\n                        }\n\n                        DragAndDrop.visualMode = DragAndDropVisualMode.Copy;\n                        evt.Use();\n                        return;\n                    }\n                }\n            }\n            DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;\n        }\n\n        private void DoSpriteDropAfterGeneratingNewDopeline(AnimationClip animationClip, EditorCurveBinding? spriteBinding)\n        {\n            // Create the new curve for our sprites\n            AnimationWindowCurve newCurve = new AnimationWindowCurve(animationClip, (EditorCurveBinding)spriteBinding, typeof(Sprite));\n\n            // Perform the drop onto the curve\n            PerformDragAndDrop(newCurve, 0f);\n\n            // Assign the Sprite in the first keyframe to the SpriteRenderer's Sprite property\n            AssignSpriteToSpriteRenderer(newCurve);\n        }\n\n        private void AssignSpriteToSpriteRenderer(AnimationWindowCurve curve)\n        {\n            var rootGameObject = state.selection.rootGameObject;\n            if (rootGameObject == null)\n                return;\n\n            var hasValidCurve = curve.keyframes.Count > 0 && curve.binding.type == typeof(SpriteRenderer);\n            if (!hasValidCurve)\n                return;\n\n            var spriteRenderer = AnimationUtility.GetAnimatedObject(rootGameObject, curve.binding) as SpriteRenderer;\n            var hasValidSpriteRenderer = spriteRenderer != null && spriteRenderer.sprite == null;\n            if (!hasValidSpriteRenderer)\n                return;\n\n            var keyframe = curve.keyframes[0];\n            var sprite = keyframe.value as Sprite;\n            if (sprite != null)\n            {\n                Undo.RecordObject(spriteRenderer, \"Add Sprite\");\n                spriteRenderer.sprite = sprite;\n            }\n        }\n\n        private void HandleRectangleToolEvents()\n        {\n            m_RectangleTool.HandleEvents();\n        }\n\n        private bool DopelineForValueTypeExists(Type valueType)\n        {\n            return state.filteredCurves.Exists(curve => curve.valueType == valueType);\n        }\n\n        public EditorCurveBinding[] GetAnimatableProperties(AnimationWindowSelectionItem selection, Type valueType)\n        {\n            EditorCurveBinding[] allBindings = null;\n            if (selection.gameObject != null)\n            {\n                allBindings = state.controlInterface.GetAnimatableBindings(selection.gameObject);\n            }\n            else if (selection.scriptableObject != null)\n            {\n                allBindings = state.controlInterface.GetAnimatableBindings();\n            }\n\n            return allBindings\n                .Where(binding => state.controlInterface.GetValueType(binding) == valueType)\n                .ToArray();\n        }\n\n        private EditorCurveBinding? CreateNewPptrDopeline(AnimationWindowSelectionItem selectedItem, Type valueType)\n        {\n            EditorCurveBinding[] potentialBindings = null;\n            if (selectedItem.rootGameObject != null)\n            {\n                potentialBindings = GetAnimatableProperties(selectedItem, valueType);\n                if (potentialBindings.Length == 0 && valueType == typeof(Sprite))  // No animatable properties for Sprite available. Default as SpriteRenderer.\n                {\n                    return CreateNewSpriteRendererDopeline(selectedItem.rootGameObject, selectedItem.rootGameObject);\n                }\n            }\n            else if (selectedItem.scriptableObject != null)\n            {\n                potentialBindings = GetAnimatableProperties(selectedItem, valueType);\n            }\n\n            if (potentialBindings == null || potentialBindings.Length == 0)\n                return null;\n\n            if (potentialBindings.Length == 1) // Single property for this valuetype, return it\n            {\n                return potentialBindings[0];\n            }\n            else // Multiple properties, dropdown selection\n            {\n                List<string> menuItems = new List<string>();\n                foreach (EditorCurveBinding binding in potentialBindings)\n                    menuItems.Add(binding.type.Name);\n\n                List<object> userDataList = new List<object>();\n                userDataList.Add(selectedItem.animationClip);\n                userDataList.Add(potentialBindings);\n\n                Rect r = new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 1, 1);\n                EditorUtility.DisplayCustomMenu(r, EditorGUIUtility.TempContent(menuItems.ToArray()), -1, SelectTypeForCreatingNewPptrDopeline, userDataList);\n                return null; // We return null, but creation is handled via dropdown callback code\n            }\n        }\n\n        private void SelectTypeForCreatingNewPptrDopeline(object userData, string[] options, int selected)\n        {\n            List<object> userDataList = userData as List<object>;\n            AnimationClip animationClip = userDataList[0] as AnimationClip;\n            List<EditorCurveBinding> bindings = userDataList[1] as List<EditorCurveBinding>;\n\n            if (bindings.Count > selected)\n                DoSpriteDropAfterGeneratingNewDopeline(animationClip, bindings[selected]);\n        }\n\n        private EditorCurveBinding CreateNewSpriteRendererDopeline(GameObject targetGameObject, GameObject rootGameObject)\n        {\n            // Let's make sure there is spriterenderer to animate\n            if (!targetGameObject.GetComponent<SpriteRenderer>())\n                targetGameObject.AddComponent<SpriteRenderer>();\n\n            return EditorCurveBinding.PPtrCurve(\n                AnimationUtility.CalculateTransformPath(targetGameObject.transform, rootGameObject.transform),\n                typeof(SpriteRenderer),\n                \"m_Sprite\");\n        }\n\n        private void HandleDragAndDrop(DopeLine dopeline)\n        {\n            Event evt = Event.current;\n\n            if (evt.type != EventType.DragPerform && evt.type != EventType.DragUpdated)\n                return;\n\n            if (DoDragAndDrop(dopeline, dopeline.position, evt.type == EventType.DragPerform))\n            {\n                DragAndDrop.visualMode = DragAndDropVisualMode.Copy;\n                evt.Use();\n            }\n            else\n            {\n                DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;\n            }\n        }\n\n        private void HandleMouseDown(DopeLine dopeline)\n        {\n            Event evt = Event.current;\n            if (!dopeline.position.Contains(evt.mousePosition))\n                return;\n\n            bool keysAreSelected = false;\n            foreach (AnimationWindowKeyframe keyframe in dopeline.keys)\n            {\n                Rect r = GetKeyframeRect(dopeline, keyframe);\n                if (r.Contains(evt.mousePosition) && state.KeyIsSelected(keyframe))\n                {\n                    keysAreSelected = true;\n                    break;\n                }\n            }\n\n            // For ctrl selecting, we unselect keys if we clicked a selected key frame.\n            bool canUnselectKeys = (keysAreSelected && EditorGUI.actionKey);\n\n            // Only allow new selected keys if current clicked key frame is unselected.\n            bool canSelectKeys = !keysAreSelected;\n\n            // If there are no selected keyframe in click without shift or EditorGUI.actionKey, then clear all other selections\n            if (!keysAreSelected && !EditorGUI.actionKey && !evt.shift)\n                state.ClearSelections();\n\n            float startTime = state.PixelToTime(Event.current.mousePosition.x);\n            float endTime = startTime;\n\n            // For shift selecting we need to have time range we choose between\n            if (Event.current.shift)\n            {\n                foreach (AnimationWindowKeyframe key in dopeline.keys)\n                {\n                    if (state.KeyIsSelected(key))\n                    {\n                        if (key.time < startTime)\n                            startTime = key.time;\n                        if (key.time > endTime)\n                            endTime = key.time;\n                    }\n                }\n            }\n\n            bool clickedOnKeyframe = false;\n            foreach (AnimationWindowKeyframe keyframe in dopeline.keys)\n            {\n                Rect r = GetKeyframeRect(dopeline, keyframe);\n                if (r.Contains(evt.mousePosition))\n                {\n                    clickedOnKeyframe = true;\n\n                    if (canUnselectKeys)\n                    {\n                        if (state.KeyIsSelected(keyframe))\n                        {\n                            state.UnselectKey(keyframe);\n\n                            if (!state.AnyKeyIsSelected(dopeline))\n                                state.UnSelectHierarchyItem(dopeline);\n                        }\n                    }\n                    else if (canSelectKeys)\n                    {\n                        if (!state.KeyIsSelected(keyframe))\n                        {\n                            if (Event.current.shift)\n                            {\n                                foreach (AnimationWindowKeyframe key in dopeline.keys)\n                                    if (key == keyframe || key.time > startTime && key.time < endTime)\n                                        state.SelectKey(key);\n                            }\n                            else\n                            {\n                                state.SelectKey(keyframe);\n                            }\n\n                            if (!dopeline.isMasterDopeline)\n                                state.SelectHierarchyItem(dopeline, EditorGUI.actionKey || evt.shift);\n                        }\n                    }\n\n                    state.activeKeyframe = keyframe;\n                    m_MousedownOnKeyframe = true;\n                    evt.Use();\n                }\n            }\n\n            if (dopeline.isMasterDopeline)\n            {\n                HashSet<int> hierarchyIDs = state.GetAffectedHierarchyIDs(state.selectedKeys);\n                state.SelectHierarchyItems(hierarchyIDs, true, true);\n            }\n\n            if (evt.clickCount == 2 && evt.button == 0 && !Event.current.shift && !EditorGUI.actionKey)\n                HandleDopelineDoubleclick(dopeline);\n\n            // Move playhead when clicked with right mouse button\n            if (evt.button == 1 && !state.controlInterface.playing)\n            {\n                // Clear keyframe selection if right clicked empty space\n                if (!clickedOnKeyframe)\n                {\n                    state.ClearSelections();\n                    m_IsDraggingPlayheadStarted = true;\n                    HandleUtility.Repaint();\n                    evt.Use();\n                }\n            }\n        }\n\n        private void HandleDopelineDoubleclick(DopeLine dopeline)\n        {\n            float timeAtMousePosition = state.PixelToTime(Event.current.mousePosition.x, AnimationWindowState.SnapMode.SnapToFrame);\n            AnimationKeyTime mouseKeyTime = AnimationKeyTime.Time(timeAtMousePosition, state.frameRate);\n            AnimationWindowUtility.AddKeyframes(state, dopeline.curves, mouseKeyTime);\n\n            Event.current.Use();\n        }\n\n        private void HandleContextMenu(DopeLine dopeline)\n        {\n            if (!dopeline.position.Contains(Event.current.mousePosition))\n                return;\n\n            // Actual context menu\n            GenerateMenu(dopeline).ShowAsContext();\n        }\n\n        private Rect GetKeyframeRect(DopeLine dopeline, AnimationWindowKeyframe keyframe)\n        {\n            float time = keyframe != null ? keyframe.time : 0f;\n\n            float width = 10f;\n            if (dopeline.isPptrDopeline && dopeline.tallMode && (keyframe == null || keyframe.value != null))\n                width = dopeline.position.height;\n\n            return new Rect(state.TimeToPixel(state.SnapToFrame(time, AnimationWindowState.SnapMode.SnapToFrame)) + GetKeyframeOffset(dopeline, keyframe), dopeline.position.yMin, width, dopeline.position.height);\n        }\n\n        // This means \"how much is the rendered keyframe offset in pixels for x-axis\".\n        // Say you are rendering keyframe to some time t. The time t relates to some pixel x, but you then need to offset because keyframe diamond center represents the time, not the left edge\n        // However for pptr keyframes, the time is represented by left edge\n        private float GetKeyframeOffset(DopeLine dopeline, AnimationWindowKeyframe keyframe)\n        {\n            if (dopeline.isPptrDopeline && dopeline.tallMode && (keyframe == null || keyframe.value != null))\n                return k_PptrKeyframeOffset;\n            else\n                return k_KeyframeOffset;\n        }\n\n        // Frame the selected keyframes or selected dopelines\n        public void FrameClip()\n        {\n            if (state.disabled)\n                return;\n\n            Vector2 timeRange = state.timeRange;\n            timeRange.y = Mathf.Max(timeRange.x + 0.1f, timeRange.y);\n            SetShownHRangeInsideMargins(timeRange.x, timeRange.y);\n        }\n\n        public void FrameSelected()\n        {\n            Bounds frameBounds = new Bounds();\n            bool firstKey = true;\n\n            bool keyframesSelected = state.selectedKeys.Count > 0;\n\n            if (keyframesSelected)\n            {\n                foreach (AnimationWindowKeyframe key in state.selectedKeys)\n                {\n                    Vector2 pt = new Vector2(key.time, 0.0f);\n                    if (firstKey)\n                    {\n                        frameBounds.SetMinMax(pt, pt);\n                        firstKey = false;\n                    }\n                    else\n                    {\n                        frameBounds.Encapsulate(pt);\n                    }\n                }\n            }\n\n            // No keyframes selected. Frame to selected dopelines\n            bool frameToClip = !keyframesSelected;\n            if (!keyframesSelected)\n            {\n                bool dopelinesSelected = state.hierarchyState.selectedIDs.Count > 0;\n                if (dopelinesSelected)\n                {\n                    foreach (AnimationWindowCurve curve in state.activeCurves)\n                    {\n                        int keyCount = curve.keyframes.Count;\n\n                        if (keyCount > 1)\n                        {\n                            Vector2 pt1 = new Vector2(curve.keyframes[0].time, 0.0f);\n                            Vector2 pt2 = new Vector2(curve.keyframes[keyCount - 1].time, 0.0f);\n\n                            if (firstKey)\n                            {\n                                frameBounds.SetMinMax(pt1, pt2);\n                                firstKey = false;\n                            }\n                            else\n                            {\n                                frameBounds.Encapsulate(pt1);\n                                frameBounds.Encapsulate(pt2);\n                            }\n\n                            frameToClip = false;\n                        }\n                    }\n                }\n            }\n\n\n            if (frameToClip)\n                FrameClip();\n            else\n            {\n                // Let's make sure we don't zoom too close.\n                frameBounds.size = new Vector3(Mathf.Max(frameBounds.size.x, 0.1f), Mathf.Max(frameBounds.size.y, 0.1f), 0);\n                SetShownHRangeInsideMargins(frameBounds.min.x, frameBounds.max.x);\n            }\n        }\n\n        private bool DoDragAndDrop(DopeLine dopeLine, Rect position, bool perform)\n        {\n            if (position.Contains(Event.current.mousePosition) == false)\n                return false;\n\n            if (!ValidateDragAndDropObjects())\n                return false;\n\n            System.Type targetType = DragAndDrop.objectReferences[0].GetType();\n            AnimationWindowCurve curve = null;\n            if (dopeLine.valueType == targetType)\n            {\n                curve = dopeLine.curves[0];\n            }\n            else\n            {\n                // dopeline ValueType wasn't exact match. We can still look for a curve that accepts our drop object type\n                foreach (AnimationWindowCurve dopelineCurve in dopeLine.curves)\n                {\n                    if (dopelineCurve.isPPtrCurve)\n                    {\n                        if (dopelineCurve.valueType == targetType)\n                            curve = dopelineCurve;\n\n                        List<Sprite> sprites = SpriteUtility.GetSpriteFromPathsOrObjects(DragAndDrop.objectReferences, DragAndDrop.paths, Event.current.type);\n                        if (dopelineCurve.valueType == typeof(Sprite) && sprites.Count > 0)\n                        {\n                            curve = dopelineCurve;\n                            targetType = typeof(Sprite);\n                        }\n                    }\n                }\n            }\n\n            if (curve == null)\n                return false;\n\n            if (!curve.clipIsEditable)\n                return false;\n\n            if (perform)\n            {\n                float time = Mathf.Max(state.PixelToTime(Event.current.mousePosition.x, AnimationWindowState.SnapMode.SnapToFrame), 0f);\n                AnimationWindowCurve targetCurve = GetCurveOfType(dopeLine, targetType);\n                PerformDragAndDrop(targetCurve, time);\n            }\n\n            return true;\n        }\n\n        private void PerformDragAndDrop(AnimationWindowCurve targetCurve, float time)\n        {\n            if (DragAndDrop.objectReferences.Length == 0 || targetCurve == null)\n                return;\n\n            string undoLabel = L10n.Tr(\"Drop Key\");\n            state.SaveKeySelection(undoLabel);\n\n            state.ClearSelections();\n            Object[] objectReferences = GetSortedDragAndDropObjectReferences();\n\n            int startFrame = AnimationKeyTime.Time(time, targetCurve.clip.frameRate).frame;\n\n            for (int i = 0; i < objectReferences.Length; ++i)\n            {\n                Object value = objectReferences[i];\n\n                if (value is Texture2D)\n                    value = SpriteUtility.TextureToSprite(value as Texture2D);\n\n                CreateNewPPtrKeyframe(AnimationKeyTime.Frame(startFrame + i, targetCurve.clip.frameRate).time, value, targetCurve);\n            }\n\n            state.SaveCurve(targetCurve.clip, targetCurve, undoLabel);\n            DragAndDrop.AcceptDrag();\n        }\n\n        private Object[] GetSortedDragAndDropObjectReferences()\n        {\n            Object[] objectReferences = DragAndDrop.objectReferences;\n\n            // Use same name compare as when we sort in the backend: See AssetDatabase.cpp: SortChildren\n            System.Array.Sort(objectReferences, (a, b) => EditorUtility.NaturalCompare(a.name, b.name));\n\n            return objectReferences;\n        }\n\n        private void CreateNewPPtrKeyframe(float time, Object value, AnimationWindowCurve targetCurve)\n        {\n            ObjectReferenceKeyframe referenceKeyframe = new ObjectReferenceKeyframe();\n\n            referenceKeyframe.time = time;\n            referenceKeyframe.value = value;\n\n            AnimationWindowKeyframe keyframe = new AnimationWindowKeyframe(targetCurve, referenceKeyframe);\n            AnimationKeyTime newTime = AnimationKeyTime.Time(keyframe.time, state.frameRate);\n            targetCurve.AddKeyframe(keyframe, newTime);\n            state.SelectKey(keyframe);\n        }\n\n        // if targetType == null, it means that all types are fine (as long as they are all of the same type)\n        private static bool ValidateDragAndDropObjects()\n        {\n            if (DragAndDrop.objectReferences.Length == 0)\n                return false;\n\n            // Let's be safe and early out if any of the objects are null or if they aren't all of the same type (exception beign sprite vs. texture2D, which are considered equal here)\n            for (int i = 0; i < DragAndDrop.objectReferences.Length; i++)\n            {\n                Object obj = DragAndDrop.objectReferences[i];\n                if (obj == null)\n                {\n                    return false;\n                }\n\n                if (i < DragAndDrop.objectReferences.Length - 1)\n                {\n                    Object nextObj = DragAndDrop.objectReferences[i + 1];\n                    bool bothAreSpritesOrTextures = (obj is Texture2D || obj is Sprite) && (nextObj is Texture2D || nextObj is Sprite);\n\n                    if (obj.GetType() != nextObj.GetType() && !bothAreSpritesOrTextures)\n                    {\n                        return false;\n                    }\n                }\n            }\n            return true;\n        }\n\n        private AnimationWindowCurve GetCurveOfType(DopeLine dopeLine, System.Type type)\n        {\n            foreach (AnimationWindowCurve curve in dopeLine.curves)\n            {\n                if (curve.valueType == type)\n                    return curve;\n            }\n            return null;\n        }\n\n        // For optimizing. Starting from keyIndex, we check through any key with same time and see if any are selected\n        private bool AnyKeyIsSelectedAtTime(DopeLine dopeLine, int keyIndex)\n        {\n            AnimationWindowKeyframe keyframe = dopeLine.keys[keyIndex];\n            int firstTimeHash = keyframe.m_TimeHash;\n\n            int length = dopeLine.keys.Count;\n            for (int i = keyIndex; i < length; i++)\n            {\n                keyframe = dopeLine.keys[i];\n                int timeHash = keyframe.m_TimeHash;\n\n                if (timeHash != firstTimeHash)\n                    return false;\n\n                if (state.KeyIsSelected(keyframe))\n                    return true;\n            }\n\n            return false;\n        }\n\n        private struct AddKeyToDopelineContext\n        {\n            public DopeLine dopeline;\n            public AnimationKeyTime time;\n        }\n\n        private void AddKeyToDopeline(object obj) { AddKeyToDopeline((AddKeyToDopelineContext)obj); }\n        private void AddKeyToDopeline(AddKeyToDopelineContext context)\n        {\n            AnimationWindowUtility.AddKeyframes(state, context.dopeline.curves, context.time);\n        }\n\n        private void DeleteKeys(object obj) { DeleteKeys((List<AnimationWindowKeyframe>)obj); }\n        private void DeleteKeys(List<AnimationWindowKeyframe> keys)\n        {\n            state.DeleteKeys(keys);\n        }\n\n        internal class DopeSheetSelectionRect\n        {\n            Vector2 m_SelectStartPoint;\n            Vector2 m_SelectMousePoint;\n            bool m_ValidRect;\n            private DopeSheetEditor owner;\n\n            enum SelectionType { Normal, Additive, Subtractive }\n            public readonly GUIStyle createRect = \"U2D.createRect\";\n\n            static int s_RectSelectionID = GUIUtility.GetPermanentControlID();\n\n            public DopeSheetSelectionRect(DopeSheetEditor owner)\n            {\n                this.owner = owner;\n            }\n\n            public void OnGUI(Rect position)\n            {\n                Event evt = Event.current;\n                Vector2 mousePos = evt.mousePosition;\n                int id = s_RectSelectionID;\n                switch (evt.GetTypeForControl(id))\n                {\n                    case EventType.MouseDown:\n                        if (evt.button == 0 && position.Contains(mousePos))\n                        {\n                            GUIUtility.hotControl = id;\n                            m_SelectStartPoint = mousePos;\n                            m_ValidRect = false;\n                            evt.Use();\n                        }\n                        break;\n                    case EventType.MouseDrag:\n                        if (GUIUtility.hotControl == id)\n                        {\n                            m_ValidRect = Mathf.Abs((mousePos - m_SelectStartPoint).x) > 1f;\n\n                            if (m_ValidRect)\n                                m_SelectMousePoint = new Vector2(mousePos.x, mousePos.y);\n\n                            evt.Use();\n                        }\n                        break;\n\n                    case EventType.Repaint:\n                        if (GUIUtility.hotControl == id && m_ValidRect)\n                            EditorStyles.selectionRect.Draw(GetCurrentPixelRect(), GUIContent.none, false, false, false, false);\n                        break;\n\n                    case EventType.MouseUp:\n                        if (GUIUtility.hotControl == id && evt.button == 0)\n                        {\n                            if (m_ValidRect)\n                            {\n                                if (!evt.shift && !EditorGUI.actionKey)\n                                    owner.state.ClearSelections();\n\n                                float frameRate = owner.state.frameRate;\n\n                                Rect timeRect = GetCurrentTimeRect();\n                                GUI.changed = true;\n\n                                owner.state.ClearHierarchySelection();\n\n                                HashSet<AnimationWindowKeyframe> toBeUnselected = new HashSet<AnimationWindowKeyframe>();\n                                HashSet<AnimationWindowKeyframe> toBeSelected = new HashSet<AnimationWindowKeyframe>();\n\n                                foreach (DopeLine dopeline in owner.state.dopelines)\n                                {\n                                    if (dopeline.position.yMin >= timeRect.yMin && dopeline.position.yMax <= timeRect.yMax)\n                                    {\n                                        foreach (AnimationWindowKeyframe keyframe in dopeline.keys)\n                                        {\n                                            AnimationKeyTime startTime = AnimationKeyTime.Time(timeRect.xMin, frameRate);\n                                            AnimationKeyTime endTime = AnimationKeyTime.Time(timeRect.xMax, frameRate);\n\n                                            AnimationKeyTime keyTime = AnimationKeyTime.Time(keyframe.time, frameRate);\n                                            // for dopeline tallmode, we don't want to select the sprite at the end. It just feels wrong.\n                                            if (!dopeline.tallMode && keyTime.frame >= startTime.frame && keyTime.frame <= endTime.frame ||\n                                                dopeline.tallMode && keyTime.frame >= startTime.frame && keyTime.frame < endTime.frame)\n                                            {\n                                                if (!toBeSelected.Contains(keyframe) && !toBeUnselected.Contains(keyframe))\n                                                {\n                                                    if (!owner.state.KeyIsSelected(keyframe))\n                                                        toBeSelected.Add(keyframe);\n                                                    else if (owner.state.KeyIsSelected(keyframe))\n                                                        toBeUnselected.Add(keyframe);\n                                                }\n                                            }\n                                        }\n                                    }\n                                }\n\n                                // Only if all the keys inside rect are selected, we want to unselect them.\n                                if (toBeSelected.Count == 0)\n                                    foreach (AnimationWindowKeyframe keyframe in toBeUnselected)\n                                        owner.state.UnselectKey(keyframe);\n\n                                foreach (AnimationWindowKeyframe keyframe in toBeSelected)\n                                    owner.state.SelectKey(keyframe);\n\n                                // Update hierarchy selection based on newly selected keys\n                                foreach (DopeLine dopeline in owner.state.dopelines)\n                                    if (owner.state.AnyKeyIsSelected(dopeline))\n                                        owner.state.SelectHierarchyItem(dopeline, true, false);\n                            }\n                            else\n                            {\n                                owner.state.ClearSelections();\n                            }\n                            evt.Use();\n                            GUIUtility.hotControl = 0;\n                        }\n                        break;\n                }\n            }\n\n            public Rect GetCurrentPixelRect()\n            {\n                float height = AnimationWindowHierarchyGUI.k_DopeSheetRowHeight;\n                Rect r = AnimationWindowUtility.FromToRect(m_SelectStartPoint, m_SelectMousePoint);\n                r.xMin = owner.state.TimeToPixel(owner.state.PixelToTime(r.xMin, AnimationWindowState.SnapMode.SnapToFrame), AnimationWindowState.SnapMode.SnapToFrame);\n                r.xMax = owner.state.TimeToPixel(owner.state.PixelToTime(r.xMax, AnimationWindowState.SnapMode.SnapToFrame), AnimationWindowState.SnapMode.SnapToFrame);\n                r.yMin = Mathf.Floor(r.yMin / height) * height;\n                r.yMax = (Mathf.Floor(r.yMax / height) + 1) * height;\n                return r;\n            }\n\n            public Rect GetCurrentTimeRect()\n            {\n                float height = AnimationWindowHierarchyGUI.k_DopeSheetRowHeight;\n                Rect r = AnimationWindowUtility.FromToRect(m_SelectStartPoint, m_SelectMousePoint);\n                r.xMin = owner.state.PixelToTime(r.xMin, AnimationWindowState.SnapMode.SnapToFrame);\n                r.xMax = owner.state.PixelToTime(r.xMax, AnimationWindowState.SnapMode.SnapToFrame);\n                r.yMin = Mathf.Floor(r.yMin / height) * height;\n                r.yMax = (Mathf.Floor(r.yMax / height) + 1) * height;\n                return r;\n            }\n        }\n\n        public void UpdateCurves(List<ChangedCurve> changedCurves, string undoText)\n        {\n            Undo.RegisterCompleteObjectUndo(state.activeAnimationClip, undoText);\n\n            foreach (ChangedCurve changedCurve in changedCurves)\n            {\n                AnimationWindowCurve curve = state.filteredCurves.Find(c => changedCurve.curveId == c.GetHashCode());\n                if (curve != null)\n                {\n                    AnimationUtility.SetEditorCurve(curve.clip, changedCurve.binding, changedCurve.curve);\n                }\n                else\n                {\n                    Debug.LogError(\"Could not match ChangedCurve data to destination curves.\");\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/DopeSheetEditorRectangleTool.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditorInternal;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class DopeSheetEditorRectangleTool : RectangleTool\n    {\n        const int kScaleLeftWidth = 17;\n        const int kScaleLeftMarginHorizontal = 0;\n        const float kScaleLeftMarginVertical = 4;\n\n        const int kScaleRightWidth = 17;\n        const int kScaleRightMarginHorizontal = 0;\n        const float kScaleRightMarginVertical = 4;\n\n        const int kHLabelMarginHorizontal = 8;\n        const int kHLabelMarginVertical = 1;\n\n        static Rect g_EmptyRect = new Rect(0f, 0f, 0f, 0f);\n\n        struct ToolLayout\n        {\n            public Rect summaryRect;\n            public Rect selectionRect;\n\n            public Rect scaleLeftRect;\n            public Rect scaleRightRect;\n\n            public Vector2 leftLabelAnchor;\n            public Vector2 rightLabelAnchor;\n        }\n\n        private DopeSheetEditor m_DopeSheetEditor;\n        private AnimationWindowState m_State;\n\n        private ToolLayout m_Layout;\n\n        private Vector2 m_Pivot;\n        private Vector2 m_Previous;\n        private Vector2 m_MouseOffset;\n\n        private bool m_IsDragging;\n        private bool m_RippleTime;\n        private float m_RippleTimeStart;\n        private float m_RippleTimeEnd;\n\n        private AreaManipulator[] m_SelectionBoxes;\n\n        private AreaManipulator m_SelectionScaleLeft;\n        private AreaManipulator m_SelectionScaleRight;\n\n        private AreaManipulator m_SelectionRippleLeft;\n        private AreaManipulator m_SelectionRippleRight;\n\n        private bool hasSelection { get { return (m_State.selectedKeys.Count > 0); } }\n        private Bounds selectionBounds { get { return m_State.selectionBounds; } }\n        private float frameRate { get { return m_State.frameRate; } }\n        private bool rippleTime { get { return m_State.rippleTime; } }\n\n        private bool isDragging { get { return m_IsDragging || m_DopeSheetEditor.isDragging; } }\n\n        public override void Initialize(TimeArea timeArea)\n        {\n            base.Initialize(timeArea);\n            m_DopeSheetEditor = timeArea as DopeSheetEditor;\n            m_State = m_DopeSheetEditor.state;\n\n            if (m_SelectionBoxes == null)\n            {\n                m_SelectionBoxes = new AreaManipulator[2];\n\n                for (int i = 0; i < 2; ++i)\n                {\n                    m_SelectionBoxes[i] = new AreaManipulator(styles.rectangleToolSelection, MouseCursor.MoveArrow);\n\n                    m_SelectionBoxes[i].onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                    {\n                        bool curveEditorOverride = evt.shift || EditorGUI.actionKey;\n                        if (!curveEditorOverride && hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                        {\n                            OnStartMove(new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0.0f), rippleTime);\n                            return true;\n                        }\n\n                        return false;\n                    };\n                    m_SelectionBoxes[i].onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                    {\n                        OnMove(new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0.0f));\n                        return true;\n                    };\n                    m_SelectionBoxes[i].onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                    {\n                        OnEndMove();\n                        return true;\n                    };\n                }\n            }\n\n            if (m_SelectionScaleLeft == null)\n            {\n                m_SelectionScaleLeft = new AreaManipulator(styles.dopesheetScaleLeft, MouseCursor.ResizeHorizontal);\n\n                m_SelectionScaleLeft.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartScale(ToolCoord.Right, ToolCoord.Left, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), false);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_SelectionScaleLeft.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate));\n                    return true;\n                };\n                m_SelectionScaleLeft.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndScale();\n                    return true;\n                };\n            }\n\n            if (m_SelectionScaleRight == null)\n            {\n                m_SelectionScaleRight = new AreaManipulator(styles.dopesheetScaleRight, MouseCursor.ResizeHorizontal);\n\n                m_SelectionScaleRight.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartScale(ToolCoord.Left, ToolCoord.Right, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), false);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_SelectionScaleRight.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate));\n                    return true;\n                };\n                m_SelectionScaleRight.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndScale();\n                    return true;\n                };\n            }\n\n            if (m_SelectionRippleLeft == null)\n            {\n                m_SelectionRippleLeft = new AreaManipulator(styles.dopesheetRippleLeft, MouseCursor.ResizeHorizontal);\n\n                m_SelectionRippleLeft.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartScale(ToolCoord.Right, ToolCoord.Left, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), true);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_SelectionRippleLeft.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate));\n                    return true;\n                };\n                m_SelectionRippleLeft.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndScale();\n                    return true;\n                };\n            }\n\n            if (m_SelectionRippleRight == null)\n            {\n                m_SelectionRippleRight = new AreaManipulator(styles.dopesheetRippleRight, MouseCursor.ResizeHorizontal);\n\n                m_SelectionRippleRight.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    if (hasSelection && manipulator.rect.Contains(evt.mousePosition))\n                    {\n                        OnStartScale(ToolCoord.Left, ToolCoord.Right, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), true);\n                        return true;\n                    }\n\n                    return false;\n                };\n                m_SelectionRippleRight.onDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate));\n                    return true;\n                };\n                m_SelectionRippleRight.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) =>\n                {\n                    OnEndScale();\n                    return true;\n                };\n            }\n        }\n\n        public void OnGUI()\n        {\n            if (!hasSelection)\n                return;\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            m_Layout = CalculateLayout();\n\n            m_SelectionBoxes[0].OnGUI(m_Layout.summaryRect);\n            m_SelectionBoxes[1].OnGUI(m_Layout.selectionRect);\n\n            bool showRippleHandles = (rippleTime && !isDragging) || (m_RippleTime && isDragging);\n\n            if (showRippleHandles)\n            {\n                m_SelectionRippleLeft.OnGUI(m_Layout.scaleLeftRect);\n                m_SelectionRippleRight.OnGUI(m_Layout.scaleRightRect);\n            }\n            else\n            {\n                m_SelectionScaleLeft.OnGUI(m_Layout.scaleLeftRect);\n                m_SelectionScaleRight.OnGUI(m_Layout.scaleRightRect);\n            }\n\n            DrawLabels();\n        }\n\n        public void HandleEvents()\n        {\n            if (rippleTime)\n            {\n                m_SelectionRippleLeft.HandleEvents();\n                m_SelectionRippleRight.HandleEvents();\n            }\n            else\n            {\n                m_SelectionScaleLeft.HandleEvents();\n                m_SelectionScaleRight.HandleEvents();\n            }\n\n            m_SelectionBoxes[0].HandleEvents();\n            m_SelectionBoxes[1].HandleEvents();\n        }\n\n        private ToolLayout CalculateLayout()\n        {\n            ToolLayout layout = new ToolLayout();\n\n            Bounds bounds = selectionBounds;\n\n            bool canScaleX = !Mathf.Approximately(bounds.size.x, 0f);\n\n            float xMin = TimeToPixel(bounds.min.x);\n            float xMax = TimeToPixel(bounds.max.x);\n\n            float yMin = 0f, yMax = 0f;\n            bool firstKey = true;\n\n            float heightCumul = 0f;\n\n            List<DopeLine> dopelines = m_State.dopelines;\n            for (int i = 0; i < dopelines.Count; ++i)\n            {\n                DopeLine dopeline = dopelines[i];\n\n                float dopelineHeight = (dopeline.tallMode ? AnimationWindowHierarchyGUI.k_DopeSheetRowHeightTall : AnimationWindowHierarchyGUI.k_DopeSheetRowHeight);\n\n                if (!dopeline.isMasterDopeline)\n                {\n                    int length = dopeline.keys.Count;\n                    for (int j = 0; j < length; j++)\n                    {\n                        AnimationWindowKeyframe keyframe = dopeline.keys[j];\n                        if (m_State.KeyIsSelected(keyframe))\n                        {\n                            if (firstKey)\n                            {\n                                yMin = heightCumul;\n                                firstKey = false;\n                            }\n\n                            yMax = heightCumul + dopelineHeight;\n                            break;\n                        }\n                    }\n                }\n\n                heightCumul += dopelineHeight;\n            }\n\n            layout.summaryRect = new Rect(xMin, 0f, xMax - xMin, AnimationWindowHierarchyGUI.k_DopeSheetRowHeight);\n            layout.selectionRect = new Rect(xMin, yMin, xMax - xMin, yMax - yMin);\n\n            // Scale handles.\n            if (canScaleX)\n            {\n                layout.scaleLeftRect = new Rect(layout.selectionRect.xMin - kScaleLeftMarginHorizontal - kScaleLeftWidth, layout.selectionRect.yMin + kScaleLeftMarginVertical, kScaleLeftWidth, layout.selectionRect.height - kScaleLeftMarginVertical * 2);\n                layout.scaleRightRect = new Rect(layout.selectionRect.xMax + kScaleRightMarginHorizontal, layout.selectionRect.yMin + kScaleRightMarginVertical, kScaleRightWidth, layout.selectionRect.height - kScaleRightMarginVertical * 2);\n            }\n            else\n            {\n                layout.scaleLeftRect = g_EmptyRect;\n                layout.scaleRightRect = g_EmptyRect;\n            }\n\n            if (canScaleX)\n            {\n                layout.leftLabelAnchor = new Vector2(layout.summaryRect.xMin - kHLabelMarginHorizontal, contentRect.yMin + kHLabelMarginVertical);\n                layout.rightLabelAnchor = new Vector2(layout.summaryRect.xMax + kHLabelMarginHorizontal, contentRect.yMin + kHLabelMarginVertical);\n            }\n            else\n            {\n                layout.leftLabelAnchor = layout.rightLabelAnchor = new Vector2(layout.summaryRect.center.x + kHLabelMarginHorizontal, contentRect.yMin + kHLabelMarginVertical);\n            }\n\n            return layout;\n        }\n\n        private void DrawLabels()\n        {\n            if (isDragging == false)\n                return;\n\n            bool canScaleX = !Mathf.Approximately(selectionBounds.size.x, 0f);\n\n            if (canScaleX)\n            {\n                GUIContent leftLabelContent = new GUIContent(string.Format(\"{0}\", m_DopeSheetEditor.FormatTime(selectionBounds.min.x, m_State.frameRate, m_State.timeFormat)));\n                GUIContent rightLabelContent = new GUIContent(string.Format(\"{0}\", m_DopeSheetEditor.FormatTime(selectionBounds.max.x, m_State.frameRate, m_State.timeFormat)));\n\n                Vector2 leftLabelSize = styles.dragLabel.CalcSize(leftLabelContent);\n                Vector2 rightLabelSize = styles.dragLabel.CalcSize(rightLabelContent);\n\n                EditorGUI.DoDropShadowLabel(new Rect(m_Layout.leftLabelAnchor.x - leftLabelSize.x, m_Layout.leftLabelAnchor.y, leftLabelSize.x, leftLabelSize.y), leftLabelContent, styles.dragLabel, 0.3f);\n                EditorGUI.DoDropShadowLabel(new Rect(m_Layout.rightLabelAnchor.x, m_Layout.rightLabelAnchor.y, rightLabelSize.x, rightLabelSize.y), rightLabelContent, styles.dragLabel, 0.3f);\n            }\n            else\n            {\n                GUIContent labelContent = new GUIContent(string.Format(\"{0}\", m_DopeSheetEditor.FormatTime(selectionBounds.center.x, m_State.frameRate, m_State.timeFormat)));\n                Vector2 labelSize = styles.dragLabel.CalcSize(labelContent);\n\n                EditorGUI.DoDropShadowLabel(new Rect(m_Layout.leftLabelAnchor.x, m_Layout.leftLabelAnchor.y, labelSize.x, labelSize.y), labelContent, styles.dragLabel, 0.3f);\n            }\n        }\n\n        private void OnStartScale(ToolCoord pivotCoord, ToolCoord pickedCoord, Vector2 mousePos, bool rippleTime)\n        {\n            Bounds bounds = selectionBounds;\n\n            m_IsDragging = true;\n            m_Pivot = ToolCoordToPosition(pivotCoord, bounds);\n            m_Previous = ToolCoordToPosition(pickedCoord, bounds);\n            m_MouseOffset = mousePos - m_Previous;\n            m_RippleTime = rippleTime;\n            m_RippleTimeStart = bounds.min.x;\n            m_RippleTimeEnd = bounds.max.x;\n\n            m_State.StartLiveEdit();\n        }\n\n        private void OnScaleTime(float time)\n        {\n            Matrix4x4 transform;\n            bool flipX;\n            if (CalculateScaleTimeMatrix(m_Previous.x, time, m_MouseOffset.x, m_Pivot.x, frameRate, out transform, out flipX))\n                TransformKeys(transform, flipX, false);\n        }\n\n        private void OnEndScale()\n        {\n            m_State.EndLiveEdit();\n            m_IsDragging = false;\n        }\n\n        internal void OnStartMove(Vector2 position, bool rippleTime)\n        {\n            Bounds bounds = selectionBounds;\n\n            m_IsDragging = true;\n            m_Previous = position;\n            m_RippleTime = rippleTime;\n            m_RippleTimeStart = bounds.min.x;\n            m_RippleTimeEnd = bounds.max.x;\n\n            m_State.StartLiveEdit();\n        }\n\n        internal void OnMove(Vector2 position)\n        {\n            Vector2 dv = position - m_Previous;\n\n            Matrix4x4 transform = Matrix4x4.identity;\n            transform.SetTRS(new Vector3(dv.x, dv.y, 0f), Quaternion.identity, Vector3.one);\n\n            TransformKeys(transform, false, false);\n        }\n\n        internal void OnEndMove()\n        {\n            m_State.EndLiveEdit();\n            m_IsDragging = false;\n        }\n\n        private void TransformKeys(Matrix4x4 matrix, bool flipX, bool flipY)\n        {\n            if (m_RippleTime)\n                m_State.TransformRippleKeys(matrix, m_RippleTimeStart, m_RippleTimeEnd, flipX, true);\n            else\n                m_State.TransformSelectedKeys(matrix, flipX, flipY, true);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/GameObjectSelectionItem.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditorInternal\n{\n    [Serializable]\n    internal class GameObjectSelectionItem : AnimationWindowSelectionItem\n    {\n        public static GameObjectSelectionItem Create(GameObject gameObject)\n        {\n            var selectionItem = new GameObjectSelectionItem();\n\n            selectionItem.gameObject = gameObject;\n            selectionItem.animationClip = null;\n            selectionItem.id = 0; // no need for id since there's only one item in selection.\n\n            if (selectionItem.rootGameObject != null)\n            {\n                AnimationClip[] allClips = AnimationUtility.GetAnimationClips(selectionItem.rootGameObject);\n\n                if (selectionItem.animationClip == null && selectionItem.gameObject != null) // there is activeGO but clip is still null\n                    selectionItem.animationClip = allClips.Length > 0 ? allClips[0] : null;\n                else if (!Array.Exists(allClips, x => x == selectionItem.animationClip))  // clip doesn't belong to the currently active GO\n                    selectionItem.animationClip = allClips.Length > 0 ? allClips[0] : null;\n            }\n\n            return selectionItem;\n        }\n\n        public override AnimationClip animationClip\n        {\n            set\n            {\n                base.animationClip = value;\n            }\n            get\n            {\n                if (animationPlayer == null)\n                    return null;\n\n                return base.animationClip;\n            }\n        }\n\n        public override void Synchronize()\n        {\n            if (rootGameObject != null)\n            {\n                AnimationClip[] allClips = AnimationUtility.GetAnimationClips(rootGameObject);\n                if (allClips.Length > 0)\n                {\n                    if (!Array.Exists(allClips, x => x == animationClip))\n                    {\n                        animationClip = allClips[0];\n                    }\n                }\n                else\n                {\n                    animationClip = null;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/IAnimationContextualResponder.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditorInternal\n{\n    // Required information for animation recording.\n    internal interface IAnimationContextualResponder\n    {\n        bool IsAnimatable(PropertyModification[] modifications);\n        bool IsEditable(Object targetObject);\n\n        bool KeyExists(PropertyModification[] modifications);\n        bool CandidateExists(PropertyModification[] modifications);\n\n        bool CurveExists(PropertyModification[] modifications);\n\n        bool HasAnyCandidates();\n        bool HasAnyCurves();\n\n        void AddKey(PropertyModification[] modifications);\n        void RemoveKey(PropertyModification[] modifications);\n\n        void RemoveCurve(PropertyModification[] modifications);\n\n        void AddCandidateKeys();\n        void AddAnimatedKeys();\n\n        void GoToNextKeyframe(PropertyModification[] modifications);\n        void GoToPreviousKeyframe(PropertyModification[] modifications);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/IAnimationRecordingState.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditorInternal\n{\n    // Required information for animation recording.\n    internal interface IAnimationRecordingState\n    {\n        GameObject activeGameObject { get; }\n        GameObject activeRootGameObject { get; }\n        AnimationClip activeAnimationClip { get; }\n        int currentFrame { get; }\n\n        bool addZeroFrame { get; }\n\n        bool DiscardModification(PropertyModification modification);\n        void SaveCurve(AnimationWindowCurve curve);\n        void AddPropertyModification(EditorCurveBinding binding, PropertyModification propertyModification, bool keepPrefabOverride);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/IAnimationWindowControl.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditorInternal\n{\n    // Compatibility implementation of IAnimationWindowController.\n    abstract class IAnimationWindowControl : ScriptableObject, IAnimationWindowController\n    {\n        [SerializeReference] AnimationWindowState m_State;\n\n        public virtual void OnEnable()\n        {\n            hideFlags = HideFlags.HideAndDontSave;\n        }\n\n        public abstract void OnSelectionChanged();\n\n        public void Init(AnimationWindowState state)\n        {\n            m_State = state;\n        }\n\n        void IAnimationWindowController.OnCreate(AnimationWindow animationWindow, UnityEngine.Component component)\n        {\n        }\n\n        void IAnimationWindowController.OnDestroy()\n        {\n            // Animation Window has ownership of `IAnimationWindowControl` in legacy workflow.\n            Object.DestroyImmediate(this);\n        }\n\n        float IAnimationWindowController.time\n        {\n            get => time.time;\n            set => GoToTime(value);\n        }\n\n        int IAnimationWindowController.frame\n        {\n            get => time.frame;\n            set => GoToFrame(value);\n        }\n\n        public abstract AnimationKeyTime time { get; }\n\n        public abstract void GoToTime(float time);\n        public abstract void GoToFrame(int frame);\n\n        // Not used anymore. This was not used by either the AnimationWindow nor Timeline.\n        // Replaced by setting IAnimationWindowController.time.\n        public abstract void StartScrubTime();\n        public abstract void ScrubTime(float time);\n        public abstract void EndScrubTime();\n\n        // Not used anymore. Required internal knowledge of the Animation Window and\n        // default implementation should suffice.\n        public abstract void GoToPreviousFrame();\n        public abstract void GoToNextFrame();\n        public abstract void GoToPreviousKeyframe();\n        public abstract void GoToNextKeyframe();\n        public abstract void GoToFirstKeyframe();\n        public abstract void GoToLastKeyframe();\n\n        public abstract bool canPlay { get; }\n\n        bool IAnimationWindowController.playing\n        {\n            get => playing;\n            set\n            {\n                if (value)\n                    StartPlayback();\n                else\n                    StopPlayback();\n            }\n        }\n\n        public abstract bool playing { get; }\n        public abstract bool StartPlayback();\n        public abstract void StopPlayback();\n        public abstract bool PlaybackUpdate();\n\n        public abstract bool canPreview { get; }\n\n        bool IAnimationWindowController.previewing\n        {\n            get => previewing;\n            set\n            {\n                if (value)\n                    StartPreview();\n                else\n                    StopPreview();\n            }\n        }\n\n        public abstract bool previewing { get; }\n        public abstract bool StartPreview();\n        public abstract void StopPreview();\n\n        public abstract bool canRecord { get; }\n\n        bool IAnimationWindowController.recording\n        {\n            get => recording;\n            set\n            {\n                if (value)\n                    StartRecording(null);\n                else\n                    StopRecording();\n            }\n        }\n\n        public abstract bool recording { get; }\n        // targetObject parameter is not used.\n        public abstract bool StartRecording(Object targetObject);\n        public abstract void StopRecording();\n\n        public abstract void ResampleAnimation();\n\n        public abstract void ProcessCandidates();\n        public abstract void ClearCandidates();\n\n        EditorCurveBinding[] IAnimationWindowController.GetAnimatableBindings()\n        {\n            if (m_State == null)\n                return Array.Empty<EditorCurveBinding>();\n\n            var rootGameObject = m_State.activeRootGameObject;\n            var scriptableObject = m_State.activeScriptableObject;\n\n            if (rootGameObject != null)\n            {\n                return AnimationWindowUtility.GetAnimatableBindings(rootGameObject);\n            }\n            if (scriptableObject != null)\n            {\n                return AnimationUtility.GetAnimatableBindings(scriptableObject);\n            }\n\n            return Array.Empty<EditorCurveBinding>();\n        }\n\n        EditorCurveBinding[] IAnimationWindowController.GetAnimatableBindings(GameObject gameObject)\n        {\n            if (m_State == null)\n                return Array.Empty<EditorCurveBinding>();\n\n            var rootGameObject = m_State.activeRootGameObject;\n            return AnimationUtility.GetAnimatableBindings(gameObject, rootGameObject);\n        }\n\n        System.Type IAnimationWindowController.GetValueType(EditorCurveBinding binding)\n        {\n            if (m_State == null)\n                return default;\n\n            var rootGameObject = m_State.activeRootGameObject;\n            var scriptableObject = m_State.activeScriptableObject;\n\n            if (rootGameObject != null)\n            {\n                return AnimationUtility.GetEditorCurveValueType(rootGameObject, binding);\n            }\n            else if (scriptableObject != null)\n            {\n                return AnimationUtility.GetEditorCurveValueType(scriptableObject, binding);\n            }\n            else\n            {\n                if (binding.isPPtrCurve)\n                {\n                    // Cannot extract type of PPtrCurve.\n                    return null;\n                }\n                else\n                {\n                    // Cannot extract type of AnimationCurve.  Default to float.\n                    return typeof(float);\n                }\n            }\n        }\n\n        float IAnimationWindowController.GetFloatValue(EditorCurveBinding binding)\n        {\n            if (m_State == null)\n                return default;\n\n            AnimationUtility.GetFloatValue(m_State.activeRootGameObject, binding, out var value);\n            return value;\n        }\n\n        int IAnimationWindowController.GetIntValue(EditorCurveBinding binding)\n        {\n            if (m_State == null)\n                return default;\n\n            AnimationUtility.GetDiscreteIntValue(m_State.activeRootGameObject, binding, out var value);\n            return value;\n        }\n\n        UnityEngine.Object IAnimationWindowController.GetObjectReferenceValue(EditorCurveBinding binding)\n        {\n            if (m_State == null)\n                return default;\n\n            AnimationUtility.GetObjectReferenceValue(m_State.activeRootGameObject, binding, out var value);\n            return value;\n        }\n\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/IAnimationWindowController.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    interface IAnimationWindowController\n    {\n        void OnCreate(AnimationWindow animationWindow, UnityEngine.Component component);\n        void OnDestroy();\n        void OnSelectionChanged();\n\n        float time { get; set; }\n        int frame { get; set; }\n\n        bool canPlay { get; }\n        bool playing { get; set; }\n\n        bool PlaybackUpdate();\n\n        bool canPreview { get; }\n        bool previewing { get; set; }\n\n        bool canRecord { get; }\n        bool recording { get; set; }\n\n        void ResampleAnimation();\n\n        void ProcessCandidates();\n        void ClearCandidates();\n\n        EditorCurveBinding[] GetAnimatableBindings(GameObject gameObject);\n        EditorCurveBinding[] GetAnimatableBindings();\n        System.Type GetValueType(EditorCurveBinding binding);\n        float GetFloatValue(EditorCurveBinding binding);\n        int GetIntValue(EditorCurveBinding binding);\n        UnityEngine.Object GetObjectReferenceValue(EditorCurveBinding binding);\n\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/MinMaxCurveEditorWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class MinMaxCurveEditorWindow : EditorWindow\n    {\n        const int k_PresetsHeight = 46;\n        const float k_WindowMinSize = 240;\n        const float k_WindowMaxSize = 10000;\n        const float k_PresetSwatchMargin = 45f;\n        const float k_PresetSwatchWidth = 40f;\n        const float k_PresetSwatchHeight = 25f;\n        const float k_PresetSwatchSeperation = 5;\n        const float k_PresetsDropdownButtonSize = 20;\n\n        static MinMaxCurveEditorWindow s_SharedMinMaxCurveEditor;\n\n        static CurveEditorWindow.Styles s_Styles;\n\n        CurveEditor m_CurveEditor;\n\n        AnimationCurve m_MinCurve;\n        AnimationCurve m_MaxCurve;\n\n        SerializedProperty m_MultiplierProperty;\n        Color m_Color;\n\n        DoubleCurvePresetsContentsForPopupWindow m_CurvePresets;\n\n        [SerializeField]\n        GUIView delegateView;\n\n        public static MinMaxCurveEditorWindow instance\n        {\n            get\n            {\n                if (!s_SharedMinMaxCurveEditor)\n                    s_SharedMinMaxCurveEditor = ScriptableObject.CreateInstance<MinMaxCurveEditorWindow>();\n                return s_SharedMinMaxCurveEditor;\n            }\n        }\n\n        public AnimationCurve minCurve { get { return m_MinCurve; } }\n        public AnimationCurve maxCurve { get { return m_MaxCurve; } }\n\n        public static string xAxisLabel { get; set; } = \"time\";\n\n        public static bool visible\n        {\n            get { return s_SharedMinMaxCurveEditor != null; }\n        }\n\n        // Called by OnEnable to make sure the CurveEditor is not null,\n        // and by Show so we get a fresh CurveEditor when the user clicks a new curve.\n        void Init(CurveEditorSettings settings)\n        {\n            m_CurveEditor = new CurveEditor(GetCurveEditorRect(), GetCurveWrapperArray(), true);\n            m_CurveEditor.curvesUpdated = UpdateCurve;\n            m_CurveEditor.scaleWithWindow = true;\n            m_CurveEditor.margin = 40;\n            if (settings != null)\n                m_CurveEditor.settings = settings;\n            m_CurveEditor.settings.hTickLabelOffset = 10;\n            m_CurveEditor.settings.rectangleToolFlags = CurveEditorSettings.RectangleToolFlags.MiniRectangleTool;\n            m_CurveEditor.settings.undoRedoSelection = true;\n            m_CurveEditor.settings.showWrapperPopups = true;\n            m_CurveEditor.settings.xAxisLabel = xAxisLabel;\n            UpdateRegionDomain();\n\n            // For each of horizontal and vertical axis, if we have a finite range for that axis, use that range,\n            // otherwise use framing logic to determine shown range for that axis.\n            bool frameH = true;\n            bool frameV = true;\n            if (!float.IsNegativeInfinity(m_CurveEditor.settings.hRangeMin) && !float.IsInfinity(m_CurveEditor.settings.hRangeMax))\n            {\n                m_CurveEditor.SetShownHRangeInsideMargins(m_CurveEditor.settings.hRangeMin, m_CurveEditor.settings.hRangeMax);\n                frameH = false;\n            }\n            if (!float.IsNegativeInfinity(m_CurveEditor.settings.vRangeMin) && !float.IsInfinity(m_CurveEditor.settings.vRangeMax))\n            {\n                m_CurveEditor.SetShownVRangeInsideMargins(m_CurveEditor.settings.vRangeMin, m_CurveEditor.settings.vRangeMax);\n                frameV = false;\n            }\n\n            m_CurveEditor.FrameSelected(frameH, frameV);\n        }\n\n        void InitCurvePresets()\n        {\n            if (m_CurvePresets == null)\n            {\n                AnimationCurve max = m_CurveEditor.animationCurves[0].curve;\n                AnimationCurve min = m_CurveEditor.animationCurves.Length > 1 ? m_CurveEditor.animationCurves[1].curve : new AnimationCurve();\n\n                // Selection callback for library window\n                System.Action<DoubleCurve> presetSelectedCallback = delegate(DoubleCurve presetCurve)\n                {\n                    var doubleCurve = new DoubleCurve(min, max, true);\n                    doubleCurve.minCurve.keys = CurveEditorWindow.GetNormalizedKeys(presetCurve.minCurve.keys, m_CurveEditor);\n                    doubleCurve.minCurve.postWrapMode = presetCurve.minCurve.postWrapMode;\n                    doubleCurve.minCurve.preWrapMode = presetCurve.minCurve.preWrapMode;\n\n                    doubleCurve.maxCurve.keys = CurveEditorWindow.GetNormalizedKeys(presetCurve.maxCurve.keys, m_CurveEditor);\n                    doubleCurve.maxCurve.postWrapMode = presetCurve.maxCurve.postWrapMode;\n                    doubleCurve.maxCurve.preWrapMode = presetCurve.maxCurve.preWrapMode;\n\n                    m_MinCurve = doubleCurve.minCurve;\n                    m_MaxCurve = doubleCurve.maxCurve;\n\n                    m_CurveEditor.SelectNone();\n                    RefreshShownCurves();\n                    SendEvent(\"CurveChanged\", true);\n                };\n\n                // We set the curve to save when showing the popup to ensure to scale the current state of the curve\n                m_CurvePresets = new DoubleCurvePresetsContentsForPopupWindow(new DoubleCurve(min, max, true), presetSelectedCallback);\n                m_CurvePresets.InitIfNeeded();\n                m_CurvePresets.GetPresetLibraryEditor().GetCurrentLib().useRanges = false;\n            }\n        }\n\n        public static void SetCurves(SerializedProperty max, SerializedProperty min, SerializedProperty multiplier, Color color)\n        {\n            instance.m_Color = color;\n\n            if (max == null)\n                instance.m_MaxCurve = null;\n            else\n                instance.m_MaxCurve = max.hasMultipleDifferentValues ? new AnimationCurve() : max.animationCurveValue;\n\n            if (min == null)\n                instance.m_MinCurve = null;\n            else\n                instance.m_MinCurve = min.hasMultipleDifferentValues ? new AnimationCurve() : min.animationCurveValue;\n\n            instance.m_MultiplierProperty = multiplier;\n            instance.RefreshShownCurves();\n        }\n\n        public static void ShowPopup(GUIView viewToUpdate)\n        {\n            instance.Show(viewToUpdate, null);\n        }\n\n        void SetAxisUiScalarsCallback(Vector2 newAxisScalars)\n        {\n            if (m_MultiplierProperty == null)\n                return;\n\n            m_MultiplierProperty.floatValue = newAxisScalars.y;\n\n            // We must apply the changes as this is called outside of the OnGUI code and changes made will not be applied.\n            m_MultiplierProperty.serializedObject.ApplyModifiedProperties();\n        }\n\n        Vector2 GetAxisUiScalarsCallback()\n        {\n            if (m_MultiplierProperty == null)\n                return Vector2.one;\n\n            if (m_MultiplierProperty.floatValue < 0)\n            {\n                m_MultiplierProperty.floatValue = Mathf.Abs(m_MultiplierProperty.floatValue);\n                m_MultiplierProperty.serializedObject.ApplyModifiedProperties();\n            }\n\n            return new Vector2(1, m_MultiplierProperty.floatValue);\n        }\n\n        CurveWrapper GetCurveWrapper(AnimationCurve curve, int id)\n        {\n            CurveWrapper cw = new CurveWrapper();\n            cw.id = id;\n            cw.groupId = -1;\n            cw.color = m_Color;\n            cw.hidden = false;\n            cw.readOnly = false;\n            cw.getAxisUiScalarsCallback = GetAxisUiScalarsCallback;\n            cw.setAxisUiScalarsCallback = SetAxisUiScalarsCallback;\n            cw.renderer = new NormalCurveRenderer(curve);\n            cw.renderer.SetWrap(curve.preWrapMode, curve.postWrapMode);\n            return cw;\n        }\n\n        CurveWrapper[] GetCurveWrapperArray()\n        {\n            int id = \"Curve\".GetHashCode();\n\n            if (m_MaxCurve != null)\n            {\n                var maxWrapper = GetCurveWrapper(m_MaxCurve, id);\n                if (m_MinCurve != null)\n                {\n                    var minWrapper = GetCurveWrapper(m_MinCurve, id + 1);\n                    minWrapper.regionId = maxWrapper.regionId = 1;\n                    return new[] { maxWrapper, minWrapper };\n                }\n                else\n                {\n                    return new[] { maxWrapper };\n                }\n            }\n\n            return new CurveWrapper[] {};\n        }\n\n        Rect GetCurveEditorRect()\n        {\n            return new Rect(0, 0, position.width, position.height - k_PresetsHeight);\n        }\n\n        void OnEnable()\n        {\n            if (s_SharedMinMaxCurveEditor && s_SharedMinMaxCurveEditor != this)\n                s_SharedMinMaxCurveEditor.Close();\n            s_SharedMinMaxCurveEditor = this;\n            Init(null);\n        }\n\n        void OnDestroy()\n        {\n            m_CurvePresets.GetPresetLibraryEditor().UnloadUsedLibraries();\n        }\n\n        void OnDisable()\n        {\n            m_CurveEditor.OnDisable();\n            if (s_SharedMinMaxCurveEditor == this)\n                s_SharedMinMaxCurveEditor = null;\n        }\n\n        void RefreshShownCurves()\n        {\n            m_CurveEditor.animationCurves = GetCurveWrapperArray();\n            UpdateRegionDomain();\n        }\n\n        void UpdateRegionDomain()\n        {\n            // Calculate region domain for drawing the shaded region between 2 curves.\n            var domain = new Vector2(float.MaxValue, float.MinValue);\n            if (m_MaxCurve != null && m_MinCurve != null)\n            {\n                foreach (var animationCurve in new[] { m_MaxCurve, m_MinCurve })\n                {\n                    var keyCount = animationCurve.length;\n                    if (keyCount > 0)\n                    {\n                        var keys = animationCurve.keys;\n                        domain.x = Mathf.Min(domain.x, animationCurve[0].time);\n                        domain.y = Math.Max(domain.y, animationCurve[keyCount - 1].time);\n                    }\n                }\n            }\n            m_CurveEditor.settings.curveRegionDomain = domain;\n        }\n\n        public void Show(GUIView viewToUpdate, CurveEditorSettings settings)\n        {\n            delegateView = viewToUpdate;\n            Init(settings);\n            ShowAuxWindow();\n            titleContent = EditorGUIUtility.TrTextContent(\"Curve Editor\");\n\n            // deal with window size\n            minSize = new Vector2(k_WindowMinSize, k_WindowMinSize + k_PresetsHeight);\n            maxSize = new Vector2(k_WindowMaxSize, k_WindowMaxSize);\n        }\n\n        void DrawPresetSwatchArea()\n        {\n            GUI.Box(new Rect(0, position.height - k_PresetsHeight, position.width, k_PresetsHeight), \"\", s_Styles.curveSwatchArea);\n            Color curveColor = m_Color;\n            curveColor.a *= 0.6f;\n            float yPos = position.height - k_PresetsHeight + (k_PresetsHeight - k_PresetSwatchHeight) * 0.5f;\n            InitCurvePresets();\n            var curveLibrary = m_CurvePresets.GetPresetLibraryEditor().GetCurrentLib();\n            if (curveLibrary != null)\n            {\n                GUIContent guiContent = EditorGUIUtility.TempContent(string.Empty);\n                for (int i = 0; i < curveLibrary.Count(); i++)\n                {\n                    Rect swatchRect = new Rect(k_PresetSwatchMargin + (k_PresetSwatchWidth + k_PresetSwatchSeperation) * i, yPos, k_PresetSwatchWidth, k_PresetSwatchHeight);\n                    guiContent.tooltip = curveLibrary.GetName(i);\n                    if (GUI.Button(swatchRect, guiContent, s_Styles.curveSwatch))\n                    {\n                        AnimationCurve max = m_CurveEditor.animationCurves[0].curve;\n                        AnimationCurve min = m_CurveEditor.animationCurves.Length > 1 ? m_CurveEditor.animationCurves[1].curve : null;\n                        var animCurve = curveLibrary.GetPreset(i) as DoubleCurve;\n\n                        max.keys = CurveEditorWindow.GetDenormalizedKeys(animCurve.maxCurve.keys, m_CurveEditor);\n                        max.postWrapMode = animCurve.maxCurve.postWrapMode;\n                        max.preWrapMode = animCurve.maxCurve.preWrapMode;\n\n                        if (min != null)\n                        {\n                            min.keys = CurveEditorWindow.GetDenormalizedKeys(animCurve.minCurve.keys, m_CurveEditor);\n                            min.postWrapMode = animCurve.minCurve.postWrapMode;\n                            min.preWrapMode = animCurve.minCurve.preWrapMode;\n                        }\n\n                        m_CurveEditor.SelectNone();\n                        RefreshShownCurves();\n                        SendEvent(\"CurveChanged\", true);\n                    }\n                    if (Event.current.type == EventType.Repaint)\n                        curveLibrary.Draw(swatchRect, i);\n\n                    if (swatchRect.xMax > position.width - 2 * k_PresetSwatchMargin)\n                        break;\n                }\n            }\n\n            // Dropdown\n            Rect presetDropDownButtonRect = new Rect(k_PresetSwatchMargin - k_PresetsDropdownButtonSize, yPos + k_PresetSwatchSeperation, k_PresetsDropdownButtonSize, k_PresetsDropdownButtonSize);\n            if (EditorGUI.DropdownButton(presetDropDownButtonRect, EditorGUI.GUIContents.titleSettingsIcon, FocusType.Passive, EditorStyles.inspectorTitlebarText))\n            {\n                if (m_MaxCurve != null)\n                {\n                    AnimationCurve max = m_CurveEditor.animationCurves[0].curve;\n                    AnimationCurve maxCopy = new AnimationCurve(CurveEditorWindow.GetNormalizedKeys(max.keys, m_CurveEditor));\n                    maxCopy.postWrapMode = max.postWrapMode;\n                    maxCopy.preWrapMode = max.preWrapMode;\n\n                    AnimationCurve minCopy = null;\n                    if (m_MinCurve != null)\n                    {\n                        AnimationCurve min = m_CurveEditor.animationCurves[1].curve;\n                        minCopy = new AnimationCurve(CurveEditorWindow.GetNormalizedKeys(min.keys, m_CurveEditor));\n                        minCopy.postWrapMode = min.postWrapMode;\n                        minCopy.preWrapMode = min.preWrapMode;\n                    }\n\n                    m_CurvePresets.doubleCurveToSave = new DoubleCurve(minCopy, maxCopy, true);\n                    PopupWindow.Show(presetDropDownButtonRect, m_CurvePresets);\n                }\n            }\n        }\n\n        void OnGUI()\n        {\n            bool gotMouseUp = (Event.current.type == EventType.MouseUp);\n\n            if (delegateView == null)\n            {\n                m_MinCurve = null;\n                m_MaxCurve = null;\n            }\n\n            if (s_Styles == null)\n                s_Styles = new CurveEditorWindow.Styles();\n\n            // Curve Editor\n            m_CurveEditor.rect = GetCurveEditorRect();\n            m_CurveEditor.hRangeLocked = Event.current.shift;\n            m_CurveEditor.vRangeLocked = EditorGUI.actionKey;\n\n            GUI.changed = false;\n\n            GUI.Label(m_CurveEditor.drawRect, GUIContent.none, s_Styles.curveEditorBackground);\n            m_CurveEditor.OnGUI();\n\n            DrawPresetSwatchArea();\n\n            if (Event.current.type == EventType.Used && gotMouseUp)\n            {\n                DoUpdateCurve(false);\n                SendEvent(\"CurveChangeCompleted\", true);\n            }\n            else if (Event.current.type != EventType.Layout && Event.current.type != EventType.Repaint)\n            {\n                DoUpdateCurve(true);\n            }\n        }\n\n        public void UpdateCurve()\n        {\n            DoUpdateCurve(false);\n        }\n\n        void DoUpdateCurve(bool exitGUI)\n        {\n            bool minChanged = m_CurveEditor.animationCurves.Length > 0 && m_CurveEditor.animationCurves[0] != null && m_CurveEditor.animationCurves[0].changed;\n            bool maxChanged = m_CurveEditor.animationCurves.Length > 1 && m_CurveEditor.animationCurves[1] != null && m_CurveEditor.animationCurves[1].changed;\n\n            if (minChanged || maxChanged)\n            {\n                if (minChanged)\n                    m_CurveEditor.animationCurves[0].changed = false;\n\n                if (maxChanged)\n                    m_CurveEditor.animationCurves[1].changed = false;\n\n                RefreshShownCurves();\n                SendEvent(\"CurveChanged\", exitGUI);\n            }\n        }\n\n        void SendEvent(string eventName, bool exitGUI)\n        {\n            if (delegateView)\n            {\n                Event e = EditorGUIUtility.CommandEvent(eventName);\n                Repaint();\n                delegateView.SendEvent(e);\n                if (exitGUI)\n                    GUIUtility.ExitGUI();\n            }\n            GUI.changed = true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/RectangleTool.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditor\n{\n    internal class RectangleTool\n    {\n        private TimeArea m_TimeArea;\n        private Styles m_Styles;\n\n        internal enum ToolCoord\n        {\n            BottomLeft,\n            Bottom,\n            BottomRight,\n\n            Left,\n            Center,\n            Right,\n\n            TopLeft,\n            Top,\n            TopRight\n        }\n\n        internal class Styles\n        {\n            public GUIStyle rectangleToolHBarLeft = \"RectangleToolHBarLeft\";\n            public GUIStyle rectangleToolHBarRight = \"RectangleToolHBarRight\";\n            public GUIStyle rectangleToolHBar = \"RectangleToolHBar\";\n\n            public GUIStyle rectangleToolVBarBottom = \"RectangleToolVBarBottom\";\n            public GUIStyle rectangleToolVBarTop = \"RectangleToolVBarTop\";\n            public GUIStyle rectangleToolVBar = \"RectangleToolVBar\";\n\n            public GUIStyle rectangleToolSelection = \"RectangleToolSelection\";\n            public GUIStyle rectangleToolHighlight = \"RectangleToolHighlight\";\n\n            public GUIStyle rectangleToolScaleLeft = \"RectangleToolScaleLeft\";\n            public GUIStyle rectangleToolScaleRight = \"RectangleToolScaleRight\";\n            public GUIStyle rectangleToolScaleBottom = \"RectangleToolScaleBottom\";\n            public GUIStyle rectangleToolScaleTop = \"RectangleToolScaleTop\";\n\n            public GUIStyle rectangleToolRippleLeft = \"RectangleToolRippleLeft\";\n            public GUIStyle rectangleToolRippleRight = \"RectangleToolRippleRight\";\n\n            public GUIStyle dopesheetScaleLeft = \"DopesheetScaleLeft\";\n            public GUIStyle dopesheetScaleRight = \"DopesheetScaleRight\";\n\n            public GUIStyle dopesheetRippleLeft = \"DopesheetRippleLeft\";\n            public GUIStyle dopesheetRippleRight = \"DopesheetRippleRight\";\n\n            public GUIStyle dragLabel = \"ProfilerBadge\";\n        }\n\n        public TimeArea timeArea { get { return m_TimeArea; } }\n\n        public Styles styles { get { return m_Styles; } }\n\n        public Rect contentRect\n        {\n            get\n            {\n                return new Rect(0, 0, m_TimeArea.drawRect.width, m_TimeArea.drawRect.height);\n            }\n        }\n\n        public virtual void Initialize(TimeArea timeArea)\n        {\n            m_TimeArea = timeArea;\n\n            if (m_Styles == null)\n                m_Styles = new Styles();\n        }\n\n        public Vector2 ToolCoordToPosition(ToolCoord coord, Bounds bounds)\n        {\n            switch (coord)\n            {\n                case ToolCoord.BottomLeft:\n                    return bounds.min;\n                case ToolCoord.Bottom:\n                    return new Vector2(bounds.center.x, bounds.min.y);\n                case ToolCoord.BottomRight:\n                    return new Vector2(bounds.max.x, bounds.min.y);\n\n                case ToolCoord.Left:\n                    return new Vector2(bounds.min.x, bounds.center.y);\n                case ToolCoord.Center:\n                    return bounds.center;\n                case ToolCoord.Right:\n                    return new Vector2(bounds.max.x, bounds.center.y);\n\n                case ToolCoord.TopLeft:\n                    return new Vector2(bounds.min.x, bounds.max.y);\n                case ToolCoord.Top:\n                    return new Vector2(bounds.center.x, bounds.max.y);\n                case ToolCoord.TopRight:\n                    return bounds.max;\n            }\n\n            return Vector2.zero;\n        }\n\n        public bool CalculateScaleTimeMatrix(float fromTime, float toTime, float offsetTime, float pivotTime, float frameRate, out Matrix4x4 transform, out bool flipKeys)\n        {\n            transform = Matrix4x4.identity;\n            flipKeys = false;\n\n            float thresholdTime = (Mathf.Approximately(frameRate, 0f)) ? 0.001f : 1f / frameRate;\n\n            float dtNum = toTime - pivotTime;\n            float dtDenum = fromTime - pivotTime;\n\n            // Scale handle overlaps pivot, discard operation.\n            if ((Mathf.Abs(dtNum) - Mathf.Abs(offsetTime)) < 0f)\n                return false;\n\n            dtNum = (Mathf.Sign(dtNum) == Mathf.Sign(dtDenum)) ? dtNum - offsetTime : dtNum + offsetTime;\n\n            if (Mathf.Approximately(dtDenum, 0f))\n            {\n                transform.SetTRS(new Vector3(dtNum, 0f, 0f), Quaternion.identity, Vector3.one);\n                flipKeys = false;\n\n                return true;\n            }\n\n            if (Mathf.Abs(dtNum) < thresholdTime)\n                dtNum = (dtNum < 0f) ? -thresholdTime : thresholdTime;\n\n            float scaleTime = dtNum / dtDenum;\n\n            transform.SetTRS(new Vector3(pivotTime, 0f, 0f), Quaternion.identity, Vector3.one);\n            transform = transform * Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(scaleTime, 1f, 1f));\n            transform = transform * Matrix4x4.TRS(new Vector3(-pivotTime, 0f), Quaternion.identity, Vector3.one);\n\n            flipKeys = scaleTime < 0f;\n\n            return true;\n        }\n\n        public bool CalculateScaleValueMatrix(float fromValue, float toValue, float offsetValue, float pivotValue, out Matrix4x4 transform, out bool flipKeys)\n        {\n            transform = Matrix4x4.identity;\n            flipKeys = false;\n\n            float thresholdValue = 0.001f;\n\n            float dvNum = toValue - pivotValue;\n            float dvDenum = fromValue - pivotValue;\n\n            // Scale handle overlaps pivot, discard operation.\n            if ((Mathf.Abs(dvNum) - Mathf.Abs(offsetValue)) < 0f)\n                return false;\n\n            dvNum = (Mathf.Sign(dvNum) == Mathf.Sign(dvDenum)) ? dvNum - offsetValue : dvNum + offsetValue;\n\n            if (Mathf.Approximately(dvDenum, 0f))\n            {\n                transform.SetTRS(new Vector3(0f, dvNum, 0f), Quaternion.identity, Vector3.one);\n                flipKeys = false;\n\n                return true;\n            }\n\n            if (Mathf.Abs(dvNum) < thresholdValue)\n                dvNum = (dvNum < 0f) ? -thresholdValue : thresholdValue;\n\n            float scaleValue = dvNum / dvDenum;\n\n            transform.SetTRS(new Vector3(0f, pivotValue, 0f), Quaternion.identity, Vector3.one);\n            transform = transform * Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1f, scaleValue, 1f));\n            transform = transform * Matrix4x4.TRS(new Vector3(0f, -pivotValue, 0f), Quaternion.identity, Vector3.one);\n\n            flipKeys = scaleValue < 0f;\n\n            return true;\n        }\n\n        public float PixelToTime(float pixelTime, float frameRate)\n        {\n            float width = contentRect.width;\n            float visibleTimeSpan = m_TimeArea.shownArea.xMax - m_TimeArea.shownArea.xMin;\n            float minVisibleTime = m_TimeArea.shownArea.xMin;\n\n            float time = ((pixelTime / width) * visibleTimeSpan + minVisibleTime);\n            if (frameRate != 0f)\n                time = Mathf.Round(time * frameRate) / frameRate;\n\n            return time;\n        }\n\n        public float PixelToValue(float pixelValue)\n        {\n            float height = contentRect.height;\n\n            float pixelPerValue = m_TimeArea.m_Scale.y * -1f;\n            float zeroValuePixel = m_TimeArea.shownArea.yMin * pixelPerValue * -1f;\n\n            float value = (height - pixelValue - zeroValuePixel) / pixelPerValue;\n\n            return value;\n        }\n\n        public float TimeToPixel(float time)\n        {\n            float width = contentRect.width;\n            float visibleTimeSpan = m_TimeArea.shownArea.xMax - m_TimeArea.shownArea.xMin;\n            float minVisibleTime = m_TimeArea.shownArea.xMin;\n\n            float pixelTime = (time - minVisibleTime) * width / visibleTimeSpan;\n\n            return pixelTime;\n        }\n\n        public float ValueToPixel(float value)\n        {\n            float height = contentRect.height;\n\n            float pixelPerValue = m_TimeArea.m_Scale.y * -1f;\n            float zeroValuePixel = m_TimeArea.shownArea.yMin * pixelPerValue * -1f;\n\n            float pixelValue = height - (value * pixelPerValue + zeroValuePixel);\n\n            return pixelValue;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimationWindow/RotationCurveInterpolation.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class RotationCurveInterpolation\n    {\n        public struct State\n        {\n            public bool allAreNonBaked;\n            public bool allAreBaked;\n            public bool allAreRaw;\n            public bool allAreRotations;\n        }\n\n        public static char[] kPostFix = { 'x', 'y', 'z', 'w' };\n\n        public enum Mode { Baked, NonBaked, RawQuaternions, RawEuler, Undefined }\n\n        public static Mode GetModeFromCurveData(EditorCurveBinding data)\n        {\n            if (AnimationWindowUtility.IsTransformType(data.type) && data.propertyName.StartsWith(\"localEulerAngles\"))\n            {\n                if (data.propertyName.StartsWith(\"localEulerAnglesBaked\"))\n                    return Mode.Baked;\n                else if (data.propertyName.StartsWith(\"localEulerAnglesRaw\"))\n                    return Mode.RawEuler;\n                else\n                    return Mode.NonBaked;\n            }\n            else if (AnimationWindowUtility.IsTransformType(data.type) && data.propertyName.StartsWith(\"m_LocalRotation\"))\n                return Mode.RawQuaternions;\n\n            return Mode.Undefined;\n        }\n\n        // Extracts the interpolation state for the selection from the clip\n        public static State GetCurveState(AnimationClip clip, EditorCurveBinding[] selection)\n        {\n            State state;\n            state.allAreRaw = true;\n            state.allAreNonBaked = true;\n            state.allAreBaked = true;\n            state.allAreRotations = true;\n\n            foreach (EditorCurveBinding data in selection)\n            {\n                Mode mode = GetModeFromCurveData(data);\n                state.allAreBaked &= (mode == Mode.Baked);\n                state.allAreNonBaked &= (mode == Mode.NonBaked);\n                state.allAreRaw &= mode == (Mode.RawEuler);\n                state.allAreRotations &= mode != (Mode.Undefined);\n            }\n\n            return state;\n        }\n\n        public static char ExtractComponentCharacter(string name)\n        {\n            return name[name.Length - 1];\n        }\n\n        public static string GetPrefixForInterpolation(Mode newInterpolationMode)\n        {\n            if (newInterpolationMode == Mode.Baked)\n                return \"localEulerAnglesBaked\";\n            else if (newInterpolationMode == Mode.NonBaked)\n                return \"localEulerAngles\";\n            else if (newInterpolationMode == Mode.RawEuler)\n                return \"localEulerAnglesRaw\";\n            else if (newInterpolationMode == Mode.RawQuaternions)\n                return \"m_LocalRotation\";\n            else\n                return null;\n        }\n\n        internal static EditorCurveBinding[] ConvertRotationPropertiesToDefaultInterpolation(AnimationClip clip, EditorCurveBinding[] selection)\n        {\n            var mode = clip.legacy ? Mode.Baked : Mode.RawEuler;\n            return ConvertRotationPropertiesToInterpolationType(selection, mode);\n        }\n\n        internal static EditorCurveBinding[] ConvertRotationPropertiesToInterpolationType(EditorCurveBinding[] selection, Mode newInterpolationMode)\n        {\n            if (selection.Length != 4)\n                return selection;\n\n            if (GetModeFromCurveData(selection[0]) == Mode.RawQuaternions)\n            {\n                EditorCurveBinding[] newCurves = new EditorCurveBinding[3];\n                newCurves[0] = selection[0];\n                newCurves[1] = selection[1];\n                newCurves[2] = selection[2];\n\n                string prefix = GetPrefixForInterpolation(newInterpolationMode);\n                newCurves[0].propertyName = prefix + \".x\";\n                newCurves[1].propertyName = prefix + \".y\";\n                newCurves[2].propertyName = prefix + \".z\";\n\n                return newCurves;\n            }\n            else\n                return selection;\n        }\n\n        static EditorCurveBinding[] GenerateTransformCurveBindingArray(string path, string property, Type type, int count)\n        {\n            EditorCurveBinding[] bindings = new EditorCurveBinding[count];\n            for (int i = 0; i < count; i++)\n                bindings[i] = EditorCurveBinding.FloatCurve(path, type, property + kPostFix[i]);\n            return bindings;\n        }\n\n        static public EditorCurveBinding[] RemapAnimationBindingForAddKey(EditorCurveBinding binding, AnimationClip clip)\n        {\n            if (!AnimationWindowUtility.IsTransformType(binding.type))\n            {\n                return null;\n            }\n            else if (binding.propertyName.StartsWith(\"m_LocalPosition.\"))\n            {\n                if (binding.type == typeof(Transform))\n                    return GenerateTransformCurveBindingArray(binding.path, \"m_LocalPosition.\", binding.type, 3);\n                else\n                    return null;\n            }\n            else if (binding.propertyName.StartsWith(\"m_LocalScale.\"))\n                return GenerateTransformCurveBindingArray(binding.path, \"m_LocalScale.\", binding.type, 3);\n            else if (binding.propertyName.StartsWith(\"m_LocalRotation\"))\n            {\n                return SelectRotationBindingForAddKey(binding, clip);\n            }\n            else\n                return null;\n        }\n\n        static public EditorCurveBinding[] RemapAnimationBindingForRotationAddKey(EditorCurveBinding binding, AnimationClip clip)\n        {\n            if (!AnimationWindowUtility.IsTransformType(binding.type))\n            {\n                return null;\n            }\n            else if (binding.propertyName.StartsWith(\"m_LocalRotation\"))\n            {\n                return SelectRotationBindingForAddKey(binding, clip);\n            }\n            else\n                return null;\n        }\n\n        static private EditorCurveBinding[] SelectRotationBindingForAddKey(EditorCurveBinding binding, AnimationClip clip)\n        {\n            EditorCurveBinding testBinding = binding;\n            testBinding.propertyName = \"localEulerAnglesBaked.x\";\n            if (AnimationUtility.GetEditorCurve(clip, testBinding) != null)\n                return GenerateTransformCurveBindingArray(binding.path, \"localEulerAnglesBaked.\", binding.type, 3);\n            else\n            {\n                testBinding.propertyName = \"localEulerAngles.x\";\n                if (AnimationUtility.GetEditorCurve(clip, testBinding) != null)\n                {\n                    return GenerateTransformCurveBindingArray(binding.path, \"localEulerAngles.\", binding.type, 3);\n                }\n                else\n                {\n                    testBinding.propertyName = \"localEulerAnglesRaw.x\";\n                    if (clip.legacy && AnimationUtility.GetEditorCurve(clip, testBinding) == null)\n                        return GenerateTransformCurveBindingArray(binding.path, \"localEulerAnglesBaked.\", binding.type, 3);\n\n                    return GenerateTransformCurveBindingArray(binding.path, \"localEulerAnglesRaw.\", binding.type, 3);\n                }\n            }\n        }\n\n        static public EditorCurveBinding RemapAnimationBindingForRotationCurves(EditorCurveBinding curveBinding, AnimationClip clip)\n        {\n            if (!AnimationWindowUtility.IsTransformType(curveBinding.type))\n                return curveBinding;\n\n            // Convert rotation binding to valid editor curve binding.\n            // Only a single rotation binding (RawEuler, Baked or NonBaked) should be allowed in one clip.\n            // RawQuaternions should be converted to appropriate euler bindings if available.\n            Mode mode = GetModeFromCurveData(curveBinding);\n            if (mode != Mode.Undefined)\n            {\n                string suffix = curveBinding.propertyName.Split('.')[1];\n\n                EditorCurveBinding newBinding = curveBinding;\n\n                if (mode != Mode.NonBaked)\n                {\n                    newBinding.propertyName = GetPrefixForInterpolation(Mode.NonBaked) + \".\" + suffix;\n                    AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, newBinding);\n                    if (curve != null)\n                        return newBinding;\n                }\n\n                if (mode != Mode.Baked)\n                {\n                    newBinding.propertyName = GetPrefixForInterpolation(Mode.Baked) + \".\" + suffix;\n                    AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, newBinding);\n                    if (curve != null)\n                        return newBinding;\n                }\n\n                if (mode != Mode.RawEuler)\n                {\n                    newBinding.propertyName = GetPrefixForInterpolation(Mode.RawEuler) + \".\" + suffix;\n                    AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, newBinding);\n                    if (curve != null)\n                        return newBinding;\n                }\n\n                return curveBinding;\n            }\n            else\n                return curveBinding;\n        }\n\n        internal static void SetInterpolation(AnimationClip clip, EditorCurveBinding[] curveBindings, Mode newInterpolationMode)\n        {\n            Undo.RegisterCompleteObjectUndo(clip, L10n.Tr(\"Rotation Interpolation\"));\n\n            if (clip.legacy && newInterpolationMode == Mode.RawEuler)\n            {\n                Debug.LogWarning(\"Warning, Euler Angles interpolation mode is not fully supported for Legacy animation clips. If you mix clips using Euler Angles interpolation with clips using other interpolation modes (using Animation.CrossFade, Animation.Blend or other methods), you will get erroneous results. Use with caution.\", clip);\n            }\n            List<EditorCurveBinding> newCurvesBindings = new List<EditorCurveBinding>();\n            List<AnimationCurve> newCurveDatas = new List<AnimationCurve>();\n            List<EditorCurveBinding> oldCurvesBindings = new List<EditorCurveBinding>();\n\n            foreach (EditorCurveBinding curveBinding in curveBindings)\n            {\n                Mode currentMode = GetModeFromCurveData(curveBinding);\n\n                if (currentMode == Mode.Undefined)\n                    continue;\n\n                if (currentMode == Mode.RawQuaternions)\n                {\n                    Debug.LogWarning(\"Can't convert quaternion curve: \" + curveBinding.propertyName);\n                    continue;\n                }\n\n                AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, curveBinding);\n\n                if (curve == null)\n                    continue;\n\n                string newPropertyPath = GetPrefixForInterpolation(newInterpolationMode) + '.' + ExtractComponentCharacter(curveBinding.propertyName);\n\n                EditorCurveBinding newBinding = new EditorCurveBinding();\n                newBinding.propertyName = newPropertyPath;\n                newBinding.type = curveBinding.type;\n                newBinding.path = curveBinding.path;\n                newCurvesBindings.Add(newBinding);\n                newCurveDatas.Add(curve);\n\n                EditorCurveBinding removeCurve = new EditorCurveBinding();\n                removeCurve.propertyName = curveBinding.propertyName;\n                removeCurve.type = curveBinding.type;\n                removeCurve.path = curveBinding.path;\n                oldCurvesBindings.Add(removeCurve);\n            }\n\n            Undo.RegisterCompleteObjectUndo(clip, L10n.Tr(\"Rotation Interpolation\"));\n\n            foreach (EditorCurveBinding binding in oldCurvesBindings)\n                AnimationUtility.SetEditorCurve(clip, binding, null);\n\n            foreach (EditorCurveBinding binding in newCurvesBindings)\n                AnimationUtility.SetEditorCurve(clip, binding, newCurveDatas[newCurvesBindings.IndexOf(binding)]);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/AnimatorController.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.IO;\nusing System.Collections.Generic;\nusing RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute;\n\nnamespace UnityEditor.Animations\n{\n    [NativeClass(null)]\n    public sealed partial class AnimatorController : RuntimeAnimatorController\n    {\n        internal System.Action OnAnimatorControllerDirty;\n\n        internal static AnimatorController lastActiveController = null;\n        internal  static int lastActiveLayerIndex = 0;\n        private const string kControllerExtension = \"controller\";\n\n        internal PushUndoIfNeeded undoHandler = new PushUndoIfNeeded(true);\n        internal bool pushUndo { set { undoHandler.pushUndo = value; } }\n\n        internal string GetDefaultBlendTreeParameter()\n        {\n            for (int i = 0; i < parameters.Length; i++)\n            {\n                if (parameters[i].type == AnimatorControllerParameterType.Float)\n                    return parameters[i].name;\n            }\n            AddParameter(\"Blend\", AnimatorControllerParameterType.Float);\n            return \"Blend\";\n        }\n\n        [RequiredByNativeCode]\n        internal static void OnInvalidateAnimatorController(AnimatorController controller)\n        {\n            if (controller.OnAnimatorControllerDirty != null)\n                controller.OnAnimatorControllerDirty();\n        }\n\n        internal AnimatorStateMachine FindEffectiveRootStateMachine(int layerIndex)\n        {\n            AnimatorControllerLayer currentLayer = layers[layerIndex];\n            while (currentLayer.syncedLayerIndex != -1)\n            {\n                currentLayer = layers[currentLayer.syncedLayerIndex];\n            }\n            return currentLayer.stateMachine;\n        }\n\n        public void AddLayer(string name)\n        {\n            AnimatorControllerLayer newLayer = new AnimatorControllerLayer();\n            newLayer.name = MakeUniqueLayerName(name);\n            newLayer.stateMachine = new AnimatorStateMachine();\n            newLayer.stateMachine.name = newLayer.name;\n            newLayer.stateMachine.hideFlags = HideFlags.HideInHierarchy;\n\n            if (AssetDatabase.GetAssetPath(this) != \"\")\n                AssetDatabase.AddObjectToAsset(newLayer.stateMachine, AssetDatabase.GetAssetPath(this));\n\n            undoHandler.DoUndoCreated(newLayer.stateMachine, \"Layer added\");\n\n            AddLayer(newLayer);\n        }\n\n        public void AddLayer(AnimatorControllerLayer layer)\n        {\n            undoHandler.DoUndo(this, \"Layer added\");\n\n            AnimatorControllerLayer[] layerVector = layers;\n            ArrayUtility.Add(ref layerVector, layer);\n            layers = layerVector;\n        }\n\n        internal void RemoveLayers(List<int> layerIndexes)\n        {\n            undoHandler.DoUndo(this, \"Layers removed\");\n\n            AnimatorControllerLayer[] layerVector = this.layers;\n            foreach (var layerIndex in layerIndexes)\n            {\n                for (var i = 0; i < layerVector.Length; ++i)\n                {\n                    var syncedLayerIndex = layerVector[i].syncedLayerIndex;\n                    if (syncedLayerIndex > layerIndex)\n                    {\n                        // synced layer is after the layer being removed, so it's going to be shifted upon removal\n                        layerVector[i].syncedLayerIndex = syncedLayerIndex - 1;\n                    }\n                }\n\n                RemoveLayerInternal(layerIndex, ref layerVector);\n            }\n            this.layers = layerVector;\n        }\n\n        private void RemoveLayerInternal(int index, ref AnimatorControllerLayer[] layerVector)\n        {\n            if (layerVector[index].syncedLayerIndex == -1 && layerVector[index].stateMachine != null)\n            {\n                undoHandler.DoUndo(layerVector[index].stateMachine, \"Layer removed\");\n                layerVector[index].stateMachine.Clear();\n                if (MecanimUtilities.AreSameAsset(this, layerVector[index].stateMachine))\n                    Undo.DestroyObjectImmediate(layerVector[index].stateMachine);\n            }\n\n            ArrayUtility.Remove(ref layerVector, layerVector[index]);\n        }\n\n        public void RemoveLayer(int index)\n        {\n            undoHandler.DoUndo(this, \"Layer removed\");\n\n            AnimatorControllerLayer[] layerVector = layers;\n            RemoveLayerInternal(index, ref layerVector);\n            layers = layerVector;\n        }\n\n        internal bool IsStateInLayer(AnimatorState state, int layerIndex)\n        {\n            if (layerIndex >= layers.Length)\n            {\n                return false;\n            }\n\n            return layers[layerIndex].stateMachine.HasState(state);\n        }\n\n        internal int GetStateLayer(AnimatorState state)\n        {\n            for (int i = 0; i < layers.Length; ++i)\n            {\n                if (layers[i].stateMachine.HasState(state))\n                {\n                    return i;\n                }\n            }\n\n            return -1;\n        }\n\n        public void AddParameter(string name, AnimatorControllerParameterType type)\n        {\n            AnimatorControllerParameter newParameter = new AnimatorControllerParameter();\n            newParameter.name = MakeUniqueParameterName(name);\n            newParameter.type = type;\n\n            AddParameter(newParameter);\n        }\n\n        public void AddParameter(AnimatorControllerParameter paramater)\n        {\n            undoHandler.DoUndo(this, \"Parameter added\");\n            AnimatorControllerParameter[] parameterVector = parameters;\n            ArrayUtility.Add(ref parameterVector, paramater);\n            parameters = parameterVector;\n        }\n\n        public void RemoveParameter(int index)\n        {\n            undoHandler.DoUndo(this, \"Parameter removed\");\n            AnimatorControllerParameter[] parameterVector = parameters;\n            ArrayUtility.Remove(ref parameterVector, parameterVector[index]);\n            parameters = parameterVector;\n        }\n\n        public void RemoveParameter(AnimatorControllerParameter parameter)\n        {\n            undoHandler.DoUndo(this, \"Parameter removed\");\n            AnimatorControllerParameter[] parameterVector = parameters;\n            ArrayUtility.Remove(ref parameterVector, parameter);\n            parameters = parameterVector;\n        }\n\n        // We cannot call AddMotion from native code, because there are multiple signatures of that method, creating ambiguity.\n        [RequiredByNativeCode]\n        private AnimatorState AddMotionInternal(Motion motion)\n        {\n            return AddMotion(motion);\n        }\n\n        public AnimatorState AddMotion(Motion motion)\n        {\n            return AddMotion(motion, 0);\n        }\n\n        public AnimatorState AddMotion(Motion motion, int layerIndex)\n        {\n            AnimatorState state = layers[layerIndex].stateMachine.AddState(motion.name);\n            state.motion = motion;\n            return state;\n        }\n\n        public AnimatorState CreateBlendTreeInController(string name, out BlendTree tree)\n        {\n            return CreateBlendTreeInController(name, out tree, 0);\n        }\n\n        public AnimatorState CreateBlendTreeInController(string name, out BlendTree tree, int layerIndex)\n        {\n            tree = new BlendTree();\n            tree.name = name;\n            tree.blendParameter = tree.blendParameterY = GetDefaultBlendTreeParameter();\n\n            if (AssetDatabase.GetAssetPath(this) != \"\")\n                AssetDatabase.AddObjectToAsset(tree, AssetDatabase.GetAssetPath(this));\n\n            undoHandler.DoUndoCreated(tree, \"Blend Tree Created\");\n\n            AnimatorState state = layers[layerIndex].stateMachine.AddState(tree.name);\n            state.motion = tree;\n            return state;\n        }\n\n        public static AnimatorController CreateAnimatorControllerAtPath(string path)\n        {\n            AnimatorController controller = new AnimatorController();\n\n            controller.name = Path.GetFileName(path);\n            AssetDatabase.CreateAsset(controller, path);\n\n            controller.pushUndo = false;\n            controller.AddLayer(\"Base Layer\");\n            controller.pushUndo = true;\n\n            return controller;\n        }\n\n        public static AnimationClip AllocateAnimatorClip(string name)\n        {\n            var clip = UnityEditorInternal.AnimationWindowUtility.AllocateAndSetupClip(true);\n            clip.name = name;\n            return clip;\n        }\n\n        [RequiredByNativeCode]\n        internal static AnimatorController CreateAnimatorControllerForClip(AnimationClip clip, GameObject animatedObject)\n        {\n            string path = AssetDatabase.GetAssetPath(clip);\n\n            if (string.IsNullOrEmpty(path))\n                return null;\n\n            string name = System.Text.RegularExpressions.Regex.Replace(animatedObject.name, @\"[\\\\\\./]\", \"_\");\n\n            path = Path.Combine(FileUtil.DeleteLastPathNameComponent(path), name + \".\" + kControllerExtension);\n            path = AssetDatabase.GenerateUniqueAssetPath(path);\n\n            if (string.IsNullOrEmpty(path))\n                return null;\n\n\n            return CreateAnimatorControllerAtPathWithClip(path, clip);\n        }\n\n        public static AnimatorController CreateAnimatorControllerAtPathWithClip(string path, AnimationClip clip)\n        {\n            AnimatorController controller = CreateAnimatorControllerAtPath(path);\n\n            AnimatorStateMachine stateMachine = controller.layers[0].stateMachine;\n            stateMachine.pushUndo = false;\n            var state = stateMachine.AddState(clip.name);\n            state.motion = clip;\n            stateMachine.pushUndo = true;\n\n            return controller;\n        }\n\n        public void SetStateEffectiveMotion(AnimatorState state, Motion motion)\n        {\n            SetStateEffectiveMotion(state, motion, 0);\n        }\n\n        public void SetStateEffectiveMotion(AnimatorState state, Motion motion, int layerIndex)\n        {\n            //delete existing nested blend tree asset\n            Motion selectedMotion = GetStateEffectiveMotion(state, layerIndex);\n            BlendTree blendTree = selectedMotion as BlendTree;\n\n            if (blendTree != null && !AssetDatabase.IsMainAsset(blendTree))\n            {\n                MecanimUtilities.DestroyBlendTreeRecursive(blendTree);\n            }\n\n            if (layers[layerIndex].syncedLayerIndex == -1)\n            {\n                undoHandler.DoUndo(state, \"Set Motion\");\n                state.motion = motion;\n            }\n            else\n            {\n                undoHandler.DoUndo(this, \"Set Motion\");\n                AnimatorControllerLayer[] layerArray = layers;\n                layerArray[layerIndex].SetOverrideMotion(state, motion);\n                layers = layerArray;\n            }\n        }\n\n        public Motion GetStateEffectiveMotion(AnimatorState state)\n        {\n            return GetStateEffectiveMotion(state, 0);\n        }\n\n        public Motion GetStateEffectiveMotion(AnimatorState state, int layerIndex)\n        {\n            if (layerIndex < 0 || layerIndex > layers.Length)\n                return null;\n\n            return layers[layerIndex].syncedLayerIndex == -1 ? state.motion : layers[layerIndex].GetOverrideMotion(state);\n        }\n\n        public void SetStateEffectiveBehaviours(AnimatorState state, int layerIndex, StateMachineBehaviour[] behaviours)\n        {\n            if (layers[layerIndex].syncedLayerIndex == -1)\n            {\n                undoHandler.DoUndo(state, \"Set Behaviours\");\n                state.behaviours = behaviours;\n            }\n            else\n            {\n                undoHandler.DoUndo(this, \"Set Behaviours\");\n                Internal_SetEffectiveBehaviours(state, layerIndex, behaviours);\n            }\n        }\n\n        public StateMachineBehaviour[] GetStateEffectiveBehaviours(AnimatorState state, int layerIndex)\n        {\n            if (layerIndex < 0 || layerIndex > layers.Length)\n                return Array.Empty<StateMachineBehaviour>();\n\n            return Internal_GetEffectiveBehaviours(state, layerIndex) as StateMachineBehaviour[];\n        }\n\n        [System.Obsolete(\"parameterCount is obsolete. Use parameters.Length instead.\", true)]\n        int parameterCount\n        {\n            get { return 0; }\n        }\n\n        [System.Obsolete(\"layerCount is obsolete. Use layers.Length instead.\", true)]\n        int layerCount\n        {\n            get { return 0; }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/BlendTree.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditor;\nusing UnityEditor.Animations;\nusing System.Linq;\n\nnamespace UnityEditor.Animations\n{\n    [ExcludeFromPreset]\n    public partial class BlendTree : Motion\n    {\n        public void AddChild(Motion motion)\n        {\n            AddChild(motion, Vector2.zero, 0);\n        }\n\n        public void AddChild(Motion motion, Vector2 position)\n        {\n            AddChild(motion, position, 0);\n        }\n\n        public void AddChild(Motion motion, float threshold)\n        {\n            AddChild(motion, Vector2.zero, threshold);\n        }\n\n        public void RemoveChild(int index)\n        {\n            Undo.RecordObject(this, \"Remove Child\");\n            ChildMotion[] childMotions = children;\n            ArrayUtility.RemoveAt(ref childMotions, index);\n            children = childMotions;\n        }\n\n        internal void AddChild(Motion motion, Vector2 position, float threshold)\n        {\n            Undo.RecordObject(this, \"Added BlendTree Child\");\n            ChildMotion[] childMotions = children;\n            ChildMotion newMotion = new ChildMotion();\n            newMotion.timeScale = 1;\n            newMotion.motion = motion;\n            newMotion.position = position;\n            newMotion.threshold = threshold;\n            newMotion.directBlendParameter = \"Blend\";\n            ArrayUtility.Add(ref childMotions, newMotion);\n            children = childMotions;\n        }\n\n        public BlendTree CreateBlendTreeChild(float threshold)\n        {\n            return CreateBlendTreeChild(Vector2.zero, threshold);\n        }\n\n        public BlendTree CreateBlendTreeChild(Vector2 position)\n        {\n            return CreateBlendTreeChild(position, 0);\n        }\n\n        internal bool HasChild(BlendTree childTree, bool recursive)\n        {\n            foreach (ChildMotion child in children)\n            {\n                if (child.motion == childTree)\n                {\n                    return true;\n                }\n\n                if (recursive && child.motion is BlendTree && (child.motion as BlendTree).HasChild(childTree, true))\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        internal BlendTree CreateBlendTreeChild(Vector2 position, float threshold)\n        {\n            BlendTree tree = new BlendTree();\n            tree.name = \"BlendTree\";\n            tree.hideFlags = HideFlags.HideInHierarchy;\n            if (AssetDatabase.GetAssetPath(this) != \"\")\n                AssetDatabase.AddObjectToAsset(tree, AssetDatabase.GetAssetPath(this));\n\n            Undo.RegisterCreatedObjectUndo(tree, \"Blend Tree Created\");\n\n            Undo.RecordObject(this, \"Created BlendTree Child\");\n\n            AddChild(tree, position, threshold);\n            return tree;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/EditorCurveBinding.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEngine.Playables;\nusing UnityEngine.Scripting.APIUpdating;\nusing UnityEngine.Internal;\nusing UnityEngine;\nusing static UnityEditor.AnimationUtility;\n\nnamespace UnityEditor\n{\n    [NativeType(CodegenOptions.Custom, \"MonoEditorCurveBinding\")]\n    public struct EditorCurveBinding : IEquatable<EditorCurveBinding>\n    {\n        // The path of the game object / bone being animated.\n        public string path;\n\n        // The type of the component / material being animated.\n        private Type   m_type;\n\n        // The name of the property being animated.\n        public string propertyName;\n\n        // is it a PPtr curve\n        private int   m_isPPtrCurve;\n\n        //is it a discrete curve\n        private int   m_isDiscreteCurve;\n\n        //is it a serialize reference curve\n        private int  m_isSerializeReferenceCurve;\n\n        //is it placeholder curve\n        private int   m_isPhantom;\n\n        //is it a unknown curve: mean it needs to be processed further more to find out what is this curve\n        // This is necessary to support old user code using FloatCurve for non float type\n        private int  m_isUnknownCurve;\n\n        // This is only used internally for deleting curves\n        internal int  m_ClassID;\n        internal int  m_ScriptInstanceID;\n\n        public bool  isPPtrCurve { get { return m_isPPtrCurve != 0; } }\n        public bool  isDiscreteCurve { get { return m_isDiscreteCurve != 0; } }\n\n        public bool isSerializeReferenceCurve { get { return m_isSerializeReferenceCurve != 0; } }\n        internal bool  isPhantom { get { return m_isPhantom != 0; } set { m_isPhantom = value == true ? 1 : 0; } }\n\n        public static bool operator==(EditorCurveBinding lhs, EditorCurveBinding rhs)\n        {\n            // Only if classID actually has been setup do we compare it (It might only be type)\n            if (lhs.m_ClassID != 0 && rhs.m_ClassID != 0)\n            {\n                if (lhs.m_ClassID != rhs.m_ClassID || lhs.m_ScriptInstanceID != rhs.m_ScriptInstanceID)\n                    return false;\n            }\n\n            return lhs.m_isPPtrCurve == rhs.m_isPPtrCurve && lhs.m_isDiscreteCurve == rhs.m_isDiscreteCurve && lhs.m_isSerializeReferenceCurve == rhs.m_isSerializeReferenceCurve && lhs.path == rhs.path && lhs.type == rhs.type && lhs.propertyName == rhs.propertyName;\n        }\n\n        public static bool operator!=(EditorCurveBinding lhs, EditorCurveBinding rhs)\n        {\n            return !(lhs == rhs);\n        }\n\n        public override int GetHashCode()\n        {\n            return String.Format(\"{0}:{1}:{2}\", path, type.Name, propertyName).GetHashCode();\n        }\n\n        public override bool Equals(object other)\n        {\n            return other is EditorCurveBinding && Equals((EditorCurveBinding)other);\n        }\n\n        public bool Equals(EditorCurveBinding other)\n        {\n            return this == other;\n        }\n\n        public Type type\n        {\n            get { return m_type; }\n            set { m_type = value; m_ClassID = 0; m_ScriptInstanceID = 0; }\n        }\n\n        static private void BaseCurve(string inPath, System.Type inType, string inPropertyName, out EditorCurveBinding binding)\n        {\n            binding = new EditorCurveBinding();\n            binding.path = inPath;\n            binding.type = inType;\n            binding.propertyName = inPropertyName;\n            binding.m_isPhantom = 0;\n        }\n\n        static public EditorCurveBinding FloatCurve(string inPath, System.Type inType, string inPropertyName)\n        {\n            EditorCurveBinding binding;\n            BaseCurve(inPath, inType, inPropertyName, out binding);\n            binding.m_isPPtrCurve = 0;\n            binding.m_isDiscreteCurve = 0;\n            binding.m_isSerializeReferenceCurve = 0;\n            binding.m_isUnknownCurve = 1;\n\n            return binding;\n        }\n\n        static public EditorCurveBinding PPtrCurve(string inPath, System.Type inType, string inPropertyName)\n        {\n            EditorCurveBinding binding;\n            BaseCurve(inPath, inType, inPropertyName, out binding);\n            binding.m_isPPtrCurve = 1;\n            binding.m_isDiscreteCurve = 1;\n            binding.m_isSerializeReferenceCurve = 0;\n            binding.m_isUnknownCurve = 0;\n            return binding;\n        }\n\n        static public EditorCurveBinding DiscreteCurve(string inPath, System.Type inType, string inPropertyName)\n        {\n            EditorCurveBinding binding;\n            BaseCurve(inPath, inType, inPropertyName, out binding);\n            binding.m_isPPtrCurve = 0;\n            binding.m_isDiscreteCurve = 1;\n            binding.m_isSerializeReferenceCurve = 0;\n            binding.m_isUnknownCurve = 0;\n\n            DiscreteBindingResult result = AnimationUtility.IsDiscreteIntBinding(binding);\n            if (result == DiscreteBindingResult.IncompatibleFieldType || result == DiscreteBindingResult.MissingDiscreteAttribute)\n            {\n                Debug.LogWarning(\n                    $\"Property [\" + inPropertyName + \"] is not a supported discrete curve binding. \" +\n                    \"Discrete curves only support [\" + typeof(Enum) + \"] and [\" + typeof(int) + \" with the `DiscreteEvaluation` attribute].\");\n\n                binding.m_isDiscreteCurve = 0;\n                binding.m_isUnknownCurve = 1;\n            }\n\n            return binding;\n        }\n\n        static public EditorCurveBinding SerializeReferenceCurve(string inPath, System.Type inType, long refID, string inPropertyName, bool isPPtr, bool isDiscrete)\n        {\n            EditorCurveBinding binding;\n            BaseCurve(inPath, inType, $\"managedReferences[{refID}].{inPropertyName}\", out binding);\n            binding.m_isPPtrCurve = isPPtr ? 1 : 0;\n            binding.m_isDiscreteCurve = isDiscrete || isPPtr ? 1 : 0;\n            binding.m_isSerializeReferenceCurve = 1;\n            binding.m_isUnknownCurve = 0;\n\n            return binding;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/GameObjectRecorder.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEditor;\nusing Object = UnityEngine.Object;\nusing uei = UnityEngine.Internal;\n\nnamespace UnityEditor.Animations\n{\n    public struct CurveFilterOptions\n    {\n        public float positionError;\n        public float rotationError;\n        public float scaleError;\n        public float floatError;\n        public bool keyframeReduction;\n        public bool unrollRotation;\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/EditorCurveBinding.bindings.h\")]\n    [NativeHeader(\"Editor/Src/Animation/GameObjectRecorder.h\")]\n    [NativeHeader(\"Modules/Animation/AnimationClip.h\")]\n    [NativeType]\n    public class GameObjectRecorder : Object\n    {\n        readonly static CurveFilterOptions k_DefaultCurveFilterOptions = new CurveFilterOptions()\n        {\n            unrollRotation = true,\n            keyframeReduction = true,\n            positionError = 0.5f,\n            rotationError = 0.5f,\n            scaleError = 0.5f,\n            floatError = 0.5f\n        };\n\n        public GameObjectRecorder(GameObject root)\n        {\n            Internal_Create(this, root);\n        }\n\n        public void BindComponentsOfType<T>(GameObject target, bool recursive)\n            where T : Component\n        {\n            BindComponentsOfType(target, typeof(T), recursive);\n        }\n\n        public void BindComponentsOfType(GameObject target, Type componentType, bool recursive)\n        {\n            Component[] components;\n            if (recursive)\n                components = target.GetComponentsInChildren(componentType, true);\n            else\n                components = target.GetComponents(componentType);\n\n            for (int i = 0; i < components.Length; ++i)\n                BindComponent(components[i]);\n        }\n\n        extern private static void Internal_Create([Writable] GameObjectRecorder self, [NotNull] GameObject root);\n\n        // Root.\n        extern public GameObject root { get; }\n\n        // Bindings.\n        public void Bind(EditorCurveBinding binding)\n        {\n            if (!binding.type.IsSubclassOf(typeof(UnityEngine.Object)))\n                throw new InvalidCastException(\"Binding type should derive from Unity type.\");\n\n            BindInternal(binding);\n        }\n\n        [NativeMethod(\"Bind\")]\n        extern private void BindInternal(EditorCurveBinding binding);\n\n        extern public void BindAll(GameObject target, bool recursive);\n        extern public void BindComponent([NotNull] Component component);\n\n        extern public EditorCurveBinding[] GetBindings();\n\n        // Recording.\n        extern public void TakeSnapshot(float dt);\n        extern public float currentTime { get; }\n        extern public bool isRecording { get; }\n\n        public void SaveToClip(AnimationClip clip)\n        {\n            SaveToClip(clip, 60.0f);\n        }\n\n        public void SaveToClip(AnimationClip clip, float fps)\n        {\n            if (fps <= Mathf.Epsilon)\n                throw new ArgumentException(\"FPS can't be 0.0 or less\");\n\n            if (!isRecording)\n                throw new InvalidOperationException(\"Cannot save to clip as there is nothing to save. The method TakeSnapshot() has not been called.\");\n\n            SaveToClipInternal(clip, fps, k_DefaultCurveFilterOptions);\n\n            AnimationUtility.onCurveWasModified?.Invoke(clip, new EditorCurveBinding(), AnimationUtility.CurveModifiedType.ClipModified);\n        }\n\n        public void SaveToClip(AnimationClip clip, float fps, CurveFilterOptions filterOptions)\n        {\n            if (fps <= Mathf.Epsilon)\n                throw new ArgumentException(\"FPS can't be 0.0 or less\");\n\n            if (filterOptions.keyframeReduction)\n            {\n                if (filterOptions.positionError < 0 || filterOptions.rotationError < 0 || filterOptions.scaleError < 0 || filterOptions.floatError < 0)\n                    throw new ArgumentException(\"Allowed errors for keyframe reduction cannot be negative.\");\n            }\n\n            if (!isRecording)\n                throw new InvalidOperationException(\"Cannot save to clip as there is nothing to save. The method TakeSnapshot() has not been called.\");\n\n            SaveToClipInternal(clip, fps, filterOptions);\n\n            AnimationUtility.onCurveWasModified?.Invoke(clip, new EditorCurveBinding(), AnimationUtility.CurveModifiedType.ClipModified);\n        }\n\n        [NativeMethod(\"SaveToClip\")]\n        extern void SaveToClipInternal(AnimationClip clip, float fps, CurveFilterOptions filterOptions);\n\n        extern public void ResetRecording();\n\n        // Obsolete\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"The GameObjectRecorder constructor now takes a root GameObject\", true)]\n        public GameObjectRecorder() {}\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"BindComponent() using a System::Type is obsolete, use BindComponentsOfType() instead (UnityUpgradable) -> BindComponentsOfType(*)\", true)]\n        public void BindComponent(GameObject target, Type componentType, bool recursive) {}\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"\\\"BindComponent<T>() where T : Component\\\" is obsolete, use BindComponentsOfType<T>() instead (UnityUpgradable) -> BindComponentsOfType<T>(*)\", true)]\n        public void BindComponent<T>(GameObject target, bool recursive) where T : Component {}\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/MaterialAnimationUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor;\nusing UnityEngine;\nusing ShaderPropertyType = UnityEngine.Rendering.ShaderPropertyType;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditorInternal\n{\n    static internal class MaterialAnimationUtility\n    {\n        const string kMaterialPrefix = \"material.\";\n\n        static PropertyModification[] CreatePropertyModifications(int count, Object target)\n        {\n            PropertyModification[] modifications = new PropertyModification[count];\n            for (int i = 0; i < modifications.Length; i++)\n            {\n                modifications[i] = new PropertyModification();\n                modifications[i].target = target;\n            }\n            return modifications;\n        }\n\n        static void SetupPropertyModification(string name, float value, PropertyModification prop)\n        {\n            prop.propertyPath = kMaterialPrefix + name;\n            prop.value = value.ToString();\n        }\n\n        static PropertyModification[] MaterialPropertyToPropertyModifications(MaterialProperty materialProp, Object target, float value)\n        {\n            PropertyModification[] modifications = CreatePropertyModifications(1, target);\n            SetupPropertyModification(materialProp.name, value, modifications[0]);\n            return modifications;\n        }\n\n        static PropertyModification[] MaterialPropertyToPropertyModifications(MaterialProperty materialProp, Object target, Color color)\n        {\n            PropertyModification[] modifications = CreatePropertyModifications(4, target);\n            SetupPropertyModification(materialProp.name + \".r\", color.r, modifications[0]);\n            SetupPropertyModification(materialProp.name + \".g\", color.g, modifications[1]);\n            SetupPropertyModification(materialProp.name + \".b\", color.b, modifications[2]);\n            SetupPropertyModification(materialProp.name + \".a\", color.a, modifications[3]);\n            return modifications;\n        }\n\n        static PropertyModification[] MaterialPropertyToPropertyModifications(MaterialProperty materialProp, Object target, Vector4 vec)\n        {\n            return MaterialPropertyToPropertyModifications(materialProp.name, target, vec);\n        }\n\n        static PropertyModification[] MaterialPropertyToPropertyModifications(string name, Object target, Vector4 vec)\n        {\n            PropertyModification[] modifications = CreatePropertyModifications(4, target);\n            SetupPropertyModification(name + \".x\", vec.x, modifications[0]);\n            SetupPropertyModification(name + \".y\", vec.y, modifications[1]);\n            SetupPropertyModification(name + \".z\", vec.z, modifications[2]);\n            SetupPropertyModification(name + \".w\", vec.w, modifications[3]);\n            return modifications;\n        }\n\n        static bool ApplyMaterialModificationToAnimationRecording(PropertyModification[] previousModifications, PropertyModification[] currentModifications)\n        {\n            UndoPropertyModification[] undoModifications = new UndoPropertyModification[previousModifications.Length];\n            for (int i = 0; i < undoModifications.Length; ++i)\n            {\n                undoModifications[i].previousValue = previousModifications[i];\n                undoModifications[i].currentValue = currentModifications[i];\n            }\n\n            UndoPropertyModification[] ret = Undo.InvokePostprocessModifications(undoModifications);\n            return ret.Length != undoModifications.Length;\n        }\n\n        static public bool OverridePropertyColor(MaterialProperty materialProp, Renderer target, out Color color)\n        {\n            var propertyPaths = new List<string>();\n            string basePropertyPath = kMaterialPrefix + materialProp.name;\n\n            if (materialProp.propertyType == ShaderPropertyType.Texture)\n            {\n                propertyPaths.Add(basePropertyPath + \"_ST.x\");\n                propertyPaths.Add(basePropertyPath + \"_ST.y\");\n                propertyPaths.Add(basePropertyPath + \"_ST.z\");\n                propertyPaths.Add(basePropertyPath + \"_ST.w\");\n            }\n            else if (materialProp.propertyType == ShaderPropertyType.Color)\n            {\n                propertyPaths.Add(basePropertyPath + \".r\");\n                propertyPaths.Add(basePropertyPath + \".g\");\n                propertyPaths.Add(basePropertyPath + \".b\");\n                propertyPaths.Add(basePropertyPath + \".a\");\n            }\n            else if (materialProp.propertyType == ShaderPropertyType.Vector)\n            {\n                propertyPaths.Add(basePropertyPath + \".x\");\n                propertyPaths.Add(basePropertyPath + \".y\");\n                propertyPaths.Add(basePropertyPath + \".z\");\n                propertyPaths.Add(basePropertyPath + \".w\");\n            }\n            else\n            {\n                propertyPaths.Add(basePropertyPath);\n            }\n\n            if (propertyPaths.Exists(path => AnimationMode.IsPropertyAnimated(target, path)))\n            {\n                color = AnimationMode.animatedPropertyColor;\n                if (AnimationMode.InAnimationRecording())\n                    color = AnimationMode.recordedPropertyColor;\n                else if (propertyPaths.Exists(path => AnimationMode.IsPropertyCandidate(target, path)))\n                    color = AnimationMode.candidatePropertyColor;\n\n                return true;\n            }\n\n            color = Color.white;\n            return false;\n        }\n\n        static public void SetupMaterialPropertyBlock(MaterialProperty materialProp, int changedMask, Renderer target)\n        {\n            MaterialPropertyBlock block = new MaterialPropertyBlock();\n            target.GetPropertyBlock(block);\n            materialProp.WriteToMaterialPropertyBlock(block, changedMask);\n            target.SetPropertyBlock(block);\n        }\n\n        static public void TearDownMaterialPropertyBlock(Renderer target)\n        {\n            target.SetPropertyBlock(null);\n        }\n\n        static public bool ApplyMaterialModificationToAnimationRecording(MaterialProperty materialProp, int changedMask, Renderer target, object oldValue)\n        {\n            bool applied = false;\n            switch (materialProp.propertyType)\n            {\n                case ShaderPropertyType.Color:\n                    SetupMaterialPropertyBlock(materialProp, changedMask, target);\n                    applied = ApplyMaterialModificationToAnimationRecording(MaterialPropertyToPropertyModifications(materialProp, target, (Color)oldValue), MaterialPropertyToPropertyModifications(materialProp, target, materialProp.colorValue));\n                    if (!applied)\n                        TearDownMaterialPropertyBlock(target);\n                    return applied;\n\n                case ShaderPropertyType.Vector:\n                    SetupMaterialPropertyBlock(materialProp, changedMask, target);\n                    applied = ApplyMaterialModificationToAnimationRecording(MaterialPropertyToPropertyModifications(materialProp, target, (Vector4)oldValue), MaterialPropertyToPropertyModifications(materialProp, target, materialProp.vectorValue));\n                    if (!applied)\n                        TearDownMaterialPropertyBlock(target);\n                    return applied;\n\n                case ShaderPropertyType.Float:\n                case ShaderPropertyType.Range:\n                    SetupMaterialPropertyBlock(materialProp, changedMask, target);\n                    applied = ApplyMaterialModificationToAnimationRecording(MaterialPropertyToPropertyModifications(materialProp, target, (float)oldValue), MaterialPropertyToPropertyModifications(materialProp, target, materialProp.floatValue));\n                    if (!applied)\n                        TearDownMaterialPropertyBlock(target);\n                    return applied;\n\n                case ShaderPropertyType.Texture:\n                {\n                    if (MaterialProperty.IsTextureOffsetAndScaleChangedMask(changedMask))\n                    {\n                        string name = materialProp.name + \"_ST\";\n                        SetupMaterialPropertyBlock(materialProp, changedMask, target);\n                        applied = ApplyMaterialModificationToAnimationRecording(MaterialPropertyToPropertyModifications(name, target, (Vector4)oldValue), MaterialPropertyToPropertyModifications(name, target, materialProp.textureScaleAndOffset));\n                        if (!applied)\n                            TearDownMaterialPropertyBlock(target);\n                        return applied;\n                    }\n                    else\n                        return false;\n                }\n            }\n\n            return false;\n        }\n\n        static public PropertyModification[] MaterialPropertyToPropertyModifications(MaterialProperty materialProp, Renderer target)\n        {\n            switch (materialProp.propertyType)\n            {\n                case ShaderPropertyType.Color:\n                    return MaterialPropertyToPropertyModifications(materialProp, target, materialProp.colorValue);\n                case ShaderPropertyType.Vector:\n                    return MaterialPropertyToPropertyModifications(materialProp, target, materialProp.vectorValue);\n                case ShaderPropertyType.Float:\n                case ShaderPropertyType.Range:\n                    return MaterialPropertyToPropertyModifications(materialProp, target, materialProp.floatValue);\n\n                case ShaderPropertyType.Texture:\n                {\n                    string name = materialProp.name + \"_ST\";\n                    return MaterialPropertyToPropertyModifications(name, target, materialProp.vectorValue);\n                }\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/MecanimUtilities.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing System.Linq;\n\n\nnamespace UnityEditor.Animations\n{\n    internal class MecanimUtilities\n    {\n        public static bool StateMachineRelativePath(AnimatorStateMachine parent, AnimatorStateMachine toFind,\n            ref List<AnimatorStateMachine> hierarchy)\n        {\n            hierarchy.Add(parent);\n            if (parent == toFind)\n                return true;\n            var childStateMachines = AnimatorStateMachine.StateMachineCache.GetChildStateMachines(parent);\n            for (int i = 0; i < childStateMachines.Length; i++)\n            {\n                if (StateMachineRelativePath(childStateMachines[i].stateMachine, toFind, ref hierarchy))\n                    return true;\n            }\n            hierarchy.Remove(parent);\n            return false;\n        }\n\n        internal static bool AreSameAsset(Object obj1, Object obj2)\n        {\n            return AssetDatabase.GetAssetPath(obj1) == AssetDatabase.GetAssetPath(obj2);\n        }\n\n        internal static void DestroyBlendTreeRecursive(BlendTree blendTree)\n        {\n            for (int i = 0; i < blendTree.children.Length; i++)\n            {\n                BlendTree childBlendTree = blendTree.children[i].motion as BlendTree;\n                if (childBlendTree != null && AreSameAsset(blendTree, childBlendTree))\n                    DestroyBlendTreeRecursive(childBlendTree);\n            }\n\n            Undo.DestroyObjectImmediate(blendTree);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/SerializedStringTable.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections;\n\n[System.Serializable]\ninternal class SerializedStringTable\n{\n    [SerializeField] private string[] keys;\n    [SerializeField] private int[] values;\n    private Hashtable table;\n    public Hashtable hashtable { get { SanityCheck(); return table; } }\n\n    public int Length { get { SanityCheck(); return keys.Length; } }\n\n    private void SanityCheck()\n    {\n        if (keys == null)\n        {\n            keys = new string[0];\n            values = new int[0];\n        }\n        if (table == null)\n        {\n            table = new Hashtable();\n            for (int i = 0; i < keys.Length; i++) table[keys[i]] = values[i];\n        }\n    }\n\n    private void SynchArrays()\n    {\n        keys = new string[table.Count];\n        values = new int[table.Count];\n        table.Keys.CopyTo(keys, 0);\n        table.Values.CopyTo(values, 0);\n    }\n\n    public void Set(string key, int value)\n    {\n        SanityCheck();\n        table[key] = value;\n        SynchArrays();\n    }\n\n    public void Set(string key)\n    {\n        Set(key, 0);\n    }\n\n    public bool Contains(string key)\n    {\n        SanityCheck();\n        return table.Contains(key);\n    }\n\n    public int Get(string key)\n    {\n        SanityCheck();\n        if (!table.Contains(key)) return -1;\n        return (int)table[key];\n    }\n\n    public void Remove(string key)\n    {\n        SanityCheck();\n        if (table.Contains(key)) table.Remove(key);\n        SynchArrays();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/StateMachine.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditor;\nusing System.Linq;\n\nnamespace UnityEditor.Animations\n{\n    internal struct PushUndoIfNeeded\n    {\n        public bool pushUndo\n        {\n            get { return impl.m_PushUndo; }\n            set { impl.m_PushUndo = value; }\n        }\n\n        public PushUndoIfNeeded(bool pushUndo)\n        {\n            m_Impl = new PushUndoIfNeededImpl(pushUndo);\n        }\n\n        public void DoUndo(Object target, string undoOperation)\n        {\n            impl.DoUndo(target, undoOperation);\n        }\n\n        public void DoUndoCreated(Object target, string undoOperation)\n        {\n            impl.DoUndoCreated(target, undoOperation);\n        }\n\n        PushUndoIfNeededImpl impl\n        {\n            get\n            {\n                if (m_Impl == null)\n                    m_Impl = new PushUndoIfNeededImpl(true);\n                return m_Impl;\n            }\n        }\n\n        PushUndoIfNeededImpl m_Impl;\n\n        private class PushUndoIfNeededImpl\n        {\n            public PushUndoIfNeededImpl(bool pushUndo)\n            {\n                m_PushUndo = pushUndo;\n            }\n\n            public void DoUndo(Object target, string undoOperation)\n            {\n                if (m_PushUndo)\n                {\n                    Undo.RegisterCompleteObjectUndo(target, undoOperation);\n                }\n            }\n\n            public void DoUndoCreated(Object target, string undoOperation)\n            {\n                if (m_PushUndo)\n                {\n                    Undo.RegisterCreatedObjectUndo(target, undoOperation);\n                }\n            }\n\n            public bool m_PushUndo;\n        }\n    }\n\n\n    public partial class AnimatorTransitionBase : Object\n    {\n        private PushUndoIfNeeded undoHandler =  new PushUndoIfNeeded(true);\n        internal bool pushUndo { set { undoHandler.pushUndo = value; } }\n\n        public void AddCondition(AnimatorConditionMode mode, float threshold, string parameter)\n        {\n            undoHandler.DoUndo(this, \"Condition added\");\n\n            AnimatorCondition[] conditionVector = conditions;\n            AnimatorCondition newCondition = new AnimatorCondition();\n            newCondition.mode = mode;\n            newCondition.parameter = parameter;\n            newCondition.threshold = threshold;\n\n            ArrayUtility.Add(ref conditionVector, newCondition);\n            conditions = conditionVector;\n        }\n\n        public void RemoveCondition(AnimatorCondition condition)\n        {\n            undoHandler.DoUndo(this, \"Condition removed\");\n            AnimatorCondition[] conditionVector = conditions;\n            ArrayUtility.Remove(ref conditionVector, condition);\n            conditions = conditionVector;\n        }\n    }\n\n    [HelpURL(\"StateMachineTransitions\")]\n    internal class AnimatorDefaultTransition : ScriptableObject\n    {\n    }\n\n    [HelpURL(\"class-State\")]\n    public partial class AnimatorState : Object\n    {\n        private PushUndoIfNeeded undoHandler = new PushUndoIfNeeded(true);\n        internal bool pushUndo { set { undoHandler.pushUndo = value; } }\n\n\n        public void AddTransition(AnimatorStateTransition transition)\n        {\n            undoHandler.DoUndo(this, \"Transition added\");\n\n            AnimatorStateTransition[] transitionsVector = transitions;\n            ArrayUtility.Add(ref transitionsVector, transition);\n            transitions = transitionsVector;\n        }\n\n        public void RemoveTransition(AnimatorStateTransition transition)\n        {\n            undoHandler.DoUndo(this, \"Transition removed\");\n\n            AnimatorStateTransition[] transitionsVector = transitions;\n            ArrayUtility.Remove(ref transitionsVector, transition);\n            transitions = transitionsVector;\n\n            if (MecanimUtilities.AreSameAsset(this, transition))\n                Undo.DestroyObjectImmediate(transition);\n        }\n\n        private AnimatorStateTransition CreateTransition(bool setDefaultExitTime)\n        {\n            AnimatorStateTransition newTransition = new AnimatorStateTransition();\n            newTransition.hasExitTime = false;\n            newTransition.hasFixedDuration = true;\n            if (AssetDatabase.GetAssetPath(this) != \"\")\n                AssetDatabase.AddObjectToAsset(newTransition, AssetDatabase.GetAssetPath(this));\n            newTransition.hideFlags = HideFlags.HideInHierarchy;\n\n            undoHandler.DoUndoCreated(newTransition, \"Transition Created\");\n\n            if (setDefaultExitTime)\n                SetDefaultTransitionExitTime(ref newTransition);\n\n            return newTransition;\n        }\n\n        private void SetDefaultTransitionExitTime(ref AnimatorStateTransition newTransition)\n        {\n            newTransition.hasExitTime = true;\n\n            if (motion != null && motion.averageDuration > 0.0f)\n            {\n                const float transitionDefaultDuration = 0.25f;\n                float transitionDurationNormalized = transitionDefaultDuration / motion.averageDuration;\n                newTransition.duration = transitionDefaultDuration;\n                newTransition.exitTime = 1.0f - transitionDurationNormalized;\n            }\n            else\n            {\n                newTransition.duration = 0.25f;\n                newTransition.exitTime = 0.75f;\n            }\n        }\n\n        public AnimatorStateTransition AddTransition(AnimatorState destinationState)\n        {\n            AnimatorStateTransition newTransition = CreateTransition(false);\n            newTransition.destinationState = destinationState;\n            AddTransition(newTransition);\n            return newTransition;\n        }\n\n        public AnimatorStateTransition AddTransition(AnimatorStateMachine destinationStateMachine)\n        {\n            AnimatorStateTransition newTransition = CreateTransition(false);\n            newTransition.destinationStateMachine = destinationStateMachine;\n            AddTransition(newTransition);\n            return newTransition;\n        }\n\n        public AnimatorStateTransition AddTransition(AnimatorState destinationState, bool defaultExitTime)\n        {\n            AnimatorStateTransition newTransition = CreateTransition(defaultExitTime);\n            newTransition.destinationState = destinationState;\n            AddTransition(newTransition);\n            return newTransition;\n        }\n\n        public AnimatorStateTransition AddTransition(AnimatorStateMachine destinationStateMachine, bool defaultExitTime)\n        {\n            AnimatorStateTransition newTransition = CreateTransition(defaultExitTime);\n            newTransition.destinationStateMachine = destinationStateMachine;\n            AddTransition(newTransition);\n            return newTransition;\n        }\n\n        public AnimatorStateTransition AddExitTransition()\n        {\n            return AddExitTransition(false);\n        }\n\n        public AnimatorStateTransition AddExitTransition(bool defaultExitTime)\n        {\n            AnimatorStateTransition newTransition = CreateTransition(defaultExitTime);\n            newTransition.isExit = true;\n            AddTransition(newTransition);\n            return newTransition;\n        }\n\n        internal AnimatorStateMachine FindParent(AnimatorStateMachine root)\n        {\n            if (root.HasState(this, false)) return root;\n            else return root.stateMachinesRecursive.Find(sm => sm.stateMachine.HasState(this, false)).stateMachine;\n        }\n\n        internal AnimatorStateTransition FindTransition(AnimatorState destinationState) // pp todo return a list?\n        {\n            return (new List<AnimatorStateTransition>(transitions)).Find(t => t.destinationState == destinationState);\n        }\n\n        [System.Obsolete(\"uniqueName does not exist anymore. Consider using .name instead.\", true)]\n        public string uniqueName\n        {\n            get { return \"\"; }\n        }\n\n        [System.Obsolete(\"GetMotion() is obsolete. Use motion\", true)]\n        public Motion GetMotion()\n        {\n            return null;\n        }\n\n        [System.Obsolete(\"uniqueNameHash does not exist anymore.\", true)]\n        public int uniqueNameHash\n        {\n            get { return -1; }\n        }\n    }\n\n    [HelpURL(\"NestedStateMachines\")]\n    public partial class AnimatorStateMachine : Object\n    {\n        private PushUndoIfNeeded undoHandler = new PushUndoIfNeeded(true);\n        internal bool pushUndo { set { undoHandler.pushUndo = value; } }\n\n        internal class StateMachineCache\n        {\n            static Dictionary<AnimatorStateMachine, ChildAnimatorStateMachine[]> m_ChildStateMachines;\n            static bool m_Initialized;\n\n            static void Init()\n            {\n                if (!m_Initialized)\n                {\n                    m_ChildStateMachines = new Dictionary<AnimatorStateMachine, ChildAnimatorStateMachine[]>();\n                    m_Initialized = true;\n                }\n            }\n\n            static public void Clear()\n            {\n                Init();\n                m_ChildStateMachines.Clear();\n            }\n\n            static public ChildAnimatorStateMachine[] GetChildStateMachines(AnimatorStateMachine parent)\n            {\n                Init();\n\n                ChildAnimatorStateMachine[] children;\n                if (m_ChildStateMachines.TryGetValue(parent, out children) == false)\n                {\n                    children = parent.stateMachines;\n                    m_ChildStateMachines.Add(parent, children);\n                }\n                return children;\n            }\n        }\n        internal List<ChildAnimatorState> statesRecursive\n        {\n            get\n            {\n                List<ChildAnimatorState> ret = new List<ChildAnimatorState>();\n                ret.AddRange(states);\n\n                for (int j = 0; j < stateMachines.Length; j++)\n                {\n                    ret.AddRange(stateMachines[j].stateMachine.statesRecursive);\n                }\n                return ret;\n            }\n        }\n\n        internal List<ChildAnimatorStateMachine> stateMachinesRecursive\n        {\n            get\n            {\n                List<ChildAnimatorStateMachine> ret = new List<ChildAnimatorStateMachine>();\n                var childStateMachines = AnimatorStateMachine.StateMachineCache.GetChildStateMachines(this);\n                ret.AddRange(childStateMachines);\n\n                for (int j = 0; j < childStateMachines.Length; j++)\n                {\n                    ret.AddRange(childStateMachines[j].stateMachine.stateMachinesRecursive);\n                }\n                return ret;\n            }\n        }\n\n        internal List<AnimatorStateTransition> anyStateTransitionsRecursive\n        {\n            get\n            {\n                List<AnimatorStateTransition> childTransitions = new List<AnimatorStateTransition>();\n                childTransitions.AddRange(anyStateTransitions);\n\n                foreach (ChildAnimatorStateMachine stateMachine in stateMachines)\n                {\n                    childTransitions.AddRange(stateMachine.stateMachine.anyStateTransitionsRecursive);\n                }\n\n                return childTransitions;\n            }\n        }\n\n        internal Vector3 GetStatePosition(AnimatorState state)\n        {\n            ChildAnimatorState[] animatorStates = states;\n            for (int i = 0; i < animatorStates.Length; i++)\n                if (state == animatorStates[i].state)\n                    return animatorStates[i].position;\n\n            System.Diagnostics.Debug.Fail(\"Can't find state (\" + state.name + \") in parent state machine (\" + name + \").\");\n            return Vector3.zero;\n        }\n\n        internal void SetStatePosition(AnimatorState state, Vector3 position)\n        {\n            ChildAnimatorState[] childStates = states;\n            for (int i = 0; i < childStates.Length; i++)\n                if (state == childStates[i].state)\n                {\n                    childStates[i].position = position;\n                    states = childStates;\n                    return;\n                }\n\n            System.Diagnostics.Debug.Fail(\"Can't find state (\" + state.name + \") in parent state machine (\" + name + \").\");\n        }\n\n        internal Vector3 GetStateMachinePosition(AnimatorStateMachine stateMachine)\n        {\n            ChildAnimatorStateMachine[] childSM = stateMachines;\n            for (int i = 0; i < childSM.Length; i++)\n                if (stateMachine == childSM[i].stateMachine)\n                    return childSM[i].position;\n\n            System.Diagnostics.Debug.Fail(\"Can't find state machine (\" + stateMachine.name + \") in parent state machine (\" + name + \").\");\n\n            return Vector3.zero;\n        }\n\n        internal void SetStateMachinePosition(AnimatorStateMachine stateMachine, Vector3 position)\n        {\n            ChildAnimatorStateMachine[] childSM = stateMachines;\n            for (int i = 0; i < childSM.Length; i++)\n                if (stateMachine == childSM[i].stateMachine)\n                {\n                    childSM[i].position = position;\n                    stateMachines = childSM;\n                    return;\n                }\n\n            System.Diagnostics.Debug.Fail(\"Can't find state machine (\" + stateMachine.name + \") in parent state machine (\" + name + \").\");\n        }\n\n        public AnimatorState AddState(string name)\n        {\n            return AddState(name, states.Length > 0 ? states[states.Length - 1].position + new Vector3(35, 65) : new Vector3(200, 0, 0));\n        }\n\n        public AnimatorState AddState(string name, Vector3 position)\n        {\n            AnimatorState state = new AnimatorState();\n            state.hideFlags = HideFlags.HideInHierarchy;\n            state.name = MakeUniqueStateName(name);\n\n            if (AssetDatabase.GetAssetPath(this) != \"\")\n                AssetDatabase.AddObjectToAsset(state, AssetDatabase.GetAssetPath(this));\n\n            undoHandler.DoUndoCreated(state, \"State Created\");\n\n            AddState(state, position);\n\n            return state;\n        }\n\n        public void AddState(AnimatorState state, Vector3 position)\n        {\n            ChildAnimatorState[] childStates = states;\n            if (System.Array.Exists(childStates, childState => childState.state == state))\n            {\n                Debug.LogWarning(System.String.Format(\"State '{0}' already exists in state machine '{1}', discarding new state.\", state.name, name));\n                return;\n            }\n\n            undoHandler.DoUndo(this, \"State added\");\n\n            ChildAnimatorState newState = new ChildAnimatorState();\n            newState.state = state;\n            newState.position = position;\n\n            ArrayUtility.Add(ref childStates, newState);\n            states = childStates;\n        }\n\n        public void RemoveState(AnimatorState state)\n        {\n            undoHandler.DoUndo(this, \"State removed\");\n            undoHandler.DoUndo(state, \"State removed\");\n            RemoveStateInternal(state);\n        }\n\n        public AnimatorStateMachine AddStateMachine(string name)\n        {\n            return AddStateMachine(name, Vector3.zero);\n        }\n\n        public AnimatorStateMachine AddStateMachine(string name, Vector3 position)\n        {\n            AnimatorStateMachine stateMachine = new AnimatorStateMachine();\n            stateMachine.hideFlags = HideFlags.HideInHierarchy;\n            stateMachine.name = MakeUniqueStateMachineName(name);\n\n            AddStateMachine(stateMachine, position);\n\n            if (AssetDatabase.GetAssetPath(this) != \"\")\n                AssetDatabase.AddObjectToAsset(stateMachine, AssetDatabase.GetAssetPath(this));\n\n            undoHandler.DoUndoCreated(stateMachine, \"StateMachine Created\");\n\n            return stateMachine;\n        }\n\n        public void AddStateMachine(AnimatorStateMachine stateMachine, Vector3 position)\n        {\n            ChildAnimatorStateMachine[] childStateMachines = stateMachines;\n            if (System.Array.Exists(childStateMachines, childStateMachine => childStateMachine.stateMachine == stateMachine))\n            {\n                Debug.LogWarning(System.String.Format(\"Sub state machine '{0}' already exists in state machine '{1}', discarding new state machine.\", stateMachine.name, name));\n                return;\n            }\n\n            undoHandler.DoUndo(this, \"StateMachine \" + stateMachine.name + \" added\");\n            ChildAnimatorStateMachine newStateMachine = new ChildAnimatorStateMachine();\n            newStateMachine.stateMachine = stateMachine;\n            newStateMachine.position = position;\n\n            ArrayUtility.Add(ref childStateMachines, newStateMachine);\n            stateMachines = childStateMachines;\n        }\n\n        public void RemoveStateMachine(AnimatorStateMachine stateMachine)\n        {\n            undoHandler.DoUndo(this, \"StateMachine removed\");\n            undoHandler.DoUndo(stateMachine, \"StateMachine removed\");\n            RemoveStateMachineInternal(stateMachine);\n        }\n\n        private AnimatorStateTransition AddAnyStateTransition()\n        {\n            AnimatorStateTransition newTransition = new AnimatorStateTransition();\n            newTransition.hasExitTime = false;\n            newTransition.hasFixedDuration = true;\n            newTransition.duration = 0.25f;\n            newTransition.exitTime = 0.75f;\n            newTransition.hideFlags = HideFlags.HideInHierarchy;\n\n            if (AssetDatabase.GetAssetPath(this) != \"\")\n                AssetDatabase.AddObjectToAsset(newTransition, AssetDatabase.GetAssetPath(this));\n\n            undoHandler.DoUndoCreated(newTransition, \"AnyState Transition Created\");\n\n            undoHandler.DoUndo(this, \"AnyState Transition Added\");\n\n            AnimatorStateTransition[] transitionsVector = anyStateTransitions;\n            ArrayUtility.Add(ref transitionsVector, newTransition);\n            anyStateTransitions = transitionsVector;\n\n            return newTransition;\n        }\n\n        public AnimatorStateTransition AddAnyStateTransition(AnimatorState destinationState)\n        {\n            AnimatorStateTransition newTransition = AddAnyStateTransition();\n            newTransition.destinationState = destinationState;\n            return newTransition;\n        }\n\n        public AnimatorStateTransition AddAnyStateTransition(AnimatorStateMachine destinationStateMachine)\n        {\n            AnimatorStateTransition newTransition = AddAnyStateTransition();\n            newTransition.destinationStateMachine = destinationStateMachine;\n            return newTransition;\n        }\n\n        public bool RemoveAnyStateTransition(AnimatorStateTransition transition)\n        {\n            if ((new List<AnimatorStateTransition>(anyStateTransitions)).Any(t => t == transition))\n            {\n                undoHandler.DoUndo(this, \"AnyState Transition Removed\");\n\n                AnimatorStateTransition[] transitionsVector = anyStateTransitions;\n                ArrayUtility.Remove(ref transitionsVector, transition);\n                anyStateTransitions = transitionsVector;\n\n                if (MecanimUtilities.AreSameAsset(this, transition))\n                    Undo.DestroyObjectImmediate(transition);\n\n                return true;\n            }\n\n            return false;\n        }\n\n        internal void RemoveAnyStateTransitionRecursive(AnimatorStateTransition transition)\n        {\n            if (RemoveAnyStateTransition(transition))\n                return;\n\n            List<ChildAnimatorStateMachine> childStateMachines = stateMachinesRecursive;\n            foreach (ChildAnimatorStateMachine sm in childStateMachines)\n            {\n                if (sm.stateMachine.RemoveAnyStateTransition(transition))\n                    return;\n            }\n        }\n\n        public AnimatorTransition AddStateMachineTransition(AnimatorStateMachine sourceStateMachine)\n        {\n            AnimatorTransition newTransition = new AnimatorTransition();\n            AddStateMachineTransition(sourceStateMachine, newTransition);\n            return newTransition;\n        }\n\n        public AnimatorTransition AddStateMachineTransition(AnimatorStateMachine sourceStateMachine, AnimatorStateMachine destinationStateMachine)\n        {\n            var newTransition = new AnimatorTransition();\n            newTransition.destinationStateMachine = destinationStateMachine;\n            AddStateMachineTransition(sourceStateMachine, newTransition);\n            return newTransition;\n        }\n\n        public AnimatorTransition AddStateMachineTransition(AnimatorStateMachine sourceStateMachine, AnimatorState destinationState)\n        {\n            var newTransition = new AnimatorTransition();\n            newTransition.destinationState = destinationState;\n            AddStateMachineTransition(sourceStateMachine, newTransition);\n            return newTransition;\n        }\n\n        internal void AddStateMachineTransition(AnimatorStateMachine sourceStateMachine, AnimatorTransition transition)\n        {\n            transition.hideFlags = HideFlags.HideInHierarchy;\n\n            if (AssetDatabase.GetAssetPath(this) != \"\")\n                AssetDatabase.AddObjectToAsset(transition, AssetDatabase.GetAssetPath(this));\n\n            undoHandler.DoUndoCreated(transition, \"StateMachine Transition Created\");\n\n            undoHandler.DoUndo(this, \"StateMachine Transition Added\");\n\n            AnimatorTransition[] transitionsVector = GetStateMachineTransitions(sourceStateMachine);\n            ArrayUtility.Add(ref transitionsVector, transition);\n            SetStateMachineTransitions(sourceStateMachine, transitionsVector);\n        }\n\n        public AnimatorTransition AddStateMachineExitTransition(AnimatorStateMachine sourceStateMachine)\n        {\n            var newTransition = new AnimatorTransition();\n            newTransition.isExit = true;\n            AddStateMachineTransition(sourceStateMachine, newTransition);\n            return newTransition;\n        }\n\n        public bool RemoveStateMachineTransition(AnimatorStateMachine sourceStateMachine, AnimatorTransition transition)\n        {\n            undoHandler.DoUndo(this, \"StateMachine Transition Removed\");\n\n            AnimatorTransition[] transitionsVector = GetStateMachineTransitions(sourceStateMachine);\n            int baseSize = transitionsVector.Length;\n            ArrayUtility.Remove(ref transitionsVector, transition);\n            SetStateMachineTransitions(sourceStateMachine, transitionsVector);\n\n            if (MecanimUtilities.AreSameAsset(this, transition))\n                Undo.DestroyObjectImmediate(transition);\n\n            return baseSize != transitionsVector.Length;\n        }\n\n        private AnimatorTransition AddEntryTransition()\n        {\n            AnimatorTransition newTransition = new AnimatorTransition();\n            newTransition.hideFlags = HideFlags.HideInHierarchy;\n\n            if (AssetDatabase.GetAssetPath(this) != \"\")\n                AssetDatabase.AddObjectToAsset(newTransition, AssetDatabase.GetAssetPath(this));\n\n            undoHandler.DoUndoCreated(newTransition, \"Entry Transition Created\");\n\n            undoHandler.DoUndo(this, \"Entry Transition Added\");\n            AnimatorTransition[] transitionsVector = entryTransitions;\n            ArrayUtility.Add(ref transitionsVector, newTransition);\n            entryTransitions = transitionsVector;\n\n            return newTransition;\n        }\n\n        public AnimatorTransition AddEntryTransition(AnimatorState destinationState)\n        {\n            AnimatorTransition newTransition = AddEntryTransition();\n            newTransition.destinationState = destinationState;\n            return newTransition;\n        }\n\n        public AnimatorTransition AddEntryTransition(AnimatorStateMachine destinationStateMachine)\n        {\n            AnimatorTransition newTransition = AddEntryTransition();\n            newTransition.destinationStateMachine = destinationStateMachine;\n            return newTransition;\n        }\n\n        public bool RemoveEntryTransition(AnimatorTransition transition)\n        {\n            if ((new List<AnimatorTransition>(entryTransitions)).Any(t => t == transition))\n            {\n                undoHandler.DoUndo(this, \"Entry Transition Removed\");\n                AnimatorTransition[] transitionsVector = entryTransitions;\n                ArrayUtility.Remove(ref transitionsVector, transition);\n                entryTransitions = transitionsVector;\n\n                if (MecanimUtilities.AreSameAsset(this, transition))\n                    Undo.DestroyObjectImmediate(transition);\n\n                return true;\n            }\n\n            return false;\n        }\n\n        internal ChildAnimatorState FindState(int nameHash)\n        {\n            return (new List<ChildAnimatorState>(states)).Find(s => s.state.nameHash == nameHash);\n        }\n\n        internal ChildAnimatorState FindState(string name)\n        {\n            return (new List<ChildAnimatorState>(states)).Find(s => s.state.name == name);\n        }\n\n        internal bool HasState(AnimatorState state)\n        {\n            return statesRecursive.Any(s => s.state == state);\n        }\n\n        internal bool IsDirectParent(AnimatorStateMachine stateMachine)\n        {\n            return stateMachines.Any(sm => sm.stateMachine == stateMachine);\n        }\n\n        internal bool HasStateMachine(AnimatorStateMachine child)\n        {\n            return stateMachinesRecursive.Any(sm => sm.stateMachine == child);\n        }\n\n        internal bool HasTransition(AnimatorState stateA, AnimatorState stateB)\n        {\n            return stateA.transitions.Any(t => t.destinationState == stateB) ||\n                stateB.transitions.Any(t => t.destinationState == stateA);\n        }\n\n        internal AnimatorStateMachine FindParent(AnimatorStateMachine stateMachine)\n        {\n            if (stateMachines.Any(childSM => childSM.stateMachine == stateMachine))\n                return this;\n            else\n                return stateMachinesRecursive.Find(sm => sm.stateMachine.stateMachines.Any(childSM => childSM.stateMachine == stateMachine)).stateMachine;\n        }\n\n        internal AnimatorStateMachine FindStateMachine(string path)\n        {\n            string[] smNames = path.Split('.');\n\n            // first element is always Root statemachine 'this'\n            AnimatorStateMachine currentSM = this;\n            // last element is state name, we don't care\n            for (int i = 1; i < smNames.Length - 1 && currentSM != null; ++i)\n            {\n                var childStateMachines = AnimatorStateMachine.StateMachineCache.GetChildStateMachines(currentSM);\n                int index = System.Array.FindIndex(childStateMachines, t => t.stateMachine.name == smNames[i]);\n                currentSM = index >= 0 ? childStateMachines[index].stateMachine : null;\n            }\n\n            return (currentSM == null) ? this : currentSM;\n        }\n\n        internal AnimatorStateMachine FindStateMachine(AnimatorState state)\n        {\n            if (HasState(state, false))\n                return this;\n\n            List<ChildAnimatorStateMachine> childStateMachines = stateMachinesRecursive;\n            int index = childStateMachines.FindIndex(sm => sm.stateMachine.HasState(state, false));\n            return index >= 0 ? childStateMachines[index].stateMachine : null;\n        }\n\n        internal AnimatorStateTransition FindTransition(AnimatorState destinationState)\n        {\n            return (new List<AnimatorStateTransition>(anyStateTransitions)).Find(t => t.destinationState == destinationState);\n        }\n\n        [System.Obsolete(\"stateCount is obsolete. Use .states.Length  instead.\", true)]\n        int stateCount\n        {\n            get { return 0; }\n        }\n\n        [System.Obsolete(\"stateMachineCount is obsolete. Use .stateMachines.Length instead.\", true)]\n        int stateMachineCount\n        {\n            get { return 0; }\n        }\n\n        [System.Obsolete(\"GetTransitionsFromState is obsolete. Use AnimatorState.transitions instead.\", true)]\n        AnimatorState GetTransitionsFromState(AnimatorState state)\n        {\n            return null;\n        }\n\n        [System.Obsolete(\"uniqueNameHash does not exist anymore.\", true)]\n        int uniqueNameHash\n        {\n            get { return -1; }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/TickHandler.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    internal class TickHandler\n    {\n        // Variables related to drawing tick markers\n        [SerializeField] private float[] m_TickModulos = new float[] {}; // array with possible modulo numbers to choose from\n        [SerializeField] private float[] m_TickStrengths = new float[] {}; // array with current strength of each modulo number\n        [SerializeField] private int m_SmallestTick = 0; // index of the currently smallest modulo number used to draw ticks\n        [SerializeField] private int m_BiggestTick = -1; // index of the currently biggest modulo number used to draw ticks\n        [SerializeField] private float m_MinValue = 0; // shownArea min (in curve space)\n        [SerializeField] private float m_MaxValue = 1; // shownArea max (in curve space)\n        [SerializeField] private float m_PixelRange = 1; // total width/height of curveeditor\n\n        public int tickLevels { get { return m_BiggestTick - m_SmallestTick + 1; } }\n\n        private List<float> m_TickList = new List<float>(1000);\n\n        public void SetTickModulos(float[] tickModulos)\n        {\n            m_TickModulos = tickModulos;\n        }\n\n        public List<float> GetTickModulosForFrameRate(float frameRate)\n        {\n            List<float> modulos;\n\n            // Make frames multiples of 5 and 10, if frameRate is too high (avoid overflow) or not an even number\n            if (frameRate > int.MaxValue / 2.0f || frameRate != Mathf.Round(frameRate))\n            {\n                modulos = new List<float>\n                {\n                    1f / frameRate,\n                    5f / frameRate,\n                    10f / frameRate,\n                    50f / frameRate,\n                    100f / frameRate,\n                    500f / frameRate,\n                    1000f / frameRate,\n                    5000f / frameRate,\n                    10000f / frameRate,\n                    50000f / frameRate,\n                    100000f / frameRate,\n                    500000f / frameRate\n                };\n\n                return modulos;\n            }\n\n            List<int> dividers = new List<int>();\n            int divisor = 1;\n            while (divisor < frameRate)\n            {\n                if (Math.Abs(divisor - frameRate) < 1e-5)\n                    break;\n                int multiple = Mathf.RoundToInt(frameRate / divisor);\n                if (multiple % 60 == 0)\n                {\n                    divisor *= 2;\n                    dividers.Add(divisor);\n                }\n                else if (multiple % 30 == 0)\n                {\n                    divisor *= 3;\n                    dividers.Add(divisor);\n                }\n                else if (multiple % 20 == 0)\n                {\n                    divisor *= 2;\n                    dividers.Add(divisor);\n                }\n                else if (multiple % 10 == 0)\n                {\n                    divisor *= 2;\n                    dividers.Add(divisor);\n                }\n                else if (multiple % 5 == 0)\n                {\n                    divisor *= 5;\n                    dividers.Add(divisor);\n                }\n                else if (multiple % 2 == 0)\n                {\n                    divisor *= 2;\n                    dividers.Add(divisor);\n                }\n                else if (multiple % 3 == 0)\n                {\n                    divisor *= 3;\n                    dividers.Add(divisor);\n                }\n                else\n                    divisor = Mathf.RoundToInt(frameRate);\n            }\n            modulos = new List<float>(13 + dividers.Count);\n\n            for (int i = 0; i < dividers.Count; i++)\n                modulos.Add(1f / dividers[dividers.Count - i - 1]);\n\n            // Ticks based on seconds\n            modulos.Add(1);\n            modulos.Add(5);\n            modulos.Add(10);\n            modulos.Add(30);\n            modulos.Add(60);\n            modulos.Add(60 * 5);\n            modulos.Add(60 * 10);\n            modulos.Add(60 * 30);\n            modulos.Add(3600);\n            modulos.Add(3600 * 6);\n            modulos.Add(3600 * 24);\n            modulos.Add(3600 * 24 * 7);\n            modulos.Add(3600 * 24 * 14);\n            return modulos;\n        }\n\n        public void SetTickModulosForFrameRate(float frameRate)\n        {\n            var modulos = GetTickModulosForFrameRate(frameRate);\n            SetTickModulos(modulos.ToArray());\n        }\n\n        public void SetRanges(float minValue, float maxValue, float minPixel, float maxPixel)\n        {\n            m_MinValue = minValue;\n            m_MaxValue = maxValue;\n            m_PixelRange = maxPixel - minPixel;\n        }\n\n        public float[] GetTicksAtLevel(int level, bool excludeTicksFromHigherlevels)\n        {\n            if (level < 0)\n                return new float[0] {};\n\n            m_TickList.Clear();\n            GetTicksAtLevel(level, excludeTicksFromHigherlevels, m_TickList);\n            return m_TickList.ToArray();\n        }\n\n        public void GetTicksAtLevel(int level, bool excludeTicksFromHigherlevels, List<float> list)\n        {\n            if (list == null)\n                throw new System.ArgumentNullException(\"list\");\n\n            int l = Mathf.Clamp(m_SmallestTick + level, 0, m_TickModulos.Length - 1);\n            int startTick = Mathf.FloorToInt(m_MinValue / m_TickModulos[l]);\n            int endTick = Mathf.CeilToInt(m_MaxValue / m_TickModulos[l]);\n            for (int i = startTick; i <= endTick; i++)\n            {\n                // Return if tick mark is at same time as larger tick mark\n                if (excludeTicksFromHigherlevels\n                    && l < m_BiggestTick\n                    && (i % Mathf.RoundToInt(m_TickModulos[l + 1] / m_TickModulos[l]) == 0))\n                    continue;\n                list.Add(i * m_TickModulos[l]);\n            }\n        }\n\n        public float GetStrengthOfLevel(int level)\n        {\n            return m_TickStrengths[m_SmallestTick + level];\n        }\n\n        public float GetPeriodOfLevel(int level)\n        {\n            return m_TickModulos[Mathf.Clamp(m_SmallestTick + level, 0, m_TickModulos.Length - 1)];\n        }\n\n        public int GetLevelWithMinSeparation(float pixelSeparation)\n        {\n            for (int i = 0; i < m_TickModulos.Length; i++)\n            {\n                // How far apart (in pixels) these modulo ticks are spaced:\n                float tickSpacing = m_TickModulos[i] * m_PixelRange / (m_MaxValue - m_MinValue);\n                if (tickSpacing >= pixelSeparation)\n                    return i - m_SmallestTick;\n            }\n            return -1;\n        }\n\n        public void SetTickStrengths(float tickMinSpacing, float tickMaxSpacing, bool sqrt)\n        {\n            if (m_TickStrengths == null || m_TickStrengths.Length != m_TickModulos.Length)\n            {\n                m_TickStrengths = new float[m_TickModulos.Length];\n            }\n\n            m_SmallestTick = 0;\n            m_BiggestTick = m_TickModulos.Length - 1;\n\n            // Find the strength for each modulo number tick marker\n            for (int i = m_TickModulos.Length - 1; i >= 0; i--)\n            {\n                // How far apart (in pixels) these modulo ticks are spaced:\n                float tickSpacing = m_TickModulos[i] * m_PixelRange / (m_MaxValue - m_MinValue);\n\n                // Calculate the strength of the tick markers based on the spacing:\n                m_TickStrengths[i] =\n                    (tickSpacing - tickMinSpacing) / (tickMaxSpacing - tickMinSpacing);\n\n                // Beyond kTickHeightFatThreshold the ticks don't get any bigger or fatter,\n                // so ignore them, since they are already covered by smalle modulo ticks anyway:\n                if (m_TickStrengths[i] >= 1) m_BiggestTick = i;\n\n                // Do not show tick markers less than 3 pixels apart:\n                if (tickSpacing <= tickMinSpacing) { m_SmallestTick = i; break; }\n            }\n\n            // Use sqrt on actively used modulo number tick markers\n            for (int i = m_SmallestTick; i <= m_BiggestTick; i++)\n            {\n                m_TickStrengths[i] = Mathf.Clamp01(m_TickStrengths[i]);\n                if (sqrt)\n                    m_TickStrengths[i] = Mathf.Sqrt(m_TickStrengths[i]);\n            }\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Animation/TickStyle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    internal class TickStyle\n    {\n        public EditorGUIUtility.SkinnedColor tickColor = new EditorGUIUtility.SkinnedColor(new Color(0.0f, 0.0f, 0.0f, 0.2f), new Color(.45f, .45f, .45f, 0.2f)); // color and opacity of ticks\n        public EditorGUIUtility.SkinnedColor labelColor = new EditorGUIUtility.SkinnedColor(new Color(0.0f, 0.0f, 0.0f, 0.32f), new Color(0.8f, 0.8f, 0.8f, 0.32f)); // color and opacity of tick labels\n        public int distMin = 10; // min distance between ticks before they disappear completely\n        public int distFull = 80; // distance between ticks where they gain full strength\n        public int distLabel = 50; // min distance between tick labels\n        public bool stubs = false; // draw ticks as stubs or as full lines?\n        public bool centerLabel = false; // center label on tick lines\n        public string unit = \"\"; // unit to write after the number\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/TimeArea.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Globalization;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    class TimeArea : ZoomableArea\n    {\n        [SerializeField] private TickHandler m_HTicks;\n\n        public TickHandler hTicks\n        {\n            get { return m_HTicks; }\n            set { m_HTicks = value; }\n        }\n\n        [SerializeField] private TickHandler m_VTicks;\n\n        static readonly List<float> s_TickCache = new List<float>(1000);\n\n        public TickHandler vTicks\n        {\n            get { return m_VTicks; }\n            set { m_VTicks = value; }\n        }\n\n        internal const int kTickRulerDistMin = 3\n        ;     // min distance between ruler tick marks before they disappear completely\n\n        internal const int kTickRulerDistFull = 80; // distance between ruler tick marks where they gain full strength\n        internal const int kTickRulerDistLabel = 40; // min distance between ruler tick mark labels\n        internal const float kTickRulerHeightMax = 0.7f; // height of the ruler tick marks when they are highest\n\n        internal const float kTickRulerFatThreshold = 0.5f\n        ;     // size of ruler tick marks at which they begin getting fatter\n\n        public enum TimeFormat\n        {\n            None, // Unformatted time\n            TimeFrame, // Time:Frame\n            Frame // Integer frame\n        }\n\n        class Styles2\n        {\n            public GUIStyle timelineTick = \"AnimationTimelineTick\";\n            public GUIStyle playhead = \"AnimationPlayHead\";\n        }\n\n        static Styles2 timeAreaStyles;\n\n        static void InitStyles()\n        {\n            if (timeAreaStyles == null)\n                timeAreaStyles = new Styles2();\n        }\n\n        public TimeArea(bool minimalGUI) : this(minimalGUI, true, true) {}\n\n        public TimeArea(bool minimalGUI, bool enableSliderZoom) : this(minimalGUI, enableSliderZoom, enableSliderZoom) {}\n\n        public TimeArea(bool minimalGUI, bool enableSliderZoomHorizontal, bool enableSliderZoomVertical) : base(minimalGUI, enableSliderZoomHorizontal, enableSliderZoomVertical)\n        {\n            float[] modulos = new float[]\n            {\n                0.0000001f, 0.0000005f, 0.000001f, 0.000005f, 0.00001f, 0.00005f, 0.0001f, 0.0005f,\n                0.001f, 0.005f, 0.01f, 0.05f, 0.1f, 0.5f, 1, 5, 10, 50, 100, 500,\n                1000, 5000, 10000, 50000, 100000, 500000, 1000000, 5000000, 10000000\n            };\n            hTicks = new TickHandler();\n            hTicks.SetTickModulos(modulos);\n            vTicks = new TickHandler();\n            vTicks.SetTickModulos(modulos);\n        }\n\n        public void SetTickMarkerRanges()\n        {\n            hTicks.SetRanges(shownArea.xMin, shownArea.xMax, drawRect.xMin, drawRect.xMax);\n            vTicks.SetRanges(shownArea.yMin, shownArea.yMax, drawRect.yMin, drawRect.yMax);\n        }\n\n        public void DrawMajorTicks(Rect position, float frameRate)\n        {\n            GUI.BeginGroup(position);\n            if (Event.current.type != EventType.Repaint)\n            {\n                GUI.EndGroup();\n                return;\n            }\n            InitStyles();\n\n            HandleUtility.ApplyWireMaterial();\n\n            SetTickMarkerRanges();\n            hTicks.SetTickStrengths(kTickRulerDistMin, kTickRulerDistFull, true);\n\n            Color tickColor = timeAreaStyles.timelineTick.normal.textColor;\n            tickColor.a = 0.1f;\n\n            if (Application.platform == RuntimePlatform.WindowsEditor)\n                GL.Begin(GL.QUADS);\n            else\n                GL.Begin(GL.LINES);\n\n            // Draw tick markers of various sizes\n            Rect theShowArea = shownArea;\n            for (int l = 0; l < hTicks.tickLevels; l++)\n            {\n                float strength = hTicks.GetStrengthOfLevel(l) * .9f;\n                if (strength > kTickRulerFatThreshold)\n                {\n                    s_TickCache.Clear();\n                    hTicks.GetTicksAtLevel(l, true, s_TickCache);\n                    for (int i = 0; i < s_TickCache.Count; i++)\n                    {\n                        if (s_TickCache[i] < 0) continue;\n                        int frame = Mathf.RoundToInt(s_TickCache[i] * frameRate);\n                        float x = FrameToPixel(frame, frameRate, position, theShowArea);\n                        // Draw line\n                        DrawVerticalLineFast(x, 0.0f, position.height, tickColor);\n                    }\n                }\n            }\n\n            GL.End();\n            GUI.EndGroup();\n        }\n\n        public void TimeRuler(Rect position, float frameRate)\n        {\n            TimeRuler(position, frameRate, true, false, 1f, TimeFormat.TimeFrame);\n        }\n\n        public void TimeRuler(Rect position, float frameRate, bool labels, bool useEntireHeight, float alpha,\n            TimeFormat timeFormat)\n        {\n            Color backupCol = GUI.color;\n            GUI.BeginGroup(position);\n            InitStyles();\n\n            HandleUtility.ApplyWireMaterial();\n\n            Color tempBackgroundColor = GUI.backgroundColor;\n\n            SetTickMarkerRanges();\n            hTicks.SetTickStrengths(kTickRulerDistMin, kTickRulerDistFull, true);\n\n            Color baseColor = timeAreaStyles.timelineTick.normal.textColor;\n            baseColor.a = 0.75f * alpha;\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                if (Application.platform == RuntimePlatform.WindowsEditor)\n                    GL.Begin(GL.QUADS);\n                else\n                    GL.Begin(GL.LINES);\n\n                // Draw tick markers of various sizes\n\n                Rect cachedShowArea = shownArea;\n                for (int l = 0; l < hTicks.tickLevels; l++)\n                {\n                    float strength = hTicks.GetStrengthOfLevel(l) * .9f;\n                    s_TickCache.Clear();\n                    hTicks.GetTicksAtLevel(l, true, s_TickCache);\n                    for (int i = 0; i < s_TickCache.Count; i++)\n                    {\n                        if (s_TickCache[i] < hRangeMin || s_TickCache[i] > hRangeMax)\n                            continue;\n                        int frame = Mathf.RoundToInt(s_TickCache[i] * frameRate);\n\n                        float height = useEntireHeight\n                            ? position.height\n                            : position.height * Mathf.Min(1, strength) * kTickRulerHeightMax;\n                        float x = FrameToPixel(frame, frameRate, position, cachedShowArea);\n\n                        // Draw line\n                        DrawVerticalLineFast(x, position.height - height + 0.5f, position.height - 0.5f,\n                            new Color(1, 1, 1, strength / kTickRulerFatThreshold) * baseColor);\n                    }\n                }\n\n                GL.End();\n            }\n\n            if (labels)\n            {\n                // Draw tick labels\n                int labelLevel = hTicks.GetLevelWithMinSeparation(kTickRulerDistLabel);\n                s_TickCache.Clear();\n                hTicks.GetTicksAtLevel(labelLevel, false, s_TickCache);\n                for (int i = 0; i < s_TickCache.Count; i++)\n                {\n                    if (s_TickCache[i] < hRangeMin || s_TickCache[i] > hRangeMax)\n                        continue;\n\n                    int frame = Mathf.RoundToInt(s_TickCache[i] * frameRate);\n                    // Important to take floor of positions of GUI stuff to get pixel correct alignment of\n                    // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time.\n\n                    float labelpos = Mathf.Floor(FrameToPixel(frame, frameRate, position));\n                    string label = FormatTickTime(s_TickCache[i], frameRate, timeFormat);\n                    GUI.Label(new Rect(labelpos + 3, -1, 40, 20), label, timeAreaStyles.timelineTick);\n                }\n            }\n            GUI.EndGroup();\n\n            GUI.backgroundColor = tempBackgroundColor;\n            GUI.color = backupCol;\n        }\n\n        public static void DrawPlayhead(float x, float yMin, float yMax, float thickness, float alpha)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n            InitStyles();\n            float halfThickness = thickness * 0.5f;\n            Color lineColor = timeAreaStyles.playhead.normal.textColor.AlphaMultiplied(alpha);\n            if (thickness > 1f)\n            {\n                Rect labelRect = Rect.MinMaxRect(x - halfThickness, yMin, x + halfThickness, yMax);\n                EditorGUI.DrawRect(labelRect, lineColor);\n            }\n            else\n            {\n                DrawVerticalLine(x, yMin, yMax, lineColor);\n            }\n        }\n\n        public static void DrawVerticalLine(float x, float minY, float maxY, Color color)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            Color backupCol = Handles.color;\n\n            HandleUtility.ApplyWireMaterial();\n            if (Application.platform == RuntimePlatform.WindowsEditor)\n                GL.Begin(GL.QUADS);\n            else\n                GL.Begin(GL.LINES);\n            DrawVerticalLineFast(x, minY, maxY, color);\n            GL.End();\n\n            Handles.color = backupCol;\n        }\n\n        public static void DrawVerticalLineFast(float x, float minY, float maxY, Color color)\n        {\n            if (Application.platform == RuntimePlatform.WindowsEditor)\n            {\n                GL.Color(color);\n                GL.Vertex(new Vector3(x - 0.5f, minY, 0));\n                GL.Vertex(new Vector3(x + 0.5f, minY, 0));\n                GL.Vertex(new Vector3(x + 0.5f, maxY, 0));\n                GL.Vertex(new Vector3(x - 0.5f, maxY, 0));\n            }\n            else\n            {\n                GL.Color(color);\n                GL.Vertex(new Vector3(x, minY, 0));\n                GL.Vertex(new Vector3(x, maxY, 0));\n            }\n        }\n\n        public enum TimeRulerDragMode\n        {\n            None,\n            Start,\n            End,\n            Dragging,\n            Cancel\n        }\n\n        static float s_OriginalTime;\n        static float s_PickOffset;\n\n        public TimeRulerDragMode BrowseRuler(Rect position, ref float time, float frameRate, bool pickAnywhere,\n            GUIStyle thumbStyle)\n        {\n            int id = GUIUtility.GetControlID(3126789, FocusType.Passive);\n            return BrowseRuler(position, id, ref time, frameRate, pickAnywhere, thumbStyle);\n        }\n\n        public TimeRulerDragMode BrowseRuler(Rect position, int id, ref float time, float frameRate, bool pickAnywhere,\n            GUIStyle thumbStyle)\n        {\n            Event evt = Event.current;\n            Rect pickRect = position;\n            if (time != -1)\n            {\n                pickRect.x = Mathf.Round(TimeToPixel(time, position)) - thumbStyle.overflow.left;\n                pickRect.width = thumbStyle.fixedWidth + thumbStyle.overflow.horizontal;\n            }\n\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.Repaint:\n                    if (time != -1)\n                    {\n                        bool hover = position.Contains(evt.mousePosition);\n                        pickRect.x += thumbStyle.overflow.left;\n                        thumbStyle.Draw(pickRect, id == GUIUtility.hotControl, hover || id == GUIUtility.hotControl,\n                            false, false);\n                    }\n                    break;\n                case EventType.MouseDown:\n                    if (pickRect.Contains(evt.mousePosition))\n                    {\n                        GUIUtility.hotControl = id;\n                        s_PickOffset = evt.mousePosition.x - TimeToPixel(time, position);\n                        evt.Use();\n                        return TimeRulerDragMode.Start;\n                    }\n                    else if (pickAnywhere && position.Contains(evt.mousePosition))\n                    {\n                        GUIUtility.hotControl = id;\n\n                        float newT = SnapTimeToWholeFPS(PixelToTime(evt.mousePosition.x, position), frameRate);\n                        s_OriginalTime = time;\n                        if (newT != time)\n                            GUI.changed = true;\n                        time = newT;\n                        s_PickOffset = 0;\n                        evt.Use();\n                        return TimeRulerDragMode.Start;\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        float newT = SnapTimeToWholeFPS(PixelToTime(evt.mousePosition.x - s_PickOffset, position),\n                            frameRate);\n                        if (newT != time)\n                            GUI.changed = true;\n                        time = newT;\n\n                        evt.Use();\n                        return TimeRulerDragMode.Dragging;\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                        return TimeRulerDragMode.End;\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (GUIUtility.hotControl == id && evt.keyCode == KeyCode.Escape)\n                    {\n                        if (time != s_OriginalTime)\n                            GUI.changed = true;\n                        time = s_OriginalTime;\n\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                        return TimeRulerDragMode.Cancel;\n                    }\n                    break;\n            }\n            return TimeRulerDragMode.None;\n        }\n\n        private float FrameToPixel(float i, float frameRate, Rect rect, Rect theShownArea)\n        {\n            return (i - theShownArea.xMin * frameRate) * rect.width / (theShownArea.width * frameRate);\n        }\n\n        public float FrameToPixel(float i, float frameRate, Rect rect)\n        {\n            return FrameToPixel(i, frameRate, rect, shownArea);\n        }\n\n        public float TimeField(Rect rect, int id, float time, float frameRate, TimeFormat timeFormat)\n        {\n            if (timeFormat == TimeFormat.None)\n            {\n                float newTime = EditorGUI.DoFloatField(\n                    EditorGUI.s_RecycledEditor,\n                    rect,\n                    new Rect(0, 0, 0, 0),\n                    id,\n                    time,\n                    EditorGUI.kFloatFieldFormatString,\n                    EditorStyles.numberField,\n                    false);\n\n                return SnapTimeToWholeFPS(newTime, frameRate);\n            }\n\n            if (timeFormat == TimeFormat.Frame)\n            {\n                int frame = Mathf.RoundToInt(time * frameRate);\n\n                int newFrame = EditorGUI.DoIntField(\n                    EditorGUI.s_RecycledEditor,\n                    rect,\n                    new Rect(0, 0, 0, 0),\n                    id,\n                    frame,\n                    EditorGUI.kIntFieldFormatString,\n                    EditorStyles.numberField,\n                    false,\n                    0f);\n\n                return (float)newFrame / frameRate;\n            }\n            else // if (timeFormat == TimeFormat.TimeFrame)\n            {\n                string str = FormatTime(time, frameRate, TimeFormat.TimeFrame);\n\n                string allowedCharacters = \"0123456789.,:\";\n\n                bool changed;\n                str = EditorGUI.DoTextField(EditorGUI.s_RecycledEditor, id, rect, str, EditorStyles.numberField,\n                    allowedCharacters, out changed, false, false, false);\n\n                if (changed)\n                {\n                    if (GUIUtility.keyboardControl == id)\n                    {\n                        GUI.changed = true;\n\n                        // Make sure that comma & period are interchangable.\n                        str = str.Replace(',', '.');\n\n                        // format is time:frame\n                        int index = str.IndexOf(':');\n                        if (index >= 0)\n                        {\n                            string timeStr = str.Substring(0, index);\n                            string frameStr = str.Substring(index + 1);\n\n                            int timeValue, frameValue;\n                            if (int.TryParse(timeStr, out timeValue) && int.TryParse(frameStr, out frameValue))\n                            {\n                                float newTime = (float)timeValue + (float)frameValue / frameRate;\n                                return newTime;\n                            }\n                        }\n                        // format is floating time value.\n                        else\n                        {\n                            float newTime;\n                            if (float.TryParse(str, out newTime))\n                            {\n                                return SnapTimeToWholeFPS(newTime, frameRate);\n                            }\n                        }\n                    }\n                }\n            }\n\n            return time;\n        }\n\n        public float ValueField(Rect rect, int id, float value)\n        {\n            float newValue = EditorGUI.DoFloatField(\n                EditorGUI.s_RecycledEditor,\n                rect,\n                new Rect(0, 0, 0, 0),\n                id,\n                value,\n                EditorGUI.kFloatFieldFormatString,\n                EditorStyles.numberField,\n                false);\n\n            return newValue;\n        }\n\n        public string FormatTime(float time, float frameRate, TimeFormat timeFormat)\n        {\n            if (timeFormat == TimeFormat.None)\n            {\n                int hDecimals;\n                if (frameRate != 0)\n                    hDecimals = MathUtils.GetNumberOfDecimalsForMinimumDifference(1 / frameRate);\n                else\n                    hDecimals = MathUtils.GetNumberOfDecimalsForMinimumDifference(shownArea.width / drawRect.width);\n\n                return time.ToString(\"N\" + hDecimals, CultureInfo.InvariantCulture.NumberFormat);\n            }\n\n            int frame = Mathf.RoundToInt(time * frameRate);\n\n            if (timeFormat == TimeFormat.TimeFrame)\n            {\n                int frameDigits = frameRate != 0 ? ((int)frameRate - 1).ToString().Length : 1;\n                string sign = string.Empty;\n                if (frame < 0)\n                {\n                    sign = \"-\";\n                    frame = -frame;\n                }\n                return sign + (frame / (int)frameRate) + \":\" +\n                    (frame % frameRate).ToString().PadLeft(frameDigits, '0');\n            }\n            else\n            {\n                return frame.ToString();\n            }\n        }\n\n        public virtual string FormatTickTime(float time, float frameRate, TimeFormat timeFormat)\n        {\n            return FormatTime(time, frameRate, timeFormat);\n        }\n\n        public string FormatValue(float value)\n        {\n            int vDecimals = MathUtils.GetNumberOfDecimalsForMinimumDifference(shownArea.height / drawRect.height);\n            return value.ToString(\"N\" + vDecimals, CultureInfo.InvariantCulture.NumberFormat);\n        }\n\n        public float SnapTimeToWholeFPS(float time, float frameRate)\n        {\n            if (frameRate == 0)\n                return time;\n            return Mathf.Round(time * frameRate) / frameRate;\n        }\n\n        public void DrawTimeOnSlider(float time, Color c, float maxTime, float leftSidePadding = 0, float rightSidePadding = 0)\n        {\n            const float maxTimeFudgeFactor = 3;\n            if (!hSlider)\n                return;\n\n            if (styles.horizontalScrollbar == null)\n                styles.InitGUIStyles(false, allowSliderZoomHorizontal, allowSliderZoomVertical);\n\n            var inMin = TimeToPixel(0, rect); // Assume 0 minTime\n            var inMax = TimeToPixel(maxTime, rect);\n            var outMin = TimeToPixel(shownAreaInsideMargins.xMin, rect) + styles.horizontalScrollbarLeftButton.fixedWidth + leftSidePadding;\n            var outMax = TimeToPixel(shownAreaInsideMargins.xMax, rect) - (styles.horizontalScrollbarRightButton.fixedWidth + rightSidePadding);\n            var x = (TimeToPixel(time, rect) - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;\n            if (x > rect.xMax - (styles.horizontalScrollbarLeftButton.fixedWidth + leftSidePadding + maxTimeFudgeFactor))\n                return;\n            var inset = styles.sliderWidth - styles.visualSliderWidth;\n            var otherInset = (vSlider && hSlider) ? inset : 0;\n            var hRangeSliderRect = new Rect(drawRect.x + 1, drawRect.yMax - inset, drawRect.width - otherInset, styles.sliderWidth);\n\n            var p1 = new Vector2(x, hRangeSliderRect.yMin);\n            var p2 = new Vector2(x, hRangeSliderRect.yMax);\n\n            var lineRect = Rect.MinMaxRect(p1.x - 0.5f, p1.y, p2.x + 0.5f, p2.y);\n            EditorGUI.DrawRect(lineRect, c);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Animation/TransitionPreview.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing UnityEditor.Animations;\n\nnamespace UnityEditor\n{\n    internal class TransitionPreview\n    {\n        private AvatarPreview m_AvatarPreview;\n        private TimelineControl m_Timeline;\n\n        private AnimatorController m_Controller;\n        private AnimatorStateMachine m_StateMachine;\n        private List<Vector2> m_ParameterMinMax = new List<Vector2>();\n        private List<ParameterInfo> m_ParameterInfoList;\n\n        private AnimatorStateTransition m_RefTransition;\n        private TransitionInfo m_RefTransitionInfo = new TransitionInfo();\n        private AnimatorStateTransition m_Transition;\n        private AnimatorState m_SrcState;\n        private AnimatorState m_DstState;\n        private AnimatorState m_RefSrcState;\n        private AnimatorState m_RefDstState;\n\n\n        private Motion m_SrcMotion;\n        private Motion m_DstMotion;\n\n        private bool m_ShowBlendValue = false;\n\n        private bool m_MustResample = true;\n        private bool m_MustSampleMotions = false;\n        private bool m_MustResetParameterInfoList = false;\n        public bool mustResample { set { m_MustResample = value; } get { return m_MustResample; } }\n        private float m_LastEvalTime = -1.0f;\n        private bool m_IsResampling = false;\n\n        private AvatarMask m_LayerMask;\n        private int m_LayerIndex;\n\n        private bool m_ValidTransition = true;\n\n        class ParameterInfo\n        {\n            public string m_Name;\n            public float m_Value;\n        }\n\n        int FindParameterInfo(List<ParameterInfo> parameterInfoList, string name)\n        {\n            int ret = -1;\n\n            for (int i = 0; i < parameterInfoList.Count && ret == -1; i++)\n            {\n                if (parameterInfoList[i].m_Name == name)\n                {\n                    ret = i;\n                }\n            }\n\n            return ret;\n        }\n\n        class TransitionInfo\n        {\n            AnimatorState m_SrcState;\n            AnimatorState m_DstState;\n            float m_TransitionDuration;\n            float m_TransitionOffset;\n            float m_ExitTime;\n\n            public bool IsEqual(TransitionInfo info)\n            {\n                return m_SrcState == info.m_SrcState &&\n                    m_DstState == info.m_DstState &&\n                    Mathf.Approximately(m_TransitionDuration, info.m_TransitionDuration) &&\n                    Mathf.Approximately(m_TransitionOffset, info.m_TransitionOffset) &&\n                    Mathf.Approximately(m_ExitTime, info.m_ExitTime);\n            }\n\n            public TransitionInfo()\n            {\n                Init();\n            }\n\n            void Init()\n            {\n                m_SrcState = null;\n                m_DstState = null;\n                m_TransitionDuration = 0.0f;\n                m_TransitionOffset = 0.0f;\n                m_ExitTime = 0.5f;\n            }\n\n            public void Set(AnimatorStateTransition transition, AnimatorState srcState, AnimatorState dstState)\n            {\n                if (transition != null)\n                {\n                    m_SrcState = srcState;\n                    m_DstState = dstState;\n                    m_TransitionDuration = transition.duration;\n                    m_TransitionOffset = transition.offset;\n                    m_ExitTime = transition.exitTime;\n                }\n                else\n                {\n                    Init();\n                }\n            }\n        }\n\n\n        private void CopyStateForPreview(AnimatorState src, ref AnimatorState dst)\n        {\n            dst.iKOnFeet = src.iKOnFeet;\n            dst.speed = src.speed;\n            dst.mirror = src.mirror;\n\n            dst.motion = src.motion;\n        }\n\n        private void CopyTransitionForPreview(AnimatorStateTransition src, ref AnimatorStateTransition dst)\n        {\n            if (src != null)\n            {\n                dst.duration = src.duration;\n                dst.offset = src.offset;\n                dst.exitTime = src.exitTime;\n                dst.hasFixedDuration = src.hasFixedDuration;\n            }\n        }\n\n        float m_LeftStateWeightA = 0;\n        float m_LeftStateWeightB = 1;\n        float m_LeftStateTimeA = 0;\n        float m_LeftStateTimeB = 1;\n\n        float m_RightStateWeightA = 0;\n        float m_RightStateWeightB = 1;\n        float m_RightStateTimeA = 0;\n        float m_RightStateTimeB = 1;\n\n        List<TimelineControl.PivotSample> m_SrcPivotList = new List<TimelineControl.PivotSample>();\n        List<TimelineControl.PivotSample> m_DstPivotList = new List<TimelineControl.PivotSample>();\n\n        private bool MustResample(TransitionInfo info)\n        {\n            bool isInPlayback = m_AvatarPreview != null && m_AvatarPreview.Animator != null && m_AvatarPreview.Animator.recorderMode == AnimatorRecorderMode.Playback;\n            return !isInPlayback || mustResample || !info.IsEqual(m_RefTransitionInfo);\n        }\n\n        private void WriteParametersInController()\n        {\n            if (m_Controller)\n            {\n                int parameterCount = m_Controller.parameters.Length;\n\n                for (int i = 0; i < parameterCount; i++)\n                {\n                    string parameterName = m_Controller.parameters[i].name;\n\n                    int parameterInfoIndex = FindParameterInfo(m_ParameterInfoList, parameterName);\n\n                    if (parameterInfoIndex != -1)\n                    {\n                        m_AvatarPreview.Animator.SetFloat(parameterName, m_ParameterInfoList[parameterInfoIndex].m_Value);\n                    }\n                }\n            }\n        }\n\n        private void ResampleTransition(AnimatorStateTransition transition, AvatarMask layerMask, TransitionInfo info, Animator previewObject)\n        {\n            m_IsResampling = true;\n            m_MustResample = false;\n            m_ValidTransition = true;\n\n            bool resetTimeSettings = m_RefTransition != transition;\n\n            m_RefTransition = transition;\n            m_RefTransitionInfo = info;\n\n            m_LayerMask = layerMask;\n\n            if (m_AvatarPreview != null)\n            {\n                m_AvatarPreview.OnDisable();\n                m_AvatarPreview = null;\n            }\n\n            ClearController();\n\n            Motion sourceStateMotion = m_RefSrcState.motion;\n            Init(previewObject, sourceStateMotion != null ? sourceStateMotion : m_RefDstState.motion);\n\n            if (m_Controller == null)  //  did not create controller\n            {\n                m_IsResampling = false;\n                return;\n            }\n\n            // since transform might change during sampling, and could alter the default valuesarray, and break recording\n            m_AvatarPreview.Animator.allowConstantClipSamplingOptimization = false;\n\n            // sample all frames\n\n            m_StateMachine.defaultState = m_DstState;\n            m_Transition.mute = true;\n            AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);\n            m_AvatarPreview.Animator.Update(0.00001f);\n            WriteParametersInController();\n            m_AvatarPreview.Animator.SetLayerWeight(m_LayerIndex, 1);\n\n            float nextStateDuration = m_AvatarPreview.Animator.GetCurrentAnimatorStateInfo(m_LayerIndex).length;\n\n            m_StateMachine.defaultState = m_SrcState;\n            m_Transition.mute = false;\n            AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);\n            m_AvatarPreview.Animator.Update(0.00001f);\n            WriteParametersInController();\n            m_AvatarPreview.Animator.SetLayerWeight(m_LayerIndex, 1);\n\n            float currentStateDuration = m_AvatarPreview.Animator.GetCurrentAnimatorStateInfo(m_LayerIndex).length;\n\n            if (m_LayerIndex > 0)\n                m_AvatarPreview.Animator.stabilizeFeet = false;\n            float maxDuration = (currentStateDuration * m_RefTransition.exitTime) + (m_Transition.duration * (m_RefTransition.hasFixedDuration ? 1.0f : currentStateDuration)) + nextStateDuration;\n\n            // case 546812 disable previewer if the duration is too big, otherwise it hang Unity. 2000.0f is an arbitrary choice, it can be increase if needed.\n            // in some case we got a m_Transition.duration == Infinity, bail out before unity hang.\n            if (maxDuration > 2000.0f)\n            {\n                Debug.LogWarning(\"Transition duration is longer than 2000 second, Disabling previewer.\");\n                m_ValidTransition = false;\n                m_IsResampling = false;\n                return;\n            }\n\n            float effectiveCurrentStatetime = m_RefTransition.exitTime > 0 ? currentStateDuration * m_RefTransition.exitTime : currentStateDuration;\n            // We want 30 samples/sec, maxed at 300 sample for very long state, and very short animation like 1 frame should at least get 5 sample\n            float currentStateStepTime = effectiveCurrentStatetime > 0 ? Mathf.Min(Mathf.Max(effectiveCurrentStatetime / 300.0f, 1.0f / 30.0f), effectiveCurrentStatetime / 5.0f) :  1.0f / 30.0f;\n            float nextStateStepTime = nextStateDuration > 0 ? Mathf.Min(Mathf.Max(nextStateDuration / 300.0f, 1.0f / 30.0f), nextStateDuration / 5.0f) : 1.0f / 30.0f;\n\n            currentStateStepTime = Mathf.Max(currentStateStepTime, maxDuration / 600.0f);\n            nextStateStepTime = Mathf.Max(nextStateStepTime, maxDuration / 600.0f);\n\n            float stepTime = currentStateStepTime;\n\n            float currentTime = 0.0f;\n\n            bool hasStarted = false;\n            bool hasTransitioned = false;\n            bool hasFinished = false;\n\n            //For transitions with exit time == 0, skip to end of clip so transition happens on first frame\n            if (m_RefTransition.exitTime == 0)\n            {\n                m_AvatarPreview.Animator.CrossFade(0, 0f, 0, 0.9f);\n            }\n            m_AvatarPreview.Animator.StartRecording(-1);\n\n            m_AvatarPreview.Animator.Update(0.0f);\n            AnimatorStateInfo currentState = m_AvatarPreview.Animator.GetCurrentAnimatorStateInfo(m_LayerIndex);\n            m_LeftStateWeightA = currentState.normalizedTime;\n            m_LeftStateTimeA = currentTime;\n            while (!hasFinished)\n            {\n                m_AvatarPreview.Animator.Update(stepTime);\n\n                currentState = m_AvatarPreview.Animator.GetCurrentAnimatorStateInfo(m_LayerIndex);\n                currentTime += stepTime;\n\n                if (!hasStarted)\n                {\n                    m_LeftStateWeightB = currentState.normalizedTime;\n                    m_LeftStateTimeB = currentTime;\n\n                    hasStarted = true;\n                }\n\n                if (hasTransitioned && currentTime >= maxDuration)\n                {\n                    hasFinished = true;\n                }\n\n                if (!hasTransitioned && currentState.IsName(m_DstState.name))\n                {\n                    m_RightStateWeightA = currentState.normalizedTime;\n                    m_RightStateTimeA = currentTime;\n\n                    hasTransitioned = true;\n                }\n\n                if (!hasTransitioned)\n                {\n                    m_LeftStateWeightB = currentState.normalizedTime;\n                    m_LeftStateTimeB = currentTime;\n                }\n\n                if (hasTransitioned || hasFinished)\n                {\n                    m_RightStateWeightB = currentState.normalizedTime;\n                    m_RightStateTimeB = currentTime;\n                }\n\n                if (m_AvatarPreview.Animator.IsInTransition(m_LayerIndex))\n                {\n                    stepTime = nextStateStepTime;\n                }\n            }\n\n            float endTime = currentTime;\n            m_AvatarPreview.Animator.StopRecording();\n\n            if (Mathf.Approximately(m_LeftStateWeightB, m_LeftStateWeightA) || Mathf.Approximately(m_RightStateWeightB,  m_RightStateWeightA))\n            {\n                Debug.LogWarning(\"Difference in effective length between states is too big. Transition preview will be disabled.\");\n                m_ValidTransition = false;\n                m_IsResampling = false;\n                return;\n            }\n\n            float leftDuration =  (m_LeftStateTimeB - m_LeftStateTimeA) / (m_LeftStateWeightB - m_LeftStateWeightA);\n            float rightDuration = (m_RightStateTimeB - m_RightStateTimeA) / (m_RightStateWeightB - m_RightStateWeightA);\n\n            // Ensure step times make sense based on these timings\n            // If step time is too small, the samping will take too long\n            currentStateStepTime = Mathf.Max(currentStateStepTime, leftDuration / 600.0f);\n            nextStateStepTime = Mathf.Max(nextStateStepTime, rightDuration / 600.0f);\n\n            if (m_MustSampleMotions)\n            {\n                // Do this as infrequently as possible\n                m_MustSampleMotions = false;\n                m_SrcPivotList.Clear();\n                m_DstPivotList.Clear();\n\n                stepTime = nextStateStepTime;\n                m_StateMachine.defaultState  = m_DstState;\n                m_Transition.mute = true;\n                AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);\n                m_AvatarPreview.Animator.Update(0.0f);\n                m_AvatarPreview.Animator.SetLayerWeight(m_LayerIndex, 1);\n                m_AvatarPreview.Animator.Update(0.0000001f);\n                WriteParametersInController();\n                currentTime = 0.0f;\n                while (currentTime <= rightDuration)\n                {\n                    TimelineControl.PivotSample sample = new TimelineControl.PivotSample();\n                    sample.m_Time = currentTime;\n                    sample.m_Weight = m_AvatarPreview.Animator.pivotWeight;\n                    m_DstPivotList.Add(sample);\n                    m_AvatarPreview.Animator.Update(stepTime * 2);\n                    currentTime += stepTime * 2;\n                }\n\n                stepTime = currentStateStepTime;\n                m_StateMachine.defaultState = m_SrcState;\n                m_Transition.mute = true;\n                AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);\n                m_AvatarPreview.Animator.Update(0.0000001f);\n                WriteParametersInController();\n                m_AvatarPreview.Animator.SetLayerWeight(m_LayerIndex, 1);\n                currentTime = 0.0f;\n                while (currentTime <= leftDuration)\n                {\n                    TimelineControl.PivotSample sample = new TimelineControl.PivotSample();\n                    sample.m_Time = currentTime;\n                    sample.m_Weight = m_AvatarPreview.Animator.pivotWeight;\n                    m_SrcPivotList.Add(sample);\n                    m_AvatarPreview.Animator.Update(stepTime * 2);\n                    currentTime += stepTime * 2;\n                }\n\n                m_Transition.mute = false;\n                AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);\n                m_AvatarPreview.Animator.Update(0.0000001f);\n                WriteParametersInController();\n            }\n\n            m_Timeline.StopTime = m_AvatarPreview.timeControl.stopTime = endTime;\n            m_AvatarPreview.timeControl.currentTime = m_Timeline.Time;\n            if (resetTimeSettings)\n            {\n                m_Timeline.Time = m_Timeline.StartTime = m_AvatarPreview.timeControl.currentTime = m_AvatarPreview.timeControl.startTime = 0;\n                m_Timeline.ResetRange();\n            }\n\n            m_AvatarPreview.Animator.StartPlayback();\n\n            m_AvatarPreview.Animator.playbackTime = 0f;\n            m_AvatarPreview.Animator.Update(0f);\n            m_AvatarPreview.ResetPreviewFocus();\n\n            m_IsResampling = false;\n        }\n\n        public void SetTransition(AnimatorStateTransition transition, AnimatorState sourceState, AnimatorState destinationState, AnimatorControllerLayer srcLayer, Animator previewObject)\n        {\n            m_RefSrcState = sourceState;\n            m_MustResetParameterInfoList = m_RefDstState != destinationState;\n\n            m_RefDstState = destinationState;\n            TransitionInfo info = new TransitionInfo();\n            info.Set(transition, sourceState, destinationState);\n\n            if (MustResample(info))\n            {\n                ResampleTransition(transition, srcLayer.avatarMask, info, previewObject);\n            }\n        }\n\n        private void OnPreviewAvatarChanged()\n        {\n            m_RefTransitionInfo = new TransitionInfo();\n            ClearController();\n            CreateController();\n            CreateParameterInfoList();\n        }\n\n        void ClearController()\n        {\n            if (m_AvatarPreview != null && m_AvatarPreview.Animator != null)\n                AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, null);\n\n            Object.DestroyImmediate(m_Controller);\n            Object.DestroyImmediate(m_SrcState);\n            Object.DestroyImmediate(m_DstState);\n            Object.DestroyImmediate(m_Transition);\n\n            m_StateMachine = null;\n            m_Controller = null;\n            m_SrcState = null;\n            m_DstState = null;\n            m_Transition = null;\n        }\n\n        void CreateParameterInfoList()\n        {\n            m_ParameterInfoList = new List<ParameterInfo>();\n            if (m_Controller && m_Controller.parameters != null)\n            {\n                int parameterCount = m_Controller.parameters.Length;\n                for (int i = 0; i < parameterCount; i++)\n                {\n                    ParameterInfo parameterInfo = new ParameterInfo();\n                    parameterInfo.m_Name = m_Controller.parameters[i].name;\n                    m_ParameterInfoList.Add(parameterInfo);\n                }\n            }\n        }\n\n        void CreateController()\n        {\n            if (m_Controller == null && m_AvatarPreview != null && m_AvatarPreview.Animator != null && m_RefTransition != null)\n            {\n                // controller\n                m_LayerIndex = 0;\n                m_Controller = new AnimatorController();\n                m_Controller.pushUndo = false;\n                m_Controller.hideFlags = HideFlags.HideAndDontSave;\n                m_Controller.AddLayer(\"preview\");\n\n                bool isDefaultMask = true;\n\n                if (m_LayerMask != null)\n                {\n                    for (AvatarMaskBodyPart i = 0; i < AvatarMaskBodyPart.LastBodyPart && isDefaultMask; i++)\n                        if (!m_LayerMask.GetHumanoidBodyPartActive(i)) isDefaultMask = false;\n\n                    if (!isDefaultMask)\n                    {\n                        m_Controller.AddLayer(\"Additionnal\");\n                        m_LayerIndex++;\n                        AnimatorControllerLayer[] layers = m_Controller.layers;\n                        layers[m_LayerIndex].avatarMask = m_LayerMask;\n                        m_Controller.layers = layers;\n                    }\n                }\n                m_StateMachine = m_Controller.layers[m_LayerIndex].stateMachine;\n                m_StateMachine.pushUndo = false;\n                m_StateMachine.hideFlags = HideFlags.HideAndDontSave;\n\n                m_SrcMotion = m_RefSrcState.motion;\n                m_DstMotion = m_RefDstState.motion;\n\n                /// Add parameters\n                m_ParameterMinMax.Clear();\n\n                if (m_SrcMotion && m_SrcMotion is BlendTree)\n                {\n                    BlendTree leftBlendTree = m_SrcMotion as BlendTree;\n\n                    for (int i = 0; i < leftBlendTree.recursiveBlendParameterCount; i++)\n                    {\n                        string blendValueName = leftBlendTree.GetRecursiveBlendParameter(i);\n                        if (m_Controller.IndexOfParameter(blendValueName) == -1)\n                        {\n                            m_Controller.AddParameter(blendValueName, AnimatorControllerParameterType.Float);\n                            m_ParameterMinMax.Add(new Vector2(leftBlendTree.GetRecursiveBlendParameterMin(i), leftBlendTree.GetRecursiveBlendParameterMax(i)));\n                        }\n                    }\n                }\n\n                if (m_DstMotion && m_DstMotion is BlendTree)\n                {\n                    BlendTree rightBlendTree = m_DstMotion as BlendTree;\n\n                    for (int i = 0; i < rightBlendTree.recursiveBlendParameterCount; i++)\n                    {\n                        string blendValueName = rightBlendTree.GetRecursiveBlendParameter(i);\n                        int parameterIndex = m_Controller.IndexOfParameter(blendValueName);\n                        if (parameterIndex == -1)\n                        {\n                            m_Controller.AddParameter(blendValueName, AnimatorControllerParameterType.Float);\n                            m_ParameterMinMax.Add(new Vector2(rightBlendTree.GetRecursiveBlendParameterMin(i), rightBlendTree.GetRecursiveBlendParameterMax(i)));\n                        }\n                        else\n                        {\n                            m_ParameterMinMax[parameterIndex] =\n                                new Vector2(Mathf.Min(rightBlendTree.GetRecursiveBlendParameterMin(i), m_ParameterMinMax[parameterIndex][0]),\n                                    Mathf.Max(rightBlendTree.GetRecursiveBlendParameterMax(i), m_ParameterMinMax[parameterIndex][1]));\n                        }\n                    }\n                }\n\n\n                // states\n                m_SrcState = m_StateMachine.AddState(m_RefSrcState.name);\n                m_SrcState.pushUndo = false;\n                m_SrcState.hideFlags = HideFlags.HideAndDontSave;\n                m_DstState = m_StateMachine.AddState(m_RefDstState.name);\n                m_DstState.pushUndo = false;\n                m_DstState.hideFlags = HideFlags.HideAndDontSave;\n\n                CopyStateForPreview(m_RefSrcState, ref m_SrcState);\n                CopyStateForPreview(m_RefDstState, ref m_DstState);\n\n                // transition\n                m_Transition = m_SrcState.AddTransition(m_DstState, true);\n                m_Transition.pushUndo = false;\n                m_Transition.hideFlags = HideFlags.DontSave;\n                CopyTransitionForPreview(m_RefTransition, ref m_Transition);\n\n                DisableIKOnFeetIfNeeded();\n\n\n                AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);\n\n                m_Controller.OnAnimatorControllerDirty += ControllerDirty;\n            }\n        }\n\n        private void ControllerDirty()\n        {\n            if (!m_IsResampling)\n                m_MustResample = true;\n        }\n\n        private void DisableIKOnFeetIfNeeded()\n        {\n            bool disable = m_SrcMotion == null || m_DstMotion == null;\n\n            if (m_LayerIndex > 0)\n            {\n                disable = !m_LayerMask.hasFeetIK;\n            }\n\n            if (disable)\n            {\n                m_SrcState.iKOnFeet = false;\n                m_DstState.iKOnFeet = false;\n            }\n        }\n\n        private void Init(Animator scenePreviewObject, Motion motion)\n        {\n            if (m_AvatarPreview == null)\n            {\n                m_AvatarPreview = new AvatarPreview(scenePreviewObject, motion);\n                m_AvatarPreview.OnAvatarChangeFunc = OnPreviewAvatarChanged;\n                m_AvatarPreview.ShowIKOnFeetButton = false;\n                m_AvatarPreview.ResetPreviewFocus();\n            }\n\n            if (m_Timeline == null)\n            {\n                m_Timeline = new TimelineControl();\n                m_MustSampleMotions = true;\n            }\n\n            CreateController();\n\n            if(m_ParameterInfoList == null || m_MustResetParameterInfoList)\n            {\n                m_MustResetParameterInfoList = false;\n                CreateParameterInfoList();\n            }\n\n        }\n\n        public void DoTransitionPreview()\n        {\n            if (m_Controller == null)\n                return;\n\n            DoTimeline();\n\n            // Draw the blend values\n\n            AnimatorControllerParameter[] parameters = m_Controller.parameters;\n            if (parameters.Length > 0)\n            {\n                m_ShowBlendValue = EditorGUILayout.Foldout(m_ShowBlendValue, \"BlendTree Parameters\", true);\n\n                if (m_ShowBlendValue)\n                {\n                    for (int i = 0; i < parameters.Length; i++)\n                    {\n                        AnimatorControllerParameter parameter = m_Controller.parameters[i];\n                        float value = m_ParameterInfoList[i].m_Value;\n                        float newValue = EditorGUILayout.Slider(parameter.name, value, m_ParameterMinMax[i][0], m_ParameterMinMax[i][1]);\n                        if (newValue != value)\n                        {\n                            m_ParameterInfoList[i].m_Value = newValue;\n                            mustResample = true;\n                            m_MustSampleMotions = true;\n                        }\n                    }\n                }\n            }\n        }\n\n        private void DoTimeline()\n        {\n            if (!m_ValidTransition)\n            {\n                return;\n            }\n            // get local durations\n            float srcStateDuration =  (m_LeftStateTimeB - m_LeftStateTimeA) / (m_LeftStateWeightB - m_LeftStateWeightA);\n            float dstStateDuration = (m_RightStateTimeB - m_RightStateTimeA) / (m_RightStateWeightB - m_RightStateWeightA);\n            float transitionDuration =  m_Transition.duration * (m_RefTransition.hasFixedDuration ? 1.0f : srcStateDuration);\n\n            // Set the timeline values\n            m_Timeline.SrcStartTime = 0f;\n            m_Timeline.SrcStopTime = srcStateDuration;\n            m_Timeline.SrcName = m_RefSrcState.name;\n            m_Timeline.HasExitTime = m_RefTransition.hasExitTime;\n\n            m_Timeline.srcLoop = m_SrcMotion ? m_SrcMotion.isLooping : false;\n            m_Timeline.dstLoop = m_DstMotion ? m_DstMotion.isLooping : false;\n\n            m_Timeline.TransitionStartTime = m_RefTransition.exitTime * srcStateDuration;\n            m_Timeline.TransitionStopTime = m_Timeline.TransitionStartTime + transitionDuration;\n\n            m_Timeline.Time = m_AvatarPreview.timeControl.currentTime;\n\n            m_Timeline.DstStartTime = m_Timeline.TransitionStartTime - m_RefTransition.offset * dstStateDuration;\n            m_Timeline.DstStopTime =  m_Timeline.DstStartTime + dstStateDuration;\n\n            m_Timeline.SampleStopTime = m_AvatarPreview.timeControl.stopTime;\n\n            if (m_Timeline.TransitionStopTime == Mathf.Infinity)\n                m_Timeline.TransitionStopTime = Mathf.Min(m_Timeline.DstStopTime, m_Timeline.SrcStopTime);\n\n\n            m_Timeline.DstName = m_RefDstState.name;\n\n            m_Timeline.SrcPivotList = m_SrcPivotList;\n            m_Timeline.DstPivotList = m_DstPivotList;\n\n            // Do the timeline\n            Rect previewRect = EditorGUILayout.GetControlRect(false, 150, EditorStyles.label);\n\n            EditorGUI.BeginChangeCheck();\n\n            bool changedData = m_Timeline.DoTimeline(previewRect);\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (changedData)\n                {\n                    Undo.RegisterCompleteObjectUndo(m_RefTransition, \"Edit Transition\");\n                    m_RefTransition.exitTime =  m_Timeline.TransitionStartTime / m_Timeline.SrcDuration;\n                    m_RefTransition.duration = m_Timeline.TransitionDuration / (m_RefTransition.hasFixedDuration ? 1.0f : m_Timeline.SrcDuration);\n                    m_RefTransition.offset = (m_Timeline.TransitionStartTime - m_Timeline.DstStartTime) / m_Timeline.DstDuration;\n                }\n\n                m_AvatarPreview.timeControl.nextCurrentTime = Mathf.Clamp(m_Timeline.Time, 0, m_AvatarPreview.timeControl.stopTime);\n            }\n        }\n\n        public void OnDisable()\n        {\n            ClearController();\n\n            if (m_Timeline != null)\n            {\n                m_Timeline = null;\n            }\n\n            if (m_AvatarPreview != null)\n            {\n                m_AvatarPreview.OnDisable();\n                m_AvatarPreview = null;\n            }\n        }\n\n        public bool HasPreviewGUI()\n        {\n            return true;\n        }\n\n        public void OnPreviewSettings()\n        {\n            if (m_AvatarPreview != null)\n                m_AvatarPreview.DoPreviewSettings();\n        }\n\n        public void OnInteractivePreviewGUI(Rect r, GUIStyle background)\n        {\n            if (m_AvatarPreview != null && m_Controller != null)\n            {\n                bool isRepaint = (Event.current.type == EventType.Repaint);\n\n                if (isRepaint)\n                    m_AvatarPreview.timeControl.Update();\n\n                if (m_LastEvalTime != m_AvatarPreview.timeControl.currentTime && isRepaint)\n                {\n                    m_AvatarPreview.Animator.playbackTime = m_AvatarPreview.timeControl.currentTime;\n                    m_AvatarPreview.Animator.Update(0);\n                    m_LastEvalTime = m_AvatarPreview.timeControl.currentTime;\n                }\n\n                m_AvatarPreview.DoAvatarPreview(r, background);\n            }\n        }\n    }\n}//namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/Animation/ZoomableArea.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    // NOTE: do _not_ use GUILayout to get the rectangle for zoomable area,\n    // will not work and will start failing miserably (mouse events not hitting it, etc.).\n    // That's because ZoomableArea is using GUILayout itself, and needs an actual\n    // physical rectangle.\n\n    [System.Serializable]\n    internal class ZoomableArea\n    {\n        // Global state\n        private static Vector2 m_MouseDownPosition = new Vector2(-1000000, -1000000); // in transformed space\n        private static int zoomableAreaHash = \"ZoomableArea\".GetHashCode();\n\n        // Range lock settings\n        [SerializeField] private bool m_HRangeLocked;\n        [SerializeField] private bool m_VRangeLocked;\n        public bool hRangeLocked { get { return m_HRangeLocked; } set { m_HRangeLocked = value; } }\n        public bool vRangeLocked { get { return m_VRangeLocked; } set { m_VRangeLocked = value; } }\n\n        // Zoom lock settings\n        public bool hZoomLockedByDefault = false;\n        public bool vZoomLockedByDefault = false;\n\n        [SerializeField] private float m_HBaseRangeMin = 0;\n        [SerializeField] private float m_HBaseRangeMax = 1;\n        [SerializeField] private float m_VBaseRangeMin = 0;\n        [SerializeField] private float m_VBaseRangeMax = 1;\n        public float hBaseRangeMin { get { return m_HBaseRangeMin; } set { m_HBaseRangeMin = value; } }\n        public float hBaseRangeMax { get { return m_HBaseRangeMax; } set { m_HBaseRangeMax = value; } }\n        public float vBaseRangeMin { get { return m_VBaseRangeMin; } set { m_VBaseRangeMin = value; } }\n        public float vBaseRangeMax { get { return m_VBaseRangeMax; } set { m_VBaseRangeMax = value; } }\n        [SerializeField] private bool m_HAllowExceedBaseRangeMin = true;\n        [SerializeField] private bool m_HAllowExceedBaseRangeMax = true;\n        [SerializeField] private bool m_VAllowExceedBaseRangeMin = true;\n        [SerializeField] private bool m_VAllowExceedBaseRangeMax = true;\n        public bool hAllowExceedBaseRangeMin { get { return m_HAllowExceedBaseRangeMin; } set { m_HAllowExceedBaseRangeMin = value; } }\n        public bool hAllowExceedBaseRangeMax { get { return m_HAllowExceedBaseRangeMax; } set { m_HAllowExceedBaseRangeMax = value; } }\n        public bool vAllowExceedBaseRangeMin { get { return m_VAllowExceedBaseRangeMin; } set { m_VAllowExceedBaseRangeMin = value; } }\n        public bool vAllowExceedBaseRangeMax { get { return m_VAllowExceedBaseRangeMax; } set { m_VAllowExceedBaseRangeMax = value; } }\n        public float hRangeMin\n        {\n            get { return (hAllowExceedBaseRangeMin ? Mathf.NegativeInfinity : hBaseRangeMin); }\n            set { SetAllowExceed(ref m_HBaseRangeMin, ref m_HAllowExceedBaseRangeMin, value); }\n        }\n        public float hRangeMax\n        {\n            get { return (hAllowExceedBaseRangeMax ? Mathf.Infinity : hBaseRangeMax); }\n            set { SetAllowExceed(ref m_HBaseRangeMax, ref m_HAllowExceedBaseRangeMax, value); }\n        }\n        public float vRangeMin\n        {\n            get { return (vAllowExceedBaseRangeMin ? Mathf.NegativeInfinity : vBaseRangeMin); }\n            set { SetAllowExceed(ref m_VBaseRangeMin, ref m_VAllowExceedBaseRangeMin, value); }\n        }\n        public float vRangeMax\n        {\n            get { return (vAllowExceedBaseRangeMax ? Mathf.Infinity : vBaseRangeMax); }\n            set { SetAllowExceed(ref m_VBaseRangeMax, ref m_VAllowExceedBaseRangeMax, value); }\n        }\n        private void SetAllowExceed(ref float rangeEnd, ref bool allowExceed, float value)\n        {\n            if (value == Mathf.NegativeInfinity || value == Mathf.Infinity)\n            {\n                rangeEnd = (value == Mathf.NegativeInfinity ? 0 : 1);\n                allowExceed = true;\n            }\n            else\n            {\n                rangeEnd = value;\n                allowExceed = false;\n            }\n        }\n\n        private const float kMinScale = 0.00001f;\n        private const float kMaxScale = 100000.0f;\n        private float m_HScaleMin = kMinScale;\n        private float m_HScaleMax = kMaxScale;\n        private float m_VScaleMin = kMinScale;\n        private float m_VScaleMax = kMaxScale;\n\n        private float m_MinWidth = 0.05f;\n        private const float kMinHeight = 0.05f;\n\n        private const float k_ScrollStepSize = 10f; // mirrors GUI scrollstepsize as there is no global const for this.\n\n        public float minWidth\n        {\n            get { return m_MinWidth; }\n            set\n            {\n                if (value > 0)\n                    m_MinWidth = value;\n                else\n                {\n                    Debug.LogWarning(\"Zoomable area width cannot have a value of \" +\n                        \"or below 0. Reverting back to a default value of 0.05f\");\n                    m_MinWidth = 0.05f;\n                }\n            }\n        }\n\n        public float hScaleMin\n        {\n            get { return m_HScaleMin; }\n            set\n            {\n                m_HScaleMin = Mathf.Clamp(value, kMinScale, kMaxScale);\n                styles.enableSliderZoomHorizontal = allowSliderZoomHorizontal;\n            }\n        }\n        public float hScaleMax\n        {\n            get { return m_HScaleMax; }\n            set\n            {\n                m_HScaleMax = Mathf.Clamp(value, kMinScale, kMaxScale);\n                styles.enableSliderZoomHorizontal = allowSliderZoomHorizontal;\n            }\n        }\n        public float vScaleMin\n        {\n            get { return m_VScaleMin; }\n            set\n            {\n                m_VScaleMin = Mathf.Clamp(value, kMinScale, kMaxScale);\n                styles.enableSliderZoomVertical = allowSliderZoomVertical;\n            }\n        }\n        public float vScaleMax\n        {\n            get { return m_VScaleMax; }\n            set\n            {\n                m_VScaleMax = Mathf.Clamp(value, kMinScale, kMaxScale);\n                styles.enableSliderZoomVertical = allowSliderZoomVertical;\n            }\n        }\n\n\n        // Window resize settings\n        [SerializeField] private bool m_ScaleWithWindow = false;\n        public bool scaleWithWindow { get { return m_ScaleWithWindow; } set { m_ScaleWithWindow = value; } }\n\n        // Slider settings\n        [SerializeField] private bool m_HSlider = true;\n        [SerializeField] private bool m_VSlider = true;\n        public bool hSlider { get { return m_HSlider; } set { Rect r = rect; m_HSlider = value; rect = r; } }\n        public bool vSlider { get { return m_VSlider; } set { Rect r = rect; m_VSlider = value; rect = r; } }\n\n        [SerializeField] private bool m_IgnoreScrollWheelUntilClicked = false;\n        public bool ignoreScrollWheelUntilClicked { get { return m_IgnoreScrollWheelUntilClicked; } set { m_IgnoreScrollWheelUntilClicked = value; } }\n\n        [SerializeField] private bool m_EnableMouseInput = true;\n        public bool enableMouseInput { get { return m_EnableMouseInput; } set { m_EnableMouseInput = value; } }\n\n        [SerializeField] private bool m_EnableSliderZoomHorizontal = true;\n        [SerializeField] private bool m_EnableSliderZoomVertical = true;\n\n        // if the min and max scaling does not allow for actual zooming, there is no point in allowing it\n        protected bool allowSliderZoomHorizontal { get { return m_EnableSliderZoomHorizontal && m_HScaleMin < m_HScaleMax; } }\n        protected bool allowSliderZoomVertical { get { return m_EnableSliderZoomVertical && m_VScaleMin < m_VScaleMax; } }\n\n        public bool m_UniformScale;\n        public bool uniformScale { get { return m_UniformScale; } set { m_UniformScale = value; } }\n\n        // This is optional now, but used to be default behaviour because ZoomableAreas are mostly graphs with +Y being up\n        public enum YDirection\n        {\n            Positive,\n            Negative\n        }\n        [SerializeField] private YDirection m_UpDirection = YDirection.Positive;\n        public YDirection upDirection\n        {\n            get\n            {\n                return m_UpDirection;\n            }\n            set\n            {\n                if (m_UpDirection != value)\n                {\n                    m_UpDirection = value;\n                    m_Scale.y = -m_Scale.y;\n                }\n            }\n        }\n\n        // View and drawing settings\n        [SerializeField] private Rect m_DrawArea = new Rect(0, 0, 100, 100);\n        internal void SetDrawRectHack(Rect r) { m_DrawArea = r; }\n        [SerializeField] internal Vector2 m_Scale = new Vector2(1, -1);\n        [SerializeField] internal Vector2 m_Translation = new Vector2(0, 0);\n        [SerializeField] private float m_MarginLeft, m_MarginRight, m_MarginTop, m_MarginBottom;\n        [SerializeField] private Rect m_LastShownAreaInsideMargins = new Rect(0, 0, 100, 100);\n\n        public Vector2 scale { get { return m_Scale; } }\n        public Vector2 translation { get { return m_Translation; } }\n        public float margin { set { m_MarginLeft = m_MarginRight = m_MarginTop = m_MarginBottom = value; } }\n        public float leftmargin { get { return m_MarginLeft; } set { m_MarginLeft = value; } }\n        public float rightmargin { get { return m_MarginRight; } set { m_MarginRight = value; } }\n        public float topmargin { get { return m_MarginTop; } set { m_MarginTop = value; } }\n        public float bottommargin { get { return m_MarginBottom; } set { m_MarginBottom = value; } }\n        public float vSliderWidth { get { return vSlider ? styles.sliderWidth : 0f; } }\n        public float hSliderHeight { get { return hSlider ? styles.sliderWidth : 0f; } }\n\n        // IDs for controls\n        internal int areaControlID;\n        int verticalScrollbarID, horizontalScrollbarID;\n\n        [SerializeField] bool m_MinimalGUI;\n\n        public class Styles\n        {\n            public GUIStyle horizontalScrollbar;\n            public GUIStyle horizontalMinMaxScrollbarThumb\n            {\n                get\n                {\n                    return GetSliderAxisStyle(enableSliderZoomHorizontal).horizontal;\n                }\n            }\n            public GUIStyle horizontalScrollbarLeftButton;\n            public GUIStyle horizontalScrollbarRightButton;\n            public GUIStyle verticalScrollbar;\n            public GUIStyle verticalMinMaxScrollbarThumb\n            {\n                get\n                {\n                    return GetSliderAxisStyle(enableSliderZoomVertical).vertical;\n                }\n            }\n            public GUIStyle verticalScrollbarUpButton;\n            public GUIStyle verticalScrollbarDownButton;\n\n            public bool enableSliderZoomHorizontal;\n            public bool enableSliderZoomVertical;\n\n            public float sliderWidth;\n            public float visualSliderWidth;\n\n            private bool minimalGUI;\n\n            private SliderTypeStyles.SliderAxisStyles GetSliderAxisStyle(bool enableSliderZoom)\n            {\n                if (minimalGUI)\n                    return enableSliderZoom ? minimalSliderStyles.minMaxSliders : minimalSliderStyles.scrollbar;\n                else\n                    return enableSliderZoom ? normalSliderStyles.minMaxSliders : normalSliderStyles.scrollbar;\n            }\n\n            private static SliderTypeStyles minimalSliderStyles;\n            private static SliderTypeStyles normalSliderStyles;\n\n            private class SliderTypeStyles\n            {\n                public SliderAxisStyles scrollbar;\n                public SliderAxisStyles minMaxSliders;\n                public class SliderAxisStyles\n                {\n                    public GUIStyle horizontal;\n                    public GUIStyle vertical;\n                }\n            }\n\n            public Styles(bool minimalGUI)\n            {\n                if (minimalGUI)\n                {\n                    visualSliderWidth = 0;\n                    sliderWidth = 13;\n                }\n                else\n                {\n                    visualSliderWidth = 13;\n                    sliderWidth = 13;\n                }\n            }\n\n            public void InitGUIStyles(bool minimalGUI, bool enableSliderZoom)\n            {\n                InitGUIStyles(minimalGUI, enableSliderZoom, enableSliderZoom);\n            }\n\n            public void InitGUIStyles(bool minimalGUI, bool enableSliderZoomHorizontal, bool enableSliderZoomVertical)\n            {\n                this.minimalGUI = minimalGUI;\n                this.enableSliderZoomHorizontal = enableSliderZoomHorizontal;\n                this.enableSliderZoomVertical = enableSliderZoomVertical;\n\n                if (minimalGUI)\n                {\n                    if (minimalSliderStyles == null)\n                    {\n                        minimalSliderStyles = new SliderTypeStyles()\n                        {\n                            scrollbar = new SliderTypeStyles.SliderAxisStyles() { horizontal = \"MiniSliderhorizontal\", vertical = \"MiniSliderVertical\" },\n                            minMaxSliders = new SliderTypeStyles.SliderAxisStyles() { horizontal = \"MiniMinMaxSliderHorizontal\", vertical = \"MiniMinMaxSlidervertical\" },\n                        };\n                    }\n                    horizontalScrollbarLeftButton = GUIStyle.none;\n                    horizontalScrollbarRightButton = GUIStyle.none;\n                    horizontalScrollbar = GUIStyle.none;\n                    verticalScrollbarUpButton = GUIStyle.none;\n                    verticalScrollbarDownButton = GUIStyle.none;\n                    verticalScrollbar = GUIStyle.none;\n                }\n                else\n                {\n                    if (normalSliderStyles == null)\n                    {\n                        normalSliderStyles = new SliderTypeStyles()\n                        {\n                            scrollbar = new SliderTypeStyles.SliderAxisStyles() { horizontal = \"horizontalscrollbarthumb\", vertical = \"verticalscrollbarthumb\" },\n                            minMaxSliders = new SliderTypeStyles.SliderAxisStyles() { horizontal = \"horizontalMinMaxScrollbarThumb\", vertical = \"verticalMinMaxScrollbarThumb\" },\n                        };\n                    }\n                    horizontalScrollbarLeftButton = \"horizontalScrollbarLeftbutton\";\n                    horizontalScrollbarRightButton = \"horizontalScrollbarRightbutton\";\n                    horizontalScrollbar = GUI.skin.horizontalScrollbar;\n                    verticalScrollbarUpButton = \"verticalScrollbarUpbutton\";\n                    verticalScrollbarDownButton = \"verticalScrollbarDownbutton\";\n                    verticalScrollbar = GUI.skin.verticalScrollbar;\n                }\n            }\n        }\n\n        private Styles m_Styles;\n        protected Styles styles\n        {\n            get\n            {\n                if (m_Styles == null)\n                    m_Styles = new Styles(m_MinimalGUI);\n                return m_Styles;\n            }\n        }\n\n        public Rect rect\n        {\n            get { return new Rect(drawRect.x, drawRect.y, drawRect.width + (m_VSlider ? styles.visualSliderWidth : 0), drawRect.height + (m_HSlider ? styles.visualSliderWidth : 0)); }\n            set\n            {\n                Rect newDrawArea = new Rect(value.x, value.y, value.width - (m_VSlider ? styles.visualSliderWidth : 0), value.height - (m_HSlider ? styles.visualSliderWidth : 0));\n                if (newDrawArea != m_DrawArea)\n                {\n                    if (m_ScaleWithWindow)\n                    {\n                        m_DrawArea = newDrawArea;\n                        shownAreaInsideMargins = m_LastShownAreaInsideMargins;\n                    }\n                    else\n                    {\n                        m_Translation += new Vector2((newDrawArea.width - m_DrawArea.width) / 2, (newDrawArea.height - m_DrawArea.height) / 2);\n                        m_DrawArea = newDrawArea;\n                    }\n                }\n                EnforceScaleAndRange();\n            }\n        }\n        public Rect drawRect { get { return m_DrawArea; } }\n\n        public void SetShownHRangeInsideMargins(float min, float max)\n        {\n            float widthInsideMargins = drawRect.width - leftmargin - rightmargin;\n            if (widthInsideMargins < m_MinWidth) widthInsideMargins = m_MinWidth;\n\n            float denum = max - min;\n            if (denum < m_MinWidth) denum = m_MinWidth;\n\n            m_Scale.x = widthInsideMargins / denum;\n\n            m_Translation.x = -min * m_Scale.x + leftmargin;\n            EnforceScaleAndRange();\n        }\n\n        public void SetShownHRange(float min, float max)\n        {\n            float denum = max - min;\n            if (denum < m_MinWidth) denum = m_MinWidth;\n\n            m_Scale.x = drawRect.width / denum;\n\n            m_Translation.x = -min * m_Scale.x;\n            EnforceScaleAndRange();\n        }\n\n        public void SetShownVRangeInsideMargins(float min, float max)\n        {\n            float heightInsideMargins = drawRect.height - topmargin - bottommargin;\n            if (heightInsideMargins < kMinHeight) heightInsideMargins = kMinHeight;\n\n            float denum = max - min;\n            if (denum < kMinHeight) denum = kMinHeight;\n\n            if (m_UpDirection == YDirection.Positive)\n            {\n                m_Scale.y = -heightInsideMargins / denum;\n                m_Translation.y = drawRect.height - min * m_Scale.y - topmargin;\n            }\n            else\n            {\n                m_Scale.y = heightInsideMargins / denum;\n                m_Translation.y = -min * m_Scale.y - bottommargin;\n            }\n            EnforceScaleAndRange();\n        }\n\n        public void SetShownVRange(float min, float max)\n        {\n            float denum = max - min;\n            if (denum < kMinHeight) denum = kMinHeight;\n\n            if (m_UpDirection == YDirection.Positive)\n            {\n                m_Scale.y = -drawRect.height / denum;\n                m_Translation.y = drawRect.height - min * m_Scale.y;\n            }\n            else\n            {\n                m_Scale.y = drawRect.height / denum;\n                m_Translation.y = -min * m_Scale.y;\n            }\n            EnforceScaleAndRange();\n        }\n\n        // ShownArea is in curve space\n        public Rect shownArea\n        {\n            set\n            {\n                float width = (value.width < m_MinWidth) ? m_MinWidth : value.width;\n                float height = (value.height < kMinHeight) ? kMinHeight : value.height;\n\n                if (m_UpDirection == YDirection.Positive)\n                {\n                    m_Scale.x = drawRect.width / width;\n                    m_Scale.y = -drawRect.height / height;\n                    m_Translation.x = -value.x * m_Scale.x;\n                    m_Translation.y = drawRect.height - value.y * m_Scale.y;\n                }\n                else\n                {\n                    m_Scale.x = drawRect.width / width;\n                    m_Scale.y = drawRect.height / height;\n                    m_Translation.x = -value.x * m_Scale.x;\n                    m_Translation.y = -value.y * m_Scale.y;\n                }\n                EnforceScaleAndRange();\n            }\n            get\n            {\n                if (m_UpDirection == YDirection.Positive)\n                {\n                    return new Rect(\n                        -m_Translation.x / m_Scale.x,\n                        -(m_Translation.y - drawRect.height) / m_Scale.y,\n                        drawRect.width / m_Scale.x,\n                        drawRect.height / -m_Scale.y\n                    );\n                }\n                else\n                {\n                    return new Rect(\n                        -m_Translation.x / m_Scale.x,\n                        -m_Translation.y / m_Scale.y,\n                        drawRect.width / m_Scale.x,\n                        drawRect.height / m_Scale.y\n                    );\n                }\n            }\n        }\n\n        public Rect shownAreaInsideMargins\n        {\n            set\n            {\n                shownAreaInsideMarginsInternal = value;\n                EnforceScaleAndRange();\n            }\n            get\n            {\n                return shownAreaInsideMarginsInternal;\n            }\n        }\n\n        private Rect shownAreaInsideMarginsInternal\n        {\n            set\n            {\n                float width = (value.width < m_MinWidth) ? m_MinWidth : value.width;\n                float height = (value.height < kMinHeight) ? kMinHeight : value.height;\n\n                float widthInsideMargins = drawRect.width - leftmargin - rightmargin;\n                if (widthInsideMargins < m_MinWidth) widthInsideMargins = m_MinWidth;\n\n                float heightInsideMargins = drawRect.height - topmargin - bottommargin;\n                if (heightInsideMargins < kMinHeight) heightInsideMargins = kMinHeight;\n\n                if (m_UpDirection == YDirection.Positive)\n                {\n                    m_Scale.x = widthInsideMargins / width;\n                    m_Scale.y = -heightInsideMargins / height;\n                    m_Translation.x = -value.x * m_Scale.x + leftmargin;\n                    m_Translation.y = drawRect.height - value.y * m_Scale.y - topmargin;\n                }\n                else\n                {\n                    m_Scale.x = widthInsideMargins / width;\n                    m_Scale.y = heightInsideMargins / height;\n                    m_Translation.x = -value.x * m_Scale.x + leftmargin;\n                    m_Translation.y = -value.y * m_Scale.y + topmargin;\n                }\n            }\n            get\n            {\n                float leftmarginRel = leftmargin / m_Scale.x;\n                float rightmarginRel = rightmargin / m_Scale.x;\n                float topmarginRel = topmargin / m_Scale.y;\n                float bottommarginRel = bottommargin / m_Scale.y;\n\n                Rect area = shownArea;\n                area.x += leftmarginRel;\n                area.y -= topmarginRel;\n                area.width -= leftmarginRel + rightmarginRel;\n                area.height += topmarginRel + bottommarginRel;\n                return area;\n            }\n        }\n\n        float GetWidthInsideMargins(float widthWithMargins, bool substractSliderWidth = false)\n        {\n            float width = (widthWithMargins < m_MinWidth) ? m_MinWidth : widthWithMargins;\n            float widthInsideMargins = width - leftmargin - rightmargin - (substractSliderWidth ? (m_VSlider ? styles.visualSliderWidth : 0) : 0);\n            return Mathf.Max(widthInsideMargins, m_MinWidth);\n        }\n\n        float GetHeightInsideMargins(float heightWithMargins, bool substractSliderHeight = false)\n        {\n            float height = (heightWithMargins < kMinHeight) ? kMinHeight : heightWithMargins;\n            float heightInsideMargins = height - topmargin - bottommargin - (substractSliderHeight ? (m_HSlider ? styles.visualSliderWidth : 0) : 0);\n            return Mathf.Max(heightInsideMargins, kMinHeight);\n        }\n\n        public virtual Bounds drawingBounds\n        {\n            get\n            {\n                return new Bounds(\n                    new Vector3((hBaseRangeMin + hBaseRangeMax) * 0.5f, (vBaseRangeMin + vBaseRangeMax) * 0.5f, 0),\n                    new Vector3(hBaseRangeMax - hBaseRangeMin, vBaseRangeMax - vBaseRangeMin, 1)\n                );\n            }\n        }\n\n\n        // Utility transform functions\n\n        public Matrix4x4 drawingToViewMatrix\n        {\n            get\n            {\n                return Matrix4x4.TRS(m_Translation, Quaternion.identity, new Vector3(m_Scale.x, m_Scale.y, 1));\n            }\n        }\n\n        public Vector2 DrawingToViewTransformPoint(Vector2 lhs)\n        { return new Vector2(lhs.x * m_Scale.x + m_Translation.x, lhs.y * m_Scale.y + m_Translation.y); }\n        public Vector3 DrawingToViewTransformPoint(Vector3 lhs)\n        { return new Vector3(lhs.x * m_Scale.x + m_Translation.x, lhs.y * m_Scale.y + m_Translation.y, 0); }\n\n        public Vector2 ViewToDrawingTransformPoint(Vector2 lhs)\n        { return new Vector2((lhs.x - m_Translation.x) / m_Scale.x , (lhs.y - m_Translation.y) / m_Scale.y); }\n        public Vector3 ViewToDrawingTransformPoint(Vector3 lhs)\n        { return new Vector3((lhs.x - m_Translation.x) / m_Scale.x , (lhs.y - m_Translation.y) / m_Scale.y, 0); }\n\n        public Vector2 DrawingToViewTransformVector(Vector2 lhs)\n        { return new Vector2(lhs.x * m_Scale.x, lhs.y * m_Scale.y); }\n        public Vector3 DrawingToViewTransformVector(Vector3 lhs)\n        { return new Vector3(lhs.x * m_Scale.x, lhs.y * m_Scale.y, 0); }\n\n        public Vector2 ViewToDrawingTransformVector(Vector2 lhs)\n        { return new Vector2(lhs.x / m_Scale.x, lhs.y / m_Scale.y); }\n        public Vector3 ViewToDrawingTransformVector(Vector3 lhs)\n        { return new Vector3(lhs.x / m_Scale.x, lhs.y / m_Scale.y, 0); }\n\n        public Vector2 mousePositionInDrawing\n        {\n            get { return ViewToDrawingTransformPoint(Event.current.mousePosition); }\n        }\n\n        public Vector2 NormalizeInViewSpace(Vector2 vec)\n        {\n            vec = Vector2.Scale(vec, m_Scale);\n            vec /= vec.magnitude;\n            return Vector2.Scale(vec, new Vector2(1 / m_Scale.x, 1 / m_Scale.y));\n        }\n\n        // Utility mouse event functions\n\n        private bool IsZoomEvent()\n        {\n            return (\n                (Event.current.button == 1 && Event.current.alt) // right+alt drag\n                //|| (Event.current.button == 0 && Event.current.command) // left+commend drag\n                //|| (Event.current.button == 2 && Event.current.command) // middle+command drag\n\n            );\n        }\n\n        private bool IsPanEvent()\n        {\n            return (\n                (Event.current.button == 0 && Event.current.alt) // left+alt drag\n                || (Event.current.button == 2 && !Event.current.command) // middle drag\n            );\n        }\n\n        public ZoomableArea()\n        {\n            m_MinimalGUI = false;\n        }\n\n        public ZoomableArea(bool minimalGUI)\n        {\n            m_MinimalGUI = minimalGUI;\n        }\n\n        public ZoomableArea(bool minimalGUI, bool enableSliderZoom) : this(minimalGUI, enableSliderZoom, enableSliderZoom) {}\n\n        public ZoomableArea(bool minimalGUI, bool enableSliderZoomHorizontal, bool enableSliderZoomVertical)\n        {\n            m_MinimalGUI = minimalGUI;\n            m_EnableSliderZoomHorizontal = enableSliderZoomHorizontal;\n            m_EnableSliderZoomVertical = enableSliderZoomVertical;\n        }\n\n        public void BeginViewGUI()\n        {\n            if (styles.horizontalScrollbar == null)\n                styles.InitGUIStyles(m_MinimalGUI, allowSliderZoomHorizontal, allowSliderZoomVertical);\n\n            if (enableMouseInput)\n                HandleZoomAndPanEvents(m_DrawArea);\n\n            horizontalScrollbarID = GUIUtility.GetControlID(EditorGUIExt.s_MinMaxSliderHash, FocusType.Passive);\n            verticalScrollbarID = GUIUtility.GetControlID(EditorGUIExt.s_MinMaxSliderHash, FocusType.Passive);\n\n            if (!m_MinimalGUI || Event.current.type != EventType.Repaint)\n                SliderGUI();\n        }\n\n        public void HandleZoomAndPanEvents(Rect area)\n        {\n            GUILayout.BeginArea(area);\n\n            area.x = 0;\n            area.y = 0;\n            int id = GUIUtility.GetControlID(zoomableAreaHash, FocusType.Passive, area);\n            areaControlID = id;\n\n            switch (Event.current.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (area.Contains(Event.current.mousePosition))\n                    {\n                        // Catch keyboard control when clicked inside zoomable area\n                        // (used to restrict scrollwheel)\n                        GUIUtility.keyboardControl = id;\n\n                        if (IsZoomEvent() || IsPanEvent())\n                        {\n                            GUIUtility.hotControl = id;\n                            m_MouseDownPosition = mousePositionInDrawing;\n\n                            Event.current.Use();\n                        }\n                    }\n                    break;\n                case EventType.MouseUp:\n                    //Debug.Log(\"mouse-up!\");\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n\n                        // If we got the mousedown, the mouseup is ours as well\n                        // (no matter if the click was in the area or not)\n                        m_MouseDownPosition = new Vector2(-1000000, -1000000);\n                        //Event.current.Use();\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl != id) break;\n\n                    if (IsZoomEvent())\n                    {\n                        // Zoom in around mouse down position\n                        HandleZoomEvent(m_MouseDownPosition, false);\n                        Event.current.Use();\n                    }\n                    else if (IsPanEvent())\n                    {\n                        // Pan view\n                        Pan();\n                        Event.current.Use();\n                    }\n                    break;\n                case EventType.ScrollWheel:\n                    if (!area.Contains(Event.current.mousePosition))\n                    {\n                        HandleScrolling(area);\n                        break;\n                    }\n\n                    if (m_IgnoreScrollWheelUntilClicked && GUIUtility.keyboardControl != id)\n                        break;\n\n                    // Zoom in around cursor position\n                    HandleZoomEvent(mousePositionInDrawing, true);\n                    Event.current.Use();\n                    break;\n            }\n\n            GUILayout.EndArea();\n        }\n\n        void HandleScrolling(Rect area)\n        {\n            if (m_MinimalGUI)\n                return;\n            if (m_VSlider && new Rect(area.x + area.width, area.y + GUI.skin.verticalScrollbarUpButton.fixedHeight, vSliderWidth, area.height - (GUI.skin.verticalScrollbarDownButton.fixedHeight + hSliderHeight)).Contains(Event.current.mousePosition))\n            {\n                SetTransform(new Vector2(m_Translation.x, m_Translation.y - (Event.current.delta.y * k_ScrollStepSize)), m_Scale);\n                Event.current.Use();\n                return;\n            }\n\n            if (m_HSlider && new Rect(area.x + GUI.skin.horizontalScrollbarLeftButton.fixedWidth, area.y + area.height, area.width - (GUI.skin.horizontalScrollbarRightButton.fixedWidth + vSliderWidth), hSliderHeight).Contains(Event.current.mousePosition))\n            {\n                SetTransform(new Vector2(m_Translation.x + (Event.current.delta.y * k_ScrollStepSize), m_Translation.y), m_Scale);\n                Event.current.Use();\n            }\n        }\n\n        public void EndViewGUI()\n        {\n            if (m_MinimalGUI && Event.current.type == EventType.Repaint)\n                SliderGUI();\n        }\n\n        void SliderGUI()\n        {\n            if (!m_HSlider && !m_VSlider)\n                return;\n\n            using (new EditorGUI.DisabledScope(!enableMouseInput))\n            {\n                Bounds editorBounds = drawingBounds;\n                Rect area = shownAreaInsideMargins;\n                float min, max;\n                float inset = styles.sliderWidth - styles.visualSliderWidth;\n                float otherInset = (vSlider && hSlider) ? inset : 0;\n\n                Vector2 scaleDelta = m_Scale;\n                // Horizontal range slider\n                if (m_HSlider)\n                {\n                    Rect hRangeSliderRect = new Rect(drawRect.x + 1, drawRect.yMax - inset, drawRect.width - otherInset, styles.sliderWidth);\n                    float shownXRange = area.width;\n                    float shownXMin = area.xMin;\n                    if (allowSliderZoomHorizontal)\n                    {\n                        EditorGUIExt.MinMaxScroller(hRangeSliderRect, horizontalScrollbarID,\n                            ref shownXMin, ref shownXRange,\n                            editorBounds.min.x, editorBounds.max.x,\n                            Mathf.NegativeInfinity, Mathf.Infinity,\n                            styles.horizontalScrollbar, styles.horizontalMinMaxScrollbarThumb,\n                            styles.horizontalScrollbarLeftButton, styles.horizontalScrollbarRightButton, true);\n                    }\n                    else\n                    {\n                        shownXMin = GUI.Scroller(hRangeSliderRect,\n                            shownXMin, shownXRange, editorBounds.min.x, editorBounds.max.x,\n                            styles.horizontalScrollbar, styles.horizontalMinMaxScrollbarThumb,\n                            styles.horizontalScrollbarLeftButton, styles.horizontalScrollbarRightButton, true);\n                    }\n                    min = shownXMin;\n                    max = shownXMin + shownXRange;\n                    float rectWidthWithinMargins = GetWidthInsideMargins(rect.width, true);\n                    if (min > area.xMin)\n                        min = Mathf.Min(min, max - rectWidthWithinMargins / m_HScaleMax);\n                    if (max < area.xMax)\n                        max = Mathf.Max(max, min + rectWidthWithinMargins / m_HScaleMax);\n                    SetShownHRangeInsideMargins(min, max);\n                }\n\n                // Vertical range slider\n                // Reverse y values since y increses upwards for the draw area but downwards for the slider\n                if (m_VSlider)\n                {\n                    if (m_UpDirection == YDirection.Positive)\n                    {\n                        Rect vRangeSliderRect = new Rect(drawRect.xMax - inset, drawRect.y, styles.sliderWidth, drawRect.height - otherInset);\n                        float shownYRange = area.height;\n                        float shownYMin = -area.yMax;\n                        if (allowSliderZoomVertical)\n                        {\n                            EditorGUIExt.MinMaxScroller(vRangeSliderRect, verticalScrollbarID,\n                                ref shownYMin, ref shownYRange,\n                                -editorBounds.max.y, -editorBounds.min.y,\n                                Mathf.NegativeInfinity, Mathf.Infinity,\n                                styles.verticalScrollbar, styles.verticalMinMaxScrollbarThumb,\n                                styles.verticalScrollbarUpButton, styles.verticalScrollbarDownButton, false);\n                        }\n                        else\n                        {\n                            shownYMin = GUI.Scroller(vRangeSliderRect,\n                                shownYMin, shownYRange, -editorBounds.max.y, -editorBounds.min.y,\n                                styles.verticalScrollbar, styles.verticalMinMaxScrollbarThumb,\n                                styles.verticalScrollbarUpButton, styles.verticalScrollbarDownButton, false);\n                        }\n                        min = -(shownYMin + shownYRange);\n                        max = -shownYMin;\n                        float rectHeightWithinMargins = GetHeightInsideMargins(rect.height, true);\n                        if (min > area.yMin)\n                            min = Mathf.Min(min, max - rectHeightWithinMargins / m_VScaleMax);\n                        if (max < area.yMax)\n                            max = Mathf.Max(max, min + rectHeightWithinMargins / m_VScaleMax);\n                        SetShownVRangeInsideMargins(min, max);\n                    }\n                    else\n                    {\n                        Rect vRangeSliderRect = new Rect(drawRect.xMax - inset, drawRect.y, styles.sliderWidth, drawRect.height - otherInset);\n                        float shownYRange = area.height;\n                        float shownYMin = area.yMin;\n                        if (allowSliderZoomVertical)\n                        {\n                            EditorGUIExt.MinMaxScroller(vRangeSliderRect, verticalScrollbarID,\n                                ref shownYMin, ref shownYRange,\n                                editorBounds.min.y, editorBounds.max.y,\n                                Mathf.NegativeInfinity, Mathf.Infinity,\n                                styles.verticalScrollbar, styles.verticalMinMaxScrollbarThumb,\n                                styles.verticalScrollbarUpButton, styles.verticalScrollbarDownButton, false);\n                        }\n                        else\n                        {\n                            shownYMin = GUI.Scroller(vRangeSliderRect,\n                                shownYMin, shownYRange, editorBounds.min.y, editorBounds.max.y,\n                                styles.verticalScrollbar, styles.verticalMinMaxScrollbarThumb,\n                                styles.verticalScrollbarUpButton, styles.verticalScrollbarDownButton, false);\n                        }\n                        min = shownYMin;\n                        max = shownYMin + shownYRange;\n                        float rectHeightWithinMargins = GetHeightInsideMargins(rect.height, true);\n                        if (min > area.yMin)\n                            min = Mathf.Min(min, max - rectHeightWithinMargins / m_VScaleMax);\n                        if (max < area.yMax)\n                            max = Mathf.Max(max, min + rectHeightWithinMargins / m_VScaleMax);\n                        SetShownVRangeInsideMargins(min, max);\n                    }\n                }\n\n                if (uniformScale)\n                {\n                    float aspect = drawRect.width / drawRect.height;\n                    scaleDelta -= m_Scale;\n                    var delta = new Vector2(-scaleDelta.y * aspect, -scaleDelta.x / aspect);\n\n                    m_Scale -= delta;\n                    m_Translation.x -= scaleDelta.y / 2;\n                    m_Translation.y -= scaleDelta.x / 2;\n                    EnforceScaleAndRange();\n                }\n            }\n        }\n\n        private void Pan()\n        {\n            if (!m_HRangeLocked)\n                m_Translation.x += Event.current.delta.x;\n            if (!m_VRangeLocked)\n                m_Translation.y += Event.current.delta.y;\n\n            EnforceScaleAndRange();\n        }\n\n        private void HandleZoomEvent(Vector2 zoomAround, bool scrollwhell)\n        {\n            // Get delta (from scroll wheel or mouse pad)\n            // Add x and y delta to cover all cases\n            // (scrool view has only y or only x when shift is pressed,\n            // while mouse pad has both x and y at all times)\n            float delta = Event.current.delta.x + Event.current.delta.y;\n\n            if (scrollwhell)\n                delta = -delta;\n\n            // Scale multiplier. Don't allow scale of zero or below!\n            float scale = Mathf.Max(0.01F, 1 + delta * 0.01F);\n\n            // Cap scale when at min width to not \"glide\" away when zooming closer\n            float width = shownAreaInsideMargins.width;\n            if (width / scale <= m_MinWidth)\n                return;\n\n            SetScaleFocused(zoomAround, scale * m_Scale, Event.current.shift, EditorGUI.actionKey);\n        }\n\n        // Sets a new scale, keeping focalPoint in the same relative position\n        public void SetScaleFocused(Vector2 focalPoint, Vector2 newScale)\n        {\n            SetScaleFocused(focalPoint, newScale, false, false);\n        }\n\n        public void SetScaleFocused(Vector2 focalPoint, Vector2 newScale, bool lockHorizontal, bool lockVertical)\n        {\n            if (uniformScale)\n                lockHorizontal = lockVertical = false;\n            else\n            {\n                // if an axis is locked by default, it is as if that modifier key is permanently held down\n                // actually pressing the key then lifts the lock. In other words, LockedByDefault acts like an inversion.\n                if (hZoomLockedByDefault)\n                    lockHorizontal = !lockHorizontal;\n\n                if (hZoomLockedByDefault)\n                    lockVertical = !lockVertical;\n            }\n\n            if (!m_HRangeLocked && !lockHorizontal)\n            {\n                // Offset to make zoom centered around cursor position\n                m_Translation.x -= focalPoint.x * (newScale.x - m_Scale.x);\n\n                // Apply zooming\n                m_Scale.x = newScale.x;\n            }\n            if (!m_VRangeLocked && !lockVertical)\n            {\n                // Offset to make zoom centered around cursor position\n                m_Translation.y -= focalPoint.y * (newScale.y - m_Scale.y);\n\n                // Apply zooming\n                m_Scale.y = newScale.y;\n            }\n\n            EnforceScaleAndRange();\n        }\n\n        public void SetTransform(Vector2 newTranslation, Vector2 newScale)\n        {\n            m_Scale = newScale;\n            m_Translation = newTranslation;\n            EnforceScaleAndRange();\n        }\n\n        public void EnforceScaleAndRange()\n        {\n            Rect oldArea = m_LastShownAreaInsideMargins;\n            Rect newArea = shownAreaInsideMargins;\n            if (newArea == oldArea)\n                return;\n\n            float minChange = 0.01f;\n\n            if (!Mathf.Approximately(newArea.width, oldArea.width))\n            {\n                float constrainedWidth = newArea.width;\n                if (newArea.width < oldArea.width)\n                {\n                    // The shown area decreasing in size means the scale is increasing. This happens e.g. while zooming in.\n                    // Only the max scale restricts the shown area size here, range has no influence.\n                    constrainedWidth = GetWidthInsideMargins(drawRect.width / m_HScaleMax, false);\n                }\n                else\n                {\n                    constrainedWidth = GetWidthInsideMargins(drawRect.width / m_HScaleMin, false);\n\n                    if (hRangeMax != Mathf.Infinity && hRangeMin != Mathf.NegativeInfinity)\n                    {\n                        // range only has an influence if it is enforced, i.e. not infinity\n                        float denum = hRangeMax - hRangeMin;\n                        if (denum < m_MinWidth) denum = m_MinWidth;\n\n                        constrainedWidth = Mathf.Min(constrainedWidth, denum);\n                    }\n                }\n\n                float xLerp = Mathf.InverseLerp(oldArea.width, newArea.width, constrainedWidth);\n                float newWidth = Mathf.Lerp(oldArea.width, newArea.width, xLerp);\n                float widthChange = Mathf.Abs(newWidth - newArea.width);\n                newArea = new Rect(\n                    // only affect the position if there was any significant change in width\n                    // this fixes an issue where if width was only different due to rounding issues, position changes are ignored as xLerp comes back 0 (or very nearly 0)\n                    widthChange > minChange ? Mathf.Lerp(oldArea.x, newArea.x, xLerp) : newArea.x,\n                    newArea.y,\n                    newWidth,\n                    newArea.height\n                );\n            }\n            if (!Mathf.Approximately(newArea.height, oldArea.height))\n            {\n                float constrainedHeight = newArea.height;\n                if (newArea.height < oldArea.height)\n                {\n                    // The shown area decreasing in size means the scale is increasing. This happens e.g. while zooming in.\n                    // Only the max scale restricts the shown area size here, range has no influence.\n                    constrainedHeight = GetHeightInsideMargins(drawRect.height / m_VScaleMax, false);\n                }\n                else\n                {\n                    constrainedHeight = GetHeightInsideMargins(drawRect.height / m_VScaleMin, false);\n\n                    if (vRangeMax != Mathf.Infinity && vRangeMin != Mathf.NegativeInfinity)\n                    {\n                        // range only has an influence if it is enforced, i.e. not infinity\n                        float denum = vRangeMax - vRangeMin;\n                        if (denum < kMinHeight) denum = kMinHeight;\n                        constrainedHeight = Mathf.Min(constrainedHeight, denum);\n                    }\n                }\n\n                float yLerp = Mathf.InverseLerp(oldArea.height, newArea.height, constrainedHeight);\n                float newHeight = Mathf.Lerp(oldArea.height, newArea.height, yLerp);\n                float heightChange = Mathf.Abs(newHeight - newArea.height);\n                newArea = new Rect(\n                    newArea.x,\n                    // only affect the position if there was any significant change in height\n                    // this fixes an issue where if height was only different due to rounding issues, position changes are ignored as yLerp comes back 0 (or very nearly 0)\n                    heightChange > minChange ? Mathf.Lerp(oldArea.y, newArea.y, yLerp) : newArea.y,\n                    newArea.width,\n                    newHeight\n                );\n            }\n\n            // Enforce ranges\n            if (newArea.xMin < hRangeMin)\n                newArea.x = hRangeMin;\n            if (newArea.xMax > hRangeMax)\n                newArea.x = hRangeMax - newArea.width;\n            if (newArea.yMin < vRangeMin)\n                newArea.y = vRangeMin;\n            if (newArea.yMax > vRangeMax)\n                newArea.y = vRangeMax - newArea.height;\n\n            shownAreaInsideMarginsInternal = newArea;\n            m_LastShownAreaInsideMargins = shownAreaInsideMargins;\n        }\n\n        public float PixelToTime(float pixelX, Rect rect)\n        {\n            Rect area = shownArea;\n            return ((pixelX - rect.x) * area.width / rect.width + area.x);\n        }\n\n        public float TimeToPixel(float time, Rect rect)\n        {\n            Rect area = shownArea;\n            return (time - area.x) / area.width * rect.width + rect.x;\n        }\n\n        public float PixelDeltaToTime(Rect rect)\n        {\n            return shownArea.width / rect.width;\n        }\n\n        public void UpdateZoomScale(float fMaxScaleValue, float fMinScaleValue)\n        {\n            // Update/reset the values of the scale to new zoom range, if the current values do not fall in the range of the new resolution\n\n            if (m_Scale.y > fMaxScaleValue || m_Scale.y < fMinScaleValue)\n            {\n                m_Scale.y = m_Scale.y > fMaxScaleValue ? fMaxScaleValue : fMinScaleValue;\n            }\n\n            if (m_Scale.x > fMaxScaleValue || m_Scale.x < fMinScaleValue)\n            {\n                m_Scale.x = m_Scale.x > fMaxScaleValue ? fMaxScaleValue : fMinScaleValue;\n            }\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/AnimationCurvePreviewCache.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEditor;\n\nnamespace UnityEditorInternal\n{\n    [NativeHeader(\"Editor/Src/AnimationCurvePreviewCache.bindings.h\")]\n    [NativeHeader(\"Editor/Src/Utility/SerializedProperty.h\")]\n    [NativeHeader(\"Runtime/Graphics/Texture2D.h\")]\n    [StaticAccessor(\"AnimationCurvePreviewCacheBindings\", StaticAccessorType.DoubleColon)]\n    internal class AnimationCurvePreviewCache\n    {\n        // Regions as SerializedProperty\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, SerializedProperty property2, Color color, Rect curveRanges)\n        {\n            return GetPreview(previewWidth, previewHeight, property, property2, color, Color.clear, Color.clear);\n        }\n\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, SerializedProperty property2, Color color, Color topFillColor, Color bottomFillColor, Rect curveRanges)\n        {\n            if (property2 == null)\n                return GetPropertyPreviewFilled(previewWidth, previewHeight, true, curveRanges, property, color, topFillColor, bottomFillColor);\n            else\n                return GetPropertyPreviewRegionFilled(previewWidth, previewHeight, true, curveRanges, property, property2, color, topFillColor, bottomFillColor);\n        }\n\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, SerializedProperty property2, Color color)\n        {\n            return GetPreview(previewWidth, previewHeight, property, property2, color, Color.clear, Color.clear);\n        }\n\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, SerializedProperty property2, Color color, Color topFillColor, Color bottomFillColor)\n        {\n            if (property2 == null)\n                return GetPropertyPreviewFilled(previewWidth, previewHeight, false, new Rect(), property, color, topFillColor, bottomFillColor);\n            else\n                return GetPropertyPreviewRegionFilled(previewWidth, previewHeight, false, new Rect(), property, property2, color, topFillColor, bottomFillColor);\n        }\n\n        // Regions as AnimationCurves\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, AnimationCurve curve2, Color color, Color topFillColor, Color bottomFillColor, Rect curveRanges)\n        {\n            return GetCurvePreviewRegionFilled(previewWidth, previewHeight, true, curveRanges, curve, curve2, color, topFillColor, bottomFillColor);\n        }\n\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, AnimationCurve curve2, Color color, Rect curveRanges)\n        {\n            return GetPreview(previewWidth, previewHeight, curve, curve2, color, Color.clear, Color.clear, curveRanges);\n        }\n\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, AnimationCurve curve2, Color color, Color topFillColor, Color bottomFillColor)\n        {\n            return GetCurvePreviewRegionFilled(previewWidth, previewHeight, false, new Rect(), curve, curve2, color, topFillColor, bottomFillColor);\n        }\n\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, AnimationCurve curve2, Color color)\n        {\n            return GetPreview(previewWidth, previewHeight, curve, curve2, color, Color.clear, Color.clear, new Rect());\n        }\n\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, Color color, Color topFillColor, Color bottomFillColor, Rect curveRanges)\n        {\n            return GetPropertyPreviewFilled(previewWidth, previewHeight, true, curveRanges, property, color, topFillColor, bottomFillColor);\n        }\n\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, Color color, Rect curveRanges)\n        {\n            return GetPreview(previewWidth, previewHeight, property, color, Color.clear, Color.clear, curveRanges);\n        }\n\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, Color color, Color topFillColor, Color bottomFillColor)\n        {\n            return GetPropertyPreviewFilled(previewWidth, previewHeight, false, new Rect(), property, color, topFillColor, bottomFillColor);\n        }\n\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, Color color)\n        {\n            return GetPreview(previewWidth, previewHeight, property, color, Color.clear, Color.clear, new Rect());\n        }\n\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, Color color, Color topFillColor, Color bottomFillColor, Rect curveRanges)\n        {\n            return GetCurvePreviewFilled(previewWidth, previewHeight, true, curveRanges, curve, color, topFillColor, bottomFillColor);\n        }\n\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, Color color, Rect curveRanges)\n        {\n            return GetPreview(previewWidth, previewHeight, curve, color, Color.clear, Color.clear, curveRanges);\n        }\n\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, Color color, Color topFillColor, Color bottomFillColor)\n        {\n            return GetCurvePreviewFilled(previewWidth, previewHeight, false, new Rect(), curve, color, topFillColor, bottomFillColor);\n        }\n\n        public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, Color color)\n        {\n            return GetPreview(previewWidth, previewHeight, curve, color, Color.clear, Color.clear, new Rect());\n        }\n\n        public static extern Texture2D GenerateCurvePreview(int previewWidth, int previewHeight, Rect curveRanges, AnimationCurve curve, Color color, Texture2D existingTexture);\n\n        internal extern static void ClearCache();\n\n        private extern static Texture2D GetPropertyPreview(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, SerializedProperty property, Color color);\n        private extern static Texture2D GetPropertyPreviewFilled(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, SerializedProperty property, Color color, Color topFillColor, Color bottomFillColor);\n        private extern static Texture2D GetPropertyPreviewRegion(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, SerializedProperty property, SerializedProperty property2, Color color);\n        private extern static Texture2D GetPropertyPreviewRegionFilled(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, SerializedProperty property, SerializedProperty property2, Color color, Color topFillColor, Color bottomFillColor);\n        private extern static Texture2D GetCurvePreview(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, AnimationCurve curve, Color color);\n        private extern static Texture2D GetCurvePreviewFilled(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, AnimationCurve curve, Color color, Color topFillColor, Color bottomFillColor);\n        private extern static Texture2D GetCurvePreviewRegion(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, AnimationCurve curve, AnimationCurve curve2, Color color);\n        private extern static Texture2D GetCurvePreviewRegionFilled(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, AnimationCurve curve, AnimationCurve curve2, Color color, Color topFillColor, Color bottomFillColor);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AnimatorController.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Playables;\nusing UnityEngine.Animations;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEngineInternal;\nusing UnityEditor;\nusing System.Runtime.InteropServices;\n\nnamespace UnityEditor.Animations\n{\n    [NativeHeader(\"Modules/Animation/Animator.h\")]\n    [NativeHeader(\"Editor/Src/Animation/StateMachineBehaviourScripting.h\")]\n    [NativeHeader(\"Editor/Src/Animation/AnimatorController.bindings.h\")]\n    [NativeHeader(\"Modules/Animation/AnimatorController.h\")]\n    public partial class AnimatorController : RuntimeAnimatorController\n    {\n        public AnimatorController()\n        {\n            Internal_Create(this);\n        }\n\n        [FreeFunction(\"AnimatorControllerBindings::Internal_Create\")]\n        extern private static void Internal_Create([Writable] AnimatorController self);\n\n        extern public AnimatorControllerLayer[] layers\n        {\n            [FreeFunction(Name = \"AnimatorControllerBindings::GetLayers\", HasExplicitThis = true)]\n            get;\n            [FreeFunction(Name = \"AnimatorControllerBindings::SetLayers\", HasExplicitThis = true, ThrowsException = true)]\n            [param: Unmarshalled]\n            set;\n        }\n\n        extern public AnimatorControllerParameter[] parameters\n        {\n            [FreeFunction(Name = \"AnimatorControllerBindings::GetParameters\", HasExplicitThis = true)]\n            get;\n            [FreeFunction(Name = \"AnimatorControllerBindings::SetParameters\", HasExplicitThis = true, ThrowsException = true)]\n            [param: Unmarshalled]\n            set;\n        }\n\n        [FreeFunction(Name = \"AnimatorControllerBindings::GetEffectiveAnimatorController\")]\n        extern internal static AnimatorController GetEffectiveAnimatorController(Animator animator);\n\n\n        internal static AnimatorControllerPlayable FindAnimatorControllerPlayable(Animator animator, AnimatorController controller)\n        {\n            PlayableHandle handle = new PlayableHandle();\n            Internal_FindAnimatorControllerPlayable(ref handle, animator, controller);\n            if (!handle.IsValid())\n                return AnimatorControllerPlayable.Null;\n            return new AnimatorControllerPlayable(handle);\n        }\n\n        [FreeFunction(Name = \"AnimatorControllerBindings::Internal_FindAnimatorControllerPlayable\")]\n        extern internal static void Internal_FindAnimatorControllerPlayable(ref PlayableHandle ret, Animator animator, AnimatorController controller);\n\n        public static void SetAnimatorController(Animator animator, AnimatorController controller)\n        {\n            animator.runtimeAnimatorController = controller;\n        }\n\n        extern internal int IndexOfParameter(string name);\n        extern internal void RenameParameter(string prevName, string newName);\n        extern public string MakeUniqueParameterName(string name);\n        extern public string MakeUniqueLayerName(string name);\n\n        static public StateMachineBehaviourContext[] FindStateMachineBehaviourContext(StateMachineBehaviour behaviour)\n        {\n            return Internal_FindStateMachineBehaviourContext(behaviour);\n        }\n\n        [FreeFunction(\"FindStateMachineBehaviourContext\")]\n        extern internal static StateMachineBehaviourContext[] Internal_FindStateMachineBehaviourContext(ScriptableObject behaviour);\n\n        [FreeFunction(\"AnimatorControllerBindings::Internal_CreateStateMachineBehaviour\")]\n        extern public static int CreateStateMachineBehaviour(MonoScript script);\n\n        [FreeFunction(\"AnimatorControllerBindings::CanAddStateMachineBehaviours\")]\n        extern internal static  bool CanAddStateMachineBehaviours();\n\n        extern internal MonoScript GetBehaviourMonoScript(AnimatorState state, int layerIndex, int behaviourIndex);\n\n        [FreeFunction]\n        extern private static ScriptableObject ScriptingAddStateMachineBehaviourWithType(Type stateMachineBehaviourType, [NotNull] AnimatorController controller, [NotNull] AnimatorState state, int layerIndex);\n\n\n        [TypeInferenceRule(TypeInferenceRules.TypeReferencedByFirstArgument)]\n        public StateMachineBehaviour AddEffectiveStateMachineBehaviour(Type stateMachineBehaviourType, AnimatorState state, int layerIndex)\n        {\n            return (StateMachineBehaviour)ScriptingAddStateMachineBehaviourWithType(stateMachineBehaviourType, this, state, layerIndex);\n        }\n\n        public T AddEffectiveStateMachineBehaviour<T>(AnimatorState state, int layerIndex) where T : StateMachineBehaviour\n        {\n            return AddEffectiveStateMachineBehaviour(typeof(T), state, layerIndex) as T;\n        }\n\n        public T[] GetBehaviours<T>() where T : StateMachineBehaviour\n        {\n            return ConvertStateMachineBehaviour<T>(InternalGetBehaviours(typeof(T)));\n        }\n\n        [FreeFunction(Name = \"AnimatorControllerBindings::Internal_GetBehaviours\", HasExplicitThis = true)]\n        extern internal ScriptableObject[] InternalGetBehaviours([NotNull] Type type);\n\n        internal static T[] ConvertStateMachineBehaviour<T>(ScriptableObject[] rawObjects) where T : StateMachineBehaviour\n        {\n            if (rawObjects == null) return null;\n            T[] typedObjects = new T[rawObjects.Length];\n            for (int i = 0; i < typedObjects.Length; i++)\n                typedObjects[i] = (T)rawObjects[i];\n            return typedObjects;\n        }\n\n        extern internal UnityEngine.Object[] CollectObjectsUsingParameter(string parameterName);\n\n        internal extern  bool isAssetBundled\n        {\n            [NativeName(\"IsAssetBundled\")]\n            get;\n        }\n\n        extern internal void AddStateEffectiveBehaviour([NotNull] AnimatorState state, int layerIndex, int instanceID);\n        extern internal void RemoveStateEffectiveBehaviour([NotNull] AnimatorState state, int layerIndex, int behaviourIndex);\n\n        [FreeFunction(Name = \"AnimatorControllerBindings::Internal_GetEffectiveBehaviours\", HasExplicitThis = true)]\n        extern internal ScriptableObject[] Internal_GetEffectiveBehaviours([NotNull] AnimatorState state, int layerIndex);\n\n        [FreeFunction(Name = \"AnimatorControllerBindings::Internal_SetEffectiveBehaviours\", HasExplicitThis = true)]\n        extern internal void Internal_SetEffectiveBehaviours([NotNull] AnimatorState state, int layerIndex, [Unmarshalled] ScriptableObject[] behaviours);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AnimatorControllerLayer.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEditor;\nusing System.Runtime.InteropServices;\n\nnamespace UnityEditor.Animations\n{\n    public enum AnimatorLayerBlendingMode\n    {\n        Override = 0,\n        Additive = 1,\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/AnimatorControllerLayer.h\")]\n    [NativeHeader(\"Editor/Src/Animation/AnimatorControllerLayer.bindings.h\")]\n    [StructLayout(LayoutKind.Sequential)]\n    [NativeType(CodegenOptions.Custom, \"MonoStateMotionPair\")]\n    internal struct StateMotionPair\n    {\n        public AnimatorState m_State;\n        public Motion m_Motion;\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/AnimatorControllerLayer.h\")]\n    [NativeHeader(\"Editor/Src/Animation/AnimatorControllerLayer.bindings.h\")]\n    [StructLayout(LayoutKind.Sequential)]\n    [NativeType(CodegenOptions.Custom, \"MonoStateBehavioursPair\")]\n    internal struct StateBehavioursPair\n    {\n        public AnimatorState m_State;\n        public ScriptableObject[] m_Behaviours;\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/AnimatorControllerLayer.h\")]\n    [NativeHeader(\"Editor/Src/Animation/AnimatorControllerLayer.bindings.h\")]\n    [StructLayout(LayoutKind.Sequential)]\n    [NativeAsStruct]\n    [NativeType(CodegenOptions.Custom, \"MonoAnimatorControllerLayer\")]\n    public partial class AnimatorControllerLayer\n    {\n        public string                     name                        {   get { return m_Name; }                      set { m_Name = value; }  }\n        public AnimatorStateMachine       stateMachine                {   get { return m_StateMachine; }              set { m_StateMachine = value; }  }\n        public AvatarMask                 avatarMask                  {   get { return m_AvatarMask; }                set { m_AvatarMask = value; }    }\n        public AnimatorLayerBlendingMode  blendingMode                {   get { return m_BlendingMode; }              set { m_BlendingMode = value; }  }\n        public int                        syncedLayerIndex            {   get { return m_SyncedLayerIndex; }          set { m_SyncedLayerIndex = value; }  }\n        public bool                       iKPass                      {   get { return m_IKPass; }                    set { m_IKPass = value; }    }\n        public float                      defaultWeight               {   get { return m_DefaultWeight; }             set { m_DefaultWeight = value; } }\n        public bool                       syncedLayerAffectsTiming    {   get { return m_SyncedLayerAffectsTiming; }  set { m_SyncedLayerAffectsTiming = value; }}\n\n        public Motion                     GetOverrideMotion(AnimatorState state)\n        {\n            if (m_Motions != null)\n                foreach (StateMotionPair pair in m_Motions)\n                    if (pair.m_State == state)\n                        return pair.m_Motion;\n\n            return null;\n        }\n\n        public void                       SetOverrideMotion(AnimatorState state, Motion motion)\n        {\n            if (m_Motions == null) m_Motions =  new StateMotionPair[] {};\n            for (int i = 0; i < m_Motions.Length; ++i)\n            {\n                if (m_Motions[i].m_State == state)\n                {\n                    m_Motions[i].m_Motion = motion;\n                    return;\n                }\n            }\n\n            StateMotionPair newPair;\n            newPair.m_State = state;\n            newPair.m_Motion = motion;\n            ArrayUtility.Add(ref m_Motions, newPair);\n        }\n\n        public StateMachineBehaviour[]    GetOverrideBehaviours(AnimatorState state)\n        {\n            if (m_Behaviours != null)\n            {\n                foreach (StateBehavioursPair pair in m_Behaviours)\n                {\n                    if (pair.m_State == state)\n                        return pair.m_Behaviours as StateMachineBehaviour[];\n                }\n            }\n            return new StateMachineBehaviour[0];\n        }\n\n        public void                           SetOverrideBehaviours(AnimatorState state, StateMachineBehaviour[] behaviours)\n        {\n            if (m_Behaviours == null) m_Behaviours =  new StateBehavioursPair[] {};\n            for (int i = 0; i < m_Behaviours.Length; ++i)\n            {\n                if (m_Behaviours[i].m_State == state)\n                {\n                    m_Behaviours[i].m_Behaviours = behaviours;\n                    return;\n                }\n            }\n\n            StateBehavioursPair newPair;\n            newPair.m_State = state;\n            newPair.m_Behaviours = behaviours;\n            ArrayUtility.Add(ref m_Behaviours, newPair);\n        }\n\n        string                            m_Name;\n        AnimatorStateMachine              m_StateMachine;\n        AvatarMask                        m_AvatarMask;\n        StateMotionPair[]                 m_Motions;\n        StateBehavioursPair[]             m_Behaviours;\n        AnimatorLayerBlendingMode         m_BlendingMode;\n        int                               m_SyncedLayerIndex = -1;\n        bool                              m_IKPass;\n        float                             m_DefaultWeight;\n        bool                              m_SyncedLayerAffectsTiming;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Annotation/AnnotationUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeType(CodegenOptions.Custom, \"AnnotationBindings\")]\n    struct Annotation\n    {\n        public int iconEnabled;\n        public int gizmoEnabled;\n        public int flags;\n        public int classID;\n        public string scriptClass;\n    }\n\n    [NativeHeader(\"Editor/Mono/Annotation/AnnotationUtility.bindings.h\")]\n    [NativeHeader(\"Editor/Src/Gizmos/AnnotationManager.h\")]\n    static class AnnotationUtility\n    {\n        // Similar values as in Annotation (in AnnotationManager.h)\n        public enum Flags\n        {\n            kHasIcon = 1 << 0,\n            kHasGizmo = 1 << 1,\n            kIsDisabled = 1 << 2\n        };\n\n        extern internal static  Annotation[] GetAnnotations();\n\n        extern internal static  Annotation[] GetRecentlyChangedAnnotations();\n\n        extern internal static Annotation GetAnnotation(int classID, string scriptClass);\n\n        [StaticAccessor(\"GetAnnotationManager()\", StaticAccessorType.Dot)]\n        extern internal static  string GetNameOfCurrentSetup();\n\n        extern internal static  void SetGizmoEnabled(int classID, string scriptClass, int gizmoEnabled, bool addToMostRecentChanged);\n\n        extern internal static  void SetIconEnabled(int classID, string scriptClass, int iconEnabled);\n\n        [StaticAccessor(\"GizmoManager::Get()\", StaticAccessorType.Dot)]\n        extern internal static  int SetGizmosDirty();\n\n        [StaticAccessor(\"GetAnnotationManager()\", StaticAccessorType.Dot)]\n        extern internal static  string[] GetPresetList();\n\n        [StaticAccessor(\"GetAnnotationManager()\", StaticAccessorType.Dot)]\n        extern internal static  void LoadPreset(string presetName);\n\n        [StaticAccessor(\"GetAnnotationManager()\", StaticAccessorType.Dot)]\n        extern internal static  void SavePreset(string presetName);\n\n        [StaticAccessor(\"GetAnnotationManager()\", StaticAccessorType.Dot)]\n        extern internal static  void DeletePreset(string presetName);\n\n        [StaticAccessor(\"GetAnnotationManager()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"ResetPresetsToFactorySettings\")]\n        extern internal static  void ResetToFactorySettings();\n\n        [StaticAccessor(\"GetAnnotationManager()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"3dGizmosEnabled\")]\n        internal extern static bool use3dGizmos { get; set; }\n\n        [StaticAccessor(\"GetAnnotationManager()\", StaticAccessorType.Dot)]\n        // Thomas Tu: 2019-06-20. Will be marked as Obsolete.\n        // We need to deal with code dependency in packages first.\n        internal extern static bool showGrid { get; set; }\n\n        [StaticAccessor(\"GetAnnotationManager()\", StaticAccessorType.Dot)]\n        internal extern static bool showSelectionOutline { get; set; }\n\n        [StaticAccessor(\"GetAnnotationManager()\", StaticAccessorType.Dot)]\n        internal extern static bool showSelectionWire { get; set; }\n\n        [StaticAccessor(\"GetAnnotationManager()\", StaticAccessorType.Dot)]\n        internal extern static float iconSize { get; set; }\n\n        [StaticAccessor(\"GetAnnotationManager()\", StaticAccessorType.Dot)]\n        internal extern static float fadeGizmoSize { get; set; }\n\n        [StaticAccessor(\"GetAnnotationManager()\", StaticAccessorType.Dot)]\n        internal extern static bool fadeGizmos { get; set; }\n\n        [StaticAccessor(\"GetAnnotationManager()\", StaticAccessorType.Dot)]\n        internal extern static bool useInspectorExpandedState { get; set; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Annotation/AnnotationWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditor.ShortcutManagement;\n\nnamespace UnityEditor\n{\n    internal class AnnotationWindow : EditorWindow\n    {\n        private static SavedBool s_ShowTerrainDebugWarnings = new SavedBool(\"Terrain.ShowDebugWarnings\", true);\n\n        public static bool ShowTerrainDebugWarnings\n        {\n            get => s_ShowTerrainDebugWarnings.value;\n            set => s_ShowTerrainDebugWarnings.value = value;\n        }\n\n        class Styles\n        {\n            public GUIStyle toggle = \"Toggle\";\n            public GUIStyle toggleMixed = EditorStyles.toggleMixed;\n            public GUIStyle listEvenBg = \"ObjectPickerResultsOdd\";//\"ObjectPickerResultsEven\";//\n            public GUIStyle listOddBg = \"ObjectPickerResultsEven\";//\"ObjectPickerResultsEven\";//\n            public GUIStyle background = \"grey_border\";\n            public GUIStyle seperator = \"sv_iconselector_sep\";\n            public GUIStyle iconDropDown = \"IN dropdown\";\n            public GUIStyle listTextStyle;\n            public GUIStyle listHeaderStyle;\n            public GUIStyle columnHeaderStyle;\n            public const float k_ToggleSize = 17f;\n\n            public Styles()\n            {\n                listTextStyle = new GUIStyle(EditorStyles.label);\n                listTextStyle.alignment = TextAnchor.MiddleLeft;\n                listTextStyle.padding.left = 10;\n\n                listHeaderStyle = new GUIStyle(EditorStyles.boldLabel);\n                listHeaderStyle.padding.left = 5;\n\n                columnHeaderStyle = EditorStyles.miniLabel;\n            }\n        }\n\n        private enum EnabledState\n        {\n            NotSet = -1,\n            None = 0,\n            All = 1,\n            Mixed = 2\n        }\n\n        const float k_WindowWidth = 270;\n        const float k_ScrollBarWidth = 14;\n        const float k_ListElementHeight = 18;\n        const float k_FrameWidth = 1f;\n        float iconSize = 16;\n        float gizmoRightAlign;\n        float gizmoTextRightAlign;\n        float iconRightAlign;\n        float iconTextRightAlign;\n\n        static AnnotationWindow s_AnnotationWindow = null;\n        static long s_LastClosedTime;\n        const long k_JustClosedPeriod = 400;\n\n        static Styles m_Styles;\n        List<GizmoInfo> m_RecentAnnotations;\n        List<GizmoInfo> m_BuiltinAnnotations;\n        List<GizmoInfo> m_ScriptAnnotations;\n        Vector2 m_ScrollPosition;\n        bool m_SyncWithState;\n        string m_LastScriptThatHasShownTheIconSelector;\n\n        List<MonoScript> m_MonoScriptIconsChanged;\n\n        const int maxShowRecent = 5;\n        readonly string textGizmoVisible = L10n.Tr(\"Show/Hide Gizmo\");\n        GUIContent generalContent = EditorGUIUtility.TrTextContent(\"General\");\n        GUIContent iconToggleContent = EditorGUIUtility.TrTextContent(\"\", \"Show/Hide Icon\");\n        GUIContent iconSelectContent = EditorGUIUtility.TrTextContent(\"\", \"Select Icon\");\n        GUIContent icon3dGizmoContent = EditorGUIUtility.TrTextContent(\"3D Icons\");\n        GUIContent terrainDebugWarnings = EditorGUIUtility.TrTextContent(\"Terrain Debug Warnings\");\n        GUIContent showOutlineContent = EditorGUIUtility.TrTextContent(\"Selection Outline\");\n        GUIContent showWireframeContent = EditorGUIUtility.TrTextContent(\"Selection Wire\");\n        GUIContent fadeGizmosContent = EditorGUIUtility.TrTextContent(\"Fade Gizmos\", \"Fade out and stop rendering gizmos that are small on screen\");\n        GUIContent lightProbeVisualizationContent = EditorGUIUtility.TrTextContent(\"Light Probe Visualization\");\n        GUIContent displayWeightsContent = EditorGUIUtility.TrTextContent(\"Display Weights\");\n        GUIContent displayOcclusionContent = EditorGUIUtility.TrTextContent(\"Display Occlusion\");\n        GUIContent highlightInvalidCellsContent = EditorGUIUtility.TrTextContent(\"Highlight Invalid Cells\", \"Highlight the invalid cells that cannot be used for probe interpolation.\");\n        private bool m_IsGameView;\n\n        string m_SearchFilter = string.Empty;\n\n        const float exponentStart = -3.0f;\n        const float exponentRange = 3.0f;\n\n        static float ConvertTexelWorldSizeTo01(float texelWorldSize)\n        {\n            if (texelWorldSize == -1.0f)\n                return 1.0f;\n            if (texelWorldSize == 0.0f)\n                return 0.0f;\n            return (Mathf.Log10(texelWorldSize) - exponentStart) / exponentRange;\n        }\n\n        static float Convert01ToTexelWorldSize(float value01)\n        {\n            if (value01 <= 0.0f)\n                return 0.0f; // always hidden\n            return Mathf.Pow(10.0f, exponentStart + exponentRange * value01); // texel size is between 10e-2 (0.01) and 10e2 (100) worldunits. (texel in the icon texture)\n        }\n\n        public void MonoScriptIconChanged(MonoScript monoScript)\n        {\n            if (monoScript == null)\n                return;\n\n            bool add = true;\n            foreach (MonoScript m in m_MonoScriptIconsChanged)\n                if (m.GetInstanceID() == monoScript.GetInstanceID())\n                    add = false;\n\n            if (add)\n                m_MonoScriptIconsChanged.Add(monoScript);\n        }\n\n        static public void IconChanged()\n        {\n            if (s_AnnotationWindow != null)\n                s_AnnotationWindow.IconHasChanged();\n        }\n\n        float GetTopSectionHeight()\n        {\n            const int numberOfGeneralControls = 6;\n\n            int numberOfLightProbeVisualizationControls = 0;\n            if (!UnityEngine.Rendering.SupportedRenderingFeatures.active.overridesLightProbeSystem)\n            {\n                if (LightProbeVisualization.lightProbeVisualizationMode == LightProbeVisualization.LightProbeVisualizationMode.None)\n                    numberOfLightProbeVisualizationControls = 3;\n                else\n                    numberOfLightProbeVisualizationControls = 5;\n            }\n\n            int numberOfControls = numberOfGeneralControls + numberOfLightProbeVisualizationControls;\n            return EditorGUI.kSingleLineHeight * numberOfControls + EditorGUI.kControlVerticalSpacing * (numberOfControls - 1) + EditorStyles.inspectorBig.padding.bottom;\n        }\n\n        void OnEnable()\n        {\n            AssemblyReloadEvents.beforeAssemblyReload += Close;\n            hideFlags = HideFlags.DontSave;\n        }\n\n        void OnDisable()\n        {\n            AssemblyReloadEvents.beforeAssemblyReload -= Close;\n            // When window closes we copy all changes to monoimporters (reimport monoScripts)\n            foreach (MonoScript monoScript in m_MonoScriptIconsChanged)\n                IconSelector.CopyIconToImporter(monoScript);\n\n            s_LastClosedTime = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond;\n            s_AnnotationWindow = null;\n        }\n\n        internal static bool ShowAtPosition(Rect buttonRect, bool isGameView)\n        {\n            // We could not use realtimeSinceStartUp since it is set to 0 when entering/exitting playmode, we assume an increasing time when comparing time.\n            long nowMilliSeconds = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond;\n            bool justClosed = nowMilliSeconds < s_LastClosedTime + k_JustClosedPeriod;\n            if (!justClosed)\n            {\n                Event.current.Use();\n                if (s_AnnotationWindow == null)\n                    s_AnnotationWindow = ScriptableObject.CreateInstance<AnnotationWindow>();\n                else\n                {\n                    // We are treating AnnotationWindow like a PopupWindow which has logic to reclose it when opened,\n                    // AuxWindows derived from EditorWindow reset/reopen when repeatedly clicking the open button by design.\n                    // Call Cancel() here if it is already open.\n                    s_AnnotationWindow.Cancel();\n                    return false;\n                }\n\n                s_AnnotationWindow.Init(buttonRect, isGameView);\n                return true;\n            }\n            return false;\n        }\n\n        void Init(Rect buttonRect, bool isGameView)\n        {\n            // Has to be done before calling Show / ShowWithMode\n            buttonRect = GUIUtility.GUIToScreenRect(buttonRect);\n\n            m_MonoScriptIconsChanged = new List<MonoScript>();\n\n            m_SyncWithState = true;\n\n            m_IsGameView = isGameView;\n\n            SyncToState();\n\n            float windowHeight = 2 * k_FrameWidth + GetTopSectionHeight() + DrawNormalList(false, 100, 0, 10000);\n            windowHeight = Mathf.Min(windowHeight, 900);\n            Vector2 windowSize = new Vector2(k_WindowWidth, windowHeight);\n\n            ShowAsDropDown(buttonRect, windowSize);\n        }\n\n        private void IconHasChanged()\n        {\n            if (string.IsNullOrEmpty(m_LastScriptThatHasShownTheIconSelector))\n                return;\n\n            foreach (GizmoInfo t in m_ScriptAnnotations)\n            {\n                if (t.scriptClass == m_LastScriptThatHasShownTheIconSelector)\n                {\n                    if (t.iconEnabled == false)\n                    {\n                        t.iconEnabled = true;\n                        SetIconState(t);\n                        break;\n                    }\n                }\n            }\n            SyncToState();\n\n            Repaint();\n        }\n\n        void Cancel()\n        {\n            // Undo changes we have done.\n            // PerformTemporaryUndoStack must be called before Close() below\n            // to ensure that we properly undo changes before closing window.\n            //Undo.PerformTemporaryUndoStack();\n\n            Close();\n            GUI.changed = true;\n            GUIUtility.ExitGUI();\n        }\n\n        GizmoInfo GetAInfo(int classID, string scriptClass)\n        {\n            if (scriptClass != \"\")\n                return m_ScriptAnnotations.Find(delegate(GizmoInfo o) { return o.scriptClass == scriptClass; });\n\n            return m_BuiltinAnnotations.Find(delegate(GizmoInfo o) { return o.classID == classID; });\n        }\n\n        private void SyncToState()\n        {\n            // Sync annotations\n            Annotation[] a = AnnotationUtility.GetAnnotations();\n\n            m_BuiltinAnnotations = new List<GizmoInfo>();\n            m_ScriptAnnotations = new List<GizmoInfo>();\n            for (int i = 0; i < a.Length; ++i)\n            {\n                GizmoInfo anno = new GizmoInfo(a[i]);\n\n                if(string.IsNullOrEmpty(anno.scriptClass))\n                    m_BuiltinAnnotations.Add(anno);\n                else\n                    m_ScriptAnnotations.Add(anno);\n            }\n\n            m_BuiltinAnnotations.Sort();\n            m_ScriptAnnotations.Sort();\n\n            // Sync recently changed annotations\n            m_RecentAnnotations = new List<GizmoInfo>();\n            Annotation[] recent = AnnotationUtility.GetRecentlyChangedAnnotations();\n            for (int i = 0; i < recent.Length && i < maxShowRecent; ++i)\n            {\n                // Note: ainfo can be null if script has been renamed.\n                GizmoInfo ainfo = GetAInfo(recent[i].classID, recent[i].scriptClass);\n                if (ainfo != null)\n                    m_RecentAnnotations.Add(ainfo);\n            }\n\n            m_SyncWithState = false;\n        }\n\n        internal void OnGUI()\n        {\n            if (m_Styles == null)\n                m_Styles = new Styles();\n\n            if (m_SyncWithState)\n                SyncToState();\n\n            // Content\n            float topSectionHeight = GetTopSectionHeight();\n            DrawTopSection(topSectionHeight);\n            DrawAnnotationList(topSectionHeight, position.height - topSectionHeight);\n\n            // Background with 1 pixel border\n            if (Event.current.type == EventType.Repaint)\n                m_Styles.background.Draw(new Rect(0, 0, position.width, position.height), GUIContent.none, false, false, false, false);\n\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)\n                Cancel();\n        }\n\n        // ------------------------------------\n        // TOP SECTION\n        // ------------------------------------\n        void DrawTopSection(float topSectionHeight)\n        {\n            // Bg\n            GUI.Label(new Rect(k_FrameWidth, 0, position.width - 2 * k_FrameWidth, topSectionHeight), \"\", EditorStyles.inspectorBig);\n\n            float topmargin = 7;\n            float margin = 11;\n            float curY = topmargin;\n\n            float labelWidth = m_Styles.listHeaderStyle.CalcSize(terrainDebugWarnings).x + GUI.skin.toggle.CalcSize(GUIContent.none).x + 1;\n            float rowHeight = 18;\n\n            // General section\n            Rect toggleRect = new Rect(margin, curY, labelWidth, rowHeight);\n            GUI.Label(toggleRect, generalContent, EditorStyles.boldLabel);\n            curY += rowHeight;\n\n            // 3D icons toggle & slider\n            toggleRect = new Rect(margin, curY, labelWidth, rowHeight);\n            AnnotationUtility.use3dGizmos = GUI.Toggle(toggleRect, AnnotationUtility.use3dGizmos, icon3dGizmoContent);\n            using (new EditorGUI.DisabledScope(!AnnotationUtility.use3dGizmos))\n            {\n                float texelWorldSize = AnnotationUtility.iconSize;\n                float sliderWidth = position.width - margin - labelWidth;\n                float iconSize01 = ConvertTexelWorldSizeTo01(texelWorldSize);\n                Rect sliderRect = new Rect(labelWidth + margin, curY, sliderWidth - margin, rowHeight);\n                iconSize01 = GUI.HorizontalSlider(sliderRect, iconSize01, 0.0f, 1.0f);\n                if (GUI.changed)\n                {\n                    AnnotationUtility.iconSize = Convert01ToTexelWorldSize(iconSize01);\n                    SceneView.RepaintAll();\n                }\n            }\n            curY += rowHeight;\n\n            // Gizmo fadeout toggle & slider\n            toggleRect = new Rect(margin, curY, labelWidth, rowHeight);\n            AnnotationUtility.fadeGizmos = GUI.Toggle(toggleRect, AnnotationUtility.fadeGizmos, fadeGizmosContent);\n            using (new EditorGUI.DisabledScope(!AnnotationUtility.fadeGizmos))\n            {\n                float fadeSize = AnnotationUtility.fadeGizmoSize;\n                float sliderWidth = position.width - margin - labelWidth;\n                Rect sliderRect = new Rect(labelWidth + margin, curY, sliderWidth - margin, rowHeight);\n                float newFadeSize = GUI.HorizontalSlider(sliderRect, fadeSize, 2.0f, 10.0f);\n                if (fadeSize != newFadeSize)\n                {\n                    AnnotationUtility.fadeGizmoSize = newFadeSize;\n                    SceneView.RepaintAll();\n                }\n            }\n            curY += rowHeight;\n\n            using (new EditorGUI.DisabledScope(m_IsGameView))\n            {\n                // Selection outline/wire\n                toggleRect = new Rect(margin, curY, labelWidth, rowHeight);\n                AnnotationUtility.showSelectionOutline = GUI.Toggle(toggleRect, AnnotationUtility.showSelectionOutline, showOutlineContent);\n                curY += rowHeight;\n\n                toggleRect = new Rect(margin, curY, labelWidth, rowHeight);\n                AnnotationUtility.showSelectionWire = GUI.Toggle(toggleRect, AnnotationUtility.showSelectionWire, showWireframeContent);\n                curY += rowHeight;\n\n                // TODO: Change to Debug Errors & Debug Warnings\n                toggleRect = new Rect(margin, curY, labelWidth, rowHeight);\n                EditorGUI.BeginChangeCheck();\n                s_ShowTerrainDebugWarnings.value = GUI.Toggle(toggleRect, s_ShowTerrainDebugWarnings.value, terrainDebugWarnings);\n                if (EditorGUI.EndChangeCheck())\n                    SceneView.RepaintAll();\n            }\n            curY += rowHeight;\n\n            // Light probe section\n            if (!UnityEngine.Rendering.SupportedRenderingFeatures.active.overridesLightProbeSystem)\n            {\n                curY += rowHeight;\n                toggleRect = new Rect(margin, curY, labelWidth, rowHeight);\n                GUI.Label(toggleRect, lightProbeVisualizationContent, EditorStyles.boldLabel);\n                curY += rowHeight;\n\n                toggleRect = new Rect(margin, curY, position.width - margin * 2, rowHeight);\n                LightProbeVisualization.lightProbeVisualizationMode = (LightProbeVisualization.LightProbeVisualizationMode)EditorGUI.EnumPopup(toggleRect, LightProbeVisualization.lightProbeVisualizationMode);\n                curY += rowHeight;\n\n                if (LightProbeVisualization.lightProbeVisualizationMode != LightProbeVisualization.LightProbeVisualizationMode.None)\n                {\n                    toggleRect = new Rect(margin, curY, labelWidth, rowHeight);\n                    LightProbeVisualization.showInterpolationWeights = GUI.Toggle(toggleRect, LightProbeVisualization.showInterpolationWeights, displayWeightsContent);\n                    curY += rowHeight;\n\n                    toggleRect = new Rect(margin, curY, labelWidth, rowHeight);\n                    LightProbeVisualization.showOcclusions = GUI.Toggle(toggleRect, LightProbeVisualization.showOcclusions, displayOcclusionContent);\n                    curY += rowHeight;\n\n                    toggleRect = new Rect(margin, curY, labelWidth, rowHeight);\n                    LightProbeVisualization.highlightInvalidCells = GUI.Toggle(toggleRect, LightProbeVisualization.highlightInvalidCells, highlightInvalidCellsContent);\n                }\n            }\n        }\n\n        // ------------------------------------\n        // ANNOTATION SECTION\n        // ------------------------------------\n\n        // Returns height used\n        void DrawAnnotationList(float startY, float height)\n        {\n            // Calc sizes\n            const float barHeight = 1;\n            Rect scrollViewRect = new Rect(0,\n                startY + barHeight,\n                position.width - 4,\n                height - barHeight - k_FrameWidth);\n            float totalContentHeight = DrawNormalList(false, 0, 0, 100000);\n            Rect contentRect = new Rect(0, 0, 1, totalContentHeight);\n            bool isScrollbarVisible = totalContentHeight > scrollViewRect.height;\n            float listElementWidth = scrollViewRect.width;\n            if (isScrollbarVisible)\n                listElementWidth -= k_ScrollBarWidth;\n\n            // Scrollview\n            m_ScrollPosition = GUI.BeginScrollView(scrollViewRect, m_ScrollPosition, contentRect, false, false, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar, EditorStyles.scrollViewAlt);\n            {\n                DrawNormalList(true, listElementWidth, m_ScrollPosition.y - k_ListElementHeight, m_ScrollPosition.y + totalContentHeight);\n            }\n            GUI.EndScrollView();\n        }\n\n        void Flip(ref bool even)\n        {\n            even = !even;\n        }\n\n        float DrawNormalList(bool doDraw, float listElementWidth, float startY, float endY)\n        {\n            bool even = true;\n            float curY = 0;\n            bool headerDrawn = false;\n            bool searchDrawn = false;\n\n            curY = DrawListSection(curY, L10n.Tr(\"Recently Changed\"),    m_RecentAnnotations,    doDraw, listElementWidth, startY, endY, ref even, true,  ref headerDrawn, ref searchDrawn);\n            curY = DrawListSection(curY, L10n.Tr(\"Scripts\"),             m_ScriptAnnotations,    doDraw, listElementWidth, startY, endY, ref even, false, ref headerDrawn, ref searchDrawn);\n            curY = DrawListSection(curY, L10n.Tr(\"Built-in Components\"), m_BuiltinAnnotations,   doDraw, listElementWidth, startY, endY, ref even, false, ref headerDrawn, ref searchDrawn);\n\n            return curY;\n        }\n\n        bool DoesMatchFilter(GizmoInfo el)\n        {\n            if (string.IsNullOrEmpty(m_SearchFilter))\n                return true;\n            if (el.name.IndexOf(m_SearchFilter, System.StringComparison.OrdinalIgnoreCase) < 0)\n                return false;\n            return true;\n        }\n\n        float DrawListSection(float y, string sectionHeader, List<GizmoInfo> listElements, bool doDraw, float listElementWidth, float startY, float endY, ref bool even, bool useSeperator, ref bool headerDrawn, ref bool searchDrawn)\n        {\n            float curY = y;\n            const float kSearchPaddingV = 3;\n            const float kSearchHeight = EditorGUI.kSingleSmallLineHeight + kSearchPaddingV;\n            const float extraHeader = 15;\n            const float headerHeight = 20;\n\n            if (listElements.Count > 0)\n            {\n                if (doDraw)\n                {\n                    // Header background\n                    Rect rect = new Rect(1, curY, listElementWidth - 2, extraHeader + (headerDrawn ? 0 : kSearchHeight) + headerHeight);\n                    Flip(ref even);\n                    GUIStyle backgroundStyle = even ? m_Styles.listEvenBg : m_Styles.listOddBg; // m_Styles.listSectionHeaderBg;//\n                    GUI.Label(rect, GUIContent.Temp(\"\"), backgroundStyle);\n                }\n\n                // Search field\n                if (!searchDrawn)\n                {\n                    searchDrawn = true;\n                    if (doDraw)\n                    {\n                        Rect searchRect = new Rect(11, curY + kSearchPaddingV, listElementWidth - 16, EditorGUI.kSingleSmallLineHeight);\n                        m_SearchFilter = EditorGUI.ToolbarSearchField(searchRect, m_SearchFilter, false);\n                    }\n                    curY += kSearchHeight;\n                }\n\n                curY += extraHeader;\n                if (doDraw)\n                {\n                    // Header text\n                    DrawListHeader(sectionHeader, listElements, new Rect(3, curY, listElementWidth, headerHeight), ref headerDrawn);\n                }\n                curY += headerHeight;\n\n                // List elements\n                for (int i = 0; i < listElements.Count; ++i)\n                {\n                    if (!DoesMatchFilter(listElements[i]))\n                        continue;\n                    Flip(ref even);\n                    if (curY > startY && curY < endY)\n                    {\n                        Rect rect = new Rect(1, curY, listElementWidth - 2, k_ListElementHeight);\n                        if (doDraw)\n                            DrawListElement(rect, even, listElements[i]);\n                    }\n                    curY += k_ListElementHeight;\n                }\n\n                if (useSeperator)\n                {\n                    float height = 6;\n                    if (doDraw)\n                    {\n                        GUIStyle backgroundStyle = even ? m_Styles.listEvenBg : m_Styles.listOddBg;\n                        GUI.Label(new Rect(1, curY, listElementWidth - 2, height), GUIContent.Temp(\"\"), backgroundStyle);\n                        GUI.Label(new Rect(10, curY + 3, listElementWidth - 15, 3), GUIContent.Temp(\"\"), m_Styles.seperator);\n                    }\n                    curY += height;\n                }\n            }\n\n            return curY;\n        }\n\n        void DrawListHeader(string header, List<GizmoInfo> elements, Rect rect, ref bool headerDrawn)\n        {\n            GUI.Label(rect, GUIContent.Temp(header), m_Styles.listHeaderStyle);\n\n            float toggleSize = Styles.k_ToggleSize;\n            EnabledState enabledState = EnabledState.NotSet;\n\n            for (int i = 0; i < elements.Count; i++)\n            {\n                var element = elements[i];\n                if (!DoesMatchFilter(element))\n                    continue;\n\n                if (element.hasGizmo)\n                {\n                    if (enabledState == EnabledState.NotSet)\n                    {\n                        enabledState = element.gizmoEnabled ? EnabledState.All : EnabledState.None;\n                    }\n                    else if ((enabledState == EnabledState.All) != element.gizmoEnabled)\n                    {\n                        enabledState = EnabledState.Mixed;\n                        break;\n                    }\n                }\n            }\n\n            if (enabledState == EnabledState.NotSet)\n                return;\n\n            var gizmoText = \"gizmo\";\n            var gizmoTextSize = m_Styles.columnHeaderStyle.CalcSize(new GUIContent(gizmoText));\n            gizmoTextRightAlign = gizmoTextSize.x;\n            gizmoRightAlign = gizmoTextRightAlign - (gizmoTextSize.x * 0.5f - m_Styles.toggle.CalcSize(GUIContent.none).x*0.5f);\n            var iconText = \"icon\";\n            var iconTextSize = m_Styles.columnHeaderStyle.CalcSize(new GUIContent(iconText));\n            iconTextRightAlign = iconTextSize.x + gizmoTextRightAlign + 10;\n            iconRightAlign = iconTextRightAlign - (iconTextSize.x * 0.5f - iconSize * 0.5f);\n\n\n            GUIStyle style = m_Styles.toggle;\n            bool enabled = enabledState == EnabledState.All;\n            bool setMixed = enabledState == EnabledState.Mixed;\n            if (setMixed)\n                style = m_Styles.toggleMixed;\n\n            Rect toggleRect = new Rect(rect.width - gizmoRightAlign, rect.y + (rect.height - toggleSize) * 0.5f, toggleSize, toggleSize);\n\n            EditorGUI.BeginChangeCheck();\n            bool newEnabled = GUI.Toggle(toggleRect, enabled, GUIContent.none, style);\n            if (EditorGUI.EndChangeCheck())\n            {\n                for (int i = 0; i < elements.Count; i++)\n                {\n                    var element = elements[i];\n                    if (!DoesMatchFilter(element))\n                        continue;\n\n                    if (element.gizmoEnabled != newEnabled)\n                    {\n                        element.gizmoEnabled = newEnabled;\n                        SetGizmoState(element, false);\n                    }\n                }\n            }\n\n            if (headerDrawn == false)\n            {\n                headerDrawn = true;\n                GUI.color = new Color(1, 1, 1, 0.65f);\n\n                //  Column headers\n                Rect columnRect = rect;\n                columnRect.y -= gizmoTextSize.y + 3;\n                columnRect.x = rect.width - gizmoTextRightAlign;\n                GUI.Label(columnRect, gizmoText, m_Styles.columnHeaderStyle);\n\n                columnRect.x = rect.width - iconTextRightAlign;\n                GUI.Label(columnRect, iconText, m_Styles.columnHeaderStyle);\n\n                GUI.color = Color.white;\n            }\n        }\n\n        void DrawListElement(Rect rect, bool even, GizmoInfo ainfo)\n        {\n            if (ainfo == null)\n            {\n                Debug.LogError(\"DrawListElement: AInfo not valid!\");\n                return;\n            }\n\n            string tooltip;\n            float togglerSize = Styles.k_ToggleSize;\n            float disabledAlpha = 0.3f;\n\n            // We maintain our own gui.changed\n            bool orgGUIChanged = GUI.changed;\n            bool orgGUIEnabled = GUI.enabled;\n            Color orgColor = GUI.color;\n            GUI.changed = false;\n            GUI.enabled = true;\n\n            // Bg\n            GUIStyle backgroundStyle = even ? m_Styles.listEvenBg : m_Styles.listOddBg;\n            GUI.Label(rect, GUIContent.Temp(\"\"), backgroundStyle);\n\n\n            // Text\n            Rect textRect = rect;\n            //textRect.x += 22;\n            textRect.width = rect.width - iconRightAlign - 22; // ensure text doesnt flow behind toggles\n            GUI.Label(textRect, ainfo.name, m_Styles.listTextStyle);\n\n\n            // Icon toggle\n            Rect iconRect = new Rect(rect.width - iconRightAlign + 2, rect.y + (rect.height - iconSize) * 0.5f, iconSize, iconSize); // +2 because the given rect is shortened by 2px before this method call\n            if (ainfo.scriptClass != \"\")\n            {\n                Rect div = iconRect;\n                div.x += 18;\n                div.y += 1;\n                div.width = 1;\n                div.height = 12;\n\n                if (!EditorGUIUtility.isProSkin)\n                    GUI.color = new Color(0, 0, 0, 0.33f);\n                else\n                    GUI.color = new Color(1, 1, 1, 0.13f);\n\n                GUI.DrawTexture(div, EditorGUIUtility.whiteTexture, ScaleMode.StretchToFill);\n                GUI.color = Color.white;\n\n                if (!ainfo.disabled)\n                {\n                    Rect arrowRect = iconRect;\n                    arrowRect.x += 18;\n                    arrowRect.y += 0;\n                    arrowRect.width = 9;\n\n                    if (GUI.Button(arrowRect, iconSelectContent, m_Styles.iconDropDown))\n                    {\n                        Object script = EditorGUIUtility.GetScript(ainfo.scriptClass);\n                        if (script != null)\n                        {\n                            m_LastScriptThatHasShownTheIconSelector = ainfo.scriptClass;\n                            if (IconSelector.ShowAtPosition(script, arrowRect, true))\n                            {\n                                IconSelector.SetMonoScriptIconChangedCallback(MonoScriptIconChanged);\n                                GUIUtility.ExitGUI();\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (ainfo.thumb != null)\n            {\n                if (!ainfo.iconEnabled)\n                {\n                    GUI.color = new Color(GUI.color.r, GUI.color.g, GUI.color.b, disabledAlpha);\n                    tooltip = \"\";\n                }\n\n                iconToggleContent.image = ainfo.thumb;\n                if (GUI.Button(iconRect, iconToggleContent, GUIStyle.none))\n                {\n                    ainfo.iconEnabled = !ainfo.iconEnabled;\n                    SetIconState(ainfo);\n                }\n\n                GUI.color = orgColor;\n            }\n\n            if (GUI.changed)\n            {\n                SetIconState(ainfo);\n                GUI.changed = false;\n            }\n\n            GUI.enabled = true;\n            GUI.color = orgColor;\n\n            // Gizmo toggle\n            if (ainfo.hasGizmo)\n            {\n                tooltip = textGizmoVisible;\n\n                Rect togglerRect = new Rect(rect.width - gizmoRightAlign + 2, rect.y + (rect.height - togglerSize) * 0.5f, togglerSize, togglerSize); // +2 because the given rect is shortened by 2px before this method call\n                ainfo.gizmoEnabled = GUI.Toggle(togglerRect, ainfo.gizmoEnabled, new GUIContent(\"\", tooltip), m_Styles.toggle);\n                if (GUI.changed)\n                {\n                    SetGizmoState(ainfo);\n                }\n            }\n\n            GUI.enabled = orgGUIEnabled;\n            GUI.changed = orgGUIChanged;\n            GUI.color = orgColor;\n        }\n\n        void SetIconState(GizmoInfo ainfo)\n        {\n            AnnotationUtility.SetIconEnabled(ainfo.classID, ainfo.scriptClass, ainfo.iconEnabled ? 1 : 0);\n            SceneView.RepaintAll();\n        }\n\n        void SetGizmoState(GizmoInfo ainfo, bool addToMostRecentChanged = true)\n        {\n            AnnotationUtility.SetGizmoEnabled(ainfo.classID, ainfo.scriptClass, ainfo.gizmoEnabled ? 1 : 0, addToMostRecentChanged);\n            SceneView.RepaintAll();\n        }\n\n        [Shortcut(\"Scene View/Toggle Selection Outline\", typeof(SceneView))]\n        static void ToggleSelectionOutline()\n        {\n            AnnotationUtility.showSelectionOutline = !AnnotationUtility.showSelectionOutline;\n        }\n\n        [Shortcut(\"Scene View/Toggle Selection Wireframe\", typeof(SceneView))]\n        static void ToggleSelectionWireframe()\n        {\n            AnnotationUtility.showSelectionWire = !AnnotationUtility.showSelectionWire;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Annotation/GizmoInfo.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityObject = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [Serializable]\n    public class GizmoInfo : IComparable\n    {\n        [SerializeField]\n        bool m_IconEnabled;\n\n        [SerializeField]\n        bool m_GizmoEnabled;\n\n        [SerializeField]\n        int m_ClassID;\n\n        [SerializeField]\n        string m_ScriptClass;\n\n        [SerializeField]\n        string m_Name;\n\n        [SerializeField]\n        int m_Flags;\n\n        [NonSerialized]\n        UnityObject m_Script;\n\n        [NonSerialized]\n        Texture2D m_Thumb;\n\n        internal GizmoInfo()\n        {\n            m_IconEnabled = false;\n            m_GizmoEnabled = false;\n            m_ClassID = -1;\n            m_ScriptClass = null;\n            m_Name = \"\";\n            m_Flags = 0;\n        }\n\n        internal GizmoInfo(Annotation annotation)\n        {\n            m_GizmoEnabled = annotation.gizmoEnabled > 0;\n            m_IconEnabled = annotation.iconEnabled > 0;\n            m_ClassID = annotation.classID;\n            m_ScriptClass = annotation.scriptClass;\n            m_Flags = annotation.flags;\n            m_Name = string.IsNullOrEmpty(m_ScriptClass)\n                ? UnityType.FindTypeByPersistentTypeID(m_ClassID).name\n                : m_Name = m_ScriptClass;\n        }\n\n        internal int classID => m_ClassID;\n\n        internal string scriptClass => m_ScriptClass;\n\n        public string name => m_Name;\n\n        public bool hasGizmo => (m_Flags & (int)AnnotationUtility.Flags.kHasGizmo) > 0;\n\n        public bool gizmoEnabled\n        {\n            get => m_GizmoEnabled;\n            set => m_GizmoEnabled = value;\n        }\n\n        public bool hasIcon => (m_Flags & (int)AnnotationUtility.Flags.kHasIcon) > 0;\n\n        public bool iconEnabled\n        {\n            get => m_IconEnabled;\n            set => m_IconEnabled = value;\n        }\n\n        internal bool disabled => (m_Flags & (int)AnnotationUtility.Flags.kIsDisabled) > 0;\n\n        public UnityObject script\n        {\n            get\n            {\n                if (m_Script == null && m_ScriptClass != \"\")\n                    m_Script = EditorGUIUtility.GetScript(m_ScriptClass);\n                return m_Script;\n            }\n        }\n\n        public Texture2D thumb\n        {\n            get\n            {\n                if (m_Thumb == null)\n                {\n                    // Icon for scripts\n                    if (script != null)\n                        m_Thumb = EditorGUIUtility.GetIconForObject(m_Script);\n                    // Icon for builtin components\n                    else if (hasIcon)\n                        m_Thumb = AssetPreview.GetMiniTypeThumbnailFromClassID(m_ClassID);\n                }\n\n                return m_Thumb;\n            }\n    }\n\n        public int CompareTo(object obj)\n        {\n            if(obj is GizmoInfo other)\n                return m_Name.CompareTo(other.m_Name);\n            return 1;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Annotation/GizmoUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public static class GizmoUtility\n    {\n        const float k_MinFadeGizmoSize = 1f;\n        const float k_MaxFadeGizmoSize = 10f;\n\n        static void GetAnnotationIdAndClass(Type type, out int id, out string klass)\n        {\n            var unityType = UnityType.FindTypeByName(type.Name);\n            id = unityType?.persistentTypeID ?? 0;\n            // In AnnotationManager, if script name is null or empty the persistent ID is used. If not, the type is\n            // assumed to be a built-in type.\n            klass = unityType == null ? type.Name : null;\n        }\n\n        public static bool TryGetGizmoInfo(Type type, out GizmoInfo info)\n        {\n            GetAnnotationIdAndClass(type, out var id, out var name);\n            var annotation = AnnotationUtility.GetAnnotation(id, name);\n\n            if (annotation.gizmoEnabled == -1 && annotation.iconEnabled == -1 && annotation.flags == -1)\n            {\n                info = new GizmoInfo();\n                return false;\n            }\n\n            info = new GizmoInfo(annotation);\n            return true;\n        }\n\n        public static GizmoInfo[] GetGizmoInfo()\n        {\n            var annotations = AnnotationUtility.GetAnnotations();\n            return annotations.Select(x => new GizmoInfo(x)).ToArray();\n        }\n\n        public static void ApplyGizmoInfo(GizmoInfo info, bool addToRecentlyChanged = true)\n        {\n            int gizmoEnabled = info.gizmoEnabled ? 1 : 0;\n            AnnotationUtility.SetGizmoEnabled(info.classID, info.scriptClass, gizmoEnabled, addToRecentlyChanged);\n            AnnotationUtility.SetIconEnabled(info.classID, info.scriptClass, info.iconEnabled ? 1 : 0);\n        }\n\n        public static void SetGizmoEnabled(Type type, bool enabled, bool addToRecentlyChanged = true)\n        {\n            GetAnnotationIdAndClass(type, out var id, out var name);\n            AnnotationUtility.SetGizmoEnabled(id, name, enabled ? 1 : 0, addToRecentlyChanged);\n        }\n\n        public static void SetIconEnabled(Type type, bool enabled)\n        {\n            GetAnnotationIdAndClass(type, out var id, out var name);\n            AnnotationUtility.SetIconEnabled(id, name, enabled ? 1 : 0);\n        }\n\n        public static float iconSize\n        {\n            get => AnnotationUtility.iconSize;\n            set => AnnotationUtility.iconSize = Mathf.Clamp01(value);\n        }\n\n        public static bool use3dIcons\n        {\n            get => AnnotationUtility.use3dGizmos;\n            set => AnnotationUtility.use3dGizmos = value;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Annotation/LayerVisibilityWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditorInternal;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class LayerVisibilityWindow : EditorWindow\n    {\n        private class Styles\n        {\n            public readonly GUIStyle background = \"grey_border\";\n            public readonly GUIStyle menuItem = \"MenuItem\";\n            public readonly GUIStyle listEvenBg = \"ObjectPickerResultsOdd\";\n            public readonly GUIStyle listOddBg = \"ObjectPickerResultsEven\";\n            public readonly GUIStyle separator = \"sv_iconselector_sep\";\n            public readonly GUIStyle listTextStyle;\n            public readonly GUIStyle listHeaderStyle;\n            public readonly Texture2D visibleOn = EditorGUIUtility.LoadIcon(\"animationvisibilitytoggleon\");\n            public readonly Texture2D visibleOff = EditorGUIUtility.LoadIcon(\"animationvisibilitytoggleoff\");\n            public readonly Texture2D pickable = EditorGUIUtility.LoadIcon(\"scenepicking_pickable\");\n            public readonly Texture2D notpickable = EditorGUIUtility.LoadIcon(\"scenepicking_notpickable\");\n            public readonly GUIContent editLayers = EditorGUIUtility.TrTextContent(\"Edit Layers...\");\n            public Styles()\n            {\n                listTextStyle = new GUIStyle(EditorStyles.label);\n                listTextStyle.alignment = TextAnchor.MiddleLeft;\n                listTextStyle.padding.left = 10;\n\n                listHeaderStyle = new GUIStyle(EditorStyles.boldLabel);\n                listHeaderStyle.padding.left = 5;\n            }\n        }\n\n        const float k_ScrollBarWidth = 14;\n        const float k_FrameWidth = 1f;\n        const float k_ToggleSize = 17;\n        const float k_SeparatorHeight = 6;\n        const string k_LayerVisible = \"Show/Hide Layer\";\n        const string k_LayerPickable = \"Toggle Pickable status this Layer. Non-Pickable items cannot be selected in the Scene View.\";\n\n        private static LayerVisibilityWindow s_LayerVisibilityWindow;\n        private static long s_LastClosedTime;\n        const long k_JustClosedPeriod = 400;\n\n        private static Styles s_Styles;\n        private List<string> s_LayerNames;\n        private List<int> s_LayerMasks;\n        private int m_AllLayersMask;\n\n        private float m_ContentHeight;\n        private Vector2 m_ScrollPosition;\n\n        private void CalcValidLayers()\n        {\n            s_LayerNames = new List<string>();\n            s_LayerMasks = new List<int>();\n            m_AllLayersMask = 0;\n\n            for (var i = 0; i < 32; i++)\n            {\n                var s = InternalEditorUtility.GetLayerName(i);\n                if (s == string.Empty)\n                    continue;\n                s_LayerNames.Add(string.Format(\"{0}: {1}\", i, s));\n                s_LayerMasks.Add(i);\n                m_AllLayersMask |= (1 << i);\n            }\n        }\n\n        internal void OnEnable()\n        {\n            hideFlags = HideFlags.DontSave;\n            wantsMouseMove = true;\n        }\n\n        internal void OnDisable()\n        {\n            s_LastClosedTime = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond;\n            s_LayerVisibilityWindow = null;\n        }\n\n        internal static bool ShowAtPosition(Rect buttonRect)\n        {\n            // We could not use realtimeSinceStartUp since it is set to 0 when entering/exitting playmode, we assume an increasing time when comparing time.\n            long nowMilliSeconds = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond;\n            bool justClosed = nowMilliSeconds < s_LastClosedTime + k_JustClosedPeriod;\n            if (!justClosed)\n            {\n                Event.current.Use();\n                if (s_LayerVisibilityWindow == null)\n                    s_LayerVisibilityWindow = CreateInstance<LayerVisibilityWindow>();\n                s_LayerVisibilityWindow.Init(buttonRect);\n                return true;\n            }\n            return false;\n        }\n\n        private void Init(Rect buttonRect)\n        {\n            // Has to be done before calling Show / ShowWithMode\n            buttonRect = GUIUtility.GUIToScreenRect(buttonRect);\n\n            CalcValidLayers();\n\n            var rowCount = (s_LayerNames.Count + 2 + 1 + 1);\n\n            var windowHeight = rowCount * EditorGUI.kSingleLineHeight + k_SeparatorHeight;\n\n            int sortingLayerCount = InternalEditorUtility.GetSortingLayerCount();\n            if (sortingLayerCount > 1)\n            {\n                windowHeight += k_SeparatorHeight + EditorGUI.kSingleLineHeight;\n                windowHeight += sortingLayerCount * EditorGUI.kSingleLineHeight;\n            }\n            m_ContentHeight = windowHeight;\n            windowHeight += 2 * k_FrameWidth;\n            windowHeight = Mathf.Min(windowHeight, 600);\n\n            var windowSize = new Vector2(180, windowHeight);\n            ShowAsDropDown(buttonRect, windowSize);\n        }\n\n        internal void OnGUI()\n        {\n            // We do not use the layout event\n            if (Event.current.type == EventType.Layout)\n                return;\n\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            var scrollViewRect = new Rect(k_FrameWidth, k_FrameWidth, position.width - 2 * k_FrameWidth, position.height - 2 * k_FrameWidth);\n            var contentRect = new Rect(0, 0, 1, m_ContentHeight);\n            bool isScrollbarVisible = m_ContentHeight > scrollViewRect.height;\n            float listElementWidth = scrollViewRect.width;\n            if (isScrollbarVisible)\n                listElementWidth -= k_ScrollBarWidth;\n\n            m_ScrollPosition = GUI.BeginScrollView(scrollViewRect, m_ScrollPosition, contentRect, false, false, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar, EditorStyles.scrollViewAlt);\n            Draw(listElementWidth);\n            GUI.EndScrollView();\n\n            // Background with 1 pixel border\n            GUI.Label(new Rect(0, 0, position.width, position.height), GUIContent.none, s_Styles.background);\n\n            // Use mouse move so we get hover state correctly in the menu item rows\n            if (Event.current.type == EventType.MouseMove)\n                Event.current.Use();\n\n            // Escape closes the window\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)\n            {\n                Close();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        private void DrawListBackground(Rect rect, bool even)\n        {\n            GUIStyle backgroundStyle = even ? s_Styles.listEvenBg : s_Styles.listOddBg;\n            GUI.Label(rect, GUIContent.none, backgroundStyle);\n        }\n\n        private void DrawHeader(ref Rect rect, string text, ref bool even)\n        {\n            DrawListBackground(rect, even);\n            GUI.Label(rect, GUIContent.Temp(text), s_Styles.listHeaderStyle);\n            rect.y += EditorGUI.kSingleLineHeight;\n            even = !even;\n        }\n\n        private void DrawSeparator(ref Rect rect, bool even)\n        {\n            DrawListBackground(new Rect(rect.x + 1, rect.y, rect.width - 2, k_SeparatorHeight), even);\n            GUI.Label(new Rect(rect.x + 5, rect.y + 3, rect.width - 10, 3), GUIContent.none, s_Styles.separator);\n            rect.y += k_SeparatorHeight;\n        }\n\n        private void Draw(float listElementWidth)\n        {\n            var drawPos = new Rect(0, 0, listElementWidth, EditorGUI.kSingleLineHeight);\n\n            bool even = false;\n\n            DrawHeader(ref drawPos, \"Layers\", ref even);\n\n            // Everything & nothing entries\n            DoSpecialLayer(drawPos, true, ref even);\n            drawPos.y += EditorGUI.kSingleLineHeight;\n            DoSpecialLayer(drawPos, false, ref even);\n            drawPos.y += EditorGUI.kSingleLineHeight;\n\n            // Layers\n            for (var i = 0; i < s_LayerNames.Count; ++i)\n            {\n                DoOneLayer(drawPos, i, ref even);\n                drawPos.y += EditorGUI.kSingleLineHeight;\n            }\n\n            // Sorting layers, if anything else than the single default one is present\n            int sortingLayerCount = InternalEditorUtility.GetSortingLayerCount();\n            if (sortingLayerCount > 1)\n            {\n                DrawSeparator(ref drawPos, even);\n                DrawHeader(ref drawPos, \"Sorting Layers\", ref even);\n                for (var i = 0; i < sortingLayerCount; ++i)\n                {\n                    DoOneSortingLayer(drawPos, i, ref even);\n                    drawPos.y += EditorGUI.kSingleLineHeight;\n                }\n            }\n\n            // Edit Layers entry\n            DrawSeparator(ref drawPos, even);\n            DrawListBackground(drawPos, even);\n            if (GUI.Button(drawPos, s_Styles.editLayers, s_Styles.menuItem))\n            {\n                Close();\n                Selection.activeObject = EditorApplication.tagManager;\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        void DoSpecialLayer(Rect rect, bool all, ref bool even)\n        {\n            int visibleMask = Tools.visibleLayers;\n            int expectedMask = all ? m_AllLayersMask : 0;\n            bool visible = (visibleMask & m_AllLayersMask) == expectedMask;\n            bool visibleChanged, lockedChanged;\n            DoLayerEntry(rect, all ? \"Everything\" : \"Nothing\", even, true, false, visible, false, out visibleChanged, out lockedChanged);\n            if (visibleChanged)\n            {\n                Tools.visibleLayers = all ? ~0 : 0;\n                RepaintAllSceneViews();\n            }\n            even = !even;\n        }\n\n        void DoOneLayer(Rect rect, int index, ref bool even)\n        {\n            int visibleMask = Tools.visibleLayers;\n            int lockedMask = Tools.lockedLayers;\n            int layerMask = 1 << (s_LayerMasks[index]);\n            bool visible = (visibleMask & layerMask) != 0;\n            bool locked = (lockedMask & layerMask) != 0;\n            bool visibleChanged, lockedChanged;\n            DoLayerEntry(rect, s_LayerNames[index], even, true, true, visible, locked, out visibleChanged, out lockedChanged);\n            if (visibleChanged)\n            {\n                Tools.visibleLayers ^= layerMask;\n                RepaintAllSceneViews();\n            }\n            if (lockedChanged)\n            {\n                Tools.lockedLayers ^= layerMask;\n            }\n            even = !even;\n        }\n\n        void DoOneSortingLayer(Rect rect, int index, ref bool even)\n        {\n            bool locked = InternalEditorUtility.GetSortingLayerLocked(index);\n            bool visibleChanged, lockedChanged;\n            DoLayerEntry(rect, InternalEditorUtility.GetSortingLayerName(index), even, false, true, true, locked, out visibleChanged, out lockedChanged);\n            if (lockedChanged)\n            {\n                InternalEditorUtility.SetSortingLayerLocked(index, !locked);\n            }\n            even = !even;\n        }\n\n        private void DoLayerEntry(Rect rect, string layerName, bool even, bool showVisible, bool showLock, bool visible, bool picked, out bool visibleChanged, out bool lockedChanged)\n        {\n            DrawListBackground(rect, even);\n\n            EditorGUI.BeginChangeCheck();\n            // text (works as visibility toggle as well)\n            Rect textRect = rect;\n            textRect.width -= k_ToggleSize * 2;\n            visible = GUI.Toggle(textRect, visible, EditorGUIUtility.TempContent(layerName), s_Styles.listTextStyle);\n\n            // visible checkbox\n            var toggleRect = new Rect(rect.width - k_ToggleSize * 2, rect.y + (rect.height - k_ToggleSize) * 0.5f, k_ToggleSize, k_ToggleSize);\n            visibleChanged = false;\n            if (showVisible)\n            {\n                var iconRect = toggleRect;\n                var gc = new GUIContent(string.Empty, visible ? s_Styles.visibleOn : s_Styles.visibleOff, k_LayerVisible);\n                GUI.Toggle(iconRect, visible, gc, GUIStyle.none);\n                visibleChanged = EditorGUI.EndChangeCheck();\n            }\n\n            // locked checkbox\n            lockedChanged = false;\n            if (showLock)\n            {\n                toggleRect.x += k_ToggleSize;\n                EditorGUI.BeginChangeCheck();\n                var gc = new GUIContent(string.Empty, picked ? s_Styles.notpickable : s_Styles.pickable, k_LayerPickable);\n                GUI.Toggle(toggleRect, picked, gc, GUIStyle.none);\n                lockedChanged = EditorGUI.EndChangeCheck();\n            }\n        }\n\n        static void RepaintAllSceneViews()\n        {\n            foreach (SceneView sv in Resources.FindObjectsOfTypeAll(typeof(SceneView)))\n                sv.Repaint();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Annotation/SceneFXWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    internal class SceneFXWindow : PopupWindowContent\n    {\n        private class Styles\n        {\n            public readonly GUIStyle menuItem = \"MenuItem\";\n        }\n\n        private static Styles s_Styles;\n        private readonly SceneView m_SceneView;\n\n        const float kFrameWidth = 1f;\n\n        public override Vector2 GetWindowSize()\n        {\n            var windowHeight = 2f * kFrameWidth + EditorGUI.kSingleLineHeight * 7;\n            if (UnityEngine.VFX.VFXManager.activateVFX)\n            {\n                windowHeight += EditorGUI.kSingleLineHeight;\n            }\n            var windowSize = new Vector2(160, windowHeight);\n            return windowSize;\n        }\n\n        public SceneFXWindow(SceneView sceneView)\n        {\n            m_SceneView = sceneView;\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            if (m_SceneView == null || m_SceneView.sceneViewState == null)\n                return;\n\n            // We do not use the layout event\n            if (Event.current.type == EventType.Layout)\n                return;\n\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            // Content\n            Draw(rect);\n\n            // Use mouse move so we get hover state correctly in the menu item rows\n            if (Event.current.type == EventType.MouseMove)\n                Event.current.Use();\n\n            // Escape closes the window\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)\n            {\n                editorWindow.Close();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        private void Draw(Rect rect)\n        {\n            if (m_SceneView == null || m_SceneView.sceneViewState == null)\n                return;\n\n            var drawPos = new Rect(kFrameWidth, kFrameWidth, rect.width - 2 * kFrameWidth, EditorGUI.kSingleLineHeight);\n\n            var state = m_SceneView.sceneViewState;\n\n            DrawListElement(drawPos, \"Skybox\", state.showSkybox, value => state.showSkybox = value);\n            drawPos.y += EditorGUI.kSingleLineHeight;\n\n            if(SupportedRenderingFeatures.active.supportsClouds)\n            {\n                DrawListElement(drawPos, \"Clouds\", state.showClouds, value => state.showClouds = value);\n                drawPos.y += EditorGUI.kSingleLineHeight;\n            }\n\n            DrawListElement(drawPos, \"Fog\", state.showFog, value => state.showFog = value);\n            drawPos.y += EditorGUI.kSingleLineHeight;\n\n            DrawListElement(drawPos, \"Flares\", state.showFlares, value => state.showFlares = value);\n            drawPos.y += EditorGUI.kSingleLineHeight;\n\n            DrawListElement(drawPos, \"Always Refresh\", state.alwaysRefresh, value => state.alwaysRefresh = value);\n            drawPos.y += EditorGUI.kSingleLineHeight;\n\n            DrawListElement(drawPos, \"Post Processing\", state.showImageEffects, value => state.showImageEffects = value);\n            drawPos.y += EditorGUI.kSingleLineHeight;\n\n            DrawListElement(drawPos, \"Particle Systems\", state.showParticleSystems, value => state.showParticleSystems = value);\n            drawPos.y += EditorGUI.kSingleLineHeight;\n\n\n            if (UnityEngine.VFX.VFXManager.activateVFX)\n            {\n                DrawListElement(drawPos, \"Visual Effect Graphs\", state.showVisualEffectGraphs, value => state.showVisualEffectGraphs = value);\n                drawPos.y += EditorGUI.kSingleLineHeight;\n            }\n        }\n\n        void DrawListElement(Rect rect, string toggleName, bool value, Action<bool> setValue)\n        {\n            EditorGUI.BeginChangeCheck();\n            bool result = GUI.Toggle(rect, value, EditorGUIUtility.TempContent(toggleName), s_Styles.menuItem);\n            if (EditorGUI.EndChangeCheck())\n            {\n                setValue(result);\n                m_SceneView.Repaint();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Annotation/SceneRenderModeWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    // Match EditorDrawingMode order in C++ code!\n    public enum DrawCameraMode\n    {\n        UserDefined = int.MinValue,\n        Normal = -1,\n        Textured = 0,\n        Wireframe = 1,\n        TexturedWire = 2,\n        ShadowCascades = 3,\n        RenderPaths = 4,\n        AlphaChannel = 5,\n        Overdraw = 6,\n        Mipmaps = 7,\n        DeferredDiffuse = 8,\n        DeferredSpecular = 9,\n        DeferredSmoothness = 10,\n        DeferredNormal = 11,\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"Renamed to better distinguish this mode from new Progressive baked modes. Please use RealtimeCharting instead. (UnityUpgradable) -> RealtimeCharting\", true)]\n        Charting = -12,\n        RealtimeCharting = 12,\n\n        Systems = 13,\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"Renamed to better distinguish this mode from new Progressive baked modes. Please use RealtimeAlbedo instead. (UnityUpgradable) -> RealtimeAlbedo\", true)]\n        Albedo = -14,\n        RealtimeAlbedo = 14,\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"Renamed to better distinguish this mode from new Progressive baked modes. Please use RealtimeEmissive instead. (UnityUpgradable) -> RealtimeEmissive\", true)]\n        Emissive = -15,\n        RealtimeEmissive = 15,\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"Renamed to better distinguish this mode from new Progressive baked modes. Please use RealtimeIndirect instead. (UnityUpgradable) -> RealtimeIndirect\", true)]\n        Irradiance = -16,\n        RealtimeIndirect = 16,\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"Renamed to better distinguish this mode from new Progressive baked modes. Please use RealtimeDirectionality instead. (UnityUpgradable) -> RealtimeDirectionality\", true)]\n        Directionality = -17,\n        RealtimeDirectionality = 17,\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"Renamed to better distinguish this mode from new Progressive baked modes. Please use BakedLightmap instead. (UnityUpgradable) -> BakedLightmap\", true)]\n        Baked = -18,\n        BakedLightmap = 18,\n\n        Clustering = 19,\n        LitClustering = 20,\n        ValidateAlbedo = 21,\n        ValidateMetalSpecular = 22,\n        ShadowMasks = 23,\n        LightOverlap = 24,\n        BakedAlbedo = 25,\n        BakedEmissive = 26,\n        BakedDirectionality = 27,\n        BakedTexelValidity = 28,\n        BakedIndices = 29,\n        BakedCharting = 30,\n        SpriteMask = 31,\n        BakedUVOverlap = 32,\n        TextureStreaming = 33,\n        BakedLightmapCulling = 34,\n        GIContributorsReceivers = 35,\n    }\n\n    internal class SceneRenderModeWindow : PopupWindowContent\n    {\n        static class Styles\n        {\n            private static GUIStyle menuItem;\n            private static GUIStyle separator;\n            private static GUIContent debuggerLabel;\n\n            public static GUIStyle s_MenuItem => menuItem ?? (menuItem = \"MenuItem\");\n            public static GUIStyle s_Separator => separator ?? (separator = \"sv_iconselector_sep\");\n            public static GUIContent s_DebuggerLabel => debuggerLabel ??= EditorGUIUtility.TrTextContent(\"Rendering Debugger...\");\n\n            private static readonly string kShadingMode = \"Shading Mode\";\n            private static readonly string kMiscellaneous = \"Miscellaneous\";\n            private static readonly string kDeferred = \"Deferred\";\n            private static readonly string kLighting = \"Lighting\";\n            private static readonly string kRealtimeGI = \"Realtime Global Illumination\";\n            private static readonly string kBakedGI = \"Baked Global Illumination\";\n\n            // Map all builtin DrawCameraMode entries\n            // This defines the order in which the entries appear in the dropdown menu!\n            public static readonly SceneView.CameraMode[] sBuiltinCameraModes =\n            {\n                new SceneView.CameraMode(DrawCameraMode.Textured, \"Shaded\", kShadingMode, false),\n                new SceneView.CameraMode(DrawCameraMode.Wireframe, \"Wireframe\", kShadingMode, false),\n                new SceneView.CameraMode(DrawCameraMode.TexturedWire, \"Shaded Wireframe\", kShadingMode, false),\n\n                new SceneView.CameraMode(DrawCameraMode.GIContributorsReceivers, \"Contributors / Receivers\", kLighting),\n                new SceneView.CameraMode(DrawCameraMode.ShadowCascades, \"Shadow Cascades\", kLighting),\n\n                new SceneView.CameraMode(DrawCameraMode.RealtimeIndirect, \"Indirect\", kRealtimeGI),\n                new SceneView.CameraMode(DrawCameraMode.RealtimeDirectionality, \"Directionality\", kRealtimeGI),\n                new SceneView.CameraMode(DrawCameraMode.RealtimeAlbedo, \"Albedo\", kRealtimeGI),\n                new SceneView.CameraMode(DrawCameraMode.RealtimeEmissive, \"Emissive\", kRealtimeGI),\n                new SceneView.CameraMode(DrawCameraMode.RealtimeCharting, \"UV Charts\", kRealtimeGI),\n                new SceneView.CameraMode(DrawCameraMode.Systems, \"Systems\", kRealtimeGI),\n                new SceneView.CameraMode(DrawCameraMode.Clustering, \"Clustering\", kRealtimeGI),\n                new SceneView.CameraMode(DrawCameraMode.LitClustering, \"Lit Clustering\", kRealtimeGI),\n\n                new SceneView.CameraMode(DrawCameraMode.BakedLightmap, \"Baked Lightmap\", kBakedGI),\n                new SceneView.CameraMode(DrawCameraMode.BakedDirectionality, \"Directionality\", kBakedGI),\n                new SceneView.CameraMode(DrawCameraMode.ShadowMasks, \"Shadowmask\", kBakedGI),\n                new SceneView.CameraMode(DrawCameraMode.BakedAlbedo, \"Albedo\", kBakedGI),\n                new SceneView.CameraMode(DrawCameraMode.BakedEmissive, \"Emissive\", kBakedGI),\n                new SceneView.CameraMode(DrawCameraMode.BakedCharting, \"UV Charts\", kBakedGI),\n                new SceneView.CameraMode(DrawCameraMode.BakedTexelValidity, \"Texel Validity\", kBakedGI),\n                new SceneView.CameraMode(DrawCameraMode.BakedUVOverlap, \"UV Overlap\", kBakedGI),\n                new SceneView.CameraMode(DrawCameraMode.BakedIndices, \"Lightmap Indices\", kBakedGI),\n                new SceneView.CameraMode(DrawCameraMode.LightOverlap, \"Light Overlap\", kBakedGI),\n\n                new SceneView.CameraMode(DrawCameraMode.DeferredDiffuse, \"Albedo\", kDeferred),\n                new SceneView.CameraMode(DrawCameraMode.DeferredSpecular, \"Specular\", kDeferred),\n                new SceneView.CameraMode(DrawCameraMode.DeferredSmoothness, \"Smoothness\", kDeferred),\n                new SceneView.CameraMode(DrawCameraMode.DeferredNormal, \"Normal\", kDeferred),\n\n                new SceneView.CameraMode(DrawCameraMode.RenderPaths, \"Render Paths\", kMiscellaneous),\n                new SceneView.CameraMode(DrawCameraMode.AlphaChannel, \"Alpha Channel\", kMiscellaneous),\n                new SceneView.CameraMode(DrawCameraMode.Overdraw, \"Overdraw\", kMiscellaneous),\n                new SceneView.CameraMode(DrawCameraMode.Mipmaps, \"Mipmaps\", kMiscellaneous),\n                new SceneView.CameraMode(DrawCameraMode.TextureStreaming, \"Texture Mipmap Streaming\", kMiscellaneous),\n                new SceneView.CameraMode(DrawCameraMode.SpriteMask, \"Sprite Mask\", kMiscellaneous),\n                new SceneView.CameraMode(DrawCameraMode.ValidateAlbedo, \"Validate Albedo\", kMiscellaneous),\n                new SceneView.CameraMode(DrawCameraMode.ValidateMetalSpecular, \"Validate Metal Specular\", kMiscellaneous),\n            };\n\n        }\n\n        // UUM-96180: Default CameraMode should be DrawCameraMode.GIContributorsReceivers\n        internal static SceneView.CameraMode defaultCameraMode\n        {\n            get\n            {\n                var mode = Styles.sBuiltinCameraModes [3];\n                if(mode.drawMode != DrawCameraMode.GIContributorsReceivers)\n                    Debug.LogError(\"Default Draw Camera mode should be set to DrawCameraMode.GIContributorsReceivers.\");\n                return mode;\n            }\n        }\n\n        private Dictionary<string, bool> foldoutStates = new Dictionary<string, bool>();\n\n        private float windowHeight\n        {\n            get\n            {\n                int headers;\n                int modes;\n\n                // Hide unsupported items and headers\n                headers = Styles.sBuiltinCameraModes.Where(mode => m_SceneView.IsCameraDrawModeSupported(mode) && mode.show)\n                              .Select(mode => mode.section).Distinct().Count() +\n                          SceneView.userDefinedModes.Where(mode => m_SceneView.IsCameraDrawModeSupported(mode) && mode.show)\n                              .Select(mode => mode.section).Distinct().Count();\n                modes = Styles.sBuiltinCameraModes.Count(mode => m_SceneView.IsCameraDrawModeSupported(mode) && mode.show) +\n                        SceneView.userDefinedModes.Count(mode => m_SceneView.IsCameraDrawModeSupported(mode) && mode.show);\n\n                return UpdatedHeight(headers, modes, GraphicsSettings.isScriptableRenderPipelineEnabled);\n            }\n        }\n\n        const float windowWidth = 205;\n        const float kSeparatorHeight = 3;\n        const float kHeaderHorizontalPadding = 5f;\n        const float kHeaderVerticalPadding = 3f;\n\n        readonly SceneView m_SceneView;\n\n        public SceneRenderModeWindow(SceneView sceneView)\n        {\n            m_SceneView = sceneView;\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            return new Vector2(windowWidth, windowHeight);\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            if (m_SceneView == null || m_SceneView.sceneViewState == null)\n                return;\n\n            // We do not use the layout event\n            if (Event.current.type == EventType.Layout)\n                return;\n\n            Draw(rect.width);\n\n            if (GUI.changed)\n            {\n                GUIUtility.ExitGUI();\n                editorWindow.RepaintImmediately();\n                GUI.changed = false; // Reset the changed flag\n            }\n\n            // Use mouse move so we get hover state correctly in the menu item rows\n            if (Event.current.type == EventType.MouseMove)\n                Event.current.Use();\n\n            // Escape closes the window\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)\n            {\n                editorWindow.Close();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        private void DrawSeparator(ref Rect rect)\n        {\n            var labelRect = rect;\n            labelRect.x += kHeaderHorizontalPadding;\n            labelRect.y += kSeparatorHeight;\n            labelRect.width -= kHeaderHorizontalPadding * 2;\n            labelRect.height = kSeparatorHeight;\n\n            GUI.Label(labelRect, GUIContent.none, Styles.s_Separator);\n            rect.y += kSeparatorHeight;\n        }\n\n        //Opens render debugger window located at \\newSRP\\unity\\Packages\\com.unity.render-pipelines.core\\Editor\\Debugging\\DebugWindow.cs\n        private void DrawRenderingDebuggerShortCut(Rect rect)\n        {\n            var labelRect = rect;\n            labelRect.y += kHeaderVerticalPadding;\n            EditorGUI.LabelField(labelRect,string.Empty, Styles.s_MenuItem);\n            labelRect.x -= kHeaderHorizontalPadding;\n            var debuggerLabelSize = EditorStyles.foldout.CalcSize(Styles.s_DebuggerLabel);\n            labelRect.height = debuggerLabelSize.y;\n\n            if (GUI.Button(labelRect, Styles.s_DebuggerLabel,  Styles.s_MenuItem))\n            {\n                EditorApplication.ExecuteMenuItem(\"Window/Analysis/Rendering Debugger\");\n                editorWindow.Close();\n            }\n            rect.y += labelRect.height;\n\n        }\n\n        private void Draw(float listElementWidth)\n        {\n            var drawPos = new Rect(0, 0, listElementWidth, EditorGUI.kSingleLineHeight);\n            string lastSection = null;\n\n            foreach (SceneView.CameraMode mode in SceneView.userDefinedModes.OrderBy(mode => mode.section)\n                         .Concat(Styles.sBuiltinCameraModes))\n            {\n                if (!mode.show)\n                    continue;\n\n                // Draw separators and headers\n                if (mode.drawMode != DrawCameraMode.UserDefined && !m_SceneView.IsCameraDrawModeSupported(mode))\n                    // Hide unsupported items and headers\n                    continue;\n\n                if (lastSection != mode.section)\n                {\n                    lastSection = mode.section;\n                    if (!foldoutStates.ContainsKey(lastSection))\n                    {\n                        foldoutStates.Add(lastSection, true);\n                    }\n\n                    bool previousState = foldoutStates[lastSection];\n                    Rect foldoutRect = new Rect(drawPos.x, drawPos.y, drawPos.width, EditorGUI.kSingleLineHeight);\n\n                    EditorGUI.LabelField(foldoutRect,string.Empty, Styles.s_MenuItem);\n                    foldoutStates[lastSection] = EditorGUI.Foldout(foldoutRect, foldoutStates[lastSection], EditorGUIUtility.TextContent(lastSection), true);\n\n                    drawPos.y += EditorGUI.kSingleLineHeight;\n\n                    if (previousState != foldoutStates[lastSection])\n                    {\n                        UpdateWindowSize();\n                    }\n                }\n\n                if (foldoutStates[lastSection])\n                {\n                    using (new EditorGUI.DisabledScope(!m_SceneView.IsCameraDrawModeEnabled(mode)))\n                    {\n                        using (new EditorGUI.IndentLevelScope())\n                        {\n                            DoBuiltinMode(ref drawPos, mode);\n                        }\n                    }\n                }\n            }\n\n            if (GraphicsSettings.isScriptableRenderPipelineEnabled)\n            {\n                DrawSeparator(ref drawPos);\n                DrawRenderingDebuggerShortCut(drawPos);\n            }\n        }\n\n        private void UpdateWindowSize()\n        {\n            if (editorWindow != null && Event.current.type != EventType.Layout)\n            {\n                float newWindowHeight = RecalculateWindowHeight();\n                editorWindow.minSize = new Vector2(windowWidth, newWindowHeight);\n                editorWindow.maxSize = new Vector2(windowWidth, newWindowHeight);\n            }\n        }\n\n        private float RecalculateWindowHeight()\n        {\n            int headers = 0;\n            int modes = 0;\n\n            string lastSection = null;\n            foreach (SceneView.CameraMode mode in SceneView.userDefinedModes.OrderBy(mode => mode.section)\n                         .Concat(Styles.sBuiltinCameraModes))\n            {\n                if (!mode.show)\n                    continue;\n\n                if (mode.drawMode != DrawCameraMode.UserDefined && !m_SceneView.IsCameraDrawModeSupported(mode))\n                    continue;\n\n                if (lastSection != mode.section)\n                {\n                    headers++;\n                    lastSection = mode.section;\n                }\n\n                if (foldoutStates.ContainsKey(lastSection) && foldoutStates[lastSection])\n                {\n                    modes++;\n                }\n            }\n\n            return UpdatedHeight(headers, modes, GraphicsSettings.isScriptableRenderPipelineEnabled);\n        }\n\n        private float UpdatedHeight(int headers, int modes, bool isSRP)\n        {\n            int separators = headers - 1;\n            return ((headers + modes + (isSRP ? 1 : 0)) * EditorGUI.kSingleLineHeight) + (kSeparatorHeight * separators);\n        }\n\n\n        bool IsModeEnabled(DrawCameraMode mode)\n        {\n            return m_SceneView.IsCameraDrawModeEnabled(GetBuiltinCameraMode(mode));\n        }\n\n        void DoBuiltinMode(ref Rect rect, SceneView.CameraMode mode)\n        {\n            using (new EditorGUI.DisabledScope(!m_SceneView.CheckDrawModeForRenderingPath(mode.drawMode)))\n            {\n                EditorGUI.BeginChangeCheck();\n\n                GUI.Toggle(rect, m_SceneView.cameraMode == mode, EditorGUIUtility.TextContent(mode.name),\n                    Styles.s_MenuItem);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_SceneView.cameraMode = mode;\n                    m_SceneView.Repaint();\n                    GUIUtility.ExitGUI();\n                }\n\n                rect.y += EditorGUI.kSingleLineHeight;\n            }\n        }\n\n        public static GUIContent GetGUIContent(DrawCameraMode drawCameraMode)\n        {\n            if (drawCameraMode == DrawCameraMode.UserDefined)\n                return GUIContent.none;\n            return EditorGUIUtility.TextContent(Styles.sBuiltinCameraModes\n                .Single(mode => mode.drawMode == drawCameraMode).name);\n        }\n\n        internal static SceneView.CameraMode GetBuiltinCameraMode(DrawCameraMode drawMode)\n        {\n            if (drawMode == DrawCameraMode.Normal)\n                drawMode = DrawCameraMode.Textured;\n            return Styles.sBuiltinCameraModes.Single(mode => mode.drawMode == drawMode);\n        }\n\n        internal static bool DrawCameraModeExists(DrawCameraMode drawMode)\n        {\n            foreach (var mode in Styles.sBuiltinCameraModes)\n            {\n                if (mode.drawMode == drawMode)\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Annotation/SceneViewCameraWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public class SceneViewCameraWindow : PopupWindowContent\n    {\n        static class Styles\n        {\n            public static readonly GUIContent copyPlacementLabel = EditorGUIUtility.TrTextContent(\"Copy Placement\");\n            public static readonly GUIContent pastePlacementLabel = EditorGUIUtility.TrTextContent(\"Paste Placement\");\n            public static readonly GUIContent copySettingsLabel = EditorGUIUtility.TrTextContent(\"Copy Settings\");\n            public static readonly GUIContent pasteSettingsLabel = EditorGUIUtility.TrTextContent(\"Paste Settings\");\n            public static readonly GUIContent resetSettingsLabel = EditorGUIUtility.TrTextContent(\"Reset Settings\");\n            public static readonly GUIContent cameraSpeedRange = EditorGUIUtility.TrTextContent(\" \");\n\n            public static readonly GUIStyle settingsArea;\n\n            static Styles()\n            {\n                settingsArea = new GUIStyle\n                {\n                    border = new RectOffset(4, 4, 4, 4),\n                };\n            }\n        }\n\n        readonly SceneView m_SceneView;\n\n        GUIContent m_CameraSpeedSliderContent;\n        GUIContent m_AccelerationEnabled;\n        GUIContent[] m_MinMaxContent;\n        GUIContent m_FieldOfView;\n        GUIContent m_DynamicClip;\n        GUIContent m_OcclusionCulling;\n        GUIContent m_EasingEnabled;\n        GUIContent m_SceneCameraLabel = EditorGUIUtility.TrTextContent(\"Scene Camera\");\n        GUIContent m_NavigationLabel = EditorGUIUtility.TrTextContent(\"Navigation\");\n\n        readonly string k_ClippingPlaneWarning = L10n.Tr(\"Using extreme values between the near and far planes may cause rendering issues. In general, to get better precision move the Near plane as far as possible.\");\n\n        const int kFieldCount = 13;\n        const int kWindowWidth = 290;\n        const int kContentPadding = 4;\n        const int k_HeaderSpacing = 2;\n        const int kWindowHeight = ((int)EditorGUI.kSingleLineHeight) * kFieldCount + kContentPadding * 2 + k_HeaderSpacing * 2;\n        const float kPrefixLabelWidth = 120f;\n\n        // FOV values chosen to be the smallest and largest before extreme visual corruption\n        const float k_MinFieldOfView = 4f;\n        const float k_MaxFieldOfView = 120f;\n\n        Vector2 m_WindowSize;\n        Vector2 m_Scroll;\n\n        public static event Action<SceneView> additionalSettingsGui;\n\n        public override Vector2 GetWindowSize()\n        {\n            return m_WindowSize;\n        }\n\n        public SceneViewCameraWindow(SceneView sceneView)\n        {\n            m_SceneView = sceneView;\n\n            m_CameraSpeedSliderContent = EditorGUIUtility.TrTextContent(\"Camera Speed\", \"The current speed of the camera in the Scene view.\");\n            m_AccelerationEnabled = EditorGUIUtility.TrTextContent(\"Camera Acceleration\", \"Check this to enable acceleration when moving the camera. When enabled, camera speed is evaluated as a modifier. With acceleration disabled, the camera is accelerated to the Camera Speed.\");\n            m_FieldOfView = EditorGUIUtility.TrTextContent(\"Field of View\", \"The height of the camera's view angle. Measured in degrees vertically, or along the local Y axis.\");\n            m_DynamicClip = EditorGUIUtility.TrTextContent(\"Dynamic Clipping\", \"Check this to enable camera's near and far clipping planes to be calculated relative to the viewport size of the Scene.\");\n            m_OcclusionCulling = EditorGUIUtility.TrTextContent(\"Occlusion Culling\", \"Check this to enable occlusion culling in the Scene view. Occlusion culling disables rendering of objects when they\\'re not currently seen by the camera because they\\'re hidden (occluded) by other objects.\");\n            m_EasingEnabled = EditorGUIUtility.TrTextContent(\"Camera Easing\", \"Check this to enable camera movement easing. This makes the camera ease in when it starts moving and ease out when it stops.\");\n            m_WindowSize = new Vector2(kWindowWidth, kWindowHeight);\n            m_MinMaxContent = new[]\n            {\n                EditorGUIUtility.TrTextContent(\"Min\", $\"The minimum speed of the camera in the Scene view. Valid values are between [{SceneView.CameraSettings.kAbsoluteSpeedMin}, {SceneView.CameraSettings.kAbsoluteSpeedMax - 1}].\"),\n                EditorGUIUtility.TrTextContent(\"Max\", $\"The maximum speed of the camera in the Scene view. Valid values are between [{SceneView.CameraSettings.kAbsoluteSpeedMin + .0001f}, {SceneView.CameraSettings.kAbsoluteSpeedMax}].\")\n            };\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            if (m_SceneView == null || m_SceneView.sceneViewState == null)\n                return;\n\n            Draw();\n\n            // Escape closes the window\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)\n            {\n                editorWindow.Close();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        void Draw()\n        {\n            var settings = m_SceneView.cameraSettings;\n\n            m_Scroll = GUILayout.BeginScrollView(m_Scroll);\n\n            GUILayout.BeginVertical(Styles.settingsArea);\n            EditorGUI.BeginChangeCheck();\n\n            GUILayout.Space(k_HeaderSpacing);\n\n            GUILayout.BeginHorizontal();\n            GUILayout.Label(m_SceneCameraLabel, EditorStyles.boldLabel);\n            GUILayout.FlexibleSpace();\n            if (GUILayout.Button(EditorGUI.GUIContents.titleSettingsIcon, EditorStyles.iconButton))\n                ShowContextMenu(m_SceneView);\n            GUILayout.EndHorizontal();\n\n            EditorGUIUtility.labelWidth = kPrefixLabelWidth;\n\n            // fov isn't applicable in orthographic mode, and orthographic size is controlled by the user zoom\n            using (new EditorGUI.DisabledScope(m_SceneView.orthographic))\n            {\n                settings.fieldOfView = EditorGUILayout.Slider(m_FieldOfView, settings.fieldOfView, k_MinFieldOfView, k_MaxFieldOfView);\n            }\n\n            settings.dynamicClip = EditorGUILayout.Toggle(m_DynamicClip, settings.dynamicClip);\n\n            using (new EditorGUI.DisabledScope(settings.dynamicClip))\n            {\n                float near = settings.nearClip, far = settings.farClip;\n                DrawStackedFloatField(EditorGUI.s_ClipingPlanesLabel,\n                    EditorGUI.s_NearAndFarLabels[0],\n                    EditorGUI.s_NearAndFarLabels[1], ref near, ref far,\n                    EditorGUI.kNearFarLabelsWidth);\n                settings.SetClipPlanes(near, far);\n                if(far/near > 10000000 || near < 0.0001f)\n                    EditorGUILayout.HelpBox(k_ClippingPlaneWarning,MessageType.Warning);\n            }\n\n            settings.occlusionCulling = EditorGUILayout.Toggle(m_OcclusionCulling, settings.occlusionCulling);\n\n            if (EditorGUI.EndChangeCheck())\n                m_SceneView.Repaint();\n\n            EditorGUILayout.Space(k_HeaderSpacing);\n\n            GUILayout.Label(m_NavigationLabel, EditorStyles.boldLabel);\n\n            settings.easingEnabled = EditorGUILayout.Toggle(m_EasingEnabled, settings.easingEnabled);\n            settings.accelerationEnabled = EditorGUILayout.Toggle(m_AccelerationEnabled, settings.accelerationEnabled);\n\n            EditorGUI.BeginChangeCheck();\n            float min = settings.speedMin, max = settings.speedMax, speed = settings.RoundSpeedToNearestSignificantDecimal(settings.speed);\n            speed = EditorGUILayout.Slider(m_CameraSpeedSliderContent, speed, min, max);\n            if (EditorGUI.EndChangeCheck())\n                settings.speed = settings.RoundSpeedToNearestSignificantDecimal(speed);\n\n            EditorGUI.BeginChangeCheck();\n\n            DrawStackedFloatField(Styles.cameraSpeedRange,\n                m_MinMaxContent[0],\n                m_MinMaxContent[1],\n                ref min, ref max,\n                EditorGUI.kNearFarLabelsWidth);\n\n\n            if (EditorGUI.EndChangeCheck())\n                settings.SetSpeedMinMax(min, max);\n\n            EditorGUIUtility.labelWidth = 0f;\n\n            if (additionalSettingsGui != null)\n            {\n                EditorGUILayout.Space(k_HeaderSpacing);\n                additionalSettingsGui(m_SceneView);\n\n                if (Event.current.type == EventType.Repaint)\n                    m_WindowSize.y = Math.Min(GUILayoutUtility.GetLastRect().yMax + kContentPadding * 2, kWindowHeight * 3);\n            }\n\n            GUILayout.EndVertical();\n            GUILayout.EndScrollView();\n        }\n\n        static void DrawStackedFloatField(GUIContent label, GUIContent firstFieldLabel, GUIContent secondFieldLabel, ref float near, ref float far, float propertyLabelsWidth, params GUILayoutOption[] options)\n        {\n            bool hasLabel = EditorGUI.LabelHasContent(label);\n            float height = EditorGUI.kSingleLineHeight * 2 + EditorGUI.kVerticalSpacingMultiField;\n            Rect r = EditorGUILayout.GetControlRect(hasLabel, height, EditorStyles.numberField, options);\n\n            Rect fieldPosition = EditorGUI.PrefixLabel(r, label);\n            fieldPosition.height = EditorGUI.kSingleLineHeight;\n\n            float oldLabelWidth = EditorGUIUtility.labelWidth;\n            int oldIndentLevel = EditorGUI.indentLevel;\n\n            EditorGUIUtility.labelWidth = propertyLabelsWidth;\n            EditorGUI.indentLevel = 0;\n\n            near = EditorGUI.FloatField(fieldPosition, firstFieldLabel, near);\n            fieldPosition.y += EditorGUI.kSingleLineHeight + EditorGUI.kVerticalSpacingMultiField;\n            far = EditorGUI.FloatField(fieldPosition, secondFieldLabel, far);\n\n            EditorGUI.indentLevel = oldIndentLevel;\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n        }\n\n        internal static void ShowContextMenu(SceneView view)\n        {\n            var menu = new GenericMenu();\n            menu.AddItem(Styles.copyPlacementLabel, false, () => CopyPlacement(view));\n            if (CanPastePlacement())\n                menu.AddItem(Styles.pastePlacementLabel, false, () => PastePlacement(view));\n            else\n                menu.AddDisabledItem(Styles.pastePlacementLabel);\n            menu.AddItem(Styles.copySettingsLabel, false, () => CopySettings(view));\n            if (Clipboard.HasCustomValue<SceneView.CameraSettings>())\n                menu.AddItem(Styles.pasteSettingsLabel, false, () => PasteSettings(view));\n            else\n                menu.AddDisabledItem(Styles.pasteSettingsLabel);\n            menu.AddItem(Styles.resetSettingsLabel, false, () => ResetSettings(view));\n\n            menu.ShowAsContext();\n        }\n\n        // ReSharper disable once UnusedMember.Local - called by a shortcut\n        [Shortcut(\"Camera/Copy Placement\")]\n        static void CopyPlacementShortcut()\n        {\n            // if we are interacting with a game view, copy the main camera placement\n            var playView = PlayModeView.GetLastFocusedPlayModeView();\n            if (playView != null && (EditorWindow.focusedWindow == playView || EditorWindow.mouseOverWindow == playView))\n            {\n                var cam = Camera.main;\n                if (cam != null)\n                    Clipboard.SetCustomValue(new TransformWorldPlacement(cam.transform));\n            }\n            // otherwise copy the last active scene view placement\n            else\n            {\n                var sceneView = SceneView.lastActiveSceneView;\n                if (sceneView != null)\n                    CopyPlacement(sceneView);\n            }\n        }\n\n        static void CopyPlacement(SceneView view)\n        {\n            Clipboard.SetCustomValue(new TransformWorldPlacement(view.camera.transform));\n        }\n\n        // ReSharper disable once UnusedMember.Local - called by a shortcut\n        [Shortcut(\"Camera/Paste Placement\")]\n        static void PastePlacementShortcut()\n        {\n            var sceneView = SceneView.lastActiveSceneView;\n            if (sceneView == null) return;\n            if (CanPastePlacement())\n                PastePlacement(sceneView);\n        }\n\n        static bool CanPastePlacement()\n        {\n            return Clipboard.HasCustomValue<TransformWorldPlacement>();\n        }\n\n        static void PastePlacement(SceneView view)\n        {\n            var tr = view.camera.transform;\n            var placement = Clipboard.GetCustomValue<TransformWorldPlacement>();\n            tr.position = placement.position;\n            tr.rotation = placement.rotation;\n            tr.localScale = placement.scale;\n\n            // Similar to what AlignViewToObject does, except we need to do that instantly\n            // in case the shortcut key was pressed while FPS camera controls (right click drag)\n            // were active.\n            view.size = 10;\n            view.LookAt(tr.position + tr.forward * view.cameraDistance, tr.rotation, view.size, view.orthographic, true);\n\n            view.Repaint();\n        }\n\n        static void CopySettings(SceneView view)\n        {\n            Clipboard.SetCustomValue(view.cameraSettings);\n        }\n\n        static void PasteSettings(SceneView view)\n        {\n            view.cameraSettings = Clipboard.GetCustomValue<SceneView.CameraSettings>();\n            view.Repaint();\n        }\n\n        static void ResetSettings(SceneView view)\n        {\n            view.ResetCameraSettings();\n            view.Repaint();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ArrayUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    // Helpers for builtin arrays ...\n    // These are O(n) operations (where List<T>() is used) - the arrays are actually copied (http://msdn.microsoft.com/en-us/library/fkbw11z0.aspx)\n    // but its pretty helpful for now\n    public static class ArrayUtility\n    {\n        //appends ''item'' to the end of ''array''\n        public static void Add<T>(ref T[] array, T item)\n        {\n            System.Array.Resize(ref array, array.Length + 1);\n            array[array.Length - 1] = item;\n        }\n\n        //compares two arrays\n        public static bool ArrayEquals<T>(T[] lhs, T[] rhs)\n        {\n            if (lhs == null || rhs == null)\n                return lhs == rhs;\n\n            if (lhs.Length != rhs.Length)\n                return false;\n\n            for (int i = 0; i < lhs.Length; i++)\n            {\n                if (!lhs[i].Equals(rhs[i]))\n                    return false;\n            }\n            return true;\n        }\n\n        //compares two arrays\n        public static bool ArrayReferenceEquals<T>(T[] lhs, T[] rhs)\n        {\n            if (lhs == null || rhs == null)\n                return lhs == rhs;\n\n            if (lhs.Length != rhs.Length)\n                return false;\n\n            for (int i = 0; i < lhs.Length; i++)\n            {\n                if (!object.ReferenceEquals(lhs[i], rhs[i]))\n                    return false;\n            }\n            return true;\n        }\n\n        //appends items to the end of array\n        public static void AddRange<T>(ref T[] array, T[] items)\n        {\n            int size = array.Length;\n            System.Array.Resize(ref array, array.Length + items.Length);\n            for (int i = 0; i < items.Length; i++)\n                array[size + i] = items[i];\n        }\n\n        //inserts item ''item'' at position ''index''\n        public static void Insert<T>(ref T[] array, int index, T item)\n        {\n            ArrayList a = new ArrayList();\n            a.AddRange(array);\n            a.Insert(index, item);\n            array = a.ToArray(typeof(T)) as T[];\n        }\n\n        //removes ''item'' from ''array''\n        public static void Remove<T>(ref T[] array, T item)\n        {\n            List<T> newList = new List<T>(array);\n            newList.Remove(item);\n            array = newList.ToArray();\n        }\n\n        public static List<T> FindAll<T>(T[] array, Predicate<T> match)\n        {\n            List<T> list = new List<T>(array);\n            return list.FindAll(match);\n        }\n\n        public static T Find<T>(T[] array, Predicate<T> match)\n        {\n            List<T> list = new List<T>(array);\n            return list.Find(match);\n        }\n\n        //Find the index of the first element that satisfies the predicate\n        public static int FindIndex<T>(T[] array, Predicate<T> match)\n        {\n            List<T> list = new List<T>(array);\n            return list.FindIndex(match);\n        }\n\n        //index of first element with value ''value''\n        public static int IndexOf<T>(T[] array, T value)\n        {\n            List<T> list = new List<T>(array);\n            return list.IndexOf(value);\n        }\n\n        //index of the last element with value ''value''\n        public static int LastIndexOf<T>(T[] array, T value)\n        {\n            List<T> list = new List<T>(array);\n            return list.LastIndexOf(value);\n        }\n\n        //remove element at position ''index''\n        public static void RemoveAt<T>(ref T[] array, int index)\n        {\n            List<T> list = new List<T>(array);\n            list.RemoveAt(index);\n            array = list.ToArray();\n        }\n\n        //determines if the array contains the item\n        public static bool Contains<T>(T[] array, T item)\n        {\n            List<T> list = new List<T>(array);\n            return list.Contains(item);\n        }\n\n        //Clears the array\n        public static void Clear<T>(ref T[] array)\n        {\n            System.Array.Clear(array, 0, array.Length);\n            System.Array.Resize(ref array, 0);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssemblyHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Collections.Generic;\nusing Mono.Cecil;\nusing UnityEditor.Modules;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing System.Runtime.InteropServices;\nusing UnityEngine.Scripting;\nusing Debug = UnityEngine.Debug;\nusing Unity.Profiling;\nusing UnityEditor.AssetImporters;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEngine.Scripting.APIUpdating;\n\nnamespace UnityEditor\n{\n    internal class AssemblyHelper\n    {\n        static Dictionary<string, bool> managedToDllType = new Dictionary<string, bool>();\n        static BuildPlayerDataExtractor m_BuildPlayerDataExtractor = new BuildPlayerDataExtractor();\n\n        static public bool IsUnityEngineModule(AssemblyDefinition assembly)\n        {\n            return assembly.CustomAttributes.Any(a => a.AttributeType.FullName == typeof(UnityEngineModuleAssembly).FullName);\n        }\n\n        static public bool IsUnityEngineModule(Assembly assembly)\n        {\n            return assembly.GetCustomAttributes(typeof(UnityEngineModuleAssembly), false).Length > 0;\n        }\n\n        public static string[] GetDefaultAssemblySearchPaths()\n        {\n            // Add the path to all available precompiled assemblies\n            var target = EditorUserBuildSettings.activeBuildTarget;\n            var precompiledAssemblyPaths = InternalEditorUtility.GetPrecompiledAssemblyPaths();\n\n            HashSet<string> searchPaths = new HashSet<string>(precompiledAssemblyPaths);\n\n            var precompiledAssemblies = InternalEditorUtility.GetUnityAssemblies(true, target);\n            foreach (var asm in precompiledAssemblies)\n                searchPaths.Add(Path.GetDirectoryName(asm.Path));\n\n            // Add Unity compiled assembly output directory.\n            // Required for MonoBehaviour derived types like UIBehaviour that\n            // were previous in a precompiled UnityEngine.UI.dll, but are now\n            // compiled in a package.\n            searchPaths.Add(InternalEditorUtility.GetEditorScriptAssembliesPath());\n\n            return searchPaths.ToArray();\n        }\n\n        [RequiredByNativeCode]\n        public static bool ExtractAllClassesThatAreUserExtendedScripts(string path, out string[] classNamesArray, out string[] classNameSpacesArray, out string[] movedFromNamespacesArray)\n        {\n            var typesDerivedFromMonoBehaviour = TypeCache.GetTypesDerivedFrom<MonoBehaviour>();\n            var typesDerivedFromScriptableObject = TypeCache.GetTypesDerivedFrom<ScriptableObject>();\n            var typesDerivedFromScriptedImporter = TypeCache.GetTypesDerivedFrom<ScriptedImporter>();\n\n            var fileName = Path.GetFileName(path);\n            IEnumerable<Type> userTypes = typesDerivedFromMonoBehaviour.Where(x => Path.GetFileName(x.Assembly.Location) == fileName);\n            userTypes = userTypes\n                .Concat(typesDerivedFromScriptableObject.Where(x => Path.GetFileName(x.Assembly.Location) == fileName))\n                .Concat(typesDerivedFromScriptedImporter.Where(x => Path.GetFileName(x.Assembly.Location) == fileName)).ToList();\n\n            List<string> classNames = new List<string>(userTypes.Count());\n            List<string> nameSpaces = new List<string>(userTypes.Count());\n            List<string> originalNamespaces = new List<string>(userTypes.Count());\n\n            string pathToAssembly = null;\n            foreach (var userType in userTypes)\n            {\n                if (string.IsNullOrEmpty(pathToAssembly))\n                    pathToAssembly = Path.GetFullPath(userType.Assembly.Location);\n\n                classNames.Add(userType.Name);\n                nameSpaces.Add(userType.Namespace);\n\n                var movedFromAttribute = userType.GetCustomAttribute<MovedFromAttribute>();\n                originalNamespaces.Add(movedFromAttribute?.data.nameSpace);\n            }\n\n            classNamesArray = classNames.ToArray();\n            classNameSpacesArray = nameSpaces.ToArray();\n            movedFromNamespacesArray = originalNamespaces.ToArray();\n\n            return !Utility.IsPathsEqual(pathToAssembly, path);\n        }\n\n        /// Extract information about all types in the specified assembly, searchDirs might be used to resolve dependencies.\n        [RequiredByNativeCode]\n        static public AssemblyInfoManaged[] ExtractAssemblyTypeInfo(bool isEditor)\n        {\n            var extractAssemblyTypeInfo = m_BuildPlayerDataExtractor.ExtractAssemblyTypeInfo(isEditor);\n            return extractAssemblyTypeInfo;\n        }\n\n        static public AssemblyInfoManaged[] ExtractAssemblyTypeInfoFromFiles(string[] typeDbJsonPaths)\n        {\n            return m_BuildPlayerDataExtractor.ExtractAssemblyTypeInfoFromFiles(typeDbJsonPaths);\n        }\n\n        [StructLayout(LayoutKind.Sequential)]\n        public struct RuntimeInitializeOnLoadMethodsData\n        {\n            public RuntimeInitializeClassInfo[] classInfos;\n            public int methodsCount;\n        }\n\n        [RequiredByNativeCode]\n        public static void ExtractPlayerRuntimeInitializeOnLoadMethods(string jsonPath)\n        {\n            try\n            {\n                m_BuildPlayerDataExtractor.ExtractPlayerRuntimeInitializeOnLoadMethods(jsonPath);\n            }\n            catch (Exception exception)\n            {\n                Debug.LogError($\"Failed extracting RuntimeInitializeOnLoadMethods. Player will not be able to execute RuntimeInitializeOnLoadMethods: {exception.Message}{Environment.NewLine}{exception.StackTrace}\");\n            }\n        }\n\n        internal static Type[] GetTypesFromAssembly(Assembly assembly)\n        {\n            if (assembly == null)\n                return new Type[] {};\n            try\n            {\n                return assembly.GetTypes();\n            }\n            catch (ReflectionTypeLoadException)\n            {\n                return new Type[] {};\n            }\n        }\n\n        public static bool IsManagedAssembly(string file)\n        {\n            bool isManagedDll;\n            if (managedToDllType.TryGetValue(file, out isManagedDll))\n            {\n                return isManagedDll;\n            }\n            var res = InternalEditorUtility.IsDotNetDll(file);\n            managedToDllType[file] = res;\n            return res;\n        }\n\n        public static bool IsInternalAssembly(string file)\n        {\n            return ModuleUtils.GetAdditionalReferencesForUserScripts().Any(p => p.Equals(file));\n        }\n\n        /// <summary>\n        /// Performs a depth-first-search topological sort on the input assemblies,\n        /// based on the outgoing assembly references from each assembly. The\n        /// returned list is sorted such that assembly A appears before any\n        /// assemblies that depend (directly or indirectly) on assembly A.\n        /// </summary>\n        internal static Assembly[] TopologicalSort(Assembly[] assemblies)\n        {\n            using var _ = new ProfilerMarker(\"SortAssembliesTopologically\").Auto();\n\n            var assembliesByName = new Dictionary<string, int>(assemblies.Length);\n            for (var i = 0; i < assemblies.Length; i++)\n            {\n                assembliesByName[assemblies[i].GetName().Name] = i;\n            }\n\n            var result = new Assembly[assemblies.Length];\n            var resultIndex = 0;\n\n            var visited = new TopologicalSortVisitStatus[assemblies.Length];\n\n            void VisitAssembly(int index)\n            {\n                var visitStatus = visited[index];\n\n                switch (visitStatus)\n                {\n                    case TopologicalSortVisitStatus.Visiting:\n                        // We have a cyclic dependency between assemblies. This should really be an error, but...\n                        // We need to allow cyclic dependencies between assemblies, because the rest of Unity allows them.\n                        // For example if you make an assembly override for UnityEngine.AccessibilityModule.dll,\n                        // it will reference UnityEditor.CoreModule.dll, which in turn references\n                        // UnityEngine.AccessibilityModule.dll... and that doesn't trigger an error.\n                        // The topological sort won't be correct in this case, but it's better than erroring-out.\n                        break;\n\n                    case TopologicalSortVisitStatus.NotVisited:\n                        visited[index] = TopologicalSortVisitStatus.Visiting;\n\n                        var assembly = assemblies[index];\n\n                        var assemblyReferences = assembly.GetReferencedAssemblies();\n                        foreach (var assemblyReference in assemblyReferences)\n                        {\n                            // It's okay if we can't resolve the assembly. It just means that the referenced assembly\n                            // is not in the input set of assemblies, so we wouldn't be able to sort it anyway.\n                            if (assembliesByName.TryGetValue(assemblyReference.Name, out var referencedAssembly))\n                            {\n                                VisitAssembly(referencedAssembly);\n                            }\n                        }\n\n                        visited[index] = TopologicalSortVisitStatus.Visited;\n\n                        result[resultIndex++] = assembly;\n                        break;\n                }\n            }\n\n            for (var i = 0; i < assemblies.Length; i++)\n            {\n                VisitAssembly(i);\n            }\n\n            return result;\n        }\n\n        private enum TopologicalSortVisitStatus : byte\n        {\n            NotVisited,\n            Visiting,\n            Visited\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssemblyInfo/AssemblyInfo.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n// NOTE: the build system includes this source file in ALL Editor modules\n\nusing System.Runtime.CompilerServices;\nusing UnityEngine;\n\n[assembly: AssemblyIsEditorAssembly]\n\n// TODO: over time, remove the InternalsVisibleTo attributes from this section\n// You can start by moving them to EditorCoreModuleAssemblyInfo.cs to reduce internal visibility\n// To remove a line in there, the target assembly must not depend on _any_ internal API from built-in Editor modules\n\n\n// ADD_NEW_PLATFORM_HERE\n[assembly: InternalsVisibleTo(\"Unity.LiveNotes\")]\n[assembly: InternalsVisibleTo(\"Unity.Audio.Tests\")]\n[assembly: InternalsVisibleTo(\"Unity.Burst\")]\n[assembly: InternalsVisibleTo(\"Unity.Burst.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.Cloud.Collaborate.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.CollabProxy.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.CollabProxy.EditorTests\")]\n[assembly: InternalsVisibleTo(\"Unity.CollabProxy.UI\")]\n[assembly: InternalsVisibleTo(\"Unity.CollabProxy.UI.Tests\")]\n[assembly: InternalsVisibleTo(\"Unity.CollabProxy.Client\")]\n[assembly: InternalsVisibleTo(\"Unity.CollabProxy.Client.Tests\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.Advertisements\")]\n[assembly: InternalsVisibleTo(\"Unity.PackageManager\")]\n[assembly: InternalsVisibleTo(\"Unity.PackageManagerStandalone\")]\n[assembly: InternalsVisibleTo(\"Unity.AndroidBuildPipeline\")]\n[assembly: InternalsVisibleTo(\"Unity.Automation\")]\n[assembly: InternalsVisibleTo(\"UnityEngine.Common\")]\n[assembly: InternalsVisibleTo(\"Unity.PureCSharpTests\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.Android\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.Android.CommonUtils\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.Animation\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.AssetImporting\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.BuildPipeline\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.Builds\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.CrashReporting\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.DeploymentTargets\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.EditorApplication\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.EditorUI\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.GameCore\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.GameView\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.Lightmapping\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.Metro\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.Misc\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.PackageManager\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.Profiler\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.PS4\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.PS5\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.Switch\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.Rendering\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.SceneVisibility\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.ScriptCompilation\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.ShortcutManager\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.UIToolkit\")]\n[assembly: InternalsVisibleTo(\"Unity.IntegrationTests.Framework.PackageManager\")]\n[assembly: InternalsVisibleTo(\"Unity.DeploymentTests.Services\")]\n[assembly: InternalsVisibleTo(\"Unity.PerformanceIntegrationTests\")]\n[assembly: InternalsVisibleTo(\"Unity.Timeline.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.PackageManagerUI.Develop.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.DeviceSimulator.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.Timeline.EditorTests\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.Graphs\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.UWP.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.iOS.Extensions.Common\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.Apple.Extensions.Common\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.iOS.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.VisionOS.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.AppleTV.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.Android.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.XboxOne.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.PS4.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.PS5.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.Switch.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.WebGL.Extensions\")]\n[assembly: InternalsVisibleTo(\"Unity.Automation.Players.WebGL\")]\n[assembly: InternalsVisibleTo(\"Unity.WebGL.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.LinuxStandalone.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.CloudRendering.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.EmbeddedLinux.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.QNX.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.Kepler.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.WindowsStandalone.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.OSXStandalone.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.Lumin.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.GameCoreScarlett.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.GameCoreXboxOne.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.GameCoreCommon.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.Networking\")]\n[assembly: InternalsVisibleTo(\"UnityEngine.Networking\")]\n[assembly: InternalsVisibleTo(\"Unity.Analytics.Editor\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.Analytics\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.Purchasing\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.Lumin\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.Switch.Extensions\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.EditorTestsRunner\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.TestRunner\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.TestRunner.Tests\")]\n[assembly: InternalsVisibleTo(\"Unity.Compiler.Client\")]\n[assembly: InternalsVisibleTo(\"ExternalCSharpCompiler\")]\n[assembly: InternalsVisibleTo(\"UnityEngine.TestRunner\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.VR\")]\n[assembly: InternalsVisibleTo(\"Unity.RuntimeTests\")]\n[assembly: InternalsVisibleTo(\"Unity.RuntimeTests.Framework\")]\n[assembly: InternalsVisibleTo(\"Assembly-CSharp-Editor-firstpass-testable\")]\n[assembly: InternalsVisibleTo(\"Assembly-CSharp-Editor-testable\")]\n[assembly: InternalsVisibleTo(\"DynamicProxyGenAssembly2\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.InteractiveTutorialsFramework\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.Networking\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.UI\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.AR\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.SpatialTracking\")]\n[assembly: InternalsVisibleTo(\"Unity.WindowsMRAutomation\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.001\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.002\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.003\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.004\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.005\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.006\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.007\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.008\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.009\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.010\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.011\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.012\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.013\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.014\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.015\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.016\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.017\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.018\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.019\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.020\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.021\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.022\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.023\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridge.024\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridgeDev.001\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridgeDev.002\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridgeDev.003\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridgeDev.004\")]\n[assembly: InternalsVisibleTo(\"Unity.InternalAPIEditorBridgeDev.005\")]\n[assembly: InternalsVisibleTo(\"Unity.XR.Remoting.Editor\")]\n[assembly: InternalsVisibleTo(\"UnityEngine.Common\")]\n[assembly: InternalsVisibleTo(\"Unity.UI.Builder.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.UI.TestFramework.Editor.Tests\")] // for UI Test Framework\n[assembly: InternalsVisibleTo(\"UnityEditor.UIBuilderModule\")]\n[assembly: InternalsVisibleTo(\"Unity.UI.Builder.EditorTests\")]\n[assembly: InternalsVisibleTo(\"Unity.GraphViewTestUtilities.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.ProBuilder.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.2D.Sprite.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.2D.Sprite.EditorTests\")]\n[assembly: InternalsVisibleTo(\"Unity.2D.Tilemap.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.2D.Tilemap.EditorTests\")]\n[assembly: InternalsVisibleTo(\"Unity.PackageCleanConsoleTest.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.TextCore.Editor.Tests\")]\n[assembly: InternalsVisibleTo(\"UnityEditor.TextCoreTextEngineModule\")]\n[assembly: InternalsVisibleTo(\"Unity.TextMeshPro.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.Animation.Editor.AnimationWindow\")]\n[assembly: InternalsVisibleTo(\"Unity.VisualEffectGraph.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.Testing.VisualEffectGraph.EditorTests\")]\n[assembly: InternalsVisibleTo(\"Unity.VisualEffectGraph.EditorTests\")]\n[assembly: InternalsVisibleTo(\"Unity.RenderPipelines.Multiple_SRP.EditorTests\")]\n[assembly: InternalsVisibleTo(\"Unity.ShaderGraph.Editor\")]\n\n[assembly: InternalsVisibleTo(\"Unity.SceneTemplate.Editor\")]\n[assembly: InternalsVisibleTo(\"com.unity.purchasing.udp.Editor\")]\n[assembly: InternalsVisibleTo(\"com.unity.search.extensions.editor\")]\n\n[assembly: InternalsVisibleTo(\"UnityEditor.Android.Extensions\")]\n\n[assembly: InternalsVisibleTo(\"Unity.Entities.Build\")]\n\n[assembly: InternalsVisibleTo(\"Unity.Muse.Chat.Bridge\")]\n[assembly: InternalsVisibleTo(\"Unity.AI.Assistant.Bridge.Editor\")]\n\n[assembly: InternalsVisibleTo(\"Unity.Multiplayer.Playmode.Editor.Bridge\")]\n[assembly: InternalsVisibleTo(\"Unity.DedicatedServer.Editor.Bridge\")]\n\n[assembly: InternalsVisibleTo(\"Unity.Scenes\")]\n\n\n[assembly: InternalsVisibleTo(\"UnityEditor.Switch.Tests\")]\n\n[assembly: InternalsVisibleTo(\"UnityEditor.BuildProfileModule.Tests\")]\n\n[assembly: InternalsVisibleTo(\"UnityEditor.PS4.Tests\")]\n\n[assembly: InternalsVisibleTo(\"UnityEditor.PS5.Tests\")]\n\n[assembly: InternalsVisibleTo(\"Unity.Automation.Players.EmbeddedLinux\")]\n[assembly: InternalsVisibleTo(\"Unity.Automation.Players.QNX\")]\n\n[assembly: InternalsVisibleTo(\"Unity.GraphToolsAuthoringFramework.InternalEditorBridge\")]\n\n// Module test assemblies\n[assembly: InternalsVisibleTo(\"Unity.Modules.iOSExtensions.Tests.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.Modules.Licensing.Tests.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.Modules.PlatformIcons.Tests.Editor\")]\n// This should move with the AnimationWindow to a module at some point\n[assembly: InternalsVisibleTo(\"Unity.Modules.Animation.AnimationWindow.Tests.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.Modules.Physics.Tests.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.Tests.Shared\")]\n\n// Test Assemblies\n[assembly: InternalsVisibleTo(\"Unity.Core.UnityEvent.Tests.Editor\")]\n[assembly: InternalsVisibleTo(\"Unity.Core.Scripting.AssemblyVersion.Tests.Editor\")]\n\n"
  },
  {
    "path": "Editor/Mono/AssemblyReloadEvents.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    public static class AssemblyReloadEvents\n    {\n        public delegate void AssemblyReloadCallback();\n        public static event AssemblyReloadCallback beforeAssemblyReload\n        {\n            add => m_BeforeAssemblyReloadEvent.Add(value);\n            remove => m_BeforeAssemblyReloadEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<AssemblyReloadCallback> m_BeforeAssemblyReloadEvent =\n            new EventWithPerformanceTracker<AssemblyReloadCallback>($\"{nameof(AssemblyReloadEvents)}.{nameof(beforeAssemblyReload)}\");\n        public static event AssemblyReloadCallback afterAssemblyReload\n        {\n            add => m_AfterAssemblyReloadEvent.Add(value);\n            remove => m_AfterAssemblyReloadEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<AssemblyReloadCallback> m_AfterAssemblyReloadEvent =\n            new EventWithPerformanceTracker<AssemblyReloadCallback>($\"{nameof(AssemblyReloadEvents)}.{nameof(afterAssemblyReload)}\");\n\n        [RequiredByNativeCode]\n        static void OnBeforeAssemblyReload()\n        {\n            if (!m_BeforeAssemblyReloadEvent.hasSubscribers)\n                return;\n            using var scope = new ProgressScope(\"OnBeforeAssemblyReload Callback\", \"\", forceUpdate: true);\n            foreach (var evt in m_BeforeAssemblyReloadEvent)\n            {\n                scope.SetText($\"{evt.Method?.DeclaringType?.FullName}.{evt.Method?.Name}\", true);\n                evt();\n            }\n        }\n\n        [RequiredByNativeCode]\n        static void OnAfterAssemblyReload()\n        {\n            if (!m_AfterAssemblyReloadEvent.hasSubscribers)\n                return;\n            using var scope = new ProgressScope(\"OnAfterAssemblyReload Callback\", \"\", forceUpdate: true);\n            foreach (var evt in m_AfterAssemblyReloadEvent)\n            {\n                scope.SetText($\"{evt.Method?.DeclaringType?.FullName}.{evt.Method?.Name}\", true);\n                evt();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssemblyValidation.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing Mono.Cecil;\nusing Unity.IO.LowLevel.Unsafe;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    static class AssemblyValidation\n    {\n        // Keep in sync with AssemblyValidationFlags in MonoManager.cpp\n        [Flags]\n        public enum ErrorFlags\n        {\n            None = 0,\n            ReferenceHasErrors = (1 << 0),\n            UnresolvableReference = (1 << 1),\n            IncompatibleWithEditor = (1 << 2),\n            AsmdefPluginConflict = (1 << 3)\n        }\n\n        [StructLayout(LayoutKind.Sequential)]\n        public struct Error\n        {\n            public ErrorFlags flags;\n            public string message;\n            public string assemblyPath;\n\n            public void Add(ErrorFlags newFlags, string newMessage)\n            {\n                flags |= newFlags;\n\n                if (message == null)\n                {\n                    message = newMessage;\n                }\n                else\n                {\n                    message += string.Format(\"\\n{0}\", newMessage);\n                }\n            }\n\n            public bool HasFlag(ErrorFlags testFlags)\n            {\n                return (flags & testFlags) == testFlags;\n            }\n\n            public void ClearFlags(ErrorFlags clearFlags)\n            {\n                flags &= ~clearFlags;\n            }\n        }\n\n        public struct AssemblyAndReferences\n        {\n            public int assemblyIndex;\n            public int[] referenceIndicies;\n        }\n\n        class AssemblyResolver : BaseAssemblyResolver\n        {\n            readonly IDictionary<string, AssemblyDefinition> cache;\n\n            public AssemblyResolver()\n            {\n                cache = new Dictionary<string, AssemblyDefinition>(StringComparer.Ordinal);\n            }\n\n            public override AssemblyDefinition Resolve(AssemblyNameReference name)\n            {\n                if (name == null)\n                    throw new ArgumentNullException(\"name\");\n\n                AssemblyDefinition assembly;\n                if (cache.TryGetValue(name.Name, out assembly))\n                    return assembly;\n\n                assembly = base.Resolve(name);\n                cache[name.Name] = assembly;\n\n                return assembly;\n            }\n\n            public void RegisterAssembly(AssemblyDefinition assembly)\n            {\n                if (assembly == null)\n                    throw new ArgumentNullException(\"assembly\");\n\n                var name = assembly.Name.Name;\n                if (cache.ContainsKey(name))\n                    return;\n\n                cache[name] = assembly;\n            }\n\n            protected override void Dispose(bool disposing)\n            {\n                foreach (var assembly in cache.Values)\n                    assembly.Dispose();\n\n                cache.Clear();\n\n                base.Dispose(disposing);\n            }\n        }\n\n        [RequiredByNativeCode]\n        public static Error[] ValidateAssemblies(string[] assemblyPaths, bool enableLogging)\n        {\n            var searchPaths = AssemblyHelper.GetDefaultAssemblySearchPaths();\n\n            var assemblyDefinitions = LoadAssemblyDefinitions(assemblyPaths, searchPaths);\n\n            if (enableLogging)\n            {\n                // Prints assemblies and their references to the Editor.log\n                PrintAssemblyDefinitions(assemblyDefinitions);\n\n                foreach (var searchPath in searchPaths)\n                {\n                    Console.WriteLine(\"[AssemblyValidation] Search Path: '\" + searchPath + \"'\");\n                }\n            }\n\n            var errors = ValidateAssemblyDefinitions(assemblyPaths,\n                assemblyDefinitions);\n\n            return errors;\n        }\n\n        [RequiredByNativeCode]\n        internal static Error[] ValidateRoslynAnalyzers(string[] analyzerPaths)\n        {\n            var readerParameters = new ReaderParameters\n            {\n                ReadingMode = ReadingMode.Deferred\n            };\n            List<Error> errors = new List<Error>();\n            foreach(var analyzer in analyzerPaths)\n            {\n                using (var analyzerDefinition = AssemblyDefinition.ReadAssembly(analyzer, readerParameters))\n                {\n                    var netstandardVersion = analyzerDefinition.MainModule.AssemblyReferences.Where(r => r.Name == \"netstandard\").FirstOrDefault();\n                    if (netstandardVersion != null && netstandardVersion.Version >= new Version(2, 1))\n                    {\n                        errors.Add(new Error\n                        {\n                            assemblyPath = analyzer,\n                            flags = ErrorFlags.ReferenceHasErrors,\n                            message = $\"{analyzerDefinition.Name.Name} references {netstandardVersion}. A roslyn analyzer should reference netstandard version 2.0\"\n                        });\n                    }\n\n                }\n            }\n            return errors.ToArray();\n        }\n\n        [RequiredByNativeCode]\n        public static Error[] ValidateAssemblyDefinitionFiles()\n        {\n            var customScriptAssemblies = EditorCompilationInterface.Instance.GetCustomScriptAssemblies();\n\n            if (customScriptAssemblies.Length == 0)\n                return null;\n\n            var pluginImporters = PluginImporter.GetAllImporters();\n\n            if (pluginImporters == null || pluginImporters.Length == 0)\n                return null;\n\n            var pluginFilenameToAssetPath = new Dictionary<string, string>();\n\n            foreach (var pluginImporter in pluginImporters)\n            {\n                var pluginAssetPath = pluginImporter.assetPath;\n                var lowerPluginFilename = AssetPath.GetFileName(pluginAssetPath).ToLower(CultureInfo.InvariantCulture);\n                pluginFilenameToAssetPath[lowerPluginFilename] = pluginAssetPath;\n            }\n\n            var errors = new List<Error>();\n\n            foreach (var customScriptAssembly in customScriptAssemblies)\n            {\n                var lowerAsmdefFilename = $\"{customScriptAssembly.Name.ToLower(CultureInfo.InvariantCulture)}.dll\";\n\n                string pluginPath;\n\n                if (pluginFilenameToAssetPath.TryGetValue(lowerAsmdefFilename, out pluginPath))\n                {\n                    var error = new Error()\n                    {\n                        message = $\"Plugin '{pluginPath}' has the same filename as Assembly Definition File '{customScriptAssembly.FilePath}'. Rename the assemblies to avoid hard to diagnose issues and crashes.\",\n                        flags = ErrorFlags.AsmdefPluginConflict,\n                        assemblyPath = pluginPath\n                    };\n\n                    errors.Add(error);\n                }\n            }\n\n            return errors.ToArray();\n        }\n\n        public static bool ShouldValidateReferences(string path,\n            Dictionary<string, PrecompiledAssembly> allPrecompiledAssemblies)\n        {\n\n            if (!allPrecompiledAssemblies.TryGetValue(path, out var precompiledAssembly))\n                return true;\n\n            return precompiledAssembly.Flags.HasFlag(AssemblyFlags.ValidateAssembly);\n        }\n\n        public static void PrintAssemblyDefinitions(AssemblyDefinition[] assemblyDefinitions)\n        {\n            foreach (var assemblyDefinition in assemblyDefinitions)\n            {\n                Console.WriteLine(\"[AssemblyValidation] Assembly: \" + assemblyDefinition.Name);\n\n                var assemblyReferences = GetAssemblyNameReferences(assemblyDefinition);\n\n                foreach (var reference in assemblyReferences)\n                {\n                    Console.WriteLine(\"[AssemblyValidation]   Reference: \" + reference);\n                }\n            }\n        }\n\n        public static Error[] ValidateAssembliesInternal(string[] assemblyPaths,\n            string[] searchPaths)\n        {\n            var assemblyDefinitions = LoadAssemblyDefinitions(assemblyPaths, searchPaths);\n            return ValidateAssemblyDefinitions(assemblyPaths, assemblyDefinitions);\n        }\n\n        public static Error[] ValidateAssemblyDefinitions(string[] assemblyPaths,\n            AssemblyDefinition[] assemblyDefinitions)\n        {\n            var errors = new Error[assemblyPaths.Length];\n\n            CheckAssemblyReferences(assemblyPaths,\n                errors,\n                assemblyDefinitions);\n\n            return errors;\n        }\n\n        public static AssemblyDefinition[] LoadAssemblyDefinitions(string[] assemblyPaths, string[] searchPaths)\n        {\n            var assemblyResolver = new AssemblyResolver();\n\n            foreach (var asmpath in searchPaths)\n                assemblyResolver.AddSearchDirectory(asmpath);\n\n            var readerParameters = new ReaderParameters\n            {\n                AssemblyResolver = assemblyResolver\n            };\n\n            var assemblyDefinitions = new AssemblyDefinition[assemblyPaths.Length];\n\n            for (int i = 0; i < assemblyPaths.Length; ++i)\n            {\n                assemblyDefinitions[i] = AssemblyDefinition.ReadAssembly(assemblyPaths[i], readerParameters);\n                // Cecil tries to resolve references by filename, since Unity force loads\n                // assemblies, then assembly reference will resolve even if the assembly name\n                // does not match the assembly filename. So we register all assemblies in\n                // in the resolver.\n                assemblyResolver.RegisterAssembly(assemblyDefinitions[i]);\n            }\n\n            return assemblyDefinitions;\n        }\n\n        public static void CheckAssemblyReferences(string[] assemblyPaths,\n            Error[] errors,\n            AssemblyDefinition[] assemblyDefinitions)\n        {\n            var assemblyDefinitionNameToIndex = new Dictionary<string, int>();\n            var assembliesAndReferencesArray = new AssemblyAndReferences[assemblyPaths.Length];\n\n            for (int i = 0; i < assemblyDefinitions.Length; ++i)\n            {\n                assemblyDefinitionNameToIndex[assemblyDefinitions[i].Name.Name] = i;\n                assembliesAndReferencesArray[i] = new AssemblyAndReferences\n                {\n                    assemblyIndex = i,\n                    referenceIndicies = new int[0]\n                };\n            }\n\n            var precompiledAssemblies = EditorCompilationInterface.Instance\n                .PrecompiledAssemblyProvider.GetAllPrecompiledAssemblies()\n                .Where(x => x.Flags.HasFlag(AssemblyFlags.UserAssembly));\n            var allPrecompiledAssemblies = precompiledAssemblies.ToDictionary(x => AssetPath.ReplaceSeparators(VirtualFileSystem.ToLogicalPath(x.Path)));\n\n            for (int i = 0; i < assemblyPaths.Length; ++i)\n            {\n                if (errors[i].HasFlag(ErrorFlags.IncompatibleWithEditor))\n                    continue;\n\n                var assemblyPath = assemblyPaths[i];\n\n                // Check if \"Validate References\" option is enabled\n                // in the PluginImporter\n                if (!ShouldValidateReferences(AssetPath.ReplaceSeparators(assemblyPath), allPrecompiledAssemblies))\n                    continue;\n\n                ResolveAndSetupReferences(i,\n                    errors,\n                    assemblyDefinitions,\n                    assemblyDefinitionNameToIndex,\n                    assembliesAndReferencesArray,\n                    assemblyPath);\n            }\n\n            // Check assemblies for references to assemblies with errors\n            int referenceErrorCount;\n\n            do\n            {\n                referenceErrorCount = 0;\n\n                foreach (var assemblyAndReferences in assembliesAndReferencesArray)\n                {\n                    var assemblyIndex = assemblyAndReferences.assemblyIndex;\n\n                    foreach (var referenceIndex in assemblyAndReferences.referenceIndicies)\n                    {\n                        var referenceError = errors[referenceIndex];\n                        if (errors[assemblyIndex].flags == ErrorFlags.None &&\n                            referenceError.flags != ErrorFlags.None)\n                        {\n                            if (referenceError.HasFlag(ErrorFlags.IncompatibleWithEditor))\n                            {\n                                errors[assemblyIndex].Add(ErrorFlags.ReferenceHasErrors | ErrorFlags.IncompatibleWithEditor,\n                                    string.Format(\"Reference '{0}' is incompatible with the editor.\",\n                                        assemblyDefinitions[referenceIndex].Name.Name));\n                            }\n                            else\n                            {\n                                errors[assemblyIndex].Add(ErrorFlags.ReferenceHasErrors | referenceError.flags,\n                                    string.Format(\"Reference has errors '{0}'.\",\n                                        assemblyDefinitions[referenceIndex].Name.Name));\n                            }\n\n                            referenceErrorCount++;\n                        }\n                    }\n                }\n            }\n            while (referenceErrorCount > 0);\n        }\n\n        public static void ResolveAndSetupReferences(int index,\n            Error[] errors,\n            AssemblyDefinition[] assemblyDefinitions,\n            Dictionary<string, int> assemblyDefinitionNameToIndex,\n            AssemblyAndReferences[] assemblyAndReferences,\n            string assemblyPath)\n        {\n            var assemblyDefinition = assemblyDefinitions[index];\n            var assemblyResolver = assemblyDefinition.MainModule.AssemblyResolver;\n\n            var assemblyReferences = GetAssemblyNameReferences(assemblyDefinition);\n\n            var referenceIndieces = new List<int>\n            {\n                Capacity = assemblyReferences.Length\n            };\n\n            bool isReferencingUnityAssemblies = false;\n            foreach (var reference in assemblyReferences)\n            {\n                if (!isReferencingUnityAssemblies && (Utility.FastStartsWith(reference.Name, \"UnityEngine\", \"unityengine\") || Utility.FastStartsWith(reference.Name, \"UnityEditor\", \"unityeditor\")))\n                {\n                    isReferencingUnityAssemblies = true;\n                }\n\n                try\n                {\n                    var referenceAssemblyDefinition = assemblyResolver.Resolve(reference);\n\n                    if (reference.Name == assemblyDefinition.Name.Name)\n                    {\n                        errors[index].Add(ErrorFlags.ReferenceHasErrors, $\"{reference.Name} references itself.\");\n                    }\n\n                    if (assemblyDefinitionNameToIndex.TryGetValue(referenceAssemblyDefinition.Name.Name, out int referenceAssemblyDefinitionIndex))\n                    {\n                        referenceIndieces.Add(referenceAssemblyDefinitionIndex);\n                    }\n                }\n                catch (AssemblyResolutionException)\n                {\n                    errors[index].Add(ErrorFlags.UnresolvableReference,\n                        string.Format(\"Unable to resolve reference '{0}'. Is the assembly missing or incompatible with the current platform?\\nReference validation can be disabled in the Plugin Inspector.\",\n                            reference.Name));\n                }\n            }\n\n            if (isReferencingUnityAssemblies)\n            {\n                var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(assemblyPath);\n                if (assemblyDefinitions[index].Name.Name != fileNameWithoutExtension)\n                {\n                    errors[index].Add(ErrorFlags.ReferenceHasErrors, $\"Assembly name '{assemblyDefinitions[index].Name.Name}' does not match file name '{fileNameWithoutExtension}'\");\n                }\n            }\n\n            assemblyAndReferences[index].referenceIndicies = referenceIndieces.ToArray();\n        }\n\n        private static bool IsInSameFolder(AssemblyDefinition first, AssemblyDefinition second)\n        {\n            var firstAssemblyPath = Path.GetDirectoryName(first.MainModule.FileName);\n            var secondAssemblyPath = Path.GetDirectoryName(second.MainModule.FileName);\n            return firstAssemblyPath.Equals(secondAssemblyPath, StringComparison.Ordinal);\n        }\n\n        private static bool IsSigned(AssemblyNameReference reference)\n        {\n            //Bug in Cecil where HasPublicKey is always false\n            foreach (var publicTokenByte in reference.PublicKeyToken)\n            {\n                if (publicTokenByte != 0)\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public static AssemblyNameReference[] GetAssemblyNameReferences(AssemblyDefinition assemblyDefinition)\n        {\n            List<AssemblyNameReference> result = new List<AssemblyNameReference>\n            {\n                Capacity = 16\n            };\n\n            foreach (ModuleDefinition module in assemblyDefinition.Modules)\n            {\n                var references = module.AssemblyReferences;\n\n                foreach (var reference in references)\n                {\n                    result.Add(reference);\n                }\n            }\n\n            return result.ToArray();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetDatabase/AssetDatabase.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.VersionControl;\nusing UnityEngine.Scripting;\nusing uei = UnityEngine.Internal;\n\nnamespace UnityEditor\n{\n    public sealed partial class AssetDatabase\n    {\n        // Delegate to be called from [[AssetDatabase.ImportPackage]] callbacks\n        public delegate void ImportPackageCallback(string packageName);\n\n        // Delegate to be called from [[AssetDatabase.ImportPackage]] callbacks in the event of failure\n        public delegate void ImportPackageFailedCallback(string packageName, string errorMessage);\n\n        // Delegate to be called when package import begins\n        public static event ImportPackageCallback importPackageStarted\n        {\n            add => m_importPackageStartedEvent.Add(value);\n            remove => m_importPackageStartedEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<ImportPackageCallback> m_importPackageStartedEvent = new EventWithPerformanceTracker<ImportPackageCallback>($\"{nameof(AssetDatabase)}.{nameof(importPackageStarted)}\");\n\n        // Delegate to be called when package import completes\n        public static event ImportPackageCallback importPackageCompleted\n        {\n            add => m_importPackageCompletedEvent.Add(value);\n            remove => m_importPackageCompletedEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<ImportPackageCallback> m_importPackageCompletedEvent = new EventWithPerformanceTracker<ImportPackageCallback>($\"{nameof(AssetDatabase)}.{nameof(importPackageCompleted)}\");\n\n        // Called when package import completes, listing the selected items\n        public static Action<string[]> onImportPackageItemsCompleted;\n        private static DelegateWithPerformanceTracker<Action<string[]>> m_onImportPackageItemsCompleted = new DelegateWithPerformanceTracker<Action<string[]>>($\"{nameof(AssetDatabase)}.{nameof(onImportPackageItemsCompleted)}\");\n\n        // Delegate to be called when package import is cancelled\n        public static event ImportPackageCallback importPackageCancelled\n        {\n            add => m_importPackageCancelledEvent.Add(value);\n            remove => m_importPackageCancelledEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<ImportPackageCallback> m_importPackageCancelledEvent = new EventWithPerformanceTracker<ImportPackageCallback>($\"{nameof(AssetDatabase)}.{nameof(importPackageCancelled)}\");\n\n        // Delegate to be called when package import fails\n        public static event ImportPackageFailedCallback importPackageFailed\n        {\n            add => m_importPackageFailedEvent.Add(value);\n            remove => m_importPackageFailedEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<ImportPackageFailedCallback> m_importPackageFailedEvent = new EventWithPerformanceTracker<ImportPackageFailedCallback>($\"{nameof(AssetDatabase)}.{nameof(importPackageFailed)}\");\n\n        [RequiredByNativeCode]\n        private static void Internal_CallImportPackageStarted(string packageName)\n        {\n            foreach (var evt in m_importPackageStartedEvent)\n                evt(packageName);\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_CallImportPackageCompleted(string packageName)\n        {\n            foreach (var evt in m_importPackageCompletedEvent)\n                evt(packageName);\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_CallOnImportPackageItemsCompleted(string[] items)\n        {\n            foreach (var evt in m_onImportPackageItemsCompleted.UpdateAndInvoke(onImportPackageItemsCompleted))\n                evt(items);\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_CallImportPackageCancelled(string packageName)\n        {\n            foreach (var evt in m_importPackageCancelledEvent)\n                evt(packageName);\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_CallImportPackageFailed(string packageName, string errorMessage)\n        {\n            foreach (var evt in m_importPackageFailedEvent)\n                evt(packageName, errorMessage);\n        }\n\n        [RequiredByNativeCode]\n        private static bool Internal_IsOpenForEdit(string assetOrMetaFilePath)\n        {\n            return IsOpenForEdit(assetOrMetaFilePath);\n        }\n\n        public static void CanOpenForEdit(string[] assetOrMetaFilePaths, List<string> outNotEditablePaths, [uei.DefaultValue(\"StatusQueryOptions.UseCachedIfPossible\")] StatusQueryOptions statusQueryOptions = StatusQueryOptions.UseCachedIfPossible)\n        {\n            if (assetOrMetaFilePaths == null)\n                throw new ArgumentNullException(nameof(assetOrMetaFilePaths));\n            if (outNotEditablePaths == null)\n                throw new ArgumentNullException(nameof(outNotEditablePaths));\n            UnityEngine.Profiling.Profiler.BeginSample(\"AssetDatabase.CanOpenForEdit\");\n            AssetModificationProcessorInternal.CanOpenForEdit(assetOrMetaFilePaths, outNotEditablePaths, statusQueryOptions);\n            UnityEngine.Profiling.Profiler.EndSample();\n        }\n\n        public static void IsOpenForEdit(string[] assetOrMetaFilePaths, List<string> outNotEditablePaths, [uei.DefaultValue(\"StatusQueryOptions.UseCachedIfPossible\")] StatusQueryOptions statusQueryOptions = StatusQueryOptions.UseCachedIfPossible)\n        {\n            if (assetOrMetaFilePaths == null)\n                throw new ArgumentNullException(nameof(assetOrMetaFilePaths));\n            if (outNotEditablePaths == null)\n                throw new ArgumentNullException(nameof(outNotEditablePaths));\n            UnityEngine.Profiling.Profiler.BeginSample(\"AssetDatabase.IsOpenForEdit\");\n            AssetModificationProcessorInternal.IsOpenForEdit(assetOrMetaFilePaths, outNotEditablePaths, statusQueryOptions);\n            UnityEngine.Profiling.Profiler.EndSample();\n        }\n\n        [RequiredByNativeCode]\n        private static bool Internal_MakeEditable(string path)\n        {\n            return MakeEditable(path);\n        }\n\n        public static bool MakeEditable(string path)\n        {\n            if (path == null)\n                throw new ArgumentNullException(nameof(path));\n            return MakeEditable(new[] {path});\n        }\n\n        [RequiredByNativeCode]\n        private static bool Internal_MakeEditable2(string[] paths, string prompt = null, List<string> outNotEditablePaths = null)\n        {\n            return MakeEditable(paths, prompt, outNotEditablePaths);\n        }\n\n        public static bool MakeEditable(string[] paths, string prompt = null, List<string> outNotEditablePaths = null)\n        {\n            if (paths == null)\n                throw new ArgumentNullException(nameof(paths));\n            UnityEngine.Profiling.Profiler.BeginSample(\"AssetDatabase.MakeEditable\");\n            ChangeSet changeSet = null;\n            var result = Provider.HandlePreCheckoutCallback(ref paths, ref changeSet);\n            if (result && !AssetModificationProcessorInternal.MakeEditable(paths, prompt, outNotEditablePaths))\n                result = false;\n            if (result && !Provider.MakeEditableImpl(paths, prompt, changeSet, outNotEditablePaths))\n                result = false;\n            UnityEngine.Profiling.Profiler.EndSample();\n            return result;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetDatabase/AssetDatabase.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEditor.AssetImporters;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    partial class AssetDatabase\n    {\n        // Gets the path to the text .meta file associated with an asset\n        [Obsolete(\"GetTextMetaDataPathFromAssetPath has been renamed to GetTextMetaFilePathFromAssetPath (UnityUpgradable) -> GetTextMetaFilePathFromAssetPath(*)\",true)]\n        public static string GetTextMetaDataPathFromAssetPath(string path) { return null; }\n    }\n\n    // Used to be part of Asset Server, and public API for some reason.\n    [Obsolete(\"AssetStatus enum is not used anymore (Asset Server has been removed)\",true)]\n    public enum AssetStatus\n    {\n        Calculating = -1,\n        ClientOnly = 0,\n        ServerOnly = 1,\n        Unchanged = 2,\n        Conflict = 3,\n        Same = 4,\n        NewVersionAvailable = 5,\n        NewLocalVersion = 6,\n        RestoredFromTrash = 7,\n        Ignored = 8,\n        BadState = 9\n    }\n\n    // Used to be part of Asset Server, and public API for some reason.\n    [Obsolete(\"AssetsItem class is not used anymore (Asset Server has been removed)\",true)]\n    [StructLayout(LayoutKind.Sequential)]\n    [System.Serializable]\n    public sealed class AssetsItem\n    {\n        public string guid;\n        public string pathName;\n        public string message;\n        public string exportedAssetPath;\n        public string guidFolder;\n        public int enabled;\n        public int assetIsDir;\n        public int changeFlags;\n        public string previewPath;\n        public int exists;\n    }\n}\n\nnamespace UnityEditor.Experimental\n{\n    public partial class AssetDatabaseExperimental\n    {\n        [FreeFunction(\"AssetDatabase::ClearImporterOverride\")]\n        [Obsolete(\"AssetDatabaseExperimental.ClearImporterOverride() has been deprecated. Use AssetDatabase.ClearImporterOverride() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.ClearImporterOverride(*)\", true)]\n        extern public static void ClearImporterOverride(string path);\n\n        [FreeFunction(\"AssetDatabase::IsCacheServerEnabled\")]\n        [Obsolete(\"AssetDatabaseExperimental.IsCacheServerEnabled() has been deprecated. Use AssetDatabase.IsCacheServerEnabled() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.IsCacheServerEnabled(*)\", true)]\n        public extern static bool IsCacheServerEnabled();\n\n        [Obsolete(\"AssetDatabaseExperimental.SetImporterOverride<T>() has been deprecated. Use AssetDatabase.SetImporterOverride<T>() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.SetImporterOverride<T>(*)\", true)]\n        public static void SetImporterOverride<T>(string path)\n            where T : ScriptedImporter\n        {\n            AssetDatabase.SetImporterOverrideInternal(path, typeof(T));\n        }\n\n        [FreeFunction(\"AssetDatabase::GetImporterOverride\")]\n        [Obsolete(\"AssetDatabaseExperimental.GetImporterOverride() has been deprecated. Use AssetDatabase.GetImporterOverride() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.GetImporterOverride(*)\", true)]\n        extern public static System.Type GetImporterOverride(string path);\n\n        [FreeFunction(\"AssetDatabase::GetAvailableImporters\")]\n        [Obsolete(\"AssetDatabaseExperimental.GetAvailableImporterTypes() has been deprecated. Use AssetDatabase.GetAvailableImporters() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.GetAvailableImporters(*)\", true)]\n        extern public static Type[] GetAvailableImporterTypes(string path);\n\n        [FreeFunction(\"AcceleratorClientCanConnectTo\")]\n        [Obsolete(\"AssetDatabaseExperimental.CanConnectToCacheServer() has been deprecated. Use AssetDatabase.CanConnectToCacheServer() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.CanConnectToCacheServer(*)\", true)]\n        public extern static bool CanConnectToCacheServer(string ip, UInt16 port);\n\n        [FreeFunction()]\n        [Obsolete(\"AssetDatabaseExperimental.RefreshSettings() has been deprecated. Use AssetDatabase.RefreshSettings() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.RefreshSettings(*)\", true)]\n        public extern static void RefreshSettings();\n\n        [Obsolete(\"AssetDatabaseExperimental.CacheServerConnectionChangedParameters has been deprecated. Use UnityEditor.CacheServerConnectionChangedParameters instead (UnityUpgradable) -> UnityEditor.CacheServerConnectionChangedParameters\", true)]\n        public struct CacheServerConnectionChangedParameters\n        {\n        }\n\n#pragma warning disable 67\n        [Obsolete(\"AssetDatabaseExperimental.cacheServerConnectionChanged has been deprecated. Use AssetDatabase.cacheServerConnectionChanged instead (UnityUpgradable) -> UnityEditor.AssetDatabase.cacheServerConnectionChanged\", true)]\n        public static event Action<CacheServerConnectionChangedParameters> cacheServerConnectionChanged;\n#pragma warning restore 67\n\n        [FreeFunction(\"AcceleratorClientIsConnected\")]\n        [Obsolete(\"AssetDatabaseExperimental.IsConnectedToCacheServer() has been deprecated. Use AssetDatabase.IsConnectedToCacheServer() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.IsConnectedToCacheServer(*)\", true)]\n        public extern static bool IsConnectedToCacheServer();\n\n        [FreeFunction()]\n        [Obsolete(\"AssetDatabaseExperimental.GetCacheServerAddress() has been deprecated. Use AssetDatabase.GetCacheServerAddress() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.GetCacheServerAddress(*)\", true)]\n        public extern static string GetCacheServerAddress();\n\n        [FreeFunction()]\n        [Obsolete(\"AssetDatabaseExperimental.GetCacheServerPort() has been deprecated. Use AssetDatabase.GetCacheServerPort() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.GetCacheServerPort(*)\", true)]\n        public extern static UInt16 GetCacheServerPort();\n\n        [FreeFunction(\"AssetDatabase::GetCacheServerNamespacePrefix\")]\n        [Obsolete(\"AssetDatabaseExperimental.GetCacheServerNamespacePrefix() has been deprecated. Use AssetDatabase.GetCacheServerNamespacePrefix() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.GetCacheServerNamespacePrefix(*)\", true)]\n        public extern static string GetCacheServerNamespacePrefix();\n\n        [FreeFunction(\"AssetDatabase::GetCacheServerEnableDownload\")]\n        [Obsolete(\"AssetDatabaseExperimental.GetCacheServerEnableDownload() has been deprecated. Use AssetDatabase.GetCacheServerEnableDownload() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.GetCacheServerEnableDownload(*)\", true)]\n        public extern static bool GetCacheServerEnableDownload();\n\n        [FreeFunction(\"AssetDatabase::GetCacheServerEnableUpload\")]\n        [Obsolete(\"AssetDatabaseExperimental.GetCacheServerEnableUpload() has been deprecated. Use AssetDatabase.GetCacheServerEnableUpload() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.GetCacheServerEnableUpload(*)\", true)]\n        public extern static bool GetCacheServerEnableUpload();\n\n        [FreeFunction(\"AssetDatabase::IsDirectoryMonitoringEnabled\")]\n        [Obsolete(\"AssetDatabaseExperimental.IsDirectoryMonitoringEnabled() has been deprecated. Use AssetDatabase.IsDirectoryMonitoringEnabled() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.IsDirectoryMonitoringEnabled(*)\", true)]\n        public extern static bool IsDirectoryMonitoringEnabled();\n\n        [FreeFunction(\"AssetDatabaseExperimental::RegisterCustomDependency\")]\n        [PreventExecutionInState(AssetDatabasePreventExecution.kPreventCustomDependencyChanges, PreventExecutionSeverity.PreventExecution_ManagedException, \"Custom dependencies can only be removed when the assetdatabase is not importing.\")]\n        [Obsolete(\"AssetDatabaseExperimental.RegisterCustomDependency() has been deprecated. Use AssetDatabase.RegisterCustomDependency() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.RegisterCustomDependency(*)\", true)]\n        public extern static void RegisterCustomDependency(string dependency, Hash128 hashOfValue);\n\n        [FreeFunction(\"AssetDatabaseExperimental::UnregisterCustomDependencyPrefixFilter\")]\n        [PreventExecutionInState(AssetDatabasePreventExecution.kPreventCustomDependencyChanges, PreventExecutionSeverity.PreventExecution_ManagedException, \"Custom dependencies can only be removed when the assetdatabase is not importing.\")]\n        [Obsolete(\"AssetDatabaseExperimental.UnregisterCustomDependencyPrefixFilter() has been deprecated. Use AssetDatabase.UnregisterCustomDependencyPrefixFilter() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.UnregisterCustomDependencyPrefixFilter(*)\", true)]\n        public extern static UInt32 UnregisterCustomDependencyPrefixFilter(string prefixFilter);\n\n        [FreeFunction(\"AssetDatabase::IsAssetImportProcess\")]\n        [Obsolete(\"AssetDatabaseExperimental.IsAssetImportWorkerProcess() has been deprecated. Use AssetDatabase.IsAssetImportWorkerProcess() instead (UnityUpgradable) -> UnityEditor.AssetDatabase.IsAssetImportWorkerProcess(*)\", true)]\n        public extern static bool IsAssetImportWorkerProcess();\n    }\n}\n\n"
  },
  {
    "path": "Editor/Mono/AssetDatabase/AssetDatabaseSearching.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing UnityEditor.Utils;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    public sealed partial class AssetDatabase\n    {\n        public static string[] FindAssets(string filter)\n        {\n            return FindAssets(filter, null);\n        }\n\n        public static string[] FindAssets(string filter, string[] searchInFolders)\n        {\n            var searchFilter = new SearchFilter { searchArea = SearchFilter.SearchArea.AllAssets };\n            SearchUtility.ParseSearchString(filter, searchFilter);\n            if (searchInFolders != null && searchInFolders.Length > 0)\n            {\n                searchFilter.folders = searchInFolders;\n                searchFilter.searchArea = SearchFilter.SearchArea.SelectedFolders;\n            }\n\n            return FindAssets(searchFilter);\n        }\n\n        internal static string[] FindAssets(SearchFilter searchFilter)\n        {\n            return FindAllAssets(searchFilter).Select(property => property.guid).Distinct().ToArray();\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal static IEnumerable<HierarchyProperty> FindAllAssets(SearchFilter searchFilter)\n        {\n            var enumerator = EnumerateAllAssets(searchFilter);\n            while (enumerator.MoveNext())\n                yield return enumerator.Current;\n        }\n\n        internal static IEnumerator<HierarchyProperty> EnumerateAllAssets(SearchFilter searchFilter)\n        {\n            if (searchFilter.folders != null && searchFilter.folders.Length > 0 && searchFilter.searchArea == SearchFilter.SearchArea.SelectedFolders)\n                return FindInFolders(searchFilter, p => p);\n\n            return FindEverywhere(searchFilter, p => p);\n        }\n\n        private static IEnumerator<T> FindInFolders<T>(SearchFilter searchFilter, Func<HierarchyProperty,  T> selector)\n        {\n            var folders = new List<string>();\n            folders.AddRange(searchFilter.folders);\n            if (folders.Remove(PackageManager.Folders.GetPackagesPath()))\n            {\n                var packages = PackageManagerUtilityInternal.GetAllVisiblePackages(searchFilter.skipHidden);\n                foreach (var package in packages)\n                {\n                    if (!folders.Contains(package.assetPath))\n                        folders.Add(package.assetPath);\n                }\n            }\n\n            HierarchyProperty propertyWithFilter = null;\n            foreach (var folderPath in folders)\n            {\n                var sanitizedFolderPath = folderPath.ConvertSeparatorsToUnity().TrimTrailingSlashes();\n                var folderInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(sanitizedFolderPath);\n                var rootPath = \"Assets\";\n\n                // Find the right rootPath if folderPath is part of a package\n                var packageInfo = PackageManager.PackageInfo.FindForAssetPath(sanitizedFolderPath);\n                if (packageInfo != null)\n                {\n                    rootPath = packageInfo.assetPath;\n                    if (searchFilter.skipHidden && !PackageManagerUtilityInternal.IsPathInVisiblePackage(rootPath))\n                        continue;\n                }\n\n                // Set empty filter to ensure we search all assets to find folder\n                var property = new HierarchyProperty(rootPath);\n                property.SetSearchFilter(new SearchFilter());\n                if (property.Find(folderInstanceID, null))\n                {\n                    // Set filter after we found the folder\n                    if (propertyWithFilter != null)\n                        property.CopySearchFilterFrom(propertyWithFilter);\n                    else\n                    {\n                        property.SetSearchFilter(searchFilter);\n                        propertyWithFilter = property;\n                    }\n\n                    int folderDepth = property.depth;\n                    int[] expanded = null; // enter all children of folder\n                    while (property.NextWithDepthCheck(expanded, folderDepth + 1))\n                    {\n                        yield return selector(property);\n                    }\n                }\n                else\n                {\n                    Debug.LogWarning(\"AssetDatabase.FindAssets: Folder not found: '\" + sanitizedFolderPath + \"'\");\n                }\n            }\n        }\n\n        private static IEnumerator<T> FindEverywhere<T>(SearchFilter searchFilter, Func<HierarchyProperty, T> selector)\n        {\n            var rootPaths = new List<string>();\n            if (searchFilter.searchArea == SearchFilter.SearchArea.AllAssets ||\n                searchFilter.searchArea == SearchFilter.SearchArea.InAssetsOnly)\n            {\n                rootPaths.Add(\"Assets\");\n            }\n            if (searchFilter.searchArea == SearchFilter.SearchArea.AllAssets ||\n                searchFilter.searchArea == SearchFilter.SearchArea.InPackagesOnly)\n            {\n                var packages = PackageManagerUtilityInternal.GetAllVisiblePackages(searchFilter.skipHidden);\n                foreach (var package in packages)\n                {\n                    rootPaths.Add(package.assetPath);\n                }\n            }\n\n            HierarchyProperty lastProperty = null;\n            foreach (var rootPath in rootPaths)\n            {\n                var property = new HierarchyProperty(rootPath);\n                if (lastProperty != null)\n                    property.CopySearchFilterFrom(lastProperty);\n                else\n                    property.SetSearchFilter(searchFilter);\n                lastProperty = property;\n                while (property.Next(null))\n                {\n                    yield return selector(property);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetDatabase/AssetImportInProgressProxy.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [NativeType(Header = \"Modules/AssetDatabase/Editor/Public/AssetImportInProgressProxy.h\")]\n    class AssetImportInProgressProxy : UnityEngine.Object\n    {\n        public extern GUID asset\n        {\n            [NativeMethod(\"GetAsset\")]\n            get;\n            [NativeMethod(\"SetAsset\")]\n            set;\n        }\n\n        [NativeMethod]\n        public extern static bool IsProxyAsset(int instanceID);\n    }\n\n    [CustomEditor(typeof(AssetImportInProgressProxy))]\n    class AssetImportInProgressProxyEditor : Editor\n    {\n        public override void OnInspectorGUI()\n        {\n            var proxy = (AssetImportInProgressProxy)target;\n\n            if (GUILayout.Button(\"Import\"))\n            {\n                var mainAsset = AssetDatabase.LoadMainAssetAtGUID(proxy.asset);\n                Selection.activeObject = mainAsset;\n                //@TODO: Properly call this from C++ when asset import completes...\n                //EditorApplication.projectWindowChanged();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetDatabase/AssetMoveInfo.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Experimental\n{\n    public struct AssetMoveInfo : IEquatable<AssetMoveInfo>\n    {\n        public AssetMoveInfo(string sourceAssetPath, string destinationAssetPath)\n        {\n            this.sourceAssetPath = sourceAssetPath;\n            this.destinationAssetPath = destinationAssetPath;\n        }\n\n        public string sourceAssetPath { get; }\n        public string destinationAssetPath { get; }\n\n        public bool Equals(AssetMoveInfo other)\n        {\n            return string.Equals(sourceAssetPath, other.sourceAssetPath) && string.Equals(destinationAssetPath, other.destinationAssetPath);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj)) return false;\n            return obj is AssetMoveInfo && Equals((AssetMoveInfo)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                return ((sourceAssetPath != null ? sourceAssetPath.GetHashCode() : 0) * 397) ^ (destinationAssetPath != null ? destinationAssetPath.GetHashCode() : 0);\n            }\n        }\n\n        public static bool operator==(AssetMoveInfo left, AssetMoveInfo right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator!=(AssetMoveInfo left, AssetMoveInfo right)\n        {\n            return !left.Equals(right);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetDatabase/AssetPreview.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Mono/AssetDatabase/AssetPreview.bindings.h\")]\n    [NativeHeader(\"Editor/Src/Utility/ObjectImages.h\")]\n    public sealed class AssetPreview\n    {\n        private const int kSharedClientID = 0;\n\n        public static Texture2D GetAssetPreview(Object asset)\n        {\n            if (asset != null)\n                return GetAssetPreview(asset.GetInstanceID());\n            return null;\n        }\n\n        internal static Texture2D GetAssetPreview(EntityId entityId)\n        {\n            return GetAssetPreview(entityId, kSharedClientID);\n        }\n\n        [FreeFunction(\"AssetPreviewBindings::GetAssetPreview\")]\n        internal static extern Texture2D GetAssetPreview(EntityId entityId, int clientID);\n\n        [FreeFunction(\"AssetPreviewBindings::HasAssetPreview\")]\n        internal static extern bool HasAssetPreview(EntityId entityId, int clientID);\n\n        internal static Texture2D GetAssetPreviewFromGUID(string guid)\n        {\n            return GetAssetPreviewFromGUID(guid, kSharedClientID);\n        }\n\n        [FreeFunction(\"AssetPreviewBindings::GetAssetPreviewFromGUID\")]\n        internal static extern Texture2D GetAssetPreviewFromGUID(string guid, int clientID);\n\n        public static bool IsLoadingAssetPreview(int instanceID)\n        {\n            return IsLoadingAssetPreview(instanceID, kSharedClientID);\n        }\n\n        public static bool IsLoadingAssetPreview(EntityId entityId)\n        {\n            return IsLoadingAssetPreview(entityId, kSharedClientID);\n        }\n\n        [FreeFunction(\"AssetPreviewBindings::IsLoadingAssetPreview\")]\n        internal static extern bool IsLoadingAssetPreview(EntityId entityId, int clientID);\n\n        public static bool IsLoadingAssetPreviews()\n        {\n            return IsLoadingAssetPreviews(kSharedClientID);\n        }\n\n        [FreeFunction(\"AssetPreviewBindings::IsLoadingAssetPreviews\")]\n        internal static extern bool IsLoadingAssetPreviews(int clientID);\n\n        internal static bool HasAnyNewPreviewTexturesAvailable()\n        {\n            return HasAnyNewPreviewTexturesAvailable(kSharedClientID);\n        }\n\n        [FreeFunction(\"AssetPreviewBindings::HasAnyNewPreviewTexturesAvailable\")]\n        internal static extern bool HasAnyNewPreviewTexturesAvailable(int clientID);\n\n        public static void SetPreviewTextureCacheSize(int size)\n        {\n            SetPreviewTextureCacheSize(size, kSharedClientID);\n        }\n\n        [FreeFunction(\"AssetPreviewBindings::SetPreviewTextureCacheSize\")]\n        internal static extern void SetPreviewTextureCacheSize(int size, int clientID);\n\n        [FreeFunction(\"AssetPreviewBindings::ClearTemporaryAssetPreviews\")]\n        internal static extern void ClearTemporaryAssetPreviews();\n\n        [FreeFunction(\"AssetPreviewBindings::DeletePreviewTextureManagerByID\")]\n        internal static extern void DeletePreviewTextureManagerByID(int clientID);\n\n        public static Texture2D GetMiniThumbnail(Object obj)\n        {\n            return (Texture2D)GetMiniThumbnailInternal(obj);\n        }\n\n        [FreeFunction(\"TextureForObject\")]\n        private static extern Texture GetMiniThumbnailInternal(Object obj);\n\n        public static Texture2D GetMiniTypeThumbnail(Type type)\n        {\n            return GetMiniTypeThumbnailFromType(type);\n        }\n\n        [FreeFunction(\"AssetPreviewBindings::GetMiniTypeThumbnailFromObject\")]\n        internal static extern Texture2D GetMiniTypeThumbnail(Object obj);\n\n        [FreeFunction(\"AssetPreviewBindings::GetMiniTypeThumbnailFromClassID\")]\n        internal static extern Texture2D GetMiniTypeThumbnailFromClassID(int classID);\n\n        [FreeFunction(\"AssetPreviewBindings::GetMiniTypeThumbnailFromType\")]\n        internal static extern Texture2D GetMiniTypeThumbnailFromType(Type managedType);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetDatabase/AssetsModifiedProcessor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Profiling;\n\nnamespace UnityEditor.Experimental\n{\n    public abstract class AssetsModifiedProcessor\n    {\n        public HashSet<string> assetsReportedChanged { get; set; }\n\n        protected void ReportAssetChanged(string assetChanged)\n        {\n            if (assetsReportedChanged == null)\n                throw new InvalidOperationException(\"Cannot call ReportAssetChanged outside of the OnAssetsModified callback\");\n\n            assetsReportedChanged.Add(assetChanged);\n        }\n\n        //Note: changedAssets including added and moved assets may be a usability issue. Review before making public.\n        ///<summary>Fired when the [[AssetDatabase]] detects Asset changes before any Assets are imported.</summary>\n        ///<param name=\"changedAssets\">Paths to the Assets whose file contents have changed. Includes all added and moved Assets.</param>\n        ///<param name=\"addedAssets\">Paths to added Assets.</param>\n        ///<param name=\"deletedAssets\">Paths to deleted Assets.</param>\n        ///<param name=\"movedAssets\">Array of AssetMoveInfo that contains the previous and current location of any moved Assets.</param>\n        ///<description> An Asset will only be reported moved if its .meta file is moved as well.</description>\n        protected abstract void OnAssetsModified(string[] changedAssets, string[] addedAssets, string[] deletedAssets, AssetMoveInfo[] movedAssets);\n\n        internal void Internal_OnAssetsModified(string[] changedAssets, string[] addedAssets, string[] deletedAssets, AssetMoveInfo[] movedAssets)\n        {\n            var type = GetType();\n            using (new EditorPerformanceMarker($\"{type.Name}.{nameof(OnAssetsModified)}\", type).Auto())\n            {\n                OnAssetsModified(changedAssets, addedAssets, deletedAssets, movedAssets);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetDeleteResult.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor\n{\n    [Flags]\n    public enum AssetDeleteResult\n    {\n        // Tells the internal implementation that the callback did not delete the asset. The asset will be delete by the internal implementation.\n        DidNotDelete = 0,\n\n        // Tells Unity that the file cannot be deleted and Unity should leave it alone.\n        FailedDelete = 1,\n\n        //  Tells Unity that the asset was deleted by the callback. Unity will not try to delete the asset, but will delete the cached version and preview file.\n        DidDelete = 2\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetModificationProcessor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing UnityEditor.VersionControl;\nusing UnityEditorInternal;\nusing UnityEditorInternal.VersionControl;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEditor.Profiling;\nusing UnityEngine.Scripting.APIUpdating;\n\nnamespace UnityEditor\n{\n    [MovedFrom(\"\")]\n    public class AssetModificationProcessor\n    {\n    }\n\n    internal class AssetModificationProcessorInternal\n    {\n        static bool CheckArgumentTypes(Type[] types, MethodInfo method)\n        {\n            ParameterInfo[] parameters = method.GetParameters();\n\n            if (types.Length != parameters.Length)\n            {\n                Debug.LogWarning(\"Parameter count did not match. Expected: \" + types.Length + \" Got: \" + parameters.Length + \" in \" + method.DeclaringType + \".\" + method.Name);\n                return false;\n            }\n\n            int i = 0;\n            foreach (Type type in types)\n            {\n                ParameterInfo pInfo = parameters[i];\n                if (type != pInfo.ParameterType)\n                {\n                    Debug.LogWarning(\"Parameter type mismatch at parameter \" + i + \". Expected: \" + type + \" Got: \" + pInfo.ParameterType + \" in \" + method.DeclaringType + \".\" + method.Name);\n                    return false;\n                }\n                ++i;\n            }\n\n            return true;\n        }\n\n        static bool CheckArgumentTypesAndReturnType(Type[] types, MethodInfo method, System.Type returnType)\n        {\n            if (returnType != method.ReturnType)\n            {\n                Debug.LogWarning(\"Return type mismatch. Expected: \" + returnType + \" Got: \" + method.ReturnType + \" in \" + method.DeclaringType + \".\" + method.Name);\n                return false;\n            }\n\n            return CheckArgumentTypes(types, method);\n        }\n\n        static bool CheckArguments(object[] args, MethodInfo method)\n        {\n            Type[] types = new Type[args.Length];\n\n            for (int i = 0; i < args.Length; i++)\n                types[i] = args[i].GetType();\n\n            return CheckArgumentTypes(types, method);\n        }\n\n        static bool CheckArgumentsAndReturnType(object[] args, MethodInfo method, System.Type returnType)\n        {\n            Type[] types = new Type[args.Length];\n\n            for (int i = 0; i < args.Length; i++)\n                types[i] = args[i].GetType();\n\n            return CheckArgumentTypesAndReturnType(types, method, returnType);\n        }\n\n#pragma warning disable 0618\n        static System.Collections.Generic.IEnumerable<System.Type> assetModificationProcessors = null;\n        static System.Collections.Generic.IEnumerable<System.Type> AssetModificationProcessors\n        {\n            get\n            {\n                if (assetModificationProcessors == null)\n                {\n                    List<Type> processors = new List<Type>();\n                    processors.AddRange(TypeCache.GetTypesDerivedFrom<AssetModificationProcessor>());\n                    assetModificationProcessors = processors.ToArray();\n                }\n                return assetModificationProcessors;\n            }\n        }\n#pragma warning restore 0618\n\n        [RequiredByNativeCode]\n        internal static void OnWillCreateAsset(string path)\n        {\n            foreach (var assetModificationProcessorClass in AssetModificationProcessors)\n            {\n                const string methodName = \"OnWillCreateAsset\";\n                MethodInfo method = assetModificationProcessorClass.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);\n                if (method != null)\n                {\n                    object[] args = { path };\n                    if (!CheckArguments(args, method))\n                        continue;\n\n                    using (new EditorPerformanceMarker($\"{assetModificationProcessorClass.Name}.{methodName}\", assetModificationProcessorClass).Auto())\n                        method.Invoke(null, args);\n                }\n            }\n        }\n\n        // ReSharper disable once UnusedMember.Local - invoked from native code\n        [RequiredByNativeCode]\n        static void FileModeChanged(string[] assets, FileMode mode)\n        {\n            AssetModificationHook.FileModeChanged(assets, mode);\n\n            object[] args = { assets, mode };\n            foreach (var type in AssetModificationProcessors)\n            {\n                const string methodName = \"FileModeChanged\";\n                var method = type.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);\n                if (method == null)\n                    continue;\n                if (!CheckArgumentsAndReturnType(args, method, typeof(void)))\n                    continue;\n                using (new EditorPerformanceMarker($\"{type.Name}.{methodName}\", type).Auto())\n                    method.Invoke(null, args);\n            }\n        }\n\n        // Postprocess on all assets once an automatic import has completed\n        // ReSharper disable once UnusedMember.Local - invoked from native code\n        [RequiredByNativeCode]\n        static void OnWillSaveAssets(string[] assets, out string[] assetsThatShouldBeSaved, out string[] assetsThatShouldBeReverted, bool explicitlySaveAsset)\n        {\n            assetsThatShouldBeReverted = new string[0];\n            assetsThatShouldBeSaved = assets;\n\n            bool showSaveDialog = assets.Length > 0 && EditorPrefs.GetBool(\"VerifySavingAssets\", false) && InternalEditorUtility.isHumanControllingUs;\n\n            // If we are only saving a single scene or prefab and the user explicitly said we should, skip the dialog. We don't need\n            // to verify this twice.\n            if (explicitlySaveAsset && assets.Length == 1 && (assets[0].EndsWith(\".unity\") || assets[0].EndsWith(\".prefab\")))\n                showSaveDialog = false;\n\n            if (showSaveDialog)\n                AssetSaveDialog.ShowWindow(assets, out assetsThatShouldBeSaved);\n            else\n                assetsThatShouldBeSaved = assets;\n\n            foreach (var assetModificationProcessorClass in AssetModificationProcessors)\n            {\n                const string methodName = \"OnWillSaveAssets\";\n                MethodInfo method = assetModificationProcessorClass.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);\n                if (method != null)\n                {\n                    object[] args = { assetsThatShouldBeSaved };\n                    if (!CheckArguments(args, method))\n                        continue;\n\n                    string[] result;\n                    using (new EditorPerformanceMarker($\"{assetModificationProcessorClass.Name}.{methodName}\", assetModificationProcessorClass).Auto())\n                        result = (string[])method.Invoke(null, args);\n\n                    if (result != null)\n                        assetsThatShouldBeSaved = result;\n                }\n            }\n\n            if (assetsThatShouldBeSaved == null)\n            {\n                return;\n            }\n\n            var assetsNotOpened = new List<string>();\n            AssetDatabase.IsOpenForEdit(assetsThatShouldBeSaved, assetsNotOpened, StatusQueryOptions.ForceUpdate);\n            assets = assetsNotOpened.ToArray();\n\n            // Try to checkout if needed\n            var notEditableAssets = new List<string>();\n            if (assets.Length != 0 && !AssetDatabase.MakeEditable(assets, null, notEditableAssets))\n            {\n                // only save assets that can be made editable (not locked by someone else, etc.),\n                // unless we are in the behavior mode that just overwrites everything anyway\n                if (!EditorUserSettings.overwriteFailedCheckoutAssets)\n                {\n                    assetsThatShouldBeReverted = notEditableAssets.ToArray();\n                    assetsThatShouldBeSaved = assetsThatShouldBeSaved.Except(assetsThatShouldBeReverted).ToArray();\n                }\n            }\n        }\n\n        [RequiredByNativeCode]\n        static AssetMoveResult OnWillMoveAsset(string fromPath, string toPath, string[] newPaths, string[] NewMetaPaths)\n        {\n            AssetMoveResult finalResult = AssetMoveResult.DidNotMove;\n            finalResult = AssetModificationHook.OnWillMoveAsset(fromPath, toPath);\n\n            foreach (var assetModificationProcessorClass in AssetModificationProcessors)\n            {\n                const string methodName = \"OnWillMoveAsset\";\n                MethodInfo method = assetModificationProcessorClass.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);\n                if (method != null)\n                {\n                    object[] args = { fromPath, toPath };\n                    if (!CheckArgumentsAndReturnType(args, method, finalResult.GetType()))\n                        continue;\n\n                    using (new EditorPerformanceMarker($\"{assetModificationProcessorClass.Name}.{methodName}\", assetModificationProcessorClass).Auto())\n                        finalResult |= (AssetMoveResult)method.Invoke(null, args);\n                }\n            }\n\n            return finalResult;\n        }\n\n        [RequiredByNativeCode]\n        static AssetDeleteResult OnWillDeleteAsset(string assetPath, RemoveAssetOptions options)\n        {\n            AssetDeleteResult finalResult = AssetDeleteResult.DidNotDelete;\n\n            foreach (var assetModificationProcessorClass in AssetModificationProcessors)\n            {\n                const string methodName = \"OnWillDeleteAsset\";\n                MethodInfo method = assetModificationProcessorClass.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);\n                if (method != null)\n                {\n                    object[] args = { assetPath, options };\n                    if (!CheckArgumentsAndReturnType(args, method, finalResult.GetType()))\n                        continue;\n\n                    using (new EditorPerformanceMarker($\"{assetModificationProcessorClass.Name}.{methodName}\", assetModificationProcessorClass).Auto())\n                        finalResult |= (AssetDeleteResult)method.Invoke(null, args);\n                }\n            }\n\n            if (finalResult != AssetDeleteResult.DidNotDelete)\n                return finalResult;\n\n            finalResult = AssetModificationHook.OnWillDeleteAsset(assetPath, options);\n\n            return finalResult;\n        }\n\n        [RequiredByNativeCode]\n        static void OnWillDeleteAssets(string[] assetPaths, AssetDeleteResult[] outPathDeletionResults, RemoveAssetOptions options)\n        {\n            for (int i = 0; i < outPathDeletionResults.Length; i++)\n                outPathDeletionResults[i] = (int)AssetDeleteResult.DidNotDelete;\n\n            List<string> nonDeletedPaths    = new List<string>();\n            List<int> nonDeletedPathIndices = new List<int>();\n            foreach (var assetModificationProcessorClass in AssetModificationProcessors)\n            {\n                const string methodName = \"OnWillDeleteAsset\";\n                MethodInfo method = assetModificationProcessorClass.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);\n                if (method == null)\n                    continue;\n\n                for (int i = 0; i < assetPaths.Length; i++)\n                {\n                    object[] args = { assetPaths[i], options };\n                    if (!CheckArgumentsAndReturnType(args, method, typeof(AssetDeleteResult)))\n                        continue;\n\n\n                    using (new EditorPerformanceMarker($\"{assetModificationProcessorClass.Name}.{methodName}\", assetModificationProcessorClass).Auto())\n                    {\n                        AssetDeleteResult callbackResult = (AssetDeleteResult)method.Invoke(null, args);\n                        outPathDeletionResults[i] |= callbackResult;\n                    }\n                }\n            }\n\n            for (int i = 0; i < assetPaths.Length; i++)\n            {\n                if (outPathDeletionResults[i] == (int)AssetDeleteResult.DidNotDelete)\n                {\n                    nonDeletedPaths.Add(assetPaths[i]);\n                    nonDeletedPathIndices.Add(i);\n                }\n            }\n\n            if (nonDeletedPaths.Count > 0)\n            {\n                if (!Provider.enabled || EditorUserSettings.WorkOffline)\n                    return;\n\n                for (int i = 0; i < nonDeletedPaths.Count; i++)\n                {\n                    if (!Provider.PathIsVersioned(nonDeletedPaths[i]))\n                    {\n                        nonDeletedPaths.RemoveAt(i);\n                        nonDeletedPathIndices.RemoveAt(i);\n                        i--;\n                    }\n                }\n\n                var nonDeletedPathDeletionResults = new AssetDeleteResult[nonDeletedPaths.Count];\n\n                AssetModificationHook.OnWillDeleteAssets(nonDeletedPaths.ToArray(), nonDeletedPathDeletionResults, options);\n\n                for (int i = 0; i < nonDeletedPathIndices.Count; i++)\n                {\n                    outPathDeletionResults[nonDeletedPathIndices[i]] = nonDeletedPathDeletionResults[i];\n                }\n            }\n        }\n\n        static MethodInfo[] s_CanOpenForEditMethods;\n        static MethodInfo[] s_LegacyCanOpenForEditMethods;\n        static MethodInfo[] s_IsOpenForEditMethods;\n        static MethodInfo[] s_LegacyIsOpenForEditMethods;\n\n        static void GetOpenForEditMethods(bool canOpenForEditVariant, out MethodInfo[] methods, out MethodInfo[] legacyMethods)\n        {\n            if (canOpenForEditVariant)\n            {\n                if (s_CanOpenForEditMethods == null)\n                    GetOpenForEditMethods(\"CanOpenForEdit\", out s_CanOpenForEditMethods, out s_LegacyCanOpenForEditMethods);\n                methods = s_CanOpenForEditMethods;\n                legacyMethods = s_LegacyCanOpenForEditMethods;\n            }\n            else\n            {\n                if (s_IsOpenForEditMethods == null)\n                    GetOpenForEditMethods(\"IsOpenForEdit\", out s_IsOpenForEditMethods, out s_LegacyIsOpenForEditMethods);\n                methods = s_IsOpenForEditMethods;\n                legacyMethods = s_LegacyIsOpenForEditMethods;\n            }\n        }\n\n        static void GetOpenForEditMethods(string name, out MethodInfo[] methods, out MethodInfo[] legacyMethods)\n        {\n            var methodList = new List<MethodInfo>();\n            var legacyMethodList = new List<MethodInfo>();\n\n            Type[] types = { typeof(string[]), typeof(List<string>), typeof(StatusQueryOptions) };\n            Type[] legacyTypes = { typeof(string), typeof(string).MakeByRefType() };\n\n            foreach (var type in AssetModificationProcessors)\n            {\n                // First look for a method with a signature that accepts multiple paths \"bool (string[] assetOrMetaFilePaths, List<string> outNotEditablePaths, StatusQueryOptions statusQueryOptions)\".\n                MethodInfo method;\n                try\n                {\n                    method = type.GetMethod(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, types, null);\n                }\n                catch (AmbiguousMatchException)\n                {\n                    Debug.LogWarning($\"Ambiguous {name} methods in {type.Name}.\");\n                    continue;\n                }\n                if (method?.ReturnType == typeof(bool))\n                {\n                    methodList.Add(method);\n                    continue;\n                }\n\n                // Then look for a legacy method that accepts single path only \"bool (string assetOrMetaFilePath, out string message)\".\n                MethodInfo legacyMethod;\n                try\n                {\n                    legacyMethod = type.GetMethod(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);\n                }\n                catch (AmbiguousMatchException)\n                {\n                    Debug.LogWarning($\"Ambiguous {name} methods in {type.Name}.\");\n                    continue;\n                }\n                if (legacyMethod != null && CheckArgumentTypesAndReturnType(legacyTypes, legacyMethod, typeof(bool)))\n                    legacyMethodList.Add(legacyMethod);\n            }\n\n            methods = methodList.ToArray();\n            legacyMethods = legacyMethodList.ToArray();\n        }\n\n        enum Editability\n        {\n            Never,\n            Always,\n            Maybe\n        }\n\n        static Editability GetPathEditability(string assetPath)\n        {\n            // read-only asset locations (e.g. shared packages) are considered not editable\n            bool rootFolder, readOnly;\n            bool validPath = AssetDatabase.TryGetAssetFolderInfo(assetPath, out rootFolder, out readOnly);\n            if (validPath && readOnly)\n                return Editability.Never;\n\n            // other paths that are not know to asset database, and not versioned, are considered always editable\n            if (!VersionControlUtils.IsPathVersioned(assetPath))\n                return Editability.Always;\n\n            return Editability.Maybe;\n        }\n\n        static bool GetOpenForEditViaScriptCallbacks(bool canOpenForEditVariant, string[] paths, List<string> notEditablePaths, out string message, StatusQueryOptions options)\n        {\n            message = string.Empty;\n            GetOpenForEditMethods(canOpenForEditVariant, out var methods, out var legacyMethods);\n\n            if (methods.Length != 0)\n            {\n                object[] args = { paths, notEditablePaths, options };\n                foreach (var method in methods)\n                {\n                    if (!(bool)method.Invoke(null, args))\n                        return false;\n                }\n            }\n\n            if (legacyMethods.Length != 0)\n            {\n                foreach (var legacyMethod in legacyMethods)\n                {\n                    var result = true;\n                    foreach (var path in paths)\n                    {\n                        object[] legacyArgs = { path, null };\n                        if (!(bool)legacyMethod.Invoke(null, legacyArgs))\n                        {\n                            result = false;\n                            notEditablePaths.Add(path);\n                            message = legacyArgs[1] as string;\n                        }\n                    }\n\n                    if (!result)\n                        return false;\n                }\n            }\n\n            return true;\n        }\n\n        internal static bool CanOpenForEdit(string assetPath, out string message, StatusQueryOptions statusOptions)\n        {\n            if (IsOpenForEdit(assetPath, out message, statusOptions))\n                return true;\n\n            // Status has just been updated so there's no need to force update again.\n            if (statusOptions == StatusQueryOptions.ForceUpdate)\n                statusOptions = StatusQueryOptions.UseCachedIfPossible;\n\n            return GetOpenForEdit(true, assetPath, out message, statusOptions);\n        }\n\n        internal static bool IsOpenForEdit(string assetPath, out string message, StatusQueryOptions statusOptions)\n        {\n            return GetOpenForEdit(false, assetPath, out message, statusOptions);\n        }\n\n        static bool GetOpenForEdit(bool canOpenForEditVariant, string assetPath, out string message, StatusQueryOptions statusOptions)\n        {\n            message = string.Empty;\n            if (string.IsNullOrEmpty(assetPath))\n                return true; // treat empty/null paths as editable (might be under Library folders etc.)\n\n            var editability = GetPathEditability(assetPath);\n            if (editability == Editability.Always)\n                return true;\n            if (editability == Editability.Never)\n                return false;\n\n            if (!AssetModificationHook.GetOpenForEdit(canOpenForEditVariant, assetPath, out message, statusOptions))\n                return false;\n\n            return GetOpenForEditViaScriptCallbacks(canOpenForEditVariant, new[] { assetPath }, new List<string>(), out message, statusOptions);\n        }\n\n        internal static bool CanOpenForEdit(string[] assetOrMetaFilePaths, List<string> outNotEditablePaths, StatusQueryOptions statusQueryOptions)\n        {\n            outNotEditablePaths.Clear();\n            if (assetOrMetaFilePaths == null || assetOrMetaFilePaths.Length == 0)\n                return true;\n\n            var queryList = GetQueryList(assetOrMetaFilePaths, outNotEditablePaths);\n            if (queryList.Count == 0)\n                return outNotEditablePaths.Count == 0;\n\n            // Get a list of paths that are not open for edit.\n            var notOpenForEditPaths = new List<string>();\n            AssetModificationHook.GetOpenForEdit(false, queryList, notOpenForEditPaths, statusQueryOptions);\n            GetOpenForEditViaScriptCallbacks(false, queryList.ToArray(), notOpenForEditPaths, out var message, statusQueryOptions);\n\n            if (notOpenForEditPaths.Count == 0)\n                return outNotEditablePaths.Count == 0;\n\n            // Status has just been updated so there's no need to force update again.\n            if (statusQueryOptions == StatusQueryOptions.ForceUpdate)\n                statusQueryOptions = StatusQueryOptions.UseCachedIfPossible;\n\n            // Check paths that are not open for edit.\n            if (!AssetModificationHook.GetOpenForEdit(true, notOpenForEditPaths, outNotEditablePaths, statusQueryOptions))\n                return false;\n\n            return GetOpenForEditViaScriptCallbacks(true, notOpenForEditPaths.ToArray(), outNotEditablePaths, out message, statusQueryOptions);\n        }\n\n        internal static bool IsOpenForEdit(string[] assetOrMetaFilePaths, List<string> outNotEditablePaths, StatusQueryOptions statusQueryOptions)\n        {\n            outNotEditablePaths.Clear();\n            if (assetOrMetaFilePaths == null || assetOrMetaFilePaths.Length == 0)\n                return true;\n\n            var queryList = GetQueryList(assetOrMetaFilePaths, outNotEditablePaths);\n            if (queryList.Count == 0)\n                return outNotEditablePaths.Count == 0;\n\n            // check with VCS\n            if (!AssetModificationHook.GetOpenForEdit(false, queryList, outNotEditablePaths, statusQueryOptions))\n                return false;\n\n            // check with possible script callbacks\n            return GetOpenForEditViaScriptCallbacks(false, queryList.ToArray(), outNotEditablePaths, out var message, statusQueryOptions);\n        }\n\n        static List<string> GetQueryList(string[] paths, List<string> outNotEditablePaths)\n        {\n            var result = new List<string>(paths.Length);\n            foreach (var path in paths)\n            {\n                if (string.IsNullOrEmpty(path))\n                    continue; // treat empty/null paths as editable (might be under Library folders etc.)\n                var editability = GetPathEditability(path);\n                if (editability == Editability.Always)\n                    continue;\n                if (editability == Editability.Never)\n                {\n                    outNotEditablePaths.Add(path);\n                    continue;\n                }\n                result.Add(path);\n            }\n            return result;\n        }\n\n        [RequiredByNativeCode]\n        internal static void OnStatusUpdated()\n        {\n            WindowPending.OnStatusUpdated();\n\n            foreach (var assetModificationProcessorClass in AssetModificationProcessors)\n            {\n                const string methodName = \"OnStatusUpdated\";\n                MethodInfo method = assetModificationProcessorClass.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);\n                if (method != null)\n                {\n                    object[] args = {};\n                    if (!CheckArgumentsAndReturnType(args, method, typeof(void)))\n                        continue;\n\n                    using (new EditorPerformanceMarker($\"{assetModificationProcessorClass.Name}.{methodName}\", assetModificationProcessorClass).Auto())\n                        method.Invoke(null, args);\n                }\n            }\n        }\n\n        static MethodInfo[] s_MakeEditableMethods;\n\n        static MethodInfo[] GetMakeEditableMethods()\n        {\n            if (s_MakeEditableMethods == null)\n            {\n                var methods = new List<MethodInfo>();\n                Type[] types = { typeof(string[]), typeof(string), typeof(List<string>) };\n                foreach (var type in AssetModificationProcessors)\n                {\n                    MethodInfo method;\n                    try\n                    {\n                        method = type.GetMethod(\"MakeEditable\", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);\n                    }\n                    catch (AmbiguousMatchException)\n                    {\n                        Debug.LogWarning($\"Ambiguous MakeEditable methods in {type.Name}.\");\n                        continue;\n                    }\n                    if (method != null && CheckArgumentTypesAndReturnType(types, method, typeof(bool)))\n                        methods.Add(method);\n                }\n                s_MakeEditableMethods = methods.ToArray();\n            }\n            return s_MakeEditableMethods;\n        }\n\n        internal static bool MakeEditable(string[] paths, string prompt, List<string> outNotEditablePaths)\n        {\n            var methods = GetMakeEditableMethods();\n            if (methods == null || methods.Length == 0)\n                return true;\n\n            object[] args = { paths, prompt ?? string.Empty, outNotEditablePaths ?? new List<string>() };\n            foreach (var method in methods)\n            {\n                if (!(bool)method.Invoke(null, args))\n                    return false;\n            }\n\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetMoveResult.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor\n{\n    [Flags]\n    public enum AssetMoveResult\n    {\n        // Tells the internal implementation that the asset was not moved physically on disk by the script\n        DidNotMove = 0,\n\n        // Tells the internal implementation that the script could not move the assets, and Unity should not attempt to move the asset\n        FailedMove = 1,\n\n        // Tells the internal implementation that the script moved the asset physically on disk. The internal implementation will\n        DidMove = 2\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/AssemblyDefinitionImporter.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    [ExcludeFromPreset]\n    public sealed partial class AssemblyDefinitionImporter : AssetImporter\n    {\n    }\n\n    public sealed partial class AssemblyDefinitionAsset : TextAsset\n    {\n        private AssemblyDefinitionAsset() {}\n\n        private AssemblyDefinitionAsset(string text) {}\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/AssemblyDefinitionReferenceImporter.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    [ExcludeFromPreset]\n    public sealed partial class AssemblyDefinitionReferenceImporter : AssetImporter\n    {\n    }\n\n    public sealed partial class AssemblyDefinitionReferenceAsset : TextAsset\n    {\n        private AssemblyDefinitionReferenceAsset() {}\n\n        private AssemblyDefinitionReferenceAsset(string text) {}\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/AssetImportContext.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEngine.Scripting.APIUpdating;\nusing Debug = UnityEngine.Debug;\nusing Object = UnityEngine.Object;\nusing UnityEditor.Experimental;\n\nnamespace UnityEditor.AssetImporters\n{\n    /// Universal structure that holds all the data relevant to importing an asset, including temporary data that needs to be shared across stages that make on any given importer's pipeline.\n    ///\n    /// Breaking up legacy importers into peaces and re-arranging them as pipelines that use those pieces so that the pieces can become building blocks that other importers can re-use implies that the pieces\n    /// is not coupled with any given importer. For this decoupling and maximizing reuse, we need something that can hold the information describing what is being imported but also the data generated by the\n    /// various parts that make up an importers pipeline. This container simply transports information from one \"stage\" to the other. Each stage is free to add/delete/alter the content of the container\n    [RequiredByNativeCode]\n    [NativeHeader(\"Editor/Src/AssetPipeline/AssetImportContext.h\")]\n    [MovedFrom(\"UnityEditor.Experimental.AssetImporters\")]\n    public class AssetImportContext\n    {\n        // The bindings generator is setting the instance pointer in this field\n        internal IntPtr m_Self;\n\n        // the context can only be instantiated in native code\n        AssetImportContext() {}\n\n        public extern string assetPath { get; internal set; }\n\n        [Obsolete(\"GetResultPath has been deprecated. Use GetOutputArtifactFilePath(string) instead (UnityUpgradable) -> GetOutputArtifactFilePath(*)\")]\n        [NativeName(\"GetOutputArtifactFilePath\")]\n        public extern string GetResultPath(string extension);\n\n        public extern BuildTarget selectedBuildTarget { get; }\n\n        [NativeThrows]\n        public extern void SetMainObject(Object obj);\n        public extern Object mainObject { get; }\n\n        public void AddObjectToAsset(string identifier, Object obj)\n        {\n            AddObjectToAsset(identifier, obj, null);\n        }\n\n        [FreeFunction(\"AssetImportContextBindings::GetObjects\", HasExplicitThis = true)]\n        public extern void GetObjects([NotNull] List<Object> objects);\n\n        [NativeThrows]\n        public extern void AddObjectToAsset(string identifier, Object obj, Texture2D thumbnail);\n\n        // Create a dependency against the contents of the source asset at the provided path\n        // * if the asset at the path changes, it will trigger an import\n        // * if the asset at the path moves, it will trigger an import\n        public void DependsOnSourceAsset(string path)\n        {\n            if (string.IsNullOrEmpty(path))\n            {\n                throw new ArgumentNullException(\"path\", \"Cannot add dependency on invalid path.\");\n            }\n\n            DependsOnSourceAssetInternal(path);\n        }\n\n        [NativeName(\"DependsOnSourceAsset\")]\n        private extern void DependsOnSourceAssetInternal(string path);\n\n        public void DependsOnSourceAsset(GUID guid)\n        {\n            if (guid.Empty())\n            {\n                throw new ArgumentNullException(\"guid\", \"Cannot add dependency on empty GUID.\");\n            }\n\n            DependsOnSourceAssetInternalGUID(guid);\n        }\n\n        [NativeName(\"DependsOnSourceAsset\")]\n        private extern void DependsOnSourceAssetInternalGUID(GUID guid);\n\n        [NativeName(\"GetFolderEntries\")]\n        internal extern GUID[] GetFolderEntries(GUID folder);\n\n        internal void DependsOnImportedAsset(string path)\n        {\n            if (string.IsNullOrEmpty(path))\n            {\n                throw new ArgumentNullException(\"path\", \"Cannot add dependency on invalid path.\");\n            }\n\n            DependsOnImportedAssetInternal(path);\n        }\n\n        [NativeName(\"GetArtifactFilePath\")]\n        private extern string GetArtifactFilePath_Internal(string path, string fileName);\n\n        public string GetArtifactFilePath(string path, string fileName)\n        {\n            return GetArtifactFilePath_Internal(path, fileName);\n        }\n\n        public string GetArtifactFilePath(GUID guid, string fileName)\n        {\n            return GetArtifactFilePath(new ArtifactKey(guid), fileName);\n        }\n\n        public extern string GetArtifactFilePath(ArtifactKey key, string fileName);\n\n        public extern string GetOutputArtifactFilePath(string fileName);\n\n        [NativeName(\"DependsOnImportedAsset\")]\n        private extern void DependsOnImportedAssetInternal(string path);\n\n        public extern Object GetReferenceToAssetMainObject(string path);\n\n        public void DependsOnArtifact(ArtifactKey key)\n        {\n            if (!key.isValid)\n            {\n                throw new ArgumentNullException(\"key\", \"Cannot add dependency on invalid ArtifactKey.\");\n            }\n\n            DependsOnArtifactInternal(key);\n        }\n\n        [NativeName(\"DependsOnArtifact\")]\n        private extern void DependsOnArtifactInternal(ArtifactKey key);\n\n        public void DependsOnArtifact(GUID guid)\n        {\n            if (guid.Empty())\n            {\n                throw new ArgumentNullException(\"guid\", \"Cannot add dependency on empty GUID.\");\n            }\n\n            DependsOnArtifactInternalGUID(guid);\n        }\n\n        [NativeName(\"DependsOnArtifact\")]\n        private extern void DependsOnArtifactInternalGUID(GUID guid);\n\n        public void DependsOnArtifact(string path)\n        {\n            if (string.IsNullOrEmpty(path))\n            {\n                throw new ArgumentNullException(\"path\", \"Cannot add dependency on invalid path.\");\n            }\n\n            DependsOnArtifactInternalPath(path);\n        }\n\n        [NativeName(\"DependsOnArtifact\")]\n        private extern void DependsOnArtifactInternalPath(string path);\n\n        public void DependsOnCustomDependency(string dependency)\n        {\n            if (string.IsNullOrEmpty(dependency))\n            {\n                throw new ArgumentNullException(\"dependency\", \"Cannot add custom dependency on an empty custom dependency.\");\n            }\n\n            if (string.CompareOrdinal(dependency,\"srp/default-shader\") == 0 && assetPath.EndsWith(\".shader\", StringComparison.OrdinalIgnoreCase))\n            {\n                throw new Exception($\"A shader '{assetPath}' cannot depend on the 'srp/default-shader' custom dependency because this operation is unsupported.\");\n            }\n\n            DependsOnCustomDependencyInternal(dependency);\n        }\n\n        [NativeName(\"DependsOnCustomDependency\")]\n        private extern void DependsOnCustomDependencyInternal(string path);\n\n        extern void AddImportLog(string msg, string file, int line, ImportLogFlags flags, UnityEngine.Object obj);\n\n        void AddImportLog(string msg, ImportLogFlags flags, UnityEngine.Object obj)\n        {\n            var st = new StackTrace(2, true);\n            var sf = st.GetFrame(0);\n            AddImportLog(msg, sf.GetFileName(), sf.GetFileLineNumber(), flags, obj);\n        }\n\n        public void LogImportError(string msg, UnityEngine.Object obj = null)\n        {\n            AddImportLog(msg, ImportLogFlags.Error, obj);\n        }\n\n        internal void LogImportError(string msg, string file, int line, UnityEngine.Object obj = null)\n        {\n            AddImportLog(msg, file, line, ImportLogFlags.Error, obj);\n        }\n\n        public void LogImportWarning(string msg, UnityEngine.Object obj = null)\n        {\n            AddImportLog(msg, ImportLogFlags.Warning, obj);\n        }\n\n        internal void LogImportWarning(string msg, string file, int line, UnityEngine.Object obj = null)\n        {\n            AddImportLog(msg, file, line, ImportLogFlags.Warning, obj);\n        }\n\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(AssetImportContext ctx) => ctx.m_Self;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/AssetImporter.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEditor.AssetImporters;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/AssetPipeline/AssetImporter.h\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/AssetImporter.bindings.h\")]\n    [ExcludeFromObjectFactory]\n    [Preserve]\n    [UsedByNativeCode]\n    public partial class AssetImporter : Object\n    {\n        [NativeType(CodegenOptions.Custom, \"MonoSourceAssetIdentifier\")]\n        public struct SourceAssetIdentifier\n        {\n            public SourceAssetIdentifier(Object asset)\n            {\n                if (asset == null)\n                {\n                    throw new ArgumentNullException(\"asset\");\n                }\n\n                this.type = asset.GetType();\n                this.name = asset.name;\n            }\n\n            public SourceAssetIdentifier(Type type, string name)\n            {\n                if (type == null)\n                {\n                    throw new ArgumentNullException(\"type\");\n                }\n\n                if (name == null)\n                {\n                    throw new ArgumentNullException(\"name\");\n                }\n\n                if (string.IsNullOrEmpty(name))\n                {\n                    throw new ArgumentException(\"The name is empty\", \"name\");\n                }\n\n                this.type = type;\n                this.name = name;\n            }\n\n            public Type type;\n            public string name;\n        }\n\n        [NativeName(\"AssetPathName\")]\n        public extern  string assetPath\n        {\n            get;\n        }\n\n        public extern  bool importSettingsMissing\n        {\n            get;\n        }\n\n        public extern  ulong assetTimeStamp\n        {\n            get;\n        }\n\n        public extern  string userData\n        {\n            get;\n            set;\n        }\n\n        public extern  string assetBundleName\n        {\n            get;\n            set;\n        }\n\n        public extern  string assetBundleVariant\n        {\n            get;\n            set;\n        }\n\n        public static ImportLog GetImportLog(string path)\n        {\n            return GetImportLog(AssetDatabase.GUIDFromAssetPath(path));\n        }\n\n        [FreeFunction(\"AssetImporter::GetImportLog\")]\n        internal static extern ImportLog GetImportLog(GUID guid);\n\n        [FreeFunction(\"AssetImporter::GetImportLogEntriesCount\")]\n        internal static extern bool GetImportLogEntriesCount(GUID guid, out int nbErrors, out int nbWarnings);\n\n        [NativeName(\"SetAssetBundleName\")]\n        extern public void SetAssetBundleNameAndVariant(string assetBundleName, string assetBundleVariant);\n\n        [NativeMethod(\"SetThumbnailFromTexture2D\")]\n        extern internal void SetThumbnailFromTexture2D(Texture2D image, int instanceID);\n\n        [FreeFunction(\"FindAssetImporterAtAssetPath\")]\n        extern public static  AssetImporter GetAtPath(string path);\n\n        public void SaveAndReimport()\n        {\n            AssetDatabase.ImportAsset(assetPath);\n        }\n\n        [FreeFunction(\"AssetImporterBindings::LocalFileIDToClassID\")]\n        extern internal static  int LocalFileIDToClassID(long fileId);\n\n        [FreeFunction(\"AssetImporterBindings::MakeLocalFileIDWithHash\")]\n        extern internal static long MakeLocalFileIDWithHash(int persistentTypeId, string name, long offset);\n        extern internal long MakeInternalID(int persistentTypeId, string name);\n\n        extern public void AddRemap(SourceAssetIdentifier identifier, Object externalObject);\n\n        extern public bool RemoveRemap(SourceAssetIdentifier identifier);\n\n        extern internal void RenameSubAssets(int peristentTypeId, string[] oldNames, string[] newNames);\n\n        [FreeFunction(\"AssetImporterBindings::GetIdentifiers\")]\n        extern private static SourceAssetIdentifier[] GetIdentifiers(AssetImporter self);\n        [FreeFunction(\"AssetImporterBindings::GetExternalObjects\")]\n        extern private static Object[] GetExternalObjects(AssetImporter self);\n\n        public Dictionary<SourceAssetIdentifier, Object> GetExternalObjectMap()\n        {\n            // bogdanc: this is not optimal - we should have only one call to get both the identifiers and the external objects.\n            // However, the new bindings do not support well output array parameters.\n            // FIXME: change this to a single call when the bindings are fixed\n            SourceAssetIdentifier[] identifiers = GetIdentifiers(this);\n            Object[] externalObjects = GetExternalObjects(this);\n\n            Dictionary<SourceAssetIdentifier, Object> map = new Dictionary<SourceAssetIdentifier, Object>();\n\n            for (int i = 0; i < identifiers.Length; ++i)\n            {\n                map.Add(identifiers[i], externalObjects[i]);\n            }\n\n            return map;\n        }\n\n        [FreeFunction(\"AssetImporterBindings::RegisterImporter\", ThrowsException = true)]\n        extern internal static  void RegisterImporter(Type importer, int importerVersion, int queuePos, string fileExt, bool supportsImportDependencyHinting, bool autoSelect, bool allowCaching);\n\n        [FreeFunction(\"AssetImporterBindings::SupportsRemappedAssetType\", HasExplicitThis = true, IsThreadSafe = true)]\n        public extern bool SupportsRemappedAssetType(Type type);\n\n        internal extern double GetImportStartTime();\n\n        internal AssetPostprocessor.PostprocessorInfo[] GetDynamicPostprocessors()\n        {\n            return AssetPostprocessingInternal.GetSortedDynamicPostprocessorsForAsset(assetPath).ToArray();\n        }\n\n        internal static AssetPostprocessor.PostprocessorInfo[] GetStaticPostprocessors(Type importerType)\n        {\n            return AssetPostprocessingInternal.GetSortedStaticPostprocessorTypes(importerType).ToArray();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/BumpMapSettings.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [StaticAccessor(\"BumpMapSettings::Get()\", StaticAccessorType.Dot)]\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/BumpMapSettings.h\")]\n    internal class BumpMapSettings\n    {\n        public static extern bool silentMode { get; set; }\n\n        public static extern void PerformBumpMapCheck([NotNull] Material material);\n    }\n\n    public static class MaterialEditorExtensions\n    {\n        public static void PerformBumpMapCheck(this Material material)\n        {\n            BumpMapSettings.PerformBumpMapCheck(material);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/CameraDescription.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.AssetImporters\n{\n    [RequiredByNativeCode]\n    [NativeHeader(\"Editor/Src/AssetPipeline/ModelImporting/CameraDescription.h\")]\n    public class CameraDescription : IDisposable\n    {\n        internal IntPtr m_Ptr;\n\n        public CameraDescription()\n        {\n            m_Ptr = Internal_Create();\n        }\n\n        ~CameraDescription()\n        {\n            Destroy();\n        }\n\n        public void Dispose()\n        {\n            Destroy();\n            GC.SuppressFinalize(this);\n        }\n\n        void Destroy()\n        {\n            if (m_Ptr != IntPtr.Zero)\n            {\n                Internal_Destroy(m_Ptr);\n                m_Ptr = IntPtr.Zero;\n            }\n        }\n\n        public bool TryGetProperty(string propertyName, out float value) => TryGetFloatProperty(propertyName, out value);\n        public bool TryGetProperty(string propertyName, out Vector4 value) => TryGetVector4Property(propertyName, out value);\n        public bool TryGetProperty(string propertyName, out string value) => TryGetStringProperty(propertyName, out value);\n        public bool TryGetProperty(string propertyName, out int value) => TryGetIntProperty(propertyName, out value);\n\n        public extern void GetVector4PropertyNames(List<string> names);\n        public extern void GetFloatPropertyNames(List<string> names);\n        public extern void GetStringPropertyNames(List<string> names);\n        public extern void GetIntPropertyNames(List<string> names);\n\n        extern bool TryGetVector4Property(string propertyName, out Vector4 value);\n        extern bool TryGetFloatProperty(string propertyName, out float value);\n        extern bool TryGetStringProperty(string propertyName, out string value);\n        extern bool TryGetIntProperty(string propertyName, out int value);\n\n        public bool TryGetAnimationCurve(string clipName, string propertyName, out AnimationCurve value)\n        {\n            value = TryGetAnimationCurve(clipName, propertyName);\n            return value != null;\n        }\n\n        public extern bool HasAnimationCurveInClip(string clipName, string propertyName);\n        public extern bool HasAnimationCurve(string propertyName);\n        extern AnimationCurve TryGetAnimationCurve(string clipName, string propertyName);\n\n        static extern IntPtr Internal_Create();\n        static extern void Internal_Destroy(IntPtr ptr);\n\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(CameraDescription desc) => desc.m_Ptr;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/ComputeShaderImporter.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/AssetPipeline/ComputeShaderImporter.h\")]\n    public sealed partial class ComputeShaderImporter : AssetImporter\n    {\n        public PreprocessorOverride preprocessorOverride { get { return PreprocessorOverride.UseProjectSettings; } set {} }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/IHVImageFormatImporter.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n    [Obsolete(\"DDSImporter is obsolete. Use IHVImageFormatImporter instead (UnityUpgradable) -> IHVImageFormatImporter\", true)]\n    [NativeClass(null)]\n    public sealed class DDSImporter : AssetImporter\n    {\n        public bool isReadable { get {return false; } set {} }\n    }\n\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/IHVImageFormatImporter.h\")]\n    public sealed class IHVImageFormatImporter : AssetImporter\n    {\n        public extern bool isReadable\n        {\n            get;\n            set;\n        }\n\n        public extern FilterMode filterMode\n        {\n            get;\n            set;\n        }\n\n        // note: wrapMode getter returns U wrapping axis\n        public extern TextureWrapMode wrapMode\n        {\n            [NativeName(\"GetWrapU\")]\n            get;\n            [NativeName(\"SetWrapUVW\")]\n            set;\n        }\n\n        [NativeName(\"WrapU\")]\n        public extern TextureWrapMode wrapModeU\n        {\n            get;\n            set;\n        }\n\n        [NativeName(\"WrapV\")]\n        public extern TextureWrapMode wrapModeV\n        {\n            get;\n            set;\n        }\n\n        [NativeName(\"WrapW\")]\n        public extern TextureWrapMode wrapModeW\n        {\n            get;\n            set;\n        }\n\n        [NativeConditional(\"ENABLE_TEXTURE_STREAMING\")]\n        public extern bool streamingMipmaps\n        {\n            get;\n            set;\n        }\n\n        [NativeConditional(\"ENABLE_TEXTURE_STREAMING\")]\n        public extern int streamingMipmapsPriority\n        {\n            get;\n            set;\n        }\n\n        public extern bool ignoreMipmapLimit\n        {\n            get;\n            set;\n        }\n\n        public extern string mipmapLimitGroupName\n        {\n            get;\n            set;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/ImportLog.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor.AssetImporters\n{\n    // Subset of C++ LogMessageFlags in LogAssert.h\n    [Flags]\n    public enum ImportLogFlags\n    {\n        None = 0, // kNoLogMessageFlags\n        Error = 1 << 6, // kAssetImportError\n        Warning = 1 << 7 // kAssetImportWarning\n    };\n\n    [NativeHeader(\"Editor/Src/AssetPipeline/ImportLog.h\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/ImportLog.bindings.h\")]\n    [ExcludeFromObjectFactory]\n    public sealed class ImportLog : Object\n    {\n        internal struct Filters\n        {\n            public const string SearchToken = \"i\";\n            public const string AllIssuesStr = \"all\";\n            public const string ErrorsStr = \"errors\";\n            public const string WarningsStr = \"warnings\";\n        }\n\n        [NativeType(CodegenOptions.Custom, \"MonoImportLogEntry\")]\n        public struct ImportLogEntry\n        {\n            public string message;\n            public ImportLogFlags flags;\n            public int line;\n            public string file;\n\n            public UnityEngine.Object context\n            {\n                get => Object.FindObjectFromInstanceID(instanceID);\n                set => instanceID = value.GetInstanceID();\n            }\n\n            internal int instanceID;\n        };\n\n        public extern ImportLogEntry[] logEntries\n        {\n            [NativeMethod(\"GetLogEntries\")]\n            get;\n        }\n\n        [NativeMethod(\"PrintToConsole\")]\n        internal extern void PrintToConsole();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/LightDescription.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.AssetImporters\n{\n    [RequiredByNativeCode]\n    [NativeHeader(\"Editor/Src/AssetPipeline/ModelImporting/LightDescription.h\")]\n    public class LightDescription : IDisposable\n    {\n        internal IntPtr m_Ptr;\n\n        public LightDescription()\n        {\n            m_Ptr = Internal_Create();\n        }\n\n        ~LightDescription()\n        {\n            Destroy();\n        }\n\n        public void Dispose()\n        {\n            Destroy();\n            GC.SuppressFinalize(this);\n        }\n\n        void Destroy()\n        {\n            if (m_Ptr != IntPtr.Zero)\n            {\n                Internal_Destroy(m_Ptr);\n                m_Ptr = IntPtr.Zero;\n            }\n        }\n\n        public bool TryGetProperty(string propertyName, out float value) => TryGetFloatProperty(propertyName, out value);\n        public bool TryGetProperty(string propertyName, out Vector4 value) => TryGetVector4Property(propertyName, out value);\n        public bool TryGetProperty(string propertyName, out string value) => TryGetStringProperty(propertyName, out value);\n        public bool TryGetProperty(string propertyName, out int value) => TryGetIntProperty(propertyName, out value);\n\n        public extern void GetVector4PropertyNames(List<string> names);\n        public extern void GetFloatPropertyNames(List<string> names);\n        public extern void GetStringPropertyNames(List<string> names);\n        public extern void GetIntPropertyNames(List<string> names);\n\n        extern bool TryGetVector4Property(string propertyName, out Vector4 value);\n        extern bool TryGetFloatProperty(string propertyName, out float value);\n        extern bool TryGetStringProperty(string propertyName, out string value);\n        extern bool TryGetIntProperty(string propertyName, out int value);\n\n        public bool TryGetAnimationCurve(string clipName, string propertyName, out AnimationCurve value)\n        {\n            value = TryGetAnimationCurve(clipName, propertyName);\n            return value != null;\n        }\n\n        public extern bool HasAnimationCurveInClip(string clipName, string propertyName);\n        public extern bool HasAnimationCurve(string propertyName);\n        extern AnimationCurve TryGetAnimationCurve(string clipName, string propertyName);\n\n        static extern IntPtr Internal_Create();\n        static extern void Internal_Destroy(IntPtr ptr);\n\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(LightDescription desc) => desc.m_Ptr;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/LocalCacheServer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.IO;\nusing UnityEditor.Utils;\n\nnamespace UnityEditor\n{\n    internal class LocalCacheServer\n    {\n        public const string PathKey = \"LocalCacheServerPath\";\n        public const string CustomPathKey = \"LocalCacheServerCustomPath\";\n\n        public static string GetCacheLocation()\n        {\n            var cachePath = EditorPrefs.GetString(PathKey);\n            var enableCustomPath = EditorPrefs.GetBool(CustomPathKey);\n            var result = cachePath;\n            if (!enableCustomPath || string.IsNullOrEmpty(cachePath))\n                result = Paths.Combine(OSUtil.GetDefaultCachePath(), \"CacheServer\");\n            return result;\n        }\n\n        public static void Setup()\n        {\n            var mode = (AssetPipelinePreferences.CacheServerMode)EditorPrefs.GetInt(\"CacheServerMode\");\n\n            if (mode == AssetPipelinePreferences.CacheServerMode.Local)\n            {\n                EditorGUILayout.HelpBox(\"Local CacheServer is no longer supported\", MessageType.Info, true);\n            }\n        }\n\n        public static void Clear()\n        {\n            string cacheDirectoryPath = GetCacheLocation();\n            if (Directory.Exists(cacheDirectoryPath))\n                Directory.Delete(cacheDirectoryPath, true);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/MaterialDescription.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.AssetImporters\n{\n    [NativeType(Header = \"Editor/Src/AssetPipeline/ModelImporting/MaterialDescription.h\")]\n    public struct TexturePropertyDescription\n    {\n        public Vector2 offset;\n        public Vector2 scale;\n        public Texture texture;\n        public string relativePath;\n        public string path;\n    }\n\n    [RequiredByNativeCode]\n    [NativeHeader(\"Editor/Src/AssetPipeline/ModelImporting/MaterialDescription.h\")]\n    public class MaterialDescription : IDisposable\n    {\n        internal IntPtr m_Ptr;\n\n        public MaterialDescription()\n        {\n            m_Ptr = Internal_Create();\n        }\n\n        ~MaterialDescription()\n        {\n            Destroy();\n        }\n\n        public void Dispose()\n        {\n            Destroy();\n            GC.SuppressFinalize(this);\n        }\n\n        void Destroy()\n        {\n            if (m_Ptr != IntPtr.Zero)\n            {\n                Internal_Destroy(m_Ptr);\n                m_Ptr = IntPtr.Zero;\n            }\n        }\n\n        [NativeProperty(\"materialName\", TargetType.Field)]\n        public extern string materialName { get; }\n\n        public bool TryGetProperty(string propertyName, out float value) => TryGetFloatProperty(propertyName, out value);\n        public bool TryGetProperty(string propertyName, out Vector4 value) => TryGetVector4Property(propertyName, out value);\n        public bool TryGetProperty(string propertyName, out string value) => TryGetStringProperty(propertyName, out value);\n        public bool TryGetProperty(string propertyName, out TexturePropertyDescription value) => TryGetTextureProperty(propertyName, out value);\n\n        public extern void GetVector4PropertyNames(List<string> names);\n        public extern void GetFloatPropertyNames(List<string> names);\n        public extern void GetTexturePropertyNames(List<string> names);\n        public extern void GetStringPropertyNames(List<string> names);\n\n        extern bool TryGetVector4Property(string propertyName, out Vector4 value);\n        extern bool TryGetFloatProperty(string propertyName, out float value);\n        extern bool TryGetTextureProperty(string propertyName, out TexturePropertyDescription value);\n        extern bool TryGetStringProperty(string propertyName, out string value);\n\n        public bool TryGetAnimationCurve(string clipName, string propertyName, out AnimationCurve value)\n        {\n            value = TryGetAnimationCurve(clipName, propertyName);\n            return value != null;\n        }\n\n        public extern bool HasAnimationCurveInClip(string clipName, string propertyName);\n        public extern bool HasAnimationCurve(string propertyName);\n        extern AnimationCurve TryGetAnimationCurve(string clipName, string propertyName);\n\n        static extern IntPtr Internal_Create();\n        static extern void Internal_Destroy(IntPtr ptr);\n\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(MaterialDescription desc) => desc.m_Ptr;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/ShaderImporter.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/AssetPipeline/ShaderImporter.h\")]\n    public sealed partial class ShaderImporter : AssetImporter\n    {\n        public extern Shader GetShader();\n\n        public extern void SetDefaultTextures(string[] name, Texture[] textures);\n\n        public extern Texture GetDefaultTexture(string name);\n\n        public extern void SetNonModifiableTextures(string[] name, Texture[] textures);\n\n        public extern Texture GetNonModifiableTexture(string name);\n\n        public PreprocessorOverride preprocessorOverride { get { return PreprocessorOverride.UseProjectSettings; } set {} }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/ShaderIncludeImporter.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/AssetPipeline/ShaderIncludeImporter.h\")]\n    internal sealed partial class ShaderIncludeImporter : AssetImporter\n    {\n    }\n\n    [NativeHeader(\"Editor/Src/Shaders/ShaderInclude.h\")]\n    public sealed partial class ShaderInclude : TextAsset\n    {\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/SpeedTree/SpeedTree9Importer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nusing UnityEditor.AssetImporters;\n\nusing STVertex = UnityEditor.SpeedTree.Importer.Vertex;\nusing Material = UnityEngine.Material;\nusing Color = UnityEngine.Color;\n\nusing static UnityEditor.SpeedTree.Importer.SpeedTreeImporterCommon;\nusing static UnityEditor.SpeedTree.Importer.WindConfigSDK;\nusing static UnityEditor.SpeedTree.Importer.SpeedTree9Importer;\nusing static UnityEditor.SpeedTree.Importer.SpeedTree9Reader;\n\nnamespace UnityEditor.SpeedTree.Importer\n{\n    // [2024-09-27] version: 3\n    // Fixed code that would lead to m_LODCount vs m_PerLODSettings.arraySize mismatching in GUI \n    [ScriptedImporter(version: 3, ext: \"st9\", AllowCaching = true)]\n    public class SpeedTree9Importer : ScriptedImporter\n    {\n        const int SPEEDTREE_9_WIND_VERSION = 1;\n        const int SPEEDTREE_9_MATERIAL_VERSION = 1;\n\n        internal static class ImporterSettings\n        {\n            internal const string kGameObjectName = \"SpeedTree\";\n            internal const string kLegacyShaderName = \"Nature/SpeedTree9\";\n            internal const string kWindAssetName = \"SpeedTreeWind\";\n            internal const string kSRPDependencyName = \"SpeedTree9Importer_DefaultShader\";\n            internal const string kMaterialSettingsDependencyname = \"SpeedTree9Importer_MaterialSettings\";\n            internal const string kIconName = \"UnityEditor/SpeedTree9Importer Icon\";\n        }\n\n        private static class Styles\n        {\n            internal static readonly Texture2D kIcon = EditorGUIUtility.FindTexture(ImporterSettings.kIconName);\n        }\n\n        private struct STMeshGeometry\n        {\n            public Vector3[] vertices;\n            public Vector3[] normals;\n            public Vector4[] tangents;\n            public Color32[] colors32;\n            public Vector4[][] uvs;\n            public int lodIndex;\n\n            public STMeshGeometry(int vertexCount, int UVCount, int indexLod)\n            {\n                vertices = new Vector3[vertexCount];\n                normals = new Vector3[vertexCount];\n                tangents = new Vector4[vertexCount];\n                colors32 = new Color32[vertexCount];\n                uvs = new Vector4[UVCount][];\n                lodIndex = indexLod;\n\n                for (int i = 0; i < UVCount; ++i)\n                {\n                    uvs[i] = new Vector4[vertexCount];\n                }\n            }\n        }\n\n        [SerializeField]\n        internal MeshSettings m_MeshSettings = new MeshSettings();\n\n        [SerializeField]\n        internal MaterialSettings m_MaterialSettings = new MaterialSettings();\n\n        [SerializeField]\n        internal LightingSettings m_LightingSettings = new LightingSettings();\n\n        [SerializeField]\n        internal AdditionalSettings m_AdditionalSettings = new AdditionalSettings();\n\n        [SerializeField]\n        internal LODSettings m_LODSettings = new LODSettings();\n\n        [SerializeField]\n        internal List<PerLODSettings> m_PerLODSettings = new List<PerLODSettings>();\n\n        [SerializeField]\n        internal WindSettings m_WindSettings = new WindSettings();\n\n        [SerializeField]\n        internal int m_MaterialVersion = SPEEDTREE_9_MATERIAL_VERSION;\n\n        /// <summary>\n        /// Necessary to set default HDRP properties and materials upgrade.\n        /// </summary>\n        /// <param name=\"mainObject\">The main object used by the importer, containing the data.</param>\n        public delegate void OnAssetPostProcess(GameObject mainObject);\n\n        /// <summary>\n        /// Exposes the Diffuse Profile property in the importer inspector with compatible render pipelines.\n        /// </summary>\n        /// <param name=\"diffusionProfileAsset\">The serialized property of the diffusion profile asset.</param>\n        /// <param name=\"diffusionProfileHash\">The serialized property of the diffusion profile hash.</param>\n        /// <remarks>\n        /// Necessary to expose the Diffuse Profile property in the inspector, since the importer is not\n        /// aware of HDRP as it's a package. This property is highly used by artists, so exposing it is a big win.\n        /// </remarks>\n        public delegate void OnCustomEditorSettings(ref SerializedProperty diffusionProfileAsset, ref SerializedProperty diffusionProfileHash);\n\n        [SerializeField]\n        internal SpeedTreeImporterOutputData m_OutputImporterData;\n\n        private static ulong s_DefaultShaderHash;\n        private static readonly TimeSpan k_CheckDependencyFrequency = TimeSpan.FromSeconds(5);\n        private static DateTime s_LastCheck;\n\n        // Cache main objects, created during import process.\n        private AssetImportContext m_Context;\n        private SpeedTree9Reader m_Tree;\n        private Shader m_Shader;\n        private SpeedTreeWindAsset m_WindAsset;\n\n        // Values cached at the begining of the import process.\n        private bool m_HasFacingData;\n        private bool m_HasBranch2Data;\n        private bool m_LastLodIsBillboard;\n        private bool m_WindEnabled;\n        private uint m_LODCount;\n        private uint m_CollisionObjectsCount;\n        private string m_PathFromDirectory;\n\n        internal bool MaterialsShouldBeRegenerated => m_MaterialVersion != SPEEDTREE_9_MATERIAL_VERSION;\n\n        public override bool SupportsRemappedAssetType(Type type)\n        {\n            return true;\n        }\n\n        public override void OnImportAsset(AssetImportContext ctx)\n        {\n            m_Context = ctx;\n            m_Tree = new SpeedTree9Reader();\n\n            FileStatus status = m_Tree.Initialize(ctx.assetPath);\n            if (status != FileStatus.Valid)\n            {\n                ctx.LogImportError($\"Error while initializing the SpeedTree9 reader: {status}.\");\n                return;\n            }\n\n            m_Tree.ReadContent();\n\n            CacheTreeImporterValues(ctx.assetPath);\n\n            ctx.DependsOnCustomDependency(ImporterSettings.kSRPDependencyName);\n\n            if (!TryGetShaderForCurrentRenderPipeline(out m_Shader))\n            {\n                ctx.LogImportError(\"SpeedTree9 shader is invalid, cannot create Materials for this SpeedTree asset.\");\n                return;\n            }\n\n            m_OutputImporterData = SpeedTreeImporterOutputData.Create();\n            m_OutputImporterData.hasBillboard = m_LastLodIsBillboard;\n\n            CalculateScaleFactorFromUnit();\n\n            if (m_WindEnabled)\n            {\n                m_OutputImporterData.m_WindConfig = CopySpeedTree9WindConfig(m_Tree.Wind, m_MeshSettings.scaleFactor, m_Tree.Bounds);\n                SetWindParameters(ref m_OutputImporterData.m_WindConfig);\n\n                m_WindAsset = new SpeedTreeWindAsset(SPEEDTREE_9_WIND_VERSION, m_OutputImporterData.m_WindConfig)\n                {\n                    name = ImporterSettings.kWindAssetName,\n                };\n            }\n\n            GameObject mainObject = new GameObject(ImporterSettings.kGameObjectName);\n\n            if (m_AdditionalSettings.generateRigidbody)\n            {\n                CreateAndAddRigidBodyToAsset(mainObject);\n            }\n\n            ctx.AddObjectToAsset(ImporterSettings.kGameObjectName, mainObject);\n            ctx.SetMainObject(mainObject);\n\n            SetThumbnailFromTexture2D(Styles.kIcon, mainObject.GetInstanceID());\n\n            m_OutputImporterData.mainObject = mainObject;\n\n            CalculateBillboardAndPerLODSettings();\n\n            CreateMeshAndMaterials();\n\n            CreateAssetIdentifiersAndAddMaterialsToContext();\n\n            if (m_AdditionalSettings.generateColliders && m_CollisionObjectsCount > 0)\n            {\n                CreateAndAddCollidersToAsset();\n            }\n\n            if (m_WindEnabled)\n            {\n                ctx.AddObjectToAsset(ImporterSettings.kWindAssetName, m_WindAsset);\n            }\n\n            ctx.AddObjectToAsset(m_OutputImporterData.name, m_OutputImporterData);\n            ctx.DependsOnCustomDependency(ImporterSettings.kMaterialSettingsDependencyname);\n\n            AddDependencyOnExtractedMaterials();\n\n            TriggerAllCallbacks();\n        }\n\n        private void TriggerAllCallbacks()\n        {\n            var allMethods = AttributeHelper.GetMethodsWithAttribute<MaterialSettingsCallbackAttribute>().methodsWithAttributes;\n            foreach (var method in allMethods)\n            {\n                var callback = Delegate.CreateDelegate(typeof(OnAssetPostProcess), method.info) as OnAssetPostProcess;\n                callback?.Invoke(m_OutputImporterData.mainObject);\n            }\n        }\n\n        private void CacheTreeImporterValues(string assetPath)\n        {\n            // Variables used a lot are cached, since accessing any Reader array has a non-negligeable cost. \n            m_LODCount = (uint)m_Tree.Lod.Length;\n            if(m_LODCount > LODGroupGUI.kLODColors.Length)\n            {\n                Debug.LogWarningFormat(\"Number of LOD meshes in asset ({0}) is larger than the maximum number supported by Unity GUI ({1}).\" +\n                    \"\\nImporting only the first {1} LOD meshes.\"\n                    , m_LODCount, LODGroupGUI.kLODColors.Length);\n\n                // LODGroup GUI won't draw if we're above this limit, so we prevent future assertions here.\n                m_LODCount = (uint)LODGroupGUI.kLODColors.Length;\n            }\n\n            m_HasFacingData = TreeHasFacingData();\n            m_HasBranch2Data = m_Tree.Wind.DoBranch2;\n            m_LastLodIsBillboard = m_Tree.BillboardInfo.LastLodIsBillboard;\n            m_CollisionObjectsCount = (uint)m_Tree.CollisionObjects.Length;\n\n            WindConfigSDK windCfg = m_Tree.Wind;\n            m_WindEnabled = (windCfg.DoShared || windCfg.DoBranch1 || windCfg.DoBranch2 || windCfg.DoRipple)\n                && m_WindSettings.enableWind;\n\n            m_PathFromDirectory = Path.GetDirectoryName(assetPath) + \"/\";\n        }\n\n        internal void RegenerateMaterials()\n        {\n            m_OutputImporterData = AssetDatabase.LoadAssetAtPath<SpeedTreeImporterOutputData>(assetPath);\n\n            if (m_OutputImporterData.hasEmbeddedMaterials)\n            {\n                // TODO: Verify if we could only generate the embedded materials\n                // instead of reimporting entirely the asset.\n                SaveAndReimport();\n                return;\n            }\n\n            try\n            {\n                AssetDatabase.StartAssetEditing();\n\n                RegenerateAndPopulateExternalMaterials(this.assetPath);\n\n                TriggerAllCallbacks();\n            }\n            finally\n            {\n                AssetDatabase.StopAssetEditing();\n            }\n        }\n\n        [InitializeOnLoadMethod]\n        static void InitializeEditorCallback()\n        {\n            EditorApplication.update += DirtyCustomDependencies;\n            s_DefaultShaderHash = ComputeDefaultShaderHash();\n            AssetDatabase.RegisterCustomDependency(ImporterSettings.kSRPDependencyName, new Hash128(s_DefaultShaderHash, 0));\n        }\n\n\n        static ulong CombineHash(ulong h1, ulong h2)\n        {\n            unchecked\n            {\n                return h1 ^ h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2); // Similar to c++ boost::hash_combine\n            }\n        }\n\n        static ulong ComputeDefaultShaderHash()\n        {\n            ulong newDefaultShaderHash = 0UL;\n            if (GraphicsSettings.GetDefaultShader(DefaultShaderType.SpeedTree9) == null)\n            {\n                newDefaultShaderHash = 0;\n            }\n            else\n            {\n                if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(GraphicsSettings.GetDefaultShader(DefaultShaderType.SpeedTree9), out var guid,\n                        out long fileId))\n                {\n                    newDefaultShaderHash = CombineHash((ulong)guid.GetHashCode(), (ulong)fileId);\n                }\n            }\n\n            return newDefaultShaderHash;\n        }\n\n        static void DirtyCustomDependencies()\n        {\n            DateTime now = DateTime.UtcNow;\n            if (Application.isPlaying || ((now - s_LastCheck) < k_CheckDependencyFrequency))\n            {\n                return;\n            }\n\n            s_LastCheck = now;\n\n            ulong newDefaultShaderHash = ComputeDefaultShaderHash();\n            if (s_DefaultShaderHash != newDefaultShaderHash)\n            {\n                s_DefaultShaderHash = newDefaultShaderHash;\n                AssetDatabase.RegisterCustomDependency(ImporterSettings.kSRPDependencyName, new Hash128(s_DefaultShaderHash, 0));\n                AssetDatabase.Refresh();\n            }\n        }\n\n        #region Mesh Geometry & Renderers\n        private Mesh CreateMeshAndGeometry(Lod lod, int lodIndex)\n        {\n            bool isBillboard = m_LastLodIsBillboard && (lodIndex == (m_LODCount - 1));\n            int vertexCount = (int)lod.Vertices.Length;\n            int numUVs = CalculateNumUVs(isBillboard);\n\n            STMeshGeometry sTMeshGeometry = new STMeshGeometry(vertexCount, numUVs, lodIndex);\n\n            CalculateMeshGeometry(sTMeshGeometry, lod, isBillboard);\n\n            Mesh mesh = new Mesh()\n            {\n                name = \"LOD\" + sTMeshGeometry.lodIndex + \"_Mesh\",\n                indexFormat = (sTMeshGeometry.vertices.Length > 65535) ? IndexFormat.UInt32 : IndexFormat.UInt16,\n                subMeshCount = (int)lod.DrawCalls.Length,\n                vertices = sTMeshGeometry.vertices,\n                normals = sTMeshGeometry.normals,\n                tangents = sTMeshGeometry.tangents,\n                colors32 = sTMeshGeometry.colors32\n            };\n\n            mesh.SetUVs(0, sTMeshGeometry.uvs[0]);\n            mesh.SetUVs(1, sTMeshGeometry.uvs[1]);\n            if (!isBillboard)\n            {\n                // SpeedTree shader expects certain UV2 & UV3 values for leaf facing & wind.\n                // if we don't claim them here now, tree rendering may break when Unity\n                // uses UV2 & UV3 and the shader finds unexpected values.\n                mesh.SetUVs(2, sTMeshGeometry.uvs[2]); // Branch2Pos, Branch2Dir, Branch2Weight, <Unused>\n                mesh.SetUVs(3, sTMeshGeometry.uvs[3]); // 2/3 Anchor XYZ, FacingFlag\n            }\n\n            return mesh;\n        }\n\n        private void SetMeshIndices(Mesh mesh, Lod lod, DrawCall draw, int drawIndex)\n        {\n            int[] indices = new int[draw.IndexCount];\n\n            uint[] lodIndices = lod.Indices;\n\n            for (int index = 0; index < draw.IndexCount; ++index)\n            {\n                indices[index] = unchecked((int)lodIndices[unchecked((int)(draw.IndexStart + index))]);\n            }\n            mesh.SetIndices(indices, MeshTopology.Triangles, drawIndex, true);\n        }\n\n        private void CreateMeshAndLODObjects(Mesh mesh, int lodIndex, ref LOD[] lods)\n        {\n            mesh.RecalculateUVDistributionMetrics();\n            GameObject lodObject = new GameObject(\"LOD\" + lodIndex);\n            lodObject.transform.parent = m_OutputImporterData.mainObject.transform;\n\n            MeshFilter meshFilter = lodObject.AddComponent<MeshFilter>();\n            meshFilter.mesh = mesh;\n\n            MeshRenderer renderer = lodObject.AddComponent<MeshRenderer>();\n            {\n                lods[lodIndex] = new LOD(m_PerLODSettings[lodIndex].height, new Renderer[] { renderer });\n\n                SetMeshRendererSettings(renderer, lodIndex);\n            }\n\n            AddTreeComponentToLODObject(lodObject);\n\n            m_Context.AddObjectToAsset(mesh.name, mesh);\n        }\n\n        private void CalculateMeshGeometry(STMeshGeometry sTMeshGeometry, Lod lod, bool isBillboard)\n        {\n            STVertex[] vertices = lod.Vertices;\n\n            for (int i = 0; i < sTMeshGeometry.vertices.Length; ++i)\n            {\n                STVertex vertex = vertices[i];\n\n                sTMeshGeometry.vertices[i].Set(\n                    vertex.Anchor.X + (vertex.CameraFacing ? -vertex.Offset.X : vertex.Offset.X),\n                    vertex.Anchor.Y + vertex.Offset.Y,\n                    vertex.Anchor.Z + vertex.Offset.Z);\n\n                sTMeshGeometry.vertices[i] *= m_MeshSettings.scaleFactor;\n\n                sTMeshGeometry.normals[i].Set(vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z);\n\n                Vector3 vertexTangent = new Vector3(vertex.Tangent.X, vertex.Tangent.Y, vertex.Tangent.Z);\n                Vector3 binormal = Vector3.Cross(sTMeshGeometry.normals[i], vertexTangent);\n                Vector2 vertexBinormal = new Vector3(vertex.Binormal.X, vertex.Binormal.Y, vertex.Binormal.Z);\n\n                float dot = Vector3.Dot(binormal, vertexBinormal);\n                float flip = (dot < 0.0f) ? -1.0f : 1.0f;\n\n                sTMeshGeometry.tangents[i].Set(vertex.Tangent.X, vertex.Tangent.Y, vertex.Tangent.Z, flip);\n\n                sTMeshGeometry.colors32[i] = new Color(\n                    vertex.Color.X * vertex.AmbientOcclusion,\n                    vertex.Color.Y * vertex.AmbientOcclusion,\n                    vertex.Color.Z * vertex.AmbientOcclusion,\n                    vertex.BlendWeight);\n\n                // Texcoord setup:\n                // 0        Diffuse UV, Branch1Pos, Branch1Dir\n                // 1        Lightmap UV, Branch1Weight, RippleWeight\n\n                // If Branch2 is available:\n                // 2        Branch2Pos, Branch2Dir, Branch2Weight, <Unused>\n\n                // If camera-facing geom is available:\n                // 2/3      Anchor XYZ, FacingFlag\n\n                int currentUV = 0;\n                sTMeshGeometry.uvs[currentUV++][i].Set(\n                    vertex.TexCoord.X,\n                    vertex.TexCoord.Y,\n                    vertex.BranchWind1.X,\n                    vertex.BranchWind1.Y);\n\n                sTMeshGeometry.uvs[currentUV++][i].Set(\n                    vertex.LightmapTexCoord.X,\n                    vertex.LightmapTexCoord.Y,\n                    vertex.BranchWind1.Z,\n                    vertex.RippleWeight);\n\n                if (!isBillboard)\n                {\n                    float anchorX = m_HasFacingData ? vertex.Anchor.X * m_MeshSettings.scaleFactor : 0.0f;\n                    float anchorY = m_HasFacingData ? vertex.Anchor.Y * m_MeshSettings.scaleFactor : 0.0f;\n                    float anchorZ = m_HasFacingData ? vertex.Anchor.Z * m_MeshSettings.scaleFactor : 0.0f;\n                    float leafFacingFlag = vertex.CameraFacing ? 1.0f : 0.0f;\n\n                    sTMeshGeometry.uvs[currentUV++][i].Set(\n                        m_HasBranch2Data ? vertex.BranchWind2.X : anchorX,\n                        m_HasBranch2Data ? vertex.BranchWind2.Y : anchorY,\n                        m_HasBranch2Data ? vertex.BranchWind2.Z : anchorZ,\n                        m_HasBranch2Data ? 0.0f /*UNUSED*/      : leafFacingFlag);\n\n                    bool useUV3 = m_HasBranch2Data && m_HasFacingData;\n                    sTMeshGeometry.uvs[currentUV++][i].Set(\n                         useUV3 ? anchorX        : 0.0f,\n                         useUV3 ? anchorY        : 0.0f,\n                         useUV3 ? anchorZ        : 0.0f,\n                         useUV3 ? leafFacingFlag : 0.0f);\n                }\n            }\n        }\n\n        private void SetMeshRendererSettings(MeshRenderer renderer, int lodIndex)\n        {\n            ShadowCastingMode castMode = (m_LightingSettings.enableShadowCasting) ? ShadowCastingMode.On : ShadowCastingMode.Off;\n            LightProbeUsage probeUsage = (m_LightingSettings.enableLightProbes) ? LightProbeUsage.BlendProbes : LightProbeUsage.Off;\n            ReflectionProbeUsage reflectionProbe = m_LightingSettings.reflectionProbeEnumValue;\n            bool receiveShadows = m_LightingSettings.enableShadowReceiving;\n\n            if (m_PerLODSettings[lodIndex].enableSettingOverride)\n            {\n                castMode = m_PerLODSettings[lodIndex].castShadows ? ShadowCastingMode.On : ShadowCastingMode.Off;\n                probeUsage = m_PerLODSettings[lodIndex].useLightProbes ? LightProbeUsage.BlendProbes : LightProbeUsage.Off;\n                receiveShadows = m_PerLODSettings[lodIndex].receiveShadows;\n                reflectionProbe = m_PerLODSettings[lodIndex].reflectionProbeUsage;\n            }\n\n            renderer.sharedMaterials = RetrieveMaterialsForCurrentLod(lodIndex);\n            renderer.motionVectorGenerationMode = m_AdditionalSettings.motionVectorModeEnumValue;\n            renderer.receiveShadows = receiveShadows;\n            renderer.shadowCastingMode = castMode;\n            renderer.lightProbeUsage = probeUsage;\n            renderer.reflectionProbeUsage = reflectionProbe;\n        }\n\n        private int CalculateNumUVs(bool isBillboard)\n        {\n            int numUVs = 2;\n            if (!isBillboard)\n            {\n                numUVs += 2; // reserve UV2 & UV3 for 3D-geometry to detect leaf facing (VS effect) correctly\n            }\n            return numUVs;\n        }\n        #endregion\n\n        #region LODs\n        private PerLODSettings InstantiateAndInitializeLODSettingsObject(bool isBillboardLOD)\n        {\n            return new PerLODSettings()\n            {\n                enableSettingOverride = isBillboardLOD,\n                enableBump = m_MaterialSettings.enableBumpMapping,\n                enableHue = m_MaterialSettings.enableHueVariation,\n                enableSubsurface = m_MaterialSettings.enableSubsurfaceScattering,\n                castShadows = true,\n                receiveShadows = true,\n                useLightProbes = !isBillboardLOD,\n                reflectionProbeUsage = isBillboardLOD ? ReflectionProbeUsage.Off : ReflectionProbeUsage.BlendProbes,\n            };\n        }\n\n        private void CalculateBillboardAndPerLODSettings()\n        {\n            if (m_PerLODSettings.Count > m_LODCount)\n            {\n                m_PerLODSettings.RemoveRange((int)m_LODCount, m_PerLODSettings.Count);\n            }\n            else if (m_PerLODSettings.Count < m_LODCount)\n            {\n                m_PerLODSettings.Clear();\n                for (int i = 0; i < m_LODCount; ++i)\n                {\n                    bool isBillboardLOD = m_LastLodIsBillboard && i == m_LODCount - 1;\n\n                    PerLODSettings lodSettings = InstantiateAndInitializeLODSettingsObject(isBillboardLOD);\n\n                    m_PerLODSettings.Add(lodSettings);\n                }\n\n                // Always reset LOD heights if size doesn't match.\n                for (int i = 0; i < m_LODCount; ++i)\n                {\n                    m_PerLODSettings[i].height = (i == 0) ? 0.5f : m_PerLODSettings[i - 1].height * 0.5f;\n                }\n\n                if (m_LODCount > 0)\n                {\n                    // Using this pattern to avoid using 'Last' from Linq.\n                    m_PerLODSettings[^1].height = 0.01f;\n                }\n            }\n\n            Debug.Assert(m_PerLODSettings.Count == m_LODCount);\n        }\n\n        private Material[] RetrieveMaterialsForCurrentLod(int lodIndex)\n        {\n            List<MaterialInfo> materials = m_OutputImporterData.lodMaterials.materials;\n\n            if (materials == null || materials.Count == 0)\n                return null;\n\n            List<int> matIDs = m_OutputImporterData.lodMaterials.lodToMaterials[lodIndex];\n\n            // Using this pattern to avoid using 'Select' from Linq.\n            Material[] lodMaterials = new Material[matIDs.Count];\n            for (int i = 0; i < matIDs.Count; ++i)\n            {\n                lodMaterials[i] = materials[matIDs[i]].material;\n            }\n\n            return lodMaterials;\n        }\n\n        private void AddLODGroupToMainObjectAndSetTransition(LOD[] lods)\n        {\n            LODGroup lodGroup = m_OutputImporterData.mainObject.AddComponent<LODGroup>();\n            lodGroup.SetLODs(lods);\n\n            int numLODs = lods.Length;\n\n            if (m_LODSettings.enableSmoothLODTransition && numLODs > 0)\n            {\n                lodGroup.fadeMode = LODFadeMode.CrossFade;\n                lodGroup.animateCrossFading = m_LODSettings.animateCrossFading;\n                lodGroup.lastLODBillboard = m_LastLodIsBillboard;\n\n                if (!m_LODSettings.animateCrossFading)\n                {\n                    int lastLod = numLODs - 1;\n                    lods[lastLod].fadeTransitionWidth = m_LODSettings.fadeOutWidth;\n\n                    if (m_LastLodIsBillboard && numLODs > 2)\n                    {\n                        int lastMeshLOD = numLODs - 2;\n                        lods[lastMeshLOD].fadeTransitionWidth = m_LODSettings.billboardTransitionCrossFadeWidth;\n                    }\n                }\n            }\n\n            lodGroup.RecalculateBounds();\n        }\n\n        private void AddTreeComponentToLODObject(GameObject mainObject)\n        {\n            // Register the wind asset ptr through Tree component.\n            Tree treeComponent = mainObject.AddComponent<Tree>();\n            if (m_WindEnabled)\n            {\n                treeComponent.windAsset = m_WindAsset;\n            }\n        }\n        #endregion\n\n        #region Materials\n        private void CreateMeshAndMaterials(bool regenerateMaterials = false)\n        {\n            LOD[] lods = new LOD[m_LODCount];\n\n            // Loop each LOD (mesh) of the asset.\n            for (int lodIndex = 0; lodIndex < m_LODCount; ++lodIndex)\n            {\n                Lod lod = m_Tree.Lod[lodIndex];\n                Mesh mesh = CreateMeshAndGeometry(lod, lodIndex);\n\n                // Loop each DrawCall (material) of the current mesh LOD.\n                for (int drawIndex = 0; drawIndex < lod.DrawCalls.Length; ++drawIndex)\n                {\n                    DrawCall draw = lod.DrawCalls[drawIndex];\n\n                    STMaterial stMaterial = m_Tree.Materials[(int)draw.MaterialIndex];\n\n                    CreateMaterialsForCurrentLOD(stMaterial, lodIndex, regenerateMaterials);\n\n                    SetMeshIndices(mesh, lod, draw, drawIndex);\n                }\n\n                CreateMeshAndLODObjects(mesh, lodIndex, ref lods);\n            }\n\n            AddLODGroupToMainObjectAndSetTransition(lods);\n        }\n\n        private void CreateMaterialsForCurrentLOD(STMaterial stMaterial, int lodIndex, bool regenerateMaterials)\n        {\n            bool matOverrided = m_PerLODSettings[lodIndex].enableSettingOverride;\n            bool isBillboard = m_LastLodIsBillboard && (lodIndex == (m_LODCount - 1));\n\n            // Overrided LODs have they own unique material.\n            string stMatName = stMaterial.Name;\n            if (matOverrided && !isBillboard)\n                stMatName += String.Format(\"LOD{0}\", lodIndex);\n\n            // Retrieve previously extracted material and update serialized index.\n            if (TryGetExternalMaterial(stMatName, out var extractedMat))\n            {\n                // Explicity regenerate materials, should happen when bumping the material version for example.\n                if (regenerateMaterials)\n                {\n                    extractedMat = CreateMaterial(stMaterial, lodIndex, extractedMat.name, m_PathFromDirectory);\n\n                    SetMaterialTextureAndColorProperties(stMaterial, extractedMat, lodIndex, m_PathFromDirectory);\n                }\n                else\n                {\n                    RetrieveMaterialSpecialProperties(extractedMat);\n                }\n\n                var existedMatIndex = m_OutputImporterData.lodMaterials.materials.FindIndex(m => m.defaultName == stMatName);\n                if (existedMatIndex == -1)\n                {\n                    m_OutputImporterData.lodMaterials.materials.Add(new MaterialInfo { material = extractedMat, defaultName = stMatName, exported = true });\n                    m_OutputImporterData.lodMaterials.matNameToIndex[stMatName] = m_OutputImporterData.lodMaterials.materials.Count - 1;\n                }\n                else\n                {\n                    m_OutputImporterData.lodMaterials.matNameToIndex[stMatName] = existedMatIndex;\n                }\n            }\n            // Create material if it doesn't exist yet.\n            else if (!m_OutputImporterData.lodMaterials.matNameToIndex.ContainsKey(stMatName))\n            {\n                Material newMat = CreateMaterial(stMaterial, lodIndex, stMatName, m_PathFromDirectory);\n\n                m_OutputImporterData.lodMaterials.materials.Add(new MaterialInfo { material = newMat, defaultName = stMatName, exported = false });\n                m_OutputImporterData.lodMaterials.matNameToIndex.Add(stMatName, m_OutputImporterData.lodMaterials.materials.Count - 1);\n            }\n\n            // Map the material id to the current LOD.\n            int indexMat = m_OutputImporterData.lodMaterials.matNameToIndex[stMatName];\n            m_OutputImporterData.lodMaterials.AddLodMaterialIndex(lodIndex, indexMat);\n        }\n\n        private void CreateAssetIdentifiersAndAddMaterialsToContext()\n        {\n            m_OutputImporterData.materialsIdentifiers.Clear();\n\n            foreach (MaterialInfo matInfo in m_OutputImporterData.lodMaterials.materials)\n            {\n                m_OutputImporterData.hasEmbeddedMaterials |= !matInfo.exported;\n\n                if (!matInfo.exported)\n                {\n                    m_Context.AddObjectToAsset(matInfo.material.name, matInfo.material);\n\n                    // It looks like a limitation from the default AssetImporter system. When deleting extracted materials manually,\n                    // the external object map still contains a null reference, even after a reimport of the asset.\n                    if (TryGetSourceAssetIdentifierFromName(matInfo.material.name, out var assetIdentifier))\n                    {\n                        RemoveRemap(assetIdentifier);\n                    }\n                }\n\n                m_OutputImporterData.materialsIdentifiers.Add(new AssetIdentifier(matInfo.material.GetType(), matInfo.defaultName));\n            }\n        }\n\n        private void RegenerateMaterialsFromTree()\n        {\n            for (int lodIndex = 0; lodIndex < m_LODCount; lodIndex++)\n            {\n                Lod stLOD = m_Tree.Lod[lodIndex];\n\n                // Loop necessary materials for current LOD.\n                for (int drawIndex = 0; drawIndex < stLOD.DrawCalls.Length; ++drawIndex)\n                {\n                    int matIndex = (int)stLOD.DrawCalls[drawIndex].MaterialIndex;\n                    STMaterial stMaterial = m_Tree.Materials[matIndex];\n\n                    CreateMaterialsForCurrentLOD(stMaterial, lodIndex, regenerateMaterials: true);\n                }\n            }\n        }\n\n        private void RegenerateAndPopulateExternalMaterials(string assetPath)\n        {\n            // This object could potentially be cached, but this function is rarely triggered (only when bumping the material version)\n            // so the cost of caching it is not really interesting.\n            m_Tree = new SpeedTree9Reader();\n\n            FileStatus status = m_Tree.Initialize(assetPath);\n            if (status != FileStatus.Valid)\n            {\n                Debug.LogError($\"Error while initializing the SpeedTree9 reader: {status}.\");\n                return;\n            }\n\n            m_Tree.ReadContent();\n\n            CacheTreeImporterValues(assetPath);\n\n            if (!TryGetShaderForCurrentRenderPipeline(out m_Shader))\n            {\n                Debug.LogError(\"SpeedTree9 shader is invalid, cannot create Materials for this SpeedTree asset.\");\n                return;\n            }\n\n            m_OutputImporterData = AssetDatabase.LoadAssetAtPath<SpeedTreeImporterOutputData>(assetPath);\n            m_OutputImporterData.lodMaterials.materials.Clear();\n\n            if (m_WindEnabled)\n            {\n                m_OutputImporterData.m_WindConfig = CopySpeedTree9WindConfig(m_Tree.Wind, m_MeshSettings.scaleFactor, m_Tree.Bounds);\n            }\n\n            RegenerateMaterialsFromTree();\n\n            foreach (MaterialInfo matInfo in m_OutputImporterData.lodMaterials.materials)\n            {\n                m_OutputImporterData.hasEmbeddedMaterials |= !matInfo.exported;\n\n                m_OutputImporterData.materialsIdentifiers.Add(new AssetIdentifier(matInfo.material.GetType(), matInfo.material.name));\n\n                // Remap the new material to the importer 'ExternalObjectMap'.\n                if (TryGetExternalMaterial(matInfo.defaultName, out var extractedMat))\n                {\n                    string newMatPath = AssetDatabase.GetAssetPath(extractedMat);\n\n                    // Not ideal, but it's safer to regenerate entirely the material (in case the pipeline has changed)\n                    // and to avoid any potential issue with the 'ExternalObject' system (material null during next import)\n                    if (File.Exists(newMatPath))\n                    {\n                        File.Delete(newMatPath);\n                        AssetDatabase.CreateAsset(matInfo.material, newMatPath);\n                    }\n\n                    if (TryGetSourceAssetIdentifierFromName(matInfo.defaultName, out var assetIdentifier))\n                    {\n                        AddRemap(assetIdentifier, matInfo.material);\n                    }\n                }\n            }\n        }\n\n        private bool TryGetExternalMaterial(string name, out Material material)\n        {\n            var externalObjMap = GetExternalObjectMap();\n\n            foreach (var obj in externalObjMap)\n            {\n                if (obj.Key.name == name)\n                {\n                    material = obj.Value as Material;\n                    return material != null;\n                }\n            }\n\n            material = null;\n            return false;\n        }\n\n        private bool TryGetSourceAssetIdentifierFromName(string name, out SourceAssetIdentifier assetIdentifier)\n        {\n            var externalObjMap = GetExternalObjectMap();\n\n            foreach (var obj in externalObjMap)\n            {\n                if (obj.Key.name == name)\n                {\n                    assetIdentifier = obj.Key;\n                    return true;\n                }\n            }\n\n            assetIdentifier = new SourceAssetIdentifier();\n            return false;\n        }\n\n        private Material CreateMaterial(STMaterial stMaterial, int lod, string matName, string path)\n        {\n            Material mat = new Material(m_Shader)\n            {\n                name = matName\n            };\n\n            RetrieveMaterialSpecialProperties(mat);\n\n            SetMaterialTextureAndColorProperties(stMaterial, mat, lod, path);\n\n            SetMaterialOtherProperties(stMaterial, mat);\n\n            SetWindKeywords(mat, stMaterial.Billboard);\n\n            return mat;\n        }\n\n        private bool SetMaterialTexture(Material mat, STMaterial stMaterial, int indexMap, string path, int property)\n        {\n            if (stMaterial.Maps.Length > indexMap)\n            {\n                MaterialMap stMatMap = stMaterial.Maps[indexMap];\n                string mapPath = stMatMap.Path;\n\n                if (!stMatMap.Used)\n                    return false;\n\n                if (!string.IsNullOrEmpty(mapPath))\n                {\n                    Texture2D texture = LoadTexture(mapPath, path);\n\n                    if (texture != null)\n                    {\n                        mat.SetTexture(property, texture);\n                        return true;\n                    }\n                }\n            }\n\n            return false;\n        }\n\n        private Texture2D LoadTexture(string mapPath, string path)\n        {\n            string texturePath = path + mapPath;\n\n            Texture2D texture = (m_Context != null)\n                ? m_Context.GetReferenceToAssetMainObject(texturePath) as Texture2D\n                : AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D)) as Texture2D;\n\n            if (texture != null)\n                return texture;\n\n            // Textures are not located near the asset, let's check if they were moved somewhere else.\n            string mapPathWithoutExtension = Path.GetFileNameWithoutExtension(mapPath);\n            string[] textureAssets = AssetDatabase.FindAssets(mapPathWithoutExtension);\n\n            if (textureAssets != null && textureAssets.Length > 0)\n            {\n                string assetPathFromGUID = AssetDatabase.GUIDToAssetPath(textureAssets[0]);\n\n                texture = (m_Context != null)\n                    ? m_Context.GetReferenceToAssetMainObject(assetPathFromGUID) as Texture2D\n                    : AssetDatabase.LoadAssetAtPath(assetPathFromGUID, typeof(Texture2D)) as Texture2D;\n\n                return texture;\n            }\n\n            return null;\n        }\n\n        private bool TryGetInstanceIDFromMaterialProperty(Material material, int propertyName, out int id)\n        {\n            if (!material.HasProperty(propertyName))\n            {\n                id = 0;\n                return false;\n            }\n\n            var property = material.GetTexture(propertyName);\n            id = property.GetInstanceID();\n\n            return true;\n        }\n\n        // Not all pipelines support the following properties, so we don't draw them in the inspector if that's the case.\n        private void RetrieveMaterialSpecialProperties(Material mat)\n        {\n            m_OutputImporterData.hasAlphaClipThreshold |= mat.HasProperty(MaterialProperties.AlphaClipThresholdID);\n            m_OutputImporterData.hasTransmissionScale |= mat.HasProperty(MaterialProperties.TransmissionScaleID);\n        }\n\n        private void SetMaterialTextureAndColorProperties(STMaterial stMaterial, Material mat, int lodIndex, string path)\n        {\n            bool enableHueVariation = m_MaterialSettings.enableHueVariation;\n            bool enableBumpMapping = m_MaterialSettings.enableBumpMapping;\n            bool enableSubsurfaceScattering = m_MaterialSettings.enableSubsurfaceScattering;\n\n            if (m_PerLODSettings[lodIndex].enableSettingOverride)\n            {\n                enableHueVariation = m_PerLODSettings[lodIndex].enableHue;\n                enableBumpMapping = m_PerLODSettings[lodIndex].enableBump;\n                enableSubsurfaceScattering = m_PerLODSettings[lodIndex].enableSubsurface;\n            }\n\n            // MainTex and Color\n            {\n                bool colorTex = SetMaterialTexture(mat, stMaterial, 0, path, MaterialProperties.MainTexID);\n\n                if (colorTex && TryGetInstanceIDFromMaterialProperty(mat, MaterialProperties.MainTexID, out int id) && id != 0)\n                {\n                    mat.SetColor(MaterialProperties.ColorTintID, m_MaterialSettings.mainColor);\n                }\n                else if (colorTex)\n                {\n                    Vec4 stColorVec = stMaterial.Maps[3].Color;\n                    Color rpColor = new Color(stColorVec.X, stColorVec.Y, stColorVec.Z, stColorVec.W);\n\n                    mat.SetColor(MaterialProperties.ColorTintID, m_MaterialSettings.mainColor * rpColor);\n                }\n            }\n\n            // Bump map\n            {\n                bool hasNormalMap = SetMaterialTexture(mat, stMaterial, 1, path, MaterialProperties.NormalMapID);\n                bool enableFeature = hasNormalMap && enableBumpMapping;\n\n                mat.SetFloat(MaterialProperties.NormalMapKwToggleID, (enableFeature) ? 1.0f : 0.0f);\n            }\n\n            // Glossiness, metallic, AO\n            {\n                bool foundExtra = SetMaterialTexture(mat, stMaterial, 2, path, MaterialProperties.ExtraTexID);\n\n                int id = 0;\n                if (foundExtra && TryGetInstanceIDFromMaterialProperty(mat, MaterialProperties.ExtraTexID, out id) && id != 0)\n                {\n                    // _Glossiness (== _Smoothness) is multipled in the shader with the texture values if ExtraTex is present.\n                    // Set default value 1.0f to override the default value 0.5, otherwise, the original texture values will\n                    // be scaled down to half as much. Same goes for _Metallic\n                    mat.SetFloat(MaterialProperties.GlossinessID, 1.0f);\n                    mat.SetFloat(MaterialProperties.MetallicID, 1.0f);\n                }\n                else if (foundExtra)\n                {\n                    Vec4 stColor = stMaterial.Maps[2].Color;\n                    mat.SetFloat(MaterialProperties.GlossinessID, stColor.X);\n                    mat.SetFloat(MaterialProperties.MetallicID, stColor.Y);\n                }\n\n                mat.SetFloat(MaterialProperties.ExtraMapKwToggleID, (foundExtra && id != 0) ? 1.0f : 0.0f);\n            }\n\n            // Extra and SSS\n            if (stMaterial.TwoSided || stMaterial.Billboard)\n            {\n                bool hasSSSTex = SetMaterialTexture(mat, stMaterial, 3, path, MaterialProperties.SubsurfaceTexID);\n                bool setToggle = hasSSSTex && enableSubsurfaceScattering;\n\n                // TODO: To implement in ST9 Shader.\n                mat.SetFloat(MaterialProperties.SubsurfaceKwToggleID, (setToggle) ? 1.0f : 0.0f);\n\n                if (hasSSSTex && TryGetInstanceIDFromMaterialProperty(mat, MaterialProperties.SubsurfaceTexID, out int id) && id != 0)\n                {\n                    mat.SetColor(MaterialProperties.SubsurfaceColorID, new Color(1.0f, 1.0f, 1.0f, 1.0f));\n                }\n                else if (hasSSSTex)\n                {\n                    Vec4 stColor = stMaterial.Maps[3].Color;\n                    mat.SetColor(MaterialProperties.SubsurfaceColorID, new Color(stColor.X, stColor.Y, stColor.Z, stColor.W));\n                }\n\n                if (m_OutputImporterData.hasAlphaClipThreshold && mat.HasFloat(MaterialProperties.AlphaClipThresholdID))\n                {\n                    mat.SetFloat(MaterialProperties.AlphaClipThresholdID, m_MaterialSettings.alphaClipThreshold);\n                }\n\n                if (m_OutputImporterData.hasTransmissionScale && mat.HasFloat(MaterialProperties.TransmissionScaleID))\n                {\n                    mat.SetFloat(MaterialProperties.TransmissionScaleID, m_MaterialSettings.transmissionScale);\n                }\n            }\n\n            // Hue effect\n            {\n                mat.SetFloat(MaterialProperties.HueVariationKwToggleID, enableHueVariation ? 1.0f : 0.0f);\n                mat.SetColor(MaterialProperties.HueVariationColorID, m_MaterialSettings.hueVariation);\n            }\n        }\n\n        private void SetMaterialOtherProperties(STMaterial stMaterial, Material mat)\n        {\n            bool isBillboard = stMaterial.Billboard;\n\n            // Other properties\n            mat.SetFloat(MaterialProperties.BillboardKwToggleID, isBillboard ? 1.0f : 0.0f);\n            if (isBillboard)\n            {\n                mat.EnableKeyword(MaterialKeywords.BillboardID);\n            }\n            mat.SetFloat(MaterialProperties.LeafFacingKwToggleID, m_HasFacingData ? 1.0f : 0.0f);\n\n            if (mat.HasFloat(MaterialProperties.DoubleSidedToggleID))\n                mat.SetFloat(MaterialProperties.DoubleSidedToggleID, stMaterial.TwoSided ? 1.0f : 0.0f);\n\n            if (mat.HasFloat(MaterialProperties.DoubleSidedNormalModeID))\n                mat.SetFloat(MaterialProperties.DoubleSidedNormalModeID, stMaterial.FlipNormalsOnBackside ? 0.0f : 2.0f);\n\n            if (mat.HasVector(MaterialProperties.DiffusionProfileAssetID))\n                mat.SetVector(MaterialProperties.DiffusionProfileAssetID, m_MaterialSettings.diffusionProfileAssetID);\n\n            if (mat.HasFloat(MaterialProperties.DiffusionProfileID))\n                mat.SetFloat(MaterialProperties.DiffusionProfileID, m_MaterialSettings.diffusionProfileID);\n\n            if (mat.HasFloat(MaterialProperties.BackfaceNormalModeID))\n                mat.SetFloat(MaterialProperties.BackfaceNormalModeID, stMaterial.FlipNormalsOnBackside ? 0.0f : 2.0f);\n\n            if (mat.HasFloat(MaterialProperties.TwoSidedID))\n                mat.SetFloat(MaterialProperties.TwoSidedID, stMaterial.TwoSided ? 0.0f : 2.0f); // matches cull mode. 0: no cull\n\n            mat.enableInstancing = true;\n            mat.doubleSidedGI = stMaterial.TwoSided;\n        }\n\n        private void SetWindKeywords(Material material, bool isBillboardMat)\n        {\n            if (material == null)\n                return;\n\n            //------------------------------------------------------------------------\n            // Note:\n            //   mat.SetFloat(...)      : Legacy rendering pipeline keyword toggle\n            //   mat.EnableKeyword(...) : SRP keyword toggle\n            //------------------------------------------------------------------------\n            SpeedTreeWindConfig9 windCfg = m_OutputImporterData.m_WindConfig;\n\n            if (windCfg.doShared != 0)\n            {\n                material.SetFloat(MaterialProperties.WindSharedKwToggle, 1.0f);\n            }\n            if (!isBillboardMat)\n            {\n                if (windCfg.doBranch2 != 0)\n                {\n                    material.SetFloat(MaterialProperties.WindBranch2KwToggle, 1.0f);\n                }\n                if (windCfg.doBranch1 != 0)\n                {\n                    material.SetFloat(MaterialProperties.WindBranch1KwToggle, 1.0f);\n                }\n                if (windCfg.doRipple != 0)\n                {\n                    material.SetFloat(MaterialProperties.WindRippleKwToggle, 1.0f);\n                    if (windCfg.doShimmer != 0)\n                    {\n                        material.SetFloat(MaterialProperties.WindShimmerKwToggle, 1.0f);\n                    }\n                }\n            }\n        }\n\n        internal bool SearchAndRemapMaterials(string materialFolderPath)\n        {\n            bool changedMappings = false;\n\n            if (materialFolderPath == null)\n                throw new ArgumentNullException(\"materialFolderPath\");\n\n            if (string.IsNullOrEmpty(materialFolderPath))\n                throw new ArgumentException(string.Format(\"Invalid material folder path: {0}.\", materialFolderPath), \"materialFolderPath\");\n\n            string[] guids = AssetDatabase.FindAssets(\"t:Material\", new string[] { materialFolderPath });\n            List<Tuple<string, Material>> materials = new List<Tuple<string, Material>>();\n            foreach (string guid in guids)\n            {\n                string path = AssetDatabase.GUIDToAssetPath(guid);\n                // ensure that we only load material assets, not embedded materials\n                Material material = AssetDatabase.LoadMainAssetAtPath(path) as Material;\n                if (material)\n                    materials.Add(new Tuple<string, Material>(path, material));\n            }\n\n            m_OutputImporterData = AssetDatabase.LoadAssetAtPath<SpeedTreeImporterOutputData>(assetPath);\n            AssetIdentifier[] importedMaterials = m_OutputImporterData.materialsIdentifiers.ToArray();\n\n            foreach (Tuple<string, Material> material in materials)\n            {\n                string materialName = material.Item2.name;\n                string materialFile = material.Item1;\n\n                // the legacy materials have the LOD in the path, while the new materials have the LOD as part of the name\n                bool isLegacyMaterial = !materialName.Contains(\"LOD\") && !materialName.Contains(\"Billboard\");\n                bool hasLOD = isLegacyMaterial && materialFile.Contains(\"LOD\");\n                string lod = Path.GetFileNameWithoutExtension(Path.GetDirectoryName(materialFile));\n                AssetIdentifier importedMaterial = Array.Find(importedMaterials, x => x.name.Contains(materialName) && (!hasLOD || x.name.Contains(lod)));\n\n                if (!string.IsNullOrEmpty(importedMaterial.name))\n                {\n                    SourceAssetIdentifier importedIdentifier = new SourceAssetIdentifier(material.Item2);\n\n                    AddRemap(importedIdentifier, material.Item2);\n                    changedMappings = true;\n                }\n            }\n\n            return changedMappings;\n        }\n\n        internal string GetMaterialFolderPath()\n        {\n            return FileUtil.DeleteLastPathNameComponent(assetPath) + \"/\";\n        }\n\n        internal void SetMaterialsVersionToCurrent()\n        {\n            m_MaterialVersion = SPEEDTREE_9_MATERIAL_VERSION;\n            MarkDirty();\n        }\n\n        private void AddDependencyOnExtractedMaterials()\n        {\n            Dictionary<SourceAssetIdentifier, UnityEngine.Object> extMap = GetExternalObjectMap();\n\n            foreach (var entry in extMap)\n            {\n                if (entry.Value != null)\n                {\n                    string matPath = AssetDatabase.GetAssetPath(entry.Value);\n\n                    m_Context.DependsOnImportedAsset(matPath);\n\n                    // Necessary to avoid the warning \"Import of asset setup artifact dependency to but dependency isn't used\n                    // and therefore not registered in the asset database\".\n                    AssetDatabase.LoadAssetAtPath(matPath, typeof(Material));\n                }\n            }\n        }\n        #endregion\n\n        #region Wind\n        private unsafe SpeedTreeWindConfig9 CopySpeedTree9WindConfig(WindConfigSDK wind, float scaleFactor, in Bounds3 treeBounds)\n        {\n            const bool CHECK_ZERO = true;\n            const bool DONT_CHECK_ZERO = false;\n\n            void CopyCurve(in float[] src, float* dst)\n            {\n                const int NUM_CURVE_ELEMENTS = 20;\n                Debug.Assert(src.Length == NUM_CURVE_ELEMENTS);\n                for (global::System.Int32 i = 0; i < NUM_CURVE_ELEMENTS; i++)\n                {\n                    dst[i] = src[i];\n                }\n            }\n\n            void CopyCurveScale(in float[] src, float* dst, float scaleFactor)\n            {\n                const int NUM_CURVE_ELEMENTS = 20;\n                Debug.Assert(src.Length == NUM_CURVE_ELEMENTS);\n                for (global::System.Int32 i = 0; i < NUM_CURVE_ELEMENTS; i++)\n                {\n                    dst[i] = src[i] * scaleFactor;\n                }\n            }\n\n            bool ValidCurve(float[] curve, bool bCheckZero = CHECK_ZERO)\n            {\n                bool bNonZero = false;\n                for (int i = 0; i < curve.Length; ++i)\n                {\n                    bNonZero |= curve[i] != 0.0f;\n                    if (float.IsNaN(curve[i]))\n                    {\n                        return false;\n                    }\n                }\n\n                if (bCheckZero)\n                {\n                    return bNonZero;\n                }\n                return true;\n            }\n\n            bool BranchHasAllCurvesValid(in WindBranch b)\n            {\n                return ValidCurve(b.Bend)\n                    && ValidCurve(b.Oscillation)\n                    && ValidCurve(b.Speed, CHECK_ZERO)\n                    && ValidCurve(b.Turbulence)\n                    && ValidCurve(b.Flexibility, DONT_CHECK_ZERO\n                );\n            }\n\n            bool RippleHasAllCurvesValid(in WindRipple r)\n            {\n                return ValidCurve(r.Planar)\n                    && ValidCurve(r.Directional)\n                    && ValidCurve(r.Speed)\n                    && ValidCurve(r.Flexibility, DONT_CHECK_ZERO\n                );\n            }\n\n            SpeedTreeWindConfig9 cfg = new SpeedTreeWindConfig9();\n\n            // common\n            WindConfigCommon common = wind.Common;\n            cfg.strengthResponse = common.StrengthResponse;\n            cfg.directionResponse = common.DirectionResponse;\n            cfg.gustFrequency = common.GustFrequency;\n            cfg.gustStrengthMin = common.GustStrengthMin;\n            cfg.gustStrengthMax = common.GustStrengthMax;\n            cfg.gustDurationMin = common.GustDurationMin;\n            cfg.gustDurationMax = common.GustDurationMax;\n            cfg.gustRiseScalar = common.GustRiseScalar;\n            cfg.gustFallScalar = common.GustFallScalar;\n\n            // st9\n            cfg.branch1StretchLimit = wind.Branch1StretchLimit * scaleFactor;\n            cfg.branch2StretchLimit = wind.Branch2StretchLimit * scaleFactor;\n            cfg.importScale = scaleFactor;\n            cfg.treeExtentX = (treeBounds.Max.X - treeBounds.Min.X) * scaleFactor;\n            cfg.treeExtentY = (treeBounds.Max.Y - treeBounds.Min.Y) * scaleFactor;\n            cfg.treeExtentZ = (treeBounds.Max.Z - treeBounds.Min.Z) * scaleFactor;\n\n            if (wind.DoShared)\n            {\n                WindConfigSDK.WindBranch shared = wind.Shared;\n                CopyCurveScale(shared.Bend, cfg.bendShared, scaleFactor);\n                CopyCurveScale(shared.Oscillation, cfg.oscillationShared, scaleFactor);\n                CopyCurve(shared.Speed, cfg.speedShared);\n                CopyCurve(shared.Turbulence, cfg.turbulenceShared);\n                CopyCurve(shared.Flexibility, cfg.flexibilityShared);\n                cfg.independenceShared = shared.Independence;\n                cfg.sharedHeightStart = wind.SharedStartHeight; // this is a % value\n                if (BranchHasAllCurvesValid(in shared))\n                {\n                    cfg.doShared = 1;\n                }\n            }\n\n            if (wind.DoBranch1)\n            {\n                WindConfigSDK.WindBranch branch1 = wind.Branch1;\n                CopyCurveScale(branch1.Bend, cfg.bendBranch1, scaleFactor);\n                CopyCurveScale(branch1.Oscillation, cfg.oscillationBranch1, scaleFactor);\n                CopyCurve(branch1.Speed, cfg.speedBranch1);\n                CopyCurve(branch1.Turbulence, cfg.turbulenceBranch1);\n                CopyCurve(branch1.Flexibility, cfg.flexibilityBranch1);\n                cfg.independenceBranch1 = branch1.Independence;\n                if (BranchHasAllCurvesValid(in branch1))\n                {\n                    cfg.doBranch1 = 1;\n                }\n            }\n\n            if (wind.DoBranch2)\n            {\n                WindConfigSDK.WindBranch branch2 = wind.Branch2;\n                CopyCurveScale(branch2.Bend, cfg.bendBranch2, scaleFactor);\n                CopyCurveScale(branch2.Oscillation, cfg.oscillationBranch2, scaleFactor);\n                CopyCurve(branch2.Speed, cfg.speedBranch2);\n                CopyCurve(branch2.Turbulence, cfg.turbulenceBranch2);\n                CopyCurve(branch2.Flexibility, cfg.flexibilityBranch2);\n                cfg.independenceBranch2 = branch2.Independence;\n                if (BranchHasAllCurvesValid(in branch2))\n                {\n                    cfg.doBranch2 = 1;\n                }\n            }\n\n            if (wind.DoRipple)\n            {\n                WindConfigSDK.WindRipple ripple = wind.Ripple;\n                CopyCurveScale(ripple.Planar, cfg.planarRipple, scaleFactor);\n                CopyCurveScale(ripple.Directional, cfg.directionalRipple, scaleFactor);\n                CopyCurve(ripple.Speed, cfg.speedRipple);\n                CopyCurve(ripple.Flexibility, cfg.flexibilityRipple);\n                cfg.independenceRipple = ripple.Independence;\n                if (RippleHasAllCurvesValid(in ripple))\n                {\n                    cfg.doRipple = 1;\n                    if (wind.DoShimmer)\n                    {\n                        cfg.doShimmer = 1;\n                        cfg.shimmerRipple = ripple.Shimmer;\n                    }\n                }\n            }\n            return cfg;\n        }\n\n        private void SetWindParameters(ref SpeedTreeWindConfig9 cfg)\n        {\n            cfg.strengthResponse = m_WindSettings.strenghResponse;\n            cfg.directionResponse = m_WindSettings.directionResponse;\n            cfg.windIndependence = m_WindSettings.randomness;\n        }\n\n        #endregion\n\n        #region Others\n        private void CalculateScaleFactorFromUnit()\n        {\n            switch (m_MeshSettings.unitConversion)\n            {\n                // Use units in the imported file without any conversion.\n                case STUnitConversion.kLeaveAsIs:\n                    m_MeshSettings.scaleFactor = 1.0f;\n                    break;\n                case STUnitConversion.kFeetToMeters:\n                    m_MeshSettings.scaleFactor = SpeedTreeConstants.kFeetToMetersRatio;\n                    break;\n                case STUnitConversion.kCentimetersToMeters:\n                    m_MeshSettings.scaleFactor = SpeedTreeConstants.kCentimetersToMetersRatio;\n                    break;\n                case STUnitConversion.kInchesToMeters:\n                    m_MeshSettings.scaleFactor = SpeedTreeConstants.kInchesToMetersRatio;\n                    break;\n                case STUnitConversion.kCustomConversion:\n                    /* no-op */\n                    break;\n            }\n        }\n\n        private bool TreeHasFacingData()\n        {\n            for (int lodIndex = 0; lodIndex < m_LODCount; ++lodIndex)\n            {\n                Lod lod = m_Tree.Lod[lodIndex];\n\n                for (int drawIndex = 0; drawIndex < lod.DrawCalls.Length; ++drawIndex)\n                {\n                    DrawCall draw = lod.DrawCalls[drawIndex];\n                    if(draw.ContainsFacingGeometry)\n                        return true;\n                }\n            }\n            return false;\n        }\n\n        internal static bool TryGetShaderForCurrentRenderPipeline(out Shader shader)\n        {\n            shader = GraphicsSettings.GetDefaultShader(DefaultShaderType.SpeedTree9);\n            if (shader == null)\n            {\n                shader = Shader.Find(ImporterSettings.kLegacyShaderName);\n            }\n\n            return shader != null;\n        }\n\n        private void CreateAndAddRigidBodyToAsset(GameObject mainObject)\n        {\n            Rigidbody rb = mainObject.AddComponent<Rigidbody>();\n            if (rb != null)\n            {\n                rb.useGravity = false;\n                rb.isKinematic = true;\n            }\n        }\n\n        private void CreateAndAddCollidersToAsset()\n        {\n            for (int iCollider = 0; iCollider < m_CollisionObjectsCount; ++iCollider)\n            {\n                CollisionObject stCollider = m_Tree.CollisionObjects[iCollider];\n\n                GameObject collisionObject = new GameObject(\"Collider\" + (iCollider + 1));\n                collisionObject.transform.parent = m_OutputImporterData.mainObject.transform;\n\n                Vector3 vOne = new Vector3(stCollider.Position.X, stCollider.Position.Y, stCollider.Position.Z);\n                Vector3 vTwo = new Vector3(stCollider.Position2.X, stCollider.Position2.Y, stCollider.Position2.Z);\n\n                vOne *= m_MeshSettings.scaleFactor;\n                vTwo *= m_MeshSettings.scaleFactor;\n\n                collisionObject.transform.position = (vOne + vTwo) * 0.5f;\n\n                if ((vOne - vTwo).sqrMagnitude < 0.001f)\n                {\n                    SphereCollider collider = collisionObject.AddComponent<SphereCollider>();\n                    collider.radius = stCollider.Radius * m_MeshSettings.scaleFactor;\n                }\n                else\n                {\n                    CapsuleCollider collider = collisionObject.AddComponent<CapsuleCollider>();\n                    collider.direction = 2;\n                    collider.radius = stCollider.Radius * m_MeshSettings.scaleFactor;\n                    collider.height = (vOne - vTwo).magnitude;\n                    collisionObject.transform.LookAt(vTwo);\n                }\n\n                m_Context.AddObjectToAsset(collisionObject.name, collisionObject);\n            }\n        }\n\n        internal float[] GetPerLODSettingsHeights()\n        {\n            float[] heightsArray = new float[m_PerLODSettings.Count];\n\n            for (int i = 0; i < m_PerLODSettings.Count; ++i)\n            {\n                heightsArray[i] = m_PerLODSettings[i].height;\n            }\n\n            return heightsArray;\n        }\n        #endregion\n    }\n\n    // Use a postprocessor to set various settings on the textures since these dont stick during first import.\n    class SpeedTree9Postprocessor : AssetPostprocessor\n    {\n        private static void OnPostprocessAllAssets(\n            string[] importedAssets,\n            string[] deletedAssets,\n            string[] movedAssets,\n            string[] movedFromAssetPaths,\n            bool didDomainReload)\n        {\n            foreach (string assetFilename in importedAssets)\n            {\n                if (Path.GetExtension(assetFilename) == \".st9\")\n                {\n                    try\n                    {\n                        AssetDatabase.StartAssetEditing();\n\n                        ChangeTextureImporterSettingsForSt9Files(assetFilename);\n                    }\n                    finally\n                    {\n                        AssetDatabase.StopAssetEditing();\n                    }\n                }\n            }\n\n            if (didDomainReload)\n            {\n                if (TryGetHashSpeedTreeAttributeMaterialSettings(out List<string> strToHash))\n                {\n                    Hash128 hash = new Hash128();\n\n                    foreach (string str in strToHash)\n                    {\n                        hash.Append(str);\n                    }\n\n                    AssetDatabase.RegisterCustomDependency(ImporterSettings.kMaterialSettingsDependencyname, hash);\n                }\n                else\n                {\n                    AssetDatabase.UnregisterCustomDependencyPrefixFilter(ImporterSettings.kMaterialSettingsDependencyname);\n                }\n            }\n        }\n\n        private static bool TryGetHashSpeedTreeAttributeMaterialSettings(out List<string> strToHash)\n        {\n            var allMethods = AttributeHelper.GetMethodsWithAttribute<MaterialSettingsCallbackAttribute>().methodsWithAttributes;\n\n            strToHash = new List<string>();\n\n            foreach (var method in allMethods)\n            {\n                MaterialSettingsCallbackAttribute attribute = method.attribute as MaterialSettingsCallbackAttribute;\n\n                strToHash.Add($\"{method.info.Name}-{method.info.DeclaringType.AssemblyQualifiedName}-{attribute.MethodVersion.ToString()}\");\n            }\n\n            strToHash.Sort();\n            return strToHash.Count > 0;\n        }\n\n        private static void ChangeTextureImporterSettingsForSt9Files(string assetPath)\n        {\n            SpeedTree9Reader tree = new SpeedTree9Reader();\n\n            FileStatus status = tree.Initialize(assetPath);\n            if (status != FileStatus.Valid)\n            {\n                Debug.LogError($\"Error while initializing the SpeedTree9 reader: {status}.\");\n                return;\n            }\n\n            tree.ReadContent();\n\n            string path = Path.GetDirectoryName(assetPath) + \"/\";\n            for (int matIndex = 0; matIndex < tree.Materials.Length; ++matIndex)\n            {\n                STMaterial stMaterial = tree.Materials[matIndex];\n\n                if (TryGetTextureImporterFromIndex(stMaterial, 0, path, out TextureImporter texImporterColor))\n                    ApplyColorTextureSettings(texImporterColor);\n\n                if (TryGetTextureImporterFromIndex(stMaterial, 1, path, out TextureImporter texImporterNormal))\n                    ApplyNormalTextureSettings(texImporterNormal);\n\n                if (TryGetTextureImporterFromIndex(stMaterial, 2, path, out TextureImporter texImporterExtra))\n                    ApplyExtraTextureSettings(texImporterExtra);\n            }\n        }\n\n        private static bool TryGetTextureImporterFromIndex(\n            STMaterial stMaterial,\n            int index,\n            string directoryPath,\n            out TextureImporter textureImporter)\n        {\n            textureImporter = null;\n\n            if (stMaterial.Maps.Length <= index)\n                return false;\n\n            MaterialMap mat = stMaterial.Maps[index];\n            if (!mat.Used || string.IsNullOrEmpty(mat.Path))\n                return false;\n\n            TextureImporter texImporter = TextureImporter.GetAtPath(directoryPath + mat.Path) as TextureImporter;\n            if (texImporter == null)\n                return false;\n\n            textureImporter = texImporter;\n            return true;\n        }\n\n        private static void ApplyColorTextureSettings(TextureImporter texImporter)\n        {\n            if (texImporter.alphaIsTransparency &&\n                texImporter.mipMapsPreserveCoverage &&\n                texImporter.alphaTestReferenceValue == 0.1f)\n                return;\n\n            texImporter.alphaIsTransparency = true;\n            texImporter.mipMapsPreserveCoverage = true;\n            texImporter.alphaTestReferenceValue = 0.1f;\n\n            EditorUtility.SetDirty(texImporter);\n            texImporter.SaveAndReimport();\n        }\n\n        private static void ApplyNormalTextureSettings(TextureImporter texImporter)\n        {\n            if (texImporter.textureType == TextureImporterType.NormalMap)\n                return;\n\n            texImporter.textureType = TextureImporterType.NormalMap;\n\n            EditorUtility.SetDirty(texImporter);\n            texImporter.SaveAndReimport();\n        }\n\n        private static void ApplyExtraTextureSettings(TextureImporter texImporter)\n        {\n            if (texImporter.sRGBTexture == false)\n                return;\n\n            texImporter.sRGBTexture = false;\n\n            EditorUtility.SetDirty(texImporter);\n            texImporter.SaveAndReimport();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/SpeedTree/SpeedTree9ImporterEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.AssetImporters;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing System;\n\nnamespace UnityEditor.SpeedTree.Importer\n{\n    [CustomEditor(typeof(SpeedTree9Importer))]\n    [CanEditMultipleObjects]\n    internal class SpeedTree9ImporterEditor : AssetImporterTabbedEditor\n    {\n        private static class Styles\n        {\n            public static GUIContent ApplyAndGenerate = EditorGUIUtility.TrTextContent(\"Apply & Generate Materials\", \"Apply current importer settings and generate materials with new settings.\");\n            public static GUIContent Regenerate = EditorGUIUtility.TrTextContent(\"Regenerate Materials\", \"Regenerate materials from the current importer settings.\");\n            public static GUIContent RegenerateRemapped = EditorGUIUtility.TrTextContent(\"Regenerate Materials\", \"Regenerate the remapped materials from the current import settings.\");\n            public static GUIContent ApplyAndGenerateRemapped = EditorGUIUtility.TrTextContent(\"Apply & Generate Materials\", \"Apply current importer settings and regenerate the remapped materials with new settings.\");\n\n            public static readonly string ModelTabName = \"Model\";\n            public static readonly string MaterialsTabName = \"Materials\";\n            public static readonly string WindTabName = \"Wind\";\n        }\n\n        private bool m_HasRemappedMaterials = false;\n        private SpeedTreeImporterOutputData m_OutputImporterData = null;\n        private SpeedTree9Importer m_STImporter = null;\n\n        internal IEnumerable<SpeedTree9Importer> importers\n        {\n            get\n            {\n                SpeedTree9Importer[] st9Importers = new SpeedTree9Importer[targets.Length];\n\n                for (int i = 0; i < targets.Length; ++i)\n                {\n                    st9Importers[i] = targets[i] as SpeedTree9Importer;\n                }\n\n                return st9Importers;\n            }\n        }\n\n        public override void OnEnable()\n        {\n            m_STImporter = target as SpeedTree9Importer;\n\n            if (tabs == null)\n            {\n                tabs = new BaseAssetImporterTabUI[]\n                {\n                    new SpeedTree9ImporterModelEditor(this),\n                    new SpeedTree9ImporterMaterialEditor(this),\n                    new SpeedTree9ImporterWindEditor(this)\n                };\n                m_TabNames = new string[] { Styles.ModelTabName, Styles.MaterialsTabName, Styles.WindTabName };\n            }\n\n            m_OutputImporterData = AssetDatabase.LoadAssetAtPath<SpeedTreeImporterOutputData>(m_STImporter.assetPath);\n            Debug.Assert(m_OutputImporterData != null);\n\n            base.OnEnable();\n        }\n\n        public override void OnDisable()\n        {\n            foreach (var tab in tabs)\n            {\n                tab.OnDisable();\n            }\n            base.OnDisable();\n        }\n\n        // None of the ModelImporter sub editors support multi preview.\n        public override bool HasPreviewGUI()\n        {\n            return base.HasPreviewGUI() && targets.Length < 2;\n        }\n\n        // Only show the imported GameObject when the Model tab is active.\n        public override bool showImportedObject { get { return activeTab is SpeedTree9ImporterModelEditor; } }\n\n        public override GUIContent GetPreviewTitle()\n        {\n            var tab = activeTab as ModelImporterClipEditor;\n            if (tab != null)\n                return new GUIContent(tab.selectedClipName);\n\n            return base.GetPreviewTitle();\n        }\n\n        internal bool upgradeMaterials\n        {\n            get\n            {\n                foreach (var importer in importers)\n                {\n                    if (importer != null && importer.MaterialsShouldBeRegenerated)\n                        return true;\n                }\n                return false;\n            }\n        }\n\n        protected override bool OnApplyRevertGUI()\n        {\n            bool applied = base.OnApplyRevertGUI();\n\n            bool hasModified = HasModified();\n            if (tabs == null) // Hitting apply, we lose the tabs object within base.OnApplyRevertGUI()\n            {\n                if (hasModified)\n                    Apply();\n                return applied;\n            }\n\n            bool doMatsHaveDifferentShaders = (tabs[0] as SpeedTree9ImporterModelEditor).DoMaterialsHaveDifferentShader();\n\n            // We show the \"Generate\" button when we have extracted materials since the user should have 2 choices:\n            // - Apply the importer settings changes on top of the extracted materials (by regenerating them)\n            // - Only apply the importer settings changes to the embedded materials and not the extracted ones,\n            //   since the users might want to be able to keep their own changes without the importer to erase them.\n            m_HasRemappedMaterials = HasRemappedMaterials();\n\n            if (upgradeMaterials || doMatsHaveDifferentShaders || m_HasRemappedMaterials)\n            {\n                // Force material upgrade when a custom render pipeline is active so that render pipeline-specific material\n                // modifications may be applied.\n                bool upgrade = upgradeMaterials || (UnityEngine.Rendering.GraphicsSettings.currentRenderPipeline != null);\n\n                if (GUILayout.Button(GetGenerateButtonText(hasModified, upgrade)))\n                {\n                    // Apply the changes and generate the materials before importing so that asset previews are up-to-date.\n                    if (hasModified)\n                        Apply();\n\n                    if (upgrade)\n                    {\n                        foreach (var importer in importers)\n                        {\n                            importer.SetMaterialsVersionToCurrent();\n                        }\n                    }\n\n                    GenerateMaterials();\n\n                    if (hasModified || upgrade)\n                    {\n                        // Necessary since we remap the newly generated materials to the mesh LOD(s).\n                        SaveChanges();\n                        applied = true;\n                    }\n                }\n            }\n\n            return applied;\n        }\n\n        internal GUIContent GetGenerateButtonText(bool modified, bool upgrade)\n        {\n            if (modified || upgrade)\n            {\n                if (m_HasRemappedMaterials)\n                    return Styles.ApplyAndGenerate;\n                else\n                    return Styles.ApplyAndGenerateRemapped;\n            }\n            else\n            {\n                if (m_HasRemappedMaterials)\n                    return Styles.Regenerate;\n                else\n                    return Styles.RegenerateRemapped;\n            }\n        }\n\n        private bool HasEmbeddedMaterials\n        {\n            get\n            {\n                bool materialsValid = m_OutputImporterData.lodMaterials.materials.Count > 0\n                    && m_OutputImporterData.lodMaterials.materials.TrueForAll(p => p.material != null);\n\n                return m_OutputImporterData.hasEmbeddedMaterials && materialsValid;\n            }\n        }\n\n        private void GenerateMaterials()\n        {\n            List<string> paths = new List<string>();\n            List<string> matFolders = new List<string>();\n            List<SpeedTree9Importer> importersWithEmbeddedMaterials = new List<SpeedTree9Importer>();\n\n            // TODO: Add support for multi-edit.\n            if (HasEmbeddedMaterials)\n            {\n                importersWithEmbeddedMaterials.Add(m_STImporter);\n            }\n\n            foreach (var importer in importersWithEmbeddedMaterials)\n            {\n                var remappedAssets = importer.GetExternalObjectMap();\n\n                List<UnityEngine.Object> materials = new List<UnityEngine.Object>();\n\n                foreach (var asset in remappedAssets)\n                {\n                    if (asset.Value is Material && asset.Value != null)\n                    {\n                        materials.Add(asset.Value);\n                    }\n                }\n\n                foreach (var material in materials)\n                {\n                    string path = AssetDatabase.GetAssetPath(material);\n                    paths.Add(path);\n                    matFolders.Add(FileUtil.DeleteLastPathNameComponent(path));\n                }\n            }\n\n            bool doGenerate = true;\n            if (paths.Count > 0)\n            {\n                doGenerate = AssetDatabase.MakeEditable(paths.ToArray(), $\"Materials will be checked out in:\\n{string.Join(\"\\n\", matFolders.ToArray())}\");\n            }\n\n            if (doGenerate)\n            {\n                foreach (var importer in importers)\n                {\n                    importer.RegenerateMaterials();\n                }\n            }\n        }\n\n        private bool HasRemappedMaterials()\n        {\n            m_HasRemappedMaterials = true;\n\n            if (m_OutputImporterData.materialsIdentifiers.Count == 0)\n                return true;\n\n            // if the m_ExternalObjecs map has any unapplied changes, keep the state of the button as is\n            if (serializedObject.hasModifiedProperties)\n                return m_HasRemappedMaterials;\n\n            m_HasRemappedMaterials = true;\n            foreach (var importer in importers)\n            {\n                var externalObjectMap = importer.GetExternalObjectMap();\n                var materialArray = m_OutputImporterData.materialsIdentifiers.ToArray();// importer.SourceMaterials.ToArray();\n\n                int remappedMaterialCount = 0;\n                foreach (var entry in externalObjectMap)\n                {\n                    if (entry.Key.type == typeof(Material) && Array.Exists(materialArray, x => x.name == entry.Key.name && entry.Value != null))\n                        ++remappedMaterialCount;\n                }\n\n                m_HasRemappedMaterials = m_HasRemappedMaterials && remappedMaterialCount != 0;\n                if (!m_HasRemappedMaterials)\n                    break;\n            }\n            return m_HasRemappedMaterials;\n        }\n    }\n\n    internal abstract class BaseSpeedTree9ImporterTabUI : BaseAssetImporterTabUI\n    {\n        protected SpeedTreeImporterOutputData m_OutputImporterData;\n\n        internal BaseSpeedTree9ImporterTabUI(AssetImporterEditor panelContainer)\n            : base(panelContainer)\n        {\n        }\n        internal override void OnEnable()\n        {\n            TryLoadOutputImporterData();\n        }\n\n        protected IEnumerable<SpeedTree9Importer> importers\n        {\n            get { return (panelContainer as SpeedTree9ImporterEditor).importers; }\n        }\n\n        protected bool upgradeMaterials\n        {\n            get { return (panelContainer as SpeedTree9ImporterEditor).upgradeMaterials; }\n        }\n\n        protected bool TryLoadOutputImporterData()\n        {\n            m_OutputImporterData = null;\n\n            // Doesn't support multi-edit for now.\n            foreach (SpeedTree9Importer importer in importers)\n            {\n                m_OutputImporterData = AssetDatabase.LoadAssetAtPath<SpeedTreeImporterOutputData>(importer.assetPath);\n                break;\n            }\n\n            return m_OutputImporterData != null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/SpeedTree/SpeedTree9ImporterMaterialEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.AssetImporters;\nusing UnityEngine;\n\nnamespace UnityEditor.SpeedTree.Importer\n{\n    class SpeedTree9ImporterMaterialEditor : BaseSpeedTree9ImporterTabUI\n    {\n        private static class Styles\n        {\n            public static GUIContent RemapOptions = EditorGUIUtility.TrTextContent(\"On Demand Remap\");\n            public static GUIContent RemapMaterialsInProject = EditorGUIUtility.TrTextContent(\"Search and Remap...\", \"Click on this button to search and remap the materials from the project.\");\n            public static GUIContent ExternalMaterialMappings = EditorGUIUtility.TrTextContent(\"Remapped Materials\", \"External materials to use for each embedded material.\");\n\n            public static GUIContent Materials = EditorGUIUtility.TrTextContent(\"Materials\");\n            public static GUIContent ExtractEmbeddedMaterials = EditorGUIUtility.TrTextContent(\"Extract Materials...\", \"Click on this button to extract the embedded materials.\");\n\n            public static GUIContent InternalMaterialHelp = EditorGUIUtility.TrTextContent(\"Materials are embedded inside the imported asset.\");\n            public static GUIContent MaterialAssignmentsHelp = EditorGUIUtility.TrTextContent(\"Material assignments can be remapped below.\");\n\n            public static GUIContent ExternalMaterialSearchHelp = EditorGUIUtility.TrTextContent(\"Searches the user provided directory and matches the materials that share the same name and LOD with the originally imported material.\");\n            public static GUIContent SelectMaterialFolder = EditorGUIUtility.TrTextContent(\"Select Materials Folder\");\n        }\n\n        private SpeedTree9Importer m_STImporter;\n        private SerializedProperty m_ExternalObjects;\n\n        private bool m_ShowMaterialRemapOptions;\n        private bool m_HasEmbeddedMaterials;\n\n        private bool ImporterHasEmbeddedMaterials\n        {\n            get\n            {\n                bool materialsValid = m_OutputImporterData.lodMaterials.materials.Count > 0\n                    && m_OutputImporterData.lodMaterials.materials.TrueForAll(p => p.material != null);\n\n                return m_OutputImporterData.hasEmbeddedMaterials && materialsValid;\n            }\n        }\n\n        public SpeedTree9ImporterMaterialEditor(AssetImporterEditor panelContainer)\n            : base(panelContainer)\n        { }\n\n        internal override void OnEnable()\n        {\n            base.OnEnable();\n\n            m_STImporter = target as SpeedTree9Importer;\n\n            m_ExternalObjects = serializedObject.FindProperty(\"m_ExternalObjects\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            ShowMaterialGUI();\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        private bool HasEmbeddedMaterials()\n        {\n            if (m_OutputImporterData.materialsIdentifiers.Count == 0 || !ImporterHasEmbeddedMaterials)\n                return false;\n\n            // if the m_ExternalObjecs map has any unapplied changes, keep the state of the button as is\n            if (m_ExternalObjects.serializedObject.hasModifiedProperties)\n                return m_HasEmbeddedMaterials;\n\n            m_HasEmbeddedMaterials = true;\n            foreach (var t in m_ExternalObjects.serializedObject.targetObjects)\n            {\n                var externalObjectMap = m_STImporter.GetExternalObjectMap();\n                var materialsList = m_OutputImporterData.materialsIdentifiers.ToArray();// m_STImporter.m_Materials.ToArray();\n\n                int remappedMaterialCount = 0;\n                foreach (var entry in externalObjectMap)\n                {\n                    bool isMatValid = Array.Exists(materialsList, x => x.name == entry.Key.name && entry.Value != null);\n                    if (entry.Key.type == typeof(Material) && isMatValid)\n                        ++remappedMaterialCount;\n                }\n\n                m_HasEmbeddedMaterials = m_HasEmbeddedMaterials && remappedMaterialCount != materialsList.Length;\n            }\n            return m_HasEmbeddedMaterials;\n        }\n\n        private void ShowMaterialGUI()\n        {\n            serializedObject.UpdateIfRequiredOrScript();\n\n            string materialHelp = string.Empty;\n            int arraySize = m_OutputImporterData.materialsIdentifiers.Count;\n\n            if (arraySize > 0 && HasEmbeddedMaterials())\n            {\n                // we're generating materials inside the prefab\n                materialHelp = Styles.InternalMaterialHelp.text;\n            }\n            \n            if (targets.Length == 1 && arraySize > 0)\n            {\n                materialHelp += \" \" + Styles.MaterialAssignmentsHelp.text;\n            }\n\n            if (ExtractMaterialsGUI())\n            {\n                // Necessary to avoid the error \"BeginLayoutGroup must be called first\".\n                GUIUtility.ExitGUI();\n                return;\n            }\n            \n            if (!string.IsNullOrEmpty(materialHelp))\n            {\n                EditorGUILayout.HelpBox(materialHelp, MessageType.Info);\n            }\n\n            // The material remap list\n            if (targets.Length == 1 && arraySize > 0)\n            {\n                GUILayout.Label(Styles.ExternalMaterialMappings, EditorStyles.boldLabel);\n\n                if (MaterialRemapOptions())\n                    return;\n\n                // The list of material names is immutable, whereas the map of external objects can change based on user actions.\n                // For each material name, map the external object associated with it.\n                // The complexity comes from the fact that we may not have an external object in the map, so we can't make a property out of it\n                for (int materialIdx = 0; materialIdx < arraySize; ++materialIdx)\n                {\n                    string name = m_OutputImporterData.materialsIdentifiers[materialIdx].name;\n                    string type = m_OutputImporterData.materialsIdentifiers[materialIdx].type;\n\n                    SerializedProperty materialProp = null;\n                    Material material = null;\n                    int propertyIdx = 0;\n\n                    for (int externalObjectIdx = 0, count = m_ExternalObjects.arraySize; externalObjectIdx < count; ++externalObjectIdx)\n                    {\n                        SerializedProperty pair = m_ExternalObjects.GetArrayElementAtIndex(externalObjectIdx);\n                        string externalName = pair.FindPropertyRelative(\"first.name\").stringValue;\n                        string externalType = pair.FindPropertyRelative(\"first.type\").stringValue;\n\n                        // Cannot do a strict comparison, since externalType is set to \"UnityEngine:Material\" (C++)\n                        // and type \"UnityEngine.Material\" (C#).\n                        bool typeMatching = externalType.Contains(\"Material\") && type.Contains(\"Material\");\n\n                        if (externalName == name && typeMatching)\n                        {\n                            materialProp = pair.FindPropertyRelative(\"second\");\n                            material = materialProp != null ? materialProp.objectReferenceValue as Material : null;\n\n                            // If 'material' is null, it's likely because it was deleted. So we assign null to 'materialProp'\n                            // to avoid the 'missing material' reference error in the UI.\n                            materialProp = (material != null) ? pair.FindPropertyRelative(\"second\") : null;\n                            propertyIdx = externalObjectIdx;\n                            break;\n                        }\n                    }\n\n                    GUIContent nameLabel = EditorGUIUtility.TextContent(name);\n                    nameLabel.tooltip = name;\n                    if (materialProp != null)\n                    {\n                        EditorGUI.BeginChangeCheck();\n                        EditorGUILayout.ObjectField(materialProp, typeof(Material), nameLabel);\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            if (materialProp.objectReferenceValue == null)\n                            {\n                                m_ExternalObjects.DeleteArrayElementAtIndex(propertyIdx);\n                            }\n                        }\n                    }\n                    else\n                    {\n                        EditorGUI.BeginChangeCheck();\n                        material = EditorGUILayout.ObjectField(nameLabel, material, typeof(Material), false) as Material;\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            if (material != null)\n                            {\n                                int newIndex = m_ExternalObjects.arraySize++;\n                                SerializedProperty pair = m_ExternalObjects.GetArrayElementAtIndex(newIndex);\n                                pair.FindPropertyRelative(\"first.name\").stringValue = name;\n                                pair.FindPropertyRelative(\"first.type\").stringValue = type;\n                                pair.FindPropertyRelative(\"second\").objectReferenceValue = material;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        private bool ExtractMaterialsGUI()\n        {\n            bool buttonPressed = false;\n\n            EditorGUILayout.BeginHorizontal();\n            {\n                EditorGUILayout.PrefixLabel(Styles.Materials);\n                using (new EditorGUI.DisabledScope(!HasEmbeddedMaterials()))\n                {\n                    buttonPressed = GUILayout.Button(Styles.ExtractEmbeddedMaterials);\n\n                    if (buttonPressed)\n                    {\n                        // use the first target for selecting the destination folder, but apply that path for all targets\n                        string destinationPath = m_STImporter.assetPath;\n                        destinationPath = EditorUtility.SaveFolderPanel(Styles.SelectMaterialFolder.text,\n                            FileUtil.DeleteLastPathNameComponent(destinationPath), \"\");\n                        if (string.IsNullOrEmpty(destinationPath))\n                        {\n                            // Cancel the extraction if the user did not select a folder.\n                            EditorGUILayout.EndHorizontal();\n                            return buttonPressed;\n                        }\n                        destinationPath = FileUtil.GetProjectRelativePath(destinationPath);\n\n                        try\n                        {\n                            // batch the extraction of the materials\n                            AssetDatabase.StartAssetEditing();\n\n                            PrefabUtility.ExtractMaterialsFromAsset(targets, destinationPath);\n                        }\n                        finally\n                        {\n                            AssetDatabase.StopAssetEditing();\n                        }\n                    }\n                }\n            }\n            EditorGUILayout.EndHorizontal();\n\n            // AssetDatabase.StopAssetEditing() invokes OnEnable(), which invalidates all the serialized properties, so we must return.\n            return buttonPressed;\n        }\n\n        private bool MaterialRemapOptions()\n        {\n            bool buttonPressed = false;\n\n            m_ShowMaterialRemapOptions = EditorGUILayout.Foldout(m_ShowMaterialRemapOptions, Styles.RemapOptions);\n            if (m_ShowMaterialRemapOptions)\n            {\n                EditorGUI.indentLevel++;\n\n                EditorGUILayout.HelpBox(Styles.ExternalMaterialSearchHelp.text, MessageType.Info);\n\n                EditorGUI.indentLevel--;\n\n                using (new EditorGUILayout.HorizontalScope())\n                {\n                    GUILayout.FlexibleSpace();\n                    using (new EditorGUI.DisabledScope(assetTarget == null))\n                    {\n                        buttonPressed = GUILayout.Button(Styles.RemapMaterialsInProject);\n                        if (buttonPressed)\n                        {\n                            bool bStartedAssetEditing = false;\n                            try\n                            {\n                                foreach (var t in targets)\n                                {\n                                    string folderToSearch = m_STImporter.GetMaterialFolderPath();\n                                    folderToSearch = EditorUtility.OpenFolderPanel(Styles.SelectMaterialFolder.text, folderToSearch, \"\");\n\n                                    bool bUserSelectedAFolder = folderToSearch != \"\"; // folderToSearch is empty if the user cancels the window\n                                    if (bUserSelectedAFolder)\n                                    {\n                                        string projectRelativePath = FileUtil.GetProjectRelativePath(folderToSearch);\n                                        bool bRelativePathIsNotEmpty = projectRelativePath != \"\";\n                                        if (bRelativePathIsNotEmpty)\n                                        {\n                                            AssetDatabase.StartAssetEditing();\n                                            bStartedAssetEditing = true;\n                                            m_STImporter.SearchAndRemapMaterials(projectRelativePath);\n\n                                            AssetDatabase.WriteImportSettingsIfDirty(m_STImporter.assetPath);\n                                            AssetDatabase.ImportAsset(m_STImporter.assetPath, ImportAssetOptions.ForceUpdate);\n                                        }\n                                        else\n                                        {\n                                            Debug.LogWarning(\"Selected folder is outside of the project's folder hierarchy, please provide a folder from the project.\\n\");\n                                        }\n                                    }\n                                }\n                            }\n                            finally\n                            {\n                                if (bStartedAssetEditing)\n                                {\n                                    AssetDatabase.StopAssetEditing();\n                                }\n                            }\n                        }\n                    }\n                }\n                EditorGUILayout.Space();\n            }\n\n            return buttonPressed;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/SpeedTree/SpeedTree9ImporterModelEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.AssetImporters;\nusing System;\nusing UnityEditor.AnimatedValues;\nusing UnityEngine;\nusing System.IO;\nusing System.Collections.Generic;\nusing static UnityEditor.SpeedTree.Importer.SpeedTree9Importer;\n\nusing Styles = UnityEditor.SpeedTree.Importer.SpeedTreeImporterCommonEditor.Styles;\n\nnamespace UnityEditor.SpeedTree.Importer\n{\n    class SpeedTree9ImporterModelEditor : BaseSpeedTree9ImporterTabUI\n    {\n        // Mesh properties\n        private SerializedProperty m_UnitConversion;\n        private SerializedProperty m_ScaleFactor;\n\n        // Material properties\n        private SerializedProperty m_MainColor;\n        private SerializedProperty m_EnableHueVariation;\n        private SerializedProperty m_HueVariation;\n        private SerializedProperty m_AlphaClipThreshold;\n        private SerializedProperty m_TransmissionScale;\n        private SerializedProperty m_EnableBumpMapping;\n        private SerializedProperty m_EnableSubsurfaceScattering;\n        private SerializedProperty m_DiffusionProfileAssetID;\n        private SerializedProperty m_DiffusionProfileID;\n\n        // Lighting properties\n        private SerializedProperty m_EnableShadowCasting;\n        private SerializedProperty m_EnableShadowReceiving;\n        private SerializedProperty m_EnableLightProbes;\n        private SerializedProperty m_ReflectionProbeEnumValue;\n\n        // Additional Settings properties\n        private SerializedProperty m_MotionVectorModeEnumValue;\n        private SerializedProperty m_GenerateColliders;\n        private SerializedProperty m_GenerateRigidbody;\n\n        // LOD properties\n        private SerializedProperty m_EnableSmoothLOD;\n        private SerializedProperty m_AnimateCrossFading;\n        private SerializedProperty m_BillboardTransitionCrossFadeWidth;\n        private SerializedProperty m_FadeOutWidth;\n        private SerializedProperty m_PerLODSettings;\n\n        // LODGroup GUI\n        private int m_SelectedLODSlider = -1;\n        private int m_SelectedLODRange = 0;\n        private SavedBool[] m_LODGroupFoldoutHeaderValues = null;\n        private Texture2D[] m_LODColorTextures;\n\n        private AnimBool m_ShowSmoothLODOptions = new AnimBool();\n        private AnimBool m_ShowCrossFadeWidthOptions = new AnimBool();\n\n        private SpeedTree9Importer m_StEditor;\n\n        public SpeedTree9ImporterModelEditor(AssetImporterEditor panelContainer)\n            : base(panelContainer)\n        { }\n\n        internal override void OnEnable()\n        {\n            base.OnEnable();\n\n            m_StEditor = target as SpeedTree9Importer;\n\n            // Mesh properties\n            {\n                MeshSettings meshSettings = m_StEditor.m_MeshSettings;\n                string meshSettingsStr = nameof(m_StEditor.m_MeshSettings);\n\n                m_UnitConversion = FindPropertyFromName(meshSettingsStr, nameof(meshSettings.unitConversion));\n                m_ScaleFactor = FindPropertyFromName(meshSettingsStr, nameof(meshSettings.scaleFactor));\n            }\n\n            // Material properties\n            {\n                MaterialSettings matSettings = m_StEditor.m_MaterialSettings;\n                string matSettingsStr = nameof(m_StEditor.m_MaterialSettings);\n\n                m_MainColor = FindPropertyFromName(matSettingsStr, nameof(matSettings.mainColor));\n                m_EnableHueVariation = FindPropertyFromName(matSettingsStr, nameof(matSettings.enableHueVariation));\n                m_HueVariation = FindPropertyFromName(matSettingsStr, nameof(matSettings.hueVariation));\n                m_AlphaClipThreshold = FindPropertyFromName(matSettingsStr, nameof(matSettings.alphaClipThreshold));\n                m_TransmissionScale = FindPropertyFromName(matSettingsStr, nameof(matSettings.transmissionScale));\n                m_EnableBumpMapping = FindPropertyFromName(matSettingsStr, nameof(matSettings.enableBumpMapping));\n                m_EnableSubsurfaceScattering = FindPropertyFromName(matSettingsStr, nameof(matSettings.enableSubsurfaceScattering));\n\n                m_DiffusionProfileAssetID = FindPropertyFromName(matSettingsStr, nameof(matSettings.diffusionProfileAssetID));\n                m_DiffusionProfileID = FindPropertyFromName(matSettingsStr, nameof(matSettings.diffusionProfileID));\n            }\n\n            // Lighting properties\n            {\n                LightingSettings lightSettings = m_StEditor.m_LightingSettings;\n                string lightSettingsStr = nameof(m_StEditor.m_LightingSettings);\n\n                m_EnableShadowCasting = FindPropertyFromName(lightSettingsStr, nameof(lightSettings.enableShadowCasting));\n                m_EnableShadowReceiving = FindPropertyFromName(lightSettingsStr, nameof(lightSettings.enableShadowReceiving));\n                m_EnableLightProbes = FindPropertyFromName(lightSettingsStr, nameof(lightSettings.enableLightProbes));\n                m_ReflectionProbeEnumValue = FindPropertyFromName(lightSettingsStr, nameof(lightSettings.reflectionProbeEnumValue));\n            }\n\n            // Additional Settings properties\n            {\n                AdditionalSettings addSettings = m_StEditor.m_AdditionalSettings;\n                string addSettingsStr = nameof(m_StEditor.m_AdditionalSettings);\n\n                m_MotionVectorModeEnumValue = FindPropertyFromName(addSettingsStr, nameof(addSettings.motionVectorModeEnumValue));\n                m_GenerateColliders = FindPropertyFromName(addSettingsStr, nameof(addSettings.generateColliders));\n                m_GenerateRigidbody = FindPropertyFromName(addSettingsStr, nameof(addSettings.generateRigidbody));\n            }\n\n            // LOD properties\n            {\n                LODSettings lodSettings = m_StEditor.m_LODSettings;\n                string lodSettingsStr = nameof(m_StEditor.m_LODSettings);\n\n                m_EnableSmoothLOD = FindPropertyFromName(lodSettingsStr, nameof(lodSettings.enableSmoothLODTransition));\n                m_AnimateCrossFading = FindPropertyFromName(lodSettingsStr, nameof(lodSettings.animateCrossFading));\n                m_BillboardTransitionCrossFadeWidth = FindPropertyFromName(lodSettingsStr, nameof(lodSettings.billboardTransitionCrossFadeWidth));\n                m_FadeOutWidth = FindPropertyFromName(lodSettingsStr, nameof(lodSettings.fadeOutWidth));\n                m_PerLODSettings = serializedObject.FindProperty(nameof(m_StEditor.m_PerLODSettings));\n            }\n\n            // Other\n            {\n                m_ShowSmoothLODOptions.value = m_EnableSmoothLOD.hasMultipleDifferentValues || m_EnableSmoothLOD.boolValue;\n                m_ShowSmoothLODOptions.valueChanged.AddListener(Repaint);\n\n                m_ShowCrossFadeWidthOptions.value = m_AnimateCrossFading.hasMultipleDifferentValues || !m_AnimateCrossFading.boolValue;\n                m_ShowCrossFadeWidthOptions.valueChanged.AddListener(Repaint);\n            }\n\n            ResetFoldoutLists();\n        }\n\n        internal override void OnDisable()\n        {\n            base.OnDisable();\n\n            m_ShowSmoothLODOptions.valueChanged.RemoveListener(Repaint);\n            m_ShowCrossFadeWidthOptions.valueChanged.RemoveListener(Repaint);\n        }\n\n        void TriggerCallbacks()\n        {\n            var allMethods = AttributeHelper.GetMethodsWithAttribute<DiffuseProfileCallbackAttribute>().methodsWithAttributes;\n            foreach (var method in allMethods)\n            {\n                var callback = Delegate.CreateDelegate(typeof(OnCustomEditorSettings), method.info) as OnCustomEditorSettings;\n                callback?.Invoke(ref m_DiffusionProfileAssetID, ref m_DiffusionProfileID);\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            // Mesh properties\n            SpeedTreeImporterCommonEditor.ShowMeshGUI(ref m_UnitConversion, ref m_ScaleFactor);\n\n            EditorGUILayout.Space();\n\n            // Material Properties\n            SpeedTreeImporterCommonEditor.ShowMaterialGUI(\n                ref m_MainColor,\n                ref m_EnableHueVariation,\n                ref m_HueVariation,\n                ref m_AlphaClipThreshold,\n                ref m_EnableBumpMapping,\n                ref m_EnableSubsurfaceScattering,\n                renderHueVariationDropdown: m_EnableHueVariation.boolValue,\n                renderAlphaTestRef: m_OutputImporterData.hasAlphaClipThreshold\n                );\n\n            if (m_OutputImporterData.hasTransmissionScale)\n            {\n                EditorGUILayout.PropertyField(m_TransmissionScale, Styles.TransmissionScale);\n            }\n\n            // Update the Diffuse Profile is necessary\n            TriggerCallbacks();\n\n            EditorGUILayout.Space();\n\n            // Lighting Properties\n            SpeedTreeImporterCommonEditor.ShowLightingGUI(\n                ref m_EnableShadowCasting,\n                ref m_EnableShadowReceiving,\n                ref m_EnableLightProbes,\n                ref m_ReflectionProbeEnumValue);\n\n            EditorGUILayout.Space();\n\n            // Additional Settings\n            SpeedTreeImporterCommonEditor.ShowAdditionalSettingsGUI(\n                ref m_MotionVectorModeEnumValue,\n                ref m_GenerateColliders,\n                ref m_GenerateRigidbody);\n\n            EditorGUILayout.Space();\n\n            // LOD properties\n            SpeedTreeImporterCommonEditor.ShowLODGUI(\n                ref m_EnableSmoothLOD,\n                ref m_AnimateCrossFading,\n                ref m_BillboardTransitionCrossFadeWidth,\n                ref m_FadeOutWidth,\n                ref m_ShowSmoothLODOptions,\n                ref m_ShowCrossFadeWidthOptions);\n\n            EditorGUILayout.Space();\n\n            ShowLODGUI();\n\n            ShowMaterialWarnings();\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        private void ShowMaterialWarnings()\n        {\n            EditorGUILayout.Space();\n\n            bool materialsNeedToBeUpgraded = upgradeMaterials;\n\n            if (materialsNeedToBeUpgraded)\n            {\n                EditorGUILayout.HelpBox(\n                    String.Format(\"SpeedTree materials need to be upgraded. \" +\n                    \"Please back them up (if modified manually) then hit the \\\"{0}\\\" button below.\", Styles.ApplyAndGenerate.text)\n                    , MessageType.Warning\n                );\n            }\n            else if (!materialsNeedToBeUpgraded && DoMaterialsHaveDifferentShader())\n            {\n                EditorGUILayout.HelpBox(\n                    String.Format(\"There is a different SpeedTree shader provided by the current render pipeline \" +\n                    \"which probably is more suitable for rendering. Hit the \\\"{0}\\\" button to regenerate the materials.\"\n                        , (panelContainer as SpeedTree9ImporterEditor).GetGenerateButtonText(HasModified()\n                        , materialsNeedToBeUpgraded).text\n                    )\n                    , MessageType.Warning\n                );\n            }\n        }\n\n        private SerializedProperty FindPropertyFromName(string parentProperty, string childProperty)\n        {\n            const string dotStr = \".\";\n\n            string finalName = String.Concat(parentProperty, dotStr, childProperty);\n\n            return serializedObject.FindProperty(finalName);\n        }\n\n        internal bool DoMaterialsHaveDifferentShader()\n        {\n            if (assetTargets is null || assetTargets.Length == 0)\n            {\n                return false;\n            }\n\n            GameObject[] prefabs = new GameObject[assetTargets.Length];\n            for (int i = 0; i < assetTargets.Length; ++i)\n            {\n                prefabs[i] = assetTargets[i] as GameObject;\n            }\n\n            List<SpeedTree9Importer> importerArray = new List<SpeedTree9Importer>();\n            foreach (SpeedTree9Importer importer in importers)\n            {\n                importerArray.Add(importer);\n            }\n\n            string defaultShaderName = String.Empty;\n            if (TryGetShaderForCurrentRenderPipeline(out var shader))\n            {\n                defaultShaderName = shader.name;\n            }\n            else\n            {\n                Debug.LogWarning(\"SpeedTree9 shader is invalid, cannot create Materials for this SpeedTree asset.\");\n            }\n\n            // In tests assetTargets can become null\n            for (int i = 0; i < Math.Min(importerArray.Count, prefabs?.Length ?? 0); ++i)\n            {\n                foreach (var mr in prefabs[i].transform.GetComponentsInChildren<MeshRenderer>())\n                {\n                    foreach (var mat in mr.sharedMaterials)\n                    {\n                        if (mat?.shader.name != defaultShaderName)\n                            return true;\n                    }\n                }\n            }\n\n            return false;\n        }\n\n        // TODO: Abstract the following code, so it can be shared between ST8 and ST9.\n\n        private void ShowLODGUI()\n        {\n            // LOD slider + Customizations\n            if (HasSameLODConfig())\n            {\n                var area = GUILayoutUtility.GetRect(0, LODGroupGUI.kSliderBarHeight, GUILayout.ExpandWidth(true));\n                var lods = GetLODInfoArray(area);\n                bool bDrawLODCustomizationGUI = m_SelectedLODRange != -1 && lods.Count > 0;\n\n                EditorGUILayout.Space();\n\n                DrawLODLevelSlider(area, lods);\n\n                if (bDrawLODCustomizationGUI)\n                {\n                    GUILayout.Space(5);\n                    DrawLODGroupFoldouts(lods);\n                }\n            }\n\n            //  Mixed Value LOD Slider\n            else\n            {\n                if (CanUnifyLODConfig())\n                {\n                    EditorGUILayout.BeginHorizontal();\n                    GUILayout.FlexibleSpace();\n                    Rect buttonRect = GUILayoutUtility.GetRect(Styles.ResetLOD, EditorStyles.miniButton);\n                    if (GUI.Button(buttonRect, Styles.ResetLOD, EditorStyles.miniButton))\n                    {\n                        var dropDownMenu = new GenericMenu();\n                        foreach (SpeedTree9Importer importer in importers)\n                        {\n                            float[] heights = importer.GetPerLODSettingsHeights();\n                            string[] heightsFormated = new string[heights.Length];\n                            for (int i = 0; i < heights.Length; ++i)\n                            {\n                                heightsFormated[i] = string.Format(\"{0:0}%\", heights[i] * 100);\n                            }\n\n                            var menuText = String.Format(\"{0}: {1}\",\n                                Path.GetFileNameWithoutExtension(importer.assetPath),\n                                String.Join(\" | \", heightsFormated));\n                            dropDownMenu.AddItem(new GUIContent(menuText), false, OnResetLODMenuClick, importer);\n                        }\n                        dropDownMenu.DropDown(buttonRect);\n                    }\n                    EditorGUILayout.EndHorizontal();\n                }\n                else\n                {\n                    EditorGUILayout.HelpBox(Styles.MultiSelectionLODNotSupported.text, MessageType.Info);\n                }\n            }\n\n            EditorGUILayout.Space();\n        }\n\n        private readonly int m_LODSliderId = \"LODSliderIDHash\".GetHashCode();\n\n        private void DrawLODLevelSlider(Rect sliderPosition, List<LODGroupGUI.LODInfo> lods)\n        {\n            int sliderId = GUIUtility.GetControlID(m_LODSliderId, FocusType.Passive);\n            Event evt = Event.current;\n\n            switch (evt.GetTypeForControl(sliderId))\n            {\n                case EventType.Repaint:\n                    {\n                        LODGroupGUI.DrawLODSlider(sliderPosition, lods, m_SelectedLODRange);\n                        break;\n                    }\n                case EventType.MouseDown:\n                    {\n                        // Slightly grow position on the x because edge buttons overflow by 5 pixels\n                        var barPosition = sliderPosition;\n                        barPosition.x -= 5;\n                        barPosition.width += 10;\n\n                        if (barPosition.Contains(evt.mousePosition))\n                        {\n                            evt.Use();\n                            GUIUtility.hotControl = sliderId;\n\n                            // Check for button click\n                            var clickedButton = false;\n\n                            // case:464019 have to re-sort the LOD array for these buttons to get the overlaps in the right order...\n                            List<LODGroupGUI.LODInfo> lodsLeft = new List<LODGroupGUI.LODInfo>();\n                            List<LODGroupGUI.LODInfo> lodsRight = new List<LODGroupGUI.LODInfo>();\n\n                            foreach (LODGroupGUI.LODInfo lodInfo in lods)\n                            {\n                                if (lodInfo.ScreenPercent > 0.5f)\n                                {\n                                    lodsLeft.Add(lodInfo);\n                                }\n                                else\n                                {\n                                    lodsRight.Add(lodInfo);\n                                }\n                            }\n\n                            // Descending order.\n                            lodsLeft.Sort(new Comparison<LODGroupGUI.LODInfo>((i1, i2) => i2.LODLevel.CompareTo(i1.LODLevel)));\n\n                            // Ascending order.\n                            lodsRight.Sort(new Comparison<LODGroupGUI.LODInfo>((i1, i2) => i1.LODLevel.CompareTo(i2.LODLevel)));\n\n                            var lodButtonOrder = new List<LODGroupGUI.LODInfo>();\n                            lodButtonOrder.AddRange(lodsLeft);\n                            lodButtonOrder.AddRange(lodsRight);\n\n                            foreach (var lod in lodButtonOrder)\n                            {\n                                if (lod.m_ButtonPosition.Contains(evt.mousePosition))\n                                {\n                                    m_SelectedLODSlider = lod.LODLevel;\n                                    m_SelectedLODRange = lod.LODLevel;\n                                    clickedButton = true;\n                                    break;\n                                }\n                            }\n\n                            if (!clickedButton)\n                            {\n                                // Check for range click\n                                foreach (var lod in lodButtonOrder)\n                                {\n                                    if (lod.m_RangePosition.Contains(evt.mousePosition))\n                                    {\n                                        m_SelectedLODSlider = -1;\n                                        m_SelectedLODRange = lod.LODLevel;\n                                        ExpandSelectedHeaderAndCloseRemaining(m_SelectedLODRange);\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                        break;\n                    }\n                case EventType.MouseUp:\n                    {\n                        if (GUIUtility.hotControl == sliderId)\n                        {\n                            GUIUtility.hotControl = 0;\n                            evt.Use();\n                        }\n                        break;\n                    }\n                case EventType.MouseDrag:\n                    {\n                        if (GUIUtility.hotControl == sliderId && m_SelectedLODSlider >= 0 && lods[m_SelectedLODSlider] != null)\n                        {\n                            evt.Use();\n\n                            var cameraPercent = LODGroupGUI.GetCameraPercent(evt.mousePosition, sliderPosition);\n                            // Bias by 0.1% so that there is no skipping when sliding\n                            LODGroupGUI.SetSelectedLODLevelPercentage(cameraPercent - 0.001f, m_SelectedLODSlider, lods);\n                            m_PerLODSettings.GetArrayElementAtIndex(m_SelectedLODSlider).FindPropertyRelative(\"height\").floatValue = lods[m_SelectedLODSlider].RawScreenPercent;\n                        }\n                        break;\n                    }\n            }\n        }\n\n        private void DrawLODGroupFoldouts(List<LODGroupGUI.LODInfo> lods)\n        {\n            // check camera and bail if null\n            Camera camera = null;\n            if (SceneView.lastActiveSceneView && SceneView.lastActiveSceneView.camera)\n                camera = SceneView.lastActiveSceneView.camera;\n            if (camera == null)\n                return;\n\n            // draw lod foldouts\n            for (int i = 0; i < m_PerLODSettings.arraySize; i++)\n            {\n                DrawLODGroupFoldout(camera, i, ref m_LODGroupFoldoutHeaderValues[i], lods);\n            }\n        }\n\n        private string GetLODSubmeshAndTriCountLabel(int numLODs, int lodGroupIndex, SpeedTree9Importer im, LODGroup lodGroup)\n        {\n            LOD[] lods = lodGroup.GetLODs();\n\n            if(lods.Length != numLODs)\n            {\n                Debug.LogWarningFormat(\"Number of LODs mismatch between serialized object & LODGroup: {0}\\nPlease re-import the asset and kindly report a bug if this warning keeps coming back.\", im.assetPath);\n                numLODs = lods.Length;\n            }\n\n            int[][] primitiveCounts = new int[numLODs][];\n            int[] submeshCounts = new int[numLODs];\n            for (int i = 0; i < lods.Length; i++)\n            {\n                Renderer[] renderers = lods[i].renderers;\n                primitiveCounts[i] = new int[renderers.Length];\n\n                for (int j = 0; j < renderers.Length; j++)\n                {\n                    bool hasMismatchingSubMeshTopologyTypes = LODGroupEditor.CheckIfMeshesHaveMatchingTopologyTypes(renderers);\n\n                    Mesh rendererMesh = LODGroupEditor.GetMeshFromRendererIfAvailable(renderers[j]);\n                    if (rendererMesh == null)\n                        continue;\n\n                    submeshCounts[i] += rendererMesh.subMeshCount;\n\n                    if (hasMismatchingSubMeshTopologyTypes)\n                    {\n                        primitiveCounts[i][j] = rendererMesh.vertexCount;\n                    }\n                    else\n                    {\n                        for (int subMeshIndex = 0; subMeshIndex < rendererMesh.subMeshCount; subMeshIndex++)\n                        {\n                            primitiveCounts[i][j] += (int)rendererMesh.GetIndexCount(subMeshIndex) / 3;\n                        }\n                    }\n                }\n            }\n\n            int totalTriCount = 0;\n            if (primitiveCounts.Length > 0 && primitiveCounts[lodGroupIndex] != null)\n            {\n                Array.ForEach(primitiveCounts[lodGroupIndex], delegate (int i) { totalTriCount += i; });\n            }\n\n            int sumPrimitiveCounts = 0;\n            Array.ForEach(primitiveCounts[0], delegate (int i) { sumPrimitiveCounts += i; });\n\n            int lod0TriCount = sumPrimitiveCounts;\n\n            var triCountChange = lod0TriCount != 0 ? (float)totalTriCount / lod0TriCount * 100 : 0;\n            string triangleChangeLabel = lodGroupIndex > 0 && lod0TriCount != 0 ? $\"({triCountChange.ToString(\"f2\")}% LOD0)\" : \"\";\n\n            bool wideInspector = Screen.width >= 480;\n            triangleChangeLabel = wideInspector ? triangleChangeLabel : \"\";\n            string submeshCountLabel = wideInspector ? $\"- {submeshCounts[lodGroupIndex]} Sub Mesh(es)\" : \"\";\n\n            return $\"{totalTriCount} {LODGroupGUI.GUIStyles.m_TriangleCountLabel.text} {triangleChangeLabel} {submeshCountLabel}\";\n        }\n\n        private Color GetLODGroupColor(int lodIndex)\n        {\n            return LODGroupGUI.kLODColors[lodIndex % LODGroupGUI.kLODColors.Length];\n        }\n\n        private void DrawLODGroupFoldout(Camera camera, int lodGroupIndex, ref SavedBool foldoutState, List<LODGroupGUI.LODInfo> lodInfoList)\n        {\n            GameObject[] ObjectArrayToGameObjectArray(UnityEngine.Object[] objects)\n            {\n                if (objects == null)\n                    return null;\n\n                GameObject[] gameObjects = new GameObject[objects.Length];\n\n                for (int i = 0; i < objects.Length; ++i)\n                {\n                    gameObjects[i] = objects[i] as GameObject;\n                }\n\n                return gameObjects;\n            }\n\n            List<SpeedTree9Importer> importersList = new List<SpeedTree9Importer>(importers);\n\n            GameObject[] prefabs = ObjectArrayToGameObjectArray(assetTargets); // In tests assetTargets can become null\n            SpeedTree9Importer[] importerArray = importersList.ToArray();\n\n            int numSelectedAssets = Math.Min(importerArray.Length, prefabs?.Length ?? 0);\n            bool isDrawingSelectedLODGroup = m_SelectedLODRange == lodGroupIndex;\n\n            // even though multiple assets may be selected, this code path\n            // ensures the numLODs match for all the selected assets (see HasSameLODConfig() calls)\n            int numLODs = m_PerLODSettings.arraySize;\n            bool hasBillboard = m_OutputImporterData.hasBillboard;\n\n            string LODFoldoutHeaderLabel = (hasBillboard && lodGroupIndex == m_PerLODSettings.arraySize - 1)\n                ? \"Billboard\"\n                : $\"LOD {lodGroupIndex}\";\n\n            // primitive and submesh counts are displayed only when a single asset is selected\n            string LODFoldoutHeaderGroupAdditionalText = numSelectedAssets == 1\n                ? GetLODSubmeshAndTriCountLabel(numLODs, lodGroupIndex, importerArray[0], prefabs[0].GetComponentInChildren<LODGroup>())\n                : \"\";\n\n            // ------------------------------------------------------------------------------------------------------------------------------\n\n            if (isDrawingSelectedLODGroup)\n                LODGroupGUI.DrawRoundedBoxAroundLODDFoldout(lodGroupIndex, m_SelectedLODRange);\n            else\n                EditorGUILayout.BeginVertical(EditorStyles.helpBox);\n\n            foldoutState.value = LODGroupGUI.FoldoutHeaderGroupInternal(\n                GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebarFlat)\n                , foldoutState.value\n                , LODFoldoutHeaderLabel\n                , m_LODColorTextures[lodGroupIndex]\n                , GetLODGroupColor(lodGroupIndex) * 0.6f // 0.5f magic number is copied from LODGroupsGUI.cs\n                , LODFoldoutHeaderGroupAdditionalText\n            );\n\n            if (foldoutState.value) // expanded LOD-specific options panel\n            {\n                DrawLODSettingCustomizationGUI(lodInfoList, lodGroupIndex);\n            }\n\n            if (isDrawingSelectedLODGroup)\n                GUILayoutUtility.EndLayoutGroup();\n            else\n                EditorGUILayout.EndVertical();\n        }\n\n        private void DrawLODSettingCustomizationGUI(List<LODGroupGUI.LODInfo> lods, int lodIndex)\n        {\n            bool isBillboard = (lodIndex == lods.Count - 1) && m_OutputImporterData.hasBillboard;\n\n            SerializedProperty selectedLODProp = m_PerLODSettings.GetArrayElementAtIndex(lodIndex);\n            SerializedProperty lodSettingOverride = selectedLODProp.FindPropertyRelative(\"enableSettingOverride\");\n\n            // We don't want to clutter the GUI with same options but for billboards, instead\n            // we treat the Billboard LOD level as always 'overrideSettings' and display the\n            // billboard options below without the 'enableSettingOverride' warning text.\n            if (isBillboard)\n            {\n                EditorGUILayout.LabelField(\"Billboard Options\", EditorStyles.boldLabel);\n                EditorGUILayout.HelpBox(Styles.BillboardSettingsHelp.text, MessageType.Info);\n            }\n            else\n            {\n                // Toggle\n                GUIContent customizationLabel = EditorGUIUtility.TrTextContent(String.Format(\"Customize {0} options\", lods[lodIndex].LODName), \"To override options for a certain LOD, check this box and select the LOD from the LOD slider above\");\n                EditorGUILayout.PropertyField(lodSettingOverride, customizationLabel);\n\n                // Warning\n                if (lodSettingOverride.boolValue)\n                {\n                    EditorGUILayout.HelpBox(Styles.EnableLodCustomizationsWarn.text, MessageType.Warning);\n                }\n            }\n            EditorGUILayout.Space();\n\n            // settings\n            using (new EditorGUI.DisabledScope(!lodSettingOverride.boolValue))\n            {\n                EditorGUILayout.Space();\n                EditorGUILayout.LabelField(\"Lighting\", EditorStyles.boldLabel);\n                EditorGUILayout.PropertyField(selectedLODProp.FindPropertyRelative(\"castShadows\"), Styles.CastShadows);\n\n                using (new EditorGUI.DisabledScope(!UnityEngine.Rendering.SupportedRenderingFeatures.active.receiveShadows))\n                {\n                    EditorGUILayout.PropertyField(selectedLODProp.FindPropertyRelative(\"receiveShadows\"), Styles.ReceiveShadows);\n                }\n\n                var useLightProbes = selectedLODProp.FindPropertyRelative(\"useLightProbes\");\n                EditorGUILayout.PropertyField(useLightProbes, Styles.UseLightProbes);\n                if (!useLightProbes.hasMultipleDifferentValues && useLightProbes.boolValue && isBillboard)\n                    EditorGUILayout.HelpBox(\"Enabling Light Probe for billboards breaks batched rendering and may cause performance problem.\", MessageType.Warning);\n\n                // TODO: reflection probe support when PBS is implemented\n                //EditorGUILayout.PropertyField(SelectedLODProp.FindPropertyRelative(\"useReflectionProbes\"), Styles.UseReflectionProbes);\n\n                EditorGUILayout.Space();\n                EditorGUILayout.LabelField(\"Material\", EditorStyles.boldLabel);\n                EditorGUILayout.PropertyField(selectedLODProp.FindPropertyRelative(\"enableHue\"), Styles.EnableColorVariation);\n                EditorGUILayout.PropertyField(selectedLODProp.FindPropertyRelative(\"enableBump\"), Styles.EnableBump);\n\n                EditorGUILayout.PropertyField(selectedLODProp.FindPropertyRelative(\"enableSubsurface\"), Styles.EnableSubsurface);\n            }\n        }\n\n        private void OnResetLODMenuClick(object userData)\n        {\n            //var toHeights = (userData as SpeedTreeImporter).LODHeights;\n            for (int i = 0; i < m_StEditor.m_PerLODSettings.Count; ++i)\n            {\n                var toHeight = m_StEditor.m_PerLODSettings[i].height;\n                m_PerLODSettings.GetArrayElementAtIndex(i).FindPropertyRelative(\"height\").floatValue = toHeight;\n            }\n        }\n\n        private bool HasSameLODConfig()\n        {\n            if (m_PerLODSettings.FindPropertyRelative(\"Array.size\").hasMultipleDifferentValues)\n                return false;\n\n            for (int i = 0; i < m_PerLODSettings.arraySize; ++i)\n            {\n                if (m_PerLODSettings.GetArrayElementAtIndex(i).FindPropertyRelative(\"height\").hasMultipleDifferentValues)\n                    return false;\n            }\n            return true;\n        }\n\n        private void ExpandSelectedHeaderAndCloseRemaining(int index)\n        {\n            // need this to safeguard against drag & drop on Culled section\n            // as that sets the LOD index to 8 which is outside of the total\n            // allowed LOD range\n            if (index >= m_PerLODSettings.arraySize)\n                return;\n\n            Array.ForEach(m_LODGroupFoldoutHeaderValues, el => el.value = false);\n            m_LODGroupFoldoutHeaderValues[index].value = true;\n        }\n\n        private List<LODGroupGUI.LODInfo> GetLODInfoArray(Rect area)\n        {\n            int lodCount = m_PerLODSettings.arraySize;\n            return LODGroupGUI.CreateLODInfos(\n                lodCount, area,\n                i => i == lodCount - 1 && m_OutputImporterData.hasBillboard ? \"Billboard\" : String.Format(\"LOD {0}\", i),\n                i => m_PerLODSettings.GetArrayElementAtIndex(i).FindPropertyRelative(\"height\").floatValue);\n        }\n\n        private bool CanUnifyLODConfig()\n        {\n            // TODO: Add multi-selection support for LOD UI.\n            return false;\n        }\n\n        void InitAndSetFoldoutLabelTextures()\n        {\n            m_LODColorTextures = new Texture2D[m_PerLODSettings.arraySize];\n            for (int i = 0; i < m_LODColorTextures.Length; i++)\n            {\n                m_LODColorTextures[i] = new Texture2D(1, 1);\n                m_LODColorTextures[i].SetPixel(0, 0, GetLODGroupColor(i));\n            }\n        }\n\n        void ResetFoldoutLists()\n        {\n            int lodArraySize = Mathf.Min(m_PerLODSettings.arraySize, LODGroupGUI.kLODColors.Length);\n            m_LODGroupFoldoutHeaderValues = new SavedBool[lodArraySize];\n            for (int i = 0; i < lodArraySize; i++)\n            {\n                m_LODGroupFoldoutHeaderValues[i] = new SavedBool($\"{target.GetType()}.lodFoldout{i}\", false);\n            }\n            InitAndSetFoldoutLabelTextures();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/SpeedTree/SpeedTree9ImporterWindEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.AssetImporters;\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor.SpeedTree.Importer\n{\n    class SpeedTree9ImporterWindEditor : BaseSpeedTree9ImporterTabUI\n    {\n        private class Styles\n        {\n            public static GUIContent EnableWind = EditorGUIUtility.TrTextContent(\"Enable Wind\");\n            public static GUIContent StrengthResponse = EditorGUIUtility.TrTextContent(\"Strength Response\", \"The strength response of the wind.\");\n            public static GUIContent DirectionResponse = EditorGUIUtility.TrTextContent(\"Direction Response\", \"The direction response of the wind.\");\n            public static GUIContent WindRandomness = EditorGUIUtility.TrTextContent(\"Randomness\", \"Amount of world position based noise applied to each tree.\");\n        }\n\n        private SerializedProperty m_EnableWind;\n        private SerializedProperty m_StrengthResponse;\n        private SerializedProperty m_DirectionResponse;\n        private SerializedProperty m_WindRandomness;\n\n        private SpeedTree9Importer m_StEditor;\n\n        public SpeedTree9ImporterWindEditor(AssetImporterEditor panelContainer)\n            : base(panelContainer)\n        { }\n\n        internal override void OnEnable()\n        {\n            m_StEditor = target as SpeedTree9Importer;\n\n            WindSettings windSettings = m_StEditor.m_WindSettings;\n            string windSettingsStr = nameof(m_StEditor.m_WindSettings);\n\n            m_EnableWind = FindPropertyFromName(windSettingsStr, nameof(windSettings.enableWind));\n            m_StrengthResponse = FindPropertyFromName(windSettingsStr, nameof(windSettings.strenghResponse));\n            m_DirectionResponse = FindPropertyFromName(windSettingsStr, nameof(windSettings.directionResponse));\n            m_WindRandomness = FindPropertyFromName(windSettingsStr, nameof(windSettings.randomness));\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUILayout.PropertyField(m_EnableWind, Styles.EnableWind);\n\n            using (new EditorGUI.DisabledScope(!m_EnableWind.boolValue))\n            {\n                EditorGUILayout.PropertyField(m_StrengthResponse, Styles.StrengthResponse);\n                EditorGUILayout.PropertyField(m_DirectionResponse, Styles.DirectionResponse);\n                EditorGUILayout.PropertyField(m_WindRandomness, Styles.WindRandomness);\n            }\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        private SerializedProperty FindPropertyFromName(string parentProperty, string childProperty)\n        {\n            const string dotStr = \".\";\n\n            string finalName = String.Concat(parentProperty, dotStr, childProperty);\n\n            return serializedObject.FindProperty(finalName);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/SpeedTree/SpeedTree9Reader.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\n\nnamespace UnityEditor.SpeedTree.Importer\n{\n    #region Data Classes\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct Vec2\n    {\n        private float x, y;\n\n        public float X\n        {\n            get { return x; }\n            set { x = value; }\n        }\n\n        public float Y\n        {\n            get { return y; }\n            set { y = value; }\n        }\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct Vec3\n    {\n        private float x, y, z;\n\n        public float X\n        {\n            get { return x; }\n            set { x = value; }\n        }\n\n        public float Y\n        {\n            get { return y; }\n            set { y = value; }\n        }\n\n        public float Z\n        {\n            get { return z; }\n            set { z = value; }\n        }\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct Vec4\n    {\n        private float x, y, z, w;\n\n        public float X\n        {\n            get { return x; }\n            set { x = value; }\n        }\n\n        public float Y\n        {\n            get { return y; }\n            set { y = value; }\n        }\n\n        public float Z\n        {\n            get { return z; }\n            set { z = value; }\n        }\n\n        public float W\n        {\n            get { return w; }\n            set { w = value; }\n        }\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct Bounds3\n    {\n        public Vec3 Min { get; private set; }\n        public Vec3 Max { get; private set; }\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct Vertex\n    {\n        public Vec3 Anchor { get; private set; }\n        public Vec3 Offset { get; private set; }\n        public Vec3 LodOffset { get; private set; }\n        public Vec3 Normal { get; private set; }\n        public Vec3 Tangent { get; private set; }\n        public Vec3 Binormal { get; private set; }\n        public Vec2 TexCoord { get; private set; }\n        public Vec2 LightmapTexCoord { get; private set; }\n        public Vec3 Color { get; private set; }\n        public float AmbientOcclusion { get; private set; }\n        public float BlendWeight { get; private set; }\n        public Vec3 BranchWind1 { get; private set; } // pos, dir, weight\n        public Vec3 BranchWind2 { get; private set; }\n        public float RippleWeight { get; private set; }\n        public bool CameraFacing { get; private set; }\n        public uint BoneID { get; private set; }\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct DrawCall\n    {\n        public uint MaterialIndex { get; private set; }\n        public bool ContainsFacingGeometry { get; private set; }\n        public uint IndexStart { get; private set; }\n        public uint IndexCount { get; private set; }\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct Bone\n    {\n        public uint ID { get; private set; }\n        public bool ParentID { get; private set; }\n        public Vec3 Start { get; private set; }\n        public Vec3 End { get; private set; }\n        public float Radius { get; private set; }\n    }\n\n    #endregion\n\n    #region Data Tables\n    interface ReaderData\n    {\n        public void Initialize(Byte[] data, int offset);\n    }\n\n    class Lod : ReaderData\n    {\n        private enum OffsetData\n        {\n            Vertices = 0,\n            Indices = 1,\n            DrawCalls = 2\n        }\n\n        public Vertex[] Vertices { get; private set; }\n        public uint[] Indices { get; private set; }\n        public DrawCall[] DrawCalls { get; private set; }\n\n        public void Initialize(Byte[] data, int offset)\n        {\n            Vertices = SpeedTree9ReaderUtility.GetArray<Vertex>(data, offset, (int)OffsetData.Vertices);\n            Indices = SpeedTree9ReaderUtility.GetArray<uint>(data, offset, (int)OffsetData.Indices);\n            DrawCalls = SpeedTree9ReaderUtility.GetArray<DrawCall>(data, offset, (int)OffsetData.DrawCalls);\n        }\n    }\n\n    class BillboardInfo : ReaderData\n    {\n        private enum OffsetData\n        {\n            LastLodIsBillboard = 0,\n            IncludesTopDown = 1,\n            SideViewCount = 2\n        }\n\n        public bool LastLodIsBillboard { get; private set; }\n        public bool IncludesTopDown { get; private set; }\n        public uint SideViewCount { get; private set; }\n\n        public void Initialize(Byte[] data, int offset)\n        {\n            LastLodIsBillboard = SpeedTree9ReaderUtility.GetBool(data, offset, (int)OffsetData.LastLodIsBillboard);\n            IncludesTopDown = SpeedTree9ReaderUtility.GetBool(data, offset, (int)OffsetData.IncludesTopDown);\n            SideViewCount = SpeedTree9ReaderUtility.GetUInt(data, offset, (int)OffsetData.SideViewCount);\n        }\n    }\n\n    class CollisionObject : ReaderData\n    {\n        private enum OffsetData\n        {\n            Position = 0,\n            Position2 = 1,\n            Radius = 2,\n            UserData = 3\n        }\n\n        public Vec3 Position { get; private set; }\n        public Vec3 Position2 { get; private set; }\n        public float Radius { get; private set; }\n        public string UserData { get; private set; }\n\n        public void Initialize(Byte[] data, int offset)\n        {\n            Position = SpeedTree9ReaderUtility.GetStruct<Vec3>(data, offset, (int)OffsetData.Position);\n            Position2 = SpeedTree9ReaderUtility.GetStruct<Vec3>(data, offset, (int)OffsetData.Position2);\n            Radius = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.Radius);\n            UserData = SpeedTree9ReaderUtility.GetString(data, offset, (int)OffsetData.UserData);\n        }\n    }\n\n    class MaterialMap : ReaderData\n    {\n        private enum OffsetData\n        {\n            Used = 0,\n            Path = 1,\n            Color = 2\n        }\n\n        public bool Used { get; private set; }\n        public string Path { get; private set; }\n        public Vec4 Color { get; private set; }\n\n        public void Initialize(Byte[] data, int offset)\n        {\n            Used = SpeedTree9ReaderUtility.GetBool(data, offset, (int)OffsetData.Used);\n            Path = SpeedTree9ReaderUtility.GetString(data, offset, (int)OffsetData.Path);\n            Color = SpeedTree9ReaderUtility.GetStruct<Vec4>(data, offset, (int)OffsetData.Color);\n        }\n    }\n\n    class STMaterial : ReaderData\n    {\n        private enum OffsetData\n        {\n            Name = 0,\n            TwoSided = 1,\n            FlipNormalsOnBackside = 2,\n            Billboard = 3,\n            Maps = 4\n        }\n\n        public string Name { get; private set; }\n        public bool TwoSided { get; private set; }\n        public bool FlipNormalsOnBackside { get; private set; }\n        public bool Billboard { get; private set; }\n        public MaterialMap[] Maps { get; private set; }\n\n        public void Initialize(Byte[] data, int offset)\n        {\n            Name = SpeedTree9ReaderUtility.GetString(data, offset, (int)OffsetData.Name);\n            TwoSided = SpeedTree9ReaderUtility.GetBool(data, offset, (int)OffsetData.TwoSided);\n            FlipNormalsOnBackside = SpeedTree9ReaderUtility.GetBool(data, offset, (int)OffsetData.FlipNormalsOnBackside);\n            Billboard = SpeedTree9ReaderUtility.GetBool(data, offset, (int)OffsetData.Billboard);\n            Maps = SpeedTree9ReaderUtility.GetDataObjectArray<MaterialMap>(data, offset, (int)OffsetData.Maps);\n        }\n    }\n    #endregion\n\n    #region Wind Data Tables\n    class WindConfigCommon : ReaderData\n    {\n        private enum OffsetData\n        {\n            StrengthResponse = 0,\n            DirectionResponse = 1,\n            GustFrequency = 5,\n            GustStrengthMin = 6,\n            GustStrengthMax = 7,\n            GustDurationMin = 8,\n            GustDurationMax = 9,\n            GustRiseScalar = 10,\n            GustFallScalar = 11,\n            CurrentStrength = 15\n        }\n\n        public float StrengthResponse { get; private set; }\n        public float DirectionResponse { get; private set; }\n        public float GustFrequency { get; private set; }\n        public float GustStrengthMin { get; private set; }\n        public float GustStrengthMax { get; private set; }\n        public float GustDurationMin { get; private set; }\n        public float GustDurationMax { get; private set; }\n        public float GustRiseScalar { get; private set; }\n        public float GustFallScalar { get; private set; }\n        public float CurrentStrength { get; private set; }\n\n        public void Initialize(Byte[] data, int offset)\n        {\n            StrengthResponse = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.StrengthResponse);\n            DirectionResponse = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.DirectionResponse);\n            GustFrequency = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.GustFrequency);\n            GustStrengthMin = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.GustStrengthMin);\n            GustStrengthMax = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.GustStrengthMax);\n            GustDurationMin = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.GustDurationMin);\n            GustDurationMax = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.GustDurationMax);\n            GustRiseScalar = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.GustRiseScalar);\n            GustFallScalar = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.GustFallScalar);\n            CurrentStrength = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.CurrentStrength);\n        }\n    };\n\n    class WindConfigSDK : ReaderData\n    {\n        internal class WindBranch : ReaderData\n        {\n            private enum OffsetData\n            {\n                Bend = 0,\n                Oscillation = 1,\n                Speed = 2,\n                Turbulence = 3,\n                Flexibility = 4,\n                Independence = 5\n            }\n\n            public float[] Bend { get; private set; }\n            public float[] Oscillation { get; private set; }\n            public float[] Speed { get; private set; }\n            public float[] Turbulence { get; private set; }\n            public float[] Flexibility { get; private set; }\n            public float Independence { get; private set; }\n\n            public void Initialize(Byte[] data, int offset)\n            {\n                Bend = SpeedTree9ReaderUtility.GetArray<float>(data, offset, (int)OffsetData.Bend);\n                Oscillation = SpeedTree9ReaderUtility.GetArray<float>(data, offset, (int)OffsetData.Oscillation);\n                Speed = SpeedTree9ReaderUtility.GetArray<float>(data, offset, (int)OffsetData.Speed);\n                Turbulence = SpeedTree9ReaderUtility.GetArray<float>(data, offset, (int)OffsetData.Turbulence);\n                Flexibility = SpeedTree9ReaderUtility.GetArray<float>(data, offset, (int)OffsetData.Flexibility);\n                Independence = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.Independence);\n            }\n        };\n\n        internal class WindRipple : ReaderData\n        {\n            private enum OffsetData\n            {\n                Planar = 0,\n                Directional = 1,\n                Speed = 2,\n                Flexibility = 3,\n                Shimmer = 4,\n                Independence = 5\n            }\n\n            public float[] Planar { get; private set; }\n            public float[] Directional { get; private set; }\n            public float[] Speed { get; private set; }\n            public float[] Flexibility { get; private set; }\n            public float Shimmer { get; private set; }\n            public float Independence { get; private set; }\n\n            public void Initialize(Byte[] data, int offset)\n            {\n                Planar = SpeedTree9ReaderUtility.GetArray<float>(data, offset, (int)OffsetData.Planar);\n                Directional = SpeedTree9ReaderUtility.GetArray<float>(data, offset, (int)OffsetData.Directional);\n                Speed = SpeedTree9ReaderUtility.GetArray<float>(data, offset, (int)OffsetData.Speed);\n                Flexibility = SpeedTree9ReaderUtility.GetArray<float>(data, offset, (int)OffsetData.Flexibility);\n                Shimmer = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.Shimmer);\n                Independence = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.Independence);\n            }\n        };\n\n        private enum OffsetData\n        {\n            Common = 0,\n            Shared = 1,\n            Branch1 = 2,\n            Branch2 = 3,\n            Ripple = 4,\n            SharedStartHeight = 10,\n            Branch1StretchLimit = 11,\n            Branch2StretchLimit = 12,\n            DoShared = 15,\n            DoBranch1 = 16,\n            DoBranch2 = 17,\n            DoRipple = 18,\n            DoShimmer = 19\n        }\n\n        public WindConfigCommon Common { get; private set; }\n        public WindBranch Shared { get; private set; }\n        public WindBranch Branch1 { get; private set; }\n        public WindBranch Branch2 { get; private set; }\n        public WindRipple Ripple { get; private set; }\n\n        public float SharedStartHeight { get; private set; }\n        public float Branch1StretchLimit { get; private set; }\n        public float Branch2StretchLimit { get; private set; }\n\n        public bool DoShared { get; private set; }\n        public bool DoBranch1 { get; private set; }\n        public bool DoBranch2 { get; private set; }\n        public bool DoRipple { get; private set; }\n        public bool DoShimmer { get; private set; }\n\n        public void Initialize(Byte[] data, int offset)\n        {\n            Common = SpeedTree9ReaderUtility.GetDataObject<WindConfigCommon>(data, offset, (int)OffsetData.Common);\n            Shared = SpeedTree9ReaderUtility.GetDataObject<WindBranch>(data, offset, (int)OffsetData.Shared);\n            Branch1 = SpeedTree9ReaderUtility.GetDataObject<WindBranch>(data, offset, (int)OffsetData.Branch1);\n            Branch2 = SpeedTree9ReaderUtility.GetDataObject<WindBranch>(data, offset, (int)OffsetData.Branch2);\n            Ripple = SpeedTree9ReaderUtility.GetDataObject<WindRipple>(data, offset, (int)OffsetData.Ripple);\n\n            SharedStartHeight = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.SharedStartHeight);\n            Branch1StretchLimit = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.Branch1StretchLimit);\n            Branch2StretchLimit = SpeedTree9ReaderUtility.GetFloat(data, offset, (int)OffsetData.Branch2StretchLimit);\n\n            DoShared = SpeedTree9ReaderUtility.GetBool(data, offset, (int)OffsetData.DoShared);\n            DoBranch1 = SpeedTree9ReaderUtility.GetBool(data, offset, (int)OffsetData.DoBranch1);\n            DoBranch2 = SpeedTree9ReaderUtility.GetBool(data, offset, (int)OffsetData.DoBranch2);\n            DoRipple = SpeedTree9ReaderUtility.GetBool(data, offset, (int)OffsetData.DoRipple);\n            DoShimmer = SpeedTree9ReaderUtility.GetBool(data, offset, (int)OffsetData.DoShimmer);\n        }\n    };\n    #endregion\n\n    #region Reader Utilities\n    static class SpeedTree9ReaderUtility\n    {\n        public static int GetOffset(in Byte[] data, int offsetIn, int index)\n        {\n            int offset = offsetIn + (index + 1) * 4;\n            return offsetIn + (int)BitConverter.ToUInt32(data, offset);\n        }\n\n        public static float GetFloat(in Byte[] data, int offsetIn, int index)\n        {\n            return BitConverter.ToSingle(data, GetOffset(data, offsetIn, index));\n        }\n\n        public static string GetString(in Byte[] data, int offsetIn, int index)\n        {\n            int offset = GetOffset(data, offsetIn, index);\n            int length = (int)BitConverter.ToUInt32(data, offset);\n            return System.Text.Encoding.UTF8.GetString(data, offset + 4, length - 1);\n        }\n\n        public static T GetStruct<T>(in Byte[] data, int offsetIn, int index) where T : struct\n        {\n            int offset = GetOffset(data, offsetIn, index);\n            return MemoryMarshal.Cast<byte, T>(data.AsSpan().Slice(offset))[0];\n        }\n\n        public static bool GetBool(in Byte[] data, int offsetIn, int index)\n        {\n            return GetInt(data, offsetIn, index) != 0;\n        }\n\n        public static int GetInt(in Byte[] data, int offsetIn, int index)\n        {\n            return BitConverter.ToInt32(data, GetOffset(data, offsetIn, index));\n        }\n\n        public static uint GetUInt(in Byte[] data, int offsetIn, int index)\n        {\n            return BitConverter.ToUInt32(data, GetOffset(data, offsetIn, index));\n        }\n\n        public static T[] GetArray<T>(Byte[] data, int offset, int type) where T : struct\n        {\n            int offsetData = SpeedTree9ReaderUtility.GetOffset(data, offset, (int)type);\n            uint countData = BitConverter.ToUInt32(data, offsetData);\n\n            T[] array = new T[countData];\n\n            for (int i = 0; i < countData; i++)\n            {\n                array[i] = MemoryMarshal.Cast<byte, T>(data.AsSpan().Slice(offsetData + 4))[i];\n            }\n\n            return array;\n        }\n\n        public static T GetDataObject<T>(in Byte[] data, int offset, int index) where T : ReaderData, new()\n        {\n            int dataOffset = SpeedTree9ReaderUtility.GetOffset(data, offset, index);\n\n            T readData = new T();\n            readData.Initialize(data, dataOffset);\n\n            return readData;\n        }\n\n        public static T[] GetDataObjectArray<T>(in Byte[] data, int offset, int index) where T : ReaderData, new()\n        {\n            int dataOffset = SpeedTree9ReaderUtility.GetOffset(data, offset, index);\n            uint dataCount = BitConverter.ToUInt32(data, dataOffset);\n\n            T[] readData = new T[dataCount];\n\n            for (int i = 0; i < dataCount; i++)\n            {\n                int offsetNew = SpeedTree9ReaderUtility.GetOffset(data, dataOffset, i);\n\n                T newData = new T();\n                newData.Initialize(data, offsetNew);\n\n                readData[i] = newData;\n            }\n\n            return readData;\n        }\n    }\n    #endregion\n\n    internal class SpeedTree9Reader : IDisposable\n    {\n        internal enum FileStatus\n        {\n            Valid = 0,\n            InvalidPath = 1,\n            InvalidSignature = 2\n        }\n\n        enum OffsetData\n        {\n            VersionMajor = 0,\n            VersionMinor = 1,\n            Bounds = 2,\n            Lod = 5,\n            BillboardInfo = 6,\n            CollisionObjects = 7,\n            Materials = 10,\n            Wind = 15\n        }\n\n        const string k_TokenKey = \"SpeedTree9______\";\n\n        public uint VersionMajor { get; private set; }\n        public uint VersionMinor { get; private set; }\n        public Bounds3 Bounds { get; private set; }\n        public Lod[] Lod { get; private set; }\n        public BillboardInfo BillboardInfo { get; private set; }\n        public CollisionObject[] CollisionObjects { get; private set; }\n        public STMaterial[] Materials { get; private set; }\n        public WindConfigSDK Wind { get; private set; }\n\n        private string m_AssetPath;\n        private FileStream m_FileStream;\n        private int m_Offset;\n        private bool m_Disposed;\n\n        public FileStatus Initialize(string assetPath)\n        {\n            m_AssetPath = assetPath;\n            m_FileStream = new FileStream(m_AssetPath, FileMode.Open, FileAccess.Read);\n\n            if (!File.Exists(assetPath))\n            {\n                return FileStatus.InvalidPath;\n            }\n\n            if (!ValidateFileSignature())\n            {\n                return FileStatus.InvalidSignature;\n            }\n\n            return FileStatus.Valid;\n        }\n\n        public void Dispose()\n        {\n            Dispose(true);\n            GC.SuppressFinalize(this);\n        }\n\n        protected void Dispose(bool disposing)\n        {\n            if (!m_Disposed)\n            {\n                // Manual release of managed resources.\n                if (disposing)\n                {\n                    if (m_FileStream != null)\n                    {\n                        m_FileStream.Close();\n                    }\n                }\n\n                // Release unmanaged resources.\n                m_Disposed = true;\n            }\n        }\n\n        public void ReadContent()\n        {\n            byte[] data = File.ReadAllBytes(m_AssetPath);\n\n            VersionMajor = SpeedTree9ReaderUtility.GetUInt(data, m_Offset, (int)OffsetData.VersionMajor);\n            VersionMinor = SpeedTree9ReaderUtility.GetUInt(data, m_Offset, (int)OffsetData.VersionMinor);\n            Bounds = SpeedTree9ReaderUtility.GetStruct<Bounds3>(data, m_Offset, (int)OffsetData.Bounds);\n            Lod = SpeedTree9ReaderUtility.GetDataObjectArray<Lod>(data, m_Offset, (int)OffsetData.Lod);\n            BillboardInfo = SpeedTree9ReaderUtility.GetDataObject<BillboardInfo>(data, m_Offset, (int)OffsetData.BillboardInfo);\n            CollisionObjects = SpeedTree9ReaderUtility.GetDataObjectArray<CollisionObject>(data, m_Offset, (int)OffsetData.CollisionObjects);\n            Materials = SpeedTree9ReaderUtility.GetDataObjectArray<STMaterial>(data, m_Offset, (int)OffsetData.Materials);\n            Wind = SpeedTree9ReaderUtility.GetDataObject<WindConfigSDK>(data, m_Offset, (int)OffsetData.Wind);\n\n            if (m_FileStream != null)\n            {\n                m_FileStream.Close();\n            }\n        }\n\n        private unsafe bool ValidateFileSignature()\n        {\n            byte[] buffer = new byte[k_TokenKey.Length];\n\n            try\n            {\n                int bytesRead = m_FileStream.Read(buffer, m_Offset, k_TokenKey.Length);\n\n                if (bytesRead != buffer.Length)\n                {\n                    return false;\n                }\n            }\n            catch (UnauthorizedAccessException ex)\n            {\n                Debug.LogError(ex.Message);\n            }\n\n            bool valid = true;\n            for (int i = 0; i < k_TokenKey.Length && valid; ++i)\n            {\n                valid &= (k_TokenKey[i] == buffer[i]);\n            }\n\n            if (valid)\n            {\n                m_Offset = k_TokenKey.Length;\n            }\n\n            return valid;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/SpeedTree/SpeedTreeImporterCommon.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing UnityEngine.Rendering;\nusing UnityEditor.AnimatedValues;\n\nnamespace UnityEditor.SpeedTree.Importer\n{\n    class SpeedTreeConstants\n    {\n        internal static readonly float kFeetToMetersRatio = 0.3048f;\n        internal static readonly float kCentimetersToMetersRatio = 0.01f;\n        internal static readonly float kInchesToMetersRatio = 0.0254f;\n        internal static readonly float kAlphaTestRef = 0.33f;\n        internal static readonly string kBillboardMaterialName = \"Billboard\";\n    }\n\n    static class SpeedTreeImporterCommon\n    {\n        internal enum STUnitConversion\n        {\n            kLeaveAsIs = 0,\n            kFeetToMeters,\n            kCentimetersToMeters,\n            kInchesToMeters,\n            kCustomConversion\n        };\n\n        internal static class MaterialProperties\n        {\n            internal static readonly int MainTexID = Shader.PropertyToID(\"_MainTex\");\n            internal static readonly int ColorTintID = Shader.PropertyToID(\"_ColorTint\");\n\n            internal static readonly int NormalMapKwToggleID = Shader.PropertyToID(\"_NormalMapKwToggle\");\n            internal static readonly int NormalMapID = Shader.PropertyToID(\"_NormalMap\");\n\n            internal static readonly int ExtraMapKwToggleID = Shader.PropertyToID(\"_ExtraMapKwToggle\");\n            internal static readonly int ExtraTexID = Shader.PropertyToID(\"_ExtraTex\");\n            internal static readonly int GlossinessID = Shader.PropertyToID(\"_Glossiness\");\n            internal static readonly int MetallicID = Shader.PropertyToID(\"_Metallic\");\n\n            internal static readonly int SubsurfaceKwToggleID = Shader.PropertyToID(\"_SubsurfaceKwToggle\");\n            internal static readonly int SubsurfaceTexID = Shader.PropertyToID(\"_SubsurfaceTex\");\n            internal static readonly int SubsurfaceColorID = Shader.PropertyToID(\"_SubsurfaceColor\");\n            internal static readonly int AlphaClipThresholdID = Shader.PropertyToID(\"_AlphaClipThreshold\");\n            internal static readonly int TransmissionScaleID = Shader.PropertyToID(\"_TransmissionScale\");\n            internal static readonly int DiffusionProfileAssetID = Shader.PropertyToID(\"_Diffusion_Profile_Asset\");\n            internal static readonly int DiffusionProfileID = Shader.PropertyToID(\"_DiffusionProfile\");\n\n            internal static readonly int HueVariationKwToggleID = Shader.PropertyToID(\"_HueVariationKwToggle\");\n            internal static readonly int HueVariationColorID = Shader.PropertyToID(\"_HueVariationColor\");\n\n            internal static readonly int LeafFacingKwToggleID = Shader.PropertyToID(\"_LeafFacingKwToggle\");\n            internal static readonly int BillboardKwToggleID = Shader.PropertyToID(\"_BillboardKwToggle\");\n            internal static readonly int DoubleSidedToggleID = Shader.PropertyToID(\"_DoubleSidedKwToggle\");\n            internal static readonly int DoubleSidedNormalModeID = Shader.PropertyToID(\"_DoubleSidedNormalMode\");\n            internal static readonly int BackfaceNormalModeID = Shader.PropertyToID(\"_BackfaceNormalMode\");\n            internal static readonly int TwoSidedID = Shader.PropertyToID(\"_TwoSided\");\n\n            internal static readonly int WindSharedKwToggle = Shader.PropertyToID(\"_WIND_SHARED\");\n            internal static readonly int WindBranch2KwToggle = Shader.PropertyToID(\"_WIND_BRANCH2\");\n            internal static readonly int WindBranch1KwToggle = Shader.PropertyToID(\"_WIND_BRANCH1\");\n            internal static readonly int WindRippleKwToggle = Shader.PropertyToID(\"_WIND_RIPPLE\");\n            internal static readonly int WindShimmerKwToggle = Shader.PropertyToID(\"_WIND_SHIMMER\");\n        }\n\n        internal static class MaterialKeywords\n        {\n            internal static readonly string VBSetupStandardID = \"VB_SETUP_STANDARD\";\n            internal static readonly string VBSetupBranch2ID = \"VB_SETUP_BRANCH2\";\n            internal static readonly string VBSetupCameraFacingID = \"VB_SETUP_CAMERA_FACING\";\n            internal static readonly string VBSetupBranch2AndCameraFacingID = \"VB_SETUP_BRANCH2_AND_CAMERA_FACING\";\n            internal static readonly string VBSetupBillboardID = \"VB_SETUP_BILLBOARD\";\n            internal static readonly string VBSetupID = \"VB_SETUP\";\n            internal static readonly string BillboardID = \"_BILLBOARD\";\n        }\n    }\n\n    static class SpeedTreeImporterCommonEditor\n    {\n        internal class Styles\n        {\n            // Meshes labels\n            public static GUIContent MeshesHeader = EditorGUIUtility.TrTextContent(\"Meshes\");\n            public static GUIContent UnitConversion = EditorGUIUtility.TrTextContent(\"Unit Conversion\", \"Select the unit conversion to apply to the imported SpeedTree asset.\");\n            public static GUIContent ScaleFactor = EditorGUIUtility.TrTextContent(\"Scale Factor\", \"How much to scale the tree model, interpreting the exported units as meters. Must be positive.\");\n            public static GUIContent[] UnitConversionNames =\n            {\n                  new GUIContent(\"Leave As Is\")\n                , new GUIContent(\"ft to m\")\n                , new GUIContent(\"cm to m\")\n                , new GUIContent(\"inch to m\")\n                , new GUIContent(\"Custom\")\n            };\n\n            // Materials labels\n            public static GUIContent MaterialHeader = EditorGUIUtility.TrTextContent(\"Material\");\n            public static GUIContent MainColor = EditorGUIUtility.TrTextContent(\"Main Color\", \"The color modulating the diffuse lighting component.\");\n            public static GUIContent EnableColorVariation = EditorGUIUtility.TrTextContent(\"Color Variation\", \"Color is determined by linearly interpolating between the Main Color & Color Variation values based on the world position X, Y and Z values\");\n            public static GUIContent EnableBump = EditorGUIUtility.TrTextContent(\"Normal Map\", \"Enable normal (Bump) mapping.\");\n            public static GUIContent EnableSubsurface = EditorGUIUtility.TrTextContent(\"Subsurface Scattering\", \"Enable subsurface scattering effects.\");\n            public static GUIContent HueVariation = EditorGUIUtility.TrTextContent(\"Variation Color (RGB), Intensity (A)\", \"Tint the tree with the Variation Color\");\n            public static GUIContent AlphaTestRef = EditorGUIUtility.TrTextContent(\"Alpha Cutoff\", \"The alpha-test reference value.\");\n            public static GUIContent TransmissionScale = EditorGUIUtility.TrTextContent(\"Transmission Scale\", \"The transmission scale value.\");\n\n            // Lighting labels\n            public static GUIContent LightingHeader = EditorGUIUtility.TrTextContent(\"Lighting\");\n            public static GUIContent CastShadows = EditorGUIUtility.TrTextContent(\"Cast Shadows\", \"The tree casts shadow\");\n            public static GUIContent ReceiveShadows = EditorGUIUtility.TrTextContent(\"Receive Shadows\", \"The tree receives shadow\");\n            public static GUIContent UseLightProbes = EditorGUIUtility.TrTextContent(\"Light Probes\", \"The tree uses light probe for lighting\"); // TODO: update help text\n            public static GUIContent UseReflectionProbes = EditorGUIUtility.TrTextContent(\"Reflection Probes\", \"The tree uses reflection probe for rendering\"); // TODO: update help text\n            public static GUIContent[] ReflectionProbeUsageNames = GetReflectionProbeUsageNames();\n\n            public static GUIContent[] GetReflectionProbeUsageNames()\n            {\n                string[] names = Enum.GetNames(typeof(ReflectionProbeUsage));\n                GUIContent[] probUsageNames = new GUIContent[names.Length];\n\n                for (int i = 0; i < names.Length; ++i)\n                {\n                    string varName = ObjectNames.NicifyVariableName(names[i]);\n                    probUsageNames[i] = (new GUIContent(varName));\n                }\n\n                return probUsageNames;\n            }\n\n            // Additional Settings labels\n            public static GUIContent AdditionalSettingsHeader = EditorGUIUtility.TrTextContent(\"Additional Settings\");\n            public static GUIContent MotionVectorMode = EditorGUIUtility.TrTextContent(\"Motion Vectors\", \"Motion vector mode to set for the mesh renderer of each LOD object\");\n\n            // Wind labels\n            public static GUIContent WindHeader = EditorGUIUtility.TrTextContent(\"Wind\");\n            public static GUIContent WindQuality = EditorGUIUtility.TrTextContent(\"Wind Quality\", \"Controls the wind effect's quality.\");\n            public static GUIContent[] MotionVectorModeNames =  // Match SharedRendererDataTypes.h / enum MotionVectorGenerationMode\n{\n                  new GUIContent(\"Camera Motion Only\")  // kMotionVectorCamera = 0,    // Use camera motion for motion vectors\n                , new GUIContent(\"Per Object Motion\")   // kMotionVectorObject,        // Use a per object motion vector pass for this object\n                , new GUIContent(\"Force No Motion\")     // kMotionVectorForceNoMotion, // Force no motion for this object (0 into motion buffer)\n            };\n\n            public static GUIContent[] GetWindQualityNames()\n            {\n                GUIContent[] windQualityNames = new GUIContent[SpeedTreeImporter.windQualityNames.Length];\n\n                for (int i = 0; i < SpeedTreeImporter.windQualityNames.Length; ++i)\n                {\n                    windQualityNames[i] = new GUIContent(SpeedTreeImporter.windQualityNames[i]);\n                }\n\n                return windQualityNames;\n            }\n\n            // LOD labels\n            public static GUIContent LODHeader = EditorGUIUtility.TrTextContent(\"LOD\");\n            public static GUIContent ResetLOD = EditorGUIUtility.TrTextContent(\"Reset LOD to...\", \"Unify the LOD settings for all selected assets\");\n            public static GUIContent SmoothLOD = EditorGUIUtility.TrTextContent(\"Smooth Transitions\", \"Toggles smooth LOD transitions\");\n            public static GUIContent AnimateCrossFading = EditorGUIUtility.TrTextContent(\"Animate Cross-fading\", \"Cross-fading is animated instead of being calculated by distance\");\n            public static GUIContent CrossFadeWidth = EditorGUIUtility.TrTextContent(\"Crossfade Width\", \"Proportion of the last 3D mesh LOD region width which is used for cross-fading to billboard tree\");\n            public static GUIContent FadeOutWidth = EditorGUIUtility.TrTextContent(\"Fade Out Width\", \"The proportion of the billboard LOD region width that is used to fade out the billboard.\");\n\n            public static GUIContent EnableLodCustomizationsWarn = EditorGUIUtility.TrTextContent(\"Customizing LOD options may help with tuning the GPU performance but will likely negatively impact the instanced draw batching, i.e. CPU performance.\\nPlease use the per-LOD customizations with careful memory and performance profiling for both CPU and GPU and remember that these options are a trade-off rather than a free win.\");\n            public static GUIContent BillboardSettingsHelp = EditorGUIUtility.TrTextContent(\"Billboard options are separate from the 3D model options shown above.\\nChange the options below for influencing billboard rendering.\");\n            public static GUIContent MultiSelectionLODNotSupported = EditorGUIUtility.TrTextContent(\"Multi-selection is not supported for LOD settings.\");\n\n            public static GUIContent ApplyAndGenerate = EditorGUIUtility.TrTextContent(\"Apply & Generate Materials\", \"Apply current importer settings and generate asset materials with the new settings.\");\n        }\n\n        static internal void ShowMeshGUI(\n            ref SerializedProperty unitConversionEnumValue,\n            ref SerializedProperty scaleFactor)\n        {\n            GUILayout.Label(Styles.MeshesHeader, EditorStyles.boldLabel);\n\n            EditorGUILayout.Popup(unitConversionEnumValue, Styles.UnitConversionNames, Styles.UnitConversion);\n\n            bool bShowCustomScaleFactor = unitConversionEnumValue.intValue == Styles.UnitConversionNames.Length - 1;\n            if (bShowCustomScaleFactor)\n            {\n                EditorGUILayout.PropertyField(scaleFactor, Styles.ScaleFactor);\n                if (scaleFactor.floatValue < 0f)\n                {\n                    scaleFactor.floatValue = 0f;\n                }\n                if (scaleFactor.floatValue == 0f)\n                {\n                    EditorGUILayout.HelpBox(\"Scale factor must be positive.\", MessageType.Warning);\n                }\n            }\n        }\n\n        static internal void ShowMaterialGUI(\n            ref SerializedProperty mainColor,\n            ref SerializedProperty enableHueVariation,\n            ref SerializedProperty hueVariation,\n            ref SerializedProperty alphaTestRef,\n            ref SerializedProperty enableBumpMapping,\n            ref SerializedProperty enableSubsurfaceScattering,\n            bool renderHueVariationDropdown = false,\n            bool renderAlphaTestRef = false)\n        {\n            EditorGUILayout.LabelField(Styles.MaterialHeader, EditorStyles.boldLabel);\n\n            EditorGUILayout.PropertyField(mainColor, Styles.MainColor);\n            EditorGUILayout.PropertyField(enableHueVariation, Styles.EnableColorVariation);\n\n            if (renderHueVariationDropdown)\n            {\n                EditorGUILayout.PropertyField(hueVariation, Styles.HueVariation);\n            }\n\n            if (renderAlphaTestRef)\n                EditorGUILayout.Slider(alphaTestRef, 0f, 1f, Styles.AlphaTestRef);\n\n            EditorGUILayout.PropertyField(enableBumpMapping, Styles.EnableBump);\n            EditorGUILayout.PropertyField(enableSubsurfaceScattering, Styles.EnableSubsurface);\n        }\n\n        static internal void ShowLightingGUI(\n            ref SerializedProperty enableShadowCasting,\n            ref SerializedProperty enableShadowReceiving,\n            ref SerializedProperty enableLightProbeUsage,\n            ref SerializedProperty reflectionProbeUsage)\n        {\n            GUILayout.Label(Styles.LightingHeader, EditorStyles.boldLabel);\n\n            EditorGUILayout.PropertyField(enableShadowCasting, Styles.CastShadows);\n\n            // from the docs page: https://docs.unity3d.com/Manual/SpeedTree.html\n            // Known issues: As with any other renderer, the Receive Shadows option has no effect while using deferred rendering.\n            // TODO: test and conditionally expose this field\n            using (new EditorGUI.DisabledScope(!UnityEngine.Rendering.SupportedRenderingFeatures.active.receiveShadows))\n            {\n                EditorGUILayout.PropertyField(enableShadowReceiving, Styles.ReceiveShadows);\n            }\n\n            EditorGUILayout.PropertyField(enableLightProbeUsage, Styles.UseLightProbes);\n        }\n\n        static internal void ShowAdditionalSettingsGUI(\n            ref SerializedProperty motionVectorModeEnumValue,\n            ref SerializedProperty generateColliders,\n            ref SerializedProperty generateRigidbody)\n        {\n            GUILayout.Label(Styles.AdditionalSettingsHeader, EditorStyles.boldLabel);\n            EditorGUILayout.Popup(motionVectorModeEnumValue, Styles.MotionVectorModeNames, Styles.MotionVectorMode);\n\n            EditorGUILayout.PropertyField(generateColliders);\n            EditorGUILayout.PropertyField(generateRigidbody);\n        }\n\n        static internal void ShowWindGUI(\n            ref SerializedProperty bestWindQuality,\n            ref SerializedProperty selectedWindQuality)\n        {\n            GUILayout.Label(Styles.WindHeader, EditorStyles.boldLabel);\n\n            int NumAvailableWindQualityOptions = 1 + bestWindQuality.intValue; // 0 is None, we want at least 1 value\n            ArraySegment<GUIContent> availableWindQualityOptions = new ArraySegment<GUIContent>(Styles.GetWindQualityNames(), 0, NumAvailableWindQualityOptions);\n            EditorGUILayout.Popup(selectedWindQuality, availableWindQualityOptions.ToArray(), Styles.WindQuality);\n        }\n\n        static internal void ShowLODGUI(\n            ref SerializedProperty enableSmoothLOD,\n            ref SerializedProperty animateCrossFading,\n            ref SerializedProperty billboardTransitionCrossFadeWidth,\n            ref SerializedProperty fadeOutWidth,\n            ref AnimBool showSmoothLODOptions,\n            ref AnimBool showCrossFadeWidthOptions)\n        {\n            showSmoothLODOptions.target = enableSmoothLOD.hasMultipleDifferentValues || enableSmoothLOD.boolValue;\n            showCrossFadeWidthOptions.target = animateCrossFading.hasMultipleDifferentValues || !animateCrossFading.boolValue;\n\n            GUILayout.Label(Styles.LODHeader, EditorStyles.boldLabel);\n\n            EditorGUILayout.PropertyField(enableSmoothLOD, Styles.SmoothLOD);\n\n            using (new EditorGUI.IndentLevelScope())\n            {\n                // Note: FadeGroupScope doesn't work here, as if the 'faded' is not updated correctly.\n\n                if (EditorGUILayout.BeginFadeGroup(showSmoothLODOptions.faded))\n                {\n                    EditorGUILayout.PropertyField(animateCrossFading, Styles.AnimateCrossFading);\n\n                    if (EditorGUILayout.BeginFadeGroup(showCrossFadeWidthOptions.faded))\n                    {\n                        EditorGUILayout.Slider(billboardTransitionCrossFadeWidth, 0.0f, 1.0f, Styles.CrossFadeWidth);\n                        EditorGUILayout.Slider(fadeOutWidth, 0.0f, 1.0f, Styles.FadeOutWidth);\n                    }\n                    EditorGUILayout.EndFadeGroup();\n                }\n                EditorGUILayout.EndFadeGroup();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/SpeedTree/SpeedTreeImporterOutputData.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\n\nnamespace UnityEditor.SpeedTree.Importer\n{\n    internal class SpeedTreeImporterOutputData : ScriptableObject\n    {\n        /// <summary>\n        /// The main object of the asset.\n        /// </summary>\n        public GameObject mainObject;\n\n        /// <summary>\n        /// Contains the materials data and materials are assigned per LOD with an index.\n        /// </summary>\n        public LODMaterials lodMaterials = new LODMaterials();\n\n        /// <summary>\n        /// The materials metadata used for the materials extraction code.\n        /// </summary>\n        public List<AssetIdentifier> materialsIdentifiers = new List<AssetIdentifier>();\n\n        /// <summary>\n        /// Represents the wind configuration parameters.\n        /// </summary>\n        public SpeedTreeWindConfig9 m_WindConfig = new SpeedTreeWindConfig9();\n\n        /// <summary>\n        /// Determines if the current asset has embedded materials or not.\n        /// </summary>\n        public bool hasEmbeddedMaterials = false;\n\n        /// <summary>\n        /// Determines if the current Shader supports alpha clip threshold.\n        /// </summary>\n        public bool hasAlphaClipThreshold = false;\n\n        /// <summary>\n        /// Determines if the current Shader supports transmision scale.\n        /// </summary>\n        public bool hasTransmissionScale = false;\n\n        /// <summary>\n        /// Determines if the current asset has a biilboard or not.\n        /// </summary>\n        public bool hasBillboard = false;\n\n        /// <summary>\n        /// Create an instance of SpeedTreeImporterOutputData with default settings.\n        /// </summary>\n        /// <returns>The newly created SpeedTreeImporterOutputData instance.</returns>\n        static public SpeedTreeImporterOutputData Create()\n        {\n            SpeedTreeImporterOutputData outputImporterData = CreateInstance<SpeedTreeImporterOutputData>();\n            outputImporterData.name = \"ImporterOutputData\";\n\n            // Ideally, we should use this flag so the file is not visible in the asset prefab.\n            // Though, it breaks the 'AssetDatabase.LoadAssetAtPath' function (the file is not loaded anymore).\n            // outputImporterData.hideFlags = HideFlags.HideInHierarchy;\n\n            return outputImporterData;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/SpeedTree/SpeedTreeImporterSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing UnityEngine.Rendering;\n\nusing System.Collections.Generic;\nusing static UnityEditor.SpeedTree.Importer.SpeedTreeImporterCommon;\n\nnamespace UnityEditor.SpeedTree.Importer\n{\n    [Serializable]\n    internal class MeshSettings\n    {\n        public STUnitConversion unitConversion = STUnitConversion.kFeetToMeters;\n        public float scaleFactor = SpeedTreeConstants.kFeetToMetersRatio;\n    }\n\n    [Serializable]\n    internal class MaterialSettings\n    {\n        public Color mainColor = Color.white;\n        public Color hueVariation = new Color(1.0f, 0.5f, 0.0f, 0.1f);\n        public float alphaClipThreshold = 0.10f;\n        public float transmissionScale = 0.0f;\n\n        public bool enableHueVariation = false;\n        public bool enableBumpMapping = true;\n        public bool enableSubsurfaceScattering = true;\n\n        public Vector4 diffusionProfileAssetID = Vector4.zero;\n        public uint diffusionProfileID = 0;\n    }\n\n    [Serializable]\n    internal class LightingSettings\n    {\n        public bool enableShadowCasting = true;\n        public bool enableShadowReceiving = true;\n        public bool enableLightProbes = true;\n        public ReflectionProbeUsage reflectionProbeEnumValue = ReflectionProbeUsage.BlendProbes;\n    }\n\n    [Serializable]\n    internal class AdditionalSettings\n    {\n        public MotionVectorGenerationMode motionVectorModeEnumValue = MotionVectorGenerationMode.Object;\n        public bool generateColliders = true;\n        public bool generateRigidbody = true;\n    }\n\n    [Serializable]\n    internal class LODSettings\n    {\n        public bool enableSmoothLODTransition = true;\n        public bool animateCrossFading = true;\n        public float billboardTransitionCrossFadeWidth = 0.25f;\n        public float fadeOutWidth = 0.25f;\n        public bool hasBillboard = false;\n    }\n\n    [Serializable]\n    internal class PerLODSettings\n    {\n        public bool enableSettingOverride = false;\n\n        // LOD\n        public float height = 0.5f;\n\n        // Lighting\n        public bool castShadows = false;\n        public bool receiveShadows = false;\n        public bool useLightProbes = false;\n        public ReflectionProbeUsage reflectionProbeUsage = ReflectionProbeUsage.Off;\n\n        // Material\n        public bool enableBump = false;\n        public bool enableHue = false;\n        public bool enableSubsurface = false;\n    };\n\n    [Serializable]\n    internal class MaterialInfo\n    {\n        public Material material = null;\n        public string defaultName = null;\n        public bool exported = false;\n    }\n\n    [Serializable]\n    internal class LODMaterials\n    {\n        public List<MaterialInfo> materials = new List<MaterialInfo>();\n        public Dictionary<int, List<int>> lodToMaterials = new Dictionary<int, List<int>>();\n        public Dictionary<string, int> matNameToIndex = new Dictionary<string, int>();\n\n        public void AddLodMaterialIndex(int lod, int matIndex)\n        {\n            if (lodToMaterials.ContainsKey(lod))\n            {\n                lodToMaterials[lod].Add(matIndex);\n            }\n            else\n            {\n                lodToMaterials.Add(lod, new List<int>() { matIndex});\n            }\n        }\n    }\n\n    [Serializable]\n    internal class WindSettings\n    {\n        public bool enableWind = true;\n\n        [Range(1.0f, 20.0f)]\n        public float strenghResponse = 5.0f;\n\n        [Range(1.0f, 20.0f)]\n        public float directionResponse = 2.5f;\n\n        [Range(0.0f, 1.0f)]\n        public float randomness = 0.5f;\n    }\n\n    // Ideally, we should use 'AssetImporter.SourceAssetIdentifier', but this struct has many problems:\n    // 1 - 'Type' is not a serializable type, so it's always equal to null in our context.\n    // 2 - The C# struct is not matching the C++ class.\n    // 3 - Missing the 'Serializable' attribute on top of the struct.\n    [Serializable]\n    internal class AssetIdentifier\n    {\n        public string type;\n        public string name;\n\n        public AssetIdentifier(UnityEngine.Object asset)\n        {\n            if (asset == null)\n            {\n                throw new ArgumentNullException(\"asset\");\n            }\n\n            this.type = asset.GetType().ToString();\n            this.name = asset.name;\n        }\n\n        public AssetIdentifier(Type type, string name)\n        {\n            if (type == null)\n            {\n                throw new ArgumentNullException(\"type\");\n            }\n\n            if (name == null)\n            {\n                throw new ArgumentNullException(\"name\");\n            }\n\n            if (string.IsNullOrEmpty(name))\n            {\n                throw new ArgumentException(\"The name is empty\", \"name\");\n            }\n\n            this.type = type.ToString();\n            this.name = name;\n        }\n    }\n\n    /// <summary>\n    /// This attribute is used as a callback to set SRP specific properties from the importer.\n    /// </summary>\n    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]\n    public class MaterialSettingsCallbackAttribute : Attribute\n    {\n        /// <summary>\n        /// The version of the method.\n        /// </summary>\n        public int MethodVersion;\n\n        /// <summary>\n        /// Initializes a new instance of the MaterialSettingsCallbackAttribute with the given method version.\n        /// </summary>\n        /// <param name=\"methodVersion\">The given method version.</param>\n        public MaterialSettingsCallbackAttribute(int methodVersion)\n        {\n            MethodVersion = methodVersion;\n        }\n\n        [RequiredSignature]\n        static void SignatureExample(GameObject mainObject)\n        {\n            throw new InvalidOperationException();\n        }\n    }\n\n    /// <summary>\n    /// This attribute is used as a callback to extend the inspector by adding\n    /// the Diffuse Profile property when the HDRP package is in use.\n    /// </summary>\n    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]\n    public class DiffuseProfileCallbackAttribute : Attribute\n    {\n        /// <summary>\n        /// The version of the method.\n        /// </summary>\n        public int MethodVersion;\n\n        /// <summary>\n        /// Initializes a new instance of the DiffuseProfileCallbackAttribute with the given method version.\n        /// </summary>\n        /// <param name=\"methodVersion\">The given method version.</param>\n        public DiffuseProfileCallbackAttribute(int methodVersion)\n        {\n            MethodVersion = methodVersion;\n        }\n\n        [RequiredSignature]\n        static void SignatureExample(ref SerializedProperty diffusionProfileAsset, ref SerializedProperty diffusionProfileHash)\n        {\n            throw new InvalidOperationException();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/SpeedTreeImporter.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/AssetPipeline/SpeedTreeImporter.h\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/SpeedTreeImporter.bindings.h\")]\n    [NativeHeader(\"Runtime/Camera/ReflectionProbeTypes.h\")]\n    public partial class SpeedTreeImporter : AssetImporter\n    {\n        public enum MaterialLocation\n        {\n            External = 0,\n            InPrefab = 1\n        }\n\n        public extern bool hasImported\n        {\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::HasImported\", HasExplicitThis = true)]\n            get;\n        }\n\n        public extern string materialFolderPath\n        {\n            get;\n        }\n\n        public extern MaterialLocation materialLocation\n        {\n            get;\n            set;\n        }\n\n        public extern bool isV8\n        {\n            get;\n        }\n\n        public extern Shader defaultShader { get; }\n\n        public extern Shader defaultBillboardShader { get; }\n\n        /////////////////////////////////////////////////////////////////////////////\n        // Mesh properties\n\n        public extern float scaleFactor { get; set; }\n\n\n        /////////////////////////////////////////////////////////////////////////////\n        // Material properties\n\n        public extern Color mainColor { get; set; }\n\n        // The below properties (specColor and shininess) were first made obsolete in 5.4, they didn't work anyway, AND SpeedTreeImporter should rarely be scripted by anyone\n        // because of that I would say they can be safely removed for 5.6\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"specColor is no longer used and has been deprecated.\", true)]\n        public Color specColor {  get; set; }\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"shininess is no longer used and has been deprecated.\", true)]\n        public float shininess {  get; set; }\n\n        public extern Color hueVariation { get; set; }\n        public extern float alphaTestRef { get; set; }\n        public extern bool enableBumpByDefault { get; set; }\n        public extern bool enableHueByDefault { get; set; }\n        public extern bool enableSubsurfaceByDefault { get; set; }\n\n        /////////////////////////////////////////////////////////////////////////////\n        // Lighting properties\n\n        public extern bool castShadowsByDefault { get; set; }\n        public extern bool receiveShadowsByDefault { get; set; }\n        public extern bool useLightProbesByDefault { get; set; }\n        public extern int reflectionProbeUsagesByDefault { get; set; }\n\n        /////////////////////////////////////////////////////////////////////////////\n        // Wind properties\n\n        public static readonly string[] windQualityNames = new[] { \"None\", \"Fastest\", \"Fast\", \"Better\", \"Best\", \"Palm\" };\n        public extern int bestWindQuality { get; }\n        public extern int selectedWindQuality { get; set; }\n\n        /////////////////////////////////////////////////////////////////////////////\n        // Physics settings\n\n        public extern bool generateRigidbody { get; set; }\n        public extern bool generateColliders { get; set; }\n\n        /////////////////////////////////////////////////////////////////////////////\n        // LOD settings\n\n        public extern bool hasBillboard\n        {\n            [NativeName(\"HasBillboard\")]\n            get;\n        }\n\n\n        public extern bool enableSmoothLODTransition { get; set; }\n        public extern bool animateCrossFading { get; set; }\n        public extern float billboardTransitionCrossFadeWidth { get; set; }\n        public extern float fadeOutWidth { get; set; }\n\n        public extern bool[] enableSettingOverride\n        {\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::GetEnableSettingOverride\", HasExplicitThis = true)]\n            get;\n            [NativeThrows]\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::SetEnableSettingOverride\", HasExplicitThis = true)]\n            set;\n        }\n\n        public extern float[] LODHeights\n        {\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::GetLODHeights\", HasExplicitThis = true)]\n            get;\n            [NativeThrows]\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::SetLODHeights\", HasExplicitThis = true)]\n            set;\n        }\n\n        public extern bool[] castShadows\n        {\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::GetCastShadows\", HasExplicitThis = true)]\n            get;\n            [NativeThrows]\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::SetCastShadows\", HasExplicitThis = true)]\n            set;\n        }\n\n        public extern bool[] receiveShadows\n        {\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::GetReceiveShadows\", HasExplicitThis = true)]\n            get;\n            [NativeThrows]\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::SetReceiveShadows\", HasExplicitThis = true)]\n            set;\n        }\n\n        public extern bool[] useLightProbes\n        {\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::GetUseLightProbes\", HasExplicitThis = true)]\n            get;\n            [NativeThrows]\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::SetUseLightProbes\", HasExplicitThis = true)]\n            set;\n        }\n\n        public extern ReflectionProbeUsage[] reflectionProbeUsages\n        {\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::GetReflectionProbeUsages\", HasExplicitThis = true)]\n            get;\n            [NativeThrows]\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::SetReflectionProbeUsages\", HasExplicitThis = true)]\n            set;\n        }\n\n        public extern bool[] enableBump\n        {\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::GetEnableBump\", HasExplicitThis = true)]\n            get;\n            [NativeThrows]\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::SetEnableBump\", HasExplicitThis = true)]\n            set;\n        }\n\n        public extern bool[] enableHue\n        {\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::GetEnableHue\", HasExplicitThis = true)]\n            get;\n            [NativeThrows]\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::SetEnableHue\", HasExplicitThis = true)]\n            set;\n        }\n\n        public extern bool[] enableSubsurface\n        {\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::GetEnableSubsurface\", HasExplicitThis = true)]\n            get;\n            [NativeThrows]\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::SetEnableSubsurface\", HasExplicitThis = true)]\n            set;\n        }\n\n        public extern int[] windQualities\n        {\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::GetWindQuality\", HasExplicitThis = true)]\n            get;\n            [NativeThrows]\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::SetWindQuality\", HasExplicitThis = true)]\n            set;\n        }\n\n        /////////////////////////////////////////////////////////////////////////////\n\n        public extern void GenerateMaterials();\n\n        internal extern bool materialsShouldBeRegenerated\n        {\n            [NativeName(\"MaterialsShouldBeRegenerated\")]\n            get;\n        }\n\n        internal extern void SetMaterialVersionToCurrent();\n\n        internal extern SourceAssetIdentifier[] sourceMaterials\n        {\n            [FreeFunction(Name = \"SpeedTreeImporterBindings::GetSourceMaterials\", HasExplicitThis = true)]\n            get;\n        }\n\n        public bool SearchAndRemapMaterials(string materialFolderPath)\n        {\n            bool changedMappings = false;\n\n            if (materialFolderPath == null)\n                throw new ArgumentNullException(\"materialFolderPath\");\n\n            if (string.IsNullOrEmpty(materialFolderPath))\n                throw new ArgumentException(string.Format(\"Invalid material folder path: {0}.\", materialFolderPath), \"materialFolderPath\");\n\n            var guids = AssetDatabase.FindAssets(\"t:Material\", new string[] { materialFolderPath });\n            List<Tuple<string, Material>> materials = new List<Tuple<string, Material>>();\n            foreach (var guid in guids)\n            {\n                var path = AssetDatabase.GUIDToAssetPath(guid);\n                // ensure that we only load material assets, not embedded materials\n                var material = AssetDatabase.LoadMainAssetAtPath(path) as Material;\n                if (material)\n                    materials.Add(new Tuple<string, Material>(path, material));\n            }\n\n            var importedMaterials = sourceMaterials;\n            foreach (var material in materials)\n            {\n                var materialName = material.Item2.name;\n                var materialFile = material.Item1;\n\n                // the legacy materials have the LOD in the path, while the new materials have the LOD as part of the name\n                var isLegacyMaterial = !materialName.Contains(\"LOD\") && !materialName.Contains(\"Billboard\");\n                var hasLOD = isLegacyMaterial && materialFile.Contains(\"LOD\");\n                var lod = Path.GetFileNameWithoutExtension(Path.GetDirectoryName(materialFile));\n                var importedMaterial = Array.Find(importedMaterials, x => x.name.Contains(materialName) && (!hasLOD || x.name.Contains(lod)));\n\n                if (!string.IsNullOrEmpty(importedMaterial.name))\n                {\n                    AddRemap(importedMaterial, material.Item2);\n                    changedMappings = true;\n                }\n            }\n\n            return changedMappings;\n        }\n    }\n\n    class SpeedTreePostProcessor : AssetPostprocessor\n    {\n        private static void FixExtraTexture_sRGB(IEnumerable<UnityEngine.Object> subAssets)\n        {\n            AssetDatabase.StartAssetEditing();\n\n            foreach (var subAsset in subAssets)\n            {\n                if (subAsset is Material)\n                {\n                    Material m = subAsset as Material;\n                    Texture tex = m.GetTexture(\"_ExtraTex\");\n                    if (tex)\n                    {\n                        string texturePath = AssetDatabase.GetAssetOrScenePath(tex);\n                        TextureImporter texImporter = AssetImporter.GetAtPath(texturePath) as TextureImporter;\n                        if(texImporter)\n                        {\n                            // Multiple materials may be referencing the same ExtraTexture, therefore\n                            // we'll need to check the importer's setting and only queue a single reimport\n                            // for a given texture.\n                            if (texImporter.sRGBTexture)\n                            {\n                                texImporter.sRGBTexture = false; // extra texture does not contain color data, hence shouldn't be sRGB.\n                                texImporter.SaveAndReimport();\n                            }\n\n                            \n                        }\n                    }\n                }\n            }\n            AssetDatabase.StopAssetEditing();\n        }\n\n        static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)\n        {\n            foreach (var asset in importedAssets)\n            {\n                bool st8 = asset.EndsWith(\".st\", StringComparison.OrdinalIgnoreCase);\n                if(st8)\n                {\n                    SpeedTreeImporter importer = AssetImporter.GetAtPath(asset) as SpeedTreeImporter;\n                    if (importer == null)\n                        continue;\n\n                    // Check the external materials in case the user has extracted\n                    Dictionary<AssetImporter.SourceAssetIdentifier, UnityEngine.Object> externalAssets = importer.GetExternalObjectMap();\n                    if(externalAssets != null)\n                        FixExtraTexture_sRGB(externalAssets.Values);\n\n                    // Check the object subassets -- updates the materials if they're embedded in the SpeedTree asset\n                    UnityEngine.Object[] subAssets = AssetDatabase.LoadAllAssetsAtPath(asset);\n                    FixExtraTexture_sRGB(subAssets);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing System.Runtime.InteropServices;\nusing System.Collections.Generic;\nusing Unity.Collections;\nusing Unity.Collections.LowLevel.Unsafe;\nusing UnityEngine.Scripting.APIUpdating;\n\nnamespace UnityEditor.AssetImporters\n{\n    [StructLayout(LayoutKind.Sequential)]\n    [MovedFrom(\"UnityEditor.Experimental.AssetImporters\")]\n    public struct SpriteImportData\n    {\n        private string m_Name;\n        private Rect m_Rect;\n        private SpriteAlignment m_Alignment;\n        private Vector2 m_Pivot;\n        private Vector4 m_Border;\n        private string m_CustomData;\n        private float m_TessellationDetail;\n        private string m_SpriteID;\n        private List<Vector2[]> m_Outline;\n\n        public string name { get { return m_Name; } set { m_Name = value; } }\n        public Rect rect { get { return m_Rect; } set { m_Rect = value; } }\n        public SpriteAlignment alignment { get { return m_Alignment; } set { m_Alignment = value; } }\n        public Vector2 pivot { get { return m_Pivot; } set { m_Pivot = value; } }\n        public Vector4 border { get { return m_Border; } set { m_Border = value; } }\n        internal string customData { get { return m_CustomData; } set { m_CustomData = value; } }\n        public List<Vector2[]> outline { get { return m_Outline; } set { m_Outline = value; } }\n        public float tessellationDetail {get { return m_TessellationDetail; } set { m_TessellationDetail = value; } }\n        public string spriteID {get { return m_SpriteID; } set { m_SpriteID = value; } }\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    [MovedFrom(\"UnityEditor.Experimental.AssetImporters\")]\n    public struct TextureGenerationOutput\n    {\n        [NativeName(\"texture\")]\n        private Texture m_Texture;\n        [NativeName(\"importInspectorWarnings\")]\n        private string m_ImportInspectorWarnings;\n        [NativeName(\"importWarnings\")]\n        private string[] m_ImportWarnings;\n        [NativeName(\"thumbNail\")]\n        private Texture2D m_ThumbNail;\n        [NativeName(\"sprites\")]\n        private Sprite[] m_Sprites;\n\n        public Texture2D texture { get { return m_Texture as Texture2D; } }\n        public Texture output { get { return m_Texture; } }\n        public string importInspectorWarnings { get { return m_ImportInspectorWarnings; } }\n        public string[] importWarnings { get { return m_ImportWarnings; } }\n        public Texture2D thumbNail { get { return m_ThumbNail; } }\n        public Sprite[] sprites { get { return m_Sprites; } }\n    }\n\n\n    [StructLayout(LayoutKind.Sequential)]\n    [NativeAsStruct]\n    [MovedFrom(\"UnityEditor.Experimental.AssetImporters\")]\n    public class SourceTextureInformation\n    {\n        [NativeName(\"width\")]\n        private int m_Width;\n        [NativeName(\"height\")]\n        private int m_Height;\n        [NativeName(\"sourceContainsAlpha\")]\n        private bool m_SourceContainsAlpha;\n        [NativeName(\"sourceWasHDR\")]\n        private bool m_SourceWasHDR;\n\n        public int width { get { return m_Width; } set {m_Width = value; } }\n        public int height { get { return m_Height; } set {m_Height = value; } }\n        public bool containsAlpha { get { return m_SourceContainsAlpha; } set {m_SourceContainsAlpha = value; } }\n        public bool hdr { get { return m_SourceWasHDR; } set {m_SourceWasHDR = value; } }\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    [MovedFrom(\"UnityEditor.Experimental.AssetImporters\")]\n    public struct TextureGenerationSettings\n    {\n        [NativeName(\"assetPath\")]\n        private string m_AssetPath;\n        [NativeName(\"qualifyForSpritePacking\")]\n        private bool m_QualifyForSpritePacking;\n        [NativeName(\"enablePostProcessor\")]\n        private bool m_EnablePostProcessor;\n        [NativeName(\"tiSettings\")]\n        private TextureImporterSettings m_Settings;\n        [NativeName(\"platformSettings\")]\n        private TextureImporterPlatformSettings m_PlatformSettings;\n        [NativeName(\"sourceTextureInformation\")]\n        private SourceTextureInformation m_SourceTextureInformation;\n        [NativeName(\"spriteSheetData\")]\n        private SpriteImportData[] m_SpriteImportData;\n        [NativeName(\"spritePackingTag\")]\n        private string m_SpritePackingTag;\n        [NativeName(\"secondarySpriteTextures\")]\n        private SecondarySpriteTexture[] m_SecondarySpriteTextures;\n\n        public TextureGenerationSettings(TextureImporterType type)\n        {\n            m_EnablePostProcessor = true;\n            m_AssetPath = \"\";\n            m_QualifyForSpritePacking = false;\n            m_SpritePackingTag = \"\";\n            m_SpriteImportData = null;\n            m_SecondarySpriteTextures = null;\n\n            m_SourceTextureInformation = new SourceTextureInformation();\n            m_SourceTextureInformation.width = m_SourceTextureInformation.height = 0;\n            m_SourceTextureInformation.containsAlpha = false;\n            m_SourceTextureInformation.hdr = false;\n\n            m_PlatformSettings = new TextureImporterPlatformSettings();\n            m_PlatformSettings.overridden = false;\n            m_PlatformSettings.format = TextureImporterFormat.Automatic;\n            m_PlatformSettings.maxTextureSize = 2048;\n            m_PlatformSettings.allowsAlphaSplitting = false;\n            m_PlatformSettings.resizeAlgorithm = TextureResizeAlgorithm.Mitchell;\n            m_PlatformSettings.compressionQuality = (int)TextureCompressionQuality.Normal;\n            m_PlatformSettings.crunchedCompression = false;\n            m_PlatformSettings.name = TextureImporter.defaultPlatformName;\n\n            // Values from TextureImporterSettings native constructor\n            m_Settings = new TextureImporterSettings();\n            m_Settings.textureType = type;\n            m_Settings.textureShape = TextureImporterShape.Texture2D;\n            m_Settings.convertToNormalMap = false;\n            m_Settings.mipmapEnabled = true;\n            m_Settings.mipmapFilter = TextureImporterMipFilter.BoxFilter;\n            m_Settings.sRGBTexture = true;\n            m_Settings.borderMipmap = false;\n            m_Settings.mipMapsPreserveCoverage = false;\n            m_Settings.alphaTestReferenceValue = 0.5f;\n            m_Settings.readable = false;\n            m_Settings.fadeOut = false;\n            m_Settings.mipmapFadeDistanceStart = 1;\n            m_Settings.mipmapFadeDistanceEnd = 3;\n            m_Settings.heightmapScale = 0.25f;\n            m_Settings.normalMapFilter = TextureImporterNormalFilter.Standard;\n            m_Settings.flipGreenChannel = false;\n            m_Settings.swizzleRaw = 0x03020100; // R,G,B,A\n            m_Settings.cubemapConvolution = 0;\n            m_Settings.generateCubemap = TextureImporterGenerateCubemap.AutoCubemap;\n            m_Settings.seamlessCubemap = false;\n            m_Settings.npotScale = TextureImporterNPOTScale.ToNearest;\n            m_Settings.spriteMode = (int)SpriteImportMode.Single;\n            m_Settings.spriteExtrude = 1;\n            m_Settings.spriteMeshType = SpriteMeshType.Tight;\n            m_Settings.spriteAlignment = (int)SpriteAlignment.Center;\n            m_Settings.spritePivot = Vector2.one * 0.5f;\n            m_Settings.spritePixelsPerUnit = 100;\n            m_Settings.spriteBorder = Vector4.zero;\n            m_Settings.alphaSource = TextureImporterAlphaSource.FromInput;\n            m_Settings.alphaIsTransparency = false;\n            m_Settings.spriteTessellationDetail = -1;\n            m_Settings.wrapMode = m_Settings.wrapModeU = m_Settings.wrapModeV = m_Settings.wrapModeW = TextureWrapMode.Repeat;\n\n            // From TextureImporterSettings::ApplyTextureType\n            switch (type)\n            {\n                case TextureImporterType.Default:\n                    m_Settings.sRGBTexture = true;\n                    m_Settings.mipmapEnabled = true;\n                    break;\n                case TextureImporterType.NormalMap:\n                    m_Settings.sRGBTexture = false;\n                    break;\n                case TextureImporterType.GUI:\n                    m_Settings.sRGBTexture = false;\n                    m_Settings.mipmapEnabled = false;\n                    m_Settings.alphaIsTransparency = true;\n                    m_Settings.npotScale = TextureImporterNPOTScale.None;\n                    m_Settings.aniso = 1;\n                    m_Settings.wrapMode = m_Settings.wrapModeU = m_Settings.wrapModeV = m_Settings.wrapModeW = TextureWrapMode.Clamp;\n                    break;\n                case TextureImporterType.Sprite:\n                    m_Settings.npotScale = TextureImporterNPOTScale.None;\n                    m_Settings.alphaIsTransparency = true;\n                    m_Settings.mipmapEnabled = false;\n                    m_Settings.sRGBTexture = true;\n                    m_Settings.wrapMode = m_Settings.wrapModeU = m_Settings.wrapModeV = m_Settings.wrapModeW = TextureWrapMode.Clamp;\n                    m_Settings.alphaSource = TextureImporterAlphaSource.FromInput;\n                    break;\n                case TextureImporterType.Cursor:\n                    m_Settings.readable = true;\n                    m_Settings.alphaIsTransparency = true;\n                    m_Settings.mipmapEnabled = false;\n                    m_Settings.npotScale = TextureImporterNPOTScale.None;\n                    m_Settings.aniso = 1;\n                    m_Settings.wrapMode = m_Settings.wrapModeU = m_Settings.wrapModeV = m_Settings.wrapModeW = TextureWrapMode.Clamp;\n                    break;\n                case TextureImporterType.Cookie:\n                    m_Settings.borderMipmap = true;\n                    m_Settings.wrapMode = m_Settings.wrapModeU = m_Settings.wrapModeV = m_Settings.wrapModeW = TextureWrapMode.Clamp;\n                    m_Settings.aniso = 0;\n                    break;\n                case TextureImporterType.Lightmap:\n                    m_Settings.sRGBTexture = true;\n                    m_Settings.npotScale = TextureImporterNPOTScale.ToNearest;\n                    m_Settings.alphaIsTransparency = false;\n                    m_Settings.alphaSource = TextureImporterAlphaSource.None;\n                    break;\n                case TextureImporterType.DirectionalLightmap:\n                    m_Settings.sRGBTexture = false;\n                    m_Settings.npotScale = TextureImporterNPOTScale.ToNearest;\n                    m_Settings.alphaIsTransparency = false;\n                    m_Settings.alphaSource = TextureImporterAlphaSource.None;\n                    break;\n                case TextureImporterType.Shadowmask:\n                    m_Settings.sRGBTexture = false;\n                    m_Settings.npotScale = TextureImporterNPOTScale.ToNearest;\n                    m_Settings.alphaIsTransparency = false;\n                    m_Settings.alphaSource = TextureImporterAlphaSource.None;\n                    break;\n                case TextureImporterType.SingleChannel:\n                    m_Settings.sRGBTexture = false;\n                    break;\n            }\n        }\n\n        public string assetPath { get { return m_AssetPath; } set { m_AssetPath = value; } }\n        public bool qualifyForSpritePacking { get { return m_QualifyForSpritePacking; } set { m_QualifyForSpritePacking = value; } }\n        public bool enablePostProcessor { get { return m_EnablePostProcessor; } set { m_EnablePostProcessor = value; } }\n        public TextureImporterSettings textureImporterSettings { get { return m_Settings; } set { m_Settings = value; } }\n        public TextureImporterPlatformSettings platformSettings { get { return m_PlatformSettings; } set { m_PlatformSettings = value; } }\n        public SourceTextureInformation sourceTextureInformation { get { return m_SourceTextureInformation; } set { m_SourceTextureInformation = value; } }\n        public SpriteImportData[] spriteImportData { get { return m_SpriteImportData; } set { m_SpriteImportData = value; } }\n        public string spritePackingTag { get { return m_SpritePackingTag; } set { m_SpritePackingTag = value; } }\n        public SecondarySpriteTexture[] secondarySpriteTextures { get { return m_SecondarySpriteTextures; } set { m_SecondarySpriteTextures = value; } }\n    }\n\n\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/TextureGenerator.h\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/TextureImporterTypes.h\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/TextureImporter.bindings.h\")]\n    [NativeHeader(\"Runtime/Serialize/BuildTarget.h\")]\n    [MovedFrom(\"UnityEditor.Experimental.AssetImporters\")]\n    public static unsafe class TextureGenerator\n    {\n        public static TextureGenerationOutput GenerateTexture(TextureGenerationSettings settings, NativeArray<Color32> colorBuffer)\n        {\n            return GenerateTextureImpl(settings, colorBuffer.GetUnsafeReadOnlyPtr(), colorBuffer.Length * UnsafeUtility.SizeOf<Color32>(), 4);\n        }\n        \n        public static TextureGenerationOutput GenerateTexture(TextureGenerationSettings settings, NativeArray<Color> colorBuffer)\n        {\n            return GenerateTextureImpl(settings, colorBuffer.GetUnsafeReadOnlyPtr(), colorBuffer.Length * UnsafeUtility.SizeOf<Color>(), 16);\n        }\n\n        [NativeThrows]\n        [NativeMethod(\"GenerateTextureScripting\")]\n        extern static unsafe TextureGenerationOutput GenerateTextureImpl(TextureGenerationSettings settings, void* colorBuffer, int colorBufferLength, int bytesPerPixel);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/TextureImporter.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing UnityEditor.Build;\nusing UnityEditor.AssetImporters;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    // Texture importer lets you modify [[Texture2D]] import settings from editor scripts.\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/TextureImporter.h\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/TextureImporter.deprecated.h\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/TextureImporterUtils.h\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/TextureImporterPlatformSettingsUtils.h\")]\n    [NativeHeader(\"Editor/Src/EditorUserBuildSettings.h\")]\n    public sealed partial class TextureImporter : AssetImporter\n    {\n        [FreeFunction]\n        internal static extern string GetTexturePlatformSerializationName(string platformName);\n\n        [Obsolete(\"textureFormat is no longer accessible at the TextureImporter level. For old 'simple' formats use the textureCompression property for the equivalent automatic choice (Uncompressed for TrueColor, Compressed and HQCommpressed for 16 bits). For platform specific formats use the [[PlatformTextureSettings]] API. Using this setter will setup various parameters to match the new automatic system as well as possible. Getter will return the last value set.\")]\n        public extern TextureImporterFormat textureFormat\n        {\n            [FreeFunction(\"GetTextureFormat\", HasExplicitThis = true)]\n            get;\n            [FreeFunction(\"SetTextureFormat\", HasExplicitThis = true)]\n            set;\n        }\n\n        [NativeProperty(\"TextureImporter::s_DefaultPlatformName\", true, TargetType.Field)]\n        internal static extern string defaultPlatformName\n        {\n            get;\n        }\n\n        public extern int maxTextureSize { get; set; }\n        [NativeProperty(\"TextureCompressionQuality\", false, TargetType.Function)]\n        public extern int compressionQuality { get; set; }\n        public extern bool crunchedCompression { get; set; }\n        public extern bool allowAlphaSplitting { get; set; }\n\n        public extern AndroidETC2FallbackOverride androidETC2FallbackOverride { get; set; }\n        public extern TextureImporterCompression textureCompression { get; set; }\n        public extern TextureImporterAlphaSource alphaSource { get; set; }\n\n        internal extern bool forceMaximumCompressionQuality_BC6H_BC7 { get; set; }\n\n        // Generate alpha channel from intensity?\n        [Obsolete(\"Use UnityEditor.TextureImporter.alphaSource instead.\")]\n        public bool grayscaleToAlpha\n        {\n            get { return alphaSource == TextureImporterAlphaSource.FromGrayScale; }\n            set { if (value) alphaSource = TextureImporterAlphaSource.FromGrayScale; else alphaSource = TextureImporterAlphaSource.FromInput; }\n        }\n\n        // TODO: make this use struct for possible future expansion\n\n        // Whether the texture allows alpha splitting for compressions like ETC1\n        [Obsolete(\"Use UnityEditor.TextureImporter.GetPlatformTextureSettings() instead.\")]\n        [NativeMethod(HasExplicitThis = true)]\n        public extern bool GetAllowsAlphaSplitting();\n\n        [Obsolete(\"Use UnityEditor.TextureImporter.SetPlatformTextureSettings() instead.\")]\n        [NativeMethod(HasExplicitThis = true)]\n        public extern void SetAllowsAlphaSplitting(bool flag);\n\n        public bool GetPlatformTextureSettings(string platform, out int maxTextureSize, out TextureImporterFormat textureFormat, out int compressionQuality, out bool etc1AlphaSplitEnabled)\n        {\n            TextureImporterPlatformSettings settings = GetPlatformTextureSettings(platform);\n            maxTextureSize = settings.maxTextureSize;\n            textureFormat = settings.format;\n            compressionQuality = settings.compressionQuality;\n            etc1AlphaSplitEnabled = settings.allowsAlphaSplitting;\n\n            return settings.overridden;\n        }\n\n        public bool GetPlatformTextureSettings(string platform, out int maxTextureSize, out TextureImporterFormat textureFormat, out int compressionQuality)\n        {\n            bool etc1AlphaSplitEnabled = false;\n            return GetPlatformTextureSettings(platform, out maxTextureSize, out textureFormat, out compressionQuality, out etc1AlphaSplitEnabled);\n        }\n\n        public bool GetPlatformTextureSettings(string platform, out int maxTextureSize, out TextureImporterFormat textureFormat)\n        {\n            int compressionQuality = 0;\n            bool etc1AlphaSplitEnabled = false;\n            return GetPlatformTextureSettings(platform, out maxTextureSize, out textureFormat, out compressionQuality, out etc1AlphaSplitEnabled);\n        }\n\n        // C++ implementation will return default platform if the requested platform is not valid.\n        // See \"Editor/Mono/BuildPipeline/BuildPlatform.cs\" -> \"GetValidPlatformNames\" for more\n        // information regarding what is considered to be a valid platform.\n        [NativeName(\"GetPlatformTextureSettings\")]\n        private extern TextureImporterPlatformSettings GetPlatformTextureSetting_Internal(string platform);\n\n        // Read texture settings for specified platform into [[TextureImporterPlatformSettings]] class.\n        // public API will always return a valid TextureImporterPlatformSettings, creating it based on the default one if it did not exist.\n        public TextureImporterPlatformSettings GetPlatformTextureSettings(string platform)\n        {\n            platform = GetTexturePlatformSerializationName(platform); // String may refer to a platform group: if != \"Standalone\", ensure it refers to a platform instead. E.g.: \"iOS\", not \"iPhone\".\n\n            TextureImporterPlatformSettings dest = GetPlatformTextureSetting_Internal(platform);\n            if (platform != dest.name)\n            {\n                dest.name = platform;\n                dest.overridden = false;\n            }\n            return dest;\n        }\n\n        public TextureImporterPlatformSettings GetDefaultPlatformTextureSettings()\n        {\n            return GetPlatformTextureSettings(TextureImporterInspector.s_DefaultPlatformName);\n        }\n\n        public TextureImporterFormat GetAutomaticFormat(string platform)\n        {\n            platform = GetTexturePlatformSerializationName(platform); // String may refer to a platform group: if != \"Standalone\", ensure it refers to a platform instead. E.g.: \"iOS\", not \"iPhone\".\n            TextureImporterSettings settings = new TextureImporterSettings();\n            ReadTextureSettings(settings);\n            TextureImporterPlatformSettings platformSettings = GetPlatformTextureSettings(platform);\n\n            BuildTarget buildTarget = BuildPipeline.GetBuildTargetByName(platform);\n            if (buildTarget != BuildTarget.NoTarget)\n            {\n                return DefaultFormatFromTextureParameters(settings,\n                    !platformSettings.overridden ? GetDefaultPlatformTextureSettings() : platformSettings,\n                    DoesSourceTextureHaveAlpha(),\n                    IsSourceTextureHDR(),\n                    buildTarget);\n\n                // Regarding the \"GetDefaultPlatformTextureSettings\" call: in case 1281084, we made it so that platform settings stop automatically\n                // resetting to the default platform's settings when the platform override is disabled. This introduced a regression where\n                // \"GetAutomaticFormat\" would not return the actual format used by platforms with a disabled override, (as in, the one indicated in\n                // the default platform's settings) which is why we pass in the default platform's settings instead.\n            }\n\n            return TextureImporterFormat.Automatic;\n        }\n\n        [Obsolete(\"Use UnityEditor.TextureImporter.SetPlatformTextureSettings(TextureImporterPlatformSettings) instead.\")]\n        public void SetPlatformTextureSettings(string platform, int maxTextureSize, TextureImporterFormat textureFormat, int compressionQuality, bool allowsAlphaSplit)\n        {\n            TextureImporterPlatformSettings dest = GetPlatformTextureSettings(platform);\n            dest.overridden = true;\n            dest.maxTextureSize = maxTextureSize;\n            dest.format = textureFormat;\n            dest.compressionQuality = compressionQuality;\n            dest.allowsAlphaSplitting = allowsAlphaSplit;\n            SetPlatformTextureSettings(dest);\n        }\n\n        [Obsolete(\"Use UnityEditor.TextureImporter.SetPlatformTextureSettings(TextureImporterPlatformSettings) instead.\")]\n        public void SetPlatformTextureSettings(string platform, int maxTextureSize, TextureImporterFormat textureFormat)\n        {\n            SetPlatformTextureSettings(platform, maxTextureSize, textureFormat, false);\n        }\n\n        [Obsolete(\"Use UnityEditor.TextureImporter.SetPlatformTextureSettings(TextureImporterPlatformSettings) instead.\")]\n        public void SetPlatformTextureSettings(string platform, int maxTextureSize, TextureImporterFormat textureFormat, [DefaultValue(false)] bool allowsAlphaSplit)\n        {\n            TextureImporterPlatformSettings dest = GetPlatformTextureSettings(platform);\n            dest.overridden = true;\n            dest.maxTextureSize = maxTextureSize;\n            dest.format = textureFormat;\n            dest.allowsAlphaSplitting = allowsAlphaSplit;\n            SetPlatformTextureSettings(dest);\n        }\n\n        [NativeName(\"SetPlatformTextureSettings\")]\n        private extern void SetPlatformTextureSettings_Internal(TextureImporterPlatformSettings platformSettings);\n\n        // Set specific target platform settings\n        public void SetPlatformTextureSettings(TextureImporterPlatformSettings platformSettings)\n        {\n            platformSettings.name = GetTexturePlatformSerializationName(platformSettings.name); // String may refer to a platform group: if != \"Standalone\", ensure it refers to a platform instead. E.g.: \"iOS\", not \"iPhone\".\n            SetPlatformTextureSettings_Internal(platformSettings);\n        }\n\n        // Clear specific target platform settings\n        [NativeName(\"ClearPlatformTextureSettings\")]\n        private extern void ClearPlatformTextureSettings_Internal(string platform);\n\n        public void ClearPlatformTextureSettings(string platform)\n        {\n            platform = GetTexturePlatformSerializationName(platform); // String may refer to a platform group: if != \"Standalone\", ensure it refers to a platform instead. E.g.: \"iOS\", not \"iPhone\".\n            ClearPlatformTextureSettings_Internal(platform);\n        }\n\n        [FreeFunction]\n        internal static extern  TextureImporterFormat DefaultFormatFromTextureParameters([NotNull] TextureImporterSettings settings, TextureImporterPlatformSettings platformSettings, bool doesTextureContainAlpha, bool sourceWasHDR, BuildTarget destinationPlatform);\n\n        [FreeFunction]\n        internal static extern TextureImporterFormat[] RecommendedFormatsFromTextureTypeAndPlatform(TextureImporterType textureType, BuildTarget destinationPlatform);\n\n        [RequiredByNativeCode]\n        public static bool IsPlatformTextureFormatValid(TextureImporterType textureType, BuildTarget target, TextureImporterFormat currentFormat)\n        {\n            if (currentFormat != TextureImporterFormat.Automatic)\n            {\n                int[] formatValues;\n                string[] formatStrings;\n                TextureImportValidFormats.GetPlatformTextureFormatValuesAndStrings(textureType, target, out formatValues, out formatStrings);\n                return Array.Exists(formatValues, i => i == (int)currentFormat);\n            }\n\n            return true;\n        }\n\n        [RequiredByNativeCode]\n        public static bool IsDefaultPlatformTextureFormatValid(TextureImporterType textureType, TextureImporterFormat currentFormat)\n        {\n            if (currentFormat != TextureImporterFormat.Automatic)\n            {\n                int[] formatValues;\n                string[] formatStrings;\n                TextureImportValidFormats.GetDefaultTextureFormatValuesAndStrings(textureType, out formatValues, out formatStrings);\n                return Array.Exists(formatValues, i => i == (int)currentFormat);\n            }\n\n            return true;\n        }\n\n        // Cubemap generation mode.\n        public extern TextureImporterGenerateCubemap generateCubemap { get; set; }\n        // Scaling mode for non power of two textures.\n        [NativeProperty(\"NPOTScale\")]\n        public extern TextureImporterNPOTScale npotScale { get; set; }\n\n        // Is texture data readable from scripts.\n        public extern bool isReadable { get; set; }\n\n        // Is texture data able to be streamed by mip level.\n        [NativeConditional(\"ENABLE_TEXTURE_STREAMING\")]\n        public extern bool streamingMipmaps { get; set; }\n        // This texture's mipmap streaming priority.\n\n        [NativeConditional(\"ENABLE_TEXTURE_STREAMING\")]\n        public extern int streamingMipmapsPriority { get; set; }\n\n        // Is texture VT only\n        [NativeConditional(\"ENABLE_VIRTUALTEXTURING\")]\n        [NativeProperty(\"VTOnly\")]\n        public extern bool vtOnly { get; set; }\n\n        public extern bool ignoreMipmapLimit { get; set; }\n        public extern string mipmapLimitGroupName { get; set; }\n\n        // Generate mip maps for the texture?\n        public extern bool mipmapEnabled { get; set; }\n        // Keep texture borders the same when generating mipmaps?\n        public extern bool borderMipmap { get; set; }\n        // When in linear rendering should this texture be sampled with hardware gamma correction (sRGB) or without (linear)?\n        [NativeProperty(\"sRGBTexture\")]\n        public extern bool sRGBTexture { get; set; }\n\n        // Should alpha MIP maps preserve coverage during the alpha test?\n        public extern bool mipMapsPreserveCoverage { get; set; }\n        // Alpha test reference value which determines the coverage.\n        public extern float alphaTestReferenceValue { get; set; }\n\n        // Mipmap filtering mode.\n        [NativeProperty(\"MipmapMode\")]\n        public extern TextureImporterMipFilter mipmapFilter { get; set; }\n        // Fade out mip levels to gray color?\n        public extern bool fadeout { get; set; }\n        // Mip level where texture begins to fade out.\n        public extern int mipmapFadeDistanceStart { get; set; }\n        // Mip level where texture is faded out completely.\n        public extern int mipmapFadeDistanceEnd { get; set; }\n\n        // Should mip maps be generated with gamma correction?\n        [Obsolete(\"generateMipsInLinearSpace Property deprecated. Mipmaps are always generated in linear space.\")]\n        public bool generateMipsInLinearSpace\n        {\n            get { return true; }\n            set {}\n        }\n\n        [Obsolete(\"correctGamma Property deprecated. Mipmaps are always generated in linear space.\")]\n        public bool correctGamma\n        {\n            get { return true; }\n            set {}\n        }\n\n        [Obsolete(\"linearTexture Property deprecated. Use sRGBTexture instead.\")]\n        public bool linearTexture { get { return !sRGBTexture; } set { sRGBTexture = !value; } }\n\n        [Obsolete(\"normalmap Property deprecated. Check [[TextureImporterSettings.textureType]] instead. Getter will work as expected. Setter will set textureType to NormalMap if true, nothing otherwise.\")]\n        public bool normalmap\n        {\n            get { return textureType == TextureImporterType.NormalMap; }\n            set { if (value) textureType = TextureImporterType.NormalMap; else textureType = TextureImporterType.Default; }\n        }\n\n        [Obsolete(\"lightmap Property deprecated. Check [[TextureImporterSettings.textureType]] instead. Getter will work as expected. Setter will set textureType to Lightmap if true, nothing otherwise.\")]\n        public bool lightmap\n        {\n            get { return textureType == TextureImporterType.Lightmap; }\n            set { if (value) textureType = TextureImporterType.Lightmap; else textureType = TextureImporterType.Default; }\n        }\n\n        public extern bool convertToNormalmap { get; set; }\n        public extern TextureImporterNormalFilter normalmapFilter { get; set; }\n        public extern bool flipGreenChannel { get; set; }\n\n        extern uint swizzle { get; set; }\n        public TextureImporterSwizzle swizzleR\n        {\n            get => (TextureImporterSwizzle)(swizzle & 0xFF);\n            set => swizzle = (swizzle & 0xFFFFFF00) | (uint)value;\n        }\n        public TextureImporterSwizzle swizzleG\n        {\n            get => (TextureImporterSwizzle)((swizzle >> 8) & 0xFF);\n            set => swizzle = (swizzle & 0xFFFF00FF) | ((uint)value<<8);\n        }\n        public TextureImporterSwizzle swizzleB\n        {\n            get => (TextureImporterSwizzle)((swizzle >> 16) & 0xFF);\n            set => swizzle = (swizzle & 0xFF00FFFF) | ((uint)value<<16);\n        }\n        public TextureImporterSwizzle swizzleA\n        {\n            get => (TextureImporterSwizzle)((swizzle >> 24) & 0xFF);\n            set => swizzle = (swizzle & 0x00FFFFFF) | ((uint)value<<24);\n        }\n\n        [NativeProperty(\"NormalmapHeightScale\")]\n        public extern float heightmapScale { get; set; }\n\n        // Anisotropic filtering level of the texture.\n        public extern int anisoLevel { get; set; }\n\n        // Filtering mode of the texture.\n        public extern FilterMode filterMode { get; set; }\n\n        // note: wrapMode getter returns U wrapping axis\n        public extern TextureWrapMode wrapMode\n        {\n            [NativeName(\"GetWrapU\")]\n            get;\n            [NativeName(\"SetWrapUVW\")]\n            set;\n        }\n        [NativeProperty(\"WrapU\")]\n        public extern TextureWrapMode wrapModeU { get; set; }\n        [NativeProperty(\"WrapV\")]\n        public extern TextureWrapMode wrapModeV { get; set; }\n        [NativeProperty(\"WrapW\")]\n        public extern TextureWrapMode wrapModeW { get; set; }\n\n        // Mip map bias of the texture.\n        public extern float mipMapBias { get; set; }\n\n        // Use alpha channel as transparency. Removes white borders from transparent textures\n        public extern bool alphaIsTransparency { get; set; }\n\n        public extern bool qualifiesForSpritePacking { get; }\n\n        [NativeProperty(\"SpriteMode\")]\n        public extern  SpriteImportMode spriteImportMode { get; set; }\n\n        [NativeProperty(\"SpriteMetaDatas\")]\n        [Obsolete(\"Support for accessing sprite meta data through spritesheet has been removed. Please use the UnityEditor.U2D.Sprites.ISpriteEditorDataProvider interface instead.\")]\n        public extern SpriteMetaData[] spritesheet { get; set; }\n\n        public extern SecondarySpriteTexture[] secondarySpriteTextures { get; set; }\n\n        [Obsolete(\"Support for packing sprites through spritePackingTag has been removed. Please use SpriteAtlas instead.\")]\n        public string spritePackingTag { get { return \"\"; } set { } }\n\n        // The number of pixels in one unit. Note: The C++ side still uses the name pixelsToUnits which is misleading,\n        // but has not been changed yet to minimize merge conflicts.\n        [NativeProperty(\"SpritePixelsToUnits\")]\n        public extern float spritePixelsPerUnit { get; set; }\n\n        [System.Obsolete(\"Use spritePixelsPerUnit property instead.\")]\n        public extern float spritePixelsToUnits { get; set; }\n\n        public extern Vector2 spritePivot { get; set; }\n        public extern Vector4 spriteBorder { get; set; }\n\n        internal void GetWidthAndHeight(ref int width, ref int height)\n        {\n            var info = GetSourceTextureInformation();\n            width = info.width;\n            height = info.height;\n        }\n\n        public void GetSourceTextureWidthAndHeight(out int width, out int height)\n        {\n            var info = GetSourceTextureInformation();\n            if (info.width == -1)\n                throw new InvalidOperationException(\"The texture has not yet finished importing. This most likely means this method was called in an AssetPostprocessor.OnPreprocessAsset callback.\");\n\n            width = info.width;\n            height = info.height;\n        }\n\n        internal bool IsSourceTextureHDR()\n        {\n            return GetSourceTextureInformation().hdr;\n        }\n\n        private extern SourceTextureInformation GetSourceTextureInformation();\n\n        [FreeFunction(\"IsCompressedETCTextureFormat\")]\n        internal static extern  bool IsTextureFormatETC1Compression(TextureFormat fmt);\n\n        [FreeFunction(\"IsBuildTargetETC\")]\n        internal static extern  bool IsETC1SupportedByBuildTarget(BuildTarget target);\n\n        // Does textures source image have alpha channel.\n        public bool DoesSourceTextureHaveAlpha()\n        {\n            var info = GetSourceTextureInformation();\n            if (info.width == -1)\n                throw new ArgumentException(\"May only be called in OnPostProcessTexture\");\n\n            return info.containsAlpha;\n        }\n\n        // Does textures source image have RGB channels.\n        [System.Obsolete(\"DoesSourceTextureHaveColor always returns true in Unity.\")]\n        public bool DoesSourceTextureHaveColor()\n        {\n            return true;\n        }\n\n        // Which type of texture are we dealing with here\n        public extern TextureImporterType textureType { get; set; }\n        public extern TextureImporterShape textureShape { get; set; }\n\n        // Read texture settings into [[TextureImporterSettings]] class.\n        public void ReadTextureSettings(TextureImporterSettings dest)\n        {\n            settings.CopyTo(dest);\n        }\n\n        // Set texture importers settings from [[TextureImporterSettings]] class.\n        public void SetTextureSettings(TextureImporterSettings src)\n        {\n            ValidateAndCorrectTextureImporterSettings(src);\n            settings = src;\n        }\n\n        private void ValidateAndCorrectTextureImporterSettings(TextureImporterSettings m_Settings)\n        {\n            switch (m_Settings.textureType)\n            {\n                case TextureImporterType.Sprite:\n                    m_Settings.npotScale = ValidateAndCorrectSetting(m_Settings.npotScale, TextureImporterNPOTScale.None, nameof(m_Settings.npotScale));\n                    break;\n            }\n        }\n\n        private T ValidateAndCorrectSetting<T>(T actual, T expected, string settingName)\n        {\n            if (!actual.Equals(expected))\n            {\n                Debug.LogWarning($\"You cannot set {settingName} to {actual} for this texture type. It has been reset to {expected}.\");\n                return expected;\n            }\n            return actual;\n        }\n\n        private extern TextureImporterSettings settings { get; set; }\n\n        [NativeName(\"GetImportInspectorWarning\")]\n        internal extern string GetImportWarnings();\n\n        public extern void ReadTextureImportInstructions(BuildTarget target, out TextureFormat desiredFormat, out ColorSpace colorSpace, out int compressionQuality);\n\n        internal extern bool textureStillNeedsToBeCompressed { [NativeName(\"DoesTextureStillNeedToBeCompressed\")] get; }\n\n        // This is pure backward compatibility codepath. It can be removed when we decide that the time has come\n        internal extern bool removeMatte { get; set; }\n\n        public extern bool ignorePngGamma { get; set; }\n\n        // This is for remapping Sprite that are renamed.\n        extern internal bool GetNameFromInternalIDMap(long id, ref string name);\n\n        [NativeName(\"GetSpriteMetaDatas\")]\n        internal extern SpriteMetaData[] GetSpriteMetaDatas();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/TextureImporterEnums.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.ComponentModel;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    // Lightmap format of a [[Texture2D|texture]].\n    internal enum TextureUsageMode\n    {\n        // Not a lightmap.\n        Default = 0,\n        // Range [0;2] packed to [0;1] with loss of precision.\n        BakedLightmapDoubleLDR = 1,\n        // Range [0;kLightmapRGBMMax] packed to [0;1] with multiplier stored in the alpha channel.\n        BakedLightmapRGBM = 2,\n        // Compressed DXT5 normal map\n        NormalmapDXT5nm = 3,\n        // Plain RGB normal map\n        NormalmapPlain = 4,\n        RGBMEncoded = 5,\n        // Texture is always padded if NPOT and on low-end hardware\n        AlwaysPadded = 6,\n        DoubleLDR = 7,\n        // Baked lightmap without any encoding\n        BakedLightmapFullHDR = 8,\n        RealtimeLightmapRGBM = 9,\n        NormalmapASTCnm = 10,\n        SingleChannelRed = 11,\n        SingleChannelAlpha = 12,\n    }\n\n    // Imported texture format for [[TextureImporter]].\n    public enum TextureImporterFormat\n    {\n        Automatic = -1,\n        // Choose a compressed format automatically.\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member TextureImporterFormat.AutomaticCompressed is obsolete. Use the TextureImporter.textureCompression property instead.\", true)]\n        AutomaticCompressed = -1,\n        // Choose a 16 bit format automatically.\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member TextureImporterFormat.Automatic16bit is obsolete. Use TextureImporter.textureCompression property instead.\", true)]\n        Automatic16bit = -2,\n        // Choose a Truecolor format automatically.\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member TextureImporterFormat.AutomaticTruecolor is obsolete. Use the TextureImporter.textureCompression property instead.\", true)]\n        AutomaticTruecolor = -3,\n        // Choose a Crunched format automatically.\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member TextureImporterFormat.AutomaticCrunched is obsolete. Use the TextureImporter.crunchedCompression property instead.\", true)]\n        AutomaticCrunched = -5,\n        // Choose an HDR format automatically.\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member TextureImporterFormat.AutomaticHDR is obsolete. HDR is handled automatically now.\", true)]\n        AutomaticHDR = -6,\n        // Choose a compresssed HDR format automatically.\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member TextureImporterFormat.AutomaticCompressedHDR is obsolete. HDR is handled automatically now.\", true)]\n        AutomaticCompressedHDR = -7,\n\n        // DXT1 compressed texture format.\n        DXT1 = 10,\n        // DXT5 compressed texture format.\n        DXT5 = 12,\n        // RGB 16 bit texture format.\n        RGB16 = 7,\n        // RGB 24 bit texture format.\n        RGB24 = 3,\n        // Alpha 8 bit texture format.\n        // RGBA 32 bit texture format.\n        Alpha8 = 1,\n        // Red 16 bit texture format.\n        R16 = 9,\n        // Red 8 bit texture format.\n        R8 = 63,\n        // RG 16 bit texture format.\n        RG16 = 62,\n        // RGBA 16 bit texture format.\n        ARGB16 = 2,\n        // RGBA 32 bit texture format.\n        RGBA32 = 4,\n        // ARGB 32 bit texture format.\n        ARGB32 = 5,\n        // RGBA 16 bit (4444) texture format.\n        RGBA16 = 13,\n\n        // R 16 bit texture format.\n        RHalf = 15,\n        // RG 32 bit texture format.\n        RGHalf = 16,\n        // RGBA 64 bit texture format.\n        RGBAHalf = 17,\n\n        // R 32 bit texture format.\n        RFloat = 18,\n        // RG 64 bit texture format.\n        RGFloat = 19,\n        // RGBA 128 bit texture format.\n        RGBAFloat = 20,\n\n        // RGB 32 bit packed float format.\n        RGB9E5 = 22,\n\n        // R BC4 compressed texture format.\n        BC4 = 26,\n        // RG BC5 compressed texture format.\n        BC5 = 27,\n        // HDR RGB BC6 compressed texture format.\n        BC6H = 24,\n        // RGBA BC7 compressed texture format.\n        BC7 = 25,\n\n        // DXT1 crunched texture format.\n        DXT1Crunched = 28,\n        // DXT5 crunched texture format.\n        DXT5Crunched = 29,\n\n        // PowerVR (iPhone) 2 bits/pixel compressed color texture format.\n        [System.Obsolete(\"Texture compression format PVRTC has been deprecated and will be removed in a future release\")]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        PVRTC_RGB2 = 30,\n        // PowerVR (iPhone) 2 bits/pixel compressed with alpha channel texture format.\n        [System.Obsolete(\"Texture compression format PVRTC has been deprecated and will be removed in a future release\")]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        PVRTC_RGBA2 = 31,\n        // PowerVR (iPhone) 4 bits/pixel compressed color texture format.\n        [System.Obsolete(\"Texture compression format PVRTC has been deprecated and will be removed in a future release\")]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        PVRTC_RGB4 = 32,\n        // PowerVR (iPhone) 4 bits/pixel compressed with alpha channel texture format.\n        [System.Obsolete(\"Texture compression format PVRTC has been deprecated and will be removed in a future release\")]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        PVRTC_RGBA4 = 33,\n\n        // ETC (GLES2.0) 4 bits/pixel compressed RGB texture format.\n        ETC_RGB4 = 34,\n\n        // ATC (Android) 4 bits/pixel compressed RGB texture format.\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ATC_RGB4 is obsolete. Use ETC_RGB4 (UnityUpgradable) -> ETC_RGB4\", true)]\n        ATC_RGB4 = 35,\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ATC_RGBA8 is obsolete. Use ETC2_RGBA8 (UnityUpgradable) -> ETC2_RGBA8\", true)]\n        ATC_RGBA8 = 36,\n\n        // EAC 4 bits/pixel compressed 16-bit R texture format\n        EAC_R = 41,\n        // EAC 4 bits/pixel compressed 16-bit signed R texture format\n        EAC_R_SIGNED = 42,\n        // EAC 8 bits/pixel compressed 16-bit RG texture format\n        EAC_RG = 43,\n        // EAC 8 bits/pixel compressed 16-bit signed RG texture format\n        EAC_RG_SIGNED = 44,\n\n        // ETC2 (GLES3.0) 4 bits/pixel compressed RGB texture format.\n        ETC2_RGB4 = 45,\n        // ETC2 (GLES3.0) 4 bits/pixel compressed RGB + 1-bit alpha texture format.\n        ETC2_RGB4_PUNCHTHROUGH_ALPHA = 46,\n        // ETC2 (GLES3.0) 8 bits/pixel compressed RGBA texture format.\n        ETC2_RGBA8 = 47,\n\n        // ASTC uses 128bit block of varying sizes (we use only square blocks). It does not distinguish RGB/RGBA\n        ASTC_4x4 = 48,\n        ASTC_5x5 = 49,\n        ASTC_6x6 = 50,\n        ASTC_8x8 = 51,\n        ASTC_10x10 = 52,\n        ASTC_12x12 = 53,\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ASTC_RGB_4x4 is obsolete. Use ASTC_4x4 (UnityUpgradable) -> ASTC_4x4\", true)]\n        ASTC_RGB_4x4 = -48,\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ASTC_RGB_5x5 is obsolete. Use ASTC_5x5 (UnityUpgradable) -> ASTC_5x5\", true)]\n        ASTC_RGB_5x5 = -49,\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ASTC_RGB_6x6 is obsolete. Use ASTC_6x6 (UnityUpgradable) -> ASTC_6x6\", true)]\n        ASTC_RGB_6x6 = -50,\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ASTC_RGB_8x8 is obsolete. Use ASTC_8x8 (UnityUpgradable) -> ASTC_8x8\", true)]\n        ASTC_RGB_8x8 = -51,\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ASTC_RGB_10x10 is obsolete. Use ASTC_10x10 (UnityUpgradable) -> ASTC_10x10\", true)]\n        ASTC_RGB_10x10 = -52,\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ASTC_RGB_12x12 is obsolete. Use ASTC_12x12 (UnityUpgradable) -> ASTC_12x12\", true)]\n        ASTC_RGB_12x12 = -53,\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ASTC_RGBA_4x4 is obsolete. Use ASTC_4x4 (UnityUpgradable) -> ASTC_4x4\", true)]\n        ASTC_RGBA_4x4 = -54,\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ASTC_RGBA_5x5 is obsolete. Use ASTC_5x5 (UnityUpgradable) -> ASTC_5x5\", true)]\n        ASTC_RGBA_5x5 = -55,\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ASTC_RGBA_6x6 is obsolete. Use ASTC_6x6 (UnityUpgradable) -> ASTC_6x6\", true)]\n        ASTC_RGBA_6x6 = -56,\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ASTC_RGBA_8x8 is obsolete. Use ASTC_8x8 (UnityUpgradable) -> ASTC_8x8\", true)]\n        ASTC_RGBA_8x8 = -57,\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ASTC_RGBA_10x10 is obsolete. Use ASTC_10x10 (UnityUpgradable) -> ASTC_10x10\", true)]\n        ASTC_RGBA_10x10 = -58,\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ASTC_RGBA_12x12 is obsolete. Use ASTC_12x12 (UnityUpgradable) -> ASTC_12x12\", true)]\n        ASTC_RGBA_12x12 = -59,\n\n        // Nintendo 3DS-flavoured ETC\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ETC_RGB4_3DS is obsolete. Nintendo 3DS is no longer supported.\", true)]\n        ETC_RGB4_3DS = -60,\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [System.Obsolete(\"Enum member ETC_RGBA8_3DS is obsolete. Nintendo 3DS is no longer supported.\", true)]\n        ETC_RGBA8_3DS = -61,\n\n        // ETC1 crunched texture format.\n        ETC_RGB4Crunched = 64,\n        // ETC2_RGBA8 crunched texture format.\n        ETC2_RGBA8Crunched = 65,\n\n        // ASTC (block size 4x4) compressed HDR RGB(A) texture format.\n        ASTC_HDR_4x4 = 66,\n        // ASTC (block size 5x5) compressed HDR RGB(A)  texture format.\n        ASTC_HDR_5x5 = 67,\n        // ASTC (block size 4x6x6) compressed HDR RGB(A) texture format.\n        ASTC_HDR_6x6 = 68,\n        // ASTC (block size 8x8) compressed HDR RGB(A) texture format.\n        ASTC_HDR_8x8 = 69,\n        // ASTC (block size 10x10) compressed HDR RGB(A) texture format.\n        ASTC_HDR_10x10 = 70,\n        // ASTC (block size 12x12) compressed HDR RGB(A) texture format.\n        ASTC_HDR_12x12 = 71,\n\n        RG32 = 72,\n        RGB48 = 73,\n        RGBA64 = 74,\n        R8_SIGNED = 75,\n        RG16_SIGNED = 76,\n        RGB24_SIGNED = 77,\n        RGBA32_SIGNED = 78,\n        R16_SIGNED = 79,\n        RG32_SIGNED = 80,\n        RGB48_SIGNED = 81,\n        RGBA64_SIGNED = 82,\n    }\n\n    // Mip map filter for [[TextureImporter]].\n    public enum TextureImporterMipFilter\n    {\n        // Box mipmap filter.\n        BoxFilter = 0,\n        // Kaiser mipmap filter.\n        KaiserFilter = 1,\n    }\n\n    // Cubemap generation mode for [[TextureImporter]].\n    public enum TextureImporterGenerateCubemap\n    {\n        // Do not generate cubemap (default).\n        [System.Obsolete(\"This value is deprecated (use TextureImporter.textureShape instead).\")]\n        None = 0,\n\n        // Generate cubemap from spheremap texture.\n        Spheremap = 1,\n\n        // Generate cubemap from cylindrical texture.\n        Cylindrical = 2,\n        [System.Obsolete(\"Obscure shperemap modes are not supported any longer (use TextureImporterGenerateCubemap.Spheremap instead).\")]\n        SimpleSpheremap = 3,\n        [System.Obsolete(\"Obscure shperemap modes are not supported any longer (use TextureImporterGenerateCubemap.Spheremap instead).\")]\n        NiceSpheremap = 4,\n\n        // Generate cubemap from vertical or horizontal cross texture.\n        FullCubemap = 5,\n\n        // Automatically determine type of cubemap generation from the source image.\n        AutoCubemap = 6\n    }\n\n    // Scaling mode for non power of two textures in [[TextureImporter]].\n    public enum TextureImporterNPOTScale\n    {\n        // Keep non power of two textures as is.\n        None = 0,\n        // Scale to nearest power of two.\n        ToNearest = 1,\n        // Scale to larger power of two.\n        ToLarger = 2,\n        // Scale to smaller power of two.\n        ToSmaller = 3,\n    }\n\n    // Normal map filtering mode for [[TextureImporter]].\n    public enum TextureImporterNormalFilter\n    {\n        // Standard normal map filter.\n        Standard = 0,\n        // Sobel normal map filter.\n        Sobel = 1,\n    }\n\n    // Texture Alpha Usage [[TextureImporter]].\n    public enum TextureImporterAlphaSource\n    {\n        // Alpha won't be used.\n        None = 0,\n        // Alpha comes from input texture if one is provided.\n        FromInput = 1,\n        // Alpha is generated from image gray scale\n        FromGrayScale = 2,\n    }\n\n    // Single Channel Texture Component [[TextureImporter]].\n    public enum TextureImporterSingleChannelComponent\n    {\n        // Use the Alpha channel.\n        Alpha = 0,\n        // Use the Red color channel.\n        Red = 1,\n    }\n\n    [RequiredByNativeCode]\n    public enum TextureImporterType\n    {\n        Default = 0,\n        NormalMap = 1,\n        GUI = 2,\n        Sprite = 8,\n        Cursor = 7,\n        Cookie = 4,\n        Lightmap = 6,\n        SingleChannel = 10,\n        Shadowmask = 11,\n        DirectionalLightmap = 12,\n\n        [System.Obsolete(\"Use Default (UnityUpgradable) -> Default\", true)]\n        Image = Int32.MinValue,\n        [System.Obsolete(\"Use NormalMap (UnityUpgradable) -> NormalMap\", true)]\n        Bump = -1,\n        [System.Obsolete(\"Use importer.textureShape = TextureImporterShape.TextureCube\", true)]\n        Cubemap = -3,\n        [System.Obsolete(\"Use a texture setup as a cubemap with glossy reflection instead\", true)]\n        Reflection = -3,\n        [System.Obsolete(\"Use Default instead. All texture types now have an Advanced foldout (UnityUpgradable) -> Default\", true)]\n        Advanced = -5,\n        [System.Obsolete(\"HDRI is not supported anymore\", true)]\n        HDRI = -9,\n    }\n\n    public enum TextureImporterCompression\n    {\n        Uncompressed = 0,\n        Compressed = 1,\n        // High quality compression formats\n        CompressedHQ = 2,\n        // Low quality compression formats but high Performance - low bandwidth - max compression\n        CompressedLQ = 3\n    }\n\n    public enum TextureResizeAlgorithm\n    {\n        // Default high quality one size fits ALMOST all cases\n        Mitchell = 0,\n        // Might provide better result for some noise textures, when sharp details wanted\n        Bilinear = 1\n    }\n\n    [Flags]\n    public enum TextureImporterShape\n    {\n        Texture2D = 1 << 0,\n        TextureCube = 1 << 1,\n        Texture2DArray = 1 << 2,\n        Texture3D = 1 << 3,\n    }\n\n    public enum SpriteImportMode\n    {\n        None = 0,\n        Single = 1,\n        Multiple = 2,\n        Polygon = 3\n    }\n\n    public enum AndroidETC2FallbackOverride\n    {\n        // Use build settings\n        UseBuildSettings = 0,\n        // 32-bit uncompressed\n        Quality32Bit = 1,\n        // 16-bit uncompressed\n        Quality16Bit = 2,\n        // 32-bit uncompressed, downscaled 2x\n        Quality32BitDownscaled = 3\n    }\n\n    public enum TextureImporterSwizzle\n    {\n        R = 0,\n        G = 1,\n        B = 2,\n        A = 3,\n        OneMinusR = 4,\n        OneMinusG = 5,\n        OneMinusB = 6,\n        OneMinusA = 7,\n        Zero = 8,\n        One = 9\n    }\n\n    // Cookie light type mode for [[TextureImporter]].\n    internal enum TextureImporterCookieLightType\n    {\n        Spot = 0,\n        Directional = 1,\n        Point = 2\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/TextureImporterTypes.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Serialization;\n\nnamespace UnityEditor\n{\n    [StructLayout(LayoutKind.Sequential)]\n    public struct SpriteMetaData\n    {\n        public string name;\n        public Rect rect;\n        public int alignment;\n        public Vector2 pivot;\n        public Vector4 border;\n        internal string customData;\n    }\n\n    // Note: MUST match memory layout of TextureImporterSettings in TextureImporter.h!\n    // This means you need to be careful about field sizes (e.g. don't use \"bool\" since they are different size in C# and C++).\n    [System.Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    [NativeAsStruct]\n    [NativeType(CodegenOptions.Custom, \"TextureImporterSettings\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/TextureImporter.bindings.h\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/TextureImporterTypes.h\")]\n    public sealed class TextureImporterSettings\n    {\n        [SerializeField]\n        int   m_AlphaSource = (int)TextureImporterAlphaSource.FromInput;\n        [SerializeField]\n        int   m_MipMapMode;\n        [SerializeField]\n        int  m_EnableMipMap = 1;\n        [SerializeField]\n        int  m_FadeOut;\n        [SerializeField]\n        int  m_BorderMipMap;\n        [SerializeField]\n        int m_MipMapsPreserveCoverage;\n        [SerializeField]\n        float m_AlphaTestReferenceValue;\n        [SerializeField]\n        int    m_MipMapFadeDistanceStart;\n        [SerializeField]\n        int    m_MipMapFadeDistanceEnd;\n\n        #pragma warning disable 169\n\n        [SerializeField]\n        int  m_ConvertToNormalMap;\n        [SerializeField]\n        float  m_HeightScale;\n        [SerializeField]\n        int     m_NormalMapFilter;\n        [SerializeField]\n        int m_FlipGreenChannel;\n        [SerializeField]\n        uint m_Swizzle = 0x03020100;\n        [SerializeField]\n        int  m_IsReadable;\n\n        [SerializeField]\n        int  m_StreamingMipmaps;\n        [SerializeField]\n        int  m_StreamingMipmapsPriority;\n\n        [SerializeField]\n        int m_VTOnly;\n        [SerializeField, FormerlySerializedAs(\"m_IgnoreMasterTextureLimit\")]\n        int m_IgnoreMipmapLimit;\n\n        [SerializeField]\n        int    m_NPOTScale;\n        [SerializeField]\n        int  m_sRGBTexture = 1;\n\n        [SerializeField]\n        int    m_SpriteMode;\n        [SerializeField]\n        uint   m_SpriteExtrude;\n        [SerializeField]\n        int   m_SpriteMeshType;\n        [SerializeField]\n        int    m_Alignment;\n        [SerializeField]\n        Vector2    m_SpritePivot;\n        [SerializeField]\n        float  m_SpritePixelsToUnits;\n        [SerializeField]\n        Vector4    m_SpriteBorder;\n        [SerializeField]\n        int m_SpriteGenerateFallbackPhysicsShape;\n\n        [SerializeField]\n        int    m_GenerateCubemap;\n        [SerializeField]\n        int    m_CubemapConvolution;\n        [SerializeField]\n        int    m_SeamlessCubemap;\n\n        [SerializeField]\n        int m_AlphaIsTransparency;\n\n        [SerializeField]\n        float m_SpriteTessellationDetail;\n\n        [SerializeField]\n        int m_TextureType;\n        [SerializeField]\n        int m_TextureShape;\n\n        [SerializeField]\n        int m_SingleChannelComponent;\n\n        [SerializeField]\n        int m_FlipbookRows;\n\n        [SerializeField]\n        int m_FlipbookColumns;\n\n        [SerializeField]\n        int m_IgnorePngGamma;\n\n        [SerializeField]\n        int m_CookieMode;\n\n        // memory layout of these is in TextureSettings.h\n        [SerializeField]\n        [NativeName(\"m_TextureSettings.m_FilterMode\")]\n        int     m_FilterMode;\n        [SerializeField]\n        [NativeName(\"m_TextureSettings.m_Aniso\")]\n        int     m_Aniso;\n        [SerializeField]\n        [NativeName(\"m_TextureSettings.m_MipBias\")]\n        float   m_MipBias;\n        [SerializeField]\n        [NativeName(\"m_TextureSettings.m_WrapU\")]\n        int m_WrapU;\n        [SerializeField]\n        [NativeName(\"m_TextureSettings.m_WrapV\")]\n        int m_WrapV;\n        [SerializeField]\n        [NativeName(\"m_TextureSettings.m_WrapW\")]\n        int m_WrapW;\n\n        // Deprecated since texture importer overhaul. Kept for backward compatibility purpose.\n        [SerializeField]\n        [NativeName(\"m_NormalMap_Deprecated\")]\n        int m_NormalMap;\n        [SerializeField]\n        [NativeName(\"m_TextureFormat_Deprecated\")]\n        int m_TextureFormat;\n        [SerializeField]\n        [NativeName(\"m_MaxTextureSize_Deprecated\")]\n        int m_MaxTextureSize;\n        [SerializeField]\n        [NativeName(\"m_Lightmap_Deprecated\")]\n        int m_Lightmap;\n        [SerializeField]\n        [NativeName(\"m_CompressionQuality_Deprecated\")]\n        int m_CompressionQuality;\n        [SerializeField]\n        [NativeName(\"m_LinearTexture_Deprecated\")]\n        int m_LinearTexture;\n        [SerializeField]\n        [NativeName(\"m_GrayScaleToAlpha_Deprecated\")]\n        int m_GrayScaleToAlpha;\n        [SerializeField]\n        [NativeName(\"m_RGBM_Deprecated\")]\n        int m_RGBM;\n        [SerializeField]\n        [NativeName(\"m_CubemapConvolutionSteps_Deprecated\")]\n        int m_CubemapConvolutionSteps;\n        [SerializeField]\n        [NativeName(\"m_CubemapConvolutionExponent_Deprecated\")]\n        float m_CubemapConvolutionExponent;\n\n        // These are just part of a hack to support backward compatibility for maxTextureSize, textureFormat and compressionQualityProperties\n        [SerializeField]\n        private int m_MaxTextureSizeSet;\n        [SerializeField]\n        private int m_CompressionQualitySet;\n        [SerializeField]\n        private int m_TextureFormatSet;\n\n        //For backward compatibility for an incorrectly applied gamma decoding step (bug)\n        [SerializeField]\n        int m_ApplyGammaDecoding;\n\n        public TextureImporterType textureType\n        {\n            get {return (TextureImporterType)m_TextureType; }\n            set { m_TextureType = (int)value; }\n        }\n\n        public TextureImporterShape textureShape\n        {\n            get {return (TextureImporterShape)m_TextureShape; }\n            set { m_TextureShape = (int)value; }\n        }\n\n        public TextureImporterMipFilter mipmapFilter\n        {\n            get {return (TextureImporterMipFilter)m_MipMapMode; }\n            set { m_MipMapMode = (int)value; }\n        }\n        public bool mipmapEnabled\n        {\n            get {return m_EnableMipMap != 0; }\n            set { m_EnableMipMap = value ? 1 : 0; }\n        }\n\n        [Obsolete(\"Texture mips are now always generated in linear space\")]\n        public bool generateMipsInLinearSpace\n        {\n            get { return true; }\n            set {}\n        }\n        public bool sRGBTexture\n        {\n            get {return m_sRGBTexture != 0; }\n            set { m_sRGBTexture = value ? 1 : 0; }\n        }\n        public bool fadeOut\n        {\n            get {return m_FadeOut != 0; }\n            set { m_FadeOut = value ? 1 : 0; }\n        }\n        public bool borderMipmap\n        {\n            get {return m_BorderMipMap != 0; }\n            set { m_BorderMipMap = value ? 1 : 0; }\n        }\n        public bool mipMapsPreserveCoverage\n        {\n            get { return m_MipMapsPreserveCoverage != 0; }\n            set { m_MipMapsPreserveCoverage = value ? 1 : 0; }\n        }\n        public float alphaTestReferenceValue\n        {\n            get { return m_AlphaTestReferenceValue; }\n            set { m_AlphaTestReferenceValue = value; }\n        }\n        public int mipmapFadeDistanceStart\n        {\n            get {return m_MipMapFadeDistanceStart; }\n            set { m_MipMapFadeDistanceStart = value; }\n        }\n        public int mipmapFadeDistanceEnd\n        {\n            get {return m_MipMapFadeDistanceEnd; }\n            set { m_MipMapFadeDistanceEnd = value; }\n        }\n        public bool convertToNormalMap\n        {\n            get {return m_ConvertToNormalMap != 0; }\n            set { m_ConvertToNormalMap = value ? 1 : 0; }\n        }\n        public float heightmapScale\n        {\n            get {return m_HeightScale; }\n            set { m_HeightScale = value; }\n        }\n        public TextureImporterNormalFilter normalMapFilter\n        {\n            get {return (TextureImporterNormalFilter)m_NormalMapFilter; }\n            set { m_NormalMapFilter = (int)value; }\n        }\n        public bool flipGreenChannel\n        {\n            get => m_FlipGreenChannel != 0;\n            set => m_FlipGreenChannel = value ? 1 : 0;\n        }\n\n        public TextureImporterSwizzle swizzleR\n        {\n            get => (TextureImporterSwizzle)(m_Swizzle & 0xFF);\n            set => m_Swizzle = (m_Swizzle & 0xFFFFFF00) | (uint)value;\n        }\n        public TextureImporterSwizzle swizzleG\n        {\n            get => (TextureImporterSwizzle)((m_Swizzle >> 8) & 0xFF);\n            set => m_Swizzle = (m_Swizzle & 0xFFFF00FF) | ((uint)value<<8);\n        }\n        public TextureImporterSwizzle swizzleB\n        {\n            get => (TextureImporterSwizzle)((m_Swizzle >> 16) & 0xFF);\n            set => m_Swizzle = (m_Swizzle & 0xFF00FFFF) | ((uint)value<<16);\n        }\n        public TextureImporterSwizzle swizzleA\n        {\n            get => (TextureImporterSwizzle)((m_Swizzle >> 24) & 0xFF);\n            set => m_Swizzle = (m_Swizzle & 0x00FFFFFF) | ((uint)value<<24);\n        }\n        internal uint swizzleRaw\n        {\n            get => m_Swizzle;\n            set => m_Swizzle = value;\n        }\n        public TextureImporterAlphaSource alphaSource\n        {\n            get {return (TextureImporterAlphaSource)m_AlphaSource; }\n            set { m_AlphaSource = (int)value; }\n        }\n        public TextureImporterSingleChannelComponent singleChannelComponent\n        {\n            get {return (TextureImporterSingleChannelComponent)m_SingleChannelComponent; }\n            set { m_SingleChannelComponent = (int)value; }\n        }\n\n        public int flipbookRows\n        {\n            get => m_FlipbookRows;\n            set => m_FlipbookRows = value;\n        }\n\n        public int flipbookColumns\n        {\n            get => m_FlipbookColumns;\n            set => m_FlipbookColumns = value;\n        }\n\n        public bool readable\n        {\n            get {return m_IsReadable != 0; }\n            set { m_IsReadable = value ? 1 : 0; }\n        }\n\n        public bool streamingMipmaps\n        {\n            get {return m_StreamingMipmaps != 0; }\n            set { m_StreamingMipmaps = value ? 1 : 0; }\n        }\n        public int streamingMipmapsPriority\n        {\n            get {return m_StreamingMipmapsPriority; }\n            set { m_StreamingMipmapsPriority = value; }\n        }\n\n        public bool vtOnly\n        {\n            get { return m_VTOnly != 0; }\n            set { m_VTOnly = value ? 1 : 0; }\n        }\n        public bool ignoreMipmapLimit\n        {\n            get { return m_IgnoreMipmapLimit != 0; }\n            set { m_IgnoreMipmapLimit = value ? 1 : 0; }\n        }\n\n        public TextureImporterNPOTScale npotScale\n        {\n            get {return (TextureImporterNPOTScale)m_NPOTScale; }\n            set { m_NPOTScale = (int)value; }\n        }\n        public TextureImporterGenerateCubemap generateCubemap\n        {\n            get {return (TextureImporterGenerateCubemap)m_GenerateCubemap; }\n            set { m_GenerateCubemap = (int)value; }\n        }\n        public TextureImporterCubemapConvolution cubemapConvolution\n        {\n            get {return (TextureImporterCubemapConvolution)m_CubemapConvolution; }\n            set { m_CubemapConvolution = (int)value; }\n        }\n        public bool seamlessCubemap\n        {\n            get {return m_SeamlessCubemap != 0; }\n            set { m_SeamlessCubemap = value ? 1 : 0; }\n        }\n        public FilterMode filterMode\n        {\n            get {return (FilterMode)m_FilterMode; }\n            set { m_FilterMode = (int)value; }\n        }\n        public int aniso\n        {\n            get {return m_Aniso; }\n            set { m_Aniso = value; }\n        }\n        public float mipmapBias\n        {\n            get {return m_MipBias; }\n            set { m_MipBias = value; }\n        }\n        public TextureWrapMode wrapMode\n        {\n            get { return (TextureWrapMode)m_WrapU; }\n            set { m_WrapU = (int)value; m_WrapV = (int)value; m_WrapW = (int)value; }\n        }\n        public TextureWrapMode wrapModeU\n        {\n            get { return (TextureWrapMode)m_WrapU; }\n            set { m_WrapU = (int)value; }\n        }\n        public TextureWrapMode wrapModeV\n        {\n            get { return (TextureWrapMode)m_WrapV; }\n            set { m_WrapV = (int)value; }\n        }\n        public TextureWrapMode wrapModeW\n        {\n            get { return (TextureWrapMode)m_WrapW; }\n            set { m_WrapW = (int)value; }\n        }\n        public bool alphaIsTransparency\n        {\n            get {return m_AlphaIsTransparency != 0; }\n            set { m_AlphaIsTransparency = value ? 1 : 0; }\n        }\n\n        public bool ignorePngGamma\n        {\n            get { return m_IgnorePngGamma != 0; }\n            set { m_IgnorePngGamma = value ? 1 : 0; }\n        }\n\n        public int spriteMode\n        {\n            get {return m_SpriteMode; }\n            set { m_SpriteMode = value; }\n        }\n\n        // The number of pixels in one unit. Note: Internally, the name m_SpritePixelsToUnits has not been changed yet to minimize merge conflicts.\n        public float spritePixelsPerUnit\n        {\n            get {return m_SpritePixelsToUnits; }\n            set { m_SpritePixelsToUnits = value; }\n        }\n        [System.Obsolete(\"Use spritePixelsPerUnit property instead.\")]\n        public float spritePixelsToUnits\n        {\n            get {return m_SpritePixelsToUnits; }\n            set { m_SpritePixelsToUnits = value; }\n        }\n\n        public float spriteTessellationDetail\n        {\n            get {return m_SpriteTessellationDetail; }\n            set { m_SpriteTessellationDetail = value; }\n        }\n        public uint spriteExtrude\n        {\n            get { return m_SpriteExtrude; }\n            set { m_SpriteExtrude = value; }\n        }\n\n        public SpriteMeshType spriteMeshType\n        {\n            get { return (SpriteMeshType)m_SpriteMeshType; }\n            set { m_SpriteMeshType = (int)value; }\n        }\n\n        public int spriteAlignment\n        {\n            get {return m_Alignment; }\n            set { m_Alignment = value; }\n        }\n\n        public Vector2 spritePivot\n        {\n            get { return m_SpritePivot; }\n            set { m_SpritePivot = value; }\n        }\n\n        public Vector4 spriteBorder\n        {\n            get { return m_SpriteBorder; }\n            set { m_SpriteBorder = value; }\n        }\n\n        public bool spriteGenerateFallbackPhysicsShape\n        {\n            get {return m_SpriteGenerateFallbackPhysicsShape != 0; }\n            set { m_SpriteGenerateFallbackPhysicsShape = value ? 1 : 0; }\n        }\n\n        [FreeFunction(\"TextureImporterBindings::Equal\")]\n        public static extern bool Equal(TextureImporterSettings a, TextureImporterSettings b);\n\n        public void CopyTo(TextureImporterSettings target)\n        {\n            Copy(this, target);\n        }\n\n        // Test texture importer settings for equality.\n        [FreeFunction(\"TextureImporterBindings::CopyTo\")]\n        private static extern void Copy([NotNull] TextureImporterSettings self, [Out][NotNull] TextureImporterSettings target);\n\n        // Configure parameters to import a texture for a purpose of ''type'', as described [[TextureImporterType|here]].\n        [Obsolete(\"ApplyTextureType(TextureImporterType, bool) is deprecated, use ApplyTextureType(TextureImporterType)\")]\n        public void ApplyTextureType(TextureImporterType type, bool applyAll)\n        {\n            Internal_ApplyTextureType(this, type);\n        }\n\n        public void ApplyTextureType(TextureImporterType type)\n        {\n            Internal_ApplyTextureType(this, type);\n        }\n\n        [FreeFunction(\"TextureImporterBindings::ApplyTextureType\")]\n        private static extern void Internal_ApplyTextureType([Out][NotNull] TextureImporterSettings self, TextureImporterType type);\n\n        // Deprecated APIs\n        [Obsolete(\"Use sRGBTexture instead\")]\n        public bool linearTexture\n        {\n            get { return !sRGBTexture; }\n            set { sRGBTexture = !value; }\n        }\n        [Obsolete(\"Check importer.textureType against TextureImporterType.NormalMap instead. Getter will work as expected. Setter will set textureType to NormalMap if true, nothing otherwise\")]\n        public bool normalMap\n        {\n            get { return textureType == TextureImporterType.NormalMap; }\n            set { if (value) textureType = TextureImporterType.NormalMap; else textureType = TextureImporterType.Default; }\n        }\n        [Obsolete(\"Texture format can only be overridden on a per platform basis. See [[TextureImporterPlatformSettings]]\")]\n        public TextureImporterFormat textureFormat\n        {\n            get {return (TextureImporterFormat)m_TextureFormat; }\n            set {m_TextureFormat = (int)textureFormat; textureFormatSet = 1; }\n        }\n        [Obsolete(\"Texture max size can only be overridden on a per platform basis. See [[TextureImporter.maxTextureSize]] for Default platform or [[TextureImporterPlatformSettings]]\")]\n        public int maxTextureSize\n        {\n            get { return m_MaxTextureSize; }\n            set { m_MaxTextureSize = value; maxTextureSizeSet = 1; }\n        }\n        [Obsolete(\"Check importer.textureType against TextureImporterType.Lightmap instead. Getter will work as expected. Setter will set textureType to Lightmap if true, nothing otherwise.\")]\n        public bool lightmap\n        {\n            get { return textureType == TextureImporterType.Lightmap; }\n            set { if (value) textureType = TextureImporterType.Lightmap; else textureType = TextureImporterType.Default; }\n        }\n        [Obsolete(\"RGBM is no longer a user's choice but has become an implementation detail hidden to the user.\")]\n        public TextureImporterRGBMMode rgbm\n        {\n            get { return (TextureImporterRGBMMode)m_RGBM; }\n            set { m_RGBM = (int)value; }\n        }\n        [Obsolete(\"Use UnityEditor.TextureImporter.alphaSource instead\")]\n        public bool grayscaleToAlpha\n        {\n            get { return alphaSource == TextureImporterAlphaSource.FromGrayScale; }\n            set { if (value) alphaSource = TextureImporterAlphaSource.FromGrayScale; else alphaSource = TextureImporterAlphaSource.FromInput; }\n        }\n\n        [Obsolete(\"Not used anymore. The right values are automatically picked by the importer.\")]\n        public int cubemapConvolutionSteps\n        {\n            get {return m_CubemapConvolutionSteps; }\n            set {m_CubemapConvolutionSteps = value; }\n        }\n        [Obsolete(\"Not used anymore. The right values are automatically picked by the importer.\")]\n        public float cubemapConvolutionExponent\n        {\n            get {return m_CubemapConvolutionExponent; }\n            set {m_CubemapConvolutionExponent = value; }\n        }\n        [Obsolete(\"Texture compression can only be overridden on a per platform basis. See [[TextureImporter.compressionQuality]] for Default platform or [[TextureImporterPlatformSettings]]\")]\n        public int compressionQuality\n        {\n            get { return m_CompressionQuality; }\n            set { m_CompressionQuality = value; compressionQualitySet = 1; }\n        }\n        private int maxTextureSizeSet\n        {\n            get { return m_MaxTextureSizeSet; }\n            set { m_MaxTextureSizeSet = value; }\n        }\n\n        private int textureFormatSet\n        {\n            get { return m_TextureFormatSet; }\n            set { m_TextureFormatSet = value; }\n        }\n\n        private int compressionQualitySet\n        {\n            get { return m_CompressionQualitySet; }\n            set { m_CompressionQualitySet = value; }\n        }\n    }\n\n    // Note: MUST match memory layout of TextureImporterPlatformSettings in TextureImporterTypes.h!\n    // This means you need to be careful about field sizes (e.g. don't use \"bool\" since they are different size in C# and C++).\n    [System.Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    [NativeAsStruct]\n    [NativeType(CodegenOptions.Custom, \"TextureImporterPlatformSettings_Marshalling\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/TextureImporter.bindings.h\")]\n    public sealed partial class TextureImporterPlatformSettings\n    {\n        [SerializeField]\n        [NativeName(\"m_BuildTarget\")]\n        string m_Name = TextureImporterInspector.s_DefaultPlatformName;\n        [SerializeField]\n        int m_Overridden = 0;\n        [SerializeField]\n        int m_IgnorePlatformSupport = 0;\n        [SerializeField]\n        int m_MaxTextureSize = 2048;\n        [SerializeField]\n        int m_ResizeAlgorithm = (int)TextureResizeAlgorithm.Mitchell;\n        [SerializeField]\n        int m_TextureFormat = (int)TextureImporterFormat.Automatic;\n        [SerializeField]\n        int m_TextureCompression = (int)TextureImporterCompression.Compressed;\n        [SerializeField]\n        int m_CompressionQuality = (int)TextureCompressionQuality.Normal;\n\n        [SerializeField]\n        internal int m_ForceMaximumCompressionQuality_BC6H_BC7 = 0;\n\n        [SerializeField]\n        int m_CrunchedCompression = 0;\n        [SerializeField]\n        int m_AllowsAlphaSplitting = 0;\n        [SerializeField]\n        int m_AndroidETC2FallbackOverride = (int)AndroidETC2FallbackOverride.UseBuildSettings;\n\n        public string name\n        {\n            get { return m_Name; }\n            set { m_Name = value; }\n        }\n\n        public bool overridden\n        {\n            get { return m_Overridden != 0; }\n            set { m_Overridden = value ? 1 : 0; }\n        }\n\n        public bool ignorePlatformSupport\n        {\n            get { return m_IgnorePlatformSupport != 0; }\n            set { m_IgnorePlatformSupport = value ? 1 : 0; }\n        }\n\n        public int maxTextureSize\n        {\n            get { return m_MaxTextureSize; }\n            set { m_MaxTextureSize = value; }\n        }\n\n        public TextureResizeAlgorithm resizeAlgorithm\n        {\n            get { return (TextureResizeAlgorithm)m_ResizeAlgorithm; }\n            set { m_ResizeAlgorithm = (int)value; }\n        }\n\n        public TextureImporterFormat format\n        {\n            get { return (TextureImporterFormat)m_TextureFormat; }\n            set { m_TextureFormat = (int)value; }\n        }\n        public TextureImporterCompression textureCompression\n        {\n            get { return (TextureImporterCompression)m_TextureCompression; }\n            set { m_TextureCompression = (int)value; }\n        }\n\n        public int compressionQuality\n        {\n            get { return m_CompressionQuality; }\n            set { m_CompressionQuality = value; }\n        }\n\n        internal int forceMaximumCompressionQuality_BC6H_BC7\n        {\n            get { return m_ForceMaximumCompressionQuality_BC6H_BC7; }\n            set { m_ForceMaximumCompressionQuality_BC6H_BC7 = value; }\n        }\n\n        public bool crunchedCompression\n        {\n            get { return m_CrunchedCompression != 0; }\n            set { m_CrunchedCompression = value ? 1 : 0; }\n        }\n\n        public bool allowsAlphaSplitting\n        {\n            get { return m_AllowsAlphaSplitting != 0; }\n            set { m_AllowsAlphaSplitting = value ? 1 : 0; }\n        }\n\n        public AndroidETC2FallbackOverride androidETC2FallbackOverride\n        {\n            get { return (AndroidETC2FallbackOverride)m_AndroidETC2FallbackOverride; }\n            set { m_AndroidETC2FallbackOverride = (int)value; }\n        }\n\n        public void CopyTo(TextureImporterPlatformSettings target)\n        {\n            Copy(this, target);\n        }\n\n        [FreeFunction(\"TextureImporterBindings::CopyTo\")]\n        private static extern void Copy([NotNull] TextureImporterPlatformSettings self, [Out][NotNull] TextureImporterPlatformSettings target);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPipeline/TextureUtil.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Experimental.Rendering; //for GraphicsFormat\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/TextureImporterUtils.h\")]\n    [NativeHeader(\"Runtime/Graphics/TextureFormat.h\")]\n    [NativeHeader(\"Runtime/Graphics/Format.h\")]\n    internal static class TextureUtil\n    {\n        [FreeFunction]\n        public static extern long GetStorageMemorySizeLong([NotNull] Texture t);\n\n        [FreeFunction]\n        public static extern long GetRuntimeMemorySizeLong([NotNull] Texture t);\n\n        [FreeFunction]\n        public static extern bool IsNonPowerOfTwo([NotNull] Texture2D t);\n\n        [FreeFunction]\n        public static extern TextureUsageMode GetUsageMode([NotNull] Texture t);\n\n        [FreeFunction]\n        public static extern bool IsNormalMapUsageMode(TextureUsageMode usageMode);\n\n        [FreeFunction]\n        public static extern bool IsRGBMUsageMode(TextureUsageMode usageMode);\n\n        [FreeFunction]\n        public static extern bool IsDoubleLDRUsageMode(TextureUsageMode usageMode);\n\n        [FreeFunction]\n        public static extern int GetBytesFromTextureFormat(TextureFormat inFormat);\n\n        [FreeFunction]\n        public static extern int GetRowBytesFromWidthAndFormat(int width, TextureFormat format);\n\n        [FreeFunction]\n        public static extern bool IsValidTextureFormat(TextureFormat format);\n\n        [Obsolete(\"IsCompressedTextureFormat has been moved to GraphicsFormatUtility.IsCompressedFormat(TextureFormat)\")]\n        [FreeFunction(\"IsAnyCompressedTextureFormat\")]\n        public static extern bool IsCompressedTextureFormat(TextureFormat format);\n\n        [Obsolete(\"IsCompressedCrunchTextureFormat has been moved to GraphicsFormatUtility.IsCrunchFormat(TextureFormat)\")]\n        [FreeFunction(\"IsCompressedCrunchTextureFormat\")]\n        public static extern bool IsCompressedCrunchTextureFormat(TextureFormat format);\n\n        [FreeFunction]\n        public static extern TextureFormat GetTextureFormat([NotNull] Texture texture);\n\n        [Obsolete(\"IsAlphaOnlyTextureFormat has been moved to GraphicsFormatUtility.IsAlphaOnlyFormat(TextureFormat)\")]\n        [FreeFunction]\n        public static extern bool IsAlphaOnlyTextureFormat(TextureFormat format);\n\n        [Obsolete(\"IsHDRFormat has been moved to GraphicsFormatUtility.IsHDRFormat(TextureFormat)\")]\n        [FreeFunction]\n        public static extern bool IsHDRFormat(TextureFormat format);\n\n        [Obsolete(\"IsHDRGraphicsFormat has been moved to GraphicsFormatUtility.IsHDRFormat(GraphicsFormat)\")]\n        [FreeFunction(\"IsHDRFormat\")]\n        public static extern bool IsHDRGraphicsFormat(GraphicsFormat format);\n\n        [Obsolete(\"HasAlphaTextureFormat has been moved to GraphicsFormatUtility.HasAlphaChannel(TextureFormat)\")]\n        [FreeFunction]\n        public static extern bool HasAlphaTextureFormat(TextureFormat format);\n\n        [Obsolete(\"GetTextureFormatString has been moved to GraphicsFormatUtility.GetFormatString(TextureFormat)\")]\n        [FreeFunction]\n        public static extern string GetTextureFormatString(TextureFormat format);\n\n        [FreeFunction]\n        public static extern string GetTextureColorSpaceString([NotNull] Texture texture);\n\n        [Obsolete(\"ConvertToAlphaTextureFormat has been moved to GraphicsFormatUtility.ConvertToAlphaFormat(TextureFormat)\")]\n        [FreeFunction]\n        public static extern TextureFormat ConvertToAlphaTextureFormat(TextureFormat format);\n\n        public static bool IsDepthRTFormat(RenderTextureFormat format)\n        {\n            return format == RenderTextureFormat.Depth || format == RenderTextureFormat.Shadowmap;\n        }\n\n        [FreeFunction]\n        public static extern bool HasMipMap([NotNull] Texture t);\n\n        [FreeFunction]\n        public static extern bool NeedsExposureControl([NotNull] Texture t);\n\n        [FreeFunction]\n        public static extern int GetGPUWidth([NotNull] Texture t);\n\n        [FreeFunction]\n        public static extern int GetGPUHeight([NotNull] Texture t);\n\n        [FreeFunction]\n        public static extern int GetMipmapCount([NotNull] Texture t);\n\n        [FreeFunction]\n        public static extern bool GetLinearSampled([NotNull] Texture t);\n\n        public static int GetDefaultCompressionQuality()\n        {\n            return (int)TextureCompressionQuality.Normal;\n        }\n\n        [FreeFunction]\n        public static extern Vector4 GetTexelSizeVector([NotNull] Texture t);\n\n        [FreeFunction]\n        public static extern Texture2D GetSourceTexture([NotNull] Cubemap cubemapRef, CubemapFace face);\n\n        [FreeFunction]\n        public static extern void SetSourceTexture([NotNull] Cubemap cubemapRef, CubemapFace face, Texture2D tex);\n\n        [FreeFunction]\n        public static extern void CopyTextureIntoCubemapFace([NotNull] Texture2D textureRef, [NotNull] Cubemap cubemapRef, CubemapFace face);\n\n        [FreeFunction]\n        public static extern void CopyCubemapFaceIntoTexture([NotNull] Cubemap cubemapRef, CubemapFace face, [NotNull] Texture2D textureRef);\n\n        [FreeFunction]\n        public static extern bool ReformatCubemap([NotNull] Cubemap cubemap, int width, int height, TextureFormat textureFormat, bool useMipmap, bool linear);\n\n        [FreeFunction]\n        public static extern bool ReformatTexture([NotNull] ref Texture2D texture, int width, int height, TextureFormat textureFormat, bool useMipmap, bool linear);\n\n        [FreeFunction]\n        public static extern void SetAnisoLevelNoDirty(Texture tex, int level);\n\n        [FreeFunction]\n        public static extern void SetWrapModeNoDirty(Texture tex, TextureWrapMode u, TextureWrapMode v, TextureWrapMode w);\n\n        [FreeFunction]\n        public static extern void SetMipMapBiasNoDirty(Texture tex, float bias);\n\n        [FreeFunction]\n        public static extern void SetFilterModeNoDirty(Texture tex, FilterMode mode);\n\n        [FreeFunction]\n        public static extern bool IsCubemapReadable([NotNull] Cubemap cubemapRef);\n\n        [FreeFunction]\n        public static extern void MarkCubemapReadable(Cubemap cubemapRef, bool readable);\n\n        [FreeFunction]\n        public static extern bool GetTexture2DStreamingMipmaps(Texture2D texture);\n\n        [FreeFunction]\n        public static extern int GetTexture2DStreamingMipmapsPriority(Texture2D texture);\n\n        [FreeFunction]\n        public static extern bool GetCubemapStreamingMipmaps(Cubemap cubemap);\n\n        [FreeFunction]\n        public static extern int GetCubemapStreamingMipmapsPriority(Cubemap cubemap);\n\n        [FreeFunction]\n        public static extern void SetTexture2DStreamingMipmaps(Texture2D textureRef, bool streaming);\n\n        [FreeFunction]\n        public static extern void SetTexture2DStreamingMipmapsPriority(Texture2D textureRef, int priority);\n\n        [FreeFunction]\n        public static extern void SetCubemapStreamingMipmaps(Cubemap cubemapRef, bool streaming);\n\n        [FreeFunction]\n        public static extern void SetCubemapStreamingMipmapsPriority(Cubemap cubemapRef, int priority);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPostprocessor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Internal;\nusing UnityEngine.Scripting;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEditor.AssetImporters;\nusing Object = UnityEngine.Object;\nusing UnityEditor.Profiling;\nusing UnityEditor.Callbacks;\n\nnamespace UnityEditor\n{\n    // AssetPostprocessor lets you hook into the import pipeline and run scripts prior or after importing assets.\n    public partial class AssetPostprocessor\n    {\n        internal struct PostprocessorInfo\n        {\n            public Type Type { get; }\n            public string[] Methods { get; }\n            public uint Version { get; }\n            public int Priority { get; }\n            /// <summary>\n            /// StaticDependency is true if any method in the postprocessor is not part of the NonAutomaticDependencyMethods list.\n            /// This is used to know which PostprocessorInfo should be used for the static importer dependency hash.\n            /// </summary>\n            public bool StaticDependency { get; }\n\n            public PostprocessorInfo(Type assetPostprocessorType, int importerPriority)\n            {\n                Type = assetPostprocessorType;\n                Methods = null;\n                Version = 0;\n                StaticDependency = false;\n                Priority = importerPriority;\n            }\n\n            public PostprocessorInfo(Type assetPostprocessorType, string[] implementedMethods)\n            {\n                Type = assetPostprocessorType;\n                Methods = implementedMethods;\n                StaticDependency = Methods.Intersect(AssetPostprocessingInternal.k_NonAutomaticDependencyMethods).Count() != Methods.Length;\n\n                var inst = (AssetPostprocessor)Activator.CreateInstance(assetPostprocessorType);\n                Version = inst.GetVersion();\n                Priority = inst.GetPostprocessOrder();\n            }\n        }\n\n        private string m_PathName;\n        private AssetImportContext m_Context;\n\n        // The path name of the asset being imported.\n        public string assetPath { get { return m_PathName; } set { m_PathName = value; } }\n\n        // The context of the import, used to specify dependencies\n        public AssetImportContext context { get { return m_Context; } internal set { m_Context = value; } }\n\n        // Logs an import warning to the console.\n        [ExcludeFromDocs]\n        [Obsolete(\"Use context.LogImportWarning(string) instead.\")]\n        public void LogWarning(string warning)\n        {\n            Object context = null;\n            LogWarning(warning, context);\n        }\n\n        [Obsolete(\"Use context.LogImportWarning(string, Object) instead.\")]\n        public void LogWarning(string warning, [DefaultValue(\"null\")] Object context)\n        {\n            if (m_Context != null)\n                m_Context.LogImportWarning(warning, context);\n            else\n                Debug.LogWarning(warning, context);\n        }\n\n        // Logs an import error message to the console.\n        [ExcludeFromDocs]\n        [Obsolete(\"Use context.LogImportError(string) instead.\")]\n        public void LogError(string warning)\n        {\n            Object context = null;\n            LogError(warning, context);\n        }\n\n        [Obsolete(\"Use context.LogImportError(string, Object) instead.\")]\n        public void LogError(string warning, [DefaultValue(\"null\")] Object context)\n        {\n            if (m_Context != null)\n                m_Context.LogImportError(warning, context);\n            else\n                Debug.LogError(warning, context);\n        }\n\n        // Returns the version of the asset postprocessor.\n        public virtual uint GetVersion() { return 0; }\n\n        // Reference to the asset importer\n        public AssetImporter assetImporter { get { return AssetImporter.GetAtPath(assetPath); } }\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"To set or get the preview, call EditorUtility.SetAssetPreview or AssetPreview.GetAssetPreview instead\", true)]\n        public Texture2D preview { get { return null; } set {} }\n\n        // Override the order in which importers are processed.\n        public virtual int GetPostprocessOrder() { return 0; }\n\n    }\n\n    class OnPostprocessAllAssetsCallbackCollection : OrderedCallbackCollection\n    {\n        public class MethodInfoCallback : Callback\n        {\n            public MethodInfo Method { get; }\n\n            public override Type classType => Method.DeclaringType;\n\n            public bool MethodDomainReload { get; }\n\n            public override string name => classType.FullName;\n\n            public MethodInfoCallback(MethodInfo method, bool methodDomainReload)\n            {\n                Method = method;\n                MethodDomainReload = methodDomainReload;\n            }\n\n            public override IEnumerable<T> GetCustomAttributes<T>() => Method.GetCustomAttributes<T>();\n        }\n\n        public override string name => \"OnPostprocessAllAssets\";\n\n        public override List<Callback> GetCallbacks()\n        {\n            var methodArgTypes = new Type[] { typeof(string).MakeArrayType(), typeof(string).MakeArrayType(), typeof(string).MakeArrayType(), typeof(string).MakeArrayType() };\n            var methodDomainReloadParamArgTypes = new Type[] { methodArgTypes[0], methodArgTypes[1], methodArgTypes[2], methodArgTypes[3], typeof(bool) };\n            const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;\n\n            var callbacks = new List<Callback>();\n            foreach (var assetPostprocessorClass in TypeCache.GetTypesDerivedFrom<AssetPostprocessor>())\n            {\n                var method = assetPostprocessorClass.GetMethod(\"OnPostprocessAllAssets\", flags, null, methodArgTypes, null);\n                if (method != null)\n                {\n                    callbacks.Add(new MethodInfoCallback(method, false));\n                }\n                else\n                {\n                    // OnPostprocessAllAssets with didDomainReload parameter\n                    method = assetPostprocessorClass.GetMethod(\"OnPostprocessAllAssets\", flags, null, methodDomainReloadParamArgTypes, null);\n                    if (method != null)\n                    {\n                        callbacks.Add(new MethodInfoCallback(method, true));\n                    }\n                }\n            }\n\n            return callbacks;\n        }\n    }\n\n    internal class AssetPostprocessingInternal\n    {\n        // What is it:\n        // Static postprocessor methods always called for each importer that are part of importer static dependency.\n        // No new postprocessors should be added to these lists. Please reach out to #devs-import-workflow to talk about new additions.\n        internal static readonly string[] k_NonAutomaticDependencyMethods =\n        {\n            \"OnPreprocessAsset\",\n        };\n        static readonly string[] k_ModelImporterPostprocessors =\n        {\n            \"OnPreprocessModel\",\n            \"OnPostprocessMeshHierarchy\",\n            \"OnPostprocessModel\",\n            \"OnPreprocessAnimation\",\n            \"OnPostprocessAnimation\",\n            \"OnPostprocessGameObjectWithAnimatedUserProperties\",\n            \"OnPostprocessGameObjectWithUserProperties\",\n            \"OnPostprocessMaterial\",\n            \"OnAssignMaterialModel\",\n            \"OnPreprocessMaterialDescription\",\n        };\n\n        static readonly string[] k_DynamicModelImporterPostprocessors =\n        {\n            \"OnPreprocessCameraDescription\",\n            \"OnPreprocessLightDescription\"\n        };\n\n        static readonly string[] k_TextureImporterPostprocessors =\n        {\n            \"OnPreprocessTexture\",\n            \"OnPostprocessTexture\",\n            \"OnPostprocessCubemap\",\n            \"OnPostprocessSprites\",\n            \"OnPostprocessTexture3D\",\n            \"OnPostprocessTexture2DArray\"\n        };\n\n        static readonly string[] k_IHVImporterPostprocessors =\n        {\n            \"OnPostprocessTexture\",\n        };\n        static readonly string[] k_AudioImporterPostprocessors =\n        {\n            \"OnPreprocessAudio\",\n            \"OnPostprocessAudio\",\n        };\n        static readonly string[] k_SpeedTreeImporterPostprocessors =\n        {\n            \"OnPreprocessSpeedTree\",\n            \"OnPostprocessSpeedTree\",\n        };\n        static readonly string[] k_PrefabImporterPostprocessors =\n        {\n            \"OnPostprocessPrefab\",\n        };\n        static readonly string[] k_CameraPostprocessors =\n        {\n            \"OnPreprocessCameraDescription\",\n        };\n        static readonly string[] k_LightPostprocessors =\n        {\n            \"OnPreprocessLightDescription\",\n        };\n        static readonly string[] k_TexturePreprocessors =\n        {\n            \"OnPreprocessTexture\",\n        };\n        static readonly string[] k_Texture2DPostprocessors =\n        {\n            \"OnPostprocessTexture\",\n        };\n        static readonly string[] k_Texture2DArrayPostprocessors =\n        {\n            \"OnPostprocessTexture2DArray\"\n        };\n        static readonly string[] k_Texture3DPostprocessors =\n        {\n            \"OnPostprocessTexture3D\"\n        };\n        static readonly string[] k_TextureCubePostprocessors =\n        {\n            \"OnPostprocessCubemap\"\n        };\n        static readonly string[] k_SpritePostprocessors =\n        {\n            \"OnPostprocessSprites\",\n        };\n\n        static Dictionary<string, string[]> s_PostprocessorMethodsByDependencyKey;\n        static Dictionary<Type, string[]> s_StaticPostprocessorMethodsByImporterType;\n        static Dictionary<Type, string[]> s_DynamicPostprocessorMethodsByImporterType;\n\n        // Internal for debugging purposes. We can generate dependency graphs to help understand issues.\n        internal static OnPostprocessAllAssetsCallbackCollection s_OnPostprocessAllAssetsCallbacks = new OnPostprocessAllAssetsCallbackCollection();\n\n        static AssetPostprocessingInternal()\n        {\n            s_StaticPostprocessorMethodsByImporterType = new Dictionary<Type, string[]>();\n            s_StaticPostprocessorMethodsByImporterType.Add(typeof(ModelImporter), k_ModelImporterPostprocessors);\n            s_StaticPostprocessorMethodsByImporterType.Add(typeof(IHVImageFormatImporter), k_IHVImporterPostprocessors);\n            s_StaticPostprocessorMethodsByImporterType.Add(typeof(SpeedTreeImporter), k_SpeedTreeImporterPostprocessors);\n            s_StaticPostprocessorMethodsByImporterType.Add(typeof(AudioImporter), k_AudioImporterPostprocessors);\n            s_StaticPostprocessorMethodsByImporterType.Add(typeof(PrefabImporter), k_PrefabImporterPostprocessors);\n\n            s_DynamicPostprocessorMethodsByImporterType = new Dictionary<Type, string[]>();\n            s_DynamicPostprocessorMethodsByImporterType.Add(typeof(ModelImporter), k_DynamicModelImporterPostprocessors);\n            s_DynamicPostprocessorMethodsByImporterType.Add(typeof(TextureImporter), k_TextureImporterPostprocessors);\n\n            s_PostprocessorMethodsByDependencyKey = new Dictionary<string, string[]>();\n            s_PostprocessorMethodsByDependencyKey.Add(kCameraPostprocessorDependencyName, k_CameraPostprocessors);\n            s_PostprocessorMethodsByDependencyKey.Add(kLightPostprocessorDependencyName, k_LightPostprocessors);\n            s_PostprocessorMethodsByDependencyKey.Add(kTexturePreprocessorDependencyName, k_TexturePreprocessors);\n            s_PostprocessorMethodsByDependencyKey.Add(kTexture2DPostprocessorDependencyName, k_Texture2DPostprocessors);\n            s_PostprocessorMethodsByDependencyKey.Add(kTexture2DArrayPostprocessorDependencyName, k_Texture2DArrayPostprocessors);\n            s_PostprocessorMethodsByDependencyKey.Add(kTexture3DPostprocessorDependencyName, k_Texture3DPostprocessors);\n            s_PostprocessorMethodsByDependencyKey.Add(kTextureCubePostprocessorDependencyName, k_TextureCubePostprocessors);\n            s_PostprocessorMethodsByDependencyKey.Add(kTextureSpritePostprocessorDependencyName, k_SpritePostprocessors);\n        }\n\n        [Serializable]\n        class AssetPostProcessorAnalyticsData\n        {\n            public string importActionId;\n            public List<AssetPostProcessorMethodCallAnalyticsData> postProcessorCalls = new List<AssetPostProcessorMethodCallAnalyticsData>();\n        }\n\n        [Serializable]\n        struct AssetPostProcessorMethodCallAnalyticsData\n        {\n            public string methodName;\n            public float duration_sec;\n            public int invocationCount;\n        }\n\n        static void LogPostProcessorMissingDefaultConstructor(Type type)\n        {\n            Debug.LogErrorFormat(\"{0} requires a default constructor to be used as an asset post processor\", type);\n        }\n\n        [RequiredByNativeCode]\n        // Postprocess on all assets once an automatic import has completed\n        static void PostprocessAllAssets(string[] importedAssets, string[] addedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromPathAssets, bool didDomainReload)\n        {\n            object[] args = { importedAssets, deletedAssets, movedAssets, movedFromPathAssets };\n            object[] argsWithDidDomainReload = { importedAssets, deletedAssets, movedAssets, movedFromPathAssets, didDomainReload};\n            var containsNoAssets = importedAssets.Length == 0 && addedAssets.Length == 0 && deletedAssets.Length == 0 && movedAssets.Length == 0 && movedFromPathAssets.Length == 0;\n\n            foreach (OnPostprocessAllAssetsCallbackCollection.MethodInfoCallback assetPostProcessor in s_OnPostprocessAllAssetsCallbacks.sortedCallbacks)\n            {\n                try\n                {\n                    if (assetPostProcessor.MethodDomainReload)\n                    {\n                        using (new EditorPerformanceMarker($\"{assetPostProcessor.classType.Name}.OnPostprocessAllAssets\", assetPostProcessor.classType).Auto())\n                            InvokeMethod(assetPostProcessor.Method, argsWithDidDomainReload);\n                    }\n                    else\n                    {\n                        if (containsNoAssets)\n                            continue;\n\n                        using (new EditorPerformanceMarker($\"{assetPostProcessor.classType.Name}.OnPostprocessAllAssets\", assetPostProcessor.classType).Auto())\n                            InvokeMethod(assetPostProcessor.Method, args);\n                    }\n                }\n                catch (Exception e)\n                {\n                    Debug.LogException(e);\n                }\n            }\n\n            using (new EditorPerformanceMarker(\"SyncVS.PostprocessSyncProject\").Auto())\n                CodeEditorProjectSync.PostprocessSyncProject(importedAssets, addedAssets, deletedAssets, movedAssets, movedFromPathAssets);\n        }\n\n        internal class CompareAssetImportPriority : IComparer<AssetPostprocessor.PostprocessorInfo>, IComparer<AssetPostprocessor>\n        {\n            public int Compare(AssetPostprocessor.PostprocessorInfo x, AssetPostprocessor.PostprocessorInfo y)\n            {\n                int xo = x.Priority;\n                int yo = y.Priority;\n\n                var compare = xo.CompareTo(yo);\n                if (compare == 0)\n                {\n                    compare = x.Type.FullName.CompareTo(y.Type.FullName);\n                    if (compare == 0)\n                        compare = x.Type.AssemblyQualifiedName.CompareTo(y.Type.AssemblyQualifiedName);\n                }\n                return compare;\n            }\n\n            public int Compare(AssetPostprocessor x, AssetPostprocessor y)\n            {\n                var xi = new AssetPostprocessor.PostprocessorInfo(x.GetType(), x.GetPostprocessOrder());\n                var yi = new AssetPostprocessor.PostprocessorInfo(y.GetType(), y.GetPostprocessOrder());\n                return Compare(xi, yi);\n            }\n        }\n\n        private static string BuildStaticDependencyHashString(SortedSet<AssetPostprocessor.PostprocessorInfo> list)\n        {\n            var hashStr = \"\";\n            foreach (var info in list)\n            {\n                if (info.StaticDependency)\n                {\n                    hashStr += info.Type.AssemblyQualifiedName;\n                    hashStr += '.';\n                    hashStr += info.Version;\n                    hashStr += '|';\n                }\n            }\n\n            return hashStr;\n        }\n\n        private static string BuildHashString(SortedList<string, uint> list)\n        {\n            var hashStr = \"\";\n            foreach (var pair in list)\n            {\n                hashStr += pair.Key;\n                hashStr += '.';\n                hashStr += pair.Value;\n                hashStr += '|';\n            }\n\n            return hashStr;\n        }\n\n        internal const string kCameraPostprocessorDependencyName = \"postprocessor/camera\";\n        internal const string kLightPostprocessorDependencyName = \"postprocessor/light\";\n        internal const string kTexture2DPostprocessorDependencyName = \"postprocessor/texture2D\";\n        internal const string kTextureCubePostprocessorDependencyName = \"postprocessor/textureCube\";\n        internal const string kTexture3DPostprocessorDependencyName = \"postprocessor/texture3D\";\n        internal const string kTexture2DArrayPostprocessorDependencyName = \"postprocessor/texture2DArray\";\n        internal const string kTextureSpritePostprocessorDependencyName = \"postprocessor/textureSprite\";\n        internal const string kTexturePreprocessorDependencyName = \"postprocessor/texturePreprocessor\";\n\n        static Stack<SortedSet<AssetPostprocessor>> m_PostprocessStack = null;\n        static SortedSet<AssetPostprocessor> m_ImportProcessors = null;\n\n        static Type[] m_PostprocessorClasses = null;\n        static string m_MeshProcessorsHashString = null;\n        static string m_AudioProcessorsHashString = null;\n        static string m_SpeedTreeProcessorsHashString = null;\n        static string m_PrefabProcessorsHashString = null;\n        static string m_CameraProcessorsHashString = null;\n        static string m_LightProcessorsHashString = null;\n        static string m_Texture2DProcessorsHashString = null;\n        static string m_TextureCubeProcessorsHashString = null;\n        static string m_Texture3DPostprocessorDependencyName = null;\n        static string m_Texture2DArrayDependencyName = null;\n        static string m_TextureSpriteDependencyName = null;\n        static string m_TexturePreprocessorDependencyName = null;\n\n        static Dictionary<Type, SortedSet<AssetPostprocessor.PostprocessorInfo>> s_StaticPostprocessorsPerImporterType = new Dictionary<Type, SortedSet<AssetPostprocessor.PostprocessorInfo>>();\n        static Dictionary<Type, SortedSet<AssetPostprocessor.PostprocessorInfo>> s_DynamicPostprocessorsPerImporterType = new Dictionary<Type, SortedSet<AssetPostprocessor.PostprocessorInfo>>();\n\n        static Stack<AssetPostProcessorAnalyticsData> s_AnalyticsEventsStack = new Stack<AssetPostProcessorAnalyticsData>();\n\n        static Type[] GetCachedAssetPostprocessorClasses()\n        {\n            if (m_PostprocessorClasses == null)\n                m_PostprocessorClasses = TypeCache.GetTypesDerivedFrom<AssetPostprocessor>().ToArray();\n            return m_PostprocessorClasses;\n        }\n\n        [RequiredByNativeCode]\n        static void InitPostprocessorsForTextureGenerator(string pathName)\n        {\n            var analyticsEvent = new AssetPostProcessorAnalyticsData();\n            analyticsEvent.importActionId = \"None\";\n            s_AnalyticsEventsStack.Push(analyticsEvent);\n\n            m_ImportProcessors = new SortedSet<AssetPostprocessor>(new CompareAssetImportPriority());\n            foreach (var postprocessorInfo in GetSortedStaticPostprocessorTypes(typeof(TextureImporter)))\n            {\n                var assetPostprocessor = (AssetPostprocessor)Activator.CreateInstance(postprocessorInfo.Type);\n                assetPostprocessor.assetPath = pathName;\n                assetPostprocessor.context = null;\n                m_ImportProcessors.Add(assetPostprocessor);\n            }\n\n            foreach (var postprocessorInfo in GetSortedDynamicPostprocessorTypes(typeof(TextureImporter)))\n            {\n                var assetPostprocessor = (AssetPostprocessor)Activator.CreateInstance(postprocessorInfo.Type);\n                assetPostprocessor.assetPath = pathName;\n                assetPostprocessor.context = null;\n                m_ImportProcessors.Add(assetPostprocessor);\n            }\n\n            // Setup postprocessing stack to support reentrancy (Import asset immediate)\n            if (m_PostprocessStack == null)\n                m_PostprocessStack = new Stack<SortedSet<AssetPostprocessor>>();\n            m_PostprocessStack.Push(m_ImportProcessors);\n        }\n\n        [RequiredByNativeCode]\n        static void InitPostprocessors(AssetImportContext context, string pathName, Type importerType, double importStartTime)\n        {\n            var analyticsEvent = new AssetPostProcessorAnalyticsData();\n            analyticsEvent.importActionId = ((int)Math.Floor(importStartTime * 1000)).ToString();\n            s_AnalyticsEventsStack.Push(analyticsEvent);\n\n            m_ImportProcessors = new SortedSet<AssetPostprocessor>(new CompareAssetImportPriority());\n            foreach (var postprocessorInfo in GetSortedStaticPostprocessorTypes(importerType))\n            {\n                var assetPostprocessor = (AssetPostprocessor)Activator.CreateInstance(postprocessorInfo.Type);\n                assetPostprocessor.assetPath = pathName;\n                assetPostprocessor.context = context;\n                m_ImportProcessors.Add(assetPostprocessor);\n            }\n\n            foreach (var postprocessorInfo in GetSortedDynamicPostprocessorTypes(importerType))\n            {\n                var assetPostprocessor = (AssetPostprocessor)Activator.CreateInstance(postprocessorInfo.Type);\n                assetPostprocessor.assetPath = pathName;\n                assetPostprocessor.context = context;\n                m_ImportProcessors.Add(assetPostprocessor);\n            }\n\n            // Setup postprocessing stack to support reentrancy (Import asset immediate)\n            if (m_PostprocessStack == null)\n                m_PostprocessStack = new Stack<SortedSet<AssetPostprocessor>>();\n            m_PostprocessStack.Push(m_ImportProcessors);\n        }\n\n        [RequiredByNativeCode]\n        static void CleanupPostprocessors()\n        {\n            if (m_PostprocessStack != null)\n            {\n                m_PostprocessStack.Pop();\n                m_ImportProcessors = m_PostprocessStack.Count > 0 ? m_PostprocessStack.Peek() : null;\n            }\n\n            if (s_AnalyticsEventsStack.Count > 0)\n            {\n                var lastEvent = s_AnalyticsEventsStack.Pop();\n                if (lastEvent.postProcessorCalls.Count > 0)\n                    EditorAnalytics.SendAssetPostprocessorsUsage(lastEvent);\n            }\n        }\n\n        static bool ImplementsAnyOfTheses(Type type, IEnumerable<string> methods, out List<string> usedMethods)\n        {\n            usedMethods = new List<string>(methods.Where(method => type.GetMethod(method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null));\n            return usedMethods.Count > 0;\n        }\n\n        /*\n         * Returns the list of actual dynamic postprocessor methods for a particular asset.\n         * Note: That where the asset is not yet imported, this list will be empty.\n         */\n        internal static SortedSet<AssetPostprocessor.PostprocessorInfo> GetSortedDynamicPostprocessorsForAsset(string path)\n        {\n            var list = new SortedSet<AssetPostprocessor.PostprocessorInfo>(new CompareAssetImportPriority());\n\n            var guid = AssetDatabase.GUIDFromAssetPath(path);\n            if (guid.Empty())\n                return list;\n\n            //Artifact Infos may contains multiple artifacts, associated with different version of the object (E.g. Main, Preview etc.)\n            var artifactInfos = AssetDatabase.GetArtifactInfos(guid);\n\n            var allMethodsNames = new List<string>();\n            foreach (var info in artifactInfos)\n            {\n                if (!info.isCurrentArtifact)\n                    continue;\n\n                foreach (var kvp in info.dependencies)\n                {\n                    if (kvp.Value.type == ArtifactInfoDependencyType.Dynamic)\n                    {\n                        //Try to retrieve Postprocessor Methods associated with the supplied Dependency keys\n                        string dependencyName = kvp.Key.Replace(ArtifactDifferenceReporter.kEnvironment_CustomDependency + \"/\", \"\");\n                        if (s_PostprocessorMethodsByDependencyKey.TryGetValue(dependencyName, out var methodNames))\n                            allMethodsNames.AddRange(methodNames);\n                    }\n                }\n            }\n\n            if (allMethodsNames.Count == 0)\n                return list;\n\n            /*\n            * The asset has dynamic dependencies to an Asset Postprocessor, so let's find any Postprocessors which\n            * implements those methods.\n            */\n            var distinctMethodNames = allMethodsNames.Distinct();\n            foreach (Type assetPostprocessorClass in GetCachedAssetPostprocessorClasses())\n            {\n                if (ImplementsAnyOfTheses(assetPostprocessorClass, distinctMethodNames, out var methods))\n                {\n                    if (assetPostprocessorClass.GetConstructors().Any(t => t.GetParameters().Count() == 0))\n                        list.Add(new AssetPostprocessor.PostprocessorInfo(assetPostprocessorClass, methods.ToArray()));\n                    else\n                        LogPostProcessorMissingDefaultConstructor(assetPostprocessorClass);\n                }\n            }\n\n            return list;\n        }\n\n        internal static SortedSet<AssetPostprocessor.PostprocessorInfo> GetSortedStaticPostprocessorTypes(Type importer)\n        {\n            var defaultMethods = new string[]\n            {\n                \"OnPreprocessAsset\"\n            };\n            return GetSortedPostprocessorTypes(importer, s_StaticPostprocessorMethodsByImporterType, defaultMethods,\n                s_StaticPostprocessorsPerImporterType);\n        }\n\n        /*\n         * Returns the list of *possible* dynamic postprocessor methods associated with a particular importer type.\n         * See also: GetSortedDynamicPostprocessorsForAsset, to get the actual postprocessor methods for a given asset.\n         */\n        internal static SortedSet<AssetPostprocessor.PostprocessorInfo> GetSortedDynamicPostprocessorTypes(Type importer)\n        {\n            return GetSortedPostprocessorTypes(importer, s_DynamicPostprocessorMethodsByImporterType, new string[0],\n                s_DynamicPostprocessorsPerImporterType);\n        }\n\n        static SortedSet<AssetPostprocessor.PostprocessorInfo> GetSortedPostprocessorTypes(Type importer, Dictionary<Type, string[]> postprocessorMethodsByImporterType, string[] defaultMethods, Dictionary<Type, SortedSet<AssetPostprocessor.PostprocessorInfo>> cache)\n        {\n            if (cache.TryGetValue(importer, out var cachedPostprocessors))\n                return cachedPostprocessors;\n\n            var list = new SortedSet<AssetPostprocessor.PostprocessorInfo>(new CompareAssetImportPriority());\n            var allMethodsNames = defaultMethods.ToList();\n            var methodsType = importer;\n            while (methodsType != null && methodsType != typeof(AssetImporter))\n            {\n                if (postprocessorMethodsByImporterType.TryGetValue(methodsType, out var methodNames))\n                    allMethodsNames.AddRange(methodNames);\n                methodsType = methodsType.BaseType;\n            }\n\n            foreach (Type assetPostprocessorClass in GetCachedAssetPostprocessorClasses())\n            {\n                if (ImplementsAnyOfTheses(assetPostprocessorClass, allMethodsNames, out var methods))\n                {\n                    if (assetPostprocessorClass.GetConstructors().Any(t => t.GetParameters().Count() == 0))\n                        list.Add(new AssetPostprocessor.PostprocessorInfo(assetPostprocessorClass, methods.ToArray()));\n                    else\n                        LogPostProcessorMissingDefaultConstructor(assetPostprocessorClass);\n                }\n            }\n\n            cache.Add(importer, list);\n\n            return list;\n        }\n\n        [RequiredByNativeCode]\n        static string GetMeshProcessorsHashString()\n        {\n            if (m_MeshProcessorsHashString != null)\n                return m_MeshProcessorsHashString;\n\n            m_MeshProcessorsHashString = BuildStaticDependencyHashString(GetSortedStaticPostprocessorTypes(typeof(ModelImporter)));\n            return m_MeshProcessorsHashString;\n        }\n\n        [RequiredByNativeCode]\n        static void PreprocessAsset()\n        {\n            foreach (AssetPostprocessor inst in m_ImportProcessors)\n            {\n                InvokeMethodIfAvailable(inst, \"OnPreprocessAsset\", null);\n            }\n        }\n\n        [RequiredByNativeCode]\n        static void PreprocessModel(string pathName)\n        {\n            CallPostProcessMethods(\"OnPreprocessModel\", null);\n        }\n\n        [RequiredByNativeCode]\n        static void PreprocessSpeedTree(string pathName)\n        {\n            CallPostProcessMethods(\"OnPreprocessSpeedTree\", null);\n        }\n\n        [RequiredByNativeCode]\n        static void PreprocessAnimation(string pathName)\n        {\n            CallPostProcessMethods(\"OnPreprocessAnimation\", null);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessAnimation(GameObject root, AnimationClip clip)\n        {\n            object[] args = { root, clip };\n            CallPostProcessMethods(\"OnPostprocessAnimation\", args);\n        }\n\n        [RequiredByNativeCode]\n        static Material ProcessMeshAssignMaterial(Renderer renderer, Material material)\n        {\n            object[] args = { material, renderer };\n            Material assignedMaterial;\n            CallPostProcessMethodsUntilReturnedObjectIsValid(\"OnAssignMaterialModel\", args, out assignedMaterial);\n\n            return assignedMaterial;\n        }\n\n        [RequiredByNativeCode]\n        static bool ProcessMeshHasAssignMaterial()\n        {\n            foreach (AssetPostprocessor inst in m_ImportProcessors)\n            {\n                if (inst.GetType().GetMethod(\"OnAssignMaterialModel\", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null)\n                    return true;\n            }\n\n            return false;\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessMeshHierarchy(GameObject root)\n        {\n            object[] args = { root };\n            CallPostProcessMethods(\"OnPostprocessMeshHierarchy\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessMesh(GameObject gameObject)\n        {\n            object[] args = { gameObject };\n            CallPostProcessMethods(\"OnPostprocessModel\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessSpeedTree(GameObject gameObject)\n        {\n            object[] args = { gameObject };\n            CallPostProcessMethods(\"OnPostprocessSpeedTree\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessMaterial(Material material)\n        {\n            object[] args = { material };\n            CallPostProcessMethods(\"OnPostprocessMaterial\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PreprocessCameraDescription(AssetImportContext assetImportContext, CameraDescription description, Camera camera, AnimationClip[] animations)\n        {\n            assetImportContext.DependsOnCustomDependency(kCameraPostprocessorDependencyName);\n            object[] args = { description, camera, animations };\n            CallPostProcessMethods(\"OnPreprocessCameraDescription\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PreprocessLightDescription(AssetImportContext assetImportContext, LightDescription description, Light light, AnimationClip[] animations)\n        {\n            assetImportContext.DependsOnCustomDependency(kLightPostprocessorDependencyName);\n            object[] args = { description, light, animations };\n            CallPostProcessMethods(\"OnPreprocessLightDescription\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PreprocessMaterialDescription(MaterialDescription description, Material material, AnimationClip[] animations)\n        {\n            object[] args = { description, material, animations };\n            CallPostProcessMethods(\"OnPreprocessMaterialDescription\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessGameObjectWithUserProperties(GameObject go, string[] prop_names, object[] prop_values)\n        {\n            object[] args = { go, prop_names, prop_values };\n            CallPostProcessMethods(\"OnPostprocessGameObjectWithUserProperties\", args);\n        }\n\n        [RequiredByNativeCode]\n        static EditorCurveBinding[] PostprocessGameObjectWithAnimatedUserProperties(GameObject go, EditorCurveBinding[] bindings)\n        {\n            object[] args = { go, bindings };\n            CallPostProcessMethods(\"OnPostprocessGameObjectWithAnimatedUserProperties\", args);\n            return bindings;\n        }\n\n        [RequiredByNativeCode]\n        static void PreprocessTexture(string pathName, AssetImportContext context)\n        {\n            if (context != null)\n            {\n                context.DependsOnCustomDependency(kTexturePreprocessorDependencyName);\n            }\n\n            CallPostProcessMethods(\"OnPreprocessTexture\", null);\n        }\n\n        [RequiredByNativeCode]\n        static void PreprocessTextureFromScript(string pathName)\n        {\n            CallPostProcessMethods(\"OnPreprocessTexture\", null);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessTexture(Texture2D tex, string pathName, AssetImportContext context)\n        {\n            if (context != null)\n            {\n                context.DependsOnCustomDependency(kTexture2DPostprocessorDependencyName);\n            }\n            object[] args = { tex };\n            CallPostProcessMethods(\"OnPostprocessTexture\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessTextureFromScript(Texture2D tex, string pathName)\n        {\n            object[] args = { tex };\n            CallPostProcessMethods(\"OnPostprocessTexture\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessCubemap(Cubemap tex, string pathName, AssetImportContext context)\n        {\n            if (context != null)\n            {\n                context.DependsOnCustomDependency(kTextureCubePostprocessorDependencyName);\n            }\n            object[] args = { tex };\n            CallPostProcessMethods(\"OnPostprocessCubemap\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessCubemapFromScript(Cubemap tex, string pathName)\n        {\n            object[] args = { tex };\n            CallPostProcessMethods(\"OnPostprocessCubemap\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessTexture3D(Texture3D tex, string pathName, AssetImportContext context)\n        {\n            if (context != null)\n            {\n                context.DependsOnCustomDependency(kTexture3DPostprocessorDependencyName);\n            }\n            object[] args = { tex };\n            CallPostProcessMethods(\"OnPostprocessTexture3D\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessTexture3DFromScript(Texture3D tex, string pathName)\n        {\n            object[] args = { tex };\n            CallPostProcessMethods(\"OnPostprocessTexture3D\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessTexture2DArray(Texture2DArray tex, string pathName, AssetImportContext context)\n        {\n            if (context != null)\n            {\n                context.DependsOnCustomDependency(kTexture2DArrayPostprocessorDependencyName);\n            }\n            object[] args = { tex };\n            CallPostProcessMethods(\"OnPostprocessTexture2DArray\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessTexture2DArrayFromScript(Texture2DArray tex, string pathName)\n        {\n            object[] args = { tex };\n            CallPostProcessMethods(\"OnPostprocessTexture2DArray\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessSprites(Texture2D tex, string pathName, Sprite[] sprites, AssetImportContext context)\n        {\n            if (context != null)\n            {\n                context.DependsOnCustomDependency(kTextureSpritePostprocessorDependencyName);\n            }\n            object[] args = { tex, sprites };\n            CallPostProcessMethods(\"OnPostprocessSprites\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessSpritesFromScript(Texture2D tex, string pathName, Sprite[] sprites)\n        {\n            object[] args = { tex, sprites };\n            CallPostProcessMethods(\"OnPostprocessSprites\", args);\n        }\n\n        [RequiredByNativeCode]\n        static string GetAudioProcessorsHashString()\n        {\n            if (m_AudioProcessorsHashString != null)\n                return m_AudioProcessorsHashString;\n\n            m_AudioProcessorsHashString = BuildStaticDependencyHashString(GetSortedStaticPostprocessorTypes(typeof(AudioImporter)));\n            return m_AudioProcessorsHashString;\n        }\n\n        [RequiredByNativeCode]\n        static void PreprocessAudio(string pathName)\n        {\n            CallPostProcessMethods(\"OnPreprocessAudio\", null);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessAudio(AudioClip clip, string pathName)\n        {\n            object[] args = { clip };\n            CallPostProcessMethods(\"OnPostprocessAudio\", args);\n        }\n\n        [RequiredByNativeCode]\n        static string GetPrefabProcessorsHashString()\n        {\n            if (m_PrefabProcessorsHashString != null)\n                return m_PrefabProcessorsHashString;\n            m_PrefabProcessorsHashString = BuildStaticDependencyHashString(GetSortedStaticPostprocessorTypes(typeof(PrefabImporter)));\n            return m_PrefabProcessorsHashString;\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessPrefab(GameObject prefabAssetRoot)\n        {\n            object[] args = { prefabAssetRoot };\n            CallPostProcessMethods(\"OnPostprocessPrefab\", args);\n        }\n\n        [RequiredByNativeCode]\n        static void PostprocessAssetbundleNameChanged(string assetPath, string previousAssetBundleName, string newAssetBundleName)\n        {\n            object[] args = { assetPath, previousAssetBundleName, newAssetBundleName };\n\n            foreach (var assetPostprocessorClass in GetCachedAssetPostprocessorClasses())\n            {\n                var assetPostprocessor = Activator.CreateInstance(assetPostprocessorClass) as AssetPostprocessor;\n                InvokeMethodIfAvailable(assetPostprocessor, \"OnPostprocessAssetbundleNameChanged\", args);\n            }\n        }\n\n        [RequiredByNativeCode]\n        static string GetSpeedTreeProcessorsHashString()\n        {\n            if (m_SpeedTreeProcessorsHashString != null)\n                return m_SpeedTreeProcessorsHashString;\n            m_SpeedTreeProcessorsHashString = BuildStaticDependencyHashString(GetSortedStaticPostprocessorTypes(typeof(SpeedTreeImporter)));\n            return m_SpeedTreeProcessorsHashString;\n        }\n\n        [InitializeOnLoadMethod]\n        static void RefreshCustomDependencies()\n        {\n            AssetDatabase.RegisterCustomDependency(kCameraPostprocessorDependencyName, Hash128.Compute(GetCameraProcessorsHashString()));\n            AssetDatabase.RegisterCustomDependency(kLightPostprocessorDependencyName, Hash128.Compute(GetLightProcessorsHashString()));\n            AssetDatabase.RegisterCustomDependency(kTexture2DPostprocessorDependencyName, Hash128.Compute(GetTexture2DProcessorsHashString()));\n            AssetDatabase.RegisterCustomDependency(kTextureCubePostprocessorDependencyName, Hash128.Compute(GetTextureCubeProcessorsHashString()));\n            AssetDatabase.RegisterCustomDependency(kTexture3DPostprocessorDependencyName, Hash128.Compute(GetTexture3DProcessorsHashString()));\n            AssetDatabase.RegisterCustomDependency(kTexture2DArrayPostprocessorDependencyName, Hash128.Compute(GetTexture2DArrayProcessorsHashString()));\n            AssetDatabase.RegisterCustomDependency(kTextureSpritePostprocessorDependencyName, Hash128.Compute(GetTextureSpriteProcessorsHashString()));\n            AssetDatabase.RegisterCustomDependency(kTexturePreprocessorDependencyName, Hash128.Compute(GetTexturePreProcessorsHashString()));\n        }\n\n        static void GetProcessorHashString(string methodName, ref string hashString)\n        {\n            if (hashString != null)\n                return;\n\n            var versionsByType = new SortedList<string, uint>();\n\n            foreach (var assetPostprocessorClass in GetCachedAssetPostprocessorClasses())\n            {\n                try\n                {\n                    if (assetPostprocessorClass.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null)\n                    {\n                        var inst = Activator.CreateInstance(assetPostprocessorClass) as AssetPostprocessor;\n                        uint version = inst.GetVersion();\n                        versionsByType.Add(assetPostprocessorClass.FullName, version);\n                    }\n                }\n                catch (MissingMethodException)\n                {\n                    LogPostProcessorMissingDefaultConstructor(assetPostprocessorClass);\n                }\n                catch (Exception e)\n                {\n                    Debug.LogException(e);\n                }\n            }\n\n            hashString = BuildHashString(versionsByType);\n        }\n\n        [RequiredByNativeCode]\n        static string GetCameraProcessorsHashString()\n        {\n            GetProcessorHashString(\"OnPreprocessCameraDescription\", ref m_CameraProcessorsHashString);\n            return m_CameraProcessorsHashString;\n        }\n\n        [RequiredByNativeCode]\n        static string GetLightProcessorsHashString()\n        {\n            GetProcessorHashString(\"OnPreprocessLightDescription\", ref m_LightProcessorsHashString);\n            return m_LightProcessorsHashString;\n        }\n\n        [RequiredByNativeCode]\n        static string GetTexturePreProcessorsHashString()\n        {\n            GetProcessorHashString(\"OnPreprocessTexture\", ref m_TexturePreprocessorDependencyName);\n            return m_TexturePreprocessorDependencyName;\n        }\n\n        [RequiredByNativeCode]\n        static string GetTexture2DProcessorsHashString()\n        {\n            GetProcessorHashString(\"OnPostprocessTexture\", ref m_Texture2DProcessorsHashString);\n            return m_Texture2DProcessorsHashString;\n        }\n\n        [RequiredByNativeCode]\n        static string GetTextureCubeProcessorsHashString()\n        {\n            GetProcessorHashString(\"OnPostprocessCubemap\", ref m_TextureCubeProcessorsHashString);\n            return m_TextureCubeProcessorsHashString;\n        }\n\n        [RequiredByNativeCode]\n        static string GetTexture3DProcessorsHashString()\n        {\n            GetProcessorHashString(\"OnPostprocessTexture3D\", ref m_Texture3DPostprocessorDependencyName);\n            return m_Texture3DPostprocessorDependencyName;\n        }\n\n        [RequiredByNativeCode]\n        static string GetTexture2DArrayProcessorsHashString()\n        {\n            GetProcessorHashString(\"OnPostprocessTexture2DArray\", ref m_Texture2DArrayDependencyName);\n            return m_Texture2DArrayDependencyName;\n        }\n\n        [RequiredByNativeCode]\n        static string GetTextureSpriteProcessorsHashString()\n        {\n            GetProcessorHashString(\"OnPostprocessSprites\", ref m_TextureSpriteDependencyName);\n            return m_TextureSpriteDependencyName;\n        }\n\n        static bool IsAssetPostprocessorAnalyticsEnabled()\n        {\n            return EditorAnalytics.enabled;\n        }\n\n        static void CallPostProcessMethodsUntilReturnedObjectIsValid<T>(string methodName, object[] args, out T returnedObject) where T : class\n        {\n            returnedObject = default(T);\n            int invocationCount = 0;\n            float startTime = Time.realtimeSinceStartup;\n\n            foreach (AssetPostprocessor inst in m_ImportProcessors)\n            {\n                if (InvokeMethodIfAvailable(inst, methodName, args, ref returnedObject))\n                {\n                    invocationCount++;\n                    break;\n                }\n            }\n\n            if (IsAssetPostprocessorAnalyticsEnabled() && invocationCount > 0)\n            {\n                var methodCallAnalytics = new AssetPostProcessorMethodCallAnalyticsData();\n                methodCallAnalytics.invocationCount = invocationCount;\n                methodCallAnalytics.methodName = methodName;\n                methodCallAnalytics.duration_sec = Time.realtimeSinceStartup - startTime;\n                s_AnalyticsEventsStack.Peek().postProcessorCalls.Add(methodCallAnalytics);\n            }\n        }\n\n        static void CallPostProcessMethods(string methodName, object[] args)\n        {\n            if (m_ImportProcessors == null)\n            {\n                throw new Exception(\"m_ImportProcessors is null, InitPostProcessors should be called before any of the post process methods are called.\");\n            }\n\n            if (IsAssetPostprocessorAnalyticsEnabled())\n            {\n                int invocationCount = 0;\n                float startTime = Time.realtimeSinceStartup;\n                foreach (AssetPostprocessor inst in m_ImportProcessors)\n                {\n                    if (InvokeMethodIfAvailable(inst, methodName, args))\n                        invocationCount++;\n                }\n\n                if (invocationCount > 0)\n                {\n                    var methodCallAnalytics = new AssetPostProcessorMethodCallAnalyticsData();\n                    methodCallAnalytics.invocationCount = invocationCount;\n                    methodCallAnalytics.methodName = methodName;\n                    methodCallAnalytics.duration_sec = Time.realtimeSinceStartup - startTime;\n                    s_AnalyticsEventsStack.Peek().postProcessorCalls.Add(methodCallAnalytics);\n                }\n            }\n            else\n            {\n                foreach (AssetPostprocessor inst in m_ImportProcessors)\n                {\n                    InvokeMethodIfAvailable(inst, methodName, args);\n                }\n            }\n        }\n\n        static object InvokeMethod(MethodInfo method, object[] args)\n        {\n            object res = null;\n            using (new EditorPerformanceMarker(method.DeclaringType.Name + \".\" + method.Name, method.DeclaringType).Auto())\n            {\n                res = method.Invoke(null, args);\n            }\n\n            return res;\n        }\n\n        static bool InvokeMethodIfAvailable(object target, string methodName, object[] args)\n        {\n            var type = target.GetType();\n            MethodInfo method = type.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);\n            if (method != null)\n            {\n                using (new EditorPerformanceMarker(type.Name + \".\" + methodName, type).Auto())\n                {\n                    method.Invoke(target, args);\n                }\n\n                return true;\n            }\n            return false;\n        }\n\n        static bool InvokeMethodIfAvailable<T>(object target, string methodName, object[] args, ref T returnedObject) where T : class\n        {\n            var type = target.GetType();\n            MethodInfo method = type.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);\n            if (method != null)\n            {\n                using (new EditorPerformanceMarker(type.Name + \".\" + methodName, type).Auto())\n                {\n                    returnedObject = method.Invoke(target, args) as T;\n                }\n\n                return returnedObject != null;\n            }\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetPreviewUpdater.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    internal static class AssetPreviewUpdater\n    {\n        [RequiredByNativeCode]\n        public static Texture2D CreatePreviewForAsset(Object obj, Object[] subAssets, string assetPath)\n        {\n            return CreatePreview(obj, subAssets, assetPath, 128, 128);\n        }\n\n        // Generate a preview texture for an asset\n        public static Texture2D CreatePreview(Object obj, Object[] subAssets, string assetPath, int width, int height)\n        {\n            var type = CustomEditorAttributes.FindCustomEditorType(obj, false);\n            if (type == null)\n                return null;\n\n            var info = type.GetMethod(\"RenderStaticPreview\");\n            if (info == null)\n            {\n                Debug.LogError(\"Fail to find RenderStaticPreview base method\");\n                return null;\n            }\n\n            if (info.DeclaringType == typeof(Editor))\n                return null;\n\n            var editor = Editor.CreateEditor(obj);\n            if (editor == null)\n                return null;\n            \n            var previewTexture = editor.RenderStaticPreview(assetPath, subAssets, width, height);\n\n            // For debugging we write the preview to a file (keep)\n            //{\n            //  var bytes = tex.EncodeToPNG();\n            //  string previewFilePath = string.Format (\"{0}/../SavedPreview{1}.png\", Application.dataPath, (int)(EditorApplication.timeSinceStartup*1000));\n            //  System.IO.File.WriteAllBytes(previewFilePath, bytes);\n            //  Debug.Log (\"Wrote preview file to: \" +previewFilePath);\n            //}\n\n            Object.DestroyImmediate(editor);\n            return previewTexture;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetStore/AssetStoreAsset.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    /**\n     *  An asset store asset.\n     */\n    public sealed class AssetStoreAsset\n    {\n        /* Search result data\n         *\n         * This is returned when searching for assets\n         */\n        public int id;\n        public string name;\n        public string displayName;      // name without extension, we cache it to prevent string operations when rendering\n        public string staticPreviewURL;\n        public string dynamicPreviewURL;\n        public string className;\n        public string price;\n        public int packageID;\n\n        /* Preview data\n         *\n         * This is returned when clicking on an assets for preview\n         */\n        internal class PreviewInfo\n        {\n            public string packageName;\n            public string packageShortUrl;\n            public int packageSize;\n            public string packageVersion;\n            public int packageRating;\n            public int packageAssetCount;\n            public bool isPurchased;\n            public bool isDownloadable;\n            public string publisherName;\n            public string encryptionKey;\n            public string packageUrl;\n            public float buildProgress; // -1 when not building\n            public float downloadProgress; // -1 when not downloading\n            public string categoryName;\n        }\n\n        internal PreviewInfo previewInfo;\n\n        //\n        public Texture2D previewImage;\n        internal AssetBundleCreateRequest previewBundleRequest;\n        internal AssetBundle previewBundle;\n        internal Object previewAsset;\n        internal bool disposed;\n\n        // public AssetStoreAssetsInfo assetsInfo;\n        public AssetStoreAsset()\n        {\n            disposed = false;\n        }\n\n        public void Dispose()\n        {\n            if (previewImage != null)\n            {\n                Object.DestroyImmediate(previewImage);\n                previewImage = null;\n            }\n            if (previewBundle != null)\n            {\n                previewBundle.Unload(true);\n                previewBundle = null;\n                previewAsset = null;\n            }\n            disposed = true;\n        }\n\n        public Object Preview\n        {\n            get\n            {\n                if (previewAsset != null)\n                    return previewAsset;\n\n                return previewImage;\n            }\n        }\n\n        public bool HasLivePreview\n        {\n            get\n            {\n                return previewAsset != null;\n            }\n        }\n\n        internal string DebugString\n        {\n            get\n            {\n                string r = string.Format(\"id: {0}\\nname: {1}\\nstaticPreviewURL: {2}\\ndynamicPreviewURL: {3}\\n\" +\n                    \"className: {4}\\nprice: {5}\\npackageID: {6}\",\n                    id, name ?? \"N/A\", staticPreviewURL ?? \"N/A\", dynamicPreviewURL ?? \"N/A\", className ?? \"N/A\", price, packageID);\n                if (previewInfo != null)\n                {\n                    r += string.Format(\"previewInfo {{\\n\" +\n                        \"    packageName: {0}\\n\" +\n                        \"    packageShortUrl: {1}\\n\" +\n                        \"    packageSize: {2}\\n\" +\n                        \"    packageVersion: {3}\\n\" +\n                        \"    packageRating: {4}\\n\" +\n                        \"    packageAssetCount: {5}\\n\" +\n                        \"    isPurchased: {6}\\n\" +\n                        \"    isDownloadable: {7}\\n\" +\n                        \"    publisherName: {8}\\n\" +\n                        \"    encryptionKey: {9}\\n\" +\n                        \"    packageUrl: {10}\\n\" +\n                        \"    buildProgress: {11}\\n\" +\n                        \"    downloadProgress: {12}\\n\" +\n                        \"    categoryName: {13}\\n\" +\n                        \"}}\",\n                        previewInfo.packageName ?? \"N/A\",\n                        previewInfo.packageShortUrl ?? \"N/A\",\n                        previewInfo.packageSize,\n                        previewInfo.packageVersion ?? \"N/A\",\n                        previewInfo.packageRating,\n                        previewInfo.packageAssetCount,\n                        previewInfo.isPurchased,\n                        previewInfo.isDownloadable,\n                        previewInfo.publisherName ?? \"N/A\",\n                        previewInfo.encryptionKey ?? \"N/A\",\n                        previewInfo.packageUrl ?? \"N/A\",\n                        previewInfo.buildProgress,\n                        previewInfo.downloadProgress,\n                        previewInfo.categoryName ?? \"N/A\");\n                }\n                return r;\n            }\n        }\n    }\n\n    /**\n     *  An asset store asset selection.\n     *\n     *  This class works as a singleton for keeping the list of selected\n     *  asset store assets. This is not handled by the normal select framework\n     *  because an asset store asset does not have an instanceID since it is not\n     *  actually an asset in the local project.\n     *\n     *  Currently there is only support for handling a single selected asset store\n     *  asset at a time. This class is somewhat prepared for multiple asset store asset\n     *  selections though.\n     */\n    internal static class AssetStoreAssetSelection\n    {\n        public delegate void AssetsRefreshed();\n\n        static internal Dictionary<int, AssetStoreAsset> s_SelectedAssets;\n\n        public static void AddAsset(AssetStoreAsset searchResult, Texture2D placeholderPreviewImage)\n        {\n            if (placeholderPreviewImage != null)\n                searchResult.previewImage = ScaleImage(placeholderPreviewImage, 256, 256);\n\n            searchResult.previewInfo = null;\n            searchResult.previewBundleRequest = null;\n\n            // Dynamic previews is asset bundles to be displayed in\n            // the inspector. Static previews are images.\n            if (!string.IsNullOrEmpty(searchResult.dynamicPreviewURL) && searchResult.previewBundle == null)\n            {\n                // Debug.Log(\"dyn url \" + searchResult.disposed.ToString() + \" \" + searchResult.dynamicPreviewURL);\n                searchResult.disposed = false;\n                // searchResult.previewBundle = AssetBundle.CreateFromFile(\"/users/jonasd/test.unity3d\");\n                // searchResult.previewAsset = searchResult.previewBundle.mainAsset;\n\n                // Request the asset bundle data from the url and register a callback\n                AsyncHTTPClient client = new AsyncHTTPClient(searchResult.dynamicPreviewURL);\n                client.doneCallback = delegate(IAsyncHTTPClient c) {\n                    if (!client.IsSuccess())\n                    {\n                        System.Console.WriteLine(\"Error downloading dynamic preview: \" + client.text);\n                        // Try the static preview instead\n                        searchResult.dynamicPreviewURL = null;\n                        DownloadStaticPreview(searchResult);\n                        return;\n                    }\n\n                    // We only suppport one asset so grab the first one\n                    AssetStoreAsset sel = GetFirstAsset();\n\n                    // Make sure that the selection hasn't changed meanwhile\n                    if (searchResult.disposed || sel == null || searchResult.id != sel.id)\n                    {\n                        //Debug.Log(\"dyn disposed \" + searchResult.disposed.ToString() + \" \" + (sel == null ? \"null\" : sel.id.ToString()) + \" \" + searchResult.id.ToString());\n                        return;\n                    }\n\n                    // Go create the asset bundle in memory from the binary blob asynchronously\n                    try\n                    {\n                        AssetBundleCreateRequest cr = AssetBundle.LoadFromMemoryAsync(c.bytes);\n\n                        // Workaround: Don't subject the bundle to the usual compatibility checks.  We want\n                        // to stay compatible with previews created in prior versions of Unity and with the\n                        // stuff we put into previews, we should generally be able to still load the content\n                        // in the editor.\n                        cr.DisableCompatibilityChecks();\n\n                        searchResult.previewBundleRequest = cr;\n                        EditorApplication.CallbackFunction callback = null;\n\n                        // The callback will be called each tick and check if the asset bundle is ready\n                        double startTime = EditorApplication.timeSinceStartup;\n                        callback = () => {\n                            AssetStoreUtils.UpdatePreloading();\n\n                            if (!cr.isDone)\n                            {\n                                double nowTime = EditorApplication.timeSinceStartup;\n                                if (nowTime - startTime > 10.0)\n                                {\n                                    // Timeout. Stop polling\n                                    EditorApplication.update -= callback;\n                                    System.Console.WriteLine(\"Timed out fetch live preview bundle \" +\n                                        (searchResult.dynamicPreviewURL ?? \"<n/a>\"));\n                                    // Debug.Log(\"Not done Timed out\" + cr.progress.ToString() );\n                                }\n                                else\n                                {\n                                    // Debug.Log(\"Not done \" + cr.progress.ToString() );\n                                }\n                                return;\n                            }\n\n                            // Done cooking. Stop polling.\n                            EditorApplication.update -= callback;\n\n                            // Make sure that the selection hasn't changed meanwhile\n                            AssetStoreAsset sel2 = GetFirstAsset();\n                            if (searchResult.disposed || sel2 == null || searchResult.id != sel2.id)\n                            {\n                                // No problem. Just ignore.\n                                // Debug.Log(\"dyn late disposed \" + searchResult.disposed.ToString() + \" \" + (sel2 == null ? \"null\" : sel2.id.ToString()) + \" \" + searchResult.id.ToString());\n                            }\n                            else\n                            {\n                                searchResult.previewBundle = cr.assetBundle;\n#pragma warning disable 618\n                                if (cr.assetBundle == null ||  cr.assetBundle.mainAsset == null)\n                                {\n                                    // Failed downloading live preview. Fallback to static\n                                    searchResult.dynamicPreviewURL = null;\n                                    DownloadStaticPreview(searchResult);\n                                }\n                                else\n                                    searchResult.previewAsset = searchResult.previewBundle.mainAsset;\n#pragma warning restore 618\n                            }\n                        };\n\n                        EditorApplication.update += callback;\n                    }\n                    catch (System.Exception e)\n                    {\n                        System.Console.Write(e.Message);\n                        Debug.Log(e.Message);\n                    }\n                };\n                client.Begin();\n            }\n            else if (!string.IsNullOrEmpty(searchResult.staticPreviewURL))\n            {\n                DownloadStaticPreview(searchResult);\n            }\n\n            // searchResult.previewBundle = null;\n            AddAssetInternal(searchResult);\n\n            RefreshFromServer(null);\n        }\n\n        // Also used by AssetStoreToolUtils\n        internal static void AddAssetInternal(AssetStoreAsset searchResult)\n        {\n            if (s_SelectedAssets == null)\n                s_SelectedAssets = new Dictionary<int, AssetStoreAsset>();\n            s_SelectedAssets[searchResult.id] = searchResult;\n        }\n\n        static void DownloadStaticPreview(AssetStoreAsset searchResult)\n        {\n            AsyncHTTPClient client = new AsyncHTTPClient(searchResult.staticPreviewURL);\n            client.doneCallback = delegate(IAsyncHTTPClient c) {\n                if (!client.IsSuccess())\n                {\n                    System.Console.WriteLine(\"Error downloading static preview: \" + client.text);\n                    // Debug.LogError(\"Error downloading static preview: \" + client.text);\n                    return;\n                }\n\n                // Need to put the texture through some scaling magic in order for the\n                // TextureInspector to be able to show it.\n                // TODO: This is a workaround and should be fixed.\n                Texture2D srcTex = c.texture;\n                Texture2D tex = new Texture2D(srcTex.width, srcTex.height, TextureFormat.RGB24, false, true);\n                AssetStorePreviewManager.ScaleImage(tex.width, tex.height, srcTex, tex, null);\n                // tex.Compress(true);\n                searchResult.previewImage = tex;\n\n                Object.DestroyImmediate(srcTex);\n                AssetStoreAssetInspector.Instance.Repaint();\n            };\n            client.Begin();\n        }\n\n        // Refresh information about displayed asset by quering the\n        // asset store server. This is typically after the user has\n        // logged in because we need to know if he already owns the\n        // displayed asset.\n        public static void RefreshFromServer(AssetsRefreshed callback)\n        {\n            if (s_SelectedAssets.Count == 0)\n                return;\n\n            // Refetch assetInfo\n            // Query the asset store for more info\n            List<AssetStoreAsset> queryAssets = new List<AssetStoreAsset>();\n            foreach (KeyValuePair<int, AssetStoreAsset> qasset in s_SelectedAssets)\n                queryAssets.Add(qasset.Value);\n\n            // This will fill the queryAssets with extra preview data\n            AssetStoreClient.AssetsInfo(queryAssets,\n                delegate(AssetStoreAssetsInfo results) {\n                    AssetStoreAssetInspector.paymentAvailability = AssetStoreAssetInspector.PaymentAvailability.ServiceDisabled;\n                    if (!string.IsNullOrEmpty(results.error))\n                    {\n                        System.Console.WriteLine(\"Error performing Asset Store Info search: \" + results.error);\n                        AssetStoreAssetInspector.OfflineNoticeEnabled = true;\n                        //Debug.LogError(\"Error performing Asset Store Info search: \" + results.error);\n                        if (callback != null) callback();\n                        return;\n                    }\n                    AssetStoreAssetInspector.OfflineNoticeEnabled = false;\n\n                    if (results.status == AssetStoreAssetsInfo.Status.Ok)\n                        AssetStoreAssetInspector.paymentAvailability = AssetStoreAssetInspector.PaymentAvailability.Ok;\n                    else if (results.status == AssetStoreAssetsInfo.Status.BasketNotEmpty)\n                        AssetStoreAssetInspector.paymentAvailability = AssetStoreAssetInspector.PaymentAvailability.BasketNotEmpty;\n                    else if (results.status == AssetStoreAssetsInfo.Status.AnonymousUser)\n                        AssetStoreAssetInspector.paymentAvailability = AssetStoreAssetInspector.PaymentAvailability.AnonymousUser;\n\n                    AssetStoreAssetInspector.s_PurchaseMessage = results.message;\n                    AssetStoreAssetInspector.s_PaymentMethodCard = results.paymentMethodCard;\n                    AssetStoreAssetInspector.s_PaymentMethodExpire = results.paymentMethodExpire;\n                    AssetStoreAssetInspector.s_PriceText = results.priceText;\n\n                    AssetStoreAssetInspector.Instance.Repaint();\n                    if (callback != null) callback();\n                });\n        }\n\n        private static Texture2D ScaleImage(Texture2D source, int w, int h)\n        {\n            // Bug: When scaling down things look weird unless the source size is\n            //      == 0 when mod 4. Therefore we just return null if that's the case.\n            if (source.width % 4 != 0)\n                return null;\n\n            Texture2D result = new Texture2D(w, h, TextureFormat.RGB24, false, true);\n            Color[] rpixels = result.GetPixels(0);\n\n            double dx = 1.0 / (double)w;\n            double dy = 1.0 / (double)h;\n            double x = 0;\n            double y = 0;\n            int idx = 0;\n            for (int j = 0; j < h; j++)\n            {\n                for (int i = 0; i < w; i++, idx++)\n                {\n                    rpixels[idx] = source.GetPixelBilinear((float)x, (float)y);\n                    x += dx;\n                }\n                x = 0;\n                y += dy;\n            }\n            result.SetPixels(rpixels, 0);\n            result.Apply();\n            return result;\n        }\n\n        public static bool ContainsAsset(int id)\n        {\n            return s_SelectedAssets != null && s_SelectedAssets.ContainsKey(id);\n        }\n\n        public static void Clear()\n        {\n            if (s_SelectedAssets == null)\n                return;\n            foreach (var kv in s_SelectedAssets)\n                kv.Value.Dispose();\n\n            s_SelectedAssets.Clear();\n        }\n\n        public static int Count\n        {\n            get { return s_SelectedAssets == null ? 0 : s_SelectedAssets.Count; }\n        }\n\n        public static bool Empty\n        {\n            get { return s_SelectedAssets == null ? true : s_SelectedAssets.Count == 0; }\n        }\n\n        public static AssetStoreAsset GetFirstAsset()\n        {\n            if (s_SelectedAssets == null)\n                return null;\n            var i = s_SelectedAssets.GetEnumerator();\n            if (!i.MoveNext())\n                return null;\n            return i.Current.Value;\n        }\n    }\n\n    /**\n     *  In addition to being an inspector for AssetStoreAssets this\n     *  inspector works as the object that is selected when an\n     *  asset store asset is selected ie.\n     *  Selection.object == AssetStoreAssetInspector.Instance\n     *  when asset store assets are selected.\n     */\n    [CustomEditor(typeof(AssetStoreAssetInspector))]\n    internal class AssetStoreAssetInspector : Editor\n    {\n        static AssetStoreAssetInspector s_SharedAssetStoreAssetInspector;\n\n        public static AssetStoreAssetInspector Instance\n        {\n            get\n            {\n                if (s_SharedAssetStoreAssetInspector == null)\n                {\n                    s_SharedAssetStoreAssetInspector = ScriptableObject.CreateInstance<AssetStoreAssetInspector>();\n                    s_SharedAssetStoreAssetInspector.hideFlags = HideFlags.HideAndDontSave;\n                }\n                return s_SharedAssetStoreAssetInspector;\n            }\n        }\n\n        class Styles\n        {\n            public GUIStyle link = new GUIStyle(EditorStyles.label);\n            public Styles()\n            {\n                link.normal.textColor = new Color(.26f, .51f, .75f, 1f);\n            }\n        }\n\n        static Styles styles;\n\n        bool packageInfoShown = true;\n\n        // Payment info for all selected assets\n        internal static string s_PurchaseMessage = \"\";\n        internal static string s_PaymentMethodCard = \"\";\n        internal static string s_PaymentMethodExpire = \"\";\n        internal static string s_PriceText = \"\";\n        static GUIContent[] sStatusWheel;\n\n        public static bool OfflineNoticeEnabled { get; set; }\n\n        // Asset store payment availability\n        internal enum PaymentAvailability\n        {\n            BasketNotEmpty,\n            ServiceDisabled,\n            AnonymousUser,\n            Ok\n        }\n\n        internal static PaymentAvailability m_PaymentAvailability;\n        internal static PaymentAvailability paymentAvailability\n        {\n            get\n            {\n                if (AssetStoreClient.LoggedOut())\n                    m_PaymentAvailability = PaymentAvailability.AnonymousUser;\n                return m_PaymentAvailability;\n            }\n            set\n            {\n                if (AssetStoreClient.LoggedOut())\n                    m_PaymentAvailability = PaymentAvailability.AnonymousUser;\n                else\n                    m_PaymentAvailability = value;\n            }\n        }\n\n        int lastAssetID;\n\n        // Callback for curl to call\n        public void OnDownloadProgress(string id, string message, int bytes, int total)\n        {\n            AssetStoreAsset activeAsset = AssetStoreAssetSelection.GetFirstAsset();\n            if (activeAsset == null) return;\n            AssetStoreAsset.PreviewInfo info = activeAsset.previewInfo;\n            if (info == null) return;\n\n            if (activeAsset.packageID.ToString() != id)\n                return;\n\n            if ((message == \"downloading\" || message == \"connecting\") && !OfflineNoticeEnabled)\n            {\n                info.downloadProgress = (float)bytes / (float)total;\n            }\n            else\n            {\n                info.downloadProgress = -1f;\n            }\n            Repaint();\n        }\n\n        public void Update()\n        {\n            // Repaint if asset has changed.\n            // This has to be done here because the .target is always set to\n            // this inspector when inspecting asset store assets.\n            AssetStoreAsset a = AssetStoreAssetSelection.GetFirstAsset();\n            bool hasProgress = a != null && a.previewInfo != null && (a.previewInfo.buildProgress >= 0f || a.previewInfo.downloadProgress >= 0f);\n            if ((a == null && lastAssetID != 0) ||\n                (a != null && lastAssetID != a.id) ||\n                hasProgress)\n            {\n                lastAssetID = a == null ? 0 : a.id;\n                Repaint();\n            }\n\n            // Repaint when the main asset of a possibly downloaded bundle is ready for preview\n            if (a != null && a.previewBundle != null)\n            {\n                a.previewBundle.Unload(false);\n                a.previewBundle = null;\n                Repaint();\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (styles == null)\n            {\n                // Set the singleton in case the DrawEditors() has created this window\n                s_SharedAssetStoreAssetInspector = this;\n                styles = new Styles();\n            }\n\n            AssetStoreAsset activeAsset = AssetStoreAssetSelection.GetFirstAsset();\n            AssetStoreAsset.PreviewInfo info = null;\n            if (activeAsset != null)\n                info = activeAsset.previewInfo;\n\n            if (activeAsset != null)\n                target.name = string.Format(\"Asset Store: {0}\", activeAsset.name);\n            else\n                target.name = \"Asset Store\";\n\n            EditorGUILayout.BeginVertical();\n\n            bool guiEnabled = GUI.enabled;\n\n            GUI.enabled = activeAsset != null && activeAsset.packageID != 0;\n\n            if (OfflineNoticeEnabled)\n            {\n                Color col = GUI.color;\n                GUI.color = Color.yellow;\n                GUILayout.Label(\"Network is offline\");\n                GUI.color = col;\n            }\n\n            if (activeAsset != null)\n            {\n                string typeName = activeAsset.className == null ? \"\" : activeAsset.className.Split(new char[] {' '}, 2)[0];\n                bool isPackage = activeAsset.id == -activeAsset.packageID;\n                if (isPackage)\n                    typeName = \"Package\";\n                if (activeAsset.HasLivePreview)\n                    typeName = activeAsset.Preview.GetType().Name;\n                EditorGUILayout.LabelField(\"Type\", typeName);\n\n                if (isPackage)\n                {\n                    packageInfoShown = true;\n                }\n                else\n                {\n                    EditorGUILayout.Separator();\n                    packageInfoShown = EditorGUILayout.Foldout(packageInfoShown , \"Part of package\", true);\n                }\n                if (packageInfoShown)\n                {\n                    EditorGUILayout.LabelField(\"Name\", info == null ? \"-\" : info.packageName);\n                    EditorGUILayout.LabelField(\"Version\", info == null ? \"-\" : info.packageVersion);\n                    string price = info == null ? \"-\" : (!string.IsNullOrEmpty(activeAsset.price) ? activeAsset.price : \"free\");\n                    EditorGUILayout.LabelField(\"Price\", price);\n                    string rating = info != null && info.packageRating >= 0 ? info.packageRating + \" of 5\" : \"-\";\n                    EditorGUILayout.LabelField(\"Rating\", rating);\n                    EditorGUILayout.LabelField(\"Size\", info == null ? \"-\" : intToSizeString(info.packageSize));\n                    string assetCount = info != null && info.packageAssetCount >= 0 ? info.packageAssetCount.ToString() : \"-\";\n                    EditorGUILayout.LabelField(\"Asset count\", assetCount);\n                    GUILayout.BeginHorizontal();\n                    EditorGUILayout.PrefixLabel(\"Web page\");\n                    bool hasPageUrl = info != null && info.packageShortUrl != null && info.packageShortUrl != \"\";\n                    bool guiBefore = GUI.enabled;\n                    GUI.enabled = hasPageUrl;\n\n                    if (GUILayout.Button(hasPageUrl ? new GUIContent(info.packageShortUrl, \"View in browser\") : EditorGUIUtility.TempContent(\"-\"), styles.link))\n                    {\n                        Application.OpenURL(info.packageShortUrl);\n                    }\n                    if (GUI.enabled)\n                        EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link);\n                    GUI.enabled = guiBefore;\n                    GUILayout.EndHorizontal();\n                    EditorGUILayout.LabelField(\"Publisher\", info == null ? \"-\" : info.publisherName);\n                }\n\n                if (activeAsset.id != 0)\n                {\n                    GUILayout.BeginHorizontal();\n                    GUILayout.FlexibleSpace();\n\n                    if (GUILayout.Button(\"Open Asset Store\", GUILayout.Height(40), GUILayout.Width(120)))\n                    {\n                        OpenItemInAssetStore(activeAsset);\n                        GUIUtility.ExitGUI();\n                    }\n                    GUILayout.FlexibleSpace();\n                    GUILayout.EndHorizontal();\n                }\n                GUILayout.FlexibleSpace();\n            }\n            EditorWrapper editor = previewEditor;\n            if (editor != null && activeAsset != null && activeAsset.HasLivePreview)\n                editor.OnAssetStoreInspectorGUI();\n\n            GUI.enabled = guiEnabled;\n\n            EditorGUILayout.EndVertical();\n        }\n\n        public static void OpenItemInAssetStore(AssetStoreAsset activeAsset)\n        {\n            if (activeAsset.id != 0)\n            {\n                AssetStore.Open(string.Format(\"content/{0}?assetID={1}\", activeAsset.packageID, activeAsset.id));\n            }\n        }\n\n        private static string intToSizeString(int inValue)\n        {\n            if (inValue < 0)\n                return \"unknown\";\n            float val = (float)inValue;\n            string[] scale = new string[] { \"TB\", \"GB\", \"MB\", \"KB\", \"Bytes\" };\n            int idx = scale.Length - 1;\n            while (val > 1000.0f && idx >= 0)\n            {\n                val /= 1000f;\n                idx--;\n            }\n\n            if (idx < 0)\n                return \"<error>\";\n\n            return string.Format(\"{0:#.##} {1}\", val, scale[idx]);\n        }\n\n        public override bool HasPreviewGUI()\n        {\n            return (target != null && AssetStoreAssetSelection.Count != 0);\n        }\n\n        EditorWrapper m_PreviewEditor;\n        Object m_PreviewObject;\n\n        public void OnEnable()\n        {\n            EditorApplication.update += Update;\n            AssetStoreUtils.RegisterDownloadDelegate(this);\n        }\n\n        public void OnDisable()\n        {\n            EditorApplication.update -= Update;\n            if (m_PreviewEditor != null)\n            {\n                m_PreviewEditor.Dispose();\n                m_PreviewEditor = null;\n            }\n            if (m_PreviewObject != null)\n                m_PreviewObject = null;\n            AssetStoreUtils.UnRegisterDownloadDelegate(this);\n        }\n\n        private EditorWrapper previewEditor\n        {\n            get\n            {\n                AssetStoreAsset asset = AssetStoreAssetSelection.GetFirstAsset();\n                if (asset == null) return null;\n                Object preview = asset.Preview;\n                if (preview == null) return null;\n\n                if (preview != m_PreviewObject)\n                {\n                    m_PreviewObject = preview;\n\n                    if (m_PreviewEditor != null)\n                        m_PreviewEditor.Dispose();\n\n                    m_PreviewEditor = EditorWrapper.Make(m_PreviewObject, EditorFeatures.PreviewGUI);\n                }\n\n                return m_PreviewEditor;\n            }\n        }\n\n        public override void OnPreviewSettings()\n        {\n            AssetStoreAsset asset = AssetStoreAssetSelection.GetFirstAsset();\n            if (asset == null) return;\n\n            EditorWrapper editor = previewEditor;\n            if (editor != null && asset.HasLivePreview)\n                editor.OnPreviewSettings();\n        }\n\n        public override string GetInfoString()\n        {\n            EditorWrapper editor = previewEditor;\n            AssetStoreAsset a = AssetStoreAssetSelection.GetFirstAsset();\n            if (a == null)\n                return \"No item selected\";\n\n            if (editor != null && a.HasLivePreview)\n                return editor.GetInfoString();\n\n            return \"\";\n        }\n\n        public override void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            if (m_PreviewObject == null) return;\n            EditorWrapper editor = previewEditor;\n\n            // Special handling for animation clips because they only have\n            // an interactive preview available which shows play button etc.\n            // The OnPreviewGUI is also used for the small icons in the top\n            // of the inspectors where buttons should not be rendered.\n\n            if (editor != null && m_PreviewObject is AnimationClip)\n                editor.OnPreviewGUI(r, background); // currently renders nothing for animation clips\n            else\n                OnInteractivePreviewGUI(r, background);\n        }\n\n        public override void OnInteractivePreviewGUI(Rect r, GUIStyle background)\n        {\n            EditorWrapper editor = previewEditor;\n            if (editor != null)\n            {\n                editor.OnInteractivePreviewGUI(r, background);\n            }\n\n            // If the live preview is not available yes the show a spinner\n            AssetStoreAsset a = AssetStoreAssetSelection.GetFirstAsset();\n            if (a != null && !a.HasLivePreview && !string.IsNullOrEmpty(a.dynamicPreviewURL))\n            {\n                GUIContent c = StatusWheel;\n                r.y += (r.height - c.image.height) / 2f;\n                r.x += (r.width - c.image.width) / 2f;\n                GUI.Label(r, StatusWheel);\n                Repaint();\n            }\n        }\n\n        static GUIContent StatusWheel\n        {\n            get\n            {\n                if (sStatusWheel == null)\n                {\n                    sStatusWheel = new GUIContent[12];\n                    for (int i = 0; i < 12; i++)\n                    {\n                        GUIContent gc = new GUIContent();\n                        gc.image = EditorGUIUtility.LoadIcon(\"WaitSpin\" + i.ToString(\"00\")) as Texture2D;\n                        sStatusWheel[i] = gc;\n                    }\n                }\n                int frame = (int)Mathf.Repeat(Time.realtimeSinceStartup * 10, 11.99f);\n                return sStatusWheel[frame];\n            }\n        }\n\n        public override GUIContent GetPreviewTitle()\n        {\n            return GUIContent.Temp(\"Asset Store Preview\");\n        }\n    } // Inspector class\n}\n"
  },
  {
    "path": "Editor/Mono/AssetStore/AssetStoreClient.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n/*\n * Server class handling communication with the server backend\n *\n * Jonas Drewsen - (C) Unity3d.com - 2011\n *\n */\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditorInternal;\nusing System.Text.RegularExpressions;\nusing System.IO;\nusing System.Collections.Generic;\nusing System;\nusing System.Net;\nusing System.Net.Security;\nusing System.Security.Cryptography.X509Certificates;\n\n\nnamespace UnityEditor\n{\n    /**\n     * The raw response from the asset store before being parsed into\n     * specific result class (see below).\n     */\n    class AssetStoreResponse\n    {\n        internal IAsyncHTTPClient job;\n        public Dictionary<string, JSONValue> dict;\n        public bool ok;\n        public bool failed { get { return !ok; } }\n        public string message\n        {\n            get\n            {\n                if (dict == null || !dict.ContainsKey(\"message\")) return null;\n                return dict[\"message\"].AsString(true);\n            }\n        }\n        // Encode a string into a json string\n        private static string EncodeString(string str)\n        {\n            str = str.Replace(\"\\\"\", \"\\\\\\\"\");\n            str = str.Replace(\"\\\\\", \"\\\\\\\\\");\n            str = str.Replace(\"\\b\", \"\\\\b\");\n            str = str.Replace(\"\\f\", \"\\\\f\");\n            str = str.Replace(\"\\n\", \"\\\\n\");\n            str = str.Replace(\"\\r\", \"\\\\r\");\n            str = str.Replace(\"\\t\", \"\\\\t\");\n            // We do not use \\uXXXX specifier but direct unicode in the string.\n            return str;\n        }\n\n        public override string ToString()\n        {\n            string res = \"{\";\n            string delim = \"\";\n            foreach (KeyValuePair<string, JSONValue> kv in dict)\n            {\n                res += delim + '\"' + EncodeString(kv.Key) + \"\\\" : \" + kv.Value;\n                delim = \", \";\n            }\n            return res + \"}\";\n        }\n    }\n\n    /**\n     * All results derive from this class.\n     */\n    abstract class AssetStoreResultBase<Derived> where Derived : class\n    {\n        public delegate void Callback(Derived res);\n        private Callback callback;\n        public string error;\n        public string warnings;\n\n        public AssetStoreResultBase(Callback cb)\n        {\n            callback = cb;\n            warnings = \"\";\n        }\n\n        public void Parse(AssetStoreResponse response)\n        {\n            if (response.job != null && response.job.IsSuccess())\n            {\n                if (response.job.responseCode >= 300)\n                    error = string.Format(\"HTTP status code {0}\", response.job.responseCode);\n                else if (response.dict.ContainsKey(\"error\"))\n                    error = response.dict[\"error\"].AsString(true);\n                else\n                    Parse(response.dict);\n            }\n            else\n            {\n                string url = response.job == null ? \"nulljob\" : (response.job.url == null ? \"null\" : response.job.url);\n                error = \"Error receiving response from server on url '\" + url + \"': \" + (response.job.text ?? \"n/a\");\n            }\n            callback(this as Derived);\n        }\n\n        abstract protected void Parse(Dictionary<string, JSONValue> dict);\n    }\n\n\n    /**\n     * Result that contains the list of asset matching a search criteria.\n     */\n    class AssetStoreSearchResults : AssetStoreResultBase<AssetStoreSearchResults>\n    {\n        internal struct Group\n        {\n            public static Group Create()\n            {\n                Group g = new Group();\n                g.assets = new List<AssetStoreAsset>();\n                g.label = \"\";\n                g.name = \"\";\n                g.offset = 0;\n                g.limit = -1; // no limit\n                return g;\n            }\n\n            public List<AssetStoreAsset> assets;\n            public int totalFound;\n            public string label;\n            public string name;\n            public int offset;\n            public int limit;\n        }\n\n        internal List<Group> groups = new List<Group>();\n\n        public AssetStoreSearchResults(Callback c) : base(c) {}\n\n        protected override void Parse(Dictionary<string, JSONValue> dict)\n        {\n            foreach (JSONValue v in dict[\"groups\"].AsList(true))\n            {\n                Group group = Group.Create();\n                ParseList(v, ref group);\n                groups.Add(group);\n            }\n            JSONValue offsets = dict[\"query\"][\"offsets\"];\n            List<JSONValue> limits = dict[\"query\"][\"limits\"].AsList(true);\n            int idx = 0;\n            foreach (JSONValue v in offsets.AsList(true))\n            {\n                Group g = groups[idx];\n                g.offset = (int)v.AsFloat(true);\n                g.limit = (int)limits[idx].AsFloat(true);\n                groups[idx] = g;\n                idx++;\n            }\n        }\n\n        static string StripExtension(string path)\n        {\n            if (path == null) return null;\n\n            int i = path.LastIndexOf(\".\");\n            return i < 0 ? path : path.Substring(0, i);\n        }\n\n        private void ParseList(JSONValue matches, ref Group group)\n        {\n            List<AssetStoreAsset> assets = group.assets;\n\n            if (matches.ContainsKey(\"error\"))\n                error = matches[\"error\"].AsString(true);\n            if (matches.ContainsKey(\"warnings\"))\n                warnings = matches[\"warnings\"].AsString(true);\n\n            if (matches.ContainsKey(\"name\"))\n                group.name = matches[\"name\"].AsString(true);\n            if (matches.ContainsKey(\"label\"))\n                group.label = matches[\"label\"].AsString(true);\n            group.label = group.label ?? group.name; // fallback\n            if (matches.ContainsKey(\"total_found\"))\n                group.totalFound = (int)matches[\"total_found\"].AsFloat(true);\n\n            if (matches.ContainsKey(\"matches\"))\n            {\n                foreach (JSONValue asset in matches[\"matches\"].AsList(true))\n                {\n                    AssetStoreAsset res = new AssetStoreAsset();\n                    if (!asset.ContainsKey(\"id\") || !asset.ContainsKey(\"name\") || !asset.ContainsKey(\"package_id\"))\n                        continue;\n\n                    res.id = (int)asset[\"id\"].AsFloat();\n                    res.name = asset[\"name\"].AsString();\n                    res.displayName = StripExtension(res.name);\n                    res.packageID = (int)asset[\"package_id\"].AsFloat();\n\n                    if (asset.ContainsKey(\"static_preview_url\"))\n                        res.staticPreviewURL = asset[\"static_preview_url\"].AsString();\n                    if (asset.ContainsKey(\"dynamic_preview_url\"))\n                        res.dynamicPreviewURL = asset[\"dynamic_preview_url\"].AsString();\n\n                    res.className = asset.ContainsKey(\"class_name\") ? asset[\"class_name\"].AsString() : \"\";\n                    if (asset.ContainsKey(\"price\"))\n                        res.price = asset[\"price\"].AsString();\n                    assets.Add(res);\n                }\n            }\n        }\n    }\n\n    /**\n     * Result that will flesh out the specified AssetStoreAssets with\n     * info to be displayed in an inspector.\n     */\n    class AssetStoreAssetsInfo : AssetStoreResultBase<AssetStoreAssetsInfo>\n    {\n        internal enum Status\n        {\n            BasketNotEmpty,\n            ServiceDisabled,\n            AnonymousUser,\n            Ok\n        }\n        internal Status status;\n\n        internal Dictionary<int, AssetStoreAsset> assets = new Dictionary<int, AssetStoreAsset>();\n        internal bool paymentTokenAvailable;\n        internal string paymentMethodCard;\n        internal string paymentMethodExpire;\n        internal float price;\n        internal float vat;\n        internal string currency;\n        internal string priceText;\n        internal string vatText;\n        internal string message;\n\n        internal AssetStoreAssetsInfo(Callback c, List<AssetStoreAsset> assets) : base(c)\n        {\n            foreach (AssetStoreAsset a in assets)\n                this.assets[a.id] = a;\n        }\n\n        protected override void Parse(Dictionary<string, JSONValue> dict)\n        {\n            Dictionary<string, JSONValue> purchaseInfo = dict[\"purchase_info\"].AsDict(true);\n            string statusStr = purchaseInfo[\"status\"].AsString(true);\n            if (statusStr == \"basket-not-empty\")\n                status = Status.BasketNotEmpty;\n            else if (statusStr == \"service-disabled\")\n                status = Status.ServiceDisabled;\n            else if (statusStr == \"user-anonymous\")\n                status = Status.AnonymousUser;\n            else if (statusStr == \"ok\")\n                status = Status.Ok;\n\n            paymentTokenAvailable = purchaseInfo[\"payment_token_available\"].AsBool();\n            if (purchaseInfo.ContainsKey(\"payment_method_card\"))\n                paymentMethodCard = purchaseInfo[\"payment_method_card\"].AsString(true);\n            if (purchaseInfo.ContainsKey(\"payment_method_expire\"))\n                paymentMethodExpire = purchaseInfo[\"payment_method_expire\"].AsString(true);\n            price = purchaseInfo[\"price\"].AsFloat(true);\n            vat = purchaseInfo[\"vat\"].AsFloat(true);\n            priceText = purchaseInfo[\"price_text\"].AsString(true);\n            vatText = purchaseInfo[\"vat_text\"].AsString(true);\n            currency = purchaseInfo[\"currency\"].AsString(true);\n            message = purchaseInfo.ContainsKey(\"message\") ? purchaseInfo[\"message\"].AsString(true) : null;\n\n            List<JSONValue> assetsIn = dict[\"results\"].AsList(true);\n\n            foreach (JSONValue val in assetsIn)\n            {\n                AssetStoreAsset asset;\n                int aid = 0;\n                if (val[\"id\"].IsString())\n                    aid = int.Parse(val[\"id\"].AsString());\n                else\n                    aid = (int)val[\"id\"].AsFloat();\n\n                if (!assets.TryGetValue(aid, out asset))\n                    continue;\n\n                if (asset.previewInfo == null)\n                    asset.previewInfo = new AssetStoreAsset.PreviewInfo();\n\n                AssetStoreAsset.PreviewInfo a = asset.previewInfo;\n                asset.className = val[\"class_names\"].AsString(true).Trim();\n                a.packageName = val[\"package_name\"].AsString(true).Trim();\n                a.packageShortUrl = val[\"short_url\"].AsString(true).Trim();\n                // a.packagePrice = val.ContainsKey(\"price_text\") ? val[\"price_text\"].AsString(true).Trim() : null;\n                asset.price = val.ContainsKey(\"price_text\") ? val[\"price_text\"].AsString(true).Trim() : null;\n                a.packageSize = int.Parse(val.Get(\"package_size\").IsNull() ? \"-1\" : val[\"package_size\"].AsString(true));\n                asset.packageID = int.Parse(val[\"package_id\"].AsString());\n                a.packageVersion = val[\"package_version\"].AsString();\n                a.packageRating = int.Parse(val.Get(\"rating\").IsNull() || val[\"rating\"].AsString(true).Length == 0 ? \"-1\" : val[\"rating\"].AsString(true));\n                a.packageAssetCount = int.Parse(val[\"package_asset_count\"].IsNull() ? \"-1\" : val[\"package_asset_count\"].AsString(true));\n                a.isPurchased = val.ContainsKey(\"purchased\") ? val[\"purchased\"].AsBool(true) : false;\n                a.isDownloadable = a.isPurchased || asset.price == null;\n                a.publisherName = val[\"publisher_name\"].AsString(true).Trim();\n                // a.previewBundle = (!val.ContainsKey(\"preview_bundle\") || val[\"preview_bundle\"].IsNull()) ? \"\" : val[\"preview_bundle\"].AsString(true);\n                a.packageUrl = val.Get(\"package_url\").IsNull() ? \"\" : val[\"package_url\"].AsString(true);\n                a.encryptionKey = val.Get(\"encryption_key\").IsNull() ? \"\" : val[\"encryption_key\"].AsString(true);\n                a.categoryName = val.Get(\"category_name\").IsNull() ? \"\" : val[\"category_name\"].AsString(true);\n                a.buildProgress = -1f;\n                a.downloadProgress = -1f;\n            }\n        }\n    }\n\n    /**\n     * Success of purchasing a package\n     */\n    class PurchaseResult : AssetStoreResultBase<PurchaseResult>\n    {\n        public enum Status\n        {\n            BasketNotEmpty,\n            ServiceDisabled,\n            AnonymousUser,\n            PasswordMissing,\n            PasswordWrong,\n            PurchaseDeclined,\n            Ok\n        }\n        public Status status;\n        public int packageID;\n        public string message;\n\n        public PurchaseResult(Callback c) : base(c)\n        {\n        }\n\n        protected override void Parse(Dictionary<string, JSONValue> dict)\n        {\n            packageID = int.Parse(dict[\"package_id\"].AsString());\n            message = dict.ContainsKey(\"message\") ? dict[\"message\"].AsString(true) : null;\n\n            string statusStr = dict[\"status\"].AsString(true);\n            if (statusStr == \"basket-not-empty\")\n                status = Status.BasketNotEmpty;\n            else if (statusStr == \"service-disabled\")\n                status = Status.ServiceDisabled;\n            else if (statusStr == \"user-anonymous\")\n                status = Status.AnonymousUser;\n            else if (statusStr == \"password-missing\")\n                status = Status.PasswordMissing;\n            else if (statusStr == \"password-wrong\")\n                status = Status.PasswordWrong;\n            else if (statusStr == \"purchase-declined\")\n                status = Status.PurchaseDeclined;\n            else if (statusStr == \"ok\")\n                status = Status.Ok;\n        }\n    }\n\n    /**\n     * Status of building a package on the asset store server.\n     */\n    class BuildPackageResult : AssetStoreResultBase<BuildPackageResult>\n    {\n        internal AssetStoreAsset asset;\n        internal int packageID;\n\n        internal BuildPackageResult(AssetStoreAsset asset, Callback c) : base(c)\n        {\n            this.asset = asset;\n            packageID = -1;\n        }\n\n        protected override void Parse(Dictionary<string, JSONValue> dict)\n        {\n            dict = dict[\"download\"].AsDict();\n\n            packageID = int.Parse(dict[\"id\"].AsString());\n            if (packageID != asset.packageID)\n            {\n                Debug.LogError(\"Got asset store server build result from mismatching package\");\n                return;\n            }\n            asset.previewInfo.packageUrl = dict.ContainsKey(\"url\") ? dict[\"url\"].AsString(true) : \"\";\n            asset.previewInfo.encryptionKey = dict.ContainsKey(\"key\") ? dict[\"key\"].AsString(true) : \"\";\n\n            // The asset store is weird. Of pct is 0 it returns a 0.0 float, if it is > 0 it returns a string with the pct ie \"23\".\n            asset.previewInfo.buildProgress = (dict[\"progress\"].IsFloat() ? dict[\"progress\"].AsFloat(true) : float.Parse(dict[\"progress\"].AsString(true), System.Globalization.CultureInfo.InvariantCulture)) / 100.0f;\n        }\n    }\n\n\n    /**\n     * The main API class for communication with the asset store server.\n     * Most interesting methods are the static ones specified in the\n     * bottom of this class.\n     */\n    class AssetStoreClient\n    {\n        const string kUnauthSessionID = \"26c4202eb475d02864b40827dfff11a14657aa41\";\n\n        internal enum LoginState\n        {\n            LOGGED_OUT,\n            IN_PROGRESS,\n            LOGGED_IN,\n            LOGIN_ERROR\n        }\n\n        static string s_AssetStoreUrl = null;\n        static string s_AssetStoreSearchUrl = null;\n        static LoginState sLoginState = AssetStoreClient.LoginState.LOGGED_OUT;\n        static string sLoginErrorMessage = null;\n        public static string LoginErrorMessage { get { return sLoginErrorMessage; } }\n        public delegate void DoneCallback(AssetStoreResponse response);\n        public delegate void DoneLoginCallback(string errorMessage);\n\n        // Version parameters expected by the server\n        static string VersionParams\n        {\n            get\n            {\n                return \"unityversion=\" + System.Uri.EscapeDataString(Application.unityVersion) + \"&skip_terms=1\";\n            }\n        }\n\n        // The base asset store url as parsed from the loader.html file\n        static string AssetStoreUrl\n        {\n            get\n            {\n                if (s_AssetStoreUrl == null)\n                    s_AssetStoreUrl = AssetStoreUtils.GetAssetStoreUrl();\n                // s_AssetStoreUrl = \"https://kharma-test.unity3d.com\";\n                return s_AssetStoreUrl;\n            }\n        }\n\n        // The base asset store url as parsed from the loader.html file\n        static string AssetStoreSearchUrl\n        {\n            get\n            {\n                if (s_AssetStoreSearchUrl == null)\n                    s_AssetStoreSearchUrl = AssetStoreUtils.GetAssetStoreSearchUrl();\n                // s_AssetStoreSearchUrl = \"http://shawarma-test.unity3d.com\";\n                return s_AssetStoreSearchUrl;\n            }\n        }\n\n        static AssetStoreClient()\n        {\n            ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };\n        }\n\n        // The base server API url. This is used for all the normal request towards the server API.\n        static string APIUrl(string path)\n        {\n            return String.Format(\"{0}/api{2}.json?{1}\" , AssetStoreUrl, VersionParams, path);\n        }\n\n        static string APISearchUrl(string path)\n        {\n            return String.Format(\"{0}/public-api{2}.json?{1}\" , AssetStoreSearchUrl, VersionParams, path);\n        }\n\n        // The saved session ID if the user has allowed remembering it.\n        static string SavedSessionID\n        {\n            get\n            {\n                if (RememberSession)\n                    return EditorPrefs.GetString(\"kharma.sessionid\", \"\");\n                return \"\";\n            }\n            set { EditorPrefs.SetString(\"kharma.sessionid\", value); }\n        }\n\n        public static bool HasSavedSessionID\n        {\n            get { return !string.IsNullOrEmpty(SavedSessionID); }\n        }\n\n        internal static string ActiveSessionID\n        {\n            get\n            {\n                if (AssetStoreContext.SessionHasString(\"kharma.active_sessionid\"))\n                    return AssetStoreContext.SessionGetString(\"kharma.active_sessionid\");\n                return \"\";\n            }\n            set { AssetStoreContext.SessionSetString(\"kharma.active_sessionid\", value); }\n        }\n\n        public static bool HasActiveSessionID\n        {\n            get { return !string.IsNullOrEmpty(ActiveSessionID); }\n        }\n\n        static string ActiveOrUnauthSessionID\n        {\n            get\n            {\n                string s = ActiveSessionID;\n                if (s == \"\")\n                    return kUnauthSessionID;\n                return s;\n            }\n        }\n\n        static public bool RememberSession\n        {\n            get { return EditorPrefs.GetString(\"kharma.remember_session\") == \"1\"; }\n            set { EditorPrefs.SetString(\"kharma.remember_session\", value ? \"1\" : \"0\"); }\n        }\n\n        // The authentication token\n        static string GetToken()\n        {\n            return InternalEditorUtility.GetAuthToken();\n        }\n\n        // Login status\n        public static bool LoggedIn() { return !string.IsNullOrEmpty(ActiveSessionID); }\n        public static bool LoggedOut() { return string.IsNullOrEmpty(ActiveSessionID); }\n        public static bool LoginError() { return sLoginState == LoginState.LOGIN_ERROR; }\n        public static bool LoginInProgress() { return sLoginState == LoginState.IN_PROGRESS; }\n\n        internal static void LoginWithCredentials(string username, string password, bool rememberMe, DoneLoginCallback callback)\n        {\n            if (sLoginState == LoginState.IN_PROGRESS)\n            {\n                Debug.LogError(\"Tried to login with credentials while already in progress of logging in\");\n                return;\n            }\n            sLoginState = LoginState.IN_PROGRESS;\n            RememberSession = rememberMe;\n            string url = AssetStoreUrl + \"/login?skip_terms=1\";\n\n            AssetStoreClient.sLoginErrorMessage = null;\n            AsyncHTTPClient client = new AsyncHTTPClient(url.Replace(\"http://\", \"https://\"));\n            client.postData = \"user=\" + username + \"&pass=\" + password;\n            client.header[\"X-Unity-Session\"] = kUnauthSessionID + GetToken();\n            client.doneCallback = WrapLoginCallback(callback);\n            client.Begin();\n        }\n\n        /*\n         * Tries to login using a remembered session\n         */\n        internal static void LoginWithRememberedSession(DoneLoginCallback callback)\n        {\n            if (sLoginState == LoginState.IN_PROGRESS)\n            {\n                Debug.LogError(\"Tried to login with remembered session while already in progress of logging in\");\n                return;\n            }\n            sLoginState = LoginState.IN_PROGRESS;\n\n            // Make sure the session is not present if we're not allowed to use it\n            if (!RememberSession)\n                SavedSessionID = \"\";\n\n            string url = AssetStoreUrl + \"/login?skip_terms=1&reuse_session=\" + SavedSessionID;\n            AssetStoreClient.sLoginErrorMessage = null;\n            AsyncHTTPClient client = new AsyncHTTPClient(url);\n            client.header[\"X-Unity-Session\"] = kUnauthSessionID + GetToken();\n            client.doneCallback = WrapLoginCallback(callback);\n            client.Begin();\n        }\n\n        // Helper function for login callbacks\n        static AsyncHTTPClient.DoneCallback WrapLoginCallback(DoneLoginCallback callback)\n        {\n            return delegate(IAsyncHTTPClient job) {\n                // We're logging in\n                string msg = job.text;\n                if (!job.IsSuccess())\n                {\n                    AssetStoreClient.sLoginState = LoginState.LOGIN_ERROR;\n                    AssetStoreClient.sLoginErrorMessage = job.responseCode >= 200 && job.responseCode < 300 ? msg : \"Failed to login - please retry\";\n                }\n                else if (msg.StartsWith(\"<!DOCTYPE\"))     // TODO: Expose status line in job\n                {\n                    AssetStoreClient.sLoginState = LoginState.LOGIN_ERROR;\n                    AssetStoreClient.sLoginErrorMessage = \"Failed to login\";\n                }\n                else\n                {\n                    AssetStoreClient.sLoginState = LoginState.LOGGED_IN;\n                    if (msg.Contains(\"@\"))     // login with reused session id returns the user email\n                        AssetStoreClient.ActiveSessionID = SavedSessionID;\n                    else\n                        AssetStoreClient.ActiveSessionID = msg;\n\n                    if (RememberSession)\n                    {\n                        SavedSessionID = ActiveSessionID;\n                    }\n                }\n                callback(AssetStoreClient.sLoginErrorMessage);\n            };\n        }\n\n        public static void Logout()\n        {\n            ActiveSessionID = \"\";\n            SavedSessionID = \"\";\n            sLoginState = AssetStoreClient.LoginState.LOGGED_OUT;\n        }\n\n        // Create a pending HTTP GET request to the server\n        static AsyncHTTPClient CreateJSONRequest(string url, DoneCallback callback)\n        {\n            AsyncHTTPClient client = new AsyncHTTPClient(url);\n            client.header[\"X-Unity-Session\"] = ActiveOrUnauthSessionID + GetToken();\n            client.doneCallback = WrapJsonCallback(callback);\n            client.Begin();\n            return client;\n        }\n\n        // Create a pending HTTP POST request to the server\n        static AsyncHTTPClient CreateJSONRequestPost(string url, Dictionary<string, string> param,\n            DoneCallback callback)\n        {\n            AsyncHTTPClient client = new AsyncHTTPClient(url);\n\n            client.header[\"X-Unity-Session\"] = ActiveOrUnauthSessionID + GetToken();\n            client.postDictionary = param;\n\n            client.doneCallback = WrapJsonCallback(callback);\n            client.Begin();\n            return client;\n        }\n\n        /* TODO: Implement PUT from a filepath in back end curl code\n        // Create a pending HTTP PUT request to the server\n        static void CreateJSONRequestPut(string url, string filepath,\n                                                 DoneCallback callback) {\n            AsyncHTTPClient job = new AsyncHTTPClient(url, \"PUT\");\n            client.SetUploadFilePath(filepath);\n            client.header[\"X-Unity-Session\"] = ActiveOrUnauthSessionID + GetToken();\n            client.doneCallback = WrapJsonCallback(callback);\n            client.Begin();\n        }\n        */\n\n        /* Handle HTTP results and forward them to the original callback.\n         *\n         * This will callback any handler registered for requests that has finished.\n         */\n        private static AsyncHTTPClient.DoneCallback WrapJsonCallback(DoneCallback callback)\n        {\n            return delegate(IAsyncHTTPClient job) {\n                if (job.IsDone())\n                {\n                    try\n                    {\n                        AssetStoreResponse c = ParseContent(job);\n                        callback(c);\n                    }\n                    catch (Exception ex)\n                    {\n                        Debug.Log(\"Uncaught exception in async net callback: \" + ex.Message);\n                        Debug.Log(ex.StackTrace);\n                    }\n                }\n            };\n        }\n\n        /*\n         * Parse the HTTP response as a JSON string and into a AssetStoreResponse object.\n         */\n        static AssetStoreResponse ParseContent(IAsyncHTTPClient job)\n        {\n            AssetStoreResponse resp = new AssetStoreResponse();\n            resp.job = job;\n            resp.dict = null;\n            resp.ok = false;\n            AsyncHTTPClient.State state = job.state;\n            string content = job.text;\n            if (!AsyncHTTPClient.IsSuccess(state))\n            {\n                Console.WriteLine(content);\n                // Debug.Log(\"Request error: \" + content);\n                return resp; // abort\n            }\n\n            string status;\n            string message;\n            resp.dict = ParseJSON(content, out status, out message);\n            if (status == \"error\")\n            {\n                Debug.LogError(\"Request error (\" + status + \"): \" + message);\n                return resp;\n            }\n            resp.ok = true;\n            return resp;\n        }\n\n        /*\n         * Parse the HTTP response as a JSON string into a string/JSONValue dictionary\n         */\n        static Dictionary<string, JSONValue> ParseJSON(string content, out string status, out string message)\n        {\n            // extract ids etc. from json message\n            message = null;\n            status = null;\n            JSONValue jval;\n            try\n            {\n                JSONParser parser = new JSONParser(content);\n                jval = parser.Parse();\n            }\n            catch (JSONParseException ex)\n            {\n                Debug.Log(\"Error parsing server reply: \" + content);\n                Debug.Log(ex.Message);\n                return null;\n            }\n            Dictionary<string, JSONValue> dict;\n            try\n            {\n                dict = jval.AsDict(true);\n                if (dict == null)\n                {\n                    Debug.Log(\"Error parsing server message: \" + content);\n                    return null;\n                }\n                // Old backend encapsulated all replies in a \"result\" dict. Just unwrap that here.\n                if (dict.ContainsKey(\"result\") && dict[\"result\"].IsDict())\n                {\n                    dict = dict[\"result\"].AsDict(true);\n                }\n\n                if (dict.ContainsKey(\"message\"))\n                    message = dict[\"message\"].AsString(true);\n                if (dict.ContainsKey(\"status\"))\n                    status = dict[\"status\"].AsString(true);\n                else if (dict.ContainsKey(\"error\"))\n                {\n                    status = dict[\"error\"].AsString(true);\n                    if (status == \"\")\n                        status = \"ok\";\n                }\n                else\n                    status = \"ok\";\n            }\n            catch (JSONTypeException ex)\n            {\n                Debug.Log(\"Error parsing server reply. \" + content);\n                Debug.Log(ex.Message);\n                return null;\n            }\n            return dict;\n        }\n\n        internal struct SearchCount\n        {\n            public string name;\n            public int offset;\n            public int limit;\n        }\n\n\n        /*\n         * Searches the asset store for assets and passes the results to DoneCallback\n         */\n        internal static AsyncHTTPClient SearchAssets(string searchString, string[] requiredClassNames, string[] assetLabels,\n            List<SearchCount> counts,\n            AssetStoreSearchResults.Callback callback)\n        {\n            string offsets = \"\";\n            string limits = \"\";\n            string groupNames = \"\";\n            string delim = \"\";\n            foreach (SearchCount v in counts)\n            {\n                offsets += delim + v.offset;\n                limits += delim + v.limit;\n                groupNames += delim + v.name;\n                delim = \",\";\n            }\n\n            // If one af the class names is \"MonoScript\" then also include \"Script\" since\n            // that is what asset store expects\n            if (Array.Exists(requiredClassNames, (string a) => { return a.Equals(\"MonoScript\", StringComparison.OrdinalIgnoreCase); }))\n            {\n                Array.Resize(ref requiredClassNames, requiredClassNames.Length + 1);\n                requiredClassNames[requiredClassNames.Length - 1] = \"Script\";\n            }\n\n            string url =  string.Format(\"{0}&q={1}&c={2}&l={3}&O={4}&N={5}&G={6}\",\n                APISearchUrl(\"/search/assets\"),\n                System.Uri.EscapeDataString(searchString),\n                System.Uri.EscapeDataString(string.Join(\",\", requiredClassNames)),\n                System.Uri.EscapeDataString(string.Join(\",\", assetLabels)),\n                offsets, limits, groupNames);\n\n            //Debug.Log(url);\n            //Debug.Log(\"session key \" + ActiveOrUnauthSessionID + GetToken());\n            AssetStoreSearchResults r = new AssetStoreSearchResults(callback);\n            return CreateJSONRequest(url, delegate(AssetStoreResponse ar) { r.Parse(ar); });\n        }\n\n        /*\n         * Looks up assets by ID in the asset store and passes the results to DoneCallback\n         */\n        internal static AsyncHTTPClient AssetsInfo(List<AssetStoreAsset> assets, AssetStoreAssetsInfo.Callback callback)\n        {\n            string url = APIUrl(\"/assets/list\");\n            foreach (AssetStoreAsset asset in assets)\n                url += \"&id=\" + asset.id;\n            // Debug.Log(url);\n            AssetStoreAssetsInfo r = new AssetStoreAssetsInfo(callback, assets);\n            return CreateJSONRequest(url, delegate(AssetStoreResponse ar) { r.Parse(ar); });\n        }\n\n        /*\n         * Returns purchase info for the package that has assetID as part of it.\n         */\n        internal static AsyncHTTPClient DirectPurchase(int packageID, string password, PurchaseResult.Callback callback)\n        {\n            string url = APIUrl(string.Format(\"/purchase/direct/{0}\", packageID.ToString()));\n            // Debug.Log(url);\n            PurchaseResult r = new PurchaseResult(callback);\n            Dictionary<string, string> d = new Dictionary<string, string>();\n            d[\"password\"] = password;\n            return CreateJSONRequestPost(url, d, delegate(AssetStoreResponse ar) { r.Parse(ar); });\n        }\n\n        internal static AsyncHTTPClient BuildPackage(AssetStoreAsset asset, BuildPackageResult.Callback callback)\n        {\n            string url = APIUrl(\"/content/download/\" + asset.packageID);\n            // Debug.Log(url);\n            BuildPackageResult r = new BuildPackageResult(asset, callback);\n            return CreateJSONRequest(url, delegate(AssetStoreResponse ar) { r.Parse(ar); });\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetStore/AssetStoreContext.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditorInternal;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Text.RegularExpressions;\nusing System.Linq;\nusing System.IO;\nusing UnityEditor.Web;\n\nnamespace UnityEditor\n{\n    [InitializeOnLoad]\n    internal partial class AssetStoreContext\n    {\n        static AssetStoreContext()\n        {\n            AssetStoreContext.GetInstance();\n        }\n\n        public static AssetStoreContext GetInstance()\n        {\n            if (s_Instance == null)\n            {\n                s_Instance = new AssetStoreContext();\n            }\n\n            return s_Instance;\n        }\n\n        public string GetInitialOpenURL()\n        {\n            if (initialOpenURL != null)\n            {\n                string tmp = initialOpenURL;\n                initialOpenURL = null;\n                return tmp;\n            }\n            else\n            {\n                return \"\";\n            }\n        }\n\n        public string GetAuthToken()\n        {\n            return UnityEditorInternal.InternalEditorUtility.GetAuthToken();\n        }\n\n        [Obsolete(\"GetLicenseFlags is no longer supported\", error: true)]\n        public int[] GetLicenseFlags()\n        {\n            return new int[] {};\n        }\n\n        public string GetString(string key)\n        {\n            return EditorPrefs.GetString(key);\n        }\n\n        public int GetInt(string key)\n        {\n            return EditorPrefs.GetInt(key);\n        }\n\n        public float GetFloat(string key)\n        {\n            return EditorPrefs.GetFloat(key);\n        }\n\n        public void SetString(string key, string value)\n        {\n            EditorPrefs.SetString(key, value);\n        }\n\n        public void SetInt(string key, int value)\n        {\n            EditorPrefs.SetInt(key, value);\n        }\n\n        public void SetFloat(string key, float value)\n        {\n            EditorPrefs.SetFloat(key, value);\n        }\n\n        public bool HasKey(string key)\n        {\n            return EditorPrefs.HasKey(key);\n        }\n\n        public void DeleteKey(string key)\n        {\n            EditorPrefs.DeleteKey(key);\n        }\n\n        public int GetSkinIndex()\n        {\n            return EditorGUIUtility.skinIndex;\n        }\n\n        public bool OpenPackage(string id)\n        {\n            return OpenPackage(id, \"default\");\n        }\n\n        public bool OpenPackage(string id, string action)\n        {\n            return OpenPackageInternal(id);\n        }\n\n        public static bool OpenPackageInternal(string id)\n        {\n            Match match = s_GeneratedIDRegExp.Match(id);\n            if (match.Success && File.Exists(match.Groups[1].Value)) // If id looks like a path name, just try to open that\n            {\n                AssetDatabase.ImportPackage(match.Groups[1].Value, true);\n                return true;\n            }\n            else\n            {\n                foreach (PackageInfo package in PackageInfo.GetPackageList())\n                {\n                    if (package.jsonInfo != \"\")\n                    {\n                        JSONValue item = JSONParser.SimpleParse(package.jsonInfo);\n                        string itemID = item.Get(\"id\").IsNull() ? null : item[\"id\"].AsString(true);\n                        if (itemID != null && itemID == id && File.Exists(package.packagePath))\n                        {\n                            AssetDatabase.ImportPackage(package.packagePath, true);\n                            return true;\n                        }\n                    }\n                }\n            }\n            Debug.LogError(\"Unknown package ID \" + id);\n            return false;\n        }\n\n        public void OpenBrowser(string url)\n        {\n            Application.OpenURL(url);\n        }\n\n        [Serializable]\n        public struct DownloadAssetInfo\n        {\n            public string package_id;\n            public string package_name;\n            public string publisher_name;\n            public string category_name;\n        }\n\n        public void Download(Package package, DownloadInfo downloadInfo)\n        {\n            Download(\n                downloadInfo.id,\n                downloadInfo.url,\n                downloadInfo.key,\n                package.title,\n                package.publisher.label,\n                package.category.label,\n                null\n            );\n        }\n\n        public static void Download(string package_id, string url, string key, string package_name,\n            string publisher_name, string category_name, AssetStoreUtils.DownloadDoneCallback doneCallback)\n        {\n            string[] dest = PackageStorePath(publisher_name, category_name,\n                package_name, package_id, url);\n\n            JSONValue existing = JSONParser.SimpleParse(AssetStoreUtils.CheckDownload(package_id, url, dest, key));\n\n            // If the package is actively being downloaded right now just return\n            if (existing.Get(\"in_progress\").AsBool(true))\n            {\n                Debug.Log(\"Will not download \" + package_name + \". Download is already in progress.\");\n                return;\n            }\n\n            // The package is not being downloaded.\n            // If the package has previously been partially downloaded then\n            // resume that download.\n            string existingUrl = existing.Get(\"download.url\").AsString(true);\n            string existingKey = existing.Get(\"download.key\").AsString(true);\n            bool resumeOK = (existingUrl == url && existingKey == key);\n\n            JSONValue download = new JSONValue();\n            download[\"url\"] = url;\n            download[\"key\"] = key;\n            JSONValue parameters = new JSONValue();\n            parameters[\"download\"] = download;\n\n            AssetStoreUtils.Download(package_id, url, dest, key, parameters.ToString(), resumeOK, doneCallback);\n            EditorAnalytics.SendAssetDownloadEvent(new DownloadAssetInfo()\n            {\n                package_id = package_id,\n                package_name = package_name,\n                publisher_name = publisher_name,\n                category_name = category_name\n            });\n        }\n\n        /// <summary>\n        /// Create an array consisting of publisherName, categoryName and packageName\n        /// This is to be used by AssetStoreUtils.*Download functions\n        /// </summary>\n        public static string[] PackageStorePath(string publisher_name,\n            string category_name,\n            string package_name,\n            string package_id,\n            string url)\n        {\n            string[] dest = { publisher_name, category_name, package_name };\n\n            for (int i = 0; i < 3; i++)\n                dest[i] = s_InvalidPathCharsRegExp.Replace(dest[i], \"\");\n\n            // If package name cannot be stored as a valid file name, use the package id\n            if (dest[2] == \"\")\n                dest[2] = s_InvalidPathCharsRegExp.Replace(package_id, \"\");\n\n            // If still no valid chars use a mangled url as the file name\n            if (dest[2] == \"\")\n                dest[2] = s_InvalidPathCharsRegExp.Replace(url, \"\");\n\n            return dest;\n        }\n\n        public PackageList GetPackageList()\n        {\n            var packages = new Dictionary<string, Package>();\n            var packageInfos = PackageInfo.GetPackageList();\n\n            foreach (PackageInfo info in packageInfos)\n            {\n                Package package = new Package();\n                if (info.jsonInfo == \"\")\n                {\n                    package.title = System.IO.Path.GetFileNameWithoutExtension(info.packagePath);\n                    package.id = info.packagePath;\n\n                    if (IsBuiltinStandardAsset(info.packagePath))\n                    {\n                        package.publisher = new LabelAndId { label = \"Unity Technologies\", id = \"1\" };\n                        package.category = new LabelAndId { label = \"Prefab Packages\", id = \"4\" };\n                        package.version = \"3.5.0.0\";\n                    }\n                }\n                else\n                {\n                    var jsonData = JSONParser.SimpleParse(info.jsonInfo);\n                    if (jsonData.IsNull())\n                        continue;\n\n                    package.Initialize(jsonData);\n\n                    if (package.id == null)\n                    {\n                        var linkId = jsonData.Get(\"link.id\");\n                        if (!linkId.IsNull())\n                            package.id = linkId.AsString();\n                        else\n                            package.id = info.packagePath;\n                    }\n                }\n\n                package.local_icon = info.iconURL;\n                package.local_path = info.packagePath;\n\n                // If no package with the same ID is in the dictionary yet or if the current package\n                // is newer than what we currently have in the dictionary, add the package to the\n                // dictionary.\n                if (!packages.ContainsKey(package.id) ||\n                    packages[package.id].version_id == null ||\n                    packages[package.id].version_id == \"-1\" ||\n                    (package.version_id != null && package.version_id != \"-1\" && Int32.Parse(packages[package.id].version_id) <= Int32.Parse(package.version_id)))\n                {\n                    packages[package.id] = package;\n                }\n            }\n\n            var results = packages.Values.ToArray();\n            return new PackageList { results = results };\n        }\n\n        private bool IsBuiltinStandardAsset(string path)\n        {\n            return s_StandardPackageRegExp.IsMatch(path);\n        }\n\n        private static Regex s_StandardPackageRegExp = new Regex(@\"/Standard Packages/(Character\\ Controller|Glass\\ Refraction\\ \\(Pro\\ Only\\)|Image\\ Effects\\ \\(Pro\\ Only\\)|Light\\ Cookies|Light\\ Flares|Particles|Physic\\ Materials|Projectors|Scripts|Standard\\ Assets\\ \\(Mobile\\)|Skyboxes|Terrain\\ Assets|Toon\\ Shading|Tree\\ Creator|Water\\ \\(Basic\\)|Water\\ \\(Pro\\ Only\\))\\.unitypackage$\", RegexOptions.IgnoreCase);\n        private static Regex s_GeneratedIDRegExp = new Regex(@\"^\\{(.*)\\}$\");\n        private static Regex s_InvalidPathCharsRegExp = new Regex(@\"[^a-zA-Z0-9() _-]\");\n\n        internal string initialOpenURL;\n\n        private static AssetStoreContext s_Instance;\n\n        // Some data is created through reflection in C++ and then\n        // passed on to us.  Shut up warning about fields that are\n        // never assigned to.\n        #pragma warning disable 0649\n\n        // The following classes are used for data interchange with JavaScript.\n        // Public fields in them directly translate to respective properties on\n        // JavaScript objects.\n\n        public class DownloadInfo\n        {\n            public string url;\n            public string key;\n            public string id;\n        }\n\n        public class LabelAndId\n        {\n            public string label;\n            public string id;\n\n            public void Initialize(JSONValue json)\n            {\n                if (json.ContainsKey(\"label\"))\n                    label = json[\"label\"].AsString();\n\n                if (json.ContainsKey(\"id\"))\n                    id = json[\"id\"].AsString();\n            }\n\n            public override string ToString()\n            {\n                return string.Format(\"{{label={0}, id={1}}}\", label, id);\n            }\n        }\n\n        public class Link\n        {\n            public string type;\n            public string id;\n\n            public void Initialize(JSONValue json)\n            {\n                if (json.ContainsKey(\"type\"))\n                    type = json[\"type\"].AsString();\n\n                if (json.ContainsKey(\"id\"))\n                    id = json[\"id\"].AsString();\n            }\n\n            public override string ToString()\n            {\n                return string.Format(\"{{type={0}, id={1}}}\", type, id);\n            }\n        }\n\n        public class Package\n        {\n            public string title;\n            public string id;\n            public string version;\n            public string version_id;\n            public string local_icon;\n            public string local_path;\n            public string pubdate;\n            public string description;\n            public LabelAndId publisher;\n            public LabelAndId category;\n            public Link link;\n\n            public void Initialize(JSONValue json)\n            {\n                if (json.ContainsKey(\"title\"))\n                    title = json[\"title\"].AsString();\n\n                if (json.ContainsKey(\"id\"))\n                    id = json[\"id\"].AsString();\n\n                if (json.ContainsKey(\"version\"))\n                    version = json[\"version\"].AsString();\n\n                if (json.ContainsKey(\"version_id\"))\n                    version_id = json[\"version_id\"].AsString();\n\n                if (json.ContainsKey(\"local_icon\"))\n                    local_icon = json[\"local_icon\"].AsString();\n\n                if (json.ContainsKey(\"local_path\"))\n                    local_path = json[\"local_path\"].AsString();\n\n                if (json.ContainsKey(\"pubdate\"))\n                    pubdate = json[\"pubdate\"].AsString();\n\n                if (json.ContainsKey(\"description\"))\n                    description = json[\"description\"].AsString();\n\n                if (json.ContainsKey(\"publisher\"))\n                {\n                    publisher = new LabelAndId();\n                    publisher.Initialize(json[\"publisher\"]);\n                }\n\n                if (json.ContainsKey(\"category\"))\n                {\n                    category = new LabelAndId();\n                    category.Initialize(json[\"category\"]);\n                }\n\n                if (json.ContainsKey(\"link\"))\n                {\n                    link = new Link();\n                    link.Initialize(json[\"link\"]);\n                }\n            }\n\n            public override string ToString()\n            {\n                return string.Format\n                        (\"{{title={0}, id={1}, publisher={2}, category={3}, pubdate={8}, version={4}, version_id={5}, description={9}, link={10}, local_icon={6}, local_path={7}}}\",\n                        title, id, publisher, category, version, version_id, local_icon, local_path, pubdate, description, link);\n            }\n        }\n\n        public class PackageList\n        {\n            public Package[] results;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetStore/AssetStorePreviewManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    /**\n     * Fetching and caches preview images of asset store assets from the\n     * asset store server\n     */\n    internal sealed class AssetStorePreviewManager\n    {\n        private AssetStorePreviewManager() {} // disallow instantiation\n\n        static AssetStorePreviewManager s_SharedAssetStorePreviewManager = null;\n        static RenderTexture s_RenderTexture = null;\n\n        static internal AssetStorePreviewManager Instance\n        {\n            get\n            {\n                if (s_SharedAssetStorePreviewManager == null)\n                {\n                    s_SharedAssetStorePreviewManager = new AssetStorePreviewManager();\n                    s_SharedAssetStorePreviewManager.m_DummyItem.lastUsed = -1;\n                }\n                return s_SharedAssetStorePreviewManager;\n            }\n        }\n\n        public class CachedAssetStoreImage\n        {\n            private const double kFadeTime = 0.5;\n\n            public Texture2D image;\n            public double lastUsed; // time since app start\n            public double lastFetched; // time since app start\n            public int requestedWidth; //\n            public string label; //\n            internal AsyncHTTPClient client; // null if not in progress of fetching preview\n            public Color color\n            {\n                get\n                {\n                    return Color.Lerp(new Color(1, 1, 1, 0), new Color(1, 1, 1, 1),\n                        Mathf.Min(1f, (float)((EditorApplication.timeSinceStartup - lastFetched) / kFadeTime)));\n                }\n            }\n        }\n\n\n        // @TODO: MAKE handling of incoming images span several repaints in order to\n        //        not have the jumpy behaviour. Just put the in a queue an handle them from there.\n        //\n\n\n        Dictionary<string, CachedAssetStoreImage> m_CachedAssetStoreImages;\n        const int kMaxConcurrentDownloads = 15;\n        const int kMaxConvertionsPerTick = 1;\n        int m_MaxCachedAssetStoreImages = 10;\n        int m_Aborted = 0;\n        int m_Success = 0;\n        internal int Requested = 0;\n        internal int CacheHit = 0;\n        int m_CacheRemove = 0;\n        int m_ConvertedThisTick = 0;\n        CachedAssetStoreImage m_DummyItem = new CachedAssetStoreImage();\n\n        static bool s_NeedsRepaint = false;\n\n        static Dictionary<string, CachedAssetStoreImage> CachedAssetStoreImages\n        {\n            get\n            {\n                if (Instance.m_CachedAssetStoreImages == null)\n                {\n                    Instance.m_CachedAssetStoreImages = new Dictionary<string, CachedAssetStoreImage>();\n                }\n                return Instance.m_CachedAssetStoreImages;\n            }\n        }\n\n        public static int MaxCachedImages\n        {\n            get { return Instance.m_MaxCachedAssetStoreImages; }\n            set { Instance.m_MaxCachedAssetStoreImages  = value; }\n        }\n\n        public static bool CacheFull\n        {\n            get { return CachedAssetStoreImages.Count >= MaxCachedImages; }\n        }\n\n        public static int Downloading\n        {\n            get\n            {\n                int c = 0;\n                foreach (KeyValuePair<string, CachedAssetStoreImage> kv in CachedAssetStoreImages)\n                    if (kv.Value.client != null) c++;\n                return c;\n            }\n        }\n\n        public static string StatsString()\n        {\n            return string.Format(\"Reqs: {0}, OK: {1}, Abort: {2}, CacheDel: {3}, Cache: {4}/{5}, CacheHit: {6}\",\n                Instance.Requested, Instance.m_Success, Instance.m_Aborted, Instance.m_CacheRemove,\n                AssetStorePreviewManager.CachedAssetStoreImages.Count,\n                Instance.m_MaxCachedAssetStoreImages,\n                Instance.CacheHit);\n        }\n\n        /**\n         * Return a texture from a url that points to an image resource\n         *\n         * This method does not block but queues a request to fetch the image and return null.\n         * When the image has been fetched this method will return the image texture downloaded.\n         */\n        public static CachedAssetStoreImage TextureFromUrl(string url, string label, int textureSize, GUIStyle labelStyle, GUIStyle iconStyle, bool onlyCached)\n        {\n            if (string.IsNullOrEmpty(url))\n                return Instance.m_DummyItem;\n\n            CachedAssetStoreImage cached;\n            bool newentry = true;\n\n            if (CachedAssetStoreImages.TryGetValue(url, out cached))\n            {\n                cached.lastUsed = EditorApplication.timeSinceStartup;\n\n                // Refetch the image if the size has changed and is not in the progress of being fetched\n                bool refetchInitiated = cached.requestedWidth == textureSize;\n                bool correctSize = cached.image != null && cached.image.width == textureSize;\n\n                bool cacheRequestAborted = cached.requestedWidth == -1;\n\n                if ((correctSize || refetchInitiated || onlyCached) && !cacheRequestAborted)\n                {\n                    Instance.CacheHit++;\n\n                    // Use cached image (that may be null) if we're in progress of fetching the image\n                    // or if we have rendered the images correctly\n                    //return cached;\n                    bool fetchingImage = cached.client != null;\n                    bool labelDrawn = cached.label == null;\n                    bool valid = fetchingImage || labelDrawn;\n                    bool convPerTickExceeded = Instance.m_ConvertedThisTick > kMaxConvertionsPerTick;\n                    s_NeedsRepaint = s_NeedsRepaint || convPerTickExceeded;\n                    return (valid || convPerTickExceeded) ?\n                        cached :\n                        RenderEntry(cached, labelStyle, iconStyle);\n                }\n                //Debug.Log(string.Format(\"Found {0} {1} {2} {3}\", correctSize, refetchInitiated, onlyCached, cacheRequestAborted));\n                newentry = false;\n                if (Downloading >= kMaxConcurrentDownloads) return cached.image == null ? Instance.m_DummyItem : cached;\n            }\n            else\n            {\n                if (onlyCached || Downloading >= kMaxConcurrentDownloads)   return Instance.m_DummyItem;\n                cached = new CachedAssetStoreImage();\n                cached.image = null;\n                cached.lastUsed = EditorApplication.timeSinceStartup;\n                //Debug.Log(\"url is \" + textureSize.ToString() + \" \" + url);\n            }\n\n            // Only set fetch time when there is not image in order to use it for\n            // fading in the image when it becomes available\n            if (cached.image == null)\n                cached.lastFetched = EditorApplication.timeSinceStartup;\n\n            cached.requestedWidth = textureSize;\n            cached.label = label;\n\n            AsyncHTTPClient client = null;\n            client = SetupTextureDownload(cached, url, \"previewSize-\" + textureSize);\n\n            ExpireCacheEntries();\n\n            if (newentry)\n                CachedAssetStoreImages.Add(url, cached);\n\n            client.Begin();\n\n            Instance.Requested++;\n            return cached;\n        }\n\n        private static AsyncHTTPClient SetupTextureDownload(CachedAssetStoreImage cached, string url, string tag)\n        {\n            AsyncHTTPClient client = new AsyncHTTPClient(url);\n            cached.client = client;\n            client.tag = tag;\n            client.doneCallback = delegate(IAsyncHTTPClient c) {\n                // Debug.Log(\"Got image \" + EditorApplication.timeSinceStartup.ToString());\n                cached.client = null;\n                if (!client.IsSuccess())\n                {\n                    if (client.state != AsyncHTTPClient.State.ABORTED)\n                    {\n                        string err = \"error \" + client.text + \" \" + client.state + \" '\" + url + \"'\";\n                        if (ObjectListArea.s_Debug)\n                            Debug.LogError(err);\n                        else\n                            System.Console.Write(err);\n                    }\n                    else\n                    {\n                        Instance.m_Aborted++;\n                    }\n                    return;\n                }\n\n                // In the case of refetch because of resize first destroy the current image\n                if (cached.image != null)\n                    Object.DestroyImmediate(cached.image);\n\n                cached.image = c.texture;\n\n                s_NeedsRepaint = true;\n                Instance.m_Success++;\n            };\n            return client;\n        }\n\n        // Make room for image if needed (because of cache limits)\n        private static void ExpireCacheEntries()\n        {\n            while (CacheFull)\n            {\n                string oldestUrl = null;\n                CachedAssetStoreImage oldestEntry = null;\n                foreach (KeyValuePair<string, CachedAssetStoreImage> kv in CachedAssetStoreImages)\n                {\n                    if (oldestEntry == null || oldestEntry.lastUsed > kv.Value.lastUsed)\n                    {\n                        oldestEntry = kv.Value;\n                        oldestUrl = kv.Key;\n                    }\n                }\n                CachedAssetStoreImages.Remove(oldestUrl);\n                Instance.m_CacheRemove++;\n                if (oldestEntry == null)\n                {\n                    Debug.LogError(\"Null entry found while removing cache entry\");\n                    break;\n                }\n                if (oldestEntry.client != null)\n                {\n                    oldestEntry.client.Abort();\n                    oldestEntry.client = null;\n                }\n                if (oldestEntry.image != null)\n                    Object.DestroyImmediate(oldestEntry.image);\n            }\n        }\n\n        /*\n         * When the new GUI system is is place this should render the label to the cached icon\n         * to speed up rendering. For now we just scale the incoming image and render the label\n         * separately\n         */\n        private static CachedAssetStoreImage RenderEntry(CachedAssetStoreImage cached, GUIStyle labelStyle, GUIStyle iconStyle)\n        {\n            if (cached.label == null || cached.image == null) return cached;\n            Texture2D tmp = cached.image;\n            cached.image = new Texture2D(cached.requestedWidth, cached.requestedWidth, TextureFormat.RGB24, false, true);\n            ScaleImage(cached.requestedWidth, cached.requestedWidth, tmp, cached.image, iconStyle);\n            // Compressing creates artifacts on the images\n            // cached.image.Compress(true);\n            Object.DestroyImmediate(tmp);\n            cached.label = null;\n            Instance.m_ConvertedThisTick++;\n            return cached;\n        }\n\n        /** Slow version of scaling an image but i doesn't\n         *  matter since it is not performance critical\n         */\n        internal static void ScaleImage(int w, int h, Texture2D inimage, Texture2D outimage, GUIStyle bgStyle)\n        {\n            SavedRenderTargetState saved = new SavedRenderTargetState();\n\n            if (s_RenderTexture != null && (s_RenderTexture.width != w || s_RenderTexture.height != h))\n            {\n                Object.DestroyImmediate(s_RenderTexture);\n                s_RenderTexture = null;\n            }\n\n            if (s_RenderTexture == null)\n            {\n                s_RenderTexture = RenderTexture.GetTemporary(w, h, 16, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);\n                s_RenderTexture.hideFlags = HideFlags.HideAndDontSave;\n            }\n\n            RenderTexture r = s_RenderTexture;\n            RenderTexture.active = r;\n            Rect rect = new Rect(0, 0, w, h);\n\n            EditorGUIUtility.SetRenderTextureNoViewport(r);\n            GL.LoadOrtho();\n            GL.LoadPixelMatrix(0, w, h, 0);\n            ShaderUtil.rawViewportRect = new Rect(0, 0, w, h);\n            ShaderUtil.rawScissorRect = new Rect(0 , 0, w, h);\n            GL.Clear(true, true, new Color(0, 0, 0, 0));\n\n            Rect blitRect = rect;\n            if (inimage.width > inimage.height)\n            {\n                float newHeight = (float)blitRect.height * ((float)inimage.height / (float)inimage.width);\n                blitRect.height = (int)newHeight;\n                blitRect.y += (int)(newHeight * 0.5f);\n            }\n            else if (inimage.width < inimage.height)\n            {\n                float newWidth = (float)blitRect.width * ((float)inimage.width / (float)inimage.height);\n                blitRect.width = (int)newWidth;\n                blitRect.x += (int)(newWidth * 0.5f);\n            }\n            if (bgStyle != null && bgStyle.normal != null && bgStyle.normal.background != null)\n                Graphics.DrawTexture(rect, bgStyle.normal.background);\n\n            Graphics.DrawTexture(blitRect, inimage);\n            outimage.ReadPixels(rect, 0, 0, false);\n            outimage.Apply();\n            outimage.hideFlags = HideFlags.HideAndDontSave;\n            saved.Restore();\n        }\n\n        /*\n         * Check if textures queued for download has finished downloading.\n         * This call will reset the flag for finished downloads.\n         */\n        public static bool CheckRepaint()\n        {\n            bool needsRepaint = s_NeedsRepaint;\n            s_NeedsRepaint = false;\n            return needsRepaint;\n        }\n\n        // Abort fetching all previews with the specified size\n        public static void AbortSize(int size)\n        {\n            AsyncHTTPClient.AbortByTag(\"previewSize-\" + size);\n\n            // Mark any pending requests for that width in the cases as invalid\n            // now that requests has been aborted.\n            foreach (KeyValuePair<string, CachedAssetStoreImage> kv in AssetStorePreviewManager.CachedAssetStoreImages)\n            {\n                if (kv.Value.requestedWidth != size)\n                    continue;\n                kv.Value.requestedWidth = -1;\n                kv.Value.client = null;\n            }\n        }\n\n        // Abort fetching all reviews that haven't been used since timestamp\n        public static void AbortOlderThan(double timestamp)\n        {\n            foreach (KeyValuePair<string, CachedAssetStoreImage> kv in AssetStorePreviewManager.CachedAssetStoreImages)\n            {\n                CachedAssetStoreImage entry = kv.Value;\n                if (entry.lastUsed >= timestamp || entry.client == null)\n                    continue;\n                entry.requestedWidth = -1;\n                entry.client.Abort();\n                entry.client = null;\n            }\n\n            // @TODO: Currently we know that AbortOlderThan is called exactly once each repaint.\n            //        Therefore this counter can be reset here. Should probably be moved to a\n            //        more intuitive location.\n            Instance.m_ConvertedThisTick = 0;\n        }\n    }\n} // UnityEditor namespace\n"
  },
  {
    "path": "Editor/Mono/AssetStore/AssetStoreWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing UnityEditor.Connect;\nusing UnityEditor.PackageManager.UI;\nusing UnityEditor.UIElements;\n\nnamespace UnityEditor\n{\n    [EditorWindowTitle(title = \"Asset Store\", icon = \"Asset Store\")]\n    internal class AssetStoreWindow : EditorWindow\n    {\n        public static AssetStoreWindow Init()\n        {\n            if (EditorPrefs.GetBool(\"AlwaysOpenAssetStoreInBrowser\", false))\n            {\n                OpenAssetStoreInBrowser();\n                return null;\n            }\n            else\n            {\n                AssetStoreWindow window = GetWindow<AssetStoreWindow>(typeof(SceneView));\n                window.SetMinMaxSizes();\n                window.Show();\n                return window;\n            }\n        }\n\n        [MenuItem(\"Window/Package Management/Asset Store\", false, 2000)]\n        public static void OpenAssetStoreInBrowser()\n        {\n            string assetStoreUrl = UnityConnect.instance.GetConfigurationURL(CloudConfigUrl.CloudAssetStoreUrl);\n            assetStoreUrl += \"?utm_source=unity-editor-window-menu&utm_medium=desktop-app\";\n            if (UnityConnect.instance.loggedIn)\n                UnityConnect.instance.OpenAuthorizedURLInWebBrowser(assetStoreUrl);\n            else Application.OpenURL(assetStoreUrl);\n        }\n\n        [MenuItem(\"Window/Package Management/My Assets\", false, 1501)]\n        public static void OpenMyAssetsInPackageManager()\n        {\n            PackageManagerWindow.OpenAndSelectPage(PackageManager.UI.Internal.MyAssetsPage.k_Id);\n        }\n\n        public void OnEnable()\n        {\n            this.antiAliasing = 4;\n            titleContent = GetLocalizedTitleContent();\n            var windowResource = EditorGUIUtility.Load(\"UXML/AssetStore/AssetStoreWindow.uxml\") as VisualTreeAsset;\n            if (windowResource != null)\n            {\n                var root = windowResource.CloneTree();\n\n                var lightStyleSheet = EditorGUIUtility.Load(UIElementsEditorUtility.s_DefaultCommonLightStyleSheetPath) as StyleSheet;\n                var assetStoreStyleSheet = EditorGUIUtility.Load(\"StyleSheets/AssetStore/AssetStoreWindow.uss\") as StyleSheet;\n                var styleSheet = CreateInstance<StyleSheet>();\n                styleSheet.isDefaultStyleSheet = true;\n\n                var resolver = new StyleSheets.StyleSheetResolver();\n                resolver.AddStyleSheets(lightStyleSheet, assetStoreStyleSheet);\n                resolver.ResolveTo(styleSheet);\n                root.styleSheets.Add(styleSheet);\n\n                rootVisualElement.Add(root);\n                root.StretchToParentSize();\n\n                visitWebsiteButton.clickable.clicked += OnVisitWebsiteButtonClicked;\n                launchPackageManagerButton.clickable.clicked += OnLaunchPackageManagerButtonClicked;\n\n                alwaysOpenInBrowserToggle.SetValueWithoutNotify(EditorPrefs.GetBool(\"AlwaysOpenAssetStoreInBrowser\", false));\n\n                alwaysOpenInBrowserToggle.RegisterValueChangedCallback(changeEvent =>\n                {\n                    EditorPrefs.SetBool(\"AlwaysOpenAssetStoreInBrowser\", changeEvent.newValue);\n                });\n            }\n        }\n\n        public void OnDisable()\n        {\n            visitWebsiteButton.clickable.clicked -= OnVisitWebsiteButtonClicked;\n            launchPackageManagerButton.clickable.clicked -= OnLaunchPackageManagerButtonClicked;\n        }\n\n        public static void OpenURL(string url)\n        {\n            string assetStoreUrl = $\"{UnityConnect.instance.GetConfigurationURL(CloudConfigUrl.CloudAssetStoreUrl)}/packages/{url}\";\n            if (UnityEditor.Connect.UnityConnect.instance.loggedIn)\n                UnityEditor.Connect.UnityConnect.instance.OpenAuthorizedURLInWebBrowser(assetStoreUrl);\n            else Application.OpenURL(assetStoreUrl);\n        }\n\n        private void OnVisitWebsiteButtonClicked()\n        {\n            OpenAssetStoreInBrowser();\n        }\n\n        private void OnLaunchPackageManagerButtonClicked()\n        {\n            PackageManagerWindow.OpenAndSelectPackage(null);\n        }\n\n        private void SetMinMaxSizes()\n        {\n            this.minSize = new Vector2(455, 354);\n            this.maxSize = new Vector2(4000, 4000);\n        }\n\n        private Button visitWebsiteButton { get { return rootVisualElement.Q<Button>(\"visitWebsiteButton\"); } }\n        private Button launchPackageManagerButton { get { return rootVisualElement.Q<Button>(\"launchPackageManagerButton\"); } }\n        private Toggle alwaysOpenInBrowserToggle { get { return rootVisualElement.Q<Toggle>(\"alwaysOpenInBrowserToggle\"); } }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetStore/Json.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n/*\n * Simple recursive descending JSON parser and\n * JSON string builder.\n *\n * Jonas Drewsen - (C) Unity3d.com - 2010\n *\n * JSONParser parser = new JSONParser(\" { \\\"hello\\\" : 42.3 } \");\n * JSONValue value = parser.Parse();\n *\n * bool is_it_float = value.isFloat();\n * float the_float = value.asFloat();\n *\n */\n\nusing System.Collections.Generic;\nusing System;\nusing System.Globalization;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    /*\n     * JSON value structure\n     *\n     * Example:\n     * JSONValue v = JSONValue.NewDict();\n     * v[\"hello\"] = JSONValue.NewString(\"world\");\n     * asset(v[\"hello\"].AsString() == \"world\");\n     *\n     */\n    internal struct JSONValue\n    {\n        public JSONValue(object o)\n        {\n            data = o;\n        }\n\n        public bool IsString() { return data is string; }\n        public bool IsFloat() { return data is float; }\n        public bool IsList() { return data is List<JSONValue>; }\n        public bool IsDict() { return data is Dictionary<string, JSONValue>; }\n        public bool IsBool() { return data is bool; }\n        public bool IsNull() { return data == null; }\n\n        public static implicit operator JSONValue(string s)\n        {\n            return new JSONValue(s);\n        }\n\n        public static implicit operator JSONValue(float s)\n        {\n            return new JSONValue(s);\n        }\n\n        public static implicit operator JSONValue(bool s)\n        {\n            return new JSONValue(s);\n        }\n\n        public static implicit operator JSONValue(int s)\n        {\n            return new JSONValue((float)s);\n        }\n\n        public object AsObject()\n        {\n            return data;\n        }\n\n        public string AsString(bool nothrow)\n        {\n            if (data is string)\n                return (string)data;\n            if (!nothrow)\n                throw new JSONTypeException(\"Tried to read non-string json value as string\");\n            return \"\";\n        }\n\n        public string AsString()\n        {\n            return AsString(false);\n        }\n\n        public float AsFloat(bool nothrow)\n        {\n            if (data is float)\n                return (float)data;\n            if (!nothrow)\n                throw new JSONTypeException(\"Tried to read non-float json value as float\");\n            return 0.0f;\n        }\n\n        public float AsFloat()\n        {\n            return AsFloat(false);\n        }\n\n        public bool AsBool(bool nothrow)\n        {\n            if (data is bool)\n                return (bool)data;\n            if (!nothrow)\n                throw new JSONTypeException(\"Tried to read non-bool json value as bool\");\n            return false;\n        }\n\n        public bool AsBool()\n        {\n            return AsBool(false);\n        }\n\n        public List<JSONValue> AsList(bool nothrow)\n        {\n            if (data is List<JSONValue>)\n                return (List<JSONValue>)data;\n            if (!nothrow)\n                throw new JSONTypeException(\"Tried to read \" + data.GetType().Name + \" json value as list\");\n            return null;\n        }\n\n        public List<JSONValue> AsList()\n        {\n            return AsList(false);\n        }\n\n        public Dictionary<string, JSONValue> AsDict(bool nothrow)\n        {\n            if (data is Dictionary<string, JSONValue>)\n                return (Dictionary<string, JSONValue>)data;\n            if (!nothrow)\n                throw new JSONTypeException(\"Tried to read non-dictionary json value as dictionary\");\n            return null;\n        }\n\n        public Dictionary<string, JSONValue> AsDict()\n        {\n            return AsDict(false);\n        }\n\n        public static JSONValue NewString(string val)\n        {\n            return new JSONValue(val);\n        }\n\n        public static JSONValue NewFloat(float val)\n        {\n            return new JSONValue(val);\n        }\n\n        public static JSONValue NewDict()\n        {\n            return new JSONValue(new Dictionary<string, JSONValue>());\n        }\n\n        public static JSONValue NewList()\n        {\n            return new JSONValue(new List<JSONValue>());\n        }\n\n        public static JSONValue NewBool(bool val)\n        {\n            return new JSONValue(val);\n        }\n\n        public static JSONValue NewNull()\n        {\n            return new JSONValue(null);\n        }\n\n        public JSONValue this[string index]\n        {\n            get\n            {\n                Dictionary<string, JSONValue> dict = AsDict();\n                return dict[index];\n            }\n            set\n            {\n                if (data == null)\n                    data = new Dictionary<string, JSONValue>();\n                Dictionary<string, JSONValue> dict = AsDict();\n                dict[index] = value;\n            }\n        }\n\n        public bool ContainsKey(string index)\n        {\n            if (!IsDict())\n                return false;\n            return AsDict().ContainsKey(index);\n        }\n\n        // Get the specified field in a dict or null json value if\n        // no such field exists. The key can point to a nested structure\n        // e.g. key1.key2 in  { key1 : { key2 : 32 } }\n        public JSONValue Get(string key)\n        {\n            if (!IsDict())\n                return new JSONValue(null);\n            JSONValue value = this;\n            foreach (string part in key.Split('.'))\n            {\n                if (!value.ContainsKey(part))\n                    return new JSONValue(null);\n                value = value[part];\n            }\n            return value;\n        }\n\n        // Convenience dict value setting\n        public void Set(string key, string value)\n        {\n            if (value == null)\n            {\n                this[key] = NewNull();\n                return;\n            }\n            this[key] = NewString(value);\n        }\n\n        // Convenience dict value setting\n        public void Set(string key, float value)\n        {\n            this[key] = NewFloat(value);\n        }\n\n        // Convenience dict value setting\n        public void Set(string key, bool value)\n        {\n            this[key] = NewBool(value);\n        }\n\n        // Convenience list value add\n        public void Add(string value)\n        {\n            List<JSONValue> list = AsList();\n            if (value == null)\n            {\n                list.Add(NewNull());\n                return;\n            }\n            list.Add(NewString(value));\n        }\n\n        // Convenience list value add\n        public void Add(float value)\n        {\n            List<JSONValue> list = AsList();\n            list.Add(NewFloat(value));\n        }\n\n        // Convenience list value add\n        public void Add(bool value)\n        {\n            List<JSONValue> list = AsList();\n            list.Add(NewBool(value));\n        }\n\n        /*\n         * Serialize a JSON value to string.\n         * This will recurse down through dicts and list type JSONValues.\n         */\n        public override string ToString()\n        {\n            if (IsString())\n            {\n                return \"\\\"\" + EncodeString(AsString()) + \"\\\"\";\n            }\n            else if (IsFloat())\n            {\n                return AsFloat().ToString();\n            }\n            else if (IsList())\n            {\n                string res = \"[\";\n                string delim = \"\";\n                foreach (JSONValue i in AsList())\n                {\n                    res += delim + i;\n                    delim = \", \";\n                }\n                return res + \"]\";\n            }\n            else if (IsDict())\n            {\n                string res = \"{\";\n                string delim = \"\";\n                foreach (KeyValuePair<string, JSONValue> kv in AsDict())\n                {\n                    res += delim + '\"' + EncodeString(kv.Key) + \"\\\" : \" + kv.Value;\n                    delim = \", \";\n                }\n                return res + \"}\";\n            }\n            else if (IsBool())\n            {\n                return AsBool() ? \"true\" : \"false\";\n            }\n            else if (IsNull())\n            {\n                return \"null\";\n            }\n            else\n            {\n                throw new JSONTypeException(\"Cannot serialize json value of unknown type\");\n            }\n        }\n\n        // Encode a string into a json string\n        private static string EncodeString(string str)\n        {\n            str = str.Replace(\"\\\"\", \"\\\\\\\"\");\n            str = str.Replace(\"\\\\\", \"\\\\\\\\\");\n            str = str.Replace(\"\\b\", \"\\\\b\");\n            str = str.Replace(\"\\f\", \"\\\\f\");\n            str = str.Replace(\"\\n\", \"\\\\n\");\n            str = str.Replace(\"\\r\", \"\\\\r\");\n            str = str.Replace(\"\\t\", \"\\\\t\");\n            // We do not use \\uXXXX specifier but direct unicode in the string.\n            return str;\n        }\n\n        object data;\n    }\n\n    class JSONParseException : Exception\n    {\n        public JSONParseException(string msg) : base(msg)\n        {\n        }\n    }\n\n    class JSONTypeException : Exception\n    {\n        public JSONTypeException(string msg) : base(msg)\n        {\n        }\n    }\n\n    /*\n     * Top down recursive JSON parser\n     *\n     * Example:\n     * string json = \"{ \\\"hello\\\" : \\\"world\\\", \\\"age\\\" : 100000, \"sister\" : null }\";\n     * JSONValue val = JSONParser.SimpleParse(json);\n     * asset( val[\"hello\"].AsString() == \"world\" );\n     *\n     */\n    class JSONParser\n    {\n        private string json;\n        private int line;\n        private int linechar;\n        private int len;\n        private int idx;\n        private int pctParsed;\n        private char cur;\n\n        public static JSONValue SimpleParse(string jsondata)\n        {\n            var parser = new JSONParser(jsondata);\n            try\n            {\n                return parser.Parse();\n            }\n            catch (JSONParseException ex)\n            {\n                Debug.LogError(ex.Message);\n            }\n            return new JSONValue(null);\n        }\n\n        /*\n         * Setup a parse to be ready for parsing the given string\n         */\n        public JSONParser(string jsondata)\n        {\n            // TODO: fix that parser needs trailing spaces;\n            json = jsondata + \"    \";\n            line = 1;\n            linechar = 1;\n            len = json.Length;\n            idx = 0;\n            pctParsed = 0;\n        }\n\n        /*\n         * Parse the entire json data string into a JSONValue structure hierarchy\n         */\n        public JSONValue Parse()\n        {\n            cur = json[idx];\n            return ParseValue();\n        }\n\n        private char Next()\n        {\n            if (cur == '\\n')\n            {\n                line++;\n                linechar = 0;\n            }\n            idx++;\n            if (idx >= len)\n                throw new JSONParseException(\"End of json while parsing at \" + PosMsg());\n\n            linechar++;\n\n            int newPct = (int)((float)idx * 100f / (float)len);\n            if (newPct != pctParsed)\n            {\n                pctParsed = newPct;\n            }\n            cur = json[idx];\n            return cur;\n        }\n\n        private void SkipWs()\n        {\n            string ws = \" \\n\\t\\r\";\n            while (ws.IndexOf(cur) != -1) Next();\n        }\n\n        private string PosMsg()\n        {\n            return \"line \" + line + \", column \" + linechar;\n        }\n\n        private JSONValue ParseValue()\n        {\n            // Skip spaces\n            SkipWs();\n\n            switch (cur)\n            {\n                case '[':\n                    return ParseArray();\n                case '{':\n                    return ParseDict();\n                case '\"':\n                    return ParseString();\n                case '-':\n                case '0':\n                case '1':\n                case '2':\n                case '3':\n                case '4':\n                case '5':\n                case '6':\n                case '7':\n                case '8':\n                case '9':\n                    return ParseNumber();\n                case 't':\n                case 'f':\n                case 'n':\n                    return ParseConstant();\n                default:\n                    throw new JSONParseException(\"Cannot parse json value starting with '\" + json.Substring(idx, 5) + \"' at \" + PosMsg());\n            }\n        }\n\n        private JSONValue ParseArray()\n        {\n            Next();\n            SkipWs();\n            List<JSONValue> arr = new List<JSONValue>();\n            while (cur != ']')\n            {\n                arr.Add(ParseValue());\n                SkipWs();\n                if (cur == ',')\n                {\n                    Next();\n                    SkipWs();\n                }\n            }\n            Next();\n            return new JSONValue(arr);\n        }\n\n        private JSONValue ParseDict()\n        {\n            Next();\n            SkipWs();\n            Dictionary<string, JSONValue> dict = new Dictionary<string, JSONValue>();\n            while (cur != '}')\n            {\n                JSONValue key = ParseValue();\n                if (!key.IsString())\n                    throw new JSONParseException(\"Key not string type at \" + PosMsg());\n                SkipWs();\n                if (cur != ':')\n                    throw new JSONParseException(\"Missing dict entry delimiter ':' at \" + PosMsg());\n                Next();\n                dict.Add(key.AsString(), ParseValue());\n                SkipWs();\n                if (cur == ',')\n                {\n                    Next();\n                    SkipWs();\n                }\n            }\n            Next();\n            return new JSONValue(dict);\n        }\n\n        static char[] endcodes = new char[] { '\\\\', '\"' };\n\n        private JSONValue ParseString()\n        {\n            string res = \"\";\n\n            Next();\n\n            while (idx < len)\n            {\n                int endidx = json.IndexOfAny(endcodes, idx);\n                if (endidx < 0)\n                    throw new JSONParseException(\"missing '\\\"' to end string at \" + PosMsg());\n\n                res += json.Substring(idx, endidx - idx);\n\n                if (json[endidx] == '\"')\n                {\n                    cur = json[endidx];\n                    idx = endidx;\n                    break;\n                }\n\n                endidx++; // get escape code\n                if (endidx >= len)\n                    throw new JSONParseException(\"End of json while parsing while parsing string at \" + PosMsg());\n\n                // char at endidx is \\\n                char ncur = json[endidx];\n                switch (ncur)\n                {\n                    case '\"':\n                        goto case '/';\n                    case '\\\\':\n                        goto case '/';\n                    case '/':\n                        res += ncur;\n                        break;\n                    case 'b':\n                        res += '\\b';\n                        break;\n                    case 'f':\n                        res += '\\f';\n                        break;\n                    case 'n':\n                        res += '\\n';\n                        break;\n                    case 'r':\n                        res += '\\r';\n                        break;\n                    case 't':\n                        res += '\\t';\n                        break;\n                    case 'u':\n                        // Unicode char specified by 4 hex digits\n                        string digit = \"\";\n                        if (endidx + 4 >= len)\n                            throw new JSONParseException(\"End of json while parsing while parsing unicode char near \" + PosMsg());\n                        digit += json[endidx + 1];\n                        digit += json[endidx + 2];\n                        digit += json[endidx + 3];\n                        digit += json[endidx + 4];\n                        try\n                        {\n                            int d = System.Int32.Parse(digit, System.Globalization.NumberStyles.AllowHexSpecifier);\n                            res += (char)d;\n                        }\n                        catch (FormatException)\n                        {\n                            throw new JSONParseException(\"Invalid unicode escape char near \" + PosMsg());\n                        }\n                        endidx += 4;\n                        break;\n                    default:\n                        throw new JSONParseException(\"Invalid escape char '\" + ncur + \"' near \" + PosMsg());\n                }\n                idx = endidx + 1;\n            }\n            if (idx >= len)\n                throw new JSONParseException(\"End of json while parsing while parsing string near \" + PosMsg());\n\n            cur = json[idx];\n\n            Next();\n            return new JSONValue(res);\n        }\n\n        private JSONValue ParseNumber()\n        {\n            string resstr = \"\";\n\n            if (cur == '-')\n            {\n                resstr = \"-\";\n                Next();\n            }\n\n            while (cur >= '0' && cur <= '9')\n            {\n                resstr += cur;\n                Next();\n            }\n            if (cur == '.')\n            {\n                Next();\n                resstr += '.';\n                while (cur >= '0' && cur <= '9')\n                {\n                    resstr += cur;\n                    Next();\n                }\n            }\n\n            if (cur == 'e' || cur == 'E')\n            {\n                resstr += \"e\";\n                Next();\n                if (cur != '-' && cur != '+')\n                {\n                    // throw new JSONParseException(\"Missing - or + in 'e' potent specifier at \" + PosMsg());\n                    resstr += cur;\n                    Next();\n                }\n                while (cur >= '0' && cur <= '9')\n                {\n                    resstr += cur;\n                    Next();\n                }\n            }\n\n            try\n            {\n                float f = System.Convert.ToSingle(resstr, CultureInfo.InvariantCulture);\n                return new JSONValue(f);\n            }\n            catch (Exception)\n            {\n                throw new JSONParseException(\"Cannot convert string to float : '\" + resstr + \"' at \" + PosMsg());\n            }\n        }\n\n        private JSONValue ParseConstant()\n        {\n            string c = \"\";\n            c = \"\" + cur + Next() + Next() + Next();\n            Next();\n            if (c == \"true\")\n            {\n                return new JSONValue(true);\n            }\n            else if (c == \"fals\")\n            {\n                if (cur == 'e')\n                {\n                    Next();\n                    return new JSONValue(false);\n                }\n            }\n            else if (c == \"null\")\n            {\n                return new JSONValue(null);\n            }\n            throw new JSONParseException(\"Invalid token at \" + PosMsg());\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetStore.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\n\nnamespace UnityEditorInternal\n{\n    // Keep internal and undocumented until we expose more functionality\n    //*undocumented*\n    public sealed class AssetStore\n    {\n        //*undocumented*\n        public static void Open(string assetStoreURL)\n        {\n            if (assetStoreURL != \"\")\n                AssetStoreWindow.OpenURL(assetStoreURL);\n            else\n                AssetStoreWindow.Init();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetStoreCachePathManager.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditorInternal\n{\n    [NativeHeader(\"Editor/Src/AssetStore/AssetStoreCachePathManager.h\")]\n    internal partial class AssetStoreCachePathManager\n    {\n        [FreeFunction(\"AssetStoreCachePathManager::GetDefaultConfig\")]\n        public static extern CachePathConfig GetDefaultConfig();\n\n        [FreeFunction(\"AssetStoreCachePathManager::GetConfig\")]\n        public static extern CachePathConfig GetConfig();\n\n        [FreeFunction(\"AssetStoreCachePathManager::SetConfig\")]\n        public static extern ConfigStatus SetConfig(string newPath);\n\n        [FreeFunction(\"AssetStoreCachePathManager::ResetConfig\")]\n        public static extern ConfigStatus ResetConfig();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetStoreCachePathManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEditor.PackageManager;\nusing System.Runtime.InteropServices;\nusing RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute;\n\nnamespace UnityEditorInternal\n{\n    internal partial class AssetStoreCachePathManager\n    {\n        public enum ConfigStatus\n        {\n            Success = 0,\n            InvalidPath,\n            ReadOnly,\n            EnvironmentOverride,\n            Default,\n            Failed\n        };\n\n        [Serializable]\n        [StructLayout(LayoutKind.Sequential)]\n        [RequiredByNativeCode]\n        [NativeAsStruct]\n        internal class CachePathConfig\n        {\n            [SerializeField]\n            [NativeName(\"path\")]\n            private string m_Path = \"\";\n\n            [SerializeField]\n            [NativeName(\"source\")]\n            private ConfigSource m_Source = ConfigSource.Unknown;\n\n            [SerializeField]\n            [NativeName(\"status\")]\n            private ConfigStatus m_Status = ConfigStatus.Success;\n\n            public string path => m_Path;\n\n            public ConfigSource source => m_Source;\n\n            public ConfigStatus status => m_Status;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetStoreContext.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Mono/AssetStore.bindings.h\")]\n    [StaticAccessor(\"AssetStoreScriptBindings\", StaticAccessorType.DoubleColon)]\n    internal partial class AssetStoreContext\n    {\n        extern public static void SessionSetString(string key, string value);\n        extern public static string SessionGetString(string key);\n        extern public static void SessionRemoveString(string key);\n        extern public static bool SessionHasString(string key);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetStoreToolUtils.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing Object = UnityEngine.Object;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditorInternal\n{\n    [NativeHeader(\"Editor/Mono/AssetStore.bindings.h\")]\n    [StaticAccessor(\"AssetStoreScriptBindings\", StaticAccessorType.DoubleColon)]\n    public sealed partial class AssetStoreToolUtils\n    {\n        [System.Obsolete(\"BuildAssetStoreAssetBundle has been made obsolete. Please use BuildPipeline.BuildAssetBundles() or Addressables.\", true)]\n        extern public static bool BuildAssetStoreAssetBundle(Object targetObject, string targetPath);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetStoreUtils.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Mono/AssetStore.bindings.h\")]\n    [StaticAccessor(\"AssetStoreScriptBindings\", StaticAccessorType.DoubleColon)]\n    internal class AssetStoreUtils\n    {\n        private const string kAssetStoreUrl = \"https://shawarma.unity3d.com\";\n        public delegate void DownloadDoneCallback(string package_id, string message, int bytes, int total);\n\n        extern public static string BuildBaseDownloadPath(string publisher, string category);\n        extern public static string BuildFinalDownloadPath(string baseDir, string packageName);\n\n        [NativeThrows]\n        extern public static void Download(string id, string url, string[] destination, string key, string jsonData, bool resumeOK, DownloadDoneCallback doneCallback = null);\n        [NativeThrows]\n        extern public static string CheckDownload(string id, string url, string[] destination, string key);\n        [NativeThrows]\n        extern public static bool AbortDownload(string[] destination);\n        extern public static void RegisterDownloadDelegate([NotNull] ScriptableObject d);\n        extern public static void UnRegisterDownloadDelegate([NotNull] ScriptableObject d);\n        extern public static string GetLoaderPath();\n        extern public static void UpdatePreloading();\n\n        public static string GetAssetStoreUrl()\n        {\n            return kAssetStoreUrl;\n        }\n\n        public static string GetAssetStoreSearchUrl()\n        {\n            return GetAssetStoreUrl().Replace(\"https\", \"http\"); // Use use http (and not https) when searching because its faster\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AssetsMenuUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    internal enum ScriptTemplate\n    {\n        CSharp_NewBehaviourScript = 0,\n        CSharp_NewPlayableBehaviour,\n        Shader_NewSurfaceShader,\n        CSharp_NewSceneTemplatePipelineScript,\n        CSharp_NewPlayableAsset,\n        CSharp_NewScriptableObjectScript,\n        Shader_NewUnlitShader,\n        AsmDef_NewEditModeTestAssembly,\n        AsmDef_NewTestAssembly,\n        AsmDef_NewAssembly,\n        AsmRef_NewAssemblyReference,\n        CSharp_NewEmptyScript,\n        CSharp_NewTestScript,\n        Shader_NewImageEffectShader,\n        Shader_NewComputeShader,\n        Shader_NewRayTracingShader,\n        CSharp_NewStateMachineBehaviourScript,\n        CSharp_NewSubStateMachineBehaviourScript,\n        Count\n    }\n\n    [NativeHeader(\"Editor/Src/Commands/AssetsMenuUtility.h\")]\n    internal static class AssetsMenuUtility\n    {\n        public static extern bool SelectionHasImmutable();\n        public static string GetScriptTemplatePath(ScriptTemplate template)\n        {\n            return GetScriptTemplatePath((int)template);\n        }\n\n        private static extern string GetScriptTemplatePath(int index);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AsyncHTTPClient.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Mono/AsyncHTTPClient.bindings.h\")]\n    internal partial class AsyncHTTPClient\n    {\n        private delegate void RequestProgressCallback(AsyncHTTPClient.State status, int downloaded, int totalSize);\n        private delegate void RequestDoneCallback(AsyncHTTPClient.State status, int httpStatus);\n\n        private static extern IntPtr SubmitClientRequest(string tag, string url, string[] headers, string method, string data, RequestDoneCallback doneDelegate, RequestProgressCallback progressDelegate = null);\n\n        private static extern byte[] GetBytesByHandle(IntPtr handle);\n\n        private static extern Texture2D GetTextureByHandle(IntPtr handle);\n\n        private static extern string[] GetHeadersByHandle(IntPtr handle);\n\n        public static extern void AbortByTag(string tag);\n\n        private static extern void AbortByHandle(IntPtr handle);\n\n        [FreeFunction]\n        public static extern void CurlRequestCheck();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AsyncHTTPClient.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Net;\nusing System.IO;\nusing System.Text;\nusing System.Threading;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing System.Linq;\n\nnamespace UnityEditor\n{\n    internal interface IAsyncHTTPClient\n    {\n        string text { get; }\n        byte[] bytes { get; }\n        Texture2D texture { get; }\n        AsyncHTTPClient.State state { get; }\n        int responseCode { get; }\n        string tag { get; set; }\n        Dictionary<string, string> header { get; set; }\n\n        Dictionary<string, string> responseHeader { get; }\n\n        string postData { set; }\n        Dictionary<string, string> postDictionary { set; }\n\n        AsyncHTTPClient.DoneCallback doneCallback { get; set; }\n\n        string url { get; }\n\n        void Abort();\n        bool IsAborted();\n        bool IsDone();\n        bool IsSuccess();\n        void Begin();\n    }\n\n    /*\n     * A HTTP job for performing HTTP requests in a thread\n     * This class is primarily used by the Server class.\n     */\n    internal partial class AsyncHTTPClient : IAsyncHTTPClient\n    {\n        internal enum State\n        {\n            INIT,\n            CONNECTING,\n            CONNECTED,\n            UPLOADING,\n            DOWNLOADING,\n            CONFIRMING,\n            DONE_OK,\n            DONE_FAILED,\n            ABORTED,\n            TIMEOUT\n        }\n        private IntPtr m_Handle;\n        public delegate void DoneCallback(IAsyncHTTPClient client);\n        public delegate void StatusCallback(State status, int bytesDone, int bytesTotal);\n\n        public StatusCallback statusCallback;\n        public DoneCallback doneCallback { get; set; }\n\n        string m_ToUrl;\n        string m_FromData;\n        string m_Method;\n\n        public string url\n        {\n            get {  return m_ToUrl; }\n        }\n\n        public string text\n        {\n            get\n            {\n                System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();\n                byte[] b = bytes;\n                if (b == null) return null;\n                return encoding.GetString(b);\n            }\n        }\n\n        public byte[] bytes\n        {\n            get\n            {\n                return GetBytesByHandle(m_Handle);\n            }\n        }\n        public Texture2D texture\n        {\n            get\n            {\n                return GetTextureByHandle(m_Handle);\n            }\n        }\n\n        public State state { get; private set; }\n        public int responseCode { get; private set; }\n        public string tag { get; set; }\n\n        public Dictionary<string, string> responseHeader\n        {\n            get\n            {\n                string[] headerFlattened = GetHeadersByHandle(m_Handle);\n                Dictionary<string, string> ret = new Dictionary<string, string>();\n                foreach (var curr in headerFlattened)\n                {\n                    if (string.IsNullOrEmpty(curr))\n                        continue;\n                    string[] line = curr.Split(new string[] { \": \" }, StringSplitOptions.None);\n                    if (line.Length > 1)\n                        ret.Add(line[0], string.Concat(line.Skip(1).ToArray()));\n                    else\n                        ret.Add(curr, \"\");\n                }\n                return ret;\n            }\n        }\n\n        public Dictionary<string, string> header { get; set; }\n\n        /* GET request\n         *\n         */\n        public AsyncHTTPClient(string _toUrl)\n        {\n            m_ToUrl = _toUrl;\n            m_FromData = null;\n            m_Method = \"\";\n            state = State.INIT;\n            header = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);\n            m_Handle = (IntPtr)0;\n            tag = \"\";\n            statusCallback = null;\n        }\n\n        /* Any method request\n         *\n         */\n        public AsyncHTTPClient(string _toUrl, string _method)\n        {\n            m_ToUrl = _toUrl;\n            m_FromData = null;\n            m_Method = _method;\n            state = State.INIT;\n            header = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);\n            m_Handle = (IntPtr)0;\n            tag = \"\";\n            statusCallback = null;\n        }\n\n        /* If this job has been set as a POST job this will overwrite the\n         * data to be posted. The job must not have been started yet\n         * ie. Begin() should not have been called.\n         */\n        public string postData\n        {\n            set\n            {\n                m_FromData = value;\n                if (m_Method == \"\")\n                    m_Method = \"POST\";\n                if (!header.ContainsKey(\"Content-Type\"))\n                    header[\"Content-Type\"] = \"application/x-www-form-urlencoded\";\n            }\n        }\n\n        /*\n         * POST request for uploading url application/x-www-form-urlencoded dictionary.\n         * The encoding normally allows for duplicate keys, but this method is restricted\n         * to unique keys.\n         */\n        public Dictionary<string, string> postDictionary\n        {\n            set\n            {\n                postData = string.Join(\"&\", value.Select(kv => EscapeLong(kv.Key) + \"=\" + EscapeLong(kv.Value)).ToArray());\n            }\n        }\n\n        /*\n         *\n         */\n        public void Abort()\n        {\n            state = State.ABORTED;\n\n            AbortByHandle(m_Handle);\n        }\n\n        public bool IsAborted()\n        {\n            return state == State.ABORTED;\n        }\n\n        public bool IsDone()\n        {\n            return IsDone(state);\n        }\n\n        public static bool IsDone(State state)\n        {\n            switch (state)\n            {\n                case State.DONE_OK:\n                case State.DONE_FAILED:\n                case State.ABORTED:\n                case State.TIMEOUT:\n                    return true;\n                default: return false;\n            }\n        }\n\n        public bool IsSuccess()\n        {\n            return state == State.DONE_OK;\n        }\n\n        public static bool IsSuccess(State state)\n        {\n            return state == State.DONE_OK;\n        }\n\n        public void Begin()\n        {\n            if (IsAborted())\n            {\n                state = State.ABORTED;\n                return;\n            }\n            if (m_Method == \"\")\n                m_Method = \"GET\";\n\n            string[] headerFlattened = header.Select(kv => string.Format(\"{0}: {1}\", kv.Key, kv.Value)).ToArray();\n\n            m_Handle = SubmitClientRequest(tag, m_ToUrl, headerFlattened, m_Method, m_FromData, Done, Progress);\n        }\n\n        private void Done(State status, int i_ResponseCode)\n        {\n            state = status;\n            responseCode = i_ResponseCode;\n\n            if (doneCallback != null)\n                doneCallback(this);\n\n            m_Handle = (IntPtr)0; // The CurlRequestMessage will be deallocated after this callback returns\n        }\n\n        private void Progress(State status, int bytesDone, int bytesTotal)\n        {\n            state = status;\n            if (statusCallback != null)\n                statusCallback(status, bytesDone, bytesTotal);\n        }\n\n        /*\n         * The normal escape function does not support strings longer than 32766 characters\n         */\n        private string EscapeLong(string v)\n        {\n            StringBuilder q = new StringBuilder();\n            const int c_ChunkLength = 32766;\n            for (int i = 0; i < v.Length; i += c_ChunkLength)\n            {\n                q.Append(System.Uri.EscapeDataString(v.Substring(i, v.Length - i > c_ChunkLength ? c_ChunkLength : v.Length - i)));\n            }\n            return q.ToString();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AttributeHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing System;\nusing System.Collections;\nusing System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\nnamespace UnityEditor\n{\n    [RequiredByNativeCode]\n    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]\n    internal sealed partial class RequiredSignatureAttribute : Attribute {}\n\n    internal class AttributeHelper\n    {\n        [StructLayout(LayoutKind.Sequential)]\n        struct MonoGizmoMethod\n        {\n            public MethodInfo drawGizmo;\n            public Type       drawnType;\n            public int        options;\n        }\n\n        [RequiredByNativeCode]\n        static MonoGizmoMethod[] ExtractGizmos(Assembly assembly)\n        {\n            var commands = new List<MonoGizmoMethod>();\n\n            foreach (var mi in EditorAssemblies.GetAllMethodsWithAttribute<DrawGizmo>(BindingFlags.Static).Where(m => m.DeclaringType.Assembly == assembly))\n            {\n                var attrs = mi.GetCustomAttributes(typeof(DrawGizmo), false).Cast<DrawGizmo>();\n                foreach (var gizmoAttr in attrs)\n                {\n                    var parameters = mi.GetParameters();\n                    if (parameters.Length != 2)\n                    {\n                        Debug.LogWarningFormat(\n                            \"Method {0}.{1} is marked with the DrawGizmo attribute but does not take parameters (ComponentType, GizmoType) so will be ignored.\",\n                            mi.DeclaringType?.FullName, mi.Name\n                        );\n                        continue;\n                    }\n                    if (mi.DeclaringType != null && mi.DeclaringType.IsGenericTypeDefinition)\n                    {\n                        Debug.LogWarningFormat(\n                            \"Method {0}.{1} is marked with the DrawGizmo attribute but is defined on a generic type definition, so will be ignored.\",\n                            mi.DeclaringType.FullName, mi.Name\n                        );\n                        continue;\n                    }\n\n                    Type targetType;\n                    if (gizmoAttr.drawnType == null)\n                        targetType = parameters[0].ParameterType;\n                    else if (parameters[0].ParameterType.IsAssignableFrom(gizmoAttr.drawnType))\n                        targetType = gizmoAttr.drawnType;\n                    else\n                    {\n                        Debug.LogWarningFormat(\n                            \"Method {0}.{1} is marked with the DrawGizmo attribute but the component type it applies to could not be determined.\",\n                            mi.DeclaringType?.FullName, mi.Name\n                        );\n                        continue;\n                    }\n\n                    if (parameters[1].ParameterType != typeof(GizmoType) &&\n                        parameters[1].ParameterType != typeof(int))\n                    {\n                        Debug.LogWarningFormat(\n                            \"Method {0}.{1} is marked with the DrawGizmo attribute but does not take a second parameter of type GizmoType so will be ignored.\",\n                            mi.DeclaringType?.FullName, mi.Name\n                        );\n                        continue;\n                    }\n\n                    if (targetType.IsInterface)\n                    {\n                        var types = TypeCache.GetTypesDerivedFrom(targetType);\n                        foreach (var type in types)\n                        {\n                            //Limit the types to the classes that have the interface and not it's children\n                            if (type.BaseType != null && type.BaseType.IsAssignableFrom(targetType))\n                                continue;\n\n                            commands.Add(new MonoGizmoMethod\n                            {\n                                drawnType = type,\n                                drawGizmo = mi,\n                                options = (int)gizmoAttr.drawOptions,\n                            });\n                        }\n                    }\n                    else\n                    {\n                        commands.Add(new MonoGizmoMethod\n                        {\n                            drawnType = targetType,\n                            drawGizmo = mi,\n                            options = (int)gizmoAttr.drawOptions,\n                        });\n                    }\n                }\n            }\n            return commands.ToArray();\n        }\n\n        [RequiredByNativeCode]\n        static object GetComponentMenuName(Type type)\n        {\n            var attrs = type.GetCustomAttributes(typeof(AddComponentMenu), false);\n            if (attrs.Length > 0)\n            {\n                var menu = (AddComponentMenu)attrs[0];\n                return menu.componentMenu;\n            }\n            return null;\n        }\n\n        [RequiredByNativeCode]\n        static int GetComponentMenuOrdering(Type type)\n        {\n            var attrs = type.GetCustomAttributes(typeof(AddComponentMenu), false);\n            if (attrs.Length > 0)\n            {\n                var menu = (AddComponentMenu)attrs[0];\n                return menu.componentOrder;\n            }\n            return 0;\n        }\n\n        [StructLayout(LayoutKind.Sequential)]\n        struct MonoCreateAssetItem\n        {\n            public string menuItem;\n            public string fileName;\n            public int    order;\n            public Type   type;\n        }\n\n        [RequiredByNativeCode]\n        static MonoCreateAssetItem[] ExtractCreateAssetMenuItems()\n        {\n            var result = new List<MonoCreateAssetItem>();\n\n            foreach (var type in TypeCache.GetTypesWithAttribute<CreateAssetMenuAttribute>())\n            {\n                var attr = type.GetCustomAttributes(typeof(CreateAssetMenuAttribute), false).FirstOrDefault() as CreateAssetMenuAttribute;\n                if (attr == null)\n                    continue;\n\n                if (!type.IsSubclassOf(typeof(ScriptableObject)))\n                {\n                    Debug.LogWarningFormat(\"CreateAssetMenu attribute on {0} will be ignored as {0} is not derived from ScriptableObject.\", type.FullName);\n                    continue;\n                }\n\n                string menuItemName = (string.IsNullOrEmpty(attr.menuName)) ? ObjectNames.NicifyVariableName(type.Name) : attr.menuName;\n                string fileName = (string.IsNullOrEmpty(attr.fileName)) ? (\"New \" + ObjectNames.NicifyVariableName(type.Name) + \".asset\") : attr.fileName;\n                if (!System.IO.Path.HasExtension(fileName))\n                    fileName = fileName + \".asset\";\n\n                // trim the trailing space from the menu name:\n                // 1. visually it is hard to differentialte menu names with or without spaces.\n                // 2. when asset menu is searched, it will search the trimmed menu name, so it will create a edge case where a menu name with space could not be found after creation.\n                menuItemName = menuItemName.TrimEnd();\n\n                var item = new MonoCreateAssetItem\n                {\n                    menuItem = menuItemName,\n                    fileName = fileName,\n                    order = attr.order,\n                    type = type\n                };\n                result.Add(item);\n            }\n\n            return result.ToArray();\n        }\n\n        internal static bool GameObjectContainsAttribute<T>(GameObject go) where T : Attribute\n        {\n            var behaviours = go.GetComponents(typeof(Component));\n            for (var index = 0; index < behaviours.Length; index++)\n            {\n                var behaviour = behaviours[index];\n                if (behaviour == null)\n                    continue;\n\n                var behaviourType = behaviour.GetType();\n                if (behaviourType.GetCustomAttributes(typeof(T), true).Length > 0)\n                    return true;\n            }\n            return false;\n        }\n\n        internal static IEnumerable<TReturnValue> CallMethodsWithAttribute<TReturnValue, TAttr>(params object[] arguments)\n            where TAttr : Attribute\n        {\n            foreach (var method in EditorAssemblies.GetAllMethodsWithAttribute<TAttr>(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))\n                yield return (TReturnValue)method.Invoke(null, arguments);\n        }\n\n        private static bool AreSignaturesMatching(MethodInfo left, MethodInfo right)\n        {\n            if (left.IsStatic != right.IsStatic)\n                return false;\n            if (left.ReturnType != right.ReturnType)\n                return false;\n\n\n            ParameterInfo[] leftParams = left.GetParameters();\n            ParameterInfo[] rightParams = right.GetParameters();\n            if (leftParams.Length != rightParams.Length)\n                return false;\n            for (int i = 0; i < leftParams.Length; i++)\n            {\n                if (leftParams[i].ParameterType != rightParams[i].ParameterType)\n                    return false;\n            }\n\n            return true;\n        }\n\n        internal static string MethodToString(MethodInfo method)\n        {\n            return string.Format(\"{0}{1}\", method.IsStatic ? \"static \" : \"\", method);\n        }\n\n        internal static bool MethodMatchesAnyRequiredSignatureOfAttribute(MethodInfo method, Type attributeType)\n        {\n            List<MethodInfo> validSignatures = new List<MethodInfo>();\n            foreach (var signature in attributeType.GetMethods(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly))\n            {\n                var requiredSignatureAttributes = signature.GetCustomAttributes(typeof(RequiredSignatureAttribute), false);\n                if (requiredSignatureAttributes.Length > 0)\n                {\n                    if (AreSignaturesMatching(method, signature))\n                    {\n                        return true;\n                    }\n                    validSignatures.Add(signature);\n                }\n            }\n            if (validSignatures.Count == 0)\n                Debug.LogError(MethodToString(method) + \" has an invalid attribute : \" + attributeType + \". \" + attributeType +  \" must have at least one required signature declaration\");\n            else if (validSignatures.Count == 1)\n                Debug.LogError(MethodToString(method) + \" does not match \" + attributeType + \" expected signature.\\n Use \" + MethodToString(validSignatures[0]));\n            else\n                Debug.LogError(MethodToString(method) + \" does not match any of \" + attributeType + \" expected signatures.\\n Valid signatures are: \" + string.Join(\" , \", validSignatures.Select((a) => MethodToString(a)).ToArray()));\n            return false;\n        }\n\n        internal struct MethodWithAttribute\n        {\n            public MethodInfo info;\n            public Attribute attribute;\n        }\n\n        internal class MethodInfoSorter\n        {\n            internal MethodInfoSorter(List<MethodWithAttribute> methodsWithAttributes)\n            {\n                this.methodsWithAttributes = methodsWithAttributes;\n            }\n\n            public IEnumerable<MethodInfo> FilterAndSortOnAttribute<T>(Func<T, bool> filter, Func<T, IComparable> sorter) where T : Attribute\n            {\n                return methodsWithAttributes.Where(a => filter((T)a.attribute)).OrderBy(c => sorter((T)c.attribute)).Select(o => o.info);\n            }\n\n            public IEnumerable<MethodWithAttribute> methodsWithAttributes { get; }\n        }\n\n        static Dictionary<Type, MethodInfoSorter> s_DecoratedMethodsByAttrTypeCache = new Dictionary<Type, MethodInfoSorter>();\n        private const BindingFlags kAllStatic = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;\n\n        internal static MethodInfoSorter GetMethodsWithAttribute<T>(BindingFlags bindingFlags = kAllStatic) where T : Attribute\n        {\n            MethodInfoSorter result;\n            if (!s_DecoratedMethodsByAttrTypeCache.TryGetValue(typeof(T), out result))\n            {\n                var tmp = new List<MethodWithAttribute>();\n                foreach (var method in EditorAssemblies.GetAllMethodsWithAttribute<T>(bindingFlags))\n                {\n                    if (method.IsGenericMethod)\n                    {\n                        Debug.LogErrorFormat(\n                            \"{0} is a generic method. {1} cannot be applied to it.\", MethodToString(method), typeof(T)\n                        );\n                    }\n                    else\n                    {\n                        foreach (var attr in method.GetCustomAttributes(typeof(T), false))\n                        {\n                            if (MethodMatchesAnyRequiredSignatureOfAttribute(method, typeof(T)))\n                            {\n                                var methodWithAttribute = new MethodWithAttribute { info = method, attribute = (T)attr };\n                                tmp.Add(methodWithAttribute);\n                            }\n                        }\n                    }\n                }\n\n                result = new MethodInfoSorter(tmp);\n                s_DecoratedMethodsByAttrTypeCache[typeof(T)] = result;\n            }\n            return result;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Analytics/AudioAnalytics.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Analytics;\n\nnamespace UnityEditor.Audio.Analytics;\n\nstatic class AudioAnalytics\n{\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Analytics/AudioRandomContainerBuildAnalyticsEvent.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.Build;\nusing UnityEditor.Build.Reporting;\nusing UnityEngine;\nusing UnityEngine.Audio;\nusing UnityEngine.Analytics;\n\nnamespace UnityEditor.Audio.Analytics;\n\nclass AudioRandomContainerBuildAnalyticsEvent : IPostprocessBuildWithReport\n{\n    [AnalyticInfo(eventName: \"audioRandomContainerBuild\", vendorKey: \"unity.audio\", maxEventsPerHour: 60, maxNumberOfElements: 2)]\n    internal class AudioRandomAnalytic : IAnalytic\n    {\n        public AudioRandomAnalytic(string build_guid, int count)\n        {\n            this.build_guid = build_guid;\n            this.count = count;\n        }\n\n        [Serializable]\n        struct Payload : IAnalytic.IData\n        {\n            public string build_guid;\n            public int count;\n        }\n\n\n        public bool TryGatherData(out IAnalytic.IData data, out Exception error)\n        {\n            error = null;\n            data = new Payload\n            {\n                build_guid = build_guid,\n                count = count\n            };\n\n            return data != null;\n        }\n\n        private string build_guid;\n        private int count;\n    }\n\n\n    public int callbackOrder { get; }\n\n    public void OnPostprocessBuild(BuildReport report)\n    {\n        SendEvent(report);\n    }\n\n    static void SendEvent(BuildReport report)\n    {\n        if (!EditorAnalytics.enabled\n            || AudioSettings.unityAudioDisabled\n            || report == null\n            || report.packedAssets.Length == 0)\n        {\n            return;\n        }\n\n        var count = 0;\n\n        for (var i = 0; i < report.packedAssets.Length; ++i)\n        {\n            var infos = report.packedAssets[i].GetContents();\n\n            for (var j = 0; j < infos.Length; ++j)\n            {\n                if (infos[j].type == typeof(AudioRandomContainer))\n                {\n                    ++count;\n                }\n            }\n        }\n\n        EditorAnalytics.SendAnalytic(new AudioRandomAnalytic(report.summary.guid.ToString(), count));\n    }\n    \n   }\n"
  },
  {
    "path": "Editor/Mono/Audio/Analytics/AudioRandomContainerQuitAnalyticsEvent.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Analytics;\n\nnamespace UnityEditor.Audio.Analytics;\n\n[InitializeOnLoad]\nclass AudioRandomContainerQuitAnalyticsEvent\n{\n    [AnalyticInfo(eventName: \"audioRandomContainerQuit\", vendorKey: \"unity.audio\", maxEventsPerHour: 60, maxNumberOfElements: 1)]\n    internal class AudioRandomAnalytic : IAnalytic\n    {\n        public AudioRandomAnalytic(int count)\n        {\n            this.count = count;\n        }\n\n        [Serializable]\n        struct Payload : IAnalytic.IData\n        {\n            public int count;\n        }\n\n\n        public bool TryGatherData(out IAnalytic.IData data, out Exception error)\n        {\n            error = null;\n            data = new Payload\n            {\n                count = count\n            };\n\n            return data != null;\n        }\n\n        private int count;\n    }\n\n    static AudioRandomContainerQuitAnalyticsEvent()\n    {\n        EditorApplication.wantsToQuit += OnEditorApplicationWantsToQuit;\n    }\n\n    static bool OnEditorApplicationWantsToQuit()\n    {\n        SendEvent();\n        return true;\n    }\n\n    static void SendEvent()\n    {\n        if (!EditorAnalytics.enabled || AudioSettings.unityAudioDisabled)\n        {\n            return;\n        }\n\n        var assetPaths = AssetDatabase.FindAssets(\"t:AudioRandomContainer\");\n        EditorAnalytics.SendAnalytic(new AudioRandomAnalytic(assetPaths.Length));\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/AudioContainerListDragAndDropManipulator.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor;\n\nclass AudioContainerListDragAndDropManipulator : PointerManipulator\n{\n    internal delegate void AddAudioClipsDelegate(List<AudioClip> audioClips);\n\n    internal AddAudioClipsDelegate addAudioClipsDelegate;\n\n    public AudioContainerListDragAndDropManipulator(VisualElement root)\n    {\n        target = root.Q<VisualElement>(\"audio-clips-list-view\");\n    }\n\n    protected override void RegisterCallbacksOnTarget()\n    {\n        target.RegisterCallback<DragUpdatedEvent>(OnDragUpdate);\n        target.RegisterCallback<DragPerformEvent>(OnDragPerform);\n    }\n\n    protected override void UnregisterCallbacksFromTarget()\n    {\n        target?.UnregisterCallback<DragUpdatedEvent>(OnDragUpdate);\n        target?.UnregisterCallback<DragPerformEvent>(OnDragPerform);\n    }\n\n    static void OnDragUpdate(DragUpdatedEvent _)\n    {\n        DragAndDrop.visualMode = DragAndDropVisualMode.Generic;\n    }\n\n    void OnDragPerform(DragPerformEvent evt)\n    {\n        var audioClips = new List<AudioClip>();\n\n        foreach (var path in DragAndDrop.paths)\n        {\n            var audioClip = AssetDatabase.LoadAssetAtPath<AudioClip>(path);\n\n            if (audioClip != null)\n                audioClips.Add(audioClip);\n        }\n\n        if (audioClips.Count > 0)\n        {\n            DragAndDrop.AcceptDrag();\n            addAudioClipsDelegate?.Invoke(audioClips);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/AudioContainerWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Audio;\nusing UnityEditor.Audio.UIElements;\nusing UnityEditor.ShortcutManagement;\nusing UnityEditor.UIElements;\nusing UnityEngine;\nusing UnityEngine.Assertions;\nusing UnityEngine.Audio;\nusing UnityEngine.Scripting;\nusing UnityEngine.UIElements;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor;\n\nsealed class AudioContainerWindow : EditorWindow\n{\n    enum Icons\n    {\n        Play = 0,\n        Stop = 1,\n        Skip = 2,\n        DiceOff = 3,\n        DiceOn = 4\n    }\n\n    /// <summary>\n    /// The cached instance of the window, if it is open.\n    /// </summary>\n    internal static AudioContainerWindow Instance { get; private set; }\n\n    internal readonly AudioContainerWindowState State = new();\n\n    /// <summary>\n    /// Holds the added list elements in the list interaction callbacks.\n    /// Only used locally in these methods, but it's a global member to avoid GC.\n    /// </summary>\n    readonly List<AudioContainerElement> m_AddedElements = new();\n    readonly string k_EmptyGuidString = Guid.Empty.ToString(\"N\");\n    readonly Texture2D[] k_IconTextureCache = new Texture2D[Enum.GetNames(typeof(Icons)).Length];\n\n    VisualElement m_ContainerRootVisualElement;\n    VisualElement m_Day0RootVisualElement;\n\n    // Preview section\n    Label m_AssetNameLabel;\n    Button m_PlayStopButton;\n    VisualElement m_PlayStopButtonImage;\n    Button m_SkipButton;\n    VisualElement m_SkipButtonImage;\n\n    // Volume section\n    Slider m_VolumeSlider;\n    AudioRandomRangeSliderTracker m_VolumeRandomRangeTracker;\n    FloatField m_VolumeField;\n    Button m_VolumeRandomizationButton;\n    VisualElement m_VolumeRandomizationButtonImage;\n    MinMaxSlider m_VolumeRandomizationRangeSlider;\n    Vector2Field m_VolumeRandomizationRangeField;\n    AudioLevelMeter m_Meter;\n\n    // Pitch section\n    Slider m_PitchSlider;\n    AudioRandomRangeSliderTracker m_PitchRandomRangeTracker;\n    FloatField m_PitchField;\n    Button m_PitchRandomizationButton;\n    VisualElement m_PitchRandomizationButtonImage;\n    MinMaxSlider m_PitchRandomizationRangeSlider;\n    Vector2Field m_PitchRandomizationRangeField;\n\n    // Clip list section\n    ListView m_ClipsListView;\n    AudioContainerListDragAndDropManipulator m_DragManipulator;\n\n    // Trigger and playback mode section\n    RadioButtonGroup m_TriggerRadioButtonGroup;\n    RadioButtonGroup m_PlaybackModeRadioButtonGroup;\n    IntegerField m_AvoidRepeatingLastField;\n\n    // Automatic trigger section\n    RadioButtonGroup m_AutomaticTriggerModeRadioButtonGroup;\n    Slider m_TimeSlider;\n    AudioRandomRangeSliderTracker m_TimeRandomRangeTracker;\n    FloatField m_TimeField;\n    Button m_TimeRandomizationButton;\n    VisualElement m_TimeRandomizationButtonImage;\n    MinMaxSlider m_TimeRandomizationRangeSlider;\n    Vector2Field m_TimeRandomizationRangeField;\n    RadioButtonGroup m_LoopRadioButtonGroup;\n    IntegerField m_CountField;\n    Button m_CountRandomizationButton;\n    VisualElement m_CountRandomizationButtonImage;\n    MinMaxSlider m_CountRandomizationRangeSlider;\n    Vector2Field m_CountRandomizationRangeField;\n    Label m_AutomaticTriggerModeLabel;\n    Label m_LoopLabel;\n\n    bool m_IsVisible;\n    bool m_IsInitializing;\n    bool m_Day0ElementsInitialized;\n    bool m_ContainerElementsInitialized;\n    bool m_IsSubscribedToGUICallbacksAndEvents;\n    bool m_ClipFieldProgressBarsAreCleared = true;\n\n    /// <summary>\n    /// Holds the previous state of the list elements for undo/delete housekeeping\n    /// </summary>\n    List<AudioContainerElement> m_CachedElements = new();\n\n    [RequiredByNativeCode]\n    internal static void CreateAudioRandomContainerWindow()\n    {\n        var window = GetWindow<AudioContainerWindow>();\n        window.Show();\n    }\n\n    // Used by tests.\n    internal bool IsInitializedForTargetDisplay()\n    {\n        return m_ContainerElementsInitialized && m_IsSubscribedToGUICallbacksAndEvents;\n    }\n\n    static void OnCreateButtonClicked()\n    {\n        ProjectWindowUtil.CreateAudioRandomContainer();\n    }\n\n    void OnEnable()\n    {\n        if (Instance == null)\n        {\n            Instance = this;\n        }\n\n        SetTitle();\n    }\n\n    void OnDisable()\n    {\n        State.OnDestroy();\n        UnsubscribeFromGUICallbacksAndEvents();\n        m_IsInitializing = false;\n        m_Day0ElementsInitialized = false;\n        m_ContainerElementsInitialized = false;\n        m_CachedElements.Clear();\n        m_AddedElements.Clear();\n\n        if (Instance == this)\n        {\n            Instance = null;\n        }\n    }\n\n    void OnFocus()\n    {\n        if (State.AudioContainer != null)\n        {\n            UpdateTransportButtonStates();\n        }\n    }\n\n    void Update()\n    {\n        if (!m_IsVisible)\n            return;\n\n        if (State.IsPreviewPlayingOrPaused()) { UpdateClipFieldProgressBars(); }\n        else if (!m_ClipFieldProgressBarsAreCleared) { ClearClipFieldProgressBars(); }\n\n        if (m_Meter != null)\n        {\n            if (State.IsPreviewPlayingOrPaused())\n            {\n                if (State != null) { m_Meter.Value = State.GetMeterValue(); }\n                else { m_Meter.Value = -80.0f; }\n            }\n            else\n            {\n                if (m_Meter.Value != -80.0f) { m_Meter.Value = -80.0f; }\n            }\n        }\n    }\n\n    void SetTitle()\n    {\n        var titleString = \"Audio Random Container\";\n\n        if (State.IsDirty())\n            titleString += \"*\";\n\n        titleContent = new GUIContent(titleString)\n        {\n            image = GetIconTexture(Icons.DiceOff)\n        };\n    }\n\n    void CreateGUI()\n    {\n        try\n        {\n            if (m_IsInitializing)\n                return;\n\n            m_IsInitializing = true;\n\n            var root = rootVisualElement;\n\n            if (root.childCount == 0)\n            {\n                var rootAsset = UIToolkitUtilities.LoadUxml(\"UXML/Audio/AudioRandomContainer.uxml\");\n                Assert.IsNotNull(rootAsset);\n                rootAsset.CloneTree(root);\n\n                var styleSheet = UIToolkitUtilities.LoadStyleSheet(\"StyleSheets/Audio/AudioRandomContainer.uss\");\n                Assert.IsNotNull(styleSheet);\n                root.styleSheets.Add(styleSheet);\n                root.Add(State.GetResourceTrackerElement());\n\n                m_ContainerRootVisualElement = UIToolkitUtilities.GetChildByName<ScrollView>(root, \"ARC_ScrollView\");\n                Assert.IsNotNull(m_ContainerRootVisualElement);\n                m_Day0RootVisualElement = UIToolkitUtilities.GetChildByName<VisualElement>(root, \"Day0\");\n                Assert.IsNotNull(m_Day0RootVisualElement);\n            }\n\n            if (m_ContainerElementsInitialized)\n                root.Unbind();\n\n            if (State.AudioContainer == null)\n            {\n                if (!m_Day0ElementsInitialized)\n                {\n                    InitializeDay0Elements();\n                    m_Day0ElementsInitialized = true;\n                }\n\n                m_Day0RootVisualElement.style.display = DisplayStyle.Flex;\n                m_ContainerRootVisualElement.style.display = DisplayStyle.None;\n            }\n            else\n            {\n                if (!m_ContainerElementsInitialized)\n                {\n                    InitializeContainerElements();\n                    m_ContainerElementsInitialized = true;\n                    EditorApplication.update += OneTimeEditorApplicationUpdate;\n                }\n\n                if (!m_IsSubscribedToGUICallbacksAndEvents)\n                    SubscribeToGUICallbacksAndEvents();\n\n                BindAndTrackObjectAndProperties();\n\n                m_Day0RootVisualElement.style.display = DisplayStyle.None;\n                m_ContainerRootVisualElement.style.display = DisplayStyle.Flex;\n                m_CachedElements = State.AudioContainer.elements.ToList();\n                m_ClipsListView.Rebuild(); // Force a list rebuild when the list has changed or it will not always render correctly due to a UI toolkit bug.\n            }\n        }\n        finally\n        {\n            m_IsInitializing = false;\n        }\n    }\n\n    bool IsDisplayingTarget()\n    {\n        return\n            m_Day0RootVisualElement != null\n            && m_Day0RootVisualElement.style.display == DisplayStyle.None\n            && m_ContainerRootVisualElement != null\n            && m_ContainerRootVisualElement.style.display == DisplayStyle.Flex;\n    }\n\n    void InitializeDay0Elements()\n    {\n        var createButtonLabel = UIToolkitUtilities.GetChildByName<Label>(m_Day0RootVisualElement, \"CreateButtonLabel\");\n        var createButton = UIToolkitUtilities.GetChildByName<Button>(m_Day0RootVisualElement, \"CreateButton\");\n        createButton.clicked += OnCreateButtonClicked;\n        createButtonLabel.text = \"Select an existing Audio Random Container asset in the project browser or create a new one using the button below.\";\n    }\n\n    void InitializeContainerElements()\n    {\n        InitializePreviewElements();\n        InitializeVolumeElements();\n        InitializePitchElements();\n        InitializeClipListElements();\n        InitializeTriggerAndPlayModeElements();\n        InitializeAutomaticTriggerElements();\n    }\n\n    void SubscribeToGUICallbacksAndEvents()\n    {\n        if (!m_ContainerElementsInitialized || m_IsSubscribedToGUICallbacksAndEvents)\n        {\n            return;\n        }\n\n        SubscribeToPreviewCallbacksAndEvents();\n        SubscribeToVolumeCallbacksAndEvents();\n        SubscribeToPitchCallbacksAndEvents();\n        SubscribeToClipListCallbacksAndEvents();\n        SubscribeToAutomaticTriggerCallbacksAndEvents();\n        SubscribeToTooltipCallbacksAndEvents();\n        SubscribeToAudioMasterMuteCallbacksAndEvents();\n        m_IsSubscribedToGUICallbacksAndEvents = true;\n    }\n\n    void UnsubscribeFromGUICallbacksAndEvents()\n    {\n        if (!m_ContainerElementsInitialized || !m_IsSubscribedToGUICallbacksAndEvents)\n        {\n            return;\n        }\n\n        UnsubscribeFromPreviewCallbacksAndEvents();\n        UnsubscribeFromVolumeCallbacksAndEvents();\n        UnsubscribeFromPitchCallbacksAndEvents();\n        UnsubscribeFromClipListCallbacksAndEvents();\n        UnsubscribeFromAutomaticTriggerCallbacksAndEvents();\n        UnsubscribeFromTooltipCallbacksAndEvents();\n        UnsubscribeFromAudioMasterMuteCallbacksAndEvents();\n        m_IsSubscribedToGUICallbacksAndEvents = false;\n    }\n\n    void BindAndTrackObjectAndProperties()\n    {\n        m_ContainerRootVisualElement.TrackSerializedObjectValue(State.SerializedObject, OnSerializedObjectChanged);\n\n        BindAndTrackPreviewProperties();\n        BindAndTrackVolumeProperties();\n        BindAndTrackPitchProperties();\n        BindAndTrackClipListProperties();\n        BindAndTrackTriggerAndPlayModeProperties();\n        BindAndTrackAutomaticTriggerProperties();\n    }\n\n    void OnTargetChanged(object sender, EventArgs e)\n    {\n        SetTitle();\n        CreateGUI();\n\n        if (State.AudioContainer == null)\n            m_CachedElements.Clear();\n        else\n            m_CachedElements = State.AudioContainer.elements.ToList();\n    }\n\n    void OnSerializedObjectChanged(SerializedObject obj)\n    {\n        SetTitle();\n    }\n\n    void OneTimeEditorApplicationUpdate()\n    {\n        // Setting this is a temp workaround for a UIToolKit bug\n        // https://unity.slack.com/archives/C3414V4UV/p1681828689005249?thread_ts=1676901177.340799&cid=C3414V4UV\n        m_ClipsListView.reorderable = true;\n        m_ClipsListView.reorderMode = ListViewReorderMode.Animated;\n        EditorApplication.update -= OneTimeEditorApplicationUpdate;\n    }\n\n    static void InsertUnitFieldForFloatField(VisualElement field, string unit)\n    {\n        var floatInput = UIToolkitUtilities.GetChildByName<VisualElement>(field, \"unity-text-input\");\n        var unitTextElement = new TextElement\n        {\n            name = \"numeric-field-unit-label\",\n            text = unit\n        };\n        floatInput.Add(unitTextElement);\n    }\n\n    #region Preview\n\n    void InitializePreviewElements()\n    {\n        m_AssetNameLabel = UIToolkitUtilities.GetChildByName<Label>(m_ContainerRootVisualElement, \"asset-name-label\");\n        m_PlayStopButton = UIToolkitUtilities.GetChildByName<Button>(m_ContainerRootVisualElement, \"play-button\");\n        m_PlayStopButtonImage = UIToolkitUtilities.GetChildByName<VisualElement>(m_ContainerRootVisualElement, \"play-button-image\");\n        m_SkipButton = UIToolkitUtilities.GetChildByName<Button>(m_ContainerRootVisualElement, \"skip-button\");\n        m_SkipButtonImage = UIToolkitUtilities.GetChildByName<VisualElement>(m_ContainerRootVisualElement, \"skip-button-image\");\n        m_SkipButtonImage.style.backgroundImage = GetIconTexture(Icons.Skip);\n    }\n\n    void SubscribeToPreviewCallbacksAndEvents()\n    {\n        m_PlayStopButton.clicked += OnPlayStopButtonClicked;\n        m_SkipButton.clicked += OnSkipButtonClicked;\n    }\n\n    void UnsubscribeFromPreviewCallbacksAndEvents()\n    {\n        if (m_PlayStopButton != null)\n            m_PlayStopButton.clicked -= OnPlayStopButtonClicked;\n\n        if (m_SkipButton != null)\n            m_SkipButton.clicked -= OnSkipButtonClicked;\n    }\n\n    void BindAndTrackPreviewProperties()\n    {\n        UpdateTransportButtonStates();\n        m_AssetNameLabel.text = State.AudioContainer.name;\n    }\n\n    void OnPlayStopButtonClicked()\n    {\n        if (State.IsPreviewPlayingOrPaused())\n        {\n            State.StopPreview();\n            ClearClipFieldProgressBars();\n        }\n        else\n            State.PlayPreview();\n\n        UpdateTransportButtonStates();\n    }\n\n    void OnSkipButtonClicked()\n    {\n        if (State.IsPreviewPlayingOrPaused())\n            State.Skip();\n    }\n\n    void UpdateTransportButtonStates()\n    {\n        var editorIsPaused = EditorApplication.isPaused;\n\n        m_PlayStopButton?.SetEnabled(State.IsReadyToPlayPreview() && !editorIsPaused && !EditorUtility.audioMasterMute);\n        m_SkipButton?.SetEnabled(State.IsPreviewPlayingOrPaused() && State.AudioContainer.triggerMode == AudioRandomContainerTriggerMode.Automatic && !editorIsPaused && !EditorUtility.audioMasterMute);\n        m_PlayStopButtonImage.style.backgroundImage = State.IsPreviewPlayingOrPaused() ? GetIconTexture(Icons.Stop) : GetIconTexture(Icons.Play);\n    }\n\n    Texture2D GetIconTexture(Icons icon)\n    {\n        var cacheIndex = (int)icon;\n\n        var name = icon switch\n        {\n            Icons.Play or Icons.Stop or Icons.Skip => icon.ToString(),\n            Icons.DiceOff => \"AudioRandomContainer On Icon\",\n            Icons.DiceOn => \"AudioRandomContainer Icon\",\n            _ => throw new ArgumentOutOfRangeException(nameof(icon), icon, null)\n        };\n\n        if (k_IconTextureCache[cacheIndex] == null)\n        {\n            k_IconTextureCache[cacheIndex] = EditorGUIUtility.IconContent(name).image as Texture2D;\n        }\n\n        return k_IconTextureCache[cacheIndex];\n    }\n\n    void OnTransportStateChanged(object sender, EventArgs e)\n    {\n        UpdateTransportButtonStates();\n    }\n\n    void EditorPauseStateChanged(object sender, EventArgs e)\n    {\n        UpdateTransportButtonStates();\n    }\n\n    #endregion\n\n    #region Volume\n\n    void InitializeVolumeElements()\n    {\n        m_Meter = UIToolkitUtilities.GetChildByName<AudioLevelMeter>(m_ContainerRootVisualElement, \"meter\");\n        m_VolumeSlider = UIToolkitUtilities.GetChildByName<Slider>(m_ContainerRootVisualElement, \"volume-slider\");\n        m_VolumeRandomRangeTracker = AudioRandomRangeSliderTracker.Create(m_VolumeSlider, State.AudioContainer.volumeRandomizationRange);\n        m_VolumeField = UIToolkitUtilities.GetChildByName<FloatField>(m_ContainerRootVisualElement, \"volume-field\");\n        m_VolumeRandomizationButton = UIToolkitUtilities.GetChildByName<Button>(m_ContainerRootVisualElement, \"volume-randomization-button\");\n        m_VolumeRandomizationButtonImage = UIToolkitUtilities.GetChildByName<VisualElement>(m_ContainerRootVisualElement, \"volume-randomization-button-image\");\n        m_VolumeRandomizationRangeSlider = UIToolkitUtilities.GetChildByName<MinMaxSlider>(m_ContainerRootVisualElement, \"volume-randomization-range-slider\");\n        m_VolumeRandomizationRangeField = UIToolkitUtilities.GetChildByName<Vector2Field>(m_ContainerRootVisualElement, \"volume-randomization-range-field\");\n        var volumeRandomizationMinField = UIToolkitUtilities.GetChildByName<FloatField>(m_VolumeRandomizationRangeField, \"unity-x-input\");\n        var volumeRandomizationMaxField = UIToolkitUtilities.GetChildByName<FloatField>(m_VolumeRandomizationRangeField, \"unity-y-input\");\n\n        m_VolumeField.formatString = \"0.#\";\n        InsertUnitFieldForFloatField(m_VolumeField, \"dB\");\n        m_VolumeField.isDelayed = true;\n        volumeRandomizationMinField.isDelayed = true;\n        volumeRandomizationMinField.label = \"\";\n        volumeRandomizationMinField.formatString = \"0.#\";\n        InsertUnitFieldForFloatField(volumeRandomizationMinField, \"dB\");\n        volumeRandomizationMaxField.isDelayed = true;\n        volumeRandomizationMaxField.label = \"\";\n        volumeRandomizationMaxField.formatString = \"0.#\";\n        InsertUnitFieldForFloatField(volumeRandomizationMaxField, \"dB\");\n    }\n\n    void SubscribeToVolumeCallbacksAndEvents()\n    {\n        m_VolumeRandomizationButton.clicked += OnVolumeRandomizationButtonClicked;\n        m_VolumeSlider.RegisterValueChangedCallback(OnVolumeChanged);\n        m_VolumeRandomizationRangeSlider.RegisterValueChangedCallback(OnVolumeRandomizationRangeChanged);\n        m_VolumeRandomizationRangeField.RegisterValueChangedCallback(OnVolumeRandomizationRangeChanged);\n    }\n\n    void UnsubscribeFromVolumeCallbacksAndEvents()\n    {\n        if (m_VolumeRandomizationButton != null)\n            m_VolumeRandomizationButton.clicked -= OnVolumeRandomizationButtonClicked;\n\n        m_VolumeSlider?.UnregisterValueChangedCallback(OnVolumeChanged);\n        m_VolumeRandomizationRangeSlider?.UnregisterValueChangedCallback(OnVolumeRandomizationRangeChanged);\n        m_VolumeRandomizationRangeField?.UnregisterValueChangedCallback(OnVolumeRandomizationRangeChanged);\n    }\n\n    void BindAndTrackVolumeProperties()\n    {\n        var volumeProperty = State.SerializedObject.FindProperty(\"m_Volume\");\n        var volumeRandomizationEnabledProperty = State.SerializedObject.FindProperty(\"m_VolumeRandomizationEnabled\");\n        var volumeRandomizationRangeProperty = State.SerializedObject.FindProperty(\"m_VolumeRandomizationRange\");\n\n        m_VolumeSlider.BindProperty(volumeProperty);\n        m_VolumeField.BindProperty(volumeProperty);\n        m_VolumeRandomizationRangeSlider.BindProperty(volumeRandomizationRangeProperty);\n        m_VolumeRandomizationRangeField.BindProperty(volumeRandomizationRangeProperty);\n\n        m_VolumeRandomizationButton.TrackPropertyValue(volumeRandomizationEnabledProperty, OnVolumeRandomizationEnabledChanged);\n\n        OnVolumeRandomizationEnabledChanged(volumeRandomizationEnabledProperty);\n    }\n\n    void OnVolumeChanged(ChangeEvent<float> evt)\n    {\n        m_VolumeRandomRangeTracker.SetRange(State.AudioContainer.volumeRandomizationRange);\n    }\n\n    void OnVolumeRandomizationRangeChanged(ChangeEvent<Vector2> evt)\n    {\n        // Have to clamp immediately here to avoid UI jitter because the min-max slider cannot clamp before updating the property\n        var newValue = evt.newValue;\n\n        if (newValue.x > 0)\n            newValue.x = 0;\n\n        if (newValue.y < 0)\n            newValue.y = 0;\n\n        m_VolumeRandomRangeTracker.SetRange(newValue);\n    }\n\n    void OnVolumeRandomizationEnabledChanged(SerializedProperty property)\n    {\n        if (property.boolValue)\n        {\n            m_VolumeRandomizationButtonImage.style.backgroundImage = GetIconTexture(Icons.DiceOn);\n            m_VolumeRandomizationRangeSlider.SetEnabled(true);\n            m_VolumeRandomizationRangeField.SetEnabled(true);\n            m_VolumeRandomRangeTracker.SetEnabled(true);\n        }\n        else\n        {\n            m_VolumeRandomizationButtonImage.style.backgroundImage = GetIconTexture(Icons.DiceOff);\n            m_VolumeRandomizationRangeSlider.SetEnabled(false);\n            m_VolumeRandomizationRangeField.SetEnabled(false);\n            m_VolumeRandomRangeTracker.SetEnabled(false);\n        }\n    }\n\n    void OnVolumeRandomizationButtonClicked()\n    {\n        var newButtonStateString = !State.AudioContainer.volumeRandomizationEnabled ? \"Enabled\" : \"Disabled\";\n        Undo.RecordObject(State.AudioContainer, $\"Modified Volume Randomization {newButtonStateString} in {State.AudioContainer.name}\");\n        State.AudioContainer.volumeRandomizationEnabled = !State.AudioContainer.volumeRandomizationEnabled;\n    }\n\n    #endregion\n\n    #region Pitch\n\n    void InitializePitchElements()\n    {\n        m_PitchSlider = UIToolkitUtilities.GetChildByName<Slider>(m_ContainerRootVisualElement, \"pitch-slider\");\n        m_PitchRandomRangeTracker = AudioRandomRangeSliderTracker.Create(m_PitchSlider, State.AudioContainer.pitchRandomizationRange);\n        m_PitchField = UIToolkitUtilities.GetChildByName<FloatField>(m_ContainerRootVisualElement, \"pitch-field\");\n        m_PitchRandomizationButton = UIToolkitUtilities.GetChildByName<Button>(m_ContainerRootVisualElement, \"pitch-randomization-button\");\n        m_PitchRandomizationButtonImage = UIToolkitUtilities.GetChildByName<VisualElement>(m_ContainerRootVisualElement, \"pitch-randomization-button-image\");\n        m_PitchRandomizationRangeSlider = UIToolkitUtilities.GetChildByName<MinMaxSlider>(m_ContainerRootVisualElement, \"pitch-randomization-range-slider\");\n        m_PitchRandomizationRangeField = UIToolkitUtilities.GetChildByName<Vector2Field>(m_ContainerRootVisualElement, \"pitch-randomization-range-field\");\n        var pitchRandomizationMinField = UIToolkitUtilities.GetChildByName<FloatField>(m_PitchRandomizationRangeField, \"unity-x-input\");\n        var pitchRandomizationMaxField = UIToolkitUtilities.GetChildByName<FloatField>(m_PitchRandomizationRangeField, \"unity-y-input\");\n\n        m_PitchField.formatString = \"0\";\n        InsertUnitFieldForFloatField(m_PitchField, \"ct\");\n        m_PitchField.isDelayed = true;\n        pitchRandomizationMinField.isDelayed = true;\n        pitchRandomizationMinField.label = \"\";\n        pitchRandomizationMinField.formatString = \"0\";\n        InsertUnitFieldForFloatField(pitchRandomizationMinField, \"ct\");\n        pitchRandomizationMaxField.isDelayed = true;\n        pitchRandomizationMaxField.label = \"\";\n        pitchRandomizationMaxField.formatString = \"0\";\n        InsertUnitFieldForFloatField(pitchRandomizationMaxField, \"ct\");\n    }\n\n    void SubscribeToPitchCallbacksAndEvents()\n    {\n        m_PitchRandomizationButton.clicked += OnPitchRandomizationButtonClicked;\n        m_PitchSlider.RegisterValueChangedCallback(OnPitchChanged);\n        m_PitchRandomizationRangeSlider.RegisterValueChangedCallback(OnPitchRandomizationRangeChanged);\n        m_PitchRandomizationRangeField.RegisterValueChangedCallback(OnPitchRandomizationRangeChanged);\n    }\n\n    void UnsubscribeFromPitchCallbacksAndEvents()\n    {\n        if (m_PitchRandomizationButton != null)\n            m_PitchRandomizationButton.clicked -= OnPitchRandomizationButtonClicked;\n\n        m_PitchSlider?.UnregisterValueChangedCallback(OnPitchChanged);\n        m_PitchRandomizationRangeSlider?.UnregisterValueChangedCallback(OnPitchRandomizationRangeChanged);\n        m_PitchRandomizationRangeField?.UnregisterValueChangedCallback(OnPitchRandomizationRangeChanged);\n    }\n\n    void BindAndTrackPitchProperties()\n    {\n        var pitchProperty = State.SerializedObject.FindProperty(\"m_Pitch\");\n        var pitchRandomizationEnabledProperty = State.SerializedObject.FindProperty(\"m_PitchRandomizationEnabled\");\n        var pitchRandomizationRangeProperty = State.SerializedObject.FindProperty(\"m_PitchRandomizationRange\");\n\n        m_PitchSlider.BindProperty(pitchProperty);\n        m_PitchField.BindProperty(pitchProperty);\n        m_PitchRandomizationRangeSlider.BindProperty(pitchRandomizationRangeProperty);\n        m_PitchRandomizationRangeField.BindProperty(pitchRandomizationRangeProperty);\n\n        m_PitchRandomizationButton.TrackPropertyValue(pitchRandomizationEnabledProperty, OnPitchRandomizationEnabledChanged);\n\n        OnPitchRandomizationEnabledChanged(pitchRandomizationEnabledProperty);\n    }\n\n    void OnPitchChanged(ChangeEvent<float> evt)\n    {\n        m_PitchRandomRangeTracker.SetRange(State.AudioContainer.pitchRandomizationRange);\n    }\n\n    void OnPitchRandomizationRangeChanged(ChangeEvent<Vector2> evt)\n    {\n        // Have to clamp immediately here to avoid UI jitter because the min-max slider cannot clamp before updating the property\n        var newValue = evt.newValue;\n\n        if (newValue.x > 0)\n            newValue.x = 0;\n\n        if (newValue.y < 0)\n            newValue.y = 0;\n\n        m_PitchRandomRangeTracker.SetRange(newValue);\n    }\n\n    void OnPitchRandomizationEnabledChanged(SerializedProperty property)\n    {\n        if (property.boolValue)\n        {\n            m_PitchRandomizationButtonImage.style.backgroundImage = GetIconTexture(Icons.DiceOn);\n            m_PitchRandomizationRangeSlider.SetEnabled(true);\n            m_PitchRandomizationRangeField.SetEnabled(true);\n            m_PitchRandomRangeTracker.SetEnabled(true);\n        }\n        else\n        {\n            m_PitchRandomizationButtonImage.style.backgroundImage = GetIconTexture(Icons.DiceOff);\n            m_PitchRandomizationRangeSlider.SetEnabled(false);\n            m_PitchRandomizationRangeField.SetEnabled(false);\n            m_PitchRandomRangeTracker.SetEnabled(false);\n        }\n    }\n\n    void OnPitchRandomizationButtonClicked()\n    {\n        var newButtonStateString = !State.AudioContainer.pitchRandomizationEnabled ? \"Enabled\" : \"Disabled\";\n        Undo.RecordObject(State.AudioContainer, $\"Modified Pitch Randomization {newButtonStateString} in {State.AudioContainer.name}\");\n        State.AudioContainer.pitchRandomizationEnabled = !State.AudioContainer.pitchRandomizationEnabled;\n    }\n\n    #endregion\n\n    #region ClipList\n\n    void InitializeClipListElements()\n    {\n        m_ClipsListView = UIToolkitUtilities.GetChildByName<ListView>(m_ContainerRootVisualElement, \"audio-clips-list-view\");\n        m_ClipsListView.CreateDragAndDropController();\n        m_DragManipulator = new AudioContainerListDragAndDropManipulator(m_ContainerRootVisualElement);\n        m_ClipsListView.fixedItemHeight = 24;\n    }\n\n    void SubscribeToClipListCallbacksAndEvents()\n    {\n        m_ClipsListView.itemsAdded += OnListItemsAdded;\n        m_ClipsListView.itemsRemoved += OnListItemsRemoved;\n        m_ClipsListView.itemIndexChanged += OnItemListIndexChanged;\n        m_ClipsListView.makeItem = OnMakeListItem;\n        m_ClipsListView.bindItem = OnBindListItem;\n        m_ClipsListView.unbindItem = OnUnbindListItem;\n        m_DragManipulator.addAudioClipsDelegate += OnAudioClipDrag;\n    }\n\n    void UnsubscribeFromClipListCallbacksAndEvents()\n    {\n        if (m_ClipsListView != null)\n        {\n            m_ClipsListView.itemsAdded -= OnListItemsAdded;\n            m_ClipsListView.itemsRemoved -= OnListItemsRemoved;\n            m_ClipsListView.itemIndexChanged -= OnItemListIndexChanged;\n            m_ClipsListView.makeItem = null;\n            m_ClipsListView.bindItem = null;\n            m_ClipsListView.unbindItem = null;\n        }\n\n        if (m_DragManipulator != null)\n            m_DragManipulator.addAudioClipsDelegate -= OnAudioClipDrag;\n    }\n\n    void BindAndTrackClipListProperties()\n    {\n        var clipsProperty = State.SerializedObject.FindProperty(\"m_Elements\");\n\n        m_ClipsListView.BindProperty(clipsProperty);\n        m_ClipsListView.TrackPropertyValue(clipsProperty, OnAudioClipListChanged);\n    }\n\n    static void UpdateListElementName(Object element, Object clip = null)\n    {\n        AssetDatabase.TryGetGUIDAndLocalFileIdentifier(element, out var guid, out var localId);\n        var name = clip == null ? nameof(AudioContainerElement) : clip.name;\n        element.name = $\"{name}_{{{localId}}}\";\n    }\n\n    static VisualElement OnMakeListItem()\n    {\n        var element = UIToolkitUtilities.LoadUxml(\"UXML/Audio/AudioContainerElement.uxml\").Instantiate();\n        var volumeField = UIToolkitUtilities.GetChildByName<FloatField>(element, \"volume-field\");\n        InsertUnitFieldForFloatField(volumeField, \"dB\");\n        return element;\n    }\n\n    void OnBindListItem(VisualElement element, int index)\n    {\n        // There is currently a bug in UIToolkit where the reported index can be out of bounds after shrinking the list\n        if (index > State.AudioContainer.elements.Length - 1)\n            return;\n\n        var enabledToggle = UIToolkitUtilities.GetChildByName<Toggle>(element, \"enabled-toggle\");\n        var audioClipField = UIToolkitUtilities.GetChildByName<AudioContainerElementClipField>(element, \"audio-clip-field\");\n        var volumeField = UIToolkitUtilities.GetChildByName<FloatField>(element, \"volume-field\");\n        volumeField.formatString = \"0.#\";\n\n        audioClipField.objectType = typeof(AudioClip);\n\n        var listElement = State.AudioContainer.elements[index];\n\n        if (listElement == null)\n        {\n            Debug.LogError($\"AudioContainerElement at index {index} is null. Please report using `Help > Report a Bug...`.\");\n            element.SetEnabled(false);\n            return;\n        }\n\n        element.SetEnabled(true);\n        audioClipField.RegisterCallback<DragPerformEvent>(OnListDragPerform);\n        audioClipField.AssetElementInstanceID = listElement.GetInstanceID();\n\n        var serializedObject = new SerializedObject(listElement);\n\n        var enabledProperty = serializedObject.FindProperty(\"m_Enabled\");\n        var audioClipProperty = serializedObject.FindProperty(\"m_AudioClip\");\n        var volumeProperty = serializedObject.FindProperty(\"m_Volume\");\n\n        // Shouldn't be necessary to unbind here, but currently required to work around an exception\n        // being thrown when calling TrackPropertyValue. See https://jira.unity3d.com/browse/UUM-46918\n        // Should be removed once this issue has been fixed.\n        enabledToggle.Unbind();\n        audioClipField.Unbind();\n        volumeField.Unbind();\n\n        enabledToggle.BindProperty(enabledProperty);\n        audioClipField.BindProperty(audioClipProperty);\n        volumeField.BindProperty(volumeProperty);\n\n        enabledToggle.TrackPropertyValue(enabledProperty, OnElementEnabledToggleChanged);\n        audioClipField.TrackPropertyValue(audioClipProperty, OnElementAudioClipChanged);\n        volumeField.TrackPropertyValue(volumeProperty, OnElementPropertyChanged);\n\n        enabledToggle.RegisterValueChangedCallback(OnElementEnabledToggleChanged);\n        audioClipField.RegisterValueChangedCallback(OnElementAudioClipChanged);\n    }\n\n    void OnUnbindListItem(VisualElement element, int index)\n    {\n        var enabledToggle = UIToolkitUtilities.GetChildByName<Toggle>(element, \"enabled-toggle\");\n        var audioClipField = UIToolkitUtilities.GetChildByName<AudioContainerElementClipField>(element, \"audio-clip-field\");\n        var volumeField = UIToolkitUtilities.GetChildByName<FloatField>(element, \"volume-field\");\n\n        enabledToggle.UnregisterValueChangedCallback(OnElementEnabledToggleChanged);\n        audioClipField.UnregisterValueChangedCallback(OnElementAudioClipChanged);\n        audioClipField.UnregisterCallback<DragPerformEvent>(OnListDragPerform);\n\n        enabledToggle.Unbind();\n        audioClipField.Unbind();\n        volumeField.Unbind();\n    }\n\n    static void OnListDragPerform(DragPerformEvent evt)\n    {\n        evt.StopPropagation();\n    }\n\n    void OnElementEnabledToggleChanged(ChangeEvent<bool> evt)\n    {\n        State.OnAudioClipListChanged();\n    }\n\n    void OnElementEnabledToggleChanged(SerializedProperty property)\n    {\n        State.OnAudioClipListChanged();\n\n        OnElementPropertyChanged(property);\n        UpdateTransportButtonStates();\n\n        // Changing a property on the ListElement subasset does not call CheckConsistency on the main Asset\n        // So quickly flip the values to force an update. :(\n        var last = State.AudioContainer.avoidRepeatingLast;\n        State.AudioContainer.avoidRepeatingLast = -1;\n        State.AudioContainer.avoidRepeatingLast = last;\n    }\n\n    void OnElementAudioClipChanged(ChangeEvent<Object> evt)\n    {\n        State.OnAudioClipListChanged();\n    }\n\n    void OnElementAudioClipChanged(SerializedProperty property)\n    {\n        State.OnAudioClipListChanged();\n\n        var element = property.serializedObject.targetObject as AudioContainerElement;\n        Assert.IsNotNull(element);\n        var clip = property.objectReferenceValue as AudioClip;\n        UpdateListElementName(element, clip);\n        OnElementPropertyChanged(property);\n        UpdateTransportButtonStates();\n    }\n\n    void OnElementPropertyChanged(SerializedProperty property)\n    {\n        EditorUtility.SetDirty(State.AudioContainer);\n        SetTitle();\n    }\n\n    void OnListItemsAdded(IEnumerable<int> indices)\n    {\n        State.OnAudioClipListChanged();\n\n        var indicesArray = indices as int[] ?? indices.ToArray();\n        const string undoName = $\"Add {nameof(AudioRandomContainer)} element\";\n        var groupUndoName = undoName;\n\n        if (indicesArray.Length > 1)\n        {\n            groupUndoName = $\"{undoName}s\";\n        }\n\n        Undo.SetCurrentGroupName(groupUndoName);\n        var elements = State.AudioContainer.elements.ToList();\n        m_AddedElements.Clear();\n\n        foreach (var index in indicesArray)\n        {\n            var element = new AudioContainerElement\n            {\n                hideFlags = HideFlags.HideInHierarchy\n            };\n            AssetDatabase.AddObjectToAsset(element, State.AudioContainer);\n            UpdateListElementName(element);\n            elements[index] = element;\n            m_AddedElements.Add(element);\n        }\n\n        State.AudioContainer.elements = elements.ToArray();\n\n        foreach (var element in m_AddedElements)\n        {\n            Undo.RegisterCreatedObjectUndo(element, undoName);\n        }\n    }\n\n    void OnListItemsRemoved(IEnumerable<int> indices)\n    {\n        State.OnAudioClipListChanged();\n\n        var indicesArray = indices as int[] ?? indices.ToArray();\n\n        // Confusingly, this callback is sometimes invoked post-delete and sometimes pre-delete,\n        // i.e. the AudioRandomContainer.elements property may or may not be updated at this time,\n        // so we use the cached list to be sure we get the correct reference to the subasset to delete.\n        foreach (var index in indicesArray)\n        {\n            if (m_CachedElements[index] != null)\n            {\n                Undo.DestroyObjectImmediate(m_CachedElements[index]);\n            }\n        }\n\n        var undoName = $\"Remove {nameof(AudioRandomContainer)} element\";\n\n        if (indicesArray.Length > 1)\n        {\n            undoName = $\"{undoName}s\";\n        }\n\n        Undo.SetCurrentGroupName(undoName);\n    }\n\n    void OnItemListIndexChanged(int oldIndex, int newIndex)\n    {\n        State.OnAudioClipListChanged();\n        Undo.SetCurrentGroupName($\"Reorder {nameof(AudioRandomContainer)} list\");\n    }\n\n    void OnAudioClipDrag(List<AudioClip> audioClips)\n    {\n        State.OnAudioClipListChanged();\n\n        const string undoName = $\"Add {nameof(AudioRandomContainer)} element\";\n        var groupUndoName = undoName;\n\n        if (audioClips.Count > 1)\n        {\n            groupUndoName = $\"{undoName}s\";\n        }\n\n        Undo.RegisterCompleteObjectUndo(State.AudioContainer, groupUndoName);\n        Undo.SetCurrentGroupName(groupUndoName);\n        var elements = State.AudioContainer.elements.ToList();\n        m_AddedElements.Clear();\n\n        foreach (var audioClip in audioClips)\n        {\n            var element = new AudioContainerElement\n            {\n                audioClip = audioClip,\n                hideFlags = HideFlags.HideInHierarchy\n            };\n            AssetDatabase.AddObjectToAsset(element, State.AudioContainer);\n            UpdateListElementName(element, audioClip);\n            elements.Add(element);\n            m_AddedElements.Add(element);\n        }\n\n        State.AudioContainer.elements = elements.ToArray();\n\n        foreach (var element in m_AddedElements)\n        {\n            Undo.RegisterCreatedObjectUndo(element, undoName);\n        }\n    }\n\n    // NOTE: this function is also the entry point for handling undo-redo of clip list changes.\n    void OnAudioClipListChanged(SerializedProperty property)\n    {\n        State.OnAudioClipListChanged();\n\n        // Do manual fixup of orphaned subassets after a possible undo of item removal\n        // because the undo system does not play nice with RegisterCreatedObjectUndo.\n        if (m_CachedElements.Count < State.AudioContainer.elements.Length)\n        {\n            var elements = State.AudioContainer.elements;\n\n            foreach (var elm in elements)\n            {\n                // If the element is null, OnBindListItem will handle it, log an error and grey out the list entry.\n                if (elm == null)\n                {\n                    continue;\n                }\n\n                AssetDatabase.TryGetGUIDAndLocalFileIdentifier(elm, out var guid, out var localId);\n\n                // An empty asset GUID means the subasset has lost the reference\n                // to the main asset after an undo of item removal, so re-add it manually.\n                if (guid.Equals(k_EmptyGuidString))\n                    AssetDatabase.AddObjectToAsset(elm, State.AudioContainer);\n            }\n        }\n\n        // Update the cached list of elements\n        m_CachedElements = State.AudioContainer.elements.ToList();\n\n        // Force a list rebuild when the list has changed or it will not always render correctly\n        m_ClipsListView.Rebuild();\n\n        ClearClipFieldProgressBars();\n        UpdateTransportButtonStates();\n        SetTitle();\n    }\n\n    void UpdateClipFieldProgressBars()\n    {\n        var playables = State.GetActivePlayables();\n\n        if (playables == null)\n            return;\n\n        // Iterate over the ActivePlayables from the runtime and try and match them to the instance ID on the clip field.\n        // if its a match, set the progress and remove the clip field to avoid overwriting the progress.\n        var clipFields = m_ClipsListView.Query<AudioContainerElementClipField>().ToList();\n\n        // We need to sort the active playables as the runtime does not guarantee order\n        Array.Sort(playables, (x, y) => x.settings.scheduledTime.CompareTo(y.settings.scheduledTime));\n\n        for (var i = playables.Length - 1; i >= 0; i--)\n        {\n            var playable = new AudioClipPlayable(playables[i].clipPlayableHandle);\n\n            for (var j = clipFields.Count - 1; j >= 0; j--)\n            {\n                var field = clipFields[j];\n\n                if (field.AssetElementInstanceID == playables[i].settings.element.GetInstanceID())\n                {\n                    field.Progress = playable.GetClipPositionSec() / playable.GetClip().length;\n                    clipFields.RemoveAt(j);\n                }\n            }\n        }\n\n        // Any clip fields that did not have a match with active playables should have their progress set to 0.\n        foreach (var field in clipFields)\n            if (field.Progress != 0.0f)\n                field.Progress = 0.0f;\n\n        m_ClipFieldProgressBarsAreCleared = false;\n    }\n\n    void ClearClipFieldProgressBars()\n    {\n        if (m_ClipsListView == null)\n            return;\n\n        var clipFields = m_ClipsListView.Query<AudioContainerElementClipField>().ToList();\n\n        foreach (var field in clipFields)\n            field.Progress = 0.0f;\n\n        m_ClipFieldProgressBarsAreCleared = true;\n    }\n\n    #endregion\n\n    #region TriggerAndPlaybackMode\n\n    void InitializeTriggerAndPlayModeElements()\n    {\n        m_TriggerRadioButtonGroup = UIToolkitUtilities.GetChildByName<RadioButtonGroup>(m_ContainerRootVisualElement, \"trigger-radio-button-group\");\n        m_PlaybackModeRadioButtonGroup = UIToolkitUtilities.GetChildByName<RadioButtonGroup>(m_ContainerRootVisualElement, \"playback-radio-button-group\");\n        m_AvoidRepeatingLastField = UIToolkitUtilities.GetChildByName<IntegerField>(m_ContainerRootVisualElement, \"avoid-repeating-last-field\");\n    }\n\n    void BindAndTrackTriggerAndPlayModeProperties()\n    {\n        var triggerProperty = State.SerializedObject.FindProperty(\"m_TriggerMode\");\n        var playbackModeProperty = State.SerializedObject.FindProperty(\"m_PlaybackMode\");\n        var avoidRepeatingLastProperty = State.SerializedObject.FindProperty(\"m_AvoidRepeatingLast\");\n\n        m_TriggerRadioButtonGroup.BindProperty(triggerProperty);\n        m_TriggerRadioButtonGroup.TrackPropertyValue(triggerProperty, OnTriggerChanged);\n        m_PlaybackModeRadioButtonGroup.BindProperty(playbackModeProperty);\n        m_PlaybackModeRadioButtonGroup.TrackPropertyValue(playbackModeProperty, OnPlaybackModeChanged);\n        m_AvoidRepeatingLastField.BindProperty(avoidRepeatingLastProperty);\n\n        OnTriggerChanged((AudioRandomContainerTriggerMode)m_TriggerRadioButtonGroup.value);\n        OnPlaybackModeChanged(playbackModeProperty);\n    }\n\n    void OnTriggerChanged(SerializedProperty property)\n    {\n        OnTriggerChanged((AudioRandomContainerTriggerMode)property.intValue);\n    }\n\n    void OnTriggerChanged(AudioRandomContainerTriggerMode mode)\n    {\n        var enabled = mode == AudioRandomContainerTriggerMode.Automatic;\n        m_AutomaticTriggerModeRadioButtonGroup.SetEnabled(enabled);\n        m_TimeSlider.SetEnabled(enabled);\n        m_TimeField.SetEnabled(enabled);\n        m_LoopRadioButtonGroup.SetEnabled(enabled);\n        m_AutomaticTriggerModeLabel.SetEnabled(enabled);\n        m_LoopLabel.SetEnabled(enabled);\n        m_TimeRandomizationButton.SetEnabled(enabled);\n        m_CountRandomizationButton.SetEnabled(enabled);\n\n        var loopProperty = State.SerializedObject.FindProperty(\"m_LoopMode\");\n        OnLoopChanged(loopProperty);\n\n        var timeRandomizationEnabledProperty = State.SerializedObject.FindProperty(\"m_AutomaticTriggerTimeRandomizationEnabled\");\n        OnTimeRandomizationEnabledChanged(timeRandomizationEnabledProperty);\n    }\n\n    void OnPlaybackModeChanged(SerializedProperty property)\n    {\n        m_AvoidRepeatingLastField.SetEnabled(property.intValue == (int)AudioRandomContainerPlaybackMode.Random);\n    }\n\n    #endregion\n\n    #region AutomaticTrigger\n\n    void InitializeAutomaticTriggerElements()\n    {\n        m_AutomaticTriggerModeRadioButtonGroup = UIToolkitUtilities.GetChildByName<RadioButtonGroup>(m_ContainerRootVisualElement, \"trigger-mode-radio-button-group\");\n        m_TimeSlider = UIToolkitUtilities.GetChildByName<Slider>(m_ContainerRootVisualElement, \"time-slider\");\n        m_TimeRandomRangeTracker = AudioRandomRangeSliderTracker.Create(m_TimeSlider, State.AudioContainer.automaticTriggerTimeRandomizationRange);\n        m_TimeField = UIToolkitUtilities.GetChildByName<FloatField>(m_ContainerRootVisualElement, \"time-field\");\n        m_TimeRandomizationButton = UIToolkitUtilities.GetChildByName<Button>(m_ContainerRootVisualElement, \"time-randomization-button\");\n        m_TimeRandomizationButtonImage = UIToolkitUtilities.GetChildByName<VisualElement>(m_ContainerRootVisualElement, \"time-randomization-button-image\");\n        m_TimeRandomizationRangeSlider = UIToolkitUtilities.GetChildByName<MinMaxSlider>(m_ContainerRootVisualElement, \"time-randomization-range-slider\");\n        m_TimeRandomizationRangeField = UIToolkitUtilities.GetChildByName<Vector2Field>(m_ContainerRootVisualElement, \"time-randomization-range-field\");\n        var timeRandomizationMinField = UIToolkitUtilities.GetChildByName<FloatField>(m_TimeRandomizationRangeField, \"unity-x-input\");\n        var timeRandomizationMaxField = UIToolkitUtilities.GetChildByName<FloatField>(m_TimeRandomizationRangeField, \"unity-y-input\");\n        m_LoopRadioButtonGroup = UIToolkitUtilities.GetChildByName<RadioButtonGroup>(m_ContainerRootVisualElement, \"loop-radio-button-group\");\n        m_CountField = UIToolkitUtilities.GetChildByName<IntegerField>(m_ContainerRootVisualElement, \"count-field\");\n        m_CountRandomizationButton = UIToolkitUtilities.GetChildByName<Button>(m_ContainerRootVisualElement, \"count-randomization-button\");\n        m_CountRandomizationButtonImage = UIToolkitUtilities.GetChildByName<VisualElement>(m_ContainerRootVisualElement, \"count-randomization-button-image\");\n        m_CountRandomizationRangeSlider = UIToolkitUtilities.GetChildByName<MinMaxSlider>(m_ContainerRootVisualElement, \"count-randomization-range-slider\");\n        m_CountRandomizationRangeField = UIToolkitUtilities.GetChildByName<Vector2Field>(m_ContainerRootVisualElement, \"count-randomization-range-field\");\n        var countRandomizationMinField = UIToolkitUtilities.GetChildByName<FloatField>(m_CountRandomizationRangeField, \"unity-x-input\");\n        var countRandomizationMaxField = UIToolkitUtilities.GetChildByName<FloatField>(m_CountRandomizationRangeField, \"unity-y-input\");\n        m_AutomaticTriggerModeLabel = UIToolkitUtilities.GetChildByName<Label>(m_ContainerRootVisualElement, \"automatic-trigger-mode-label\");\n        m_LoopLabel = UIToolkitUtilities.GetChildByName<Label>(m_ContainerRootVisualElement, \"loop-label\");\n\n        m_TimeField.formatString = \"0.00\";\n        InsertUnitFieldForFloatField(m_TimeField, \"s\");\n        m_TimeField.isDelayed = true;\n        timeRandomizationMinField.isDelayed = true;\n        timeRandomizationMinField.label = \"\";\n        timeRandomizationMinField.formatString = \"0.#\";\n        InsertUnitFieldForFloatField(timeRandomizationMinField, \"s\");\n        timeRandomizationMaxField.isDelayed = true;\n        timeRandomizationMaxField.label = \"\";\n        timeRandomizationMaxField.formatString = \"0.#\";\n        InsertUnitFieldForFloatField(timeRandomizationMaxField, \"s\");\n\n        m_CountField.formatString = \"0.#\";\n        m_CountField.isDelayed = true;\n        countRandomizationMinField.isDelayed = true;\n        countRandomizationMinField.label = \"\";\n        countRandomizationMaxField.isDelayed = true;\n        countRandomizationMaxField.label = \"\";\n    }\n\n    void SubscribeToAutomaticTriggerCallbacksAndEvents()\n    {\n        m_TimeRandomizationButton.clicked += OnTimeRandomizationButtonClicked;\n        m_CountRandomizationButton.clicked += OnCountRandomizationButtonClicked;\n        m_TimeSlider.RegisterValueChangedCallback(OnTimeChanged);\n        m_TimeRandomizationRangeField.RegisterValueChangedCallback(OnTimeRandomizationRangeChanged);\n        m_TimeRandomizationRangeSlider.RegisterValueChangedCallback(OnTimeRandomizationRangeChanged);\n    }\n\n    void UnsubscribeFromAutomaticTriggerCallbacksAndEvents()\n    {\n        if (m_TimeRandomizationButton != null)\n            m_TimeRandomizationButton.clicked -= OnTimeRandomizationButtonClicked;\n\n        if (m_CountRandomizationButton != null)\n            m_CountRandomizationButton.clicked -= OnCountRandomizationButtonClicked;\n\n        m_TimeSlider?.UnregisterValueChangedCallback(OnTimeChanged);\n        m_TimeRandomizationRangeField?.UnregisterValueChangedCallback(OnTimeRandomizationRangeChanged);\n        m_TimeRandomizationRangeSlider?.UnregisterValueChangedCallback(OnTimeRandomizationRangeChanged);\n    }\n\n    void SubscribeToTooltipCallbacksAndEvents()\n    {\n        rootVisualElement.RegisterCallback<TooltipEvent>(ShowTooltip, TrickleDown.TrickleDown);\n    }\n\n    void SubscribeToAudioMasterMuteCallbacksAndEvents()\n    {\n        EditorUtility.onAudioMasterMuteWasUpdated += OnAudioMasterMuteChanged;\n    }\n\n    void UnsubscribeFromTooltipCallbacksAndEvents()\n    {\n        rootVisualElement.UnregisterCallback<TooltipEvent>(ShowTooltip);\n    }\n\n    void UnsubscribeFromAudioMasterMuteCallbacksAndEvents()\n    {\n        EditorUtility.onAudioMasterMuteWasUpdated -= OnAudioMasterMuteChanged;\n    }\n\n    void ShowTooltip(TooltipEvent evt)\n    {\n        var name = (evt.target as VisualElement).name;\n\n        if (name == \"play-button\" || name == \"play-button-image\")\n        {\n            if (EditorUtility.audioMasterMute)\n            {\n                evt.tooltip = \"Previewing is disabled when the game view is muted. To enable previewing unmute the game view.\";\n            }\n            else\n            {\n                var mode = State.IsPreviewPlayingOrPaused() ? \"Stop\" : \"Play\";\n                var shortcut = ShortcutManager.instance.GetShortcutBinding(\"Audio/Play-stop Audio Random Container\");\n\n                if (shortcut.Equals(ShortcutBinding.empty))\n                {\n                    evt.tooltip = mode;\n                }\n                else\n                {\n                    evt.tooltip = mode + \" (\" + shortcut + \")\";\n                }\n            }\n\n            evt.rect = (evt.target as VisualElement).worldBound;\n            evt.StopPropagation();\n        }\n    }\n\n    void BindAndTrackAutomaticTriggerProperties()\n    {\n        var automaticTriggerModeProperty = State.SerializedObject.FindProperty(\"m_AutomaticTriggerMode\");\n        var triggerTimeProperty = State.SerializedObject.FindProperty(\"m_AutomaticTriggerTime\");\n        var triggerTimeRandomizationEnabledProperty = State.SerializedObject.FindProperty(\"m_AutomaticTriggerTimeRandomizationEnabled\");\n        var triggerTimeRandomizationRangeProperty = State.SerializedObject.FindProperty(\"m_AutomaticTriggerTimeRandomizationRange\");\n        var loopModeProperty = State.SerializedObject.FindProperty(\"m_LoopMode\");\n        var loopCountProperty = State.SerializedObject.FindProperty(\"m_LoopCount\");\n        var loopCountRandomizationEnabledProperty = State.SerializedObject.FindProperty(\"m_LoopCountRandomizationEnabled\");\n        var loopCountRandomizationRangeProperty = State.SerializedObject.FindProperty(\"m_LoopCountRandomizationRange\");\n\n        m_AutomaticTriggerModeRadioButtonGroup.BindProperty(automaticTriggerModeProperty);\n        m_TimeSlider.BindProperty(triggerTimeProperty);\n        m_TimeField.BindProperty(triggerTimeProperty);\n        m_TimeRandomizationRangeSlider.BindProperty(triggerTimeRandomizationRangeProperty);\n        m_TimeRandomizationRangeField.BindProperty(triggerTimeRandomizationRangeProperty);\n        m_LoopRadioButtonGroup.BindProperty(loopModeProperty);\n        m_CountField.BindProperty(loopCountProperty);\n        m_CountRandomizationRangeSlider.BindProperty(loopCountRandomizationRangeProperty);\n        m_CountRandomizationRangeField.BindProperty(loopCountRandomizationRangeProperty);\n\n        m_TimeRandomizationButton.TrackPropertyValue(triggerTimeRandomizationEnabledProperty, OnTimeRandomizationEnabledChanged);\n        m_LoopRadioButtonGroup.TrackPropertyValue(loopModeProperty, OnLoopChanged);\n        m_CountRandomizationButton.TrackPropertyValue(loopCountRandomizationEnabledProperty, OnCountRandomizationEnabledChanged);\n\n        OnTimeRandomizationEnabledChanged(triggerTimeRandomizationEnabledProperty);\n        OnLoopChanged(loopModeProperty);\n        OnCountRandomizationEnabledChanged(loopCountRandomizationEnabledProperty);\n    }\n\n    void OnTimeChanged(ChangeEvent<float> evt)\n    {\n        m_TimeRandomRangeTracker.SetRange(State.AudioContainer.automaticTriggerTimeRandomizationRange);\n    }\n\n    void OnTimeRandomizationRangeChanged(ChangeEvent<Vector2> evt)\n    {\n        // Have to clamp immediately here to avoid UI jitter because the min-max slider cannot clamp before updating the property\n        var newValue = evt.newValue;\n\n        if (newValue.x > 0)\n            newValue.x = 0;\n\n        if (newValue.y < 0)\n            newValue.y = 0;\n\n        m_TimeRandomRangeTracker.SetRange(newValue);\n    }\n\n    void OnTimeRandomizationEnabledChanged(SerializedProperty property)\n    {\n        if (property.boolValue\n            && State.AudioContainer.triggerMode == AudioRandomContainerTriggerMode.Automatic)\n        {\n            m_TimeRandomizationButtonImage.style.backgroundImage = GetIconTexture(Icons.DiceOn);\n            m_TimeRandomizationRangeSlider.SetEnabled(true);\n            m_TimeRandomizationRangeField.SetEnabled(true);\n            m_TimeRandomRangeTracker.SetEnabled(true);\n        }\n        else\n        {\n            m_TimeRandomizationButtonImage.style.backgroundImage = GetIconTexture(Icons.DiceOff);\n            m_TimeRandomizationRangeSlider.SetEnabled(false);\n            m_TimeRandomizationRangeField.SetEnabled(false);\n            m_TimeRandomRangeTracker.SetEnabled(false);\n        }\n    }\n\n    void OnTimeRandomizationButtonClicked()\n    {\n        var newButtonStateString = !State.AudioContainer.automaticTriggerTimeRandomizationEnabled ? \"Enabled\" : \"Disabled\";\n        Undo.RecordObject(State.AudioContainer, $\"Modified Time Randomization {newButtonStateString} in {State.AudioContainer.name}\");\n        State.AudioContainer.automaticTriggerTimeRandomizationEnabled = !State.AudioContainer.automaticTriggerTimeRandomizationEnabled;\n    }\n\n    void OnLoopChanged(SerializedProperty property)\n    {\n        var enabled = property.intValue != (int)AudioRandomContainerLoopMode.Infinite && State.AudioContainer.triggerMode == AudioRandomContainerTriggerMode.Automatic;\n\n        m_CountField.SetEnabled(enabled);\n        m_CountRandomizationRangeSlider.SetEnabled(enabled);\n        m_CountRandomizationRangeField.SetEnabled(enabled);\n        m_CountRandomizationButton.SetEnabled(enabled);\n\n        var countRandomizationEnabledProperty = State.SerializedObject.FindProperty(\"m_LoopCountRandomizationEnabled\");\n        OnCountRandomizationEnabledChanged(countRandomizationEnabledProperty);\n    }\n\n    void OnCountRandomizationEnabledChanged(SerializedProperty property)\n    {\n        if (property.boolValue\n            && State.AudioContainer.loopMode != AudioRandomContainerLoopMode.Infinite\n            && State.AudioContainer.triggerMode == AudioRandomContainerTriggerMode.Automatic)\n        {\n            m_CountRandomizationButtonImage.style.backgroundImage = GetIconTexture(Icons.DiceOn);\n            m_CountRandomizationRangeSlider.SetEnabled(true);\n            m_CountRandomizationRangeField.SetEnabled(true);\n        }\n        else\n        {\n            m_CountRandomizationButtonImage.style.backgroundImage = GetIconTexture(Icons.DiceOff);\n            m_CountRandomizationRangeSlider.SetEnabled(false);\n            m_CountRandomizationRangeField.SetEnabled(false);\n        }\n    }\n\n    void OnCountRandomizationButtonClicked()\n    {\n        var newButtonStateString = !State.AudioContainer.loopCountRandomizationEnabled ? \"Enabled\" : \"Disabled\";\n        Undo.RecordObject(State.AudioContainer, $\"Modified Count Randomization {newButtonStateString} in {State.AudioContainer.name}\");\n        State.AudioContainer.loopCountRandomizationEnabled = !State.AudioContainer.loopCountRandomizationEnabled;\n    }\n\n    void OnAudioMasterMuteChanged(bool isMuted)\n    {\n        if (isMuted && State.IsPreviewPlayingOrPaused())\n        {\n            State.StopPreview();\n            ClearClipFieldProgressBars();\n        }\n\n        UpdateTransportButtonStates();\n    }\n\n    #endregion\n\n    #region GlobalEditorCallbackHandlers\n\n    void OnBecameVisible()\n    {\n        m_IsVisible = true;\n        State.TargetChanged += OnTargetChanged;\n        State.TransportStateChanged += OnTransportStateChanged;\n        State.EditorPauseStateChanged += EditorPauseStateChanged;\n        State.Resume();\n\n        if (!m_IsSubscribedToGUICallbacksAndEvents\n            && m_ContainerElementsInitialized\n            && IsDisplayingTarget())\n        {\n            SubscribeToGUICallbacksAndEvents();\n        }\n    }\n\n    void OnBecameInvisible()\n    {\n        m_IsVisible = false;\n        State.TargetChanged -= OnTargetChanged;\n        State.TransportStateChanged -= OnTransportStateChanged;\n        State.EditorPauseStateChanged -= EditorPauseStateChanged;\n        State.Suspend();\n\n        if (m_IsSubscribedToGUICallbacksAndEvents\n            && m_ContainerElementsInitialized\n            && IsDisplayingTarget())\n        {\n            UnsubscribeFromGUICallbacksAndEvents();\n        }\n\n        EditorApplication.update -= OneTimeEditorApplicationUpdate;\n        ClearClipFieldProgressBars();\n    }\n\n    void OnWillSaveAssets(IEnumerable<string> paths)\n    {\n        // If there is no target we are in day 0 state.\n        if (State.AudioContainer == null)\n            return;\n\n        foreach (var path in paths)\n            if (path == State.TargetPath)\n            {\n                SetTitle();\n                return;\n            }\n    }\n\n    void OnAssetsImported(IEnumerable<string> paths)\n    {\n        // If there is no target we are in day 0 state.\n        if (State.AudioContainer == null)\n            return;\n\n        foreach (var path in paths)\n            if (path == State.TargetPath)\n            {\n                State.SerializedObject.Update();\n                OnTargetChanged(this, EventArgs.Empty);\n                return;\n            }\n    }\n\n    void OnAssetsDeleted(IEnumerable<string> paths)\n    {\n        // The target reference will already be invalid at this point if it's been deleted.\n        if (State.AudioContainer != null)\n            return;\n\n        // ...but we still have the target path available for the check.\n        foreach (var path in paths)\n            if (path == State.TargetPath)\n            {\n                State.Reset();\n                OnTargetChanged(this, EventArgs.Empty);\n                return;\n            }\n    }\n\n    void OnAssetsMoved(IEnumerable<string> paths)\n    {\n        // If there is no target we are in day 0 state.\n        if (State.AudioContainer == null)\n            return;\n\n        foreach (var path in paths)\n            if (path == State.TargetPath)\n            {\n                State.UpdateTargetPath();\n            }\n    }\n\n    class AudioContainerModificationProcessor : AssetModificationProcessor\n    {\n        /// <summary>\n        /// Handles save of AudioRandomContainer assets\n        /// and relays it to AudioContainerWindow,\n        /// removing the asterisk in the window tab label.\n        /// </summary>\n        static string[] OnWillSaveAssets(string[] paths)\n        {\n            // NOTE: this is a global callback that is triggered by changes to ANY project assets of ANY type,\n            // even when the window is closed, so no heavy calls should be done here unless\n            // the window is actually open. To avoid affecting editor performance we use the\n            // cached instance for an early out check rather than EditorWindow.HasOpenInstances.\n            if (Instance == null)\n            {\n                return paths;\n            }\n\n            Instance.OnWillSaveAssets(paths);\n            return paths;\n        }\n    }\n\n    class AudioContainerPostProcessor : AssetPostprocessor\n    {\n        /// <summary>\n        /// Handles import and deletion of AudioRandomContainer assets\n        /// and relays it to AudioContainerWindow,\n        /// refreshing or clearing the window content.\n        /// </summary>\n        static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssets)\n        {\n            // NOTE: this is a global callback that is triggered by changes to ANY project assets of ANY type,\n            // even when the window is closed, so no heavy calls should be done here unless\n            // the window is actually open. To avoid affecting editor performance we use the\n            // cached instance for an early out check rather than EditorWindow.HasOpenInstances.\n            if (Instance == null)\n            {\n                return;\n            }\n\n            if (movedFromAssets.Length > 0)\n                Instance.OnAssetsMoved(movedFromAssets);\n\n            if (importedAssets.Length > 0)\n                Instance.OnAssetsImported(importedAssets);\n\n            if (deletedAssets.Length > 0)\n                Instance.OnAssetsDeleted(deletedAssets);\n        }\n    }\n\n    #endregion\n\n    #region Shortcuts\n\n    [Shortcut(\"Audio/Play-stop Audio Random Container\", typeof(AudioContainerWindow), KeyCode.P, ShortcutModifiers.Alt)]\n    static void Preview(ShortcutArguments args)\n    {\n        var audioContainerWindow = focusedWindow as AudioContainerWindow;\n\n        if (audioContainerWindow != null && audioContainerWindow.IsDisplayingTarget() && !EditorUtility.audioMasterMute)\n        {\n            audioContainerWindow.OnPlayStopButtonClicked();\n        }\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/AudioContainerWindowState.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.UIElements;\nusing UnityEngine;\nusing UnityEngine.Audio;\nusing UnityEngine.UIElements;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor;\n\nsealed class AudioContainerWindowState\n{\n    // Used by tests.\n    internal const string previewAudioSourceName = \"PreviewAudioSource595651\";\n\n    AudioRandomContainer m_AudioContainer;\n    AudioSource m_PreviewAudioSource;\n    SerializedObject m_SerializedObject;\n    VisualElement m_ResourceTrackerElement;\n    AudioSource m_TrackedSource;\n\n    // Need this flag to track transport state changes immediately, as there could be a\n    // one-frame delay to get the correct value from AudioSource.isContainerPlaying.\n    bool m_IsPreviewPlayingOrPausedLocalFlag;\n    bool m_IsSuspended;\n\n    internal event EventHandler TargetChanged;\n    internal event EventHandler TransportStateChanged;\n    internal event EventHandler EditorPauseStateChanged;\n\n    internal AudioContainerWindowState()\n    {\n        EditorApplication.playModeStateChanged += OnEditorPlayModeStateChanged;\n        EditorApplication.pauseStateChanged += OnEditorPauseStateChanged;\n        Selection.selectionChanged += OnSelectionChanged;\n    }\n\n    internal AudioRandomContainer AudioContainer\n    {\n        get\n        {\n            if (m_AudioContainer == null && m_TrackedSource == null)\n                UpdateTarget();\n\n            return m_AudioContainer;\n        }\n    }\n\n    internal SerializedObject SerializedObject\n    {\n        get\n        {\n            if (m_AudioContainer != null && (m_SerializedObject == null || m_SerializedObject.targetObject != m_AudioContainer))\n                m_SerializedObject = new SerializedObject(m_AudioContainer);\n\n            return m_SerializedObject;\n        }\n    }\n\n    internal string TargetPath { get; private set; }\n\n    internal void UpdateTargetPath()\n    {\n        if (m_AudioContainer != null)\n        {\n            TargetPath = AssetDatabase.GetAssetPath(m_AudioContainer);\n        }\n        else\n        {\n            TargetPath = null;\n        }\n    }\n\n    internal void Reset()\n    {\n        StopPreview();\n        m_AudioContainer = null;\n        m_SerializedObject = null;\n        m_IsPreviewPlayingOrPausedLocalFlag = false;\n        UpdateTargetPath();\n    }\n\n    internal VisualElement GetResourceTrackerElement()\n    {\n        m_ResourceTrackerElement = new VisualElement();\n        return m_ResourceTrackerElement;\n    }\n\n    internal void OnDestroy()\n    {\n        StopPreview();\n\n        if (m_PreviewAudioSource != null)\n            Object.DestroyImmediate(m_PreviewAudioSource.gameObject);\n\n        EditorApplication.playModeStateChanged -= OnEditorPlayModeStateChanged;\n        EditorApplication.pauseStateChanged -= OnEditorPauseStateChanged;\n        Selection.selectionChanged -= OnSelectionChanged;\n    }\n\n    internal void Suspend()\n    {\n        m_IsSuspended = true;\n        StopPreview();\n\n        if (m_PreviewAudioSource != null)\n            Object.DestroyImmediate(m_PreviewAudioSource.gameObject);\n    }\n\n    internal void Resume()\n    {\n        m_IsSuspended = false;\n        UpdateTarget();\n    }\n\n    /// <summary>\n    /// Updates the current target based on the currently selected object in the editor.\n    /// </summary>\n    void UpdateTarget()\n    {\n        if (m_IsSuspended)\n            return;\n\n        AudioRandomContainer newTarget = null;\n        AudioSource audioSource = null;\n        var selectedObject = Selection.activeObject;\n\n        // The logic below deals with selecting our new ARC target, whatever we set m_AudioContainer to below will be\n        // used by AudioContainerWindow to display the ARC if the target is valid or a day0 state if the target is null.\n        // If the selection is a GameObject, we always want to swap the target, a user selecting GameObjects in the\n        // scene hierarchy should always see what ARC is on a particular object, this includes the scenario of not\n        // having an AudioSource and the value of the resource property on an AudioSource being null/not an ARC.\n        // If the selected object is not a GameObject, we only swap targets if it is an ARC - meaning if you are\n        // selecting objects in the project browser it holds on to the last ARC selected.\n\n        if (selectedObject != null)\n        {\n            if (selectedObject is GameObject go)\n            {\n                audioSource = go.GetComponent<AudioSource>();\n\n                if (audioSource != null)\n                {\n                    newTarget = audioSource.resource as AudioRandomContainer;\n                }\n            }\n            else\n            {\n                if (selectedObject is AudioRandomContainer container)\n                {\n                    newTarget = container;\n                }\n                else\n                {\n                    newTarget = m_AudioContainer;\n                }\n            }\n        }\n        else\n        {\n            newTarget = m_AudioContainer;\n        }\n\n        var targetChanged = m_AudioContainer != newTarget;\n        var trackedSourceChanged = m_TrackedSource != audioSource;\n\n        if (!targetChanged && !trackedSourceChanged)\n        {\n            return;\n        }\n\n        Reset();\n\n        m_AudioContainer = newTarget;\n        m_TrackedSource = audioSource;\n\n        if (m_AudioContainer != null)\n        {\n            UpdateTargetPath();\n        }\n\n        if (targetChanged)\n        {\n            TargetChanged?.Invoke(this, EventArgs.Empty);\n        }\n\n        if (trackedSourceChanged)\n        {\n            UpdateResourceTrackerElement();\n        }\n    }\n\n    void OnResourceChanged(SerializedProperty property)\n    {\n        var container = property.objectReferenceValue as AudioRandomContainer;\n\n        if (m_AudioContainer == container)\n            return;\n\n        Reset();\n        m_AudioContainer = container;\n\n        if (m_AudioContainer != null)\n        {\n            UpdateTargetPath();\n        }\n\n        TargetChanged?.Invoke(this, EventArgs.Empty);\n\n        UpdateResourceTrackerElement();\n    }\n\n    void UpdateResourceTrackerElement()\n    {\n        if (m_ResourceTrackerElement != null)\n        {\n            m_ResourceTrackerElement.Unbind();\n        }\n\n        if (m_TrackedSource != null)\n        {\n            var trackedSourceSO = new SerializedObject(m_TrackedSource);\n            var trackedSourceResourceProperty = trackedSourceSO.FindProperty(\"m_Resource\");\n            m_ResourceTrackerElement.TrackPropertyValue(trackedSourceResourceProperty, OnResourceChanged);\n        }\n    }\n\n    internal void PlayPreview()\n    {\n        var canNotPlay = m_IsSuspended || IsPreviewPlayingOrPaused() || !IsReadyToPlayPreview();\n\n        if (canNotPlay)\n            return;\n\n        if (m_PreviewAudioSource == null)\n        {\n            // Create a hidden game object in the scene with an AudioSource for editor previewing purposes.\n            // The preview object is created on play and destroyed on stop.\n            // This means that this object is a hidden part of the user's scene during play/pause.\n            var gameObject = new GameObject\n            {\n                name = previewAudioSourceName,\n                hideFlags = HideFlags.HideInHierarchy | HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild\n            };\n\n            m_PreviewAudioSource = gameObject.AddComponent<AudioSource>();\n            m_PreviewAudioSource.playOnAwake = false;\n        }\n\n        m_PreviewAudioSource.resource = m_AudioContainer;\n        m_PreviewAudioSource.Play();\n        m_IsPreviewPlayingOrPausedLocalFlag = true;\n        TransportStateChanged?.Invoke(this, EventArgs.Empty);\n        EditorApplication.update += OnEditorApplicationUpdate;\n    }\n\n    internal void StopPreview()\n    {\n        var canNotStop = m_IsSuspended || !IsPreviewPlayingOrPaused();\n\n        if (canNotStop)\n            return;\n\n        m_PreviewAudioSource.Stop();\n        m_PreviewAudioSource.resource = null;\n        m_IsPreviewPlayingOrPausedLocalFlag = false;\n        TransportStateChanged?.Invoke(this, EventArgs.Empty);\n        EditorApplication.update -= OnEditorApplicationUpdate;\n    }\n\n    internal void OnAudioClipListChanged()\n    {\n        // We don't support live updates that affect the clip scheduling,\n        // so stop the preview and any other audio sources that reference this asset.\n        AudioContainer.NotifyObservers(AudioRandomContainer.ChangeEventType.List);\n        StopPreview();\n    }\n\n    internal void Skip()\n    {\n        var canNotSkip = m_IsSuspended || !IsPreviewPlayingOrPaused();\n\n        if (canNotSkip)\n            return;\n\n        m_PreviewAudioSource.SkipToNextElementIfHasContainer();\n    }\n\n    internal bool IsPreviewPlayingOrPaused()\n    {\n        return m_IsPreviewPlayingOrPausedLocalFlag || (m_PreviewAudioSource != null && m_PreviewAudioSource.isContainerPlaying);\n    }\n\n    /// <summary>\n    /// Checks if the window has a current target with at least one enabled audio clip assigned.\n    /// </summary>\n    /// <returns>Whether or not there are valid audio clips to play</returns>\n    internal bool IsReadyToPlayPreview()\n    {\n        if (m_AudioContainer == null)\n            return false;\n\n        var elements = m_AudioContainer.elements;\n\n        for (var i = 0; i < elements.Length; ++i)\n            if (elements[i] != null && elements[i].audioClip != null && elements[i].enabled)\n                return true;\n\n        return false;\n    }\n\n    internal ActivePlayable[] GetActivePlayables()\n    {\n        return IsPreviewPlayingOrPaused() ? m_PreviewAudioSource.containerActivePlayables : null;\n    }\n\n    internal float GetMeterValue()\n    {\n        return m_PreviewAudioSource.GetAudioRandomContainerRuntimeMeterValue();\n    }\n\n    internal bool IsDirty()\n    {\n        return m_AudioContainer != null && EditorUtility.IsDirty(m_AudioContainer);\n    }\n\n    void OnEditorApplicationUpdate()\n    {\n        if (m_PreviewAudioSource != null && m_PreviewAudioSource.isContainerPlaying)\n            return;\n\n        m_IsPreviewPlayingOrPausedLocalFlag = false;\n        TransportStateChanged?.Invoke(this, EventArgs.Empty);\n        EditorApplication.update -= OnEditorApplicationUpdate;\n    }\n\n    void OnEditorPlayModeStateChanged(PlayModeStateChange state)\n    {\n        if (state is PlayModeStateChange.ExitingEditMode or PlayModeStateChange.ExitingPlayMode)\n        {\n            StopPreview();\n\n            if (m_PreviewAudioSource != null)\n            {\n                Object.DestroyImmediate(m_PreviewAudioSource.gameObject);\n            }\n        }\n    }\n\n    void OnEditorPauseStateChanged(PauseState state)\n    {\n        if (m_AudioContainer == null || m_IsSuspended)\n        {\n            return;\n        }\n\n        EditorPauseStateChanged?.Invoke(this, EventArgs.Empty);\n    }\n\n    void OnSelectionChanged()\n    {\n        UpdateTarget();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Bindings/AudioUtil.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Mono/Audio/Bindings/AudioUtil.bindings.h\")]\n    [StaticAccessor(\"AudioUtilScriptBindings\", StaticAccessorType.DoubleColon)]\n    internal class AudioUtil\n    {\n        [StaticAccessor(\"GetAudioManager()\", StaticAccessorType.Dot)]\n        extern public static bool resetAllAudioClipPlayCountsOnPlay { get; set; }\n\n        [StaticAccessor(\"GetAudioManager()\", StaticAccessorType.Dot)]\n        extern public static void PlayPreviewClip([NotNull] AudioClip clip, int startSample = 0, bool loop = false);\n\n        [StaticAccessor(\"GetAudioManager()\", StaticAccessorType.Dot)]\n        extern public static void PausePreviewClip();\n\n        [StaticAccessor(\"GetAudioManager()\", StaticAccessorType.Dot)]\n        extern public static void ResumePreviewClip();\n\n        [StaticAccessor(\"GetAudioManager()\", StaticAccessorType.Dot)]\n        extern public static void LoopPreviewClip(bool on);\n\n        [StaticAccessor(\"GetAudioManager()\", StaticAccessorType.Dot)]\n        extern public static bool IsPreviewClipPlaying();\n\n        [StaticAccessor(\"GetAudioManager()\", StaticAccessorType.Dot)]\n        extern public static void StopAllPreviewClips();\n\n        [StaticAccessor(\"GetAudioManager()\", StaticAccessorType.Dot)]\n        extern public static float GetPreviewClipPosition();\n\n        [StaticAccessor(\"GetAudioManager()\", StaticAccessorType.Dot)]\n        extern public static int GetPreviewClipSamplePosition();\n\n        [StaticAccessor(\"GetAudioManager()\", StaticAccessorType.Dot)]\n        extern public static void SetPreviewClipSamplePosition([NotNull] AudioClip clip, int iSamplePosition);\n\n        extern public static int GetSampleCount(AudioClip clip);\n        extern public static int GetChannelCount(AudioClip clip);\n        extern public static int GetBitRate(AudioClip clip);\n        extern public static int GetBitsPerSample(AudioClip clip);\n        extern public static int GetFrequency(AudioClip clip);\n        extern public static int GetSoundSize(AudioClip clip);\n        extern public static AudioCompressionFormat GetSoundCompressionFormat(AudioClip clip);\n        extern public static AudioCompressionFormat GetTargetPlatformSoundCompressionFormat(AudioClip clip);\n\n        extern public static bool canUseSpatializerEffect\n        {\n            [FreeFunction(Name = \"GetAudioManager().CanUseSpatializerEffect\")]\n            get;\n        }\n\n        extern public static string[] GetAmbisonicDecoderPluginNames();\n        extern public static bool HasPreview(AudioClip clip);\n        extern public static AudioImporter GetImporterFromClip(AudioClip clip);\n        extern public static float[] GetMinMaxData(AudioImporter importer);\n        extern public static double GetDuration(AudioClip clip);\n\n        [FreeFunction(Name = \"GetAudioManager().GetMemoryAllocated\")]\n        extern public static int GetFMODMemoryAllocated();\n\n        [FreeFunction(Name = \"GetAudioManager().GetCPUUsage\")]\n        extern public static float GetFMODCPUUsage();\n\n        extern public static bool IsTrackerFile(AudioClip clip);\n        extern public static int GetMusicChannelCount(AudioClip clip);\n\n        extern public static AnimationCurve GetLowpassCurve(AudioLowPassFilter lowPassFilter);\n        extern public static Vector3 GetListenerPos();\n        extern public static void UpdateAudio();\n        extern public static void SetListenerTransform(Transform t);\n\n        extern public static bool HasAudioCallback(MonoBehaviour behaviour);\n\n        extern public static int GetCustomFilterChannelCount(MonoBehaviour behaviour);\n        extern public static int GetCustomFilterProcessTime(MonoBehaviour behaviour);\n        extern public static float GetCustomFilterMaxIn(MonoBehaviour behaviour, int channel);\n        extern public static float GetCustomFilterMaxOut(MonoBehaviour behaviour, int channel);\n\n        extern internal static void SetProfilerShowAllGroups(bool value);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Effects/AudioCurveRendering.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditor\n{\n    public class AudioCurveRendering\n    {\n        // This slight adjustment is needed to make sure that numerical imprecision doesn't suddenly snap to the wrong pixel (causing vertical gaps and overdrawn lines)\n        private static float pixelEpsilon = 0.005f;\n\n        public delegate float AudioCurveEvaluator(float x);\n        public delegate float AudioCurveAndColorEvaluator(float x, out Color col);\n        public delegate void AudioMinMaxCurveAndColorEvaluator(float x, out Color col, out float minValue, out float maxValue);\n        public static readonly Color kAudioOrange = new Color(255 / 255f, 168 / 255f, 7 / 255f);\n\n        // -------------\n        // Frame, background and clipping utils\n        // -------------\n\n        // Returns the content rect (clipped)\n        public static Rect BeginCurveFrame(Rect r)\n        {\n            DrawCurveBackground(r);\n\n            // Frame is subtracted from rect\n            r = DrawCurveFrame(r);\n\n            // Content is clipped with group\n            GUI.BeginGroup(r);\n            return new Rect(0, 0, r.width, r.height);\n        }\n\n        public static void EndCurveFrame()\n        {\n            GUI.EndGroup();\n        }\n\n        // Returns content rect\n        public static Rect DrawCurveFrame(Rect r)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return r;\n\n            EditorStyles.colorPickerBox.Draw(r, false, false, false, false);\n\n            // Adjust rect for frame: colorPickerBox style has 1 px border\n            r.x += 1f;\n            r.y += 1f;\n            r.width -= 2f;\n            r.height -= 2f;\n            return r;\n        }\n\n        public static void DrawCurveBackground(Rect r)\n        {\n            EditorGUI.DrawRect(r, new Color(0.3f, 0.3f, 0.3f));\n        }\n\n        // -------------\n        // Curve rendering -- do not remove any of these, as they may be used by custom GUIs of native audio plugins\n        // -------------\n\n        public static void DrawFilledCurve(Rect r, AudioCurveEvaluator eval, Color curveColor)\n        {\n            DrawFilledCurve(\n                r,\n                delegate(float x, out Color color)\n                {\n                    color = curveColor;\n                    return eval(x);\n                }\n            );\n        }\n\n        public static void DrawFilledCurve(Rect r, AudioCurveAndColorEvaluator eval)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            HandleUtility.ApplyWireMaterial();\n\n            GL.Begin(GL.LINES);\n\n            // Adjust by a half pixel to each side so that the transition covers a full pixel.\n            // This is needed for very slowly rising edges.\n            float pixelScale = (float)EditorGUIUtility.pixelsPerPoint;\n            float pixelSize = 1.0f / pixelScale;\n            float pixelHalfSize = 0.5f * pixelSize;\n            float pixelWidth = Mathf.Ceil(r.width) * pixelScale;\n            float startx = Mathf.Floor(r.x) + pixelEpsilon;\n            float wx = 1.0f / (float)(pixelWidth - 1);\n            float cy = r.height * 0.5f;\n            float my = r.y + 0.5f * r.height;\n            float y1 = r.y + r.height;\n            Color color;\n\n            float py = Mathf.Clamp(cy * eval(0.0f, out color), -cy, cy);\n            for (int x = 0; x < pixelWidth; x++)\n            {\n                float nx = startx + x * pixelSize;\n                float ny = Mathf.Clamp(cy * eval(x * wx, out color), -cy, cy);\n                float e1 = Mathf.Min(ny, py) - pixelHalfSize;\n                float e2 = Mathf.Max(ny, py) + pixelHalfSize;\n                GL.Color(new Color(color.r, color.g, color.b, 0.0f));\n                AudioMixerDrawUtils.Vertex(nx, my - e2);\n                GL.Color(color);\n                AudioMixerDrawUtils.Vertex(nx, my - e1);\n                AudioMixerDrawUtils.Vertex(nx, my - e1);\n                AudioMixerDrawUtils.Vertex(nx, y1);\n                py = ny;\n            }\n\n            GL.End();\n        }\n\n        // Enforces minValue <= maxValue\n        private static void Sort2(ref float minValue, ref float maxValue)\n        {\n            if (minValue > maxValue)\n            {\n                float tmp = minValue;\n                minValue = maxValue;\n                maxValue = tmp;\n            }\n        }\n\n        public static void DrawMinMaxFilledCurve(Rect r, AudioMinMaxCurveAndColorEvaluator eval)\n        {\n            HandleUtility.ApplyWireMaterial();\n            DrawMinMaxFilledCurveInternal(r, eval);\n        }\n\n        internal static void DrawMinMaxFilledCurveInternal(Rect r, AudioMinMaxCurveAndColorEvaluator eval)\n        {\n            GL.Begin(GL.LINES);\n\n            // Adjust by a half pixel to each side so that the transition covers a full pixel.\n            // This is needed for very slowly rising edges.\n            float pixelScale = (float)EditorGUIUtility.pixelsPerPoint;\n            float pixelSize = 1.0f / pixelScale;\n            float pixelHalfSize = 0.5f * pixelSize;\n            float pixelWidth = Mathf.Ceil(r.width) * pixelScale;\n            float startx = Mathf.Floor(r.x) + pixelEpsilon;\n            float wx = 1.0f / (float)(pixelWidth - 1);\n            float cy = r.height * 0.5f;\n            float my = r.y + 0.5f * r.height;\n            float minValue, maxValue;\n            Color color;\n            eval(0.0001f, out color, out minValue, out maxValue); Sort2(ref minValue, ref maxValue);\n            float pyMax = my - cy * Mathf.Clamp(maxValue, -1.0f, 1.0f);\n            float pyMin = my - cy * Mathf.Clamp(minValue, -1.0f, 1.0f);\n            float y1 = r.y, y2 = r.y + r.height;\n            for (int x = 0; x < pixelWidth; x++)\n            {\n                float nx = startx + x * pixelSize;\n                eval(x * wx, out color, out minValue, out maxValue); Sort2(ref minValue, ref maxValue);\n                Color edgeColor = new Color(color.r, color.g, color.b, 0.0f);\n                float nyMax = my - cy * Mathf.Clamp(maxValue, -1.0f, 1.0f);\n                float nyMin = my - cy * Mathf.Clamp(minValue, -1.0f, 1.0f);\n                float a = Mathf.Clamp(Mathf.Min(nyMax, pyMax) - pixelHalfSize, y1, y2);\n                float b = Mathf.Clamp(Mathf.Max(nyMax, pyMax) + pixelHalfSize, y1, y2);\n                float c = Mathf.Clamp(Mathf.Min(nyMin, pyMin) - pixelHalfSize, y1, y2);\n                float d = Mathf.Clamp(Mathf.Max(nyMin, pyMin) + pixelHalfSize, y1, y2);\n                Sort2(ref a, ref c); Sort2(ref b, ref d); Sort2(ref a, ref b); Sort2(ref c, ref d); Sort2(ref b, ref c);\n                GL.Color(edgeColor);\n                AudioMixerDrawUtils.Vertex(nx, a);\n                GL.Color(color);\n                AudioMixerDrawUtils.Vertex(nx, b);\n                AudioMixerDrawUtils.Vertex(nx, b);\n                AudioMixerDrawUtils.Vertex(nx, c);\n                AudioMixerDrawUtils.Vertex(nx, c);\n                GL.Color(edgeColor);\n                AudioMixerDrawUtils.Vertex(nx, d);\n                pyMin = nyMin;\n                pyMax = nyMax;\n            }\n\n            GL.End();\n        }\n\n        public static void DrawSymmetricFilledCurve(Rect r, AudioCurveAndColorEvaluator eval)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            HandleUtility.ApplyWireMaterial();\n\n            GL.Begin(GL.LINES);\n\n            // Adjust by a half pixel to each side so that the transition covers a full pixel.\n            // This is needed for very slowly rising edges.\n            float pixelScale = (float)EditorGUIUtility.pixelsPerPoint;\n            float pixelSize = 1.0f / pixelScale;\n            float pixelHalfSize = 0.5f * pixelSize;\n            float pixelWidth = Mathf.Ceil(r.width) * pixelScale;\n            float startx = Mathf.Floor(r.x) + pixelEpsilon;\n            float wx = 1.0f / (float)(pixelWidth - 1);\n            float cy = r.height * 0.5f;\n            float my = r.y + 0.5f * r.height;\n            Color color;\n\n            float py = Mathf.Clamp(cy * eval(0.0001f, out color), 0.0f, cy);\n            for (int x = 0; x < pixelWidth; x++)\n            {\n                float nx = startx + x * pixelSize;\n                float ny = Mathf.Clamp(cy * eval(x * wx, out color), 0.0f, cy);\n                float e1 = Mathf.Max(Mathf.Min(ny, py) - pixelHalfSize, 0.0f); // Avoid self-intersection\n                float e2 = Mathf.Min(Mathf.Max(ny, py) + pixelHalfSize, cy);\n                Color edgeColor = new Color(color.r, color.g, color.b, 0.0f);\n                GL.Color(edgeColor);\n                AudioMixerDrawUtils.Vertex(nx, my - e2);\n                GL.Color(color);\n                AudioMixerDrawUtils.Vertex(nx, my - e1);\n                AudioMixerDrawUtils.Vertex(nx, my - e1);\n                AudioMixerDrawUtils.Vertex(nx, my + e1);\n                AudioMixerDrawUtils.Vertex(nx, my + e1);\n                GL.Color(edgeColor);\n                AudioMixerDrawUtils.Vertex(nx, my + e2);\n                py = ny;\n            }\n\n            GL.End();\n        }\n\n        public static void DrawCurve(Rect r, AudioCurveEvaluator eval, Color curveColor)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            HandleUtility.ApplyWireMaterial();\n\n            int numpoints = (int)Mathf.Ceil(r.width);\n            float cy = r.height * 0.5f;\n            float ws = 1.0f / (numpoints - 1);\n            var line = GetPointCache(numpoints);\n            for (int n = 0; n < numpoints; n++)\n            {\n                line[n].x = (int)n + r.x;\n                line[n].y = cy - cy * eval(n * ws) + r.y;\n                line[n].z = 0.0f;\n            }\n\n            GUI.BeginClip(r);\n            Handles.color = curveColor;\n            Handles.DrawAAPolyLine(3.0f, numpoints, line);\n            GUI.EndClip();\n        }\n\n        static Vector3[] s_PointCache;\n        static Vector3[] GetPointCache(int numPoints)\n        {\n            if (s_PointCache == null || s_PointCache.Length != numPoints)\n            {\n                s_PointCache = new Vector3[numPoints];\n            }\n            return s_PointCache;\n        }\n\n        // -------------\n        // Curve gradient rect\n        // -------------\n\n        public static void DrawGradientRect(Rect r, Color c1, Color c2, float blend, bool horizontal)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n            HandleUtility.ApplyWireMaterial();\n            GL.Begin(GL.QUADS);\n            if (horizontal)\n            {\n                GL.Color(new Color(c1.r, c1.g, c1.b, c1.a * blend));\n                GL.Vertex3(r.x, r.y, 0);\n                GL.Vertex3(r.x + r.width, r.y, 0);\n                GL.Color(new Color(c2.r, c2.g, c2.b, c2.a * blend));\n                GL.Vertex3(r.x + r.width, r.y + r.height, 0);\n                GL.Vertex3(r.x, r.y + r.height, 0);\n            }\n            else\n            {\n                GL.Color(new Color(c1.r, c1.g, c1.b, c1.a * blend));\n                GL.Vertex3(r.x, r.y + r.height, 0);\n                GL.Vertex3(r.x, r.y, 0);\n                GL.Color(new Color(c2.r, c2.g, c2.b, c2.a * blend));\n                GL.Vertex3(r.x + r.width, r.y, 0);\n                GL.Vertex3(r.x + r.width, r.y + r.height, 0);\n            }\n            GL.End();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Effects/AudioMixerEffectPlugin.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor.Audio\n{\n    public class AudioMixerEffectPlugin : IAudioEffectPlugin\n    {\n        internal AudioMixerController m_Controller;\n        internal AudioMixerEffectController m_Effect;\n        internal MixerParameterDefinition[] m_ParamDefs;\n\n        static bool s_ParameterChangeUndoIsRecorded;\n        static bool s_ParameterChangeUndoGroupNameIsSet;\n\n        static readonly Dictionary<string, float> k_UpdatedParameterMap = new Dictionary<string, float>();\n\n        readonly HashSet<string> m_VerifiedParameters = new HashSet<string>();\n\n        public override bool SetFloatParameter(string name, float value)\n        {\n            if (!HasParameter(name))\n            {\n                return false;\n            }\n\n            GetFloatParameter(name, out var previousValue);\n\n            if (Mathf.Approximately(value, previousValue))\n            {\n                return true;\n            }\n\n            if (k_UpdatedParameterMap.Count == 0 && !s_ParameterChangeUndoIsRecorded)\n            {\n                Undo.RecordObject(m_Controller.TargetSnapshot, $\"Change {name}\");\n            }\n\n            k_UpdatedParameterMap[name] = value;\n\n            if (k_UpdatedParameterMap.Count > 1 && !s_ParameterChangeUndoGroupNameIsSet)\n            {\n                Undo.SetCurrentGroupName(\"Change Effect Parameters\");\n                s_ParameterChangeUndoGroupNameIsSet = true;\n            }\n\n            m_Effect.SetValueForParameter(m_Controller, m_Controller.TargetSnapshot, name, value);\n\n            return true;\n        }\n\n        public override bool GetFloatParameter(string name, out float value)\n        {\n            if (!HasParameter(name))\n            {\n                value = default;\n\n                return false;\n            }\n\n            if (k_UpdatedParameterMap.TryGetValue(name, out value))\n            {\n                return true;\n            }\n\n            value = m_Effect.GetValueForParameter(m_Controller, m_Controller.TargetSnapshot, name);\n\n            return true;\n        }\n\n        public override bool GetFloatParameterInfo(string name, out float minRange, out float maxRange, out float defaultValue)\n        {\n            foreach (var p in m_ParamDefs)\n            {\n                if (p.name == name)\n                {\n                    minRange = p.minRange;\n                    maxRange = p.maxRange;\n                    defaultValue = p.defaultValue;\n                    return true;\n                }\n            }\n\n            minRange = 0.0f;\n            maxRange = 1.0f;\n            defaultValue = 0.5f;\n            return false;\n        }\n\n        public override bool GetFloatBuffer(string name, out float[] data, int numsamples)\n        {\n            m_Effect.GetFloatBuffer(m_Controller, name, out data, numsamples);\n            return true;\n        }\n\n        public override int GetSampleRate()\n        {\n            return AudioSettings.outputSampleRate;\n        }\n\n        public override bool IsPluginEditableAndEnabled()\n        {\n            return AudioMixerController.EditingTargetSnapshot() && !m_Effect.bypass;\n        }\n\n        // Call this after each interaction that changes effect parameters.\n        // NOTE: It is assumed that parameter changes can only happen on a single effect at a time.\n        internal static void OnParameterChangesDone()\n        {\n            k_UpdatedParameterMap.Clear();\n            s_ParameterChangeUndoIsRecorded = false;\n            s_ParameterChangeUndoGroupNameIsSet = false;\n        }\n\n        bool HasParameter(string name)\n        {\n            if (m_VerifiedParameters.Contains(name))\n            {\n                return true;\n            }\n\n            for (var i = 0; i < m_ParamDefs.Length; ++i)\n            {\n                if (m_ParamDefs[i].name.Equals(name))\n                {\n                    m_VerifiedParameters.Add(name);\n                    return true;\n                }\n            }\n\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Effects/Complex.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditor\n{\n    // System.Numerics is not available\n    internal class ComplexD\n    {\n        public double real;\n        public double imag;\n\n        public ComplexD(double real, double imag)\n        {\n            this.real = real;\n            this.imag = imag;\n        }\n\n        static public ComplexD Add(ComplexD a, ComplexD b)\n        {\n            return new ComplexD(\n                a.real + b.real,\n                a.imag + b.imag);\n        }\n\n        static public ComplexD Add(ComplexD a, double b)\n        {\n            return new ComplexD(\n                a.real + b,\n                a.imag);\n        }\n\n        static public ComplexD Add(double a, ComplexD b)\n        {\n            return new ComplexD(\n                a + b.real,\n                b.imag);\n        }\n\n        static public ComplexD Sub(ComplexD a, ComplexD b)\n        {\n            return new ComplexD(\n                a.real - b.real,\n                a.imag - b.imag);\n        }\n\n        static public ComplexD Sub(ComplexD a, double b)\n        {\n            return new ComplexD(\n                a.real - b,\n                a.imag);\n        }\n\n        static public ComplexD Sub(double a, ComplexD b)\n        {\n            return new ComplexD(\n                a - b.real,\n                -b.imag);\n        }\n\n        static public ComplexD Mul(ComplexD a, ComplexD b)\n        {\n            return new ComplexD(\n                a.real * b.real - a.imag * b.imag,\n                a.real * b.imag + a.imag * b.real);\n        }\n\n        static public ComplexD Mul(ComplexD a, double b)\n        {\n            return new ComplexD(\n                a.real * b,\n                a.imag * b);\n        }\n\n        static public ComplexD Mul(double a, ComplexD b)\n        {\n            return new ComplexD(\n                a * b.real,\n                a * b.imag);\n        }\n\n        static public ComplexD Div(ComplexD a, ComplexD b)\n        {\n            double d = b.real * b.real + b.imag * b.imag;\n            double s = 1.0 / d;\n            return new ComplexD(\n                (a.real * b.real + a.imag * b.imag) * s,\n                (a.imag * b.real - a.real * b.imag) * s);\n        }\n\n        static public ComplexD Div(double a, ComplexD b)\n        {\n            double d = b.real * b.real + b.imag * b.imag;\n            double s = a / d;\n            return new ComplexD(\n                s * b.real,\n                -s * b.imag);\n        }\n\n        static public ComplexD Div(ComplexD a, double b)\n        {\n            double s = 1.0 / b;\n            return new ComplexD(\n                a.real * s,\n                a.imag * s);\n        }\n\n        static public ComplexD Exp(double omega)\n        {\n            return new ComplexD(\n                Math.Cos(omega),\n                Math.Sin(omega));\n        }\n\n        static public ComplexD Pow(ComplexD a, double b)\n        {\n            double p = Math.Atan2(a.imag, a.real);\n            double m = Math.Pow(a.Mag2(), b * 0.5f);\n            return new ComplexD(\n                m * Math.Cos(p * b),\n                m * Math.Sin(p * b)\n            );\n        }\n\n        public double Mag2() { return real * real + imag * imag; }\n        public double Mag() { return Math.Sqrt(Mag2()); }\n\n        public static ComplexD operator+(ComplexD a, ComplexD b) { return Add(a, b); }\n        public static ComplexD operator-(ComplexD a, ComplexD b) { return Sub(a, b); }\n        public static ComplexD operator*(ComplexD a, ComplexD b) { return Mul(a, b); }\n        public static ComplexD operator/(ComplexD a, ComplexD b) { return Div(a, b); }\n        public static ComplexD operator+(ComplexD a, double b) { return Add(a, b); }\n        public static ComplexD operator-(ComplexD a, double b) { return Sub(a, b); }\n        public static ComplexD operator*(ComplexD a, double b) { return Mul(a, b); }\n        public static ComplexD operator/(ComplexD a, double b) { return Div(a, b); }\n        public static ComplexD operator+(double a, ComplexD b) { return Add(a, b); }\n        public static ComplexD operator-(double a, ComplexD b) { return Sub(a, b); }\n        public static ComplexD operator*(double a, ComplexD b) { return Mul(a, b); }\n        public static ComplexD operator/(double a, ComplexD b) { return Div(a, b); }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Effects/DuckVolumeGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n//#define DEBUG_PLOT_GAIN\n\nusing System;\nusing System.Globalization;\nusing UnityEditor.Audio;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class DuckVolumeGUI : IAudioEffectPluginGUI\n    {\n        public static string kThresholdName = \"Threshold\";\n        public static string kRatioName = \"Ratio\";\n        public static string kMakeupGainName = \"Make-up Gain\";\n        public static string kAttackTimeName = \"Attack Time\";\n        public static string kReleaseTimeName = \"Release Time\";\n        public static string kKneeName = \"Knee\";\n\n        public override string Name\n        {\n            get { return \"Duck Volume\"; }\n        }\n\n        public override string Description\n        {\n            get { return \"Volume Ducking\"; }\n        }\n\n        public override string Vendor\n        {\n            get { return \"Unity Technologies\"; }\n        }\n\n        public static GUIStyle BuildGUIStyleForLabel(Color color, int fontSize, bool wrapText, FontStyle fontstyle, TextAnchor anchor)\n        {\n            GUIStyle style = new GUIStyle();\n            style.focused.background = style.onNormal.background;\n            style.focused.textColor = color;\n            style.alignment = anchor;\n            style.fontSize = fontSize;\n            style.fontStyle = fontstyle;\n            style.wordWrap = wrapText;\n            style.clipping = TextClipping.Overflow;\n            style.normal.textColor = color;\n            return style;\n        }\n\n        public static GUIStyle textStyle10 = BuildGUIStyleForLabel(Color.grey, 10, false, FontStyle.Normal, TextAnchor.MiddleLeft);\n\n        public static void DrawText(float x, float y, string text)\n        {\n            GUI.Label(new Rect(x, y - 5, 200, 10), new GUIContent(text, \"\"), textStyle10);\n        }\n\n        public static void DrawLine(float x1, float y1, float x2, float y2, Color col)\n        {\n            Handles.color = col;\n            Handles.DrawLine(new Vector3(x1, y1, 0), new Vector3(x2, y2, 0));\n        }\n\n        public enum DragType\n        {\n            None,\n            ThresholdAndKnee,\n            Ratio,\n            MakeupGain,\n        }\n\n        static DragType dragtype = DragType.None;\n\n        protected static Color ScaleAlpha(Color col, float blend)\n        {\n            return new Color(col.r, col.g, col.b, col.a * blend);\n        }\n\n        protected static void DrawVU(Rect r, float level, float blend, bool topdown)\n        {\n            level = 1.0f - level;\n            const float border = 1;\n            var r2 = new Rect(r.x + border, r.y + border + (topdown ? 0.0f : level * r.height), r.width - 2 * border, r.y - 2 * border + (topdown ? level * r.height : r.height - level * r.height));\n            AudioMixerDrawUtils.DrawRect(r, new Color(0.1f, 0.1f, 0.1f));\n            AudioMixerDrawUtils.DrawRect(r2, new Color(0.6f, 0.2f, 0.2f));\n        }\n\n        // Input: normalized x value [0;1]. Returns: normalized y value [-1;-1]\n        static float EvaluateDuckingVolume(float x, float ratio, float threshold, float makeupGain, float knee, float dbRange, float dbMin)\n        {\n            float duckGradient = 1.0f / ratio;\n            float duckThreshold = threshold;\n            float duckMakeupGain = makeupGain;\n            float duckKnee = knee;\n            float duckKneeC1 = (knee > 0.0f) ? ((duckGradient - 1.0f) / (4.0f * knee)) : 0.0f;\n            float duckKneeC2 = duckThreshold - knee;\n\n            float level = x * dbRange + dbMin;\n            float gain = level;\n            float t = level - duckThreshold;\n            if (t > -duckKnee && t < duckKnee)\n            {\n                t += duckKnee;\n                gain = t * (duckKneeC1 * t + 1.0f) + duckKneeC2;\n            }\n            else if (t > 0.0f)\n                gain = duckThreshold + duckGradient * t;\n\n            return (2.0f * (gain + duckMakeupGain - dbMin) / dbRange) - 1.0f;\n        }\n\n        static bool CurveDisplay(IAudioEffectPlugin plugin, Rect r0, ref float threshold, ref float ratio, ref float makeupGain, ref float attackTime, ref float releaseTime, ref float knee, float sidechainLevel, float outputLevel, float blend)\n        {\n            Event evt = Event.current;\n            int controlID = GUIUtility.GetControlID(FocusType.Passive);\n\n            Rect r = AudioCurveRendering.BeginCurveFrame(r0);\n\n            const float thresholdActiveWidth = 10f;\n            float vuWidth = 10f;\n\n            float minThreshold, maxThreshold, defThreshold;\n            plugin.GetFloatParameterInfo(kThresholdName, out minThreshold, out maxThreshold, out defThreshold);\n            float minRatio, maxRatio, defRatio;\n            plugin.GetFloatParameterInfo(kRatioName, out minRatio, out maxRatio, out defRatio);\n            float minMakeupGain, maxMakeupGain, defMakeupGain;\n            plugin.GetFloatParameterInfo(kMakeupGainName, out minMakeupGain, out maxMakeupGain, out defMakeupGain);\n            float minKnee, maxKnee, defKnee;\n            plugin.GetFloatParameterInfo(kKneeName, out minKnee, out maxKnee, out defKnee);\n\n            float dbRange = 100.0f, dbMin = -80.0f;\n            float thresholdPosX = r.width * (threshold - dbMin) / dbRange;\n\n            bool modifiedValue = false;\n            switch (evt.GetTypeForControl(controlID))\n            {\n                case EventType.MouseDown:\n                    if (r.Contains(Event.current.mousePosition) && evt.button == 0)\n                    {\n                        dragtype = DragType.None;\n                        GUIUtility.hotControl = controlID;\n                        EditorGUIUtility.SetWantsMouseJumping(1);\n                        evt.Use();\n\n                        // Ensure visible state change on mousedown to make it clear that interaction is possible\n                        if ((Mathf.Abs(r.x + thresholdPosX - evt.mousePosition.x) >= thresholdActiveWidth))\n                            dragtype = (evt.mousePosition.x < r.x + thresholdPosX) ? DragType.MakeupGain : DragType.Ratio;\n                        else\n                            dragtype = DragType.ThresholdAndKnee;\n                    }\n\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == controlID && evt.button == 0)\n                    {\n                        dragtype = DragType.None;\n                        GUIUtility.hotControl = 0;\n                        EditorGUIUtility.SetWantsMouseJumping(0);\n                        evt.Use();\n                        AudioMixerEffectPlugin.OnParameterChangesDone();\n                    }\n\n                    break;\n\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == controlID)\n                    {\n                        float dragAcceleration = evt.alt ? .25f : 1f;\n                        if (dragtype == DragType.ThresholdAndKnee)\n                        {\n                            bool dragKnee = Mathf.Abs(evt.delta.x) < Mathf.Abs(evt.delta.y);\n                            if (dragKnee)\n                                knee = Mathf.Clamp(knee + evt.delta.y * 0.5f * dragAcceleration, minKnee, maxKnee);\n                            else\n                                threshold = Mathf.Clamp(threshold + evt.delta.x * 0.1f * dragAcceleration, minThreshold, maxThreshold);\n                        }\n                        else if (dragtype == DragType.Ratio)\n                            ratio = Mathf.Clamp(ratio + evt.delta.y * (ratio > 1.0f ? 0.05f : 0.003f) * dragAcceleration, minRatio, maxRatio);\n                        else if (dragtype == DragType.MakeupGain)\n                            makeupGain = Mathf.Clamp(makeupGain - evt.delta.y * 0.5f * dragAcceleration, minMakeupGain, maxMakeupGain);\n                        else\n                        {\n                            Debug.LogError(\"Drag: Unhandled enum\");\n                        }\n\n                        modifiedValue = true;\n                        evt.Use();\n                    }\n\n                    break;\n            }\n\n            if (evt.type == EventType.Repaint)\n            {\n                // Curve\n                HandleUtility.ApplyWireMaterial();\n\n                //float sidechainPosX = r.width * (sidechainLevel - dbMin) / dbRange;\n                float thresholdPosY = r.height * (1.0f - ((threshold - dbMin + makeupGain) / dbRange));\n                Color thresholdColor = new Color(0.7f, 0.7f, 0.7f);\n                Color sidechainColor = Color.black;\n\n\n                float duckGradient = 1.0f / ratio;\n                float duckThreshold = threshold;\n                float duckSidechainLevel = sidechainLevel;\n                float duckMakeupGain = makeupGain;\n                float duckKnee = knee;\n                float duckKneeC1 = (knee > 0.0f) ? ((duckGradient - 1.0f) / (4.0f * knee)) : 0.0f;\n                float duckKneeC2 = duckThreshold - knee;\n\n                // Main filled curve\n                AudioCurveRendering.DrawFilledCurve(\n                    r,\n                    delegate(float x, out Color col)\n                    {\n                        float level = x * dbRange + dbMin;\n                        float gain = level;\n                        float t = level - duckThreshold;\n                        col = ScaleAlpha(duckSidechainLevel > level ? AudioCurveRendering.kAudioOrange : Color.grey, blend);\n                        if (t > -duckKnee && t < duckKnee)\n                        {\n                            t += duckKnee;\n                            gain = t * (duckKneeC1 * t + 1.0f) + duckKneeC2;\n\n                            if (dragtype == DragType.ThresholdAndKnee)\n                            {\n                                const float mult = 1.2f;\n                                col = new Color(col.r * mult, col.g * mult, col.b * mult);\n                            }\n                        }\n                        else if (t > 0.0f)\n                            gain = duckThreshold + duckGradient * t;\n\n                        return (2.0f * (gain + duckMakeupGain - dbMin) / dbRange) - 1.0f;\n                    }\n                );\n\n                // Curve shown when modifying MakeupGain\n                if (dragtype == DragType.MakeupGain)\n                {\n                    AudioCurveRendering.DrawCurve(\n                        r,\n                        delegate(float x)\n                        {\n                            float level = x * dbRange + dbMin;\n                            float gain = level;\n                            float t = level - duckThreshold;\n                            if (t > -duckKnee && t < duckKnee)\n                            {\n                                t += duckKnee;\n                                gain = t * (duckKneeC1 * t + 1.0f) + duckKneeC2;\n                            }\n                            else if (t > 0.0f)\n                                gain = duckThreshold + duckGradient * t;\n\n                            return (2.0f * (gain + duckMakeupGain - dbMin) / dbRange) - 1.0f;\n                        },\n                        Color.white\n                    );\n                }\n\n\n                // Threshold text and line\n                textStyle10.normal.textColor = ScaleAlpha(thresholdColor, blend);\n                EditorGUI.DrawRect(new Rect(r.x + thresholdPosX, r.y, 1, r.height), textStyle10.normal.textColor);\n                DrawText(r.x + thresholdPosX + 4, r.y + 6, string.Format(CultureInfo.InvariantCulture.NumberFormat, \"Threshold: {0:F1} dB\", threshold));\n\n                // Sidechain text and line\n                textStyle10.normal.textColor = ScaleAlpha(sidechainColor, blend);\n                DrawText(r.x + 4, r.y + r.height - 10, sidechainLevel < -80 ? \"Input: None\" : string.Format(CultureInfo.InvariantCulture.NumberFormat, \"Input: {0:F1} dB\", sidechainLevel));\n\n                if (dragtype == DragType.Ratio)\n                {\n                    float aspect = r.height / r.width;\n                    Handles.DrawAAPolyLine(2.0f,\n                        new[] { Color.black, Color.black },\n                        new[]\n                        {\n                            new Vector3(r.x + thresholdPosX + r.width, r.y + thresholdPosY - aspect * r.width, 0.0f),\n                            new Vector3(r.x + thresholdPosX - r.width, r.y + thresholdPosY + aspect * r.width, 0.0f)\n                        });\n                    Handles.DrawAAPolyLine(3.0f,\n                        new[] { Color.white, Color.white },\n                        new[]\n                        {\n                            new Vector3(r.x + thresholdPosX + r.width, r.y + thresholdPosY - aspect * duckGradient * r.width, 0.0f),\n                            new Vector3(r.x + thresholdPosX - r.width, r.y + thresholdPosY + aspect * duckGradient * r.width, 0.0f)\n                        });\n                }\n                else if (dragtype == DragType.ThresholdAndKnee)\n                {\n                    // Knee min and max lines\n                    float normalizedKnee1 = (threshold - knee - dbMin) / dbRange;\n                    float normalizedKnee2 = (threshold + knee - dbMin) / dbRange;\n                    float y1 = EvaluateDuckingVolume(normalizedKnee1, ratio, threshold, makeupGain, knee, dbRange, dbMin);\n                    float y2 = EvaluateDuckingVolume(normalizedKnee2, ratio, threshold, makeupGain, knee, dbRange, dbMin);\n                    float knee1PosY = r.yMax - (y1 + 1f) * 0.5f * r.height;\n                    float knee2PosY = r.yMax - (y2 + 1f) * 0.5f * r.height;\n                    EditorGUI.DrawRect(new Rect(r.x + normalizedKnee1 * r.width, knee1PosY, 1, r.height - knee1PosY), new Color(0, 0, 0, 0.5f));\n                    EditorGUI.DrawRect(new Rect(r.x + normalizedKnee2 * r.width - 1, knee2PosY, 1, r.height - knee2PosY), new Color(0, 0, 0, 0.5f));\n\n                    // Enhanced threshold\n                    EditorGUI.DrawRect(new Rect(r.x + thresholdPosX - 1, r.y, 3, r.height), Color.white);\n                }\n\n                outputLevel = (Mathf.Clamp(outputLevel - makeupGain, dbMin, dbMin + dbRange) - dbMin) / dbRange;\n                if (EditorApplication.isPlaying)\n                {\n                    const int margin = 2;\n                    Rect vuRect = new Rect(r.x + r.width - vuWidth + margin, r.y + margin, vuWidth - 2 * margin, r.height - 2 * margin);\n                    DrawVU(vuRect, outputLevel, blend, true);\n                }\n            }\n\n            AudioCurveRendering.EndCurveFrame();\n\n            return modifiedValue;\n        }\n\n        public override bool OnGUI(IAudioEffectPlugin plugin)\n        {\n            var blend = plugin.IsPluginEditableAndEnabled() ? 1.0f : 0.5f;\n\n            plugin.GetFloatParameter(kThresholdName, out var threshold);\n            plugin.GetFloatParameter(kRatioName, out var ratio);\n            plugin.GetFloatParameter(kMakeupGainName, out var makeupGain);\n            plugin.GetFloatParameter(kAttackTimeName, out var attackTime);\n            plugin.GetFloatParameter(kReleaseTimeName, out var releaseTime);\n            plugin.GetFloatParameter(kKneeName, out var knee);\n\n            plugin.GetFloatBuffer(\"Metering\", out var metering, 2);\n\n            GUILayout.Space(5f);\n\n            var r = GUILayoutUtility.GetRect(200, 160, GUILayout.ExpandWidth(true));\n\n            if (CurveDisplay(plugin, r, ref threshold, ref ratio, ref makeupGain, ref attackTime, ref releaseTime, ref knee, metering[0], metering[1], blend))\n            {\n                plugin.SetFloatParameter(kThresholdName, threshold);\n                plugin.SetFloatParameter(kRatioName, ratio);\n                plugin.SetFloatParameter(kMakeupGainName, makeupGain);\n                plugin.SetFloatParameter(kAttackTimeName, attackTime);\n                plugin.SetFloatParameter(kReleaseTimeName, releaseTime);\n                plugin.SetFloatParameter(kKneeName, knee);\n            }\n\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Effects/IAudioEffectPlugin.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditor\n{\n    public abstract class IAudioEffectPlugin\n    {\n        public abstract bool SetFloatParameter(string name, float value);\n        public abstract bool GetFloatParameter(string name, out float value);\n        public abstract bool GetFloatParameterInfo(string name, out float minRange, out float maxRange, out float defaultValue);\n        public abstract bool GetFloatBuffer(string name, out float[] data, int numsamples);\n        public abstract int GetSampleRate();\n        public abstract bool IsPluginEditableAndEnabled();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Effects/IAudioEffectPluginGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditor\n{\n    public abstract class IAudioEffectPluginGUI\n    {\n        public abstract string Name { get; }\n        public abstract string Description { get; }\n        public abstract string Vendor { get; }\n        public abstract bool OnGUI(IAudioEffectPlugin plugin);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Effects/ParamEQGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Globalization;\nusing UnityEditor.Audio;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class ParamEqGUI : IAudioEffectPluginGUI\n    {\n        public static string kCenterFreqName = \"Center freq\";\n        public static string kOctaveRangeName = \"Octave range\";\n        public static string kFrequencyGainName = \"Frequency gain\";\n\n        public override string Name\n        {\n            get { return \"ParamEQ\"; }\n        }\n\n        public override string Description\n        {\n            get { return \"Parametric equalizer\"; }\n        }\n\n        public override string Vendor\n        {\n            get { return \"Firelight Technologies\"; }\n        }\n\n        const bool useLogScale = true;\n\n        public static GUIStyle BuildGUIStyleForLabel(Color color, int fontSize, bool wrapText, FontStyle fontstyle, TextAnchor anchor)\n        {\n            GUIStyle style = new GUIStyle();\n            style.focused.background = style.onNormal.background;\n            style.focused.textColor = color;\n            style.alignment = anchor;\n            style.fontSize = fontSize;\n            style.fontStyle = fontstyle;\n            style.wordWrap = wrapText;\n            style.clipping = TextClipping.Overflow;\n            style.normal.textColor = color;\n            return style;\n        }\n\n        public static GUIStyle textStyle10 = BuildGUIStyleForLabel(Color.grey, 10, false, FontStyle.Normal, TextAnchor.MiddleCenter);\n\n        static void DrawFrequencyTickMarks(Rect r, float samplerate, bool logScale, Color col)\n        {\n            textStyle10.normal.textColor = col;\n            float px = r.x, w = 60.0f;\n            for (float normFreq = 0; normFreq < 1.0f; normFreq += 0.01f)\n            {\n                float f = (float)MapNormalizedFrequency(normFreq, samplerate, logScale, true);\n                float x = r.x + normFreq * r.width;\n                if (x - px > w)\n                {\n                    EditorGUI.DrawRect(new Rect(x, r.yMax - 5f, 1f, 5f), col);\n                    GUI.Label(new Rect(x, r.yMax - 22f, 1, 15f), (f < 1000.0f) ? string.Format(CultureInfo.InvariantCulture.NumberFormat, \"{0:F0} Hz\", f) : string.Format(CultureInfo.InvariantCulture.NumberFormat, \"{0:F0} kHz\", f * 0.001f), textStyle10);\n                    px = x;\n                }\n            }\n        }\n\n        protected static Color ScaleAlpha(Color col, float blend)\n        {\n            return new Color(col.r, col.g, col.b, col.a * blend);\n        }\n\n        // Maps from normalized frequency to real frequency\n        static double MapNormalizedFrequency(double f, double sr, bool useLogScale, bool forward)\n        {\n            double maxFreq = 0.5 * sr;\n            if (useLogScale)\n            {\n                const double lowestFreq = 10.0;\n                if (forward)\n                    return lowestFreq * Math.Pow(maxFreq / lowestFreq, f);\n                return Math.Log(f / lowestFreq) / Math.Log(maxFreq / lowestFreq);\n            }\n\n            return (forward) ? (f * maxFreq) : (f / maxFreq);\n        }\n\n        static bool ParamEqualizerCurveEditor(IAudioEffectPlugin plugin, Rect r, ref float centerFreq, ref float bandwidth, ref float gain, float blend)\n        {\n            Event evt = Event.current;\n            int controlID = GUIUtility.GetControlID(FocusType.Passive);\n\n            r = AudioCurveRendering.BeginCurveFrame(r);\n\n            float minCenterFreq, maxCenterFreq, defCenterFreq;\n            plugin.GetFloatParameterInfo(kCenterFreqName, out minCenterFreq, out maxCenterFreq, out defCenterFreq);\n            float minOctaveRange, maxOctaveRange, defOctaveRange;\n            plugin.GetFloatParameterInfo(kOctaveRangeName, out minOctaveRange, out maxOctaveRange, out defOctaveRange);\n            float minGain, maxGain, defGain;\n            plugin.GetFloatParameterInfo(kFrequencyGainName, out minGain, out maxGain, out defGain);\n\n            bool modifiedValue = false;\n            switch (evt.GetTypeForControl(controlID))\n            {\n                case EventType.MouseDown:\n                    if (r.Contains(Event.current.mousePosition) && evt.button == 0)\n                    {\n                        GUIUtility.hotControl = controlID;\n                        EditorGUIUtility.SetWantsMouseJumping(1);\n                        evt.Use();\n                    }\n\n                    break;\n\n                case EventType.MouseUp:\n                    // Signal\n                    if (GUIUtility.hotControl == controlID && evt.button == 0)\n                    {\n                        GUIUtility.hotControl = 0;\n                        EditorGUIUtility.SetWantsMouseJumping(0);\n                        evt.Use();\n                        AudioMixerEffectPlugin.OnParameterChangesDone();\n                    }\n\n                    break;\n\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == controlID)\n                    {\n                        float dragAcceleration = Event.current.alt ? .25f : 1f;\n                        centerFreq = Mathf.Clamp((float)MapNormalizedFrequency(MapNormalizedFrequency(centerFreq, plugin.GetSampleRate(), useLogScale, false) + evt.delta.x / r.width, plugin.GetSampleRate(), useLogScale, true), minCenterFreq, maxCenterFreq);\n                        if (Event.current.shift)\n                            bandwidth = Mathf.Clamp(bandwidth - evt.delta.y * 0.02f * dragAcceleration, minOctaveRange, maxOctaveRange);\n                        else\n                            gain = Mathf.Clamp(gain - evt.delta.y * 0.01f * dragAcceleration, minGain, maxGain);\n                        modifiedValue = true;\n                        evt.Use();\n                    }\n\n                    break;\n            }\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                // Mark CenterFreq with a vertical line\n                float c = (float)MapNormalizedFrequency(centerFreq, plugin.GetSampleRate(), useLogScale, false);\n                EditorGUI.DrawRect(new Rect(c * r.width + r.x, r.y, 1f, r.height), GUIUtility.hotControl == controlID ? new Color(0.6f, 0.6f, 0.6f) : new Color(0.4f, 0.4f, 0.4f));\n\n                // Curve\n                HandleUtility.ApplyWireMaterial();\n                double kPI = 3.1415926;\n                double wm = -2.0f * kPI / plugin.GetSampleRate();\n                double w0 = 2.0 * kPI * centerFreq / plugin.GetSampleRate();\n                double Q = 1.0 / bandwidth;\n                double A = gain;\n                double alpha = Math.Sin(w0) / (2.0 * Q);\n                double b0 = 1.0 + alpha * A;\n                double b1 = -2.0 * Math.Cos(w0);\n                double b2 = 1.0 - alpha * A;\n                double a0 = 1.0 + alpha / A;\n                double a1 = -2.0 * Math.Cos(w0);\n                double a2 = 1.0 - alpha / A;\n                AudioCurveRendering.DrawCurve(\n                    r,\n                    delegate(float x)\n                    {\n                        double f = MapNormalizedFrequency(x, plugin.GetSampleRate(), useLogScale, true);\n                        ComplexD w = ComplexD.Exp(wm * f);\n                        ComplexD n = w * (w * b2 + b1) + b0;\n                        ComplexD d = w * (w * a2 + a1) + a0;\n                        ComplexD h = n / d;\n                        double mag = Math.Log10(h.Mag2());\n                        return (float)(0.5 * mag); // 20 dB range\n                    },\n                    ScaleAlpha(AudioCurveRendering.kAudioOrange, blend)\n                );\n            }\n\n            DrawFrequencyTickMarks(r, plugin.GetSampleRate(), useLogScale, new Color(1.0f, 1.0f, 1.0f, 0.3f * blend));\n\n            AudioCurveRendering.EndCurveFrame();\n\n            return modifiedValue;\n        }\n\n        public override bool OnGUI(IAudioEffectPlugin plugin)\n        {\n            var blend = plugin.IsPluginEditableAndEnabled() ? 1.0f : 0.5f;\n\n            plugin.GetFloatParameter(kCenterFreqName, out var centerFreq);\n            plugin.GetFloatParameter(kOctaveRangeName, out var octaveRange);\n            plugin.GetFloatParameter(kFrequencyGainName, out var frequencyGain);\n\n            GUILayout.Space(5f);\n\n            var r = GUILayoutUtility.GetRect(200, 100, GUILayout.ExpandWidth(true));\n\n            if (ParamEqualizerCurveEditor(plugin, r, ref centerFreq, ref octaveRange, ref frequencyGain, blend))\n            {\n                plugin.SetFloatParameter(kCenterFreqName, centerFreq);\n                plugin.SetFloatParameter(kOctaveRangeName, octaveRange);\n                plugin.SetFloatParameter(kFrequencyGainName, frequencyGain);\n            }\n\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/AudioMixerDescription.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System;\nusing System.Collections.Generic;\n\n//FIXME: change this to nested namespaces when we merge in trunk\nnamespace UnityEditor.Audio\n{\n    internal class MixerEffectDefinition\n    {\n        public MixerEffectDefinition(string name, MixerParameterDefinition[] parameters)\n        {\n            this.m_EffectName = name;\n            this.m_Parameters = new MixerParameterDefinition[parameters.Length];\n            Array.Copy(parameters, this.m_Parameters, parameters.Length);\n        }\n\n        public string name\n        {\n            get { return this.m_EffectName; }\n        }\n\n        public MixerParameterDefinition[] parameters\n        {\n            get { return this.m_Parameters; }\n        }\n\n        private readonly string m_EffectName;\n        //TODO: GUI callback\n        private readonly MixerParameterDefinition[] m_Parameters;\n    }\n\n\n    [InitializeOnLoad]\n    static class MixerEffectDefinitionReloader\n    {\n        // We use this class with InitializeOnLoad attribute for ensuring MixerEffectDefinitions are refreshed\n        // when needed: 1) At startup, 2) after script recompile and 3) when project changes (new effects can have been added)\n        static MixerEffectDefinitionReloader()\n        {\n            MixerEffectDefinitions.Refresh();\n\n            EditorApplication.projectChanged += OnProjectChanged;\n        }\n\n        static void OnProjectChanged()\n        {\n            MixerEffectDefinitions.Refresh();\n        }\n    }\n\n\n    internal sealed partial class MixerEffectDefinitions\n    {\n        public static void Refresh()\n        {\n            ClearDefinitions();\n\n            RegisterAudioMixerEffect(\"Attenuation\", new MixerParameterDefinition[0]);\n\n            RegisterAudioMixerEffect(\"Send\", new MixerParameterDefinition[0]);\n\n            RegisterAudioMixerEffect(\"Receive\", new MixerParameterDefinition[0]);\n\n            var duckVolDef = new MixerParameterDefinition[7];\n            duckVolDef[0] = new MixerParameterDefinition { name = \"Threshold\", units = \"dB\", displayScale = 1.0f, displayExponent = 1.0f, minRange = -80.0f, maxRange = 0.0f, defaultValue = -10.0f, description = \"Threshold of side-chain level detector\" };\n            duckVolDef[1] = new MixerParameterDefinition { name = \"Ratio\", units = \"%\", displayScale = 100.0f, displayExponent = 1.0f, minRange = 0.2f, maxRange = 10.0f, defaultValue = 2.0f, description = \"Ratio of compression applied when side-chain signal exceeds threshold\" };\n            duckVolDef[2] = new MixerParameterDefinition { name = \"Attack Time\", units = \"ms\", displayScale = 1000.0f, displayExponent = 3.0f, minRange = 0.0f, maxRange = 10.0f, defaultValue = 0.1f, description = \"Level detector attack time\" };\n            duckVolDef[3] = new MixerParameterDefinition { name = \"Release Time\", units = \"ms\", displayScale = 1000.0f, displayExponent = 3.0f, minRange = 0.0f, maxRange = 10.0f, defaultValue = 0.1f, description = \"Level detector release time\" };\n            duckVolDef[4] = new MixerParameterDefinition { name = \"Make-up Gain\", units = \"dB\", displayScale = 1.0f, displayExponent = 1.0f, minRange = -80.0f, maxRange = 40.0f, defaultValue = 0.0f, description = \"Make-up gain\" };\n            duckVolDef[5] = new MixerParameterDefinition { name = \"Knee\", units = \"dB\", displayScale = 1.0f, displayExponent = 1.0f, minRange = 0.0f, maxRange = 50.0f, defaultValue = 10.0f, description = \"Sharpness of compression curve knee\" };\n            duckVolDef[6] = new MixerParameterDefinition { name = \"Sidechain Mix\", units = \"%\", displayScale = 100.0f, displayExponent = 1.0f, minRange = 0.0f, maxRange = 1.0f, defaultValue = 1.0f, description = \"Sidechain/source mix. If set to 100% the compressor detects level entirely from sidechain signal.\" };\n            RegisterAudioMixerEffect(\"Duck Volume\", duckVolDef);\n            AddDefinitionRuntime(\"Duck Volume\", duckVolDef);\n\n            string[] effectNames = GetAudioEffectNames();\n            foreach (var effectName in effectNames)\n            {\n                MixerParameterDefinition[] paramDesc = GetAudioEffectParameterDesc(effectName);\n                RegisterAudioMixerEffect(effectName, paramDesc);\n            }\n        }\n\n        public static bool EffectExists(string name)\n        {\n            foreach (MixerEffectDefinition definition in s_MixerEffectDefinitions)\n            {\n                if (definition.name == name)\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        public static string[] GetEffectList()\n        {\n            string[] effectNames = new string[s_MixerEffectDefinitions.Count];\n            for (int i = 0; i < s_MixerEffectDefinitions.Count; i++)\n            {\n                effectNames[i] = s_MixerEffectDefinitions[i].name;\n            }\n\n            return effectNames;\n        }\n\n        public static void ClearDefinitions()\n        {\n            s_MixerEffectDefinitions.Clear();\n            ClearDefinitionsRuntime();\n        }\n\n        public static MixerParameterDefinition[] GetEffectParameters(string effect)\n        {\n            foreach (MixerEffectDefinition definition in s_MixerEffectDefinitions)\n            {\n                if (definition.name == effect)\n                {\n                    return definition.parameters;\n                }\n            }\n\n            return new MixerParameterDefinition[0];\n        }\n\n        public static bool RegisterAudioMixerEffect(string name, MixerParameterDefinition[] definitions)\n        {\n            foreach (MixerEffectDefinition definition in s_MixerEffectDefinitions)\n            {\n                if (definition.name == name)\n                {\n                    //Cannot add this type, already exists in the system.\n                    return false;\n                }\n            }\n\n            MixerEffectDefinition newDefinition = new MixerEffectDefinition(name, definitions);\n            s_MixerEffectDefinitions.Add(newDefinition);\n\n            //Wasteful - Clears the runtime representation each time a new effect is added and rebuilds all runtime\n            //representations.\n            ClearDefinitionsRuntime();\n            foreach (MixerEffectDefinition definition in s_MixerEffectDefinitions)\n            {\n                AddDefinitionRuntime(definition.name,  definition.parameters);\n            }\n\n            return true;\n        }\n\n        private static readonly List<MixerEffectDefinition> s_MixerEffectDefinitions = new List<MixerEffectDefinition>();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/Bindings/AudioMixerController.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.Audio;\nusing Object = UnityEngine.Object;\nusing Random = System.Random;\n\nnamespace UnityEditor.Audio\n{\n    abstract class AudioParameterPath\n    {\n        public GUID parameter;\n\n        public abstract string ResolveStringPath(bool getOnlyBasePath);\n    }\n\n    class AudioGroupParameterPath : AudioParameterPath\n    {\n        public AudioMixerGroupController group;\n\n        public AudioGroupParameterPath(AudioMixerGroupController group, GUID parameter)\n        {\n            this.group = group;\n            this.parameter = parameter;\n        }\n\n        public override string ResolveStringPath(bool getOnlyBasePath)\n        {\n            if (getOnlyBasePath)\n                return GetBasePath(group.GetDisplayString(), null);\n\n            if (group.GetGUIDForVolume() == parameter)\n            {\n                return \"Volume\" + GetBasePath(group.GetDisplayString(), null);\n            }\n\n            if (group.GetGUIDForPitch() == parameter)\n            {\n                return \"Pitch\" + GetBasePath(group.GetDisplayString(), null);\n            }\n\n            return \"Error finding Parameter path.\";\n        }\n\n        protected string GetBasePath(string group, string effect)\n        {\n            string result = \" (of \" + group;\n            if (!string.IsNullOrEmpty(effect))\n                result += \"\\u2794\" + effect; //u2794 is a right arrow character\n            result += \")\";\n            return result;\n        }\n    }\n\n    sealed class AudioEffectParameterPath : AudioGroupParameterPath\n    {\n        public AudioMixerEffectController effect;\n\n        public AudioEffectParameterPath(AudioMixerGroupController group, AudioMixerEffectController effect, GUID parameter)\n            : base(group, parameter)\n        {\n            this.effect = effect;\n        }\n\n        public override string ResolveStringPath(bool getOnlyBasePath)\n        {\n            if (getOnlyBasePath)\n                return GetBasePath(group.GetDisplayString(), effect.effectName);\n\n            if (effect.GetGUIDForMixLevel() == parameter)\n            {\n                if (effect.IsSend())\n                {\n                    var allGroups = group.controller.GetAllAudioGroupsSlow();\n                    var effectMap = AudioMixerGroupController.GetEffectMapSlow(allGroups);\n                    return $\"Send level{GetBasePath(group.GetDisplayString(), null)} to {effect.sendTarget.GetDisplayString(effectMap)}\";\n                }\n\n                return $\"Mix Level{GetBasePath(group.GetDisplayString(), effect.effectName)}\";\n            }\n\n            MixerParameterDefinition[] paramDefs = MixerEffectDefinitions.GetEffectParameters(effect.effectName);\n\n            for (int i = 0; i < paramDefs.Length; i++)\n            {\n                GUID guid = effect.GetGUIDForParameter(paramDefs[i].name);\n\n                if (guid == parameter)\n                {\n                    return paramDefs[i].name + GetBasePath(group.GetDisplayString(), effect.effectName);\n                }\n            }\n\n            return \"Error finding Parameter path.\";\n        }\n    }\n\n    delegate void ChangedExposedParameterHandler();\n\n    [ExcludeFromPreset]\n    sealed partial class AudioMixerController : AudioMixer\n    {\n        public static float kMinVolume = -80.0f; // The minimum volume is the level at which sends and effects can be bypassed\n        public static float kMaxEffect = 0.0f;\n        public static float kVolumeWarp = 1.7f;\n        public static string s_GroupEffectDisplaySeperator = \"\\\\\"; // Use backslash instead of forward slash to prevent OS menus from splitting path and creating submenus\n\n        public event ChangedExposedParameterHandler ChangedExposedParameter;\n\n        public void OnChangedExposedParameter()\n        {\n            if (ChangedExposedParameter != null)\n                ChangedExposedParameter();\n        }\n\n        public void ClearEventHandlers()\n        {\n            if (ChangedExposedParameter != null)\n            {\n                foreach (Delegate d in ChangedExposedParameter.GetInvocationList())\n                {\n                    ChangedExposedParameter -= (ChangedExposedParameterHandler)d;\n                }\n            }\n        }\n\n        [NonSerialized]\n        Dictionary<GUID, AudioParameterPath> m_ExposedParamPathCache;\n\n        Dictionary<GUID, AudioParameterPath> exposedParamCache\n        {\n            get\n            {\n                if (m_ExposedParamPathCache == null)\n                    m_ExposedParamPathCache = new Dictionary<GUID, AudioParameterPath>();\n\n                return m_ExposedParamPathCache;\n            }\n        }\n\n        string FindUniqueParameterName(string template, ExposedAudioParameter[] parameters)\n        {\n            string unique = template;\n            int counter = 1;\n            for (int i = 0; i < parameters.Length; i++)\n            {\n                if (unique == parameters[i].name)\n                {\n                    unique = template + \" \" + counter++;\n                    i = -1;\n                }\n            }\n\n            return unique;\n        }\n\n        int SortFuncForExposedParameters(ExposedAudioParameter p1, ExposedAudioParameter p2)\n        {\n            return string.CompareOrdinal(ResolveExposedParameterPath(p1.guid, true), ResolveExposedParameterPath(p2.guid, true));\n        }\n\n        public void AddExposedParameter(AudioParameterPath path)\n        {\n            if (path == null)\n            {\n                Debug.LogError(\"Trying to expose null parameter.\");\n                return;\n            }\n\n            if (path.parameter == default)\n            {\n                Debug.LogError(\"Trying to expose parameter with default GUID.\");\n                return;\n            }\n\n            if (ContainsExposedParameter(path.parameter))\n            {\n                Debug.LogError(\"Cannot expose the same parameter more than once.\");\n                return;\n            }\n\n            var parameters = new List<ExposedAudioParameter>(exposedParameters);\n            var newParam = new ExposedAudioParameter();\n            newParam.name = FindUniqueParameterName(\"MyExposedParam\", exposedParameters);\n            newParam.guid = path.parameter;\n            parameters.Add(newParam);\n\n            // We sort the exposed params by path\n            parameters.Sort(SortFuncForExposedParameters);\n\n            exposedParameters = parameters.ToArray();\n            OnChangedExposedParameter();\n\n            //Cache the path!\n            exposedParamCache[path.parameter] = path;\n\n            AudioMixerUtility.RepaintAudioMixerAndInspectors();\n        }\n\n        public bool ContainsExposedParameter(GUID parameter)\n        {\n            return exposedParameters.Where(val => val.guid == parameter).ToArray().Length > 0;\n        }\n\n        public void RemoveExposedParameter(GUID parameterGuid)\n        {\n            exposedParameters = exposedParameters.Where(val => val.guid != parameterGuid).ToArray();\n            OnChangedExposedParameter();\n\n            //Tidy up the cache..\n            if (exposedParamCache.ContainsKey(parameterGuid))\n                exposedParamCache.Remove(parameterGuid);\n\n            AudioMixerUtility.RepaintAudioMixerAndInspectors();\n        }\n\n        public string ResolveExposedParameterPath(GUID parameter, bool getOnlyBasePath)\n        {\n            // Consult the cache of parameters first.\n            if (exposedParamCache.ContainsKey(parameter))\n            {\n                var path = exposedParamCache[parameter];\n\n                return path.ResolveStringPath(getOnlyBasePath);\n            }\n\n            // Search through the whole mixer!\n            List<AudioMixerGroupController> groups = GetAllAudioGroupsSlow();\n\n            foreach (AudioMixerGroupController group in groups)\n            {\n                if (group.GetGUIDForVolume() == parameter || group.GetGUIDForPitch() == parameter)\n                {\n                    var newPath = new AudioGroupParameterPath(group, parameter);\n                    exposedParamCache[parameter] = newPath;\n                    return newPath.ResolveStringPath(getOnlyBasePath);\n                }\n\n                for (var i = 0; i < group.effects.Length; i++)\n                {\n                    var effect = group.effects[i];\n\n                    if (effect.IsSend() && parameter == effect.GetGUIDForMixLevel())\n                    {\n                        var newPath = new AudioEffectParameterPath(group, effect, parameter);\n                        exposedParamCache[parameter] = newPath;\n                        return newPath.ResolveStringPath(getOnlyBasePath);\n                    }\n\n                    var paramDefs = MixerEffectDefinitions.GetEffectParameters(effect.effectName);\n\n                    for (var j = 0; j < paramDefs.Length; j++)\n                    {\n                        var guid = effect.GetGUIDForParameter(paramDefs[j].name);\n\n                        if (guid == parameter)\n                        {\n                            var newPath = new AudioEffectParameterPath(group, effect, parameter);\n                            exposedParamCache[parameter] = newPath;\n                            return newPath.ResolveStringPath(getOnlyBasePath);\n                        }\n                    }\n                }\n            }\n\n            return \"Error finding Parameter path\";\n        }\n\n        public static AudioMixerController CreateMixerControllerAtPath(string path)\n        {\n            var controller = new AudioMixerController();\n            controller.CreateDefaultAsset(path);\n            return controller;\n        }\n\n        public void CreateDefaultAsset(string path)\n        {\n            masterGroup = new AudioMixerGroupController(this);\n            masterGroup.name = \"Master\";\n            masterGroup.PreallocateGUIDs();\n\n            var attenuation = new AudioMixerEffectController(\"Attenuation\");\n            attenuation.PreallocateGUIDs();\n            masterGroup.InsertEffect(attenuation, 0);\n\n            AudioMixerSnapshotController snapshot = new AudioMixerSnapshotController(this);\n            snapshot.name = \"Snapshot\";\n            snapshots = new[] { snapshot };\n\n            startSnapshot = snapshot;\n\n            Object[] objectArray = { this, masterGroup, attenuation, snapshot };\n            AssetDatabase.CreateAssetFromObjects(objectArray, path);\n        }\n\n        void BuildTestSetup(Random r, AudioMixerGroupController parent, int minSpan, int maxSpan, int maxGroups, string prefix, ref int numGroups)\n        {\n            int span = (numGroups == 0) ? maxSpan : r.Next(minSpan, maxSpan + 1);\n            for (int i = 0; i < span; i++)\n            {\n                var name = prefix + i;\n                var g = CreateNewGroup(name, false);\n                AddChildToParent(g, parent);\n                if (++numGroups >= maxGroups)\n                    return;\n                BuildTestSetup(r, g, minSpan, (maxSpan > minSpan) ? (maxSpan - 1) : minSpan, maxGroups, name, ref numGroups);\n            }\n        }\n\n        public void BuildTestSetup(int minSpan, int maxSpan, int maxGroups)\n        {\n            int numGroups = 0;\n            DeleteGroups(masterGroup.children);\n            BuildTestSetup(new Random(), masterGroup, minSpan, maxSpan, maxGroups, \"G\", ref numGroups);\n        }\n\n        public List<AudioMixerGroupController> GetAllAudioGroupsSlow()\n        {\n            var groups = new List<AudioMixerGroupController>();\n\n            if (masterGroup != null)\n                GetAllAudioGroupsSlowRecurse(masterGroup, groups);\n\n            return groups;\n        }\n\n        static void GetAllAudioGroupsSlowRecurse(AudioMixerGroupController g, List<AudioMixerGroupController> groups)\n        {\n            groups.Add(g);\n\n            foreach (var c in g.children)\n                GetAllAudioGroupsSlowRecurse(c, groups);\n        }\n\n        public bool HasMoreThanOneGroup()\n        {\n            return masterGroup.children.Length > 0;\n        }\n\n        // Returns true if there is an ancestor of child in the groups list\n        bool IsChildOf(AudioMixerGroupController child, List<AudioMixerGroupController> groups)\n        {\n            var ancestor = child;\n\n            while (ancestor != null)\n            {\n                ancestor = FindParentGroup(masterGroup, ancestor);\n\n                if (ancestor != null && groups.Contains(ancestor))\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        // Checks whether the groups in the list are in some kind of child-parent relationship. They do of course have common ancestors, but there shouldn't be any\n        // ancestor path from items in the list to any other items in the list.\n        public bool AreAnyOfTheGroupsInTheListAncestors(List<AudioMixerGroupController> groups)\n        {\n            return groups.Any(g => IsChildOf(g, groups));\n        }\n\n        // Before duplicating or removing a selection, this function is called to make sure that the selection does not contain any items that are in a\n        // child-parent relationship. By working on a cleaned list, duplication/removal is simplified a lot and just becomes a matter or recursively traversing\n        // each of the items in the selection without the need to watch out for sub-items that already got deleted during the recursive traversal.\n        void RemoveAncestorGroups(List<AudioMixerGroupController> groups)\n        {\n            groups.RemoveAll(g => IsChildOf(g, groups));\n            Equals(AreAnyOfTheGroupsInTheListAncestors(groups), false);\n        }\n\n        void RemoveExposedParametersContainedInEffect(AudioMixerEffectController effect)\n        {\n            // Cleanup exposed parameters that were in the effect\n            var exposedParams = exposedParameters;\n\n            if (exposedParams.Length == 0)\n            {\n                return;\n            }\n\n            var undoString = \"Remove Exposed Effect Parameter\";\n\n            if (exposedParams.Length > 1)\n            {\n                undoString = $\"{undoString}s\";\n            }\n\n            Undo.RecordObject(this, undoString);\n\n            foreach (var param in exposedParams)\n            {\n                if (effect.ContainsParameterGUID(param.guid))\n                {\n                    RemoveExposedParameter(param.guid);\n                }\n            }\n        }\n\n        void RemoveExposedParametersContainedInGroup(AudioMixerGroupController group)\n        {\n            // Clean up the exposed parameters that were in the group.\n            var exposedParams = exposedParameters;\n\n            if (exposedParams.Length == 0)\n            {\n                return;\n            }\n\n            var undoString = \"Remove Exposed Group Parameter\";\n\n            if (exposedParams.Length > 1)\n            {\n                undoString = $\"{undoString}s\";\n            }\n\n            Undo.RecordObject(this, undoString);\n\n            foreach (var param in exposedParams)\n            {\n                if (group.GetGUIDForVolume() == param.guid || group.GetGUIDForPitch() == param.guid)\n                    RemoveExposedParameter(param.guid);\n            }\n        }\n\n        void PreprocessGroupsToDeleteRecursive(AudioMixerGroupController group, ICollection<Object> objecsToDelete)\n        {\n            var children = group.children;\n\n            foreach (var child in children)\n                PreprocessGroupsToDeleteRecursive(child, objecsToDelete);\n\n            var effects = group.effects;\n\n            foreach (var effect in effects)\n            {\n                ClearSendConnectionsTo(effect);\n                RemoveExposedParametersContainedInEffect(effect);\n                objecsToDelete.Add(effect);\n            }\n\n            RemoveExposedParametersContainedInGroup(group);\n            objecsToDelete.Add(group);\n        }\n\n        public void DeleteGroups(AudioMixerGroupController[] groups)\n        {\n            if (groups.Length == 0)\n            {\n                Debug.LogError(\"Group array is empty.\");\n                return;\n            }\n\n            var filteredGroups = groups.ToList();\n            RemoveAncestorGroups(filteredGroups);\n\n            var undoGroupName = \"Remove Group\";\n\n            if (groups.Length > 1)\n            {\n                undoGroupName = $\"{undoGroupName}s\";\n            }\n\n            Undo.RegisterCompleteObjectUndo(this, undoGroupName);\n\n            var objectsToDestroy = new List<Object>();\n\n            for (var i = filteredGroups.Count - 1; i >= 0; --i)\n            {\n                if (filteredGroups[i] == null)\n                {\n                    Debug.LogError(\"Skipping null element in group array.\");\n                    filteredGroups.RemoveAt(i);\n                    continue;\n                }\n\n                PreprocessGroupsToDeleteRecursive(filteredGroups[i], objectsToDestroy);\n            }\n\n            var allGroups = GetAllAudioGroupsSlow();\n\n            foreach (var group in allGroups)\n            {\n                var childGroupsToRemove = filteredGroups.Intersect(group.children).ToArray();\n\n                if (childGroupsToRemove.Any())\n                {\n                    Undo.RecordObject(group, \"Detach Group Children\");\n                    group.children = group.children.Except(childGroupsToRemove).ToArray();\n                }\n            }\n\n            foreach (var o in objectsToDestroy)\n            {\n                Undo.DestroyObjectImmediate(o);\n            }\n\n            OnUnitySelectionChanged();\n\n            Undo.SetCurrentGroupName(undoGroupName);\n        }\n\n        public void RemoveEffect(AudioMixerEffectController effect, AudioMixerGroupController group)\n        {\n            if (effect == null)\n            {\n                Debug.LogError(\"Effect is null.\");\n                return;\n            }\n\n            if (group == null)\n            {\n                Debug.LogError(\"Group is null.\");\n                return;\n            }\n\n            var effects = group.effects;\n            var foundEffect = false;\n\n            for (var i = 0; i < effects.Length; ++i)\n            {\n                if (effects[i] == effect)\n                {\n                    foundEffect = true;\n                    break;\n                }\n            }\n\n            if (!foundEffect)\n            {\n                Debug.LogError($\"Group {group.name} does not contain effect {effect.name}\");\n                return;\n            }\n\n            ClearSendConnectionsTo(effect);\n            RemoveExposedParametersContainedInEffect(effect);\n\n            var modifiedEffectsList = new List<AudioMixerEffectController>(group.effects);\n            modifiedEffectsList.Remove(effect);\n\n            const string undoGroupName = \"Remove Effect\";\n\n            Undo.RecordObject(group, undoGroupName);\n\n            group.effects = modifiedEffectsList.ToArray();\n\n            Undo.DestroyObjectImmediate(effect);\n            Undo.SetCurrentGroupName(undoGroupName);\n        }\n\n        public void OnSubAssetChanged()\n        {\n            AssetDatabase.SaveAssets();\n            AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(this));\n        }\n\n        public void CloneNewSnapshotFromTarget(bool storeUndoState)\n        {\n            var snapshotList = new List<AudioMixerSnapshotController>(snapshots);\n            var ob = Instantiate(TargetSnapshot);\n            var newSnapshot = ob;\n            newSnapshot.name = TargetSnapshot.name + \" - Copy\";\n            snapshotList.Add(newSnapshot);\n            snapshots = snapshotList.ToArray();\n            TargetSnapshot = snapshotList[snapshotList.Count - 1];\n\n            AssetDatabase.AddObjectToAsset(newSnapshot, this);\n            if (storeUndoState)\n                Undo.RegisterCreatedObjectUndo(newSnapshot, \"\");\n\n            OnSubAssetChanged();\n        }\n\n        public void RemoveTargetSnapshot()\n        {\n            if (snapshots.Length < 2)\n                return;\n\n            var deletedSnapshot = TargetSnapshot;\n\n            Undo.RecordObject(this, \"Remove Snapshot\");\n\n            var snapshotList = new List<AudioMixerSnapshotController>(snapshots);\n            snapshotList.Remove(deletedSnapshot);\n            snapshots = snapshotList.ToArray();\n\n            Undo.DestroyObjectImmediate(deletedSnapshot);\n\n            OnSubAssetChanged();\n        }\n\n        public void RemoveSnapshot(AudioMixerSnapshotController snapshot)\n        {\n            if (snapshots.Length < 2)\n                return;\n\n            var deletedSnapshot = snapshot;\n\n            Undo.RecordObject(this, \"Remove Snapshot\");\n\n            var snapshotList = new List<AudioMixerSnapshotController>(snapshots);\n            snapshotList.Remove(deletedSnapshot);\n            snapshots = snapshotList.ToArray();\n\n            Undo.DestroyObjectImmediate(deletedSnapshot);\n\n            OnSubAssetChanged();\n        }\n\n        public AudioMixerGroupController CreateNewGroup(string name, bool storeUndoState)\n        {\n            var group = new AudioMixerGroupController(this);\n            group.name = name;\n            group.PreallocateGUIDs();\n\n            var effect = new AudioMixerEffectController(\"Attenuation\");\n            AddNewSubAsset(effect, storeUndoState);\n            effect.PreallocateGUIDs();\n\n            group.InsertEffect(effect, 0);\n            AddNewSubAsset(group, storeUndoState);\n\n            return group;\n        }\n\n        public void AddChildToParent(AudioMixerGroupController child, AudioMixerGroupController parent)\n        {\n            RemoveGroupsFromParent(new[] { child }, false);\n            var modifiedChildList = new List<AudioMixerGroupController>(parent.children);\n            modifiedChildList.Add(child);\n            parent.children = modifiedChildList.ToArray();\n        }\n\n        void AddNewSubAsset(Object obj, bool storeUndoState)\n        {\n            AssetDatabase.AddObjectToAsset(obj, this);\n            if (storeUndoState)\n                Undo.RegisterCreatedObjectUndo(obj, \"\");\n        }\n\n        public void RemoveGroupsFromParent(AudioMixerGroupController[] groups, bool storeUndoState)\n        {\n            List<AudioMixerGroupController> filteredGroups = groups.ToList();\n            RemoveAncestorGroups(filteredGroups);\n\n            if (storeUndoState)\n                Undo.RecordObject(this, \"Remove group\");\n            foreach (var g in filteredGroups)\n            {\n                List<AudioMixerGroupController> allGroups = GetAllAudioGroupsSlow();\n                foreach (var parent in allGroups)\n                {\n                    List<AudioMixerGroupController> modifiedChildList = new List<AudioMixerGroupController>(parent.children);\n                    if (modifiedChildList.Contains(g))\n                        modifiedChildList.Remove(g);\n                    if (parent.children.Length != modifiedChildList.Count)\n                        parent.children = modifiedChildList.ToArray();\n                }\n            }\n        }\n\n        public AudioMixerGroupController FindParentGroup(AudioMixerGroupController node, AudioMixerGroupController group)\n        {\n            for (int n = 0; n < node.children.Length; n++)\n            {\n                if (node.children[n] == group)\n                    return node;\n                var g = FindParentGroup(node.children[n], group);\n                if (g != null)\n                    return g;\n            }\n\n            return null;\n        }\n\n        public AudioMixerEffectController CopyEffect(AudioMixerEffectController sourceEffect)\n        {\n            var copiedEffect = new AudioMixerEffectController(sourceEffect.effectName);\n            copiedEffect.name = sourceEffect.name;\n            copiedEffect.PreallocateGUIDs();\n            MixerParameterDefinition[] paramDefs = MixerEffectDefinitions.GetEffectParameters(sourceEffect.effectName);\n            float value;\n            foreach (var s in snapshots)\n            {\n                if (s.GetValue(sourceEffect.GetGUIDForMixLevel(), out value))\n                    s.SetValue(copiedEffect.GetGUIDForMixLevel(), value);\n                foreach (var p in paramDefs)\n                {\n                    if (s.GetValue(sourceEffect.GetGUIDForParameter(p.name), out value))\n                        s.SetValue(copiedEffect.GetGUIDForParameter(p.name), value);\n                }\n            }\n\n            AssetDatabase.AddObjectToAsset(copiedEffect, this);\n            return copiedEffect;\n        }\n\n        AudioMixerGroupController DuplicateGroupRecurse(AudioMixerGroupController sourceGroup, bool recordUndo)\n        {\n            var targetGroup = new AudioMixerGroupController(this);\n\n            // Copy effects\n            var targetEffectsList = new List<AudioMixerEffectController>();\n            foreach (var sourceEffect in sourceGroup.effects)\n            {\n                targetEffectsList.Add(CopyEffect(sourceEffect));\n            }\n\n            // Copy child groups\n            var targetChildren = new List<AudioMixerGroupController>();\n            foreach (var childGroup in sourceGroup.children)\n                targetChildren.Add(DuplicateGroupRecurse(childGroup, recordUndo));\n\n            targetGroup.name = sourceGroup.name + \" - Copy\";\n            targetGroup.PreallocateGUIDs();\n            targetGroup.effects = targetEffectsList.ToArray();\n            targetGroup.children = targetChildren.ToArray();\n            targetGroup.solo = sourceGroup.solo;\n            targetGroup.mute = sourceGroup.mute;\n            targetGroup.bypassEffects = sourceGroup.bypassEffects;\n            float value;\n            foreach (var s in snapshots)\n            {\n                if (s.GetValue(sourceGroup.GetGUIDForVolume(), out value))\n                    s.SetValue(targetGroup.GetGUIDForVolume(), value);\n                if (s.GetValue(sourceGroup.GetGUIDForPitch(), out value))\n                    s.SetValue(targetGroup.GetGUIDForPitch(), value);\n            }\n\n            AssetDatabase.AddObjectToAsset(targetGroup, this);\n\n            if (recordUndo)\n                Undo.RegisterCreatedObjectUndo(targetGroup, targetGroup.name);\n\n            // Add to view if source is shown (so it's visible in the channelstrip)\n            if (CurrentViewContainsGroup(sourceGroup.groupID))\n                targetGroup.controller.AddGroupToCurrentView(targetGroup);\n\n            return targetGroup;\n        }\n\n        // Returns duplicated root groups (traverse group.children to get all groups duplicated)\n        public List<AudioMixerGroupController> DuplicateGroups(AudioMixerGroupController[] sourceGroups, bool recordUndo)\n        {\n            List<AudioMixerGroupController> filteredGroups = sourceGroups.ToList();\n            RemoveAncestorGroups(filteredGroups);\n\n            var allRoots = new List<AudioMixerGroupController>();\n\n            foreach (var source in filteredGroups)\n            {\n                AudioMixerGroupController parent = FindParentGroup(masterGroup, source);\n                if (parent != null && source != null)\n                {\n                    if (recordUndo)\n                        Undo.RecordObject(parent, \"Reparent AudioMixerGroup\");\n\n                    AudioMixerGroupController copy = DuplicateGroupRecurse(source, recordUndo);\n\n                    var modifiedChildList = new List<AudioMixerGroupController>(parent.children);\n                    modifiedChildList.Add(copy);\n                    parent.children = modifiedChildList.ToArray();\n\n                    allRoots.Add(copy);\n                }\n            }\n\n            return allRoots;\n        }\n\n        public void CopyEffectSettingsToAllSnapshots(AudioMixerGroupController group, int effectIndex, AudioMixerSnapshotController snapshot, bool includeWetParam)\n        {\n            AudioMixerSnapshotController[] snaps = snapshots;\n            for (int n = 0; n < snaps.Length; n++)\n            {\n                if (snaps[n] == snapshot)\n                    continue;\n                var effect = group.effects[effectIndex];\n                MixerParameterDefinition[] paramDefs = MixerEffectDefinitions.GetEffectParameters(effect.effectName);\n                float value;\n                if (includeWetParam)\n                {\n                    var guid = effect.GetGUIDForMixLevel();\n                    if (snapshot.GetValue(guid, out value))\n                        snaps[n].SetValue(guid, value);\n                }\n\n                foreach (var p in paramDefs)\n                {\n                    var guid = effect.GetGUIDForParameter(p.name);\n                    if (snapshot.GetValue(guid, out value))\n                        snaps[n].SetValue(guid, value);\n                }\n            }\n        }\n\n        public void CopyAllSettingsToAllSnapshots(AudioMixerGroupController group, AudioMixerSnapshotController snapshot)\n        {\n            for (int n = 0; n < group.effects.Length; n++)\n                CopyEffectSettingsToAllSnapshots(group, n, snapshot, true);\n\n            AudioMixerSnapshotController[] snaps = snapshots;\n            for (int n = 0; n < snaps.Length; n++)\n            {\n                if (snaps[n] == snapshot)\n                    continue;\n                var dst = snaps[n];\n                group.SetValueForVolume(this, dst, group.GetValueForVolume(this, snapshot));\n                group.SetValueForPitch(this, dst, group.GetValueForPitch(this, snapshot));\n            }\n        }\n\n        public void CopyAttenuationToAllSnapshots(AudioMixerGroupController group, AudioMixerSnapshotController snapshot)\n        {\n            AudioMixerSnapshotController[] snaps = snapshots;\n            for (int n = 0; n < snaps.Length; n++)\n            {\n                if (snaps[n] == snapshot)\n                    continue;\n                var dst = snaps[n];\n                group.SetValueForVolume(this, dst, group.GetValueForVolume(this, snapshot));\n            }\n        }\n\n        public void ReparentSelection(AudioMixerGroupController newParent, int insertionIndex, List<AudioMixerGroupController> selection)\n        {\n            // We are moving items so we adjust the insertion index to accomodate that any items above the insertion index is removed before inserting\n            if (insertionIndex >= 0)\n                insertionIndex -= newParent.children.ToList().GetRange(0, insertionIndex).Count(selection.Contains);\n\n            Undo.RecordObject(newParent, \"Change Audio Mixer Group Parent\");\n            List<AudioMixerGroupController> groups = GetAllAudioGroupsSlow();\n            foreach (var g in groups)\n            {\n                // Check if any groups in the selection is part of current groups child list\n                if (g.children.Intersect(selection).Any())\n                {\n                    Undo.RecordObject(g, string.Empty); // empty string will use undo name above\n                    var modifiedChildList = new List<AudioMixerGroupController>(g.children);\n                    foreach (var c in selection)\n                        modifiedChildList.Remove(c);\n                    g.children = modifiedChildList.ToArray();\n                }\n            }\n\n            // When dragging upon we insert as first child\n            if (insertionIndex == -1)\n                insertionIndex = 0;\n\n            var newChildList = new List<AudioMixerGroupController>(newParent.children);\n            newChildList.InsertRange(insertionIndex, selection);\n            newParent.children = newChildList.ToArray();\n        }\n\n        public static bool InsertEffect(AudioMixerEffectController effect, ref List<AudioMixerEffectController> targetEffects, int targetIndex)\n        {\n            if (targetIndex < 0 || targetIndex > targetEffects.Count)\n            {\n                Debug.LogError(\"Inserting effect failed! size: \" + targetEffects.Count + \" at index: \" + targetIndex);\n                return false;\n            }\n\n            targetEffects.Insert(targetIndex, effect);\n            return true;\n        }\n\n        public static bool MoveEffect(ref List<AudioMixerEffectController> sourceEffects, int sourceIndex, ref List<AudioMixerEffectController> targetEffects, int targetIndex)\n        {\n            if (sourceEffects == targetEffects)\n            {\n                if (targetIndex > sourceIndex)\n                    targetIndex--;\n                if (sourceIndex == targetIndex)\n                    return false;\n            }\n\n            if (sourceIndex < 0 || sourceIndex >= sourceEffects.Count)\n                return false;\n            if (targetIndex < 0 || targetIndex > targetEffects.Count)\n                return false;\n            AudioMixerEffectController effect = sourceEffects[sourceIndex];\n            sourceEffects.RemoveAt(sourceIndex);\n            targetEffects.Insert(targetIndex, effect);\n            return true;\n        }\n\n        void ClearSendConnectionsTo(AudioMixerEffectController sendTarget)\n        {\n            var allGroups = GetAllAudioGroupsSlow();\n\n            foreach (var g in allGroups)\n            {\n                foreach (var e in g.effects)\n                {\n                    if (e.IsSend() && e.sendTarget == sendTarget)\n                    {\n                        var guid = e.GetGUIDForMixLevel();\n\n                        if (ContainsExposedParameter(guid))\n                        {\n                            Undo.RecordObjects(new Object[] { this, e }, \"Clear Send target\");\n                            RemoveExposedParameter(guid);\n                        }\n                        else\n                        {\n                            Undo.RecordObject(e, \"Clear Send target\");\n                        }\n\n                        e.sendTarget = null;\n                    }\n                }\n            }\n        }\n\n        public class ConnectionNode\n        {\n            public bool visited;\n            public object groupTail;\n            public List<object> targets = new List<object>();\n            public AudioMixerGroupController group;\n            public AudioMixerEffectController effect;\n\n            public string GetDisplayString()\n            {\n                string s = group.GetDisplayString();\n                if (effect != null)\n                    s += s_GroupEffectDisplaySeperator + effect.effectName;\n                return s;\n            }\n        }\n\n        // Builds a graph over all connections going out of a group (the parent counts as one).\n        // While building the map, the existing routing of effectSlotUnderTest are ignored and pretended it is connected to targetToTest instead.\n        // Then checks are performed whether this setup would cause any loops in the graph.\n        static Dictionary<object, ConnectionNode> BuildTemporaryGraph(\n            List<AudioMixerGroupController> allGroups,\n            AudioMixerGroupController groupWhoseEffectIsChanged, AudioMixerEffectController effectWhoseTargetIsChanged, AudioMixerEffectController targetToTest,\n            AudioMixerGroupController modifiedGroup1, List<AudioMixerEffectController> modifiedGroupEffects1,\n            AudioMixerGroupController modifiedGroup2, List<AudioMixerEffectController> modifiedGroupEffects2\n        )\n        {\n            // First build the chains of groups and their contained effects\n            var graph = new Dictionary<object, ConnectionNode>();\n            foreach (var group in allGroups)\n            {\n                var groupNode = new ConnectionNode();\n                groupNode.group = group;\n                groupNode.effect = null;\n                graph[group] = groupNode;\n                object groupTail = group;\n                var reorderedEffects = (group == modifiedGroup1) ? modifiedGroupEffects1 : (group == modifiedGroup2) ? modifiedGroupEffects2 : group.effects.ToList();\n                foreach (var effect in reorderedEffects)\n                {\n                    if (!graph.ContainsKey(effect))\n                        graph[effect] = new ConnectionNode();\n                    graph[effect].group = group;\n                    graph[effect].effect = effect;\n                    if (!graph[groupTail].targets.Contains(effect))\n                        graph[groupTail].targets.Add(effect);\n                    AudioMixerEffectController target = (group == groupWhoseEffectIsChanged && effectWhoseTargetIsChanged == effect) ? targetToTest : effect.sendTarget;\n                    if (target != null)\n                    {\n                        if (!graph.ContainsKey(target))\n                        {\n                            graph[target] = new ConnectionNode();\n                            graph[target].group = group;\n                            graph[target].effect = target;\n                        }\n\n                        if (!graph[effect].targets.Contains(target))\n                            graph[effect].targets.Add(target);\n                    }\n\n                    groupTail = effect;\n                }\n\n                graph[group].groupTail = groupTail;\n            }\n\n            return graph;\n        }\n\n        static void ListTemporaryGraph(Dictionary<object, ConnectionNode> graph)\n        {\n            Debug.Log(\"Listing temporary graph:\");\n            int nodeIndex = 0;\n            foreach (var node in graph)\n            {\n                Debug.Log(string.Format(\"Node {0}: {1}\", nodeIndex++, node.Value.GetDisplayString()));\n                int targetIndex = 0;\n                foreach (var t in node.Value.targets)\n                    Debug.Log(string.Format(\"  Target {0}: {1}\", targetIndex++, graph[t].GetDisplayString()));\n            }\n        }\n\n        static bool CheckForCycle(object curr, Dictionary<object, ConnectionNode> graph, List<ConnectionNode> identifiedLoop)\n        {\n            var node = graph[curr];\n            if (node.visited)\n            {\n                if (identifiedLoop != null)\n                {\n                    identifiedLoop.Clear();\n                    identifiedLoop.Add(node);\n                }\n\n                return true;\n            }\n\n            node.visited = true;\n            foreach (var s in node.targets)\n            {\n                if (CheckForCycle(s, graph, identifiedLoop))\n                {\n                    node.visited = false;\n                    if (identifiedLoop != null)\n                        identifiedLoop.Add(node);\n                    return true;\n                }\n            }\n\n            node.visited = false;\n            return false;\n        }\n\n        public static bool DoesTheTemporaryGraphHaveAnyCycles(List<AudioMixerGroupController> allGroups, List<ConnectionNode> identifiedLoop, Dictionary<object, ConnectionNode> graph)\n        {\n            foreach (var g in allGroups)\n            {\n                if (CheckForCycle(g, graph, identifiedLoop))\n                {\n                    // Clean up identified loop so that we only show the looping part and not what lead to it\n                    if (identifiedLoop != null)\n                    {\n                        var start = identifiedLoop[0];\n                        int i;\n                        for (i = 1; i < identifiedLoop.Count;)\n                            if (identifiedLoop[i++] == start)\n                                break;\n                        identifiedLoop.RemoveRange(i, identifiedLoop.Count - i);\n                        identifiedLoop.Reverse();\n                    }\n\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        public static bool WillChangeOfEffectTargetCauseFeedback(List<AudioMixerGroupController> allGroups, AudioMixerGroupController groupWhoseEffectIsChanged, int effectWhoseTargetIsChanged, AudioMixerEffectController targetToTest, List<ConnectionNode> identifiedLoop)\n        {\n            var graph = BuildTemporaryGraph(allGroups, groupWhoseEffectIsChanged, groupWhoseEffectIsChanged.effects[effectWhoseTargetIsChanged], targetToTest, null, null, null, null);\n\n            // Connect the chains up using the group hierarchy\n            foreach (var group in allGroups)\n            {\n                foreach (var childGroup in group.children)\n                {\n                    var tailOfChildGroup = graph[childGroup].groupTail;\n                    if (!graph[tailOfChildGroup].targets.Contains(group))\n                        graph[tailOfChildGroup].targets.Add(group);\n                }\n            }\n\n            //ListTemporaryGraph(graph);\n\n            return DoesTheTemporaryGraphHaveAnyCycles(allGroups, identifiedLoop, graph);\n        }\n\n        public static bool WillModificationOfTopologyCauseFeedback(List<AudioMixerGroupController> allGroups, List<AudioMixerGroupController> groupsToBeMoved, AudioMixerGroupController newParentForMovedGroups, List<ConnectionNode> identifiedLoop)\n        {\n            var graph = BuildTemporaryGraph(allGroups, null, null, null, null, null, null, null);\n\n            // Connect the chains up using the group hierarchy, pretending that the groups in the list groupsToBeMoved belong to newParentForMovedGroups\n            foreach (var group in allGroups)\n            {\n                foreach (var childGroup in group.children)\n                {\n                    var parentGroup = (groupsToBeMoved.Contains(childGroup)) ? newParentForMovedGroups : group;\n                    var tailOfChildGroup = graph[childGroup].groupTail;\n                    if (!graph[tailOfChildGroup].targets.Contains(parentGroup))\n                        graph[tailOfChildGroup].targets.Add(parentGroup);\n                }\n            }\n\n            //ListTemporaryGraph(graph);\n\n            return DoesTheTemporaryGraphHaveAnyCycles(allGroups, identifiedLoop, graph);\n        }\n\n        public static bool WillMovingEffectCauseFeedback(List<AudioMixerGroupController> allGroups, AudioMixerGroupController sourceGroup, int sourceIndex, AudioMixerGroupController targetGroup, int targetIndex, List<ConnectionNode> identifiedLoop)\n        {\n            Dictionary<object, ConnectionNode> graph;\n\n            if (sourceGroup == targetGroup)\n            {\n                var modifiedEffects = sourceGroup.effects.ToList();\n                if (!MoveEffect(ref modifiedEffects, sourceIndex, ref modifiedEffects, targetIndex))\n                    return false;\n                graph = BuildTemporaryGraph(allGroups, null, null, null, sourceGroup, modifiedEffects, null, null);\n            }\n            else\n            {\n                var modifiedSourceEffects = sourceGroup.effects.ToList();\n                var modifiedTargetEffects = targetGroup.effects.ToList();\n                if (!MoveEffect(ref modifiedSourceEffects, sourceIndex, ref modifiedTargetEffects, targetIndex))\n                    return false;\n                graph = BuildTemporaryGraph(allGroups, null, null, null, sourceGroup, modifiedSourceEffects, targetGroup, modifiedTargetEffects);\n            }\n\n            // Connect the chains up using the group hierarchy\n            foreach (var group in allGroups)\n            {\n                foreach (var childGroup in group.children)\n                {\n                    var tailOfChildGroup = graph[childGroup].groupTail;\n                    if (!graph[tailOfChildGroup].targets.Contains(group))\n                        graph[tailOfChildGroup].targets.Add(group);\n                }\n            }\n\n            //ListTemporaryGraph(graph);\n\n            return DoesTheTemporaryGraphHaveAnyCycles(allGroups, identifiedLoop, graph);\n        }\n\n        public static float DbToLin(float x)\n        {\n            // This check needs to be kept in sync with the runtime. It serves as a cutoff point at which connections can be cut or effects bypassed.\n            if (x < kMinVolume)\n                return 0.0f;\n\n            return Mathf.Pow(10.0f, x * 0.05f);\n        }\n\n        public void CloneViewFromCurrent()\n        {\n            Undo.RecordObject(this, \"Create view\");\n\n            var viewList = new List<MixerGroupView>(views);\n            MixerGroupView view = new MixerGroupView();\n            view.name = views[currentViewIndex].name + \" - Copy\";\n            view.guids = views[currentViewIndex].guids;\n            viewList.Add(view);\n            views = viewList.ToArray();\n\n            currentViewIndex = viewList.Count - 1;\n        }\n\n        public void DeleteView(int index)\n        {\n            Undo.RecordObject(this, \"Delete view\");\n\n            var viewList = new List<MixerGroupView>(views);\n            viewList.RemoveAt(index);\n            views = viewList.ToArray();\n\n            int newIndex = Mathf.Clamp(currentViewIndex, 0, viewList.Count - 1);\n            ForceSetView(newIndex);\n        }\n\n        public void SetView(int index)\n        {\n            if (currentViewIndex != index)\n                ForceSetView(index);\n        }\n\n        public void SanitizeGroupViews()\n        {\n            List<AudioMixerGroupController> allGroups = GetAllAudioGroupsSlow();\n            var viewList = views;\n\n            for (int i = 0; i < viewList.Length; i++)\n            {\n                viewList[i].guids =\n                    (from x in viewList[i].guids\n                        from y in allGroups\n                        where y.groupID == x\n                        select x).ToArray();\n            }\n\n            views = viewList.ToArray();\n        }\n\n        public void ForceSetView(int index)\n        {\n            currentViewIndex = index;\n            SanitizeGroupViews();\n        }\n\n        public void AddGroupToCurrentView(AudioMixerGroupController group)\n        {\n            var viewList = views;\n            List<GUID> guidList = viewList[currentViewIndex].guids.ToList();\n            guidList.Add(group.groupID);\n            viewList[currentViewIndex].guids = guidList.ToArray();\n            views = viewList.ToArray();\n        }\n\n        public void SetCurrentViewVisibility(GUID[] guids)\n        {\n            var viewList = views;\n            viewList[currentViewIndex].guids = guids;\n            views = viewList.ToArray();\n            SanitizeGroupViews();\n        }\n\n        public AudioMixerGroupController[] GetCurrentViewGroupList()\n        {\n            List<AudioMixerGroupController> allGroups = GetAllAudioGroupsSlow();\n            MixerGroupView view = views[currentViewIndex];\n\n            return (from g in allGroups\n                where view.guids.Contains(g.groupID)\n                select g).ToArray();\n        }\n\n        public static float VolumeToScreenMapping(float value, float screenRange, bool forward)\n        {\n            float screenRange1 = GetVolumeSplitPoint() * screenRange;\n            float screenRange2 = screenRange - screenRange1;\n            if (forward)\n                return (value > 0.0f) ? (screenRange1 - Mathf.Pow(value / GetMaxVolume(), 1.0f / kVolumeWarp) * screenRange1) : ((Mathf.Pow(value / kMinVolume, 1.0f / kVolumeWarp) * screenRange2) + screenRange1);\n            return (value < screenRange1) ? (Mathf.Pow(1.0f - (value / screenRange1), kVolumeWarp) * GetMaxVolume()) : (Mathf.Pow((value - screenRange1) / screenRange2, kVolumeWarp) * kMinVolume);\n        }\n\n        public void OnUnitySelectionChanged()\n        {\n            List<AudioMixerGroupController> allGroups = GetAllAudioGroupsSlow();\n\n            var selected = Selection.GetFiltered(typeof(AudioMixerGroupController), SelectionMode.Deep);\n            m_CachedSelection = allGroups.Intersect(selected.Select(g => (AudioMixerGroupController)g)).ToList();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/Bindings/AudioMixerGroup.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor.Audio\n{\n    [ExcludeFromPreset]\n    partial class AudioMixerGroupController\n    {\n        public static Dictionary<AudioMixerEffectController, AudioMixerGroupController> GetEffectMapSlow(List<AudioMixerGroupController> allGroups)\n        {\n            var effectMap = new Dictionary<AudioMixerEffectController, AudioMixerGroupController>();\n\n            foreach (var g in allGroups)\n                foreach (var e in g.effects)\n                    effectMap[e] = g;\n\n            return effectMap;\n        }\n\n        public void InsertEffect(AudioMixerEffectController effect, int index)\n        {\n            var modifiedEffectsList = new List<AudioMixerEffectController>(effects);\n            modifiedEffectsList.Add(null);\n            for (int i = modifiedEffectsList.Count - 1; i > index; i--)\n                modifiedEffectsList[i] = modifiedEffectsList[i - 1];\n            modifiedEffectsList[index] = effect;\n            effects = modifiedEffectsList.ToArray();\n        }\n\n        public bool HasAttenuation()\n        {\n            foreach (var e in effects)\n                if (e.IsAttenuation())\n                    return true;\n            return false;\n        }\n\n        public void DumpHierarchy(string title, int level)\n        {\n            if (title != \"\")\n                Console.WriteLine(title);\n\n            string prefix = \"\";\n            int l = level;\n            while (l-- > 0)\n                prefix += \"  \";\n            Console.WriteLine(prefix + \"name=\" + name);\n\n            prefix += \"  \";\n            foreach (var f in effects)\n                Console.WriteLine(prefix + \"effect=\" + f);\n\n            foreach (var g in children)\n                g.DumpHierarchy(\"\", level + 1);\n        }\n\n        public string GetDisplayString()\n        {\n            return name; // AudioMixerController.FixNameForPopupMenu(name);\n        }\n\n        public override string ToString()\n        {\n            return name;\n        }\n    }\n\n    class MixerGroupControllerCompareByName : IComparer<AudioMixerGroupController>\n    {\n        public int Compare(AudioMixerGroupController x, AudioMixerGroupController y)\n        {\n            return StringComparer.InvariantCultureIgnoreCase.Compare(x.GetDisplayString(), y.GetDisplayString());\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/AudioMixerChannelStripView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System;\nusing UnityEditorInternal;\nusing UnityEditor.Audio;\nusing System.Globalization;\nusing UnityEngine.Audio;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class AudioMixerChannelStripView\n    {\n        [Serializable]\n        public class State\n        {\n            public Vector2 m_ScrollPos = new Vector2(0, 0);\n        }\n\n        public static float kVolumeScaleMouseDrag = 1.0f;\n        public static float kEffectScaleMouseDrag = 0.3f; // higher precision for effect slot editing\n\n        private static Color kMoveColorHighlight = new Color(0.3f, 0.6f, 1.0f, 0.4f);\n        private static Color kMoveSlotColHiAllowed = new Color(1f, 1f, 1f, 0.7f); //new Color(59 / 255f, 162 / 255f, 216 / 255f, 0.7f);\n        private static Color kMoveSlotColLoAllowed = new Color(1f, 1f, 1f, 0.0f);\n        private static Color kMoveSlotColBorderAllowed = new Color(1f, 1f, 1f, 1.0f);\n        private static Color kMoveSlotColHiDisallowed = new Color(1.0f, 0.0f, 0.0f, 0.7f);\n        private static Color kMoveSlotColLoDisallowed = new Color(0.8f, 0.0f, 0.0f, 0.0f);\n        private static Color kMoveSlotColBorderDisallowed = new Color(1.0f, 0.0f, 0.0f, 1.0f);\n        private static int kRectSelectionHashCode = \"RectSelection\".GetHashCode();\n        private static int kEffectDraggingHashCode = \"EffectDragging\".GetHashCode();\n        private static int kVerticalFaderHash = \"VerticalFader\".GetHashCode();\n\n        public int m_FocusIndex = -1;\n        public int m_IndexCounter = 0;\n        public int m_EffectInteractionControlID;\n        public int m_RectSelectionControlID;\n        public float m_MouseDragStartX = 0.0f;\n        public float m_MouseDragStartY = 0.0f;\n        public float m_MouseDragStartValue = 0.0f;\n        public Vector2 m_RectSelectionStartPos = new Vector2(0, 0);\n        public Rect m_RectSelectionRect = new Rect(0, 0, 0, 0);\n\n        State m_State;\n        private AudioMixerController m_Controller;\n        private MixerGroupControllerCompareByName m_GroupComparer = new MixerGroupControllerCompareByName();\n        private bool m_WaitingForDragEvent = false;\n        private int m_ChangingWetMixIndex = -1;\n        private int m_MovingEffectSrcIndex = -1;\n        private int m_MovingEffectDstIndex = -1;\n        private Rect m_MovingSrcRect = new Rect(-1, -1, 0, 0);\n        private Rect m_MovingDstRect = new Rect(-1, -1, 0, 0);\n        private bool m_MovingEffectAllowed = false;\n        private AudioMixerGroupController m_MovingSrcGroup = null;\n        private AudioMixerGroupController m_MovingDstGroup = null;\n        private const float k_MinVULevel = -80f;\n        private List<int> m_LastNumChannels = new List<int>();\n\n        private bool m_RequiresRepaint = false;\n        public bool requiresRepaint\n        {\n            get\n            {\n                if (m_RequiresRepaint)\n                {\n                    m_RequiresRepaint = false;\n                    return true;\n                }\n                return false;\n            }\n        }\n\n        const float headerHeight = 22f;\n        const float vuHeight = 170f;\n        const float dbHeight = 17f;\n        const float soloMuteBypassHeight = 30f;\n        const float effectHeight = 16f;\n        const float spaceBetween = 0;\n        const int channelStripSpacing = 4;\n        const float channelStripBaseWidth = 90f;\n        const float spaceBetweenMainGroupsAndReferenced = 50f;\n        readonly Vector2 channelStripsOffset = new Vector2(15, 10);\n\n        // For background ui\n        static Texture2D m_GridTexture;\n        private const float kGridTileWidth = 12.0f;\n        private static readonly Color kGridColorDark = new Color(0f, 0f, 0f, 0.18f);\n        private static readonly Color kGridColorLight = new Color(0f, 0f, 0f, 0.10f);\n        private static Color gridColor\n        {\n            get\n            {\n                if (EditorGUIUtility.isProSkin)\n                    return kGridColorDark;\n                else\n                    return kGridColorLight;\n            }\n        }\n\n        private AudioMixerDrawUtils.Styles styles\n        {\n            get { return AudioMixerDrawUtils.styles; }\n        }\n\n        public AudioMixerChannelStripView(AudioMixerChannelStripView.State state)\n        {\n            m_State = state;\n        }\n\n        static Texture2D CreateTilableGridTexture(int width, int height, Color backgroundColor, Color lineColor)\n        {\n            Color[] pixels = new Color[width * height];\n\n            // background\n            for (int i = 0; i < height * width; i++)\n                pixels[i] = backgroundColor;\n\n            // right edge\n            for (int i = 0; i < height; i++)\n                pixels[i * width + (width - 1)] = lineColor;\n\n            // bottom edge\n            for (int i = 0; i < width; i++)\n                pixels[(height - 1) * width + i] = lineColor;\n\n            Texture2D texture = new Texture2D(width, height, TextureFormat.RGBA32, false);\n            texture.hideFlags = HideFlags.HideAndDontSave;\n            texture.SetPixels(pixels);\n            texture.Apply();\n            return texture;\n        }\n\n        Texture2D gridTextureTilable\n        {\n            get\n            {\n                if (m_GridTexture == null)\n                    m_GridTexture = CreateTilableGridTexture((int)kGridTileWidth, (int)kGridTileWidth, new Color(0, 0, 0, 0), gridColor);\n                return m_GridTexture;\n            }\n        }\n\n        void DrawAreaBackground(Rect rect)\n        {\n            if (Event.current.type == EventType.Repaint)\n            {\n                // Draw background\n                Color prevColor = GUI.color;\n                GUI.color = new Color(1, 1, 1, EditorGUIUtility.isProSkin ? 0.6f : 0.2f);\n                AudioMixerDrawUtils.styles.channelStripAreaBackground.Draw(rect, false, false, false, false);\n                GUI.color = prevColor;\n                // Draw grid\n                //GUI.DrawTextureWithTexCoords (rect, gridTextureTilable, new Rect(0, 0, rect.width / gridTextureTilable.width, rect.height / gridTextureTilable.height), true);\n            }\n        }\n\n        private void SetFocus() { m_FocusIndex = m_IndexCounter; }\n        private void ClearFocus() { m_FocusIndex = -1; }\n        private bool HasFocus() { return m_FocusIndex == m_IndexCounter; }\n        private bool IsFocusActive() { return m_FocusIndex != -1; }\n\n        public class EffectContext\n        {\n            public EffectContext(AudioMixerController controller, AudioMixerGroupController[] groups, int index, string name)\n            {\n                this.controller = controller;\n                this.groups = groups;\n                this.index = index;\n                this.name = name;\n            }\n\n            public AudioMixerController controller;\n            public AudioMixerGroupController[] groups;\n            public int index;\n            public string name;\n        }\n\n        public static void InsertEffectPopupCallback(object obj)\n        {\n            EffectContext context = (EffectContext)obj;\n\n            foreach (AudioMixerGroupController group in context.groups)\n            {\n                Undo.RecordObject(group, \"Add effect\");\n                AudioMixerEffectController newEffect = new AudioMixerEffectController(context.name);\n\n                int index = (context.index == -1 || context.index > group.effects.Length) ? group.effects.Length : context.index;\n                group.InsertEffect(newEffect, index);\n                AssetDatabase.AddObjectToAsset(newEffect, context.controller);\n                newEffect.PreallocateGUIDs();\n            }\n\n            AudioMixerUtility.RepaintAudioMixerAndInspectors();\n        }\n\n        public void RemoveEffectPopupCallback(object obj)\n        {\n            EffectContext context = (EffectContext)obj;\n\n            foreach (AudioMixerGroupController group in context.groups)\n            {\n                if (context.index >= group.effects.Length)\n                    continue;\n                AudioMixerEffectController effect = group.effects[context.index];\n                context.controller.RemoveEffect(effect, group);\n            }\n\n            AudioMixerUtility.RepaintAudioMixerAndInspectors();\n        }\n\n        public class ConnectSendContext\n        {\n            public ConnectSendContext(AudioMixerController controller, AudioMixerEffectController sendEffect, AudioMixerEffectController targetEffect)\n            {\n                this.controller = controller;\n                this.sendEffect = sendEffect;\n                this.targetEffect = targetEffect;\n            }\n\n            public AudioMixerController controller;\n            public AudioMixerEffectController sendEffect;\n            public AudioMixerEffectController targetEffect;\n        }\n\n        public static void ConnectSendPopupCallback(object obj)\n        {\n            var context = (ConnectSendContext)obj;\n\n            if (context.targetEffect == null)\n            {\n                var guid = context.sendEffect.GetGUIDForMixLevel();\n\n                if (context.controller.ContainsExposedParameter(guid))\n                {\n                    Undo.RecordObjects(new Object[] {context.controller, context.sendEffect}, \"Remove Send Target\");\n                    context.controller.RemoveExposedParameter(guid);\n                }\n            }\n            else\n            {\n                Undo.RecordObject(context.sendEffect, \"Change Send Target\");\n            }\n\n            context.sendEffect.sendTarget = context.targetEffect;\n            AudioMixerUtility.RepaintAudioMixerAndInspectors();\n        }\n\n        private bool ClipRect(Rect r, Rect clipRect, ref Rect overlap)\n        {\n            overlap.x = Mathf.Max(r.x, clipRect.x);\n            overlap.y = Mathf.Max(r.y, clipRect.y);\n            overlap.width = Mathf.Min(r.x + r.width, clipRect.x + clipRect.width) - overlap.x;\n            overlap.height = Mathf.Min(r.y + r.height, clipRect.y + clipRect.height) - overlap.y;\n            return overlap.width > 0.0f && overlap.height > 0.0f;\n        }\n\n        public float VerticalFader(Rect r, float value, int direction, float dragScale, bool drawScaleValues, bool drawMarkerValue, string tooltip, float maxValue, GUIStyle style)\n        {\n            Event evt = Event.current;\n            int handleHeight = (int)style.fixedHeight;\n            int faderScreenRange = (int)r.height - handleHeight;\n            float valueScreenPos = AudioMixerController.VolumeToScreenMapping(Mathf.Clamp(value, AudioMixerController.kMinVolume, maxValue), faderScreenRange, true);\n            Rect handleRect = new Rect(r.x, r.y + (int)valueScreenPos, r.width, handleHeight);\n\n            int controlID = GUIUtility.GetControlID(kVerticalFaderHash, FocusType.Passive);\n\n            switch (evt.GetTypeForControl(controlID))\n            {\n                case EventType.MouseDown:\n                    if (r.Contains(evt.mousePosition) && GUIUtility.hotControl == 0)\n                    {\n                        m_MouseDragStartY = evt.mousePosition.y;\n                        m_MouseDragStartValue = valueScreenPos;\n                        GUIUtility.hotControl = controlID;\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == controlID)\n                    {\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == controlID)\n                    {\n                        valueScreenPos = Mathf.Clamp(m_MouseDragStartValue + dragScale * (evt.mousePosition.y - m_MouseDragStartY), 0.0f, faderScreenRange);\n                        value = Mathf.Clamp(AudioMixerController.VolumeToScreenMapping(valueScreenPos, faderScreenRange, false), AudioMixerController.kMinVolume, maxValue);\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.Repaint:\n\n                    // Ticks and Numbers\n                    if (drawScaleValues)\n                    {\n                        float tickStartY = r.y + handleHeight / 2f;\n                        float level = maxValue;\n                        using (new EditorGUI.DisabledScope(true))\n                        {\n                            while (level >= AudioMixerController.kMinVolume)\n                            {\n                                float y = AudioMixerController.VolumeToScreenMapping(level, faderScreenRange, true);\n\n                                if (level / 10 % 2 == 0)\n                                    GUI.Label(new Rect(r.x, tickStartY + y - 7, r.width, 14), GUIContent.Temp(Mathf.RoundToInt(level).ToString()), styles.vuValue);\n                                EditorGUI.DrawRect(new Rect(r.x, tickStartY + y - 1, 5f, 1), new Color(0, 0, 0, 0.5f));\n                                level -= 10.0f;\n                            }\n                        }\n                    }\n\n                    // Drag handle\n                    if (drawMarkerValue)\n                        style.Draw(handleRect, GUIContent.Temp(Mathf.RoundToInt(value).ToString()), false, false, false, false);\n                    else\n                        style.Draw(handleRect, false, false, false, false);\n                    AudioMixerDrawUtils.AddTooltipOverlay(handleRect, tooltip);\n                    break;\n            }\n\n            return value;\n        }\n\n        private static Color hfaderCol1 = new Color(0.2f, 0.2f, 0.2f, 1.0f);\n        private static Color hfaderCol2 = new Color(0.4f, 0.4f, 0.4f, 1.0f);\n\n        public float HorizontalFader(Rect r, float value, float minValue, float maxValue, int direction, float dragScale)\n        {\n            m_IndexCounter++;\n            Rect r2 = new Rect(r);\n            float handleWidth = r.width * 0.2f, faderScreenRange = r2.width - handleWidth;\n            AudioMixerDrawUtils.DrawGradientRect(r2, hfaderCol1, hfaderCol2);\n            Event evt = Event.current;\n            if (evt.type == EventType.MouseDown && r2.Contains(evt.mousePosition))\n            {\n                m_MouseDragStartX = evt.mousePosition.x;\n                m_MouseDragStartValue = value;\n                SetFocus();\n            }\n            if (HasFocus())\n            {\n                if (evt.type == EventType.MouseDrag)\n                {\n                    value = m_MouseDragStartValue + (dragScale * (maxValue - minValue) * (evt.mousePosition.x - m_MouseDragStartX) / faderScreenRange);\n                    Event.current.Use();\n                }\n                else if (evt.type == EventType.MouseUp)\n                {\n                    ClearFocus();\n                    Event.current.Use();\n                }\n            }\n            value = Mathf.Clamp(value, minValue, maxValue);\n            r2.x = r.x;\n            r2.width = r.width;\n            r2.x = r.x + faderScreenRange * ((value - minValue) / (maxValue - minValue));\n            r2.width = handleWidth;\n            AudioMixerDrawUtils.DrawGradientRect(r2, hfaderCol2, hfaderCol1);\n            return value;\n        }\n\n        public GUIStyle GetEffectBarStyle(AudioMixerEffectController effect)\n        {\n            if (effect.IsSend() || effect.IsReceive() || effect.IsDuckVolume())\n                return styles.sendReturnBar;\n            if (effect.IsAttenuation())\n                return styles.attenuationBar;\n\n            return styles.effectBar;\n        }\n\n        class PatchSlot\n        {\n            public AudioMixerGroupController group;\n            public float x, y;\n        }\n\n        GUIContent bypassButtonContent = EditorGUIUtility.TrTextContent(\"\", \"Toggle bypass on this effect\");\n        void EffectSlot(Rect effectRect, AudioMixerSnapshotController snapshot, AudioMixerEffectController effect, int effectIndex, ref int highlightEffectIndex, ChannelStripParams p, ref Dictionary<AudioMixerEffectController, PatchSlot> patchslots)\n        {\n            if (effect == null)\n                return;\n\n            Rect r = effectRect;\n\n            Event evt = Event.current;\n            if (evt.type == EventType.Repaint && patchslots != null && (effect.IsSend() || MixerEffectDefinitions.EffectCanBeSidechainTarget(effect)))\n            {\n                var c = new PatchSlot();\n                c.group = p.group;\n                c.x = r.xMax - (r.yMax - r.yMin) * 0.5f;\n                c.y = (r.yMin + r.yMax) * 0.5f;\n                patchslots[effect] = c;\n            }\n\n            // Bypass button\n            const float bypassWidth = 10.0f;\n            bool isBypassable = !effect.DisallowsBypass();\n            Rect bypassRect = r; bypassRect.width = bypassWidth;\n            r.xMin += bypassWidth;\n            if (isBypassable)\n            {\n                // Handle mouse input is first, rendering is further down (to render on top).\n                if (GUI.Button(bypassRect, bypassButtonContent, GUIStyle.none))\n                {\n                    Undo.RecordObject(effect, \"Bypass Effect\");\n                    effect.bypass = !effect.bypass;\n                    m_Controller.UpdateBypass();\n                    InspectorWindow.RepaintAllInspectors();\n                }\n            }\n\n            // Effect\n            m_IndexCounter++;\n\n            // Repaint\n            // We are using the following GUIStyle backgrounds for:\n            //  Normal: Disabled by bypass or group bypass\n            //  Hover: Enabled, not draggable\n            //  Active: Enabled, background for draggable bar\n            //  Focused: Enabled, foreground for draggable bar\n\n            float level = Mathf.Clamp(effect.GetValueForMixLevel(m_Controller, snapshot), AudioMixerController.kMinVolume, AudioMixerController.kMaxEffect);\n            bool showLevel = (effect.IsSend() && effect.sendTarget != null) || effect.enableWetMix;\n            if (evt.type == EventType.Repaint)\n            {\n                GUIStyle style = GetEffectBarStyle(effect);\n\n                float drawLevel = (showLevel) ? ((level - AudioMixerController.kMinVolume) / (AudioMixerController.kMaxEffect - AudioMixerController.kMinVolume)) : 1.0f;\n                bool enabled = (!p.group.bypassEffects && !effect.bypass) || effect.DisallowsBypass();\n                Color col1 = AudioMixerDrawUtils.GetEffectColor(effect);\n                if (!enabled)\n                    col1 = new Color(col1.r * 0.5f, col1.g * 0.5f, col1.b * 0.5f);\n\n                if (enabled)\n                {\n                    if (drawLevel < 1.0f)\n                    {\n                        // Bar forground (we need special for small widths because style rendering with borders have a min width to work)\n                        float forgroundWidth = r.width * drawLevel;\n                        const float minimumWidthForBorderSetup = 4f;\n                        if (forgroundWidth < minimumWidthForBorderSetup)\n                        {\n                            // Forground less than minimumWidthForBorderSetup (Always show marker to indicate the slot is draggable)\n                            const float markerWidth = 2f;\n                            forgroundWidth = Mathf.Max(forgroundWidth, markerWidth);\n                            float frac = 1f - forgroundWidth / minimumWidthForBorderSetup;\n\n                            Color orgColor = GUI.color;\n                            if (!GUI.enabled)\n                                GUI.color = new Color(1, 1, 1, 0.5f);\n                            GUI.DrawTextureWithTexCoords(new Rect(r.x, r.y, forgroundWidth, r.height), style.focused.background, new Rect(frac, 0f, 1f - frac, 1f));\n                            GUI.color = orgColor;\n                        }\n                        else\n                        {\n                            // Forground larger than minimumWidthForBorderSetup (uses border setup)\n                            style.Draw(new Rect(r.x, r.y, forgroundWidth, r.height), false, false, false, true);\n                        }\n\n                        // Bar background\n                        GUI.DrawTexture(new Rect(r.x + forgroundWidth, r.y, r.width - forgroundWidth, r.height), style.onFocused.background, ScaleMode.StretchToFill);\n                    }\n                    else\n                    {\n                        //GUI.DrawTexture(r, showLevel ? style.focused.background : style.hover.background, ScaleMode.StretchToFill);\n                        style.Draw(r, !showLevel, false, false, showLevel);\n                    }\n\n                    // Cursor icon needs to proper work with dragging: TODO use hotcontrol\n                    //if (showLevel)\n                    //  EditorGUIUtility.AddCursorRect(r, MouseCursor.SlideArrow);\n                }\n                else\n                {\n                    // Disabled\n                    style.Draw(r, false, false, false, false);\n                }\n\n                // Bypass toggle\n                if (isBypassable)\n                    styles.circularToggle.Draw(new Rect(bypassRect.x + 2, bypassRect.y + 5f, bypassRect.width - 2, bypassRect.width - 2f), false, false, !effect.bypass, false);\n\n                if (effect.IsSend() && effect.sendTarget != null)\n                {\n                    bypassRect.y -= 1;\n                    GUI.Label(bypassRect, styles.sendString, EditorStyles.miniLabel);\n                }\n\n                using (new EditorGUI.DisabledScope(!enabled))\n                {\n                    string name = GetEffectSlotName(effect, showLevel, snapshot, p);\n                    string tooltip = GetEffectSlotTooltip(effect, r, p);\n                    GUI.Label(new Rect(r.x, r.y, r.width - bypassWidth, r.height), GUIContent.Temp(name, tooltip), styles.effectName);\n                }\n            }\n            else\n            {\n                EffectSlotDragging(effectRect, snapshot, effect, showLevel, level, effectIndex, ref highlightEffectIndex, p);\n            }\n        }\n\n        string GetEffectSlotName(AudioMixerEffectController effect, bool showLevel, AudioMixerSnapshotController snapshot, ChannelStripParams p)\n        {\n            if (m_ChangingWetMixIndex == m_IndexCounter && showLevel)\n            {\n                return string.Format(\"{0:F1} dB\", effect.GetValueForMixLevel(m_Controller, snapshot));\n            }\n\n            if (effect.IsSend() && effect.sendTarget != null)\n            {\n                return effect.GetSendTargetDisplayString(p.effectMap);\n            }\n\n            return effect.effectName;\n        }\n\n        string GetEffectSlotTooltip(AudioMixerEffectController effect, Rect effectRect, ChannelStripParams p)\n        {\n            // Only fetch a tooltip if the cursor is inside the rect\n            if (!effectRect.Contains(Event.current.mousePosition))\n                return string.Empty;\n\n            if (effect.IsSend())\n            {\n                if (effect.sendTarget != null)\n                {\n                    string sendTarget = effect.GetSendTargetDisplayString(p.effectMap);\n                    return \"Send to: \" + sendTarget; // We add the tooltip here because we rarely\n                }\n                else\n                {\n                    return styles.emptySendSlotGUIContent.tooltip;\n                }\n            }\n            if (effect.IsReceive())\n            {\n                return styles.returnSlotGUIContent.tooltip;\n            }\n            if (effect.IsDuckVolume())\n            {\n                return styles.duckVolumeSlotGUIContent.tooltip;\n            }\n            if (effect.IsAttenuation())\n            {\n                return styles.attenuationSlotGUIContent.tooltip;\n            }\n\n            // Tooltip for all other effects\n            return styles.effectSlotGUIContent.tooltip;\n        }\n\n        private void EffectSlotDragging(Rect r, AudioMixerSnapshotController snapshot, AudioMixerEffectController effect, bool showLevel, float level, int effectIndex, ref int highlightEffectIndex, ChannelStripParams p)\n        {\n            Event evt = Event.current;\n\n            switch (evt.GetTypeForControl(m_EffectInteractionControlID))\n            {\n                case EventType.MouseDown:\n                    if (r.Contains(evt.mousePosition) && evt.button == 0 && GUIUtility.hotControl == 0)\n                    {\n                        GUIUtility.hotControl = m_EffectInteractionControlID;\n                        m_MouseDragStartX = evt.mousePosition.x;\n                        m_MouseDragStartValue = level;\n                        highlightEffectIndex = effectIndex;\n                        m_MovingEffectSrcIndex = -1;\n                        m_MovingEffectDstIndex = -1;\n                        m_WaitingForDragEvent = true;\n                        m_MovingSrcRect = r;\n                        m_MovingDstRect = r;\n                        m_MovingSrcGroup = p.group;\n                        m_MovingDstGroup = p.group;\n                        m_MovingEffectAllowed = true;\n                        SetFocus();\n                        Event.current.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(1);\n                        InspectorWindow.RepaintAllInspectors();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == m_EffectInteractionControlID && evt.button == 0 && p.stripRect.Contains(evt.mousePosition))\n                    {\n                        if (m_MovingEffectDstIndex != -1 && m_MovingEffectAllowed)\n                        {\n                            if (IsDuplicateKeyPressed() && CanDuplicateDraggedEffect())\n                            {\n                                // Duplicate effect\n                                AudioMixerEffectController sourceEffect = m_MovingSrcGroup.effects[m_MovingEffectSrcIndex];\n                                AudioMixerEffectController copiedEffect = m_MovingSrcGroup.controller.CopyEffect(sourceEffect);\n                                var targetEffects = m_MovingDstGroup.effects.ToList();\n                                if (AudioMixerController.InsertEffect(copiedEffect, ref targetEffects, m_MovingEffectDstIndex))\n                                {\n                                    m_MovingDstGroup.effects = targetEffects.ToArray();\n                                }\n                            }\n                            else\n                            {\n                                // Move effect\n                                if (m_MovingSrcGroup == m_MovingDstGroup)\n                                {\n                                    var effects = m_MovingSrcGroup.effects.ToList();\n                                    if (AudioMixerController.MoveEffect(ref effects, m_MovingEffectSrcIndex, ref effects, m_MovingEffectDstIndex))\n                                    {\n                                        m_MovingSrcGroup.effects = effects.ToArray();\n                                    }\n                                }\n                                else if (!m_MovingSrcGroup.effects[m_MovingEffectSrcIndex].IsAttenuation())\n                                {\n                                    var sourceEffects = m_MovingSrcGroup.effects.ToList();\n                                    var targetEffects = m_MovingDstGroup.effects.ToList();\n                                    if (AudioMixerController.MoveEffect(ref sourceEffects, m_MovingEffectSrcIndex, ref targetEffects, m_MovingEffectDstIndex))\n                                    {\n                                        m_MovingSrcGroup.effects = sourceEffects.ToArray();\n                                        m_MovingDstGroup.effects = targetEffects.ToArray();\n                                    }\n                                }\n                            }\n                        }\n\n                        ClearEffectDragging(ref highlightEffectIndex);\n                        evt.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(0);\n                        GUIUtility.ExitGUI();  // We changed order of effects so stop iterating effects\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n\n                    if (GUIUtility.hotControl == m_EffectInteractionControlID)\n                    {\n                        // Detect direction of drag to decide if we want to adjust value or move effect\n                        if (HasFocus() && m_WaitingForDragEvent && (evt.delta.x != 0 || evt.delta.y != 0))\n                        {\n                            m_ChangingWetMixIndex = -1;\n                            if (effectIndex < p.group.effects.Length)\n                            {\n                                if (Mathf.Abs(evt.delta.y) > Mathf.Abs(evt.delta.x))\n                                {\n                                    // Move effect\n                                    m_MovingEffectSrcIndex = effectIndex;\n                                    ClearFocus();\n                                }\n                                else\n                                {\n                                    // Change wet mix value\n                                    m_ChangingWetMixIndex = m_IndexCounter;\n                                }\n                            }\n                            m_WaitingForDragEvent = false;\n                        }\n\n                        // Moving effect so detect effect insertion on this strip\n                        if (IsMovingEffect() && p.stripRect.Contains(evt.mousePosition))\n                        {\n                            float h2 = r.height * 0.5f;\n                            float min = effectIndex == 0 ? -h2 : 0;\n                            float max = effectIndex == p.group.effects.Length - 1 ? r.height + h2 : r.height;\n                            float dy = evt.mousePosition.y - r.y;\n                            if (dy >= min && dy <= max && effectIndex < p.group.effects.Length)\n                            {\n                                int newMovingEffectDstIndex = (dy < h2) ? effectIndex : (effectIndex + 1);\n                                if (newMovingEffectDstIndex != m_MovingEffectDstIndex || m_MovingDstGroup != p.group)\n                                {\n                                    m_MovingDstRect.x = r.x;\n                                    m_MovingDstRect.width = r.width;\n                                    m_MovingDstRect.y = ((dy < h2) ? r.y : (r.y + r.height)) - 1;\n                                    m_MovingEffectDstIndex = newMovingEffectDstIndex;\n                                    m_MovingDstGroup = p.group;\n                                    m_MovingEffectAllowed =\n                                        !(m_MovingSrcGroup.effects[m_MovingEffectSrcIndex].IsAttenuation() && m_MovingSrcGroup != m_MovingDstGroup) &&\n                                        !AudioMixerController.WillMovingEffectCauseFeedback(p.allGroups, m_MovingSrcGroup, m_MovingEffectSrcIndex, m_MovingDstGroup, newMovingEffectDstIndex, null) &&\n                                        (!IsDuplicateKeyPressed() || CanDuplicateDraggedEffect());\n                                }\n                                evt.Use(); // We use when having valid pos so because if drag event is not used after all strips we clear drag destination to remove insert hightlight for invalid positions\n                            }\n                        }\n\n                        // Changing wetmix level\n                        if (IsAdjustingWetMix() && HasFocus())\n                        {\n                            if (showLevel)\n                            {\n                                m_WaitingForDragEvent = false;\n\n                                float tmp = kEffectScaleMouseDrag * HandleUtility.niceMouseDelta + level;\n                                float deltaLevel = Mathf.Clamp(tmp, AudioMixerController.kMinVolume, AudioMixerController.kMaxEffect) - level;\n                                if (deltaLevel != 0.0f)\n                                {\n                                    Undo.RecordObject(m_Controller.TargetSnapshot, \"Change effect level\");\n                                    if (effect.IsSend() && m_Controller.CachedSelection.Count > 1 && m_Controller.CachedSelection.Contains(p.group))\n                                    {\n                                        List<AudioMixerEffectController> changeEffects = new List<AudioMixerEffectController>();\n                                        foreach (var g in m_Controller.CachedSelection)\n                                            foreach (var e in g.effects)\n                                                if (e.effectName == effect.effectName && e.sendTarget == effect.sendTarget)\n                                                    changeEffects.Add(e);\n                                        foreach (var e in changeEffects)\n                                            if (!e.IsSend() || e.sendTarget != null)\n                                                e.SetValueForMixLevel(\n                                                    m_Controller,\n                                                    snapshot,\n                                                    Mathf.Clamp(e.GetValueForMixLevel(m_Controller, snapshot) + deltaLevel, AudioMixerController.kMinVolume, AudioMixerController.kMaxEffect));\n                                    }\n                                    else\n                                    {\n                                        if (!effect.IsSend() || effect.sendTarget != null)\n                                            effect.SetValueForMixLevel(\n                                                m_Controller,\n                                                snapshot,\n                                                Mathf.Clamp(level + deltaLevel, AudioMixerController.kMinVolume, AudioMixerController.kMaxEffect));\n                                    }\n                                    InspectorWindow.RepaintAllInspectors();\n                                }\n                                evt.Use();\n                            }\n                        }\n                    }\n                    break;\n            }\n        }\n\n        void ClearEffectDragging(ref int highlightEffectIndex)\n        {\n            if (GUIUtility.hotControl == m_EffectInteractionControlID)\n                GUIUtility.hotControl = 0;\n            m_MovingEffectSrcIndex = -1;\n            m_MovingEffectDstIndex = -1;\n            m_MovingSrcRect = new Rect(-1, -1, 0, 0);\n            m_MovingDstRect = new Rect(-1, -1, 0, 0);\n            m_MovingSrcGroup = null;\n            m_MovingDstGroup = null;\n            m_ChangingWetMixIndex = -1;\n            highlightEffectIndex = -1;\n            ClearFocus();\n            InspectorWindow.RepaintAllInspectors();\n        }\n\n        void UnhandledEffectDraggingEvents(ref int highlightEffectIndex)\n        {\n            Event evt = Event.current;\n\n            switch (evt.GetTypeForControl(m_EffectInteractionControlID))\n            {\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == m_EffectInteractionControlID && evt.button == 0)\n                    {\n                        ClearEffectDragging(ref highlightEffectIndex);\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == m_EffectInteractionControlID)\n                    {\n                        // Clear dst group when dragging outside the strips\n                        m_MovingEffectDstIndex = -1;\n                        m_MovingDstRect = new Rect(-1, -1, 0, 0);\n                        m_MovingDstGroup = null;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.Repaint:\n\n                    if (IsMovingEffect())\n                    {\n                        // Mark the effect being dragged\n                        if (evt.type == EventType.Repaint)\n                        {\n                            EditorGUI.DrawRect(m_MovingSrcRect, kMoveColorHighlight);\n\n                            // Set + cursor when duplicating dragged effect\n                            var cursor = (IsDuplicateKeyPressed() && m_MovingEffectAllowed) ? MouseCursor.ArrowPlus : MouseCursor.ResizeVertical;\n                            EditorGUIUtility.AddCursorRect(new Rect(evt.mousePosition.x - 10, evt.mousePosition.y - 10, 20, 20), cursor, m_EffectInteractionControlID);\n                        }\n                    }\n\n                    if (m_MovingEffectDstIndex != -1 && m_MovingDstRect.y >= 0.0f)// && m_MovingEffectDstIndex != m_MovingEffectSrcIndex && m_MovingEffectDstIndex != m_MovingEffectSrcIndex +1)\n                    {\n                        float kMoveRange = 2;\n                        Color moveSlotColLo = (m_MovingEffectAllowed) ? kMoveSlotColLoAllowed : kMoveSlotColLoDisallowed;\n                        Color moveSlotColHi = (m_MovingEffectAllowed) ? kMoveSlotColHiAllowed : kMoveSlotColHiDisallowed;\n                        Color moveSlotColBorder = (m_MovingEffectAllowed) ? kMoveSlotColBorderAllowed : kMoveSlotColBorderDisallowed;\n                        AudioMixerDrawUtils.DrawGradientRect(new Rect(m_MovingDstRect.x, m_MovingDstRect.y - kMoveRange, m_MovingDstRect.width, kMoveRange), moveSlotColLo, moveSlotColHi);\n                        AudioMixerDrawUtils.DrawGradientRect(new Rect(m_MovingDstRect.x, m_MovingDstRect.y, m_MovingDstRect.width, kMoveRange), moveSlotColHi, moveSlotColLo);\n                        AudioMixerDrawUtils.DrawGradientRect(new Rect(m_MovingDstRect.x, m_MovingDstRect.y - 1, m_MovingDstRect.width, 1), moveSlotColBorder, moveSlotColBorder);\n                    }\n\n                    break;\n            }\n        }\n\n        bool IsDuplicateKeyPressed()\n        {\n            return Event.current.alt;\n        }\n\n        bool CanDuplicateDraggedEffect()\n        {\n            if (IsMovingEffect() && m_MovingSrcGroup != null)\n                return !m_MovingSrcGroup.effects[m_MovingEffectSrcIndex].IsAttenuation();\n            return false;\n        }\n\n        private class BusConnection\n        {\n            public BusConnection(float srcX, float srcY, AudioMixerEffectController targetEffect, float mixLevel, Color col, bool isSend, bool isSelected)\n            {\n                this.srcX = srcX;\n                this.srcY = srcY;\n                this.targetEffect = targetEffect;\n                this.mixLevel = mixLevel;\n                this.color = col;\n                this.isSend = isSend;\n                this.isSelected = isSelected;\n            }\n\n            public AudioMixerEffectController targetEffect;\n            public float srcX;\n            public float srcY;\n            public float mixLevel;\n            public Color color;\n            public bool isSend;\n            public bool isSelected;\n        }\n\n        private void RecordSelectedGroupUndoState(List<AudioMixerGroupController> selection, string text)\n        {\n            foreach (var g in selection)\n            {\n                Undo.RecordObject(g, text);\n            }\n        }\n\n        private bool DoSoloButton(Rect r, AudioMixerGroupController group, List<AudioMixerGroupController> allGroups, List<AudioMixerGroupController> selection)\n        {\n            Event evt = Event.current;\n\n            // Right click toggle\n            if (evt.type == EventType.MouseUp && evt.button == 1 && r.Contains(evt.mousePosition) && allGroups.Any(g => g.solo))\n            {\n                RecordSelectedGroupUndoState(selection, \"Change solo state\");\n                foreach (var g in allGroups)\n                    g.solo = false;\n                evt.Use();\n                return true;\n            }\n\n            bool newState = GUI.Toggle(r, group.solo, styles.soloGUIContent, AudioMixerDrawUtils.styles.soloToggle);\n            if (newState != group.solo)\n            {\n                RecordSelectedGroupUndoState(selection, \"Change solo state\");\n                group.solo = !group.solo;\n                foreach (var g in selection)\n                    g.solo = group.solo;\n                return true;\n            }\n\n\n            return false;\n        }\n\n        private bool DoMuteButton(Rect r, AudioMixerGroupController group, List<AudioMixerGroupController> allGroups, bool anySoloActive, List<AudioMixerGroupController> selection)\n        {\n            Event evt = Event.current;\n            // Right click toggle\n            if (evt.type == EventType.MouseUp && evt.button == 1 && r.Contains(evt.mousePosition) && allGroups.Any(g => g.mute))\n            {\n                RecordSelectedGroupUndoState(selection, \"Change mute state\");\n                if (allGroups.Any(g => g.solo))\n                    return false;\n                foreach (var g in allGroups)\n                    g.mute = false;\n                evt.Use();\n                return true;\n            }\n            Color orgColor = GUI.color;\n            bool dimColor = anySoloActive && group.mute;\n            if (dimColor)\n                GUI.color = new Color(GUI.color.r, GUI.color.g, GUI.color.b, 0.5f);\n            bool newState = GUI.Toggle(r, group.mute, styles.muteGUIContent, AudioMixerDrawUtils.styles.muteToggle);\n            if (dimColor)\n                GUI.color = orgColor;\n\n            if (newState != group.mute)\n            {\n                RecordSelectedGroupUndoState(selection, \"Change mute state\");\n                group.mute = !group.mute;\n                foreach (var g in selection)\n                    g.mute = group.mute;\n                return true;\n            }\n\n            return false;\n        }\n\n        private bool DoBypassEffectsButton(Rect r, AudioMixerGroupController group, List<AudioMixerGroupController> allGroups, List<AudioMixerGroupController> selection)\n        {\n            Event evt = Event.current;\n            // Right click toggle\n            if (evt.type == EventType.MouseUp && evt.button == 1 && r.Contains(evt.mousePosition) && allGroups.Any(g => g.bypassEffects))\n            {\n                RecordSelectedGroupUndoState(selection, \"Change bypass state\");\n                foreach (var g in allGroups)\n                    g.bypassEffects = false;\n                evt.Use();\n                return true;\n            }\n\n            bool newState = GUI.Toggle(r, group.bypassEffects, styles.bypassGUIContent, AudioMixerDrawUtils.styles.bypassToggle);\n            if (newState != group.bypassEffects)\n            {\n                RecordSelectedGroupUndoState(selection, \"Change bypass state\");\n                group.bypassEffects = !group.bypassEffects;\n                foreach (var g in selection)\n                    g.bypassEffects = group.bypassEffects;\n                return true;\n            }\n\n            return false;\n        }\n\n        private static bool RectOverlaps(Rect r1, Rect r2)\n        {\n            Rect overlap = new Rect();\n            overlap.x = Mathf.Max(r1.x, r2.x);\n            overlap.y = Mathf.Max(r1.y, r2.y);\n            overlap.width = Mathf.Min(r1.x + r1.width, r2.x + r2.width) - overlap.x;\n            overlap.height = Mathf.Min(r1.y + r1.height, r2.y + r2.height) - overlap.y;\n            return overlap.width > 0.0f && overlap.height > 0.0f;\n        }\n\n        bool IsRectSelectionActive()\n        {\n            return GUIUtility.hotControl == m_RectSelectionControlID;\n        }\n\n        // Handles multiselection (using shift + ctrl/cmd)\n        void GroupClicked(AudioMixerGroupController clickedGroup, ChannelStripParams p, bool clickedControlInGroup)\n        {\n            // Get ids from items\n            List<int> allIDs = new List<int>();\n            foreach (var group in p.shownGroups)\n                allIDs.Add(group.GetInstanceID());\n\n            List<int> selectedIDs = new List<int>();\n            foreach (var group in m_Controller.CachedSelection)\n                selectedIDs.Add(group.GetInstanceID());\n\n            int lastClickedID = selectedIDs.Count > 0 ? selectedIDs.Last() : 0;\n            bool allowMultiselection = true;\n            bool keepMultiSelection = Event.current.shift || clickedControlInGroup;\n            bool useShiftAsActionKey = false;\n\n            List<int> newSelection = InternalEditorUtility.GetNewSelection(clickedGroup.GetInstanceID(), allIDs, selectedIDs, lastClickedID, keepMultiSelection, useShiftAsActionKey, allowMultiselection);\n            List<AudioMixerGroupController> groups = (from x in p.allGroups where newSelection.Contains(x.GetInstanceID()) select x).ToList();\n\n            Selection.objects = groups.ToArray();\n            m_Controller.OnUnitySelectionChanged();\n\n            InspectorWindow.RepaintAllInspectors();\n        }\n\n        private void DoAttenuationFader(Rect r, AudioMixerGroupController group, List<AudioMixerGroupController> selection, GUIStyle style)\n        {\n            float volume = Mathf.Clamp(group.GetValueForVolume(m_Controller, m_Controller.TargetSnapshot), AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume());\n            float newVolume = VerticalFader(r, volume, 1, kVolumeScaleMouseDrag, true, true, styles.attenuationFader.tooltip, AudioMixerController.GetMaxVolume(), style);\n            if (volume != newVolume)\n            {\n                float deltaVolume = newVolume - volume;\n                Undo.RecordObject(m_Controller.TargetSnapshot, \"Change volume fader\");\n                foreach (var g in selection)\n                {\n                    float vol = Mathf.Clamp(g.GetValueForVolume(m_Controller, m_Controller.TargetSnapshot), AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume());\n                    g.SetValueForVolume(\n                        m_Controller,\n                        m_Controller.TargetSnapshot,\n                        Mathf.Clamp(vol + deltaVolume, AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume()));\n                }\n                InspectorWindow.RepaintAllInspectors();\n            }\n        }\n\n        static internal void AddEffectItemsToMenu(AudioMixerController controller, AudioMixerGroupController[] groups, int insertIndex, string prefix, GenericMenu pm)\n        {\n            string[] effectNames = MixerEffectDefinitions.GetEffectList();\n            for (int t = 0; t < effectNames.Length; t++)\n            {\n                if (effectNames[t] != \"Attenuation\")\n                    pm.AddItem(new GUIContent(prefix + effectNames[t]),\n                        false,\n                        InsertEffectPopupCallback,\n                        new EffectContext(controller, groups, insertIndex, effectNames[t]));\n            }\n        }\n\n        private void DoEffectSlotInsertEffectPopup(Rect buttonRect, AudioMixerGroupController group, List<AudioMixerGroupController> allGroups,\n            int effectSlotIndex, ref Dictionary<AudioMixerEffectController, AudioMixerGroupController> effectMap)\n        {\n            GenericMenu pm = new GenericMenu();\n\n            AudioMixerGroupController[] groups = new AudioMixerGroupController[] { group };\n\n            if (effectSlotIndex < group.effects.Length)\n            {\n                var effect = group.effects[effectSlotIndex];\n                if (!effect.IsAttenuation() && !effect.IsSend() && !effect.IsReceive() && !effect.IsDuckVolume())\n                {\n                    pm.AddItem(EditorGUIUtility.TrTextContent(\"Allow Wet Mixing (causes higher memory usage)\"), effect.enableWetMix, delegate { AudioMixerUtility.ToggleEffectWetMix(effect); });\n                    pm.AddItem(EditorGUIUtility.TrTextContent(\"Bypass\"), effect.bypass, delegate { effect.bypass = !effect.bypass; m_Controller.UpdateBypass(); InspectorWindow.RepaintAllInspectors(); });\n                    pm.AddSeparator(\"\");\n                }\n\n                AddEffectItemsToMenu(group.controller, groups, effectSlotIndex, \"Add effect before/\", pm);\n                AddEffectItemsToMenu(group.controller, groups, effectSlotIndex + 1, \"Add effect after/\", pm);\n            }\n            else\n            {\n                // Add effect at the end of the list\n                AddEffectItemsToMenu(group.controller, groups, effectSlotIndex, \"\", pm);\n            }\n\n            if (effectSlotIndex < group.effects.Length)\n            {\n                var effect = group.effects[effectSlotIndex];\n                if (!effect.IsAttenuation())\n                {\n                    pm.AddSeparator(\"\");\n                    pm.AddItem(EditorGUIUtility.TrTextContent(\"Remove\"), false, RemoveEffectPopupCallback, new EffectContext(m_Controller, groups, effectSlotIndex, \"\"));\n                    bool insertedSeparator = false;\n                    if (effect.IsSend())\n                    {\n                        if (effect.sendTarget != null)\n                        {\n                            if (!insertedSeparator)\n                            {\n                                insertedSeparator = true;\n                                pm.AddSeparator(\"\");\n                            }\n\n                            var sendContext = new ConnectSendContext(group.controller, effect, null);\n                            pm.AddItem(EditorGUIUtility.TrTextContent(\"Disconnect from '\" + effect.GetSendTargetDisplayString(effectMap) + \"'\") , false, ConnectSendPopupCallback, sendContext);\n                        }\n\n                        if (!insertedSeparator)\n                            AddSeperatorIfAnyReturns(pm, allGroups);\n                        AddMenuItemsForReturns(pm, \"Connect to \", effectSlotIndex, group, allGroups, effectMap, effect, false);\n                    }\n                }\n            }\n            pm.DropDown(buttonRect);\n            Event.current.Use();\n        }\n\n        void AddSeperatorIfAnyReturns(GenericMenu pm, List<AudioMixerGroupController> allGroups)\n        {\n            foreach (var g in allGroups)\n            {\n                foreach (var ge in g.effects)\n                {\n                    if (ge.IsReceive() || ge.IsDuckVolume())\n                    {\n                        pm.AddSeparator(\"\");\n                        return;\n                    }\n                }\n            }\n        }\n\n        public static void AddMenuItemsForReturns(GenericMenu pm, string prefix, int effectIndex, AudioMixerGroupController group, List<AudioMixerGroupController> allGroups,\n            Dictionary<AudioMixerEffectController, AudioMixerGroupController> effectMap, AudioMixerEffectController effect, bool showCurrent)\n        {\n            foreach (var g in allGroups)\n            {\n                foreach (var ge in g.effects)\n                {\n                    if (MixerEffectDefinitions.EffectCanBeSidechainTarget(ge))\n                    {\n                        var identifiedLoop = new List<AudioMixerController.ConnectionNode>();\n\n                        //TODO: In the future, consider allowing feedback loops, as the send code now allows for this, though give a warning to the user\n                        // that they may be doing something stupid\n                        if (!AudioMixerController.WillChangeOfEffectTargetCauseFeedback(allGroups, group, effectIndex, ge, identifiedLoop))\n                        {\n                            if (showCurrent || effect.sendTarget != ge)\n                            {\n                                var sendContext = new ConnectSendContext(group.controller, effect, ge);\n                                pm.AddItem(new GUIContent(prefix + \"'\" + ge.GetDisplayString(effectMap) + \"'\"), effect.sendTarget == ge, ConnectSendPopupCallback, sendContext);\n                            }\n                        }\n                        else\n                        {\n                            string baseString = \"A connection to '\" + ge.GetDisplayString(effectMap) + \"' would result in a feedback loop/\";\n                            pm.AddDisabledItem(new GUIContent(baseString + \"Loop: \"));\n                            int loopIndex = 1;\n                            foreach (var s in identifiedLoop)\n                            {\n                                pm.AddDisabledItem(new GUIContent(baseString + loopIndex + \": \" + s.GetDisplayString() + \"->\"));\n                                loopIndex++;\n                            }\n                            pm.AddDisabledItem(new GUIContent(baseString + loopIndex + \": ...\"));\n                        }\n                    }\n                }\n            }\n        }\n\n        public void VUMeter(AudioMixerGroupController group, Rect r, float level, float peak)\n        {\n            EditorGUI.VUMeter.VerticalMeter(r, level, peak,  EditorGUI.VUMeter.verticalVUTexture, Color.grey);\n        }\n\n        private GUIContent headerGUIContent = new GUIContent();\n\n        class ChannelStripParams\n        {\n            public int index;\n            public Rect stripRect;\n            public Rect visibleRect;\n            public bool visible;\n            public AudioMixerGroupController group;\n            public int maxEffects;\n            public bool drawingBuses;\n            public bool anySoloActive;\n            public List<BusConnection> busConnections = new List<BusConnection>();\n            public List<AudioMixerGroupController> rectSelectionGroups = new List<AudioMixerGroupController>();\n            public List<AudioMixerGroupController> allGroups;\n            public List<AudioMixerGroupController> shownGroups;\n\n            public int numChannels = 0;\n            public float[] vuinfo_level = new float[9];\n            public float[] vuinfo_peak = new float[9];\n\n            //public int highlightEffectIndex;\n            public Dictionary<AudioMixerEffectController, AudioMixerGroupController> effectMap;\n\n            const float kAddEffectButtonHeight = 16f;\n\n            public List<Rect> bgRects;\n            public readonly int kHeaderIndex = 0;\n            public readonly int kVUMeterFaderIndex = 1;\n            public readonly int kTotalVULevelIndex = 2;\n            public readonly int kSoloMuteBypassIndex = 3;\n            public readonly int kEffectStartIndex = 4;\n\n            public void Init(AudioMixerController controller, Rect channelStripRect, int maxNumEffects)\n            {\n                numChannels = controller.GetGroupVUInfo(group.groupID, false, vuinfo_level, vuinfo_peak);\n                //numChannels = 8; // debugging\n\n                maxEffects = maxNumEffects;\n                bgRects = GetBackgroundRects(channelStripRect, group, maxEffects);\n                stripRect = channelStripRect;\n\n\n                stripRect.yMax = bgRects[bgRects.Count - 1].yMax; // Ensure full height\n            }\n\n            List<Rect> GetBackgroundRects(Rect r, AudioMixerGroupController group, int maxNumGroups)\n            {\n                List<float> heights = new List<float>();\n                heights.AddRange(Enumerable.Repeat(0f, kEffectStartIndex));\n                heights[kHeaderIndex] = headerHeight;\n                heights[kVUMeterFaderIndex] = vuHeight;\n                heights[kTotalVULevelIndex] = dbHeight;\n                heights[kSoloMuteBypassIndex] = soloMuteBypassHeight;\n                int maxNumEffectSlots = maxNumGroups; // maxNumGroups includes an empty slot used as button for adding new effect\n                for (int i = 0; i < maxNumEffectSlots; ++i)\n                    heights.Add(effectHeight);\n                heights.Add(10f);\n\n                List<Rect> rects = new List<Rect>();\n                float curY = r.y;\n                foreach (int height in heights)\n                {\n                    if (rects.Count > 0)\n                        curY += spaceBetween;\n\n                    rects.Add(new Rect(r.x, curY, r.width, height));\n                    curY += height;\n                }\n\n                curY += 10f; // space between last effect and add button\n\n                rects.Add(new Rect(r.x, curY, r.width, kAddEffectButtonHeight));\n\n                return rects;\n            }\n        }\n\n        void DrawBackgrounds(ChannelStripParams p, bool selected)\n        {\n            if (Event.current.type == EventType.Repaint)\n            {\n                // Bg\n                styles.channelStripBg.Draw(p.stripRect, false, false, selected, false);\n\n                // Line over effects (todo: move to texture)\n                float lightColor = 119f / 255f;\n                float darkColor = 58f / 255f;\n                Color lineColor = EditorGUIUtility.isProSkin ? new Color(darkColor, darkColor, darkColor) : new Color(lightColor, lightColor, lightColor);\n                Rect lineRect = p.bgRects[p.kEffectStartIndex];\n                lineRect.y -= 1;\n                lineRect.height = 1;\n                EditorGUI.DrawRect(lineRect, lineColor);\n\n                // Optimize by rendering vu numbers and lines in one texture\n                //Rect vuNumbersRect = p.bgRects[1];\n                //vuNumbersRect.x = p.stripRect.xMax - 90f;\n                //vuNumbersRect.x = vuNumbersRect.xMax - AudioMixerDrawUtils.styles.channelStripVUMeterBg.normal.background.width; // right align\n                //AudioMixerDrawUtils.styles.channelStripVUMeterBg.Draw(vuNumbersRect, false, false, false, false); // 0 -80 dB numbers overlay\n            }\n\n            // User color\n            Rect colorRect = p.bgRects[p.kVUMeterFaderIndex];\n            colorRect.height = EditorGUIUtility.isProSkin ? 1 : 2;\n            colorRect.y -= colorRect.height;\n\n            int colorIndex = p.group.userColorIndex;\n            if (colorIndex != 0)\n                EditorGUI.DrawRect(colorRect, AudioMixerColorCodes.GetColor(colorIndex));\n        }\n\n        void OpenGroupContextMenu(AudioMixerGroupController[] groups)\n        {\n            GenericMenu pm = new GenericMenu();\n\n            AddEffectItemsToMenu(groups[0].controller, groups, 0, \"Add effect at top/\", pm);\n            AddEffectItemsToMenu(groups[0].controller, groups, -1, \"Add effect at bottom/\", pm);\n\n            pm.AddSeparator(string.Empty);\n            AudioMixerColorCodes.AddColorItemsToGenericMenu(pm, groups);\n            pm.AddSeparator(string.Empty);\n\n            pm.ShowAsContext();\n        }\n\n        private void DrawChannelStrip(ChannelStripParams p, ref int highlightEffectIndex, ref Dictionary<AudioMixerEffectController, PatchSlot> patchslots, bool showBusConnectionsOfSelection)\n        {\n            Event evt = Event.current;\n\n            bool mouseDownInsideStrip = evt.type == EventType.MouseDown && p.stripRect.Contains(evt.mousePosition);\n\n            // Selection rendering state\n            bool selected = m_Controller.CachedSelection.Contains(p.group);\n            if (IsRectSelectionActive())\n            {\n                if (RectOverlaps(p.stripRect, m_RectSelectionRect))\n                {\n                    p.rectSelectionGroups.Add(p.group);\n                    selected = true;\n                }\n            }\n\n            // Draw all background rects\n            DrawBackgrounds(p, selected);\n\n            // Header area\n            headerGUIContent.text = headerGUIContent.tooltip = p.group.GetDisplayString();\n            GUI.Label(p.bgRects[p.kHeaderIndex], headerGUIContent, AudioMixerDrawUtils.styles.channelStripHeaderStyle);\n\n            // VU Meter and attenuation area\n            Rect innerRect = new RectOffset(-6, 0, 0, -4).Add(p.bgRects[p.kVUMeterFaderIndex]);\n\n            float spaceBetweenColumns = 1f;\n            float column1Width = 54f;\n            float column2Width = innerRect.width - column1Width - spaceBetweenColumns;\n            Rect column1Rect = new Rect(innerRect.x, innerRect.y, column1Width, innerRect.height);\n            Rect column2Rect = new Rect(column1Rect.xMax + spaceBetweenColumns, innerRect.y, column2Width, innerRect.height);\n\n            float faderWidth = 29f;\n            Rect faderRect = new Rect(column2Rect.x, column2Rect.y, faderWidth, column2Rect.height);\n            Rect tripleButtonRect = p.bgRects[p.kSoloMuteBypassIndex];\n            GUIStyle attenuationMarkerStyle = AudioMixerDrawUtils.styles.channelStripAttenuationMarkerSquare;\n            using (new EditorGUI.DisabledScope(!AudioMixerController.EditingTargetSnapshot()))\n            {\n                DoVUMeters(column1Rect, attenuationMarkerStyle.fixedHeight, p);\n                DoAttenuationFader(faderRect, p.group, m_Controller.CachedSelection, attenuationMarkerStyle);\n                DoTotaldB(p);\n                DoEffectList(p, selected, ref highlightEffectIndex, ref patchslots, showBusConnectionsOfSelection);\n            }\n\n            // We want to be able to set mute, solo and bypass even when EditingTargetSnapshot is false for testing during gameplay\n            DoSoloMuteBypassButtons(tripleButtonRect, p.group, p.allGroups, m_Controller.CachedSelection, p.anySoloActive);\n\n            // Handle group click after all controls so we can detect if a control was clicked by checking if the event was used here\n            if (mouseDownInsideStrip && evt.button == 0)\n                GroupClicked(p.group, p, evt.type == EventType.Used);\n\n            // Check context click after all UI controls (only show if we did not interact with any controls)\n            if (evt.type == EventType.ContextClick && p.stripRect.Contains(evt.mousePosition))\n            {\n                evt.Use();\n\n                //If its part of an existing selection, then pass all, otherwise pretend its a new selection\n                if (selected)\n                    OpenGroupContextMenu(m_Controller.CachedSelection.ToArray());\n                else\n                    OpenGroupContextMenu(new AudioMixerGroupController[] { p.group });\n            }\n        }\n\n        void DoTotaldB(ChannelStripParams p)\n        {\n            // Right align db but shown centered (prevents 'db' from jumping around)\n            float textWidth = 50f;\n            styles.totalVULevel.padding.right = (int)((p.stripRect.width - textWidth) * 0.5f);\n            float vu_level = Mathf.Max(p.vuinfo_level[8], k_MinVULevel);\n            Rect rect = p.bgRects[p.kTotalVULevelIndex];\n            GUI.Label(rect, string.Format(CultureInfo.InvariantCulture.NumberFormat, \"{0:F1} dB\", vu_level), styles.totalVULevel);\n        }\n\n        GUIContent addText = EditorGUIUtility.TrTextContent(\"Add...\");\n        void DoEffectList(ChannelStripParams p, bool selected, ref int highlightEffectIndex, ref Dictionary<AudioMixerEffectController, PatchSlot> patchslots, bool showBusConnectionsOfSelection)\n        {\n            Event evt = Event.current;\n            for (int i = 0; i < p.maxEffects; i++)\n            {\n                Rect effectRect = p.bgRects[p.kEffectStartIndex + i];\n                if (i < p.group.effects.Length)\n                {\n                    AudioMixerEffectController effect = p.group.effects[i];\n                    if (p.visible)\n                    {\n                        // Use right click event first\n                        if (evt.type == EventType.ContextClick && effectRect.Contains(Event.current.mousePosition))\n                        {\n                            ClearFocus();\n                            DoEffectSlotInsertEffectPopup(effectRect, p.group, p.allGroups, i, ref p.effectMap);\n                            evt.Use();\n                        }\n\n                        // Then do effect button\n                        EffectSlot(effectRect, m_Controller.TargetSnapshot, effect, i, ref highlightEffectIndex, p, ref patchslots);\n                    }\n                }\n            }\n\n            // Empty slot below effects\n            if (p.visible)\n            {\n                Rect effectRect = p.bgRects[p.bgRects.Count - 1];\n                if (evt.type == EventType.Repaint)\n                {\n                    GUI.DrawTextureWithTexCoords(new Rect(effectRect.x, effectRect.y, effectRect.width, effectRect.height - 1), styles.effectBar.hover.background, new Rect(0, 0.5f, 0.1f, 0.1f));\n                    GUI.Label(effectRect, addText, styles.effectName);\n                }\n                if (evt.type == EventType.MouseDown && effectRect.Contains(Event.current.mousePosition))\n                {\n                    ClearFocus();\n                    int insertEffectAtIndex = p.group.effects.Length;\n                    DoEffectSlotInsertEffectPopup(effectRect, p.group, p.allGroups, insertEffectAtIndex, ref p.effectMap);\n                    evt.Use();\n                }\n            }\n        }\n\n        float DoVUMeters(Rect vuRect, float attenuationMarkerHeight, ChannelStripParams p)\n        {\n            float spaceBetweenMeters = 1f;\n\n            // When the audiomixer has been rebuild we might have some frames where numChannels is not initialized.\n            // To prevent flickering we use last valid num channels used at current index\n            int numChannels = p.numChannels;\n            if (numChannels == 0)\n            {\n                if (p.index >= 0 && p.index < m_LastNumChannels.Count)\n                    numChannels = m_LastNumChannels[p.index];\n            }\n            else\n            {\n                // Cache valid numChannels for current index\n                while (p.index >= m_LastNumChannels.Count)\n                    m_LastNumChannels.Add(0);\n                m_LastNumChannels[p.index] = numChannels;\n            }\n\n            // Adjust rect based on how many channels we have\n            if (numChannels <= 2)\n            {\n                const float twoChannelWidth = 25f;\n                vuRect.x = vuRect.xMax - twoChannelWidth; // right align\n                vuRect.width = twoChannelWidth;\n            }\n\n            // This can happen when simulating player builds, i.e. not calculating VU-info for most of the channels.\n            if (numChannels == 0)\n                return vuRect.x;\n\n            float vuOffsetY = Mathf.Floor(attenuationMarkerHeight / 2);\n            vuRect.y += vuOffsetY;\n            vuRect.height -= 2 * vuOffsetY;\n            float vuWidth = Mathf.Round((vuRect.width - numChannels * spaceBetweenMeters) / numChannels);\n            Rect vuSubRect = new Rect(vuRect.xMax - vuWidth, vuRect.y, vuWidth, vuRect.height);\n            // Draw from right to left to ensure perfect right side pixel position (we are rounding widths above)\n            for (int i = numChannels - 1; i >= 0; i--)\n            {\n                if (i != numChannels - 1)\n                    vuSubRect.x -= vuSubRect.width + spaceBetweenMeters;\n\n                float warpedLevel = 1f - AudioMixerController.VolumeToScreenMapping(Mathf.Clamp(p.vuinfo_level[i], AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume()), 1f, true);\n                float warpedPeak =  1f - AudioMixerController.VolumeToScreenMapping(Mathf.Clamp(p.vuinfo_peak[i], AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume()), 1f, true);\n                VUMeter(p.group, vuSubRect, warpedLevel, warpedPeak);\n            }\n            AudioMixerDrawUtils.AddTooltipOverlay(vuRect, styles.vuMeterGUIContent.tooltip);\n\n            return vuSubRect.x;\n        }\n\n        void DoSoloMuteBypassButtons(Rect rect, AudioMixerGroupController group, List<AudioMixerGroupController> allGroups, List<AudioMixerGroupController> selection, bool anySoloActive)\n        {\n            float buttonSize = 21f;\n            float spaceBetween = 2f;\n            float startX = rect.x + (rect.width - (buttonSize * 3 + spaceBetween * 2)) * 0.5f;\n            Rect buttonRect = new Rect(startX, rect.y, buttonSize, buttonSize);\n            bool needMixerUpdate = false;\n            needMixerUpdate |= DoSoloButton(buttonRect, group, allGroups, selection);\n            buttonRect.x += buttonSize + spaceBetween;\n            needMixerUpdate |= DoMuteButton(buttonRect, group, allGroups, anySoloActive, selection);\n            if (needMixerUpdate)\n                m_Controller.UpdateMuteSolo();\n            buttonRect.x += buttonSize + spaceBetween;\n            if (DoBypassEffectsButton(buttonRect, group, allGroups, selection))\n                m_Controller.UpdateBypass();\n        }\n\n        public void OnMixerControllerChanged(AudioMixerController controller)\n        {\n            m_Controller = controller;\n        }\n\n        [System.NonSerialized]\n        private int FrameCounter = 0;\n\n        [System.NonSerialized]\n        private GUIStyle developerInfoStyle = AudioMixerDrawUtils.BuildGUIStyleForLabel(new Color(1.0f, 0.0f, 0.0f, 0.5f), 20, false, FontStyle.Bold, TextAnchor.MiddleLeft);\n\n        public void ShowDeveloperOverlays(Rect rect, Event evt, bool show)\n        {\n            if (show && Unsupported.IsDeveloperMode() && evt.type == EventType.Repaint)\n            {\n                AudioMixerDrawUtils.ReadOnlyLabel(new Rect(rect.x + 5, rect.y + 5, rect.width - 10, 20), \"Current snapshot: \" + m_Controller.TargetSnapshot.name, developerInfoStyle);\n                AudioMixerDrawUtils.ReadOnlyLabel(new Rect(rect.x + 5, rect.y + 25, rect.width - 10, 20), \"Frame count: \" + FrameCounter++, developerInfoStyle);\n            }\n        }\n\n        public static float Lerp(float x1, float x2, float t)\n        {\n            return x1 + (x2 - x1) * t;\n        }\n\n        public static void GetCableVertex(float x1, float y1, float x2, float y2, float x3, float y3, float t, out float x, out float y)\n        {\n            x = Lerp(Lerp(x1, x2, t), Lerp(x2, x3, t), t);\n            y = Lerp(Lerp(y1, y2, t), Lerp(y2, y3, t), t);\n        }\n\n        [System.NonSerialized]\n        private Vector3[] cablepoints = new Vector3[20];\n\n        public void OnGUI(Rect rect, bool showReferencedBuses, bool showBusConnections, bool showBusConnectionsOfSelection, List<AudioMixerGroupController> allGroups, Dictionary<AudioMixerEffectController, AudioMixerGroupController> effectMap, bool sortGroupsAlphabetically, bool showDeveloperOverlays, AudioMixerGroupController scrollToItem)\n        {\n            if (m_Controller == null)\n            {\n                DrawAreaBackground(rect);\n                return;\n            }\n\n            if (Event.current.type == EventType.Layout)\n                return;\n\n            m_RectSelectionControlID = GUIUtility.GetControlID(kRectSelectionHashCode, FocusType.Passive);\n            m_EffectInteractionControlID = GUIUtility.GetControlID(kEffectDraggingHashCode, FocusType.Passive);\n\n            m_IndexCounter = 0;\n\n            Event evt = Event.current;\n            var sortedGroups = m_Controller.GetCurrentViewGroupList().ToList();\n            if (sortGroupsAlphabetically)\n                sortedGroups.Sort(m_GroupComparer);\n\n            Rect baseChannelStripRect = new Rect(channelStripsOffset.x, channelStripsOffset.y, channelStripBaseWidth, 300);\n            if (scrollToItem != null)\n            {\n                int index = sortedGroups.IndexOf(scrollToItem);\n                if (index >= 0)\n                {\n                    float x = (baseChannelStripRect.width + channelStripSpacing) * index - m_State.m_ScrollPos.x;\n                    if (x < -20 || x > rect.width)\n                        m_State.m_ScrollPos.x += x;\n                }\n            }\n\n            var unsortedBuses = new List<AudioMixerGroupController>();\n            foreach (var c in sortedGroups)\n            {\n                foreach (var e in c.effects)\n                {\n                    if (e.sendTarget != null)\n                    {\n                        var targetGroup = effectMap[e.sendTarget];\n                        if (!unsortedBuses.Contains(targetGroup) && !sortedGroups.Contains(targetGroup))\n                            unsortedBuses.Add(targetGroup);\n                    }\n                }\n            }\n            List<AudioMixerGroupController> buses = unsortedBuses.ToList();\n            buses.Sort(m_GroupComparer);\n\n            // Show referenced buses after all sorted groups\n            int numMainGroups = sortedGroups.Count;\n            if (showReferencedBuses && buses.Count > 0)\n                sortedGroups.AddRange(buses);\n\n            int maxEffects = 1;\n            foreach (var c in sortedGroups)\n                maxEffects = Mathf.Max(maxEffects, c.effects.Length);\n\n            bool isShowingReferencedGroups = sortedGroups.Count != numMainGroups;\n            Rect contentRect = GetContentRect(sortedGroups, isShowingReferencedGroups, maxEffects);\n            m_State.m_ScrollPos = GUI.BeginScrollView(rect, m_State.m_ScrollPos, contentRect);\n            DrawAreaBackground(new Rect(0, 0, 10000, 10000));\n\n            // Setup shared AudioGroup data\n            var channelStripParams = new ChannelStripParams\n            {\n                effectMap = effectMap,\n                allGroups = allGroups,\n                shownGroups = sortedGroups,\n                anySoloActive = allGroups.Any(g => g.solo),\n                visibleRect = new Rect(m_State.m_ScrollPos.x, m_State.m_ScrollPos.y, rect.width, rect.height)\n            };\n\n            var patchslots = showBusConnections ? new Dictionary<AudioMixerEffectController, PatchSlot>() : null;\n            for (int i = 0; i < sortedGroups.Count; ++i)\n            {\n                var group = sortedGroups[i];\n                // Specific parameter data for current AudioGroup\n                channelStripParams.index = i;\n                channelStripParams.group = group;\n                channelStripParams.drawingBuses = false;\n                channelStripParams.visible = RectOverlaps(channelStripParams.visibleRect, baseChannelStripRect);\n                channelStripParams.Init(m_Controller, baseChannelStripRect, maxEffects);\n\n                DrawChannelStrip(channelStripParams, ref m_Controller.m_HighlightEffectIndex, ref patchslots, showBusConnectionsOfSelection);\n\n                // If we click inside the the strip rect we use the event to ensure the mousedown is not caught by rectangle selection\n                if (evt.type == EventType.MouseDown && evt.button == 0 && channelStripParams.stripRect.Contains(evt.mousePosition))\n                    evt.Use();\n                // If we are dragging effects we reset destination index when dragging outside effects\n                if (IsMovingEffect() && evt.type == EventType.MouseDrag && channelStripParams.stripRect.Contains(evt.mousePosition) && GUIUtility.hotControl == m_EffectInteractionControlID)\n                {\n                    m_MovingEffectDstIndex = -1;\n                    evt.Use();\n                }\n                baseChannelStripRect.x += channelStripParams.stripRect.width + channelStripSpacing;\n\n                // Add extra space to referenced groups\n                if (showReferencedBuses && i == numMainGroups - 1 && sortedGroups.Count > numMainGroups)\n                {\n                    baseChannelStripRect.x += 50f;\n\n                    using (new EditorGUI.DisabledScope(true))\n                    {\n                        GUI.Label(new Rect(baseChannelStripRect.x, channelStripParams.stripRect.yMax, 130, 22), styles.referencedGroups, styles.channelStripHeaderStyle);\n                    }\n                }\n            }\n            UnhandledEffectDraggingEvents(ref m_Controller.m_HighlightEffectIndex);\n\n            if (evt.type == EventType.Repaint && patchslots != null)\n            {\n                foreach (var c in patchslots)\n                {\n                    var slot = c.Value;\n                    bool active = !showBusConnectionsOfSelection || m_Controller.CachedSelection.Contains(slot.group);\n                    if (active)\n                        styles.circularToggle.Draw(new Rect(slot.x - 3, slot.y - 3, 6, 6), false, false, active, false);\n                }\n                float moveamp = Mathf.Exp(-0.03f * Time.time * Time.time) * 0.1f;\n                var trCol1 = new Color(0.0f, 0.0f, 0.0f, AudioMixerController.EditingTargetSnapshot() ? 0.1f : 0.05f);\n                var trCol2 = new Color(0.0f, 0.0f, 0.0f, AudioMixerController.EditingTargetSnapshot() ? 1.0f : 0.5f);\n                foreach (var c in patchslots)\n                {\n                    var sourceEffect = c.Key;\n                    var targetEffect = sourceEffect.sendTarget;\n                    if (targetEffect == null)\n                        continue;\n                    var sourceSlot = c.Value;\n                    if (!patchslots.ContainsKey(targetEffect))\n                        continue;\n                    var targetSlot = patchslots[targetEffect];\n                    int color = sourceEffect.GetInstanceID() ^ targetEffect.GetInstanceID();\n                    float phase = (color & 63) * 0.1f;\n                    float mx1 = Mathf.Abs(targetSlot.x - sourceSlot.x) * Mathf.Sin(Time.time * 5.0f + phase) * moveamp + (sourceSlot.x + targetSlot.x) * 0.5f;\n                    float my1 = Mathf.Abs(targetSlot.y - sourceSlot.y) * Mathf.Cos(Time.time * 5.0f + phase) * moveamp + Math.Max(sourceSlot.y, targetSlot.y) + Mathf.Max(Mathf.Min(0.5f * Math.Abs(targetSlot.y - sourceSlot.y), 50.0f), 50.0f);\n                    for (int i = 0; i < cablepoints.Length; i++)\n                        GetCableVertex(\n                            sourceSlot.x, sourceSlot.y,\n                            mx1, my1,\n                            targetSlot.x, targetSlot.y,\n                            (float)i / (float)(cablepoints.Length - 1),\n                            out cablepoints[i].x, out cablepoints[i].y);\n                    bool skip = showBusConnectionsOfSelection && !m_Controller.CachedSelection.Contains(sourceSlot.group) && !m_Controller.CachedSelection.Contains(targetSlot.group);\n                    Handles.color = skip ? trCol1 : trCol2;\n                    Handles.DrawAAPolyLine(7.0f, cablepoints.Length, cablepoints);\n                    if (skip)\n                        continue;\n                    color ^= (color >> 6) ^ (color >> 12) ^ (color >> 18);\n                    Handles.color =\n                        new Color(\n                            (color       & 3) * 0.15f + 0.55f,\n                            ((color >> 2) & 3) * 0.15f + 0.55f,\n                            ((color >> 4) & 3) * 0.15f + 0.55f,\n                            AudioMixerController.EditingTargetSnapshot() ? 1.0f : 0.5f);\n                    Handles.DrawAAPolyLine(4.0f, cablepoints.Length, cablepoints);\n                    Handles.color = new Color(1.0f, 1.0f, 1.0f, AudioMixerController.EditingTargetSnapshot() ? 0.5f : 0.25f);\n                    Handles.DrawAAPolyLine(3.0f, cablepoints.Length, cablepoints);\n                }\n            }\n\n            RectSelection(channelStripParams);\n\n            GUI.EndScrollView(true);\n            AudioMixerDrawUtils.DrawScrollDropShadow(rect, m_State.m_ScrollPos.y, contentRect.height);\n            WarningOverlay(allGroups, rect, contentRect);\n            ShowDeveloperOverlays(rect, evt, showDeveloperOverlays);\n\n            if (!EditorApplication.isPlaying && !m_Controller.isSuspended)\n                m_RequiresRepaint = true;\n        }\n\n        bool IsMovingEffect()\n        {\n            return m_MovingEffectSrcIndex != -1;\n        }\n\n        bool IsAdjustingWetMix()\n        {\n            return m_ChangingWetMixIndex != -1;\n        }\n\n        void RectSelection(ChannelStripParams channelStripParams)\n        {\n            Event evt = Event.current;\n\n            if (evt.type == EventType.MouseDown && evt.button == 0 && GUIUtility.hotControl == 0)\n            {\n                if (!evt.shift)\n                {\n                    Selection.objects = new UnityEngine.Object[0];\n                    m_Controller.OnUnitySelectionChanged();\n                }\n                GUIUtility.hotControl = m_RectSelectionControlID;\n\n                m_RectSelectionStartPos = evt.mousePosition;\n                m_RectSelectionRect = new Rect(m_RectSelectionStartPos.x, m_RectSelectionStartPos.y, 0, 0);\n                Event.current.Use();\n                InspectorWindow.RepaintAllInspectors();\n            }\n\n            if (evt.type == EventType.MouseDrag)\n            {\n                if (IsRectSelectionActive())\n                {\n                    m_RectSelectionRect.x = Mathf.Min(m_RectSelectionStartPos.x, evt.mousePosition.x);\n                    m_RectSelectionRect.y = Mathf.Min(m_RectSelectionStartPos.y, evt.mousePosition.y);\n                    m_RectSelectionRect.width = Mathf.Max(m_RectSelectionStartPos.x, evt.mousePosition.x) - m_RectSelectionRect.x;\n                    m_RectSelectionRect.height = Mathf.Max(m_RectSelectionStartPos.y, evt.mousePosition.y) - m_RectSelectionRect.y;\n                    Event.current.Use();\n                }\n\n                if (m_MovingSrcRect.y >= 0.0f)\n                    Event.current.Use();\n            }\n\n            if (IsRectSelectionActive() && evt.GetTypeForControl(m_RectSelectionControlID) == EventType.MouseUp)\n            {\n                var newChannelStripSelection = (evt.shift) ? m_Controller.CachedSelection : new List<AudioMixerGroupController>();\n                foreach (var g in channelStripParams.rectSelectionGroups)\n                    if (!newChannelStripSelection.Contains(g))\n                        newChannelStripSelection.Add(g);\n                Selection.objects = newChannelStripSelection.ToArray();\n                m_Controller.OnUnitySelectionChanged();\n\n                GUIUtility.hotControl = 0;\n                Event.current.Use();\n                //InspectorWindow.RepaintAllInspectors();\n            }\n\n            if (evt.type == EventType.Repaint)\n            {\n                if (IsRectSelectionActive())\n                {\n                    Color rectSelCol = new Color(1, 1, 1, 0.3f);\n                    AudioMixerDrawUtils.DrawGradientRectHorizontal(m_RectSelectionRect, rectSelCol, rectSelCol);\n                }\n            }\n        }\n\n        void WarningOverlay(List<AudioMixerGroupController> allGroups, Rect rect, Rect contentRect)\n        {\n            int numSoloed = 0, numMuted = 0, numBypassEffects = 0;\n            foreach (var g in allGroups)\n            {\n                if (g.solo)\n                    numSoloed++;\n                if (g.mute)\n                    numMuted++;\n                if (g.bypassEffects)\n                    numBypassEffects += g.effects.Length - 1; // one of the effects is \"Attenuation\"\n                else\n                    numBypassEffects += g.effects.Count(e => e.bypass);\n            }\n\n            Event evt = Event.current;\n\n            // Warning overlay\n            if (evt.type == EventType.Repaint && numSoloed > 0 || numMuted > 0 || numBypassEffects > 0)\n            {\n                string warningStr = \"Warning: \" + (\n                    (numSoloed > 0) ? (numSoloed + (numSoloed > 1 ? \" groups\" : \" group\") + \" currently soloed\") :\n                    (numMuted > 0) ? (numMuted + (numMuted > 1 ? \" groups\" : \" group\") + \" currently muted\") :\n                    (numBypassEffects + (numBypassEffects > 1 ? \" effects\" : \" effect\") + \" currently bypassed\")\n                );\n\n                //bool verticalScrollbar = contentRect.height > rect.height;\n                bool horizontalScrollbar = contentRect.width > rect.width;\n                const float margin = 5f;\n                float textwidth = styles.warningOverlay.CalcSize(GUIContent.Temp(warningStr)).x;\n                Rect warningRect =\n                    new Rect(rect.x + margin + Mathf.Max((rect.width - 2 * margin - textwidth) * 0.5f, 0f),\n                        rect.yMax - styles.warningOverlay.fixedHeight - margin - (horizontalScrollbar ? 17f : 0f),\n                        textwidth,\n                        styles.warningOverlay.fixedHeight);\n\n                GUI.Label(warningRect, GUIContent.Temp(warningStr), styles.warningOverlay);\n            }\n        }\n\n        Rect GetContentRect(List<AudioMixerGroupController> sortedGroups, bool isShowingReferencedGroups, int maxEffects)\n        {\n            float fixedHeight = headerHeight + vuHeight + dbHeight + soloMuteBypassHeight;\n            float maxHeight = channelStripsOffset.y + fixedHeight + (maxEffects * effectHeight) + 10 + effectHeight + 10;\n\n            float maxWidth = channelStripsOffset.x * 2 + (channelStripBaseWidth + channelStripSpacing) * sortedGroups.Count + (isShowingReferencedGroups ? spaceBetweenMainGroupsAndReferenced : 0f);\n            return new Rect(0, 0, maxWidth, maxHeight);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/AudioMixerColorCodes.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.Audio;\n\nnamespace UnityEditor\n{\n    internal static class AudioMixerColorCodes\n    {\n        // Must match 'colorNames' array\n        static Color[] darkSkinColors = new[]\n        {\n            new Color(0.5f, 0.5f, 0.5f, 0.2f),\n            new Color(255 / 255f, 208 / 255f,   0 / 255f),\n            new Color(245 / 255f, 156 / 255f,   4 / 255f),\n            new Color(255 / 255f,  75 / 255f,  58 / 255f),\n            new Color(255 / 255f,  97 / 255f, 156 / 255f),\n            new Color(168 / 255f, 114 / 255f, 183 / 255f),\n            new Color(13 / 255f, 156 / 255f, 210 / 255f),\n            new Color(0 / 255f,  190 / 255f, 200 / 255f),\n            new Color(138 / 255f, 192 / 255f,   1 / 255f)\n        };\n\n        // Must match 'colorNames' array\n        static Color[] lightSkinColors = new[]\n        {\n            new Color(0.5f, 0.5f, 0.5f, 0.2f),\n            new Color(255 / 255f, 214 / 255f,  22 / 255f),\n            new Color(247 / 255f, 147 / 255f,   0 / 255f),\n            new Color(255 / 255f,  75 / 255f,  58 / 255f),\n            new Color(255 / 255f,  97 / 255f, 156 / 255f),\n            new Color(168 / 255f, 114 / 255f, 183 / 255f),\n            new Color(13 / 255f, 156 / 255f, 210 / 255f),\n            new Color(0 / 255f, 181 / 255f, 185 / 255f),\n            new Color(114 / 255f, 169 / 255f,  24 / 255f)\n        };\n\n        static string[] colorNames = new[] {    \"No Color\",\n                                                \"Yellow\",\n                                                \"Orange\",\n                                                \"Red\",\n                                                \"Magenta\",\n                                                \"Violet\",\n                                                \"Blue\",\n                                                \"Cyan\",\n                                                \"Green\" };\n\n        static string[] GetColorNames()\n        {\n            return colorNames;\n        }\n\n        static Color[] GetColors()\n        {\n            if (EditorGUIUtility.isProSkin)\n                return darkSkinColors;\n            else\n                return lightSkinColors;\n        }\n\n        public static void AddColorItemsToGenericMenu(GenericMenu menu, AudioMixerGroupController[] groups)\n        {\n            var colors = GetColors();\n            var names = GetColorNames();\n\n            for (int i = 0; i < colors.Length; i++)\n            {\n                bool selected = (groups.Length == 1) && (i == groups[0].userColorIndex);\n                menu.AddItem(new GUIContent(names[i]), selected, ItemCallback, new ItemData { groups = groups, index = i });\n            }\n        }\n\n        struct ItemData\n        {\n            public AudioMixerGroupController[] groups;\n            public int index;\n        }\n        static void ItemCallback(object data)\n        {\n            ItemData d = (ItemData)data;\n\n            Undo.RecordObjects(d.groups, \"Change Group(s) Color\");\n\n            foreach (AudioMixerGroupController group in d.groups)\n                group.userColorIndex = d.index;\n        }\n\n        public static Color GetColor(int index)\n        {\n            var colors = GetColors();\n            if (index >= 0 && index < colors.Length)\n                return colors[index];\n\n            Debug.LogError(\"Invalid color code index: \" + index);\n            return Color.white;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/AudioMixerDrawUtils.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.Audio;\n\nnamespace UnityEditor\n{\n    internal class AudioMixerDrawUtils\n    {\n        // OpenGL and D3D<11 use different ways of specifying the rasterization grid, so in order to draw exactly we need to account for this.\n        private static float vertexOffset = -1.0f;\n        private static void DetectVertexOffset()\n        {\n            //string driver = SystemInfo.graphicsDeviceVersion;\n            //vertexOffset = 0.5f; //(driver.StartsWith(\"OpenGL\") || driver.StartsWith(\"Direct3D 11\")) ? 0.0f : 0.5f;\n            //vertexOffset /= EditorGUIUtility.pixelsPerPoint;\n            vertexOffset = 0.0f;\n            //Debug.Log(\"Detected vertex offset as \" + vertexOffset + \" driver=\" + driver);\n        }\n\n        static readonly Color kAttenuationColor = AudioCurveRendering.kAudioOrange;\n        static readonly Color kEffectColor = new Color(103 / 255f, 160 / 255f, 0 / 255f);\n        static readonly Color kSendColor = new Color(0 / 255f, 147 / 255f, 170 / 255f);\n        static readonly Color kReceiveColor = kSendColor;\n        static readonly Color kDuckVolumeColor = kSendColor;\n\n        public static Color GetEffectColor(AudioMixerEffectController effect)\n        {\n            if (effect.IsSend())\n                return (effect.sendTarget != null) ? kSendColor : Color.gray;\n            if (effect.IsReceive())\n                return kReceiveColor;\n            if (effect.IsDuckVolume())\n                return kDuckVolumeColor;\n            if (effect.IsAttenuation())\n                return kAttenuationColor;\n\n            return kEffectColor;\n        }\n\n        public static Color kBackgroundHi          = new Color(0.5f, 0.5f, 0.5f);\n        public static Color kBackgroundLo          = new Color(0.3f, 0.3f, 0.3f);\n        public static Color kBackgroundHiHighlight = new Color(0.6f, 0.6f, 0.6f);\n        public static Color kBackgroundLoHighlight = new Color(0.4f, 0.4f, 0.4f);\n\n        public class Styles\n        {\n            public GUIStyle headerStyle = GetStyle(\"AM HeaderStyle\");\n            public GUIStyle reorderableListLabel = GetStyle(\"ReorderableList\");\n            public GUIStyle regionBg = GetStyle(\"RegionBg\");\n            public GUIStyle channelStripVUMeterBg = GetStyle(\"ChannelStripVUMeterBg\");\n            public GUIStyle channelStripAreaBackground = GetStyle(\"CurveEditorBackground\"); //\"flow background\";\n            public GUIStyle channelStripBg = GetStyle(\"ChannelStripBg\");\n            public GUIStyle duckingMarker = GetStyle(\"ChannelStripDuckingMarker\");\n            public GUIStyle channelStripAttenuationMarkerSquare = GetStyle(\"ChannelStripAttenuationMarkerSquare\");\n            public GUIStyle channelStripHeaderStyle = GetStyle(\"AM ChannelStripHeaderStyle\");\n            public GUIStyle soloToggle = GetStyle(\"SoloToggle\");\n            public GUIStyle muteToggle = GetStyle(\"MuteToggle\");\n            public GUIStyle bypassToggle = GetStyle(\"BypassToggle\");\n            public GUIStyle circularToggle = GetStyle(\"CircularToggle\");\n            public GUIStyle totalVULevel = GetStyle(\"AM TotalVuLabel\");\n            public GUIStyle attenuationBar =  GetStyle(\"ChannelStripAttenuationBar\");\n            public GUIStyle effectBar =  GetStyle(\"ChannelStripEffectBar\");\n            public GUIStyle sendReturnBar =  GetStyle(\"ChannelStripSendReturnBar\");\n            public GUIStyle effectName =  GetStyle(\"AM EffectName\");\n            public GUIStyle vuValue =  GetStyle(\"AM VuValue\");\n            public GUIStyle mixerHeader =  GetStyle(\"AM MixerHeader2\");\n            public GUIStyle warningOverlay = GetStyle(\"WarningOverlay\");\n            public Texture2D scrollShadowTexture = EditorGUIUtility.FindTexture(\"ScrollShadow\");\n            public Texture2D leftToRightShadowTexture = EditorGUIUtility.FindTexture(\"LeftToRightShadow\");\n            public GUIContent soloGUIContent = EditorGUIUtility.TrTextContent(\"\", \"Adds this group to set of soloed groups\");\n            public GUIContent muteGUIContent = EditorGUIUtility.TrTextContent(\"\", \"Mutes this group\");\n            public GUIContent bypassGUIContent = EditorGUIUtility.TrTextContent(\"\", \"Bypasses the effects on this group\");\n            public GUIContent effectSlotGUIContent = EditorGUIUtility.TrTextContent(\"\", \"Drag horizontally to change wet mix levels or vertically to change order of effects. Note: Enable wet mixing in the context menu.\");\n            public GUIContent attenuationSlotGUIContent = EditorGUIUtility.TrTextContent(\"\", \"Place the attenuation slot in the effect stack where attenuation should take effect\");\n            public GUIContent emptySendSlotGUIContent = EditorGUIUtility.TrTextContent(\"\", \"Connect to a Receive in the context menu or in the inspector\");\n            public GUIContent returnSlotGUIContent = EditorGUIUtility.TrTextContent(\"\", \"Connect a Send to this Receive\");\n            public GUIContent duckVolumeSlotGUIContent = EditorGUIUtility.TrTextContent(\"\", \"Connect a Send to this Duck Volume\");\n            public GUIContent duckingFaderGUIContent = EditorGUIUtility.TrTextContent(\"\", \"Ducking Fader\");\n            public GUIContent attenuationFader = EditorGUIUtility.TrTextContent(\"\", \"Attenuation fader\");\n            public GUIContent vuMeterGUIContent = EditorGUIUtility.TrTextContent(\"\", \"The VU meter shows the current level of the mix of all sounds and subgroups.\");\n            public GUIContent referencedGroups = EditorGUIUtility.TrTextContent(\"Referenced groups\", \"Mixer groups that are hidden but are referenced by the visible mixer groups are shown here for convenience\");\n            public GUIContent sendString = new GUIContent(\"s\");\n\n\n            static GUIStyle GetStyle(string styleName)\n            {\n                return styleName; // Implicit construction of GUIStyle\n            }\n\n            public Styles()\n            {\n                scrollShadowTexture = EditorGUIUtility.FindTexture(\"ScrollShadow\");\n            }\n        }\n        static Styles s_Styles;\n        public static Styles styles { get { return s_Styles; }}\n        public static void InitStyles()\n        {\n            if (s_Styles == null)\n            {\n                s_Styles = new Styles();\n                DetectVertexOffset();\n            }\n        }\n\n        public static float GetAlpha()\n        {\n            return GUI.enabled ? 1.0f : 0.7f;\n        }\n\n        public static void DrawSplitter()\n        {\n            Rect r = GUILayoutUtility.GetRect(1, 1);\n            if (Event.current.type == EventType.Repaint)\n            {\n                Color color = (EditorGUIUtility.isProSkin ? new Color(0.12f, 0.12f, 0.12f, 1.333f) : new Color(0.6f, 0.6f, 0.6f, 1.333f)); // dark : light\n                EditorGUI.DrawRect(r, color);\n            }\n        }\n\n        public static void Vertex(float x, float y)\n        {\n            GL.Vertex3(x + vertexOffset, y + vertexOffset, 0);\n        }\n\n        public static void DrawLine(float x1, float y1, float x2, float y2, Color c)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            HandleUtility.ApplyWireMaterial();\n            GL.Begin(GL.LINES);\n            GL.Color(new Color(c.r, c.g, c.b, c.a * GetAlpha()));\n            Vertex(x1, y1);\n            Vertex(x2, y2);\n            GL.End();\n        }\n\n        //todo: 339 draw calls in our test case. Reduce it to fewer calls into this function.\n        public static void DrawGradientRect(Rect r, Color c1, Color c2)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n            //Profiler.BeginSample (\"DrawGradientRect\");\n            HandleUtility.ApplyWireMaterial();\n            GL.Begin(GL.QUADS);\n            GL.Color(new Color(c1.r, c1.g, c1.b, c1.a * GetAlpha()));\n            Vertex(r.x, r.y);\n            Vertex(r.x + r.width, r.y);\n            GL.Color(new Color(c2.r, c2.g, c2.b, c2.a * GetAlpha()));\n            Vertex(r.x + r.width, r.y + r.height);\n            Vertex(r.x, r.y + r.height);\n            GL.End();\n            //Profiler.EndSample ();\n        }\n\n        public static void DrawGradientRectHorizontal(Rect r, Color c1, Color c2)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n            //Profiler.BeginSample (\"DrawGradientRectHorizontal\");\n            HandleUtility.ApplyWireMaterial();\n            GL.Begin(GL.QUADS);\n            GL.Color(new Color(c1.r, c1.g, c1.b, c1.a * GetAlpha()));\n            Vertex(r.x + r.width, r.y);\n            Vertex(r.x + r.width, r.y + r.height);\n            GL.Color(new Color(c2.r, c2.g, c2.b, c2.a * GetAlpha()));\n            Vertex(r.x, r.y + r.height);\n            Vertex(r.x, r.y);\n            GL.End();\n            //Profiler.EndSample ();\n        }\n\n        internal const float kSectionHeaderHeight = 22f;\n        internal const float kSpaceBetweenSections = 10f;\n\n        public static void DrawRegionBg(Rect rect, out Rect headerRect, out Rect contentRect)\n        {\n            const float headerIndent = 2f;\n            headerRect = new Rect(rect.x + headerIndent, rect.y, rect.width - headerIndent, kSectionHeaderHeight);\n            contentRect = new Rect(rect.x, headerRect.yMax, rect.width, rect.height - kSectionHeaderHeight);\n            GUI.Label(new RectOffset(1, 1, 1, 1).Add(contentRect), GUIContent.none, EditorStyles.frameBox);\n        }\n\n        public static void HeaderLabel(Rect r, GUIContent text, Texture2D icon)\n        {\n            if (icon != null)\n            {\n                EditorGUIUtility.SetIconSize(new Vector2(16, 16));\n                GUI.Label(r, icon, styles.headerStyle);\n                EditorGUIUtility.SetIconSize(Vector2.zero);\n                r.xMin += 20f;\n            }\n            GUI.Label(r, text, styles.headerStyle);\n        }\n\n        public static GUIStyle BuildGUIStyleForLabel(Color color, int fontSize, bool wrapText, FontStyle fontstyle, TextAnchor anchor)\n        {\n            GUIStyle style = new GUIStyle();\n            style.focused.background = style.onNormal.background;\n            style.focused.textColor = color;\n            style.alignment = anchor;\n            style.fontSize = fontSize;\n            style.fontStyle = fontstyle;\n            style.wordWrap = wrapText;\n            style.clipping = TextClipping.Clip;\n            style.normal.textColor = color;\n            style.padding = new RectOffset(4, 4, 4, 4);\n            return style;\n        }\n\n        public static void ReadOnlyLabel(Rect r, GUIContent content, GUIStyle style)\n        {\n            GUI.Label(r, content, style);\n        }\n\n        public static void ReadOnlyLabel(Rect r, string text, GUIStyle style)\n        {\n            GUI.Label(r, GUIContent.Temp(text), style);\n        }\n\n        public static void ReadOnlyLabel(Rect r, string text, GUIStyle style, string tooltipText)\n        {\n            GUI.Label(r, GUIContent.Temp(text, tooltipText), style);\n        }\n\n        public static void AddTooltipOverlay(Rect r, string tooltip)\n        {\n            GUI.Label(r, GUIContent.Temp(string.Empty, tooltip), s_Styles.headerStyle);\n        }\n\n        public static void DrawConnection(Color col, float mixLevel, float srcX, float srcY, float dstX, float dstY, float width)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            //Profiler.BeginSample (\"DrawConnection\");\n            HandleUtility.ApplyWireMaterial();\n\n            var dirX = dstX - srcX;\n            var dirY = dstY - srcY;\n            var scale = width / Mathf.Sqrt(dirX * dirX + dirY * dirY);\n            dirX *= scale;\n            dirY *= scale;\n\n            float a = 2.0f, b = 1.2f;\n            var arrowPoints = new Vector3[4];\n            arrowPoints[0] = new Vector3(dstX, dstY);\n            arrowPoints[1] = new Vector3(dstX - a * dirX + b * dirY, dstY - a * dirY - b * dirX);\n            arrowPoints[2] = new Vector3(dstX - a * dirX - b * dirY, dstY - a * dirY + b * dirX);\n            arrowPoints[3] = arrowPoints[0];\n\n            Color triColor = new Color(col.r, col.g, col.b, mixLevel * 0.3f + 0.3f);\n            Shader.SetGlobalColor(\"_HandleColor\", triColor);\n            GL.Begin(GL.TRIANGLES);\n            GL.Color(triColor);\n            GL.Vertex(arrowPoints[0]);\n            GL.Vertex(arrowPoints[1]);\n            GL.Vertex(arrowPoints[2]);\n            GL.End();\n\n            Handles.DrawAAPolyLine(width, new[] { triColor, triColor, triColor, triColor }, arrowPoints);\n\n            Handles.DrawAAPolyLine(\n                width,\n                new[] { new Color(col.r, col.g, col.b, mixLevel), new Color(col.r, col.g, col.b, mixLevel) },\n                new[] { new Vector3(srcX, srcY, 0.0f), new Vector3(dstX, dstY, 0.0f) }\n            );\n            //Profiler.EndSample ();\n        }\n\n        public static void DrawVerticalShow(Rect rect, bool fadeToTheRight)\n        {\n            Rect textureCoordRect = fadeToTheRight ? new Rect(0, 0, 1, 1) : new Rect(1, 1, -1, -1);   // flip over X\n            GUI.DrawTextureWithTexCoords(rect, styles.leftToRightShadowTexture, textureCoordRect);\n        }\n\n        public static void DrawScrollDropShadow(Rect scrollViewRect, float scrollY, float contentHeight)\n        {\n            if (Event.current.type == EventType.Repaint)\n            {\n                bool isShowingScrollBar = contentHeight > scrollViewRect.height;\n                if (!isShowingScrollBar)\n                    return;\n\n                const float shadowHeightTop = 20f;\n                const float shadowHeightBottom = 10f;\n                const float fadeDist = 10f;\n\n                Color orgColor = GUI.color;\n\n                // Top shadow is faded in over the first 'fadeDist'\n                float alpha = scrollY > fadeDist ? 1f : (scrollY / fadeDist);\n                if (alpha < 1f)\n                    GUI.color = new Color(1, 1, 1, alpha);\n                if (alpha > 0f)\n                    GUI.DrawTexture(new Rect(scrollViewRect.x, scrollViewRect.y, scrollViewRect.width, shadowHeightTop), styles.scrollShadowTexture);\n                if (alpha < 1f)\n                    GUI.color = orgColor;\n\n                // Bottom shadow is shown if the scroll bar is visible\n                float scrollAvailable = Mathf.Max(contentHeight - scrollViewRect.height, 0f);\n                float alphaBottom = (scrollAvailable - scrollY) > fadeDist ? 1f : (scrollAvailable - scrollY) / fadeDist;\n                if (alphaBottom < 1f)\n                    GUI.color = new Color(1, 1, 1, alphaBottom);\n                if (alphaBottom > 0f)\n                    GUI.DrawTextureWithTexCoords(new Rect(scrollViewRect.x, scrollViewRect.yMax - shadowHeightBottom, scrollViewRect.width, shadowHeightBottom), styles.scrollShadowTexture, new Rect(1, 1, -1, -1)); // flip over Y\n                if (alphaBottom < 1f)\n                    GUI.color = orgColor;\n            }\n        }\n\n        public static void DrawRect(Rect rect, Color color)\n        {\n            Color orgColor = GUI.color;\n            GUI.color = color;\n            GUI.Label(rect, GUIContent.Temp(string.Empty), EditorGUIUtility.whiteTextureStyle);   // Using style rendering so that disabled state is reflected in rendering\n            GUI.color = orgColor;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/AudioMixerEffectGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.Audio;\n\nnamespace UnityEditor\n{\n    internal static class AudioMixerEffectGUI\n    {\n        const string kAudioSliderFloatFormat = \"F2\";\n        const string kExposedParameterUnicodeChar = \" \\u2794\";\n\n        public static void EffectHeader(string text)\n        {\n            GUILayout.Label(text, styles.headerStyle);\n        }\n\n        public static bool Slider(GUIContent label, ref float value, float displayScale, float displayExponent, string unit, float leftValue, float rightValue, AudioMixerController controller, AudioParameterPath path, params GUILayoutOption[] options)\n        {\n            EditorGUI.BeginChangeCheck();\n\n            float oldNumberWidth = EditorGUIUtility.fieldWidth;\n            string origFormat = EditorGUI.kFloatFieldFormatString;\n\n            bool exposed = controller.ContainsExposedParameter(path.parameter);\n            float displayValue = value * displayScale;\n\n            EditorGUIUtility.fieldWidth = 70f;     // do not go over 70 because then sliders will not be shown when inspector has minimal width\n            EditorGUI.kFloatFieldFormatString = kAudioSliderFloatFormat;\n            EditorGUI.s_UnitString = unit;\n\n            try\n            {\n                GUIContent content = label;\n                if (exposed)\n                    content = GUIContent.Temp(label.text + kExposedParameterUnicodeChar, label.tooltip);\n\n                displayValue = EditorGUILayout.PowerSlider(content, displayValue, leftValue * displayScale, rightValue * displayScale, displayExponent, options);\n            }\n            finally\n            {\n                EditorGUI.s_UnitString = null;\n                EditorGUI.kFloatFieldFormatString = origFormat;\n                EditorGUIUtility.fieldWidth = oldNumberWidth;\n            }\n\n            if (Event.current.type == EventType.ContextClick)\n            {\n                Rect wholeSlider = GUILayoutUtility.topLevel.GetLast();\n                if (wholeSlider.Contains(Event.current.mousePosition))\n                {\n                    Event.current.Use();\n\n                    GenericMenu pm = new GenericMenu();\n                    if (!exposed)\n                        pm.AddItem(EditorGUIUtility.TrTextContent(\"Expose '\" + path.ResolveStringPath(false) + \"' to script\"), false, ExposePopupCallback, new ExposedParamContext(controller, path));\n                    else\n                        pm.AddItem(EditorGUIUtility.TrTextContent(\"Unexpose\"), false, UnexposePopupCallback, new ExposedParamContext(controller, path));\n\n                    ParameterTransitionType existingType;\n                    bool overrideExists = controller.TargetSnapshot.GetTransitionTypeOverride(path.parameter, out existingType);\n                    System.Diagnostics.Debug.Assert(!overrideExists || existingType == ParameterTransitionType.Lerp);\n\n                    pm.AddSeparator(string.Empty);\n                    pm.AddItem(EditorGUIUtility.TrTextContent(\"Linear Snapshot Transition\"), existingType == ParameterTransitionType.Lerp, ParameterTransitionOverrideCallback, new ParameterTransitionOverrideContext(controller, path.parameter, ParameterTransitionType.Lerp));\n                    pm.AddItem(EditorGUIUtility.TrTextContent(\"Smoothstep Snapshot Transition\"), existingType == ParameterTransitionType.Smoothstep, ParameterTransitionOverrideCallback, new ParameterTransitionOverrideContext(controller, path.parameter, ParameterTransitionType.Smoothstep));\n                    pm.AddItem(EditorGUIUtility.TrTextContent(\"Squared Snapshot Transition\"), existingType == ParameterTransitionType.Squared, ParameterTransitionOverrideCallback, new ParameterTransitionOverrideContext(controller, path.parameter, ParameterTransitionType.Squared));\n                    pm.AddItem(EditorGUIUtility.TrTextContent(\"SquareRoot Snapshot Transition\"), existingType == ParameterTransitionType.SquareRoot, ParameterTransitionOverrideCallback, new ParameterTransitionOverrideContext(controller, path.parameter, ParameterTransitionType.SquareRoot));\n                    pm.AddItem(EditorGUIUtility.TrTextContent(\"BrickwallStart Snapshot Transition\"), existingType == ParameterTransitionType.BrickwallStart, ParameterTransitionOverrideCallback, new ParameterTransitionOverrideContext(controller, path.parameter, ParameterTransitionType.BrickwallStart));\n                    pm.AddItem(EditorGUIUtility.TrTextContent(\"BrickwallEnd Snapshot Transition\"), existingType == ParameterTransitionType.BrickwallEnd, ParameterTransitionOverrideCallback, new ParameterTransitionOverrideContext(controller, path.parameter, ParameterTransitionType.BrickwallEnd));\n                    pm.AddItem(EditorGUIUtility.TrTextContent(\"Attenuation Snapshot Transition\"), existingType == ParameterTransitionType.Attenuation, ParameterTransitionOverrideCallback, new ParameterTransitionOverrideContext(controller, path.parameter, ParameterTransitionType.Attenuation));\n                    pm.AddSeparator(string.Empty);\n\n                    pm.ShowAsContext();\n                }\n            }\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                value = displayValue / displayScale;\n                return true;\n            }\n            return false;\n        }\n\n        private class ExposedParamContext\n        {\n            public ExposedParamContext(AudioMixerController controller, AudioParameterPath path)\n            {\n                this.controller = controller;\n                this.path = path;\n            }\n\n            public AudioMixerController controller;\n            public AudioParameterPath path;\n        }\n\n\n        public static void ExposePopupCallback(object obj)\n        {\n            ExposedParamContext context = (ExposedParamContext)obj;\n            Undo.RecordObject(context.controller, \"Expose Mixer Parameter\");\n            context.controller.AddExposedParameter(context.path);\n\n            AudioMixerUtility.RepaintAudioMixerAndInspectors();\n        }\n\n        public static void UnexposePopupCallback(object obj)\n        {\n            ExposedParamContext context = (ExposedParamContext)obj;\n            Undo.RecordObject(context.controller, \"Unexpose Mixer Parameter\");\n            context.controller.RemoveExposedParameter(context.path.parameter);\n\n            AudioMixerUtility.RepaintAudioMixerAndInspectors();\n        }\n\n        private class ParameterTransitionOverrideContext\n        {\n            public ParameterTransitionOverrideContext(AudioMixerController controller, GUID parameter, ParameterTransitionType type)\n            {\n                this.controller = controller;\n                this.parameter = parameter;\n                this.type = type;\n            }\n\n            public AudioMixerController     controller;\n            public GUID                     parameter;\n            public ParameterTransitionType  type;\n        }\n\n        private class ParameterTransitionOverrideRemoveContext\n        {\n            public ParameterTransitionOverrideRemoveContext(AudioMixerController controller, GUID parameter)\n            {\n                this.controller = controller;\n                this.parameter = parameter;\n            }\n\n            public AudioMixerController     controller;\n            public GUID                     parameter;\n        }\n\n        public static void ParameterTransitionOverrideCallback(object obj)\n        {\n            ParameterTransitionOverrideContext context = (ParameterTransitionOverrideContext)obj;\n            Undo.RecordObject(context.controller, \"Change Parameter Transition Type\");\n            if (context.type == ParameterTransitionType.Lerp)\n                context.controller.TargetSnapshot.ClearTransitionTypeOverride(context.parameter);\n            else\n                context.controller.TargetSnapshot.SetTransitionTypeOverride(context.parameter, context.type);\n        }\n\n        public static bool PopupButton(GUIContent label, GUIContent buttonContent, GUIStyle style, out Rect buttonRect, params GUILayoutOption[] options)\n        {\n            if (label != null)\n            {\n                Rect r = EditorGUILayout.s_LastRect = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n                int id = EditorGUIUtility.GetControlID(\"EditorPopup\".GetHashCode(), FocusType.Keyboard, r);\n                buttonRect = EditorGUI.PrefixLabel(r, id, label);\n            }\n            else\n            {\n                Rect r = GUILayoutUtility.GetRect(buttonContent, style, options);\n                buttonRect = r;\n            }\n\n            return EditorGUI.DropdownButton(buttonRect, buttonContent, FocusType.Passive, style);\n        }\n\n        private static AudioMixerDrawUtils.Styles styles { get { return AudioMixerDrawUtils.styles; } }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/AudioMixerEffectView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System;\nusing UnityEditor.Audio;\n\nnamespace UnityEditor\n{\n    class AudioMixerEffectView\n    {\n        private const float kMinPitch        =  0.01f;\n        private const float kMaxPitch        = 10.0f;\n\n        private const int kLabelWidth = 170;\n        private const int kTextboxWidth = 70;\n\n        private AudioMixerGroupController m_PrevGroup = null;\n        private readonly EffectDragging m_EffectDragging;\n        private int m_LastNumChannels = 0;\n\n        private AudioMixerEffectPlugin m_SharedPlugin = new AudioMixerEffectPlugin();\n        private Dictionary<string, IAudioEffectPluginGUI> m_CustomEffectGUIs = new Dictionary<string, IAudioEffectPluginGUI>();\n\n        static class Texts\n        {\n            public static GUIContent editInPlaymode = EditorGUIUtility.TrTextContent(\"Edit in Playmode\");\n            public static GUIContent pitch = EditorGUIUtility.TrTextContent(\"Pitch\");\n            public static GUIContent addEffect = EditorGUIUtility.TrTextContent(\"Add Effect\");\n            public static GUIContent volume = EditorGUIUtility.TrTextContent(\"Volume\");\n            public static GUIContent sendLevel = EditorGUIUtility.TrTextContent(\"Send level\");\n            public static GUIContent bus = EditorGUIUtility.TrTextContent(\"Receive\");\n            public static GUIContent none = EditorGUIUtility.TrTextContent(\"None\");\n            public static GUIContent wet = EditorGUIUtility.TrTextContent(\"Wet\", \"Enables/disables wet/dry ratio on this effect. Note that this makes the DSP graph more complex and requires additional CPU and memory, so use it only when necessary.\");\n            public static string dB = \"dB\";\n            public static string percentage = \"%\";\n            public static string cpuFormatString = \" - CPU: {0:#0.00}%\";\n        }\n\n        public AudioMixerEffectView()\n        {\n            m_EffectDragging = new EffectDragging();\n\n            Type pluginType = typeof(IAudioEffectPluginGUI);\n            foreach (var assembly in System.AppDomain.CurrentDomain.GetAssemblies())\n            {\n                //Debug.Log(\"Assembly: \" + assembly.FullName);\n                try\n                {\n                    var types = assembly.GetTypes();\n                    //Debug.Log(\"Contained types: \" + types.ToString());\n                    foreach (Type t in types.Where(t => !t.IsAbstract && pluginType.IsAssignableFrom(t)))\n                    {\n                        //Debug.Log(\"Instantiating type: \" + t.FullName);\n                        RegisterCustomGUI(Activator.CreateInstance(t) as IAudioEffectPluginGUI);\n                    }\n                }\n                catch (System.Exception)\n                {\n                    //Debug.Log(\"Failed getting types in assembly: \" + assembly.FullName);\n                }\n            }\n        }\n\n        public bool RegisterCustomGUI(IAudioEffectPluginGUI gui)\n        {\n            string name = gui.Name;\n            if (m_CustomEffectGUIs.ContainsKey(name))\n            {\n                var oldGUI = m_CustomEffectGUIs[name];\n                Debug.LogError(\"Attempt to register custom GUI for plugin \" + name + \" failed as another plugin is already registered under this name.\");\n                Debug.LogError(\"Plugin trying to register itself: \" + gui.Description + \" (Vendor: \" + gui.Vendor + \")\");\n                Debug.LogError(\"Plugin already registered: \" + oldGUI.Description + \" (Vendor: \" + oldGUI.Vendor + \")\");\n                return false;\n            }\n\n            m_CustomEffectGUIs[name] = gui;\n            return true;\n        }\n\n        public void OnGUI(AudioMixerGroupController group)\n        {\n            if (group == null)\n                return;\n\n            Rect totalRect = EditorGUILayout.BeginVertical();\n\n            if (EditorApplication.isPlaying)\n            {\n                GUILayout.BeginHorizontal();\n                GUILayout.FlexibleSpace();\n                EditorGUI.BeginChangeCheck();\n                GUILayout.Toggle(AudioSettings.editingInPlaymode, Texts.editInPlaymode, EditorStyles.miniButton, GUILayout.Width(120));\n                if (EditorGUI.EndChangeCheck())\n                    AudioSettings.editingInPlaymode = !AudioSettings.editingInPlaymode;\n                GUILayout.FlexibleSpace();\n                GUILayout.EndHorizontal();\n            }\n\n            using (new EditorGUI.DisabledScope(!AudioMixerController.EditingTargetSnapshot()))\n            {\n                var controller = group.controller;\n\n                if (group != m_PrevGroup)\n                {\n                    m_PrevGroup = group;\n                    controller.m_HighlightEffectIndex = -1;\n                    AudioMixerUtility.RepaintAudioMixerAndInspectors();\n                }\n\n                // Do Effect modules\n                var allGroups = controller.GetAllAudioGroupsSlow();\n                var effectMap = AudioMixerGroupController.GetEffectMapSlow(allGroups);\n\n                DoInitialModule(group, controller, allGroups);\n                for (int effectIndex = 0; effectIndex < group.effects.Length; effectIndex++)\n                {\n                    DoEffectGUI(effectIndex, group, allGroups, effectMap, ref controller.m_HighlightEffectIndex);\n                }\n\n                m_EffectDragging.HandleDragging(totalRect, group, controller);\n\n                GUILayout.Space(10f);\n\n                EditorGUILayout.BeginHorizontal();\n\n                GUILayout.FlexibleSpace();\n                if (EditorGUILayout.DropdownButton(Texts.addEffect, FocusType.Passive, GUISkin.current.button))\n                {\n                    GenericMenu pm = new GenericMenu();\n                    Rect buttonRect = GUILayoutUtility.topLevel.GetLast();\n                    AudioMixerGroupController[] groupArray = new AudioMixerGroupController[] { group };\n                    AudioMixerChannelStripView.AddEffectItemsToMenu(controller, groupArray, group.effects.Length, string.Empty, pm);\n                    pm.DropDown(buttonRect);\n                }\n\n                EditorGUILayout.EndHorizontal();\n            }\n\n            EditorGUILayout.EndVertical();\n        }\n\n        public static float DoInitialModule(AudioMixerGroupController group, AudioMixerController controller, List<AudioMixerGroupController> allGroups)\n        {\n            Rect totalRect = EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);\n\n            // Pitch\n            float value = group.GetValueForPitch(controller, controller.TargetSnapshot);\n            if (AudioMixerEffectGUI.Slider(Texts.pitch, ref value, 100.0f, 1.0f, Texts.percentage, kMinPitch, kMaxPitch, controller, new AudioGroupParameterPath(group, group.GetGUIDForPitch())))\n            {\n                Undo.RecordObject(controller.TargetSnapshot, \"Change Pitch\");\n                group.SetValueForPitch(controller, controller.TargetSnapshot, value);\n            }\n\n            GUILayout.Space(5f);\n            EditorGUILayout.EndVertical();\n\n            AudioMixerDrawUtils.DrawSplitter();\n\n            return totalRect.height;\n        }\n\n        public void DoEffectGUI(int effectIndex, AudioMixerGroupController group, List<AudioMixerGroupController> allGroups, Dictionary<AudioMixerEffectController, AudioMixerGroupController> effectMap, ref int highlightEffectIndex)\n        {\n            Event evt = Event.current;\n\n            AudioMixerController controller = group.controller;\n            AudioMixerEffectController effect = group.effects[effectIndex];\n            MixerParameterDefinition[] paramDefs = MixerEffectDefinitions.GetEffectParameters(effect.effectName);\n\n            // This rect is valid after every layout event\n            Rect totalRect = EditorGUILayout.BeginVertical();\n\n            bool hovering = totalRect.Contains(evt.mousePosition);\n            EventType evtType = evt.GetTypeForControl(m_EffectDragging.dragControlID);\n\n            if (evtType == EventType.MouseMove && hovering && highlightEffectIndex != effectIndex)\n            {\n                highlightEffectIndex = effectIndex;\n                AudioMixerUtility.RepaintAudioMixerAndInspectors();\n            }\n\n            // Header\n            const float colorCodeWidth = 6f;\n            var gearSize = EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.titleSettingsIcon);\n            Rect headerRect = GUILayoutUtility.GetRect(1, 17f);\n            Rect colorCodeRect = new Rect(headerRect.x + 6f, headerRect.y + 5f, colorCodeWidth, colorCodeWidth);\n            Rect labelRect = new Rect(headerRect.x + 8f + colorCodeWidth, headerRect.y, headerRect.width - 8f - colorCodeWidth - gearSize.x - 5f, headerRect.height);\n            Rect gearRect = new Rect(labelRect.xMax, headerRect.y, gearSize.x, gearSize.y);\n            Rect dragRect = new Rect(headerRect.x, headerRect.y, headerRect.width - gearSize.x - 5f, headerRect.height);\n            {\n                bool showCPU = EditorPrefs.GetBool(AudioMixerGroupEditor.kPrefKeyForShowCpuUsage, false) && EditorUtility.audioProfilingEnabled;\n\n                float val = EditorGUIUtility.isProSkin ? 0.1f : 1.0f;\n                Color headerColor =  new Color(val, val, val, 0.2f);\n                Color origColor = GUI.color;\n                GUI.color = headerColor;\n                GUI.DrawTexture(headerRect, EditorGUIUtility.whiteTexture);\n                GUI.color = origColor;\n\n                Color effectColorCode = AudioMixerDrawUtils.GetEffectColor(effect);\n                EditorGUI.DrawRect(colorCodeRect, effectColorCode);\n                GUI.Label(labelRect, showCPU ? effect.effectName + string.Format(Texts.cpuFormatString, effect.GetCPUUsage(controller)) : effect.effectName, EditorStyles.boldLabel);\n                if (EditorGUI.DropdownButton(gearRect, EditorGUI.GUIContents.titleSettingsIcon, FocusType.Passive, EditorStyles.iconButton))\n                {\n                    ShowEffectContextMenu(group, effect, effectIndex, controller, gearRect);\n                }\n\n                // Show context menu if right clicking in header rect (for convenience)\n                if (evt.type == EventType.ContextClick && headerRect.Contains(evt.mousePosition))\n                {\n                    ShowEffectContextMenu(group, effect, effectIndex, controller, new Rect(evt.mousePosition.x, headerRect.y, 1, headerRect.height));\n                    evt.Use();\n                }\n\n                if (evtType == EventType.Repaint)\n                    EditorGUIUtility.AddCursorRect(dragRect, MouseCursor.ResizeVertical, m_EffectDragging.dragControlID);\n            }\n\n            using (new EditorGUI.DisabledScope(effect.bypass || group.bypassEffects))\n            {\n                EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);\n\n                if (effect.IsAttenuation())\n                {\n                    EditorGUILayout.BeginVertical();\n                    float value = group.GetValueForVolume(controller, controller.TargetSnapshot);\n                    if (AudioMixerEffectGUI.Slider(Texts.volume, ref value, 1.0f, 1.0f, Texts.dB, AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume(), controller, new AudioGroupParameterPath(group, group.GetGUIDForVolume())))\n                    {\n                        Undo.RecordObject(controller.TargetSnapshot, \"Change Volume Fader\");\n                        group.SetValueForVolume(controller, controller.TargetSnapshot, value);\n                        AudioMixerUtility.RepaintAudioMixerAndInspectors();\n                    }\n\n                    //FIXME\n                    // 1) The VUMeter used is not in the same style that fits the rest of the Audio UI\n                    // 2) The layout of the VU meters is hacked together and a lot of magic numbers are used.\n                    int numChannels = 0;\n                    float[] vuinfo_level = new float[9];\n                    float[] vuinfo_peak = new float[9];\n\n                    numChannels = group.controller.GetGroupVUInfo(group.groupID, true, vuinfo_level, vuinfo_peak);\n\n                    if (evt.type == EventType.Layout)\n                    {\n                        m_LastNumChannels = numChannels;\n                    }\n                    else\n                    {\n                        if (numChannels != m_LastNumChannels)\n                            HandleUtility.Repaint();      // Repaint to ensure correct rendered num channels\n\n                        // Ensure same num channels as in layout event to not break IMGUI controlID handling\n                        numChannels = m_LastNumChannels;\n                    }\n\n                    GUILayout.Space(4f);\n                    for (int c = 0; c < numChannels; ++c)\n                    {\n                        float level = 1 - AudioMixerController.VolumeToScreenMapping(Mathf.Clamp(vuinfo_level[c], AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume()), 1, true);\n                        float peak = 1 - AudioMixerController.VolumeToScreenMapping(Mathf.Clamp(vuinfo_peak[c], AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume()), 1, true);\n                        EditorGUILayout.VUMeterHorizontal(level, peak, GUILayout.Height(10));\n\n                        //This allows the meters to drop to 0 after PlayMode has stopped.\n                        if (!EditorApplication.isPlaying && peak > 0.0F)\n                            AudioMixerUtility.RepaintAudioMixerAndInspectors();\n                    }\n                    GUILayout.Space(4f);\n                    EditorGUILayout.EndVertical();\n                }\n\n                if (effect.IsSend())\n                {\n                    Rect buttonRect;\n                    GUIContent buttonContent = (effect.sendTarget == null) ? Texts.none : GUIContent.Temp(effect.GetSendTargetDisplayString(effectMap));\n                    if (AudioMixerEffectGUI.PopupButton(Texts.bus, buttonContent, EditorStyles.popup, out buttonRect))\n                        ShowBusPopupMenu(effectIndex, @group, allGroups, effectMap, effect, buttonRect);\n\n                    if (effect.sendTarget != null)\n                    {\n                        var wetLevel = effect.GetValueForMixLevel(controller, controller.TargetSnapshot);\n                        var sendGuid = effect.GetGUIDForMixLevel();\n\n                        if (AudioMixerEffectGUI.Slider(Texts.sendLevel, ref wetLevel, 1.0f, 1.0f, Texts.dB, AudioMixerController.kMinVolume, AudioMixerController.kMaxEffect, controller, new AudioEffectParameterPath(group, effect, sendGuid)))\n                        {\n                            Undo.RecordObject(controller.TargetSnapshot, \"Change Send Level\");\n                            effect.SetValueForMixLevel(controller, controller.TargetSnapshot, wetLevel);\n                            AudioMixerUtility.RepaintAudioMixerAndInspectors();\n                        }\n                    }\n                }\n\n                if (MixerEffectDefinitions.EffectCanBeSidechainTarget(effect))\n                {\n                    bool anyTargetsFound = false;\n                    foreach (var g in allGroups)\n                    {\n                        foreach (var e in g.effects)\n                        {\n                            if (e.IsSend() && e.sendTarget == effect)\n                            {\n                                anyTargetsFound = true;\n                                break;\n                            }\n                        }\n                        if (anyTargetsFound)\n                            break;\n                    }\n                    if (!anyTargetsFound)\n                    {\n                        GUILayout.Label(EditorGUIUtility.TrTextContent(\"No Send sources connected.\", EditorGUIUtility.warningIcon));\n                    }\n                }\n\n                // Wet mix\n                if (effect.enableWetMix && !effect.IsReceive() && !effect.IsDuckVolume() && !effect.IsAttenuation() && !effect.IsSend())\n                {\n                    float wetLevel = effect.GetValueForMixLevel(controller, controller.TargetSnapshot);\n                    if (AudioMixerEffectGUI.Slider(Texts.wet, ref wetLevel, 1.0f, 1.0f, Texts.dB, AudioMixerController.kMinVolume, AudioMixerController.kMaxEffect, controller, new AudioEffectParameterPath(group, effect, effect.GetGUIDForMixLevel())))\n                    {\n                        Undo.RecordObject(controller.TargetSnapshot, \"Change Mix Level\");\n                        effect.SetValueForMixLevel(controller, controller.TargetSnapshot, wetLevel);\n                        AudioMixerUtility.RepaintAudioMixerAndInspectors();\n                    }\n                }\n\n                // All other effects\n                bool drawDefaultGUI = true;\n                if (m_CustomEffectGUIs.ContainsKey(effect.effectName))\n                {\n                    var customGUI = m_CustomEffectGUIs[effect.effectName];\n                    m_SharedPlugin.m_Controller = controller;\n                    m_SharedPlugin.m_Effect = effect;\n                    m_SharedPlugin.m_ParamDefs = paramDefs;\n                    drawDefaultGUI = customGUI.OnGUI(m_SharedPlugin);\n                }\n                if (drawDefaultGUI)\n                {\n                    foreach (var p in paramDefs)\n                    {\n                        float value = effect.GetValueForParameter(controller, controller.TargetSnapshot, p.name);\n                        if (AudioMixerEffectGUI.Slider(GUIContent.Temp(p.name, p.description), ref value, p.displayScale, p.displayExponent, p.units, p.minRange, p.maxRange, controller, new AudioEffectParameterPath(group, effect, effect.GetGUIDForParameter(p.name))))\n                        {\n                            Undo.RecordObject(controller.TargetSnapshot, \"Change \" + p.name);\n                            effect.SetValueForParameter(controller, controller.TargetSnapshot, p.name, value);\n                        }\n                    }\n                    if (paramDefs.Length > 0)\n                        GUILayout.Space(6f);\n                }\n            }\n\n            m_EffectDragging.HandleDragElement(effectIndex, totalRect, dragRect, group, allGroups);\n\n            EditorGUILayout.EndVertical(); // indented effect contents\n            EditorGUILayout.EndVertical(); // calc total size\n\n            AudioMixerDrawUtils.DrawSplitter();\n        }\n\n        private static void ShowEffectContextMenu(AudioMixerGroupController group, AudioMixerEffectController effect, int effectIndex, AudioMixerController controller, Rect buttonRect)\n        {\n            GenericMenu menu = new GenericMenu();\n\n            if (!effect.IsReceive())\n            {\n                if (!effect.IsAttenuation() && !effect.IsSend() && !effect.IsDuckVolume())\n                {\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Allow Wet Mixing (causes higher memory usage)\"), effect.enableWetMix, delegate { AudioMixerUtility.ToggleEffectWetMix(effect); });\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Bypass\"), effect.bypass, delegate()\n                    {\n                        Undo.RecordObject(effect, \"Bypass Effect\");\n                        effect.bypass = !effect.bypass;\n\n                        controller.UpdateBypass();\n                        AudioMixerUtility.RepaintAudioMixerAndInspectors();\n                    });\n                    menu.AddSeparator(\"\");\n                }\n\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Copy effect settings to all snapshots\"), false, delegate()\n                {\n                    Undo.RecordObject(controller, \"Copy effect settings to all snapshots\");\n                    if (effect.IsAttenuation())\n                        controller.CopyAttenuationToAllSnapshots(group, controller.TargetSnapshot);\n                    else\n                        controller.CopyEffectSettingsToAllSnapshots(group, effectIndex, controller.TargetSnapshot, effect.IsSend());\n                    AudioMixerUtility.RepaintAudioMixerAndInspectors();\n                });\n\n                if (!effect.IsAttenuation() && !effect.IsSend() && !effect.IsDuckVolume() && effect.enableWetMix)\n                {\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Copy effect settings to all snapshots, including wet level\"), false, delegate()\n                    {\n                        Undo.RecordObject(controller, \"Copy effect settings to all snapshots, including wet level\");\n                        controller.CopyEffectSettingsToAllSnapshots(group, effectIndex, controller.TargetSnapshot, true);\n                        AudioMixerUtility.RepaintAudioMixerAndInspectors();\n                    });\n                }\n\n                menu.AddSeparator(\"\");\n            }\n\n            AudioMixerGroupController[] groupArray = new AudioMixerGroupController[] { group };\n            AudioMixerChannelStripView.AddEffectItemsToMenu(controller, groupArray, effectIndex, \"Add effect before/\", menu);\n            AudioMixerChannelStripView.AddEffectItemsToMenu(controller, groupArray, effectIndex + 1, \"Add effect after/\", menu);\n\n            if (!effect.IsAttenuation())\n            {\n                menu.AddSeparator(\"\");\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Remove this effect\"), false, delegate()\n                {\n                    controller.RemoveEffect(effect, group);\n                    AudioMixerUtility.RepaintAudioMixerAndInspectors();\n                });\n            }\n\n            menu.DropDown(buttonRect);\n        }\n\n        private static void ShowBusPopupMenu(int effectIndex, AudioMixerGroupController group, List<AudioMixerGroupController> allGroups, Dictionary<AudioMixerEffectController, AudioMixerGroupController> effectMap, AudioMixerEffectController effect, Rect buttonRect)\n        {\n            GenericMenu pm = new GenericMenu();\n            var sendContext = new AudioMixerChannelStripView.ConnectSendContext(group.controller, effect, null);\n            pm.AddItem(EditorGUIUtility.TrTextContent(\"None\"), false, AudioMixerChannelStripView.ConnectSendPopupCallback, sendContext);\n            pm.AddSeparator(\"\");\n            AudioMixerChannelStripView.AddMenuItemsForReturns(pm, string.Empty, effectIndex, group, allGroups, effectMap, effect, true);\n\n            if (pm.GetItemCount() == 2)\n            {\n                pm.AddDisabledItem(EditorGUIUtility.TrTextContent(\"No valid Receive targets found\"));\n            }\n\n            pm.DropDown(buttonRect);\n        }\n\n        // -----------------------------------\n        // Effect dragging logic and rendering\n        // -----------------------------------\n        class EffectDragging\n        {\n            public EffectDragging()\n            {\n                m_DragControlID = GUIUtility.GetPermanentControlID();\n            }\n\n            public bool IsDraggingIndex(int effectIndex)\n            {\n                return m_MovingSrcIndex == effectIndex && GUIUtility.hotControl == m_DragControlID;\n            }\n\n            public int dragControlID\n            {\n                get { return m_DragControlID; }\n            }\n\n            private bool isDragging\n            {\n                get { return m_MovingSrcIndex != -1 && GUIUtility.hotControl == m_DragControlID; }\n            }\n\n            private readonly Color kMoveColorBorderAllowed = new Color(1.0f, 1.0f, 1.0f, 1.0f);\n            private readonly Color kMoveColorHiAllowed = new Color(1.0f, 1.0f, 1.0f, 0.3f);\n            private readonly Color kMoveColorLoAllowed = new Color(1.0f, 1.0f, 1.0f, 0.0f);\n            private readonly Color kMoveColorBorderDisallowed = new Color(0.8f, 0.0f, 0.0f, 1.0f);\n            private readonly Color kMoveColorHiDisallowed = new Color(1.0f, 0.0f, 0.0f, 0.3f);\n            private readonly Color kMoveColorLoDisallowed = new Color(1.0f, 0.0f, 0.0f, 0.0f);\n\n            private readonly int m_DragControlID = 0;\n            private int m_MovingSrcIndex = -1;\n            private int m_MovingDstIndex = -1;\n            private bool m_MovingEffectAllowed = false;\n            private float m_MovingPos = 0;\n            private Rect m_MovingRect = new Rect(0, 0, 0, 0);\n            private float m_DragHighlightPos = -1.0f;\n            private float m_DragHighlightHeight = 2f;\n\n            // Called per effect\n            public void HandleDragElement(int effectIndex, Rect effectRect, Rect dragRect, AudioMixerGroupController group, List<AudioMixerGroupController> allGroups)\n            {\n                Event evt = Event.current;\n\n                switch (evt.GetTypeForControl(m_DragControlID))\n                {\n                    case EventType.MouseDown:\n                        if (evt.button == 0 && dragRect.Contains(evt.mousePosition) && GUIUtility.hotControl == 0)\n                        {\n                            m_MovingSrcIndex = effectIndex;\n                            m_MovingPos = evt.mousePosition.y;\n                            m_MovingRect = new Rect(effectRect.x, effectRect.y - m_MovingPos, effectRect.width, effectRect.height);\n                            GUIUtility.hotControl = m_DragControlID;\n                            EditorGUIUtility.SetWantsMouseJumping(1);\n                            evt.Use();\n                        }\n                        break;\n\n                    case EventType.Repaint:\n                        if (effectIndex == m_MovingSrcIndex)\n                        {\n                            using (new EditorGUI.DisabledScope(true))\n                            {\n                                AudioMixerDrawUtils.styles.channelStripAreaBackground.Draw(effectRect, false, false, false, false);\n                            }\n                        }\n                        break;\n                }\n\n                if (isDragging)\n                {\n                    float h2 = effectRect.height * 0.5f;\n                    float dy = evt.mousePosition.y - effectRect.y - h2;\n\n                    if (Mathf.Abs(dy) <= h2)\n                    {\n                        int newMovingDstIndex = (dy < 0.0f) ? effectIndex : (effectIndex + 1);\n                        if (newMovingDstIndex != m_MovingDstIndex)\n                        {\n                            m_DragHighlightPos = (dy < 0.0f) ? effectRect.y : (effectRect.y + effectRect.height);\n                            m_MovingDstIndex = newMovingDstIndex;\n                            m_MovingEffectAllowed = !AudioMixerController.WillMovingEffectCauseFeedback(allGroups, group, m_MovingSrcIndex, group, newMovingDstIndex, null);\n                        }\n                    }\n\n                    // Do not draw drag highlight line for positions where no change will happen\n                    if (m_MovingDstIndex == m_MovingSrcIndex || m_MovingDstIndex == m_MovingSrcIndex + 1)\n                    {\n                        m_DragHighlightPos = 0;\n                    }\n                }\n            }\n\n            // Called once per OnGUI\n            public void HandleDragging(Rect totalRect, AudioMixerGroupController group, AudioMixerController controller)\n            {\n                // Early out if we are not dragging\n                if (!isDragging)\n                    return;\n\n                Event evt = Event.current;\n                const float kMoveRange = 15;\n\n                switch (evt.GetTypeForControl(m_DragControlID))\n                {\n                    case EventType.MouseDrag:\n                        m_MovingPos = evt.mousePosition.y;\n                        evt.Use();\n                        break;\n\n                    case EventType.MouseUp:\n                        evt.Use();\n                        if (m_MovingSrcIndex != -1)\n                        {\n                            if (m_MovingDstIndex != -1 && m_MovingEffectAllowed)\n                            {\n                                var effects = group.effects.ToList();\n                                if (AudioMixerController.MoveEffect(ref effects, m_MovingSrcIndex, ref effects, m_MovingDstIndex))\n                                    group.effects = effects.ToArray();\n                            }\n                            m_MovingSrcIndex = -1;\n                            m_MovingDstIndex = -1;\n                            controller.m_HighlightEffectIndex = -1;\n                            if (GUIUtility.hotControl == m_DragControlID)\n                                GUIUtility.hotControl = 0;\n                            EditorGUIUtility.SetWantsMouseJumping(0);\n                            AudioMixerUtility.RepaintAudioMixerAndInspectors();\n                            EditorGUIUtility.ExitGUI(); // Exit because we changed order of effects\n                        }\n                        break;\n\n                    case EventType.Repaint:\n                        if (m_DragHighlightPos > 0.0f)\n                        {\n                            float w = totalRect.width;\n                            Color moveColorLo = (m_MovingEffectAllowed) ? kMoveColorLoAllowed : kMoveColorLoDisallowed;\n                            Color moveColorHi = (m_MovingEffectAllowed) ? kMoveColorHiAllowed : kMoveColorHiDisallowed;\n                            Color moveColorBorder = (m_MovingEffectAllowed) ? kMoveColorBorderAllowed : kMoveColorBorderDisallowed;\n                            AudioMixerDrawUtils.DrawGradientRect(new Rect(m_MovingRect.x, m_DragHighlightPos - kMoveRange, w, kMoveRange), moveColorLo, moveColorHi);\n                            AudioMixerDrawUtils.DrawGradientRect(new Rect(m_MovingRect.x, m_DragHighlightPos, w, kMoveRange), moveColorHi, moveColorLo);\n                            AudioMixerDrawUtils.DrawGradientRect(new Rect(m_MovingRect.x, m_DragHighlightPos - m_DragHighlightHeight / 2, w, m_DragHighlightHeight), moveColorBorder, moveColorBorder);\n                        }\n                        break;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParameterView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.IO;\nusing System;\nusing UnityEditorInternal;\nusing UnityEditor.Audio;\n\nnamespace UnityEditor\n{\n    class AudioMixerExposedParameterView\n    {\n        private ReorderableListWithRenameAndScrollView m_ReorderableListWithRenameAndScrollView;\n        private AudioMixerController m_Controller;\n        private SerializedObject m_ControllerSerialized;\n        ReorderableListWithRenameAndScrollView.State m_State;\n\n        private float height { get { return m_ReorderableListWithRenameAndScrollView.list.GetHeight(); } }\n\n        public AudioMixerExposedParameterView(ReorderableListWithRenameAndScrollView.State state)\n        {\n            m_State = state;\n        }\n\n        public void OnMixerControllerChanged(AudioMixerController controller)\n        {\n            m_Controller = controller;\n\n            if (m_Controller)\n                m_Controller.ChangedExposedParameter += new ChangedExposedParameterHandler(RecreateListControl);\n\n            RecreateListControl();\n        }\n\n        public void RecreateListControl()\n        {\n            if (m_Controller != null)\n            {\n                m_ControllerSerialized = new SerializedObject(m_Controller);\n                var exposedParams = m_ControllerSerialized.FindProperty(\"m_ExposedParameters\");\n                System.Diagnostics.Debug.Assert(exposedParams != null);\n\n                ReorderableList reorderableList = new ReorderableList(m_ControllerSerialized, exposedParams, false, false, false, false);\n                reorderableList.onReorderCallback = EndDragChild;\n                reorderableList.drawElementCallback += DrawElement;\n                reorderableList.elementHeight = 18;\n                reorderableList.headerHeight = 0;\n                reorderableList.footerHeight = 0;\n                reorderableList.showDefaultBackground = false;\n\n                m_ReorderableListWithRenameAndScrollView = new ReorderableListWithRenameAndScrollView(reorderableList, m_State);\n                m_ReorderableListWithRenameAndScrollView.onNameChangedAtIndex += NameChanged;\n                m_ReorderableListWithRenameAndScrollView.onDeleteItemAtIndex += Delete;\n                m_ReorderableListWithRenameAndScrollView.onGetNameAtIndex += GetNameOfElement;\n            }\n        }\n\n        public void OnGUI(Rect rect)\n        {\n            if (m_Controller == null)\n                return;\n\n            m_ReorderableListWithRenameAndScrollView.OnGUI(rect);\n        }\n\n        public void OnContextClick(int itemIndex)\n        {\n            GenericMenu pm = new GenericMenu();\n            pm.AddItem(\n                EditorGUIUtility.TrTextContent(\"Unexpose\"),\n                false,\n                delegate(object data) { Delete((int)data); },\n                itemIndex);\n\n            pm.AddItem(\n                EditorGUIUtility.TrTextContent(\"Rename\"),\n                false,\n                delegate(object data) { m_ReorderableListWithRenameAndScrollView.BeginRename((int)data, 0f); },\n                itemIndex);\n\n            pm.ShowAsContext();\n        }\n\n        void DrawElement(Rect rect, int index, bool isActive, bool isFocused)\n        {\n            Event evt = Event.current;\n            if (evt.type == EventType.ContextClick && rect.Contains(evt.mousePosition))\n            {\n                OnContextClick(index);\n                evt.Use();\n            }\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            // The left side of the text is drawn by the reorderable list, now draw the additional right aligned text\n            using (new EditorGUI.DisabledScope(true))\n            {\n                m_ReorderableListWithRenameAndScrollView.elementStyleRightAligned.Draw(rect, GetInfoString(index), false, false, false, false);\n            }\n        }\n\n        public Vector2 CalcSize()\n        {\n            if (m_ReorderableListWithRenameAndScrollView.list.count != m_Controller.exposedParameters.Length)\n            {\n                RecreateListControl();\n            }\n            float maxWidth = 0;\n            for (int index = 0; index < m_ReorderableListWithRenameAndScrollView.list.count; index++)\n            {\n                var width = WidthOfRow(index, m_ReorderableListWithRenameAndScrollView.elementStyle, m_ReorderableListWithRenameAndScrollView.elementStyleRightAligned);\n                if (width > maxWidth)\n                    maxWidth = width;\n            }\n            return new Vector2(maxWidth, height);\n        }\n\n        string GetInfoString(int index)\n        {\n            ExposedAudioParameter exposedParam = m_Controller.exposedParameters[index];\n            return m_Controller.ResolveExposedParameterPath(exposedParam.guid, false);\n        }\n\n        private float WidthOfRow(int index, GUIStyle leftStyle, GUIStyle rightStyle)\n        {\n            const float kMinSpacing = 25f;\n            string infoString = GetInfoString(index);\n            Vector2 infoSize = rightStyle.CalcSize(GUIContent.Temp(infoString));\n            Vector2 size = leftStyle.CalcSize(GUIContent.Temp(GetNameOfElement(index)));\n            float width = size.x + infoSize.x + kMinSpacing;\n            return width;\n        }\n\n        string GetNameOfElement(int index)\n        {\n            ExposedAudioParameter exposedParam = m_Controller.exposedParameters[index];\n            return exposedParam.name;\n        }\n\n        public void NameChanged(int index, string newName)\n        {\n            const int kMaxNameLength = 64;\n            if (newName.Length > kMaxNameLength)\n            {\n                newName = newName.Substring(0, kMaxNameLength);\n                Debug.LogWarning(\"Maximum name length of an exposed parameter is \" + kMaxNameLength + \" characters. Name truncated to '\" + newName + \"'\");\n            }\n            ExposedAudioParameter[] parameters = m_Controller.exposedParameters;\n            parameters[index].name = newName;\n            m_Controller.exposedParameters = parameters;\n        }\n\n        void Delete(int index)\n        {\n            if (m_Controller != null)\n            {\n                Undo.RecordObject(m_Controller, \"Unexpose Mixer Parameter\");\n                ExposedAudioParameter exposedParam = m_Controller.exposedParameters[index];\n                m_Controller.RemoveExposedParameter(exposedParam.guid);\n            }\n        }\n\n        public void EndDragChild(ReorderableList list)\n        {\n            m_ControllerSerialized.ApplyModifiedProperties();\n        }\n\n        public void OnEvent()\n        {\n            m_ReorderableListWithRenameAndScrollView.OnEvent();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParametersPopup.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing UnityEditor.Audio;\n\nnamespace UnityEditor\n{\n    internal partial class AudioMixerExposedParametersPopup : PopupWindowContent\n    {\n        // Shows pop up\n        internal static void Popup(AudioMixerController controller, GUIStyle style, params GUILayoutOption[] options)\n        {\n            GUIContent content = GetButtonContent(controller);\n            Rect buttonRect = GUILayoutUtility.GetRect(content, style, options);\n            if (EditorGUI.DropdownButton(buttonRect, content, FocusType.Passive, style))\n            {\n                PopupWindow.Show(buttonRect, new AudioMixerExposedParametersPopup(controller));\n            }\n        }\n\n        // Cache to prevent constructing string on every event\n        static GUIContent m_ButtonContent = EditorGUIUtility.TrTextContent(\"\", \"Audio Mixer parameters can be exposed to scripting. Select an Audio Mixer Group, right click one of its properties in the Inspector and select 'Expose'.\");\n        static int m_LastNumExposedParams = -1;\n        static GUIContent GetButtonContent(AudioMixerController controller)\n        {\n            if (controller.numExposedParameters != m_LastNumExposedParams)\n            {\n                m_ButtonContent.text = string.Format(\"Exposed Parameters ({0})\", controller.numExposedParameters);\n                m_LastNumExposedParams = controller.numExposedParameters;\n            }\n            return m_ButtonContent;\n        }\n\n        //\n        private readonly AudioMixerExposedParameterView m_ExposedParametersView;\n\n        AudioMixerExposedParametersPopup(AudioMixerController controller)\n        {\n            m_ExposedParametersView = new AudioMixerExposedParameterView(new ReorderableListWithRenameAndScrollView.State());\n            m_ExposedParametersView.OnMixerControllerChanged(controller);\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            m_ExposedParametersView.OnEvent();\n            m_ExposedParametersView.OnGUI(rect);\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            Vector2 size = m_ExposedParametersView.CalcSize();\n            size.x = Math.Max(size.x, 125f);\n            size.y = Math.Max(size.y, 23f);\n            return size;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/AudioMixerGroupTreeView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.IO;\nusing System;\nusing UnityEditorInternal;\nusing UnityEditor.Audio;\nusing UnityEditor.IMGUI.Controls;\nusing Object = UnityEngine.Object;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewGUI = UnityEditor.IMGUI.Controls.TreeViewGUI<int>;\nusing TreeViewDataSource = UnityEditor.IMGUI.Controls.TreeViewDataSource<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    // Item\n\n    internal class AudioMixerTreeViewNode : TreeViewItem\n    {\n        public AudioMixerGroupController group { get; set; }\n\n        public AudioMixerTreeViewNode(int instanceID, int depth, TreeViewItem parent, string displayName, AudioMixerGroupController group)\n            : base(instanceID, depth, parent, displayName)\n        {\n            this.group = group;\n        }\n    }\n\n    // Dragging\n    // We want dragging to work from the mixer window to the inspector like the project browser, but also want\n    // custom dragging behavior (reparent the group sub assets) so we derive from AssetOrGameObjectTreeViewDragging\n    // and override DoDrag.\n\n    internal class AudioGroupTreeViewDragging : AssetsTreeViewDragging\n    {\n        private AudioMixerGroupTreeView m_owner;\n\n        public AudioGroupTreeViewDragging(TreeViewController treeView, AudioMixerGroupTreeView owner)\n            : base(treeView)\n        {\n            m_owner = owner;\n        }\n\n        public override void StartDrag(TreeViewItem draggedItem, List<int> draggedItemIDs)\n        {\n            if (!EditorApplication.isPlaying)\n                base.StartDrag(draggedItem, draggedItemIDs);\n        }\n\n        public override DragAndDropVisualMode DoDrag(TreeViewItem parentNode, TreeViewItem targetNode, bool perform, DropPosition dragPos)\n        {\n            var parentGroupNode = parentNode as AudioMixerTreeViewNode;\n            var draggedGroups = new List<Object>(DragAndDrop.objectReferences).OfType<AudioMixerGroupController>().ToList();\n            if (parentGroupNode != null && draggedGroups.Count > 0)\n            {\n                var draggedIDs = (from i in draggedGroups select i.GetInstanceID()).ToList();\n                bool validDrag = ValidDrag(parentNode, draggedIDs) && !AudioMixerController.WillModificationOfTopologyCauseFeedback(m_owner.Controller.GetAllAudioGroupsSlow(), draggedGroups, parentGroupNode.group, null);\n                if (perform && validDrag)\n                {\n                    AudioMixerGroupController parentGroup = parentGroupNode.group;\n\n                    // If insertionIndex is -1 we are dropping upon the parentNode\n                    int insertionIndex = GetInsertionIndex(parentNode, targetNode, dragPos);\n\n                    m_owner.Controller.ReparentSelection(parentGroup, insertionIndex, draggedGroups);\n                    m_owner.ReloadTree();\n                    m_owner.Controller.OnSubAssetChanged();\n                    m_TreeView.SetSelection(draggedIDs.ToArray(), true); // Ensure dropped item(s) are selected and revealed (fixes selection if click dragging a single item that is not selected when drag was started)\n                }\n\n                return validDrag ? DragAndDropVisualMode.Move : DragAndDropVisualMode.Rejected;\n            }\n\n            return DragAndDropVisualMode.None;\n        }\n\n        bool ValidDrag(TreeViewItem parent, List<int> draggedInstanceIDs)\n        {\n            TreeViewItem currentParent = parent;\n            while (currentParent != null)\n            {\n                if (draggedInstanceIDs.Contains(currentParent.id))\n                    return false;\n                currentParent = currentParent.parent;\n            }\n\n            return true;\n        }\n    }\n\n    // Datasource\n\n    internal class AudioGroupDataSource : TreeViewDataSource\n    {\n        public AudioGroupDataSource(TreeViewController treeView, AudioMixerController controller)\n            : base(treeView)\n        {\n            m_Controller = controller;\n        }\n\n        private void AddNodesRecursively(AudioMixerGroupController group, TreeViewItem parent, int depth)\n        {\n            var children = new List<TreeViewItem>();\n            for (int i = 0; i < group.children.Length; ++i)\n            {\n                int uniqueNodeID = GetUniqueNodeID(group.children[i]);\n                var node = new AudioMixerTreeViewNode(uniqueNodeID, depth, parent, group.children[i].name, group.children[i]);\n                node.parent = parent;\n                children.Add(node);\n                AddNodesRecursively(group.children[i], node, depth + 1);\n            }\n\n            parent.children = children;\n        }\n\n        static public int GetUniqueNodeID(AudioMixerGroupController group)\n        {\n            return group.GetInstanceID(); // alternative: group.groupID.GetHashCode();\n        }\n\n        public override void FetchData()\n        {\n            if (m_Controller == null)\n            {\n                m_RootItem = null;\n                return;\n            }\n\n            if (m_Controller.masterGroup == null)\n            {\n                Debug.LogError(\"The Master group is missing !!!\");\n                m_RootItem = null;\n                return;\n            }\n\n            int uniqueNodeID = GetUniqueNodeID(m_Controller.masterGroup);\n            m_RootItem = new AudioMixerTreeViewNode(uniqueNodeID, 0, null, m_Controller.masterGroup.name, m_Controller.masterGroup);\n            AddNodesRecursively(m_Controller.masterGroup, m_RootItem, 1);\n            m_NeedRefreshRows = true;\n        }\n\n        public override bool IsRenamingItemAllowed(TreeViewItem node)\n        {\n            var audioNode = node as AudioMixerTreeViewNode;\n            if (audioNode.group == m_Controller.masterGroup)\n                return false;\n\n            return true;\n        }\n\n        public AudioMixerController m_Controller;\n    }\n\n    // Node GUI\n\n    internal class AudioGroupTreeViewGUI : TreeViewGUI\n    {\n        readonly float column1Width = 20f;\n        readonly GUIContent k_VisibleON = EditorGUIUtility.TrIconContent(\"animationvisibilitytoggleon\");\n        readonly GUIContent k_VisibleOFF = EditorGUIUtility.TrIconContent(\"animationvisibilitytoggleoff\");\n        public Action<AudioMixerTreeViewNode, bool> NodeWasToggled;\n        public AudioMixerController m_Controller = null;\n\n        public AudioGroupTreeViewGUI(TreeViewController treeView)\n            : base(treeView)\n        {\n            k_BaseIndent = column1Width;\n            k_IconWidth = 0;\n            k_TopRowMargin = k_BottomRowMargin = 2f;\n        }\n\n        void OpenGroupContextMenu(AudioMixerTreeViewNode audioNode, bool visible)\n        {\n            GenericMenu menu = new GenericMenu();\n\n            if (NodeWasToggled != null)\n            {\n                menu.AddItem(new GUIContent(visible ? \"Hide group\" : \"Show Group\"), false, () => NodeWasToggled(audioNode, !visible));\n            }\n\n            menu.AddSeparator(string.Empty);\n\n            AudioMixerGroupController[] groups;\n            if (m_Controller.CachedSelection.Contains(audioNode.group))\n                groups = m_Controller.CachedSelection.ToArray();\n            else\n                groups = new AudioMixerGroupController[] { audioNode.group };\n\n            AudioMixerColorCodes.AddColorItemsToGenericMenu(menu, groups);\n            menu.ShowAsContext();\n        }\n\n        override public void OnRowGUI(Rect rowRect, TreeViewItem node, int row, bool selected, bool focused)\n        {\n            Event evt = Event.current;\n            DoItemGUI(rowRect, row, node, selected, focused, false);\n\n            if (m_Controller == null)\n                return;\n\n            var audioNode = node as AudioMixerTreeViewNode;\n            if (audioNode != null)\n            {\n                bool oldSelected = m_Controller.CurrentViewContainsGroup(audioNode.group.groupID);\n                const float kIconSize = 16f;\n\n                float xMargin = 3f;\n                Rect iconRect = new Rect(rowRect.x + xMargin, rowRect.y, kIconSize, kIconSize);\n                Rect iconBgRect = new Rect(iconRect.x + 1, iconRect.y + 1, iconRect.width - 2, iconRect.height - 2);\n\n                int colorIndex = audioNode.group.userColorIndex;\n                if (colorIndex > 0)\n                    EditorGUI.DrawRect(new Rect(rowRect.x, iconBgRect.y, 2, iconBgRect.height), AudioMixerColorCodes.GetColor(colorIndex));\n\n                if (oldSelected)\n                    GUI.DrawTexture(iconRect, k_VisibleON.image);\n                else\n                    GUI.DrawTexture(iconRect, k_VisibleOFF.image);\n\n                Rect toggleRect = new Rect(2, rowRect.y, rowRect.height, rowRect.height);\n                if (evt.type == EventType.MouseUp && evt.button == 0 && toggleRect.Contains(evt.mousePosition))\n                {\n                    if (NodeWasToggled != null)\n                        NodeWasToggled(audioNode, !oldSelected);\n                }\n\n                if (evt.type == EventType.ContextClick && iconRect.Contains(evt.mousePosition))\n                {\n                    OpenGroupContextMenu(audioNode, oldSelected);\n                    evt.Use();\n                }\n            }\n        }\n\n        protected override Texture GetIconForItem(TreeViewItem node)\n        {\n            if (node != null && node.icon != null)\n                return node.icon;\n            return null;\n        }\n\n        protected override void SyncFakeItem() {}\n\n        protected override void RenameEnded()\n        {\n            bool userAccepted = GetRenameOverlay().userAcceptedRename;\n            if (userAccepted)\n            {\n                string name = string.IsNullOrEmpty(GetRenameOverlay().name) ? GetRenameOverlay().originalName : GetRenameOverlay().name;\n                int instanceID = GetRenameOverlay().userData;\n                var audioNode = m_TreeView.FindItem(instanceID) as AudioMixerTreeViewNode;\n                if (audioNode != null)\n                {\n                    ObjectNames.SetNameSmartWithInstanceID(instanceID, name);\n                    foreach (var effect in audioNode.group.effects)\n                        effect.ClearCachedDisplayName();\n                    m_TreeView.ReloadData();\n                    if (m_Controller != null)\n                        m_Controller.OnSubAssetChanged();\n                }\n            }\n        }\n    }\n\n    // TreeView\n\n    internal class AudioMixerGroupPopupContext\n    {\n        public AudioMixerGroupPopupContext(AudioMixerController controller, AudioMixerGroupController group)\n        {\n            this.controller = controller;\n            this.groups = new AudioMixerGroupController[] { group };\n        }\n\n        public AudioMixerGroupPopupContext(AudioMixerController controller, AudioMixerGroupController[] groups)\n        {\n            this.controller = controller;\n            this.groups = groups;\n        }\n\n        public AudioMixerController controller;\n        public AudioMixerGroupController[] groups;\n    }\n\n    internal class AudioMixerGroupTreeView\n    {\n        private AudioMixerController m_Controller;\n        private AudioGroupDataSource m_AudioGroupTreeDataSource;\n        private TreeViewState m_AudioGroupTreeState;\n        private TreeViewController m_AudioGroupTree;\n        private AudioGroupTreeViewGUI m_TreeViewGUI;\n        private AudioMixerGroupController m_ScrollToItem;\n\n        class Styles\n        {\n            public GUIContent header = EditorGUIUtility.TrTextContent(\"Groups\", \"An Audio Mixer Group is used by e.g Audio Sources to modify the audio output before it reaches the Audio Listener. An Audio Mixer Group will route its output to another Audio Mixer Group if it is made a child of that group. The Master Group will route its output to the Audio Listener if it doesn't route its output into another Mixer.\");\n            public GUIContent addButton = EditorGUIUtility.TrIconContent(\"CreateAddNew\", \"Add child group\");\n            public Texture2D audioMixerGroupIcon = EditorGUIUtility.FindTexture(typeof(UnityEngine.Audio.AudioMixerGroup));\n        }\n\n        static Styles s_Styles;\n\n        public AudioMixerGroupTreeView(AudioMixerWindow mixerWindow, TreeViewState treeState)\n        {\n            m_AudioGroupTreeState = treeState;\n\n            m_AudioGroupTree = new TreeViewController(mixerWindow, m_AudioGroupTreeState);\n            m_AudioGroupTree.deselectOnUnhandledMouseDown = false;\n            m_AudioGroupTree.selectionChangedCallback += OnTreeSelectionChanged;\n            m_AudioGroupTree.contextClickItemCallback += OnTreeViewContextClick;\n            m_AudioGroupTree.expandedStateChanged += SaveExpandedState;\n\n            m_TreeViewGUI = new AudioGroupTreeViewGUI(m_AudioGroupTree);\n            m_TreeViewGUI.NodeWasToggled += OnNodeToggled;\n\n            m_AudioGroupTreeDataSource = new AudioGroupDataSource(m_AudioGroupTree, m_Controller);\n            m_AudioGroupTree.Init(mixerWindow.position,\n                m_AudioGroupTreeDataSource, m_TreeViewGUI,\n                new AudioGroupTreeViewDragging(m_AudioGroupTree, this)\n            );\n            m_AudioGroupTree.ReloadData();\n        }\n\n        public AudioMixerController Controller\n        {\n            get { return m_Controller; }\n        }\n\n        public AudioMixerGroupController ScrollToItem\n        {\n            get { return m_ScrollToItem; }\n        }\n\n        public void UseScrollView(bool useScrollView)\n        {\n            m_AudioGroupTree.useScrollView = useScrollView;\n        }\n\n        public void ReloadTreeData()\n        {\n            m_AudioGroupTree.ReloadData();\n        }\n\n        public void ReloadTree()\n        {\n            m_AudioGroupTree.ReloadData();\n            if (m_Controller != null)\n                m_Controller.SanitizeGroupViews();\n        }\n\n        public void AddChildGroupPopupCallback(object obj)\n        {\n            AudioMixerGroupPopupContext context = (AudioMixerGroupPopupContext)obj;\n            if (context.groups != null && context.groups.Length > 0)\n                AddAudioMixerGroup(context.groups[0]);\n        }\n\n        public void AddSiblingGroupPopupCallback(object obj)\n        {\n            AudioMixerGroupPopupContext context = (AudioMixerGroupPopupContext)obj;\n            if (context.groups != null && context.groups.Length > 0)\n            {\n                var item = m_AudioGroupTree.FindItem(context.groups[0].GetInstanceID()) as AudioMixerTreeViewNode;\n                if (item != null)\n                {\n                    var parent = item.parent as AudioMixerTreeViewNode;\n                    AddAudioMixerGroup(parent.group);\n                }\n            }\n        }\n\n        public void AddAudioMixerGroup(AudioMixerGroupController parent)\n        {\n            if (parent == null || m_Controller == null)\n                return;\n\n            var newGroup = m_Controller.CreateNewGroup(\"New Group\", true);\n            Undo.RecordObjects(new UnityEngine.Object[] { m_Controller, parent }, \"Add Child Group\");\n            m_Controller.AddChildToParent(newGroup, parent);\n            m_Controller.AddGroupToCurrentView(newGroup);\n\n            Selection.objects = new[] { newGroup };\n            m_Controller.OnUnitySelectionChanged();\n            m_AudioGroupTree.SetSelection(new int[] { newGroup.GetInstanceID() }, true);\n            ReloadTree();\n            m_Controller.OnSubAssetChanged();\n            m_AudioGroupTree.BeginNameEditing(0f);\n        }\n\n        static string PluralIfNeeded(int count)\n        {\n            return count > 1 ? \"s\" : \"\";\n        }\n\n        public void DeleteGroups(List<AudioMixerGroupController> groups)\n        {\n            foreach (AudioMixerGroupController group in groups)\n            {\n                if (group.HasDependentMixers())\n                {\n                    if (!EditorUtility.DisplayDialog(\"Referenced Group\", \"Deleted group is referenced by another AudioMixer, are you sure?\", \"Delete\", \"Cancel\"))\n                        return;\n                    break;\n                }\n            }\n\n            m_Controller.DeleteGroups(groups.ToArray());\n            ReloadTree();\n            m_Controller.OnSubAssetChanged();\n        }\n\n        public void DuplicateGroups(List<AudioMixerGroupController> groups, bool recordUndo)\n        {\n            if (recordUndo)\n            {\n                Undo.RecordObject(m_Controller, \"Duplicate group\" + PluralIfNeeded(groups.Count));\n                Undo.RecordObject(m_Controller.masterGroup, \"\");\n            }\n\n            var duplicatedRoots = m_Controller.DuplicateGroups(groups.ToArray(), recordUndo);\n            if (duplicatedRoots.Count > 0)\n            {\n                ReloadTree();\n                m_Controller.OnSubAssetChanged();\n                var instanceIDs = duplicatedRoots.Select(audioMixerGroup => audioMixerGroup.GetInstanceID()).ToArray();\n                m_AudioGroupTree.SetSelection(instanceIDs, false);\n                m_AudioGroupTree.Frame(instanceIDs[instanceIDs.Length - 1], true, false);\n            }\n        }\n\n        void DeleteGroupsPopupCallback(object obj)\n        {\n            var audioMixerGroupTreeView = (AudioMixerGroupTreeView)obj;\n            audioMixerGroupTreeView.DeleteGroups(GetGroupSelectionWithoutMasterGroup());\n        }\n\n        void DuplicateGroupPopupCallback(object obj)\n        {\n            var audioMixerGroupTreeView = (AudioMixerGroupTreeView)obj;\n            audioMixerGroupTreeView.DuplicateGroups(GetGroupSelectionWithoutMasterGroup(), true);\n        }\n\n        void RenameGroupCallback(object obj)\n        {\n            var item = (TreeViewItem)obj;\n            m_AudioGroupTree.SetSelection(new int[] { item.id }, false);\n            m_AudioGroupTree.BeginNameEditing(0f);\n        }\n\n        List<AudioMixerGroupController> GetGroupSelectionWithoutMasterGroup()\n        {\n            var items = GetAudioMixerGroupsFromNodeIDs(m_AudioGroupTree.GetSelection());\n            items.Remove(m_Controller.masterGroup);\n            return items;\n        }\n\n        public void OnTreeViewContextClick(int index)\n        {\n            var node = m_AudioGroupTree.FindItem(index);\n            if (node != null)\n            {\n                AudioMixerTreeViewNode mixerNode = node as AudioMixerTreeViewNode;\n                if (mixerNode != null && mixerNode.group != null)\n                {\n                    GenericMenu pm = new GenericMenu();\n\n                    if (!EditorApplication.isPlaying)\n                    {\n                        pm.AddItem(EditorGUIUtility.TrTextContent(\"Add child group\"), false, AddChildGroupPopupCallback, new AudioMixerGroupPopupContext(m_Controller, mixerNode.group));\n                        if (mixerNode.group != m_Controller.masterGroup)\n                        {\n                            pm.AddItem(EditorGUIUtility.TrTextContent(\"Add sibling group\"), false, AddSiblingGroupPopupCallback, new AudioMixerGroupPopupContext(m_Controller, mixerNode.group));\n                            pm.AddSeparator(\"\");\n                            pm.AddItem(EditorGUIUtility.TrTextContent(\"Rename\"), false, RenameGroupCallback, node);\n\n                            // Mastergroup cannot be deleted nor duplicated\n                            var selection = GetGroupSelectionWithoutMasterGroup().ToArray();\n                            pm.AddItem(new GUIContent((selection.Length > 1) ? \"Duplicate groups (and children)\" : \"Duplicate group (and children)\"), false, DuplicateGroupPopupCallback, this);\n                            pm.AddItem(new GUIContent((selection.Length > 1) ? \"Remove groups (and children)\" : \"Remove group (and children)\"), false, DeleteGroupsPopupCallback, this);\n                        }\n                    }\n                    else\n                    {\n                        pm.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Modifying group topology in play mode is not allowed\"));\n                    }\n\n                    pm.ShowAsContext();\n                }\n            }\n        }\n\n        void OnNodeToggled(AudioMixerTreeViewNode node, bool nodeWasEnabled)\n        {\n            Undo.RecordObject(m_Controller, \"Changed Group Visibility\");\n            var treeSelection = GetAudioMixerGroupsFromNodeIDs(m_AudioGroupTree.GetSelection());\n            if (!treeSelection.Contains(node.group))\n                treeSelection = new List<AudioMixerGroupController> { node.group };\n            var newSelection = new List<GUID>();\n            var allGroups = m_Controller.GetAllAudioGroupsSlow();\n            foreach (var g in allGroups)\n            {\n                bool inOldSelection = m_Controller.CurrentViewContainsGroup(g.groupID);\n                bool inNewSelection = treeSelection.Contains(g);\n                bool add = inOldSelection && !inNewSelection;\n                if (!inOldSelection && inNewSelection)\n                    add = nodeWasEnabled;\n                if (add)\n                    newSelection.Add(g.groupID);\n            }\n\n            m_Controller.SetCurrentViewVisibility(newSelection.ToArray());\n        }\n\n        List<AudioMixerGroupController> GetAudioMixerGroupsFromNodeIDs(int[] instanceIDs)\n        {\n            List<AudioMixerGroupController> newSelectedGroups = new List<AudioMixerGroupController>();\n            foreach (var s in instanceIDs)\n            {\n                var node = m_AudioGroupTree.FindItem(s);\n                if (node != null)\n                {\n                    AudioMixerTreeViewNode mixerNode = node as AudioMixerTreeViewNode;\n                    if (mixerNode != null)\n                        newSelectedGroups.Add(mixerNode.group);\n                }\n            }\n\n            return newSelectedGroups;\n        }\n\n        public void OnTreeSelectionChanged(int[] selection)\n        {\n            var groups = GetAudioMixerGroupsFromNodeIDs(selection);\n            Selection.objects = groups.ToArray();\n            m_Controller.OnUnitySelectionChanged();\n            if (groups.Count == 1)\n                m_ScrollToItem = groups[0];\n            InspectorWindow.RepaintAllInspectors();\n        }\n\n        public void InitSelection(bool revealSelectionAndFrameLastSelected)\n        {\n            if (m_Controller == null)\n                return;\n\n            var groups = m_Controller.CachedSelection;\n            m_AudioGroupTree.SetSelection((from x in groups select x.GetInstanceID()).ToArray(), revealSelectionAndFrameLastSelected);\n        }\n\n        public float GetTotalHeight()\n        {\n            if (m_Controller == null)\n                return 0f;\n            return m_AudioGroupTree.gui.GetTotalSize().y + AudioMixerDrawUtils.kSectionHeaderHeight;\n        }\n\n        public void OnGUI(Rect rect)\n        {\n            int treeViewKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard);\n\n            m_ScrollToItem = null;\n\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            m_AudioGroupTree.OnEvent();\n\n            Rect headerRect, contentRect;\n            using (new EditorGUI.DisabledScope(m_Controller == null))\n            {\n                AudioMixerDrawUtils.DrawRegionBg(rect, out headerRect, out contentRect);\n                AudioMixerDrawUtils.HeaderLabel(headerRect, s_Styles.header, s_Styles.audioMixerGroupIcon);\n            }\n\n            if (m_Controller != null)\n            {\n                AudioMixerGroupController parent = (m_Controller.CachedSelection.Count == 1) ? m_Controller.CachedSelection[0] : m_Controller.masterGroup;\n                using (new EditorGUI.DisabledScope(EditorApplication.isPlaying))\n                {\n                    if (GUI.Button(new Rect(headerRect.xMax - 17f, headerRect.y + 3f, 16f, 16f), s_Styles.addButton, EditorStyles.iconButton))\n                        AddAudioMixerGroup(parent);\n                }\n\n                m_AudioGroupTree.OnGUI(contentRect, treeViewKeyboardControlID);\n                AudioMixerDrawUtils.DrawScrollDropShadow(contentRect, m_AudioGroupTree.state.scrollPos.y, m_AudioGroupTree.gui.GetTotalSize().y);\n\n                HandleKeyboardEvents(treeViewKeyboardControlID);\n                HandleCommandEvents(treeViewKeyboardControlID);\n            }\n        }\n\n        void HandleCommandEvents(int treeViewKeyboardControlID)\n        {\n            if (GUIUtility.keyboardControl != treeViewKeyboardControlID)\n                return;\n\n            EventType eventType = Event.current.type;\n            if (eventType == EventType.ExecuteCommand || eventType == EventType.ValidateCommand)\n            {\n                bool execute = eventType == EventType.ExecuteCommand;\n\n                if (Event.current.commandName == EventCommandNames.Delete || Event.current.commandName == EventCommandNames.SoftDelete)\n                {\n                    Event.current.Use();\n                    if (execute)\n                    {\n                        DeleteGroups(GetGroupSelectionWithoutMasterGroup());\n                        GUIUtility.ExitGUI(); // Cached groups might have been deleted to so early out of event\n                    }\n                }\n                else if (Event.current.commandName == EventCommandNames.Duplicate)\n                {\n                    Event.current.Use();\n                    if (execute)\n                        DuplicateGroups(GetGroupSelectionWithoutMasterGroup(), true);\n                }\n            }\n        }\n\n        void HandleKeyboardEvents(int treeViewKeyboardControlID)\n        {\n            if (GUIUtility.keyboardControl != treeViewKeyboardControlID)\n                return;\n\n            Event evt = Event.current;\n            if (evt.keyCode == KeyCode.Space && evt.type == EventType.KeyDown)\n            {\n                int[] selection = m_AudioGroupTree.GetSelection();\n                if (selection.Length > 0)\n                {\n                    AudioMixerTreeViewNode node = m_AudioGroupTree.FindItem(selection[0]) as AudioMixerTreeViewNode;\n                    bool shown = m_Controller.CurrentViewContainsGroup(node.group.groupID);\n                    OnNodeToggled(node, !shown);\n                    evt.Use();\n                }\n            }\n        }\n\n        public void OnMixerControllerChanged(AudioMixerController controller)\n        {\n            if (m_Controller != controller)\n            {\n                m_TreeViewGUI.m_Controller = controller;\n                m_Controller = controller;\n                m_AudioGroupTreeDataSource.m_Controller = controller;\n                if (controller != null)\n                {\n                    ReloadTree();\n                    InitSelection(false);\n                    LoadExpandedState();\n                    m_AudioGroupTree.data.SetExpandedWithChildren(m_AudioGroupTree.data.root, true);\n                }\n            }\n        }\n\n        static string GetUniqueAudioMixerName(AudioMixerController controller)\n        {\n            return \"AudioMixer_\" + controller.GetInstanceID();\n        }\n\n        void SaveExpandedState()\n        {\n            SessionState.SetIntArray(GetUniqueAudioMixerName(m_Controller), m_AudioGroupTreeState.expandedIDs.ToArray());\n        }\n\n        void LoadExpandedState()\n        {\n            int[] cachedExpandedState = SessionState.GetIntArray(GetUniqueAudioMixerName(m_Controller), null);\n            if (cachedExpandedState != null)\n            {\n                m_AudioGroupTreeState.expandedIDs = new List<int>(cachedExpandedState);\n            }\n            else\n            {\n                // Expand whole tree. If no cached data then its the first time tree was loaded in this session\n                m_AudioGroupTree.state.expandedIDs = new List<int>();\n                m_AudioGroupTree.data.SetExpandedWithChildren(m_AudioGroupTree.data.root, true);\n            }\n        }\n\n        public void EndRenaming()\n        {\n            m_AudioGroupTree.EndNameEditing(true);\n        }\n\n        public void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            ReloadTree();\n            if (m_Controller != null)\n                m_Controller.OnSubAssetChanged();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/AudioMixerGroupViewList.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.IO;\nusing System;\nusing UnityEditorInternal;\nusing UnityEditor.Audio;\n\nnamespace UnityEditor\n{\n    internal class AudioMixerGroupViewList\n    {\n        ReorderableListWithRenameAndScrollView m_ReorderableListWithRenameAndScrollView;\n        AudioMixerController m_Controller;\n        List<MixerGroupView> m_Views;\n        readonly ReorderableListWithRenameAndScrollView.State m_State;\n\n        class Styles\n        {\n            public GUIContent header = EditorGUIUtility.TrTextContent(\"Views\", \"A view is the saved visibility state of the current Mixer Groups. Use views to setup often used combinations of Mixer Groups.\");\n            public GUIContent addButton = EditorGUIUtility.TrIconContent(\"CreateAddNew\");\n            public Texture2D viewsIcon = EditorGUIUtility.FindTexture(\"AudioMixerView Icon\");\n        }\n        static Styles s_Styles;\n\n        public AudioMixerGroupViewList(ReorderableListWithRenameAndScrollView.State state)\n        {\n            m_State = state;\n        }\n\n        public void OnMixerControllerChanged(AudioMixerController controller)\n        {\n            m_Controller = controller;\n            RecreateListControl();\n        }\n\n        public void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            RecreateListControl();\n        }\n\n        public void OnEvent()\n        {\n            if (m_Controller == null)\n                return;\n            m_ReorderableListWithRenameAndScrollView.OnEvent();\n        }\n\n        public void RecreateListControl()\n        {\n            if (m_Controller == null)\n                return;\n\n            m_Views = new List<MixerGroupView>(m_Controller.views);\n\n            // Ensure default view\n            if (m_Views.Count == 0)\n            {\n                var view = new MixerGroupView();\n                view.guids = m_Controller.GetAllAudioGroupsSlow().Select(gr => gr.groupID).ToArray();\n                view.name = \"View\";\n                m_Views.Add(view);\n                SaveToBackend();\n            }\n\n            var reorderableList = new ReorderableList(m_Views, typeof(MixerGroupView), true, false, false, false);\n            reorderableList.onReorderCallback += EndDragChild;\n            reorderableList.elementHeight = 18;\n            reorderableList.headerHeight = 0;\n            reorderableList.footerHeight = 0;\n            reorderableList.showDefaultBackground = false;\n            reorderableList.index = m_Controller.currentViewIndex;\n\n            if (m_Controller.currentViewIndex >= reorderableList.count)\n                Debug.LogError(\"State mismatch, currentViewIndex: \" + m_Controller.currentViewIndex + \", num items: \" + reorderableList.count);\n\n            // Now extend reorderable list with scrollview and renaming functionality\n            m_ReorderableListWithRenameAndScrollView = new ReorderableListWithRenameAndScrollView(reorderableList, m_State);\n            m_ReorderableListWithRenameAndScrollView.onSelectionChanged += SelectionChanged;\n            m_ReorderableListWithRenameAndScrollView.onNameChangedAtIndex += NameChanged;\n            m_ReorderableListWithRenameAndScrollView.onDeleteItemAtIndex += Delete;\n            m_ReorderableListWithRenameAndScrollView.onGetNameAtIndex += GetNameOfElement;\n            m_ReorderableListWithRenameAndScrollView.onCustomDrawElement += CustomDrawElement;\n        }\n\n        public float GetTotalHeight()\n        {\n            if (m_Controller == null)\n                return 0f;\n            return m_ReorderableListWithRenameAndScrollView.list.GetHeight() + AudioMixerDrawUtils.kSectionHeaderHeight;\n        }\n\n        public void OnGUI(Rect rect)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            Rect headerRect, contentRect;\n            using (new EditorGUI.DisabledScope(m_Controller == null))\n            {\n                AudioMixerDrawUtils.DrawRegionBg(rect, out headerRect, out contentRect);\n                AudioMixerDrawUtils.HeaderLabel(headerRect, s_Styles.header, s_Styles.viewsIcon);\n            }\n\n            if (m_Controller != null)\n            {\n                // Ensure in-sync\n                if (m_ReorderableListWithRenameAndScrollView.list.index != m_Controller.currentViewIndex)\n                {\n                    m_ReorderableListWithRenameAndScrollView.list.index = m_Controller.currentViewIndex;\n                    m_ReorderableListWithRenameAndScrollView.FrameItem(m_Controller.currentViewIndex);\n                }\n\n                m_ReorderableListWithRenameAndScrollView.OnGUI(contentRect);\n\n                // Call after list to prevent id mismatch\n                if (GUI.Button(new Rect(headerRect.xMax - 17f, headerRect.y + 3f, 16f, 16f), s_Styles.addButton, EditorStyles.iconButton))\n                    Add();\n            }\n        }\n\n        public void CustomDrawElement(Rect r, int index, bool isActive, bool isFocused)\n        {\n            Event evt = Event.current;\n            if (evt.type == EventType.MouseUp && evt.button == 1 && r.Contains(evt.mousePosition))\n            {\n                ViewsContexttMenu.Show(r, index, this);\n                evt.Use();\n            }\n\n            bool isSelected = (index == m_ReorderableListWithRenameAndScrollView.list.index) && !m_ReorderableListWithRenameAndScrollView.IsRenamingIndex(index);\n            m_ReorderableListWithRenameAndScrollView.DrawElementText(r, index, isActive, isSelected, isFocused);\n        }\n\n        void SaveToBackend()\n        {\n            m_Controller.views = m_Views.ToArray();\n        }\n\n        void LoadFromBackend()\n        {\n            m_Views.Clear();\n            m_Views.AddRange(m_Controller.views);\n        }\n\n        string GetNameOfElement(int index)\n        {\n            return m_Views[index].name;\n        }\n\n        void Add()\n        {\n            m_Controller.CloneViewFromCurrent();\n            LoadFromBackend();\n\n            int newSelectedIndex = m_Views.Count - 1;\n            m_Controller.currentViewIndex = newSelectedIndex;\n            m_ReorderableListWithRenameAndScrollView.BeginRename(newSelectedIndex, 0f);\n        }\n\n        void Delete(int index)\n        {\n            if (m_Views.Count <= 1)\n            {\n                Debug.Log(\"Deleting all views is not allowed\");\n                return;\n            }\n\n            m_Controller.DeleteView(index);\n            LoadFromBackend();\n        }\n\n        public void NameChanged(int index, string newName)\n        {\n            LoadFromBackend();\n            MixerGroupView view = m_Views[index];\n            view.name = newName;\n            m_Views[index] = view;\n            SaveToBackend();\n        }\n\n        public void SelectionChanged(int selectedIndex)\n        {\n            LoadFromBackend();\n            m_Controller.SetView(selectedIndex);\n        }\n\n        public void EndDragChild(ReorderableList list)\n        {\n            m_Views = m_ReorderableListWithRenameAndScrollView.list.list as List<MixerGroupView>;\n            SaveToBackend();\n        }\n\n        void Rename(int index)\n        {\n            m_ReorderableListWithRenameAndScrollView.BeginRename(index, 0f);\n        }\n\n        void DuplicateCurrentView()\n        {\n            m_Controller.CloneViewFromCurrent();\n            LoadFromBackend();\n        }\n\n        internal class ViewsContexttMenu\n        {\n            class data\n            {\n                public int viewIndex;\n                public AudioMixerGroupViewList list;\n            }\n\n            static public void Show(Rect buttonRect, int viewIndex, AudioMixerGroupViewList list)\n            {\n                var menu = new GenericMenu();\n                data input = new data() { viewIndex = viewIndex, list = list };\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Rename\"), false, Rename, input);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Duplicate\"), false, Duplicate, input);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Delete\"), false, Delete, input);\n\n                menu.DropDown(buttonRect);\n            }\n\n            static void Rename(object userData)\n            {\n                data input = userData as data;\n                input.list.Rename(input.viewIndex);\n            }\n\n            static void Duplicate(object userData)\n            {\n                data input = userData as data;\n                input.list.m_Controller.currentViewIndex = input.viewIndex;\n                input.list.DuplicateCurrentView();\n            }\n\n            static void Delete(object userData)\n            {\n                data input = userData as data;\n                input.list.Delete(input.viewIndex);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/AudioMixerSelection.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditor.Audio;\n\nnamespace UnityEditor\n{\n    internal class AudioMixerSelection\n    {\n        public AudioMixerSelection(AudioMixerController controller)\n        {\n            m_Controller = controller;\n            ChannelStripSelection = new List<AudioMixerGroupController>();\n            SyncToUnitySelection();\n        }\n\n        private AudioMixerController m_Controller;\n        public List<AudioMixerGroupController> ChannelStripSelection { get; private set; }\n\n        // Channelstrip selection\n        // We rely on SyncToUnitySelection is being called after setting Selection.objects through AudioWindow::OnSelectionChange ()\n        public void SyncToUnitySelection()\n        {\n            if (m_Controller != null)\n                RefreshCachedChannelStripSelection();\n        }\n\n        public void SetChannelStrips(List<AudioMixerGroupController> newSelection)\n        {\n            Selection.objects = newSelection.ToArray();\n            //Debug.Log(\"SetChannelStrips \" + DebugUtils.ListToString(Selection.instanceIDs));\n        }\n\n        public void SetSingleChannelStrip(AudioMixerGroupController group)\n        {\n            Selection.objects = new[] {group};\n            //Debug.Log(\"SetSingleChannelStrip \" + DebugUtils.ListToString(Selection.instanceIDs));\n        }\n\n        public void ToggleChannelStrip(AudioMixerGroupController group)\n        {\n            var selection = new List<Object>(Selection.objects);\n            if (selection.Contains(group))\n                selection.Remove(group);\n            else\n                selection.Add(group);\n            Selection.objects = selection.ToArray();\n        }\n\n        public void ClearChannelStrips()\n        {\n            Selection.objects = new Object[0];\n            //Debug.Log(\"ClearChannelStrips \" + DebugUtils.ListToString(Selection.instanceIDs));\n        }\n\n        public bool HasSingleChannelStripSelection()\n        {\n            return ChannelStripSelection.Count == 1;\n        }\n\n        private void RefreshCachedChannelStripSelection()\n        {\n            var selected = Selection.GetFiltered(typeof(AudioMixerGroupController), SelectionMode.Deep);\n            ChannelStripSelection = new List<AudioMixerGroupController>();\n            List<AudioMixerGroupController> allGroups = m_Controller.GetAllAudioGroupsSlow();\n\n            foreach (var g in allGroups)\n                if (selected.Contains(g))\n                    ChannelStripSelection.Add(g);\n        }\n\n        // Call this after making changes to the group topology (when removing groups)\n        public void Sanitize()\n        {\n            RefreshCachedChannelStripSelection();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/AudioMixerSnapshotView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.IO;\nusing System;\nusing UnityEditorInternal;\nusing UnityEditor.Audio;\n\nnamespace UnityEditor\n{\n    internal class AudioMixerSnapshotListView\n    {\n        private ReorderableListWithRenameAndScrollView m_ReorderableListWithRenameAndScrollView;\n        private AudioMixerController m_Controller;\n        List<AudioMixerSnapshotController> m_Snapshots;\n        ReorderableListWithRenameAndScrollView.State m_State;\n\n        class Styles\n        {\n            public GUIContent starIcon = EditorGUIUtility.TrIconContent(\"Favorite\", \"Start snapshot\");\n            public GUIContent header = EditorGUIUtility.TrTextContent(\"Snapshots\", \"A snapshot is a set of values for all parameters in the mixer. When using the mixer, you modify parameters in the selected snapshot. Blend between multiple snapshots at runtime.\");\n            public GUIContent addButton = EditorGUIUtility.TrIconContent(\"CreateAddNew\");\n            public Texture2D snapshotsIcon = EditorGUIUtility.FindTexture(typeof(UnityEngine.Audio.AudioMixerSnapshot));\n        }\n        static Styles s_Styles;\n\n\n        public AudioMixerSnapshotListView(ReorderableListWithRenameAndScrollView.State state)\n        {\n            m_State = state;\n        }\n\n        public void OnMixerControllerChanged(AudioMixerController controller)\n        {\n            m_Controller = controller;\n            RecreateListControl();\n        }\n\n        int GetSnapshotIndex(AudioMixerSnapshotController snapshot)\n        {\n            for (int i = 0; i < m_Snapshots.Count; i++)\n            {\n                if (m_Snapshots[i] == snapshot)\n                    return i;\n            }\n\n            return 0;\n        }\n\n        void RecreateListControl()\n        {\n            if (m_Controller == null)\n                return;\n\n            m_Snapshots = new List<AudioMixerSnapshotController>(m_Controller.snapshots);\n\n            ReorderableList reorderableList = new ReorderableList(m_Snapshots, typeof(AudioMixerSnapshotController), true, false, false, false);\n            reorderableList.onReorderCallback = EndDragChild;\n            reorderableList.elementHeight = 18f;\n            reorderableList.headerHeight = 0f;\n            reorderableList.footerHeight = 0f;\n            reorderableList.showDefaultBackground = false;\n            reorderableList.index = GetSnapshotIndex(m_Controller.TargetSnapshot);\n\n            m_ReorderableListWithRenameAndScrollView = new ReorderableListWithRenameAndScrollView(reorderableList, m_State);\n            m_ReorderableListWithRenameAndScrollView.onSelectionChanged += SelectionChanged;\n            m_ReorderableListWithRenameAndScrollView.onNameChangedAtIndex += NameChanged;\n            m_ReorderableListWithRenameAndScrollView.onDeleteItemAtIndex += Delete;\n            m_ReorderableListWithRenameAndScrollView.onGetNameAtIndex += GetNameOfElement;\n            m_ReorderableListWithRenameAndScrollView.onCustomDrawElement += CustomDrawElement;\n        }\n\n        void SaveToBackend()\n        {\n            m_Controller.snapshots = m_Snapshots.ToArray();\n\n            m_Controller.OnSubAssetChanged();\n        }\n\n        public void LoadFromBackend()\n        {\n            if (m_Controller == null)\n                return;\n\n            m_Snapshots.Clear();\n            m_Snapshots.AddRange(m_Controller.snapshots);\n        }\n\n        public void OnEvent()\n        {\n            if (m_Controller == null)\n                return;\n            m_ReorderableListWithRenameAndScrollView.OnEvent();\n        }\n\n        public void CustomDrawElement(Rect r, int index, bool isActive, bool isFocused)\n        {\n            Event evt = Event.current;\n            if (evt.type == EventType.MouseUp && evt.button == 1 && r.Contains(evt.mousePosition))\n            {\n                SnapshotMenu.Show(r, m_Snapshots[index], this);\n                evt.Use();\n            }\n\n            const float iconSize = 16f;\n            const float spacing = 5f;\n\n            bool isSelected = (index == m_ReorderableListWithRenameAndScrollView.list.index) && !m_ReorderableListWithRenameAndScrollView.IsRenamingIndex(index);\n\n            // Text\n            r.width -= iconSize + spacing;\n            m_ReorderableListWithRenameAndScrollView.DrawElementText(r, index, isActive, isSelected, isFocused);\n\n            // Startup icon\n            if (m_Controller.startSnapshot == m_Snapshots[index])\n            {\n                r.x = r.xMax + spacing + 5f;\n                r.y = r.y + (r.height - iconSize) / 2;\n                r.width = r.height = iconSize;\n                GUI.Label(r, s_Styles.starIcon, GUIStyle.none);\n            }\n        }\n\n        public float GetTotalHeight()\n        {\n            if (m_Controller == null)\n                return 0f;\n            return m_ReorderableListWithRenameAndScrollView.list.GetHeight() + AudioMixerDrawUtils.kSectionHeaderHeight;\n        }\n\n        public void OnGUI(Rect rect)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            Rect headerRect, contentRect;\n            using (new EditorGUI.DisabledScope(m_Controller == null))\n            {\n                AudioMixerDrawUtils.DrawRegionBg(rect, out headerRect, out contentRect);\n                AudioMixerDrawUtils.HeaderLabel(headerRect, s_Styles.header, s_Styles.snapshotsIcon);\n            }\n\n            if (m_Controller != null)\n            {\n                // Ensure gui is in-sync with backend (TargetSnapShotIndex can be changed anytime from the backend)\n                int targetIndex = GetSnapshotIndex(m_Controller.TargetSnapshot);\n                if (targetIndex != m_ReorderableListWithRenameAndScrollView.list.index)\n                {\n                    m_ReorderableListWithRenameAndScrollView.list.index = targetIndex;\n                    m_ReorderableListWithRenameAndScrollView.FrameItem(targetIndex);\n                }\n                m_ReorderableListWithRenameAndScrollView.OnGUI(contentRect);\n\n                if (GUI.Button(new Rect(headerRect.xMax - 17f, headerRect.y + 3f, 16f, 16f), s_Styles.addButton, EditorStyles.iconButton))\n                    Add();\n            }\n        }\n\n        public void SelectionChanged(int index)\n        {\n            //For some UI reason, selecting some region just below the last element of the\n            //re-orderable list will cause a selection index greater than is available.\n            if (index >= m_Snapshots.Count)\n                index = m_Snapshots.Count - 1;\n\n            m_Controller.TargetSnapshot = m_Snapshots[index];\n            UpdateViews();\n        }\n\n        string GetNameOfElement(int index)\n        {\n            return m_Snapshots[index].name;\n        }\n\n        private string DeduplicateNewName(int index, string newName)\n        {\n            int suffix = 1;\n            string source = newName;\n            bool duplicate;\n            do\n            {\n                duplicate = false;\n                for (int i = 0; i < m_Snapshots.Count; i++)\n                {\n                    if (i != index && m_Snapshots[i].name == newName)\n                    {\n                        duplicate = true;\n                        newName = String.Format(\"{0} ({1:D2})\", source, suffix);\n                        suffix++;\n                        break;\n                    }\n                }\n            }\n            while (duplicate);\n            return newName;\n        }\n\n        public void NameChanged(int index, string newName)\n        {\n            if (newName.Equals(m_Snapshots[index].name))\n            {\n                return;\n            }\n\n            Undo.RecordObject(m_Snapshots[index], \"Rename snapshot\");\n            newName = DeduplicateNewName(index, newName);\n            m_Snapshots[index].name = newName;\n            SaveToBackend();\n        }\n\n        void DuplicateCurrentSnapshot()\n        {\n            Undo.RecordObject(m_Controller, \"Duplicate current snapshot\");\n            m_Controller.CloneNewSnapshotFromTarget(true);\n            LoadFromBackend();\n            UpdateViews();\n        }\n\n        void Add()\n        {\n            Undo.RecordObject(m_Controller, \"Add new snapshot\");\n            m_Controller.CloneNewSnapshotFromTarget(true);\n            LoadFromBackend();\n            Rename(m_Controller.TargetSnapshot);\n            UpdateViews();\n        }\n\n        void DeleteSnapshot(AudioMixerSnapshotController snapshot)\n        {\n            AudioMixerSnapshotController[] snapshots = m_Controller.snapshots;\n            if (snapshots.Length <= 1)\n            {\n                Debug.Log(\"You must have at least 1 snapshot in an AudioMixer.\");\n                return;\n            }\n\n            m_Controller.RemoveSnapshot(snapshot);\n            LoadFromBackend();\n            m_ReorderableListWithRenameAndScrollView.list.index = GetSnapshotIndex(m_Controller.TargetSnapshot);\n            UpdateViews();\n        }\n\n        void Delete(int index)\n        {\n            DeleteSnapshot(m_Snapshots[index]);\n        }\n\n        public void EndDragChild(ReorderableList list)\n        {\n            Undo.RecordObject(m_Controller, \"Drag\");\n            m_Snapshots = m_ReorderableListWithRenameAndScrollView.list.list as List<AudioMixerSnapshotController>;\n            SaveToBackend();\n        }\n\n        private void UpdateViews()\n        {\n            AudioMixerWindow mixerWindow = (AudioMixerWindow)WindowLayout.FindEditorWindowOfType(typeof(AudioMixerWindow));\n            if (mixerWindow != null)\n                mixerWindow.Repaint();\n\n            InspectorWindow.RepaintAllInspectors();\n        }\n\n        void SetAsStartupSnapshot(AudioMixerSnapshotController snapshot)\n        {\n            Undo.RecordObject(m_Controller, \"Set start snapshot\");\n            m_Controller.startSnapshot = snapshot;\n        }\n\n        void Rename(AudioMixerSnapshotController snapshot)\n        {\n            m_ReorderableListWithRenameAndScrollView.BeginRename(GetSnapshotIndex(snapshot), 0f);\n        }\n\n        internal class SnapshotMenu\n        {\n            class data\n            {\n                public AudioMixerSnapshotController snapshot;\n                public AudioMixerSnapshotListView list;\n            }\n\n            static public void Show(Rect buttonRect, AudioMixerSnapshotController snapshot, AudioMixerSnapshotListView list)\n            {\n                var menu = new GenericMenu();\n                data input = new data() { snapshot = snapshot, list = list };\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Set as start Snapshot\"), false, SetAsStartupSnapshot, input);\n                menu.AddSeparator(\"\");\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Rename\"), false, Rename, input);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Duplicate\"), false, Duplicate, input);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Delete\"), false, Delete, input);\n\n                menu.DropDown(buttonRect);\n            }\n\n            static void SetAsStartupSnapshot(object userData)\n            {\n                data input = userData as data;\n                input.list.SetAsStartupSnapshot(input.snapshot);\n            }\n\n            static void Rename(object userData)\n            {\n                data input = userData as data;\n                input.list.Rename(input.snapshot);\n            }\n\n            static void Duplicate(object userData)\n            {\n                data input = userData as data;\n                input.list.DuplicateCurrentSnapshot();\n            }\n\n            static void Delete(object userData)\n            {\n                data input = userData as data;\n                input.list.DeleteSnapshot(input.snapshot);\n            }\n        }\n\n        public void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            LoadFromBackend();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/AudioMixerUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Audio;\n\nnamespace UnityEditor\n{\n    internal class AudioMixerUtility\n    {\n        static public void RepaintAudioMixerAndInspectors()\n        {\n            InspectorWindow.RepaintAllInspectors();\n            AudioMixerWindow.RepaintAudioMixerWindow();\n        }\n\n        static public void ToggleEffectWetMix(AudioMixerEffectController effect)\n        {\n            var undoEntryPrefix = effect.enableWetMix ? \"Disable\" : \"Enable\";\n            Undo.RecordObject(effect, $\"{undoEntryPrefix} Wet Mixing\");\n            effect.enableWetMix = !effect.enableWetMix;\n            RepaintAudioMixerAndInspectors();\n        }\n\n        public class VisitorFetchInstanceIDs\n        {\n            public List<int> instanceIDs = new List<int>();\n            public void Visitor(AudioMixerGroupController group)\n            {\n                instanceIDs.Add(group.GetInstanceID());\n            }\n        }\n\n        public static void VisitGroupsRecursivly(AudioMixerGroupController group, Action<AudioMixerGroupController> visitorCallback)\n        {\n            foreach (var child in group.children)\n                VisitGroupsRecursivly(child, visitorCallback);\n\n            if (visitorCallback != null)\n                visitorCallback(group);\n        }\n    }\n}\n// namespace\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/AudioMixerWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System;\nusing UnityEditorInternal;\nusing UnityEditor.Audio;\nusing UnityEditor.IMGUI.Controls;\nusing RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    [EditorWindowTitle(title = \"Audio Mixer\", icon = \"Audio Mixer\")]\n    internal class AudioMixerWindow : EditorWindow, IHasCustomMenu\n    {\n        static AudioMixerWindow s_Instance;\n\n        static string kAudioMixerUseRMSMetering = \"AudioMixerUseRMSMetering\";\n        static string kAudioMixerUseHorzLayout = \"AudioMixerUseHorzLayout\";\n\n        enum SectionType\n        {\n            MixerTree,\n            GroupTree,\n            ViewList,\n            SnapshotList\n        }\n\n        public enum LayoutMode\n        {\n            Uninitialized = -1,\n            Horizontal = 0,\n            Vertical = 1\n        }\n\n        [Serializable]\n        class Layout\n        {\n            [SerializeField]\n            public SplitterState m_VerticalSplitter;\n            [SerializeField]\n            public SplitterState m_HorizontalSplitter;\n        }\n\n        [NonSerialized]\n        bool m_Initialized;\n\n        AudioMixerController m_Controller;\n        List<AudioMixerController> m_AllControllers;\n\n        AudioMixerChannelStripView.State m_ChannelStripViewState;\n        AudioMixerChannelStripView m_ChannelStripView;\n        TreeViewState m_AudioGroupTreeState;\n        AudioMixerGroupTreeView m_GroupTree;\n        [SerializeField] TreeViewStateWithAssetUtility m_MixersTreeState; // Use SerializeField so it is stored in the layout file (persistant)\n        AudioMixersTreeView m_MixersTree;\n        ReorderableListWithRenameAndScrollView.State m_ViewsState;\n        AudioMixerGroupViewList m_GroupViews;\n        ReorderableListWithRenameAndScrollView.State m_SnapshotState;\n        AudioMixerSnapshotListView m_SnapshotListView;\n\n        [SerializeField]\n        Layout m_LayoutStripsOnTop;\n        [SerializeField]\n        Layout m_LayoutStripsOnRight;\n        [SerializeField]\n        SectionType[] m_SectionOrder = { SectionType.MixerTree, SectionType.SnapshotList, SectionType.GroupTree, SectionType.ViewList }; // default order\n\n        [SerializeField]\n        LayoutMode m_LayoutMode = LayoutMode.Uninitialized;\n        [SerializeField]\n        bool m_SortGroupsAlphabetically = false;\n        [SerializeField]\n        bool m_ShowReferencedBuses = true;\n        [SerializeField]\n        bool m_ShowBusConnections = false;\n        [SerializeField]\n        bool m_ShowBusConnectionsOfSelection = false;\n\n        Vector2 m_SectionsScrollPosition = Vector2.zero;\n        int m_RepaintCounter = 2;\n        Vector2 m_LastSize;\n        bool m_GroupsRenderedAboveSections = true;\n\n        [NonSerialized]\n        bool m_ShowDeveloperOverlays = false;\n\n        readonly TickTimerHelper m_Ticker = new TickTimerHelper(1.0 / 20.0);\n\n        public AudioMixerController controller { get { return m_Controller; } }\n\n        LayoutMode layoutMode\n        {\n            get\n            {\n                return m_LayoutMode;\n            }\n            set\n            {\n                m_LayoutMode = value;\n                m_RepaintCounter = 2;\n                EditorPrefs.SetBool(kAudioMixerUseHorzLayout, m_LayoutMode == LayoutMode.Horizontal);\n            }\n        }\n\n        class GUIContents\n        {\n            public GUIContent editSnapShots;\n\n            public GUIContents()\n            {\n                editSnapShots = EditorGUIUtility.TrTextContent(\"Edit in Play Mode\", \"Edit in playmode and your changes are automatically saved. Note when editing is disabled, live values are shown.\", EditorGUIUtility.TrIconContent(\"Animation.Record\", \"Are scene and inspector changes recorded into the animation curves?\").image);\n            }\n        }\n        private static GUIContents s_GuiContents;\n\n        class AudioMixerPostprocessor : AssetPostprocessor\n        {\n            static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromPath)\n            {\n                if (s_Instance != null)\n                {\n                    bool anyMixers = importedAssets.Any(val => val.EndsWith(\".mixer\"));\n                    anyMixers |= deletedAssets.Any(val => val.EndsWith(\".mixer\"));\n                    anyMixers |= movedAssets.Any(val => val.EndsWith(\".mixer\"));\n                    anyMixers |= movedFromPath.Any(val => val.EndsWith(\".mixer\"));\n\n                    if (anyMixers)\n                        s_Instance.UpdateAfterAssetChange();\n                }\n            }\n        }\n\n        void UpdateAfterAssetChange()\n        {\n            m_AllControllers = FindAllAudioMixerControllers();\n\n            if (m_MixersTree == null)\n                Init();\n\n            if (m_Controller != null)\n            {\n                m_Controller.SanitizeGroupViews();\n                m_Controller.OnUnitySelectionChanged();\n            }\n\n            if (m_GroupTree != null)\n                m_GroupTree.ReloadTreeData();\n\n            if (m_GroupViews != null)\n                m_GroupViews.RecreateListControl();\n\n            if (m_SnapshotListView != null)\n                m_SnapshotListView.LoadFromBackend();\n\n            if (m_MixersTree != null)\n                m_MixersTree.ReloadTree();\n\n            AudioMixerUtility.RepaintAudioMixerAndInspectors();\n        }\n\n        [RequiredByNativeCode]\n        public static void CreateAudioMixerWindow()\n        {\n            var win = GetWindow<AudioMixerWindow>(typeof(ProjectBrowser));  // From usability tests we decided to auto dock together with project browser to prevent the mixer window keep going behind the main window on OSX\n\n            if (win.m_Pos.width < 400f)\n                win.m_Pos = new Rect(win.m_Pos.x, win.m_Pos.y, 800, 450f);  // Set default size if window is small\n        }\n\n        public static void RepaintAudioMixerWindow()\n        {\n            if (s_Instance != null)\n                s_Instance.Repaint();\n        }\n\n        void Init()\n        {\n            if (m_Initialized)\n                return;\n\n            if (m_LayoutStripsOnTop == null)\n                m_LayoutStripsOnTop = new Layout();\n\n            if (m_LayoutStripsOnTop.m_VerticalSplitter == null || m_LayoutStripsOnTop.m_VerticalSplitter.realSizes.Length != 2)\n            {\n                m_LayoutStripsOnTop.m_VerticalSplitter = SplitterState.FromAbsolute(new float[] { 65, 35 }, new float[] { 85, 105 }, null);\n            }\n\n            if (m_LayoutStripsOnTop.m_HorizontalSplitter == null || m_LayoutStripsOnTop.m_HorizontalSplitter.realSizes.Length != 4)\n                m_LayoutStripsOnTop.m_HorizontalSplitter = SplitterState.FromAbsolute(new float[] { 60, 60, 60, 60 }, new float[] { 85, 85, 85, 85 }, null);\n\n            if (m_LayoutStripsOnRight == null)\n                m_LayoutStripsOnRight = new Layout();\n\n            if (m_LayoutStripsOnRight.m_HorizontalSplitter == null || m_LayoutStripsOnRight.m_HorizontalSplitter.realSizes.Length != 2)\n                m_LayoutStripsOnRight.m_HorizontalSplitter = SplitterState.FromAbsolute(new float[] { 30, 70 }, new float[] { 160, 160 }, null);\n\n            if (m_LayoutStripsOnRight.m_VerticalSplitter == null || m_LayoutStripsOnRight.m_VerticalSplitter.realSizes.Length != 4)\n                m_LayoutStripsOnRight.m_VerticalSplitter = SplitterState.FromAbsolute(new float[] { 60, 60, 60, 60 }, new float[] { 100, 85, 85, 85 }, null);\n\n            if (m_AudioGroupTreeState == null)\n                m_AudioGroupTreeState = new TreeViewState();\n            m_GroupTree = new AudioMixerGroupTreeView(this, m_AudioGroupTreeState);\n\n            if (m_MixersTreeState == null)\n                m_MixersTreeState = new TreeViewStateWithAssetUtility();\n            m_MixersTree = new AudioMixersTreeView(this, m_MixersTreeState, GetAllControllers);\n\n            if (m_ViewsState == null)\n                m_ViewsState = new ReorderableListWithRenameAndScrollView.State();\n            m_GroupViews = new AudioMixerGroupViewList(m_ViewsState);\n\n            if (m_SnapshotState == null)\n                m_SnapshotState = new ReorderableListWithRenameAndScrollView.State();\n            m_SnapshotListView = new AudioMixerSnapshotListView(m_SnapshotState);\n\n            if (m_ChannelStripViewState == null)\n                m_ChannelStripViewState = new AudioMixerChannelStripView.State();\n            m_ChannelStripView = new AudioMixerChannelStripView(m_ChannelStripViewState);\n\n            OnMixerControllerChanged();\n\n            m_Initialized = true;\n        }\n\n        List<AudioMixerController> GetAllControllers()\n        {\n            return m_AllControllers;\n        }\n\n        static List<AudioMixerController> FindAllAudioMixerControllers()\n        {\n            var result = new List<AudioMixerController>();\n            foreach (var prop in AssetDatabase.FindAllAssets(new SearchFilter() { classNames = new[] { \"AudioMixerController\" } }))\n            {\n                var controller = prop.pptrValue as AudioMixerController;\n\n                if (controller)\n                {\n                    if (controller.HasValidSnapshots())\n                        result.Add(controller);\n                    else\n                        Debug.LogError($\"Can not display audio mixer window for '{controller.name}' as it could not be properly initialized. The mixer asset is possibly corrupted.\");\n                }\n            }\n            return result;\n        }\n\n        public void Awake()\n        {\n            m_AllControllers = FindAllAudioMixerControllers();\n\n            if (m_MixersTreeState != null)\n            {\n                // Clear state that are serialized in the layout file that should not survive closing/starting Unity\n                m_MixersTreeState.OnAwake();\n                m_MixersTreeState.selectedIDs = new List<int>();\n            }\n        }\n\n        public void OnEnable()\n        {\n            if (m_LayoutMode == LayoutMode.Uninitialized)\n            {\n                // We use vertical layout as default as it is the most compact layout\n                m_LayoutMode = EditorPrefs.GetBool(kAudioMixerUseHorzLayout) ? LayoutMode.Horizontal : LayoutMode.Vertical;\n            }\n            titleContent = GetLocalizedTitleContent();\n\n            s_Instance = this;\n\n            Undo.undoRedoEvent += UndoRedoPerformed;\n            EditorApplication.pauseStateChanged += OnPauseStateChanged;\n            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;\n        }\n\n        public void OnDisable()\n        {\n            EditorApplication.pauseStateChanged -= OnPauseStateChanged;\n            EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;\n            Undo.undoRedoEvent -= UndoRedoPerformed;\n        }\n\n        void OnPauseStateChanged(PauseState state)\n        {\n            OnPauseOrPlayModeStateChanged();\n        }\n\n        void OnPlayModeStateChanged(PlayModeStateChange state)\n        {\n            OnPauseOrPlayModeStateChanged();\n        }\n\n        void OnPauseOrPlayModeStateChanged()\n        {\n            m_Ticker.Reset();  // ensures immediate tick on play mode change\n            if (m_Controller != null)\n            {\n                Repaint();\n            }\n\n            EndRenaming();\n        }\n\n        void OnLostFocus()\n        {\n            EndRenaming();\n        }\n\n        void EndRenaming()\n        {\n            if (m_GroupTree != null)\n                m_GroupTree.EndRenaming();\n\n            if (m_MixersTree != null)\n                m_MixersTree.EndRenaming();\n        }\n\n        public void UndoRedoPerformed(in UndoRedoInfo info)\n        {\n            if (m_Controller == null)\n                return;\n\n            // Undo may have deleted one of the selected groups\n            m_Controller.OnSubAssetChanged();\n            m_Controller.SanitizeGroupViews();\n            m_Controller.OnUnitySelectionChanged();\n\n            if (m_GroupTree != null)\n                m_GroupTree.OnUndoRedoPerformed(info);\n\n            if (m_GroupViews != null)\n                m_GroupViews.OnUndoRedoPerformed(info);\n\n            if (m_SnapshotListView != null)\n                m_SnapshotListView.OnUndoRedoPerformed(info);\n\n            if (m_MixersTree != null)\n                m_MixersTree.OnUndoRedoPerformed(info);\n\n            AudioMixerUtility.RepaintAudioMixerAndInspectors();\n        }\n\n        void OnMixerControllerChanged()\n        {\n            if (m_Controller != null && !m_Controller.HasValidSnapshots())\n            {\n                Debug.LogError($\"Can not display audio mixer window for '{m_Controller.name}' as it could not be properly initialized. The mixer asset is possibly corrupted.\");\n                return;\n            }\n\n            if (m_Controller)\n                m_Controller.ClearEventHandlers();\n\n            m_MixersTree.OnMixerControllerChanged(m_Controller);\n            m_GroupTree.OnMixerControllerChanged(m_Controller);\n            m_GroupViews.OnMixerControllerChanged(m_Controller);\n            m_ChannelStripView.OnMixerControllerChanged(m_Controller);\n            m_SnapshotListView.OnMixerControllerChanged(m_Controller);\n\n            if (m_Controller)\n                m_Controller.ForceSetView(m_Controller.currentViewIndex);\n        }\n\n        // Called from C++\n        public void Update()\n        {\n            if (m_Ticker.DoTick())\n            {\n                if (EditorApplication.isPlaying || (m_ChannelStripView != null && m_ChannelStripView.requiresRepaint))\n                    Repaint();\n            }\n        }\n\n        void DetectControllerChange()\n        {\n            AudioMixerController oldController = m_Controller;\n            if (Selection.activeObject is AudioMixerController)\n                m_Controller = Selection.activeObject as AudioMixerController;\n\n            if (m_Controller != oldController)\n            {\n                if (m_Controller.HasValidSnapshots())\n                    OnMixerControllerChanged();\n                else\n                {\n                    Debug.LogError($\"Can not display audio mixer window for '{m_Controller.name}' as it could not be properly initialized. The mixer asset is possibly corrupted.\");\n                }\n            }\n        }\n\n        // Called from C++\n        void OnSelectionChange()\n        {\n            if (m_Controller != null)\n                m_Controller.OnUnitySelectionChanged();\n\n            if (m_GroupTree != null)\n                m_GroupTree.InitSelection(true);\n\n            Repaint();\n        }\n\n        Dictionary<AudioMixerEffectController, AudioMixerGroupController> GetEffectMap(List<AudioMixerGroupController> allGroups)\n        {\n            var effectMap = new Dictionary<AudioMixerEffectController, AudioMixerGroupController>();\n            foreach (var g in allGroups)\n                foreach (var e in g.effects)\n                    effectMap[e] = g;\n            return effectMap;\n        }\n\n        void DoToolbar()\n        {\n            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar, GUILayout.Height(EditorGUI.kWindowToolbarHeight));\n            GUILayout.FlexibleSpace();\n            if (m_Controller != null)\n            {\n                if (Application.isPlaying)\n                {\n                    Color orgColor = GUI.backgroundColor;\n                    if (AudioSettings.editingInPlaymode)\n                        GUI.backgroundColor = AnimationMode.animatedPropertyColor;\n\n                    EditorGUI.BeginChangeCheck();\n                    AudioSettings.editingInPlaymode = GUILayout.Toggle(AudioSettings.editingInPlaymode, s_GuiContents.editSnapShots, EditorStyles.toolbarButton);\n                    if (EditorGUI.EndChangeCheck())\n                        InspectorWindow.RepaintAllInspectors();\n\n                    GUI.backgroundColor = orgColor;\n                }\n                GUILayout.FlexibleSpace();\n\n                AudioMixerExposedParametersPopup.Popup(m_Controller, EditorStyles.toolbarPopup);\n            }\n            EditorGUILayout.EndHorizontal();\n        }\n\n        void RepaintIfNeeded()\n        {\n            if (m_RepaintCounter > 0)\n            {\n                if (Event.current.type == EventType.Repaint)\n                {\n                    m_RepaintCounter--;\n                    //Debug.Log (\"Repainting (left: \" + m_RepaintCounter + \")\");\n                }\n                Repaint();\n            }\n        }\n\n        public void OnGUI()\n        {\n            Init();\n\n            if (s_GuiContents == null)\n                s_GuiContents = new GUIContents();\n            AudioMixerDrawUtils.InitStyles();\n\n            DetectControllerChange();\n\n            m_GroupViews.OnEvent();\n            m_SnapshotListView.OnEvent();\n\n            DoToolbar();\n\n            List<AudioMixerGroupController> allGroups;\n            if (m_Controller != null)\n                allGroups = m_Controller.GetAllAudioGroupsSlow();\n            else\n                allGroups = new List<AudioMixerGroupController>();\n\n            var effectMap = GetEffectMap(allGroups);\n\n            m_GroupTree.UseScrollView(m_LayoutMode == LayoutMode.Horizontal);\n\n            if (m_LayoutMode == LayoutMode.Horizontal)\n                LayoutWithStripsOnTop(allGroups, effectMap);\n            else\n                LayoutWithStripsOnRightSideOneScrollBar(allGroups, effectMap);\n\n            // Ensure valid layout after maximizing window\n            if (m_LastSize.x != position.width || m_LastSize.y != position.height)\n            {\n                m_RepaintCounter = 2;\n                m_LastSize = new Vector2(position.width, position.height);\n            }\n\n            RepaintIfNeeded();\n        }\n\n        void LayoutWithStripsOnRightSideOneScrollBar(List<AudioMixerGroupController> allGroups, Dictionary<AudioMixerEffectController, AudioMixerGroupController> effectMap)\n        {\n            // Do layouting\n            SplitterState horizontalState = m_LayoutStripsOnRight.m_HorizontalSplitter;\n            SplitterGUILayout.BeginHorizontalSplit(horizontalState, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));\n            SplitterGUILayout.EndHorizontalSplit();\n\n            float column1Width = horizontalState.realSizes[0];\n            float column2Width = position.width - column1Width;\n            Rect column1Rect = new Rect(0, EditorGUI.kWindowToolbarHeight, column1Width, position.height - EditorGUI.kWindowToolbarHeight);\n            Rect column2Rect = new Rect(column1Width, EditorGUI.kWindowToolbarHeight, column2Width, column1Rect.height);\n\n            // Column1\n\n            // Background color for mixertree and views (if needed)\n            if (EditorGUIUtility.isProSkin)\n                EditorGUI.DrawRect(column1Rect, EditorGUIUtility.isProSkin ? new Color(0.19f, 0.19f, 0.19f) : new Color(0.6f, 0.6f, 0.6f, 0f));\n\n            // Rects for sections\n            float spacing = AudioMixerDrawUtils.kSpaceBetweenSections;\n            Rect[] sectionRects = new Rect[m_SectionOrder.Length];\n            const float xPos = 0f;\n            float yPos = 0f;\n            for (int i = 0; i < m_SectionOrder.Length; i++)\n            {\n                yPos += spacing;\n                if (i > 0)\n                    yPos += sectionRects[i - 1].height;\n                sectionRects[i] = new Rect(xPos, yPos, column1Rect.width, GetHeightOfSection(m_SectionOrder[i]));\n\n                // Adjust for left and right margins\n                const float margin = 4f;\n                sectionRects[i].x += margin;\n                sectionRects[i].width -= margin * 2;\n            }\n            Rect contentRect = new Rect(0, 0, 1, sectionRects.Last().yMax);\n\n            // Adjust for scrollbar\n            if (contentRect.height > column1Rect.height)\n            {\n                for (int i = 0; i < sectionRects.Length; i++)\n                    sectionRects[i].width -= 14;\n            }\n\n            // Scroll view\n            m_SectionsScrollPosition = GUI.BeginScrollView(column1Rect, m_SectionsScrollPosition, contentRect);\n            DoSections(column1Rect, sectionRects, m_SectionOrder);\n            GUI.EndScrollView();\n\n            // Column2\n            m_ChannelStripView.OnGUI(column2Rect, m_ShowReferencedBuses, m_ShowBusConnections, m_ShowBusConnectionsOfSelection, allGroups, effectMap, m_SortGroupsAlphabetically, m_ShowDeveloperOverlays, m_GroupTree.ScrollToItem);\n\n            // Vertical line (split)\n            EditorGUI.DrawRect(new Rect(column1Rect.xMax - 1, EditorGUI.kWindowToolbarHeight, 1, position.height - EditorGUI.kWindowToolbarHeight), EditorGUIUtility.isProSkin ? new Color(0.15f, 0.15f, 0.15f) : new Color(0.6f, 0.6f, 0.6f));\n        }\n\n        void LayoutWithStripsOnTop(List<AudioMixerGroupController> allGroups, Dictionary<AudioMixerEffectController, AudioMixerGroupController> effectMap)\n        {\n            // Do layouting\n            SplitterState horizontalState = m_LayoutStripsOnTop.m_HorizontalSplitter;\n            SplitterState verticalState = m_LayoutStripsOnTop.m_VerticalSplitter;\n\n            SplitterGUILayout.BeginVerticalSplit(verticalState, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));\n            if (m_GroupsRenderedAboveSections)\n            {\n                GUILayout.BeginVertical();\n                GUILayout.EndVertical();\n            }\n            SplitterGUILayout.BeginHorizontalSplit(horizontalState, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));\n            if (!m_GroupsRenderedAboveSections)\n            {\n                GUILayout.BeginVertical();\n                GUILayout.EndVertical();\n            }\n            SplitterGUILayout.EndHorizontalSplit();\n            SplitterGUILayout.EndVerticalSplit();\n\n            float channelStripYPos = m_GroupsRenderedAboveSections ? EditorGUI.kWindowToolbarHeight : EditorGUI.kWindowToolbarHeight + verticalState.realSizes[0];\n            float channelStripHeight = m_GroupsRenderedAboveSections ? verticalState.realSizes[0] : verticalState.realSizes[1];\n\n            float sectionsYPos = !m_GroupsRenderedAboveSections ? EditorGUI.kWindowToolbarHeight : EditorGUI.kWindowToolbarHeight + verticalState.realSizes[0];\n            float sectionsHeight = !m_GroupsRenderedAboveSections ? verticalState.realSizes[0] : verticalState.realSizes[1];\n\n            Rect channelStripViewRect = new Rect(0, channelStripYPos, position.width, channelStripHeight);\n            Rect totalRectOfSections = new Rect(0, channelStripViewRect.yMax, position.width, position.height - channelStripViewRect.height);\n\n            // Rects for sections\n            Rect[] sectionRects = new Rect[m_SectionOrder.Length];\n            const float spaceFromBottom = 12f;\n            for (int i = 0; i < sectionRects.Length; i++)\n            {\n                float xPos = (i > 0) ? sectionRects[i - 1].xMax : 0f;\n                sectionRects[i] = new Rect(xPos, sectionsYPos, horizontalState.realSizes[i], sectionsHeight - spaceFromBottom);\n            }\n\n            // Spacing between lists\n            const float halfSpaceBetween = 4f;\n            sectionRects[0].x += 2 * halfSpaceBetween;\n            sectionRects[0].width -= 3 * halfSpaceBetween;\n            sectionRects[sectionRects.Length - 1].x += halfSpaceBetween;\n            sectionRects[sectionRects.Length - 1].width -= 3 * halfSpaceBetween;\n            for (int i = 1; i < sectionRects.Length - 1; i++)\n            {\n                sectionRects[i].x += halfSpaceBetween;\n                sectionRects[i].width -= halfSpaceBetween * 2;\n            }\n\n            // Do content\n            DoSections(totalRectOfSections, sectionRects, m_SectionOrder);\n            m_ChannelStripView.OnGUI(channelStripViewRect, m_ShowReferencedBuses, m_ShowBusConnections, m_ShowBusConnectionsOfSelection, allGroups, effectMap, m_SortGroupsAlphabetically, m_ShowDeveloperOverlays, m_GroupTree.ScrollToItem);\n\n            // Horizontal line (split)\n            EditorGUI.DrawRect(new Rect(0, EditorGUI.kWindowToolbarHeight + verticalState.realSizes[0] - 1, position.width, 1), new Color(0f, 0f, 0f, 0.4f));\n        }\n\n        float GetHeightOfSection(SectionType sectionType)\n        {\n            switch (sectionType)\n            {\n                case SectionType.MixerTree: return m_MixersTree.GetTotalHeight();\n                case SectionType.SnapshotList: return m_SnapshotListView.GetTotalHeight();\n                case SectionType.GroupTree: return m_GroupTree.GetTotalHeight();\n                case SectionType.ViewList: return m_GroupViews.GetTotalHeight();\n                default:\n                    Debug.LogError(\"Unhandled enum value\");\n                    break;\n            }\n            return 0f;\n        }\n\n        void DoSections(Rect totalRectOfSections, Rect[] sectionRects, SectionType[] sectionOrder)\n        {\n            Event evt = Event.current;\n            bool enabledGUI = m_Controller == null || AudioMixerController.EditingTargetSnapshot();\n\n            for (int i = 0; i < sectionOrder.Length; ++i)\n            {\n                Rect sectionRect = sectionRects[i];\n                if (sectionRect.height <= 0.0f)\n                    continue;\n\n                switch (sectionOrder[i])\n                {\n                    case SectionType.MixerTree:\n                        m_MixersTree.OnGUI(sectionRect);\n                        break;\n                    case SectionType.SnapshotList:\n                        using (new EditorGUI.DisabledScope(!enabledGUI))\n                        {\n                            m_SnapshotListView.OnGUI(sectionRect);\n                        }\n                        break;\n                    case SectionType.GroupTree:\n                        m_GroupTree.OnGUI(sectionRect);\n                        break;\n                    case SectionType.ViewList:\n                        m_GroupViews.OnGUI(sectionRect);\n                        break;\n                    default:\n                        Debug.LogError(\"Unhandled enum value\");\n                        break;\n                }\n\n                if (evt.type == EventType.ContextClick)\n                {\n                    Rect sectionHeaderRect = new Rect(sectionRect.x, sectionRect.y, sectionRect.width - 15f, AudioMixerDrawUtils.kSectionHeaderHeight);\n                    if (sectionHeaderRect.Contains(evt.mousePosition))\n                    {\n                        ReorderContextMenu(sectionHeaderRect, i);\n                        evt.Use();\n                    }\n                }\n            }\n        }\n\n        void ReorderContextMenu(Rect rect, int sectionIndex)\n        {\n            Event evt = Event.current;\n            if (Event.current.type == EventType.ContextClick && rect.Contains(evt.mousePosition))\n            {\n                GUIContent moveUp = new GUIContent(m_LayoutMode == LayoutMode.Horizontal ? \"Move Left\" : \"Move Up\");\n                GUIContent moveDown = new GUIContent(m_LayoutMode == LayoutMode.Horizontal ? \"Move Right\" : \"Move Down\");\n\n                GenericMenu menu = new GenericMenu();\n                if (sectionIndex > 1)\n                    menu.AddItem(moveUp, false, ChangeSectionOrder, new Vector2(sectionIndex, -1));\n                else\n                    menu.AddDisabledItem(moveUp);\n                if (sectionIndex > 0 && sectionIndex < m_SectionOrder.Length - 1)\n                    menu.AddItem(moveDown, false, ChangeSectionOrder, new Vector2(sectionIndex, 1));\n                else\n                    menu.AddDisabledItem(moveDown);\n                menu.ShowAsContext();\n            }\n        }\n\n        void ChangeSectionOrder(object userData)\n        {\n            Vector2 sectionIndexAndDirection = (Vector2)userData;\n            int sectionIndex = (int)sectionIndexAndDirection.x;\n            int direction = (int)sectionIndexAndDirection.y;\n            int newSectionIndex = Mathf.Clamp(sectionIndex + direction, 0, m_SectionOrder.Length - 1);\n            if (newSectionIndex != sectionIndex)\n            {\n                SectionType tmp = m_SectionOrder[sectionIndex];\n                m_SectionOrder[sectionIndex] = m_SectionOrder[newSectionIndex];\n                m_SectionOrder[newSectionIndex] = tmp;\n            }\n        }\n\n        public MixerParameterDefinition ParamDef(string name, string desc, string units, float displayScale, float minRange, float maxRange, float defaultValue)\n        {\n            MixerParameterDefinition paramDef = new MixerParameterDefinition();\n            paramDef.name = name;\n            paramDef.description = desc;\n            paramDef.units = units;\n            paramDef.displayScale = displayScale;\n            paramDef.minRange = minRange;\n            paramDef.maxRange = maxRange;\n            paramDef.defaultValue = defaultValue;\n            return paramDef;\n        }\n\n        // Add items to the context menu for the AudioMixerWindow (the tree horizontal lines, upper right corner)\n        public virtual void AddItemsToMenu(GenericMenu menu)\n        {\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Sort groups alphabetically\"), m_SortGroupsAlphabetically, delegate { m_SortGroupsAlphabetically = !m_SortGroupsAlphabetically; });\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Show referenced groups\"), m_ShowReferencedBuses, delegate { m_ShowReferencedBuses = !m_ShowReferencedBuses; });\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Show group connections\"), m_ShowBusConnections, delegate { m_ShowBusConnections = !m_ShowBusConnections; });\n            if (m_ShowBusConnections)\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Only highlight selected group connections\"), m_ShowBusConnectionsOfSelection, delegate { m_ShowBusConnectionsOfSelection = !m_ShowBusConnectionsOfSelection; });\n            menu.AddSeparator(\"\");\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Vertical layout\"), layoutMode == LayoutMode.Vertical, delegate { layoutMode = LayoutMode.Vertical; });\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Horizontal layout\"), layoutMode == LayoutMode.Horizontal, delegate { layoutMode = LayoutMode.Horizontal; });\n            menu.AddSeparator(\"\");\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Use RMS metering for display\"), EditorPrefs.GetBool(kAudioMixerUseRMSMetering, true), delegate { EditorPrefs.SetBool(kAudioMixerUseRMSMetering, true); });\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Use peak metering for display\"), !EditorPrefs.GetBool(kAudioMixerUseRMSMetering, true), delegate { EditorPrefs.SetBool(kAudioMixerUseRMSMetering, false); });\n            if (Unsupported.IsDeveloperMode())\n            {\n                menu.AddSeparator(\"\");\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"DEVELOPER/Groups Rendered Above\"), m_GroupsRenderedAboveSections, delegate { m_GroupsRenderedAboveSections = !m_GroupsRenderedAboveSections; });\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"DEVELOPER/Build 10 groups\"), false, delegate { m_Controller.BuildTestSetup(0, 7, 10); });\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"DEVELOPER/Build 20 groups\"), false, delegate { m_Controller.BuildTestSetup(0, 7, 20); });\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"DEVELOPER/Build 40 groups\"), false, delegate { m_Controller.BuildTestSetup(0, 7, 40); });\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"DEVELOPER/Build 80 groups\"), false, delegate { m_Controller.BuildTestSetup(0, 7, 80); });\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"DEVELOPER/Build 160 groups\"), false, delegate { m_Controller.BuildTestSetup(0, 7, 160); });\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"DEVELOPER/Build chain of 10 groups\"), false, delegate { m_Controller.BuildTestSetup(1, 1, 10); });\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"DEVELOPER/Build chain of 20 groups \"), false, delegate { m_Controller.BuildTestSetup(1, 1, 20); });\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"DEVELOPER/Build chain of 40 groups\"), false, delegate { m_Controller.BuildTestSetup(1, 1, 40); });\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"DEVELOPER/Build chain of 80 groups\"), false, delegate { m_Controller.BuildTestSetup(1, 1, 80); });\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"DEVELOPER/Show overlays\"), m_ShowDeveloperOverlays, delegate { m_ShowDeveloperOverlays = !m_ShowDeveloperOverlays; });\n            }\n        }\n    }\n\n    internal class AssetSelectionPopupMenu\n    {\n        static public void Show(Rect buttonRect, string[] classNames, int initialSelectedInstanceID)\n        {\n            var menu = new GenericMenu();\n\n            var objs = AssetDatabase.FindAllAssets(new SearchFilter() { classNames = classNames }).Select(property => property.pptrValue).ToList();\n            if (objs.Any())\n            {\n                objs.Sort((result1, result2) => EditorUtility.NaturalCompare(result1.name, result2.name));\n                foreach (var obj in objs)\n                {\n                    var assetName = new GUIContent(obj.name);\n                    bool selected = obj.GetInstanceID() == initialSelectedInstanceID;\n                    menu.AddItem(assetName, selected, SelectCallback, obj);\n                }\n            }\n            else\n            {\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"No Audio Mixers found in this project\"));\n            }\n            menu.DropDown(buttonRect);\n        }\n\n        static void SelectCallback(object userData)\n        {\n            UnityEngine.Object obj = userData as UnityEngine.Object;\n            if (obj != null)\n                Selection.activeInstanceID = obj.GetInstanceID();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/AudioMixersTreeView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.IO;\nusing UnityEditor.ProjectWindowCallback;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System;\nusing UnityEditor.Audio;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine.Audio;\nusing Object = UnityEngine.Object;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewUtility = UnityEditor.IMGUI.Controls.TreeViewUtility<int>;\nusing TreeViewGUI = UnityEditor.IMGUI.Controls.TreeViewGUI<int>;\nusing TreeViewDragging = UnityEditor.IMGUI.Controls.TreeViewDragging<int>;\nusing TreeViewDataSource = UnityEditor.IMGUI.Controls.TreeViewDataSource<int>;\nusing TreeViewItemAlphaNumericSort = UnityEditor.IMGUI.Controls.TreeViewItemAlphaNumericSort<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    // Item\n\n    internal class AudioMixerItem : TreeViewItem\n    {\n        public AudioMixerController mixer { get; set; }\n        public string infoText { get; set; }\n        public float labelWidth { get; set; }\n        bool lastSuspendedState { get; set; }\n        const string kSuspendedText = \" - Inactive\";\n\n        public AudioMixerItem(int id, int depth, TreeViewItem parent, string displayName, AudioMixerController mixer, string infoText)\n            : base(id, depth, parent, displayName)\n        {\n            this.mixer = mixer;\n            this.infoText = infoText;\n            UpdateSuspendedString(true);\n        }\n\n        public void UpdateSuspendedString(bool force)\n        {\n            bool isSuspended = mixer.isSuspended;\n            if (lastSuspendedState != isSuspended || force)\n            {\n                lastSuspendedState = isSuspended;\n\n                if (isSuspended)\n                    AddSuspendedText();\n                else\n                    RemoveSuspendedText();\n            }\n        }\n\n        void RemoveSuspendedText()\n        {\n            int index = infoText.IndexOf(kSuspendedText, StringComparison.Ordinal);\n            if (index >= 0)\n                infoText = infoText.Remove(index, kSuspendedText.Length);\n        }\n\n        void AddSuspendedText()\n        {\n            int index = infoText.IndexOf(kSuspendedText, StringComparison.Ordinal);\n            if (index < 0)\n                infoText += kSuspendedText;\n        }\n    }\n\n\n    // Dragging\n\n    internal class AudioMixerTreeViewDragging : TreeViewDragging\n    {\n        private const string k_AudioMixerDraggingID = \"AudioMixerDragging\";\n        Action<List<AudioMixerController>, AudioMixerController> m_MixersDroppedOnMixerCallback;\n\n        class DragData\n        {\n            public DragData(List<AudioMixerItem> draggedItems)\n            {\n                m_DraggedItems = draggedItems;\n            }\n\n            public List<AudioMixerItem> m_DraggedItems;\n        }\n\n        public AudioMixerTreeViewDragging(TreeViewController treeView, Action<List<AudioMixerController>, AudioMixerController> mixerDroppedOnMixerCallback)\n            : base(treeView)\n        {\n            m_MixersDroppedOnMixerCallback = mixerDroppedOnMixerCallback;\n        }\n\n        public override void StartDrag(TreeViewItem draggedNode, List<int> draggedNodes)\n        {\n            // We do not allow changing routing in playmode for now\n            if (EditorApplication.isPlaying)\n                return;\n\n            List<AudioMixerItem> draggedItems = GetAudioMixerItemsFromIDs(draggedNodes);\n\n            DragAndDrop.PrepareStartDrag();\n            DragAndDrop.SetGenericData(k_AudioMixerDraggingID, new DragData(draggedItems));\n            string title = draggedNodes.Count + \" AudioMixer\" + (draggedNodes.Count > 1 ? \"s\" : \"\"); // title is only shown on OSX (at the cursor)\n            DragAndDrop.StartDrag(title);\n        }\n\n        public override bool DragElement(TreeViewItem targetItem, Rect targetItemRect, int row)\n        {\n            // First ensure we are dragging AudioMixers (and not some other objects)\n            var dragData = DragAndDrop.GetGenericData(k_AudioMixerDraggingID) as DragData;\n            if (dragData == null)\n            {\n                DragAndDrop.visualMode = DragAndDropVisualMode.None;\n                return false;\n            }\n\n            // Handle the case where we hover inside the treeview rect but not over any items\n            bool isDraggingOverEmptyArea = targetItem == null;\n            if (isDraggingOverEmptyArea && m_TreeView.GetTotalRect().Contains(Event.current.mousePosition))\n            {\n                if (m_DropData != null)\n                {\n                    // Ensure no rendering of target items\n                    m_DropData.ClearPerEventState();\n                }\n\n                if (Event.current.type == EventType.DragPerform)\n                {\n                    DragAndDrop.AcceptDrag();\n                    if (m_MixersDroppedOnMixerCallback != null)\n                        m_MixersDroppedOnMixerCallback(GetAudioMixersFromItems(dragData.m_DraggedItems), null);\n                }\n                DragAndDrop.visualMode = DragAndDropVisualMode.Move;\n                Event.current.Use();\n                return false;\n            }\n\n            // Normal handling when over dragging over items\n            return base.DragElement(targetItem, targetItemRect, row);\n        }\n\n        public override DragAndDropVisualMode DoDrag(TreeViewItem parentNode, TreeViewItem targetNode, bool perform, DropPosition dragPos)\n        {\n            var dragData = DragAndDrop.GetGenericData(k_AudioMixerDraggingID) as DragData;\n            if (dragData == null)\n                return DragAndDropVisualMode.None;\n\n            var draggedItems = dragData.m_DraggedItems;\n            var parentMixerItem = parentNode as AudioMixerItem;\n            if (parentMixerItem != null && dragData != null)\n            {\n                List<AudioMixerGroupController> draggedMasterGroups = (from i in draggedItems select i.mixer.masterGroup).ToList();\n                var allGroups = parentMixerItem.mixer.GetAllAudioGroupsSlow();\n                bool causesFeedback = AudioMixerController.WillModificationOfTopologyCauseFeedback(allGroups, draggedMasterGroups, parentMixerItem.mixer.masterGroup, null);\n                bool validDrag = ValidDrag(parentNode, draggedItems) && !causesFeedback;\n                if (perform && validDrag)\n                {\n                    if (m_MixersDroppedOnMixerCallback != null)\n                        m_MixersDroppedOnMixerCallback(GetAudioMixersFromItems(draggedItems), parentMixerItem.mixer);\n                }\n                return validDrag ? DragAndDropVisualMode.Move : DragAndDropVisualMode.Rejected;\n            }\n            return DragAndDropVisualMode.None;\n        }\n\n        bool ValidDrag(TreeViewItem parent, List<AudioMixerItem> draggedItems)\n        {\n            List<int> draggedIDs = (from n in draggedItems select n.id).ToList();\n\n            TreeViewItem currentParent = parent;\n            while (currentParent != null)\n            {\n                if (draggedIDs.Contains(currentParent.id))\n                    return false;\n                currentParent = currentParent.parent;\n            }\n            return true;\n        }\n\n        private List<AudioMixerItem> GetAudioMixerItemsFromIDs(List<int> draggedMixers)\n        {\n            var found = TreeViewUtility.FindItemsInList(draggedMixers, m_TreeView.data.GetRows());\n            return found.OfType<AudioMixerItem>().ToList();\n        }\n\n        private List<AudioMixerController> GetAudioMixersFromItems(List<AudioMixerItem> draggedItems)\n        {\n            return (from i in draggedItems select i.mixer).ToList();\n        }\n    }\n\n\n    // Datasource\n\n    internal class AudioMixersDataSource : TreeViewDataSource\n    {\n        Func<List<AudioMixerController>> m_GetAllControllersCallback;\n\n        public AudioMixersDataSource(TreeViewController treeView, Func<List<AudioMixerController>> getAllControllersCallback)\n            : base(treeView)\n        {\n            showRootItem = false;\n            m_GetAllControllersCallback = getAllControllersCallback;\n        }\n\n        public override void FetchData()\n        {\n            int depth = -1;\n            bool expandAll = m_TreeView.state.expandedIDs.Count == 0; // State is persisted so only do this once per new AudioMixerWindow\n\n            m_RootItem = new TreeViewItem(1010101010, depth, null, \"InvisibleRoot\");\n            SetExpanded(m_RootItem.id, true);\n\n            List<AudioMixerController> m_Mixers = m_GetAllControllersCallback();\n\n            m_NeedRefreshRows = true;\n            if (m_Mixers.Count > 0)\n            {\n                // First create a tree view item for each controller\n                var roots = m_Mixers.Select(mixer => new AudioMixerItem(mixer.GetInstanceID(), 0, m_RootItem, mixer.name, mixer, GetInfoText(mixer))).ToList();\n\n                // Rearrange items to a tree based on output mixer group\n                foreach (var item in roots)\n                {\n                    SetChildParentOfMixerItem(item, roots);\n                }\n\n                SetItemDepthRecursive(m_RootItem, -1);  // -1 because the root item is hidden\n                SortRecursive(m_RootItem);\n\n                if (expandAll)\n                    m_TreeView.data.SetExpandedWithChildren(m_RootItem, true);\n            }\n        }\n\n        static string GetInfoText(AudioMixerController controller)\n        {\n            string s;\n            if (controller.outputAudioMixerGroup != null)\n                s = string.Format(\"({0} of {1})\",  controller.outputAudioMixerGroup.name, controller.outputAudioMixerGroup.audioMixer.name);\n            else\n                s = \"(Audio Listener)\";\n            return s;\n        }\n\n        void SetChildParentOfMixerItem(AudioMixerItem item, List<AudioMixerItem> items)\n        {\n            if (item.mixer.outputAudioMixerGroup != null)\n            {\n                var parentMixer = item.mixer.outputAudioMixerGroup.audioMixer;\n                var parentItem = TreeViewUtility.FindItemInList(parentMixer.GetInstanceID(), items) as AudioMixerItem;\n                if (parentItem != null)\n                {\n                    parentItem.AddChild(item);\n                }\n            }\n            else\n            {\n                m_RootItem.AddChild(item);\n            }\n        }\n\n        void SetItemDepthRecursive(TreeViewItem item, int depth)\n        {\n            item.depth = depth;\n            if (!item.hasChildren)\n                return;\n\n            foreach (var child in item.children)\n                SetItemDepthRecursive(child, depth + 1);\n        }\n\n        void SortRecursive(TreeViewItem item)\n        {\n            if (!item.hasChildren)\n                return;\n            item.children.Sort(new TreeViewItemAlphaNumericSort());\n\n            foreach (var child in item.children)\n                SortRecursive(child);\n        }\n\n        public override bool IsRenamingItemAllowed(TreeViewItem item)\n        {\n            return true;\n        }\n\n        public int GetInsertAfterItemIDForNewItem(string newName, TreeViewItem parentItem)\n        {\n            // Find pos under parent\n            int insertAfterID = parentItem.id;\n\n            if (!parentItem.hasChildren)\n                return insertAfterID;\n\n            for (int idx = 0; idx < parentItem.children.Count; ++idx)\n            {\n                int instanceID = parentItem.children[idx].id;\n\n                // Use same name compare as when we sort in the backend: See AssetDatabase.cpp: SortChildren\n                string propertyPath = AssetDatabase.GetAssetPath(instanceID);\n                if (EditorUtility.NaturalCompare(Path.GetFileNameWithoutExtension(propertyPath), newName) > 0)\n                    break;\n\n                insertAfterID = instanceID;\n            }\n            return insertAfterID;\n        }\n\n        override public void InsertFakeItem(int id, int parentID, string name, Texture2D icon)\n        {\n            TreeViewItem checkItem = FindItem(id);\n            if (checkItem != null)\n            {\n                Debug.LogError(\"Cannot insert fake Item because id is not unique \" + id + \" Item already there: \" + checkItem.displayName);\n                return;\n            }\n\n            if (FindItem(parentID) != null)\n            {\n                // Ensure parent Item's children is visible\n                SetExpanded(parentID, true);\n\n                var visibleRows = GetRows();\n\n                TreeViewItem parentItem;\n                int parentIndex = TreeViewController.GetIndexOfID(visibleRows, parentID);\n                if (parentIndex >= 0)\n                    parentItem = visibleRows[parentIndex];\n                else\n                    parentItem = m_RootItem; // Fallback to root Item as parent\n\n                // Create fake item for insertion\n                int indentLevel = parentItem.depth + 1;\n                m_FakeItem = new TreeViewItem(id, indentLevel, parentItem, name);\n                m_FakeItem.icon = icon;\n\n                // Find pos under parent\n                int insertAfterID = GetInsertAfterItemIDForNewItem(name, parentItem);\n\n                // Find pos in expanded rows and insert\n                int index = TreeViewController.GetIndexOfID(visibleRows, insertAfterID);\n                if (index >= 0)\n                {\n                    // Ensure to bypass all children of 'insertAfterID'\n                    while (++index < visibleRows.Count)\n                    {\n                        if (visibleRows[index].depth <= indentLevel)\n                            break;\n                    }\n\n                    if (index < visibleRows.Count)\n                        visibleRows.Insert(index, m_FakeItem);\n                    else\n                        visibleRows.Add(m_FakeItem);\n                }\n                else\n                {\n                    // not visible parent: insert as first\n                    if (visibleRows.Count > 0)\n                        visibleRows.Insert(0, m_FakeItem);\n                    else\n                        visibleRows.Add(m_FakeItem);\n                }\n\n                m_NeedRefreshRows = false;\n\n                m_TreeView.Frame(m_FakeItem.id, true, false);\n                m_TreeView.Repaint();\n            }\n            else\n            {\n                Debug.LogError(\"No parent Item found with ID: \" + parentID);\n            }\n        }\n    }\n\n    // Item GUI\n\n    internal class AudioMixersTreeViewGUI : TreeViewGUI\n    {\n        public AudioMixersTreeViewGUI(TreeViewController treeView)\n            : base(treeView)\n        {\n            k_IconWidth = 0;\n            k_TopRowMargin = k_BottomRowMargin = 2f;\n        }\n\n        protected override void OnContentGUI(Rect rect, int row, TreeViewItem item, string label, bool selected, bool focused, bool useBoldFont, bool isPinging)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            if (!isPinging)\n            {\n                // The rect is assumed indented and sized after the content when pinging\n                float indent = GetContentIndent(item);\n                rect.x += indent;\n                rect.width -= indent;\n            }\n\n            AudioMixerItem mixerItem = item as AudioMixerItem;\n            if (mixerItem == null)\n                return;\n\n            lineStyle = useBoldFont ? Styles.lineBoldStyle : Styles.lineStyle;\n\n            // Draw text\n            lineStyle.padding.left = (int)(k_IconWidth + iconTotalPadding + k_SpaceBetweenIconAndText);\n            lineStyle.Draw(rect, label, false, false, selected, focused);\n\n            // Draw info text\n            mixerItem.UpdateSuspendedString(false);\n            const float minSpaceBetween = 8f;\n            if (mixerItem.labelWidth <= 0)\n                mixerItem.labelWidth = lineStyle.CalcSize(GUIContent.Temp(label)).x;   // only calc once\n            Rect infoRect = rect;\n            infoRect.x += mixerItem.labelWidth + minSpaceBetween;\n            using (new EditorGUI.DisabledScope(true))\n            {\n                lineStyle.Draw(infoRect, mixerItem.infoText, false, false, false, false);\n            }\n\n            // TODO Icon overlay (RCS)\n            if (iconOverlayGUI != null)\n            {\n                Rect iconOverlayRect = rect;\n                iconOverlayRect.width = k_IconWidth + iconTotalPadding;\n                iconOverlayGUI(item, iconOverlayRect);\n            }\n        }\n\n        protected override Texture GetIconForItem(TreeViewItem node)\n        {\n            return null; // We do not want any icons\n        }\n\n        protected CreateAssetUtility GetCreateAssetUtility()\n        {\n            return ((TreeViewStateWithAssetUtility)m_TreeView.state).createAssetUtility;\n        }\n\n        protected override void RenameEnded()\n        {\n            string name = string.IsNullOrEmpty(GetRenameOverlay().name) ? GetRenameOverlay().originalName : GetRenameOverlay().name;\n            int instanceID = GetRenameOverlay().userData;\n            bool isCreating = GetCreateAssetUtility().IsCreatingNewAsset();\n            bool userAccepted = GetRenameOverlay().userAcceptedRename;\n\n            if (userAccepted)\n            {\n                if (isCreating)\n                {\n                    // Create a new asset\n                    GetCreateAssetUtility().EndNewAssetCreation(name);\n                    m_TreeView.ReloadData();\n                }\n                else\n                {\n                    // Rename an existing asset\n                    ObjectNames.SetNameSmartWithInstanceID(instanceID, name);\n                }\n            }\n            else if (isCreating)\n                GetCreateAssetUtility().EndNewAssetCreationCanceled(name);\n        }\n\n        override protected void ClearRenameAndNewItemState()\n        {\n            GetCreateAssetUtility().Clear();\n            base.ClearRenameAndNewItemState();\n        }\n\n        AudioMixerItem GetSelectedItem()\n        {\n            return m_TreeView.FindItem(m_TreeView.GetSelection().FirstOrDefault()) as AudioMixerItem;\n        }\n\n        override protected void SyncFakeItem()\n        {\n            if (!m_TreeView.data.HasFakeItem() && GetCreateAssetUtility().IsCreatingNewAsset())\n            {\n                // Get selection from tree\n                int parentInstanceID = m_TreeView.data.root.id;\n                var selectedItem = GetSelectedItem();\n                if (selectedItem != null)\n                    parentInstanceID = selectedItem.parent.id;\n                m_TreeView.data.InsertFakeItem(GetCreateAssetUtility().instanceID, parentInstanceID, GetCreateAssetUtility().originalName, GetCreateAssetUtility().icon);\n            }\n\n            if (m_TreeView.data.HasFakeItem() && !GetCreateAssetUtility().IsCreatingNewAsset())\n            {\n                m_TreeView.data.RemoveFakeItem();\n            }\n        }\n\n        public void BeginCreateNewMixer()\n        {\n            //int instanceID, EndNameEditAction endAction, string pathName, Texture2D icon, string resourceFile\n            ClearRenameAndNewItemState();\n\n            // Use resouce file to store instanceID for output group so we can use that for the newly created audiomixer\n            string resourceFileData = string.Empty;\n            var selectedItem = GetSelectedItem();\n            if (selectedItem != null && selectedItem.mixer.outputAudioMixerGroup != null)\n                resourceFileData = selectedItem.mixer.outputAudioMixerGroup.GetInstanceID().ToString();\n\n            int instanceID = 0;\n\n            if (GetCreateAssetUtility().BeginNewAssetCreation(\n                instanceID, ScriptableObject.CreateInstance<DoCreateAudioMixer>(), \"NewAudioMixer.mixer\", null, resourceFileData))\n            {\n                SyncFakeItem();\n\n                // Start naming the asset\n                bool renameStarted = GetRenameOverlay().BeginRename(GetCreateAssetUtility().originalName, instanceID, 0f);\n                if (!renameStarted)\n                    Debug.LogError(\"Rename not started (when creating new asset)\");\n            }\n        }\n    }\n\n\n    // TreeView\n\n    internal class AudioMixersTreeView\n    {\n        private TreeViewController m_TreeView;\n        const int kObjectSelectorID = 1212;\n        List<AudioMixerController> m_DraggedMixers;\n\n        class Styles\n        {\n            public GUIContent header = EditorGUIUtility.TrTextContent(\"Mixers\", \"All mixers in the project are shown here. By default, a mixer outputs to the AudioListener but mixers can also route their output to other mixers. Each mixer shows where it outputs (in parenthesis). To reroute a mixer simply drag the mixer upon another mixer and select a group from the popup.\");\n            public GUIContent addButton = EditorGUIUtility.TrIconContent(\"CreateAddNew\", \"Add mixer asset. The asset will be saved in the same folder as the current selected mixer or, if none is selected, saved in the Assets folder.\");\n            public Texture2D audioMixerIcon = EditorGUIUtility.FindTexture(typeof(AudioMixerController));\n        }\n        static Styles s_Styles;\n\n        public AudioMixersTreeView(AudioMixerWindow mixerWindow, TreeViewState treeState, Func<List<AudioMixerController>> getAllControllersCallback)\n        {\n            m_TreeView = new TreeViewController(mixerWindow, treeState);\n            m_TreeView.deselectOnUnhandledMouseDown = false;\n            m_TreeView.selectionChangedCallback += OnTreeSelectionChanged;\n            m_TreeView.contextClickItemCallback += OnTreeViewContextClick;\n\n            var treeViewGUI = new AudioMixersTreeViewGUI(m_TreeView);\n            var treeViewDataSource = new AudioMixersDataSource(m_TreeView, getAllControllersCallback);\n            var treeViewDragging = new AudioMixerTreeViewDragging(m_TreeView, OnMixersDroppedOnMixerCallback);\n            m_TreeView.Init(mixerWindow.position, treeViewDataSource, treeViewGUI, treeViewDragging);\n            m_TreeView.ReloadData();\n        }\n\n        public void ReloadTree()\n        {\n            m_TreeView.ReloadData();\n            m_TreeView.Repaint();\n        }\n\n        public void OnMixerControllerChanged(AudioMixerController controller)\n        {\n            if (controller != null)\n                m_TreeView.SetSelection(new int[] {controller.GetInstanceID()}, true);\n        }\n\n        public void DeleteAudioMixerCallback(object obj)\n        {\n            AudioMixerController controller = (AudioMixerController)obj;\n            if (controller != null)\n            {\n                ProjectWindowUtil.DeleteAssets(new[] { controller.GetInstanceID() }.ToList(), true);\n            }\n        }\n\n        public void OnTreeViewContextClick(int index)\n        {\n            AudioMixerItem node = (AudioMixerItem)m_TreeView.FindItem(index);\n            if (node != null)\n            {\n                GenericMenu pm = new GenericMenu();\n                pm.AddItem(EditorGUIUtility.TrTextContent(\"Delete AudioMixer\"), false, DeleteAudioMixerCallback, node.mixer);\n                pm.ShowAsContext();\n            }\n        }\n\n        public void OnTreeSelectionChanged(int[] selection)\n        {\n            Selection.instanceIDs = selection;\n        }\n\n        public float GetTotalHeight()\n        {\n            const float minHeight = 20f;\n            return AudioMixerDrawUtils.kSectionHeaderHeight + Mathf.Max(minHeight, m_TreeView.gui.GetTotalSize().y);\n        }\n\n        public void OnGUI(Rect rect)\n        {\n            int treeViewKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard);\n\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            m_TreeView.OnEvent();\n\n            Rect headerRect, contentRect;\n            AudioMixerDrawUtils.DrawRegionBg(rect, out headerRect, out contentRect);\n            AudioMixerDrawUtils.HeaderLabel(headerRect, s_Styles.header, s_Styles.audioMixerIcon);\n\n            if (GUI.Button(new Rect(headerRect.xMax - 17f, headerRect.y + 3f, 16f, 16f), s_Styles.addButton, EditorStyles.iconButton))\n            {\n                AudioMixersTreeViewGUI gui = m_TreeView.gui as AudioMixersTreeViewGUI;\n                gui.BeginCreateNewMixer();\n            }\n\n            m_TreeView.OnGUI(contentRect, treeViewKeyboardControlID);\n\n            if (m_TreeView.data.rowCount == 0)\n            {\n                using (new EditorGUI.DisabledScope(true))\n                {\n                    GUI.Label(new RectOffset(-20, 0, -2, 0).Add(contentRect), \"No mixers found\");\n                }\n            }\n\n            AudioMixerDrawUtils.DrawScrollDropShadow(contentRect, m_TreeView.state.scrollPos.y, m_TreeView.gui.GetTotalSize().y);\n\n            HandleCommandEvents(treeViewKeyboardControlID);\n            HandleObjectSelectorResult();\n        }\n\n        void HandleCommandEvents(int treeViewKeyboardControlID)\n        {\n            if (GUIUtility.keyboardControl != treeViewKeyboardControlID)\n                return;\n\n            EventType eventType = Event.current.type;\n            if (eventType == EventType.ExecuteCommand || eventType == EventType.ValidateCommand)\n            {\n                bool execute = eventType == EventType.ExecuteCommand;\n\n                if (Event.current.commandName == EventCommandNames.Delete || Event.current.commandName == EventCommandNames.SoftDelete)\n                {\n                    Event.current.Use();\n                    if (execute)\n                        ProjectWindowUtil.DeleteAssets(m_TreeView.GetSelection().ToList(), true);\n                }\n                else if (Event.current.commandName == EventCommandNames.Duplicate)\n                {\n                    Event.current.Use();\n                    if (execute)\n                        AssetClipboardUtility.DuplicateAssets(m_TreeView.GetSelection());\n                }\n            }\n        }\n\n        const string kExpandedStateIdentifier = \"AudioMixerWindowMixers\";\n\n        public void EndRenaming()\n        {\n            m_TreeView.EndNameEditing(true);\n        }\n\n        public void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            ReloadTree();\n        }\n\n        void OnMixersDroppedOnMixerCallback(List<AudioMixerController> draggedMixers, AudioMixerController droppedUponMixer)\n        {\n            // Set Unity selection when drag ended (when dragging non selected items we just render them as selected while dragging)\n            int[] draggedIDs = (from i in draggedMixers select i.GetInstanceID()).ToArray();\n            m_TreeView.SetSelection(draggedIDs, true);\n            Selection.instanceIDs = draggedIDs;\n\n            if (droppedUponMixer == null)\n            {\n                // Dragged to the root -> clear all outputgroups\n                Undo.RecordObjects(draggedMixers.ToArray(), \"Set output group for mixer\" + (draggedMixers.Count > 1 ? \"s\" : \"\"));\n                foreach (var mixer in draggedMixers)\n                    mixer.outputAudioMixerGroup = null;\n                ReloadTree();\n            }\n            else\n            {\n                // Show Object Selector for output group selection\n                m_DraggedMixers = draggedMixers;\n                Object startSelection = draggedMixers.Count == 1 ? draggedMixers[0].outputAudioMixerGroup : null;\n                ObjectSelector.get.Show(startSelection, typeof(AudioMixerGroup), null, false, new List<int>() { droppedUponMixer.GetInstanceID() });\n                ObjectSelector.get.objectSelectorID = kObjectSelectorID;\n                ObjectSelector.get.titleContent = EditorGUIUtility.TrTextContent(\"Select Output Audio Mixer Group\");\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        void HandleObjectSelectorResult()\n        {\n            Event evt = Event.current;\n            if (evt.type == EventType.ExecuteCommand)\n            {\n                string commandName = evt.commandName;\n                if (commandName == ObjectSelector.ObjectSelectorUpdatedCommand && ObjectSelector.get.objectSelectorID == kObjectSelectorID)\n                {\n                    if (m_DraggedMixers == null || m_DraggedMixers.Count == 0)\n                        Debug.LogError(\"Unexpected invalid mixer list used for dragging\");\n\n                    var selected =  ObjectSelector.GetCurrentObject();\n                    AudioMixerGroup selectedGroup = selected != null ? selected as AudioMixerGroup : null;\n                    Undo.RecordObjects(m_DraggedMixers.ToArray(), \"Set output group for mixer\" + (m_DraggedMixers.Count > 1 ? \"s\" : \"\"));\n                    foreach (var mixer in m_DraggedMixers)\n                    {\n                        if (mixer != null)\n                            mixer.outputAudioMixerGroup = selectedGroup;\n                        else\n                            Debug.LogError(\"invalid mixer: is null\");\n                    }\n\n                    GUI.changed = true;\n                    evt.Use();\n\n                    ReloadTree();\n\n                    // Ensure newly selected output group is revealed\n                    int[] selectedIDs = (from i in m_DraggedMixers select i.GetInstanceID()).ToArray();\n                    m_TreeView.SetSelection(selectedIDs, true);\n                }\n\n                if (commandName == ObjectSelector.ObjectSelectorClosedCommand)\n                {\n                    m_DraggedMixers = null;  // cleanup stored state\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/ReorderableListWithRenameAndScrollView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System;\nusing RenameOverlay = UnityEditor.RenameOverlay<int>;\n\nnamespace UnityEditorInternal\n{\n    internal class ReorderableListWithRenameAndScrollView\n    {\n        [Serializable]\n        public class State\n        {\n            public Vector2 m_ScrollPos = new Vector2(0, 0);\n            public RenameOverlay m_RenameOverlay = new RenameOverlay();\n        }\n\n        ReorderableList m_ReorderableList;\n        State m_State;\n        int m_LastSelectedIndex = -1;\n        bool m_HadKeyFocusAtMouseDown = false;\n        int m_FrameIndex = -1;\n\n        public GUIStyle listElementStyle = null; // if null then a default style is used\n        public GUIStyle renameOverlayStyle = null;  // if null then the default rename style is used\n        public Func<int, string> onGetNameAtIndex; // rect, index, selected\n        public Action<int, string> onNameChangedAtIndex; // index, new name\n        public Action<int> onSelectionChanged;\n        public Action<int> onDeleteItemAtIndex;\n        public ReorderableList.ElementCallbackDelegate onCustomDrawElement;\n        public ReorderableList list { get { return m_ReorderableList; } }\n\n        public class Styles\n        {\n            public GUIStyle reorderableListLabel = \"ReorderableList\";\n            public GUIStyle reorderableListLabelRightAligned = \"ReorderableListRightAligned\";\n        }\n        static Styles s_Styles;\n\n        public GUIStyle elementStyle\n        {\n            get { return listElementStyle ?? s_Styles.reorderableListLabel; }\n        }\n\n        public GUIStyle elementStyleRightAligned\n        {\n            get { return s_Styles.reorderableListLabelRightAligned; }\n        }\n\n        public ReorderableListWithRenameAndScrollView(ReorderableList list, State state)\n        {\n            m_State = state;\n\n            m_ReorderableList = list;\n\n            // Add common handling for the following delegates\n            m_ReorderableList.drawElementCallback += DrawElement;\n            m_ReorderableList.onSelectCallback += SelectCallback;\n            m_ReorderableList.onMouseUpCallback += MouseUpCallback;\n            m_ReorderableList.onReorderCallback += ReorderCallback;\n        }\n\n        RenameOverlay GetRenameOverlay()\n        {\n            return m_State.m_RenameOverlay;\n        }\n\n        public void OnEvent()\n        {\n            GetRenameOverlay().OnEvent();\n        }\n\n        void EnsureRowIsVisible(int index, float scrollGUIHeight)\n        {\n            if (index < 0)\n                return;\n\n            float topPixelOfRow = m_ReorderableList.elementHeight * index + 2;\n            float scrollBottom = topPixelOfRow - scrollGUIHeight + m_ReorderableList.elementHeight + 3;\n            m_State.m_ScrollPos.y = Mathf.Clamp(m_State.m_ScrollPos.y, scrollBottom, topPixelOfRow);\n        }\n\n        public void OnGUI(Rect rect)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            //Event evt = Event.current;\n\n            if (onGetNameAtIndex == null)\n                Debug.LogError(\"Ensure to set: 'onGetNameAtIndex'\");\n\n            Event evt = Event.current;\n\n            if (evt.type == EventType.MouseDown && rect.Contains(evt.mousePosition))\n                m_HadKeyFocusAtMouseDown = m_ReorderableList.HasKeyboardControl();\n\n            if (m_FrameIndex != -1)\n            {\n                EnsureRowIsVisible(m_FrameIndex, rect.height);\n                m_FrameIndex = -1;\n            }\n\n            GUILayout.BeginArea(rect);\n            m_State.m_ScrollPos = GUILayout.BeginScrollView(m_State.m_ScrollPos);\n\n            m_ReorderableList.DoLayoutList();\n\n            GUILayout.EndScrollView();\n            GUILayout.EndArea();\n            AudioMixerDrawUtils.DrawScrollDropShadow(rect, m_State.m_ScrollPos.y, m_ReorderableList.GetHeight());\n\n            KeyboardHandling();\n            CommandHandling();\n        }\n\n        public bool IsRenamingIndex(int index)\n        {\n            return GetRenameOverlay().IsRenaming() && GetRenameOverlay().userData == index && !GetRenameOverlay().isWaitingForDelay;\n        }\n\n        public void DrawElement(Rect r, int index, bool isActive, bool isFocused)\n        {\n            if (IsRenamingIndex(index))\n            {\n                // We do not want to set rect when they can be invalid, this can happen for layout or used events\n                if (r.width >= 0f && r.height >= 0f)\n                {\n                    r.x -= 2; // Fit rename field text perfect with label\n                    GetRenameOverlay().editFieldRect = r;\n                }\n                DoRenameOverlay();\n            }\n            else\n            {\n                if (onCustomDrawElement != null)\n                    onCustomDrawElement(r, index, isActive, isFocused);\n                else\n                    DrawElementText(r, index, isActive, index == m_ReorderableList.index, isFocused);\n            }\n        }\n\n        public void DrawElementText(Rect r, int index, bool isActive, bool isSelected, bool isFocused)\n        {\n            if (Event.current.type == EventType.Repaint && onGetNameAtIndex != null)\n            {\n                elementStyle.Draw(r, onGetNameAtIndex(index), false, false, isSelected, isFocused);\n            }\n        }\n\n        virtual public void DoRenameOverlay()\n        {\n            if (GetRenameOverlay().IsRenaming())\n                if (!GetRenameOverlay().OnGUI())\n                    RenameEnded();\n        }\n\n        public void BeginRename(int index, float delay)\n        {\n            GetRenameOverlay().BeginRename(onGetNameAtIndex(index), index, delay);\n            m_ReorderableList.index = index;\n            m_LastSelectedIndex = index;\n            FrameItem(index);\n        }\n\n        void RenameEnded()\n        {\n            if (GetRenameOverlay().userAcceptedRename)\n            {\n                if (onNameChangedAtIndex != null)\n                {\n                    string name = string.IsNullOrEmpty(GetRenameOverlay().name) ? GetRenameOverlay().originalName : GetRenameOverlay().name;\n                    int index = GetRenameOverlay().userData;\n                    onNameChangedAtIndex(index, name);\n                }\n            }\n\n            // We give keyboard focus back to our reorderable list because the rename utility stole it (now we give it back)\n            if (GetRenameOverlay().HasKeyboardFocus())\n                m_ReorderableList.GrabKeyboardFocus();\n\n            GetRenameOverlay().Clear();\n        }\n\n        public void EndRename(bool acceptChanges)\n        {\n            if (GetRenameOverlay().IsRenaming())\n            {\n                GetRenameOverlay().EndRename(acceptChanges);\n                RenameEnded();\n            }\n        }\n\n        public void ReorderCallback(ReorderableList list)\n        {\n            m_LastSelectedIndex = list.index;\n        }\n\n        public void MouseUpCallback(ReorderableList list)\n        {\n            if (m_HadKeyFocusAtMouseDown && list.index == m_LastSelectedIndex)\n                BeginRename(list.index, 0.5f);\n\n            m_LastSelectedIndex = list.index;\n        }\n\n        // Fired on mousedown on elemement\n        public void SelectCallback(ReorderableList list)\n        {\n            FrameItem(list.index);\n            if (onSelectionChanged != null)\n                onSelectionChanged(list.index);\n        }\n\n        void RemoveSelected()\n        {\n            if (m_ReorderableList.index < 0 || m_ReorderableList.index >= m_ReorderableList.count)\n            {\n                Debug.Log(\"Invalid index to remove \" + m_ReorderableList.index);\n                return;\n            }\n\n            if (onDeleteItemAtIndex != null)\n                onDeleteItemAtIndex(m_ReorderableList.index);\n        }\n\n        public void FrameItem(int index)\n        {\n            m_FrameIndex = index;\n        }\n\n        bool CanBeginRename()\n        {\n            return !GetRenameOverlay().IsRenaming() && m_ReorderableList.index >= 0;\n        }\n\n        void CommandHandling()\n        {\n            Event evt = Event.current;\n            if (Event.current.type == EventType.ExecuteCommand)\n            {\n                switch (evt.commandName)\n                {\n                    case EventCommandNames.OnLostFocus:\n                        EndRename(true);\n                        evt.Use();\n                        break;\n                }\n            }\n        }\n\n        void KeyboardHandling()\n        {\n            Event evt = Event.current;\n            if (evt.type != EventType.KeyDown)\n                return;\n\n            if (m_ReorderableList.HasKeyboardControl())\n            {\n                switch (Event.current.keyCode)\n                {\n                    case KeyCode.Home:\n                        evt.Use();\n                        m_ReorderableList.index = 0;\n                        FrameItem(m_ReorderableList.index);\n                        break;\n\n                    case KeyCode.End:\n                        evt.Use();\n                        m_ReorderableList.index = m_ReorderableList.count - 1;\n                        FrameItem(m_ReorderableList.index);\n                        break;\n\n                    case KeyCode.Return:\n                    case KeyCode.KeypadEnter:\n                        if (CanBeginRename() && Application.platform == RuntimePlatform.OSXEditor)\n                        {\n                            BeginRename(m_ReorderableList.index, 0f);\n                            evt.Use();\n                        }\n                        break;\n\n                    case KeyCode.F2:\n                        if (CanBeginRename() && Application.platform != RuntimePlatform.OSXEditor)\n                        {\n                            BeginRename(m_ReorderableList.index, 0f);\n                            evt.Use();\n                        }\n                        break;\n\n                    case KeyCode.Delete:\n                        RemoveSelected();\n                        evt.Use();\n                        break;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/Mixer/GUI/TreeViewForAudioMixerGroups.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.Audio;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine.Audio;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewGUI = UnityEditor.IMGUI.Controls.TreeViewGUI<int>;\nusing TreeViewDataSource = UnityEditor.IMGUI.Controls.TreeViewDataSource<int>;\n\n\nnamespace UnityEditor\n{\n    internal static class TreeViewForAudioMixerGroup\n    {\n        public static void CreateAndSetTreeView(ObjectTreeForSelector.TreeSelectorData data)\n        {\n            var ignoreController = InternalEditorUtility.GetObjectFromInstanceID(data.userData) as AudioMixerController;\n\n            // Create treeview\n            var treeView = new TreeViewController(data.editorWindow, data.state);\n            var treeGui = new GroupTreeViewGUI(treeView);\n            var dataSource = new TreeViewDataSourceForMixers(treeView, ignoreController);\n            dataSource.onVisibleRowsChanged += treeGui.CalculateRowRects;\n            treeView.deselectOnUnhandledMouseDown = false;\n            treeView.Init(data.treeViewRect, dataSource, treeGui, null);\n\n            // Set\n            data.objectTreeForSelector.SetTreeView(treeView);\n        }\n\n        static readonly int kNoneItemID = 0;\n        static string s_NoneText = \"None\";\n\n        // GUI\n\n        class GroupTreeViewGUI : TreeViewGUI\n        {\n            private readonly Texture2D k_AudioGroupIcon = EditorGUIUtility.FindTexture(typeof(AudioMixerGroup));\n            private readonly Texture2D k_AudioListenerIcon = EditorGUIUtility.FindTexture(typeof(AudioListener));\n\n            private const float k_SpaceBetween = 25f;\n            private const float k_HeaderHeight = 20f;\n\n            private List<Rect> m_RowRects = new List<Rect>();\n\n            public GroupTreeViewGUI(TreeViewController treeView) : base(treeView)\n            {\n            }\n\n            public override Rect GetRowRect(int row, float rowWidth)\n            {\n                if (m_TreeView.isSearching)\n                {\n                    return base.GetRowRect(row, rowWidth);\n                }\n\n                if (m_TreeView.data.rowCount != m_RowRects.Count)\n                    CalculateRowRects();\n\n                return m_RowRects[row];\n            }\n\n            public override void OnRowGUI(Rect rowRect, TreeViewItem item, int row, bool selected, bool focused)\n            {\n                // Use normal line height when searching (its just a list)\n                if (m_TreeView.isSearching)\n                {\n                    base.OnRowGUI(rowRect, item, row, selected, focused);\n                    return;\n                }\n\n                DoItemGUI(rowRect, row, item, selected, focused, false);\n                bool isRootItem = item.parent == m_TreeView.data.root;\n                bool isNoneItem = item.id == kNoneItemID;\n                if (isRootItem && !isNoneItem)\n                {\n                    AudioMixerController controller = ((MixerTreeViewItem)item).group.controller;\n                    GUI.Label(new Rect(rowRect.x + 2f, rowRect.y - 18f, rowRect.width, 18f), GUIContent.Temp(controller.name), EditorStyles.boldLabel);\n                }\n            }\n\n            protected override Texture GetIconForItem(TreeViewItem item)\n            {\n                if (item != null)\n                {\n                    if (item.icon != null)\n                        return item.icon;\n\n                    if (item.id == kNoneItemID)\n                        return k_AudioListenerIcon;\n                }\n\n                return k_AudioGroupIcon;\n            }\n\n            protected override void SyncFakeItem()\n            {\n            }\n\n            protected override void RenameEnded()\n            {\n            }\n\n            // ------------------\n            // Size section\n\n            private bool IsController(TreeViewItem item)\n            {\n                return (item.parent == m_TreeView.data.root) && (item.id != kNoneItemID);\n            }\n\n            public void CalculateRowRects()\n            {\n                if (m_TreeView.isSearching)\n                    return;\n                const float startY = 2f;\n                float rowWidth = GUIClip.visibleRect.width;\n                var rows = m_TreeView.data.GetRows();\n                m_RowRects = new List<Rect>(rows.Count);\n                float curY = startY;\n                for (int i = 0; i < rows.Count; ++i)\n                {\n                    bool isController = IsController(rows[i]);\n                    float spacing = (isController ? k_SpaceBetween : 0f);\n                    curY += spacing;\n                    float height = k_LineHeight;\n                    m_RowRects.Add(new Rect(0, curY, rowWidth, height));\n                    curY += height;\n                }\n            }\n\n            // Calc correct width if horizontal scrollbar is wanted return new Vector2(1, height)\n            public override Vector2 GetTotalSize()\n            {\n                if (m_TreeView.isSearching)\n                {\n                    Vector2 size =  base.GetTotalSize();\n                    size.x = 1;// GetMaxWidth (rows);\n                    return size;\n                }\n\n                if (m_RowRects.Count == 0)\n                    return new Vector2(1, 1);\n\n                //float maxWidth = GUIClip.visibleRect.width; // GetMaxWidth (rows);\n                return new Vector2(1, m_RowRects[m_RowRects.Count - 1].yMax);\n            }\n\n            public override int GetNumRowsOnPageUpDown(TreeViewItem fromItem, bool pageUp, float heightOfTreeView)\n            {\n                if (m_TreeView.isSearching)\n                    return base.GetNumRowsOnPageUpDown(fromItem, pageUp, heightOfTreeView);\n                return (int)Mathf.Floor(heightOfTreeView / k_LineHeight);   // good enough though not exact due to k_SpaceBetween\n            }\n\n            // Should return the row number of the first and last row thats fits in the pixel rect defined by top and height\n            public override void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible)\n            {\n                if (m_TreeView.isSearching)\n                {\n                    base.GetFirstAndLastRowVisible(out firstRowVisible, out lastRowVisible);\n                    return;\n                }\n                var rowCount = m_TreeView.data.rowCount;\n                if (rowCount != m_RowRects.Count)\n                    Debug.LogError(\"Mismatch in state: rows vs cached rects\");\n\n                int firstVisible = -1;\n                int lastVisible = -1;\n\n                float topPixel = m_TreeView.state.scrollPos.y;\n                float heightInPixels = m_TreeView.GetTotalRect().height;\n                for (int i = 0; i < m_RowRects.Count; ++i)\n                {\n                    bool visible = ((m_RowRects[i].y > topPixel && (m_RowRects[i].y < topPixel + heightInPixels))) ||\n                        ((m_RowRects[i].yMax > topPixel && (m_RowRects[i].yMax < topPixel + heightInPixels)));\n\n                    if (visible)\n                    {\n                        if (firstVisible == -1)\n                            firstVisible = i;\n                        lastVisible = i;\n                    }\n                }\n\n                if (firstVisible != -1 && lastVisible != -1)\n                {\n                    firstRowVisible = firstVisible;\n                    lastRowVisible = lastVisible;\n                }\n                else\n                {\n                    firstRowVisible = 0;\n                    lastRowVisible = rowCount - 1;\n                }\n            }\n        }\n\n        class MixerTreeViewItem : TreeViewItem\n        {\n            public MixerTreeViewItem(int id, int depth, TreeViewItem parent, string displayName, AudioMixerGroupController groupController)\n                : base(id, depth, parent, displayName)\n            {\n                group = groupController;\n            }\n\n            public AudioMixerGroupController group { get; set; }\n        }\n\n        // Datasource\n\n        class TreeViewDataSourceForMixers : TreeViewDataSource\n        {\n            public AudioMixerController ignoreThisController { get; private set; }\n\n            public TreeViewDataSourceForMixers(TreeViewController treeView, AudioMixerController ignoreController)\n                : base(treeView)\n            {\n                showRootItem = false;\n                rootIsCollapsable = false;\n                ignoreThisController = ignoreController;\n                alwaysAddFirstItemToSearchResult = true;\n            }\n\n            bool ShouldShowController(AudioMixerController controller, List<int> allowedInstanceIDs)\n            {\n                if (!controller)\n                    return false;\n\n                if (allowedInstanceIDs != null && allowedInstanceIDs.Count > 0)\n                    return allowedInstanceIDs.Contains(controller.GetInstanceID());\n\n                return true;\n            }\n\n            public override void FetchData()\n            {\n                int depth = -1;\n                m_RootItem = new TreeViewItem(1010101010, depth, null, \"InvisibleRoot\");\n                SetExpanded(m_RootItem.id, true);\n\n                List<int> allowedInstanceIDs = ObjectSelector.get.allowedInstanceIDs;\n\n                var controllers = new List<AudioMixerController>();\n                foreach (var prop in AssetDatabase.FindAllAssets(new SearchFilter() { classNames = new[] { \"AudioMixerController\" }, searchArea = SearchFilter.SearchArea.AllAssets }))\n                {\n                    var controller = prop.pptrValue as AudioMixerController;\n                    if (ShouldShowController(controller, allowedInstanceIDs))\n                        controllers.Add(controller);\n                }\n\n                var roots = new List<TreeViewItem>();\n\n                // First add the 'None' item, then add all groups\n                roots.Add(new TreeViewItem(kNoneItemID, 0, m_RootItem, s_NoneText));\n\n                foreach (var controller in controllers)\n                    roots.Add(BuildSubTree(controller));\n\n                m_RootItem.children = roots;\n\n                // If we only have one controller then just expand that entirely to the user doesnt have to. (If we have more than one root keep them collapsed and let the user expand)\n                if (controllers.Count == 1)\n                    m_TreeView.data.SetExpandedWithChildren(m_RootItem, true);\n\n                m_NeedRefreshRows = true;\n            }\n\n            private TreeViewItem BuildSubTree(AudioMixerController controller)\n            {\n                AudioMixerGroupController masterGroup = controller.masterGroup;\n                var masterItem = new MixerTreeViewItem(masterGroup.GetInstanceID(), 0, m_RootItem, masterGroup.name, masterGroup);\n                AddChildrenRecursive(masterGroup, masterItem);\n                return masterItem;\n            }\n\n            private void AddChildrenRecursive(AudioMixerGroupController group, TreeViewItem item)\n            {\n                item.children = new List<TreeViewItem>(group.children.Length);\n                for (int i = 0; i < group.children.Length; ++i)\n                {\n                    item.children.Add(new MixerTreeViewItem(group.children[i].GetInstanceID(), item.depth + 1, item, group.children[i].name, group.children[i]));\n                    AddChildrenRecursive(group.children[i], item.children[i]);\n                }\n            }\n\n            public override bool CanBeMultiSelected(TreeViewItem item)\n            {\n                return false;\n            }\n\n            public override bool IsRenamingItemAllowed(TreeViewItem item)\n            {\n                return false;\n            }\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Audio/StreamedAudioClipPreview.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing UnityEngine;\n\n\nnamespace UnityEditor\n{\n    class StreamedAudioClipPreview : WaveformPreview\n    {\n        static class AudioClipMinMaxOverview\n        {\n            static Dictionary<AudioClip, float[]> s_Data = new Dictionary<AudioClip, float[]>();\n            public static float[] GetOverviewFor(AudioClip clip)\n            {\n                if (!s_Data.ContainsKey(clip))\n                {\n                    var path = AssetDatabase.GetAssetPath(clip);\n                    if (path == null)\n                        return null;\n                    var importer = AssetImporter.GetAtPath(path);\n                    if (importer == null)\n                        return null;\n\n                    s_Data[clip] = AudioUtil.GetMinMaxData(importer as AudioImporter);\n                }\n\n                return s_Data[clip];\n            }\n        }\n\n        struct ClipPreviewDetails\n        {\n            public float[] preview;\n            public int previewSamples;\n            public double normalizedDuration;\n            public double normalizedStart;\n            public double deltaStep;\n            public AudioClip clip;\n            public int previewPixelsToRender;\n            public double localStart;\n            public double localLength;\n            public bool looping;\n\n            public ClipPreviewDetails(AudioClip clip, bool isLooping, int size, double localStart, double localLength)\n            {\n                if (size < 2)\n                    throw new ArgumentException(\"Size has to be larger than 1\");\n\n                if (localLength <= 0)\n                    throw new ArgumentException(\"length has to be longer than zero\", \"localLength\");\n\n                if (localStart < 0)\n                    throw new ArgumentException(\"localStart has to be positive\", \"localStart\");\n\n                if (clip == null)\n                    throw new ArgumentNullException(\"clip\");\n\n                this.clip = clip;\n\n                preview = AudioClipMinMaxOverview.GetOverviewFor(clip);\n\n                if (preview == null)\n                    throw new ArgumentException(\"Clip \" + clip + \"'s overview preview is null\");\n\n                looping = isLooping;\n\n                this.localStart = localStart;\n                this.localLength = localLength;\n\n                if (looping)\n                {\n                    previewPixelsToRender = size;\n                }\n                else\n                {\n                    var clampedLength = Math.Min(clip.length - localStart, localLength);\n                    previewPixelsToRender = (int)Math.Min(size, size * Math.Max(0, clampedLength / localLength));\n                }\n\n                previewSamples = preview.Length / (clip.channels * 2);\n                normalizedDuration = localLength / clip.length;\n                normalizedStart = localStart / clip.length;\n                deltaStep = (previewSamples * normalizedDuration) / (size - 1);\n            }\n\n            public bool IsCandidateForStreaming()\n            {\n                // shortcut, no need to start the stream if the start extends beyond the first clip region and the clip is \"hold\"\n                if (!looping && localStart >= clip.length)\n                    return false;\n\n                return deltaStep < 0.5;\n            }\n        }\n        struct Segment\n        {\n            public WaveformStreamer streamer;\n            public int streamingIndexOffset;\n            public int textureOffset;\n            public int segmentLength;\n        }\n\n        class StreamingContext\n        {\n            public int index;\n        }\n\n        Dictionary<WaveformStreamer, StreamingContext> m_Contexts = new Dictionary<WaveformStreamer, StreamingContext>();\n        Segment[] m_StreamedSegments;\n        AudioClip m_Clip;\n\n        public StreamedAudioClipPreview(AudioClip clip, int initialSize)\n            : base(clip, initialSize, clip.channels)\n        {\n            m_ClearTexture = false;\n            m_Clip = clip;\n            m_Start = 0;\n            m_Length = clip.length;\n        }\n\n        protected override void InternalDispose()\n        {\n            base.InternalDispose();\n            KillAndClearStreamers();\n            m_StreamedSegments = null;\n        }\n\n        protected override void OnModifications(MessageFlags cFlags)\n        {\n            bool restartStreaming = false;\n\n            if (HasFlag(cFlags, MessageFlags.TextureChanged) || HasFlag(cFlags, MessageFlags.Size) || HasFlag(cFlags, MessageFlags.Length) || HasFlag(cFlags, MessageFlags.Looping))\n            {\n                KillAndClearStreamers();\n\n                if (length <= 0)\n                    return;\n\n                var details = new ClipPreviewDetails(m_Clip, looping, (int)Size.x, start, length);\n\n                UploadPreview(details);\n\n                if (details.IsCandidateForStreaming())\n                    restartStreaming = true;\n            }\n\n            if (!optimized)\n            {\n                KillAndClearStreamers();\n                restartStreaming = false;\n            }\n            else if (HasFlag(cFlags, MessageFlags.Optimization) && !restartStreaming)\n            {\n                // optimization toggled on, need to query whether we should start streaming\n                var details = new ClipPreviewDetails(m_Clip, looping, (int)Size.x, start, length);\n\n                if (details.IsCandidateForStreaming())\n                    restartStreaming = true;\n            }\n\n            if (restartStreaming)\n            {\n                m_StreamedSegments = CalculateAndStartStreamers(start, length);\n\n                if (m_StreamedSegments != null && m_StreamedSegments.Length > 0)\n                {\n                    foreach (var r in m_StreamedSegments)\n                    {\n                        if (!m_Contexts.ContainsKey(r.streamer))\n                            m_Contexts.Add(r.streamer, new StreamingContext());\n                    }\n                }\n            }\n\n            base.OnModifications(cFlags);\n        }\n\n        void KillAndClearStreamers()\n        {\n            foreach (var c in m_Contexts)\n            {\n                c.Key.Stop();\n            }\n\n            m_Contexts.Clear();\n        }\n\n        Segment[] CalculateAndStartStreamers(double localStart, double localLength)\n        {\n            Segment[] segments = null;\n            var originalStart = localStart;\n            // we don't care about the global position, only the locally visible offset into the clip\n            localStart %= m_Clip.length;\n\n            var secondsPerPixel = localLength / Size.x;\n\n            if (!looping)\n            {\n                // holding (= !looping) is a special case handled before everything\n                // else, because it's very simple to implement since it defines a\n                // section capped by length of the clip\n\n                if (originalStart > m_Clip.length)\n                    return null;\n\n                var clampedLength = Math.Min(m_Clip.length - originalStart, localLength);\n                var previewPixelsToRender = (int)Math.Min(Size.x, Size.x * Math.Max(0, clampedLength / localLength));\n\n                if (previewPixelsToRender < 1)\n                    return null;\n\n                segments = new Segment[1];\n\n                segments[0].streamer = new WaveformStreamer(m_Clip, originalStart, clampedLength, previewPixelsToRender, OnNewWaveformData);\n                segments[0].segmentLength = (int)Size.x;\n                segments[0].textureOffset = 0;\n                segments[0].streamingIndexOffset = 0;\n\n                return segments;\n            }\n\n            // epsilon added to discriminate between invisible floating point rounding errors\n            // and actual loops (i.e. more than a single pixel larger than then length)\n            if (localStart + localLength - secondsPerPixel > m_Clip.length)\n            {\n                var secondsToPixels = Size.x / localLength;\n\n                // special case, the first part is clipped but at least one full length of the clip is available\n                // we can then use one streamer to fill in all visible segments\n                if (localLength >= m_Clip.length)\n                {\n                    var numberOfLoops = localLength / m_Clip.length;\n                    var streamer = new WaveformStreamer(m_Clip, 0, m_Clip.length, (int)(Size.x / numberOfLoops), OnNewWaveformData);\n\n                    var currentClipSegmentPart = m_Clip.length - localStart;\n\n                    var localPosition = 0.0;\n\n                    segments = new Segment[Mathf.CeilToInt((float)((localStart + localLength) / m_Clip.length))];\n\n                    for (int i = 0; i < segments.Length; ++i)\n                    {\n                        var cappedLength = Math.Min(currentClipSegmentPart + localPosition, localLength) - localPosition;\n                        segments[i].streamer = streamer;\n                        segments[i].segmentLength = (int)(cappedLength * secondsToPixels);\n                        segments[i].textureOffset = (int)(localPosition * secondsToPixels);\n                        segments[i].streamingIndexOffset = (int)((m_Clip.length - currentClipSegmentPart) * secondsToPixels);\n\n                        localPosition += currentClipSegmentPart;\n                        currentClipSegmentPart = m_Clip.length;\n                    }\n                }\n                else\n                {\n                    // two disjoint regions, since streaming is time-continuous we have to split it up in two portions\n                    var firstPart = m_Clip.length - localStart;\n                    var secondPart = localLength - firstPart;\n\n                    segments = new Segment[2];\n\n                    segments[0].streamer = new WaveformStreamer(m_Clip, localStart, firstPart, (int)(firstPart * secondsToPixels), OnNewWaveformData);\n                    segments[0].segmentLength = (int)(firstPart * secondsToPixels);\n                    segments[0].textureOffset = 0;\n                    segments[0].streamingIndexOffset = 0;\n\n                    segments[1].streamer = new WaveformStreamer(m_Clip, 0, secondPart, (int)(secondPart * secondsToPixels), OnNewWaveformData);\n                    segments[1].segmentLength = (int)(secondPart * secondsToPixels);\n                    segments[1].textureOffset = (int)(firstPart * secondsToPixels);\n                    segments[1].streamingIndexOffset = 0;\n                }\n            }\n            else\n            {\n                // handle single visible part of clip, that does not extend beyond the end\n                // with a length less than a clip - equaling one streamer.\n                segments = new Segment[1];\n\n                segments[0].streamer = new WaveformStreamer(m_Clip, localStart, localLength, (int)Size.x, OnNewWaveformData);\n                segments[0].segmentLength = (int)Size.x;\n                segments[0].textureOffset = 0;\n                segments[0].streamingIndexOffset = 0;\n            }\n\n            return segments;\n        }\n\n        void UploadPreview(ClipPreviewDetails details)\n        {\n            var channels = details.clip.channels;\n            float[] resampledPreview = new float[(int)(channels * Size.x * 2)];\n\n            if (details.localStart + details.localLength > details.clip.length)\n            {\n                ResamplePreviewLooped(details, resampledPreview);\n            }\n            else\n                ResamplePreviewConfined(details, resampledPreview);\n\n            SetMMWaveData(0, resampledPreview);\n        }\n\n        void ResamplePreviewConfined(ClipPreviewDetails details, float[] resampledPreview)\n        {\n            var channels = m_Clip.channels;\n            var samples = details.previewSamples;\n            var delta = details.deltaStep;\n            var position = details.normalizedStart * samples;\n            var preview = details.preview;\n\n            if (delta > 0.5)\n            {\n                int oldPosition = (int)position, floorPosition = oldPosition;\n                // for each step, there's more than one sample so we do min max on the min max data\n                // to avoid aliasing issues\n                for (int i = 0; i < details.previewPixelsToRender; ++i)\n                {\n                    for (int c = 0; c < channels; ++c)\n                    {\n                        var x = oldPosition;\n                        floorPosition = (int)position;\n\n                        float min = preview[2 * x * channels + c * 2];\n                        float max = preview[2 * x * channels + c * 2 + 1];\n\n                        while (++x < floorPosition)\n                        {\n                            // yes, the data contained in the min max audio util overview is actually swapped (maxmin data)\n                            min = Mathf.Max(min, preview[2 * x * channels + c * 2]);\n                            max = Mathf.Min(max, preview[2 * x * channels + c * 2 + 1]);\n                        }\n\n                        resampledPreview[2 * i * channels + c * 2] = max;\n                        resampledPreview[2 * i * channels + c * 2 + 1] = min;\n                    }\n\n                    position += delta;\n                    oldPosition = floorPosition;\n                }\n            }\n            else\n            {\n                // fractionate interpolation\n                for (int i = 0; i < details.previewPixelsToRender; ++i)\n                {\n                    var x = (int)(position - 1);\n                    var x1 = x + 1;\n                    float fraction = (float)((position - 1) - x);\n\n                    x = Mathf.Max(0, x);\n                    x1 = Mathf.Min(x1, samples - 1);\n\n                    for (int c = 0; c < channels; ++c)\n                    {\n                        var minCurrent = preview[2 * x * channels + c * 2];\n                        var maxCurrent = preview[2 * x * channels + c * 2 + 1];\n\n                        var minNext = preview[2 * x1 * channels + c * 2];\n                        var maxNext = preview[2 * x1 * channels + c * 2 + 1];\n\n                        resampledPreview[2 * i * channels + c * 2] = fraction * maxNext + (1 - fraction) * maxCurrent;\n                        resampledPreview[2 * i * channels + c * 2 + 1] = fraction * minNext + (1 - fraction) * minCurrent;\n                    }\n\n                    position += delta;\n                }\n            }\n        }\n\n        void ResamplePreviewLooped(ClipPreviewDetails details, float[] resampledPreview)\n        {\n            var previewSize = details.preview.Length;\n            var channels = m_Clip.channels;\n            var samples = details.previewSamples;\n\n            var delta = details.deltaStep;\n            var position = details.normalizedStart * samples;\n            var preview = details.preview;\n\n            if (delta > 0.5)\n            {\n                int oldPosition = (int)position, floorPosition = oldPosition;\n                // for each step, there's more than one sample so we do min max on the min max data\n                // to avoid aliasing issues\n                for (int i = 0; i < details.previewPixelsToRender; ++i)\n                {\n                    for (int c = 0; c < channels; ++c)\n                    {\n                        var x = oldPosition;\n                        floorPosition = (int)position;\n\n                        var wrappedIndex = (2 * x * channels + c * 2) % previewSize;\n\n                        float min = preview[wrappedIndex];\n                        float max = preview[wrappedIndex + 1];\n\n                        while (++x < floorPosition)\n                        {\n                            wrappedIndex = (2 * x * channels + c * 2) % previewSize;\n                            // yes, the data contained in the min max audio util overview is actually swapped (maxmin data)\n                            min = Mathf.Max(min, preview[wrappedIndex]);\n                            max = Mathf.Min(max, preview[wrappedIndex + 1]);\n                        }\n\n                        resampledPreview[2 * i * channels + c * 2] = max;\n                        resampledPreview[2 * i * channels + c * 2 + 1] = min;\n                    }\n\n                    position += delta;\n                    oldPosition = floorPosition;\n                }\n            }\n            else\n            {\n                // fractionate interpolation\n                for (int i = 0; i < details.previewPixelsToRender; ++i)\n                {\n                    var x = (int)(position - 1);\n                    var x1 = x + 1;\n                    float fraction = (float)((position - 1) - x);\n\n                    for (int c = 0; c < channels; ++c)\n                    {\n                        var xWrapped = (2 * x * channels + c * 2) % previewSize;\n\n                        var minCurrent = preview[xWrapped];\n                        var maxCurrent = preview[xWrapped + 1];\n\n                        var x1Wrapped = (2 * x1 * channels + c * 2) % previewSize;\n\n                        var minNext = preview[x1Wrapped];\n                        var maxNext = preview[x1Wrapped + 1];\n\n                        resampledPreview[2 * i * channels + c * 2] = fraction * maxNext + (1 - fraction) * maxCurrent;\n                        resampledPreview[2 * i * channels + c * 2 + 1] = fraction * minNext + (1 - fraction) * minCurrent;\n                    }\n\n                    position += delta;\n                }\n            }\n        }\n\n        bool OnNewWaveformData(WaveformStreamer streamer, float[] data, int remaining)\n        {\n            StreamingContext c = m_Contexts[streamer];\n\n            int pixelPos = c.index / m_Clip.channels;\n\n            for (var i = 0; i < m_StreamedSegments.Length; i++)\n            {\n                if (m_StreamedSegments[i].streamer == streamer && pixelPos >= m_StreamedSegments[i].streamingIndexOffset && m_StreamedSegments[i].segmentLength > (pixelPos - m_StreamedSegments[i].streamingIndexOffset))\n                {\n                    SetMMWaveData((m_StreamedSegments[i].textureOffset - m_StreamedSegments[i].streamingIndexOffset) * m_Clip.channels + c.index, data);\n                }\n            }\n\n            c.index += data.Length / 2;\n\n            return remaining != 0;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/UIElements/AudioContainerElementClipField.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.UIElements;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Audio.UIElements;\n\nclass AudioContainerElementClipField : ObjectField\n{\n    [Serializable]\n    public new class UxmlSerializedData : ObjectField.UxmlSerializedData\n    {\n        public override object CreateInstance() => new AudioContainerElementClipField();\n    }\n\n    public int AssetElementInstanceID { get; set; }\n    public double Progress\n    {\n        get => m_Progress;\n\n        set\n        {\n            m_Progress = value;\n            MarkDirtyRepaint();\n        }\n    }\n\n    float m_ObjectFieldBorderWidth;\n    float m_ObjectSelectorWidth;\n    Color m_ProgressBarColor;\n    Color m_ProgressBarBackgroundColor;\n    double m_Progress;\n\n    static readonly CustomStyleProperty<Color> s_ProgressBarColorProperty = new(\"--progress-bar-color\");\n    static readonly CustomStyleProperty<Color> s_ProgressBarBackgroundColorProperty = new(\"--progress-bar-background\");\n\n    public AudioContainerElementClipField()\n    {\n        generateVisualContent += GenerateVisualContent;\n        RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);\n        RegisterCallback<CustomStyleResolvedEvent>(CustomStylesResolved);\n    }\n\n    static void CustomStylesResolved(CustomStyleResolvedEvent evt)\n    {\n        AudioContainerElementClipField element = (AudioContainerElementClipField)evt.currentTarget;\n        element.UpdateCustomStyles();\n    }\n\n    void UpdateCustomStyles()\n    {\n        if (customStyle.TryGetValue(s_ProgressBarColorProperty, out var progressColor))\n        {\n            m_ProgressBarColor = progressColor;\n        }\n\n        if (customStyle.TryGetValue(s_ProgressBarBackgroundColorProperty, out var progressBackgroundColor))\n        {\n            m_ProgressBarBackgroundColor = progressBackgroundColor;\n        }\n    }\n\n    void OnGeometryChanged(GeometryChangedEvent evt)\n    {\n            CacheChildSettings();\n            MarkDirtyRepaint();\n    }\n\n    void CacheChildSettings()\n    {\n        var objField = UIToolkitUtilities.GetChildByClassName<VisualElement>(this, \"unity-object-field__input\");\n        var col = objField.resolvedStyle.backgroundColor;\n        col.a = 0;\n        objField.style.backgroundColor = col;\n        m_ObjectFieldBorderWidth = objField.resolvedStyle.borderBottomWidth;\n\n        var selector = UIToolkitUtilities.GetChildByClassName<VisualElement>(this, \"unity-object-field__selector\");\n        m_ObjectSelectorWidth = selector.boundingBox.width;\n    }\n\n    static void GenerateVisualContent(MeshGenerationContext context)\n    {\n        var element = context.visualElement as AudioContainerElementClipField;\n        var painter2D = context.painter2D;\n        var rect = context.visualElement.contentRect;\n        rect.yMax -= element.m_ObjectFieldBorderWidth;\n        rect.yMin += element.m_ObjectFieldBorderWidth;\n        rect.xMin += element.m_ObjectFieldBorderWidth;\n\n        var progress = element.m_Progress;\n        var progressMaxX = (float)(((rect.xMax - element.m_ObjectSelectorWidth) - rect.xMin) * progress);\n        painter2D.fillColor = element.m_ProgressBarColor;\n        painter2D.BeginPath();\n        painter2D.MoveTo(new Vector2(rect.xMin, rect.yMin));\n        painter2D.LineTo(new Vector2(progressMaxX, rect.yMin));\n        painter2D.LineTo(new Vector2(progressMaxX, rect.yMax));\n        painter2D.LineTo(new Vector2(rect.xMin, rect.yMax));\n        painter2D.ClosePath();\n        painter2D.Fill();\n\n        // redraw background\n        painter2D.fillColor = element.m_ProgressBarBackgroundColor;\n        painter2D.BeginPath();\n        painter2D.MoveTo(new Vector2(progressMaxX, rect.yMin));\n        painter2D.LineTo(new Vector2(rect.xMax, rect.yMin));\n        painter2D.LineTo(new Vector2(rect.xMax, rect.yMax));\n        painter2D.LineTo(new Vector2(progressMaxX, rect.yMax));\n        painter2D.ClosePath();\n        painter2D.Fill();\n\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/UIElements/AudioLevelMeter.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing Color = UnityEngine.Color;\n\nnamespace UnityEditor.Audio.UIElements\n{\n    internal class AudioLevelMeter : VisualElement\n    {\n        [Serializable]\n        internal new class UxmlSerializedData : VisualElement.UxmlSerializedData\n        {\n            public override object CreateInstance() => new AudioLevelMeter();\n        }\n\n        private float m_Value = -80.0f; // Value of the meter in dBFS.\n\n        public float Value\n        {\n            get\n            {\n                return m_Value;\n            }\n\n            set\n            {\n                m_Value = value;\n                MarkDirtyRepaint();\n            }\n        }\n\n        public AudioLevelMeter() : base()\n        {\n            generateVisualContent += GenerateVisualContent;\n\n            RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);\n        }\n\n        private void OnGeometryChanged(GeometryChangedEvent evt)\n        {\n            MarkDirtyRepaint();\n        }\n\n        private const float k_YellowStart = 11.0f / 14.0f;\n        private const float k_RedStart    = 13.0f / 14.0f;\n\n        private static float ConvertDBFSToMeterScale(float value)\n        {\n            // Converts dBFS to the non-linear scale that the meter uses.\n\n            switch (value)\n            {\n                case <= -80.0f: return 0.0f;\n                case <= -30.0f: return value / (10.0f * 14.0f) + 80.0f / (10.0f * 14.0f) + 0.0f / 14.0f;\n                case <= -24.0f: return value / ( 6.0f * 14.0f) + 30.0f / ( 6.0f * 14.0f) + 5.0f / 14.0f;\n                case <=   0.0f: return value / ( 3.0f * 14.0f) + 24.0f / ( 3.0f * 14.0f) + 6.0f / 14.0f;\n                default: return 1.0f;\n            }\n        }\n\n        private static Rect ShrinkRectBy(Rect rect, RectOffset offset)\n        {\n            var minX = rect.xMin + offset.left;\n            var maxX = rect.xMax - offset.right;\n            var minY = rect.yMin + offset.bottom;\n            var maxY = rect.yMax - offset.top;\n\n            return new Rect(minX, minY, maxX - minX, maxY - minY);\n        }\n\n        static void GenerateVisualContent(MeshGenerationContext context)\n        {\n            var painter2D = context.painter2D;\n\n            var value = ConvertDBFSToMeterScale((context.visualElement as AudioLevelMeter).m_Value);\n\n            var width = context.visualElement.contentRect.width;\n\n            var rect1 = context.visualElement.contentRect;\n\n            painter2D.fillColor = Color.gray;\n            painter2D.BeginPath();\n            painter2D.MoveTo(new Vector2(rect1.xMin, rect1.yMin));\n            painter2D.LineTo(new Vector2(rect1.xMax, rect1.yMin));\n            painter2D.LineTo(new Vector2(rect1.xMax, rect1.yMax));\n            painter2D.LineTo(new Vector2(rect1.xMin, rect1.yMax));\n            painter2D.ClosePath();\n            painter2D.Fill();\n\n            if (value > 0)\n            {\n                var start = 0.0f;\n                var end = width * Mathf.Min(value, k_YellowStart);\n                var rect2 = ShrinkRectBy(context.visualElement.contentRect, new RectOffset((int) start, (int) (width - end), 0, 0));\n\n                painter2D.fillColor = Color.green;\n                painter2D.BeginPath();\n                painter2D.MoveTo(new Vector2(rect2.xMin, rect2.yMin));\n                painter2D.LineTo(new Vector2(rect2.xMax, rect2.yMin));\n                painter2D.LineTo(new Vector2(rect2.xMax, rect2.yMax));\n                painter2D.LineTo(new Vector2(rect2.xMin, rect2.yMax));\n                painter2D.ClosePath();\n                painter2D.Fill();\n            }\n\n            if (value > k_YellowStart)\n            {\n                var start = width * k_YellowStart;\n                var end = width * Mathf.Min(value, k_RedStart);\n                var rect2 = ShrinkRectBy(context.visualElement.contentRect, new RectOffset((int) start, (int) (width - end), 0, 0));\n\n                painter2D.fillColor = Color.yellow;\n                painter2D.BeginPath();\n                painter2D.MoveTo(new Vector2(rect2.xMin, rect2.yMin));\n                painter2D.LineTo(new Vector2(rect2.xMax, rect2.yMin));\n                painter2D.LineTo(new Vector2(rect2.xMax, rect2.yMax));\n                painter2D.LineTo(new Vector2(rect2.xMin, rect2.yMax));\n                painter2D.ClosePath();\n                painter2D.Fill();\n            }\n\n            if (value > k_RedStart)\n            {\n                var start = width * k_RedStart;\n                var end = width * Mathf.Min(value, width);\n                var rect2 = ShrinkRectBy(context.visualElement.contentRect, new RectOffset((int) start, (int) (width - end), 0, 0));\n\n                painter2D.fillColor = Color.red;\n                painter2D.BeginPath();\n                painter2D.MoveTo(new Vector2(rect2.xMin, rect2.yMin));\n                painter2D.LineTo(new Vector2(rect2.xMax, rect2.yMin));\n                painter2D.LineTo(new Vector2(rect2.xMax, rect2.yMax));\n                painter2D.LineTo(new Vector2(rect2.xMin, rect2.yMax));\n                painter2D.ClosePath();\n                painter2D.Fill();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/UIElements/AudioRandomRangeSliderTracker.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Transactions;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing UnityEngine.UIElements.Layout;\n\nnamespace UnityEditor.Audio.UIElements;\n\nclass AudioRandomRangeSliderTracker : VisualElement\n{\n    [Serializable]\n    public new class UxmlSerializedData : VisualElement.UxmlSerializedData\n    {\n        public override object CreateInstance() => new AudioRandomRangeSliderTracker();\n    }\n\n    static readonly CustomStyleProperty<Color> s_TrackerEnabledColorProperty = new(\"--tracker-color\");\n\n    Slider m_ParentSlider;\n    Vector2 m_Range = Vector2.zero;\n    Color m_TrackerEnabledColor;\n    Color m_TrackerDisabledColor = Color.gray;\n\n    static void CustomStylesResolved(CustomStyleResolvedEvent evt)\n    {\n        var element = (AudioRandomRangeSliderTracker)evt.currentTarget;\n\n        element.UpdateCustomStyles();\n    }\n\n    void UpdateCustomStyles()\n    {\n        if (customStyle.TryGetValue(s_TrackerEnabledColorProperty, out var trackerColor))\n        {\n            m_TrackerEnabledColor = trackerColor;\n        }\n    }\n\n    internal static AudioRandomRangeSliderTracker Create(Slider parentSlider, Vector2 range)\n    {\n        var dragContainer = UIToolkitUtilities.GetChildByName<VisualElement>(parentSlider, \"unity-drag-container\");\n        var rangeTrackerAsset = UIToolkitUtilities.LoadUxml(\"UXML/Audio/AudioRandomRangeSliderTracker.uxml\");\n        var baseTracker = UIToolkitUtilities.GetChildByName<VisualElement>(parentSlider, \"unity-tracker\");\n        var insertionIndex = dragContainer.IndexOf(baseTracker) + 1;\n        var templateContainer = rangeTrackerAsset.Instantiate();\n\n        dragContainer.Insert(insertionIndex, templateContainer);\n\n        var rangeTracker = UIToolkitUtilities.GetChildAtIndex<AudioRandomRangeSliderTracker>(templateContainer, 0);\n\n        rangeTracker.SetRange(range);\n        rangeTracker.m_ParentSlider = parentSlider;\n        rangeTracker.generateVisualContent += GenerateVisualContent;\n        rangeTracker.RegisterCallback<CustomStyleResolvedEvent>(CustomStylesResolved);\n        rangeTracker.m_ParentSlider.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);\n        rangeTracker.RegisterCallback<PropertyChangedEvent>(OnPropertyChanged);\n        rangeTracker.style.overflow = Overflow.Visible;\n\n        return rangeTracker;\n    }\n\n    internal void SetRange(Vector2 range)\n    {\n        m_Range = range;\n\n        MarkDirtyRepaint();\n    }\n\n    static void OnGeometryChanged(GeometryChangedEvent evt)\n    {\n        var sliderTracker = UIToolkitUtilities.GetChildByClassName<AudioRandomRangeSliderTracker>(evt.elementTarget, \"unity-audio-random-range-slider-tracker\");\n\n        sliderTracker.SetRange(sliderTracker.m_Range);\n    }\n\n    static void OnPropertyChanged(PropertyChangedEvent evt)\n    {\n        var sliderTracker = evt.elementTarget;\n\n        if (evt.property == \"enabledSelf\")\n        {\n            sliderTracker.MarkDirtyRepaint();\n        }\n    }\n\n    // Maps 'x' from the range '[x_min; x_max]' to the range '[y_min; y_max]'.\n    static float Map(float x, float x_min, float x_max, float y_min, float y_max)\n    {\n        var a = (x_max - x) / (x_max - x_min);\n        var b = (x - x_min) / (x_max - x_min);\n\n        return a * y_min + b * y_max;\n    }\n\n    static void GenerateVisualContent(MeshGenerationContext context)\n    {\n        var painter2D = context.painter2D;\n        var sliderTracker = context.visualElement as AudioRandomRangeSliderTracker;\n        var range = sliderTracker.m_Range;\n        var parentSlider = sliderTracker.m_ParentSlider;\n        var contentRect = context.visualElement.contentRect;\n\n        var hasPositiveRandomizationApplied = range.y > 0.0f;\n        var hasNegativeRandomizationApplied = range.x < 0.0f;\n\n        // Offset the range so it is centered around the parent slider's current value.\n        range.x += parentSlider.value;\n        range.y += parentSlider.value;\n\n        // Measured from a screenshot of the slider. The value is in pixels.\n        var sliderHeadWidth = 10.0f;\n        var trackHeight = contentRect.yMax - contentRect.yMin;\n\n        // Map the range from the slider value range (e.g. dB) to the horizontal span of the content-rect (px).\n        var left  = Map(range.x, parentSlider.lowValue, parentSlider.highValue, contentRect.xMin + sliderHeadWidth / 2.0f, contentRect.xMax - sliderHeadWidth / 2.0f);\n        var right = Map(range.y, parentSlider.lowValue, parentSlider.highValue, contentRect.xMin + sliderHeadWidth / 2.0f, contentRect.xMax - sliderHeadWidth / 2.0f);\n\n        if (hasPositiveRandomizationApplied) { right += sliderHeadWidth / 2.0f; }\n        if (hasNegativeRandomizationApplied) { left  -= sliderHeadWidth / 2.0f; }\n\n        // Determine if the slider value is being clipped in either end.\n        var lowEndClipped = left < contentRect.xMin;\n        var highEndClipped = right > contentRect.xMax;\n\n        // Clamp the mapped range so that it lies within the boundaries of the content-rect.\n        left =  Mathf.Clamp(left, contentRect.xMin, contentRect.xMax);\n        right = Mathf.Clamp(right, contentRect.xMin, contentRect.xMax);\n\n        // Draw the tracker.\n        painter2D.fillColor = sliderTracker.enabledSelf ? sliderTracker.m_TrackerEnabledColor : sliderTracker.m_TrackerDisabledColor;\n        painter2D.BeginPath();\n        painter2D.MoveTo(new Vector2(left, contentRect.yMin));\n        painter2D.LineTo(new Vector2(right, contentRect.yMin));\n        painter2D.LineTo(new Vector2(right, contentRect.yMax));\n        painter2D.LineTo(new Vector2(left, contentRect.yMax));\n        painter2D.ClosePath();\n        painter2D.Fill();\n\n        if (sliderTracker.enabledSelf && lowEndClipped)\n        {\n            painter2D.fillColor = sliderTracker.m_TrackerEnabledColor;\n            painter2D.BeginPath();\n            painter2D.MoveTo(new Vector2(contentRect.xMin - trackHeight * 2, contentRect.yMin));\n            painter2D.LineTo(new Vector2(contentRect.xMin - trackHeight * 1, contentRect.yMin));\n            painter2D.LineTo(new Vector2(contentRect.xMin - trackHeight * 1, contentRect.yMax));\n            painter2D.LineTo(new Vector2(contentRect.xMin - trackHeight * 2, contentRect.yMax));\n            painter2D.ClosePath();\n            painter2D.Fill();\n        }\n\n        if (sliderTracker.enabledSelf && highEndClipped)\n        {\n            painter2D.fillColor = sliderTracker.m_TrackerEnabledColor;\n            painter2D.BeginPath();\n            painter2D.MoveTo(new Vector2(contentRect.xMax + trackHeight * 1, contentRect.yMin));\n            painter2D.LineTo(new Vector2(contentRect.xMax + trackHeight * 2, contentRect.yMin));\n            painter2D.LineTo(new Vector2(contentRect.xMax + trackHeight * 2, contentRect.yMax));\n            painter2D.LineTo(new Vector2(contentRect.xMax + trackHeight * 1, contentRect.yMax));\n            painter2D.ClosePath();\n            painter2D.Fill();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/UIElements/OnAudioFilterReadLevelMeter.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Audio.UIElements\n{\n    internal class OnAudioFilterReadLevelMeter : IMGUIContainer\n    {\n        AudioFilterGUI m_IMGUI_AudioFilterGUI = new AudioFilterGUI();\n\n        public OnAudioFilterReadLevelMeter(MonoBehaviour behaviour)\n        {\n            onGUIHandler = () =>\n            {\n                if (GUIView.current != null)\n                {\n                    m_IMGUI_AudioFilterGUI.DrawAudioFilterGUI(behaviour);\n                }\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/UIElements/Tickmarks.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing Color = UnityEngine.Color;\n\nnamespace UnityEditor.Audio.UIElements\n{\n    internal class Tickmarks : VisualElement\n    {\n        private interface Scale\n        {\n            int DivisionCount();\n            string[] Labels();\n            int[] SubDivisionCount();\n            float[] LabelOffsets();\n        }\n\n        private struct LargeScale : Scale\n        {\n            public int DivisionCount() { return 15; }\n            public string[] Labels() { return new string[] { \"80\", \"70\", \"60\", \"50\", \"40\", \"30\", \"24\", \"21\", \"18\", \"15\", \"12\", \"9\", \"6\", \"3\", \"0\" }; }\n            public int[] SubDivisionCount() { return new int[] { 4, 4, 4, 4, 4, 5, 2, 2, 2, 2, 2, 2, 2, 2 };  }\n            public float[] LabelOffsets() { return new float[] { -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -3.5f, -3.5f, -3.5f, -3.5f }; }\n        }\n\n        private struct CompactScale : Scale\n        {\n            public int DivisionCount() { return 8; }\n            public string[] Labels() { return new string[] { \"80\", \"60\", \"40\", \"24\", \"18\", \"12\", \"6\", \"0\" }; }\n            public int[] SubDivisionCount() { return new int[] { 4, 4, 3, 2, 2, 2, 2 };  }\n            public float[] LabelOffsets() { return new float[] { -6, -6, -6, -6, -6, -6, -3.5f, -3.5f }; }\n        }\n\n        private struct MiniScale : Scale\n        {\n            public int DivisionCount() { return 5; }\n            public string[] Labels() { return new string[] { \"80\", \"45\", \"21\", \"12\", \"0\" }; }\n            public int[] SubDivisionCount() { return new int[] { 6, 3, 2, 3 };  }\n            public float[] LabelOffsets() { return new float[] { -6, -6, -6, -6, -3.5f }; }\n        }\n\n        [Serializable]\n        public new class UxmlSerializedData : VisualElement.UxmlSerializedData\n        {\n            public override object CreateInstance() => new Tickmarks();\n        }\n\n        public Tickmarks() : base()\n        {\n            generateVisualContent += context => GenerateVisualContent(context);\n            RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);\n            RegisterCallback<CustomStyleResolvedEvent>(CustomStylesResolved);\n        }\n\n        private static void CustomStylesResolved(CustomStyleResolvedEvent evt)\n        {\n            Tickmarks element = (Tickmarks)evt.currentTarget;\n            element.GetColorsFromStylesheet();\n        }\n\n        private static readonly CustomStyleProperty<Color> s_TickmarkColorProperty = new(\"--tickmark-color\");\n\n        private Color m_TickmarkColor;\n\n        private void GetColorsFromStylesheet()\n        {\n            if (customStyle.TryGetValue(s_TickmarkColorProperty, out var tickmarkColor))\n            {\n                m_TickmarkColor = tickmarkColor;\n            }\n        }\n\n        private void OnGeometryChanged(GeometryChangedEvent evt)\n        {\n            MarkDirtyRepaint();\n        }\n\n        private static void GenerateVisualContent(MeshGenerationContext context)\n        {\n            var painter2D = context.painter2D;\n\n            var contentRect = context.visualElement.contentRect;\n\n            Scale scale = contentRect.width > 350 ? new LargeScale() : (contentRect.width > 175 ? new CompactScale() : new MiniScale());\n\n            var tickmarkColor = (context.visualElement as Tickmarks).m_TickmarkColor;\n            var textColor = tickmarkColor.RGBMultiplied(1.2f); // Compensate for a bug in UI Toolkit which causes MeshGenerationContext.DrawText to render text lighter than the color that you provide.\n\n            for (int index = 0; index < scale.DivisionCount(); index += 1)\n            {\n                var pos = contentRect.width * index / (scale.DivisionCount() - 1.0f);\n\n                var rect = new Rect(pos - 0.5f, 5.0f, 1.0f, 8.0f);\n\n                painter2D.fillColor = tickmarkColor;\n                painter2D.BeginPath();\n                painter2D.MoveTo(new Vector2(rect.xMin, rect.yMin));\n                painter2D.LineTo(new Vector2(rect.xMax, rect.yMin));\n                painter2D.LineTo(new Vector2(rect.xMax, rect.yMax));\n                painter2D.LineTo(new Vector2(rect.xMin, rect.yMax));\n                painter2D.ClosePath();\n                painter2D.Fill();\n            }\n\n            for (int index = 0; index < scale.DivisionCount() - 1; index += 1)\n            {\n                var pos = contentRect.width * index / (scale.DivisionCount() - 1.0f);\n                var spacing = contentRect.width / (scale.DivisionCount() - 1.0f);\n                var subDivCount = scale.SubDivisionCount()[index];\n\n                for (int subIndex = 0; subIndex < subDivCount; subIndex++)\n                {\n                    var rect = new Rect(pos - 0.5f + spacing * (subIndex + 1.0f) / (subDivCount + 1.0f), 5.0f, 1.0f, 4.0f);\n\n                    painter2D.fillColor = tickmarkColor;\n                    painter2D.BeginPath();\n                    painter2D.MoveTo(new Vector2(rect.xMin, rect.yMin));\n                    painter2D.LineTo(new Vector2(rect.xMax, rect.yMin));\n                    painter2D.LineTo(new Vector2(rect.xMax, rect.yMax));\n                    painter2D.LineTo(new Vector2(rect.xMin, rect.yMax));\n                    painter2D.ClosePath();\n                    painter2D.Fill();\n                }\n            }\n\n            for (int index = 0; index < scale.DivisionCount(); index += 1)\n            {\n                var pos = contentRect.width * index / (scale.DivisionCount() - 1.0f);\n\n                var rect = new Rect(pos - 10.0f, 10, 20.0f, 20.0f);\n\n                context.DrawText(scale.Labels()[index], new Vector2(pos + scale.LabelOffsets()[index], 14.0f), 10.0f, textColor);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/UIToolkitUtilities.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Assertions;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Audio;\n\nstatic class UIToolkitUtilities\n{\n    internal static VisualTreeAsset LoadUxml(string filePath)\n    {\n        var asset = EditorGUIUtility.Load(filePath) as VisualTreeAsset;\n        Assert.IsNotNull(asset, $\"Could not load UXML file from editor default resources at path: {filePath}.\");\n        return asset;\n    }\n\n    internal static StyleSheet LoadStyleSheet(string filePath)\n    {\n        var asset = EditorGUIUtility.Load(filePath) as StyleSheet;\n        Assert.IsNotNull(asset, $\"Could not load UXML file from editor default resources at path: {filePath}.\");\n        return asset;\n    }\n\n    internal static T GetChildByName<T>(VisualElement parentElement, string childName) where T : VisualElement\n    {\n        var childElement = parentElement.Query<VisualElement>(childName).First();\n        Assert.IsNotNull(childElement, $\"Could not find child element '{childName}' in visual tree of element '{parentElement.name}'.\");\n        var childElementCast = childElement as T;\n        Assert.IsNotNull(childElementCast, $\"Child element '{childName}' of '{parentElement.name}' is not of type {nameof(T)}\");\n        return childElementCast;\n    }\n\n    internal static T GetChildByClassName<T>(VisualElement parentElement, string childClassName) where T : VisualElement\n    {\n        var childElement = parentElement.Query<VisualElement>(className: childClassName).First();\n        Assert.IsNotNull(childElement, $\"Could not find child element '{childClassName}' in visual tree of element '{parentElement.name}'.\");\n        var childElementCast = childElement as T;\n        Assert.IsNotNull(childElementCast, $\"Child element '{childClassName}' of '{parentElement.name}' is not of type {nameof(T)}\");\n        return childElementCast;\n    }\n\n    internal static T GetChildAtIndex<T>(VisualElement parentElement, int index) where T : VisualElement\n    {\n        var childElement = parentElement.ElementAt(index);\n        Assert.IsNotNull(childElement, $\"{parentElement.name} has no child element at '{index}.\");\n        var childElementCast = childElement as T;\n        Assert.IsNotNull(childElementCast, $\"Child element of '{parentElement.name}' at index {index} is not of type {nameof(T)}\");\n        return childElementCast;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/WaveformPreview.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class WaveformPreview : IDisposable\n    {\n        static int s_BaseTextureWidth = 4096;\n        static Material s_Material;\n\n        public double start { get { return m_Start; } }\n        public double length { get { return m_Length; } }\n\n        public Color backgroundColor { get; set; }\n        public Color waveColor { get; set; }\n        public event Action updated;\n        public UnityEngine.Object presentedObject;\n\n        public bool optimized\n        {\n            get { return m_Optimized; }\n            set\n            {\n                if (m_Optimized != value)\n                {\n                    if (value)\n                        m_Dirty = true;\n\n                    m_Optimized = value;\n                    m_Flags |= MessageFlags.Optimization;\n                }\n            }\n        }\n\n        public bool looping\n        {\n            get { return m_Looping; }\n            set\n            {\n                if (m_Looping != value)\n                {\n                    m_Dirty = true;\n                    m_Looping = value;\n                    m_Flags |= MessageFlags.Looping;\n                }\n            }\n        }\n\n        public enum ChannelMode\n        {\n            MonoSum,\n            Separate,\n            SpecificChannel\n        }\n\n        [Flags]\n        protected enum MessageFlags\n        {\n            None = 0,\n            Size = 1 << 0,\n            Length = 1 << 1,\n            Start = 1 << 2,\n            Optimization = 1 << 3,\n            TextureChanged = 1 << 4,\n            ContentsChanged = 1 << 5,\n            Looping = 1 << 6\n        }\n\n        protected static bool HasFlag(MessageFlags flags, MessageFlags test)\n        {\n            return (flags & test) != 0;\n        }\n\n        protected double m_Start;\n        protected double m_Length;\n        protected bool m_ClearTexture = true;\n        protected Vector2 Size { get { return m_Size; } }\n\n        Texture2D m_Texture;\n        Vector2 m_Size;\n        int m_Channels;\n        int m_Samples;\n        int m_SpecificChannel;\n        ChannelMode m_ChannelMode;\n\n        bool m_Looping;\n        bool m_Optimized;\n        bool m_Dirty;\n        bool m_Disposed;\n        MessageFlags m_Flags;\n\n        protected WaveformPreview(UnityEngine.Object presentedObject, int samplesAndWidth, int channels)\n        {\n            this.presentedObject = presentedObject;\n            optimized = true;\n            m_Samples = samplesAndWidth;\n            m_Channels = channels;\n            backgroundColor = new Color(40 / 255.0f, 40 / 255.0f, 40 / 255.0f, 1.0f);\n            waveColor = new Color(255.0f / 255.0f, 140.0f / 255.0f, 0 / 255.0f, 1.0f);\n            UpdateTexture(samplesAndWidth, channels);\n        }\n\n        protected internal WaveformPreview(UnityEngine.Object presentedObject, int samplesAndWidth, int channels, bool deferTextureCreation)\n        {\n            this.presentedObject = presentedObject;\n            optimized = true;\n            m_Samples = samplesAndWidth;\n            m_Channels = channels;\n            backgroundColor = new Color(40 / 255.0f, 40 / 255.0f, 40 / 255.0f, 1.0f);\n            waveColor = new Color(255.0f / 255.0f, 140.0f / 255.0f, 0 / 255.0f, 1.0f);\n            if (!deferTextureCreation)\n                UpdateTexture(samplesAndWidth, channels);\n        }\n\n        public void Dispose()\n        {\n            if (!m_Disposed)\n            {\n                m_Disposed = true;\n                InternalDispose();\n\n                if (m_Texture != null)\n                {\n                    if (Application.isPlaying)\n                        UnityEngine.Object.Destroy(m_Texture);\n                    else\n                        UnityEngine.Object.DestroyImmediate(m_Texture);\n                }\n\n                m_Texture = null;\n            }\n        }\n\n        protected virtual void InternalDispose() {}\n\n        public void Render(Rect rect)\n        {\n            if (s_Material == null)\n            {\n                s_Material = EditorGUIUtility.LoadRequired(\"Previews/PreviewAudioClipWaveform.mat\") as Material;\n            }\n\n            s_Material.SetTexture(\"_WavTex\", m_Texture);\n            s_Material.SetFloat(\"_SampCount\", m_Samples);\n            s_Material.SetFloat(\"_ChanCount\", m_Channels);\n            s_Material.SetFloat(\"_RecPixelSize\", 1.0f / rect.height);\n            s_Material.SetColor(\"_BacCol\", backgroundColor);\n            s_Material.SetColor(\"_ForCol\", waveColor);\n\n            int mode = -2;\n\n            if (m_ChannelMode == ChannelMode.Separate)\n                mode = -1;\n            else if (m_ChannelMode == ChannelMode.SpecificChannel)\n                mode = m_SpecificChannel;\n\n            s_Material.SetFloat(\"_ChanDrawMode\", (float)mode);\n\n            Graphics.DrawTexture(rect, m_Texture, s_Material);\n        }\n\n        public bool ApplyModifications()\n        {\n            if (m_Dirty || m_Texture == null)\n            {\n                m_Flags |= UpdateTexture((int)m_Size.x, m_Channels) ? MessageFlags.TextureChanged : MessageFlags.None;\n                OnModifications(m_Flags);\n                m_Flags = MessageFlags.None;\n\n                m_Texture.Apply();\n                m_Dirty = false;\n                return true;\n            }\n\n            return false;\n        }\n\n        public void SetChannelMode(ChannelMode mode, int specificChannelToRender)\n        {\n            m_ChannelMode = mode;\n            m_SpecificChannel = specificChannelToRender;\n        }\n\n        public void SetChannelMode(ChannelMode mode)\n        {\n            SetChannelMode(mode, 0);\n        }\n\n        bool UpdateTexture(int width, int channels)\n        {\n            int widthWithChannels = width * channels;\n            int textureHeight = 1 + widthWithChannels / s_BaseTextureWidth;\n\n            Action<bool> updateTexture =\n                clear =>\n            {\n                if (m_Texture == null)\n                {\n                    m_Texture = new Texture2D(s_BaseTextureWidth, textureHeight, TextureFormat.RGBAHalf, false, true);\n                    m_Texture.filterMode = FilterMode.Point;\n                    clear = false;\n                }\n                else\n                {\n                    m_Texture.Reinitialize(s_BaseTextureWidth, textureHeight);\n                }\n\n                if (!clear)\n                    return;\n\n                var fillColorArray = m_Texture.GetPixels();\n                for (var i = 0; i < fillColorArray.Length; ++i)\n                    fillColorArray[i] = Color.black;\n\n                m_Texture.SetPixels(fillColorArray);\n            };\n\n            if (width == m_Samples && channels == m_Channels && m_Texture != null)\n            {\n                return false;\n            }\n\n            // resample texture here\n            updateTexture(m_ClearTexture);\n\n            m_Samples = width;\n            m_Channels = channels;\n\n            return m_Dirty = true;\n        }\n\n        public void OptimizeForSize(Vector2 newSize)\n        {\n            newSize = new Vector2(Mathf.Ceil(newSize.x), Mathf.Ceil(newSize.y));\n\n            if (newSize.x != m_Size.x)\n            {\n                m_Size = newSize;\n                m_Flags |= MessageFlags.Size;\n                m_Dirty = true;\n            }\n        }\n\n        protected virtual void OnModifications(MessageFlags changedFlags) {}\n\n        public void SetTimeInfo(double start, double length)\n        {\n            if (start != m_Start || length != m_Length)\n            {\n                m_Start = start;\n                m_Length = length;\n                m_Dirty = true;\n                m_Flags |= MessageFlags.Start | MessageFlags.Length;\n            }\n        }\n\n        public virtual void SetMMWaveData(int interleavedOffset, float[] data)\n        {\n            // could be optimized, but profiling shows it isn't the bottleneck at all\n            for (int i = 0; i < data.Length; interleavedOffset++, i += 2)\n            {\n                int x = interleavedOffset % s_BaseTextureWidth;\n                int y = interleavedOffset / s_BaseTextureWidth;\n                m_Texture.SetPixel(x, y, new Color(data[i], data[i + 1], 0.0f, 0.0f));\n            }\n\n            m_Dirty = true;\n            m_Flags |= MessageFlags.ContentsChanged;\n\n            if (updated != null)\n                updated();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/WaveformPreviewFactory.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing UnityEngine;\n\n\nnamespace UnityEditor\n{\n    static class WaveformPreviewFactory\n    {\n        public static WaveformPreview Create(int initialSize, AudioClip clip)\n        {\n            return new StreamedAudioClipPreview(clip, initialSize);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Audio/WaveformStreamer.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeType(Header = \"Editor/Mono/Audio/WaveformStreamer.bindings.h\")]\n    internal sealed partial class WaveformStreamer\n    {\n        internal IntPtr m_Data;\n\n        public bool done\n        {\n            get { return Internal_WaveformStreamerQueryFinishedStatus(m_Data); }\n        }\n        public void Stop()\n        {\n            Internal_WaveformStreamerStop(m_Data);\n        }\n\n        public WaveformStreamer(AudioClip clip, double start, double duration,\n                                int numOutputSamples, Func<WaveformStreamer, float[], int, bool> onNewWaveformData)\n        {\n            m_Data = Internal_WaveformStreamerCreate(this, clip, start, duration, numOutputSamples, onNewWaveformData);\n        }\n\n        private WaveformStreamer(AudioClip clip, double start, double duration,\n                                 int numOutputSamples, Func<object, float[], int, bool> onNewWaveformData)\n        {\n            m_Data = Internal_WaveformStreamerCreateUntyped(this, clip, start, duration, numOutputSamples, onNewWaveformData);\n        }\n\n        ~WaveformStreamer()\n        {\n            if (m_Data != IntPtr.Zero)\n                Internal_WaveformStreamerDestroy(m_Data);\n        }\n\n        internal static object CreateUntypedWaveformStreamer(AudioClip clip, double start, double duration,\n            int numOutputSamples, Func<object, float[], int, bool> onNewWaveformData)\n        {\n            return new WaveformStreamer(clip, start, duration, numOutputSamples, onNewWaveformData);\n        }\n\n        [NativeThrows]\n        internal static extern IntPtr Internal_WaveformStreamerCreate([Unmarshalled] WaveformStreamer instance, [NotNull] AudioClip clip, double start, double duration,\n            int numOutputSamples, [NotNull] Func<WaveformStreamer, float[], int, bool> onNewWaveformData);\n\n        internal static extern bool Internal_WaveformStreamerQueryFinishedStatus(IntPtr streamer);\n\n        internal static extern void Internal_WaveformStreamerStop(IntPtr streamer);\n\n        [NativeThrows]\n        internal static extern IntPtr Internal_WaveformStreamerCreateUntyped(object instance, [NotNull] AudioClip clip, double start, double duration,\n            int numOutputSamples, [NotNull] Func<object, float[], int, bool> onNewWaveformData);\n\n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern void Internal_WaveformStreamerDestroy(IntPtr streamer);\n\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(WaveformStreamer streamer) => streamer.m_Data;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/AvatarUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Modules/Animation/Animator.h\")]\n    [NativeHeader(\"Editor/Src/Animation/AvatarUtility.h\")]\n    internal class AvatarUtility\n    {\n        extern static internal void SetHumanPose([NotNull] Animator animator, float[] dof);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BaseBuildTarget.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.Build;\nusing UnityEngine;\n\nnamespace UnityEditor;\n\ninternal abstract class BaseBuildTarget : IBuildTarget\n{\n    public virtual string DisplayName => TargetName;\n\n    // linux is the default, no need to explicitly specify it\n    public const string kRootSystemTypeWin = \"win32\";\n    public const string kRootSystemTypeMac = \"macos\";\n    public virtual string RootSystemType => \"linux\";\n\n    public abstract RuntimePlatform RuntimePlatform { get; }\n    public abstract string TargetName { get; }\n    public abstract GUID Guid { get; }\n\n    public abstract int GetLegacyId { get; }\n\n    public virtual IBuildPlatformProperties BuildPlatformProperties => Properties as IBuildPlatformProperties;\n    public virtual IGraphicsPlatformProperties GraphicsPlatformProperties => Properties as IGraphicsPlatformProperties;\n    public virtual IPlayerConnectionPlatformProperties PlayerConnectionPlatformProperties => Properties as IPlayerConnectionPlatformProperties;\n    public virtual IIconPlatformProperties IconPlatformProperties => Properties as IIconPlatformProperties;\n    public virtual IUIPlatformProperties UIPlatformProperties => Properties as IUIPlatformProperties;\n    public virtual IAudioPlatformProperties AudioPlatformProperties => Properties as IAudioPlatformProperties;\n    public virtual IVRPlatformProperties VRPlatformProperties => Properties as IVRPlatformProperties;\n    public virtual ISubtargetPlatformProperties TextureSubtargetPlatformProperties => Properties as ISubtargetPlatformProperties;\n\n    protected virtual IPlatformProperties Properties => null;\n\n    public bool TryGetProperties<T>(out T properties) where T: IPlatformProperties\n    {\n        if (Properties is T)\n        {\n            properties = (T)Properties;\n            return true;\n        }\n        properties = default(T);\n        return false;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BlendTree.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Collections;\nusing UnityEditor;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Animations\n{\n    public enum BlendTreeType\n    {\n        Simple1D = 0 ,\n        SimpleDirectional2D = 1,\n        FreeformDirectional2D = 2,\n        FreeformCartesian2D = 3,\n        Direct = 4\n    }\n\n    [NativeType(\"Editor/Src/Animation/BlendTree.h\")]\n    [StructLayout(LayoutKind.Sequential)]\n    public struct ChildMotion\n    {\n        public Motion         motion                  { get { return m_Motion; }               set { m_Motion = value; }          }\n        public float          threshold               { get { return m_Threshold; }            set { m_Threshold = value; }       }\n        public Vector2        position                { get { return m_Position; }             set { m_Position = value; }        }\n        public float          timeScale               { get { return m_TimeScale; }            set { m_TimeScale = value; }       }\n        public float          cycleOffset             { get { return m_CycleOffset; }          set { m_CycleOffset = value; }     }\n        public string         directBlendParameter    { get { return m_DirectBlendParameter; }     set { m_DirectBlendParameter = value; }}\n        public bool           mirror                  { get { return m_Mirror; }               set { m_Mirror = value; }          }\n\n        Motion        m_Motion;\n        float         m_Threshold;\n        Vector2       m_Position;\n        float         m_TimeScale;\n        float         m_CycleOffset;\n        string        m_DirectBlendParameter;\n        bool          m_Mirror;\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/BlendTree.bindings.h\")]\n    [NativeType(\"Editor/Src/Animation/BlendTree.h\")]\n    public partial class BlendTree : Motion\n    {\n        public BlendTree()\n        {\n            Internal_Create(this);\n        }\n\n        [FreeFunction(\"BlendTreeBindings::Internal_Create\")]\n        extern private static void Internal_Create([Writable] BlendTree self);\n\n        extern public string          blendParameter\n        {\n            get;\n            set;\n        }\n        extern public string          blendParameterY\n        {\n            get;\n            set;\n        }\n        extern public BlendTreeType   blendType\n        {\n            get;\n            set;\n        }\n\n        extern public ChildMotion[] children\n        {\n            get;\n            set;\n        }\n\n        extern internal int GetChildMotionCount();\n\n        internal Motion GetChildMotion(int index)\n        {\n            if (index < 0 && index >= GetChildMotionCount())\n                throw new ArgumentOutOfRangeException(\"index\");\n\n            return Internal_GetChildMotion(index);\n        }\n\n        [NativeMethod(\"GetChildMotion\")]\n        extern internal Motion Internal_GetChildMotion(int index);\n\n        [NativeMethod(\"SetDirectBlendParameter\")]\n        extern internal void SetDirectBlendTreeParameter(int index, string parameter);\n\n        [NativeMethod(\"GetDirectBlendParameter\")]\n        extern internal string GetDirectBlendTreeParameter(int index);\n\n        extern public bool useAutomaticThresholds\n        {\n            get;\n            set;\n        }\n        extern public float minThreshold\n        {\n            get;\n            set;\n        }\n        extern public float maxThreshold\n        {\n            get;\n            set;\n        }\n\n        extern internal void SortChildren();\n\n        extern internal int    recursiveBlendParameterCount\n        {\n            get;\n        }\n        extern internal string GetRecursiveBlendParameter(int index);\n        extern internal float GetRecursiveBlendParameterMin(int index);\n        extern internal float GetRecursiveBlendParameterMax(int index);\n\n        extern internal void SetInputBlendValue(string blendValueName, float value);\n        extern internal float GetInputBlendValue(string blendValueName);\n\n        [NativeMethod(\"GetAnimationClips\")]\n        extern internal AnimationClip[] GetAnimationClipsFlattened();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BlendTreePreviewUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing System.Runtime.InteropServices;\n\nnamespace UnityEditorInternal\n{\n    [NativeHeader(\"Editor/Src/Animation/BlendTreePreviewUtility.h\")]\n    public class BlendTreePreviewUtility\n    {\n        extern public static void GetRootBlendTreeChildWeights([NotNull] Animator animator, int layerIndex, int stateHash, [Out] float[] weightArray);\n\n        extern public static void CalculateRootBlendTreeChildWeights([NotNull] Animator animator, int layerIndex, int stateHash, [Out] float[] weightArray, float blendX, float blendY);\n\n        public static void CalculateBlendTexture(Animator animator, int layerIndex, int stateHash, Texture2D blendTexture, Texture2D[] weightTextures, Rect rect)\n        {\n            CalculateBlendTexture(animator, layerIndex, stateHash, blendTexture, weightTextures, rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);\n        }\n\n        extern protected static void  CalculateBlendTexture([NotNull] Animator animator, int layerIndex, int stateHash, Texture2D blendTexture, Texture2D[] weightTextures, float minX, float minY, float maxX, float maxY);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BrokenPrefabAsset.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Modules/AssetPipelineEditor/Public/BrokenPrefabAsset.h\")]\n    public class BrokenPrefabAsset : DefaultAsset\n    {\n        private BrokenPrefabAsset() {}\n\n        public extern BrokenPrefabAsset brokenPrefabParent { get; }\n        public extern bool isVariant { get; }\n        public extern bool isPrefabFileValid { get; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BrokenPrefabAssetEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.UIElements;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(BrokenPrefabAsset))]\n    class BrokenPrefabAssetEditor : Editor\n    {\n        public override VisualElement CreateInspectorGUI()\n        {\n            var container = new VisualElement();\n\n            var brokenPrefab = (BrokenPrefabAsset)target;\n\n            container.Add(new HelpBox(\n                brokenPrefab.message,\n                brokenPrefab.isWarning ? HelpBoxMessageType.Error : HelpBoxMessageType.Info));\n\n            if (brokenPrefab.isVariant)\n            {\n                var brokenPrefabParent = brokenPrefab.brokenPrefabParent;\n                var field = new ObjectField(\"Variant Parent\");\n                field.SetEnabled(false);\n                if(brokenPrefabParent != null)\n                {\n                    field.value = brokenPrefabParent;\n                    field.objectType = typeof(BrokenPrefabAsset);\n                }\n                else\n                {\n                    //Hack to display \"Missing\" instead of \"None\"\n                    var missingGameObject = EditorUtility.CreateGameObjectWithHideFlags(\"Missing GameObject for Object Field\", HideFlags.HideAndDontSave);\n                    DestroyImmediate(missingGameObject);\n                    field.value = missingGameObject;\n                    field.objectType = typeof(GameObject);\n                }\n\n                container.Add(field);\n            }\n\n            return container;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BugReportingTools.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing uei = UnityEngine.Internal;\n\nnamespace UnityEditor.BugReporting\n{\n    // Keep in sync with \"Editor/Platform/Interface/BugReportingTools.h\"\n    internal enum BugReportMode { ManualOpen, CrashBug, FatalError, CocoaExceptionOrAssertion, ManualSimple }\n\n    [NativeHeader(\"Editor/Mono/BugReportingTools.bindings.h\")]\n    internal sealed class BugReportingTools\n    {\n        [StaticAccessor(\"BugReportingToolsBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"LaunchBugReportingTool\")]\n        public static extern void LaunchBugReporter(BugReportMode mode, string[] additionalArguments);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/Android/AndroidPostGenerateGradleProject.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Build;\nusing UnityEngine;\n\nnamespace UnityEditor.Android\n{\n    public interface IPostGenerateGradleAndroidProject : IOrderedCallback\n    {\n        void OnPostGenerateGradleAndroidProject(string path);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/AssemblyStripper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing NiceIO;\nusing UnityEditor.Build.Reporting;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditor.Build;\nusing UnityEditor.Modules;\nusing UnityEditor.UnityLinker;\nusing Debug = UnityEngine.Debug;\n\nnamespace UnityEditorInternal\n{\n    internal class AssemblyStripper\n    {\n        static List<NPath> ProcessBuildPipelineGenerateAdditionalLinkXmlFiles(BuildPostProcessArgs args)\n        {\n            var results = new List<NPath>();\n            var processors = BuildPipelineInterfaces.processors.unityLinkerProcessors;\n            if (processors == null)\n                return results;\n\n            NPath stagingAreaManaged = $\"{args.stagingAreaData}/Managed\";\n            var pipelineData = new UnityLinkerBuildPipelineData(args.target, stagingAreaManaged.MakeAbsolute().ToString());\n\n            foreach (var processor in processors)\n            {\n                results.Add(processor.GenerateAdditionalLinkXmlFile(args.report, pipelineData));\n                var processorType = processor.GetType();\n\n                // The OnBeforeRun and OnAfterRun methods are no longer supported. We warn if the project uses them.\n                // But since these were interface methods, any project using GenerateAdditionalLinkXmlFile also had to\n                // implement these. So we only want to warn if the methods are not empty.\n                //\n                // To detect if we should consider a method as \"empty\" we check if the method body has more than 2 bytes.\n                // An empty method is 1 byte (ret), or 2 bytes in debug mode (nop, ret). The assumption is that there is\n                // no viable void method with side effects having only 2 bytes.\n\n                var onBeforeRun = processorType.GetMethod(\"OnBeforeRun\");\n                if (onBeforeRun != null && onBeforeRun.GetMethodBody().GetILAsByteArray().Length > 2)\n                    Debug.LogWarning($\"{processorType} has a non-empty OnBeforeRun method, but IUnityLinkerProcessor.OnBeforeRun is no longer supported.\");\n                var onAfterRun = processorType.GetMethod(\"OnAfterRun\");\n                if (onAfterRun != null && onAfterRun.GetMethodBody().GetILAsByteArray().Length > 2)\n                    Debug.LogWarning($\"{processorType} has a non-empty OnAfterRun method, but IUnityLinkerProcessor.OnAfterRun is no longer supported.\");\n            }\n\n            return results;\n        }\n\n        internal static IEnumerable<NPath> GetUserBlacklistFiles()\n        {\n            return Directory.GetFiles(\"Assets\", \"link.xml\", SearchOption.AllDirectories)\n                .Select(s => Path.Combine(Directory.GetCurrentDirectory(), s))\n                .ToNPaths();\n        }\n\n        public static string[] GetLinkXmlFiles(BuildPostProcessArgs args, NPath linkerInputDirectory)\n        {\n            var linkXmlFiles = new List<NPath>();\n\n            if (args.usedClassRegistry != null)\n            {\n                var buildFiles = args.report.GetFiles();\n                linkXmlFiles.Add(WriteMethodsToPreserveBlackList(args.usedClassRegistry, linkerInputDirectory));\n                linkXmlFiles.Add(WriteTypesInScenesBlacklist(args.usedClassRegistry, linkerInputDirectory, buildFiles));\n                linkXmlFiles.Add(WriteSerializedTypesBlacklist(args.usedClassRegistry, linkerInputDirectory, buildFiles));\n            }\n\n            linkXmlFiles.AddRange(ProcessBuildPipelineGenerateAdditionalLinkXmlFiles(args));\n            linkXmlFiles.AddRange(GetUserBlacklistFiles());\n\n            var isMonoBackend = PlayerSettings.GetScriptingBackend(NamedBuildTarget.FromActiveSettings(args.target)) == ScriptingImplementation.Mono2x;\n            if (isMonoBackend)\n            {\n                // The old Mono assembly stripper uses per-platform link.xml files if available. Apply these here.\n                var buildToolsDirectory = BuildPipeline.GetBuildToolsDirectory(args.target);\n                if (!string.IsNullOrEmpty(buildToolsDirectory))\n                {\n                    var platformDescriptor = Path.Combine(buildToolsDirectory, \"link.xml\");\n                    if (File.Exists(platformDescriptor))\n                        linkXmlFiles.Add(platformDescriptor);\n                }\n            }\n\n            return linkXmlFiles\n                .Where(p => p?.FileExists() ?? false)\n                .Select(p => p.MakeAbsolute().ToString())\n                .ToArray();\n        }\n\n        static bool BuildFileMatchesAssembly(BuildFile file, string assemblyName)\n        {\n            return file.path.ToNPath().FileNameWithoutExtension == assemblyName &&\n                (file.role == \"ManagedLibrary\" ||\n                    file.role == \"DependentManagedLibrary\" ||\n                    file.role == \"ManagedEngineAPI\");\n        }\n\n        private static NPath WriteTypesInScenesBlacklist(RuntimeClassRegistry rcr, NPath linkerInputDirectory, BuildFile[] buildFiles)\n        {\n            var items = rcr.GetAllManagedTypesInScenes();\n\n            var sb = new StringBuilder();\n            sb.AppendLine(\"<linker>\");\n            foreach (var assemblyTypePair in items.OrderBy(t => t.Key))\n            {\n                // Some how stuff for assemblies that will not be in the build make it into UsedTypePerUserAssembly such as\n                // ex: [UnityEditor.TestRunner.dll] UnityEditor.TestTools.TestRunner.TestListCacheData\n                //\n                // Filter anything out where the assembly doesn't exist so that UnityLinker can be strict about preservations in link xml files\n                var filename = assemblyTypePair.Key.ToNPath().FileNameWithoutExtension;\n                if (buildFiles.All(file => !BuildFileMatchesAssembly(file, filename)))\n                    continue;\n\n                sb.AppendLine($\"\\t<assembly fullname=\\\"{filename}\\\">\");\n                foreach (var type in assemblyTypePair.Value.OrderBy(s => s))\n                {\n                    sb.AppendLine($\"\\t\\t<type fullname=\\\"{type}\\\" preserve=\\\"nothing\\\"/>\");\n                }\n                sb.AppendLine(\"\\t</assembly>\");\n            }\n            sb.AppendLine(\"</linker>\");\n\n            var path = linkerInputDirectory.Combine(\"TypesInScenes.xml\");\n            path.WriteAllText(sb.ToString());\n            return path;\n        }\n\n        private static NPath WriteSerializedTypesBlacklist(RuntimeClassRegistry rcr, NPath linkerInputDirectory, BuildFile[] buildFiles)\n        {\n            var items = rcr.GetAllSerializedClassesAsString();\n            var oneOrMoreItemsWritten = false;\n            var sb = new StringBuilder();\n            sb.AppendLine(\"<linker>\");\n            foreach (var assemblyTypePair in items.OrderBy(t => t.Key))\n            {\n                // Filter anything out where the assembly doesn't exist so that UnityLinker can be strict about preservations in link xml files\n                if (buildFiles.All(file => !BuildFileMatchesAssembly(file, assemblyTypePair.Key)))\n                    continue;\n\n                sb.AppendLine($\"\\t<assembly fullname=\\\"{assemblyTypePair.Key}\\\">\");\n                foreach (var type in assemblyTypePair.Value.OrderBy(s => s))\n                {\n                    oneOrMoreItemsWritten = true;\n                    sb.AppendLine($\"\\t\\t<type fullname=\\\"{type}\\\" preserve=\\\"nothing\\\" serialized=\\\"true\\\"/>\");\n                }\n                sb.AppendLine(\"\\t</assembly>\");\n            }\n            sb.AppendLine(\"</linker>\");\n\n            // Avoid writing empty files\n            if (!oneOrMoreItemsWritten)\n                return null;\n\n            var path = linkerInputDirectory.Combine(\"SerializedTypes.xml\");\n            path.WriteAllText(sb.ToString());\n            return path;\n        }\n\n        private static UnityType s_GameManagerTypeInfo = null;\n        internal static UnityType GameManagerTypeInfo\n        {\n            get\n            {\n                if (s_GameManagerTypeInfo == null)\n                {\n                    UnityType result = UnityType.FindTypeByName(\"GameManager\");\n                    if (result == null)\n                        throw new ArgumentException(string.Format(\"Could not map typename '{0}' to type info ({1})\", \"GameManager\", \"initializing code stripping utils\"));\n                    s_GameManagerTypeInfo = result;\n                }\n\n                return s_GameManagerTypeInfo;\n            }\n        }\n\n        internal static void UpdateBuildReport(LinkerToEditorData dataFromLinker, StrippingInfo strippingInfo)\n        {\n            foreach (var moduleInfo in dataFromLinker.report.modules)\n            {\n                strippingInfo.AddModule(moduleInfo.name);\n                foreach (var moduleDependency in moduleInfo.dependencies)\n                {\n                    strippingInfo.RegisterDependency(StrippingInfo.ModuleName(moduleInfo.name), moduleDependency.name);\n\n                    if (!string.IsNullOrEmpty(moduleDependency.icon))\n                        strippingInfo.SetIcon(moduleDependency.name, moduleDependency.icon);\n\n                    // Hacky way to match the existing behavior\n                    if (moduleDependency.name == \"UnityConnectSettings\")\n                        strippingInfo.RegisterDependency(moduleDependency.name, \"Required by UnityAnalytics\");\n\n                    foreach (var scene in moduleDependency.scenes)\n                    {\n                        strippingInfo.RegisterDependency(moduleDependency.name, scene);\n\n                        var klass = UnityType.FindTypeByName(moduleDependency.name);\n                        if (klass != null && !klass.IsDerivedFrom(GameManagerTypeInfo))\n                        {\n                            if (scene.EndsWith(\".unity\"))\n                                strippingInfo.SetIcon(scene, \"class/SceneAsset\");\n                            else\n                                strippingInfo.SetIcon(scene, \"class/AssetBundle\");\n                        }\n                    }\n                }\n            }\n        }\n\n        internal static LinkerToEditorData ReadLinkerToEditorData(string outputDirectory)\n        {\n            var dataPath = Path.Combine(outputDirectory, \"UnityLinkerToEditorData.json\");\n            var contents = File.ReadAllText(dataPath);\n            var data = JsonUtility.FromJson<LinkerToEditorData>(contents);\n            return data;\n        }\n\n        public static string WriteEditorData(BuildPostProcessArgs args, NPath linkerInputDirectory)\n        {\n            CollectIncludedAndExcludedModules(out var forceIncludeModules, out var forceExcludeModules);\n\n            var editorToLinkerData = new EditorToLinkerData\n            {\n                typesInScenes = GetTypesInScenesInformation(args.report, args.usedClassRegistry)\n                    .OrderBy(data => data.fullManagedTypeName ?? data.nativeClass)\n                    .ToArray(),\n                allNativeTypes = CollectNativeTypeData().ToArray(),\n                forceIncludeModules = forceIncludeModules.ToArray(),\n                forceExcludeModules = forceExcludeModules.ToArray()\n            };\n\n            var path = linkerInputDirectory.Combine(\"EditorToUnityLinkerData.json\");\n            File.WriteAllText(path.ToString(), JsonUtility.ToJson(editorToLinkerData, true));\n            return path.MakeAbsolute().ToString();\n        }\n\n        static List<EditorToLinkerData.TypeInSceneData> GetTypesInScenesInformation(BuildReport report, RuntimeClassRegistry rcr)\n        {\n            var items = new List<EditorToLinkerData.TypeInSceneData>();\n            foreach (var nativeClass in rcr.GetAllNativeClassesIncludingManagersAsString())\n            {\n                var unityType = UnityType.FindTypeByName(nativeClass);\n\n                var managedName = RuntimeClassMetadataUtils.ScriptingWrapperTypeNameForNativeID(unityType.persistentTypeID);\n                var usedInScenes = rcr.GetScenesForClass(unityType.persistentTypeID)?.OrderBy(p => p);\n\n                bool noManagedType = unityType.persistentTypeID != 0 && managedName == \"UnityEngine.Object\";\n                var information = new EditorToLinkerData.TypeInSceneData(\n                    noManagedType ? null : \"UnityEngine.dll\",\n                    noManagedType ? null : managedName,\n                    nativeClass,\n                    unityType.module,\n                    usedInScenes != null ? usedInScenes.ToArray() : null);\n\n                items.Add(information);\n            }\n\n            var buildFiles = report.GetFiles();\n            foreach (var userAssembly in rcr.UsedTypePerUserAssembly)\n            {\n                // Some how stuff for assemblies that will not be in the build make it into UsedTypePerUserAssembly such as\n                // ex: [UnityEditor.TestRunner.dll] UnityEditor.TestTools.TestRunner.TestListCacheData\n                //\n                // Filter anything out where the assembly doesn't exist so that UnityLinker can be strict about being able to find\n                // all of the types that are reported as being in the scene.\n                var filename = userAssembly.Key.ToNPath().FileNameWithoutExtension;\n                if (buildFiles.All(file => !BuildFileMatchesAssembly(file, filename)))\n                    continue;\n\n                foreach (var type in userAssembly.Value)\n                    items.Add(new EditorToLinkerData.TypeInSceneData(userAssembly.Key, type, null, null, null));\n            }\n\n            return items;\n        }\n\n        static List<EditorToLinkerData.NativeTypeData> CollectNativeTypeData()\n        {\n            var items = new List<EditorToLinkerData.NativeTypeData>();\n            foreach (var unityType in UnityType.GetTypes())\n            {\n                items.Add(new EditorToLinkerData.NativeTypeData\n                {\n                    name = unityType.name,\n                    qualifiedName = unityType.qualifiedName,\n                    nativeNamespace = unityType.hasNativeNamespace ? unityType.nativeNamespace : null,\n                    module = unityType.module,\n                    baseName = unityType.baseClass != null ? unityType.baseClass.name : null,\n                    baseModule = unityType.baseClass != null ? unityType.baseClass.module : null,\n                });\n            }\n\n            return items;\n        }\n\n        private class AssemblyStripperModuleAdder : IPreStrippingModuleAdder\n        {\n            private List<string> m_ForceIncludes;\n\n            public AssemblyStripperModuleAdder(List<string> forceIncludes)\n            {\n                m_ForceIncludes = forceIncludes;\n            }\n\n            public void AddModule(string moduleName)\n            {\n                if (IsModuleIncluded(moduleName))\n                    return;\n\n                m_ForceIncludes.Add(moduleName);\n            }\n\n            public bool IsModuleIncluded(string moduleName)\n                => m_ForceIncludes.Any(i => string.Equals(i, moduleName));\n        }\n\n        public static event Action<IPreStrippingModuleAdder> onCollectIncludedModules;\n\n        static void CollectIncludedAndExcludedModules(out List<string> forceInclude, out List<string> forceExclude)\n        {\n            forceInclude = new List<string>();\n            forceExclude = new List<string>();\n            // Apply manual stripping overrides\n            foreach (var module in ModuleMetadata.GetModuleNames())\n            {\n                var includeSetting = ModuleMetadata.GetModuleIncludeSettingForModule(module);\n                if (includeSetting == ModuleIncludeSetting.ForceInclude)\n                    forceInclude.Add(module);\n                else if (includeSetting == ModuleIncludeSetting.ForceExclude)\n                    forceExclude.Add(module);\n            }\n\n            var adder = new AssemblyStripperModuleAdder(forceInclude);\n            onCollectIncludedModules?.Invoke(adder);\n        }\n\n        private static NPath WriteMethodsToPreserveBlackList(RuntimeClassRegistry rcr, NPath linkerInputDirectory)\n        {\n            var contents = GetMethodPreserveBlacklistContents(rcr);\n            if (contents == null)\n                return null;\n            var methodPreserveBlackList = linkerInputDirectory.Combine(\"MethodsToPreserve.xml\");\n            methodPreserveBlackList.WriteAllText(contents);\n            return methodPreserveBlackList;\n        }\n\n        private static string GetMethodPreserveBlacklistContents(RuntimeClassRegistry rcr)\n        {\n            if (rcr.GetMethodsToPreserve().Count == 0)\n                return null;\n\n            var sb = new StringBuilder();\n            sb.AppendLine(\"<linker>\");\n\n            var groupedByAssembly = rcr.GetMethodsToPreserve().GroupBy(m => m.assembly);\n            foreach (var assembly in groupedByAssembly.OrderBy(a => a.Key))\n            {\n                var assemblyName = assembly.Key;\n                sb.AppendLine(string.Format(\"\\t<assembly fullname=\\\"{0}\\\" ignoreIfMissing=\\\"1\\\">\", assemblyName));\n                var groupedByType = assembly.GroupBy(m => m.fullTypeName);\n                foreach (var type in groupedByType.OrderBy(t => t.Key))\n                {\n                    sb.AppendLine(string.Format(\"\\t\\t<type fullname=\\\"{0}\\\">\", type.Key));\n                    foreach (var method in type.OrderBy(m => m.methodName))\n                        sb.AppendLine(string.Format(\"\\t\\t\\t<method name=\\\"{0}\\\"/>\", method.methodName));\n                    sb.AppendLine(\"\\t\\t</type>\");\n                }\n                sb.AppendLine(\"\\t</assembly>\");\n            }\n\n            sb.AppendLine(\"</linker>\");\n            return sb.ToString();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/AssemblyTypeInfoGenerator.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n// #define DOLOG\nusing System;\nusing System.Runtime.InteropServices;\nusing Mono.Cecil;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    using GenericInstanceTypeMap = System.Collections.Generic.Dictionary<TypeReference, TypeReference>;\n    [NativeHeader(\"Modules/BuildPipeline/Editor/Public/TypeDB.h\")]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct FieldInfoManaged\n    {\n        public string name;\n        public string type;\n        public int flags;\n        public int fixedBufferLength;\n        public string fixedBufferTypename;\n    }\n\n    [NativeHeader(\"Modules/BuildPipeline/Editor/Public/TypeDB.h\")]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct TypeInformationManaged\n    {\n        public string className;\n        public FieldInfoManaged[] fieldInfos;\n    }\n\n    [NativeHeader(\"Modules/BuildPipeline/Editor/Public/TypeDB.h\")]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct AssemblyInfoManaged\n    {\n        public string name;\n        public string path;\n        public TypeInformationManaged[] types;\n    }\n\n    [Serializable]\n    internal class ExtractRoot<T>\n    {\n        public T[] root;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/BuildFailedException.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Build\n{\n    [RequiredByNativeCode]\n    public class BuildFailedException : Exception\n    {\n        // We can set the BuildFailedException to be silent if we know we have already printed an\n        // error message for the failure. That is the case when the BuildFailedException originates\n        // from the BeeBuildPostprocessor. That way we can avoid redundant error messages about builds\n        // failing.\n        private bool m_Silent;\n\n        internal BuildFailedException(string message, bool silent = false) :\n            base(message)\n        {\n            m_Silent = silent;\n        }\n\n        public BuildFailedException(string message) :\n            base(message)\n        {\n        }\n\n        public BuildFailedException(Exception innerException) :\n            base(null, innerException)\n        {\n        }\n\n        [RequiredByNativeCode]\n        private bool IsSilent()\n        {\n            return m_Silent;\n        }\n\n        [RequiredByNativeCode]\n        private Exception BuildFailedException_GetInnerException()\n        {\n            return InnerException;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Reflection;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Build.Reporting;\nusing UnityEditor.Profiling;\nusing UnityEditor.Rendering;\nusing UnityEngine.Scripting;\nusing UnityEditor.AssetImporters;\nusing UnityEngine.SceneManagement;\nusing UnityEditor.Build.Profile;\n\nnamespace UnityEditor.Build\n{\n    public interface IOrderedCallback\n    {\n        int callbackOrder { get; }\n    }\n\n    [Obsolete(\"Use IPreprocessBuildWithReport instead\")]\n    public interface IPreprocessBuild : IOrderedCallback\n    {\n        void OnPreprocessBuild(BuildTarget target, string path);\n    }\n\n    public abstract class BuildPlayerProcessor : IOrderedCallback\n    {\n        public virtual int callbackOrder => 0;\n        public abstract void PrepareForBuild(BuildPlayerContext buildPlayerContext);\n    }\n\n    public interface IPreprocessBuildWithReport : IOrderedCallback\n    {\n        void OnPreprocessBuild(BuildReport report);\n    }\n\n    public interface IFilterBuildAssemblies : IOrderedCallback\n    {\n        string[] OnFilterAssemblies(BuildOptions buildOptions, string[] assemblies);\n    }\n\n    [Obsolete(\"Use IPostprocessBuildWithReport instead\")]\n    public interface IPostprocessBuild : IOrderedCallback\n    {\n        void OnPostprocessBuild(BuildTarget target, string path);\n    }\n\n    public interface IPostprocessBuildWithReport : IOrderedCallback\n    {\n        void OnPostprocessBuild(BuildReport report);\n    }\n\n    public interface IPostBuildPlayerScriptDLLs : IOrderedCallback\n    {\n        void OnPostBuildPlayerScriptDLLs(BuildReport report);\n    }\n\n    [Obsolete(\"Use IProcessSceneWithReport instead\")]\n    public interface IProcessScene : IOrderedCallback\n    {\n        void OnProcessScene(UnityEngine.SceneManagement.Scene scene);\n    }\n\n    public interface IProcessSceneWithReport : IOrderedCallback\n    {\n        void OnProcessScene(UnityEngine.SceneManagement.Scene scene, BuildReport report);\n    }\n\n    public interface IActiveBuildTargetChanged : IOrderedCallback\n    {\n        void OnActiveBuildTargetChanged(BuildTarget previousTarget, BuildTarget newTarget);\n    }\n\n    public interface IPreprocessShaders : IOrderedCallback\n    {\n        void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList<ShaderCompilerData> data);\n    }\n\n    public interface IPreprocessComputeShaders : IOrderedCallback\n    {\n        void OnProcessComputeShader(ComputeShader shader, string kernelName, IList<ShaderCompilerData> data);\n    }\n\n    // This API lets you generate native plugins to be integrated into the player build,\n    // during the incremental player build. The incremental player build platform implementations will know\n    // how to consume these plugins and link them into the build.\n    internal interface IGenerateNativePluginsForAssemblies : IOrderedCallback\n    {\n        // Arguments to the PrepareOnMainThread method\n        public struct PrepareArgs\n        {\n            // The currently active build report.\n            public BuildReport report { get; set; }\n        }\n\n        // Return value of the PrepareOnMainThread method\n        public struct PrepareResult\n        {\n            // Any pathname in here will be considered an input file to the generated plugins;\n            // Any changes to any of these files will trigger a rebuild of the plugins.\n            public string[] additionalInputFiles { get; set; }\n\n            // Message to be shown in the progress bar when the GenerateNativePluginsForAssemblies method is run.\n            public string displayName { get; set; }\n        }\n\n        // Prepare method which is called on the main thread before the incremental player build starts.\n        // Use this to do any work which must happen on the main thread, and to set up dependencies which must trigger a\n        // rebuild of the generated plugins.\n        public PrepareResult PrepareOnMainThread(PrepareArgs args);\n\n        // Arguments to the GenerateNativePluginsForAssemblies method\n\n        public struct GenerateArgs\n        {\n            // Path names to the managed assembly files on disk as built for the currently active player target\n            public string[] assemblyFiles { get; set; }\n        }\n\n        // Return value of the GenerateNativePluginsForAssemblies method\n        public struct GenerateResult\n        {\n            // Any pathname returned in this array will be treated as a plugin to be linked into the player\n            public string[] generatedPlugins { get; set; }\n            public string[] generatedSymbols { get; set; }\n        }\n\n        // Method to generate native plugins during the player build. This will be called on a thread by the incremental\n        // player build pipeline to allow generating native plugins from editor code which will be linked into the player.\n        // If the plugins have already be generated in a previous build, this will only be called if any of the input\n        // files have changed. Input files are all assemblies (as specified in args.assemblyFiles) and all input files\n        // returned by `PrepareOnMainThread` in `additionalInputFiles`.\n        public GenerateResult GenerateNativePluginsForAssemblies(GenerateArgs args);\n    }\n\n    public interface IUnityLinkerProcessor : IOrderedCallback\n    {\n        string GenerateAdditionalLinkXmlFile(BuildReport report, UnityLinker.UnityLinkerBuildPipelineData data);\n    }\n\n    [Obsolete(\"The IIl2CppProcessor interface has been removed from Unity. Use IPostBuildPlayerScriptDLLs if you need to access player assemblies before il2cpp runs.\", true)]\n    public interface IIl2CppProcessor : IOrderedCallback\n    {\n    }\n\n    internal static class BuildPipelineInterfaces\n    {\n        internal class Processors\n        {\n#pragma warning disable 618\n            public List<IPreprocessBuild> buildPreprocessors;\n            public List<IPostprocessBuild> buildPostprocessors;\n            public List<IProcessScene> sceneProcessors;\n#pragma warning restore 618\n\n            public List<BuildPlayerProcessor> buildPlayerProcessors;\n\n            public List<IPreprocessBuildWithReport> buildPreprocessorsWithReport;\n            public List<IPostprocessBuildWithReport> buildPostprocessorsWithReport;\n            public List<IPostprocessLaunch> launchPostprocessors;\n            public List<IProcessSceneWithReport> sceneProcessorsWithReport;\n\n            public List<IFilterBuildAssemblies> filterBuildAssembliesProcessor;\n            public List<IActiveBuildTargetChanged> buildTargetProcessors;\n            public List<IPreprocessShaders> shaderProcessors;\n            public List<IPreprocessComputeShaders> computeShaderProcessors;\n            public List<IPostBuildPlayerScriptDLLs> buildPlayerScriptDLLProcessors;\n\n            public List<IUnityLinkerProcessor> unityLinkerProcessors;\n            public List<IGenerateNativePluginsForAssemblies> generateNativePluginsForAssembliesProcessors;\n        }\n\n        private static Processors m_Processors;\n        internal static Processors processors\n        {\n            get\n            {\n                m_Processors = m_Processors ?? new Processors();\n                return m_Processors;\n            }\n            set { m_Processors = value; }\n        }\n\n        [Flags]\n        internal enum BuildCallbacks\n        {\n            None = 0,\n            BuildProcessors = 1,\n            SceneProcessors = 2,\n            BuildTargetProcessors = 4,\n            FilterAssembliesProcessors = 8,\n            ShaderProcessors = 16,\n            BuildPlayerScriptDLLProcessors = 32,\n            UnityLinkerProcessors = 64,\n            GenerateNativePluginsForAssembliesProcessors = 128,\n            ComputeShaderProcessors = 256\n        }\n\n        //common comparer for all callback types\n        internal static int CompareICallbackOrder(IOrderedCallback a, IOrderedCallback b)\n        {\n            return a.callbackOrder.CompareTo(b.callbackOrder);\n        }\n\n        static void AddToList<T>(object o, ref List<T> list) where T : class\n        {\n            T inst = o as T;\n            if (inst == null)\n                return;\n            if (list == null)\n                list = new List<T>();\n            list.Add(inst);\n        }\n\n        static void AddToListIfTypeImplementsInterface<T>(Type t, ref object o, ref List<T> list) where T : class\n        {\n            if (!ValidateType<T>(t))\n                return;\n\n            if (o == null)\n                o = Activator.CreateInstance(t);\n            AddToList(o, ref list);\n        }\n\n        private class AttributeCallbackWrapper : IPostprocessBuildWithReport, IProcessSceneWithReport, IActiveBuildTargetChanged\n        {\n            internal int m_callbackOrder;\n            internal MethodInfo m_method;\n\n            public int callbackOrder { get { return m_callbackOrder; } }\n\n            public AttributeCallbackWrapper(MethodInfo m)\n            {\n                m_callbackOrder = ((CallbackOrderAttribute)Attribute.GetCustomAttribute(m, typeof(CallbackOrderAttribute))).callbackOrder;\n                m_method = m;\n            }\n\n            public void OnActiveBuildTargetChanged(BuildTarget previousTarget, BuildTarget newTarget)\n            {\n                m_method.Invoke(null, new object[] { previousTarget, newTarget });\n            }\n\n            public void OnPostprocessBuild(BuildReport report)\n            {\n                m_method.Invoke(null, new object[] { report.summary.platform, report.summary.outputPath });\n            }\n\n            public void OnProcessScene(UnityEngine.SceneManagement.Scene scene, BuildReport report)\n            {\n                m_method.Invoke(null, null);\n            }\n        }\n\n        //this variable is reinitialized on domain reload so any calls to Init after a domain reload will set things up correctly\n        static BuildCallbacks previousFlags = BuildCallbacks.None;\n        [RequiredByNativeCode]\n        internal static void InitializeBuildCallbacks(BuildCallbacks findFlags)\n        {\n            if (findFlags == previousFlags)\n                return;\n\n            CleanupBuildCallbacks();\n            previousFlags = findFlags;\n\n            bool findBuildProcessors = (findFlags & BuildCallbacks.BuildProcessors) == BuildCallbacks.BuildProcessors;\n            bool findSceneProcessors = (findFlags & BuildCallbacks.SceneProcessors) == BuildCallbacks.SceneProcessors;\n            bool findTargetProcessors = (findFlags & BuildCallbacks.BuildTargetProcessors) == BuildCallbacks.BuildTargetProcessors;\n            bool findFilterProcessors = (findFlags & BuildCallbacks.FilterAssembliesProcessors) == BuildCallbacks.FilterAssembliesProcessors;\n            bool findShaderProcessors = (findFlags & BuildCallbacks.ShaderProcessors) == BuildCallbacks.ShaderProcessors;\n            bool findComputeShaderProcessors = (findFlags & BuildCallbacks.ComputeShaderProcessors) == BuildCallbacks.ComputeShaderProcessors;\n            bool findBuildPlayerScriptDLLsProcessors = (findFlags & BuildCallbacks.BuildPlayerScriptDLLProcessors) == BuildCallbacks.BuildPlayerScriptDLLProcessors;\n            bool findUnityLinkerProcessors = (findFlags & BuildCallbacks.UnityLinkerProcessors) == BuildCallbacks.UnityLinkerProcessors;\n            bool findGenerateNativePluginsForAssembliesProcessors = (findFlags & BuildCallbacks.GenerateNativePluginsForAssembliesProcessors) == BuildCallbacks.GenerateNativePluginsForAssembliesProcessors;\n\n            var postProcessBuildAttributeParams = new Type[] { typeof(BuildTarget), typeof(string) };\n            foreach (var t in TypeCache.GetTypesDerivedFrom<IOrderedCallback>())\n            {\n                if (t.IsAbstract || t.IsInterface)\n                    continue;\n\n                // Defer creating the instance until we actually add it to one of the lists\n                object instance = null;\n\n                if (findBuildProcessors)\n                {\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.buildPlayerProcessors);\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.buildPreprocessors);\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.buildPreprocessorsWithReport);\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.buildPostprocessors);\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.buildPostprocessorsWithReport);\n                }\n\n                if (findSceneProcessors)\n                {\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.sceneProcessors);\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.sceneProcessorsWithReport);\n                }\n\n                if (findTargetProcessors)\n                {\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.buildTargetProcessors);\n                }\n\n                if (findFilterProcessors)\n                {\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.filterBuildAssembliesProcessor);\n                }\n\n                if (findUnityLinkerProcessors)\n                {\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.unityLinkerProcessors);\n                }\n\n                if (findGenerateNativePluginsForAssembliesProcessors)\n                {\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.generateNativePluginsForAssembliesProcessors);\n                }\n\n                if (findShaderProcessors)\n                {\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.shaderProcessors);\n                }\n\n                if (findComputeShaderProcessors)\n                {\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.computeShaderProcessors);\n                }\n\n                if (findBuildPlayerScriptDLLsProcessors)\n                {\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.buildPlayerScriptDLLProcessors);\n                }\n            }\n\n            if (findBuildProcessors)\n            {\n                foreach (var m in EditorAssemblies.GetAllMethodsWithAttribute<Callbacks.PostProcessBuildAttribute>())\n                    if (ValidateMethod<Callbacks.PostProcessBuildAttribute>(m, postProcessBuildAttributeParams))\n                        AddToList(new AttributeCallbackWrapper(m), ref processors.buildPostprocessorsWithReport);\n            }\n\n            if (findSceneProcessors)\n            {\n                foreach (var m in EditorAssemblies.GetAllMethodsWithAttribute<Callbacks.PostProcessSceneAttribute>())\n                    if (ValidateMethod<Callbacks.PostProcessSceneAttribute>(m, Type.EmptyTypes))\n                        AddToList(new AttributeCallbackWrapper(m), ref processors.sceneProcessorsWithReport);\n            }\n\n            processors.buildPlayerProcessors?.Sort(CompareICallbackOrder);\n            if (processors.buildPreprocessors != null)\n                processors.buildPreprocessors.Sort(CompareICallbackOrder);\n            if (processors.buildPreprocessorsWithReport != null)\n                processors.buildPreprocessorsWithReport.Sort(CompareICallbackOrder);\n            if (processors.buildPostprocessors != null)\n                processors.buildPostprocessors.Sort(CompareICallbackOrder);\n            if (processors.buildPostprocessorsWithReport != null)\n                processors.buildPostprocessorsWithReport.Sort(CompareICallbackOrder);\n            if (processors.buildTargetProcessors != null)\n                processors.buildTargetProcessors.Sort(CompareICallbackOrder);\n            if (processors.sceneProcessors != null)\n                processors.sceneProcessors.Sort(CompareICallbackOrder);\n            if (processors.sceneProcessorsWithReport != null)\n                processors.sceneProcessorsWithReport.Sort(CompareICallbackOrder);\n            if (processors.filterBuildAssembliesProcessor != null)\n                processors.filterBuildAssembliesProcessor.Sort(CompareICallbackOrder);\n            if (processors.unityLinkerProcessors != null)\n                processors.unityLinkerProcessors.Sort(CompareICallbackOrder);\n            if (processors.generateNativePluginsForAssembliesProcessors != null)\n                processors.generateNativePluginsForAssembliesProcessors.Sort(CompareICallbackOrder);\n            if (processors.shaderProcessors != null)\n                processors.shaderProcessors.Sort(CompareICallbackOrder);\n            if (processors.computeShaderProcessors != null)\n                processors.computeShaderProcessors.Sort(CompareICallbackOrder);\n            if (processors.buildPlayerScriptDLLProcessors != null)\n                processors.buildPlayerScriptDLLProcessors.Sort(CompareICallbackOrder);\n        }\n\n        internal static bool ValidateType<T>(Type t)\n        {\n            return (typeof(T).IsAssignableFrom(t) && t != typeof(AttributeCallbackWrapper));\n        }\n\n        static bool ValidateMethod<T>(MethodInfo method, Type[] expectedArguments)\n        {\n            Type attribute = typeof(T);\n            if (method.IsDefined(attribute, false))\n            {\n                // Remove the `Attribute` from the name.\n                if (!method.IsStatic)\n                {\n                    string atributeName = attribute.Name.Replace(\"Attribute\", \"\");\n                    Debug.LogErrorFormat(\"Method {0} with {1} attribute must be static.\", method.Name, atributeName);\n                    return false;\n                }\n\n                if (method.IsGenericMethod || method.IsGenericMethodDefinition)\n                {\n                    string atributeName = attribute.Name.Replace(\"Attribute\", \"\");\n                    Debug.LogErrorFormat(\"Method {0} with {1} attribute cannot be generic.\", method.Name, atributeName);\n                    return false;\n                }\n\n                var parameters = method.GetParameters();\n                bool signatureCorrect = parameters.Length == expectedArguments.Length;\n                if (signatureCorrect)\n                {\n                    // Check types match\n                    for (int i = 0; i < parameters.Length; ++i)\n                    {\n                        if (parameters[i].ParameterType != expectedArguments[i])\n                        {\n                            signatureCorrect = false;\n                            break;\n                        }\n                    }\n                }\n\n                if (!signatureCorrect)\n                {\n                    string atributeName = attribute.Name.Replace(\"Attribute\", \"\");\n                    string expectedArgumentsString = \"static void \" + method.Name + \"(\";\n\n                    for (int i = 0; i < expectedArguments.Length; ++i)\n                    {\n                        expectedArgumentsString += expectedArguments[i].Name;\n                        if (i != expectedArguments.Length - 1)\n                            expectedArgumentsString += \", \";\n                    }\n                    expectedArgumentsString += \")\";\n\n                    Debug.LogErrorFormat(\"Method {0} with {1} attribute does not have the correct signature, expected: {2}.\", method.Name, atributeName, expectedArgumentsString);\n                    return false;\n                }\n                return true;\n            }\n            return false;\n        }\n\n        private static bool InvokeCallbackInterfacesPair<T1, T2>(List<T1> oneInterfaces, Action<T1> invocationOne, List<T2> twoInterfaces, Action<T2> invocationTwo, bool exitOnFailure) where T1 : IOrderedCallback where T2 : IOrderedCallback\n        {\n            if (oneInterfaces == null && twoInterfaces == null)\n                return true;\n\n            // We want to walk both interface lists and invoke the callbacks, but if we just did the whole of list 1 followed by the whole of list 2, the ordering would be wrong.\n            // So, we have to walk both lists simultaneously, calling whichever callback has the lower ordering value\n            IEnumerator<T1> e1 = (oneInterfaces != null) ? (IEnumerator<T1>)oneInterfaces.GetEnumerator() : null;\n            IEnumerator<T2> e2 = (twoInterfaces != null) ? (IEnumerator<T2>)twoInterfaces.GetEnumerator() : null;\n            if (e1 != null && !e1.MoveNext())\n                e1 = null;\n            if (e2 != null && !e2.MoveNext())\n                e2 = null;\n\n            while (e1 != null || e2 != null)\n            {\n                try\n                {\n                    if (e1 != null && (e2 == null || e1.Current.callbackOrder < e2.Current.callbackOrder))\n                    {\n                        var callback = e1.Current;\n                        if (!e1.MoveNext())\n                            e1 = null;\n                        invocationOne(callback);\n                    }\n                    else if (e2 != null)\n                    {\n                        var callback = e2.Current;\n                        if (!e2.MoveNext())\n                            e2 = null;\n                        invocationTwo(callback);\n                    }\n                }\n                catch (TargetInvocationException e)\n                {\n                    // Note: Attribute based callbacks are called via reflection.\n                    // Exceptions in those calls are wrapped in TargetInvocationException\n                    Debug.LogException(e.InnerException);\n                    if (exitOnFailure)\n                        return false;\n                }\n                catch (Exception e)\n                {\n                    Debug.LogException(e);\n                    if (exitOnFailure)\n                        return false;\n                }\n            }\n\n            return true;\n        }\n\n        internal static void PreparePlayerBuild(BuildPlayerContext context)\n        {\n            foreach (var p in processors.buildPlayerProcessors ?? new List<BuildPlayerProcessor>())\n                p.PrepareForBuild(context);\n        }\n\n        [RequiredByNativeCode]\n        internal static void OnBuildPreProcess(BuildReport report)\n        {\n#pragma warning disable 618\n            InvokeCallbackInterfacesPair(\n                processors.buildPreprocessors, bpp => bpp.OnPreprocessBuild(report.summary.platform, report.summary.outputPath),\n                processors.buildPreprocessorsWithReport, bpp => bpp.OnPreprocessBuild(report),\n                (report.summary.options & BuildOptions.StrictMode) != 0 || (report.summary.assetBundleOptions & BuildAssetBundleOptions.StrictMode) != 0);\n#pragma warning restore 618\n\n            // NOTE: This is a workaround for PLAT-11795.\n            // Sometimes, when a player settings override is modified in one of the callbacks, its internal\n            // serialized version is not updated prior to the build. As a result it will be restored to the\n            // serialized values. To avoid that situation we force the update here.\n            var profile = BuildProfile.GetActiveBuildProfile();\n            if (profile != null)\n                profile.SerializePlayerSettings();\n        }\n\n        [RequiredByNativeCode]\n        internal static void OnSceneProcess(UnityEngine.SceneManagement.Scene scene, BuildReport report)\n        {\n#pragma warning disable 618\n            InvokeCallbackInterfacesPair(\n                processors.sceneProcessors, spp =>\n                {\n                    using (new EditorPerformanceMarker($\"{spp.GetType().Name}.{nameof(spp.OnProcessScene)}\", spp.GetType()).Auto())\n                        spp.OnProcessScene(scene);\n                },\n                processors.sceneProcessorsWithReport, spp =>\n                {\n                    using (new EditorPerformanceMarker($\"{spp.GetType().Name}.{nameof(spp.OnProcessScene)}\", spp.GetType()).Auto())\n                        spp.OnProcessScene(scene, report);\n                },\n                report && ((report.summary.options & BuildOptions.StrictMode) != 0 || (report.summary.assetBundleOptions & BuildAssetBundleOptions.StrictMode) != 0));\n#pragma warning restore 618\n        }\n\n        [RequiredByNativeCode]\n        internal static Hash128 OnSceneProcess_HashVersion()\n        {\n            Hash128 hashVersion = new Hash128();\n\n            Type versionAttrribute = typeof(BuildCallbackVersionAttribute);\n#pragma warning disable 618\n            if (processors.sceneProcessors != null)\n            {\n                foreach (IProcessScene processor in processors.sceneProcessors)\n                {\n                    Type processorType = processor.GetType();\n                    hashVersion.Append(processorType.AssemblyQualifiedName);\n\n                    BuildCallbackVersionAttribute attribute = Attribute.GetCustomAttribute(processorType, versionAttrribute, false) as BuildCallbackVersionAttribute;\n                    hashVersion.Append(attribute != null ? attribute.Version : 1);\n                }\n            }\n#pragma warning restore 618\n\n            if (processors.sceneProcessorsWithReport != null)\n            {\n                foreach (IProcessSceneWithReport processor in processors.sceneProcessorsWithReport)\n                {\n                    Type processorType = processor.GetType();\n                    hashVersion.Append(processorType.AssemblyQualifiedName);\n\n                    BuildCallbackVersionAttribute attribute = Attribute.GetCustomAttribute(processorType, versionAttrribute, false) as BuildCallbackVersionAttribute;\n                    hashVersion.Append(attribute != null ? attribute.Version : 1);\n                }\n            }\n            return hashVersion;\n        }\n\n        [RequiredByNativeCode]\n        internal static void OnBuildPostProcess(BuildReport report)\n        {\n#pragma warning disable 618\n            InvokeCallbackInterfacesPair(\n                processors.buildPostprocessors, bpp => bpp.OnPostprocessBuild(report.summary.platform, report.summary.outputPath),\n                processors.buildPostprocessorsWithReport, bpp => bpp.OnPostprocessBuild(report),\n                (report.summary.options & BuildOptions.StrictMode) != 0 || (report.summary.assetBundleOptions & BuildAssetBundleOptions.StrictMode) != 0);\n#pragma warning restore 618\n        }\n\n\n        // Some platforms like Desktop, instead of launching the app via C#, perform their launch in C++\n        // See BuildPlayer.cpp LaunchPlayerIfSupported, which calls native LaunchApplication\n        // Internal_OnPostprocessLaunch is used by this code path\n        [RequiredByNativeCode]\n        internal static void Internal_OnPostprocessLaunch(BuildTarget buildTarget, bool success)\n        {\n            OnPostprocessLaunch(new DefaultLaunchReport(NamedBuildTarget.FromActiveSettings(buildTarget), success ? LaunchResult.Succeeded : LaunchResult.Failed));\n        }\n\n        internal static void OnPostprocessLaunch(ILaunchReport launchReport)\n        {\n            // Domain reload happens after player build, so anything collected in InitializeBuildCallbacks gets invalidated\n            // Thus collect callbacks here as necessary\n            if (processors.launchPostprocessors == null)\n            {\n                foreach (var t in TypeCache.GetTypesDerivedFrom<IPostprocessLaunch>())\n                {\n                    if (t.IsAbstract || t.IsInterface)\n                        continue;\n\n                    object instance = null;\n                    AddToListIfTypeImplementsInterface(t, ref instance, ref processors.launchPostprocessors);\n                }\n\n                processors?.launchPostprocessors?.Sort(CompareICallbackOrder);\n            }\n\n            if (processors.launchPostprocessors == null)\n                return;\n\n            foreach (var run in processors.launchPostprocessors)\n            {\n                try\n                {\n                    run.OnPostprocessLaunch(launchReport);\n                }\n                catch (Exception e)\n                {\n                    Debug.LogException(e);\n                }\n            }\n        }\n\n        [RequiredByNativeCode]\n        internal static void OnActiveBuildTargetChanged(BuildTarget previousPlatform, BuildTarget newPlatform)\n        {\n            if (processors.buildTargetProcessors != null)\n            {\n                foreach (IActiveBuildTargetChanged abtc in processors.buildTargetProcessors)\n                {\n                    try\n                    {\n                        abtc.OnActiveBuildTargetChanged(previousPlatform, newPlatform);\n                    }\n                    catch (Exception e)\n                    {\n                        Debug.LogException(e);\n                    }\n                }\n            }\n        }\n\n        [RequiredByNativeCode]\n        internal static ShaderCompilerData[] OnPreprocessShaders(Shader shader, ShaderSnippetData snippet, ShaderCompilerData[] data)\n        {\n            var dataList = data.ToList();\n            if (processors.shaderProcessors != null)\n            {\n                foreach (IPreprocessShaders abtc in processors.shaderProcessors)\n                {\n                    abtc.OnProcessShader(shader, snippet, dataList);\n                }\n            }\n            return dataList.ToArray();\n        }\n\n        [RequiredByNativeCode]\n        internal static ShaderCompilerData[] OnPreprocessComputeShaders(ComputeShader shader, string kernelName, ShaderCompilerData[] data)\n        {\n            var dataList = data.ToList();\n            if (processors.computeShaderProcessors != null)\n            {\n                foreach (IPreprocessComputeShaders abtc in processors.computeShaderProcessors)\n                {\n                    try\n                    {\n                        abtc.OnProcessComputeShader(shader, kernelName, dataList);\n                    }\n                    catch (Exception e)\n                    {\n                        Debug.LogException(e);\n                    }\n                }\n            }\n            return dataList.ToArray();\n        }\n\n        [RequiredByNativeCode]\n        internal static bool HasOnPostBuildPlayerScriptDLLs()\n        {\n            return (processors.buildPlayerScriptDLLProcessors != null && processors.buildPlayerScriptDLLProcessors.Any());\n        }\n\n        [RequiredByNativeCode]\n        internal static void OnPostBuildPlayerScriptDLLs(BuildReport report)\n        {\n            if (processors.buildPlayerScriptDLLProcessors != null)\n            {\n                foreach (var step in processors.buildPlayerScriptDLLProcessors)\n                {\n                    try\n                    {\n                        step.OnPostBuildPlayerScriptDLLs(report);\n                    }\n                    catch (Exception e)\n                    {\n                        Debug.LogException(e);\n                        if ((report.summary.options & BuildOptions.StrictMode) != 0 || (report.summary.assetBundleOptions & BuildAssetBundleOptions.StrictMode) != 0)\n                            return;\n                    }\n                }\n            }\n        }\n\n        [RequiredByNativeCode]\n        internal static string[] FilterAssembliesIncludedInBuild(BuildOptions buildOptions, string[] assemblies)\n        {\n            if (processors.filterBuildAssembliesProcessor == null)\n            {\n                return assemblies;\n            }\n\n            string[] startAssemblies = assemblies;\n            string[] filteredAssemblies = assemblies;\n\n\n            foreach (var filteredAssembly in processors.filterBuildAssembliesProcessor)\n            {\n                int assemblyCount = filteredAssemblies.Length;\n                filteredAssemblies = filteredAssembly.OnFilterAssemblies(buildOptions, filteredAssemblies);\n                if (filteredAssemblies.Length > assemblyCount)\n                {\n                    throw new Exception(\"More Assemblies in the list than delivered. Only filtering, not adding extra assemblies\");\n                }\n            }\n\n            if (!filteredAssemblies.All(x => startAssemblies.Contains(x)))\n            {\n                throw new Exception(\"New Assembly names are in the list. Only filtering are allowed\");\n            }\n\n            return filteredAssemblies;\n        }\n\n        [RequiredByNativeCode]\n        internal static void CleanupBuildCallbacks()\n        {\n            processors.buildTargetProcessors = null;\n            processors.buildPlayerProcessors = null;\n            processors.buildPreprocessors = null;\n            processors.buildPostprocessors = null;\n            processors.sceneProcessors = null;\n            processors.buildPreprocessorsWithReport = null;\n            processors.buildPostprocessorsWithReport = null;\n            processors.sceneProcessorsWithReport = null;\n            processors.filterBuildAssembliesProcessor = null;\n            processors.unityLinkerProcessors = null;\n            processors.generateNativePluginsForAssembliesProcessors = null;\n            processors.shaderProcessors = null;\n            processors.computeShaderProcessors = null;\n            processors.buildPlayerScriptDLLProcessors = null;\n            previousFlags = BuildCallbacks.None;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/BuildPlatform.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing System.Collections.Generic;\nusing DiscoveredTargetInfo = UnityEditor.BuildTargetDiscovery.DiscoveredTargetInfo;\nusing TargetAttributes = UnityEditor.BuildTargetDiscovery.TargetAttributes;\n\nnamespace UnityEditor.Build\n{\n    // All settings for a build platform.\n    internal class BuildPlatform : ICloneable\n    {\n        // short name used for texture settings, etc.\n        public string name;\n        public NamedBuildTarget namedBuildTarget;\n        public bool installed;\n        public bool hideInUi;\n        public string tooltip;\n        public BuildTarget defaultTarget;\n\n        // TODO: Some packages are still using targetGroup, so we keep it here as a getter for compatibility\n        public BuildTargetGroup targetGroup => namedBuildTarget.ToBuildTargetGroup();\n\n        string m_LocTitle;\n        string m_IconId;\n\n        ScalableGUIContent m_Title;\n        ScalableGUIContent m_SmallTitle;\n\n        Texture2D m_CompoundSmallIcon;\n        Texture2D m_CompoundSmallIconForQualitySettings;\n        string m_CompoundTooltip;\n        ScalableGUIContent m_CompoundTitle;\n\n        IEnumerable<BuildPlatform> m_DerivedPlatforms;\n\n        public GUIContent title => m_CompoundTitle ?? m_Title;\n        public Texture2D smallIcon => ((GUIContent)m_SmallTitle).image as Texture2D;\n\n        public Texture2D compoundSmallIcon => GetCompoundSmallIcon();\n        public Texture2D compoundSmallIconForQualitySettings => GetCompoundSmallIconForQualitySettings();\n        public string compoundTooltip => m_CompoundTooltip ?? tooltip;\n\n        public BuildPlatform(string locTitle, string iconId, NamedBuildTarget namedBuildTarget, BuildTarget defaultTarget, bool hideInUi, bool installed)\n            : this(locTitle, \"\", iconId, namedBuildTarget, defaultTarget, hideInUi, installed)\n        {\n        }\n\n        public BuildPlatform(string locTitle, string tooltip, string iconId, NamedBuildTarget namedBuildTarget, BuildTarget defaultTarget, bool hideInUi, bool installed)\n        {\n            this.namedBuildTarget = namedBuildTarget;\n            name = namedBuildTarget.TargetName;\n\n            m_IconId = iconId;\n            m_LocTitle = locTitle;\n            m_Title = CreateTitle(locTitle, iconId);\n\n            m_SmallTitle = new ScalableGUIContent(null, null, iconId + \".Small\");\n            this.tooltip = tooltip;\n            this.hideInUi = hideInUi;\n            this.defaultTarget = defaultTarget;\n            this.installed = installed;\n        }\n\n        public object Clone()\n        {\n            return MemberwiseClone();\n        }\n\n        Texture2D GetCompoundSmallIcon()\n        {\n            GenerateCompoundData();\n            return m_CompoundSmallIcon == null ? smallIcon : m_CompoundSmallIcon;\n        }\n\n        Texture2D GetCompoundSmallIconForQualitySettings()\n        {\n            GenerateCompoundData();\n            return m_CompoundSmallIconForQualitySettings == null ? smallIcon : m_CompoundSmallIconForQualitySettings;\n        }\n\n        void GenerateCompoundData()\n        {\n            if (m_DerivedPlatforms != null && (m_CompoundSmallIcon == null || m_CompoundSmallIconForQualitySettings == null))\n            {\n                GenerateCompoundTooltip(m_DerivedPlatforms);\n                GenerateCompoundTitle(m_DerivedPlatforms);\n                GenerateCompoundIconTexture(m_DerivedPlatforms);\n            }\n        }\n\n        internal void SetDerivedPlatforms(IEnumerable<BuildPlatform> derivedPlatforms)\n        {\n            m_DerivedPlatforms = derivedPlatforms;\n        }\n\n        static ScalableGUIContent CreateTitle(string locTitle, string iconId)\n        {\n            // Workaround for some platforms which have | in their name which is also used as separator for tooltips\n            const string TooltipSeparator = \"|\";\n            if (locTitle.Contains(TooltipSeparator))\n                return new ScalableGUIContent(locTitle.Replace(TooltipSeparator, \" \"), null, iconId);\n            else\n                return new ScalableGUIContent(locTitle, null, iconId);\n        }\n\n        void GenerateCompoundIconTexture(IEnumerable<BuildPlatform> derivedPlatforms)\n        {\n            static Texture2D DuplicateAsReadableTexture(Texture2D sourceTexture)\n            {\n                var renderTexture = RenderTexture.GetTemporary(sourceTexture.width, sourceTexture.height,\n                    0, RenderTextureFormat.Default, RenderTextureReadWrite.Linear);\n                Graphics.Blit(sourceTexture, renderTexture);\n                var previouslyActiveRenderTexture = RenderTexture.active;\n                RenderTexture.active = renderTexture;\n                var readableTexture = new Texture2D(sourceTexture.width, sourceTexture.height);\n                readableTexture.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);\n                readableTexture.pixelsPerPoint = sourceTexture.pixelsPerPoint;\n                readableTexture.Apply();\n                RenderTexture.active = previouslyActiveRenderTexture;\n                RenderTexture.ReleaseTemporary(renderTexture);\n                return readableTexture;\n            }\n\n            static void ClearTexture(Texture2D texture)\n            {\n                Color TransparentBlack = new(0, 0, 0, 0);\n                for (int y = 0; y < texture.height; y++)\n                {\n                    for (int x = 0; x < texture.width; x++)\n                    {\n                        texture.SetPixel(x, y, TransparentBlack);\n                    }\n                }\n            }\n\n            var readableSmallIcon = DuplicateAsReadableTexture(smallIcon);\n            var qualityIconWidth = readableSmallIcon.width;\n            var qualityIconHeight = readableSmallIcon.height;\n            var compoundIconWidth = readableSmallIcon.width;\n            var compoundIconHeight = readableSmallIcon.height;\n            var horizontalGapSize = (int)Math.Round(4 * readableSmallIcon.pixelsPerPoint);\n            var verticalGapSize = (int)Math.Round(2 * readableSmallIcon.pixelsPerPoint);\n            foreach (var derivedPlatform in derivedPlatforms)\n            {\n                var derivedSmallIcon = derivedPlatform.smallIcon;\n                compoundIconWidth += horizontalGapSize;\n                qualityIconHeight += verticalGapSize;\n                compoundIconHeight = Math.Max(compoundIconHeight, derivedSmallIcon.height);\n                compoundIconWidth += derivedSmallIcon.width;\n                qualityIconHeight += derivedSmallIcon.height;\n            }\n            var qualityTexture = new Texture2D(qualityIconWidth, qualityIconHeight, readableSmallIcon.format, false);\n            var texture = new Texture2D(compoundIconWidth, compoundIconHeight, readableSmallIcon.format, false);\n            ClearTexture(qualityTexture);\n            ClearTexture(texture);\n            var compoundIconXPosition = 0;\n            var qualityIconYPosition = qualityIconHeight - readableSmallIcon.height;\n            texture.CopyPixels(readableSmallIcon, 0, 0, 0, 0, readableSmallIcon.width, readableSmallIcon.height, 0, compoundIconXPosition, 0);\n            qualityTexture.CopyPixels(readableSmallIcon, 0, 0, 0, 0, readableSmallIcon.width, readableSmallIcon.height, 0, 0, qualityIconYPosition);\n            compoundIconXPosition += readableSmallIcon.width;\n            qualityIconYPosition -= verticalGapSize;\n            foreach (var derivedPlatform in derivedPlatforms)\n            {\n                var readableDerivedSmallIcon = DuplicateAsReadableTexture(derivedPlatform.smallIcon);\n                compoundIconXPosition += horizontalGapSize;\n                qualityIconYPosition -= readableDerivedSmallIcon.height;\n                texture.CopyPixels(readableDerivedSmallIcon, 0, 0, 0, 0, readableDerivedSmallIcon.width, readableDerivedSmallIcon.height, 0, compoundIconXPosition, 0);\n                qualityTexture.CopyPixels(readableDerivedSmallIcon, 0, 0, 0, 0, readableDerivedSmallIcon.width, readableDerivedSmallIcon.height, 0, 0, qualityIconYPosition);\n                compoundIconXPosition += readableDerivedSmallIcon.width;\n                qualityIconYPosition -= verticalGapSize;\n            }\n            texture.pixelsPerPoint = readableSmallIcon.pixelsPerPoint;\n            texture.Apply();\n            qualityTexture.pixelsPerPoint = readableSmallIcon.pixelsPerPoint;\n            qualityTexture.Apply();\n            m_CompoundSmallIcon = texture;\n            m_CompoundSmallIconForQualitySettings = qualityTexture;\n        }\n\n        void GenerateCompoundTooltip(IEnumerable<BuildPlatform> derivedPlatforms)\n        {\n            var ttip = m_LocTitle;\n            foreach (var derivedPlatform in derivedPlatforms)\n            {\n                ttip += $\", {derivedPlatform.m_LocTitle}\";\n            }\n            ttip += \" settings\";\n            m_CompoundTooltip = ttip;\n        }\n\n        void GenerateCompoundTitle(IEnumerable<BuildPlatform> derivedPlatforms)\n        {\n            var title = m_LocTitle;\n            foreach (var derivedPlatform in derivedPlatforms)\n            {\n                title += $\", {derivedPlatform.m_LocTitle}\";\n            }\n            m_CompoundTitle = CreateTitle(title, m_IconId);\n        }\n    }\n\n    internal class BuildPlatformWithSubtarget : BuildPlatform\n    {\n        public int subtarget;\n\n        public BuildPlatformWithSubtarget(string locTitle, string tooltip, string iconId, NamedBuildTarget namedBuildTarget, BuildTarget defaultTarget, int subtarget, bool hideInUi, bool installed)\n            : base(locTitle, tooltip, iconId, namedBuildTarget, defaultTarget, hideInUi, installed)\n        {\n            this.subtarget = subtarget;\n            name = namedBuildTarget.TargetName;\n        }\n    }\n\n    internal class BuildPlatforms\n    {\n        static readonly BuildPlatforms s_Instance = new BuildPlatforms();\n\n        public static BuildPlatforms instance => s_Instance;\n\n        internal BuildPlatforms()\n        {\n            List<BuildPlatform> buildPlatformsList = new List<BuildPlatform>();\n            DiscoveredTargetInfo[] buildTargets = BuildTargetDiscovery.GetBuildTargetInfoList();\n\n            // Standalone needs to be first\n            // Before we had BuildTarget.StandaloneWindows for BuildPlatform.defaultTarget\n            // But that doesn't make a lot of sense, as editor use it in places, so it should agree with editor platform\n            // TODO: should we poke module manager for target support? i think we can assume support for standalone for editor platform\n            // TODO: even then - picking windows standalone unconditionally wasn't much better\n            BuildTarget standaloneTarget = BuildTarget.StandaloneWindows;\n            if (Application.platform == RuntimePlatform.OSXEditor)\n                standaloneTarget = BuildTarget.StandaloneOSX;\n            else if (Application.platform == RuntimePlatform.LinuxEditor)\n                standaloneTarget = BuildTarget.StandaloneLinux64;\n\n            buildPlatformsList.Add(new BuildPlatformWithSubtarget(BuildPipeline.GetBuildTargetGroupDisplayName(BuildTargetGroup.Standalone), \"\", \"BuildSettings.Standalone\",\n                NamedBuildTarget.Standalone, standaloneTarget, (int)StandaloneBuildSubtarget.Player, false, true));\n\n            // TODO: We should consider extend BuildTargetDiscovery to support named targets and subtargets,\n            // specially if at some point other platforms use them.\n            // The installed value is set by the linux, mac or win ExtensionModule.cs when they are loaded.\n            buildPlatformsList.Add(new BuildPlatformWithSubtarget(\"Dedicated Server\", \"\", \"BuildSettings.DedicatedServer\",\n                NamedBuildTarget.Server, standaloneTarget, (int)StandaloneBuildSubtarget.Server, false, false));\n\n            foreach (var target in buildTargets)\n            {\n                if (!target.HasFlag(TargetAttributes.IsStandalonePlatform))\n                {\n                    NamedBuildTarget namedBuildTarget = NamedBuildTarget.FromBuildTargetGroup(BuildPipeline.GetBuildTargetGroup(target.buildTargetPlatformVal));\n                    var buildPlatform = new BuildPlatform(\n                        BuildPipeline.GetBuildTargetGroupDisplayName(namedBuildTarget.ToBuildTargetGroup()),\n                        target.iconName,\n                        namedBuildTarget,\n                        target.buildTargetPlatformVal,\n                        hideInUi: target.HasFlag(TargetAttributes.HideInUI),\n                        installed: BuildPipeline.GetPlaybackEngineDirectory(target.buildTargetPlatformVal, BuildOptions.None, false) != string.Empty);\n                    buildPlatformsList.Add(buildPlatform);\n                    var derivedBuildTargets = BuildTargetDiscovery.GetDerivedBuildTargetInfoList(target.buildTargetPlatformVal);\n                    if (derivedBuildTargets.Length > 0)\n                    {\n                        var derivedBuildPlatforms = new List<BuildPlatform>();\n                        foreach (var derivedTarget in derivedBuildTargets)\n                        {\n                            derivedBuildPlatforms.Add(new BuildPlatform(\n                                derivedTarget.niceName,\n                                derivedTarget.iconName,\n                                namedBuildTarget,\n                                target.buildTargetPlatformVal,\n                                hideInUi: target.HasFlag(TargetAttributes.HideInUI),\n                                installed: BuildPipeline.GetPlaybackEngineDirectory(target.buildTargetPlatformVal, BuildOptions.None, false) != string.Empty));\n                        }\n                        buildPlatform.SetDerivedPlatforms(derivedBuildPlatforms);\n                    }\n                }\n            }\n\n            foreach (var buildPlatform in buildPlatformsList)\n            {\n                buildPlatform.tooltip = buildPlatform.title.text + \" settings\";\n            }\n\n            buildPlatforms = buildPlatformsList.ToArray();\n        }\n\n        public BuildPlatform[] buildPlatforms;\n\n        public string GetBuildTargetDisplayName(BuildTargetGroup buildTargetGroup, BuildTarget target, int subtarget)\n        {\n            if (buildTargetGroup == BuildTargetGroup.Standalone && subtarget == (int)StandaloneBuildSubtarget.Server)\n                return GetBuildTargetDisplayName(NamedBuildTarget.Server, target);\n\n            return GetBuildTargetDisplayName(NamedBuildTarget.FromBuildTargetGroup(buildTargetGroup), target);\n        }\n\n        public string GetBuildTargetDisplayName(NamedBuildTarget namedBuildTarget, BuildTarget target)\n        {\n            foreach (BuildPlatform cur in buildPlatforms)\n            {\n                if (cur.defaultTarget == target && cur.namedBuildTarget == namedBuildTarget)\n                    return cur.title.text;\n            }\n\n#pragma warning disable CS0618 // Member is obsolete\n            string targetName = BuildTargetDiscovery.BuildPlatformDisplayName(namedBuildTarget, target);\n#pragma warning restore CS0618\n            return targetName.Length == 0 ? \"Unsupported Target\" : targetName;\n        }\n\n        public string GetModuleDisplayName(NamedBuildTarget namedBuildTarget, BuildTarget buildTarget)\n        {\n            return GetBuildTargetDisplayName(namedBuildTarget, buildTarget);\n        }\n\n        int BuildPlatformIndexFromNamedBuildTarget(NamedBuildTarget target)\n        {\n            for (int i = 0; i < buildPlatforms.Length; i++)\n                if (target == buildPlatforms[i].namedBuildTarget)\n                    return i;\n            return -1;\n        }\n\n        public BuildPlatform BuildPlatformFromNamedBuildTarget(NamedBuildTarget target)\n        {\n            int index = BuildPlatformIndexFromNamedBuildTarget(target);\n            return index != -1 ? buildPlatforms[index] : null;\n        }\n\n        public List<BuildPlatform> GetValidPlatforms(bool includeMetaPlatforms)\n        {\n            List<BuildPlatform> platforms = new List<BuildPlatform>();\n            foreach (BuildPlatform bp in buildPlatforms)\n                if (bp.namedBuildTarget == NamedBuildTarget.Standalone ||\n                    (bp.installed && BuildPipeline.IsBuildPlatformSupported(bp.defaultTarget)))\n                    platforms.Add(bp);\n\n            return platforms;\n        }\n\n        public List<BuildPlatform> GetValidPlatforms()\n        {\n            return GetValidPlatforms(false);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/BuildPlayerContext.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing NiceIO;\n\nnamespace UnityEditor.Build\n{\n    public sealed class BuildPlayerContext\n    {\n        // Temporary tracking through a global instance\n        internal static BuildPlayerContext ActiveInstance { get; private set; }\n\n        public BuildPlayerOptions BuildPlayerOptions { get; }\n\n        internal BuildPlayerContext(BuildPlayerOptions buildPlayerOptions)\n        {\n            BuildPlayerOptions = buildPlayerOptions;\n            ActiveInstance = this;\n        }\n\n        // Streaming Assets\n        private Dictionary<NPath, NPath> StreamingAssetFiles { get; } = new Dictionary<NPath, NPath>();\n        internal IEnumerable<(NPath dst, NPath src)> StreamingAssets => StreamingAssetFiles.Select(e => (e.Key, e.Value));\n\n        public void AddAdditionalPathToStreamingAssets(string directoryOrFile, string pathInStreamingAssets = null)\n        {\n            NPath sourcePath = directoryOrFile;\n            if (sourcePath.DirectoryExists())\n            {\n                NPath targetPath = pathInStreamingAssets ?? \"\";\n                foreach (var file in sourcePath.Files(true))\n                    AddAdditionalFileToStreamingAssets(file, targetPath.Combine(file.RelativeTo(sourcePath)));\n            }\n            else if (sourcePath.FileExists())\n            {\n                NPath targetPath = pathInStreamingAssets ?? sourcePath.FileName;\n                AddAdditionalFileToStreamingAssets(sourcePath, targetPath);\n            }\n            else\n            {\n                throw new FileNotFoundException(\"No such file or directory.\", sourcePath.ToString());\n            }\n        }\n\n        private void AddAdditionalFileToStreamingAssets(NPath sourceFile, NPath targetPath)\n        {\n            if (StreamingAssetFiles.TryGetValue(targetPath, out var existingValue))\n            {\n                // If someone is adding the same file more than once we ignore subsequent adds\n                if (existingValue == sourceFile)\n                    return;\n\n                // Throw an exception and tell the user what the problem is\n                throw new ArgumentException(\n                    $\"Unable to add '{sourceFile}' to StreamingAssets. An entry for '{targetPath}' has already been added, '{existingValue}'.\");\n            }\n            StreamingAssetFiles.Add(targetPath, sourceFile);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/DataBuildDirtyTracker.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing NiceIO;\nusing UnityEditor.Build.Reporting;\nusing UnityEngine;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Mono.BuildPipeline\n{\n    internal class DataBuildDirtyTracker\n    {\n        [Serializable]\n        class BuildDataInputFile\n        {\n            public string path;\n            public string contentHash;\n\n            public BuildDataInputFile(NPath npath, bool developmentBuild)\n            {\n                path = npath.ToString();\n                if (npath.HasExtension(\"cs\"))\n                {\n                    var monoScript = AssetDatabase.LoadAssetAtPath<MonoScript>(path);\n                    if (monoScript != null)\n                        contentHash = monoScript.GetPropertiesHashString(developmentBuild);\n                }\n                else\n                    contentHash = AssetDatabase.GetAssetDependencyHash(npath.ToString()).ToString();\n            }\n        }\n\n        [Serializable]\n        class BuildData\n        {\n            public BuildDataInputFile[] scenes;\n            public BuildDataInputFile[] inputFiles;\n            public BuildDataInputFile activeBuildProfile;\n            public string[] enabledModules;\n            public string[] resourcePaths;\n            public BuildOptions buildOptions;\n            public string unityVersion;\n\n            // These options could impact the cache data files.\n            public static BuildOptions BuildOptionsMask = BuildOptions.CompressWithLz4 |\n                BuildOptions.ConnectToHost |\n                BuildOptions.ConnectWithProfiler |\n                BuildOptions.UncompressedAssetBundle |\n                BuildOptions.CompressWithLz4HC;\n\n            public string[] assemblyNames;\n        }\n\n        private BuildData buildData;\n        private string[] scenes;\n        private NPath activeBuildProfilePath;\n        public BuildOptions buildOptions;\n        private string[] assemblyNames;\n\n        bool CheckAssetDirty(BuildDataInputFile file)\n        {\n            NPath path = file.path;\n            if (!path.Exists())\n            {\n                Console.WriteLine($\"Rebuilding Data files because {path} is dirty (deleted)\");\n                return true;\n            }\n\n            string contentHash = \"\";\n            if (path.Extension == \"cs\")\n            {\n                var monoScript = AssetDatabase.LoadAssetAtPath<MonoScript>(path.ToString());\n                if (monoScript != null)\n                    contentHash = monoScript.GetPropertiesHashString(buildOptions.HasFlag(BuildOptions.Development));\n            }\n            else\n                contentHash = AssetDatabase.GetAssetDependencyHash(file.path).ToString();\n\n            if (contentHash != file.contentHash)\n            {\n                Console.WriteLine($\"Rebuilding Data files because {path} is dirty (hash)\");\n                return true;\n            }\n\n            return false;\n        }\n\n        bool DoCheckDirty()\n        {\n            if (Application.unityVersion != buildData.unityVersion)\n            {\n                Console.WriteLine($\"Rebuilding Data files because they were built with a different Unity version {Application.unityVersion} vs {buildData.unityVersion}\");\n                return true;\n            }\n\n            if (!scenes.SequenceEqual(buildData.scenes.Select(f => f.path)))\n            {\n                Console.WriteLine(\"Rebuilding Data files because the scene list is dirty\");\n                return true;\n            }\n\n            if ((buildOptions & BuildData.BuildOptionsMask) != buildData.buildOptions)\n            {\n                Console.WriteLine(\"Rebuilding Data files because the build options have changed\");\n                return true;\n            }\n\n            if (!assemblyNames.SequenceEqual(buildData.assemblyNames))\n            {\n                Console.WriteLine(\"Rebuilding Data files because the assembly list is dirty\");\n                return true;\n            }\n\n            if (buildData.inputFiles.Any(CheckAssetDirty))\n                return true;\n\n            var resourcePaths = ResourcesAPIInternal.GetAllPaths(\"\").OrderBy(p => p).ToArray();\n            if (!resourcePaths.SequenceEqual(buildData.resourcePaths))\n            {\n                for (int i = 0; i < resourcePaths.Length || i < buildData.resourcePaths.Length; i++)\n                {\n                    string path;\n                    if (i >= resourcePaths.Length)\n                        path = buildData.resourcePaths[i];\n                    else if (i >= buildData.resourcePaths.Length)\n                        path = resourcePaths[i];\n                    else if (buildData.resourcePaths[i] != resourcePaths[i])\n                        path = resourcePaths[i];\n                    else\n                        continue;\n\n                    Console.WriteLine($\"Rebuilding Data files because {path} is dirty (Resource file added or removed)\");\n                    return true;\n                }\n            }\n\n            var enabledModules = ModuleMetadata.GetModuleNames()\n                .Where(m => ModuleMetadata.GetModuleIncludeSettingForModule(m) != ModuleIncludeSetting.ForceExclude);\n            if (!enabledModules.SequenceEqual(buildData.enabledModules))\n            {\n                Console.WriteLine($\"Rebuilding Data files because enabled modules have changed\");\n                return true;\n            }\n\n            if ((activeBuildProfilePath != buildData.activeBuildProfile.path) || (!string.IsNullOrEmpty(buildData.activeBuildProfile.path) && CheckAssetDirty(buildData.activeBuildProfile)))\n            {\n                Console.WriteLine($\"Rebuilding Data files because the active build profile have changed\");\n                return true;\n            }\n\n            Console.WriteLine(\"Not rebuilding Data files -- no changes\");\n            return false;\n        }\n\n        [RequiredByNativeCode]\n        static public void WriteBuildData(string buildDataPath, BuildReport report, string[] scenes, string[] prefabs, string activeBuildProfilePath, string[] assemblyNames)\n        {\n            var developmentBuild = report.summary.options.HasFlag(BuildOptions.Development);\n            var inputScenes = new List<BuildDataInputFile>();\n            foreach (var scene in scenes)\n                inputScenes.Add(new BuildDataInputFile(scene, developmentBuild));\n\n            var inputFiles = new List<BuildDataInputFile>();\n            foreach (var scene in scenes)\n                inputFiles.Add(new BuildDataInputFile(scene, developmentBuild));\n            foreach (var prefab in prefabs)\n                inputFiles.Add(new BuildDataInputFile(prefab, developmentBuild));\n            foreach (var assetInfo in report.packedAssets.SelectMany(a => a.contents))\n            {\n                if (assetInfo.sourceAssetPath.ToNPath().FileExists() && !assetInfo.sourceAssetPath.StartsWith(\".\"))\n                    inputFiles.Add(new BuildDataInputFile(assetInfo.sourceAssetPath, developmentBuild));\n            }\n            foreach (var projectSetting in new NPath(\"ProjectSettings\").Files(\"*.asset\", true))\n                inputFiles.Add(new BuildDataInputFile(projectSetting, developmentBuild));\n\n            var buildData = new BuildData()\n            {\n                scenes = inputScenes.ToArray(),\n                inputFiles = inputFiles.ToArray(),\n                activeBuildProfile = new BuildDataInputFile(activeBuildProfilePath, developmentBuild),\n                buildOptions = report.summary.options & BuildData.BuildOptionsMask,\n                unityVersion = Application.unityVersion,\n                resourcePaths = ResourcesAPIInternal.GetAllPaths(\"\").OrderBy(p => p).ToArray(),\n                enabledModules = ModuleMetadata.GetModuleNames()\n                    .Where(m => ModuleMetadata.GetModuleIncludeSettingForModule(m) != ModuleIncludeSetting.ForceExclude)\n                    .ToArray(),\n                assemblyNames = assemblyNames.OrderBy(p => p).ToArray()\n            };\n            buildDataPath.ToNPath().WriteAllText(JsonUtility.ToJson(buildData));\n        }\n\n        [RequiredByNativeCode]\n        static public bool CheckDirty(string buildDataPath, BuildOptions buildOptions, string[] scenes, string activeBuildProfilePath, string[] assemblyNames)\n        {\n            NPath buildReportPath = buildDataPath;\n            if (!buildReportPath.FileExists())\n                return true;\n\n            try\n            {\n                DataBuildDirtyTracker tracker = new DataBuildDirtyTracker()\n                {\n                    buildData = JsonUtility.FromJson<BuildData>(buildReportPath.ReadAllText()),\n                    scenes = scenes,\n                    activeBuildProfilePath = activeBuildProfilePath,\n                    buildOptions = buildOptions,\n                    assemblyNames = assemblyNames.OrderBy(p => p).ToArray()\n                };\n                return tracker.DoCheckDirty();\n            }\n            catch (Exception e)\n            {\n                Console.WriteLine($\"Rebuilding Data files because the build data file is corrupt: {e}\");\n                return true;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/DesktopStandaloneBuildWindowExtension.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor;\nusing UnityEditor.Modules;\nusing UnityEditor.Build;\nusing UnityEngine;\n\ninternal abstract class DesktopStandaloneBuildWindowExtension : DefaultBuildWindowExtension\n{\n    private GUIContent m_StandaloneTarget = EditorGUIUtility.TrTextContent(\"Target Platform\", \"Destination platform for standalone build\");\n    private GUIContent m_Architecture = EditorGUIUtility.TrTextContent(\"Architecture\", \"Build m_Architecture for standalone\");\n    private BuildTarget[] m_StandaloneSubtargets;\n    private GUIContent[] m_StandaloneSubtargetStrings;\n\n    protected bool m_HasMonoPlayers;\n    protected bool m_HasIl2CppPlayers;\n    protected bool m_HasCoreCLRPlayers;\n    protected bool m_HasServerMonoPlayers;\n    protected bool m_HasServerIl2CppPlayers;\n    protected bool m_IsRunningOnHostPlatform;\n\n    public bool MonoPlayersInstalled(NamedBuildTarget namedBuildTarget)\n    {\n        return namedBuildTarget == NamedBuildTarget.Server ? m_HasServerMonoPlayers : m_HasMonoPlayers;\n    }\n\n    public bool Il2CppPlayersInstalled(NamedBuildTarget namedBuildTarget)\n    {\n        return namedBuildTarget == NamedBuildTarget.Server ? m_HasServerIl2CppPlayers : m_HasIl2CppPlayers;\n    }\n\n    public static void SetArchitectureForPlatform(BuildTarget buildTarget, OSArchitecture architecture)\n    {\n        EditorUserBuildSettings.SetPlatformSettings(BuildPipeline.GetBuildTargetName(buildTarget), EditorUserBuildSettings.kSettingArchitecture, architecture.ToString().ToLower());\n    }\n\n    public DesktopStandaloneBuildWindowExtension(bool hasMonoPlayers, bool hasIl2CppPlayers, bool hasCoreCLRPlayers, bool hasServerMonoPlayers, bool hasServerIl2CppPlayers)\n    {\n        SetupStandaloneSubtargets();\n\n        m_IsRunningOnHostPlatform = Application.platform == GetHostPlatform();\n        m_HasIl2CppPlayers = hasIl2CppPlayers;\n        m_HasCoreCLRPlayers = hasCoreCLRPlayers;\n        m_HasMonoPlayers = hasMonoPlayers;\n        m_HasServerMonoPlayers = hasServerMonoPlayers;\n        m_HasServerIl2CppPlayers = hasServerIl2CppPlayers;\n    }\n\n    private void SetupStandaloneSubtargets()\n    {\n        List<BuildTarget> standaloneSubtargetsList = new List<BuildTarget>();\n        List<GUIContent> standaloneSubtargetStringsList = new List<GUIContent>();\n\n        if (ModuleManager.IsPlatformSupportLoadedByBuildTarget(BuildTarget.StandaloneWindows))\n        {\n            standaloneSubtargetsList.Add(BuildTarget.StandaloneWindows);\n            standaloneSubtargetStringsList.Add(EditorGUIUtility.TrTextContent(\"Windows\"));\n        }\n        if (ModuleManager.IsPlatformSupportLoadedByBuildTarget(BuildTarget.StandaloneOSX))\n        {\n            standaloneSubtargetsList.Add(BuildTarget.StandaloneOSX);\n            standaloneSubtargetStringsList.Add(EditorGUIUtility.TrTextContent(\"macOS\"));\n        }\n        if (ModuleManager.IsPlatformSupportLoadedByBuildTarget(BuildTarget.StandaloneLinux64))\n        {\n            standaloneSubtargetsList.Add(BuildTarget.StandaloneLinux64);\n            standaloneSubtargetStringsList.Add(EditorGUIUtility.TrTextContent(\"Linux\"));\n        }\n\n        m_StandaloneSubtargets = standaloneSubtargetsList.ToArray();\n        m_StandaloneSubtargetStrings = standaloneSubtargetStringsList.ToArray();\n    }\n\n    internal static BuildTarget GetBestStandaloneTarget(BuildTarget selectedTarget)\n    {\n        if (ModuleManager.IsPlatformSupportLoadedByBuildTarget(selectedTarget))\n            return selectedTarget;\n        if (RuntimePlatform.WindowsEditor == Application.platform && ModuleManager.IsPlatformSupportLoadedByBuildTarget(BuildTarget.StandaloneWindows))\n            return BuildTarget.StandaloneWindows64;\n        if (RuntimePlatform.OSXEditor == Application.platform && ModuleManager.IsPlatformSupportLoadedByBuildTarget(BuildTarget.StandaloneOSX))\n            return BuildTarget.StandaloneOSX;\n        if (ModuleManager.IsPlatformSupportLoadedByBuildTarget(BuildTarget.StandaloneOSX))\n            return BuildTarget.StandaloneOSX;\n        if (ModuleManager.IsPlatformSupportLoadedByBuildTarget(BuildTarget.StandaloneLinux64))\n            return BuildTarget.StandaloneLinux64;\n        return BuildTarget.StandaloneWindows64;\n    }\n\n    struct BuildTargetInfo\n    {\n        public BuildTarget buildTarget;\n        public OSArchitecture architecture;\n    }\n\n    private static BuildTarget DefaultTargetForPlatform(BuildTarget target)\n    {\n        switch (target)\n        {\n            case BuildTarget.StandaloneWindows:\n            case BuildTarget.StandaloneWindows64:\n                return BuildTarget.StandaloneWindows64;\n                // Deprecated\n#pragma warning disable 612, 618\n            case BuildTarget.StandaloneLinux:\n            case BuildTarget.StandaloneLinuxUniversal:\n#pragma warning restore 612, 618\n            case BuildTarget.StandaloneLinux64:\n                return BuildTarget.StandaloneLinux64;\n            case BuildTarget.StandaloneOSX:\n                // Deprecated\n#pragma warning disable 612, 618\n            case BuildTarget.StandaloneOSXIntel:\n            case BuildTarget.StandaloneOSXIntel64:\n#pragma warning restore 612, 618\n                return BuildTarget.StandaloneOSX;\n            default:\n                return target;\n        }\n    }\n\n    private static BuildTargetInfo DefaultArchitectureForTarget(BuildTarget target)\n    {\n        switch (target)\n        {\n            case BuildTarget.StandaloneWindows:\n            case BuildTarget.StandaloneWindows64:\n                return new BuildTargetInfo\n                {\n                    buildTarget = BuildTarget.StandaloneWindows64,\n                    architecture = OSArchitecture.x64\n                };\n                // Deprecated\n#pragma warning disable 612, 618\n            case BuildTarget.StandaloneLinux:\n            case BuildTarget.StandaloneLinuxUniversal:\n#pragma warning restore 612, 618\n            case BuildTarget.StandaloneLinux64:\n                return new BuildTargetInfo\n                {\n                    buildTarget = BuildTarget.StandaloneLinux64,\n                    architecture = OSArchitecture.x64\n                };\n            case BuildTarget.StandaloneOSX:\n                // Deprecated\n#pragma warning disable 612, 618\n            case BuildTarget.StandaloneOSXIntel:\n            case BuildTarget.StandaloneOSXIntel64:\n#pragma warning restore 612, 618\n                return new BuildTargetInfo\n                {\n                    buildTarget = BuildTarget.StandaloneOSX,\n                    architecture = OSArchitecture.x64\n                };\n            default:\n                return new BuildTargetInfo\n                {\n                    buildTarget = target,\n                    architecture = OSArchitecture.x64\n                };\n        }\n    }\n\n    protected virtual void ShowArchitectureSpecificOptions() {}\n\n    public override void ShowPlatformBuildOptions()\n    {\n        BuildTarget selectedTarget = GetBestStandaloneTarget(EditorUserBuildSettings.selectedStandaloneTarget);\n        BuildTargetInfo newTarget = new BuildTargetInfo {buildTarget = EditorUserBuildSettings.selectedStandaloneTarget};\n\n        int selectedIndex = Math.Max(0, Array.IndexOf(m_StandaloneSubtargets, DefaultTargetForPlatform(selectedTarget)));\n        int newIndex = EditorGUILayout.Popup(m_StandaloneTarget, selectedIndex, m_StandaloneSubtargetStrings);\n\n        if (newIndex != selectedIndex)\n        {\n            newTarget = DefaultArchitectureForTarget(m_StandaloneSubtargets[newIndex]);\n        }\n\n        if (newTarget.buildTarget != EditorUserBuildSettings.selectedStandaloneTarget)\n        {\n            // setting selectedStandaloneTarget has side-effect: stops playmode\n            EditorUserBuildSettings.selectedStandaloneTarget = newTarget.buildTarget;\n            SetArchitectureForPlatform(newTarget.buildTarget, newTarget.architecture);\n            GUIUtility.ExitGUI();\n        }\n\n        ShowArchitectureSpecificOptions();\n        ShowBackendErrorIfNeeded();\n    }\n\n    protected void ShowBackendErrorIfNeeded()\n    {\n        var error = GetCannotBuildPlayerInCurrentSetupError();\n        if (string.IsNullOrEmpty(error))\n            return;\n\n        EditorGUILayout.HelpBox(error, MessageType.Error);\n    }\n\n    public override bool EnabledBuildButton()\n    {\n        return string.IsNullOrEmpty(GetCannotBuildPlayerInCurrentSetupError());\n    }\n\n    protected virtual string GetCannotBuildPlayerInCurrentSetupError()\n    {\n        var namedBuildTarget = EditorUserBuildSettingsUtils.CalculateSelectedNamedBuildTarget();\n        var scriptingBackend = PlayerSettings.GetScriptingBackend(namedBuildTarget);\n\n        if (namedBuildTarget == NamedBuildTarget.Server)\n        {\n            if (scriptingBackend == ScriptingImplementation.Mono2x && !m_HasServerMonoPlayers)\n                return $\"Dedicated Server support (Mono) for {GetHostPlatformName()} is not installed.\";\n\n            if (scriptingBackend == ScriptingImplementation.IL2CPP && !m_IsRunningOnHostPlatform)\n                return string.Format(\"{0} IL2CPP player can only be built on {0}.\", GetHostPlatformName());\n\n            if (scriptingBackend == ScriptingImplementation.IL2CPP && !m_HasServerIl2CppPlayers)\n                return $\"Dedicated Server support (IL2CPP) for {GetHostPlatformName()} is not installed.\";\n\n            return null;\n        }\n\n        switch(scriptingBackend)\n        {\n            case ScriptingImplementation.Mono2x:\n            {\n                if (!MonoPlayersInstalled(namedBuildTarget))\n                    return \"Currently selected scripting backend (Mono) is not installed.\";\n                break;\n            }\n            #pragma warning disable 618\n            case ScriptingImplementation.CoreCLR:\n            {\n                if (!m_HasCoreCLRPlayers)\n                    return $\"Currently selected scripting backend (CoreCLR) is not {(Unsupported.IsSourceBuild() ? \"installed\" : \"supported\")}.\"; // CORECLR_FIXME remove sourcebuild\n                break;\n            }\n            case ScriptingImplementation.IL2CPP:\n            {\n                if (!m_IsRunningOnHostPlatform)\n                    return string.Format(\"{0} IL2CPP player can only be built on {0}.\", GetHostPlatformName());\n                if (!Il2CppPlayersInstalled(namedBuildTarget))\n                    return \"Currently selected scripting backend (IL2CPP) is not installed.\";\n                break;\n            }\n            default:\n            {\n                return $\"Unknown scripting backend: {scriptingBackend}\";\n            }\n        }\n\n        return null;\n    }\n\n    protected abstract RuntimePlatform GetHostPlatform();\n    protected abstract string GetHostPlatformName();\n\n    public override bool ShouldDrawWaitForManagedDebugger()\n    {\n        return true;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor;\nusing UnityEditor.Build;\nusing UnityEditor.Build.Reporting;\nusing UnityEditor.Modules;\nusing UnityEditorInternal;\nusing UnityEngine;\n\ninternal abstract class DesktopStandalonePostProcessor : BeeBuildPostprocessor\n{\n    public override bool SupportsLz4Compression() => true;\n    public override bool SupportsInstallInBuildFolder() => true;\n    protected abstract string GetPlatformString(BuildPostProcessArgs args);\n    protected override IPluginImporterExtension GetPluginImpExtension() => new DesktopPluginImporterExtension();\n\n    protected virtual string GetVariationName(BuildPostProcessArgs args)\n    {\n        return string.Format(\"{0}_{1}_{2}_{3}\",\n            GetPlatformString(args),\n            GetServer(args) ? \"server\" : \"player\",\n            GetDevelopment(args) ? \"development\" : \"nondevelopment\",\n            GetScriptingBackend(args).ToString().ToLowerInvariant());\n    }\n\n    protected bool GetServer(BuildPostProcessArgs args) =>\n        GetNamedBuildTarget(args) == NamedBuildTarget.Server;\n\n    protected string GetVariationFolder(BuildPostProcessArgs args) =>\n        $\"{args.playerPackage}/Variations/{GetVariationName(args)}\";\n\n    public override void UpdateBootConfig(BuildTarget target, BootConfigData config, BuildOptions options)\n    {\n        base.UpdateBootConfig(target, config, options);\n        if (PlayerSettings.forceSingleInstance)\n            config.AddKey(\"single-instance\");\n        if (!PlayerSettings.useFlipModelSwapchain)\n            config.AddKey(\"force-d3d11-bitblt-model\");\n        if ((options & BuildOptions.EnableCodeCoverage) != 0)\n            config.Set(\"enableCodeCoverage\", \"1\");\n        if (!PlayerSettings.usePlayerLog)\n            config.AddKey(\"nolog\");\n        if (PlayerSettings.GetCaptureStartupLogs(NamedBuildTarget.FromActiveSettings(target)))\n            config.Set(\"capture-startup-logs\", \"1\");\n    }\n\n    public override ILaunchReport LaunchPlayer(BuildLaunchPlayerArgs args)\n    {\n        // This happens directly from BuildPlayer.cpp\n        return null;\n    }\n\n    readonly bool m_HasMonoPlayers;\n    readonly bool m_HasIl2CppPlayers;\n    readonly bool m_HasCoreCLRPlayers;\n    readonly bool m_HasServerMonoPlayers;\n    readonly bool m_HasServerIl2CppPlayers;\n    readonly bool m_HasServerCoreCLRPlayers;\n\n    protected DesktopStandalonePostProcessor(bool hasMonoPlayers, bool hasIl2CppPlayers, bool hasCoreCLRPlayers, bool hasServerMonoPlayers, bool hasServerIl2CppPlayers, bool hasServerCoreCLRPlayers)\n    {\n        m_HasMonoPlayers = hasMonoPlayers;\n        m_HasIl2CppPlayers = hasIl2CppPlayers;\n        m_HasCoreCLRPlayers = hasCoreCLRPlayers;\n        m_HasServerMonoPlayers = hasServerMonoPlayers;\n        m_HasServerIl2CppPlayers = hasServerIl2CppPlayers;\n        m_HasServerCoreCLRPlayers = hasServerCoreCLRPlayers;\n    }\n\n    public override string PrepareForBuild(BuildPlayerOptions buildOptions)\n    {\n        var namedBuildTarget = NamedBuildTarget.FromActiveSettings(buildOptions.target);\n        var isServer = namedBuildTarget == NamedBuildTarget.Server;\n\n        switch (PlayerSettings.GetScriptingBackend(namedBuildTarget))\n        {\n            case ScriptingImplementation.Mono2x:\n                if (!isServer && !m_HasMonoPlayers)\n                    return \"Currently selected scripting backend (Mono) is not installed.\";\n                if (isServer && !m_HasServerMonoPlayers)\n                    return $\"Dedicated Server support for {GetPlatformNameForBuildProgram(default)} is not installed.\";\n                break;\n            case ScriptingImplementation.IL2CPP:\n                if (!isServer && !m_HasIl2CppPlayers)\n                    return \"Currently selected scripting backend (IL2CPP) is not installed.\";\n                if (isServer && !m_HasServerIl2CppPlayers)\n                    return $\"Dedicated Server support for {GetPlatformNameForBuildProgram(default)} is not installed.\";\n                break;\n            #pragma warning disable 618\n            case ScriptingImplementation.CoreCLR:\n                if (!isServer && !m_HasCoreCLRPlayers)\n                    return \"Currently selected scripting backend (CoreCLR) is not installed.\";\n                if (isServer && !m_HasServerCoreCLRPlayers)\n                    return $\"Dedicated Server support for {GetPlatformNameForBuildProgram(default)} is not installed.\";\n                break;\n            default:\n                return $\"Unknown scripting backend: {PlayerSettings.GetScriptingBackend(namedBuildTarget)}\";\n        }\n\n        return base.PrepareForBuild(buildOptions);\n    }\n\n    internal class ScriptingImplementations : DefaultScriptingImplementations\n    {\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/DesktopStandaloneUserBuildSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditorInternal;\nusing UnityEditor.Modules;\nusing System.Collections.Generic;\nusing System.Text;\n\ninternal static class DesktopStandaloneUserBuildSettings\n{\n    internal static string PlatformName\n    {\n        get\n        {\n            return \"Standalone\";\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/IPostprocessLaunch.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor.Build\n{\n    public enum LaunchResult\n    {\n        Unknown = 0,\n        Succeeded = 1,\n        // For ex., when running on multiple Android devices, some succeeded, some didn't\n        PartiallySucceeded = 2,\n        Failed = 3\n    }\n\n    public interface ILaunchReport\n    {\n        public NamedBuildTarget buildTarget { get; }\n\n        public LaunchResult result { get; }\n    }\n\n    // Unity will provide DefaultLaunchReport for OnPostprocessLaunch callback if platform doesn't provide its own launch report\n    public class DefaultLaunchReport : ILaunchReport\n    {\n        public NamedBuildTarget buildTarget { get; }\n\n        public LaunchResult result { get; }\n\n        internal DefaultLaunchReport(NamedBuildTarget buildTarget, LaunchResult result)\n        {\n            this.buildTarget = buildTarget;\n            this.result = result;\n        }\n    }\n\n    public interface IPostprocessLaunch : IOrderedCallback\n    {\n        void OnPostprocessLaunch(ILaunchReport launchReport);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Runtime.InteropServices;\nusing NiceIO;\nusing UnityEditor;\nusing UnityEditor.Build;\nusing UnityEditor.Build.Reporting;\nusing UnityEditor.Utils;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing Debug = UnityEngine.Debug;\nusing UnityEngine.Scripting.APIUpdating;\n\nnamespace UnityEditor\n{\n    [MovedFrom(\"UnityEditor.LinuxStandalone\")]\n    public abstract class Sysroot\n    {\n        public abstract string Name { get; }\n        public abstract bool Initialize();\n        public abstract string HostPlatform { get; }\n        public abstract string HostArch { get; }\n        public abstract string TargetPlatform { get; }\n        public abstract string TargetArch { get; }\n        public abstract IEnumerable<string> GetIl2CppArguments();\n        public abstract string GetSysrootPath();\n        public abstract string GetToolchainPath();\n        public abstract string GetIl2CppCompilerFlags();\n        // The sysroot package does not currently contain an implemenation for this method, adding a default implementation to avoid breaking stuff\n        public virtual string[] GetIl2CppAdditionalLibraries() => Array.Empty<string>();\n        // The sysroot package does not currently contain an implemenation for this method, adding a default implementation to avoid breaking stuff\n        public virtual string[] GetIl2CppAdditionalDefines() => Array.Empty<string>();\n        // The sysroot package does not currently contain an implemenation for this method, adding a default implementation to avoid breaking stuff\n        public virtual string[] GetIl2CppAdditionalIncludeDirectories() => Array.Empty<string>();\n        // The sysroot package does not currently contain an implemenation for this method, adding a default implementation to avoid breaking stuff\n        public virtual string[] GetIl2CppAdditionalLinkDirectories() => Array.Empty<string>();\n        public abstract string GetIl2CppLinkerFlags();\n        // The sysroot package does not currently contain an implemenation for this method, adding a default implementation to avoid breaking stuff\n        public virtual string GetIl2CppLinkerFlagsFile() => null;\n    }\n}\n\nnamespace UnityEditorInternal\n{\n    internal static class SysrootManager\n    {\n        private static Dictionary<string, Sysroot> _knownSysroots = null;\n        private static Dictionary<string, string> _archMap = null;\n        private static string _hostPlatform = null;\n        private static string _hostArch = null;\n\n        private static string MakeKey(string hostPlatform, string hostArch, string targetPlatform, string targetArch)\n        {\n            return $\"{hostPlatform.ToLower()},{hostArch.ToLower()},{targetPlatform.ToLower()},{targetArch.ToLower()}\";\n        }\n\n        private static string MakeKey(string targetPlatform, string targetArch)\n        {\n            return MakeKey(_hostPlatform, _hostArch, targetPlatform, targetArch);\n        }\n\n\n        [InitializeOnLoadMethod]\n        public static void Initialize()\n        {\n            CreateArchMapping();\n            RegisterSysroots();\n        }\n\n        private static void CreateArchMapping()\n        {\n            _archMap = new Dictionary<string, string>();\n            _archMap.Add(\"amd64\", \"x86_64\");\n            _archMap.Add(\"i686\", \"x86\");\n        }\n\n        private static string MapArch(string arch)\n        {\n            string mapped;\n            if (_archMap.TryGetValue(arch.ToLower(), out mapped))\n                return mapped;\n            return arch.ToLower();\n        }\n\n        private static void RegisterSysroots()\n        {\n            _knownSysroots = new Dictionary<string, Sysroot>();\n            foreach (var type in TypeCache.GetTypesDerivedFrom<Sysroot>())\n            {\n                var sysroot = Activator.CreateInstance(type, new object[] {}, new object[] {}) as Sysroot;\n                if (sysroot != null)\n                {\n                    if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable(\"UNITY_SYSROOT_DEBUG\")))\n                        UnityEngine.Debug.Log($\"Found sysroot: {sysroot.Name}, hp={sysroot.HostPlatform}, ha={sysroot.HostArch}, tp={sysroot.TargetPlatform}, ta={sysroot.TargetArch}\");\n                    _knownSysroots.Add(MakeKey(sysroot.HostPlatform, sysroot.HostArch, sysroot.TargetPlatform, sysroot.TargetArch), sysroot);\n                }\n            }\n        }\n\n        private static bool GetTargetPlatformAndArchFromBuildTarget(BuildTarget target, out string targetPlatform, out string targetArch)\n        {\n            switch (target)\n            {\n                case BuildTarget.StandaloneLinux64:\n                case BuildTarget.LinuxHeadlessSimulation:\n                    targetPlatform = \"linux\";\n                    targetArch = \"x86_64\";\n                    return true;\n                case BuildTarget.WebGL:\n                    targetPlatform = \"webgl\";\n                    targetArch = \"\";\n                    return true;\n                case BuildTarget.EmbeddedLinux:\n                    targetPlatform = \"embeddedlinux\";\n                    targetArch = \"\";\n                    return true;\n            }\n\n            targetPlatform = null;\n            targetArch = null;\n            return false;\n        }\n\n        private static void GetPosixPlatformAndArch()\n        {\n            var p = new Process();\n            p.StartInfo.FileName = \"uname\";\n            p.StartInfo.Arguments = \"-s -m\";\n            p.StartInfo.RedirectStandardError = true;\n            p.StartInfo.RedirectStandardOutput = true;\n            p.StartInfo.UseShellExecute = false;\n            p.Start();\n            var parts = p.StandardOutput.ReadToEnd().Split(new char[] { ' ', '\\r', '\\n' });\n            p.WaitForExit();\n            if (parts.Length > 1)\n            {\n                _hostPlatform = parts[0].ToLower();\n                _hostArch = MapArch(parts[1]);\n            }\n        }\n\n        private static string AllowEnvironmentOverride(string origValue, string envVar)\n        {\n            string envValue = Environment.GetEnvironmentVariable(envVar);\n            return envValue == null ? origValue : envValue;\n        }\n\n        private static bool GetHostPlatformAndArch()\n        {\n            if (_hostPlatform != null && _hostArch != null)\n                return true;\n\n            switch (Environment.OSVersion.Platform)\n            {\n                case PlatformID.Win32NT:\n                    _hostPlatform = \"windows\";\n                    _hostArch = MapArch(Environment.GetEnvironmentVariable(\"PROCESSOR_ARCHITECTURE\"));\n                    break;\n                case PlatformID.Unix:\n                    GetPosixPlatformAndArch();\n                    break;\n            }\n\n            _hostPlatform = AllowEnvironmentOverride(_hostPlatform, \"UNITY_SYSROOT_HOST_PLATFORM\");\n            _hostArch = AllowEnvironmentOverride(_hostArch, \"UNITY_SYSROOT_HOST_ARCH\");\n\n            return _hostPlatform != null && _hostArch != null;\n        }\n\n        public static Sysroot FindSysroot(BuildTarget target)\n        {\n            string targetPlatform, targetArch;\n            if (!GetTargetPlatformAndArchFromBuildTarget(target, out targetPlatform, out targetArch))\n                return null;\n\n            return FindSysroot(targetPlatform, targetArch);\n        }\n\n        private static Sysroot FindSysroot(string targetPlatform, string targetArch)\n        {\n            if (!GetHostPlatformAndArch())\n                return null;\n\n            Sysroot sysroot;\n            if (!_knownSysroots.TryGetValue(MakeKey(targetPlatform, targetArch), out sysroot))\n                return null;\n\n            if (!sysroot.Initialize())\n            {\n                UnityEngine.Debug.Log($\"Failed to initialize sysroot {sysroot.Name}\");\n                return null;\n            }\n\n            return sysroot;\n        }\n\n        public static string HostTargetTuple(BuildTarget buildTarget)\n        {\n            if (GetHostPlatformAndArch())\n            {\n                string targetPlatform;\n                string targetArch;\n                if (GetTargetPlatformAndArchFromBuildTarget(buildTarget, out targetPlatform, out targetArch))\n                {\n                    string host;\n                    switch (_hostPlatform)\n                    {\n                        case \"darwin\":\n                            host = $\"macos-{_hostArch}\";\n                            break;\n                        case \"windows\":\n                            host = $\"win-{_hostArch}\";\n                            break;\n                        default:\n                            host = $\"{_hostPlatform}-{_hostArch}\";\n                            break;\n                    }\n                    string target = String.IsNullOrEmpty(targetArch) ? targetPlatform : $\"{targetPlatform}-{targetArch}\";\n                    return host == target ? target : $\"{host}-{target}\";\n                }\n            }\n            return null;\n        }\n\n        public static IEnumerable<Sysroot> EnumerateSysroots()\n        {\n            foreach (Sysroot sysroot in _knownSysroots.Values)\n            {\n                yield return sysroot;\n            }\n        }\n    }\n\n    internal class IL2CPPUtils\n    {\n        private static readonly string[] BaseDefinesWindows = new[]\n        {\n            \"_CRT_SECURE_NO_WARNINGS\",\n            \"_WINSOCK_DEPRECATED_NO_WARNINGS\",\n            \"WIN32\",\n            \"WINDOWS\",\n            \"_UNICODE\",\n            \"UNICODE\",\n        };\n\n        private static readonly string[] BaseDefines20 = new[]\n        {\n            \"ALL_INTERIOR_POINTERS=1\",\n            \"GC_GCJ_SUPPORT=1\",\n            \"JAVA_FINALIZATION=1\",\n            \"NO_EXECUTE_PERMISSION=1\",\n            \"GC_NO_THREADS_DISCOVERY=1\",\n            \"IGNORE_DYNAMIC_LOADING=1\",\n            \"GC_DONT_REGISTER_MAIN_STATIC_DATA=1\",\n            \"GC_VERSION_MAJOR=7\",\n            \"GC_VERSION_MINOR=7\",\n            \"GC_VERSION_MICRO=0\",\n            \"GC_THREADS=1\",\n            \"USE_MMAP=1\",\n            \"USE_MUNMAP=1\",\n        }.ToArray();\n\n        private static readonly string[] BaseDefines46 = BaseDefines20.Concat(new[]\n        {\n            \"NET_4_0=1\",\n            \"UNITY_AOT=1\",\n            \"NET_STANDARD_2_0=1\",\n            \"NET_UNITY_4_8=1\",\n            \"NET_STANDARD=1\",\n        }).ToArray();\n\n        internal static string ApiCompatibilityLevelToDotNetProfileArgument(ApiCompatibilityLevel compatibilityLevel, BuildTarget target)\n        {\n            switch (compatibilityLevel)\n            {\n                case ApiCompatibilityLevel.NET_2_0_Subset:\n                    return \"legacyunity\";\n\n                case ApiCompatibilityLevel.NET_2_0:\n                    return \"net20\";\n\n                case ApiCompatibilityLevel.NET_Unity_4_8:\n                case ApiCompatibilityLevel.NET_Standard:\n                    return \"unityaot-\" + BuildTargetDiscovery.GetPlatformProfileSuffix(target);\n\n                default:\n                    throw new NotSupportedException(string.Format(\"ApiCompatibilityLevel.{0} is not supported by IL2CPP!\", compatibilityLevel));\n            }\n        }\n\n        internal static string[] GetBuilderDefinedDefines(BuildTarget target, ApiCompatibilityLevel apiCompatibilityLevel, bool enableIl2CppDebugger)\n        {\n            List<string> defines = new List<string>();\n\n            switch (apiCompatibilityLevel)\n            {\n                case ApiCompatibilityLevel.NET_2_0:\n                case ApiCompatibilityLevel.NET_2_0_Subset:\n                    defines.AddRange(BaseDefines20);\n                    break;\n\n                case ApiCompatibilityLevel.NET_Unity_4_8:\n                case ApiCompatibilityLevel.NET_Standard:\n                    defines.AddRange(BaseDefines46);\n                    break;\n\n                default:\n                    throw new InvalidOperationException($\"IL2CPP doesn't support building with {apiCompatibilityLevel} API compatibility level!\");\n            }\n\n            if (target == BuildTarget.StandaloneWindows || target == BuildTarget.StandaloneWindows64 ||\n                target == BuildTarget.XboxOne || target == BuildTarget.WSAPlayer)\n            {\n                defines.AddRange(BaseDefinesWindows);\n\n                if (target == BuildTarget.WSAPlayer)\n                {\n                    defines.Add(\"WINAPI_FAMILY=WINAPI_FAMILY_APP\");\n                }\n                else\n                {\n                    defines.Add(\"WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP\");\n                }\n            }\n\n            if (enableIl2CppDebugger)\n                defines.Add(\"IL2CPP_MONO_DEBUGGER=1\");\n\n            if (BuildPipeline.IsFeatureSupported(\"ENABLE_SCRIPTING_GC_WBARRIERS\", target))\n            {\n                var hasGCBarrierValidation = PlayerSettings.gcWBarrierValidation;\n                if (hasGCBarrierValidation)\n                {\n                    defines.Add(\"IL2CPP_ENABLE_STRICT_WRITE_BARRIERS=1\");\n                    defines.Add(\"IL2CPP_ENABLE_WRITE_BARRIER_VALIDATION=1\");\n                }\n\n                var hasIncrementalGCTimeSlice = PlayerSettings.gcIncremental && (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6 || apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0 ||\n                    apiCompatibilityLevel == ApiCompatibilityLevel.NET_Unity_4_8 || apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard);\n\n                if (hasGCBarrierValidation || hasIncrementalGCTimeSlice)\n                {\n                    var timeslice = hasIncrementalGCTimeSlice ? \"3\" : \"0\";\n                    defines.Add(\"IL2CPP_ENABLE_WRITE_BARRIERS=1\");\n                    defines.Add($\"IL2CPP_INCREMENTAL_TIME_SLICE={timeslice}\");\n                }\n            }\n\n            return defines.ToArray();\n        }\n\n        internal static string GetIl2CppFolder()\n        {\n            return GetIl2CppFolder(out var _);\n        }\n\n        internal static bool UsingDevelopmentBuild()\n        {\n            GetIl2CppFolder(out var isDevelopmentLocation);\n            return isDevelopmentLocation;\n        }\n\n        static string GetIl2CppFolder(out bool isDevelopmentLocation)\n        {\n            var pathOverride = System.Environment.GetEnvironmentVariable(\"UNITY_IL2CPP_PATH\");\n            if (!string.IsNullOrEmpty(pathOverride))\n            {\n                isDevelopmentLocation = true;\n                return pathOverride;\n            }\n\n            pathOverride = Debug.GetDiagnosticSwitch(\"VMIl2CppPath\").value as string;\n            if (!string.IsNullOrEmpty(pathOverride))\n            {\n                isDevelopmentLocation = true;\n                return pathOverride;\n            }\n\n            isDevelopmentLocation = false;\n            return Path.GetFullPath(Path.Combine(\n                EditorApplication.applicationContentsPath,\n                \"il2cpp\"));\n        }\n\n        internal static string GetBCLExtensionsFolder()\n        {\n            var il2CppFolder = GetIl2CppFolder(out var isDevelopmentLocation);\n            if (isDevelopmentLocation)\n                return Path.Combine(il2CppFolder, \"build\", \"tests\", \"BCLExtensions\", \"net471\");\n\n            return Paths.Combine(il2CppFolder, \"BCLExtensions\");\n        }\n\n        internal static IEnumerable<string> GetBCLExtensionLibraries()\n        {\n            var bclExtensionsFolder = GetBCLExtensionsFolder();\n            return new string[]\n            {\n                Path.Combine(bclExtensionsFolder, \"System.Runtime.WindowsRuntime.dll\"),\n                Path.Combine(bclExtensionsFolder, \"System.Runtime.WindowsRuntime.UI.Xaml.dll\"),\n            };\n        }\n\n        internal static string GetExePath(string toolName)\n        {\n            var platform = Application.platform;\n            var il2CppFolder = GetIl2CppFolder(out var isDevelopmentLocation);\n            var expectedToolExecutableName = $\"{toolName}{(platform == RuntimePlatform.WindowsEditor ? \".exe\" : \"\")}\";\n\n            if (isDevelopmentLocation)\n            {\n                // Locating the correct development build to use is a little tricky.  Complications come from\n                // 1) We don't know if the Debug or Release build is desired.  To overcome this we will pick whichever was modified most recently\n                // 2) We don't know if the published or non-published build is desired.  Again, we'll use whichever was modified most recently\n                // 3) Published builds for all platforms may or may not be built.  We need to make sure not to pick a build for a different platform\n\n                // Note that this logic will intentionally avoid checking for an expected TFM.  This is a dev build.  Using w/e is newest is probably\n                // the most robust and maintainable approach.\n\n                var toolBinDirectory = Path.Combine(il2CppFolder, toolName, \"bin\").ToNPath();\n                var candidates = toolBinDirectory.Files($\"*{expectedToolExecutableName}\", recurse: true)\n                    .OrderByDescending(f => f.GetLastWriteTimeUtc())\n                    .ToArray();\n\n                if (candidates.Length == 0)\n                    throw new InvalidOperationException($\"{toolName} does not appear to be built in {il2CppFolder}\");\n\n                var expectedPublishDirectoryName = BinaryDirectoryForPlatform(platform).ToNPath();\n\n                foreach (var candidate in candidates)\n                {\n                    // Examples :\n                    // 1)   il2cpp/bin/Release/<tfm>/il2cpp.exe\n                    // 2)   il2cpp/bin/Debug/<tfm>/il2cpp.exe\n                    if (candidate.Parent.Parent.Parent.FileName == \"bin\")\n                    {\n                        // Found a non-published build\n                        return candidate.ToString();\n                    }\n\n                    // Examples :\n                    // 1)   il2cpp/bin/Release/<tfm>/<platform dir>/publish/il2cpp.exe\n                    // 2)   il2cpp/bin/Debug/<tfm>/<platform dir>/publish/il2cpp.exe\n                    if (candidate.Parent.FileName == \"publish\" && candidate.Parent.Parent.FileName == expectedPublishDirectoryName)\n                    {\n                        // found a published build\n                        return candidate.ToString();\n                    }\n\n                    // There is a 3rd path structure that we will ignore\n                    // Examples :\n                    // 1)   il2cpp/bin/Release/<tfm>/<platform dir>/il2cpp.exe\n                    // 2)   il2cpp/bin/Debug/<tfm>/<platform dir>/il2cpp.exe\n                }\n\n                throw new InvalidOperationException($\"Could not determine which of the {candidates.Length} of {toolName} to use.  The expected TFM or expected directory layout may have changed and this logic may need to be updated\");\n            }\n\n            var deployDirectory = $\"{il2CppFolder}/build/deploy\";\n            return $\"{deployDirectory}/{expectedToolExecutableName}\";\n        }\n\n        internal static string GetLibrarySearchPaths(string name, string tfm, string customRoot = null)\n        {\n            var il2CppFolder = GetIl2CppFolder(out var isDevelopmentLocation);\n            var expectedToolExecutableName = $\"{name}.dll\";\n\n            if (isDevelopmentLocation)\n            {\n                // Locating the correct development build to use is a little tricky.  Complications come from\n                // 1) We don't know if the Debug or Release build is desired.  To overcome this we will pick whichever was modified most recently\n\n                var topLevel = il2CppFolder;\n                if (customRoot != null)\n                    topLevel = Path.Combine(topLevel, customRoot);\n\n                var toolBinDirectory = Path.Combine(topLevel, name, \"bin\").ToNPath();\n                var candidates = toolBinDirectory.Files($\"*{expectedToolExecutableName}\", recurse: true)\n                    .Where(f => f.Parent.FileName == tfm)\n                    .OrderByDescending(f => f.GetLastWriteTimeUtc())\n                    .ToArray();\n\n                if (candidates.Length == 0)\n                    throw new InvalidOperationException($\"{name} does not appear to be built in {il2CppFolder}\");\n\n                return candidates[0].Parent.ToString();\n            }\n\n            throw new ArgumentException($\"Could not locate assembly for {name}\");\n        }\n\n        internal static string ConstructBeeLibrarySearchPath()\n        {\n            var projectBinDirs = new[]\n            {\n                GetLibrarySearchPaths(\"Unity.Options\", \"netstandard2.0\", \"repos/UnityOptions\"),\n                GetLibrarySearchPaths(\"Unity.Linker.Api\", \"netstandard2.0\"),\n                GetLibrarySearchPaths(\"Unity.IL2CPP.Api\", \"netstandard2.0\"),\n                GetLibrarySearchPaths(\"Unity.Api.Attributes\", \"netstandard2.0\"),\n                GetLibrarySearchPaths(\"Unity.IL2CPP.Bee.IL2CPPExeCompileCppBuildProgram.Data\", \"netstandard2.0\"),\n                GetLibrarySearchPaths(\"Unity.IL2CPP.Bee.BuildLogic\", \"net6.0\"),\n                // Now the quirky part.  We need to locate the platform build logic assemblies.\n                // While il2cpp will have these during some build scenarios (IDE build or build.pl)\n                // the project that will always have all of the is il2cpp-compile\n                GetExePath(\"il2cpp-compile\").ToNPath().Parent\n            };\n\n            return projectBinDirs.Aggregate(string.Empty, (accum, next) => $\"{accum}{Path.PathSeparator}{next}\");\n        }\n\n        internal static string GetAdditionalArguments()\n        {\n            var arguments = new List<string>();\n            var additionalArgs = PlayerSettings.GetAdditionalIl2CppArgs();\n            if (!string.IsNullOrEmpty(additionalArgs))\n                arguments.Add(additionalArgs);\n\n            additionalArgs = System.Environment.GetEnvironmentVariable(\"IL2CPP_ADDITIONAL_ARGS\");\n            if (!string.IsNullOrEmpty(additionalArgs))\n            {\n                arguments.Add(additionalArgs);\n            }\n\n            additionalArgs = Debug.GetDiagnosticSwitch(\"VMIl2CppAdditionalArgs\").value as string;\n            if (!string.IsNullOrEmpty(additionalArgs))\n            {\n                arguments.Add(additionalArgs.Trim('\\''));\n            }\n\n            return arguments.Aggregate(String.Empty, (current, arg) => current + arg + \" \");\n        }\n\n        private static string BinaryDirectoryForPlatform(RuntimePlatform platform)\n        {\n            if (platform == RuntimePlatform.WindowsEditor)\n                return \"win-x64\";\n            else if (platform == RuntimePlatform.LinuxEditor)\n                return \"linux-x64\";\n\n            var arch = RuntimeInformation.ProcessArchitecture.ToString().ToLower();\n            if (platform == RuntimePlatform.OSXEditor && arch == \"arm64\")\n                return \"osx-arm64\";\n            return \"osx-x64\";\n        }\n    }\n\n    internal class IL2CPPBuilder\n    {\n        [RequiredByNativeCode]\n        public static string GetBuildAnalyticsSummaryCollectorExe()\n        {\n            return IL2CPPUtils.GetExePath(\"Analytics\");\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/NamedBuildTarget.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\n\nnamespace UnityEditor.Build\n{\n    public readonly struct NamedBuildTarget : IEquatable<NamedBuildTarget>, IComparable<NamedBuildTarget>\n    {\n        private static readonly string[] k_ValidNames =\n        {\n            \"\",\n            \"FakePlatform\",\n            \"Standalone\",\n            \"Server\",\n            \"iPhone\",\n            \"Android\",\n            \"WebGL\",\n            \"Windows Store Apps\",\n            \"PS4\",\n            \"XboxOne\",\n            \"tvOS\",\n            \"VisionOS\",\n            \"Nintendo Switch\",\n            \"Stadia\",\n            \"CloudRendering\",\n            \"LinuxHeadlessSimulation\",\n            \"Lumin\",\n            // This should have been \"GameCoreXboxSeries\"\n            \"GameCoreScarlett\",\n            \"GameCoreXboxOne\",\n            \"PS5\",\n            \"EmbeddedLinux\",\n            \"QNX\",\n            \"ReservedCFE\",\n            \"Kepler\",\n        };\n\n        public static readonly NamedBuildTarget Unknown = new NamedBuildTarget(\"\");\n        public static readonly NamedBuildTarget Standalone = new NamedBuildTarget(\"Standalone\");\n        public static readonly NamedBuildTarget Server = new NamedBuildTarget(\"Server\");\n        public static readonly NamedBuildTarget iOS = new NamedBuildTarget(\"iPhone\");\n        public static readonly NamedBuildTarget Android = new NamedBuildTarget(\"Android\");\n        public static readonly NamedBuildTarget WebGL = new NamedBuildTarget(\"WebGL\");\n        public static readonly NamedBuildTarget WindowsStoreApps = new NamedBuildTarget(\"Windows Store Apps\");\n        // NDA platforms should not have been added here into the public API\n        public static readonly NamedBuildTarget PS4 = new NamedBuildTarget(\"PS4\");\n        public static readonly NamedBuildTarget PS5 = new NamedBuildTarget(\"PS5\");\n        public static readonly NamedBuildTarget XboxOne = new NamedBuildTarget(\"XboxOne\");\n        public static readonly NamedBuildTarget tvOS = new NamedBuildTarget(\"tvOS\");\n        public static readonly NamedBuildTarget VisionOS = new NamedBuildTarget(\"VisionOS\");\n        public static readonly NamedBuildTarget NintendoSwitch = new NamedBuildTarget(\"Nintendo Switch\");\n        [System.Obsolete(\"Stadia has been removed in 2023.1\")]\n        public static readonly NamedBuildTarget Stadia = new NamedBuildTarget(\"Stadia\");\n        public static readonly NamedBuildTarget LinuxHeadlessSimulation = new NamedBuildTarget(\"LinuxHeadlessSimulation\");\n        [System.Obsolete(\"CloudRendering is deprecated, please use LinuxHeadlessSimulation (UnityUpgradable) -> LinuxHeadlessSimulation\", false)]\n        public static readonly NamedBuildTarget CloudRendering = LinuxHeadlessSimulation;\n        public static readonly NamedBuildTarget EmbeddedLinux  = new NamedBuildTarget(\"EmbeddedLinux\");\n        public static readonly NamedBuildTarget QNX  = new NamedBuildTarget(\"QNX\");\n\n        public string TargetName { get; }\n\n        internal NamedBuildTarget(string targetName)\n        {\n            if (!k_ValidNames.Contains(targetName))\n            {\n                throw new ArgumentException($\"'{targetName}' is not a valid build target name\");\n            }\n\n            TargetName = targetName;\n        }\n\n        public BuildTargetGroup ToBuildTargetGroup()\n        {\n            switch (TargetName)\n            {\n                case \"Server\":\n                    return BuildTargetGroup.Standalone;\n                default:\n                    return BuildPipeline.GetBuildTargetGroupByName(TargetName);\n            }\n        }\n\n        public static NamedBuildTarget FromBuildTargetGroup(BuildTargetGroup buildTargetGroup)\n        {\n            switch (buildTargetGroup)\n            {\n                case BuildTargetGroup.Unknown:\n                    return NamedBuildTarget.Unknown;\n                case BuildTargetGroup.Standalone:\n                    return NamedBuildTarget.Standalone;\n                case BuildTargetGroup.iOS:\n                    return NamedBuildTarget.iOS;\n                case BuildTargetGroup.Android:\n                    return NamedBuildTarget.Android;\n                case BuildTargetGroup.WebGL:\n                    return NamedBuildTarget.WebGL;\n                case BuildTargetGroup.WSA:\n                    return NamedBuildTarget.WindowsStoreApps;\n                case BuildTargetGroup.PS4:\n                    return NamedBuildTarget.PS4;\n                case BuildTargetGroup.XboxOne:\n                    return NamedBuildTarget.XboxOne;\n                case BuildTargetGroup.tvOS:\n                    return NamedBuildTarget.tvOS;\n                case BuildTargetGroup.VisionOS:\n                    return NamedBuildTarget.VisionOS;\n                case BuildTargetGroup.Switch:\n                    return NamedBuildTarget.NintendoSwitch;\n                case BuildTargetGroup.LinuxHeadlessSimulation:\n                    return NamedBuildTarget.LinuxHeadlessSimulation;\n                case BuildTargetGroup.EmbeddedLinux:\n                    return NamedBuildTarget.EmbeddedLinux;\n                case BuildTargetGroup.QNX:\n                    return NamedBuildTarget.QNX;\n\n                // Build targets that are not explicitly listed\n                case BuildTargetGroup.GameCoreXboxSeries:\n                    return new NamedBuildTarget(\"GameCoreScarlett\");\n                case BuildTargetGroup.GameCoreXboxOne:\n                    return new NamedBuildTarget(\"GameCoreXboxOne\");\n                case BuildTargetGroup.PS5:\n                    return new NamedBuildTarget(\"PS5\");\n                case BuildTargetGroup.ReservedCFE:\n                    return new NamedBuildTarget(\"ReservedCFE\");\n                case BuildTargetGroup.Kepler:\n                    return new NamedBuildTarget(\"Kepler\");\n            }\n\n            throw new ArgumentException($\"There is no a valid NamedBuildTarget for BuildTargetGroup '{buildTargetGroup}'\");\n        }\n\n        // TODO: We shouldn't be assuming that the namedBuildTarget can be extracted from the\n        // active settings. This should be passed through the callstack instead when building.\n        // We will need to use BuildTargetSelection (BuildTarget + Subtarget) that is in the cpp side.\n        // For now this fixes an issue where Dedicated Server compiles with the Standalone settings.\n        internal static NamedBuildTarget FromActiveSettings(BuildTarget target)\n        {\n            var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(target);\n\n            if (buildTargetGroup == BuildTargetGroup.Standalone && (StandaloneBuildSubtarget)EditorUserBuildSettings.GetActiveSubtargetFor(target) == StandaloneBuildSubtarget.Server)\n            {\n                return NamedBuildTarget.Server;\n            }\n\n            return NamedBuildTarget.FromBuildTargetGroup(buildTargetGroup);\n        }\n\n        internal static NamedBuildTarget FromTargetAndSubtarget(BuildTarget target, int subtarget)\n        {\n            var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(target);\n            if (buildTargetGroup == BuildTargetGroup.Standalone)\n            {\n                var standaloneSubtarget = (StandaloneBuildSubtarget)subtarget;\n                switch (standaloneSubtarget)\n                {\n                    case StandaloneBuildSubtarget.Player:\n                        return NamedBuildTarget.Standalone;\n                    case StandaloneBuildSubtarget.Server:\n                        return NamedBuildTarget.Server;\n                    default:\n                        throw new ArgumentException($\"'{standaloneSubtarget}' is not a valid subtarget for the Standalone build target\");\n                }\n            }\n\n            return NamedBuildTarget.FromBuildTargetGroup(buildTargetGroup);\n        }\n\n        public static bool operator==(NamedBuildTarget lhs, NamedBuildTarget rhs)\n        {\n            return lhs.Equals(rhs);\n        }\n\n        public static bool operator!=(NamedBuildTarget lhs, NamedBuildTarget rhs)\n        {\n            return !lhs.Equals(rhs);\n        }\n\n        public override int GetHashCode()\n        {\n            return TargetName.GetHashCode();\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj == null || GetType() != obj.GetType())\n            {\n                return false;\n            }\n            return Equals((NamedBuildTarget)obj);\n        }\n\n        public bool Equals(NamedBuildTarget other)\n        {\n            return TargetName == other.TargetName;\n        }\n\n        public int CompareTo(NamedBuildTarget other)\n        {\n            return TargetName.CompareTo(other.TargetName);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/OSArchitecture.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor.Build\n{\n    public enum OSArchitecture\n    {\n        x64,\n        ARM64,\n        x64ARM64,\n        x86,\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/PostprocessBuildPlayer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.IO;\nusing System;\nusing UnityEditor.Build;\nusing UnityEditor.Build.Reporting;\nusing UnityEditor.Modules;\nusing UnityEditor.DeploymentTargets;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    class MissingBuildPropertiesException : Exception {}\n\n    // Holds data needed to verify a target against a set of requirements\n    internal abstract class DeploymentTargetRequirements\n    {\n    }\n\n    // Holds data needed for operating (launching etc) on a build\n    internal abstract class BuildProperties : ScriptableObject\n    {\n        public static BuildProperties GetFromBuildReport(BuildReport report)\n        {\n            var allData = report.GetAppendices<BuildProperties>();\n            if (allData.Length > 0)\n                return allData[0];\n\n            throw new MissingBuildPropertiesException();\n        }\n\n        public abstract DeploymentTargetRequirements GetTargetRequirements();\n    }\n\n    internal static class PostprocessBuildPlayer\n    {\n        internal const string StreamingAssets = \"Assets/StreamingAssets\";\n\n        internal static void AddProjectBootConfigKey(string key)\n        {\n            AddProjectBootConfigKeyValue(key, null);\n        }\n\n        internal static void AddProjectBootConfigKeyValue(string key, string value)\n        {\n            projectBootConfigEntries[key] = value;\n        }\n\n        internal static bool RemoveProjectBootConfigKey(string key)\n        {\n            return projectBootConfigEntries.Remove(key);\n        }\n\n        internal static bool GetProjectBootConfigKeyValue(string key, out string value)\n        {\n            return projectBootConfigEntries.TryGetValue(key, out value);\n        }\n\n        internal static void ClearProjectBootConfigEntries()\n        {\n            projectBootConfigEntries.Clear();\n        }\n\n        private static Dictionary<string, string> projectBootConfigEntries = new Dictionary<string, string>();\n\n        internal static string GetStreamingAssetsBundleManifestPath()\n        {\n            string manifestPath = \"\";\n            if (Directory.Exists(StreamingAssets))\n            {\n                var tmpPath = Path.Combine(StreamingAssets, \"StreamingAssets.manifest\");\n                if (File.Exists(tmpPath))\n                    manifestPath = tmpPath;\n            }\n\n            return manifestPath;\n        }\n\n        [RequiredByNativeCode]\n        static public string PrepareForBuild(BuildPlayerOptions buildOptions)\n        {\n            var postprocessor = ModuleManager.GetBuildPostProcessor(buildOptions.target);\n            if (postprocessor == null)\n                return null;\n            return postprocessor.PrepareForBuild(buildOptions);\n        }\n\n        static public string GetExtensionForBuildTarget(BuildTargetGroup targetGroup, BuildTarget target, BuildOptions options) =>\n           GetExtensionForBuildTarget(target, EditorUserBuildSettings.GetActiveSubtargetFor(target), options);\n\n        static public string GetExtensionForBuildTarget(BuildTarget target, int subtarget, BuildOptions options)\n        {\n            IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(target);\n            if (postprocessor == null)\n                return string.Empty;\n            return postprocessor.GetExtension(target, subtarget, options);\n        }\n\n        static public string GetExtensionForBuildTarget(BuildTarget target, BuildOptions options) =>\n            GetExtensionForBuildTarget(target, EditorUserBuildSettings.GetActiveSubtargetFor(target), options);\n\n        static public bool SupportsInstallInBuildFolder(BuildTarget target)\n        {\n            IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(target);\n            if (postprocessor != null)\n            {\n                return postprocessor.SupportsInstallInBuildFolder();\n            }\n\n            return false;\n        }\n\n        static public bool SupportsLz4Compression(BuildTargetGroup targetGroup, BuildTarget target) =>\n            SupportsLz4Compression(target);\n\n        static public bool SupportsLz4Compression(BuildTarget target)\n        {\n            IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(target);\n            if (postprocessor != null)\n                return postprocessor.SupportsLz4Compression();\n            return false;\n        }\n\n        static public Compression GetDefaultCompression(BuildTarget target)\n        {\n            IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(target);\n            if (postprocessor != null)\n                return postprocessor.GetDefaultCompression();\n            return Compression.None;\n        }\n\n        private class NoTargetsFoundException : Exception\n        {\n            public NoTargetsFoundException() : base() {}\n            public NoTargetsFoundException(string message) : base(message) {}\n        }\n\n        [RequiredByNativeCode]\n        static public void Launch(BuildTarget buildTarget, string path, string productName, BuildOptions options, BuildReport buildReport)\n        {\n            IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(buildTarget);\n            if (postprocessor != null)\n            {\n                BuildLaunchPlayerArgs args;\n                args.target = buildTarget;\n                args.playerPackage = BuildPipeline.GetPlaybackEngineDirectory(buildTarget, options);\n                args.installPath = path;\n                args.productName = productName;\n                args.options = options;\n                args.report = buildReport;\n\n                var launchResult = postprocessor.LaunchPlayer(args);\n                // If platform didn't provide any platform specific results, at the very least provide default implementation\n                if (launchResult == null)\n                    launchResult = new DefaultLaunchReport(NamedBuildTarget.FromActiveSettings(buildTarget), LaunchResult.Unknown);\n\n                BuildPipelineInterfaces.OnPostprocessLaunch(launchResult);\n            }\n            else\n            {\n                throw new UnityException(\n                    $\"Launching for build target {buildTarget} is not supported: There is no build post-processor available.\");\n            }\n        }\n\n        public static LaunchResult GetLaunchResult(IReadOnlyList<IDeploymentLaunchResult> deploymentLaunchResults)\n        {\n            var successLaunches = 0;\n            foreach (var r in deploymentLaunchResults)\n            {\n                if (r.Success)\n                    successLaunches++;\n            }\n\n            if (successLaunches == 0)\n                return LaunchResult.Failed;\n            if (successLaunches == deploymentLaunchResults.Count)\n                return LaunchResult.Succeeded;\n            return LaunchResult.PartiallySucceeded;\n        }\n\n        static public IReadOnlyList<IDeploymentLaunchResult> LaunchOnTargets(BuildTarget buildTarget, BuildReport buildReport, List<DeploymentTargetId> launchTargets)\n        {\n            var launches = new List<IDeploymentLaunchResult>();\n            try\n            {\n                // Early out so as not to show/update progressbars unnecessarily\n                if (buildReport == null)\n                    throw new System.NotSupportedException();\n\n                ProgressHandler progressHandler = new ProgressHandler(\"Deploying Player\",\n                    delegate(string title, string message, float globalProgress)\n                    {\n                        if (EditorUtility.DisplayCancelableProgressBar(title, message, globalProgress))\n                            throw new DeploymentOperationAbortedException();\n                    }, 0.1f);     // BuildPlayer.cpp starts off at 0.1f for some reason\n\n                var taskManager = new ProgressTaskManager(progressHandler);\n\n                // Launch on all selected targets\n                taskManager.AddTask(() =>\n                {\n                    int successfulLaunches = 0;\n                    var exceptions = new List<DeploymentOperationFailedException>();\n                    foreach (var target in launchTargets)\n                    {\n                        IDeploymentLaunchResult launchResult;\n                        try\n                        {\n                            var manager = DeploymentTargetManager.CreateInstance(buildReport.summary.platform);\n                            var buildProperties = BuildProperties.GetFromBuildReport(buildReport);\n                            launchResult = manager.LaunchBuildOnTarget(buildProperties, target, taskManager.SpawnProgressHandlerFromCurrentTask());\n                            if (launchResult != null && launchResult.Success)\n                                successfulLaunches++;\n                        }\n                        catch (DeploymentOperationFailedException e)\n                        {\n                            launchResult = e.launchResult;\n                            exceptions.Add(e);     \n                        }\n\n                        launches.Add(launchResult);\n                    }\n\n                    foreach (var e in exceptions)\n                        UnityEngine.Debug.LogException(e);\n\n                    if (successfulLaunches == 0)\n                    {\n                        // TODO: Maybe more specifically no compatible targets?\n                        throw new NoTargetsFoundException(\"Could not launch build\");\n                    }\n                });\n\n                taskManager.Run();\n            }\n            catch (DeploymentOperationFailedException e)\n            {\n                UnityEngine.Debug.LogException(e);\n                EditorUtility.DisplayDialog(e.title, e.Message, \"OK\");\n            }\n            catch (DeploymentOperationAbortedException)\n            {\n                System.Console.WriteLine(\"Deployment aborted\");\n            }\n            catch (NoTargetsFoundException)\n            {\n                throw new UnityException(string.Format(\"Could not find any valid targets to launch on for {0}\", buildTarget));\n            }\n\n            return launches;\n        }\n\n        [RequiredByNativeCode]\n        static public void UpdateBootConfig(BuildTarget target, BootConfigData config, BuildOptions options)\n        {\n            IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(target);\n            if (postprocessor != null)\n                postprocessor.UpdateBootConfig(target, config, options);\n\n            foreach (var keyValue in projectBootConfigEntries)\n            {\n                if ((keyValue.Value == null) || keyValue.Value.All(char.IsWhiteSpace))\n                    config.AddKey(keyValue.Key);\n                else\n                    config.Set(keyValue.Key, keyValue.Value);\n            }\n        }\n\n        [RequiredByNativeCode]\n        static public void Postprocess(BuildTarget target, int subtarget, string installPath, string companyName, string productName,\n            BuildOptions options,\n            RuntimeClassRegistry usedClassRegistry, BuildReport report)\n        {\n            string stagingArea = \"Temp/StagingArea\";\n            string stagingAreaData = \"Temp/StagingArea/Data\";\n            string stagingAreaDataManaged = \"Temp/StagingArea/Data/Managed\";\n            string playerPackage = BuildPipeline.GetPlaybackEngineDirectory(target, options);\n\n            // Disallow providing an empty string as the installPath\n            bool willInstallInBuildFolder = (options & BuildOptions.InstallInBuildFolder) != 0 && SupportsInstallInBuildFolder(target);\n            if (installPath == String.Empty && !willInstallInBuildFolder)\n                throw new Exception(installPath + \" must not be an empty string\");\n\n            IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(target);\n            if (postprocessor == null)\n                // If postprocessor is not provided, build target is not supported\n                throw new UnityException($\"Build target '{target}' not supported\");\n\n            try\n            {\n                AddIconsArgs iconArgs;\n                iconArgs.stagingArea = stagingArea;\n                if (!postprocessor.AddIconsToBuild(iconArgs))\n                    throw new BuildFailedException(\"Failed to add player icon\");\n\n                BuildPostProcessArgs args;\n                args.target = target;\n                args.subtarget = subtarget;\n                args.stagingAreaData = stagingAreaData;\n                args.stagingArea = stagingArea;\n                args.stagingAreaDataManaged = stagingAreaDataManaged;\n                args.playerPackage = playerPackage;\n                args.installPath = installPath;\n                args.companyName = companyName;\n                args.productName = productName;\n                args.productGUID = PlayerSettings.productGUID;\n                args.options = options;\n                args.usedClassRegistry = usedClassRegistry;\n                args.report = report;\n\n                BuildProperties props;\n                postprocessor.PostProcess(args, out props);\n\n                if (props != null)\n                {\n                    report.AddAppendix(props);\n                }\n\n                return;\n            }\n            catch (BuildFailedException)\n            {\n                throw;\n            }\n            catch (Exception e)\n            {\n                // Rethrow exceptions during build postprocessing as BuildFailedException, so we don't pretend the build was fine.\n                throw new BuildFailedException(e);\n            }\n        }\n\n        public static void PostProcessCompletedBuild(BuildPostProcessArgs args)\n        {\n            var postprocessor = ModuleManager.GetBuildPostProcessor(args.target);\n            postprocessor.PostProcessCompletedBuild(args);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/RenderPipeline/EnsureSinglePipelineOnBuild.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.Build.Reporting;\nusing UnityEngine;\n\nnamespace UnityEditor.Build.Rendering\n{\n    class EnsureSinglePipelineOnBuild : IPreprocessBuildWithReport\n    {\n        public int callbackOrder => (int) ExecutionOrder.EnsureSinglePipeline;\n\n        public void OnPreprocessBuild(BuildReport report)\n        {\n            var buildTargetGroupName = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget).ToString();\n            if (!QualitySettings.SamePipelineAssetsForPlatform(buildTargetGroupName))\n                throw new BuildFailedException($\"The current build target has assets in its associated Quality levels and Graphics Settings that belong to different render pipelines. Please check your settings.\");\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/RenderPipeline/RenderPipelineBuildProcessor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor.Build.Rendering\n{\n    enum ExecutionOrder\n    {\n        EnsureSinglePipeline = int.MinValue,\n        StripRenderPipelineGlobalSettingsAsset,\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/RenderPipeline/RenderPipelineGlobalSettingsStripper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.Build.Reporting;\nusing UnityEditor.Rendering;\nusing UnityEngine;\nusing UnityEngine.Pool;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor.Build.Rendering\n{\n    class RenderPipelineGlobalSettingsStripper : IPreprocessBuildWithReport, IPostprocessBuildWithReport\n    {\n        public int callbackOrder => (int) ExecutionOrder.StripRenderPipelineGlobalSettingsAsset;\n\n        static bool s_IsCurrentRenderPipelineGlobalsSettingsDirty;\n        static bool s_IsGraphicsSettingsDirty;\n\n        public void OnPreprocessBuild(BuildReport report)\n        {\n            s_IsCurrentRenderPipelineGlobalsSettingsDirty = false;\n            s_IsGraphicsSettingsDirty = false;\n\n            var renderPipelineAssets = ListPool<RenderPipelineAsset>.Get();\n\n            var buildTargetGroupName = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget).ToString();\n            QualitySettings.GetAllRenderPipelineAssetsForPlatform(buildTargetGroupName, ref renderPipelineAssets);\n\n            if (renderPipelineAssets.Count > 0 && renderPipelineAssets[0] != null)\n            {\n                // Top level stripping, even if there are multiple pipelines registered into the project, as we are building we are making sure the only one that is being transferred into the player is the current one.\n                if (renderPipelineAssets[0].pipelineType != null)\n                {\n                    var renderPipelineGlobalSettingsAsset = EditorGraphicsSettings.GetRenderPipelineGlobalSettingsAsset(renderPipelineAssets[0].pipelineType);\n\n                    if (renderPipelineGlobalSettingsAsset != null)\n                    {\n                        s_IsGraphicsSettingsDirty = EditorUtility.IsDirty(GraphicsSettings.GetGraphicsSettings());\n                        s_IsCurrentRenderPipelineGlobalsSettingsDirty = EditorUtility.IsDirty(renderPipelineGlobalSettingsAsset);\n\n                        // The asset needs to be dirty, in order to tell the BuildPlayer to always transfer the latest state of the asset.\n                        // The main reason is due to IRenderPipelineGraphicsSettings stripping from the user side.\n\n                        if (!s_IsCurrentRenderPipelineGlobalsSettingsDirty)\n                            EditorUtility.SetDirty(renderPipelineGlobalSettingsAsset);\n\n                        GraphicsSettings.currentRenderPipelineGlobalSettings = renderPipelineGlobalSettingsAsset;\n                    }\n                }\n                else\n                    Debug.LogWarning($\"{renderPipelineAssets[0].GetType().Name} must inherit from {nameof(RenderPipelineAsset)}<T> instead of {nameof(RenderPipelineAsset)} to benefit from {nameof(RenderPipelineGlobalSettingsStripper)}.\");\n            }\n\n            ListPool<RenderPipelineAsset>.Release(renderPipelineAssets);\n        }\n\n        public void OnPostprocessBuild(BuildReport report)\n        {\n            if (GraphicsSettings.currentRenderPipelineGlobalSettings != null)\n            {\n                // Clean the previous dirty flag.\n                if (!s_IsCurrentRenderPipelineGlobalsSettingsDirty)\n                    EditorUtility.ClearDirty(GraphicsSettings.currentRenderPipelineGlobalSettings);\n\n                // Set to null the asset, and clean the dirty flag\n                GraphicsSettings.currentRenderPipelineGlobalSettings = null;\n                if (!s_IsGraphicsSettingsDirty)\n                    EditorUtility.ClearDirty(GraphicsSettings.GetGraphicsSettings());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/RuntimeClassMetadata.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing UnityEditor.Compilation;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEngine.Scripting;\nusing System.Diagnostics;\n\nnamespace UnityEditor\n{\n    /// <summary>\n    ///  Registry for Unity native-managed class dependencies. Aimed to make native and managed code stripping possible.\n    ///  Note: only UnityEngine.dll content is covered there.\n    /// </summary>\n    internal class RuntimeClassRegistry\n    {\n        protected Dictionary<string, HashSet<string>> serializedClassesPerAssembly = new Dictionary<string, HashSet<string>>();\n        protected Dictionary<string, HashSet<string>> m_UsedTypesPerUserAssembly = new Dictionary<string, HashSet<string>>();\n        protected Dictionary<int, List<string>> classScenes = new Dictionary<int, List<string>>();\n        protected UnityType objectUnityType = null;\n\n        public Dictionary<string, HashSet<string>> UsedTypePerUserAssembly\n        {\n            get { return m_UsedTypesPerUserAssembly; }\n        }\n\n        // Store all registered native classes (including managers) here.\n        // This is a step in the refactor of native code stripping. RuntimeClassRegistry should only be carrying this information to post process scripts rather than doing so much.\n        protected Dictionary<int, string> allNativeClasses = new Dictionary<int, string>();\n\n        public List<string> GetScenesForClass(int ID)\n        {\n            if (!classScenes.ContainsKey(ID))\n                return null;\n            return classScenes[ID];\n        }\n\n        [RequiredByNativeCode]\n        public void AddNativeClassID(int ID)\n        {\n            string className = UnityType.FindTypeByPersistentTypeID(ID).name;\n            ////System.Console.WriteLine(\"Looking for ID {0} name {1} --> is manager? {2}\", ID, className, functionalityGroups.ContainsValue(className));\n\n            // Native class found\n            if (className.Length > 0)\n                allNativeClasses[ID] = className;\n        }\n\n        [RequiredByNativeCode]\n        public void SetUsedTypesInUserAssembly(string[] typeNames, string assemblyName)\n        {\n            string assemblyFileName = assemblyName;\n            if (!assemblyFileName.EndsWith(\".dll\"))\n            {\n                assemblyFileName = assemblyName + \".dll\";\n            }\n\n            if (!m_UsedTypesPerUserAssembly.TryGetValue(assemblyFileName, out HashSet<string> types))\n            {\n                m_UsedTypesPerUserAssembly[assemblyFileName] = types = new HashSet<string>();\n            }\n\n            foreach (var typeName in typeNames)\n                types.Add(typeName);\n        }\n\n        [RequiredByNativeCode]\n        public void SetSerializedTypesInUserAssembly(string[] typeNames, string assemblyName)\n        {\n            if (!serializedClassesPerAssembly.TryGetValue(assemblyName, out HashSet<string> types))\n                serializedClassesPerAssembly[assemblyName] = types = new HashSet<string>();\n\n            foreach (var typeName in typeNames)\n                types.Add(typeName);\n        }\n\n        private static readonly string[] s_TreatedAsUserAssemblies =\n        {\n            // Treat analytics as we user assembly. If it is not used, it won't be in the directory,\n            // so this should not add to the build size unless it is really used.\n            \"Unity.Analytics.dll\",\n        };\n\n        private static string[] GetTargetUserAssemblyNames()\n        {\n            EditorCompilation.TargetAssemblyInfo[] allTargetAssemblies = EditorCompilationInterface.GetTargetAssemblyInfos();\n\n            string[] targetAssemblyNames = new string[allTargetAssemblies.Length + s_TreatedAsUserAssemblies.Length];\n\n            for (int i = 0; i < allTargetAssemblies.Length; ++i)\n            {\n                targetAssemblyNames[i] = allTargetAssemblies[i].Name;\n            }\n            for (int i = 0; i < s_TreatedAsUserAssemblies.Length; ++i)\n            {\n                targetAssemblyNames[allTargetAssemblies.Length + i] = s_TreatedAsUserAssemblies[i];\n            }\n            for (int i=0; i<targetAssemblyNames.Length; ++i)\n            {\n                if (!targetAssemblyNames[i].EndsWith(\".dll\"))\n                    targetAssemblyNames[i] += \".dll\";\n            }\n            return targetAssemblyNames;\n        }\n\n        private bool IsAssemblyDLLUsed(string assemblyName, string[] userAssemblyNames) \n        {\n            Debug.Assert(assemblyName.EndsWith(\".dll\"));\n            if (m_UsedTypesPerUserAssembly == null)\n                return true;\n\n            if (Array.IndexOf(userAssemblyNames, assemblyName) != -1)\n            {\n                // Don't treat code in packages as used automatically (case 1003047).\n                var asmdefPath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(assemblyName);\n                if (asmdefPath == null || !EditorCompilationInterface.Instance.IsPathInPackageDirectory(asmdefPath))\n                    return true;\n            }\n            bool isUsed = m_UsedTypesPerUserAssembly.ContainsKey(assemblyName);\n            return isUsed;\n        }\n\n        protected void AddUsedClass(string assemblyName, string className)\n        {\n            if (string.IsNullOrEmpty(assemblyName))\n                throw new ArgumentException(nameof(assemblyName));\n\n            if (string.IsNullOrEmpty(className))\n                throw new ArgumentException(nameof(className));\n\n            string assemblyFileName = assemblyName;\n            if (!assemblyFileName.EndsWith(\".dll\"))\n            {\n                assemblyFileName = assemblyName + \".dll\";\n            }\n            if (!m_UsedTypesPerUserAssembly.TryGetValue(assemblyFileName, out HashSet<string> types))\n            {\n                m_UsedTypesPerUserAssembly[assemblyFileName] = types = new HashSet<string>();\n            }\n\n            types.Add(className);\n        }\n\n        [RequiredByNativeCode]\n        protected void AddSerializedClass(string assemblyName, string className)\n        {\n            if (string.IsNullOrEmpty(assemblyName))\n                throw new ArgumentException(nameof(assemblyName));\n\n            if (string.IsNullOrEmpty(className))\n                throw new ArgumentException(nameof(className));\n\n            if (!serializedClassesPerAssembly.TryGetValue(assemblyName, out HashSet<string> types))\n                serializedClassesPerAssembly[assemblyName] = types = new HashSet<string>();\n\n            types.Add(className);\n        }\n\n        public void AddNativeClassFromName(string className)\n        {\n            if (objectUnityType == null)\n                objectUnityType = UnityType.FindTypeByName(\"Object\");\n\n            var t = UnityType.FindTypeByName(className);\n\n            ////System.Console.WriteLine(\"Looking for name {1}  ID {0}\", classID, className);\n            if (t != null && t.persistentTypeID != objectUnityType.persistentTypeID)\n                allNativeClasses[t.persistentTypeID] = className;\n        }\n\n        public Dictionary<string, string[]> GetAllManagedTypesInScenes()\n        {\n            var items = new Dictionary<string, string[]>();\n\n            // Use a hashset to remove duplicate types.\n            // Duplicates of UnityEngine.Object will happen because native types without a managed type will come back as\n            // UnityEngine.Object\n            var engineModuleTypes = new HashSet<string>();\n            foreach (var nativeClassID in allNativeClasses.Keys)\n            {\n                var managedName = RuntimeClassMetadataUtils.ScriptingWrapperTypeNameForNativeID(nativeClassID);\n\n                if (string.IsNullOrEmpty(managedName))\n                    continue;\n\n                engineModuleTypes.Add(managedName);\n            }\n\n            bool engineModuleTypesAdded = false;\n            foreach (var userAssembly in m_UsedTypesPerUserAssembly)\n            {\n                if (userAssembly.Key == \"UnityEngine.dll\" && !engineModuleTypesAdded)\n                {\n                    engineModuleTypes.UnionWith(userAssembly.Value);\n                    items.Add(userAssembly.Key, engineModuleTypes.ToArray());\n                    engineModuleTypesAdded = true;\n                    continue;\n                }\n\n                items.Add(userAssembly.Key, userAssembly.Value.ToArray());\n            }\n            if (!engineModuleTypesAdded)\n            {\n                items.Add(\"UnityEngine.dll\", engineModuleTypes.ToArray());\n            }\n            return items;\n        }\n\n        public List<string> GetAllNativeClassesIncludingManagersAsString()\n        {\n            return new List<string>(allNativeClasses.Values);\n        }\n\n        public IEnumerable<KeyValuePair<string, string[]>> GetAllSerializedClassesAsString()\n        {\n            foreach (var pair in serializedClassesPerAssembly)\n            {\n                yield return new KeyValuePair<string, string[]>(pair.Key, pair.Value.ToArray());\n            }\n        }\n\n        [RequiredByNativeCode]\n        public MethodDescription[] GetAllMethodsToPreserve()\n        {\n            return m_MethodsToPreserve.ToArray();\n        }\n\n        [RequiredByNativeCode]\n        public string[] GetAllSerializedClassesAssemblies()\n        {\n            return serializedClassesPerAssembly.Keys.ToArray();\n        }\n\n        [RequiredByNativeCode]\n        public string[] GetAllSerializedClassesForAssembly(string assembly)\n        {\n            return serializedClassesPerAssembly[assembly].ToArray();\n        }\n\n        [RequiredByNativeCode]\n        public static RuntimeClassRegistry Create()\n        {\n            return new RuntimeClassRegistry();\n        }\n\n        [RequiredByNativeCode]\n        public void Initialize(int[] nativeClassIDs)\n        {\n            foreach (int ID in nativeClassIDs)\n                AddNativeClassID(ID);\n        }\n\n        [RequiredByNativeCode]\n        public void SetSceneClasses(int[] nativeClassIDs, string scene)\n        {\n            foreach (int ID in nativeClassIDs)\n            {\n                AddNativeClassID(ID);\n                if (!classScenes.ContainsKey(ID))\n                    classScenes[ID] = new List<string>();\n                classScenes[ID].Add(scene);\n            }\n        }\n\n        // Needs to stay in sync with MethodDescription in Editor/Src/BuildPipeline/BuildSerialization.h\n        [StructLayout(LayoutKind.Sequential)]\n        internal class MethodDescription\n        {\n            public string assembly;\n            public string fullTypeName;\n            public string methodName;\n        }\n\n        internal List<MethodDescription> m_MethodsToPreserve = new List<MethodDescription>();\n\n        //invoked by native code\n        [RequiredByNativeCode]\n        public void AddMethodToPreserve(string assembly, string ns, string klassName, string methodName)\n        {\n            m_MethodsToPreserve.Add(new MethodDescription()\n            {\n                assembly = assembly,\n                fullTypeName = ns + (ns.Length > 0 ? \".\" : \"\") + klassName,\n                methodName = methodName\n            });\n        }\n\n        [RequiredByNativeCode]\n        public void AddMethodToPreserveWithFullTypeName(string assembly, string fullTypeName, string methodName)\n        {\n            m_MethodsToPreserve.Add(new MethodDescription()\n            {\n                assembly = assembly,\n                fullTypeName = fullTypeName,\n                methodName = methodName\n            });\n        }\n\n        internal List<MethodDescription> GetMethodsToPreserve()\n        {\n            return m_MethodsToPreserve;\n        }\n\n        internal List<string> m_UserAssemblies = new List<string>();\n\n        //invoked by native code\n        [RequiredByNativeCode]\n        internal void AddUserAssembly(string assembly)\n        {\n            if (!m_UserAssemblies.Contains(assembly))\n                m_UserAssemblies.Add(assembly);\n        }\n\n        internal string[] GetUsedUserAssemblies()\n        {\n            var userAssemblyNames = GetTargetUserAssemblyNames();\n            return m_UserAssemblies.Where(s => IsAssemblyDLLUsed(s, userAssemblyNames)).ToArray();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/RuntimeClassMetadataUtils.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Runtime/Scripting/Scripting.h\")]\n    internal class RuntimeClassMetadataUtils\n    {\n        [FreeFunction(\"Scripting::ScriptingWrapperTypeNameForNativeID\")]\n        extern public static string ScriptingWrapperTypeNameForNativeID(int id);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline/UnityLinker/UnityLinkerBuildPipelineData.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.UnityLinker\n{\n    /// <summary>\n    /// Data exposed during IRunUnityLinker callbacks\n    /// </summary>\n    public sealed class UnityLinkerBuildPipelineData\n    {\n        public readonly BuildTarget target;\n        [Obsolete(\"For platforms using the new incremental build pipeline, inputDirectory will no longer contain any files\", false)]\n        public readonly string inputDirectory;\n\n        public UnityLinkerBuildPipelineData(BuildTarget target, string inputDirectory)\n        {\n            this.target = target;\n#pragma warning disable 618\n            this.inputDirectory = inputDirectory;\n#pragma warning restore\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipeline.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEditor.Build.Reporting;\nusing Mono.Cecil;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing System.Runtime.InteropServices;\nusing UnityEditor.Build;\nusing UnityEditor.Build.Profile;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    // Building options. Multiple options can be combined together.\n    [Flags]\n    public enum BuildOptions\n    {\n        // Perform the specified build without any special settings or extra tasks.\n        None = 0,\n\n        // Build a development version of the standalone player.\n        Development = 1 << 0,\n\n        // Run the built player.\n        AutoRunPlayer = 1 << 2,\n\n        // Show the built player.\n        ShowBuiltPlayer = 1 << 3,\n\n        // For internal use. Used when BuildAssetBundles implementation triggers part of the player build code path when packaging Scenes into AssetBundles.\n        BuildAdditionalStreamedScenes = 1 << 4,\n\n        // Do not overwrite player directory, but accept user's modifications.\n        AcceptExternalModificationsToPlayer = 1 << 5,\n\n        //*undocumented*\n        InstallInBuildFolder = 1 << 6,\n\n        // Do a non-incremental, clean cache build\n        CleanBuildCache = 1 << 7,\n\n        // automatically connects the profiler when the build is ran\n        ConnectWithProfiler = 1 << 8,\n\n        // Allow script debuggers to attach to the player remotely.\n        AllowDebugging = 1 << 9,\n\n        // Symlink runtime libraries when generating iOS XCode project. (Faster iteration time).\n        [Obsolete(\"BuildOptions.SymlinkLibraries is obsolete. Use BuildOptions.SymlinkSources instead (UnityUpgradable) -> [UnityEditor] BuildOptions.SymlinkSources\", false)]\n\n        SymlinkLibraries = 1 << 10,\n\n        // Symlink runtime libraries and reference externally .m, .mm, .c, .cpp, .swift files from Unity project when generating iOS XCode project.(Faster iteration time).\n        // Reference externally .java, .kt files when generating Android gradle project\n        SymlinkSources = 1 << 10,\n\n        // Don't compress the data when creating the asset bundle.\n        UncompressedAssetBundle = 1 << 11,\n\n        [Obsolete(\"Use BuildOptions.Development instead\")]\n        StripDebugSymbols = 0,\n        [Obsolete(\"Texture Compression is now always enabled\")]\n        CompressTextures = 0,\n\n        //Set the player to try to connect to the host\n        ConnectToHost = 1 << 12,\n\n        //custom connection id\n        CustomConnectionID = 1 << 13,\n\n        // Headless Mode\n        [Obsolete(\"Use StandaloneBuildSubtarget.Server instead\")]\n        EnableHeadlessMode = 1 << 14,\n\n        // Build scripts only\n        BuildScriptsOnly = 1 << 15,\n\n        PatchPackage = 1 << 16,\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"BuildOptions.IL2CPP is deprecated and has no effect. Use PlayerSettings.SetScriptingBackend() instead.\", true)]\n        Il2CPP = 0,\n\n        // Include assertions in non development builds\n        ForceEnableAssertions = 1 << 17,\n\n        // Forces chunk-based LZ4 compression for the asset bundle. Such asset bundles can be decompressed on the fly.\n        CompressWithLz4 = 1 << 18,\n\n        CompressWithLz4HC = 1 << 19,\n\n        //*undocumented*\n        [Obsolete(\"Specify IL2CPP optimization level in Player Settings.\")]\n        ForceOptimizeScriptCompilation = 0,\n\n        // Request that the CRC of the built output be computed and included in the build report\n        ComputeCRC = 1 << 20,\n\n        // Force the build to fail when any errors are encountered\n        StrictMode = 1 << 21,\n\n        IncludeTestAssemblies = 1 << 22,\n\n        // Will forces the buildGUID to all zeros\n        NoUniqueIdentifier = 1 << 23,\n\n        // Wait for player connection on start\n        WaitForPlayerConnection = 1 << 25,\n\n        // Enables Code Coverage. Can be used as a complimentary way of enabling code coverage on platforms\n        // that do not support command line arguments\n        EnableCodeCoverage = 1 << 26,\n\n        // Only needed internally for AssetBundleStripUnityVersion\n        //StripUnityVersion = 1 << 27\n\n        // Enable C# code instrumentation for the player.\n        EnableDeepProfilingSupport = 1 << 28,\n\n        // The BuildReport object returned by BuildPipeline.BuildPlayer will contain more details (about build times and contents), at the cost of a slightly (typically, a few percents) longer build time\n        DetailedBuildReport = 1 << 29,\n\n        [Obsolete(\"Shader LiveLink is no longer supported.\")]\n        ShaderLivelinkSupport = 0,\n\n    }\n\n    // Asset Bundle building options.\n    [Flags]\n    public enum BuildAssetBundleOptions\n    {\n        // Perform the build without any special option.\n        None = 0,\n\n        // Don't compress the data when creating the asset bundle.\n        UncompressedAssetBundle = 1, // 1 << 0\n\n        // Includes all dependencies.\n        [Obsolete(\"This has been made obsolete. It is always enabled in the new AssetBundle build system introduced in 5.0.\")]\n        CollectDependencies = 2, // 1 << 1\n\n        // Forces inclusion of the entire asset.\n        [Obsolete(\"This has been made obsolete. It is always disabled in the new AssetBundle build system introduced in 5.0.\")]\n        CompleteAssets = 4, // 1 << 2\n\n        // Do not include type information within the AssetBundle.\n        DisableWriteTypeTree = 8, // 1 << 3\n\n        // Builds an asset bundle using a hash for the id of the object stored in the asset bundle.\n        [Obsolete(\"This has been made obsolete. It is always enabled in the new AssetBundle build system introduced in 5.0.\")]\n        DeterministicAssetBundle = 16, // 1 << 4\n\n        // Force rebuild the asset bundle.\n        ForceRebuildAssetBundle = 32, // 1 << 5\n\n        // Ignore the type tree changes.\n        IgnoreTypeTreeChanges = 64, // 1 << 6,\n\n        // Append hash to the output name.\n        AppendHashToAssetBundleName = 128, // 1 << 7\n\n        // Forces chunk-based LZ4 compression for the asset bundle. Such asset bundles can be decompressed on the fly.\n        ChunkBasedCompression = 256, // 1 << 8\n\n        // Force the build to fail when any errors are encountered\n        StrictMode = 512, // 1 << 9\n\n        // Do a dry run build which doesn't actually build the asset bundles.\n        DryRunBuild = 1024, // 1 << 10\n\n        // Turns off loading an asset using file name. Results in faster AssetBundle.LoadFromFile.\n        DisableLoadAssetByFileName = 4096, // 1 << 12,\n\n        // Turns off loading an asset using file name + extension. Results in faster AssetBundle.LoadFromFile.\n        DisableLoadAssetByFileNameWithExtension = 8192, // 1 << 13,\n\n        //kAssetBundleAllowEditorOnlyScriptableObjects is defined in the native BuildAssetBundleOptions as 1 << 14\n        //AssetBundleAllowEditorOnlyScriptableObjects = 1 << 14,\n\n        //Removes the Unity Version number in the Archive File & Serialized File headers during the build.\n        AssetBundleStripUnityVersion = 32768, // 1 << 15\n\n        // Calculate bundle hash on the bundle content\n        UseContentHash = 65536, // 1 << 16\n\n        // Use when AssetBundle dependencies need to be calculated recursively, such as when you have a dependency chain of matching typed Scriptable Objects\n        RecurseDependencies = 131072, // 1 << 17\n\n        // Sprites are normally copied to all bundles that reference them. This flag prevents that behavior if the sprite is not in an atlas.\n        StripUnatlasedSpriteCopies = 262144 // 1 << 18\n    }\n\n    // Keep in sync with CanAppendBuild in EditorUtility.h\n    public enum CanAppendBuild\n    {\n        Unsupported = 0,\n        Yes = 1,\n        No = 2,\n    }\n\n    public struct AssetBundleBuild\n    {\n        public string   assetBundleName;\n        public string   assetBundleVariant;\n        public string[] assetNames;\n        [NativeName(\"nameOverrides\")]\n        public string[] addressableNames;\n    }\n\n    // NB! Keep in sync with BuildPlayerOptionsManagedStruct in Editor/Src/BuildPipeline/BuildPlayerOptions.h\n    [StructLayout(LayoutKind.Sequential)]\n    public struct BuildPlayerOptions\n    {\n        public string[] scenes {get; set; }\n        public string locationPathName {get; set; }\n        public string assetBundleManifestPath {get; set; }\n        public BuildTargetGroup targetGroup {get; set; }\n        public BuildTarget target {get; set; }\n        public int subtarget { get; set; }\n        public BuildOptions options {get; set; }\n        public string[] extraScriptingDefines { get; set; }\n    }\n\n    public struct BuildPlayerWithProfileOptions\n    {\n        public BuildProfile buildProfile { get; set; }\n        public string locationPathName { get; set; }\n        public string assetBundleManifestPath { get; set; }\n        public BuildOptions options { get; set; }\n    }\n\n    internal struct BuildPlayerDataOptions\n    {\n        public string[] scenes { get; set; }\n        public BuildTargetGroup targetGroup { get; set; }\n        public BuildTarget target { get; set; }\n        public int subtarget { get; set; }\n        public BuildOptions options { get; set; }\n        public string[] extraScriptingDefines { get; set; }\n    }\n\n    // Keep in sync with Runtime\\Network\\PlayerCommunicator\\PlayerConnectionTypes.h\n    public enum PlayerConnectionInitiateMode\n    {\n        None,\n        PlayerConnectsToHost,\n        PlayerListens\n    }\n\n\n    [StructLayout(LayoutKind.Sequential)]\n    public struct BuildAssetBundlesParameters\n    {\n        public string outputPath { get; set; }\n        public AssetBundleBuild[] bundleDefinitions { get; set; }\n        public BuildAssetBundleOptions options { get; set; }\n        public BuildTarget targetPlatform { get; set; }\n        public int subtarget { get; set; }\n        public string[] extraScriptingDefines { get; set; }\n    }\n\n    // Lets you programmatically build players or AssetBundles which can be loaded from the web.\n    [NativeHeader(\"Editor/Mono/BuildPipeline.bindings.h\")]\n    [StaticAccessor(\"BuildPipeline\", StaticAccessorType.DoubleColon)]\n    public class BuildPipeline\n    {\n        [FreeFunction(IsThreadSafe = true)]\n        public static extern BuildTargetGroup GetBuildTargetGroup(BuildTarget platform);\n\n        // Uses the implementation in \"BuildPipeline.bindings.h\"\n        internal static extern BuildTargetGroup GetBuildTargetGroupByName(string platform);\n\n        internal static extern BuildTarget GetBuildTargetByName(string platform);\n        internal static extern EditorScriptCompilationOptions GetScriptCompileFlags(BuildOptions buildOptions, BuildTarget buildTarget);\n\n        [FreeFunction]\n        internal static extern string GetBuildTargetGroupDisplayName(BuildTargetGroup targetPlatformGroup);\n\n        [FreeFunction(\"GetBuildTargetUniqueName\", IsThreadSafe = true)]\n        public static extern string GetBuildTargetName(BuildTarget targetPlatform);\n\n        [FreeFunction(IsThreadSafe = true)]\n        internal static extern string GetEditorTargetName();\n\n        [NativeHeader(\"Editor/Src/BuildPipeline/BuildPlayerHelpers.h\")]\n        [FreeFunction]\n        internal static extern void ShowBuildProfileWindow();\n\n        [Obsolete(\"PushAssetDependencies has been made obsolete. Please use the new AssetBundle build system introduced in 5.0 and check BuildAssetBundles documentation for details.\", true)]\n        [FreeFunction]\n        public static extern void PushAssetDependencies();\n\n        [Obsolete(\"PopAssetDependencies has been made obsolete. Please use the new AssetBundle build system introduced in 5.0 and check BuildAssetBundles documentation for details.\", true)]\n        [FreeFunction]\n        public static extern void PopAssetDependencies();\n\n        private static void LogBuildExceptionAndExit(string buildFunctionName, System.Exception exception)\n        {\n            Debug.LogErrorFormat(\"Internal Error in {0}:\", buildFunctionName);\n            Debug.LogException(exception);\n            EditorApplication.Exit(1);\n        }\n\n        [FreeFunction]\n        public extern static CanAppendBuild BuildCanBeAppended(BuildTarget target, string location);\n\n        [RequiredByNativeCode]\n        internal static BuildPlayerContext PreparePlayerBuild(BuildPlayerOptions buildPlayerOptions)\n        {\n            var buildPlayerContext = new BuildPlayerContext(buildPlayerOptions);\n            BuildPipelineInterfaces.PreparePlayerBuild(buildPlayerContext);\n            return buildPlayerContext;\n        }\n\n        /// <summary>\n        /// Builds a player.\n        /// </summary>\n        /// <param name=\"buildPlayerWithProfileOptions\">The BuildPlayerWithProfileOptions to be built with.</param>\n        /// <returns>A BuildReport giving build process information.</returns>\n        /// <exception cref=\"ArgumentException\">Throws if build profile is null.</exception>\n        public static BuildReport BuildPlayer(BuildPlayerWithProfileOptions buildPlayerWithProfileOptions)\n        {\n            var buildProfile = buildPlayerWithProfileOptions.buildProfile;\n            if (buildProfile == null)\n                throw new ArgumentException(\"Build profile is invalid.\");\n\n            BuildProfileContext.activeProfile = buildProfile;\n            var buildPlayerOptions = BuildProfileModuleUtil.GetBuildPlayerOptionsFromActiveProfile(\n                buildPlayerWithProfileOptions.locationPathName, buildPlayerWithProfileOptions.assetBundleManifestPath, buildPlayerWithProfileOptions.options);\n            return BuildPlayer(buildPlayerOptions);\n        }\n\n        public static BuildReport BuildPlayer(EditorBuildSettingsScene[] levels, string locationPathName, BuildTarget target, BuildOptions options)\n        {\n            BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();\n            buildPlayerOptions.scenes = EditorBuildSettingsScene.GetActiveSceneList(levels);\n            buildPlayerOptions.locationPathName = locationPathName;\n            buildPlayerOptions.target = target;\n            buildPlayerOptions.subtarget = EditorUserBuildSettings.GetActiveSubtargetFor(target);\n            buildPlayerOptions.options = options;\n            return BuildPlayer(buildPlayerOptions);\n        }\n\n        public static BuildReport BuildPlayer(string[] levels, string locationPathName, BuildTarget target, BuildOptions options)\n        {\n            BuildTargetGroup buildTargetGroup = GetBuildTargetGroup(target);\n            BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();\n            buildPlayerOptions.scenes = levels;\n            buildPlayerOptions.locationPathName = locationPathName;\n            buildPlayerOptions.targetGroup = buildTargetGroup;\n            buildPlayerOptions.target = target;\n            buildPlayerOptions.subtarget = EditorUserBuildSettings.GetActiveSubtargetFor(target);\n            buildPlayerOptions.options = options;\n            return BuildPlayer(buildPlayerOptions);\n        }\n\n        public static BuildReport BuildPlayer(BuildPlayerOptions buildPlayerOptions)\n        {\n            return BuildPlayer(buildPlayerOptions.scenes, buildPlayerOptions.locationPathName, buildPlayerOptions.assetBundleManifestPath, buildPlayerOptions.targetGroup, buildPlayerOptions.target, buildPlayerOptions.subtarget, buildPlayerOptions.options, buildPlayerOptions.extraScriptingDefines);\n        }\n\n        private static BuildReport BuildPlayer(string[] scenes, string locationPathName, string assetBundleManifestPath, BuildTargetGroup buildTargetGroup, BuildTarget target, int subtarget, BuildOptions options, string[] extraScriptingDefines)\n        {\n            if (isBuildingPlayer)\n                throw new InvalidOperationException(\"Cannot start a new build because there is already a build in progress.\");\n\n            if (buildTargetGroup == BuildTargetGroup.Unknown)\n                buildTargetGroup = GetBuildTargetGroup(target);\n\n            string locationPathNameError;\n            if (!ValidateLocationPathNameForBuildTarget(locationPathName, target, subtarget, options, out locationPathNameError))\n                throw new ArgumentException(locationPathNameError);\n\n            string scenesError;\n            if (!ValidateScenePaths(scenes, out scenesError))\n                throw new ArgumentException(scenesError);\n\n            if ((options & BuildOptions.AcceptExternalModificationsToPlayer) == BuildOptions.AcceptExternalModificationsToPlayer)\n            {\n                CanAppendBuild canAppend = BuildCanBeAppended(target, locationPathName);\n                if (canAppend == CanAppendBuild.Unsupported)\n                    throw new InvalidOperationException(\"The build target does not support build appending.\");\n                if (canAppend == CanAppendBuild.No)\n                    throw new InvalidOperationException(\"The build cannot be appended.\");\n            }\n\n            if (scenes != null)\n            {\n                for (int i = 0; i < scenes.Length; i++)\n                    scenes[i] = scenes[i].Replace('\\\\', '/').Replace(\"//\", \"/\");\n            }\n\n            if ((options & BuildOptions.Development) == 0)\n            {\n                if ((options & BuildOptions.AllowDebugging) != 0)\n                {\n                    throw new ArgumentException(\"Non-development build cannot allow debugging. Either add the Development build option, or remove the AllowDebugging build option.\");\n                }\n\n                if ((options & BuildOptions.EnableDeepProfilingSupport) != 0)\n                {\n                    throw new ArgumentException(\"Non-development build cannot allow deep profiling support. Either add the Development build option, or remove the EnableDeepProfilingSupport build option.\");\n                }\n\n                if ((options & BuildOptions.ConnectWithProfiler) != 0)\n                {\n                    throw new ArgumentException(\"Non-development build cannot allow auto-connecting the profiler. Either add the Development build option, or remove the ConnectWithProfiler build option.\");\n                }\n            }\n\n            try\n            {\n                return BuildPlayerInternal(scenes, locationPathName, assetBundleManifestPath, buildTargetGroup, target, subtarget, options, extraScriptingDefines);\n            }\n            catch (System.ArgumentException argumentException)\n            {\n                Debug.LogException(argumentException);\n                return null;\n            }\n            catch (System.Exception exception)\n            {\n                // In some case BuildPlayer might let a null reference exception fall through. Prevent data loss by just exiting.\n                LogBuildExceptionAndExit(\"BuildPipeline.BuildPlayer\", exception);\n                return null;\n            }\n        }\n\n        internal static bool ValidateLocationPathNameForBuildTarget(string locationPathName, BuildTarget target, int subtarget, BuildOptions options, out string errorMessage)\n        {\n            if (string.IsNullOrEmpty(locationPathName))\n            {\n                var willInstallInBuildFolder = (options & BuildOptions.InstallInBuildFolder) != 0 &&\n                    PostprocessBuildPlayer.SupportsInstallInBuildFolder(target);\n                if (!willInstallInBuildFolder)\n                {\n                    errorMessage =\n                        \"The 'locationPathName' parameter for BuildPipeline.BuildPlayer should not be null or empty.\";\n                    return false;\n                }\n            }\n            else if (string.IsNullOrEmpty(Path.GetFileName(locationPathName)))\n            {\n                var extensionForBuildTarget = PostprocessBuildPlayer.GetExtensionForBuildTarget(target, subtarget, options);\n\n                if (!string.IsNullOrEmpty(extensionForBuildTarget))\n                {\n                    errorMessage = string.Format(\n                        \"For the '{0}' target the 'locationPathName' parameter for BuildPipeline.BuildPlayer should not end with a directory separator.\\n\" +\n                        \"Provided path: '{1}', expected a path with the extension '.{2}'.\", target, locationPathName,\n                        extensionForBuildTarget);\n                    return false;\n                }\n            }\n\n            errorMessage = \"\";\n\n            return true;\n        }\n\n        internal static bool ValidateScenePaths(string[] scenes, out string errorMessage)\n        {\n            if (scenes != null)\n            {\n                for (int i = 0; i < scenes.Length; i++)\n                {\n                    string scenePath = scenes[i].Replace('\\\\', '/');\n\n                    if (scenePath.Contains(\"///\"))\n                    {\n                        errorMessage = string.Format(\"Scene path \\\"{0}\\\" contains invalid directory separators.\", scenes[i]);\n                        return false;\n                    }\n                }\n            }\n\n            errorMessage = \"\";\n\n            return true;\n        }\n\n        [FreeFunction]\n        internal static extern bool IsFeatureSupported(string define, BuildTarget platform);\n\n        // Builds one or more scenes and all their dependencies into a compressed asset bundle.\n        [Obsolete(\"BuildStreamedSceneAssetBundle has been made obsolete. Please use the new AssetBundle build system introduced in 5.0 and check BuildAssetBundles documentation for details.\", true)]\n        public static string BuildStreamedSceneAssetBundle(string[] levels, string locationPath, BuildTarget target, BuildOptions options) { return \"\"; }\n\n        // Builds one or more scenes and all their dependencies into a compressed asset bundle.\n        [Obsolete(\"BuildStreamedSceneAssetBundle has been made obsolete. Please use the new AssetBundle build system introduced in 5.0 and check BuildAssetBundles documentation for details.\", true)]\n        public static string BuildStreamedSceneAssetBundle(string[] levels, string locationPath, BuildTarget target) { return \"\"; }\n\n        // Builds one or more scenes and all their dependencies into a compressed asset bundle.\n        [Obsolete(\"BuildStreamedSceneAssetBundle has been made obsolete. Please use the new AssetBundle build system introduced in 5.0 and check BuildAssetBundles documentation for details.\", true)]\n        public static string BuildStreamedSceneAssetBundle(string[] levels, string locationPath, BuildTarget target, out uint crc, BuildOptions options)\n        {\n            crc = 0;\n            return \"\";\n        }\n\n        // Builds one or more scenes and all their dependencies into a compressed asset bundle.\n        [Obsolete(\"BuildStreamedSceneAssetBundle has been made obsolete. Please use the new AssetBundle build system introduced in 5.0 and check BuildAssetBundles documentation for details.\", true)]\n        internal static string BuildStreamedSceneAssetBundle(string[] levels, string locationPath, BuildTargetGroup buildTargetGroup, BuildTarget target, int subtarget, out uint crc, BuildOptions options)\n        {\n            crc = 0;\n            return \"\";\n        }\n\n        // Builds one or more scenes and all their dependencies into a compressed asset bundle.\n        [Obsolete(\"BuildStreamedSceneAssetBundle has been made obsolete. Please use the new AssetBundle build system introduced in 5.0 and check BuildAssetBundles documentation for details.\", true)]\n        public static string BuildStreamedSceneAssetBundle(string[] levels, string locationPath, BuildTarget target, out uint crc)\n        {\n            crc = 0;\n            return \"\";\n        }\n\n        private static BuildReport BuildPlayerInternal(string[] levels, string locationPathName, string assetBundleManifestPath, BuildTargetGroup buildTargetGroup, BuildTarget target, int subtarget, BuildOptions options, string[] extraScriptingDefines)\n        {\n            if (!BuildPlayerWindow.DefaultBuildMethods.IsBuildPathValid(locationPathName, out var msg))\n                throw new ArgumentException($\"Invalid build path: '{locationPathName}'. {msg}\");\n\n            if (buildTargetGroup == BuildTargetGroup.Standalone)\n            {\n                if (subtarget == (int)StandaloneBuildSubtarget.Default)\n                    subtarget = (int)EditorUserBuildSettings.standaloneBuildSubtarget;\n\n                EditorUserBuildSettings.standaloneBuildSubtarget = (StandaloneBuildSubtarget)subtarget;\n            }\n\n            return BuildPlayerInternalNoCheck(levels, locationPathName, assetBundleManifestPath, buildTargetGroup, target, subtarget, options, extraScriptingDefines, false);\n        }\n\n        // Is a player currently building?\n        public static extern bool isBuildingPlayer { [FreeFunction(\"IsBuildingPlayer\")] get; }\n\n        // Just like BuildPlayer, but does not check for Pro license. Used from build player dialog.\n        internal static extern BuildReport BuildPlayerInternalNoCheck(string[] levels, string locationPathName, string assetBundleManifestPath, BuildTargetGroup buildTargetGroup, BuildTarget target, int subtarget, BuildOptions options, string[] extraScriptingDefines, bool delayToAfterScriptReload);\n\n        internal static extern void BuildPlayerInternalPostBuild(BuildReport report);\n\n        [FreeFunction(\"WriteBootConfigInternal\", ThrowsException = true)]\n        static extern void WriteBootConfigInternal(string outputFile, BuildTarget target, BuildOptions options);\n\n        public static void WriteBootConfig(string outputFile, BuildTarget target, BuildOptions options)\n        {\n            WriteBootConfigInternal(outputFile,  target, options);\n        }\n\n        [StructLayout(LayoutKind.Sequential)]\n        private struct BuildPlayerDataResult\n        {\n            internal BuildReport report;\n            internal RuntimeClassRegistry usedClasses;\n        }\n\n        internal static BuildReport BuildPlayerData(BuildPlayerDataOptions buildPlayerDataOptions, out RuntimeClassRegistry usedClasses)\n        {\n            if (GetBuildTargetGroup(buildPlayerDataOptions.target) == BuildTargetGroup.Standalone &&\n                buildPlayerDataOptions.subtarget == (int)StandaloneBuildSubtarget.Default)\n            {\n                buildPlayerDataOptions.subtarget = (int) EditorUserBuildSettings.standaloneBuildSubtarget;\n            }\n\n            var result = BuildPlayerData(buildPlayerDataOptions);\n            usedClasses = result.usedClasses;\n            return result.report;\n        }\n\n        private static extern BuildPlayerDataResult BuildPlayerData(BuildPlayerDataOptions buildPlayerDataOptions);\n#pragma warning disable 618\n\n        // Builds an AssetBundle.\n        [Obsolete(\"BuildAssetBundle has been made obsolete. Please use the new AssetBundle build system introduced in 5.0 and check BuildAssetBundles documentation for details.\", true)]\n        public static bool BuildAssetBundle(UnityEngine.Object mainAsset, UnityEngine.Object[] assets, string pathName, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform) { return false; }\n\n        [Obsolete(\"BuildAssetBundle has been made obsolete. Please use the new AssetBundle build system introduced in 5.0 and check BuildAssetBundles documentation for details.\", true)]\n        public static bool BuildAssetBundle(UnityEngine.Object mainAsset, UnityEngine.Object[] assets, string pathName, out uint crc, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform)\n        {\n            crc = 0;\n            return false;\n        }\n\n        // Builds an AssetBundle, with custom names for the assets.\n        [Obsolete(\"BuildAssetBundleExplicitAssetNames has been made obsolete. Please use the new AssetBundle build system introduced in 5.0 and check BuildAssetBundles documentation for details.\", true)]\n        public static bool BuildAssetBundleExplicitAssetNames(UnityEngine.Object[] assets, string[] assetNames, string pathName, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform)\n        {\n            return false;\n        }\n\n        // Builds an AssetBundle, with custom names for the assets.\n        [Obsolete(\"BuildAssetBundleExplicitAssetNames has been made obsolete. Please use the new AssetBundle build system introduced in 5.0 and check BuildAssetBundles documentation for details.\", true)]\n        public static bool BuildAssetBundleExplicitAssetNames(UnityEngine.Object[] assets, string[] assetNames, string pathName, out uint crc, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform)\n        {\n            crc = 0;\n            return false;\n        }\n\n#pragma warning restore 618\n\n\n        public static AssetBundleManifest BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform)\n        {\n            BuildAssetBundlesParameters input = new BuildAssetBundlesParameters\n            {\n                outputPath = outputPath,\n                bundleDefinitions = null, // Bundle assignment will be read from AssetDatabase\n                options = assetBundleOptions,\n                targetPlatform = targetPlatform,\n                subtarget = EditorUserBuildSettings.GetActiveSubtargetFor(targetPlatform),\n            };\n\n            return BuildAssetBundles(input);\n        }\n\n        public static AssetBundleManifest BuildAssetBundles(string outputPath, AssetBundleBuild[] builds, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform)\n        {\n            if (builds == null)\n                // This signature is specifically meant for specifying the bundle definition array, so it is not optional\n                throw new ArgumentException(\"AssetBundleBuild cannot be null.\");\n\n            BuildAssetBundlesParameters input = new BuildAssetBundlesParameters\n            {\n                outputPath = outputPath,\n                bundleDefinitions = builds,\n                options = assetBundleOptions,\n                targetPlatform = targetPlatform,\n                subtarget = EditorUserBuildSettings.GetActiveSubtargetFor(targetPlatform),\n            };\n\n            return BuildAssetBundles(input);\n        }\n\n        public static AssetBundleManifest BuildAssetBundles(BuildAssetBundlesParameters buildParameters)\n        {\n            if (buildParameters.targetPlatform == 0 || buildParameters.targetPlatform == BuildTarget.NoTarget)\n            {\n                buildParameters.targetPlatform = EditorUserBuildSettings.activeBuildTarget;\n\n                // Note: subtarget is associated with multiple enums, and 0 may have a specific meaning,\n                // so we only auto-set it when the target is also coming from the build settings\n                buildParameters.subtarget = EditorUserBuildSettings.GetActiveSubtargetFor(buildParameters.targetPlatform);\n            }\n\n            // For Standalone platforms, the Default subtarget means to use the current active one\n            if (GetBuildTargetGroup(buildParameters.targetPlatform) == BuildTargetGroup.Standalone &&\n                (StandaloneBuildSubtarget)buildParameters.subtarget == StandaloneBuildSubtarget.Default)\n            {\n                buildParameters.subtarget = EditorUserBuildSettings.GetActiveSubtargetFor(buildParameters.targetPlatform);\n            }\n\n            if (isBuildingPlayer)\n                throw new InvalidOperationException(\"Cannot build asset bundles while a build is in progress.\");\n\n            if (!System.IO.Directory.Exists(buildParameters.outputPath))\n                throw new ArgumentException(\"The output path \\\"\" + buildParameters.outputPath + \"\\\" doesn't exist\");\n\n            return BuildAssetBundlesInternal(buildParameters);\n        }\n\n        [NativeThrows]\n        private static extern AssetBundleManifest BuildAssetBundlesInternal(BuildAssetBundlesParameters buildParameters);\n\n        [FreeFunction(\"GetPlayerDataSessionId\")]\n        internal static extern string GetSessionIdForBuildTarget(BuildTarget target, int subtarget);\n\n        [FreeFunction(\"ExtractCRCFromAssetBundleManifestFile\")]\n        public static extern bool GetCRCForAssetBundle(string targetPath, out uint crc);\n\n        [FreeFunction(\"ExtractHashFromAssetBundleManifestFile\")]\n        public static extern bool GetHashForAssetBundle(string targetPath, out Hash128 hash);\n\n        [FreeFunction(\"BuildPlayerLicenseCheck\", IsThreadSafe = true)]\n        internal static extern bool LicenseCheck(BuildTarget target);\n\n        // TODO: remove, superseded by IsBuildPlatformSupported()\n        [FreeFunction]\n        public static extern bool IsBuildTargetSupported(BuildTargetGroup buildTargetGroup, BuildTarget target);\n\n        [FreeFunction]\n        internal static extern bool IsBuildPlatformSupported(BuildTarget target);\n\n        public static string GetPlaybackEngineDirectory(BuildTarget target, BuildOptions options)\n        {\n            return GetPlaybackEngineDirectory(target, options, true);\n        }\n\n        public static string GetPlaybackEngineDirectory(BuildTarget target, BuildOptions options, bool assertUnsupportedPlatforms)\n        {\n            BuildTargetGroup buildTargetGroup = GetBuildTargetGroup(target);\n            return GetPlaybackEngineDirectory(buildTargetGroup, target, options, assertUnsupportedPlatforms);\n        }\n\n        public static string GetPlaybackEngineDirectory(BuildTargetGroup buildTargetGroup, BuildTarget target, BuildOptions options)\n        {\n            return GetPlaybackEngineDirectory(buildTargetGroup, target, options, true);\n        }\n\n        [FreeFunction(IsThreadSafe = true)]\n        public static extern string GetPlaybackEngineDirectory(BuildTargetGroup buildTargetGroup, BuildTarget target, BuildOptions options, bool assertUnsupportedPlatforms);\n\n        [FreeFunction]\n        internal static extern bool IsServerBuildPlatformSupported(BuildTarget target);\n\n        internal static string GetBuildToolsDirectory(BuildTarget target)\n        {\n            return Path.Combine(GetPlaybackEngineDirectory(target, BuildOptions.None, false), \"Tools\");\n        }\n\n        [FreeFunction]\n        internal static extern string GetMonoRuntimeLibDirectory(BuildTarget target);\n\n        [RequiredByNativeCode]\n        internal static string CompatibilityProfileToClassLibFolder(ApiCompatibilityLevel compatibilityLevel)\n        {\n            var target = EditorUserBuildSettings.activeBuildTarget;\n            var suffix = BuildTargetDiscovery.GetPlatformProfileSuffix(target);\n\n            switch (compatibilityLevel)\n            {\n                case ApiCompatibilityLevel.NET_Unity_4_8:\n                    return \"unityjit-\" + suffix;\n\n                case ApiCompatibilityLevel.NET_Standard:\n                    return \"unityaot-\" + suffix;\n\n                default:\n                    Debug.LogError($\"Unknown API compatibility level: {compatibilityLevel}.\");\n                    return \"unityjit\";\n            }\n        }\n\n        internal static string GetBuildTargetGroupName(BuildTarget target)\n        {\n            return GetBuildTargetGroupName(GetBuildTargetGroup(target));\n        }\n\n        [FreeFunction]\n        internal static extern string GetBuildTargetGroupName(BuildTargetGroup buildTargetGroup);\n\n        [RequiredByNativeCode]\n        public static PlayerConnectionInitiateMode GetPlayerConnectionInitiateMode(BuildTarget targetPlatform, BuildOptions buildOptions)\n        {\n            bool connectProfilerOnStartup = (buildOptions & BuildOptions.ConnectWithProfiler) != 0;\n\n            bool connect = (buildOptions & BuildOptions.ConnectToHost) != 0 || (connectProfilerOnStartup && DoesBuildTargetSupportPlayerConnectionPlayerToEditor(targetPlatform));\n            return connect ? PlayerConnectionInitiateMode.PlayerConnectsToHost : PlayerConnectionInitiateMode.PlayerListens;\n        }\n\n        [RequiredByNativeCode]\n        private static bool DoesBuildTargetSupportPlayerConnectionPlayerToEditor(BuildTarget targetPlatform)\n        {\n            if (BuildTargetDiscovery.TryGetProperties(targetPlatform, out IPlayerConnectionPlatformProperties properties))\n            {\n                return properties.SupportsConnect;\n            }\n            return false;\n        }\n\n        [RequiredByNativeCode]\n        private static bool DoesBuildTargetSupportPlayerConnectionListening(BuildTarget platform)\n        {\n            if (BuildTargetDiscovery.TryGetProperties(platform, out IPlayerConnectionPlatformProperties properties))\n            {\n                return properties.SupportsListen;\n            }\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPipelineExperimental.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Experimental\n{\n    [Obsolete(\"BuildPipelineExperimental is no longer supported and will be removed\")]\n    public static class BuildPipelineExperimental\n    {\n        public static string GetSessionIdForBuildTarget(BuildTarget target)\n        {\n            return BuildPipeline.GetSessionIdForBuildTarget(target, 0);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPlayerDataExtractor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.IO;\nusing UnityEditor.Build.Player;\nusing UnityEditor.VisualStudioIntegration;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class BuildPlayerDataExtractor\n    {\n        private readonly IDirectoryIO m_DirectoryIO;\n        private readonly IFileIO m_FileIO;\n\n        public BuildPlayerDataExtractor()\n        {\n            m_DirectoryIO = new DirectoryIOProvider();\n            m_FileIO = new FileIOProvider();\n        }\n\n        public AssemblyInfoManaged[] ExtractAssemblyTypeInfo(bool isEditor)\n        {\n            var buildPlayerDataGeneratorHelper = new BuildPlayerDataGenerator();\n            return ExtractAssemblyTypeInfoFromFiles(buildPlayerDataGeneratorHelper.GetTypeDbFilePaths(isEditor));\n        }\n\n        public  AssemblyInfoManaged[] ExtractAssemblyTypeInfoFromFiles(string[] typeDbJsonPaths)\n        {\n            List<AssemblyInfoManaged> assemblyInfoResults = new List<AssemblyInfoManaged>(typeDbJsonPaths.Length);\n            foreach (var typeDbFile in typeDbJsonPaths)\n            {\n                var assemblyInfos = JsonUtility.FromJson<ExtractRoot<AssemblyInfoManaged>>(File.ReadAllText(typeDbFile));\n                assemblyInfoResults.AddRange(assemblyInfos.root);\n            }\n            return assemblyInfoResults.ToArray();\n        }\n\n        public void ExtractPlayerRuntimeInitializeOnLoadMethods(string jsonPath)\n        {\n            m_DirectoryIO.CreateDirectory(jsonPath);\n\n            var path = Path.Combine(BuildPlayerDataGenerator.OutputPath, \"Player\");\n            var sourceRuntimeInitializeOnLoads = Path.Combine(path, \"RuntimeInitializeOnLoads.json\");\n            if (!m_DirectoryIO.Exists(path) || !m_FileIO.Exists(sourceRuntimeInitializeOnLoads))\n            {\n                return;\n            }\n\n            m_FileIO.Copy(sourceRuntimeInitializeOnLoads, Path.Combine(jsonPath, \"RuntimeInitializeOnLoads.json\"), true);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPlayerSceneTreeView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.IO;\nusing UnityEditor.IMGUI.Controls;\nusing TreeView = UnityEditor.IMGUI.Controls.TreeView<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    internal class BuildPlayerSceneTreeViewItem : TreeViewItem\n    {\n        private const string kAssetsFolder = \"Assets/\";\n        private const string kSceneExtension = \".unity\";\n        public static int kInvalidCounter = -1;\n\n        private string m_FullName;\n\n        public bool active;\n        public int counter;\n        public string fullName\n        {\n            get => m_FullName;\n            set\n            {\n                if (m_FullName == value)\n                    return;\n\n                m_FullName = value;\n                displayName = m_FullName;\n                if (displayName.StartsWith(kAssetsFolder))\n                    displayName = displayName.Remove(0, kAssetsFolder.Length);\n                var ext = displayName.LastIndexOf(kSceneExtension);\n                if (ext > 0)\n                    displayName = displayName.Substring(0, ext);\n            }\n        }\n        public GUID guid;\n\n        public void UpdateName()\n        {\n            var name = AssetDatabase.GUIDToAssetPath(guid.ToString());\n            if (!string.IsNullOrEmpty(name) && name != fullName)\n                fullName = name;\n        }\n\n        public BuildPlayerSceneTreeViewItem(EditorBuildSettingsScene scene) : base(scene.guid.GetHashCode(), 0)\n        {\n            active = scene.enabled;\n            counter = kInvalidCounter;\n            guid = scene.guid;\n            fullName = scene.path;\n            UpdateName();\n        }\n    }\n\n    internal class BuildPlayerSceneTreeView : TreeView\n    {\n        public BuildPlayerSceneTreeView(TreeViewState state) : base(state)\n        {\n            showBorder = true;\n            EditorBuildSettings.sceneListChanged += HandleExternalSceneListChange;\n        }\n\n        internal void UnsubscribeListChange()\n        {\n            EditorBuildSettings.sceneListChanged -= HandleExternalSceneListChange;\n        }\n\n        private void HandleExternalSceneListChange()\n        {\n            Reload();\n        }\n\n        protected override TreeViewItem BuildRoot()\n        {\n            var root = new TreeViewItem(-1, -1);\n            root.children = new List<TreeViewItem>();\n\n            List<EditorBuildSettingsScene> scenes = new List<EditorBuildSettingsScene>(GetScenes());\n            foreach (var sc in scenes)\n            {\n                var item = new BuildPlayerSceneTreeViewItem(sc);\n                root.AddChild(item);\n            }\n            return root;\n        }\n\n        protected override bool CanBeParent(TreeViewItem item)\n        {\n            return false;\n        }\n\n        protected override void BeforeRowsGUI()\n        {\n            int counter = 0;\n            foreach (var item in rootItem.children)\n            {\n                var bpst = item as BuildPlayerSceneTreeViewItem;\n                if (bpst == null)\n                    continue;\n\n                bpst.UpdateName();\n\n                //Need to set counter here because RowGUI is only called on items that are visible.\n                if (bpst.active)\n                {\n                    bpst.counter = counter;\n                    counter++;\n                }\n                else\n                    bpst.counter = BuildPlayerSceneTreeViewItem.kInvalidCounter;\n            }\n\n            base.BeforeRowsGUI();\n        }\n\n        protected override void RowGUI(RowGUIArgs args)\n        {\n            var sceneItem = args.item as BuildPlayerSceneTreeViewItem;\n            if (sceneItem != null)\n            {\n                var sceneWasDeleted = sceneItem.guid.Empty();\n                var sceneExists = !sceneWasDeleted && File.Exists(sceneItem.fullName);\n\n                using (new EditorGUI.DisabledScope(!sceneExists))\n                {\n                    var newState = sceneItem.active;\n                    if (!sceneExists)\n                        newState = false;\n                    newState = GUI.Toggle(new Rect(args.rowRect.x, args.rowRect.y, 16f, 16f), newState, \"\");\n                    if (newState != sceneItem.active)\n                    {\n                        if (GetSelection().Contains(sceneItem.id))\n                        {\n                            var selection = GetSelection();\n                            foreach (var id in selection)\n                            {\n                                var item = FindItem(id, rootItem) as BuildPlayerSceneTreeViewItem;\n                                item.active = newState;\n                            }\n                        }\n                        else\n                        {\n                            sceneItem.active = newState;\n                        }\n\n                        SetScenes(GetSceneList());\n                    }\n\n                    base.RowGUI(args);\n\n                    if (sceneItem.counter != BuildPlayerSceneTreeViewItem.kInvalidCounter)\n                    {\n                        TreeView.DefaultGUI.LabelRightAligned(args.rowRect, \"\" + sceneItem.counter, args.selected, args.focused);\n                    }\n                    else if (sceneItem.displayName == string.Empty || !sceneExists)\n                    {\n                        TreeView.DefaultGUI.LabelRightAligned(args.rowRect, \"Deleted\", args.selected, args.focused);\n                    }\n                }\n            }\n            else\n                base.RowGUI(args);\n        }\n\n        protected override DragAndDropVisualMode HandleDragAndDrop(DragAndDropArgs args)\n        {\n            DragAndDropVisualMode visualMode = DragAndDropVisualMode.None;\n\n            var draggedIDs = DragAndDrop.GetGenericData(\"BuildPlayerSceneTreeViewItem\") as List<int>;\n            if (draggedIDs != null && draggedIDs.Count > 0)\n            {\n                visualMode = DragAndDropVisualMode.Move;\n                if (args.performDrop)\n                {\n                    int newIndex = FindDropAtIndex(args);\n\n                    var result = new List<TreeViewItem>();\n                    int toInsert = 0;\n                    foreach (var item in rootItem.children)\n                    {\n                        if (toInsert == newIndex)\n                        {\n                            foreach (var id in draggedIDs)\n                            {\n                                result.Add(FindItem(id, rootItem));\n                            }\n                        }\n                        toInsert++;\n                        if (!draggedIDs.Contains(item.id))\n                        {\n                            result.Add(item);\n                        }\n                    }\n\n                    if (result.Count < rootItem.children.Count) //must be appending.\n                    {\n                        foreach (var id in draggedIDs)\n                        {\n                            result.Add(FindItem(id, rootItem));\n                        }\n                    }\n                    rootItem.children = result;\n                    SetScenes(GetSceneList());\n                    ReloadAndSelect(draggedIDs);\n                    Repaint();\n                }\n            }\n            else if (DragAndDrop.paths != null && DragAndDrop.paths.Length > 0)\n            {\n                visualMode = DragAndDropVisualMode.Copy;\n                if (args.performDrop)\n                {\n                    var scenes = new List<EditorBuildSettingsScene>(GetScenes());\n                    var scenesToAdd = new List<EditorBuildSettingsScene>();\n                    var selection = new List<int>();\n\n                    foreach (var path in DragAndDrop.paths)\n                    {\n                        if (AssetDatabase.GetMainAssetTypeAtPath(path) == typeof(SceneAsset))\n                        {\n                            var guid = new GUID(AssetDatabase.AssetPathToGUID(path));\n                            selection.Add(guid.GetHashCode());\n\n                            bool unique = true;\n                            foreach (var scene in scenes)\n                            {\n                                if (scene.path == path)\n                                {\n                                    unique = false;\n                                    break;\n                                }\n                            }\n                            if (unique)\n                                scenesToAdd.Add(new EditorBuildSettingsScene(path, true));\n                        }\n                    }\n\n\n                    int newIndex = FindDropAtIndex(args);\n                    scenes.InsertRange(newIndex, scenesToAdd);\n                    SetScenes(scenes.ToArray());\n                    ReloadAndSelect(selection);\n                    Repaint();\n                }\n            }\n            return visualMode;\n        }\n\n        private void ReloadAndSelect(IList<int> hashCodes)\n        {\n            Reload();\n            SetSelection(hashCodes, TreeViewSelectionOptions.RevealAndFrame);\n            SelectionChanged(hashCodes);\n        }\n\n        protected override void DoubleClickedItem(int id)\n        {\n            BuildPlayerSceneTreeViewItem item = FindItem(id , rootItem) as BuildPlayerSceneTreeViewItem;\n            int instanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(item.fullName);\n            EditorGUIUtility.PingObject(instanceID);\n        }\n\n        protected int FindDropAtIndex(DragAndDropArgs args)\n        {\n            int indexToDrop = args.insertAtIndex;\n\n            // covers if(args.dragAndDropPosition == DragAndDropPosition.OutsideItems) and a safety check.\n            if (indexToDrop < 0 || indexToDrop > rootItem.children.Count)\n                indexToDrop = rootItem.children.Count;\n\n            return indexToDrop;\n        }\n\n        protected override bool CanStartDrag(CanStartDragArgs args)\n        {\n            return true;\n        }\n\n        protected override void SetupDragAndDrop(SetupDragAndDropArgs args)\n        {\n            DragAndDrop.PrepareStartDrag();\n            DragAndDrop.SetGenericData(\"BuildPlayerSceneTreeViewItem\", new List<int>(args.draggedItemIDs));\n            DragAndDrop.visualMode = DragAndDropVisualMode.Copy;\n            DragAndDrop.StartDrag(\"BuildPlayerSceneTreeView\");\n        }\n\n        protected override void KeyEvent()\n        {\n            if ((Event.current.keyCode == KeyCode.Delete || Event.current.keyCode == KeyCode.Backspace) &&\n                (GetSelection().Count > 0))\n            {\n                RemoveSelection();\n            }\n        }\n\n        protected override void ContextClicked()\n        {\n            if (GetSelection().Count > 0)\n            {\n                GenericMenu menu = new GenericMenu();\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Remove Selection\"), false, RemoveSelection);\n                menu.ShowAsContext();\n            }\n        }\n\n        protected void RemoveSelection()\n        {\n            foreach (var nodeID in GetSelection())\n            {\n                rootItem.children.Remove(FindItem(nodeID, rootItem));\n            }\n            SetScenes(GetSceneList());\n            Reload();\n            Repaint();\n        }\n\n        protected virtual EditorBuildSettingsScene[] GetScenes() => EditorBuildSettings.scenes;\n        protected virtual void SetScenes(EditorBuildSettingsScene[] scenes) => EditorBuildSettings.scenes = scenes;\n\n        public EditorBuildSettingsScene[] GetSceneList()\n        {\n            var sceneList = new EditorBuildSettingsScene[rootItem.children.Count];\n            for (int index = 0; index < rootItem.children.Count; index++)\n            {\n                var sceneItem = rootItem.children[index] as BuildPlayerSceneTreeViewItem;\n                sceneList[index] = new EditorBuildSettingsScene(sceneItem.fullName, sceneItem.active);\n\n                // If the scene was deleted AssetPathToGUID may not work and the guid will be lost\n                // In that case restore it to the previous value\n                if (sceneList[index].guid.Empty() && !sceneItem.guid.Empty())\n                    sceneList[index].guid = sceneItem.guid;\n            }\n            return sceneList;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPlayerWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Text.RegularExpressions;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing UnityEditor.SceneManagement;\nusing UnityEditor.Build;\nusing UnityEditorInternal;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing JetBrains.Annotations;\nusing UnityEditor.Modules;\nusing GraphicsDeviceType = UnityEngine.Rendering.GraphicsDeviceType;\nusing Object = UnityEngine.Object;\nusing TargetAttributes = UnityEditor.BuildTargetDiscovery.TargetAttributes;\nusing RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute;\nusing UnityEditor.Connect;\nusing UnityEditor.Utils;\nusing UnityEditor.Build.Profile;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    public partial class BuildPlayerWindow : EditorWindow\n    {\n        class Styles\n        {\n            public GUIContent invalidColorSpaceMessage = EditorGUIUtility.TrTextContent(\"In order to build a player, go to 'Player Settings...' to resolve the incompatibility between the Color Space and the current settings.\", EditorGUIUtility.GetHelpIcon(MessageType.Warning));\n            public GUIContent invalidLightmapEncodingMessage = EditorGUIUtility.TrTextContent(\"In order to build a player, go to 'Player Settings...' to resolve the incompatibility between the Lightmap Encoding value you have selected and the current settings.\", EditorGUIUtility.GetHelpIcon(MessageType.Warning));\n            public GUIContent invalidHDRCubemapEncodingMessage = EditorGUIUtility.TrTextContent(\"In order to build a player, go to 'Player Settings...' to resolve the incompatibility between the HDR Cubemap Encoding value you have selected and the current settings.\", EditorGUIUtility.GetHelpIcon(MessageType.Warning));\n            public GUIContent invalidVirtualTexturingSettingMessage = EditorGUIUtility.TrTextContent(\"Cannot build player because Virtual Texturing is enabled, but the target platform or graphics API does not support Virtual Texturing. Go to Player Settings to resolve the incompatibility.\", EditorGUIUtility.GetHelpIcon(MessageType.Warning));\n            public GUIContent compilingMessage = EditorGUIUtility.TrTextContent(\"Cannot build player while editor is importing assets or compiling scripts.\", EditorGUIUtility.GetHelpIcon(MessageType.Warning));\n            public GUIStyle title = EditorStyles.boldLabel;\n            public GUIStyle evenRow = \"CN EntryBackEven\";\n            public GUIStyle oddRow = \"CN EntryBackOdd\";\n            public GUIStyle platformSelector = \"PlayerSettingsPlatform\";\n\n            public GUIContent platformTitle = EditorGUIUtility.TrTextContent(\"Platform\", \"Which platform to build for\");\n            public GUIContent switchPlatform = EditorGUIUtility.TrTextContent(\"Switch Platform\");\n            public GUIContent build = EditorGUIUtility.TrTextContent(\"Build\");\n            public GUIContent buildAndRun = EditorGUIUtility.TrTextContent(\"Build And Run\");\n            public GUIContent scenesInBuild = EditorGUIUtility.TrTextContent(\"Scenes In Build\", \"Which scenes to include in the build\");\n            public GUIContent checkOut = EditorGUIUtility.TrTextContent(\"Check out\");\n            public GUIContent addOpenSource = EditorGUIUtility.TrTextContent(\"Add Open Scenes\");\n            public string noModuleLoaded = L10n.Tr(\"No {0} module loaded.\");\n            public GUIContent openDownloadPage = EditorGUIUtility.TrTextContent(\"Open Download Page\");\n            public GUIContent installModuleWithHub = EditorGUIUtility.TrTextContent(\"Install with Unity Hub\");\n            public string EditorWillNeedToBeReloaded = L10n.Tr(\"Note: Editor will need to be restarted to load any newly installed modules\");\n            public string infoText = L10n.Tr(\"{0} is not included in your Unity Pro license. Your {0} build will include a Unity Personal Edition splash screen.\\n\\nYou must be eligible to use Unity Personal Edition to use this build option. Please refer to our EULA for further information.\");\n            public GUIContent eula = EditorGUIUtility.TrTextContent(\"Eula\");\n            public string addToYourPro = L10n.Tr(\"Add {0} to your Unity Pro license\");\n            public GUIContent installInBuildFolder = EditorGUIUtility.TrTextContent(\"Install into source code 'build' folder\", \"Install into source checkout 'build' folder, for debugging with source code\");\n            public GUIContent installInBuildFolderHelp = EditorGUIUtility.TrIconContent(\"_Help\", \"Open documentation about source code building and debugging\");\n\n            public Texture2D activePlatformIcon = EditorGUIUtility.IconContent(\"BuildSettings.SelectedIcon\").image as Texture2D;\n\n            public const float kButtonWidth = 110;\n\n            public string shopURL = \"https://store.unity.com/products/unity-pro\";\n\n            public GUIContent GetDownloadErrorForTarget(BuildTarget target)\n            {\n                return null;\n            }\n\n            // string and matching enum values for standalone subtarget dropdowm\n            public GUIContent debugBuild = EditorGUIUtility.TrTextContent(\"Development Build\");\n            public GUIContent autoconnectProfiler = EditorGUIUtility.TrTextContent(\"Autoconnect Profiler\", \"When the build is started, an open Profiler Window will automatically connect to the Player and start profiling. The \\\"Build And Run\\\" option will also automatically open the Profiler Window.\");\n            public GUIContent autoconnectProfilerDisabled = EditorGUIUtility.TrTextContent(\"Autoconnect Profiler\", \"Profiling is only enabled in a Development Player.\");\n            public GUIContent buildWithDeepProfiler = EditorGUIUtility.TrTextContent(\"Deep Profiling Support\", \"Build Player with Deep Profiling Support. This might affect Player performance.\");\n            public GUIContent buildWithDeepProfilerDisabled = EditorGUIUtility.TrTextContent(\"Deep Profiling Support\", \"Profiling is only enabled in a Development Player.\");\n            public GUIContent allowDebugging = EditorGUIUtility.TrTextContent(\"Script Debugging\", \"Enable this setting to allow your script code to be debugged.\");\n            public GUIContent waitForManagedDebugger = EditorGUIUtility.TrTextContent(\"Wait For Managed Debugger\", \"Show a dialog where you can attach a managed debugger before any script execution. Can also use volume Up or Down button to confirm on Android.\");\n            public GUIContent managedDebuggerFixedPort = EditorGUIUtility.TrTextContent(\"Managed Debugger Fixed Port\", \"Use the specified port to attach to the managed debugger. If 0, the port will be automatically selected.\");\n            public GUIContent explicitNullChecks = EditorGUIUtility.TrTextContent(\"Explicit Null Checks\");\n            public GUIContent explicitDivideByZeroChecks = EditorGUIUtility.TrTextContent(\"Divide By Zero Checks\");\n            public GUIContent explicitArrayBoundsChecks = EditorGUIUtility.TrTextContent(\"Array Bounds Checks\");\n            public GUIContent learnAboutUnityCloudBuild = EditorGUIUtility.TrTextContent(\"Learn about Unity Build Automation\");\n            public GUIContent compressionMethod = EditorGUIUtility.TrTextContent(\"Compression Method\", \"Compression applied to Player data (scenes and resources).\\nDefault - none or default platform compression.\\nLZ4 - fast compression suitable for Development Builds.\\nLZ4HC - higher compression rate variance of LZ4, causes longer build times. Works best for Release Builds.\");\n\n            public readonly GUIContent assetImportOverrides = EditorGUIUtility.TrTextContent(\"Asset Import Overrides\", \"Asset import overrides for local development. Reducing maximum texture size or compression settings can speed up asset imports and platform switches.\");\n            public readonly GUIContent maxTextureSize = EditorGUIUtility.TrTextContent(\"Max Texture Size\", \"Maximum texture import size for local development. Reducing maximum texture size can speed up asset imports and platform switches.\");\n            public readonly GUIContent[] maxTextureSizeLabels =\n            {\n                EditorGUIUtility.TrTextContent(\"No Override\", \"Use maximum texture size as specified in per-texture import settings.\"),\n                EditorGUIUtility.TrTextContent(\"Max 2048\", \"Make imported textures never exceed 2048 pixels in width or height.\"),\n                EditorGUIUtility.TrTextContent(\"Max 1024\", \"Make imported textures never exceed 1024 pixels in width or height.\"),\n                EditorGUIUtility.TrTextContent(\"Max 512\", \"Make imported textures never exceed 512 pixels in width or height.\"),\n                EditorGUIUtility.TrTextContent(\"Max 256\", \"Make imported textures never exceed 256 pixels in width or height.\"),\n                EditorGUIUtility.TrTextContent(\"Max 128\", \"Make imported textures never exceed 128 pixels in width or height.\"),\n                EditorGUIUtility.TrTextContent(\"Max 64\", \"Make imported textures never exceed 64 pixels in width or height.\"),\n            };\n            public readonly int[] maxTextureSizeValues =\n            {\n                0,\n                2048,\n                1024,\n                512,\n                256,\n                128,\n                64,\n            };\n            public readonly GUIContent[] textureCompressionLabels =\n            {\n                EditorGUIUtility.TrTextContent(\"No Override\", \"Do not modify texture import compression settings.\"),\n                EditorGUIUtility.TrTextContent(\"Force Fast Compressor\", \"Use a faster but lower quality texture compression mode for all compressed textures. Turn off Crunch compression.\"),\n                EditorGUIUtility.TrTextContent(\"Force Uncompressed\", \"Do not compress textures.\"),\n                EditorGUIUtility.TrTextContent(\"Force No Crunch\", \"Disable crunch compression on textures.\")\n            };\n            public readonly int[] textureCompressionValues =\n            {\n                (int)OverrideTextureCompression.NoOverride,\n                (int)OverrideTextureCompression.ForceFastCompressor,\n                (int)OverrideTextureCompression.ForceUncompressed,\n                (int)OverrideTextureCompression.ForceNoCrunchCompression\n            };\n\n            public readonly GUIContent textureCompression = EditorGUIUtility.TrTextContent(\"Texture Compression\", \"Texture compression override for local development. Fast or Uncompressed can speed up asset imports and platform switches.\");\n            public readonly GUIContent applyOverrides = EditorGUIUtility.TrTextContent(\"Apply Overrides\", \"Apply asset import override settings\");\n\n            public Compression[] compressionTypes =\n            {\n                Compression.None,\n                Compression.Lz4,\n                Compression.Lz4HC\n            };\n\n            public GUIContent[] compressionStrings =\n            {\n                EditorGUIUtility.TrTextContent(\"Default\"),\n                EditorGUIUtility.TrTextContent(\"LZ4\"),\n                EditorGUIUtility.TrTextContent(\"LZ4HC\"),\n            };\n\n            public static GUIStyle boldFoldout;\n\n            static Styles()\n            {\n                boldFoldout = new GUIStyle(EditorStyles.foldout) {fontStyle = FontStyle.Bold};\n            }\n        }\n\n\n        Vector2 scrollPosition = new Vector2(0, 0);\n        Vector2 buildTargetSettingsScrollPosition = new Vector2(0, 0);\n        const string kEditorBuildSettingsPath = \"ProjectSettings/EditorBuildSettings.asset\";\n\n        static Styles styles;\n\n        static bool isEditorinstalledWithHub = IsEditorInstalledWithHub();\n\n        internal static event Action<BuildProfile> drawingMultiplayerBuildOptions;\n\n        [UsedImplicitly, RequiredByNativeCode]\n        public static void ShowBuildPlayerWindow()\n        {\n            BuildPipeline.ShowBuildProfileWindow();\n        }\n\n        internal static bool WillDrawMultiplayerBuildOptions() => drawingMultiplayerBuildOptions != null;\n\n        internal static void DrawMultiplayerBuildOption(BuildProfile buildProfile)\n        {\n            drawingMultiplayerBuildOptions?.Invoke(buildProfile);\n        }\n\n        static bool BuildLocationIsValid(string path)\n        {\n            return path.Length > 0 && Directory.Exists(FileUtil.DeleteLastPathNameComponent(path));\n        }\n\n        [RequiredByNativeCode]\n        static bool BuildPlayerAndRunEnabled()\n        {\n            var buildTarget = EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget();\n            NamedBuildTarget namedBuildTarget = EditorUserBuildSettingsUtils.CalculateSelectedNamedBuildTarget();\n            BuildPlatform platform = BuildPlatforms.instance.BuildPlatformFromNamedBuildTarget(namedBuildTarget);\n            string module = ModuleManager.GetTargetStringFrom(buildTarget);\n            IBuildWindowExtension buildWindowExtension = ModuleManager.GetBuildWindowExtension(module);\n\n            bool buildPlayerAndRunEnabled = buildWindowExtension != null ? buildWindowExtension.EnabledBuildAndRunButton() && !(EditorUserBuildSettings.installInBuildFolder) : !(EditorUserBuildSettings.installInBuildFolder);\n            return buildPlayerAndRunEnabled;\n        }\n\n        // This overload is used by the Build & Run menu item & hot key - prompt for location only if the configured\n        // output location is not valid.\n        [UsedImplicitly, RequiredByNativeCode]\n        static void BuildPlayerAndRun()\n        {\n            var buildTarget = EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget();\n            var lastBuildLocation = EditorUserBuildSettings.GetBuildLocation(buildTarget);\n            bool buildLocationIsValid = BuildLocationIsValid(lastBuildLocation);\n\n            if (buildLocationIsValid && BuildTargetDiscovery.TryGetBuildTarget(buildTarget, out var iBuildTarget))\n            {\n                string buildLocation = iBuildTarget.BuildPlatformProperties?.ValidateBuildLocation();\n                if (buildLocation != null)\n                    EditorUserBuildSettings.SetBuildLocation(buildTarget, buildLocation);\n            }\n\n            BuildPlayerAndRunInternal(!buildLocationIsValid);\n        }\n\n        // This overload is used by the default player window, to always prompt for build location\n        static void BuildPlayerAndRunInternal(bool askForBuildLocation)\n        {\n            CallBuildMethods(askForBuildLocation, BuildOptions.AutoRunPlayer | BuildOptions.StrictMode);\n        }\n\n        public BuildPlayerWindow()\n        {\n            s_CurrOverrideMaxTextureSize = -1;\n            minSize = new Vector2(640, 580);\n            position = new Rect(50, 50, minSize.x, minSize.y);\n            titleContent = EditorGUIUtility.TrTextContent(\"Build Settings\");\n        }\n\n        BuildPlayerSceneTreeView m_TreeView;\n        [SerializeField]\n        TreeViewState m_TreeViewState;\n        void ActiveScenesGUI()\n        {\n            if (m_TreeView == null)\n            {\n                if (m_TreeViewState == null)\n                    m_TreeViewState = new TreeViewState();\n                m_TreeView = new BuildPlayerSceneTreeView(m_TreeViewState);\n                m_TreeView.Reload();\n            }\n            Rect scenesInBuildRect = GUILayoutUtility.GetRect(styles.scenesInBuild, styles.title);\n            GUI.Label(scenesInBuildRect, styles.scenesInBuild, styles.title);\n\n            Rect rect = GUILayoutUtility.GetRect(0, position.width, 0, position.height, GUILayout.MinHeight(20));\n            m_TreeView.OnGUI(rect);\n        }\n\n        void OnDisable()\n        {\n            if (m_TreeView != null)\n                m_TreeView.UnsubscribeListChange();\n        }\n\n        void AddOpenScenes()\n        {\n            List<EditorBuildSettingsScene> list = new List<EditorBuildSettingsScene>(EditorBuildSettings.scenes);\n\n            bool isSceneAdded = false;\n            for (int i = 0; i < SceneManager.sceneCount; i++)\n            {\n                Scene scene = SceneManager.GetSceneAt(i);\n\n                if (EditorSceneManager.IsAuthoringScene(scene))\n                    continue;\n\n                if (scene.path.Length == 0 && !EditorSceneManager.SaveScene(scene, \"\", false))\n                    continue;\n\n                if (list.Any(s => s.path == scene.path))\n                    continue;\n\n                GUID newGUID;\n                GUID.TryParse(scene.guid, out newGUID);\n                var buildSettingsScene = (newGUID == default(GUID)) ?\n                    new EditorBuildSettingsScene(scene.path, true) :\n                    new EditorBuildSettingsScene(newGUID, true);\n                list.Add(buildSettingsScene);\n                isSceneAdded = true;\n            }\n\n            if (!isSceneAdded)\n                return;\n\n            EditorBuildSettings.scenes = list.ToArray();\n            m_TreeView.Reload();\n            Repaint();\n            GUIUtility.ExitGUI();\n        }\n\n        static int s_CurrOverrideMaxTextureSize = -1;\n        static OverrideTextureCompression s_CurrOverrideTextureCompression;\n\n        static bool hasAssetImportOverrideChanges =>\n            s_CurrOverrideMaxTextureSize != EditorUserBuildSettings.overrideMaxTextureSize ||\n            s_CurrOverrideTextureCompression != EditorUserBuildSettings.overrideTextureCompression;\n\n        static void ApplyAssetImportOverridesToSettingsAsset()\n        {\n            EditorUserBuildSettings.overrideMaxTextureSize = s_CurrOverrideMaxTextureSize;\n            EditorUserBuildSettings.overrideTextureCompression = s_CurrOverrideTextureCompression;\n        }\n\n        static void DrawOverrideLine()\n        {\n            var rect = EditorGUILayout.s_LastRect;\n            var prevMargin = EditorGUIUtility.leftMarginCoord;\n            EditorGUIUtility.leftMarginCoord = 2;\n            EditorGUI.DrawOverrideBackgroundApplicable(rect);\n            EditorGUIUtility.leftMarginCoord = prevMargin;\n        }\n\n        SavedBool m_ShowOverrides;\n\n        void AssetImportOverridesGui()\n        {\n            if (s_CurrOverrideMaxTextureSize < 0)\n            {\n                // fetch initial values\n                s_CurrOverrideMaxTextureSize = EditorUserBuildSettings.overrideMaxTextureSize;\n                s_CurrOverrideTextureCompression = EditorUserBuildSettings.overrideTextureCompression;\n            }\n\n            if (m_ShowOverrides == null)\n                m_ShowOverrides = new SavedBool(\"BuildSettingsWindow.ShowImportOverrides\", true);\n\n            GUILayout.Space(5);\n            m_ShowOverrides.value = EditorGUILayout.Foldout(m_ShowOverrides.value, styles.assetImportOverrides, true, Styles.boldFoldout);\n            if (m_ShowOverrides.value)\n            {\n                var oldLabelWidth = EditorGUIUtility.labelWidth;\n                EditorGUIUtility.labelWidth = 125;\n                s_CurrOverrideMaxTextureSize = EditorGUILayout.IntPopup(\n                    styles.maxTextureSize,\n                    s_CurrOverrideMaxTextureSize,\n                    styles.maxTextureSizeLabels,\n                    styles.maxTextureSizeValues);\n                if (s_CurrOverrideMaxTextureSize != 0)\n                    DrawOverrideLine();\n\n                s_CurrOverrideTextureCompression = (OverrideTextureCompression)EditorGUILayout.IntPopup(\n                    styles.textureCompression,\n                    (int)s_CurrOverrideTextureCompression,\n                    styles.textureCompressionLabels,\n                    styles.textureCompressionValues);\n                if (s_CurrOverrideTextureCompression != OverrideTextureCompression.NoOverride)\n                    DrawOverrideLine();\n                EditorGUIUtility.labelWidth = oldLabelWidth;\n            }\n            else\n            {\n                // when the settings are folded, but there are some overrides, then display the blue override\n                // indicator on the side of the foldout itself\n                if (s_CurrOverrideMaxTextureSize != 0 || s_CurrOverrideTextureCompression != OverrideTextureCompression.NoOverride)\n                    DrawOverrideLine();\n            }\n        }\n\n        void ActiveBuildTargetsGUI()\n        {\n            GUILayout.BeginVertical();\n            GUILayout.BeginVertical(GUILayout.Width(255));\n            GUILayout.Label(styles.platformTitle, styles.title);\n            scrollPosition = GUILayout.BeginScrollView(scrollPosition, \"OL Box\");\n\n            // Draw enabled build targets first, then draw disabled build targets\n            bool even = false;\n            for (int requireEnabled = 0; requireEnabled < 2; requireEnabled++)\n            {\n                bool showRequired = requireEnabled == 0;\n                foreach (BuildPlatform gt in BuildPlatforms.instance.buildPlatforms)\n                {\n                    // All installed build targets will be shown on the first pass (showRequired = true)\n                    if (gt.installed != showRequired)\n                        continue;\n\n                    // Some build targets are not publicly available, show them only when they are installed\n                    if (!gt.installed && gt.hideInUi)\n                        continue;\n\n                    // Some build targets are only compatible with specific OS\n#pragma warning disable CS0618 // Member is obsolete\n                    if (!BuildTargetDiscovery.BuildPlatformIsAvailableOnHostPlatform(gt.defaultTarget, SystemInfo.operatingSystemFamily))\n#pragma warning restore CS0618\n                        continue;\n\n                    GUI.contentColor = gt.installed ? Color.white : new Color(1, 1, 1, 0.5f);\n                    ShowOption(gt, gt.title, even ? styles.evenRow : styles.oddRow);\n                    even = !even;\n                }\n                GUI.contentColor = Color.white;\n            }\n\n            GUILayout.EndScrollView();\n\n            AssetImportOverridesGui();\n            GUILayout.EndVertical();\n            GUILayout.Space(10);\n\n            GUILayout.BeginHorizontal();\n\n            // Switch build target\n            BuildTarget selectedTarget = EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget();\n            GUI.enabled = BuildPipeline.IsBuildPlatformSupported(selectedTarget);\n            if (GUILayout.Button(EditorGUIUtility.TrTextContent(\"Player Settings...\"), GUILayout.Width(Styles.kButtonWidth)))\n            {\n                SettingsService.OpenProjectSettings(\"Project/Player\");\n                GUIUtility.ExitGUI();\n            }\n            GUI.enabled = true;\n\n            // Apply import overrides\n            if (hasAssetImportOverrideChanges)\n            {\n                if (GUILayout.Button(styles.applyOverrides, GUILayout.Width(Styles.kButtonWidth)))\n                {\n                    ApplyAssetImportOverridesToSettingsAsset();\n                    AssetDatabase.Refresh();\n                }\n            }\n\n            GUILayout.EndHorizontal();\n\n            GUILayout.EndVertical();\n        }\n\n        void ShowAlert()\n        {\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(10);\n            GUILayout.BeginVertical();\n            EditorGUILayout.HelpBox(EditorGUIUtility.TrTextContent(\"Unable to access Unity services. Please log in, or request membership to this project to use these services.\").text, MessageType.Warning);\n            GUILayout.EndVertical();\n            GUILayout.Space(5);\n            GUILayout.EndHorizontal();\n        }\n\n        void ShowOption(BuildPlatform bp, GUIContent title, GUIStyle background)\n        {\n            Rect r = GUILayoutUtility.GetRect(50, 36);\n            r.x += 1;\n            r.y += 1;\n            bool selected = bp.IsSelected();\n            bool active = bp.IsActive();\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                background.Draw(r, GUIContent.none, false, false, selected, false);\n\n                Texture image = null;\n\n                if (selected && title.image)\n                {\n                    image = EditorUtility.GetIconInActiveState(title.image);\n                }\n\n                if (image == null)\n                {\n                    image = title.image;\n                }\n\n                GUI.Label(new Rect(r.x + 3, r.y + 3, 32, 32), image, GUIStyle.none);\n\n                if (active)\n                    GUI.Label(new Rect(r.xMax - styles.activePlatformIcon.width - 8, r.y + 3 + (32 - styles.activePlatformIcon.height) / 2,\n                        styles.activePlatformIcon.width, styles.activePlatformIcon.height),\n                        styles.activePlatformIcon, GUIStyle.none);\n            }\n\n            if (GUI.Toggle(r, selected, title.text, styles.platformSelector))\n            {\n                if (!selected)\n                {\n                    bp.Select();\n\n                    // Repaint inspectors, as they may be showing platform target specific things.\n                    Object[] inspectors = Resources.FindObjectsOfTypeAll(typeof(InspectorWindow));\n                    for (int i = 0; i < inspectors.Length; i++)\n                    {\n                        InspectorWindow inspector = inspectors[i] as InspectorWindow;\n                        if (inspector != null)\n                            inspector.Repaint();\n                    }\n\n                    // We also need to repaint project settings window.\n                    Object[] projecSettingsWindows = Resources.FindObjectsOfTypeAll(typeof(ProjectSettingsWindow));\n                    for (int i = 0; i < projecSettingsWindows.Length; i++)\n                    {\n                        ProjectSettingsWindow projecSettingsWindow = projecSettingsWindows[i] as ProjectSettingsWindow;\n                        if (projecSettingsWindow != null)\n                            projecSettingsWindow.Repaint();\n                    }\n                }\n            }\n        }\n\n        void OnGUI()\n        {\n            if (styles == null)\n            {\n                styles = new Styles();\n            }\n            // Override the 'old' build settings window in favor of the new build profile window.\n            BuildPipeline.ShowBuildProfileWindow();\n            Close();\n        }\n\n        static bool IsAnyStandaloneModuleLoaded()\n        {\n            return ModuleManager.IsPlatformSupportLoadedByBuildTarget(BuildTarget.StandaloneLinux64) ||\n                ModuleManager.IsPlatformSupportLoadedByBuildTarget(BuildTarget.StandaloneOSX) ||\n                ModuleManager.IsPlatformSupportLoadedByBuildTarget(BuildTarget.StandaloneWindows);\n        }\n\n        static bool IsVirtualTexturingSettingsValid(BuildPlatform platform)\n        {\n            if (!PlayerSettings.GetVirtualTexturingSupportEnabled())\n            {\n                return true;\n            }\n\n            if (!UnityEngine.Rendering.VirtualTexturingEditor.Building.IsPlatformSupportedForPlayer(platform.defaultTarget))\n            {\n                return false;\n            }\n\n            GraphicsDeviceType[] gfxTypes = PlayerSettings.GetGraphicsAPIs(platform.defaultTarget);\n            bool supportedAPI = true;\n            foreach (GraphicsDeviceType api in gfxTypes)\n            {\n                supportedAPI &= UnityEngine.Rendering.VirtualTexturingEditor.Building.IsRenderAPISupported(api, platform.defaultTarget, false);\n            }\n\n            return supportedAPI;\n        }\n\n        // Major.Minor.Micro followed by one of abxfp followed by an identifier, optionally suffixed with \" (revisionhash)\"\n        static Regex s_VersionPattern = new Regex(@\"(?<shortVersion>\\d+\\.\\d+\\.\\d+(?<suffix>((?<alphabeta>[abx])|[fp])[^\\s]*))( \\((?<revision>[a-fA-F\\d]+)\\))?\",\n            RegexOptions.Compiled);\n\n        internal static string GetPlaybackEngineDownloadURL(GUID platformGuid)\n        {\n            if (!BuildTargetDiscovery.BuildPlatformCanBeInstalledWithHub(platformGuid))\n                return \"https://unity3d.com/platform-installation\";\n\n            string fullVersion = InternalEditorUtility.GetFullUnityVersion();\n            string revision = \"\";\n            string shortVersion = \"\";\n            Match versionMatch = s_VersionPattern.Match(fullVersion);\n            if (!versionMatch.Success || !versionMatch.Groups[\"shortVersion\"].Success || !versionMatch.Groups[\"suffix\"].Success)\n                Debug.LogWarningFormat(\"Error parsing version '{0}'\", fullVersion);\n\n            if (versionMatch.Groups[\"shortVersion\"].Success)\n                shortVersion = versionMatch.Groups[\"shortVersion\"].Value;\n            if (versionMatch.Groups[\"revision\"].Success)\n                revision = versionMatch.Groups[\"revision\"].Value;\n\n            var downloadLinkName = BuildTargetDiscovery.BuildPlatformDownloadLinkName(platformGuid);\n\n            string prefix = \"download\";\n            string suffix = \"download_unity\";\n            string folder = \"Unknown\";\n            string extension = string.Empty;\n\n            if (versionMatch.Groups[\"alphabeta\"].Success)\n            {\n                // These releases are hosted on the beta site\n                prefix = \"beta\";\n                suffix = \"download\";\n            }\n\n            if (Application.platform == RuntimePlatform.WindowsEditor)\n            {\n                folder = \"TargetSupportInstaller\";\n                extension = \".exe\";\n            }\n            else if (Application.platform == RuntimePlatform.OSXEditor)\n            {\n                folder = \"MacEditorTargetInstaller\";\n                extension = \".pkg\";\n            }\n            else if (Application.platform == RuntimePlatform.LinuxEditor)\n            {\n                if (downloadLinkName == \"Android\" || downloadLinkName == \"Mac-Mono\" || downloadLinkName == \"Windows-Mono\")\n                {\n                    folder = \"MacEditorTargetInstaller\";\n                    extension = \".pkg\";\n                }\n                else\n                {\n                    folder = \"LinuxEditorTargetInstaller\";\n                    extension = \".tar.xz\";\n                }\n            }\n\n            return string.Format(\"https://{0}.unity3d.com/{1}/{2}/{3}/UnitySetup-{4}-Support-for-Editor-{5}{6}\", prefix, suffix, revision, folder, downloadLinkName, shortVersion, extension);\n        }\n\n        internal static string GetUnityHubModuleDownloadURL(GUID platformGuid)\n        {\n            string fullVersion = InternalEditorUtility.GetFullUnityVersion();\n            string revision = \"\";\n            string shortVersion = \"\";\n            Match versionMatch = s_VersionPattern.Match(fullVersion);\n            if (!versionMatch.Success || !versionMatch.Groups[\"shortVersion\"].Success || !versionMatch.Groups[\"suffix\"].Success)\n                Debug.LogWarningFormat(\"Error parsing version '{0}'\", fullVersion);\n\n            if (versionMatch.Groups[\"shortVersion\"].Success)\n                shortVersion = versionMatch.Groups[\"shortVersion\"].Value;\n            if (versionMatch.Groups[\"revision\"].Success)\n                revision = versionMatch.Groups[\"revision\"].Value;\n\n            var downloadLinkName = BuildTargetDiscovery.BuildPlatformDownloadLinkName(platformGuid);\n\n            return string.Format(\"unityhub://{0}/{1}/module={2}\", shortVersion, revision, downloadLinkName.ToLower());\n        }\n\n        internal static bool IsModuleNotInstalled(NamedBuildTarget namedBuildTarget, BuildTarget buildTarget)\n        {\n            bool licensed = BuildPipeline.LicenseCheck(buildTarget);\n            bool installed = BuildPlatforms.instance.BuildPlatformFromNamedBuildTarget(namedBuildTarget).installed;\n\n            string moduleName = ModuleManager.GetTargetStringFrom(buildTarget);\n\n            return !installed ||\n                (licensed && !string.IsNullOrEmpty(moduleName) &&\n                ModuleManager.GetBuildPostProcessor(moduleName) == null &&\n                (BuildTargetGroup.Standalone != EditorUserBuildSettings.selectedBuildTargetGroup ||\n                    !IsAnyStandaloneModuleLoaded()));\n        }\n\n        internal static bool IsEditorInstalledWithHub()\n        {\n            var applicationFolderPath = Directory.GetParent(EditorApplication.applicationPath).FullName;\n            var path = \"\";\n\n            if (Application.platform == RuntimePlatform.OSXEditor)\n                path = Path.Combine(applicationFolderPath, \"modules.json\");\n            else if (Application.platform == RuntimePlatform.WindowsEditor)\n                path = Path.Combine(Directory.GetParent(applicationFolderPath).FullName, \"modules.json\");\n            else if (Application.platform == RuntimePlatform.LinuxEditor)\n                path = Path.Combine(Directory.GetParent(applicationFolderPath).FullName, \"modules.json\");\n\n            return File.Exists(path);\n        }\n\n        void ShowBuildTargetSettings()\n        {\n            EditorGUIUtility.labelWidth = Mathf.Min(180, (position.width - 265) * 0.47f);\n\n            BuildTarget buildTarget = EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget();\n            NamedBuildTarget namedBuildTarget = EditorUserBuildSettingsUtils.CalculateSelectedNamedBuildTarget();\n            var platformGuid = BuildTargetDiscovery.GetGUIDFromBuildTarget(namedBuildTarget, buildTarget);\n            BuildPlatform platform = BuildPlatforms.instance.BuildPlatformFromNamedBuildTarget(namedBuildTarget);\n            IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(buildTarget);\n            bool licensed = BuildPipeline.LicenseCheck(buildTarget);\n\n            // Draw the group name (text & icon separately to have some space between them)\n            var titleIconSize = 16;\n            Rect r = GUILayoutUtility.GetRect(50, titleIconSize);\n            if (Event.current.type == EventType.Repaint)\n                GUI.DrawTexture(new Rect(r.x, r.y, titleIconSize, titleIconSize), platform.compoundSmallIcon);\n            r.x += titleIconSize + 5;\n            GUI.Label(r, platform.title.text, styles.title);\n\n            GUILayout.Space(10);\n\n            if (IsModuleNotInstalled(namedBuildTarget, buildTarget))\n            {\n                ShowNoModuleLabel(platformGuid,\n                    styles.noModuleLoaded,\n                    styles.openDownloadPage,\n                    styles.installModuleWithHub,\n                    styles.EditorWillNeedToBeReloaded);\n                GUIBuildButtons(false, false, false, platform, postprocessor);\n                return;\n            }\n            else if (Application.HasProLicense() && !InternalEditorUtility.HasAdvancedLicenseOnBuildTarget(buildTarget))\n            {\n                // Show copy for using personal edition build targets with pro edition editor\n                string infoText = string.Format(styles.infoText,\n                    BuildPlatforms.instance.GetBuildTargetDisplayName(namedBuildTarget, buildTarget));\n\n                GUILayout.BeginVertical(EditorStyles.helpBox);\n                GUILayout.Label(infoText, EditorStyles.wordWrappedMiniLabel);\n                GUILayout.BeginHorizontal();\n                if (GUILayout.Button(styles.eula, EditorStyles.miniButton))\n                    Application.OpenURL(\"http://unity3d.com/legal/eula\");\n                if (GUILayout.Button(string.Format(styles.addToYourPro, BuildPlatforms.instance.GetBuildTargetDisplayName(namedBuildTarget, buildTarget)), EditorStyles.miniButton))\n                    Application.OpenURL(\"http://unity3d.com/get-unity\");\n                GUILayout.EndHorizontal();\n                GUILayout.EndVertical();\n            }\n\n            GUIContent error = styles.GetDownloadErrorForTarget(buildTarget);\n            if (error != null)\n            {\n                GUILayout.Label(error, EditorStyles.wordWrappedLabel);\n                GUIBuildButtons(false, false, false, platform, postprocessor);\n                return;\n            }\n\n            // Draw not licensed buy now UI\n            if (!licensed)\n            {\n                string niceName = BuildPipeline.GetBuildTargetGroupDisplayName(namedBuildTarget.ToBuildTargetGroup());\n                string licenseMsg = \"Your license does not cover {0} Publishing.\";\n                string buttonMsg = \"Go to Our Online Store\";\n                string licenseURL = styles.shopURL;\n                if (BuildTargetDiscovery.PlatformHasFlag(buildTarget, TargetAttributes.IsConsole))\n                {\n                    licenseMsg += \" Please see the {0} section of the Platform Module Installation documentation for more details.\";\n                    buttonMsg = \"Platform Module Installation\";\n                    licenseURL = \"https://unity3d.com/platform-installation\";\n                }\n                else if (BuildTargetDiscovery.PlatformHasFlag(buildTarget, TargetAttributes.IsStandalonePlatform))\n                    buttonMsg = \"\";\n\n                GUIContent[] notLicensedMessage =\n                {\n                    EditorGUIUtility.TextContent(string.Format(L10n.Tr(licenseMsg), niceName)),\n                    EditorGUIUtility.TextContent(L10n.Tr(buttonMsg)),\n                    new GUIContent(licenseURL)\n                };\n\n                GUILayout.Label(notLicensedMessage[0], EditorStyles.wordWrappedLabel);\n                GUILayout.Space(5);\n                GUILayout.BeginHorizontal();\n                GUILayout.FlexibleSpace();\n                if (notLicensedMessage[1].text.Length != 0)\n                {\n                    if (GUILayout.Button(notLicensedMessage[1]))\n                    {\n                        Application.OpenURL(notLicensedMessage[2].text);\n                    }\n                }\n                GUILayout.EndHorizontal();\n                GUIBuildButtons(false, false, false, platform, postprocessor);\n                return;\n            }\n\n            buildTargetSettingsScrollPosition = GUILayout.BeginScrollView(buildTargetSettingsScrollPosition);\n\n            // FIXME: WHY IS THIS ALL IN ONE FUNCTION?!\n            // Draw the side bar to the right. Different options like specific Standalone player to build, profiling and debugging options, etc.\n            string module = ModuleManager.GetTargetStringFrom(buildTarget);\n            IBuildWindowExtension buildWindowExtension = ModuleManager.GetBuildWindowExtension(module);\n            if (buildWindowExtension != null)\n                buildWindowExtension.ShowPlatformBuildOptions();\n\n            GUI.changed = false;\n            GUI.enabled = true;\n\n            bool enableBuildButton = buildWindowExtension != null ? buildWindowExtension.EnabledBuildButton() : true;\n            bool enableBuildAndRunButton = false;\n\n            bool shouldDrawDebuggingToggle = buildWindowExtension != null ? buildWindowExtension.ShouldDrawScriptDebuggingCheckbox() : true;\n            bool shouldDrawExplicitNullChecksToggle = buildWindowExtension != null ? buildWindowExtension.ShouldDrawExplicitNullCheckbox() : false;\n            bool shouldDrawDivideByZeroChecksToggle = buildWindowExtension != null ? buildWindowExtension.ShouldDrawExplicitDivideByZeroCheckbox() : false;\n            bool shouldDrawArrayBoundsChecksToggle = buildWindowExtension != null ? buildWindowExtension.ShouldDrawExplicitArrayBoundsCheckbox() : false;\n            bool shouldDrawDevelopmentPlayerToggle = buildWindowExtension != null ? buildWindowExtension.ShouldDrawDevelopmentPlayerCheckbox() : true;\n\n            bool canInstallInBuildFolder = false;\n\n            if (BuildPipeline.IsBuildPlatformSupported(buildTarget))\n            {\n                bool shouldDrawProfilerToggles = buildWindowExtension != null ? buildWindowExtension.ShouldDrawProfilerCheckbox() : true;\n\n                GUI.enabled = shouldDrawDevelopmentPlayerToggle;\n                if (shouldDrawDevelopmentPlayerToggle)\n                    EditorUserBuildSettings.development = EditorGUILayout.Toggle(styles.debugBuild, EditorUserBuildSettings.development);\n\n                bool developmentBuild = EditorUserBuildSettings.development;\n\n                GUI.enabled = developmentBuild;\n\n                if (shouldDrawProfilerToggles)\n                {\n                    var profilerDisabled = !GUI.enabled && !developmentBuild;\n\n                    var autoConnectLabel = profilerDisabled ? styles.autoconnectProfilerDisabled : styles.autoconnectProfiler;\n                    EditorUserBuildSettings.connectProfiler = EditorGUILayout.Toggle(autoConnectLabel, EditorUserBuildSettings.connectProfiler);\n\n                    var buildWithDeepProfilerLabel = profilerDisabled ? styles.buildWithDeepProfilerDisabled : styles.buildWithDeepProfiler;\n                    EditorUserBuildSettings.buildWithDeepProfilingSupport = EditorGUILayout.Toggle(buildWithDeepProfilerLabel, EditorUserBuildSettings.buildWithDeepProfilingSupport);\n                }\n\n                GUI.enabled = developmentBuild;\n                if (shouldDrawDebuggingToggle)\n                {\n                    using (new EditorGUI.DisabledScope(buildWindowExtension != null ? buildWindowExtension.ShouldDisableManagedDebuggerCheckboxes() : false))\n                    {\n                        EditorUserBuildSettings.allowDebugging = EditorGUILayout.Toggle(styles.allowDebugging, EditorUserBuildSettings.allowDebugging);\n\n                        // Not all platforms have native dialog implemented in Runtime\\Misc\\GiveDebuggerChanceToAttachIfRequired.cpp\n                        // Display this option only for developer builds\n                        bool shouldDrawWaitForManagedDebugger = buildWindowExtension != null ? buildWindowExtension.ShouldDrawWaitForManagedDebugger() : false;\n\n                        if (EditorUserBuildSettings.allowDebugging && shouldDrawWaitForManagedDebugger)\n                        {\n                            EditorUserBuildSettings.waitForManagedDebugger = EditorGUILayout.Toggle(styles.waitForManagedDebugger, EditorUserBuildSettings.waitForManagedDebugger);\n                        }\n\n                        bool shouldDrawManagedDebuggerFixedPort = buildWindowExtension != null ? buildWindowExtension.ShouldDrawManagedDebuggerFixedPort() : false;\n                        if (EditorUserBuildSettings.allowDebugging && shouldDrawManagedDebuggerFixedPort)\n                        {\n                            EditorUserBuildSettings.managedDebuggerFixedPort = EditorGUILayout.IntField(styles.managedDebuggerFixedPort, EditorUserBuildSettings.managedDebuggerFixedPort);\n                        }\n                    }\n\n                    if (EditorUserBuildSettings.allowDebugging && PlayerSettings.GetScriptingBackend(namedBuildTarget) == ScriptingImplementation.IL2CPP)\n                    {\n                        var apiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(namedBuildTarget);\n                        bool isDebuggerUsable = apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6 || apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0 ||\n                            apiCompatibilityLevel == ApiCompatibilityLevel.NET_Unity_4_8 || apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard;\n\n                        if (!isDebuggerUsable)\n                            EditorGUILayout.HelpBox(\"Script debugging is only supported with IL2CPP on .NET 4.x and .NET Standard 2.0 API Compatibility Levels.\", MessageType.Warning);\n                    }\n                }\n\n                if (shouldDrawExplicitNullChecksToggle)\n                {\n                    // Force 'ExplicitNullChecks' to true if it's a development build.\n                    GUI.enabled = !developmentBuild;\n                    if (GUI.enabled == false)\n                    {\n                        EditorUserBuildSettings.explicitNullChecks = true;\n                    }\n                    EditorUserBuildSettings.explicitNullChecks = EditorGUILayout.Toggle(styles.explicitNullChecks, EditorUserBuildSettings.explicitNullChecks);\n                    // Undo force from above\n                    GUI.enabled = developmentBuild;\n                }\n\n                if (shouldDrawDivideByZeroChecksToggle)\n                {\n                    // Force 'explicitDivideByZeroChecks' to true if it's a development build.\n                    GUI.enabled = !developmentBuild;\n                    if (GUI.enabled == false)\n                    {\n                        EditorUserBuildSettings.explicitDivideByZeroChecks = true;\n                    }\n                    EditorUserBuildSettings.explicitDivideByZeroChecks = EditorGUILayout.Toggle(styles.explicitDivideByZeroChecks, EditorUserBuildSettings.explicitDivideByZeroChecks);\n                    // Undo force from above\n                    GUI.enabled = developmentBuild;\n                }\n\n                if (shouldDrawArrayBoundsChecksToggle)\n                {\n                    // Force 'explicitArrayBoundsChecks' to true if it's a development build.\n                    GUI.enabled = !developmentBuild;\n                    if (GUI.enabled == false)\n                    {\n                        EditorUserBuildSettings.explicitArrayBoundsChecks = true;\n                    }\n                    EditorUserBuildSettings.explicitArrayBoundsChecks = EditorGUILayout.Toggle(styles.explicitArrayBoundsChecks, EditorUserBuildSettings.explicitArrayBoundsChecks);\n                    // Undo force from above\n                    GUI.enabled = developmentBuild;\n                }\n\n                GUI.enabled = true;\n\n                if (postprocessor != null && postprocessor.SupportsLz4Compression())\n                {\n                    var cmpIdx = Array.IndexOf(styles.compressionTypes, EditorUserBuildSettings.GetCompressionType(namedBuildTarget.ToBuildTargetGroup()));\n                    if (cmpIdx == -1)\n                        cmpIdx = Array.IndexOf(styles.compressionTypes, postprocessor.GetDefaultCompression());\n                    if (cmpIdx == -1)\n                        cmpIdx = 1; // Lz4 by default.\n                    cmpIdx = EditorGUILayout.Popup(styles.compressionMethod, cmpIdx, styles.compressionStrings);\n                    EditorUserBuildSettings.SetCompressionType(namedBuildTarget.ToBuildTargetGroup(), styles.compressionTypes[cmpIdx]);\n                }\n\n                canInstallInBuildFolder = Unsupported.IsSourceBuild() && PostprocessBuildPlayer.SupportsInstallInBuildFolder(buildTarget);\n\n                if (enableBuildButton)\n                {\n                    enableBuildAndRunButton = buildWindowExtension != null ? buildWindowExtension.EnabledBuildAndRunButton()\n                        && !(EditorUserBuildSettings.installInBuildFolder) : !(EditorUserBuildSettings.installInBuildFolder);\n                }\n            }\n            else\n            {\n                GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));\n\n                GUILayout.BeginVertical(GUILayout.ExpandWidth(true));\n\n                GUILayout.Label(string.Format(L10n.Tr(\"{0} is not supported in this build.\\nDownload a build that supports it.\"), BuildPipeline.GetBuildTargetGroupDisplayName(namedBuildTarget.ToBuildTargetGroup())));\n\n                GUILayout.EndVertical();\n                GUILayout.FlexibleSpace();\n                GUILayout.EndHorizontal();\n            }\n\n            drawingMultiplayerBuildOptions?.Invoke(BuildProfileContext.instance.GetForClassicPlatform(platformGuid));\n\n            GUILayout.EndScrollView();\n\n            GUIBuildButtons(buildWindowExtension, enableBuildButton, enableBuildAndRunButton,\n                canInstallInBuildFolder, platform, postprocessor);\n        }\n\n        internal static void ShowNoModuleLabel(\n            GUID platformGuid,\n            string noModuleLoaded,\n            GUIContent openDownloadPage,\n            GUIContent installModuleWithHub,\n            string editorWillNeedToBeReloaded)\n        {\n            var basePlatformGuid = BuildTargetDiscovery.GetBasePlatformGUID(platformGuid);\n            var displayName = BuildTargetDiscovery.BuildPlatformDisplayName(basePlatformGuid);\n            GUILayout.Label(EditorGUIUtility.TextContent(string.Format(noModuleLoaded, displayName)));\n\n            var url = string.Empty;\n            if (!isEditorinstalledWithHub || !BuildTargetDiscovery.BuildPlatformCanBeInstalledWithHub(platformGuid))\n            {\n                if (GUILayout.Button(openDownloadPage, EditorStyles.miniButton, GUILayout.ExpandWidth(false)))\n                {\n                    url = GetPlaybackEngineDownloadURL(platformGuid);\n                    Help.BrowseURL(url);\n                }\n            }\n            else\n            {\n                if (GUILayout.Button(installModuleWithHub, EditorStyles.miniButton, GUILayout.ExpandWidth(false)))\n                {\n                    url = GetUnityHubModuleDownloadURL(platformGuid);\n                    Help.BrowseURL(url);\n                }\n            }\n\n            GUILayout.Label(editorWillNeedToBeReloaded, EditorStyles.wordWrappedMiniLabel);\n        }\n\n        private static void GUIBuildButtons(bool enableBuildButton,\n            bool enableBuildAndRunButton,\n            bool canInstallInBuildFolder,\n            BuildPlatform platform,\n            IBuildPostprocessor postprocessor)\n        {\n            GUIBuildButtons(null, enableBuildButton, enableBuildAndRunButton, canInstallInBuildFolder, platform, postprocessor);\n        }\n\n        private static void GUIBuildButtons(IBuildWindowExtension buildWindowExtension,\n            bool enableBuildButton,\n            bool enableBuildAndRunButton,\n            bool canInstallInBuildFolder,\n            BuildPlatform platform,\n            IBuildPostprocessor postprocessor)\n        {\n            GUILayout.FlexibleSpace();\n\n\n            if (canInstallInBuildFolder)\n            {\n                GUILayout.BeginHorizontal();\n                EditorUserBuildSettings.installInBuildFolder = GUILayout.Toggle(EditorUserBuildSettings.installInBuildFolder, styles.installInBuildFolder, GUILayout.ExpandWidth(false));\n                if (GUILayout.Button(styles.installInBuildFolderHelp, EditorStyles.iconButton))\n                {\n                    var path = Path.Combine(Unsupported.GetBaseUnityDeveloperFolder(), \"Documentation/BuildDocs/view\");\n                    if (Application.platform == RuntimePlatform.WindowsEditor)\n                        System.Diagnostics.Process.Start(path + \".cmd\");\n                    else\n                        System.Diagnostics.Process.Start(\"/bin/bash\", path);\n                }\n                GUILayout.EndHorizontal();\n            }\n            else\n                EditorUserBuildSettings.installInBuildFolder = false;\n\n            if ((buildWindowExtension != null) && Unsupported.IsSourceBuild())\n                buildWindowExtension.ShowInternalPlatformBuildOptions();\n\n\n            if (buildWindowExtension != null)\n                buildWindowExtension.ShowPlatformBuildWarnings();\n\n            // Disable the 'Build' and 'Build And Run' buttons when the project setup doesn't satisfy the platform requirements\n            if (enableBuildButton && enableBuildAndRunButton)\n            {\n                if (!IsVirtualTexturingSettingsValid(platform))\n                {\n                    enableBuildAndRunButton = false;\n                    enableBuildButton = false;\n                    EditorGUILayout.HelpBox(styles.invalidVirtualTexturingSettingMessage);\n                }\n            }\n\n            if (EditorApplication.isCompiling || EditorApplication.isUpdating)\n            {\n                enableBuildAndRunButton = false;\n                enableBuildButton = false;\n                EditorGUILayout.HelpBox(styles.compilingMessage);\n            }\n            GUILayout.BeginHorizontal();\n            GUILayout.FlexibleSpace();\n            if (EditorGUILayout.LinkButton(styles.learnAboutUnityCloudBuild))\n            {\n                Application.OpenURL(string.Format(\"{0}/from/editor/buildsettings?upid={1}&pid={2}&currentplatform={3}&selectedplatform={4}&unityversion={5}\",\n                    UnityEditorInternal.WebURLs.cloudBuildPage, CloudProjectSettings.projectId, PlayerSettings.productGUID, EditorUserBuildSettings.activeBuildTarget, EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget(), Application.unityVersion));\n            }\n            GUILayout.EndHorizontal();\n            // Space 6 for alignment with platform column and to reduce missclicks with Build And Run button\n            GUILayout.Space(6);\n\n            GUILayout.BeginHorizontal();\n            GUILayout.FlexibleSpace();\n\n            GUIContent buildButton = null;\n            GUIContent buildAndRunButton = null;\n            bool askForBuildLocation = true;\n            if (buildWindowExtension != null)\n            {\n                buildWindowExtension.GetBuildButtonTitles(out buildButton, out buildAndRunButton);\n                askForBuildLocation = buildWindowExtension.AskForBuildLocation();\n            }\n\n            buildButton = buildButton ?? styles.build;\n            buildAndRunButton = buildAndRunButton ?? styles.buildAndRun;\n\n            // Run last build button(s)\n            if (buildWindowExtension != null && buildWindowExtension.ShouldDrawRunLastBuildButton())\n            {\n                buildWindowExtension.DoRunLastBuildButtonGui();\n            }\n\n            // Switching build target in the editor\n            BuildTarget selectedTarget = EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget(platform.namedBuildTarget);\n\n            bool selectedTargetIsActive = platform.IsActive();\n\n            if (selectedTargetIsActive)\n            {\n                // Build Button\n                GUI.enabled = enableBuildButton;\n\n                {\n                    Rect buildRect = GUILayoutUtility.GetRect(buildButton, EditorStyles.dropDownToggleButton,\n                        GUILayout.Width(Styles.kButtonWidth));\n                    Rect buildRectPopupButton = buildRect;\n                    buildRectPopupButton.x += buildRect.width - 16;\n                    buildRectPopupButton.width = 16;\n\n                    if (EditorGUI.DropdownButton(buildRectPopupButton, GUIContent.none, FocusType.Passive,\n                        GUIStyle.none))\n                    {\n                        GenericMenu menu = new GenericMenu();\n                        menu.AddItem(new GUIContent(\"Clean Build…\"), false,\n                            () =>\n                            {\n                                CallBuildMethods(askForBuildLocation,\n                                    BuildOptions.ShowBuiltPlayer | BuildOptions.CleanBuildCache);\n                            });\n                        menu.AddItem(new GUIContent(\"Force skip data build\"), false,\n                            () =>\n                            {\n                                CallBuildMethods(askForBuildLocation,\n                                    BuildOptions.ShowBuiltPlayer | BuildOptions.BuildScriptsOnly);\n                            });\n                        menu.DropDown(buildRect);\n                    }\n                    else if (GUI.Button(buildRect, buildButton, EditorStyles.dropDownToggleButton))\n                    {\n                        CallBuildMethods(askForBuildLocation, BuildOptions.ShowBuiltPlayer);\n                        GUIUtility.ExitGUI();\n                    }\n                }\n            }\n            else\n            {\n                GUI.enabled = BuildPipeline.IsBuildPlatformSupported(selectedTarget);\n                if (GUILayout.Button(styles.switchPlatform, GUILayout.Width(Styles.kButtonWidth)))\n                {\n                    ApplyAssetImportOverridesToSettingsAsset();\n                    platform.SetActive();\n                    GUIUtility.ExitGUI();\n                }\n            }\n\n            // Build and Run button\n            GUI.enabled = enableBuildAndRunButton && selectedTargetIsActive;\n            if (GUILayout.Button(buildAndRunButton, GUILayout.Width(Styles.kButtonWidth)))\n            {\n                BuildPlayerAndRunInternal(askForBuildLocation);\n                GUIUtility.ExitGUI();\n            }\n\n            GUILayout.EndHorizontal();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildPlayerWindowBuildMethods.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.Modules;\nusing UnityEditor.Build;\nusing UnityEngine;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing System.Collections;\nusing System.IO;\nusing System;\nusing System.Linq;\nusing UnityEditor.Build.Reporting;\nusing UnityEditor.Connect;\nusing UnityEditor.Profiling;\nusing UnityEditor.Utils;\nusing UnityEditor.Build.Profile;\n\nnamespace UnityEditor\n{\n    public partial class BuildPlayerWindow : EditorWindow\n    {\n        private static Func<BuildPlayerOptions, BuildPlayerOptions> getBuildPlayerOptionsHandler;\n        private static Action<BuildPlayerOptions> buildPlayerHandler;\n        private static bool m_Building = false;\n        internal static Action<BuildReport> buildCompletionHandler;\n\n        /// <summary>\n        /// Exception thrown when an abort or error condition is reached within a build method delegate.\n        /// </summary>\n        public class BuildMethodException : System.Exception\n        {\n            /// <summary>\n            /// Constructor for aborting a method without displaying an error.\n            /// </summary>\n            public BuildMethodException() : base(\"\") {}\n\n            /// <summary>\n            /// Constructor for aborting on error that will print the log the given message as an error.\n            /// </summary>\n            /// <param name=\"message\"></param>\n            public BuildMethodException(string message) : base(message) {}\n        }\n\n        /// <summary>\n        /// Register a delegate method to calculate BuildPlayerOptions that are passed to the build process.\n        /// </summary>\n        /// <param name=\"func\">Delegate method</param>\n        public static void RegisterGetBuildPlayerOptionsHandler(Func<BuildPlayerOptions, BuildPlayerOptions> func)\n        {\n            // Display a warning if user scripts try to register this delegate multiple times\n            if (func != null && getBuildPlayerOptionsHandler != null)\n                Debug.LogWarning(\"The get build player options handler in BuildPlayerWindow is being reassigned!\");\n\n            getBuildPlayerOptionsHandler = func;\n        }\n\n        /// <summary>\n        /// Register a delegate method to execute a player build process.\n        /// </summary>\n        /// <param name=\"func\">Delegate method</param>\n        public static void RegisterBuildPlayerHandler(Action<BuildPlayerOptions> func)\n        {\n            // Display a warning if user scripts try to register this delegate multiple times\n            if (func != null && buildPlayerHandler != null)\n                Debug.LogWarning(\"The build player handler in BuildPlayerWindow is being reassigned!\");\n\n            buildPlayerHandler = func;\n        }\n\n        /// <summary>\n        /// Method called by the UI when the \"Build\" or \"Build and Run\" buttons are pressed.\n        /// </summary>\n        /// <param name=\"defaultBuildOptions\"></param>\n        internal static void CallBuildMethods(bool askForBuildLocation, BuildOptions defaultBuildOptions)\n        {\n            EditorCompilationInterface.IsCompiling(out var isCompiling);\n            if (isCompiling)\n            {\n                Debug.LogWarning(\"Cannot build player while editor is compiling scripts.\");\n                return;\n            }\n\n            // One build at a time!\n            if (m_Building)\n                return;\n            try\n            {\n                m_Building = true;\n                BuildPlayerOptions options = new BuildPlayerOptions();\n                options.options = defaultBuildOptions;\n\n                if (getBuildPlayerOptionsHandler != null)\n                    options = getBuildPlayerOptionsHandler(options);\n                else\n                    options = DefaultBuildMethods.GetBuildPlayerOptionsInternal(askForBuildLocation, options);\n\n                if (buildPlayerHandler != null)\n                    buildPlayerHandler(options);\n                else\n                    DefaultBuildMethods.BuildPlayer(options);\n            }\n            catch (BuildMethodException)\n            {\n            }\n            finally\n            {\n                m_Building = false;\n            }\n        }\n\n        /// <summary>\n        /// Default (legacy) implementation of player window build methods.\n        /// </summary>\n        public static class DefaultBuildMethods\n        {\n            /// <summary>\n            /// Default implementation of the build player method.\n            /// </summary>\n            /// <param name=\"options\"></param>\n            public static void BuildPlayer(BuildPlayerOptions options)\n            {\n                if (!UnityConnect.instance.canBuildWithUPID)\n                {\n                    if (!EditorUtility.DisplayDialog(\"Missing Project ID\", \"Because you are not a member of this project this build will not access Unity services.\\nDo you want to continue?\", \"Yes\", \"No\"))\n                        throw new BuildMethodException();\n                }\n\n                if (!BuildPipeline.IsBuildPlatformSupported(options.target))\n                    throw new BuildMethodException(\"Build target is not supported.\");\n\n                string module = ModuleManager.GetTargetStringFrom(options.target);\n                IBuildWindowExtension buildWindowExtension = ModuleManager.GetBuildWindowExtension(module);\n                if (buildWindowExtension != null && (options.options & BuildOptions.AutoRunPlayer) != 0 && !buildWindowExtension.EnabledBuildAndRunButton())\n                    throw new BuildMethodException();\n\n                if (Unsupported.IsBleedingEdgeBuild())\n                {\n                    var sb = new System.Text.StringBuilder();\n                    sb.AppendLine(\"This version of Unity is a BleedingEdge build that has not seen any manual testing.\");\n                    sb.AppendLine(\"You should consider this build unstable.\");\n                    sb.AppendLine(\"We strongly recommend that you use a normal version of Unity instead.\");\n\n                    if (EditorUtility.DisplayDialog(\"BleedingEdge Build\", sb.ToString(), \"Cancel\", \"OK\"))\n                        throw new BuildMethodException();\n                }\n\n                // See if we need to switch platforms and delay the build.  We do this whenever\n                // we're trying to build for a target different from the active one so as to ensure\n                // that the compiled script code we have loaded is built for the same platform we\n                // are building for.  As we can't reload while our editor stuff is still executing,\n                // we need to defer to after the next script reload then.\n                bool delayToAfterScriptReload = false;\n                if (EditorUserBuildSettings.activeBuildTarget != options.target ||\n                    EditorUserBuildSettings.activeBuildTargetGroup != options.targetGroup)\n                {\n                    if (!EditorUserBuildSettings.SwitchActiveBuildTargetAsync(options.targetGroup, options.target))\n                    {\n                        // Switching the build target failed.  No point in trying to continue\n                        // with a build.\n                        var errStr = string.Format(\"Could not switch to build target '{0}', '{1}'.\",\n                            BuildPipeline.GetBuildTargetGroupDisplayName(options.targetGroup),\n                            BuildPlatforms.instance.GetBuildTargetDisplayName(options.targetGroup, options.target, options.subtarget));\n                        throw new BuildMethodException(errStr);\n                    }\n\n                    if (EditorApplication.isCompiling)\n                        delayToAfterScriptReload = true;\n                }\n\n                bool locationPathExistedBeforeBuild = System.IO.Directory.Exists(options.locationPathName);\n                // Trigger build.\n                // Note: report will be null, if delayToAfterScriptReload = true\n                var report = BuildPipeline.BuildPlayerInternalNoCheck(options.scenes, options.locationPathName, options.assetBundleManifestPath, options.targetGroup, options.target, options.subtarget, options.options, options.extraScriptingDefines, delayToAfterScriptReload);\n\n                if (report != null\n                )\n                {\n                    var resultStr = String.Format(\"Build completed with a result of '{0}' in {1} seconds ({2} ms) [{3} -> {4}, {5}]\",\n                        report.summary.result.ToString(\"g\"),\n                        Convert.ToInt32(report.summary.totalTime.TotalSeconds),\n                        Convert.ToInt32(report.summary.totalTime.TotalMilliseconds),\n                        report.summary.buildStartedAt.ToLocalTime(),\n                        report.summary.buildEndedAt.ToLocalTime(),\n                        FriendlyFormatBuildDuration(report.summary.totalTime)\n                        );\n                        \n                    switch (report.summary.result)\n                    {\n                        case Build.Reporting.BuildResult.Unknown:\n                            Debug.LogWarning(resultStr);\n                            break;\n                        case Build.Reporting.BuildResult.Failed:\n                            //  On some platforms the user creates the build folder, therefore they own the folder and\n                            // it should not be automatically deleted by the Unity Editor, even if it is empty (case 1073851)\n                            if (options.target != BuildTarget.XboxOne && !locationPathExistedBeforeBuild)\n                                DeleteBuildFolderIfEmpty(report.summary.outputPath);\n                            Debug.LogError(resultStr + \"\\n\" + report.SummarizeErrors());\n                            throw new BuildMethodException();\n                        default:\n                            Debug.Log(resultStr);\n                            break;\n                    }\n\n                    buildCompletionHandler?.Invoke(report);\n                }\n            }\n\n            static string FriendlyFormatBuildDuration(TimeSpan duration)\n            {\n                int totalHours = (int)duration.TotalHours;\n\n                if (totalHours > 0)\n                {\n                    return string.Format(\"{0}h {1:D2}m {2:D2}s\", totalHours, duration.Minutes, duration.Seconds);\n                }\n\n                if (duration.Minutes > 0)\n                {\n                    return string.Format(\"{0}m {1:D2}s\", duration.Minutes, duration.Seconds);\n                }\n\n                return string.Format(\"{0:D2}s\", duration.Seconds);\n            }\n\n            /// <summary>\n            /// Default implementation for calculating build options before building the player.\n            /// </summary>\n            /// <param name=\"defaultBuildPlayerOptions\"></param>\n            /// <returns></returns>\n            public static BuildPlayerOptions GetBuildPlayerOptions(BuildPlayerOptions defaultBuildPlayerOptions)\n            {\n                return GetBuildPlayerOptionsInternal(true, defaultBuildPlayerOptions);\n            }\n\n            internal static bool IsInstallInBuildFolderOption()\n            {\n                BuildTarget buildTarget = EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget();\n                BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;\n\n                return EditorUserBuildSettings.installInBuildFolder &&\n                    PostprocessBuildPlayer.SupportsInstallInBuildFolder(buildTarget) &&\n                    (Unsupported.IsSourceBuild() || IsMetroPlayer(buildTarget));\n            }\n\n            internal static BuildPlayerOptions GetBuildPlayerOptionsInternal(bool askForBuildLocation, BuildPlayerOptions defaultBuildPlayerOptions)\n            {\n                var options = defaultBuildPlayerOptions;\n\n                bool updateExistingBuild = false;\n\n                BuildTarget buildTarget = EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget();\n                BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;\n                int subtarget = EditorUserBuildSettings.GetSelectedSubtargetFor(buildTarget);\n\n                options.options = BuildProfileModuleUtil.GetBuildOptions(buildTarget, buildTargetGroup, string.Empty, options.options);\n\n                if ((options.options & BuildOptions.InstallInBuildFolder) == 0 &&\n                    (options.options & BuildOptions.PatchPackage) == 0)\n                {\n                    if (askForBuildLocation && !PickBuildLocation(buildTargetGroup, buildTarget, subtarget, options.options, out updateExistingBuild))\n                        throw new BuildMethodException();\n\n                    var newLocation = EditorUserBuildSettings.GetBuildLocation(buildTarget);\n\n                    if (newLocation.Length == 0)\n                    {\n                        throw new BuildMethodException(\"Build location for buildTarget \" + buildTarget + \" is not valid.\");\n                    }\n\n                    if (!askForBuildLocation)\n                    {\n                        switch (BuildPipeline.BuildCanBeAppended(buildTarget, newLocation))\n                        {\n                            case CanAppendBuild.Unsupported:\n                                break;\n                            case CanAppendBuild.Yes:\n                                updateExistingBuild = true;\n                                break;\n                            case CanAppendBuild.No:\n                                if (!PickBuildLocation(buildTargetGroup, buildTarget, subtarget, options.options, out updateExistingBuild))\n                                    throw new BuildMethodException();\n\n                                newLocation = EditorUserBuildSettings.GetBuildLocation(buildTarget);\n                                if (!BuildLocationIsValid(newLocation))\n                                    throw new BuildMethodException(\"Build location for buildTarget \" + buildTarget + \" is not valid.\");\n\n                                break;\n                        }\n                    }\n                }\n\n                if (updateExistingBuild)\n                    options.options |= BuildOptions.AcceptExternalModificationsToPlayer;\n\n                options.target = buildTarget;\n                options.subtarget = subtarget;\n                options.targetGroup = buildTargetGroup;\n                options.locationPathName = EditorUserBuildSettings.GetBuildLocation(buildTarget);\n                options.assetBundleManifestPath = PostprocessBuildPlayer.GetStreamingAssetsBundleManifestPath();\n\n                // Build a list of scenes that are enabled\n                ArrayList scenesList = new ArrayList();\n                EditorBuildSettingsScene[] editorScenes = EditorBuildSettings.scenes;\n                foreach (EditorBuildSettingsScene scene in editorScenes)\n                {\n                    if (scene.enabled && !string.IsNullOrEmpty(scene.path))\n                        scenesList.Add(scene.path);\n                }\n\n                options.scenes = scenesList.ToArray(typeof(string)) as string[];\n\n                return options;\n            }\n\n            private static bool PickBuildLocation(BuildTargetGroup targetGroup, BuildTarget target, int subtarget, BuildOptions options, out bool updateExistingBuild)\n            {\n                updateExistingBuild = false;\n                var previousPath = EditorUserBuildSettings.GetBuildLocation(target);\n\n                string defaultFolder;\n                string defaultName;\n                if (previousPath == String.Empty)\n                {\n                    defaultFolder = FileUtil.DeleteLastPathNameComponent(Application.dataPath);\n                    defaultName = \"\";\n                }\n                else\n                {\n                    defaultFolder = FileUtil.DeleteLastPathNameComponent(previousPath);\n                    defaultName = FileUtil.GetLastPathNameComponent(previousPath);\n                }\n\n                string extension = PostprocessBuildPlayer.GetExtensionForBuildTarget(target, subtarget, options);\n                // Invalidate default name, if extension mismatches the default file (for ex., when switching between folder type export to file type export, see Android)\n                if (extension != Path.GetExtension(defaultName).Replace(\".\", \"\"))\n                    defaultName = string.Empty;\n\n                // Hack: For Windows Standalone, we want the BuildPanel to choose a folder,\n                // but we don't want BuildPlayer to take a folder path because historically it took an .exe path\n                // and we would be breaking tons of projects!\n                bool isWindowsStandalone = target == BuildTarget.StandaloneWindows || target == BuildTarget.StandaloneWindows64;\n                string realExtension = extension;\n                if (isWindowsStandalone)\n                {\n                    extension = string.Empty;\n                    // Remove the filename.exe part from the path\n                    if (!string.IsNullOrEmpty(defaultName))\n                        defaultName = Path.GetDirectoryName(defaultName);\n                }\n\n                string title = \"Build \" + BuildPlatforms.instance.GetBuildTargetDisplayName(targetGroup, target, subtarget);\n\n                string path;\n                bool isValidPath = false;\n                do\n                {\n                    path = EditorUtility.SaveBuildPanel(target, title, defaultFolder, defaultName, extension, out updateExistingBuild);\n                    if (path == string.Empty)\n                        return false;\n\n                    if (IsBuildPathValid(path, out var msg))\n                    {\n                        isValidPath = true;\n                    }\n                    else if (!EditorUtility.DisplayDialog(\"Invalid build path\", msg, \"OK\", \"Cancel\"))\n                    {\n                        Debug.LogError($\"Invalid build path: '{path}'. {msg}\");\n                        return false;\n                    }\n\n                } while (!isValidPath);\n\n                if (isWindowsStandalone)\n                {\n                    extension = realExtension;\n                    path = Path.Combine(path, Paths.MakeValidFileName(PlayerSettings.productName) + '.' + extension);\n                }\n\n                // Enforce extension if needed\n                if (extension != string.Empty && FileUtil.GetPathExtension(path).ToLower() != extension)\n                    path += '.' + extension;\n\n                // A path may not be empty initially, but it could contain, e.g., a drive letter (as in Windows),\n                // so even appending an extension will work fine, but in reality the name will be, for example,\n                // G:/\n                //Debug.Log(path);\n\n                string currentlyChosenName = FileUtil.GetLastPathNameComponent(path);\n                if (currentlyChosenName == string.Empty)\n                    return false; // No nameless projects, please\n\n                // We don't want to re-create a directory that already exists, this may\n                // result in access-denials that will make users unhappy.\n                string check_dir = extension != string.Empty ? FileUtil.DeleteLastPathNameComponent(path) : path;\n                if (!Directory.Exists(check_dir))\n                    Directory.CreateDirectory(check_dir);\n\n                // On OSX we've got replace/update dialog, for other platforms warn about deleting\n                // files in target folder.\n                if ((target == BuildTarget.iOS) && (Application.platform != RuntimePlatform.OSXEditor))\n                    if (!FolderIsEmpty(path) && !UserWantsToDeleteFiles(path))\n                        return false;\n\n                EditorUserBuildSettings.SetBuildLocation(target, path);\n                return true;\n            }\n\n            private static string NormalizePath(string path)\n            {\n                var fullPath = path;\n                if (fullPath.Length > 1 && fullPath[fullPath.Length - 1] == '.' && fullPath[fullPath.Length - 2] != '.')\n                    fullPath = fullPath.Remove(fullPath.Length - 1);\n\n                if (fullPath.EndsWith(\"/\") || fullPath.EndsWith(\"\\\\\"))\n                    fullPath = fullPath.Remove(fullPath.Length - 1);\n\n                fullPath = string.IsNullOrEmpty(fullPath) ? string.Empty : Path.GetFullPath(fullPath);\n\n                if (Path.DirectorySeparatorChar == '/')\n                    return fullPath;\n                return fullPath.Replace(Path.DirectorySeparatorChar, '/');\n            }\n\n            internal static bool IsBuildPathValid(string path, out string errorMessage)\n            {\n                errorMessage = default;\n                var cleanedPath = NormalizePath(path);\n                if (cleanedPath.Equals(string.Empty) &&\n                    IsInstallInBuildFolderOption())\n                    return true;\n\n                var basePath = NormalizePath(Application.dataPath + \"/../\");\n\n                // Allow build into the Temp folder (used by Unity TestRunner)\n                var invalidPaths = new[]\n                {\n                    NormalizePath(basePath + \"/Assets\"),\n                    NormalizePath(basePath + \"/ProjectSettings\"),\n                    NormalizePath(basePath + \"/Library\"),\n                    NormalizePath(basePath + \"/Packages\"),\n                    NormalizePath(basePath + \"/UserSettings\")\n                };\n\n                var invalidPath = invalidPaths.FirstOrDefault(p => cleanedPath.Contains(p, StringComparison.OrdinalIgnoreCase));\n                if (!string.IsNullOrEmpty(invalidPath))\n                {\n                    var dirName = Path.GetFileName(invalidPath);\n                    errorMessage = $\"The '{dirName}' directory is an internal work directory of Unity and \" +\n                                    \"projects should not be built inside it. Please choose another directory for the build output.\";\n                    return false;\n                }\n\n                if (cleanedPath.Equals(basePath, StringComparison.OrdinalIgnoreCase))\n                {\n                    errorMessage = \"The project root directory should not be used as a build output directory. \" +\n                                   \"Please create a subdirectory for the build output.\";\n                    return false;\n                }\n\n                var userDesktopPath = NormalizePath(Environment.GetFolderPath(Environment.SpecialFolder.Desktop));\n                if (cleanedPath.Equals(userDesktopPath, StringComparison.OrdinalIgnoreCase))\n                {\n                    errorMessage = \"The desktop directory should not be used as a build output directory. \" +\n                                   \"Please create a subdirectory for the build output.\";\n                    return false;\n                }\n\n                return true;\n            }\n\n            private static void DeleteBuildFolderIfEmpty(string path)\n            {\n                if (Directory.Exists(path) && FolderIsEmpty(path))\n                    Directory.Delete(path);\n            }\n\n            private static bool FolderIsEmpty(string path)\n            {\n                if (!Directory.Exists(path))\n                    return true;\n\n                return (Directory.GetDirectories(path).Length == 0)\n                    && (Directory.GetFiles(path).Length == 0);\n            }\n\n            private static bool UserWantsToDeleteFiles(string path)\n            {\n                string text =\n                    \"WARNING: all files and folders located in target folder: '\" + path + \"' will be deleted by build process.\";\n                return EditorUtility.DisplayDialog(\"Deleting existing files\", text, \"OK\", \"Cancel\");\n            }\n\n            private static bool IsMetroPlayer(BuildTarget target)\n            {\n                return target == BuildTarget.WSAPlayer;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfile.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEditor.Modules;\n\nnamespace UnityEditor.Build.Profile\n{\n    /// <summary>\n    /// Provides a set of configuration settings you can use to build your application on a particular platform.\n    /// </summary>\n    [RequiredByNativeCode(GenerateProxy = true)]\n    [StructLayout(LayoutKind.Sequential)]\n    [ExcludeFromObjectFactory]\n    [ExcludeFromPreset]\n    [HelpURL(\"build-profiles-reference\")]\n    public sealed partial class BuildProfile : ScriptableObject\n    {\n        /// <summary>\n        /// Asset Schema Version\n        /// </summary>\n        [SerializeField]\n        uint m_AssetVersion = 1;\n\n        /// <summary>\n        /// Build Target used to fetch module and build profile extension.\n        /// </summary>\n        [SerializeField] BuildTarget m_BuildTarget = BuildTarget.NoTarget;\n        [VisibleToOtherModules]\n        internal BuildTarget buildTarget\n        {\n            get => m_BuildTarget;\n            set => m_BuildTarget = value;\n        }\n\n        /// <summary>\n        /// Subtarget, Default for all non-Standalone platforms.\n        /// </summary>\n        [SerializeField] StandaloneBuildSubtarget m_Subtarget;\n        [VisibleToOtherModules]\n        internal StandaloneBuildSubtarget subtarget\n        {\n            get => m_Subtarget;\n            set => m_Subtarget = value;\n        }\n\n        /// <summary>\n        /// Platform ID of the build profile.\n        /// Correspond to platform GUID in <see cref=\"BuildTargetDiscovery\"/>\n        /// </summary>\n        [SerializeField] string m_PlatformId;\n        [VisibleToOtherModules]\n        internal GUID platformGuid\n        {\n            get => new GUID(m_PlatformId);\n            set => m_PlatformId = value.ToString();\n        }\n\n        /// <summary>\n        /// Platform ID of the build profile as string.\n        /// This is needed because the server team decided to use this\n        /// internal getter in their package.\n        /// PLEASE DON'T USE, USE platformGuid INSTEAD!\n        /// </summary>\n        [VisibleToOtherModules]\n        internal string platformId => m_PlatformId;\n\n        /// <summary>\n        /// Platform module specific build settings; e.g. AndroidBuildSettings.\n        /// </summary>\n        [SerializeReference] BuildProfilePlatformSettingsBase m_PlatformBuildProfile;\n        [VisibleToOtherModules]\n        internal BuildProfilePlatformSettingsBase platformBuildProfile\n        {\n            get => m_PlatformBuildProfile;\n            set => m_PlatformBuildProfile = value;\n        }\n\n        /// <summary>\n        /// Boolean flag for overriding global scene list.\n        /// When true, the scene list <see cref=\"scenes\"/> in the build profile is used\n        /// when building. Otherwise, the global scene list is used.\n        /// </summary>\n        /// <seealso cref=\"EditorBuildSettings\"/>\n        [SerializeField] private bool m_OverrideGlobalSceneList = false;\n        public bool overrideGlobalScenes\n        {\n            get => m_OverrideGlobalSceneList;\n            set => m_OverrideGlobalSceneList = value;\n        }\n\n        /// <summary>\n        /// List of scenes specified in the build profile.\n        /// </summary>\n        [SerializeField] private EditorBuildSettingsScene[] m_Scenes = Array.Empty<EditorBuildSettingsScene>();\n        public EditorBuildSettingsScene[] scenes\n        {\n            get\n            {\n                CheckSceneListConsistency();\n                return m_Scenes;\n            }\n            set\n            {\n                if (m_Scenes == value)\n                    return;\n\n                m_Scenes = value;\n                CheckSceneListConsistency();\n\n                if (this == BuildProfileContext.activeProfile && overrideGlobalScenes)\n                    EditorBuildSettings.SceneListChanged();\n            }\n        }\n\n        /// <summary>\n        /// Scripting Compilation Defines used during player and editor builds.\n        /// </summary>\n        [SerializeField] private string[] m_ScriptingDefines = Array.Empty<string>();\n        public string[] scriptingDefines\n        {\n            get => m_ScriptingDefines;\n            set => m_ScriptingDefines = value;\n        }\n\n        [VisibleToOtherModules]\n        internal Action OnPackageAddProgress;\n\n        [SerializeField]\n        PlayerSettingsYaml m_PlayerSettingsYaml = new();\n\n        PlayerSettings m_PlayerSettings;\n        [VisibleToOtherModules]\n        internal PlayerSettings playerSettings\n        {\n            get { return m_PlayerSettings; }\n\n            set { m_PlayerSettings = value; }\n        }\n\n        [VisibleToOtherModules]\n        internal Action OnPlayerSettingsUpdatedFromYAML;\n\n        /// <summary>\n        /// Cross-pipeline graphics settings overrides in build profile\n        /// </summary>\n        [VisibleToOtherModules]\n        internal BuildProfileGraphicsSettings graphicsSettings;\n\n        [VisibleToOtherModules]\n        internal Action OnGraphicsSettingsSubAssetRemoved;\n\n        /// <summary>\n        /// Quality settings overrides in build profile\n        /// </summary>\n        [VisibleToOtherModules]\n        internal BuildProfileQualitySettings qualitySettings;\n\n        [VisibleToOtherModules]\n        internal Action OnQualitySettingsSubAssetRemoved;\n\n        // TODO: Return server IBuildTargets for server build profiles. (https://jira.unity3d.com/browse/PLAT-6612)\n        /// <summary>\n        /// Get the IBuildTarget of the build profile.\n        /// </summary>\n        internal IBuildTarget GetIBuildTarget() => ModuleManager.GetIBuildTarget(platformGuid);\n\n        /// <summary>\n        /// Get the list of scenes that is used when building with the build profile.\n        /// </summary>\n        /// <returns>\n        /// Returns the build profile's scene list when it's overriding global scenes. Otherwise,\n        /// returns the global scene list.\n        /// </returns>\n        public EditorBuildSettingsScene[] GetScenesForBuild()\n        {\n            if (overrideGlobalScenes)\n                return scenes;\n\n            return EditorBuildSettings.globalScenes;\n        }\n\n        /// <summary>\n        /// Returns true if the given <see cref=\"BuildProfile\"/> is the active profile or a classic\n        /// profile for the EditorUserBuildSettings active build target.\n        /// </summary>\n        [VisibleToOtherModules]\n        internal bool IsActiveBuildProfileOrPlatform()\n        {\n            if (BuildProfileContext.activeProfile == this)\n                return true;\n\n            if (BuildProfileContext.activeProfile is not null\n                || !BuildProfileContext.IsClassicPlatformProfile(this))\n                return false;\n\n            return platformGuid == EditorUserBuildSettings.activePlatformGuid;\n        }\n\n        [VisibleToOtherModules]\n        internal bool CanBuildLocally()\n        {\n            // Note: If the build profile is still being configured (package add info is present)\n            // we do not want it to be buildable.\n            if (BuildProfileContext.instance.TryGetPackageAddInfo(this, out _))\n                return false;\n            // Note: A platform build profile may have a non-null value even if its module is not installed.\n            // This scenario is true for server platform profiles, which are the same type as the standalone one.\n            return platformBuildProfile != null && BuildProfileModuleUtil.IsModuleInstalled(platformGuid);\n        }\n\n        internal string GetLastRunnableBuildPathKey()\n        {\n            if (platformBuildProfile == null)\n                return string.Empty;\n\n            var key = platformBuildProfile.GetLastRunnableBuildPathKey();\n            if (string.IsNullOrEmpty(key) || BuildProfileContext.IsClassicPlatformProfile(this))\n                return key;\n\n            string assetPath = AssetDatabase.GetAssetPath(this);\n            return BuildProfileModuleUtil.GetLastRunnableBuildKeyFromAssetPath(assetPath, key);\n        }\n\n        /// <summary>\n        /// Duplicate the build profile. Note this does not create a new asset.\n        /// </summary>\n        [VisibleToOtherModules]\n        internal BuildProfile Duplicate()\n        {\n            var duplicatedProfile = Instantiate(this);\n\n            if (graphicsSettings != null)\n                duplicatedProfile.graphicsSettings = Instantiate(graphicsSettings);\n\n            if (qualitySettings != null)\n                duplicatedProfile.qualitySettings = Instantiate(qualitySettings);\n\n            return duplicatedProfile;\n        }\n\n        [VisibleToOtherModules]\n        internal void ResetToGlobalQualitySettingsValues()\n        {\n            var buildTargetGroupString = BuildPipeline.GetBuildTargetGroup(buildTarget).ToString();\n            var globalQualityLevels = QualitySettings.GetActiveQualityLevelsForPlatform(buildTargetGroupString);\n\n            var newBuildProfileQualityLevels = new string[globalQualityLevels.Length];\n\n            // populates newBuildProfileQualityLevels array with global quality levels in their existing order\n            for (int i = 0; i < globalQualityLevels.Length; i++)\n            {\n                newBuildProfileQualityLevels[i] = QualitySettings.names[globalQualityLevels[i]];\n            }\n\n            var globalDefaultQualityLevelIndex = QualitySettings.GetDefaultQualityForPlatform(buildTargetGroupString);\n            if (globalDefaultQualityLevelIndex != -1)\n                qualitySettings.defaultQualityLevel = QualitySettings.names[globalDefaultQualityLevelIndex];\n            else\n                qualitySettings.defaultQualityLevel = newBuildProfileQualityLevels.Length > 0 ? QualitySettings.names[globalQualityLevels[0]] : string.Empty;\n\n            qualitySettings.qualityLevels = newBuildProfileQualityLevels;\n\n            EditorUtility.SetDirty(qualitySettings);\n        }\n\n        void OnEnable()\n        {\n            ValidateDataConsistency();\n\n            // Check if the platform support module has been installed,\n            // and try to set an uninitialized platform settings.\n            if (platformBuildProfile == null)\n                TryCreatePlatformSettings();\n\n            onBuildProfileEnable?.Invoke(this);\n            LoadPlayerSettings();\n\n            TryLoadGraphicsSettings();\n            TryLoadQualitySettings();\n\n            if (BuildProfileContext.instance.TryGetPackageAddInfo(this, out var packageAddInfo))\n            {\n                packageAddInfo.OnPackageAddProgress = () =>\n                {\n                    OnPackageAddProgress?.Invoke();\n                };\n                packageAddInfo.OnPackageAddComplete = () =>\n                {\n                    NotifyBuildProfileExtensionOfCreation(packageAddInfo.preconfiguredSettingsVariant);\n                };\n                packageAddInfo.RequestPackageInstallation();\n            }\n\n            if (!EditorUserBuildSettings.isBuildProfileAvailable\n                || BuildProfileContext.activeProfile != this)\n                return;\n\n            // On disk changes invoke OnEnable,\n            // Check against the last observed editor defines.\n            string[] lastCompiledDefines = BuildProfileContext.instance.cachedEditorScriptingDefines;\n            if (ArrayUtility.ArrayEquals(m_ScriptingDefines, lastCompiledDefines))\n            {\n                return;\n            }\n            BuildProfileContext.instance.cachedEditorScriptingDefines = m_ScriptingDefines;\n            BuildProfileModuleUtil.RequestScriptCompilation(this);\n        }\n\n        void TryLoadGraphicsSettings()\n        {\n            if (graphicsSettings != null)\n                return;\n\n            var path = AssetDatabase.GetAssetPath(this);\n            var objects = AssetDatabase.LoadAllAssetsAtPath(path);\n\n            var data = Array.Find(objects, obj => obj is BuildProfileGraphicsSettings) as BuildProfileGraphicsSettings;\n            if (data == null)\n                return;\n\n            graphicsSettings = data;\n        }\n\n        void TryLoadQualitySettings()\n        {\n            if (qualitySettings != null)\n                return;\n\n            var path = AssetDatabase.GetAssetPath(this);\n            var objects = AssetDatabase.LoadAllAssetsAtPath(path);\n\n            var data = Array.Find(objects, obj => obj is BuildProfileQualitySettings) as BuildProfileQualitySettings;\n            if (data == null)\n                return;\n\n            qualitySettings = data;\n        }\n\n        void OnDisable()\n        {\n            if (IsActiveBuildProfileOrPlatform())\n                EditorUserBuildSettings.SetActiveProfileScriptingDefines(m_ScriptingDefines);\n\n            var playerSettingsDirty = EditorUtility.IsDirty(m_PlayerSettings);\n            if (playerSettingsDirty)\n            {\n                BuildProfileModuleUtil.SerializePlayerSettings(this);\n                EditorUtility.SetDirty(this);\n            }\n\n            // OnDisable is called when entering play mode, during domain reloads, or when the object is destroyed.\n            // Avoid removing player settings for the first two cases to prevent slow syncs (e.g., color space) caused by global manager updates.\n            if (!EditorApplication.isUpdating)\n            {\n                RemovePlayerSettings();\n            }\n        }\n\n        [MenuItem(\"CONTEXT/BuildProfile/Reset\", false)]\n        static void ContextMenuReset(MenuCommand menuCommand)\n        {\n            var targetBuildProfile = (BuildProfile) menuCommand.context;\n            if (targetBuildProfile == null)\n                return;\n\n            targetBuildProfile.platformBuildProfile = null;\n            targetBuildProfile.TryCreatePlatformSettings();\n            targetBuildProfile.overrideGlobalScenes = false;\n            targetBuildProfile.scenes = Array.Empty<EditorBuildSettingsScene>();\n            targetBuildProfile.scriptingDefines = Array.Empty<string>();\n\n            BuildProfileModuleUtil.RemovePlayerSettings(targetBuildProfile);\n            targetBuildProfile.RemoveQualitySettings();\n            targetBuildProfile.RemoveGraphicsSettings();\n\n            AssetDatabase.SaveAssetIfDirty(targetBuildProfile);\n        }\n\n        void ValidateDataConsistency()\n        {\n            // Keep serialized platform GUID in sync with serialized build target and subtarget.\n            if (platformGuid.Empty())\n            {\n                platformGuid = BuildProfileContext.IsSharedProfile(buildTarget) ?\n                    new GUID(string.Empty) : BuildProfileModuleUtil.GetPlatformId(buildTarget, subtarget);\n                EditorUtility.SetDirty(this);\n            }\n            else\n            {\n                var (curBuildTarget, curSubtarget) = BuildProfileModuleUtil.GetBuildTargetAndSubtarget(platformGuid);\n                if (buildTarget != curBuildTarget || subtarget != curSubtarget)\n                {\n                    buildTarget = curBuildTarget;\n                    subtarget = curSubtarget;\n                    EditorUtility.SetDirty(this);\n                }\n            }\n\n            CheckSceneListConsistency();\n\n            // On disk changes to active profile may change platform guid.\n            // Specifically copying the entire YAML of a valid build profile.\n            if (this == BuildProfileContext.activeProfile && platformGuid != EditorUserBuildSettings.activePlatformGuid)\n            {\n                EditorUserBuildSettings.SwitchActiveBuildTargetGuid(this);\n            }\n        }\n\n        /// <summary>\n        /// EditorBuildSettingsScene stores both path and GUID. Path can become\n        /// invalid when scenes are moved or renamed and must be recalculated.\n        /// </summary>\n        /// <see cref=\"EditorBuildSettings\"/> native function, EnsureScenesAreValid.\n        void CheckSceneListConsistency()\n        {\n            int length = m_Scenes.Length;\n            for (int i = length - 1; i >= 0; i--)\n            {\n                var scene = m_Scenes[i];\n\n                // EditorBuildSettingScene entry may be null.\n                if (scene == null)\n                {\n                    RemoveAt(i);\n                    continue;\n                }\n\n                bool isGuidValid = !scene.guid.Empty();\n                if (isGuidValid)\n                {\n                    // Scene may have been moved or renamed.\n                    scene.path = AssetDatabase.GUIDToAssetPath(scene.guid);\n                }\n\n\n                // Asset may have been deleted.\n                // AssetDatabase may cache GUID to/from path mapping.\n                if (string.IsNullOrEmpty(scene.path) || !AssetDatabase.AssetPathExists(scene.path))\n                {\n                    // Scene Object may have been deleted from disk.\n                    RemoveAt(i);\n                    continue;\n                }\n\n                if (!isGuidValid)\n                    scene.guid = AssetDatabase.GUIDFromAssetPath(scene.path);\n            }\n\n            if (length == m_Scenes.Length)\n                return;\n\n            var result = new EditorBuildSettingsScene[length];\n            Array.Copy(m_Scenes, result, length);\n            m_Scenes = result;\n            EditorUtility.SetDirty(this);\n            return;\n\n            void RemoveAt(int index)\n            {\n                length--;\n                Array.Copy(m_Scenes, index + 1, m_Scenes, index, length - index);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfileAPI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor.Build.Profile\n{\n    public sealed partial class BuildProfile\n    {\n        /// <summary>\n        /// Gets the active build profile.\n        /// </summary>\n        /// <returns>\n        /// The active build profile. Returns null when a classic platform is active.\n        /// </returns>\n        public static BuildProfile GetActiveBuildProfile()\n        {\n            return BuildProfileContext.activeProfile;\n        }\n\n        /// <summary>\n        /// Sets the active build profile.\n        /// </summary>\n        /// <param name=\"buildProfile\">\n        /// The build profile to be set as the active build profile.\n        /// When the value is null, Unity sets the classic platform as active.\n        /// </param>\n        public static void SetActiveBuildProfile(BuildProfile buildProfile)\n        {\n            BuildProfileContext.activeProfile = buildProfile;\n\n            if (buildProfile == null)\n                return;\n\n            BuildProfileModuleUtil.SwitchLegacyActiveFromBuildProfile(buildProfile);\n        }\n\n        /// <summary>\n        /// Gets a component of type T associated with the build profile, its global fallback,\n        /// or null if the component is not available.\n        /// </summary>\n        public T GetComponent<T>() where T : class\n        {\n            if (typeof(T) == typeof(PlayerSettings))\n            {\n                if (m_PlayerSettings != null)\n                    return m_PlayerSettings as T;\n                return s_GlobalPlayerSettings as T;\n            }\n\n            return null;\n        }\n\n        /// <summary>\n        /// Gets a component of type T associated with the currently active build profile,\n        /// its global fallback, or null if the component is not available.\n        /// </summary>\n        public static T GetActiveComponent<T>() where T : class\n        {\n            var buildProfile = GetActiveBuildProfile();\n            if (buildProfile == null)\n            {\n                if (typeof(T) == typeof(PlayerSettings))\n                    return s_GlobalPlayerSettings as T;\n            }\n            else\n            {\n                return buildProfile.GetComponent<T>();\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfileCLI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Build.Profile\n{\n    internal static class BuildProfileCLI\n    {\n        [RequiredByNativeCode]\n        static void BuildActiveProfileWithPath(string locationPathName)\n        {\n            var options = new BuildPlayerWithProfileOptions()\n            {\n                buildProfile = BuildProfile.GetActiveBuildProfile(),\n                locationPathName = locationPathName,\n                options = BuildOptions.None\n            };\n\n            BuildPipeline.BuildPlayer(options);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfileContext.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing JetBrains.Annotations;\nusing UnityEditor.Modules;\nusing UnityEditor.Rendering;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Build.Profile\n{\n    /// <summary>\n    /// Caches build workflow metadata for the current project.\n    /// Handles management of required platform build profiles and implements\n    /// native bindings for mapping migrated settings to backing profile.\n    /// </summary>\n    [InitializeOnLoad]\n    [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n    internal sealed class BuildProfileContext : ScriptableObject\n    {\n        const string k_BuildProfileProviderAssetPath = \"Library/BuildProfileContext.asset\";\n        const string k_BuildProfilePath = \"Library/BuildProfiles\";\n        const string k_SharedProfilePath = $\"{k_BuildProfilePath}/SharedProfile.asset\";\n        static BuildProfileContext s_Instance;\n\n        [SerializeField]\n        string[] m_CachedEditorScriptingDefines = Array.Empty<string>();\n\n        [SerializeField]\n        List<string> m_LastRunnableBuildPathKeys = new();\n        internal List<string> LastRunnableBuildPathKeys => m_LastRunnableBuildPathKeys;\n\n        /// <summary>\n        /// Cached mapping of platform ID to classic platform build profile.\n        /// </summary>\n        Dictionary<GUID, BuildProfile> m_PlatformIdToClassicPlatformProfile = new();\n\n        /// <summary>\n        /// Cached editor scripting defines for the active profile.\n        /// On disk changes to build profile asset, cached value is referenced\n        /// when determining if a recompilation is required.\n        /// </summary>\n        [VisibleToOtherModules]\n        internal string[] cachedEditorScriptingDefines\n        {\n            get => m_CachedEditorScriptingDefines;\n            set => m_CachedEditorScriptingDefines = value;\n        }\n\n        /// <summary>\n        /// Specifies the custom build profile used by the build pipeline and editor APIs when getting build settings.\n        /// </summary>\n        /// <remarks>\n        /// Classic platforms, while build profiles in code, are not managed by the AssetDatabase and implement complex\n        /// shared setting behaviour that is not compatible with the new build profile workflow. From the end users\n        /// perspective Classic Platform and Build Profiles are different concepts.\n        /// </remarks>\n        [VisibleToOtherModules]\n        internal static BuildProfile activeProfile\n        {\n            get\n            {\n                return EditorUserBuildSettings.activeBuildProfile;\n            }\n\n            set\n            {\n                var prev = EditorUserBuildSettings.activeBuildProfile;\n\n                if (value == null || value.platformBuildProfile == null)\n                {\n                    prev?.UpdateGlobalManagerPlayerSettings(activeWillBeRemoved: true);\n                    EditorUserBuildSettings.activeBuildProfile = null;\n\n                    activeProfileChanged?.Invoke(prev, null);\n                    OnActiveProfileChangedForSettingExtension(prev, null);\n                    EditorGraphicsSettings.activeProfileHasGraphicsSettings = false;\n                    BuildProfileModuleUtil.RequestScriptCompilation(null);\n                    return;\n                }\n\n                // Only compare prev with value after the null check, as\n                // EditorUserBuildSettings.activeBuildProfile will return null\n                // if the build profile has been destroyed but on native side\n                // it's still pointing to a dead pptr.\n                if (ReferenceEquals(prev, value))\n                    return;\n\n                if (s_Instance != null && s_Instance.m_PlatformIdToClassicPlatformProfile.TryGetValue(\n                    value.platformGuid, out var entry) && entry == value)\n                {\n                    Debug.LogWarning(\"[BuildProfile] Classic Platforms cannot be set as the active build profile.\");\n                    return;\n                }\n\n                EditorUserBuildSettings.activeBuildProfile = value;\n\n                OnActiveProfileChangedForSettingExtension(prev, value);\n                value.UpdateGlobalManagerPlayerSettings();\n                activeProfileChanged?.Invoke(prev, value);\n                EditorGraphicsSettings.activeProfileHasGraphicsSettings = ActiveProfileHasGraphicsSettings();\n                BuildProfileModuleUtil.RequestScriptCompilation(value);\n            }\n        }\n\n        [SerializeField]\n        List<BuildProfilePackageAddInfo> m_PackageAddInfos = new();\n\n        [VisibleToOtherModules]\n        internal bool TryGetPackageAddInfo(BuildProfile profile, out BuildProfilePackageAddInfo result)\n        {\n            var profileGuid = GetProfileGUID(profile);\n            foreach (var packageAddInfo in m_PackageAddInfos)\n            {\n                if (packageAddInfo.profileGuid == profileGuid)\n                {\n                    result = packageAddInfo;\n                    return true;\n                }\n            }\n            result = null;\n            return false;\n        }\n\n        [VisibleToOtherModules]\n        internal void AddPackageAddInfo(BuildProfile profile, string[] packagesToAdd, int preconfiguredSettingsVariant)\n        {\n            if ((packagesToAdd.Length == 0) && (preconfiguredSettingsVariant == BuildProfilePackageAddInfo.preconfiguredSettingsVariantNotSet))\n                return;\n\n            var profileGuid = GetProfileGUID(profile);\n            var packageAddInfo = new BuildProfilePackageAddInfo()\n            {\n                profileGuid = profileGuid,\n                packagesToAdd = packagesToAdd,\n                preconfiguredSettingsVariant = preconfiguredSettingsVariant\n            };\n            m_PackageAddInfos.Add(packageAddInfo);\n        }\n\n        [VisibleToOtherModules]\n        internal void ClearPackageAddInfo(BuildProfile profile)\n        {\n            if (TryGetPackageAddInfo(profile, out BuildProfilePackageAddInfo packageAddInfo))\n            {\n                m_PackageAddInfos.Remove(packageAddInfo);\n            }\n        }\n\n        static string GetProfileGUID(BuildProfile profile)\n        {\n            var profilePath = AssetDatabase.GetAssetPath(profile);\n            var profileGuid = AssetDatabase.AssetPathToGUID(profilePath);\n            return profileGuid;\n        }\n\n        static void OnActiveProfileChangedForSettingExtension(BuildProfile previous, BuildProfile newProfile)\n        {\n            var settingsExtension = ModuleManager.GetEditorSettingsExtension(EditorUserBuildSettings.activePlatformGuid);\n            settingsExtension?.OnActiveProfileChanged(previous, newProfile);\n        }\n\n        internal static void HandlePendingChangesBeforeEnterPlaymode()\n        {\n            if (!EditorUserBuildSettings.isBuildProfileAvailable)\n                return;\n\n            var defines = BuildDefines.GetBuildProfileScriptDefines();\n            if (!ArrayUtility.ArrayEquals(defines, instance.cachedEditorScriptingDefines))\n            {\n                instance.cachedEditorScriptingDefines = defines;\n                PlayerSettings.RecompileScripts(\"Build profile has been modified.\");\n            }\n        }\n\n        /// <summary>\n        /// Callback invoked when the active build profile has been changed to a new value.\n        /// </summary>\n        /// <see cref=\"activeProfile\"/>\n        /// <remarks>\n        /// Callback passes a value to the previously active Build Profile. A <i>null</i> value\n        /// indicates there's no active profile (set or unset).\n        /// <code>\n        /// activeProfileChanged += (BuildProfile prev, BuildProfile cur) => {}\n        /// </code>\n        /// </remarks>\n        public static event Action<BuildProfile, BuildProfile> activeProfileChanged;\n\n        /// <summary>\n        /// Stores metadata required for Build Profile window and legacy APIs\n        /// as part of the Library folder.\n        /// </summary>\n        [UsedImplicitly]\n        internal static BuildProfileContext instance\n        {\n            [VisibleToOtherModules]\n            get\n            {\n                if (s_Instance == null)\n                {\n                    CreateOrLoad();\n                }\n\n                return s_Instance;\n            }\n        }\n\n        // Note: this has to be a serializable type such as List<T>, so that\n        // the references to classic build profiles survive domain reloads\n        internal List<BuildProfile> classicPlatformProfiles\n        {\n            [VisibleToOtherModules]\n            get;\n            private set;\n        }\n\n        /// <summary>\n        /// A hidden build profile for syncing shared settings for backwards compatibility.\n        /// </summary>\n        internal BuildProfile sharedProfile\n        {\n            get;\n            private set;\n        }\n\n        static BuildProfileContext()\n        {\n            // Asset operations such as asset loading should be avoided in InitializeOnLoad methods.\n            // We delay the creation of the classic platform profiles until the next editor update.\n            EditorApplication.delayCall += () =>\n            {\n                if (s_Instance == null)\n                    CreateOrLoad();\n            };\n        }\n\n        // On domain reload ScriptableObject objects gets reconstructed from a backup. We therefore set the s_Instance here\n        private BuildProfileContext()\n        {\n            if (s_Instance != null)\n            {\n                Debug.LogError(\"BuildProfileContext singleton already exists.\");\n            }\n            else\n            {\n                s_Instance = this;\n\n                // this can become null due to DestroyImmediate() or domain reload.\n                System.Diagnostics.Debug.Assert(s_Instance != null);\n            }\n        }\n\n        [RequiredByNativeCode]\n        internal static BuildProfile GetActiveOrClassicBuildProfile(\n            BuildTarget target, StandaloneBuildSubtarget subTarget = StandaloneBuildSubtarget.Default, string sharedSetting = null)\n        {\n            var platformGuid = BuildProfileModuleUtil.GetPlatformId(target, subTarget);\n            if (ShouldReturnActiveProfile(platformGuid, sharedSetting))\n                return activeProfile;\n\n            // For backwards compatibility, getter will look for\n            // the classic platform build profile for the target platform\n            // when no suitable active profile is found.\n            return IsSharedProfile(platformGuid) ? instance.sharedProfile : instance.GetForClassicPlatform(platformGuid);\n        }\n\n        /// <summary>\n        /// This method allows the native code to fetch the development setting from\n        /// build profiles without allocations.\n        /// </summary>\n        /// <remarks>\n        /// This is a workaround for certain allocation-sensitive graphics tests to pass.\n        /// We use return by ref to avoid the allocation that occurs when the return value\n        /// is boxed into a ScriptingObjectPtr.\n        /// </remarks>\n        [RequiredByNativeCode]\n        internal static void GetActiveOrClassicBuildProfileDevelopmentSetting(ref bool value)\n        {\n            var profile = IsSharedSettingEnabledInActiveProfile(\"development\") ?\n                activeProfile : instance.sharedProfile;\n\n            if (profile == null || profile.platformBuildProfile == null)\n                value = false;\n            else\n                value = profile.platformBuildProfile.development;\n        }\n\n        internal static bool TryGetActiveOrClassicPlatformSettingsBase<T>(\n            BuildTarget target, StandaloneBuildSubtarget subTarget, out T result) where T : BuildProfilePlatformSettingsBase\n        {\n            BuildProfile buildProfile = GetActiveOrClassicBuildProfile(target, subTarget);\n            if (buildProfile != null && buildProfile.platformBuildProfile is T platformProfile)\n            {\n                result = platformProfile;\n                return true;\n            }\n\n            result = null;\n            return false;\n        }\n\n        internal BuildProfile GetForClassicPlatform(GUID platformGuid)\n        {\n            return m_PlatformIdToClassicPlatformProfile.GetValueOrDefault(platformGuid);\n        }\n\n        /// <summary>\n        /// Get the classic platform profile for the specified build target and subtarget.\n        /// This is needed because the server team decided to use this\n        /// internal method in their package.\n        /// </summary>\n        [Obsolete(\"Do not use internal APIs from packages.\")]\n        internal BuildProfile GetForClassicPlatform(BuildTarget target, StandaloneBuildSubtarget subtarget)\n        {\n            if (!BuildProfileModuleUtil.IsStandalonePlatform(target))\n                subtarget = StandaloneBuildSubtarget.Default;\n            else if (subtarget == StandaloneBuildSubtarget.Default)\n                subtarget = StandaloneBuildSubtarget.Player;\n\n            var platformId = BuildProfileModuleUtil.GetPlatformId(target, subtarget);\n            return GetForClassicPlatform(platformId);\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n        internal static bool IsClassicPlatformProfile(BuildProfile profile)\n        {\n            if (instance.m_PlatformIdToClassicPlatformProfile.TryGetValue(profile.platformGuid, out var classicProfile))\n            {\n                return classicProfile == profile;\n            }\n\n            return false;\n        }\n\n        /// <summary>\n        /// List of missing platforms modules that are not installed, don't have a classic platform profile,\n        /// and can be shown in the Build Settings window.\n        /// </summary>\n        /// <see cref=\"BuildPlayerWindow.ActiveBuildTargetsGUI\"/>\n        [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n        internal List<GUID> GetMissingKnownPlatformModules()\n        {\n            var missingPlatforms = new List<GUID>();\n            var keys = BuildProfileModuleUtil.FindAllViewablePlatforms();\n            for (var index = 0; index < keys.Count; index++)\n            {\n                var key = keys[index];\n\n                if (m_PlatformIdToClassicPlatformProfile.ContainsKey(key))\n                    continue;\n\n                if (BuildProfileModuleUtil.IsPlatformVisibleInPlatformBrowserOnly(key))\n                    continue;\n\n                // Installed flag, as calculated by BuildPlatform\n                if (BuildProfileModuleUtil.IsModuleInstalled(key))\n                    continue;\n\n                // Some build targets are only compatible with specific OS\n                if (!BuildTargetDiscovery.BuildPlatformIsAvailableOnHostPlatform(key, SystemInfo.operatingSystemFamily))\n                    continue;\n\n                missingPlatforms.Add(key);\n            }\n\n            return missingPlatforms;\n        }\n\n        /// <summary>\n        /// Check if there's an active build profile with player settings\n        /// </summary>\n        static internal bool ProjectHasActiveProfileWithPlayerSettings()\n        {\n            var activeBuildProfile = BuildProfile.GetActiveBuildProfile();\n            return activeBuildProfile?.playerSettings != null;\n        }\n\n        /// <summary>\n        /// Check if the active build profile has graphics settings\n        /// </summary>\n        internal static bool ActiveProfileHasGraphicsSettings()\n        {\n            if (activeProfile == null)\n                return false;\n\n            return activeProfile.graphicsSettings != null;\n        }\n\n        /// <summary>\n        /// Check if the active build profile has quality settings\n        /// </summary>\n        internal static bool ActiveProfileHasQualitySettings()\n        {\n            if (activeProfile == null)\n                return false;\n\n            return activeProfile.qualitySettings != null;\n        }\n\n        /// <summary>\n        /// Sync the active build profile to EditorUserBuildSettings to ensure they are in a consistent state.\n        /// </summary>\n        void SyncActiveProfileToFallback()\n        {\n            if (!EditorUserBuildSettings.isBuildProfileAvailable)\n                return;\n\n            var buildProfile = activeProfile ?? GetForClassicPlatform(EditorUserBuildSettings.activePlatformGuid);\n\n            if (buildProfile == null)\n            {\n                EditorUserBuildSettings.isBuildProfileAvailable = false;\n                return;\n            }\n\n            EditorUserBuildSettings.CopyFromBuildProfile(buildProfile);\n\n            var extension = ModuleManager.GetBuildProfileExtension(buildProfile.platformGuid);\n            if (extension != null)\n            {\n                extension.CopyPlatformSettingsFromBuildProfile(buildProfile.platformBuildProfile);\n            }\n\n            EditorUserBuildSettings.isBuildProfileAvailable = false;\n        }\n\n        void OnDisable()\n        {\n            Save();\n\n            // Platform profiles must be manually serialized for changes to persist.\n            foreach (var kvp in m_PlatformIdToClassicPlatformProfile)\n            {\n                SaveBuildProfileInProject(kvp.Value);\n            }\n\n            if (sharedProfile != null)\n                SaveBuildProfileInProject(sharedProfile);\n\n            SyncActiveProfileToFallback();\n\n            EditorApplication.quitting -= SyncActiveProfileToFallback;\n        }\n\n        void OnEnable()\n        {\n            EditorUserBuildSettings.isBuildProfileAvailable = true;\n            EditorApplication.quitting -= SyncActiveProfileToFallback;\n            EditorApplication.quitting += SyncActiveProfileToFallback;\n\n            if (classicPlatformProfiles == null)\n                classicPlatformProfiles = new List<BuildProfile>();\n\n            if (classicPlatformProfiles.Count > 0)\n            {\n                // classicPlatformProfiles survived the domain reload - just readd them to the classic profile map\n                foreach (var profileObj in classicPlatformProfiles)\n                    m_PlatformIdToClassicPlatformProfile.Add(profileObj.platformGuid, profileObj);\n            }\n\n            // Load platform build profiles from the Library folder.\n            if (!Directory.Exists(k_BuildProfilePath))\n                return;\n\n            var viewablePlatformKeys = BuildProfileModuleUtil.FindAllViewablePlatforms();\n            for (var index = 0; index < viewablePlatformKeys.Count; index++)\n            {\n                var key = viewablePlatformKeys[index];\n\n                if (m_PlatformIdToClassicPlatformProfile.ContainsKey(key))\n                    continue;\n\n                if (!BuildProfileModuleUtil.IsModuleInstalled(key))\n                    continue;\n\n                if (BuildProfileModuleUtil.IsPlatformVisibleInPlatformBrowserOnly(key))\n                    continue;\n\n                string path = GetFilePathForBuildProfile(key);\n\n                if (!File.Exists(path))\n                {\n                    GetOrCreateClassicPlatformBuildProfile(key);\n                    continue;\n                }\n\n                var profile = InternalEditorUtility.LoadSerializedFileAndForget(path);\n                if (profile == null || profile.Length == 0 || profile[0] is not BuildProfile profileObj)\n                {\n                    Debug.LogWarning($\"Failed to load build profile from {path}.\");\n                    continue;\n                }\n\n                m_PlatformIdToClassicPlatformProfile.Add(profileObj.platformGuid, profileObj);\n                classicPlatformProfiles.Add(profileObj);\n            }\n\n            if (sharedProfile == null)\n            {\n                if (!File.Exists(k_SharedProfilePath))\n                    return;\n\n                var sharedProfileArray = InternalEditorUtility.LoadSerializedFileAndForget(k_SharedProfilePath);\n                if (sharedProfileArray == null || sharedProfileArray.Length == 0 || sharedProfileArray[0] is not BuildProfile sharedProfileObj)\n                {\n                    Debug.LogWarning($\"Failed to load shared profile from {k_SharedProfilePath}.\");\n                    return;\n                }\n\n                sharedProfile = sharedProfileObj;\n            }\n\n            EditorGraphicsSettings.activeProfileHasGraphicsSettings = ActiveProfileHasGraphicsSettings();\n\n            var buildProfile = activeProfile;\n\n            if (buildProfile == null)\n            {\n                buildProfile = GetForClassicPlatform(EditorUserBuildSettings.activePlatformGuid);\n\n                // profile can be null if we're in the middle of creating classic profiles\n                if (buildProfile == null)\n                    return;\n\n                // We only copy EditorUserBuildSettings into the build profile for classic platforms as we don't want to modify actual user assets\n                EditorUserBuildSettings.CopyToBuildProfile(buildProfile);\n            }\n\n            var extension = ModuleManager.GetBuildProfileExtension(buildProfile.platformGuid);\n            if (extension != null)\n            {\n                extension.CopyPlatformSettingsToBuildProfile(buildProfile.platformBuildProfile);\n            }\n        }\n\n        /// <summary>\n        /// Creates platform build profiles for all installed and buildable platforms.\n        /// Platforms with sub targets will generate multiple profiles.\n        /// </summary>\n        void CheckInstalledBuildPlatforms()\n        {\n            var viewablePlatformKeys = BuildProfileModuleUtil.FindAllViewablePlatforms();\n            for (var index = 0; index < viewablePlatformKeys.Count; index++)\n            {\n                var key = viewablePlatformKeys[index];\n\n                if (BuildProfileModuleUtil.IsPlatformVisibleInPlatformBrowserOnly(key))\n                    continue;\n\n                if (!BuildProfileModuleUtil.IsModuleInstalled(key))\n                    continue;\n\n                if (ModuleManager.GetBuildProfileExtension(key) == null)\n                {\n                    // Require platform support and implemented build profile extension for the target platform.\n                    var displayName = BuildTargetDiscovery.BuildPlatformDisplayName(key);\n                    Debug.LogWarning($\"Platform {displayName} does not support build profiles.\");\n                    continue;\n                }\n\n                GetOrCreateClassicPlatformBuildProfile(key);\n            }\n\n            GetOrCreateSharedBuildProfile();\n        }\n\n        BuildProfile GetOrCreateClassicPlatformBuildProfile(GUID platformId)\n        {\n            if (m_PlatformIdToClassicPlatformProfile.TryGetValue(platformId, out var profile) && profile != null)\n            {\n                return profile;\n            }\n\n            // Platform profiles are not managed by the AssetDatabase.\n            // We will manually handle serialization and deserialization of these objects.\n            var buildProfile = BuildProfile.CreateInstance(platformId);\n            buildProfile.hideFlags = HideFlags.DontSave;\n\n            m_PlatformIdToClassicPlatformProfile.Add(platformId, buildProfile);\n            classicPlatformProfiles.Add(buildProfile);\n\n            // Only copy after adding to the platform guid -> classic profiles dictionary, so EditorUserBuildSettings\n            // can access the classic profiles when copying the settings\n            EditorUserBuildSettings.CopyToBuildProfile(buildProfile);\n\n            // Classic profile's shared settings should be populated by the existing shared profile\n            if (sharedProfile != null)\n            {\n                var sharedSettings = sharedProfile.platformBuildProfile as SharedPlatformSettings;\n                sharedSettings?.CopySharedSettingsToBuildProfile(buildProfile);\n            }\n\n            // Created profile can also be populated by settings on the managed side\n            var extension = ModuleManager.GetBuildProfileExtension(buildProfile.platformGuid);\n            if (extension != null)\n            {\n                extension.CopyPlatformSettingsToBuildProfile(buildProfile.platformBuildProfile);\n            }\n            else\n            {\n                var displayName = BuildTargetDiscovery.BuildPlatformDisplayName(buildProfile.platformGuid);\n                Debug.LogError($\"Build profile extension is null for platform {displayName} and build profile {buildProfile.name}.\");\n            }\n\n            return buildProfile;\n        }\n\n        BuildProfile GetOrCreateSharedBuildProfile()\n        {\n            if (sharedProfile != null)\n                return sharedProfile;\n\n            // Shared profile is stored in the Library folder is not managed by the AssetDatabase.\n            // We will manually handle serialization and deserialization of it.\n            var buildProfile = ScriptableObject.CreateInstance<BuildProfile>();\n            buildProfile.buildTarget = BuildTarget.NoTarget;\n            buildProfile.subtarget = StandaloneBuildSubtarget.Default;\n            buildProfile.platformGuid = new GUID(string.Empty);\n            buildProfile.platformBuildProfile = new SharedPlatformSettings();\n            buildProfile.hideFlags = HideFlags.DontSave;\n\n            sharedProfile = buildProfile;\n\n            // Only copy after setting shared profile, so EditorUserBuildSettings can access the shared profile\n            // when copying the settings.\n            EditorUserBuildSettings.CopyToBuildProfile(buildProfile);\n\n            return buildProfile;\n        }\n\n        static void SaveBuildProfileInProject(BuildProfile profile)\n        {\n            if (!Directory.Exists(k_BuildProfilePath))\n            {\n                Directory.CreateDirectory(k_BuildProfilePath);\n            }\n\n            string path = IsSharedProfile(profile.platformGuid) ? k_SharedProfilePath : GetFilePathForBuildProfile(profile.platformGuid);\n            InternalEditorUtility.SaveToSerializedFileAndForget(new []{ profile }, path, allowTextSerialization: true);\n        }\n\n        static void CreateOrLoad()\n        {\n            // LoadSerializedFileAndForget will call non-static BuildProfileContext constructor\n            var buildProfileContext = InternalEditorUtility.LoadSerializedFileAndForget(k_BuildProfileProviderAssetPath);\n            if (buildProfileContext != null && buildProfileContext.Length > 0 && buildProfileContext[0] != null)\n            {\n                s_Instance = buildProfileContext[0] as BuildProfileContext;\n                if (s_Instance == null)\n                    Debug.LogError(\"BuildProfileContext asset exists but could not be loaded.\");\n            }\n            else if (s_Instance == null)\n            {\n                s_Instance = CreateInstance<BuildProfileContext>();\n                s_Instance.hideFlags = HideFlags.DontSave;\n            }\n\n            System.Diagnostics.Debug.Assert(s_Instance != null);\n            s_Instance.CheckInstalledBuildPlatforms();\n\n            s_Instance.cachedEditorScriptingDefines = BuildDefines.GetBuildProfileScriptDefines();\n\n            BuildProfileModuleUtil.DeleteLastRunnableBuildKeyForDeletedProfiles();\n\n            OnActiveProfileChangedForSettingExtension(null, activeProfile);\n        }\n\n        [RequiredByNativeCode, UsedImplicitly]\n        static void SetActiveOrClassicProfileRawPlatformSetting(string settingName, string settingValue, BuildTarget target, StandaloneBuildSubtarget subtarget)\n        {\n            // If it is a shared setting, we will set the value in the active profile if the specified shared setting\n            // is enabled in the active profile; Otherwise, we will set the value in the shared profile.\n            if (IsSharedProfile(target))\n            {\n                var profile = GetActiveOrClassicBuildProfile(target, subtarget, settingName);\n                profile?.platformBuildProfile.SetRawPlatformSetting(settingName, settingValue);\n                return;\n            }\n\n            if (TryGetActiveOrClassicPlatformSettingsBase(target, subtarget, out BuildProfilePlatformSettingsBase platformProfile))\n            {\n                platformProfile.SetRawPlatformSetting(settingName, settingValue);\n            }\n            else if (subtarget != StandaloneBuildSubtarget.Server)\n            {\n                // We shouldn't log a warning if it's the server, since it's possible to not have the server installed and have\n                // the set being called. That's because we double write the setting on native side (for player and server)\n                Debug.LogWarning($\"Can't set {settingName} in build profile. The platform build profile settings is null. Verify that the module for {target} is installed.\");\n            }\n        }\n\n        [RequiredByNativeCode, UsedImplicitly]\n        static void EnsureInitialized()\n        {\n            GC.KeepAlive(instance);\n        }\n\n        [RequiredByNativeCode, UsedImplicitly]\n        static string GetActiveOrClassicProfileRawPlatformSetting(string settingName, BuildTarget target, StandaloneBuildSubtarget subtarget)\n        {\n            // If it is a shared setting, we will return the value from the active profile if the specified shared setting\n            // is enabled in the active profile; Otherwise, we will return the value from the shared profile.\n            if (IsSharedProfile(target))\n            {\n                var profile = GetActiveOrClassicBuildProfile(target, subtarget, settingName);\n                return profile?.platformBuildProfile.GetRawPlatformSetting(settingName) ?? string.Empty;\n            }\n\n            if (TryGetActiveOrClassicPlatformSettingsBase(target, subtarget, out BuildProfilePlatformSettingsBase platformProfile))\n            {\n                string value = platformProfile?.GetRawPlatformSetting(settingName);\n                return value != null ? value : string.Empty;\n            }\n\n            return string.Empty;\n        }\n\n        [RequiredByNativeCode, UsedImplicitly]\n        static bool SetActiveCommonGraphicsSetting(string settingName, int value)\n        {\n            if (!ActiveProfileHasGraphicsSettings())\n                return false;\n\n            activeProfile.graphicsSettings.SetGraphicsSetting(settingName, value);\n            return true;\n        }\n\n        [RequiredByNativeCode, UsedImplicitly]\n        static int GetActiveCommonGraphicsSetting(string settingName)\n        {\n            if (!ActiveProfileHasGraphicsSettings())\n                return BuildProfileGraphicsSettings.k_InvalidGraphicsSetting;\n\n            return activeProfile.graphicsSettings.GetGraphicsSetting(settingName);\n        }\n\n        [RequiredByNativeCode, UsedImplicitly]\n        static bool SetActiveAlwaysIncludedShaders(Shader[] shaders)\n        {\n            if (!ActiveProfileHasGraphicsSettings())\n                return false;\n\n            activeProfile.graphicsSettings.alwaysIncludedShaders = shaders;\n            return true;\n        }\n\n        [RequiredByNativeCode, UsedImplicitly]\n        static Shader[] GetActiveAlwaysIncludedShaders()\n        {\n            if (!ActiveProfileHasGraphicsSettings())\n                return null;\n\n            return activeProfile.graphicsSettings.alwaysIncludedShaders;\n        }\n\n        [RequiredByNativeCode, UsedImplicitly]\n        static ShaderVariantCollection[] GetActiveShaderVariantCollections()\n        {\n            if (!ActiveProfileHasGraphicsSettings())\n                return null;\n\n            return activeProfile?.graphicsSettings.preloadedShaders;\n        }\n\n        [RequiredByNativeCode, UsedImplicitly]\n        static bool SetActiveShaderVariantCollections(ShaderVariantCollection[] collection)\n        {\n            if (!ActiveProfileHasGraphicsSettings())\n                return false;\n\n            activeProfile.graphicsSettings.preloadedShaders = collection;\n            return true;\n        }\n\n        [RequiredByNativeCode, UsedImplicitly]\n        static string[] GetActiveProfileQualityLevels()\n        {\n            if (!ActiveProfileHasQualitySettings())\n                return Array.Empty<string>();\n\n            return activeProfile.qualitySettings.qualityLevels;\n        }\n\n        [RequiredByNativeCode, UsedImplicitly]\n        static string GetActiveProfileDefaultQualityLevel()\n        {\n            if (!ActiveProfileHasQualitySettings())\n                return string.Empty;\n\n            return activeProfile.qualitySettings.defaultQualityLevel;\n        }\n\n        [RequiredByNativeCode]\n        static string GetActiveBuildProfilePath()\n        {\n            if (activeProfile)\n                return AssetDatabase.GetAssetPath(activeProfile);\n\n            return string.Empty;\n        }\n\n        [RequiredByNativeCode]\n        static bool HasActiveProfileWithPlayerSettings(out int instanceID)\n        {\n            if (activeProfile?.playerSettings != null)\n            {\n                instanceID = activeProfile.GetInstanceID();\n                return true;\n            }\n\n            instanceID = 0;\n            return false;\n        }\n\n        [RequiredByNativeCode]\n        static void UpdateActiveProfilePlayerSettingsObjectFromYAML()\n        {\n            activeProfile?.UpdatePlayerSettingsObjectFromYAML();\n        }\n\n        [RequiredByNativeCode]\n        static void SerializeActiveProfilePlayerSettings()\n        {\n            var profile = EditorUserBuildSettings.activeBuildProfile;\n            if (profile == null)\n                return;\n\n            if (!EditorUtility.IsDirty(profile.playerSettings))\n                return;\n\n            profile.SerializePlayerSettings();\n        }\n\n\n        static bool ShouldReturnActiveProfile(GUID platformGuid, string sharedSetting = null)\n        {\n            if (!string.IsNullOrEmpty(sharedSetting))\n                return IsSharedSettingEnabledInActiveProfile(sharedSetting);\n\n            if (activeProfile == null || platformGuid.Empty())\n                return false;\n\n            return platformGuid == activeProfile.platformGuid;\n        }\n\n        static bool IsSharedSettingEnabledInActiveProfile(string settingName)\n        {\n            if (activeProfile == null)\n                return false;\n\n            var platformSettingsBase = activeProfile.platformBuildProfile;\n            if (platformSettingsBase == null)\n                return false;\n\n            return platformSettingsBase.IsSharedSettingEnabled(settingName);\n        }\n\n        static string GetFilePathForBuildProfile(GUID platformId) =>\n            $\"{k_BuildProfilePath}/PlatformProfile.{platformId}.asset\";\n\n        static void Save() => InternalEditorUtility.SaveToSerializedFileAndForget(new[] { instance },\n            k_BuildProfileProviderAssetPath, true);\n\n        [VisibleToOtherModules]\n        internal static bool IsSharedProfile(BuildTarget target) => target == BuildTarget.NoTarget;\n\n        [VisibleToOtherModules]\n        internal static bool IsSharedProfile(GUID platformGuid) => platformGuid.Empty();\n\n        internal static void UpdateScriptingDefineSymbolsInActivePlayerSettingsOverride(NamedBuildTarget buildTarget, string defines)\n        {\n            var profile = activeProfile;\n\n            if (profile == null)\n                return;\n\n            if (profile.playerSettings == null)\n                return;\n\n            PlayerSettings.SetScriptingDefineSymbols_Internal(profile.playerSettings, buildTarget.TargetName, defines);\n            profile.SerializePlayerSettings();\n            EditorUtility.SetDirty(profile);\n            AssetDatabase.SaveAssetIfDirty(profile);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfileCreate.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing JetBrains.Annotations;\nusing UnityEditor.Modules;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor.Build.Profile\n{\n    public sealed partial class BuildProfile\n    {\n        [UsedImplicitly]\n        internal static event Action<BuildProfile> onBuildProfileEnable;\n        [VisibleToOtherModules]\n        internal static void AddOnBuildProfileEnable(Action<BuildProfile> action) => onBuildProfileEnable += action;\n        [VisibleToOtherModules]\n        internal static void RemoveOnBuildProfileEnable(Action<BuildProfile> action) => onBuildProfileEnable -= action;\n\n        // This callback is of use when a build profile is created via AssetDatabase, and we need to notify the UI\n        // and select the newly created profile in the listview.\n        [UsedImplicitly]\n        internal static event Action<BuildProfile> onBuildProfileCreated;\n        [VisibleToOtherModules]\n        internal static void AddOnBuildProfileCreated(Action<BuildProfile> action) => onBuildProfileCreated += action;\n        [VisibleToOtherModules]\n        internal static void RemoveOnBuildProfileCreated(Action<BuildProfile> action) => onBuildProfileCreated -= action;\n\n        internal static BuildProfile CreateInstance(BuildTarget buildTarget, StandaloneBuildSubtarget subtarget)\n        {\n            var platformGuid = BuildProfileModuleUtil.GetPlatformId(buildTarget, subtarget);\n            ValidatePlatform(platformGuid);\n\n            var buildProfile = CreateInstance<BuildProfile>();\n            buildProfile.buildTarget = buildTarget;\n            buildProfile.subtarget = subtarget;\n            buildProfile.platformGuid = platformGuid;\n            buildProfile.OnEnable();\n            return buildProfile;\n        }\n\n        internal static BuildProfile CreateInstance(GUID platformId)\n        {\n            ValidatePlatform(platformId);\n\n            var (buildTarget, subtarget) = BuildProfileModuleUtil.GetBuildTargetAndSubtarget(platformId);\n            var buildProfile = CreateInstance<BuildProfile>();\n            buildProfile.buildTarget = buildTarget;\n            buildProfile.subtarget = subtarget;\n            buildProfile.platformGuid = platformId;\n            buildProfile.OnEnable();\n            return buildProfile;\n        }\n\n        /// <summary>\n        /// Internal helper function for creating new build profile assets and invoking the onBuildProfileCreated\n        /// event after an asset is created by AssetDatabase.CreateAsset.\n        /// </summary>\n        [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n        internal static void CreateInstance(GUID platformId, string assetPath)\n        {\n            CreateInstance(platformId, assetPath, -1, Array.Empty<string>());\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n        internal static void CreateInstance(GUID platformId, string assetPath, int preconfiguredSettingsVariant, string[] packagesToAdd)\n        {\n            ValidateFileNameLength(assetPath);\n            ValidatePlatform(platformId);\n\n            var (buildTarget, subtarget) = BuildProfileModuleUtil.GetBuildTargetAndSubtarget(platformId);\n            var buildProfile = CreateInstance<BuildProfile>();\n            buildProfile.buildTarget = buildTarget;\n            buildProfile.subtarget = subtarget;\n            buildProfile.platformGuid = platformId;\n            AssetDatabase.CreateAsset(\n                buildProfile,\n                AssetDatabase.GenerateUniqueAssetPath(assetPath));\n            BuildProfileContext.instance.AddPackageAddInfo(buildProfile, packagesToAdd, preconfiguredSettingsVariant);\n            buildProfile.OnEnable();\n            // Notify the UI of creation so that the new build profile can be selected\n            onBuildProfileCreated?.Invoke(buildProfile);\n        }\n\n        /// <summary>\n        /// Validates if the provided platform GUID is valid by checking against all supported platforms.\n        /// Throws an ArgumentException if the platform is not valid.\n        /// </summary>\n        /// <param name=\"platformGuid\">The GUID of the platform to validate.</param>\n        static void ValidatePlatform(GUID platformGuid)\n        {\n            foreach (var guid in BuildTargetDiscovery.GetAllPlatforms())\n            {\n                if (guid == platformGuid)\n                    return;\n            }\n\n            throw new ArgumentException(\"A build profile must be created for a valid platform.\");\n        }\n\n        /// <summary>\n        /// Validates if the provided path name length is supported by the Asset database.\n        /// Throws an ArgumentException if the platform is not valid.\n        /// </summary>\n        /// <param name=\"assetPath\">The path to the build profile to be created.</param>\n        static void ValidateFileNameLength(string assetPath)\n        {\n            // File name length is limited by the asset database\n            if (Path.GetFileName(assetPath).Length > BuildProfileModuleUtil.k_MaxAssetFileNameLength)\n                throw new ArgumentException($\"Build profile name is too long ({Path.GetFileName(assetPath).Length}) - max supported is {BuildProfileModuleUtil.k_MaxAssetFileNameLength}\");\n        }\n\n        internal void NotifyBuildProfileExtensionOfCreation(int preconfiguredSettingsVariant)\n        {\n            var buildProfileExtension = BuildProfileModuleUtil.GetBuildProfileExtension(platformGuid);\n            if (buildProfileExtension != null)\n            {\n                buildProfileExtension.OnBuildProfileCreated(this, preconfiguredSettingsVariant);\n                SerializePlayerSettings();\n                AssetDatabase.SaveAssetIfDirty(this);\n            }\n            BuildProfileContext.instance.ClearPackageAddInfo(this);\n        }\n\n        void TryCreatePlatformSettings()\n        {\n            if (platformBuildProfile != null)\n            {\n                Debug.LogError(\"[BuildProfile] Platform settings already created.\");\n                return;\n            }\n\n            IBuildProfileExtension buildProfileExtension = ModuleManager.GetBuildProfileExtension(platformGuid);\n            if (buildProfileExtension != null && ModuleManager.IsPlatformSupportLoadedByGuid(platformGuid))\n            {\n                platformBuildProfile = buildProfileExtension.CreateBuildProfilePlatformSettings();\n                EditorUtility.SetDirty(this);\n            }\n        }\n\n        /// <summary>\n        /// Add Graphics Settings overrides to the build profile.\n        /// </summary>\n        internal void CreateGraphicsSettings()\n        {\n            if (graphicsSettings != null)\n                return;\n\n            graphicsSettings = CreateInstance<BuildProfileGraphicsSettings>();\n            graphicsSettings.Instantiate();\n            AssetDatabase.AddObjectToAsset(graphicsSettings, this);\n            EditorUtility.SetDirty(this);\n        }\n\n        /// <summary>\n        /// Remove the Graphics Settings overrides from the build profile.\n        /// </summary>\n        internal void RemoveGraphicsSettings()\n        {\n            if (graphicsSettings == null)\n                return;\n\n            AssetDatabase.RemoveObjectFromAsset(graphicsSettings);\n            graphicsSettings = null;\n            EditorUtility.SetDirty(this);\n\n            OnGraphicsSettingsSubAssetRemoved?.Invoke();\n        }\n\n        /// <summary>\n        /// Add Quality Settings overrides to the build profile.\n        /// </summary>\n        internal void CreateQualitySettings()\n        {\n            if (qualitySettings != null)\n                return;\n\n            qualitySettings = ScriptableObject.CreateInstance<BuildProfileQualitySettings>();\n            qualitySettings.Instantiate();\n            AssetDatabase.AddObjectToAsset(qualitySettings, this);\n            EditorUtility.SetDirty(this);\n        }\n\n        /// <summary>\n        /// Remove the Quality Settings overrides from the build profile.\n        /// </summary>\n        internal void RemoveQualitySettings()\n        {\n            if (qualitySettings == null)\n                return;\n\n            AssetDatabase.RemoveObjectFromAsset(qualitySettings);\n            qualitySettings = null;\n            EditorUtility.SetDirty(this);\n\n            OnQualitySettingsSubAssetRemoved?.Invoke();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfileGraphicsSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Rendering;\nusing UnityEditor.Rendering;\n\nnamespace UnityEditor.Build.Profile\n{\n    [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n    sealed class BuildProfileGraphicsSettings : ScriptableObject\n    {\n        internal const int k_InvalidGraphicsSetting = -2;\n\n        [SerializeField] StrippingModes m_LightmapStripping = StrippingModes.Automatic;\n        [SerializeField] bool m_LightmapKeepPlain = true;\n        [SerializeField] bool m_LightmapKeepDirCombined = true;\n        [SerializeField] bool m_LightmapKeepDynamicPlain = true;\n        [SerializeField] bool m_LightmapKeepDynamicDirCombined = true;\n        [SerializeField] bool m_LightmapKeepShadowMask = true;\n        [SerializeField] bool m_LightmapKeepSubtractive = true;\n        [SerializeField] StrippingModes m_FogStripping = StrippingModes.Automatic;\n        [SerializeField] bool m_FogKeepLinear = true;\n        [SerializeField] bool m_FogKeepExp = true;\n        [SerializeField] bool m_FogKeepExp2 = true;\n        [SerializeField] InstancingStrippingMode m_InstancingStripping = InstancingStrippingMode.StripUnused;\n        [SerializeField] BatchRendererGroupStrippingMode m_BrgStripping = BatchRendererGroupStrippingMode.KeepIfEntitiesGraphics;\n        [SerializeField] bool m_LogWhenShaderIsCompiled = false;\n        [SerializeField] bool m_CameraRelativeLightCulling = false;\n        [SerializeField] bool m_CameraRelativeShadowCulling = false;\n        [SerializeField] VideoShadersIncludeMode m_VideoShadersIncludeMode = VideoShadersIncludeMode.Always;\n        [SerializeField] Shader[] m_AlwaysIncludedShaders = Array.Empty<Shader>();\n        [SerializeField] LightProbeOutsideHullStrategy m_LightProbeOutsideHullStrategy = LightProbeOutsideHullStrategy.kLightProbeSearchTetrahedralHull;\n        [SerializeField] ShaderVariantCollection[] m_PreloadedShaders = Array.Empty<ShaderVariantCollection>();\n        [SerializeField] int m_PreloadShadersBatchTimeLimit = -1;\n\n        internal StrippingModes lightmapStripping\n        {\n            get => m_LightmapStripping;\n            set => m_LightmapStripping = value;\n        }\n\n        internal bool lightmapKeepPlain\n        {\n            get => m_LightmapKeepPlain;\n            set => m_LightmapKeepPlain = value;\n        }\n\n        internal bool lightmapKeepDirCombined\n        {\n            get => m_LightmapKeepDirCombined;\n            set => m_LightmapKeepDirCombined = value;\n        }\n\n        internal bool lightmapKeepDynamicPlain\n        {\n            get => m_LightmapKeepDynamicPlain;\n            set => m_LightmapKeepDynamicPlain = value;\n        }\n\n        internal bool lightmapKeepDynamicDirCombined\n        {\n            get => m_LightmapKeepDynamicDirCombined;\n            set => m_LightmapKeepDynamicDirCombined = value;\n        }\n\n        internal bool lightmapKeepShadowMask\n        {\n            get => m_LightmapKeepShadowMask;\n            set => m_LightmapKeepShadowMask = value;\n        }\n\n        internal bool lightmapKeepSubtractive\n        {\n            get => m_LightmapKeepSubtractive;\n            set => m_LightmapKeepSubtractive = value;\n        }\n\n        internal StrippingModes fogStripping\n        {\n            get => m_FogStripping;\n            set => m_FogStripping = value;\n        }\n\n        internal bool fogKeepLinear\n        {\n            get => m_FogKeepLinear;\n            set => m_FogKeepLinear = value;\n        }\n\n        internal bool fogKeepExp\n        {\n            get => m_FogKeepExp;\n            set => m_FogKeepExp = value;\n        }\n\n        internal bool fogKeepExp2\n        {\n            get => m_FogKeepExp2;\n            set => m_FogKeepExp2 = value;\n        }\n\n        internal InstancingStrippingMode instancingStripping\n        {\n            get => m_InstancingStripping;\n            set => m_InstancingStripping = value;\n        }\n\n        internal BatchRendererGroupStrippingMode brgStripping\n        {\n            get => m_BrgStripping;\n            set => m_BrgStripping = value;\n        }\n\n        internal bool logWhenShaderIsCompiled\n        {\n            get => m_LogWhenShaderIsCompiled;\n            set => m_LogWhenShaderIsCompiled = value;\n        }\n\n        internal bool cameraRelativeLightCulling\n        {\n            get => m_CameraRelativeLightCulling;\n            set => m_CameraRelativeLightCulling = value;\n        }\n\n        internal bool cameraRelativeShadowCulling\n        {\n            get => m_CameraRelativeShadowCulling;\n            set => m_CameraRelativeShadowCulling = value;\n        }\n\n        internal VideoShadersIncludeMode videoShadersIncludeMode\n        {\n            get => m_VideoShadersIncludeMode;\n            set => m_VideoShadersIncludeMode = value;\n        }\n\n        internal Shader[] alwaysIncludedShaders\n        {\n            get => m_AlwaysIncludedShaders;\n            set => m_AlwaysIncludedShaders = value;\n        }\n\n        internal LightProbeOutsideHullStrategy lightProbeOutsideHullStrategy\n        {\n            get => m_LightProbeOutsideHullStrategy;\n            set => m_LightProbeOutsideHullStrategy = value;\n        }\n\n        internal ShaderVariantCollection[] preloadedShaders\n        {\n            get => m_PreloadedShaders;\n            set => m_PreloadedShaders = value;\n        }\n\n        internal int preloadShadersBatchTimeLimit\n        {\n            get => m_PreloadShadersBatchTimeLimit;\n            set => m_PreloadShadersBatchTimeLimit = value;\n        }\n\n        public void Instantiate()\n        {\n            name = \"Graphics Settings\";\n            hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;\n        }\n\n        public void SetGraphicsSetting(string settingName, int value)\n        {\n            switch (settingName)\n            {\n                case \"LightmapStripping\":\n                    lightmapStripping = (StrippingModes)value;\n                    break;\n                case \"LightmapKeepPlain\":\n                    lightmapKeepPlain = IntegerToBoolean(value);\n                    break;\n                case \"LightmapKeepDirCombined\":\n                    lightmapKeepDirCombined = IntegerToBoolean(value);\n                    break;\n                case \"LightmapKeepDynamicPlain\":\n                    lightmapKeepDynamicPlain = IntegerToBoolean(value);\n                    break;\n                case \"LightmapKeepDynamicDirCombined\":\n                    lightmapKeepDynamicDirCombined = IntegerToBoolean(value);\n                    break;\n                case \"LightmapKeepShadowMask\":\n                    lightmapKeepShadowMask = IntegerToBoolean(value);\n                    break;\n                case \"LightmapKeepSubtractive\":\n                    lightmapKeepSubtractive = IntegerToBoolean(value);\n                    break;\n                case \"FogStripping\":\n                    fogStripping = (StrippingModes)value;\n                    break;\n                case \"FogKeepLinear\":\n                    fogKeepLinear = IntegerToBoolean(value);\n                    break;\n                case \"FogKeepExp\":\n                    fogKeepExp = IntegerToBoolean(value);\n                    break;\n                case \"FogKeepExp2\":\n                    fogKeepExp2 = IntegerToBoolean(value);\n                    break;\n                case \"InstancingStripping\":\n                    instancingStripping = (InstancingStrippingMode)value;\n                    break;\n                case \"BrgStripping\":\n                    brgStripping = (BatchRendererGroupStrippingMode)value;\n                    break;\n                case \"LogWhenShaderIsCompiled\":\n                    logWhenShaderIsCompiled = IntegerToBoolean(value);\n                    break;\n                case \"CameraRelativeLightCulling\":\n                    cameraRelativeLightCulling = IntegerToBoolean(value);\n                    break;\n                case \"CameraRelativeShadowCulling\":\n                    cameraRelativeShadowCulling = IntegerToBoolean(value);\n                    break;\n                case \"VideoShadersIncludeMode\":\n                    videoShadersIncludeMode = (VideoShadersIncludeMode)value;\n                    break;\n                case \"LightProbeOutsideHullStrategy\":\n                    lightProbeOutsideHullStrategy = (LightProbeOutsideHullStrategy)value;\n                    break;\n                case \"PreloadShadersBatchTimeLimit\":\n                    preloadShadersBatchTimeLimit = value;\n                    break;\n            }\n\n            static bool IntegerToBoolean(int value) => value != 0;\n        }\n\n        public int GetGraphicsSetting(string settingName)\n        {\n            return settingName switch\n            {\n                \"LightmapStripping\" => (int)lightmapStripping,\n                \"LightmapKeepPlain\" => BooleanToInteger(lightmapKeepPlain),\n                \"LightmapKeepDirCombined\" => BooleanToInteger(lightmapKeepDirCombined),\n                \"LightmapKeepDynamicPlain\" => BooleanToInteger(lightmapKeepDynamicPlain),\n                \"LightmapKeepDynamicDirCombined\" => BooleanToInteger(lightmapKeepDynamicDirCombined),\n                \"LightmapKeepShadowMask\" => BooleanToInteger(lightmapKeepShadowMask),\n                \"LightmapKeepSubtractive\" => BooleanToInteger(lightmapKeepSubtractive),\n                \"FogStripping\" => (int)fogStripping,\n                \"FogKeepLinear\" => BooleanToInteger(fogKeepLinear),\n                \"FogKeepExp\" => BooleanToInteger(fogKeepExp),\n                \"FogKeepExp2\" => BooleanToInteger(fogKeepExp2),\n                \"InstancingStripping\" => (int)instancingStripping,\n                \"BrgStripping\" => (int)brgStripping,\n                \"LogWhenShaderIsCompiled\" => BooleanToInteger(logWhenShaderIsCompiled),\n                \"CameraRelativeLightCulling\" => BooleanToInteger(cameraRelativeLightCulling),\n                \"CameraRelativeShadowCulling\" => BooleanToInteger(cameraRelativeShadowCulling),\n                \"VideoShadersIncludeMode\" => (int)videoShadersIncludeMode,\n                \"LightProbeOutsideHullStrategy\" => (int)lightProbeOutsideHullStrategy,\n                \"PreloadShadersBatchTimeLimit\" => preloadShadersBatchTimeLimit,\n                _ => k_InvalidGraphicsSetting,\n            };\n\n            static int BooleanToInteger(bool value) => value ? 1 : 0;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfileGraphicsSettingsEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.UIElements;\nusing UnityEngine.Bindings;\nusing UnityEngine.UIElements;\nusing UnityEngine.Rendering;\nusing UnityEngine;\n\nnamespace UnityEditor.Build.Profile\n{\n    [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n    [CustomEditor(typeof(BuildProfileGraphicsSettings))]\n    class BuildProfileGraphicsSettingsEditor : Editor\n    {\n        const string k_Uxml = \"BuildProfile/UXML/BuildProfileCommonGraphicsSettings.uxml\";\n        const string k_StyleSheet = \"BuildProfile/StyleSheets/BuildProfile.uss\";\n        const string k_LastDefaultPropertyPath = \"m_EditorClassIdentifier\";\n\n        public override VisualElement CreateInspectorGUI()\n        {\n            var root = new VisualElement();\n            var visualTree = EditorGUIUtility.LoadRequired(k_Uxml) as VisualTreeAsset;\n            var windowUss = EditorGUIUtility.LoadRequired(k_StyleSheet) as StyleSheet;\n            visualTree.CloneTree(root);\n            root.styleSheets.Add(windowUss);\n\n            root.Bind(serializedObject);\n            root.Query<UIElements.ProjectSettings.ProjectSettingsElementWithSO>()\n                .ForEach(d => d.InitializeWithoutWindow(serializedObject));\n\n            BindEnumFieldWithFadeGroup(root, \"Lightmap\", CalculateLightmapStrippingFromCurrentScene);\n            BindEnumFieldWithFadeGroup(root, \"Fog\", CalculateFogStrippingFromCurrentScene);\n\n            BindShaderPreload(root);\n\n            // Align fields as in the inspector\n            var type = typeof(BaseField<>);\n            root.Query<BindableElement>()\n                .Where(e =>\n                    IsSubclassOfGeneric(type, e.GetType()))\n                .ForEach(e =>\n                    e.EnableInClassList(BaseField<bool>.alignedFieldUssClassName, true));\n\n            return root;\n        }\n\n        void BindEnumFieldWithFadeGroup(VisualElement content, string id, Action buttonCallback)\n        {\n            var enumMode = content.MandatoryQ<EnumField>($\"{id}Modes\");\n            var enumModeGroup = content.MandatoryQ<VisualElement>($\"{id}ModesGroup\");\n            var enumModeProperty = serializedObject.FindProperty($\"m_{id}Stripping\");\n\n            static bool IsModesGroupVisible(StrippingModes mode) => mode == StrippingModes.Custom;\n            UIElementsEditorUtility.SetVisibility(enumModeGroup, IsModesGroupVisible((StrippingModes)enumModeProperty.intValue));\n            var lightmapModesUpdate = UIElementsEditorUtility.BindSerializedProperty<StrippingModes>(enumMode, enumModeProperty,\n                mode => UIElementsEditorUtility.SetVisibility(enumModeGroup, IsModesGroupVisible(mode)));\n            lightmapModesUpdate?.Invoke();\n\n            content.MandatoryQ<Button>($\"Import{id}FromCurrentScene\").clicked += buttonCallback;\n        }\n\n        void BindShaderPreload(VisualElement root)\n        {\n            var shaderPreloadProperty = serializedObject.FindProperty(\"m_PreloadedShaders\");\n            shaderPreloadProperty.isExpanded = false;\n            \n            var delayedShaderTimeLimitProperty = serializedObject.FindProperty(\"m_PreloadShadersBatchTimeLimit\");\n            var shaderPreloadToggle = root.MandatoryQ<Toggle>(\"ShaderPreloadToggle\");\n            var delayedShaderTimeLimitGroup = root.MandatoryQ<VisualElement>(\"DelayedShaderTimeLimitGroup\");\n            var delayedShaderTimeLimit = root.MandatoryQ<IntegerField>(\"DelayedShaderTimeLimit\");\n            shaderPreloadToggle.RegisterValueChangedCallback(evt => {\n                delayedShaderTimeLimitGroup.style.display = evt.newValue ? DisplayStyle.Flex : DisplayStyle.None;\n                var newVal = evt.newValue ? delayedShaderTimeLimit.value : -1;\n                if (delayedShaderTimeLimitProperty.intValue != newVal)\n                {\n                    delayedShaderTimeLimitProperty.intValue = newVal;\n                    delayedShaderTimeLimitProperty.serializedObject.ApplyModifiedProperties();\n                }\n            });\n            delayedShaderTimeLimit.RegisterValueChangedCallback(evt =>\n            {\n                if (delayedShaderTimeLimitProperty.intValue != evt.newValue)\n                {\n                    delayedShaderTimeLimitProperty.intValue = evt.newValue;\n                    delayedShaderTimeLimitProperty.serializedObject.ApplyModifiedProperties();\n                }\n            });\n            shaderPreloadToggle.SetValueWithoutNotify(delayedShaderTimeLimitProperty.intValue >= 0);\n            delayedShaderTimeLimit.SetValueWithoutNotify(Mathf.Max(0, delayedShaderTimeLimitProperty.intValue));\n            delayedShaderTimeLimitGroup.style.display = delayedShaderTimeLimitProperty.intValue >= 0 ? DisplayStyle.Flex : DisplayStyle.None;\n            \n            var shaderTracking = root.MandatoryQ<HelpBox>(\"ShaderTrackingInfoBox\");\n            shaderTracking.schedule.Execute(() =>\n                shaderTracking.text =\n                    $\"Currently tracked: {ShaderUtil.GetCurrentShaderVariantCollectionShaderCount()} shaders {ShaderUtil.GetCurrentShaderVariantCollectionVariantCount()} total variants\").Every(500);\n\n            var saveButton = root.MandatoryQ<Button>(\"SaveShaderVariants\");\n            saveButton.clickable = new Clickable(() =>\n            {\n                var assetPath = EditorUtility.SaveFilePanelInProject(\n                    L10n.Tr(\"Save Shader Variant Collection\"),\n                    \"NewShaderVariants\",\n                    \"shadervariants\",\n                    L10n.Tr(\"Save shader variant collection\"),\n                    ProjectWindowUtil.GetActiveFolderPath());\n                if (!string.IsNullOrEmpty(assetPath))\n                    ShaderUtil.SaveCurrentShaderVariantCollection(assetPath);\n            });\n            var clearButton = root.MandatoryQ<Button>(\"ClearCurrentShaderVariants\");\n            clearButton.clickable = new Clickable(ShaderUtil.ClearCurrentShaderVariantCollection);\n        }\n\n        void CalculateLightmapStrippingFromCurrentScene()\n        {\n            bool lightmapKeepPlain, lightmapKeepDirCombined, lightmapKeepDynamicPlain, lightmapKeepDynamicDirCombined, lightmapKeepShadowMask, lightmapKeepSubtractive;\n            ShaderUtil.CalculateLightmapStrippingFromCurrentSceneForBuildProfile(out lightmapKeepPlain, out lightmapKeepDirCombined,\n                out lightmapKeepDynamicPlain, out lightmapKeepDynamicDirCombined, out lightmapKeepShadowMask, out lightmapKeepSubtractive);\n\n            serializedObject.FindProperty(\"m_LightmapKeepPlain\").boolValue = lightmapKeepPlain;\n            serializedObject.FindProperty(\"m_LightmapKeepDirCombined\").boolValue = lightmapKeepDirCombined;\n            serializedObject.FindProperty(\"m_LightmapKeepDynamicPlain\").boolValue = lightmapKeepDynamicPlain;\n            serializedObject.FindProperty(\"m_LightmapKeepDynamicDirCombined\").boolValue = lightmapKeepDynamicDirCombined;\n            serializedObject.FindProperty(\"m_LightmapKeepShadowMask\").boolValue = lightmapKeepShadowMask;\n            serializedObject.FindProperty(\"m_LightmapKeepSubtractive\").boolValue = lightmapKeepSubtractive;\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        void CalculateFogStrippingFromCurrentScene()\n        {\n            bool fogKeepLinear, fogKeepExp, fogKeepExp2;\n            ShaderUtil.CalculateFogStrippingFromCurrentSceneForBuildProfile(out fogKeepLinear, out fogKeepExp, out fogKeepExp2);\n\n            serializedObject.FindProperty(\"m_FogKeepLinear\").boolValue = fogKeepLinear;\n            serializedObject.FindProperty(\"m_FogKeepExp\").boolValue = fogKeepExp;\n            serializedObject.FindProperty(\"m_FogKeepExp2\").boolValue = fogKeepExp2;\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        static bool IsSubclassOfGeneric(Type genericType, Type typeToCheck) {\n            while (typeToCheck != null && typeToCheck != typeof(object))\n            {\n                var currentType = typeToCheck.IsGenericType ? typeToCheck.GetGenericTypeDefinition() : typeToCheck;\n                if (genericType == currentType)\n                    return true;\n                typeToCheck = typeToCheck.BaseType;\n            }\n            return false;\n        }\n\n        public bool IsDataEqualToGlobalGraphicsSettings()\n        {\n            var globalGraphicsSettings = GraphicsSettings.GetGraphicsSettings();\n            var globalGraphicsSettingsSO = new SerializedObject(globalGraphicsSettings);\n            var profileSerializedProperty = serializedObject.FindProperty(k_LastDefaultPropertyPath);\n\n            while (profileSerializedProperty.Next(false))\n            {\n                var globalSerializedProperty = globalGraphicsSettingsSO.FindProperty(profileSerializedProperty.name);\n                if (profileSerializedProperty.isArray)\n                {\n                    if (profileSerializedProperty.arraySize != globalSerializedProperty.arraySize)\n                        return false;\n\n                    for (int i = 0; i < profileSerializedProperty.arraySize; i++)\n                    {\n                        var profileArrayElement = profileSerializedProperty.GetArrayElementAtIndex(i);\n                        var globalArrayElement = globalSerializedProperty.GetArrayElementAtIndex(i);\n                        if (profileArrayElement.boxedValue != globalArrayElement.boxedValue)\n                            return false;\n                    }\n                }\n                else if (!profileSerializedProperty.boxedValue.Equals(globalSerializedProperty.boxedValue))\n                    return false;\n            }\n\n            return true;\n        }\n\n        public void ResetToGlobalGraphicsSettingsValues()\n        {\n            var globalGraphicsSettings = GraphicsSettings.GetGraphicsSettings();\n            var globalGraphicsSettingsSO = new SerializedObject(globalGraphicsSettings);\n            var profileSerializedProperty = serializedObject.FindProperty(k_LastDefaultPropertyPath);\n\n            while (profileSerializedProperty.Next(false))\n            {\n                var globalSerializedProperty = globalGraphicsSettingsSO.FindProperty(profileSerializedProperty.name);\n                if (profileSerializedProperty.isArray)\n                {\n                    profileSerializedProperty.arraySize = globalSerializedProperty.arraySize;\n                    for (int i = 0; i < profileSerializedProperty.arraySize; i++)\n                    {\n                        var profileArrayElement = profileSerializedProperty.GetArrayElementAtIndex(i);\n                        var globalArrayElement = globalSerializedProperty.GetArrayElementAtIndex(i);\n                        profileArrayElement.boxedValue = globalArrayElement.boxedValue;\n                    }\n                }\n                else\n                    profileSerializedProperty.boxedValue = globalSerializedProperty.boxedValue;\n            }\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfileModuleUtil.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\nusing UnityEditor.Modules;\nusing UnityEditor.PackageManager.UI.Internal;\nusing UnityEditor.Rendering;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Rendering;\nusing UnityEngine.UIElements;\nusing TargetAttributes = UnityEditor.BuildTargetDiscovery.TargetAttributes;\nusing UnityEditor.Profiling;\nusing InternalEditorUtility = UnityEditorInternal.InternalEditorUtility;\n\nnamespace UnityEditor.Build.Profile\n{\n    /// <summary>\n    /// Internal utility class for Build Profile Module.\n    /// </summary>\n    [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n    internal class BuildProfileModuleUtil\n    {\n        const string k_BuyProUrl = \"https://store.unity.com/products/unity-pro\";\n        const string k_ConsoleModuleUrl = \"https://unity3d.com/platform-installation\";\n        const string k_LastRunnableBuildPathSeparator = \"_\";\n        const string k_StyleSheet = \"BuildProfile/StyleSheets/BuildProfile.uss\";\n        // The asset database supports file name length to max. 250 symbols\n        // Leave 3 symbols for the GenerateUniqueAssetPath() that adds \" 1\"(2,3...) in case\n        // an asset with such name already exists.\n        public const int k_MaxAssetFileNameLength = 247;\n        // For UI cases where the extension `.asset` is not taken into consideration\n        public const int k_MaxAssetFileNameLengthWithoutExtension = k_MaxAssetFileNameLength - 6;\n        static readonly string k_NoModuleLoaded = L10n.Tr(\"No {0} module loaded.\");\n        static readonly string k_DerivedPlatformInactive = L10n.Tr(\"{0} is currently disabled.\");\n        static readonly string k_DerivedPlatformDisabled = L10n.Tr(\"{0} was disabled via command-line arguments.\");\n        static readonly string k_EditorWillNeedToBeReloaded = L10n.Tr(\"Note: Editor will need to be restarted to load any newly installed modules\");\n        static readonly string k_BuildProfileRecompileReason = L10n.Tr(\"Active build profile scripting defines changes.\");\n        static readonly GUIContent k_OpenDownloadPage = EditorGUIUtility.TrTextContent(\"Open Download Page\");\n        static readonly GUIContent k_InstallModuleWithHub = EditorGUIUtility.TrTextContent(\"Install with Unity Hub\");\n        static readonly GUIContent k_ActivateDerivedPlatform = EditorGUIUtility.TrTextContent(\"Enable Platform\");\n        static HashSet<string> s_BuildProfileIconModules = new()\n        {\n            \"Switch\",\n        };\n\n        /// <summary>\n        /// Classic platform display name for a given build profile.\n        /// </summary>\n        public static string GetClassicPlatformDisplayName(GUID platformId) =>\n            GetModuleDisplayName(platformId);\n\n        /// <summary>\n        /// Platform description.\n        /// </summary>\n        public static string GetPlatformDescription(GUID platformGuid) =>\n            BuildTargetDiscovery.BuildPlatformDescription(platformGuid);\n\n        /// <summary>\n        /// Get Platform list of name and link url pair.\n        /// </summary>\n        public static List<BuildTargetDiscovery.NameAndLink> GetPlatformNameLinkList(GUID platformGuid) =>\n            BuildTargetDiscovery.BuildPlatformNameLinkList(platformGuid);\n\n        /// <summary>\n        /// Fetch default editor platform icon texture.\n        /// </summary>\n        public static Texture2D GetHelpIcon()\n        {\n            return EditorGUIUtility.LoadIcon(\"_Help\");\n        }\n        /// <summary>\n        /// Fetch subtitle used to show under the main platform name.\n        /// </summary>\n        public static string GetSubtitle(GUID platformGUID)\n        {\n            return BuildTargetDiscovery.BuildPlatformSubtitle(platformGUID);\n        }\n\n        /// <summary>\n        /// Fetch default editor platform icon texture.\n        /// </summary>\n        public static Texture2D GetPlatformIcon(GUID platformId)\n        {\n            if (LoadBuildProfileIcon(platformId, out Texture2D icon))\n                return icon;\n\n            return EditorGUIUtility.LoadIcon(GetPlatformIconId(platformId));\n        }\n\n        /// <summary>\n        /// Fetch small (16x16) editor platform icon texture.\n        /// </summary>\n        public static Texture2D GetPlatformIconSmall(GUID platformId)\n        {\n            if (LoadBuildProfileIcon(platformId, out Texture2D icon))\n                return icon;\n\n            return EditorGUIUtility.LoadIcon(GetPlatformIconId(platformId) + \".Small\");\n        }\n\n        [Obsolete(\"Do not use internal APIs from packages.\")]\n        public static Texture2D GetPlatformIconSmall(string platformId)\n        {\n            return GetPlatformIconSmall(new GUID(platformId));\n        }\n\n        /// <summary>\n        /// Fetch scene list icon for build profiles\n        /// </summary>\n        public static Texture2D GetSceneListIcon()\n        {\n            return EditorGUIUtility.LoadIcon(\"SceneList Icon\");\n        }\n\n        /// <summary>\n        /// Load internal warning icon\n        /// </summary>\n        public static Texture2D GetWarningIcon()\n        {\n            return EditorGUIUtility.LoadIcon(\"d_console.warnicon.sml\");\n        }\n\n        /// <summary>\n        /// Returns true if the module is installed and editor has permissions\n        /// for the given platform guid.\n        /// </summary>\n        public static bool IsModuleInstalled(GUID platformId)\n        {\n            var (buildTarget, _) = GetBuildTargetAndSubtarget(platformId);\n\n            bool installed = BuildTargetDiscovery.BuildPlatformIsInstalled(platformId);\n            return installed\n                && BuildPipeline.LicenseCheck(buildTarget)\n                && ModuleManager.IsPlatformSupportLoadedByGuid(platformId);\n        }\n\n        [Obsolete(\"Do not use internal APIs from packages.\")]\n        public static bool IsModuleInstalled(string platformId)\n        {\n            return IsModuleInstalled(new GUID(platformId));\n        }\n\n        /// <summary>\n        /// Returns true if an installed module supports build profiles.\n        /// </summary>\n        public static bool IsBuildProfileSupported(GUID platformId)\n        {\n            return ModuleManager.GetBuildProfileExtension(platformId) != null;\n        }\n\n        [Obsolete(\"Do not use internal APIs from packages.\")]\n        public static bool IsBuildProfileSupported(string platformId)\n        {\n            return IsBuildProfileSupported(new GUID(platformId));\n        }\n\n        /// <summary>\n        /// Generate button and label for downloading a platform module.\n        /// </summary>\n        /// <see cref=\"BuildPlayerWindow.ShowNoModuleLabel\"/>\n        public static VisualElement CreateModuleNotInstalledElement(GUID platformId)\n        {\n            var buildProfileWindowUss = EditorGUIUtility.LoadRequired(k_StyleSheet) as StyleSheet;\n            VisualElement container = new VisualElement();\n\n            container.styleSheets.Add(buildProfileWindowUss);\n            container.AddClasses(\"flex-row align-items-center flex-wrap full-width\");\n\n            if (BuildTargetDiscovery.BuildPlatformIsInstalled(platformId) && BuildTargetDiscovery.BuildPlatformIsDerivedPlatform(platformId))\n            {\n                return GetPlatformNotEnabledElement(platformId, container);\n            }\n\n            // TODO: this is a workaround for onboarding instructions to fix EmbeddedLinux and QNX\n            // needs to be removed when https://jira.unity3d.com/browse/PLAT-7721 is implemented\n            if (BuildTargetDiscovery.BuildPlatformTryGetCustomInstallLinkAndText(platformId, out var url, out var text))\n            {\n                return GetPlatformContactSalesElement(container, text, url);\n            }\n\n            if (IsBuildProfileDisabledViaArguments(platformId))\n            {\n                return GetPlatformDisabledViaArgumentsElement(platformId, container);\n            }\n\n            return GetPlatformNotInstalledElement(platformId, container);\n        }\n\n        static bool IsBuildProfileDisabledViaArguments(GUID platformId)\n        {\n            var (buildTarget, _) = BuildTargetDiscovery.GetBuildTargetAndSubtargetFromGUID(platformId);\n            var buildTargetInfoList = BuildTargetDiscovery.GetBuildTargetInfoList();\n\n            foreach (var info in buildTargetInfoList)\n                if (info.buildTargetPlatformVal.Equals(buildTarget))\n                    return InternalEditorUtility.IsPlaybackEngineDisabled(info.dirName);\n\n            return false;\n        }\n\n        /// <summary>\n        /// Exported from <see cref=\"BuildPlayerWindow\"/>, UI code specifically for when current license does not cover\n        /// BuildTarget.\n        /// </summary>\n        /// <returns>null when no license errors, else license check UI</returns>\n        public static VisualElement CreateLicenseNotFoundElement(GUID platformId)\n        {\n            var buildTarget = GetBuildTargetAndSubtarget(platformId).Item1;\n            if (BuildPipeline.LicenseCheck(buildTarget))\n                return null;\n\n            string displayName = GetModuleDisplayName(platformId);\n            string licenseMsg = L10n.Tr(\"Your license does not cover {0} Publishing.\");\n            string buttonMsg = L10n.Tr(\"Go to Our Online Store\");\n            string url = k_BuyProUrl;\n            if (BuildTargetDiscovery.PlatformHasFlag(buildTarget, TargetAttributes.IsConsole))\n            {\n                licenseMsg += \" Please see the {0} section of the Platform Module Installation documentation for more details.\";\n                buttonMsg = L10n.Tr(\"Platform Module Installation\");\n                url = k_ConsoleModuleUrl;\n            }\n            licenseMsg = L10n.Tr(licenseMsg);\n\n            var root = new VisualElement();\n            root.style.flexDirection = FlexDirection.Column;\n            var label = new Label(string.Format(licenseMsg, displayName));\n            label.style.whiteSpace = WhiteSpace.Normal;\n            root.Add(label);\n            if (!IsStandalonePlatform(buildTarget))\n            {\n                var button = new Button(() => Application.OpenURL(url));\n                button.style.width = 200;\n                button.text = buttonMsg;\n                root.Add(button);\n            }\n            return root;\n        }\n\n        public static bool IsStandalonePlatform(BuildTarget buildTarget) =>\n            BuildTargetDiscovery.PlatformHasFlag(buildTarget, TargetAttributes.IsStandalonePlatform);\n\n        /// <summary>\n        /// Retrieve the respective module name for a platform guid.\n        /// </summary>\n        public static string GetModuleName(GUID platformId)\n        {\n            var buildTarget = GetBuildTargetAndSubtarget(platformId).Item1;\n            return BuildTargetDiscovery.GetModuleNameForBuildTarget(buildTarget);\n        }\n\n        /// <summary>\n        /// Internal method for switching <see cref=\"EditorUserBuildSettings\"/> active build target and subtarget.\n        /// </summary>\n        public static void SwitchLegacyActiveFromBuildProfile(BuildProfile profile)\n        {\n            EditorUserBuildSettings.SwitchActiveBuildTargetGuid(profile);\n        }\n\n        public static void SwitchLegacySelectedBuildTargets(BuildProfile profile)\n        {\n            var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(profile.buildTarget);\n            var buildTargetSubTarget = (int)profile.subtarget;\n\n            if (buildTargetGroup == BuildTargetGroup.Standalone)\n                EditorUserBuildSettings.SetSelectedSubtargetFor(profile.buildTarget, buildTargetSubTarget);\n            EditorUserBuildSettings.selectedBuildTargetGroup = buildTargetGroup;\n        }\n\n        /// <summary>\n        /// Internally invoke <see cref=\"BuildPlayerWindow.CallBuildMethods(bool, BuildOptions)\"/>.\n        /// </summary>\n        public static void CallInternalBuildMethods(bool askForBuildLocation, BuildOptions options)\n        {\n            BuildPlayerWindow.CallBuildMethods(askForBuildLocation, options);\n        }\n\n        /// <summary>\n        /// Construct the build player options from the active build profile.\n        /// </summary>\n        /// <param name=\"buildLocation\">The path where the application will be built.</param>\n        /// <param name=\"assetBundleManifestPath\">The path to the asset bundle manifest file.</param>\n        /// <param name=\"customBuildOptions\">Custom build options to be applied.</param>\n        /// <see cref=\"BuildPlayerWindow.DefaultBuildMethods.GetBuildPlayerOptionsInternal\"/>\n        internal static BuildPlayerOptions GetBuildPlayerOptionsFromActiveProfile(string buildLocation, string assetBundleManifestPath, BuildOptions customBuildOptions)\n        {\n            var options = new BuildPlayerOptions();\n            var activeProfile = BuildProfile.GetActiveBuildProfile();\n\n            if (activeProfile == null)\n                throw new ArgumentException(\"Active build profile is null.\");\n\n            var buildTarget = activeProfile.buildTarget;\n            var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(buildTarget);\n            int subtarget = IsStandalonePlatform(buildTarget) ?\n                (int)activeProfile.subtarget : EditorUserBuildSettings.GetActiveSubtargetFor(buildTarget);\n\n            options.options = GetBuildOptions(buildTarget, buildTargetGroup, buildLocation, customBuildOptions);\n            options.target = buildTarget;\n            options.subtarget = subtarget;\n            options.targetGroup = buildTargetGroup;\n            options.locationPathName = buildLocation;\n            options.assetBundleManifestPath = assetBundleManifestPath ?? PostprocessBuildPlayer.GetStreamingAssetsBundleManifestPath();\n            options.scenes = EditorBuildSettingsScene.GetActiveSceneList(activeProfile.GetScenesForBuild());\n\n            return options;\n        }\n\n        internal static BuildOptions GetBuildOptions(BuildTarget buildTarget, BuildTargetGroup buildTargetGroup, string buildLocation, BuildOptions options = BuildOptions.None)\n        {\n            // Check if Lz4 is supported for the current buildtargetgroup and enable it if need be\n            if (PostprocessBuildPlayer.SupportsLz4Compression(buildTarget))\n            {\n                var compression = EditorUserBuildSettings.GetCompressionType(buildTargetGroup);\n                if (compression < 0)\n                    compression = PostprocessBuildPlayer.GetDefaultCompression(buildTarget);\n                if (compression == Compression.Lz4)\n                    options |= BuildOptions.CompressWithLz4;\n                else if (compression == Compression.Lz4HC)\n                    options |= BuildOptions.CompressWithLz4HC;\n            }\n\n            bool developmentBuild = EditorUserBuildSettings.development;\n            if (developmentBuild)\n                options |= BuildOptions.Development;\n            if (EditorUserBuildSettings.allowDebugging && developmentBuild)\n                options |= BuildOptions.AllowDebugging;\n            if (EditorUserBuildSettings.symlinkSources)\n                options |= BuildOptions.SymlinkSources;\n\n            if (BuildTargetDiscovery.TryGetBuildTarget(buildTarget, out IBuildTarget iBuildTarget))\n            {\n                if (EditorUserBuildSettings.connectProfiler && (developmentBuild || (iBuildTarget.PlayerConnectionPlatformProperties?.ForceAllowProfilerConnection ?? false)) )\n                    options |= BuildOptions.ConnectWithProfiler;\n            }\n\n            if (EditorUserBuildSettings.buildWithDeepProfilingSupport && developmentBuild)\n                options |= BuildOptions.EnableDeepProfilingSupport;\n            if (EditorUserBuildSettings.buildScriptsOnly)\n                options |= BuildOptions.BuildScriptsOnly;\n            if (!string.IsNullOrEmpty(ProfilerUserSettings.customConnectionID) && developmentBuild)\n                options |= BuildOptions.CustomConnectionID;\n\n            if (EditorUserBuildSettings.installInBuildFolder &&\n                PostprocessBuildPlayer.SupportsInstallInBuildFolder(buildTarget) &&\n                Unsupported.IsSourceBuild())\n            {\n                options |= BuildOptions.InstallInBuildFolder;\n            }\n            else if ((options & BuildOptions.PatchPackage) == 0)\n            {\n                if (!string.IsNullOrEmpty(buildLocation) && BuildPipeline.BuildCanBeAppended(buildTarget, buildLocation) == CanAppendBuild.Yes)\n                    options |= BuildOptions.AcceptExternalModificationsToPlayer;\n            }\n\n            return options;\n        }\n\n        public static IBuildProfileExtension GetBuildProfileExtension(GUID platformId) =>\n            ModuleManager.GetBuildProfileExtension(platformId);\n\n        public static GUIStyle dropDownToggleButton => EditorStyles.dropDownToggleButton;\n\n        /// <summary>\n        /// Returns all discovered platform keys that are possible Build Profile targets.\n        /// </summary>\n        public static List<GUID> FindAllViewablePlatforms()\n        {\n            var result = new List<GUID>();\n\n            foreach (var platformGuid in BuildTargetDiscovery.GetAllPlatforms())\n            {\n                var installed = BuildTargetDiscovery.BuildPlatformIsInstalled(platformGuid);\n                if (!installed && BuildTargetDiscovery.BuildPlatformIsHiddenInUI(platformGuid))\n                    continue;\n\n                result.Add(platformGuid);\n            }\n\n            // Swap current editor standalone platform to the top.\n            if (Application.platform == RuntimePlatform.OSXEditor)\n                result.Reverse(0, 2);\n            if (Application.platform == RuntimePlatform.LinuxEditor)\n                result.Reverse(0, 3);\n\n            return result;\n        }\n\n        public static bool IsPlatformVisibleInPlatformBrowserOnly(GUID platformGuid)\n        {\n            return BuildTargetDiscovery.BuildPlatformIsVisibleInPlatformBrowserOnly(platformGuid);\n        }\n\n        public static bool IsPlatformAvailableOnHostPlatform(GUID platformGuid, OperatingSystemFamily operatingSystemFamily)\n        {\n            return BuildTargetDiscovery.BuildPlatformIsAvailableOnHostPlatform(platformGuid, SystemInfo.operatingSystemFamily);\n        }\n\n        /// <summary>\n        /// Check if the user is able to build his VT-enabled Player for a target platform\n        /// </summary>\n        public static bool IsVirtualTexturingSettingsValid(GUID platformGuid)\n        {\n            if (!PlayerSettings.GetVirtualTexturingSupportEnabled())\n            {\n                return true;\n            }\n\n            var (buildTarget, _) = GetBuildTargetAndSubtarget(platformGuid);\n            if (!UnityEngine.Rendering.VirtualTexturingEditor.Building.IsPlatformSupportedForPlayer(buildTarget))\n            {\n                return false;\n            }\n\n            GraphicsDeviceType[] gfxTypes = PlayerSettings.GetGraphicsAPIs(buildTarget);\n            bool supportedAPI = true;\n            foreach (GraphicsDeviceType api in gfxTypes)\n            {\n                supportedAPI &= UnityEngine.Rendering.VirtualTexturingEditor.Building.IsRenderAPISupported(api, buildTarget, false);\n            }\n\n            return supportedAPI;\n        }\n\n        /// <summary>\n        /// Remove player settings for deleted build profile assets. For example, when deleting them\n        /// in the project folder\n        /// </summary>\n        public static void CleanUpPlayerSettingsForDeletedBuildProfiles(IList<BuildProfile> currentBuildProfiles)\n        {\n            BuildProfile.CleanUpPlayerSettingsForDeletedBuildProfiles(currentBuildProfiles);\n        }\n\n        /// <summary>\n        /// Check if build profile has serialized player settings\n        /// </summary>\n        public static bool HasSerializedPlayerSettings(BuildProfile buildProfile)\n        {\n            return buildProfile.HasSerializedPlayerSettings();\n        }\n\n        /// <summary>\n        /// Serialize build profile player settings\n        /// </summary>\n        public static void SerializePlayerSettings(BuildProfile buildProfile)\n        {\n            buildProfile.SerializePlayerSettings();\n        }\n\n        /// <summary>\n        /// Remove build profile player settings object and clear player settings yaml\n        /// </summary>\n        public static void RemovePlayerSettings(BuildProfile buildProfile)\n        {\n            buildProfile.RemovePlayerSettings(clearYaml: true);\n        }\n\n        /// <summary>\n        /// Create graphics settings override for build profile\n        /// </summary>\n        public static void CreateGraphicsSettings(BuildProfile buildProfile)\n        {\n            buildProfile.CreateGraphicsSettings();\n        }\n\n        /// <summary>\n        /// Remove build profile graphics settings override\n        /// </summary>\n        public static void RemoveGraphicsSettings(BuildProfile buildProfile)\n        {\n            buildProfile.RemoveGraphicsSettings();\n        }\n\n        /// <summary>\n        /// Create graphics settings quality for build profile\n        /// </summary>\n        public static void CreateQualitySettings(BuildProfile buildProfile)\n        {\n            buildProfile.CreateQualitySettings();\n        }\n\n        /// <summary>\n        /// Remove build profile quality settings override\n        /// </summary>\n        public static void RemoveQualitySettings(BuildProfile buildProfile)\n        {\n            buildProfile.RemoveQualitySettings();\n        }\n\n        public static void NotifyBuildProfileExtensionOfCreation(BuildProfile buildProfile, int preconfiguredSettingsVariant)\n        {\n            buildProfile.NotifyBuildProfileExtensionOfCreation(preconfiguredSettingsVariant);\n        }\n\n        /// <summary>\n        /// Create player settings for build profile based on global player settings\n        /// </summary>\n        public static void CreatePlayerSettingsFromGlobal(BuildProfile buildProfile)\n        {\n            buildProfile.CreatePlayerSettingsFromGlobal();\n        }\n\n        /// <summary>\n        /// Checks if player settings values are the same as project settings values\n        /// </summary>\n        public static bool IsDataEqualToProjectSettings(PlayerSettings playerSettings)\n        {\n            return BuildProfile.IsDataEqualToProjectSettings(playerSettings);\n        }\n\n        /// Retrieve string of filename invalid characters\n        /// </summary>\n        /// <returns></returns>\n        public static string GetFilenameInvalidCharactersStr()\n        {\n            return EditorUtility.GetInvalidFilenameChars();\n        }\n\n        /// <summary>\n        /// Delete last runnable build key in EditorPrefs for a profile that will be deleted\n        /// </summary>\n        public static void DeleteLastRunnableBuildKeyForProfile(BuildProfile profile)\n        {\n            var lastRunnableKey = profile.GetLastRunnableBuildPathKey();\n            if (!string.IsNullOrEmpty(lastRunnableKey))\n                EditorPrefs.DeleteKey(lastRunnableKey);\n        }\n\n        /// <summary>\n        /// Delete last runnable build keys in EditorPrefs for deleted profiles\n        /// </summary>\n        public static void DeleteLastRunnableBuildKeyForDeletedProfiles()\n        {\n            List<string> lastRunnableBuildPathKeys = BuildProfileContext.instance.LastRunnableBuildPathKeys;\n            for (int i = lastRunnableBuildPathKeys.Count - 1; i >= 0; i--)\n            {\n                string key = lastRunnableBuildPathKeys[i];\n                var assetPath = GetAssetPathFromLastRunnableBuildKey(key);\n                if (!AssetDatabase.AssetPathExists(assetPath))\n                {\n                    lastRunnableBuildPathKeys.RemoveAt(i);\n                    EditorPrefs.DeleteKey(key);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Get last runnable build key from build profile path\n        /// </summary>\n        public static string GetLastRunnableBuildKeyFromAssetPath(string assetPath, string baseKey)\n        {\n            return string.IsNullOrEmpty(assetPath) ? string.Empty : $\"{baseKey}{k_LastRunnableBuildPathSeparator}{assetPath}\";\n        }\n\n        /// On the next editor update recompile scripts.\n        /// </summary>\n        public static void RequestScriptCompilation(BuildProfile profile)\n        {\n            if (profile != null)\n                BuildProfileContext.instance.cachedEditorScriptingDefines = profile.scriptingDefines;\n            else\n                BuildProfileContext.instance.cachedEditorScriptingDefines = Array.Empty<string>();\n\n            EditorApplication.delayCall += TryRecompileScripts;\n        }\n\n        /// <summary>\n        /// Recompile scripts if the active build profile scripting defines\n        /// differs from the last compilation defines.\n        /// </summary>\n        static void TryRecompileScripts()\n        {\n            if (EditorApplication.isCompiling)\n                return;\n\n            PlayerSettings.RecompileScripts(k_BuildProfileRecompileReason);\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n        internal static void SuppressMissingTypeWarning()\n        {\n            SerializationUtility.SuppressMissingTypeWarning(nameof(BuildProfile));\n        }\n\n        internal static string GetBuildProfileLastRunnableBuildPathKey(BuildTarget buildTarget, StandaloneBuildSubtarget standaloneBuildSubtarget)\n        {\n            var platformGuid = GetPlatformId(buildTarget, standaloneBuildSubtarget);\n            var activeProfile = BuildProfile.GetActiveBuildProfile();\n            if (activeProfile != null && activeProfile.platformGuid == platformGuid)\n                return activeProfile.GetLastRunnableBuildPathKey();\n\n            var classicProfile = BuildProfileContext.instance.GetForClassicPlatform(platformGuid);\n            return classicProfile != null ? classicProfile.GetLastRunnableBuildPathKey() : string.Empty;\n        }\n\n        internal static void SetBuildProfileLastRunnableBuildPathKey(string key, string value)\n        {\n            if (BuildProfile.GetActiveBuildProfile() != null &&\n                !BuildProfileContext.instance.LastRunnableBuildPathKeys.Contains(key))\n            {\n                BuildProfileContext.instance.LastRunnableBuildPathKeys.Add(key);\n            }\n            EditorPrefs.SetString(key, value);\n        }\n\n        static bool LoadBuildProfileIcon(GUID platformId, out Texture2D icon)\n        {\n            var moduleName = GetModuleName(platformId);\n            if (s_BuildProfileIconModules.Contains(moduleName))\n            {\n                icon = EditorGUIUtility.FindTexture(typeof(BuildProfile));\n                return true;\n            }\n\n            icon = null;\n            return false;\n        }\n\n        static string GetPlatformIconId(GUID platformId)\n        {\n            var iconName = BuildTargetDiscovery.BuildPlatformIconName(platformId);\n\n            if (string.IsNullOrEmpty(iconName))\n                return \"BuildSettings.Editor\";\n\n            return iconName;\n        }\n\n        static string GetModuleDisplayName(GUID platformId)\n        {\n            return BuildTargetDiscovery.BuildPlatformDisplayName(platformId);\n        }\n\n        /// <summary>\n        /// Get build profile path from the last runnable build key\n        /// </summary>\n        static string GetAssetPathFromLastRunnableBuildKey(string key)\n        {\n            int lastUnderscoreIndex = key.LastIndexOf(k_LastRunnableBuildPathSeparator);\n            return lastUnderscoreIndex != -1 ? key[(lastUnderscoreIndex + 1)..] : string.Empty;\n        }\n\n        /// <summary>\n        /// Get the platform GUID corresponding to the BuildTarget and the StandaloneBuildSubtarget.\n        /// </summary>\n        /// <param name=\"buildTarget\">The BuildTarget to get the platform GUID for.</param>\n        /// <param name=\"subtarget\">The StandaloneBuildSubtarget to get the platform GUID for.</param>\n        /// <returns>The platform GUID. Derived platform GUID when the active platform is a derived platform. Base platform GUID otherwise.</returns>\n        public static GUID GetPlatformId(BuildTarget buildTarget, StandaloneBuildSubtarget subtarget)\n        {\n            var platformGuid = subtarget == StandaloneBuildSubtarget.Server && IsStandalonePlatform(buildTarget)\n                ? BuildTargetDiscovery.GetGUIDFromBuildTarget(NamedBuildTarget.Server, buildTarget)\n                : BuildTargetDiscovery.GetGUIDFromBuildTarget(buildTarget);\n            return platformGuid;\n        }\n\n        public static (BuildTarget, StandaloneBuildSubtarget) GetBuildTargetAndSubtarget(GUID platformId)\n        {\n            return BuildTargetDiscovery.GetBuildTargetAndSubtargetFromGUID(platformId);\n        }\n\n        public static string[] BuildPlatformRequiredPackages(GUID platformGuid)\n        {\n            return BuildTargetDiscovery.BuildPlatformRequiredPackages(platformGuid);\n        }\n\n        public static string[] BuildPlatformRecommendedPackages(GUID platformGuid)\n        {\n            return BuildTargetDiscovery.BuildPlatformRecommendedPackages(platformGuid);\n        }\n\n        public static string BuildPlatformDescription(GUID platformGuid)\n        {\n            return BuildTargetDiscovery.BuildPlatformDescription(platformGuid);\n        }\n\n        public static void OnActiveProfileGraphicsSettingsChanged(bool hasGraphicsSettings)\n        {\n            EditorGraphicsSettings.activeProfileHasGraphicsSettings = hasGraphicsSettings;\n            GraphicsSettingsInspector.OnActiveProfileGraphicsSettingsChanged?.Invoke();\n        }\n\n        internal static void RemoveQualityLevelFromAllProfiles(string qualityLevelName)\n        {\n            var profiles = GetAllBuildProfiles();\n            foreach (var profile in profiles)\n            {\n                if (profile.qualitySettings == null)\n                    continue;\n\n                profile.qualitySettings.RemoveQualityLevel(qualityLevelName);\n            }\n        }\n\n        internal static void RenameQualityLevelInAllProfiles(string oldName, string newName)\n        {\n            var profiles = GetAllBuildProfiles();\n            foreach (var profile in profiles)\n            {\n                if (profile.qualitySettings == null)\n                    continue;\n\n                profile.qualitySettings.RenameQualityLevel(oldName, newName);\n            }\n        }\n\n        /// <summary>\n        /// Get all custom build profiles in the project.\n        /// </summary>\n        public static List<BuildProfile> GetAllBuildProfiles()\n        {\n            var alreadyLoadedBuildProfiles = Resources.FindObjectsOfTypeAll<BuildProfile>();\n\n            const string buildProfileAssetSearchString = $\"t:{nameof(BuildProfile)}\";\n            var assetsGuids = AssetDatabase.FindAssets(buildProfileAssetSearchString);\n            var result = new List<BuildProfile>(assetsGuids.Length);\n\n            // Suppress missing type warning thrown by serialization. This could happen\n            // when the build profile window is opened, then entering play mode and the\n            // module for that profile is not installed.\n            BuildProfileModuleUtil.SuppressMissingTypeWarning();\n\n            foreach (var guid in assetsGuids)\n            {\n                string path = AssetDatabase.GUIDToAssetPath(guid);\n                BuildProfile profile = AssetDatabase.LoadAssetAtPath<BuildProfile>(path);\n                if (profile == null)\n                {\n                    Debug.LogWarning($\"[BuildProfile] Failed to load asset at path: {path}\");\n                    continue;\n                }\n\n                result.Add(profile);\n            }\n\n            foreach (var buildProfile in alreadyLoadedBuildProfiles)\n            {\n                // Asset database will not give us any build profiles that get created in memory\n                // and we need to include them in this list as we use it to detect that build profiles\n                // have been destroyed and destroy their resources like PlayerSettings afterwards.\n                // Skipping the in-memory build profiles will result in us deleting their associated\n                // player settings object while it's being used and will lead to a crash (UUM-77423)\n                if (buildProfile &&\n                    !BuildProfileContext.IsClassicPlatformProfile(buildProfile) &&\n                    !BuildProfileContext.IsSharedProfile(buildProfile.platformGuid) &&\n                    !EditorUtility.IsPersistent(buildProfile))\n                {\n                    result.Add(buildProfile);\n                }\n            }\n\n            return result;\n        }\n\n        public static PlayerSettings GetGlobalPlayerSettings()\n        {\n            return BuildProfile.GetGlobalPlayerSettings();\n        }\n\n        /// <summary>\n        /// Handles change in global player settings object from the build profile workflow.\n        /// Checks that the player settings in <see cref=\"nextBuildProfile\"/> can be applied\n        /// and/or requests action from the end user.\n        /// </summary>\n        /// <returns>\n        ///     true, if player settings for the next profile have been handled.\n        /// </returns>\n        public static bool HandlePlayerSettingsChanged(\n            BuildProfile currentBuildProfile, BuildProfile nextBuildProfile)\n        {\n            PlayerSettings projectSettingsPlayerSettings = GetGlobalPlayerSettings();\n            PlayerSettings currentPlayerSettings = projectSettingsPlayerSettings;\n            PlayerSettings nextPlayerSettings = projectSettingsPlayerSettings;\n\n            var currentBuildTarget = EditorUserBuildSettings.activeBuildTarget;\n            var nextBuildTarget = EditorUserBuildSettings.activeBuildTarget;\n\n            if (currentBuildProfile != null)\n            {\n                currentBuildTarget = currentBuildProfile.buildTarget;\n                if (currentBuildProfile.playerSettings != null)\n                {\n                    currentPlayerSettings = currentBuildProfile.playerSettings;\n                }\n            }\n\n            if (nextBuildProfile != null)\n            {\n                nextBuildTarget = nextBuildProfile.buildTarget;\n                if (nextBuildProfile.playerSettings != null)\n                {\n                    nextPlayerSettings = nextBuildProfile.playerSettings;\n                }\n            }\n\n            var settingsRequiringRestart = PlayerSettings.GetSettingsRequiringRestart(currentPlayerSettings,\n                nextPlayerSettings, currentBuildTarget, nextBuildTarget);\n            // if we've found settings that need restarting..\n            if (settingsRequiringRestart.Length > 0 )\n            {\n                // ..we show the restart prompt, if the user restarts, we add a restart call to the editor\n                if (ShowRestartEditorDialog(settingsRequiringRestart))\n                {\n                    if (ContainsPlayerSetting(settingsRequiringRestart, PlayerSettingsRequiringRestart.VirtualTexturing))\n                    {\n                        PlayerSettings.SyncVirtualTexturingState(nextPlayerSettings);\n                    }\n\n                    EditorApplication.delayCall += EditorApplication.RestartEditorAndRecompileScripts;\n                    return true;\n                }\n                else\n                {\n                    return false;\n                }\n            }\n\n            // Handle editor changed requiring background work without an editor prompt.\n            PlayerSettingsEditor.HandlePlayerSettingsChanged(\n                currentPlayerSettings, nextPlayerSettings,\n                currentBuildTarget, nextBuildTarget);\n            return true;\n        }\n\n\n        /// <summary>\n        /// Show the restart editor dialog with the names of the settings that required the restart to take effect.\n        /// </summary>\n        static bool ShowRestartEditorDialog(PlayerSettingsRequiringRestart[] settingsRequiringRestart)\n        {\n            var editorPromptText = new StringBuilder();\n            editorPromptText.AppendLine(L10n.Tr(\"The Unity editor must be restarted for the following settings to take effect:\"));\n            var playerSettingNames = GetPlayerSettingNamesToEditorRestartPromptText(settingsRequiringRestart);\n            editorPromptText.AppendLine(playerSettingNames.ToString());\n            return EditorUtility.DisplayDialog(L10n.Tr(\"Unity editor restart required\"),\n                editorPromptText.ToString(), L10n.Tr(\"Apply\"), L10n.Tr(\"Cancel\"));\n        }\n\n\n        internal static PlayerSettings GetBuildProfileOrGlobalPlayerSettings(BuildProfile buildProfile)\n        {\n            if (buildProfile == null || buildProfile.playerSettings == null)\n            {\n                return BuildProfile.GetGlobalPlayerSettings();\n            }\n            return buildProfile.playerSettings;\n        }\n\n        public static bool IsBasePlatformOfActivePlatform(GUID platformGuid)\n        {\n            var module = ModuleManager.FindPlatformSupportModule(EditorUserBuildSettings.activePlatformGuid);\n            if (module == null)\n                return false;\n            if (module is IDerivedBuildTargetProvider derivedBuildTargetProvider)\n            {\n                var basePlatformGuid = derivedBuildTargetProvider.GetBasePlatformGuid();\n                return basePlatformGuid == platformGuid;\n            }\n            return false;\n        }\n\n        public static void RepaintProjectSettingsWindow()\n        {\n            foreach (var window in EditorWindow.activeEditorWindows)\n            {\n                if (window is ProjectSettingsWindow)\n                {\n                    window.Repaint();\n                }\n            }\n        }\n\n        /*\n         * private helper functions\n         */\n        private static bool ContainsPlayerSetting(PlayerSettingsRequiringRestart[] playerSettings, PlayerSettingsRequiringRestart targetSetting)\n        {\n            foreach (PlayerSettingsRequiringRestart setting in playerSettings)\n            {\n                if (setting == targetSetting)\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        private static StringBuilder GetPlayerSettingNamesToEditorRestartPromptText(PlayerSettingsRequiringRestart[] settingsRequiringRestart)\n        {\n            var settingsText = new StringBuilder();\n            foreach (PlayerSettingsRequiringRestart setting in settingsRequiringRestart)\n            {\n                var settingPromptText = setting switch\n                {\n                    PlayerSettingsRequiringRestart.IncrementalGC => \"Incremental GC\",\n                    PlayerSettingsRequiringRestart.ActiveInputHandling => \"Active Input Handling\",\n                    PlayerSettingsRequiringRestart.GraphicsJobs => \"Graphics Jobs\",\n                    PlayerSettingsRequiringRestart.VirtualTexturing => \"Virtual Texturing\",\n                    _ => string.Empty\n                };\n                settingsText.AppendLine(settingPromptText);\n            }\n            return settingsText;\n        }\n\n        public static void InstallRequiredPackagesForClassicProfileIfRequired(BuildProfile profile, Func<string, string, bool> doesUserApprove)\n        {\n            if (!BuildProfileContext.IsClassicPlatformProfile(profile))\n                return;\n\n            var buildTarget = profile.GetIBuildTarget();\n            if (buildTarget == null)\n                return;\n            if (!buildTarget.TryGetProperties<IBuildPlatformProperties>(out var properties))\n                return;\n\n            if (!properties.ShouldInstallRequiredPackagesOnActivationOfClassicPlatform)\n                return;\n\n            var packages = BuildTargetDiscovery.BuildPlatformRequiredPackages(profile.platformGuid);\n            if (packages.Length == 0)\n                return;\n\n            var packageStringBuilder = new StringBuilder();\n            var neededPackages = new List<string>();\n            foreach (var package in packages)\n            {\n                if (!PackageManager.PackageInfo.IsPackageRegistered(package))\n                {\n                    packageStringBuilder.AppendLine().Append(package);\n                    neededPackages.Add(package);\n                }\n            }\n\n            if (neededPackages.Count == 0)\n                return;\n\n            if (doesUserApprove != null && !doesUserApprove.Invoke(buildTarget.DisplayName, packageStringBuilder.ToString()))\n                return;\n\n            PackageManager.Client.AddAndRemove(neededPackages.ToArray());\n        }\n\n        static VisualElement GetPlatformNotInstalledElement(GUID platformGuid, VisualElement container)\n        {\n            var basePlatformGuid = BuildTargetDiscovery.GetBasePlatformGUID(platformGuid);\n            var displayName = BuildTargetDiscovery.BuildPlatformDisplayName(basePlatformGuid);\n\n            var platformNotLoadedLabel = new Label(string.Format(k_NoModuleLoaded, displayName));\n            var editorReloadNeededLabel = new Label(k_EditorWillNeedToBeReloaded);\n            var labels = new VisualElement();\n\n            labels.AddClasses(\"flex-column flex-grow-1\");\n            editorReloadNeededLabel.AddClasses(\"text-small wrap\");\n\n            labels.Add(platformNotLoadedLabel);\n            labels.Add(editorReloadNeededLabel);\n\n            var url = string.Empty;\n            Button button;\n\n            if (!BuildPlayerWindow.IsEditorInstalledWithHub() || !BuildTargetDiscovery.BuildPlatformCanBeInstalledWithHub(platformGuid))\n            {\n                button = new Button(() =>\n                {\n                    url = BuildPlayerWindow.GetPlaybackEngineDownloadURL(platformGuid);\n                    Help.BrowseURL(url);\n                })\n                {\n                    text = k_OpenDownloadPage.ToString()\n                };\n            }\n            else\n            {\n                button = new Button(() =>\n                {\n                    url = BuildPlayerWindow.GetUnityHubModuleDownloadURL(platformGuid);\n                    Help.BrowseURL(url);\n                })\n                {\n                    text = k_InstallModuleWithHub.ToString()\n                };\n            }\n\n            container.Add(labels);\n            container.Add(button);\n\n            return container;\n        }\n\n        private static VisualElement GetPlatformDisabledViaArgumentsElement(GUID platformId, VisualElement container)\n        {\n            container.Add(new Label(string.Format(k_DerivedPlatformDisabled,\n                BuildTargetDiscovery.BuildPlatformDisplayName(platformId))));\n\n            return container;\n        }\n\n        private static VisualElement GetPlatformContactSalesElement(VisualElement container, string text, string url)\n        {\n            var label = new Label(text);\n\n            label.AddClasses(\"flex-grow-1 flex-shrink-1 wrap\");\n\n            container.Add(label);\n            container.Add(new Button(() =>\n            {\n                Help.BrowseURL(url);\n            })\n            {\n                text = \"Contact Sales\"\n            });\n\n            return container;\n        }\n\n        private static VisualElement GetPlatformNotEnabledElement(GUID platformId, VisualElement container)\n        {\n            var label = new Label(string.Format(k_DerivedPlatformInactive,\n                BuildTargetDiscovery.BuildPlatformDisplayName(platformId)));\n\n            label.AddToClassList(\"flex-grow-1\");\n\n            container.Add(label);\n            container.Add(new Button(() =>\n            {\n                EditorPrefs.SetInt(platformId.ToString(), 1);\n                RequestScriptCompilation(BuildProfileContext.activeProfile);\n            })\n            {\n                text = k_ActivateDerivedPlatform.ToString()\n            });\n\n            return container;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfilePackageAddInfo.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing System.Collections.Generic;\n\nnamespace UnityEditor.Build.Profile;\n\n[VisibleToOtherModules]\ninternal class BuildProfilePackageAddInfo\n{\n    public const int preconfiguredSettingsVariantNotSet = -2;\n\n    public enum ProgressState\n    {\n        PackageStateUnknown,\n        PackagePending,\n        PackageDownloading,\n        PackageInstalling,\n        PackageReady,\n        PackageError,\n        ConfigurationPending,\n        ConfigurationRunning\n    }\n\n    public record struct ProgressEntry(ProgressState state, string name, int packageCount);\n\n    [SerializeField]\n    public string profileGuid = string.Empty;\n    [SerializeField]\n    public string[] packagesToAdd { get; set; } = Array.Empty<string>();\n    [SerializeField]\n    public int preconfiguredSettingsVariant { get; set; } = preconfiguredSettingsVariantNotSet;\n\n    public Action OnPackageAddProgress;\n    public Action OnPackageAddComplete;\n\n    PackageManager.Requests.AddAndRemoveRequest m_PackageAddRequest = null;\n    ProgressEntry m_PackageAddProgressInfo = new();\n\n    public void RequestPackageInstallation()\n    {\n        if (packagesToAdd.Length > 0)\n        {\n            m_PackageAddRequest = PackageManager.Client.AddAndRemove(packagesToAdd);\n            m_PackageAddRequest.progressUpdated += HandlePackageAddProgress;\n        }\n        else if (preconfiguredSettingsVariant != preconfiguredSettingsVariantNotSet)\n        {\n            OnPackageAddComplete?.Invoke();\n        }\n    }\n\n    public ProgressEntry GetPackageAddProgressInfo() => m_PackageAddProgressInfo;\n\n    bool ContainsPackage(string name)\n    {\n        foreach (var package in packagesToAdd)\n        {\n            if (package == name)\n                return true;\n        }\n        return false;\n    }\n\n    void HandlePackageAddProgress(PackageManager.ProgressUpdateEventArgs progress)\n    {\n        int readyPackageNum = 0;\n        bool done = false;\n        bool packageInstalling = false;\n        bool packageDownloading = false;\n        bool packageErr = false;\n        string packageNames = \"\";\n        int packagesDownloadingCnt = 0;\n        int packagesInstallingCnt = 0;\n        int packagesErrCnt = 0;\n\n\n        ProgressEntry info;\n        foreach (var entry in progress.entries)\n        {\n            if (ContainsPackage(entry.name))\n            {\n                if (packageNames.Length > 0)\n                    packageNames += \" \";\n                switch (entry.state)\n                {\n                    case PackageManager.ProgressState.Ready:\n                        readyPackageNum += 1;\n                        break;\n                    case PackageManager.ProgressState.Error:\n                        packageErr = true;\n                        packagesErrCnt++;\n                        break;\n                    case PackageManager.ProgressState.Downloading:\n                        packageDownloading = true;\n                        packagesDownloadingCnt++;\n                        break;\n                    case PackageManager.ProgressState.Installing:\n                        packageInstalling = true;\n                        packagesInstallingCnt++;\n                        break;\n                }\n                packageNames += entry.name;\n            }\n        }\n\n        done = (readyPackageNum == packagesToAdd.Length);\n\n        if (packageErr)\n        {\n            info = new ProgressEntry(ProgressState.PackageError, packageNames, packagesErrCnt);\n        }\n        else if (packageInstalling)\n        {\n            info = new ProgressEntry(ProgressState.PackageInstalling, packageNames, packagesInstallingCnt);\n        }\n        else if (packageDownloading)\n        {\n            info = new ProgressEntry(ProgressState.PackageDownloading, packageNames, packagesDownloadingCnt);\n        }\n        else\n        {\n            info = new ProgressEntry(done ? ProgressState.ConfigurationRunning : ProgressState.ConfigurationPending, packageNames, 0);\n        }\n\n        m_PackageAddProgressInfo = info;\n        OnPackageAddProgress?.Invoke();\n        if (done)\n        {\n            m_PackageAddRequest = null;\n            packagesToAdd = Array.Empty<string>();\n            OnPackageAddComplete?.Invoke();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfilePlatformSettingsBase.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.Modules;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor.Build.Profile\n{\n    /// <summary>\n    /// Base class for platform module specific build settings.\n    /// Implementation fetched from BuildProfileExtension, <see cref=\"ModuleManager.GetBuildProfileExtension\"/>.\n    /// </summary>\n    [Serializable]\n    [VisibleToOtherModules]\n    internal abstract class BuildProfilePlatformSettingsBase\n    {\n        internal const string k_SettingDevelopment = \"development\";\n        internal const string k_SettingConnectProfiler = \"connectProfiler\";\n        internal const string k_SettingBuildWithDeepProfilingSupport = \"buildWithDeepProfilingSupport\";\n        internal const string k_SettingAllowDebugging = \"allowDebugging\";\n        internal const string k_SettingWaitForManagedDebugger = \"WaitForManagedDebugger\";\n        internal const string k_SettingManagedDebuggerFixedPort = \"ManagedDebuggerFixedPort\";\n        internal const string k_SettingCompressionType = \"compressionType\";\n        internal const string k_SettingExplicitNullChecks = \"explicitNullChecks\";\n        internal const string k_SettingExplicitDivideByZeroChecks = \"explicitDivideByZeroChecks\";\n        internal const string k_SettingExplicitArrayBoundsChecks = \"explicitArrayBoundsChecks\";\n        internal const string k_SettingInstallInBuildFolder = \"installInBuildFolder\";\n\n        internal const int k_InvalidCompressionIdx = -1;\n        internal const int k_MaxPortNumber = 65535;\n\n        [SerializeField] bool m_Development = false;\n        [SerializeField] bool m_ConnectProfiler = false;\n        [SerializeField] bool m_BuildWithDeepProfilingSupport = false;\n        [SerializeField] bool m_AllowDebugging = false;\n        [SerializeField] bool m_WaitForManagedDebugger = false;\n        [SerializeField] int m_ManagedDebuggerFixedPort = 0;\n        [SerializeField] bool m_ExplicitNullChecks = false;\n        [SerializeField] bool m_ExplicitDivideByZeroChecks = false;\n        [SerializeField] bool m_ExplicitArrayBoundsChecks = false;\n        [SerializeField] Compression m_CompressionType = (Compression)k_InvalidCompressionIdx;\n        [SerializeField] bool m_InstallInBuildFolder = false;\n\n        internal protected virtual bool development\n        {\n            get => m_Development;\n            set => m_Development = value;\n        }\n\n        internal protected virtual bool connectProfiler\n        {\n            get => m_ConnectProfiler;\n            set => m_ConnectProfiler = value;\n        }\n\n        internal protected virtual bool buildWithDeepProfilingSupport\n        {\n            get => m_BuildWithDeepProfilingSupport;\n            set => m_BuildWithDeepProfilingSupport = value;\n        }\n\n        internal protected virtual bool allowDebugging\n        {\n            get => m_AllowDebugging;\n            set => m_AllowDebugging = value;\n        }\n\n        internal protected virtual bool waitForManagedDebugger\n        {\n            get => m_WaitForManagedDebugger;\n            set => m_WaitForManagedDebugger = value;\n        }\n\n        internal protected virtual int managedDebuggerFixedPort\n        {\n            get\n            {\n                if (0 < m_ManagedDebuggerFixedPort && m_ManagedDebuggerFixedPort <= k_MaxPortNumber)\n                {\n                    return m_ManagedDebuggerFixedPort;\n                }\n                return 0;\n            }\n            set => m_ManagedDebuggerFixedPort = value;\n        }\n\n        internal protected virtual bool explicitNullChecks\n        {\n            get => m_ExplicitNullChecks;\n            set => m_ExplicitNullChecks = value;\n        }\n\n        internal protected virtual bool explicitDivideByZeroChecks\n        {\n            get => m_ExplicitDivideByZeroChecks;\n            set => m_ExplicitDivideByZeroChecks = value;\n        }\n\n        internal protected virtual bool explicitArrayBoundsChecks\n        {\n            get => m_ExplicitArrayBoundsChecks;\n            set => m_ExplicitArrayBoundsChecks = value;\n        }\n\n        internal virtual Compression compressionType\n        {\n            get => m_CompressionType;\n            set => m_CompressionType = value;\n        }\n\n        internal protected virtual bool installInBuildFolder\n        {\n            get => m_InstallInBuildFolder;\n            set => m_InstallInBuildFolder = value;\n        }\n\n\n        /// <summary>\n        /// Set platform setting based on strings for name and value. Native\n        /// calls this to keep build profiles and EditorUserBuildSettings\n        /// PlatformSettings dictionary in sync for backward compatibility.\n        /// </summary>\n        public virtual void SetRawPlatformSetting(string name, string value)\n        {\n            switch (name)\n            {\n                case k_SettingWaitForManagedDebugger:\n                    waitForManagedDebugger = value.ToString().ToLower() == \"true\";\n                    break;\n                case k_SettingManagedDebuggerFixedPort:\n                {\n                    if (Int32.TryParse(value, out int intValue))\n                    {\n                        if (0 < intValue && intValue <= k_MaxPortNumber)\n                        {\n                            managedDebuggerFixedPort = intValue;\n                            break;\n                        }\n                    }\n                    managedDebuggerFixedPort = 0;\n                    break;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Get platform setting value based on its name. Native calls this to\n        /// keep build profiles and EditorUserBuildSettings PlatformSettings\n        /// dictionary settings in sync for backward compatibility.\n        /// </summary>\n        public virtual string GetRawPlatformSetting(string name)\n        {\n            if (name.Equals(k_SettingWaitForManagedDebugger))\n            {\n                return waitForManagedDebugger.ToString().ToLower();\n            }\n            else if (name.Equals(k_SettingManagedDebuggerFixedPort))\n            {\n                return managedDebuggerFixedPort.ToString();\n            }\n\n            return null;\n        }\n\n        /// <summary>\n        /// Specify if a shared setting for a platform is enabled to determine\n        /// if native should fetch the value from the active profile or the shared\n        /// profile.\n        /// </summary>\n        public virtual bool IsSharedSettingEnabled(string name)\n        {\n            return name switch\n            {\n                k_SettingDevelopment => true,\n                k_SettingConnectProfiler => true,\n                k_SettingBuildWithDeepProfilingSupport => true,\n                k_SettingAllowDebugging => true,\n                k_SettingWaitForManagedDebugger => true,\n                k_SettingManagedDebuggerFixedPort => false,\n                k_SettingExplicitNullChecks => false,\n                k_SettingExplicitDivideByZeroChecks => false,\n                k_SettingExplicitArrayBoundsChecks => false,\n                k_SettingInstallInBuildFolder => true,\n                _ => false,\n            };\n        }\n\n        /// <summary>\n        /// Set platform-specific shared settings based on strings for name and value.\n        /// The shared profile calls this to sync platform-specific shared settings\n        /// across relevant platforms.\n        /// </summary>\n        public virtual void SetSharedSetting(string name, string value)\n        {\n        }\n\n        /// <summary>\n        /// Get platform-specific shared settings based on strings for name. Most shared\n        /// settings don't need to be in it. Use it only in rare cases where a platform-specific\n        /// shared setting need to be fetched outside of its platform module.\n        /// </summary>\n        public virtual string GetSharedSetting(string name)\n        {\n            return null;\n        }\n\n        /// <summary>\n        /// Get last path of a runnable build for this build profile\n        /// </summary>\n        public virtual string GetLastRunnableBuildPathKey()\n        {\n            return string.Empty;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfilePlayerSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\nusing UnityEngine;\n\nnamespace UnityEditor.Build.Profile\n{\n    public partial class BuildProfile\n    {\n        [Serializable]\n        internal class PlayerSettingsYaml\n        {\n            [Serializable]\n            class YamlSetting\n            {\n                public string line;\n\n                public YamlSetting(string newLine)\n                {\n                    // Prefixing the YAML property value with '|' to escape special characters\n                    // and avoid 'Failed to parse' yaml error\n                    line = $\"{\"| \"}{newLine}\";\n                }\n\n                public string GetLine()\n                {\n                    return line[2..];\n                }\n            }\n\n            [SerializeField]\n            List<YamlSetting> m_Settings = new();\n\n            internal void SetSettingsFromYaml(string yamlStr)\n            {\n                m_Settings.Clear();\n\n                // Splitting the YAML single string into individual lines to better readability\n                // in the asset file\n                var settings = yamlStr.Split(\"\\n\");\n                string prevLine = \"\";\n                foreach (var setting in settings)\n                {\n                    // When the } is on the second line, we should join the two lines.\n                    // Otherwise, we will break the serialization for the object by adding\n                    // the '-line' in front of the second line that when deserialized, it does not\n                    // know how to parse it.\n                    if (setting.Contains(\"{\") && !setting.Contains(\"}\"))\n                    {\n                        prevLine = setting;\n                        continue;\n                    }\n\n                    if (!string.IsNullOrEmpty(prevLine))\n                    {\n                        if (setting.Contains(\"}\"))\n                        {\n                            m_Settings.Add(new YamlSetting(prevLine + setting));\n                        }\n                        else\n                        {\n                            Debug.LogWarning(\"a { has no closing } on the second line. Invalid Serialization.\");\n                        }\n                        prevLine = \"\";\n                        continue;\n                    }\n\n                    var newSetting = new YamlSetting(setting);\n                    m_Settings.Add(newSetting);\n                }\n            }\n\n            internal string GetYamlString()\n            {\n                var stringBuilder = new StringBuilder();\n                foreach (var setting in m_Settings)\n                {\n                    stringBuilder.AppendLine(setting.GetLine());\n                }\n                return stringBuilder.ToString();\n            }\n\n            internal bool HasSettings()\n            {\n                return m_Settings.Count > 0;\n            }\n\n            internal void Clear()\n            {\n                m_Settings.Clear();\n            }\n        }\n\n        const string k_ProjectSettingsAssetPath = \"ProjectSettings/ProjectSettings.asset\";\n\n        static PlayerSettings s_GlobalPlayerSettings;\n\n        static readonly List<PlayerSettings> s_LoadedPlayerSettings = new();\n\n        internal void LoadPlayerSettings()\n        {\n            TryLoadProjectSettingsAssetPlayerSettings();\n            DeserializePlayerSettings();\n        }\n\n        internal void UpdatePlayerSettingsObjectFromYAML()\n        {\n            if (!HasSerializedPlayerSettings())\n                return;\n\n            PlayerSettings.UpdatePlayerSettingsObjectFromYAML(playerSettings, m_PlayerSettingsYaml.GetYamlString());\n            OnPlayerSettingsUpdatedFromYAML?.Invoke();\n        }\n\n        internal void CreatePlayerSettingsFromGlobal()\n        {\n            if (m_PlayerSettings != null || BuildProfileContext.IsClassicPlatformProfile(this))\n                return;\n\n            var newPlayerSettings = Instantiate(s_GlobalPlayerSettings);\n\n            var yamlStr = PlayerSettings.SerializeAsYAMLString(newPlayerSettings);\n            m_PlayerSettingsYaml.SetSettingsFromYaml(yamlStr);\n            m_PlayerSettings = newPlayerSettings;\n            s_LoadedPlayerSettings.Add(m_PlayerSettings);\n\n            UpdateGlobalManagerPlayerSettings();\n        }\n\n        internal void RemovePlayerSettings(bool clearYaml = false)\n        {\n            if (BuildProfileContext.IsClassicPlatformProfile(this))\n                return;\n\n            UpdateGlobalManagerPlayerSettings(activeWillBeRemoved: true);\n\n            if (m_PlayerSettings != null)\n            {\n                DestroyImmediate(m_PlayerSettings, true);\n                s_LoadedPlayerSettings.Remove(m_PlayerSettings);\n                m_PlayerSettings = null;\n\n                if (clearYaml)\n                    m_PlayerSettingsYaml.Clear();\n            }\n\n            OnPlayerSettingsUpdatedFromYAML?.Invoke();\n        }\n\n        internal static void CleanUpPlayerSettingsForDeletedBuildProfiles(IList<BuildProfile> currentBuildProfiles)\n        {\n            TrySetProjectSettingsAssetAsGlobalManagerPlayerSettings();\n\n            for (int i = s_LoadedPlayerSettings.Count - 1; i >= 0; i--)\n            {\n                var loadedPlayerSettings = s_LoadedPlayerSettings[i];\n                if (loadedPlayerSettings == null)\n                {\n                    s_LoadedPlayerSettings.RemoveAt(i);\n                    continue;\n                }\n\n                bool shouldDelete = true;\n                foreach (var profile in currentBuildProfiles)\n                {\n                    if (profile.playerSettings == loadedPlayerSettings)\n                    {\n                        shouldDelete = false;\n                        break;\n                    }\n                }\n\n                if (shouldDelete)\n                {\n                    s_LoadedPlayerSettings.RemoveAt(i);\n                    DestroyImmediate(loadedPlayerSettings, true);\n                }\n            }\n        }\n\n        internal void SerializePlayerSettings()\n        {\n            if (m_PlayerSettings == null)\n                return;\n\n            PlayerSettings.EnsureUnityConnectSettingsEqual(m_PlayerSettings, s_GlobalPlayerSettings);\n\n            var yamlStr = PlayerSettings.SerializeAsYAMLString(m_PlayerSettings);\n            m_PlayerSettingsYaml.SetSettingsFromYaml(yamlStr);\n        }\n\n        internal void DeserializePlayerSettings()\n        {\n            if (!HasSerializedPlayerSettings())\n                return;\n\n            var isDirtyBeforeDeserialize = EditorUtility.IsDirty(m_PlayerSettings);\n            if (m_PlayerSettings == null)\n                m_PlayerSettings = PlayerSettings.DeserializeFromYAMLString(m_PlayerSettingsYaml.GetYamlString());\n            else\n                UpdatePlayerSettingsObjectFromYAML();\n            s_LoadedPlayerSettings.Add(m_PlayerSettings);\n\n            if (!isDirtyBeforeDeserialize)\n                EditorUtility.ClearDirty(m_PlayerSettings);\n\n            PlayerSettings.EnsureUnityConnectSettingsEqual(m_PlayerSettings, s_GlobalPlayerSettings);\n            UpdateGlobalManagerPlayerSettings();\n        }\n\n        internal bool HasSerializedPlayerSettings()\n        {\n            return m_PlayerSettingsYaml.HasSettings();\n        }\n\n        internal void UpdateGlobalManagerPlayerSettings(bool activeWillBeRemoved = false)\n        {\n            if (BuildProfileContext.activeProfile != this)\n                return;\n\n            var playerSettings = (HasSerializedPlayerSettings() && !activeWillBeRemoved) ? m_PlayerSettings : s_GlobalPlayerSettings;\n            PlayerSettings.SetOverridePlayerSettingsInternal(playerSettings);\n        }\n\n        internal static void TrySetProjectSettingsAssetAsGlobalManagerPlayerSettings()\n        {\n            if (BuildProfileContext.activeProfile != null)\n                return;\n\n            TryLoadProjectSettingsAssetPlayerSettings();\n            if (!PlayerSettings.IsGlobalManagerPlayerSettings(s_GlobalPlayerSettings))\n                PlayerSettings.SetOverridePlayerSettingsInternal(s_GlobalPlayerSettings);\n        }\n\n        internal static bool IsDataEqualToProjectSettings(PlayerSettings targetPlayerSettings)\n        {\n            var projectSettingsYaml = PlayerSettings.SerializeAsYAMLString(s_GlobalPlayerSettings);\n            var targetSettingsYaml = PlayerSettings.SerializeAsYAMLString(targetPlayerSettings);\n            return projectSettingsYaml == targetSettingsYaml;\n        }\n\n        static void TryLoadProjectSettingsAssetPlayerSettings()\n        {\n            if (s_GlobalPlayerSettings == null)\n                s_GlobalPlayerSettings = AssetDatabase.LoadAssetAtPath<PlayerSettings>(k_ProjectSettingsAssetPath);\n        }\n\n        internal static PlayerSettings GetGlobalPlayerSettings()\n        {\n            return s_GlobalPlayerSettings;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfileQualitySettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor.Build.Profile\n{\n    [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n    sealed class BuildProfileQualitySettings : ScriptableObject\n    {\n        [SerializeField] string m_DefaultQualityLevel = string.Empty;\n        [SerializeField] string[] m_QualityLevels = Array.Empty<string>();\n\n        public string defaultQualityLevel\n        {\n            get => m_DefaultQualityLevel;\n            set => m_DefaultQualityLevel = value;\n        }\n\n        public string[] qualityLevels\n        {\n            get => m_QualityLevels;\n            set => m_QualityLevels = value;\n        }\n\n        public void Instantiate()\n        {\n            name = \"Quality Settings\";\n            hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;\n        }\n\n        public void RemoveQualityLevel(string qualityLevel)\n        {\n            var index = Array.IndexOf(qualityLevels, qualityLevel);\n            if (index == -1)\n                return;\n\n            var newQualityLevels = new string[qualityLevels.Length - 1];\n            Array.Copy(qualityLevels, 0, newQualityLevels, 0, index);\n            Array.Copy(qualityLevels, index + 1, newQualityLevels, index, qualityLevels.Length - index - 1);\n            qualityLevels = newQualityLevels;\n\n            if (defaultQualityLevel == qualityLevel)\n                defaultQualityLevel = qualityLevels.Length > 0 ? qualityLevels[0] : string.Empty;\n\n            EditorUtility.SetDirty(this);\n        }\n\n        public void RenameQualityLevel(string oldName, string newName)\n        {\n            var index = Array.IndexOf(qualityLevels, oldName);\n            if (index == -1)\n                return;\n\n            qualityLevels[index] = newName;\n\n            if (defaultQualityLevel == oldName)\n                defaultQualityLevel = newName;\n\n            EditorUtility.SetDirty(this);\n        }\n\n        public void AddQualityLevel(string qualityLevel)\n        {\n            var newQualityLevels = new string[qualityLevels.Length + 1];\n            Array.Copy(qualityLevels, 0, newQualityLevels, 0, qualityLevels.Length);\n            newQualityLevels[qualityLevels.Length] = qualityLevel;\n            qualityLevels = newQualityLevels;\n\n            EditorUtility.SetDirty(this);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfileQualitySettingsEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.UIElements;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Build.Profile\n{\n    [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n    [CustomEditor(typeof(BuildProfileQualitySettings))]\n    sealed class BuildProfileQualitySettingsEditor : Editor\n    {\n        const string k_Uxml = \"BuildProfile/UXML/BuildProfileQualitySettings.uxml\";\n        const string k_StyleSheet = \"BuildProfile/StyleSheets/BuildProfile.uss\";\n        const string k_QualitySettingsWindow = \"Project/Quality\";\n        static readonly GUIContent k_qualitySettingsWindow = EditorGUIUtility.TrTextContent(\"Quality...\");\n        static readonly string k_InvalidQualityLevelWarning =\n            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.\");\n        static readonly string k_EmptyQualitySettingsWarning =\n            L10n.Tr(\"When no Quality levels are listed, the build will take from the global list of Quality levels.\");\n        static readonly string k_SetDefaultQualityLevelMenuText = L10n.Tr(\"Set as Default\");\n\n        SerializedProperty m_QualityLevels;\n        SerializedProperty m_DefaultQualityLevel;\n        HelpBox warning;\n\n        public override VisualElement CreateInspectorGUI()\n        {\n            var root = new VisualElement();\n            var visualTree = EditorGUIUtility.LoadRequired(k_Uxml) as VisualTreeAsset;\n            var windowUss = EditorGUIUtility.LoadRequired(k_StyleSheet) as StyleSheet;\n            visualTree.CloneTree(root);\n            root.styleSheets.Add(windowUss);\n\n            m_QualityLevels = serializedObject.FindProperty(\"m_QualityLevels\");\n            m_DefaultQualityLevel = serializedObject.FindProperty(\"m_DefaultQualityLevel\");\n\n            root.Bind(serializedObject);\n            SetupQualityLevelsList(root);\n\n            return root;\n        }\n\n        void SetupQualityLevelsList(VisualElement root)\n        {\n            warning = root.Q<HelpBox>(\"invalid-quality-levels-warning-help-box\");\n            UpdateInvalidQualityLevelsWarning();\n\n            var qualityLevelsList = root.Q<ListView>(\"quality-levels\");\n            root.TrackPropertyValue(m_QualityLevels, sp => {\n                UpdateInvalidQualityLevelsWarning();\n                qualityLevelsList.RefreshItems();\n            });\n            root.TrackPropertyValue(m_DefaultQualityLevel, sp => qualityLevelsList.RefreshItems());\n\n            qualityLevelsList.makeItem = () => new QualityLevelItem(SetDefaultQualityLevelContextMenu());\n            qualityLevelsList.bindItem = (element, index) =>\n            {\n                if (m_QualityLevels.arraySize == 0 || index >= m_QualityLevels.arraySize)\n                    return;\n\n                var item = element as QualityLevelItem;\n                var qualityLevelName = m_QualityLevels.GetArrayElementAtIndex(index).stringValue;\n\n                item.text = qualityLevelName;\n                if (IsDefaultQualityLevel(qualityLevelName))\n                    item.SetDefaultIndicator(true);\n                else\n                    item.SetDefaultIndicator(false);\n            };\n            qualityLevelsList.onAdd = list =>\n            {\n                var menu = new GenericMenu();\n                var allQualityLevels = QualitySettings.names;\n                foreach (var level in allQualityLevels)\n                {\n                    if (!IsQualityLevelAdded(level))\n                        menu.AddItem(new GUIContent(level), false, () => AddQualityLevel(level));\n                }\n\n                menu.AddSeparator(string.Empty);\n                menu.AddItem(k_qualitySettingsWindow, false, () => SettingsService.OpenProjectSettings(k_QualitySettingsWindow));\n                menu.ShowAsContext();\n            };\n            qualityLevelsList.onRemove = list =>\n            {\n                RemoveQualityLevel();\n            };\n\n            void AddQualityLevel(string newLevel)\n            {\n                m_QualityLevels.InsertArrayElementAtIndex(m_QualityLevels.arraySize);\n                m_QualityLevels.GetArrayElementAtIndex(m_QualityLevels.arraySize - 1).stringValue = newLevel;\n\n                if (m_QualityLevels.arraySize == 1)\n                    m_DefaultQualityLevel.stringValue = newLevel;\n\n                serializedObject.ApplyModifiedProperties();\n            }\n\n            void RemoveQualityLevel()\n            {\n                if (m_QualityLevels.arraySize == 0)\n                    return;\n\n                var selectedIndex = qualityLevelsList.selectedIndex;\n\n                if (selectedIndex < 0 || selectedIndex >= m_QualityLevels.arraySize)\n                    selectedIndex = m_QualityLevels.arraySize - 1;\n\n                if (selectedIndex >= 0)\n                {\n                    var deletedQualityLevel = m_QualityLevels.GetArrayElementAtIndex(selectedIndex).stringValue;\n                    m_QualityLevels.DeleteArrayElementAtIndex(selectedIndex);\n\n                    if (IsDefaultQualityLevel(deletedQualityLevel))\n                        m_DefaultQualityLevel.stringValue = m_QualityLevels.arraySize > 0 ?\n                            m_QualityLevels.GetArrayElementAtIndex(0).stringValue : string.Empty;\n\n                    serializedObject.ApplyModifiedProperties();\n                }\n            }\n        }\n\n        bool IsDefaultQualityLevel(string qualityLevel) => m_DefaultQualityLevel.stringValue == qualityLevel;\n\n        bool IsQualityLevelAdded(string level)\n        {\n            for (var i = 0; i < m_QualityLevels.arraySize; i++)\n            {\n                if (m_QualityLevels.GetArrayElementAtIndex(i).stringValue == level)\n                    return true;\n            }\n\n            return false;\n        }\n\n        void UpdateInvalidQualityLevelsWarning()\n        {\n            if (m_QualityLevels.arraySize == 0)\n            {\n                warning.text = k_EmptyQualitySettingsWarning;\n                warning.style.display = DisplayStyle.Flex;\n            }\n            else if (HasInvalidQualityLevels())\n            {\n                warning.text = k_InvalidQualityLevelWarning;\n                warning.style.display = DisplayStyle.Flex;\n            }\n            else\n                warning.style.display = DisplayStyle.None;\n        }\n\n        bool HasInvalidQualityLevels()\n        {\n            var allQualityLevels = QualitySettings.names;\n            for (var i = 0; i < m_QualityLevels.arraySize; i++)\n            {\n                var level = m_QualityLevels.GetArrayElementAtIndex(i).stringValue;\n                if (Array.IndexOf(allQualityLevels, level) == -1)\n                    return true;\n            }\n\n            return false;\n        }\n\n        ContextualMenuManipulator SetDefaultQualityLevelContextMenu()\n        {\n            var menu = new ContextualMenuManipulator(evt =>\n            {\n                var selectedQualityLevel = evt.target as QualityLevelItem;\n                if (selectedQualityLevel == null)\n                    return;\n\n                evt.menu.AppendAction(k_SetDefaultQualityLevelMenuText, action =>\n                {\n                    m_DefaultQualityLevel.stringValue = selectedQualityLevel.text;\n                    serializedObject.ApplyModifiedProperties();\n                });\n            });\n\n            return menu;\n        }\n\n        public bool IsDataEqualToGlobalQualitySettings(BuildProfile profile)\n        {\n            var buildTarget = profile.buildTarget;\n            var buildTargetGroupString = BuildPipeline.GetBuildTargetGroup(buildTarget).ToString();\n\n            var globalQualityLevels = QualitySettings.GetActiveQualityLevelsForPlatform(buildTargetGroupString);\n            if (m_QualityLevels.arraySize != globalQualityLevels.Length)\n                return false;\n\n            var allQualityLevels = QualitySettings.names;\n            for (var i = 0; i < m_QualityLevels.arraySize; i++)\n            {\n                var levelIndex = globalQualityLevels[i];\n                if (m_QualityLevels.GetArrayElementAtIndex(i).stringValue != allQualityLevels[levelIndex])\n                    return false;\n            }\n\n            var globalDefaultQualityLevelIndex = QualitySettings.GetDefaultQualityForPlatform(buildTargetGroupString);\n            if (globalDefaultQualityLevelIndex != -1)\n            {\n                var globalDefaultQualityLevel = allQualityLevels[globalDefaultQualityLevelIndex];\n                if (m_DefaultQualityLevel.stringValue != globalDefaultQualityLevel)\n                    return false;\n            }\n\n            return true;\n        }\n\n        class QualityLevelItem : VisualElement\n        {\n            const string k_Uxml = \"BuildProfile/UXML/BuildProfileQualitySettingsListElement.uxml\";\n            const string k_StyleSheet = \"BuildProfile/StyleSheets/BuildProfile.uss\";\n            static readonly string k_DefaultIndicatorText = L10n.Tr(\"Default\");\n            protected readonly Label m_Text;\n            protected readonly Label m_DefaultIndicator;\n\n            internal string text\n            {\n                get => m_Text.text;\n                set => m_Text.text = value;\n            }\n\n            internal QualityLevelItem(IManipulator manipulator)\n            {\n                var uxml = EditorGUIUtility.LoadRequired(k_Uxml) as VisualTreeAsset;\n                var stylesheet = EditorGUIUtility.LoadRequired(k_StyleSheet) as StyleSheet;\n                styleSheets.Add(stylesheet);\n                uxml.CloneTree(this);\n\n                m_Text = this.Q<Label>(\"quality-level-name\");\n                m_DefaultIndicator = this.Q<Label>(\"default-quality-level-indicator\");\n                m_DefaultIndicator.text = k_DefaultIndicatorText;\n                SetDefaultIndicator(false);\n\n                this.AddManipulator(manipulator);\n            }\n\n            internal void SetDefaultIndicator(bool isDefault)\n            {\n                if (isDefault)\n                    m_DefaultIndicator.style.display = DisplayStyle.Flex;\n                else\n                    m_DefaultIndicator.style.display = DisplayStyle.None;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfileRenameOverlay.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.IO;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Build.Profile\n{\n    /// <summary>\n    /// Handles displaying tooltip view for renaming build profile\n    /// items with text field\n    /// </summary>\n    [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n    internal class BuildProfileRenameOverlay\n    {\n        static readonly string k_InvalidChars = BuildProfileModuleUtil.GetFilenameInvalidCharactersStr();\n        static readonly string k_ErrorMessage = string.Format(L10n.Tr(\"A file name can't contain any of the following characters:\\t{0}\"), k_InvalidChars);\n        static readonly string k_ErrorMessageLength = string.Format(L10n.Tr(\"Build profile name can't be longer than {0} symbols\"), BuildProfileModuleUtil.k_MaxAssetFileNameLengthWithoutExtension);\n\n        TextField m_TextField;\n        Rect? m_ErrorRect = null;\n\n        Rect errorRect\n        {\n            get\n            {\n                if (m_ErrorRect == null)\n                    m_ErrorRect = GUIUtility.GUIToScreenRect(m_TextField.worldBound);\n\n                return m_ErrorRect.Value;\n            }\n        }\n\n        public BuildProfileRenameOverlay(TextField textField)\n        {\n            m_TextField = textField;\n        }\n\n        public void OnNameChanged(string previousValue, string newValue)\n        {\n            // It's fine to call show and close tooltip on multiple frames\n            // since it only opens if not opened before. Also it only closes if\n            // not closed before\n            if (HasInvalidCharacterIndex(newValue))\n            {\n                // We can't use the text field's tooltip property since it's displayed\n                // automatically on hover. So we use the TooltipView to display the\n                // error message (same way as the RenameOverlay used for assets)\n                TooltipView.Show(k_ErrorMessage, errorRect);\n                m_TextField.SetValueWithoutNotify(previousValue);\n\n                // The cursor should be kept in place when adding an invalid character\n                var targetIndex = Mathf.Max(m_TextField.cursorIndex - 1, 0);\n                m_TextField.cursorIndex = targetIndex;\n                m_TextField.selectIndex = targetIndex;\n            }\n            else if (newValue.Length > BuildProfileModuleUtil.k_MaxAssetFileNameLengthWithoutExtension)\n            {\n                TooltipView.Show(k_ErrorMessageLength, errorRect);\n                m_TextField.SetValueWithoutNotify(previousValue);\n\n                // The cursor should be kept in place when adding too much\n                var targetIndex = Mathf.Max(m_TextField.cursorIndex - 1, 0);\n                m_TextField.cursorIndex = targetIndex;\n                m_TextField.selectIndex = targetIndex;\n            }\n            else\n            {\n                TooltipView.ForceClose();\n            }\n        }\n\n        public void OnRenameEnd()\n        {\n            // Make sure tooltip is closed\n            TooltipView.ForceClose();\n        }\n\n        bool HasInvalidCharacterIndex(string value)\n        {\n            return value.IndexOfAny(k_InvalidChars.ToCharArray()) >= 0;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfileSceneListTreeView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.SceneManagement;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.SceneManagement;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor.Build.Profile\n{\n    /// <summary>\n    /// Handles mapping the existing <see cref=\"BuildPlayerSceneTreeView\"/> component\n    /// to build profile. Classic platforms specifically target scenes stored in\n    /// <see cref=\"EditorBuildSettings\"/>.\n    /// </summary>\n    [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n    internal class BuildProfileSceneTreeView : BuildPlayerSceneTreeView\n    {\n        readonly bool m_IsEditorBuildSettingsSceneList;\n        readonly BuildProfile m_Target;\n\n        public BuildProfileSceneTreeView(TreeViewState state, BuildProfile target) : base(state)\n        {\n            showBorder = false;\n            m_Target = target;\n            m_IsEditorBuildSettingsSceneList = target == null;\n        }\n\n        /// <summary>\n        /// Exported from <see cref=\"BuildPlayerWindow\"/>.\n        /// </summary>\n        public void AddOpenScenes()\n        {\n            List<EditorBuildSettingsScene> list = new List<EditorBuildSettingsScene>(GetScenes());\n\n            bool isSceneAdded = false;\n            for (int i = 0; i < SceneManager.sceneCount; i++)\n            {\n                Scene scene = SceneManager.GetSceneAt(i);\n\n                if (EditorSceneManager.IsAuthoringScene(scene))\n                    continue;\n\n                if (scene.path.Length == 0 && !EditorSceneManager.SaveScene(scene, \"\", false))\n                    continue;\n\n                if (list.Exists(s => s.path == scene.path))\n                    continue;\n\n                GUID newGUID;\n                GUID.TryParse(scene.guid, out newGUID);\n                var buildSettingsScene = (newGUID == default(GUID)) ?\n                    new EditorBuildSettingsScene(scene.path, true) :\n                    new EditorBuildSettingsScene(newGUID, true);\n                list.Add(buildSettingsScene);\n                isSceneAdded = true;\n            }\n\n            if (!isSceneAdded)\n                return;\n\n            SetScenes(list.ToArray());\n            Reload();\n            GUIUtility.ExitGUI();\n        }\n\n        protected override EditorBuildSettingsScene[] GetScenes() => (m_IsEditorBuildSettingsSceneList)\n            ? EditorBuildSettings.GetEditorBuildSettingsSceneIgnoreProfile()\n            : m_Target.scenes;\n\n        protected override void SetScenes(EditorBuildSettingsScene[] scenes)\n        {\n            if (!m_IsEditorBuildSettingsSceneList)\n            {\n                Undo.RecordObject(m_Target, \"Scene list\");\n                m_Target.scenes = scenes;\n                EditorUtility.SetDirty(m_Target);\n                return;\n            }\n\n            // Classic platforms scene list can only be changed through this component\n            // and write data directly to EditorBuildSettings.\n            EditorBuildSettings.SetEditorBuildSettingsSceneIgnoreProfile(scenes);\n            if (BuildProfileContext.activeProfile is null)\n                EditorBuildSettings.SceneListChanged();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/BuildProfileState.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor.Build.Profile\n{\n    [VisibleToOtherModules]\n    internal enum ActionState\n    {\n        /// <summary>\n        /// Action is visible and clickable.\n        /// </summary>\n        Enabled,\n\n        /// <summary>\n        /// Action is visible and non-clickable.\n        /// </summary>\n        Disabled,\n\n        /// <summary>\n        /// Action is hidden.\n        /// </summary>\n        Hidden\n    }\n\n    [VisibleToOtherModules]\n    internal class BuildProfileWorkflowState\n    {\n        Action<BuildProfileWorkflowState> m_OnStateChanged;\n\n        public BuildProfileWorkflowState(Action<BuildProfileWorkflowState> onStateChanged)\n        {\n            this.m_OnStateChanged = onStateChanged;\n        }\n\n        /// <summary>\n        /// When set, build actions in the Build Profile Window will query the user for a build location.\n        /// </summary>\n        public bool askForBuildLocation { get; set; } = true;\n\n        /// <summary>\n        /// Name to be displayed in the build button name\n        /// </summary>\n        public string buildButtonDisplayName { get; set; } = L10n.Tr(\"Build\");\n\n        /// <summary>\n        /// Name to be displayed in the build and run button name\n        /// </summary>\n        public string buildAndRunButtonDisplayName { get; set; } = L10n.Tr(\"Build And Run\");\n\n        /// <summary>\n        /// Activate action allows a profile to be set as active profile.\n        /// </summary>\n        public ActionState activateAction { get; set; } = ActionState.Enabled;\n\n        /// <summary>\n        /// Allows invoking the Build Pipeline for the selected profile.\n        /// </summary>\n        public ActionState buildAction { get; set; } = ActionState.Enabled;\n\n        /// <summary>\n        /// Allows invoking the Build Pipeline for the selected profile with BuildAndRun flag set.\n        /// </summary>\n        public ActionState buildAndRunAction { get; set; } = ActionState.Enabled;\n\n        /// <summary>\n        /// Allows invoking of Cloud Build for the selected profile.\n        /// </summary>\n        public ActionState buildInCloudPackageAction { get; set; } = ActionState.Enabled;\n\n        /// <summary>\n        /// Additional actions shown in the Build Profile Window as generally defined by the Build Profile Extension.\n        /// </summary>\n        /// <remarks>\n        /// Primary use case is for 'Run Last Build' action from console paltforms which implement\n        /// module specific build callbacks.\n        /// </remarks>\n        public IList<(string displayName, bool isOn, Action callback, ActionState state)> additionalActions { get; set; }\n            = new List<(string, bool, Action, ActionState)>();\n\n        /// <summary>\n        /// Reprocess the current state.\n        /// </summary>\n        public void Refresh() => m_OnStateChanged?.Invoke(this);\n\n        /// <summary>\n        /// Apply the next state, OnStateChanged callback should handle reducing the\n        /// target state into the current one.\n        /// </summary>\n        public void Apply(BuildProfileWorkflowState next) => m_OnStateChanged?.Invoke(next);\n\n        /// <summary>\n        /// Merges two <see cref=\"ActionState\"/> values.\n        /// </summary>\n        public static ActionState CalculateActionState(ActionState lhs, ActionState rhs)\n        {\n            if (lhs == ActionState.Hidden || rhs == ActionState.Hidden)\n                return ActionState.Hidden;\n            if (lhs == ActionState.Disabled || rhs == ActionState.Disabled)\n                return ActionState.Disabled;\n            return ActionState.Enabled;\n        }\n\n        /// <summary>\n        /// Update the build action and the build and run action to the specified <see cref=\"ActionState\"/> and refresh.\n        /// </summary>\n        public void UpdateBuildActionStates(ActionState buildActionState, ActionState buildAndRunActionState)\n        {\n            if (buildAction == buildActionState && buildAndRunAction == buildAndRunActionState)\n                return;\n\n            buildAction = buildActionState;\n            buildAndRunAction = buildAndRunActionState;\n            Refresh();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/Events.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Analytics;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Build.Profile\n{\n    /// <summary>\n    /// Event for when building an active build profile.\n    /// </summary>\n    [AnalyticInfo(eventName: \"buildProfileBuildTime\", vendorKey: \"unity.buildprofile\")]\n    internal class BuildProfileBuildTimeEvent : IAnalytic\n    {\n        [Serializable]\n        internal struct Payload : IAnalytic.IData\n        {\n            /// <summary>\n            /// Platform ID of the target build profile.\n            /// </summary>\n            public string platformId;\n\n            /// <summary>\n            /// Platform display name of the target build profile.\n            /// </summary>\n            public string platformDisplayName;\n\n            /// <summary>\n            /// Unique identifier of the profile asset. Not available\n            /// for classic platforms.\n            /// </summary>\n            public string profileAssetGUID;\n        }\n\n        Payload m_Payload;\n\n        public BuildProfileBuildTimeEvent(Payload payload)\n        {\n            this.m_Payload = payload;\n        }\n\n        public bool TryGatherData(out IAnalytic.IData data, out Exception error)\n        {\n            error = null;\n            data = m_Payload;\n            return data != null;\n        }\n\n        [RequiredByNativeCode]\n        public static void SendBuildProfile()\n        {\n            if (!EditorUserBuildSettings.isBuildProfileAvailable)\n                return;\n\n            var profile = BuildProfile.GetActiveBuildProfile();\n            if (profile == null)\n                return;\n\n            EditorAnalytics.SendAnalytic(new BuildProfileBuildTimeEvent(new BuildProfileBuildTimeEvent.Payload\n            {\n                platformId = profile.platformId,\n                platformDisplayName = BuildProfileModuleUtil.GetClassicPlatformDisplayName(profile.platformGuid),\n                profileAssetGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(profile))\n            }));\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildProfile/SharedPlatformSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing TargetAttributes = UnityEditor.BuildTargetDiscovery.TargetAttributes;\n\nnamespace UnityEditor.Build.Profile\n{\n    [Serializable]\n    internal sealed class SharedPlatformSettings: BuildProfilePlatformSettingsBase\n    {\n        internal const string k_SettingWindowsDevicePortalAddress = \"windowsDevicePortalAddress\";\n        internal const string k_SettingWindowsDevicePortalUsername = \"windowsDevicePortalUsername\";\n        internal const string k_SettingWindowsDevicePortalPassword = \"windowsDevicePortalPassword\";\n        internal const string k_SettingForceInstallation = \"forceInstallation\";\n        internal const string k_SettingiOSXcodeBuildConfig = \"iOSXcodeBuildConfig\";\n        internal const string k_SettingSymlinkSources = \"symlinkSources\";\n        internal const string k_SettingPreferredXcode = \"preferredXcode\";\n        internal const string k_SettingSymlinkTrampoline = \"symlinkTrampoline\";\n        internal const string k_SettingRemoteDeviceInfo = \"remoteDeviceInfo\";\n        internal const string k_SettingRemoteDeviceAddress = \"remoteDeviceAddress\";\n        internal const string k_SettingRemoteDeviceUsername = \"remoteDeviceUsername\";\n        internal const string k_SettingRemoteDeviceExports = \"remoteDeviceExports\";\n        internal const string k_SettingPathOnRemoteDevice = \"pathOnRemoteDevice\";\n\n        [SerializeField] string m_WindowsDevicePortalAddress = string.Empty;\n        [SerializeField] string m_WindowsDevicePortalUsername = string.Empty;\n        string m_WindowsDevicePortalPassword = string.Empty;\n        [SerializeField] bool m_ForceInstallation = false;\n        [SerializeField] XcodeBuildConfig m_iOSXcodeBuildConfig = XcodeBuildConfig.Release;\n        [SerializeField] bool m_SymlinkSources = false;\n        [SerializeField] string m_PreferredXcode = string.Empty;\n        [SerializeField] bool m_SymlinkTrampoline = false;\n        [SerializeField] bool m_RemoteDeviceInfo = false;\n        [SerializeField] string m_RemoteDeviceAddress = string.Empty;\n        [SerializeField] string m_RemoteDeviceUsername = string.Empty;\n        [SerializeField] string m_RemoteDeviceExports = string.Empty;\n        [SerializeField] string m_PathOnRemoteDevice = string.Empty;\n\n        internal protected override bool development\n        {\n            get => base.development;\n            set\n            {\n                if (base.development != value)\n                {\n                    base.development = value;\n                    SyncSharedSettings(k_SettingDevelopment);\n                }\n            }\n        }\n\n        internal protected override bool connectProfiler\n        {\n            get => base.connectProfiler;\n            set\n            {\n                if (base.connectProfiler != value)\n                {\n                    base.connectProfiler = value;\n                    SyncSharedSettings(k_SettingConnectProfiler);\n                }\n            }\n        }\n\n        internal protected override bool buildWithDeepProfilingSupport\n        {\n            get => base.buildWithDeepProfilingSupport;\n            set\n            {\n                if (base.buildWithDeepProfilingSupport != value)\n                {\n                    base.buildWithDeepProfilingSupport = value;\n                    SyncSharedSettings(k_SettingBuildWithDeepProfilingSupport);\n                }\n            }\n        }\n\n        internal protected override bool allowDebugging\n        {\n            get => base.allowDebugging;\n            set\n            {\n                if (base.allowDebugging != value)\n                {\n                    base.allowDebugging = value;\n                    SyncSharedSettings(k_SettingAllowDebugging);\n                }\n            }\n        }\n\n        internal protected override bool waitForManagedDebugger\n        {\n            get => base.waitForManagedDebugger;\n            set\n            {\n                if (base.waitForManagedDebugger != value)\n                {\n                    base.waitForManagedDebugger = value;\n                    SyncSharedSettings(k_SettingWaitForManagedDebugger);\n                }\n            }\n        }\n\n        internal protected override int managedDebuggerFixedPort\n        {\n            get => base.managedDebuggerFixedPort;\n            set\n            {\n                if (base.managedDebuggerFixedPort != value)\n                {\n                    base.managedDebuggerFixedPort = value;\n                    SyncSharedSettings(k_SettingManagedDebuggerFixedPort);\n                }\n            }\n        }\n\n        internal protected override bool explicitNullChecks\n        {\n            get => base.explicitNullChecks;\n            set\n            {\n                if (base.explicitNullChecks != value)\n                {\n                    base.explicitNullChecks = value;\n                    SyncSharedSettings(k_SettingExplicitNullChecks);\n                }\n            }\n        }\n\n        internal protected override bool explicitDivideByZeroChecks\n        {\n            get => base.explicitDivideByZeroChecks;\n            set\n            {\n                if (base.explicitDivideByZeroChecks != value)\n                {\n                    base.explicitDivideByZeroChecks = value;\n                    SyncSharedSettings(k_SettingExplicitDivideByZeroChecks);\n                }\n            }\n        }\n\n        internal protected override bool explicitArrayBoundsChecks\n        {\n            get => base.explicitArrayBoundsChecks;\n            set\n            {\n                if (base.explicitArrayBoundsChecks != value)\n                {\n                    base.explicitArrayBoundsChecks = value;\n                    SyncSharedSettings(k_SettingExplicitArrayBoundsChecks);\n                }\n            }\n        }\n\n        internal override Compression compressionType\n        {\n            get => base.compressionType;\n            set\n            {\n                if (base.compressionType != value)\n                {\n                    base.compressionType = value;\n                    SyncSharedSettings(k_SettingCompressionType);\n                }\n            }\n        }\n\n        internal protected override bool installInBuildFolder\n        {\n            get => base.installInBuildFolder;\n            set\n            {\n                if (base.installInBuildFolder != value)\n                {\n                    base.installInBuildFolder = value;\n                    SyncSharedSettings(k_SettingInstallInBuildFolder);\n                }\n            }\n        }\n\n        public string windowsDevicePortalAddress\n        {\n            get => m_WindowsDevicePortalAddress;\n            set\n            {\n                if (m_WindowsDevicePortalAddress != value)\n                {\n                    m_WindowsDevicePortalAddress = value;\n                    SyncSharedSettings(k_SettingWindowsDevicePortalAddress);\n                }\n            }\n        }\n\n        public string windowsDevicePortalUsername\n        {\n            get =>  EditorUserBuildSettings.DecodeBase64(m_WindowsDevicePortalUsername);\n            set\n            {\n                string encodedString = EditorUserBuildSettings.EncodeBase64(value);\n\n                if (m_WindowsDevicePortalUsername != encodedString)\n                {\n                    m_WindowsDevicePortalUsername = EditorUserBuildSettings.EncodeBase64(value);\n                    SyncSharedSettings(k_SettingWindowsDevicePortalUsername);\n                }\n            }\n        }\n\n        public string windowsDevicePortalPassword\n        {\n            get => EditorUserBuildSettings.DecodeBase64(m_WindowsDevicePortalPassword);\n            set\n            {\n                string encodedString = EditorUserBuildSettings.EncodeBase64(value);\n\n                if (m_WindowsDevicePortalPassword != encodedString)\n                {\n                    m_WindowsDevicePortalPassword = encodedString;\n                    SyncSharedSettings(k_SettingWindowsDevicePortalPassword);\n                }\n            }\n        }\n\n        public bool forceInstallation\n        {\n            get => m_ForceInstallation;\n            set\n            {\n                if (m_ForceInstallation != value)\n                {\n                    m_ForceInstallation = value;\n                    SyncSharedSettings(k_SettingForceInstallation);\n                }\n            }\n        }\n\n        public XcodeBuildConfig iOSXcodeBuildConfig\n        {\n            get => m_iOSXcodeBuildConfig;\n            set\n            {\n                if (m_iOSXcodeBuildConfig != value)\n                {\n                    m_iOSXcodeBuildConfig = value;\n                    SyncSharedSettings(k_SettingiOSXcodeBuildConfig);\n                }\n            }\n        }\n\n        public bool symlinkSources\n        {\n            get => m_SymlinkSources;\n            set\n            {\n                if (m_SymlinkSources != value)\n                {\n                    m_SymlinkSources = value;\n                    SyncSharedSettings(k_SettingSymlinkSources);\n                }\n            }\n        }\n\n        public string preferredXcode\n        {\n            get => m_PreferredXcode;\n            set\n            {\n                if (m_PreferredXcode != value)\n                {\n                    m_PreferredXcode = value;\n                    SyncSharedSettings(k_SettingPreferredXcode);\n                }\n            }\n        }\n\n        public bool symlinkTrampoline\n        {\n            get => m_SymlinkTrampoline;\n            set\n            {\n                if (m_SymlinkTrampoline != value)\n                {\n                    m_SymlinkTrampoline = value;\n                    SyncSharedSettings(k_SettingSymlinkTrampoline);\n                }\n            }\n        }\n\n        public bool remoteDeviceInfo\n        {\n            get => m_RemoteDeviceInfo;\n            set\n            {\n                if (m_RemoteDeviceInfo != value)\n                {\n                    m_RemoteDeviceInfo = value;\n                    SyncSharedSettings(k_SettingRemoteDeviceInfo);\n                }\n            }\n        }\n\n        public string remoteDeviceAddress\n        {\n            get => m_RemoteDeviceAddress;\n            set\n            {\n                if (m_RemoteDeviceAddress != value)\n                {\n                    m_RemoteDeviceAddress = value;\n                    SyncSharedSettings(k_SettingRemoteDeviceAddress);\n                }\n            }\n        }\n\n        public string remoteDeviceUsername\n        {\n            get => m_RemoteDeviceUsername;\n            set\n            {\n                if (m_RemoteDeviceUsername != value)\n                {\n                    m_RemoteDeviceUsername = value;\n                    SyncSharedSettings(k_SettingRemoteDeviceUsername);\n                }\n            }\n        }\n\n        public string remoteDeviceExports\n        {\n            get => m_RemoteDeviceExports;\n            set\n            {\n                if (m_RemoteDeviceExports != value)\n                {\n                    m_RemoteDeviceExports = value;\n                    SyncSharedSettings(k_SettingRemoteDeviceExports);\n                }\n            }\n        }\n\n        public string pathOnRemoteDevice\n        {\n            get => m_PathOnRemoteDevice;\n            set\n            {\n                if (m_PathOnRemoteDevice != value)\n                {\n                    m_PathOnRemoteDevice = value;\n                    SyncSharedSettings(k_SettingPathOnRemoteDevice);\n                }\n            }\n        }\n\n        public override string GetSharedSetting(string name)\n        {\n            return name switch\n            {\n                k_SettingWindowsDevicePortalPassword => windowsDevicePortalPassword,\n                _ => null,\n            };\n        }\n\n        void SyncSharedSettings(string name)\n        {\n            var classicProfiles = BuildProfileContext.instance.classicPlatformProfiles;\n            foreach (var profile in classicProfiles)\n            {\n                var platformSettingsBase = profile.platformBuildProfile;\n                if (platformSettingsBase == null)\n                    continue;\n\n                switch (name)\n                {\n                    case k_SettingDevelopment:\n                        platformSettingsBase.development = development;\n                        break;\n                    case k_SettingConnectProfiler:\n                        platformSettingsBase.connectProfiler = connectProfiler;\n                        break;\n                    case k_SettingBuildWithDeepProfilingSupport:\n                        platformSettingsBase.buildWithDeepProfilingSupport = buildWithDeepProfilingSupport;\n                        break;\n                    case k_SettingAllowDebugging:\n                        platformSettingsBase.allowDebugging = allowDebugging;\n                        break;\n                    case k_SettingWaitForManagedDebugger:\n                        platformSettingsBase.waitForManagedDebugger = waitForManagedDebugger;\n                        break;\n                    case k_SettingManagedDebuggerFixedPort:\n                        platformSettingsBase.managedDebuggerFixedPort = managedDebuggerFixedPort;\n                        break;\n                    case k_SettingExplicitNullChecks:\n                        platformSettingsBase.explicitNullChecks = explicitNullChecks;\n                        break;\n                    case k_SettingExplicitDivideByZeroChecks:\n                        platformSettingsBase.explicitDivideByZeroChecks = explicitDivideByZeroChecks;\n                        break;\n                    case k_SettingExplicitArrayBoundsChecks:\n                        platformSettingsBase.explicitArrayBoundsChecks = explicitArrayBoundsChecks;\n                        break;\n                    case k_SettingCompressionType:\n                    {\n                        var isStandalone = BuildProfileModuleUtil.IsStandalonePlatform(profile.buildTarget);\n                        if (isStandalone)\n                        {\n                            platformSettingsBase.compressionType = compressionType;\n                        }\n                        break;\n                    }\n                    case k_SettingInstallInBuildFolder:\n                        platformSettingsBase.installInBuildFolder = installInBuildFolder;\n                        break;\n                    case k_SettingWindowsDevicePortalAddress:\n                        platformSettingsBase.SetSharedSetting(k_SettingWindowsDevicePortalAddress, windowsDevicePortalAddress);\n                        break;\n                    case k_SettingWindowsDevicePortalUsername:\n                        platformSettingsBase.SetSharedSetting(k_SettingWindowsDevicePortalUsername, windowsDevicePortalUsername);\n                        break;\n                    case k_SettingWindowsDevicePortalPassword:\n                        platformSettingsBase.SetSharedSetting(k_SettingWindowsDevicePortalPassword, windowsDevicePortalPassword);\n                        break;\n                    case k_SettingForceInstallation:\n                        platformSettingsBase.SetSharedSetting(k_SettingForceInstallation, forceInstallation.ToString().ToLower());\n                        break;\n                    case k_SettingiOSXcodeBuildConfig:\n                        platformSettingsBase.SetSharedSetting(k_SettingiOSXcodeBuildConfig, iOSXcodeBuildConfig.ToString());\n                        break;\n                    case k_SettingSymlinkSources:\n                        platformSettingsBase.SetSharedSetting(k_SettingSymlinkSources, symlinkSources.ToString().ToLower());\n                        break;\n                    case k_SettingPreferredXcode:\n                        platformSettingsBase.SetSharedSetting(k_SettingPreferredXcode, preferredXcode);\n                        break;\n                    case k_SettingSymlinkTrampoline:\n                        platformSettingsBase.SetSharedSetting(k_SettingSymlinkTrampoline, symlinkTrampoline.ToString().ToLower());\n                        break;\n                    case k_SettingRemoteDeviceInfo:\n                        platformSettingsBase.SetSharedSetting(k_SettingRemoteDeviceInfo, remoteDeviceInfo.ToString().ToLower());\n                        break;\n                    case k_SettingRemoteDeviceAddress:\n                        platformSettingsBase.SetSharedSetting(k_SettingRemoteDeviceAddress, remoteDeviceAddress);\n                        break;\n                    case k_SettingRemoteDeviceUsername:\n                        platformSettingsBase.SetSharedSetting(k_SettingRemoteDeviceUsername, remoteDeviceUsername);\n                        break;\n                    case k_SettingRemoteDeviceExports:\n                        platformSettingsBase.SetSharedSetting(k_SettingRemoteDeviceExports, remoteDeviceExports);\n                        break;\n                    case k_SettingPathOnRemoteDevice:\n                        platformSettingsBase.SetSharedSetting(k_SettingPathOnRemoteDevice, pathOnRemoteDevice);\n                        break;\n                }\n            }\n        }\n\n        // <summary>\n        // Copy shared settings to a build profile.\n        // </summary>\n        public void CopySharedSettingsToBuildProfile(BuildProfile profile)\n        {\n            if (profile == null)\n                return;\n\n            var platformSettings = profile.platformBuildProfile;\n            if (platformSettings == null)\n                return;\n\n            platformSettings.development = development;\n            platformSettings.connectProfiler = connectProfiler;\n            platformSettings.buildWithDeepProfilingSupport = buildWithDeepProfilingSupport;\n            platformSettings.allowDebugging = allowDebugging;\n            platformSettings.waitForManagedDebugger = waitForManagedDebugger;\n            platformSettings.managedDebuggerFixedPort = managedDebuggerFixedPort;\n            platformSettings.explicitNullChecks = explicitNullChecks;\n            platformSettings.explicitDivideByZeroChecks = explicitDivideByZeroChecks;\n            platformSettings.explicitArrayBoundsChecks = explicitArrayBoundsChecks;\n            if (BuildProfileModuleUtil.IsStandalonePlatform(profile.buildTarget))\n                platformSettings.compressionType = compressionType;\n            platformSettings.installInBuildFolder = installInBuildFolder;\n            platformSettings.SetSharedSetting(k_SettingWindowsDevicePortalAddress, windowsDevicePortalAddress);\n            platformSettings.SetSharedSetting(k_SettingWindowsDevicePortalUsername, windowsDevicePortalUsername);\n            platformSettings.SetSharedSetting(k_SettingWindowsDevicePortalPassword, windowsDevicePortalPassword);\n            platformSettings.SetSharedSetting(k_SettingForceInstallation, forceInstallation.ToString().ToLower());\n            platformSettings.SetSharedSetting(k_SettingiOSXcodeBuildConfig, iOSXcodeBuildConfig.ToString());\n            platformSettings.SetSharedSetting(k_SettingSymlinkSources, symlinkSources.ToString().ToLower());\n            platformSettings.SetSharedSetting(k_SettingPreferredXcode, preferredXcode);\n            platformSettings.SetSharedSetting(k_SettingSymlinkTrampoline, symlinkTrampoline.ToString().ToLower());\n            platformSettings.SetSharedSetting(k_SettingRemoteDeviceInfo, remoteDeviceInfo.ToString().ToLower());\n            platformSettings.SetSharedSetting(k_SettingRemoteDeviceAddress, remoteDeviceAddress);\n            platformSettings.SetSharedSetting(k_SettingRemoteDeviceUsername, remoteDeviceUsername);\n            platformSettings.SetSharedSetting(k_SettingRemoteDeviceExports, remoteDeviceExports);\n            platformSettings.SetSharedSetting(k_SettingPathOnRemoteDevice, pathOnRemoteDevice);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildTarget.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    // Target build platform.\n    // When adding new platform, read this first - https://confluence.hq.unity3d.com/display/DEV/Adding+new+platform\n    // When removing platform, read this first - https://confluence.hq.unity3d.com/display/DEV/Removing+platform\n    [NativeType(\"Runtime/Serialize/SerializationMetaFlags.h\")]\n    public enum BuildTarget\n    {\n        // Build an OS X standalone (universal build, with x86_64 currently supported).\n        StandaloneOSX = 2,\n\n        [System.Obsolete(\"Use StandaloneOSX instead (UnityUpgradable) -> StandaloneOSX\", true)]\n        StandaloneOSXUniversal = 3,\n\n        [System.Obsolete(\"StandaloneOSXIntel has been removed in 2017.3\")]\n        StandaloneOSXIntel = 4,\n\n        // Build a 32 bit Windows standalone.\n        StandaloneWindows = 5,\n\n        // *undocumented*\n        [System.Obsolete(\"WebPlayer has been removed in 5.4\", true)]\n        WebPlayer = 6,\n\n        // *undocumented*\n        [System.Obsolete(\"WebPlayerStreamed has been removed in 5.4\", true)]\n        WebPlayerStreamed = 7,\n\n        // Build an iOS player\n        iOS = 9,\n\n        // *undocumented*\n        [System.Obsolete(\"PS3 has been removed in >=5.5\")]\n        PS3 = 10,\n\n        // *undocumented*\n        [System.Obsolete(\"XBOX360 has been removed in 5.5\")]\n        XBOX360 = 11,\n\n        // was StandaloneBroadcom = 12,\n\n        // Build an Android .apk standalone app\n        Android = 13,\n\n        // was StandaloneGLESEmu = 14,\n        // was StandaloneGLES20Emu = 15,\n        // was NaCl = 16,\n\n        // Build a Linux standalone (i386 only).\n        [System.Obsolete(\"StandaloneLinux has been removed in 2019.2\")]\n        StandaloneLinux = 17,\n\n        // Build a Windows standalone.\n        StandaloneWindows64 = 19,\n\n        // *undocumented*\n        WebGL = 20,\n\n        // *undocumented*\n        WSAPlayer = 21,\n\n        // Build a Linux standalone (x86_64 only).\n        StandaloneLinux64 = 24,\n\n        // Build a Linux standalone (i386/x86_64 universal).\n        [System.Obsolete(\"StandaloneLinuxUniversal has been removed in 2019.2\")]\n        StandaloneLinuxUniversal = 25,\n\n        [System.Obsolete(\"Use WSAPlayer with Windows Phone 8.1 selected\")]\n        WP8Player = 26,\n\n        [System.Obsolete(\"StandaloneOSXIntel64 has been removed in 2017.3\")]\n        StandaloneOSXIntel64 = 27,\n\n        [System.Obsolete(\"BlackBerry has been removed in 5.4\")]\n        BlackBerry = 28,\n\n        [System.Obsolete(\"Tizen has been removed in 2017.3\")]\n        Tizen = 29,\n\n        /// Build a Vita Standalone\n        /// SA: BuildPipeline.BuildPlayer.\n        [System.Obsolete(\"PSP2 is no longer supported as of Unity 2018.3\")]\n        PSP2 = 30,\n\n        /// Build a PS4 Standalone\n        /// SA: BuildPipeline.BuildPlayer.\n        PS4 = 31,\n\n        /// Build a Unity PlayStation Mobile (PSM) application\n        /// SA: BuildPipeline.BuildPlayer.\n        [System.Obsolete(\"PSM has been removed in >= 5.3\")]\n        PSM = 32,\n\n        /// Build an Xbox One Standalone\n        /// SA: BuildPipeline.BuildPlayer.\n        XboxOne = 33,\n\n        [System.Obsolete(\"SamsungTV has been removed in 2017.3\")]\n        SamsungTV = 34,\n\n        /// Build a Nintendo 3DS application\n        /// SA: BuildPipeline.BuildPlayer.\n        [System.Obsolete(\"Nintendo 3DS support is unavailable since 2018.1\")]\n        N3DS = 35,\n\n        /// Build a Wii U player\n        [System.Obsolete(\"Wii U support was removed in 2018.1\")]\n        WiiU = 36,\n\n        tvOS = 37,\n\n        Switch = 38,\n\n        [System.Obsolete(\"Lumin has been removed in 2022.2\")]\n        Lumin = 39,\n\n        [System.Obsolete(\"Stadia has been removed in 2023.1\")]\n        Stadia = 40,\n\n        [System.Obsolete(\"CloudRendering is deprecated, please use LinuxHeadlessSimulation (UnityUpgradable) -> LinuxHeadlessSimulation\", false)]\n        CloudRendering = 41,\n\n        LinuxHeadlessSimulation = 41, // LinuxHeadlessSimulation intenionally set to the same as CloudRendering\n\n        [System.Obsolete(\"GameCoreScarlett is deprecated, please use GameCoreXboxSeries (UnityUpgradable) -> GameCoreXboxSeries\", false)]\n        GameCoreScarlett = 42,\n        GameCoreXboxSeries = 42, // GameCoreXboxSeries intentionally set to the same as GameCoreScarlett\n        GameCoreXboxOne = 43,\n\n        PS5 = 44,\n\n        EmbeddedLinux = 45,\n\n        QNX = 46,\n\n        VisionOS = 47,\n        \n        ReservedCFE = 48,\n\n        Kepler = 49,\n\n        // obsolete identifiers. We're using different values so that ToString() works.\n        [System.Obsolete(\"Use iOS instead (UnityUpgradable) -> iOS\", true)]\n        iPhone = -1,\n        [System.Obsolete(\"BlackBerry has been removed in 5.4\")]\n        BB10 = -1,\n        [System.Obsolete(\"Use WSAPlayer instead (UnityUpgradable) -> WSAPlayer\", true)]\n        MetroPlayer = -1,\n\n        // *undocumented*\n        NoTarget = -2,\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildTargetConverter.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing JetBrains.Annotations;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal static class BuildTargetConverter\n    {\n        [UsedImplicitly] // used by com.unity.test-framework package\n        public static RuntimePlatform? TryConvertToRuntimePlatform(BuildTarget buildTarget)\n        {\n            switch (buildTarget)\n            {\n                case BuildTarget.Android:\n                    return RuntimePlatform.Android;\n                case BuildTarget.PS4:\n                    return RuntimePlatform.PS4;\n                case BuildTarget.PS5:\n                    return RuntimePlatform.PS5;\n                case BuildTarget.StandaloneLinux64:\n                    return RuntimePlatform.LinuxPlayer;\n                case BuildTarget.LinuxHeadlessSimulation:\n                    return RuntimePlatform.LinuxPlayer;\n                case BuildTarget.StandaloneOSX:\n                    return RuntimePlatform.OSXPlayer;\n                case BuildTarget.StandaloneWindows:\n                    return RuntimePlatform.WindowsPlayer;\n                case BuildTarget.StandaloneWindows64:\n                    return RuntimePlatform.WindowsPlayer;\n                case BuildTarget.Switch:\n                    return RuntimePlatform.Switch;\n                case BuildTarget.WSAPlayer:\n                    return RuntimePlatform.WSAPlayerARM;\n                case BuildTarget.XboxOne:\n                    return RuntimePlatform.XboxOne;\n                case BuildTarget.iOS:\n                    return RuntimePlatform.IPhonePlayer;\n                case BuildTarget.tvOS:\n                    return RuntimePlatform.tvOS;\n                case BuildTarget.VisionOS:\n                    return RuntimePlatform.VisionOS;\n                case BuildTarget.WebGL:\n                    return RuntimePlatform.WebGLPlayer;\n                case BuildTarget.GameCoreXboxSeries:\n                    return RuntimePlatform.GameCoreXboxSeries;\n                case BuildTarget.GameCoreXboxOne:\n                    return RuntimePlatform.GameCoreXboxOne;\n                case BuildTarget.EmbeddedLinux:\n                    return RuntimePlatform.EmbeddedLinuxArm64;\n                case BuildTarget.QNX:\n                    return RuntimePlatform.QNXArm64;\n                default:\n                    return null;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildTargetDiscovery.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing UnityEditor.Build;\nusing UnityEditor.Utils;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing GraphicsDeviceType = UnityEngine.Rendering.GraphicsDeviceType;\nusing UnityEditor.Modules;\n\nnamespace UnityEditor\n{\n    [StaticAccessor(\"BuildTargetDiscovery::GetInstance()\", StaticAccessorType.Dot)]\n    [NativeHeader(\"Editor/Src/BuildPipeline/BuildTargetDiscovery.h\")]\n    [RequiredByNativeCode]\n    [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n    internal static class BuildTargetDiscovery\n    {\n        [Flags]\n        public enum TargetAttributes\n        {\n            None                            = 0,\n            IsDeprecated                    = (1 << 0),\n            HasIntegratedGPU                = (1 << 1),\n            IsConsole                       = (1 << 2),\n            IsX64                           = (1 << 3),\n            IsStandalonePlatform            = (1 << 4),\n            DynamicBatchingDisabled         = (1 << 5),\n            CompressedGPUSkinningDisabled   = (1 << 6),\n            UseForsythOptimizedMeshData     = (1 << 7),\n            DisableEnlighten                = (1 << 8),\n            // unused in 2023LTS: ReflectionEmitDisabled          = (1 << 9),\n            OSFontsDisabled                 = (1 << 10),\n            NoDefaultUnityFonts             = (1 << 11),\n            // removed in 2019.3: SupportsFacebook = (1 << 12),\n            WarnForMouseEvents              = (1 << 13),\n            HideInUI                        = (1 << 14),\n            GPUSkinningNotSupported         = (1 << 15),\n            StrippingNotSupported           = (1 << 16),\n            DisableNativeHDRLightmaps       = (1 << 17),\n            UsesNativeHDR                   = (1 << 18),\n            // removed: ProtectedGraphicsMem = (1 << 19),\n            IsMTRenderingDisabledByDefault  = (1 << 20),\n            ConfigurableNormalMapEncoding   = (1 << 21),\n            ConfigurableDefaultTextureCompressionFormat = (1 << 22)\n        }\n\n        [StructLayout(LayoutKind.Sequential)]\n        public struct DiscoveredTargetInfo\n        {\n            public string moduleName;\n            public string dirName;\n            public string platformDefine;\n            public string niceName;\n            public string iconName;\n            public string assemblyName;\n\n            public BuildTarget buildTargetPlatformVal;\n\n            // Build targets can have many names to identify them\n            public string[] nameList;\n\n            // Build targets can sometimes support more than one renderer\n            public int[] rendererList;\n\n            public TargetAttributes flags;\n\n            public bool HasFlag(TargetAttributes flag) { return (flags & flag) == flag; }\n        }\n\n        public static extern bool PlatformHasFlag(BuildTarget platform, TargetAttributes flag);\n\n        public static extern bool PlatformGroupHasFlag(BuildTargetGroup group, TargetAttributes flag);\n\n        public static extern DiscoveredTargetInfo[] GetBuildTargetInfoList();\n\n        internal static DiscoveredTargetInfo[] GetDerivedBuildTargetInfoList(BuildTarget target)\n        {\n            List<DiscoveredTargetInfo> discoveredTargetInfos = new();\n            var module = ModuleManager.FindPlatformSupportModule(ModuleManager.GetTargetStringFrom(target));\n            if (module is IDerivedBuildTargetProvider derivedBuildTargetProvider)\n            {\n                var derivedBuildTargets = derivedBuildTargetProvider.GetDerivedBuildTargets();\n                foreach (var derivedBuildTarget in derivedBuildTargets)\n                {\n                    if (derivedBuildTargetProvider.TryGetDiscoveredTargetInfo(derivedBuildTarget.Guid, out var discoveredTargetInfo))\n                        discoveredTargetInfos.Add(discoveredTargetInfo);\n                }\n            }\n            return discoveredTargetInfos.ToArray();\n        }\n\n        public static extern BuildTarget GetBuildTargetByName(string name);\n\n        public static extern int[] GetRenderList(BuildTarget platform);\n\n        public static extern string GetModuleNameForBuildTarget(BuildTarget platform);\n\n        public static extern string GetModuleNameForBuildTargetGroup(BuildTargetGroup group);\n\n        public static string GetPlatformProfileSuffix(BuildTarget buildTarget)\n        {\n            if (BuildTargetDiscovery.TryGetBuildTarget(buildTarget, out var iBuildTarget))\n            {\n                return iBuildTarget.RootSystemType;\n            }\n            return string.Empty;\n        }\n\n        public static bool BuildTargetSupportsRenderer(BuildPlatform platform, GraphicsDeviceType type)\n        {\n            BuildTarget buildTarget = platform.defaultTarget;\n            if (platform.namedBuildTarget == NamedBuildTarget.Standalone)\n                buildTarget = DesktopStandaloneBuildWindowExtension.GetBestStandaloneTarget(buildTarget);\n\n            foreach (int var in GetRenderList(buildTarget))\n            {\n                if ((GraphicsDeviceType)var == type)\n                    return true;\n            }\n\n            return false;\n        }\n\n        public static string GetScriptAssemblyName(DiscoveredTargetInfo btInfo)\n        {\n            return !String.IsNullOrEmpty(btInfo.assemblyName) ? btInfo.assemblyName : btInfo.nameList[0];\n        }\n\n        public static bool TryGetBuildTarget(BuildTarget platform, out IBuildTarget buildTarget)\n        {\n            buildTarget = Modules.ModuleManager.GetIBuildTarget(platform);\n            return buildTarget != null;\n        }\n\n        public static bool TryGetProperties<T>(BuildTarget platform, out T properties) where T : IPlatformProperties\n        {\n            if (TryGetBuildTarget(platform, out var buildTarget))\n            {\n                return buildTarget.TryGetProperties(out properties);\n            }\n            properties = default(T);\n            return false;\n        }\n\n        public static BuildTarget[] StandaloneBuildTargets { get; internal set; } = new BuildTarget[]\n        {\n            BuildTarget.StandaloneOSX,\n            BuildTarget.StandaloneWindows,\n            BuildTarget.StandaloneWindows64,\n            BuildTarget.StandaloneLinux64,\n        };\n\n        internal static bool IsStandalonePlatform(BuildTarget buildTarget)\n        {\n            foreach (var target in StandaloneBuildTargets)\n            {\n                if (target == buildTarget)\n                    return true;\n            }\n\n            return false;\n        }\n\n        [RequiredByNativeCode]\n        internal static bool DoesBuildTargetSupportStereoInstancingRendering(BuildTarget buildTarget)\n        {\n            if (BuildTargetDiscovery.TryGetBuildTarget(buildTarget, out var iBuildTarget))\n            {\n                return iBuildTarget.VRPlatformProperties?.SupportStereoInstancingRendering ?? false;\n            }\n            return false;\n        }\n\n        [RequiredByNativeCode]\n        internal static bool DoesBuildTargetSupportStereoMultiviewRendering(BuildTarget buildTarget)\n        {\n            if (BuildTargetDiscovery.TryGetBuildTarget(buildTarget, out var iBuildTarget))\n            {\n                return iBuildTarget.VRPlatformProperties?.SupportStereoMultiviewRendering ?? false;\n            }\n            return false;\n        }\n\n        [RequiredByNativeCode]\n        internal static bool DoesBuildTargetSupportStereo360Capture(BuildTarget buildTarget)\n        {\n            if (BuildTargetDiscovery.TryGetBuildTarget(buildTarget, out var iBuildTarget))\n            {\n                return iBuildTarget.VRPlatformProperties?.SupportStereo360Capture ?? false;\n            }\n            return false;\n        }\n\n        [RequiredByNativeCode]\n        internal static bool DoesBuildTargetSupportSinglePassStereoRendering(BuildTarget buildTarget)\n        {\n            if (BuildTargetDiscovery.TryGetBuildTarget(buildTarget, out var iBuildTarget))\n            {\n                return iBuildTarget.VRPlatformProperties?.SupportSinglePassStereoRendering ?? false;\n            }\n            return false;\n        }\n\n        [Flags]\n        enum PlatformAttributes\n        {\n            None = 0,\n            IsDeprecated = (1 << 0),\n            IsWindowsBuildTarget = (1 << 1),\n            IsWindowsArm64BuildTarget = (1 << 2),\n            IsMacBuildTarget = (1 << 3),\n            IsLinuxBuildTarget = (1 << 4),\n            IsMobileBuildTarget = (1 << 5),\n            IsNDAPlatform = (1 << 6),\n            IsHidden = (1 << 7),\n            ExternalDownloadForBuildTarget = (1 << 8),\n            IsWindowsServerBuildTarget = (1 << 9),\n            IsMacServerBuildTarget = (1 << 10),\n            IsLinuxServerBuildTarget = (1 << 11),\n            IsVisibleInPlatformBrowserOnly = (1 << 12),\n            IsDerivedBuildTarget = (1 << 13),\n        }\n        public record struct NameAndLink(string name, string linkUrl);\n\n        struct PlatformInfo\n        {\n            public string displayName = String.Empty;\n            public string downloadLinkName = String.Empty;\n            public BuildTarget buildTarget = BuildTarget.NoTarget;\n            public StandaloneBuildSubtarget subtarget = StandaloneBuildSubtarget.Default;\n            public PlatformAttributes flags = PlatformAttributes.None;\n\n            public string[] requiredPackage = new string[] {};\n            public string[] recommendedPackage = new string[] {};\n            public string description = L10n.Tr(\"\");\n            public string instructions = L10n.Tr(\"*standard install form hub\");\n            public string iconName = \"BuildSettings.Editor\";\n            public string subtitle = \"\";\n            public List<NameAndLink> nameAndLinkToShowUnderTitle = null;\n\n            // TODO: this is a workaround for onboarding instructions to fix EmbeddedLinux and QNX\n            // needs to be removed when https://jira.unity3d.com/browse/PLAT-7721 is implemented\n            public NameAndLink? temporaryLabelAndLinkForIndustrialOnboarding = null;\n\n            public PlatformInfo() {}\n\n            public bool HasFlag(PlatformAttributes flag) { return (flags & flag) == flag; }\n        }\n\n\n        static GUID EmptyGuid = new GUID(\"\");\n\n        static Dictionary<BuildTarget, GUID> s_BuildTargetToPlatformGUID = new Dictionary<BuildTarget, GUID>();\n\n        // This list should not be exposed ouside of BuildTargetDiscovery to avoid NDA spillage, provide a access function for data here instead.\n        // Changes here should be synced with the usage of\n        // BuildTargetDiscovery::HideInUI flag in [Platform]BuildTarget.cpp\n        // This list is ordered by the order in which platforms are displayed in the build profiles window (Do not change!)\n        // Changes here should be synced with kBuildTargetUIOrder[] in BuildTargetDiscovery.cpp\n        // Name changes here must be reflected in the platform [PLATFORM]BuildTarget.cs and [Platform]BuildTarget.cpp respective DisplayName, niceName and iconName\n        static readonly Dictionary<GUID, PlatformInfo> allPlatforms = new Dictionary<GUID, PlatformInfo>\n        {\n            // first standalones and servers\n            {\n                new(\"4e3c793746204150860bf175a9a41a05\"),\n                new PlatformInfo\n                {\n                    displayName = \"Windows\",\n                    downloadLinkName = \"Windows-Mono\",\n                    description = L10n.Tr(\"Access an ecosystem of Unity-supported game development solutions to reach the vast PC gamer audience around the world. Leverage DirectX 12 and inline ray tracing support for cutting edge visual fidelity. Use the Microsoft GDK packages to further unlock the Microsoft gaming ecosystem.\"),\n                    subtarget = StandaloneBuildSubtarget.Player,\n                    buildTarget = BuildTarget.StandaloneWindows64,\n                    iconName = \"BuildSettings.Windows\",\n                    flags = PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget\n                }\n            },\n            {\n                new(\"0d2129357eac403d8b359c2dcbf82502\"),\n                new PlatformInfo\n                {\n                    displayName = \"macOS\",\n                    downloadLinkName = \"Mac-Mono\",\n                    description = L10n.Tr(\"Take advantage of Unity’s support for the latest Mac devices with M series chips. The Mac Standalone platform also supports Intel-based Mac devices.\"),\n                    subtarget = StandaloneBuildSubtarget.Player,\n                    buildTarget = BuildTarget.StandaloneOSX,\n                    iconName = \"BuildSettings.OSX\",\n                    flags = PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget\n                }\n            },\n            {\n                new(\"cb423bfea44b4d658edb8bc5d91a3024\"),\n                new PlatformInfo\n                {\n                    displayName = \"Linux\",\n                    downloadLinkName = \"Linux-Mono\",\n                    description = L10n.Tr(\"Leverage Unity’s platform support for Linux, including an ecosystem of game development solutions for creators of all skill levels.\"),\n                    subtarget = StandaloneBuildSubtarget.Player,\n                    buildTarget = BuildTarget.StandaloneLinux64,\n                    iconName = \"BuildSettings.Linux\",\n                    flags = PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget\n                }\n            },\n            // Server platforms\n            {\n                new(\"8d1e1bca926649cba89d37a4c66e8b3d\"),\n                new PlatformInfo\n                {\n                    displayName = \"Windows Server\",\n                    downloadLinkName = \"Windows-Server\",\n                    description = L10n.Tr(\"Benefit from Unity’s support for developing games and applications on the Dedicated Windows Server platform, including publishing multiplayer games.\"),\n                    buildTarget = BuildTarget.StandaloneWindows64,\n                    subtarget = StandaloneBuildSubtarget.Server,\n                    iconName = \"BuildSettings.DedicatedServer\",\n                    requiredPackage = new string[]{L10n.Tr(\"com.unity.dedicated-server\") },\n                    flags = PlatformAttributes.IsWindowsServerBuildTarget | PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget\n                }\n            },\n            {\n                new(\"8659dec1db6b4fac86149f99f2fa4291\"),\n                new PlatformInfo\n                {\n                    displayName = \"macOS Server\",\n                    downloadLinkName = \"Mac-Server\",\n                    description = L10n.Tr(\"Benefit from Unity’s support for developing games and applications on the Dedicated Mac Server platform, including publishing multiplayer games.\"),\n                    buildTarget = BuildTarget.StandaloneOSX,\n                    subtarget = StandaloneBuildSubtarget.Server,\n                    iconName = \"BuildSettings.DedicatedServer\",\n                    requiredPackage = new string[]{L10n.Tr(\"com.unity.dedicated-server\") },\n                    flags = PlatformAttributes.IsMacServerBuildTarget | PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget\n                }\n            },\n            {\n                new(\"91d938b35f6f4798811e41f2acf9377f\"),\n                new PlatformInfo\n                {\n                    displayName = \"Linux Server\",\n                    downloadLinkName = \"Linux-Server\",\n                    description =  L10n.Tr(\"Benefit from Unity’s support for developing games and applications on the Dedicated Linux Server platform, including publishing multiplayer games.\"),\n                    buildTarget = BuildTarget.StandaloneLinux64,\n                    subtarget = StandaloneBuildSubtarget.Server,\n                    iconName = \"BuildSettings.DedicatedServer\",\n                    requiredPackage = new string[]{L10n.Tr(\"com.unity.dedicated-server\") },\n                    flags = PlatformAttributes.IsLinuxServerBuildTarget | PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget\n                }\n            },\n            // then mobile\n            {\n                new(\"b9b35072a6f44c2e863f17467ea3dc13\"),\n                new PlatformInfo\n                {\n                    displayName = \"Android™\",\n                    downloadLinkName = \"Android\",\n                    description = L10n.Tr(\"Android is a large and varied device ecosystem with over 3bn active devices. Benefit from Unity’s longstanding and wide-ranging resources for the entire development lifecycle for Android games. This includes tools and services for rapid iteration, performance optimization, player engagement, and revenue growth.\"),\n                    buildTarget = BuildTarget.Android,\n                    nameAndLinkToShowUnderTitle = new List<NameAndLink>\n                    {\n                        new NameAndLink{name = L10n.Tr(\"Unity Android Manual\"),  linkUrl = $\"https://docs.unity3d.com/{Help.GetShortReleaseVersion()}/Documentation/Manual/android.html\"},\n                    },\n                    iconName = \"BuildSettings.Android\",\n                    flags = PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget\n                }\n            },\n            {\n                new(\"ad48d16a66894befa4d8181998c3cb09\"),\n                new PlatformInfo\n                {\n                    displayName = \"iOS\",\n                    downloadLinkName = \"iOS\",\n                    description =  L10n.Tr(\"Benefit from Unity’s longstanding and wide-ranging resources for the entire development lifecycle for iOS games. This includes tools and services for rapid iteration, performance optimization, player engagement, and revenue growth.\"),\n                    buildTarget = BuildTarget.iOS,\n                    iconName = \"BuildSettings.iPhone\",\n                    flags = PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget\n                }\n            },\n            // then consoles\n            {\n                new(\"5d4f9b64eeb74b18a2de0de6f0c36931\"),\n                new PlatformInfo\n                {\n                    displayName = \"PlayStation®4\",\n                    downloadLinkName = \"PS4\",\n                    instructions = L10n.Tr(\"This platform is not available to download from the Unity website, contact the platform holder directly to learn more.\"),\n                    description = L10n.Tr(\"Create your game with a comprehensive development platform for PlayStation®4. Discover powerful creation tools to take your PlayStation game to the next level.\"),\n                    buildTarget = BuildTarget.PS4,\n                    nameAndLinkToShowUnderTitle = new List<NameAndLink>\n                    {\n                        new NameAndLink{ name = L10n.Tr(\"Register as a PlayStation developer\"), linkUrl = \"https://partners.playstation.net/\"}\n                    },\n                    iconName = \"BuildSettings.PS4\",\n                    flags = PlatformAttributes.ExternalDownloadForBuildTarget | PlatformAttributes.IsNDAPlatform | PlatformAttributes.IsWindowsBuildTarget\n                }\n            },\n            {\n                new(\"e30a9c34166844499a56eaa4ed115c44\"),\n                new PlatformInfo\n                {\n                    displayName = \"PlayStation®5\",\n                    downloadLinkName = \"PS5\",\n                    instructions = L10n.Tr(\"This platform is not available to download from the Unity website, contact the platform holder directly to learn more.\"),\n                    description = L10n.Tr(\"Create your game with a comprehensive development platform for PlayStation®5. Discover powerful creation tools to take your PlayStation game to the next level.\"),\n                    buildTarget = BuildTarget.PS5,\n                    nameAndLinkToShowUnderTitle = new List<NameAndLink>\n                    {\n                        new NameAndLink{name = L10n.Tr(\"Register as a PlayStation developer\"), linkUrl = \"https://partners.playstation.net/\"}\n                    },\n                    iconName = \"BuildSettings.PS5\",\n                    flags = PlatformAttributes.ExternalDownloadForBuildTarget | PlatformAttributes.IsNDAPlatform | PlatformAttributes.IsWindowsBuildTarget\n                }\n            },\n            {\n                new(\"c9f186cd3d594a1496bca1860359f842\"),\n                new PlatformInfo\n                {\n                    displayName = \"Xbox Series X|S\",\n                    downloadLinkName = \"GameCoreScarlett\",\n                    instructions = L10n.Tr(\"This platform is not available to download from the Unity website, contact the platform holder directly to learn more.\"),\n                    description = L10n.Tr(\"Attract players around the world on the latest generation of Xbox: Xbox Series X|S. Push the graphical fidelity of your games with inline ray tracing, all while maintaining performance with the latest optimizations for DirectX 12.\"),\n                    buildTarget = BuildTarget.GameCoreXboxSeries,\n                    nameAndLinkToShowUnderTitle = new List<NameAndLink>\n                    {\n                         new NameAndLink{name = L10n.Tr(\"Register as an Xbox developer\"), linkUrl = \"https://www.xbox.com/en-US/developers/id\"}\n                    },\n                    iconName = \"BuildSettings.GameCoreScarlett\",\n                    flags = PlatformAttributes.IsHidden | PlatformAttributes.IsWindowsBuildTarget\n                }\n            },\n            {\n                new(\"a6f1094111614cba85f0508bf9778843\"),\n                new PlatformInfo\n                {\n                    displayName = \"Xbox One\",\n                    downloadLinkName = \"GameCoreXboxOne\",\n                    instructions = L10n.Tr(\"This platform is not available to download from the Unity website, contact the platform holder directly to learn more.\"),\n                    description = L10n.Tr(\"Attract and engage over 50 million players around the world on Xbox One.\"),\n                    buildTarget = BuildTarget.GameCoreXboxOne,\n                    nameAndLinkToShowUnderTitle = new List<NameAndLink>\n                    {\n                        new NameAndLink{name = L10n.Tr(\"Register as an Xbox developer\"), linkUrl =\"https://www.xbox.com/en-US/developers/id\"}\n                    },\n                    iconName = \"BuildSettings.GameCoreXboxOne\",\n                    flags = PlatformAttributes.ExternalDownloadForBuildTarget | PlatformAttributes.IsHidden | PlatformAttributes.IsWindowsBuildTarget\n                }\n            },\n            {\n                new(\"08d61a9cdfb840119d9bea5588e2f338\"),\n                new PlatformInfo\n                {\n                    displayName = \"Nintendo Switch™\",\n                    downloadLinkName = \"Switch\",\n                    instructions = L10n.Tr(\"This platform is not available to download from the Unity website, contact the platform holder directly to learn more.\"),\n                    description = L10n.Tr(\"Bring your game to Nintendo Switch™ with Unity’s optimized platform support as well as a dedicated forum.\"),\n                    buildTarget = BuildTarget.Switch,\n                    nameAndLinkToShowUnderTitle = new List<NameAndLink>\n                    {\n                        new NameAndLink{name = L10n.Tr(\"Register as a Nintendo developer\"), linkUrl = \"http://developer.nintendo.com\"}\n                    },\n                    iconName = \"BuildSettings.Switch\",\n                    flags = PlatformAttributes.IsHidden | PlatformAttributes.IsNDAPlatform | PlatformAttributes.IsWindowsBuildTarget\n                }\n            },\n            {\n               new(\"25a09d2ed10c42f789b61d99b4d9bf83\"),\n               new PlatformInfo\n               {\n                    displayName = \"ReservedCFE\",\n                    instructions = L10n.Tr(\"This platform is not available to download from the Unity website, contact the platform holder directly to learn more.\"),\n                    description =  L10n.Tr(\"Benefit from Unity’s support for developing games and applications on this platform\"),\n                    buildTarget = BuildTarget.ReservedCFE,\n                    flags = PlatformAttributes.ExternalDownloadForBuildTarget | PlatformAttributes.IsHidden | PlatformAttributes.IsNDAPlatform | PlatformAttributes.IsWindowsBuildTarget\n                }\n            },\n            // then others\n            {\n                new(\"84a3bb9e7420477f885e98145999eb20\"),\n                new PlatformInfo\n                {\n                    displayName = \"Web\",\n                    downloadLinkName = \"WebGL\",\n                    description =  L10n.Tr(\"Leverage Unity’s web solutions to offer your players near-instant access to their favorite games, no matter where they want to play. Our web platform includes support for desktop and mobile browsers.\"),\n                    buildTarget = BuildTarget.WebGL,\n                    iconName = \"BuildSettings.WebGL\",\n                    flags = PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget\n                }\n            },\n            {\n               new(\"d80a96315208455a9ba318d697981cfc\"),\n               new PlatformInfo\n               {\n                    displayName = \"Facebook Instant Games\",\n                    downloadLinkName = \"WebGL\",\n                    description = L10n.Tr(\n                        \"Build for Facebook Instant Games to take advantage of the extensive user base and social features within the Facebook and Messenger app. \" +\n                        \"This platform offers default settings for both mobile and desktop builds, along with optimization tools and a streamlined publishing process.\"\n                    ),\n                    subtitle = \"From <color=\\\"white\\\"><b>Meta</b></color>\",\n                    buildTarget = BuildTarget.WebGL,\n                    iconName = \"BuildSettings.Facebook\",\n                    requiredPackage = new string[]{\"com.unity.meta-instant-games-sdk\"},\n                    recommendedPackage = new string[]{\"com.unity.web.stripping-tool\"},\n                    flags = PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget | PlatformAttributes.IsVisibleInPlatformBrowserOnly | PlatformAttributes.IsDerivedBuildTarget\n                }\n            },\n            {\n               new(\"80657fe557de4d17822398b3a01b8c9e\"),\n               new PlatformInfo\n               {\n                    displayName = \"Meta Quest\",\n                    downloadLinkName = \"Android\",\n                    description = L10n.Tr(\n                        \"Take advantage of Unity's support for Meta Quest platforms and leverage Unity's extensive XR tools and frameworks. \" +\n                        \"This platform offers default project settings and configurations for a streamlined publishing process.\"\n                    ),\n                    buildTarget = BuildTarget.Android,\n                    iconName = \"BuildSettings.Meta\",\n                    requiredPackage = new string[]{L10n.Tr(\"com.unity.xr.openxr\") },\n                    flags = PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget | PlatformAttributes.IsDerivedBuildTarget\n                }\n            },\n            {\n                new(\"a71389c8cc8e4edc99d30db86d62ee8f\"),\n                new PlatformInfo\n                {\n                    displayName = \"Android XR\",\n                    downloadLinkName = \"Android\",\n                    description = L10n.Tr(\"Android XR provides a strong foundation for high-performance, immersive experiences. OpenXR conformance ensures support for widely used XR extensions, while cross-platform tools provide a familiar development experience. The Android XR build profile offers pre-configured settings tailored for Android XR development, making getting started fast and easy.\"),\n                    buildTarget = BuildTarget.Android,\n                    iconName = \"BuildSettings.Android\",\n                    requiredPackage = new string[]{L10n.Tr(\"com.unity.xr.androidxr-openxr\") },\n                    flags = PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget | PlatformAttributes.IsDerivedBuildTarget\n                }\n            },\n            {\n                new(\"32e92b6f4db44fadb869cafb8184d021\"),\n                new PlatformInfo\n                {\n                    displayName = \"Universal Windows Platform\",\n                    downloadLinkName = \"Universal-Windows-Platform\",\n                    description = L10n.Tr(\"Benefit from Unity’s runtime support for UWP, ensuring you’re able to reach as many users as possible in the Microsoft ecosystem. UWP is used for HoloLens and Windows 10 and 11 devices, among others.\"),\n                    buildTarget = BuildTarget.WSAPlayer,\n                    iconName = \"BuildSettings.Metro\",\n                    flags = PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget\n                }\n            },\n            {\n                new(\"81e4f4c492fd4311bbf5b0b88a28c737\"),\n                new PlatformInfo\n                {\n                    displayName = \"tvOS\",\n                    downloadLinkName = \"AppleTV\",\n                    description = L10n.Tr(\"Choose tvOS if you’re planning to develop applications for Apple TVs. tvOS is based on the iOS operating system and has many similar frameworks, technologies, and concepts.\"),\n                    buildTarget = BuildTarget.tvOS,\n                    iconName = \"BuildSettings.tvOS\",\n                    flags = PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget\n                }\n            },\n            {\n                new(\"53916e6f1f7240d992977ffa2322b047\"),\n                new PlatformInfo\n                {\n                    displayName = \"visionOS\",\n                    downloadLinkName = \"VisionOS\",\n                    description = L10n.Tr(\"Build for Apple Vision Pro today.\\nBe among the first to create games, lifestyle experiences, and industry apps for Apple's all-new platform. Familiar frameworks and tools. Get ready to design and build an entirely new universe of apps and games for Apple Vision Pro.\"),\n                    buildTarget = BuildTarget.VisionOS,\n                    iconName = \"BuildSettings.visionOS\",\n                    flags = PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget\n                }\n            },\n            {\n                new(\"f188349a68c441ec9e3eb4c6f59abd41\"),\n                new PlatformInfo\n                {\n                    displayName = \"Linux Headless Simulation\",\n                    downloadLinkName = \"CloudRendering\",\n                    description = L10n.Tr(\"Utilize Unity’s headless Linux editor to deploy high-fidelity simulations at scale in cloud environments.\"),\n                    buildTarget = BuildTarget.LinuxHeadlessSimulation,\n                    iconName = \"BuildSettings.LinuxHeadlessSimulation\",\n                    flags = PlatformAttributes.IsHidden | PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget\n                }\n            },\n            {\n                new(\"f1d7bec2fd7f42f481c66ef512f47845\"),\n                new PlatformInfo\n                {\n                    displayName = \"Embedded Linux\",\n                    downloadLinkName = \"EmbeddedLinux\",\n                    instructions = L10n.Tr(\"As the Embedded Linux platform for Unity is not yet available to download from the Unity website, contact your Account Manager or the Unity Sales team to get access.\"),\n                    description = L10n.Tr(\"Choose Embedded Linux, a compact version of Linux, if you are planning to build applications for embedded devices and appliances.\"),\n                    buildTarget = BuildTarget.EmbeddedLinux,\n                    iconName = \"BuildSettings.EmbeddedLinux\",\n\n                    // TODO: this is a workaround for onboarding instructions to fix EmbeddedLinux and QNX\n                    // needs to be removed when https://jira.unity3d.com/browse/PLAT-7721 is implemented\n                    temporaryLabelAndLinkForIndustrialOnboarding = new NameAndLink{name = L10n.Tr(\"No Embedded Linux module loaded. If you are a current Embedded Platforms customer, contact your Account Manager for download instructions.\\nFor information on access and licensing, contact the Unity Sales team.\"), linkUrl = \"https://create.unity.com/unity-for-industries?sfcid=7015G000000KFqdQAG&sflsa=2023-04-na-dg-hmi-solutions-contact-us\"},\n\n                    flags = PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget\n                }\n            },\n            {\n                new(\"99ef95e1e9b048fa9628d7eed27a8646\"),\n                new PlatformInfo\n                {\n                    displayName = \"QNX®\",\n                    downloadLinkName = \"QNX\",\n                    instructions = L10n.Tr(\"As the QNX platform for Unity is not yet available to download from the Unity website, contact your Account Manager or the Unity Sales team to get access.\"),\n                    description = L10n.Tr(\"Deploy the Unity runtime to automotive and other embedded systems utilizing the Blackberry® QNX® real-time operating system.\"),\n                    buildTarget = BuildTarget.QNX,\n                    iconName = \"BuildSettings.QNX\",\n\n                    // TODO: this is a workaround for onboarding instructions to fix EmbeddedLinux and QNX\n                    // needs to be removed when https://jira.unity3d.com/browse/PLAT-7721 is implemented\n                    temporaryLabelAndLinkForIndustrialOnboarding = new NameAndLink{name = L10n.Tr(\"No QNX® module loaded. If you are a current Embedded Platforms customer, contact your Account Manager for download instructions.\\nFor information on access and licensing, contact the Unity Sales team.\"), linkUrl = \"https://create.unity.com/unity-for-industries?sfcid=7015G000000KFqdQAG&sflsa=2023-04-na-dg-hmi-solutions-contact-us\"},\n\n                    flags = PlatformAttributes.IsWindowsBuildTarget | PlatformAttributes.IsWindowsArm64BuildTarget | PlatformAttributes.IsLinuxBuildTarget | PlatformAttributes.IsMacBuildTarget\n                }\n            },\n            {\n               new(\"f8c7649c24f344129a97cf9854e2d582\"),\n               new PlatformInfo\n               {\n                    displayName = \"Kepler\",\n                    buildTarget = BuildTarget.Kepler,\n                    iconName = \"BuildSettings.EmbeddedLinux\",\n                    flags = PlatformAttributes.IsMacBuildTarget | PlatformAttributes.IsNDAPlatform | PlatformAttributes.IsHidden\n                }\n            }\n        };\n\n        static readonly Dictionary<GUID, bool> k_PlatformInstalledData = new();\n\n\n        static BuildTargetDiscovery()\n        {\n            PreloadBuildPlatformInstalledData();\n        }\n        public static IEnumerable<GUID> GetAllPlatforms() => allPlatforms.Keys;\n\n        /// <summary>\n        /// Get the platform GUID corresponding to the NamedBuildTarget and BuildTarget.\n        /// </summary>\n        /// <param name=\"namedBuildTarget\">The NamedBuildTarget to get the platform GUID for.</param>\n        /// <param name=\"buildTarget\">The BuildTarget to get the platform GUID for.</param>\n        /// <returns>The platform GUID. Derived platform GUID when the active platform is a derived platform. Base platform GUID otherwise.</returns>\n        public static GUID GetGUIDFromBuildTarget(NamedBuildTarget namedBuildTarget, BuildTarget buildTarget)\n        {\n            if (TryGetServerGUIDFromBuildTarget(namedBuildTarget, buildTarget, out var value))\n                return value;\n\n            return GetGUIDFromBuildTarget(buildTarget);\n        }\n\n        /// <summary>\n        /// Get the platform GUID corresponding to the BuildTarget. Note this method does not work with the server platforms.\n        /// Use the namedBuildTarget overload of <see cref=\"BuildTargetDiscovery.GetGUIDFromBuildTarget\"/> for server platforms.\n        /// </summary>\n        /// <param name=\"buildTarget\">The BuildTarget to get the platform GUID for.</param>\n        /// <returns>The platform GUID. Derived platform GUID when the active platform is a derived platform. Base platform GUID otherwise.</returns>\n        public static GUID GetGUIDFromBuildTarget(BuildTarget buildTarget)\n        {\n            if (s_BuildTargetToPlatformGUID.TryGetValue(buildTarget, out GUID value))\n            {\n                var module = ModuleManager.FindPlatformSupportModule(value);\n                if (module != null && module is IDerivedBuildTargetProvider)\n                    return module.PlatformBuildTarget.Guid;\n                else\n                    return value;\n            }\n\n            return EmptyGuid;\n        }\n\n        internal static bool TryGetServerGUIDFromBuildTarget(NamedBuildTarget namedBuildTarget, BuildTarget buildTarget, out GUID result)\n        {\n            result = EmptyGuid;\n\n            if (namedBuildTarget == NamedBuildTarget.Server)\n            {\n                foreach (var platform in allPlatforms)\n                {\n                    if(platform.Value.subtarget == StandaloneBuildSubtarget.Server)\n                    {\n                        if((buildTarget == BuildTarget.StandaloneWindows || buildTarget == BuildTarget.StandaloneWindows64) && platform.Value.HasFlag(PlatformAttributes.IsWindowsServerBuildTarget))\n                            result = platform.Key;\n                        else if(buildTarget == BuildTarget.StandaloneLinux64 && platform.Value.HasFlag(PlatformAttributes.IsLinuxServerBuildTarget))\n                            result = platform.Key;\n                        else if(buildTarget == BuildTarget.StandaloneOSX && platform.Value.HasFlag(PlatformAttributes.IsMacServerBuildTarget))\n                            result = platform.Key;\n                    }\n                }\n            }\n            return !result.Empty();\n        }\n\n        internal static GUID GetBasePlatformGUIDFromBuildTarget(NamedBuildTarget namedBuildTarget, BuildTarget buildTarget)\n        {\n            if (TryGetServerGUIDFromBuildTarget(namedBuildTarget, buildTarget, out var value))\n                return value;\n\n            if (s_BuildTargetToPlatformGUID.TryGetValue(buildTarget, out GUID guid))\n                return guid;\n\n            return EmptyGuid;\n        }\n\n        /// <summary>\n        /// Get the base platform GUID given a platform GUID.\n        /// </summary>\n        /// <param name=\"platformGuid\">The platform GUID to get the base platform GUID for.</param>\n        /// <returns>The base platform GUID. If the platform is not a derived platform, the same GUID is returned.</returns>\n        internal static GUID GetBasePlatformGUID(GUID platformGuid)\n        {\n            if (!allPlatforms.TryGetValue(platformGuid, out PlatformInfo platformInfo))\n                return EmptyGuid;\n\n            if (!platformInfo.HasFlag(PlatformAttributes.IsDerivedBuildTarget))\n                return platformGuid;\n\n            if (s_BuildTargetToPlatformGUID.TryGetValue(platformInfo.buildTarget, out GUID basePlatformGuid))\n                return basePlatformGuid;\n\n            return EmptyGuid;\n        }\n\n        public static (BuildTarget, StandaloneBuildSubtarget) GetBuildTargetAndSubtargetFromGUID(GUID guid)\n        {\n            if(allPlatforms.TryGetValue(guid,out PlatformInfo platformInfo))\n                return (platformInfo.buildTarget, platformInfo.subtarget);\n\n            return (BuildTarget.NoTarget, StandaloneBuildSubtarget.Default);\n        }\n\n        static void PreloadBuildPlatformInstalledData()\n        {\n            foreach (var platform in allPlatforms)\n            {\n                // Capture BuildTarget to GUID mapping for all platforms.\n                // Considers that StandaloneWindows and StandaloneWindows64 are the same platform.\n                if (platform.Value.buildTarget != BuildTarget.StandaloneWindows\n                    && platform.Value.subtarget != StandaloneBuildSubtarget.Server\n                    && !platform.Value.HasFlag(PlatformAttributes.IsDerivedBuildTarget))\n                {\n                    s_BuildTargetToPlatformGUID.Add(platform.Value.buildTarget, platform.Key);\n                    if (platform.Value.buildTarget == BuildTarget.StandaloneWindows64)\n                        s_BuildTargetToPlatformGUID.Add(BuildTarget.StandaloneWindows, platform.Key);\n                }\n\n                var playbackEngineDirectory = BuildPipeline.GetPlaybackEngineDirectory(platform.Value.buildTarget, BuildOptions.None, false);\n\n                if (string.IsNullOrEmpty(playbackEngineDirectory))\n                {\n                    k_PlatformInstalledData.Add(platform.Key, false);\n                    continue;\n                }\n\n                if (!IsStandalonePlatform(platform.Value.buildTarget))\n                {\n                    k_PlatformInstalledData.Add(platform.Key, true);\n                    continue;\n                }\n\n                bool isInstalled = false;\n                if (platform.Value.HasFlag(PlatformAttributes.IsWindowsServerBuildTarget) ||\n                    platform.Value.HasFlag(PlatformAttributes.IsLinuxServerBuildTarget) ||\n                    platform.Value.HasFlag(PlatformAttributes.IsMacServerBuildTarget))\n                    isInstalled = BuildPipeline.IsServerBuildPlatformSupported(platform.Value.buildTarget);\n                else\n                    isInstalled = true;\n\n                k_PlatformInstalledData.Add(platform.Key, isInstalled);\n            }\n        }\n\n        [System.Obsolete(\"BuildPlatformIsInstalled(BuildTarget) is obsolete. Use BuildPlatformIsInstalled(IBuildTarget) instead.\", false)]\n        public static bool BuildPlatformIsInstalled(BuildTarget platform) => BuildPlatformIsInstalled(GetGUIDFromBuildTarget(platform));\n\n        public static bool BuildPlatformIsInstalled(IBuildTarget platform) => BuildPlatformIsInstalled(platform.Guid);\n\n        public static bool BuildPlatformIsInstalled(GUID platformGuid)\n        {\n            if (k_PlatformInstalledData.TryGetValue(platformGuid, out bool isInstalled))\n                return isInstalled;\n\n            return false;\n        }\n\n        [System.Obsolete(\"BuildPlatformIsAvailableOnHostPlatform(BuildTarget) is obsolete. Use BuildPlatformIsAvailableOnHostPlatform(IBuildTarget) instead.\", false)]\n        public static bool BuildPlatformIsAvailableOnHostPlatform(BuildTarget platform, UnityEngine.OperatingSystemFamily hostPlatform) => BuildPlatformIsAvailableOnHostPlatform(GetGUIDFromBuildTarget(platform), hostPlatform);\n        public static bool BuildPlatformIsAvailableOnHostPlatform(IBuildTarget platform, UnityEngine.OperatingSystemFamily hostPlatform) => BuildPlatformIsAvailableOnHostPlatform(platform.Guid, hostPlatform);\n\n        public static bool BuildPlatformIsAvailableOnHostPlatform(GUID guid, UnityEngine.OperatingSystemFamily hostPlatform)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo))\n            {\n                if (hostPlatform == UnityEngine.OperatingSystemFamily.Windows && IsWindowsArm64Architecture() && platformInfo.HasFlag(PlatformAttributes.IsWindowsArm64BuildTarget))\n                    return true;\n                if (hostPlatform == UnityEngine.OperatingSystemFamily.Windows && platformInfo.HasFlag(PlatformAttributes.IsWindowsBuildTarget))\n                    return true;\n                else if (hostPlatform == UnityEngine.OperatingSystemFamily.MacOSX && platformInfo.HasFlag(PlatformAttributes.IsMacBuildTarget))\n                    return true;\n                else if (hostPlatform == UnityEngine.OperatingSystemFamily.Linux && platformInfo.HasFlag(PlatformAttributes.IsLinuxBuildTarget))\n                    return true;\n            }\n\n            return false;\n        }\n\n        static bool IsWindowsArm64Architecture()\n        {\n            // Based on WindowsUtility.GetHostOSArchitecture() in platform dependent code\n            // We can't use RuntimeInformation.OSArchitecture because it doesn't work on emulations\n            var architecture = Environment.GetEnvironmentVariable(\"PROCESSOR_ARCHITECTURE\", EnvironmentVariableTarget.Machine);\n            if (string.IsNullOrEmpty(architecture))\n                return false;\n\n            architecture = architecture.ToLowerInvariant();\n            return architecture.Contains(\"arm64\") || architecture.Contains(\"aarch64\");\n        }\n\n        [System.Obsolete(\"BuildPlatformCanBeInstalledWithHub(BuildTarget) is obsolete. Use BuildPlatformCanBeInstalledWithHub(IBuildTarget) instead.\", false)]\n        public static bool BuildPlatformCanBeInstalledWithHub(BuildTarget platform) => BuildPlatformCanBeInstalledWithHub(GetGUIDFromBuildTarget(platform));\n\n        public static bool BuildPlatformCanBeInstalledWithHub(IBuildTarget platform) => BuildPlatformCanBeInstalledWithHub(platform.Guid);\n\n        public static bool BuildPlatformCanBeInstalledWithHub(GUID guid)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo) && platformInfo.HasFlag(PlatformAttributes.ExternalDownloadForBuildTarget))\n                return false;\n\n            return true;\n        }\n\n        [System.Obsolete(\"BuildPlatformIsUnderNDA(BuildTarget) is obsolete. Use BuildPlatformIsUnderNDA(IBuildTarget) instead.\", false)]\n\n        public static bool BuildPlatformIsUnderNDA(BuildTarget platform) => BuildPlatformIsUnderNDA(GetGUIDFromBuildTarget(platform));\n\n        public static bool BuildPlatformIsUnderNDA(IBuildTarget platform) => BuildPlatformIsUnderNDA(platform.Guid);\n\n        public static bool BuildPlatformIsUnderNDA(GUID guid)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo) && platformInfo.HasFlag(PlatformAttributes.IsNDAPlatform))\n                return true;\n\n            return false;\n        }\n\n        [System.Obsolete(\"BuildPlatformIsHiddenInUI(BuildTarget) is obsolete. Use BuildPlatformIsHiddenInUI(IBuildTarget) instead.\", false)]\n        public static bool BuildPlatformIsHiddenInUI(BuildTarget platform) => BuildPlatformIsHiddenInUI(GetGUIDFromBuildTarget(platform));\n\n        public static bool BuildPlatformIsHiddenInUI(IBuildTarget platform) => BuildPlatformIsHiddenInUI(platform.Guid);\n\n        public static bool BuildPlatformIsHiddenInUI(GUID guid)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo) && platformInfo.HasFlag(PlatformAttributes.IsHidden))\n                return true;\n\n            return false;\n        }\n\n        internal static bool BuildPlatformIsDerivedPlatform(GUID guid)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo) && platformInfo.HasFlag(PlatformAttributes.IsDerivedBuildTarget))\n                return true;\n\n            return false;\n        }\n\n        [System.Obsolete(\"BuildPlatformRecommendeddPackages(BuildTarget) is obsolete. Use BuildPlatformRecommendedPackages(IBuildTarget) instead.\", false)]\n        public static string[] BuildPlatformRecommendedPackages(BuildTarget platform) => BuildPlatformRecommendedPackages(GetGUIDFromBuildTarget(platform));\n\n        public static string[] BuildPlatformRecommendedPackages(IBuildTarget platform) => BuildPlatformRecommendedPackages(platform.Guid);\n\n        public static string[] BuildPlatformRecommendedPackages(GUID guid)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo))\n                    return platformInfo.recommendedPackage;\n\n            return Array.Empty<string>();\n        }\n\n        public static string[] BuildPlatformRequiredPackages(IBuildTarget platform) => BuildPlatformRequiredPackages(platform.Guid);\n\n        public static string[] BuildPlatformRequiredPackages(GUID guid)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo))\n                return platformInfo.requiredPackage;\n\n            return Array.Empty<string>();\n        }\n\n        [System.Obsolete(\"BuildPlatformDescription(BuildTarget) is obsolete. Use BuildPlatformDescription(IBuildTarget) instead.\", false)]\n\n        public static string BuildPlatformDescription(BuildTarget platform) => BuildPlatformDescription(GetGUIDFromBuildTarget(platform));\n\n        public static string BuildPlatformDescription(IBuildTarget platform) => BuildPlatformDescription(platform.Guid);\n\n        public static string BuildPlatformDescription(GUID guid)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo))\n                return platformInfo.description;\n\n            return string.Empty;\n        }\n\n        public static List<NameAndLink> BuildPlatformNameLinkList(GUID guid)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo))\n                return platformInfo.nameAndLinkToShowUnderTitle;\n\n            return null;\n        }\n\n        // TODO: this is a workaround for onboarding instructions to fix EmbeddedLinux and QNX\n        // needs to be removed when https://jira.unity3d.com/browse/PLAT-7721 is implemented\n        public static bool BuildPlatformTryGetCustomInstallLinkAndText(GUID guid, out string url, out string text)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo))\n            {\n                var nameAndLink = platformInfo.temporaryLabelAndLinkForIndustrialOnboarding;\n                if (nameAndLink != null)\n                {\n                    url = nameAndLink.Value.linkUrl;\n                    text = nameAndLink.Value.name;\n                    return true;\n                }\n            }\n            url = string.Empty;\n            text = string.Empty;\n            return false;\n        }\n\n        [System.Obsolete(\"BuildPlatformOnboardingInstructions(BuildTarget) is obsolete. Use BuildPlatformOnboardingInstructions(IBuildTarget) instead.\", false)]\n        public static string BuildPlatformOnboardingInstructions(BuildTarget platform) => BuildPlatformOnboardingInstructions(GetGUIDFromBuildTarget(platform));\n\n        public static string BuildPlatformOnboardingInstructions(IBuildTarget platform) => BuildPlatformOnboardingInstructions(platform.Guid);\n\n        public static string BuildPlatformOnboardingInstructions(GUID guid)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo))\n                return platformInfo.instructions;\n\n            return string.Empty;\n        }\n\n        [System.Obsolete(\"BuildPlatformDisplayName(BuildTarget) is obsolete. Use BuildPlatformDisplayName(IBuildTarget) instead.\", false)]\n        public static string BuildPlatformDisplayName(BuildTarget platform) => BuildPlatformDisplayName(GetGUIDFromBuildTarget(platform));\n\n        public static string BuildPlatformDisplayName(IBuildTarget platform) => BuildPlatformDisplayName(platform.Guid);\n\n        public static string BuildPlatformDisplayName(GUID guid)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo))\n                return platformInfo.displayName;\n\n            return string.Empty;\n        }\n\n        [System.Obsolete(\"BuildPlatformDisplayName(NamedBuildTarget, BuildTarget) is obsolete. Use BuildPlatformDisplayName(IBuildTarget) instead.\", false)]\n        public static string BuildPlatformDisplayName(NamedBuildTarget namedBuildTarget, BuildTarget buildTarget) => BuildPlatformDisplayName(GetGUIDFromBuildTarget(namedBuildTarget, buildTarget));\n\n        public static string BuildPlatformDownloadLinkName(GUID guid)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo))\n                return platformInfo.downloadLinkName;\n\n            return string.Empty;\n        }\n\n        [System.Obsolete(\"BuildPlatformIconName(BuildTarget) is obsolete. Use BuildPlatformIconName(IBuildTarget) instead.\", false)]\n        public static string BuildPlatformIconName(BuildTarget platform) => BuildPlatformIconName(GetGUIDFromBuildTarget(platform));\n\n        public static string BuildPlatformIconName(IBuildTarget platform) => BuildPlatformIconName(platform.Guid);\n\n        public static string BuildPlatformIconName(GUID guid)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo))\n                return platformInfo.iconName;\n\n            return string.Empty;\n        }\n\n        public static bool BuildPlatformIsVisibleInPlatformBrowserOnly(GUID guid)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo) && platformInfo.HasFlag(PlatformAttributes.IsVisibleInPlatformBrowserOnly))\n                return true;\n\n            return false;\n        }\n\n        public static string BuildPlatformSubtitle(GUID guid)\n        {\n            if (allPlatforms.TryGetValue(guid, out PlatformInfo platformInfo))\n                return platformInfo.subtitle;\n\n            return string.Empty;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/BuildTargetGroup.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\nusing System;\n\nnamespace UnityEditor\n{\n    // Build target group.\n    // ADD_NEW_PLATFORM_HERE\n    [NativeType(Header = \"Editor/Src/BuildPipeline/BuildTargetPlatformSpecific.h\")]\n    public enum BuildTargetGroup\n    {\n        // Unknown target.\n        Unknown = 0,\n\n        // PC (Windows, Mac, Linux).\n        Standalone = 1,\n\n        //*undocumented*\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"WebPlayer was removed in 5.4, consider using WebGL\", true)]\n        WebPlayer = 2,\n\n        // Apple iOS target.\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"Use iOS instead (UnityUpgradable) -> iOS\", true)]\n        iPhone = 4,\n\n        iOS = 4,\n\n        // *undocumented*\n        [Obsolete(\"PS3 has been removed in >=5.5\")]\n        PS3 = 5,\n\n        // *undocumented*\n        [Obsolete(\"XBOX360 has been removed in 5.5\")]\n        XBOX360 = 6,\n\n        // Android target.\n        Android = 7,\n\n        // was Broadcom = 8,\n        // was GLESEmu = 9,\n        // was GLES20Emu = 10,\n        // was NaCl = 11,\n\n        WebGL = 13,\n\n        WSA = 14,\n\n        //*undocumented*\n        [Obsolete(\"Use WSA instead\")]\n        Metro = 14,\n\n        [Obsolete(\"Use WSA instead\")]\n        WP8 = 15,\n\n        //*undocumented*\n        [Obsolete(\"BlackBerry has been removed as of 5.4\")]\n        BlackBerry = 16,\n\n        [System.Obsolete(\"Tizen has been removed in 2017.3\")]\n        Tizen = 17,\n\n        /// Sony Playstation Vita target.\n        [System.Obsolete(\"PSP2 is no longer supported as of Unity 2018.3\")]\n        PSP2 = 18,\n\n        /// Sony Playstation 4 target.\n        PS4 = 19,\n\n        /// Unity Playstation Mobile target.\n        [Obsolete(\"PSM has been removed in >= 5.3\")]\n        PSM = 20,\n\n        /// Xbox One target.\n        XboxOne = 21,\n\n        [Obsolete(\"SamsungTV has been removed as of 2017.3\")]\n        SamsungTV = 22,\n\n        /// Nintendo 3DS target.\n        [System.Obsolete(\"Nintendo 3DS support is unavailable since 2018.1\")]\n        N3DS = 23,\n\n        [Obsolete(\"Wii U support was removed in 2018.1\")]\n        WiiU = 24,\n\n        tvOS = 25,\n\n        [Obsolete(\"Facebook support was removed in 2019.3\")]\n        Facebook = 26,\n\n        Switch = 27,\n\n        [Obsolete(\"Lumin has been removed in 2022.2\")]\n        Lumin = 28,\n\n        [Obsolete(\"Stadia has been removed in 2023.1\")]\n        Stadia = 29,\n\n        [System.Obsolete(\"CloudRendering is deprecated, please use LinuxHeadlessSimulation (UnityUpgradable) -> LinuxHeadlessSimulation\", false)]\n        CloudRendering = 30,\n        LinuxHeadlessSimulation = 30,\n\n        [System.Obsolete(\"GameCoreScarlett is deprecated, please use GameCoreXboxSeries (UnityUpgradable) -> GameCoreXboxSeries\", false)]\n        GameCoreScarlett = 31,\n        GameCoreXboxSeries = 31, // GameCoreXboxSeries intentionally set to the same as GameCoreScarlett\n        GameCoreXboxOne = 32,\n\n        PS5 = 33,\n\n        EmbeddedLinux = 34,\n\n        QNX = 35,\n\n        VisionOS = 36,\n        \n        ReservedCFE = 37,\n\n        Kepler = 38,\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CSPreProcess.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Diagnostics;\nusing System.IO;\nusing System;\nusing System.Linq;\nusing System.Text;\nusing UnityEditor.Scripting.Compilers;\nusing UnityEngine;\nusing UnityEditor.Modules;\nusing UnityEngine.Scripting;\nusing UnityEditorInternal;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal class ManagedEditorCodeRebuilder\n    {\n        private static readonly char[] kNewlineChars = new[] { '\\r', '\\n' };\n\n        [RequiredByNativeCode]\n        static bool Run(bool includeModules)\n        {\n            int exitcode;\n            var messages = ParseResults(GetOutputStream(GetJamStartInfo(includeModules), out exitcode));\n            const int logIdentifierForUnityEditorCompilationMessages = 2345;\n            UnityEngine.Debug.RemoveLogEntriesByIdentifier(logIdentifierForUnityEditorCompilationMessages);\n            foreach (var message in messages)\n            {\n                UnityEngine.Debug.LogCompilerMessage(message.message, message.file, message.line, message.column, true, message.type == CompilerMessageType.Error, logIdentifierForUnityEditorCompilationMessages, 0);\n            }\n\n            return exitcode == 0;\n        }\n\n        private static ProcessStartInfo GetJamStartInfo(bool includeModules)\n        {\n            StringBuilder moduleArgs = new StringBuilder();\n            moduleArgs.Append(\"jam.pl LiveReloadableEditorAssemblies \" + InternalEditorUtility.GetBuildSystemVariationArgs());\n            if (includeModules)\n            {\n                foreach (string target in ModuleManager.GetJamTargets())\n                    moduleArgs.Append(\" \").Append(target);\n            }\n\n            var psi = new ProcessStartInfo\n            {\n                WorkingDirectory = Unsupported.GetBaseUnityDeveloperFolder(),\n                RedirectStandardOutput = true,\n                RedirectStandardError = false,\n                //The only reason jam.pl exists is that I cannot figure out how to call jam.bat, or jam.exe directly. magic.\n                Arguments = moduleArgs.ToString(),\n                FileName = \"perl\",\n            };\n\n            var path = Environment.GetEnvironmentVariable(\"PATH\") ?? \"\";\n            // on macOS the typical mercurial path might not be in our environment variable, so add it for executing jam\n            if (Application.platform == RuntimePlatform.OSXEditor)\n            {\n                var localBin = \"/usr/local/bin\";\n                if (!path.Contains(localBin))\n                    path = $\"{path}:{localBin}\";\n            }\n            psi.EnvironmentVariables[\"PATH\"] = path;\n\n            return psi;\n        }\n\n        private static CompilerMessage[] ParseResults(string text)\n        {\n            Console.Write(text);\n            var lines = text.Split(kNewlineChars, StringSplitOptions.RemoveEmptyEntries);\n            var prefix = Unsupported.GetBaseUnityDeveloperFolder();\n\n            var msgs = new MicrosoftCSharpCompilerOutputParser().Parse(lines, false).ToList();\n            for (var index = 0; index < msgs.Count; index++)\n            {\n                var msg = msgs[index];\n                msg.file = Path.Combine(prefix, msg.file);\n                msgs[index] = msg;\n            }\n            return msgs.ToArray();\n        }\n\n        private static string GetOutputStream(ProcessStartInfo startInfo, out int exitCode)\n        {\n            startInfo.UseShellExecute = false;\n            startInfo.CreateNoWindow = true;\n            var p = new Process { StartInfo = startInfo };\n\n            // Read data asynchronously\n            var sbStandardOut = new StringBuilder();\n            var sbStandardError = new StringBuilder();\n            p.OutputDataReceived += (sender, data) => sbStandardOut.AppendLine(data.Data);\n            p.ErrorDataReceived += (sender, data) => sbStandardError.AppendLine(data.Data);\n            p.Start();\n            if (startInfo.RedirectStandardError)\n                p.BeginErrorReadLine();\n            else\n                p.BeginOutputReadLine();\n\n            // Wain until process is done\n            p.WaitForExit();\n\n            var output = startInfo.RedirectStandardError ? sbStandardError.ToString() : sbStandardOut.ToString();\n            exitCode = p.ExitCode;\n            return output;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Callbacks.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute;\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    [RequiredByNativeCode]\n    public abstract partial class CallbackOrderAttribute : Attribute\n    {\n        protected int m_CallbackOrder;\n        internal int callbackOrder { get {return m_CallbackOrder; } }\n    }\n\n    [RequiredByNativeCode]\n    [System.Obsolete(\"PostProcessAttribute has been renamed to CallbackOrderAttribute.\")]\n    public abstract partial class PostProcessAttribute : CallbackOrderAttribute\n    {\n        [System.Obsolete(\"PostProcessAttribute has been renamed. Use m_CallbackOrder of CallbackOrderAttribute.\")]\n        protected int m_PostprocessOrder;\n\n        [System.Obsolete(\"PostProcessAttribute has been renamed. Use callbackOrder of CallbackOrderAttribute.\")]\n        internal int GetPostprocessOrder { get {return m_PostprocessOrder; } }\n    }\n\n    namespace Callbacks\n    {\n        internal sealed partial class RegisterPluginsAttribute : CallbackOrderAttribute\n        {\n            public RegisterPluginsAttribute() { m_CallbackOrder = 1; }\n            public RegisterPluginsAttribute(int callbackOrder) { m_CallbackOrder = callbackOrder; }\n\n            [RequiredSignature]\n            static IEnumerable<PluginDesc> Signature(BuildTarget target) { throw new InvalidOperationException(); }\n        }\n\n        [RequiredByNativeCode]\n        public sealed partial class PostProcessBuildAttribute : CallbackOrderAttribute\n        {\n            public PostProcessBuildAttribute() { m_CallbackOrder = 1; }\n            public PostProcessBuildAttribute(int callbackOrder) { m_CallbackOrder = callbackOrder; }\n\n            [RequiredSignature]\n            static void Signature(BuildTarget target, string pathToBuiltProject) { throw new InvalidOperationException(); }\n        }\n\n        [RequiredByNativeCode]\n        public sealed partial class PostProcessSceneAttribute : CallbackOrderAttribute\n        {\n            private int m_version;\n\n            public PostProcessSceneAttribute() { m_CallbackOrder = 1; m_version = 0; }\n\n            public PostProcessSceneAttribute(int callbackOrder) { m_CallbackOrder = callbackOrder; m_version = 0; }\n\n            public PostProcessSceneAttribute(int callbackOrder, int version) { m_CallbackOrder = callbackOrder; m_version = version; }\n\n            [RequiredByNativeCode]\n            internal int GetVersion() => m_version;\n\n            [RequiredSignature]\n            static void Signature() { throw new InvalidOperationException(); }\n        }\n\n        [RequiredByNativeCode]\n        public sealed partial class DidReloadScripts : CallbackOrderAttribute\n        {\n            public DidReloadScripts() { m_CallbackOrder = 1; }\n\n            public DidReloadScripts(int callbackOrder) { m_CallbackOrder = callbackOrder; }\n\n            [RequiredSignature]\n            static void Signature() { throw new InvalidOperationException(); }\n        }\n\n        // Native version in Editor/Src/EditorHelper.h\n        public enum OnOpenAssetAttributeMode\n        {\n            Execute,\n            Validate\n        }\n\n        // Add this attribute to a static method to get a callback for opening an asset inside Unity before trying to open it with an external tool\n        [RequiredByNativeCode]\n        public sealed partial class OnOpenAssetAttribute : CallbackOrderAttribute\n        {\n            OnOpenAssetAttributeMode m_AttributeMode;\n\n            public OnOpenAssetAttribute() : this(OnOpenAssetAttributeMode.Execute) {}\n            public OnOpenAssetAttribute(OnOpenAssetAttributeMode attributeMode) : this(1, attributeMode) {}\n            public OnOpenAssetAttribute(int callbackOrder) : this(callbackOrder, OnOpenAssetAttributeMode.Execute) {}\n            public OnOpenAssetAttribute(int callbackOrder, OnOpenAssetAttributeMode attributeMode) { m_CallbackOrder = callbackOrder; m_AttributeMode = attributeMode; }\n\n            [RequiredSignature]\n            static bool Signature(int instanceID) { throw new InvalidOperationException(); }\n\n            [RequiredSignature]\n            static bool SignatureLine(int instanceID, int line) { throw new InvalidOperationException(); }\n\n            [RequiredSignature]\n            static bool SignatureLineColumn(int instanceID, int line, int column) { throw new InvalidOperationException(); }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Camera/BuiltinBakedReflectionSystem.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Assertions;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing System.Collections.Generic;\n\nnamespace UnityEditor.Experimental.Rendering\n{\n    [NativeHeader(\"Editor/Src/Camera/BuiltinBakedReflectionSystem.h\")]\n    [NativeHeader(\"Editor/Src/Camera/SceneStateHash.h\")]\n    [StructLayout(LayoutKind.Sequential)]\n    [RequiredByNativeCode]\n    class BuiltinBakedReflectionSystem : IScriptableBakedReflectionSystem\n    {\n        IntPtr m_Ptr = IntPtr.Zero;\n        IScriptableBakedReflectionSystemStageNotifier m_Handle;\n\n        public int stageCount { get { return 3; } }\n\n        [NativeName(\"StateHashes\")]\n        extern public Hash128[] stateHashes\n        {\n            get;\n        }\n\n        bool disposed { get { return m_Ptr == IntPtr.Zero; } }\n\n        BuiltinBakedReflectionSystem()\n        {\n            m_Ptr = Internal_GetPtr();\n        }\n\n        ~BuiltinBakedReflectionSystem()\n        {\n            Dispose(false);\n        }\n\n        public void Tick(SceneStateHash dependencies, IScriptableBakedReflectionSystemStageNotifier handle)\n        {\n            if (disposed)\n                throw new ObjectDisposedException(\"BuiltinBakedReflectionSystem\");\n\n            m_Handle = handle;\n            Assert.IsNotNull(m_Handle);\n\n            Internal_Tick(dependencies);\n        }\n\n        public void SynchronizeReflectionProbes()\n        {\n            if (disposed)\n                throw new ObjectDisposedException(\"BuiltinBakedReflectionSystem\");\n\n            Internal_SynchronizeReflectionProbes();\n        }\n\n        public void Clear()\n        {\n            if (disposed)\n                throw new ObjectDisposedException(\"BuiltinBakedReflectionSystem\");\n\n            Internal_Clear();\n        }\n\n        public bool BakeAllReflectionProbes()\n        {\n            if (disposed)\n                throw new ObjectDisposedException(\"BuiltinBakedReflectionSystem\");\n\n            return Internal_BakeAllReflectionProbes();\n        }\n\n        public void Cancel()\n        {\n            // Cancel is empty on purpose\n            // We need to have this callback on the C# side as it is the only way the C# implementation\n            // is notified when the user cancelled the bake\n        }\n\n        public void Dispose()\n        {\n            Dispose(true);\n        }\n\n        void Dispose(bool disposing)\n        {\n            m_Ptr = IntPtr.Zero;\n        }\n\n        [RequiredByNativeCode]\n        static BuiltinBakedReflectionSystem Internal_BuiltinBakedReflectionSystem_New()\n        {\n            var instance = new BuiltinBakedReflectionSystem();\n            instance.Internal_SetPtr(instance);\n            return instance;\n        }\n\n        [RequiredByNativeCode]\n        void Internal_BuiltinBakedReflectionSystem_EnterStage(int stage, string progressMessage, float progress)\n        {\n            Assert.IsNotNull(m_Handle);\n\n            m_Handle.EnterStage(stage, progressMessage, progress);\n        }\n\n        [RequiredByNativeCode]\n        void Internal_BuiltinBakedReflectionSystem_ExitStage(int stage)\n        {\n            Assert.IsNotNull(m_Handle);\n\n            m_Handle.ExitStage(stage);\n        }\n\n        [RequiredByNativeCode]\n        void Internal_BuiltinBakedReflectionSystem_SetIsDone(bool isDone)\n        {\n            Assert.IsNotNull(m_Handle);\n\n            m_Handle.SetIsDone(isDone);\n        }\n\n        [NativeMethod(\"Get\")]\n        static extern IntPtr Internal_GetPtr();\n\n        extern void Internal_Tick(SceneStateHash dependencies);\n        extern void Internal_SynchronizeReflectionProbes();\n        extern void Internal_Clear();\n        extern void Internal_SetPtr([Unmarshalled] BuiltinBakedReflectionSystem ptr);\n        extern bool Internal_BakeAllReflectionProbes();\n\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(BuiltinBakedReflectionSystem system) => system.m_Ptr;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Camera/CameraProjectionCache.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public struct CameraProjectionCache\n    {\n        Matrix4x4 m_WorldToClip;\n        Rect m_Viewport;\n        float m_ScreenHeight;\n\n        public CameraProjectionCache(Camera camera)\n        {\n            m_WorldToClip = camera.projectionMatrix * camera.worldToCameraMatrix;\n            m_Viewport = camera.pixelRect;\n            m_ScreenHeight = GUIClip.visibleRect.height * EditorGUIUtility.pixelsPerPoint;\n        }\n\n        public Vector2 WorldToScreenPoint(Vector3 worldPoint)\n        {\n            Vector3 clip = m_WorldToClip.MultiplyPoint(worldPoint);\n\n            return new Vector2(\n                m_Viewport.x + (1.0f + clip.x) * m_Viewport.width * 0.5f,\n                m_Viewport.y + (1.0f + clip.y) * m_Viewport.height * 0.5f);\n        }\n\n        public Vector2 WorldToGUIPoint(Vector3 worldPoint)\n        {\n            return ScreenToGUIPoint(WorldToScreenPoint(worldPoint));\n        }\n\n        public Vector2 GUIToScreenPoint(Vector2 guiPoint)\n        {\n            var pixels = EditorGUIUtility.PointsToPixels(guiPoint);\n            pixels.y = m_ScreenHeight - pixels.y;\n            return pixels;\n        }\n\n        public Vector2 ScreenToGUIPoint(Vector2 screenPoint)\n        {\n            screenPoint.y = m_ScreenHeight - screenPoint.y;\n            return GUIClip.Clip(EditorGUIUtility.PixelsToPoints(screenPoint));\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Camera/EditorCameraUtils.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing Unity.Collections;\nusing Unity.Collections.LowLevel.Unsafe;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Internal;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Rendering\n{\n    [NativeHeader(\"Editor/Src/Camera/EditorCameraUtils.h\")]\n    [RequiredByNativeCode]\n    public static class EditorCameraUtils\n    {\n        public static bool RenderToCubemap(this Camera camera, Texture target, int faceMask, StaticEditorFlags culledFlags)\n            => RenderToCubemapImpl(camera, target, faceMask, culledFlags) == 1;\n\n        public static unsafe void GetRenderersFilteringResults(ReadOnlySpan<int> rendererIDs, Span<bool> results)\n        {\n            if (rendererIDs.Length != results.Length)\n                throw new ArgumentException(\"rendererIDs and results NativeArrays don't match in length.\");\n\n            GetRenderersFilteringResultsImpl(rendererIDs, results);\n        }\n\n        public static unsafe void GetRenderersHiddenResultBits(ReadOnlySpan<int> rendererIDs, Span<ulong> resultBits)\n        {\n            const int kBitsPerChunkCount = sizeof(ulong) * 8;\n\n            int resultBitsLengthExpected = (rendererIDs.Length + kBitsPerChunkCount - 1) / kBitsPerChunkCount;\n\n            if (resultBitsLengthExpected != resultBits.Length)\n                throw new ArgumentException(\"Unexpected resultBits Span length. The expected length of resultBits Span should be equal to the formula: (rendererIDs.Length + 63) / 64\");\n\n            GetRenderersHiddenResultBitsImpl(rendererIDs, resultBits);\n        }\n\n        [FreeFunction(\"EditorCameraUtilsScripting::RenderToCubemap\")]\n        static extern int RenderToCubemapImpl(Camera camera, Texture target, [DefaultValue(\"63\")] int faceMask, StaticEditorFlags culledFlags);\n\n        [FreeFunction(\"EditorCameraUtilsScripting::GetRenderersFilteringResults\")]\n        static extern unsafe void GetRenderersFilteringResultsImpl(ReadOnlySpan<int> rendererIDs, Span<bool> results);\n\n        [FreeFunction(\"EditorCameraUtilsScripting::GetRenderersHiddenResultBits\")]\n        static extern unsafe void GetRenderersHiddenResultBitsImpl(ReadOnlySpan<int> rendererIDs, Span<ulong> resultBits);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Camera/IScriptableBakedReflectionSystem.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor.Experimental.Rendering\n{\n    public interface IScriptableBakedReflectionSystem : IDisposable\n    {\n        int stageCount { get; }\n        Hash128[] stateHashes { get; }\n\n        void Tick(SceneStateHash sceneStateHash, IScriptableBakedReflectionSystemStageNotifier handle);\n        void SynchronizeReflectionProbes();\n        void Clear();\n        void Cancel();\n        bool BakeAllReflectionProbes();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Camera/IScriptableBakedReflectionSystemStageNotifier.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor.Experimental.Rendering\n{\n    public interface IScriptableBakedReflectionSystemStageNotifier\n    {\n        void EnterStage(int stage, string progressMessage, float progress);\n        void ExitStage(int stage);\n\n        void SetIsDone(bool isDone);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Camera/SceneStateHash.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Experimental.Rendering\n{\n    [RequiredByNativeCode]\n    public struct SceneStateHash : IEquatable<SceneStateHash>\n    {\n        Hash128 m_SceneObjectsHash;\n        Hash128 m_SkySettingsHash;\n        Hash128 m_AmbientProbeHash;\n\n        public Hash128 sceneObjectsHash => m_SceneObjectsHash;\n        public Hash128 skySettingsHash => m_SkySettingsHash;\n        public Hash128 ambientProbeHash => m_AmbientProbeHash;\n\n        public SceneStateHash(\n            Hash128 sceneObjectsHash,\n            Hash128 skySettingsHash,\n            Hash128 ambientProbeHash\n        )\n        {\n            m_SceneObjectsHash = sceneObjectsHash;\n            m_SkySettingsHash = skySettingsHash;\n            m_AmbientProbeHash = ambientProbeHash;\n        }\n\n        public bool Equals(SceneStateHash other)\n        {\n            return sceneObjectsHash.Equals(other.sceneObjectsHash)\n                && skySettingsHash.Equals(other.skySettingsHash)\n                && ambientProbeHash.Equals(other.ambientProbeHash);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n                return false;\n            return obj is SceneStateHash\n                && Equals((SceneStateHash)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            var h = new Hash128();\n            unsafe\n            {\n                fixed(Hash128* ptr = &m_SceneObjectsHash) h.Append(ptr, (ulong)sizeof(Hash128));\n                fixed(Hash128* ptr = &m_SkySettingsHash) h.Append(ptr, (ulong)sizeof(Hash128));\n                fixed(Hash128* ptr = &m_AmbientProbeHash) h.Append(ptr, (ulong)sizeof(Hash128));\n            }\n            return h.GetHashCode();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Camera/ScriptableBakedReflectionSystem.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor.Experimental.Rendering\n{\n    public abstract class ScriptableBakedReflectionSystem : IScriptableBakedReflectionSystem\n    {\n        public int stageCount { get; }\n\n        public Hash128[] stateHashes { get; protected set; }\n\n        protected ScriptableBakedReflectionSystem(int stageCount)\n        {\n            this.stageCount = stageCount;\n        }\n\n        public virtual void Tick(SceneStateHash sceneStateHash, IScriptableBakedReflectionSystemStageNotifier handle) {}\n        public virtual void SynchronizeReflectionProbes() {}\n        public virtual void Clear() {}\n        public virtual void Cancel() {}\n        public virtual bool BakeAllReflectionProbes() { return false; }\n\n        protected virtual void Dispose(bool disposing) {}\n\n        void IDisposable.Dispose()\n        {\n            Dispose(true);\n            GC.SuppressFinalize(this);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Camera/ScriptableBakedReflectionSystemSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing JetBrains.Annotations;\nusing UnityEngine;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Experimental.Rendering\n{\n    [RequiredByNativeCode]\n    public static class ScriptableBakedReflectionSystemSettings\n    {\n        public static IScriptableBakedReflectionSystem system\n        {\n            get { return Internal_ScriptableBakedReflectionSystemSettings_system; }\n            set { Internal_ScriptableBakedReflectionSystemSettings_system = value; }\n        }\n        static IScriptableBakedReflectionSystem Internal_ScriptableBakedReflectionSystemSettings_system\n        {\n            [RequiredByNativeCode] get { return s_Instance?.implementation; }\n            [RequiredByNativeCode] set\n            {\n                if (s_Instance == null)\n                {\n                    Console.WriteLine(\"[WARNING] ScriptableBakedReflectionSystemWrapper instance must be initialized from CPP before InitializeOnLoad\");\n                    return;\n                }\n\n                if (value == null || value.Equals(null))\n                {\n                    Debug.LogError(\"'null' cannot be assigned to ScriptableBakedReflectionSystemSettings.system\");\n                    return;\n                }\n\n                // We always allow the BuiltinBakedReflectionSystem, it is set by Unity on domain reload\n                // However, we issue a warning when multiple different IScriptableBakedReflectionSystem have been assigned.\n                if (!(system is BuiltinBakedReflectionSystem)\n                    && !(value is BuiltinBakedReflectionSystem)\n                    && system != value)\n                    Debug.LogWarningFormat(\"ScriptableBakedReflectionSystemSettings.system is assigned more than once. Only a the last instance will be used. (Last instance {0}, New instance {1})\", system, value);\n\n                if (s_Instance.implementation != value)\n                {\n                    if (s_Instance.implementation != null)\n                        s_Instance.implementation.Dispose();\n                    s_Instance.implementation = value;\n                }\n            }\n        }\n\n        static ScriptableBakedReflectionSystemWrapper s_Instance = null;\n\n        [UsedImplicitly, RequiredByNativeCode]\n        static ScriptableBakedReflectionSystemWrapper Internal_ScriptableBakedReflectionSystemSettings_InitializeWrapper(IntPtr ptr)\n        {\n            s_Instance = new ScriptableBakedReflectionSystemWrapper(ptr);\n            return s_Instance;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Camera/ScriptableBakedReflectionSystemWrapper.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Experimental.Rendering\n{\n    [RequiredByNativeCode]\n    [NativeHeader(\"Editor/Src/Camera/ScriptableBakedReflectionSystem.h\")]\n    [StructLayout(LayoutKind.Sequential)]\n    class ScriptableBakedReflectionSystemWrapper : IDisposable, IScriptableBakedReflectionSystemStageNotifier\n    {\n        IntPtr m_Ptr = IntPtr.Zero;\n        bool Disposed { get { return m_Ptr == IntPtr.Zero; } }\n\n        internal IScriptableBakedReflectionSystem implementation { get; set; }\n\n        internal ScriptableBakedReflectionSystemWrapper(IntPtr ptr)\n        {\n            m_Ptr = ptr;\n        }\n\n        ~ScriptableBakedReflectionSystemWrapper()\n        {\n            Dispose(false);\n        }\n\n        Hash128[] Internal_ScriptableBakedReflectionSystemWrapper_stateHashes\n        {\n            [RequiredByNativeCode]\n            get { return implementation != null ? implementation.stateHashes : null; }\n        }\n\n        int Internal_ScriptableBakedReflectionSystemWrapper_stageCount\n        {\n            [RequiredByNativeCode]\n            get { return implementation != null ? implementation.stageCount : 0; }\n        }\n\n        void IDisposable.Dispose()\n        {\n            Dispose(true);\n            GC.SuppressFinalize(this);\n        }\n\n        void IScriptableBakedReflectionSystemStageNotifier.EnterStage(int stage, string progressMessage, float progress)\n        {\n            if (Disposed)\n                throw new ObjectDisposedException(\"ScriptableBakedReflectionSystemWrapper\");\n\n            ScriptingEnterStage(m_Ptr, stage, progressMessage, progress);\n        }\n\n        void IScriptableBakedReflectionSystemStageNotifier.ExitStage(int stage)\n        {\n            if (Disposed)\n                throw new ObjectDisposedException(\"ScriptableBakedReflectionSystemWrapper\");\n\n            ScriptingExitStage(m_Ptr, stage);\n        }\n\n        void IScriptableBakedReflectionSystemStageNotifier.SetIsDone(bool isDone)\n        {\n            if (Disposed)\n                throw new ObjectDisposedException(\"ScriptableBakedReflectionSystemWrapper\");\n\n            ScriptingSetIsDone(m_Ptr, isDone);\n        }\n\n        void Dispose(bool disposing)\n        {\n            m_Ptr = IntPtr.Zero;\n            implementation = null;\n        }\n\n        [RequiredByNativeCode]\n        void Internal_ScriptableBakedReflectionSystemWrapper_Tick(SceneStateHash deps)\n        {\n            if (Disposed)\n                throw new ObjectDisposedException(\"ScriptableBakedReflectionSystemWrapper\");\n\n            if (implementation != null)\n                implementation.Tick(deps, this);\n        }\n\n        [RequiredByNativeCode]\n        void Internal_ScriptableBakedReflectionSystemWrapper_SynchronizeReflectionProbes()\n        {\n            if (Disposed)\n                throw new ObjectDisposedException(\"ScriptableBakedReflectionSystemWrapper\");\n\n            if (implementation != null)\n                implementation.SynchronizeReflectionProbes();\n        }\n\n        [RequiredByNativeCode]\n        void Internal_ScriptableBakedReflectionSystemWrapper_Clear()\n        {\n            if (Disposed)\n                throw new ObjectDisposedException(\"ScriptableBakedReflectionSystemWrapper\");\n\n            if (implementation != null)\n                implementation.Clear();\n        }\n\n        [RequiredByNativeCode]\n        void Internal_ScriptableBakedReflectionSystemWrapper_Cancel()\n        {\n            if (Disposed)\n                throw new ObjectDisposedException(\"ScriptableBakedReflectionSystemWrapper\");\n\n            if (implementation != null)\n                implementation.Cancel();\n        }\n\n        [RequiredByNativeCode]\n        bool Internal_ScriptableBakedReflectionSystemWrapper_BakeAllReflectionProbes()\n        {\n            if (Disposed)\n                throw new ObjectDisposedException(\"ScriptableBakedReflectionSystemWrapper\");\n\n            if (implementation != null)\n                return implementation.BakeAllReflectionProbes();\n\n            return false;\n        }\n\n        [StaticAccessor(\"ScriptableBakedReflectionSystem\", StaticAccessorType.DoubleColon)]\n        static extern void ScriptingEnterStage(IntPtr objPtr, int stage, string progressMessage, float progress);\n\n        [StaticAccessor(\"ScriptableBakedReflectionSystem\", StaticAccessorType.DoubleColon)]\n        static extern void ScriptingExitStage(IntPtr objPtr, int stage);\n\n        [StaticAccessor(\"ScriptableBakedReflectionSystem\", StaticAccessorType.DoubleColon)]\n        static extern void ScriptingSetIsDone(IntPtr objPtr, bool isDone);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Categorize.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing UnityEngine.Categorization;\nusing Unity.Collections;\n\nnamespace UnityEditor.Categorization\n{\n    /* Sorting API that rely on DisplayCategory and DisplaySubCategory */\n\n    internal interface ICategorizable\n    {\n        Type type { get; }\n    }\n    \n    interface IOrdering\n    {\n        string name { get; }\n        int order { get; }\n    }\n\n    //Need to be a class to prevent loop definition with leaf that can cause issue when loading type through reflection\n    internal class Category<T> : IEnumerable<T>, IOrdering\n        where T : ICategorizable, IOrdering\n    {\n        public List<T> content { get; private set; }\n        public string name { get; private set; }\n        public int order { get; private set; }\n        public Type type => content.Count > 0 ? content[0].type : null;\n        public T this[int i] => content[i];\n        public int count => content.Count;\n\n        public Category(string name, int order)\n        {\n            content = new();\n            this.name = name;\n            this.order = order;\n        }\n\n        public void Add(T newElement, IComparer<T> comparer)\n            => content.AddSorted(newElement, comparer);\n\n        public IEnumerator<T> GetEnumerator() => content.GetEnumerator();\n        IEnumerator IEnumerable.GetEnumerator() => content.GetEnumerator();\n    }\n\n    internal struct LeafElement<T> : IOrdering, ICategorizable\n        where T : ICategorizable\n    {\n        public T data { get; private set; }\n        public static implicit operator T(LeafElement<T> leaftElement)\n            => leaftElement.data;\n\n        public string name { get; private set; }\n        public int order { get; private set; }\n        public Category<LeafElement<T>> parent { get; private set; }\n        public Type type => typeof(T);\n\n        public LeafElement(T data, string name, int order, Category<LeafElement<T>> parent)\n        {\n            this.data = data;\n            this.name = name;\n            this.order = order;\n            this.parent = parent;\n        }\n    }\n\n    internal static class CategorizeHelper\n    {\n        struct OrderingComparer<T> : IComparer<T>\n            where T : IOrdering\n        {\n            public int Compare(T a, T b)\n            {\n                var order = a.order.CompareTo(b.order);\n                if (order != 0)\n                    return order;\n                return a.name.CompareTo(b.name);\n            }\n        }\n\n        internal static List<Category<LeafElement<T>>> SortByCategory<T>(this List<T> list)\n            where T : ICategorizable\n        {\n            var categories = new Dictionary<string, Category<LeafElement<T>>>();\n            var result = new List<Category<LeafElement<T>>>();\n            var comparerLeaf = new OrderingComparer<LeafElement<T>>();\n            var comparerCategory = new OrderingComparer<Category<LeafElement<T>>>();\n\n            foreach(var entry in list)\n            {\n                var type = entry.type;\n                CategoryInfoAttribute categoryInfo = type.GetCustomAttribute<CategoryInfoAttribute>();\n                ElementInfoAttribute displayInfo = type.GetCustomAttribute<ElementInfoAttribute>();\n                int categoryOrder = categoryInfo?.Order ?? int.MaxValue;\n                int inCategoryOrder = displayInfo?.Order ?? int.MaxValue;\n                string categoryName = categoryInfo?.Name\n                    // Keep compatibility with previous used attribute for 23.3LTS\n                    ?? type.GetCustomAttribute<System.ComponentModel.CategoryAttribute>()?.Category;\n                string name = displayInfo?.Name ?? ObjectNames.NicifyVariableName(type.Name);\n                categoryName ??= name;\n\n                Category<LeafElement<T>> category;\n                if (!categories.TryGetValue(categoryName, out category))\n                {\n                    category = new Category<LeafElement<T>>(categoryName, categoryOrder);\n                    categories[categoryName] = category;\n                    result.AddSorted(category, comparerCategory);\n                }\n\n                category.Add(new LeafElement<T>(entry, name, inCategoryOrder, category), comparerLeaf);\n            }\n\n            return result;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ChangeTrackerHandle.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/Utility/ChangeTracker.h\")]\n    [RequiredByNativeCode]\n    internal class SerializedObjectChangeTracker: IDisposable\n    {\n        IntPtr m_Handle;\n\n        // This is so the garbage collector won't clean up SerializedObject behind the scenes.\n        internal SerializedObject m_SerializedObject;\n\n        private SerializedProperty[] m_ModifiedTrackedProperties;\n        private static readonly SerializedProperty[] s_EmptyPropertyArray = new SerializedProperty[] { };\n\n        public SerializedObjectChangeTracker(SerializedObject obj)\n        {\n            m_SerializedObject= obj;\n            m_Handle = Internal_AcquireTracker(obj);\n            m_ModifiedTrackedProperties = s_EmptyPropertyArray;\n        }\n\n        ~SerializedObjectChangeTracker() { Dispose(); }\n\n        [ThreadAndSerializationSafe()]\n        public void Dispose()\n        {\n            if (m_Handle != IntPtr.Zero)\n            {\n                ClearModifiedTrackedProperties();\n                Internal_ReleaseTracker(m_Handle);\n                m_Handle = IntPtr.Zero;\n                m_SerializedObject = null;\n            }\n        }\n\n\n        public SerializedProperty[] GetModifiedTrackedProperties()\n        {\n            return m_ModifiedTrackedProperties;\n        }\n\n        public void ClearModifiedTrackedProperties()\n        {\n            if (m_ModifiedTrackedProperties.Length > 0)\n            {\n                for (int i = 0; i < m_ModifiedTrackedProperties.Length; ++i)\n                {\n                    m_ModifiedTrackedProperties[i].Dispose();\n                }\n\n                m_ModifiedTrackedProperties = s_EmptyPropertyArray;\n            }\n        }\n\n        public bool HasModifiedTrackedProperties()\n        {\n            return m_ModifiedTrackedProperties.Length > 0;\n        }\n\n        [NativeName(\"GetSyncedTrackedProperties\")]\n        public extern int[] GetSyncedTrackedProperties();\n\n        [NativeName(\"HasModifiedTrackedProperties\")]\n        internal extern bool HasModifiedTrackedPropertiesInternal();\n\n        [NativeName(\"GetModifiedTrackedProperties\")]\n        private extern SerializedProperty[] GetModifiedTrackedPropertiesInternal();\n\n        [NativeName(\"ClearModifiedTrackedProperties\")]\n        private extern void ClearModifiedTrackedPropertiesInternal();\n\n        [FreeFunction(\"SerializedObjectChangeTracker::AcquireTracker\")]\n        private static extern IntPtr Internal_AcquireTracker(UnityEditor.SerializedObject o);\n\n        [FreeFunction(\"SerializedObjectChangeTracker::ReleaseTracker\", IsThreadSafe = true)]\n        private static extern void Internal_ReleaseTracker(IntPtr handle);\n\n        // returns true if object changed since last poll\n        internal bool PollForChanges(bool updateSerializedObject)\n        {\n            if (m_Handle == IntPtr.Zero)\n                throw new ArgumentNullException(\"Not a valid handle, has it been released already?\");\n            bool result = Internal_PollChanges(updateSerializedObject);\n\n            if (HasModifiedTrackedPropertiesInternal())\n            {\n                m_ModifiedTrackedProperties = GetModifiedTrackedPropertiesInternal();\n                for (int i = 0; i < m_ModifiedTrackedProperties.Length; ++i)\n                {\n                    m_ModifiedTrackedProperties[i].m_SerializedObject = m_SerializedObject;\n                }\n\n                ClearModifiedTrackedPropertiesInternal();\n            }\n            else\n            {\n                m_ModifiedTrackedProperties = s_EmptyPropertyArray;\n            }\n\n            return result;\n        }\n\n        [NativeName(\"PollChanges\")]\n        private extern bool Internal_PollChanges(bool updateSerializedObject);\n\n        [NativeName(\"TrackPropertyValue\")]\n        internal extern void AddPropertyTracking(SerializedProperty property);\n\n        internal void RemovePropertyTracking(SerializedProperty property)\n        {\n            RemovePropertyTracking(property.hashCodeForPropertyPath);\n        }\n\n        [NativeName(\"UntrackPropertyValue\")]\n        internal extern void RemovePropertyTracking(int propertyPathHash);\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(UnityEditor.SerializedObjectChangeTracker obj) => obj.m_Handle;\n        }\n\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Clipboard/Clipboard.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\n// ReSharper disable PossibleInvalidOperationException -- we are accessing bool?\n// values in this file many times, but ensuring they are set before.\n\n// ReSharper disable once CheckNamespace - we explicitly want UnityEditor namespace\nnamespace UnityEditor\n{\n    internal static class Clipboard\n    {\n        static ClipboardState m_State = new ClipboardState();\n\n        public static bool hasLong\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchLong();\n                return m_State.m_HasLong.Value;\n            }\n        }\n\n        public static long longValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchLong();\n                return m_State.m_ValueLong;\n            }\n\n            set => EditorGUIUtility.systemCopyBuffer = value.ToString();\n        }\n\n        public static bool hasUlong\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchUlong();\n                return m_State.m_HasUlong.Value;\n            }\n        }\n\n        public static ulong uLongValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchUlong();\n                return m_State.m_ValueUlong;\n            }\n\n            set => EditorGUIUtility.systemCopyBuffer = value.ToString();\n        }\n\n        public static bool hasUint\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchUint();\n                return m_State.m_HasUint.Value;\n            }\n        }\n\n        public static uint uIntValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchUint();\n                return m_State.m_ValueUint;\n            }\n\n            set => EditorGUIUtility.systemCopyBuffer = value.ToString();\n        }\n\n        public static bool hasInteger\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchInteger();\n                return m_State.m_HasInteger.Value;\n            }\n        }\n\n        public static int integerValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchInteger();\n                return m_State.m_ValueInteger;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = value.ToString();\n        }\n\n        public static bool hasFloat\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchFloat();\n                return m_State.m_HasFloat.Value;\n            }\n        }\n\n        public static float floatValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchFloat();\n                return m_State.m_ValueFloat;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = value.ToString(CultureInfo.InvariantCulture);\n        }\n\n        public static bool hasString\n        {\n            get\n            {\n                FetchState();\n                return !string.IsNullOrEmpty(m_State.m_RawContents);\n            }\n        }\n\n        public static string stringValue\n        {\n            get\n            {\n                FetchState();\n                return m_State.m_RawContents;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = value;\n        }\n\n        public static bool hasLayerMask\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchLayerMask();\n                return m_State.m_HasLayerMask.Value;\n            }\n        }\n\n        public static LayerMask layerMaskValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchLayerMask();\n                return m_State.m_ValueLayerMask;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = $\"LayerMask({value.value})\";\n        }\n\n        public static bool hasRenderingLayerMask\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchRenderingLayerMask();\n                return m_State.m_HasRenderingLayerMask.Value;\n            }\n        }\n\n        public static RenderingLayerMask renderingLayerMaskValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchRenderingLayerMask();\n                return m_State.m_ValueRenderingLayerMask;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = $\"RenderingLayerMask({value.value})\";\n        }\n\n\n        public static bool hasBool\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchBool();\n                return m_State.m_HasBool.Value;\n            }\n        }\n\n        public static bool boolValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchBool();\n                return m_State.m_ValueBool;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = value.ToString();\n        }\n\n        public static bool hasGuid\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchGuid();\n                return m_State.m_HasGuid.Value;\n            }\n        }\n\n        public static GUID guidValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchGuid();\n                return m_State.m_ValueGuid;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = value.ToString();\n        }\n\n        public static bool hasHash128\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchHash128();\n                return m_State.m_HasHash128.Value;\n            }\n        }\n\n        public static Hash128 hash128Value\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchHash128();\n                return m_State.m_ValueHash128;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = value.ToString();\n        }\n\n        public static bool hasVector3\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchVector3();\n                return m_State.m_HasVector3.Value;\n            }\n        }\n\n        public static Vector3 vector3Value\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchVector3();\n                return m_State.m_ValueVector3;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = ClipboardParser.WriteVector3(value);\n        }\n\n        public static bool hasVector2\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchVector2();\n                return m_State.m_HasVector2.Value;\n            }\n        }\n\n        public static Vector2 vector2Value\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchVector2();\n                return m_State.m_ValueVector2;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = ClipboardParser.WriteVector2(value);\n        }\n\n        public static bool hasVector4\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchVector4();\n                return m_State.m_HasVector4.Value;\n            }\n        }\n\n        public static Vector4 vector4Value\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchVector4();\n                return m_State.m_ValueVector4;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = ClipboardParser.WriteVector4(value);\n        }\n\n        public static bool hasQuaternion\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchQuaternion();\n                return m_State.m_HasQuaternion.Value;\n            }\n        }\n\n        public static Quaternion quaternionValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchQuaternion();\n                return m_State.m_ValueQuaternion;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = ClipboardParser.WriteQuaternion(value);\n        }\n\n        public static bool hasRect\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchRect();\n                return m_State.m_HasRect.Value;\n            }\n        }\n\n        public static Rect rectValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchRect();\n                return m_State.m_ValueRect;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = ClipboardParser.WriteRect(value);\n        }\n\n        public static bool hasBounds\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchBounds();\n                return m_State.m_HasBounds.Value;\n            }\n        }\n\n        public static Bounds boundsValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchBounds();\n                return m_State.m_ValueBounds;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = ClipboardParser.WriteBounds(value);\n        }\n\n        public static bool hasColor\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchColor();\n                return m_State.m_HasColor.Value;\n            }\n        }\n\n        public static Color colorValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchColor();\n                return m_State.m_ValueColor;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = ClipboardParser.WriteColor(value);\n        }\n\n        public static bool hasObject\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchObject();\n                return m_State.m_HasObject.Value;\n            }\n        }\n\n        public static Object objectValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchObject();\n                return m_State.m_ValueObject;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = ClipboardParser.WriteCustom(new ObjectWrapper(value));\n        }\n\n        public static bool hasGradient\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchGradient();\n                return m_State.m_HasGradient.Value;\n            }\n        }\n\n        public static Gradient gradientValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchGradient();\n                return m_State.m_ValueGradient;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = ClipboardParser.WriteCustom(new GradientWrapper(value));\n        }\n\n        public static bool hasAnimationCurve\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchAnimationCurve();\n                return m_State.m_HasAnimationCurve.Value;\n            }\n        }\n\n        public static AnimationCurve animationCurveValue\n        {\n            get\n            {\n                FetchState();\n                m_State.FetchAnimationCurve();\n                return m_State.m_ValueAnimationCurve;\n            }\n            set => EditorGUIUtility.systemCopyBuffer = ClipboardParser.WriteCustom(new AnimationCurveWrapper(value));\n        }\n\n        public static bool HasCustomValue<T>() where T : new()\n        {\n            FetchState();\n            return m_State.FetchCustom<T>(out _);\n        }\n\n        public static T GetCustomValue<T>() where T : new()\n        {\n            FetchState();\n            m_State.FetchCustom<T>(out var res);\n            return res;\n        }\n\n        public static void SetCustomValue<T>(T val) where T : new()\n        {\n            EditorGUIUtility.systemCopyBuffer = ClipboardParser.WriteCustom<T>(val);\n        }\n\n        const string kGenericPrefix = \"GenericPropertyJSON:\";\n\n        public static bool HasSerializedProperty()\n        {\n            return stringValue?.StartsWith(kGenericPrefix) ?? false;\n        }\n\n        public static void SetSerializedProperty(SerializedProperty src)\n        {\n            var encoded = ClipboardParser.WriteGenericSerializedProperty(src);\n            var json = Json.Serialize(encoded);\n            stringValue = kGenericPrefix + json;\n        }\n\n        public static void GetSerializedProperty(SerializedProperty dst)\n        {\n            var clip = stringValue;\n            if (!clip.StartsWith(kGenericPrefix))\n                return;\n            if (!(Json.Deserialize(clip.Substring(kGenericPrefix.Length)) is Dictionary<string, object> jsonObjects))\n                return;\n            ClipboardParser.ParseGenericSerializedProperty(dst, jsonObjects);\n        }\n\n        public static bool HasEnumProperty(SerializedProperty prop)\n        {\n            return ClipboardParser.ParseEnumPropertyIndex(stringValue, prop) >= 0 || ClipboardParser.ParseEnumPropertyFlag(stringValue, prop) >= 0;\n        }\n\n        public static void GetEnumProperty(SerializedProperty prop)\n        {\n            ClipboardParser.ParseEnumProperty(stringValue, prop);\n        }\n\n        public static void SetEnumProperty(SerializedProperty prop)\n        {\n            EditorGUIUtility.systemCopyBuffer = ClipboardParser.WriteEnumProperty(prop);\n        }\n\n        static void FetchState()\n        {\n            var systemClipboard = EditorGUIUtility.systemCopyBuffer;\n            if (systemClipboard == m_State.m_RawContents)\n                return;\n            m_State = new ClipboardState {m_RawContents = systemClipboard};\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Clipboard/ClipboardContextMenu.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\n// ReSharper disable once CheckNamespace - we explicitly want UnityEditor namespace\nnamespace UnityEditor\n{\n    internal static class ClipboardContextMenu\n    {\n        // Adds Copy/Paste entries into the menu if not null,\n        // or handles Copy/Paste commands in the given event if not null.\n        internal static void SetupPropertyCopyPaste(SerializedProperty property, GenericMenu menu, Event evt)\n        {\n            var type = property.propertyType;\n            // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault -- we don't support all the types\n            switch (type)\n            {\n                case SerializedPropertyType.Vector2:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.vector2Value = p.vector2Value,\n                        p => Clipboard.hasVector2,\n                        p => p.vector2Value = Clipboard.vector2Value);\n                    break;\n                case SerializedPropertyType.Vector3:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.vector3Value = p.vector3Value,\n                        p => Clipboard.hasVector3,\n                        p => p.vector3Value = Clipboard.vector3Value);\n                    break;\n                case SerializedPropertyType.Vector4:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.vector4Value = p.vector4Value,\n                        p => Clipboard.hasVector4,\n                        p => p.vector4Value = Clipboard.vector4Value);\n                    break;\n                case SerializedPropertyType.Boolean:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.boolValue = p.boolValue,\n                        p => Clipboard.hasBool,\n                        p => p.boolValue = Clipboard.boolValue);\n                    break;\n                case SerializedPropertyType.Quaternion: SetupQuaternion(property, menu, evt); break;\n                case SerializedPropertyType.ObjectReference: SetupObjectReference(property, menu, evt); break;\n                case SerializedPropertyType.Color:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.colorValue = p.colorValue,\n                        p => Clipboard.hasColor,\n                        p => p.colorValue = Clipboard.colorValue);\n                    break;\n                case SerializedPropertyType.Gradient:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.gradientValue = p.gradientValue,\n                        p => Clipboard.hasGradient,\n                        delegate(SerializedProperty p) {\n                            p.gradientValue = Clipboard.gradientValue;\n                            UnityEditorInternal.GradientPreviewCache.ClearCache();\n                        });\n                    break;\n                case SerializedPropertyType.AnimationCurve:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.animationCurveValue = p.animationCurveValue,\n                        p => Clipboard.hasAnimationCurve,\n                        p => p.animationCurveValue = Clipboard.animationCurveValue);\n                    break;\n                case SerializedPropertyType.Vector2Int:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.vector2Value = p.vector2IntValue,\n                        p => Clipboard.hasVector2,\n                        delegate(SerializedProperty p)\n                        {\n                            var vi = Clipboard.vector2Value;\n                            p.vector2IntValue = new Vector2Int((int)vi.x, (int)vi.y);\n                        });\n                    break;\n                case SerializedPropertyType.Vector3Int:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.vector3Value = p.vector3IntValue,\n                        p => Clipboard.hasVector3,\n                        delegate(SerializedProperty p)\n                        {\n                            var vi = Clipboard.vector3Value;\n                            p.vector3IntValue = new Vector3Int((int)vi.x, (int)vi.y, (int)vi.z);\n                        });\n                    break;\n                case SerializedPropertyType.Rect:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.rectValue = p.rectValue,\n                        p => Clipboard.hasRect,\n                        p => p.rectValue = Clipboard.rectValue);\n                    break;\n                case SerializedPropertyType.RectInt:\n                    SetupAction(property, menu, evt,\n                        delegate(SerializedProperty p)\n                        {\n                            var ri = p.rectIntValue;\n                            Clipboard.rectValue = new Rect(ri.x, ri.y, ri.width, ri.height);\n                        },\n                        p => Clipboard.hasRect,\n                        delegate(SerializedProperty p)\n                        {\n                            var r = Clipboard.rectValue;\n                            p.rectIntValue = new RectInt((int)r.x, (int)r.y, (int)r.width, (int)r.height);\n                        });\n                    break;\n                case SerializedPropertyType.Bounds:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.boundsValue = p.boundsValue,\n                        p => Clipboard.hasBounds,\n                        p => p.boundsValue = Clipboard.boundsValue);\n                    break;\n                case SerializedPropertyType.BoundsInt:\n                    SetupAction(property, menu, evt,\n                        p =>\n                        {\n                            var b = p.boundsIntValue;\n                            Clipboard.boundsValue = new Bounds(b.position, b.size * 2);\n                        },\n                        p => Clipboard.hasBounds,\n                        p =>\n                        {\n                            var b = Clipboard.boundsValue;\n                            p.boundsIntValue = new BoundsInt(new Vector3Int((int)b.center.x, (int)b.center.y, (int)b.center.z),\n                                new Vector3Int((int)(b.size.x / 2), (int)(b.size.y / 2), (int)(b.size.z / 2)));\n                        });\n                    break;\n                case SerializedPropertyType.LayerMask:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.layerMaskValue = p.intValue,\n                        p => Clipboard.hasLayerMask,\n                        p => p.intValue = Clipboard.layerMaskValue);\n                    break;\n                case SerializedPropertyType.RenderingLayerMask:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.renderingLayerMaskValue = p.uintValue,\n                        p => Clipboard.hasRenderingLayerMask,\n                        p => p.uintValue = Clipboard.renderingLayerMaskValue);\n                    break;\n                case SerializedPropertyType.Enum:\n                    SetupAction(property, menu, evt,\n                        Clipboard.SetEnumProperty,\n                        Clipboard.HasEnumProperty,\n                        Clipboard.GetEnumProperty);\n                    break;\n                case SerializedPropertyType.Hash128:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.hash128Value = p.hash128Value,\n                        p => Clipboard.hasHash128,\n                        p => p.hash128Value = Clipboard.hash128Value);\n                    break;\n                case SerializedPropertyType.Generic:\n                    if (property.type == \"MinMaxGradient\")\n                    {\n                        SetupMinMaxGradient(property, menu, evt);\n                    }\n                    else if (property.type == \"MinMaxCurve\")\n                    {\n                        SetupMinMaxCurve(property, menu, evt);\n                    }\n                    else\n                    {\n                        if (property.isArray && property.arrayElementType == \"managedReference<>\") break;\n\n                        SetupAction(property, menu, evt,\n                            Clipboard.SetSerializedProperty,\n                            p => Clipboard.HasSerializedProperty(),\n                            Clipboard.GetSerializedProperty);\n                    }\n                    break;\n                case SerializedPropertyType.Integer:\n                    {\n                        switch (property.numericType)\n                        {\n                            case SerializedPropertyNumericType.Int64:\n                                SetupAction(property, menu, evt,\n                                            p => Clipboard.longValue = p.longValue,\n                                            p => Clipboard.hasLong,\n                                            p => p.longValue = Clipboard.longValue);\n                                break;\n\n                            case SerializedPropertyNumericType.UInt64:\n                                SetupAction(property, menu, evt,\n                                            p => Clipboard.uLongValue = p.ulongValue,\n                                            p => Clipboard.hasUlong,\n                                            p => p.ulongValue = Clipboard.uLongValue);\n                                break;\n\n                            case SerializedPropertyNumericType.UInt32:\n                                SetupAction(property, menu, evt,\n                                            p => Clipboard.uIntValue = p.uintValue,\n                                            p => Clipboard.hasUint,\n                                            p => p.uintValue = Clipboard.uIntValue);\n                                break;\n\n                            case SerializedPropertyNumericType.UInt16:\n                                SetupAction(property, menu, evt,\n                                            p => Clipboard.uIntValue = (System.UInt16)p.uintValue,\n                                            p => Clipboard.hasUint,\n                                            p => p.uintValue = (System.UInt16)Clipboard.uIntValue);\n                                break;\n\n                            case SerializedPropertyNumericType.Int16:\n                                SetupAction(property, menu, evt,\n                                            p => Clipboard.integerValue = (System.Int16)p.intValue,\n                                            p => Clipboard.hasInteger,\n                                            p => p.intValue = (System.UInt16)Clipboard.integerValue);\n                                break;\n                            case SerializedPropertyNumericType.UInt8:\n                                SetupAction(property, menu, evt,\n                                            p => Clipboard.uIntValue = (System.Byte)p.uintValue,\n                                            p => Clipboard.hasUint,\n                                            p => p.uintValue = (System.Byte)Clipboard.uIntValue);\n                                break;\n                            case SerializedPropertyNumericType.Int8:\n                                SetupAction(property, menu, evt,\n                                            p => Clipboard.integerValue = (System.Byte)p.intValue,\n                                            p => Clipboard.hasInteger,\n                                            p => p.intValue = (System.Byte)Clipboard.integerValue);\n                                break;\n\n                            default:\n                                SetupAction(property, menu, evt,\n                                    p => Clipboard.integerValue = p.intValue,\n                                    p => Clipboard.hasInteger,\n                                    p => p.intValue = Clipboard.integerValue);\n                                break;\n                        }\n                    }\n                    break;\n                case SerializedPropertyType.Float:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.floatValue = p.floatValue,\n                        p => Clipboard.hasFloat,\n                        p => p.floatValue = Clipboard.floatValue);\n                    break;\n                case SerializedPropertyType.String:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.stringValue = p.stringValue,\n                        p => Clipboard.hasString,\n                        p => p.stringValue = Clipboard.stringValue);\n                    break;\n                case SerializedPropertyType.Character:\n                    SetupAction(property, menu, evt,\n                        p => Clipboard.stringValue = ((char)p.intValue).ToString(),\n                        p => Clipboard.hasString && Clipboard.stringValue.Length == 1,\n                        p => p.intValue = Convert.ToChar(Clipboard.stringValue[0]));\n                    break;\n            }\n        }\n\n        static readonly GUIContent kCopyContent = EditorGUIUtility.TrTextContent(\"Copy\");\n        static readonly GUIContent kPasteContent = EditorGUIUtility.TrTextContent(\"Paste\");\n        static readonly GUIContent kCopyEulerContent = EditorGUIUtility.TrTextContent(\"Copy Euler Angles\");\n        static readonly GUIContent kCopyQuatContent = EditorGUIUtility.TrTextContent(\"Copy Quaternion\");\n        static readonly GUIContent kCopyPathContent = EditorGUIUtility.TrTextContent(\"Copy Path\");\n        static readonly GUIContent kCopyGuidContent = EditorGUIUtility.TrTextContent(\"Copy GUID\");\n        static readonly GUIContent kPasteMinColorContent = EditorGUIUtility.TrTextContent(\"Paste Min Color\");\n        static readonly GUIContent kPasteMaxColorContent = EditorGUIUtility.TrTextContent(\"Paste Max Color\");\n        static readonly GUIContent kPasteMinGradientContent = EditorGUIUtility.TrTextContent(\"Paste Min Gradient\");\n        static readonly GUIContent kPasteMaxGradientContent = EditorGUIUtility.TrTextContent(\"Paste Max Gradient\");\n        static readonly GUIContent kPasteMinScalarContent = EditorGUIUtility.TrTextContent(\"Paste Min Scalar\");\n        static readonly GUIContent kPasteMaxScalarContent = EditorGUIUtility.TrTextContent(\"Paste Max Scalar\");\n        static readonly GUIContent kPasteMinCurveContent = EditorGUIUtility.TrTextContent(\"Paste Min Curve\");\n        static readonly GUIContent kPasteMaxCurveContent = EditorGUIUtility.TrTextContent(\"Paste Max Curve\");\n\n        static void AddSeparator(GenericMenu menu)\n        {\n            if (menu.GetItemCount() > 0)\n                menu.AddSeparator(\"\");\n        }\n\n        internal static GUIContent overrideCopyContent { set; get; }\n        internal static GUIContent overridePasteContent { set; get; }\n\n        static void SetupAction(SerializedProperty property, GenericMenu menu, Event evt,\n            Action<SerializedProperty> copyFunc,\n            Func<SerializedProperty, bool> canPasteFunc,\n            Action<SerializedProperty> pasteFunc)\n        {\n            var canCopy = !property.hasMultipleDifferentValues;\n            var canPaste = GUI.enabled && canPasteFunc(property);\n\n            if (menu != null)\n            {\n                AddSeparator(menu);\n\n                var copyContent = overrideCopyContent ?? kCopyContent;\n                if (canCopy)\n                    menu.AddItem(copyContent, false, o => copyFunc((SerializedProperty)o), property);\n                else\n                    menu.AddDisabledItem(copyContent);\n\n                var pasteContent = overridePasteContent ?? kPasteContent;\n                if (canPaste)\n                {\n                    menu.AddItem(pasteContent, false,\n                        delegate(object o)\n                        {\n                            var prop = (SerializedProperty)o;\n                            pasteFunc(prop);\n                            prop.serializedObject.ApplyModifiedProperties();\n                            // Constrain proportions scale widget might need extra recalculation, notify if a paste\n                            ConstrainProportionsTransformScale.NotifyPropertyPasted(prop.propertyPath);\n                        }, property);\n                }\n                else\n                {\n                    menu.AddDisabledItem(pasteContent);\n                }\n            }\n\n            if (evt != null)\n            {\n                if (canCopy && evt.commandName == EventCommandNames.Copy)\n                {\n                    if (evt.type == EventType.ValidateCommand)\n                        evt.Use();\n                    if (evt.type == EventType.ExecuteCommand)\n                    {\n                        copyFunc(property);\n                        evt.Use();\n                    }\n                }\n                if (canPaste && evt.commandName == EventCommandNames.Paste)\n                {\n                    if (evt.type == EventType.ValidateCommand)\n                        evt.Use();\n                    if (evt.type == EventType.ExecuteCommand)\n                    {\n                        pasteFunc(property);\n                        property.serializedObject.ApplyModifiedProperties();\n                        evt.Use();\n                    }\n                }\n            }\n        }\n\n        static void PasteQuaternion(SerializedProperty p)\n        {\n            p.quaternionValue = Clipboard.hasQuaternion ? Clipboard.quaternionValue : Quaternion.Euler(Clipboard.vector3Value);\n            p.serializedObject.ApplyModifiedProperties();\n        }\n\n        static void SetupQuaternion(SerializedProperty property, GenericMenu menu, Event evt)\n        {\n            var canCopy = !property.hasMultipleDifferentValues;\n            var canPaste = GUI.enabled && (Clipboard.hasQuaternion || Clipboard.hasVector3);\n\n            if (menu != null)\n            {\n                AddSeparator(menu);\n                if (canCopy)\n                {\n                    menu.AddItem(kCopyEulerContent, false, o => Clipboard.vector3Value = ((SerializedProperty)o).quaternionValue.eulerAngles, property);\n                    menu.AddItem(kCopyQuatContent, false, o => Clipboard.quaternionValue = ((SerializedProperty)o).quaternionValue, property);\n                }\n                else\n                {\n                    menu.AddDisabledItem(kCopyEulerContent);\n                    menu.AddDisabledItem(kCopyQuatContent);\n                }\n                if (canPaste)\n                    menu.AddItem(kPasteContent, false, o => PasteQuaternion((SerializedProperty)o), property);\n                else\n                    menu.AddDisabledItem(kPasteContent);\n            }\n            if (evt != null)\n            {\n                if (canCopy && evt.commandName == EventCommandNames.Copy)\n                {\n                    if (evt.type == EventType.ValidateCommand)\n                        evt.Use();\n                    if (evt.type == EventType.ExecuteCommand)\n                    {\n                        Clipboard.quaternionValue = property.quaternionValue;\n                        evt.Use();\n                    }\n                }\n                if (canPaste && evt.commandName == EventCommandNames.Paste)\n                {\n                    if (evt.type == EventType.ValidateCommand)\n                        evt.Use();\n                    if (evt.type == EventType.ExecuteCommand)\n                    {\n                        PasteQuaternion(property);\n                        evt.Use();\n                    }\n                }\n            }\n        }\n\n        static void SetupMinMaxGradient(SerializedProperty property, GenericMenu menu, Event evt)\n        {\n            var canCopy = !property.hasMultipleDifferentValues;\n            var canPasteWhole = GUI.enabled && Clipboard.HasSerializedProperty();\n\n            if (menu != null)\n            {\n                AddSeparator(menu);\n\n                var copyContent = overrideCopyContent ?? kCopyContent;\n                if (canCopy)\n                    menu.AddItem(copyContent, false, o => Clipboard.SetSerializedProperty((SerializedProperty)o), property);\n                else\n                    menu.AddDisabledItem(copyContent);\n\n                var pasteContent = overridePasteContent ?? kPasteContent;\n\n                if (canPasteWhole)\n                {\n                    menu.AddItem(pasteContent, false,\n                        delegate (object o)\n                        {\n                            var prop = (SerializedProperty)o;\n                            Clipboard.GetSerializedProperty(prop);\n                            prop.serializedObject.ApplyModifiedProperties();\n                        }, property);\n                }\n                else if (GUI.enabled && Clipboard.hasColor)\n                {\n                    MinMaxGradientState state = (MinMaxGradientState)property.FindPropertyRelative(\"minMaxState\").intValue;\n                    if (state == MinMaxGradientState.k_Color)\n                    {\n                        AddPasteColorItem(property.FindPropertyRelative(\"maxColor\"), menu, pasteContent);\n                    }\n                    else if (state == MinMaxGradientState.k_RandomBetweenTwoColors)\n                    {\n                        // Allow the user to choose whether to paste the color on their clipboard to either the max or min\n                        AddPasteColorItem(property.FindPropertyRelative(\"maxColor\"), menu, kPasteMaxColorContent);\n                        AddPasteColorItem(property.FindPropertyRelative(\"minColor\"), menu, kPasteMinColorContent);\n                    }\n                    else\n                    {\n                        menu.AddDisabledItem(pasteContent);\n                    }\n                }\n                else if (GUI.enabled && Clipboard.hasGradient)\n                {\n                    MinMaxGradientState state = (MinMaxGradientState)property.FindPropertyRelative(\"minMaxState\").intValue;\n                    if (state == MinMaxGradientState.k_Gradient || state == MinMaxGradientState.k_RandomColor)\n                    {\n                        AddPasteGradientItem(property.FindPropertyRelative(\"maxGradient\"), menu, pasteContent);\n                    }\n                    else if (state == MinMaxGradientState.k_RandomBetweenTwoGradients)\n                    {\n                        // Allow the user to choose whether to paste the gradient on their clipboard to either the max or min\n                        AddPasteGradientItem(property.FindPropertyRelative(\"maxGradient\"), menu, kPasteMaxGradientContent);\n                        AddPasteGradientItem(property.FindPropertyRelative(\"minGradient\"), menu, kPasteMinGradientContent);\n                    }\n                    else\n                    {\n                        menu.AddDisabledItem(pasteContent);\n                    }\n                }\n                else\n                {\n                    menu.AddDisabledItem(pasteContent);\n                }\n            }\n            if (evt != null)\n            {\n                if (canCopy && evt.commandName == EventCommandNames.Copy)\n                {\n                    if (evt.type == EventType.ValidateCommand)\n                        evt.Use();\n                    if (evt.type == EventType.ExecuteCommand)\n                    {\n                        Clipboard.SetSerializedProperty(property);\n                        evt.Use();\n                    }\n                }\n                if (canPasteWhole && evt.commandName == EventCommandNames.Paste)\n                {\n                    if (evt.type == EventType.ValidateCommand)\n                        evt.Use();\n                    if (evt.type == EventType.ExecuteCommand)\n                    {\n                        Clipboard.GetSerializedProperty(property);\n                        property.serializedObject.ApplyModifiedProperties();\n                        evt.Use();\n                    }\n                }\n            }\n        }\n        static void SetupMinMaxCurve(SerializedProperty property, GenericMenu menu, Event evt)\n        {\n            var canCopy = !property.hasMultipleDifferentValues;\n            var canPasteWhole = GUI.enabled && Clipboard.HasSerializedProperty();\n\n            if (menu != null)\n            {\n                AddSeparator(menu);\n\n                var copyContent = overrideCopyContent ?? kCopyContent;\n                if (canCopy)\n                    menu.AddItem(copyContent, false, o => Clipboard.SetSerializedProperty((SerializedProperty)o), property);\n                else\n                    menu.AddDisabledItem(copyContent);\n\n                var pasteContent = overridePasteContent ?? kPasteContent;\n\n                if (canPasteWhole)\n                {\n                    menu.AddItem(pasteContent, false,\n                        delegate (object o)\n                        {\n                            var prop = (SerializedProperty)o;\n                            Clipboard.GetSerializedProperty(prop);\n                            prop.serializedObject.ApplyModifiedProperties();\n                        }, property);\n                }\n                else if (GUI.enabled && Clipboard.hasFloat)\n                {\n                    MinMaxCurveState state = (MinMaxCurveState)property.FindPropertyRelative(\"minMaxState\").intValue;\n                    if (state == MinMaxCurveState.k_Scalar)\n                    {\n                        AddPasteFloatItem(property.FindPropertyRelative(\"scalar\"), menu, pasteContent);\n                    }\n                    else if (state == MinMaxCurveState.k_TwoScalars)\n                    {\n                        // Allow the user to choose whether to paste the float on their clipboard to either the min or max\n                        AddPasteFloatItem(property.FindPropertyRelative(\"minScalar\"), menu, kPasteMinScalarContent);\n                        AddPasteFloatItem(property.FindPropertyRelative(\"scalar\"), menu, kPasteMaxScalarContent);\n                    }\n                    else\n                    {\n                        menu.AddDisabledItem(pasteContent);\n                    }\n                }\n                else if (GUI.enabled && Clipboard.hasAnimationCurve)\n                {\n                    MinMaxCurveState state = (MinMaxCurveState)property.FindPropertyRelative(\"minMaxState\").intValue;\n                    if (state == MinMaxCurveState.k_Curve)\n                    {\n                        AddPasteCurveItem(property.FindPropertyRelative(\"maxCurve\"), menu, pasteContent);\n                    }\n                    else if (state == MinMaxCurveState.k_TwoCurves)\n                    {\n                        // Allow the user to choose whether to paste the color on their clipboard to either the max or min\n                        AddPasteCurveItem(property.FindPropertyRelative(\"maxCurve\"), menu, kPasteMaxCurveContent);\n                        AddPasteCurveItem(property.FindPropertyRelative(\"minCurve\"), menu, kPasteMinCurveContent);\n                    }\n                    else\n                    {\n                        menu.AddDisabledItem(pasteContent);\n                    }\n                }\n                else\n                {\n                    menu.AddDisabledItem(pasteContent);\n                }\n            }\n            if (evt != null)\n            {\n                if (canCopy && evt.commandName == EventCommandNames.Copy)\n                {\n                    if (evt.type == EventType.ValidateCommand)\n                        evt.Use();\n                    if (evt.type == EventType.ExecuteCommand)\n                    {\n                        Clipboard.SetSerializedProperty(property);\n                        evt.Use();\n                    }\n                }\n                if (canPasteWhole && evt.commandName == EventCommandNames.Paste)\n                {\n                    if (evt.type == EventType.ValidateCommand)\n                        evt.Use();\n                    if (evt.type == EventType.ExecuteCommand)\n                    {\n                        Clipboard.GetSerializedProperty(property);\n                        property.serializedObject.ApplyModifiedProperties();\n                        evt.Use();\n                    }\n                }\n            }\n        }\n\n        static void AddPasteColorItem(SerializedProperty property, GenericMenu menu, GUIContent menuItemContent)\n        {\n            menu.AddItem(menuItemContent, false,\n            delegate (object o)\n            {\n                var prop = (SerializedProperty)o;\n                prop.colorValue = Clipboard.colorValue;\n                prop.serializedObject.ApplyModifiedProperties();\n            }, property);\n        }\n\n        static void AddPasteGradientItem(SerializedProperty property, GenericMenu menu, GUIContent menuItemContent)\n        {\n            menu.AddItem(menuItemContent, false,\n            delegate (object o)\n            {\n                var prop = (SerializedProperty)o;\n                prop.gradientValue = Clipboard.gradientValue;\n                prop.serializedObject.ApplyModifiedProperties();\n                UnityEditorInternal.GradientPreviewCache.ClearCache();\n            }, property);\n        }\n        static void AddPasteFloatItem(SerializedProperty property, GenericMenu menu, GUIContent menuItemContent)\n        {\n            menu.AddItem(menuItemContent, false,\n            delegate (object o)\n            {\n                var prop = (SerializedProperty)o;\n                prop.floatValue = Clipboard.floatValue;\n                prop.serializedObject.ApplyModifiedProperties();\n            }, property);\n        }\n        static void AddPasteCurveItem(SerializedProperty property, GenericMenu menu, GUIContent menuItemContent)\n        {\n            menu.AddItem(menuItemContent, false,\n            delegate (object o)\n            {\n                var prop = (SerializedProperty)o;\n                prop.animationCurveValue = Clipboard.animationCurveValue;\n                prop.serializedObject.ApplyModifiedProperties();\n                UnityEditorInternal.AnimationCurvePreviewCache.ClearCache();\n            }, property);\n        }\n\n        static void PasteObjectReference(SerializedProperty p)\n        {\n            if (Clipboard.hasObject)\n                p.objectReferenceValue = Clipboard.objectValue;\n            else if (Clipboard.hasGuid)\n                p.objectReferenceValue = AssetDatabase.LoadMainAssetAtGUID(Clipboard.guidValue);\n            else if (!new GUID(AssetDatabase.AssetPathToGUID(Clipboard.stringValue)).Empty())\n                p.objectReferenceValue = AssetDatabase.LoadMainAssetAtPath(Clipboard.stringValue);\n            p.serializedObject.ApplyModifiedProperties();\n        }\n\n        static void SetupObjectReference(SerializedProperty property, GenericMenu menu, Event evt)\n        {\n            var hasPasteObject = Clipboard.hasObject;\n            var hasPasteGuid = Clipboard.hasGuid;\n            var hasPastePath = !new GUID(AssetDatabase.AssetPathToGUID(Clipboard.stringValue)).Empty();\n            var obj = property.objectReferenceValue;\n\n            var canCopy = !property.hasMultipleDifferentValues && obj != null;\n            var canPaste = GUI.enabled && (hasPasteGuid || hasPastePath || hasPasteObject);\n\n            if (menu != null)\n            {\n                AddSeparator(menu);\n                var hasAsset = canCopy && AssetDatabase.Contains(obj);\n                if (canCopy)\n                    menu.AddItem(kCopyContent, false, o => Clipboard.objectValue = (UnityEngine.Object)o, obj);\n                else\n                    menu.AddDisabledItem(kCopyContent);\n                if (hasAsset)\n                {\n                    menu.AddItem(kCopyPathContent, false, o => Clipboard.stringValue = AssetDatabase.GetAssetPath((UnityEngine.Object)o).ToString(), obj);\n                    menu.AddItem(kCopyGuidContent, false, o => Clipboard.guidValue = new GUID(AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath((UnityEngine.Object)o))), obj);\n                }\n                else\n                {\n                    menu.AddDisabledItem(kCopyPathContent);\n                    menu.AddDisabledItem(kCopyGuidContent);\n                }\n\n                if (canPaste)\n                    menu.AddItem(kPasteContent, false, o => PasteObjectReference((SerializedProperty)o), property);\n                else\n                    menu.AddDisabledItem(kPasteContent);\n            }\n\n            if (evt != null)\n            {\n                if (canCopy && evt.commandName == EventCommandNames.Copy)\n                {\n                    if (evt.type == EventType.ValidateCommand)\n                        evt.Use();\n                    if (evt.type == EventType.ExecuteCommand)\n                    {\n                        Clipboard.objectValue = obj;\n                        evt.Use();\n                    }\n                }\n                if (canPaste && evt.commandName == EventCommandNames.Paste)\n                {\n                    if (evt.type == EventType.ValidateCommand)\n                        evt.Use();\n                    if (evt.type == EventType.ExecuteCommand)\n                    {\n                        PasteObjectReference(property);\n                        evt.Use();\n                    }\n                }\n            }\n        }\n\n        //\n        // Clipboard related Transform component context menus\n        //\n\n        [MenuItem(\"CONTEXT/Transform/Copy/Position\", false, 100100)] // ReSharper disable once UnusedMember.Local\n        static void CopyTransformPositionMenu(MenuCommand command)\n        {\n            var tr = command.context as Transform;\n            if (tr == null)\n                return;\n            Clipboard.vector3Value = tr.localPosition;\n        }\n\n        [MenuItem(\"CONTEXT/Transform/Paste/Position\", true)] // ReSharper disable once UnusedMember.Local\n        static bool PasteTransformPositionMenuValidate(MenuCommand command)\n        {\n            var tr = command.context as Transform;\n            return tr != null && Clipboard.hasVector3 && IsUserModifiable(tr);\n        }\n\n        [MenuItem(\"CONTEXT/Transform/Paste/Position\", false, 100100)] // ReSharper disable once UnusedMember.Local\n        static void PasteTransformPositionMenu(MenuCommand command)\n        {\n            var tr = command.context as Transform;\n            if (tr == null)\n                return;\n            Undo.RecordObject(tr, $\"Paste {tr.gameObject.name} Position\");\n            tr.localPosition = Clipboard.vector3Value;\n        }\n\n        [MenuItem(\"CONTEXT/Transform/Copy/Rotation\", false, 100102)] // ReSharper disable once UnusedMember.Local\n        static void CopyTransformRotationMenu(MenuCommand command)\n        {\n            var tr = command.context as Transform;\n            if (tr == null)\n                return;\n            Clipboard.vector3Value = tr.localEulerAngles;\n        }\n\n        [MenuItem(\"CONTEXT/Transform/Paste/Rotation\", true)] // ReSharper disable once UnusedMember.Local\n        static bool PasteTransformRotationMenuValidate(MenuCommand command)\n        {\n            var tr = command.context as Transform;\n            return tr != null && (Clipboard.hasVector3 || Clipboard.hasQuaternion) && IsUserModifiable(tr);\n        }\n\n        [MenuItem(\"CONTEXT/Transform/Paste/Rotation\", false, 100102)] // ReSharper disable once UnusedMember.Local\n        static void PasteTransformRotationMenu(MenuCommand command)\n        {\n            var tr = command.context as Transform;\n            if (tr == null)\n                return;\n            Undo.RecordObject(tr, $\"Paste {tr.gameObject.name} Rotation\");\n            if (Clipboard.hasQuaternion)\n                tr.localRotation = Clipboard.quaternionValue;\n            else\n                tr.localEulerAngles = Clipboard.vector3Value;\n        }\n\n        [MenuItem(\"CONTEXT/Transform/Copy/Scale\", false, 100103)] // ReSharper disable once UnusedMember.Local\n        static void CopyTransformScaleMenu(MenuCommand command)\n        {\n            var tr = command.context as Transform;\n            if (tr == null)\n                return;\n            Clipboard.vector3Value = tr.localScale;\n        }\n\n        [MenuItem(\"CONTEXT/Transform/Paste/Scale\", true)] // ReSharper disable once UnusedMember.Local\n        static bool PasteTransformScaleMenuValidate(MenuCommand command)\n        {\n            var tr = command.context as Transform;\n            return tr != null && Clipboard.hasVector3 && IsUserModifiable(tr);\n        }\n\n        [MenuItem(\"CONTEXT/Transform/Paste/Scale\", false, 100103)] // ReSharper disable once UnusedMember.Local\n        static void PasteTransformScaleMenu(MenuCommand command)\n        {\n            var tr = command.context as Transform;\n            if (tr == null)\n                return;\n            Undo.RecordObject(tr, $\"Paste {tr.gameObject.name} Scale\");\n            tr.localScale = Clipboard.vector3Value;\n        }\n\n        [MenuItem(\"CONTEXT/Transform/Copy/World Transform\", false, 100150)] // ReSharper disable once UnusedMember.Local\n        static void CopyTransformWorldPlacementMenu(MenuCommand command)\n        {\n            var tr = command.context as Transform;\n            if (tr == null)\n                return;\n            Clipboard.SetCustomValue(new TransformWorldPlacement(tr));\n        }\n\n        [MenuItem(\"CONTEXT/Transform/Paste/World Transform\", true)] // ReSharper disable once UnusedMember.Local\n        static bool PasteTransformWorldPlacementMenuValidate(MenuCommand command)\n        {\n            var tr = command.context as Transform;\n            return tr != null && IsUserModifiable(tr) && Clipboard.HasCustomValue<TransformWorldPlacement>();\n        }\n\n        [MenuItem(\"CONTEXT/Transform/Paste/World Transform\", false, 100150)] // ReSharper disable once UnusedMember.Local\n        static void PasteTransformWorldPlacementMenu(MenuCommand command)\n        {\n            var tr = command.context as Transform;\n            if (tr == null)\n                return;\n            Undo.RecordObject(tr, $\"Paste {tr.gameObject.name} World Placement\");\n            var placement = Clipboard.GetCustomValue<TransformWorldPlacement>();\n            tr.position = placement.position;\n            tr.rotation = placement.rotation;\n            tr.localScale = placement.scale;\n        }\n\n        //@TODO This really should be a helper utility somewhere else\n        static bool IsUserModifiable(UnityEngine.Object o)\n        {\n            if (o == null)\n                return false;\n            if ((o.hideFlags & HideFlags.NotEditable) != 0)\n                return false;\n            if (EditorUtility.IsPersistent(o))\n            {\n                if (PrefabUtility.IsPartOfImmutablePrefab(o))\n                    return false;\n                if (!Editor.IsAppropriateFileOpenForEdit(o))\n                    return false;\n            }\n            return true;\n        }\n    }\n\n    [Serializable]\n    internal class TransformWorldPlacement\n    {\n        public TransformWorldPlacement()\n        {\n            position = Vector3.zero;\n            rotation = Quaternion.identity;\n            scale = Vector3.one;\n        }\n\n        public TransformWorldPlacement(Transform t)\n        {\n            position = t.position;\n            rotation = t.rotation;\n            scale = t.localScale;\n        }\n\n        public Vector3 position;\n        public Quaternion rotation;\n        public Vector3 scale;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Clipboard/ClipboardParser.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Text;\nusing System.Text.RegularExpressions;\nusing UnityEditor.Build.Content;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\n// ReSharper disable once CheckNamespace - we explicitly want UnityEditor namespace\nnamespace UnityEditor\n{\n    internal static class ClipboardParser\n    {\n        public static bool ParseGuid(string text, out GUID res)\n        {\n            res = new GUID();\n            if (string.IsNullOrEmpty(text))\n                return false;\n            return GUID.TryParse(text, out res);\n        }\n\n        public static bool ParseHash128(string text, out Hash128 res)\n        {\n            res = new Hash128();\n            if (string.IsNullOrEmpty(text))\n                return false;\n            res = Hash128.Parse(text);\n            return res.isValid;\n        }\n\n        public static bool ParseBool(string text, out bool res)\n        {\n            res = false;\n            if (string.IsNullOrEmpty(text))\n                return false;\n            return bool.TryParse(text, out res);\n        }\n\n        public static bool ParseLayerMask(string text, out LayerMask res)\n        {\n            res = 0;\n            if (string.IsNullOrEmpty(text))\n                return false;\n\n            var match = Regex.Match(text, @\"^LayerMask\\(([\\-0-9]+)\\)\");\n            if (match.Success && match.Groups.Count > 1)\n            {\n                if (int.TryParse(match.Groups[1].Value, out var id))\n                {\n                    res = id;\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public static bool ParseRenderingLayerMask(string text, out RenderingLayerMask res)\n        {\n            res = 0;\n            if (string.IsNullOrEmpty(text))\n                return false;\n\n            var match = Regex.Match(text, @\"^RenderingLayerMask\\(([0-9]+)\\)\");\n            if (match.Success && match.Groups.Count > 1)\n            {\n                if (uint.TryParse(match.Groups[1].Value, out var id))\n                {\n                    res = id;\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        static float[] ParseFloats(string text, string prefix, int count)\n        {\n            if (string.IsNullOrEmpty(text))\n                return null;\n\n            // build a regex that matches \"Prefix(a,b,c,...)\" at start of text\n            var sb = new StringBuilder();\n            sb.Append('^');\n            sb.Append(prefix);\n            sb.Append(\"\\\\(\");\n            for (var i = 0; i < count; ++i)\n            {\n                if (i != 0)\n                    sb.Append(',');\n                sb.Append(\"([^,]+)\");\n            }\n            sb.Append(\"\\\\)\");\n\n            var match = Regex.Match(text, sb.ToString());\n            if (!match.Success || match.Groups.Count <= count)\n                return null;\n\n            var res = new float[count];\n            for (var i = 0; i < count; ++i)\n            {\n                if (float.TryParse(match.Groups[i + 1].Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var f))\n                    res[i] = f;\n                else\n                    return null;\n            }\n            return res;\n        }\n\n        public static bool ParseVector3(string text, out Vector3 res)\n        {\n            res = Vector3.zero;\n            var v = ParseFloats(text, \"Vector3\", 3);\n            if (v == null)\n                return false;\n            res = new Vector3(v[0], v[1], v[2]);\n            return true;\n        }\n\n        public static string WriteVector3(Vector3 value)\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"Vector3({0:g9},{1:g9},{2:g9})\", value.x, value.y, value.z);\n        }\n\n        public static bool ParseVector2(string text, out Vector2 res)\n        {\n            res = Vector2.zero;\n            var v = ParseFloats(text, \"Vector2\", 2);\n            if (v == null)\n                return false;\n            res = new Vector2(v[0], v[1]);\n            return true;\n        }\n\n        public static string WriteVector2(Vector2 value)\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"Vector2({0:g9},{1:g9})\", value.x, value.y);\n        }\n\n        public static bool ParseVector4(string text, out Vector4 res)\n        {\n            res = Vector4.zero;\n            var v = ParseFloats(text, \"Vector4\", 4);\n            if (v == null)\n                return false;\n            res = new Vector4(v[0], v[1], v[2], v[3]);\n            return true;\n        }\n\n        public static string WriteVector4(Vector4 value)\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"Vector4({0:g9},{1:g9},{2:g9},{3:g9})\", value.x, value.y, value.z, value.w);\n        }\n\n        public static bool ParseRect(string text, out Rect res)\n        {\n            res = Rect.zero;\n            var v = ParseFloats(text, \"Rect\", 4);\n            if (v == null)\n                return false;\n            res = new Rect(v[0], v[1], v[2], v[3]);\n            return true;\n        }\n\n        public static string WriteRect(Rect value)\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"Rect({0:g9},{1:g9},{2:g9},{3:g9})\", value.x, value.y, value.width, value.height);\n        }\n\n        public static bool ParseBounds(string text, out Bounds res)\n        {\n            res = new Bounds();\n            var v = ParseFloats(text, \"Bounds\", 6);\n            if (v == null)\n                return false;\n            res = new Bounds(new Vector3(v[0], v[1], v[2]), new Vector3(v[3] * 2, v[4] * 2, v[5] * 2));\n            return true;\n        }\n\n        public static string WriteBounds(Bounds value)\n        {\n            return string.Format(CultureInfo.InvariantCulture,\n                \"Bounds({0:g9},{1:g9},{2:g9},{3:g9},{4:g9},{5:g9})\",\n                value.center.x, value.center.y, value.center.z, value.extents.x, value.extents.y, value.extents.z);\n        }\n\n        public static bool ParseQuaternion(string text, out Quaternion res)\n        {\n            res = Quaternion.identity;\n            var v = ParseFloats(text, \"Quaternion\", 4);\n            if (v == null)\n                return false;\n            res = new Quaternion(v[0], v[1], v[2], v[3]);\n            return true;\n        }\n\n        internal static bool? ParseInteger(string text, out int res)\n        {\n            res = 0;\n            if (string.IsNullOrEmpty(text))\n                return false;\n            return int.TryParse(text, out res);\n        }\n\n        internal static bool? ParseLong(string text, out long res)\n        {\n            res = 0;\n            if (string.IsNullOrEmpty(text))\n                return false;\n            return long.TryParse(text, out res);\n        }\n\n        internal static bool? ParseUlong(string text, out ulong res)\n        {\n            res = 0;\n            if (string.IsNullOrEmpty(text))\n                return false;\n            return ulong.TryParse(text, out res);\n        }\n\n        internal static bool? ParseUint(string text, out uint res)\n        {\n            res = 0;\n            if(string.IsNullOrEmpty(text))\n                return false;\n            return uint.TryParse(text, out res);\n        }\n\n        internal static bool? ParseFloat(string text, out float res)\n        {\n            res = 0;\n            if (string.IsNullOrEmpty(text))\n                return false;\n            return float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out res);\n        }\n\n        public static string WriteQuaternion(Quaternion value)\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"Quaternion({0:g9},{1:g9},{2:g9},{3:g9})\", value.x, value.y, value.z, value.w);\n        }\n\n        public static bool ParseColor(string text, out Color res)\n        {\n            res = Color.black;\n            if (string.IsNullOrEmpty(text))\n                return false;\n\n            if (ColorUtility.TryParseHtmlString(text, out res))\n                return true;\n\n            var v = ParseFloats(text, \"Color\", 4);\n            if (v == null)\n                return false;\n            res = new Color(v[0], v[1], v[2], v[3]);\n            return true;\n        }\n\n        public static string WriteColor(Color val)\n        {\n            // check if this is a color that can be represented in LDR fine\n            Color32 ldr = val;\n            Color hdrFromLdr = ldr;\n            if (((Vector4)val - (Vector4)hdrFromLdr).sqrMagnitude < 0.0001f)\n            {\n                if (ldr.a == 255)\n                    return '#' + ColorUtility.ToHtmlStringRGB(val);\n                return '#' + ColorUtility.ToHtmlStringRGBA(val);\n            }\n\n            return string.Format(CultureInfo.InvariantCulture, \"Color({0:g9},{1:g9},{2:g9},{3:g9})\", val.r, val.g, val.b, val.a);\n        }\n\n        internal const string kEnumPrefix = \"Enum:\";\n\n        public static int ParseEnumPropertyIndex(string text, SerializedProperty prop)\n        {\n            if (!text.StartsWith(kEnumPrefix))\n                return -1;\n            var val = text.Substring(kEnumPrefix.Length);\n            if (string.IsNullOrEmpty(val))\n                return -1;\n            var names = prop.enumDisplayNames;\n            var idx = Array.IndexOf(names, val);\n            if (idx < 0)\n                return -1;\n            return idx;\n        }\n\n        public static int ParseEnumPropertyFlag(string text, SerializedProperty prop)\n        {\n            if (!text.StartsWith(kEnumPrefix))\n                return -1;\n            var val = text.Substring(kEnumPrefix.Length);\n            if (string.IsNullOrEmpty(val))\n                return -1;\n\n            try\n            {\n                var flag = Convert.ToInt32(val, 2);\n\n                if (flag > -1)\n                    return flag;\n                return -1;\n            }\n            catch\n            {\n                return -1;\n            }\n        }\n\n        public static void ParseEnumProperty(string text, SerializedProperty prop)\n        {\n            var idx = ParseEnumPropertyIndex(text, prop);\n            if (idx >= 0)\n                prop.enumValueIndex = idx;\n            else\n            {\n                var flag = ParseEnumPropertyFlag(text, prop);\n                if (flag >= 0)\n                    prop.enumValueFlag = flag;\n            }\n        }\n\n        public static string WriteEnumProperty(SerializedProperty prop)\n        {\n            if (prop.propertyType != SerializedPropertyType.Enum)\n                return string.Empty;\n            var idx = prop.enumValueIndex;\n            var names = prop.enumDisplayNames;\n            if (idx < 0 || idx >= names.Length)\n            {\n                var binary = Convert.ToString(prop.enumValueFlag, 2);\n                binary = binary.PadLeft(names.Length, '0');\n                return $\"{kEnumPrefix}{binary}\";\n            }\n\n            return $\"{kEnumPrefix}{names[idx]}\";\n        }\n\n        public static bool ParseCustom<T>(string text, out T res) where T : new()\n        {\n            res = new T();\n            if (string.IsNullOrEmpty(text))\n                return false;\n            var prefix = CustomPrefix<T>();\n            if (!text.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))\n                return false;\n            try\n            {\n                EditorJsonUtility.FromJsonOverwrite(text.Substring(prefix.Length), res);\n            }\n            catch (ArgumentException)\n            {\n                return false;\n            }\n            return true;\n        }\n\n        public static string WriteCustom<T>(T val)\n        {\n            return CustomPrefix<T>() + EditorJsonUtility.ToJson(val);\n        }\n\n        static string CustomPrefix<T>()\n        {\n            return typeof(T).FullName + \"JSON:\";\n        }\n\n        static object GetIntegerValue(in SerializedProperty p)\n        {\n            switch (p.type)\n            {\n                case \"long\":\n                case \"ulong\":\n                    return p.longValue;\n            }\n\n            return p.intValue;\n        }\n\n        // Given a serialized property, produce an object structure for JSON encoding of it.\n        internal static Dictionary<string, object> WriteGenericSerializedProperty(SerializedProperty p)\n        {\n            var res = new Dictionary<string, object>\n            {\n                [\"name\"] = p.name,\n                [\"type\"] = (int)p.propertyType\n            };\n            switch (p.propertyType)\n            {\n                case SerializedPropertyType.Integer:\n                case SerializedPropertyType.LayerMask:\n                case SerializedPropertyType.Character:\n                    res[\"val\"] = GetIntegerValue(p); break;\n                case SerializedPropertyType.RenderingLayerMask:\n                    res[\"val\"] = p.uintValue; break;\n                case SerializedPropertyType.Boolean: res[\"val\"] = p.boolValue; break;\n                case SerializedPropertyType.Float: res[\"val\"] = p.floatValue; break;\n                case SerializedPropertyType.String: res[\"val\"] = p.stringValue; break;\n                case SerializedPropertyType.ObjectReference: res[\"val\"] = WriteCustom(new ObjectWrapper(p.objectReferenceValue)); break;\n                case SerializedPropertyType.ArraySize: res[\"val\"] = p.intValue; break;\n                case SerializedPropertyType.AnimationCurve: res[\"val\"] = WriteCustom(new AnimationCurveWrapper(p.animationCurveValue)); break;\n                case SerializedPropertyType.Enum: res[\"val\"] = WriteEnumProperty(p); break;\n                case SerializedPropertyType.Bounds: res[\"val\"] = WriteBounds(p.boundsValue); break;\n                case SerializedPropertyType.Gradient: res[\"val\"] = WriteCustom(new GradientWrapper(p.gradientValue)); break;\n                case SerializedPropertyType.Quaternion: res[\"val\"] = WriteQuaternion(p.quaternionValue); break;\n                case SerializedPropertyType.Vector2Int: res[\"val\"] = WriteVector2(p.vector2IntValue); break;\n                case SerializedPropertyType.Vector3Int: res[\"val\"] = WriteVector3(p.vector3IntValue); break;\n                case SerializedPropertyType.RectInt:\n                    var ri = p.rectIntValue;\n                    res[\"val\"] = WriteRect(new Rect(ri.x, ri.y, ri.width, ri.height));\n                    break;\n                case SerializedPropertyType.BoundsInt:\n                    var bi = p.boundsIntValue;\n                    res[\"val\"] = WriteBounds(new Bounds(bi.center, bi.size));\n                    break;\n\n                // Copy/Paste of these for generic serialized properties is not implemented yet.\n                case SerializedPropertyType.ExposedReference: break;\n                case SerializedPropertyType.FixedBufferSize: break;\n                case SerializedPropertyType.ManagedReference: break;\n\n                default:\n                    if (p.isArray)\n                    {\n                        res[\"arraySize\"] = p.arraySize;\n                        res[\"arrayType\"] = p.arrayElementType;\n                    }\n                    if (p.hasChildren)\n                    {\n                        var children = new List<object>();\n                        SerializedProperty chit = p.Copy();\n                        var end = chit.GetEndProperty();\n                        chit.Next(true);\n                        while (!SerializedProperty.EqualContents(chit, end))\n                        {\n                            children.Add(WriteGenericSerializedProperty(chit));\n                            if (!chit.Next(false))\n                                break;\n                        }\n                        res[\"children\"] = children;\n                    }\n                    break;\n            }\n            return res;\n        }\n\n        // Given an object structure from JSON encoding, apply that to a serialized property.\n        internal static void ParseGenericSerializedProperty(SerializedProperty prop, Dictionary<string, object> obj)\n        {\n            if (prop == null)\n                return;\n            if (!obj.TryGetValue(\"name\", out var oName)) return;\n            var name = oName as string;\n            if (string.IsNullOrEmpty(name)) return;\n\n            if (!obj.TryGetValue(\"type\", out var oType)) return;\n            if (!(oType is long)) return;\n            try\n            {\n                var propertyType = (SerializedPropertyType)Convert.ToInt32(oType);\n                if (propertyType != prop.propertyType)\n                    return;\n                obj.TryGetValue(\"val\", out var oval);\n\n                switch (propertyType)\n                {\n                    case SerializedPropertyType.Integer:\n                    case SerializedPropertyType.LayerMask:\n                    case SerializedPropertyType.Character:\n                        if (string.Equals(prop.type, \"long\", StringComparison.Ordinal) ||\n                            string.Equals(prop.type, \"ulong\", StringComparison.Ordinal))\n                            prop.longValue = Convert.ToInt64(oval);\n                        else\n                            prop.intValue = Convert.ToInt32(oval);\n                        break;\n                    case SerializedPropertyType.RenderingLayerMask:\n                        prop.uintValue = Convert.ToUInt32(oval);\n                        break;\n                    case SerializedPropertyType.Boolean:\n                        prop.boolValue = Convert.ToBoolean(oval);\n                        break;\n                    case SerializedPropertyType.Float:\n                        prop.floatValue = Convert.ToSingle(oval);\n                        break;\n                    case SerializedPropertyType.String:\n                        prop.stringValue = Convert.ToString(oval);\n                        break;\n                    case SerializedPropertyType.ObjectReference:\n                        if (ParseCustom<ObjectWrapper>(Convert.ToString(oval), out var objectWrapper))\n                            prop.objectReferenceValue = objectWrapper.ToObject();\n                        break;\n                    case SerializedPropertyType.ArraySize:\n                        prop.arraySize = Convert.ToInt32(oval);\n                        break;\n                    case SerializedPropertyType.AnimationCurve:\n                        if (ParseCustom<AnimationCurveWrapper>(Convert.ToString(oval), out var animWrapper))\n                            prop.animationCurveValue = animWrapper.curve;\n                        break;\n                    case SerializedPropertyType.Enum:\n                        ParseEnumProperty(Convert.ToString(oval), prop);\n                        break;\n                    case SerializedPropertyType.Bounds:\n                        if (ParseBounds(Convert.ToString(oval), out var boundsValue))\n                            prop.boundsValue = boundsValue;\n                        break;\n                    case SerializedPropertyType.Gradient:\n                        if (ParseCustom<GradientWrapper>(Convert.ToString(oval), out var gradientWrapper))\n                        {\n                            prop.gradientValue = gradientWrapper.gradient;\n                            UnityEditorInternal.GradientPreviewCache.ClearCache();\n                        }\n                        break;\n                    case SerializedPropertyType.Quaternion:\n                        if (ParseQuaternion(Convert.ToString(oval), out var quaternionValue))\n                            prop.quaternionValue = quaternionValue;\n                        break;\n                    case SerializedPropertyType.Vector2Int:\n                        if (ParseVector2(Convert.ToString(oval), out var v2Value))\n                            prop.vector2IntValue = new Vector2Int((int)v2Value.x, (int)v2Value.y);\n                        break;\n                    case SerializedPropertyType.Vector3Int:\n                        if (ParseVector3(Convert.ToString(oval), out var v3Value))\n                            prop.vector3IntValue = new Vector3Int((int)v3Value.x, (int)v3Value.y, (int)v3Value.z);\n                        break;\n                    case SerializedPropertyType.RectInt:\n                        if (ParseRect(Convert.ToString(oval), out var rectValue))\n                            prop.rectIntValue = new RectInt((int)rectValue.x, (int)rectValue.y, (int)rectValue.width, (int)rectValue.height);\n                        break;\n                    case SerializedPropertyType.BoundsInt:\n                        if (ParseBounds(Convert.ToString(oval), out var biValue))\n                            prop.boundsIntValue = new BoundsInt(\n                                new Vector3Int((int)biValue.center.x, (int)biValue.center.y, (int)biValue.center.z),\n                                new Vector3Int((int)biValue.size.x, (int)biValue.size.y, (int)biValue.size.z));\n                        break;\n\n                    // Copy/Paste of these for generic serialized properties is not implemented yet.\n                    case SerializedPropertyType.FixedBufferSize: break;\n                    case SerializedPropertyType.ExposedReference: break;\n                    case SerializedPropertyType.ManagedReference: break;\n\n                    default:\n                        if (prop.isArray)\n                        {\n                            if (!obj.TryGetValue(\"arraySize\", out var oArraySize))\n                                return;\n                            if (!obj.TryGetValue(\"arrayType\", out var oArrayType))\n                                return;\n                            if (Convert.ToString(oArrayType) != prop.arrayElementType)\n                                return;\n                            prop.arraySize = Convert.ToInt32(oArraySize);\n                        }\n\n                        if (prop.hasChildren)\n                        {\n                            if (!obj.TryGetValue(\"children\", out var oChildren))\n                                return;\n                            if (!(oChildren is List<object> children))\n                                return;\n\n                            SerializedProperty chit = prop.Copy();\n                            var end = chit.GetEndProperty();\n                            chit.Next(true);\n                            var index = 0;\n                            while (!SerializedProperty.EqualContents(chit, end) && index < children.Count)\n                            {\n                                if (!(children[index] is Dictionary<string, object> ch))\n                                    return;\n                                ParseGenericSerializedProperty(chit, ch);\n                                if (!chit.Next(false))\n                                    break;\n                                ++index;\n                            }\n                        }\n\n                        break;\n                }\n            }\n            catch (InvalidCastException)\n            {\n            }\n        }\n    }\n\n    [Serializable]\n    internal class ObjectWrapper\n    {\n        public ObjectWrapper() {}\n\n        public ObjectWrapper(Object o)\n        {\n            if (o == null)\n                return;\n            instanceID = o.GetInstanceID();\n            if (!ObjectIdentifier.TryGetObjectIdentifier(o, out var id))\n                return;\n            guid = id.guid.ToString();\n            localId = id.localIdentifierInFile;\n            type = id.fileType;\n        }\n\n        public Object ToObject()\n        {\n            var id = new ObjectIdentifier\n            {\n                guid = new GUID(guid),\n                localIdentifierInFile = localId,\n                fileType = type\n            };\n            if (!id.guid.Empty())\n            {\n                var o = ObjectIdentifier.ToObject(id);\n                if (o != null)\n                    return o;\n            }\n            return EditorUtility.InstanceIDToObject(instanceID);\n        }\n\n        // guid/localId/type are for asset references; these are used if present\n        public string guid = \"\";\n        public long localId = 0;\n        public FileType type = FileType.NonAssetType;\n        // instanceIDs are for in-scene references, not stable across sessions but fine for local copy/paste\n        public int instanceID = 0;\n    }\n\n    [Serializable]\n    internal class GradientWrapper\n    {\n        public GradientWrapper() { gradient = new Gradient(); }\n        public GradientWrapper(Gradient g) { gradient = g; }\n        public Gradient gradient;\n    }\n\n    [Serializable]\n    internal class AnimationCurveWrapper\n    {\n        public AnimationCurveWrapper() { curve = new AnimationCurve(); }\n        public AnimationCurveWrapper(AnimationCurve g) { curve = g; }\n        public AnimationCurve curve;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Clipboard/ClipboardState.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\n// ReSharper disable once CheckNamespace - we explicitly want UnityEditor namespace\nnamespace UnityEditor\n{\n    // Holds cache/state of things present in clipboard, for a particular clipboard\n    // contents value. Once system clipboard changes, a new state is re-created.\n    // Doing queries or gets into the state (e.g. query for presence of color in the clipboard)\n    // is cached and figured out only once per state lifetime.\n    internal class ClipboardState\n    {\n        internal string m_RawContents;\n\n        internal bool? m_HasGuid;\n        internal GUID m_ValueGuid;\n        internal void FetchGuid()\n        {\n            if (!m_HasGuid.HasValue)\n                m_HasGuid = ClipboardParser.ParseGuid(m_RawContents, out m_ValueGuid);\n        }\n\n        internal bool? m_HasHash128;\n        internal Hash128 m_ValueHash128;\n        internal void FetchHash128()\n        {\n            if (!m_HasHash128.HasValue)\n                m_HasHash128 = ClipboardParser.ParseHash128(m_RawContents, out m_ValueHash128);\n        }\n\n        internal bool? m_HasBool;\n        internal bool m_ValueBool;\n        internal void FetchBool()\n        {\n            if (!m_HasBool.HasValue)\n                m_HasBool = ClipboardParser.ParseBool(m_RawContents, out m_ValueBool);\n        }\n\n        internal bool? m_HasLayerMask;\n        internal LayerMask m_ValueLayerMask;\n        internal void FetchLayerMask()\n        {\n            if (!m_HasLayerMask.HasValue)\n                m_HasLayerMask = ClipboardParser.ParseLayerMask(m_RawContents, out m_ValueLayerMask);\n        }\n\n        internal bool? m_HasRenderingLayerMask;\n        internal RenderingLayerMask m_ValueRenderingLayerMask;\n        internal void FetchRenderingLayerMask()\n        {\n            if (!m_HasRenderingLayerMask.HasValue)\n                m_HasRenderingLayerMask = ClipboardParser.ParseRenderingLayerMask(m_RawContents, out m_ValueRenderingLayerMask);\n        }\n\n        internal bool? m_HasVector3;\n        internal Vector3 m_ValueVector3;\n        internal void FetchVector3()\n        {\n            if (!m_HasVector3.HasValue)\n                m_HasVector3 = ClipboardParser.ParseVector3(m_RawContents, out m_ValueVector3);\n        }\n\n        internal bool? m_HasVector2;\n        internal Vector2 m_ValueVector2;\n        internal void FetchVector2()\n        {\n            if (!m_HasVector2.HasValue)\n                m_HasVector2 = ClipboardParser.ParseVector2(m_RawContents, out m_ValueVector2);\n        }\n\n        internal bool? m_HasVector4;\n        internal Vector4 m_ValueVector4;\n        internal void FetchVector4()\n        {\n            if (!m_HasVector4.HasValue)\n                m_HasVector4 = ClipboardParser.ParseVector4(m_RawContents, out m_ValueVector4);\n        }\n\n        internal bool? m_HasQuaternion;\n        internal Quaternion m_ValueQuaternion;\n        internal void FetchQuaternion()\n        {\n            if (!m_HasQuaternion.HasValue)\n                m_HasQuaternion = ClipboardParser.ParseQuaternion(m_RawContents, out m_ValueQuaternion);\n        }\n\n        internal bool? m_HasColor;\n        internal Color m_ValueColor;\n        internal void FetchColor()\n        {\n            if (!m_HasColor.HasValue)\n                m_HasColor = ClipboardParser.ParseColor(m_RawContents, out m_ValueColor);\n        }\n\n        internal bool? m_HasRect;\n        internal Rect m_ValueRect;\n        internal void FetchRect()\n        {\n            if (!m_HasRect.HasValue)\n                m_HasRect = ClipboardParser.ParseRect(m_RawContents, out m_ValueRect);\n        }\n\n        internal bool? m_HasBounds;\n        internal Bounds m_ValueBounds;\n        internal void FetchBounds()\n        {\n            if (!m_HasBounds.HasValue)\n                m_HasBounds = ClipboardParser.ParseBounds(m_RawContents, out m_ValueBounds);\n        }\n\n        internal bool? m_HasObject;\n        internal Object m_ValueObject;\n        internal void FetchObject()\n        {\n            if (!m_HasObject.HasValue)\n            {\n                m_HasObject = ClipboardParser.ParseCustom<ObjectWrapper>(m_RawContents, out var wrapper);\n                m_ValueObject = wrapper.ToObject();\n            }\n        }\n\n        internal bool? m_HasGradient;\n        internal Gradient m_ValueGradient;\n        internal void FetchGradient()\n        {\n            if (!m_HasGradient.HasValue)\n            {\n                m_HasGradient = ClipboardParser.ParseCustom<GradientWrapper>(m_RawContents, out var wrapper);\n                m_ValueGradient = wrapper.gradient;\n            }\n        }\n\n        internal bool? m_HasAnimationCurve;\n        internal AnimationCurve m_ValueAnimationCurve;\n        internal void FetchAnimationCurve()\n        {\n            if (!m_HasAnimationCurve.HasValue)\n            {\n                m_HasAnimationCurve = ClipboardParser.ParseCustom<AnimationCurveWrapper>(m_RawContents, out var wrapper);\n                m_ValueAnimationCurve = wrapper.curve;\n            }\n        }\n\n        readonly Dictionary<Type, object> m_ValuesCustom = new Dictionary<Type, object>();\n\n        internal bool FetchCustom<T>(out T res) where T : new()\n        {\n            var key = typeof(T);\n            if (m_ValuesCustom.TryGetValue(key, out var cached))\n            {\n                if (cached != null)\n                {\n                    res = (T)cached;\n                    return true;\n                }\n                res = default;\n                return false;\n            }\n            var ok = ClipboardParser.ParseCustom(m_RawContents, out res);\n            m_ValuesCustom.Add(key, ok ? res : default);\n            return ok;\n        }\n\n        internal bool? m_HasInteger;\n        internal int m_ValueInteger;\n        internal void FetchInteger()\n        {\n            if (!m_HasInteger.HasValue)\n                m_HasInteger = ClipboardParser.ParseInteger(m_RawContents, out m_ValueInteger);\n        }\n\n        internal bool? m_HasLong;\n        internal long m_ValueLong;\n\n        internal void FetchLong()\n        {\n            if (!m_HasLong.HasValue)\n                m_HasLong = ClipboardParser.ParseLong(m_RawContents, out m_ValueLong);\n        }\n\n        internal bool? m_HasUlong;\n        internal ulong m_ValueUlong;\n\n        internal void FetchUlong()\n        {\n            if (!m_HasUlong.HasValue)\n                m_HasUlong = ClipboardParser.ParseUlong(m_RawContents, out m_ValueUlong);\n        }\n\n        internal bool? m_HasUint;\n        internal uint m_ValueUint;\n\n        internal void FetchUint()\n        {\n            if (!m_HasUint.HasValue)\n                m_HasUint = ClipboardParser.ParseUint(m_RawContents, out m_ValueUint);\n        }\n\n        internal bool? m_HasFloat;\n        internal float m_ValueFloat;\n        internal void FetchFloat()\n        {\n            if (!m_HasFloat.HasValue)\n                m_HasFloat = ClipboardParser.ParseFloat(m_RawContents, out m_ValueFloat);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ClipboardUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\n\nnamespace UnityEditor\n{\n    public static class ClipboardUtility\n    {\n        public static Func<GameObject, bool> canCopyGameObject;\n        public static Func<GameObject, bool> canCutGameObject;\n        public static Func<GameObject, bool> canDuplicateGameObject;\n        public static event Action<GameObject[]> copyingGameObjects;\n        public static event Action<GameObject[]> cuttingGameObjects;\n        public static event Action<GameObject[]> duplicatingGameObjects;\n        public static event Action<GameObject[]> duplicatedGameObjects;\n        public static event Action<GameObject[]> rejectedGameObjects;\n        public static event Action<GameObject[]> pastedGameObjects;\n\n        private static void FilterSelection(Func<GameObject, bool> filter)\n        {\n            if (filter == null)\n                return;\n\n            // If we dont have any filters we really should just leave right now\n            Delegate[] invocationList = filter.GetInvocationList();\n            int invocationListLength = invocationList.Length;\n\n            if (invocationListLength == 0)\n                return;\n\n            // Make our tracking objects\n            int selectedGameObjectsLength = Selection.gameObjects.Length;\n            Queue<UnityEngine.Object> pass = new Queue<UnityEngine.Object>(selectedGameObjectsLength);\n            Queue<GameObject> fail = new Queue<GameObject>(selectedGameObjectsLength);\n\n            // Iterate through our selected game objects, checking each\n            for (int i = 0; i < selectedGameObjectsLength; i++)\n            {\n                GameObject currentGameObject = Selection.gameObjects[i];\n\n                bool shouldInclude = true;\n                for (int j = 0; j < invocationListLength; j++)\n                {\n                    Func<GameObject, bool> func = (Func<GameObject, bool>)invocationList[j];\n\n                    // Passed, next check\n                    if (func.Invoke(currentGameObject))\n                        continue;\n\n                    // Failed, add to failures\n                    if (fail.Contains(currentGameObject))\n                        continue;\n\n                    fail.Enqueue(currentGameObject);\n                    shouldInclude = false;\n                    break;\n                }\n\n                // Passed everything add to passed gameobjects\n                if (shouldInclude && !pass.Contains(currentGameObject))\n                {\n                    pass.Enqueue(currentGameObject);\n                }\n            }\n\n            // Update the selection with the filtered GameObjects\n            Selection.objects = pass.ToArray();\n\n            // Notify after filter, for that off chance someone wants to subscribe for logging OR be able to reintroduce\n            // into the selection an object at their control.\n            if (rejectedGameObjects != null && fail.Count > 0)\n            {\n                rejectedGameObjects.Invoke(fail.ToArray());\n            }\n        }\n\n        internal static void CutGO()\n        {\n            FilterSelection(canCutGameObject);\n            cuttingGameObjects?.Invoke(Selection.gameObjects);\n            CutBoard.CutGO();\n            RepaintHierarchyWindowsAfterPaste();\n        }\n\n        internal static void CopyGO()\n        {\n            CutBoard.Reset();\n            FilterSelection(canCopyGameObject);\n            copyingGameObjects?.Invoke(Selection.gameObjects);\n            Unsupported.CopyGameObjectsToPasteboard();\n        }\n\n        internal static void PasteGO(Transform fallbackParent)\n        {\n            if (CutBoard.hasCutboardData)\n            {\n                CutBoard.PasteGameObjects(fallbackParent, false);\n                RepaintHierarchyWindowsAfterPaste();\n            }\n            // If it is not a Cut operation, execute regular paste\n            else\n            {\n                bool customParentIsSelected = GetIsCustomParentSelected(fallbackParent);\n                Unsupported.PasteGameObjectsFromPasteboard();\n                if (customParentIsSelected)\n                    Selection.activeTransform.SetParent(fallbackParent, true);\n            }\n            pastedGameObjects?.Invoke(Selection.gameObjects);\n        }\n\n        internal static void PasteGOAsChild(bool worldPositionStays = false)\n        {\n            Transform[] selected = Selection.transforms;\n\n            // paste as a child if a gameObject is selected\n            if (selected.Length == 1)\n            {\n                Scene subScene = new Scene();\n                bool pasteToSubScene = false;\n                bool isSubScene = false;\n\n                // If target is subScene make sure we just move objects under subScene\n                if (SubSceneGUI.IsSubSceneHeader(selected[0].gameObject))\n                {\n                    subScene = SubSceneGUI.GetSubScene(selected[0].gameObject);\n                    isSubScene = subScene.isSubScene;\n                    pasteToSubScene = subScene.IsValid();\n                }\n\n                // handle paste after cut\n                if (CutBoard.hasCutboardData)\n                {\n                    if (pasteToSubScene)\n                    {\n                        if (subScene.handle != 0)\n                        {\n                            CutBoard.PasteToScene(subScene, selected[0]);\n                            pastedGameObjects?.Invoke(Selection.gameObjects);\n                        }\n                    }\n                    else if (!isSubScene)\n                    {\n                        CutBoard.PasteAsChildren(selected[0], worldPositionStays);\n                        pastedGameObjects?.Invoke(Selection.gameObjects);\n                    }\n                }\n                // paste after copy\n                else if (pasteToSubScene || !isSubScene)\n                {\n                    Unsupported.PasteGameObjectsFromPasteboard(selected[0],\n                        pasteToSubScene ? subScene.handle : 0,\n                        worldPositionStays);\n                    pastedGameObjects?.Invoke(Selection.gameObjects);\n                }\n            }\n            RepaintHierarchyWindowsAfterPaste();\n        }\n\n        internal static void DuplicateGO(Transform fallbackParent)\n        {\n            CutBoard.Reset();\n            FilterSelection(canDuplicateGameObject);\n            bool customParentIsSelected = GetIsCustomParentSelected(fallbackParent);\n            duplicatingGameObjects?.Invoke(Selection.gameObjects);\n            Unsupported.DuplicateGameObjectsUsingPasteboard();\n            if (customParentIsSelected)\n                Selection.activeTransform.SetParent(fallbackParent, true);\n            duplicatedGameObjects?.Invoke(Selection.gameObjects);\n        }\n\n        internal static bool CanPasteAsChild()\n        {\n            bool canPaste = (Unsupported.CanPasteGameObjectsFromPasteboard() || CutBoard.hasCutboardData)\n                && ((SceneHierarchyWindow.lastInteractedHierarchyWindow != null && SceneHierarchyWindow.lastInteractedHierarchyWindow.sceneHierarchy != null)\n                    || SceneView.lastActiveSceneView != null)\n                && Selection.transforms.Length == 1;\n\n            var activeGO = Selection.activeGameObject;\n            if (activeGO != null && SubSceneGUI.IsSubSceneHeader(activeGO))\n                return canPaste && SubSceneGUI.GetSubScene(activeGO).IsValid();\n\n            return canPaste;\n        }\n\n        internal static bool GetIsCustomParentSelected(Transform fallbackParent)\n        {\n            if (fallbackParent == null)\n                return false;\n\n            GameObject[] selected = Selection.gameObjects;\n            for (int i = 0; i < selected.Length; i++)\n            {\n                if (selected[i] == fallbackParent.gameObject)\n                    return true;\n            }\n\n            return false;\n        }\n\n        static void RepaintHierarchyWindowsAfterPaste()\n        {\n            if (SceneHierarchyWindow.lastInteractedHierarchyWindow == null)\n                return;\n\n\n            foreach (var win in SceneHierarchyWindow.GetAllSceneHierarchyWindows())\n            {\n                win.Repaint();\n            }\n        }\n\n        internal static void ResetCutboardAndRepaintHierarchyWindows()\n        {\n            if (CutBoard.hasCutboardData)\n            {\n                CutBoard.Reset();\n                RepaintHierarchyWindowsAfterPaste();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CloudBuild/CloudBuild.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditor.Utils;\nusing UnityEditor.Web;\nusing UnityEditorInternal;\nusing UnityEditor.Connect;\n\nnamespace UnityEditor.CloudBuild\n{\n    [InitializeOnLoad]\n    internal class CloudBuild\n    {\n        public Dictionary<string, Dictionary<string, string>> GetScmCandidates()\n        {\n            Dictionary<string, Dictionary<string, string>> candidates = new Dictionary<string, Dictionary<string, string>>();\n\n            Dictionary<string, string> git = DetectGit();\n            if (git != null)\n            {\n                candidates.Add(\"git\", git);\n            }\n            Dictionary<string, string> mercurial = DetectMercurial();\n            if (mercurial != null)\n            {\n                candidates.Add(\"mercurial\", mercurial);\n            }\n\n            Dictionary<string, string> subversion = DetectSubversion();\n            if (subversion != null)\n            {\n                candidates.Add(\"subversion\", subversion);\n            }\n\n            Dictionary<string, string> perforce = DetectPerforce();\n            if (perforce != null)\n            {\n                candidates.Add(\"perforce\", perforce);\n            }\n            return candidates;\n        }\n\n        private Dictionary<string, string> DetectGit()\n        {\n            Dictionary<string, string> gitSettings = new Dictionary<string, string>();\n\n            string url = RunCommand(\"git\", \"config --get remote.origin.url\");\n            if (String.IsNullOrEmpty(url))\n            {\n                return null;\n            }\n            gitSettings.Add(\"url\", url);\n            gitSettings.Add(\"branch\", RunCommand(\"git\", \"rev-parse --abbrev-ref HEAD\"));\n            gitSettings.Add(\"root\", RemoveProjectDirectory(RunCommand(\"git\", \"rev-parse --show-toplevel\")));\n            return gitSettings;\n        }\n\n        private Dictionary<string, string> DetectMercurial()\n        {\n            Dictionary<string, string> mercurialSettings = new Dictionary<string, string>();\n\n            string url = RunCommand(\"hg\", \"paths default\");\n            if (String.IsNullOrEmpty(url))\n            {\n                return null;\n            }\n            mercurialSettings.Add(\"url\", url);\n            mercurialSettings.Add(\"branch\", RunCommand(\"hg\", \"branch\"));\n            mercurialSettings.Add(\"root\", RemoveProjectDirectory(RunCommand(\"hg\", \"root\")));\n            return mercurialSettings;\n        }\n\n        private Dictionary<string, string> DetectSubversion()\n        {\n            Dictionary<string, string> subversionSettings = new Dictionary<string, string>();\n\n            string info = RunCommand(\"svn\", \"info\");\n            if (info == null)\n            {\n                return null;\n            }\n            string[] lines = info.Split(Environment.NewLine.ToCharArray());\n            foreach (var s in lines)\n            {\n                string[] parts = s.Split(new char[] {':'}, 2);\n                if (parts.Length == 2)\n                {\n                    if (parts[0].Equals(\"Repository Root\"))\n                    {\n                        subversionSettings.Add(\"url\", parts[1].Trim());\n                    }\n\n                    if (parts[0].Equals(\"URL\"))\n                    {\n                        subversionSettings.Add(\"branch\", parts[1].Trim());\n                    }\n\n                    if (parts[0].Equals(\"Working Copy Root Path\"))\n                    {\n                        subversionSettings.Add(\"root\", RemoveProjectDirectory(parts[1].Trim()));\n                    }\n                }\n            }\n            if (!subversionSettings.ContainsKey(\"url\"))\n            {\n                return null;\n            }\n            return subversionSettings;\n        }\n\n        private Dictionary<string, string> DetectPerforce()\n        {\n            Dictionary<string, string> perforceSettings = new Dictionary<string, string>();\n\n            string url = Environment.GetEnvironmentVariable(\"P4PORT\");\n            if (String.IsNullOrEmpty(url))\n            {\n                return null;\n            }\n            perforceSettings.Add(\"url\", url);\n\n            string client = Environment.GetEnvironmentVariable(\"P4CLIENT\");\n            if (!String.IsNullOrEmpty(client))\n            {\n                perforceSettings.Add(\"workspace\", client);\n            }\n            return perforceSettings;\n        }\n\n        private String RunCommand(string command, string arguments)\n        {\n            try\n            {\n                ProcessStartInfo startInfo = new ProcessStartInfo(command);\n                startInfo.Arguments = arguments;\n                Program program = new Program(startInfo);\n                program.Start();\n                program.WaitForExit();\n                if (program.ExitCode < 0)\n                {\n                    return null;\n                }\n                var sb = new System.Text.StringBuilder();\n                foreach (var s in program.GetStandardOutput())\n                {\n                    sb.AppendLine(s);\n                }\n                return sb.ToString().TrimEnd(Environment.NewLine.ToCharArray());\n            }\n            catch (System.ComponentModel.Win32Exception)\n            {\n                // Problem executing, most likely Executable not found in path on Windows systems\n                return null;\n            }\n        }\n\n        private String RemoveProjectDirectory(string workingDirectory)\n        {\n            string currentDirectory = Directory.GetCurrentDirectory();\n\n            // handle windows command line clients returning *nix like paths\n            if (currentDirectory.StartsWith(workingDirectory.Replace('/', '\\\\')))\n            {\n                workingDirectory = workingDirectory.Replace('/', '\\\\');\n            }\n            currentDirectory = currentDirectory.Replace(workingDirectory, \"\");\n            return currentDirectory.Trim(Path.DirectorySeparatorChar);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CodeEditor/CodeEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Text;\nusing UnityEditor;\nusing UnityEditor.Callbacks;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing static UnityEditor.TypeCache;\n\nnamespace Unity.CodeEditor\n{\n    public class CodeEditor\n    {\n        public struct Installation\n        {\n            public string Name;\n            public string Path;\n        }\n\n        private readonly List<IExternalCodeEditor> m_ExternalCodeEditors = new List<IExternalCodeEditor>();\n        private readonly IExternalCodeEditor m_DefaultEditor = new DefaultExternalCodeEditor();\n        private IExternalCodeEditor m_CurrentEditor;\n        private Installation m_CurrentInstallation;\n        internal const string SystemDefaultPath = \"\";\n\n        public IExternalCodeEditor CurrentCodeEditor\n        {\n            get\n            {\n                if (m_CurrentEditor == m_DefaultEditor && !IsCurrentEditorPathExplicitlySet)\n                {\n                    // try to resolve first found visual studio installation and enable it\n                    try\n                    {\n                        var vs = m_ExternalCodeEditors.FirstOrDefault(e => e.GetType().Name == \"VisualStudioEditor\");\n                        var installs = vs?.Installations;\n                        if (installs != null && installs.Length > 0)\n                        {\n                            SetCodeEditor(installs[0].Path);\n                        }\n                    }\n                    catch (Exception ex)\n                    {\n                        Debug.LogWarning($\"Can't locate Visual Studio installation: {ex.Message}\");\n                    }\n                }\n                return m_CurrentEditor;\n            }\n        }\n        public Installation CurrentInstallation => m_CurrentInstallation;\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public static IExternalCodeEditor CurrentEditor => Editor.CurrentCodeEditor;\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public static string CurrentEditorInstallation => CurrentEditorPath;\n        public static string CurrentEditorPath => EditorPrefs.GetString(\"kScriptsDefaultApp\", \"\");\n        private static bool IsCurrentEditorPathExplicitlySet => EditorPrefs.HasKey(\"kScriptsDefaultApp\");\n\n        public static CodeEditor Editor { get; } = new CodeEditor();\n\n        public CodeEditor()\n        {\n            m_CurrentEditor = m_DefaultEditor;\n            m_CurrentInstallation = GetInstallationForPath(CurrentEditorPath);\n        }\n\n        [RequiredByNativeCode]\n        private static bool OpenProject(string path, int line, int column)\n        {\n            var didOpenProject = Editor.CurrentCodeEditor.OpenProject(path, line, column);\n            if (didOpenProject)\n            {\n                CodeEditorAnalytics.SendCodeEditorUsage(CodeEditor.Editor.CurrentCodeEditor);\n            }\n            return didOpenProject;\n        }\n\n        [OnOpenAsset]\n        private static bool OnOpenAsset(int instanceID, int line, int column)\n        {\n            var selected = EditorUtility.InstanceIDToObject(instanceID);\n            var assetPath = AssetDatabase.GetAssetPath(selected);\n\n            if (string.IsNullOrEmpty(assetPath))\n            {\n                return false;\n            }\n\n            var assetFilePath = Path.GetFullPath(assetPath);\n            var didOpenProject = Editor.CurrentCodeEditor.OpenProject(assetFilePath, line, column);\n            if (didOpenProject)\n            {\n                CodeEditorAnalytics.SendCodeEditorUsage(CodeEditor.Editor.CurrentCodeEditor);\n            }\n            return didOpenProject;\n        }\n\n        public Installation GetInstallationForPath(string editorPath)\n        {\n            if (editorPath == null)\n            {\n                throw new ArgumentException(\"GetInstallationForPath: Does not allow null editorPath\");\n            }\n\n            Installation installation;\n            if (editorPath == CodeEditor.SystemDefaultPath)\n            {\n                m_DefaultEditor.TryGetInstallationForPath(editorPath, out installation);\n                return installation;\n            }\n\n            foreach (var codeEditor in m_ExternalCodeEditors)\n            {\n                if (codeEditor.TryGetInstallationForPath(editorPath, out installation))\n                {\n                    return installation;\n                }\n            }\n            m_DefaultEditor.TryGetInstallationForPath(editorPath, out installation);\n            return installation;\n        }\n\n        public IExternalCodeEditor GetCodeEditorForPath(string editorPath)\n        {\n            if (editorPath == null)\n            {\n                throw new ArgumentException(\"GetCodeEditorForPath: Does not allow null editorPath\");\n            }\n\n            if (editorPath == CodeEditor.SystemDefaultPath)\n            {\n                return m_DefaultEditor;\n            }\n\n            foreach (var codeEditor in m_ExternalCodeEditors)\n            {\n                if (codeEditor.TryGetInstallationForPath(editorPath, out _))\n                {\n                    return codeEditor;\n                }\n            }\n            return m_DefaultEditor;\n        }\n\n        public Dictionary<string, string> GetFoundScriptEditorPaths()\n        {\n            var result = new Dictionary<string, string>();\n\n            foreach (var installation in m_ExternalCodeEditors.SelectMany(codeEditor => codeEditor.Installations))\n            {\n                AddIfPathExists(installation.Name, installation.Path, result);\n            }\n\n            return result;\n        }\n\n        private static void AddIfPathExists(string name, string path, Dictionary<string, string> list)\n        {\n            if (list.ContainsKey(path)) return;\n            if (Directory.Exists(path)) list.Add(path, name);\n            else if (File.Exists(path)) list.Add(path, name);\n        }\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public static void SetExternalScriptEditor(string path)\n        {\n            Editor.SetCodeEditor(path);\n        }\n\n        public void SetCodeEditor(string editorPath)\n        {\n            if (editorPath == null)\n            {\n                throw new ArgumentException(\"SetCodeEditor: Does not allow null editorPath\");\n            }\n\n            EditorPrefs.SetString(\"kScriptsDefaultApp\", editorPath);\n            m_CurrentEditor = ComputeCurrentEditor(editorPath);\n            m_CurrentInstallation = GetInstallationForPath(editorPath);\n            m_CurrentEditor.Initialize(editorPath);\n        }\n\n        private IExternalCodeEditor ComputeCurrentEditor(string editorPath)\n        {\n            if (m_ExternalCodeEditors.Count() == 0)\n            {\n                TypeCollection collection = TypeCache.GetTypesDerivedFrom<IExternalCodeEditor>();\n                for (int i = 0; i < collection.Count(); i++)\n                {\n                    var codeEditorType = collection[i];\n                    if (codeEditorType == typeof(DefaultExternalCodeEditor))\n                        continue;\n\n                    if (codeEditorType.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null) != null)\n                    {\n                        IExternalCodeEditor codeEditor = (IExternalCodeEditor)Activator.CreateInstance(codeEditorType);\n                        m_ExternalCodeEditors.Add(codeEditor);\n                    }\n                }\n            }\n\n            return GetCodeEditorForPath(editorPath);\n        }\n\n        public static void Register(IExternalCodeEditor externalCodeEditor)\n        {\n            if (Editor.m_ExternalCodeEditors.Select(editor => editor.GetType()).Any(editorType => editorType == externalCodeEditor.GetType()))\n                return;\n            Editor.m_ExternalCodeEditors.Add(externalCodeEditor);\n            if (IsCurrentEditorPathExplicitlySet)\n            {\n                CodeEditor.Editor.SetCodeEditor(Editor.m_CurrentInstallation.Path);\n            }\n        }\n\n        public static void Unregister(IExternalCodeEditor externalCodeEditor)\n        {\n            Editor.m_ExternalCodeEditors.Remove(externalCodeEditor);\n            CodeEditor.Editor.SetCodeEditor(Editor.m_CurrentInstallation.Path);\n        }\n\n        public static bool OSOpenFile(string appPath, string arguments)\n        {\n            return ExternalEditor.OSOpenFileWithArgument(appPath, arguments);\n        }\n\n        public static string ParseArgument(string arguments, string path, int line, int column)\n        {\n            var newArgument = arguments.Replace(\"$(ProjectPath)\", QuoteForProcessStart(Directory.GetParent(Application.dataPath).FullName));\n            newArgument = newArgument.Replace(\"$(File)\", string.IsNullOrEmpty(path) ? \"\" : QuoteForProcessStart(path));\n            newArgument = newArgument.Replace(\"$(Line)\", line >= 0 ? line.ToString() : \"0\");\n            newArgument = newArgument.Replace(\"$(Column)\", column >= 0 ? column.ToString() : \"0\");\n            return newArgument;\n        }\n\n        /// <summary>\n        /// Quote a string for passing as a single argument to Process.Start\n        /// and append it to this string builder.\n        /// </summary>\n        /// <remarks>\n        /// On Windows, quote according to the Win32 CommandLineToArgvW API scheme,\n        /// used by most Windows applications (with some notable exceptions, like\n        /// cmd.exe and cscript.exe). On Unix, Mono uses the entirely incompatible\n        /// GLib g_shell_parse_argv function for converting the argument string to\n        /// a native Unix argument list, so quote for that instead.\n        ///\n        /// Do not use this to quote arguments for command line shells (cmd.exe\n        /// or POSIX shell), as these may use distinct quotation mechanisms.\n        ///\n        /// Do not append two quoted arguments without an (unquoted) separator\n        /// between them: Two consecutive quotation marks triggers undocumented\n        /// behavior in CommandLineToArgvW and possibly other argument processors.\n        /// </remarks>\n        // https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/\n        public static string QuoteForProcessStart(string argument)\n        {\n            var sb = new StringBuilder();\n            // Quote for g_shell_parse_argv when running on Unix (under Mono).\n            if (Application.platform != RuntimePlatform.WindowsEditor)\n            {\n                sb.Append('\\'');\n                sb.Append(argument.Replace(\"\\\\\", \"\\\\\\\\\").Replace(\"'\", \"\\\\'\"));\n                sb.Append('\\'');\n                return sb.ToString();\n            }\n\n            sb.Append('\"');\n            for (int i = 0; i < argument.Length; ++i)\n            {\n                char c = argument[i];\n                if (c == '\"')\n                {\n                    for (int j = i - 1; j >= 0 && argument[j] == '\\\\'; --j)\n                        sb.Append('\\\\');\n                    sb.Append('\\\\');\n                }\n                sb.Append(c);\n            }\n            for (int j = argument.Length - 1; j >= 0 && argument[j] == '\\\\'; --j)\n                sb.Append('\\\\');\n            sb.Append('\"');\n            return sb.ToString();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CodeEditor/CodeEditorAnalytics.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEngine;\nusing UnityEngine.Analytics;\n\nnamespace Unity.CodeEditor\n{\n    class CodeEditorAnalytics\n    {\n        [AnalyticInfo(eventName: \"CodeEditorUsage\", vendorKey: \"unity.codeeditor\")]\n        public class CodeEditorAnalytic : IAnalytic\n        {\n            private IExternalCodeEditor codeEditor = null;\n\n            public CodeEditorAnalytic(IExternalCodeEditor codeEditor)\n            {\n                this.codeEditor = codeEditor;\n            }\n\n            struct AnalyticsData : IAnalytic.IData\n            {\n                [SerializeField] public string code_editor;\n            }\n            public bool TryGatherData(out IAnalytic.IData data, out Exception error)\n            {\n                data = new AnalyticsData()\n                {\n                    code_editor = codeEditor.GetType().FullName\n                };\n\n                error = null;\n                return true;\n            }\n        }\n\n        public static void SendCodeEditorUsage(IExternalCodeEditor codeEditor)\n        {\n            EditorAnalytics.SendAnalytic(new CodeEditorAnalytic(codeEditor));\n        }    \n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CodeEditor/CodeEditorProjectSync.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing Unity.CodeEditor;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    internal class CodeEditorProjectSync : AssetPostprocessor\n    {\n        class BuildTargetChangedHandler : Build.IActiveBuildTargetChanged\n        {\n            public int callbackOrder => 0;\n\n            public void OnActiveBuildTargetChanged(BuildTarget oldTarget, BuildTarget newTarget)\n            {\n                CodeEditor.Editor.CurrentCodeEditor.SyncAll();\n            }\n        }\n\n        [RequiredByNativeCode]\n        public static void SyncEditorProject()\n        {\n            CodeEditor.Editor.CurrentCodeEditor.SyncAll();\n        }\n\n        // For the time being this doesn't use the callback\n        public static void PostprocessSyncProject(\n            string[] importedAssets,\n            string[] addedAssets,\n            string[] deletedAssets,\n            string[] movedAssets,\n            string[] movedFromAssetPaths)\n        {\n            CodeEditor.Editor.CurrentCodeEditor.SyncIfNeeded(addedAssets, deletedAssets, movedAssets, movedFromAssetPaths, importedAssets);\n        }\n\n        [MenuItem(\"Assets/Open C# Project\", secondaryPriority = 1)]\n        static void SyncAndOpenSolution()\n        {\n            // Ensure that the mono islands are up-to-date\n            AssetDatabase.Refresh();\n            CodeEditor.Editor.CurrentCodeEditor.SyncAll();\n\n            CodeEditor.Editor.CurrentCodeEditor.OpenProject();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CodeEditor/DefaultExternalCodeEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing Unity.CodeEditor;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Assertions;\nusing NiceIO;\n\nnamespace UnityEditor\n{\n    internal class DefaultExternalCodeEditor : IExternalCodeEditor\n    {\n        static readonly GUIContent k_ResetArguments = EditorGUIUtility.TrTextContent(\"Reset argument\");\n        static readonly string[] supportedExtensions = { \"json\", \"asmdef\", \"log\", \"cs\", \"uxml\", \"uss\", \"shader\", \"compute\", \"cginc\", \"hlsl\", \"glslinc\", \"template\", \"raytrace\" };\n        static bool IsOSX => Application.platform == RuntimePlatform.OSXEditor;\n        static bool IsWindows => Application.platform == RuntimePlatform.WindowsEditor;\n        static bool IsLinux => Application.platform == RuntimePlatform.LinuxEditor;\n\n        string m_ChosenInstallation;\n\n        const string k_ArgumentKey = \"kScriptEditorArgs\";\n        const string k_DefaultArgument = \"$(File)\";\n\n        string Arguments\n        {\n            get\n            {\n                // Starting in Unity 5.5, we support setting script editor arguments on OSX and\n                // use then when opening the script editor.\n                // Before Unity 5.5, we would still save the default script editor args in EditorPrefs,\n                // even though we never used them. This means that the user potentially has some\n                // script editor args saved and once he upgrades to 5.5, they will be used when\n                // open the script editor. Which unintended and causes a regression in behaviour.\n                // So on OSX we change the key for per application for script editor args,\n                // to avoid reading the one from previous versions.\n                // The year 2021: Delete mac hack.\n                if (IsOSX)\n                {\n                    var oldMac = EditorPrefs.GetString(\"kScriptEditorArgs_\" + Installation);\n                    if (!string.IsNullOrEmpty(oldMac))\n                    {\n                        EditorPrefs.SetString(k_ArgumentKey, oldMac);\n                    }\n                }\n\n                return EditorPrefs.GetString(k_ArgumentKey + Installation, k_DefaultArgument);\n            }\n            set\n            {\n                if (IsOSX)\n                {\n                    EditorPrefs.SetString(\"kScriptEditorArgs_\" + Installation, value);\n                }\n\n                EditorPrefs.SetString(k_ArgumentKey + Installation, value);\n            }\n        }\n\n        string Installation\n        {\n            get\n            {\n                if (m_ChosenInstallation == null)\n                    m_ChosenInstallation = CodeEditor.CurrentEditorPath;\n                return m_ChosenInstallation;\n            }\n            set\n            {\n                m_ChosenInstallation = value;\n            }\n        }\n\n        public CodeEditor.Installation[] Installations { get; }\n        public bool TryGetInstallationForPath(string editorPath, out CodeEditor.Installation installation)\n        {\n            if (string.IsNullOrEmpty(editorPath))\n            {\n                installation = new CodeEditor.Installation\n                {\n                    Name = \"\",\n                    Path = \"\"\n                };\n                return false;\n            }\n            installation = new CodeEditor.Installation\n            {\n                Name = OSUtil.GetAppFriendlyName(editorPath) + \" (internal)\",\n                Path = editorPath\n            };\n            return true;\n        }\n\n        public void OnGUI()\n        {\n            Arguments = EditorGUILayout.TextField(\"External Script Editor Args\", Arguments);\n            if (GUILayout.Button(k_ResetArguments, GUILayout.Width(120)))\n            {\n                Arguments = k_DefaultArgument;\n            }\n        }\n\n        public void SyncIfNeeded(string[] addedFiles, string[] deletedFiles, string[] movedFiles, string[] movedFromFiles, string[] importedFiles)\n        {\n        }\n\n        public void SyncAll()\n        {\n        }\n\n        public void Initialize(string editorInstallationPath)\n        {\n        }\n\n        static string[] DefaultExtensions =>\n            EditorSettings.projectGenerationUserExtensions\n                .Concat(supportedExtensions)\n                .Distinct().ToArray();\n\n        static bool SupportsExtension(string path)\n        {\n            var extension = Path.GetExtension(path);\n            if (string.IsNullOrEmpty(extension))\n                return false;\n            return DefaultExtensions.Contains(extension.TrimStart('.'));\n        }\n\n        public bool OpenProject(string path, int line, int column)\n        {\n            if (path != CodeEditor.SystemDefaultPath && !SupportsExtension(path)) // Assets - Open C# Project passes empty path here\n            {\n                return false;\n            }\n\n            var applicationPath = CodeEditor.CurrentEditorPath.Trim();\n            var doesNotExistWarning =\n                $\"External Code Editor application path does not exist ({applicationPath})! Please select a different application.\";\n\n            var npath = new NPath(applicationPath);\n            if (applicationPath == null || !npath.Exists())\n            {\n                UnityEngine.Debug.LogWarning(doesNotExistWarning);\n                return false;\n            }\n\n            if (applicationPath == CodeEditor.SystemDefaultPath)\n            {\n                return InternalEditorUtility.OpenFileAtLineExternal(path, -1, -1);\n            }\n\n            string fileName = \"\";\n            string arguments = \"\";\n            switch (Application.platform)\n            {\n                case RuntimePlatform.OSXEditor:\n                    return CodeEditor.OSOpenFile(applicationPath, CodeEditor.ParseArgument(Arguments, path, line, column));\n                case RuntimePlatform.LinuxEditor:\n                    fileName = applicationPath;\n                    arguments = CodeEditor.ParseArgument(Arguments, path, line, column);\n                    break;\n                case RuntimePlatform.WindowsEditor:\n                    fileName = \"cmd.exe\";\n                    arguments = \"/C \\\"\" + CodeEditor.QuoteForProcessStart(applicationPath) +\n                                \" \" + CodeEditor.ParseArgument(Arguments, path, line, column) + \"\\\"\";\n                    break;\n            }\n\n            var process = new Process\n            {\n                StartInfo = new ProcessStartInfo\n                {\n                    FileName = fileName,\n                    Arguments = arguments,\n                    WindowStyle = ProcessWindowStyle.Hidden,\n                    CreateNoWindow = true,\n                    UseShellExecute = true,\n                }\n            };\n            var result = process.Start();\n            return result;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CodeEditor/ExternalEditor.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace Unity.CodeEditor\n{\n    [NativeHeader(\"Editor/Platform/Interface/ExternalEditor.h\")]\n    internal class ExternalEditor\n    {\n        [FreeFunction(\"PlatformSpecificOpenFileAtLine\")]\n        internal static extern bool OSOpenFileWithArgument(string appPath, string arguments);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CodeEditor/IExternalCodeEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace Unity.CodeEditor\n{\n    public interface IExternalCodeEditor\n    {\n        CodeEditor.Installation[] Installations { get; }\n        bool TryGetInstallationForPath(string editorPath, out CodeEditor.Installation installation);\n        void OnGUI();\n        void SyncIfNeeded(string[] addedFiles, string[] deletedFiles, string[] movedFiles, string[] movedFromFiles, string[] importedFiles);\n        void SyncAll();\n        void Initialize(string editorInstallationPath);\n        bool OpenProject(string filePath = \"\", int line = -1, int column = -1);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CodeEditor/SyncVS.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Security.Cryptography;\nusing System.Text;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    internal class SyncVS\n    {\n        [RequiredByNativeCode]\n        public static void SyncSolution()\n        {\n            // Ensure that the mono islands are up-to-date\n            AssetDatabase.Refresh();\n\n            // TODO: Rider and possibly other code editors, use reflection to call this method.\n            // To avoid conflicts and null reference exception, this is left as a dummy method.\n            Unity.CodeEditor.CodeEditor.Editor.CurrentCodeEditor.SyncAll();\n        }\n    }\n\n    namespace VisualStudioIntegration\n    {\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public static class SolutionGuidGenerator\n        {\n            public static string GuidForProject(string projectName)\n            {\n                return ComputeGuidHashFor(projectName + \"salt\");\n            }\n\n            public static string GuidForSolution(string projectName, string sourceFileExtension)\n            {\n                if (sourceFileExtension.ToLower() == \"cs\")\n                    // GUID for a C# class library: http://www.codeproject.com/Reference/720512/List-of-Visual-Studio-Project-Type-GUIDs\n                    return \"FAE04EC0-301F-11D3-BF4B-00C04F79EFBC\";\n                return ComputeGuidHashFor(projectName);\n            }\n\n            private static string ComputeGuidHashFor(string input)\n            {\n                var hash = MD5.Create().ComputeHash(Encoding.Default.GetBytes(input));\n                return HashAsGuid(HashToString(hash));\n            }\n\n            private static string HashAsGuid(string hash)\n            {\n                var guid = hash.Substring(0, 8) + \"-\" + hash.Substring(8, 4) + \"-\" + hash.Substring(12, 4) + \"-\" + hash.Substring(16, 4) + \"-\" + hash.Substring(20, 12);\n                return guid.ToUpper();\n            }\n\n            private static string HashToString(byte[] bs)\n            {\n                var sb = new StringBuilder();\n                foreach (byte b in bs)\n                    sb.Append(b.ToString(\"x2\"));\n                return sb.ToString();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Collab/CollabToUVCSBridge.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n// This file was introduced as part of the collab removal, it supports any versions of com.unity.collab-proxy under 1.17.7\n// It allows for an error free upgrade by provinding mock classes for the removed ones.\n\nusing System;\nusing System.Diagnostics;\nusing System.Collections.Generic;\n\nusing UnityEditor.Connect;\nusing UnityEditor.PackageManager;\nusing UnityEngine;\n\n#pragma warning disable 0067\n#pragma warning disable 0618\nnamespace UnityEditor.Collaboration\n{\n    internal static class LogObsolete\n    {\n        static bool s_Initialized;\n        static bool s_NeedsLogging;\n        static Stopwatch s_Stopwatch = Stopwatch.StartNew();\n\n        internal static void Log()\n        {\n            if (!s_Initialized)\n                s_NeedsLogging = IsObsolete(\"com.unity.collab-proxy\", \"1.1\");\n\n            s_Initialized = true;\n\n            if (!s_NeedsLogging)\n                return;\n\n            if (s_Stopwatch.ElapsedMilliseconds < 1000)\n                return;\n\n            UnityEngine.Debug.unityLogger.LogWarning(\n                \"com.unity.collab-proxy\",\n                \"This version of the package is not supported, please upgrade to the latest version. https://unity.com/solutions/version-control\");\n\n            s_Stopwatch.Restart();\n        }\n\n        internal static bool IsObsolete(string packageName, string version)\n        {\n            UnityEditor.PackageManager.PackageInfo package = null;\n            try\n            {\n                package = UnityEditor.PackageManager.PackageInfo.FindForPackageName(packageName);\n            }\n            catch\n            {\n                return false;\n            }\n\n            if (package == null)\n                return false;\n\n            if (package.version == null)\n                return false;\n\n            return package.version.StartsWith(version);\n        }\n    }\n\n    internal class Collab\n    {\n        static Collab s_instance = null;\n        public static Collab instance {\n            get\n            {\n                if (s_instance == null)\n                    s_instance = new Collab();\n\n                LogObsolete.Log();\n                return s_instance;\n            }\n        }\n\n        Collab()\n        {\n        }\n\n        [Flags]\n        public enum Operation\n        {\n            Noop = 0,\n            Publish = 1 << 0,\n            Update = 1 << 1,\n            Revert = 1 << 2,\n            GoBack = 1 << 3,\n            Restore = 1 << 4,\n            Diff = 1 << 5,\n            ConflictDiff = 1 << 6,\n            Exclude = 1 << 7,\n            Include = 1 << 8,\n            ChooseMine = 1 << 9,\n            ChooseTheirs = 1 << 10,\n            ExternalMerge = 1 << 11,\n        }\n\n        [Flags]\n        public enum CollabStates : uint\n        {\n            kCollabNone = 0,\n            kCollabLocal = 1,\n            kCollabSynced = 1 << 1,\n            kCollabOutOfSync = 1 << 2,\n            kCollabIgnored = 1 << 3,\n            kCollabCheckedOutLocal = 1 << 4,\n            kCollabCheckedOutRemote = 1 << 5,\n            kCollabDeletedLocal = 1 << 6,\n            kCollabDeletedRemote = 1 << 7,\n            kCollabAddedLocal = 1 << 8,\n            kCollabAddedRemote = 1 << 9,\n            kCollabConflicted = 1 << 10,\n            kCollabMovedLocal = 1 << 11,\n            kCollabMovedRemote = 1 << 12,\n            kCollabUpdating = 1 << 13,\n            kCollabReadOnly = 1 << 14,\n            kCollabMetaFile = 1 << 15,\n            kCollabUseMine = 1 << 16,\n            kCollabUseTheir = 1 << 17,\n            kCollabMerged = 1 << 18,\n            kCollabPendingMerge = 1 << 19,\n            kCollabFolderMetaFile = 1 << 20,\n            KCollabContentChanged = 1 << 21,\n            KCollabContentConflicted = 1 << 22,\n            KCollabContentDeleted = 1 << 23,\n            kCollabInvalidState = 1 << 30,\n            kAnyLocalChanged = (kCollabAddedLocal | kCollabCheckedOutLocal | kCollabDeletedLocal | kCollabMovedLocal),\n            kAnyLocalEdited = (kCollabAddedLocal | kCollabCheckedOutLocal | kCollabMovedLocal),\n            kCollabAny = 0xFFFFFFFF\n        }\n\n        internal enum CollabStateID { None, Uninitialized, Initialized }\n\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(Collab collab){ return IntPtr.Zero; }\n        }\n\n        public event StateChangedDelegate StateChanged;\n        public event StateChangedDelegate RevisionUpdated;\n        public event RevisionChangedDelegate RevisionUpdated_V2;\n        public event StateChangedDelegate JobsCompleted;\n        public event ErrorDelegate ErrorOccurred;\n        public event SetErrorDelegate ErrorOccurred_V2;\n        public event ErrorDelegate ErrorCleared;\n        public event ChangeItemsChangedDelegate ChangeItemsChanged;\n        public event ChangeItemsChangedDelegate SelectedChangeItemsChanged;\n        public event StateChangedDelegate CollabInfoChanged;\n        public static int GetRevisionsData(bool withChanges, int startIndex, int numRevisions){ return 0; }\n        public static int GetSingleRevisionData(bool withChanges, string id){ return 0; }\n        public static RevisionsData PopulateRevisionsData(IntPtr nativeData){ return new RevisionsData(); }\n        public static Revision PopulateSingleRevisionData(IntPtr nativeData){ return new Revision(); }\n        public static ShowToolbarAtPositionDelegate ShowToolbarAtPosition = null;\n        public static IsToolbarVisibleDelegate IsToolbarVisible = null;\n        public static CloseToolbarDelegate CloseToolbar = null;\n        public static ShowHistoryWindowDelegate ShowHistoryWindow = null;\n        public static ShowChangesWindowDelegate ShowChangesWindow = null;\n        public static string[] clientType = Array.Empty<string>();\n        internal static string editorPrefCollabClientType = string.Empty;\n        public static string GetProjectClientType() { return string.Empty; }\n        public static void SetVersionControl(IVersionControl instance){}\n        internal static bool HasVersionControl(){ return false; }\n        internal static void ShowChangesWindowView(){}\n        internal static CollabStates GetAssetState(string assetGuid, string assetPath){ return (CollabStates)0; }\n        public static void OnSettingStatusChanged(CollabSettingType type, CollabSettingStatus status){}\n        public static bool InitializeSoftlocksViewController(){ return false; }\n        public static bool IsDiffToolsAvailable(){ return false; }\n        public static void SwitchToDefaultMode(){}\n        public static void OnProgressEnabledSettingStatusChanged(CollabSettingType type, CollabSettingStatus status){}\n\n        public CollabInfo collabInfo { get; }\n        public void SetSeat(bool value){}\n        public void RefreshSeatAvailabilityAsync(){}\n        public string GetProjectGUID(){ return string.Empty; }\n        public bool ShouldDoInitialCommit(){ return false; }\n        public void ShowDifferences(string path){}\n        public void SendNotification(){}\n        public void SetError(int errorCode){}\n        public void ClearError(int errorCode){}\n        public void ClearErrors(){}\n        public void ForceRefresh(bool refreshAssetDatabase){}\n        public void SetCollabEnabledForCurrentProject(bool enabled){}\n        public bool IsCollabEnabledForCurrentProject(){ return false; }\n        public bool IsAssetIgnored(string path){ return false; }\n        public bool ShouldTrackAsset(string path){ return false; }\n        public string GetProjectPath(){ return string.Empty; }\n        public bool IsConnected(){ return false; }\n        public bool AnyJobRunning(){ return false; }\n        public bool JobRunning(int a_jobID){ return false; }\n        public CollabStates GetAssetState(string guid){ return (CollabStates)0; }\n        public CollabStates GetSelectedAssetState(){ return (CollabStates)0; }\n        public CollabStateID GetCollabState(){ return (CollabStateID)0; }\n        public bool ValidateSelectiveCommit(){ return false; }\n        public void Disconnect(){}\n        public void CancelJobByType(int jobType, bool forceCancel){}\n        public void DoInitialCommit(){}\n        public void Update(string revisionID, bool updateToRevision){}\n        public void RevertFile(string path, bool forceOverwrite){}\n        public void RevertFiles(ChangeItem[] changeItems, bool forceOverwrite){}\n        public void LaunchConflictExternalMerge(string path){}\n        public void ShowConflictDifferences(string path){}\n        public void ResyncSnapshot(){}\n        public void GoBackToRevision(string revisionID, bool updateToRevision){}\n        public void ResyncToRevision(string revisionID){}\n        public Change[] GetCollabConflicts(){ return Array.Empty<Change>(); }\n        public void CheckConflictsResolvedExternal(){}\n        public bool AreTestsRunning(){ return false; }\n        public void SetTestsRunning(bool running){}\n        public void ClearAllFailures(){}\n        public void ClearNextOperationFailure(){}\n        public void ClearNextOperationFailureForFile(string path){}\n        public string GetGUIDForTests(){ return string.Empty; }\n        public void NewGUIDForTests(){}\n        public void FailNextOperation(Collab.Operation operation, int code){}\n        public void TimeOutNextOperation(Collab.Operation operation, int timeOutSec){}\n        public void FailNextOperationForFile(string path, Collab.Operation operation, int code){}\n        public void TimeOutNextOperationForFile(string path, Collab.Operation operation, int timeOutSec){}\n        public void TestPostSoftLockAsCollaborator(string projectGuid, string projectPath, string machineGuid, string assetGuid){}\n        public void TestClearSoftLockAsCollaborator(string projectGuid, string projectPath, string machineGuid, string softLockHash){}\n        internal bool GetErrorInternal(int errorFilter, out UnityErrorInfo info){ info = new UnityErrorInfo(); return false; }\n        public void Publish(string comment, bool useSelectedAssets, bool confirmMatchesPrevious){}\n        public void PublishAssetsAsync(string comment, ChangeItem[] changes){}\n        public void ClearSelectedChangesToPublish(){}\n        public void SendCollabInfoNotification(){}\n        public CollabFilters collabFilters = new CollabFilters();\n        public String projectBrowserSingleSelectionPath { get; set; }\n        public String projectBrowserSingleMetaSelectionPath { get; set; }\n        public string[] currentProjectBrowserSelection;\n        public void RefreshAvailableLocalChangesSynchronous(){}\n        public bool GetError(UnityConnect.UnityErrorFilter errorFilter, out UnityErrorInfo info){ info = new UnityErrorInfo(); return false; }\n        public void CancelJob(int jobType){}\n        public void UpdateEditorSelectionCache(){}\n        public CollabInfo GetCollabInfo(){ return new CollabInfo(); }\n        public void SaveAssets(){}\n        public void ShowInProjectBrowser(string filterString){}\n        public bool SetConflictsResolvedMine(string[] paths){ return false; }\n        public bool SetConflictsResolvedTheirs(string[] paths){ return false; }\n        public PublishInfo GetChangesToPublish() { return new PublishInfo(); }\n        public PublishInfo_V2 GetChangesToPublish_V2() { return new PublishInfo_V2(); }\n        public void SetChangesToPublish(ChangeItem[] changes){}\n        public ProgressInfo GetJobProgress(int jobId){ return new ProgressInfo(); }\n    }\n\n    internal enum CollabSettingType\n    {\n        InProgressEnabled = 0,\n        InProgressProjectEnabled = 1,\n        InProgressGlobalEnabled = 2\n    }\n\n    internal enum CollabSettingStatus\n    {\n        None = 0,\n        Available = 1\n    }\n\n    internal class CollabSettingsManager\n    {\n        public delegate void SettingStatusChanged(CollabSettingType type, CollabSettingStatus status);\n        public static Dictionary<CollabSettingType, SettingStatusChanged> statusNotifier = new Dictionary<CollabSettingType, SettingStatusChanged>();\n\n        static CollabSettingsManager(){}\n\n        public static bool IsAvailable(CollabSettingType type)\n        {\n            return false;\n        }\n\n        public static bool inProgressEnabled { get; }\n    }\n\n    internal class ProgressInfo\n    {\n        public enum ProgressType : uint\n        {\n            None = 0,\n            Count = 1,\n            Percent = 2,\n            Both = 3\n        }\n\n        public int jobId { get { return 0; } }\n        public string title { get { return string.Empty; } }\n        public string extraInfo { get { return string.Empty; } }\n        public int currentCount { get { return 0; } }\n        public int totalCount { get { return 0; } }\n        public bool completed { get { return true; } }\n        public bool cancelled { get { return false; } }\n        public bool canCancel { get { return false; } }\n        public string lastErrorString { get { return string.Empty; } }\n        public ulong lastError { get { return 0; } }\n        public int percentComplete { get{ return 0; } }\n        public bool isProgressTypeCount { get { return false; } }\n        public bool isProgressTypePercent { get { return false; } }\n        public bool errorOccured { get { return false; } }\n    }\n\n    internal class ChangeItem\n    {\n        public string Path { get; set; }\n        public Change.RevertableStates RevertableState { get; set; }\n        public string RelatedTo { get; set; }\n        public string RevisionId { get; set; }\n        public string Hash { get; set; }\n        public Collab.CollabStates State { get; set; }\n        public long Size { get; set; }\n        public string DownloadPath { get; set; }\n        public string FromPath { get; set; }\n    }\n\n    internal class PublishInfo\n    {\n        public Change[] changes;\n        public bool filter;\n    }\n\n    internal class PublishInfo_V2\n    {\n        public ChangeItem[] changes;\n        public bool filter;\n    }\n\n    internal class RevisionsResult\n    {\n        public List<Revision> Revisions = new List<Revision>();\n        public int RevisionsInRepo = -1;\n        public int Count { get { return 0; } }\n\n        public void Clear(){}\n    }\n\n    internal interface IRevisionsService\n    {\n        event RevisionsDelegate FetchRevisionsCallback;\n        void GetRevisions(int offset, int count);\n        string tipRevision { get; }\n        string currentUser { get; }\n    }\n\n    internal class RevisionsService : IRevisionsService\n    {\n        public event RevisionsDelegate FetchRevisionsCallback;\n        public event SingleRevisionDelegate FetchSingleRevisionCallback;\n\n        public string tipRevision { get { return string.Empty; } }\n        public string currentUser { get { return string.Empty; } }\n\n        public RevisionsService(Collab collabInstance, UnityConnect connectInstance)\n        {\n        }\n\n        public void GetRevisions(int offset, int count){}\n\n        public void GetRevision(string revId){}\n    }\n\n    internal class Change\n    {\n        public enum RevertableStates : uint\n        {\n            Revertable                         = 1 << 0,\n            NotRevertable                      = 1 << 1,\n            Revertable_File                    = 1 << 2,\n            Revertable_Folder                  = 1 << 3,\n            Revertable_EmptyFolder             = 1 << 4,\n            NotRevertable_File                 = 1 << 5,\n            NotRevertable_Folder               = 1 << 6,\n            NotRevertable_FileAdded            = 1 << 7,\n            NotRevertable_FolderAdded          = 1 << 8,\n            NotRevertable_FolderContainsAdd    = 1 << 9,\n            InvalidRevertableState             = (uint)1 << 31\n        }\n\n        public string path { get { return string.Empty; } }\n        public Collab.CollabStates state { get { return (Collab.CollabStates)0; } }\n        public bool isRevertable { get { return false; } }\n        public RevertableStates revertableState { get { return (RevertableStates)0; } }\n        public string relatedTo { get { return string.Empty; } }\n        public bool isMeta { get { return false; } }\n        public bool isConflict { get { return false; } }\n        public bool isFolderMeta { get { return false; } }\n        public bool isResolved { get { return false; } }\n        public string localStatus { get { return string.Empty; } }\n        public string remoteStatus { get { return string.Empty; } }\n        public string resolveStatus { get { return string.Empty; } }\n\n        internal bool HasState(Collab.CollabStates states)\n        {\n            return false;\n        }\n\n        internal bool HasRevertableState(RevertableStates revertableStates)\n        {\n            return false;\n        }\n    }\n\n    internal abstract class AbstractFilters\n    {\n        public List<string[]> filters { get; set;}\n        public abstract void InitializeFilters();\n        public bool ContainsSearchFilter(string name, string searchString){ return false; }\n        public void ShowInFavoriteSearchFilters(){}\n        public void HideFromFavoriteSearchFilters(){}\n    }\n\n    internal class CollabFilters : AbstractFilters\n    {\n        public override void InitializeFilters(){}\n        public void ShowInProjectBrowser(string filterString){}\n        public void OnCollabStateChanged(CollabInfo info){}\n    }\n\n\n    internal delegate void StateChangedDelegate(CollabInfo info);\n    internal delegate void RevisionChangedDelegate(CollabInfo info, string rev, string action);\n    internal delegate void SetErrorDelegate(UnityErrorInfo error);\n    internal delegate void ErrorDelegate();\n    internal delegate bool ShowToolbarAtPositionDelegate(Rect screenRect);\n    internal delegate bool IsToolbarVisibleDelegate();\n    internal delegate void ShowHistoryWindowDelegate();\n    internal delegate void ShowChangesWindowDelegate();\n    internal delegate void CloseToolbarDelegate();\n    internal delegate void ChangesChangedDelegate(Change[] changes, bool isFiltered);\n    internal delegate void ChangeItemsChangedDelegate(ChangeItem[] changes, bool isFiltered);\n    delegate void RevisionsDelegate(RevisionsResult revisionsResult);\n    delegate void SingleRevisionDelegate(Revision? revision);\n\n    internal struct CollabInfo\n    {\n        public bool ready { get { return true; } }\n        public bool update { get { return false; } }\n        public bool publish { get { return false; } }\n        public bool inProgress { get { return false; } }\n        public bool maintenance { get { return false; } }\n        public bool conflict { get { return false; } }\n        public bool refresh { get { return false; } }\n        public bool seat { get { return false; } }\n        public string tip { get { return string.Empty; } }\n        public bool Equals(CollabInfo other){ return false; }\n    }\n\n    internal struct ChangeAction\n    {\n        public ChangeAction(string path = \"\", string action = \"\"){}\n        public string path { get { return string.Empty; } }\n        public string action { get { return string.Empty; } }\n    }\n\n    internal struct Revision\n    {\n        internal Revision(string revisionID = \"\", string authorName = \"\", string author = \"\", string comment = \"\", string reference = \"\", ulong timeStamp = 0, bool isObtained = false, ChangeAction[] entries = null, CloudBuildStatus[] buildStatuses = null){}\n        public string authorName { get { return string.Empty;  } }\n        public string author { get { return string.Empty;  } }\n        public string comment { get { return string.Empty;  } }\n        public string revisionID { get { return string.Empty;  } }\n        public string reference { get { return string.Empty;  } }\n        public ulong timeStamp { get { return 0;  } }\n        public bool isObtained { get { return false;  } }\n        public ChangeAction[] entries { get { return Array.Empty<ChangeAction>();  } }\n        public CloudBuildStatus[] buildStatuses { get { return Array.Empty<CloudBuildStatus>();  } }\n    }\n\n    internal struct CloudBuildStatus\n    {\n        internal CloudBuildStatus(string platform = \"\", bool complete = false, bool success = false){}\n        public string platform { get { return string.Empty; } }\n        public bool complete { get { return false; } }\n        public bool success { get { return false; } }\n    }\n\n    internal struct RevisionData\n    {\n        public string id;\n        public int index;\n        public DateTime timeStamp;\n        public string authorName;\n        public string comment;\n        public bool obtained;\n        public bool current;\n        public bool inProgress;\n        public bool enabled;\n        public BuildState buildState;\n        public int buildFailures;\n        public ICollection<ChangeData> changes;\n        public int changesTotal;\n        public bool changesTruncated;\n    }\n\n    internal struct RevisionsData\n    {\n        public int RevisionsInRepo {get { return 0; }}\n        public int RevisionOffset {get { return 0; }}\n        public int ReturnedRevisions {get { return 0; }}\n        public Revision[] Revisions {get { return Array.Empty<Revision>(); }}\n    }\n\n    internal enum HistoryState\n    {\n        Error,\n        Offline,\n        Maintenance,\n        LoggedOut,\n        NoSeat,\n        Disabled,\n        Waiting,\n        Ready,\n    }\n\n    internal enum BuildState\n    {\n        None,\n        Configure,\n        Success,\n        Failed,\n        InProgress,\n    }\n\n    internal struct ChangeData\n    {\n        public string path;\n        public string action;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Collab/IVersionControl.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor.Collaboration\n{\n    internal interface IVersionControl\n    {\n        bool SupportsDownloads();\n        bool SupportsAsyncChanges();\n        bool OnEnableVersionControl();\n        void OnDisableVersionControl();\n        void MergeDownloadedFiles(bool isFullDownload);\n    }\n\n    internal interface IVersionControl_V2 : IVersionControl\n    {\n        void RefreshAvailableLocalChangesSynchronous();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CollectImportedDependenciesAttribute.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEngine.Scripting;\nusing static UnityEditor.AttributeHelper;\nusing UnityEngine.Scripting.APIUpdating;\n\nnamespace UnityEditor.AssetImporters\n{\n    [RequiredByNativeCode]\n    [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]\n    [MovedFrom(\"UnityEditor.Experimental.AssetImporters\")]\n    public class CollectImportedDependenciesAttribute : Attribute\n    {\n        private Type m_ImporterType;\n        private uint m_Version;\n\n        public CollectImportedDependenciesAttribute(Type importerType, uint version)\n        {\n            m_ImporterType = importerType;\n            m_Version = version;\n        }\n\n        public Type importerType { get { return m_ImporterType; } }\n        public uint version { get { return m_Version; } }\n\n        [RequiredSignature]\n        static string[] CollectImportedDependenciesSignature(string assetPath) { throw new InvalidOperationException(); }\n    }\n\n    static class ImportedDependenciesApi\n    {\n        static Dictionary<Type, string> s_ImportDependenciesHashStringMap = null;\n        static Dictionary<Type, MethodWithAttribute[]> s_ImportDependencyCallbackTypeMap = null;\n\n        private static IEnumerable<MethodWithAttribute> GetImportedDependenciesCallbacksAndAttributesForImporter(Type importerType)\n        {\n            if (s_ImportDependencyCallbackTypeMap != null && s_ImportDependencyCallbackTypeMap.ContainsKey(importerType))\n                return s_ImportDependencyCallbackTypeMap[importerType];\n\n            if (s_ImportDependencyCallbackTypeMap == null)\n                s_ImportDependencyCallbackTypeMap = new Dictionary<Type, MethodWithAttribute[]>();\n\n            Func<CollectImportedDependenciesAttribute, bool> filter = (a) => a.importerType.IsAssignableFrom(importerType);\n            s_ImportDependencyCallbackTypeMap[importerType] = AttributeHelper.GetMethodsWithAttribute<CollectImportedDependenciesAttribute>(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)\n                .methodsWithAttributes\n                .Where(x => filter((CollectImportedDependenciesAttribute)x.attribute))\n                .ToArray();\n\n            return s_ImportDependencyCallbackTypeMap[importerType];\n        }\n\n        [RequiredByNativeCode]\n        private static MethodInfo[] GetImportedDependenciesCallbacks(Type importerType)\n        {\n            return GetImportedDependenciesCallbacksAndAttributesForImporter(importerType).Select(x => x.info).ToArray();\n        }\n\n        private static string BuildHashString(SortedList<string, uint> list)\n        {\n            var hashStr = \"\";\n            foreach (var pair in list)\n            {\n                hashStr += pair.Key;\n                hashStr += '.';\n                hashStr += pair.Value;\n                hashStr += '|';\n            }\n\n            return hashStr;\n        }\n\n        [RequiredByNativeCode]\n        static string GetImportedDependenciesCallbacksHashString(Type importerType)\n        {\n            if (s_ImportDependenciesHashStringMap != null && s_ImportDependenciesHashStringMap.ContainsKey(importerType))\n                return s_ImportDependenciesHashStringMap[importerType];\n\n            if (s_ImportDependenciesHashStringMap == null)\n                s_ImportDependenciesHashStringMap = new Dictionary<Type, string>();\n\n            var versionsByType = new SortedList<string, uint>();\n\n            var methodsWithAttribute = GetImportedDependenciesCallbacksAndAttributesForImporter(importerType);\n\n            foreach (var method in methodsWithAttribute)\n            {\n                var attribute = (CollectImportedDependenciesAttribute)method.attribute;\n                var version = attribute.version;\n                string methodName = method.info.Name;\n                string className = method.info.ReflectedType.FullName;\n\n                string fullMethodName = className + \".\" + methodName;\n\n                if (version != 0)\n                {\n                    versionsByType.Add(fullMethodName, version);\n                }\n            }\n\n            s_ImportDependenciesHashStringMap[importerType] = BuildHashString(versionsByType);\n            return s_ImportDependenciesHashStringMap[importerType];\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Commands/CommandService.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing JetBrains.Annotations;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEngine;\nusing UnityEngine.Internal;\n\nnamespace UnityEditor\n{\n    [ExcludeFromDocs]\n    public delegate void CommandHandler(CommandExecuteContext context);\n\n    [ExcludeFromDocs, AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]\n    public class CommandHandlerAttribute : Attribute\n    {\n        public string id { get; }\n        public string label { get; }\n        public CommandHint hint { get; }\n\n        public CommandHandlerAttribute(string id, string label, CommandHint hint)\n        {\n            this.id = id;\n            this.label = label;\n            this.hint = hint;\n        }\n\n        public CommandHandlerAttribute(string id) : this(id, id, CommandHint.Any) {}\n        public CommandHandlerAttribute(string id, CommandHint hint) : this(id, id, hint) {}\n        public CommandHandlerAttribute(string id, string label) : this(id, label, CommandHint.Any) {}\n\n        [UsedImplicitly, RequiredSignature] static void RequiredSignature(CommandExecuteContext context) {}\n    }\n\n    [ExcludeFromDocs, Flags]\n    public enum CommandHint : long\n    {\n        Undefined   = -1,\n        None        = 0,\n        Event       = 1 << 0,\n        Menu        = 1 << 1,\n        Shortcut    = 1 << 2,\n        Shelf       = 1 << 3,\n\n        UI          = 1 << 20,\n        OnGUI       = UI | 1 << 21,\n        UIElements  = UI | 1 << 22,\n\n        Validate    = 1 << 30,\n        UserDefined = 1 << 31,\n\n        Any = ~0L\n    }\n\n    [ExcludeFromDocs]\n    public class CommandExecuteContext\n    {\n        public object[] args;\n        public object result;\n        public CommandHint hint;\n\n        // args[0] should at least be null and args be size of 1 or more.\n        public object data => args[0];\n\n        public T GetArgument<T>(int index, T defaultValue = default(T))\n        {\n            if (index < 0 || index >= args.Length)\n                throw new ArgumentOutOfRangeException(nameof(index));\n            return (T)args[index];\n        }\n    }\n\n    [ExcludeFromDocs]\n    public static class CommandService\n    {\n        private struct Command\n        {\n            public string id;\n            public string label;\n            public CommandHint hint;\n            public CommandHandler handler;\n            public bool managed;\n        }\n\n        private static Dictionary<string, Command> s_Commands;\n        private static readonly object[] k_DefaultArgs = { null };\n\n        static CommandService()\n        {\n            s_Commands = ScanAttributes().ToDictionary(c => c.id, c => c);\n        }\n\n        public static string GetCommandLabel(string commandId)\n        {\n            if (!Exists(commandId))\n                throw new ArgumentException($\"No command with id {commandId} exists\", nameof(commandId));\n\n            return s_Commands[commandId].label;\n        }\n\n        public static void RegisterCommand(string id, string label, CommandHandler handler, CommandHint hint = CommandHint.Any)\n        {\n            if (Exists(id))\n                throw new ArgumentException($\"A command with id {id} already exists\", nameof(id));\n\n            s_Commands[id] = new Command {id = id, label = label ?? id, hint = hint, handler = handler, managed = false};\n        }\n\n        public static void RegisterCommand(string id, CommandHandler handler, CommandHint hint = CommandHint.Any)\n        {\n            RegisterCommand(id, id, handler, hint);\n        }\n\n        public static bool UnregisterCommand(string id)\n        {\n            if (!Exists(id))\n                return false;\n\n            if (s_Commands[id].managed)\n                Debug.LogWarning($\"The command {id} was not explicitly registered by the user and should not be unregistered.\");\n\n            return s_Commands.Remove(id);\n        }\n\n        public static bool Exists(string id)\n        {\n            return s_Commands.ContainsKey(id);\n        }\n\n        public static object Execute(string id)\n        {\n            return ExecuteCommand(id, CommandHint.Any, k_DefaultArgs);\n        }\n\n        public static object Execute(string id, CommandHint hint)\n        {\n            return ExecuteCommand(id, hint, k_DefaultArgs);\n        }\n\n        public static object Execute(string id, CommandHint hint, params object[] args)\n        {\n            var contextArgs = args != null && args.Length > 0 ? args : k_DefaultArgs;\n            return ExecuteCommand(id, hint, contextArgs);\n        }\n\n        private static IEnumerable<Command> ScanAttributes()\n        {\n            var commands = new List<Command>();\n            foreach (var mi in TypeCache.GetMethodsWithAttribute<CommandHandlerAttribute>())\n            {\n                CommandHandler callback = null;\n                try\n                {\n                    callback = (CommandHandler)Delegate.CreateDelegate(typeof(CommandHandler), mi);\n                }\n                catch(Exception e)\n                {\n                    Debug.LogError($\"Cannot create CommandHandler from Attribute: {mi.Name} {e.Message}\");\n                    continue;\n                }\n\n                foreach (var attr in mi.GetCustomAttributes<CommandHandlerAttribute>())\n                {\n                    if (commands.Any(c => c.id == attr.id))\n                    {\n                        Debug.LogWarning($\"There is already a command with the ID {attr.id}. \" +\n                            \"Commands need to have a unique ID, i.e. \\\"Unity/Category/Command_42\\\".\");\n                        continue;\n                    }\n\n                    commands.Add(new Command { id = attr.id, label = attr.label ?? attr.id, hint = attr.hint, handler = callback, managed = true });\n                }\n            }\n\n            return commands;\n        }\n\n        private static object ExecuteCommand(string id, CommandHint hint, object[] args)\n        {\n            if (!Exists(id))\n                throw new ArgumentException($\"Command {id} does not exist\", nameof(id));\n\n            var command = s_Commands[id];\n\n            if ((command.hint & hint) == 0)\n                throw new ArgumentException($\"Command ({id}, {command.hint}) does not match the hinting {hint}\", nameof(id));\n\n            var context = new CommandExecuteContext { hint = hint, args = args, result = null };\n            command.handler(context);\n            return context.result;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Commands/GOCreationCommands.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEditor.SceneManagement;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing UnityEngine.Video;\n\nnamespace UnityEditor\n{\n    static class GOCreationCommands\n    {\n        internal enum PlacementMode\n        {\n            SceneIntersection,\n            WorldOrigin,\n            ScenePivot\n        }\n        static SavedInt s_PlacementModePref = new SavedInt(\"Create3DObject.PlacementMode\", 0);\n        internal static PlacementMode s_PlacementMode\n        {\n            get => (PlacementMode)s_PlacementModePref.value;\n            set => s_PlacementModePref.value = (int)value;\n        }\n\n        // This is here because we can't pass Scenes around with the MenuCommand context. SceneHierarchy toggles this\n        // flag when add object context menu items are invoked from a context click on Scene headers. If you make use of\n        // this, be sure to return it's value to 'false' as soon as your operation is out of scope.\n        internal static bool forcePlaceObjectsAtWorldOrigin;\n\n        static bool placeObjectsAtWorldOrigin\n        {\n            get { return s_PlacementMode == PlacementMode.WorldOrigin || forcePlaceObjectsAtWorldOrigin; }\n        }\n\n        private static void SetGameObjectParent(GameObject go, Transform parentTransform)\n        {\n            var transform = go.transform;\n            Undo.SetTransformParent(transform, parentTransform, \"Reparenting\");\n            transform.localPosition = Vector3.zero;\n            transform.localRotation = Quaternion.identity;\n            transform.localScale = Vector3.one;\n            go.layer = parentTransform.gameObject.layer;\n\n            if (parentTransform.GetComponent<RectTransform>())\n                ObjectFactory.AddComponent<RectTransform>(go);\n        }\n\n        internal static Vector3 GetNewObjectPosition()\n        {\n            var sceneView = SceneView.lastActiveSceneView;\n            if (placeObjectsAtWorldOrigin || sceneView == null) return Vector3.zero;\n\n            if (sceneView.in2DMode)\n                return new Vector3((float)Math.Round(sceneView.pivot.x, 5), (float)Math.Round(sceneView.pivot.y, 5), 0f);\n\n            if (s_PlacementMode == PlacementMode.SceneIntersection)\n            {\n                var prevCamera = Camera.current;\n\n                Handles.Internal_SetCurrentCamera(sceneView.camera);\n                var guiPoint = HandleUtility.WorldToGUIPoint(sceneView.pivot);\n                var didPlace = HandleUtility.PlaceObject(guiPoint, out var position, out _);\n                Handles.Internal_SetCurrentCamera(prevCamera);\n\n                if (didPlace)\n                    return new Vector3((float)Math.Round(position.x, 5), (float)Math.Round(position.y, 5), (float)Math.Round(position.z, 5));\n            }\n\n            // if s_PlacementMode == PlacementMode.ScenePivot\n            var pivot = sceneView.pivot;\n            return new Vector3((float)Math.Round(pivot.x, 5), (float)Math.Round(pivot.y, 5), (float)Math.Round(pivot.z, 5));\n        }\n\n        internal static void Place(GameObject go, GameObject parent, bool ignoreSceneViewPosition = true, bool alignWithSceneCamera = false)\n        {\n            Transform defaultObjectTransform = SceneView.GetDefaultParentObjectIfSet();\n\n            if (parent != null)\n            {\n                // At this point, RecordStructureChange is already ongoing (from the CreatePrimitive call through the CreateAndPlacePrimitive method). We need to flush the stack to finalise the RecordStructureChange before the\n                // following SetTransformParent call takes place.\n                Undo.FlushTrackedObjects();\n\n                SetGameObjectParent(go, parent.transform);\n            }\n            else if (defaultObjectTransform != null)\n            {\n                // At this point, RecordStructureChange is already ongoing (from the CreatePrimitive call through the CreateAndPlacePrimitive method). We need to flush the stack to finalise the RecordStructureChange before the\n                // following SetTransformParent call takes place.\n                Undo.FlushTrackedObjects();\n\n                SetGameObjectParent(go, defaultObjectTransform);\n            }\n            else\n            {\n                // When creating a 3D object without a parent, this option puts it at the world origin instead of scene pivot.\n                if (placeObjectsAtWorldOrigin)\n                    go.transform.position = Vector3.zero;\n                else if (ignoreSceneViewPosition)\n                {\n                    if(alignWithSceneCamera && go.TryGetComponent<Camera>(out var cam))\n                    {\n                        if (SceneView.lastActiveSceneView?.in2DMode == true)\n                        {\n                            // set 2D mode specific camera defaults\n                            cam.orthographic = true;\n                            cam.transform.position = new Vector3(0f, 0f, -10f);\n                        }\n\n                        SceneView.AlignCameraWithView(cam);\n                    }\n                    else\n                        go.transform.position = GetNewObjectPosition();\n                }\n\n                StageUtility.PlaceGameObjectInCurrentStage(go); // may change parent\n            }\n\n            // Only at this point do we know the actual parent of the object and can modify its name accordingly.\n            GameObjectUtility.EnsureUniqueNameForSibling(go);\n            Undo.SetCurrentGroupName(\"Create \" + go.name);\n\n            var sh = SceneHierarchyWindow.GetSceneHierarchyWindowToFocusForNewGameObjects();\n            if (sh != null)\n                sh.Focus();\n\n            Selection.activeGameObject = go;\n        }\n\n        [MenuItem(\"GameObject/Create Empty %#n\", priority = 0, secondaryPriority = 1)]\n        static void CreateEmpty(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            Place(ObjectFactory.CreateGameObject(\"GameObject\"), parent);\n        }\n\n        [MenuItem(\"GameObject/Create Empty Child &#n\", priority = 0, secondaryPriority = 2)]\n        static void CreateEmptyChild(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            if (parent == null)\n            {\n                var activeGO = Selection.activeGameObject;\n                if (activeGO != null && !EditorUtility.IsPersistent(activeGO))\n                    parent = activeGO;\n            }\n\n            // If selected GameObject is a Sub Scene header, place GameObject in active scene\n            // similar to what happens when other scene headers are selected.\n            SceneHierarchyHooks.SubSceneInfo info = SubSceneGUI.GetSubSceneInfo(parent);\n            if (info.isValid)\n                parent = null;\n\n            var go = ObjectFactory.CreateGameObject(\"GameObject\");\n            Place(go, parent);\n        }\n\n        // Avoiding executing this method per-object, by adding menu item manually in SceneHierarchy\n        [MenuItem(\"GameObject/Create Empty Parent %#g\", priority = 0, secondaryPriority = 3)]\n        internal static void CreateEmptyParent()\n        {\n            Transform[] selected = Selection.transforms;\n            GameObject defaultParentObject = SceneView.GetDefaultParentObjectIfSet()?.gameObject;\n            string defaultParentObjectSceneGUID = defaultParentObject?.scene.guid;\n\n            // Clear default parent object so we could always reparent and move the new parent to the scene we need\n            if (defaultParentObject != null)\n            {\n                SceneHierarchy.ClearDefaultParentObject(defaultParentObjectSceneGUID);\n            }\n\n            // If selected object is a prefab, get the its root object\n            if (selected.Length > 0)\n            {\n                for (int i = 0; i < selected.Length; i++)\n                {\n                    if (PrefabUtility.GetPrefabAssetType(selected[i].gameObject) != PrefabAssetType.NotAPrefab)\n                    {\n                        selected[i] = PrefabUtility.GetOutermostPrefabInstanceRoot(selected[i].gameObject).transform;\n                    }\n                }\n            }\n\n            // Selection.transform does not provide correct list order, so we have to do it manually\n            selected = selected.ToList().OrderBy(g => g.GetSiblingIndex()).ToArray();\n\n            GameObject go = ObjectFactory.CreateGameObject(\"GameObject\");\n\n            if (Selection.activeGameObject == null && Selection.gameObjects != null)\n            {\n                Selection.activeGameObject = Selection.gameObjects[0];\n            }\n\n            if (Selection.activeGameObject != null)\n                go.transform.position = Selection.activeGameObject.transform.position;\n\n            GameObject parent = Selection.activeTransform != null ? Selection.activeTransform.gameObject : null;\n            Transform sibling = null;\n\n            if (parent != null)\n            {\n                sibling = parent.transform;\n                parent = parent.transform.parent != null ? parent.transform.parent.gameObject : null;\n            }\n\n            Place(go, parent, false);\n            var rectTransform = go.GetComponent<RectTransform>();\n\n            // If new parent is RectTransform, make sure its position and size matches child rect transforms\n            if (rectTransform != null && selected != null && selected.Length > 0)\n            {\n                CenterRectTransform(selected, rectTransform);\n            }\n\n            if (parent == null && sibling != null)\n            {\n                Undo.MoveGameObjectToScene(go,  sibling.gameObject.scene, \"Move To Scene\");\n            }\n\n            if (parent == null && sibling == null)\n            {\n                go.transform.SetAsLastSibling();\n            }\n            else\n            {\n                go.transform.MoveAfterSibling(sibling, true);\n            }\n\n            // At this point, RecordStructureChange is already ongoing (from the CreateGameObject call).\n            // We need to flush the stack to finalise the RecordStructureChange before any of following SetTransformParent calls takes place.\n            Undo.FlushTrackedObjects();\n\n            // Put gameObjects under a created parent\n            if (selected.Length > 0)\n            {\n                foreach (var gameObject in selected)\n                {\n                    if (gameObject != null)\n                    {\n                        Undo.SetTransformParent(gameObject.transform, go.transform, \"Reparenting\");\n                        gameObject.transform.SetAsLastSibling();\n                    }\n                }\n\n                SceneHierarchyWindow.lastInteractedHierarchyWindow.SetExpanded(go.GetInstanceID(), true);\n\n                // Ensure empty parent after reparenting jumps into rename mode if needed UUM-15042\n                if (SceneHierarchyWindow.s_EnterRenameModeForNewGO)\n                {\n                    SceneHierarchyWindow.FrameAndRenameNewGameObject();\n                }\n            }\n\n            // Set back default parent object if we have one\n            if (defaultParentObject != null)\n            {\n                SceneHierarchy.UpdateSessionStateInfoAndActiveParentObjectValuesForScene(defaultParentObjectSceneGUID, defaultParentObject.GetInstanceID());\n            }\n        }\n\n        [MenuItem(\"GameObject/Create Empty Parent %#g\", true, priority = 0)]\n        internal static bool ValidateCreateEmptyParent()\n        {\n            GameObject[] selected = Selection.gameObjects;\n            if (selected.Length == 0)\n            {\n                return false;\n            }\n            else\n            {\n                // Check if selected objects are under the same parent and in the same scene\n                Scene targetScene = selected[0].scene;\n                Transform parent = selected[0].transform.parent;\n                foreach (var go in selected)\n                {\n                    if (go.transform.parent != parent || go.scene != targetScene)\n                        return false;\n                }\n\n                // Check if we are not trying to create parent object for root object if we are in prefab stage\n                if (StageNavigationManager.instance.currentStage is PrefabStage)\n                {\n                    GameObject rootGameObject = PrefabStageUtility.GetCurrentPrefabStage().prefabContentsRoot.gameObject;\n                    foreach (var go in selected)\n                    {\n                        if (go.gameObject == rootGameObject)\n                            return false;\n                    }\n                }\n\n                return true;\n            }\n        }\n\n        static void CenterRectTransform(Transform[] selected, RectTransform rectTransform)\n        {\n            Vector3 min = Vector3.zero;\n            Vector3 max = Vector3.zero;\n            bool hasRect = false;\n\n            foreach (var item in selected)\n            {\n                RectTransform rt = item.gameObject.GetComponent<RectTransform>();\n\n                if (rt)\n                {\n                    Vector3 pos = rt.localPosition;\n                    Vector3 scale = rt.localScale;\n                    Vector2 sizeDelta = rt.sizeDelta;\n\n                    if (!hasRect)\n                    {\n                        min = new Vector3(pos.x - sizeDelta.x * scale.x / 2, pos.y - sizeDelta.y * scale.y / 2, pos.z);\n                        max = new Vector3(pos.x + sizeDelta.x * scale.x / 2, pos.y + sizeDelta.y * scale.y / 2, pos.z);\n                        hasRect = true;\n                    }\n                    else\n                    {\n                        min = new Vector3(Math.Min(min.x, pos.x - sizeDelta.x * scale.x / 2), Math.Min(min.y, pos.y - sizeDelta.y * scale.y / 2), Math.Min(min.z, pos.z));\n                        max = new Vector3(Math.Max(max.x, pos.x + sizeDelta.x * scale.x / 2), Math.Max(max.y, pos.y + sizeDelta.y * scale.y / 2), Math.Max(max.z, pos.z));\n                    }\n                }\n            }\n\n            if (hasRect)\n            {\n                rectTransform.localPosition = new Vector3(min.x + (max.x - min.x) / 2, min.y + (max.y - min.y) / 2, min.z + (max.z - min.z) / 2);\n                rectTransform.sizeDelta = new Vector2(max.x - min.x, max.y - min.y);\n            }\n        }\n\n        static void CreateAndPlacePrimitive(PrimitiveType type, GameObject parent)\n        {\n            var primitive = ObjectFactory.CreatePrimitive(type);\n            primitive.name = type.ToString();\n            Place(primitive, parent);\n        }\n\n        [MenuItem(\"GameObject/3D Object/Cube\", priority = 1)]\n        static void CreateCube(MenuCommand menuCommand)\n        {\n            CreateAndPlacePrimitive(PrimitiveType.Cube, menuCommand.context as GameObject);\n        }\n\n        [MenuItem(\"GameObject/3D Object/Sphere\", priority = 2)]\n        static void CreateSphere(MenuCommand menuCommand)\n        {\n            CreateAndPlacePrimitive(PrimitiveType.Sphere, menuCommand.context as GameObject);\n        }\n\n        [MenuItem(\"GameObject/3D Object/Capsule\", priority = 3)]\n        static void CreateCapsule(MenuCommand menuCommand)\n        {\n            CreateAndPlacePrimitive(PrimitiveType.Capsule, menuCommand.context as GameObject);\n        }\n\n        [MenuItem(\"GameObject/3D Object/Cylinder\", priority = 4)]\n        static void CreateCylinder(MenuCommand menuCommand)\n        {\n            CreateAndPlacePrimitive(PrimitiveType.Cylinder, menuCommand.context as GameObject);\n        }\n\n        [MenuItem(\"GameObject/3D Object/Plane\", priority = 5)]\n        static void CreatePlane(MenuCommand menuCommand)\n        {\n            CreateAndPlacePrimitive(PrimitiveType.Plane, menuCommand.context as GameObject);\n        }\n\n        [MenuItem(\"GameObject/3D Object/Quad\", priority = 6)]\n        static void CreateQuad(MenuCommand menuCommand)\n        {\n            CreateAndPlacePrimitive(PrimitiveType.Quad, menuCommand.context as GameObject);\n        }\n\n        [MenuItem(\"GameObject/Light/Directional Light\", priority = 1)]\n        static void CreateDirectionalLight(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            var go = ObjectFactory.CreateGameObject(\"Directional Light\", typeof(Light));\n\n            go.GetComponent<Light>().type = LightType.Directional;\n            go.GetComponent<Transform>().SetLocalEulerAngles(new Vector3(50, -30, 0), RotationOrder.OrderZXY);\n\n            Place(go, parent);\n        }\n\n        [MenuItem(\"GameObject/Light/Point Light\", priority = 2)]\n        static void CreatePointLight(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            var go = ObjectFactory.CreateGameObject(\"Point Light\", typeof(Light));\n\n            go.GetComponent<Light>().type = LightType.Point;\n\n            Place(go, parent);\n        }\n\n        [MenuItem(\"GameObject/Light/Spot Light\", priority = 3)]\n        static void CreateSpotLight(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            var go = ObjectFactory.CreateGameObject(\"Spot Light\", typeof(Light));\n\n            go.GetComponent<Light>().type = LightType.Spot;\n            go.GetComponent<Transform>().SetLocalEulerAngles(new Vector3(90, 0, 0), RotationOrder.OrderZXY);\n\n            Place(go, parent);\n        }\n\n        [MenuItem(\"GameObject/Light/Area Light\", priority = 4)]\n        static void CreateAreaLight(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            var go = ObjectFactory.CreateGameObject(\"Area Light\", typeof(Light));\n\n            go.GetComponent<Light>().type = LightType.Rectangle;\n            go.GetComponent<Light>().shadows = LightShadows.Soft;\n            go.GetComponent<Transform>().SetLocalEulerAngles(new Vector3(90, 0, 0), RotationOrder.OrderZXY);\n\n            Place(go, parent);\n        }\n\n        [MenuItem(\"GameObject/Light/Reflection Probe\", priority = 20)]\n        static void CreateReflectionProbe(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            Place(ObjectFactory.CreateGameObject(\"Reflection Probe\", typeof(ReflectionProbe)), parent);\n        }\n\n        // Adjusted to fit with Probe Volume menu items (Packages\\com.unity.render-pipelines.core\\Editor\\Lighting\\ProbeVolumeMenuItems.cs)\n        // Choosing 80000 + 9 to avoid conflicts with any future additions to the Probe Volumes menus\n        [MenuItem(\"GameObject/Light/Light Probe Group\", priority = 80009)]\n        static void CreateLightProbeGroup(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            Place(ObjectFactory.CreateGameObject(\"Light Probe Group\", typeof(LightProbeGroup)), parent);\n        }\n\n        [MenuItem(\"GameObject/Audio/Audio Source\", priority = 1)]\n        static void CreateAudioSource(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            Place(ObjectFactory.CreateGameObject(\"Audio Source\", typeof(AudioSource)), parent);\n        }\n\n        [MenuItem(\"GameObject/Audio/Audio Reverb Zone\", priority = 2)]\n        static void CreateAudioReverbZone(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            Place(ObjectFactory.CreateGameObject(\"Audio Reverb Zone\", typeof(AudioReverbZone)), parent);\n        }\n\n        [MenuItem(\"GameObject/Video/Video Player\", priority = 1)]\n        static void CreateVideoPlayer(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            Place(ObjectFactory.CreateGameObject(\"Video Player\", typeof(VideoPlayer)), parent);\n        }\n\n        [MenuItem(\"GameObject/Effects/Particle System\", priority = 1)]\n        static void CreateParticleSystem(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            var go = ObjectFactory.CreateGameObject(\"Particle System\", typeof(ParticleSystem));\n\n            go.GetComponent<Transform>().SetLocalEulerAngles(new Vector3(-90, 0, 0), RotationOrder.OrderZXY);\n            var renderer = go.GetComponent<ParticleSystemRenderer>();\n            renderer.material = Material.GetDefaultParticleMaterial();\n            renderer.oldTrailMaterial = Material.GetDefaultLineMaterial(); // This trick means that when enabling the trails module for the first time, there is a default material assigned\n            Place(go, parent);\n        }\n\n        [MenuItem(\"GameObject/Effects/Particle System Force Field\", priority = 2)]\n        static void CreateParticleSystemForceField(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            Place(ObjectFactory.CreateGameObject(\"Particle System Force Field\", typeof(ParticleSystemForceField)), parent);\n        }\n\n        [MenuItem(\"GameObject/Effects/Trail\", priority = 3)]\n        static void CreateTrail(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            var go = ObjectFactory.CreateGameObject(\"Trail\", typeof(TrailRenderer));\n            go.GetComponent<TrailRenderer>().material = Material.GetDefaultLineMaterial();\n            Place(go, parent);\n        }\n\n        [MenuItem(\"GameObject/Effects/Line\", priority = 4)]\n        static void CreateLine(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            var go = ObjectFactory.CreateGameObject(\"Line\", typeof(LineRenderer));\n            var line = go.GetComponent<LineRenderer>();\n            line.material = Material.GetDefaultLineMaterial();\n            line.widthMultiplier = 0.1f;\n            line.useWorldSpace = false;\n            Place(go, parent);\n        }\n\n        [MenuItem(\"GameObject/Camera\", priority = 11)]\n        static void CreateCamera(MenuCommand menuCommand)\n        {\n            var parent = menuCommand.context as GameObject;\n            Place(ObjectFactory.CreateGameObject(\"Camera\", typeof(Camera), typeof(AudioListener)), parent, alignWithSceneCamera: true);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CompilationPipeline.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor.Compilation\n{\n    [Flags]\n    enum CompilationSetupErrors     // Keep in sync with enum CompilationSetupErrors::Flags in ScriptCompilationPipeline.h\n    {\n        None                        = 0,\n        LoadError                   = 1 << 0, // set when AssemblyDefinitionException is thrown\n        All                         = LoadError,\n    };\n\n    [NativeHeader(\"Editor/Src/ScriptCompilation/ScriptCompilationPipeline.h\")]\n    public static partial class CompilationPipeline\n    {\n        [FreeFunction]\n        internal static extern void DisableScriptDebugInfo();\n\n        [FreeFunction]\n        internal static extern void EnableScriptDebugInfo();\n\n        [FreeFunction]\n        internal static extern bool IsScriptDebugInfoEnabled();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ComponentUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Internal;\nusing UnityObject = UnityEngine.Object;\n\nnamespace UnityEditorInternal\n{\n    [NativeHeader(\"Editor/Src/ComponentUtility.bindings.h\")]\n    [StaticAccessor(\"ComponentUtilityBindings\", StaticAccessorType.DoubleColon)]\n    public sealed partial class ComponentUtility\n    {\n        public static bool MoveComponentUp(Component component)\n        {\n            return MoveComponentUp_Internal(new[] { component }, false, false);\n        }\n\n        [FreeFunction]\n        static extern bool MoveComponentUp_Internal(UnityObject[] context, bool validateOnly, bool showDialog);\n\n        public static bool MoveComponentDown(Component component)\n        {\n            return MoveComponentDown_Internal(new UnityObject[] { component }, false, false);\n        }\n\n        [FreeFunction]\n        static extern bool MoveComponentDown_Internal(UnityObject[] context, bool validateOnly, bool showDialog);\n\n        public static bool CopyComponent(Component component)\n        {\n            return CopyComponent(new UnityObject[] { component }, false);\n        }\n\n        [FreeFunction]\n        static extern bool CopyComponent(UnityObject[] context, bool validateOnly);\n\n        public static bool PasteComponentValues(Component component)\n        {\n            return PasteComponentValues(new UnityObject[] { component }, false);\n        }\n\n        [FreeFunction]\n        static extern bool PasteComponentValues(UnityObject[] context, bool validateOnly);\n\n        //Append new Components to the GameObject\n        public static extern bool PasteComponentAsNew([NotNull] GameObject go);\n\n        internal static extern bool CollectConnectedComponents([NotNull] GameObject targetGameObject, Component[] components, bool copy, [NotNull] List<Component> outCollectedComponents, out string outErrorMessage);\n\n        internal static bool MoveComponentToGameObject(Component component, GameObject targetGameObject)\n        {\n            return MoveComponentToGameObject(component, targetGameObject, false);\n        }\n\n        [FreeFunction(\"MoveComponent\")]\n        internal static extern bool MoveComponentToGameObject([NotNull] Component component, [NotNull] GameObject targetGameObject, [DefaultValue(\"false\")] bool validateOnly);\n\n        internal static bool MoveComponentRelativeToComponent(Component component, Component targetComponent, bool aboveTarget)\n        {\n            return MoveComponentRelativeToComponent(component, targetComponent, aboveTarget, false);\n        }\n\n        [FreeFunction(\"MoveComponent\")]\n        internal static extern bool MoveComponentRelativeToComponent([NotNull] Component component, [NotNull] Component targetComponent, bool aboveTarget, [DefaultValue(\"false\")] bool validateOnly);\n\n        internal static bool MoveComponentsRelativeToComponents(Component[] components, Component[] targetComponents, bool aboveTarget)\n        {\n            return MoveComponentsRelativeToComponents(components, targetComponents, aboveTarget, false);\n        }\n\n        [FreeFunction(\"MoveComponents\")]\n        internal static extern bool MoveComponentsRelativeToComponents(Component[] components, Component[] targetComponents, bool aboveTarget, [DefaultValue(\"false\")] bool validateOnly);\n\n        internal static extern bool CopyComponentToGameObject([NotNull] Component component, [NotNull] GameObject targetGameObject, bool validateOnly, [NotNull] List<Component> outNewComponents);\n        internal static extern bool CopyComponentToGameObjects([NotNull] Component component, GameObject[] targetGameObjects, bool validateOnly, [NotNull] List<Component> outNewComponents);\n        internal static extern bool CopyComponentRelativeToComponent([NotNull] Component component, [NotNull] Component targetComponent, bool aboveTarget, bool validateOnly, [NotNull] List<Component> outNewComponents);\n        internal static extern bool CopyComponentRelativeToComponents([NotNull] Component component, Component[] targetComponents, bool aboveTarget, bool validateOnly, [NotNull] List<Component> outNewComponents);\n        internal static extern bool CopyComponentsRelativeToComponents(Component[] components, Component[] targetComponents, bool aboveTarget, bool validateOnly, List<Component> outNewComponents);\n\n        [FreeFunction]\n        internal static extern bool WarnCanAddScriptComponent([NotNull] GameObject gameObject, [NotNull] MonoScript script);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ComponentUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace UnityEditorInternal\n{\n    public partial class ComponentUtility\n    {\n        static private bool CompareComponentOrderAndTypes(List<Component> srcComponents, List<Component> dstComponents)\n        {\n            if (srcComponents.Count != dstComponents.Count)\n                return false;\n\n            for (int i = 0; i != srcComponents.Count; i++)\n            {\n                if (srcComponents[i].GetType() != dstComponents[i].GetType())\n                    return false;\n            }\n\n            return true;\n        }\n\n        private static void DestroyComponents(List<Component> components)\n        {\n            // Delete in reverse order (to avoid errors when RequireComponent is used)\n            for (int i = components.Count - 1; i >= 0; i--)\n                UnityEngine.Object.DestroyImmediate(components[i]);\n        }\n\n        public delegate bool IsDesiredComponent(Component c);\n\n        public static void DestroyComponentsMatching(GameObject dst, IsDesiredComponent componentFilter)\n        {\n            var dstComponents = new List<Component>();\n            dst.GetComponents(dstComponents);\n            dstComponents.RemoveAll(x => !componentFilter(x));\n            DestroyComponents(dstComponents);\n        }\n\n        public static void ReplaceComponentsIfDifferent(GameObject src, GameObject dst, IsDesiredComponent componentFilter)\n        {\n            var srcComponents = new List<Component>();\n            src.GetComponents(srcComponents);\n            srcComponents.RemoveAll(x => !componentFilter(x));\n\n            var dstComponents = new List<Component>();\n            dst.GetComponents(dstComponents);\n            dstComponents.RemoveAll(x => !componentFilter(x));\n\n            // Generate components\n            if (!CompareComponentOrderAndTypes(srcComponents, dstComponents))\n            {\n                DestroyComponents(dstComponents);\n\n                // Add src components to dst\n                dstComponents.Clear();\n                for (int i = 0; i != srcComponents.Count; i++)\n                {\n                    Component com = dst.AddComponent(srcComponents[i].GetType());\n                    dstComponents.Add(com);\n                }\n            }\n\n            // Copy Data to components\n            for (int i = 0; i != srcComponents.Count; i++)\n                UnityEditor.EditorUtility.CopySerializedIfDifferent(srcComponents[i], dstComponents[i]);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ConsoleWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Globalization;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing System.Reflection;\nusing System.Text;\nusing JetBrains.Annotations;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing UnityEngine.Networking.PlayerConnection;\nusing UnityEditor.Networking.PlayerConnection;\nusing Unity.Collections.LowLevel.Unsafe;\nusing Unity.Collections;\nusing UnityEditor.Profiling;\n\nnamespace UnityEditor\n{\n    [EditorWindowTitle(title = \"Console\", useTypeNameAsIconName = true)]\n    internal class ConsoleWindow : EditorWindow, IHasCustomMenu\n    {\n        internal delegate void EntryDoubleClickedDelegate(LogEntry entry);\n        private static bool s_StripLoggingCallstack;\n        private static bool m_UseMonospaceFont;\n        private static Font m_MonospaceFont;\n        private static int m_DefaultFontSize;\n        private static List<MethodInfo> s_MethodsToHideInCallstack = null;\n        private static Dictionary<MethodInfo, Regex> s_GenericMethodSignatureRegex = null;\n        private static bool m_ShouldSkipClearingConsoleAfterBuild = false;\n\n        //TODO: move this out of here\n        internal class Constants\n        {\n            private static bool ms_Loaded;\n            private static int ms_logStyleLineCount;\n            public static GUIStyle Box;\n            public static GUIStyle MiniButton;\n            public static GUIStyle MiniButtonRight;\n            public static GUIStyle LogStyle;\n            public static GUIStyle WarningStyle;\n            public static GUIStyle ErrorStyle;\n            public static GUIStyle IconLogStyle;\n            public static GUIStyle IconWarningStyle;\n            public static GUIStyle IconErrorStyle;\n            public static GUIStyle EvenBackground;\n            public static GUIStyle OddBackground;\n            public static GUIStyle MessageStyle;\n            public static GUIStyle StatusError;\n            public static GUIStyle StatusWarn;\n            public static GUIStyle StatusLog;\n            public static GUIStyle Toolbar;\n            public static GUIStyle CountBadge;\n            public static GUIStyle LogSmallStyle;\n            public static GUIStyle WarningSmallStyle;\n            public static GUIStyle ErrorSmallStyle;\n            public static GUIStyle IconLogSmallStyle;\n            public static GUIStyle IconWarningSmallStyle;\n            public static GUIStyle IconErrorSmallStyle;\n            public static GUIStyle ConsoleSearchNoResult;\n\n            public static readonly GUIContent Clear = EditorGUIUtility.TrTextContent(\"Clear\", \"Clear console entries\");\n            public static readonly GUIContent ClearOnPlay = EditorGUIUtility.TrTextContent(\"Clear on Play\");\n            public static readonly GUIContent ClearOnBuild = EditorGUIUtility.TrTextContent(\"Clear on Build\");\n            public static readonly GUIContent ClearOnRecompile = EditorGUIUtility.TrTextContent(\"Clear on Recompile\");\n            public static readonly GUIContent Collapse = EditorGUIUtility.TrTextContent(\"Collapse\", \"Collapse identical entries\");\n            public static readonly GUIContent ErrorPause = EditorGUIUtility.TrTextContent(\"Error Pause\", \"Pause Play Mode on error\");\n            public static readonly GUIContent StopForAssert = EditorGUIUtility.TrTextContent(\"Stop for Assert\");\n            public static readonly GUIContent StopForError = EditorGUIUtility.TrTextContent(\"Stop for Error\");\n            public static readonly GUIContent UseMonospaceFont = EditorGUIUtility.TrTextContent(\"Use Monospace font\");\n            public static readonly GUIContent StripLoggingCallstack = EditorGUIUtility.TrTextContent(\"Strip logging callstack\");\n\n            public static int LogStyleLineCount\n            {\n                get { return ms_logStyleLineCount; }\n                set\n                {\n                    ms_logStyleLineCount = value;\n\n                    // If Constants hasn't been initialized yet we just skip this for now\n                    // and let Init() call this for us in a bit.\n                    if (!ms_Loaded)\n                        return;\n                    UpdateLogStyleFixedHeights();\n                }\n            }\n\n            public static void Init()\n            {\n                if (ms_Loaded)\n                    return;\n                ms_Loaded = true;\n                Box = \"CN Box\";\n\n                MiniButton = \"ToolbarButton\";\n                MiniButtonRight = \"ToolbarButtonRight\";\n                Toolbar = \"Toolbar\";\n                LogStyle = \"CN EntryInfo\";\n                LogSmallStyle = \"CN EntryInfoSmall\";\n                WarningStyle = \"CN EntryWarn\";\n                WarningSmallStyle = \"CN EntryWarnSmall\";\n                ErrorStyle = \"CN EntryError\";\n                ErrorSmallStyle = \"CN EntryErrorSmall\";\n                IconLogStyle = \"CN EntryInfoIcon\";\n                IconLogSmallStyle = \"CN EntryInfoIconSmall\";\n                IconWarningStyle = \"CN EntryWarnIcon\";\n                IconWarningSmallStyle = \"CN EntryWarnIconSmall\";\n                IconErrorStyle = \"CN EntryErrorIcon\";\n                IconErrorSmallStyle = \"CN EntryErrorIconSmall\";\n                EvenBackground = \"CN EntryBackEven\";\n                OddBackground = \"CN EntryBackodd\";\n                MessageStyle = \"CN Message\";\n                StatusError = \"CN StatusError\";\n                StatusWarn = \"CN StatusWarn\";\n                StatusLog = \"CN StatusInfo\";\n                CountBadge = \"CN CountBadge\";\n\n                ConsoleSearchNoResult = new GUIStyle(EditorStyles.centeredGreyMiniLabel)\n                {\n                    name = \"console-search-no-result\",\n                    fontSize = 20,\n                    wordWrap = true\n                };\n\n                // If the console window isn't open OnEnable() won't trigger so it will end up with 0 lines,\n                // so we always make sure we read it up when we initialize here.\n                LogStyleLineCount = EditorPrefs.GetInt(\"ConsoleWindowLogLineCount\", 2);\n\n                m_MonospaceFont = EditorGUIUtility.Load(\"Fonts/RobotoMono/RobotoMono-Regular.ttf\") as Font;\n                m_UseMonospaceFont = HasFlag(ConsoleFlags.UseMonospaceFont);\n                s_StripLoggingCallstack = HasFlag(ConsoleFlags.StripLoggingCallstack);\n                m_DefaultFontSize = LogStyle.fontSize;\n                SetFont();\n                (s_MethodsToHideInCallstack, s_GenericMethodSignatureRegex) = InitializeHideInCallstackMethodsCache();\n            }\n\n            internal static void UpdateLogStyleFixedHeights()\n            {\n                // Whenever we change the line height count or the styles are set we need to update the fixed height\n                // of the following GuiStyles so the entries do not get cropped incorrectly.\n                ErrorStyle.fixedHeight = (LogStyleLineCount * ErrorStyle.lineHeight) + ErrorStyle.border.top;\n                WarningStyle.fixedHeight = (LogStyleLineCount * WarningStyle.lineHeight) + WarningStyle.border.top;\n                LogStyle.fixedHeight = (LogStyleLineCount * LogStyle.lineHeight) + LogStyle.border.top;\n            }\n        }\n\n        int m_LineHeight;\n        int m_BorderHeight;\n\n        bool m_HasUpdatedGuiStyles;\n\n        string m_ConsoleSearchNoResultMsg = \"\";\n\n        ListViewState m_ListView;\n        bool m_SyncAutoScroll;\n        string m_ActiveText = \"\";\n        StringBuilder m_CopyString;\n        bool m_DevBuild;\n        int m_CallstackTextStart = 0;\n        private Mode m_ActiveMode = Mode.None;\n\n        Vector2 m_TextScroll = Vector2.zero;\n\n        int m_LastActiveEntryIndex = -1;\n        [NonSerialized]\n        int m_IndexHintCache;\n        bool m_RestoreLatestSelection;\n\n        //Make sure the minimum height of the panels can accomodate the cpmplete scroll bar icons\n        SplitterState spl = SplitterState.FromRelative(new float[] {70, 30}, new float[] {60, 60}, null);\n\n        static bool ms_LoadedIcons = false;\n        static internal Texture2D iconInfo, iconWarn, iconError;\n        static internal Texture2D iconInfoSmall, iconWarnSmall, iconErrorSmall;\n        static internal Texture2D iconInfoMono, iconWarnMono, iconErrorMono;\n\n        int ms_LVHeight = 0;\n\n        internal class ConsoleAttachToPlayerState : GeneralConnectionState\n        {\n            public ConsoleAttachToPlayerState(EditorWindow parentWindow, Action<string, EditorConnectionTarget?> connectedCallback = null) : base(parentWindow, connectedCallback)\n            {\n                // This is needed to force initialize the instance and the state so that messages from players are received and printed to the console (if that is the serialized state)\n                // on creation of the ConsoleWindow UI instead of when the uer first clicks on the dropdown, and triggers AddItemsToTree.\n                PlayerConnectionLogReceiver.instance.State = PlayerConnectionLogReceiver.instance.State;\n            }\n\n            internal bool IsConnected()\n            {\n                return PlayerConnectionLogReceiver.instance.State != PlayerConnectionLogReceiver.ConnectionState.Disconnected;\n            }\n\n            internal void PlayerLoggingOptionSelected()\n            {\n                PlayerConnectionLogReceiver.instance.State = IsConnected() ? PlayerConnectionLogReceiver.ConnectionState.Disconnected : PlayerConnectionLogReceiver.ConnectionState.CleanLog;\n            }\n\n            internal bool IsLoggingFullLog()\n            {\n                return PlayerConnectionLogReceiver.instance.State == PlayerConnectionLogReceiver.ConnectionState.FullLog;\n            }\n\n            internal void FullLogOptionSelected()\n            {\n                PlayerConnectionLogReceiver.instance.State = IsLoggingFullLog() ? PlayerConnectionLogReceiver.ConnectionState.CleanLog : PlayerConnectionLogReceiver.ConnectionState.FullLog;\n            }\n\n            public override void AddItemsToTree(ConnectionTreeViewWindow view, Rect position)\n            {\n                view.SetLoggingOptions(this);\n                base.AddItemsToTree(view, position);\n            }\n        }\n\n        IConnectionState m_ConsoleAttachToPlayerState;\n\n        [Flags]\n        internal enum Mode\n        {\n            None = 0,\n            Error = 1 << 0,\n            Assert = 1 << 1,\n            Log = 1 << 2,\n            Fatal = 1 << 4,\n            DontPreprocessCondition = 1 << 5,\n            AssetImportError = 1 << 6,\n            AssetImportWarning = 1 << 7,\n            ScriptingError = 1 << 8,\n            ScriptingWarning = 1 << 9,\n            ScriptingLog = 1 << 10,\n            ScriptCompileError = 1 << 11,\n            ScriptCompileWarning = 1 << 12,\n            StickyError = 1 << 13,\n            MayIgnoreLineNumber = 1 << 14,\n            ReportBug = 1 << 15,\n            DisplayPreviousErrorInStatusBar = 1 << 16,\n            ScriptingException = 1 << 17,\n            DontExtractStacktrace = 1 << 18,\n            ShouldClearOnPlay = 1 << 19,\n            GraphCompileError = 1 << 20,\n            ScriptingAssertion = 1 << 21,\n            VisualScriptingError = 1 << 22\n        }\n\n        enum ConsoleFlags\n        {\n            Collapse = 1 << 0,\n            ClearOnPlay = 1 << 1,\n            ErrorPause = 1 << 2,\n            Verbose = 1 << 3,\n            StopForAssert = 1 << 4,\n            StopForError = 1 << 5,\n            Autoscroll = 1 << 6,\n            LogLevelLog = 1 << 7,\n            LogLevelWarning = 1 << 8,\n            LogLevelError = 1 << 9,\n            ShowTimestamp = 1 << 10,\n            ClearOnBuild = 1 << 11,\n            ClearOnRecompile = 1 << 12,\n            UseMonospaceFont = 1 << 13,\n            StripLoggingCallstack = 1 << 14,\n        }\n\n        static ConsoleWindow ms_ConsoleWindow = null;\n        private string m_SearchText;\n\n        static readonly int k_HasSpaceForExtraButtonsCutoff = 420;\n\n        public static void ShowConsoleWindow(bool immediate)\n        {\n            if (!ms_ConsoleWindow)\n            {\n                ms_ConsoleWindow = ScriptableObject.CreateInstance<ConsoleWindow>();\n                if (UnityEditor.MPE.ProcessService.level == MPE.ProcessLevel.Main)\n                    ms_ConsoleWindow.Show(immediate);\n                else\n                    ms_ConsoleWindow.ShowModalUtility();\n                if (ms_ConsoleWindow)\n                    ms_ConsoleWindow.Focus();\n            }\n            else\n            {\n                ms_ConsoleWindow.Show(immediate);\n                ms_ConsoleWindow.Focus();\n            }\n        }\n\n        static internal void LoadIcons()\n        {\n            if (ms_LoadedIcons)\n                return;\n\n            ms_LoadedIcons = true;\n            iconInfo = EditorGUIUtility.LoadIcon(\"console.infoicon\");\n            iconWarn = EditorGUIUtility.LoadIcon(\"console.warnicon\");\n            iconError = EditorGUIUtility.LoadIcon(\"console.erroricon\");\n            iconInfoSmall = EditorGUIUtility.LoadIcon(\"console.infoicon.sml\");\n            iconWarnSmall = EditorGUIUtility.LoadIcon(\"console.warnicon.sml\");\n            iconErrorSmall = EditorGUIUtility.LoadIcon(\"console.erroricon.sml\");\n\n            // TODO: Once we get the proper monochrome images put them here.\n            /*iconInfoMono = EditorGUIUtility.LoadIcon(\"console.infoicon.mono\");\n            iconWarnMono = EditorGUIUtility.LoadIcon(\"console.warnicon.mono\");\n            iconErrorMono = EditorGUIUtility.LoadIcon(\"console.erroricon.mono\");*/\n            iconInfoMono = EditorGUIUtility.LoadIcon(\"console.infoicon.inactive.sml\");\n            iconWarnMono = EditorGUIUtility.LoadIcon(\"console.warnicon.inactive.sml\");\n            iconErrorMono = EditorGUIUtility.LoadIcon(\"console.erroricon.inactive.sml\");\n            Constants.Init();\n        }\n\n        [RequiredByNativeCode]\n        public static void LogChanged()\n        {\n            if (!ms_ConsoleWindow)\n                return;\n            ms_ConsoleWindow.Repaint();\n            ConsoleWindowUtility.Internal_CallLogsHaveChanged();\n        }\n\n        public ConsoleWindow()\n        {\n            position = new Rect(200, 200, 800, 400);\n            m_ListView = new ListViewState(0, 0);\n            m_CopyString = new StringBuilder();\n            m_SearchText = string.Empty;\n        }\n\n        internal void OnEnable()\n        {\n            if (m_ConsoleAttachToPlayerState == null)\n                m_ConsoleAttachToPlayerState = new ConsoleAttachToPlayerState(this);\n\n            // Update the filter on enable for DomainReload(keep current filter) and window opening(reset filter because m_searchText is null)\n            SetFilter(LogEntries.GetFilteringText());\n\n            wantsLessLayoutEvents = true;\n            titleContent = GetLocalizedTitleContent();\n            ms_ConsoleWindow = this;\n            m_DevBuild = Unsupported.IsDeveloperMode();\n\n            Constants.LogStyleLineCount = EditorPrefs.GetInt(\"ConsoleWindowLogLineCount\", 2);\n        }\n\n        internal void OnDisable()\n        {\n            m_ConsoleAttachToPlayerState?.Dispose();\n            m_ConsoleAttachToPlayerState = null;\n        }\n\n        private int RowHeight => (Constants.LogStyleLineCount > 1 ? Mathf.Max(32, (Constants.LogStyleLineCount * m_LineHeight)) : m_LineHeight) + m_BorderHeight;\n\n        private static bool HasMode(int mode, Mode modeToCheck) { return (mode & (int)modeToCheck) != 0; }\n        private static bool HasFlag(ConsoleFlags flags) { return (LogEntries.consoleFlags & (int)flags) != 0; }\n        private static void SetFlag(ConsoleFlags flags, bool val) { LogEntries.SetConsoleFlag((int)flags, val); }\n\n        static internal Texture2D GetIconForErrorMode(int mode, bool large)\n        {\n            // Errors\n            if (HasMode(mode, Mode.Fatal | Mode.Assert |\n                Mode.Error | Mode.ScriptingError |\n                Mode.AssetImportError | Mode.ScriptCompileError |\n                Mode.GraphCompileError | Mode.ScriptingAssertion))\n                return large ? iconError : iconErrorSmall;\n            // Warnings\n            if (HasMode(mode, Mode.ScriptCompileWarning | Mode.ScriptingWarning | Mode.AssetImportWarning))\n                return large ? iconWarn : iconWarnSmall;\n            // Logs\n            if (HasMode(mode, Mode.Log | Mode.ScriptingLog))\n                return large ? iconInfo : iconInfoSmall;\n\n            // Nothing\n            return null;\n        }\n\n        static internal GUIStyle GetStyleForErrorMode(int mode, bool isIcon, bool isSmall)\n        {\n            // Errors\n            if (HasMode(mode, Mode.Fatal | Mode.Assert |\n                Mode.Error | Mode.ScriptingError |\n                Mode.AssetImportError | Mode.ScriptCompileError |\n                Mode.GraphCompileError | Mode.ScriptingAssertion | Mode.ScriptingException))\n            {\n                if (isIcon)\n                {\n                    if (isSmall)\n                    {\n                        return Constants.IconErrorSmallStyle;\n                    }\n                    return Constants.IconErrorStyle;\n                }\n\n                if (isSmall)\n                {\n                    return Constants.ErrorSmallStyle;\n                }\n                return Constants.ErrorStyle;\n            }\n            // Warnings\n            if (HasMode(mode, Mode.ScriptCompileWarning | Mode.ScriptingWarning | Mode.AssetImportWarning))\n            {\n                if (isIcon)\n                {\n                    if (isSmall)\n                    {\n                        return Constants.IconWarningSmallStyle;\n                    }\n                    return Constants.IconWarningStyle;\n                }\n\n                if (isSmall)\n                {\n                    return Constants.WarningSmallStyle;\n                }\n                return Constants.WarningStyle;\n            }\n            // Logs\n            if (isIcon)\n            {\n                if (isSmall)\n                {\n                    return Constants.IconLogSmallStyle;\n                }\n                return Constants.IconLogStyle;\n            }\n\n            if (isSmall)\n            {\n                return Constants.LogSmallStyle;\n            }\n            return Constants.LogStyle;\n        }\n\n        static internal GUIStyle GetStatusStyleForErrorMode(int mode)\n        {\n            // Errors\n            if (HasMode(mode, Mode.Fatal | Mode.Assert |\n                Mode.Error | Mode.ScriptingError |\n                Mode.AssetImportError | Mode.ScriptCompileError |\n                Mode.GraphCompileError | Mode.ScriptingAssertion))\n                return Constants.StatusError;\n            // Warnings\n            if (HasMode(mode, Mode.ScriptCompileWarning | Mode.ScriptingWarning | Mode.AssetImportWarning))\n                return Constants.StatusWarn;\n            // Logs\n            return Constants.StatusLog;\n        }\n\n        void SetActiveEntry(LogEntry entry)\n        {\n            if (entry != null)\n            {\n                m_ActiveText = entry.message;\n                m_ActiveMode = (Mode)entry.mode;\n                entry.callstackTextStartUTF8 = entry.message.Length;\n                m_CallstackTextStart = entry.callstackTextStartUTF16;\n                var entryRow = LogEntries.GetEntryRowIndex(entry.globalLineIndex, m_IndexHintCache);\n                m_IndexHintCache = entryRow;\n            }\n            else\n            {\n                m_CallstackTextStart = 0;\n                m_ActiveText = string.Empty;\n                m_ListView.row = -1;\n                m_CopyString.Clear();\n                m_ActiveMode = Mode.None;\n            }\n        }\n\n        [UsedImplicitly, RequiredByNativeCode]\n        internal static void ShowConsoleRow(int row)\n        {\n            ShowConsoleWindow(false);\n\n            if (ms_ConsoleWindow)\n            {\n                ms_ConsoleWindow.m_ListView.row = row;\n                ms_ConsoleWindow.m_ListView.selectionChanged = true;\n                ms_ConsoleWindow.Repaint();\n            }\n        }\n\n        void UpdateListView()\n        {\n            m_HasUpdatedGuiStyles = true;\n            int newRowHeight = RowHeight;\n\n            // We reset the scroll list to auto scrolling whenever the log entry count is modified\n            m_ListView.rowHeight = newRowHeight;\n            m_ListView.row = -1;\n            SetScrollPosYFromRow(LogEntries.GetCount());\n        }\n\n        bool HasSpaceForExtraButtons()\n        {\n            return position.width > k_HasSpaceForExtraButtonsCutoff;\n        }\n\n        internal void OnGUI()\n        {\n            Event e = Event.current;\n            LoadIcons();\n\n            if (!m_HasUpdatedGuiStyles)\n            {\n                m_LineHeight = Mathf.RoundToInt(Constants.ErrorStyle.lineHeight);\n                m_BorderHeight = Constants.ErrorStyle.border.top + Constants.ErrorStyle.border.bottom;\n                UpdateListView();\n            }\n\n            GUILayout.BeginHorizontal(Constants.Toolbar);\n\n            // Clear button and clearing options\n            bool clearClicked = false;\n            if (EditorGUILayout.DropDownToggle(ref clearClicked, Constants.Clear, EditorStyles.toolbarDropDownToggle))\n            {\n                var clearOnPlay = HasFlag(ConsoleFlags.ClearOnPlay);\n                var clearOnBuild = HasFlag(ConsoleFlags.ClearOnBuild);\n                var clearOnRecompile = HasFlag(ConsoleFlags.ClearOnRecompile);\n\n                GenericMenu menu = new GenericMenu();\n                menu.AddItem(Constants.ClearOnPlay, clearOnPlay, () => { SetFlag(ConsoleFlags.ClearOnPlay, !clearOnPlay); });\n                menu.AddItem(Constants.ClearOnBuild, clearOnBuild, () => { SetFlag(ConsoleFlags.ClearOnBuild, !clearOnBuild); });\n                menu.AddItem(Constants.ClearOnRecompile, clearOnRecompile, () => { SetFlag(ConsoleFlags.ClearOnRecompile, !clearOnRecompile); });\n                var rect = GUILayoutUtility.GetLastRect();\n                rect.y += EditorGUIUtility.singleLineHeight;\n                menu.DropDown(rect);\n            }\n            if (clearClicked)\n            {\n                LogEntries.Clear();\n                GUIUtility.keyboardControl = 0;\n            }\n\n            int currCount = LogEntries.GetCount();\n            bool showSearchNoResultMessage = currCount == 0 && !String.IsNullOrEmpty(m_SearchText);\n            m_SyncAutoScroll = false;\n            if (m_ListView.totalRows != currCount)\n            {\n                // scroll bar was at the bottom?\n                var expectedScrollPosY = GetScrollPosY(m_ListView.totalRows);\n                if (m_ListView.scrollPos.y >= expectedScrollPosY)\n                {\n                    m_ListView.scrollPos.y = GetScrollPosY(currCount);\n                    m_SyncAutoScroll = true;\n                }\n            }\n\n            bool wasCollapsed = HasFlag(ConsoleFlags.Collapse);\n            SetFlag(ConsoleFlags.Collapse, GUILayout.Toggle(wasCollapsed, Constants.Collapse, Constants.MiniButton));\n\n            bool collapsedChanged = (wasCollapsed != HasFlag(ConsoleFlags.Collapse));\n            if (collapsedChanged)\n            {\n                // unselect if collapsed flag changed\n                m_ListView.row = -1;\n\n                // scroll to bottom\n                SetScrollPosYFromRow(LogEntries.GetCount());\n            }\n\n            if (HasSpaceForExtraButtons())\n            {\n                SetFlag(ConsoleFlags.ErrorPause, GUILayout.Toggle(HasFlag(ConsoleFlags.ErrorPause), Constants.ErrorPause, Constants.MiniButton));\n                PlayerConnectionGUILayout.ConnectionTargetSelectionDropdown(m_ConsoleAttachToPlayerState, EditorStyles.toolbarDropDown, (int)(position.width - k_HasSpaceForExtraButtonsCutoff) + 80 );\n            }\n\n            GUILayout.FlexibleSpace();\n\n            // Search bar\n            if (HasSpaceForExtraButtons())\n                SearchField(e);\n\n            // Flags\n            int errorCount = 0, warningCount = 0, logCount = 0;\n            LogEntries.GetCountsByType(ref errorCount, ref warningCount, ref logCount);\n            EditorGUI.BeginChangeCheck();\n            bool setLogFlag = GUILayout.Toggle(HasFlag(ConsoleFlags.LogLevelLog), new GUIContent((logCount <= 999 ? logCount.ToString() : \"999+\"), logCount > 0 ? iconInfoSmall : iconInfoMono), Constants.MiniButton);\n            bool setWarningFlag = GUILayout.Toggle(HasFlag(ConsoleFlags.LogLevelWarning), new GUIContent((warningCount <= 999 ? warningCount.ToString() : \"999+\"), warningCount > 0 ? iconWarnSmall : iconWarnMono), Constants.MiniButton);\n            bool setErrorFlag = GUILayout.Toggle(HasFlag(ConsoleFlags.LogLevelError), new GUIContent((errorCount <= 999 ? errorCount.ToString() : \"999+\"), errorCount > 0 ? iconErrorSmall : iconErrorMono), Constants.MiniButtonRight);\n            // Active entry index may no longer be valid\n            if (EditorGUI.EndChangeCheck())\n            {\n                SetActiveEntry(null);\n                m_LastActiveEntryIndex = -1;\n            }\n\n            SetFlag(ConsoleFlags.LogLevelLog, setLogFlag);\n            SetFlag(ConsoleFlags.LogLevelWarning, setWarningFlag);\n            SetFlag(ConsoleFlags.LogLevelError, setErrorFlag);\n\n            GUILayout.EndHorizontal();\n\n            if (showSearchNoResultMessage)\n            {\n                Rect r = new Rect(0, EditorGUI.kSingleLineHeight, ms_ConsoleWindow.position.width, ms_ConsoleWindow.position.height - EditorGUI.kSingleLineHeight);\n                GUI.Box(r, m_ConsoleSearchNoResultMsg, Constants.ConsoleSearchNoResult);\n            }\n            else\n            {\n                // Console entries\n                SplitterGUILayout.BeginVerticalSplit(spl);\n\n                GUIContent tempContent = new GUIContent();\n                int id = GUIUtility.GetControlID(0);\n                int rowDoubleClicked = -1;\n\n                /////@TODO: Make Frame selected work with ListViewState\n                using (new GettingLogEntriesScope(m_ListView))\n                {\n                    int selectedRow = -1;\n                    bool openSelectedItem = false;\n                    bool collapsed = HasFlag(ConsoleFlags.Collapse);\n                    float scrollPosY = m_ListView.scrollPos.y;\n\n                    foreach (ListViewElement el in ListViewGUI.ListView(m_ListView,\n                        ListViewOptions.wantsRowMultiSelection, Constants.Box))\n                    {\n                        // Destroy latest restore entry if needed\n                        if (e.type == EventType.ScrollWheel || e.type == EventType.Used)\n                            DestroyLatestRestoreEntry();\n\n                        // Make sure that scrollPos.y is always up to date after restoring last entry\n                        if (m_RestoreLatestSelection)\n                        {\n                            SetScrollPosY(scrollPosY);\n                        }\n\n                        if (e.type == EventType.MouseDown && e.button == 0 && el.position.Contains(e.mousePosition))\n                        {\n                            selectedRow = m_ListView.row;\n                            DestroyLatestRestoreEntry();\n                            LogEntry entry = new LogEntry();\n                            LogEntries.GetEntryInternal(el.row, entry);\n                            if (entry.instanceID != 0 && e.clickCount != 2)\n                                EditorGUIUtility.PingObject(entry.instanceID);\n                            if (e.clickCount == 2)\n                                openSelectedItem = true;\n                            m_SyncAutoScroll = false;\n                        }\n                        else if (e.type == EventType.Repaint)\n                        {\n                            int mode = 0;\n                            string text = null;\n                            LogEntries.GetLinesAndModeFromEntryInternal(el.row, Constants.LogStyleLineCount, ref mode,\n                                ref text);\n                            bool entryIsSelected = m_ListView.selectedItems != null &&\n                                el.row < m_ListView.selectedItems.Length &&\n                                m_ListView.selectedItems[el.row];\n\n                            // offset value in x for icon and text\n                            var offset = Constants.LogStyleLineCount == 1 ? 4 : 8;\n\n                            // Draw the background\n                            GUIStyle s = el.row % 2 == 0 ? Constants.OddBackground : Constants.EvenBackground;\n                            s.Draw(el.position, false, false, entryIsSelected, false);\n\n                            // Draw the icon\n                            GUIStyle iconStyle = GetStyleForErrorMode(mode, true, Constants.LogStyleLineCount == 1);\n                            Rect iconRect = el.position;\n                            iconRect.x += offset;\n                            iconRect.y += 2;\n\n                            iconStyle.Draw(iconRect, false, false, entryIsSelected, false);\n\n                            // Draw the text\n                            tempContent.text = text;\n                            GUIStyle errorModeStyle =\n                                GetStyleForErrorMode(mode, false, Constants.LogStyleLineCount == 1);\n                            var textRect = el.position;\n                            textRect.x += offset;\n\n                            if (string.IsNullOrEmpty(m_SearchText))\n                                errorModeStyle.Draw(textRect, tempContent, id, m_ListView.row == el.row);\n                            else if (text != null)\n                            {\n                                //the whole text contains the searchtext, we have to know where it is\n                                int startIndex = text.IndexOf(m_SearchText, StringComparison.OrdinalIgnoreCase);\n                                if (startIndex == -1\n                                ) // the searchtext is not in the visible text, we don't show the selection\n                                    errorModeStyle.Draw(textRect, tempContent, id, m_ListView.row == el.row);\n                                else // the searchtext is visible, we show the selection\n                                {\n                                    int endIndex = startIndex + m_SearchText.Length;\n\n                                    const bool isActive = false;\n                                    const bool\n                                        hasKeyboardFocus =\n                                        true;     // This ensure we draw the selection text over the label.\n                                    const bool drawAsComposition = false;\n                                    Color selectionColor = GUI.skin.settings.selectionColor;\n\n                                    errorModeStyle.DrawWithTextSelection(textRect, tempContent, isActive,\n                                        hasKeyboardFocus, startIndex, endIndex, drawAsComposition, selectionColor);\n                                }\n                            }\n\n                            if (collapsed)\n                            {\n                                Rect badgeRect = el.position;\n                                tempContent.text = LogEntries.GetEntryCount(el.row)\n                                    .ToString(CultureInfo.InvariantCulture);\n                                Vector2 badgeSize = Constants.CountBadge.CalcSize(tempContent);\n\n                                if (Constants.CountBadge.fixedHeight > 0)\n                                    badgeSize.y = Constants.CountBadge.fixedHeight;\n                                badgeRect.xMin = badgeRect.xMax - badgeSize.x;\n                                badgeRect.yMin += ((badgeRect.yMax - badgeRect.yMin) - badgeSize.y) * 0.5f;\n                                badgeRect.x -= 5f;\n                                GUI.Label(badgeRect, tempContent, Constants.CountBadge);\n                            }\n                        }\n                    }\n\n                    if (selectedRow != -1)\n                    {\n                        var expectedScrollPosY = GetScrollPosY(m_ListView.totalRows);\n                        if (m_ListView.scrollPos.y >= expectedScrollPosY)\n                        {\n                            SetScrollPosY(expectedScrollPosY - 1);\n                        }\n                    }\n\n                    // Make sure the selected entry is up to date\n                    if (m_ListView.totalRows == 0 || m_ListView.row >= m_ListView.totalRows || m_ListView.row < 0)\n                    {\n                        if (m_ActiveText.Length != 0)\n                        {\n                            SetActiveEntry(null);\n                            DestroyLatestRestoreEntry();\n                        }\n                    }\n                    else\n                    {\n                        LogEntry entry = new LogEntry();\n                        LogEntries.GetEntryInternal(m_ListView.row, entry);\n                        SetActiveEntry(entry);\n                        m_LastActiveEntryIndex = entry.globalLineIndex;\n\n\n                        // see if selected entry changed. if so - clear additional info\n                        LogEntries.GetEntryInternal(m_ListView.row, entry);\n                        if (m_ListView.selectionChanged || !m_ActiveText.Equals(entry.message))\n                        {\n                            SetActiveEntry(entry);\n                            m_LastActiveEntryIndex = entry.globalLineIndex;\n                            m_TextScroll = Vector2.zero;\n                            activeEntryChanged?.Invoke();\n                        }\n\n\n                        // If copy, get the messages from selected rows\n                        if (e.type == EventType.ExecuteCommand && e.commandName == EventCommandNames.Copy &&\n                            m_ListView.selectedItems != null)\n                        {\n                            m_CopyString.Clear();\n                            for (int rowIndex = 0; rowIndex < m_ListView.selectedItems.Length; rowIndex++)\n                            {\n                                if (m_ListView.selectedItems[rowIndex])\n                                {\n                                    LogEntries.GetEntryInternal(rowIndex, entry);\n                                    m_CopyString.AppendLine(entry.message);\n                                }\n                            }\n                        }\n                    }\n\n                    // Open entry using return key\n                    if ((GUIUtility.keyboardControl == m_ListView.ID) && (e.type == EventType.KeyDown) &&\n                        (e.keyCode == KeyCode.Return) && (m_ListView.row != 0))\n                    {\n                        selectedRow = m_ListView.row;\n                        openSelectedItem = true;\n                    }\n\n                    if (e.type != EventType.Layout && ListViewGUI.ilvState.rectHeight != 1)\n                        ms_LVHeight = ListViewGUI.ilvState.rectHeight;\n\n                    if (openSelectedItem)\n                    {\n                        rowDoubleClicked = selectedRow;\n                        e.Use();\n                    }\n                }\n\n                // Prevent dead locking in EditorMonoConsole by delaying callbacks (which can log to the console) until after LogEntries.EndGettingEntries() has been\n                // called (this releases the mutex in EditorMonoConsole so logging again is allowed). Fix for case 1081060.\n                if (rowDoubleClicked != -1)\n                    LogEntries.RowGotDoubleClicked(rowDoubleClicked);\n\n                // Display active text (We want word wrapped text with a vertical scrollbar)\n                string stackWithHyperlinks = StacktraceWithHyperlinks(m_ActiveText, m_CallstackTextStart, s_StripLoggingCallstack, m_ActiveMode);\n                float height = Constants.MessageStyle.CalcHeight(GUIContent.Temp(stackWithHyperlinks), position.width);\n\n                var rect = EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true), GUILayout.MinHeight(height + 10));\n                EditorGUI.ScrollableLabelAreaInternal(rect, stackWithHyperlinks, ref m_TextScroll, Constants.MessageStyle);\n                EditorGUILayout.EndHorizontal();\n\n                SplitterGUILayout.EndVerticalSplit();\n            }\n\n            // Copy & Paste selected item\n            if ((e.type == EventType.ValidateCommand || e.type == EventType.ExecuteCommand) && e.commandName == EventCommandNames.Copy && m_CopyString != null)\n            {\n                if (e.type == EventType.ExecuteCommand)\n                    EditorGUIUtility.systemCopyBuffer = m_CopyString.ToString();\n                e.Use();\n            }\n\n            if (!ms_ConsoleWindow)\n                ms_ConsoleWindow = this;\n\n            if (m_SyncAutoScroll)\n            {\n                // Enforce autoscroll according to any potentially new rows having been added during OnGUI\n                SetScrollPosYFromRow(m_ListView.totalRows);\n            }\n        }\n\n        private void SetScrollPosY(float posY)\n        {\n            m_ListView.scrollPos.y = posY;\n            m_SyncAutoScroll = false;\n        }\n\n        private void SetScrollPosYFromRow(int rowIndex)\n        {\n            SetScrollPosY(GetScrollPosY(rowIndex));\n        }\n\n        private float GetScrollPosY(int rowIndex)\n        {\n            return rowIndex * m_ListView.rowHeight - ms_LVHeight;\n        }\n\n        private void SearchField(Event e)\n        {\n            string searchBarName = \"SearchFilter\";\n            if (e.commandName == EventCommandNames.Find)\n            {\n                if (e.type == EventType.ExecuteCommand)\n                {\n                    EditorGUI.FocusTextInControl(searchBarName);\n                }\n\n                if (e.type != EventType.Layout)\n                    e.Use();\n            }\n\n            string searchText = m_SearchText;\n\n            if (e.type == EventType.KeyDown)\n            {\n                if (e.keyCode == KeyCode.Escape)\n                {\n                    searchText = string.Empty;\n                    GUIUtility.keyboardControl = m_ListView.ID;\n                    Repaint();\n                    if (!String.IsNullOrEmpty(m_SearchText))\n                        RestoreLastActiveEntry();\n                }\n                else if ((e.keyCode == KeyCode.UpArrow || e.keyCode == KeyCode.DownArrow) &&\n                         GUI.GetNameOfFocusedControl() == searchBarName)\n                {\n                    GUIUtility.keyboardControl = m_ListView.ID;\n                }\n            }\n\n            GUI.SetNextControlName(searchBarName);\n            Rect rect = GUILayoutUtility.GetRect(0, EditorGUILayout.kLabelFloatMaxW * 1.5f, EditorGUI.kSingleLineHeight,\n                EditorGUI.kSingleLineHeight, EditorStyles.toolbarSearchField, GUILayout.MinWidth(60),\n                GUILayout.MaxWidth(300));\n            var filteringText = EditorGUI.ToolbarSearchField(rect, searchText, false);\n            if (m_SearchText != filteringText)\n            {\n                SetFilter(filteringText);\n            }\n        }\n\n        internal static string StacktraceWithHyperlinks(string stacktraceText, int callstackTextStart, bool shouldStripCallstack, Mode mode)\n        {\n            StringBuilder textWithHyperlinks = new StringBuilder();\n            textWithHyperlinks.Append(stacktraceText.Substring(0, callstackTextStart));\n            var lines = stacktraceText.Substring(callstackTextStart).Split(new string[] { \"\\n\" }, StringSplitOptions.None);\n\n            if (shouldStripCallstack)\n                lines = StripCallstack(mode, s_GenericMethodSignatureRegex, s_MethodsToHideInCallstack, lines);\n\n            for (int i = 0; i < lines.Length; ++i)\n            {\n                string textBeforeFilePath = \" (at \";\n                int filePathIndex = lines[i].IndexOf(textBeforeFilePath, StringComparison.Ordinal);\n                if (filePathIndex > 0)\n                {\n                    filePathIndex += textBeforeFilePath.Length;\n                    if (lines[i][filePathIndex] != '<') // sometimes no url is given, just an id between <>, we can't do an hyperlink\n                    {\n                        string filePathPart = lines[i].Substring(filePathIndex);\n                        int lineIndex = filePathPart.LastIndexOf(\":\", StringComparison.Ordinal); // LastIndex because the url can contain ':' ex:\"C:\"\n                        if (lineIndex > 0)\n                        {\n                            int endLineIndex = filePathPart.LastIndexOf(\")\", StringComparison.Ordinal); // LastIndex because files or folder in the url can contain ')'\n                            if (endLineIndex > 0)\n                            {\n                                string lineString =\n                                    filePathPart.Substring(lineIndex + 1, (endLineIndex) - (lineIndex + 1));\n                                string filePath = filePathPart.Substring(0, lineIndex);\n\n                                textWithHyperlinks.Append($\"{lines[i].Substring(0, filePathIndex)}<color={EditorGUIUtility.GetHyperlinkColorForSkin()}><link=\\\"href='{filePath}' line='{lineString}'\\\">{filePath}:{lineString}</link></color>)\\n\");\n\n                                continue; // continue to evade the default case\n                            }\n                        }\n                    }\n                }\n                // default case if no hyperlink : we just write the line\n                textWithHyperlinks.Append(lines[i] + \"\\n\");\n            }\n            // Remove the last \\n\n            if (textWithHyperlinks.Length > 0) // textWithHyperlinks always ends with \\n if it is not empty\n                textWithHyperlinks.Remove(textWithHyperlinks.Length - 1, 1);\n\n            return textWithHyperlinks.ToString();\n        }\n\n        internal static string GetCallstackFormattedSignatureFromGenericMethod(Dictionary<MethodInfo, Regex> methodSignatureRegex, MethodInfo method, string line)\n        {\n            if (string.IsNullOrEmpty(line) || method == null || methodSignatureRegex == null)\n                return null;\n\n            var classType = method.DeclaringType;\n            if (classType == null)\n                return null;\n\n            if (!methodSignatureRegex.TryGetValue(method, out Regex regex))\n                return null;\n\n            if (regex == null)\n                return null;\n\n            var match = regex.Match(line);\n            if (!match.Success)\n                return null;\n\n            var parameterStrings = match.Groups[match.Groups.Count - 1].Value.Split(',');\n            var methodParameters = method.GetParameters();\n            if (parameterStrings == null || parameterStrings.Length != methodParameters.Length)\n                return null;\n\n            var dict = new Dictionary<string, string>();\n            for (int i = 0; i < methodParameters.Length; i++)\n            {\n                var param = methodParameters[i].ParameterType.ToString();\n                parameterStrings[i] = parameterStrings[i].Trim(' ');\n                if (!dict.ContainsKey(param))\n                {\n                    dict.Add(param, parameterStrings[i]);\n                    continue;\n                }\n\n                if (methodParameters[i].ParameterType.IsByRef)\n                {\n                    var trimmedParam = param.Trim('&');\n                    if (!dict.ContainsKey(trimmedParam))\n                    {\n                        dict.Add(trimmedParam, parameterStrings[i].Trim('&'));\n                        continue;\n                    }\n                }\n\n                var nextParam = dict[param];\n                if (!nextParam.Equals(parameterStrings[i], StringComparison.Ordinal))\n                    return null;\n            }\n\n            return match.Value;\n        }\n\n        internal static string GetCallstackFormattedScriptingExceptionSignature(MethodInfo method)\n        {\n            if (method == null)\n                return null;\n\n            var classType = method.DeclaringType;\n            if (classType == null)\n                return null;\n\n            var sb = new StringBuilder(255);\n            var ns = classType.Namespace;\n            if (!string.IsNullOrEmpty(ns))\n            {\n                sb.Append(ns);\n                sb.Append(\".\");\n            }\n\n            sb.Append(classType.Name);\n            sb.Append(\":\");\n            sb.Append(method.Name);\n            sb.Append(\"(\");\n\n            var pi = method.GetParameters();\n            if (pi.Length > 0)\n                sb.Append(pi[0].ParameterType.Name);\n\n            for (int i = 1; i < pi.Length; i++)\n            {\n                sb.Append(\", \");\n                sb.Append(pi[i].ParameterType.Name);\n            }\n\n            sb.Append(\")\");\n            return sb.ToString();\n        }\n\n        internal static string[] StripCallstack(Mode mode, Dictionary<MethodInfo, Regex> methodSignatureRegex, List<MethodInfo> methodsToHideInCallstack, string[] lines)\n        {\n            if (methodsToHideInCallstack == null || methodSignatureRegex == null || lines == null)\n                return lines;\n\n            var strippedLines = lines.ToList();\n            var isException = HasMode((int)mode, Mode.ScriptingException);\n            strippedLines.RemoveAll(line =>\n            {\n                foreach (var method in methodsToHideInCallstack)\n                {\n                    if (!line.Contains(method.Name, StringComparison.Ordinal))\n                        continue;\n\n                    if (method.IsGenericMethod)\n                    {\n                        var genericMethodSignature = GetCallstackFormattedSignatureFromGenericMethod(methodSignatureRegex, method, line);\n                        if (genericMethodSignature == null)\n                            continue;\n\n                        return true;\n                    }\n\n                    var logMethodSignature = LogEntries.GetCallstackFormattedSignatureInternal(method);\n                    if (logMethodSignature != null && line.Contains(logMethodSignature, StringComparison.Ordinal))\n                        return true;\n\n                    if (isException)\n                    {\n                        var exceptionMethodSignature = GetCallstackFormattedScriptingExceptionSignature(method);\n                        if (exceptionMethodSignature != null && line.Contains(exceptionMethodSignature, StringComparison.Ordinal))\n                            return true;\n                    }\n                }\n\n                return false;\n            });\n\n            return strippedLines.ToArray();\n        }\n\n        [UsedImplicitly]\n        public static bool GetConsoleErrorPause()\n        {\n            return HasFlag(ConsoleFlags.ErrorPause);\n        }\n\n        [UsedImplicitly]\n        public static void SetConsoleErrorPause(bool enabled)\n        {\n            SetFlag(ConsoleFlags.ErrorPause, enabled);\n        }\n\n        public struct StackTraceLogTypeData\n        {\n            public LogType logType;\n            public StackTraceLogType stackTraceLogType;\n        }\n\n        public void ToggleLogStackTraces(object userData)\n        {\n            StackTraceLogTypeData data = (StackTraceLogTypeData)userData;\n            PlayerSettings.SetStackTraceLogType(data.logType, data.stackTraceLogType);\n        }\n\n        public void ToggleLogStackTracesForAll(object userData)\n        {\n            foreach (LogType logType in Enum.GetValues(typeof(LogType)))\n                PlayerSettings.SetStackTraceLogType(logType, (StackTraceLogType)userData);\n        }\n\n        public void AddItemsToMenu(GenericMenu menu)\n        {\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Open Player Log\"), false, UnityEditorInternal.InternalEditorUtility.OpenPlayerConsole);\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Open Editor Log\"), false, UnityEditorInternal.InternalEditorUtility.OpenEditorConsole);\n\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Show Timestamp\"), HasFlag(ConsoleFlags.ShowTimestamp), SetTimestamp);\n\n            if (m_DevBuild)\n            {\n                menu.AddItem(Constants.StopForAssert, HasFlag(ConsoleFlags.StopForAssert),\n                    () => { SetFlag(ConsoleFlags.StopForAssert, !HasFlag(ConsoleFlags.StopForAssert)); });\n                menu.AddItem(Constants.StopForError, HasFlag(ConsoleFlags.StopForError),\n                    () => { SetFlag(ConsoleFlags.StopForError, !HasFlag(ConsoleFlags.StopForError)); });\n            }\n\n            for (int i = 1; i <= 10; ++i)\n            {\n                var lineString = i == 1 ? \"Line\" : \"Lines\";\n                menu.AddItem(new GUIContent(string.Format(\"Log Entry/{0} {1}\", i, lineString)), i == Constants.LogStyleLineCount, SetLogLineCount, i);\n            }\n\n            menu.AddItem(Constants.UseMonospaceFont, m_UseMonospaceFont, OnFontButtonValueChange);\n            menu.AddItem(Constants.StripLoggingCallstack, s_StripLoggingCallstack, OnStripLoggingCallstackButtonValueChange);\n\n            AddStackTraceLoggingMenu(menu);\n        }\n\n        internal ListViewState GetListViewState() { return m_ListView; }\n\n        private static void OnFontButtonValueChange()\n        {\n            m_UseMonospaceFont = !m_UseMonospaceFont;\n            SetFlag(ConsoleFlags.UseMonospaceFont, m_UseMonospaceFont);\n            SetFont();\n        }\n\n        private static void SetFont()\n        {\n            var styles = new[]\n            {\n                Constants.LogStyle,\n                Constants.LogSmallStyle,\n                Constants.WarningStyle,\n                Constants.WarningSmallStyle,\n                Constants.ErrorStyle,\n                Constants.ErrorSmallStyle,\n                Constants.MessageStyle,\n            };\n\n            Font font = m_UseMonospaceFont ? m_MonospaceFont : null;\n\n            foreach (var style in styles)\n            {\n                style.font = font;\n                style.fontSize = m_DefaultFontSize;\n            }\n\n            // Make sure to update the fixed height so the entries do not get cropped incorrectly.\n            Constants.UpdateLogStyleFixedHeights();\n        }\n\n        private static void OnStripLoggingCallstackButtonValueChange()\n        {\n            s_StripLoggingCallstack = !s_StripLoggingCallstack;\n            SetFlag(ConsoleFlags.StripLoggingCallstack, s_StripLoggingCallstack);\n        }\n\n        internal static (List<MethodInfo>, Dictionary<MethodInfo, Regex>) InitializeHideInCallstackMethodsCache()\n        {\n            var methods = TypeCache.GetMethodsWithAttribute<HideInCallstackAttribute>();\n            if (methods.Count == 0)\n                return (null, null);\n\n            var methodsToHideInCallstack = new List<MethodInfo>();\n            var genericMethodSignatureRegexes = new Dictionary<MethodInfo, Regex>();\n            foreach (var method in methods)\n            {\n                methodsToHideInCallstack.Add(method);\n                if (method.IsGenericMethod)\n                {\n                    var classType = method.DeclaringType;\n                    if (classType == null)\n                        continue;\n\n                    var ns = classType.Namespace;\n                    var pattern = $\"{(string.IsNullOrEmpty(ns) ? \"\" : $@\"({ns})\\.\")}(\" + classType.Name +\n                                  @\")\\:(\" + method.Name + @\")([^\\(]*)\\s*\\(([^\\)]+)\\)\";\n                    var regex = new Regex(pattern, RegexOptions.Compiled);\n                    if (!genericMethodSignatureRegexes.TryAdd(method, regex))\n                        continue;\n                }\n            }\n\n            return (methodsToHideInCallstack, genericMethodSignatureRegexes);\n        }\n\n        private void SetTimestamp()\n        {\n            SetFlag(ConsoleFlags.ShowTimestamp, !HasFlag(ConsoleFlags.ShowTimestamp));\n        }\n\n        private void SetLogLineCount(object obj)\n        {\n            int count = (int)obj;\n            EditorPrefs.SetInt(\"ConsoleWindowLogLineCount\", count);\n            Constants.LogStyleLineCount = count;\n\n            UpdateListView();\n        }\n\n        private void AddStackTraceLoggingMenu(GenericMenu menu)\n        {\n            // TODO: Maybe remove this, because it basically duplicates UI in PlayerSettings\n            foreach (LogType logType in Enum.GetValues(typeof(LogType)))\n            {\n                foreach (StackTraceLogType stackTraceLogType in Enum.GetValues(typeof(StackTraceLogType)))\n                {\n                    StackTraceLogTypeData data;\n                    data.logType = logType;\n                    data.stackTraceLogType = stackTraceLogType;\n\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Stack Trace Logging/\" + logType + \"/\" + stackTraceLogType), PlayerSettings.GetStackTraceLogType(logType) == stackTraceLogType,\n                        ToggleLogStackTraces, data);\n                }\n            }\n\n            int stackTraceLogTypeForAll = (int)PlayerSettings.GetStackTraceLogType(LogType.Log);\n            foreach (LogType logType in Enum.GetValues(typeof(LogType)))\n            {\n                if (PlayerSettings.GetStackTraceLogType(logType) != (StackTraceLogType)stackTraceLogTypeForAll)\n                {\n                    stackTraceLogTypeForAll = -1;\n                    break;\n                }\n            }\n\n            foreach (StackTraceLogType stackTraceLogType in Enum.GetValues(typeof(StackTraceLogType)))\n            {\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Stack Trace Logging/All/\" + stackTraceLogType), (StackTraceLogType)stackTraceLogTypeForAll == stackTraceLogType,\n                    ToggleLogStackTracesForAll, stackTraceLogType);\n            }\n        }\n\n        internal static void ClearConsoleOnRecompile()\n        {\n            //After building a player, there's a recompilation happening as well\n            //And in order not to lose the log entries, we need to skip clearing the console one time\n            if (BuildPipeline.isBuildingPlayer)\n            {\n                m_ShouldSkipClearingConsoleAfterBuild = true;\n            }\n\n            // During build process, there are multiple compilation events that can trigger console clearing\n            // We don't want to lose the log entries during build process so we re-enable the flag only when editor is not building\n            // For clearing on build we have a separate option\n            if (HasFlag(ConsoleFlags.ClearOnRecompile) && !BuildPipeline.isBuildingPlayer)\n            {\n                if (!m_ShouldSkipClearingConsoleAfterBuild)\n                {\n                    LogEntries.Clear();\n                }\n                else\n                {\n                    m_ShouldSkipClearingConsoleAfterBuild = false;\n                }\n            }\n\n        }\n\n        private void SetFilter(string filteringText)\n        {\n            m_RestoreLatestSelection = String.IsNullOrEmpty(filteringText) && !String.IsNullOrEmpty(m_SearchText) && m_LastActiveEntryIndex != -1;\n            if (filteringText == null)\n            {\n                m_SearchText = \"\";\n                LogEntries.SetFilteringText(\"\");\n            }\n            else\n            {\n                m_ConsoleSearchNoResultMsg = $\"No results for \\\"{filteringText}\\\"\";\n                m_SearchText = filteringText;\n                LogEntries.SetFilteringText(filteringText); // Reset the active entry when we change the filtering text\n            }\n\n            if (m_RestoreLatestSelection)\n            {\n                RestoreLastActiveEntry();\n            }\n            else\n            {\n                // if we have an active selection before domain reload, we need to restore it. So it shouldn't set active entry to null.\n                if (m_LastActiveEntryIndex == -1)\n                {\n                    SetActiveEntry(null);\n                    DestroyLatestRestoreEntry();\n                }\n            }\n        }\n\n        void RestoreLastActiveEntry()\n        {\n            int rowIndex = LogEntries.GetEntryRowIndex(m_LastActiveEntryIndex);\n            if (rowIndex != -1)\n            {\n                ShowConsoleRow(rowIndex);\n                m_ListView.selectedItems = new bool[rowIndex + 1];\n                m_ListView.selectedItems[rowIndex] = true;\n                SetScrollPosYFromRow(rowIndex);\n            }\n            else\n            {\n                SetActiveEntry(null);\n            }\n        }\n\n        void DestroyLatestRestoreEntry()\n        {\n            m_LastActiveEntryIndex = -1;\n            m_RestoreLatestSelection = false;\n        }\n\n        internal static event EntryDoubleClickedDelegate entryWithManagedCallbackDoubleClicked;\n\n        internal static event Action activeEntryChanged;\n\n        [UsedImplicitly, RequiredByNativeCode]\n        private static void SendEntryDoubleClicked(LogEntry entry)\n        {\n            entryWithManagedCallbackDoubleClicked?.Invoke(entry);\n        }\n\n        [UsedImplicitly] // This method is used by the Visual Scripting project. Please do not delete. Contact @husseink for more information.\n        internal void AddMessageWithDoubleClickCallback(string message, string file, int mode, int instanceID)\n        {\n            var outputEntry = new LogEntry {message = message, file = file, mode = mode, instanceID = instanceID};\n            LogEntries.AddMessageWithDoubleClickCallback(outputEntry);\n        }\n\n        [UsedImplicitly]\n        internal static void AddMessages(NativeArray<LogEntryStruct> messages)\n        {\n            unsafe\n            {\n                LogEntries.AddMessagesImpl(messages.GetUnsafeReadOnlyPtr(), messages.Length);\n            }\n        }\n\n        [UsedImplicitly]\n        internal static void AddMessage(ref LogEntryStruct message)\n        {\n            unsafe\n            {\n                fixed (void* ptr = &message)\n                {\n                    LogEntries.AddMessagesImpl(ptr, 1);\n                }\n            }\n        }\n    }\n\n    internal struct GettingLogEntriesScope : IDisposable\n    {\n        private bool m_Disposed;\n\n        public GettingLogEntriesScope(ListViewState listView)\n        {\n            m_Disposed = false;\n            listView.totalRows = LogEntries.StartGettingEntries();\n        }\n\n        public void Dispose()\n        {\n            if (m_Disposed)\n                return;\n            LogEntries.EndGettingEntries();\n            m_Disposed = true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ConsoleWindowUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor\n{\n    public static class ConsoleWindowUtility\n    {\n        public static event Action consoleLogsChanged;\n\n        public static void GetConsoleLogCounts(out int error, out int warn, out int log)\n        {\n            int outError = 0;\n            int outWarn = 0;\n            int outLog = 0;\n\n            LogEntries.GetCountsByType(ref outError, ref outWarn, ref outLog);\n\n            error = outError;\n            warn = outWarn;\n            log = outLog;\n        }\n\n        internal static void Internal_CallLogsHaveChanged()\n        {\n            consoleLogsChanged?.Invoke();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ContainerWindow.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    // How ContainerWindows are visualized. Used with ContainerWindow.Show\n    [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n    internal enum ShowMode\n    {\n        // Show as a normal window with max, min & close buttons.\n        NormalWindow = 0,\n        // Used for a popup menu. On mac this means light shadow and no titlebar.\n        PopupMenu = 1,\n        // Utility window - floats above the app. Disappears when app loses focus.\n        Utility = 2,\n        // Window has no shadow or decorations. Used internally for dragging stuff around.\n        NoShadow = 3,\n        // The Unity main window. On mac, this is the same as NormalWindow, except window doesn't have a close button.\n        MainWindow = 4,\n        // Aux windows. The ones that close the moment you move the mouse out of them.\n        AuxWindow = 5,\n        // Like PopupMenu, but without keyboard focus\n        Tooltip = 6,\n        // Modal Utility window\n        ModalUtility = 7,\n    }\n\n    //[StaticAccessor(\"ContainerWindowBindings\", StaticAccessorType.DoubleColon)]\n    [NativeHeader(\"Editor/Src/Windowing/ContainerWindow.bindings.h\")]\n    internal partial class ContainerWindow\n    {\n        private const string k_ScriptingPrefix = \"ContainerWindowBindings::\";\n\n        extern Rect Internal_Position\n        {\n            [FreeFunction(k_ScriptingPrefix + \"GetPosition\", HasExplicitThis = true)] get;\n            [FreeFunction(k_ScriptingPrefix + \"SetPosition\", HasExplicitThis = true)] set;\n        }\n\n        [FreeFunction(k_ScriptingPrefix + \"SetFreeze\", HasExplicitThis = true)]\n        public extern void SetFreeze(bool freeze);\n        public extern bool maximized {[FreeFunction(k_ScriptingPrefix + \"IsWindowMaximized\", HasExplicitThis = true)] get; }\n\n        [FreeFunction(k_ScriptingPrefix + \"SetAlpha\", HasExplicitThis = true)]\n        public extern void SetAlpha(float alpha);\n\n        // Used by invisible \"under the mouse\" window of the eye dropper.\n        [FreeFunction(k_ScriptingPrefix + \"SetInvisible\", HasExplicitThis = true)]\n        public extern void SetInvisible();\n\n        [FreeFunction(k_ScriptingPrefix + \"IsZoomed\", HasExplicitThis = true)]\n        public extern bool IsZoomed();\n\n        [FreeFunction(k_ScriptingPrefix + \"DisplayAllViews\", HasExplicitThis = true)]\n        public extern void DisplayAllViews();\n\n        [FreeFunction(k_ScriptingPrefix + \"Minimize\", HasExplicitThis = true)]\n        public extern void Minimize();\n\n        [FreeFunction(k_ScriptingPrefix + \"ToggleMaximize\", HasExplicitThis = true)]\n        public extern void ToggleMaximize();\n\n        [FreeFunction(k_ScriptingPrefix + \"MoveInFrontOf\", HasExplicitThis = true)]\n        public extern void MoveInFrontOf(ContainerWindow other);\n\n        [FreeFunction(k_ScriptingPrefix + \"MoveBehindOf\", HasExplicitThis = true)]\n        public extern void MoveBehindOf(ContainerWindow other);\n\n        [FreeFunction(k_ScriptingPrefix + \"SendCaptionEvent\", HasExplicitThis = true)]\n        public extern void SendCaptionEvent(bool mouseDown);\n\n        [FreeFunction(k_ScriptingPrefix + \"Internal_Destroy\", HasExplicitThis = true)]\n        public extern void Internal_Destroy();\n\n        [FreeFunction(k_ScriptingPrefix + \"Internal_SetMinMaxSizes\", HasExplicitThis = true)]\n        private extern void Internal_SetMinMaxSizes(Vector2 minSize, Vector2 maxSize);\n\n        [FreeFunction(k_ScriptingPrefix + \"Internal_Show\", HasExplicitThis = true, ThrowsException = true)]\n        private extern void Internal_Show(Rect r, int showMode, Vector2 minSize, Vector2 maxSize);\n\n        [FreeFunction(k_ScriptingPrefix + \"Internal_BringLiveAfterCreation\", HasExplicitThis = true)]\n        private extern void Internal_BringLiveAfterCreation(bool displayImmediately, bool setFocus, bool showMaximized);\n\n        [FreeFunction(k_ScriptingPrefix + \"Internal_SetTitle\", HasExplicitThis = true)]\n        private extern void Internal_SetTitle(string title);\n\n        [FreeFunction(k_ScriptingPrefix + \"Internal_SetHasUnsavedChanges\", HasExplicitThis = true)]\n        private extern void Internal_SetHasUnsavedChanges(bool hasUnsavedChanges);\n\n        [FreeFunction(k_ScriptingPrefix + \"SetBackgroundColor\", HasExplicitThis = true)]\n        private extern void SetBackgroundColor(Color color);\n\n        [FreeFunction(k_ScriptingPrefix + \"Internal_GetTopleftScreenPosition\", HasExplicitThis = true)]\n        private extern Vector2 Internal_GetTopleftScreenPosition();\n\n        // Disables any repaints until freeze is set to false again.\n        [FreeFunction(k_ScriptingPrefix + \"SetFreezeDisplay\")]\n        public static extern void SetFreezeDisplay(bool freeze);\n\n        [FreeFunction(k_ScriptingPrefix + \"GetOrderedWindowList\")]\n        internal static extern void GetOrderedWindowList();\n\n        [FreeFunction(k_ScriptingPrefix + \"FitRectToMouseScreen\")]\n        internal static extern Rect FitRectToMouseScreen(Rect rect, bool forceCompletelyVisible, ContainerWindow windowForBorderCalculation);\n\n        [FreeFunction(k_ScriptingPrefix + \"FitRectToScreen\")]\n        internal static extern Rect FitRectToScreen(Rect rect, Vector2 uiPositionToFindScreen, bool forceCompletelyVisible, ContainerWindow windowForBorderCalculation);\n\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ContainerWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.StyleSheets;\nusing System.Runtime.InteropServices;\nusing System.Collections.Generic;\nusing System;\nusing System.Text;\nusing UnityEngine.Pool;\nusing UnityEngine.Scripting;\nusing UnityEditorInternal;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [StructLayout(LayoutKind.Sequential)]\n    [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n    internal partial class ContainerWindow : ScriptableObject\n    {\n        [SerializeField] MonoReloadableIntPtr m_WindowPtr;\n        [SerializeField] Rect m_PixelRect;\n        [SerializeField] int m_ShowMode;\n        [SerializeField] string m_Title = \"\";\n\n        [SerializeField, UnityEngine.Serialization.FormerlySerializedAs(\"m_MainView\")] View m_RootView;\n        [SerializeField] Vector2 m_MinSize = new Vector2(120, 80);\n        [SerializeField] Vector2 m_MaxSize = new Vector2(8192, 8192);\n        [SerializeField] bool m_Maximized;\n\n        static readonly bool k_IsMultiplayerClone = Array.Exists(Environment.GetCommandLineArgs(), arg => arg == \"--virtual-project-clone\");\n\n        internal bool m_DontSaveToLayout = false;\n        private bool m_HasUnsavedChanges = false;\n        private List<EditorWindow> m_UnsavedEditorWindows;\n\n        private int m_ButtonCount;\n        private float m_TitleBarWidth;\n\n        const float kTitleHeight = 24f;\n        internal const float kButtonWidth = 16f, kButtonHeight = 16f;\n\n        static internal bool macEditor => Application.platform == RuntimePlatform.OSXEditor;\n\n        static internal bool s_Modal = false;\n        private static ContainerWindow s_MainWindow;\n\n        static internal ContainerWindow mainWindow { get => s_MainWindow; }\n\n        static readonly string s_ContextMenuID = \"UnityEditor.UIElements.EditorMenuExtensions+ContextMenu\";\n\n        private static class Styles\n        {\n            public static float borderSize => macEditor ? osxBorderSize : winBorderSize;\n            public static float buttonMargin => macEditor ? osxBorderMargin : winBorderMargin;\n\n            private static SVC<float> winBorderSize = new SVC<float>(\"--container-window-buttons-right-margin-win\");\n            private static SVC<float> osxBorderSize = new SVC<float>(\"--container-window-buttons-right-margin-osx\");\n            private static SVC<float> winBorderMargin = new SVC<float>(\"--container-window-button-left-right-margin-win\");\n            private static SVC<float> osxBorderMargin = new SVC<float>(\"--container-window-button-left-right-margin-osx\");\n        }\n        static internal float buttonHorizontalSpace => (kButtonWidth + Styles.buttonMargin * 2f);\n        static internal float buttonStackWidth => Styles.borderSize;\n        public ContainerWindow()\n        {\n            m_PixelRect = new Rect(0, 0, 400, 300);\n            m_UnsavedEditorWindows = new List<EditorWindow>();\n        }\n\n        private static Func<bool> MppmCloseCallback;\n\n        internal void __internalAwake()\n        {\n            hideFlags = HideFlags.DontSave;\n        }\n\n        private void OnDestroy()\n        {\n            Internal_Destroy();\n        }\n\n        // Pixel-position on screen.\n        public Rect position\n        {\n            get => Internal_Position;\n            set\n            {\n                if (!View.IsValidViewRect(value))\n                    throw new ArgumentException($\"Invalid position: {value}\");\n\n                Internal_Position = value;\n            }\n        }\n\n        internal ShowMode showMode => (ShowMode)m_ShowMode;\n\n        private string m_WindowID = null;\n        internal string windowID\n        {\n            get\n            {\n                if (String.IsNullOrEmpty(m_WindowID))\n                    return GetWindowID();\n                return m_WindowID;\n            }\n\n            set\n            {\n                m_WindowID = value;\n            }\n        }\n\n        internal static bool IsPopup(ShowMode mode)\n        {\n            return (ShowMode.PopupMenu == mode);\n        }\n\n        internal bool isPopup => IsPopup((ShowMode)m_ShowMode);\n\n        internal void ShowPopup()\n        {\n            ShowPopupWithMode(ShowMode.PopupMenu, true);\n        }\n\n        internal void ShowTooltip()\n        {\n            ShowPopupWithMode(ShowMode.Tooltip, false);\n        }\n\n        internal void ShowPopupWithMode(ShowMode mode, bool giveFocus)\n        {\n            try\n            {\n                if (mode == ShowMode.MainWindow)\n                    throw new ArgumentException(\"Cannot create more than one main window.\");\n\n                m_ShowMode = (int)mode;\n                Internal_Show(m_PixelRect, m_ShowMode, m_MinSize, m_MaxSize);\n                if (m_RootView)\n                    m_RootView.SetWindowRecurse(this);\n                Internal_SetTitle(m_Title);\n                Save();\n\n                // System windows that come from the OS (like a context menu from search) need theming\n                SetBackgroundColor(skinBackgroundColor);\n\n                //  only set focus if mode is a popupMenu.\n                Internal_BringLiveAfterCreation(true, giveFocus, false);\n\n                // Fit window to screen - needs to be done after bringing the window live\n                position = FitRectToScreen(m_PixelRect, m_PixelRect.center, true, this);\n                rootView.position = new Rect(0, 0, GUIUtility.RoundToPixelGrid(m_PixelRect.width), GUIUtility.RoundToPixelGrid(m_PixelRect.height));\n                rootView.Reflow();\n            }\n            catch\n            {\n                DestroyImmediate(this, true);\n                throw;\n            }\n        }\n\n        private static readonly Color lightSkinColor = new Color(0.941f, 0.941f, 0.941f, 1.0f);\n        private static readonly Color darkSkinColor = new Color(0.078f, 0.0784f, 0.0784f, 1.0f);\n        static Color skinBackgroundColor => EditorGUIUtility.isProSkin ? darkSkinColor : lightSkinColor;\n\n        // Show the editor window.\n        public void Show(ShowMode showMode, bool loadPosition, bool displayImmediately, bool setFocus)\n        {\n            try\n            {\n                if (showMode == ShowMode.MainWindow && s_MainWindow && s_MainWindow != this)\n                    throw new InvalidOperationException(\"Trying to create a second main window from layout when one already exists.\");\n\n                bool useMousePos = showMode == ShowMode.AuxWindow;\n                if (showMode == ShowMode.AuxWindow)\n                    showMode = ShowMode.Utility;\n\n                if (showMode == ShowMode.Utility\n                    || showMode == ShowMode.ModalUtility\n                    || showMode == ShowMode.AuxWindow\n                    || IsPopup(showMode))\n                    m_DontSaveToLayout = true;\n\n                m_ShowMode = (int)showMode;\n\n                // Load previous position/size\n                if (!isPopup)\n                    Load(loadPosition);\n                if (useMousePos)\n                    LoadInCurrentMousePosition();\n\n                var initialMaximizedState = m_Maximized;\n\n                Internal_Show(m_PixelRect, m_ShowMode, m_MinSize, m_MaxSize);\n\n                // Tell the main view its now in this window (quick hack to get platform-specific code to move its views to the right window)\n                if (m_RootView)\n                    m_RootView.SetWindowRecurse(this);\n\n                Internal_SetTitle(m_Title);\n\n                SetBackgroundColor(skinBackgroundColor);\n\n                Internal_BringLiveAfterCreation(displayImmediately, setFocus, initialMaximizedState);\n\n                // Window could be killed by now in user callbacks...\n                if (!this)\n                    return;\n\n                if (showMode == ShowMode.MainWindow)\n                    s_MainWindow = this;\n\n                // Fit window to screen - needs to be done after bringing the window live\n                FitWindowToScreen(useMousePos);\n\n                rootView.Reflow();\n\n                // save position right away\n                Save();\n\n                // Restore the initial maximized state since Internal_BringLiveAfterCreation might not be reflected right away and Save() might alter it.\n                m_Maximized = initialMaximizedState;\n            }\n            catch\n            {\n                DestroyImmediate(this, true);\n                throw;\n            }\n        }\n\n        internal void FitWindowToScreen(bool useMousePos)\n        {\n            if (useMousePos)\n                position = FitRectToMouseScreen(m_PixelRect, true, this);\n            else\n                position = FitRectToScreen(m_PixelRect, m_PixelRect.center, true, this);\n\n            if (rootView)\n                rootView.position = new Rect(0, 0, GUIUtility.RoundToPixelGrid(m_PixelRect.width), GUIUtility.RoundToPixelGrid(m_PixelRect.height));\n        }\n\n        public void OnEnable()\n        {\n            if (m_RootView)\n                m_RootView.Initialize(this);\n            SetBackgroundColor(skinBackgroundColor);\n        }\n\n        public void SetMinMaxSizes(Vector2 min, Vector2 max)\n        {\n            if (!View.IsValidViewSize(min))\n                throw new ArgumentException($\"Invalid minimum size: {min}\");\n\n            if (!View.IsValidViewSize(max))\n                throw new ArgumentException($\"Invalid maximum size: {max}\");\n\n            m_MinSize = min;\n            m_MaxSize = max;\n            Rect r = position;\n            Rect r2 = r;\n            r2.width = Mathf.Clamp(r.width, min.x, max.x);\n            r2.height = Mathf.Clamp(r.height, min.y, max.y);\n            if (r2.width != r.width || r2.height != r.height)\n                position = r2;\n            Internal_SetMinMaxSizes(min, max);\n        }\n\n        static internal bool CanCloseAll(bool includeMainWindow)\n        {\n            using (var pooledObject = ListPool<EditorWindow>.Get(out List<EditorWindow> unsaved))\n            {\n                foreach (var window in windows)\n                {\n                    if (includeMainWindow || window.showMode != ShowMode.MainWindow)\n                    {\n                        unsaved.AddRange(window.m_UnsavedEditorWindows);\n                    }\n                }\n\n                if (unsaved.Count > 0)\n                    return AskToClose(unsaved);\n\n                return true;\n            }\n        }\n\n        private bool CanClose()\n        {\n            if (Application.isHumanControllingUs && hasUnsavedChanges)\n            {\n                return AskToClose(m_UnsavedEditorWindows);\n            }\n            if (Application.isHumanControllingUs && IsMultiplayerClone())\n                return MultiplayerCloneClose();\n\n\n            return true;\n        }\n\n        internal static bool CanClose(EditorWindow dockedTab)\n        {\n            if (Application.isHumanControllingUs && dockedTab.hasUnsavedChanges)\n            {\n                var unsaved = new List<EditorWindow>() { dockedTab };\n                return AskToClose(unsaved);\n            }\n\n            return true;\n        }\n\n        internal bool CanCloseAllExcept(EditorWindow editorWindow)\n        {\n            if (!Application.isHumanControllingUs)\n                return true;\n\n            using (var pooledObject = ListPool<EditorWindow>.Get(out List<EditorWindow> unsaved))\n            {\n                foreach (var w in m_UnsavedEditorWindows)\n                {\n                    if (w != editorWindow)\n                        unsaved.Add(w);\n                }\n\n                if (unsaved.Count > 0)\n                    return AskToClose(unsaved);\n            }\n\n            return true;\n        }\n\n        private static bool MultiplayerCloneClose()\n        {\n            if (MppmCloseCallback != null)\n                return MppmCloseCallback.Invoke();\n            return true;\n        }\n\n        internal static void SetMppmCanCloseCallback(Func<bool> mppmCanCloseCallback )\n        {\n            MppmCloseCallback = mppmCanCloseCallback;\n        }\n\n        private static bool AskToClose(List<EditorWindow> allUnsaved)\n        {\n            Debug.Assert(Application.isHumanControllingUs && allUnsaved.Count > 0);\n\n            const int kSave = 0;\n            const int kCancel = 1;\n            const int kDiscard = 2;\n\n            int option = 1; // Cancel\n\n            if (allUnsaved.Count == 1)\n            {\n                var title = allUnsaved[0].titleContent.text;\n\n                option = EditorUtility.DisplayDialogComplex((string.IsNullOrEmpty(title) ? \"\" : (title + \" - \")) + L10n.Tr(\"Unsaved Changes Detected\"),\n                    allUnsaved[0].saveChangesMessage,\n                    L10n.Tr(\"Save\"),\n                    L10n.Tr(\"Cancel\"),\n                    L10n.Tr(\"Discard\"));\n            }\n            else\n            {\n                var savedChangesBuilder = new StringBuilder();\n\n                int last = allUnsaved.Count - 1;\n                for (int i = 0; i < last; ++i)\n                {\n                    savedChangesBuilder.Append(allUnsaved[i].saveChangesMessage);\n                    savedChangesBuilder.Append('\\n');\n                }\n                savedChangesBuilder.Append(allUnsaved[last]);\n\n                option = EditorUtility.DisplayDialogComplex(L10n.Tr(\"Unsaved Changes Detected\"),\n                    savedChangesBuilder.ToString(),\n                    L10n.Tr(\"Save All\"),\n                    L10n.Tr(\"Cancel\"),\n                    L10n.Tr(\"Discard All\"));\n            }\n\n            try\n            {\n                switch (option)\n                {\n                    case kSave:\n                        bool areAllSaved = true;\n                        foreach (var w in allUnsaved)\n                        {\n                            w.SaveChanges();\n                            areAllSaved &= !w.hasUnsavedChanges;\n                        }\n                        return areAllSaved;\n                    case kDiscard:\n                        foreach (var w in allUnsaved)\n                            w.DiscardChanges();\n                        break;\n                    case kCancel:\n                        break;\n                    default:\n                        Debug.LogError(\"Unrecognized option.\");\n                        break;\n                }\n\n                return option != kCancel;\n            }\n            catch (Exception ex)\n            {\n                EditorUtility.DisplayDialog(L10n.Tr(\"Save Changes Failed\"),\n                    ex.Message,\n                    L10n.Tr(\"OK\"));\n\n                return false;\n            }\n        }\n\n        // Closes the Window _without prompting_\n        public void Close()\n        {\n            // Because this is a UnityObject, DestroyImmediate _will_ nullify the this pointer.\n            // This can guard against double-close\n            if (this == null)\n                return;\n\n            Save();\n            if (InternalEditorUtility.isHumanControllingUs)\n                EditorWindow.UpdateWindowMenuListing();\n\n            if (s_MainWindow == this)\n                s_MainWindow = null;\n\n            if (m_RootView)\n            {\n                DestroyImmediate(m_RootView, true);\n                m_RootView = null;\n            }\n\n            DestroyImmediate(this, true);\n        }\n\n        [RequiredByNativeCode]\n        private void RequestCloseSentByNativeCode()\n        {\n            if (CanClose())\n            {\n                Close();\n            }\n        }\n\n        [RequiredByNativeCode]\n        internal bool IsMultiplayerClone()\n        {\n            return k_IsMultiplayerClone;\n        }\n\n        private static List<EditorWindow> FindUnsavedChanges(View view)\n        {\n            var unsavedChanges = new List<EditorWindow>();\n\n            foreach (View v in view.allChildren)\n            {\n                switch (v)\n                {\n                    case DockArea dockArea:\n                        foreach (var windowClose in dockArea.m_Panes)\n                            if (windowClose.hasUnsavedChanges)\n                                unsavedChanges.Add(windowClose);\n                        break;\n                    case HostView hostView:\n                        if (hostView.actualView?.hasUnsavedChanges ?? false)\n                            unsavedChanges.Add(hostView.actualView);\n                        break;\n                    default:\n                        break;\n                }\n            }\n\n            return unsavedChanges;\n        }\n\n        public void UnsavedStateChanged()\n        {\n            m_UnsavedEditorWindows = FindUnsavedChanges(rootView);\n            hasUnsavedChanges = m_UnsavedEditorWindows.Count > 0;\n        }\n\n        internal bool IsNotDocked()\n        {\n            return ( // hallelujah\n\n                (m_ShowMode == (int)ShowMode.Utility || m_ShowMode == (int)ShowMode.AuxWindow || m_ShowMode == (int)ShowMode.PopupMenu) ||\n                (m_ShowMode == (int)ShowMode.MainWindow && rootView is HostView) ||\n                (rootView is SplitView &&\n                    rootView.children.Length == 1 &&\n                    rootView.children[0] is DockArea &&\n                    ((DockArea)rootView.children[0]).m_Panes.Count == 1)\n            );\n        }\n\n        internal string GetWindowID()\n        {\n            if (!rootView)\n                return string.Empty;\n\n            HostView v = rootView as HostView;\n\n            if (v == null && rootView is SplitView && rootView.children.Length > 0)\n                v = rootView.children[0] as HostView;\n\n            if (v == null || !v.actualView)\n                return rootView.GetType().ToString();\n\n            if (rootView.children.Length > 0)\n            {\n                DockArea dockArea = null;\n\n                foreach (var child in rootView.children)\n                {\n                    if (child is DockArea)\n                    {\n                        dockArea = (DockArea)child;\n                        break;\n                    }\n                }\n\n                if (dockArea && dockArea.m_Panes.Count > 0)\n                {\n                    return (m_ShowMode == (int)ShowMode.Utility || m_ShowMode == (int)ShowMode.AuxWindow) ? v.actualView.GetType().ToString()\n                        : dockArea.m_Panes[0].GetType().ToString();\n                }\n            }\n\n            return v.actualView.GetType().ToString();\n        }\n\n        public bool IsMainWindow()\n        {\n            return m_ShowMode == (int)ShowMode.MainWindow && m_DontSaveToLayout == false;\n        }\n\n        internal void SaveGeometry()\n        {\n            string ID = windowID;\n            if (string.IsNullOrEmpty(ID) || IsValidContextMenu())\n                return;\n\n            // save position/size\n            EditorPrefs.SetFloat(ID + \"x\", m_PixelRect.x);\n            EditorPrefs.SetFloat(ID + \"y\", m_PixelRect.y);\n            EditorPrefs.SetFloat(ID + \"w\", m_PixelRect.width);\n            EditorPrefs.SetFloat(ID + \"h\", m_PixelRect.height);\n            EditorPrefs.SetBool(ID + \"z\", m_Maximized);\n        }\n\n        public void Save()\n        {\n            m_Maximized = IsZoomed();\n            SaveGeometry();\n        }\n\n        bool IsValidContextMenu()\n        {\n            return string.Equals(s_ContextMenuID, windowID);\n        }\n\n        internal void LoadGeometry(bool loadPosition)\n        {\n            string ID = windowID;\n            // Check for invalid ID and validate context menu to avoid soft locks on invalid positions UW-105\n            if (string.IsNullOrEmpty(ID) || IsValidContextMenu())\n                return;\n\n            // get position/size\n            Rect p = m_PixelRect;\n            if (loadPosition)\n            {\n                // Use the current mouse position as the 'default' position if we cant\n                // load the position from our saved preferences. This allows the newly created\n                // window to pop up on the same monitor as the main window when a saved position\n                // couldn't be loaded rather than defaulting to monitor '0'\n                Vector2 mousePos = Editor.GetCurrentMousePosition();\n\n                p.x = EditorPrefs.GetFloat(ID + \"x\", mousePos.x);\n                p.y = EditorPrefs.GetFloat(ID + \"y\", mousePos.y);\n                p.width = EditorPrefs.GetFloat(ID + \"w\", m_PixelRect.width);\n                p.height = EditorPrefs.GetFloat(ID + \"h\", m_PixelRect.height);\n                m_Maximized = EditorPrefs.GetBool(ID + \"z\");\n            }\n            p.width = Mathf.Min(Mathf.Max(p.width, m_MinSize.x), m_MaxSize.x);\n            p.height = Mathf.Min(Mathf.Max(p.height, m_MinSize.y), m_MaxSize.y);\n            m_PixelRect = p;\n        }\n\n        internal void LoadInCurrentMousePosition()\n        {\n            Vector2 mousePos = Editor.GetCurrentMousePosition();\n\n            Rect p = m_PixelRect;\n            p.x = mousePos.x;\n            p.y = mousePos.y;\n            m_PixelRect = p;\n        }\n\n        private void Load(bool loadPosition)\n        {\n            if (!IsMainWindow() && IsNotDocked())\n                LoadGeometry(loadPosition);\n        }\n\n        internal void OnResize()\n        {\n            if (rootView == null)\n                return;\n\n            // Depending on the context, GUIUtility.pixelsPerPoint isn't reliable at this point, so we must not round.\n            // Anyway the backend is responsible of providing a window size that is aligned with the pixel grid, so it\n            // shouldn't be necessary. In the past position.width and position.height were rounded. When moving a window\n            // from a monitor that had a given scaling to another monitor with a different scaling, this could cause the\n            // original pixelsPerPoint to be used. As a result, black borders could appear for the first frame.\n            rootView.position = new Rect(0, 0, position.width, position.height);\n\n            // save position\n            Save();\n        }\n\n        // The title of the window, including unsaved changes markings, if any.\n        public string displayedTitle { get; private set; }\n\n        private void UpdateTitle()\n        {\n            displayedTitle = hasUnsavedChanges ? m_Title + \"*\" : m_Title;\n            Internal_SetTitle(displayedTitle);\n        }\n\n        // The title of the window\n        public string title\n        {\n            get\n            {\n                return m_Title;\n            }\n            set\n            {\n                if (m_Title != value)\n                {\n                    m_Title = value;\n                    UpdateTitle();\n                }\n            }\n        }\n\n        public bool hasUnsavedChanges\n        {\n            get\n            {\n                return m_HasUnsavedChanges;\n            }\n            private set\n            {\n                if (m_HasUnsavedChanges != value)\n                {\n                    m_HasUnsavedChanges = value;\n                    Internal_SetHasUnsavedChanges(value);\n                    UpdateTitle();\n                }\n            }\n        }\n\n        // Array of all visible ContainerWindows, from frontmost to last\n        static List<ContainerWindow> s_AllWindows = new List<ContainerWindow>();\n        public static ContainerWindow[] windows\n        {\n            get\n            {\n                s_AllWindows.Clear();\n                GetOrderedWindowList();\n                return s_AllWindows.ToArray();\n            }\n        }\n\n        internal void AddToWindowList()\n        {\n            s_AllWindows.Add(this);\n        }\n\n        // TODO: Handle title bar height and other things\n        public Vector2 WindowToScreenPoint(Vector2 windowPoint)\n        {\n            Vector2 hmm = Internal_GetTopleftScreenPosition();\n            return windowPoint + hmm;// + new Vector2 (position.x, position.y) + hmm;\n        }\n\n        public View rootView\n        {\n            get { return m_RootView; }\n            set\n            {\n                m_RootView = value;\n                m_RootView.SetWindowRecurse(this);\n                m_RootView.position = new Rect(0, 0, Mathf.Ceil(position.width), Mathf.Ceil(position.height));\n                m_MinSize = value.minSize;\n                m_MaxSize = value.maxSize;\n            }\n        }\n\n        public SplitView rootSplitView\n        {\n            get\n            {\n                if (m_ShowMode == (int)ShowMode.MainWindow && rootView && rootView.children.Length == 3)\n                    return rootView.children[1] as SplitView;\n                if (m_ShowMode == (int)ShowMode.MainWindow && rootView && rootView.children.Length == 2)\n                    return rootView.children[0] as SplitView;\n\n                foreach (var c in rootView.children)\n                {\n                    var sv = c as SplitView;\n                    if (sv)\n                        return sv;\n                }\n\n                return rootView as SplitView;\n            }\n        }\n\n        internal string DebugHierarchy()\n        {\n            return rootView.DebugHierarchy(0);\n        }\n\n        internal Rect GetDropDownRect(Rect buttonRect, Vector2 minSize, Vector2 maxSize, PopupLocation[] locationPriorityOrder)\n        {\n            return PopupLocationHelper.GetDropDownRect(buttonRect, minSize, maxSize, this, locationPriorityOrder);\n        }\n\n        internal Rect GetDropDownRect(Rect buttonRect, Vector2 minSize, Vector2 maxSize)\n        {\n            return PopupLocationHelper.GetDropDownRect(buttonRect, minSize, maxSize, this);\n        }\n    }\n} //namespace\n"
  },
  {
    "path": "Editor/Mono/ContextMenuUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.EditorTools;\nusing UnityEditor.Snap;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing UnityEditor.UIElements;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor.Actions\n{\n    public static class ContextMenuUtility\n    {\n        static void AddAction(DropdownMenu menu, string path, Action action, bool active = true)\n        {\n            menu.AppendAction(path, _ => action?.Invoke(),\n                _ => active ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);\n        }\n\n        public static void AddMenuItem(DropdownMenu menu, string menuItemPath, string contextMenuPath = \"\")\n        {\n            AddMenuItemWithContext(menu, Selection.objects, menuItemPath, contextMenuPath);\n        }\n\n        public static void AddMenuItemWithContext(DropdownMenu menu, IEnumerable<Object> context, string menuItemPath, string contextMenuPath = \"\")\n        {\n            var contextArray = ToArray(context);\n            var enabled = Menu.GetEnabledWithContext(menuItemPath, contextArray);\n            AddMenuItemWithContext(menu, context, enabled, menuItemPath, contextMenuPath);\n        }\n\n        internal static void AddMenuItemWithContext(DropdownMenu menu, IEnumerable<Object> context, bool enabled, string menuItemPath, string contextMenuPath = \"\")\n        {\n            var contextArray = ToArray(context);\n            string shortcut = Menu.GetHotkey(menuItemPath);\n            string path = (string.IsNullOrEmpty(contextMenuPath) ? menuItemPath : contextMenuPath)\n                + (string.IsNullOrEmpty(shortcut) ? \"\" : \" \" + shortcut);\n\n            AddAction(menu, path,\n                () => { EditorApplication.delayCall += () => ExecuteMenuItem(contextArray, menuItemPath); }, enabled);\n        }\n\n        static void ExecuteMenuItem(Object[] context, string menuItemPath)\n        {\n            // Claudia Antoun, 05-16-23, can safely be removed when UW-153 is fixed.\n            if (SceneView.lastActiveSceneView != null)\n                SceneView.lastActiveSceneView.Focus();\n\n            EditorApplication.ExecuteMenuItemWithTemporaryContext(menuItemPath, context);\n        }\n\n        public static void AddMenuItemsForType<T>(DropdownMenu menu, IEnumerable<T> targets) where T : Object\n        {\n            AddMenuItemsForType(menu, typeof(T), targets);\n        }\n\n        public static void AddMenuItemsForType(DropdownMenu menu, Type type, IEnumerable<Object> targets, string submenu = \"\")\n        {\n            var componentName = type.Name;\n            Menu.UpdateContextMenu(ToArray(targets), 0);\n            AddMenuItems(menu, componentName, Menu.GetMenuItems($\"CONTEXT/{componentName}/\", false, true), targets, submenu);\n        }\n\n        static void AddMenuItems(DropdownMenu menu, string componentName, ScriptingMenuItem[] items, IEnumerable<Object> targets, string submenu)\n        {\n            string context = $\"CONTEXT/{componentName}/\";\n            if (!string.IsNullOrEmpty(submenu) && submenu[^1] != '/')\n                submenu += '/';\n\n            int lastItemPriority = -1;\n            foreach (var menuItem in items)\n            {\n                var menuPath = menuItem.path;\n                var newPath = $\"{submenu}{menuPath.Substring(context.Length)}\";\n\n                // Add separator between items with priority differing by over 10 points\n                if (lastItemPriority != -1 && menuItem.priority > lastItemPriority + 10)\n                    menu.AppendSeparator(newPath.Substring(0, newPath.LastIndexOf('/') + 1));\n                lastItemPriority = menuItem.priority;\n\n                if (!menuItem.isSeparator)\n                    AddMenuItemWithContext(menu, targets, menuPath, newPath);\n            }\n        }\n\n        static void AddGameObjectClipboardEntriesTo(DropdownMenu menu)\n        {\n            var isThereGameObjectInSelection = Selection.gameObjects.Length > 0;\n            var isPasteEnabled = CutBoard.CanGameObjectsBePasted() || Unsupported.CanPasteGameObjectsFromPasteboard();\n            AddClipboardEntriesTo(menu, isThereGameObjectInSelection, isThereGameObjectInSelection, isPasteEnabled, isThereGameObjectInSelection, isThereGameObjectInSelection);\n        }\n\n        public static void AddClipboardEntriesTo(DropdownMenu menu)\n        {\n            var isThereGameObjectInSelection = Selection.gameObjects.Length > 0;\n            var isPasteEnabled = GUIUtility.systemCopyBuffer.Length > 0;\n            AddClipboardEntriesTo(menu, isThereGameObjectInSelection, isThereGameObjectInSelection, isPasteEnabled, isThereGameObjectInSelection, isThereGameObjectInSelection);\n        }\n\n        public static void AddClipboardEntriesTo(DropdownMenu menu, bool cutEnabled, bool copyEnabled, bool pasteEnabled, bool duplicateEnabled, bool deleteEnabled)\n        {\n            AddMenuItemWithContext(menu, null, cutEnabled, \"Edit/Cut\", \"Cut\");\n            AddMenuItemWithContext(menu, null, copyEnabled, \"Edit/Copy\", \"Copy\");\n            AddMenuItemWithContext(menu, null, pasteEnabled, \"Edit/Paste\", \"Paste\");\n            AddMenuItemWithContext(menu, null, duplicateEnabled, \"Edit/Duplicate\", \"Duplicate\");\n            AddMenuItemWithContext(menu, null, deleteEnabled, \"Edit/Delete\", \"Delete\");\n        }\n\n        public static void AddComponentEntriesTo(DropdownMenu menu)\n        {\n            var editors = ActiveEditorTracker.sharedTracker.activeEditors;\n            foreach (var editor in editors)\n            {\n                var type = editor.target.GetType();\n                if (type == typeof(GameObject) || type == typeof(Material))\n                    continue;\n\n                Menu.UpdateContextMenu(editor.targets, 0);\n\n                var items = Menu.GetMenuItems($\"CONTEXT/{type.Name}/\", false, true);\n                if (items.Length == 0)\n                    continue;\n\n                AddMenuItems(menu, type.Name, items, editor.targets, type.Name);\n            }\n        }\n\n        public static void AddGameObjectEntriesTo(DropdownMenu menu)\n        {\n            bool hasSelectedGO = Selection.gameObjects.Length > 0;\n            bool hasSelectedExactlyOneGO = Selection.gameObjects.Length == 1;\n            AddGameObjectClipboardEntriesTo(menu);\n\n            menu.AppendSeparator();\n\n            AddMenuItemWithContext(menu, null, \"GameObject/Move To View\", \"Move to View\");\n            AddMenuItemWithContext(menu, null, \"GameObject/Align With View\", \"Align with View\");\n            AddAction(menu, \"Move to Grid Position\", Shortcuts.PushToGrid, hasSelectedGO);\n\n            menu.AppendSeparator();\n\n            AddAction(menu,\n                SceneVisibilityState.isolation ? \"Exit Isolation\" : \"Isolate\",\n                SceneVisibilityManager.ToggleIsolateSelectionShortcut,\n                SceneVisibilityState.isolation || hasSelectedGO);\n\n            menu.AppendSeparator();\n\n            AddMenuItemWithContext(menu, null, \"Component/Add...\", \"Add Component...\");\n            AddMenuItemWithContext(menu, null, \"Assets/Properties...\", \"Properties...\");\n\n            // Prefab menu items that only make sense if a single object is selected.\n            var listOfSceneHierarchyWindows = SceneHierarchyWindow.GetAllSceneHierarchyWindows();\n            if (hasSelectedExactlyOneGO && listOfSceneHierarchyWindows.Count > 0)\n                listOfSceneHierarchyWindows[0].sceneHierarchy?.PopulateDropdownMenuWithPrefabMenuItems(menu);\n\n            // Component entries\n            if (hasSelectedGO)\n            {\n                menu.AppendSeparator();\n                AddComponentEntriesTo(menu);\n            }\n        }\n\n        internal static DropdownMenu CreateActionMenu()\n        {\n            var contextMenu = new DropdownMenu();\n\n            Menu.CreateActionMenuBegin();\n\n            EditorToolManager.activeToolContext.PopulateMenu(contextMenu);\n            AddMenuItemsForType(contextMenu, ToolManager.activeContextType, EditorToolManager.activeToolContext.targets);\n            EditorToolManager.activeTool.PopulateMenu(contextMenu);\n            AddMenuItemsForType(contextMenu, ToolManager.activeToolType, EditorToolManager.activeTool.targets);\n\n            Menu.CreateActionMenuEnd();\n\n            return contextMenu;\n        }\n\n        internal static void ShowActionMenu()\n        {\n            if (Event.current == null)\n                return;\n\n            var dropdownMenu = CreateActionMenu();\n            if (dropdownMenu.MenuItems().Count == 0)\n                AddAction(dropdownMenu, \"No Actions for this Context\", null, false);\n\n#pragma warning disable CS0618 // Type or member is obsolete\n            EditorMenuExtensions.DoDisplayEditorMenuFromImGUI(dropdownMenu, new Rect(Event.current.mousePosition, Vector2.zero));\n#pragma warning restore CS0618 // Type or member is obsolete\n        }\n\n        static T[] ToArray<T>(IEnumerable<T> enumerable) where T : Object\n        {\n            if (enumerable == null)\n                return null;\n\n            if (enumerable is T[] arr)\n                return arr;\n\n            var size = 0;\n            foreach (var item in enumerable)\n                size++;\n\n            T[] items = new T[size];\n            var index = 0;\n            foreach (var item in enumerable)\n            {\n                items[index] = item;\n                index++;\n            }\n\n            return items;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CustomEditorAttributes.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor;\n\ninternal partial class CustomEditorAttributes\n{\n    [RequiredByNativeCode]\n    internal static Type FindCustomEditorType(Object obj, bool multiEdit)\n    {\n        return obj == null ? null : FindCustomEditorTypeByType(obj.GetType(), multiEdit);\n    }\n\n    [RequiredByNativeCode]\n    internal static Type FindCustomEditorTypeByType(Type type, bool multiEdit)\n    {\n        return instance.GetCustomEditorType(type, multiEdit);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CustomEditorAttributes.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics.CodeAnalysis;\nusing System.Linq;\nusing System.Reflection;\nusing JetBrains.Annotations;\nusing Unity.Collections;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    internal partial class CustomEditorAttributes\n    {\n        static CustomEditorAttributes instance => k_Instance.Value;\n\n        static readonly Lazy<CustomEditorAttributes> k_Instance = new(() => new CustomEditorAttributes());\n\n        readonly CustomEditorCache m_Cache = new CustomEditorCache();\n\n        readonly Func<List<MonoEditorType>, Type>[] m_GetEditorWhenSRPEnabled =\n        {\n            FindEditorsByRenderPipeline,\n            FindEditorsOnlyByAttribute,\n            UseNotSupportedOnInspector\n        };\n\n        readonly Func<List<MonoEditorType>, Type>[] m_GetEditorWhenBuiltinEnabled =\n        {\n            FindEditorsOnlyByAttribute,\n            UseNotSupportedOnInspector\n        };\n\n        Func<List<MonoEditorType>, Type>[] m_CurrentGetEditorList => GraphicsSettings.isScriptableRenderPipelineEnabled ? m_GetEditorWhenSRPEnabled : m_GetEditorWhenBuiltinEnabled;\n\n        CustomEditorAttributes()\n        {\n            Initialize();\n        }\n\n        Type GetCustomEditorType(Type type, bool multiEdit)\n        {\n            if (type == null)\n                return null;\n\n            var editor = GetEditor(type, multiEdit, Pass.Regular);\n            return editor ?? GetEditor(type, multiEdit, Pass.Fallback);\n        }\n\n        Type GetEditor(Type type, bool multiEdit, Pass pass)\n        {\n            for (var inspected = type; inspected != null; inspected = inspected.BaseType)\n            {\n                if (!m_Cache.TryGet(inspected, multiEdit, out var foundEditors))\n                    continue;\n\n                var filteredEditors = foundEditors\n                    .Where(e => IsAppropriateEditor(e, type != inspected, pass == Pass.Fallback))\n                    .ToList();\n\n                var inspectorType = FindEditors(filteredEditors);\n                if (inspectorType != null)\n                    return inspectorType;\n            }\n\n            return null;\n        }\n\n        Type FindEditors(List<MonoEditorType> editors)\n        {\n            if (!editors.Any())\n                return null;\n\n            var getEditorActions = m_CurrentGetEditorList;\n            for (int i = 0; i < getEditorActions.Length; i++)\n            {\n                var inspectorType = getEditorActions[i].Invoke(editors);\n                if (inspectorType != null)\n                    return inspectorType;\n            }\n\n            return null;\n        }\n\n        static Type FindEditorsByRenderPipeline(List<MonoEditorType> editors)\n        {\n            Type editorToUse = null;\n            var rpType = GraphicsSettings.currentRenderPipelineAssetType;\n            for (var i = 0; i < editors.Count; i++)\n            {\n                var editor = editors[i];\n                if (editor.supportedRenderPipelineTypes == null)\n                    continue;\n\n                var isEditorSupported = SupportedOnRenderPipelineAttribute.GetSupportedMode(editor.supportedRenderPipelineTypes, rpType);\n                if (isEditorSupported == SupportedOnRenderPipelineAttribute.SupportedMode.Supported)\n                    return editor.inspectorType;\n\n                if (isEditorSupported == SupportedOnRenderPipelineAttribute.SupportedMode.SupportedByBaseClass)\n                    editorToUse = editor.inspectorType;\n            }\n\n            return editorToUse;\n        }\n\n        static Type FindEditorsOnlyByAttribute(List<MonoEditorType> editors)\n        {\n            for (var i = 0; i < editors.Count; i++)\n            {\n                var editor = editors[i];\n                if (editor.supportedRenderPipelineTypes != null)\n                    continue;\n\n                return editor.inspectorType;\n            }\n\n            return null;\n        }\n\n        static Type UseNotSupportedOnInspector(List<MonoEditorType> editors)\n        {\n            if (!editors.Any())\n                return null;\n\n            var allEditorHaveSupportedOn = true;\n            for (var i = 0; i < editors.Count; i++)\n            {\n                var editor = editors[i];\n                if (editor.supportedRenderPipelineTypes == null)\n                    allEditorHaveSupportedOn = false;\n            }\n\n            return allEditorHaveSupportedOn ? typeof(NotSupportedOnRenderPipelineInspector) : null;\n        }\n\n        static bool IsAppropriateEditor(MonoEditorType editor, bool isChildClass, bool isFallbackPass)\n        {\n            if (isChildClass && !editor.editorForChildClasses)\n                // skip if it's a child class and this editor doesn't want to match on children\n                return false;\n\n            //if it is fallback pas we expect every editor to be fallback editor\n            return isFallbackPass == editor.isFallback;\n        }\n\n        internal static void Rebuild()\n        {\n            instance.Initialize();\n        }\n\n        void Initialize()\n        {\n            m_Cache.Clear();\n            var types = TypeCache.GetTypesWithAttribute<CustomEditor>();\n            foreach (var type in types)\n            {\n                var inspectAttr = type.GetCustomAttribute<CustomEditor>(false);\n                if (inspectAttr.m_InspectedType == null)\n                    Debug.Log(\"Can't load custom inspector \" + type.Name + \" because the inspected type is null.\");\n                else if (!type.IsSubclassOf(typeof(Editor)))\n                {\n                    // Suppress a warning on TweakMode, we did this bad in the default project folder\n                    // and it's going to be too hard for customers to figure out how to fix it and also quite pointless.\n                    if (type.FullName == \"TweakMode\" && type.IsEnum &&\n                        inspectAttr.m_InspectedType.FullName == \"BloomAndFlares\")\n                        continue;\n\n                    Debug.LogWarning(\n                        type.Name +\n                        \" uses the CustomEditor attribute but does not inherit from Editor.\\nYou must inherit from Editor. See the Editor class script documentation.\");\n                }\n                else\n                {\n                    var isValid = TryGatherRenderPipelineTypes(type, inspectAttr, out var renderPipelineTypes);\n                    if (!isValid)\n                    {\n                        Debug.LogError($\"Inspector {type.FullName} contains invalid attribute. This inspector will be skipped.\");\n                        continue;\n                    }\n\n                    var monoEditorType = new MonoEditorType(type, renderPipelineTypes, inspectAttr.m_EditorForChildClasses, inspectAttr.isFallback);\n                    m_Cache.Add(type, inspectAttr, monoEditorType);\n                }\n            }\n        }\n\n        [MustUseReturnValue]\n        static bool TryGatherRenderPipelineTypes([DisallowNull] Type type, [DisallowNull] CustomEditor inspectAttr, [NotNullWhen(true)] out Type[] results)\n        {\n            var supportedOnAttribute = type.GetCustomAttribute<SupportedOnRenderPipelineAttribute>(false);\n            if (supportedOnAttribute != null)\n            {\n                if (supportedOnAttribute.renderPipelineTypes == null)\n                {\n                    results = null;\n                    return false;\n                }\n\n                var supportedPipelines = supportedOnAttribute.renderPipelineTypes\n                    .Where(r => r != null)\n                    .Distinct()\n                    .ToArray();\n                if (supportedPipelines.Length > 0)\n                {\n                    results = supportedPipelines;\n                    return true;\n                }\n            }\n\n#pragma warning disable CS0618\n            if (inspectAttr is CustomEditorForRenderPipelineAttribute attr)\n            {\n                results = new[] { attr.renderPipelineType };\n                return true;\n            }\n#pragma warning restore CS0618\n\n            results = null;\n            return true;\n        }\n\n        enum Pass\n        {\n            Regular,\n            Fallback\n        }\n\n        internal readonly struct MonoEditorType\n        {\n            public readonly Type inspectorType;\n            public readonly Type[] supportedRenderPipelineTypes;\n            public readonly bool editorForChildClasses;\n            public readonly bool isFallback;\n\n            public MonoEditorType(Type inspectorType, Type[] supportedRenderPipelineTypes, bool editorForChildClasses, bool isFallback)\n            {\n                this.inspectorType = inspectorType;\n                this.supportedRenderPipelineTypes = supportedRenderPipelineTypes;\n                this.editorForChildClasses = editorForChildClasses;\n                this.isFallback = isFallback;\n            }\n        }\n\n        struct MonoEditorTypeStorage\n        {\n            public List<MonoEditorType> customEditors;\n            public List<MonoEditorType> customEditorsMultiEdition;\n\n            public MonoEditorTypeStorage()\n            {\n                customEditors = new List<MonoEditorType>();\n                customEditorsMultiEdition = new List<MonoEditorType>();\n            }\n        }\n\n        class CustomEditorCache\n        {\n            readonly Dictionary<Type, MonoEditorTypeStorage> m_CustomEditorCache = new();\n            readonly SortUnityTypesFirstComparer m_SortUnityTypesFirstComparer = new();\n\n            internal void Clear()\n            {\n                m_CustomEditorCache.Clear();\n            }\n\n            internal bool TryGet(Type type, bool multiedition, out List<MonoEditorType> editors)\n            {\n                if (m_CustomEditorCache.TryGetValue(type, out var storedEditors))\n                {\n                    editors = multiedition ? storedEditors.customEditorsMultiEdition : storedEditors.customEditors;\n                    return true;\n                }\n\n                if (!type.IsGenericType)\n                {\n                    editors = null;\n                    return false;\n                }\n\n                type = type.GetGenericTypeDefinition();\n                if (m_CustomEditorCache.TryGetValue(type, out storedEditors))\n                {\n                    editors = multiedition ? storedEditors.customEditorsMultiEdition : storedEditors.customEditors;\n                    return true;\n                }\n\n                editors = null;\n                return false;\n            }\n\n            internal void Add(Type type, CustomEditor inspectAttr, MonoEditorType monoEditorType)\n            {\n                var isItExistInCache = m_CustomEditorCache.TryGetValue(inspectAttr.m_InspectedType, out var storage);\n                if (!isItExistInCache)\n                    storage = new MonoEditorTypeStorage();\n\n                storage.customEditors.AddSorted(monoEditorType, m_SortUnityTypesFirstComparer);\n                if (type.GetCustomAttribute<CanEditMultipleObjects>(false) != null)\n                    storage.customEditorsMultiEdition.AddSorted(monoEditorType, m_SortUnityTypesFirstComparer);\n\n                if (!isItExistInCache)\n                    m_CustomEditorCache.Add(inspectAttr.m_InspectedType, storage);\n            }\n\n            struct SortUnityTypesFirstComparer : IComparer<MonoEditorType>\n            {\n                public int Compare(MonoEditorType typeA, MonoEditorType typeB)\n                {\n                    return SortUnityTypesFirst(typeA, typeB);\n                }\n\n                static int SortUnityTypesFirst(MonoEditorType typeA, MonoEditorType typeB)\n                {\n                    var xAssemblyIsUnity = InternalEditorUtility.IsUnityAssembly(typeA.inspectorType);\n                    var yAssemblyIsUnity = InternalEditorUtility.IsUnityAssembly(typeB.inspectorType);\n\n                    if (xAssemblyIsUnity == yAssemblyIsUnity)\n                        return string.CompareOrdinal(typeA.inspectorType.FullName, typeB.inspectorType.FullName);\n                    if (xAssemblyIsUnity)\n                        return 1;\n                    return -1;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CustomInspectorStubs.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditorInternal;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    // Exposed as internal, editor-only, because we only need it do make a custom inspector\n    [NativeClass(null)]\n    [ExcludeFromPreset]\n    internal sealed class AudioManager : ProjectSettingsBase\n    {\n        private AudioManager() {}\n    }\n\n    // Exposed as internal, editor-only, because we only need it do make a custom inspector\n    [NativeClass(null)]\n    internal sealed class Physics2DSettings : ProjectSettingsBase\n    {\n        private Physics2DSettings() {}\n    }\n\n    // Exposed as internal, editor-only, because we only need it do make a custom inspector\n    [NativeClass(null)]\n    [ExcludeFromPreset]\n    internal sealed class MonoManager : ProjectSettingsBase\n    {\n        private MonoManager() {}\n    }\n\n    // Exposed as internal, editor-only, because we only need it do make a custom inspector\n    [NativeClass(null)]\n    [ExcludeFromPreset]\n    internal sealed class VFXManager : ProjectSettingsBase\n    {\n        private VFXManager()\n        {\n        }\n\n        [SettingsProvider]\n        internal static SettingsProvider CreateProjectSettingsProvider()\n        {\n            if (!UnityEngine.VFX.VFXManager.activateVFX)\n                return null;\n            var provider = AssetSettingsProvider.CreateProviderFromAssetPath(\n                \"Project/VFX\", \"ProjectSettings/VFXManager.asset\",\n                SettingsProvider.GetSearchKeywordsFromPath(\"ProjectSettings/VFXManager.asset\"));\n            return provider;\n        }\n    }\n\n    // Exposed as internal, editor-only, because we only need it do make a custom inspector\n    [NativeClass(null)]\n    internal sealed class InputManager : ProjectSettingsBase\n    {\n        private InputManager() {}\n\n        [SettingsProvider]\n        internal static SettingsProvider CreateProjectSettingsProvider()\n        {\n            // The new input system adds objects to InputManager.asset. This means we can't use AssetSettingsProvider.CreateProviderFromAssetPath\n            // as it will load *all* objects at that path and try to create an editor for it.\n            // NOTE: When the input system package is uninstalled, InputManager.asset will contain serialized MonoBehaviour objects for which\n            //       the C# classes are no longer available. They will thus not load correctly and appear as null entries.\n            var obj = AssetDatabase.LoadAssetAtPath<InputManager>(\"ProjectSettings/InputManager.asset\");\n            if (obj != null && obj.name == \"InputManager\")\n            {\n                var provider = AssetSettingsProvider.CreateProviderFromObject(\"Project/Input Manager\", obj,\n                    SettingsProvider.GetSearchKeywordsFromPath(\"ProjectSettings/InputManager.asset\"));\n                return provider;\n            }\n            return null;\n        }\n    }\n\n    [CustomEditor(typeof(InputManager))]\n    internal sealed class InputManagerEditor : Editor\n    {\n        public override void OnInspectorGUI()\n        {\n            if (PlayerSettings.GetDisableOldInputManagerSupport())\n                EditorGUILayout.HelpBox(\"This is where you can configure the controls to use with the UnityEngine.Input API. But you have switched input handling to \\\"Input System Package\\\" in your Player Settings. The Input Manager will not be used.\", MessageType.Error);\n            else\n                EditorGUILayout.HelpBox(\"This is where you can configure the controls to use with the UnityEngine.Input API. Consider using the new Input System Package instead.\", MessageType.Info);\n            DrawDefaultInspector();\n            EditorGUILayout.HelpBox(\"Physical Keys enables keyboard language layout independent mapping of key codes to physical keys. For example, 'q' will be the key to the right of the tab key no matter which (if any) key on the keyboard currently generates a 'q' character.\", MessageType.Info);\n        }\n    }\n\n    // Exposed as internal, editor-only, because we only need it do make a custom inspector\n    [NativeClass(null)]\n    internal sealed class TimeManager : ProjectSettingsBase\n    {\n        private TimeManager() {}\n    }\n\n    // Exposed as internal, editor-only, because we only need it do make a custom inspector\n    [NativeClass(null)]\n    internal sealed class MemorySettings : ProjectSettingsBase\n    {\n        private MemorySettings() {}\n    }\n\n\n    // Exposed as internal, editor-only, because we only need it do make a custom inspector\n    [NativeClass(null)]\n    internal sealed class UnityConnectSettings : ProjectSettingsBase\n    {\n        private UnityConnectSettings() {}\n    }\n\n    [NativeConditional(\"ENABLE_CLUSTERINPUT\")]\n    internal sealed class ClusterInputSettings\n    {\n        private ClusterInputSettings() {}\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/CutBoard.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.SceneManagement;\nusing UnityEngine.SceneManagement;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal static class CutBoard\n    {\n        internal static bool hasCutboardData { get { return m_GOCutboard != null && m_GOCutboard.Length > 0; } }\n        private static Transform[] m_GOCutboard;\n        private static Object[] m_SelectedObjects;\n        private static HashSet<Transform> m_CutAffectedGOs = new HashSet<Transform>();\n        private const string kCutAndPaste = \"Cut And Paste\";\n        private static Stage m_StageCutWasPerformedIn;\n\n        internal static void CutGO()\n        {\n            m_GOCutboard = Selection.transforms;\n            m_SelectedObjects = Selection.objects;\n            // Selection.transform does not provide correct list order, so we have to do it manually\n            m_GOCutboard = m_GOCutboard.ToList().OrderBy(g => Array.IndexOf(m_SelectedObjects, g.gameObject)).ToArray();\n\n            // Return if nothing selected\n            if (!hasCutboardData)\n                return;\n\n            m_StageCutWasPerformedIn = StageUtility.GetStage(m_GOCutboard[0].gameObject);\n\n            // If cut gameObject is prefab, get its root transform\n            for (int i = 0; i < m_GOCutboard.Length; i++)\n            {\n                if (PrefabUtility.GetPrefabAssetType(m_GOCutboard[i].gameObject) != PrefabAssetType.NotAPrefab)\n                {\n                    m_GOCutboard[i] = PrefabUtility.GetOutermostPrefabInstanceRoot(m_GOCutboard[i].gameObject)?.transform;\n                }\n            }\n\n            // Cut gameObjects should be visually marked as cut, so adding them to the hashset\n            m_CutAffectedGOs.Clear();\n            foreach (var item in m_GOCutboard)\n            {\n                m_CutAffectedGOs.Add(item);\n                AddChildrenToHashset(item);\n            }\n\n            // Clean pasteboard when cutting gameObjects\n            Unsupported.ClearPasteboard();\n        }\n\n        internal static bool CanGameObjectsBePasted()\n        {\n            return hasCutboardData && AreCutAndPasteStagesSame();\n        }\n\n        internal static void PasteGameObjects(Transform fallbackParent, bool worldPositionStays)\n        {\n            if (!AreCutAndPasteStagesSame())\n                return;\n\n            // Paste as a sibling of a active transform\n            if (Selection.activeTransform != null)\n            {\n                PasteAsSiblings(Selection.activeTransform, worldPositionStays);\n            }\n            // If nothing selected, paste as child of the fallback parent if present\n            else if (fallbackParent != null)\n            {\n                PasteAsChildren(fallbackParent, worldPositionStays);\n            }\n            // Otherwise, move to the scene of the active object\n            else\n            {\n                Scene targetScene = EditorSceneManager.GetSceneByHandle(Selection.activeInstanceID);\n                PasteToScene(targetScene, fallbackParent);\n            }\n        }\n\n        internal static void PasteAsChildren(Transform parent, bool worldPositionStays)\n        {\n            if (m_GOCutboard == null || !AreCutAndPasteStagesSame())\n                return;\n\n            foreach (var go in m_GOCutboard)\n            {\n                if (go != null && CanSetParent(go, parent))\n                {\n                    SetParent(go, parent, worldPositionStays);\n                }\n            }\n\n            Selection.objects = m_SelectedObjects;\n            // Reset cutBoard and greyed out gameObject list after paste\n            Reset();\n        }\n\n        private static void PasteAsSiblings(Transform target, bool worldPositionStays)\n        {\n            foreach (var go in m_GOCutboard)\n            {\n                if (go != null && CanSetParent(go, target))\n                {\n                    if (target.parent != null)\n                        SetParent(go, target.parent, worldPositionStays);\n                    else\n                        MoveToScene(go, target.gameObject.scene);\n                }\n            }\n\n            Selection.objects = m_SelectedObjects;\n            // Reset cutBoard and greyed out gameObject list after paste\n            Reset();\n        }\n\n        internal static void PasteToScene(Scene targetScene, Transform targetGO)\n        {\n            foreach (var go in m_GOCutboard)\n            {\n                if (go != null && CanSetParent(go, targetGO))\n                {\n                    MoveToScene(go, targetScene);\n                }\n            }\n\n            Selection.objects = m_SelectedObjects;\n            // Reset cutBoard and greyed out gameObject list after paste\n            Reset();\n        }\n\n        private static void SetParent(Transform go, Transform parent, bool worldPositionStays)\n        {\n            Undo.SetTransformParent(go, parent, worldPositionStays, kCutAndPaste);\n            go.SetAsLastSibling();\n        }\n\n        private static void MoveToScene(Transform current, Scene target)\n        {\n            if (current == null)\n                return;\n\n            Undo.SetTransformParent(current, null, kCutAndPaste);\n\n            if (target.isLoaded)\n            {\n                Undo.MoveGameObjectToScene(current.gameObject, target, kCutAndPaste);\n            }\n\n            current.SetAsLastSibling();\n        }\n\n        private static void AddChildrenToHashset(Transform parent)\n        {\n            for (int i = 0; i < parent.childCount; i++)\n            {\n                Transform childTransform = parent.transform.GetChild(i);\n                m_CutAffectedGOs.Add(childTransform);\n                if (childTransform.childCount > 0)\n                {\n                    AddChildrenToHashset(childTransform);\n                }\n            }\n        }\n\n        internal static bool IsGameObjectPartOfCutAndPaste(GameObject gameObject)\n        {\n            if (gameObject == null || !hasCutboardData)\n                return false;\n\n            var transform = gameObject.transform;\n            if (transform == null)\n                return false;\n\n            if (m_CutAffectedGOs.Contains(transform))\n                return true;\n\n            return false;\n        }\n\n        internal static void Reset()\n        {\n            m_SelectedObjects = null;\n            m_GOCutboard = null;\n            m_CutAffectedGOs.Clear();\n        }\n\n        internal static bool AreCutAndPasteStagesSame()\n        {\n            return m_StageCutWasPerformedIn == StageUtility.GetCurrentStage();\n        }\n\n        private static bool CanSetParent(Transform transform, Transform target)\n        {\n            bool canSetParent = transform != target;\n            if (target != null)\n                canSetParent = canSetParent && !transform.IsChildOf(target) && !target.IsChildOf(transform);\n            if (SubSceneGUI.IsSubSceneHeader(transform.gameObject))\n                canSetParent = canSetParent && !SubSceneGUI.IsChildOrSameAsOtherTransform(transform, target) && !SubSceneGUI.IsChildOrSameAsOtherTransform(target, transform);\n\n            return canSetParent;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/DataMode.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityObject = UnityEngine.Object;\nusing DataModeSupportHandler = UnityEditor.DeclareDataModeSupportAttribute.DataModeSupportHandler;\n\nnamespace UnityEditor\n{\n    /// <summary>\n    /// Options for the different modes of an <see cref=\"EditorWindow\"/>.\n    /// </summary>\n    //\n    // Dev note:\n    //\n    // There should be no reason to ever add to this enum. It exists only to express the duality between author-time\n    // and runtime data. If you feel like you need to add to this, please reconsider: it will likely break the\n    // `Authoring VS Runtime` feature for DOTS.\n    //\n    // Thank you for your consideration and have a great day!\n    //\n    // Sincerely,\n    // The #dots-editor team\n    //\n    [Serializable]\n    public enum DataMode // Values must be kept in sync with `DataMode.h`\n    {\n        /// <summary>\n        /// Represents a situation or context in which the usage of <see cref=\"DataMode\"/> is not applicable.\n        /// </summary>\n        /// <remarks> <para>\n        /// This mode disables the DataMode switch in the docking area.\n        /// </para> </remarks>\n        Disabled = 0,\n        /// <summary>\n        /// Uses this mode where only authoring data is available.\n        /// </summary>\n        /// <remarks> <para>\n        /// In this mode, only authoring data is available. When exiting Play mode, Unity retains authoring data.\n        /// </para> </remarks>\n        Authoring = 1,\n        /// <summary>\n        /// Uses this mode where a mix of authoring and runtime data is available.\n        /// </summary>\n        /// <remarks> <para>\n        /// In this mode, a mixture of authoring and runtime data is available.\n        /// When exiting Play mode, Unity loses runtime data. However, it retains any authoring data.\n        /// </para> </remarks>\n        Mixed = 2,\n        /// <summary>\n        /// Uses this mode where only runtime data is available.\n        /// </summary>\n        /// <remarks> <para>\n        /// In this mode, only runtime data is available. When exiting Play mode, Unity loses runtime data.\n        /// </para> </remarks>\n        Runtime = 3\n    }\n\n    /// <summary>\n    /// Container for the different parameters of the <see cref=\"IDataModeController.dataModeChanged\"/> event.\n    /// </summary>\n    /// <param name=\"nextDataMode\"> DataMode to which the <see cref=\"EditorWindow\"/> should change.</param>\n    /// <param name=\"changedThroughUI\"> Whether the change was initiated by the DataMode switcher UI\n    /// at the top-right of the Editor window.</param>\n    public readonly struct DataModeChangeEventArgs\n    {\n        public readonly DataMode nextDataMode;\n        public readonly bool changedThroughUI;\n\n        public DataModeChangeEventArgs(DataMode nextDataMode, bool changedThroughUI)\n        {\n            this.nextDataMode = nextDataMode;\n            this.changedThroughUI = changedThroughUI;\n        }\n    }\n\n    /// <summary>\n    /// Interface with which any <see cref=\"EditorWindow\"/> can interact with <see cref=\"DataMode\"/> functionalities.\n    /// To obtain an instance, use <see cref=\"EditorWindow.dataModeController\"/>>\n    /// </summary>\n    /// <remarks> <para>\n    /// This interface displays a switch in the docking area when the window is visible and has\n    /// more than one supported DataModes.\n    /// </para> </remarks>\n    public interface IDataModeController\n    {\n        /// <summary>\n        /// Returns the <see cref=\"DataMode\"/> currently active for the <see cref=\"EditorWindow\"/> that\n        /// owns this instance of IDataModeController.\n        /// </summary>\n        DataMode dataMode { get; }\n\n        /// <summary>\n        /// Event for subscribing to <see cref=\"DataMode\"/> changes.\n        /// </summary>\n        /// <remarks> <para>\n        /// This method accepts <see cref=\"DataModeChangeEventArgs\"/>>.\n        /// For example, you can register to this method to update the contents of the window for the given data mode.\n        /// </para> </remarks>\n        event Action<DataModeChangeEventArgs> dataModeChanged;\n\n        /// <summary>\n        /// Updates the list of <see cref=\"DataMode\"/>s that the <see cref=\"EditorWindow\"/> supports,\n        /// and sets the preferred DataMode to be used when the DataMode switcher UI is set to Automatic.\n        /// </summary>\n        /// <remarks> <para>\n        /// That list of the DataModes the Editor window supports varies based on a number of factors,\n        /// so it should only contain the DataModes available to the current context.\n        /// For example, a window might support the <see cref=\"DataMode.Authoring\"/> and <see cref=\"DataMode.Runtime\"/>\n        /// modes when in Edit mode, and the <see cref=\"DataMode.Mixed\"/> and <see cref=\"DataMode.Runtime\"/> modes when\n        /// in Play mode. A common pattern for that case is to store two lists internally and use\n        /// <see cref=\"EditorApplication.isPlaying\"/> to select which one to return.\n        /// <param name=\"supportedDataMode\"> A list of the supported DataModes. </param>\n        /// <param name=\"preferredDataMode\">\n        /// Preferred DataMode to use given the current context when the DataMode switcher UI is set to Automatic.\n        /// </param>\n        /// </para> </remarks>\n        void UpdateSupportedDataModes(IList<DataMode> supportedDataMode, DataMode preferredDataMode);\n\n        /// <summary>\n        /// Requests a <see cref=\"DataMode\"/> change for the <see cref=\"EditorWindow\"/>.\n        /// </summary>\n        /// <remarks> <para>\n        /// If the DataMode switcher UI is currently set to Automatic, the Editor window also\n        /// changes to that preferred DataMode.\n        /// <seealso cref=\"IDataModeController.UpdateSupportedDataModes\"/>>\n        /// </para> </remarks>\n        /// <param name=\"newDataMode\">\n        /// The DataMode to which the Editor window should change.\n        /// </param>\n        /// <returns>\n        /// Whether the Editor window has accepted the requested DataMode change.\n        /// </returns>>\n        bool TryChangeDataMode(DataMode newDataMode);\n    }\n\n    // DataModeController handles DataMode related actions internally.\n    // Each Editor window has a DataModeController instance.\n    [Serializable]\n    internal sealed class DataModeController : IDataModeController\n    {\n        static readonly DataMode[] k_DefaultModes = Array.Empty<DataMode>();\n\n        public event Action<DataModeChangeEventArgs> dataModeChanged;\n\n        [SerializeField] DataMode m_DataMode = DataMode.Disabled;\n        public DataMode dataMode\n        {\n            get => m_DataMode;\n            private set => m_DataMode = value;\n        }\n\n        [SerializeField] DataMode m_PreferredDataMode = DataMode.Disabled;\n        public DataMode preferredDataMode\n        {\n            get => m_PreferredDataMode;\n            private set => m_PreferredDataMode = value;\n        }\n\n        [SerializeField] DataMode[] m_SupportedDataModes = k_DefaultModes;\n        public IList<DataMode> supportedDataModes\n        {\n            get => m_SupportedDataModes;\n            private set => m_SupportedDataModes = value.ToArray();\n        }\n\n        [SerializeField] internal bool isAutomatic = true;\n\n        readonly List<DataMode> m_DataModeSanitizationCache = new List<DataMode>(3); // Number of modes, minus `Disabled`\n\n        public void UpdateSupportedDataModes(IList<DataMode> supported, DataMode preferred)\n        {\n            SanitizeSupportedDataModesList(supported.ToList(), m_DataModeSanitizationCache);\n\n            supportedDataModes = m_DataModeSanitizationCache.Count != 0 ? m_DataModeSanitizationCache : k_DefaultModes;\n\n            preferredDataMode = supportedDataModes.Count switch\n            {\n                0 => DataMode.Disabled,\n                1 => supportedDataModes[0],\n                _ => supportedDataModes.Contains(preferred) ? preferred : supportedDataModes[0]\n            };\n\n            if (!isAutomatic || dataMode == preferredDataMode)\n                return;\n\n            // Recover if automatic\n            dataMode = preferredDataMode;\n            dataModeChanged?.Invoke(new DataModeChangeEventArgs(dataMode, false));\n        }\n\n        static void SanitizeSupportedDataModesList(IReadOnlyList<DataMode> originalList, List<DataMode> sanitizedList)\n        {\n            sanitizedList.Clear();\n\n            foreach (var mode in originalList)\n            {\n                if (mode == DataMode.Disabled)\n                    continue; // Never list `DataMode.Disabled`\n\n                if (sanitizedList.Contains(mode))\n                    continue; // Prevent duplicate entries\n\n                sanitizedList.Add(mode);\n            }\n\n            // Ensure we are displaying the data modes in a predefined order, regardless of\n            // the order in which the user defined their list.\n            sanitizedList.Sort();\n        }\n\n        public bool ShouldDrawDataModesSwitch()\n        {\n            return dataMode != DataMode.Disabled\n                   // We don't want to show DataMode switch if there are not\n                   // at least 2 modes supported at the current moment.\n                   && supportedDataModes.Count > 1;\n        }\n\n        public bool TryChangeDataMode(DataMode newDataMode)\n        {\n            // Only change if currently in automatic mode\n            if (!isAutomatic || dataMode == newDataMode || !supportedDataModes.Contains(newDataMode))\n                return false;\n\n            dataMode = newDataMode;\n            dataModeChanged?.Invoke(new DataModeChangeEventArgs(newDataMode, false));\n            return true;\n        }\n\n        // Invoked when user interacts with the DataMode dropdown menu, for internal use only.\n        internal void SwitchToAutomatic()\n        {\n            if (isAutomatic)\n                return;\n\n            isAutomatic = true;\n\n            if (dataMode == preferredDataMode)\n                return;\n\n            // If the DataMode is not supported in current context, we fall back to default one.\n            dataMode = preferredDataMode;\n            dataModeChanged?.Invoke(new DataModeChangeEventArgs(dataMode, true));\n        }\n\n        // Invoked when user interacts with the DataMode dropdown men, for internal use only.\n        internal void SwitchToStickyDataMode(DataMode stickyDataMode)\n        {\n            isAutomatic = false;\n\n            if (dataMode == stickyDataMode)\n                return;\n\n            dataMode = supportedDataModes.Contains(stickyDataMode)\n                ? stickyDataMode\n                : preferredDataMode;\n\n            dataModeChanged?.Invoke(new DataModeChangeEventArgs(dataMode, true));\n        }\n    }\n\n    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n    [Obsolete(\"IDataModeHandler has been deprecated, please use EditorWindow.dataModeController instead.\", false)]\n    public interface IDataModeHandler\n    {\n        DataMode dataMode { get; }\n        IReadOnlyList<DataMode> supportedDataModes { get; }\n        bool IsDataModeSupported(DataMode mode);\n        void SwitchToNextDataMode();\n        void SwitchToDataMode(DataMode mode);\n        void SwitchToDefaultDataMode();\n    }\n\n    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n    [Obsolete(\"IDataModeHandlerAndDispatcher has been deprecated, please use EditorWindow.dataModeController instead.\", false)]\n    public interface IDataModeHandlerAndDispatcher : IDataModeHandler\n    {\n        event Action<DataMode> dataModeChanged;\n    }\n\n    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]\n    class DeclareDataModeSupportAttribute : Attribute\n    {\n        public delegate void DataModeSupportHandler(UnityObject activeSelection, UnityObject activeContext, HashSet<DataMode> supportedModes);\n\n        [RequiredSignature]\n        static void signature(UnityObject activeSelection, UnityObject activeContext, HashSet<DataMode> supportedModes)\n        {\n        }\n    }\n\n    static class DataModeSupportUtils\n    {\n        static readonly List<DataModeSupportHandler> k_Handlers = new(4);\n\n        static DataModeSupportUtils()\n        {\n            Rebuild();\n        }\n\n        public static void GetDataModeSupport(UnityObject activeSelection, UnityObject activeContext, HashSet<DataMode> supportedDataModes)\n        {\n            foreach (var handler in k_Handlers)\n            {\n                handler(activeSelection, activeContext, supportedDataModes);\n            }\n        }\n\n        static void Rebuild()\n        {\n            k_Handlers.Clear();\n            var candidates = TypeCache.GetMethodsWithAttribute<DeclareDataModeSupportAttribute>();\n            var attributeType = typeof(DeclareDataModeSupportAttribute);\n            foreach (var candidate in candidates)\n            {\n                if (!AttributeHelper.MethodMatchesAnyRequiredSignatureOfAttribute(candidate, attributeType))\n                    continue;\n\n                if (Delegate.CreateDelegate(typeof(DataModeSupportHandler), candidate) is DataModeSupportHandler handler)\n                    k_Handlers.Add(handler);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/DefaultAsset.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing UnityEngine.Bindings;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Modules/AssetPipelineEditor/Public/DefaultImporter.h\")]\n    // This class is public for users to be able to make custom editors for this type (see case 656580)\n    public class DefaultAsset : UnityEngine.Object\n    {\n        internal enum ErrorCodes\n        {\n            NoError,\n            PrefabCorruptedFileIds,\n            ImportFail_TooMuch_Data,\n            ImportFail_MetaFile_GUID_Mismatch,\n            ImportFail_ImporterCrashed,\n            ErrorCodeCount\n        };\n\n        private protected DefaultAsset() {}\n        internal extern string message { get; }\n\n        internal extern int errorCode { get; }\n\n        internal extern bool isWarning {[NativeName(\"IsWarning\")] get; }\n    }\n\n    [CustomEditor(typeof(DefaultAsset), isFallback = true)] // fallback so broad-matching user inspectors always win (e.g. case #656580)\n    class DefaultAssetInspector : Editor\n    {\n        public override VisualElement CreateInspectorGUI()\n        {\n            var container = new VisualElement();\n\n            var defaultAsset = (DefaultAsset)target;\n            if (defaultAsset.message.Length > 0)\n            {\n                var helpBox = new HelpBox(\n                    defaultAsset.message,\n                    defaultAsset.isWarning ? HelpBoxMessageType.Warning : HelpBoxMessageType.Info);\n                container.Add(helpBox);\n            }\n            if (defaultAsset.errorCode == (int)DefaultAsset.ErrorCodes.ImportFail_MetaFile_GUID_Mismatch)\n            {\n                var button = new Button(() =>\n                {\n                    var metaPath = AssetDatabase.GetAssetPath(target).Trim('/') + \".meta\";\n                    File.SetLastWriteTimeUtc(metaPath,DateTime.UtcNow);\n                    AssetDatabase.Refresh();\n                });\n                button.text = \"Fix Now\";\n                container.Add(button);\n            }\n\n            return container;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Delayer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor\n{\n    class Delayer\n    {\n        private long m_LastExecutionTime;\n        private Action<object> m_Action;\n        private readonly long m_DebounceDelay;\n        private object m_Context;\n        private readonly bool m_IsThrottle;\n        private readonly bool m_FirstExecuteImmediate;\n        private bool m_DelayInProgress;\n\n        internal static readonly TimeSpan DefaultDelay = TimeSpan.FromMilliseconds(200);\n\n        /// <summary>\n        /// Throttle the action to be executed at most once every delay.\n        /// If no delay is specified default delay is <see cref=\"DefaultDelay\"/>\n        /// </summary>\n        /// <param name=\"action\">action to be executed</param>\n        /// <param name=\"delay\">delay of the action, if not specified <see cref=\"DefaultDelay\"/> will be used</param>\n        /// <returns>a new instance of a <see cref=\"Delayer\"/></returns>\n        public static Delayer Throttle(Action<object> action, TimeSpan? delay = null)\n        {\n            return new Delayer(action, delay ?? DefaultDelay, true, false);\n        }\n\n        /// <summary>\n        /// Throttle the action to be executed at most once every delay.\n        /// </summary>\n        /// <param name=\"action\">action to be executed</param>\n        /// <param name=\"delay\">delay of the action</param>\n        /// <param name=\"firstExecuteImmediate\">if true, the action will be executed immediately</param>\n        /// <returns>a new instance of a <see cref=\"Delayer\"/></returns>\n        public static Delayer Throttle(Action<object> action, TimeSpan delay, bool firstExecuteImmediate)\n        {\n            return new Delayer(action, delay, true, firstExecuteImmediate);\n        }\n\n        /// <summary>\n        /// Debounce the action to be executed after the delay has passed.\n        /// If no delay is specified default delay is <see cref=\"DefaultDelay\"/>\n        /// </summary>\n        /// <param name=\"action\">action to be executed</param>\n        /// <param name=\"delay\">delay of the action, if not specified <see cref=\"DefaultDelay\"/> will be used</param>\n        /// <returns>a new instance of a <see cref=\"Delayer\"/></returns>\n        public static Delayer Debounce(Action<object> action, TimeSpan? delay = null)\n        {\n            return new Delayer(action, delay ?? DefaultDelay, false, false);\n        }\n\n        /// <summary>\n        /// Debounce the action to be executed after the delay has passed.\n        /// </summary>\n        /// <param name=\"action\">action to be executed</param>\n        /// <param name=\"delay\">delay for the action</param>\n        /// <param name=\"firstExecuteImmediate\">if true, the action will be executed immediately</param>\n        /// <returns>a new instance of a <see cref=\"Delayer\"/></returns>\n        public static Delayer Debounce(Action<object> action, TimeSpan delay, bool firstExecuteImmediate)\n        {\n            return new Delayer(action, delay, false, firstExecuteImmediate);\n        }\n\n        /// <summary>\n        /// Try to execute the action\n        /// </summary>\n        /// <param name=\"context\">Context object to pass to the configured action</param>\n        public void Execute(object context = null)\n        {\n            m_Context = context;\n\n            if (m_IsThrottle)\n            {\n                if (m_LastExecutionTime == 0 || !m_DelayInProgress)\n                    Throttle();\n            }\n            else\n            {\n                if (m_FirstExecuteImmediate && m_LastExecutionTime == 0)\n                {\n                    m_Action?.Invoke(m_Context);\n                    m_LastExecutionTime = DateTime.UtcNow.Ticks;\n                }\n                else\n                {\n                    m_LastExecutionTime = DateTime.UtcNow.Ticks;\n                    Debounce();\n                }\n            }\n        }\n\n        private Delayer(Action<object> action, TimeSpan delay, bool isThrottle, bool firstExecuteImmediate)\n        {\n            m_Action = action;\n            m_DebounceDelay = delay.Ticks;\n            m_IsThrottle = isThrottle;\n            m_FirstExecuteImmediate = firstExecuteImmediate;\n        }\n\n        public void Abort()\n        {\n            EditorApplication.tick -= Debounce;\n            EditorApplication.tick -= Throttle;\n        }\n\n        public void Dispose()\n        {\n            Abort();\n\n            m_Context = null;\n            m_Action = null;\n            m_DelayInProgress = false;\n        }\n\n        private void Debounce()\n        {\n            var currentTime = DateTime.UtcNow.Ticks;\n            if (m_LastExecutionTime != 0 && DelayHasPassed(currentTime))\n            {\n                m_DelayInProgress = false;\n                EditorApplication.tick -= Debounce;\n                m_Action?.Invoke(m_Context);\n                m_LastExecutionTime = 0;\n            }\n            else\n            {\n                if (!m_DelayInProgress)\n                    EditorApplication.tick += Debounce;\n                m_DelayInProgress = true;\n            }\n        }\n\n        private void Throttle()\n        {\n            var currentTime = DateTime.UtcNow.Ticks;\n\n            if (m_FirstExecuteImmediate)\n            {\n                if (m_LastExecutionTime == 0 || DelayHasPassed(currentTime))\n                {\n                    m_DelayInProgress = false;\n                    EditorApplication.tick -= Throttle;\n                    m_Action?.Invoke(m_Context);\n                    m_LastExecutionTime = currentTime;\n                }\n                else\n                {\n                    if (!m_DelayInProgress)\n                        EditorApplication.tick += Throttle;\n                    m_DelayInProgress = true;\n                }\n            }\n            else\n            {\n                if (m_LastExecutionTime != 0 && DelayHasPassed(currentTime))\n                {\n                    m_DelayInProgress = false;\n                    EditorApplication.tick -= Throttle;\n                    m_Action?.Invoke(m_Context);\n                    m_LastExecutionTime = 0;\n                }\n                else\n                {\n                    if (m_LastExecutionTime == 0)\n                        m_LastExecutionTime = currentTime;\n                    if (!m_DelayInProgress)\n                        EditorApplication.tick += Throttle;\n                    m_DelayInProgress = true;\n                }\n            }\n        }\n\n        private bool DelayHasPassed(long currentTime)\n        {\n            var timeSpan = new TimeSpan(currentTime - m_LastExecutionTime);\n            return timeSpan.Ticks >= m_DebounceDelay;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/DeploymentTargets/DefaultDeploymentTargetsExtension.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Build;\nusing UnityEditor.Modules;\nusing UnityEditorInternal;\n\nnamespace UnityEditor.DeploymentTargets\n{\n    internal class DefaultDeploymentTargetsMainThreadContext : IDeploymentTargetsMainThreadContext\n    {\n    }\n\n    internal class DefaultDeploymentTargetInfo : IDeploymentTargetInfo\n    {\n        public virtual FlagSet<DeploymentTargetSupportFlags> GetSupportFlags()\n        {\n            return DeploymentTargetSupportFlags.None;\n        }\n\n        public virtual TargetCheckResult CheckTarget(DeploymentTargetRequirements targetRequirements)\n        {\n            return new TargetCheckResult();\n        }\n\n        public virtual string GetDisplayName()\n        {\n            return \"\";\n        }\n\n        public virtual bool SupportsLaunchBuild(BuildProperties buildProperties)\n        {\n            return GetSupportFlags().HasFlags(DeploymentTargetSupportFlags.Launch) && CheckTarget(buildProperties.GetTargetRequirements()).Passed();\n        }\n    }\n\n    internal class DefaultDeploymentTargetLogger : DeploymentTargetLogger\n    {\n        internal override void Start() {}\n\n        internal override void Stop() {}\n\n        internal override void Clear() {}\n    }\n\n    internal abstract class DefaultDeploymentTargetsExtension\n        : IDeploymentTargetsExtension\n    {\n        public virtual IDeploymentTargetsMainThreadContext GetMainThreadContext(bool setup)\n        {\n            CheckGetMainThreadContextCalledOnMainThread();\n            return new DefaultDeploymentTargetsMainThreadContext();\n        }\n\n        protected void CheckGetMainThreadContextCalledOnMainThread()\n        {\n            if (!InternalEditorUtility.CurrentThreadIsMainThread())\n                throw new NotSupportedException(\"Deployment targets main thread context can only be retrieved from the main thread.\");\n        }\n\n        public virtual List<DeploymentTargetIdAndStatus> GetKnownTargets(IDeploymentTargetsMainThreadContext context, ProgressHandler progressHandler = null)\n        {\n            return new List<DeploymentTargetIdAndStatus>();\n        }\n\n        public virtual IDeploymentTargetInfo GetTargetInfo(IDeploymentTargetsMainThreadContext context, DeploymentTargetId targetId, ProgressHandler progressHandler = null)\n        {\n            return new DefaultDeploymentTargetInfo();\n        }\n\n        public virtual DeploymentTargetLogger GetTargetLogger(IDeploymentTargetsMainThreadContext context, DeploymentTargetId targetId)\n        {\n            return new DefaultDeploymentTargetLogger();\n        }\n\n        public virtual IDeploymentLaunchResult LaunchBuildOnTarget(IDeploymentTargetsMainThreadContext context, BuildProperties buildProperties, DeploymentTargetId targetId, ProgressHandler progressHandler = null)\n        {\n            throw new NotSupportedException();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/DeploymentTargets/DeploymentTargetLogger.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.DeploymentTargets\n{\n    internal abstract class DeploymentTargetLogger\n    {\n        // Starts reading log and redirects it to OnLogMessage callbacks\n        internal abstract void Start();\n\n        // Stops the logger. Can be used to implement closing process/file-stream\n        internal abstract void Stop();\n\n        // Can be used to implement clearing log sources e.g. clear ADB logcat\n        internal abstract void Clear();\n\n        // Event executed on every log message received from log source\n        // First string parameter is used as log ID, e.g. it could be stdout, stderr or any other\n        // For every unique ID passed to this event - a separate log file will be created\n        // Second string parameter is log message\n        internal event Action<string, string> logMessage;\n\n        protected virtual void OnLogMessage(string id, string message)\n        {\n            logMessage?.Invoke(id, message);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/DeploymentTargets/DeploymentTargetManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Modules;\n\nnamespace UnityEditor.DeploymentTargets\n{\n    class DeploymentTargetManager\n    {\n        const string k_ExtensionErrorMessage = \"Platform does not implement DeploymentTargetsExtension\";\n\n        readonly IDeploymentTargetsExtension m_Extension;\n        readonly IDeploymentTargetsMainThreadContext m_Context;\n\n        public IDeploymentTargetsMainThreadContext Context { get { return m_Context; }}\n        public IDeploymentTargetsExtension Extension { get { return m_Extension; } }\n\n        public static DeploymentTargetManager CreateInstance(BuildTarget buildTarget, bool setup = true)\n        {\n            var extension = GetExtension(buildTarget);\n            var context = extension.GetMainThreadContext(setup);\n            return context != null ? new DeploymentTargetManager(extension, context) : null;\n        }\n\n        public static DeploymentTargetManager CreateInstance(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget, bool setup = true)\n        {\n            return CreateInstance(buildTarget, setup);\n        }\n\n        DeploymentTargetManager(IDeploymentTargetsExtension extension, IDeploymentTargetsMainThreadContext context)\n        {\n            m_Extension = extension;\n            m_Context = context;\n        }\n\n        static IDeploymentTargetsExtension GetExtension(BuildTarget buildTarget)\n        {\n            var extension = ModuleManager.GetDeploymentTargetsExtension(buildTarget);\n            if (extension == null)\n                throw new NotSupportedException(k_ExtensionErrorMessage);\n            return extension;\n        }\n\n        public IDeploymentTargetInfo GetTargetInfo(DeploymentTargetId targetId)\n        {\n            return m_Extension.GetTargetInfo(m_Context, targetId);\n        }\n\n        public IDeploymentLaunchResult LaunchBuildOnTarget(BuildProperties buildProperties, DeploymentTargetId targetId, ProgressHandler progressHandler = null)\n        {\n            return m_Extension.LaunchBuildOnTarget(m_Context, buildProperties, targetId, progressHandler);\n        }\n\n        public List<DeploymentTargetIdAndStatus> GetKnownTargets()\n        {\n            return m_Extension.GetKnownTargets(m_Context);\n        }\n\n        internal DeploymentTargetLogger GetTargetLogger(DeploymentTargetId targetId)\n        {\n            return m_Extension.GetTargetLogger(m_Context, targetId);\n        }\n\n        // Launch a build on any target on a platform\n        public List<DeploymentTargetId> FindValidTargetsForLaunchBuild(BuildProperties buildProperties)\n        {\n            var validTargetIds = new List<DeploymentTargetId>();\n            var knownTargets = m_Extension.GetKnownTargets(m_Context);\n            foreach (var target in knownTargets)\n            {\n                if (target.status == DeploymentTargetStatus.Ready)\n                {\n                    var targetInfo = m_Extension.GetTargetInfo(m_Context, target.id);\n                    if (targetInfo.SupportsLaunchBuild(buildProperties))\n                        validTargetIds.Add(target.id);\n                }\n            }\n            return validTargetIds;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/DeploymentTargets/IDeploymentTargetsExtension.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Build;\nusing UnityEditor.Modules;\nusing UnityEngine;\n\nnamespace UnityEditor.DeploymentTargets\n{\n    internal struct DeploymentTargetId\n    {\n        // Meta-targets, to be able to select targets that does not depend on the current connection state.\n        //  For example: selecting \"all\" should launch on all connected targets, even if the number of connected targets\n        //  changes between launches.\n        internal static readonly DeploymentTargetId kDefault = new DeploymentTargetId(\"__builtin__target_default\");\n        internal static readonly DeploymentTargetId kAll = new DeploymentTargetId(\"__builtin__target_all\");\n        internal static readonly DeploymentTargetId kEnterIP = new DeploymentTargetId(\"__builtin__enter_ip\");\n\n        public string id;\n\n        public DeploymentTargetId(string id)\n        {\n            if (string.IsNullOrEmpty(id))\n                id = kDefault.id;\n            this.id = id;\n        }\n\n        public static implicit operator DeploymentTargetId(string id)\n        {\n            return new DeploymentTargetId(id);\n        }\n\n        public static implicit operator string(DeploymentTargetId id)\n        {\n            return id.id;\n        }\n\n        // Weather this is a meta target (kDefault, kAll) or a specific one.\n        public bool IsSpecificTarget()\n        {\n            return id != kDefault.id && id != kAll.id;\n        }\n    }\n\n    internal enum DeploymentTargetStatus\n    {\n        // Target is ready\n        Ready,\n        // Target is available but there are issues\n        NotReady,\n        // Target exists, but we cannot connect to it\n        Unavailable,\n        // Target does not exist or it has existed but no longer responds\n        Unknown,\n    }\n\n    internal struct DeploymentTargetIdAndStatus\n    {\n        public DeploymentTargetId id;\n        public DeploymentTargetStatus status;\n    }\n\n    internal interface IDeploymentLaunchResult\n    {\n        public bool Success { get; }\n        public string Errors { get; }\n    }\n\n    internal class DefaultDeploymentLaunchResult : IDeploymentLaunchResult\n    {\n        public bool Success { get; }\n        public string Errors { get; }\n\n        public DefaultDeploymentLaunchResult(bool success, string errors = null)\n        {\n            this.Success = success;\n\n            if (!success && string.IsNullOrEmpty(errors))\n                Debug.LogWarning(\"Deployment launch failed, but no error was provided.\");\n\n            Errors = errors == null ? string.Empty : errors;\n        }\n    }\n\n    [Flags]\n    internal enum DeploymentTargetSupportFlags\n    {\n        None            = 0,\n        Launch          = 0x01 << 0\n    }\n\n    internal enum CheckStatus\n    {\n        Ok = 0,\n        Failed\n    }\n\n    internal struct CategoryCheckResult\n    {\n        public CheckStatus status;\n        public string failureMessage;\n    }\n\n    internal struct TargetCheckResult\n    {\n        public CategoryCheckResult hardware;\n        public CategoryCheckResult sdk;\n\n        public bool Passed()\n        {\n            return hardware.status == CheckStatus.Ok &&\n                sdk.status == CheckStatus.Ok;\n        }\n    }\n\n    internal interface IDeploymentTargetInfo\n    {\n        FlagSet<DeploymentTargetSupportFlags> GetSupportFlags();\n\n        // Checks a target requirements against target information\n        // Check passes if the target is compatible\n        TargetCheckResult CheckTarget(DeploymentTargetRequirements targetRequirements);\n\n        string GetDisplayName();\n\n        bool SupportsLaunchBuild(BuildProperties buildProperties);\n    }\n\n    internal interface IDeploymentTargetsMainThreadContext\n    {\n    }\n\n    internal class DeploymentOperationAbortedException : Exception {}\n\n    internal class DeploymentOperationFailedException : Exception\n    {\n        public readonly string title;\n        public IDeploymentLaunchResult launchResult { get; }\n\n        public DeploymentOperationFailedException(string title, string message, Exception inner = null) : base(message, inner)\n        {\n            this.title = title;\n            this.launchResult = new DefaultDeploymentLaunchResult(false, message);\n        }\n\n        public DeploymentOperationFailedException(string title, string message, DefaultDeploymentLaunchResult result, Exception inner = null) : base(message, inner)\n        {\n            this.title = title;\n            this.launchResult = result;\n            if (result != null && result.Success)\n                Debug.LogWarning($\"Creating DeploymentOperationFailedException('{title}') , but launch result says it's succeeded?\");\n        }\n    }\n\n    internal class CorruptBuildException : DeploymentOperationFailedException\n    {\n        public CorruptBuildException(string message = \"Corrupt build.\", Exception inner = null) : base(\"Corrupt build\", message, inner) {}\n    }\n\n    internal interface IDeploymentTargetsExtension\n    {\n        // Returns context object populated with data that other methods can access from any thread.\n        //  setup - Pass true to setup platform if it hasn't been already setup (e.g. display dialog box to select SDK path). Throws exception if user cancels setup process.\n        //          Pass false to return null if platform hasn't been already setup. This is useful when this method is called from UI draw event.\n        //          Displaying dialog boxes at that point breaks UI. Let the user know what's going on by displaying informational label or something like that.\n        //  Can NOT be called from a background thread\n        IDeploymentTargetsMainThreadContext GetMainThreadContext(bool setup = true);\n\n        // Returns a list of all known targets and their status\n        //  Can be called from a background thread\n        List<DeploymentTargetIdAndStatus> GetKnownTargets(IDeploymentTargetsMainThreadContext context, ProgressHandler progressHandler = null);\n\n        // Returns info for a target\n        // Throws DeploymentOperationFailedException (or one of its subclasses) is something goes wrong.\n        // Throws DeploymentOperationAbortedException if process is cancelled by the user.\n        //  Can be called from a background thread\n        IDeploymentTargetInfo GetTargetInfo(IDeploymentTargetsMainThreadContext context, DeploymentTargetId targetId, ProgressHandler progressHandler = null);\n\n        // Returns device logger specific to target platform\n        // Throws DeploymentOperationFailedException (or one of its subclasses) is something goes wrong.\n        // Throws DeploymentOperationAbortedException if process is cancelled by the user.\n        DeploymentTargetLogger GetTargetLogger(IDeploymentTargetsMainThreadContext context, DeploymentTargetId targetId);\n\n        // Launches a build on a target\n        // Throws DeploymentOperationFailedException (or one of its subclasses) is something goes wrong.\n        // Throws DeploymentOperationAbortedException if process is cancelled by the user.\n        //  Can be called from a background thread\n        IDeploymentLaunchResult LaunchBuildOnTarget(IDeploymentTargetsMainThreadContext context, BuildProperties buildProperties, DeploymentTargetId targetId, ProgressHandler progressHandler = null);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/DisplayUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System;\nusing System.Collections;\nusing System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\nnamespace UnityEditor\n{\n    internal class DisplayUtility\n    {\n        static string s_DisplayStr = \"Display {0}\";\n        private static GUIContent[] s_GenericDisplayNames =\n        {\n            EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 1)), EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 2)),\n            EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 3)), EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 4)),\n            EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 5)), EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 6)),\n            EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 7)), EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 8))\n        };\n\n        private static readonly int[] s_DisplayIndices = { 0, 1, 2, 3, 4, 5, 6, 7 };\n\n        public static GUIContent[] GetGenericDisplayNames()\n        {\n            return s_GenericDisplayNames;\n        }\n\n        public static int[] GetDisplayIndices()\n        {\n            return s_DisplayIndices;\n        }\n\n        public static GUIContent[] GetDisplayNames()\n        {\n            GUIContent[] platformDisplayNames = Modules.ModuleManager.GetDisplayNames(EditorUserBuildSettings.activeBuildTarget.ToString());\n            return platformDisplayNames != null ? platformDisplayNames : s_GenericDisplayNames;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/DragAndDrop.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\nusing System.Collections;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    // Visual indication mode for Drag & Drop operation.\n    public enum DragAndDropVisualMode\n    {\n        None = 0,       // No indication (drag should not be performed).\n        Copy = 1,       // Copy dragged objects.\n        Link = 2,       // Link dragged objects to target.\n        Move = 16,      // Move dragged objects.\n        Generic = 4,    // Generic drag operation.\n        Rejected = 32   // Rejected drag operation.\n    }\n    // Needs to be kept in sync with DragAndDropForwarding.h\n    [Flags]\n    public enum HierarchyDropFlags\n    {\n        None = 0,\n        DropUpon = 1 << 0,\n        DropBetween = 1 << 1,\n        DropAfterParent = 1 << 2,\n        SearchActive = 1 << 3,\n        DropAbove = 1 << 4\n    }\n\n    public struct DragAndDropWindowTarget\n    {\n        public static readonly int projectBrowser = \"ProjectBrowser\".GetHashCode();\n        public static readonly int sceneView = \"SceneView\".GetHashCode();\n        public static readonly int hierarchy = \"Hierarchy\".GetHashCode();\n        public static readonly int inspector = \"Inspector\".GetHashCode();\n    }\n\n    // Editor drag & drop operations.\n    [NativeHeader(\"Editor/Platform/Interface/DragAndDrop.h\"),\n     StaticAccessor(\"GetDragAndDrop()\", StaticAccessorType.Dot)]\n    public class DragAndDrop\n    {\n        private static Hashtable s_GenericData;\n        private static Dictionary<int, List<Delegate>> m_DropHandlers;\n\n        internal static ProjectBrowserDropHandler DefaultProjectBrowserDropHandler = DefaultProjectBrowserDropHandlerImpl;\n        internal static InspectorDropHandler DefaultInspectorDropHandler = InternalEditorUtility.InspectorWindowDrag;\n        internal static HierarchyDropHandler DefaultHierarchyDropHandler = InternalEditorUtility.HierarchyWindowDragByID;\n\n        internal static Dictionary<int, List<Delegate>> dropHandlers\n        {\n            get\n            {\n                if (m_DropHandlers == null)\n                {\n                    m_DropHandlers = new Dictionary<int, List<Delegate>>();\n                    AddDropHandler(DefaultProjectBrowserDropHandler);\n                    AddDropHandler(DefaultInspectorDropHandler);\n                    AddDropHandler(DefaultHierarchyDropHandler);\n                }\n                return m_DropHandlers;\n            }\n        }\n\n        internal static void ClearDropHandlers()\n        {\n            m_DropHandlers?.Clear();\n            m_DropHandlers = null;\n        }\n\n        internal static void AddDropHandler(int dropDstId, Delegate handler)\n        {\n            if (HasHandler(dropDstId, handler))\n            {\n                throw new Exception(\"Delegate already registered for dropDestinationId:\" + dropDstId);\n            }\n\n            if (!dropHandlers.TryGetValue(dropDstId, out var handlers))\n            {\n                handlers = new List<Delegate>();\n                dropHandlers[dropDstId] = handlers;\n            }\n            handlers.Add(handler);\n        }\n\n        internal static void RemoveDropHandler(int dropDstId, Delegate handler)\n        {\n            if (dropHandlers.TryGetValue(dropDstId, out var handlers))\n            {\n                handlers.RemoveAll(dropHandler => dropHandler == handler);\n            }\n        }\n\n        internal static DragAndDropVisualMode DropOnProjectBrowserWindow(int dragUponInstanceId, string dropUponPath, bool perform)\n        {\n            return Drop(DragAndDropWindowTarget.projectBrowser, dragUponInstanceId, dropUponPath, perform);\n        }\n\n        internal static DragAndDropVisualMode DropOnSceneWindow(UnityEngine.Object dropUpon, Vector3 worldPosition, Vector2 viewportPosition, Transform parentForDraggedObjects, bool perform)\n        {\n            return Drop(DragAndDropWindowTarget.sceneView, dropUpon, worldPosition, viewportPosition, parentForDraggedObjects, perform);\n        }\n\n        internal static DragAndDropVisualMode DropOnInspectorWindow(UnityEngine.Object[] targets, bool perform)\n        {\n            return Drop(DragAndDropWindowTarget.inspector, targets, perform);\n        }\n\n        internal static DragAndDropVisualMode DropOnHierarchyWindow(int dropTargetInstanceID, HierarchyDropFlags dropMode, Transform parentForDraggedObjects, bool perform)\n        {\n            return Drop(DragAndDropWindowTarget.hierarchy, dropTargetInstanceID, dropMode, parentForDraggedObjects, perform);\n        }\n\n        internal static DragAndDropVisualMode Drop(int dropDstId, params object[] args)\n        {\n            SavedGUIState guiState = SavedGUIState.Create();\n\n            if (!dropHandlers.TryGetValue(dropDstId, out var handlers))\n            {\n                return DragAndDropVisualMode.Rejected;\n            }\n\n            var dropResult = DragAndDropVisualMode.None;\n            for (var i = handlers.Count - 1; i >= 0; --i)\n            {\n                var dropHandler = handlers[i];\n                dropResult = (DragAndDropVisualMode)dropHandler.DynamicInvoke(args);\n                if (dropResult != DragAndDropVisualMode.None)\n                {\n                    break;\n                }\n            }\n\n            guiState.ApplyAndForget();\n            return dropResult;\n        }\n\n        internal static DragAndDropVisualMode DefaultProjectBrowserDropHandlerImpl(int dragUponInstanceId, string dummy, bool perform)\n        {\n            HierarchyProperty search = new HierarchyProperty(HierarchyType.Assets);\n            if (search.Find(dragUponInstanceId, null))\n                return InternalEditorUtility.ProjectWindowDrag(search, perform);\n\n            if (dragUponInstanceId != 0)\n            {\n                var path = AssetDatabase.GetAssetPath(dragUponInstanceId);\n                if (string.IsNullOrEmpty(path))\n                    return DragAndDropVisualMode.Rejected;\n\n                var packageInfo = PackageManager.PackageInfo.FindForAssetPath(path);\n                if (packageInfo != null)\n                {\n                    search = new HierarchyProperty(packageInfo.assetPath);\n                    if (search.Find(dragUponInstanceId, null))\n                        return InternalEditorUtility.ProjectWindowDrag(search, perform);\n                }\n            }\n            return InternalEditorUtility.ProjectWindowDrag(null, perform);\n        }\n\n        // HandleDelayedDrag can be used to start a drag and drop\n        internal static bool HandleDelayedDrag(Rect position, int id, Object objectToDrag)\n        {\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (position.Contains(evt.mousePosition) && evt.clickCount == 1)\n                    {\n                        if (evt.button == 0 && !(Application.platform == RuntimePlatform.OSXEditor && evt.control))\n                        {\n                            GUIUtility.hotControl = id;\n                            DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), id);\n                            delay.mouseDownPosition = evt.mousePosition;\n                            return true;\n                        }\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), id);\n                        if (delay.CanStartDrag())\n                        {\n                            GUIUtility.hotControl = 0;\n                            PrepareStartDrag();\n                            Object[] references = { objectToDrag };\n                            objectReferences = references;\n                            StartDrag(ObjectNames.GetDragAndDropTitle(objectToDrag));\n                            return true;\n                        }\n                    }\n                    break;\n            }\n            return false;\n        }\n\n        // Clears drag & drop data.\n        public static void PrepareStartDrag()\n        {\n            if (Event.current != null)\n            {\n                switch (Event.current.type)\n                {\n                    case EventType.DragUpdated:\n                    case EventType.DragPerform:\n                    case EventType.DragExited:\n                        Debug.LogError($\"Calling \\\"{nameof(PrepareStartDrag)}\\\" when dragging is in progress is not supported.\");\n                        return;\n                }\n            }\n            s_GenericData = null;\n            paths = null;\n            objectReferences = new UnityEngine.Object[] {};\n            visualMode = DragAndDropVisualMode.None;\n            PrepareStartDrag_Internal();\n        }\n\n        // Start a drag operation.\n        public static void StartDrag(string title)\n        {\n            if (Event.current.type == EventType.MouseDown || Event.current.type == EventType.MouseDrag)\n            {\n                StartDrag_Internal(title);\n            }\n            else\n            {\n                Debug.LogError(\"Drags can only be started from MouseDown or MouseDrag events\");\n            }\n        }\n\n        [RequiredByNativeCode]\n        private static bool HasGenericDragData()\n        {\n            return s_GenericData != null;\n        }\n\n        // Get data associated with current drag and drop operation.\n        public static object GetGenericData(string type)\n        {\n            if (s_GenericData != null && s_GenericData.Contains(type))\n                return s_GenericData[type];\n            return null;\n        }\n\n        // Set data associated with current drag and drop operation.\n        public static void SetGenericData(string type, object data)\n        {\n            if (s_GenericData == null)\n                s_GenericData = new Hashtable();\n            s_GenericData[type] = data;\n        }\n\n        public static extern Object[] objectReferences {[NativeMethod(\"GetPPtrs\")] get; [NativeMethod(\"SetPPtrs\")] set; }\n        public static extern string[] paths { get; set; }\n        public static extern int activeControlID { get; set; }\n        public static extern DragAndDropVisualMode visualMode { get; set; }\n\n        public static extern void AcceptDrag();\n        [NativeMethod(\"PrepareStartDrag\")]\n        private static extern void PrepareStartDrag_Internal();\n        [NativeMethod(\"Cleanup\")]\n        internal static extern void Cleanup();\n        [NativeMethod(\"StartDrag\")]\n        private static extern void StartDrag_Internal(string title);\n\n        public delegate DragAndDropVisualMode ProjectBrowserDropHandler(int dragInstanceId, string dropUponPath, bool perform);\n        public delegate DragAndDropVisualMode SceneDropHandler(UnityEngine.Object dropUpon, Vector3 worldPosition, Vector2 viewportPosition, Transform parentForDraggedObjects, bool perform);\n        public delegate DragAndDropVisualMode InspectorDropHandler(UnityEngine.Object[] targets, bool perform);\n        public delegate DragAndDropVisualMode HierarchyDropHandler(int dropTargetInstanceID, HierarchyDropFlags dropMode, Transform parentForDraggedObjects, bool perform);\n\n        internal static bool HasHandler(int dropDstId)\n        {\n            return dropHandlers.ContainsKey(dropDstId);\n        }\n\n        public static bool HasHandler(int dropDstId, Delegate handler)\n        {\n            List<Delegate> handlers = null;\n            if (!dropHandlers.TryGetValue(dropDstId, out handlers))\n            {\n                return false;\n            }\n            return handlers != null && handlers.Any(dropHandler => dropHandler == handler);\n        }\n\n        public static void AddDropHandler(ProjectBrowserDropHandler handler)\n        {\n            AddDropHandler(DragAndDropWindowTarget.projectBrowser, handler);\n        }\n\n        public static void AddDropHandler(SceneDropHandler handler)\n        {\n            AddDropHandler(DragAndDropWindowTarget.sceneView, handler);\n        }\n\n        public static void AddDropHandler(HierarchyDropHandler handler)\n        {\n            AddDropHandler(DragAndDropWindowTarget.hierarchy, handler);\n        }\n\n        public static void AddDropHandler(InspectorDropHandler handler)\n        {\n            AddDropHandler(DragAndDropWindowTarget.inspector, handler);\n        }\n\n        public static void RemoveDropHandler(ProjectBrowserDropHandler handler)\n        {\n            RemoveDropHandler(DragAndDropWindowTarget.projectBrowser, handler);\n        }\n\n        public static void RemoveDropHandler(SceneDropHandler handler)\n        {\n            RemoveDropHandler(DragAndDropWindowTarget.sceneView, handler);\n        }\n\n        public static void RemoveDropHandler(HierarchyDropHandler handler)\n        {\n            RemoveDropHandler(DragAndDropWindowTarget.hierarchy, handler);\n        }\n\n        public static void RemoveDropHandler(InspectorDropHandler handler)\n        {\n            RemoveDropHandler(DragAndDropWindowTarget.inspector, handler);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/DrivenPropertyManagerInternal.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Collections;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/DrivenPropertyManagerInternal.bindings.h\")]\n    [StaticAccessor(\"DrivenPropertyManagerInternal\", StaticAccessorType.DoubleColon)]\n    internal class DrivenPropertyManagerInternal\n    {\n        extern public static bool IsDriven(Object target, string propertyPath);\n        extern public static bool IsDriving(Object driver, Object target, string propertyPath);\n        extern public static bool IsDrivingPartial(Object driver, Object target, string propertyPath);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/DrivenRectTransformUndo.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [InitializeOnLoad]\n    internal class DrivenRectTransformUndo\n    {\n        // Static constructor\n        static DrivenRectTransformUndo()\n        {\n            Undo.willFlushUndoRecord += ForceUpdateCanvases;\n            // After undo or redo performed, the 'driven values' & 'driven properties mask' need to be updated.\n            Undo.undoRedoEvent += OnUndoRedoPerformed;\n        }\n\n        static void ForceUpdateCanvases()\n        {\n            Canvas.ForceUpdateCanvases();\n        }\n\n        static void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            Canvas.ForceUpdateCanvases();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/DropInfo.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditor\n{\n    internal class DropInfo\n    {\n        internal enum Type\n        {\n            // The window will be inserted as a tab into dropArea\n            Tab = 0,\n            // The window will be a new pane (inside a scrollView)\n            Pane = 1,\n            // A new window should be created.\n            Window\n        }\n\n        public DropInfo(IDropArea source)\n        {\n            dropArea = source;\n        }\n\n        // Who claimed the drop?\n        public IDropArea dropArea;\n\n        // Extra data for the recipient to communicate between DragOVer and PerformDrop\n        public object userData = null;\n\n        // Which type of dropzone are we looking for?\n        public Type type = Type.Window;\n        // Where should the preview end up on screen.\n        public Rect rect;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/DynamicHints/DynamicHintContent.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    /// <summary>\n    /// Add this interface to all classes that can generate part of the content of a dynamic hint by examining an instance of an object\n    /// </summary>\n    internal interface IComponentDynamicHintContentGenerator\n    {\n        VisualElement CreateContent(GameObject obj);\n    }\n\n    /// <summary>\n    /// Add this interface to all classes that can generate part of the content of a dynamic hint by examining an asset\n    /// </summary>\n    internal interface IAssetDynamicHintContentGenerator\n    {\n        VisualElement CreateContent(UnityEngine.Object obj);\n    }\n\n    /// <summary>\n    /// Base class for all classes that can generate part of the content of a dynamic hint by examining an instance of a ScriptableObject\n    /// </summary>\n    /// <typeparam name=\"T\">The component for which to generate the content</typeparam>\n    internal abstract class ScriptableObjectContentGenerator<T> : IAssetDynamicHintContentGenerator where T : ScriptableObject\n    {\n        readonly string m_Title;\n        static T s_ComponentCache;\n\n        protected ScriptableObjectContentGenerator(string title)\n        {\n            m_Title = title;\n        }\n\n        /// <summary>\n        /// Defines the logic with which the object is examined to generate the content of the hint\n        /// </summary>\n        /// <param name=\"root\">The root visualElement of the hint</param>\n        /// <param name=\"objectToAnalyze\">The object this Generator will examine</param>\n        protected abstract void GenerateContent(VisualElement root, T objectToAnalyze);\n\n        public VisualElement CreateContent(UnityEngine.Object obj)\n        {\n            s_ComponentCache = obj as T;\n            if (s_ComponentCache == null) { return null; }\n\n            VisualElement content = new VisualElement();\n            content.style.marginTop = 4;\n\n            Label title = new Label();\n            title.style.marginBottom = 2;\n            title.style.unityFontStyleAndWeight = FontStyle.Bold;\n            title.text = m_Title;\n            content.Add(title);\n\n            GenerateContent(content, s_ComponentCache);\n            return content;\n        }\n\n        protected VisualElement AddInfoField(string label, string value)\n        {\n            VisualElement root = new VisualElement();\n            root.style.flexDirection = FlexDirection.Row;\n            root.style.flexGrow = 1;\n            root.style.height = 15;\n            root.Add(new Label(label));\n            Label valueLabel = new Label(value);\n            root.Add(valueLabel);\n            valueLabel.style.unityTextAlign = TextAnchor.UpperRight;\n            return root;\n        }\n    }\n\n    /// <summary>\n    /// Base class for all classes that can generate part of the content of a dynamic hint by examining an instance of a GameObject\n    /// </summary>\n    /// <typeparam name=\"T\">The component for which to generate the content</typeparam>\n    internal abstract class ComponentContentGenerator<T> : IComponentDynamicHintContentGenerator where T : Component\n    {\n        readonly string m_Title;\n        static readonly List<T> s_ComponentCache = new List<T>();\n\n        protected ComponentContentGenerator(string title)\n        {\n            m_Title = title;\n        }\n\n        /// <summary>\n        /// Defines the logic with which the targeted Components of an object are examined to generate the content of the hint\n        /// </summary>\n        /// <param name=\"root\">The root visualElement of the hint</param>\n        /// <param name=\"components\">The components this Generator will examine</param>\n        protected abstract void GenerateContent(VisualElement root, List<T> components);\n\n        public VisualElement CreateContent(GameObject obj)\n        {\n            obj.GetComponents(s_ComponentCache);\n            if (s_ComponentCache.Count == 0) { return null; }\n\n            VisualElement content = new VisualElement();\n            content.style.marginTop = 4;\n\n            Label title = new Label();\n            title.style.marginBottom = 2;\n            title.style.unityFontStyleAndWeight = FontStyle.Bold;\n            title.text = m_Title;\n            content.Add(title);\n\n            GenerateContent(content, s_ComponentCache);\n            return content;\n        }\n\n        protected VisualElement AddInfoField(string label, string value)\n        {\n            VisualElement root = new VisualElement();\n            root.style.flexDirection = FlexDirection.Row;\n            root.style.flexGrow = 1;\n            root.style.height = 15;\n            root.Add(new Label(label));\n            Label valueLabel = new Label(value);\n            root.Add(valueLabel);\n            valueLabel.style.unityTextAlign = TextAnchor.UpperRight;\n            return root;\n        }\n    }\n\n    /// <summary>\n    /// Base class for all dynamic hints\n    /// </summary>\n    internal abstract class DynamicHintContent\n    {\n        protected VisualElement root;\n        bool m_Extended;\n\n        /// <summary>\n        /// Gets or sets the state of the hint.\n        /// </summary>\n        public bool Extended\n        {\n            get { return m_Extended; }\n            set\n            {\n                if (m_Extended == value) { return; }\n\n                m_Extended = value;\n                OnExtendedStateChanged(m_Extended);\n            }\n        }\n\n        /// <summary>\n        /// Called whenever the Extended state of the hint changes.\n        /// </summary>\n        /// <param name=\"extended\"></param>\n        protected internal virtual void OnExtendedStateChanged(bool extended) {}\n\n        /// <summary>\n        /// Override this to update the content of the dynamic hint every editor frame (I.E: when playing videos)\n        /// </summary>\n        internal virtual void Update() {}\n\n        /// <summary>\n        /// Override this to load the UXML + USS of your dynamic hint and to initialize its UI logic and callbacks\n        /// </summary>\n        /// <returns></returns>\n        protected internal virtual VisualElement CreateContent() { return null; }\n\n        /// <summary>\n        /// Override this in order to return the right dimensions dependning on the dynamic hints' state and displayed controls\n        /// </summary>\n        /// <returns></returns>\n        protected internal virtual Vector2 GetContentSize() { return Vector2.zero; }\n\n        internal Rect GetRect() { return root.contentRect; }\n\n        /// <summary>\n        /// Loads the default StyleSheet according to the desired type of dynamic hint.\n        /// The StyleSheet will be added as the first StyleSheet of the element.\n        /// </summary>\n        /// <param name=\"element\">The element to which the StyleSheet will be added to. This is usually the root of your dynamic hint.</param>\n        /// <param name=\"useInstanceTooltipStyleSheet\">If true, the StyleSheet commonly used in dynamic hints that represent data of an instance of an Object will be applied.\n        /// Otherwise, the style commonly applied to dynamic hints that explain how properties or editor tools work will be applied.</param>\n        protected void AddDefaultStyleSheetAsFirstTo(VisualElement element, bool useInstanceTooltipStyleSheet)\n        {\n            StyleSheet defaultStyleSheet = useInstanceTooltipStyleSheet ? DynamicHintUtility.GetDefaultInstanceDynamicHintStyleSheet()\n                : DynamicHintUtility.GetDefaultDynamicHintStyleSheet();\n\n            if (element.styleSheets.count > 0)\n            {\n                element.styleSheetList.Insert(0, defaultStyleSheet);\n            }\n            else\n            {\n                element.styleSheets.Add(defaultStyleSheet);\n            }\n        }\n\n        internal string ToTooltipString() { return DynamicHintUtility.Serialize(this); }\n\n        /// <summary>\n        /// Converts the hint to a string\n        /// </summary>\n        /// <param name=\"hint\">the hint to convert</param>\n        public static implicit operator string(DynamicHintContent hint) { return hint.ToTooltipString(); }\n    }\n\n    /// <summary>\n    /// Tells the Dynamic Hint system which method to use to generate the Dynamic Hint of a specific class.\n    /// Must be placed on a static method.\n    /// </summary>\n    [AttributeUsage(AttributeTargets.Method)]\n    internal /*sealed*/ class DynamicHintGeneratorAttribute : Attribute //todo: make this sealed once it becomes public. For now, it can't be sealed as internal bridges need to inherit from it\n    {\n        internal Type m_Type;\n\n        public DynamicHintGeneratorAttribute(Type type)\n        {\n            m_Type = type;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/DynamicHints/DynamicHintUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing static UnityEditorInternal.InternalEditorUtility;\n\nnamespace UnityEditor\n{\n    /// <summary>\n    /// An utility class that provides Dynamic Hints' functionalities\n    /// </summary>\n    internal static class DynamicHintUtility\n    {\n        internal static string Serialize(DynamicHintContent hint)\n        {\n            return $\"[Custom Tooltip]<type>{hint.GetType().AssemblyQualifiedName}</type><content>{JsonUtility.ToJson(hint)}</content>\";\n        }\n\n        internal static DynamicHintContent Deserialize(string hint)\n        {\n            if (!hint.StartsWith(\"[Custom Tooltip]\")) { return null; }\n\n            int typeStart = hint.IndexOf(\"<type>\", StringComparison.InvariantCulture) + \"<type>\".Length;\n            int typeLength = hint.IndexOf(\"</type>\", StringComparison.InvariantCulture) - typeStart;\n            if (typeStart < 0 || typeLength < 0) { return null; }\n\n            var rawType = hint.Substring(typeStart, typeLength);\n            var type = Type.GetType(rawType);\n\n            int contentStart = hint.IndexOf(\"<content>\", StringComparison.InvariantCulture) + \"<content>\".Length;\n            int contentLength = hint.IndexOf(\"</content>\", StringComparison.InvariantCulture) - contentStart;\n            if (contentStart < 0 || contentLength < 0) { return null; }\n\n            var content = hint.Substring(contentStart, contentLength);\n            return JsonUtility.FromJson(content, type) as DynamicHintContent;\n        }\n\n        /// <summary>\n        /// Loads the StyleSheet that is usually applied to DynamicHints that show how a tool or property works.\n        /// </summary>\n        /// <returns>The StyleSheet</returns>\n        internal static StyleSheet GetDefaultDynamicHintStyleSheet()\n        {\n            return EditorGUIUtility.Load(\"StyleSheets/DynamicHints/DynamicHintCommon.uss\") as StyleSheet;\n        }\n\n        /// <summary>\n        /// Loads the StyleSheet that is usually applied to DynamicHints that represent data about the components of an instance of an object.\n        /// </summary>\n        /// <returns>The StyleSheet</returns>\n        internal static StyleSheet GetDefaultInstanceDynamicHintStyleSheet()\n        {\n            return EditorGUIUtility.Load(\"StyleSheets/DynamicHints/InstanceDynamicHintCommon.uss\") as StyleSheet;\n        }\n\n        /// <summary>\n        /// Closes the current DynamicHint being displayed\n        /// </summary>\n        public static void CloseCurrentHint()\n        {\n            TooltipView.Close();\n        }\n\n        /// <summary>\n        /// Draws a hint at a specific position of the screen.\n        /// </summary>\n        /// <param name=\"hint\">The content of the hint</param>\n        /// <param name=\"rect\">The rect where the hint will be drawn. The top-left corner of the hint will start at the X coordinate</param>\n        public static void DrawHintAt(DynamicHintContent hint, Rect rect)\n        {\n            TooltipView.s_ForceExtensionOfNextDynamicHint = true;\n            TooltipView.Show(hint.ToTooltipString(), rect);\n        }\n\n        /// <summary>\n        /// Draws a hint next to an object in the Hierarchy, if it exists and the Hierarchy is visible.\n        /// </summary>\n        /// <param name=\"hint\">The content of the hint</param>\n        /// <param name=\"objectInHierarchy\">The object the hint will be drawn next to</param>\n        public static void DrawHintNextToHierarchyObject(DynamicHintContent hint, GameObject objectInHierarchy)\n        {\n            if (!EditorWindow.HasOpenInstances<SceneHierarchyWindow>())\n            {\n                return;\n            }\n\n            EditorWindow.FocusWindowIfItsOpen<SceneHierarchyWindow>();\n\n            Rect rectOfObject = GetRectOfObjectInHierarchy(objectInHierarchy, out bool objectWasFound);\n\n            if (!objectWasFound) { return; }\n\n            AdaptRectToHierarchy(out Rect rectOfHint, GUIUtility.GUIToScreenPoint(new Vector2(rectOfObject.x, rectOfObject.y)), rectOfObject);\n            DrawHintAt(hint, rectOfHint);\n        }\n\n        /// <summary>\n        /// Draws a hint next to a visible asset in the Project Window.\n        /// </summary>\n        /// <param name=\"hint\">The content of hint tooltip</param>\n        /// <param name=\"objectToFind\">The object the hint will be drawn next to</param>\n        public static void DrawHintNextToProjectAsset(DynamicHintContent hint, UnityEngine.Object objectToFind)\n        {\n            if (!EditorWindow.HasOpenInstances<ProjectBrowser>())\n            {\n                return;\n            }\n\n            EditorWindow.FocusWindowIfItsOpen<ProjectBrowser>();\n\n            Rect rectOfObject = GetRectOfObjectInProjectExplorer(objectToFind, out bool objectWasFound);\n\n            if (!objectWasFound) { return; }\n\n            AdaptRectToProjectWindow(out Rect rectOfHint, GUIUtility.GUIToScreenPoint(new Vector2(rectOfObject.x, rectOfObject.y)));\n            DrawHintAt(hint, rectOfHint);\n        }\n\n        /// <summary>\n        /// Draws a hint next to a visible field in the Inspector.\n        /// </summary>\n        /// <param name=\"hint\">The content of the hint</param>\n        /// <param name=\"fieldPathInClass\">The path of the field within the class</param>\n        /// <param name=\"targetType\">The type of the class that contains the field</param>\n        public static void DrawHintNextToInspectorField(DynamicHintContent hint, string fieldPathInClass, Type targetType)\n        {\n            if (!EditorWindow.HasOpenInstances<InspectorWindow>())\n            {\n                return;\n            }\n\n            EditorWindow.FocusWindowIfItsOpen<InspectorWindow>();\n\n            Rect rectOfObject = GetRectOfFieldInInspector(fieldPathInClass, targetType, out bool objectWasFound);\n\n            if (!objectWasFound) { return; }\n\n            AdaptRectToInspector(out Rect rectOfHint, GUIUtility.GUIToScreenPoint(new Vector2(rectOfObject.x, rectOfObject.y)));\n            DrawHintAt(hint, rectOfHint);\n        }\n\n        /// <summary>\n        /// Draws a hint at a Rect, if the mouse is in it.\n        /// </summary>\n        /// <param name=\"hint\">The hint to draw</param>\n        /// <param name=\"tooltipRect\">The rect where the hint will be drawn</param>\n        internal static void DrawMouseTooltip(DynamicHintContent hint, Rect tooltipRect)\n        {\n            GUIStyle.SetMouseTooltip(hint.ToTooltipString(), tooltipRect);\n        }\n\n        internal static void DrawHint(Rect hintTriggerRect, Vector2 mousePosition, AssetReference assetReference)\n        {\n            if (!hintTriggerRect.Contains(mousePosition) || !GUIClip.visibleRect.Contains(mousePosition)) { return; }\n\n            string assetPath = AssetDatabase.GUIDToAssetPath(assetReference.guid);\n            var assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);\n\n            if (assetType == null) //this means the object or its base script has been deleted and is \"Missing\"\n            {\n                return;\n            }\n\n            var hintGenerators = TypeCache.GetMethodsWithAttribute<DynamicHintGeneratorAttribute>();\n            if (assetType.IsSubclassOf(typeof(ScriptableObject)))\n            {\n                DynamicHintContent hint = GetDynamicHintContentOf(hintGenerators, assetType, assetPath);\n                if (hint != null)\n                {\n                    DrawMouseTooltip(hint, hintTriggerRect);\n                }\n                return;\n            }\n\n            if (assetType == typeof(GameObject))\n            {\n                /* GameObjects can have multiple components with custom tooltips\n                 * so for now we'll just display the first one.\n                 * If needed, we could:\n                 * 1) Implement a \"priority system\" (like OrderedCallbacks)\n                 * 2) Display one big tooltip made up with all elements from custom tooltip\n                 */\n\n                GameObject assetGameObject = (GetLoadedObjectFromInstanceID(assetReference.instanceID) as GameObject);\n                if (!assetGameObject)\n                {\n                    /* this seems to happen non-deterministically at project startup depending of what the user is hovering when the editor opens,\n                     * or while the user is scrolling a list of objects and hovers one of them casually, even if the object hovered is actually a\n                     * GameObject.\n                     * */\n                    return;\n                }\n\n                foreach (var component in assetGameObject.GetComponents<Component>())\n                {\n                    if (component == null) { continue; } //this means its script has been deleted and is \"Missing\"\n\n                    DynamicHintContent hint = GetDynamicHintContentOf(hintGenerators, component.GetType(), string.Empty, component);\n                    if (hint == null) { continue; }\n\n                    DrawMouseTooltip(hint, hintTriggerRect);\n                    return;\n                }\n            }\n        }\n\n        static DynamicHintContent GetDynamicHintContentOf(TypeCache.MethodCollection hintGenerators, Type targetType, string assetPath = \"\", Component targetAsComponent = null)\n        {\n            foreach (var hintGenerator in hintGenerators)\n            {\n                foreach (var attribute in hintGenerator.GetCustomAttributes(typeof(DynamicHintGeneratorAttribute), false))\n                {\n                    if (targetType == (attribute as DynamicHintGeneratorAttribute).m_Type)\n                    {\n                        var target = targetAsComponent ? targetAsComponent : AssetDatabase.LoadMainAssetAtPath(assetPath);\n                        if (target)\n                        {\n                            return hintGenerator.Invoke(null, new[] { (object)target }) as DynamicHintContent;\n                        }\n                    }\n                }\n            }\n            return null;\n        }\n\n        static Rect GetRectOfObjectInHierarchy(GameObject objectToFind, out bool found)\n        {\n            return GetRectOfObjectInGUIView(nameof(SceneHierarchyWindow), objectToFind, out found);\n        }\n\n        static Rect GetRectOfObjectInProjectExplorer(UnityEngine.Object objectToFind, out bool found)\n        {\n            return GetRectOfObjectInGUIView(nameof(ProjectBrowser), objectToFind, out found);\n        }\n\n        static Rect GetRectOfFieldInInspector(string fieldPathInClass, Type targetType, out bool found)\n        {\n            string viewName = nameof(InspectorWindow);\n            var allViews = new List<GUIView>();\n            GUIViewDebuggerHelper.GetViews(allViews);\n\n            var propertyInstructions = new List<IMGUIPropertyInstruction>(32);\n\n            foreach (var view in allViews)\n            {\n                if (view.GetViewName() != viewName) { continue; } //todo: we should have a way to reference the window without using its name\n\n                GUIViewDebuggerHelper.DebugWindow(view);\n                view.RepaintImmediately();\n                GUIViewDebuggerHelper.GetPropertyInstructions(propertyInstructions);\n                var targetTypeName = targetType.AssemblyQualifiedName;\n\n                foreach (var instruction in propertyInstructions) //todo: we should have a way to reference hierarchy objects without using their names\n                {\n                    if (instruction.targetTypeName == targetTypeName\n                        && instruction.path == fieldPathInClass)\n                    {\n                        found = true;\n                        return instruction.rect;\n                    }\n                }\n                var drawInstructions = new List<IMGUIDrawInstruction>(32);\n                GUIViewDebuggerHelper.GetDrawInstructions(drawInstructions);\n\n                // Property instruction not found\n                // Let's see if we can find any of the ancestor instructions to allow the user to unfold\n                Rect regionRect = new Rect();\n                found = FindAncestorPropertyRegion(fieldPathInClass, targetTypeName, drawInstructions, propertyInstructions, ref regionRect);\n                return regionRect;\n            }\n            found = false;\n            return Rect.zero;\n        }\n\n        /// <summary>\n        /// Gets the field path of the parameter, relative to the class in which it is declared\n        /// </summary>\n        /// <param name=\"field\"></param>\n        /// <returns>The field path of the parameter, relative to the class in which it is declared</returns>\n        public static string GetFieldPathInClass(object field)\n        {\n            if (field == null) { return string.Empty; }\n\n            Type fieldType = field.GetType();\n            string typeAsString = fieldType.ToString();\n            bool isArray = typeAsString.EndsWithIgnoreCaseFast(\"[]]\");\n            if (isArray)\n            {\n                return fieldType.GetProperties()[0].Name + \".Array.size\";\n            }\n            return fieldType.GetProperties()[0].Name;\n        }\n\n        /* todo: the following method seems to behave differently for properties representing Arrays, compared to how it behaves for non-array properties.\n         * What happens is that regionRect becomes the \"wrong side\" of the property in the inspector */\n        static bool FindAncestorPropertyRegion(string propertyPath, string targetTypeName,\n            List<IMGUIDrawInstruction> drawInstructions, List<IMGUIPropertyInstruction> propertyInstructions,\n            ref Rect regionRect)\n        {\n            while (true)\n            {\n                // Remove last component of property path\n                var lastIndexOfDelimiter = propertyPath.LastIndexOf(\".\");\n                if (lastIndexOfDelimiter < 1)\n                {\n                    // No components left, give up\n                    return false;\n                }\n                propertyPath = propertyPath.Substring(0, lastIndexOfDelimiter);\n                foreach (var instruction in propertyInstructions)\n                {\n                    if (instruction.targetTypeName != targetTypeName || instruction.path != propertyPath) { continue; }\n                    regionRect = instruction.rect;\n\n                    // The property rect itself does not contain the foldout arrow\n                    // Expand region to include all draw instructions for this property\n                    var unifiedInstructions = new List<IMGUIInstruction>(128);\n                    GUIViewDebuggerHelper.GetUnifiedInstructions(unifiedInstructions);\n                    var collectDrawInstructions = false;\n                    var propertyBeginLevel = 0;\n                    foreach (var unifiedInstruction in unifiedInstructions)\n                    {\n                        if (collectDrawInstructions)\n                        {\n                            if (unifiedInstruction.level <= propertyBeginLevel) { break; }\n                            if (unifiedInstruction.type != InstructionType.kStyleDraw) { continue; }\n\n                            var drawRect = drawInstructions[unifiedInstruction.typeInstructionIndex].rect;\n                            if (drawRect.xMin < regionRect.xMin)\n                            {\n                                regionRect.xMin = drawRect.xMin;\n                            }\n                            if (drawRect.yMin < regionRect.yMin)\n                            {\n                                regionRect.yMin = drawRect.yMin;\n                            }\n                            if (drawRect.xMax > regionRect.xMax)\n                            {\n                                regionRect.xMax = drawRect.xMax;\n                            }\n                            if (drawRect.yMax > regionRect.yMax)\n                            {\n                                regionRect.yMax = drawRect.yMax;\n                            }\n                        }\n                        else\n                        {\n                            if (unifiedInstruction.type != InstructionType.kPropertyBegin) { continue; }\n\n                            var propertyInstruction = propertyInstructions[unifiedInstruction.typeInstructionIndex];\n                            if (propertyInstruction.targetTypeName == targetTypeName\n                                && propertyInstruction.path == propertyPath)\n                            {\n                                collectDrawInstructions = true;\n                                propertyBeginLevel = unifiedInstruction.level;\n                            }\n                        }\n                    }\n\n                    return true;\n                }\n            }\n        }\n\n        static Rect GetRectOfObjectInGUIView(string viewName, UnityEngine.Object objectToFind, out bool found)\n        {\n            var allViews = new List<GUIView>();\n            GUIViewDebuggerHelper.GetViews(allViews);\n\n            var drawInstructions = new List<IMGUIDrawInstruction>(32);\n            foreach (var view in allViews)\n            {\n                if (view.GetViewName() != viewName) { continue; } //todo: we should have a way to reference the window without using its name\n\n                GUIViewDebuggerHelper.DebugWindow(view);\n                view.RepaintImmediately();\n                GUIViewDebuggerHelper.GetDrawInstructions(drawInstructions);\n                foreach (var drawInstruction in drawInstructions) //todo: we should have a way to reference hierarchy objects without using their names\n                {\n                    //If we can reference the object represented by the draw instruction, we can find it like this\n                    /*if (drawInstruction.usedGUIContent.representedObject != null)\n                    {\n                        if (drawInstruction.usedGUIContent.representedObject == objectToFind)\n                        {\n                            found = true;\n                            return drawInstruction.rect;\n                        }\n                    }*/\n\n                    if (drawInstruction.usedGUIContent.text != objectToFind.name) { continue; }\n                    found = true;\n                    return drawInstruction.rect;\n                }\n                found = false;\n                return Rect.zero;\n            }\n            found = false;\n            return Rect.zero;\n        }\n\n        static void AdaptRectToHierarchy(out Rect rectOfHint, Vector2 screenPositionOfObject, Rect rectOfObject)\n        {\n            rectOfHint = new Rect();\n            rectOfHint.x = screenPositionOfObject.x + rectOfObject.width;\n            rectOfHint.y = screenPositionOfObject.y;\n            rectOfHint.width = 0;\n            rectOfHint.height = 0;\n        }\n\n        static void AdaptRectToInspector(out Rect rectOfHint, Vector2 screenPositionOfObject)\n        {\n            rectOfHint = new Rect();\n            rectOfHint.x = screenPositionOfObject.x;\n            rectOfHint.y = screenPositionOfObject.y;\n            rectOfHint.width = 0;\n            rectOfHint.height = 0;\n        }\n\n        static void AdaptRectToProjectWindow(out Rect rectOfHint, Vector2 screenPositionOfObject)\n        {\n            const int offsetForImprovedPositioning = 200;\n\n            rectOfHint = new Rect();\n            rectOfHint.x = screenPositionOfObject.x + offsetForImprovedPositioning;\n            rectOfHint.y = screenPositionOfObject.y;\n            rectOfHint.width = 0;\n            rectOfHint.height = 0;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorApplication.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Reflection;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.SceneManagement;\nusing UnityEditor.SceneManagement;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    // Main Application class.\n    [NativeHeader(\"Editor/Mono/EditorApplication.bindings.h\")]\n    [NativeHeader(\"Editor/Src/ScriptCompilation/ScriptCompilationPipeline.h\")]\n    [NativeHeader(\"Runtime/BaseClasses/TagManager.h\")]\n    [NativeHeader(\"Runtime/Camera/RenderSettings.h\")]\n    [NativeHeader(\"Runtime/Input/TimeManager.h\")]\n    [NativeHeader(\"Editor/Src/ProjectVersion.h\")]\n    [NativeHeader(\"Runtime/Misc/BuildSettings.h\")]\n    [NativeHeader(\"Runtime/Interfaces/ILicensing.h\")]\n    [StaticAccessor(\"EditorApplicationBindings\", StaticAccessorType.DoubleColon)]\n    public sealed partial class EditorApplication\n    {\n        internal static extern string kLastOpenedScene\n        {\n            [NativeMethod(\"GetLastOpenedScenePref\")]\n            get;\n        }\n\n        // Load the level at /path/ in play mode.\n        [Obsolete(\"Use EditorSceneManager.LoadSceneInPlayMode instead.\")]\n        public static void LoadLevelInPlayMode(string path)\n        {\n            LoadSceneParameters parameters = new LoadSceneParameters {loadSceneMode = LoadSceneMode.Single};\n            EditorSceneManager.LoadSceneInPlayMode(path, parameters);\n        }\n\n        // Load the level at /path/ additively in play mode.\n        [Obsolete(\"Use EditorSceneManager.LoadSceneInPlayMode instead.\")]\n        public static void LoadLevelAdditiveInPlayMode(string path)\n        {\n            LoadSceneParameters parameters = new LoadSceneParameters {loadSceneMode = LoadSceneMode.Additive};\n            EditorSceneManager.LoadSceneInPlayMode(path, parameters);\n        }\n\n        // Load the level at /path/ in play mode asynchronously.\n        [Obsolete(\"Use EditorSceneManager.LoadSceneAsyncInPlayMode instead.\")]\n        public static AsyncOperation LoadLevelAsyncInPlayMode(string path)\n        {\n            LoadSceneParameters parameters = new LoadSceneParameters {loadSceneMode = LoadSceneMode.Single};\n            return EditorSceneManager.LoadSceneAsyncInPlayMode(path, parameters);\n        }\n\n        // Load the level at /path/ additively in play mode asynchronously.\n        [Obsolete(\"Use EditorSceneManager.LoadSceneAsyncInPlayMode instead.\")]\n        public static AsyncOperation LoadLevelAdditiveAsyncInPlayMode(string path)\n        {\n            LoadSceneParameters parameters = new LoadSceneParameters {loadSceneMode = LoadSceneMode.Additive};\n            return EditorSceneManager.LoadSceneAsyncInPlayMode(path, parameters);\n        }\n\n        // Open another project.\n        public static void OpenProject(string projectPath, params string[] args)\n        {\n            OpenProjectInternal(projectPath, args);\n        }\n\n        private static extern void OpenProjectInternal(string projectPath, string[] args);\n\n        internal static extern void OpenFileGeneric(string path);\n\n        // Saves all serializable assets that have not yet been written to disk (eg. Materials)\n        [System.Obsolete(\"Use AssetDatabase.SaveAssets instead (UnityUpgradable) -> AssetDatabase.SaveAssets()\", true)]\n        public static void SaveAssets() {}\n\n        // Is editor currently in play mode?\n        public static extern bool isPlaying\n        {\n            get;\n            set;\n        }\n\n        public static void EnterPlaymode()\n        {\n            isPlaying = true;\n        }\n\n        public static void ExitPlaymode()\n        {\n            isPlaying = false;\n        }\n\n        // Is editor either currently in play mode, or about to switch to it? (RO)\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        public static extern bool isPlayingOrWillChangePlaymode\n        {\n            [NativeMethod(\"IsPlayingOrWillEnterExitPlaymode\")]\n            get;\n        }\n\n        // Perform a single frame step.\n        [StaticAccessor(\"GetApplication().GetPlayerLoopController()\", StaticAccessorType.Dot)]\n        public static extern void Step();\n\n        // Is editor currently paused?\n        [StaticAccessor(\"GetApplication().GetPlayerLoopController()\", StaticAccessorType.Dot)]\n        public static extern bool isPaused\n        {\n            [NativeMethod(\"IsPaused\")]\n            get;\n            [NativeMethod(\"SetPaused\")]\n            set;\n        }\n\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        internal static extern bool IsInitialized();\n\n        // Is editor currently compiling scripts? (RO)\n        public static bool isCompiling\n        {\n            get\n            {\n                EditorCompilationInterface.IsCompiling(out var isCompiling);\n                return isCompiling;\n            }\n        }\n\n        // Is editor currently updating? (RO)\n        public static extern bool isUpdating\n        {\n            get;\n        }\n\n        // Is remote connected to a client app?\n        public static extern bool isRemoteConnected\n        {\n            get;\n        }\n\n        [Obsolete(\"ScriptingRuntimeVersion has been deprecated in 2019.3 due to the removal of legacy mono\")]\n        public static ScriptingRuntimeVersion scriptingRuntimeVersion\n        {\n            get { return ScriptingRuntimeVersion.Latest; }\n        }\n\n        [StaticAccessor(\"GetILicensing()\", StaticAccessorType.Arrow)]\n        internal static extern string GetLicenseType();\n\n        // Prevents loading of assemblies when it is inconvenient.\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        public static extern void LockReloadAssemblies();\n\n        //  Must be called after LockReloadAssemblies, to reenable loading of assemblies.\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        public static extern void UnlockReloadAssemblies();\n\n        //  Check if assemblies are unlocked.\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        internal static extern bool CanReloadAssemblies();\n\n        private static extern bool ExecuteMenuItemInternal(string menuItemPath, bool logErrorOnUnfoundItem);\n\n        // Invokes the menu item in the specified path.\n        public static bool ExecuteMenuItem(string menuItemPath)\n        {\n            var sanitizedPath = MenuService.SanitizeMenuItemName(menuItemPath);\n            var isDefaultMode = ModeService.currentId == ModeService.k_DefaultModeId;\n            var result = ExecuteMenuItemInternal(sanitizedPath, isDefaultMode);\n            if (result)\n                return true;\n\n            if (!isDefaultMode)\n            {\n                // Check if the menu was found first. If so, it means that the menu just\n                // didn't pass validation. No need to check further.\n                if (Menu.MenuItemExists(sanitizedPath))\n                    return false;\n\n                var menuItems = TypeCache.GetMethodsWithAttribute<MenuItem>();\n                MethodInfo validateItem = null;\n                MethodInfo executeItem = null;\n                foreach (var item in menuItems)\n                {\n                    MenuItem itemData = (MenuItem)item.GetCustomAttributes(typeof(MenuItem), false)[0];\n                    var hotKeyIndex = Menu.FindHotkeyStartIndex(itemData.menuItem);\n                    var hasHotkey = hotKeyIndex != -1 && hotKeyIndex != itemData.menuItem.Length;\n                    bool matches;\n                    if (!hasHotkey)\n                    {\n                        matches = itemData.menuItem == sanitizedPath;\n                    }\n                    else\n                    {\n                        var stringView = itemData.menuItem.AsSpan(0, hotKeyIndex);\n                        stringView = stringView.TrimEnd();\n                        matches = stringView == sanitizedPath;\n                    }\n                    if (!matches)\n                        continue;\n\n                    if (itemData.validate)\n                        validateItem = item;\n                    else\n                        executeItem = item;\n\n                    if (validateItem != null && executeItem != null)\n                        break;\n                }\n\n                if (validateItem != null)\n                {\n                    if (!ExecuteMenuItem(validateItem, true))\n                        return false;\n                }\n\n                if (executeItem != null)\n                {\n                    return ExecuteMenuItem(executeItem, false);\n                }\n\n                Debug.LogError($\"ExecuteMenuItem failed because there is no menu named '{menuItemPath}'\");\n            }\n\n            return false;\n        }\n\n        static bool ExecuteMenuItem(MethodInfo menuMethodInfo, bool validate)\n        {\n            if (menuMethodInfo.GetParameters().Length == 0)\n            {\n                var result = menuMethodInfo.Invoke(null, new object[0]);\n                return !validate || (bool)result;\n            }\n\n            if (menuMethodInfo.GetParameters()[0].ParameterType == typeof(MenuCommand))\n            {\n                var result = menuMethodInfo.Invoke(null, new[] { new MenuCommand(null) });\n                return !validate || (bool)result;\n            }\n            return false;\n        }\n\n        // Validates the menu item in the specific path\n        internal static extern bool ValidateMenuItem(string menuItemPath);\n\n        // Like ExecuteMenuItem, but applies action to specified GameObjects if the menu action supports it.\n        internal static extern  bool ExecuteMenuItemOnGameObjects(string menuItemPath, GameObject[] objects);\n\n        // Like ExecuteMenuItem, but applies action to specified GameObjects if the menu action supports it.\n        internal static extern  bool ExecuteMenuItemWithTemporaryContext(string menuItemPath, Object[] objects);\n\n        // Path to the Unity editor contents folder (RO)\n        public static extern string applicationContentsPath\n        {\n            [FreeFunction(\"GetApplicationContentsPath\", IsThreadSafe = true)]\n            get;\n        }\n\n        // Returns the path to the Unity editor application (RO)\n        public static extern string applicationPath\n        {\n            [FreeFunction(\"GetApplicationPath\", IsThreadSafe = true)]\n            get;\n        }\n\n        // Returns true if resources are being built\n        internal static extern bool isBuildingAnyResources\n        {\n            [FreeFunction(\"IsBuildingAnyResources\")]\n            get;\n        }\n\n        // Returns true if the Package Manager is disabled\n        internal static extern bool isPackageManagerDisabled\n        {\n            [FreeFunction(\"IsPackageManagerDisabled\")]\n            get;\n        }\n\n        public static extern bool isCreateFromTemplate\n        {\n            [FreeFunction(\"IsCreateFromTemplate\")]\n            get;\n        }\n\n        internal static extern string userJavascriptPackagesPath\n        {\n            get;\n        }\n\n        public static extern bool isTemporaryProject\n        {\n            [FreeFunction(\"IsTemporaryProject\")]\n            get;\n        }\n\n        [NativeThrows]\n        public static extern void SetTemporaryProjectKeepPath(string path);\n\n        // Exit the Unity editor application.\n        public static extern void Exit(int returnValue);\n\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        internal static extern void SetSceneRepaintDirty();\n\n        public static void QueuePlayerLoopUpdate() { SetSceneRepaintDirty(); }\n\n        internal static extern void UpdateSceneIfNeeded();\n\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        public static extern void UpdateMainWindowTitle();\n\n        // Plays system beep sound.\n        [FreeFunction(\"UnityBeep\")]\n        public static extern void Beep();\n\n        internal static extern Object tagManager\n        {\n            [FreeFunction]\n            get;\n        }\n\n        internal static extern Object renderSettings\n        {\n            [FreeFunction]\n            get;\n        }\n\n        // The time since the editor was started (RO)\n        public static extern double timeSinceStartup\n        {\n            [FreeFunction]\n            get;\n        }\n\n        internal static extern string windowTitle\n        {\n            [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n            get;\n        }\n\n        internal static extern void CloseAndRelaunch(string[] arguments);\n\n        internal static extern void RequestCloseAndRelaunchWithCurrentArguments();\n\n        // Triggers the editor to restart, after which all scripts will be recompiled.\n        internal static void RestartEditorAndRecompileScripts()\n        {\n            // Clear the script assemblies so we compile after the restart.\n            EditorCompilationInterface.Instance.DeleteScriptAssemblies();\n\n            RequestCloseAndRelaunchWithCurrentArguments();\n        }\n\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        internal static extern void FileMenuNewScene();\n\n        [ThreadSafe]\n        internal static extern void SignalTick();\n\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        internal static extern void UpdateInteractionModeSettings();\n\n        internal static extern void UpdateTooltipsInPlayModeSettings();\n\n        [FreeFunction(\"GetProjectVersion().Write\")]\n        internal static extern void WriteVersion();\n\n        internal static extern GUID buildSessionGUID\n        {\n            [FreeFunction(\"GetBuildSettings().GetBuildSessionGUID\")]\n            get;\n        }\n\n        public static extern bool isFocused\n        {\n            [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n            get;\n\n            [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n            private set;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorApplication.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Text;\nusing UnityEngine.SceneManagement;\nusing UnityEngine;\nusing UnityEngine.Events;\nusing UnityEngine.Scripting;\nusing UnityEditorInternal;\nusing UnityEditor.Scripting;\nusing UnityEngine.TestTools;\nusing Unity.Profiling;\nusing UnityEditor.Profiling;\nusing UnityEditor.SceneManagement;\nusing UnityEditor.VersionControl;\nusing UnityEngine.Bindings;\nusing UnityEngine.Profiling;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    public enum PlayModeStateChange\n    {\n        EnteredEditMode,\n        ExitingEditMode,\n        EnteredPlayMode,\n        ExitingPlayMode,\n    }\n\n    // Must be kept in sync with enum in ScriptCompilationPipeline.h\n    internal enum ScriptChangesDuringPlayOptions\n    {\n        RecompileAndContinuePlaying = 0,\n        RecompileAfterFinishedPlaying = 1,\n        StopPlayingAndRecompile = 2\n    }\n\n    public enum PauseState\n    {\n        Paused,\n        Unpaused,\n    }\n\n    public class ApplicationTitleDescriptor\n    {\n        [Obsolete(\"Do not create your own instance of ApplicationTitleDescriptor. Use the one provided by EditorApplication.updateMainWindowTitle instead.\")]\n        public ApplicationTitleDescriptor(string projectName, string unityVersion, string activeSceneName, string targetName, bool codeCoverageEnabled)\n            : this(projectName, \"Unity\", unityVersion, activeSceneName, targetName, codeCoverageEnabled) {}\n\n        internal ApplicationTitleDescriptor(string projectName, string unityProductName, string unityVersion, string activeSceneName, string targetName, bool codeCoverageEnabled)\n        {\n            title = \"\";\n            this.projectName = projectName;\n            this.unityProductName = unityProductName;\n            this.unityVersion = unityVersion;\n            this.activeSceneName = activeSceneName;\n            this.targetName = targetName;\n            this.codeCoverageEnabled = codeCoverageEnabled;\n        }\n\n        public string title;\n        public string projectName { get; private set; }\n        public string unityProductName { get; private set; }\n        public string unityVersion { get; private set; }\n        public string activeSceneName { get; private set; }\n        public string targetName { get; private set; }\n        public bool codeCoverageEnabled { get; private set; }\n    }\n\n    public sealed partial class EditorApplication\n    {\n        internal static UnityAction projectWasLoaded;\n        internal static UnityAction editorApplicationQuit;\n\n        [RequiredByNativeCode]\n        static void Internal_ProjectWasLoaded()\n        {\n            projectWasLoaded?.Invoke();\n        }\n\n        [RequiredByNativeCode]\n        static bool Internal_EditorApplicationWantsToQuit()\n        {\n            if (!m_WantsToQuitEvent.hasSubscribers)\n                return true;\n\n            foreach (Func<bool> continueQuit in m_WantsToQuitEvent)\n            {\n                try\n                {\n                    if (!continueQuit())\n                        return false;\n                }\n                catch (Exception exception)\n                {\n                    Debug.LogWarningFormat(\"EditorApplication.wantsToQuit: Exception raised during quit event.\"\n                        + Environment.NewLine +\n                        \"Check the exception error's callstack to find out which event handler threw the exception.\");\n                    Debug.LogException(exception);\n\n                    if (InternalEditorUtility.isHumanControllingUs)\n                    {\n                        string st = exception.StackTrace;\n                        StringBuilder dialogText = new StringBuilder(\"An exception was thrown here:\");\n                        dialogText.AppendLine(Environment.NewLine);\n                        dialogText.AppendLine(st.Substring(0, st.IndexOf(Environment.NewLine)));\n\n                        bool abortQuit = !EditorUtility.DisplayDialog(\"Error while quitting\",\n                            dialogText.ToString(),\n                            \"Ignore\", \"Cancel Quit\");\n\n                        if (abortQuit)\n                            return false;\n                    }\n                }\n            }\n\n            return true;\n        }\n\n        [RequiredByNativeCode]\n        static void Internal_EditorApplicationQuit()\n        {\n            // VersionControlObject might depend on packages that cleanup themselves using quitting event.\n            // Therefore it's important to deactivate it beforehand.\n            VersionControlManager.Deactivate();\n\n            foreach (var evt in m_QuittingEvent)\n                evt();\n            editorApplicationQuit?.Invoke();\n            ScriptCompilers.Cleanup();\n        }\n\n        // Delegate to be called for every visible list item in the ProjectWindow on every OnGUI event.\n        public delegate void ProjectWindowItemCallback(string guid, Rect selectionRect);\n        public delegate void ProjectWindowItemInstanceCallback(int instanceID, Rect selectionRect);\n\n        // Delegate for OnGUI events for every visible list item in the ProjectWindow.\n        public static ProjectWindowItemCallback projectWindowItemOnGUI;\n        public static ProjectWindowItemInstanceCallback projectWindowItemInstanceOnGUI;\n\n        // Can be used to ensure repaint of the ProjectWindow.\n        public static void RepaintProjectWindow()\n        {\n            foreach (ProjectBrowser pb in ProjectBrowser.GetAllProjectBrowsers())\n                pb.Repaint();\n        }\n\n        // Can be used to ensure repaint of AnimationWindow\n        public static void RepaintAnimationWindow()\n        {\n            foreach (AnimEditor animEditor in AnimEditor.GetAllAnimationWindows())\n                animEditor.Repaint();\n        }\n\n        // Delegate to be called for every visible list item in the HierarchyWindow on every OnGUI event.\n        public delegate void HierarchyWindowItemCallback(int instanceID, Rect selectionRect);\n\n        // Delegate for OnGUI events for every visible list item in the HierarchyWindow.\n        public static HierarchyWindowItemCallback hierarchyWindowItemOnGUI;\n\n        // Delegate for refreshing hierarchies.\n        internal static CallbackFunction refreshHierarchy;\n\n        // Can be used to ensure repaint of the HierarchyWindow.\n        public static void RepaintHierarchyWindow()\n        {\n            refreshHierarchy?.Invoke();\n        }\n\n        // Delegate for dirtying hierarchy sorting.\n        internal static CallbackFunction dirtyHierarchySorting;\n\n        public static void DirtyHierarchyWindowSorting()\n        {\n            dirtyHierarchySorting?.Invoke();\n        }\n\n        // Delegate to be called from [[EditorApplication]] callbacks.\n        public delegate void CallbackFunction();\n\n        // Delegate to be called from [[EditorApplication]] contextual inspector callbacks.\n        public delegate void SerializedPropertyCallbackFunction(GenericMenu menu, SerializedProperty property);\n\n        // Delegate for generic updates.\n        public static CallbackFunction update;\n\n        private static DelegateWithPerformanceTracker<CallbackFunction> m_UpdateEvent = new DelegateWithPerformanceTracker<CallbackFunction>($\"{nameof(EditorApplication)}.{nameof(update)}\");\n        internal static event CallbackFunction tick;\n\n        public static event Func<bool> wantsToQuit\n        {\n            add => m_WantsToQuitEvent.Add(value);\n            remove => m_WantsToQuitEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<Func<bool>> m_WantsToQuitEvent = new EventWithPerformanceTracker<Func<bool>>($\"{nameof(EditorApplication)}.{nameof(wantsToQuit)}\");\n\n        public static event Action quitting\n        {\n            add => m_QuittingEvent.Add(value);\n            remove => m_QuittingEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<Action> m_QuittingEvent = new EventWithPerformanceTracker<Action>($\"{nameof(EditorApplication)}.{nameof(quitting)}\");\n\n        public static CallbackFunction delayCall;\n        private static DelegateWithPerformanceTracker<CallbackFunction> m_DelayCallEvent = new DelegateWithPerformanceTracker<CallbackFunction>($\"{nameof(EditorApplication)}.{nameof(delayCall)}\");\n\n        internal static Action CallDelayed(CallbackFunction action, double delaySeconds = 0.0f)\n        {\n            var startTime = DateTime.UtcNow;\n            CallbackFunction delayedHandler = null;\n            delayedHandler = new CallbackFunction(() =>\n            {\n                if ((DateTime.UtcNow - startTime).TotalSeconds < delaySeconds)\n                    return;\n                tick -= delayedHandler;\n                action();\n            });\n            tick += delayedHandler;\n            if (delaySeconds == 0f)\n                SignalTick();\n\n            return () => tick -= delayedHandler;\n        }\n\n        // Each time an object is (or a group of objects are) created, renamed, parented, unparented or destroyed this callback is raised.\n        public static event Action hierarchyChanged\n        {\n            add => m_HierarchyChangedEvent.Add(value);\n            remove => m_HierarchyChangedEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<Action> m_HierarchyChangedEvent = new EventWithPerformanceTracker<Action>($\"{nameof(EditorApplication)}.{nameof(hierarchyChanged)}\");\n\n        [Obsolete(\"Use EditorApplication.hierarchyChanged\")]\n        public static CallbackFunction hierarchyWindowChanged;\n\n        public static event Action projectChanged\n        {\n            add => m_ProjectChangedEvent.Add(value);\n            remove => m_ProjectChangedEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<Action> m_ProjectChangedEvent = new EventWithPerformanceTracker<Action>($\"{nameof(EditorApplication)}.{nameof(projectChanged)}\");\n\n        [Obsolete(\"Use EditorApplication.projectChanged\")]\n        public static CallbackFunction projectWindowChanged;\n\n        public static CallbackFunction searchChanged;\n\n        internal static CallbackFunction assetLabelsChanged;\n\n        internal static CallbackFunction assetBundleNameChanged;\n\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal static CallbackFunction fileMenuSaved;\n\n        // Delegate for changed keyboard modifier keys.\n        public static CallbackFunction modifierKeysChanged;\n\n        public static event Action<PauseState> pauseStateChanged\n        {\n            add => m_PauseStateChangedEvent.Add(value);\n            remove => m_PauseStateChangedEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<Action<PauseState>> m_PauseStateChangedEvent = new EventWithPerformanceTracker<Action<PauseState>>($\"{nameof(EditorApplication)}.{nameof(pauseStateChanged)}\");\n\n        public static event Action<PlayModeStateChange> playModeStateChanged\n        {\n            add => m_PlayModeStateChangedEvent.Add(value);\n            remove => m_PlayModeStateChangedEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<Action<PlayModeStateChange>> m_PlayModeStateChangedEvent = new EventWithPerformanceTracker<Action<PlayModeStateChange>>($\"{nameof(EditorApplication)}.{nameof(playModeStateChanged)}\");\n\n        [Obsolete(\"Use EditorApplication.playModeStateChanged and/or EditorApplication.pauseStateChanged\")]\n        public static CallbackFunction playmodeStateChanged;\n\n        // Global key up/down or mouse up/down/drag events that were not handled by anyone\n        internal static CallbackFunction globalEventHandler;\n        internal static CallbackFunction shortcutHelperBarEventHandler;\n\n        // Returns true when the pressed keys are defined in the Trigger\n        internal static Func<bool> doPressedKeysTriggerAnyShortcut;\n\n        public static event Action<bool> focusChanged;\n\n        // Windows were reordered\n        internal static CallbackFunction windowsReordered;\n\n        // Global contextual menus for inspector values\n        public static SerializedPropertyCallbackFunction contextualPropertyMenu;\n\n        public static event Action<ApplicationTitleDescriptor> updateMainWindowTitle;\n\n        internal static string GetDefaultMainWindowTitle(ApplicationTitleDescriptor desc)\n        {\n            // de facto dev tool window title conventions:\n            // https://unity.slack.com/archives/C06TQ0QMQ/p1550046908037800\n            //\n            // _windows_ & _linux_\n            //\n            //   <Project> - <ThingImEditing> [- <MaybeSomeBuildConfigStuff>] - <AppName> [<ProbablyVersionToo>]\n            //\n            //   this is done to keep the most important data at the front to deal with truncation that happens\n            //   in various interfaces like alt-tab and hover taskbar icon.\n            //\n            // _mac_\n            //\n            //   <ThingImEditing> - <Project> [- <MaybeSomeBuildConfigStuff>] - <AppName> [<ProbablyVersionToo>]\n            //\n            //   most macOS apps show the icon of \"ThingImEditing\" in front of the title, so it makes sense\n            //   for the icon to be next to what it represents. (Unity does not currently show the icon though.)\n            //\n\n            var title = Application.platform == RuntimePlatform.OSXEditor\n                ? $\"{desc.activeSceneName} - {desc.projectName}\"\n                : $\"{desc.projectName} - {desc.activeSceneName}\";\n\n            // FUTURE: [CODE COVERAGE] and the build target info do not belong in the title bar. they\n            // are there now because we want them to be always-visible to user, which normally would be a) buildconfig\n            // bar or b) status bar, but we don't have a) and our b) needs work to support such a thing.\n\n            if (!string.IsNullOrEmpty(desc.targetName))\n            {\n                title += $\" - {desc.targetName}\";\n            }\n\n            title += $\" - {desc.unityProductName} ({desc.unityVersion})\";\n\n            if (desc.codeCoverageEnabled)\n            {\n                title += \" \" + L10n.Tr(\"[CODE COVERAGE]\");\n            }\n\n            return title;\n        }\n\n        [RequiredByNativeCode]\n        internal static string BuildMainWindowTitle()\n        {\n            var desc = GetApplicationTitleDescriptor();\n            updateMainWindowTitle?.Invoke(desc);\n\n            return desc.title;\n        }\n\n        internal static ApplicationTitleDescriptor GetApplicationTitleDescriptor()\n        {\n            var activeSceneName = string.IsNullOrEmpty(SceneManager.GetActiveScene().path)\n                ? L10n.Tr(\"Untitled\")\n                : Path.GetFileNameWithoutExtension(SceneManager.GetActiveScene().path);\n\n            var unityVersion = Unsupported.IsSourceBuild() || Unsupported.IsDeveloperMode()\n                ? InternalEditorUtility.GetUnityDisplayVersion()\n                : Application.unityVersion;\n\n            var projectString = PreferencesProvider.useProjectPathInTitle\n                ? Path.GetFullPath(Path.Combine(Application.dataPath, \"..\"))\n                : GetDefaultProjectName();\n\n            var desc = new ApplicationTitleDescriptor(\n                projectString,\n                InternalEditorUtility.GetUnityProductName(),\n                unityVersion,\n                activeSceneName,\n                BuildPipeline.GetBuildTargetGroupDisplayName(BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget)),\n                Coverage.enabled\n            );\n\n            desc.title = GetDefaultMainWindowTitle(desc);\n\n            return desc;\n        }\n\n        internal static string GetDefaultProjectName()\n        {\n            return isTemporaryProject ? PlayerSettings.productName : Path.GetFileName(Path.GetDirectoryName(Application.dataPath));\n        }\n\n        [RequiredByNativeCode]\n        internal static void Internal_CallUpdateFunctions()\n        {\n            if (update == null)\n                return;\n\n            foreach (var evt in m_UpdateEvent.UpdateAndInvoke(update))\n                evt();\n        }\n\n        [RequiredByNativeCode]\n        internal static void Internal_InvokeTickEvents()\n        {\n            tick?.Invoke();\n        }\n\n        [RequiredByNativeCode]\n        internal static void Internal_CallDelayFunctions()\n        {\n            CallbackFunction delay = delayCall;\n            delayCall = null;\n            foreach (var evt in m_DelayCallEvent.UpdateAndInvoke(delay))\n                evt();\n        }\n\n        [RequiredByNativeCode]\n        internal static void Internal_SwitchSkin()\n        {\n            EditorGUIUtility.Internal_SwitchSkin();\n        }\n\n        internal static void RequestRepaintAllViews()\n        {\n            foreach (GUIView view in Resources.FindObjectsOfTypeAll(typeof(GUIView)))\n                view.Repaint();\n        }\n\n        internal static void RequestRepaintAllTexts(VersionChangeType incrementVersion)\n        {\n            foreach (GUIView view in Resources.FindObjectsOfTypeAll(typeof(GUIView)))\n            {\n                view.Repaint();\n                view.IncrementVersionForUITKText(incrementVersion);\n            }\n        }\n\n        internal static void UpdateEditorTextRenderingMode(EditorTextRenderingMode mode)\n        {\n            foreach (GUIView view in Resources.FindObjectsOfTypeAll(typeof(GUIView)))\n            {\n                view.UpdateEditorTextRenderingMode(mode);\n            }\n        }\n\n        [RequiredByNativeCode]\n        static void Internal_CallHierarchyHasChanged()\n        {\n            #pragma warning disable 618\n            hierarchyWindowChanged?.Invoke();\n            #pragma warning restore 618\n\n            foreach (var evt in m_HierarchyChangedEvent)\n                evt();\n        }\n\n        [RequiredByNativeCode]\n        static void Internal_CallProjectHasChanged()\n        {\n            #pragma warning disable 618\n            projectWindowChanged?.Invoke();\n            #pragma warning restore 618\n\n            foreach (var evt in m_ProjectChangedEvent)\n                evt();\n        }\n\n        internal static void Internal_CallSearchHasChanged()\n        {\n            searchChanged?.Invoke();\n        }\n\n        internal static void Internal_CallAssetLabelsHaveChanged()\n        {\n            assetLabelsChanged?.Invoke();\n        }\n\n        internal static void Internal_CallAssetBundleNameChanged()\n        {\n            assetBundleNameChanged?.Invoke();\n        }\n\n        [RequiredByNativeCode]\n        static void Internal_PauseStateChanged(PauseState state)\n        {\n            #pragma warning disable 618\n            playmodeStateChanged?.Invoke();\n            #pragma warning restore 618\n            using var scope = new ProgressScope($\"PauseStateChanged Callback\", \"\" , forceUpdate: true);\n            foreach (var evt in m_PauseStateChangedEvent)\n            {\n                scope.SetText($\"{evt.Method?.DeclaringType?.FullName}.{evt.Method?.Name}\", true);\n                evt(state);\n            }\n        }\n\n        [RequiredByNativeCode]\n        static void Internal_PlayModeStateChanged(PlayModeStateChange state)\n        {\n            #pragma warning disable 618\n            playmodeStateChanged?.Invoke();\n            #pragma warning restore 618\n            if (!m_PlayModeStateChangedEvent.hasSubscribers) return;\n            var stateName = state.ToString();\n\n            // Without this workaround, you will fail Editor.GameViewTests.Playmode_PlayUnfocused_IsUnfocused_WhenGameViewFocused\n            // You can still trigger UUM-74498 by showing a ProgressScope in EnteredPlayMode (including in usercode with EditorUtility.DisplayProgressBar)\n            // This is because a progress bar going away will cause the previously focused window to be refocused\n            // The underlying issue is being tracked in UUM-86918 and this workaround should be undone as part of the fix there\n            if (PlayModeView.GetMainPlayModeView() is GameView { enterPlayModeBehavior: PlayModeView.EnterPlayModeBehavior.PlayUnfocused }\n                && state == PlayModeStateChange.EnteredPlayMode)\n            {\n                foreach (var evt in m_PlayModeStateChangedEvent)\n                {\n                    evt(state);\n                }\n                return;\n            }\n            using var scope = new ProgressScope($\"PlayModeStateChanged Callback ({stateName})\", \"\", forceUpdate: true);\n            foreach (var evt in m_PlayModeStateChangedEvent)\n            {\n                scope.SetText($\"{evt.Method?.DeclaringType?.FullName}.{evt.Method?.Name}\", true);\n                evt(state);\n            }\n        }\n\n        [RequiredByNativeCode]\n        internal static void Internal_FileMenuSaved()\n        {\n            fileMenuSaved?.Invoke();\n        }\n\n        [RequiredByNativeCode]\n        static void Internal_CallKeyboardModifiersChanged()\n        {\n            modifierKeysChanged?.Invoke();\n        }\n\n        [RequiredByNativeCode]\n        static void Internal_CallWindowsReordered()\n        {\n            windowsReordered?.Invoke();\n        }\n\n        [RequiredByNativeCode]\n        static bool DoPressedKeysTriggerAnyShortcutHandler()\n        {\n            if (doPressedKeysTriggerAnyShortcut != null)\n                return doPressedKeysTriggerAnyShortcut();\n            return false;\n        }\n\n        [RequiredByNativeCode]\n        static void Internal_CallGlobalEventHandler()\n        {\n            globalEventHandler?.Invoke();\n            shortcutHelperBarEventHandler?.Invoke();\n\n            // Ensure this is called last in order to make sure no null current events are passed to other handlers\n            WindowLayout.MaximizeGestureHandler();\n\n            Event.current = null;\n        }\n\n        [RequiredByNativeCode]\n        static void Internal_FocusChanged(bool hasFocus)\n        {\n            isFocused = hasFocus;\n            focusChanged?.Invoke(hasFocus);\n        }\n\n        [MenuItem(\"File/New Scene %n\", priority = 150)]\n        static void FireFileMenuNewScene()\n        {\n            if (CommandService.Exists(\"Menu/File/NewSceneTemplate\"))\n            {\n                CommandService.Execute(\"Menu/File/NewSceneTemplate\");\n            }\n            else\n            {\n                EditorApplication.FileMenuNewScene();\n            }\n        }\n\n        [RequiredByNativeCode]\n        internal static void TogglePlaying()\n        {\n            isPlaying = !isPlaying;\n            InternalEditorUtility.RepaintAllViews();\n        }\n\n        [RequiredByNativeCode]\n        static void Internal_RestoreLastOpenedScenes()\n        {\n            using (new EditorPerformanceTracker(\"Application.RestoreLastOpenedScenes\"))\n            {\n                // Unfortunately kLastOpenedScene would more appropriately be named kLastSpecifiedScene as it refers\n                // to the last scene file as specified by the user/as chosen using Double-Click on the scene file in\n                // the file browser.  However this editor preference has been around for a while, the name stays.\n                //\n                // Try to open the last specified scene first\n                var lastOpenedScene = EditorPrefs.GetString(kLastOpenedScene);\n\n                // Open requested scene if any\n                if (!string.IsNullOrEmpty(lastOpenedScene))\n                {\n                    try\n                    {\n                        if (EditorSceneManager.CanOpenScene())\n                            EditorSceneManager.OpenScene(lastOpenedScene, OpenSceneMode.Single);\n                        else\n                            InstantiateDefaultScene();\n                    }\n                    catch (Exception e)\n                    {\n                        Debug.LogWarning($\"Error while opening specified scene \\\"{lastOpenedScene}\\\":\\n {e.Message}\");\n                    }\n\n                    // Regardless of the operation outcome, reset last opened scene so that we don't\n                    // force it next time around\n                    EditorPrefs.SetString(kLastOpenedScene, \"\");\n                }\n                else\n                {\n                    // Open last opened scenes\n                    if (!EditorSceneManager.LoadLastSceneManagerSetup())\n                        InstantiateDefaultScene();\n                }\n            }\n        }\n\n        static void InstantiateDefaultScene()\n        {\n            if (CommandService.Exists(\"Menu/File/InstantiateDefaultScene\"))\n            {\n                CommandService.Execute(\"Menu/File/InstantiateDefaultScene\");\n            }\n            else\n            {\n                EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Single);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorApplication.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEngine.SceneManagement;\nusing UnityEditor.SceneManagement;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class EditorApplication\n    {\n        [Obsolete(\"Use EditorSceneManager.NewScene (NewSceneSetup.DefaultGameObjects)\")]\n        public static void NewScene()\n        {\n            EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects);\n        }\n\n        [Obsolete(\"Use EditorSceneManager.NewScene (NewSceneSetup.EmptyScene)\")]\n        public static void NewEmptyScene()\n        {\n            EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);\n        }\n\n        // Opens the scene at /path/.\n        [Obsolete(\"Use EditorSceneManager.OpenScene\")]\n        public static bool OpenScene(string path)\n        {\n            // Check that we're not in play mode first before opening the scene.\n            if (!isPlaying)\n            {\n                Scene scene = EditorSceneManager.OpenScene(path);\n                return scene.IsValid();\n            }\n            else\n            {\n                throw new InvalidOperationException(\n                    \"EditorApplication.OpenScene() cannot be called when in the Unity Editor is in play mode.\");\n            }\n        }\n\n        [Obsolete(\"Use EditorSceneManager.OpenScene\")]\n        public static void OpenSceneAdditive(string path)\n        {\n            // Case 712517:\n            // Behaviour change introduced in 5.3\n            // Previously we allowed OpenSceneAdditive to be called during playmode.\n            // This is no longer allowed, if it happens we exit playmode which is\n            // consistent with EditorSceneManager.OpenScene(path, OpenSceneMode.Additive)\n\n            if (Application.isPlaying)\n            {\n                Debug.LogWarning(\"Exiting playmode.\\n\" +\n                    \"OpenSceneAdditive was called at a point where there was no active scene.\\n\" +\n                    \"This usually means it was called in a PostprocessScene function during scene loading or it was called during playmode.\\n\" +\n                    \"This is no longer allowed. Use SceneManager.LoadScene to load scenes at runtime or in playmode.\");\n            }\n\n            Scene srcScene = EditorSceneManager.OpenScene(path, OpenSceneMode.Additive);\n            Scene dstScene = EditorSceneManager.GetActiveScene();\n            SceneManager.MergeScenes(srcScene, dstScene);\n        }\n\n        [Obsolete(\"Use EditorSceneManager.SaveScene\")]\n        public static bool SaveScene()\n        {\n            return EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene(), \"\", false);\n        }\n\n        [Obsolete(\"Use EditorSceneManager.SaveScene\")]\n        public static bool SaveScene(string path)\n        {\n            return EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene(), path, false);\n        }\n\n        [Obsolete(\"Use EditorSceneManager.SaveScene\")]\n        public static bool SaveScene(string path, bool saveAsCopy)\n        {\n            return EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene(), path, saveAsCopy);\n        }\n\n        [Obsolete(\"Use EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo\")]\n        public static bool SaveCurrentSceneIfUserWantsTo()\n        {\n            return EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();\n        }\n\n        [Obsolete(\"This function is internal and no longer supported\")]\n        static internal bool SaveCurrentSceneIfUserWantsToForce()\n        {\n            return false;\n        }\n\n        [Obsolete(\"Use EditorSceneManager.MarkSceneDirty or EditorSceneManager.MarkAllScenesDirty\")]\n        public static void MarkSceneDirty()\n        {\n            EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());\n        }\n\n        [Obsolete(\"Use Scene.isDirty instead. Use EditorSceneManager.GetScene API to get each open scene\")]\n        public static bool isSceneDirty\n        {\n            get { return EditorSceneManager.GetActiveScene().isDirty; }\n        }\n\n        [Obsolete(\"Use EditorSceneManager to see which scenes are currently loaded\")]\n        public static string currentScene\n        {\n            get\n            {\n                Scene scene = EditorSceneManager.GetActiveScene();\n                if (scene.IsValid())\n                    return scene.path;\n\n                return \"\";\n            }\n            set\n            {\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorAssemblies.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Runtime/Scripting/TypeCache.h\")]\n    static partial class EditorAssemblies\n    {\n        const BindingFlags k_DefaultMethodBindingFlags =\n            BindingFlags.Public\n            | BindingFlags.NonPublic\n            | BindingFlags.Instance\n            | BindingFlags.Static;\n\n        internal static IEnumerable<MethodInfo> GetAllMethodsWithAttribute<T>(BindingFlags bindingFlags = k_DefaultMethodBindingFlags)\n            where T : Attribute\n        {\n            return Internal_GetAllMethodsWithAttribute(typeof(T), bindingFlags).Cast<MethodInfo>();\n        }\n\n        [FreeFunction(Name = \"GetAllMethodsWithAttribute\")]\n        extern static object[] Internal_GetAllMethodsWithAttribute(Type attrType, BindingFlags staticness);\n\n        [FreeFunction(\"GetUnchangedAssemblyNames\")]\n        internal static extern string[] GetUnchangedAssemblyNames();\n\n        internal static extern bool AllAssembliesAreUnchanged\n        {\n            [FreeFunction(\"AllAssembliesAreUnchanged\")]\n            get;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorAssemblies.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing System.Reflection;\nusing System.Runtime.CompilerServices;\nusing UnityEditor.Profiling;\nusing UnityEngine;\nusing System.Text;\nusing Unity.Profiling;\nusing UnityEngine.Scripting;\nusing Debug = UnityEngine.Debug;\n\nnamespace UnityEditor\n{\n    /// <summary>\n    /// Marks a class as requiring eager initialization.\n    ///\n    /// Classes marked with this attribute will have their static constructors\n    /// executed whenever assemblies are loaded or reloaded.\n    ///\n    /// Very useful for event (re)wiring.\n    /// </summary>\n    [RequiredByNativeCode]\n    [AttributeUsage(AttributeTargets.Class)]\n    public class InitializeOnLoadAttribute : Attribute\n    {\n    }\n\n    [RequiredByNativeCode]\n    [AttributeUsage(AttributeTargets.Method)]\n    public class InitializeOnLoadMethodAttribute : Attribute\n    {\n    }\n\n    [RequiredByNativeCode]\n    [AttributeUsage(AttributeTargets.Method)]\n    public class InitializeOnEnterPlayModeAttribute : Attribute\n    {\n    }\n\n    /// <summary>\n    /// Holds information about the current set of editor assemblies.\n    /// </summary>\n    static partial class EditorAssemblies\n    {\n        static Dictionary<Type, Type[]> m_subClasses = new Dictionary<Type, Type[]>();\n\n        /// <summary>\n        /// The same set of assemblies as <see cref=\"loadedAssemblies\"/>, but\n        /// sorted topologically according to each assembly's assembly references.\n        /// </summary>\n        private static Assembly[] m_topologicallySortedAssemblies;\n\n        /// <summary>\n        /// The currently loaded editor assemblies\n        /// (This is kept up to date from <see cref=\"SetLoadedEditorAssemblies\"/>)\n        /// </summary>\n        static internal Assembly[] loadedAssemblies\n        {\n            get; private set;\n        }\n\n        static internal IEnumerable<Type> loadedTypes\n        {\n            get { return loadedAssemblies.SelectMany(assembly => AssemblyHelper.GetTypesFromAssembly(assembly)); }\n        }\n\n        private static bool IsSubclassOfGenericType(Type klass, Type genericType)\n        {\n            if (klass.IsGenericType && klass.GetGenericTypeDefinition() == genericType)\n                return false;\n\n            for (klass = klass.BaseType; klass != null; klass = klass.BaseType)\n            {\n                if (klass.IsGenericType && klass.GetGenericTypeDefinition() == genericType)\n                    return true;\n            }\n\n            return false;\n        }\n\n        [RequiredByNativeCode]\n        private static void SetLoadedEditorAssemblies(Assembly[] assemblies)\n        {\n            loadedAssemblies = assemblies;\n\n            // clear cached subtype -> types when assemblies change\n            m_subClasses.Clear();\n\n            m_topologicallySortedAssemblies = AssemblyHelper.TopologicalSort(loadedAssemblies);\n        }\n\n        static ProfilerMarkerWithStringData _profilerMarkerProcessInitializeOnLoadAttributes = ProfilerMarkerWithStringData.Create(\"ProcessInitializeOnLoadAttribute\", \"Type\");\n        static ProfilerMarkerWithStringData _profilerMarkerProcessInitializeOnLoadMethodAttributes = ProfilerMarkerWithStringData.Create(\"ProcessInitializeOnLoadMethodAttribute\", \"MethodInfo\");\n        private static readonly ProfilerMarker _profilerMarkerSortTypes = new ProfilerMarker(\"SortTypesTopologically\");\n\n        [RequiredByNativeCode]\n        private static void ProcessInitializeOnLoadAttributes(Type[] types)\n        {\n            if (types.Length == 0)\n                return;\n            bool reportTimes = (bool)Debug.GetDiagnosticSwitch(\"EnableDomainReloadTimings\").value;\n\n            IEnumerable<Type> sortedTypes;\n            using (_profilerMarkerSortTypes.Auto())\n            {\n                // Sort types according to topologically-sorted assemblies, such that we guarantee that\n                // [InitializeOnLoad] classes in assemblies referenced by a given assembly will have been\n                // initialized prior to that assembly's own [InitializeOnLoad] classes.\n                sortedTypes = types.OrderBy(x => Array.IndexOf(m_topologicallySortedAssemblies, x.Assembly));\n            }\n\n            bool detailedProgress = types.Length <= (uint) Debug.GetDiagnosticSwitch(\"MaxInitializeAttributeDetailOnProgressBar\").value;\n\n            using var scope = new ProgressScope(detailedProgress ? \"Processing InitializeOnLoad Attributes\" : \"Processing many InitializeOnLoad Attributes\", \"Hold on...\", forceUpdate: true);\n\n            foreach (Type type in sortedTypes)\n            {\n                using (_profilerMarkerProcessInitializeOnLoadAttributes.Auto(reportTimes,\n                           () => type.AssemblyQualifiedName))\n                {\n                    var typeFullName = type?.FullName;\n                    if (detailedProgress)\n                        scope.SetText($\"{typeFullName}.{typeFullName}\", true);\n                    try\n                    {\n                        RuntimeHelpers.RunClassConstructor(type.TypeHandle);\n                    }\n                    catch (TypeLoadException x)\n                    {\n                        Debug.LogError(x.InnerException);\n                    }\n                    catch (TypeInitializationException x)\n                    {\n                        Debug.LogError(x.InnerException);\n                    }\n                }\n            }\n        }\n\n        [RequiredByNativeCode]\n        private static void ProcessInitializeOnLoadMethodAttributes()\n        {\n            bool reportTimes = (bool)Debug.GetDiagnosticSwitch(\"EnableDomainReloadTimings\").value;\n            var methods = TypeCache.GetMethodsWithAttribute<InitializeOnLoadMethodAttribute>();\n            if (methods.Count == 0) return;\n            bool showDetail = methods.Count <= (uint) Debug.GetDiagnosticSwitch(\"MaxInitializeAttributeDetailOnProgressBar\").value;\n\n            using var scope = new ProgressScope(showDetail ? \"Processing InitializeOnLoadMethod Attributes\" : \"Processing many InitializeOnLoadMethods\", \"Hold on...\", forceUpdate: true);\n            foreach (var method in methods)\n            {\n                using (_profilerMarkerProcessInitializeOnLoadMethodAttributes.Auto(reportTimes,\n                           () => $\"{method.DeclaringType?.FullName}::{method.Name}\"))\n                {\n                    if (showDetail)\n                        scope.SetText($\"{method.DeclaringType?.FullName}.{method?.Name}\", true);\n                    try\n                    {\n                        method.Invoke(null, null);\n                    }\n                    catch (Exception x)\n                    {\n                        Debug.LogError(x);\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorBuildSettings.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEngine.Scripting;\nusing UnityEngine.Bindings;\nusing System.Runtime.InteropServices;\nusing JetBrains.Annotations;\nusing Object = UnityEngine.Object;\nusing UnityEditor.Build.Profile;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [Serializable]\n    [NativeHeader(\"Editor/Src/EditorBuildSettings.h\")]\n    [NativeAsStruct]\n    [StructLayout(LayoutKind.Sequential)]\n    [UsedByNativeCode]\n    public class EditorBuildSettingsScene : IComparable\n    {\n        [NativeName(\"enabled\"), SerializeField]\n        bool m_enabled;\n        [NativeName(\"path\"), SerializeField]\n        string m_path;\n        [NativeName(\"guid\"), SerializeField]\n        GUID m_guid;\n        public EditorBuildSettingsScene() {}\n        public EditorBuildSettingsScene(string path, bool enabled)\n        {\n            m_path = path.Replace(\"\\\\\", \"/\");\n            m_enabled = enabled;\n            GUID.TryParse(AssetDatabase.AssetPathToGUID(path), out m_guid);\n        }\n\n        public EditorBuildSettingsScene(GUID guid, bool enabled)\n        {\n            m_guid = guid;\n            m_enabled = enabled;\n            m_path = AssetDatabase.GUIDToAssetPath(guid.ToString());\n        }\n\n        public bool enabled { get { return m_enabled; } set { m_enabled = value; } }\n        public string path { get { return m_path; } set { m_path = value.Replace(\"\\\\\", \"/\"); } }\n        public GUID guid { get { return m_guid; } set { m_guid = value; } }\n        public static string[] GetActiveSceneList(EditorBuildSettingsScene[] scenes)\n        {\n            return scenes.Where(scene => scene.enabled && !string.IsNullOrEmpty(scene.path)).Select(scene => scene.path).ToArray();\n        }\n\n        public int CompareTo(object obj)\n        {\n            if (obj is EditorBuildSettingsScene)\n            {\n                EditorBuildSettingsScene temp = (EditorBuildSettingsScene)obj;\n                return temp.path.CompareTo(path);\n            }\n            throw new ArgumentException(\"object is not a EditorBuildSettingsScene\");\n        }\n\n        [RequiredByNativeCode, UsedImplicitly]\n        private static void DeconstructArrayElement(EditorBuildSettingsScene[] arr, int index, out bool enabled, out string path, out GUID guid)\n        {\n            var item = arr[index];\n            enabled = item.enabled;\n            path = item.path;\n            guid = item.guid;\n        }\n    }\n\n    [NativeHeader(\"Editor/Src/EditorBuildSettings.h\")]\n    public partial class EditorBuildSettings : UnityEngine.Object\n    {\n        private EditorBuildSettings() {}\n        public static event Action sceneListChanged;\n        [RequiredByNativeCode]\n        internal static void SceneListChanged()\n        {\n            if (sceneListChanged != null)\n                sceneListChanged();\n        }\n\n        public static EditorBuildSettingsScene[] scenes\n        {\n            get\n            {\n                if (BuildProfileContext.activeProfile is not null)\n                {\n                    return BuildProfileContext.activeProfile.GetScenesForBuild();\n                }\n\n                return GetEditorBuildSettingsScenes();\n            }\n            set\n            {\n                if (BuildProfileContext.activeProfile is not null\n                    && BuildProfileContext.activeProfile.overrideGlobalScenes)\n                {\n                    BuildProfileContext.activeProfile.scenes = value;\n                }\n                else\n                {\n                    SetEditorBuildSettingsScenes(value);\n                }\n            }\n        }\n\n        public static EditorBuildSettingsScene[] globalScenes\n        {\n            get\n            {\n                return GetEditorBuildSettingsSceneIgnoreProfile();\n            }\n            set\n            {\n                SetEditorBuildSettingsSceneIgnoreProfile(value);\n            }\n        }\n\n        [RequiredByNativeCode]\n        static EditorBuildSettingsScene[] GetActiveBuildProfileSceneList()\n        {\n            if (!EditorUserBuildSettings.isBuildProfileAvailable\n                || BuildProfileContext.activeProfile is null\n                || !BuildProfileContext.activeProfile.overrideGlobalScenes)\n                return null;\n\n            return BuildProfileContext.activeProfile.scenes;\n        }\n\n        static extern EditorBuildSettingsScene[] GetEditorBuildSettingsScenes();\n        static extern void SetEditorBuildSettingsScenes(EditorBuildSettingsScene[] scenes);\n\n        [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n        internal static extern void SetEditorBuildSettingsSceneIgnoreProfile(EditorBuildSettingsScene[] scenes);\n\n        [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n        internal static extern EditorBuildSettingsScene[] GetEditorBuildSettingsSceneIgnoreProfile();\n\n        enum ConfigObjectResult\n        {\n            Succeeded,\n            FailedEntryNotFound,\n            FailedNullObj,\n            FailedNonPersistedObj,\n            FailedEntryExists,\n            FailedTypeMismatch\n        }\n\n        public static extern bool UseParallelAssetBundleBuilding { get; set; }\n\n        [NativeMethod(\"AddConfigObject\")]\n        static extern ConfigObjectResult AddConfigObjectInternal(string name, Object obj, bool overwrite);\n        public static extern bool RemoveConfigObject(string name);\n        public static extern string[] GetConfigObjectNames();\n        static extern Object GetConfigObject(string name);\n        public static void AddConfigObject(string name, Object obj, bool overwrite)\n        {\n            var result = AddConfigObjectInternal(name, obj, overwrite);\n            if (result == ConfigObjectResult.Succeeded)\n                return;\n            switch (result)\n            {\n                case ConfigObjectResult.FailedEntryExists: throw new Exception(\"Config object with name '\" + name + \"' already exists.\");\n                case ConfigObjectResult.FailedNonPersistedObj: throw new Exception(\"Cannot add non-persisted config object with name '\" + name + \"'.\");\n                case ConfigObjectResult.FailedNullObj: throw new Exception(\"Cannot add null config object with name '\" + name + \"'.\");\n            }\n        }\n\n        public static bool TryGetConfigObject<T>(string name, out T result) where T : Object\n        {\n            result = GetConfigObject(name) as T;\n            return result != null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorConnectionInternal.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Runtime/Network/PlayerCommunicator/GeneralConnection.h\")]\n    enum GeneralConnectionSendMode\n    {\n        NoBlocking,\n        AllowBlocking\n    }\n\n    [StaticAccessor(\"EditorConnection::Get()\", StaticAccessorType.Dot)]\n    [NativeHeader(\"Runtime/Network/PlayerCommunicator/EditorConnection.h\")]\n    [NativeHeader(\"Runtime/Network/PlayerCommunicator/ManagedProxy/EditorConnectionManaged.h\")]\n    internal class EditorConnectionInternal : IPlayerEditorConnectionNative\n    {\n        void IPlayerEditorConnectionNative.SendMessage(Guid messageId, byte[] data, int playerId)\n        {\n            if (messageId == Guid.Empty)\n            {\n                throw new ArgumentException(nameof(messageId) + \" must not be empty\");\n            }\n            SendMessage(messageId.ToString(\"N\"), data, playerId);\n        }\n\n        bool IPlayerEditorConnectionNative.TrySendMessage(Guid messageId, byte[] data, int playerId)\n        {\n            if (messageId == Guid.Empty)\n            {\n                throw new ArgumentException(nameof(messageId) + \" must not be empty\");\n            }\n            return TrySendMessage(messageId.ToString(\"N\"), data, playerId);\n        }\n\n        void IPlayerEditorConnectionNative.Poll()\n        {\n            PollInternal();\n        }\n\n        void IPlayerEditorConnectionNative.RegisterInternal(Guid messageId)\n        {\n            RegisterInternal(messageId.ToString(\"N\"));\n        }\n\n        void IPlayerEditorConnectionNative.UnregisterInternal(Guid messageId)\n        {\n            UnregisterInternal(messageId.ToString(\"N\"));\n        }\n\n        void IPlayerEditorConnectionNative.Initialize()\n        {\n            Initialize();\n        }\n\n        void IPlayerEditorConnectionNative.DisconnectAll()\n        {\n            DisconnectAll();\n        }\n\n        public bool IsConnected()\n        {\n            throw new NotSupportedException(\"Check the connected players list instead\");\n        }\n\n        [NativeConditional(\"ENABLE_PLAYERCONNECTION && UNITY_EDITOR\")]\n        [FreeFunction(\"EditorConnectionManaged::Get\")]\n        public extern static void Initialize();\n\n        public static void UnregisterInternal(string messageId)\n        {\n            UnregisterInternal(new GUID(messageId));\n        }\n\n        [NativeConditional(\"ENABLE_PLAYERCONNECTION && UNITY_EDITOR\")]\n        [StaticAccessor(\"EditorConnectionManaged::Get()\", StaticAccessorType.Dot)]\n        [NativeName(\"Unregister\")]\n        private extern static void UnregisterInternal(UnityEditor.GUID messageId);\n\n        public static void RegisterInternal(string messageId) { RegisterInternal(new GUID(messageId)); }\n\n        [NativeConditional(\"ENABLE_PLAYERCONNECTION && UNITY_EDITOR\")]\n        [StaticAccessor(\"EditorConnectionManaged::Get()\", StaticAccessorType.Dot)]\n        [NativeName(\"Register\")]\n        private extern static void RegisterInternal(UnityEditor.GUID messageId);\n\n\n        [NativeConditional(\"ENABLE_PLAYERCONNECTION && UNITY_EDITOR\")]\n        [NativeName(\"SendMessage\")]\n        private extern unsafe static void SendMessageInternal(int playerId, GUID messageId, byte* data, int dataSize, GeneralConnectionSendMode sendMode);\n\n        //playerId 0 is ANY_PLAYERCONNECTION\n        public static void SendMessage(string messageId, byte[] data, int playerId)\n        {\n            unsafe\n            {\n                fixed(byte* dataBytes = data)\n                SendMessageInternal(playerId, new GUID(messageId), dataBytes, data?.Length ?? 0, GeneralConnectionSendMode.AllowBlocking);\n            }\n        }\n\n        [NativeConditional(\"ENABLE_PLAYERCONNECTION && UNITY_EDITOR\")]\n        [NativeName(\"TrySendMessage\")]\n        private extern unsafe static bool TrySendMessageInternal(int playerId, GUID messageId, byte* data, int dataSize);\n\n        //playerId 0 is ANY_PLAYERCONNECTION\n        public static bool TrySendMessage(string messageId, byte[] data, int playerId)\n        {\n            unsafe\n            {\n                fixed(byte* dataBytes = data)\n                return TrySendMessageInternal(playerId, new GUID(messageId), dataBytes, data?.Length ?? 0);\n            }\n        }\n\n        [NativeName(\"Poll\")]\n        public extern static void PollInternal();\n\n        public extern static int ConnectPlayerProxy(string IP, int port);\n\n        [NativeConditional(\"ENABLE_PLAYERCONNECTION && UNITY_EDITOR\")]\n        public extern static void DisconnectAll();\n\n        [NativeConditional(\"ENABLE_PLAYERCONNECTION\")]\n        public extern static UInt32 GetLocalGuid();\n\n        [NativeConditional(\"ENABLE_PLAYERCONNECTION && UNITY_EDITOR\")]\n        extern public static string GetMulticastAddress();\n\n        [NativeConditional(\"ENABLE_PLAYERCONNECTION && UNITY_EDITOR\")]\n        extern public static UInt32 GetMulticastPort();\n\n        [NativeConditional(\"ENABLE_PLAYERCONNECTION && UNITY_EDITOR\")]\n        [NativeName(\"BuildServerIDString\")]\n        extern public static string BuildServerIdentificationFormat(string localIP, UInt32 listenPort, int flags, UInt32 localGuid, UInt32 editorGuid, string idString, bool allowDebugging, string packageString, string projectName);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorGUI.EnumMaskField.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\n\n#pragma warning disable 618 // disable obsolete warning\n\nnamespace UnityEditor\n{\n    public partial class EditorGUI\n    {\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskField(Rect position, Enum enumValue)\n        {\n            return EnumMaskField(position, enumValue, EditorStyles.popup);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskField(Rect position, Enum enumValue, GUIStyle style)\n        {\n            return EnumMaskFieldInternal(position, enumValue, style);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskField(Rect position, string label, Enum enumValue)\n        {\n            return EnumMaskField(position, label, enumValue, EditorStyles.popup);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskField(Rect position, string label, Enum enumValue, GUIStyle style)\n        {\n            return EnumMaskFieldInternal(position, EditorGUIUtility.TempContent(label), enumValue, style);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskField(Rect position, GUIContent label, Enum enumValue)\n        {\n            return EnumMaskField(position, label, enumValue, EditorStyles.popup);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskField(Rect position, GUIContent label, Enum enumValue, GUIStyle style)\n        {\n            return EnumMaskFieldInternal(position, label, enumValue, style);\n        }\n\n        [Obsolete(\"EnumMaskPopup has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskPopup(Rect position, string label, Enum selected)\n        {\n            return EnumMaskPopup(position, label, selected, EditorStyles.popup);\n        }\n\n        [Obsolete(\"EnumMaskPopup has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskPopup(Rect position, string label, Enum selected, GUIStyle style)\n        {\n            int changedFlags;\n            bool changedToValue;\n            return EnumMaskPopup(position, label, selected, out changedFlags, out changedToValue, style);\n        }\n\n        [Obsolete(\"EnumMaskPopup has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskPopup(Rect position, GUIContent label, Enum selected)\n        {\n            return EnumMaskPopup(position, label, selected, EditorStyles.popup);\n        }\n\n        [Obsolete(\"EnumMaskPopup has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskPopup(Rect position, GUIContent label, Enum selected, GUIStyle style)\n        {\n            int changedFlags;\n            bool changedToValue;\n            return EnumMaskPopup(position, label, selected, out changedFlags, out changedToValue, style);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        static Enum EnumMaskField(Rect position, GUIContent label, Enum enumValue, GUIStyle style, out int changedFlags, out bool changedToValue)\n        {\n            return DoEnumMaskField(position, label, enumValue, style, out changedFlags, out changedToValue);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        static Enum EnumMaskFieldInternal(Rect position, Enum enumValue, GUIStyle style)\n        {\n            Type enumType = enumValue.GetType();\n            if (!enumType.IsEnum)\n                throw new ArgumentException(\"Parameter enumValue must be of type System.Enum\", \"enumValue\");\n\n            var names = Enum.GetNames(enumType).Select(ObjectNames.NicifyVariableName).ToArray();\n            int flags = MaskFieldGUIDeprecated.DoMaskField(\n                IndentedRect(position),\n                GUIUtility.GetControlID(s_MaskField, FocusType.Keyboard, position),\n                Convert.ToInt32(enumValue),\n                names, style);\n            return EnumDataUtility.IntToEnumFlags(enumType, flags);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        static Enum EnumMaskFieldInternal(Rect position, GUIContent label, Enum enumValue, GUIStyle style)\n        {\n            Type enumType = enumValue.GetType();\n            if (!enumType.IsEnum)\n                throw new ArgumentException(\"Parameter enumValue must be of type System.Enum\", \"enumValue\");\n\n            var id = GUIUtility.GetControlID(s_MaskField, FocusType.Keyboard, position);\n            var position2 = EditorGUI.PrefixLabel(position, id, label);\n            position.xMax = position2.x;\n\n            var names = Enum.GetNames(enumType).Select(ObjectNames.NicifyVariableName).ToArray();\n            int flags = MaskFieldGUIDeprecated.DoMaskField(position2, id, Convert.ToInt32(enumValue), names, style);\n            return EnumDataUtility.IntToEnumFlags(enumType, flags);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        static Enum DoEnumMaskField(Rect position, GUIContent label, Enum enumValue, GUIStyle style, out int changedFlags, out bool changedToValue)\n        {\n            var enumType = enumValue.GetType();\n            if (!enumType.IsEnum)\n                throw new ArgumentException(\"Parameter enumValue must be of type System.Enum\", \"enumValue\");\n\n            var id = GUIUtility.GetControlID(s_MaskField, FocusType.Keyboard, position);\n            var names = Enum.GetNames(enumType).Select(ObjectNames.NicifyVariableName).ToArray();\n            int flags = MaskFieldGUIDeprecated.DoMaskField(\n                PrefixLabel(position, id, label),\n                id,\n                Convert.ToInt32(enumValue),\n                names, style, out changedFlags, out changedToValue);\n            return EnumDataUtility.IntToEnumFlags(enumType, flags);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        static Enum EnumMaskPopup(Rect position, string label, Enum selected, out int changedFlags, out bool changedToValue, GUIStyle style)\n        {\n            return EnumMaskPopup(position, EditorGUIUtility.TempContent(label), selected, out changedFlags, out changedToValue, style);\n        }\n\n        [Obsolete(\"EnumMaskPopup has been deprecated. Use EnumFlagsField instead.\")]\n        internal static Enum EnumMaskPopup(Rect position, GUIContent label, Enum selected, out int changedFlags, out bool changedToValue, GUIStyle style)\n        {\n            return EnumMaskPopupInternal(position, label, selected, out changedFlags, out changedToValue, style);\n        }\n\n        // Make an enum mask popup selection field.\n        [Obsolete(\"EnumMaskPopup has been deprecated. Use EnumFlagsField instead.\")]\n        static Enum EnumMaskPopupInternal(Rect position, GUIContent label, Enum selected, out int changedFlags, out bool changedToValue, GUIStyle style)\n        {\n            return EnumMaskField(position, label, selected, style, out changedFlags, out changedToValue);\n        }\n    }\n\n    public partial class EditorGUILayout\n    {\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskField(Enum enumValue, params GUILayoutOption[] options)\n        {\n            return EnumMaskField(enumValue, EditorStyles.popup, options);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskField(Enum enumValue, GUIStyle style, params GUILayoutOption[] options)\n        {\n            var r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n            return EditorGUI.EnumMaskField(r, enumValue, style);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskField(string label, Enum enumValue, params GUILayoutOption[] options)\n        {\n            return EnumMaskField(label, enumValue, EditorStyles.popup, options);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskField(string label, Enum enumValue, GUIStyle style, params GUILayoutOption[] options)\n        {\n            var r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n            return EditorGUI.EnumMaskField(r, label, enumValue, style);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskField(GUIContent label, Enum enumValue, params GUILayoutOption[] options)\n        {\n            return EnumMaskField(label, enumValue, EditorStyles.popup, options);\n        }\n\n        [Obsolete(\"EnumMaskField has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskField(GUIContent label, Enum enumValue, GUIStyle style, params GUILayoutOption[] options)\n        {\n            var r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n            return EditorGUI.EnumMaskField(r, label, enumValue, style);\n        }\n\n        [Obsolete(\"EnumMaskPopup has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskPopup(string label, Enum selected, params GUILayoutOption[] options)\n        {\n            return EnumMaskPopup(label, selected, EditorStyles.popup, options);\n        }\n\n        [Obsolete(\"EnumMaskPopup has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskPopup(string label, Enum selected, GUIStyle style, params GUILayoutOption[] options)\n        {\n            int changedFlags;\n            bool changedToValue;\n            return EnumMaskPopup(EditorGUIUtility.TempContent(label), selected, out changedFlags, out changedToValue, style, options);\n        }\n\n        [Obsolete(\"EnumMaskPopup has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskPopup(GUIContent label, Enum selected, params GUILayoutOption[] options)\n        {\n            return EnumMaskPopup(label, selected, EditorStyles.popup, options);\n        }\n\n        [Obsolete(\"EnumMaskPopup has been deprecated. Use EnumFlagsField instead.\")]\n        public static Enum EnumMaskPopup(GUIContent label, Enum selected, GUIStyle style, params GUILayoutOption[] options)\n        {\n            int changedFlags;\n            bool changedToValue;\n            return EnumMaskPopup(label, selected, out changedFlags, out changedToValue, style, options);\n        }\n\n        // Make an enum popup selection field for a bitmask.\n        [Obsolete(\"EnumMaskPopup has been deprecated. Use EnumFlagsField instead.\")]\n        static Enum EnumMaskPopup(GUIContent label, Enum selected, out int changedFlags, out bool changedToValue, GUIStyle style, params GUILayoutOption[] options)\n        {\n            Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n            return EditorGUI.EnumMaskPopup(r, label, selected, out changedFlags, out changedToValue, style);\n        }\n    }\n\n    // Class for storing state for mask menus so we can get the info back to OnGUI from the user selection\n    [Obsolete(\"MaskFieldGUIDeprecated is deprecated. Use MaskFieldGUI instead.\")]\n    static class MaskFieldGUIDeprecated\n    {\n        // Class for storing state for mask menus so we can get the info back to OnGUI from the user selection\n        private class MaskCallbackInfo\n        {\n            // The global shared popup state\n            public static MaskCallbackInfo m_Instance;\n\n            // Name of the command event sent from the popup menu to OnGUI when user has changed selection\n            private const string kMaskMenuChangedMessage = \"MaskMenuChanged\";\n\n            // The control ID of the popup menu that is currently displayed.\n            // Used to pass selection changes back again\n            private readonly int m_ControlID;\n\n            // Which item was selected\n            private int m_Mask;\n\n            //Flags to control all / nothing buttons\n            private bool m_SetAll;\n            private bool m_ClearAll;\n            private bool m_DoNothing;\n\n            // Which view should we send it to.\n            private readonly GUIView m_SourceView;\n\n            public MaskCallbackInfo(int controlID)\n            {\n                m_ControlID = controlID;\n                m_SourceView = GUIView.current;\n            }\n\n            public static int GetSelectedValueForControl(int controlID, int mask, out int changedFlags, out bool changedToValue)\n            {\n                var evt = Event.current;\n\n                // No flags are changed by default\n                changedFlags = 0;\n                changedToValue = false;\n\n                if (evt.type == EventType.ExecuteCommand && evt.commandName == kMaskMenuChangedMessage)\n                {\n                    if (m_Instance == null)\n                    {\n                        Debug.LogError(\"Mask menu has no instance\");\n                        return mask;\n                    }\n                    if (m_Instance.m_ControlID == controlID)\n                    {\n                        if (!m_Instance.m_DoNothing)\n                        {\n                            if (m_Instance.m_ClearAll)\n                            {\n                                mask = 0;\n                                changedFlags = ~0;\n                                changedToValue = false;\n                            }\n                            else if (m_Instance.m_SetAll)\n                            {\n                                mask = ~0;\n                                changedFlags = ~0;\n                                changedToValue = true;\n                            }\n                            else\n                            {\n                                mask ^= m_Instance.m_Mask;\n                                changedFlags = m_Instance.m_Mask;\n                                changedToValue = (mask & m_Instance.m_Mask) != 0;\n                            }\n\n                            GUI.changed = true;\n                        }\n                        m_Instance.m_DoNothing = false;\n                        m_Instance.m_ClearAll = false;\n                        m_Instance.m_SetAll = false;\n                        m_Instance = null;\n                        evt.Use();\n                    }\n                }\n                return mask;\n            }\n\n            internal void SetMaskValueDelegate(object userData, string[] options, int selected)\n            {\n                switch (selected)\n                {\n                    case 0:\n                        m_ClearAll = true;\n                        break;\n                    case 1:\n                        m_SetAll = true;\n                        break;\n                    default:\n                        m_Mask = ((int[])userData)[selected - 2];\n                        break;\n                }\n\n                if (m_SourceView)\n                    m_SourceView.SendEvent(EditorGUIUtility.CommandEvent(kMaskMenuChangedMessage));\n            }\n        }\n\n        /// Make a field for a generic mask.\n        internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, GUIStyle style)\n        {\n            int dummyInt;\n            bool dummyBool;\n            return DoMaskField(position, controlID, mask, flagNames, style, out dummyInt, out dummyBool);\n        }\n\n        internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, int[] flagValues, GUIStyle style)\n        {\n            int dummyInt;\n            bool dummyBool;\n            return DoMaskField(position, controlID, mask, flagNames, flagValues, style, out dummyInt, out dummyBool);\n        }\n\n        internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, GUIStyle style, out int changedFlags, out bool changedToValue)\n        {\n            var flagValues = new int[flagNames.Length];\n            for (int i = 0; i < flagValues.Length; ++i)\n                flagValues[i] = (1 << i);\n\n            return DoMaskField(position, controlID, mask, flagNames, flagValues, style, out changedFlags, out changedToValue);\n        }\n\n        /// Make a field for a generic mask.\n        /// This version also gives you back which flags were changed and what they were changed to.\n        /// This is useful if you want to make the same change to multiple objects.\n        internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, int[] flagValues, GUIStyle style, out int changedFlags, out bool changedToValue)\n        {\n            mask = MaskCallbackInfo.GetSelectedValueForControl(controlID, mask, out changedFlags, out changedToValue);\n            var selectedFlags = new List<int>();\n            var fullFlagNames = new List<string> {\"Nothing\", \"Everything\"};\n\n            for (var i = 0; i < flagNames.Length; i++)\n            {\n                if ((mask & flagValues[i]) != 0)\n                    selectedFlags.Add(i + 2);\n            }\n\n            fullFlagNames.AddRange(flagNames);\n\n            GUIContent buttonContent = EditorGUI.mixedValueContent;\n            if (!EditorGUI.showMixedValue)\n            {\n                switch (selectedFlags.Count)\n                {\n                    case 0:\n                        buttonContent = EditorGUIUtility.TempContent(\"Nothing\");\n                        selectedFlags.Add(0);\n                        break;\n                    case 1:\n                        buttonContent = new GUIContent(fullFlagNames[selectedFlags[0]]);\n                        break;\n                    default:\n                        if (selectedFlags.Count >= flagNames.Length)\n                        {\n                            buttonContent = EditorGUIUtility.TempContent(\"Everything\");\n                            selectedFlags.Add(1);\n                            // When every available item is selected, we force to ~0 to keep the mask int value consistent\n                            // between the cases where all items are individually selected vs. user clicks \"everything\"\n                            mask = ~0;\n                        }\n                        else\n                            buttonContent = EditorGUIUtility.TempContent(\"Mixed...\");\n                        break;\n                }\n            }\n            Event evt = Event.current;\n            if (evt.type == EventType.Repaint)\n            {\n                style.Draw(position, buttonContent, controlID, false);\n            }\n            else if ((evt.type == EventType.MouseDown && position.Contains(evt.mousePosition)) || evt.MainActionKeyForControl(controlID))\n            {\n                MaskCallbackInfo.m_Instance = new MaskCallbackInfo(controlID);\n                evt.Use();\n                EditorUtility.DisplayCustomMenu(position, fullFlagNames.ToArray(),\n                    // Only show selections if we are not multi-editing\n                    EditorGUI.showMixedValue ? new int[] {} : selectedFlags.ToArray(),\n                    MaskCallbackInfo.m_Instance.SetMaskValueDelegate, flagValues);\n                EditorGUIUtility.keyboardControl = controlID;\n            }\n            return mask;\n        }\n    }\n}\n\n#pragma warning restore 618 // restore obsolete warning\n"
  },
  {
    "path": "Editor/Mono/EditorGUI.RenderPipeline.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n﻿using UnityEditor.Rendering;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public partial class EditorGUI\n    {\n        static readonly int s_RenderingLayerMaskField = nameof(s_RenderingLayerMaskField).GetHashCode();\n\n        // Make a field for rendering layer masks.\n        public static void RenderingLayerMaskField(Rect position, string label, SerializedProperty property)\n        {\n            RenderingLayerMaskFieldInternal(position, new GUIContent(label), property.uintValue, property, EditorStyles.layerMaskField);\n        }\n\n        public static void RenderingLayerMaskField(Rect position, GUIContent label, SerializedProperty property)\n        {\n            RenderingLayerMaskFieldInternal(position, label, property.uintValue, property, EditorStyles.layerMaskField);\n        }\n\n        public static RenderingLayerMask RenderingLayerMaskField(Rect position, string label, RenderingLayerMask layers)\n        {\n            return RenderingLayerMaskField(position, label, layers, EditorStyles.layerMaskField);\n        }\n\n        public static RenderingLayerMask RenderingLayerMaskField(Rect position, string label, RenderingLayerMask layers, GUIStyle style)\n        {\n            return RenderingLayerMaskField(position, new GUIContent(label), layers, style);\n        }\n\n        public static RenderingLayerMask RenderingLayerMaskField(Rect position, GUIContent label, RenderingLayerMask layers)\n        {\n            return RenderingLayerMaskField(position, label, layers, EditorStyles.layerMaskField);\n        }\n\n        public static RenderingLayerMask RenderingLayerMaskField(Rect position, GUIContent label, RenderingLayerMask layers, GUIStyle style)\n        {\n            return RenderingLayerMaskFieldInternal(position, label, layers, null, style);\n        }\n\n        static uint RenderingLayerMaskFieldInternal(Rect position, GUIContent label, uint layers, SerializedProperty property, GUIStyle style)\n        {\n            var (names, values) = RenderPipelineEditorUtility.GetRenderingLayerNamesAndValuesForMask(layers);\n            var bitCount = RenderPipelineEditorUtility.GetActiveMaxRenderingLayers();\n\n            BeginChangeCheck();\n            var mixedValue = property is { hasMultipleDifferentValues: true };\n            var newValue = DrawMaskField(position, label, layers, names, values, style, mixedValue, !RenderPipelineEditorUtility.DoesMaskContainRenderingLayersOutsideOfMaxBitCount(layers, bitCount));\n            var uintValue = unchecked((uint)newValue);\n\n            if (EndChangeCheck())\n            {\n                if (uintValue != uint.MaxValue && BitOperationUtils.AreAllBitsSetForValues(uintValue, values, bitCount))\n                        uintValue = uint.MaxValue;\n\n                if(property != null)\n                    ApplyModifiedProperties(property, uintValue);\n            }\n\n            if (RenderPipelineEditorUtility.DoesMaskContainRenderingLayersOutsideOfMaxBitCount(uintValue, bitCount))\n                EditorGUILayout.HelpBox(RenderPipelineEditorUtility.GetOutsideOfMaxBitCountWarningMessage(bitCount), MessageType.Warning);\n\n            return uintValue;\n        }\n\n        static int DrawMaskField(Rect position, GUIContent label, uint layers, string[] names, int[] values, GUIStyle style, bool mixedValue, bool autoSelectEverything)\n        {\n            var id = GUIUtility.GetControlID(s_RenderingLayerMaskField, FocusType.Keyboard, position);\n            if (label != null)\n                position = PrefixLabel(position, id, label);\n\n            using var scope = new MixedValueScope(mixedValue);\n\n            return MaskFieldGUI.DoMaskField(position, id, unchecked((int)layers), names, values, style, autoSelectEverything: autoSelectEverything);\n        }\n\n        static void ApplyModifiedProperties(SerializedProperty property, uint uintValue)\n        {\n            var bits = property.FindPropertyRelative(\"m_Bits\");\n            Debug.Assert(bits != null, $\"Property for RenderingLayerMask doesn't contain m_Bits. You should use new {nameof(RenderingLayerMask)} type with this drawer.\");\n            bits.uintValue = uintValue;\n            property.serializedObject.ApplyModifiedProperties();\n            property.serializedObject.SetIsDifferentCacheDirty();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics.CodeAnalysis;\nusing System.Globalization;\nusing System.Text.RegularExpressions;\nusing UnityEditor.SceneManagement;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing UnityEngine.Rendering;\nusing UnityEditorInternal;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing Object = UnityEngine.Object;\nusing Event = UnityEngine.Event;\nusing UnityEditor.StyleSheets;\nusing UnityEditor.VersionControl;\nusing UnityEngine.Internal;\nusing VirtualTexturing = UnityEngine.Rendering.VirtualTexturing;\nusing PreviewMaterialType = UnityEditor.EditorGUIUtility.PreviewType;\nusing System.Linq;\nusing System.Reflection;\nusing Unity.Profiling;\nusing UnityEditor.Rendering;\nusing UnityEngine.Experimental.Rendering;\nusing UnityEngine.UIElements;\nusing UnityEditor.UIElements;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    // Class for editor-only GUI. This class contains general purpose 2D additions to UnityGUI.\n    // These work pretty much like the normal GUI functions - and also have matching implementations in [[EditorGUILayout]]\n    [SuppressMessage(\"ReSharper\", \"NotAccessedField.Local\")]\n    public sealed partial class EditorGUI\n    {\n        private static RecycledTextEditor activeEditor;\n\n        internal static DelayedTextEditor s_DelayedTextEditorInternal;\n        internal static DelayedTextEditor s_DelayedTextEditor => s_DelayedTextEditorInternal ??= new();\n\n        internal static RecycledTextEditor s_RecycledEditorInternal;\n        internal static RecycledTextEditor s_RecycledEditor => s_RecycledEditorInternal ??= new();\n\n        internal static string s_OriginalText = \"\";\n        internal static string s_RecycledCurrentEditingString;\n        private static bool bKeyEventActive = false;\n\n        internal static bool s_DragToPosition = false;\n        internal static bool s_Dragged = false;\n        internal static bool s_SelectAllOnMouseUp = true;\n\n        private const double kFoldoutExpandTimeout = 0.7;\n        private static double s_FoldoutDestTime;\n        private static int s_DragUpdatedOverID = 0;\n\n        private const int kSearchFieldTextLimit = 1024;\n        private static bool s_SearchFieldTextLimitApproved = false;\n        private static int s_SavekeyboardControl = 0;\n\n        private static readonly int s_FoldoutHash = \"Foldout\".GetHashCode();\n        private static readonly int s_TagFieldHash = \"s_TagFieldHash\".GetHashCode();\n        private static readonly int s_PPtrHash = \"s_PPtrHash\".GetHashCode();\n        private static readonly int s_ObjectFieldHash = \"s_ObjectFieldHash\".GetHashCode();\n        private static readonly int s_ToggleHash = \"s_ToggleHash\".GetHashCode();\n        private static readonly int s_ColorHash = \"s_ColorHash\".GetHashCode();\n        private static readonly int s_CurveHash = \"s_CurveHash\".GetHashCode();\n        private static readonly int s_LayerMaskField = \"s_LayerMaskField\".GetHashCode();\n        private static readonly int s_MaskField = \"s_MaskField\".GetHashCode();\n        private static readonly int s_EnumFlagsField = \"s_EnumFlagsField\".GetHashCode();\n        private static readonly int s_GenericField = \"s_GenericField\".GetHashCode();\n        private static readonly int s_PopupHash = \"EditorPopup\".GetHashCode();\n        private static readonly int s_KeyEventFieldHash = \"KeyEventField\".GetHashCode();\n        private static readonly int s_TextFieldHash = \"EditorTextField\".GetHashCode();\n        private static readonly int s_SearchFieldHash = \"EditorSearchField\".GetHashCode();\n        private static readonly int s_TextAreaHash = \"EditorTextField\".GetHashCode();\n        private static readonly int s_PasswordFieldHash = \"PasswordField\".GetHashCode();\n        private static readonly int s_FloatFieldHash = \"EditorTextField\".GetHashCode();\n        private static readonly int s_DelayedTextFieldHash = \"DelayedEditorTextField\".GetHashCode();\n        private static readonly int s_ArraySizeFieldHash = \"ArraySizeField\".GetHashCode();\n        private static readonly int s_SliderHash = \"EditorSlider\".GetHashCode();\n        private static readonly int s_SliderKnobHash = \"EditorSliderKnob\".GetHashCode();\n        private static readonly int s_MinMaxSliderHash = \"EditorMinMaxSlider\".GetHashCode();\n        private static readonly int s_TitlebarHash = \"GenericTitlebar\".GetHashCode();\n        private static readonly int s_ProgressBarHash = \"s_ProgressBarHash\".GetHashCode();\n        private static readonly int s_SelectableLabelHash = \"s_SelectableLabel\".GetHashCode();\n        private static readonly int s_SortingLayerFieldHash = \"s_SortingLayerFieldHash\".GetHashCode();\n        private static readonly int s_TextFieldDropDownHash = \"s_TextFieldDropDown\".GetHashCode();\n\n        private enum DragCandidateState\n        {\n            NotDragging,\n            InitiatedDragging,\n            CurrentlyDragging\n        }\n        private static DragCandidateState s_DragCandidateState = DragCandidateState.NotDragging;\n        private const float kDragDeadzone = 16;\n        private static Vector2 s_DragStartPos;\n        private static double s_DragStartValue = 0;\n        private static long s_DragStartIntValue = 0;\n        private static double s_DragSensitivity = 0;\n        private static readonly GUIContent s_LargerChar = EditorGUIUtility.TextContent(\"W\");\n        // kMiniLabelW is used for all the PrefixLabelWidths irrsepective of the character,to fix the case 1297283\n        internal static float kMiniLabelW => EditorGUI.CalcPrefixLabelWidth(s_LargerChar);\n        internal const float kPrefixPaddingRight = 2;\n        internal const float kLabelW = 80;\n        internal const float kSpacing = 5;\n        internal const float kSpacingSubLabel = 4;\n        internal const float kSliderMinW = 50;\n        internal const float kSliderMaxW = 100;\n        internal const float kSingleLineHeight = 18f;\n        internal const float kSingleSmallLineHeight = 16f;\n        internal const float kStructHeaderLineHeight = 18;\n        internal const float kObjectFieldThumbnailHeight = 64;\n        internal const float kObjectFieldMiniThumbnailHeight = 18f;\n        internal const float kObjectFieldMiniThumbnailWidth = 32f;\n        internal const float kLabelWidthRatio = 0.45f;\n        internal const float kLabelWidthPadding = 3f;\n        internal const float kLabelWidthMargin = 40f;\n        internal const float kMinLabelWidth = 120f;\n        internal static string kFloatFieldFormatString = UINumericFieldsUtils.k_FloatFieldFormatString;\n        internal static string kDoubleFieldFormatString = UINumericFieldsUtils.k_DoubleFieldFormatString;\n        internal static string kIntFieldFormatString = UINumericFieldsUtils.k_IntFieldFormatString;\n        internal static int ms_IndentLevel = 0;\n        internal const float kIndentPerLevel = 15;\n        internal const int kControlVerticalSpacingLegacy = 2;\n        internal const int kDefaultSpacing = 6;\n        internal static readonly SVC<float> kControlVerticalSpacing = new SVC<float>(\"--theme-control-vertical-spacing\", 2.0f);\n        internal static readonly SVC<float> kVerticalSpacingMultiField = new SVC<float>(\"--theme-multifield-vertical-spacing\", 0.0f);\n\n        internal static string s_UnitString = \"\";\n        internal const int kInspTitlebarIconWidth = 16;\n        internal const int kInspTitlebarFoldoutIconWidth = 13;\n        internal static readonly SVC<float> kWindowToolbarHeight = new SVC<float>(\"--window-toolbar-height\", 21f);\n        internal const int kTabButtonHeight = 22;\n        internal const int kLargeButtonHeight = 24;\n        private const string kEnabledPropertyName = \"m_Enabled\";\n        private const string k_MultiEditValueString = \"<>\";\n        private const float kDropDownArrowMargin = 2;\n        private const float kDropDownArrowWidth = 12;\n        private const float kDropDownArrowHeight = 12;\n\n        private static readonly float[] s_Vector2Floats = {0, 0};\n        private static readonly int[] s_Vector2Ints = { 0, 0 };\n        private static readonly GUIContent[] s_XYLabels = {EditorGUIUtility.TextContent(\"X\"), EditorGUIUtility.TextContent(\"Y\")};\n\n        private static readonly float[] s_Vector3Floats = {0, 0, 0};\n        private static readonly int[] s_Vector3Ints = { 0, 0, 0 };\n        private static readonly GUIContent[] s_XYZLabels = {EditorGUIUtility.TextContent(\"X\"), EditorGUIUtility.TextContent(\"Y\"), EditorGUIUtility.TextContent(\"Z\")};\n\n        private static readonly float[] s_Vector4Floats = {0, 0, 0, 0};\n        private static readonly GUIContent[] s_XYZWLabels = {EditorGUIUtility.TextContent(\"X\"), EditorGUIUtility.TextContent(\"Y\"), EditorGUIUtility.TextContent(\"Z\"), EditorGUIUtility.TextContent(\"W\")};\n\n        private const float kQuaternionFloatPrecision = 1e-6f;\n\n        private static readonly GUIContent[] s_WHLabels = {EditorGUIUtility.TextContent(\"W\"), EditorGUIUtility.TextContent(\"H\")};\n\n        private static readonly GUIContent s_CenterLabel = EditorGUIUtility.TrTextContent(\"Center\");\n        private static readonly GUIContent s_ExtentLabel = EditorGUIUtility.TrTextContent(\"Extent\");\n        private static readonly GUIContent s_PositionLabel = EditorGUIUtility.TrTextContent(\"Position\");\n        private static readonly GUIContent s_SizeLabel = EditorGUIUtility.TrTextContent(\"Size\");\n        internal static GUIContent s_PleasePressAKey = EditorGUIUtility.TrTextContent(\"[Please press a key]\");\n\n        internal static readonly GUIContent s_ClipingPlanesLabel = EditorGUIUtility.TrTextContent(\"Clipping Planes\", \"The distances from the Camera where rendering starts and stops.\");\n        internal static readonly GUIContent[] s_NearAndFarLabels = { EditorGUIUtility.TrTextContent(\"Near\", \"The closest point to the Camera where drawing occurs.\"), EditorGUIUtility.TrTextContent(\"Far\", \"The furthest point from the Camera that drawing occurs.\") };\n        internal const float kNearFarLabelsWidth = 35f;\n\n        private static int s_ColorPickID;\n\n        private static int s_CurveID;\n        internal static Color kCurveColor = Color.green;\n        internal static Color kCurveBGColor = new Color(0.337f, 0.337f, 0.337f, 1f);\n        internal static EditorGUIUtility.SkinnedColor kSplitLineSkinnedColor = new EditorGUIUtility.SkinnedColor(new Color(0.6f, 0.6f, 0.6f, 1.333f), new Color(0.12f, 0.12f, 0.12f, 1.333f));\n\n        internal static Color k_OverrideMarginColor = new Color(1f / 255f, 153f / 255f, 235f / 255f, 0.75f);\n        internal static Color k_OverrideMarginColorSelected = new Color(239f / 255f, 239f / 255f, 239f / 239f, 1f);\n        internal static Color k_OverrideMarginColorNotApplicable = new Color(1f / 255f, 153f / 255f, 235f / 255f, 0.35f);\n\n        internal static Color k_LiveModifiedMarginLightThemeColor = new Color(183f / 255f, 60f / 255f, 21f / 255f, 1f);\n        internal static Color k_LiveModifiedMarginDarkThemeColor = new Color(255f / 255f, 165f / 255f, 60f / 255f, 1f);\n\n        private const int kInspTitlebarSpacing = 4;\n        private static readonly GUIContent s_PropertyFieldTempContent = new GUIContent();\n        private static GUIContent s_IconDropDown;\n        private static Material s_IconTextureInactive;\n\n        private static bool s_HasPrefixLabel;\n        private static readonly GUIContent s_PrefixLabel = new GUIContent((string)null);\n        private static Rect s_PrefixTotalRect;\n        private static Rect s_PrefixRect;\n        private static GUIStyle s_PrefixStyle;\n        private static GUIStyle s_IconButtonStyle;\n        private static Color s_PrefixGUIColor;\n\n        private static string s_LabelHighlightContext;\n        private static Color s_LabelHighlightColor;\n        private static Color s_LabelHighlightSelectionColor;\n\n        private static string[] m_FlagNames;\n        private static int[] m_FlagValues;\n        internal static float lineHeight { get; set; } = kSingleLineHeight;\n\n        // Makes the following controls give the appearance of editing multiple different values.\n        public static bool showMixedValue { get; set; }\n\n        private static readonly GUIContent s_MixedValueContent = EditorGUIUtility.TrTextContent(\"\\u2014\", \"Mixed Values\");\n\n        internal static GUIContent mixedValueContent => s_MixedValueContent;\n\n        private static readonly Color s_MixedValueContentColor = new Color(1, 1, 1, 0.5f);\n        private static Color s_MixedValueContentColorTemp = Color.white;\n\n        internal static SavedBool s_ShowRepaintDots = new SavedBool(\"ShowRepaintDots\", true);\n\n        internal static readonly Regex s_ATagRegex = new Regex(@\"(?<=\\b=\"\")[^\"\"]*\");\n        internal static readonly Regex s_LinkTagRegex = new Regex(@\"(?<=\\b=')[^']*\");\n\n        static class Styles\n        {\n            public static Texture2D prefabOverlayAddedIcon = EditorGUIUtility.LoadIcon(\"PrefabOverlayAdded Icon\");\n            public static Texture2D prefabOverlayRemovedIcon = EditorGUIUtility.LoadIcon(\"PrefabOverlayRemoved Icon\");\n            public static readonly GUIStyle linkButton = \"FloatFieldLinkButton\";\n            public static Texture2D repaintDot = EditorGUIUtility.LoadIcon(\"RepaintDot\");\n            public static string revertPropertyValueIdenticalToSource = L10n.Tr(\"Revert (identical value to Prefab '{0}')\");\n        }\n\n        static EditorGUI()\n        {\n            hyperLinkClicked += EditorGUI_OpenFileOnHyperLinkClicked;\n        }\n\n        internal static void BeginHandleMixedValueContentColor()\n        {\n            s_MixedValueContentColorTemp = GUI.contentColor;\n            GUI.contentColor = showMixedValue ? (GUI.contentColor * s_MixedValueContentColor) : GUI.contentColor;\n        }\n\n        internal static void EndHandleMixedValueContentColor()\n        {\n            GUI.contentColor = s_MixedValueContentColorTemp;\n        }\n\n        [RequiredByNativeCode]\n        internal static bool IsEditingTextField()\n        {\n            return RecycledTextEditor.s_ActuallyEditing && activeEditor != null;\n        }\n\n        internal static void EndEditingActiveTextField()\n        {\n            activeEditor?.EndEditing();\n        }\n\n        public static void FocusTextInControl(string name)\n        {\n            GUI.FocusControl(name);\n            EditorGUIUtility.editingTextField = true;\n        }\n\n        // STACKS\n\n        internal static void ClearStacks()\n        {\n            s_EnabledStack.Clear();\n            s_IsInsideListStack.Clear();\n            GUI.isInsideList = false;\n            s_ChangedStack.Clear();\n            s_PropertyStack.Clear();\n            MaterialProperty.ClearStack();\n            ScriptAttributeUtility.s_DrawerStack.Clear();\n            s_FoldoutHeaderGroupActive = 0;\n        }\n\n        private static readonly Stack<PropertyGUIData> s_PropertyStack = new Stack<PropertyGUIData>();\n\n        private static readonly Stack<bool> s_EnabledStack = new Stack<bool>();\n        private static readonly Stack<(bool insideList, int depth)> s_IsInsideListStack = new Stack<(bool insideList, int depth)>();\n\n        // @TODO: API soon to be deprecated but still in a grace period; documentation states that users\n        //        are encouraged to use EditorGUI.DisabledScope instead. Uncomment next line when appropriate.\n        // [System.Obsolete(\"Use DisabledScope instead\", false)]\n        public class DisabledGroupScope : GUI.Scope\n        {\n            public DisabledGroupScope(bool disabled)\n            {\n                BeginDisabledGroup(disabled);\n            }\n\n            protected override void CloseScope()\n            {\n                EndDisabledGroup();\n            }\n        }\n\n        // Create a group of controls that can be disabled.\n        // @TODO: API soon to be deprecated but still in a grace period; documentation states that users\n        //        are encouraged to use EditorGUI.DisabledScope instead. Uncomment next line when appropriate.\n        // [System.Obsolete(\"Use DisabledScope instead\", false)]\n        public static void BeginDisabledGroup(bool disabled)\n        {\n            BeginDisabled(disabled);\n        }\n\n        // Ends a disabled group started with BeginDisabledGroup.\n        // @TODO: API soon to be deprecated but still in a grace period; documentation states that users\n        //        are encouraged to use EditorGUI.DisabledScope instead. Uncomment next line when appropriate.\n        // [System.Obsolete(\"Use DisabledScope instead\", false)]\n        public static void EndDisabledGroup()\n        {\n            EndDisabled();\n        }\n\n        public struct DisabledScope : IDisposable\n        {\n            bool m_Disposed;\n\n            public DisabledScope(bool disabled)\n            {\n                m_Disposed = false;\n\n                BeginDisabled(disabled);\n            }\n\n            public void Dispose()\n            {\n                if (m_Disposed)\n                    return;\n                m_Disposed = true;\n                if (!GUIUtility.guiIsExiting)\n                    EndDisabled();\n            }\n        }\n\n        internal class DisabledGuiViewInputScope : GUI.Scope\n        {\n            GUIView m_View;\n            bool m_WasDisabled;\n\n            public DisabledGuiViewInputScope(GUIView view, bool disabled)\n            {\n                m_View = view;\n                if (m_View != null)\n                {\n                    m_WasDisabled = view.disableInputEvents;\n                    m_View.disableInputEvents = disabled;\n                }\n            }\n\n            protected override void CloseScope()\n            {\n                if (m_View != null)\n                    m_View.disableInputEvents = m_WasDisabled;\n            }\n        }\n\n        internal struct LabelHighlightScope : IDisposable\n        {\n            bool m_Disposed;\n\n            public LabelHighlightScope(string labelHighlightContext, Color selectionColor, Color textColor)\n            {\n                m_Disposed = false;\n                BeginLabelHighlight(labelHighlightContext, selectionColor, textColor);\n            }\n\n            public void Dispose()\n            {\n                if (m_Disposed)\n                    return;\n                m_Disposed = true;\n                if (!GUIUtility.guiIsExiting)\n                    EndLabelHighlight();\n            }\n        }\n\n        internal struct CursorColorScope : IDisposable\n        {\n            private Color oldCursorColor;\n\n            public CursorColorScope(Color color)\n            {\n                oldCursorColor = GUI.skin.settings.cursorColor;\n                GUI.skin.settings.cursorColor = color;\n            }\n\n            public void Dispose()\n            {\n                GUI.skin.settings.cursorColor = oldCursorColor;\n            }\n        }\n\n        // Create a group of controls that can be disabled.\n        internal static void BeginDisabled(bool disabled)\n        {\n            s_EnabledStack.Push(GUI.enabled);\n            GUI.enabled &= !disabled;\n        }\n\n        // Ends a disabled group started with BeginDisabled.\n        internal static void EndDisabled()\n        {\n            // Stack might have been cleared with ClearStack(), check before pop.\n            if (s_EnabledStack.Count > 0)\n                GUI.enabled = s_EnabledStack.Pop();\n        }\n\n        internal static void BeginIsInsideList(int depth)\n        {\n            s_IsInsideListStack.Push((GUI.isInsideList, depth));\n            GUI.isInsideList = true;\n        }\n\n        internal static int GetInsideListDepth()\n        {\n            if (s_IsInsideListStack.Count > 0)\n                return s_IsInsideListStack.Peek().depth;\n            return -1;\n        }\n\n        internal static void EndIsInsideList()\n        {\n            // Stack might have been cleared with ClearStack(), check before pop.\n            if (s_IsInsideListStack.Count > 0)\n                GUI.isInsideList = s_IsInsideListStack.Pop().insideList;\n            else\n                GUI.isInsideList = false;\n        }\n\n        private static readonly Stack<bool> s_ChangedStack = new Stack<bool>();\n\n        public class ChangeCheckScope : GUI.Scope\n        {\n            bool m_ChangeChecked;\n            bool m_Changed;\n            public bool changed\n            {\n                get\n                {\n                    if (!m_ChangeChecked)\n                    {\n                        m_ChangeChecked = true;\n                        m_Changed = EndChangeCheck();\n                    }\n                    return m_Changed;\n                }\n            }\n\n            public ChangeCheckScope()\n            {\n                BeginChangeCheck();\n            }\n\n            protected override void CloseScope()\n            {\n                if (!m_ChangeChecked)\n                    EndChangeCheck();\n            }\n        }\n\n        // Check if any control was changed inside a block of code.\n        public static void BeginChangeCheck()\n        {\n            s_ChangedStack.Push(GUI.changed);\n            GUI.changed = false;\n        }\n\n        // Ends a change check started with BeginChangeCheck ().\n        // Note: BeginChangeCheck/EndChangeCheck supports nesting\n        // For ex.,\n        //   BeginChangeCheck()\n        //     BeginChangeCheck()\n        //      <GUI control changes>\n        //     EndChangeCheck() <-- will return true\n        //   EndChangeCheck() <-- will return true\n        public static bool EndChangeCheck()\n        {\n            // as we allow external code to clear stacks through ClearStacks(),\n            // we must be resilient to stacks having been unexpectedly emptied,\n            // when that happens, it is reasonable to assume things indeed have changed\n            if (s_ChangedStack.Count == 0)\n            {\n                GUI.changed = true;\n                return true;\n            }\n\n            bool changed = GUI.changed;\n            GUI.changed |= s_ChangedStack.Pop();\n            return changed;\n        }\n\n        public struct MixedValueScope : IDisposable\n        {\n            bool m_DefaultMixedValue;\n\n            public MixedValueScope(bool newMixedValue)\n            {\n                m_DefaultMixedValue = showMixedValue;\n                showMixedValue = newMixedValue;\n            }\n            void IDisposable.Dispose()\n            {\n                showMixedValue = m_DefaultMixedValue;\n            }\n        }\n\n        internal class RecycledTextEditor : TextEditor\n        {\n            internal static bool s_ActuallyEditing = false; // internal so we can save this state.\n            internal static bool s_EditingWasCompleted = false; // internal so we can save this state.\n            internal static bool s_AllowContextCutOrPaste = true; // e.g. selectable labels only allow for copying\n            private long[] s_OriginalLongValues;\n            private double[] s_OriginalDoubleValues;\n\n            IMECompositionMode m_IMECompositionModeBackup;\n\n            public long[] GetOriginalLongValues()\n            {\n                return s_OriginalLongValues;\n            }\n\n            public double[] GetOriginalDoubleValues()\n            {\n                return s_OriginalDoubleValues;\n            }\n\n            internal bool IsEditingControl(int id)\n            {\n                return GUIUtility.keyboardControl == id && controlID == id && s_ActuallyEditing && GUIView.current.hasFocus;\n            }\n\n            public virtual void BeginEditing(int id, string newText, Rect position, GUIStyle style, bool multiline, bool passwordField)\n            {\n                if (IsEditingControl(id))\n                {\n                    return;\n                }\n\n                activeEditor?.EndEditing();\n\n                activeEditor = this;\n                controlID = id;\n                text = s_OriginalText = newText;\n                isMultiline = multiline;\n                this.position = position;\n                this.style = style;\n                isPasswordField = passwordField;\n                s_ActuallyEditing = true;\n                scrollOffset = Vector2.zero;\n                UnityEditor.Undo.IncrementCurrentGroup();\n\n                m_IMECompositionModeBackup = Input.imeCompositionMode;\n                Input.imeCompositionMode = IMECompositionMode.On;\n\n                if (EditorGUI.s_PropertyStack.Count > 0)\n                {\n                    var property = EditorGUI.s_PropertyStack.Peek().property;\n\n                    switch (property.propertyType)\n                    {\n                        case SerializedPropertyType.Integer:\n                            s_OriginalLongValues = new long[property.serializedObject.targetObjectsCount];\n                            property.allLongValues.CopyTo(s_OriginalLongValues, 0);\n                            break;\n\n                        case SerializedPropertyType.Float:\n                            s_OriginalDoubleValues = new double[property.serializedObject.targetObjectsCount];\n                            property.allDoubleValues.CopyTo(s_OriginalDoubleValues, 0);\n                            break;\n\n                        default:\n                            s_OriginalDoubleValues = null;\n                            s_OriginalLongValues = null;\n                            break;\n                    }\n                }\n            }\n\n            public virtual void EndEditing()\n            {\n                if (activeEditor == this)\n                {\n                    activeEditor.m_HasFocus = false;\n                    activeEditor = null;\n                }\n\n                controlID = 0;\n                s_ActuallyEditing = false;\n                s_EditingWasCompleted = false;\n                s_AllowContextCutOrPaste = true;\n                UnityEditor.Undo.IncrementCurrentGroup();\n\n                Input.imeCompositionMode = m_IMECompositionModeBackup;\n            }\n        }\n\n        // There can be two way something can get focus\n        internal sealed class DelayedTextEditor : RecycledTextEditor\n        {\n            private int controlThatHadFocus = 0, messageControl = 0;\n            internal string controlThatHadFocusValue = \"\";\n            private GUIView viewThatHadFocus;\n            private bool m_CommitCommandSentOnLostFocus;\n            private const string CommitCommand = \"DelayedControlShouldCommit\";\n\n            private bool m_IgnoreBeginGUI = false;\n\n            public void BeginGUI()\n            {\n                if (m_IgnoreBeginGUI)\n                {\n                    return;\n                }\n                if (GUIUtility.keyboardControl == controlID)\n                {\n                    controlThatHadFocus = GUIUtility.keyboardControl;\n                    controlThatHadFocusValue = text;\n                    viewThatHadFocus = GUIView.current;\n                }\n                else\n                {\n                    controlThatHadFocus = 0;\n                }\n            }\n\n            public void EndGUI(EventType type)\n            {\n                int sendID = 0;\n                if (controlThatHadFocus != 0 && controlThatHadFocus != GUIUtility.keyboardControl)\n                {\n                    sendID = controlThatHadFocus;\n                    controlThatHadFocus = 0;\n                }\n\n                if (sendID != 0 && !m_CommitCommandSentOnLostFocus)\n                {\n                    messageControl = sendID;\n                    //              Debug.Log (\"\" + messageControl + \" lost focus to \" + GUIUtility.keyboardControl+ \" in \" + type+\". Sending Message. value:\" + controlThatHadFocusValue);\n                    m_IgnoreBeginGUI = true;\n\n                    // Explicitly set the keyboardControl for the view that had focus in preparation for the following SendEvent,\n                    // but only if the current view is the view that had focus.\n                    // This is necessary as GUIView::OnInputEvent (native) will load the old keyboardControl for nested OnGUI calls.\n                    if (GUIView.current == viewThatHadFocus)\n                        viewThatHadFocus.SetKeyboardControl(GUIUtility.keyboardControl);\n\n                    viewThatHadFocus.SendEvent(EditorGUIUtility.CommandEvent(CommitCommand));\n                    m_IgnoreBeginGUI = false;\n                    //              Debug.Log (\"Afterwards: \" + GUIUtility.keyboardControl);\n                    messageControl = 0;\n                }\n            }\n\n            public override void EndEditing()\n            {\n                //The following block handles the case where a different window is focus while editing delayed text box\n                if (Event.current == null)\n                {\n                    // We set this flag because of a bug that was trigger when you switched focus to another window really fast\n                    // right after focusing on the text box. For some reason keyboardControl was changed and the commit message\n                    // was being sent twice which caused layout issues.\n                    m_CommitCommandSentOnLostFocus = true;\n                    m_IgnoreBeginGUI = true;\n                    messageControl = controlID;\n                    var temp = GUIUtility.keyboardControl;\n                    if (viewThatHadFocus != null)\n                    {\n                        viewThatHadFocus.SetKeyboardControl(0);\n\n                        viewThatHadFocus.SendEvent(EditorGUIUtility.CommandEvent(CommitCommand));\n\n                        viewThatHadFocus.SetKeyboardControl(temp);\n                    }\n                    m_IgnoreBeginGUI = false;\n                    messageControl = 0;\n                }\n\n                base.EndEditing();\n            }\n\n            public string OnGUI(int id, string value, out bool changed)\n            {\n                Event evt = Event.current;\n                if (evt.type == EventType.ExecuteCommand && evt.commandName == CommitCommand && id == messageControl)\n                {\n                    m_CommitCommandSentOnLostFocus = false;\n                    // Only set changed to true if the value has actually changed. Otherwise EditorGUI.EndChangeCheck will report false positives,\n                    // which could for example cause unwanted undo's to be registered (in the case of e.g. editing terrain resolution, this can cause several seconds of delay)\n                    if (!showMixedValue || controlThatHadFocusValue != k_MultiEditValueString)\n                        changed = value != controlThatHadFocusValue;\n                    else\n                        changed = false;\n                    evt.Use();\n                    messageControl = 0;\n                    return controlThatHadFocusValue;\n                }\n                changed = false;\n\n                return value;\n            }\n        }\n\n        internal sealed class PopupMenuEvent\n        {\n            public string commandName;\n            public GUIView receiver;\n\n            public PopupMenuEvent(string cmd, GUIView v)\n            {\n                commandName = cmd;\n                receiver = v;\n            }\n\n            public void SendEvent()\n            {\n                if (receiver)\n                {\n                    receiver.SendEvent(EditorGUIUtility.CommandEvent(commandName));\n                }\n                else\n                {\n                    Debug.LogError(\"BUG: We don't have a receiver set up, please report\");\n                }\n            }\n        }\n\n        static void ShowTextEditorPopupMenu()\n        {\n            GenericMenu pm = new GenericMenu();\n            var enabled = GUI.enabled;\n\n            // Cut\n            if (RecycledTextEditor.s_AllowContextCutOrPaste)\n            {\n                if ((s_RecycledEditor.hasSelection || s_DelayedTextEditor.hasSelection) && !s_RecycledEditor.isPasswordField && enabled && !EditorGUI.showMixedValue)\n                    pm.AddItem(EditorGUIUtility.TrTextContent(\"Cut\"), false, new PopupMenuEvent(EventCommandNames.Cut, GUIView.current).SendEvent);\n                else\n                    pm.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Cut\"));\n            }\n\n            // Copy -- when GUI is disabled, allow Copy even with no selection (will copy everything)\n            if (((s_RecycledEditor.hasSelection || s_DelayedTextEditor.hasSelection) || !enabled) && !s_RecycledEditor.isPasswordField && !EditorGUI.showMixedValue)\n                pm.AddItem(EditorGUIUtility.TrTextContent(\"Copy\"), false, new PopupMenuEvent(EventCommandNames.Copy, GUIView.current).SendEvent);\n            else\n                pm.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Copy\"));\n\n            // Paste\n            if (s_RecycledEditor.CanPaste() && RecycledTextEditor.s_AllowContextCutOrPaste && enabled)\n            {\n                pm.AddItem(EditorGUIUtility.TrTextContent(\"Paste\"), false, new PopupMenuEvent(EventCommandNames.Paste, GUIView.current).SendEvent);\n            }\n            else\n            {\n                // pm.AddDisabledItem (EditorGUIUtility.TrTextContent (\"Paste\"));\n            }\n\n            pm.ShowAsContext();\n        }\n\n        // Is the platform-dependent \"action\" modifier key held down? (RO)\n        public static bool actionKey\n        {\n            get\n            {\n                if (Event.current == null)\n                {\n                    return false;\n                }\n                if (Application.platform == RuntimePlatform.OSXEditor)\n                {\n                    return Event.current.command;\n                }\n                else\n                {\n                    return Event.current.control;\n                }\n            }\n        }\n\n        [RequiredByNativeCode]\n        internal static void BeginCollectTooltips()\n        {\n            isCollectingTooltips = true;\n        }\n\n        [RequiredByNativeCode]\n        internal static void EndCollectTooltips()\n        {\n            isCollectingTooltips = false;\n        }\n\n        public static void DropShadowLabel(Rect position, string text)\n        {\n            DoDropShadowLabel(position, EditorGUIUtility.TempContent(text), \"PreOverlayLabel\", .6f);\n        }\n\n        public static void DropShadowLabel(Rect position, GUIContent content)\n        {\n            DoDropShadowLabel(position, content, \"PreOverlayLabel\", .6f);\n        }\n\n        public static void DropShadowLabel(Rect position, string text, GUIStyle style)\n        {\n            DoDropShadowLabel(position, EditorGUIUtility.TempContent(text), style, .6f);\n        }\n\n        // Draws a label with a drop shadow.\n        public static void DropShadowLabel(Rect position, GUIContent content, GUIStyle style)\n        {\n            DoDropShadowLabel(position, content, style, .6f);\n        }\n\n        internal static void DoDropShadowLabel(Rect position, GUIContent content, GUIStyle style, float shadowOpa)\n        {\n            if (Event.current.type != EventType.Repaint)\n            {\n                return;\n            }\n\n            DrawLabelShadow(position, content, style, shadowOpa);\n            style.Draw(position, content, false, false, false, false);\n        }\n\n        internal static void DrawLabelShadow(Rect position, GUIContent content, GUIStyle style, float shadowOpa)\n        {\n            Color temp = GUI.color, temp2 = GUI.contentColor, temp3 = GUI.backgroundColor;\n\n            // Draw only background\n            GUI.contentColor = new Color(0, 0, 0, 0);\n            style.Draw(position, content, false, false, false, false);\n\n            // Blur foreground\n            position.y += 1;\n            GUI.backgroundColor = new Color(0, 0, 0, 0);\n            GUI.contentColor = temp2;\n            Draw4(position, content, 1, GUI.color.a * shadowOpa, style);\n            Draw4(position, content, 2, GUI.color.a * shadowOpa * .42f, style);\n\n            // Draw final foreground\n            GUI.color = temp;\n            GUI.backgroundColor = temp3;\n        }\n\n        private static void Draw4(Rect position, GUIContent content, float offset, float alpha, GUIStyle style)\n        {\n            GUI.color = new Color(0, 0, 0, alpha);\n            position.y -= offset;\n            style.Draw(position, content, false, false, false, false);\n            position.y += offset * 2;\n            style.Draw(position, content, false, false, false, false);\n            position.y -= offset;\n            position.x -= offset;\n            style.Draw(position, content, false, false, false, false);\n            position.x += offset * 2;\n            style.Draw(position, content, false, false, false, false);\n        }\n\n        private static string ValidateTextLimit(String editorText)\n        {\n            string title = \"Search String Character Limit Exceeded\";\n            string fullMessage = string.Format(\"You have entered {0} characters. The character limit is {1} characters because of risk of Editor slowdown. Please confirm that you would like to continue (not recommended) or clear the field\", editorText.Length, kSearchFieldTextLimit);\n            bool selectedContinueOption = EditorUtility.DisplayDialog(title, fullMessage, \"Continue\", \"Cancel\");\n            if (selectedContinueOption)\n                s_SearchFieldTextLimitApproved = true;\n            else\n                editorText = editorText.Substring(0, kSearchFieldTextLimit);\n\n            GUIUtility.SetKeyboardControlToLastControlId();\n            return editorText;\n        }\n\n        static bool IsPrintableChar(char c)\n        {\n            if (c < 32)\n            {\n                return false;\n            }\n            return true;\n        }\n\n        internal static bool MightBePrintableKey(Event evt)\n        {\n            if (evt.command || evt.control)\n                return false;\n            if (evt.keyCode >= KeyCode.Mouse0 && evt.keyCode <= KeyCode.Mouse6)\n                return false;\n            if (evt.keyCode >= KeyCode.JoystickButton0 && evt.keyCode <= KeyCode.Joystick8Button19)\n                return false;\n            if (evt.keyCode >= KeyCode.F1 && evt.keyCode <= KeyCode.F15 ||\n                // KeyCode.F15 (296) and KeyCode.F16 (670) are not contiguous\n                evt.keyCode >= KeyCode.F16 && evt.keyCode <= KeyCode.F24)\n                return false;\n            switch (evt.keyCode)\n            {\n                case KeyCode.AltGr:\n                case KeyCode.Backspace:\n                case KeyCode.CapsLock:\n                case KeyCode.Clear:\n                case KeyCode.Delete:\n                case KeyCode.DownArrow:\n                case KeyCode.End:\n                case KeyCode.Escape:\n                case KeyCode.Help:\n                case KeyCode.Home:\n                case KeyCode.Insert:\n                case KeyCode.LeftAlt:\n                case KeyCode.LeftArrow:\n                case KeyCode.LeftCommand: // same as LeftApple\n                case KeyCode.LeftControl:\n                case KeyCode.LeftShift:\n                case KeyCode.LeftWindows:\n                case KeyCode.Menu:\n                case KeyCode.Numlock:\n                case KeyCode.PageDown:\n                case KeyCode.PageUp:\n                case KeyCode.Pause:\n                case KeyCode.Print:\n                case KeyCode.RightAlt:\n                case KeyCode.RightArrow:\n                case KeyCode.RightCommand: // same as RightApple\n                case KeyCode.RightControl:\n                case KeyCode.RightShift:\n                case KeyCode.RightWindows:\n                case KeyCode.ScrollLock:\n                case KeyCode.SysReq:\n                case KeyCode.UpArrow:\n                    return false;\n                case KeyCode.None:\n                    return IsPrintableChar(evt.character);\n                default:\n                    return true;\n            }\n        }\n\n        static EventType GetEventTypeForControlAllowDisabledContextMenuPaste(Event evt, int id)\n        {\n            // UI is enabled: regular code path\n            var wasEnabled = GUI.enabled;\n            if (wasEnabled)\n                return evt.GetTypeForControl(id);\n\n            // UI is disabled: get type as if it was enabled\n            GUI.enabled = true;\n            var type = evt.GetTypeForControl(id);\n            GUI.enabled = false;\n\n            // these events are always processed, no matter the enabled/disabled state (IMGUI::GetEventType)\n            if (type == EventType.Repaint || type == EventType.Layout || type == EventType.Used)\n                return type;\n\n            // allow context / right click, and \"Copy\" commands\n            if (type == EventType.ContextClick)\n                return type;\n            if (type == EventType.MouseDown && evt.button == 1)\n                return type;\n            if ((type == EventType.ValidateCommand || type == EventType.ExecuteCommand) && evt.commandName == EventCommandNames.Copy)\n                return type;\n\n            // ignore all other events for disabled controls\n            return EventType.Ignore;\n        }\n\n        internal static string DoTextField(RecycledTextEditor editor, int id, Rect position, string text, GUIStyle style, string allowedletters, out bool changed, bool reset, bool multiline, bool passwordField)\n        {\n            return DoTextField(editor, id, position, text, style, allowedletters, out changed, reset, multiline, passwordField, null);\n        }\n\n        // Should we select all text from the current field when the mouse goes up?\n        // (We need to keep track of this to support both SwipeSelection & initial click selects all)\n        internal static string DoTextField(RecycledTextEditor editor, int id, Rect position, string text, GUIStyle style, string allowedletters, out bool changed, bool reset, bool multiline, bool passwordField, GUIStyle cancelButtonStyle, bool checkTextLimit = false)\n        {\n            Event evt = Event.current;\n\n            // If the text field represents multiple values, the text should always start out being empty when editing it.\n            // This empty text will not be saved when simply clicking in the text field, or tabbing to it,\n            // since GUI.changed is only set to true if the user alters the string.\n            // Nevertheless, we also backup and return the original value if nothing changed.\n            // It's just nice that output is the same as input when nothing changed,\n            // even if the output should really be ignored when GUI.changed is false.\n            string origText = text;\n\n            // We assume the text is actually valid, but we do not want to change the returned value if nothing was changed\n            // So we should only check for null string on the internal text and not affect the origText which will be returned if nothing changed\n            if (text == null)\n            {\n                text = string.Empty;\n            }\n\n            if (showMixedValue)\n            {\n                text = k_MultiEditValueString;\n            }\n\n            // If we have keyboard control and our window have focus, we need to sync up the editor.\n            if (HasKeyboardFocus(id) && Event.current.type != EventType.Layout)\n            {\n                // If the editor is already set up, we just need to sync position, etc...\n                if (editor.IsEditingControl(id))\n                {\n                    // Fast path flag to ensure that we only update the scroll offset if the text area grew (dynamic height)\n                    bool requireUpdateScrollOffset = editor.position.height != position.height;\n                    editor.position = position;\n                    editor.style = style;\n                    editor.controlID = id;\n                    editor.isMultiline = multiline;\n                    editor.isPasswordField = passwordField;\n                    editor.DetectFocusChange();\n                    editor.UpdateTextHandle();\n\n                    if (requireUpdateScrollOffset)\n                        editor.UpdateScrollOffset();\n                }\n                else if (EditorGUIUtility.editingTextField || (evt.GetTypeForControl(id) == EventType.ExecuteCommand && evt.commandName == EventCommandNames.NewKeyboardFocus))\n                {\n                    // This one is worse: we are the new keyboardControl, but didn't know about it.\n                    // this means a Tab operation or setting focus from code.\n                    editor.BeginEditing(id, text, position, style, multiline, passwordField);\n                    // If cursor is invisible, it's a selectable label, and we don't want to select all automatically\n                    if (GUI.skin.settings.cursorColor.a > 0)\n                        editor.SelectAll();\n\n                    if (evt.GetTypeForControl(id) == EventType.ExecuteCommand)\n                    {\n                        evt.Use();\n                    }\n                }\n            }\n\n            // Inform editor that someone removed focus from us or a rename operation was completed.\n            if (editor.controlID == id && GUIUtility.keyboardControl != id || EditorGUIUtility.renameWasCompleted || (evt.type == EventType.ValidateCommand && evt.commandName == EventCommandNames.UndoRedoPerformed))\n            {\n                editor.EndEditing();\n            }\n\n            bool mayHaveChanged = false;\n            string textBeforeKey = editor.text;\n\n            var wasEnabled = GUI.enabled;\n\n            switch (GetEventTypeForControlAllowDisabledContextMenuPaste(evt, id))\n            {\n                case EventType.ValidateCommand:\n                    if (GUIUtility.keyboardControl == id)\n                    {\n                        switch (evt.commandName)\n                        {\n                            case EventCommandNames.Cut:\n                            case EventCommandNames.Copy:\n                                if (editor.hasSelection)\n                                {\n                                    evt.Use();\n                                }\n                                break;\n                            case EventCommandNames.Paste:\n                                if (editor.CanPaste())\n                                {\n                                    evt.Use();\n                                }\n                                break;\n                            case EventCommandNames.SelectAll:\n                            case EventCommandNames.Delete:\n                                evt.Use();\n                                break;\n                            case EventCommandNames.UndoRedoPerformed:\n                                editor.text = text;\n                                evt.Use();\n                                break;\n                        }\n                    }\n\n                    break;\n                case EventType.ExecuteCommand:\n                    if (GUIUtility.keyboardControl == id)\n                    {\n                        switch (evt.commandName)\n                        {\n                            case EventCommandNames.OnLostFocus:\n                                activeEditor?.EndEditing();\n                                evt.Use();\n                                break;\n                            case EventCommandNames.Cut:\n                                editor.BeginEditing(id, text, position, style, multiline, passwordField);\n                                editor.Cut();\n                                mayHaveChanged = true;\n                                break;\n                            case EventCommandNames.Copy:\n                                if (wasEnabled)\n                                    editor.Copy();\n                                else if (!passwordField)\n                                    GUIUtility.systemCopyBuffer = text;\n                                evt.Use();\n                                break;\n                            case EventCommandNames.Paste:\n                                editor.BeginEditing(id, text, position, style, multiline, passwordField);\n                                editor.Paste();\n                                mayHaveChanged = true;\n                                break;\n                            case EventCommandNames.SelectAll:\n                                editor.SelectAll();\n                                evt.Use();\n                                break;\n                            case EventCommandNames.Delete:\n                                // This \"Delete\" command stems from a Shift-Delete in the text editor.\n                                // On Windows, Shift-Delete in text does a cut whereas on Mac, it does a delete.\n                                editor.BeginEditing(id, text, position, style, multiline, passwordField);\n                                if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.MacOSX)\n                                {\n                                    editor.Delete();\n                                }\n                                else\n                                {\n                                    editor.Cut();\n                                }\n                                mayHaveChanged = true;\n                                evt.Use();\n                                break;\n                        }\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        if (s_Dragged && s_DragToPosition)\n                        {\n                            //GUIUtility.keyboardControl = id;\n                            //editor.BeginEditing (id, text, position, style, multiline, passwordField);\n                            editor.MoveSelectionToAltCursor();\n                            mayHaveChanged = true;\n                        }\n                        else if (s_SelectAllOnMouseUp)\n                        {\n                            // If cursor is invisible, it's a selectable label, and we don't want to select all automatically\n                            if (GUI.skin.settings.cursorColor.a > 0)\n                            {\n                                editor.SelectAll();\n                            }\n                            s_SelectAllOnMouseUp = false;\n                        }\n                        else if (!s_Dragged && evt.button == 0)\n                        {\n                            // Extract hyperlink info\n                            Dictionary<string, string> hyperLinkData;\n\n                            if (editor.HasClickedOnHREF(Event.current.mousePosition, out string href))\n                            {\n                                Application.OpenURL(href);\n                            }\n                            else if (HasClickedOnHyperlink(editor, out hyperLinkData)) // Check if the cursor is between hyperlink tags and store the hyperlink info (tag arguments in a dictionary)\n                            {\n                                // Raise event with the info\n                                var window = GUIView.current is HostView hostView ? hostView.actualView : null;\n                                hyperLinkClicked(window, new UnityEditor.HyperLinkClickedEventArgs(hyperLinkData));\n                            }\n                        }\n                        editor.MouseDragSelectsWholeWords(false);\n                        s_DragToPosition = true;\n                        s_Dragged = false;\n                        if (evt.button == 0)\n                        {\n                            GUIUtility.hotControl = 0;\n                            evt.Use();\n                        }\n                    }\n                    break;\n                case EventType.MouseDown:\n                    if (position.Contains(evt.mousePosition) && evt.button == 0)\n                    {\n                        // Does this text field already have focus?\n                        if (editor.IsEditingControl(id))\n                        { // if so, process the event normally\n                            if (Event.current.clickCount == 2 && GUI.skin.settings.doubleClickSelectsWord)\n                            {\n                                editor.MoveCursorToPosition(Event.current.mousePosition);\n                                editor.SelectCurrentWord();\n                                editor.MouseDragSelectsWholeWords(true);\n                                editor.DblClickSnap(TextEditor.DblClickSnapping.WORDS);\n                                s_DragToPosition = false;\n                            }\n                            else if (Event.current.clickCount == 3 && GUI.skin.settings.tripleClickSelectsLine)\n                            {\n                                editor.MoveCursorToPosition(Event.current.mousePosition);\n                                editor.SelectCurrentParagraph();\n                                editor.MouseDragSelectsWholeWords(true);\n                                editor.DblClickSnap(TextEditor.DblClickSnapping.PARAGRAPHS);\n                                s_DragToPosition = false;\n                            }\n                            else\n                            {\n                                editor.MoveCursorToPosition(Event.current.mousePosition);\n                                s_SelectAllOnMouseUp = false;\n                            }\n                        }\n                        else\n                        { // Otherwise, mark this as initial click and begin editing\n                            GUIUtility.keyboardControl = id;\n                            editor.BeginEditing(id, text, position, style, multiline, passwordField);\n                            editor.MoveCursorToPosition(Event.current.mousePosition);\n                            // If cursor is invisible, it's a selectable label, and we don't want to select all automatically\n                            if (GUI.skin.settings.cursorColor.a > 0)\n                            {\n                                s_SelectAllOnMouseUp = true;\n                            }\n                        }\n\n                        GUIUtility.hotControl = id;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        if (!evt.shift && editor.hasSelection && s_DragToPosition)\n                        {\n                            editor.MoveAltCursorToPosition(Event.current.mousePosition);\n                        }\n                        else\n                        {\n                            if (evt.shift)\n                            {\n                                editor.MoveCursorToPosition(Event.current.mousePosition);\n                            }\n                            else\n                            {\n                                editor.SelectToPosition(Event.current.mousePosition);\n                            }\n\n                            s_DragToPosition = false;\n                            s_SelectAllOnMouseUp = !editor.hasSelection;\n                        }\n                        s_Dragged = true;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.ContextClick:\n                    if (position.Contains(evt.mousePosition))\n                    {\n                        if (!editor.IsEditingControl(id))\n                        { // First click: focus before showing popup\n                            GUIUtility.keyboardControl = id;\n                            if (wasEnabled)\n                            {\n                                editor.BeginEditing(id, text, position, style, multiline, passwordField);\n                                editor.MoveCursorToPosition(Event.current.mousePosition);\n                            }\n                        }\n                        ShowTextEditorPopupMenu();\n                        Event.current.Use();\n                    }\n\n                    break;\n                case EventType.KeyDown:\n                    var nonPrintableTab = false;\n                    if (GUIUtility.keyboardControl == id)\n                    {\n                        char c = evt.character;\n\n                        // Let the editor handle all cursor keys, etc...\n                        if (editor.IsEditingControl(id) && editor.HandleKeyEvent(evt))\n                        {\n                            evt.Use();\n                            mayHaveChanged = true;\n                            break;\n                        }\n\n                        if (evt.keyCode == KeyCode.Escape)\n                        {\n                            if (editor.IsEditingControl(id))\n                            {\n                                if (style == EditorStyles.toolbarSearchField || style == EditorStyles.searchField || style.name.Contains(\"SearchText\"))\n                                {\n                                    s_OriginalText = \"\";\n                                }\n\n                                if (s_PropertyStack.Count > 0)\n                                {\n                                    if (s_RecycledEditor.GetOriginalDoubleValues() != null)\n                                        s_PropertyStack.Peek().property.allDoubleValues =\n                                            s_RecycledEditor.GetOriginalDoubleValues();\n\n                                    if (s_RecycledEditor.GetOriginalLongValues() != null)\n                                        s_PropertyStack.Peek().property.allLongValues =\n                                            s_RecycledEditor.GetOriginalLongValues();\n                                }\n\n                                editor.text = s_OriginalText;\n\n                                editor.EndEditing();\n                                mayHaveChanged = true;\n                            }\n                        }\n                        else if (c == '\\n' || c == 3)\n                        {\n                            if (!editor.IsEditingControl(id))\n                            {\n                                editor.BeginEditing(id, text, position, style, multiline, passwordField);\n                                editor.SelectAll();\n                            }\n                            else\n                            {\n                                if (!multiline || (evt.alt || evt.shift || evt.control))\n                                {\n                                    editor.EndEditing();\n                                }\n                                else\n                                {\n                                    editor.Insert(c);\n                                    mayHaveChanged = true;\n                                    break;\n                                }\n                            }\n                            evt.Use();\n                        }\n                        else if (c == '\\t' || evt.keyCode == KeyCode.Tab)\n                        {\n                            // Only insert tabs if multiline\n                            if (multiline && editor.IsEditingControl(id))\n                            {\n                                bool validTabCharacter = (allowedletters == null || allowedletters.IndexOf(c) != -1);\n                                bool validTabEvent = !(evt.alt || evt.shift || evt.control) && c == '\\t';\n                                if (validTabEvent && validTabCharacter)\n                                {\n                                    editor.Insert(c);\n                                    mayHaveChanged = true;\n                                }\n                            }\n                            else\n                            {\n                                nonPrintableTab = true;\n                            }\n                        }\n                        else if (c == 25 || c == 27)\n                        {\n                            // Note, OS X send characters for the following keys that we need to eat:\n                            // ASCII 25: \"End Of Medium\" on pressing shift tab\n                            // ASCII 27: \"Escape\" on pressing ESC\n                            nonPrintableTab = true;\n                        }\n                        else if (editor.IsEditingControl(id))\n                        {\n                            bool validCharacter = (allowedletters == null || allowedletters.IndexOf(c) != -1) && IsPrintableChar(c);\n                            if (validCharacter)\n                            {\n                                editor.Insert(c);\n                                mayHaveChanged = true;\n                            }\n                            else\n                            {\n                                // If the composition string is not empty, then it's likely that even though we didn't add a printable\n                                // character to the string, we should refresh the GUI, to update the composition string.\n                                if (Input.compositionString != \"\")\n                                {\n                                    editor.ReplaceSelection(\"\");\n                                    mayHaveChanged = true;\n                                }\n                            }\n                        }\n                        // consume Keycode events that might result in a printable key so they aren't passed on to other controls or shortcut manager later\n                        if (\n                            editor.IsEditingControl(id) &&\n                            MightBePrintableKey(evt) &&\n                            !nonPrintableTab // only consume tabs that actually result in a character (above) so we don't disable tabbing between keyboard controls\n                        )\n                        {\n                            evt.Use();\n                        }\n                    }\n\n                    break;\n                case EventType.Repaint:\n                    string drawText;\n                    if (editor.IsEditingControl(id))\n                    {\n                        if (showMixedValue && editor.text == k_MultiEditValueString)\n                            drawText = string.Empty;\n                        else\n                            drawText = passwordField ? \"\".PadRight(editor.text.Length, '*') : editor.text;\n                    }\n                    else if (showMixedValue)\n                    {\n                        drawText = s_MixedValueContent.text;\n                    }\n                    else\n                    {\n                        drawText = passwordField ? \"\".PadRight(text.Length, '*') : text;\n                    }\n\n                    if (!string.IsNullOrEmpty(s_UnitString) && !passwordField)\n                        drawText += \" \" + s_UnitString;\n\n                    if (!editor.IsEditingControl(id))\n                    {\n                        BeginHandleMixedValueContentColor();\n                        style.Draw(position, EditorGUIUtility.TempContent(drawText), id, false, position.Contains(Event.current.mousePosition));\n                        EndHandleMixedValueContentColor();\n                    }\n                    else\n                    {\n                        editor.DrawCursor(drawText);\n                    }\n\n                    var cursorRect = position;\n                    if (cancelButtonStyle != null && !String.IsNullOrEmpty(text))\n                        cursorRect.width -= cancelButtonStyle.fixedWidth;\n                    if (cursorRect.Contains(evt.mousePosition))\n                    {\n                        bool showLinkCursor = false;\n                        // Add the link cursor for the hyperlinks found on the editor\n                        foreach (var rect in editor.GetHyperlinksRect())\n                        {\n                            EditorGUIUtility.AddCursorRect(rect, MouseCursor.Link);\n                            if (!showLinkCursor && rect.Contains(evt.mousePosition))\n                                showLinkCursor = true;\n                        }\n\n                        // Only change mouse cursor if hotcontrol is not grabbed\n                        if (!showLinkCursor && GUIUtility.hotControl == 0)\n                            EditorGUIUtility.AddCursorRect(cursorRect, MouseCursor.Text);\n                    }\n\n                    break;\n                case EventType.ScrollWheel:\n                    // Scroll offset might need to be updated\n                    editor.UpdateScrollOffset();\n                    break;\n            }\n\n            if (GUIUtility.keyboardControl == id)\n            {\n                // TODO: remove the need for this with Optimized GUI blocks\n                GUIUtility.textFieldInput = EditorGUIUtility.editingTextField;\n            }\n\n            changed = false;\n            if (mayHaveChanged)\n            {\n                // If some action happened that could change the text AND\n                // the text actually changed, then set changed to true.\n                // Don't just compare the text only, since it also changes when changing text field.\n                // Don't leave out comparing the text though, since it will result in false positives.\n                changed = (textBeforeKey != editor.text);\n                evt.Use();\n            }\n            if (changed)\n            {\n                if (GUIUtility.keyboardControl != s_SavekeyboardControl)\n                {\n                    s_SavekeyboardControl = GUIUtility.keyboardControl;\n                    s_SearchFieldTextLimitApproved = false;\n                }\n                if (editor.text.Length > kSearchFieldTextLimit && checkTextLimit)\n                {\n                    if ((evt.control || evt.command || evt.commandName == EventCommandNames.Paste) && !s_SearchFieldTextLimitApproved)\n                    {\n                        editor.text = ValidateTextLimit(editor.text);\n                    }\n                    else if (editor.text.Length == kSearchFieldTextLimit + 1 && evt.keyCode != KeyCode.Backspace && !s_SearchFieldTextLimitApproved)\n                    {\n                        editor.text = ValidateTextLimit(editor.text);\n                    }\n                }\n                GUI.changed = true;\n                return editor.text;\n            }\n\n            RecycledTextEditor.s_AllowContextCutOrPaste = true;\n\n            return origText;\n        }\n\n        private static bool HasClickedOnHyperlink(RecycledTextEditor editor, out Dictionary<string, string> hyperLinkData)\n        {\n            hyperLinkData = new Dictionary<string, string>();\n            Vector2 mousePosition = Event.current.mousePosition;\n            if (!editor.HasClickedOnLink(mousePosition, out string link))\n                return false;\n\n            MatchCollection matches = s_ATagRegex.Matches(link);\n            if (matches.Count == 0)\n                matches = s_LinkTagRegex.Matches(link);\n\n            int endPreviousAttributeIndex = 0;\n            // for each attribute we need to find the attribute name\n            foreach (Match match in matches)\n            {\n                // We are only working on the text between the previous attribute and the current\n                string namePart = link.Substring(endPreviousAttributeIndex,\n                    (match.Index - 2) - endPreviousAttributeIndex); // -2 is the character before =\"\n                int indexName = namePart.LastIndexOf(' ') + 1;\n                string name = namePart.Substring(indexName);\n                // Add the name of the attribute and its value in the dictionary\n                hyperLinkData.Add(name, match.Value);\n\n                endPreviousAttributeIndex = match.Index + match.Value.Length + 1;\n            }\n\n            return true;\n        }\n\n        public static event Action<EditorWindow, UnityEditor.HyperLinkClickedEventArgs> hyperLinkClicked;\n\n        private static void EditorGUI_OpenFileOnHyperLinkClicked(EditorWindow window, UnityEditor.HyperLinkClickedEventArgs args)\n        {\n            string path;\n            if (!args.hyperLinkData.TryGetValue(\"href\", out path))\n                return;\n            string lineString;\n            args.hyperLinkData.TryGetValue(\"line\", out lineString);\n            int line = -1;\n            Int32.TryParse(lineString, out line);\n\n            var sanitizedPath = path.Replace('\\\\', '/');\n\n            if (!String.IsNullOrEmpty(sanitizedPath))\n            {\n                if (Uri.IsWellFormedUriString(sanitizedPath, UriKind.Absolute))\n                    Application.OpenURL(path);\n                else\n                    LogEntries.OpenFileOnSpecificLineAndColumn(path, line, -1);\n            }\n        }\n\n        // KEYEVENTFIELD HERE ===============================================================\n        internal static Event KeyEventField(Rect position, Event evt)\n        {\n            return DoKeyEventField(position, evt, GUI.skin.textField);\n        }\n\n        internal static Event DoKeyEventField(Rect position, Event _event, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_KeyEventFieldHash, FocusType.Passive, position);\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    // If the mouse is inside the button, we say that we're the hot control\n                    if (position.Contains(evt.mousePosition))\n                    {\n                        GUIUtility.hotControl = id;\n                        evt.Use();\n                        bKeyEventActive = !bKeyEventActive;\n                        EditorGUIUtility.editingTextField = bKeyEventActive;\n                    }\n                    return _event;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = id;\n\n                        // If we got the mousedown, the mouseup is ours as well\n                        // (no matter if the click was in the button or not)\n                        evt.Use();\n                    }\n                    return _event;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        evt.Use();\n                    }\n                    break;\n                case EventType.Repaint:\n                    if (bKeyEventActive)\n                    {\n                        style.Draw(position, s_PleasePressAKey, id);\n                    }\n                    else\n                    {\n                        string str = InternalEditorUtility.TextifyEvent(_event);\n                        style.Draw(position, EditorGUIUtility.TempContent(str), id);\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if ((GUIUtility.hotControl == id) && bKeyEventActive)\n                    {\n                        // ignore presses of just modifier keys\n                        if (evt.character == '\\0')\n                        {\n                            if (evt.alt && (evt.keyCode == KeyCode.AltGr || evt.keyCode == KeyCode.LeftAlt || evt.keyCode == KeyCode.RightAlt) ||\n                                evt.control && (evt.keyCode == KeyCode.LeftControl || evt.keyCode == KeyCode.RightControl) ||\n                                evt.command && (evt.keyCode == KeyCode.LeftApple || evt.keyCode == KeyCode.RightApple || evt.keyCode == KeyCode.LeftWindows || evt.keyCode == KeyCode.RightWindows) ||\n                                evt.shift && (evt.keyCode == KeyCode.LeftShift || evt.keyCode == KeyCode.RightShift || (int)evt.keyCode == 0))\n                            {\n                                return _event;\n                            }\n                        }\n                        bKeyEventActive = false;\n                        GUI.changed = true;\n                        GUIUtility.hotControl = 0;\n                        EditorGUIUtility.editingTextField = false;\n                        Event e = new Event(evt);\n                        evt.Use();\n                        return e;\n                    }\n                    break;\n            }\n            return _event;\n        }\n\n        internal static Rect GetInspectorTitleBarObjectFoldoutRenderRect(Rect rect)\n        {\n            return GetInspectorTitleBarObjectFoldoutRenderRect(rect, null);\n        }\n\n        internal static Rect GetInspectorTitleBarObjectFoldoutRenderRect(Rect rect, GUIStyle baseStyle)\n        {\n            return new Rect(rect.x + EditorStyles.titlebarFoldout.margin.left + 1f, rect.y + (rect.height - kInspTitlebarFoldoutIconWidth) / 2 + (baseStyle != null ? baseStyle.padding.top : 0), kInspTitlebarFoldoutIconWidth, kInspTitlebarFoldoutIconWidth);\n        }\n\n        [SuppressMessage(\"ReSharper\", \"RedundantCast.0\")]\n        [SuppressMessage(\"ReSharper\", \"ConditionIsAlwaysTrueOrFalse\")]\n        [SuppressMessage(\"ReSharper\", \"HeuristicUnreachableCode\")]\n        static bool IsValidForContextMenu(Object target)\n        {\n            // if the reference is *really* null, don't allow showing the context menu\n            if ((object)target == null)\n                return false;\n\n            // UnityEngine.Object overrides == null, which means we might be dealing with an invalid object\n            bool isUnityNull = target == null;\n\n            // if scripted object compares to null, then we are dealing with a missing script\n            // for which we still want to display context menu\n            if (isUnityNull && NativeClassExtensionUtilities.ExtendsANativeType(target.GetType()))\n                return true;\n\n            return !isUnityNull;\n        }\n\n        internal static bool DoObjectMouseInteraction(bool foldout, Rect interactionRect, Object[] targetObjs, int id)\n        {\n            // Always enabled, regardless of editor enabled state\n            var enabled = GUI.enabled;\n            GUI.enabled = true;\n\n            // Context menu\n            Event evt = Event.current;\n\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (interactionRect.Contains(evt.mousePosition))\n                    {\n                        if (evt.button == 0 && !(Application.platform == RuntimePlatform.OSXEditor && evt.control))\n                        {\n                            GUIUtility.hotControl = id;\n                            GUIUtility.keyboardControl = id;\n                            DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), id);\n                            delay.mouseDownPosition = evt.mousePosition;\n                            evt.Use();\n                        }\n                    }\n                    break;\n\n                case EventType.ContextClick:\n                    if (interactionRect.Contains(evt.mousePosition) && IsValidForContextMenu(targetObjs[0]))\n                    {\n                        EditorUtility.DisplayObjectContextMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), targetObjs, 0);\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                        if (interactionRect.Contains(evt.mousePosition))\n                        {\n                            GUI.changed = true;\n                            foldout = !foldout;\n                        }\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), id);\n                        if (delay.CanStartDrag())\n                        {\n                            GUIUtility.hotControl = 0;\n                            DragAndDrop.PrepareStartDrag();\n                            DragAndDrop.objectReferences = targetObjs;\n                            DragAndDrop.StartDrag(targetObjs.Length > 1\n                                ? \"<Multiple>\"\n                                : ObjectNames.GetDragAndDropTitle(targetObjs[0]));\n                        }\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.DragUpdated:\n                    if (s_DragUpdatedOverID == id)\n                    {\n                        if (interactionRect.Contains(evt.mousePosition))\n                        {\n                            if (Time.realtimeSinceStartup > s_FoldoutDestTime)\n                            {\n                                foldout = true;\n                                HandleUtility.Repaint();\n                            }\n                        }\n                        else\n                        {\n                            s_DragUpdatedOverID = 0;\n                        }\n                    }\n                    else\n                    {\n                        if (interactionRect.Contains(evt.mousePosition))\n                        {\n                            s_DragUpdatedOverID = id;\n                            s_FoldoutDestTime = Time.realtimeSinceStartup + kFoldoutExpandTimeout;\n                        }\n                    }\n\n                    if (interactionRect.Contains(evt.mousePosition))\n                    {\n                        DragAndDrop.visualMode = DragAndDrop.DropOnInspectorWindow(targetObjs, false);\n                        Event.current.Use();\n                    }\n                    break;\n\n                case EventType.DragPerform:\n                    if (interactionRect.Contains(evt.mousePosition))\n                    {\n                        DragAndDrop.visualMode = DragAndDrop.DropOnInspectorWindow(targetObjs, true);\n                        DragAndDrop.AcceptDrag();\n                        Event.current.Use();\n                    }\n                    break;\n\n                case EventType.KeyDown:\n                    if (GUIUtility.keyboardControl == id)\n                    {\n                        if (evt.keyCode == KeyCode.LeftArrow)\n                        {\n                            foldout = false;\n                            evt.Use();\n                        }\n                        if (evt.keyCode == KeyCode.RightArrow)\n                        {\n                            foldout = true;\n                            evt.Use();\n                        }\n                    }\n                    break;\n            }\n\n            // Restore enabled state for the editors.\n            GUI.enabled = enabled;\n\n            return foldout;\n        }\n\n        // This is assumed to be called from the inspector only\n        private static void DoObjectFoldoutInternal(bool foldout, Rect renderRect, int id)\n        {\n            // Always enabled, regardless of editor enabled state\n            var enabled = GUI.enabled;\n            GUI.enabled = true;\n\n            // Context menu\n            Event evt = Event.current;\n\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.Repaint:\n                    bool isPressed = GUIUtility.hotControl == id;\n                    EditorStyles.titlebarFoldout.Draw(renderRect, isPressed, isPressed, foldout, false);\n                    break;\n            }\n\n            // Restore enabled state for the editors.\n            GUI.enabled = enabled;\n        }\n\n        internal static bool DoObjectFoldout(bool foldout, Rect interactionRect, Rect renderRect, Object[] targetObjs, int id)\n        {\n            foldout = DoObjectMouseInteraction(foldout, interactionRect, targetObjs, id);\n            DoObjectFoldoutInternal(foldout, renderRect, id);\n            return foldout;\n        }\n\n        // Make a label field. (Useful for showing read-only info.)\n        internal static void LabelFieldInternal(Rect position, GUIContent label, GUIContent label2, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Passive, position);\n            position = PrefixLabel(position, id, label);\n            if (Event.current.type == EventType.Repaint)\n            {\n                style.Draw(position, label2, id);\n            }\n        }\n\n        public static bool Toggle(Rect position, bool value)\n        {\n            int id = GUIUtility.GetControlID(s_ToggleHash, FocusType.Keyboard, position);\n            return EditorGUIInternal.DoToggleForward(IndentedRect(position), id, value, GUIContent.none, EditorStyles.toggle);\n        }\n\n        public static bool Toggle(Rect position, string label, bool value)\n        {\n            return Toggle(position, EditorGUIUtility.TempContent(label), value);\n        }\n\n        public static bool Toggle(Rect position, bool value, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_ToggleHash, FocusType.Keyboard, position);\n            return EditorGUIInternal.DoToggleForward(position, id, value, GUIContent.none, style);\n        }\n\n        public static bool Toggle(Rect position, string label, bool value, GUIStyle style)\n        {\n            return Toggle(position, EditorGUIUtility.TempContent(label), value, style);\n        }\n\n        public static bool Toggle(Rect position, GUIContent label, bool value)\n        {\n            int id = GUIUtility.GetControlID(s_ToggleHash, FocusType.Keyboard, position);\n            return EditorGUIInternal.DoToggleForward(PrefixLabel(position, id, label), id, value, GUIContent.none, EditorStyles.toggle, false);\n        }\n\n        // Make a toggle.\n        public static bool Toggle(Rect position, GUIContent label, bool value, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_ToggleHash, FocusType.Keyboard, position);\n            return EditorGUIInternal.DoToggleForward(PrefixLabel(position, id, label), id, value, GUIContent.none, style);\n        }\n\n        // Make a toggle with the label on the right.\n        internal static bool ToggleLeftInternal(Rect position, GUIContent label, bool value, GUIStyle labelStyle)\n        {\n            int id = GUIUtility.GetControlID(s_ToggleHash, FocusType.Keyboard, position);\n            Rect toggleRect = IndentedRect(position);\n            Rect labelRect = IndentedRect(position);\n            var topOffset = (EditorStyles.toggle.margin.top - EditorStyles.toggle.margin.bottom) / 2;\n            labelRect.xMin += EditorStyles.toggle.padding.left;\n            labelRect.yMin -= topOffset; labelRect.yMax -= topOffset;\n            HandlePrefixLabel(position, labelRect, label, id, labelStyle);\n            return EditorGUIInternal.DoToggleForward(toggleRect, id, value, GUIContent.none, EditorStyles.toggle);\n        }\n\n        internal static bool DoToggle(Rect position, int id, bool value, GUIContent content, GUIStyle style)\n        {\n            return EditorGUIInternal.DoToggleForward(position, id, value, content, style);\n        }\n\n        internal static string TextFieldInternal(int id, Rect position, string text, GUIStyle style)\n        {\n            bool dummy;\n            text = DoTextField(s_RecycledEditor, id, IndentedRect(position), text, style, null, out dummy, false, false, false);\n            return text;\n        }\n\n        internal static string TextFieldInternal(int id, Rect position, string text, GUIStyle style, GUIStyle cancelButtonStyle)\n        {\n            bool dummy;\n            text = DoTextField(s_RecycledEditor, id, IndentedRect(position), text, style, null, out dummy, false, false, false, cancelButtonStyle);\n            return text;\n        }\n\n        internal static string TextFieldInternal(Rect position, string text, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, position);\n            bool dummy;\n            text = DoTextField(s_RecycledEditor, id, IndentedRect(position), text, style, null, out dummy, false, false, false);\n            return text;\n        }\n\n        // Make a text field.\n        internal static string TextFieldInternal(Rect position, GUIContent label, string text, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, position);\n            bool dummy;\n            text = DoTextField(s_RecycledEditor, id, PrefixLabel(position, id, label), text, style, null, out dummy, false, false, false);\n            return text;\n        }\n\n        internal static string TextFieldInternal(int id, Rect position, GUIContent label, string text, GUIStyle style)\n        {\n            bool dummy;\n            text = DoTextField(s_RecycledEditor, id, PrefixLabel(position, id, label), text, style, null, out dummy, false, false, false);\n            return text;\n        }\n\n        internal static string ToolbarSearchField(Rect position, string text, bool showWithPopupArrow)\n        {\n            int id = GUIUtility.GetControlID(s_SearchFieldHash, FocusType.Keyboard, position);\n            return ToolbarSearchField(id, position, text, showWithPopupArrow);\n        }\n\n        internal static string ToolbarSearchField(int id, Rect position, string text, bool showWithPopupArrow)\n        {\n            return ToolbarSearchField(\n                id,\n                position,\n                text,\n                showWithPopupArrow ? EditorStyles.toolbarSearchFieldPopup : EditorStyles.toolbarSearchField,\n                text != \"\" ? EditorStyles.toolbarSearchFieldCancelButton : EditorStyles.toolbarSearchFieldCancelButtonEmpty);\n        }\n\n        internal static string ToolbarSearchField(int id, Rect position, string text, GUIStyle searchFieldStyle, GUIStyle cancelButtonStyle)\n        {\n            bool dummy;\n            Rect textRect = position;\n            const float k_CancelButtonWidth = 14f;\n\n            Rect buttonRect = position;\n            buttonRect.x += position.width - k_CancelButtonWidth;\n            buttonRect.width = k_CancelButtonWidth;\n\n            if (!String.IsNullOrEmpty(text))\n                EditorGUIUtility.AddCursorRect(buttonRect, MouseCursor.Arrow);\n            if (Event.current.type == EventType.MouseUp && buttonRect.Contains(Event.current.mousePosition))\n            {\n                s_RecycledEditor.text = text = \"\";\n                GUI.changed = true;\n            }\n            text = DoTextField(s_RecycledEditor, id, textRect, text, searchFieldStyle, null, out dummy, false, false, false, cancelButtonStyle, true);\n            GUI.Button(buttonRect, GUIContent.none, cancelButtonStyle);\n\n            return text;\n        }\n\n        internal static string ToolbarSearchField(Rect position, string[] searchModes, ref int searchMode, string text)\n        {\n            int id = GUIUtility.GetControlID(s_SearchFieldHash, FocusType.Keyboard, position);\n            return ToolbarSearchField(id, position, searchModes, ref searchMode, text);\n        }\n\n        internal static string ToolbarSearchField(int id, Rect position, string[] searchModes, ref int searchMode, string text)\n        {\n            return ToolbarSearchField(\n                id,\n                position,\n                searchModes,\n                ref searchMode,\n                text,\n                EditorStyles.toolbarSearchFieldPopup,\n                EditorStyles.toolbarSearchField,\n                text != \"\" ? EditorStyles.toolbarSearchFieldCancelButton : EditorStyles.toolbarSearchFieldCancelButtonEmpty);\n        }\n\n        internal static string ToolbarSearchField(int id, Rect position, string[] searchModes, ref int searchMode, string text, GUIStyle searchFieldWithPopupStyle, GUIStyle searchFieldNoPopupStyle, GUIStyle cancelButtonStyle)\n        {\n            bool hasPopup = searchModes != null;\n            if (hasPopup)\n            {\n                searchMode = PopupCallbackInfo.GetSelectedValueForControl(id, searchMode);\n\n                Rect popupPosition = position;\n                popupPosition.width = 20;\n\n                if (Event.current.type == EventType.MouseDown && popupPosition.Contains(Event.current.mousePosition))\n                {\n                    PopupCallbackInfo.instance = new PopupCallbackInfo(id);\n                    EditorUtility.DisplayCustomMenu(position, EditorGUIUtility.TempContent(searchModes), searchMode, PopupCallbackInfo.instance.SetEnumValueDelegate, null);\n\n                    if (s_RecycledEditor.IsEditingControl(id))\n                    {\n                        Event.current.Use();\n                    }\n                }\n            }\n\n            text = ToolbarSearchField(id, position, text, hasPopup ? searchFieldWithPopupStyle : searchFieldNoPopupStyle, cancelButtonStyle);\n\n            if (hasPopup && text == \"\" && !s_RecycledEditor.IsEditingControl(id) && Event.current.type == EventType.Repaint)\n            {\n                using (new DisabledScope(true))\n                {\n                    var placeHolderTextRect = EditorStyles.toolbarSearchFieldPopup.padding.Remove(new Rect(position.x, position.y, position.width\n                        , EditorStyles.toolbarSearchFieldPopup.fixedHeight > 0 ? EditorStyles.toolbarSearchFieldPopup.fixedHeight : position.height));\n                    var oldFontSize = EditorStyles.label.fontSize;\n\n                    EditorStyles.label.fontSize = EditorStyles.toolbarSearchFieldPopup.fontSize;\n                    EditorStyles.label.Draw(placeHolderTextRect, EditorGUIUtility.TempContent(searchModes[searchMode]), false, false, false, false);\n                    EditorStyles.label.fontSize = oldFontSize;\n                }\n            }\n\n            return text;\n        }\n\n        internal static string SearchField(Rect position, string text)\n        {\n            int id = GUIUtility.GetControlID(s_SearchFieldHash, FocusType.Keyboard, position);\n            bool dummy;\n            Rect textRect = position;\n            textRect.width -= 15;\n            text = DoTextField(s_RecycledEditor, id, textRect, text, EditorStyles.searchField, null, out dummy, false, false, false);\n            Rect buttonRect = position;\n            buttonRect.x += position.width - 15;\n            buttonRect.width = 15;\n            if (GUI.Button(buttonRect, GUIContent.none, text != \"\" ? EditorStyles.searchFieldCancelButton : EditorStyles.searchFieldCancelButtonEmpty) && text != \"\")\n            {\n                s_RecycledEditor.text = text = \"\";\n                GUIUtility.keyboardControl = 0;\n            }\n            return text;\n        }\n\n        struct ScrollableAreaScope : IDisposable\n        {\n            GUIStyle style;\n            Vector2 scrollPosition;\n            Vector2 oldScrollValue;\n\n            public ScrollableAreaScope(int id, ref Rect position, string text, ref Vector2 scrollPosition, ref GUIStyle style)\n            {\n                this.style = style;\n                this.scrollPosition = scrollPosition;\n\n                position = IndentedRect(position);\n                float fullTextHeight = style.CalcHeight(GUIContent.Temp(text), position.width);\n                Rect viewRect = new Rect(0, 0, position.width, fullTextHeight);\n\n                oldScrollValue = style.contentOffset;\n                if (position.height < viewRect.height)\n                {\n                    //Scroll bar position\n                    Rect scrollbarPosition = position;\n                    scrollbarPosition.width = GUI.skin.verticalScrollbar.fixedWidth;\n                    scrollbarPosition.height -= 2;\n                    scrollbarPosition.y += 1;\n                    scrollbarPosition.x = position.x + position.width - scrollbarPosition.width;\n\n                    position.width -= scrollbarPosition.width;\n\n                    //textEditor width changed, recalculate Text and viewRect areas.\n                    fullTextHeight = style.CalcHeight(GUIContent.Temp(text), position.width);\n                    viewRect = new Rect(0, 0, position.width, fullTextHeight);\n\n                    if (position.Contains(Event.current.mousePosition) && Event.current.type == EventType.ScrollWheel)\n                    {\n                        const float mouseWheelMultiplier = 10f;\n                        float desiredY = scrollPosition.y + Event.current.delta.y * mouseWheelMultiplier;\n                        scrollPosition.y = Mathf.Clamp(desiredY, 0f, viewRect.height);\n                        Event.current.Use();\n                    }\n\n                    scrollPosition.y = GUI.VerticalScrollbar(scrollbarPosition, scrollPosition.y, position.height, 0, viewRect.height);\n\n                    if (!s_RecycledEditor.IsEditingControl(id))\n                    {\n                        //When not editing we use the style.draw, so we need to change the offset on the style instead of the RecycledEditor.\n                        style.contentOffset -= scrollPosition;\n                        style.Internal_clipOffset = scrollPosition;\n                    }\n                    else\n                    {\n                        //Move the Editor offset to match our scrollbar\n                        s_RecycledEditor.scrollOffset = scrollPosition;\n                    }\n                }\n            }\n\n            public void Dispose()\n            {\n                style.contentOffset = oldScrollValue;\n                style.Internal_clipOffset = Vector2.zero;\n            }\n        }\n\n        internal static void ScrollableLabelAreaInternal(Rect position, string text, ref Vector2 scrollPosition, GUIStyle style)\n        {\n            if (Event.current.type == EventType.Layout)\n                return;\n\n            int id = GUIUtility.GetControlID(s_SelectableLabelHash, FocusType.Keyboard, position);\n            var sendEventToTextEditor = SendEventToTextEditor(id, Event.current);\n\n            using (new ScrollableAreaScope(id, ref position, text, ref scrollPosition, ref style))\n            {\n                //Events cannot be handled at the scope level\n                EventType beforeTextFieldEventType = Event.current.type;\n                // It's possible that DoTextField will throw so we use a scoped cursor that we can safely reset the color.\n                using (new CursorColorScope(Color.clear))\n                {\n\n                    RecycledTextEditor.s_AllowContextCutOrPaste = false;\n                    if (sendEventToTextEditor)\n                    {\n                        bool isMouseDown = Event.current.rawType == EventType.MouseDown && Event.current.button == 0;\n                        bool isEditingControl = s_RecycledEditor.IsEditingControl(id);\n\n                        DoTextField(s_RecycledEditor, id, position, text, style, string.Empty, out _, false, true, false);\n\n                        if (isMouseDown && Event.current.type == EventType.Used)\n                        {\n                            // We just took control over the Scrollable label\n                            if (!isEditingControl && s_RecycledEditor.IsEditingControl(id))\n                            {\n                                // Properly set the scroll offset as it was set to 0 in the editor.BeginEditing\n                                // Move the recycled Editor offset to match our scrollbar\n                                s_RecycledEditor.scrollOffset = scrollPosition;\n                            }\n                        }\n                    }\n                }\n\n                //Only update the out scrollPosition if the user has interacted with the TextArea (the current event was used)\n                if (beforeTextFieldEventType != Event.current.type)\n                    scrollPosition = s_RecycledEditor.scrollOffset;\n            }\n        }\n\n        internal static string ScrollableTextAreaInternal(Rect position, string text, ref Vector2 scrollPosition, GUIStyle style)\n        {\n            if (Event.current.type == EventType.Layout)\n                return text;\n\n            int id = GUIUtility.GetControlID(s_TextAreaHash, FocusType.Keyboard, position);\n\n            string newValue = string.Empty;\n            using (new ScrollableAreaScope(id, ref position, text, ref scrollPosition, ref style))\n            {\n                //Events cannot be handled at the scope level\n                EventType beforeTextFieldEventType = Event.current.type;\n                newValue = DoTextField(s_RecycledEditor, id, position, text, style, null, out _, false, true,\n                    false);\n\n                //Only update the out scrollPosition if the user has interacted with the TextArea (the current event was used)\n                if (beforeTextFieldEventType != Event.current.type)\n                    scrollPosition = s_RecycledEditor.scrollOffset;\n            }\n\n            return newValue;\n        }\n\n        // Make a text area.\n        internal static string TextAreaInternal(Rect position, string text, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_TextAreaHash, FocusType.Keyboard, position);\n            bool dummy;\n            text = DoTextField(s_RecycledEditor, id, IndentedRect(position), text, style, null, out dummy, false, true, false);\n            return text;\n        }\n\n        static bool SendEventToTextEditor(int id, Event e)\n        {\n            var sendEventToTextEditor = true;\n            if (GUIUtility.keyboardControl == id && e.GetTypeForControl(id) == EventType.KeyDown)\n            {\n                switch (e.keyCode)\n                {\n                    case KeyCode.LeftArrow:\n                    case KeyCode.RightArrow:\n                    case KeyCode.UpArrow:\n                    case KeyCode.DownArrow:\n                    case KeyCode.Home:\n                    case KeyCode.End:\n                    case KeyCode.PageUp:\n                    case KeyCode.PageDown:\n                        break;\n                    case KeyCode.Space:\n                        GUIUtility.hotControl = 0;\n                        GUIUtility.keyboardControl = 0;\n                        break;\n                    default:\n                        sendEventToTextEditor = false;\n                        break;\n                }\n            }\n\n            if (e.type == EventType.ExecuteCommand && (e.commandName == EventCommandNames.Paste || e.commandName == EventCommandNames.Cut) && GUIUtility.keyboardControl == id)\n            {\n                sendEventToTextEditor = false;\n            }\n\n            return sendEventToTextEditor;\n        }\n\n        // Make a selectable label field. (Useful for showing read-only info that can be copy-pasted.)\n        internal static void SelectableLabelInternal(Rect position, string text, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_SelectableLabelHash, FocusType.Keyboard, position);\n\n            var sendEventToTextEditor = SendEventToTextEditor(id, Event.current);\n\n            // It's possible that DoTextField will throw so we use a scoped cursor that we can safely reset the color.\n            using (new CursorColorScope(Color.clear))\n            {\n                RecycledTextEditor.s_AllowContextCutOrPaste = false;\n\n                if (sendEventToTextEditor)\n                {\n                    DoTextField(s_RecycledEditor, id, IndentedRect(position), text, style, string.Empty, out _, false, true, false);\n                }\n            }\n        }\n\n        [Obsolete(\"Use PasswordField instead.\")]\n        public static string DoPasswordField(int id, Rect position, string password, GUIStyle style)\n        {\n            bool guiChanged;\n            return DoTextField(s_RecycledEditor, id, position, password, style, null, out guiChanged, false, false, true);\n        }\n\n        [Obsolete(\"Use PasswordField instead.\")]\n        public static string DoPasswordField(int id, Rect position, GUIContent label, string password, GUIStyle style)\n        {\n            bool guiChanged;\n            return DoTextField(s_RecycledEditor, id, PrefixLabel(position, id, label), password, style, null, out guiChanged, false, false, true);\n        }\n\n        internal static string PasswordFieldInternal(Rect position, string password, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_PasswordFieldHash, FocusType.Keyboard, position);\n            bool guiChanged;\n            return DoTextField(s_RecycledEditor, id, IndentedRect(position), password, style, null, out guiChanged, false, false, true);\n        }\n\n        // Make a text field where the user can enter a password.\n        internal static string PasswordFieldInternal(Rect position, GUIContent label, string password, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_PasswordFieldHash, FocusType.Keyboard, position);\n            bool guiChanged;\n            return DoTextField(s_RecycledEditor, id, PrefixLabel(position, id, label), password, style, null, out guiChanged, false, false, true);\n        }\n\n        internal static float FloatFieldInternal(Rect position, float value, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position);\n            return DoFloatField(s_RecycledEditor, IndentedRect(position), new Rect(0, 0, 0, 0), id, value, kFloatFieldFormatString, style, false);\n        }\n\n        // Make a text field for entering floats.\n        internal static float FloatFieldInternal(Rect position, GUIContent label, float value, GUIStyle style)\n        {\n            NumberFieldValue v = new NumberFieldValue(value);\n            FloatFieldInternal(position, label, ref v, style);\n            return MathUtils.ClampToFloat(v.doubleVal);\n        }\n\n        internal static void FloatFieldInternal(Rect position, GUIContent label, ref NumberFieldValue value, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position);\n            Rect position2 = PrefixLabel(position, id, label);\n            position.xMax = position2.x;\n            var dragSensitivity = Event.current.GetTypeForControl(id) == EventType.MouseDown\n                ? (float)NumericFieldDraggerUtility.CalculateFloatDragSensitivity(s_DragStartValue)\n                : 0.0f;\n            DoNumberField(s_RecycledEditor, position2, position, id, ref value, kFloatFieldFormatString, style, true, dragSensitivity);\n        }\n\n        internal static double DoubleFieldInternal(Rect position, double value, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position);\n            return DoDoubleField(s_RecycledEditor, IndentedRect(position), new Rect(0, 0, 0, 0), id, value, kDoubleFieldFormatString, style, false);\n        }\n\n        // Make a text field for entering floats.\n        internal static double DoubleFieldInternal(Rect position, GUIContent label, double value, GUIStyle style)\n        {\n            NumberFieldValue v = new NumberFieldValue(value);\n            DoubleFieldInternal(position, label, ref v, style);\n            return v.doubleVal;\n        }\n\n        internal static void DoubleFieldInternal(Rect position, GUIContent label, ref NumberFieldValue value, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position);\n            Rect position2 = PrefixLabel(position, id, label);\n            position.xMax = position2.x;\n            var dragSensitivity = Event.current.GetTypeForControl(id) == EventType.MouseDown\n                ? NumericFieldDraggerUtility.CalculateFloatDragSensitivity(s_DragStartValue)\n                : 0.0;\n            DoNumberField(s_RecycledEditor, position2, position, id, ref value, kDoubleFieldFormatString, style, true, dragSensitivity);\n        }\n\n        // Handle dragging of value\n        internal static void DragNumberValue(Rect dragHotZone, int id, bool isDouble, ref double doubleVal,\n            ref long longVal, double dragSensitivity)\n        {\n            NumberFieldValue v = default;\n            v.isDouble = isDouble;\n            v.doubleVal = doubleVal;\n            v.longVal = longVal;\n            DragNumberValue(dragHotZone, id, ref v, dragSensitivity);\n            doubleVal = v.doubleVal;\n            longVal = v.longVal;\n        }\n\n        static void DragNumberValue(Rect dragHotZone, int id, ref NumberFieldValue value, double dragSensitivity)\n        {\n            Event evt = Event.current;\n\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (GUIUtility.HitTest(dragHotZone, evt) && evt.button == 0)\n                    {\n                        // When clicking the dragging rect ensure that the number field is not\n                        // editing: otherwise we don't see the actual value but the edited temp value\n                        EditorGUIUtility.editingTextField = false;\n\n                        GUIUtility.hotControl = id;\n\n                        activeEditor?.EndEditing();\n                        evt.Use();\n                        GUIUtility.keyboardControl = id;\n\n                        s_DragCandidateState = DragCandidateState.InitiatedDragging;\n                        s_DragStartValue = value.doubleVal;\n                        s_DragStartIntValue = value.longVal;\n                        s_DragStartPos = evt.mousePosition;\n                        s_DragSensitivity = dragSensitivity;\n                        evt.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(1);\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id && s_DragCandidateState != DragCandidateState.NotDragging)\n                    {\n                        GUIUtility.hotControl = 0;\n                        s_DragCandidateState = DragCandidateState.NotDragging;\n                        evt.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(0);\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        switch (s_DragCandidateState)\n                        {\n                            case DragCandidateState.InitiatedDragging:\n                                if ((Event.current.mousePosition - s_DragStartPos).sqrMagnitude > kDragDeadzone)\n                                {\n                                    s_DragCandidateState = DragCandidateState.CurrentlyDragging;\n                                    GUIUtility.keyboardControl = id;\n                                }\n                                evt.Use();\n                                break;\n                            case DragCandidateState.CurrentlyDragging:\n                                // Don't change the editor.content.text here.\n                                // Instead, wait for scripting validation to enforce clamping etc. and then\n                                // update the editor.content.text in the repaint event.\n                                if (value.isDouble)\n                                {\n                                    value.doubleVal += HandleUtility.niceMouseDelta * s_DragSensitivity;\n                                    value.doubleVal = MathUtils.RoundBasedOnMinimumDifference(value.doubleVal, s_DragSensitivity);\n                                }\n                                else\n                                {\n                                    value.longVal += (long)Math.Round(HandleUtility.niceMouseDelta * s_DragSensitivity);\n                                }\n                                value.success = true;\n                                GUI.changed = true;\n\n                                evt.Use();\n                                break;\n                        }\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (GUIUtility.hotControl == id && evt.keyCode == KeyCode.Escape && s_DragCandidateState != DragCandidateState.NotDragging)\n                    {\n                        value.doubleVal = s_DragStartValue;\n                        value.longVal = s_DragStartIntValue;\n                        value.success = true;\n                        GUI.changed = true;\n                        //              s_LastEditorControl = -1;\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.Repaint:\n                    EditorGUIUtility.AddCursorRect(dragHotZone, MouseCursor.SlideArrow);\n                    break;\n            }\n        }\n\n        internal static float DoFloatField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, float value, string formatString, GUIStyle style, bool draggable)\n        {\n            return DoFloatField(editor, position, dragHotZone, id, value, formatString, style, draggable, Event.current.GetTypeForControl(id) == EventType.MouseDown ? (float)NumericFieldDraggerUtility.CalculateFloatDragSensitivity(s_DragStartValue) : 0.0f);\n        }\n\n        internal static float DoFloatField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, float value, string formatString, GUIStyle style, bool draggable, float dragSensitivity)\n        {\n            long dummy = 0;\n            double doubleValue = value;\n            DoNumberField(editor, position, dragHotZone, id, true, ref doubleValue, ref dummy, formatString, style, draggable, dragSensitivity);\n            return MathUtils.ClampToFloat(doubleValue);\n        }\n\n        internal static int DoIntField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, int value, string formatString, GUIStyle style, bool draggable, float dragSensitivity)\n        {\n            double dummy = 0f;\n            long longValue = value;\n            DoNumberField(editor, position, dragHotZone, id, false, ref dummy, ref longValue, formatString, style, draggable, dragSensitivity);\n\n            return MathUtils.ClampToInt(longValue);\n        }\n\n        internal static double DoDoubleField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, double value, string formatString, GUIStyle style, bool draggable)\n        {\n            return DoDoubleField(editor, position, dragHotZone, id, value, formatString, style, draggable, Event.current.GetTypeForControl(id) == EventType.MouseDown ? NumericFieldDraggerUtility.CalculateFloatDragSensitivity(s_DragStartValue) : 0.0);\n        }\n\n        internal static double DoDoubleField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, double value, string formatString, GUIStyle style, bool draggable, double dragSensitivity)\n        {\n            long dummy = 0;\n            DoNumberField(editor, position, dragHotZone, id, true, ref value, ref dummy, formatString, style, draggable, dragSensitivity);\n            return value;\n        }\n\n        internal static long DoLongField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, long value, string formatString, GUIStyle style, bool draggable, double dragSensitivity)\n        {\n            double dummy = 0f;\n            DoNumberField(editor, position, dragHotZone, id, false, ref dummy, ref value, formatString, style, draggable, dragSensitivity);\n            return value;\n        }\n\n        // allowed characters in a float field, that encompass:\n        // - numbers,\n        // - infinity/nan\n        // - expressions\n        // - expression evaluation functions\n        internal static readonly string s_AllowedCharactersForFloat = UINumericFieldsUtils.k_AllowedCharactersForFloat;\n\n        internal static readonly string s_AllowedCharactersForInt = UINumericFieldsUtils.k_AllowedCharactersForInt;\n\n        static bool HasKeyboardFocus(int controlID)\n        {\n            // Every EditorWindow has its own keyboardControl state so we also need to\n            // check if the current OS view has focus to determine if the control has actual key focus (gets the input)\n            // and not just being a focused control in an unfocused window.\n            return (GUIUtility.keyboardControl == controlID && EditorGUIUtility.HasCurrentWindowKeyFocus());\n        }\n\n        internal struct NumberFieldValue\n        {\n            public NumberFieldValue(double v)\n            {\n                isDouble = true;\n                doubleVal = v;\n                longVal = 0;\n                expression = null;\n                success = false;\n            }\n\n            public NumberFieldValue(long v)\n            {\n                isDouble = false;\n                doubleVal = 0;\n                longVal = v;\n                expression = null;\n                success = false;\n            }\n\n            public bool isDouble;\n            public double doubleVal;\n            public long longVal;\n            public ExpressionEvaluator.Expression expression;\n            public bool success;\n            public bool hasResult => success || expression != null;\n        }\n\n        internal static void DoNumberField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id,\n            bool isDouble, ref double doubleVal, ref long longVal, string formatString, GUIStyle style, bool draggable,\n            double dragSensitivity)\n        {\n            NumberFieldValue val = default;\n            val.isDouble = isDouble;\n            val.doubleVal = doubleVal;\n            val.longVal = longVal;\n            DoNumberField(editor, position, dragHotZone, id, ref val, formatString, style, draggable, dragSensitivity);\n            if (val.success)\n            {\n                doubleVal = val.doubleVal;\n                longVal = val.longVal;\n            }\n        }\n\n        internal static void StringToNumericValue(in string str, ref NumberFieldValue value)\n        {\n            if (value.isDouble)\n                StringToDouble(str, ref value);\n            else\n                StringToLong(str, ref value);\n        }\n\n        internal static void EvaluateExpressionOnNumberFieldValue(ref NumberFieldValue value)\n        {\n            if (value.isDouble)\n                value.success = value.expression.Evaluate(ref value.doubleVal);\n            else\n                value.success = value.expression.Evaluate(ref value.longVal);\n        }\n\n        internal static void GetInitialValue(ref NumberFieldValue value)\n        {\n            if (value.isDouble)\n            {\n                double oldValue = default;\n                if (UINumericFieldsUtils.TryConvertStringToDouble(s_OriginalText, out oldValue) && oldValue != value.doubleVal)\n                {\n                    value.doubleVal = oldValue;\n                    return;\n                }\n            }\n            else\n            {\n                long oldValue = default;\n                if (UINumericFieldsUtils.TryConvertStringToLong(s_OriginalText, out oldValue) && oldValue != value.longVal)\n                {\n                    value.longVal = oldValue;\n                    return;\n                }\n            }\n        }\n\n        internal static void UpdateNumberValueIfNeeded(ref NumberFieldValue value, in string str)\n        {\n            StringToNumericValue(str, ref value);\n\n            if (!value.success && value.expression != null)\n            {\n                using (s_EvalExpressionMarker.Auto())\n                {\n                    GetInitialValue(ref value);\n\n                    EvaluateExpressionOnNumberFieldValue(ref value);\n                }\n            }\n\n            GUI.changed = value.success || value.expression != null;\n        }\n        internal static void DoNumberField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id,\n            ref NumberFieldValue value, string formatString, GUIStyle style, bool draggable,\n            double dragSensitivity)\n        {\n            bool changed;\n            string allowedCharacters = value.isDouble ? s_AllowedCharactersForFloat : s_AllowedCharactersForInt;\n            if (draggable && GUI.enabled)\n            {\n                DragNumberValue(dragHotZone, id, ref value, dragSensitivity);\n            }\n\n            Event evt = Event.current;\n            string str;\n            if (HasKeyboardFocus(id) || (evt.type == EventType.MouseDown && evt.button == 0 && position.Contains(evt.mousePosition)))\n            {\n                if (!editor.IsEditingControl(id))\n                {\n                    str = s_RecycledCurrentEditingString = value.isDouble ? value.doubleVal.ToString(formatString, CultureInfo.InvariantCulture) : value.longVal.ToString(formatString, CultureInfo.InvariantCulture);\n                }\n                else\n                {\n                    str = s_RecycledCurrentEditingString;\n                    if (evt.type == EventType.ValidateCommand && evt.commandName == EventCommandNames.UndoRedoPerformed)\n                    {\n                        str = value.isDouble ? value.doubleVal.ToString(formatString, CultureInfo.InvariantCulture) : value.longVal.ToString(formatString, CultureInfo.InvariantCulture);\n                    }\n                }\n            }\n            else\n            {\n                str = value.isDouble ? value.doubleVal.ToString(formatString, CultureInfo.InvariantCulture) : value.longVal.ToString(formatString, CultureInfo.InvariantCulture);\n            }\n\n            str = DoTextField(editor, id, position, str, style, allowedCharacters, out changed, false, false, false);\n\n            if (GUIUtility.keyboardControl == id && changed)\n            {\n                // If we are still actively editing, return the input values\n                s_RecycledCurrentEditingString = str;\n\n                UpdateNumberValueIfNeeded(ref value, str);\n            }\n        }\n\n        internal static bool StringToDouble(string str, out double value)\n        {\n            NumberFieldValue v = default;\n            StringToDouble(str, ref v);\n            value = v.doubleVal;\n            return v.success;\n        }\n\n        static void StringToDouble(string str, ref NumberFieldValue value)\n        {\n            value.success = UINumericFieldsUtils.TryConvertStringToDouble(str, out value.doubleVal, out value.expression);\n        }\n\n        internal static bool StringToLong(string str, out long value)\n        {\n            NumberFieldValue v = default;\n            StringToLong(str, ref v);\n            value = v.longVal;\n            return v.success;\n        }\n\n        static void StringToLong(string str, ref NumberFieldValue value)\n        {\n            value.expression = null;\n            value.success = UINumericFieldsUtils.TryConvertStringToLong(str, out value.longVal, out value.expression);\n        }\n\n        internal static int ArraySizeField(Rect position, GUIContent label, int value, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_ArraySizeFieldHash, FocusType.Keyboard, position);\n\n            BeginChangeCheck();\n            string str = DelayedTextFieldInternal(position, id, label, value.ToString(kIntFieldFormatString), \"0123456789-\", style);\n            if (EndChangeCheck())\n            {\n                try\n                {\n                    value = int.Parse(str, CultureInfo.InvariantCulture.NumberFormat);\n                }\n                catch (FormatException)\n                {\n                }\n            }\n            return value;\n        }\n\n        internal static string DelayedTextFieldInternal(Rect position, string value, string allowedLetters, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_DelayedTextFieldHash, FocusType.Keyboard, position);\n            return DelayedTextFieldInternal(position, id, GUIContent.none, value, allowedLetters, style);\n        }\n\n        internal static string DelayedTextFieldInternal(Rect position, int id, GUIContent label, string value, string allowedLetters, GUIStyle style)\n        {\n            // Figure out which string should be shown: If we're currently editing we disregard the incoming value\n            string str;\n\n            if (HasKeyboardFocus(id))\n            {\n                // If we just got focus, set up s_RecycledCurrentEditingString\n                if (!s_DelayedTextEditor.IsEditingControl(id))\n                {\n                    str = s_RecycledCurrentEditingString = value;\n                }\n                else\n                {\n                    str = s_RecycledCurrentEditingString;\n                }\n                Event evt = Event.current;\n                if (evt.type == EventType.ValidateCommand && evt.commandName == EventCommandNames.UndoRedoPerformed)\n                {\n                    str = value;\n                }\n            }\n            else\n            {\n                str = value;\n            }\n\n            bool changed;\n            bool wasChanged = GUI.changed;\n            str = s_DelayedTextEditor.OnGUI(id, str, out changed);\n            GUI.changed = false;\n\n            if (!changed)\n            {\n                str = DoTextField(s_DelayedTextEditor, id, PrefixLabel(position, id, label), str, style, allowedLetters, out changed, false, false, false);\n                GUI.changed = false;\n                // If we are still actively editing, return the input values\n                if (GUIUtility.keyboardControl == id)\n                {\n                    if (!s_DelayedTextEditor.IsEditingControl(id))\n                    {\n                        if ((value != str) && (!showMixedValue || (showMixedValue && k_MultiEditValueString != str)))\n                        {\n                            GUI.changed = true;\n                            value = str;\n                        }\n                    }\n                    else\n                    {\n                        s_RecycledCurrentEditingString = str;\n                    }\n                }\n            }\n            else\n            {\n                GUI.changed = true;\n                value = str;\n            }\n            GUI.changed |= wasChanged;\n            return value;\n        }\n\n        internal static void DelayedTextFieldInternal(Rect position, int id, SerializedProperty property, string allowedLetters, GUIContent label, GUIStyle style)\n        {\n            label = BeginProperty(position, label, property);\n\n            BeginChangeCheck();\n            string newValue = DelayedTextFieldInternal(position, id, label, property.stringValue, allowedLetters, style);\n            if (EndChangeCheck())\n                property.stringValue = newValue;\n\n            EndProperty();\n        }\n\n        internal static void DelayedNumberFieldInternal(Rect position, Rect dragHotZone, int id, bool isDouble,\n            ref double doubleVal, ref long longVal, string formatString, GUIStyle style, bool draggable,\n            double dragSensitivity)\n        {\n            NumberFieldValue val = default;\n            val.isDouble = isDouble;\n            val.doubleVal = doubleVal;\n            val.longVal = longVal;\n            DelayedNumberFieldInternal(position, dragHotZone, id, ref val, formatString, style, draggable, dragSensitivity);\n            if (val.success)\n            {\n                doubleVal = val.doubleVal;\n                longVal = val.longVal;\n            }\n        }\n\n        static void DelayedNumberFieldInternal(Rect position, Rect dragHotZone, int id,\n            ref NumberFieldValue value, string formatString, GUIStyle style, bool draggable,\n            double dragSensitivity)\n        {\n            string allowedCharacters = value.isDouble ? s_AllowedCharactersForFloat : s_AllowedCharactersForInt;\n\n            Event evt = Event.current;\n            string str;\n            if (HasKeyboardFocus(id) || (evt.type == EventType.MouseDown && evt.button == 0 && position.Contains(evt.mousePosition)))\n            {\n                if (!s_DelayedTextEditor.IsEditingControl(id) && s_DragCandidateState == DragCandidateState.NotDragging)\n                {\n                    str = s_RecycledCurrentEditingString = value.isDouble ? value.doubleVal.ToString(formatString, CultureInfo.InvariantCulture) : value.longVal.ToString(formatString, CultureInfo.InvariantCulture);\n                }\n                else\n                {\n                    str = s_RecycledCurrentEditingString;\n                    if (evt.type == EventType.ValidateCommand && evt.commandName == EventCommandNames.UndoRedoPerformed)\n                    {\n                        str = value.isDouble ? value.doubleVal.ToString(formatString, CultureInfo.InvariantCulture) : value.longVal.ToString(formatString, CultureInfo.InvariantCulture);\n                    }\n                }\n            }\n            else\n            {\n                str = value.isDouble ? value.doubleVal.ToString(formatString, CultureInfo.InvariantCulture) : value.longVal.ToString(formatString, CultureInfo.InvariantCulture);\n            }\n\n            if (draggable)\n            {\n                double dragDouble = 0;\n                long dragLong = 0;\n                bool isConverted = value.isDouble ? StringToDouble(str, out dragDouble) : StringToLong(str, out dragLong);\n\n                if (isConverted)\n                {\n                    DragNumberValue(dragHotZone, id, value.isDouble, ref dragDouble, ref dragLong, dragSensitivity);\n                    str = value.isDouble ? dragDouble.ToString(formatString, CultureInfo.InvariantCulture) : dragLong.ToString(formatString, CultureInfo.InvariantCulture);\n                }\n            }\n\n            bool changed;\n            bool wasChanged = GUI.changed;\n            str = s_DelayedTextEditor.OnGUI(id, str, out changed);\n            GUI.changed = false;\n\n            if (!changed)\n            {\n                str = DoTextField(s_DelayedTextEditor, id, position, str, style, allowedCharacters, out changed, false, false, false);\n                GUI.changed = false;\n\n                // If we are still actively editing, return the input values\n                if (GUIUtility.keyboardControl == id)\n                {\n                    s_RecycledCurrentEditingString = str;\n\n                    if (!s_DelayedTextEditor.IsEditingControl(id) && s_DragCandidateState == DragCandidateState.NotDragging)\n                    {\n                        bool equalValues = false;\n                        if (value.isDouble)\n                        {\n                            equalValues = double.TryParse(str, out var strToDouble) && Math.Abs(value.doubleVal - strToDouble) < Double.Epsilon;\n                        }\n                        else\n                        {\n                            equalValues = str.Equals(value.longVal);\n                        }\n                        if (!equalValues && (!showMixedValue || (showMixedValue && k_MultiEditValueString != str)))\n                        {\n                            GUI.changed = true;\n                            if (value.isDouble)\n                                StringToDouble(str, ref value);\n                            else\n                                StringToLong(str, ref value);\n                        }\n                    }\n                }\n            }\n            else\n            {\n                UpdateNumberValueIfNeeded(ref value, str);\n            }\n            GUI.changed |= wasChanged;\n        }\n\n        internal static float DelayedFloatFieldInternal(Rect position, GUIContent label, float value, GUIStyle style)\n        {\n            bool wasChanged = GUI.changed;\n\n            int id = GUIUtility.GetControlID(s_DelayedTextFieldHash, FocusType.Keyboard, position);\n            long dummy = 0;\n            double doubleValue = value;\n            Rect dragHotzone = new Rect(0, 0, 0, 0);\n            bool draggable = SetDelayedDraggable(ref position, ref dragHotzone, label, id);\n\n            BeginChangeCheck();\n            DelayedNumberFieldInternal(position, dragHotzone, id, true, ref doubleValue, ref dummy, kFloatFieldFormatString, style, draggable, Event.current.GetTypeForControl(id) == EventType.MouseDown ? (float)NumericFieldDraggerUtility.CalculateFloatDragSensitivity(s_DragStartValue) : 0.0f);\n            if (EndChangeCheck())\n            {\n                if ((float)doubleValue != value)\n                    return (float)doubleValue;\n                GUI.changed = wasChanged;\n            }\n            return value;\n        }\n\n        internal static void DelayedFloatFieldInternal(Rect position, SerializedProperty property, GUIContent label)\n        {\n            label = BeginProperty(position, label, property);\n\n            BeginChangeCheck();\n            float newValue = DelayedFloatFieldInternal(position, label, property.floatValue, EditorStyles.numberField);\n            if (EndChangeCheck())\n                property.floatValue = newValue;\n\n            EndProperty();\n        }\n\n        internal static double DelayedDoubleFieldInternal(Rect position, GUIContent label, double value, GUIStyle style)\n        {\n            bool wasChanged = GUI.changed;\n\n            int id = GUIUtility.GetControlID(s_DelayedTextFieldHash, FocusType.Keyboard, position);\n            long dummy = 0;\n            double newDoubleValue = value;\n            Rect dragHotzone = new Rect(0, 0, 0, 0);\n            bool draggable = SetDelayedDraggable(ref position, ref dragHotzone, label, id);\n\n            BeginChangeCheck();\n            DelayedNumberFieldInternal(position, dragHotzone, id, true, ref newDoubleValue, ref dummy, kFloatFieldFormatString, style, draggable, Event.current.GetTypeForControl(id) == EventType.MouseDown ? (float)NumericFieldDraggerUtility.CalculateFloatDragSensitivity(s_DragStartValue) : 0.0f);\n            if (EndChangeCheck())\n            {\n                if (newDoubleValue != value)\n                    return newDoubleValue;\n                GUI.changed = wasChanged;\n            }\n            return value;\n        }\n\n        internal static int DelayedIntFieldInternal(Rect position, GUIContent label, int value, GUIStyle style)\n        {\n            bool wasChanged = GUI.changed;\n\n            int id = GUIUtility.GetControlID(s_DelayedTextFieldHash, FocusType.Keyboard, position);\n            double dummy = 0;\n            long longValue = value;\n            Rect dragHotzone = new Rect(0, 0, 0, 0);\n            bool draggable = SetDelayedDraggable(ref position, ref dragHotzone, label, id);\n\n            BeginChangeCheck();\n            DelayedNumberFieldInternal(position, dragHotzone, id, false, ref dummy, ref longValue, kIntFieldFormatString, style, draggable, Event.current.GetTypeForControl(id) == EventType.MouseDown ? (float)NumericFieldDraggerUtility.CalculateIntDragSensitivity(value) : 0.0f);\n            if (EndChangeCheck())\n            {\n                if ((int)longValue != value)\n                    return (int)longValue;\n                GUI.changed = wasChanged;\n            }\n            return value;\n        }\n\n        internal static void DelayedIntFieldInternal(Rect position, SerializedProperty property, GUIContent label)\n        {\n            label = BeginProperty(position, label, property);\n\n            BeginChangeCheck();\n            int newValue = DelayedIntFieldInternal(position, label, property.intValue, EditorStyles.numberField);\n            if (EndChangeCheck())\n                property.intValue = newValue;\n\n            EndProperty();\n        }\n\n        internal static bool SetDelayedDraggable(ref Rect position, ref Rect dragHotzone, GUIContent label, int id)\n        {\n            //Fields without labels are not considered draggable\n            bool draggable = label != GUIContent.none;\n            if (draggable)\n            {\n                dragHotzone = position;\n                position = PrefixLabel(position, id, label);\n                dragHotzone.xMax = position.x;\n            }\n            else\n            {\n                position = IndentedRect(position);\n            }\n\n            return draggable;\n        }\n\n        internal static int IntFieldInternal(Rect position, int value, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position);\n            return DoIntField(s_RecycledEditor, IndentedRect(position), new Rect(0, 0, 0, 0), id, value, kIntFieldFormatString, style, false, NumericFieldDraggerUtility.CalculateIntDragSensitivity(value));\n        }\n\n        // Make a text field for entering integers.\n        internal static int IntFieldInternal(Rect position, GUIContent label, int value, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position);\n            Rect position2 = PrefixLabel(position, id, label);\n            position.xMax = position2.x;\n            return DoIntField(s_RecycledEditor, position2, position, id, value, kIntFieldFormatString, style, true, NumericFieldDraggerUtility.CalculateIntDragSensitivity(value));\n        }\n\n        internal static long LongFieldInternal(Rect position, long value, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position);\n            return DoLongField(s_RecycledEditor, IndentedRect(position), new Rect(0, 0, 0, 0), id, value, kIntFieldFormatString, style, false, NumericFieldDraggerUtility.CalculateIntDragSensitivity(value));\n        }\n\n        // Make a text field for entering integers.\n        internal static long LongFieldInternal(Rect position, GUIContent label, long value, GUIStyle style)\n        {\n            NumberFieldValue v = new NumberFieldValue(value);\n            LongFieldInternal(position, label, ref v, style);\n            return v.longVal;\n        }\n\n        static void LongFieldInternal(Rect position, GUIContent label, ref NumberFieldValue value, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position);\n            Rect position2 = PrefixLabel(position, id, label);\n            position.xMax = position2.x;\n            var dragSensitivity = NumericFieldDraggerUtility.CalculateIntDragSensitivity(value.longVal);\n            DoNumberField(s_RecycledEditor, position2, position, id, ref value, kIntFieldFormatString, style, true, dragSensitivity);\n        }\n\n        public static float Slider(Rect position, float value, float leftValue, float rightValue)\n        {\n            int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Keyboard, position);\n            return DoSlider(IndentedRect(position), EditorGUIUtility.DragZoneRect(position, false), id, value, leftValue, rightValue, kFloatFieldFormatString);\n        }\n\n        public static float Slider(Rect position, string label, float value, float leftValue, float rightValue)\n        {\n            return Slider(position, EditorGUIUtility.TempContent(label), value, leftValue, rightValue);\n        }\n\n        // Make a slider the user can drag to change a value between a min and a max.\n        public static float Slider(Rect position, GUIContent label, float value, float leftValue, float rightValue)\n        {\n            return Slider(position, label, value, leftValue, rightValue, EditorStyles.numberField);\n        }\n\n        internal static float Slider(Rect position, GUIContent label, float value, float leftValue, float rightValue, GUIStyle textfieldStyle)\n        {\n            return PowerSlider(position, label, value, leftValue, rightValue, textfieldStyle, 1.0f);\n        }\n\n        internal static float Slider(Rect position, GUIContent label, float value, float sliderMin, float sliderMax, float textFieldMin, float textFieldMax)\n        {\n            return Slider(position, label, value, sliderMin, sliderMax, textFieldMin, textFieldMax,\n                EditorStyles.numberField, GUI.skin.horizontalSlider, GUI.skin.horizontalSliderThumb, null,\n                GUI.skin.horizontalSliderThumbExtent);\n        }\n\n        internal static float Slider(Rect position, GUIContent label, float value, float sliderMin, float sliderMax, float textFieldMin, float textFieldMax\n            , GUIStyle textfieldStyle, GUIStyle sliderStyle, GUIStyle thumbStyle, Texture2D sliderBackground, GUIStyle thumbStyleExtent)\n        {\n            var id = GUIUtility.GetControlID(s_SliderHash, FocusType.Keyboard, position);\n            var controlRect = PrefixLabel(position, id, label);\n            var dragZone = LabelHasContent(label) ? EditorGUIUtility.DragZoneRect(position) : new Rect(); // Ensure dragzone is empty when we have no label\n            return DoSlider(controlRect, dragZone, id, value, sliderMin, sliderMax, kFloatFieldFormatString, textFieldMin, textFieldMax, 1f, 1f,\n                textfieldStyle, sliderStyle, thumbStyle, sliderBackground, thumbStyleExtent);\n        }\n\n        internal static float PowerSlider(Rect position, string label, float sliderValue, float leftValue, float rightValue, float power)\n        {\n            return PowerSlider(position, EditorGUIUtility.TempContent(label), sliderValue, leftValue, rightValue, power);\n        }\n\n        // Make a power slider the user can drag to change a value between a min and a max.\n        internal static float PowerSlider(Rect position, GUIContent label, float sliderValue, float leftValue,\n            float rightValue, float power)\n        {\n            return PowerSlider(position, label, sliderValue, leftValue, rightValue, EditorStyles.numberField, power);\n        }\n\n        internal static float PowerSlider(Rect position, GUIContent label, float sliderValue, float leftValue, float rightValue, GUIStyle textfieldStyle, float power)\n        {\n            int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Keyboard, position);\n            Rect controlRect = PrefixLabel(position, id, label);\n            Rect dragZone = LabelHasContent(label) ? EditorGUIUtility.DragZoneRect(position) : new Rect(); // Ensure dragzone is empty when we have no label\n            return DoSlider(controlRect, dragZone, id, sliderValue, leftValue, rightValue, kFloatFieldFormatString, textfieldStyle, power);\n        }\n\n        public static int LogarithmicIntSlider(Rect position, string label, int sliderValue, int leftValue, int rightValue, int logbase, int textFieldMin, int textFieldMax)\n        {\n            return LogarithmicIntSlider(position, EditorGUIUtility.TempContent(label), sliderValue, leftValue, rightValue, logbase, textFieldMin, textFieldMax);\n        }\n\n        public static int LogarithmicIntSlider(Rect position, GUIContent label, int sliderValue, int leftValue, int rightValue, int logbase, int textFieldMin, int textFieldMax)\n        {\n            return LogarithmicIntSlider(position, label, sliderValue, leftValue, rightValue, EditorStyles.numberField, logbase, textFieldMin, textFieldMax);\n        }\n\n        internal static int LogarithmicIntSlider(Rect position, GUIContent label, int sliderValue, int leftValue, int rightValue, GUIStyle textfieldStyle, int logbase, int textFieldMin, int textFieldMax)\n        {\n            int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Keyboard, position);\n            Rect controlRect = PrefixLabel(position, id, label);\n            Rect dragZone = LabelHasContent(label) ? EditorGUIUtility.DragZoneRect(position) : new Rect(); // Ensure dragzone is empty when we have no label\n            return Mathf.RoundToInt(DoSlider(controlRect, dragZone, id, (float) sliderValue, (float) leftValue, (float) rightValue, kIntFieldFormatString, power:1, logbase: logbase, textFieldMin: textFieldMin, textFieldMax: textFieldMax));\n        }\n\n        private static float PowPreserveSign(float f, float p)\n        {\n            var result = Mathf.Pow(Mathf.Abs(f), p);\n            return f < 0.0f ? -result : result;\n        }\n\n        internal static GenericMenu FillPropertyContextMenu(SerializedProperty property, SerializedProperty linkedProperty = null, GenericMenu menu = null, VisualElement element = null)\n        {\n            if (property == null)\n                return null;\n\n            if (linkedProperty != null && linkedProperty.serializedObject != property.serializedObject)\n                linkedProperty = null;\n\n            GenericMenu pm = menu ?? new GenericMenu();\n\n            var itargetobjects = property.serializedObject.targetObjectsCount;\n            for (int icount = 0; icount < itargetobjects; icount++)\n            {\n                if (!property.serializedObject.targetObjects[icount])\n                    return null;\n            }\n\n            // Since the menu items are invoked with delay, we can't assume a SerializedObject we don't own\n            // will still be around at that time. Hence create our own copy. (case 1051734)\n            SerializedObject serializedObjectCopy = new SerializedObject(property.serializedObject.targetObjects);\n            SerializedProperty propertyWithPath = serializedObjectCopy.FindProperty(property.propertyPath);\n\n            if (propertyWithPath == null)\n                return null;\n\n            // FillPropertyContextMenu is now always called when a right click is done on a property.\n            // However we don't want those menu to be added when the property is disabled.\n            if (GUI.enabled)\n            {\n                ScriptAttributeUtility.GetHandler(property).AddMenuItems(property, pm);\n\n                SerializedProperty linkedPropertyWithPath = null;\n                if (linkedProperty != null)\n                {\n                    linkedPropertyWithPath = serializedObjectCopy.FindProperty(linkedProperty.propertyPath);\n                    ScriptAttributeUtility.GetHandler(linkedProperty).AddMenuItems(linkedProperty, pm);\n                }\n\n                // Would be nice to allow to set to value of a specific target for properties with children too,\n                // but it's not currently supported.\n                if (property.hasMultipleDifferentValues && !property.hasVisibleChildren)\n                {\n                    TargetChoiceHandler.AddSetToValueOfTargetMenuItems(pm, propertyWithPath, TargetChoiceHandler.SetToValueOfTarget);\n                }\n\n                Object targetObject = property.serializedObject.targetObject;\n\n                PropertyValueOriginInfo propertyOrigin = PrefabUtility.GetPropertyValueOriginInfo(property);\n\n                if (propertyOrigin.asset != null)\n                {\n                    pm.AddItem(new GUIContent(\"Go to \" + propertyOrigin.contextMenuText + \" in '\" + propertyOrigin.asset.name + \"'\"), false,\n                        () => GoToPrefab(AssetDatabase.GetAssetPath(propertyOrigin.asset), PrefabUtility.GetGameObject(targetObject)));\n                }\n\n                bool shouldDisplayPrefabContextMenuItems = property.prefabOverride || (linkedProperty?.prefabOverride ?? false);\n\n                // Only display the custom apply/revert menu for GameObjects/Components that are not part of a Prefab instance & variant.\n                var shouldDisplayApplyRevertProviderContextMenuItems = targetObject is IApplyRevertPropertyContextMenuItemProvider;\n\n                if (shouldDisplayPrefabContextMenuItems || shouldDisplayApplyRevertProviderContextMenuItems)\n                {\n                    SerializedProperty[] properties;\n                    if (linkedProperty == null)\n                        properties = new SerializedProperty[] { propertyWithPath };\n                    else\n                        properties = new SerializedProperty[] { propertyWithPath, linkedPropertyWithPath };\n\n                    if (shouldDisplayApplyRevertProviderContextMenuItems)\n                    {\n                        var provider = targetObject as IApplyRevertPropertyContextMenuItemProvider;\n                        if (provider.TryGetApplyMethodForFieldName(propertyWithPath, out Action<SerializedProperty> applyMethod))\n                        {\n                            pm.AddItem(\n                                new GUIContent() { text = $\"Apply override to '{provider.GetSourceName(targetObject as Component)}' {provider.GetSourceTerm()}\" },\n                                false,\n                                (o) => applyMethod(propertyWithPath),\n                                properties);\n                        }\n\n                        if (provider.TryGetRevertMethodForFieldName(propertyWithPath, out Action<SerializedProperty> revertMethod))\n                        {\n                            pm.AddItem(\n                                new GUIContent() { text = $\"Revert {provider.GetSourceTerm()} override\" },\n                                false,\n                                (o) => revertMethod(propertyWithPath),\n                                properties);\n                        }\n                    }\n                    else if (shouldDisplayPrefabContextMenuItems)\n                    {\n                        bool samePropertyValueAsSource = false;\n\n                        Object source = PrefabUtility.GetCorrespondingObjectFromSource(targetObject);\n                        SerializedObject sourceSerializedObject = new SerializedObject(source);\n                        SerializedProperty sourceProperty = sourceSerializedObject.FindProperty(property.propertyPath);\n\n                        samePropertyValueAsSource = SerializedProperty.DataEquals(property, sourceProperty);\n\n                        PrefabUtility.HandleApplyRevertMenuItems(\n                            null,\n                            targetObject,\n                            (menuItemContent, sourceObject, _) =>\n                            {\n                                // Add apply menu item for this apply target.\n                                TargetChoiceHandler.PropertyAndSourcePathInfo info = new TargetChoiceHandler.PropertyAndSourcePathInfo();\n                                info.properties = properties;\n                                info.assetPath = AssetDatabase.GetAssetPath(sourceObject);\n                                GameObject rootObject = PrefabUtility.GetRootGameObject(sourceObject);\n                                if (EditorUtility.IsPersistent(targetObject)\n                                    || !PrefabUtility.IsPartOfPrefabThatCanBeAppliedTo(rootObject)\n                                    || !PrefabUtility.CanPropertyBeAppliedToTarget(property, rootObject))\n                                    pm.AddDisabledItem(menuItemContent);\n                                else\n                                    pm.AddItem(menuItemContent, false, TargetChoiceHandler.ApplyPrefabPropertyOverride, info);\n                            },\n                            (menuItemContent) =>\n                            {\n                                // Add revert menu item.\n                                GUIContent content;\n                                if (samePropertyValueAsSource)\n                                {\n                                    GameObject sourceRoot = PrefabUtility.GetRootGameObject(source);\n                                    content = new GUIContent(string.Format(Styles.revertPropertyValueIdenticalToSource, sourceRoot.name));\n                                }\n                                else\n                                {\n                                    content = menuItemContent;\n                                }\n\n                                pm.AddItem(content, false, TargetChoiceHandler.RevertPrefabPropertyOverride, properties);\n                            },\n                            false,\n                            property.serializedObject.targetObjectsCount\n                        );\n                    }\n                }\n            }\n\n            // Add copy/paste clipboard operations if available (the entries themselves\n            // will check for GUI enablement; e.g. Copy should be there even for disabled\n            // GUI but Paste should not).\n            ClipboardContextMenu.SetupPropertyCopyPaste(propertyWithPath, menu: pm, evt: null);\n\n            if (GUI.enabled)\n            {\n                // If property is an element in an array, show duplicate and delete menu options\n                if (property.propertyPath.LastIndexOf(']') == property.propertyPath.Length - 1)\n                {\n                    var parentArrayPropertyPath = property.propertyPath.Substring(0, property.propertyPath.LastIndexOf(\".Array.data[\", StringComparison.Ordinal));\n                    var parentArrayProperty = property.serializedObject.FindProperty(parentArrayPropertyPath);\n\n                    var parentArrayIndex = -1;\n\n                    // Referencing the selected element in the array ensures that Duplicate/Delete\n                    // work correctly on non reordable lists, so we need to try and parse it's index out of the path string.\n                    try\n                    {\n                        // Strip the string up to the first .Array.data[\n                        var parentArrayIndexString = property.propertyPath.Substring(property.propertyPath.LastIndexOf(\".Array.data[\", StringComparison.Ordinal) + 12);\n                        // Strip everything after the next ]\n                        parentArrayIndexString = parentArrayIndexString.Substring(0, parentArrayIndexString.IndexOf(\"]\"));\n                        // Attempt to parse this into an Int32\n                        parentArrayIndex = Int32.Parse(parentArrayIndexString);\n                    }\n                    catch { /*we can't parse an array index, so leave it -1*/ }\n\n                    if (!parentArrayProperty.isFixedBuffer)\n                    {\n                        if (pm.GetItemCount() > 0)\n                        {\n                            pm.AddSeparator(\"\");\n                        }\n\n                        pm.AddItem(EditorGUIUtility.TrTextContent(\"Duplicate Array Element\"), false, (a) =>\n                        {\n                            var list = ReorderableList.GetReorderableListFromSerializedProperty(parentArrayProperty);\n\n                            var listView = element?.GetFirstAncestorOfType<ListView>();\n\n                            // If we have a ReorderableList associated with this property lets use list selection array\n                            // and apply this action to all selected elements thus having better integration with\n                            // ReorderableLists multi-selection features\n                            if (list != null && list.selectedIndices.Count > 0)\n                            {\n                                for (int i = list.selectedIndices.Count - 1; i >= 0; i--)\n                                {\n                                    if (list.selectedIndices[i] >= parentArrayProperty.arraySize) continue;\n\n                                    SerializedProperty resolvedProperty = parentArrayProperty.GetArrayElementAtIndex(list.selectedIndices[i]);\n                                    if (resolvedProperty != null)\n                                    {\n                                        if (!TargetChoiceHandler.DuplicateArrayElement(resolvedProperty)) continue;\n                                    }\n\n                                    for (int j = i; j < list.selectedIndices.Count; j++)\n                                    {\n                                        list.m_Selection[j]++;\n                                    }\n                                }\n\n                                if (list.onChangedCallback != null)\n                                    list.onChangedCallback(list);\n\n                                ReorderableList.InvalidateExistingListCaches();\n                            }\n                            else if (listView != null && listView.selectedIndices.Any())\n                            {\n                                DuplicateListViewItems(listView, parentArrayProperty);\n                            }\n                            else // Non reorderable\n                            {\n                                if (parentArrayIndex >= 0 && parentArrayIndex < parentArrayProperty.arraySize)\n                                {\n                                    SerializedProperty resolvedProperty = parentArrayProperty.GetArrayElementAtIndex(parentArrayIndex);\n                                    if (resolvedProperty != null)\n                                    {\n                                        TargetChoiceHandler.DuplicateArrayElement(resolvedProperty);\n                                    }\n                                }\n                                else\n                                {\n                                    TargetChoiceHandler.DuplicateArrayElement(a);\n                                }\n                            }\n\n                            if(list != null)\n                            {\n                                if (list.onChangedCallback != null) list.onChangedCallback(list);\n                                ReorderableList.InvalidateExistingListCaches();\n                            }\n                            EditorGUIUtility.editingTextField = false;\n                        }, propertyWithPath);\n                        pm.AddItem(EditorGUIUtility.TrTextContent(\"Delete Array Element\"), false, (a) =>\n                        {\n                            var list = ReorderableList.GetReorderableListFromSerializedProperty(parentArrayProperty);\n\n                            var listView = element?.GetFirstAncestorOfType<ListView>();\n\n                            // If we have a ReorderableList associated with this property lets use list selection array\n                            // and apply this action to all selected elements thus having better integration with\n                            // ReorderableLists multi-selection features\n                            if (list != null && list.selectedIndices.Count > 0)\n                            {\n                                foreach (var selected in list.selectedIndices.Reverse<int>())\n                                {\n                                    if (selected >= parentArrayProperty.arraySize) continue;\n\n                                    SerializedProperty resolvedProperty = parentArrayProperty.GetArrayElementAtIndex(selected);\n                                    if (resolvedProperty != null)\n                                    {\n                                        if (!TargetChoiceHandler.DeleteArrayElement(resolvedProperty)) continue;\n                                    }\n                                }\n\n                                list.m_Selection.Clear();\n\n                                if (list.onChangedCallback != null)\n                                    list.onChangedCallback(list);\n                                ReorderableList.InvalidateExistingListCaches();\n                            }\n                            else if (listView != null && listView.selectedIndices.Any())\n                            {\n                                DeleteListViewItems(listView, parentArrayProperty);\n                            }\n                            else // Non reorderable\n                            {\n                                if (parentArrayIndex >= 0 && parentArrayIndex < parentArrayProperty.arraySize)\n                                {\n                                    SerializedProperty resolvedProperty = parentArrayProperty.GetArrayElementAtIndex(parentArrayIndex);\n                                    if (resolvedProperty != null)\n                                    {\n                                        TargetChoiceHandler.DeleteArrayElement(resolvedProperty);\n                                    }\n                                }\n                                else\n                                {\n                                    TargetChoiceHandler.DeleteArrayElement(a);\n                                }\n                            }\n\n                            if(list != null)\n                            {\n                                list.m_Selection.Clear();\n                                if (list.onChangedCallback != null) list.onChangedCallback(list);\n                                ReorderableList.InvalidateExistingListCaches();\n                            }\n                            EditorGUIUtility.editingTextField = false;\n                        }, propertyWithPath);\n                    }\n                }\n            }\n\n            // If shift is held down, show debug menu options\n            // This menu is not excluded when the field is disabled\n            // because it is nice to get information about the property even when it's disabled.\n            if (Event.current.shift)\n            {\n                if (pm.GetItemCount() > 0)\n                    pm.AddSeparator(\"\");\n                pm.AddItem(EditorGUIUtility.TrTextContent(\"Print Property Path\"), false, e => Debug.Log(((SerializedProperty)e).propertyPath), propertyWithPath);\n            }\n\n            // If property is a reference and we're using VCS, add item to check it out\n            // This menu is not excluded when the field is disabled\n            // because it is nice to get information about the property even when it's disabled.\n            if (propertyWithPath.propertyType == SerializedPropertyType.ObjectReference && VersionControlUtils.isVersionControlConnected)\n            {\n                var obj = propertyWithPath.objectReferenceValue;\n                if (obj != null && !AssetDatabase.IsOpenForEdit(obj))\n                {\n                    if (pm.GetItemCount() > 0)\n                        pm.AddSeparator(\"\");\n                    pm.AddItem(\n                        new GUIContent(L10n.Tr(\"Check Out\") + \" '\" + obj.name + \"'\"),\n                        false,\n                        o => AssetDatabase.MakeEditable(AssetDatabase.GetAssetOrScenePath((Object)o)),\n                        obj);\n                }\n            }\n\n            // FillPropertyContextMenu is now always called when a right click is done on a property.\n            // However we don't want those menu to be added when the property is disabled.\n            if (GUI.enabled)\n            {\n                if (EditorApplication.contextualPropertyMenu != null)\n                {\n                    if (pm.GetItemCount() > 0)\n                        pm.AddSeparator(\"\");\n                    EditorApplication.contextualPropertyMenu(pm, property);\n                }\n            }\n\n            EditorGUIUtility.ContextualPropertyMenuCallback(pm, property);\n\n            return pm;\n        }\n\n        internal static void DeleteListViewItems(BaseListView baseListView, SerializedProperty parentArrayProperty)\n        {\n            var previousSelectedIndices = new List<int>(baseListView.selectedIndices);\n            previousSelectedIndices.Sort();\n            baseListView.ClearSelection();\n\n            for (int i = previousSelectedIndices.Count - 1; i >= 0; i--)\n            {\n                var index = previousSelectedIndices.ElementAt(i);\n                if (index >= baseListView.itemsSource.Count) continue;\n\n                SerializedProperty resolvedProperty = parentArrayProperty.GetArrayElementAtIndex(index);\n                if (resolvedProperty != null)\n                {\n                    if (!TargetChoiceHandler.DeleteArrayElement(resolvedProperty)) continue;\n                }\n            }\n        }\n\n        internal static void DuplicateListViewItems(BaseListView baseListView, SerializedProperty parentArrayProperty)\n        {\n            var previousSelectedIndices = new List<int>(baseListView.selectedIndices);\n            previousSelectedIndices.Sort();\n            var newSelectedIndices = new List<int>();\n            baseListView.ClearSelection();\n\n            for (int i = previousSelectedIndices.Count - 1; i >= 0; i--)\n            {\n                var index = previousSelectedIndices.ElementAt(i);\n                if (index >= baseListView.itemsSource.Count) continue;\n\n                SerializedProperty resolvedProperty = parentArrayProperty.GetArrayElementAtIndex(index);\n                if (resolvedProperty != null)\n                {\n                    if (!TargetChoiceHandler.DuplicateArrayElement(resolvedProperty)) continue;\n                }\n\n                // need to update the rest of the selected indices as an element was added\n                for (int j = i + 1; j < previousSelectedIndices.Count; j++)\n                {\n                    previousSelectedIndices[j]++;\n                }\n\n                for (int j = 0; j < newSelectedIndices.Count; j++)\n                {\n                    newSelectedIndices[j]++;\n                }\n\n                newSelectedIndices.Add(previousSelectedIndices[i] + 1);\n            }\n\n            newSelectedIndices.Sort();\n            baseListView.SetSelection(newSelectedIndices);\n        }\n\n        internal static void GoToPrefab(string assetPath, GameObject openedFromInstance)\n        {\n            // When this function is called from a Property Context Menu on the Overrides pop-up window, we need to make ensure that the correct GameObject\n            // (i.e. the GameObject that the property belongs to) is selected when opening Prefab Mode by explicitly setting it as the active GameObject.\n            if (EditorGUIUtility.comparisonViewMode != EditorGUIUtility.ComparisonViewMode.None)\n                Selection.activeGameObject = openedFromInstance;\n\n            PrefabStageUtility.OpenPrefab(assetPath, openedFromInstance, PrefabStage.Mode.InIsolation);\n        }\n\n        internal static void DoPropertyContextMenu(SerializedProperty property, SerializedProperty linkedProperty = null, GenericMenu menu = null)\n        {\n            GenericMenu pm = FillPropertyContextMenu(property, linkedProperty, menu);\n\n            if (pm == null || pm.GetItemCount() == 0)\n            {\n                return;\n            }\n\n            Event.current.Use();\n            pm.ShowAsContext();\n        }\n\n        public static void Slider(Rect position, SerializedProperty property, float leftValue, float rightValue)\n        {\n            Slider(position, property, leftValue, rightValue, property.displayName);\n        }\n\n        public static void Slider(Rect position, SerializedProperty property, float leftValue, float rightValue, string label)\n        {\n            Slider(position, property, leftValue, rightValue, EditorGUIUtility.TempContent(label));\n        }\n\n        // Make a slider the user can drag to change a value between a min and a max.\n        public static void Slider(Rect position, SerializedProperty property, float leftValue, float rightValue, GUIContent label)\n        {\n            label = BeginProperty(position, label, property);\n\n            BeginChangeCheck();\n\n            float newValue = Slider(position, label, property.floatValue, leftValue, rightValue);\n            if (EndChangeCheck())\n            {\n                property.floatValue = newValue;\n            }\n\n            EndProperty();\n        }\n\n        internal static void Slider(Rect position, SerializedProperty property, float sliderLeftValue, float sliderRightValue, float textLeftValue, float textRightValue, GUIContent label)\n        {\n            label = BeginProperty(position, label, property);\n\n            BeginChangeCheck();\n\n            float newValue = Slider(position, label, property.floatValue, sliderLeftValue, sliderRightValue, textLeftValue, textRightValue);\n            if (EndChangeCheck())\n            {\n                property.floatValue = newValue;\n            }\n\n            EndProperty();\n        }\n\n        internal static int IntSlider(Rect position, int value, int leftValue, int rightValue, float power = -1, float logbase = 1,\n            GUIStyle textfieldStyle = null, GUIStyle sliderStyle = null, GUIStyle thumbStyle = null, Texture2D sliderBackground = null, GUIStyle thumbStyleExtent = null)\n        {\n            int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Keyboard, position);\n            return Mathf.RoundToInt(DoSlider(IndentedRect(position), EditorGUIUtility.DragZoneRect(position), id, value, leftValue, rightValue, kIntFieldFormatString, power, logbase,\n                textfieldStyle ?? EditorStyles.numberField,\n                sliderStyle ?? GUI.skin.horizontalSlider,\n                thumbStyle ?? GUI.skin.horizontalSliderThumb,\n                sliderBackground,\n                thumbStyleExtent ?? GUI.skin.horizontalSliderThumbExtent));\n        }\n\n        public static int IntSlider(Rect position, int value, int leftValue, int rightValue)\n        {\n            int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Keyboard, position);\n            return Mathf.RoundToInt(DoSlider(IndentedRect(position), EditorGUIUtility.DragZoneRect(position), id, value, leftValue, rightValue, kIntFieldFormatString));\n        }\n\n        public static int IntSlider(Rect position, string label, int value, int leftValue, int rightValue)\n        {\n            return IntSlider(position, EditorGUIUtility.TempContent(label), value, leftValue, rightValue);\n        }\n\n        // Make a slider the user can drag to change an integer value between a min and a max.\n        public static int IntSlider(Rect position, GUIContent label, int value, int leftValue, int rightValue)\n        {\n            int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Keyboard, position);\n            return Mathf.RoundToInt(DoSlider(PrefixLabel(position, id, label), EditorGUIUtility.DragZoneRect(position), id, value, leftValue, rightValue, kIntFieldFormatString, EditorStyles.numberField));\n        }\n\n        public static void IntSlider(Rect position, SerializedProperty property, int leftValue, int rightValue)\n        {\n            IntSlider(position, property, leftValue, rightValue, property.displayName);\n        }\n\n        public static void IntSlider(Rect position, SerializedProperty property, int leftValue, int rightValue, string label)\n        {\n            IntSlider(position, property, leftValue, rightValue, EditorGUIUtility.TempContent(label));\n        }\n\n        // Make a slider the user can drag to change a value between a min and a max.\n        public static void IntSlider(Rect position, SerializedProperty property, int leftValue, int rightValue, GUIContent label)\n        {\n            label = BeginProperty(position, label, property);\n\n            BeginChangeCheck();\n\n            int newValue = IntSlider(position, label, property.intValue, leftValue, rightValue);\n            if (EndChangeCheck())\n            {\n                property.intValue = newValue;\n            }\n\n            EndProperty();\n        }\n\n        // Generic method for showing a left aligned and right aligned label within a rect\n        internal static void DoTwoLabels(Rect rect, GUIContent leftLabel, GUIContent rightLabel, GUIStyle labelStyle)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            TextAnchor oldAlignment = labelStyle.alignment;\n\n            labelStyle.alignment = TextAnchor.UpperLeft;\n            GUI.Label(rect, leftLabel, labelStyle);\n\n            labelStyle.alignment = TextAnchor.UpperRight;\n            GUI.Label(rect, rightLabel, labelStyle);\n\n            labelStyle.alignment = oldAlignment;\n        }\n\n        internal static float DoSlider(Rect position, Rect dragZonePosition, int id, float value, float left, float right, string formatString, float power = 1f, float logbase = 1f)\n        {\n            return DoSlider(position, dragZonePosition, id, value, left, right, formatString, power, logbase, EditorStyles.numberField, GUI.skin.horizontalSlider, GUI.skin.horizontalSliderThumb, null, GUI.skin.horizontalSliderThumbExtent);\n        }\n\n        internal static float DoSlider(Rect position, Rect dragZonePosition, int id, float value, float left, float right, string formatString, float textFieldMin, float textFieldMax, float power = 1f, float logbase = 1f)\n        {\n            return DoSlider(position, dragZonePosition, id, value, left, right, formatString, textFieldMin, textFieldMax, power, logbase, EditorStyles.numberField, GUI.skin.horizontalSlider, GUI.skin.horizontalSliderThumb, null, GUI.skin.horizontalSliderThumbExtent);\n        }\n\n        internal static float DoSlider(Rect position, Rect dragZonePosition, int id, float value, float left, float right, string formatString, GUIStyle textfieldStyle, float power = 1f, float logbase = 1f)\n        {\n            return DoSlider(position, dragZonePosition, id, value, left, right, formatString, power, logbase, textfieldStyle, GUI.skin.horizontalSlider, GUI.skin.horizontalSliderThumb, null, GUI.skin.horizontalSliderThumbExtent);\n        }\n\n        private static float DoSlider(Rect position, Rect dragZonePosition, int id, float value, float left, float right, string formatString, float power, float logbase, GUIStyle textfieldStyle, GUIStyle sliderStyle, GUIStyle thumbStyle, Texture2D sliderBackground, GUIStyle thumbStyleExtent)\n        {\n            return DoSlider(position, dragZonePosition, id, value, left, right, formatString, left, right, power, logbase, textfieldStyle, sliderStyle, thumbStyle, sliderBackground, thumbStyleExtent);\n        }\n\n        private static float DoSlider(\n            Rect position, Rect dragZonePosition, int id, float value, float sliderMin, float sliderMax, string formatString, float textFieldMin\n            , float textFieldMax, float power, float logbase, GUIStyle textfieldStyle, GUIStyle sliderStyle, GUIStyle thumbStyle, Texture2D sliderBackground, GUIStyle thumbStyleExtent\n        )\n        {\n            int sliderId = GUIUtility.GetControlID(s_SliderKnobHash, FocusType.Passive, position);\n            // Map some nonsensical edge cases to avoid breaking the UI.\n            // A slider with such a large range is basically useless, anyway.\n            sliderMin = Mathf.Clamp(sliderMin, float.MinValue, float.MaxValue);\n            sliderMax = Mathf.Clamp(sliderMax, float.MinValue, float.MaxValue);\n\n            float w = position.width;\n            if (w >= kSliderMinW + kSpacing + EditorGUIUtility.fieldWidth)\n            {\n                float sWidth = w - kSpacing - EditorGUIUtility.fieldWidth;\n                BeginChangeCheck();\n\n                // While the text field is not being edited, we want to share the keyboard focus with the slider, so we temporarily set it to have focus\n                if (GUIUtility.keyboardControl == id && !s_RecycledEditor.IsEditingControl(id))\n                {\n                    GUIUtility.keyboardControl = sliderId;\n                }\n\n                // Remap slider values according to power curve, if it's not identity\n                var remapLeft = sliderMin;\n                var remapRight = sliderMax;\n                var newSliderValue = value;\n                if (power != 1f)\n                {\n                    remapLeft = PowPreserveSign(sliderMin, 1f / power);\n                    remapRight = PowPreserveSign(sliderMax, 1f / power);\n                    newSliderValue = PowPreserveSign(value, 1f / power);\n                }\n                else if (logbase != 1f)\n                {\n                    remapLeft = Mathf.Log(sliderMin, logbase);\n                    remapRight = Mathf.Log(sliderMax, logbase);\n                    newSliderValue = Mathf.Log(value, logbase);\n                }\n\n                Rect sliderRect = new Rect(position.x, position.y, sWidth, position.height);\n\n                if (sliderBackground != null && Event.current.type == EventType.Repaint)\n                {\n                    var bgRect = sliderStyle.overflow.Add(sliderStyle.padding.Remove(sliderRect));\n                    Graphics.DrawTexture(bgRect, sliderBackground, new Rect(.5f / sliderBackground.width, .5f / sliderBackground.height, 1 - 1f / sliderBackground.width, 1 - 1f / sliderBackground.height), 0, 0, 0, 0, new Color(0.5f, 0.5f, 0.5f, 0.5f));\n                }\n\n                newSliderValue = GUI.Slider(sliderRect, newSliderValue, 0, remapLeft, remapRight, sliderStyle, showMixedValue ? GUI.skin.sliderMixed : thumbStyle, true, sliderId, showMixedValue ? GUI.skin.sliderMixed : thumbStyleExtent);\n                if (power != 1f)\n                {\n                    newSliderValue = PowPreserveSign(newSliderValue, power);\n                    newSliderValue = Mathf.Clamp(newSliderValue, Mathf.Min(sliderMin, sliderMax), Mathf.Max(sliderMin, sliderMax));\n                }\n                else if (logbase != 1f)\n                {\n                    newSliderValue = Mathf.Pow(logbase, newSliderValue);\n                }\n\n\n                // Do slider labels if present\n                if (EditorGUIUtility.sliderLabels.HasLabels())\n                {\n                    Color orgColor = GUI.color;\n                    GUI.color = GUI.color * new Color(1f, 1f, 1f, 0.5f);\n                    float labelHeight = Mathf.Max(EditorStyles.miniLabel.CalcHeight(EditorGUIUtility.sliderLabels.leftLabel, 0), EditorStyles.miniLabel.CalcHeight(EditorGUIUtility.sliderLabels.rightLabel, 0));\n                    Rect labelRect = new Rect(sliderRect.x, sliderRect.y + (sliderRect.height + thumbStyle.fixedHeight) / 2, sliderRect.width, labelHeight);\n                    DoTwoLabels(labelRect, EditorGUIUtility.sliderLabels.leftLabel, EditorGUIUtility.sliderLabels.rightLabel, EditorStyles.miniLabel);\n                    GUI.color = orgColor;\n                    EditorGUIUtility.sliderLabels.SetLabels(null, null);\n                }\n\n                // The keyboard control id that we want to retain is the \"main\" one that is used for the combined control, including the text field.\n                // Whenever the keyboardControl is the sliderId after calling the slider function, we set it back to this main id,\n                // regardless of whether it had keyboard focus before the function call, or just got it.\n                if (GUIUtility.keyboardControl == sliderId || GUIUtility.hotControl == sliderId)\n                {\n                    GUIUtility.keyboardControl = id;\n                }\n\n                if (GUIUtility.keyboardControl == id && Event.current.type == EventType.KeyDown && !s_RecycledEditor.IsEditingControl(id)\n                    && (Event.current.keyCode == KeyCode.LeftArrow || Event.current.keyCode == KeyCode.RightArrow))\n                {\n                    // Change by approximately 1/100 of entire range, or 1/10 if holding down shift\n                    // But round to nearest power of ten to get nice resulting numbers.\n                    float delta = MathUtils.GetClosestPowerOfTen(Mathf.Abs((sliderMax - sliderMin) * 0.01f));\n                    if (formatString == kIntFieldFormatString && delta < 1)\n                    {\n                        delta = 1;\n                    }\n                    if (Event.current.shift)\n                    {\n                        delta *= 10;\n                    }\n\n                    // Increment or decrement by just over half the delta.\n                    // This means that e.g. if delta is 1, incrementing from 1.0 will go to 2.0,\n                    // but incrementing from 0.9 is going to 1.0 rather than 2.0.\n                    // This feels more right since 1.0 is the \"next\" one.\n                    if (Event.current.keyCode == KeyCode.LeftArrow)\n                    {\n                        newSliderValue -= delta * 0.5001f;\n                    }\n                    else\n                    {\n                        newSliderValue += delta * 0.5001f;\n                    }\n\n                    // Now round to a multiple of our delta value so we get a round end result instead of just a round delta.\n                    newSliderValue = MathUtils.RoundToMultipleOf(newSliderValue, delta);\n                    GUI.changed = true;\n                    Event.current.Use();\n                }\n                if (EndChangeCheck())\n                {\n                    float valuesPerPixel = (sliderMax - sliderMin) / (sWidth - GUI.skin.horizontalSlider.padding.horizontal - GUI.skin.horizontalSliderThumb.fixedWidth);\n                    newSliderValue = MathUtils.RoundBasedOnMinimumDifference(newSliderValue, Mathf.Abs(valuesPerPixel));\n                    value = Mathf.Clamp(newSliderValue, Mathf.Min(sliderMin, sliderMax), Mathf.Max(sliderMin, sliderMax));\n                    if (s_RecycledEditor.IsEditingControl(id))\n                    {\n                        s_RecycledEditor.EndEditing();\n                    }\n                }\n\n                BeginChangeCheck();\n                var style = textfieldStyle ?? EditorStyles.numberField;\n                position.x += sWidth + kSpacing;\n                position.width = EditorGUIUtility.fieldWidth;\n\n                // Centers the textfield if it has a specified height\n                if (style.fixedHeight > 0)\n                {\n                    position.y += (position.height - style.fixedHeight) / 2;\n                }\n                var newTextFieldValue = DoFloatField(s_RecycledEditor, position,\n                    dragZonePosition, id, value, formatString, style, true);\n                if (EndChangeCheck())\n                {\n                    value = Mathf.Clamp(newTextFieldValue, Mathf.Min(textFieldMin, textFieldMax), Mathf.Max(textFieldMin, textFieldMax));\n                }\n            }\n            else\n            {\n                var style = textfieldStyle ?? EditorStyles.numberField;\n                w = Mathf.Min(EditorGUIUtility.fieldWidth, w);\n                position.x = position.xMax - w;\n                position.width = w;\n\n                // Centers the textfield if it has a specified height\n                if (style.fixedHeight > 0)\n                {\n                    position.y += (position.height - style.fixedHeight) / 2;\n                }\n                value = DoFloatField(s_RecycledEditor, position, dragZonePosition, id, value, formatString, style, true);\n                value = Mathf.Clamp(value, Mathf.Min(textFieldMin, textFieldMax), Mathf.Max(textFieldMin, textFieldMax));\n            }\n            return value;\n        }\n\n        [Obsolete(\"Switch the order of the first two parameters.\")]\n        public static void MinMaxSlider(GUIContent label, Rect position, ref float minValue, ref float maxValue, float minLimit, float maxLimit)\n        {\n            MinMaxSlider(position, label, ref minValue, ref maxValue, minLimit, maxLimit);\n        }\n\n        public static void MinMaxSlider(Rect position, string label, ref float minValue, ref float maxValue, float minLimit, float maxLimit)\n        {\n            MinMaxSlider(position, EditorGUIUtility.TempContent(label), ref minValue, ref maxValue, minLimit, maxLimit);\n        }\n\n        public static void MinMaxSlider(Rect position, GUIContent label, ref float minValue, ref float maxValue, float minLimit, float maxLimit)\n        {\n            int id = GUIUtility.GetControlID(s_MinMaxSliderHash, FocusType.Passive);\n            DoMinMaxSlider(PrefixLabel(position, id, label), id, ref minValue, ref maxValue, minLimit, maxLimit);\n        }\n\n        // Make a special slider the user can use to specify a range between a min and a max.\n        public static void MinMaxSlider(Rect position, ref float minValue, ref float maxValue, float minLimit, float maxLimit)\n        {\n            DoMinMaxSlider(IndentedRect(position), GUIUtility.GetControlID(s_MinMaxSliderHash, FocusType.Passive), ref minValue, ref maxValue, minLimit, maxLimit);\n        }\n\n        private static void DoMinMaxSlider(Rect position, int id, ref float minValue, ref float maxValue, float minLimit, float maxLimit)\n        {\n            float size = maxValue - minValue;\n            BeginChangeCheck();\n            EditorGUIExt.DoMinMaxSlider(position, id, ref minValue, ref size, minLimit, maxLimit, minLimit, maxLimit, GUI.skin.horizontalSlider, EditorStyles.minMaxHorizontalSliderThumb, true);\n            if (EndChangeCheck())\n            {\n                maxValue = minValue + size;\n            }\n        }\n\n        // The indent level of the field labels.\n        public static int indentLevel\n        {\n            get { return ms_IndentLevel; }\n            set { ms_IndentLevel = value; }\n        }\n\n        internal static float indent => indentLevel * kIndentPerLevel;\n\n        public class IndentLevelScope : GUI.Scope\n        {\n            readonly int m_IndentOffset;\n            public IndentLevelScope() : this(1) {}\n\n            public IndentLevelScope(int increment)\n            {\n                m_IndentOffset = increment;\n                indentLevel += m_IndentOffset;\n            }\n\n            protected override void CloseScope()\n            {\n                indentLevel -= m_IndentOffset;\n            }\n        }\n\n        // Make a generic popup selection field.\n        private static int PopupInternal(Rect position, GUIContent label, int selectedIndex, GUIContent[] displayedOptions, GUIStyle style)\n        {\n            return PopupInternal(position, label, selectedIndex, displayedOptions, null, style);\n        }\n\n        private static int PopupInternal(Rect position, GUIContent label, int selectedIndex, GUIContent[] displayedOptions, Func<int, bool> checkEnabled, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_PopupHash, FocusType.Keyboard, position);\n            if (label != null)\n                position = PrefixLabel(position, id, label);\n            return DoPopup(position, id, selectedIndex, displayedOptions, checkEnabled, style);\n        }\n\n        internal static int Popup(Rect position, GUIContent label, int selectedIndex, string[] displayedOptions, GUIStyle style)\n        {\n            return PopupInternal(position, label, selectedIndex, EditorGUIUtility.TempContent(displayedOptions), null, style);\n        }\n\n        internal static int Popup(Rect position, GUIContent label, int selectedIndex, string[] displayedOptions)\n        {\n            return Popup(position, label, selectedIndex, displayedOptions, EditorStyles.popup);\n        }\n\n        // Called from PropertyField\n\n        private static void Popup(Rect position, SerializedProperty property, GUIContent label)\n        {\n            BeginChangeCheck();\n            int idx = Popup(position, label, property.hasMultipleDifferentValues ? -1 : property.enumValueIndex, EnumNamesCache.GetEnumLocalizedGUIContents(property));\n            if (EndChangeCheck())\n            {\n                property.enumValueIndex = idx;\n            }\n        }\n\n        // Should be called directly - based on int properties.\n        internal static void Popup(Rect position, SerializedProperty property, GUIContent[] displayedOptions, GUIContent label)\n        {\n            label = BeginProperty(position, label, property);\n            BeginChangeCheck();\n            int idx = Popup(position, label, property.hasMultipleDifferentValues ? -1 : property.intValue, displayedOptions);\n            if (EndChangeCheck())\n            {\n                property.intValue = idx;\n            }\n            EndProperty();\n        }\n\n        private static Func<Enum, bool> s_CurrentCheckEnumEnabled;\n        private static EnumData s_CurrentEnumData;\n\n        private static bool CheckCurrentEnumTypeEnabled(int value)\n        {\n            return s_CurrentCheckEnumEnabled(s_CurrentEnumData.values[value]);\n        }\n\n        // Make an enum popup selection field.\n        private static Enum EnumPopupInternal(Rect position, GUIContent label, Enum selected, Func<Enum, bool> checkEnabled, bool includeObsolete, GUIStyle style)\n        {\n            return EnumPopupInternal(position, label, selected, selected.GetType(), checkEnabled, includeObsolete, style);\n        }\n\n        private static Enum EnumPopupInternal(Rect position, GUIContent label, Enum selected, Type enumType, Func<Enum, bool> checkEnabled, bool includeObsolete, GUIStyle style)\n        {\n            if (!enumType.IsEnum)\n            {\n                throw new ArgumentException(\"Parameter selected must be of type System.Enum\", nameof(selected));\n            }\n\n            var enumData = EnumDataUtility.GetCachedEnumData(enumType, !includeObsolete);\n            var i = showMixedValue ? -1 : Array.IndexOf(enumData.values, selected);\n            var options = EnumNamesCache.GetEnumTypeLocalizedGUIContents(enumType, enumData);\n\n            s_CurrentCheckEnumEnabled = checkEnabled;\n            s_CurrentEnumData = enumData;\n            i = PopupInternal(position, label, i, options, checkEnabled == null ? (Func<int, bool>)null : CheckCurrentEnumTypeEnabled, style);\n            s_CurrentCheckEnumEnabled = null;\n            return (i < 0 || i >= enumData.flagValues.Length) ? selected : enumData.values[i];\n        }\n\n        private static int EnumPopupInternal(Rect position, GUIContent label, int flagValue, Type enumType, Func<Enum, bool> checkEnabled, bool includeObsolete, GUIStyle style)\n        {\n            if (!enumType.IsEnum)\n            {\n                throw new ArgumentException(\"Parameter selected must be of type System.Enum\", nameof(enumType));\n            }\n\n            var enumData = EnumDataUtility.GetCachedEnumData(enumType, !includeObsolete);\n            var i = showMixedValue ? -1 : Array.IndexOf(enumData.flagValues, flagValue);\n            var options = EnumNamesCache.GetEnumTypeLocalizedGUIContents(enumType, enumData);\n\n            s_CurrentCheckEnumEnabled = checkEnabled;\n            s_CurrentEnumData = enumData;\n            i = PopupInternal(position, label, i, options, checkEnabled == null ? (Func<int, bool>)null : CheckCurrentEnumTypeEnabled, style);\n            s_CurrentCheckEnumEnabled = null;\n            return (i < 0 || i >= enumData.flagValues.Length) ? flagValue : enumData.flagValues[i];\n        }\n\n        private static int IntPopupInternal(Rect position, GUIContent label, int selectedValue, GUIContent[] displayedOptions, int[] optionValues, GUIStyle style)\n        {\n            // value --> index\n            int i;\n            if (showMixedValue)\n            {\n                i = -1;\n            }\n            else if (optionValues != null)\n            {\n                for (i = 0; (i < optionValues.Length) && (selectedValue != optionValues[i]); ++i)\n                {\n                }\n            }\n            // value = index\n            else\n            {\n                i = selectedValue;\n            }\n\n            i = PopupInternal(position, label, i, displayedOptions, style);\n\n            if (optionValues == null)\n            {\n                return i;\n            }\n            // index --> value\n            else if (i < 0 || i >= optionValues.Length)\n            {\n                return selectedValue;\n            }\n            else\n            {\n                return optionValues[i];\n            }\n        }\n\n        internal static void IntPopupInternal(Rect position, SerializedProperty property, GUIContent[] displayedOptions, int[] optionValues, GUIContent label)\n        {\n            label = BeginProperty(position, label, property);\n\n            BeginChangeCheck();\n            int newValue = IntPopupInternal(position, label, property.intValue, displayedOptions, optionValues, EditorStyles.popup);\n            if (EndChangeCheck())\n                property.intValue = newValue;\n\n            EndProperty();\n        }\n\n        internal static void SortingLayerField(Rect position, GUIContent label, SerializedProperty layerID, GUIStyle style, GUIStyle labelStyle)\n        {\n            using (new PropertyScope(position, null, layerID))\n            {\n                int id = GUIUtility.GetControlID(s_SortingLayerFieldHash, FocusType.Keyboard, position);\n                position = PrefixLabel(position, id, label, labelStyle);\n\n                Event evt = Event.current;\n                int selected = PopupCallbackInfo.GetSelectedValueForControl(id, -1);\n                if (selected != -1)\n                {\n                    int[] layerIDs = InternalEditorUtility.sortingLayerUniqueIDs;\n                    if (selected >= layerIDs.Length)\n                    {\n                        TagManagerInspector.ShowWithInitialExpansion(TagManagerInspector.InitialExpansionState.SortingLayers);\n                    }\n                    else\n                    {\n                        layerID.intValue = layerIDs[selected];\n                    }\n                }\n\n                if (evt.type == EventType.MouseDown && position.Contains(evt.mousePosition) || evt.MainActionKeyForControl(id))\n                {\n                    int i = 0;\n                    int[] layerIDs = InternalEditorUtility.sortingLayerUniqueIDs;\n                    string[] layerNames = InternalEditorUtility.sortingLayerNames;\n                    for (i = 0; i < layerIDs.Length; i++)\n                    {\n                        if (layerIDs[i] == layerID.intValue)\n                            break;\n                    }\n                    ArrayUtility.Add(ref layerNames, \"\");\n                    ArrayUtility.Add(ref layerNames, \"Add Sorting Layer...\");\n\n                    DoPopup(position, id, i, EditorGUIUtility.TempContent(layerNames), style);\n                }\n                else if (Event.current.type == EventType.Repaint)\n                {\n                    var layerName = layerID.hasMultipleDifferentValues ?\n                        mixedValueContent :\n                        EditorGUIUtility.TempContent(InternalEditorUtility.GetSortingLayerNameFromUniqueID(layerID.intValue));\n                    showMixedValue = layerID.hasMultipleDifferentValues;\n                    BeginHandleMixedValueContentColor();\n                    style.Draw(position, layerName, id, false);\n                    EndHandleMixedValueContentColor();\n                    showMixedValue = false;\n                }\n            }\n        }\n\n        // sealed partial class for storing state for popup menus so we can get the info back to OnGUI from the user selection\n        internal sealed class PopupCallbackInfo\n        {\n            // The global shared popup state\n            public static PopupCallbackInfo instance = null;\n\n            // Name of the command event sent from the popup menu to OnGUI when user has changed selection\n            internal const string kPopupMenuChangedMessage = \"PopupMenuChanged\";\n\n            // The control ID of the popup menu that is currently displayed.\n            // Used to pass selection changes back again...\n            private readonly int m_ControlID = 0;\n\n            // Which item was selected\n            private int m_SelectedIndex = 0;\n\n            // Which view should we send it to.\n            private readonly GUIView m_SourceView;\n\n            // *undoc*\n            public PopupCallbackInfo(int controlID)\n            {\n                m_ControlID = controlID;\n                m_SourceView = GUIView.current;\n            }\n\n            // *undoc*\n            public static int GetSelectedValueForControl(int controlID, int selected)\n            {\n                Event evt = Event.current;\n                if (evt.type == EventType.ExecuteCommand && evt.commandName == kPopupMenuChangedMessage)\n                {\n                    if (instance == null)\n                    {\n                        Debug.LogError(\"Popup menu has no instance\");\n                        return selected;\n                    }\n                    if (instance.m_ControlID == controlID)\n                    {\n                        GUI.changed = showMixedValue || selected != instance.m_SelectedIndex;\n                        selected = instance.m_SelectedIndex;\n                        instance = null;\n                        evt.Use();\n                    }\n                }\n                return selected;\n            }\n\n            internal void SetEnumValueDelegate(object userData, string[] options, int selected)\n            {\n                m_SelectedIndex = selected;\n                if (m_SourceView)\n                {\n                    m_SourceView.SendEvent(EditorGUIUtility.CommandEvent(kPopupMenuChangedMessage));\n                }\n            }\n        }\n\n        internal static int DoPopup(Rect position, int controlID, int selected, GUIContent[] popupValues, GUIStyle style)\n        {\n            return DoPopup(position, controlID, selected, popupValues, null, style);\n        }\n\n        internal static int DoPopup(Rect position, int controlID, int selected, GUIContent[] popupValues, Func<int, bool> checkEnabled, GUIStyle style)\n        {\n            selected = PopupCallbackInfo.GetSelectedValueForControl(controlID, selected);\n\n            GUIContent buttonContent;\n            if (showMixedValue)\n            {\n                buttonContent = s_MixedValueContent;\n            }\n            else if (selected < 0 || selected >= popupValues.Length)\n            {\n                buttonContent = GUIContent.none;\n            }\n            else\n            {\n                buttonContent = new GUIContent(popupValues[selected]);\n                buttonContent.text = EditorUtility.ParseMenuName(buttonContent.text);\n            }\n\n            Event evt = Event.current;\n            switch (evt.type)\n            {\n                case EventType.Repaint:\n                    // @TODO: Remove this hack and make all editor styles use the default font instead\n                    Font originalFont = style.font;\n                    if (originalFont && EditorGUIUtility.GetBoldDefaultFont() && originalFont == EditorStyles.miniFont)\n                    {\n                        style.font = EditorStyles.miniBoldFont;\n                    }\n\n                    BeginHandleMixedValueContentColor();\n                    style.Draw(position, buttonContent, controlID, false, position.Contains(Event.current.mousePosition));\n                    EndHandleMixedValueContentColor();\n\n                    style.font = originalFont;\n                    break;\n                case EventType.MouseDown:\n                    if (evt.button == 0 && position.Contains(evt.mousePosition))\n                    {\n                        if (Application.platform == RuntimePlatform.OSXEditor)\n                        {\n                            position.y = position.y - selected * 16 - 19;\n                        }\n\n                        PopupCallbackInfo.instance = new PopupCallbackInfo(controlID);\n                        EditorUtility.DisplayCustomMenu(position, popupValues, checkEnabled, showMixedValue ? -1 : selected, PopupCallbackInfo.instance.SetEnumValueDelegate, null, true);\n                        GUIUtility.keyboardControl = controlID;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (evt.MainActionKeyForControl(controlID))\n                    {\n                        if (Application.platform == RuntimePlatform.OSXEditor)\n                        {\n                            position.y = position.y - selected * 16 - 19;\n                        }\n\n                        PopupCallbackInfo.instance = new PopupCallbackInfo(controlID);\n                        EditorUtility.DisplayCustomMenu(position, popupValues, checkEnabled, showMixedValue ? -1 : selected, PopupCallbackInfo.instance.SetEnumValueDelegate, null);\n                        evt.Use();\n                    }\n                    break;\n            }\n            return selected;\n        }\n\n        internal static string TagFieldInternal(Rect position, string tag, GUIStyle style)\n        {\n            position = IndentedRect(position);\n\n            int id = GUIUtility.GetControlID(s_TagFieldHash, FocusType.Keyboard, position);\n\n            Event evt = Event.current;\n            int selected = PopupCallbackInfo.GetSelectedValueForControl(id, -1);\n            if (selected != -1)\n            {\n                string[] tagValues = InternalEditorUtility.tags;\n                if (selected >= tagValues.Length)\n                {\n                    TagManagerInspector.ShowWithInitialExpansion(TagManagerInspector.InitialExpansionState.Tags);\n                }\n                else\n                {\n                    tag = tagValues[selected];\n                }\n            }\n\n            if ((evt.type == EventType.MouseDown && position.Contains(evt.mousePosition)) || evt.MainActionKeyForControl(id))\n            {\n                int i = 0;\n                string[] tagValues = InternalEditorUtility.tags;\n                for (i = 0; i < tagValues.Length; i++)\n                {\n                    if (tagValues[i] == tag)\n                    {\n                        break;\n                    }\n                }\n                ArrayUtility.Add(ref tagValues, \"\");\n                ArrayUtility.Add(ref tagValues, L10n.Tr(\"Add Tag...\"));\n\n                DoPopup(position, id, i, EditorGUIUtility.TempContent(tagValues), style);\n                return tag;\n            }\n            else if (Event.current.type == EventType.Repaint)\n            {\n                BeginHandleMixedValueContentColor();\n                style.Draw(position, showMixedValue ? s_MixedValueContent : EditorGUIUtility.TempContent(tag), id, false);\n                EndHandleMixedValueContentColor();\n            }\n\n            return tag;\n        }\n\n        // Make a tag selection field.\n        internal static string TagFieldInternal(Rect position, GUIContent label, string tag, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_TagFieldHash, FocusType.Keyboard, position);\n            position = PrefixLabel(position, id, label);\n\n            Event evt = Event.current;\n            int selected = PopupCallbackInfo.GetSelectedValueForControl(id, -1);\n            if (selected != -1)\n            {\n                string[] tagValues = InternalEditorUtility.tags;\n                if (selected >= tagValues.Length)\n                {\n                    TagManagerInspector.ShowWithInitialExpansion(TagManagerInspector.InitialExpansionState.Tags);\n                }\n                else\n                {\n                    tag = tagValues[selected];\n                }\n            }\n\n            if (evt.type == EventType.MouseDown && position.Contains(evt.mousePosition) || evt.MainActionKeyForControl(id))\n            {\n                int i = 0;\n                string[] tagValues = InternalEditorUtility.tags;\n                for (i = 0; i < tagValues.Length; i++)\n                {\n                    if (tagValues[i] == tag)\n                    {\n                        break;\n                    }\n                }\n                ArrayUtility.Add(ref tagValues, \"\");\n                ArrayUtility.Add(ref tagValues, L10n.Tr(\"Add Tag...\"));\n\n                DoPopup(position, id, i, EditorGUIUtility.TempContent(tagValues), style);\n                return tag;\n            }\n            else if (Event.current.type == EventType.Repaint)\n            {\n                style.Draw(position, showMixedValue ? s_MixedValueContent : EditorGUIUtility.TempContent(tag),\n                    id, false, position.Contains(evt.mousePosition));\n            }\n\n            return tag;\n        }\n\n        // Make a layer selection field.\n        //\n        // this one is slow, but we only have one of them (in the game object inspector), so we should be ok.\n        // ARGH. This code is SO bad - I will refactor and repent after 2.5 - Nicholas\n        internal static int LayerFieldInternal(Rect position, GUIContent label, int layer, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_TagFieldHash, FocusType.Keyboard, position);\n            position = PrefixLabel(position, id, label);\n\n            Event evt = Event.current;\n            bool wasChangedBefore = GUI.changed;\n            int selected = PopupCallbackInfo.GetSelectedValueForControl(id, -1);\n            if (selected != -1)\n            {\n                if (selected >= InternalEditorUtility.layers.Length)\n                {\n                    TagManagerInspector.ShowWithInitialExpansion(TagManagerInspector.InitialExpansionState.Layers);\n                    GUI.changed = wasChangedBefore;\n                }\n                else\n                {\n                    int count = 0;\n                    for (int i = 0; i < 32; i++)\n                    {\n                        if (InternalEditorUtility.GetLayerName(i).Length != 0)\n                        {\n                            if (count == selected)\n                            {\n                                layer = i;\n                                break;\n                            }\n                            count++;\n                        }\n                    }\n                }\n            }\n\n            if ((evt.type == EventType.MouseDown && position.Contains(evt.mousePosition)) || evt.MainActionKeyForControl(id))\n            {\n                int count = 0;\n                for (int i = 0; i < 32; i++)\n                {\n                    if (InternalEditorUtility.GetLayerName(i).Length != 0)\n                    {\n                        if (i == layer)\n                        {\n                            break;\n                        }\n                        count++;\n                    }\n                }\n\n                string[] layers = InternalEditorUtility.GetLayersWithId();\n\n                ArrayUtility.Add(ref layers, \"\");\n                ArrayUtility.Add(ref layers, L10n.Tr(\"Add Layer...\"));\n\n                DoPopup(position, id, count, EditorGUIUtility.TempContent(layers), style);\n                Event.current.Use();\n\n                return layer;\n            }\n            else if (evt.type == EventType.Repaint)\n            {\n                var layerFieldContent = showMixedValue ? s_MixedValueContent : EditorGUIUtility.TempContent(InternalEditorUtility.GetLayerName(layer));\n                style.Draw(position, layerFieldContent, id, false, position.Contains(evt.mousePosition));\n            }\n\n            return layer;\n        }\n\n        internal static int MaskFieldInternal(Rect position, GUIContent label, int mask, string[] displayedOptions, GUIStyle style)\n        {\n            var id = GUIUtility.GetControlID(s_MaskField, FocusType.Keyboard, position);\n            position = PrefixLabel(position, id, label);\n            return MaskFieldGUI.DoMaskField(position, id, mask, displayedOptions, style);\n        }\n\n        internal static int MaskFieldInternal(Rect position, GUIContent label, int mask, string[] displayedOptions, int[] optionValues, GUIStyle style)\n        {\n            var id = GUIUtility.GetControlID(s_MaskField, FocusType.Keyboard, position);\n            position = PrefixLabel(position, id, label);\n            return MaskFieldGUI.DoMaskField(position, id, mask, displayedOptions, optionValues, style);\n        }\n\n        // Make a field for masks.\n        internal static int MaskFieldInternal(Rect position, int mask, string[] displayedOptions, GUIStyle style)\n        {\n            var id = GUIUtility.GetControlID(s_MaskField, FocusType.Keyboard, position);\n            return MaskFieldGUI.DoMaskField(IndentedRect(position), id, mask, displayedOptions, style);\n        }\n\n        public static Enum EnumFlagsField(Rect position, Enum enumValue)\n        {\n            return EnumFlagsField(position, enumValue, EditorStyles.popup);\n        }\n\n        public static Enum EnumFlagsField(Rect position, Enum enumValue, GUIStyle style)\n        {\n            return EnumFlagsField(position, GUIContent.none, enumValue, style);\n        }\n\n        public static Enum EnumFlagsField(Rect position, string label, Enum enumValue)\n        {\n            return EnumFlagsField(position, label, enumValue, EditorStyles.popup);\n        }\n\n        public static Enum EnumFlagsField(Rect position, string label, Enum enumValue, GUIStyle style)\n        {\n            return EnumFlagsField(position, EditorGUIUtility.TempContent(label), enumValue, style);\n        }\n\n        public static Enum EnumFlagsField(Rect position, GUIContent label, Enum enumValue)\n        {\n            return EnumFlagsField(position, label, enumValue, EditorStyles.popup);\n        }\n\n        public static Enum EnumFlagsField(Rect position, GUIContent label, Enum enumValue, GUIStyle style)\n        {\n            return EnumFlagsField(position, label, enumValue, false, style);\n        }\n\n        public static Enum EnumFlagsField(Rect position, GUIContent label, Enum enumValue, [DefaultValue(\"false\")] bool includeObsolete, [DefaultValue(\"null\")] GUIStyle style = null)\n        {\n            return EnumFlagsField(position, label, enumValue, includeObsolete, out _, out _, style ?? EditorStyles.popup);\n        }\n\n        // Internal version that also gives you back which flags were changed and what they were changed to.\n        internal static Enum EnumFlagsField(Rect position, GUIContent label, Enum enumValue, bool includeObsolete, out int changedFlags, out bool changedToValue, GUIStyle style)\n        {\n            return EnumFlagsField(position, label, enumValue, enumValue.GetType(), includeObsolete, out changedFlags, out changedToValue, style);\n        }\n\n        internal static Enum EnumFlagsField(Rect position, GUIContent label, Enum enumValue, Type enumType, bool includeObsolete, out int changedFlags, out bool changedToValue, GUIStyle style)\n        {\n            if (!enumType.IsEnum)\n                throw new ArgumentException(\"Parameter enumValue must be of type System.Enum\", nameof(enumValue));\n\n            var enumData = EnumDataUtility.GetCachedEnumData(enumType, !includeObsolete);\n            if (!enumData.serializable)\n                // this is the same message used in SerializedPropertyEnumHelper.cpp\n                throw new NotSupportedException(string.Format(\"Unsupported enum base type for {0}\", enumType.Name));\n\n            var id = GUIUtility.GetControlID(s_EnumFlagsField, FocusType.Keyboard, position);\n            position = PrefixLabel(position, id, label);\n\n            var flagsInt = EnumDataUtility.EnumFlagsToInt(enumData, enumValue);\n\n            BeginChangeCheck();\n            flagsInt = MaskFieldGUI.DoMaskField(position, id, flagsInt, enumData.displayNames, enumData.flagValues, style, out changedFlags, out changedToValue);\n            if (!EndChangeCheck())\n                return enumValue;\n\n            return EnumDataUtility.IntToEnumFlags(enumType, flagsInt);\n        }\n\n        internal static int EnumFlagsField(Rect position, GUIContent label, int enumValue, Type enumType, bool includeObsolete, GUIStyle style)\n        {\n            if (!enumType.IsEnum)\n                throw new ArgumentException(\"Specified enumType must be System.Enum\", nameof(enumType));\n\n            var enumData = EnumDataUtility.GetCachedEnumData(enumType, !includeObsolete);\n            if (!enumData.serializable)\n                // this is the same message used in SerializedPropertyEnumHelper.cpp\n                throw new NotSupportedException(string.Format(\"Unsupported enum base type for {0}\", enumType.Name));\n\n            var id = GUIUtility.GetControlID(s_EnumFlagsField, FocusType.Keyboard, position);\n            position = PrefixLabel(position, id, label);\n\n            int changedFlags;\n            bool changedToValue;\n            return MaskFieldGUI.DoMaskField(position, id, enumValue, enumData.displayNames, enumData.flagValues, style, out changedFlags, out changedToValue, enumType.GetEnumUnderlyingType());\n        }\n\n        public static void ObjectField(Rect position, SerializedProperty property)\n        {\n            ObjectField(position, property, null, null, EditorStyles.objectField);\n        }\n\n        public static void ObjectField(Rect position, SerializedProperty property, GUIContent label)\n        {\n            ObjectField(position, property, null, label, EditorStyles.objectField);\n        }\n\n        public static void ObjectField(Rect position, SerializedProperty property, Type objType)\n        {\n            ObjectField(position, property, objType, null, EditorStyles.objectField);\n        }\n\n        public static void ObjectField(Rect position, SerializedProperty property, Type objType, GUIContent label)\n        {\n            ObjectField(position, property, objType, label, EditorStyles.objectField);\n        }\n\n        // We don't expose SerializedProperty overloads with custom GUIStyle parameters according to our guidelines,\n        // but we have to provide it internally because ParticleSystem uses a style that's different from everything else.\n        internal static void ObjectField(Rect position, SerializedProperty property, Type objType, GUIContent label, GUIStyle style, ObjectFieldValidator validator = null)\n        {\n            label = BeginProperty(position, label, property);\n            ObjectFieldInternal(position, property, objType, label, style, validator);\n            EndProperty();\n        }\n\n        // This version doesn't do BeginProperty / EndProperty. It should not be called directly.\n        private static void ObjectFieldInternal(Rect position, SerializedProperty property, Type objType, GUIContent label, GUIStyle style, ObjectFieldValidator validator = null)\n        {\n            int id = GUIUtility.GetControlID(s_PPtrHash, FocusType.Keyboard, position);\n            position = PrefixLabel(position, id, label);\n\n            bool allowSceneObjects = false;\n            if (property != null)\n            {\n                // @TODO: Check all target objects.\n                Object objectBeingEdited = property.serializedObject.targetObject;\n\n                // Allow scene objects if the object being edited is NOT persistent\n                if (objectBeingEdited != null && !EditorUtility.IsPersistent(objectBeingEdited))\n                {\n                    allowSceneObjects = true;\n                }\n            }\n            DoObjectField(position, position, id, objType, property, validator, allowSceneObjects, style);\n        }\n\n        public static Object ObjectField(Rect position, Object obj, Type objType, Object targetBeingEdited)\n        {\n            int id = GUIUtility.GetControlID(s_ObjectFieldHash, FocusType.Keyboard, position);\n            return DoObjectField(IndentedRect(position), IndentedRect(position), id, obj, targetBeingEdited, objType, null, true);\n        }\n\n        public static Object ObjectField(Rect position, Object obj, Type objType, bool allowSceneObjects)\n        {\n            int id = GUIUtility.GetControlID(s_ObjectFieldHash, FocusType.Keyboard, position);\n            return DoObjectField(IndentedRect(position), IndentedRect(position), id, obj, null, objType, null, allowSceneObjects);\n        }\n\n        internal static Object ObjectField(Rect position, Object obj, Type objType, bool allowSceneObjects, GUIStyle style, GUIStyle buttonStyle)\n        {\n            int id = GUIUtility.GetControlID(s_ObjectFieldHash, FocusType.Keyboard, position);\n            return DoObjectField(IndentedRect(position), IndentedRect(position), id, obj, null, objType, null, null, null, allowSceneObjects, style, buttonStyle);\n        }\n\n        [Obsolete(\"Check the docs for the usage of the new parameter 'allowSceneObjects'.\")]\n        public static Object ObjectField(Rect position, Object obj, Type objType)\n        {\n            int id = GUIUtility.GetControlID(s_ObjectFieldHash, FocusType.Keyboard, position);\n            return DoObjectField(position, position, id, obj, null, objType, null, true);\n        }\n\n        public static Object ObjectField(Rect position, string label, Object obj, Type objType, Object targetBeingEdited)\n        {\n            return ObjectField(position, EditorGUIUtility.TempContent(label), obj, objType, targetBeingEdited);\n        }\n\n        public static Object ObjectField(Rect position, string label, Object obj, Type objType, bool allowSceneObjects)\n        {\n            return ObjectField(position, EditorGUIUtility.TempContent(label), obj, objType, allowSceneObjects);\n        }\n\n        [Obsolete(\"Check the docs for the usage of the new parameter 'allowSceneObjects'.\")]\n        public static Object ObjectField(Rect position, string label, Object obj, Type objType)\n        {\n            return ObjectField(position, EditorGUIUtility.TempContent(label), obj, objType, true);\n        }\n\n        static Rect GetObjectFieldThumbnailRect(Rect position, Type objType)\n        {\n            if (EditorGUIUtility.HasObjectThumbnail(objType) && position.height > kSingleLineHeight)\n            {\n                // Make object field with thumbnail quadratic and align to the right\n                float size = Mathf.Min(position.width, position.height);\n                position.height = size;\n                position.xMin = position.xMax - size;\n            }\n            return position;\n        }\n\n        // Make an object field. You can assign objects either by drag and drop objects or by selecting an object using the Object Picker.\n        public static Object ObjectField(Rect position, GUIContent label, Object obj, Type objType, Object targetBeingEdited)\n        {\n            int id = GUIUtility.GetControlID(s_ObjectFieldHash, FocusType.Keyboard, position);\n            position = PrefixLabel(position, id, label);\n            position = GetObjectFieldThumbnailRect(position, objType);\n            return DoObjectField(position, position, id, obj, targetBeingEdited, objType, null, true);\n        }\n\n        // Make an object field. You can assign objects either by drag and drop objects or by selecting an object using the Object Picker.\n        public static Object ObjectField(Rect position, GUIContent label, Object obj, Type objType, bool allowSceneObjects)\n        {\n            int id = GUIUtility.GetControlID(s_ObjectFieldHash, FocusType.Keyboard, position);\n            position = PrefixLabel(position, id, label);\n            position = GetObjectFieldThumbnailRect(position, objType);\n            return DoObjectField(position, position, id, obj, null, objType, null, allowSceneObjects);\n        }\n\n        internal static void GetRectsForMiniThumbnailField(Rect position, out Rect thumbRect, out Rect labelRect)\n        {\n            thumbRect = IndentedRect(position);\n            thumbRect.y -= (kObjectFieldMiniThumbnailHeight - kSingleLineHeight) * 0.5f; // center around EditorGUI.kSingleLineHeight\n            thumbRect.height = kObjectFieldMiniThumbnailHeight;\n            thumbRect.width = kObjectFieldMiniThumbnailWidth;\n\n            float labelStartX = thumbRect.x + 2 * kIndentPerLevel; // label aligns with indent levels for being able to have the following labels align with this label\n            labelRect = new Rect(labelStartX, position.y, thumbRect.x + EditorGUIUtility.labelWidth - labelStartX, position.height);\n        }\n\n        // Make a object field with the preview to the left and the label on the right thats fits on a single line height\n        internal static Object MiniThumbnailObjectField(Rect position, GUIContent label, Object obj, Type objType)\n        {\n            int id = GUIUtility.GetControlID(s_ObjectFieldHash, FocusType.Keyboard, position);\n\n            Rect thumbRect, labelRect;\n            GetRectsForMiniThumbnailField(position, out thumbRect, out labelRect);\n            HandlePrefixLabel(position, labelRect, label, id, EditorStyles.label);\n            return DoObjectField(thumbRect, thumbRect, id, obj, null, objType, null, false);\n        }\n\n        [Obsolete(\"Check the docs for the usage of the new parameter 'allowSceneObjects'.\")]\n        public static Object ObjectField(Rect position, GUIContent label, Object obj, Type objType)\n        {\n            return ObjectField(position, label, obj, objType, true);\n        }\n\n        internal static GameObject GetGameObjectFromObject(Object obj)\n        {\n            var go = obj as GameObject;\n            if (go == null && obj is Component)\n                go = ((Component)obj).gameObject;\n            return go;\n        }\n\n        internal static bool CheckForCrossSceneReferencing(Object obj1, Object obj2)\n        {\n            // If either object is not a component nor gameobject: cannot become a cross scene reference\n            GameObject go = GetGameObjectFromObject(obj1);\n            if (go == null)\n                return false;\n\n            GameObject go2 = GetGameObjectFromObject(obj2);\n            if (go2 == null)\n                return false;\n\n            // If either object is a prefab: cannot become a cross scene reference\n            if (EditorUtility.IsPersistent(go) || EditorUtility.IsPersistent(go2))\n                return false;\n\n            // If either scene is invalid: cannot become a cross scene reference\n            if (!go.scene.IsValid() || !go2.scene.IsValid())\n                return false;\n\n            return go.scene != go2.scene;\n        }\n\n        private static bool ValidateObjectReferenceValue(SerializedProperty property, Object obj, ObjectFieldValidatorOptions options)\n        {\n            if ((options & ObjectFieldValidatorOptions.ExactObjectTypeValidation) == ObjectFieldValidatorOptions.ExactObjectTypeValidation)\n                return property.ValidateObjectReferenceValueExact(obj);\n\n            return property.ValidateObjectReferenceValue(obj);\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal static Object ValidateObjectFieldAssignment(Object[] references, Type objType, SerializedProperty property, ObjectFieldValidatorOptions options)\n        {\n            if (references.Length > 0)\n            {\n                bool dragAssignment = DragAndDrop.objectReferences.Length > 0;\n                bool isTextureRef = (references[0] != null && references[0] is Texture2D);\n\n                if ((objType == typeof(Sprite)) && isTextureRef && dragAssignment)\n                {\n                    return SpriteUtility.TextureToSprite(references[0] as Texture2D);\n                }\n\n                if (property != null)\n                {\n                    if (references[0] != null && ValidateObjectReferenceValue(property, references[0], options))\n                    {\n                        if (EditorSceneManager.preventCrossSceneReferences && CheckForCrossSceneReferencing(references[0], property.serializedObject.targetObject))\n                            return null;\n\n                        if (objType != null)\n                        {\n                            if (references[0] is GameObject && typeof(Component).IsAssignableFrom(objType))\n                            {\n                                GameObject go = (GameObject)references[0];\n                                references = go.GetComponents(typeof(Component));\n                            }\n                            foreach (Object i in references)\n                            {\n                                if (i != null && objType.IsAssignableFrom(i.GetType()))\n                                {\n                                    return i;\n                                }\n                            }\n                        }\n                        else\n                        {\n                            return references[0];\n                        }\n                    }\n\n                    // If array, test against the target arrayElementType, if not test against the target Type.\n                    string testElementType = property.type;\n                    if (property.type == \"vector\")\n                        testElementType = property.arrayElementType;\n\n                    if ((testElementType == \"PPtr<Sprite>\" || testElementType == \"PPtr<$Sprite>\") && isTextureRef && dragAssignment)\n                    {\n                        return SpriteUtility.TextureToSprite(references[0] as Texture2D);\n                    }\n                }\n                else\n                {\n                    if (references[0] != null && references[0] is GameObject && typeof(Component).IsAssignableFrom(objType))\n                    {\n                        GameObject go = (GameObject)references[0];\n                        references = go.GetComponents(typeof(Component));\n                    }\n                    foreach (Object i in references)\n                    {\n                        if (i != null && objType.IsAssignableFrom(i.GetType()))\n                        {\n                            return i;\n                        }\n                    }\n                }\n            }\n            return null;\n        }\n\n        // Apply the indentLevel to a control rect\n        public static Rect IndentedRect(Rect source)\n        {\n            float x = indent;\n            return new Rect(source.x + x, source.y, source.width - x, source.height);\n        }\n\n        // Make an X & Y field for entering a [[Vector2]].\n        public static Vector2 Vector2Field(Rect position, string label, Vector2 value)\n        {\n            return Vector2Field(position, EditorGUIUtility.TempContent(label), value);\n        }\n\n        // Make an X & Y field for entering a [[Vector2]].\n        public static Vector2 Vector2Field(Rect position, GUIContent label, Vector2 value)\n        {\n            return Vector2Field(position, label, value, false);\n        }\n\n        internal static Vector2 Vector2Field(Rect position, GUIContent label, Vector2 value, bool setWideMode)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 2, 0, setWideMode);\n            position.height = kSingleLineHeight;\n            return Vector2Field(position, value);\n        }\n\n        // Make an X & Y field for entering a [[Vector2]].\n        private static Vector2 Vector2Field(Rect position, Vector2 value)\n        {\n            s_Vector2Floats[0] = value.x;\n            s_Vector2Floats[1] = value.y;\n            position.height = kSingleLineHeight;\n            BeginChangeCheck();\n            MultiFloatField(position, s_XYLabels, s_Vector2Floats);\n            if (EndChangeCheck())\n            {\n                value.x = s_Vector2Floats[0];\n                value.y = s_Vector2Floats[1];\n            }\n            return value;\n        }\n\n        // Make an X, Y & Z field for entering a [[Vector3]].\n        public static Vector3 Vector3Field(Rect position, string label, Vector3 value)\n        {\n            return Vector3Field(position, EditorGUIUtility.TempContent(label), value);\n        }\n\n        // Make an X, Y & Z field for entering a [[Vector3]].\n        public static Vector3 Vector3Field(Rect position, GUIContent label, Vector3 value)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 3);\n            position.height = kSingleLineHeight;\n            return Vector3Field(position, value);\n        }\n\n        // Make an X, Y & Z field for entering a [[Vector3]].\n        private static Vector3 Vector3Field(Rect position, Vector3 value)\n        {\n            s_Vector3Floats[0] = value.x;\n            s_Vector3Floats[1] = value.y;\n            s_Vector3Floats[2] = value.z;\n            position.height = kSingleLineHeight;\n            BeginChangeCheck();\n            MultiFloatField(position, s_XYZLabels, s_Vector3Floats);\n            if (EndChangeCheck())\n            {\n                value.x = s_Vector3Floats[0];\n                value.y = s_Vector3Floats[1];\n                value.z = s_Vector3Floats[2];\n            }\n            return value;\n        }\n\n        internal static Vector3 LinkedVector3Field(Rect position, GUIContent label, Vector3 value, ref bool proportionalScale)\n        {\n            int axisModified = 0;// use X as default modified axis\n            return LinkedVector3Field(position, label, GUIContent.none, value, ref proportionalScale, value, 0, ref axisModified);\n        }\n\n        // Make an X, Y & Z field for entering a [[Vector3]], with a \"lock\"\n        internal static Vector3 LinkedVector3Field(Rect position, GUIContent label,  GUIContent toggleContent, Vector3 value, ref bool proportionalScale, Vector3 initialScale, uint mixedValues, ref int axisModified, SerializedProperty property = null, SerializedProperty proportionalScaleProperty = null)\n        {\n            GUIContent copy = label;\n            Rect fullLabelRect = position;\n\n            BeginChangeCheck();\n\n            if (proportionalScaleProperty != null)\n            {\n                BeginPropertyInternal(fullLabelRect, label, proportionalScaleProperty);\n            }\n\n            var scalePropertyId = -1;\n            if (property != null)\n            {\n                label = BeginPropertyInternal(position, label, property);\n                scalePropertyId = GUIUtility.keyboardControl;\n            }\n\n            SerializedProperty copiedProperty = property == null ? property : property.Copy();\n            var toggle = EditorStyles.toggle.CalcSize(GUIContent.none);\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 3, toggle.x + kDefaultSpacing, false);\n            var toggleRect = position;\n            toggleRect.width = toggle.x;\n            float toggleOffset = toggleRect.width + kDefaultSpacing;\n            toggleRect.x -= toggleOffset;\n            toggle.x -= toggleOffset;\n            Styles.linkButton.alignment = TextAnchor.MiddleCenter;\n\n            // In case we have a background overlay, make sure Constrain proportions toggle won't be affected\n            Color currentColor = GUI.backgroundColor;\n            GUI.backgroundColor = Color.white;\n\n            bool previousProportionalScale = proportionalScale;\n            proportionalScale = GUI.Toggle(toggleRect, proportionalScale, toggleContent, Styles.linkButton);\n\n            if (proportionalScaleProperty != null && previousProportionalScale != proportionalScale)\n                proportionalScaleProperty.boolValue = proportionalScale;\n\n            GUI.backgroundColor = currentColor;\n\n            position.x += toggle.x + kDefaultSpacing;\n            position.width -= toggle.x + kDefaultSpacing;\n            position.height = kSingleLineHeight;\n\n            if (proportionalScaleProperty != null)\n            {\n                EndProperty();\n            }\n\n            if (property != null)\n            {\n                // Note: due to how both the scale + constrainScale property drawn and handled in a custom fashion, the lastcontrolId never correspond\n                // to the scaleProperty. Also s_PendingPropertyKeyboardHandling is nullifed by the constrainScale property.\n                // Make it work for now but I feel this whole system is super brittle.\n                // This will be hopefully fixed up when we use uitk to create these editors.\n\n                var lastId = EditorGUIUtility.s_LastControlID;\n                EditorGUIUtility.s_LastControlID = scalePropertyId;\n                s_PendingPropertyKeyboardHandling = property;\n                EndProperty();\n                EditorGUIUtility.s_LastControlID = lastId;\n            }\n\n            var newValue = LinkedVector3Field(position, value, proportionalScale, mixedValues, initialScale, ref axisModified, copiedProperty);\n\n            return newValue;\n        }\n\n        static Vector3 LinkedVector3Field(Rect position, Vector3 value, bool proportionalScale)\n        {\n            int axisModified = 0;// Use X as default modified axis\n            return LinkedVector3Field(position, value, proportionalScale, 0, value, ref axisModified);\n        }\n\n        // Make an X, Y & Z field for entering a [[Vector3]].\n        static Vector3 LinkedVector3Field(Rect position, Vector3 value, bool proportionalScale, uint mixedValues, Vector3 initialScale, ref int axisModified, SerializedProperty property = null)\n        {\n            Vector3 valueAfterChangeCheck = value;\n            s_Vector3Floats[0] = value.x;\n            s_Vector3Floats[1] = value.y;\n            s_Vector3Floats[2] = value.z;\n            position.height = kSingleLineHeight;\n            const float kPrefixWidthOffset = 3.65f;\n            LockingMultiFloatFieldInternal(position, proportionalScale, mixedValues, s_XYZLabels, s_Vector3Floats, new float[] {initialScale.x, initialScale.y, initialScale.z}, property, EditorGUI.CalcPrefixLabelWidth(s_XYZLabels[0]) + kPrefixWidthOffset);\n            if (EndChangeCheck())\n            {\n                valueAfterChangeCheck.x = s_Vector3Floats[0];\n                valueAfterChangeCheck.y = s_Vector3Floats[1];\n                valueAfterChangeCheck.z = s_Vector3Floats[2];\n            }\n\n            return proportionalScale? ConstrainProportionsTransformScale.DoScaleProportions(valueAfterChangeCheck, value, ConstrainProportionsTransformScale.m_IsAnimationPreview? value : initialScale, ref axisModified) : valueAfterChangeCheck;\n        }\n\n        // Make an X, Y field - not public (use PropertyField instead)\n        private static void Vector2Field(Rect position, SerializedProperty property, GUIContent label)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 2);\n            position.height = kSingleLineHeight;\n            SerializedProperty cur = property.Copy();\n            cur.Next(true);\n            MultiPropertyFieldInternal(position, s_XYLabels, cur, PropertyVisibility.All);\n        }\n\n        // Make an X, Y and Z field - not public (use PropertyField instead)\n        private static void Vector3Field(Rect position, SerializedProperty property, GUIContent label)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 3);\n            position.height = kSingleLineHeight;\n            SerializedProperty cur = property.Copy();\n            cur.Next(true);\n            MultiPropertyFieldInternal(position, s_XYZLabels, cur, PropertyVisibility.All);\n        }\n\n        // Make an X, Y and Z field for Quaternions - not public (use PropertyField instead)\n        private static void QuaternionEulerField(Rect position, SerializedProperty property, GUIContent label)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 3);\n            position.height = kSingleLineHeight;\n            Vector3 eulerValue = property.quaternionValue.eulerAngles;\n            s_Vector3Floats[0] = Mathf.Floor(eulerValue.x / kQuaternionFloatPrecision) * kQuaternionFloatPrecision;\n            s_Vector3Floats[1] = Mathf.Floor(eulerValue.y / kQuaternionFloatPrecision) * kQuaternionFloatPrecision;\n            s_Vector3Floats[2] = Mathf.Floor(eulerValue.z / kQuaternionFloatPrecision) * kQuaternionFloatPrecision;\n            BeginChangeCheck();\n            MultiFloatFieldInternal(position, s_XYZLabels, s_Vector3Floats);\n            if (EndChangeCheck())\n            {\n                property.quaternionValue = Quaternion.Euler(s_Vector3Floats[0], s_Vector3Floats[1], s_Vector3Floats[2]);\n            }\n        }\n\n        // Make an X, Y, Z and W field - not public (use PropertyField instead)\n        static void Vector4Field(Rect position, SerializedProperty property, GUIContent label)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 4);\n            position.height = kSingleLineHeight;\n            SerializedProperty cur = property.Copy();\n            cur.Next(true);\n            MultiPropertyFieldInternal(position, s_XYZWLabels, cur, PropertyVisibility.All);\n        }\n\n        // Make an X, Y, Z & W field for entering a [[Vector4]].\n        public static Vector4 Vector4Field(Rect position, string label, Vector4 value)\n        {\n            return Vector4Field(position, EditorGUIUtility.TempContent(label), value);\n        }\n\n        // Make an X, Y, Z & W field for entering a [[Vector4]].\n        public static Vector4 Vector4Field(Rect position, GUIContent label, Vector4 value)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 4);\n            position.height = kSingleLineHeight;\n            return Vector4FieldNoIndent(position, value);\n        }\n\n        private static Vector4 Vector4FieldNoIndent(Rect position, Vector4 value)\n        {\n            s_Vector4Floats[0] = value.x;\n            s_Vector4Floats[1] = value.y;\n            s_Vector4Floats[2] = value.z;\n            s_Vector4Floats[3] = value.w;\n            position.height = kSingleLineHeight;\n            BeginChangeCheck();\n            MultiFloatField(position, s_XYZWLabels, s_Vector4Floats);\n            if (EndChangeCheck())\n            {\n                value.x = s_Vector4Floats[0];\n                value.y = s_Vector4Floats[1];\n                value.z = s_Vector4Floats[2];\n                value.w = s_Vector4Floats[3];\n            }\n            return value;\n        }\n\n        // Make an X & Y int field for entering a [[Vector2Int]].\n        public static Vector2Int Vector2IntField(Rect position, string label, Vector2Int value)\n        {\n            return Vector2IntField(position, EditorGUIUtility.TempContent(label), value);\n        }\n\n        // Make an X & Y int field for entering a [[Vector2Int]].\n        public static Vector2Int Vector2IntField(Rect position, GUIContent label, Vector2Int value)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 2);\n            position.height = kSingleLineHeight;\n            return Vector2IntField(position, value);\n        }\n\n        // Make an X & Y int field for entering a [[Vector2Int]].\n        private static Vector2Int Vector2IntField(Rect position, Vector2Int value)\n        {\n            s_Vector2Ints[0] = value.x;\n            s_Vector2Ints[1] = value.y;\n            position.height = kSingleLineHeight;\n            BeginChangeCheck();\n            MultiIntField(position, s_XYLabels, s_Vector2Ints);\n            if (EndChangeCheck())\n            {\n                value.x = s_Vector2Ints[0];\n                value.y = s_Vector2Ints[1];\n            }\n            return value;\n        }\n\n        // Make an X, Y int field - not public (use PropertyField instead)\n        private static void Vector2IntField(Rect position, SerializedProperty property, GUIContent label)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 2);\n            position.height = kSingleLineHeight;\n            SerializedProperty cur = property.Copy();\n            cur.Next(true);\n            MultiPropertyFieldInternal(position, s_XYLabels, cur, PropertyVisibility.All);\n        }\n\n        // Make an X, Y and Z int field for entering a [[Vector3Int]].\n        public static Vector3Int Vector3IntField(Rect position, string label, Vector3Int value)\n        {\n            return Vector3IntField(position, EditorGUIUtility.TempContent(label), value);\n        }\n\n        // Make an X, Y and Z int field for entering a [[Vector3Int]].\n        public static Vector3Int Vector3IntField(Rect position, GUIContent label, Vector3Int value)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 3);\n            position.height = kSingleLineHeight;\n            return Vector3IntField(position, value);\n        }\n\n        // Make an X, Y and Z int field for entering a [[Vector3Int]].\n        private static Vector3Int Vector3IntField(Rect position, Vector3Int value)\n        {\n            s_Vector3Ints[0] = value.x;\n            s_Vector3Ints[1] = value.y;\n            s_Vector3Ints[2] = value.z;\n            position.height = kSingleLineHeight;\n            BeginChangeCheck();\n            MultiIntField(position, s_XYZLabels, s_Vector3Ints);\n            if (EndChangeCheck())\n            {\n                value.x = s_Vector3Ints[0];\n                value.y = s_Vector3Ints[1];\n                value.z = s_Vector3Ints[2];\n            }\n            return value;\n        }\n\n        // Make an X, Y and Z int field - not public (use PropertyField instead)\n        private static void Vector3IntField(Rect position, SerializedProperty property, GUIContent label)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 3);\n            position.height = kSingleLineHeight;\n            SerializedProperty cur = property.Copy();\n            cur.Next(true);\n            MultiPropertyFieldInternal(position, s_XYZLabels, cur, PropertyVisibility.All);\n        }\n\n        public static Rect RectField(Rect position, Rect value)\n        {\n            return RectFieldNoIndent(IndentedRect(position), value);\n        }\n\n        private static Rect RectFieldNoIndent(Rect position, Rect value)\n        {\n            position.height = kSingleLineHeight;\n            s_Vector2Floats[0] = value.x;\n            s_Vector2Floats[1] = value.y;\n            BeginChangeCheck();\n            // Right align the text\n            var oldAlignment = EditorStyles.label.alignment;\n            EditorStyles.label.alignment = TextAnchor.MiddleLeft;\n\n            MultiFloatFieldInternal(position, s_XYLabels, s_Vector2Floats, kMiniLabelW);\n            if (EndChangeCheck())\n            {\n                value.x = s_Vector2Floats[0];\n                value.y = s_Vector2Floats[1];\n            }\n            position.y += kSingleLineHeight + kVerticalSpacingMultiField;\n            s_Vector2Floats[0] = value.width;\n            s_Vector2Floats[1] = value.height;\n            BeginChangeCheck();\n            MultiFloatFieldInternal(position, s_WHLabels, s_Vector2Floats, kMiniLabelW);\n            if (EndChangeCheck())\n            {\n                value.width = s_Vector2Floats[0];\n                value.height = s_Vector2Floats[1];\n            }\n            EditorStyles.label.alignment = oldAlignment;\n            return value;\n        }\n\n        public static Rect RectField(Rect position, string label, Rect value)\n        {\n            return RectField(position, EditorGUIUtility.TempContent(label), value);\n        }\n\n        // Make an X, Y, W & H field for entering a [[Rect]].\n        public static Rect RectField(Rect position, GUIContent label, Rect value)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 2);\n            return RectFieldNoIndent(position, value);\n        }\n\n        // Make an X, Y, W & H for Rect using SerializedProperty (not public)\n        private static void RectField(Rect position, SerializedProperty property, GUIContent label)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 2);\n            position.height = kSingleLineHeight;\n\n            SerializedProperty cur = property.Copy();\n            cur.Next(true);\n\n            // Right align the text\n            var oldAlignment = EditorStyles.label.alignment;\n            EditorStyles.label.alignment = TextAnchor.MiddleLeft;\n            MultiPropertyFieldInternal(position, s_XYLabels, cur, PropertyVisibility.All, null, kMiniLabelW);\n            position.y += kSingleLineHeight + kVerticalSpacingMultiField;\n\n            MultiPropertyFieldInternal(position, s_WHLabels, cur, PropertyVisibility.All, null, kMiniLabelW);\n            EditorStyles.label.alignment = oldAlignment;\n        }\n\n        public static RectInt RectIntField(Rect position, RectInt value)\n        {\n            position.height = kSingleLineHeight;\n            s_Vector2Ints[0] = value.x;\n            s_Vector2Ints[1] = value.y;\n            BeginChangeCheck();\n            MultiIntField(position, s_XYLabels, s_Vector2Ints);\n            if (EndChangeCheck())\n            {\n                value.x = s_Vector2Ints[0];\n                value.y = s_Vector2Ints[1];\n            }\n            position.y += kSingleLineHeight + 2;\n            s_Vector2Ints[0] = value.width;\n            s_Vector2Ints[1] = value.height;\n            BeginChangeCheck();\n            MultiIntField(position, s_WHLabels, s_Vector2Ints);\n            if (EndChangeCheck())\n            {\n                value.width = s_Vector2Ints[0];\n                value.height = s_Vector2Ints[1];\n            }\n            return value;\n        }\n\n        public static RectInt RectIntField(Rect position, string label, RectInt value)\n        {\n            return RectIntField(position, EditorGUIUtility.TempContent(label), value);\n        }\n\n        // Make an X, Y, W & H field for entering a [[Rect]].\n        public static RectInt RectIntField(Rect position, GUIContent label, RectInt value)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 2);\n            position.height = kSingleLineHeight;\n            return RectIntField(position, value);\n        }\n\n        // Make an X, Y, W & H for RectInt using SerializedProperty (not public)\n        private static void RectIntField(Rect position, SerializedProperty property, GUIContent label)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 2);\n            position.height = kSingleLineHeight;\n\n            SerializedProperty cur = property.Copy();\n            cur.Next(true);\n            MultiPropertyFieldInternal(position, s_XYLabels, cur, PropertyVisibility.All, null, kMiniLabelW);\n            position.y += kSingleLineHeight + kVerticalSpacingMultiField;\n\n            MultiPropertyFieldInternal(position, s_WHLabels, cur, PropertyVisibility.All, null, kMiniLabelW);\n        }\n\n        private static Rect DrawBoundsFieldLabelsAndAdjustPositionForValues(Rect position, bool drawOutside, GUIContent firstContent, GUIContent secondContent)\n        {\n            const float kBoundsTextWidth = 53;\n\n            if (drawOutside)\n                position.xMin -= kBoundsTextWidth;\n\n            GUI.Label(position, firstContent, EditorStyles.label);\n            position.y += kSingleLineHeight + kVerticalSpacingMultiField;\n            GUI.Label(position, secondContent, EditorStyles.label);\n\n            position.y -= kSingleLineHeight + kVerticalSpacingMultiField;\n            position.xMin += kBoundsTextWidth;\n\n            return position;\n        }\n\n        public static Bounds BoundsField(Rect position, Bounds value)\n        {\n            return BoundsFieldNoIndent(IndentedRect(position), value, false);\n        }\n\n        public static Bounds BoundsField(Rect position, string label, Bounds value)\n        {\n            return BoundsField(position, EditorGUIUtility.TempContent(label), value);\n        }\n\n        // Make Center & Extents field for entering a [[Bounds]].\n        public static Bounds BoundsField(Rect position, GUIContent label, Bounds value)\n        {\n            if (!LabelHasContent(label))\n                return BoundsFieldNoIndent(IndentedRect(position), value, false);\n\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 3);\n            if (EditorGUIUtility.wideMode)\n                position.y += kSingleLineHeight + kVerticalSpacingMultiField;\n\n            return BoundsFieldNoIndent(position, value, true);\n        }\n\n        private static Bounds BoundsFieldNoIndent(Rect position, Bounds value, bool isBelowLabel)\n        {\n            position.height = kSingleLineHeight;\n            position = DrawBoundsFieldLabelsAndAdjustPositionForValues(position, EditorGUIUtility.wideMode && isBelowLabel, s_CenterLabel, s_ExtentLabel);\n\n            value.center = Vector3Field(position, value.center);\n            position.y += kSingleLineHeight + kVerticalSpacingMultiField;\n            value.extents = Vector3Field(position, value.extents);\n            return value;\n        }\n\n        // private (use PropertyField)\n        private static void BoundsField(Rect position, SerializedProperty property, GUIContent label)\n        {\n            bool hasLabel = LabelHasContent(label);\n            if (hasLabel)\n            {\n                int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n                position = MultiFieldPrefixLabel(position, id, label, 3);\n                if (EditorGUIUtility.wideMode)\n                    position.y += kSingleLineHeight + kVerticalSpacingMultiField;\n            }\n            position.height = kSingleLineHeight;\n            position = DrawBoundsFieldLabelsAndAdjustPositionForValues(position, EditorGUIUtility.wideMode && hasLabel, s_CenterLabel, s_ExtentLabel);\n\n            SerializedProperty cur = property.Copy();\n            cur.Next(true);\n            cur.Next(true);\n            MultiPropertyFieldInternal(position, s_XYZLabels, cur, PropertyVisibility.All, null, kMiniLabelW);\n            cur.Next(true);\n            position.y += kSingleLineHeight + kVerticalSpacingMultiField;\n            MultiPropertyFieldInternal(position, s_XYZLabels, cur, PropertyVisibility.All, null, kMiniLabelW);\n        }\n\n        public static BoundsInt BoundsIntField(Rect position, BoundsInt value)\n        {\n            return BoundsIntFieldNoIndent(IndentedRect(position), value, false);\n        }\n\n        public static BoundsInt BoundsIntField(Rect position, string label, BoundsInt value)\n        {\n            return BoundsIntField(position, EditorGUIUtility.TempContent(label), value);\n        }\n\n        public static BoundsInt BoundsIntField(Rect position, GUIContent label, BoundsInt value)\n        {\n            if (!LabelHasContent(label))\n                return BoundsIntFieldNoIndent(IndentedRect(position), value, false);\n\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, 3);\n            if (EditorGUIUtility.wideMode)\n                position.y += kSingleLineHeight + kVerticalSpacingMultiField;\n\n            return BoundsIntFieldNoIndent(position, value, true);\n        }\n\n        private static BoundsInt BoundsIntFieldNoIndent(Rect position, BoundsInt value, bool isBelowLabel)\n        {\n            position.height = kSingleLineHeight;\n            position = DrawBoundsFieldLabelsAndAdjustPositionForValues(position, EditorGUIUtility.wideMode && isBelowLabel, s_PositionLabel, s_SizeLabel);\n\n            value.position = Vector3IntField(position, value.position);\n            position.y += kSingleLineHeight + kVerticalSpacingMultiField;\n            value.size = Vector3IntField(position, value.size);\n            return value;\n        }\n\n        // private (use PropertyField)\n        private static void BoundsIntField(Rect position, SerializedProperty property, GUIContent label)\n        {\n            bool hasLabel = LabelHasContent(label);\n            if (hasLabel)\n            {\n                int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n                position = MultiFieldPrefixLabel(position, id, label, 3);\n                if (EditorGUIUtility.wideMode)\n                    position.y += kSingleLineHeight + kVerticalSpacingMultiField;\n            }\n            position.height = kSingleLineHeight;\n            position = DrawBoundsFieldLabelsAndAdjustPositionForValues(position, EditorGUIUtility.wideMode && hasLabel, s_PositionLabel, s_SizeLabel);\n\n            SerializedProperty cur = property.Copy();\n            cur.Next(true);\n            cur.Next(true);\n            MultiPropertyFieldInternal(position, s_XYZLabels, cur, PropertyVisibility.All);\n            cur.Next(true);\n            position.y += kSingleLineHeight + kVerticalSpacingMultiField;\n            MultiPropertyFieldInternal(position, s_XYZLabels, cur, PropertyVisibility.All);\n        }\n\n        public static void MultiFloatField(Rect position, GUIContent label, GUIContent[] subLabels, float[] values)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, subLabels.Length);\n            position.height = kSingleLineHeight;\n            MultiFloatField(position, subLabels, values);\n        }\n\n        public static void MultiFloatField(Rect position, GUIContent[] subLabels, float[] values)\n        {\n            MultiFloatFieldInternal(position, subLabels, values);\n        }\n\n        internal static float GetLabelWidth(GUIContent Label, float prefixLabelWidth = -1)\n        {\n            float LabelWidth = EditorGUI.CalcPrefixLabelWidth(Label);\n            if (LabelWidth > kMiniLabelW)\n                return prefixLabelWidth > 0 ? prefixLabelWidth : LabelWidth;\n            else\n                return prefixLabelWidth > 0 ? prefixLabelWidth : kMiniLabelW;\n        }\n\n        internal static void MultiFloatFieldInternal(Rect position, GUIContent[] subLabels, float[] values, float prefixLabelWidth = -1)\n        {\n            int eCount = values.Length;\n            float w = (position.width - (eCount - 1) * kSpacingSubLabel) / eCount;\n            Rect nr = new Rect(position) {width = w};\n            float t = EditorGUIUtility.labelWidth;\n            int l = indentLevel;\n            indentLevel = 0;\n            for (int i = 0; i < values.Length; i++)\n            {\n                EditorGUIUtility.labelWidth = GetLabelWidth(subLabels[i], prefixLabelWidth);\n                values[i] = FloatField(nr, subLabels[i], values[i]);\n                nr.x += w + kSpacingSubLabel;\n            }\n            EditorGUIUtility.labelWidth = t;\n            indentLevel = l;\n        }\n\n        static void LockingMultiFloatFieldInternal(Rect position, bool locked, GUIContent[] subLabels, float[] values, float prefixLabelWidth = -1)\n        {\n            LockingMultiFloatFieldInternal(position, locked, 0, subLabels, values, null, null, prefixLabelWidth);\n        }\n\n        static void LockingMultiFloatFieldInternal(Rect position, bool locked, uint mixedValues, GUIContent[] subLabels, float[] values, float[] initialValues = null, SerializedProperty property = null, float prefixLabelWidth = -1)\n        {\n            int eCount = values.Length;\n            float w = (position.width - (eCount - 1) * EditorGUI.kSpacingSubLabel) / eCount;\n            Rect nr = new Rect(position) {width = w};\n            float t = EditorGUIUtility.labelWidth;\n            int l = EditorGUI.indentLevel;\n            EditorGUI.indentLevel = 0;\n            var guiEnabledState = GUI.enabled;\n            bool hasMixedValues = mixedValues != 0;\n            uint multiselectionLock = ConstrainProportionsTransformScale.GetMultiSelectionLockedFields(property?.serializedObject?.targetObjects);\n\n            if (initialValues == null || ConstrainProportionsTransformScale.m_IsAnimationPreview)\n                initialValues = values;\n\n            // In animation preview mode we scale using last valid value instead of initialScale, make sure we won't lock fields on Vector3.zero\n            bool forceEnableFields = ConstrainProportionsTransformScale.ShouldForceEnablePropertyFields(initialValues);\n\n            bool mixedValueState = EditorGUI.showMixedValue;\n\n            for (int i = 0; i < initialValues.Length; i++)\n            {\n                if (property != null)\n                    property.Next(true);\n                EditorGUIUtility.labelWidth = prefixLabelWidth > 0 ? prefixLabelWidth : EditorGUI.CalcPrefixLabelWidth(subLabels[i]);\n\n                if (guiEnabledState)\n                {\n                    if (locked)\n                    {\n                        // If initial field value is 0, it must be locked not to break proportions\n                        GUI.enabled = forceEnableFields || !Mathf.Approximately(initialValues[i], 0) && (property != null && property.serializedObject.targetObjectsCount > 1 ? !ConstrainProportionsTransformScale.IsBit(multiselectionLock, i) : true);\n                    }\n                    else\n                    {\n                        GUI.enabled = true;\n                    }\n                }\n\n                if (hasMixedValues)\n                    EditorGUI.showMixedValue = ConstrainProportionsTransformScale.IsBit(mixedValues, i);\n\n                if (property != null)\n                {\n                    EditorGUI.PropertyField(nr, property, subLabels[i]);\n                    values[i] = property.floatValue;\n                }\n                else\n                {\n                    values[i] = EditorGUI.FloatField(nr, subLabels[i], values[i]);\n                }\n\n                if (hasMixedValues)\n                    EditorGUI.showMixedValue = false;\n\n                nr.x += w + EditorGUI.kSpacingSubLabel;\n            }\n            GUI.enabled = guiEnabledState;\n            EditorGUI.showMixedValue = mixedValueState;\n            EditorGUIUtility.labelWidth = t;\n            EditorGUI.indentLevel = l;\n        }\n\n        public static void MultiIntField(Rect position, GUIContent[] subLabels, int[] values)\n        {\n            MultiIntFieldInternal(position, subLabels, values);\n        }\n\n        internal static void MultiIntFieldInternal(Rect position, GUIContent[] subLabels, int[] values)\n        {\n            int eCount = values.Length;\n            float w = (position.width - (eCount - 1) * kSpacingSubLabel) / eCount;\n            Rect nr = new Rect(position) {width = w};\n            float t = EditorGUIUtility.labelWidth;\n            int l = indentLevel;\n            indentLevel = 0;\n            for (int i = 0; i < values.Length; i++)\n            {\n                EditorGUIUtility.labelWidth = GetLabelWidth(subLabels[i]);\n\n                values[i] = IntField(nr, subLabels[i], values[i]);\n                nr.x += w + kSpacingSubLabel;\n            }\n            EditorGUIUtility.labelWidth = t;\n            indentLevel = l;\n        }\n\n        public static void MultiPropertyField(Rect position, GUIContent[] subLabels, SerializedProperty valuesIterator, GUIContent label)\n        {\n            MultiPropertyField(position, subLabels, valuesIterator, label, PropertyVisibility.OnlyVisible);\n        }\n\n        public static void MultiPropertyField(Rect position, GUIContent[] subLabels, SerializedProperty valuesIterator, GUIContent label, PropertyVisibility visibility)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = MultiFieldPrefixLabel(position, id, label, subLabels.Length);\n            position.height = kSingleLineHeight;\n            MultiPropertyField(position, subLabels, valuesIterator, visibility);\n        }\n\n        public static void MultiPropertyField(Rect position, GUIContent[] subLabels, SerializedProperty valuesIterator)\n        {\n            MultiPropertyField(position, subLabels, valuesIterator, PropertyVisibility.OnlyVisible);\n        }\n\n        public static void MultiPropertyField(Rect position, GUIContent[] subLabels, SerializedProperty valuesIterator, PropertyVisibility visibility)\n        {\n            MultiPropertyFieldInternal(position, subLabels, valuesIterator, visibility);\n        }\n\n        public enum PropertyVisibility\n        {\n            All,\n            OnlyVisible\n        }\n\n        internal static void MultiPropertyFieldInternal(Rect position, GUIContent[] subLabels, SerializedProperty valuesIterator, PropertyVisibility visibility, bool[] disabledMask = null, float prefixLabelWidth = -1)\n        {\n            int eCount = subLabels.Length;\n            float w = (position.width - (eCount - 1) * kSpacingSubLabel) / eCount;\n            Rect nr = new Rect(position) {width = w};\n            float t = EditorGUIUtility.labelWidth;\n            int l = indentLevel;\n            indentLevel = 0;\n            for (int i = 0; i < subLabels.Length; i++)\n            {\n                EditorGUIUtility.labelWidth = GetLabelWidth(subLabels[i], prefixLabelWidth);\n\n                if (disabledMask != null)\n                    BeginDisabled(disabledMask[i]);\n                PropertyField(nr, valuesIterator, subLabels[i]);\n                if (disabledMask != null)\n                    EndDisabled();\n                nr.x += w + kSpacingSubLabel;\n\n                switch (visibility)\n                {\n                    case PropertyVisibility.All:\n                        valuesIterator.Next(false);\n                        break;\n\n                    case PropertyVisibility.OnlyVisible:\n                        valuesIterator.NextVisible(false);\n                        break;\n                }\n            }\n            EditorGUIUtility.labelWidth = t;\n            indentLevel = l;\n        }\n\n        // Make a property field that look like a multi property field (but is made up of individual properties)\n        internal static void PropertiesField(Rect position, GUIContent label, SerializedProperty[] properties, GUIContent[] propertyLabels, float propertyLabelsWidth)\n        {\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            Rect fieldPosition = PrefixLabel(position, id, label);\n            fieldPosition.height = kSingleLineHeight;\n\n            float oldLabelWidth = EditorGUIUtility.labelWidth;\n            int oldIndentLevel = indentLevel;\n\n            EditorGUIUtility.labelWidth = propertyLabelsWidth;\n            indentLevel = 0;\n            for (int i = 0; i < properties.Length; i++)\n            {\n                PropertyField(fieldPosition, properties[i], propertyLabels[i]);\n                fieldPosition.y += kSingleLineHeight + kVerticalSpacingMultiField;\n            }\n\n            indentLevel = oldIndentLevel;\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n        }\n\n        internal static int CycleButton(Rect position, int selected, GUIContent[] options, GUIStyle style)\n        {\n            if (selected >= options.Length || selected < 0)\n            {\n                selected = 0;\n                GUI.changed = true;\n            }\n            if (GUI.Button(position, options[selected], style))\n            {\n                selected++;\n                GUI.changed = true;\n                if (selected >= options.Length)\n                {\n                    selected = 0;\n                }\n            }\n            return selected;\n        }\n\n        public static Color ColorField(Rect position, Color value)\n        {\n            int id = GUIUtility.GetControlID(s_ColorHash, FocusType.Keyboard, position);\n            return DoColorField(IndentedRect(position), id, value, true, true, false);\n        }\n\n        internal static Color ColorField(Rect position, Color value, bool showEyedropper, bool showAlpha)\n        {\n            int id = GUIUtility.GetControlID(s_ColorHash, FocusType.Keyboard, position);\n            return DoColorField(position, id, value, showEyedropper, showAlpha, false);\n        }\n\n        public static Color ColorField(Rect position, string label, Color value)\n        {\n            return ColorField(position, EditorGUIUtility.TempContent(label), value);\n        }\n\n        // Make a field for selecting a [[Color]].\n        public static Color ColorField(Rect position, GUIContent label, Color value)\n        {\n            int id = GUIUtility.GetControlID(s_ColorHash, FocusType.Keyboard, position);\n            return DoColorField(PrefixLabel(position, id, label), id, value, true, true, false);\n        }\n\n        internal static Color ColorField(Rect position, GUIContent label, Color value, bool showEyedropper, bool showAlpha)\n        {\n            int id = GUIUtility.GetControlID(s_ColorHash, FocusType.Keyboard, position);\n            return DoColorField(PrefixLabel(position, id, label), id, value, showEyedropper, showAlpha, false);\n        }\n\n        #pragma warning disable 612\n        [Obsolete(\"Use EditorGUI.ColorField(Rect position, GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr)\")]\n        public static Color ColorField(Rect position, GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr, ColorPickerHDRConfig hdrConfig)\n        {\n            return ColorField(position, label, value, showEyedropper, showAlpha, hdr);\n        }\n\n        #pragma warning restore 612\n\n        public static Color ColorField(Rect position, GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr)\n        {\n            int id = GUIUtility.GetControlID(s_ColorHash, FocusType.Keyboard, position);\n            return DoColorField(PrefixLabel(position, id, label), id, value, showEyedropper, showAlpha, hdr);\n        }\n\n        const float kEyedropperSize = 20f;\n\n        private static Color DoColorField(Rect position, int id, Color value, bool showEyedropper, bool showAlpha, bool hdr)\n        {\n            Event evt = Event.current;\n            GUIStyle style = EditorStyles.colorField;\n            Color origColor = value;\n            value = showMixedValue ? Color.white : value;\n            bool hovered = position.Contains(evt.mousePosition);\n            bool hoveredEyedropper = new Rect(position.x + position.width - kEyedropperSize, position.y, kEyedropperSize, position.height).Contains(evt.mousePosition);\n\n            var wasEnabled = GUI.enabled;\n            var eventType = GetEventTypeForControlAllowDisabledContextMenuPaste(evt, id);\n\n            switch (eventType)\n            {\n                case EventType.MouseDown:\n                    if (showEyedropper)\n                    {\n                        hovered ^= hoveredEyedropper;\n                    }\n\n                    if (hovered)\n                    {\n                        switch (evt.button)\n                        {\n                            case 0:\n                                // Left click: Show the ColorPicker\n                                GUIUtility.keyboardControl = id;\n                                showMixedValue = false;\n                                ColorPicker.Show(GUIView.current, value, showAlpha, hdr);\n                                GUIUtility.ExitGUI();\n                                break;\n\n                            case 1:\n                                // Right click: Show color context menu\n                                // See ExecuteCommand section below to see handling for copy & paste\n                                GUIUtility.keyboardControl = id;\n\n                                var names = new[] {L10n.Tr(\"Copy\"), L10n.Tr(\"Paste\")};\n                                var enabled = new[] {true, wasEnabled && Clipboard.hasColor};\n                                var currentView = GUIView.current;\n\n                                EditorUtility.DisplayCustomMenu(\n                                    new Rect(Event.current.mousePosition, Vector2.zero),\n                                    names,\n                                    enabled,\n                                    null,\n                                    delegate(object data, string[] options, int selected)\n                                    {\n                                        if (selected == 0)\n                                        {\n                                            Event e = EditorGUIUtility.CommandEvent(EventCommandNames.Copy);\n                                            currentView.SendEvent(e);\n                                        }\n                                        else if (selected == 1)\n                                        {\n                                            Event e = EditorGUIUtility.CommandEvent(EventCommandNames.Paste);\n                                            currentView.SendEvent(e);\n                                        }\n                                    },\n                                    null);\n                                evt.Use();\n                                return origColor;\n                        }\n                    }\n\n                    if (showEyedropper)\n                    {\n                        if (hoveredEyedropper && wasEnabled)\n                        {\n                            GUIUtility.keyboardControl = id;\n                            EyeDropper.Start(GUIView.current);\n                            s_ColorPickID = id;\n                            GUIUtility.ExitGUI();\n                        }\n                    }\n                    break;\n\n                case EventType.Repaint:\n                    Rect position2;\n                    position2 = showEyedropper ? style.padding.Remove(position) : EditorStyles.colorPickerBox.padding.Remove(position);\n\n                    if (showEyedropper)\n                    {\n                        style.Draw(position, GUIContent.none, id, false, hovered); // Draw box outline and eyedropper icon\n                    }\n                    else\n                    {\n                        EditorStyles.colorPickerBox.Draw(position, GUIContent.none, id, false, hovered); // Draw box outline\n                    }\n\n                    // Draw color field\n                    if (showEyedropper && s_ColorPickID == id)\n                    {\n                        Color c = EyeDropper.GetPickedColor();\n                        c.a = value.a;\n                        if (hdr)\n                            c = c.linear;\n                        EditorGUIUtility.DrawColorSwatch(position2, c, showAlpha, hdr);\n                    }\n                    else\n                    {\n                        EditorGUIUtility.DrawColorSwatch(position2, value, showAlpha, hdr);\n                    }\n\n                    break;\n\n                case EventType.ValidateCommand:\n\n                    switch (evt.commandName)\n                    {\n                        case EventCommandNames.UndoRedoPerformed:\n                            // Set color in ColorPicker in case an undo/redo has been made\n                            // when ColorPicker sends an event back to this control's GUIView, it someties retains keyboardControl\n                            if ((GUIUtility.keyboardControl == id || ColorPicker.originalKeyboardControl == id) && ColorPicker.visible)\n                                ColorPicker.color = value;\n                            break;\n\n                        case EventCommandNames.Copy:\n                        case EventCommandNames.Paste:\n                            evt.Use();\n                            break;\n                    }\n                    break;\n\n                case EventType.ExecuteCommand:\n\n                    // Cancel EyeDropper if we change focus.\n                    if (showEyedropper && Event.current.commandName == EventCommandNames.NewKeyboardFocus)\n                    {\n                        EyeDropper.End();\n                        s_ColorPickID = 0;\n                    }\n\n                    // when ColorPicker sends an event back to this control's GUIView, it sometimes retains keyboardControl\n                    if (GUIUtility.keyboardControl == id || ColorPicker.originalKeyboardControl == id)\n                    {\n                        switch (evt.commandName)\n                        {\n                            case EventCommandNames.EyeDropperUpdate:\n                                HandleUtility.Repaint();\n                                break;\n                            case EventCommandNames.EyeDropperClicked:\n                                GUI.changed = true;\n                                HandleUtility.Repaint();\n                                Color c = EyeDropper.GetLastPickedColor();\n                                c.a = value.a;\n                                s_ColorPickID = 0;\n                                return hdr ? c.linear : c;\n                            case EventCommandNames.EyeDropperCancelled:\n                                HandleUtility.Repaint();\n                                s_ColorPickID = 0;\n                                break;\n                            case EventCommandNames.ColorPickerChanged:\n                                GUI.changed = true;\n                                HandleUtility.Repaint();\n                                return ColorPicker.color;\n                            case EventCommandNames.Copy:\n                                Clipboard.colorValue = value;\n                                evt.Use();\n                                break;\n                            case EventCommandNames.Paste:\n                                PasteColor(ref origColor, showAlpha, hdr);\n                                break;\n                        }\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (evt.MainActionKeyForControl(id))\n                    {\n                        evt.Use();\n                        showMixedValue = false;\n                        ColorPicker.Show(GUIView.current, value, showAlpha, hdr);\n                        GUIUtility.ExitGUI();\n                    }\n                    else if (evt.modifiers == EventModifiers.Control && GUIUtility.keyboardControl == id)\n                    {\n                        if (evt.keyCode == KeyCode.C)\n                        {\n                            Clipboard.colorValue = value;\n                            evt.Use();\n                        }\n                        else if (evt.keyCode == KeyCode.V)\n                        {\n                            PasteColor(ref origColor, showAlpha, hdr);\n                        }\n                    }\n                    break;\n            }\n            return origColor;\n        }\n\n        private static void PasteColor(ref Color origColor, bool showAlpha, bool hdr)\n        {\n            if (Clipboard.hasColor)\n            {\n                Color pasted = Clipboard.colorValue;\n                if (!hdr && pasted.maxColorComponent > 1f)\n                    pasted = pasted.RGBMultiplied(1f / pasted.maxColorComponent);\n\n                // Do not change alpha if color field is not showing alpha\n                if (!showAlpha)\n                    pasted.a = origColor.a;\n\n                origColor = pasted;\n                GUI.changed = true;\n                Event.current.Use();\n            }\n        }\n\n        public static AnimationCurve CurveField(Rect position, AnimationCurve value)\n        {\n            int id = GUIUtility.GetControlID(s_CurveHash, FocusType.Keyboard, position);\n            return DoCurveField(IndentedRect(position), id, value, kCurveColor, new Rect(), null);\n        }\n\n        public static AnimationCurve CurveField(Rect position, string label, AnimationCurve value)\n        {\n            return CurveField(position, EditorGUIUtility.TempContent(label), value);\n        }\n\n        public static AnimationCurve CurveField(Rect position, GUIContent label, AnimationCurve value)\n        {\n            int id = GUIUtility.GetControlID(s_CurveHash, FocusType.Keyboard, position);\n            return DoCurveField(PrefixLabel(position, id, label), id, value, kCurveColor, new Rect(), null);\n        }\n\n        // Variants with settings\n        public static AnimationCurve CurveField(Rect position, AnimationCurve value, Color color, Rect ranges)\n        {\n            int id = GUIUtility.GetControlID(s_CurveHash, FocusType.Keyboard, position);\n            return DoCurveField(IndentedRect(position), id, value, color, ranges, null);\n        }\n\n        public static AnimationCurve CurveField(Rect position, string label, AnimationCurve value, Color color, Rect ranges)\n        {\n            return CurveField(position, EditorGUIUtility.TempContent(label), value, color, ranges);\n        }\n\n        // Make a field for editing an [[AnimationCurve]].\n        public static AnimationCurve CurveField(Rect position, GUIContent label, AnimationCurve value, Color color, Rect ranges)\n        {\n            int id = GUIUtility.GetControlID(s_CurveHash, FocusType.Keyboard, position);\n            return DoCurveField(PrefixLabel(position, id, label), id, value, color, ranges, null);\n        }\n\n        public static void CurveField(Rect position, SerializedProperty property, Color color, Rect ranges)\n        {\n            CurveField(position, property, color, ranges, null);\n        }\n\n        // Make a field for editing an [[AnimationCurve]].\n        public static void CurveField(Rect position, SerializedProperty property, Color color, Rect ranges, GUIContent label)\n        {\n            label = BeginProperty(position, label, property);\n\n            int id = GUIUtility.GetControlID(s_CurveHash, FocusType.Keyboard, position);\n            DoCurveField(PrefixLabel(position, id, label), id, null, color, ranges, property);\n\n            EndProperty();\n        }\n\n        private static void SetCurveEditorWindowCurve(AnimationCurve value, SerializedProperty property, Color color)\n        {\n            if (property != null)\n            {\n                CurveEditorWindow.curve = property.hasMultipleDifferentValues ? new AnimationCurve() : property.animationCurveValue;\n            }\n            else\n            {\n                CurveEditorWindow.curve = value;\n            }\n            CurveEditorWindow.color = color;\n        }\n\n        internal static AnimationCurve DoCurveField(Rect position, int id, AnimationCurve value, Color color, Rect ranges, SerializedProperty property)\n        {\n            Event evt = Event.current;\n\n            // Avoid crash problems caused by textures with zero or negative sizes!\n            position.width = Mathf.Max(position.width, 2);\n            position.height = Mathf.Max(position.height, 2);\n\n            if (GUIUtility.keyboardControl == id && evt.type != EventType.Layout && GUIView.current == CurveEditorWindow.delegateView)\n            {\n                if (s_CurveID != id)\n                {\n                    s_CurveID = id;\n                    if (CurveEditorWindow.visible)\n                    {\n                        SetCurveEditorWindowCurve(value, property, color);\n                        ShowCurvePopup(ranges);\n                    }\n                }\n                else\n                {\n                    if (CurveEditorWindow.visible && Event.current.type == EventType.Repaint)\n                    {\n                        SetCurveEditorWindowCurve(value, property, color);\n                        CurveEditorWindow.instance.Repaint();\n                    }\n                }\n            }\n\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (evt.button == 0 && position.Contains(evt.mousePosition))\n                    {\n                        s_CurveID = id;\n                        GUIUtility.keyboardControl = id;\n                        SetCurveEditorWindowCurve(value, property, color);\n                        ShowCurvePopup(ranges);\n                        evt.Use();\n                        GUIUtility.ExitGUI();\n                    }\n                    break;\n                case EventType.Repaint:\n                    Rect position2 = position;\n                    position2.y += 1;\n                    position2.height -= 1;\n                    if (ranges != new Rect())\n                    {\n                        EditorGUIUtility.DrawCurveSwatch(position2, value, property, color, kCurveBGColor, ranges);\n                    }\n                    else\n                    {\n                        EditorGUIUtility.DrawCurveSwatch(position2, value, property, color, kCurveBGColor);\n                    }\n                    EditorStyles.colorPickerBox.Draw(position2, GUIContent.none, id, false);\n                    break;\n                case EventType.ExecuteCommand:\n                    if (s_CurveID == id && GUIView.current == CurveEditorWindow.delegateView)\n                    {\n                        switch (evt.commandName)\n                        {\n                            case CurveEditorWindow.CurveChangedCommand:\n                                GUI.changed = true;\n                                AnimationCurvePreviewCache.ClearCache();\n                                HandleUtility.Repaint();\n                                if (property != null)\n                                {\n                                    property.animationCurveValue = CurveEditorWindow.curve;\n                                    if (property.hasMultipleDifferentValues)\n                                    {\n                                        Debug.LogError(\"AnimationCurve SerializedProperty hasMultipleDifferentValues is true after writing.\");\n                                    }\n                                }\n                                return CurveEditorWindow.curve;\n                        }\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (evt.MainActionKeyForControl(id))\n                    {\n                        s_CurveID = id;\n                        SetCurveEditorWindowCurve(value, property, color);\n                        ShowCurvePopup(ranges);\n                        evt.Use();\n                        GUIUtility.ExitGUI();\n                    }\n\n                    break;\n            }\n            return value;\n        }\n\n        private static void ShowCurvePopup(Rect ranges)\n        {\n            CurveEditorSettings settings = new CurveEditorSettings();\n            if (ranges.width > 0 && ranges.height > 0 && ranges.width != Mathf.Infinity && ranges.height != Mathf.Infinity)\n            {\n                settings.hRangeMin = ranges.xMin;\n                settings.hRangeMax = ranges.xMax;\n                settings.vRangeMin = ranges.yMin;\n                settings.vRangeMax = ranges.yMax;\n            }\n            CurveEditorWindow.instance.Show(GUIView.current, settings);\n        }\n\n        internal static Vector2 GetObjectIconDropDownSize(float width, float height)\n        {\n            return new Vector2(width + kDropDownArrowWidth / 2 + 2 * kDropDownArrowMargin, height + kDropDownArrowWidth / 2 + 2 * kDropDownArrowMargin);\n        }\n\n        internal static void ObjectIconDropDown(Rect position, Object[] targets, bool showLabelIcons, Texture2D nullIcon, SerializedProperty iconProperty)\n        {\n            if (s_IconTextureInactive == null)\n            {\n                s_IconTextureInactive = (Material)EditorGUIUtility.LoadRequired(\"Inspectors/InactiveGUI.mat\");\n            }\n\n            if (s_IconButtonStyle == null)\n            {\n                s_IconButtonStyle = new GUIStyle(EditorStyles.iconButton)\n                {\n                    fixedWidth = 0,\n                    fixedHeight = 0\n                };\n            }\n\n            if (DropdownButton(position, GUIContent.none, FocusType.Passive, s_IconButtonStyle))\n            {\n                if (IconSelector.ShowAtPosition(targets, position, showLabelIcons))\n                {\n                    GUIUtility.ExitGUI();\n                }\n            }\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                var contentPosition = position;\n\n                contentPosition.xMin += kDropDownArrowMargin;\n                contentPosition.xMax -= kDropDownArrowMargin + kDropDownArrowWidth / 2;\n                contentPosition.yMin += kDropDownArrowMargin;\n                contentPosition.yMax -= kDropDownArrowMargin + kDropDownArrowWidth / 2;\n\n                Rect arrowRect = new Rect(contentPosition.x + contentPosition.width - kDropDownArrowWidth / 2, contentPosition.y + contentPosition.height - kDropDownArrowHeight / 2, kDropDownArrowWidth, kDropDownArrowHeight);\n                Texture2D icon = null;\n\n                if (!iconProperty.hasMultipleDifferentValues)\n                {\n                    icon = AssetPreview.GetMiniThumbnail(targets[0]);\n                }\n                if (icon == null)\n                {\n                    icon = nullIcon;\n                }\n\n                Vector2 iconSize = contentPosition.size;\n\n                if (icon)\n                {\n                    iconSize.x = Mathf.Min(icon.width, iconSize.x);\n                    iconSize.y = Mathf.Min(icon.height, iconSize.y);\n                }\n                Rect iconRect = new Rect(contentPosition.x + contentPosition.width / 2 - iconSize.x / 2, contentPosition.y + contentPosition.height / 2 - iconSize.y / 2 , iconSize.x, iconSize.y);\n                GameObject obj = targets[0] as GameObject;\n\n                bool isInactive = obj && (!EditorUtility.IsPersistent(targets[0]) && (!obj.activeSelf || !obj.activeInHierarchy));\n\n                if (isInactive)\n                {\n                    var imageAspect = icon.width / (float)icon.height;\n                    Rect iconScreenRect = new Rect();\n                    Rect sourceRect = new Rect();\n                    GUI.CalculateScaledTextureRects(iconRect, ScaleMode.ScaleToFit, imageAspect, ref iconScreenRect, ref sourceRect);\n                    Graphics.DrawTexture(iconScreenRect, icon, sourceRect, 0, 0, 0, 0, new Color(.5f, .5f, .5f, 1f), s_IconTextureInactive);\n                }\n                else\n                {\n                    GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleToFit);\n                }\n\n                if (s_IconDropDown == null)\n                {\n                    s_IconDropDown = EditorGUIUtility.IconContent(\"Icon Dropdown\");\n                }\n                GUIStyle.none.Draw(arrowRect, s_IconDropDown, false, false, false, false);\n            }\n        }\n\n        // Titlebar without foldout\n        public static void InspectorTitlebar(Rect position, Object[] targetObjs)\n        {\n            GUIStyle baseStyle = GUIStyle.none;\n            int id = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position);\n            DoInspectorTitlebar(position, id, true, targetObjs, null, baseStyle);\n        }\n\n        public static bool InspectorTitlebar(Rect position, bool foldout, Object targetObj, bool expandable)\n        {\n            return InspectorTitlebar(position, foldout, new[] {targetObj}, expandable);\n        }\n\n        // foldable titlebar.\n        public static bool InspectorTitlebar(Rect position, bool foldout, Object[] targetObjs, bool expandable)\n        {\n            GUIStyle baseStyle = EditorStyles.inspectorTitlebar;\n\n            // Important to get controlId for the foldout first, so it gets keyboard focus before the toggle does.\n            int id = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position);\n            DoInspectorTitlebar(position, id, foldout, targetObjs, null, baseStyle);\n            foldout = DoObjectMouseInteraction(foldout, position, targetObjs, id);\n\n            if (expandable)\n            {\n                Rect renderRect = GetInspectorTitleBarObjectFoldoutRenderRect(position, baseStyle);\n                DoObjectFoldoutInternal(foldout, renderRect, id);\n            }\n\n            return foldout;\n        }\n\n        // foldable titlebar based on Editor.\n        public static bool InspectorTitlebar(Rect position, bool foldout, Editor editor)\n        {\n            GUIStyle baseStyle = EditorStyles.inspectorTitlebar;\n\n            // Important to get controlId for the foldout first, so it gets keyboard focus before the toggle does.\n            int id = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position);\n            DoInspectorTitlebar(position, id, foldout, editor.targets, editor.enabledProperty, baseStyle);\n            foldout = DoObjectMouseInteraction(foldout, position, editor.targets, id);\n\n            if (editor.CanBeExpandedViaAFoldout())\n            {\n                Rect renderRect = GetInspectorTitleBarObjectFoldoutRenderRect(position, baseStyle);\n                DoObjectFoldoutInternal(foldout, renderRect, id);\n            }\n\n            return foldout;\n        }\n\n        static Rect GetIconRect(Rect position, GUIStyle baseStyle)\n        {\n            return new Rect(position.x + baseStyle.padding.left, position.y + (baseStyle.fixedHeight - kInspTitlebarIconWidth) / 2 + baseStyle.padding.top, kInspTitlebarIconWidth, kInspTitlebarIconWidth);\n        }\n\n        static Rect GetTextRect(Rect position, Rect iconRect, Rect settingsRect, GUIStyle baseStyle, GUIStyle textStyle)\n        {\n            return new Rect(iconRect.xMax + kInspTitlebarSpacing + kInspTitlebarSpacing + kInspTitlebarIconWidth,\n                position.y + (baseStyle.fixedHeight - textStyle.fixedHeight) / 2 + baseStyle.padding.top, 100, textStyle.fixedHeight)\n            { xMax = settingsRect.xMin - kInspTitlebarSpacing };\n        }\n\n        static Rect GetSettingsRect(Rect position, GUIStyle baseStyle, GUIStyle iconButtonStyle)\n        {\n            Vector2 settingsElementSize = iconButtonStyle.CalcSize(GUIContents.titleSettingsIcon);\n\n            return new Rect(position.xMax - baseStyle.padding.right - kInspTitlebarSpacing - kInspTitlebarIconWidth\n                , position.y + (baseStyle.fixedHeight - settingsElementSize.y) / 2 + baseStyle.padding.top, settingsElementSize.x, settingsElementSize.y);\n        }\n\n        internal static bool EnableCheckBoxInTitlebar(Object targetObj)\n        {\n            if (targetObj is ScriptableObject && targetObj is not StateMachineBehaviour)\n                return false;\n\n            return true;\n        }\n\n        // Make an inspector-window-like titlebar.\n        internal static void DoInspectorTitlebar(Rect position, int id, bool foldout, Object[] targetObjs, SerializedProperty enabledProperty, GUIStyle baseStyle)\n        {\n            GUIStyle textStyle = EditorStyles.inspectorTitlebarText;\n            GUIStyle iconButtonStyle = EditorStyles.iconButton;\n            Event evt = Event.current;\n            bool pressed = GUIUtility.hotControl == id;\n            bool hasFocus = GUIUtility.HasKeyFocus(id);\n            bool hovered = position.Contains(evt.mousePosition);\n\n            Rect iconRect = GetIconRect(position, baseStyle);\n            Rect settingsRect = GetSettingsRect(position, baseStyle, iconButtonStyle);\n            Rect textRect = GetTextRect(position, iconRect, settingsRect, baseStyle, textStyle);\n\n            if (evt.type == EventType.Repaint)\n            {\n                baseStyle.Draw(position, GUIContent.none, hovered, pressed, foldout, hasFocus);\n            }\n\n            bool isAddedComponentAndEventIsRepaint = false;\n            Component comp = targetObjs[0] as Component;\n            if (ShouldDrawOverrideBackground(targetObjs, evt, comp))\n            {\n                isAddedComponentAndEventIsRepaint = true;\n                DrawOverrideBackgroundApplicable(position, true);\n            }\n\n            int enabled = -1;\n            foreach (Object targetObj in targetObjs)\n            {\n                if (comp is MonoBehaviour)\n                {\n                    enabled = 1;\n                }\n                else\n                {\n                    int thisEnabled = EditorUtility.GetObjectEnabled(targetObj);\n                    if (enabled == -1)\n                    {\n                        if (EnableCheckBoxInTitlebar(targetObj))\n                            enabled = thisEnabled;\n                    }\n                    else if (enabled != thisEnabled)\n                    {\n                        enabled = -2;\n                        // Early out: mix value mode\n                        break;\n                    }\n                }\n            }\n\n            if (enabled != -1)\n            {\n                Rect toggleRect = iconRect;\n                toggleRect.x = iconRect.xMax + kInspTitlebarSpacing;\n                Rect combinedIconAndToggleRect = new Rect(iconRect.x, iconRect.y, toggleRect.xMax - iconRect.xMin, iconRect.height);\n\n                if (enabledProperty != null)\n                {\n                    enabledProperty.serializedObject.Update();\n                    EditorGUI.PropertyField(toggleRect, enabledProperty, GUIContent.none);\n                    enabledProperty.serializedObject.ApplyModifiedProperties();\n                }\n                // The codepath and usage where we do not have a SerializedProperty is more complicated while\n                // providing less functionality. It does not display a line in the margin when the enabled\n                // toggle has been overridden on a Prefab instance.\n                // The stuff it's doing with AnimationMode, undo handling, and multi object editing\n                // is all stuff that's also handled internally in SerializedProperty.\n                // It's kept for backwards compatibility only, since InspectorTitlebar is public API.\n                else\n                {\n                    bool enabledState = enabled != 0;\n                    showMixedValue = enabled == -2;\n                    BeginChangeCheck();\n\n                    Color previousColor = GUI.backgroundColor;\n                    bool animated = AnimationMode.IsPropertyAnimated(targetObjs[0], kEnabledPropertyName);\n                    if (animated)\n                    {\n                        Color animatedColor = AnimationMode.animatedPropertyColor;\n                        if (AnimationMode.InAnimationRecording())\n                            animatedColor = AnimationMode.recordedPropertyColor;\n                        else if (AnimationMode.IsPropertyCandidate(targetObjs[0], kEnabledPropertyName))\n                            animatedColor = AnimationMode.candidatePropertyColor;\n\n                        animatedColor.a *= GUI.color.a;\n                        GUI.backgroundColor = animatedColor;\n                    }\n\n                    int toggleId = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position);\n                    enabledState = EditorGUIInternal.DoToggleForward(toggleRect, toggleId, enabledState, GUIContent.none, EditorStyles.toggle);\n\n                    if (animated)\n                    {\n                        GUI.backgroundColor = previousColor;\n                    }\n\n                    if (EndChangeCheck())\n                    {\n                        Undo.RecordObjects(targetObjs, (enabledState ? \"Enable\" : \"Disable\") + \" Component\" + (targetObjs.Length > 1 ? \"s\" : \"\"));\n\n                        foreach (Object targetObj in targetObjs)\n                        {\n                            EditorUtility.SetObjectEnabled(targetObj, enabledState);\n                        }\n                    }\n\n                    showMixedValue = false;\n                }\n\n\n                if (combinedIconAndToggleRect.Contains(Event.current.mousePosition))\n                {\n                    // It's necessary to handle property context menu here in right mouse down because\n                    // component contextual menu will override this otherwise.\n                    if ((evt.type == EventType.MouseDown && evt.button == 1) || evt.type == EventType.ContextClick)\n                    {\n                        SerializedObject serializedObject = new SerializedObject(targetObjs);\n                        DoPropertyContextMenu(serializedObject.FindProperty(kEnabledPropertyName));\n                        evt.Use();\n                    }\n                }\n            }\n\n            Rect headerItemRect = settingsRect;\n            headerItemRect.x -= kInspTitlebarIconWidth + kInspTitlebarSpacing;\n            headerItemRect = EditorGUIUtility.DrawEditorHeaderItems(headerItemRect, targetObjs, kInspTitlebarSpacing);\n            textRect.xMax = headerItemRect.xMin - kInspTitlebarSpacing;\n\n            if (evt.type == EventType.Repaint)\n            {\n                var icon = AssetPreview.GetMiniThumbnail(targetObjs[0]);\n                GUIStyle.none.Draw(iconRect, EditorGUIUtility.TempContent(icon), iconRect.Contains(Event.current.mousePosition), false, false, false);\n\n                if (isAddedComponentAndEventIsRepaint)\n                    GUIStyle.none.Draw(iconRect, EditorGUIUtility.TempContent(Styles.prefabOverlayAddedIcon), false, false, false, false);\n            }\n\n            // Temporarily set GUI.enabled = true to enable the Settings button. see Case 947218.\n            var oldGUIEnabledState = GUI.enabled;\n\n            GUI.enabled = true;\n\n            switch (evt.type)\n            {\n                case EventType.MouseDown:\n                    if (EditorGUIUtility.comparisonViewMode == EditorGUIUtility.ComparisonViewMode.None && settingsRect.Contains(evt.mousePosition))\n                    {\n                        EditorUtility.DisplayObjectContextMenu(settingsRect, targetObjs, 0);\n                        evt.Use();\n                    }\n                    break;\n                case EventType.Repaint:\n                    textStyle.Draw(textRect, EditorGUIUtility.TempContent(ObjectNames.GetInspectorTitle(targetObjs[0], targetObjs.Length > 1)), hovered, pressed, foldout, hasFocus);\n                    if (EditorGUIUtility.comparisonViewMode == EditorGUIUtility.ComparisonViewMode.None)\n                    {\n                        EditorStyles.optionsButtonStyle.Draw(settingsRect, GUIContent.none, id, foldout, settingsRect.Contains(Event.current.mousePosition));\n                    }\n                    break;\n            }\n\n            GUI.enabled = oldGUIEnabledState;\n        }\n\n        internal static bool ShouldDrawOverrideBackground(Object[] targetObjs, Event evt, Component comp)\n        {\n            return evt.type == EventType.Repaint &&\n                targetObjs.Length == 1 &&\n                comp != null &&\n                EditorGUIUtility.comparisonViewMode == EditorGUIUtility.ComparisonViewMode.None &&\n                PrefabUtility.GetCorrespondingConnectedObjectFromSource(comp.gameObject) != null &&\n                PrefabUtility.GetCorrespondingObjectFromSource(comp) == null;\n        }\n\n        internal static void RemovedComponentTitlebar(Rect position, GameObject instanceGo, Component sourceComponent)\n        {\n            GUIStyle baseStyle = EditorStyles.inspectorTitlebar;\n            GUIStyle textStyle = EditorStyles.inspectorTitlebarText;\n            GUIStyle iconButtonStyle = EditorStyles.iconButton;\n\n            Rect iconRect = GetIconRect(position, baseStyle);\n            Rect settingsRect = GetSettingsRect(position, baseStyle, iconButtonStyle);\n            Rect textRect = GetTextRect(position, iconRect, settingsRect, baseStyle, textStyle);\n\n            textRect.xMax = settingsRect.xMin - kInspTitlebarSpacing;\n\n            Event evt = Event.current;\n\n            bool openMenu = false;\n            Rect openMenuRect = new Rect();\n            if (position.Contains(Event.current.mousePosition))\n            {\n                // It's necessary to handle property context menu here in right mouse down because\n                // component contextual menu will override this otherwise.\n                if ((evt.type == EventType.MouseDown && evt.button == 1) || evt.type == EventType.ContextClick)\n                    openMenu = true;\n            }\n\n            Rect headerItemRect = settingsRect;\n            headerItemRect.x -= kInspTitlebarIconWidth + kInspTitlebarSpacing;\n            textRect.xMax = headerItemRect.xMin - kInspTitlebarSpacing;\n\n            int id = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position);\n            switch (evt.type)\n            {\n                case EventType.MouseDown:\n                    if (settingsRect.Contains(evt.mousePosition))\n                    {\n                        openMenu = true;\n                        openMenuRect = settingsRect;\n                    }\n                    break;\n                case EventType.Repaint:\n                    baseStyle.Draw(position, GUIContent.none, false, false, false, false);\n\n                    if (EditorGUIUtility.comparisonViewMode == EditorGUIUtility.ComparisonViewMode.None)\n                        DrawOverrideBackgroundApplicable(position, true);\n\n                    EditorStyles.optionsButtonStyle.Draw(settingsRect, GUIContent.none, id, false, settingsRect.Contains(Event.current.mousePosition));\n\n                    var icon = AssetPreview.GetMiniThumbnail(sourceComponent);\n\n                    using (new DisabledScope(true))\n                    {\n                        GUIStyle.none.Draw(iconRect, EditorGUIUtility.TempContent(icon), false, false, false, false);\n                    }\n\n                    GUIStyle.none.Draw(iconRect, EditorGUIUtility.TempContent(Styles.prefabOverlayRemovedIcon), false, false, false, false);\n                    position = baseStyle.padding.Remove(position);\n\n                    using (new DisabledScope(true))\n                    {\n                        textStyle.Draw(textRect, EditorGUIUtility.TempContent(ObjectNames.GetInspectorTitle(sourceComponent) + \" (Removed)\"), false, false, false, false);\n                    }\n                    break;\n            }\n\n            if (openMenu)\n            {\n                GenericMenu menu = new GenericMenu();\n                PrefabUtility.HandleApplyRevertMenuItems(\n                    \"Removed Component\",\n                    instanceGo,\n                    (menuItemContent, sourceObject, _) =>\n                    {\n                        TargetChoiceHandler.ObjectInstanceAndSourceInfo info = new TargetChoiceHandler.ObjectInstanceAndSourceInfo();\n                        info.instanceObject = instanceGo;\n                        Component componentToRemove = sourceComponent;\n                        while (componentToRemove.gameObject != sourceObject)\n                        {\n                            componentToRemove = PrefabUtility.GetCorrespondingObjectFromSource(componentToRemove);\n                            if (componentToRemove == null)\n                                return;\n                        }\n                        info.correspondingObjectInSource = componentToRemove;\n                        if (!PrefabUtility.IsPartOfPrefabThatCanBeAppliedTo(componentToRemove) || EditorUtility.IsPersistent(instanceGo))\n                            menu.AddDisabledItem(menuItemContent);\n                        else\n                            menu.AddItem(menuItemContent, false, TargetChoiceHandler.ApplyPrefabRemovedComponent, info);\n                    },\n                    (menuItemContent) =>\n                    {\n                        TargetChoiceHandler.ObjectInstanceAndSourceInfo info = new TargetChoiceHandler.ObjectInstanceAndSourceInfo();\n                        info.instanceObject = instanceGo;\n                        info.correspondingObjectInSource = sourceComponent;\n                        menu.AddItem(menuItemContent, false, TargetChoiceHandler.RevertPrefabRemovedComponent, info);\n                    }\n                );\n                if (openMenuRect == new Rect())\n                    menu.ShowAsContext();\n                else\n                    menu.DropDown(settingsRect);\n                evt.Use();\n            }\n        }\n\n        internal static bool ToggleTitlebar(Rect position, GUIContent label, bool foldout, ref bool toggleValue)\n        {\n            // Important to get controlId for the foldout first, so it gets keyboard focus before the toggle does.\n            int id = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position);\n\n            GUIStyle baseStyle = EditorStyles.inspectorTitlebar;\n            GUIStyle textStyle = EditorStyles.inspectorTitlebarText;\n            GUIStyle foldoutStyle = EditorStyles.titlebarFoldout;\n\n            Rect toggleRect = new Rect(position.x + baseStyle.padding.left, position.y + baseStyle.padding.top, kInspTitlebarIconWidth, kInspTitlebarIconWidth);\n            Rect textRect = new Rect(toggleRect.xMax + kInspTitlebarSpacing, toggleRect.y, 200, kInspTitlebarIconWidth);\n\n            int toggleId = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position);\n\n            toggleValue = EditorGUIInternal.DoToggleForward(toggleRect, toggleId, toggleValue, GUIContent.none, EditorStyles.toggle);\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                baseStyle.Draw(position, GUIContent.none, id, foldout);\n                foldoutStyle.Draw(GetInspectorTitleBarObjectFoldoutRenderRect(position, baseStyle), GUIContent.none, id, foldout);\n                position = baseStyle.padding.Remove(position);\n                textStyle.Draw(textRect, label, id, foldout);\n            }\n\n            return EditorGUIInternal.DoToggleForward(IndentedRect(position), id, foldout, GUIContent.none, GUIStyle.none);\n        }\n\n        internal static bool FoldoutTitlebar(Rect position, GUIContent label, bool foldout, bool skipIconSpacing)\n        {\n            return FoldoutTitlebar(position, label, foldout, skipIconSpacing,\n                EditorStyles.inspectorTitlebar, EditorStyles.inspectorTitlebarText);\n        }\n\n        internal static bool FoldoutTitlebar(Rect position, GUIContent label, bool foldout, bool skipIconSpacing, GUIStyle baseStyle, GUIStyle textStyle)\n        {\n            // Important to get controlId for the foldout first, so it gets keyboard focus before the toggle does.\n            int id = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position);\n\n            switch (Event.current.type)\n            {\n                case EventType.KeyDown:\n                    if (GUIUtility.keyboardControl == id)\n                    {\n                        KeyCode kc = Event.current.keyCode;\n                        if (kc == KeyCode.LeftArrow && foldout || (kc == KeyCode.RightArrow && foldout == false))\n                        {\n                            foldout = !foldout;\n                            GUI.changed = true;\n                            Event.current.Use();\n                            return foldout;\n                        }\n                    }\n\n                    break;\n                case EventType.Repaint:\n                    GUIStyle foldoutStyle = EditorStyles.titlebarFoldout;\n                    var textPositionX = position.x + baseStyle.padding.left +\n                        (skipIconSpacing ? 0 : (kInspTitlebarIconWidth + kInspTitlebarSpacing));\n                    Rect textRect =\n                        new Rect(textPositionX, position.y + baseStyle.padding.top,\n                            Mathf.Max(EditorGUIUtility.labelWidth, position.xMax - textPositionX), kInspTitlebarIconWidth);\n                    bool hovered = position.Contains(Event.current.mousePosition);\n                    baseStyle.Draw(position, GUIContent.none, id, foldout, hovered);\n                    foldoutStyle.Draw(GetInspectorTitleBarObjectFoldoutRenderRect(position, baseStyle), GUIContent.none,\n                        id, foldout, hovered);\n                    position = baseStyle.padding.Remove(position);\n                    textStyle.Draw(textRect, EditorGUIUtility.TempContent(label.text), id, foldout, hovered);\n                    break;\n                default:\n                    break;\n            }\n\n            return EditorGUIInternal.DoToggleForward(IndentedRect(position), id, foldout, GUIContent.none, GUIStyle.none);\n        }\n\n        [EditorHeaderItem(typeof(Object), -1000)]\n        internal static bool HelpIconButton(Rect position, Object[] objs)\n        {\n            var obj = objs[0];\n            bool isDevBuild = Unsupported.IsSourceBuild();\n\n            // For efficiency, only check in development builds if this script is a user script.\n            bool monoBehaviourFallback = !isDevBuild;\n            if (!monoBehaviourFallback)\n            {\n                monoBehaviourFallback = HelpButtonCache.IsObjectPartOfTargetAssemblies(obj);\n            }\n\n            bool hasHelp = HelpButtonCache.HasHelpForObject(obj, monoBehaviourFallback);\n            if (hasHelp || isDevBuild)\n            {\n                // Help button should not be disabled at any time. For example VCS system disables\n                // inspectors and it wouldn't make sense to prevent users from getting help because\n                // he didn't check out the file yet.\n                bool wasEditorDisabled = GUI.enabled;\n                GUI.enabled = true;\n\n                GUIContent content = GUIContent.Temp(GUIContents.helpIcon.image);\n\n                // Only build the tooltip string if the cursor is over our help button rect\n                if (position.Contains(Event.current.mousePosition))\n                {\n                    string helpTopic = Help.GetNiceHelpNameForObject(obj, monoBehaviourFallback);\n                    if (isDevBuild && !hasHelp)\n                    {\n                        bool isScript = obj is MonoBehaviour;\n                        string pageName = (isScript ? \"script-\" : \"sealed partial class-\") + helpTopic;\n                        content.tooltip = string.Format(@\"Could not find Reference page for {0} ({1}).\\nDocs for this object is missing or all docs are missing.\\nThis warning only shows up in development builds.\", helpTopic, pageName);\n                    }\n                    else\n                    {\n                        content.tooltip = string.Format(\"Open Reference for {0}.\", ObjectNames.NicifyVariableName(helpTopic));\n                    }\n                }\n\n                Color oldColor = GUI.color;\n                if (isDevBuild && !hasHelp)\n                    GUI.color = Color.yellow;\n\n                GUIStyle helpIconStyle = EditorStyles.iconButton;\n                if (GUI.Button(position, content, helpIconStyle))\n                {\n                    Help.ShowHelpForObject(obj);\n                }\n\n                GUI.color = oldColor;\n                GUI.enabled = wasEditorDisabled;\n\n                return true;\n            }\n            return false;\n        }\n\n        // Make a label with a foldout arrow to the left of it.\n        internal static bool FoldoutInternal(Rect position, bool foldout, GUIContent content, bool toggleOnLabelClick, GUIStyle style)\n        {\n            Rect origPosition = position;\n            position = style.margin.Remove(position);\n            if (EditorGUIUtility.hierarchyMode)\n            {\n                int offset = (EditorStyles.foldout.padding.left - EditorStyles.label.padding.left);\n                position.xMin -= offset;\n            }\n\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            EventType eventType = Event.current.type;\n            // special case test, so we are able to receive mouse events when we are disabled. This allows the foldout to still be expanded/contracted when disabled.\n            if (!GUI.enabled && GUIClip.enabled && (Event.current.rawType == EventType.MouseDown || Event.current.rawType == EventType.MouseDrag || Event.current.rawType == EventType.MouseUp))\n            {\n                eventType = Event.current.rawType;\n            }\n\n            Rect clickRect = position;\n            if (!toggleOnLabelClick)\n            {\n                clickRect.width = style.padding.left;\n                clickRect.x += indent;\n            }\n            switch (eventType)\n            {\n                case EventType.MouseDown:\n                    // If the mouse is inside the button, we say that we're the hot control\n                    if (clickRect.Contains(Event.current.mousePosition) && Event.current.button == 0)\n                    {\n                        GUIUtility.keyboardControl = GUIUtility.hotControl = id;\n                        Event.current.Use();\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n\n                        // If we got the mousedown, the mouseup is ours as well\n                        // (no matter if the click was in the button or not)\n                        Event.current.Use();\n\n                        // toggle the passed-in value if the mouse was over the button & return true\n                        if (clickRect.Contains(Event.current.mousePosition))\n                        {\n                            GUI.changed = true;\n                            return !foldout;\n                        }\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        Event.current.Use();\n                    }\n                    break;\n                case EventType.Repaint:\n                    EditorStyles.foldoutSelected.Draw(position, GUIContent.none, id, s_DragUpdatedOverID == id);\n\n                    Rect drawRect = new Rect(position.x + indent, position.y, EditorGUIUtility.labelWidth - indent, position.height);\n\n                    // If mixed values, indicate it in the collapsed foldout field so it's easy to see at a glance if anything\n                    // in the Inspector has different values. Don't show it when expanded, since the difference will be visible further down.\n                    if (showMixedValue && !foldout)\n                    {\n                        style.Draw(drawRect, content, id, false, false);\n\n                        BeginHandleMixedValueContentColor();\n                        Rect fieldPosition = origPosition;\n                        fieldPosition.xMin += EditorGUIUtility.labelWidth;\n                        EditorStyles.label.Draw(fieldPosition, s_MixedValueContent, id, false);\n                        EndHandleMixedValueContentColor();\n                    }\n                    else\n                    {\n                        style.Draw(drawRect, content, id, foldout, false);\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (GUIUtility.keyboardControl == id)\n                    {\n                        KeyCode kc = Event.current.keyCode;\n                        if (kc == KeyCode.LeftArrow && foldout || (kc == KeyCode.RightArrow && foldout == false))\n                        {\n                            foldout = !foldout;\n                            GUI.changed = true;\n                            Event.current.Use();\n                        }\n                    }\n                    break;\n                case EventType.DragUpdated:\n                    if (s_DragUpdatedOverID == id)\n                    {\n                        if (position.Contains(Event.current.mousePosition))\n                        {\n                            if (Time.realtimeSinceStartup > s_FoldoutDestTime)\n                            {\n                                foldout = true;\n                                Event.current.Use();\n                            }\n                        }\n                        else\n                        {\n                            s_DragUpdatedOverID = 0;\n                        }\n                    }\n                    else\n                    {\n                        if (position.Contains(Event.current.mousePosition))\n                        {\n                            s_DragUpdatedOverID = id;\n                            s_FoldoutDestTime = Time.realtimeSinceStartup + kFoldoutExpandTimeout;\n                            Event.current.Use();\n                        }\n                    }\n                    break;\n                case EventType.DragExited:\n                    if (s_DragUpdatedOverID == id)\n                    {\n                        s_DragUpdatedOverID = 0;\n                        Event.current.Use();\n                    }\n                    break;\n            }\n            return foldout;\n        }\n\n        // Make a progress bar.\n        public static void ProgressBar(Rect position, float value, string text)\n        {\n            ProgressBar(position, value, GUIContent.Temp(text), false, EditorStyles.progressBarBack, EditorStyles.progressBarBar, EditorStyles.progressBarText);\n        }\n\n        internal static bool ProgressBar(Rect position, float value, GUIContent content, bool textOnBar,\n            GUIStyle progressBarBackgroundStyle, GUIStyle progressBarStyle, GUIStyle progressBarTextStyle)\n        {\n            bool mouseHover = position.Contains(Event.current.mousePosition);\n            int id = GUIUtility.GetControlID(s_ProgressBarHash, FocusType.Keyboard, position);\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (mouseHover)\n                    {\n                        Event.current.Use();\n                        return true;\n                    }\n                    break;\n                case EventType.Repaint:\n                    progressBarBackgroundStyle.Draw(position, mouseHover, false, false, false);\n                    if (value > 0.0f)\n                    {\n                        value = Mathf.Clamp01(value);\n                        var barRect = new Rect(position);\n                        barRect.width *= value;\n                        if (barRect.width >= 1f)\n                            progressBarStyle.Draw(barRect, GUIContent.none, mouseHover, false, false, false);\n                    }\n                    else if (value == -1.0f)\n                    {\n                        float barWidth = position.width * 0.2f;\n                        float halfBarWidth = barWidth / 2.0f;\n                        float cos = Mathf.Cos((float)EditorApplication.timeSinceStartup * 2f);\n                        float rb = position.x + halfBarWidth;\n                        float re = position.xMax - halfBarWidth;\n                        float scale = (re - rb) / 2f;\n                        float cursor = scale * cos;\n                        var barRect = new Rect(position.x + cursor + scale, position.y, barWidth, position.height);\n                        progressBarStyle.Draw(barRect, GUIContent.none, mouseHover, false, false, false);\n                    }\n                    var contentTextToDisplay = content;\n                    var contentWidth = progressBarTextStyle.CalcSize(contentTextToDisplay).x;\n                    if (contentWidth > position.width)\n                    {\n                        int numberOfVisibleCharacters = (int)((position.width / contentWidth) * content.text.Length);\n                        // we iterate in case we encounter a weird string like ________..............._________ (with big characters in the outside and small in the inside)\n                        int i = 0;\n                        do\n                        {\n                            int numberOfVisibleCharactersBySide = numberOfVisibleCharacters / 2 - 2 - i; //-2 to account for the ..., we reduce each iteration to fit\n                            contentTextToDisplay.text = content.text.Substring(0, numberOfVisibleCharactersBySide) + \"...\" + content.text.Substring(content.text.Length - numberOfVisibleCharactersBySide, numberOfVisibleCharactersBySide);\n                            ++i;\n                        }\n                        while (progressBarTextStyle.CalcSize(contentTextToDisplay).x > position.width);\n                    }\n                    progressBarTextStyle.Draw(position, contentTextToDisplay, mouseHover, false, false, false);\n                    break;\n            }\n\n            return false;\n        }\n\n        // Make a help box with a message to the user.\n        public static void HelpBox(Rect position, string message, MessageType type)\n        {\n            HelpBox(position, EditorGUIUtility.TempContent(message, EditorGUIUtility.GetHelpIcon(type)));\n        }\n\n        public static void HelpBox(Rect position, GUIContent content)\n        {\n            GUI.Label(position, content, EditorStyles.helpBox);\n        }\n\n        internal static bool LabelHasContent(GUIContent label)\n        {\n            if (label == null)\n            {\n                return true;\n            }\n            // @TODO: find out why checking for GUIContent.none doesn't work\n            return label.text != string.Empty || label.image != null;\n        }\n\n        internal static void PrepareCurrentPrefixLabel(int controlId)\n        {\n            if (s_HasPrefixLabel)\n            {\n                if (!string.IsNullOrEmpty(s_PrefixLabel.text))\n                {\n                    Color curColor = GUI.color;\n                    GUI.color = s_PrefixGUIColor;\n                    HandlePrefixLabel(s_PrefixTotalRect, s_PrefixRect, s_PrefixLabel, controlId, s_PrefixStyle);\n                    GUI.color = curColor;\n                }\n\n                s_HasPrefixLabel = false;\n            }\n        }\n\n        internal static bool IsLabelHighlightEnabled()\n        {\n            return s_LabelHighlightContext != null && s_LabelHighlightContext.Length > 1;\n        }\n\n        internal static void BeginLabelHighlight(string searchContext, Color searchHighlightSelectionColor, Color searchHighlightColor)\n        {\n            if (searchContext != null && searchContext.Trim() == \"\")\n            {\n                searchContext = null;\n            }\n            s_LabelHighlightContext = searchContext;\n            s_LabelHighlightSelectionColor = searchHighlightSelectionColor;\n            s_LabelHighlightColor = searchHighlightColor;\n        }\n\n        internal static void EndLabelHighlight()\n        {\n            s_LabelHighlightContext = null;\n        }\n\n        internal static bool DrawLabelHighlight(Rect position, GUIContent label, GUIStyle style)\n        {\n            if (!IsLabelHighlightEnabled() || !SearchUtils.MatchSearchGroups(s_LabelHighlightContext, label.text, out var startHighlight, out var endHighlight))\n                return false;\n\n            const bool isActive = false;\n            const bool hasKeyboardFocus = true; // This ensure we draw the selection text over the label.\n            const bool drawAsComposition = false;\n\n            // Override text color when in label highlight regardless of the GUIStyleState\n            var oldFocusedTextColor = style.focused.textColor;\n            style.focused.textColor = s_LabelHighlightColor;\n            style.DrawWithTextSelection(position, label, isActive, hasKeyboardFocus, startHighlight, endHighlight + 1, drawAsComposition, s_LabelHighlightSelectionColor);\n            style.focused.textColor = oldFocusedTextColor;\n\n            return true;\n        }\n\n        // Draw a prefix label and select the corresponding control if the label is clicked.\n        // If no id or an id of 0 is specified, the id of the next control will be used.\n        // For regular inline controls, the PrefixLabel method should be used,\n        // but HandlePrefixLabel can be used for customized label placement.\n        internal static void HandlePrefixLabelInternal(Rect totalPosition, Rect labelPosition, GUIContent label, int id, GUIStyle style)\n        {\n            // If we don't know the controlID at this time, delay the handling of the prefix label until the next GUIUtility.GetControlID\n            if (id == 0 && label != null)\n            {\n                s_PrefixLabel.text = label.text;\n                s_PrefixLabel.image = label.image;\n                s_PrefixLabel.tooltip = label.tooltip;\n                s_PrefixTotalRect = totalPosition;\n                s_PrefixRect = labelPosition;\n                s_PrefixStyle = style;\n                s_PrefixGUIColor = GUI.color;\n                s_HasPrefixLabel = true;\n                return;\n            }\n\n            // Control highlighting\n            if (Highlighter.searchMode == HighlightSearchMode.PrefixLabel ||\n                Highlighter.searchMode == HighlightSearchMode.Auto)\n            {\n                if (label != null) Highlighter.Handle(totalPosition, label.text);\n            }\n\n            switch (Event.current.type)\n            {\n                case EventType.Repaint:\n                    labelPosition.width += 1;\n\n                    Color oldColor = GUI.backgroundColor;\n                    GUI.backgroundColor = Color.white;\n\n                    if (!EditorGUI.DrawLabelHighlight(labelPosition, label, style))\n                        style.DrawPrefixLabel(labelPosition, label, id);\n\n                    GUI.backgroundColor = oldColor;\n                    break;\n\n                case EventType.MouseDown:\n                    if (Event.current.button == 0 && labelPosition.Contains(Event.current.mousePosition))\n                    {\n                        if (EditorGUIUtility.CanHaveKeyboardFocus(id))\n                        {\n                            GUIUtility.keyboardControl = id;\n                        }\n                        EditorGUIUtility.editingTextField = false;\n                        HandleUtility.Repaint();\n                    }\n                    break;\n            }\n        }\n\n        // Make a label in front of some control.\n        public static Rect PrefixLabel(Rect totalPosition, GUIContent label)\n        {\n            return PrefixLabel(totalPosition, 0, label, EditorStyles.label);\n        }\n\n        public static Rect PrefixLabel(Rect totalPosition, GUIContent label, GUIStyle style)\n        {\n            return PrefixLabel(totalPosition, 0, label, style);\n        }\n\n        public static Rect PrefixLabel(Rect totalPosition, int id, GUIContent label)\n        {\n            return PrefixLabel(totalPosition, id, label, EditorStyles.label);\n        }\n\n        public static Rect PrefixLabel(Rect totalPosition, int id, GUIContent label, GUIStyle style)\n        {\n            if (!LabelHasContent(label))\n            {\n                return IndentedRect(totalPosition);\n            }\n\n            Rect labelPosition = new Rect(totalPosition.x + indent, totalPosition.y, EditorGUIUtility.labelWidth - indent, lineHeight);\n            Rect fieldPosition = new Rect(totalPosition.x + EditorGUIUtility.labelWidth + kPrefixPaddingRight, totalPosition.y, totalPosition.width - EditorGUIUtility.labelWidth - kPrefixPaddingRight, totalPosition.height);\n            HandlePrefixLabel(totalPosition, labelPosition, label, id, style);\n            return fieldPosition;\n        }\n\n        internal static bool UseVTMaterial(Texture texture)\n        {\n            if (PlayerSettings.GetVirtualTexturingSupportEnabled() == false)\n                return false;\n            Texture2D tex2d = texture as Texture2D;\n            int tileSize = VirtualTexturing.EditorHelpers.tileSize;\n            return tex2d != null && tex2d.vtOnly && tex2d.width > tileSize && tex2d.height > tileSize;\n        }\n\n        internal static Rect MultiFieldPrefixLabel(Rect totalPosition, int id, GUIContent label, int columns)\n        {\n            return MultiFieldPrefixLabel(totalPosition, id, label, columns, 0, false);\n        }\n\n        internal static Rect MultiFieldPrefixLabel(Rect totalPosition, int id, GUIContent label, int columns, float labelWidthIndent, bool setWideMode)\n        {\n            if (!LabelHasContent(label))\n            {\n                return IndentedRect(totalPosition);\n            }\n\n            if (EditorGUIUtility.wideMode || setWideMode)\n            {\n                Rect labelPosition = new Rect(totalPosition.x + indent, totalPosition.y, EditorGUIUtility.labelWidth - indent - labelWidthIndent, kSingleLineHeight);\n                Rect fieldPosition = totalPosition;\n                fieldPosition.xMin += EditorGUIUtility.labelWidth + kPrefixPaddingRight;\n\n                // If there are 2 columns we use the same column widths as if there had been 3 columns\n                // in order to make columns line up neatly.\n                if (columns == 2)\n                {\n                    float columnWidth = (fieldPosition.width - (3 - 1) * kSpacingSubLabel) / 3f;\n                    fieldPosition.xMax -= (columnWidth + kSpacingSubLabel);\n                }\n\n                HandlePrefixLabel(totalPosition, labelPosition, label, id);\n                return fieldPosition;\n            }\n            else\n            {\n                Rect labelPosition = new Rect(totalPosition.x + indent, totalPosition.y, totalPosition.width - indent, kSingleLineHeight);\n                Rect fieldPosition = totalPosition;\n                fieldPosition.xMin += indent + kIndentPerLevel;\n                fieldPosition.yMin += kSingleLineHeight + kVerticalSpacingMultiField;\n                HandlePrefixLabel(totalPosition, labelPosition, label, id);\n                return fieldPosition;\n            }\n        }\n\n        public class PropertyScope : GUI.Scope\n        {\n            public GUIContent content { get; protected set; }\n\n            public PropertyScope(Rect totalPosition, GUIContent label, SerializedProperty property)\n            {\n                content = BeginProperty(totalPosition, label, property);\n            }\n\n            protected override void CloseScope()\n            {\n                EndProperty();\n            }\n        }\n\n        // Create a Property wrapper, useful for making regular GUI controls work with [[SerializedProperty]].\n        public static GUIContent BeginProperty(Rect totalPosition, GUIContent label, SerializedProperty property)\n        {\n            return BeginPropertyInternal(totalPosition, label, property);\n        }\n\n        // Create a Property wrapper, useful for making regular GUI controls work with [[SerializedProperty]].\n        internal static GUIContent BeginPropertyInternal(Rect totalPosition, GUIContent label, SerializedProperty property)\n        {\n            if (s_PendingPropertyKeyboardHandling != null)\n            {\n                DoPropertyFieldKeyboardHandling(s_PendingPropertyKeyboardHandling);\n            }\n\n            // Properties can be nested, so A BeginProperty may not be followed by its corresponding EndProperty\n            // before there have been one or more pairs of BeginProperty/EndProperty in between.\n            // The keyboard handling for a property (that handles duplicate and delete commands for array items)\n            // uses EditorGUI.lastControlID so it has to be executed for a property before any possible child\n            // properties are handled. However, it can't be done in it's own BeginProperty, because the controlID\n            // for the property is not yet known at that point. For that reason we mark the keyboard handling as\n            // pending and handle it either the next BeginProperty call (for the first child property) or if there's\n            // no child properties, then in the matching EndProperty call.\n            s_PendingPropertyKeyboardHandling = property;\n\n            if (property == null)\n            {\n                string error = (label == null ? \"\" : label.text + \": \") + \"SerializedProperty is null\";\n                HelpBox(totalPosition, \"null\", MessageType.Error);\n                throw new NullReferenceException(error);\n            }\n\n            if (Highlighter.IsSearchingForIdentifier())\n                Highlighter.HighlightIdentifier(totalPosition, property.propertyPath);\n\n            s_PropertyFieldTempContent.text = (label == null) ? property.localizedDisplayName : label.text; // no necessary to be translated.\n            s_PropertyFieldTempContent.tooltip = (label == null || string.IsNullOrEmpty(label.tooltip)) ? property.tooltip : label.tooltip;\n            s_PropertyFieldTempContent.image = label?.image;\n\n            // In inspector debug mode & when holding down alt. Show the property path of the property.\n            if (Event.current.alt && property.serializedObject.inspectorMode != InspectorMode.Normal)\n            {\n                s_PropertyFieldTempContent.tooltip = s_PropertyFieldTempContent.text = property.propertyPath;\n            }\n\n            bool wasBoldDefaultFont = EditorGUIUtility.GetBoldDefaultFont();\n            var so = property.serializedObject;\n            if (so.HasAnyInstantiatedPrefabsWithValidAsset() && EditorGUIUtility.comparisonViewMode != EditorGUIUtility.ComparisonViewMode.Original)\n            {\n                PropertyGUIData parentData = s_PropertyStack.Count > 0 ? s_PropertyStack.Peek() : new PropertyGUIData();\n                bool linkedProperties = parentData.totalPosition == totalPosition;\n\n                var hasPrefabOverride = property.prefabOverride;\n                if (!linkedProperties || hasPrefabOverride)\n                    EditorGUIUtility.SetBoldDefaultFont(hasPrefabOverride);\n\n                if (Event.current.type == EventType.Repaint && hasPrefabOverride && !property.isDefaultOverride && !property.isDrivenRectTransformProperty)\n                {\n                    Rect highlightRect = totalPosition;\n                    highlightRect.xMin += EditorGUI.indent;\n\n                    if (!PrefabUtility.CanPropertyBeAppliedToSource(property))\n                        DrawOverrideBackgroundNonApplicable(highlightRect, false);\n                    else\n                        DrawOverrideBackgroundApplicable(highlightRect, false);\n                }\n            }\n\n            if (Event.current.type == EventType.Repaint && EditorApplication.isPlaying && SerializedObject.GetLivePropertyFeatureGlobalState())\n            {\n                var component = property.serializedObject.targetObject as Component;\n                var isLiveProperty = (component != null && !component.gameObject.scene.isSubScene) || property.isLiveModified;\n\n                if (isLiveProperty)\n                {\n                    EditorGUIUtility.SetBoldDefaultFont(true);\n\n                    Rect highlightRect = totalPosition;\n                    highlightRect.xMin += EditorGUI.indent;\n                    DrawLivePropertyBackground(highlightRect, false);\n                }\n            }\n\n            s_PropertyStack.Push(new PropertyGUIData(property, totalPosition, wasBoldDefaultFont, GUI.enabled, GUI.backgroundColor));\n\n            EditorGUIUtility.BeginPropertyCallback(totalPosition, property);\n\n            if (GUIDebugger.active && Event.current.type != EventType.Layout)\n            {\n                var targetObjectTypeName = property.serializedObject.targetObject != null ?\n                    property.serializedObject.targetObject.GetType().AssemblyQualifiedName : null;\n                GUIDebugger.LogBeginProperty(targetObjectTypeName, property.propertyPath, totalPosition);\n            }\n\n            showMixedValue = property.hasMultipleDifferentValues;\n\n            if (property.isAnimated)\n            {\n                Color animatedColor = AnimationMode.animatedPropertyColor;\n                if (AnimationMode.InAnimationRecording())\n                    animatedColor = AnimationMode.recordedPropertyColor;\n                else if (property.isCandidate)\n                    animatedColor = AnimationMode.candidatePropertyColor;\n\n                animatedColor.a *= GUI.backgroundColor.a;\n                GUI.backgroundColor = animatedColor;\n            }\n            else if (PrefabUtility.IsPropertyBeingDrivenByPrefabStage(property))\n            {\n                GUI.enabled = false;\n                if (isCollectingTooltips)\n                    s_PropertyFieldTempContent.tooltip = PrefabStage.s_PrefabInContextPreviewValuesTooltip;\n            }\n\n            GUI.enabled &= property.editable;\n\n            return s_PropertyFieldTempContent;\n        }\n\n        // Ends a Property wrapper started with ::ref::BeginProperty.\n        public static void EndProperty()\n        {\n            if (GUIDebugger.active && Event.current.type != EventType.Layout)\n            {\n                GUIDebugger.LogEndProperty();\n            }\n\n            showMixedValue = false;\n            PropertyGUIData data = s_PropertyStack.Pop();\n\n            PropertyGUIData parentData = s_PropertyStack.Count > 0 ? s_PropertyStack.Peek() : new PropertyGUIData();\n            bool linkedProperties = parentData.totalPosition == data.totalPosition;\n\n            // Context menu\n            // Handle context menu in EndProperty instead of BeginProperty. This ensures that child properties\n            // get the event rather than parent properties when clicking inside the child property rects, but the menu can\n            // still be invoked for the parent property by clicking inside the parent rect but outside the child rects.\n            var oldEnable = GUI.enabled;\n            GUI.enabled = true; // Event.current.type will never return ContextClick if the GUI is disabled.\n            if (Event.current.type == EventType.ContextClick && data.totalPosition.Contains(Event.current.mousePosition))\n            {\n                GUI.enabled = oldEnable;\n                if (linkedProperties)\n                    DoPropertyContextMenu(data.property, parentData.property);\n                else\n                    DoPropertyContextMenu(data.property);\n            }\n            GUI.enabled = oldEnable;\n\n            EditorGUIUtility.SetBoldDefaultFont(data.wasBoldDefaultFont);\n            GUI.enabled = data.wasEnabled;\n            GUI.backgroundColor = data.color;\n\n            if (s_PendingPropertyKeyboardHandling != null)\n            {\n                DoPropertyFieldKeyboardHandling(s_PendingPropertyKeyboardHandling);\n            }\n\n            // Wait with deleting the property until the property stack is empty in order to avoid\n            // deleting a property in the middle of GUI calls that's dependent on it existing.\n            if (s_PendingPropertyDelete != null && s_PropertyStack.Count == 0)\n            {\n                // For SerializedProperty iteration reasons, if the property we delete is the current property,\n                // we have to delete on the actual iterator property rather than a copy of it,\n                // otherwise we get an error next time we call NextVisible on the iterator property.\n                if (s_PendingPropertyDelete.propertyPath == data.property.propertyPath)\n                {\n                    data.property.DeleteCommand();\n                }\n                else\n                {\n                    s_PendingPropertyDelete.DeleteCommand();\n                }\n                s_PendingPropertyDelete = null;\n            }\n        }\n\n        internal static void DrawOverrideBackground(Rect position, Color color, bool fixupRectForHeadersAndBackgrounds = false)\n        {\n            if (fixupRectForHeadersAndBackgrounds)\n            {\n                // Tweaks to match the specifics of how the horizontal lines between components are drawn.\n                position.yMin += 2;\n                position.yMax += 1;\n            }\n\n            DrawMarginLineForRect(position, color);\n        }\n\n        internal static void DrawOverrideBackgroundApplicable(Rect position, bool fixupRectForHeadersAndBackgrounds = false)\n        {\n            DrawOverrideBackground(position, k_OverrideMarginColor, fixupRectForHeadersAndBackgrounds);\n        }\n\n        internal static void DrawOverrideBackgroundNonApplicable(Rect position, bool fixupRectForHeadersAndBackgrounds = false)\n        {\n            DrawOverrideBackground(position, k_OverrideMarginColorNotApplicable, fixupRectForHeadersAndBackgrounds);\n        }\n\n        internal static void DrawMarginLineForRect(Rect position, Color color)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            position.x = EditorGUIUtility.leftMarginCoord - Mathf.Max(0f, GUIClip.topmostRect.xMin);\n            position.width = 2;\n            Graphics.DrawTexture(position, EditorGUIUtility.whiteTexture, new Rect(), 0, 0, 0, 0, color, guiTextureClipVerticallyMaterial);\n        }\n\n        internal static void DrawLivePropertyBackground(Rect position, bool fixupRectForHeadersAndBackgrounds = false)\n        {\n            if (fixupRectForHeadersAndBackgrounds)\n            {\n                // Tweaks to match the specifics of how the horizontal lines between components are drawn.\n                position.yMin += 2;\n                position.yMax += 1;\n            }\n\n            DrawMarginLineForRect(position, EditorGUIUtility.isProSkin? k_LiveModifiedMarginDarkThemeColor : k_LiveModifiedMarginLightThemeColor);\n        }\n\n        private static SerializedProperty s_PendingPropertyKeyboardHandling = null;\n        private static SerializedProperty s_PendingPropertyDelete = null;\n\n        private static void DoPropertyFieldKeyboardHandling(SerializedProperty property)\n        {\n            s_PendingPropertyKeyboardHandling = null;\n\n            // Only interested in processing commands if our field has keyboard focus\n            if (GUIUtility.keyboardControl != EditorGUIUtility.s_LastControlID)\n                return;\n\n            var evt = Event.current;\n\n            // Only interested in validate/execute keyboard shortcut commands\n            if (evt.type != EventType.ExecuteCommand && evt.type != EventType.ValidateCommand)\n                return;\n\n            var isExecute = Event.current.type == EventType.ExecuteCommand;\n\n            // Delete\n            if (evt.commandName == EventCommandNames.Delete || evt.commandName == EventCommandNames.SoftDelete)\n            {\n                if (isExecute)\n                {\n                    // Wait with deleting the property until the property stack is empty. See EndProperty.\n                    s_PendingPropertyDelete = property.Copy();\n                }\n                evt.Use();\n            }\n            // Duplicate\n            if (evt.commandName == EventCommandNames.Duplicate)\n            {\n                if (isExecute)\n                    property.DuplicateCommand();\n                evt.Use();\n            }\n            // Copy & Paste\n            if (evt.commandName == EventCommandNames.Copy || evt.commandName == EventCommandNames.Paste)\n            {\n                if (evt.commandName == EventCommandNames.Paste)\n                    GUI.changed = true;\n                ClipboardContextMenu.SetupPropertyCopyPaste(property, menu: null, evt: evt);\n            }\n        }\n\n        internal static void LayerMaskField(Rect position, SerializedProperty property, GUIContent label, GUIStyle style)\n        {\n            LayerMaskField(position, unchecked((uint)property.intValue), property, label, style);\n        }\n\n        // Make a field for layer masks.\n        internal static void LayerMaskField(Rect position, SerializedProperty property, GUIContent label)\n        {\n            LayerMaskField(position, unchecked((uint)property.intValue), property, label, EditorStyles.layerMaskField);\n        }\n\n        internal static LayerMask LayerMaskField(Rect position, LayerMask layers, GUIContent label)\n        {\n            return unchecked((int)LayerMaskField(position, unchecked((uint)layers.value), null, label, EditorStyles.layerMaskField));\n        }\n\n        internal static uint LayerMaskField(Rect position, UInt32 layers, GUIContent label)\n        {\n            return LayerMaskField(position, layers, null, label, EditorStyles.layerMaskField);\n        }\n\n        private static string[] s_LayerNames;\n        private static int[] s_LayerValues;\n\n        internal static uint LayerMaskField(Rect position, UInt32 layers, SerializedProperty property, GUIContent label, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_LayerMaskField, FocusType.Keyboard, position);\n\n            if (label != null)\n            {\n                position = PrefixLabel(position, id, label);\n            }\n\n            TagManager.GetDefinedLayers(ref s_LayerNames, ref s_LayerValues);\n\n            EditorGUI.BeginChangeCheck();\n            var newValue = MaskFieldGUI.DoMaskField(position, id, unchecked((int)layers), s_LayerNames, s_LayerValues, style);\n            if (EditorGUI.EndChangeCheck() && property != null)\n                property.intValue = newValue;\n            return unchecked((uint)newValue);\n        }\n\n        // Helper function for helping with debugging the editor\n        internal static void ShowRepaints()\n        {\n            if (!Unsupported.IsDeveloperMode() || !s_ShowRepaintDots)\n                return;\n\n            Color temp = GUI.color;\n            GUI.color = new Color(UnityEngine.Random.value * .6f + .4f, UnityEngine.Random.value * .6f + .4f, UnityEngine.Random.value * .6f + .4f, 1f);\n            var size = new Vector2(Styles.repaintDot.width, Styles.repaintDot.height);\n            GUI.Label(new Rect(Vector2.zero, EditorGUIUtility.PixelsToPoints(size)), Styles.repaintDot);\n            GUI.color = temp;\n        }\n\n        // Draws the alpha channel of a texture within a rectangle.\n        internal static void DrawTextureAlphaInternal(Rect position, Texture image, ScaleMode scaleMode, float imageAspect, float mipLevel)\n        {\n            var mat = UseVTMaterial(image) ? alphaVTMaterial : alphaMaterial;\n            DrawPreviewTextureInternal(position, image, mat, scaleMode, imageAspect, mipLevel, ColorWriteMask.All, 0);\n        }\n\n        // Draws texture transparently using the alpha channel.\n        internal static void DrawTextureTransparentInternal(Rect position, Texture image, ScaleMode scaleMode, float imageAspect, float mipLevel, ColorWriteMask colorWriteMask, float exposure)\n        {\n            if (imageAspect == 0f && image == null)\n            {\n                Debug.LogError(\"Please specify an image or a imageAspect\");\n                return;\n            }\n\n            if (imageAspect == 0f)\n                imageAspect = image.width / (float)image.height;\n\n            DrawTransparencyCheckerTexture(position, scaleMode, imageAspect);\n            if (image != null)\n            {\n                var mat = UseVTMaterial(image) ? transparentVTMaterial : transparentMaterial;\n                DrawPreviewTexture(position, image, mat, scaleMode, imageAspect, mipLevel, colorWriteMask, exposure);\n            }\n        }\n\n        internal static void DrawTransparencyCheckerTexture(Rect position, ScaleMode scaleMode, float imageAspect)\n        {\n            Rect screenRect = new Rect();\n            Rect sourceRect = new Rect();\n\n            GUI.CalculateScaledTextureRects(position, scaleMode, imageAspect, ref screenRect, ref sourceRect);\n\n            GUI.DrawTextureWithTexCoords(\n                screenRect,\n                transparentCheckerTexture,\n                new Rect(\n                    screenRect.width * -.5f / transparentCheckerTexture.width,\n                    screenRect.height * -.5f / transparentCheckerTexture.height,\n                    screenRect.width / transparentCheckerTexture.width,\n                    screenRect.height / transparentCheckerTexture.height),\n                false);\n        }\n\n        // Draws the texture within a rectangle.\n        internal static void DrawPreviewTextureInternal(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect, float mipLevel, ColorWriteMask colorWriteMask, float exposure)\n        {\n            if (Event.current.type == EventType.Repaint)\n            {\n                if (imageAspect == 0)\n                    imageAspect = image.width / (float)image.height;\n\n                Color colorMask = new Color(1, 1, 1, 1);\n\n                if ((colorWriteMask & ColorWriteMask.Red) == 0)\n                    colorMask.r = 0;\n                if ((colorWriteMask & ColorWriteMask.Green) == 0)\n                    colorMask.g = 0;\n                if ((colorWriteMask & ColorWriteMask.Blue) == 0)\n                    colorMask.b = 0;\n                if ((colorWriteMask & ColorWriteMask.Alpha) == 0)\n                    colorMask.a = 0;\n\n                if (mat == null)\n                    mat = GetMaterialForSpecialTexture(image, UseVTMaterial(image) ? colorVTMaterial : colorMaterial);\n\n                mat.SetColor(\"_ColorMask\", colorMask);\n                mat.SetFloat(\"_Mip\", mipLevel);\n                mat.SetFloat(\"_Exposure\", exposure);\n                mat.SetInt(\"_SNormFormat\", UnityEngine.Experimental.Rendering.GraphicsFormatUtility.IsSNormFormat(image.graphicsFormat) ? 1 : 0);\n\n                RenderTexture rt = image as RenderTexture;\n                bool manualResolve = (rt != null) && rt.bindTextureMS;\n\n                if (manualResolve)\n                {\n                    var desc = rt.descriptor;\n                    desc.bindMS = false;\n                    desc.msaaSamples = 1;\n                    RenderTexture resolved = RenderTexture.GetTemporary(desc);\n                    resolved.Create();\n                    rt.ResolveAntiAliasedSurface(resolved);\n                    image = resolved;\n                }\n\n                Rect screenRect = new Rect(), sourceRect = new Rect();\n                GUI.CalculateScaledTextureRects(position, scaleMode, imageAspect, ref screenRect, ref sourceRect);\n                Texture2D t2d = image as Texture2D;\n                if (t2d != null && TextureUtil.GetUsageMode(image) == TextureUsageMode.AlwaysPadded)\n                {\n                    // In case of always padded textures, only show the non-padded area\n                    sourceRect.width *= (float)t2d.width / TextureUtil.GetGPUWidth(t2d);\n                    sourceRect.height *= (float)t2d.height / TextureUtil.GetGPUHeight(t2d);\n                }\n                Graphics.DrawTexture(screenRect, image, sourceRect, 0, 0, 0, 0, GUI.color, mat);\n\n                //Start streaming in content for the next preview draw calls. The first draw might not have texture content to render with.\n                //StreamTexture is called after the draw call because the VT stack might not have been created yet otherwise.\n                StreamTexture(image, mat, mipLevel);\n\n                if (manualResolve)\n                {\n                    RenderTexture.ReleaseTemporary(image as RenderTexture);\n                }\n            }\n        }\n\n        internal static void StreamTexture(Texture texture, Material mat, float mipLevel)\n        {\n            if (UseVTMaterial(texture))\n            {\n                const string stackName = \"Stack\";//keep in sync with preview shader stack name\n                int stackNameId = Shader.PropertyToID(stackName);\n                Texture2D t2d = texture as Texture2D;\n\n                //Request a higher mipmap first to make sure we have (low res) data as soon as possible\n                const int fallbackResolution = 256;\n                int minDimension = Mathf.Min(texture.width, texture.height);\n                if (minDimension > fallbackResolution)\n                {\n                    float factor = (float)minDimension / (float)fallbackResolution;\n                    int fallbackMipLevel = (int)Math.Ceiling(Math.Log(factor, 2));\n\n                    if (fallbackMipLevel > (int)mipLevel)\n                        VirtualTexturing.Streaming.RequestRegion(mat, stackNameId, new Rect(0, 0, 1, 1), fallbackMipLevel, 2); //make sure the 128x128 mip is also requested to always have a fallback. Needed for mini thumbnails\n                }\n\n                if (mipLevel >= 0) //otherwise we don't know what mip will be sampled in the shader\n                {\n                    VirtualTexturing.Streaming.RequestRegion(mat, stackNameId, new Rect(0, 0, 1, 1), (int)mipLevel, 1);\n                }\n            }\n        }\n\n        // This will return appriopriate material to use with the texture according to its usage mode\n        internal static Material GetMaterialForSpecialTexture(Texture t, Material defaultMat = null, bool manualTex2Linear = false, bool useVTMaterialWhenPossible = true)\n        {\n            bool useVT = useVTMaterialWhenPossible && UseVTMaterial(t);\n\n            // i am not sure WHY do we check that (i would guess this is api user error and exception make sense, not \"return something\")\n            if (t == null) return null;\n\n            TextureUsageMode usage = TextureUtil.GetUsageMode(t);\n            TextureFormat format = TextureUtil.GetTextureFormat(t);\n            if (usage == TextureUsageMode.RealtimeLightmapRGBM || usage == TextureUsageMode.BakedLightmapRGBM || usage == TextureUsageMode.RGBMEncoded)\n                return lightmapRGBMMaterial;\n            else if (usage == TextureUsageMode.BakedLightmapDoubleLDR)\n                return lightmapDoubleLDRMaterial;\n            else if (usage == TextureUsageMode.BakedLightmapFullHDR)\n                return lightmapFullHDRMaterial;\n            else if (TextureUtil.IsNormalMapUsageMode(usage))\n            {\n                var normalMat = useVT ? normalmapVTMaterial : normalmapMaterial;\n                normalMat.SetFloat(\"_IsPlainNormalmap\", usage == TextureUsageMode.NormalmapPlain && format != TextureFormat.BC5 ? 1.0f : 0.0f);\n                normalMat.SetFloat(\"_ManualTex2Linear\", manualTex2Linear ? 1.0f : 0.0f);\n                return normalMat;\n            }\n            else if (GraphicsFormatUtility.IsAlphaOnlyFormat(format))\n            {\n                var alphaOnlyMat = useVT ? alphaVTMaterial : alphaMaterial;\n                alphaOnlyMat.SetFloat(\"_ManualTex2Linear\", manualTex2Linear ? 1.0f : 0.0f);\n                return alphaOnlyMat;\n            }\n\n\n            if (defaultMat != null)\n            {\n                defaultMat.SetInt(\"_SNormFormat\", UnityEngine.Experimental.Rendering.GraphicsFormatUtility.IsSNormFormat(t.graphicsFormat) ? 1 : 0);\n            }\n\n            return defaultMat;\n        }\n\n        internal static Texture2D transparentCheckerTexture\n        {\n            get\n            {\n                if (EditorGUIUtility.isProSkin)\n                {\n                    return EditorGUIUtility.LoadRequired(\"Previews/Textures/textureCheckerDark.png\") as Texture2D;\n                }\n                else\n                {\n                    return EditorGUIUtility.LoadRequired(\"Previews/Textures/textureChecker.png\") as Texture2D;\n                }\n            }\n        }\n\n        // before we had preview materials as static vars, but these go null on domain reload, leaking memory\n        // so now we keep them in native land\n        // we load shaders from assets and create materials once (in native), and managed code queries them when needed\n\n        internal static Material colorMaterial\n        {\n            get { return EditorGUIUtility.GetPreviewMaterial(PreviewMaterialType.Color); }\n        }\n        internal static Material colorVTMaterial\n        {\n            get { return EditorGUIUtility.GetPreviewMaterial(PreviewMaterialType.ColorVT); }\n        }\n        internal static Material alphaMaterial\n        {\n            get { return EditorGUIUtility.GetPreviewMaterial(PreviewMaterialType.Alpha); }\n        }\n        internal static Material alphaVTMaterial\n        {\n            get { return EditorGUIUtility.GetPreviewMaterial(PreviewMaterialType.AlphaVT); }\n        }\n        internal static Material transparentMaterial\n        {\n            get { return EditorGUIUtility.GetPreviewMaterial(PreviewMaterialType.Transparent); }\n        }\n        internal static Material transparentVTMaterial\n        {\n            get { return EditorGUIUtility.GetPreviewMaterial(PreviewMaterialType.TransparentVT); }\n        }\n        internal static Material normalmapMaterial\n        {\n            get { return EditorGUIUtility.GetPreviewMaterial(PreviewMaterialType.Normalmap); }\n        }\n        internal static Material normalmapVTMaterial\n        {\n            get { return EditorGUIUtility.GetPreviewMaterial(PreviewMaterialType.NormalmapVT); }\n        }\n        internal static Material lightmapRGBMMaterial\n        {\n            get { return EditorGUIUtility.GetPreviewMaterial(PreviewMaterialType.LightmapRGBM); }\n        }\n        internal static Material lightmapDoubleLDRMaterial\n        {\n            get { return EditorGUIUtility.GetPreviewMaterial(PreviewMaterialType.LightmapDoubleLDR); }\n        }\n        internal static Material lightmapFullHDRMaterial\n        {\n            get { return EditorGUIUtility.GetPreviewMaterial(PreviewMaterialType.LightmapFullHDR); }\n        }\n        internal static Material guiTextureClipVerticallyMaterial\n        {\n            get { return EditorGUIUtility.GetPreviewMaterial(PreviewMaterialType.GUITextureClipVertically); }\n        }\n\n        internal static void SetExpandedRecurse(SerializedProperty property, bool expanded)\n        {\n            SerializedProperty search = property.Copy();\n            int depth = search.depth;\n            HashSet<long> visited = null;\n            bool visitChild;\n            do\n            {\n                visitChild = true;\n                if (search.propertyType == SerializedPropertyType.ManagedReference)\n                {\n                    // Managed reference objects can form a cyclical graph, so need to track visited objects\n                    if (visited == null)\n                        visited = new HashSet<long>();\n\n                    long refId = search.managedReferenceId;\n                    if (!visited.Add(refId))\n                    {\n                        visitChild = false;\n                        continue;\n                    }\n                }\n\n                if (depth == search.depth || search.hasVisibleChildren)\n                {\n                    search.isExpanded = expanded;\n                }\n            }\n            while (search.NextVisible(visitChild) && search.depth > depth);\n        }\n\n        // Get the height needed for a ::ref::PropertyField control, not including its children and not taking custom PropertyDrawers into account.\n        internal static float GetSinglePropertyHeight(SerializedProperty property, GUIContent label)\n        {\n            if (property == null)\n                return kSingleLineHeight;\n            return GetPropertyHeight(property.propertyType, label);\n        }\n\n        // Get the height needed for a simple builtin control type.\n        public static float GetPropertyHeight(SerializedPropertyType type, GUIContent label)\n        {\n            if (type == SerializedPropertyType.Vector3 || type == SerializedPropertyType.Vector2 || type == SerializedPropertyType.Vector4 ||\n                type == SerializedPropertyType.Vector3Int || type == SerializedPropertyType.Vector2Int || type == SerializedPropertyType.Quaternion)\n            {\n                return (!LabelHasContent(label) || EditorGUIUtility.wideMode ? 0f : kStructHeaderLineHeight + kVerticalSpacingMultiField) +\n                    kSingleLineHeight;\n            }\n\n            if (type == SerializedPropertyType.Rect || type == SerializedPropertyType.RectInt)\n            {\n                return (!LabelHasContent(label) || EditorGUIUtility.wideMode ? 0f : kStructHeaderLineHeight + kVerticalSpacingMultiField) +\n                    kSingleLineHeight * 2 + kVerticalSpacingMultiField;\n            }\n\n            // Bounds field has label on its own line even in wide mode because the words \"center\" and \"extends\"\n            // would otherwise eat too much of the label space.\n            if (type == SerializedPropertyType.Bounds || type == SerializedPropertyType.BoundsInt)\n            {\n                return (!LabelHasContent(label) ? 0f : kStructHeaderLineHeight + kVerticalSpacingMultiField) + kSingleLineHeight * 2 + kVerticalSpacingMultiField;\n            }\n\n            return kSingleLineHeight;\n        }\n\n        // Get the height needed for a ::ref::PropertyField control.\n        internal static float GetPropertyHeightInternal(SerializedProperty property, GUIContent label, bool includeChildren)\n        {\n            return ScriptAttributeUtility.GetHandler(property).GetHeight(property, label, includeChildren);\n        }\n\n        [Obsolete(\"CanCacheInspectorGUI has been deprecated and is no longer used.\", false)]\n        public static bool CanCacheInspectorGUI(SerializedProperty property)\n        {\n            return false;\n        }\n\n        internal static bool HasVisibleChildFields(SerializedProperty property, bool isUIElements = false)\n        {\n            switch (property.propertyType)\n            {\n                case SerializedPropertyType.Vector3:\n                case SerializedPropertyType.Vector2:\n                case SerializedPropertyType.Vector3Int:\n                case SerializedPropertyType.Vector2Int:\n                case SerializedPropertyType.Rect:\n                case SerializedPropertyType.RectInt:\n                case SerializedPropertyType.Bounds:\n                case SerializedPropertyType.BoundsInt:\n                case SerializedPropertyType.Hash128:\n                    return false;\n            }\n\n            if (PropertyHandler.UseReorderabelListControl(property)) return false;\n\n            return property.hasVisibleChildren;\n        }\n\n        // Make a field for [[SerializedProperty]].\n        internal static bool PropertyFieldInternal(Rect position, SerializedProperty property, GUIContent label, bool includeChildren)\n        {\n            return ScriptAttributeUtility.GetHandler(property).OnGUI(position, property, label, includeChildren);\n        }\n\n        static readonly string s_ArrayMultiInfoFormatString = EditorGUIUtility.TrTextContent(\"This field cannot display arrays with more than {0} elements when multiple objects are selected.\").text;\n        static readonly GUIContent s_ArrayMultiInfoContent = new GUIContent();\n\n        static ProfilerMarker s_EvalExpressionMarker = new ProfilerMarker(\"Inspector.EvaluateMultiExpression\");\n\n        internal static bool DefaultPropertyField(Rect position, SerializedProperty property, GUIContent label)\n        {\n            label = BeginPropertyInternal(position, label, property);\n\n            SerializedPropertyType type = property.propertyType;\n\n            bool childrenAreExpanded = false;\n\n            // Should we inline? All one-line vars as well as Vector2, Vector3, Rect and Bounds properties are inlined.\n            if (!HasVisibleChildFields(property))\n            {\n                bool canUseExpression = ConstrainProportionsTransformScale.CanUseMathExpressions(property);\n                switch (type)\n                {\n                    case SerializedPropertyType.Integer:\n                    {\n                        BeginChangeCheck();\n                        NumberFieldValue val = new NumberFieldValue(property.longValue);\n                        LongField(position, label, ref val);\n                        if (EndChangeCheck() && val.hasResult)\n                        {\n                            if (val.expression != null)\n                            {\n                                using (s_EvalExpressionMarker.Auto())\n                                {\n                                    var originalValues = s_RecycledEditor.GetOriginalLongValues();\n\n                                    var values = property.allLongValues;\n                                    for (var i = 0; i < values.Length; ++i)\n                                    {\n                                        values[i] = originalValues[i];\n                                        if(canUseExpression)\n                                            val.expression.Evaluate(ref values[i], i, values.Length);\n                                    }\n                                    property.allLongValues = values;\n                                }\n                            }\n                            else\n                            {\n                                property.longValue = val.longVal;\n                            }\n                        }\n                        break;\n                    }\n                    case SerializedPropertyType.Float:\n                    {\n                        BeginChangeCheck();\n                        NumberFieldValue val = new NumberFieldValue(property.doubleValue);\n\n                        // Necessary to check for float type to get correct string formatting for float and double.\n                        bool isFloat = property.numericType == SerializedPropertyNumericType.Float;\n                        if (isFloat)\n                            FloatField(position, label, ref val);\n                        else\n                            DoubleField(position, label, ref val);\n\n                        if (EndChangeCheck() && val.hasResult)\n                        {\n                            if (val.expression != null)\n                            {\n                                using (s_EvalExpressionMarker.Auto())\n                                {\n                                    var originalValues = s_RecycledEditor.GetOriginalDoubleValues();\n\n                                    var values = property.allDoubleValues;\n                                    bool changed = false;\n                                    for (var i = 0; i < values.Length; ++i)\n                                    {\n                                        values[i] = originalValues[i];\n                                        if (canUseExpression && val.expression.Evaluate(ref values[i], i, values.Length))\n                                        {\n                                            if (isFloat)\n                                                values[i] = MathUtils.ClampToFloat(values[i]);\n\n                                            changed = true;\n                                        }\n                                    }\n\n                                    if (changed)\n                                        property.allDoubleValues = values;\n                                }\n                            }\n                            else\n                            {\n                                if (isFloat)\n                                    val.doubleVal = MathUtils.ClampToFloat(val.doubleVal);\n                                property.doubleValue = val.doubleVal;\n                            }\n                        }\n                        break;\n                    }\n                    case SerializedPropertyType.String:\n                    {\n                        BeginChangeCheck();\n                        string newValue = TextField(position, label, property.stringValue);\n                        if (EndChangeCheck())\n                        {\n                            property.stringValue = newValue;\n                        }\n                        break;\n                    }\n                    // Multi @todo: Needs style work\n                    case SerializedPropertyType.Boolean:\n                    {\n                        BeginChangeCheck();\n                        bool newValue = Toggle(position, label, property.boolValue);\n                        if (EndChangeCheck())\n                        {\n                            property.boolValue = newValue;\n                        }\n                        break;\n                    }\n                    case SerializedPropertyType.Color:\n                    {\n                        BeginChangeCheck();\n                        bool showAlpha = true;\n                        bool hdr = false;\n\n                        var propertyFieldInfo = ScriptAttributeUtility.GetFieldInfoFromProperty(property, out var propertyType);\n                        if (propertyFieldInfo != null)\n                        {\n                            var attributes = propertyFieldInfo.GetCustomAttributes<ColorUsageAttribute>(false).ToArray();\n                            if (attributes.Length > 0)\n                            {\n                                var attribute = attributes[0];\n                                showAlpha = attribute.showAlpha;\n                                hdr = attribute.hdr;\n                            }\n                        }\n\n                        Color newColor = ColorField(position, label, property.colorValue, true, showAlpha, hdr);\n                        if (EndChangeCheck())\n                        {\n                            property.colorValue = newColor;\n                        }\n                        break;\n                    }\n                    case SerializedPropertyType.ArraySize:\n                    {\n                        BeginChangeCheck();\n                        int newValue = ArraySizeField(position, label, property.intValue, EditorStyles.numberField);\n                        if (EndChangeCheck())\n                        {\n                            property.intValue = newValue;\n                        }\n                        break;\n                    }\n                    case SerializedPropertyType.FixedBufferSize:\n                    {\n                        IntField(position, label, property.intValue);\n                        break;\n                    }\n                    case SerializedPropertyType.Enum:\n                    {\n                        EnumPopup(position, property, label);\n                        break;\n                    }\n                    // Multi @todo: Needs testing for texture types\n                    case SerializedPropertyType.ObjectReference:\n                    {\n                        ObjectFieldInternal(position, property, null, label, EditorStyles.objectField);\n                        break;\n                    }\n                    case SerializedPropertyType.LayerMask:\n                    {\n                        TagManager.GetDefinedLayers(ref m_FlagNames, ref m_FlagValues);\n                        MaskFieldGUI.GetMaskButtonValue(property.intValue, m_FlagNames, m_FlagValues, out var toggleLabel, out var toggleLabelMixed);\n                        if (label != null)\n                            position = PrefixLabel(position, label, EditorStyles.label);\n\n                        var toggleLabelContent = property.hasMultipleDifferentValues ? mixedValueContent : MaskFieldGUI.DoMixedLabel(toggleLabel, toggleLabelMixed, position, EditorStyles.layerMaskField);\n                        bool toggled = DropdownButton(position, toggleLabelContent, FocusType.Keyboard, EditorStyles.layerMaskField);\n                        if (toggled)\n                        {\n                            PopupWindow.Show(position, new MaskFieldDropDown(property));\n                            GUIUtility.ExitGUI();\n                        }\n                        break;\n                    }\n                    case SerializedPropertyType.RenderingLayerMask:\n                    {\n                        RenderingLayerMaskField(position, label, property);\n                        break;\n                    }\n                    case SerializedPropertyType.Character:\n                    {\n                        char[] value = { (char)property.intValue };\n\n                        bool wasChanged = GUI.changed;\n                        GUI.changed = false;\n                        string newValue = TextField(position, label, new string(value));\n                        if (GUI.changed)\n                        {\n                            if (newValue.Length == 1)\n                            {\n                                property.intValue = newValue[0];\n                            }\n                            // Value didn't get changed after all\n                            else\n                            {\n                                GUI.changed = false;\n                            }\n                        }\n                        GUI.changed |= wasChanged;\n                        break;\n                    }\n                    case SerializedPropertyType.AnimationCurve:\n                    {\n                        int id = GUIUtility.GetControlID(s_CurveHash, FocusType.Keyboard, position);\n                        DoCurveField(PrefixLabel(position, id, label), id, null, kCurveColor, new Rect(), property);\n                        break;\n                    }\n                    case SerializedPropertyType.Gradient:\n                    {\n                        int id = GUIUtility.GetControlID(s_CurveHash, FocusType.Keyboard, position);\n                        DoGradientField(PrefixLabel(position, id, label), id, null, property, false, ColorSpace.Gamma);\n                        break;\n                    }\n                    case SerializedPropertyType.Vector3:\n                    {\n                        Vector3Field(position, property, label);\n                        break;\n                    }\n                    case SerializedPropertyType.Vector4:\n                    {\n                        Vector4Field(position, property, label);\n                        break;\n                    }\n                    case SerializedPropertyType.Vector2:\n                    {\n                        Vector2Field(position, property, label);\n                        break;\n                    }\n                    case SerializedPropertyType.Vector2Int:\n                    {\n                        Vector2IntField(position, property, label);\n                        break;\n                    }\n                    case SerializedPropertyType.Vector3Int:\n                    {\n                        Vector3IntField(position, property, label);\n                        break;\n                    }\n                    case SerializedPropertyType.Rect:\n                    {\n                        RectField(position, property, label);\n                        break;\n                    }\n                    case SerializedPropertyType.RectInt:\n                    {\n                        RectIntField(position, property, label);\n                        break;\n                    }\n                    case SerializedPropertyType.Bounds:\n                    {\n                        BoundsField(position, property, label);\n                        break;\n                    }\n                    case SerializedPropertyType.BoundsInt:\n                    {\n                        BoundsIntField(position, property, label);\n                        break;\n                    }\n                    case SerializedPropertyType.Hash128:\n                    {\n                        BeginChangeCheck();\n                        string newValue = TextField(position, label, property.hash128Value.ToString());\n                        if (EndChangeCheck())\n                        {\n                            property.hash128Value = Hash128.Parse(newValue);\n                        }\n                        break;\n                    }\n                    default:\n                    {\n                        int genericID = GUIUtility.GetControlID(s_GenericField, FocusType.Keyboard, position);\n                        PrefixLabel(position, genericID, label);\n                        break;\n                    }\n                }\n            }\n            else if (type == SerializedPropertyType.Quaternion)\n            {\n                QuaternionEulerField(position, property, label);\n            }\n            // Handle Foldout\n            else\n            {\n                Event tempEvent = new Event(Event.current);\n\n                // Handle the actual foldout first, since that's the one that supports keyboard control.\n                // This makes it work more consistent with PrefixLabel.\n                childrenAreExpanded = property.isExpanded;\n\n                bool newChildrenAreExpanded = childrenAreExpanded;\n                using (new DisabledScope(!property.editable))\n                {\n                    GUIStyle foldoutStyle = (DragAndDrop.activeControlID == -10) ? EditorStyles.foldoutPreDrop : EditorStyles.foldout;\n                    newChildrenAreExpanded = Foldout(position, childrenAreExpanded, s_PropertyFieldTempContent, true, foldoutStyle);\n                }\n\n                if (childrenAreExpanded && property.isArray && property.minArraySize > property.serializedObject.maxArraySizeForMultiEditing && property.serializedObject.isEditingMultipleObjects)\n                {\n                    Rect boxRect = position;\n                    boxRect.xMin += EditorGUIUtility.labelWidth - indent;\n\n                    s_ArrayMultiInfoContent.text = s_ArrayMultiInfoContent.tooltip = string.Format(s_ArrayMultiInfoFormatString, property.serializedObject.maxArraySizeForMultiEditing);\n                    LabelField(boxRect, GUIContent.none, s_ArrayMultiInfoContent, EditorStyles.helpBox);\n                }\n\n                if (newChildrenAreExpanded != childrenAreExpanded)\n                {\n                    // Recursive set expanded\n                    if (Event.current.alt)\n                    {\n                        SetExpandedRecurse(property, newChildrenAreExpanded);\n                    }\n                    // Expand one element only\n                    else\n                    {\n                        property.isExpanded = newChildrenAreExpanded;\n                    }\n                }\n                childrenAreExpanded = newChildrenAreExpanded;\n\n\n                // Check for drag & drop events here, to add objects to an array by dragging to the foldout.\n                // The event may have already been used by the Foldout control above, but we want to also use it here,\n                // so we use the event copy we made prior to calling the Foldout method.\n\n                // We need to use last s_LastControlID here to ensure we do not break duplicate functionality (fix for case 598389)\n                // If we called GetControlID here s_LastControlID would be incremented and would not longer be in sync with GUIUtililty.keyboardFocus that\n                // is used for duplicating (See DoPropertyFieldKeyboardHandling)\n                int id = EditorGUIUtility.s_LastControlID;\n                switch (tempEvent.type)\n                {\n                    case EventType.DragExited:\n                        if (GUI.enabled)\n                        {\n                            HandleUtility.Repaint();\n                        }\n\n                        break;\n                    case EventType.DragUpdated:\n                    case EventType.DragPerform:\n\n                        if (position.Contains(tempEvent.mousePosition) && GUI.enabled)\n                        {\n                            Object[] references = DragAndDrop.objectReferences;\n\n                            // Check each single object, so we can add multiple objects in a single drag.\n                            Object[] oArray = new Object[1];\n                            bool didAcceptDrag = false;\n                            foreach (Object o in references)\n                            {\n                                oArray[0] = o;\n                                Object validatedObject = ValidateObjectFieldAssignment(oArray, null, property, ObjectFieldValidatorOptions.None);\n                                if (validatedObject != null)\n                                {\n                                    DragAndDrop.visualMode = DragAndDropVisualMode.Copy;\n                                    if (tempEvent.type == EventType.DragPerform)\n                                    {\n                                        property.AppendFoldoutPPtrValue(validatedObject);\n                                        didAcceptDrag = true;\n                                        DragAndDrop.activeControlID = 0;\n                                    }\n                                    else\n                                    {\n                                        DragAndDrop.activeControlID = id;\n                                    }\n                                }\n                            }\n                            if (didAcceptDrag)\n                            {\n                                GUI.changed = true;\n                                DragAndDrop.AcceptDrag();\n                            }\n                        }\n                        break;\n                }\n            }\n\n            EndProperty();\n\n            return childrenAreExpanded;\n        }\n\n        internal static void DrawLegend(Rect position, Color color, string label, bool enabled)\n        {\n            position = new Rect(position.x + 2, position.y + 2, position.width - 2, position.height - 2);\n            Color oldCol = GUI.backgroundColor;\n            GUI.backgroundColor = enabled ? color : new Color(0.5f, 0.5f, 0.5f, 0.45f);\n\n            GUI.Label(position, label, \"ProfilerPaneSubLabel\");\n            GUI.backgroundColor = oldCol;\n        }\n\n        internal static string TextFieldDropDown(Rect position, string text, string[] dropDownElement)\n        {\n            return TextFieldDropDown(position, GUIContent.none, text, dropDownElement);\n        }\n\n        internal static string TextFieldDropDown(Rect position, GUIContent label, string text, string[] dropDownElement)\n        {\n            int id = GUIUtility.GetControlID(s_TextFieldDropDownHash, FocusType.Keyboard, position);\n            return DoTextFieldDropDown(PrefixLabel(position, id, label), id, text, dropDownElement, false);\n        }\n\n        internal static string DelayedTextFieldDropDown(Rect position, string text, string[] dropDownElement)\n        {\n            return DelayedTextFieldDropDown(position, GUIContent.none, text, dropDownElement);\n        }\n\n        internal static string DelayedTextFieldDropDown(Rect position, GUIContent label, string text, string[] dropDownElement)\n        {\n            int id = GUIUtility.GetControlID(s_TextFieldDropDownHash, FocusType.Keyboard, position);\n            return DoTextFieldDropDown(PrefixLabel(position, id, label), id, text, dropDownElement, true);\n        }\n\n        public static bool DropdownButton(Rect position, GUIContent content, FocusType focusType)\n        {\n            return DropdownButton(position, content, focusType, EditorStyles.miniPullDown);\n        }\n\n        public static bool DropdownButton(Rect position, GUIContent content, FocusType focusType, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_DropdownButtonHash, focusType, position);\n            return DropdownButton(id, position, content, style);\n        }\n\n        // A button that returns true on mouse down - like a popup button\n        internal static bool DropdownButton(int id, Rect position, GUIContent content, GUIStyle style)\n        {\n            Event evt = Event.current;\n            switch (evt.type)\n            {\n                case EventType.Repaint:\n                    var hovered = position.Contains(Event.current.mousePosition);\n                    if (showMixedValue)\n                    {\n                        BeginHandleMixedValueContentColor();\n                        style.Draw(position, s_MixedValueContent, id, false, hovered);\n                        EndHandleMixedValueContentColor();\n                    }\n                    else\n                        style.Draw(position, content, id, false, hovered);\n                    break;\n                case EventType.MouseDown:\n                    if (GUIUtility.HitTest(position, evt) && evt.button == 0)\n                    {\n                        GUI.GrabMouseControl(id);\n                        Event.current.Use();\n                        return true;\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUI.HasMouseControl(id))\n                    {\n                        GUI.ReleaseMouseControl();\n                        Event.current.Use();\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (GUIUtility.keyboardControl == id && evt.character == ' ')\n                    {\n                        Event.current.Use();\n                        return true;\n                    }\n                    break;\n            }\n            return false;\n        }\n\n        internal static bool isCollectingTooltips\n        {\n            get { return s_CollectingToolTips; }\n            set { s_CollectingToolTips = value; }\n        }\n\n        internal static bool s_CollectingToolTips;\n\n        internal static int AdvancedPopup(Rect rect, int selectedIndex, string[] displayedOptions)\n        {\n            return StatelessAdvancedDropdown.DoSearchablePopup(rect, selectedIndex, displayedOptions, \"MiniPullDown\");\n        }\n\n        internal static int AdvancedPopup(Rect rect, int selectedIndex, string[] displayedOptions, GUIStyle style)\n        {\n            return StatelessAdvancedDropdown.DoSearchablePopup(rect, selectedIndex, displayedOptions, style);\n        }\n\n        internal static int AdvancedLazyPopup(Rect rect, string displayedOption, int selectedIndex, Func<Tuple<int, string[]>> displayedOptionsFunc, GUIStyle style)\n        {\n            return StatelessAdvancedDropdown.DoLazySearchablePopup(rect, displayedOption, selectedIndex, displayedOptionsFunc, style);\n        }\n\n        // Draws the alpha channel of a texture within a rectangle.\n        public static void DrawTextureAlpha(Rect position, Texture image, [DefaultValue(\"ScaleMode.StretchToFill\")] ScaleMode scaleMode, [DefaultValue(\"0\")] float imageAspect, [DefaultValue(\"-1\")] float mipLevel)\n        {\n            DrawTextureAlphaInternal(position, image, scaleMode, imageAspect, mipLevel);\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawTextureAlpha(Rect position, Texture image)\n        {\n            DrawTextureAlphaInternal(position, image, ScaleMode.StretchToFill, 0, -1);\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawTextureAlpha(Rect position, Texture image, ScaleMode scaleMode)\n        {\n            DrawTextureAlphaInternal(position, image, scaleMode, 0, -1);\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawTextureAlpha(Rect position, Texture image, ScaleMode scaleMode, float imageAspect)\n        {\n            DrawTextureAlphaInternal(position, image, scaleMode, imageAspect, -1);\n        }\n\n        // Draws texture transparently using the alpha channel.\n        public static void DrawTextureTransparent(Rect position, Texture image, [DefaultValue(\"ScaleMode.StretchToFill\")] ScaleMode scaleMode, [DefaultValue(\"0\")] float imageAspect, [DefaultValue(\"-1\")] float mipLevel, [DefaultValue(\"ColorWriteMask.All\")] ColorWriteMask colorWriteMask, [DefaultValue(\"0\")] float exposure)\n        {\n            DrawTextureTransparentInternal(position, image, scaleMode, imageAspect, mipLevel, colorWriteMask, exposure);\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawTextureTransparent(Rect position, Texture image, ScaleMode scaleMode)\n        {\n            DrawTextureTransparent(position, image, scaleMode, 0);\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawTextureTransparent(Rect position, Texture image)\n        {\n            DrawTextureTransparent(position, image, ScaleMode.StretchToFill, 0);\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawTextureTransparent(Rect position, Texture image, ScaleMode scaleMode, float imageAspect)\n        {\n            DrawTextureTransparent(position, image, scaleMode, imageAspect, -1);\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawTextureTransparent(Rect position, Texture image, ScaleMode scaleMode, float imageAspect, float mipLevel)\n        {\n            DrawTextureTransparent(position, image, scaleMode, imageAspect, mipLevel, ColorWriteMask.All);\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawTextureTransparent(Rect position, Texture image, ScaleMode scaleMode, float imageAspect, float mipLevel, ColorWriteMask colorWriteMask)\n        {\n            DrawTextureTransparent(position, image, scaleMode, imageAspect, mipLevel, colorWriteMask, 0);\n        }\n\n        // Draws the texture within a rectangle.\n        public static void DrawPreviewTexture(Rect position, Texture image, [DefaultValue(\"null\")] Material mat, [DefaultValue(\"ScaleMode.StretchToFill\")] ScaleMode scaleMode,\n            [DefaultValue(\"0\")] float imageAspect, [DefaultValue(\"-1\")] float mipLevel, [DefaultValue(\"ColorWriteMask.All\")] ColorWriteMask colorWriteMask, [DefaultValue(\"0\")] float exposure)\n        {\n            DrawPreviewTextureInternal(position, image, mat, scaleMode, imageAspect, mipLevel, colorWriteMask, exposure);\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawPreviewTexture(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect, float mipLevel, ColorWriteMask colorWriteMask)\n        {\n            DrawPreviewTexture(position, image, mat, scaleMode, imageAspect, mipLevel, colorWriteMask, 0);\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawPreviewTexture(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect, float mipLevel)\n        {\n            DrawPreviewTexture(position, image, mat, scaleMode, imageAspect, mipLevel, ColorWriteMask.All);\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawPreviewTexture(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect)\n        {\n            DrawPreviewTexture(position, image, mat, scaleMode, imageAspect, -1);\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawPreviewTexture(Rect position, Texture image, Material mat, ScaleMode scaleMode)\n        {\n            DrawPreviewTexture(position, image, mat, scaleMode, 0);\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawPreviewTexture(Rect position, Texture image, Material mat)\n        {\n            DrawPreviewTexture(position, image, mat, ScaleMode.StretchToFill, 0);\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawPreviewTexture(Rect position, Texture image)\n        {\n            DrawPreviewTexture(position, image, null, ScaleMode.StretchToFill, 0);\n        }\n\n        [ExcludeFromDocs]\n        public static void LabelField(Rect position, string label)\n        {\n            LabelField(position, label, EditorStyles.label);\n        }\n\n        public static void LabelField(Rect position, string label, [DefaultValue(\"EditorStyles.label\")] GUIStyle style)\n        {\n            LabelField(position, GUIContent.none, EditorGUIUtility.TempContent(label), style);\n        }\n\n        [ExcludeFromDocs]\n        public static void LabelField(Rect position, GUIContent label)\n        {\n            LabelField(position, label, EditorStyles.label);\n        }\n\n        public static void LabelField(Rect position, GUIContent label, [DefaultValue(\"EditorStyles.label\")] GUIStyle style)\n        {\n            LabelField(position, GUIContent.none, label, style);\n        }\n\n        [ExcludeFromDocs]\n        public static void LabelField(Rect position, string label, string label2)\n        {\n            LabelField(position, label, label2, EditorStyles.label);\n        }\n\n        public static void LabelField(Rect position, string label, string label2, [DefaultValue(\"EditorStyles.label\")] GUIStyle style)\n        {\n            LabelField(position, new GUIContent(label), EditorGUIUtility.TempContent(label2), style);\n        }\n\n        [ExcludeFromDocs]\n        public static void LabelField(Rect position, GUIContent label, GUIContent label2)\n        {\n            LabelField(position, label, label2, EditorStyles.label);\n        }\n\n        public static void LabelField(Rect position, GUIContent label, GUIContent label2, [DefaultValue(\"EditorStyles.label\")] GUIStyle style)\n        {\n            LabelFieldInternal(position, label, label2, style);\n        }\n\n        public static bool LinkButton(Rect position, string label)\n        {\n            return LinkButton(position, EditorGUIUtility.TempContent(label));\n        }\n\n        public static bool LinkButton(Rect position, GUIContent label)\n        {\n            Handles.color = EditorStyles.linkLabel.normal.textColor;\n            Handles.DrawLine(new Vector3(position.xMin + EditorStyles.linkLabel.padding.left, position.yMax), new Vector3(position.xMax - EditorStyles.linkLabel.padding.right, position.yMax));\n            Handles.color = Color.white;\n\n            EditorGUIUtility.AddCursorRect(position, MouseCursor.Link);\n\n            return GUI.Button(position, label, EditorStyles.linkLabel);\n        }\n\n        [ExcludeFromDocs]\n        public static bool ToggleLeft(Rect position, string label, bool value)\n        {\n            GUIStyle labelStyle = EditorStyles.label;\n            return ToggleLeft(position, label, value, labelStyle);\n        }\n\n        public static bool ToggleLeft(Rect position, string label, bool value, [DefaultValue(\"EditorStyles.label\")] GUIStyle labelStyle)\n        {\n            return ToggleLeft(position, EditorGUIUtility.TempContent(label), value, labelStyle);\n        }\n\n        [ExcludeFromDocs]\n        public static bool ToggleLeft(Rect position, GUIContent label, bool value)\n        {\n            return ToggleLeft(position, label, value, EditorStyles.label);\n        }\n\n        public static bool ToggleLeft(Rect position, GUIContent label, bool value, [DefaultValue(\"EditorStyles.label\")] GUIStyle labelStyle)\n        {\n            return ToggleLeftInternal(position, label, value, labelStyle);\n        }\n\n        [ExcludeFromDocs]\n        public static string TextField(Rect position, string text)\n        {\n            return TextField(position, text, EditorStyles.textField);\n        }\n\n        public static string TextField(Rect position, string text, [DefaultValue(\"EditorStyles.textField\")] GUIStyle style)\n        {\n            return TextFieldInternal(position, text, style);\n        }\n\n        [ExcludeFromDocs]\n        public static string TextField(Rect position, string label, string text)\n        {\n            return TextField(position, label, text, EditorStyles.textField);\n        }\n\n        public static string TextField(Rect position, string label, string text, [DefaultValue(\"EditorStyles.textField\")] GUIStyle style)\n        {\n            return TextField(position, EditorGUIUtility.TempContent(label), text, style);\n        }\n\n        [ExcludeFromDocs]\n        public static string TextField(Rect position, GUIContent label, string text)\n        {\n            return TextField(position, label, text, EditorStyles.textField);\n        }\n\n        public static string TextField(Rect position, GUIContent label, string text, [DefaultValue(\"EditorStyles.textField\")] GUIStyle style)\n        {\n            return TextFieldInternal(position, label, text, style);\n        }\n\n        [ExcludeFromDocs]\n        public static string DelayedTextField(Rect position, string text)\n        {\n            return DelayedTextField(position, text, EditorStyles.textField);\n        }\n\n        public static string DelayedTextField(Rect position, string text, [DefaultValue(\"EditorStyles.textField\")] GUIStyle style)\n        {\n            return DelayedTextField(position, GUIContent.none, text, style);\n        }\n\n        [ExcludeFromDocs]\n        public static string DelayedTextField(Rect position, string label, string text)\n        {\n            return DelayedTextField(position, label, text, EditorStyles.textField);\n        }\n\n        public static string DelayedTextField(Rect position, string label, string text, [DefaultValue(\"EditorStyles.textField\")] GUIStyle style)\n        {\n            return DelayedTextField(position, EditorGUIUtility.TempContent(label), text, style);\n        }\n\n        [ExcludeFromDocs]\n        public static string DelayedTextField(Rect position, GUIContent label, string text)\n        {\n            return DelayedTextField(position, label, text, EditorStyles.textField);\n        }\n\n        public static string DelayedTextField(Rect position, GUIContent label, string text, [DefaultValue(\"EditorStyles.textField\")] GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, position);\n            return DelayedTextFieldInternal(position, id, label, text, null, style);\n        }\n\n        [ExcludeFromDocs]\n        public static void DelayedTextField(Rect position, SerializedProperty property)\n        {\n            DelayedTextField(position, property, null);\n        }\n\n        public static void DelayedTextField(Rect position, SerializedProperty property, [DefaultValue(\"null\")] GUIContent label)\n        {\n            DelayedTextFieldHelper(position, property, label, EditorStyles.textField);\n        }\n\n        internal static void DelayedTextFieldHelper(Rect position, SerializedProperty property, GUIContent label, GUIStyle style)\n        {\n            int id = GUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, position);\n            DelayedTextFieldInternal(position, id, property, null, label, style);\n        }\n\n        [ExcludeFromDocs]\n        public static string DelayedTextField(Rect position, GUIContent label, int controlId, string text)\n        {\n            return DelayedTextField(position, label, controlId, text, EditorStyles.textField);\n        }\n\n        public static string DelayedTextField(Rect position, GUIContent label, int controlId, string text, [DefaultValue(\"EditorStyles.textField\")] GUIStyle style)\n        {\n            return DelayedTextFieldInternal(position, controlId, label, text, null, style);\n        }\n\n        [ExcludeFromDocs]\n        public static string TextArea(Rect position, string text)\n        {\n            return TextArea(position, text, EditorStyles.textField);\n        }\n\n        public static string TextArea(Rect position, string text, [DefaultValue(\"EditorStyles.textField\")] GUIStyle style)\n        {\n            return TextAreaInternal(position, text, style);\n        }\n\n        [ExcludeFromDocs]\n        public static void SelectableLabel(Rect position, string text)\n        {\n            SelectableLabel(position, text, EditorStyles.label);\n        }\n\n        public static void SelectableLabel(Rect position, string text, [DefaultValue(\"EditorStyles.label\")] GUIStyle style)\n        {\n            SelectableLabelInternal(position, text, style);\n        }\n\n        [ExcludeFromDocs]\n        public static string PasswordField(Rect position, string password)\n        {\n            return PasswordField(position, password, EditorStyles.textField);\n        }\n\n        public static string PasswordField(Rect position, string password, [DefaultValue(\"EditorStyles.textField\")] GUIStyle style)\n        {\n            return PasswordFieldInternal(position, password, style);\n        }\n\n        [ExcludeFromDocs]\n        public static string PasswordField(Rect position, string label, string password)\n        {\n            return PasswordField(position, label, password, EditorStyles.textField);\n        }\n\n        public static string PasswordField(Rect position, string label, string password, [DefaultValue(\"EditorStyles.textField\")] GUIStyle style)\n        {\n            return PasswordField(position, EditorGUIUtility.TempContent(label), password, style);\n        }\n\n        [ExcludeFromDocs]\n        public static string PasswordField(Rect position, GUIContent label, string password)\n        {\n            return PasswordField(position, label, password, EditorStyles.textField);\n        }\n\n        public static string PasswordField(Rect position, GUIContent label, string password, [DefaultValue(\"EditorStyles.textField\")] GUIStyle style)\n        {\n            return PasswordFieldInternal(position, label, password, style);\n        }\n\n        [ExcludeFromDocs]\n        public static float FloatField(Rect position, float value)\n        {\n            return FloatField(position, value, EditorStyles.numberField);\n        }\n\n        public static float FloatField(Rect position, float value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return FloatFieldInternal(position, value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static float FloatField(Rect position, string label, float value)\n        {\n            return FloatField(position, label, value, EditorStyles.numberField);\n        }\n\n        public static float FloatField(Rect position, string label, float value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return FloatField(position, EditorGUIUtility.TempContent(label), value, style);\n        }\n\n        internal static void FloatField(Rect position, GUIContent label, ref NumberFieldValue value)\n        {\n            FloatFieldInternal(position, label, ref value, EditorStyles.numberField);\n        }\n\n        [ExcludeFromDocs]\n        public static float FloatField(Rect position, GUIContent label, float value)\n        {\n            return FloatField(position, label, value, EditorStyles.numberField);\n        }\n\n        public static float FloatField(Rect position, GUIContent label, float value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return FloatFieldInternal(position, label, value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static float DelayedFloatField(Rect position, float value)\n        {\n            return DelayedFloatField(position, value, EditorStyles.numberField);\n        }\n\n        public static float DelayedFloatField(Rect position, float value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return DelayedFloatField(position, GUIContent.none, value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static float DelayedFloatField(Rect position, string label, float value)\n        {\n            return DelayedFloatField(position, label, value, EditorStyles.numberField);\n        }\n\n        public static float DelayedFloatField(Rect position, string label, float value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return DelayedFloatField(position, EditorGUIUtility.TempContent(label), value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static float DelayedFloatField(Rect position, GUIContent label, float value)\n        {\n            return DelayedFloatField(position, label, value, EditorStyles.numberField);\n        }\n\n        public static float DelayedFloatField(Rect position, GUIContent label, float value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return DelayedFloatFieldInternal(position, label, value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static void DelayedFloatField(Rect position, SerializedProperty property)\n        {\n            DelayedFloatField(position, property, null);\n        }\n\n        public static void DelayedFloatField(Rect position, SerializedProperty property, [DefaultValue(\"null\")] GUIContent label)\n        {\n            DelayedFloatFieldInternal(position, property, label);\n        }\n\n        [ExcludeFromDocs]\n        public static double DoubleField(Rect position, double value)\n        {\n            return DoubleField(position, value, EditorStyles.numberField);\n        }\n\n        public static double DoubleField(Rect position, double value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return DoubleFieldInternal(position, value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static double DoubleField(Rect position, string label, double value)\n        {\n            return DoubleField(position, label, value, EditorStyles.numberField);\n        }\n\n        public static double DoubleField(Rect position, string label, double value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return DoubleField(position, EditorGUIUtility.TempContent(label), value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static double DoubleField(Rect position, GUIContent label, double value)\n        {\n            return DoubleField(position, label, value, EditorStyles.numberField);\n        }\n\n        public static double DoubleField(Rect position, GUIContent label, double value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return DoubleFieldInternal(position, label, value, style);\n        }\n\n        static void DoubleField(Rect position, GUIContent label, ref NumberFieldValue value)\n        {\n            DoubleFieldInternal(position, label, ref value, EditorStyles.numberField);\n        }\n\n        [ExcludeFromDocs]\n        public static double DelayedDoubleField(Rect position, double value)\n        {\n            return DelayedDoubleField(position, value, EditorStyles.numberField);\n        }\n\n        public static double DelayedDoubleField(Rect position, double value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return DelayedDoubleFieldInternal(position, null, value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static double DelayedDoubleField(Rect position, string label, double value)\n        {\n            return DelayedDoubleField(position, label, value, EditorStyles.numberField);\n        }\n\n        public static double DelayedDoubleField(Rect position, string label, double value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return DelayedDoubleField(position, EditorGUIUtility.TempContent(label), value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static double DelayedDoubleField(Rect position, GUIContent label, double value)\n        {\n            return DelayedDoubleField(position, label, value, EditorStyles.numberField);\n        }\n\n        public static double DelayedDoubleField(Rect position, GUIContent label, double value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return DelayedDoubleFieldInternal(position, label, value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int IntField(Rect position, int value)\n        {\n            return IntField(position, value, EditorStyles.numberField);\n        }\n\n        public static int IntField(Rect position, int value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return IntFieldInternal(position, value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int IntField(Rect position, string label, int value)\n        {\n            return IntField(position, label, value, EditorStyles.numberField);\n        }\n\n        public static int IntField(Rect position, string label, int value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return IntField(position, EditorGUIUtility.TempContent(label), value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int IntField(Rect position, GUIContent label, int value)\n        {\n            return IntField(position, label, value, EditorStyles.numberField);\n        }\n\n        public static int IntField(Rect position, GUIContent label, int value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return IntFieldInternal(position, label, value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int DelayedIntField(Rect position, int value)\n        {\n            return DelayedIntField(position, value, EditorStyles.numberField);\n        }\n\n        public static int DelayedIntField(Rect position, int value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return DelayedIntField(position, GUIContent.none, value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int DelayedIntField(Rect position, string label, int value)\n        {\n            return DelayedIntField(position, label, value, EditorStyles.numberField);\n        }\n\n        public static int DelayedIntField(Rect position, string label, int value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return DelayedIntField(position, EditorGUIUtility.TempContent(label), value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int DelayedIntField(Rect position, GUIContent label, int value)\n        {\n            return DelayedIntField(position, label, value, EditorStyles.numberField);\n        }\n\n        public static int DelayedIntField(Rect position, GUIContent label, int value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return DelayedIntFieldInternal(position, label, value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static void DelayedIntField(Rect position, SerializedProperty property)\n        {\n            DelayedIntField(position, property, null);\n        }\n\n        public static void DelayedIntField(Rect position, SerializedProperty property, [DefaultValue(\"null\")] GUIContent label)\n        {\n            DelayedIntFieldInternal(position, property, label);\n        }\n\n        [ExcludeFromDocs]\n        public static long LongField(Rect position, long value)\n        {\n            return LongField(position, value, EditorStyles.numberField);\n        }\n\n        public static long LongField(Rect position, long value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return LongFieldInternal(position, value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static long LongField(Rect position, string label, long value)\n        {\n            return LongField(position, label, value, EditorStyles.numberField);\n        }\n\n        public static long LongField(Rect position, string label, long value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return LongField(position, EditorGUIUtility.TempContent(label), value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static long LongField(Rect position, GUIContent label, long value)\n        {\n            return LongField(position, label, value, EditorStyles.numberField);\n        }\n\n        static void LongField(Rect position, GUIContent label, ref NumberFieldValue value)\n        {\n            LongFieldInternal(position, label, ref value, EditorStyles.numberField);\n        }\n\n        public static long LongField(Rect position, GUIContent label, long value, [DefaultValue(\"EditorStyles.numberField\")] GUIStyle style)\n        {\n            return LongFieldInternal(position, label, value, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int Popup(Rect position, int selectedIndex, string[] displayedOptions)\n        {\n            return Popup(position, selectedIndex, displayedOptions, EditorStyles.popup);\n        }\n\n        public static int Popup(Rect position, int selectedIndex, string[] displayedOptions, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return DoPopup(IndentedRect(position), GUIUtility.GetControlID(s_PopupHash, FocusType.Keyboard, position), selectedIndex, EditorGUIUtility.TempContent(displayedOptions), style);\n        }\n\n        [ExcludeFromDocs]\n        public static int Popup(Rect position, int selectedIndex, GUIContent[] displayedOptions)\n        {\n            return Popup(position, selectedIndex, displayedOptions, EditorStyles.popup);\n        }\n\n        public static int Popup(Rect position, int selectedIndex, GUIContent[] displayedOptions, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return DoPopup(IndentedRect(position), GUIUtility.GetControlID(s_PopupHash, FocusType.Keyboard, position), selectedIndex, displayedOptions, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int Popup(Rect position, string label, int selectedIndex, string[] displayedOptions)\n        {\n            return Popup(position, label, selectedIndex, displayedOptions, EditorStyles.popup);\n        }\n\n        public static int Popup(Rect position, string label, int selectedIndex, string[] displayedOptions, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return PopupInternal(position, EditorGUIUtility.TempContent(label), selectedIndex, EditorGUIUtility.TempContent(displayedOptions), style);\n        }\n\n        [ExcludeFromDocs]\n        public static int Popup(Rect position, GUIContent label, int selectedIndex, GUIContent[] displayedOptions)\n        {\n            return Popup(position, label, selectedIndex, displayedOptions, EditorStyles.popup);\n        }\n\n        public static int Popup(Rect position, GUIContent label, int selectedIndex, GUIContent[] displayedOptions, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return PopupInternal(position, label, selectedIndex, displayedOptions, style);\n        }\n\n        [ExcludeFromDocs]\n        public static Enum EnumPopup(Rect position, Enum selected)\n        {\n            return EnumPopup(position, selected, EditorStyles.popup);\n        }\n\n        public static Enum EnumPopup(Rect position, Enum selected, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return EnumPopup(position, GUIContent.none, selected, style);\n        }\n\n        [ExcludeFromDocs]\n        public static Enum EnumPopup(Rect position, string label, Enum selected)\n        {\n            return EnumPopup(position, label, selected, EditorStyles.popup);\n        }\n\n        public static Enum EnumPopup(Rect position, string label, Enum selected, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return EnumPopup(position, EditorGUIUtility.TempContent(label), selected, style);\n        }\n\n        [ExcludeFromDocs]\n        public static Enum EnumPopup(Rect position, GUIContent label, Enum selected)\n        {\n            return EnumPopup(position, label, selected, EditorStyles.popup);\n        }\n\n        public static Enum EnumPopup(Rect position, GUIContent label, Enum selected, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return EnumPopupInternal(position, label, selected, null, false, style);\n        }\n\n        public static Enum EnumPopup(Rect position, GUIContent label, Enum selected, [DefaultValue(\"null\")] Func<Enum, bool> checkEnabled, [DefaultValue(\"false\")] bool includeObsolete = false, [DefaultValue(\"null\")] GUIStyle style = null)\n        {\n            return EnumPopupInternal(position, label, selected, checkEnabled, includeObsolete, style ?? EditorStyles.popup);\n        }\n\n        private static void EnumPopup(Rect position, SerializedProperty property, GUIContent label)\n        {\n            Type type;\n            ScriptAttributeUtility.GetFieldInfoFromProperty(property, out type);\n            if (type != null && type.IsEnum)\n            {\n                BeginChangeCheck();\n                int value = EnumNamesCache.IsEnumTypeUsingFlagsAttribute(type)\n                    ? EnumFlagsField(position, label, property.intValue, type, false, EditorStyles.popup)\n                    : EnumPopupInternal(position, label, property.intValue, type, null, false, EditorStyles.popup);\n                if (EndChangeCheck())\n                {\n                    // When the flag is a negative we need to convert it or it will be clamped.\n                    Type enumType = type.GetEnumUnderlyingType();\n                    if (value < 0 && (enumType == typeof(uint) || enumType == typeof(ushort) || enumType == typeof(byte)))\n                    {\n                        property.longValue = (uint)value;\n                    }\n                    else\n                    {\n                        property.intValue = value;\n                    }\n                }\n            }\n            else\n            {\n                BeginChangeCheck();\n                int idx = Popup(position, label, property.enumValueIndex, EnumNamesCache.GetEnumLocalizedGUIContents(property));\n                if (EndChangeCheck())\n                {\n                    property.enumValueIndex = idx;\n                }\n            }\n        }\n\n        [ExcludeFromDocs]\n        public static int IntPopup(Rect position, int selectedValue, string[] displayedOptions, int[] optionValues)\n        {\n            return IntPopup(position, selectedValue, displayedOptions, optionValues, EditorStyles.popup);\n        }\n\n        public static int IntPopup(Rect position, int selectedValue, string[] displayedOptions, int[] optionValues, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return IntPopup(position, GUIContent.none, selectedValue, EditorGUIUtility.TempContent(displayedOptions), optionValues, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int IntPopup(Rect position, int selectedValue, GUIContent[] displayedOptions, int[] optionValues)\n        {\n            return IntPopup(position, selectedValue, displayedOptions, optionValues, EditorStyles.popup);\n        }\n\n        public static int IntPopup(Rect position, int selectedValue, GUIContent[] displayedOptions, int[] optionValues, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return IntPopup(position, GUIContent.none, selectedValue, displayedOptions, optionValues, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int IntPopup(Rect position, GUIContent label, int selectedValue, GUIContent[] displayedOptions, int[] optionValues)\n        {\n            return IntPopup(position, label, selectedValue, displayedOptions, optionValues, EditorStyles.popup);\n        }\n\n        public static int IntPopup(Rect position, GUIContent label, int selectedValue, GUIContent[] displayedOptions, int[] optionValues, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return IntPopupInternal(position, label, selectedValue, displayedOptions, optionValues, style);\n        }\n\n        [ExcludeFromDocs]\n        public static void IntPopup(Rect position, SerializedProperty property, GUIContent[] displayedOptions, int[] optionValues)\n        {\n            IntPopup(position, property, displayedOptions, optionValues, null);\n        }\n\n        public static void IntPopup(Rect position, SerializedProperty property, GUIContent[] displayedOptions, int[] optionValues, [DefaultValue(\"null\")] GUIContent label)\n        {\n            IntPopupInternal(position, property, displayedOptions, optionValues, label);\n        }\n\n        [ExcludeFromDocs]\n        public static int IntPopup(Rect position, string label, int selectedValue, string[] displayedOptions, int[] optionValues)\n        {\n            return IntPopup(position, label, selectedValue, displayedOptions, optionValues, EditorStyles.popup);\n        }\n\n        public static int IntPopup(Rect position, string label, int selectedValue, string[] displayedOptions, int[] optionValues, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return IntPopupInternal(position, EditorGUIUtility.TempContent(label), selectedValue, EditorGUIUtility.TempContent(displayedOptions), optionValues, style);\n        }\n\n        [ExcludeFromDocs]\n        public static string TagField(Rect position, string tag)\n        {\n            return TagField(position, tag, EditorStyles.popup);\n        }\n\n        public static string TagField(Rect position, string tag, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return TagFieldInternal(position, EditorGUIUtility.TempContent(string.Empty), tag, style);\n        }\n\n        [ExcludeFromDocs]\n        public static string TagField(Rect position, string label, string tag)\n        {\n            return TagField(position, label, tag, EditorStyles.popup);\n        }\n\n        public static string TagField(Rect position, string label, string tag, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return TagFieldInternal(position, EditorGUIUtility.TempContent(label), tag, style);\n        }\n\n        [ExcludeFromDocs]\n        public static string TagField(Rect position, GUIContent label, string tag)\n        {\n            return TagField(position, label, tag, EditorStyles.popup);\n        }\n\n        public static string TagField(Rect position, GUIContent label, string tag, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return TagFieldInternal(position, label, tag, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int LayerField(Rect position, int layer)\n        {\n            return LayerField(position, layer, EditorStyles.popup);\n        }\n\n        public static int LayerField(Rect position, int layer, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return LayerFieldInternal(position, GUIContent.none, layer, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int LayerField(Rect position, string label, int layer)\n        {\n            return LayerField(position, label, layer, EditorStyles.popup);\n        }\n\n        public static int LayerField(Rect position, string label, int layer, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return LayerFieldInternal(position, EditorGUIUtility.TempContent(label), layer, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int LayerField(Rect position, GUIContent label, int layer)\n        {\n            return LayerField(position, label, layer, EditorStyles.popup);\n        }\n\n        public static int LayerField(Rect position, GUIContent label, int layer, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return LayerFieldInternal(position, label, layer, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int MaskField(Rect position, GUIContent label, int mask, string[] displayedOptions)\n        {\n            return MaskField(position, label, mask, displayedOptions, EditorStyles.popup);\n        }\n\n        public static int MaskField(Rect position, GUIContent label, int mask, string[] displayedOptions, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return MaskFieldInternal(position, label, mask, displayedOptions, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int MaskField(Rect position, string label, int mask, string[] displayedOptions)\n        {\n            return MaskField(position, label, mask, displayedOptions, EditorStyles.popup);\n        }\n\n        public static int MaskField(Rect position, string label, int mask, string[] displayedOptions, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return MaskFieldInternal(position, GUIContent.Temp(label), mask, displayedOptions, style);\n        }\n\n        [ExcludeFromDocs]\n        public static int MaskField(Rect position, int mask, string[] displayedOptions)\n        {\n            return MaskField(position, mask, displayedOptions, EditorStyles.popup);\n        }\n\n        public static int MaskField(Rect position, int mask, string[] displayedOptions, [DefaultValue(\"EditorStyles.popup\")] GUIStyle style)\n        {\n            return MaskFieldInternal(position, mask, displayedOptions, style);\n        }\n\n        [ExcludeFromDocs]\n        public static bool Foldout(Rect position, bool foldout, string content)\n        {\n            return Foldout(position, foldout, content, EditorStyles.foldout);\n        }\n\n        public static bool Foldout(Rect position, bool foldout, string content, [DefaultValue(\"EditorStyles.foldout\")] GUIStyle style)\n        {\n            return FoldoutInternal(position, foldout, EditorGUIUtility.TempContent(content), false, style);\n        }\n\n        [ExcludeFromDocs]\n        public static bool Foldout(Rect position, bool foldout, string content, bool toggleOnLabelClick)\n        {\n            return Foldout(position, foldout, content, toggleOnLabelClick, EditorStyles.foldout);\n        }\n\n        public static bool Foldout(Rect position, bool foldout, string content, bool toggleOnLabelClick, [DefaultValue(\"EditorStyles.foldout\")] GUIStyle style)\n        {\n            return FoldoutInternal(position, foldout, EditorGUIUtility.TempContent(content), toggleOnLabelClick, style);\n        }\n\n        [ExcludeFromDocs]\n        public static bool Foldout(Rect position, bool foldout, GUIContent content)\n        {\n            return Foldout(position, foldout, content, EditorStyles.foldout);\n        }\n\n        public static bool Foldout(Rect position, bool foldout, GUIContent content, [DefaultValue(\"EditorStyles.foldout\")] GUIStyle style)\n        {\n            return FoldoutInternal(position, foldout, content, false, style);\n        }\n\n        [ExcludeFromDocs]\n        public static bool Foldout(Rect position, bool foldout, GUIContent content, bool toggleOnLabelClick)\n        {\n            return Foldout(position, foldout, content, toggleOnLabelClick, EditorStyles.foldout);\n        }\n\n        public static bool Foldout(Rect position, bool foldout, GUIContent content, bool toggleOnLabelClick, [DefaultValue(\"EditorStyles.foldout\")] GUIStyle style)\n        {\n            return FoldoutInternal(position, foldout, content, toggleOnLabelClick, style);\n        }\n\n        [ExcludeFromDocs]\n        public static void HandlePrefixLabel(Rect totalPosition, Rect labelPosition, GUIContent label, int id)\n        {\n            HandlePrefixLabel(totalPosition, labelPosition, label, id, EditorStyles.label);\n        }\n\n        [ExcludeFromDocs]\n        public static void HandlePrefixLabel(Rect totalPosition, Rect labelPosition, GUIContent label)\n        {\n            HandlePrefixLabel(totalPosition, labelPosition, label, 0, EditorStyles.label);\n        }\n\n        internal static float CalcPrefixLabelWidth(GUIContent label, GUIStyle style = null)\n        {\n            if (style == null)\n                style = EditorStyles.label;\n            return style.CalcSize(label).x;\n        }\n\n        public static void HandlePrefixLabel(Rect totalPosition, Rect labelPosition, GUIContent label, [DefaultValue(\"0\")] int id, [DefaultValue(\"EditorStyles.label\")] GUIStyle style)\n        {\n            HandlePrefixLabelInternal(totalPosition, labelPosition, label, id, style);\n        }\n\n        public static float GetPropertyHeight(SerializedProperty property, bool includeChildren)\n        {\n            return GetPropertyHeightInternal(property, null, includeChildren);\n        }\n\n        [ExcludeFromDocs]\n        public static float GetPropertyHeight(SerializedProperty property, GUIContent label)\n        {\n            return GetPropertyHeight(property, label, true);\n        }\n\n        [ExcludeFromDocs]\n        public static float GetPropertyHeight(SerializedProperty property)\n        {\n            return GetPropertyHeight(property, null, true);\n        }\n\n        public static float GetPropertyHeight(SerializedProperty property, [DefaultValue(\"null\")] GUIContent label, [DefaultValue(\"true\")] bool includeChildren)\n        {\n            return GetPropertyHeightInternal(property, label, includeChildren);\n        }\n\n        [ExcludeFromDocs]\n        public static bool PropertyField(Rect position, SerializedProperty property)\n        {\n            // Allow reorderable list to include children by default to keep similar behaviour to old arrays\n            return PropertyField(position, property, PropertyHandler.UseReorderabelListControl(property));\n        }\n\n        public static bool PropertyField(Rect position, SerializedProperty property, [DefaultValue(\"false\")] bool includeChildren)\n        {\n            return PropertyFieldInternal(position, property, null, includeChildren);\n        }\n\n        [ExcludeFromDocs]\n        public static bool PropertyField(Rect position, SerializedProperty property, GUIContent label)\n        {\n            // Allow reorderable list to include children by default to keep similar behaviour to old arrays\n            return PropertyField(position, property, label, PropertyHandler.UseReorderabelListControl(property));\n        }\n\n        public static bool PropertyField(Rect position, SerializedProperty property, GUIContent label, [DefaultValue(\"false\")] bool includeChildren)\n        {\n            return PropertyFieldInternal(position, property, label, includeChildren);\n        }\n\n        internal static class EnumNamesCache\n        {\n            static Dictionary<Type, GUIContent[]> s_EnumTypeLocalizedGUIContents = new Dictionary<Type, GUIContent[]>();\n            static Dictionary<int, GUIContent[]> s_SerializedPropertyEnumLocalizedGUIContents = new Dictionary<int, GUIContent[]>();\n            static Dictionary<Type, bool> s_IsEnumTypeUsingFlagsAttribute = new Dictionary<Type, bool>();\n            static Dictionary<Type, string[]> s_SerializedPropertyEnumDisplayNames = new Dictionary<Type, string[]>();\n            static Dictionary<Type, string[]> s_SerializedPropertyEnumNames = new Dictionary<Type, string[]>();\n\n            internal static GUIContent[] GetEnumTypeLocalizedGUIContents(Type enumType, EnumData enumData)\n            {\n                GUIContent[] result;\n                if (s_EnumTypeLocalizedGUIContents.TryGetValue(enumType, out result))\n                {\n                    return result;\n                }\n                else\n                {\n                    // Build localized data and add to cache\n                    using (new LocalizationGroup(enumType))\n                    {\n                        UnityEngine.EnumDataUtility.HandleInspectorOrderAttribute(enumType, ref enumData);\n                        result = EditorGUIUtility.TrTempContent(enumData.displayNames, enumData.tooltip);\n                        s_EnumTypeLocalizedGUIContents[enumType] = result;\n                        return result;\n                    }\n                }\n            }\n\n            internal static GUIContent[] GetEnumLocalizedGUIContents(SerializedProperty property)\n            {\n                if (property.serializedObject.targetObject == null)\n                    return EditorGUIUtility.TempContent(property.enumLocalizedDisplayNames);\n\n                var propertyHash = property.hashCodeForPropertyPathWithoutArrayIndex;\n                var typeHash = property.serializedObject.targetObject.GetType().GetHashCode();\n                var hashCode = typeHash ^ propertyHash;\n                GUIContent[] result;\n\n                if (s_SerializedPropertyEnumLocalizedGUIContents.TryGetValue(hashCode, out result))\n                {\n                    return result;\n                }\n\n                result = EditorGUIUtility.TempContent(property.enumLocalizedDisplayNames);\n                s_SerializedPropertyEnumLocalizedGUIContents[hashCode] = result;\n                return result;\n            }\n\n            internal static string[] GetEnumDisplayNames(SerializedProperty property)\n            {\n                Type enumType;\n                ScriptAttributeUtility.GetFieldInfoFromProperty(property, out enumType);\n\n                // For native properties, like Camera.m_ClearFlags, the enumType returned will be null.\n                // So we can't use it for the dict key below. Need to early out.\n                // Case: 1388694\n                if (enumType == null)\n                    return property.enumDisplayNames;\n\n                string[] result;\n                if (!s_SerializedPropertyEnumDisplayNames.TryGetValue(enumType, out result))\n                {\n                    result = property.enumDisplayNames;\n                    s_SerializedPropertyEnumDisplayNames.Add(enumType, result);\n                }\n                return result;\n            }\n\n            internal static string[] GetEnumNames(SerializedProperty property)\n            {\n                Type enumType;\n                ScriptAttributeUtility.GetFieldInfoFromProperty(property, out enumType);\n\n                string[] result;\n                if (!s_SerializedPropertyEnumNames.TryGetValue(enumType, out result))\n                {\n                    result = property.enumNames;\n                    s_SerializedPropertyEnumNames.Add(enumType, result);\n                }\n                return result;\n            }\n\n            internal static bool IsEnumTypeUsingFlagsAttribute(Type type)\n            {\n                bool result;\n                if (s_IsEnumTypeUsingFlagsAttribute.TryGetValue(type, out result))\n                    return result;\n\n                // GetCustomAttributes allocates a new List on every call so we cache the result\n                result = type.GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0;\n                s_IsEnumTypeUsingFlagsAttribute[type] = result;\n                return result;\n            }\n        }\n\n        static class HelpButtonCache\n        {\n            static Dictionary<Type, bool> s_TypeIsPartOfTargetAssembliesMap = new Dictionary<Type, bool>();\n            static Dictionary<Type, bool> s_ObjectHasHelp = new Dictionary<Type, bool>();\n\n            internal static bool HasHelpForObject(Object obj, bool monoBehaviourFallback)\n            {\n                if (obj == null)\n                    return false;\n\n                bool result;\n                if (s_ObjectHasHelp.TryGetValue(obj.GetType(), out result))\n                {\n                    return result;\n                }\n                else\n                {\n                    // Calc result and cache it\n                    result = Help.HasHelpForObject(obj, monoBehaviourFallback);\n                    s_ObjectHasHelp[obj.GetType()] = result;\n                    return result;\n                }\n            }\n\n            internal static bool IsObjectPartOfTargetAssemblies(Object obj)\n            {\n                if (obj == null)\n                    return false;\n\n                var type = obj.GetType();\n                bool result;\n                if (s_TypeIsPartOfTargetAssembliesMap.TryGetValue(type, out result))\n                {\n                    return result;\n                }\n                else\n                {\n                    // Calc result and cache it\n                    result = false;\n                    EditorCompilation.TargetAssemblyInfo[] allTargetAssemblies = EditorCompilationInterface.GetTargetAssemblyInfos();\n\n                    string assemblyName = obj.GetType().Assembly.ManifestModule.Name;\n                    for (int i = 0; i < allTargetAssemblies.Length; ++i)\n                    {\n                        if (assemblyName == allTargetAssemblies[i].Name)\n                        {\n                            result = true;\n                            break;\n                        }\n                    }\n\n                    s_TypeIsPartOfTargetAssembliesMap[type] = result;\n                    return result;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorGUILayout.RenderPipeline.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor;\n\nsealed partial class EditorGUILayout\n{\n     // Rendering Layers\n    public static uint RenderingLayerMaskField(string label, uint layers, params GUILayoutOption[] options)\n    {\n        return RenderingLayerMaskField(label, layers, EditorStyles.layerMaskField);\n    }\n\n    public static uint RenderingLayerMaskField(string label, uint layers, GUIStyle style, params GUILayoutOption[] options)\n    {\n        return RenderingLayerMaskField(new GUIContent(label), layers, style);\n    }\n\n    public static uint RenderingLayerMaskField(GUIContent label, uint layers, params GUILayoutOption[] options)\n    {\n        return RenderingLayerMaskField(label, layers, EditorStyles.layerMaskField);\n    }\n\n    public static RenderingLayerMask RenderingLayerMaskField(string label, RenderingLayerMask layers, params GUILayoutOption[] options)\n    {\n        return RenderingLayerMaskField(label, layers,  EditorStyles.layerMaskField);\n    }\n    public static RenderingLayerMask RenderingLayerMaskField(string label, RenderingLayerMask layers, GUIStyle style, params GUILayoutOption[] options)\n    {\n        return RenderingLayerMaskField(new GUIContent(label), layers,  EditorStyles.layerMaskField);\n    }\n\n    public static RenderingLayerMask RenderingLayerMaskField(GUIContent label, RenderingLayerMask layers, params GUILayoutOption[] options)\n    {\n        return RenderingLayerMaskField(label, layers,  EditorStyles.layerMaskField);\n    }\n\n    public static uint RenderingLayerMaskField(GUIContent label, uint layers, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, options);\n        return EditorGUI.RenderingLayerMaskField(r, label, layers, style);\n    }\n\n    public static RenderingLayerMask RenderingLayerMaskField(GUIContent label, RenderingLayerMask layers, GUIStyle style, params GUILayoutOption[] options)\n    {\n        var rect = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, options);\n        return EditorGUI.RenderingLayerMaskField(rect, label, layers);\n    }\n\n    public static void RenderingLayerMaskField(GUIContent label, SerializedProperty property, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, options);\n        EditorGUI.RenderingLayerMaskField(r, label, property);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorGUILayout.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Build;\nusing UnityEngine;\nusing UnityEngine.Internal;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor;\n\n// Auto-layouted version of [[EditorGUI]]\nsealed partial class EditorGUILayout\n{\n    // @TODO: Make private (and rename to not claim it's a constant). Shouldn't really be used outside of EditorGUI.\n    // Places that use this directly should likely use GetControlRect instead.\n    internal static float kLabelFloatMinW => EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing;\n\n    internal static float kLabelFloatMaxW => EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing;\n\n    internal static Rect s_LastRect;\n\n    internal const float kPlatformTabWidth = 30;\n\n    internal static SavedBool s_SelectedDefault = new SavedBool(\"Platform.ShownDefaultTab\", true);\n\n    static GUIStyle s_TabOnlyOne;\n    static GUIStyle s_TabFirst;\n    static GUIStyle s_TabMiddle;\n    static GUIStyle s_TabLast;\n\n    [ExcludeFromDocs]\n    public static bool Foldout(bool foldout, string content)\n    {\n        return Foldout(foldout, content, EditorStyles.foldout);\n    }\n\n    public static bool Foldout(bool foldout, string content, [DefaultValue(\"EditorStyles.foldout\")] GUIStyle style)\n    {\n        return Foldout(foldout, EditorGUIUtility.TempContent(content), false, style);\n    }\n\n    [ExcludeFromDocs]\n    public static bool Foldout(bool foldout, GUIContent content)\n    {\n        return Foldout(foldout, content, EditorStyles.foldout);\n    }\n\n    public static bool Foldout(bool foldout, GUIContent content, [DefaultValue(\"EditorStyles.foldout\")] GUIStyle style)\n    {\n        return Foldout(foldout, content, false, style);\n    }\n\n    [ExcludeFromDocs]\n    public static bool Foldout(bool foldout, string content, bool toggleOnLabelClick)\n    {\n        return Foldout(foldout, content, toggleOnLabelClick, EditorStyles.foldout);\n    }\n\n    public static bool Foldout(bool foldout, string content, bool toggleOnLabelClick, [DefaultValue(\"EditorStyles.foldout\")] GUIStyle style)\n    {\n        return Foldout(foldout, EditorGUIUtility.TempContent(content), toggleOnLabelClick, style);\n    }\n\n    [ExcludeFromDocs]\n    public static bool Foldout(bool foldout, GUIContent content, bool toggleOnLabelClick)\n    {\n        return Foldout(foldout, content, toggleOnLabelClick, EditorStyles.foldout);\n    }\n\n    public static bool Foldout(bool foldout, GUIContent content, bool toggleOnLabelClick, [DefaultValue(\"EditorStyles.foldout\")] GUIStyle style)\n    {\n        return FoldoutInternal(foldout, content, toggleOnLabelClick, style);\n    }\n\n    [ExcludeFromDocs]\n    public static void PrefixLabel(string label)\n    {\n        GUIStyle followingStyle = \"Button\";\n        PrefixLabel(label, followingStyle);\n    }\n\n    public static void PrefixLabel(string label, [DefaultValue(\"\\\"Button\\\"\")] GUIStyle followingStyle)\n    {\n        PrefixLabel(EditorGUIUtility.TempContent(label), followingStyle, EditorStyles.label);\n    }\n\n    public static void PrefixLabel(string label, GUIStyle followingStyle, GUIStyle labelStyle)\n    {\n        PrefixLabel(EditorGUIUtility.TempContent(label), followingStyle, labelStyle);\n    }\n\n    [ExcludeFromDocs]\n    public static void PrefixLabel(GUIContent label)\n    {\n        GUIStyle followingStyle = \"Button\";\n        PrefixLabel(label, followingStyle);\n    }\n\n    public static void PrefixLabel(GUIContent label, [DefaultValue(\"\\\"Button\\\"\")] GUIStyle followingStyle)\n    {\n        PrefixLabel(label, followingStyle, EditorStyles.label);\n    }\n\n    // Make a label in front of some control.\n    public static void PrefixLabel(GUIContent label, GUIStyle followingStyle, GUIStyle labelStyle)\n    {\n        PrefixLabelInternal(label, followingStyle, labelStyle);\n    }\n\n    public static void LabelField(string label, params GUILayoutOption[] options)\n    {\n        LabelField(GUIContent.none, EditorGUIUtility.TempContent(label), EditorStyles.label, options);\n    }\n\n    public static void LabelField(string label, GUIStyle style, params GUILayoutOption[] options)\n    {\n        LabelField(GUIContent.none, EditorGUIUtility.TempContent(label), style, options);\n    }\n\n    public static void LabelField(GUIContent label, params GUILayoutOption[] options)\n    {\n        LabelField(GUIContent.none, label, EditorStyles.label, options);\n    }\n\n    public static void LabelField(GUIContent label, GUIStyle style, params GUILayoutOption[] options)\n    {\n        LabelField(GUIContent.none, label, style, options);\n    }\n\n    public static void LabelField(string label, string label2, params GUILayoutOption[] options)\n    {\n        LabelField(new GUIContent(label), EditorGUIUtility.TempContent(label2), EditorStyles.label, options);\n    }\n\n    public static void LabelField(string label, string label2, GUIStyle style, params GUILayoutOption[] options)\n    {\n        LabelField(new GUIContent(label), EditorGUIUtility.TempContent(label2), style, options);\n    }\n\n    public static void LabelField(GUIContent label, GUIContent label2, params GUILayoutOption[] options)\n    {\n        LabelField(label, label2, EditorStyles.label, options);\n    }\n\n    // Make a label field. (Useful for showing read-only info.)\n    public static void LabelField(GUIContent label, GUIContent label2, GUIStyle style, params GUILayoutOption[] options)\n    {\n        if (!style.wordWrap)\n        {\n            // If we don't need word wrapping, just allocate the standard space to avoid corner case layout issues\n            Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, options);\n            EditorGUI.LabelField(r, label, label2, style);\n        }\n        else\n        {\n            BeginHorizontal();\n            PrefixLabel(label, style);\n            Rect r = GUILayoutUtility.GetRect(label2, style, options);\n            int oldIndent = EditorGUI.indentLevel;\n            EditorGUI.indentLevel = 0;\n            EditorGUI.LabelField(r, label2, style);\n            EditorGUI.indentLevel = oldIndent;\n            EndHorizontal();\n        }\n    }\n\n    public static bool LinkButton(string label, params GUILayoutOption[] options)\n    {\n        return LinkButton(EditorGUIUtility.TempContent(label), options);\n    }\n\n    public static bool LinkButton(GUIContent label, params GUILayoutOption[] options)\n    {\n        var position = s_LastRect = GUILayoutUtility.GetRect(label, EditorStyles.linkLabel, options);\n\n        Handles.color = EditorStyles.linkLabel.normal.textColor;\n        Handles.DrawLine(new Vector3(position.xMin + EditorStyles.linkLabel.padding.left, position.yMax), new Vector3(position.xMax - EditorStyles.linkLabel.padding.right, position.yMax));\n        Handles.color = Color.white;\n\n        EditorGUIUtility.AddCursorRect(position, MouseCursor.Link);\n\n        return GUI.Button(position, label, EditorStyles.linkLabel);\n    }\n\n    public static bool Toggle(bool value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetToggleRect(false, options);\n        return EditorGUI.Toggle(r, value);\n    }\n\n    public static bool Toggle(string label, bool value, params GUILayoutOption[] options)\n    {\n        return Toggle(EditorGUIUtility.TempContent(label), value, options);\n    }\n\n    public static bool Toggle(GUIContent label, bool value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetToggleRect(true, options);\n        return EditorGUI.Toggle(r, label, value);\n    }\n\n    public static bool Toggle(bool value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetToggleRect(false, options);\n        return EditorGUI.Toggle(r, value, style);\n    }\n\n    public static bool Toggle(string label, bool value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        return Toggle(EditorGUIUtility.TempContent(label), value, style, options);\n    }\n\n    // Make a toggle.\n    public static bool Toggle(GUIContent label, bool value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetToggleRect(true, options);\n        return EditorGUI.Toggle(r, label, value, style);\n    }\n\n    public static bool ToggleLeft(string label, bool value, params GUILayoutOption[] options)\n    {\n        return ToggleLeft(EditorGUIUtility.TempContent(label), value, options);\n    }\n\n    public static bool ToggleLeft(GUIContent label, bool value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, options);\n        return EditorGUI.ToggleLeft(r, label, value);\n    }\n\n    public static bool ToggleLeft(string label, bool value, GUIStyle labelStyle, params GUILayoutOption[] options)\n    {\n        return ToggleLeft(EditorGUIUtility.TempContent(label), value, labelStyle, options);\n    }\n\n    // Make a toggle with the label on the right.\n    public static bool ToggleLeft(GUIContent label, bool value, GUIStyle labelStyle, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, options);\n        return EditorGUI.ToggleLeft(r, label, value, labelStyle);\n    }\n\n    public static string TextField(string text, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.textField, options);\n        return EditorGUI.TextField(r, text);\n    }\n\n    public static string TextField(string text, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.TextField(r, text, style);\n    }\n\n    public static string TextField(string label, string text, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.textField, options);\n        return EditorGUI.TextField(r, label, text);\n    }\n\n    public static string TextField(string label, string text, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.TextField(r, label, text, style);\n    }\n\n    public static string TextField(GUIContent label, string text, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.textField, options);\n        return EditorGUI.TextField(r, label, text);\n    }\n\n    // Make a text field.\n    public static string TextField(GUIContent label, string text, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.TextField(r, label, text, style);\n    }\n\n    public static string DelayedTextField(string text, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.textField, options);\n        return EditorGUI.DelayedTextField(r, text);\n    }\n\n    public static string DelayedTextField(string text, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DelayedTextField(r, text, style);\n    }\n\n    public static string DelayedTextField(string label, string text, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.textField, options);\n        return EditorGUI.DelayedTextField(r, label, text);\n    }\n\n    public static string DelayedTextField(string label, string text, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DelayedTextField(r, label, text, style);\n    }\n\n    public static string DelayedTextField(GUIContent label, string text, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.textField, options);\n        return EditorGUI.DelayedTextField(r, label, text);\n    }\n\n    // Make a delayed text field.\n    public static string DelayedTextField(GUIContent label, string text, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DelayedTextField(r, label, text, style);\n    }\n\n    public static void DelayedTextField(SerializedProperty property, params GUILayoutOption[] options)\n    {\n        DelayedTextField(property, null, options);\n    }\n\n    // Make a delayed text field.\n    internal static void DelayedTextField(SerializedProperty property, GUIContent label, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(EditorGUI.LabelHasContent(label), EditorGUI.kSingleLineHeight, EditorStyles.textField, options);\n        EditorGUI.DelayedTextFieldHelper(r, property, label, style);\n    }\n\n    public static void DelayedTextField(SerializedProperty property, GUIContent label, params GUILayoutOption[] options)\n    {\n        DelayedTextField(property, label, EditorStyles.textField, options);\n    }\n\n    internal static string ToolbarSearchField(string text, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GUILayoutUtility.GetRect(0, kLabelFloatMaxW * 1.5f, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.toolbarSearchField, options);\n        int i = 0;\n        return EditorGUI.ToolbarSearchField(r, null, ref i, text);\n    }\n\n    internal static string ToolbarSearchField(string text, string[] searchModes, ref int searchMode, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GUILayoutUtility.GetRect(0, kLabelFloatMaxW * 1.5f, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.toolbarSearchField, options);\n        return EditorGUI.ToolbarSearchField(r, searchModes, ref searchMode, text);\n    }\n\n    public static string TextArea(string text, params GUILayoutOption[] options)\n    { return TextArea(text, EditorStyles.textField, options); }\n    // Make a text area.\n    public static string TextArea(string text, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GUILayoutUtility.GetRect(EditorGUIUtility.TempContent(text), style, options);\n        return EditorGUI.TextArea(r, text, style);\n    }\n\n    public static void SelectableLabel(string text, params GUILayoutOption[] options)\n    {\n        SelectableLabel(text, EditorStyles.label, options);\n    }\n\n    // Make a selectable label field. (Useful for showing read-only info that can be copy-pasted.)\n    public static void SelectableLabel(string text, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight * 2, style, options);\n        EditorGUI.SelectableLabel(r, text, style);\n    }\n\n    internal static Event KeyEventField(Event e, params GUILayoutOption[] options)\n    {\n        Rect r = GUILayoutUtility.GetRect(EditorGUI.s_PleasePressAKey, GUI.skin.textField, options);\n        return EditorGUI.KeyEventField(r, e);\n    }\n\n    public static string PasswordField(string password, params GUILayoutOption[] options)\n    {\n        return PasswordField(password, EditorStyles.textField, options);\n    }\n\n    public static string PasswordField(string password, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.PasswordField(r, password, style);\n    }\n\n    public static string PasswordField(string label, string password, params GUILayoutOption[] options)\n    {\n        return PasswordField(EditorGUIUtility.TempContent(label), password, EditorStyles.textField, options);\n    }\n\n    public static string PasswordField(string label, string password, GUIStyle style, params GUILayoutOption[] options)\n    {\n        return PasswordField(EditorGUIUtility.TempContent(label), password, style, options);\n    }\n\n    public static string PasswordField(GUIContent label, string password, params GUILayoutOption[] options)\n    {\n        return PasswordField(label, password, EditorStyles.textField, options);\n    }\n\n    // Make a text field where the user can enter a password.\n    public static string PasswordField(GUIContent label, string password, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.PasswordField(r, label, password, style);\n    }\n\n    // Peak smoothing should be handled by client. Input: value and peak is normalized values (0 - 1).\n    internal static void VUMeterHorizontal(float value, float peak, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        EditorGUI.VUMeter.HorizontalMeter(r, value, peak, EditorGUI.VUMeter.horizontalVUTexture, Color.grey);\n    }\n\n    // Auto-smoothing of peak\n    internal static void VUMeterHorizontal(float value, ref EditorGUI.VUMeter.SmoothingData data, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        EditorGUI.VUMeter.HorizontalMeter(r, value, ref data, EditorGUI.VUMeter.horizontalVUTexture, Color.grey);\n    }\n\n    public static float FloatField(float value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        return EditorGUI.FloatField(r, value);\n    }\n\n    public static float FloatField(float value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.FloatField(r, value, style);\n    }\n\n    public static float FloatField(string label, float value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        return EditorGUI.FloatField(r, label, value);\n    }\n\n    public static float FloatField(string label, float value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.FloatField(r, label, value, style);\n    }\n\n    public static float FloatField(GUIContent label, float value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        return EditorGUI.FloatField(r, label, value);\n    }\n\n    // Make a text field for entering float values.\n    public static float FloatField(GUIContent label, float value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.FloatField(r, label, value, style);\n    }\n\n    public static float DelayedFloatField(float value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        return EditorGUI.DelayedFloatField(r, value);\n    }\n\n    public static float DelayedFloatField(float value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DelayedFloatField(r, value, style);\n    }\n\n    public static float DelayedFloatField(string label, float value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        return EditorGUI.DelayedFloatField(r, label, value);\n    }\n\n    public static float DelayedFloatField(string label, float value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DelayedFloatField(r, label, value, style);\n    }\n\n    public static float DelayedFloatField(GUIContent label, float value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        return EditorGUI.DelayedFloatField(r, label, value);\n    }\n\n    // Make a delayed text field for entering float values.\n    public static float DelayedFloatField(GUIContent label, float value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DelayedFloatField(r, label, value, style);\n    }\n\n    public static void DelayedFloatField(SerializedProperty property, params GUILayoutOption[] options)\n    {\n        DelayedFloatField(property, null, options);\n    }\n\n    // Make a delayed text field for entering float values.\n    public static void DelayedFloatField(SerializedProperty property, GUIContent label, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(EditorGUI.LabelHasContent(label), EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        EditorGUI.DelayedFloatField(r, property, label);\n    }\n\n    public static double DoubleField(double value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        return EditorGUI.DoubleField(r, value);\n    }\n\n    public static double DoubleField(double value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DoubleField(r, value, style);\n    }\n\n    public static double DoubleField(string label, double value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        return EditorGUI.DoubleField(r, label, value);\n    }\n\n    public static double DoubleField(string label, double value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DoubleField(r, label, value, style);\n    }\n\n    public static double DoubleField(GUIContent label, double value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        return EditorGUI.DoubleField(r, label, value);\n    }\n\n    // Make a text field for entering double values.\n    public static double DoubleField(GUIContent label, double value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DoubleField(r, label, value, style);\n    }\n\n    public static double DelayedDoubleField(double value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        return EditorGUI.DelayedDoubleField(r, value);\n    }\n\n    public static double DelayedDoubleField(double value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DelayedDoubleField(r, value, style);\n    }\n\n    public static double DelayedDoubleField(string label, double value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        return EditorGUI.DelayedDoubleField(r, label, value);\n    }\n\n    public static double DelayedDoubleField(string label, double value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DelayedDoubleField(r, label, value, style);\n    }\n\n    public static double DelayedDoubleField(GUIContent label, double value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        return EditorGUI.DelayedDoubleField(r, label, value);\n    }\n\n    // Make a delayed text field for entering double values.\n    public static double DelayedDoubleField(GUIContent label, double value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DelayedDoubleField(r, label, value, style);\n    }\n\n    public static int IntField(int value, params GUILayoutOption[] options)\n    {\n        return IntField(value, EditorStyles.numberField, options);\n    }\n\n    public static int IntField(int value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.IntField(r, value, style);\n    }\n\n    public static int IntField(string label, int value, params GUILayoutOption[] options)\n    {\n        return IntField(label, value, EditorStyles.numberField, options);\n    }\n\n    public static int IntField(string label, int value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.IntField(r, label, value, style);\n    }\n\n    public static int IntField(GUIContent label, int value, params GUILayoutOption[] options)\n    {\n        return IntField(label, value, EditorStyles.numberField, options);\n    }\n\n    // Make a text field for entering integers.\n    public static int IntField(GUIContent label, int value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.IntField(r, label, value, style);\n    }\n\n    public static int DelayedIntField(int value, params GUILayoutOption[] options)\n    {\n        return DelayedIntField(value, EditorStyles.numberField, options);\n    }\n\n    public static int DelayedIntField(int value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DelayedIntField(r, value, style);\n    }\n\n    public static int DelayedIntField(string label, int value, params GUILayoutOption[] options)\n    {\n        return DelayedIntField(label, value, EditorStyles.numberField, options);\n    }\n\n    public static int DelayedIntField(string label, int value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DelayedIntField(r, label, value, style);\n    }\n\n    public static int DelayedIntField(GUIContent label, int value, params GUILayoutOption[] options)\n    {\n        return DelayedIntField(label, value, EditorStyles.numberField, options);\n    }\n\n    // Make a text field for entering integers.\n    public static int DelayedIntField(GUIContent label, int value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.DelayedIntField(r, label, value, style);\n    }\n\n    public static void DelayedIntField(SerializedProperty property, params GUILayoutOption[] options)\n    {\n        DelayedIntField(property, null, options);\n    }\n\n    // Make a text field for entering integers.\n    public static void DelayedIntField(SerializedProperty property, GUIContent label, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(EditorGUI.LabelHasContent(label), EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n        EditorGUI.DelayedIntField(r, property, label);\n    }\n\n    public static long LongField(long value, params GUILayoutOption[] options)\n    {\n        return LongField(value, EditorStyles.numberField, options);\n    }\n\n    public static long LongField(long value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.LongField(r, value, style);\n    }\n\n    public static long LongField(string label, long value, params GUILayoutOption[] options)\n    {\n        return LongField(label, value, EditorStyles.numberField, options);\n    }\n\n    public static long LongField(string label, long value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.LongField(r, label, value, style);\n    }\n\n    public static long LongField(GUIContent label, long value, params GUILayoutOption[] options)\n    {\n        return LongField(label, value, EditorStyles.numberField, options);\n    }\n\n    // Make a text field for entering integers.\n    public static long LongField(GUIContent label, long value, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.LongField(r, label, value, style);\n    }\n\n    public static float Slider(float value, float leftValue, float rightValue, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(false, options);\n        return EditorGUI.Slider(r, value, leftValue, rightValue);\n    }\n\n    public static float Slider(string label, float value, float leftValue, float rightValue, params GUILayoutOption[] options)\n    {\n        return Slider(EditorGUIUtility.TempContent(label), value, leftValue, rightValue, options);\n    }\n\n    // Make a slider the user can drag to change a value between a min and a max.\n    public static float Slider(GUIContent label, float value, float leftValue, float rightValue, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(true, options);\n        return EditorGUI.Slider(r, label, value, leftValue, rightValue);\n    }\n\n    internal static float Slider(GUIContent label, float value, float sliderLeftValue, float sliderRightValue, float textLeftValue, float textRightValue, params GUILayoutOption[] options)\n    {\n        return Slider(label, value, sliderLeftValue, sliderRightValue, textLeftValue, textRightValue, EditorStyles.numberField,\n            GUI.skin.horizontalSlider, GUI.skin.horizontalSliderThumb, null, GUI.skin.horizontalSliderThumbExtent, options);\n    }\n\n    static void GetSliderParts(GUIStyle baseStyle, ref GUIStyle textFieldStyle, ref GUIStyle thumbStyle, ref GUIStyle thumbExtentStyle)\n    {\n        string baseName = baseStyle.name;\n        thumbStyle = GUI.skin.FindStyle(baseName + \"Thumb\") ?? thumbStyle;\n        thumbExtentStyle = GUI.skin.FindStyle(baseName + \"ThumbExtent\") ?? thumbExtentStyle;\n        textFieldStyle = GUI.skin.FindStyle(baseName + \"TextField\") ?? textFieldStyle;\n    }\n\n    static void GetHorizontalSliderParts(GUIStyle baseStyle, out GUIStyle textFieldStyle, out GUIStyle thumbStyle, out GUIStyle thumbExtentStyle)\n    {\n        thumbStyle = GUI.skin.horizontalSliderThumb;\n        thumbExtentStyle = GUI.skin.horizontalSliderThumbExtent;\n        textFieldStyle = EditorStyles.numberField;\n\n        GetSliderParts(baseStyle, ref textFieldStyle, ref thumbStyle, ref thumbExtentStyle);\n    }\n\n    static void GetVerticalSliderParts(GUIStyle baseStyle, out GUIStyle textFieldStyle, out GUIStyle thumbStyle, out GUIStyle thumbExtentStyle)\n    {\n        thumbStyle = GUI.skin.verticalSliderThumb;\n        thumbExtentStyle = GUI.skin.verticalSliderThumbExtent;\n        textFieldStyle = EditorStyles.numberField;\n\n        GetSliderParts(baseStyle, ref textFieldStyle, ref thumbStyle, ref thumbExtentStyle);\n    }\n\n    internal static float Slider(GUIContent label, float value, float sliderLeftValue, float sliderRightValue, float textLeftValue, float textRightValue, GUIStyle sliderStyle, params GUILayoutOption[] options)\n    {\n        GUIStyle sliderThumbStyle, sliderThumbStyleExtent, sliderTextFieldStyle;\n\n        GetHorizontalSliderParts(sliderStyle, out sliderTextFieldStyle, out sliderThumbStyle, out sliderThumbStyleExtent);\n\n        return Slider(label, value, sliderLeftValue, sliderRightValue, textLeftValue, textRightValue, sliderTextFieldStyle, sliderStyle\n            , sliderThumbStyle, null, sliderThumbStyleExtent);\n    }\n\n    internal static float Slider(GUIContent label, float value, float sliderLeftValue, float sliderRightValue, float textLeftValue, float textRightValue\n        , GUIStyle sliderTextField, GUIStyle sliderStyle, GUIStyle sliderThumbStyle, Texture2D sliderBackground, GUIStyle sliderThumbStyleExtent, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(true, sliderStyle, options);\n        return EditorGUI.Slider(r, label, value, sliderLeftValue, sliderRightValue, textLeftValue, textRightValue, sliderTextField, sliderStyle, sliderThumbStyle, sliderBackground, sliderThumbStyleExtent);\n    }\n\n    public static void Slider(SerializedProperty property, float leftValue, float rightValue, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(false, options);\n        EditorGUI.Slider(r, property, leftValue, rightValue);\n    }\n\n    public static void Slider(SerializedProperty property, float leftValue, float rightValue, string label, params GUILayoutOption[] options)\n    {\n        Slider(property, leftValue, rightValue, EditorGUIUtility.TempContent(label), options);\n    }\n\n    // Make a slider the user can drag to change a value between a min and a max.\n    public static void Slider(SerializedProperty property, float leftValue, float rightValue, GUIContent label, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(true, options);\n        EditorGUI.Slider(r, property, leftValue, rightValue, label);\n    }\n\n    internal static void Slider(SerializedProperty property, float sliderLeftValue, float sliderRightValue, float textLeftValue, float textRightValue, GUIContent label, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(true, options);\n        EditorGUI.Slider(r, property, sliderLeftValue, sliderRightValue, textLeftValue, textRightValue, label);\n    }\n\n    internal static float PowerSlider(string label, float value, float leftValue, float rightValue, float power, params GUILayoutOption[] options)\n    {\n        return PowerSlider(EditorGUIUtility.TempContent(label), value, leftValue, rightValue, power, options);\n    }\n\n    // Make a power slider the user can drag to change a value between a min and a max.\n    internal static float PowerSlider(GUIContent label, float value, float leftValue, float rightValue, float power, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(true, options);\n        return EditorGUI.PowerSlider(r, label, value, leftValue, rightValue, power);\n    }\n\n    internal static int LogarithmicIntSlider(string label, int value, int leftValue, int rightValue, int logbase, int textFieldMin, int textFieldMax, params GUILayoutOption[] options)\n    {\n        return LogarithmicIntSlider(EditorGUIUtility.TempContent(label), value, leftValue, rightValue, logbase, textFieldMin, textFieldMax, options);\n    }\n\n    internal static int LogarithmicIntSlider(GUIContent label, int value, int leftValue, int rightValue, int logbase, int textFieldMin, int textFieldMax, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(true, options);\n        return EditorGUI.LogarithmicIntSlider(r, label, value, leftValue, rightValue, logbase, textFieldMin, textFieldMax);\n    }\n\n    public static int IntSlider(int value, int leftValue, int rightValue, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(false, options);\n        return EditorGUI.IntSlider(r, value, leftValue, rightValue);\n    }\n\n    internal static int IntSlider(int value, int leftValue, int rightValue, float power, GUIStyle sliderStyle, params GUILayoutOption[] options)\n    {\n        GUIStyle sliderThumbStyle, sliderThumbStyleExtent, sliderTextFieldStyle;\n\n        GetHorizontalSliderParts(sliderStyle, out sliderTextFieldStyle, out sliderThumbStyle, out sliderThumbStyleExtent);\n\n        return IntSlider(value, leftValue, rightValue, power, sliderTextFieldStyle, sliderStyle, sliderThumbStyle, null, sliderThumbStyleExtent, options);\n    }\n\n    internal static int IntSlider(int value, int leftValue, int rightValue, float power,\n        GUIStyle textfieldStyle, GUIStyle sliderStyle, GUIStyle thumbStyle, Texture2D sliderBackground, GUIStyle thumbStyleExtent, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(false, sliderStyle, options);\n        return EditorGUI.IntSlider(r, value, leftValue, rightValue, power, logbase: 1, textfieldStyle, sliderStyle, thumbStyle, sliderBackground, thumbStyleExtent);\n    }\n\n    public static int IntSlider(string label, int value, int leftValue, int rightValue, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(true, options);\n        return EditorGUI.IntSlider(r, label, value, leftValue, rightValue);\n    }\n\n    // Make a slider the user can drag to change an integer value between a min and a max.\n    public static int IntSlider(GUIContent label, int value, int leftValue, int rightValue, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(true, options);\n        return EditorGUI.IntSlider(r, label, value, leftValue, rightValue);\n    }\n\n    public static void IntSlider(SerializedProperty property, int leftValue, int rightValue, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(false, options);\n        EditorGUI.IntSlider(r, property, leftValue, rightValue, property.displayName);\n    }\n\n    public static void IntSlider(SerializedProperty property, int leftValue, int rightValue, string label, params GUILayoutOption[] options)\n    {\n        IntSlider(property, leftValue, rightValue, EditorGUIUtility.TempContent(label), options);\n    }\n\n    // Make a slider the user can drag to change an integer value between a min and a max.\n    public static void IntSlider(SerializedProperty property, int leftValue, int rightValue, GUIContent label, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(true, options);\n        EditorGUI.IntSlider(r, property, leftValue, rightValue, label);\n    }\n\n    public static void MinMaxSlider(ref float minValue, ref float maxValue, float minLimit, float maxLimit, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(false, options);\n        EditorGUI.MinMaxSlider(r, ref minValue, ref maxValue, minLimit, maxLimit);\n    }\n\n    public static void MinMaxSlider(string label, ref float minValue, ref float maxValue, float minLimit, float maxLimit, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(true, options);\n        EditorGUI.MinMaxSlider(r, label, ref minValue, ref maxValue, minLimit, maxLimit);\n    }\n\n    // Make a special slider the user can use to specify a range between a min and a max.\n    public static void MinMaxSlider(GUIContent label, ref float minValue, ref float maxValue, float minLimit, float maxLimit, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetSliderRect(true, options);\n        EditorGUI.MinMaxSlider(r, label, ref minValue, ref maxValue, minLimit, maxLimit);\n    }\n\n    public static int Popup(int selectedIndex, string[] displayedOptions, params GUILayoutOption[] options)\n    {\n        return Popup(selectedIndex, displayedOptions, EditorStyles.popup, options);\n    }\n\n    public static int Popup(int selectedIndex, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.Popup(r, selectedIndex, displayedOptions, style);\n    }\n\n    public static int Popup(int selectedIndex, GUIContent[] displayedOptions, params GUILayoutOption[] options)\n    {\n        return Popup(selectedIndex, displayedOptions, EditorStyles.popup, options);\n    }\n\n    public static int Popup(int selectedIndex, GUIContent[] displayedOptions, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.Popup(r, selectedIndex, displayedOptions, style);\n    }\n\n    public static int Popup(string label, int selectedIndex, string[] displayedOptions, params GUILayoutOption[] options)\n    {\n        return Popup(label, selectedIndex, displayedOptions, EditorStyles.popup, options);\n    }\n\n    public static int Popup(GUIContent label, int selectedIndex, string[] displayedOptions, params GUILayoutOption[] options)\n    {\n        return Popup(label, selectedIndex, displayedOptions, EditorStyles.popup, options);\n    }\n\n    public static int Popup(string label, int selectedIndex, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.Popup(r, label, selectedIndex, displayedOptions, style);\n    }\n\n    public static int Popup(GUIContent label, int selectedIndex, GUIContent[] displayedOptions, params GUILayoutOption[] options)\n    {\n        return Popup(label, selectedIndex, displayedOptions, EditorStyles.popup, options);\n    }\n\n    // Make a generic popup selection field.\n    public static int Popup(GUIContent label, int selectedIndex, GUIContent[] displayedOptions, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.Popup(r, label, selectedIndex, displayedOptions, style);\n    }\n\n    internal static int Popup(GUIContent label, int selectedIndex, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.Popup(r, label, selectedIndex, displayedOptions, style);\n    }\n\n    internal static void Popup(SerializedProperty property, GUIContent[] displayedOptions, params GUILayoutOption[] options)\n    {\n        Popup(property, displayedOptions, null, options);\n    }\n\n    internal static void Popup(SerializedProperty property, GUIContent[] displayedOptions, GUIContent label, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup, options);\n        EditorGUI.Popup(r, property, displayedOptions, label);\n    }\n\n    public static Enum EnumPopup(Enum selected, params GUILayoutOption[] options)\n    {\n        return EnumPopup(selected, EditorStyles.popup, options);\n    }\n\n    public static Enum EnumPopup(Enum selected, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.EnumPopup(r, selected, style);\n    }\n\n    public static Enum EnumPopup(string label, Enum selected, params GUILayoutOption[] options)\n    {\n        return EnumPopup(label, selected, EditorStyles.popup, options);\n    }\n\n    public static Enum EnumPopup(string label, Enum selected, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.EnumPopup(r, GUIContent.Temp(label), selected, null, false, style);\n    }\n\n    public static Enum EnumPopup(GUIContent label, Enum selected, params GUILayoutOption[] options)\n    {\n        return EnumPopup(label, selected, EditorStyles.popup, options);\n    }\n\n    // Make an enum popup selection field.\n    public static Enum EnumPopup(GUIContent label, Enum selected, GUIStyle style, params GUILayoutOption[] options)\n    {\n        return EnumPopup(label, selected, null, false, style, options);\n    }\n\n    public static Enum EnumPopup(GUIContent label, Enum selected, Func<Enum, bool> checkEnabled, bool includeObsolete, params GUILayoutOption[] options)\n    {\n        return EnumPopup(label, selected, checkEnabled, includeObsolete, EditorStyles.popup, options);\n    }\n\n    public static Enum EnumPopup(GUIContent label, Enum selected, Func<Enum, bool> checkEnabled, bool includeObsolete, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.EnumPopup(r, label, selected, checkEnabled, includeObsolete, style);\n    }\n\n    public static int IntPopup(int selectedValue, string[] displayedOptions, int[] optionValues, params GUILayoutOption[] options)\n    {\n        return IntPopup(selectedValue, displayedOptions, optionValues, EditorStyles.popup, options);\n    }\n\n    public static int IntPopup(int selectedValue, string[] displayedOptions, int[] optionValues, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.IntPopup(r,  selectedValue, displayedOptions, optionValues, style);\n    }\n\n    public static int IntPopup(int selectedValue, GUIContent[] displayedOptions, int[] optionValues, params GUILayoutOption[] options)\n    {\n        return IntPopup(selectedValue, displayedOptions, optionValues, EditorStyles.popup, options);\n    }\n\n    public static int IntPopup(int selectedValue, GUIContent[] displayedOptions, int[] optionValues, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.IntPopup(r,  GUIContent.none, selectedValue, displayedOptions, optionValues, style);\n    }\n\n    public static int IntPopup(string label, int selectedValue, string[] displayedOptions, int[] optionValues, params GUILayoutOption[] options)\n    {\n        return IntPopup(label, selectedValue, displayedOptions, optionValues, EditorStyles.popup, options);\n    }\n\n    public static int IntPopup(string label, int selectedValue, string[] displayedOptions, int[] optionValues, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.IntPopup(r, label, selectedValue, displayedOptions, optionValues, style);\n    }\n\n    public static int IntPopup(GUIContent label, int selectedValue, GUIContent[] displayedOptions, int[] optionValues, params GUILayoutOption[] options)\n    {\n        return IntPopup(label, selectedValue, displayedOptions, optionValues, EditorStyles.popup, options);\n    }\n\n    // Make an integer popup selection field.\n    public static int IntPopup(GUIContent label, int selectedValue, GUIContent[] displayedOptions, int[] optionValues, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.IntPopup(r, label, selectedValue, displayedOptions, optionValues, style);\n    }\n\n    public static void IntPopup(SerializedProperty property, GUIContent[] displayedOptions, int[] optionValues, params GUILayoutOption[] options)\n    {\n        IntPopup(property, displayedOptions, optionValues, null, options);\n    }\n\n    // Make an integer popup selection field.\n    public static void IntPopup(SerializedProperty property, GUIContent[] displayedOptions, int[] optionValues, GUIContent label, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup, options);\n        EditorGUI.IntPopup(r, property, displayedOptions, optionValues, label);\n    }\n\n    [Obsolete(\"This function is obsolete and the style is not used.\")]\n    public static void IntPopup(SerializedProperty property, GUIContent[] displayedOptions, int[] optionValues, GUIContent label, GUIStyle style, params GUILayoutOption[] options)\n    {\n        IntPopup(property, displayedOptions, optionValues, label, options);\n    }\n\n    public static string TagField(string tag, params GUILayoutOption[] options)\n    {\n        return TagField(tag, EditorStyles.popup, options);\n    }\n\n    public static string TagField(string tag, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.TagField(r, tag, style);\n    }\n\n    public static string TagField(string label, string tag, params GUILayoutOption[] options)\n    {\n        return TagField(EditorGUIUtility.TempContent(label), tag, EditorStyles.popup, options);\n    }\n\n    public static string TagField(string label, string tag, GUIStyle style, params GUILayoutOption[] options)\n    {\n        return TagField(EditorGUIUtility.TempContent(label), tag, style, options);\n    }\n\n    public static string TagField(GUIContent label, string tag, params GUILayoutOption[] options)\n    {\n        return TagField(label, tag, EditorStyles.popup, options);\n    }\n\n    // Make a tag selection field.\n    public static string TagField(GUIContent label, string tag, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.TagField(r, label, tag, style);\n    }\n\n    public static int LayerField(int layer, params GUILayoutOption[] options)\n    {\n        return LayerField(layer, EditorStyles.popup, options);\n    }\n\n    public static int LayerField(int layer, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.LayerField(r, layer, style);\n    }\n\n    public static int LayerField(string label, int layer, params GUILayoutOption[] options)\n    {\n        return LayerField(EditorGUIUtility.TempContent(label), layer, EditorStyles.popup, options);\n    }\n\n    public static int LayerField(string label, int layer, GUIStyle style, params GUILayoutOption[] options)\n    {\n        return LayerField(EditorGUIUtility.TempContent(label), layer, style, options);\n    }\n\n    public static int LayerField(GUIContent label, int layer, params GUILayoutOption[] options)\n    {\n        return LayerField(label, layer, EditorStyles.popup, options);\n    }\n\n    // Make a layer selection field.\n    public static int LayerField(GUIContent label, int layer, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.LayerField(r, label, layer, style);\n    }\n\n    public static int MaskField(GUIContent label, int mask, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options)\n    {\n        var r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.MaskField(r, label, mask, displayedOptions, style);\n    }\n\n    public static int MaskField(string label, int mask, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options)\n    {\n        var r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.MaskField(r, label, mask, displayedOptions, style);\n    }\n\n    public static int MaskField(GUIContent label, int mask, string[] displayedOptions, params GUILayoutOption[] options)\n    {\n        var r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup, options);\n        return EditorGUI.MaskField(r, label, mask, displayedOptions, EditorStyles.popup);\n    }\n\n    public static int MaskField(string label, int mask, string[] displayedOptions, params GUILayoutOption[] options)\n    {\n        var r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup, options);\n        return EditorGUI.MaskField(r, label, mask, displayedOptions, EditorStyles.popup);\n    }\n\n    public static int MaskField(int mask, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options)\n    {\n        var r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.MaskField(r, mask, displayedOptions, style);\n    }\n\n    // Make a field for masks.\n    public static int MaskField(int mask, string[] displayedOptions, params GUILayoutOption[] options)\n    {\n        var r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.popup, options);\n        return EditorGUI.MaskField(r, mask, displayedOptions, EditorStyles.popup);\n    }\n\n    public static Enum EnumFlagsField(Enum enumValue, params GUILayoutOption[] options)\n    {\n        return EnumFlagsField(enumValue, EditorStyles.popup, options);\n    }\n\n    public static Enum EnumFlagsField(Enum enumValue, GUIStyle style, params GUILayoutOption[] options)\n    {\n        var position = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.EnumFlagsField(position, enumValue, style);\n    }\n\n    public static Enum EnumFlagsField(string label, Enum enumValue, params GUILayoutOption[] options)\n    {\n        return EnumFlagsField(label, enumValue, EditorStyles.popup, options);\n    }\n\n    public static Enum EnumFlagsField(string label, Enum enumValue, GUIStyle style, params GUILayoutOption[] options)\n    {\n        return EnumFlagsField(EditorGUIUtility.TempContent(label), enumValue, style, options);\n    }\n\n    public static Enum EnumFlagsField(GUIContent label, Enum enumValue, params GUILayoutOption[] options)\n    {\n        return EnumFlagsField(label, enumValue, EditorStyles.popup, options);\n    }\n\n    public static Enum EnumFlagsField(GUIContent label, Enum enumValue, GUIStyle style, params GUILayoutOption[] options)\n    {\n        var position = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.EnumFlagsField(position, label, enumValue, style);\n    }\n\n    public static Enum EnumFlagsField(GUIContent label, Enum enumValue, bool includeObsolete, params GUILayoutOption[] options)\n    {\n        return EnumFlagsField(label, enumValue, includeObsolete, EditorStyles.popup, options);\n    }\n\n    public static Enum EnumFlagsField(GUIContent label, Enum enumValue, bool includeObsolete, GUIStyle style, params GUILayoutOption[] options)\n    {\n        var position = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.EnumFlagsField(position, label, enumValue, includeObsolete, style);\n    }\n\n    [Obsolete(\"Check the docs for the usage of the new parameter 'allowSceneObjects'.\")]\n    public static Object ObjectField(Object obj, Type objType, params GUILayoutOption[] options)\n    {\n        return ObjectField(obj, objType, true, options);\n    }\n\n    public static Object ObjectField(Object obj, Type objType, Object targetBeingEdited, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, options);\n        return EditorGUI.ObjectField(r, obj, objType, targetBeingEdited);\n    }\n\n    public static Object ObjectField(Object obj, Type objType, bool allowSceneObjects, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, options);\n        return EditorGUI.ObjectField(r, obj, objType, allowSceneObjects);\n    }\n\n    [Obsolete(\"Check the docs for the usage of the new parameter 'allowSceneObjects'.\")]\n    public static Object ObjectField(string label, Object obj, Type objType, params GUILayoutOption[] options)\n    {\n        return ObjectField(label, obj, objType, true, options);\n    }\n\n    public static Object ObjectField(string label, Object obj, Type objType, Object targetBeingEdited, params GUILayoutOption[] options)\n    {\n        return ObjectField(EditorGUIUtility.TempContent(label), obj, objType, targetBeingEdited, options);\n    }\n\n    public static Object ObjectField(string label, Object obj, Type objType, bool allowSceneObjects, params GUILayoutOption[] options)\n    {\n        return ObjectField(EditorGUIUtility.TempContent(label), obj, objType, allowSceneObjects, options);\n    }\n\n    [Obsolete(\"Check the docs for the usage of the new parameter 'allowSceneObjects'.\")]\n    public static Object ObjectField(GUIContent label, Object obj, Type objType, params GUILayoutOption[] options)\n    {\n        return ObjectField(label, obj, objType, true, options);\n    }\n\n    // Make an object field. You can assign objects either by drag'n drop objects or by selecting an object using the Object Picker.\n    public static Object ObjectField(GUIContent label, Object obj, Type objType, Object targetBeingEdited, params GUILayoutOption[] options)\n    {\n        var height = EditorGUIUtility.HasObjectThumbnail(objType) ? EditorGUI.kObjectFieldThumbnailHeight : EditorGUI.kSingleLineHeight;\n        Rect r = s_LastRect = GetControlRect(true, height, options);\n        return EditorGUI.ObjectField(r, label, obj, objType, targetBeingEdited);\n    }\n\n    // Make an object field. You can assign objects either by drag'n drop objects or by selecting an object using the Object Picker.\n    public static Object ObjectField(GUIContent label, Object obj, Type objType, bool allowSceneObjects, params GUILayoutOption[] options)\n    {\n        var height = EditorGUIUtility.HasObjectThumbnail(objType) ? EditorGUI.kObjectFieldThumbnailHeight : EditorGUI.kSingleLineHeight;\n        Rect r = s_LastRect = GetControlRect(true, height, options);\n        return EditorGUI.ObjectField(r, label, obj, objType, allowSceneObjects);\n    }\n\n    public static void ObjectField(SerializedProperty property, params GUILayoutOption[] options)\n    {\n        ObjectField(property, (GUIContent)null, options);\n    }\n\n    public static void ObjectField(SerializedProperty property, GUIContent label, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.objectField, options);\n        EditorGUI.ObjectField(r, property, label);\n    }\n\n    public static void ObjectField(SerializedProperty property, Type objType, params GUILayoutOption[] options)\n    {\n        ObjectField(property, objType, null, options);\n    }\n\n    // Make an object field. You can assign objects either by drag'n drop objects or by selecting an object using the Object Picker.\n    public static void ObjectField(SerializedProperty property, Type objType, GUIContent label, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.objectField, options);\n        EditorGUI.ObjectField(r, property, objType, label);\n    }\n\n    internal static void ObjectField(SerializedProperty property, Type objType, GUIContent label, EditorGUI.ObjectFieldValidator validator, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.objectField, options);\n        EditorGUI.ObjectField(r, property, objType, label, EditorStyles.objectField, validator);\n    }\n\n    internal static Object MiniThumbnailObjectField(GUIContent label, Object obj, Type objType, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, options);\n        return EditorGUI.MiniThumbnailObjectField(r, label, obj, objType);\n    }\n\n    public static Vector2 Vector2Field(string label, Vector2 value, params GUILayoutOption[] options)\n    {\n        return Vector2Field(EditorGUIUtility.TempContent(label), value, options);\n    }\n\n    // Make an X & Y field for entering a [[Vector2]].\n    public static Vector2 Vector2Field(GUIContent label, Vector2 value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector2, label), EditorStyles.numberField, options);\n        return EditorGUI.Vector2Field(r, label, value);\n    }\n\n    public static Vector3 Vector3Field(string label, Vector3 value, params GUILayoutOption[] options)\n    {\n        return Vector3Field(EditorGUIUtility.TempContent(label), value, options);\n    }\n\n    // Make an X, Y & Z field for entering a [[Vector3]].\n    public static Vector3 Vector3Field(GUIContent label, Vector3 value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, label), EditorStyles.numberField, options);\n        return EditorGUI.Vector3Field(r, label, value);\n    }\n\n    // Make an X, Y & Z field for entering a [[Vector3]], with a \"lock\"\n    internal static Vector3 LinkedVector3Field(GUIContent label, Vector3 value, ref bool proportionalScale, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, label), EditorStyles.numberField, options);\n        return EditorGUI.LinkedVector3Field(r, label, value, ref proportionalScale);\n    }\n\n    // Make an X, Y & Z field for entering a [[Vector3]], with a \"lock\"\n    internal static Vector3 LinkedVector3Field(GUIContent label, Vector3 value, Vector3 initialValue, ref bool proportionalScale, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, label), EditorStyles.numberField, options);\n        int axisModified = 0;// Use X as default modified axis\n        return EditorGUI.LinkedVector3Field(r, label, GUIContent.none, value, ref proportionalScale, initialValue, 0, ref axisModified, null);\n    }\n\n    // Make an X, Y, Z & W field for entering a [[Vector4]].\n    public static Vector4 Vector4Field(string label, Vector4 value, params GUILayoutOption[] options)\n    {\n        return Vector4Field(EditorGUIUtility.TempContent(label), value, options);\n    }\n\n    // Make an X, Y, Z & W field for entering a [[Vector4]].\n    public static Vector4 Vector4Field(GUIContent label, Vector4 value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector4, label), EditorStyles.numberField, options);\n        return EditorGUI.Vector4Field(r, label, value);\n    }\n\n    public static Vector2Int Vector2IntField(string label, Vector2Int value, params GUILayoutOption[] options)\n    {\n        return Vector2IntField(EditorGUIUtility.TempContent(label), value, options);\n    }\n\n    // Make an X & Y field for entering a [[Vector2Int]].\n    public static Vector2Int Vector2IntField(GUIContent label, Vector2Int value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector2Int, label), EditorStyles.numberField, options);\n        return EditorGUI.Vector2IntField(r, label, value);\n    }\n\n    public static Vector3Int Vector3IntField(string label, Vector3Int value, params GUILayoutOption[] options)\n    {\n        return Vector3IntField(EditorGUIUtility.TempContent(label), value, options);\n    }\n\n    // Make an X, Y & Z field for entering a [[Vector3Int]].\n    public static Vector3Int Vector3IntField(GUIContent label, Vector3Int value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3Int, label), EditorStyles.numberField, options);\n        return EditorGUI.Vector3IntField(r, label, value);\n    }\n\n    public static Rect RectField(Rect value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.GetPropertyHeight(SerializedPropertyType.Rect, GUIContent.none), EditorStyles.numberField, options);\n        return EditorGUI.RectField(r, value);\n    }\n\n    public static Rect RectField(string label, Rect value, params GUILayoutOption[] options)\n    {\n        return RectField(EditorGUIUtility.TempContent(label), value, options);\n    }\n\n    // Make an X, Y, W & H field for entering a [[Rect]].\n    public static Rect RectField(GUIContent label, Rect value, params GUILayoutOption[] options)\n    {\n        bool hasLabel = EditorGUI.LabelHasContent(label);\n        float height = EditorGUI.GetPropertyHeight(SerializedPropertyType.Rect, label);\n        Rect r = s_LastRect = GetControlRect(hasLabel, height, EditorStyles.numberField, options);\n        return EditorGUI.RectField(r, label, value);\n    }\n\n    public static RectInt RectIntField(RectInt value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.GetPropertyHeight(SerializedPropertyType.RectInt, GUIContent.none), EditorStyles.numberField, options);\n        return EditorGUI.RectIntField(r, value);\n    }\n\n    public static RectInt RectIntField(string label, RectInt value, params GUILayoutOption[] options)\n    {\n        return RectIntField(EditorGUIUtility.TempContent(label), value, options);\n    }\n\n    // Make an X, Y, W & H field for entering a [[RectInt]].\n    public static RectInt RectIntField(GUIContent label, RectInt value, params GUILayoutOption[] options)\n    {\n        bool hasLabel = EditorGUI.LabelHasContent(label);\n        float height = EditorGUI.GetPropertyHeight(SerializedPropertyType.RectInt, label);\n        Rect r = s_LastRect = GetControlRect(hasLabel, height, EditorStyles.numberField, options);\n        return EditorGUI.RectIntField(r, label, value);\n    }\n\n    public static Bounds BoundsField(Bounds value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.GetPropertyHeight(SerializedPropertyType.Bounds, GUIContent.none), EditorStyles.numberField, options);\n        return EditorGUI.BoundsField(r, value);\n    }\n\n    public static Bounds BoundsField(string label, Bounds value, params GUILayoutOption[] options)\n    {\n        return BoundsField(EditorGUIUtility.TempContent(label), value, options);\n    }\n\n    // Make Center & Extents field for entering a [[Bounds]].\n    public static Bounds BoundsField(GUIContent label, Bounds value, params GUILayoutOption[] options)\n    {\n        bool hasLabel = EditorGUI.LabelHasContent(label);\n        float height = EditorGUI.GetPropertyHeight(SerializedPropertyType.Bounds, label);\n        Rect r = s_LastRect = GetControlRect(hasLabel, height, EditorStyles.numberField, options);\n        return EditorGUI.BoundsField(r, label, value);\n    }\n\n    public static BoundsInt BoundsIntField(BoundsInt value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.GetPropertyHeight(SerializedPropertyType.BoundsInt, GUIContent.none), EditorStyles.numberField, options);\n        return EditorGUI.BoundsIntField(r, value);\n    }\n\n    public static BoundsInt BoundsIntField(string label, BoundsInt value, params GUILayoutOption[] options)\n    {\n        return BoundsIntField(EditorGUIUtility.TempContent(label), value, options);\n    }\n\n    // Make Center & Extents field for entering a [[BoundsInt]].\n    public static BoundsInt BoundsIntField(GUIContent label, BoundsInt value, params GUILayoutOption[] options)\n    {\n        bool hasLabel = EditorGUI.LabelHasContent(label);\n        float height = EditorGUI.GetPropertyHeight(SerializedPropertyType.BoundsInt, label);\n        Rect r = s_LastRect = GetControlRect(hasLabel, height, EditorStyles.numberField, options);\n        return EditorGUI.BoundsIntField(r, label, value);\n    }\n\n    // Make a property field that look like a multi property field (but is made up of individual properties)\n    internal static void PropertiesField(GUIContent label, SerializedProperty[] properties, GUIContent[] propertyLabels, float propertyLabelsWidth, params GUILayoutOption[] options)\n    {\n        bool hasLabel = EditorGUI.LabelHasContent(label);\n        float height = EditorGUI.kSingleLineHeight * properties.Length + EditorGUI.kVerticalSpacingMultiField * (properties.Length - 1);\n        Rect r = s_LastRect = GetControlRect(hasLabel, height, EditorStyles.numberField, options);\n        EditorGUI.PropertiesField(r, label, properties, propertyLabels, propertyLabelsWidth);\n    }\n\n    internal static int CycleButton(int selected, GUIContent[] contents, GUIStyle style, params GUILayoutOption[] options)\n    {\n        if (GUILayout.Button(contents[selected], style, options))\n        {\n            selected++;\n            if (selected >= contents.Length)\n                selected = 0;\n        }\n        return selected;\n    }\n\n    public static Color ColorField(Color value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n        return EditorGUI.ColorField(r, value);\n    }\n\n    public static Color ColorField(string label, Color value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n        return EditorGUI.ColorField(r, label, value);\n    }\n\n    // Make a field for selecting a [[Color]].\n    public static Color ColorField(GUIContent label, Color value, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n        return EditorGUI.ColorField(r, label, value);\n    }\n\n#pragma warning disable 612\n    [Obsolete(\"Use EditorGUILayout.ColorField(GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr, params GUILayoutOption[] options)\")]\n    public static Color ColorField(\n        GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr, ColorPickerHDRConfig hdrConfig, params GUILayoutOption[] options\n    )\n    {\n        return ColorField(label, value, showEyedropper, showAlpha, hdr);\n    }\n\n#pragma warning restore 612\n\n    public static Color ColorField(GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n        return EditorGUI.ColorField(r, label, value, showEyedropper, showAlpha, hdr);\n    }\n\n    public static AnimationCurve CurveField(AnimationCurve value, params GUILayoutOption[] options)\n    {\n        // TODO Change style\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n        return EditorGUI.CurveField(r, value);\n    }\n\n    public static AnimationCurve CurveField(string label, AnimationCurve value, params GUILayoutOption[] options)\n    {\n        // TODO Change style\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n        return EditorGUI.CurveField(r, label, value);\n    }\n\n    public static AnimationCurve CurveField(GUIContent label, AnimationCurve value, params GUILayoutOption[] options)\n    {\n        // TODO Change style\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n        return EditorGUI.CurveField(r, label, value);\n    }\n\n    // Variants with settings\n    public static AnimationCurve CurveField(AnimationCurve value, Color color, Rect ranges, params GUILayoutOption[] options)\n    {\n        // TODO Change style\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n        return EditorGUI.CurveField(r, value, color, ranges);\n    }\n\n    public static AnimationCurve CurveField(string label, AnimationCurve value, Color color, Rect ranges, params GUILayoutOption[] options)\n    {\n        // TODO Change style\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n        return EditorGUI.CurveField(r, label, value, color, ranges);\n    }\n\n    // Make a field for editing an [[AnimationCurve]].\n    public static AnimationCurve CurveField(GUIContent label, AnimationCurve value, Color color, Rect ranges, params GUILayoutOption[] options)\n    {\n        // TODO Change style\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n        return EditorGUI.CurveField(r, label, value, color, ranges);\n    }\n\n    public static void CurveField(SerializedProperty property, Color color, Rect ranges, params GUILayoutOption[] options)\n    {\n        CurveField(property, color, ranges, null, options);\n    }\n\n    // Make a field for editing an [[AnimationCurve]].\n    public static void CurveField(SerializedProperty property, Color color, Rect ranges, GUIContent label, params GUILayoutOption[] options)\n    {\n        // TODO Change style\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n        EditorGUI.CurveField(r, property, color, ranges, label);\n    }\n\n    public static bool InspectorTitlebar(bool foldout, Object targetObj)\n    {\n        return InspectorTitlebar(foldout, targetObj, true);\n    }\n\n    public static bool InspectorTitlebar(bool foldout, Object targetObj, bool expandable)\n    {\n        return EditorGUI.InspectorTitlebar(GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar), foldout,\n            targetObj, expandable);\n    }\n\n    // Make an inspector-window-like titlebar.\n    public static bool InspectorTitlebar(bool foldout, Object[] targetObjs)\n    {\n        return InspectorTitlebar(foldout, targetObjs, true);\n    }\n\n    public static bool InspectorTitlebar(bool foldout, Object[] targetObjs, bool expandable)\n    {\n        return EditorGUI.InspectorTitlebar(GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar), foldout,\n            targetObjs, expandable);\n    }\n\n    public static bool InspectorTitlebar(bool foldout, Editor editor)\n    {\n        return EditorGUI.InspectorTitlebar(GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar), foldout,\n            editor);\n    }\n\n    public static void InspectorTitlebar(Object[] targetObjs)\n    {\n        EditorGUI.InspectorTitlebar(GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar), targetObjs);\n    }\n\n    // Make a foldout with a toggle and title\n    internal static bool ToggleTitlebar(bool foldout, GUIContent label, ref bool toggleValue)\n    {\n        return EditorGUI.ToggleTitlebar(GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar), label, foldout, ref toggleValue);\n    }\n\n    internal static bool ToggleTitlebar(bool foldout, GUIContent label, SerializedProperty property)\n    {\n        bool toggleValue = property.boolValue;\n        EditorGUI.BeginChangeCheck();\n        foldout = EditorGUI.ToggleTitlebar(GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar), label, foldout, ref toggleValue);\n        if (EditorGUI.EndChangeCheck())\n            property.boolValue = toggleValue;\n\n        return foldout;\n    }\n\n    internal static bool FoldoutTitlebar(bool foldout, GUIContent label, bool skipIconSpacing)\n    {\n        return FoldoutTitlebar(foldout, label, skipIconSpacing, EditorStyles.inspectorTitlebar, EditorStyles.inspectorTitlebarText);\n    }\n\n    internal static bool FoldoutTitlebar(bool foldout, GUIContent label, bool skipIconSpacing, GUIStyle baseStyle, GUIStyle textStyle)\n    {\n        return EditorGUI.FoldoutTitlebar(GUILayoutUtility.GetRect(GUIContent.none, baseStyle, GUILayout.ExpandWidth(true)), label, foldout, skipIconSpacing, baseStyle, textStyle);\n    }\n\n    // Make a label with a foldout arrow to the left of it.\n    internal static bool FoldoutInternal(bool foldout, GUIContent content, bool toggleOnLabelClick, GUIStyle style)\n    {\n        Rect r = s_LastRect = GUILayoutUtility.GetRect(EditorGUIUtility.fieldWidth, EditorGUIUtility.fieldWidth, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, style);\n        return EditorGUI.Foldout(r, foldout, content, toggleOnLabelClick, style);\n    }\n\n    internal static uint LayerMaskField(UInt32 layers, GUIContent label, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, options);\n        return EditorGUI.LayerMaskField(r, layers, label);\n    }\n\n    internal static LayerMask LayerMaskField(LayerMask layers, GUIContent label, params GUILayoutOption[] options)\n    {\n        var rect = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, options);\n        return EditorGUI.LayerMaskField(rect, layers, label);\n    }\n\n    internal static void LayerMaskField(SerializedProperty property, GUIContent label, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, options);\n        EditorGUI.LayerMaskField(r, property, label);\n    }\n\n    public static void HelpBox(string message, MessageType type)\n    {\n        HelpBox(EditorGUIUtility.TempContent(message, EditorGUIUtility.GetHelpIcon(type)), true);\n    }\n\n    // Make a help box with a message to the user.\n    public static void HelpBox(string message, MessageType type, bool wide)\n    {\n        HelpBox(EditorGUIUtility.TempContent(message, EditorGUIUtility.GetHelpIcon(type)), wide);\n    }\n\n    // Make a help box with a message to the user.\n    public static void HelpBox(GUIContent content, bool wide = true)\n    {\n        LabelField(wide ? GUIContent.none : EditorGUIUtility.blankContent, content, EditorStyles.helpBox);\n    }\n\n    // Make a label in front of some control.\n    internal static void PrefixLabelInternal(GUIContent label, GUIStyle followingStyle, GUIStyle labelStyle)\n    {\n        float p = followingStyle.margin.left;\n        if (!EditorGUI.LabelHasContent(label))\n        {\n            GUILayoutUtility.GetRect(EditorGUI.indent - p, EditorGUI.kSingleLineHeight, followingStyle, GUILayout.ExpandWidth(false));\n            return;\n        }\n\n        Rect r = GUILayoutUtility.GetRect(EditorGUIUtility.labelWidth - p, EditorGUI.kSingleLineHeight, followingStyle, GUILayout.ExpandWidth(false));\n        r.xMin += EditorGUI.indent;\n        EditorGUI.HandlePrefixLabel(r, r, label, 0, labelStyle);\n    }\n\n    // Make a small space between the previous control and the following.\n    public static void Space()\n    {\n        Space(EditorGUI.kDefaultSpacing, true);\n    }\n\n    public static void Space(float width)\n    {\n        Space(width, true);\n    }\n\n    public static void Space(float width, bool expand)\n    {\n        GUILayoutUtility.GetRect(width, width, GUILayout.ExpandWidth(expand));\n    }\n\n    //[System.Obsolete (\"Use Space() instead\")]\n    // Make this function Obsolete when someone has time to _rename_ all\n    // the Standard Packages to Space(), as currently it shows tons of\n    // warnings.\n    // Same for the graphic tests.\n    // *undoc*\n    public static void Separator()\n    {\n        Space();\n    }\n\n    public class ToggleGroupScope : GUI.Scope\n    {\n        public bool enabled { get; protected set; }\n\n        public ToggleGroupScope(string label, bool toggle)\n        {\n            enabled = BeginToggleGroup(label, toggle);\n        }\n\n        public ToggleGroupScope(GUIContent label, bool toggle)\n        {\n            enabled = BeginToggleGroup(label, toggle);\n        }\n\n        protected override void CloseScope()\n        {\n            EndToggleGroup();\n        }\n    }\n\n    public static bool BeginToggleGroup(string label, bool toggle)\n    {\n        return BeginToggleGroup(EditorGUIUtility.TempContent(label), toggle);\n    }\n\n    // Begin a vertical group with a toggle to enable or disable all the controls within at once.\n    public static bool BeginToggleGroup(GUIContent label, bool toggle)\n    {\n        toggle = ToggleLeft(label, toggle, EditorStyles.boldLabel);\n        EditorGUI.BeginDisabled(!toggle);\n        GUILayout.BeginVertical();\n\n        return toggle;\n    }\n\n    // Close a group started with ::ref::BeginToggleGroup\n    public static void EndToggleGroup()\n    {\n        GUILayout.EndVertical();\n        EditorGUI.EndDisabled();\n    }\n\n    public class HorizontalScope : GUI.Scope\n    {\n        public Rect rect { get; protected set; }\n\n        public HorizontalScope(params GUILayoutOption[] options)\n        {\n            rect = BeginHorizontal(options);\n        }\n\n        public HorizontalScope(GUIStyle style, params GUILayoutOption[] options)\n        {\n            rect = BeginHorizontal(style, options);\n        }\n\n        internal HorizontalScope(GUIContent content, GUIStyle style, params GUILayoutOption[] options)\n        {\n            rect = BeginHorizontal(content, style, options);\n        }\n\n        protected override void CloseScope()\n        {\n            EndHorizontal();\n        }\n    }\n\n    public static Rect BeginHorizontal(params GUILayoutOption[] options)\n    {\n        return BeginHorizontal(GUIContent.none, GUIStyle.none, options);\n    }\n\n    // Begin a horizontal group and get its rect back.\n    public static Rect BeginHorizontal(GUIStyle style, params GUILayoutOption[] options)\n    {\n        return BeginHorizontal(GUIContent.none, style, options);\n    }\n\n    // public static Rect BeginHorizontal (string text, params GUILayoutOption[] options)                       { return BeginHorizontal (EditorGUIUtility.TempContent (text), GUIStyle.none, options); }\n    // public static Rect BeginHorizontal (Texture image, params GUILayoutOption[] options)                 { return BeginHorizontal (EditorGUIUtility.TempContent (image), GUIStyle.none, options); }\n    // public static Rect BeginHorizontal (GUIContent content, params GUILayoutOption[] options)                { return BeginHorizontal (content, GUIStyle.none, options); }\n    // public static Rect BeginHorizontal (string text, GUIStyle style, params GUILayoutOption[] options)           { return BeginHorizontal (EditorGUIUtility.TempContent (text), style, options); }\n    // public static Rect BeginHorizontal (Texture image, GUIStyle style, params GUILayoutOption[] options)     { return BeginHorizontal (EditorGUIUtility.TempContent (image), style, options); }\n    internal static Rect BeginHorizontal(GUIContent content, GUIStyle style, params GUILayoutOption[] options)\n    {\n        GUILayoutGroup g = GUILayoutUtility.BeginLayoutGroup(style, options, typeof(GUILayoutGroup));\n        g.isVertical = false;\n        if (style != GUIStyle.none || content != GUIContent.none)\n        {\n            GUI.Box(g.rect, GUIContent.none, style);\n        }\n        return g.rect;\n    }\n\n    // Close a group started with BeginHorizontal\n    public static void EndHorizontal()\n    {\n        GUILayout.EndHorizontal();\n    }\n\n    public class VerticalScope : GUI.Scope\n    {\n        public Rect rect { get; protected set; }\n\n        public VerticalScope(params GUILayoutOption[] options)\n        {\n            rect = BeginVertical(options);\n        }\n\n        public VerticalScope(GUIStyle style, params GUILayoutOption[] options)\n        {\n            rect = BeginVertical(style, options);\n        }\n\n        internal VerticalScope(GUIContent content, GUIStyle style, params GUILayoutOption[] options)\n        {\n            rect = BeginVertical(content, style, options);\n        }\n\n        protected override void CloseScope()\n        {\n            EndVertical();\n        }\n    }\n\n    public static Rect BeginVertical(params GUILayoutOption[] options)\n    {\n        return BeginVertical(GUIContent.none, GUIStyle.none, options);\n    }\n\n    // Begin a vertical group and get its rect back.\n    public static Rect BeginVertical(GUIStyle style, params GUILayoutOption[] options)\n    {\n        return BeginVertical(GUIContent.none, style, options);\n    }\n\n    // public static Rect BeginVertical (string text, params GUILayoutOption[] options)                     { return BeginVertical (EditorGUIUtility.TempContent (text), GUIStyle.none, options); }\n    // public static Rect BeginVertical (Texture image, params GUILayoutOption[] options)                   { return BeginVertical (EditorGUIUtility.TempContent (image), GUIStyle.none, options); }\n    // public static Rect BeginVertical (GUIContent content, params GUILayoutOption[] options)              { return BeginVertical (content, GUIStyle.none, options); }\n    // public static Rect BeginVertical (string text, GUIStyle style, params GUILayoutOption[] options)         { return BeginVertical (EditorGUIUtility.TempContent (text), style, options); }\n    // public static Rect BeginVertical (Texture image, GUIStyle style, params GUILayoutOption[] options)       { return BeginVertical (EditorGUIUtility.TempContent (image), style, options); }\n    internal static Rect BeginVertical(GUIContent content, GUIStyle style, params GUILayoutOption[] options)\n    {\n        GUILayoutGroup g = GUILayoutUtility.BeginLayoutGroup(style, options, typeof(GUILayoutGroup));\n        g.isVertical = true;\n        if (style != GUIStyle.none || content != GUIContent.none)\n        {\n            GUI.Box(g.rect, GUIContent.none, style);\n        }\n        return g.rect;\n    }\n\n    // Close a group started with BeginVertical\n    public static void EndVertical()\n    {\n        GUILayout.EndVertical();\n    }\n\n    public class ScrollViewScope : GUI.Scope\n    {\n        public Vector2 scrollPosition { get; protected set; }\n        public bool handleScrollWheel { get; set; }\n\n        public ScrollViewScope(Vector2 scrollPosition, params GUILayoutOption[] options)\n        {\n            handleScrollWheel = true;\n            this.scrollPosition = BeginScrollView(scrollPosition, options);\n        }\n\n        public ScrollViewScope(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical, params GUILayoutOption[] options)\n        {\n            handleScrollWheel = true;\n            this.scrollPosition = BeginScrollView(scrollPosition, alwaysShowHorizontal, alwaysShowVertical, options);\n        }\n\n        public ScrollViewScope(Vector2 scrollPosition, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, params GUILayoutOption[] options)\n        {\n            handleScrollWheel = true;\n            this.scrollPosition = BeginScrollView(scrollPosition, horizontalScrollbar, verticalScrollbar, options);\n        }\n\n        public ScrollViewScope(Vector2 scrollPosition, GUIStyle style, params GUILayoutOption[] options)\n        {\n            handleScrollWheel = true;\n            this.scrollPosition = BeginScrollView(scrollPosition, style, options);\n        }\n\n        public ScrollViewScope(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options)\n        {\n            handleScrollWheel = true;\n            this.scrollPosition = BeginScrollView(scrollPosition, alwaysShowHorizontal, alwaysShowVertical, horizontalScrollbar, verticalScrollbar, background, options);\n        }\n\n        internal ScrollViewScope(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, params GUILayoutOption[] options)\n        {\n            handleScrollWheel = true;\n            this.scrollPosition = BeginScrollView(scrollPosition, alwaysShowHorizontal, alwaysShowVertical, horizontalScrollbar, verticalScrollbar, options);\n        }\n\n        protected override void CloseScope()\n        {\n            EndScrollView(handleScrollWheel);\n        }\n    }\n\n    public static Vector2 BeginScrollView(Vector2 scrollPosition, params GUILayoutOption[] options)\n    {\n        return BeginScrollView(scrollPosition, false, false, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar, GUI.skin.scrollView, options);\n    }\n\n    public static Vector2 BeginScrollView(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical, params GUILayoutOption[] options)\n    {\n        return BeginScrollView(scrollPosition, alwaysShowHorizontal, alwaysShowVertical, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar, GUI.skin.scrollView, options);\n    }\n\n    public static Vector2 BeginScrollView(Vector2 scrollPosition, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, params GUILayoutOption[] options)\n    {\n        return BeginScrollView(scrollPosition, false, false, horizontalScrollbar, verticalScrollbar, GUI.skin.scrollView, options);\n    }\n\n    public static Vector2 BeginScrollView(Vector2 scrollPosition, GUIStyle style, params GUILayoutOption[] options)\n    {\n        string name = style.name;\n\n        GUIStyle vertical = GUI.skin.FindStyle(name + \"VerticalScrollbar\") ?? GUI.skin.verticalScrollbar;\n        GUIStyle horizontal = GUI.skin.FindStyle(name + \"HorizontalScrollbar\") ?? GUI.skin.horizontalScrollbar;\n        return BeginScrollView(scrollPosition, false, false, horizontal, vertical, style, options);\n    }\n\n    internal static Vector2 BeginScrollView(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, params GUILayoutOption[] options)\n    {\n        return BeginScrollView(scrollPosition, alwaysShowHorizontal, alwaysShowVertical, horizontalScrollbar, verticalScrollbar, GUI.skin.scrollView, options);\n    }\n\n    // Begin an automatically layouted scrollview.\n    public static Vector2 BeginScrollView(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options)\n    {\n        GUIScrollGroup g = (GUIScrollGroup)GUILayoutUtility.BeginLayoutGroup(background, null, typeof(GUIScrollGroup));\n        if (Event.current.type == EventType.Layout)\n        {\n            g.resetCoords = true;\n            g.isVertical = true;\n            g.stretchWidth = 1;\n            g.stretchHeight = 1;\n            g.verticalScrollbar = verticalScrollbar;\n            g.horizontalScrollbar = horizontalScrollbar;\n            g.ApplyOptions(options);\n        }\n        return EditorGUIInternal.DoBeginScrollViewForward(g.rect, scrollPosition, new Rect(0, 0, g.clientWidth, g.clientHeight), alwaysShowHorizontal, alwaysShowVertical, horizontalScrollbar, verticalScrollbar, background);\n    }\n\n    internal class VerticalScrollViewScope : GUI.Scope\n    {\n        public Vector2 scrollPosition { get; protected set; }\n        public bool handleScrollWheel { get; set; }\n\n        public VerticalScrollViewScope(Vector2 scrollPosition, params GUILayoutOption[] options)\n        {\n            handleScrollWheel = true;\n            this.scrollPosition = BeginVerticalScrollView(scrollPosition, options);\n        }\n\n        public VerticalScrollViewScope(Vector2 scrollPosition, bool alwaysShowVertical, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options)\n        {\n            handleScrollWheel = true;\n            this.scrollPosition = BeginVerticalScrollView(scrollPosition, alwaysShowVertical, verticalScrollbar, background, options);\n        }\n\n        protected override void CloseScope()\n        {\n            EndScrollView(handleScrollWheel);\n        }\n    }\n\n    internal static Vector2 BeginVerticalScrollView(Vector2 scrollPosition, params GUILayoutOption[] options)\n    {\n        return BeginVerticalScrollView(scrollPosition, false, GUI.skin.verticalScrollbar, GUI.skin.scrollView, options);\n    }\n\n    // Begin an automatically layouted scrollview.\n    internal static Vector2 BeginVerticalScrollView(Vector2 scrollPosition, bool alwaysShowVertical, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options)\n    {\n        GUIScrollGroup g = (GUIScrollGroup)GUILayoutUtility.BeginLayoutGroup(background, null, typeof(GUIScrollGroup));\n        if (Event.current.type == EventType.Layout)\n        {\n            g.resetCoords = true;\n            g.isVertical = true;\n            g.stretchWidth = 1;\n            g.stretchHeight = 1;\n            g.verticalScrollbar = verticalScrollbar;\n            g.horizontalScrollbar = GUIStyle.none;\n            g.allowHorizontalScroll = false;\n            g.ApplyOptions(options);\n        }\n        return EditorGUIInternal.DoBeginScrollViewForward(g.rect, scrollPosition, new Rect(0, 0, g.clientWidth, g.clientHeight), false, alwaysShowVertical, GUI.skin.horizontalScrollbar, verticalScrollbar, background);\n    }\n\n    internal class HorizontalScrollViewScope : GUI.Scope\n    {\n        public Vector2 scrollPosition { get; protected set; }\n        public bool handleScrollWheel { get; set; }\n\n        public HorizontalScrollViewScope(Vector2 scrollPosition, params GUILayoutOption[] options)\n        {\n            handleScrollWheel = true;\n            this.scrollPosition = BeginHorizontalScrollView(scrollPosition, options);\n        }\n\n        public HorizontalScrollViewScope(Vector2 scrollPosition, bool alwaysShowHorizontal, GUIStyle horizontalScrollbar, GUIStyle background, params GUILayoutOption[] options)\n        {\n            handleScrollWheel = true;\n            this.scrollPosition = BeginHorizontalScrollView(scrollPosition, alwaysShowHorizontal, horizontalScrollbar, background, options);\n        }\n\n        protected override void CloseScope()\n        {\n            EndScrollView(handleScrollWheel);\n        }\n    }\n\n    internal static Vector2 BeginHorizontalScrollView(Vector2 scrollPosition, params GUILayoutOption[] options)\n    {\n        return BeginHorizontalScrollView(scrollPosition, false, GUI.skin.horizontalScrollbar, GUI.skin.scrollView, options);\n    }\n\n    // Begin an automatically layouted scrollview.\n\n    internal static Vector2 BeginHorizontalScrollView(Vector2 scrollPosition, bool alwaysShowHorizontal, GUIStyle horizontalScrollbar, GUIStyle background, params GUILayoutOption[] options)\n    {\n        GUIScrollGroup g = (GUIScrollGroup)GUILayoutUtility.BeginLayoutGroup(background, null, typeof(GUIScrollGroup));\n        if (Event.current.type == EventType.Layout)\n        {\n            g.resetCoords = true;\n            g.isVertical = true;\n            g.stretchWidth = 1;\n            g.stretchHeight = 1;\n            g.verticalScrollbar = GUIStyle.none;\n            g.horizontalScrollbar = horizontalScrollbar;\n            g.allowHorizontalScroll = true;\n            g.allowVerticalScroll = false;\n            g.ApplyOptions(options);\n        }\n        return EditorGUIInternal.DoBeginScrollViewForward(g.rect, scrollPosition, new Rect(0, 0, g.clientWidth, g.clientHeight), alwaysShowHorizontal, false, horizontalScrollbar, GUI.skin.verticalScrollbar, background);\n    }\n\n    // Ends a scrollview started with a call to BeginScrollView.\n    public static void EndScrollView()\n    {\n        GUILayout.EndScrollView(true);\n    }\n\n    internal static void EndScrollView(bool handleScrollWheel)\n    {\n        GUILayout.EndScrollView(handleScrollWheel);\n    }\n\n    public static bool PropertyField(SerializedProperty property, params GUILayoutOption[] options)\n    {\n        return PropertyField(property, null, IsChildrenIncluded(property), options);\n    }\n\n    public static bool PropertyField(SerializedProperty property, GUIContent label, params GUILayoutOption[] options)\n    {\n        return PropertyField(property, label, IsChildrenIncluded(property), options);\n    }\n\n    public static bool PropertyField(SerializedProperty property, bool includeChildren, params GUILayoutOption[] options)\n    {\n        return PropertyField(property, null, includeChildren, options);\n    }\n\n    // Make a field for [[SerializedProperty]].\n    public static bool PropertyField(SerializedProperty property, GUIContent label, bool includeChildren, params GUILayoutOption[] options)\n    {\n        return ScriptAttributeUtility.GetHandler(property).OnGUILayout(property, label, includeChildren, options);\n    }\n\n    private static bool IsChildrenIncluded(SerializedProperty prop)\n    {\n        switch (prop.propertyType)\n        {\n            case SerializedPropertyType.Generic:\n            case SerializedPropertyType.Vector4:\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    public static Rect GetControlRect(params GUILayoutOption[] options)\n    {\n        return GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.layerMaskField, options);\n    }\n\n    public static Rect GetControlRect(bool hasLabel, params GUILayoutOption[] options)\n    {\n        return GetControlRect(hasLabel, EditorGUI.kSingleLineHeight, EditorStyles.layerMaskField, options);\n    }\n\n    public static Rect GetControlRect(bool hasLabel, float height, params GUILayoutOption[] options)\n    {\n        return GetControlRect(hasLabel, height, EditorStyles.layerMaskField, options);\n    }\n\n    public static Rect GetControlRect(bool hasLabel, float height, GUIStyle style, params GUILayoutOption[] options)\n    {\n        return GUILayoutUtility.GetRect(\n            hasLabel ? kLabelFloatMinW : EditorGUIUtility.fieldWidth,\n            kLabelFloatMaxW,\n            height, height, style, options);\n    }\n\n    internal static Rect GetSliderRect(bool hasLabel, params GUILayoutOption[] options)\n    {\n        return GetSliderRect(hasLabel, GUI.skin.horizontalSlider, options);\n    }\n\n    internal static Rect GetSliderRect(bool hasLabel, GUIStyle sliderStyle, params GUILayoutOption[] options)\n    {\n        return GUILayoutUtility.GetRect(\n            hasLabel ? kLabelFloatMinW : EditorGUIUtility.fieldWidth,\n            kLabelFloatMaxW + EditorGUI.kSpacing + EditorGUI.kSliderMaxW,\n            EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, sliderStyle, options);\n    }\n\n    internal static Rect GetToggleRect(bool hasLabel, params GUILayoutOption[] options)\n    {\n        // Toggle is 14 pixels wide while float fields are EditorGUIUtility.fieldWidth pixels wide.\n        // Store difference in variable and add to min and max width values used for float fields.\n        float toggleAdjust = (14 - EditorGUIUtility.fieldWidth);\n        return GUILayoutUtility.GetRect(\n            hasLabel ? kLabelFloatMinW + toggleAdjust : EditorGUIUtility.fieldWidth + toggleAdjust,\n            kLabelFloatMaxW + toggleAdjust,\n            EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n    }\n\n    public class FadeGroupScope : GUI.Scope\n    {\n        // when using the FadeGroupScope, make sure to only show the content when 'visible' is set to true,\n        // otherwise only the hide animation will run, and then the content will be visible again.\n        public bool visible { get; protected set; }\n\n        public FadeGroupScope(float value)\n        {\n            visible = BeginFadeGroup(value);\n        }\n\n        protected override void CloseScope()\n        {\n            EndFadeGroup();\n        }\n    }\n\n    public static bool BeginFadeGroup(float value)\n    {\n        GUILayoutFadeGroup g = (GUILayoutFadeGroup)GUILayoutUtility.BeginLayoutGroup(GUIStyle.none, null, typeof(GUILayoutFadeGroup));\n        g.isVertical = true;\n        g.resetCoords = false;\n        g.fadeValue = value;\n        g.wasGUIEnabled = GUI.enabled;\n        g.guiColor = GUI.color;\n        g.consideredForMargin = value > 0;\n\n        // We don't want the fade group gui clip to be used for calculating the label width of controls in this fade group, so we lock the context width.\n        EditorGUIUtility.LockContextWidth();\n\n        if (value != 0.0f && value != 1.0f)\n        {\n            g.resetCoords = true;\n            GUI.BeginGroup(g.rect);\n\n            if (Event.current.type == EventType.MouseDown)\n            {\n                Event.current.Use();\n            }\n        }\n\n        return value != 0;\n    }\n\n    public static void EndFadeGroup()\n    {\n        // If we're inside a fade group, end it here.\n        GUILayoutFadeGroup g = EditorGUILayoutUtilityInternal.topLevel as GUILayoutFadeGroup;\n\n        // If there are no more FadeGroups to end, display a warning.\n        if (g == null)\n        {\n            Debug.LogWarning(\"Unexpected call to EndFadeGroup! Make sure to call EndFadeGroup the same number of times as BeginFadeGroup.\");\n            return;\n        }\n\n        if (g.fadeValue != 0.0f && g.fadeValue != 1.0f)\n        {\n            GUI.EndGroup();\n        }\n\n        EditorGUIUtility.UnlockContextWidth();\n        GUI.enabled = g.wasGUIEnabled;\n        GUI.color = g.guiColor;\n        GUILayoutUtility.EndLayoutGroup();\n    }\n\n    public static BuildTargetGroup BeginBuildTargetSelectionGrouping()\n    {\n        BuildPlatform[] validPlatforms = BuildPlatforms.instance.GetValidPlatforms().ToArray();\n        int selected = BeginPlatformGrouping(validPlatforms, null);\n        return validPlatforms[selected].namedBuildTarget.ToBuildTargetGroup();\n    }\n\n    public static void EndBuildTargetSelectionGrouping()\n    {\n        EndPlatformGrouping();\n    }\n\n    internal static int BeginPlatformGrouping(BuildPlatform[] platforms, GUIContent defaultTab)\n    {\n        return BeginPlatformGrouping(platforms, defaultTab, EditorStyles.frameBox);\n    }\n\n    static Rect GetTabRect(Rect rect, int tabIndex, int tabCount, out GUIStyle tabStyle)\n    {\n        if (s_TabOnlyOne == null)\n        {\n            // Keep in sync with Tests/EditModeAndPlayModeTests/PlayerSettings/Assets/Editor/PlayerSettingsApplicationIdentifierTests.cs.\n            s_TabOnlyOne = \"Tab onlyOne\";\n            s_TabFirst = \"Tab first\";\n            s_TabMiddle = \"Tab middle\";\n            s_TabLast = \"Tab last\";\n        }\n\n        tabStyle = s_TabMiddle;\n\n        if (tabCount == 1)\n        {\n            tabStyle = s_TabOnlyOne;\n        }\n        else if (tabIndex == 0)\n        {\n            tabStyle = s_TabFirst;\n        }\n        else if (tabIndex == (tabCount - 1))\n        {\n            tabStyle = s_TabLast;\n        }\n\n        float tabWidth = rect.width / tabCount;\n        int left = Mathf.RoundToInt(tabIndex * tabWidth);\n        int right = Mathf.RoundToInt((tabIndex + 1) * tabWidth);\n        return new Rect(rect.x + left, rect.y, right - left, EditorGUI.kTabButtonHeight);\n    }\n\n    internal static int BeginPlatformGrouping(BuildPlatform[] platforms, GUIContent defaultTab, GUIStyle style)\n    {\n        return BeginPlatformGrouping(platforms, defaultTab, style, null);\n    }\n\n    internal static int BeginPlatformGrouping(BuildPlatform[] platforms, GUIContent defaultTab, GUIStyle style, Func<int, bool> showOverrideForPlatform)\n    {\n        int selectedPlatform = -1;\n        for (int i = 0; i < platforms.Length; i++)\n        {\n            if (platforms[i].IsSelected())\n            {\n                selectedPlatform = i;\n                break;\n            }\n        }\n        if (selectedPlatform == -1)\n        {\n            s_SelectedDefault.value = true;\n            selectedPlatform = 0;\n        }\n\n        int selected = defaultTab == null ? selectedPlatform : (s_SelectedDefault.value ? -1 : selectedPlatform);\n\n        bool tempEnabled = GUI.enabled;\n        GUI.enabled = true;\n        EditorGUI.BeginChangeCheck();\n        Rect r = BeginVertical(style);\n        int platformCount = platforms.Length;\n        int buttonCount = platformCount;\n        int startIndex = 0;\n\n        if (defaultTab != null)\n        {\n            buttonCount++;\n            startIndex = -1;\n        }\n\n        int buttonIndex = 0;\n        for (int i = startIndex; i < platformCount; i++, buttonIndex++)\n        {\n            GUIContent content = GUIContent.none;\n\n            if (i == -1)\n            {\n                content = defaultTab;\n            }\n            else\n            {\n                content = new GUIContent(platforms[i].compoundSmallIcon, platforms[i].compoundTooltip);\n            }\n\n            GUIStyle buttonStyle = null;\n            Rect buttonRect = GetTabRect(r, buttonIndex, buttonCount, out buttonStyle);\n\n            if (GUI.Toggle(buttonRect, selected == i, content, buttonStyle))\n                selected = i;\n            if (showOverrideForPlatform != null)\n            {\n                if (showOverrideForPlatform(i))\n                {\n                    var prevMargin = EditorGUIUtility.leftMarginCoord;\n                    var overrideRect = buttonRect;\n                    const int margin = 3;\n                    overrideRect.y += margin;\n                    overrideRect.height -= margin * 2;\n                    EditorGUIUtility.leftMarginCoord = overrideRect.x + margin;\n                    EditorGUI.DrawOverrideBackgroundApplicable(overrideRect);\n                    EditorGUIUtility.leftMarginCoord = prevMargin;\n                }\n            }\n        }\n\n        // GUILayout.Space doesn't expand to available width, so use GetRect instead\n        GUILayoutUtility.GetRect(10, EditorGUI.kTabButtonHeight);\n\n        GUI.enabled = tempEnabled;\n\n        // Important that we only actually set the selectedBuildTargetGroup if the user clicked the button.\n        // If the current selectedBuildTargetGroup is one that is not among the tabs (because the build target\n        // is not supported), then this should not be changed unless the user explicitly does so.\n        // Otherwise, if the build window is open at the same time, the unsupported build target groups will\n        // not be selectable in the build window.\n        if (EditorGUI.EndChangeCheck())\n        {\n            if (defaultTab == null)\n            {\n                platforms[selected].Select();\n            }\n            else\n            {\n                if (selected < 0)\n                {\n                    s_SelectedDefault.value = true;\n                }\n                else\n                {\n                    platforms[selected].Select();\n                    s_SelectedDefault.value = false;\n                }\n            }\n\n            // Repaint build window, if open.\n            Object[] buildWindows = Resources.FindObjectsOfTypeAll(typeof(BuildPlayerWindow));\n            foreach (Object t in buildWindows)\n            {\n                BuildPlayerWindow buildWindow = t as BuildPlayerWindow;\n                if (buildWindow != null)\n                    buildWindow.Repaint();\n            }\n        }\n\n        return selected;\n    }\n\n    internal static void EndPlatformGrouping()\n    {\n        EndVertical();\n    }\n\n    internal static void MultiSelectionObjectTitleBar(Object[] objects)\n    {\n        string text = objects[0].name + \" (\" + ObjectNames.NicifyVariableName(ObjectNames.GetTypeName(objects[0])) + \")\";\n        if (objects.Length > 1)\n        {\n            text += \" and \" + (objects.Length - 1) + \" other\" + (objects.Length > 2 ? \"s\" : \"\");\n        }\n        GUILayoutOption[] options = {  GUILayout.Height(16f) };\n        GUILayout.Label(EditorGUIUtility.TempContent(text, AssetPreview.GetMiniThumbnail(objects[0])), EditorStyles.boldLabel, options);\n    }\n\n    // Returns true if specified bit is true for all targets\n    internal static bool BitToggleField(string label, SerializedProperty bitFieldProperty, int flag)\n    {\n        bool toggle = (bitFieldProperty.intValue & flag) != 0;\n        bool different = (bitFieldProperty.hasMultipleDifferentValuesBitwise & flag) != 0;\n        EditorGUI.showMixedValue = different;\n        EditorGUI.BeginChangeCheck();\n        toggle = Toggle(label, toggle);\n        if (EditorGUI.EndChangeCheck())\n        {\n            // If toggle has mixed values, always set all to true when clicking it\n            if (different)\n            {\n                toggle = true;\n            }\n            different = false;\n            int bitIndex = -1;\n            for (int i = 0; i < 32; i++)\n            {\n                if (((1 << i) & flag) != 0)\n                {\n                    bitIndex = i;\n                    break;\n                }\n            }\n            bitFieldProperty.SetBitAtIndexForAllTargetsImmediate(bitIndex, toggle);\n        }\n        EditorGUI.showMixedValue = false;\n        return toggle && !different;\n    }\n\n    internal static void SortingLayerField(GUIContent label, SerializedProperty layerID, GUIStyle style)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style);\n        EditorGUI.SortingLayerField(r, label, layerID, style, EditorStyles.label);\n    }\n\n    internal static string TextFieldDropDown(string text, string[] dropDownElement)\n    {\n        return TextFieldDropDown(GUIContent.none, text, dropDownElement);\n    }\n\n    internal static string TextFieldDropDown(GUIContent label, string text, string[] dropDownElement)\n    {\n        Rect rect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.textField);\n        return EditorGUI.TextFieldDropDown(rect, label, text, dropDownElement);\n    }\n\n    internal static string DelayedTextFieldDropDown(string text, string[] dropDownElement)\n    {\n        return DelayedTextFieldDropDown(GUIContent.none, text, dropDownElement);\n    }\n\n    internal static string DelayedTextFieldDropDown(GUIContent label, string text, string[] dropDownElement)\n    {\n        Rect rect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.textFieldDropDownText);\n        return EditorGUI.DelayedTextFieldDropDown(rect, label, text, dropDownElement);\n    }\n\n    // A button that returns true on mouse down - like a popup button\n    public static bool DropdownButton(GUIContent content, FocusType focusType, params GUILayoutOption[] options)\n    {\n        return DropdownButton(content, focusType, \"MiniPullDown\", options);\n    }\n\n    // A button that returns true on mouse down - like a popup button\n    public static bool DropdownButton(GUIContent content, FocusType focusType, GUIStyle style, params GUILayoutOption[] options)\n    {\n        s_LastRect = GUILayoutUtility.GetRect(content, style, options);\n        return EditorGUI.DropdownButton(s_LastRect, content, focusType, style);\n    }\n\n    // A toggle that returns true on mouse down - like a popup button and returns true if checked\n    internal static bool DropDownToggle(ref bool toggled, GUIContent content, GUIStyle toggleStyle)\n    {\n        GUIStyle buttonStyle = GUIStyle.none;\n\n        // This is to be compatible with existing code\n        if (toggleStyle == EditorStyles.toolbarDropDownToggle || toggleStyle == EditorStyles.toolbarDropDownToggleRight)\n            buttonStyle = EditorStyles.toolbarDropDownToggleButton;\n\n        return DropDownToggle(ref toggled, content, toggleStyle, buttonStyle);\n    }\n\n    internal static bool DropDownToggle(ref bool toggled, GUIContent content, GUIStyle toggleStyle, GUIStyle toggleDropdownButtonStyle)\n    {\n        Rect toggleRect = GUILayoutUtility.GetRect(content, toggleStyle);\n        Rect arrowRightRect = Rect.zero;\n\n        if (toggleDropdownButtonStyle != null)\n        {\n            arrowRightRect = new Rect(toggleRect.xMax - toggleDropdownButtonStyle.fixedWidth - toggleDropdownButtonStyle.margin.right, toggleRect.y, toggleDropdownButtonStyle.fixedWidth, toggleRect.height);\n        }\n        else\n        {\n            arrowRightRect = new Rect(toggleRect.xMax - toggleStyle.padding.right, toggleRect.y, toggleStyle.padding.right, toggleRect.height);\n        }\n\n\n        int dropdownButtonId = GUIUtility.GetControlID(EditorGUI.s_DropdownButtonHash, FocusType.Passive, arrowRightRect);\n        bool clicked = EditorGUI.DropdownButton(dropdownButtonId, arrowRightRect, GUIContent.none, GUIStyle.none);\n\n        if (!clicked)\n        {\n            toggled = GUI.Toggle(toggleRect, toggled, content, toggleStyle);\n        }\n\n        // Ensure that the dropdown button is rendered on top of the toggle\n        if (Event.current.type == EventType.Repaint && toggleDropdownButtonStyle != null && toggleDropdownButtonStyle != GUIStyle.none)\n        {\n            EditorGUI.DropdownButton(dropdownButtonId, arrowRightRect, GUIContent.none, toggleDropdownButtonStyle);\n        }\n\n        return clicked;\n    }\n\n    internal static int AdvancedPopup(int selectedIndex, string[] displayedOptions, params GUILayoutOption[] options)\n    {\n        return AdvancedPopup(selectedIndex, displayedOptions, \"MiniPullDown\", options);\n    }\n\n    internal static int AdvancedPopup(int selectedIndex, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.AdvancedPopup(r, selectedIndex, displayedOptions, style);\n    }\n\n    internal static int AdvancedLazyPopup(string displayedOption, int selectedIndex, Func<Tuple<int, string[]>> displayedOptionsFunc, GUIStyle style, params GUILayoutOption[] options)\n    {\n        Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n        return EditorGUI.AdvancedLazyPopup(r, displayedOption, selectedIndex, displayedOptionsFunc, style);\n    }\n\n    [Obsolete(\"(UnityUpgradable) -> UnityEditor.HyperLinkClickedEventArgs\", true)]\n    internal class HyperLinkClickedEventArgs\n    {\n        [Obsolete(\"(UnityUpgradable) -> UnityEditor.HyperLinkClickedEventArgs.hyperLinkData\", true)]\n        public Dictionary<string, string> hyperlinkInfos { get; private set; }\n        internal HyperLinkClickedEventArgs(Dictionary<string, string> hyperLinkData) {}\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorGUIUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Internal;\nusing UnityEngine.Bindings;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    // Custom mouse cursor shapes used with EditorGUIUtility.AddCursorRect.\n    // Must Match EditorWindow::MouseCursor\n    public enum MouseCursor\n    {\n        // Normal pointer arrow\n        Arrow = 0,\n        // Text cursor\n        Text = 1,\n        // Vertical resize arrows\n        ResizeVertical = 2,\n        // Horizontal resize arrows\n        ResizeHorizontal = 3,\n        // Arrow with a Link badge (for assigning pointers)\n        Link = 4,\n        // Arrow with small arrows for indicating sliding at number fields\n        SlideArrow = 5,\n        // Resize up-right for window edges\n        ResizeUpRight = 6,\n        // Resize up-Left for window edges.\n        ResizeUpLeft = 7,\n        // Arrow with the move symbol next to it for the sceneview\n        MoveArrow = 8,\n        // Arrow with the rotate symbol next to it for the sceneview\n        RotateArrow = 9,\n        // Arrow with the scale symbol next to it for the sceneview\n        ScaleArrow = 10,\n        // Arrow with the plus symbol next to it\n        ArrowPlus = 11,\n        // Arrow with the minus symbol next to it\n        ArrowMinus = 12,\n        // Cursor with a dragging hand for pan\n        Pan = 13,\n        // Cursor with an eye for orbit\n        Orbit = 14,\n        // Cursor with a magnifying glass for zoom\n        Zoom = 15,\n        // Cursor with an eye and stylized arrow keys for FPS navigation\n        FPS = 16,\n        // The current user defined cursor\n        CustomCursor = 17,\n        // Split resize up down arrows\n        SplitResizeUpDown = 18,\n        // Split resize left right arrows\n        SplitResizeLeftRight = 19,\n        // The requested action will not be carried out\n        NotAllowed = 20,\n    }\n\n    // User message types.\n    public enum MessageType\n    {\n        // Neutral message\n        None = 0,\n        // Info message\n        Info = 1,\n        // Warning message\n        Warning = 2,\n        // Error message\n        Error = 3\n    }\n\n    // Enum that selects which skin to return from EditorGUIUtility.GetBuiltinSkin\n    public enum EditorSkin\n    {\n        // The skin used for game views.\n        Game = 0,\n        // The skin used for inspectors.\n        Inspector = 1,\n        // The skin used for scene views.\n        Scene = 2\n    }\n\n    [NativeHeader(\"Editor/Src/EditorResources.h\"),\n     NativeHeader(\"Runtime/Graphics/Texture2D.h\"),\n     NativeHeader(\"Runtime/Graphics/RenderTexture.h\"),\n     NativeHeader(\"Modules/TextRendering/Public/Font.h\"),\n     NativeHeader(\"Editor/Src/Utility/EditorGUIUtility.h\")]\n    public partial class EditorGUIUtility\n    {\n        public static extern string SerializeMainMenuToString();\n        public static extern void SetMenuLocalizationTestMode(bool onoff);\n\n        // Set icons rendered as part of [[GUIContent]] to be rendered at a specific size.\n        public static extern void SetIconSize(Vector2 size);\n\n        // Get a white texture.\n        public static extern Texture2D whiteTexture {[NativeMethod(\"GetWhiteTexture\")] get; }\n\n        // Exactly the same as GUIUtility.systemCopyBuffer, but for some reason done\n        // as a separate public API :(\n        public new static string systemCopyBuffer\n        {\n            get => GUIUtility.systemCopyBuffer;\n            set => GUIUtility.systemCopyBuffer = value;\n        }\n\n        internal static extern int skinIndex\n        {\n            [FreeFunction(\"GetEditorResources().GetSkinIdx\")] get;\n            [FreeFunction(\"GetEditorResources().SetSkinIdx\")] set;\n        }\n\n        public static extern void SetWantsMouseJumping(int wantz);\n\n        // Iterates over cameras and counts the ones that would render to a specified screen (doesn't involve culling)\n        public static extern bool IsDisplayReferencedByCameras(int displayIndex);\n\n        // Send an input event into the game.\n        public static extern void QueueGameViewInputEvent(Event evt);\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"RenderGameViewCameras is no longer supported.Consider rendering cameras manually.\", true)]\n        public static void RenderGameViewCameras(RenderTexture target, int targetDisplay, Rect screenRect, Vector2 mousePosition, bool gizmos) {}\n\n        internal static extern Object GetScript(string scriptClass);\n        public static extern void SetIconForObject([NotNull] Object obj, Texture2D icon);\n        [NativeThrows]\n        internal static extern Object GetBuiltinExtraResource(Type type, string path);\n        internal static extern BuiltinResource[] GetBuiltinResourceList(int classID);\n        internal static extern AssetBundle GetEditorAssetBundle();\n        internal static extern AssetBundle ReloadEditorAssetBundle();\n        internal static extern void SetRenderTextureNoViewport(RenderTexture rt);\n        internal static extern void SetVisibleLayers(int layers);\n        internal static extern void SetLockedLayers(int layers);\n        internal static extern bool IsGizmosAllowedForObject(Object obj);\n        internal static extern void SetCurrentViewCursor(Texture2D texture, Vector2 hotspot, MouseCursor type);\n        internal static extern void ClearCurrentViewCursor();\n        internal static extern void CleanCache(string text);\n        internal static extern void SetSearchIndexOfControlIDList(int index);\n        internal static extern int GetSearchIndexOfControlIDList();\n        internal static extern bool CanHaveKeyboardFocus(int id);\n\n        // Duplicate of SetDefaultFont in UnityEngine. We need to call it from editor code as well,\n        // while keeping both internal.\n        internal static extern void SetDefaultFont(Font font);\n\n        public static extern Texture2D GetIconForObject([NotNull] Object obj);\n\n        // Render all ingame cameras bound to a specific Display.\n        internal static extern void RenderPlayModeViewCamerasInternal(RenderTexture target, int targetDisplay, Vector2 mousePosition, bool gizmos, bool renderIMGUI);\n        internal static extern void SetupWindowSpaceAndVSyncInternal(Rect screenRect);\n\n        internal static extern void PerformTonemappingForGameView();\n        internal static extern void DrawTextureHdrSupport(Rect screenRect, Texture texture, Rect sourceRect, int leftBorder,\n            int rightBorder, int topBorder, int bottomBorder, Color color, Material mat, int pass, bool resetLinearToSrgbIfHdrActive);\n\n        private static extern Texture2D FindTextureByName(string name);\n        private static extern Texture2D FindTextureByType([NotNull] Type type);\n        internal static extern string GetObjectNameWithInfo(Object obj);\n        private static extern string GetTypeNameWithInfo(string typeName, int instanceID);\n        private static extern void Internal_SetupEventValues(object evt);\n        private static extern Vector2 Internal_GetIconSize();\n        private static extern bool Internal_GetKeyboardRect(int id, out Rect rect);\n        private static extern void Internal_MoveKeyboardFocus(bool forward);\n        private static extern int Internal_GetNextKeyboardControlID(bool forward);\n        private static extern void Internal_AddCursorRect(Rect r, MouseCursor m, int controlID);\n\n        // preview materials handling\n        internal enum PreviewType\n        {\n            Color,\n            ColorVT,\n            Alpha,\n            AlphaVT,\n            Transparent,\n            TransparentVT,\n            Normalmap,\n            NormalmapVT,\n            LightmapRGBM,\n            LightmapDoubleLDR,\n            LightmapFullHDR,\n            GUITextureClipVertically,\n        }\n        internal static extern Material GetPreviewMaterial(PreviewType type);\n    }\n\n    [NativeHeader(\"Editor/Src/InspectorExpandedState.h\"),\n     StaticAccessor(\"GetInspectorExpandedState().GetSessionState()\", StaticAccessorType.Dot)]\n    public class SessionState\n    {\n        [ExcludeFromDocs] public SessionState() {}\n\n        public static extern void SetBool(string key, bool value);\n        public static extern bool GetBool(string key, bool defaultValue);\n        public static extern void EraseBool(string key);\n        public static extern void SetFloat(string key, float value);\n        public static extern float GetFloat(string key, float defaultValue);\n        public static extern void EraseFloat(string key);\n        public static extern void SetInt(string key, int value);\n        public static extern int GetInt(string key, int defaultValue);\n        public static extern void EraseInt(string key);\n        public static extern void SetString(string key, string value);\n        public static extern string GetString(string key, string defaultValue);\n        public static extern void EraseString(string key);\n        public static extern void SetVector3(string key, Vector3 value);\n        public static extern Vector3 GetVector3(string key, Vector3 defaultValue);\n        public static extern void EraseVector3(string key);\n        public static extern void EraseIntArray(string key);\n        public static extern void SetIntArray(string key, int[] value);\n        [return:Unmarshalled]\n        public static extern int[] GetIntArray(string key, [Unmarshalled]int[] defaultValue);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorGUIUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Runtime.InteropServices;\nusing UnityEditorInternal;\nusing UnityEngine.Events;\nusing UnityEngine.Internal;\nusing UnityEngine.Scripting;\nusing UnityEngineInternal;\nusing UnityEditor.StyleSheets;\nusing UnityEditor.Experimental;\nusing UnityEditor.SceneManagement;\nusing UnityEngine.Bindings;\nusing UnityEngine.Pool;\nusing UnityEngine.UIElements;\nusing UnityObject = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    public sealed partial class EditorGUIUtility : GUIUtility\n    {\n        internal static void RegisterResourceForCleanupOnDomainReload(UnityObject obj)\n        {\n            AppDomain.CurrentDomain.DomainUnload += (object sender, EventArgs e) => { UnityObject.DestroyImmediate(obj); };\n        }\n\n        public class PropertyCallbackScope : IDisposable\n        {\n            Action<Rect, SerializedProperty> m_Callback;\n\n            public PropertyCallbackScope(Action<Rect, SerializedProperty> callback)\n            {\n                m_Callback = callback;\n\n                if (m_Callback != null)\n                    EditorGUIUtility.beginProperty += callback;\n            }\n\n            public void Dispose()\n            {\n                if (m_Callback != null)\n                    EditorGUIUtility.beginProperty -= m_Callback;\n            }\n        }\n\n        public class IconSizeScope : GUI.Scope\n        {\n            private readonly Vector2 m_OriginalIconSize;\n\n            public IconSizeScope(Vector2 iconSizeWithinScope)\n            {\n                m_OriginalIconSize = GetIconSize();\n                SetIconSize(iconSizeWithinScope);\n            }\n\n            protected override void CloseScope()\n            {\n                SetIconSize(m_OriginalIconSize);\n            }\n        }\n\n        internal static Material s_GUITextureBlit2SRGBMaterial;\n        internal static Material GUITextureBlit2SRGBMaterial\n        {\n            get\n            {\n                if (!s_GUITextureBlit2SRGBMaterial)\n                {\n                    Shader shader = LoadRequired(\"SceneView/GUITextureBlit2SRGB.shader\") as Shader;\n                    s_GUITextureBlit2SRGBMaterial = new Material(shader);\n                    s_GUITextureBlit2SRGBMaterial.hideFlags |= HideFlags.DontSaveInEditor;\n                    RegisterResourceForCleanupOnDomainReload(s_GUITextureBlit2SRGBMaterial);\n                }\n                s_GUITextureBlit2SRGBMaterial.SetFloat(\"_ManualTex2SRGB\", QualitySettings.activeColorSpace == ColorSpace.Linear ? 1.0f : 0.0f);\n                return s_GUITextureBlit2SRGBMaterial;\n            }\n        }\n\n        internal static Material s_GUITextureBlitSceneGUI;\n        internal static Material GUITextureBlitSceneGUIMaterial\n        {\n            get\n            {\n                if (!s_GUITextureBlitSceneGUI)\n                {\n                    Shader shader = LoadRequired(\"SceneView/GUITextureBlitSceneGUI.shader\") as Shader;\n                    s_GUITextureBlitSceneGUI = new Material(shader);\n                    s_GUITextureBlitSceneGUI.hideFlags |= HideFlags.DontSaveInEditor;\n                    RegisterResourceForCleanupOnDomainReload(s_GUITextureBlitSceneGUI);\n                }\n                return s_GUITextureBlitSceneGUI;\n            }\n        }\n\n        internal static int s_FontIsBold = -1;\n        internal static int s_LastControlID = 0;\n        private static float s_LabelWidth = 0f;\n\n        private static ScalableGUIContent s_InfoIcon;\n        private static ScalableGUIContent s_WarningIcon;\n        private static ScalableGUIContent s_ErrorIcon;\n\n        private static GUIStyle s_WhiteTextureStyle;\n        private static GUIStyle s_BasicTextureStyle;\n\n        static Hashtable s_TextGUIContents = new Hashtable();\n        static Hashtable s_GUIContents = new Hashtable();\n        static Hashtable s_IconGUIContents = new Hashtable();\n        static Hashtable s_SkinnedIcons = new Hashtable();\n\n        private static readonly GUIContent s_ObjectContent = new GUIContent();\n        private static readonly GUIContent s_Text = new GUIContent();\n        private static readonly GUIContent s_Image = new GUIContent();\n        private static readonly GUIContent s_TextImage = new GUIContent();\n\n        private static GUIContent s_SceneMismatch = TrTextContent(\"Scene mismatch (cross scene references not supported)\");\n        private static GUIContent s_TypeMismatch = TrTextContent(\"Type mismatch\");\n\n        internal static readonly SVC<Color> kViewBackgroundColor = new SVC<Color>(\"view\", StyleCatalogKeyword.backgroundColor, GetDefaultBackgroundColor);\n\n        /// The current UI scaling factor for high-DPI displays. For instance, 2.0 on a retina display\n\n        public new static float pixelsPerPoint => GUIUtility.pixelsPerPoint;\n\n        static EditorGUIUtility()\n        {\n            GUISkin.m_SkinChanged += SkinChanged;\n            s_HasCurrentWindowKeyFocusFunc = HasCurrentWindowKeyFocus;\n        }\n\n        // this method gets called on right clicking a property regardless of GUI.enable value.\n        internal static event Action<GenericMenu, SerializedProperty> contextualPropertyMenu;\n        internal static event Action<Rect, SerializedProperty> beginProperty;\n\n        internal static void BeginPropertyCallback(Rect totalRect, SerializedProperty property)\n        {\n            beginProperty?.Invoke(totalRect, property);\n        }\n\n        internal static void ContextualPropertyMenuCallback(GenericMenu gm, SerializedProperty prop)\n        {\n            if (contextualPropertyMenu != null)\n            {\n                if (gm.GetItemCount() > 0)\n                    gm.AddSeparator(\"\");\n                contextualPropertyMenu(gm, prop);\n            }\n        }\n\n        // returns position and size of the main Unity Editor window\n        public static Rect GetMainWindowPosition()\n        {\n            foreach (var win in ContainerWindow.windows)\n            {\n                if (win.IsMainWindow())\n                    return win.position;\n            }\n            return new Rect(0, 0, 1000, 600);\n        }\n\n        // sets position and size of the main Unity Editor window\n        public static void SetMainWindowPosition(Rect position)\n        {\n            foreach (var win in ContainerWindow.windows)\n            {\n                if (win.IsMainWindow())\n                {\n                    win.position = position;\n                    break;\n                }\n            }\n        }\n\n        internal static Rect GetCenteredWindowPosition(Rect parentWindowPosition, Vector2 size)\n        {\n            var pos = new Rect\n            {\n                x = 0,\n                y = 0,\n                width = Mathf.Min(size.x, parentWindowPosition.width * 0.90f),\n                height = Mathf.Min(size.y, parentWindowPosition.height * 0.90f)\n            };\n            var w = (parentWindowPosition.width - pos.width) * 0.5f;\n            var h = (parentWindowPosition.height - pos.height) * 0.5f;\n            pos.x = parentWindowPosition.x + w;\n            pos.y = parentWindowPosition.y + h;\n            return pos;\n        }\n\n        internal static void RepaintCurrentWindow()\n        {\n            CheckOnGUI();\n            GUIView.current.Repaint();\n        }\n\n        internal static bool HasCurrentWindowKeyFocus()\n        {\n            CheckOnGUI();\n            return GUIView.current != null && GUIView.current.hasFocus;\n        }\n\n        public static Rect PointsToPixels(Rect rect)\n        {\n            GUIUtility.WarnOnGUI();\n            var cachedPixelsPerPoint = pixelsPerPoint;\n            rect.x *= cachedPixelsPerPoint;\n            rect.y *= cachedPixelsPerPoint;\n            rect.width *= cachedPixelsPerPoint;\n            rect.height *= cachedPixelsPerPoint;\n            return rect;\n        }\n\n        public static Rect PixelsToPoints(Rect rect)\n        {\n            var cachedInvPixelsPerPoint = 1f / pixelsPerPoint;\n            rect.x *= cachedInvPixelsPerPoint;\n            rect.y *= cachedInvPixelsPerPoint;\n            rect.width *= cachedInvPixelsPerPoint;\n            rect.height *= cachedInvPixelsPerPoint;\n            return rect;\n        }\n\n        public static Vector2 PointsToPixels(Vector2 position)\n        {\n            GUIUtility.WarnOnGUI();\n            var cachedPixelsPerPoint = pixelsPerPoint;\n            position.x *= cachedPixelsPerPoint;\n            position.y *= cachedPixelsPerPoint;\n            return position;\n        }\n\n        public static Vector2 PixelsToPoints(Vector2 position)\n        {\n            var cachedInvPixelsPerPoint = 1f / pixelsPerPoint;\n            position.x *= cachedInvPixelsPerPoint;\n            position.y *= cachedInvPixelsPerPoint;\n            return position;\n        }\n\n        // Given a rectangle, GUI style and a list of items, lay them out sequentially;\n        // left to right, top to bottom.\n        public static List<Rect> GetFlowLayoutedRects(Rect rect, GUIStyle style, float horizontalSpacing, float verticalSpacing, List<string> items)\n        {\n            var result = new List<Rect>(items.Count);\n            var curPos = rect.position;\n            foreach (string item in items)\n            {\n                var gc = TempContent(item);\n                var itemSize = style.CalcSize(gc);\n                var itemRect = new Rect(curPos, itemSize);\n\n                // Reached right side, go to next row\n                if (curPos.x + itemSize.x + horizontalSpacing >= rect.xMax)\n                {\n                    curPos.x = rect.x;\n                    curPos.y += itemSize.y + verticalSpacing;\n                    itemRect.position = curPos;\n                }\n                result.Add(itemRect);\n\n                // Move next item to the left\n                curPos.x += itemSize.x + horizontalSpacing;\n            }\n\n            return result;\n        }\n\n        internal class SkinnedColor\n        {\n            Color normalColor;\n            Color proColor;\n\n            public SkinnedColor(Color color, Color proColor)\n            {\n                normalColor = color;\n                this.proColor = proColor;\n            }\n\n            public SkinnedColor(Color color)\n            {\n                normalColor = color;\n                proColor = color;\n            }\n\n            public Color color\n            {\n                get { return isProSkin ? proColor : normalColor; }\n\n                set\n                {\n                    if (isProSkin)\n                        proColor = value;\n                    else\n                        normalColor = value;\n                }\n            }\n\n            public static implicit operator Color(SkinnedColor colorSkin)\n            {\n                return colorSkin.color;\n            }\n        }\n\n        private delegate bool HeaderItemDelegate(Rect rectangle, UnityObject[] targets);\n        private static List<HeaderItemDelegate> s_EditorHeaderItemsMethods = null;\n        internal static Rect DrawEditorHeaderItems(Rect rectangle, UnityObject[] targetObjs, float spacing = 0)\n        {\n            if (targetObjs.Length == 0 || (targetObjs.Length == 1 && targetObjs[0].GetType() == typeof(System.Object)))\n                return rectangle;\n\n            if (comparisonViewMode != ComparisonViewMode.None)\n                return rectangle;\n\n            if (s_EditorHeaderItemsMethods == null)\n            {\n                List<Type> targetObjTypes = new List<Type>();\n                var type = targetObjs[0].GetType();\n                while (type.BaseType != null)\n                {\n                    targetObjTypes.Add(type);\n                    type = type.BaseType;\n                }\n\n                AttributeHelper.MethodInfoSorter methods = AttributeHelper.GetMethodsWithAttribute<EditorHeaderItemAttribute>(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);\n                Func<EditorHeaderItemAttribute, bool> filter = (a) => targetObjTypes.Any(c => a.TargetType == c);\n                var methodInfos = methods.FilterAndSortOnAttribute(filter, (a) => a.callbackOrder);\n                s_EditorHeaderItemsMethods = new List<HeaderItemDelegate>();\n                foreach (MethodInfo methodInfo in methodInfos)\n                {\n                    s_EditorHeaderItemsMethods.Add((HeaderItemDelegate)Delegate.CreateDelegate(typeof(HeaderItemDelegate), methodInfo));\n                }\n            }\n\n            float spacingToRemove = 0;\n            foreach (HeaderItemDelegate @delegate in s_EditorHeaderItemsMethods)\n            {\n                if (@delegate(rectangle, targetObjs))\n                {\n                    rectangle.x -= rectangle.width + spacing;\n                    spacingToRemove = rectangle.width + spacing;\n                }\n            }\n            rectangle.x += spacingToRemove; // the spacing after a delegate is used to position the next element to draw but the last one is not used so we must remove it before exiting the method\n\n            return rectangle;\n        }\n\n        /// <summary>\n        /// Use this container and helper class when implementing lock behaviour on a window when also using an <see cref=\"ActiveEditorTracker\"/>.\n        /// </summary>\n        [Serializable]\n        internal class EditorLockTrackerWithActiveEditorTracker : EditorLockTracker\n        {\n            internal override bool isLocked\n            {\n                get\n                {\n                    if (m_Tracker != null)\n                    {\n                        base.isLocked = m_Tracker.isLocked;\n                        return m_Tracker.isLocked;\n                    }\n                    return base.isLocked;\n                }\n                set\n                {\n                    if (m_Tracker != null)\n                    {\n                        m_Tracker.isLocked = value;\n                    }\n                    base.isLocked = value;\n                }\n            }\n\n            [SerializeField, HideInInspector]\n            ActiveEditorTracker m_Tracker;\n\n            internal ActiveEditorTracker tracker\n            {\n                get { return m_Tracker; }\n                set\n                {\n                    m_Tracker = value;\n                    if (m_Tracker != null)\n                    {\n                        isLocked = m_Tracker.isLocked;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Use this container and helper class when implementing lock behaviour on a window.\n        /// </summary>\n        [Serializable]\n        internal class EditorLockTracker\n        {\n            [Serializable] public class LockStateEvent : UnityEvent<bool> {}\n            [HideInInspector]\n            internal LockStateEvent lockStateChanged = new LockStateEvent();\n\n            const string k_LockMenuText = \"Lock\";\n            static readonly GUIContent k_LockMenuGUIContent =  TextContent(k_LockMenuText);\n\n            /// <summary>\n            /// don't set or get this directly unless from within the <see cref=\"isLocked\"/> property,\n            /// as that property also keeps track of the potentially existing tracker in <see cref=\"EditorLockTrackerWithActiveEditorTracker\"/>\n            /// </summary>\n            [SerializeField, HideInInspector]\n            bool m_IsLocked;\n            PingData m_Ping = new PingData();\n\n            internal virtual bool isLocked\n            {\n                get\n                {\n                    return m_IsLocked;\n                }\n                set\n                {\n                    bool wasLocked = m_IsLocked;\n                    m_IsLocked = value;\n\n                    if (wasLocked != m_IsLocked)\n                    {\n                        lockStateChanged.Invoke(m_IsLocked);\n                    }\n                }\n            }\n\n            internal virtual void AddItemsToMenu(GenericMenu menu, bool disabled = false)\n            {\n                if (disabled)\n                {\n                    menu.AddDisabledItem(k_LockMenuGUIContent);\n                }\n                else\n                {\n                    menu.AddItem(k_LockMenuGUIContent, isLocked, FlipLocked);\n                }\n            }\n\n            internal virtual void PingIcon()\n            {\n                m_Ping.isPinging = true;\n\n                if (m_Ping.m_PingStyle == null)\n                {\n                    m_Ping.m_PingStyle = new GUIStyle(\"TV Ping\");\n\n                    // The default padding is too high for such a small icon and causes the animation to become offset to the left.\n                    m_Ping.m_PingStyle.padding = new RectOffset(8, 0, 0, 0);\n                }\n            }\n\n            internal virtual void StopPingIcon()\n            {\n                m_Ping.isPinging = false;\n            }\n\n            internal bool ShowButton(Rect position, GUIStyle lockButtonStyle, bool disabled = false)\n            {\n                using (new EditorGUI.DisabledScope(disabled))\n                {\n                    EditorGUI.BeginChangeCheck();\n                    bool newLock = GUI.Toggle(position, isLocked, GUIContent.none, lockButtonStyle);\n\n                    if (m_Ping.isPinging && Event.current.type == EventType.Layout)\n                    {\n                        m_Ping.m_ContentRect = position;\n                        m_Ping.m_ContentRect.width *= 2f;\n                        m_Ping.m_AvailableWidth = GUIView.current.position.width;\n\n                        m_Ping.m_ContentDraw = r =>\n                        {\n                            GUI.Toggle(r, newLock, GUIContent.none, lockButtonStyle);\n                        };\n                    }\n\n                    m_Ping.HandlePing();\n\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        if (newLock != isLocked)\n                        {\n                            FlipLocked();\n                            m_Ping.isPinging = false;\n                        }\n                    }\n                }\n                return m_Ping.isPinging;\n            }\n\n            void FlipLocked()\n            {\n                isLocked = !isLocked;\n            }\n        }\n\n        // Get a texture from its source filename\n        public static Texture2D FindTexture(string name)\n        {\n            return FindTextureByName(name);\n        }\n\n        // Get texture from managed type\n        internal static Texture2D FindTexture(Type type)\n        {\n            return FindTextureByType(type);\n        }\n\n        public static GUIContent TrTextContent(string key, string text, string tooltip, Texture icon)\n        {\n            GUIContent gc = (GUIContent)s_GUIContents[key];\n            if (gc == null)\n            {\n                gc = new GUIContent(L10n.Tr(text));\n                if (tooltip != null)\n                {\n                    gc.tooltip = L10n.Tr(tooltip);\n                }\n                if (icon != null)\n                {\n                    gc.image = icon;\n                }\n                s_GUIContents[key] = gc;\n            }\n            return gc;\n        }\n\n        public static GUIContent TrTextContent(string text, string tooltip = null, Texture icon = null)\n        {\n            string key = string.Format(\"{0}|{1}\", text ?? \"\", tooltip ?? \"\");\n            return TrTextContent(key, text, tooltip, icon);\n        }\n\n        public static GUIContent TrTextContent(string text, string tooltip, string iconName)\n        {\n            string key = iconName == null ? string.Format(\"{0}|{1}\", text ?? \"\", tooltip ?? \"\") :\n                string.Format(\"{0}|{1}|{2}|{3}\", text ?? \"\", tooltip ?? \"\", iconName, pixelsPerPoint);\n            return TrTextContent(key, text, tooltip, LoadIconRequired(iconName));\n        }\n\n        public static GUIContent TrTextContent(string text, Texture icon)\n        {\n            return TrTextContent(text, null, icon);\n        }\n\n        public static GUIContent TrTextContentWithIcon(string text, Texture icon)\n        {\n            return TrTextContent(text, null, icon);\n        }\n\n        public static GUIContent TrTextContentWithIcon(string text, string iconName)\n        {\n            return TrTextContent(text, null, iconName);\n        }\n\n        public static GUIContent TrTextContentWithIcon(string text, string tooltip, string iconName)\n        {\n            return TrTextContent(text, tooltip, iconName);\n        }\n\n        public static GUIContent TrTextContentWithIcon(string text, string tooltip, Texture icon)\n        {\n            return TrTextContent(text, tooltip, icon);\n        }\n\n        public static GUIContent TrTextContentWithIcon(string text, string tooltip, MessageType messageType)\n        {\n            return TrTextContent(text, tooltip, GetHelpIcon(messageType));\n        }\n\n        public static GUIContent TrTextContentWithIcon(string text, MessageType messageType)\n        {\n            return TrTextContentWithIcon(text, null, messageType);\n        }\n\n        internal static Texture2D LightenTexture(Texture2D texture)\n        {\n            if (!texture)\n                return texture;\n            Texture2D outTexture = new Texture2D(texture.width, texture.height);\n            var outColorArray = outTexture.GetPixels();\n\n            var colorArray = texture.GetPixels();\n            for (var i = 0; i < colorArray.Length; ++i)\n                outColorArray[i] = LightenColor(colorArray[i]);\n\n            outTexture.hideFlags = HideFlags.HideAndDontSave;\n            outTexture.SetPixels(outColorArray);\n            outTexture.Apply();\n\n            return outTexture;\n        }\n\n        internal static Color LightenColor(Color color)\n        {\n            Color.RGBToHSV(color, out var h, out _, out _);\n            var outColor = Color.HSVToRGB((h + 0.5f) % 1, 0f, 0.8f);\n            outColor.a = color.a;\n            return outColor;\n        }\n\n        public static GUIContent TrIconContent(string iconName, string tooltip = null)\n        {\n            return TrIconContent(iconName, tooltip, false);\n        }\n\n        internal static GUIContent TrIconContent(string iconName, string tooltip, bool lightenTexture)\n        {\n            string key = tooltip == null ? string.Format(\"{0}|{1}\", iconName, pixelsPerPoint) :\n                string.Format(\"{0}|{1}|{2}\", iconName, tooltip, pixelsPerPoint);\n            GUIContent gc = (GUIContent)s_IconGUIContents[key];\n            if (gc != null)\n            {\n                return gc;\n            }\n            gc = new GUIContent();\n\n            if (tooltip != null)\n            {\n                gc.tooltip = L10n.Tr(tooltip);\n            }\n            gc.image = LoadIconRequired(iconName);\n            if (lightenTexture && gc.image is Texture2D tex2D)\n                gc.image = LightenTexture(tex2D);\n            s_IconGUIContents[key] = gc;\n            return gc;\n        }\n\n        public static GUIContent TrIconContent(Texture icon, string tooltip = null)\n        {\n            GUIContent gc = (tooltip != null) ? (GUIContent)s_IconGUIContents[tooltip] : null;\n            if (gc != null)\n            {\n                return gc;\n            }\n            gc = new GUIContent { image = icon };\n            if (tooltip != null)\n            {\n                gc.tooltip = L10n.Tr(tooltip);\n                s_IconGUIContents[tooltip] = gc;\n            }\n\n            return gc;\n        }\n\n        [ExcludeFromDocs]\n        public static GUIContent TrTempContent(string t)\n        {\n            return TempContent(L10n.Tr(t));\n        }\n\n        [ExcludeFromDocs]\n        public static GUIContent[] TrTempContent(string[] texts)\n        {\n            GUIContent[] retval = new GUIContent[texts.Length];\n            for (int i = 0; i < texts.Length; i++)\n                retval[i] = new GUIContent(L10n.Tr(texts[i]));\n            return retval;\n        }\n\n        [ExcludeFromDocs]\n        public static GUIContent[] TrTempContent(string[] texts, string[] tooltips)\n        {\n            GUIContent[] retval = new GUIContent[texts.Length];\n            for (int i = 0; i < texts.Length; i++)\n                retval[i] = new GUIContent(L10n.Tr(texts[i]), L10n.Tr(tooltips[i]));\n            return retval;\n        }\n\n        internal static GUIContent TrIconContent<T>(string tooltip = null) where T : UnityObject\n        {\n            return TrIconContent(FindTexture(typeof(T)), tooltip);\n        }\n\n        public static float singleLineHeight => EditorGUI.kSingleLineHeight;\n        public static float standardVerticalSpacing => EditorGUI.kControlVerticalSpacing;\n\n        internal static SliderLabels sliderLabels = new SliderLabels();\n\n        internal static GUIContent TextContent(string textAndTooltip)\n        {\n            if (textAndTooltip == null)\n                textAndTooltip = \"\";\n\n            string key = textAndTooltip;\n\n            GUIContent gc = (GUIContent)s_TextGUIContents[key];\n            if (gc == null)\n            {\n                string[] strings = GetNameAndTooltipString(textAndTooltip);\n                gc = new GUIContent(strings[1]);\n\n                if (strings[2] != null)\n                {\n                    gc.tooltip = strings[2];\n                }\n                s_TextGUIContents[key] = gc;\n            }\n            return gc;\n        }\n\n        internal static GUIContent TextContentWithIcon(string textAndTooltip, string icon)\n        {\n            if (textAndTooltip == null)\n                textAndTooltip = \"\";\n\n            if (icon == null)\n                icon = \"\";\n\n            string key = string.Format(\"{0}|{1}|{2}\", textAndTooltip, icon, pixelsPerPoint);\n\n            GUIContent gc = (GUIContent)s_TextGUIContents[key];\n            if (gc == null)\n            {\n                string[] strings = GetNameAndTooltipString(textAndTooltip);\n                gc = new GUIContent(strings[1]) { image = LoadIconRequired(icon) };\n\n                // We want to catch missing icons so we can fix them (therefore using LoadIconRequired)\n\n                if (strings[2] != null)\n                {\n                    gc.tooltip = strings[2];\n                }\n                s_TextGUIContents[key] = gc;\n            }\n            return gc;\n        }\n\n        private static Color GetDefaultBackgroundColor()\n        {\n            float kViewBackgroundIntensity = isProSkin ? 0.22f : 0.76f;\n            return new Color(kViewBackgroundIntensity, kViewBackgroundIntensity, kViewBackgroundIntensity, 1f);\n        }\n\n        // [0] original name, [1] localized name, [2] localized tooltip\n        internal static string[] GetNameAndTooltipString(string nameAndTooltip)\n        {\n            string[] retval = new string[3];\n\n            string[] s1 = nameAndTooltip.Split('|');\n\n            switch (s1.Length)\n            {\n                case 0:\n                    retval[0] = \"\";\n                    retval[1] = \"\";\n                    break;\n                case 1:\n                    retval[0] = s1[0].Trim();\n                    retval[1] = retval[0];\n                    break;\n                case 2:\n                    retval[0] = s1[0].Trim();\n                    retval[1] = retval[0];\n                    retval[2] = s1[1].Trim();\n                    break;\n                default:\n                    Debug.LogError(\"Error in Tooltips: Too many strings in line beginning with '\" + s1[0] + \"'\");\n                    break;\n            }\n            return retval;\n        }\n\n        internal static Texture2D LoadIconRequired(string name)\n        {\n            Texture2D tex = LoadIcon(name);\n\n            if (!tex)\n                Debug.LogErrorFormat(\"Unable to load the icon: '{0}'.\\nNote that either full project path should be used (with extension) \" +\n                    \"or just the icon name if the icon is located in the following location: '{1}' (without extension, since png is assumed)\",\n                    name, EditorResources.editorDefaultResourcesPath + EditorResources.iconsPath);\n\n            return tex;\n        }\n\n        // Automatically loads version of icon that matches current skin.\n        // Equivalent to Texture2DNamed in ObjectImages.cpp\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal static Texture2D LoadIcon(string name)\n        {\n            return LoadIconForSkin(name, skinIndex);\n        }\n\n        static readonly List<string> k_UserSideSupportedImageExtensions = new List<string> {\".png\"};\n\n        // Attempts to load a higher resolution icon if needed\n        internal static Texture2D LoadGeneratedIconOrNormalIcon(string name)\n        {\n            Texture2D icon = null;\n            if (GUIUtility.pixelsPerPoint > 1.0f)\n            {\n                var imageExtension = Path.GetExtension(name);\n                if (k_UserSideSupportedImageExtensions.Contains(imageExtension))\n                {\n                    var newName = $\"{Path.GetFileNameWithoutExtension(name)}@2x{imageExtension}\";\n                    var dirName = Path.GetDirectoryName(name);\n                    if (!string.IsNullOrEmpty(dirName))\n                        newName = $\"{dirName}/{newName}\";\n\n                    icon = InnerLoadGeneratedIconOrNormalIcon(newName);\n                }\n                else\n                {\n                    icon = InnerLoadGeneratedIconOrNormalIcon(name + \"@2x\");\n                }\n\n                if (icon != null)\n                    icon.pixelsPerPoint = 2.0f;\n            }\n\n            if (icon == null)\n            {\n                icon = InnerLoadGeneratedIconOrNormalIcon(name);\n            }\n\n            if (icon != null &&\n                !Mathf.Approximately(icon.pixelsPerPoint, GUIUtility.pixelsPerPoint) && //scaling are different\n                !Mathf.Approximately(GUIUtility.pixelsPerPoint % 1, 0)) //screen scaling is non-integer\n            {\n                icon.filterMode = FilterMode.Bilinear;\n            }\n\n            return icon;\n        }\n\n        // Takes a name that already includes d_ if dark skin version is desired.\n        // Equivalent to Texture2DSkinNamed in ObjectImages.cpp\n        static Texture2D InnerLoadGeneratedIconOrNormalIcon(string name)\n        {\n            Texture2D tex = Load(EditorResources.generatedIconsPath + name + \".asset\") as Texture2D;\n\n            if (!tex)\n            {\n                tex = Load(EditorResources.iconsPath + name + \".png\") as Texture2D;\n            }\n            if (!tex)\n            {\n                tex = Load(name) as Texture2D; // Allow users to specify their own project path to an icon (e.g see EditorWindowTitleAttribute)\n            }\n\n            return tex;\n        }\n\n        internal static Texture2D LoadIconForSkin(string name, int in_SkinIndex)\n        {\n            if (String.IsNullOrEmpty(name))\n                return null;\n\n            if (in_SkinIndex == 0)\n                return LoadGeneratedIconOrNormalIcon(name);\n\n            //Remap file name for dark skin\n            var newName = \"d_\" + Path.GetFileName(name);\n            var dirName = Path.GetDirectoryName(name);\n            if (!string.IsNullOrEmpty(dirName))\n                newName = $\"{dirName}/{newName}\";\n\n            Texture2D tex = LoadGeneratedIconOrNormalIcon(newName);\n            if (!tex)\n                tex = LoadGeneratedIconOrNormalIcon(name);\n            return tex;\n        }\n\n        [UsedByNativeCode]\n        internal static string GetIconPathFromAttribute(Type type)\n        {\n            if (Attribute.IsDefined(type, typeof(IconAttribute)))\n            {\n                var attributes = type.GetCustomAttributes(typeof(IconAttribute), true);\n                for (int i = 0, c = attributes.Length; i < c; i++)\n                    if (attributes[i] is IconAttribute)\n                        return ((IconAttribute)attributes[i]).path;\n            }\n            return null;\n        }\n\n        internal static GUIContent IconContent<T>(string text = null) where T : UnityObject\n        {\n            return IconContent(FindTexture(typeof(T)), text);\n        }\n\n        [ExcludeFromDocs]\n        public static GUIContent IconContent(string name)\n        {\n            return IconContent(name, null, true);\n        }\n\n        internal static GUIContent IconContent(string name, bool logError)\n        {\n            return IconContent(name, null, logError);\n        }\n\n        public static GUIContent IconContent(string name, [DefaultValue(\"null\")] string text)\n        {\n            return IconContent(name, text, true);\n        }\n\n        internal static GUIContent IconContent(string name, [DefaultValue(\"null\")] string text, bool logError)\n        {\n            GUIContent gc = (GUIContent)s_IconGUIContents[name];\n            if (gc != null)\n            {\n                return gc;\n            }\n\n            gc = new GUIContent();\n\n            if (text != null)\n            {\n                string[] strings = GetNameAndTooltipString(text);\n                if (strings[2] != null)\n                {\n                    gc.tooltip = strings[2];\n                }\n            }\n            gc.image = logError ? LoadIconRequired(name) : LoadIcon(name);\n\n            s_IconGUIContents[name] = gc;\n            return gc;\n        }\n\n        static GUIContent IconContent(Texture icon, string text)\n        {\n            GUIContent gc = text != null ? (GUIContent)s_IconGUIContents[text] : null;\n            if (gc != null)\n            {\n                return gc;\n            }\n            gc = new GUIContent { image = icon };\n\n            if (text != null)\n            {\n                string[] strings = GetNameAndTooltipString(text);\n                if (strings[2] != null)\n                {\n                    gc.tooltip = strings[2];\n                }\n                s_IconGUIContents[text] = gc;\n            }\n            return gc;\n        }\n\n        // Is the user currently using the pro skin? (RO)\n        public static bool isProSkin => skinIndex == 1;\n\n        internal static void Internal_SwitchSkin()\n        {\n            skinIndex = 1 - skinIndex;\n        }\n\n        // Return a GUIContent object with the name and icon of an Object.\n        public static GUIContent ObjectContent(UnityObject obj, Type type)\n        {\n            return ObjectContent(obj, type, ReferenceEquals(obj, null) ? 0 : obj.GetInstanceID());\n        }\n\n        internal static GUIContent ObjectContent(UnityObject obj, Type type, bool showNullIcon)\n        {\n            return ObjectContent(obj, type, ReferenceEquals(obj, null) ? 0 : obj.GetInstanceID(), showNullIcon);\n        }\n\n        internal static GUIContent ObjectContent(UnityObject obj, Type type, int instanceID, bool showNullIcon = true)\n        {\n            if (obj)\n            {\n                s_ObjectContent.text = GetObjectNameWithInfo(obj);\n                s_ObjectContent.image = AssetPreview.GetMiniThumbnail(obj);\n            }\n            else if (type != null)\n            {\n                s_ObjectContent.text = GetTypeNameWithInfo(type.Name, instanceID);\n                s_ObjectContent.image = showNullIcon ? AssetPreview.GetMiniTypeThumbnail(type) : null;\n            }\n            else\n            {\n                s_ObjectContent.text = \"<no type>\";\n                s_ObjectContent.image = null;\n            }\n            return s_ObjectContent;\n        }\n\n        internal static GUIContent ObjectContent(UnityObject obj, Type type, SerializedProperty property, EditorGUI.ObjectFieldValidator validator = null)\n        {\n            if (validator == null)\n                validator = EditorGUI.ValidateObjectFieldAssignment;\n\n            GUIContent temp;\n\n            // If obj or objType are both null, we have to rely on\n            // property.objectReferenceStringValue to display None/Missing and the\n            // correct type. But if not, EditorGUIUtility.ObjectContent is more reliable.\n            // It can take a more specific object type specified as argument into account,\n            // and it gets the icon at the same time.\n            if (obj == null && type == null && property != null && property.isValid)\n            {\n                temp = TempContent(property.objectReferenceStringValue);\n            }\n            else\n            {\n                // In order for ObjectContext to be able to distinguish between None/Missing,\n                // we need to supply an instanceID. For some reason, getting the instanceID\n                // from property.objectReferenceValue is not reliable, so we have to\n                // explicitly check property.objectReferenceInstanceIDValue if a property exists.\n                if (property != null && property.isValid)\n                    temp = ObjectContent(obj, type, property.objectReferenceInstanceIDValue, false);\n                else\n                    temp = ObjectContent(obj, type, false);\n            }\n\n            if (property != null && property.isValid)\n            {\n                if (obj != null)\n                {\n                    UnityObject[] references = { obj };\n                    if (EditorSceneManager.preventCrossSceneReferences && EditorGUI.CheckForCrossSceneReferencing(obj, property.serializedObject.targetObject))\n                    {\n                        if (!EditorApplication.isPlaying)\n                            temp = s_SceneMismatch;\n                        else\n                            temp.text = temp.text + string.Format(\" ({0})\", EditorGUI.GetGameObjectFromObject(obj).scene.name);\n                    }\n                    else if (validator(references, type, property, EditorGUI.ObjectFieldValidatorOptions.ExactObjectTypeValidation) == null)\n                        temp = s_TypeMismatch;\n                }\n            }\n\n            return temp;\n        }\n\n        internal static GUIContent TempContent(string t)\n        {\n            s_Text.image = null;\n            s_Text.text = t;\n            s_Text.tooltip = null;\n            return s_Text;\n        }\n\n        internal static GUIContent TempContent(string text, string tip)\n        {\n            s_Text.image = null;\n            s_Text.text = text;\n            s_Text.tooltip = tip;\n            return s_Text;\n        }\n\n        internal static GUIContent TempContent(Texture i)\n        {\n            s_Image.image = i;\n            s_Image.text = null;\n            s_Image.tooltip = null;\n            return s_Image;\n        }\n\n        internal static GUIContent TempContent(string t, Texture i)\n        {\n            s_TextImage.image = i;\n            s_TextImage.text = t;\n            s_TextImage.tooltip = null;\n            return s_TextImage;\n        }\n\n        internal static GUIContent[] TempContent(string[] texts)\n        {\n            GUIContent[] retval = new GUIContent[texts.Length];\n            for (int i = 0; i < texts.Length; i++)\n                retval[i] = new GUIContent(texts[i]);\n            return retval;\n        }\n\n        internal static GUIContent[] TempContent(string[] texts, string[] tooltips)\n        {\n            GUIContent[] retval = new GUIContent[texts.Length];\n            for (int i = 0; i < texts.Length; i++)\n                retval[i] = new GUIContent(texts[i], tooltips[i]);\n            return retval;\n        }\n\n        internal static bool HasHolddownKeyModifiers(Event evt)\n        {\n            return evt.shift | evt.control | evt.alt | evt.command;\n        }\n\n        // Does a given class have per-object thumbnails?\n        public static bool HasObjectThumbnail(Type objType)\n        {\n            return objType != null && (objType.IsSubclassOf(typeof(Texture)) || objType == typeof(Texture) || objType == typeof(Sprite));\n        }\n\n        // Get the size that has been set using ::ref::SetIconSize.\n        public static Vector2 GetIconSize()\n        {\n            //FIXME: this is how it really should be, but right now it seems to fail badly (unrelated null ref exceptions and then crash)\n            return Internal_GetIconSize();\n        }\n\n        internal static Texture2D infoIcon\n        {\n            get\n            {\n                if (s_InfoIcon == null)\n                    s_InfoIcon = new ScalableGUIContent(\"console.infoicon\");\n                return s_InfoIcon.image as Texture2D;\n            }\n        }\n        internal static Texture2D warningIcon\n        {\n            get\n            {\n                if (s_WarningIcon == null)\n                    s_WarningIcon = new ScalableGUIContent(\"console.warnicon\");\n                return s_WarningIcon.image as Texture2D;\n            }\n        }\n\n        internal static Texture2D errorIcon\n        {\n            get\n            {\n                if (s_ErrorIcon == null)\n                    s_ErrorIcon = new ScalableGUIContent(\"console.erroricon\");\n                return s_ErrorIcon.image as Texture2D;\n            }\n        }\n\n        internal static Texture2D GetHelpIcon(MessageType type)\n        {\n            switch (type)\n            {\n                case MessageType.Info:\n                    return infoIcon;\n                case MessageType.Warning:\n                    return warningIcon;\n                case MessageType.Error:\n                    return errorIcon;\n            }\n            return null;\n        }\n\n        // An invisible GUIContent that is not the same as GUIContent.none\n        internal static GUIContent blankContent { get; } = new GUIContent(\" \");\n\n        internal static GUIStyle whiteTextureStyle => s_WhiteTextureStyle ??\n        (s_WhiteTextureStyle = new GUIStyle {normal = {background = whiteTexture}});\n\n        internal static GUIStyle GetBasicTextureStyle(Texture2D tex)\n        {\n            if (s_BasicTextureStyle == null)\n                s_BasicTextureStyle = new GUIStyle();\n\n            s_BasicTextureStyle.normal.background = tex;\n\n            return s_BasicTextureStyle;\n        }\n\n        internal static void NotifyLanguageChanged(SystemLanguage newLanguage)\n        {\n            s_TextGUIContents = new Hashtable();\n            s_GUIContents = new Hashtable();\n            s_IconGUIContents = new Hashtable();\n            L10n.ClearCache();\n            EditorUtility.Internal_UpdateMenuTitleForLanguage(newLanguage);\n            LocalizationDatabase.currentEditorLanguage = newLanguage;\n            EditorTextSettings.UpdateLocalizationFontAsset();\n            EditorApplication.RequestRepaintAllViews();\n        }\n\n        // Get one of the built-in GUI skins, which can be the game view, inspector or scene view skin as chosen by the parameter.\n        public static GUISkin GetBuiltinSkin(EditorSkin skin)\n        {\n            return GUIUtility.GetBuiltinSkin((int)skin);\n        }\n\n        // Load a built-in resource that has to be there.\n        public static UnityObject LoadRequired(string path)\n        {\n            var o = Load(path, typeof(UnityObject));\n            if (!o)\n                Debug.LogError(\"Unable to find required resource at \" + path);\n            return o;\n        }\n\n        // Load a built-in resource\n        public static UnityObject Load(string path)\n        {\n            return Load(path, typeof(UnityObject));\n        }\n\n        [TypeInferenceRule(TypeInferenceRules.TypeReferencedBySecondArgument)]\n        private static UnityObject Load(string filename, Type type)\n        {\n            var asset = EditorResources.Load(filename, type);\n            if (asset != null)\n                return asset;\n\n            AssetBundle bundle = GetEditorAssetBundle();\n            if (bundle == null)\n            {\n                // If in batch mode, loading any Editor UI items shouldn't be needed\n                if (Application.isBatchMode)\n                    return null;\n                throw new NullReferenceException(\"Failure to load editor resource asset bundle.\");\n            }\n\n            asset = bundle.LoadAsset(filename, type);\n            if (asset != null)\n            {\n                asset.hideFlags |= HideFlags.HideAndDontSave;\n                return asset;\n            }\n\n            return AssetDatabase.LoadAssetAtPath(filename, type);\n        }\n\n        public static void PingObject(UnityObject obj)\n        {\n            if (obj != null)\n                PingObject(obj.GetInstanceID());\n        }\n\n        // Ping an object in a window like clicking it in an inspector\n        public static void PingObject(int targetInstanceID)\n        {\n            foreach (SceneHierarchyWindow shw in SceneHierarchyWindow.GetAllSceneHierarchyWindows())\n            {\n                shw.FrameObject(targetInstanceID, true);\n            }\n\n            foreach (ProjectBrowser pb in ProjectBrowser.GetAllProjectBrowsers())\n            {\n                pb.FrameObject(targetInstanceID, true);\n            }\n        }\n\n        // Same as PingObject, but renamed to avoid ambiguity when calling externally (i.e. using CallStaticMonoMethod)\n        [RequiredByNativeCode]\n        private static void PingObjectFromCPP(int targetInstanceID)\n        {\n            PingObject(targetInstanceID);\n        }\n\n        internal static void MoveFocusAndScroll(bool forward)\n        {\n            int prev = keyboardControl;\n            Internal_MoveKeyboardFocus(forward);\n            if (prev != keyboardControl)\n                RefreshScrollPosition();\n        }\n\n        internal static void RefreshScrollPosition()\n        {\n            Rect r;\n\n            if (Internal_GetKeyboardRect(keyboardControl, out r))\n            {\n                GUI.ScrollTo(r);\n            }\n        }\n\n        internal static void ScrollForTabbing(bool forward)\n        {\n            Rect r;\n\n            if (Internal_GetKeyboardRect(Internal_GetNextKeyboardControlID(forward), out r))\n            {\n                GUI.ScrollTo(r);\n            }\n        }\n\n        internal static void ResetGUIState()\n        {\n            GUI.skin = null;\n            GUI.backgroundColor = GUI.contentColor = Color.white;\n            GUI.color = EditorApplication.isPlayingOrWillChangePlaymode ? HostView.kPlayModeDarken : Color.white;\n            GUI.enabled = true;\n            GUI.changed = false;\n            EditorGUI.indentLevel = 0;\n            EditorGUI.ClearStacks();\n            fieldWidth = 0;\n            labelWidth = 0;\n            currentViewWidth = -1f;\n\n            SetBoldDefaultFont(false);\n            UnlockContextWidth();\n            hierarchyMode = false;\n            wideMode = false;\n            comparisonViewMode = ComparisonViewMode.None;\n            leftMarginCoord = 0;\n\n            //Clear the cache, so it uses the global one\n            ScriptAttributeUtility.propertyHandlerCache = null;\n        }\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"RenderGameViewCameras is no longer supported.Consider rendering cameras manually.\", true)]\n        public static void RenderGameViewCameras(Rect cameraRect, bool gizmos, bool gui) {}\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"RenderGameViewCameras is no longer supported.Consider rendering cameras manually.\", true)]\n        public static void RenderGameViewCameras(Rect cameraRect, Rect statsRect, bool gizmos, bool gui) {}\n\n        // Called from C++ GetControlID method when run from the Editor.\n        // Editor GUI needs some additional things to happen when calling GetControlID.\n        // While this will also be called for runtime code running in Play mode in the Editor,\n        // it won't have any effect. EditorGUIUtility.s_LastControlID will be set to the id,\n        // but this is only used inside the handling of a single control\n        // (see DoPropertyFieldKeyboardHandling).\n        // EditorGUI.s_PrefixLabel.text will only be not null when EditorGUI.PrefixLabel\n        // has been called without a specified controlID. The control following the PrefixLabel clears this.\n        [RequiredByNativeCode]\n        internal static void HandleControlID(int id)\n        {\n            s_LastControlID = id;\n            EditorGUI.PrepareCurrentPrefixLabel(s_LastControlID);\n        }\n\n        public static bool editingTextField\n        {\n            get { return EditorGUI.RecycledTextEditor.s_ActuallyEditing; }\n            set { EditorGUI.RecycledTextEditor.s_ActuallyEditing = value; }\n        }\n\n        internal static bool renameWasCompleted\n        {\n            get { return EditorGUI.RecycledTextEditor.s_EditingWasCompleted; }\n            set { EditorGUI.RecycledTextEditor.s_EditingWasCompleted = value; }\n        }\n\n        public static bool textFieldHasSelection\n        {\n            get { return EditorGUI.s_RecycledEditor.hasSelection; }\n        }\n\n        // hierarchyMode changes how foldouts are drawn so the foldout triangle is drawn to the left,\n        // outside the rect of the control, rather than inside the rect.\n        // This way the text of the foldout lines up with the labels of other controls.\n        // hierarchyMode is primarily enabled for editors in the Inspector.\n        public static bool hierarchyMode { get; set; } = false;\n\n        // wideMode is used when the Inspector is wide and uses a more tidy and vertically compact layout for certain controls.\n        public static bool wideMode { get; set; } = false;\n\n        internal enum ComparisonViewMode\n        {\n            None, Original, Modified\n        }\n\n        // ComparisonViewMode is used when editors are drawn in the context of showing differences between different objects.\n        // Controls that must not be used in this context can be hidden or disabled.\n        private static ComparisonViewMode s_ComparisonViewMode = ComparisonViewMode.None;\n        internal static ComparisonViewMode comparisonViewMode\n        {\n            get { return s_ComparisonViewMode; }\n            set { s_ComparisonViewMode = value; }\n        }\n\n        private static float s_LeftMarginCoord;\n        internal static float leftMarginCoord\n        {\n            get { return s_LeftMarginCoord; }\n            set { s_LeftMarginCoord = value; }\n        }\n\n        // Context width is used for calculating the label width for various editor controls.\n        // In most cases the top level clip rect is a perfect context width.\n        private static Stack<float> s_ContextWidthStack = new Stack<float>(10);\n\n        private static float CalcContextWidth()\n        {\n            float output = GUIClip.GetTopRect().width;\n            // If there's no top clip rect, fallback to using screen width.\n            if (output < 1f || output >= 40000)\n                output = currentViewWidth;\n\n            return output;\n        }\n\n        internal static void LockContextWidth()\n        {\n            s_ContextWidthStack.Push(CalcContextWidth());\n        }\n\n        internal static void UnlockContextWidth()\n        {\n            if (s_ContextWidthStack.Count > 0)\n            {\n                s_ContextWidthStack.Pop();\n            }\n        }\n\n        internal static float contextWidth\n        {\n            get\n            {\n                if (s_ContextWidthStack.Count > 0 && s_ContextWidthStack.Peek() > 0f)\n                    return s_ContextWidthStack.Peek();\n\n                return CalcContextWidth();\n            }\n        }\n\n        private static float s_OverriddenViewWidth = -1f;\n        public static float currentViewWidth\n        {\n            get\n            {\n                if (s_OverriddenViewWidth > 0f)\n                    return s_OverriddenViewWidth;\n                CheckOnGUI();\n                return GUIView.current ? GUIView.current.position.width : 0;\n            }\n            internal set\n            {\n                s_OverriddenViewWidth = value;\n            }\n        }\n\n        public static float labelWidth\n        {\n            get\n            {\n                if (s_LabelWidth > 0)\n                    return s_LabelWidth;\n\n                if (hierarchyMode)\n                    return Mathf.Max(Mathf.Ceil(contextWidth * EditorGUI.kLabelWidthRatio) - EditorGUI.kLabelWidthMargin, EditorGUI.kMinLabelWidth);\n                return 150;\n            }\n            set { s_LabelWidth = value; }\n        }\n\n        private static float s_FieldWidth = 0f;\n        public static float fieldWidth\n        {\n            get\n            {\n                if (s_FieldWidth > 0)\n                    return s_FieldWidth;\n\n                return 50;\n            }\n            set { s_FieldWidth = value; }\n        }\n\n        // Make all ref::EditorGUI look like regular controls.\n        private const string k_LookLikeControlsObsoleteMessage = \"LookLikeControls and LookLikeInspector modes are deprecated.Use EditorGUIUtility.labelWidth and EditorGUIUtility.fieldWidth to control label and field widths.\";\n        [Obsolete(k_LookLikeControlsObsoleteMessage, false)]\n        public static void LookLikeControls(float _labelWidth, float _fieldWidth)\n        {\n            fieldWidth = _fieldWidth;\n            labelWidth = _labelWidth;\n        }\n\n        [ExcludeFromDocs, Obsolete(k_LookLikeControlsObsoleteMessage, false)] public static void LookLikeControls(float _labelWidth) { LookLikeControls(_labelWidth, 0); }\n        [ExcludeFromDocs, Obsolete(k_LookLikeControlsObsoleteMessage, false)] public static void LookLikeControls() { LookLikeControls(0, 0); }\n\n        // Make all ::ref::EditorGUI look like simplified outline view controls.\n        [Obsolete(\"LookLikeControls and LookLikeInspector modes are deprecated.\", false)]\n        public static void LookLikeInspector()\n        {\n            fieldWidth = 0;\n            labelWidth = 0;\n        }\n\n        [Obsolete(\"This field is no longer used by any builtin controls. If passing this field to GetControlID, explicitly use the FocusType enum instead.\", false)]\n        public static FocusType native = FocusType.Keyboard;\n\n        internal static void SkinChanged()\n        {\n            EditorStyles.UpdateSkinCache();\n        }\n\n        internal static Rect DragZoneRect(Rect position, bool hasLabel = true)\n        {\n            return new Rect(position.x, position.y, hasLabel ? labelWidth : 0, position.height);\n        }\n\n        internal static void MoveArrayExpandedState(SerializedProperty elements, int oldActiveElement, int newActiveElement)\n        {\n            SerializedProperty prop1 = elements.GetArrayElementAtIndex(oldActiveElement);\n            SerializedProperty prop2;\n            int depth;\n            List<bool> tempIsExpanded = ListPool<bool>.Get();\n            var tempProp = prop1;\n            tempIsExpanded.Add(prop1.isExpanded);\n            bool clearGradientCache = false;\n            int next = (oldActiveElement < newActiveElement) ? 1 : -1;\n\n            for (int i = oldActiveElement + next;\n                 (oldActiveElement < newActiveElement) ? i <= newActiveElement : i >= newActiveElement;\n                 i += next)\n            {\n                prop2 = elements.GetArrayElementAtIndex(i);\n\n                var cprop1 = prop1.Copy();\n                var cprop2 = prop2.Copy();\n                depth = Math.Min(cprop1.depth, cprop2.depth);\n                while (cprop1.NextVisible(true) && cprop1.depth > depth && cprop2.NextVisible(true) && cprop2.depth > depth)\n                {\n                    if (cprop1.hasVisibleChildren && cprop2.hasVisibleChildren)\n                    {\n                        tempIsExpanded.Add(cprop1.isExpanded);\n                        cprop1.isExpanded = cprop2.isExpanded;\n                    }\n                }\n\n                prop1.isExpanded = prop2.isExpanded;\n                if (prop1.propertyType == SerializedPropertyType.Gradient)\n                    clearGradientCache = true;\n                prop1 = prop2;\n            }\n\n            prop1.isExpanded = tempIsExpanded[0];\n            depth = Math.Min(prop1.depth, tempProp.depth);\n            int k = 1;\n            while (prop1.NextVisible(true) && prop1.depth > depth && tempProp.NextVisible(true) && tempProp.depth > depth)\n            {\n                if (prop1.hasVisibleChildren && tempProp.hasVisibleChildren && tempIsExpanded.Count > k)\n                {\n                    prop1.isExpanded = tempIsExpanded[k];\n                    k++;\n                }\n            }\n            ListPool<bool>.Release(tempIsExpanded);\n\n            if (clearGradientCache)\n                GradientPreviewCache.ClearCache();\n        }\n\n        internal static void SetBoldDefaultFont(bool isBold)\n        {\n            int wantsBold = isBold ? 1 : 0;\n            if (wantsBold != s_FontIsBold)\n            {\n                SetDefaultFont(isBold ? EditorStyles.boldFont : EditorStyles.standardFont);\n                s_FontIsBold = wantsBold;\n            }\n        }\n\n        internal static bool GetBoldDefaultFont() { return s_FontIsBold == 1; }\n\n        // Creates an event\n        public static Event CommandEvent(string commandName)\n        {\n            Event e = new Event();\n            Internal_SetupEventValues(e);\n            e.type = EventType.ExecuteCommand;\n            e.commandName = commandName;\n            return e;\n        }\n\n        // Draw a color swatch.\n        public static void DrawColorSwatch(Rect position, Color color)\n        {\n            DrawColorSwatch(position, color, true);\n        }\n\n        internal static void DrawColorSwatch(Rect position, Color color, bool showAlpha)\n        {\n            DrawColorSwatch(position, color, showAlpha, false);\n        }\n\n        internal static void DrawColorSwatch(Rect position, Color color, bool showAlpha, bool hdr)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            Color oldColor = GUI.color;\n            Color oldBackgroundColor = GUI.backgroundColor;\n\n            float a = GUI.enabled ? 1 : 2;\n\n            GUI.color = EditorGUI.showMixedValue ? new Color(0.82f, 0.82f, 0.82f, a) * oldColor : new Color(color.r, color.g, color.b, a);\n            if (hdr)\n                GUI.color = GUI.color.gamma;\n            GUI.backgroundColor = Color.white;\n\n            GUIStyle gs = whiteTextureStyle;\n            gs.Draw(position, false, false, false, false);\n\n            // Render LDR -> HDR gradients on the sides when having HDR values (to let the user see what the normalized color looks like)\n            if (hdr)\n            {\n                Color32 baseColor;\n                float exposure;\n                ColorMutator.DecomposeHdrColor(GUI.color.linear, out baseColor, out exposure);\n\n                if (!Mathf.Approximately(exposure, 0f))\n                {\n                    float gradientWidth = position.width / 3f;\n                    Rect leftRect = new Rect(position.x, position.y, gradientWidth, position.height);\n                    Rect rightRect = new Rect(position.xMax - gradientWidth, position.y, gradientWidth,\n                        position.height);\n\n                    Color orgColor = GUI.color;\n                    GUI.color = ((Color)baseColor).gamma;\n                    GUIStyle basicStyle = GetBasicTextureStyle(whiteTexture);\n                    basicStyle.Draw(leftRect, false, false, false, false);\n                    basicStyle.Draw(rightRect, false, false, false, false);\n                    GUI.color = orgColor;\n\n                    basicStyle = GetBasicTextureStyle(ColorPicker.GetGradientTextureWithAlpha0To1());\n                    basicStyle.Draw(leftRect, false, false, false, false);\n                    basicStyle = GetBasicTextureStyle(ColorPicker.GetGradientTextureWithAlpha1To0());\n                    basicStyle.Draw(rightRect, false, false, false, false);\n                }\n            }\n\n            if (!EditorGUI.showMixedValue)\n            {\n                if (showAlpha)\n                {\n                    GUI.color = new Color(0, 0, 0, a);\n                    float alphaHeight = Mathf.Clamp(position.height * .2f, 2, 20);\n                    Rect alphaBarRect = new Rect(position.x, position.yMax - alphaHeight, position.width, alphaHeight);\n                    gs.Draw(alphaBarRect, false, false, false, false);\n\n                    GUI.color = new Color(1, 1, 1, a);\n                    alphaBarRect.width *= Mathf.Clamp01(color.a);\n                    gs.Draw(alphaBarRect, false, false, false, false);\n                }\n            }\n            else\n            {\n                EditorGUI.BeginHandleMixedValueContentColor();\n                gs.Draw(position, EditorGUI.mixedValueContent, false, false, false, false);\n                EditorGUI.EndHandleMixedValueContentColor();\n            }\n\n            GUI.color = oldColor;\n            GUI.backgroundColor = oldBackgroundColor;\n\n            // HDR label overlay\n            if (hdr)\n            {\n                GUI.Label(new Rect(position.x, position.y, position.width - 3, position.height), \"HDR\", EditorStyles.centeredGreyMiniLabel);\n            }\n        }\n\n        internal static void DrawRegionSwatch(Rect position, SerializedProperty property, SerializedProperty property2, Color color, Color bgColor)\n        {\n            DrawCurveSwatchInternal(position, null, null, property, property2, color, bgColor, false, new Rect(), Color.clear, Color.clear);\n        }\n\n        public static void DrawCurveSwatch(Rect position, AnimationCurve curve, SerializedProperty property, Color color, Color bgColor)\n        {\n            DrawCurveSwatchInternal(position, curve, null, property, null, color, bgColor, false, new Rect(), Color.clear, Color.clear);\n        }\n\n        public static void DrawCurveSwatch(Rect position, AnimationCurve curve, SerializedProperty property, Color color, Color bgColor, Color topFillColor, Color bottomFillColor)\n        {\n            DrawCurveSwatchInternal(position, curve, null, property, null, color, bgColor, false, new Rect(), topFillColor, bottomFillColor);\n        }\n\n        // Draw a curve swatch.\n        public static void DrawCurveSwatch(Rect position, AnimationCurve curve, SerializedProperty property, Color color, Color bgColor, Color topFillColor, Color bottomFillColor, Rect curveRanges)\n        {\n            DrawCurveSwatchInternal(position, curve, null, property, null, color, bgColor, true, curveRanges, topFillColor, bottomFillColor);\n        }\n\n        public static void DrawCurveSwatch(Rect position, AnimationCurve curve, SerializedProperty property, Color color, Color bgColor, Rect curveRanges)\n        {\n            DrawCurveSwatchInternal(position, curve, null, property, null, color, bgColor, true, curveRanges, Color.clear, Color.clear);\n        }\n\n        // Draw swatch with a filled region between two SerializedProperty curves.\n        public static void DrawRegionSwatch(Rect position, SerializedProperty property, SerializedProperty property2, Color color, Color bgColor, Rect curveRanges)\n        {\n            DrawCurveSwatchInternal(position, null, null, property, property2, color, bgColor, true, curveRanges, Color.clear, Color.clear);\n        }\n\n        // Draw swatch with a filled region between two curves.\n        public static void DrawRegionSwatch(Rect position, AnimationCurve curve, AnimationCurve curve2, Color color, Color bgColor, Rect curveRanges)\n        {\n            DrawCurveSwatchInternal(position, curve, curve2, null, null, color, bgColor, true, curveRanges, Color.clear, Color.clear);\n        }\n\n        private static void DrawCurveSwatchInternal(Rect position, AnimationCurve curve, AnimationCurve curve2, SerializedProperty property, SerializedProperty property2, Color color, Color bgColor, bool useCurveRanges, Rect curveRanges, Color topFillColor, Color bottomFillColor)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            int previewWidth = (int)position.width;\n            int previewHeight = (int)position.height;\n            int maxTextureDim = SystemInfo.maxTextureSize;\n\n            bool stretchX = previewWidth > maxTextureDim;\n            bool stretchY = previewHeight > maxTextureDim;\n            if (stretchX)\n                previewWidth = Mathf.Min(previewWidth, maxTextureDim);\n            if (stretchY)\n                previewHeight = Mathf.Min(previewHeight, maxTextureDim);\n\n            // Draw background color\n            Color oldColor = GUI.color;\n            GUI.color = EditorApplication.isPlayingOrWillChangePlaymode ? bgColor * HostView.kPlayModeDarken : bgColor;\n            GUIStyle gs = whiteTextureStyle;\n            gs.Draw(position, false, false, false, false);\n            GUI.color = oldColor;\n\n            if (property != null && property.hasMultipleDifferentValues)\n            {\n                // No obvious way to show that curve field has mixed values so we just draw\n                // the same content as for text fields since the user at least know what that means.\n                EditorGUI.BeginHandleMixedValueContentColor();\n                GUI.Label(position, EditorGUI.mixedValueContent, \"PreOverlayLabel\");\n                EditorGUI.EndHandleMixedValueContentColor();\n            }\n            else\n            {\n                Texture2D preview = null;\n                if (property != null)\n                {\n                    if (property2 == null)\n                        preview = useCurveRanges ? AnimationCurvePreviewCache.GetPreview(previewWidth, previewHeight, property, color, topFillColor, bottomFillColor, curveRanges) : AnimationCurvePreviewCache.GetPreview(previewWidth, previewHeight, property, color, topFillColor, bottomFillColor);\n                    else\n                        preview = useCurveRanges ? AnimationCurvePreviewCache.GetPreview(previewWidth, previewHeight, property, property2, color, topFillColor, bottomFillColor, curveRanges) : AnimationCurvePreviewCache.GetPreview(previewWidth, previewHeight, property, property2, color, topFillColor, bottomFillColor);\n                }\n                else if (curve != null)\n                {\n                    if (curve2 == null)\n                        preview = useCurveRanges ? AnimationCurvePreviewCache.GetPreview(previewWidth, previewHeight, curve, color, topFillColor, bottomFillColor, curveRanges) : AnimationCurvePreviewCache.GetPreview(previewWidth, previewHeight, curve, color, topFillColor, bottomFillColor);\n                    else\n                        preview = useCurveRanges ? AnimationCurvePreviewCache.GetPreview(previewWidth, previewHeight, curve, curve2, color, topFillColor, bottomFillColor, curveRanges) : AnimationCurvePreviewCache.GetPreview(previewWidth, previewHeight, curve, curve2, color, topFillColor, bottomFillColor);\n                }\n                gs = GetBasicTextureStyle(preview);\n\n                if (!stretchX && preview)\n                    position.width = preview.width;\n                if (!stretchY && preview)\n                    position.height = preview.height;\n\n                gs.Draw(position, false, false, false, false);\n            }\n        }\n\n        // Convert a color from RGB to HSV color space.\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"EditorGUIUtility.RGBToHSV is obsolete. Use Color.RGBToHSV instead (UnityUpgradable) -> [UnityEngine] UnityEngine.Color.RGBToHSV(*)\", true)]\n        public static void RGBToHSV(Color rgbColor, out float H, out float S, out float V)\n        {\n            Color.RGBToHSV(rgbColor, out H, out S, out V);\n        }\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"EditorGUIUtility.HSVToRGB is obsolete. Use Color.HSVToRGB instead (UnityUpgradable) -> [UnityEngine] UnityEngine.Color.HSVToRGB(*)\", true)]\n        public static Color HSVToRGB(float H, float S, float V)\n        {\n            return Color.HSVToRGB(H, S, V);\n        }\n\n        // Convert a set of HSV values to an RGB Color.\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"EditorGUIUtility.HSVToRGB is obsolete. Use Color.HSVToRGB instead (UnityUpgradable) -> [UnityEngine] UnityEngine.Color.HSVToRGB(*)\", true)]\n        public static Color HSVToRGB(float H, float S, float V, bool hdr)\n        {\n            return Color.HSVToRGB(H, S, V, hdr);\n        }\n\n        // Add a custom mouse pointer to a control\n        public static void AddCursorRect(Rect position, MouseCursor mouse)\n        {\n            AddCursorRect(position, mouse, 0);\n        }\n\n        public static void AddCursorRect(Rect position, MouseCursor mouse, int controlID)\n        {\n            if (Event.current.type == EventType.Repaint)\n            {\n                Rect r = GUIClip.Unclip(position);\n                Rect clip = GUIClip.topmostRect;\n                Rect clipped = Rect.MinMaxRect(Mathf.Max(r.x, clip.x), Mathf.Max(r.y, clip.y), Mathf.Min(r.xMax, clip.xMax), Mathf.Min(r.yMax, clip.yMax));\n\n                if (clipped.width <= 0 || clipped.height <= 0)\n                    return;\n                Internal_AddCursorRect(clipped, mouse, controlID);\n            }\n        }\n\n        internal static Rect HandleHorizontalSplitter(Rect dragRect, float width, float minLeftSide, float minRightSide)\n        {\n            // Add a cursor rect indicating we can drag this area\n            if (Event.current.type == EventType.Repaint)\n                AddCursorRect(dragRect, MouseCursor.SplitResizeLeftRight);\n\n            // Drag splitter\n            float deltaX = EditorGUI.MouseDeltaReader(dragRect, true).x;\n            if (deltaX != 0f)\n                dragRect.x += deltaX;\n            float newX = Mathf.Clamp(dragRect.x, minLeftSide, width - minRightSide);\n\n            // We might need to move the splitter position if our area/window size has changed\n            if (dragRect.x > width - minRightSide)\n                newX = width - minRightSide;\n\n            dragRect.x = Mathf.Clamp(newX, minLeftSide, width - minRightSide);\n            return dragRect;\n        }\n\n        internal static void DrawHorizontalSplitter(Rect dragRect)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            Color orgColor = GUI.color;\n            Color tintColor = (isProSkin) ? new Color(0.12f, 0.12f, 0.12f, 1.333f) : new Color(0.6f, 0.6f, 0.6f, 1.333f);\n            GUI.color = GUI.color * tintColor;\n            Rect splitterRect = new Rect(dragRect.x - 1, dragRect.y, 1, dragRect.height);\n            GUI.DrawTexture(splitterRect, whiteTexture);\n            GUI.color = orgColor;\n        }\n\n        internal static EventType magnifyGestureEventType => (EventType)1000;\n        internal static EventType swipeGestureEventType => (EventType)1001;\n        internal static EventType rotateGestureEventType => (EventType)1002;\n\n        public static void ShowObjectPicker<T>(UnityObject obj, bool allowSceneObjects, string searchFilter, int controlID) where T : UnityObject\n        {\n            Type objType = typeof(T);\n            //case 1113046: Delay the show method when it is called while other object picker is closing\n            if (Event.current?.commandName == \"ObjectSelectorClosed\")\n                EditorApplication.delayCall += () => SetupObjectSelector(obj, objType, allowSceneObjects, searchFilter, controlID);\n            else\n                SetupObjectSelector(obj, objType, allowSceneObjects, searchFilter, controlID);\n        }\n\n        private static void SetupObjectSelector(UnityObject obj, Type objType, bool allowSceneObjects, string searchFilter, int controlID)\n        {\n            ObjectSelector.get.Show(obj, objType, null, allowSceneObjects);\n            ObjectSelector.get.objectSelectorID = controlID;\n            ObjectSelector.get.searchFilter = searchFilter;\n        }\n\n        public static UnityObject GetObjectPickerObject()\n        {\n            return ObjectSelector.GetCurrentObject();\n        }\n\n        public static int GetObjectPickerControlID()\n        {\n            return ObjectSelector.get.objectSelectorID;\n        }\n\n        internal static string GetHyperlinkColorForSkin()\n        {\n            return skinIndex == EditorResources.darkSkinIndex ? \"#40a0ff\" : \"#0000FF\";\n        }\n\n        // Enum for tracking what styles the editor uses\n        internal enum EditorLook\n        {\n            // Hasn't been set\n            Uninitialized = 0,\n            // Looks like regular controls\n            LikeControls = 1,\n            // Looks like inspector\n            LikeInspector = 2\n        }\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal class BuiltinResource\n    {\n        public string m_Name;\n        public int m_InstanceID;\n    }\n\n    internal struct SliderLabels\n    {\n        public void SetLabels(GUIContent _leftLabel, GUIContent _rightLabel)\n        {\n            if (Event.current.type == EventType.Repaint)\n            {\n                leftLabel = _leftLabel;\n                rightLabel = _rightLabel;\n            }\n        }\n\n        public bool HasLabels()\n        {\n            if (Event.current.type == EventType.Repaint)\n            {\n                return leftLabel != null && rightLabel != null;\n            }\n            return false;\n        }\n\n        public GUIContent leftLabel;\n        public GUIContent rightLabel;\n    }\n\n    internal class GUILayoutFadeGroup : GUILayoutGroup\n    {\n        public float fadeValue;\n        public bool wasGUIEnabled;\n        public Color guiColor;\n\n        public override void CalcHeight()\n        {\n            base.CalcHeight();\n            minHeight *= fadeValue;\n            maxHeight *= fadeValue;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorGraphicsSettings.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Build;\nusing UnityEditor.Inspector.GraphicsSettingsInspectors;\nusing UnityEditor.Rendering.Settings;\nusing UnityEngine.Bindings;\nusing UnityEngine.Rendering;\nusing UnityEngine.Scripting;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor.Rendering\n{\n    [NativeHeader(\"Editor/Mono/EditorGraphicsSettings.bindings.h\")]\n    [StaticAccessor(\"EditorGraphicsSettingsScripting\", StaticAccessorType.DoubleColon)]\n    public sealed partial class EditorGraphicsSettings\n    {\n        [NativeName(\"SetTierSettings\")] extern internal static void SetTierSettingsImpl(BuildTargetGroup target, GraphicsTier tier, TierSettings settings);\n\n        extern public static TierSettings GetTierSettings(BuildTargetGroup target, GraphicsTier tier);\n        public static TierSettings GetTierSettings(NamedBuildTarget target, GraphicsTier tier) => GetTierSettings(target.ToBuildTargetGroup(), tier);\n\n        extern internal static TierSettings GetCurrentTierSettings();\n\n        extern internal static bool AreTierSettingsAutomatic(BuildTargetGroup target, GraphicsTier tier);\n        extern internal static void MakeTierSettingsAutomatic(BuildTargetGroup target, GraphicsTier tier, bool automatic);\n\n        extern internal static void OnUpdateTierSettings(BuildTargetGroup target, bool shouldReloadShaders);\n\n        // we give access to shader settings from both UI and script, and usually script access do not touch Undo system by itself\n        // hence we provide small helper for our UI to register Undo changes when needed\n        extern internal static void RegisterUndo();\n\n        extern private static AlbedoSwatchInfo[] GetAlbedoSwatches();\n        extern private static void SetAlbedoSwatches(AlbedoSwatchInfo[] swatches);\n\n        public static AlbedoSwatchInfo[] albedoSwatches\n        {\n            get { return GetAlbedoSwatches(); }\n            set { SetAlbedoSwatches(value); }\n        }\n\n        extern public static BatchRendererGroupStrippingMode batchRendererGroupShaderStrippingMode { get; }\n        extern internal static bool activeProfileHasGraphicsSettings { get; set; }\n\n        [NativeName(\"RegisterRenderPipelineSettings\")] static extern bool Internal_TryRegisterRenderPipeline(string renderpipelineName, Object settings);\n        [NativeName(\"UnregisterRenderPipelineSettings\")] static extern bool Internal_TryUnregisterRenderPipeline(string renderpipelineName);\n        [NativeName(\"GetSettingsForRenderPipeline\")] static extern Object Internal_GetSettingsForRenderPipeline(string renderpipelineName);\n\n        [NativeName(\"GetSettingsInstanceIDForRenderPipeline\")] internal static extern int Internal_GetSettingsInstanceIDForRenderPipeline(string renderpipelineName);\n\n        private static void CheckRenderPipelineType(Type renderPipelineType)\n        {\n            if (renderPipelineType == null)\n                throw new ArgumentNullException(nameof(renderPipelineType));\n\n            if (!typeof(RenderPipeline).IsAssignableFrom(renderPipelineType))\n                throw new ArgumentException($\"{renderPipelineType} must be a valid {nameof(RenderPipeline)}\");\n        }\n\n        public static void SetRenderPipelineGlobalSettingsAsset(Type renderPipelineType, RenderPipelineGlobalSettings newSettings)\n        {\n            //In Worker thread, we cannot update assets\n            if (AssetDatabase.IsAssetImportWorkerProcess())\n                return;\n\n            CheckRenderPipelineType(renderPipelineType);\n\n            bool globalSettingsAssetChanged;\n            if (newSettings != null)\n            {\n                RenderPipelineGraphicsSettingsManager.PopulateRenderPipelineGraphicsSettings(newSettings);\n                globalSettingsAssetChanged = Internal_TryRegisterRenderPipeline(renderPipelineType.FullName, newSettings);\n            }\n            else\n                globalSettingsAssetChanged = Internal_TryUnregisterRenderPipeline(renderPipelineType.FullName);\n\n            if (globalSettingsAssetChanged)\n            {\n                var rpAsset = RenderPipelineManager.currentPipelineAsset;\n                if (rpAsset != null && rpAsset.pipelineType == renderPipelineType)\n                    RenderPipelineManager.RecreateCurrentPipeline(rpAsset);\n            }\n\n            //Removing a globalSeetings and adding back another one from the same type will cause issue in the Notifier persistency cache\n            Notifier.RecomputeDictionary();  \n\n            GraphicsSettingsInspectorUtility.ReloadGraphicsSettingsEditorIfNeeded();\n        }\n\n        public static void SetRenderPipelineGlobalSettingsAsset<T>(RenderPipelineGlobalSettings newSettings)\n            where T : RenderPipeline\n        {\n            SetRenderPipelineGlobalSettingsAsset(typeof(T), newSettings);\n        }\n\n        public static RenderPipelineGlobalSettings GetRenderPipelineGlobalSettingsAsset(Type renderPipelineType)\n        {\n            CheckRenderPipelineType(renderPipelineType);\n            return Internal_GetSettingsForRenderPipeline(renderPipelineType.FullName) as RenderPipelineGlobalSettings;\n        }\n\n        public static RenderPipelineGlobalSettings GetRenderPipelineGlobalSettingsAsset<T>()\n            where T : RenderPipeline\n        {\n            return GetRenderPipelineGlobalSettingsAsset(typeof(T));\n        }\n\n        public static bool TryGetRenderPipelineSettingsForPipeline<TSettings, TPipeline>(out TSettings settings)\n            where TSettings : class, IRenderPipelineGraphicsSettings\n            where TPipeline : RenderPipeline\n        {\n            return TryGetRenderPipelineSettingsForPipeline(typeof(TPipeline), out settings);\n        }\n\n        public static bool TryGetRenderPipelineSettingsForPipeline<TSettings>(Type renderPipelineType, out TSettings settings)\n            where TSettings : class, IRenderPipelineGraphicsSettings\n        {\n            settings = null;\n\n            var pipelineGlobalSettings = GraphicsSettings.GetSettingsForRenderPipeline(renderPipelineType);\n            if (pipelineGlobalSettings == null)\n                return false;\n\n            if (pipelineGlobalSettings.TryGet(typeof(TSettings), out var baseSettings))\n                settings = baseSettings as TSettings;\n\n            return settings != null;\n        }\n\n        public static IEnumerable<Type> GetSupportedRenderPipelineGraphicsSettingsTypesForPipeline<T>()\n            where T : RenderPipelineAsset\n        {\n            foreach(var info in RenderPipelineGraphicsSettingsManager.FetchRenderPipelineGraphicsSettingInfos(typeof(T)))\n                yield return info.type;\n        }\n\n        public static void PopulateRenderPipelineGraphicsSettings(RenderPipelineGlobalSettings settings)\n        {\n            RenderPipelineGraphicsSettingsManager.PopulateRenderPipelineGraphicsSettings(settings);\n        }\n\n        [NativeName(\"GraphicsSettingsCount\")] static extern int Internal_GraphicsSettingsCount();\n        [NativeName(\"GetSettingsForRenderPipelineAt\")] static extern Object Internal_GetSettingsForRenderPipelineAt(int index);\n\n        internal static void ForEachPipelineSettings(Action<RenderPipelineGlobalSettings> action)\n        {\n            int count = Internal_GraphicsSettingsCount();\n            for (int i = 0; i < count; ++i)\n                action?.Invoke(Internal_GetSettingsForRenderPipelineAt(i) as RenderPipelineGlobalSettings);\n        }\n\n        public static TSettingsInterfaceType[] GetRenderPipelineSettingsFromInterface<TSettingsInterfaceType>()\n            where TSettingsInterfaceType : class, IRenderPipelineGraphicsSettings\n        {\n            if (!GraphicsSettings.TryGetCurrentRenderPipelineGlobalSettings(out RenderPipelineGlobalSettings asset))\n                return new TSettingsInterfaceType[] {};\n\n            if (asset.GetSettingsImplementingInterface<TSettingsInterfaceType>(out var baseSettings))\n            {\n                return baseSettings.ToArray();\n            }\n\n            return new TSettingsInterfaceType[] {};\n        }\n\n        public static bool TryGetFirstRenderPipelineSettingsFromInterface<TSettingsInterfaceType>(out TSettingsInterfaceType settings)\n            where TSettingsInterfaceType : class, IRenderPipelineGraphicsSettings\n        {\n            settings = null;\n\n            if (!GraphicsSettings.TryGetCurrentRenderPipelineGlobalSettings(out RenderPipelineGlobalSettings asset))\n                return false;\n\n            if (asset.TryGetFirstSettingsImplementingInterface<TSettingsInterfaceType>(out var baseSettings))\n            {\n                settings = baseSettings;\n                return true;\n            }\n\n            return false;\n        }\n\n        public static bool TryGetRenderPipelineSettingsFromInterface<TSettingsInterfaceType>(out TSettingsInterfaceType[] settings)\n            where TSettingsInterfaceType : class, IRenderPipelineGraphicsSettings\n        {\n            settings = null;\n\n            if (!GraphicsSettings.TryGetCurrentRenderPipelineGlobalSettings(out RenderPipelineGlobalSettings asset))\n                return false;\n\n            if (asset.GetSettingsImplementingInterface<TSettingsInterfaceType>(out var baseSettings))\n                settings = baseSettings.ToArray();\n\n            return settings != null;\n        }\n\n        public static bool TryGetRenderPipelineSettingsFromInterfaceForPipeline<TSettingsInterfaceType, TPipeline>(out TSettingsInterfaceType[] settings)\n            where TSettingsInterfaceType : class, IRenderPipelineGraphicsSettings\n            where TPipeline : RenderPipeline\n        {\n            return TryGetRenderPipelineSettingsFromInterfaceForPipeline(typeof(TPipeline), out settings);\n        }\n\n        public static bool TryGetRenderPipelineSettingsFromInterfaceForPipeline<TSettingsInterfaceType>(Type renderPipelineType, out TSettingsInterfaceType[] settings)\n            where TSettingsInterfaceType : class, IRenderPipelineGraphicsSettings\n        {\n            settings = null;\n\n            var pipelineGlobalSettings = GraphicsSettings.GetSettingsForRenderPipeline(renderPipelineType);\n            if (pipelineGlobalSettings == null)\n                return false;\n\n            if (pipelineGlobalSettings.GetSettingsImplementingInterface<TSettingsInterfaceType>(out var baseSettings))\n                settings = baseSettings.ToArray();\n\n            return settings != null;\n        }\n\n        [RequiredByNativeCode]\n        internal static bool IsGlobalSettingsContaining(UnityEngine.Object renderPipelineGlobalSettings, object renderPipelineGraphicsSettings)\n        {\n            var settings = renderPipelineGraphicsSettings as IRenderPipelineGraphicsSettings;\n            var globalSettings = renderPipelineGlobalSettings as RenderPipelineGlobalSettings;\n            return globalSettings.ContainsReference(settings);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorGraphicsSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute;\n\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEditor.Build;\n\nnamespace UnityEditor.Rendering\n{\n    public enum ShaderQuality\n    {\n        Low,\n        Medium,\n        High,\n    }\n\n    public struct AlbedoSwatchInfo\n    {\n        public string name;\n        public Color  color;\n        public float  minLuminance;\n        public float  maxLuminance;\n    }\n\n    public enum BatchRendererGroupStrippingMode\n    {\n        [InspectorName(\"Strip if Entities Graphics Package is not installed\")]\n        KeepIfEntitiesGraphics = 0,\n        StripAll,\n        KeepAll\n    }\n\n    internal enum InstancingStrippingMode\n    {\n        StripUnused = 0,\n        StripAll,\n        KeepAll\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    public struct TierSettings\n    {\n        public ShaderQuality    standardShaderQuality;\n        public CameraHDRMode    hdrMode;\n        public bool             reflectionProbeBoxProjection;\n        public bool             reflectionProbeBlending;\n        public bool             hdr;\n        public bool             detailNormalMap;\n\n        public bool             cascadedShadowMaps;\n        public bool             prefer32BitShadowMaps;\n        public bool             enableLPPV;\n        public bool             semitransparentShadows;\n\n        public RenderingPath    renderingPath;\n        public RealtimeGICPUUsage realtimeGICPUUsage;\n    }\n\n\n    public sealed partial class EditorGraphicsSettings\n    {\n        // Use the version with NamedBuildTarget passed instead.\n        // [Obsolete(\"Use SetTierSettings() instead (UnityUpgradable) -> SetTierSettings(*)\", false)]\n        public static void SetTierSettings(BuildTargetGroup target, GraphicsTier tier, TierSettings settings)\n        {\n            if (settings.renderingPath == RenderingPath.UsePlayerSettings)\n                throw new ArgumentException(\"TierSettings.renderingPath must be actual rendering path (not UsePlayerSettings)\", \"settings\");\n\n            SetTierSettingsImpl(target, tier, settings);\n            MakeTierSettingsAutomatic(target, tier, false);\n            OnUpdateTierSettings(target, true);\n        }\n\n        public static void SetTierSettings(NamedBuildTarget target, GraphicsTier tier, TierSettings settings) => SetTierSettings(target.ToBuildTargetGroup(), tier, settings);\n    }\n\n\n    //\n    // deprecated\n    //\n\n    [Obsolete(\"Use TierSettings instead (UnityUpgradable) -> UnityEditor.Rendering.TierSettings\", false)]\n    [StructLayout(LayoutKind.Sequential)]\n    public struct PlatformShaderSettings\n    {\n        [MarshalAs(UnmanagedType.I1)] public bool cascadedShadowMaps;\n        [MarshalAs(UnmanagedType.I1)] public bool reflectionProbeBoxProjection;\n        [MarshalAs(UnmanagedType.I1)] public bool reflectionProbeBlending;\n\n        public ShaderQuality    standardShaderQuality;\n    }\n\n    public sealed partial class EditorGraphicsSettings\n    {\n        [Obsolete(\"Use GetTierSettings() instead (UnityUpgradable) -> GetTierSettings(*)\", true)]\n        public static PlatformShaderSettings GetShaderSettingsForPlatform(BuildTargetGroup target, ShaderHardwareTier tier)\n        {\n            PlatformShaderSettings pss = new PlatformShaderSettings();\n            return pss;\n        }\n\n        [Obsolete(\"Use SetTierSettings() instead (UnityUpgradable) -> SetTierSettings(*)\", true)]\n        public static void SetShaderSettingsForPlatform(BuildTargetGroup target, ShaderHardwareTier tier, PlatformShaderSettings settings) {}\n\n        [Obsolete(\"Use GraphicsTier instead of ShaderHardwareTier enum\", true)]\n        public static TierSettings GetTierSettings(BuildTargetGroup target, ShaderHardwareTier tier)\n        {\n            return GetTierSettings(target, (GraphicsTier)tier);\n        }\n\n        [Obsolete(\"Use GraphicsTier instead of ShaderHardwareTier enum\", true)]\n        public static void SetTierSettings(BuildTargetGroup target, ShaderHardwareTier tier, TierSettings settings)\n        {\n            SetTierSettings(target, (GraphicsTier)tier, settings);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorHeaderItemAttribute.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]\n    internal sealed partial class EditorHeaderItemAttribute : CallbackOrderAttribute\n    {\n        public EditorHeaderItemAttribute(Type targetType, int priority = 1)\n        {\n            TargetType = targetType;\n            m_CallbackOrder = priority;\n        }\n\n        public Type TargetType;\n\n        [RequiredSignature]\n        static bool SignatureBool(Rect rectangle, UnityEngine.Object[] targetObjets) { throw new InvalidOperationException(); }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorMode/MenuService.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Collections;\nusing System.Linq;\nusing System.Reflection;\nusing JetBrains.Annotations;\nusing UnityEngine.Scripting;\nusing UnityEngine;\n\nusing JSONObject = System.Collections.IDictionary;\n\nusing static UnityEditor.ModeService;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEditor.ShortcutManagement;\n\nnamespace UnityEditor\n{\n    static class MenuService\n    {\n        private const string k_WindowMenuName = \"Window\";\n        private const string k_HelpMenuName = \"Help\";\n\n        // Contains the final ordered menus that can come either from the .mode file or from attributes\n        private static readonly Dictionary<string, MenuItemsTree<MenuItemOrderingNative>> s_MenusFromModeFile = new Dictionary<string, MenuItemsTree<MenuItemOrderingNative>>();\n        // Contains menu from attributes for modes other than default\n        // Used to add menu items from attributes when iterating through the .mode menus\n        private static Dictionary<string, MenuItemsTree<MenuItemScriptCommand>> s_MenuItemsPerMode = null;\n        // Contains menu from attributes for the default mode\n        // The default mode menus are in a separate dictionary for performance reasons, in that case we don't need the costly MenuItemsTree structure because it won't be used when iterating through the .mode menus\n\n\n        class GroupingMenuItemScriptCommand\n        {\n            public GroupingMenuItemScriptCommand(string menuName, MenuItemScriptCommand mi)\n            {\n                menuItem = mi;\n                menuPath = menuName.Substring(0, menuName.LastIndexOf('/') == -1 ? menuName.Length : menuName.LastIndexOf('/'));\n            }\n\n            public MenuItemScriptCommand menuItem;\n\n            public string menuPath;\n        }\n\n        private static Dictionary<string, GroupingMenuItemScriptCommand> s_MenuItemsDefaultMode = null;\n\n        [UsedImplicitly, RequiredByNativeCode]\n        internal static bool UseDefaultModeMenus()\n        {\n            if (currentId == k_DefaultModeId)\n                return true;\n\n            var menus = GetMenusFromModeFile(currentIndex);\n            if (menus == null)\n                return true;\n\n            return false;\n        }\n\n        // Used to filter the C# menu attributes with need in the current mode\n        [UsedImplicitly, RequiredByNativeCode]\n        internal static MenuItemScriptCommand[] GetMenuItemsFromAttributes()\n        {\n            return GetMenuItemsFromAttributesById(currentId);\n        }\n\n        // Find menu item to add\n        [UsedImplicitly, RequiredByNativeCode]\n        internal static MenuItemOrderingNative FindMenuItem(string fullMenuName)\n        {\n            var menus = GetMenusItemsFromModeFile(currentId);\n            if (menus != null)\n                return menus.FindClosestItem(fullMenuName);\n            return null;\n        }\n\n        internal static bool IsShortcutAvailableInMode(string shortcutId)\n        {\n            if (shortcutId.StartsWith(ShortcutManagement.Discovery.k_MainMenuShortcutPrefix))\n            {\n                string menuName = shortcutId.Replace(ShortcutManagement.Discovery.k_MainMenuShortcutPrefix, \"\");\n\n                var menus = GetMenusItemsFromModeFile(currentId);\n                if (menus != null)\n                    return menus.FindItem(menuName) != null;\n                return false;\n            }\n            return true;\n        }\n\n        private static MenuItemsTree<MenuItemOrderingNative> GetModeMenuTree(string modeName)\n        {\n            var mit = new MenuItemsTree<MenuItemOrderingNative>(new MenuItemOrderingNative());\n            mit.onlyLeafHaveValue = false;\n\n            var menuData = GetMenusFromModeFile(GetModeIndexById(modeName));\n            if (menuData == null)\n            {\n                if (modeName == k_DefaultModeId)\n                {\n                    // if there are no menus in the mode file and we are on the default mode, we use the default modes menus directly\n                    foreach (var menuItem in s_MenuItemsDefaultMode.Values)\n                        mit.AddChildSearch(new MenuItemOrderingNative(menuItem.menuItem.name, menuItem.menuItem.name, menuItem.menuItem.priority, menuItem.menuItem.priority, menuItem.menuItem.secondaryPriority));\n                    return mit;\n                }\n                else\n                    menuData = new List<JSONObject>();\n            }\n            s_MenuItemsPerMode.TryGetValue(modeName, out var menuItems);\n            GetModeMenuTreeRecursive(mit, menuData, menuItems);\n\n            return mit;\n        }\n\n        // Get the next menu item to add (in the right order)\n        private static void GetModeMenuTreeRecursive(MenuItemsTree<MenuItemOrderingNative> menuTree, IList menus, MenuItemsTree<MenuItemScriptCommand> menuItemsFromAttributes,\n            HashSet<string> addedMenuItemAttributes = null, string currentPrefix = \"\", string currentOriginalPrefix = \"\", int parentPriority = 0, int priority = 100)\n        {\n            if (menus == null)\n                return;\n            if (addedMenuItemAttributes == null)\n                addedMenuItemAttributes = new HashSet<string>();\n\n            for (int index = 0; index < menus.Count; ++index)\n            {\n                var menuData = menus[index];\n                // separator\n                if (menuData == null)\n                {\n                    priority += 100;\n                    continue;\n                }\n                var menu = menuData as JSONObject;\n                var isInternal = JsonUtils.JsonReadBoolean(menu, k_MenuKeyInternal);\n                if (isInternal && !Unsupported.IsDeveloperMode())\n                    continue;\n\n                var platform = JsonUtils.JsonReadString(menu, k_MenuKeyPlatform);\n                // Check the menu item platform\n                if (!String.IsNullOrEmpty(platform) && !Application.platform.ToString().ToLowerInvariant().StartsWith(platform.ToLowerInvariant()))\n                    continue;\n\n                var menuName = JsonUtils.JsonReadString(menu, k_MenuKeyName);\n                var fullMenuName = currentPrefix + menuName;\n                priority = JsonUtils.JsonReadInt(menu, k_MenuKeyPriority, priority);\n\n                float secondaryPriority = 0;\n                if (menu.Contains(k_MenuKeySecondaryPriority))\n                    secondaryPriority = (float)menu[k_MenuKeySecondaryPriority];\n\n                // if there is an original full name (complete path) then use it, else if there is an original name (path following currentOriginalPrefix) then use that, else get the menu name\n                var originalName = JsonUtils.JsonReadString(menu, k_MenuKeyOriginalFullName, currentOriginalPrefix + JsonUtils.JsonReadString(menu, k_MenuKeyOriginalName, menuName));\n\n                if (menuItemsFromAttributes != null)\n                    InsertMenuFromAttributeIfNecessary(menuTree, addedMenuItemAttributes, menuItemsFromAttributes, menuName, currentPrefix, priority, parentPriority);\n\n                // Check if we are a submenu\n                if (menu.Contains(k_MenuKeyChildren))\n                {\n                    if (menu[k_MenuKeyChildren] is IList children)\n                    {\n                        // we go deeper\n                        menuTree.AddChildSearch(new MenuItemOrderingNative(fullMenuName, originalName, priority, parentPriority, secondaryPriority: secondaryPriority));\n                        GetModeMenuTreeRecursive(menuTree, children, menuItemsFromAttributes, addedMenuItemAttributes, fullMenuName + \"/\", originalName + \"/\", priority);\n                    }\n                    else if (menu[k_MenuKeyChildren] is string wildCard && wildCard == \"*\")\n                    {\n                        var menuToAdd = new MenuItemOrderingNative(fullMenuName, originalName, priority, parentPriority, secondaryPriority: secondaryPriority, addChildren: true);\n                        if (menu.Contains(k_MenuKeyExclude))\n                        {\n                            if (menu[k_MenuKeyExclude] is IList excludedMenus)\n                            {\n                                menuToAdd.childrenToExclude = new string[excludedMenus.Count];\n                                for (int excludedMenusIndex = 0; excludedMenusIndex < excludedMenus.Count; ++excludedMenusIndex)\n                                {\n                                    if (excludedMenus[excludedMenusIndex] is JSONObject excludeMenu)\n                                        menuToAdd.childrenToExclude[excludedMenusIndex] = originalName + \"/\" + JsonUtils.JsonReadString(excludeMenu, k_MenuKeyName);\n                                }\n                            }\n                        }\n                        if (menu.Contains(k_MenuKeyNotExclude))\n                        {\n                            IList notExcludedMenus = menu[k_MenuKeyNotExclude] as IList;\n                            if (notExcludedMenus != null)\n                            {\n                                menuToAdd.childrenToNotExclude = new string[notExcludedMenus.Count];\n                                for (int notExcludedMenusIndex = 0; notExcludedMenusIndex < notExcludedMenus.Count; ++notExcludedMenusIndex)\n                                {\n                                    var notExcludeMenu = notExcludedMenus[notExcludedMenusIndex] as JSONObject;\n                                    if (notExcludeMenu != null)\n                                        menuToAdd.childrenToNotExclude[notExcludedMenusIndex] = originalName + \"/\" + JsonUtils.JsonReadString(notExcludeMenu, k_MenuKeyName);\n                                }\n                            }\n                        }\n                        menuTree.AddChildSearch(menuToAdd);\n                    }\n                }\n                else\n                    menuTree.AddChildSearch(new MenuItemOrderingNative(fullMenuName, originalName, priority, parentPriority, secondaryPriority: secondaryPriority));\n                priority++;\n            }\n            if (menuItemsFromAttributes != null)\n                InsertMenuFromAttributeIfNecessary(menuTree, addedMenuItemAttributes, menuItemsFromAttributes, null, currentPrefix, priority, parentPriority);\n\n            // no more menu at this level\n        }\n\n        private static void InsertMenuFromAttributeIfNecessary(MenuItemsTree<MenuItemOrderingNative> menuTree, HashSet<string> addedMenuItemAttributes, MenuItemsTree<MenuItemScriptCommand> menuItems, string menuName, string currentPrefix, int priority, int parentPriority)\n        {\n            if (currentPrefix == \"\")\n            {\n                bool mustAddNow = false;\n                if (menuName == null)\n                    mustAddNow = true;\n                else\n                {\n                    mustAddNow = menuName == k_WindowMenuName || menuName == k_HelpMenuName;\n                }\n                if (mustAddNow)\n                {\n                    foreach (var menuPerMode in menuItems.menuItemChildrenSorted)\n                    {\n                        if (!addedMenuItemAttributes.Contains(menuPerMode.name)\n                            && (menuName == null    // if there are no menus left we should add every menu item attributes that were not added\n                                || (!menuPerMode.name.StartsWith(k_HelpMenuName + \"/\")      // Creating a help menu from attribute should only happen if there are no menus left since Help is the last\n                                    && !(menuName == k_WindowMenuName && menuPerMode.name.StartsWith(k_WindowMenuName + \"/\")))))    //Creating a window menu from attribute should happen when there are only Help or no menu left, so if the next is Window then we should not add window menu item\n                        {\n                            addedMenuItemAttributes.Add(menuPerMode.name);\n                            menuTree.AddChildSearch(new MenuItemOrderingNative(menuPerMode.name, menuPerMode.name, menuPerMode.priority, menuPerMode.priority, menuPerMode.secondaryPriority));\n                        }\n                    }\n                }\n            }\n            else\n            {\n                // find if there is a mode specific menu to insert at this position\n                var menuItemTree = menuItems.FindTree(currentPrefix.Substring(0, currentPrefix.Length - 1));\n                if (menuItemTree != null)\n                {\n                    foreach (var menuPerMode in menuItemTree.menuItemChildrenSorted)\n                    {\n                        if (!addedMenuItemAttributes.Contains(menuPerMode.name)\n                            && (menuPerMode.priority < priority || menuName == null))\n                        {\n                            addedMenuItemAttributes.Add(menuPerMode.name);\n                            if (menuPerMode.name.Substring(currentPrefix.Length).Contains(\"/\"))\n                                menuTree.AddChildSearch(new MenuItemOrderingNative(menuPerMode.name, menuPerMode.name, menuPerMode.priority, menuPerMode.priority, menuPerMode.secondaryPriority));\n                            else\n                                menuTree.AddChildSearch(new MenuItemOrderingNative(menuPerMode.name, menuPerMode.name, menuPerMode.priority, parentPriority, menuPerMode.secondaryPriority));\n                        }\n                    }\n                }\n            }\n        }\n\n        // Find menus from command id\n        private static void LoadMenuFromCommandId(IList menus, Dictionary<string, MenuItemScriptCommand> menuItems, string prefix = \"\")\n        {\n            if (menus == null || menuItems == null)\n                return;\n\n            foreach (var menuData in menus)\n            {\n                if (menuData != null)\n                {\n                    var menu = menuData as JSONObject;\n                    if (menu == null)\n                        continue;\n                    var isInternal = JsonUtils.JsonReadBoolean(menu, k_MenuKeyInternal);\n                    if (isInternal && !Unsupported.IsDeveloperMode())\n                        continue;\n                    var menuName = JsonUtils.JsonReadString(menu, k_MenuKeyName);\n                    var fullMenuName = prefix + menuName;\n\n                    var platform = JsonUtils.JsonReadString(menu, k_MenuKeyPlatform);\n\n                    // Check the menu item platform\n                    if (!string.IsNullOrEmpty(platform) && !Application.platform.ToString().ToLowerInvariant().StartsWith(platform.ToLowerInvariant()))\n                        continue;\n\n                    // Check if we are a submenu\n                    if (menu.Contains(k_MenuKeyChildren))\n                    {\n                        if (menu[k_MenuKeyChildren] is IList children)\n                            LoadMenuFromCommandId(children, menuItems, fullMenuName + \"/\");\n                    }\n                    else\n                    {\n                        var commandId = JsonUtils.JsonReadString(menu, k_MenuKeyCommandId);\n                        if (!string.IsNullOrEmpty(commandId) && CommandService.Exists(commandId))\n                        {\n                            // Create a new menu item pointing to a command handler\n                            var shortcut = JsonUtils.JsonReadString(menu, k_MenuKeyShortcut);\n                            var @checked = JsonUtils.JsonReadBoolean(menu, k_MenuKeyChecked);\n\n                            var validateCommandId = JsonUtils.JsonReadString(menu, k_MenuKeyValidateCommandId);\n                            var commandMenuItem = MenuItemScriptCommand.InitializeFromCommand(fullMenuName, 100, commandId, validateCommandId);\n                            commandMenuItem.@checked = @checked;\n                            commandMenuItem.shortcut = shortcut;\n                            menuItems[fullMenuName] = commandMenuItem;\n                        }\n                    }\n                }\n            }\n        }\n\n        // Extract in another method for tests\n        private static MenuItemScriptCommand[] GetMenuItemsFromAttributesById(string id)\n        {\n            ExtractMenuItemsFromAttributes();\n            var menus = GetMenusFromModeFile(GetModeIndexById(id));\n\n            if (menus == null) // If there is no mode menus in the mode file\n                return CombineMenuItemsFromAttributes(id, false).Values.ToArray();\n\n            var menuItems = CombineMenuItemsFromAttributes(id, true);\n            LoadMenuFromCommandId(menus, menuItems);\n\n            return menuItems.Values.ToArray(); //In that case there is a .mode so menus will be filtered by the iterator\n        }\n\n        private static MenuItemsTree<MenuItemOrderingNative> GetMenusItemsFromModeFile(string modeName)\n        {\n            if (s_MenusFromModeFile.TryGetValue(modeName, out var menus))\n                return menus;\n\n            if (s_MenuItemsPerMode == null)\n                ExtractMenuItemsFromAttributes();\n\n            var mit = GetModeMenuTree(modeName);\n            s_MenusFromModeFile.Add(modeName, mit);\n            return mit;\n        }\n\n        private static IList GetMenusFromModeFile(int index)\n        {\n            object items = GetModeDataSection(index, ModeDescriptor.MenusKey);\n            if (items == null || (items is string wildCard && wildCard == \"*\"))\n                return null;\n\n            return items as IList;\n        }\n\n        private static void SortMenuItems(ref Dictionary<string, GroupingMenuItemScriptCommand> menuItemsPerMode)\n        {\n            menuItemsPerMode = menuItemsPerMode\n                .OrderBy(m => m.Value.menuItem.Priority)\n                .ThenBy(m => m.Value.menuItem.SecondaryPriority)\n                .ThenBy(m => m.Value.menuItem.Name)\n                .ToDictionary(x => x.Key, x => x.Value);\n        }\n\n        private static void ExtractMenuItemsFromAttributes()\n        {\n            s_MenuItemsPerMode = new Dictionary<string, MenuItemsTree<MenuItemScriptCommand>>();\n            s_MenuItemsDefaultMode = new Dictionary<string, GroupingMenuItemScriptCommand>();\n\n            var methodInfos = TypeCache.GetMethodsWithAttribute<MenuItem>()\n                .Where(m => ValidateMethodForMenuCommand(m))\n                // Order the menu items to start with Unity menus before projects menus. That way if there is a duplicate, the project one is flagged as duplicate\n                .OrderBy(m => !Utility.FastStartsWith(m.DeclaringType.Assembly.FullName, \"UnityEditor\", \"unityeditor\"))\n                .ToList();\n\n            foreach (var methodInfo in methodInfos)\n            {\n                foreach (var attribute in (MenuItem[])methodInfo.GetCustomAttributes(typeof(MenuItem), false))\n                {\n                    string menuName = SanitizeMenuItemName(attribute.menuItem);\n                    string[] editorModes = attribute.editorModes;\n                    foreach (var editorMode in editorModes)\n                    {\n                        if (editorMode == k_DefaultModeId)\n                        {\n                            if (s_MenuItemsDefaultMode.TryGetValue(menuName, out var menuItem))\n                                menuItem.menuItem.Update(attribute, methodInfo);\n                            else\n                                s_MenuItemsDefaultMode.Add(menuName, new GroupingMenuItemScriptCommand(menuName, MenuItemScriptCommand.Initialize(menuName, attribute, methodInfo)));\n                        }\n                        else\n                        {\n                            if (s_MenuItemsPerMode.TryGetValue(editorMode, out var menuItemsPerMode))\n                            {\n                                MenuItemScriptCommand menuItem = menuItemsPerMode.FindItem(menuName);\n                                if (menuItem == null)\n                                    menuItemsPerMode.AddChildSearch(MenuItemScriptCommand.Initialize(menuName, attribute, methodInfo));\n                                else\n                                    menuItem.Update(attribute, methodInfo);\n                            }\n                            else\n                            {\n                                var newMenusPerMode = new MenuItemsTree<MenuItemScriptCommand>();\n                                newMenusPerMode.AddChildSearch(MenuItemScriptCommand.Initialize(menuName, attribute, methodInfo));\n                                s_MenuItemsPerMode.Add(editorMode, newMenusPerMode);\n                            }\n                        }\n                    }\n                }\n            }\n\n            CleanUpInvalidMenuItems(ref s_MenuItemsPerMode, ref s_MenuItemsDefaultMode);\n\n            SortMenuItems(ref s_MenuItemsDefaultMode);\n        }\n\n        private static void CleanUpInvalidMenuItems(ref Dictionary<string, MenuItemsTree<MenuItemScriptCommand>> menuItemsPerMode, ref Dictionary<string, GroupingMenuItemScriptCommand> genericMenuItems)\n        {\n            foreach (var menuItemPerMode in menuItemsPerMode.Values)\n            {\n                menuItemPerMode.CleanUp();\n            }\n            // Default mode items\n            var itemsToDelete = new List<string>();\n            foreach (var menu in genericMenuItems)\n            {\n                if (menu.Value.menuItem.IsNotValid)\n                    itemsToDelete.Add(menu.Key);\n            }\n            foreach (var itemToDelete in itemsToDelete)\n            {\n                genericMenuItems.Remove(itemToDelete);\n            }\n        }\n\n        private static Dictionary<string, MenuItemScriptCommand> CombineMenuItemsFromAttributes(string id, bool menusDependOnModeFile)\n        {\n            // Create the initial menu items collection for the mode id\n            var menuItemsResult = new Dictionary<string, MenuItemScriptCommand>();\n            // We add the menus from the mode id\n            if (id != k_DefaultModeId && s_MenuItemsPerMode.ContainsKey(id))\n            {\n                foreach (var menuItem in s_MenuItemsPerMode[id].menuItemChildren)\n                    menuItemsResult.Add(menuItem.name, menuItem);\n            }\n            // Always adding the default menu, which may be filtered later when using a custom mode file\n            AddMenuItemsFromMode(menuItemsResult, s_MenuItemsDefaultMode.Values.Select(x => x.menuItem));\n\n            // If the menus depend on the .mode file, we also add the other modes menus because the mode file can reference them\n            if (menusDependOnModeFile)\n            {\n                foreach (var menuItemPerMode in s_MenuItemsPerMode)\n                {\n                    if (menuItemPerMode.Key != id)\n                    {\n                        AddMenuItemsFromMode(menuItemsResult, menuItemPerMode.Value.menuItemChildren);\n                    }\n                }\n            }\n            return menuItemsResult;\n        }\n\n        private static void AddMenuItemsFromMode(Dictionary<string, MenuItemScriptCommand> menuItemsResult, IEnumerable<MenuItemScriptCommand> menuItems)\n        {\n            foreach (var menuItem in menuItems)\n            {\n                if (!menuItemsResult.ContainsKey(menuItem.name)) // there can be multiple methods that have the same attribute name for different modes, we don't add it in that case\n                {\n                    menuItemsResult.Add(menuItem.name, menuItem);\n                }\n            }\n        }\n\n        internal static string SanitizeMenuItemName(string menuName)\n        {\n            while (menuName.StartsWith(\"/\"))\n            {\n                menuName = menuName.Substring(1);\n            }\n            // replace double // separators with /\n            menuName = System.Text.RegularExpressions.Regex.Replace(menuName, \"//\", \"/\");\n            // removing trailing \"/\" is already done when building the tree because we're removing empty entries when splitting the menu name with /\n            return menuName;\n        }\n\n        private static bool ValidateMethodForMenuCommand(MethodInfo methodInfo)\n        {\n            if (methodInfo.DeclaringType.IsGenericType)\n            {\n                Debug.LogWarningFormat(\"Method {0}.{1} cannot be used for menu commands because class {0} is an open generic type.\", methodInfo.DeclaringType, methodInfo.Name);\n                return false;\n            }\n            // Skip non-static methods for regular menus\n            if (!methodInfo.IsStatic)\n            {\n                Debug.LogWarningFormat(\"Method {0}.{1} is not static and cannot be used for menu commands.\", methodInfo.DeclaringType, methodInfo.Name);\n                return false;\n            }\n            // Skip generic methods\n            if (methodInfo.IsGenericMethod)\n            {\n                Debug.LogWarningFormat(\"Method {0}.{1} is generic and cannot be used for menu commands.\", methodInfo.DeclaringType, methodInfo.Name);\n                return false;\n            }\n            // Skip invalid methods\n            ParameterInfo[] parameters = methodInfo.GetParameters();\n            if (parameters.Length > 1)\n            {\n                Debug.LogWarningFormat(\"Method {0}.{1} has invalid parameters. MenuCommand is the only optional supported parameter.\", methodInfo.DeclaringType, methodInfo.Name);\n                return false;\n            }\n            if (parameters.Length == 1)\n            {\n                if (parameters[0].ParameterType != typeof(MenuCommand))\n                {\n                    Debug.LogWarningFormat(\"Method {0}.{1} has invalid parameters. MenuCommand is the only optional supported parameter.\", methodInfo.DeclaringType, methodInfo.Name);\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        internal class MenuItemsTree<T>\n            where T : class, IMenuItem\n        {\n            private readonly string key;\n            private T value;\n            private readonly int m_Priority;\n            private readonly float m_SecondaryPriority;\n\n            private readonly List<MenuItemsTree<T>> m_Children;\n            public List<T> menuItemChildren => GetChildrenRecursively();\n            // This list is only sorted by name and priority recursively, it doesn't handle possible rename. So it might not seem ordered for a MenuItemsTree<MenuItemOrderingNative> of renamed items\n            // WARNING: that property is called until each menu item from attributes are added when building the item of s_MenusFromModeFile in GetModeMenuTree. That means the whole tree for each menu item, so it can get quite slow if there are a lot of menu items with a mode specified in the attribute\n            public List<T> menuItemChildrenSorted => GetChildrenRecursively(true);\n\n            public bool onlyLeafHaveValue { get; set; } = true;\n\n            private List<T> GetChildrenRecursively(bool sorted = false, List<T> result = null)\n            {\n                if (result == null)\n                    result = new List<T>();\n                if (m_Children.Any())\n                {\n                    var children = m_Children;\n                    if (sorted)\n                    {\n                        children = m_Children.OrderBy(c => c.m_Priority)\n                            .ThenBy(c => c.m_SecondaryPriority)\n                            .ThenBy(c => c.key)\n                            .ToList();\n                    }\n                    foreach (var child in children)\n                        child.GetChildrenRecursively(sorted, result);\n                }\n                else if (value != null)\n                    result.Add(value);\n                return result;\n            }\n\n            public MenuItemsTree(string key = \"\", int priority = 100, float secondaryPriority = 0)\n            {\n                this.key = EditorUtility.ParseMenuName(key);\n                m_Priority = priority;\n                m_SecondaryPriority = secondaryPriority == 0 ? float.MaxValue : secondaryPriority;\n                m_Children = new List<MenuItemsTree<T>>();\n            }\n\n            public MenuItemsTree(T value) : this(value.Name, value.Priority, value.SecondaryPriority)\n            {\n                this.value = value;\n            }\n\n            // In case of renaming it's risky to use this method because the key is the original name (to be able to find it on MenuController::AddMenuItem) but the tree we might want to add this item to can have a totally different name\n            private MenuItemsTree<T> AddChildDirectly(T menuItem)\n            {\n                var child = new MenuItemsTree<T>(menuItem);\n                m_Children.Add(child);\n                return child;\n            }\n\n            private MenuItemsTree<T> AddIntermediateMenuItem(string pathPart, int priority, float secondaryPriority)\n            {\n                string name = string.IsNullOrEmpty(key) ? pathPart : key + \"/\" + pathPart;\n\n\n                var child = new MenuItemsTree<T>(name, priority, secondaryPriority);\n                m_Children.Add(child);\n                return child;\n            }\n\n            public bool AddChildSearch(T menuItem)\n            {\n                if (key == menuItem.Name)\n                {\n                    if (onlyLeafHaveValue)\n                        Debug.LogWarning($\"MenuItem {key} was added twice\");\n                    else if (value == null)\n                        value = menuItem;\n                    return true;\n                }\n                if (IsParentMenu(menuItem.Name))\n                {\n                    foreach (var child in m_Children)\n                    {\n                        if (child.AddChildSearch(menuItem))\n                            return true;\n                    }\n                    // create hierarchy from name and /\n                    string rightSide = menuItem.Name.Substring(key.Length);\n                    string[] pathSplit = rightSide.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);\n                    // create intermediate menus first\n                    var currentMenu = this;\n                    for (int i = 0; i < pathSplit.Length - 1; ++i)\n                    {\n                        currentMenu = currentMenu.AddIntermediateMenuItem(pathSplit[i], menuItem.Priority, menuItem.SecondaryPriority);\n                    }\n                    // then add the menuItem\n                    currentMenu.AddChildDirectly(menuItem);\n                    return true;\n                }\n                return false;\n            }\n\n            public bool Contains(string key)\n            {\n                return FindTree(key) != null;\n            }\n\n            public T FindItem(string key)\n            {\n                return FindTree(key)?.value;\n            }\n\n            public T FindClosestItem(string key)\n            {\n                return FindTreePrivate(key, true)?.value;\n            }\n\n            public MenuItemsTree<T> FindTree(string key)\n            {\n                return FindTreePrivate(key);\n            }\n\n            private MenuItemsTree<T> FindTreePrivate(string key, bool findClosest = false)\n            {\n                return Find(EditorUtility.ParseMenuName(key), findClosest);\n            }\n\n            private MenuItemsTree<T> Find(string key, bool findClosest = false)\n            {\n                if (this.key == key)\n                    return this;\n                if (IsParentMenu(key))\n                {\n                    foreach (var menuItem in m_Children)\n                    {\n                        var foundItem = menuItem.Find(key, findClosest);\n                        if (foundItem != null)\n                            return foundItem;\n                    }\n                    if (findClosest)\n                        return this;\n                }\n                return null;\n            }\n\n            private bool IsParentMenu(string menuName)\n            {\n                return key.Length == 0 || (key.Length < menuName.Length && menuName.StartsWith(key) && menuName.Substring(key.Length).StartsWith(\"/\"));\n            }\n\n            internal void CleanUp()\n            {\n                for (int i = 0; i < m_Children.Count;)\n                {\n                    if (m_Children[i].m_Children.Count > 0 || (m_Children[i].m_Children.Count == 0 && m_Children[i].value == null)) // CleanUp intermediate menu\n                    {\n                        m_Children[i].CleanUp();\n                        if (m_Children[i].m_Children.Count == 0) // If clean up removed every children of that child we need to remove that child\n                        {\n                            m_Children.RemoveAt(i);\n                            continue;\n                        }\n                    }\n                    else\n                    {\n                        MenuItemScriptCommand menuItem = m_Children[i].value as MenuItemScriptCommand;\n                        if (menuItem != null && menuItem.IsNotValid)\n                        {\n                            m_Children.RemoveAt(i);\n                            continue;\n                        }\n                    }\n                    ++i;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorMode/ModeService.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n//#define DEBUG_MODE_SERVICE\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing JetBrains.Annotations;\nusing UnityEditor.MPE;\nusing UnityEditor.AssetImporters;\nusing UnityEngine;\nusing UnityEngine.Internal;\nusing UnityEngine.UIElements;\nusing UnityEditor.ShortcutManagement;\n\nusing JSONObject = System.Collections.IDictionary;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    internal enum ModeAction\n    {\n    }\n\n    internal enum ModeCapability\n    {\n        Layers,\n        Layouts,\n        LayoutSwitching,\n        LayoutWindowMenu,\n        HostViewGenericMenu,\n        Playbar,\n        GameViewToolbar,\n        StatusBarExtraFeatures,\n        SafeMode,\n        Remember,\n        AllowAssetCreation,\n        StaticTabs,\n        SearchPopupButton\n    }\n\n    [Serializable]\n    internal class ModeDescriptor : ScriptableObject\n    {\n        public const string LabelKey = \"label\";\n        public const string MenusKey = \"menus\";\n        public const string LayoutKey = \"layout\";\n        public const string LayoutsKey = \"layouts\";\n        public const string ShortcutsKey = \"shortcuts\";\n        public const string CapabilitiesKey = \"capabilities\";\n        public const string ExecuteHandlersKey = \"execute_handlers\";\n\n        [SerializeField] public string path;\n    }\n\n    [UsedImplicitly, ExcludeFromPreset, ScriptedImporter(version: 1, ext: \"mode\")]\n    class ModeDescriptorImporter : ScriptedImporter\n    {\n        internal static bool allowExplicitModeRefresh { get; set; }\n        public override void OnImportAsset(AssetImportContext ctx)\n        {\n            var modeDescriptor = ScriptableObject.CreateInstance<ModeDescriptor>();\n            modeDescriptor.path = ctx.assetPath;\n            modeDescriptor.hideFlags = HideFlags.NotEditable;\n            ctx.AddObjectToAsset(\"mode\", modeDescriptor);\n            ctx.SetMainObject(modeDescriptor);\n\n            if (!allowExplicitModeRefresh)\n                return;\n\n            EditorApplication.update -= DelayLoadMode;\n            EditorApplication.update += DelayLoadMode;\n        }\n\n        public static void DelayLoadMode()\n        {\n            EditorApplication.update -= DelayLoadMode;\n            ModeService.Refresh(null);\n        }\n    }\n\n    [ExcludeFromDocs]\n    public static class ModeService\n    {\n        private struct ModeEntry\n        {\n            public string id;\n            public string name;\n            public JSONObject data;\n        }\n\n        public struct ModeChangedArgs\n        {\n            public int prevIndex;\n            public int nextIndex;\n        }\n\n        internal const string k_ModePathsCache = \"mode-paths-cache\";\n        internal const string k_DefaultModeId = \"default\";\n        internal const string k_ModeCurrentIdKeyName = \"mode-current-id\";\n        internal const string k_MenuKeyChecked = \"checked\";\n        internal const string k_MenuKeyChildren = \"children\";\n        internal const string k_MenuKeyCommandId = \"command_id\";\n        internal const string k_MenuKeyExclude = \"exclude\";\n        internal const string k_MenuKeyInternal = \"internal\";\n        internal const string k_MenuKeyItemId = \"menu_item_id\";\n        internal const string k_MenuKeyName = \"name\";\n        internal const string k_MenuKeyNotExclude = \"include\";\n        internal const string k_MenuKeyOriginalFullName = \"original_full_name\";\n        internal const string k_MenuKeyOriginalName = \"original_name\";\n        internal const string k_MenuKeyPlatform = \"platform\";\n        internal const string k_MenuKeyPriority = \"priority\";\n        internal const string k_MenuKeySecondaryPriority = \"secondary_priority\";\n        internal const string k_MenuKeyShortcut = \"shortcut\";\n        internal const string k_MenuKeyValidateCommandId = \"validate_command_id\";\n\n        public static string[] modeNames => modes.Select(m => m.name).ToArray();\n        public static int modeCount => modes.Length;\n\n        public static string currentId => currentIndex == -1 || modes.Length == 0 ? k_DefaultModeId : modes[currentIndex].id;\n        public static int currentIndex { get; private set; }\n        private static ModeEntry[] modes { get; set; } = new ModeEntry[0];\n        internal static bool hasSwitchableModes { get; private set; }\n        private static bool initialModeChanged\n        {\n            get => SessionState.GetBool(nameof(initialModeChanged), false);\n            set => SessionState.SetBool(nameof(initialModeChanged), value);\n        }\n\n        public static event Action<ModeChangedArgs> modeChanged;\n\n        static ModeService()\n        {\n            Log(\"Initialize\");\n\n            LoadModes();\n\n            modeChanged += OnModeChangeMenus;\n            modeChanged += OnModeChangeLayouts;\n            UnityEditor.PackageManager.Events.registeredPackages += OnRegisteredPackages;\n\n            ModeDescriptorImporter.allowExplicitModeRefresh = true;\n        }\n\n        private static bool IsMainWindowLoaded()\n        {\n            return WindowLayout.FindMainWindow();\n        }\n\n        internal static int GetModeIndexById(string modeId)\n        {\n            string lcModeId = modeId.ToLowerInvariant();\n            int modeIndex = Array.FindIndex(modes, m => m.id == lcModeId);\n            return modeIndex;\n        }\n\n        [RequiredByNativeCode]\n        public static void ChangeModeById(string modeId)\n        {\n            int modeIndex = GetModeIndexById(modeId);\n            if (modeIndex != -1)\n                ChangeModeByIndex(modeIndex);\n        }\n\n        public static void Update()\n        {\n            Log(\"Update\");\n            EditorApplication.RequestRepaintAllViews();\n        }\n\n        internal static void ChangeModeByIndex(int modeIndex)\n        {\n            if (currentIndex == modeIndex)\n                return;\n\n            Log($\"ChangeMode({GetModeId(modeIndex)})\");\n\n            var prevIndex = currentIndex;\n            SetModeIndex(modeIndex);\n            if (prevIndex != currentIndex)\n            {\n                try\n                {\n                    modeChanged += OnModeChangeUpdate;\n                    RaiseModeChanged(prevIndex, currentIndex);\n                }\n                catch (Exception ex)\n                {\n                    SetModeIndex(prevIndex);\n                    Debug.LogError($\"Failed to change editor mode.\\r\\n{ex}\");\n                }\n                finally\n                {\n                    modeChanged -= OnModeChangeUpdate;\n                }\n            }\n        }\n\n        internal static bool HasCapability(ModeCapability capability, bool defaultValue = false)\n        {\n            return HasCapability(currentIndex, capability, defaultValue);\n        }\n\n        internal static bool HasCapability(string capabilityName, bool defaultValue = false)\n        {\n            return HasCapability(currentIndex, capabilityName, defaultValue);\n        }\n\n        internal static bool HasCapability(int modeIndex, ModeCapability capability, bool defaultValue = false)\n        {\n            return HasCapability(modeIndex, capability.ToString().ToSnakeCase(), defaultValue);\n        }\n\n        internal static bool HasCapability(int modeIndex, string capabilityName, bool defaultValue = false)\n        {\n            var lcCapabilityName = capabilityName.ToLower();\n            var capabilities = GetModeDataSection(modeIndex, ModeDescriptor.CapabilitiesKey) as JSONObject;\n            if (capabilities == null)\n                return defaultValue;\n\n            if (!capabilities.Contains(lcCapabilityName) || capabilities[lcCapabilityName].GetType() != typeof(bool))\n                return defaultValue;\n\n            return (bool)capabilities[lcCapabilityName];\n        }\n\n        internal static bool Execute(ModeAction builtinAction, params object[] args)\n        {\n            return Execute(builtinAction.ToString(), args);\n        }\n\n        internal static bool Execute(ModeAction builtinAction, CommandHint hint, params object[] args)\n        {\n            return Execute(builtinAction.ToString(), hint, args);\n        }\n\n        internal static bool Execute(string actionName, params object[] args)\n        {\n            return Execute(actionName, CommandHint.Undefined, args);\n        }\n\n        internal static bool Execute(string actionName, CommandHint hint, params object[] args)\n        {\n            // Call some command/shortcut actions to execute the current action\n            actionName = actionName.ToLower();\n            var executeHandlers = GetModeDataSection(currentIndex, ModeDescriptor.ExecuteHandlersKey) as JSONObject;\n            if (!HasExecuteHandler(actionName, executeHandlers))\n                return false;\n\n            var result = CommandService.Execute((string)executeHandlers[actionName], hint, args);\n            return result == null || (bool)result;\n        }\n\n        internal static bool HasExecuteHandler(string actionName)\n        {\n            actionName = actionName.ToLower();\n            var executeHandlers = GetModeDataSection(currentIndex, ModeDescriptor.ExecuteHandlersKey) as JSONObject;\n            return HasExecuteHandler(actionName, executeHandlers);\n        }\n\n        static bool HasExecuteHandler(string loweredActionName, JSONObject executeHandlers)\n        {\n            if (executeHandlers == null)\n                return false;\n\n            if (!executeHandlers.Contains(loweredActionName))\n                return false;\n\n            string commandId = (string)executeHandlers[loweredActionName];\n            if (!CommandService.Exists(commandId))\n                return false;\n\n            return true;\n        }\n\n        internal static bool HasSection(int modeIndex, string sectionName)\n        {\n            if (!IsValidIndex(modeIndex))\n                return false;\n            return modes[modeIndex].data.Contains(sectionName);\n        }\n\n        internal static object GetModeDataSection(string sectionName)\n        {\n            return GetModeDataSection(currentIndex, sectionName);\n        }\n\n        internal static object GetModeDataSection(int modeIndex, string sectionName)\n        {\n            if (!IsValidIndex(modeIndex))\n                return null;\n\n            if (!modes[modeIndex].data.Contains(sectionName))\n                return null;\n\n            return modes[modeIndex].data[sectionName];\n        }\n\n        internal static IEnumerable<T> GetModeDataSectionList<T>(int modeIndex, string sectionName)\n        {\n            var list = GetModeDataSection(modeIndex, sectionName) as IList<object>;\n            if (list == null)\n                return null;\n            return list.Cast<T>();\n        }\n\n        [CommandHandler(\"ModeService/Refresh\")]\n        internal static void Refresh(CommandExecuteContext c)\n        {\n            LoadModes();\n        }\n\n        internal static void RaiseModeChanged(int prevIndex, int nextIndex)\n        {\n            Log($\"RaiseModeChanged({GetModeId(prevIndex) ?? k_DefaultModeId}, {GetModeId(nextIndex)})\");\n\n            modeChanged?.Invoke(new ModeChangedArgs { prevIndex = prevIndex, nextIndex = nextIndex });\n\n            initialModeChanged = true;\n        }\n\n        internal static bool IsValidModeId(string id)\n        {\n            return !string.IsNullOrEmpty(id) && id.All(c => char.IsLetterOrDigit(c) || c == '_' || c == '-' || c == '.');\n        }\n\n        internal static string GetDefaultModeLayout(string modeId = null)\n        {\n            var layouts = GetModeDataSection(currentIndex, ModeDescriptor.LayoutsKey) as IList<object>;\n            if (layouts != null && layouts.Count > 0)\n            {\n                var layoutPath = layouts[0] as string;\n                if (layoutPath != null)\n                {\n                    if (File.Exists(layoutPath))\n                    {\n                        return layoutPath;\n                    }\n                    else\n                    {\n                        Debug.LogWarning(\"Default Mode Layout: \" + layoutPath + \" doesn't exists.\");\n                    }\n                }\n            }\n            return null;\n        }\n\n        internal static bool HasStartupMode()\n        {\n            return Application.HasARGV(\"editor-mode\");\n        }\n\n        private static void OnRegisteredPackages(PackageManager.PackageRegistrationEventArgs evt)\n        {\n            SessionState.EraseString(k_ModePathsCache);\n            LoadModes();\n        }\n\n        private static void LoadModes()\n        {\n            Log(\"LoadModes\");\n\n            ScanModes();\n            \n            var currentModeIndex = GetSessionModeIndex();\n            if (currentModeIndex == -1)\n            {\n                currentModeIndex = LoadProjectPrefModeIndex();\n            }\n\n            if (!initialModeChanged && HasStartupMode())\n            {\n                var requestEditorMode = Application.GetValueForARGV(\"editor-mode\");\n                var modeIndex = GetModeIndexById(requestEditorMode);\n                if (modeIndex != -1)\n                {\n                    currentModeIndex = modeIndex;\n                    Console.WriteLine($\"[MODES] Loading editor mode {modeNames[currentModeIndex]} ({currentModeIndex}) from command line.\");\n                }\n            }\n\n            SetModeIndex(currentModeIndex);\n        }\n\n        private static void SaveSessionMode()\n        {\n            if (!HasCapability(ModeCapability.Remember, true))\n                return;\n            SessionState.SetString(k_ModeCurrentIdKeyName, currentId);\n        }\n\n        private static int GetSessionModeIndex()\n        {\n            var currentModeId = SessionState.GetString(k_ModeCurrentIdKeyName, \"\");\n            return GetModeIndexById(currentModeId);\n        }\n\n        internal static void InitializeCurrentMode()\n        {\n            if (initialModeChanged)\n                return;\n            Log(\"InitializeCurrentMode\");\n            RaiseModeChanged(-1, currentIndex);\n        }\n\n        private static void FillModeData(string path, Dictionary<string, object> modesData)\n        {\n            try\n            {\n                var json = SJSON.Load(path);\n                foreach (var rawModeId in json.Keys)\n                {\n                    var modeId = ((string)rawModeId).ToLower();\n                    if (IsValidModeId(modeId))\n                    {\n                        object modeData = null;\n                        if (modesData.TryGetValue(modeId, out modeData))\n                            modesData[modeId] = JsonUtils.DeepMerge(modeData as JSONObject, json[modeId] as JSONObject);\n                        else\n                            modesData[modeId] = json[modeId];\n                    }\n                    else\n                    {\n                        Debug.LogWarning($\"Invalid Mode Id: {modeId} contains non alphanumeric characters.\");\n                    }\n                }\n            }\n            catch (Exception ex)\n            {\n                Debug.LogError($\"[ModeService] Error while parsing mode file {path}.\\n{ex}\");\n            }\n        }\n\n        internal static void ScanModes()\n        {\n            var modesData = new Dictionary<string, object>\n            {\n                [k_DefaultModeId] = new Dictionary<string, object>\n                {\n                    [ModeDescriptor.LabelKey] = \"Default\"\n                }\n            };\n\n            var builtinModeFile = Path.Combine(EditorApplication.applicationContentsPath, \"Resources/default.mode\");\n            FillModeData(builtinModeFile, modesData);\n\n            var modeFilePathCache = SessionState.GetString(k_ModePathsCache, \"\");\n\n            if (modeFilePathCache == \"\")\n            {\n                var modeDescriptors = AssetDatabase.EnumerateAllAssets(new SearchFilter\n                {\n                    searchArea = SearchFilter.SearchArea.InPackagesOnly,\n                    classNames = new[] { nameof(ModeDescriptor) },\n                    showAllHits = true\n                });\n\n                while (modeDescriptors.MoveNext())\n                {\n                    var md = modeDescriptors.Current.pptrValue as ModeDescriptor;\n                    if (md == null)\n                        continue;\n                    FillModeData(md.path, modesData);\n                    modeFilePathCache += md.path + \";\";\n                }\n                SessionState.SetString(k_ModePathsCache, modeFilePathCache);\n            }\n            else\n            {\n                var paths = modeFilePathCache.Split(\";\");\n                foreach(var path in paths)\n                {\n                    if (!File.Exists(path))\n                        continue;\n                    FillModeData(path, modesData);\n                }\n            }\n\n            modes = new ModeEntry[modesData.Keys.Count];\n            modes[0] = CreateEntry(k_DefaultModeId, (JSONObject)modesData[k_DefaultModeId]);\n            var modeIndex = 1;\n            hasSwitchableModes = false;\n            foreach (var modeId in modesData.Keys)\n            {\n                if (modeId == k_DefaultModeId)\n                    continue;\n                var modeFields = (JSONObject)modesData[modeId];\n                modes[modeIndex] = CreateEntry(modeId, modeFields);\n                hasSwitchableModes |= !JsonUtils.JsonReadBoolean(modeFields, \"builtin\");\n                modeIndex++;\n            }\n\n            Array.Sort(modes, (m1, m2) =>\n            {\n                if (m1.id == \"default\")\n                    return -1;\n                if (m2.id == \"default\")\n                    return 1;\n                return m1.id.CompareTo(m2.id);\n            });\n        }\n\n        private static ModeEntry CreateEntry(string modeId, JSONObject data)\n        {\n            return new ModeEntry\n            {\n                id = modeId.ToLowerInvariant(),\n                name = JsonUtils.JsonReadString(data, ModeDescriptor.LabelKey, modeId),\n                data = data\n            };\n        }\n\n        private static void SetModeIndex(int modeIndex)\n        {\n            currentIndex = Math.Max(0, Math.Min(modeIndex, modeCount - 1));\n\n            var capabilities = GetModeDataSection(currentIndex, ModeDescriptor.CapabilitiesKey) as IDictionary;\n            if (capabilities != null)\n            {\n                foreach (var cap in capabilities.Keys)\n                {\n                    var capName = Convert.ToString(cap);\n                    if (String.IsNullOrEmpty(capName))\n                        continue;\n                    var state = capabilities[capName];\n                    if (state is Boolean)\n                        SessionState.SetBool(capName, (Boolean)state);\n                }\n            }\n\n            SaveSessionMode();\n        }\n\n        private static int LoadProjectPrefModeIndex()\n        {\n            var modePreyKeyName = GetProjectPrefKeyName(k_ModeCurrentIdKeyName);\n            var loadModeId = EditorPrefs.GetString(modePreyKeyName, \"default\");\n            var loadModeIndex = GetModeIndexById(loadModeId);\n            if (loadModeIndex == -1)\n                return 0; // Fallback to default mode index\n            Console.WriteLine($\"[MODES] Loading mode {modeNames[loadModeIndex]} ({loadModeIndex}) for {modePreyKeyName}\");\n            return loadModeIndex;\n        }\n\n        private static void SaveProjectPrefModeIndex(int modeIndex)\n        {\n            if (!HasCapability(ModeCapability.Remember, true))\n                return;\n            var modePreyKeyName = GetProjectPrefKeyName(k_ModeCurrentIdKeyName);\n            Console.WriteLine($\"[MODES] Saving user mode to {modeNames[modeIndex]} ({modeIndex}) for {modePreyKeyName}\");\n            EditorPrefs.SetString(modePreyKeyName, modes[modeIndex].id);\n        }\n\n        private static string GetProjectPrefKeyName(string prefix)\n        {\n            var key = $\"{prefix}-{Application.productName}\";\n            if (!string.IsNullOrEmpty(ProcessService.roleName))\n            {\n                key += \"-\" + ProcessService.roleName;\n            }\n            return key;\n        }\n\n        public static bool HasContextMenu(string menuId)\n        {\n            return GetContextMenu(menuId) != null;\n        }\n\n        public static void PopupContextMenu(string menuId)\n        {\n            var menuDescriptor = GetContextMenu(menuId);\n            if (menuDescriptor == null)\n                return;\n\n            GenericMenu menu = new GenericMenu();\n            BuildContextMenu(menuDescriptor, menuId, menu);\n            menu.ShowAsContext();\n        }\n\n        static private IList GetContextMenu(string menuId)\n        {\n            var section = GetModeDataSection(\"context_menus\");\n            var contextMenus = section as Dictionary<string, object>;\n            if (contextMenus == null)\n                return null;\n\n            if (menuId.EndsWith(\"/\"))\n                menuId = menuId.Remove(menuId.Length - 1);\n            if (!contextMenus.ContainsKey(menuId))\n                return null;\n            return contextMenus[menuId] as IList;\n        }\n\n        internal static bool HasDynamicLayout(int modeIndex = -1)\n        {\n            var layoutData = GetModeDataSection(modeIndex == -1 ? currentIndex : modeIndex, ModeDescriptor.LayoutKey) as JSONObject;\n            return layoutData != null;\n        }\n\n        internal static JSONObject GetDynamicLayout(int modeIndex = -1)\n        {\n            return GetModeDataSection(modeIndex == -1 ? currentIndex : modeIndex, ModeDescriptor.LayoutKey) as JSONObject;\n        }\n\n        private static void BuildContextMenu(IList menus, string menuId, GenericMenu contextMenu, string prefix = \"\")\n        {\n            if (menus == null)\n                return;\n\n            foreach (var menuData in menus)\n            {\n                if (menuData != null)\n                {\n                    var menu = menuData as JSONObject;\n                    if (menu == null)\n                        continue;\n                    var isInternal = JsonUtils.JsonReadBoolean(menu, k_MenuKeyInternal);\n                    if (isInternal && !Unsupported.IsDeveloperMode())\n                        continue;\n                    var menuName = JsonUtils.JsonReadString(menu, k_MenuKeyName);\n                    var fullMenuName = prefix + menuName;\n                    var menuItemId = menuId + fullMenuName;\n                    var platform = JsonUtils.JsonReadString(menu, k_MenuKeyPlatform);\n\n                    // Check the menu item platform\n                    if (!string.IsNullOrEmpty(platform) && !Application.platform.ToString().ToLowerInvariant().StartsWith(platform.ToLowerInvariant()))\n                        continue;\n\n                    // Check if we are a submenu\n                    if (menu.Contains(k_MenuKeyChildren))\n                    {\n                        if (menu[k_MenuKeyChildren] is IList childrenItems)\n                            BuildContextMenu(childrenItems, menuId, contextMenu, fullMenuName + \"/\");\n                        else if (menu[k_MenuKeyChildren] is string msw && msw == \"*\")\n                        {\n                            var whitelistedItems = Menu.ExtractSubmenus(menuItemId);\n                            foreach (var wi in whitelistedItems)\n                            {\n                                var @checked = Menu.GetChecked(wi);\n                                if (!Menu.GetEnabled(wi))\n                                    contextMenu.AddDisabledItem(new GUIContent(wi.Replace(menuId, \"\")), @checked);\n                                else\n                                    contextMenu.AddItem(new GUIContent(wi.Replace(menuId, \"\")), @checked, () => EditorApplication.ExecuteMenuItem(wi));\n                            }\n                        }\n                    }\n                    else\n                    {\n                        var commandId = JsonUtils.JsonReadString(menu, k_MenuKeyCommandId);\n                        if (string.IsNullOrEmpty(commandId))\n                        {\n                            // We are re-using a default menu item\n                            menuItemId = JsonUtils.JsonReadString(menu, k_MenuKeyItemId, menuItemId);\n                            if (EditorApplication.ValidateMenuItem(menuItemId))\n                                contextMenu.AddItem(new GUIContent(fullMenuName), false, () => EditorApplication.ExecuteMenuItem(menuItemId));\n                            else\n                                contextMenu.AddDisabledItem(new GUIContent(fullMenuName));\n                        }\n                        else if (CommandService.Exists(commandId))\n                        {\n                            // Create a new menu item pointing to a command handler\n                            contextMenu.AddItem(new GUIContent(fullMenuName), false, () => CommandService.Execute(commandId, CommandHint.Menu));\n                        }\n                    }\n                }\n                else\n                {\n                    contextMenu.AddSeparator(prefix);\n                }\n            }\n        }\n\n        [RequiredByNativeCode]\n        internal static string GetCurrentModeId()\n        {\n            return currentId;\n        }\n\n        private static string GetModeId(int modeIndex)\n        {\n            if (!IsValidIndex(modeIndex))\n                return null;\n\n            return modes[modeIndex].id;\n        }\n\n        private static bool IsValidIndex(int modeIndex)\n        {\n            return 0 <= modeIndex && modeIndex < modeCount;\n        }\n\n        private static void OnModeChangeLayouts(ModeChangedArgs args)\n        {\n            // Prevent double loading the default/last layout already done by the WindowLayout system.\n            if (args.prevIndex == -1 || !IsMainWindowLoaded())\n                return;\n\n            Log(\"OnModeChangeLayouts\");\n\n            if (HasCapability(ModeCapability.LayoutSwitching, true))\n            {\n                var dynamicLayout = GetDynamicLayout(args.prevIndex);\n                if (dynamicLayout == null || Convert.ToBoolean(dynamicLayout[\"restore_saved_layout\"]))\n                {\n                    WindowLayout.SaveCurrentLayoutPerMode(GetModeId(args.prevIndex));\n                }\n\n                try\n                {\n                    if (args.nextIndex != 0 || HasCapability(args.prevIndex, ModeCapability.LayoutSwitching, true))\n                    {\n                        // Load the last valid layout for this mode\n                        WindowLayout.LoadCurrentModeLayout(keepMainWindow: true);\n                    }\n                }\n                catch (Exception)\n                {\n                    // Error while loading layout. Load the default layout for current mode.\n                    WindowLayout.LoadDefaultLayout();\n                }\n            }\n\n            WindowLayout.UpdateWindowLayoutMenu();\n        }\n\n        private static void OnModeChangeUpdate(ModeChangedArgs args)\n        {\n            Log(\"OnModeChangeUpdate\");\n\n            EditorApplication.UpdateMainWindowTitle();\n            SaveProjectPrefModeIndex(args.nextIndex);\n            UnityEditorInternal.InternalEditorUtility.RepaintAllViews();\n        }\n\n        private static void OnModeChangeMenus(ModeChangedArgs args)\n        {\n            if (args.prevIndex == -1 || !IsMainWindowLoaded())\n                return;\n\n            EditorUtility.RebuildAllMenus();\n\n            ShortcutIntegration.instance.RebuildShortcuts();\n        }\n\n        private static void Log(string actionName)\n        {\n            var debugMsg = $\"[MODES] ModeService[{GetModeId(currentIndex) ?? \"none\"}].{actionName}\";\n            Console.WriteLine(debugMsg);\n        }\n\n        internal static class JsonUtils\n        {\n            public static string JsonReadString(JSONObject data, string fieldName, string defaultValue = \"\")\n            {\n                if (!data.Contains(fieldName))\n                    return defaultValue;\n                return data[fieldName] as string;\n            }\n\n            public static int JsonReadInt(JSONObject data, string fieldName, int defaultValue = 0)\n            {\n                if (!data.Contains(fieldName))\n                    return defaultValue;\n                return (int)(double)data[fieldName];\n            }\n\n            public static bool JsonReadBoolean(JSONObject data, string fieldName, bool defaultValue = false)\n            {\n                if (!data.Contains(fieldName))\n                    return defaultValue;\n                return (bool)data[fieldName];\n            }\n\n            public static Dictionary<string, object> DeepMerge(JSONObject first, JSONObject second)\n            {\n                if (first == null) throw new ArgumentNullException(nameof(first));\n                if (second == null) throw new ArgumentNullException(nameof(second));\n\n                var merged = (Dictionary<string, object>)DeepClone(first);\n                DeepMergeInto(merged, second);\n                return merged;\n            }\n\n            private static void DeepMergeInto(JSONObject destination, JSONObject source)\n            {\n                if (destination == null) throw new ArgumentNullException(nameof(destination));\n                if (source == null) throw new ArgumentNullException(nameof(source));\n\n                foreach (DictionaryEntry pair in source)\n                {\n                    if (destination.Contains(pair.Key))\n                    {\n                        var value = destination[pair.Key];\n                        var firstObject = value as JSONObject;\n                        var secondObject = pair.Value as JSONObject;\n                        if (firstObject != null && secondObject != null)\n                        {\n                            DeepMergeInto(firstObject, secondObject);\n                            continue;\n                        }\n\n                        var firstArray = value as IList;\n                        var secondArray = pair.Value as IList;\n                        if (firstArray != null && secondArray != null)\n                        {\n                            DeepMergeArray(firstArray, secondArray);\n                            continue;\n                        }\n                    }\n\n                    destination[pair.Key] = DeepClone(pair.Value);\n                }\n            }\n\n            private static void DeepMergeArray(IList firstArray, IList secondArray)\n            {\n                foreach (var secondItem in secondArray)\n                {\n                    bool merged = false;\n\n                    var secondItemObject = secondItem as JSONObject;\n                    if (secondItemObject != null)\n                    {\n                        string secondItemId = secondItemObject.Contains(\"id\")\n                            ? secondItemObject[\"id\"] as string\n                            : (secondItemObject.Contains(\"name\") ? secondItemObject[\"name\"] as string : null);\n                        if (!String.IsNullOrEmpty(secondItemId))\n                        {\n                            // Find an equivalent object in the first array\n                            foreach (var firstItem in firstArray)\n                            {\n                                var firstItemObject = firstItem as JSONObject;\n                                if (firstItemObject == null)\n                                    continue;\n\n                                string firstItemId = firstItemObject.Contains(\"id\")\n                                    ? firstItemObject[\"id\"] as string\n                                    : (firstItemObject.Contains(\"name\") ? firstItemObject[\"name\"] as string : null);\n\n                                if (String.Equals(firstItemId, secondItemId, StringComparison.OrdinalIgnoreCase))\n                                {\n                                    DeepMergeInto(firstItemObject, secondItemObject);\n                                    merged = true;\n                                }\n                            }\n                        }\n                    }\n\n                    if (!merged)\n                        firstArray.Add(secondItem);\n                }\n            }\n\n            private static object DeepClone(object jsonValue)\n            {\n                if (jsonValue == null)\n                    return null;\n\n                var listValue = jsonValue as IList;\n                if (listValue != null)\n                {\n                    var clonedList = new List<object>(listValue.Count);\n                    foreach (var item in listValue)\n                        clonedList.Add(DeepClone(item));\n                    return clonedList;\n                }\n\n                var dictionaryValue = jsonValue as JSONObject;\n                if (dictionaryValue != null)\n                {\n                    var clonedDict = new Dictionary<string, object>(dictionaryValue.Count);\n                    foreach (DictionaryEntry kvp in dictionaryValue)\n                        clonedDict.Add((string)kvp.Key, DeepClone(kvp.Value));\n                    return clonedDict;\n                }\n\n                if (jsonValue is bool || jsonValue is double || jsonValue is string)\n                    return jsonValue;\n\n                throw new ArgumentException(\"Invalid JSON value: \" + jsonValue);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorPrefs.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\nusing UnityEngine.Internal;\n\nnamespace UnityEditor\n{\n    // Stores and accesses Unity editor preferences.\n    [NativeHeader(\"Runtime/Utilities/PlayerPrefs.h\")]\n    public sealed class EditorPrefs\n    {\n        // Sends events whenever EditorPrefs values are updated\n        // NOTE: This is a quick solution for accessing editor prefs from background threads,\n        //  long term solution is to make editor prefs read/writes threadsafe\n        internal delegate void ValueWasUpdated(string key);\n        internal static event ValueWasUpdated onValueWasUpdated;\n\n        // Sets the value of the preference identified by /key/.\n        [NativeMethod(\"SetInt\")]\n        static extern void SetInt_Internal(string key, int value);\n        public static void SetInt(string key, int value)\n        {\n            SetInt_Internal(key, value);\n            onValueWasUpdated?.Invoke(key);\n        }\n\n        // Returns the value corresponding to /key/ in the preference file if it exists.\n        public static extern int GetInt(string key, [DefaultValue(\"0\")] int defaultValue);\n        public static int GetInt(string key)\n        {\n            return GetInt(key, 0);\n        }\n\n        // Sets the value of the preference identified by /key/.\n        [NativeMethod(\"SetFloat\")]\n        static extern void SetFloat_Internal(string key, float value);\n        public static void SetFloat(string key, float value)\n        {\n            SetFloat_Internal(key, value);\n            onValueWasUpdated?.Invoke(key);\n        }\n\n        // Returns the value corresponding to /key/ in the preference file if it exists.\n        public static extern float GetFloat(string key, [DefaultValue(\"0.0F\")] float defaultValue);\n        public static float GetFloat(string key)\n        {\n            return GetFloat(key, 0.0F);\n        }\n\n        // Sets the value of the preference identified by /key/.\n        [NativeMethod(\"SetString\")]\n        static extern void SetString_Internal(string key, string value);\n        public static void SetString(string key, string value)\n        {\n            SetString_Internal(key, value);\n            onValueWasUpdated?.Invoke(key);\n        }\n\n        // Returns the value corresponding to /key/ in the preference file if it exists.\n        public static extern string GetString(string key, [DefaultValue(\"\\\"\\\"\")] string defaultValue);\n        public static string GetString(string key)\n        {\n            return GetString(key, \"\");\n        }\n\n        // Sets the value of the preference identified by /key/.\n        [NativeMethod(\"SetBool\")]\n        static extern void SetBool_Internal(string key, bool value);\n        public static void SetBool(string key, bool value)\n        {\n            SetBool_Internal(key, value);\n            onValueWasUpdated?.Invoke(key);\n        }\n\n        // Returns the value corresponding to /key/ in the preference file if it exists.\n        public static extern bool GetBool(string key, [DefaultValue(\"false\")] bool defaultValue);\n        public static bool GetBool(string key)\n        {\n            return GetBool(key, false);\n        }\n\n        // Returns true if /key/ exists in the preferences.\n        public static extern bool HasKey(string key);\n\n        // Removes /key/ and its corresponding value from the preferences.\n        public static extern void DeleteKey(string key);\n\n        // Removes all keys and values from the preferences. Use with caution.\n        public static extern void DeleteAll();\n\n        internal static extern void Sync();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorResources.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor.Experimental\n{\n    [NativeHeader(\"Editor/Src/EditorResources.h\"), StaticAccessor(\"EditorResources\", StaticAccessorType.DoubleColon)]\n    partial class EditorResources\n    {\n        [NativeProperty(\"k_NormalSkinIndex\", true, TargetType.Field)] public static extern int normalSkinIndex { get; }\n        [NativeProperty(\"k_DarkSkinIndex\", true, TargetType.Field)] public static extern int darkSkinIndex { get; }\n\n        [NativeProperty(\"k_LightSkinSourcePath\", true, TargetType.Field)] public static extern string lightSkinSourcePath { get; }\n        [NativeProperty(\"k_DarkSkinSourcePath\", true, TargetType.Field)] public static extern string darkSkinSourcePath { get; }\n        [NativeProperty(\"k_FontsPath\", true, TargetType.Field)] public static extern string fontsPath { get; }\n        [NativeProperty(\"k_BrushesPath\", true, TargetType.Field)] public static extern string brushesPath { get; }\n        [NativeProperty(\"k_IconsPath\", true, TargetType.Field)] public static extern string iconsPath { get; }\n        [NativeProperty(\"k_GeneratedIconsPath\", true, TargetType.Field)] public static extern string generatedIconsPath { get; }\n        [NativeProperty(\"k_FolderIconName\", true, TargetType.Field)] public static extern string folderIconName { get; }\n        [NativeProperty(\"k_EmptyFolderIconName\", true, TargetType.Field)] public static extern string emptyFolderIconName { get; }\n        [NativeProperty(\"k_OpenedFolderIconName\", true, TargetType.Field)] internal static extern string openedFolderIconName { get; }\n        [NativeProperty(\"k_EditorDefaultResourcesPath\", true, TargetType.Field)] public static extern string editorDefaultResourcesPath { get; }\n        [NativeProperty(\"k_LibraryBundlePath\", true, TargetType.Field)] public static extern string libraryBundlePath { get; }\n\n        [NativeThrows]\n        public static extern Object Load(string assetPath, Type type);\n        public static extern string GetAssetPath(Object obj);\n    }\n\n    [Obsolete(\"EditorResourcesUtility is obsolete, please use EditorResources instead.\", false)]\n    internal sealed class EditorResourcesUtility : EditorResources\n    {\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorResources.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n//#define DEBUG_EDITOR_RESOURCES // ONLY NEEDED BY STYLING DEVS AND DESIGNERS.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing JetBrains.Annotations;\nusing UnityEditor.StyleSheets;\nusing UnityEditor.Profiling;\nusing UnityEngine;\nusing UnityEngine.Internal;\nusing UnityEditorInternal;\n\nnamespace UnityEditor.Experimental\n{\n    internal class FontDef\n    {\n        class FontData\n        {\n            private string m_File;\n            private Font m_LoadedFont;\n            private string[] m_FontNames;\n\n            public FontData(string file, string[] fontNames)\n            {\n                m_File = file;\n                m_FontNames = fontNames;\n            }\n\n            public Font font\n            {\n                get\n                {\n                    if (m_LoadedFont == null)\n                    {\n                        m_LoadedFont = EditorGUIUtility.LoadRequired(m_File) as Font;\n                        if (m_LoadedFont != null && m_FontNames != null)\n                        {\n                            m_LoadedFont.fontNames = m_FontNames;\n                        }\n                    }\n\n                    return m_LoadedFont;\n                }\n            }\n        }\n\n        public const string k_Inter = \"Inter\";\n        public const string k_LucidaGrande = \"Lucida Grande\";\n        public const string k_Verdana = \"Verdana\";\n        public const string k_SystemFont = \"System Font\";\n\n        private Dictionary<Style, FontData> m_Fonts = new Dictionary<Style, FontData>();\n\n        public enum Style\n        {\n            Normal = FontStyle.Normal,\n            Bold = FontStyle.Bold,\n            Italic = FontStyle.Italic,\n            BoldAndItalic = FontStyle.BoldAndItalic,\n            Small\n        }\n\n        public string name { get; set; }\n\n        public FontDef(string name)\n        {\n            this.name = name;\n        }\n\n        public Font GetFont(Style style)\n        {\n            FontData data;\n\n            if (m_Fonts.TryGetValue(style, out data))\n            {\n                return data.font;\n            }\n\n            if (style != Style.Normal)\n                return GetFont(Style.Normal);\n            return null;\n        }\n\n        public void SetFont(Style style, string file, string[] fontNames = null)\n        {\n            m_Fonts[style] = new FontData(file, fontNames);\n        }\n\n        public static FontDef CreateFromResources(string fontName, Dictionary<Style, string> fonts)\n        {\n            FontDef fontDef = new FontDef(fontName);\n\n            foreach (var font in fonts)\n            {\n                fontDef.SetFont(font.Key, font.Value);\n            }\n\n            return fontDef;\n        }\n\n        public static FontDef CreateSystemFont(string fontName)\n        {\n            FontDef fontDef = new FontDef(fontName);\n\n            fontDef.SetFont(Style.Small, \"Fonts/System/System Small.ttf\");\n            fontDef.SetFont(Style.Normal, \"Fonts/System/System Normal.ttf\");\n            fontDef.SetFont(Style.Bold, \"Fonts/System/System Normal Bold.ttf\");\n            return fontDef;\n        }\n    }\n\n    [ExcludeFromDocs]\n    public partial class EditorResources\n    {\n        private const string k_PrefsUserFontKey = \"user_editor_font\";\n        const string k_GlobalStyleCatalogCacheFilePath = \"Library/Style.catalog\";\n\n        private static StyleCatalog s_StyleCatalog;\n        private static bool s_RefreshGlobalStyleCatalog = false;\n\n        static class Constants\n        {\n            public static bool isDarkTheme => EditorGUIUtility.isProSkin;\n        }\n\n        // Global editor styles\n        internal static StyleCatalog styleCatalog\n        {\n            get\n            {\n                if (s_StyleCatalog == null || s_RefreshGlobalStyleCatalog)\n                    BuildCatalog();\n                return s_StyleCatalog;\n            }\n        }\n\n        private static bool CanEnableExtendedStyles()\n        {\n            var rootBlock = styleCatalog.GetStyle(StyleCatalogKeyword.root, StyleState.root);\n            var styleExtensionDisabled = rootBlock.GetBool(\"-unity-disable-style-extensions\");\n            if (!styleExtensionDisabled)\n                return true;\n            return false;\n        }\n\n        private static bool IsEditorStyleSheet(string path)\n        {\n            if (!SearchUtils.EndsWith(path, \".uss\"))\n                return false;\n            return path.IndexOf(\"/stylesheets/extensions/\", StringComparison.OrdinalIgnoreCase) != -1 &&\n                (SearchUtils.EndsWith(path, \"common.uss\") || SearchUtils.EndsWith(path, Constants.isDarkTheme ? \"dark.uss\" : \"light.uss\"));\n        }\n\n        internal static string GetDefaultFont()\n        {\n            return FontDef.k_Inter;\n        }\n\n        internal static IEnumerable<string> supportedFontNames => EditorResources.supportedFonts.Keys;\n\n        private static string s_CurrentFontName = null;\n\n        internal static string currentFontName\n        {\n            get\n            {\n                if (s_CurrentFontName == null)\n                {\n                    s_CurrentFontName = EditorPrefs.GetString(k_PrefsUserFontKey, GetDefaultFont());\n\n                    // If the current is not available then fallback to the default font\n                    if (!supportedFontNames.Contains(s_CurrentFontName))\n                    {\n                        s_CurrentFontName = GetDefaultFont();\n                        EditorPrefs.DeleteKey(k_PrefsUserFontKey);\n                    }\n                }\n\n                return s_CurrentFontName;\n            }\n        }\n\n        internal static Font GetFont(FontDef.Style fontStyle)\n        {\n            var currentFontDef = supportedFonts[currentFontName];\n\n            return currentFontDef.GetFont(fontStyle);\n        }\n\n        private static Dictionary<string, FontDef> s_SupportedFonts = null;\n        internal static Dictionary<string, FontDef> supportedFonts\n        {\n            get\n            {\n                if (s_SupportedFonts == null)\n                {\n                    s_SupportedFonts = new Dictionary<string, FontDef>();\n                    s_SupportedFonts[FontDef.k_Inter] = FontDef.CreateFromResources(FontDef.k_Inter,\n                        new Dictionary<FontDef.Style, string>\n                        {\n                            {FontDef.Style.Small, \"Fonts/Inter/Inter-Small.ttf\"},\n                            {FontDef.Style.Normal, \"Fonts/Inter/Inter-Regular.ttf\"},\n                            {FontDef.Style.Bold, \"Fonts/Inter/Inter-SemiBold.ttf\"},\n                            {FontDef.Style.Italic, \"Fonts/Inter/Inter-Italic.ttf\"},\n                            {FontDef.Style.BoldAndItalic, \"Fonts/Inter/Inter-SemiBoldItalic.ttf\"}\n                        });\n\n                }\n\n                return s_SupportedFonts;\n            }\n        }\n\n        private static List<string> GetDefaultStyleCatalogPaths()\n        {\n            bool useDarkTheme = Constants.isDarkTheme;\n            var catalogFiles = new List<string>\n            {\n                \"StyleSheets/Extensions/base/common.uss\",\n                \"UIPackageResources/StyleSheets/Default/Variables/Public/common.uss\",\n                \"StyleSheets/Northstar/common.uss\"\n            };\n\n            if (LocalizationDatabase.currentEditorLanguage == SystemLanguage.English)\n            {\n                string currentFontStyleSheet = \"StyleSheets/Extensions/fonts/\" + currentFontName.ToLowerInvariant() + \".uss\";\n\n                catalogFiles.Add(currentFontStyleSheet);\n            }\n\n            catalogFiles.Add(useDarkTheme ? \"StyleSheets/Extensions/base/dark.uss\" : \"StyleSheets/Extensions/base/light.uss\");\n            catalogFiles.Add(useDarkTheme ? \"UIPackageResources/StyleSheets/Default/Northstar/Palette/dark.uss\" : \"UIPackageResources/StyleSheets/Default/Northstar/Palette/light.uss\");\n            return catalogFiles;\n        }\n\n        static string ComputeCatalogHash(List<string> paths)\n        {\n            var hash = $\"__StyleCatalog_Hash_{InternalEditorUtility.GetUnityVersion()}_\";\n            foreach (var path in paths)\n            {\n                hash += path.GetHashCode().ToString(\"X2\");\n                var fi = new FileInfo(path);\n                if (fi.Exists)\n                    hash += fi.Length.ToString(\"X2\");\n            }\n            return hash;\n        }\n\n        static void SaveCatalogToDisk(StyleCatalog catalog, string hash, string savePath)\n        {\n            using (var stream = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None))\n            using (BinaryWriter writer = new BinaryWriter(stream))\n            {\n                writer.Write(hash);\n                catalog.Save(writer);\n            }\n        }\n\n        internal static void BuildCatalog()\n        {\n            using (new EditorPerformanceTracker(nameof(BuildCatalog)))\n            {\n                s_StyleCatalog = new StyleCatalog();\n\n                bool rebuildCatalog = true;\n                List<string> paths = new List<string>();\n                string catalogHash = \"\";\n\n                if (!EditorApplication.isBuildingAnyResources)\n                {\n                    paths = GetDefaultStyleCatalogPaths();\n\n                    foreach (var editorUssPath in AssetDatabase.GetAllAssetPaths().Where(IsEditorStyleSheet))\n                    {\n                        var artifactKey = new ArtifactKey(new GUID(AssetDatabase.AssetPathToGUID(editorUssPath)));\n                        var artifactID = AssetDatabaseExperimental.LookupArtifact(artifactKey);\n\n                        //Only add it to the list of paths it if has been imported, since later on\n                        //the asset will be loaded, and if not imported it will fail.\n                        if (artifactID.isValid)\n                        {\n                            paths.Add(editorUssPath);\n                        }\n                    }\n\n                    var forceRebuild = s_RefreshGlobalStyleCatalog;\n                    s_RefreshGlobalStyleCatalog = false;\n\n                    catalogHash = ComputeCatalogHash(paths);\n                    if (!forceRebuild && File.Exists(k_GlobalStyleCatalogCacheFilePath))\n                    {\n                        using (var cacheCatalogStream = new FileStream(k_GlobalStyleCatalogCacheFilePath, FileMode.Open,\n                            FileAccess.Read, FileShare.Read))\n                        {\n                            using (var ccReader = new BinaryReader(cacheCatalogStream))\n                            {\n                                string cacheHash = ccReader.ReadString();\n                                if (cacheHash == catalogHash)\n                                    rebuildCatalog = !s_StyleCatalog.Load(ccReader);\n                            }\n                        }\n                    }\n                }\n\n                if (rebuildCatalog)\n                {\n                    Console.WriteLine($\"Loading style catalogs ({paths.Count})\\r\\n\\t{String.Join(\"\\r\\n\\t\", paths.ToArray())}\");\n\n                    s_StyleCatalog.Load(paths);\n\n                    if (paths.Count != 0)\n                    {\n                        SaveCatalogToDisk(s_StyleCatalog, catalogHash, k_GlobalStyleCatalogCacheFilePath);\n                    }\n                }\n            }\n        }\n\n        internal static void RefreshSkin()\n        {\n            using (new EditorPerformanceTracker(nameof(RefreshSkin)))\n            {\n                if (!CanEnableExtendedStyles())\n                    return;\n\n                GUIStyle.onDraw = StylePainter.DrawStyle;\n\n                // Update gui skin style layouts\n                var skin = GUIUtility.GetDefaultSkin();\n                if (skin != null)\n                {\n                    // TODO: Emit OnStyleCatalogLoaded\n                    if (Path.GetFileName(Path.GetDirectoryName(Application.dataPath)) == \"editor_resources\")\n                        ConverterUtils.ResetSkinToPristine(skin, Constants.isDarkTheme ? SkinTarget.Dark : SkinTarget.Light);\n                    skin.font = GetFont(FontDef.Style.Normal);\n                    UpdateGUIStyleProperties(skin);\n                }\n            }\n        }\n\n        internal static void UpdateGUIStyleProperties(GUISkin skin)\n        {\n            LocalizedEditorFontManager.LocalizeEditorFonts();\n\n            skin.ForEachGUIStyleProperty(UpdateGUIStyleProperties);\n            foreach (var style in skin.customStyles)\n                UpdateGUIStyleProperties(style.name, style);\n        }\n\n        internal static List<GUIStyle> GetExtendedStylesFromSkin(GUISkin skin)\n        {\n            var extendedStyles = new List<GUIStyle>();\n            Action<string, GUIStyle> appendExtendedBlock = (name, style) =>\n            {\n                var sname = GUIStyleExtensions.StyleNameToBlockName(style.name, false);\n                if (styleCatalog.GetStyle(sname).IsValid())\n                {\n                    extendedStyles.Add(style);\n                }\n            };\n\n            skin.ForEachGUIStyleProperty(appendExtendedBlock);\n            foreach (var style in skin.customStyles)\n                appendExtendedBlock(style.name, style);\n\n            return extendedStyles;\n        }\n\n        internal static void DeleteStyleCatalogCache()\n        {\n            if (File.Exists(k_GlobalStyleCatalogCacheFilePath))\n                File.Delete(k_GlobalStyleCatalogCacheFilePath);\n        }\n\n\n        private static void UpdateGUIStyleProperties(string name, GUIStyle style)\n        {\n            var sname = GUIStyleExtensions.StyleNameToBlockName(style.name, false);\n            var block = styleCatalog.GetStyle(sname);\n            if (!block.IsValid())\n                return;\n\n            try\n            {\n                GUIStyleExtensions.PopulateStyle(styleCatalog, style, sname);\n                GUIStyleExtensions.ConvertToExtendedStyle(style);\n            }\n            catch (Exception ex)\n            {\n                Debug.LogWarning($\"Failed to parse extended style properties for {sname}\\n{ex.Message}\");\n            }\n        }\n\n        // Returns the editor resources absolute file system path.\n        public static string dataPath => Application.dataPath;\n\n        // Resolve an editor resource asset path.\n        public static string ExpandPath(string path)\n        {\n            return path.Replace(\"\\\\\", \"/\");\n        }\n\n        // Returns the full file system path of an editor resource asset path.\n        public static string GetFullPath(string path)\n        {\n            if (File.Exists(path))\n                return path;\n            return new FileInfo(ExpandPath(path)).FullName;\n        }\n\n        // Checks if an editor resource asset path exists.\n        public static bool Exists(string path)\n        {\n            if (File.Exists(path))\n                return true;\n            return File.Exists(ExpandPath(path));\n        }\n\n        // Loads an editor resource asset.\n        public static T Load<T>(string assetPath, bool isRequired = true) where T : UnityEngine.Object\n        {\n            var obj = Load(assetPath, typeof(T));\n            if (!obj && isRequired)\n                throw new FileNotFoundException(\"Could not find editor resource \" + assetPath);\n            return obj as T;\n        }\n\n        // Returns a globally defined style element by name.\n        internal static StyleBlock GetStyle(string selectorName, params StyleState[] states) { return styleCatalog.GetStyle(selectorName, states); }\n        internal static StyleBlock GetStyle(int selectorKey, params StyleState[] states) { return styleCatalog.GetStyle(selectorKey, states); }\n\n        // Loads an USS asset into the global style catalog\n        internal static void LoadStyles(string ussPath)\n        {\n            styleCatalog.Load(ussPath);\n        }\n\n        // Creates a new style catalog from a set of USS assets.\n        internal static StyleCatalog LoadCatalog(string[] ussPaths)\n        {\n            var catalog = new StyleCatalog();\n            catalog.Load(ussPaths);\n            return catalog;\n        }\n\n        [UsedImplicitly]\n        private class StyleCatalogPostProcessor : AssetPostprocessor\n        {\n            [UsedImplicitly]\n            static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)\n            {\n                if (styleCatalog == null)\n                    return;\n\n                if (importedAssets.Concat(deletedAssets).Any(path => IsEditorStyleSheet(path)))\n                    s_RefreshGlobalStyleCatalog = true;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorSceneManager.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing UnityEngine.Bindings;\nusing uei = UnityEngine.Internal;\n\nnamespace UnityEditor.SceneManagement\n{\n    // Bit mask that controls the enabled features on a preview scene\n    [System.Flags]\n    internal enum PreviewSceneFlags\n    {\n        NoFlags = 0,\n        IsPreviewScene = 1,\n        AllowCamerasForRendering = 2,\n        AllowMonoBehaviourEvents = 4,\n        AllowGlobalIlluminationLights = 8,\n        AllowAutoPlayAudioSources = 16,\n        AllFlags = 1 + 2 + 4 + 8 + 16\n    }\n\n    [NativeHeader(\"Runtime/SceneManager/SceneManager.h\")]\n    [NativeHeader(\"Modules/AssetPipelineEditor/Public/DefaultImporter.h\")]\n    [NativeHeader(\"Editor/Mono/EditorSceneManager.bindings.h\")]\n    public sealed partial class EditorSceneManager : SceneManager\n    {\n        [StaticAccessor(\"GetSceneManager()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"IsReloading\")]\n        public extern static bool IsReloading(Scene scene);\n\n        public extern static int loadedRootSceneCount\n        {\n            [StaticAccessor(\"GetSceneManager()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"GetLoadedRootSceneCount\")]\n            get;\n        }\n\n        public extern static int previewSceneCount\n        {\n            [StaticAccessor(\"GetSceneManager()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"GetPreviewSceneCount\")]\n            get;\n        }\n\n        public extern static bool preventCrossSceneReferences\n        {\n            [StaticAccessor(\"GetSceneManager()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"IsPreventingCrossSceneReferences\")]\n            get;\n\n            [StaticAccessor(\"GetSceneManager()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"SetPreventCrossSceneReferences\")]\n            set;\n        }\n\n        public extern static SceneAsset playModeStartScene\n        {\n            [StaticAccessor(\"GetSceneManager()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"GetPlayModeStartScene\")]\n            get;\n\n            [StaticAccessor(\"GetSceneManager()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"SetPlayModeStartScene\")]\n            set;\n        }\n\n        [FreeFunction(\"GetSceneTracker().CanOpenScene\")]\n        internal static extern bool CanOpenScene();\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"OpenScene\")]\n        public extern static Scene OpenScene(string scenePath, [uei.DefaultValue(\"OpenSceneMode.Single\")] OpenSceneMode mode);\n\n        public static Scene OpenPreviewScene(string scenePath)\n        {\n            return OpenPreviewScene(scenePath, true);\n        }\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"OpenPreviewScene\")]\n        internal extern static Scene OpenPreviewScene(string scenePath, bool allocateSceneCullingMask);\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"NewScene\")]\n        public extern static Scene NewScene(NewSceneSetup setup, [uei.DefaultValue(\"NewSceneMode.Single\")] NewSceneMode mode);\n\n        public static Scene NewPreviewScene()\n        {\n            return NewPreviewScene(true, PreviewSceneFlags.IsPreviewScene);\n        }\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"NewPreviewScene\")]\n        internal extern static Scene NewPreviewScene(bool allocateSceneCullingMask, PreviewSceneFlags previewSceneFlags = PreviewSceneFlags.IsPreviewScene);\n\n        [StaticAccessor(\"GetSceneManager()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"CreateSceneAsset\")]\n        private extern static bool CreateSceneAssetInternal(string scenePath, bool createDefaultGameObjects);\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"RemapAssetReferencesInSceneInternal\")]\n        private extern static void RemapAssetReferencesInSceneInternal(UnityEngine.SceneManagement.Scene scene, string[] srcPaths, string[] dstPaths, int[] srcIds, int[] dstIds);\n\n        internal static void RemapAssetReferencesInScene(UnityEngine.SceneManagement.Scene scene, Dictionary<string, string> pathMap, Dictionary<int, int> idMap = null)\n        {\n            RemapAssetReferencesInSceneInternal(scene,\n                pathMap.Keys.ToArray(), pathMap.Values.ToArray(),\n                idMap == null ? new int[0] : idMap.Keys.ToArray(),\n                idMap == null ? new int[0] : idMap.Values.ToArray()\n            );\n        }\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"CloseScene\")]\n        public extern static bool CloseScene(Scene scene, bool removeScene);\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"ClosePreviewScene\")]\n        public extern static bool ClosePreviewScene(Scene scene);\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"IsPreviewScene\")]\n        public extern static bool IsPreviewScene(Scene scene);\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"SetPreviewScenesVisibleInHierarchy\")]\n        internal extern static void SetPreviewScenesVisibleInHierarchy(bool visible);\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"GetPreviewScenesVisibleInHierarchy\")]\n        internal extern static bool GetPreviewScenesVisibleInHierarchy();\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        internal extern static Scene GetDontDestroyOnLoadScene();\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"IsPreviewSceneObject\")]\n        public extern static bool IsPreviewSceneObject(UnityEngine.Object obj);\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"IsAuthoringScene\")]\n        internal extern static bool IsAuthoringScene(Scene scene);\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"ReloadScene\")]\n        internal extern static bool ReloadScene(Scene scene);\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"ClearOpenScenesChangedOnDisk\")]\n        internal extern static void ClearOpenScenesChangedOnDisk();\n\n        internal static void SetTargetSceneForNewGameObjects(Scene scene) { SetTargetSceneForNewGameObjects(scene.handle); }\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"ClearTargetSceneForNewGameObjects\")]\n        internal extern static void ClearTargetSceneForNewGameObjects();\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"SetTargetSceneForNewGameObjects\")]\n        internal extern static void SetTargetSceneForNewGameObjects(int sceneHandle);\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"GetTargetSceneForNewGameObjects\")]\n        internal extern static Scene GetTargetSceneForNewGameObjects();\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"GetSceneByHandle\")]\n        internal extern static Scene GetSceneByHandle(int handle);\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"MoveSceneBefore\")]\n        public extern static void MoveSceneBefore(Scene src, Scene dst);\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"MoveSceneAfter\")]\n        public extern static void MoveSceneAfter(Scene src, Scene dst);\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"SaveSceneAs\")]\n        internal extern static bool SaveSceneAs(Scene scene);\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"SaveSceneInternal\")]\n        private extern static bool SaveSceneInternal(Scene scene, string dstScenePath, bool saveAsCopy);\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"SaveOpenScenes\")]\n        public extern static bool SaveOpenScenes();\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"SaveScenes\")]\n        public extern static bool SaveScenes([NotNull] Scene[] scenes);\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"SaveCurrentModifiedScenesIfUserWantsTo\")]\n        internal extern static bool SaveCurrentModifiedScenesIfUserWantsTo(string message);\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"SaveModifiedScenesIfUserWantsTo\")]\n        public extern static bool SaveModifiedScenesIfUserWantsTo([NotNull] Scene[] scenes);\n\n        [StaticAccessor(\"GetSceneManager()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"EnsureUntitledSceneHasBeenSaved\")]\n        public extern static bool EnsureUntitledSceneHasBeenSaved(string dialogContent);\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"MarkSceneDirty\")]\n        public extern static bool MarkSceneDirty(Scene scene);\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"MarkAllScenesDirty\")]\n        public extern static void MarkAllScenesDirty();\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"ClearSceneDirtiness\")]\n        internal extern static void ClearSceneDirtiness(Scene scene);\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"GetSceneManagerSetup\")]\n        public extern static SceneSetup[] GetSceneManagerSetup();\n\n        [NativeThrows]\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"RestoreSceneManagerSetup\")]\n        public extern static void RestoreSceneManagerSetup([Unmarshalled] SceneSetup[] value);\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"LoadSceneManagerSetup\")]\n        internal extern static bool LoadSceneManagerSetup(string path);\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern bool LoadLastSceneManagerSetup();\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        [NativeMethod(\"DetectCrossSceneReferences\")]\n        public extern static bool DetectCrossSceneReferences(Scene scene);\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        private extern static AsyncOperation LoadSceneInPlayModeInternal(string path, LoadSceneParameters parameters, bool isSynchronous);\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        extern public static ulong GetSceneCullingMask(Scene scene);\n\n        [StaticAccessor(\"EditorSceneManagerBindings\", StaticAccessorType.DoubleColon)]\n        extern public static void SetSceneCullingMask(Scene scene, ulong sceneCullingMask);\n\n        [StaticAccessor(\"GetSceneManager()\", StaticAccessorType.Dot)]\n        extern public static ulong CalculateAvailableSceneCullingMask();\n\n        // Use SceneCullingMasks.DefaultSceneCullingMask\n        public const ulong DefaultSceneCullingMask = SceneCullingMasks.DefaultSceneCullingMask;\n    }\n\n    public static class SceneCullingMasks\n    {\n        // If updating the bits here ensure kDefaultSceneCullingMask (in C++) is in sync. Also ensure EditorSceneManager.DefaultSceneCullingMask is in sync.\n        public const ulong DefaultSceneCullingMask = GameViewObjects | MainStageSceneViewObjects;\n        public const ulong GameViewObjects = 1UL << 63;\n        public const ulong MainStageSceneViewObjects = MainStagePrefabInstanceObjectsOpenInPrefabMode | MainStageExcludingPrefabInstanceObjectsOpenInPrefabMode;\n\n        internal const ulong MainStageExcludingPrefabInstanceObjectsOpenInPrefabMode = 1UL << 62;\n        internal const ulong MainStagePrefabInstanceObjectsOpenInPrefabMode = 1UL << 61;\n        internal const ulong PrefabStagePrefabInstanceObjectsOpenInPrefabMode = 1UL << 60;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorSceneManager.bindings.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.SceneManagement;\n\nnamespace UnityEditor.SceneManagement\n{\n    public sealed partial class EditorSceneManager : SceneManager\n    {\n        [Obsolete(\"EditorSceneManager.loadedSceneCount has been deprecated. Please use SceneManager.loadedSceneCount (UnityUpgradable) -> [UnityEngine] UnityEngine.SceneManagement.SceneManager.loadedSceneCount\")]\n        new public static int loadedSceneCount\n        {\n            get => SceneManager.loadedSceneCount;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorSceneManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Events;\nusing UnityEngine.SceneManagement;\nusing RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute;\nusing uei = UnityEngine.Internal;\n\nnamespace UnityEditor.SceneManagement\n{\n    // Must match same enums in C++\n    public enum OpenSceneMode { Single, Additive, AdditiveWithoutLoading }\n    public enum NewSceneMode { Single, Additive }\n    public enum NewSceneSetup { EmptyScene, DefaultGameObjects }\n\n    public sealed partial class EditorSceneManager : SceneManager\n    {\n        internal static UnityAction<Scene, NewSceneMode> sceneWasCreated;\n        internal static UnityAction<Scene, OpenSceneMode> sceneWasOpened;\n        public static event UnityAction<Scene, Scene> activeSceneChangedInEditMode\n        {\n            add => m_ActiveSceneChangedInEditModeEvent.Add(value);\n            remove => m_ActiveSceneChangedInEditModeEvent.Remove(value);\n        }\n\n        private static EventWithPerformanceTracker<UnityAction<Scene, Scene>> m_ActiveSceneChangedInEditModeEvent = new EventWithPerformanceTracker<UnityAction<Scene, Scene>>($\"{nameof(EditorSceneManager)}.{nameof(activeSceneChangedInEditMode)}\");\n\n        private static void PlayModeStateChangedCallback(PlayModeStateChange state)\n        {\n            switch (state)\n            {\n                case PlayModeStateChange.ExitingPlayMode:\n                    SceneManager.s_AllowLoadScene = false;\n                    break;\n                case PlayModeStateChange.EnteredEditMode:   // When in edit mode calling LoadScene will fail with an exception so it is \"ok\" to call from edit mode\n                case PlayModeStateChange.ExitingEditMode:\n                case PlayModeStateChange.EnteredPlayMode:\n                default:\n                    SceneManager.s_AllowLoadScene = true;\n                    break;\n            }\n        }\n\n        static EditorSceneManager()\n        {\n            SceneManager.s_AllowLoadScene = true;\n            EditorApplication.playModeStateChanged += PlayModeStateChangedCallback;\n        }\n\n        internal static bool CreateSceneAsset(string scenePath, bool createDefaultGameObjects)\n        {\n            if (!Utils.Paths.CheckValidAssetPathAndThatDirectoryExists(scenePath, \".unity\"))\n                return false;\n\n            return CreateSceneAssetInternal(scenePath, createDefaultGameObjects);\n        }\n\n        public static bool SaveCurrentModifiedScenesIfUserWantsTo() => SaveCurrentModifiedScenesIfUserWantsTo(null);\n\n        [uei.ExcludeFromDocs]\n        public static Scene OpenScene(string scenePath)\n        {\n            Scene result;\n            result = OpenScene(scenePath, OpenSceneMode.Single);\n            return result;\n        }\n\n        [uei.ExcludeFromDocs]\n        public static Scene NewScene(NewSceneSetup setup)\n        {\n            Scene result;\n            result = NewScene(setup, NewSceneMode.Single);\n            return result;\n        }\n\n        [uei.ExcludeFromDocs]\n        public static bool SaveScene(Scene scene, string dstScenePath)\n        {\n            bool saveAsCopy = false;\n            return SaveScene(scene, dstScenePath, saveAsCopy);\n        }\n\n        [uei.ExcludeFromDocs]\n        public static bool SaveScene(Scene scene)\n        {\n            bool saveAsCopy = false;\n            string dstScenePath = \"\";\n            return SaveScene(scene, dstScenePath, saveAsCopy);\n        }\n\n        public static bool SaveScene(Scene scene, [uei.DefaultValue(\"\\\"\\\"\")] string dstScenePath, [uei.DefaultValue(\"false\")] bool saveAsCopy)\n        {\n            if (!string.IsNullOrEmpty(dstScenePath))\n                if (!Utils.Paths.CheckValidAssetPathAndThatDirectoryExists(dstScenePath, \".unity\"))\n                    return false;\n\n            return SaveSceneInternal(scene, dstScenePath, saveAsCopy);\n        }\n\n        private static void Internal_NewSceneWasCreated(Scene scene, NewSceneMode mode)\n        {\n            if (sceneWasCreated != null)\n                sceneWasCreated(scene, mode);\n        }\n\n        private static void Internal_SceneWasOpened(Scene scene, OpenSceneMode mode)\n        {\n            if (sceneWasOpened != null)\n                sceneWasOpened(scene, mode);\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_ActiveSceneChangedInEditor(Scene previousActiveScene, Scene newActiveScene)\n        {\n            foreach (var evt in m_ActiveSceneChangedInEditModeEvent)\n            {\n                evt(previousActiveScene, newActiveScene);\n            }\n        }\n\n        public static Scene LoadSceneInPlayMode(string path, LoadSceneParameters parameters)\n        {\n            AsyncOperation op = LoadSceneInPlayModeInternal(path, parameters, true);\n            if (op != null)\n                return GetSceneAt(sceneCount - 1);\n\n            return new Scene();\n        }\n\n        public static AsyncOperation LoadSceneAsyncInPlayMode(string path, LoadSceneParameters parameters)\n        {\n            return LoadSceneInPlayModeInternal(path, parameters, false);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorSerializationUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Serialization;\nusing UnityEngine.Bindings;\nusing UnityObject = UnityEngine.Object;\nusing RefId = System.Int64;\n\nnamespace UnityEditor\n{\n    //Must match declaration in EditorSerializationUtility.h\n    [NativeType(Header = \"Editor/Src/Utility/EditorSerializationUtility.h\")]\n    public readonly struct ManagedReferenceMissingType : IEquatable<ManagedReferenceMissingType>, IComparable<ManagedReferenceMissingType>\n    {\n        public readonly String assemblyName { get { return m_AssemblyName; } }\n        public readonly String className { get { return m_ClassName; } }\n        public readonly String namespaceName { get { return m_NamespaceName; } }\n        public readonly RefId referenceId { get { return m_ReferenceId; } }\n        public readonly String serializedData { get { return m_SerializedData; } }\n\n        public bool Equals(ManagedReferenceMissingType other)\n        {\n            return referenceId == other.referenceId;\n        }\n\n        public int CompareTo(ManagedReferenceMissingType other)\n        {\n            return referenceId.CompareTo(other.referenceId);\n        }\n\n#pragma warning disable CS0649\n        [NativeName(\"assemblyName\")]\n        private readonly String m_AssemblyName;\n\n        [NativeName(\"className\")]\n        private readonly String m_ClassName;\n\n        [NativeName(\"namespaceName\")]\n        private readonly String m_NamespaceName;\n\n        [NativeName(\"referenceId\")]\n        private readonly RefId m_ReferenceId;\n\n        [NativeName(\"serializedData\")]\n        private readonly String m_SerializedData;\n#pragma warning restore CS0649\n    };\n\n    [NativeHeader(\"Editor/Src/Utility/EditorSerializationUtility.h\")]\n    public sealed class SerializationUtility\n    {\n        // Must match the same declarations in \"Runtime/Serialize/ReferenceId.h\"\n        [System.Obsolete(\"Use Serialization.ManagedReferenceUtility.RefIdUnknown instead. (UnityUpgradable) -> [UnityEngine] UnityEngine.Serialization.ManagedReferenceUtility.RefIdUnknown\", false)]\n        public const RefId RefIdUnknown = -1;\n        [System.Obsolete(\"Use Serialization.ManagedReferenceUtility.RefIdNull instead. (UnityUpgradable) -> [UnityEngine] UnityEngine.Serialization.ManagedReferenceUtility.RefIdNull\", false)]\n        public const RefId RefIdNull = -2;\n\n        [System.Obsolete(\"Use Serialization.ManagedReferenceUtility.SetManagedReferenceIdForObject instead. (UnityUpgradable) -> [UnityEngine] UnityEngine.Serialization.ManagedReferenceUtility.SetManagedReferenceIdForObject(*)\", false)]\n        public static bool SetManagedReferenceIdForObject(UnityObject obj, object scriptObj, RefId refId)\n        {\n            return ManagedReferenceUtility.SetManagedReferenceIdForObject(obj, scriptObj, refId);\n        }\n\n        [System.Obsolete(\"Use Serialization.ManagedReferenceUtility::GetManagedReferenceIdForObject instead. (UnityUpgradable) -> [UnityEngine] UnityEngine.Serialization.ManagedReferenceUtility.GetManagedReferenceIdForObject(*)\", false)]\n        public static  RefId GetManagedReferenceIdForObject(UnityObject obj, object scriptObj)\n        {\n            return ManagedReferenceUtility.GetManagedReferenceIdForObject(obj, scriptObj);\n        }\n\n        [System.Obsolete(\"Use Serialization.ManagedReferenceUtility::GetManagedReference instead. (UnityUpgradable) -> [UnityEngine] UnityEngine.Serialization.ManagedReferenceUtility.GetManagedReference(*)\", false)]\n        public static object GetManagedReference(UnityObject obj, RefId id)\n        {\n            return ManagedReferenceUtility.GetManagedReference(obj, id);\n        }\n\n        [System.Obsolete(\"Use Serialization.ManagedReferenceUtility::GetManagedReferencesIds instead. (UnityUpgradable) -> [UnityEngine] UnityEngine.Serialization.ManagedReferenceUtility.GetManagedReferenceIds(*)\", false)]\n        public static RefId[] GetManagedReferenceIds(UnityObject obj)\n        {\n            return ManagedReferenceUtility.GetManagedReferenceIds(obj);\n        }\n\n        [NativeMethod(\"HasManagedReferencesWithMissingTypes\")]\n        static extern bool HasManagedReferencesWithMissingTypesInternal(UnityObject obj);\n\n        public static bool HasManagedReferencesWithMissingTypes(UnityObject obj)\n        {\n            return HasManagedReferencesWithMissingTypesInternal(obj);\n        }\n\n        [NativeMethod(\"GetManagedReferencesWithMissingTypes\")]\n        static extern ManagedReferenceMissingType[] GetManagedReferencesWithMissingTypesInternal(UnityObject obj);\n\n        public static ManagedReferenceMissingType[] GetManagedReferencesWithMissingTypes(UnityObject obj)\n        {\n            return GetManagedReferencesWithMissingTypesInternal(obj);\n        }\n\n        [NativeMethod(\"ClearAllManagedReferencesWithMissingTypes\")]\n        static extern bool ClearAllManagedReferencesWithMissingTypesInternal(UnityObject obj);\n\n        public static bool ClearAllManagedReferencesWithMissingTypes(UnityObject obj)\n        {\n            return ClearAllManagedReferencesWithMissingTypesInternal(obj);\n        }\n\n        [NativeMethod(\"ClearManagedReferenceWithMissingType\")]\n        static extern bool ClearManagedReferenceWithMissingTypeInternal(UnityObject obj, RefId id);\n\n        public static bool ClearManagedReferenceWithMissingType(UnityObject obj, RefId id)\n        {\n            return ClearManagedReferenceWithMissingTypeInternal(obj, id);\n        }\n\n        internal static extern void SuppressMissingTypeWarning(string className);\n    };\n}\n"
  },
  {
    "path": "Editor/Mono/EditorSettings.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEngine.Bindings;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    public enum SerializationMode\n    {\n        Mixed = 0,\n        ForceBinary = 1,\n        ForceText = 2\n    }\n\n    public enum EditorBehaviorMode\n    {\n        Mode3D = 0,\n        Mode2D = 1\n    }\n\n    public enum SpritePackerMode\n    {\n        Disabled = 0,\n        [Obsolete(\"Sprite Packing Tags are deprecated. Please use Sprite Atlas asset.\")]\n        BuildTimeOnly = 1,\n        [Obsolete(\"Sprite Packing Tags are deprecated. Please use Sprite Atlas asset.\")]\n        AlwaysOn = 2,\n        BuildTimeOnlyAtlas = 3,\n        AlwaysOnAtlas = 4,\n        SpriteAtlasV2 = 5,\n        SpriteAtlasV2Build = 6,\n    }\n\n    public enum LineEndingsMode\n    {\n        OSNative = 0,\n        Unix = 1,\n        Windows = 2\n    }\n\n    public enum AssetPipelineMode\n    {\n        Version1 = 0,\n        Version2 = 1\n    }\n\n    public enum CacheServerMode\n    {\n        AsPreferences = 0,\n        Enabled = 1,\n        Disabled = 2\n    }\n\n    public enum CacheServerValidationMode\n    {\n        Disabled = 0,\n        UploadOnly = 1,\n        Enabled = 2,\n        Required = 3\n    }\n\n    [Flags]\n    public enum EnterPlayModeOptions\n    {\n        None = 0,\n        DisableDomainReload = 1 << 0,\n        DisableSceneReload = 1 << 1,\n        [Obsolete(\"Option has no effect and is deprecated.\")]\n        DisableSceneBackupUnlessDirty = 1 << 2\n    }\n\n    [NativeHeader(\"Editor/Src/EditorSettings.h\")]\n    [NativeHeader(\"Editor/Src/VersionControlSettings.h\")]\n    [NativeHeader(\"Editor/Src/EditorUserSettings.h\")]\n    public sealed class EditorSettings : Object\n    {\n        internal enum Bc7TextureCompressor\n        {\n            Default = 0,\n            Ispc = 1,\n            Bc7e = 2,\n        }\n\n        private EditorSettings()\n        {\n        }\n\n        // Device that editor should use for Unity Remote\n        public static string unityRemoteDevice\n        {\n            get { return GetConfigValue(\"UnityRemoteDevice\"); }\n            set { SetConfigValue(\"UnityRemoteDevice\", value); }\n        }\n\n        // Compression method for Unity Remote to use\n        public static string unityRemoteCompression\n        {\n            get { return GetConfigValue(\"UnityRemoteCompression\"); }\n            set { SetConfigValue(\"UnityRemoteCompression\", value); }\n        }\n\n        // Screen size for Unity Remote to use\n        public static string unityRemoteResolution\n        {\n            get { return GetConfigValue(\"UnityRemoteResolution\"); }\n            set { SetConfigValue(\"UnityRemoteResolution\", value); }\n        }\n\n        // Remote joystick input behavior for Unity Remote (use local / override with remote)\n        public static string unityRemoteJoystickSource\n        {\n            get { return GetConfigValue(\"UnityRemoteJoystickSource\"); }\n            set { SetConfigValue(\"UnityRemoteJoystickSource\", value); }\n        }\n\n        [System.Obsolete(@\"Use VersionControlSettings.mode instead.\")]\n        [StaticAccessor(\"GetVersionControlSettings()\", StaticAccessorType.Dot)]\n        public static extern string externalVersionControl\n        {\n            [NativeMethod(\"GetMode\")]\n            get;\n            [NativeMethod(\"SetMode\")]\n            set;\n        }\n\n        [FreeFunction(\"GetEditorSettings\")]\n        internal static extern EditorSettings GetEditorSettings();\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern SerializationMode serializationMode { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern LineEndingsMode lineEndingsForNewScripts { get; set; }\n\n        [Obsolete(\"EditorSettings.webSecurityEmulationEnabled is no longer supported, \" +\n            \"since the Unity Web Player is no longer supported by Unity.\")]\n        public static bool webSecurityEmulationEnabled\n        {\n            get { return false; }\n            set {}\n        }\n\n        [Obsolete(\"EditorSettings.webSecurityEmulationHostUrl is no longer supported, \" +\n            \"since the Unity Web Player is no longer supported by Unity.\")]\n        public static string webSecurityEmulationHostUrl\n        {\n            get { return \"\"; }\n            set {}\n        }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern EditorBehaviorMode defaultBehaviorMode { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern SceneAsset prefabRegularEnvironment { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern SceneAsset prefabUIEnvironment { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool prefabModeAllowAutoSave { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern SpritePackerMode spritePackerMode { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern int spritePackerPaddingPower { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        internal static extern Bc7TextureCompressor bc7TextureCompressor { get; set; }\n\n        [Obsolete(\"EditorSettings.etcTextureCompressorBehavior has been deprecated with the removal of support for ETC Legacy compression behavior.\", false)]\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern int etcTextureCompressorBehavior { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        internal static extern int etcTextureCompressorBehaviorInternal { [NativeMethod(\"GetEtcTextureCompressorBehavior\")] get; [NativeMethod(\"SetEtcTextureCompressorBehavior\")] set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern int etcTextureFastCompressor {[NativeMethod(\"GetEtcTextureFastCompressorNoOffset\")] get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern int etcTextureNormalCompressor {[NativeMethod(\"GetEtcTextureNormalCompressorNoOffset\")] get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern int etcTextureBestCompressor {[NativeMethod(\"GetEtcTextureBestCompressorNoOffset\")] get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool enableTextureStreamingInEditMode { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool enableTextureStreamingInPlayMode { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool asyncShaderCompilation { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static bool cachingShaderPreprocessor { get { return true; } set {} }\n\n        public static string[] projectGenerationUserExtensions\n        {\n            get\n            {\n                return Internal_ProjectGenerationUserExtensions\n                    .Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries).Select(s => s.TrimStart('.', '*'))\n                    .ToArray();\n            }\n            set { Internal_ProjectGenerationUserExtensions = string.Join(\";\", value); }\n        }\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public static string[] projectGenerationBuiltinExtensions\n        {\n            get { return new[] { \"cs\", \"uxml\", \"uss\", \"shader\", \"compute\", \"cginc\", \"hlsl\", \"glslinc\", \"template\", \"raytrace\" }; }\n        }\n\n        internal static extern string Internal_ProjectGenerationUserExtensions\n        {\n            [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"GetProjectGenerationIncludedExtensions\")]\n            get;\n            [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"SetProjectGenerationIncludedExtensions\")]\n            set;\n        }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern string projectGenerationRootNamespace { get; set; }\n\n        [StaticAccessor(\"GetEditorUserSettings()\", StaticAccessorType.Dot)]\n        private static extern string GetConfigValue(string name);\n\n        [StaticAccessor(\"GetEditorUserSettings()\", StaticAccessorType.Dot)]\n        private static extern void SetConfigValue(string name, string value);\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        internal static extern void SetEtcTextureCompressorLegacyBehavior();\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        internal static extern void SetEtcTextureCompressorDefaultBehavior();\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool useLegacyProbeSampleCount { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool shadowmaskStitching { get; set; }\n\n        [Obsolete(\"The disableCookiesInLightmapper setting is no longer supported. Cookies are always enabled in the Progressive Lightmapper.\", true)]\n        public static bool disableCookiesInLightmapper\n        {\n            get { return false; }\n            set {}\n        }\n\n        [Obsolete(\"The enableCookiesInLightmapper setting is no longer supported. Cookies are always enabled in the Progressive Lightmapper.\")]\n        public static bool enableCookiesInLightmapper\n        {\n            get { return true; }\n            set {}\n        }\n\n        [Obsolete(\"Bake with the Progressive Lightmapper.The backend that uses Enlighten to bake is obsolete.\", true)]\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool enableEnlightenBakedGI { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool enterPlayModeOptionsEnabled { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern EnterPlayModeOptions enterPlayModeOptions { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool serializeInlineMappingsOnOneLine { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern AssetPipelineMode assetPipelineMode { get; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern CacheServerMode cacheServerMode { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern AssetDatabase.RefreshImportMode refreshImportMode { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern string cacheServerEndpoint { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern string cacheServerNamespacePrefix { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool cacheServerEnableDownload { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool cacheServerEnableUpload { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool cacheServerEnableAuth { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool cacheServerEnableTls { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern CacheServerValidationMode cacheServerValidationMode { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern Int32 cacheServerDownloadBatchSize { get; set; }\n\n        public enum NamingScheme\n        {\n            SpaceParenthesis = 0,\n            Dot,\n            Underscore\n            // note: C++ code has more, but we don't want to expose them for Hierarchy naming\n        }\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern int gameObjectNamingDigits { get; set; }\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern NamingScheme gameObjectNamingScheme { get; set; }\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool assetNamingUsesSpace { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        internal static extern bool inspectorUseIMGUIDefaultInspector { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool referencedClipsExactNaming { get; set; }\n\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        public static extern bool forceAssetUnloadAndGCOnSceneLoad { get; set; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorUserBuildSettings.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing Object = UnityEngine.Object;\nusing Debug = UnityEngine.Debug;\nusing UnityEngine.Bindings;\nusing System;\nusing System.ComponentModel;\nusing System.Runtime.InteropServices;\nusing UnityEditor.Build;\nusing UnityEditor.Build.Profile;\nusing UnityEngine;\nusing UnityEditor.Modules;\nusing UnityEngine.Assertions;\n\nnamespace UnityEditor\n{\n    [NativeType(Header = \"Runtime/Serialize/BuildTarget.h\")]\n    public enum StandaloneBuildSubtarget\n    {\n        // *undocumented*\n        [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]\n        Default = 0,\n        Player = 2,\n        Server = 1\n    }\n\n    namespace Build\n    {\n        [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n        public enum OverrideTextureCompression\n        {\n            NoOverride = 0,\n            ForceUncompressed = 1,\n            ForceFastCompressor = 2,\n            ForceNoCrunchCompression = 3,\n        }\n\n        [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n        public enum Il2CppCodeGeneration\n        {\n            OptimizeSpeed = 0,\n            OptimizeSize = 1\n        }\n    }\n\n    /// Target PS4 build platform.\n    ///\n    /// SA: EditorUserBuildSettings.ps4BuildSubtarget.\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    public enum PS4BuildSubtarget\n    {\n        /// Build package that it's hosted on the PC\n        /// SA: EditorUserBuildSettings.ps4BuildSubtarget.\n        PCHosted = 0,\n        /// Build a package suited for TestKit testing\n        /// SA: EditorUserBuildSettings.ps4BuildSubtarget.\n        Package = 1,\n        Iso = 2,\n        GP4Project = 3,\n    }\n\n\n    /// Target PS4 build Hardware Target.\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    public enum PS4HardwareTarget\n    {\n        /// Target only Base hardware (works identically on Neo hardware)\n        BaseOnly = 0,\n\n        /// Obsolete.  Use PS4ProAndBase instead.\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"Enum member PS4HardwareTarget.NeoAndBase has been deprecated. Use PS4HardwareTarget.ProAndBase instead (UnityUpgradable) -> ProAndBase\", true)]\n        NeoAndBase = 1,\n\n        /// Target PS4 Pro hardware, also must work on Base hardware\n        ProAndBase = 1,\n    }\n\n\n    // Target Xbox build type.\n    [NativeType(Header = \"Runtime/Serialize/BuildTarget.h\")]\n    public enum XboxBuildSubtarget\n    {\n        // Development player\n        Development = 0,\n        // Master player (submission-proof)\n        Master = 1,\n        // Debug player (for building with source code)\n        Debug = 2,\n    }\n\n    [NativeType(Header = \"Runtime/Serialize/BuildTarget.h\")]\n    [Obsolete(\"The XDK Xbox One platform was removed in 2021.1\", true)]\n    public enum XboxOneDeployMethod\n    {\n        // copies files to the kit\n        Push = 0,\n        // PC network share loose files to the kit\n        RunFromPC = 2,\n        // Build Xbox One Package\n        Package = 3,\n        // Build Xbox One Package - if installed only install launch chunk for testing\n        PackageStreaming = 4,\n    }\n\n    [NativeType(Header = \"Runtime/Serialize/BuildTarget.h\")]\n    [Obsolete(\"The XDK Xbox One platform was removed in 2021.1\", false)]\n    public enum XboxOneDeployDrive\n    {\n        Default = 0,\n        Retail = 1,\n        Development = 2,\n        Ext1 = 3,\n        Ext2 = 4,\n        Ext3 = 5,\n        Ext4 = 6,\n        Ext5 = 7,\n        Ext6 = 8,\n        Ext7 = 9\n    }\n\n    [EditorBrowsable(EditorBrowsableState.Never)]\n    [Obsolete(\"UnityEditor.AndroidBuildSubtarget has been deprecated. Use UnityEditor.MobileTextureSubtarget instead (UnityUpgradable)\", true)]\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    public enum AndroidBuildSubtarget\n    {\n        Generic = -1,\n        DXT = -1,\n        PVRTC = -1,\n        ATC = -1,\n        ETC = -1,\n        ETC2 = -1,\n        ASTC = -1,\n    }\n\n    [Obsolete(\"UnityEditor.AndroidCreateSymbols has been deprecated. Use UnityEditor.Android.DebugSymbols.level instead\")]\n    public enum AndroidCreateSymbols\n    {\n        Disabled,\n        Public,\n        Debugging\n    }\n\n    // Target texture build platform.\n    [NativeType(Header = \"Runtime/Serialize/BuildTarget.h\")]\n    public enum MobileTextureSubtarget\n    {\n        // Don't override texture compression.\n        Generic = 0,\n        // S3 texture compression, nonspecific to DXT variant. Supported on devices running Nvidia Tegra2 platform, including Motorala Xoom, Motorola Atrix, Droid Bionic, and others.\n        DXT = 1,\n        // PowerVR texture compression. Available in devices running PowerVR SGX530/540 GPU, such as Motorola DROID series; Samsung Galaxy S, Nexus S, and Galaxy Tab; and others.\n        [System.Obsolete(\"Texture compression format PVRTC has been deprecated and will be removed in a future release\")]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        PVRTC = 2,\n        [System.Obsolete(\"UnityEditor.MobileTextureSubtarget.ATC has been deprecated. Use UnityEditor.MobileTextureSubtarget.ETC instead (UnityUpgradable) -> UnityEditor.MobileTextureSubtarget.ETC\", true)]\n        ATC = 3,\n        // ETC1 texture compression (or RGBA16 for textures with alpha), supported by all devices.\n        ETC = 4,\n        // ETC2/EAC texture compression, supported by GLES 3.0 devices\n        ETC2 = 5,\n        // Adaptive Scalable Texture Compression\n        ASTC = 6,\n    }\n\n    [Obsolete(\"AndroidETC2Fallback is obsolete and has no effect. It will be removed in a subsequent Unity release.\")]\n    public enum AndroidETC2Fallback\n    {\n        // 32-bit uncompressed\n        Quality32Bit = 0,\n        // 16-bit uncompressed\n        Quality16Bit = 1,\n        // 32-bit uncompressed, downscaled 2x\n        Quality32BitDownscaled = 2,\n    }\n\n    // Target texture build platform.\n    [NativeType(Header = \"Runtime/Serialize/BuildTarget.h\")]\n    public enum WebGLTextureSubtarget\n    {\n        // Don't override texture compression.\n        Generic = 0,\n        // S3 texture compression, nonspecific to DXT variant, supported by desktop browsers\n        DXT = 1,\n        // ETC2/EAC texture compression, supported by mobile devices\n        ETC2 = 3,\n        // Adaptive Scalable Texture Compression, supported by mobile devices\n        ASTC = 4,\n    }\n\n    // Client browser type\n    [NativeType(Header = \"Runtime/Serialize/BuildTarget.h\")]\n    public enum WebGLClientBrowserType\n    {\n        Default = 0,\n        Edge = 1,\n        Safari = 2,\n        Firefox = 3,\n        Chrome = 4,\n        Chromium = 5\n    }\n\n     // Client browser type\n     [NativeType(Header = \"Runtime/Serialize/BuildTarget.h\")]\n     internal enum WebGLClientPlatform\n     {\n         Desktop = 0,\n         Android = 1,\n         iOS = 2\n     }\n\n    [NativeType(Header = \"Runtime/Serialize/BuildTarget.h\")]\n    [Obsolete(\"WSASubtarget is obsolete and has no effect. It will be removed in a subsequent Unity release.\")]\n    public enum WSASubtarget\n    {\n        AnyDevice = 0,\n        PC = 1,\n        Mobile = 2,\n        HoloLens = 3\n    }\n\n    // *undocumented*\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    public enum WSASDK\n    {\n        // *undocumented*\n        SDK80 = 0,\n        // *undocumented*\n        SDK81 = 1,\n        // *undocumented*\n        PhoneSDK81 = 2,\n        // *undocumented*\n        UniversalSDK81 = 3,\n        // *undocumented*\n        UWP = 4,\n    }\n\n    // *undocumented*\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    public enum WSAUWPBuildType\n    {\n        XAML = 0,\n        D3D = 1,\n        ExecutableOnly = 2,\n    }\n\n    // *undocumented*\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    public enum WSABuildAndRunDeployTarget\n    {\n        /// *undocumented*\n        LocalMachine = 0,\n        /// *undocumented*\n        [System.Obsolete(\"UnityEditor.WSABuildAndRunDeployTarget.WindowsPhone is obsolete.\", true)]\n        WindowsPhone = 1,\n        /// *undocumented*\n        DevicePortal = 2\n    }\n\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    public enum WindowsBuildAndRunDeployTarget\n    {\n        LocalMachine = 0,\n        DevicePortal = 2\n    }\n\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    public enum WSABuildType\n    {\n        Debug = 0,\n        Release = 1,\n        Master = 2\n    }\n\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    public enum XcodeBuildConfig\n    {\n        Debug = 0,\n        Release = 1,\n    }\n\n    [Obsolete(\"iOSBuildType is obsolete. Use XcodeBuildConfig instead (UnityUpgradable) -> XcodeBuildConfig\", true)]\n    public enum iOSBuildType\n    {\n        Debug = 0,\n        Release = 1,\n    }\n\n    [NativeType(Header = \"Runtime/Serialize/BuildTarget.h\")]\n    internal enum Compression\n    {\n        None = 0,\n        Lz4 = 2,\n        Lz4HC = 3,\n    }\n\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    public enum AndroidBuildSystem\n    {\n        [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]\n        [Obsolete(\"Internal build system has been deprecated. Use Gradle instead (UnityUpgradable) -> UnityEditor.AndroidBuildSystem.Gradle\", true)]\n        Internal = 0,\n        Gradle = 1,\n        [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]\n        [Obsolete(\"ADT/eclipse project export for Android is no longer supported - please use Gradle export instead\", true)]\n        ADT = 2,\n        /// *undocumented*\n        VisualStudio = 3,\n    }\n\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    public enum AndroidBuildType\n    {\n        Debug = 0,\n        Development = 1,\n        Release = 2,\n    }\n\n    // *undocumented*\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    internal enum AppleBuildAndRunType\n    {\n        Xcode = 0,\n        Xcodebuild = 1,\n        iOSDeploy = 2,\n    }\n\n    // We used this value to control if minification is enabled and what tool to use separately for release and debug builds.\n    // With the Android Gradle Plugin changes in 3.4 the tool which will be used is the same for release and debug now\n    [Obsolete(\"AndroidMinification enum is obsolete.\", true)]\n    public enum AndroidMinification\n    {\n        None = 0,\n        Proguard = 1,\n        Gradle = 2,\n    }\n\n    // *undocumented*\n    [NativeType(Header = \"Editor/Src/EditorOnlyPlayerSettings.h\")]\n    internal struct SwitchShaderCompilerConfig\n    {\n        internal int glslcDebugLevel;\n        internal string debugInfoOutputPath;\n        internal bool triggerGraphicsDebuggersConfigUpdate;\n    }\n\n    // *undocumented*\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    public enum SwitchRomCompressionType\n    {\n        None = 0,\n        Lz4 = 1,\n    }\n\n    [NativeHeader(\"Editor/Src/EditorUserBuildSettings.h\")]\n    [StaticAccessor(\"GetEditorUserBuildSettings()\", StaticAccessorType.Dot)]\n    public partial class EditorUserBuildSettings : Object\n    {\n        internal const string kSettingArchitecture = \"Architecture\";\n        private EditorUserBuildSettings() {}\n\n        internal static extern AppleBuildAndRunType appleBuildAndRunType { get; set; }\n        internal static extern string appleDeviceId { get; set; }\n\n        // The currently selected build target group.\n        public static extern BuildTargetGroup selectedBuildTargetGroup { get; set; }\n\n        [NativeMethod(\"GetSelectedSubTargetFor\")]\n        internal static extern int GetSelectedSubtargetFor(BuildTarget target);\n\n        [NativeMethod(\"SetSelectedSubTargetFor\")]\n        internal static extern void SetSelectedSubtargetFor(BuildTarget target, int subtarget);\n\n        [NativeMethod(\"GetActiveSubTargetFor\")]\n        internal static extern int GetActiveSubtargetFor(BuildTarget target);\n\n        public static BuildTarget selectedStandaloneTarget\n        {\n            get { return internal_SelectedStandaloneTarget; }\n            set\n            {\n                string platformName = BuildPipeline.GetBuildTargetName(value);\n                var architecture = GetPlatformSettings(platformName, kSettingArchitecture).ToLower();\n                switch (value)\n                {\n                    case BuildTarget.StandaloneWindows:\n                        if (architecture != \"x86\")\n                            SetPlatformSettings(platformName, kSettingArchitecture, OSArchitecture.x86.ToString());\n                        break;\n                    case BuildTarget.StandaloneWindows64:\n                        if (architecture != \"x64\" && architecture != \"arm64\")\n                            SetPlatformSettings(platformName, kSettingArchitecture, OSArchitecture.x64.ToString());\n                        break;\n                }\n\n                internal_SelectedStandaloneTarget = value;\n            }\n        }\n\n        private static extern BuildTarget internal_SelectedStandaloneTarget\n        {\n            [NativeMethod(\"GetSelectedStandaloneTarget\")]\n            get;\n            [NativeMethod(\"SetSelectedStandaloneTargetFromBindings\")]\n            set;\n        }\n\n        internal static extern StandaloneBuildSubtarget selectedStandaloneBuildSubtarget\n        {\n            [NativeMethod(\"GetSelectedStandaloneBuildSubtarget\")]\n            get;\n            [NativeMethod(\"SetSelectedStandaloneBuildSubtarget\")]\n            set;\n        }\n\n        public static extern StandaloneBuildSubtarget standaloneBuildSubtarget\n        {\n            [NativeMethod(\"GetActiveStandaloneBuildSubtarget\")]\n            get;\n            [NativeMethod(\"SetActiveStandaloneBuildSubtarget\")]\n            set;\n        }\n\n        ///PS4 Build Subtarget\n        public static extern PS4BuildSubtarget ps4BuildSubtarget\n        {\n            [NativeMethod(\"GetSelectedPS4BuildSubtarget\")]\n            get;\n            [NativeMethod(\"SetSelectedPS4BuildSubtarget\")]\n            set;\n        }\n\n\n        ///PS4 Build Hardware Target\n        public static extern PS4HardwareTarget ps4HardwareTarget\n        {\n            [NativeMethod(\"GetPS4HardwareTarget\")]\n            get;\n            [NativeMethod(\"SetPS4HardwareTarget\")]\n            set;\n        }\n\n\n        // Are null references actively checked?\n        public static extern bool explicitNullChecks { get; set; }\n\n        // Are divide by zeros actively checked?\n        public static extern bool explicitDivideByZeroChecks { get; set; }\n\n        public static extern bool explicitArrayBoundsChecks { get; set; }\n\n        // Should we write out submission materials when building?\n        public static extern bool needSubmissionMaterials { get; set; }\n\n        [Obsolete(\"EditorUserBuildSettings.compressWithPsArc is obsolete and has no effect. It will be removed in a subsequent Unity release.\")]\n        public static bool compressWithPsArc { get => false; set {} }\n\n        // Should we force an install on the build package, even if there are validation errors\n        public static extern bool forceInstallation { get; set; }\n\n        // Should we move the package to the Bluray disc outer edge (larger ISO, but faster loading)\n        public static extern bool movePackageToDiscOuterEdge { get; set; }\n\n        // Should we compress files added to the package file\n        public static extern bool compressFilesInPackage { get; set; }\n\n        // Headless Mode\n        [Obsolete(\"Use EditorUserBuildSettings.standaloneBuildSubtarget instead.\")]\n        public static bool enableHeadlessMode\n        {\n            get => standaloneBuildSubtarget == StandaloneBuildSubtarget.Server;\n            set => standaloneBuildSubtarget = value ? StandaloneBuildSubtarget.Server : StandaloneBuildSubtarget.Player;\n        }\n\n\n        // Scripts only build\n        public static extern bool buildScriptsOnly { get; set; }\n\n        // 0..X levels are all considered part of the launch set of streaming install chunks\n        [Obsolete(\"The XDK Xbox One platform was removed in 2021.1\", true)]\n        public static extern int streamingInstallLaunchRange { get; set; }\n\n        //XboxOne Build subtarget\n        [Obsolete(\"The XDK Xbox One platform was removed in 2021.1\", true)]\n        public static extern XboxBuildSubtarget xboxBuildSubtarget\n        {\n            [NativeMethod(\"GetSelectedXboxBuildSubtarget\")]\n            get;\n            [NativeMethod(\"SetSelectedXboxBuildSubtarget\")]\n            set;\n        }\n\n        //selected Xbox One Deploy Method\n        [Obsolete(\"The XDK Xbox One platform was removed in 2021.1\", true)]\n        public static extern XboxOneDeployMethod xboxOneDeployMethod\n        {\n            [NativeMethod(\"GetSelectedXboxOneDeployMethod\")]\n            get;\n            [NativeMethod(\"SetSelectedXboxOneDeployMethod\")]\n            set;\n        }\n\n        //selected Xbox One Deployment Drive\n        [Obsolete(\"The XDK Xbox One platform was removed in 2021.1\", false)]\n        public static extern XboxOneDeployDrive xboxOneDeployDrive\n        {\n            [NativeMethod(\"GetSelectedXboxOneDeployDrive\")]\n            get;\n            [NativeMethod(\"SetSelectedXboxOneDeployDrive\")]\n            set;\n        }\n\n\n        [Obsolete(\"xboxOneUsername is deprecated, it is unnecessary and non-functional.\")]\n        public static  string xboxOneUsername { get; set; }\n\n        [Obsolete(\"xboxOneNetworkSharePath is deprecated, it is unnecessary and non-functional.\")]\n        public static  string xboxOneNetworkSharePath { get; set; }\n\n\n        // Transitive property used when adding debug ports to the\n        // manifest for our test systems. This is required to\n        // allow the XboxOne to open the required ports in its\n        // manifest.\n        [Obsolete(\"The XDK Xbox One platform was removed in 2021.1\", false)]\n        public static string xboxOneAdditionalDebugPorts { get; set; }\n        [Obsolete(\"The XDK Xbox One platform was removed in 2021.1\", false)]\n        public static bool xboxOneRebootIfDeployFailsAndRetry { get; set; }\n\n        // Android platform options.\n        public static extern MobileTextureSubtarget androidBuildSubtarget\n        {\n            [NativeMethod(\"GetSelectedAndroidBuildTextureSubtarget\")]\n            get;\n            [NativeMethod(\"SetSelectedAndroidBuildSubtarget\")]\n            set;\n        }\n\n        // WebGL platform options.\n        public static extern WebGLTextureSubtarget webGLBuildSubtarget\n        {\n            [NativeMethod(\"GetSelectedWebGLBuildTextureSubtarget\")]\n            get;\n            [NativeMethod(\"SetSelectedWebGLBuildSubtarget\")]\n            set;\n        }\n\n        public static extern string webGLClientBrowserPath { get; set; }\n\n        public static extern WebGLClientBrowserType webGLClientBrowserType\n        {\n            [NativeMethod(\"GetWebGLClientBrowserType\")]\n            get;\n            [NativeMethod(\"SetWebGLClientBrowserType\")]\n            set;\n        }\n        internal static extern WebGLClientPlatform webGLClientPlatform\n        {\n            [NativeMethod(\"GetWebGLClientPlatform\")]\n            get;\n            [NativeMethod(\"SetWebGLClientPlatform\")]\n            set;\n        }\n\n        //Compression set/get methods for the map containing type for BuildTargetGroup\n        internal static Compression GetCompressionType(BuildTargetGroup targetGroup)\n        {\n            return (Compression)GetCompressionTypeInternal(targetGroup);\n        }\n\n        [NativeMethod(\"GetSelectedCompressionType\")]\n        private static extern int GetCompressionTypeInternal(BuildTargetGroup targetGroup);\n\n        internal static void SetCompressionType(BuildTargetGroup targetGroup, Compression type)\n        {\n            SetCompressionTypeInternal(targetGroup, (int)type);\n        }\n\n        [NativeMethod(\"SetSelectedCompressionType\")]\n        private static extern void SetCompressionTypeInternal(BuildTargetGroup targetGroup, int type);\n\n        [Obsolete(\"androidETC2Fallback is obsolete and has no effect. It will be removed in a subsequent Unity release.\")]\n        public static AndroidETC2Fallback androidETC2Fallback\n        {\n            get { return AndroidETC2Fallback.Quality32Bit; }\n            set { }\n        }\n\n        public static extern AndroidBuildSystem androidBuildSystem { get; set; }\n\n        public static extern AndroidBuildType androidBuildType { get; set; }\n\n        [Obsolete(\"androidUseLegacySdkTools has been deprecated. It does not have any effect.\")]\n        public static extern bool androidUseLegacySdkTools { get; set; }\n\n        [Obsolete(\"androidCreateSymbolsZip has been deprecated. Use UnityEditor.Android.UserBuildSettings.DebugSymbols.level property\")]\n        public static bool androidCreateSymbolsZip\n        {\n            get => androidCreateSymbols != AndroidCreateSymbols.Disabled;\n            set => androidCreateSymbols = value ? AndroidCreateSymbols.Public : AndroidCreateSymbols.Disabled;\n        }\n\n        [Obsolete(\"androidCreateSymbols has been deprecated. Use UnityEditor.Android.UserBuildSettings.DebugSymbols.level property\")]\n        public static extern AndroidCreateSymbols androidCreateSymbols { get; set; }\n\n        // *undocumented*\n        // NOTE: This setting should probably not be a part of the public API as is. Atm it is used by playmode tests\n        //  and applied during build post-processing. We will however move towards separating building and launching\n        //  which makes it unclear when connections should be attempted. In the future, the DeploymentTargets\n        //  API will most likely support connecting to named external devices, which might make this setting obsolete.\n        internal static extern string androidDeviceSocketAddress { get; set; }\n\n        internal static extern string androidCurrentDeploymentTargetId { get; set; }\n\n        [Obsolete(\"EditorUserBuildSettings.wsaSubtarget is obsolete and has no effect. It will be removed in a subsequent Unity release.\")]\n        public static WSASubtarget wsaSubtarget\n        {\n            get => WSASubtarget.AnyDevice;\n            set {}\n        }\n\n        [Obsolete(\"EditorUserBuildSettings.wsaSDK is obsolete and has no effect.It will be removed in a subsequent Unity release.\")]\n        public static extern WSASDK wsaSDK\n        {\n            [NativeMethod(\"GetSelectedWSASDK\")]\n            get;\n            [NativeMethod(\"SetSelectedWSASDK\")]\n            set;\n        }\n\n\n        // *undocumented*\n        public static extern WSAUWPBuildType wsaUWPBuildType\n        {\n            [NativeMethod(\"GetSelectedWSAUWPBuildType\")]\n            get;\n            [NativeMethod(\"SetSelectedWSAUWPBuildType\")]\n            set;\n        }\n\n\n        public static extern string wsaUWPSDK\n        {\n            [NativeMethod(\"GetSelectedWSAUWPSDK\")]\n            get;\n            [NativeMethod(\"SetSelectedWSAUWPSDK\")]\n            set;\n        }\n\n        public static extern string wsaMinUWPSDK\n        {\n            [NativeMethod(\"GetSelectedWSAMinUWPSDK\")]\n            get;\n            [NativeMethod(\"SetSelectedWSAMinUWPSDK\")]\n            set;\n        }\n\n        public static extern string wsaArchitecture\n        {\n            [NativeMethod(\"GetSelectedWSAArchitecture\")]\n            get;\n            [NativeMethod(\"SetSelectedWSAArchitecture\")]\n            set;\n        }\n\n        public static extern string wsaUWPVisualStudioVersion\n        {\n            [NativeMethod(\"GetSelectedWSAUWPVSVersion\")]\n            get;\n            [NativeMethod(\"SetSelectedWSAUWPVSVersion\")]\n            set;\n        }\n\n        public static extern string windowsDevicePortalAddress\n        {\n            [NativeMethod(\"GetWindowsDevicePortalAddress\")]\n            get;\n            [NativeMethod(\"SetWindowsDevicePortalAddress\")]\n            set;\n        }\n\n        internal static string EncodeBase64(string plainText)\n        {\n            if (plainText == null)\n            {\n                plainText = string.Empty;\n            }\n\n            var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);\n            return Convert.ToBase64String(plainTextBytes);\n        }\n\n        internal static string DecodeBase64(string base64Text)\n        {\n            if (base64Text == null)\n            {\n                base64Text = string.Empty;\n            }\n\n            try\n            {\n                var base64EncodedBytes = System.Convert.FromBase64String(base64Text);\n                return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);\n            }\n            catch (FormatException)\n            {\n                return string.Empty;\n            }\n        }\n\n        public static extern string windowsDevicePortalUsername\n        {\n            [NativeMethod(\"GetWindowsDevicePortalUsername\")]\n            get;\n            [NativeMethod(\"SetWindowsDevicePortalUsername\")]\n            set;\n        }\n\n        // WDP password is not to be saved with other settings and only stored in memory until Editor is closed\n        private static string internal_windowsDevicePortalPassword;\n\n        public static string windowsDevicePortalPassword\n        {\n            get\n            {\n                var profile = BuildProfileContext.GetActiveOrClassicBuildProfile(BuildTarget.NoTarget, StandaloneBuildSubtarget.Default, SharedPlatformSettings.k_SettingWindowsDevicePortalPassword);\n                if (profile != null)\n                {\n                    var settings = profile.platformBuildProfile;\n                    return settings.GetSharedSetting(SharedPlatformSettings.k_SettingWindowsDevicePortalPassword);\n\n                }\n                return DecodeBase64(internal_windowsDevicePortalPassword);\n            }\n\n            set\n            {\n                var profile = BuildProfileContext.GetActiveOrClassicBuildProfile(BuildTarget.NoTarget, StandaloneBuildSubtarget.Default, SharedPlatformSettings.k_SettingWindowsDevicePortalPassword);\n                if (profile == null)\n                {\n                    internal_windowsDevicePortalPassword = EncodeBase64(value);\n                }\n                else\n                {\n                    if (profile.buildTarget == BuildTarget.NoTarget)\n                    {\n                        var sharedPlatformSettings = profile.platformBuildProfile as SharedPlatformSettings;\n                        // This will sync the value to applicable classic profiles through the shared profile.\n                        sharedPlatformSettings.windowsDevicePortalPassword = value;\n\n                    }\n                    else\n                    {\n                        var settings = profile.platformBuildProfile;\n                        // SetSharedSetting() is used to avoid having to cast the active custom profile to platform profiles.\n                        // This only changes the value in the active custom profile and has no effect on syncing.\n                        settings.SetSharedSetting(SharedPlatformSettings.k_SettingWindowsDevicePortalPassword, value);\n                    }\n                }\n            }\n        }\n\n        // *undocumented*\n        public static extern WSABuildAndRunDeployTarget wsaBuildAndRunDeployTarget\n        {\n            [NativeMethod(\"GetSelectedWSABuildAndRunDeployTarget\")]\n            get;\n            [NativeMethod(\"SetSelectedWSABuildAndRunDeployTarget\")]\n            set;\n        }\n\n        public static extern WindowsBuildAndRunDeployTarget windowsBuildAndRunDeployTarget\n        {\n            [NativeMethod(\"GetSelectedWindowsBuildAndRunDeployTarget\")]\n            get;\n            [NativeMethod(\"SetSelectedWindowsBuildAndRunDeployTarget\")]\n            set;\n        }\n        public static extern int overrideMaxTextureSize { get; set; }\n        public static extern Build.OverrideTextureCompression overrideTextureCompression { get; set; }\n\n        // The currently active build target.\n        public static extern BuildTarget activeBuildTarget { get; }\n\n        private static extern GUID GetInternalActivePlatformGuid();\n\n        // Internal setter only to be used for testing.\n        internal static extern void SetActivePlatformGuid(GUID platformId);\n\n        internal static GUID activePlatformGuid\n        {\n            get\n            {\n                // The following code is addressing the fact that the actually selected build target\n                // and the stored GUID might disagree. This can happen when a platform is not available\n                // in the editor(for example a user selects a platform, checks in that setting, another\n                // one pulls the project but does not have the platform installed).\n                GUID activePlatformGuid = GetInternalActivePlatformGuid();\n                GUID basePlatformGuid = BuildTargetDiscovery.GetBasePlatformGUIDFromBuildTarget(EditorUserBuildSettingsUtils.CalculateActiveNamedBuildTarget(), activeBuildTarget);\n\n                if (activePlatformGuid.Empty())\n                    return basePlatformGuid;\n\n                // Account for derived platforms (the active platform is different from its base platform).\n                // Jira https://jira.unity3d.com/browse/PLAT-9234\n                if (activePlatformGuid != basePlatformGuid)\n                {\n                    // This logic will make sure that the base platform gets selected if the encountered platform\n                    // is a derived one and the platform support for the derived platform is not available to\n                    // align with the behavior of the editor before introducing derived platforms.\n                    var module = ModuleManager.FindPlatformSupportModule(activePlatformGuid);\n                    if (module is IDerivedBuildTargetProvider)\n                        return activePlatformGuid;\n                    return basePlatformGuid;\n                }\n\n                return activePlatformGuid;\n            }\n        }\n\n        [NativeMethod(\"SwitchActiveBuildTargetGuid\")]\n        private static extern bool SwitchActiveBuildTargetAndSubTargetGuid(GUID platformGuid, BuildTarget target, int subtarget);\n        internal static bool SwitchActiveBuildTargetGuid(BuildProfile profile)\n        {\n            var platformGuid = profile.platformGuid;\n            // Account for derived platforms.\n            // Jira https://jira.unity3d.com/browse/PLAT-9234\n            // The editor triggers recompilation on a build target or subtarget change already. Both of these values\n            // will not change by design when switching between a derived platform and its base platform or between\n            // derived platforms of the same baseplatform so we need to trigger a rebuild if the GUID changes and\n            // the support module stays the same.\n            if (platformGuid != activePlatformGuid && ModuleManager.FindPlatformSupportModule(platformGuid) == ModuleManager.FindPlatformSupportModule(activePlatformGuid))\n            {\n                BuildProfileModuleUtil.RequestScriptCompilation(null);\n            }\n\n            var (buildTargetFromGuid, subTargetFromGuid) = BuildTargetDiscovery.GetBuildTargetAndSubtargetFromGUID(platformGuid);\n            int activeSubtarget = (int)subTargetFromGuid;\n\n            //This will either get the base or derived platform to cast to correct baseplatformsetting type.\n            bool result = BuildTargetDiscovery.TryGetBuildTarget(profile.buildTarget, out var buildTarget);\n            if (result && buildTarget != null)\n            {\n                var subtarget = (buildTarget.TextureSubtargetPlatformProperties == null) ? -1 :\n                    buildTarget.TextureSubtargetPlatformProperties.GetSubtargetFromPlatformSettings(profile.platformBuildProfile);\n                if (subtarget != -1) activeSubtarget = subtarget;\n            }\n\n\n            return SwitchActiveBuildTargetAndSubTargetGuid(platformGuid, buildTargetFromGuid, activeSubtarget);\n        }\n\n        // The currently active build target.\n        internal static extern BuildTargetGroup activeBuildTargetGroup { get; }\n\n        [NativeMethod(\"SwitchActiveBuildTargetSync\")]\n        internal static extern bool SwitchActiveBuildTargetAndSubtarget(BuildTarget target, int subtarget);\n        public static bool SwitchActiveBuildTarget(BuildTargetGroup targetGroup, BuildTarget target)\n            => SwitchActiveBuildTargetAndSubtarget(target, EditorUserBuildSettings.GetActiveSubtargetFor(target));\n\n        [NativeMethod(\"SwitchActiveBuildTargetAsync\")]\n        internal static extern bool SwitchActiveBuildTargetAndSubtargetAsync(BuildTarget target, int subtarget);\n        public static bool SwitchActiveBuildTargetAsync(BuildTargetGroup targetGroup, BuildTarget target)\n            => SwitchActiveBuildTargetAndSubtargetAsync(target, EditorUserBuildSettings.GetActiveSubtargetFor(target));\n\n        public static bool SwitchActiveBuildTarget(NamedBuildTarget namedBuildTarget, BuildTarget target)\n            => BuildPlatforms.instance.BuildPlatformFromNamedBuildTarget(namedBuildTarget).SetActive(target);\n\n        // This is used by tests -- note that it does tell the editor that current platform is X, without\n        // validating if support for it is installed. However it does not do things like script recompile\n        // or domain reload -- generally only useful for asset import testing.\n        [NativeMethod(\"SwitchActiveBuildTargetSyncNoCheck\")]\n        internal static extern bool SwitchActiveBuildTargetAndSubtargetNoCheck(BuildTarget target, int subtarget);\n        internal static bool SwitchActiveBuildTargetNoCheck(BuildTarget target)\n            => SwitchActiveBuildTargetAndSubtargetNoCheck(target, EditorUserBuildSettings.GetActiveSubtargetFor(target));\n\n        // DEFINE directives for the compiler.\n        public static extern string[] activeScriptCompilationDefines\n        {\n            [NativeMethod(\"GetActiveScriptCompilationDefinesBindingMethod\")]\n            get;\n        }\n\n        // Get the current location for the build.\n        public static extern string GetBuildLocation(BuildTarget target);\n\n        // Set a new location for the build.\n        public static extern void SetBuildLocation(BuildTarget target, string location);\n\n        public static void SetPlatformSettings(string platformName, string name, string value)\n        {\n            string buildTargetGroup = BuildPipeline.GetBuildTargetGroupName(BuildPipeline.GetBuildTargetByName(platformName));\n            SetPlatformSettings(buildTargetGroup, platformName, name, value);\n        }\n\n        public static extern void SetPlatformSettings(string buildTargetGroup, string buildTarget, string name, string value);\n\n        public static string GetPlatformSettings(string platformName, string name)\n        {\n            string buildTargetGroup = BuildPipeline.GetBuildTargetGroupName(BuildPipeline.GetBuildTargetByName(platformName));\n            return GetPlatformSettings(buildTargetGroup, platformName, name);\n        }\n\n        public static extern string GetPlatformSettings(string buildTargetGroup, string platformName, string name);\n\n        // Enables a development build.\n        public static extern bool development { get; set; }\n\n        [Obsolete(\"Use PlayerSettings.SetIl2CppCodeGeneration and PlayerSettings.GetIl2CppCodeGeneration instead.\", true)]\n        public static Build.Il2CppCodeGeneration il2CppCodeGeneration\n        {\n            get { return Build.Il2CppCodeGeneration.OptimizeSpeed; }\n            set { Debug.LogWarning(\"EditorUserBuildSettings.il2CppCodeGeneration is obsolete. Please use PlayerSettings.SetIl2CppCodeGeneration and PlayerSettings.GetIl2CppCodeGeneration instead.\" ); }\n        }\n\n        [Obsolete(\"Building with pre-built Engine option is no longer supported.\", true)]\n        public static bool webGLUsePreBuiltUnityEngine\n        {\n            get { return false; }\n            set {}\n        }\n\n        // Start the player with a connection to the profiler.\n        public static extern bool connectProfiler { get; set; }\n\n        // Build the player with deep profiler support.\n        public static extern bool buildWithDeepProfilingSupport { get; set; }\n\n        // Enable source-level debuggers to connect.\n        public static extern bool allowDebugging { get; set; }\n\n        // Wait for player connection on start\n        public static extern bool waitForPlayerConnection { get; set; }\n\n        // Export as Android Google Project instead of building it\n        public static extern bool exportAsGoogleAndroidProject { get; set; }\n\n        // Build Google Play App Bundle\n        public static extern bool buildAppBundle { get; set; }\n\n        // Symlink runtime libraries with an iOS Xcode project.\n        [Obsolete(\"EditorUserBuildSettings.symlinkLibraries is obsolete. Use EditorUserBuildSettings.symlinkSources instead (UnityUpgradable) -> [UnityEditor] EditorUserBuildSettings.symlinkSources\", false)]\n\n        public static bool symlinkLibraries\n        {\n            get => symlinkSources;\n            set => symlinkSources = value;\n        }\n\n        public static extern bool symlinkSources { get; set; }\n\n        // Symlink trampoline for iOS Xcode project.\n        internal static extern bool symlinkTrampoline { get; set; }\n\n\n        public static extern XcodeBuildConfig iOSXcodeBuildConfig\n        {\n            [NativeMethod(\"GetIOSXcodeBuildConfig\")] get;\n            [NativeMethod(\"SetIOSXcodeBuildConfig\")] set;\n        }\n        public static extern XcodeBuildConfig macOSXcodeBuildConfig\n        {\n            [NativeMethod(\"GetMacOSXcodeBuildConfig\")] get;\n            [NativeMethod(\"SetMacOSXcodeBuildConfig\")] set;\n        }\n\n        [Obsolete(\"iOSBuildConfigType is obsolete. Use iOSXcodeBuildConfig instead (UnityUpgradable) -> iOSXcodeBuildConfig\", true)]\n        public static iOSBuildType iOSBuildConfigType\n        {\n            // note that the actual values of iOSBuildType and XcodeBuildConfig agree\n            get => (iOSBuildType)iOSXcodeBuildConfig;\n            set => iOSXcodeBuildConfig = (XcodeBuildConfig)value;\n        }\n\n        // Create a .nsp ROM file out of the loose-files .nspd folder\n        public static extern bool switchCreateRomFile\n        {\n            [NativeMethod(\"GetCreateRomFileForSwitch\")]\n            get;\n            [NativeMethod(\"SetCreateRomFileForSwitch\")]\n            set;\n        }\n\n        public static extern bool switchEnableRomCompression\n        {\n            [NativeMethod(\"GetEnableRomCompressionForSwitch\")]\n            get;\n            [NativeMethod(\"SetEnableRomCompressionForSwitch\")]\n            set;\n        }\n\n        public static extern bool switchSaveADF\n        {\n            [NativeMethod(\"GetSaveADFForSwitch\")]\n            get;\n            [NativeMethod(\"SetSaveADFForSwitch\")]\n            set;\n        }\n\n        public static extern SwitchRomCompressionType switchRomCompressionType\n        {\n            [NativeMethod(\"GetRomCompressionTypeForSwitch\")]\n            get;\n            [NativeMethod(\"SetRomCompressionTypeForSwitch\")]\n            set;\n        }\n\n        public static extern int switchRomCompressionLevel\n        {\n            [NativeMethod(\"GetRomCompressionLevelForSwitch\")]\n            get;\n            [NativeMethod(\"SetRomCompressionLevelForSwitch\")]\n            set;\n        }\n\n        public static extern string switchRomCompressionConfig\n        {\n            [NativeMethod(\"GetRomCompressionConfigForSwitch\")]\n            get;\n            [NativeMethod(\"SetRomCompressionConfigForSwitch\")]\n            set;\n        }\n\n        // Enable linkage of NVN Graphics Debugger for Nintendo Switch.\n        public static extern bool switchNVNGraphicsDebugger\n        {\n            [NativeMethod(\"GetNVNGraphicsDebuggerForSwitch\")]\n            get;\n            [NativeMethod(\"SetNVNGraphicsDebuggerForSwitch\")]\n            set;\n        }\n\n        // Generate Nintendo Switch shader info for shader source visualization and profiling in NVN Graphics Debugger or Low-Level Graphics Debugger (LLGD)\n        public static extern bool generateNintendoSwitchShaderInfo\n        {\n            [NativeMethod(\"GetGenerateNintendoSwitchShaderInfo\")]\n            get;\n            [NativeMethod(\"SetGenerateNintendoSwitchShaderInfo\")]\n            set;\n        }\n\n        // Enable shader debugging using NVN Graphics Debugger\n        public static extern bool switchNVNShaderDebugging\n        {\n            [NativeMethod(\"GetNVNShaderDebugging\")]\n            get;\n            [NativeMethod(\"SetNVNShaderDebugging\")]\n            set;\n        }\n\n        // Enable shader debugging using NVN Graphics Debugger\n        public static extern bool switchNVNAftermath\n        {\n            [NativeMethod(\"GetNVNAftermath\")]\n            get;\n            [NativeMethod(\"SetNVNAftermath\")]\n            set;\n        }\n\n        // Enable debug validation of NVN drawcalls\n        [Obsolete(\"switchNVNDrawValidation is deprecated, use switchNVNDrawValidation_Heavy instead.\")]\n        public static bool switchNVNDrawValidation\n        {\n            get { return switchNVNDrawValidation_Heavy; }\n            set { switchNVNDrawValidation_Heavy = value; }\n        }\n\n        public static extern bool switchNVNDrawValidation_Light\n        {\n            [NativeMethod(\"GetNVNDrawValidationLight\")]\n            get;\n            [NativeMethod(\"SetNVNDrawValidationLight\")]\n            set;\n        }\n\n        public static extern bool switchNVNDrawValidation_Heavy\n        {\n            [NativeMethod(\"GetNVNDrawValidationHeavy\")]\n            get;\n            [NativeMethod(\"SetNVNDrawValidationHeavy\")]\n            set;\n        }\n\n        // Enable linkage of the Memory Tracker tool for Nintendo Switch.\n        public static extern bool switchEnableMemoryTracker\n        {\n            [NativeMethod(\"GetEnableMemoryTrackerForSwitch\")]\n            get;\n            [NativeMethod(\"SetEnableMemoryTrackerForSwitch\")]\n            set;\n        }\n\n        // On startup the application waits for Memory Tracker to connect.\n        public static extern bool switchWaitForMemoryTrackerOnStartup\n        {\n            [NativeMethod(\"GetWaitForSwitchMemoryTrackerOnStartup\")]\n            get;\n            [NativeMethod(\"SetWaitForSwitchMemoryTrackerOnStartup\")]\n            set;\n        }\n\n        // Enable linkage of DebugPad functionality for Nintendo Switch.\n        public static extern bool switchEnableDebugPad\n        {\n            [NativeMethod(\"GetEnableDebugPadForSwitch\")]\n            get;\n            [NativeMethod(\"SetEnableDebugPadForSwitch\")]\n            set;\n        }\n\n        [Obsolete(\"EditorUserBuildSettings.switchRedirectWritesToHostMount is obsolete. Use EditorUserBuildSettings.switchEnableHostIO instead (UnityUpgradable) -> switchEnableHostIO\", false)]\n        public static bool switchRedirectWritesToHostMount\n        {\n            get => switchEnableHostIO;\n            set => switchEnableHostIO = value;\n        }\n\n        // Redirect attempts to write to \"rom:\" mount, to \"host:\" mount for Nintendo Switch (for debugging and tests only)\n        public static extern bool switchEnableHostIO\n        {\n            [NativeMethod(\"GetEnableHostIOForSwitch\")]\n            get;\n            [NativeMethod(\"SetEnableHostIOForSwitch\")]\n            set;\n        }\n\n        // Enable using the HTC devkit connection for script debugging\n        public static extern bool switchHTCSScriptDebugging\n        {\n            [NativeMethod(\"GetHTCSScriptDebuggingForSwitch\")]\n            get;\n            [NativeMethod(\"SetHTCSScriptDebuggingForSwitch\")]\n            set;\n        }\n\n        public static extern bool switchUseLegacyNvnPoolAllocator\n        {\n            [NativeMethod(\"GetUseLegacyNvnPoolAllocatorForSwitch\")]\n            get;\n            [NativeMethod(\"SetUseLegacyNvnPoolAllocatorForSwitch\")]\n            set;\n        }\n\n        public static extern bool switchEnableUnpublishableErrors\n        {\n            [NativeMethod(\"GetEnableUnpublishableErrorsForSwitch\")]\n            get;\n            [NativeMethod(\"SetEnableUnpublishableErrorsForSwitch\")]\n            set;\n        }\n\n        internal static extern SwitchShaderCompilerConfig switchShaderCompilerConfig\n        {\n            [NativeMethod(\"GetSwitchShaderCompilerConfig\")]\n            get;\n            [NativeMethod(\"SetSwitchShaderCompilerConfig\")]\n            set;\n        }\n\n        // Place the built player in the build folder.\n        public static extern bool installInBuildFolder { get; set; }\n\n        public static bool waitForManagedDebugger\n        {\n            get\n            {\n                return GetPlatformSettings(\"Editor\", BuildProfilePlatformSettingsBase.k_SettingWaitForManagedDebugger) == \"true\";\n            }\n\n            set\n            {\n                SetPlatformSettings(\"Editor\", BuildProfilePlatformSettingsBase.k_SettingWaitForManagedDebugger, value.ToString().ToLower());\n            }\n        }\n\n        public static int managedDebuggerFixedPort\n        {\n            get\n            {\n                if (Int32.TryParse(GetPlatformSettings(\"Editor\", BuildProfilePlatformSettingsBase.k_SettingManagedDebuggerFixedPort), out int value)) {\n                    if (0 < value && value <= 65535)\n                    {\n                        return value;\n                    }\n                }\n                return 0;\n            }\n\n            set\n            {\n                SetPlatformSettings(\"Editor\", BuildProfilePlatformSettingsBase.k_SettingManagedDebuggerFixedPort, value.ToString().ToLower());\n            }\n        }\n\n        internal static extern bool isBuildProfileAvailable { get; set; }\n        internal static BuildProfile activeBuildProfile\n        {\n            get => GetActiveBuildProfile() as BuildProfile;\n            set => SetActiveBuildProfile(value);\n        }\n\n        private static extern ScriptableObject GetActiveBuildProfile();\n        private static extern void SetActiveBuildProfile(ScriptableObject buildProfile);\n\n        internal static extern void CopyFromBuildProfile(ScriptableObject buildProfile);\n        internal static extern void CopyToBuildProfile(ScriptableObject buildProfile);\n\n        internal static extern string[] GetActiveProfileScriptingDefines();\n        internal static extern void SetActiveProfileScriptingDefines(string[] defines);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorUserBuildSettings.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    public partial class EditorUserBuildSettings\n    {\n        // Select a new build target to be active.\n        [Obsolete(\"Please use SwitchActiveBuildTarget(BuildTargetGroup targetGroup, BuildTarget target)\")]\n        public static bool SwitchActiveBuildTarget(BuildTarget target)\n        {\n            return SwitchActiveBuildTarget(BuildPipeline.GetBuildTargetGroup(target), target);\n        }\n\n        // Triggered in response to SwitchActiveBuildTarget.\n        [Obsolete(\"UnityEditor.activeBuildTargetChanged has been deprecated.Use UnityEditor.Build.IActiveBuildTargetChanged instead.\")]\n        public static Action activeBuildTargetChanged;\n\n#pragma warning disable 0618\n        [RequiredByNativeCode]\n        internal static void Internal_ActiveBuildTargetChanged()\n        {\n            if (activeBuildTargetChanged != null)\n                activeBuildTargetChanged();\n        }\n\n#pragma warning restore 0618\n\n        // Force full optimisations for script complilation in Development builds (OBSOLETE, replaced by \"IL2CPP optimization level\" Player Setting)\n        [Obsolete(\"forceOptimizeScriptCompilation is obsolete - will always return false. Control script optimization using the 'IL2CPP optimization level' configuration in Player Settings / Other.\")]\n        public static bool forceOptimizeScriptCompilation { get { return false; } }\n\n        [Obsolete(@\"androidDebugMinification is obsolete. Use PlayerSettings.Android.minifyDebug\")]\n        public static AndroidMinification androidDebugMinification\n        {\n            get\n            {\n                return PlayerSettings.Android.minifyDebug ? AndroidMinification.Gradle : AndroidMinification.None;\n            }\n            set\n            {\n                PlayerSettings.Android.minifyDebug = value != AndroidMinification.None;\n            }\n        }\n\n        [Obsolete(@\"androidReleaseMinification is obsolete. Use PlayerSettings.Android.minifyRelease\")]\n        public static AndroidMinification androidReleaseMinification\n        {\n            get\n            {\n                return PlayerSettings.Android.minifyRelease ? AndroidMinification.Gradle : AndroidMinification.None;\n            }\n            set\n            {\n                PlayerSettings.Android.minifyRelease = value != AndroidMinification.None;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorUserBuildSettingsEmbeddedCommon.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    // Embedded Linux && QNX Architecture\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    public enum EmbeddedArchitecture\n    {\n        [UnityEngine.InspectorName(\"Arm64\")]\n        Arm64 = 0,\n\n        [System.Obsolete(\"Arm32 has been removed in 2023.2\")]\n        Arm32 = 1,\n\n        [UnityEngine.InspectorName(\"X64\")]\n        X64 = 2,\n\n        [System.Obsolete(\"X86 has been removed in 2023.2\")]\n        X86 = 3,\n    }\n\n    [NativeHeader(\"Editor/Src/EditorUserBuildSettings.h\")]\n    public partial class EditorUserBuildSettings\n    {\n        // Embedded Linux && QNX remote device information\n        public static extern bool remoteDeviceInfo { get; set; }\n        public static extern string remoteDeviceAddress { get; set; }\n        public static extern string remoteDeviceUsername { get; set; }\n        public static extern string remoteDeviceExports { get; set; }\n        public static extern string pathOnRemoteDevice { get; set; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorUserBuildSettingsEmbeddedLinux.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\n\n// wrapper class to provide similar interface as old settings. old: UnityEditor.EditorUserBuildSettings.selectedEmbeddedLinuxArchitecture   ... new: UnityEditor.EditorUserBuildSettings.EmbeddedLinux.architecture\nnamespace UnityEditor\n{\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    [Obsolete(\"EmbeddedLinuxArchitecture is deprecated. Use EmbeddedArchitecture. (UnityUpgradable) -> EmbeddedArchitecture\", false)]\n    public enum EmbeddedLinuxArchitecture\n    {\n        [UnityEngine.InspectorName(\"Arm64\")]\n        Arm64 = EmbeddedArchitecture.Arm64,\n\n        [System.Obsolete(\"Arm32 has been removed in 2023.2\")]\n        Arm32 = EmbeddedArchitecture.Arm32,\n\n        [UnityEngine.InspectorName(\"X64\")]\n        X64 = EmbeddedArchitecture.X64,\n\n        [System.Obsolete(\"X86 has been removed in 2023.2\")]\n        X86 = EmbeddedArchitecture.X86,\n    }\n\n    public partial class EditorUserBuildSettings\n    {\n        #pragma warning disable 0618\n        [Obsolete(\"EditorUserBuildSettings.selectedEmbeddedLinuxArchitecture is deprecated. EmbeddedLinux.Settings.architecture instead. (UnityUpgradable) -> [UnityEditor.EmbeddedLinux.Extensions] UnityEditor.EmbeddedLinux.Settings.architecture\", false)]\n        public static extern EmbeddedLinuxArchitecture selectedEmbeddedLinuxArchitecture\n        {\n            [NativeMethod(\"GetSelectedEmbeddedLinuxArchitecture\")]\n            get;\n            [NativeMethod(\"SetSelectedEmbeddedLinuxArchitecture\")]\n            set;\n        }\n        #pragma warning restore 0618\n    }\n}\n\n"
  },
  {
    "path": "Editor/Mono/EditorUserBuildSettingsQNX.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    public enum QNXOsVersion\n    {\n        [UnityEngine.InspectorName(\"Neutrino RTOS 7.1\")]\n        Neutrino71 = 1,\n        [UnityEngine.InspectorName(\"Neutrino RTOS 8.0\")]\n        Neutrino80 = 2,\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorUserBuildSettingsQNX.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\n//using UnityEditor.QNX;\n\n// wrapper class to provide similar interface as old settings. old: UnityEditor.EditorUserBuildSettings.selectedQnxArchitecture   ... new: UnityEditor.EditorUserBuildSettings.QNX.architecture\nnamespace UnityEditor\n{\n    [NativeType(Header = \"Editor/Src/EditorUserBuildSettings.h\")]\n    [Obsolete(\"QNXArchitecture is deprecated. Use EmbeddedArchitecture. (UnityUpgradable) -> EmbeddedArchitecture\", false)]\n    public enum QNXArchitecture\n    {\n        [UnityEngine.InspectorName(\"Arm64\")]\n        Arm64 = EmbeddedArchitecture.Arm64,\n\n        [System.Obsolete(\"Arm32 has been removed in 2023.2\")]\n        Arm32 = EmbeddedArchitecture.Arm32,\n\n        [UnityEngine.InspectorName(\"X64\")]\n        X64 = EmbeddedArchitecture.X64,\n\n        [System.Obsolete(\"X86 has been removed in 2023.2\")]\n        X86 = EmbeddedArchitecture.X86,\n    }\n\n    public partial class EditorUserBuildSettings\n    {\n        [Obsolete(\"EditorUserBuildSettings.selectedQnxOsVersion is deprecated. Use QNX.Settings.osVersion instead. (UnityUpgradable) -> [UnityEditor.QNX.Extensions] UnityEditor.QNX.Settings.osVersion\", false)]\n        public static extern QNXOsVersion selectedQnxOsVersion\n        {\n            [NativeMethod(\"GetSelectedQNXOsVersion\")]\n            get;\n            [NativeMethod(\"SetSelectedQNXOsVersion\")]\n            set;\n        }\n\n        #pragma warning disable 0618\n        [Obsolete(\"EditorUserBuildSettings.selectedQnxArchitecture is deprecated. Use QNX.Settings.architecture instead. (UnityUpgradable) -> [UnityEditor.QNX.Extensions] UnityEditor.QNX.Settings.architecture\", false)]\n        public static extern QNXArchitecture selectedQnxArchitecture\n        {\n            [NativeMethod(\"GetSelectedQNXArchitecture\")]\n            get;\n            [NativeMethod(\"SetSelectedQNXArchitecture\")]\n            set;\n        }\n        #pragma warning restore 0618\n    }\n}\n\n"
  },
  {
    "path": "Editor/Mono/EditorUserBuildSettingsUtils.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.Build;\n\nnamespace UnityEditor\n{\n    internal static class EditorUserBuildSettingsUtils\n    {\n        public static BuildTarget CalculateSelectedBuildTarget()\n        {\n            NamedBuildTarget namedBuildTarget = CalculateSelectedNamedBuildTarget();\n            return CalculateSelectedBuildTarget(namedBuildTarget);\n        }\n\n        internal static BuildTarget CalculateSelectedBuildTarget(NamedBuildTarget namedBuildTarget)\n        {\n            if (namedBuildTarget.ToBuildTargetGroup() == BuildTargetGroup.Standalone)\n            {\n                BuildTarget target = EditorUserBuildSettings.selectedStandaloneTarget;\n                if (target == BuildTarget.NoTarget)\n                    target = EditorUserBuildSettings.activeBuildTarget;\n                return DesktopStandaloneBuildWindowExtension.GetBestStandaloneTarget(target);\n            }\n            else\n            {\n                if (BuildPlatforms.instance == null)\n                    throw new System.Exception(\"Build platforms are not initialized.\");\n                BuildPlatform platform = BuildPlatforms.instance.BuildPlatformFromNamedBuildTarget(namedBuildTarget);\n                if (platform == null)\n                    throw new System.Exception(\"Could not find build platform for target group \" + namedBuildTarget.TargetName);\n                return platform.defaultTarget;\n            }\n        }\n\n        public static NamedBuildTarget CalculateSelectedNamedBuildTarget()\n        {\n            BuildTargetGroup targetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;\n            if (targetGroup == BuildTargetGroup.Unknown)\n                targetGroup = EditorUserBuildSettings.activeBuildTargetGroup;\n\n            // TODO: Eventually NamedBuildTarget will replace completetly BuildTargetGroup, and we won't need this custom check\n            if (targetGroup == BuildTargetGroup.Standalone)\n            {\n                if (EditorUserBuildSettings.selectedStandaloneBuildSubtarget == StandaloneBuildSubtarget.Server)\n                    return NamedBuildTarget.Server;\n\n                return NamedBuildTarget.Standalone;\n            }\n\n            return NamedBuildTarget.FromBuildTargetGroup(targetGroup);\n        }\n\n        public static NamedBuildTarget CalculateActiveNamedBuildTarget()\n        {\n            BuildTargetGroup targetGroup = EditorUserBuildSettings.activeBuildTargetGroup;\n\n            // TODO: Eventually NamedBuildTarget will replace completetly BuildTargetGroup, and we won't need this custom check\n            if (targetGroup == BuildTargetGroup.Standalone)\n            {\n                if (EditorUserBuildSettings.standaloneBuildSubtarget == StandaloneBuildSubtarget.Server)\n                    return NamedBuildTarget.Server;\n\n                return NamedBuildTarget.Standalone;\n            }\n\n            return NamedBuildTarget.FromBuildTargetGroup(targetGroup);\n        }\n\n        public static bool IsSelected(this BuildPlatform buildPlatform)\n        {\n            // This is the special case for Editor target selected in the UI\n            if (EditorUserBuildSettings.selectedBuildTargetGroup == BuildTargetGroup.Unknown)\n                return buildPlatform.namedBuildTarget == NamedBuildTarget.Unknown;\n\n            return buildPlatform.namedBuildTarget == CalculateSelectedNamedBuildTarget();\n        }\n\n        public static bool IsActive(this BuildPlatform buildPlatform)\n        {\n            return buildPlatform.namedBuildTarget == CalculateActiveNamedBuildTarget();\n        }\n\n        public static void Select(this BuildPlatform buildPlatform)\n        {\n            if (buildPlatform is BuildPlatformWithSubtarget)\n            {\n                var target = CalculateSelectedBuildTarget(buildPlatform.namedBuildTarget);\n                EditorUserBuildSettings.SetSelectedSubtargetFor(target, ((BuildPlatformWithSubtarget)buildPlatform).subtarget);\n            }\n\n            EditorUserBuildSettings.selectedBuildTargetGroup = buildPlatform.namedBuildTarget.ToBuildTargetGroup();\n        }\n\n        public static bool SetActive(this BuildPlatform buildPlatform)\n        {\n            var target = CalculateSelectedBuildTarget(buildPlatform.namedBuildTarget);\n            return buildPlatform.SetActive(target);\n        }\n\n        public static bool SetActive(this BuildPlatform buildPlatform, BuildTarget target)\n        {\n            if (BuildPipeline.GetBuildTargetGroup(target) != buildPlatform.namedBuildTarget.ToBuildTargetGroup())\n            {\n                UnityEngine.Debug.LogError($\"Build target {target} must be part of the {buildPlatform.namedBuildTarget.TargetName} group\");\n                return false;\n            }\n\n            if (buildPlatform is BuildPlatformWithSubtarget)\n                return EditorUserBuildSettings.SwitchActiveBuildTargetAndSubtarget(target, ((BuildPlatformWithSubtarget)buildPlatform).subtarget);\n\n            return EditorUserBuildSettings.SwitchActiveBuildTarget(buildPlatform.namedBuildTarget.ToBuildTargetGroup(), target);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorUserSettings.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nusing UnityObject = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    public enum SemanticMergeMode\n    {\n        Off = 0,\n        Premerge = 1,\n        Ask = 2,\n    }\n\n    [NativeHeader(\"Editor/Src/EditorUserSettings.h\")]\n    [StaticAccessor(\"GetEditorUserSettings()\", StaticAccessorType.Dot)]\n    public sealed class EditorUserSettings : UnityObject\n    {\n        EditorUserSettings()\n        {\n        }\n\n        static extern bool HasConfigValue(string name);\n\n        [NativeMethod(\"GetConfigValue\")]\n        static extern string Internal_GetConfigValue(string name);\n\n        public static string GetConfigValue(string name)\n        {\n            return HasConfigValue(name) ? Internal_GetConfigValue(name) : null;\n        }\n\n        public static extern void SetConfigValue(string name, string value);\n\n        internal static extern void SetPrivateConfigValue(string name, string value);\n\n        [NativeProperty(\"VCAutomaticAdd\")]\n        public static extern bool AutomaticAdd { get; set; }\n\n        [NativeProperty(\"VCWorkOffline\")]\n        public static extern bool WorkOffline { get; set; }\n\n        [NativeProperty(\"VCShowFailedCheckout\")]\n        public static extern bool showFailedCheckout { get; set; }\n\n        [NativeProperty(\"VCOverwriteFailedCheckoutAssets\")]\n        public static extern bool overwriteFailedCheckoutAssets { get; set; }\n\n        [NativeProperty(\"VCProjectOverlayIcons\")]\n        public static extern bool overlayIcons { get; set; }\n\n        [NativeProperty(\"VCHierarchyOverlayIcons\")]\n        public static extern bool hierarchyOverlayIcons { get; set; }\n\n        [NativeProperty(\"VCOtherOverlayIcons\")]\n        public static extern bool otherOverlayIcons { get; set; }\n\n        [NativeProperty(\"VCAllowAsyncUpdate\")]\n        public static extern bool allowAsyncStatusUpdate { get; set; }\n\n        [NativeProperty(\"VCScanLocalPackagesOnConnect\")]\n        public static extern bool scanLocalPackagesOnConnect { get; set; }\n\n        [NativeProperty(\"VCDebugCmd\")]\n        internal static extern bool DebugCmd { get; set; }\n\n        [NativeProperty(\"VCDebugOut\")]\n        internal static extern bool DebugOut { get; set; }\n\n        [NativeProperty(\"VCDebugCom\")]\n        internal static extern bool DebugCom { get; set; }\n\n        [NativeProperty(\"ArtifactGarbageCollection\")]\n        public static extern bool artifactGarbageCollection { get; set; }\n\n        [NativeProperty(\"CompressAssetsOnImport\")]\n        public static extern bool compressAssetsOnImport { get; set; }\n\n        public static extern SemanticMergeMode semanticMergeMode { get; set; }\n\n        public static extern int desiredImportWorkerCount { get; set; }\n\n        public static extern int standbyImportWorkerCount { get; set; }\n\n        public static extern int idleImportWorkerShutdownDelayMilliseconds { get; set; }\n\n        internal static extern void SoftReset();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\nusing UnityEngine.Bindings;\nusing UnityEngine.Internal;\nusing UnityEngine.Scripting;\nusing System.Collections.Generic;\nusing System.Linq;\nusing static UnityEditor.EditorGUI;\nusing UnityEditor.Inspector.GraphicsSettingsInspectors;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Mono/EditorUtility.bindings.h\")]\n    [NativeHeader(\"Editor/Mono/MonoEditorUtility.h\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/UnityExtensions.h\")]\n    [NativeHeader(\"Runtime/Shaders/ShaderImpl/ShaderUtilities.h\")]\n    partial class EditorUtility\n    {\n        public static extern string OpenFilePanel(string title, string directory, string extension);\n\n        private static extern string Internal_OpenFilePanelWithFilters(string title, string directory, string[] filters);\n        public static string OpenFilePanelWithFilters(string title, string directory, string[] filters)\n        {\n            if (filters.Length % 2 != 0)\n                throw new Exception(\"Filters must be declared in pairs { \\\"FileType\\\", \\\"FileExtension\\\" }; for instance { \\\"CSharp\\\", \\\"cs\\\" }. \");\n            return Internal_OpenFilePanelWithFilters(title, directory, filters);\n        }\n\n        [FreeFunction(\"RevealInFinder\")]\n        public static extern void RevealInFinder(string path);\n\n        [FreeFunction(\"DisplayDialog\")]\n        static extern bool DisplayDialogImpl(string title, string message, string ok, string cancel);\n\n        public static bool DisplayDialog(string title, string message, string ok, [DefaultValue(\"\\\"\\\"\")] string cancel)\n        {\n            // i am not sure how picky should we be about the params\n            // for example, for the buttons we have code that ignores empty strings,\n            //   to allow having \"ok\"-only dialogs (information panels, so to say)\n            // same with title+message: it sounds like we should allow skipping one of those\n            // hence we make sure that at least one button is present, and some message\n            // we can go more picky if we want in the future\n            if(string.IsNullOrEmpty(ok) && string.IsNullOrEmpty(cancel))\n                throw new ArgumentException(\"Both 'ok' and 'cancel' strings are null or empty\");\n            if(string.IsNullOrEmpty(title) && string.IsNullOrEmpty(message))\n                throw new ArgumentException(\"Both 'title' and 'message' strings are null or empty\");\n\n            using (new DisabledGuiViewInputScope(GUIView.current, true))\n            {\n                return DisplayDialogImpl(title, message, ok, cancel);\n            }\n        }\n        [ExcludeFromDocs]\n        public static bool DisplayDialog(string title, string message, string ok)\n        {\n            return DisplayDialog(title, message, ok, String.Empty);\n        }\n\n        [FreeFunction(\"DisplayDialogComplex\")]\n        static extern int DisplayDialogComplexImpl(string title, string message, string ok, string cancel, string alt);\n\n        public static int DisplayDialogComplex(string title, string message, string ok, string cancel, string alt)\n        {\n            // see the comment above in DisplayDialog\n            // our implementation allows setting some strings empty (the button will be skipped then)\n            // but we should totally ensure some buttons are set\n\n            if(string.IsNullOrEmpty(ok) && string.IsNullOrEmpty(cancel) && string.IsNullOrEmpty(alt))\n                throw new ArgumentException(\"All three 'ok', 'cancel' and 'alt' strings are null or empty\");\n            if(string.IsNullOrEmpty(title) && string.IsNullOrEmpty(message))\n                throw new ArgumentException(\"Both 'title' and 'message' strings are null or empty\");\n\n            return DisplayDialogComplexImpl(title, message, ok, cancel, alt);\n        }\n\n\n\n        [FreeFunction(\"RunOpenFolderPanel\")]\n        public static extern string OpenFolderPanel(string title, string folder, string defaultName);\n\n        [FreeFunction(\"RunSaveFolderPanel\")]\n        public static extern string SaveFolderPanel(string title, string folder, string defaultName);\n\n        [FreeFunction(\"WarnPrefab\")]\n        public static extern bool WarnPrefab(Object target, string title, string warning, string okButton);\n\n        [StaticAccessor(\"UnityExtensions::Get()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"IsInitialized\")]\n        public extern static bool IsUnityExtensionsInitialized();\n\n        public static extern bool IsPersistent(Object target);\n        public static extern bool IsValidUnityYAML(string yaml);\n        public static extern string SaveFilePanel(string title, string directory, string defaultName, string extension);\n        [ThreadSafe]\n        public static extern int NaturalCompare(string a, string b);\n        public static extern Object InstanceIDToObject(int instanceID);\n        public static extern void CompressTexture([NotNull] Texture2D texture, TextureFormat format, int quality);\n        public static extern void CompressCubemapTexture([NotNull] Cubemap texture, TextureFormat format, int quality);\n\n        private extern static int[] RemapInstanceIds(UnityEngine.Object[] objects, int[] srcIds, int[] dstIds);\n\n        internal static int[] RemapInstanceIds(UnityEngine.Object[] objects, Dictionary<int, int> idMap)\n        {\n            return RemapInstanceIds(objects, idMap.Keys.ToArray(), idMap.Values.ToArray());\n        }\n\n        private extern static void RemapAssetReferences(UnityEngine.Object[] objects, string[] sourceAssetPaths, string[] dstAssetPaths, int[] srcIds, int[] dstIds);\n\n        internal static void RemapAssetReferences(UnityEngine.Object[] objects, Dictionary<string, string> assetPathMap, Dictionary<int, int> idMap = null)\n        {\n            RemapAssetReferences(objects, assetPathMap.Keys.ToArray(), assetPathMap.Values.ToArray(),\n                idMap == null ? new int[0] : idMap.Keys.ToArray(),\n                idMap == null ? new int[0] : idMap.Values.ToArray()\n            );\n        }\n\n        [FreeFunction(\"EditorUtility::SetDirtyObjectOrScene\")]\n        public static extern void SetDirty([NotNull] Object target);\n\n        public static extern void ClearDirty([NotNull] Object target);\n\n        [FreeFunction(\"InvokeDiffTool\")]\n        public static extern string InvokeDiffTool(string leftTitle, string leftFile, string rightTitle, string rightFile, string ancestorTitle, string ancestorFile);\n\n        [FreeFunction(\"CopySerialized\")]\n        public static extern void CopySerialized([NotNull] Object source, [NotNull] Object dest);\n\n        [FreeFunction(\"CopyScriptSerialized\")]\n        public static extern void CopySerializedManagedFieldsOnly([NotNull] System.Object source, [NotNull] System.Object dest);\n\n        [FreeFunction(\"CopySerializedIfDifferent\")]\n        private static extern void InternalCopySerializedIfDifferent([NotNull] Object source, [NotNull] Object dest);\n\n        [NativeThrows]\n        [return: Unmarshalled]\n        public static extern Object[] CollectDependencies([Unmarshalled] Object[] roots);\n        public static extern Object[] CollectDeepHierarchy([Unmarshalled] Object[] roots);\n\n        [FreeFunction(\"InstantiateObjectRemoveAllNonAnimationComponents\")]\n        private static extern Object Internal_InstantiateRemoveAllNonAnimationComponentsSingle([NotNull] Object data, Vector3 pos, Quaternion rot);\n\n        [FreeFunction(\"ManagedUnloadUnusedAssetsImmediate\")]\n        private static extern void UnloadUnusedAssets(bool managedObjects);\n\n        [Obsolete(\"Use EditorUtility.UnloadUnusedAssetsImmediate instead\", false)]\n        public static void UnloadUnusedAssets()\n        {\n            UnloadUnusedAssets(true);\n        }\n\n        [Obsolete(\"Use EditorUtility.UnloadUnusedAssetsImmediate instead\", false)]\n        public static void UnloadUnusedAssetsIgnoreManagedReferences()\n        {\n            UnloadUnusedAssets(false);\n        }\n\n        [FreeFunction(\"MenuController::DisplayPopupMenu\")]\n        private static extern void Private_DisplayPopupMenu(Rect position, string menuItemPath, Object context, int contextUserData, bool shouldDiscardMenuOnSecondClick = false);\n\n        [FreeFunction(\"UpdateMenuTitleForLanguage\")]\n        internal static extern void Internal_UpdateMenuTitleForLanguage(SystemLanguage newloc);\n\n        internal static extern void RebuildAllMenus();\n        internal static extern void Internal_UpdateAllMenus();\n        internal static extern void LogAllMenus();\n        internal static extern string ParseMenuName(string menuName);\n\n        [FreeFunction(\"DisplayObjectContextPopupMenu\")]\n        internal static extern void DisplayObjectContextPopupMenu(Rect position, Object[] context, int contextUserData);\n\n        [FreeFunction(\"DisplayCustomContextPopupMenu\")]\n        private static extern void DisplayCustomContextPopupMenu(Rect screenPosition, string[] options, bool[] enabled, bool[] separator, int[] selected, SelectMenuItemFunction callback, object userData, bool showHotkey, bool allowDisplayNames, bool shouldDiscardMenuOnSecondClick = false);\n\n        [FreeFunction(\"DisplayObjectContextPopupMenuWithExtraItems\")]\n        internal static extern void DisplayObjectContextPopupMenuWithExtraItems(Rect position, Object[] context, int contextUserData, string[] options, bool[] enabled, bool[] separator, int[] selected, SelectMenuItemFunction callback, object userData, bool showHotkey);\n\n        [FreeFunction(\"FormatBytes\")]\n        public static extern string FormatBytes(long bytes);\n\n        [FreeFunction(\"DisplayProgressbarLegacy\")]\n        public static extern void DisplayProgressBar(string title, string info, float progress);\n\n        public static extern bool DisplayCancelableProgressBar(string title, string info, float progress);\n\n        [FreeFunction(\"ClearProgressbarLegacy\")]\n        public static extern void ClearProgressBar();\n\n        [FreeFunction(\"BusyProgressDialogDelayChanged\")]\n        internal static extern void BusyProgressDialogDelayChanged(float delay);\n\n        [FreeFunction(\"GetObjectEnabled\")]\n        public static extern int GetObjectEnabled(Object target);\n\n        [FreeFunction(\"SetObjectEnabled\")]\n        public static extern void SetObjectEnabled(Object target, bool enabled);\n\n        public static extern void SetSelectedRenderState(Renderer renderer, EditorSelectedRenderState renderState);\n\n        internal static extern void ForceReloadInspectors();\n        internal static extern void ForceRebuildInspectors();\n\n        [RequiredByNativeCode]\n        internal static void DelayedForceRebuildInspectors()\n        {\n            EditorApplication.CallDelayed(() =>\n            {\n                ForceRebuildInspectors();\n                GraphicsSettingsInspectorUtility.ReloadGraphicsSettingsEditorIfNeeded();\n            });\n        }\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"ExtractOggFile has no effect anymore\", false)]\n        public static bool ExtractOggFile(Object obj, string path)\n        {\n            return false;\n        }\n\n        internal static extern GameObject Internal_CreateGameObjectWithHideFlags(string name, HideFlags flags);\n\n        [FreeFunction(\"OpenWithDefaultApp\")]\n        public static extern void OpenWithDefaultApp(string fileName);\n\n        [NativeThrows] internal static extern bool WSACreateTestCertificate(string path, string publisher, string password, bool overwrite);\n        internal static extern bool WSAGetCertificateExpirationDate(string path, string password, out long expirationDate);\n\n        internal static extern bool IsWindows10OrGreater();\n\n        public static extern void SetCameraAnimateMaterials([NotNull] Camera camera, bool animate);\n        public static extern void SetCameraAnimateMaterialsTime([NotNull] Camera camera, float time);\n\n        [FreeFunction(\"ShaderLab::UpdateGlobalShaderProperties\")]\n        public static extern void UpdateGlobalShaderProperties(float time);\n\n        [FreeFunction(\"GetInvalidFilenameChars\")]\n        internal static extern string GetInvalidFilenameChars();\n\n        [FreeFunction(\"GetApplication().IsAutoRefreshEnabled\")]\n        internal static extern bool IsAutoRefreshEnabled();\n\n        [FreeFunction(\"GetApplication().GetActiveNativePlatformSupportModuleName\")]\n        internal static extern string GetActiveNativePlatformSupportModuleName();\n\n        internal static extern bool Internal_AudioMasterMute\n        {\n            [FreeFunction(\"GetAudioManager().GetMasterGroupMute\")] get;\n            [FreeFunction(\"GetAudioManager().SetMasterGroupMute\")] set;\n        }\n\n        public static bool audioMasterMute\n        {\n            get { return Internal_AudioMasterMute; }\n            set\n            {\n                if (value != Internal_AudioMasterMute)\n                {\n                    Internal_AudioMasterMute = value;\n                    onAudioMasterMuteWasUpdated?.Invoke(value);\n                }\n            }\n        }\n\n        internal delegate void AudioMasterMuteWasUpdated(bool value);\n        internal static event AudioMasterMuteWasUpdated onAudioMasterMuteWasUpdated;\n\n        internal static extern void LaunchBugReporter();\n\n        internal static extern bool audioProfilingEnabled\n        {\n            [FreeFunction(\"GetAudioManager().GetProfilingEnabled\")] get;\n        }\n\n        public static extern bool scriptCompilationFailed {[FreeFunction(\"HaveEditorCompileErrors\")] get; }\n\n        internal static extern bool EventHasDragCopyModifierPressed(Event evt);\n        internal static extern bool EventHasDragMoveModifierPressed(Event evt);\n\n        internal static extern void SaveProjectAsTemplate(string targetPath, string name, string displayName, string description, string defaultScene, string version);\n\n        [Obsolete(\"Use AssetDatabase.LoadAssetAtPath\", false),\n         FreeFunction(\"FindAssetWithKlass\", ThrowsException = true)]\n        public static extern Object FindAsset(string path, Type type);\n\n        [FreeFunction(\"LoadPlatformSupportModuleNativeDll\")]\n        internal static extern void LoadPlatformSupportModuleNativeDllInternal(string target);\n\n        [FreeFunction(\"ReloadPlatformSupportModuleNativeDll\")]\n        internal static extern void ReloadPlatformSupportModuleNativeDllInternal(string target);\n\n        [FreeFunction(\"LoadPlatformSupportNativeLibrary\")]\n        internal static extern void LoadPlatformSupportNativeLibrary(string nativeLibrary);\n\n        [NativeMethod(\"GetDirtyIndex\")]\n        public static extern int GetDirtyCount(int instanceID);\n        public static int GetDirtyCount(Object target) { return target != null ? GetDirtyCount(target.GetInstanceID()) : 0; }\n        public static extern bool IsDirty(int instanceID);\n        public static bool IsDirty(Object target) { return target != null ? IsDirty(target.GetInstanceID()) : false; }\n        internal static extern string SaveBuildPanel(BuildTarget target, string title, string directory, string defaultName, string extension, out bool updateExistingBuild);\n        internal static extern int NaturalCompareObjectNames(Object a, Object b);\n\n        [FreeFunction(\"RunSavePanelInProject\")]\n        private static extern string Internal_SaveFilePanelInProject(string title, string defaultName, string extension, string message, string path);\n\n        [RequiredByNativeCode]\n        public static void FocusProjectWindow()\n        {\n            ProjectBrowser prjBrowser = null;\n            var focusedView = GUIView.focusedView as HostView;\n            if (focusedView != null && focusedView.actualView is ProjectBrowser)\n            {\n                prjBrowser = (ProjectBrowser)focusedView.actualView;\n            }\n\n            if (prjBrowser == null)\n            {\n                var wins = Resources.FindObjectsOfTypeAll(typeof(ProjectBrowser));\n                if (wins.Length > 0)\n                {\n                    prjBrowser = wins[0] as ProjectBrowser;\n                }\n            }\n\n            if (prjBrowser != null)\n            {\n                prjBrowser.Focus(); // This line is to circumvent a limitation where a tabbed window can't be directly targeted by a command: only the focused tab can.\n                var commandEvent = EditorGUIUtility.CommandEvent(\"FocusProjectWindow\");\n                prjBrowser.SendEvent(commandEvent);\n            }\n        }\n\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        extern public static void RequestScriptReload();\n\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        [NativeThrows]\n        extern internal static void RequestPartialScriptReload();\n\n        internal static extern bool isInSafeMode\n        {\n            [FreeFunction(\"GetApplication().IsInSafeMode\")]\n            get;\n        }\n\n        [FreeFunction(\"IsRunningUnderCPUEmulation\", IsThreadSafe = true)]\n        extern public static bool IsRunningUnderCPUEmulation();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing UnityEditor.Compilation;\nusing UnityEditor.Experimental;\nusing UnityEditor.SceneManagement;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEngine.Internal;\nusing UnityEngine.SceneManagement;\nusing Object = UnityEngine.Object;\nusing UnityEditor.ShortcutManagement;\n\nnamespace UnityEditor\n{\n    [Flags]\n    public enum EditorSelectedRenderState\n    {\n        Hidden = 0,\n        Wireframe = 1,\n        Highlight = 2\n    }\n\n    public enum InteractionMode\n    {\n        // Perform action without undo or dialogs.\n        AutomatedAction,\n        // Record undo and allow potential dialogs to pop up.\n        UserAction\n    }\n\n    // Compression Quality. Corresponds to the settings in a [[wiki:class-Texture2D|texture inspector]].\n    public enum TextureCompressionQuality\n    {\n        Fast = 0, // Fast compression\n        Normal = 50, // Normal compression (default)\n        Best = 100 // Best compression\n    }\n\n    public enum DialogOptOutDecisionType\n    {\n        ForThisMachine,\n        ForThisSession,\n    }\n\n    public class SceneAsset : Object\n    {\n        private SceneAsset() {}\n    }\n\n    public partial class EditorUtility\n    {\n        static class Content\n        {\n            public static readonly string Cancel = L10n.Tr(\"Cancel\");\n            static readonly string k_DialogOptOutForThisMachine = L10n.Tr(\"Do not show me this message again on this machine.\");\n            static readonly string k_DialogOptOutForThisSession = L10n.Tr(\"Do not show me this message again for this session.\");\n            public static string GetDialogOptOutMessage(DialogOptOutDecisionType dialogOptOutType)\n            {\n                switch (dialogOptOutType)\n                {\n                    case DialogOptOutDecisionType.ForThisMachine:\n                        return k_DialogOptOutForThisMachine;\n                    case DialogOptOutDecisionType.ForThisSession:\n                        return k_DialogOptOutForThisSession;\n                    default:\n                        throw new NotImplementedException(string.Format(\"The DialogOptOut type named {0} has not been implemented.\", dialogOptOutType));\n                }\n            }\n        }\n\n        private static readonly Stack<StringBuilder> _SbPool = new Stack<StringBuilder>();\n\n        public delegate void SelectMenuItemFunction(object userData, string[] options, int selected);\n\n        internal static event Action onResetMouseDown;\n\n        public static bool LoadWindowLayout(string path)\n        {\n            return WindowLayout.TryLoadWindowLayout(path, false);\n        }\n\n        public static void CompressTexture(Texture2D texture, TextureFormat format, TextureCompressionQuality quality)\n        {\n            CompressTexture(texture, format, (int)quality);\n        }\n\n        private static void CompressTexture(Texture2D texture, TextureFormat format)\n        {\n            CompressTexture(texture, format, TextureCompressionQuality.Normal);\n        }\n\n        public static void CompressCubemapTexture(Cubemap texture, TextureFormat format, TextureCompressionQuality quality)\n        {\n            CompressCubemapTexture(texture, format, (int)quality);\n        }\n\n        private static void CompressCubemapTexture(Cubemap texture, TextureFormat format)\n        {\n            CompressCubemapTexture(texture, format, TextureCompressionQuality.Normal);\n        }\n\n        private static System.Collections.Generic.Dictionary<int, Texture> s_ActiveIconPathLUT = new System.Collections.Generic.Dictionary<int, Texture>();\n        internal static Texture GetIconInActiveState(Texture icon)\n        {\n            if (icon == null)\n                return null;\n\n            Texture selectedIcon;\n            var iconInstanceId = icon.GetInstanceID();\n            if (!s_ActiveIconPathLUT.TryGetValue(iconInstanceId, out selectedIcon))\n            {\n                const string iconText = \" icon\";\n                const string onText = \" on\";\n\n                string selectedIconPath = string.Empty;\n                string path = EditorResources.GetAssetPath(icon).ToLowerInvariant();\n                if (path.Contains(iconText))\n                    selectedIconPath = path.Replace(iconText, onText + iconText);\n                else if (path.Contains('@'))\n                    selectedIconPath = path.Replace(\"@\", onText + \"@\");\n                else if (path.EndsWith(\".png\"))\n                    selectedIconPath = path.Replace(\".png\", onText + \".png\");\n\n                selectedIcon = EditorResources.Load<Texture>(selectedIconPath, false);\n                s_ActiveIconPathLUT[iconInstanceId] = selectedIcon;\n            }\n\n            return selectedIcon;\n        }\n\n        public static string SaveFilePanelInProject(string title, string defaultName, string extension, string message)\n        {\n            return Internal_SaveFilePanelInProject(title, defaultName, extension, message, \"Assets\");\n        }\n\n        public static string SaveFilePanelInProject(string title, string defaultName, string extension, string message, string path)\n        {\n            return Internal_SaveFilePanelInProject(title, defaultName, extension, message, path);\n        }\n\n        public static void CopySerializedIfDifferent(Object source, Object dest)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (dest == null)\n                throw new ArgumentNullException(nameof(dest));\n\n            InternalCopySerializedIfDifferent(source, dest);\n        }\n\n        [Obsolete(\"Use AssetDatabase.GetAssetPath\", false)]\n        public static string GetAssetPath(Object asset)\n        {\n            return AssetDatabase.GetAssetPath(asset);\n        }\n\n        public static void UnloadUnusedAssetsImmediate()\n        {\n            UnloadUnusedAssets(true);\n        }\n\n        public static void UnloadUnusedAssetsImmediate(bool includeMonoReferencesAsRoots)\n        {\n            UnloadUnusedAssets(includeMonoReferencesAsRoots);\n        }\n\n        [Obsolete(\"Use BuildPipeline.BuildAssetBundle instead\")]\n        public static bool BuildResourceFile(Object[] selection, string pathName)\n        {\n            return false;\n        }\n\n        public static bool GetDialogOptOutDecision(DialogOptOutDecisionType dialogOptOutDecisionType, string dialogOptOutDecisionStorageKey)\n        {\n            switch (dialogOptOutDecisionType)\n            {\n                case DialogOptOutDecisionType.ForThisMachine:\n                    return EditorPrefs.GetBool(dialogOptOutDecisionStorageKey, false);\n                case DialogOptOutDecisionType.ForThisSession:\n                    return SessionState.GetBool(dialogOptOutDecisionStorageKey, false);\n                default:\n                    throw new NotImplementedException(string.Format(\"The DialogOptOut type named {0} has not been implemented.\", dialogOptOutDecisionType));\n            }\n        }\n\n        public static void SetDialogOptOutDecision(DialogOptOutDecisionType dialogOptOutDecisionType, string dialogOptOutDecisionStorageKey, bool optOutDecision)\n        {\n            switch (dialogOptOutDecisionType)\n            {\n                case DialogOptOutDecisionType.ForThisMachine:\n                    EditorPrefs.SetBool(dialogOptOutDecisionStorageKey, optOutDecision);\n                    break;\n                case DialogOptOutDecisionType.ForThisSession:\n                    SessionState.SetBool(dialogOptOutDecisionStorageKey, optOutDecision);\n                    break;\n                default:\n                    throw new NotImplementedException(string.Format(\"The DialogOptOut type named {0} has not been implemented.\", dialogOptOutDecisionType));\n            }\n        }\n\n        public static bool DisplayDialog(string title, string message, string ok, DialogOptOutDecisionType dialogOptOutDecisionType, string dialogOptOutDecisionStorageKey)\n        {\n            return DisplayDialog(title, message, ok, string.Empty, dialogOptOutDecisionType, dialogOptOutDecisionStorageKey);\n        }\n\n        public static bool DisplayDialog(string title, string message, string ok, [DefaultValue(\"\\\"\\\"\")] string cancel, DialogOptOutDecisionType dialogOptOutDecisionType, string dialogOptOutDecisionStorageKey)\n        {\n            if (GetDialogOptOutDecision(dialogOptOutDecisionType, dialogOptOutDecisionStorageKey))\n            {\n                return true;\n            }\n            else\n            {\n                bool optOutDecision;\n                bool dialogDecision = DisplayDialog(title, message, ok, cancel, Content.GetDialogOptOutMessage(dialogOptOutDecisionType), out optOutDecision);\n                // Cancel means the user pressed ESC as the Cancel button was grayed out. Don't store the opt-out decision on cancel. Also, only store it if the user opted out since it defaults to opt-in.\n                if (dialogDecision && optOutDecision)\n                    SetDialogOptOutDecision(dialogOptOutDecisionType, dialogOptOutDecisionStorageKey, optOutDecision);\n                return dialogDecision;\n            }\n        }\n\n        // TODO: This is an MVP solution. The OptOut option should be a check-box in the dialog. To achieve that, this API will need to move to bindings and get platform specific implementations.\n        static bool DisplayDialog(string title, string message, string ok, string cancel, string optOutText, out bool optOutDecision)\n        {\n            if (string.IsNullOrEmpty(cancel))\n            {\n                // we can't allow empty cancel buttons in this MVP workaround. Only the two button dialog would be possible to use and it can't differentiate between pressing a cancel button (labeled with OptOut text) and pressing X or ESC.\n                cancel = Content.Cancel;\n            }\n            int result = DisplayDialogComplex(title, message, ok, cancel, string.Format(\"{0} - {1}\", ok, optOutText));\n            // result 0 -> OK, 1 -> Cancel, 2 -> Ok & opt out\n            optOutDecision = result == 2;\n            return result != 1;\n        }\n\n        public static void DisplayPopupMenu(Rect position, string menuItemPath, MenuCommand command)\n        {\n            if (ModeService.HasContextMenu(menuItemPath))\n            {\n                ModeService.PopupContextMenu(menuItemPath);\n            }\n            else\n            {\n                // Validate input. Fixes case 406024: 'Custom context menu in a custom window crashes Unity'\n                if (menuItemPath == \"CONTEXT\" || menuItemPath == \"CONTEXT/\" || menuItemPath == \"CONTEXT\\\\\")\n                {\n                    bool error = command == null || command.context == null;\n                    if (error)\n                    {\n                        Debug.LogError(\"DisplayPopupMenu: invalid arguments: using CONTEXT requires a valid MenuCommand object. If you want a custom context menu then try using the GenericMenu.\");\n                        return;\n                    }\n                }\n\n                Vector2 temp = GUIUtility.GUIToScreenPoint(new Vector2(position.x, position.y));\n                position.x = temp.x;\n                position.y = temp.y;\n                Internal_DisplayPopupMenu(position, menuItemPath, command?.context, command?.userData ?? 0);\n            }\n            ResetMouseDown();\n        }\n\n        public static void DisplayCustomMenu(Rect position, GUIContent[] options, int selected, SelectMenuItemFunction callback, object userData)\n        {\n            DisplayCustomMenu(position, options, null, selected, callback, userData, false);\n        }\n\n        public static void DisplayCustomMenu(Rect position, GUIContent[] options, int selected, SelectMenuItemFunction callback, object userData, bool showHotkey)\n        {\n            DisplayCustomMenu(position, options, null, selected, callback, userData, showHotkey);\n        }\n\n        public static void DisplayCustomMenu(Rect position, GUIContent[] options, Func<int, bool> checkEnabled, int selected, SelectMenuItemFunction callback, object userData, bool showHotkey = false)\n        {\n            int[] selectedArray = { selected };\n            string[] strings = new string[options.Length];\n            for (int i = 0; i < options.Length; i++)\n                strings[i] = options[i].text;\n\n            bool[] enabled;\n            if (checkEnabled != null)\n            {\n                enabled = new bool[strings.Length];\n                for (int i = 0; i < strings.Length; i++)\n                {\n                    enabled[i] = checkEnabled(i);\n                }\n            }\n            else\n            {\n                enabled = Enumerable.Repeat(true, options.Length).ToArray();\n            }\n            DisplayCustomMenu(position, strings, enabled, selectedArray, callback, userData, showHotkey);\n        }\n\n        public static string FormatBytes(int bytes)\n        {\n            return FormatBytes((long)bytes);\n        }\n\n        [Obsolete(\"Use EditorUtility.SetSelectedRenderState\", false)]\n        public static void SetSelectedWireframeHidden(Renderer renderer, bool enabled)\n        {\n            SetSelectedRenderState(renderer,\n                enabled\n                ? EditorSelectedRenderState.Hidden\n                : EditorSelectedRenderState.Wireframe | EditorSelectedRenderState.Highlight);\n        }\n\n        public static GameObject CreateGameObjectWithHideFlags(string name, HideFlags flags, params Type[] components)\n        {\n            GameObject go = Internal_CreateGameObjectWithHideFlags(name, flags);\n            // always add Transform\n            go.AddComponent(typeof(Transform));\n            foreach (Type t in components)\n                go.AddComponent(t);\n            return go;\n        }\n\n        internal static bool IsHiddenInInspector(Editor editor)\n        {\n            if (!editor || editor.hideInspector)\n                return true;\n\n            // Check for missing scripts or check is serializedObject can be created.\n            if (editor.target == null && editor.serializedObject?.FindProperty(\"m_Script\") != null)\n                return false;\n\n            if (editor.inspectorMode != InspectorMode.Normal)\n                return false;\n\n            return IsHiddenInInspector(editor.target);\n        }\n\n        internal static bool IsHiddenInInspector(UnityEngine.Object target)\n        {\n            if (!target)\n                return true;\n\n            return (target.hideFlags & HideFlags.HideInInspector) == HideFlags.HideInInspector;\n        }\n\n        [Obsolete(message: \"Use UnityEditor.Compilation.AssemblyBuilder instead\", error: true)]\n        public static string[] CompileCSharp(string[] scripts, string[] references, string[] defines, string outputAssembly)\n        {\n            throw new NotSupportedException(\"CompileCSharp is no longer supported. Use UnityEditor.Compilation.AssemblyBuilder instead.\");\n        }\n\n        [Obsolete(\"Use PrefabUtility.InstantiatePrefab\", false)]\n        public static Object InstantiatePrefab(Object target)\n        {\n            return PrefabUtility.InstantiatePrefab(target);\n        }\n\n        [Obsolete(\"Use PrefabUtility.SaveAsPrefabAsset with a path instead.\", false)]\n        public static GameObject ReplacePrefab(GameObject go, Object targetPrefab, ReplacePrefabOptions options)\n        {\n            return PrefabUtility.ReplacePrefab(go, targetPrefab, options);\n        }\n\n        [Obsolete(\"Use PrefabUtility.SaveAsPrefabAsset or PrefabUtility.SaveAsPrefabAssetAndConnect with a path instead.\", false)]\n        public static GameObject ReplacePrefab(GameObject go, Object targetPrefab)\n        {\n            return PrefabUtility.ReplacePrefab(go, targetPrefab, ReplacePrefabOptions.Default);\n        }\n\n        [Obsolete(\"The concept of creating a completely empty Prefab has been discontinued. You can however use PrefabUtility.SaveAsPrefabAsset with an empty GameObject.\", false)]\n        public static Object CreateEmptyPrefab(string path)\n        {\n            return PrefabUtility.CreateEmptyPrefab(path);\n        }\n\n        [Obsolete(\"This method does nothing. Use PrefabUtility.RevertPrefabInstance.\", false)]\n        public static bool ReconnectToLastPrefab(GameObject go)\n        {\n            return false;\n        }\n\n        [Obsolete(\"Use PrefabUtility.GetPrefabAssetType and PrefabUtility.GetPrefabInstanceStatus to get the full picture about Prefab types.\", false)]\n        public static PrefabType GetPrefabType(Object target)\n        {\n            return PrefabUtility.GetPrefabType(target);\n        }\n\n        [Obsolete(\"Use PrefabUtility.GetCorrespondingObjectFromSource.\", false)]\n        public static Object GetPrefabParent(Object source)\n        {\n            return PrefabUtility.GetCorrespondingObjectFromSource(source);\n        }\n\n        [Obsolete(\"Use PrefabUtility.GetOutermostPrefabInstanceRoot if source is a Prefab instance or source.transform.root.gameObject if source is a Prefab Asset object.\", false)]\n        public static GameObject FindPrefabRoot(GameObject source)\n        {\n            return PrefabUtility.FindPrefabRoot(source);\n        }\n\n        [Obsolete(\"Use PrefabUtility.RevertObjectOverride.\", false)]\n        public static bool ResetToPrefabState(Object source)\n        {\n            return PrefabUtility.ResetToPrefabState(source);\n        }\n\n        internal static void ResetMouseDown()\n        {\n            Tools.s_ButtonDown = -1;\n            GUIUtility.hotControl = 0;\n            //Delay call because the freezing of the editor is affecting the active clutch shortcuts resetting properly\n            EditorApplication.delayCall += () => ShortcutIntegration.instance.trigger.ResetActiveClutches();\n            onResetMouseDown?.Invoke();\n        }\n\n        internal static void DisplayCustomMenu(Rect position, string[] options, int[] selected, SelectMenuItemFunction callback, object userData)\n        {\n            DisplayCustomMenu(position, options, selected, callback, userData, false);\n        }\n\n        internal static void DisplayCustomMenu(Rect position, string[] options, int[] selected, SelectMenuItemFunction callback, object userData, bool showHotkey)\n        {\n            bool[] separator = new bool[options.Length];\n            DisplayCustomMenuWithSeparators(position, options, separator, selected, callback, userData, showHotkey);\n        }\n\n        internal static void DisplayCustomMenuWithSeparators(Rect position, string[] options, bool[] separator, int[] selected, SelectMenuItemFunction callback, object userData)\n        {\n            DisplayCustomMenuWithSeparators(position, options, separator, selected, callback, userData, false);\n        }\n\n        internal static void DisplayCustomMenuWithSeparators(Rect position, string[] options, bool[] separator, int[] selected, SelectMenuItemFunction callback, object userData, bool showHotkey)\n        {\n            bool[] enabled = Enumerable.Repeat(true, options.Length).ToArray();\n\n            Vector2 temp = GUIUtility.GUIToScreenPoint(new Vector2(position.x, position.y));\n            position.x = temp.x;\n            position.y = temp.y;\n            Internal_DisplayCustomMenu(position, options, enabled, separator, selected, callback, userData, showHotkey);\n            ResetMouseDown();\n        }\n\n        internal static void DisplayCustomMenu(Rect position, string[] options, bool[] enabled, int[] selected, SelectMenuItemFunction callback, object userData)\n        {\n            DisplayCustomMenu(position, options, enabled, selected, callback, userData, false);\n        }\n\n        internal static void DisplayCustomMenu(Rect position, string[] options, bool[] enabled, int[] selected, SelectMenuItemFunction callback, object userData, bool showHotkey)\n        {\n            bool[] separator = new bool[options.Length];\n            DisplayCustomMenuWithSeparators(position, options, enabled, separator, selected, callback, userData, showHotkey);\n        }\n\n        public static void DisplayCustomMenuWithSeparators(Rect position, string[] options, bool[] enabled, bool[] separator, int[] selected, SelectMenuItemFunction callback, object userData)\n        {\n            DisplayCustomMenuWithSeparators(position, options, enabled, separator, selected, callback, userData, false);\n        }\n\n        internal static void DisplayCustomMenuWithSeparators(Rect position, string[] options, bool[] enabled, bool[] separator, int[] selected, SelectMenuItemFunction callback, object userData, bool showHotkey)\n        {\n            DisplayCustomMenuWithSeparators(position, options, enabled, separator, selected, callback, userData, showHotkey, false);\n        }\n\n\n        //This method is only valid during onGUI callbacks, prefer DisplayCustomMenuWithSeparatorsWithScreenSpacePosition that work al the time. \n        internal static void DisplayCustomMenuWithSeparators(Rect position, string[] options, bool[] enabled, bool[] separator, int[] selected, SelectMenuItemFunction callback, object userData, bool showHotkey, bool allowDisplayNames, bool shouldDiscardMenuOnSecondClick = false)\n        {\n            Vector2 temp = GUIUtility.GUIToScreenPoint(new Vector2(position.x, position.y));\n            position.x = temp.x;\n            position.y = temp.y;\n\n            DisplayCustomMenuWithSeparatorsWithScreenSpacePosition(position, options, enabled, separator, selected, callback, userData, showHotkey, allowDisplayNames, shouldDiscardMenuOnSecondClick);\n        }\n\n        internal static void DisplayCustomMenuWithSeparatorsWithScreenSpacePosition(Rect position, string[] options, bool[] enabled, bool[] separator, int[] selected, SelectMenuItemFunction callback, object userData, bool showHotkey, bool allowDisplayNames, bool shouldDiscardMenuOnSecondClick)\n        {\n            Internal_DisplayCustomMenu(position, options, enabled, separator, selected, callback, userData, showHotkey, allowDisplayNames, shouldDiscardMenuOnSecondClick);\n            ResetMouseDown();\n        }\n\n        internal static void DisplayObjectContextMenu(Rect position, Object context, int contextUserData)\n        {\n            DisplayObjectContextMenu(position, new[] { context }, contextUserData);\n        }\n\n        internal static void DisplayObjectContextMenu(Rect position, Object[] context, int contextUserData)\n        {\n            // Don't show context menu if we're inside the side-by-side diff comparison.\n            if (EditorGUIUtility.comparisonViewMode != EditorGUIUtility.ComparisonViewMode.None)\n                return;\n\n            Vector2 temp = GUIUtility.GUIToScreenPoint(new Vector2(position.x, position.y));\n            position.x = temp.x;\n            position.y = temp.y;\n\n            GenericMenu pm = new GenericMenu();\n\n            if (context != null && context.Length == 1 && context[0] is Component)\n            {\n                Object targetObject = context[0];\n                Component targetComponent = (Component)targetObject;\n\n                // Do nothing if component is not on a prefab instance.\n                if (PrefabUtility.GetCorrespondingConnectedObjectFromSource(targetComponent.gameObject) == null) { }\n                // Handle added component.\n                else if (PrefabUtility.GetCorrespondingObjectFromSource(targetObject) == null && targetComponent != null)\n                {\n                    GameObject instanceGo = targetComponent.gameObject;\n                    PrefabUtility.HandleApplyRevertMenuItems(\n                        \"Added Component\",\n                        instanceGo,\n                        (menuItemContent, sourceGo, _) =>\n                        {\n                            TargetChoiceHandler.ObjectInstanceAndSourcePathInfo info = new TargetChoiceHandler.ObjectInstanceAndSourcePathInfo();\n                            info.instanceObject = targetComponent;\n                            info.assetPath = AssetDatabase.GetAssetPath(sourceGo);\n                            GameObject rootObject = PrefabUtility.GetRootGameObject(sourceGo);\n\n                            if (targetComponent.hideFlags.HasFlag(HideFlags.DontSaveInEditor)\n                                || !PrefabUtility.IsPartOfPrefabThatCanBeAppliedTo(rootObject)\n                                || EditorUtility.IsPersistent(instanceGo))\n                            {\n                                pm.AddDisabledItem(menuItemContent);\n                            }\n                            else\n                            {\n                                pm.AddItem(menuItemContent, false, TargetChoiceHandler.ApplyPrefabAddedComponent, info);\n                            }\n                        },\n                        (menuItemContent) =>\n                        {\n                            pm.AddItem(menuItemContent, false, TargetChoiceHandler.RevertPrefabAddedComponent, targetComponent);\n                        }\n                    );\n                }\n                else\n                {\n                    bool hasPrefabOverride = false;\n                    using (var so = new SerializedObject(targetObject))\n                    {\n                        SerializedProperty property = so.GetIterator();\n                        while (property.Next(property.hasChildren))\n                        {\n                            if (property.isInstantiatedPrefab && property.prefabOverride && !property.isDefaultOverride)\n                            {\n                                hasPrefabOverride = true;\n                                break;\n                            }\n                        }\n                    }\n\n                    var coupledComponent = targetComponent.GetCoupledComponent();\n                    if (!hasPrefabOverride && coupledComponent != null)\n                    {\n                        using (var so = new SerializedObject(coupledComponent))\n                        {\n                            SerializedProperty property = so.GetIterator();\n                            while (property.Next(property.hasChildren))\n                            {\n                                if (property.isInstantiatedPrefab && property.prefabOverride && !property.isDefaultOverride)\n                                {\n                                    hasPrefabOverride = true;\n                                    break;\n                                }\n                            }\n                        }\n                    }\n\n                    // Handle modified component.\n                    if (hasPrefabOverride)\n                    {\n                        bool isObjectOverrideAllDefaultOverridesComparedToOriginalSource =\n                            PrefabUtility.IsObjectOverrideAllDefaultOverridesComparedToOriginalSource(targetObject);\n\n                        PrefabUtility.HandleApplyRevertMenuItems(\n                            \"Modified Component\",\n                            targetObject,\n                            (menuItemContent, sourceObject, instanceOrAssetObject) =>\n                            {\n                                TargetChoiceHandler.ObjectInstanceAndSourcePathInfo info = new TargetChoiceHandler.ObjectInstanceAndSourcePathInfo();\n                                info.instanceObject = targetObject;\n                                info.assetPath = AssetDatabase.GetAssetPath(sourceObject);\n                                GameObject rootObject = PrefabUtility.GetRootGameObject(sourceObject);\n                                bool isPersistent = EditorUtility.IsPersistent(instanceOrAssetObject);\n\n                                if (isPersistent || !PrefabUtility.IsPartOfPrefabThatCanBeAppliedTo(rootObject) || !PrefabUtility.HasApplicableObjectOverridesForTarget(instanceOrAssetObject, rootObject, false))\n                                    pm.AddDisabledItem(menuItemContent);\n                                else\n                                    pm.AddItem(menuItemContent, false, TargetChoiceHandler.ApplyPrefabObjectOverride, info);\n                            },\n                            (menuItemContent) =>\n                            {\n                                pm.AddItem(menuItemContent, false, TargetChoiceHandler.RevertPrefabObjectOverride, targetObject);\n                            },\n                            isObjectOverrideAllDefaultOverridesComparedToOriginalSource\n                        );\n                    }\n                }\n\n                bool isComponentAddedInNestedPrefab = false;\n\n                Object source = PrefabUtility.GetCorrespondingObjectFromSource(targetObject);\n                while (source)\n                {\n                    if (PrefabUtility.IsAddedComponentOverride(source))\n                    {\n                        isComponentAddedInNestedPrefab = true;\n                        break;\n                    }\n\n                    source = PrefabUtility.GetCorrespondingObjectFromSource(source);\n                }\n\n                if (isComponentAddedInNestedPrefab)\n                {\n                    pm.AddItem(new GUIContent(\"Go to Added Component in '\" + PrefabUtility.GetPrefabAssetRootGameObject(source).name + \"'\"), false,\n                    () => PrefabStageUtility.OpenPrefab(AssetDatabase.GetAssetPath(source), PrefabUtility.GetGameObject(targetObject), PrefabStage.Mode.InIsolation));\n                }\n\n            }\n            else if (context != null && context.Length == 1 && context[0] is Material)\n            {\n                MaterialEditor.AddAdditionalMaterialMenuItems(pm);\n            }\n\n            pm.ObjectContextDropDown(position, context, contextUserData);\n\n            ResetMouseDown();\n        }\n\n        internal static void Internal_DisplayPopupMenu(Rect position, string menuItemPath, Object context, int contextUserData, bool shouldDiscardMenuOnSecondClick = false)\n        {\n            Private_DisplayPopupMenu(position, menuItemPath, context, contextUserData, shouldDiscardMenuOnSecondClick);\n        }\n\n        internal static void ConfigurePreviewObjectSRP(GameObject go)\n        {\n            if (GraphicsSettings.isScriptableRenderPipelineEnabled &&\n                go.TryGetComponent<Renderer>(out var renderer))\n            {\n                // Case 1297670: Force the ambient probe for object preview in SRP.\n                renderer.lightProbeUsage = LightProbeUsage.Off;\n            }\n        }\n\n        internal static void InitInstantiatedPreviewRecursive(GameObject go)\n        {\n            go.hideFlags = HideFlags.HideAndDontSave;\n            ConfigurePreviewObjectSRP(go);\n            foreach (Transform c in go.transform)\n                InitInstantiatedPreviewRecursive(c.gameObject);\n        }\n\n        internal static GameObject InstantiateForAnimatorPreview(Object original)\n        {\n            if (original == null)\n                throw new ArgumentException(\"The Prefab you want to instantiate is null.\");\n\n            GameObject go = InstantiateRemoveAllNonAnimationComponents(original, Vector3.zero, Quaternion.identity) as GameObject;\n            go.name = go.name + \"AnimatorPreview\";       //To avoid FindGameObject picking up our dummy object\n            go.tag = \"Untagged\";\n            InitInstantiatedPreviewRecursive(go);\n\n            Animator[] animators = go.GetComponentsInChildren<Animator>();\n            for (int i = 0; i < animators.Length; i++)\n            {\n                Animator animator = animators[i];\n\n                animator.enabled = false;\n                animator.cullingMode = AnimatorCullingMode.AlwaysAnimate;\n                animator.logWarnings = false;\n                animator.fireEvents = false;\n            }\n\n            // We absolutely need an animator on the gameObject\n            if (animators.Length == 0)\n            {\n                Animator animator = go.AddComponent<Animator>();\n                animator.enabled = false;\n                animator.cullingMode = AnimatorCullingMode.AlwaysAnimate;\n                animator.logWarnings = false;\n                animator.fireEvents = false;\n            }\n\n            return go;\n        }\n\n        internal static Object InstantiateRemoveAllNonAnimationComponents(Object original, Vector3 position, Quaternion rotation)\n        {\n            if (original == null)\n                throw new ArgumentException(\"The Prefab you want to instantiate is null.\");\n\n            return Internal_InstantiateRemoveAllNonAnimationComponentsSingle(original, position, rotation);\n        }\n\n        private static void Internal_DisplayCustomMenu(Rect screenPosition, string[] options, bool[] enabled, bool[] separator, int[] selected, SelectMenuItemFunction callback, object userData, bool showHotkey, bool allowDisplayNames = false, bool shouldDiscardMenuOnSecondClick = false)\n        {\n            DisplayCustomContextPopupMenu(screenPosition, options, enabled, separator, selected, callback, userData, showHotkey, allowDisplayNames, shouldDiscardMenuOnSecondClick);\n        }\n\n        internal static string GetTransformPath(Transform tform)\n        {\n            if (tform.parent == null)\n                return \"/\" + tform.name;\n            return GetTransformPath(tform.parent) + \"/\" + tform.name;\n        }\n\n        internal static string GetHierarchyPath(GameObject gameObject, bool includeScene = true)\n        {\n            if (gameObject == null)\n                return String.Empty;\n\n            StringBuilder sb;\n            if (_SbPool.Count > 0)\n            {\n                sb = _SbPool.Pop();\n                sb.Clear();\n            }\n            else\n            {\n                sb = new StringBuilder(200);\n            }\n\n            try\n            {\n                if (includeScene)\n                {\n                    var sceneName = gameObject.scene.name;\n                    if (sceneName == string.Empty)\n                    {\n                        var prefabStage = PrefabStageUtility.GetPrefabStage(gameObject);\n                        if (prefabStage != null)\n                        {\n                            sceneName = \"Prefab Stage\";\n                        }\n                        else\n                        {\n                            sceneName = \"Unsaved Scene\";\n                        }\n                    }\n\n                    sb.Append(sceneName);\n                }\n\n                sb.Append(GetTransformPath(gameObject.transform));\n\n                var path = sb.ToString();\n                sb.Clear();\n                return path;\n            }\n            finally\n            {\n                _SbPool.Push(sb);\n            }\n        }\n\n        public static void SetCustomDiffTool(string  path, string twoWayDiff, string threeWayDiff, string mergeCommand, bool forceEnableCustomTool = false)\n        {\n            InternalEditorUtility.SetCustomDiffToolPrefs(path, twoWayDiff, threeWayDiff, mergeCommand);\n            PreferencesProvider.ReloadCustomDiffToolData();\n            if (forceEnableCustomTool)\n                PreferencesProvider.ForceEnableCustomTool();\n        }\n\n        public static void SetDefaultParentObject(GameObject defaultParentObject)\n        {\n            defaultParentObject = !PrefabStageUtility.IsGameObjectThePrefabRootInAnyPrefabStage(defaultParentObject) ? defaultParentObject : null;\n            SceneHierarchy.SetDefaultParentObject(false, defaultParentObject);\n        }\n\n        public static void ClearDefaultParentObject(Scene scene)\n        {\n            if (scene != null)\n                SceneHierarchy.ClearDefaultParentObject(scene.guid);\n            else\n                SceneHierarchy.ClearDefaultParentObject(\"\");\n        }\n\n        public static void ClearDefaultParentObject()\n        {\n            SceneHierarchy.ClearDefaultParentObject();\n        }\n\n        public static void OpenPropertyEditor(Object obj)\n        {\n            PropertyEditor.OpenPropertyEditor(obj);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorWindow.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/Windowing/ContainerWindow.bindings.h\")]\n    public partial class EditorWindow\n    {\n        [FreeFunction(\"ContainerWindowBindings::MakeModal\")]\n        internal static extern void Internal_MakeModal(ContainerWindow win);\n\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EditorWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Linq;\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Overlays;\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine.Scripting;\nusing UnityEngine.Internal;\nusing SerializableJsonDictionary = UnityEditor.UIElements.SerializableJsonDictionary;\nusing UnityEngine.UIElements;\nusing UnityEditor.UIElements;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [UsedByNativeCode, ExcludeFromObjectFactory]\n    public partial class EditorWindow : ScriptableObject\n    {\n        [HideInInspector]\n        bool m_AutoRepaintOnSceneChange;\n\n        [SerializeField]\n        [HideInInspector]\n        Vector2 m_MinSize = new Vector2(50, 50);\n\n        [SerializeField]\n        [HideInInspector]\n        Vector2 m_MaxSize = new Vector2(4000, 4000);\n\n        [SerializeField]\n        [HideInInspector]\n        internal GUIContent m_TitleContent;\n\n        // We use a 24-bit depth/stencil buffer by default to support the UIRenderer clipping feature\n        [HideInInspector]\n        int m_DepthBufferBits = 24;\n        [HideInInspector]\n        int m_AntiAliasing = 1;\n\n        [HideInInspector]\n        bool m_ResetPanelRenderingOnAssetChange = true;\n\n        [SerializeField]\n        [HideInInspector]\n        internal Rect m_Pos = new Rect(0, 0, 320, 550);\n\n        [SerializeField]\n        [HideInInspector]\n        internal DataModeController m_SerializedDataModeController;\n        public IDataModeController dataModeController => GetDataModeController_Internal(); // For each editor window.\n        internal DataModeController GetDataModeController_Internal()  // For HostView to use internally.\n            => m_SerializedDataModeController ??= new DataModeController();\n\n        private VisualElement m_UIRootElement;\n\n        internal VisualElement baseRootVisualElement\n        {\n            [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n            get => m_UIRootElement ??= CreateRoot();\n        }\n\n        public VisualElement rootVisualElement\n        {\n            get\n            {\n                if (this is ISupportsOverlays)\n                {\n                    if (!m_OverlaysInitialized)\n                    {\n                        var ve = overlayCanvas.rootVisualElement;\n                        baseRootVisualElement.Add(ve);\n                        overlayCanvas.Initialize(this);\n                        m_OverlaysInitialized = true;\n                    }\n\n                    return overlayCanvas.windowRoot;\n                }\n                return baseRootVisualElement;\n            }\n        }\n\n        internal virtual bool liveReloadPreferenceDefault => false;\n        internal virtual BindingLogLevel defaultBindingLogLevel => BindingLogLevel.All;\n        internal bool isUIToolkitWindow => m_UIRootElement != null && m_UIRootElement.childCount > 0;\n\n        [HideInInspector]\n        [SerializeField]\n        private SerializableJsonDictionary m_ViewDataDictionary;\n\n        [HideInInspector]\n        [SerializeField]\n        OverlayCanvas m_OverlayCanvas = new OverlayCanvas();\n\n        public OverlayCanvas overlayCanvas => m_OverlayCanvas;\n\n        [NonSerialized]\n        bool m_OverlaysInitialized;\n\n        private bool m_EnableViewDataPersistence;\n\n        private bool m_RequestedViewDataSave;\n\n        private static Action s_UpdateWindowMenuListingOff;\n\n        internal SerializableJsonDictionary viewDataDictionary\n        {\n            get\n            {\n                // If persistence is disabled, just don't even create the dictionary. Return null.\n                if (m_EnableViewDataPersistence && m_ViewDataDictionary == null)\n                {\n                    string editorPrefFileName = this.GetType().ToString();\n                    m_ViewDataDictionary = UIElements.EditorWindowViewData.instance[editorPrefFileName];\n                }\n                return m_ViewDataDictionary;\n            }\n        }\n\n        // This list contains all the editor windows that are already enabled/active/alive.\n        // It is important to check if your window is contained in this list before doing anything,\n        // such like UI build/rebuild.\n        internal static List<EditorWindow> activeEditorWindows { get; } = new List<EditorWindow>();\n\n        internal void SaveViewData()\n        {\n            m_RequestedViewDataSave = true;\n        }\n\n        private void SaveViewDataToDisk()\n        {\n            if (!m_EnableViewDataPersistence || m_ViewDataDictionary == null || !m_RequestedViewDataSave)\n                return;\n\n            string editorPrefFileName = this.GetType().ToString();\n            EditorWindowViewData.instance.Save(editorPrefFileName, m_ViewDataDictionary);\n\n            m_RequestedViewDataSave = false;\n        }\n\n        internal ISerializableJsonDictionary GetViewDataDictionary()\n        {\n            return viewDataDictionary;\n        }\n\n        // TODO: These should be made public when UIElements is no longer experimental.\n        internal void DisableViewDataPersistence()\n        {\n            m_EnableViewDataPersistence = false;\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal void ClearPersistentViewData()\n        {\n            string editorPrefFileName = this.GetType().ToString();\n            UIElements.EditorWindowViewData.instance.Clear(editorPrefFileName);\n            DestroyImmediate(m_ViewDataDictionary);\n            m_ViewDataDictionary = null;\n        }\n\n        [NonSerialized] internal bool m_IsPresented = false;\n\n        // The GameView rect is in GUI space of the view\n        Rect m_GameViewRect;\n        Rect m_GameViewClippedRect;\n        Vector2 m_GameViewTargetSize;\n        EventInterests m_EventInterests = new EventInterests();\n        bool m_DisableInputEvents;\n\n        // Dockarea we're inside.\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        [NonSerialized]\n        internal HostView m_Parent;\n\n        // Overlay a notification message over the window.\n        const double kWarningFadeoutWait = 4;\n        const double kWarningFadeoutTime = 1;\n\n        internal GUIContent m_Notification = null;\n        Vector2 m_NotificationSize;\n        internal float m_FadeoutTime = 0;\n\n        // Mark the beginning area of all popup windows.\n        public void BeginWindows()\n        {\n            EditorGUIInternal.BeginWindowsForward(1, GetInstanceID());\n        }\n\n        // Close a window group started with EditorWindow::ref::BeginWindows\n        public void EndWindows()\n        {\n            GUI.EndWindows();\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal virtual void OnResized()  {}\n\n        internal virtual void OnBackgroundViewResized(Rect pos) {}\n\n        // Does the GUI in this editor window want MouseMove events?\n        public bool wantsMouseMove\n        {\n            get\n            {\n                return m_EventInterests.wantsMouseMove;\n            }\n            set\n            {\n                m_EventInterests.wantsMouseMove = value;\n                MakeParentsSettingsMatchMe();\n            }\n        }\n\n        // Does the GUI in this editor window want MouseEnter/LeaveWindow events?\n        public bool wantsMouseEnterLeaveWindow\n        {\n            get\n            {\n                return m_EventInterests.wantsMouseEnterLeaveWindow;\n            }\n            set\n            {\n                m_EventInterests.wantsMouseEnterLeaveWindow = value;\n                MakeParentsSettingsMatchMe();\n            }\n        }\n\n        // Indicates that the editor window will only receive a layout pass before a repaint event.\n        public bool wantsLessLayoutEvents\n        {\n            get\n            {\n                return m_EventInterests.wantsLessLayoutEvents;\n            }\n            set\n            {\n                m_EventInterests.wantsLessLayoutEvents = value;\n                MakeParentsSettingsMatchMe();\n            }\n        }\n\n        internal void CheckForWindowRepaint()\n        {\n            double time = EditorApplication.timeSinceStartup;\n            if (time < m_FadeoutTime)\n                return;\n            if (time > m_FadeoutTime + kWarningFadeoutTime)\n            {\n                RemoveNotification();\n                return;\n            }\n            Repaint();\n        }\n\n        internal CustomYieldInstruction WaitUntilPresented() => new WaitUntil(() => m_IsPresented);\n\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal GUIContent GetLocalizedTitleContent()\n        {\n            return GetLocalizedTitleContentFromType(GetType());\n        }\n\n        internal static GUIContent GetLocalizedTitleContentFromType(Type t)\n        {\n            EditorWindowTitleAttribute attr = GetEditorWindowTitleAttribute(t);\n            if (attr != null)\n            {\n                string iconName = \"\";\n                if (!string.IsNullOrEmpty(attr.icon))\n                    iconName = attr.icon;\n                else if (attr.useTypeNameAsIconName)\n                    iconName = t.ToString();\n\n                if (!string.IsNullOrEmpty(iconName) && EditorGUIUtility.LoadIcon(iconName))\n                {\n                    // This should error msg if icon is not found since icon has been explicitly requested by the user\n                    return EditorGUIUtility.TrTextContentWithIcon(attr.title, iconName);\n                }\n\n                return EditorGUIUtility.TrTextContent(attr.title);\n            }\n\n            // Fallback to type name (Do not localize type name)\n            return new GUIContent(t.Name);\n        }\n\n        static EditorWindowTitleAttribute GetEditorWindowTitleAttribute(Type t)\n        {\n            object[] attrs = t.GetCustomAttributes(true);\n            foreach (object attr in attrs)\n            {\n                Attribute realAttr = (Attribute)attr;\n                if ((Type)realAttr.TypeId == typeof(EditorWindowTitleAttribute))\n                {\n                    return (EditorWindowTitleAttribute)attr;\n                }\n            }\n            return null;\n        }\n\n        // Show a notification message.\n        public void ShowNotification(GUIContent notification)\n        {\n            ShowNotification(notification, kWarningFadeoutWait);\n        }\n\n        public void ShowNotification(GUIContent notification, double fadeoutWait)\n        {\n            m_Notification = new GUIContent(notification);\n            if (m_FadeoutTime < Mathf.Epsilon)\n                EditorApplication.update += CheckForWindowRepaint;\n            m_FadeoutTime = (float)(EditorApplication.timeSinceStartup + fadeoutWait);\n        }\n\n        // Stop showing notification message.\n        public void RemoveNotification()\n        {\n            if (m_FadeoutTime == 0)\n                return;\n            EditorApplication.update -= CheckForWindowRepaint;\n            m_Notification = null;\n            m_FadeoutTime = 0;\n        }\n\n        internal void DrawNotification()\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            m_NotificationSize = EditorStyles.notificationText.CalcSize(m_Notification);\n\n            Vector2 warningSize = m_NotificationSize;\n            float targetWidth = position.width - EditorStyles.notificationText.margin.horizontal;\n            float targetHeight = position.height - EditorStyles.notificationText.margin.vertical - 20;\n\n            // See if we can fit horizontally. If not, rescale down.\n            GUIStyle scaledNotificationText = EditorStyles.notificationText;\n            if (targetWidth < m_NotificationSize.x)\n            {\n                float scale = targetWidth / m_NotificationSize.x;\n\n                scaledNotificationText = new GUIStyle(EditorStyles.notificationText);\n                scaledNotificationText.fontSize = Mathf.FloorToInt(scaledNotificationText.font.fontSize * scale);\n\n                warningSize = scaledNotificationText.CalcSize(m_Notification);\n            }\n\n            warningSize.x += 1; //we'll give the text a little room to breathe to avoid word-wrapping issues with drop shadows\n\n            if (warningSize.y > targetHeight)\n                warningSize.y = targetHeight;\n\n            Rect r = new Rect((position.width - warningSize.x - EditorStyles.notificationText.margin.horizontal) * .5f, 20 + (position.height - 20 - warningSize.y) * .7f, warningSize.x + EditorStyles.notificationText.margin.horizontal, warningSize.y);\n            double time = EditorApplication.timeSinceStartup;\n            if (time > m_FadeoutTime)\n                GUI.color = new Color(1, 1, 1, 1 - (float)((time - m_FadeoutTime) / kWarningFadeoutTime));\n            GUI.Label(r, GUIContent.none, EditorStyles.notificationBackground);\n            EditorGUI.DoDropShadowLabel(r, m_Notification, scaledNotificationText, .3f);\n        }\n\n        // Does the window automatically repaint whenever the scene has changed?\n        public bool autoRepaintOnSceneChange\n        {\n            get\n            {\n                return m_AutoRepaintOnSceneChange;\n            }\n            set\n            {\n                m_AutoRepaintOnSceneChange = value;\n                MakeParentsSettingsMatchMe();\n            }\n        }\n\n        public bool maximized\n        {\n            get\n            {\n                return WindowLayout.IsMaximized(this);\n            }\n            set\n            {\n                bool current = WindowLayout.IsMaximized(this);\n                if (value != current)\n                {\n                    if (value)\n                        WindowLayout.Maximize(this);\n                    else\n                        WindowLayout.Unmaximize(this);\n                }\n            }\n        }\n\n        internal virtual void OnMaximized() {}\n\n        internal virtual bool CanMaximize()\n        {\n            return true;\n        }\n\n        // Is EditorWindow focused?\n        public bool hasFocus { get { return m_Parent && m_Parent.actualView == this; } }\n\n        // Is EditorWindow docked?\n        public bool docked { get { return m_Parent != null && m_Parent.window != null && !m_Parent.window.IsNotDocked(); } }\n\n        // This property can be used to stop OS events from being sent to the EditorWindow\n        internal bool disableInputEvents\n        {\n            get { return m_DisableInputEvents; }\n            set\n            {\n                if (m_DisableInputEvents == value)\n                    return;\n                m_DisableInputEvents = value;\n                MakeParentsSettingsMatchMe();\n            }\n        }\n\n        // The EditorWindow which currently has keyboard focus (RO)\n        static public EditorWindow focusedWindow\n        {\n            get\n            {\n                HostView view = GUIView.focusedView as HostView;\n                if (view != null)\n                    return view.actualView;\n                else\n                    return null;\n            }\n        }\n\n        [Obsolete($\"Use {nameof(windowFocusChanged)} instead.\", false)]\n        static public Action focusedWindowChanged;\n\n        static public event Action windowFocusChanged;\n\n        static internal void OnWindowFocusChanged()\n        {\n            windowFocusChanged?.Invoke();\n        }\n\n        // The EditorWindow currently under the mouse cursor (RO)\n        static public EditorWindow mouseOverWindow\n        {\n            get\n            {\n                HostView view = GUIView.mouseOverView as HostView;\n                if (view != null)\n                    return view.actualView;\n                else\n                    return null;\n            }\n        }\n\n        internal int GetNumTabs()\n        {\n            DockArea da = m_Parent as DockArea;\n            if (da)\n            {\n                return da.m_Panes.Count;\n            }\n            return 0;\n        }\n\n        internal bool ShowNextTabIfPossible()\n        {\n            DockArea da = m_Parent as DockArea;\n            if (da)\n            {\n                int idx = da.m_Panes.IndexOf(this);\n                idx = (idx + 1) % da.m_Panes.Count;\n                if (da.selected != idx)\n                {\n                    da.selected = idx;\n                    da.Repaint();\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public void ShowTab()\n        {\n            DockArea da = m_Parent as DockArea;\n            if (da)\n            {\n                int idx = da.m_Panes.IndexOf(this);\n                if (da.selected != idx)\n                    da.selected = idx;\n            }\n\n            Repaint();\n        }\n\n        internal bool IsSelectedTab()\n        {\n            DockArea da = m_Parent as DockArea;\n            if (da)\n            {\n                int idx = da.m_Panes.IndexOf(this);\n                return da.selected == idx;\n            }\n            return false;\n        }\n\n        // Moves keyboard focus to this EditorWindow.\n        public void Focus()\n        {\n            if (m_Parent)\n            {\n                ShowTab();\n                m_Parent.Focus();\n            }\n        }\n\n        internal void MakeParentsSettingsMatchMe()\n        {\n            if (!m_Parent || m_Parent.actualView != this)\n                return;\n            m_Parent.SetTitle(GetType().FullName);\n            m_Parent.autoRepaintOnSceneChange = m_AutoRepaintOnSceneChange;\n            bool parentChanged =  m_Parent.depthBufferBits != m_DepthBufferBits || m_Parent.antiAliasing != m_AntiAliasing;\n            m_Parent.depthBufferBits = m_DepthBufferBits;\n            m_Parent.antiAliasing = m_AntiAliasing;\n            m_Parent.resetPanelRenderingOnAssetChange = m_ResetPanelRenderingOnAssetChange;\n            m_Parent.SetInternalGameViewDimensions(m_GameViewRect, m_GameViewClippedRect, m_GameViewTargetSize);\n            m_Parent.eventInterests = m_EventInterests;\n            m_Parent.disableInputEvents = m_DisableInputEvents;\n            Vector2 parentBorderSizes = new Vector2(m_Parent.borderSize.left + m_Parent.borderSize.right, m_Parent.borderSize.top + m_Parent.borderSize.bottom);\n            m_Parent.SetMinMaxSizes(minSize + parentBorderSizes, maxSize + parentBorderSizes);\n            m_Parent.SetPlayModeView(this is PlayModeView);\n            if (parentChanged)\n                m_Parent.RecreateContext();\n        }\n\n        // Show the EditorWindow as a floating utility window.\n        public void ShowUtility()\n        {\n            ShowWithMode(ShowMode.Utility);\n        }\n\n        internal void ShowTooltip()\n        {\n            ShowPopupWithMode(ShowMode.Tooltip, false);\n        }\n\n        public void ShowPopup()\n        {\n            ShowPopupWithMode(ShowMode.PopupMenu, true);\n        }\n\n        void MakeModal()\n        {\n            // If we already have modal window up we don't need to setup another modal message loop\n            if (ContainerWindow.s_Modal) return;\n\n            try\n            {\n                ContainerWindow.s_Modal = true;\n\n                SavedGUIState guiState = SavedGUIState.Create();\n                // TODO need to promote this outside of UIE\n                UnityEngine.UIElements.EventDispatcher.editorDispatcher.PushDispatcherContext();\n\n                Internal_MakeModal(m_Parent.window);\n\n                UnityEngine.UIElements.EventDispatcher.editorDispatcher.PopDispatcherContext();\n                guiState.ApplyAndForget();\n            }\n            finally\n            {\n                ContainerWindow.s_Modal = false;\n            }\n        }\n\n        public void ShowModalUtility()\n        {\n            ShowWithMode(ShowMode.ModalUtility);\n            MakeModal();\n        }\n\n        // Used for popup style windows.\n        internal void ShowPopupWithMode(ShowMode mode, bool giveFocus)\n        {\n            if (m_Parent == null)\n            {\n                ContainerWindow cw = ScriptableObject.CreateInstance<ContainerWindow>();\n                cw.title = titleContent.text;\n                HostView host = ScriptableObject.CreateInstance<HostView>();\n                host.actualView = this;\n                m_Parent = host;\n\n                Rect r = m_Parent.borderSize.Add(new Rect(position.x, position.y, position.width, position.height));\n                // Order is important here: first set rect of container, then assign main view, then apply various settings, then show.\n                // Otherwise the rect won't be set until first resize happens.\n                cw.position = r;\n                cw.rootView = host;\n                MakeParentsSettingsMatchMe();\n                cw.ShowPopupWithMode(mode, giveFocus);\n                cw.OnResize();\n            }\n        }\n\n        internal void ShowWithMode(ShowMode mode)\n        {\n            if (m_Parent == null)\n            {\n                SavedGUIState oldState = SavedGUIState.Create();\n\n                ContainerWindow cw = ScriptableObject.CreateInstance<ContainerWindow>();\n                cw.title = titleContent.text;\n                HostView host = ScriptableObject.CreateInstance<HostView>();\n                host.actualView = this;\n                m_Parent = host;\n\n                Rect r = m_Parent.borderSize.Add(new Rect(position.x, position.y, position.width, position.height));\n                // Order is important here: first set rect of container, then assign main view, then apply various settings, then show.\n                // Otherwise the rect won't be set until first resize happens.\n                cw.position = r;\n                cw.rootView = host;\n                MakeParentsSettingsMatchMe();\n                cw.Show(mode, loadPosition: true, displayImmediately: false, setFocus: true);\n                // set min/max size now that native window is not null so that it will e.g., use proper styleMask on macOS\n                cw.SetMinMaxSizes(minSize, maxSize);\n                cw.OnResize();\n                oldState.ApplyAndForget();\n            }\n        }\n\n        // Show window with dropdown behaviour (e.g. window is closed when it loses focus) and having\n        public void ShowAsDropDown(Rect buttonRect, Vector2 windowSize)\n        {\n            ShowAsDropDown(buttonRect, windowSize, null);\n        }\n\n        internal void ShowAsDropDown(Rect buttonRect, Vector2 windowSize, PopupLocation[] locationPriorityOrder)\n        {\n            ShowAsDropDown(buttonRect, windowSize, locationPriorityOrder, ShowMode.PopupMenu);\n        }\n\n        internal void ShowAsDropDown(Rect buttonRect, Vector2 windowSize, PopupLocation[] locationPriorityOrder, ShowMode mode)\n        {\n            ShowAsDropDown(buttonRect, windowSize, locationPriorityOrder, mode, true);\n        }\n\n        // Show as drop down list with custom fit to screen callback\n        // 'buttonRect' is used for displaying the dropdown below that rect if possible otherwise above\n        // 'windowSize' is used for setting up initial size\n        // 'locationPriorityOrder' is for manual popup direction, if null it uses default order: down, up, left or right\n        // 'giveFocus' is for whether the window should immediately be given focus (default true)\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal void ShowAsDropDown(Rect buttonRect, Vector2 windowSize, PopupLocation[] locationPriorityOrder, ShowMode mode, bool giveFocus)\n        {\n            // Setup position before bringing window live (otherwise the dropshadow on Windows will be placed in 0,0 first frame)\n            position = ShowAsDropDownFitToScreen(buttonRect, windowSize, locationPriorityOrder);\n\n            // ShowWithMode() always grabs window focus so we use ShowPopup() for popup windows so PopupWindowWithoutFocus\n            // will work correctly (no focus when opened).\n            if (ContainerWindow.IsPopup(mode))\n                ShowPopupWithMode(mode, giveFocus);\n            else\n                ShowWithMode(mode);\n\n            // Fit to screen again now that we have a container window\n            position = ShowAsDropDownFitToScreen(buttonRect, windowSize, locationPriorityOrder);\n\n            // Default to none resizable window\n            minSize = new Vector2(position.width, position.height);\n            maxSize = new Vector2(position.width, position.height);\n\n            // Focus window\n            if (giveFocus && focusedWindow != this)\n                Focus();\n            else\n                Repaint();\n\n            // Add after unfreezing display because AuxWindowManager.cpp assumes that aux windows are added after we got/lost- focus calls.\n            m_Parent.AddToAuxWindowList();\n\n            // Dropdown windows should not be saved to layout\n            m_Parent.window.m_DontSaveToLayout = true;\n        }\n\n        internal Rect ShowAsDropDownFitToScreen(Rect buttonRect, Vector2 windowSize, PopupLocation[] locationPriorityOrder)\n        {\n            if (m_Parent == null)\n                return new Rect(buttonRect.x, buttonRect.yMax, windowSize.x, windowSize.y);\n\n            return m_Parent.window.GetDropDownRect(buttonRect, windowSize, windowSize, locationPriorityOrder);\n        }\n\n        public void Show()\n        {\n            Show(false);\n        }\n\n        // Show the EditorWindow.\n        public void Show(bool immediateDisplay)\n        {\n            // If somebody called show on us, set up the neccessary structure for us.\n            if (m_Parent == null)\n                CreateNewWindowForEditorWindow(this, true, immediateDisplay);\n        }\n\n        // Show the editor window in the auxiliary window.\n        public void ShowAuxWindow()\n        {\n            ShowWithMode(ShowMode.AuxWindow);\n\n            // We ensure Focus change before calling AddToAuxWindowList because the\n            // AuxWindowManager assumes that focus has been changed before a new window is added.\n            Focus();\n\n            m_Parent.AddToAuxWindowList();\n        }\n\n        // Show modal editor window. Other windows will not be accessible until this one is closed.\n        public void ShowModal()\n        {\n            // It is normally bad to have different behavior on different platforms,\n            // but in this case Linux is espcially picky about converting modal dialogs.\n            // the only way we can ensure that without major API changes in window creation is to open them with this type.\n            if (Application.platform == RuntimePlatform.LinuxEditor)\n                ShowModalUtility();\n            else\n            {\n                ShowWithMode(ShowMode.AuxWindow);\n                // Make sure consumed events will not make window wait to get rendered\n                RepaintImmediately();\n                MakeModal();\n            }\n        }\n\n        static void AssignTitle(EditorWindow win, string title)\n        {\n            if (title != null)\n            {\n                win.titleContent = new GUIContent(title);\n                return;\n            }\n\n            // Do not assign anything new if the user has defined its own title.\n            var titleContent = GetLocalizedTitleContentFromType(win.GetType());\n            if (win.titleContent.text == win.GetType().ToString())\n            {\n                win.titleContent.text = titleContent.text;\n            }\n            if (win.titleContent.image == null)\n            {\n                win.titleContent.image = titleContent.image;\n            }\n        }\n\n        // Returns the first EditorWindow of type /t/ which is currently on the screen.\n        static EditorWindow GetWindowPrivate(System.Type t, bool utility, string title, bool focus, bool includeInheritingClasses = true)\n        {\n            UnityEngine.Object[] wins = Resources.FindObjectsOfTypeAll(t);\n            EditorWindow win = wins.Length > 0 ? (EditorWindow)(wins[0]) : null;\n\n            if(win != null && !includeInheritingClasses)\n            {\n                if(win.GetType().IsSubclassOf(t))\n                {\n                    win = null;\n                    for(int i = 1; i<wins.Length && win == null; ++i)\n                    {\n                        if(wins[i] != null && !wins[i].GetType().IsSubclassOf(t))\n                        {\n                            win = (EditorWindow)(wins[i]);\n                        }\n                    }\n                }\n            }\n\n            if (!win)\n            {\n                try\n                {\n                    win = ScriptableObject.CreateInstance(t) as EditorWindow;\n                    AssignTitle(win, title);\n                    if (utility)\n                        win.ShowUtility();\n                    else\n                        win.Show();\n                }\n                catch\n                {\n                    win.Close();\n                    throw;\n                }\n            }\n            else if (focus)\n            {\n                win.Show();  // For some corner cases in saved layouts, the window can be in an unvisible state.\n                             // Since the caller asked for focus, it's fair to assume he wants it always to be visible. (case 586743)\n                win.Focus();\n            }\n\n            return win;\n        }\n\n        public static EditorWindow GetWindow(System.Type windowType, [DefaultValue(\"false\")] bool utility, [DefaultValue(\"null\")] string title, [DefaultValue(\"true\")] bool focus)\n        {\n            return GetWindowPrivate(windowType, utility, title, focus);\n        }\n\n        [ExcludeFromDocs]\n        public static EditorWindow GetWindow(System.Type windowType, bool utility, string title)\n        {\n            return GetWindowPrivate(windowType, utility, title, true);\n        }\n\n        [ExcludeFromDocs]\n        public static EditorWindow GetWindow(System.Type windowType, bool utility)\n        {\n            return GetWindowPrivate(windowType, utility, null, true);\n        }\n\n        [ExcludeFromDocs]\n        public static EditorWindow GetWindow(System.Type windowType)\n        {\n            return GetWindowPrivate(windowType, false, null, true);\n        }\n\n        public static EditorWindow GetWindowWithRect(System.Type windowType, Rect rect, [DefaultValue(\"false\")] bool utility, [DefaultValue(\"null\")] string title)\n        {\n            return GetWindowWithRectPrivate(windowType, rect, utility, title);\n        }\n\n        [ExcludeFromDocs]\n        public static EditorWindow GetWindowWithRect(System.Type windowType, Rect rect, bool utility)\n        {\n            return GetWindowWithRectPrivate(windowType, rect, utility, null);\n        }\n\n        [ExcludeFromDocs]\n        public static EditorWindow GetWindowWithRect(System.Type windowType, Rect rect)\n        {\n            return GetWindowWithRectPrivate(windowType, rect, false, null);\n        }\n\n        internal static T GetWindowWithExactType<T>() where T : EditorWindow\n        {\n            return GetWindowPrivate(typeof(T), false, null, true, false) as T;\n        }\n\n        public static T GetWindow<T>() where T : EditorWindow\n        {\n            return GetWindow<T>(false, null, true);\n        }\n\n        public static T GetWindow<T>(bool utility) where T : EditorWindow\n        {\n            return GetWindow<T>(utility, null, true);\n        }\n\n        public static T GetWindow<T>(bool utility, string title) where T : EditorWindow\n        {\n            return GetWindow<T>(utility, title, true);\n        }\n\n        public static T GetWindow<T>(string title) where T : EditorWindow\n        {\n            return GetWindow<T>(title, true);\n        }\n\n        public static T GetWindow<T>(string title, bool focus) where T : EditorWindow\n        {\n            return GetWindow<T>(false, title, focus);\n        }\n\n        // Returns the first EditorWindow of type /T/ which is currently on the screen.\n        public static T GetWindow<T>(bool utility, string title, bool focus) where T : EditorWindow\n        {\n            return GetWindow(typeof(T), utility, title, focus) as T;\n        }\n\n        public static T GetWindow<T>(params System.Type[] desiredDockNextTo) where T : EditorWindow\n        {\n            return GetWindow<T>(null, true, desiredDockNextTo);\n        }\n\n        public static T GetWindow<T>(string title, params System.Type[] desiredDockNextTo) where T : EditorWindow\n        {\n            return GetWindow<T>(title, true, desiredDockNextTo);\n        }\n\n        // Returns the first EditorWindow of type /T/ which is currently on the screen.\n        public static T GetWindow<T>(string title, bool focus, params System.Type[] desiredDockNextTo) where T : EditorWindow\n        {\n            var wins = Resources.FindObjectsOfTypeAll(typeof(T)) as T[];\n            T win = wins.Length > 0 ? wins[0] : null;\n\n            //If the window already exists just focus then return it...\n            if (win != null)\n            {\n                if (focus)\n                    win.Focus();\n                return win;\n            }\n\n            return CreateWindow<T>(title, desiredDockNextTo);\n        }\n\n        public static T CreateWindow<T>(params System.Type[] desiredDockNextTo) where T : EditorWindow\n        {\n            return CreateWindow<T>(null, desiredDockNextTo);\n        }\n\n        public static T CreateWindow<T>(string title, params System.Type[] desiredDockNextTo) where T : EditorWindow\n        {\n            T win = CreateInstance<T>();\n\n            AssignTitle(win, title);\n\n            //Iterate the desired dock next to types...\n            foreach (var desired in desiredDockNextTo)\n            {\n                var windows = ContainerWindow.windows;\n                foreach (var w in windows)\n                {\n                    foreach (var view in w.rootView.allChildren)\n                    {\n                        var dockArea = view as DockArea;\n                        if (dockArea == null) continue;\n                        if (dockArea.m_Panes.Any(pane => pane.GetType() == desired))\n                        {\n                            dockArea.AddTab(win);\n                            return win;\n                        }\n                    }\n                }\n            }\n            win.Show();\n\n            return win;\n        }\n\n        public static bool HasOpenInstances<T>() where T : UnityEditor.EditorWindow\n        {\n            UnityEngine.Object[] wins = Resources.FindObjectsOfTypeAll(typeof(T));\n            return wins != null && wins.Length > 0;\n        }\n\n        // Focuses the first found EditorWindow of specified type if it is open.\n        public static void FocusWindowIfItsOpen(System.Type t)\n        {\n            UnityEngine.Object[] wins = Resources.FindObjectsOfTypeAll(t);\n            EditorWindow win = wins.Length > 0 ? (wins[0] as EditorWindow) : null;\n            if (win)\n                win.Focus();\n        }\n\n        // Focuses the first found EditorWindow of type /T/ if it is open.\n        public static void FocusWindowIfItsOpen<T>() where T : EditorWindow\n        {\n            FocusWindowIfItsOpen(typeof(T));\n        }\n\n        internal void RemoveFromDockArea()\n        {\n            DockArea da = m_Parent as DockArea;\n            if (da)\n            {\n                da.RemoveTab(this, true);\n            }\n        }\n\n        // Returns the first EditorWindow of type /t/ which is currently on the screen.\n        static EditorWindow GetWindowWithRectPrivate(System.Type t, Rect rect, bool utility, string title)\n        {\n            UnityEngine.Object[] wins = Resources.FindObjectsOfTypeAll(t);\n            EditorWindow win = wins.Length > 0 ? (EditorWindow)(wins[0]) : null;\n\n            if (!win)\n            {\n                win = ScriptableObject.CreateInstance(t) as EditorWindow;\n                win.minSize = new Vector2(rect.width, rect.height);\n                win.maxSize = new Vector2(rect.width, rect.height);\n                win.position = rect;\n                AssignTitle(win, title);\n                if (utility)\n                    win.ShowUtility();\n                else\n                    win.Show();\n            }\n            else\n                win.Focus();\n\n            return win;\n        }\n\n        public static T GetWindowWithRect<T>(Rect rect) where T : EditorWindow\n        {\n            return GetWindowWithRect<T>(rect, false, null, true);\n        }\n\n        public static T GetWindowWithRect<T>(Rect rect, bool utility) where T : EditorWindow\n        {\n            return GetWindowWithRect<T>(rect, utility, null, true);\n        }\n\n        public static T GetWindowWithRect<T>(Rect rect, bool utility, string title) where T : EditorWindow\n        {\n            return GetWindowWithRect<T>(rect, utility, title, true);\n        }\n\n        // Returns the first EditorWindow of type /t/ which is currently on the screen.\n        public static T GetWindowWithRect<T>(Rect rect, bool utility, string title, bool focus) where T : EditorWindow\n        {\n            UnityEngine.Object[] windows = Resources.FindObjectsOfTypeAll(typeof(T));\n            T window;\n\n            if (windows.Length > 0)\n            {\n                window = (T)windows[0];\n                if (focus)\n                    window.Focus();\n            }\n            else\n            {\n                window = ScriptableObject.CreateInstance<T>();\n                window.minSize = new Vector2(rect.width, rect.height);\n                window.maxSize = new Vector2(rect.width, rect.height);\n                window.position = rect;\n                AssignTitle(window, title);\n                if (utility)\n                    window.ShowUtility();\n                else\n                    window.Show();\n            }\n\n            return window;\n        }\n\n        internal static T GetWindowDontShow<T>() where T : EditorWindow\n        {\n            UnityEngine.Object[] windows = Resources.FindObjectsOfTypeAll(typeof(T));\n            return (windows.Length > 0) ? (T)windows[0] : ScriptableObject.CreateInstance<T>();\n        }\n\n        bool m_HasUnsavedChanges = false;\n        public bool hasUnsavedChanges\n        {\n            get\n            {\n                return m_HasUnsavedChanges;\n            }\n            protected set\n            {\n                if (m_HasUnsavedChanges != value)\n                {\n                    m_HasUnsavedChanges = value;\n                    m_Parent?.window?.UnsavedStateChanged();\n                }\n            }\n        }\n\n        public string saveChangesMessage { get; protected set; }\n\n        public virtual void SaveChanges()\n        {\n            hasUnsavedChanges = false;\n        }\n\n        public virtual void DiscardChanges()\n        {\n            hasUnsavedChanges = false;\n        }\n\n        // Close the editor window.\n        public void Close()\n        {\n            // Guard against multiple call to Close in the same stack\n            // (since we call DestroyImmediate at the end of Close()).\n            if (!this)\n                return;\n\n            // Ensure to restore normal workspace before destroying. Fix case 406657.\n            if (WindowLayout.IsMaximized(this))\n                WindowLayout.Unmaximize(this);\n\n            // [UUM-58449] If the focused window got closed, reset the IME composition mode to the default value. The normal codepaths may not run since this object is immediately destroyed.\n            if (focusedWindow == this)\n            {\n                GUIUtility.imeCompositionMode = IMECompositionMode.Auto;\n            }\n\n            DockArea da = m_Parent as DockArea;\n            if (da)\n            {\n                m_Parent.Focus();\n                da.RemoveTab(this, true);\n            }\n            else\n            {\n                m_Parent.window.Close();\n            }\n            UnityEngine.Object.DestroyImmediate(this, true);\n            UpdateWindowMenuListing();\n        }\n\n        // Make the window repaint.\n        public void Repaint()\n        {\n            if (m_Parent && m_Parent.actualView == this)\n            {\n                m_Parent.Repaint();\n            }\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal void RepaintImmediately()\n        {\n            if (m_Parent && m_Parent.actualView == this)\n                m_Parent.RepaintImmediately();\n        }\n\n        // the minimum size of this window\n        public Vector2 minSize\n        {\n            get\n            {\n                return m_MinSize;\n            }\n            set\n            {\n                if (!View.IsValidViewSize(value))\n                    throw new ArgumentException($\"Invalid minSize: {value}\");\n\n                m_MinSize = value;\n                MakeParentsSettingsMatchMe();\n            }\n        }\n\n        // the maximum size of this window\n        public Vector2 maxSize\n        {\n            get\n            {\n                return m_MaxSize;\n            }\n            set\n            {\n                if (!View.IsValidViewSize(value))\n                    throw new ArgumentException($\"Invalid minSize: {value}\");\n\n                m_MaxSize = value;\n                MakeParentsSettingsMatchMe();\n            }\n        }\n\n\n        // The title of this window (legacy)\n        [System.Obsolete(\"Use titleContent instead (it supports setting a title icon as well).\")]\n        public string title\n        {\n            get\n            {\n                return titleContent.text;\n            }\n            set\n            {\n                titleContent = EditorGUIUtility.TextContent(value);\n            }\n        }\n\n        public GUIContent titleContent\n        {\n            get\n            {\n                return m_TitleContent ?? (m_TitleContent = new GUIContent());  // Ensure m_TitleContent is not null (so we can prevent null checks)\n            }\n            set\n            {\n                m_TitleContent = value;\n                if (m_TitleContent != null && m_Parent && m_Parent.window && m_Parent.window.rootView == m_Parent)\n                    m_Parent.window.title = m_TitleContent.text;\n            }\n        }\n\n        public int depthBufferBits\n        {\n            get { return m_DepthBufferBits; }\n            set { m_DepthBufferBits = value; }\n        }\n\n        internal int antiAliasing\n        {\n            get { return m_AntiAliasing; }\n            set { m_AntiAliasing = value; }\n        }\n\n        internal bool resetPanelRenderingOnAssetChange\n        {\n            get => m_ResetPanelRenderingOnAssetChange;\n            set => m_ResetPanelRenderingOnAssetChange = value;\n        }\n\n        internal void SetParentGameViewDimensions(Rect rect, Rect clippedRect, Vector2 targetSize)\n        {\n            m_GameViewRect = rect;\n            m_GameViewClippedRect = clippedRect;\n            m_GameViewTargetSize = targetSize;\n            m_Parent.SetInternalGameViewDimensions(m_GameViewRect, m_GameViewClippedRect, m_GameViewTargetSize);\n        }\n\n        internal void SetPlayModeViewSize(Vector2 targetSize)\n        {\n            m_GameViewTargetSize = targetSize;\n            m_Parent.SetInternalGameViewDimensions(m_GameViewRect, m_GameViewClippedRect, m_GameViewTargetSize);\n        }\n\n        internal void SetMainPlayModeViewSize(Vector2 targetSize)\n        {\n            if (m_Parent != null)\n                m_Parent.SetMainPlayModeViewSize(targetSize);\n        }\n\n        internal void SetDisplayViewSize(int displayId, Vector2 targetSize)\n        {\n            if (m_Parent != null)\n                m_Parent.SetDisplayViewSize(displayId, targetSize);\n        }\n\n        internal Vector2 GetDisplayViewSize(int displayId)\n        {\n            if (m_Parent != null)\n               return m_Parent.GetDisplayViewSize(displayId);\n            return new Vector2(640, 480);\n        }\n\n        [Obsolete(\"AA is not supported on EditorWindows\", false)]\n        public int antiAlias\n        {\n            get { return 1; }\n            set {}\n        }\n\n        // The position of the window in screen space.\n        public Rect position\n        {\n            get\n            {\n                return m_Pos;\n            }\n            set\n            {\n                m_Pos = value;\n                // We're setting the position of this editorWindow.\n                // Only handle this is we have a parent. (unless we're just getting set up)\n                if (m_Parent)\n                {\n                    // Figure out if we're the only window here. If we are not, we need to undock us. If we are not, we should just\n                    // move the ContainerWindow that we're inside\n                    DockArea da = m_Parent as DockArea;\n                    if (!da)\n                    {\n                        if(m_Parent.window.showMode == ShowMode.Tooltip || m_Parent.window.showMode == ShowMode.PopupMenu)\n                            m_Parent.window.position = ContainerWindow.FitRectToScreen(value, value.center, true, m_Parent.window);\n                        else\n                            m_Parent.window.position = value;\n                        m_Parent.window.OnResize();\n                    }\n                    else if (da.parent && da.m_Panes.Count == 1 && !da.parent.parent)     // We should have a DockArea, then a splitView, then null\n                    {\n                        // This introduces a shift of Y coordinate by top value(20)\n                        var newPosition = da.borderSize.Add(value);\n                        // Adding the same top value\n                        newPosition.y += da.borderSize.top;\n                        da.window.position = newPosition;\n                    }\n                    else\n                    {\n                        // We're docked in a deeper hierarchy, so we need to undock us\n                        da.RemoveTab(this);\n                        // and then create a new window for us...\n                        CreateNewWindowForEditorWindow(this, true, true);\n                    }\n                }\n            }\n        }\n\n        // Sends an Event to a window.\n        public bool SendEvent(Event e)\n        {\n            return m_Parent.SendEvent(e);\n        }\n\n        public EditorWindow()\n        {\n            m_EnableViewDataPersistence = true;\n            m_RequestedViewDataSave = false;\n            titleContent.text = GetType().ToString();\n            saveChangesMessage = $\"{GetType()} has unsaved changes.\";\n\n            UpdateWindowMenuListing();\n        }\n\n        void __internalAwake()\n        {\n            hideFlags = HideFlags.DontSave; // Can't be HideAndDontSave, as that would make scriptable wizard GUI be disabled\n        }\n\n        [InitializeOnLoadMethod]\n        static void Initialize()\n        {\n            s_ShortcutContext = new OverlayShortcutContext();\n            EditorApplication.delayCall += () => ShortcutIntegration.instance.contextManager.RegisterToolContext(s_ShortcutContext);\n        }\n\n        void OnEnableINTERNAL()\n        {\n            activeEditorWindows.Add(this);\n        }\n\n        void OnDisableINTERNAL()\n        {\n            m_OverlayCanvas.OnContainerWindowDisabled();\n            SaveViewDataToDisk();\n            activeEditorWindows.Remove(this);\n        }\n\n        internal void ReleaseViewData()\n        {\n            SaveViewDataToDisk();\n            DestroyImmediate(m_ViewDataDictionary);\n            m_ViewDataDictionary = null;\n        }\n\n        // Internal stuff:\n        // Helper to show this EditorWindow\n        internal static void CreateNewWindowForEditorWindow(EditorWindow window, bool loadPosition, bool showImmediately, bool setFocus = true)\n        {\n            ContainerWindow cw = ScriptableObject.CreateInstance<ContainerWindow>();\n            SplitView sw = ScriptableObject.CreateInstance<SplitView>();\n            cw.rootView = sw;\n            DockArea da = ScriptableObject.CreateInstance<DockArea>();\n            da.AddTab(window, setFocus);\n            sw.AddChild(da);\n            Rect r = window.m_Parent.borderSize.Add(window.position);\n            cw.position = r;\n            sw.position = new Rect(0, 0, r.width, r.height);\n            window.MakeParentsSettingsMatchMe();\n            cw.Show(ShowMode.NormalWindow, loadPosition, showImmediately, setFocus: true);\n            //Need this, as show my change the size of the window, due to screen constraints\n            cw.OnResize();\n            cw.UnsavedStateChanged();\n        }\n\n        // This is such a hack, but will do for now\n        [ContextMenu(\"Add Scene\")]\n        internal void AddSceneTab() {}\n\n        [ContextMenu(\"Add Game\")]\n        internal void AddGameTab() {}\n\n        public virtual IEnumerable<Type> GetExtraPaneTypes()\n        {\n            return Enumerable.Empty<Type>();\n        }\n\n        internal static void UpdateWindowMenuListing()\n        {\n            s_UpdateWindowMenuListingOff?.Invoke();\n            s_UpdateWindowMenuListingOff = EditorApplication.CallDelayed(BuildWindowMenuListing);\n        }\n\n        internal static void BuildWindowMenuListing()\n        {\n            if (!ModeService.HasCapability(ModeCapability.LayoutWindowMenu, true))\n                return;\n\n            const string k_RootMenuItemName = \"Window/Panels\";\n\n            Menu.RemoveMenuItem(k_RootMenuItemName);\n            var editorWindows = Resources.FindObjectsOfTypeAll<EditorWindow>();\n            int menuIdx = -15;\n\n            Menu.AddMenuItem($\"{k_RootMenuItemName}/Close all floating panels...\", \"\", false, menuIdx++, () =>\n            {\n                var windows = Resources.FindObjectsOfTypeAll<ContainerWindow>();\n                foreach (var win in windows.Where(w => !!w && w.showMode != ShowMode.MainWindow))\n                    win.Close();\n            }, null);\n            Menu.AddSeparator($\"{k_RootMenuItemName}/\", menuIdx++);\n\n            int menuIndex = 1;\n            foreach (var win in editorWindows.Where(e => !!e).OrderBy(e => e.titleContent.text))\n            {\n                var title = win.titleContent.text;\n                title = title.Replace(\"/\", \"\\\\\");\n                Menu.AddMenuItem($\"{k_RootMenuItemName}/{menuIndex++} {title}\", \"\", false, menuIdx++, () => win.Focus(), null);\n            }\n        }\n\n        private VisualElement CreateRoot()\n        {\n            const string rootName = VisualElement.k_RootVisualContainerName;\n            var root = new VisualElement()\n            {\n                name = VisualElementUtils.GetUniqueName(rootName),\n                pickingMode = PickingMode.Ignore, // do not eat events so IMGUI gets them\n                viewDataKey = rootName,\n                renderHints = RenderHints.ClipWithScissors\n            };\n            root.pseudoStates |= PseudoStates.Root;\n            UIElementsEditorUtility.AddDefaultEditorStyleSheets(root);\n            root.style.overflow = Overflow.Hidden;\n            return root;\n        }\n\n        static OverlayShortcutContext s_ShortcutContext = new OverlayShortcutContext();\n\n        internal class OverlayShortcutContext : IShortcutContext\n        {\n            public EditorWindow editorWindow;\n            public bool active\n            {\n                get\n                {\n                    var focusedWindow = EditorWindow.focusedWindow;\n                    if (focusedWindow != null)\n                    {\n                        if (focusedWindow is ISupportsOverlays)\n                        {\n                            editorWindow = focusedWindow;\n                            return true;\n                        }\n                    }\n\n                    editorWindow = null;\n                    return false;\n                }\n            }\n        }\n\n        [Shortcut(\"Overlays/Toggle All Overlays\", typeof(OverlayShortcutContext), KeyCode.BackQuote, ShortcutModifiers.Shift)]\n        static void ToggleAllOverlays(ShortcutArguments args)\n        {\n            if (!(args.context is OverlayShortcutContext context))\n                return;\n            var canvas = context.editorWindow.overlayCanvas;\n            canvas.overlaysEnabled = !canvas.overlaysEnabled;\n        }\n\n        [Shortcut(\"Overlays/Hide Overlay\", typeof(OverlayShortcutContext))]\n        static void HideOverlay(ShortcutArguments args)\n        {\n            if(args.context is OverlayShortcutContext context)\n                context.editorWindow.overlayCanvas.HideHoveredOverlay();\n        }\n\n        public bool TryGetOverlay(string id, out Overlay match)\n        {\n            return m_OverlayCanvas.TryGetOverlay(id, out match);\n        }\n\n        internal void OnBackingScaleFactorChangedInternal()\n        {\n            if(overlayCanvas != null)\n                overlayCanvas.Rebuild();\n\n            OnBackingScaleFactorChanged();\n        }\n\n        protected virtual void OnBackingScaleFactorChanged() { }\n    }\n\n    [AttributeUsage(AttributeTargets.Class)]\n    public class EditorWindowTitleAttribute : System.Attribute\n    {\n        public string title { get; set; }\n        public string icon { get; set; }\n        public bool useTypeNameAsIconName { get; set; }\n    }\n\n    /// <summary>\n    /// This enumeration is used for creating instances of <see cref=\"UIFrameworkAttribute\"/>.\n    /// Values of this enumeration tell external tools which UI Framework is used on a given type of Editor UI\n    /// (that is, a specific type of EditorWindow, Editor or PropertyDrawer).\n    /// </summary>\n    internal enum UIFrameworkUsage\n    {\n        /// <summary>\n        /// By default, the usage of a UI Framework is auto-detected by reflection\n        /// </summary>\n        /// <remarks>\n        /// <para>In many cases, the UI Framework of an Editor UI type can be auto-detected.</para>\n        /// <para>If a custom EditorWindow only overrides <see cref=\"EditorWindow.CreateGUI\"/>, it will be classified as using\n        /// UI Toolkit. Similarly, if it only overrides <see cref=\"EditorWindow.OnGUI\"/>, it will be classified as using\n        /// IMGUI. Finally, if a custom EditorWindow overrides <see cref=\"EditorWindow.OnEnable\"/> but does not override\n        /// <see cref=\"EditorWindow.OnGUI\"/>, it is classified as using UI Toolkit (this was often the usage pattern until\n        /// the introduction of <see cref=\"EditorWindow.CreateGUI\"/>).\n        /// In any other case, the usage of the <see cref=\"UIFrameworkAttribute\"/> is required.</para>\n        /// <para>If a custom Editor only overrides <see cref=\"Editor.CreateInspectorGUI\"/>, it will be classified as using\n        /// UI Toolkit. Similarly, if it only overrides <see cref=\"EditorWindow.OnInspectorGUI\"/>, it will be classified as using\n        /// IMGUI. In any other case, the usage of the <see cref=\"UIFrameworkAttribute\"/> is required.</para>\n        /// </remarks>\n        AutoDetected,\n        /// <summary>\n        /// This type of Editor UI uses IMGUI\n        /// </summary>\n        IMGUI,\n        /// <summary>\n        /// This type of Editor UI uses UI Toolkit\n        /// </summary>\n        UITK,\n        /// <summary>\n        /// This type of Editor UI uses a mix of IMGUI and UI Toolkit.\n        /// </summary>\n        /// <remarks>\n        /// This value is appropriate when a type of Editor UI uses <see cref=\"IMGUIContainer\"/> because it is only\n        /// partially migrated to UI Toolkit, or because it supports immediate-mode callbacks for backwards\n        /// compatibility with existing public APIs.\n        /// </remarks>\n        Mixed,\n        /// <summary>\n        /// This type of Editor UI should not be accounted for by tooling.\n        /// </summary>\n        /// <remarks>\n        /// This value is appropriate when a type of Editor UI is not exposed to end-users.\n        /// </remarks>\n        Excluded\n    }\n\n    /// <summary>\n    /// <para>This attribute tells external tools which UI Framework is used on a given type of Editor UI\n    /// (that is, a specific type of EditorWindow, Editor or PropertyDrawer).</para>\n    ///\n    /// <para>To use this attribute, add to a custom EditorWindow or Editor class by giving it a value from the\n    /// <see cref=\"UIFrameworkUsage\"/> enumeration.</para>\n    ///\n    /// <para>In many cases, the UI Framework of an Editor UI type can be auto-detected without this attribute\n    /// (see <see cref=\"UIFrameworkUsage.AutoDetected\"/>).</para>\n    /// </summary>.\n    [AttributeUsage(AttributeTargets.Class)]\n    internal class UIFrameworkAttribute : Attribute\n    {\n        /// <summary>\n        /// UI framework used by the target type of the attribute\n        /// </summary>\n        public UIFrameworkUsage frameworkUsage { get; private set; }\n\n        /// <summary>\n        /// Constructs an instance of this class\n        /// </summary>\n        /// <param name=\"frameworkUsage\">UI framework used by the target type of the attribute</param>\n        public UIFrameworkAttribute(UIFrameworkUsage frameworkUsage)\n        {\n            this.frameworkUsage = frameworkUsage;\n        }\n    }\n\n    namespace UIElements\n    {\n        public static class UIElementsEntryPoint\n        {\n            public static void SetAntiAliasing(this EditorWindow window, int aa)\n            {\n                window.antiAliasing = aa;\n            }\n\n            public static int GetAntiAliasing(this EditorWindow window)\n            {\n                return window.antiAliasing;\n            }\n        }\n    }\n} //namespace\n"
  },
  {
    "path": "Editor/Mono/EnumDataUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing static UnityEngine.EnumDataUtility;\n\nnamespace UnityEditor\n{\n    internal static class EnumDataUtility\n    {\n        internal static EnumData GetCachedEnumData(Type enumType, bool excludeObsolete = true)\n        {\n            return UnityEngine.EnumDataUtility.GetCachedEnumData(enumType, excludeObsolete ? CachedType.ExcludeObsolete : CachedType.IncludeObsoleteExceptErrors, ObjectNames.NicifyVariableName);\n        }\n\n        internal static EnumData GetCachedEnumData(Type enumType, CachedType cachedType)\n        {\n            return UnityEngine.EnumDataUtility.GetCachedEnumData(enumType, cachedType, ObjectNames.NicifyVariableName);\n        }\n\n        internal static int EnumFlagsToInt(EnumData enumData, Enum enumValue)\n        {\n            return UnityEngine.EnumDataUtility.EnumFlagsToInt(enumData, enumValue);\n        }\n\n        internal static Enum IntToEnumFlags(Type enumType, int value)\n        {\n            return UnityEngine.EnumDataUtility.IntToEnumFlags(enumType, value);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/EventWithPerformanceTracker.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Threading;\nusing UnityEditor.Profiling;\n\nnamespace UnityEditor\n{\n    /// <summary>\n    /// Use this to enhance C# events with editor performance trackers. This can be used as a replacement of a C# event without changing\n    /// the public API. Using editor performance trackers means that the pop-up progress bar will provide more helpful information.\n    /// </summary>\n    /// <remarks>\n    /// Like C# events, adding and removing subscribers is thread-safe. Invoking the event however should only happen on the main thread\n    /// (because of the performance trackers).\n    ///\n    /// Using this type will give your performance trackers sensible names and cache them. Like regular C# events, adding and removing\n    /// subscribers may cause garbage allocations.\n    /// </remarks>\n    /// <example>\n    /// <code>\n    /// public static class Events {\n    ///     public static event SomeDelegate MyEvent;\n    ///\n    ///     private static void InvokeEvent() {\n    ///         MyEvent?.Invoke(1, 2, 3);\n    ///     }\n    /// }\n    /// </code>\n    /// can be rewritten to this:\n    /// <code>\n    /// public static class Events {\n    ///     public static event SomeDelegate MyEvent {\n    ///         add => m_MyEvent.Add(value);\n    ///         remove => m_MyEvent.Remove(value);\n    ///     }\n    ///     private static EventWithPerformanceTracker&lt;SomeDelegate&gt; m_MyEvent =\n    ///         new EventWithPerformanceTracker&lt;SomeDelegate&gt;($\"{nameof(Events)}.{nameof(MyEvent)}\");\n    ///\n    ///     private static void InvokeEvent() {\n    ///         foreach (var evt in m_Event) {\n    ///             // A performance tracker for this delegate is active here!\n    ///             evt.Invoke(1, 2, 3);\n    ///         }\n    ///     }\n    /// }\n    /// </code>\n    /// </example>\n    /// <typeparam name=\"T\">The delegate type for this event.</typeparam>\n    struct EventWithPerformanceTracker<T> where T : Delegate\n    {\n        private readonly string m_Scope;\n        // This is either a reference to a delegate or a reference to a list. This mirrors the implementation of\n        // multicast delegates in .NET. This needs to be a class to make thread-safe add/remove work.\n        private DelegateWithHandle m_Delegate;\n\n        public EventWithPerformanceTracker(string scope)\n        {\n            m_Scope = scope;\n            m_Delegate = null;\n        }\n\n        /// <summary>\n        /// Returns whether this event has any subscribers.\n        /// </summary>\n        public bool hasSubscribers => m_Delegate != null && m_Delegate.isNonEmpty;\n\n        /// <summary>\n        /// Add a subscriber to this event. This is equivalent to using += on a C# event.\n        /// </summary>\n        /// <param name=\"value\"></param>\n        public void Add(T value)\n        {\n            // Thread-safe method to subscribe to this event. The implementation closely mirrors the compiler-generated code for events.\n            // see https://sharplab.io/#v2:CYLg1APgAgTAjAWAFBQMwAJboMLoN7LpGYYCmAbqQHYAumcMAPAJa0B86AopbQLIDchYkKJpMAFnS8AFAEp8I9AF9kSoA===\n            var del = m_Delegate;\n            while (true)\n            {\n                var del2 = del;\n                var value2 = DelegateWithHandle.Add(del2, value);\n                del = Interlocked.CompareExchange(ref m_Delegate, value2, del2);\n                if (del == del2)\n                {\n                    break;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Remove a subscriber from this event. This is equivalent to using -= on a C# event.\n        /// </summary>\n        /// <param name=\"value\"></param>\n        public void Remove(T value)\n        {\n            var del = m_Delegate;\n            while (true)\n            {\n                var del2 = del;\n                var value2 = DelegateWithHandle.Remove(del2, value);\n                del = Interlocked.CompareExchange(ref m_Delegate, value2, del2);\n                if (del == del2)\n                {\n                    break;\n                }\n            }\n        }\n\n        public Enumerator GetEnumerator() => new Enumerator(this);\n\n        internal struct Enumerator : IEnumerator<T>\n        {\n            private readonly DelegateWithHandle m_Delegate;\n            private readonly string m_Scope;\n            private readonly int m_Length;\n            private int m_ActivePerformanceTracker;\n            private int m_CurrentIndex;\n\n            internal Enumerator(EventWithPerformanceTracker<T> evt)\n            {\n                m_Length = evt.m_Delegate?.length ?? 0;\n                m_Scope = evt.m_Scope;\n                m_ActivePerformanceTracker = -1;\n                m_CurrentIndex = -1;\n                m_Delegate = evt.m_Delegate;\n            }\n\n            public void Dispose()\n            {\n                if (m_ActivePerformanceTracker >= 0)\n                    EditorPerformanceTracker.StopTracker(m_ActivePerformanceTracker);\n            }\n\n            public bool MoveNext()\n            {\n                if (m_ActivePerformanceTracker >= 0)\n                    EditorPerformanceTracker.StopTracker(m_ActivePerformanceTracker);\n                m_CurrentIndex++;\n                m_ActivePerformanceTracker = m_CurrentIndex < m_Length ? m_Delegate.StartTrackerAt(m_CurrentIndex, m_Scope) : -1;\n                return m_CurrentIndex < m_Length;\n            }\n\n            public void Reset() => throw new NotImplementedException();\n\n            public T Current => m_Delegate.GetDelegateAt(m_CurrentIndex);\n\n            object IEnumerator.Current => (this as IEnumerator<T>).Current;\n        }\n\n        internal static EventWithPerformanceTracker.Entry BuildDelegate(string scope, T del)\n        {\n            if (del == null)\n            {\n                return default;\n            }\n\n            var ls = del.GetInvocationList();\n            switch (ls.Length)\n            {\n                case 0:\n                    return default;\n                case 1:\n                    return new EventWithPerformanceTracker.Entry(del, EventWithPerformanceTracker.GetPerformanceTrackerHandleForEvent(scope, del));\n                default:\n                {\n                    var entries = new EventWithPerformanceTracker.Entry[ls.Length];\n                    for (int i = 0; i < entries.Length; i++)\n                        entries[i] = new EventWithPerformanceTracker.Entry(ls[i] as T, EventWithPerformanceTracker.GetPerformanceTrackerHandleForEvent(scope, ls[i]));\n                    return new EventWithPerformanceTracker.Entry(entries);\n                }\n            }\n        }\n\n        private class DelegateWithHandle\n        {\n            private EventWithPerformanceTracker.Entry m_DelegateOrList;\n\n            private DelegateWithHandle() {}\n\n            private DelegateWithHandle(EventWithPerformanceTracker.Entry entry)\n            {\n                m_DelegateOrList = entry;\n            }\n\n            public bool isNonEmpty => m_DelegateOrList.Reference != null;\n\n            internal int length => m_DelegateOrList.length;\n\n            internal int StartTrackerAt(int idx, string scope)\n            {\n                // We have to lazily initialize the tracker because subscription might happen from any thread\n                // but we can only create editor performance trackers from the main thread.\n                ref var handle = ref m_DelegateOrList.Reference is EventWithPerformanceTracker.Entry[] list\n                    ? ref list[idx].EditorPerformanceTrackerHandle\n                    : ref m_DelegateOrList.EditorPerformanceTrackerHandle;\n\n                if (handle == EditorPerformanceTracker.InvalidTrackerHandle)\n                    handle = EventWithPerformanceTracker.GetPerformanceTrackerHandleForEvent(scope, GetDelegateAt(idx));\n                EditorPerformanceTracker.TryStartTrackerByHandle(handle, out var token);\n                return token;\n            }\n\n            internal T GetDelegateAt(int idx) => (m_DelegateOrList.Reference is EventWithPerformanceTracker.Entry[] list ? list[idx].Reference : m_DelegateOrList.Reference) as T;\n\n            internal static DelegateWithHandle Add(DelegateWithHandle dwh, T del)\n            {\n                if (dwh == null)\n                {\n                    return new DelegateWithHandle(new EventWithPerformanceTracker.Entry(del));\n                }\n                switch (dwh.m_DelegateOrList.Reference)\n                {\n                    case null:\n                        return new DelegateWithHandle(new EventWithPerformanceTracker.Entry(del));\n                    case EventWithPerformanceTracker.Entry[] list:\n                    {\n                        // This may seem wasteful, but mirrors the C# implementation of delegates. This is important\n                        // to make thread-safe events work without locking, and also to support re-entrant events.\n                        var newList = new EventWithPerformanceTracker.Entry[list.Length + 1];\n                        int n = list.Length;\n                        for (int i = 0; i < n; i++)\n                            newList[i] = list[i];\n                        newList[n] = new EventWithPerformanceTracker.Entry(del);\n                        return new DelegateWithHandle(new EventWithPerformanceTracker.Entry(newList));\n                    }\n                    default:\n                    {\n                        var newList = new EventWithPerformanceTracker.Entry[2];\n                        newList[0] = dwh.m_DelegateOrList;\n                        newList[1] = new EventWithPerformanceTracker.Entry(del);\n                        return new DelegateWithHandle(new EventWithPerformanceTracker.Entry(newList));\n                    }\n                }\n            }\n\n            private static DelegateWithHandle RemoveAt(EventWithPerformanceTracker.Entry[] array, int idx)\n            {\n                if (array.Length == 1)\n                    return null;\n                if (array.Length == 2)\n                {\n                    return new DelegateWithHandle(array[1 - idx]);\n                }\n\n                int n = array.Length;\n                var newArray = new EventWithPerformanceTracker.Entry[n - 1];\n                for (int k = 0; k < idx; k++)\n                {\n                    newArray[k] = array[k];\n                }\n\n                for (int k = idx + 1; k < n; k++)\n                {\n                    newArray[k - 1] = array[k];\n                }\n\n                return new DelegateWithHandle(new EventWithPerformanceTracker.Entry(newArray));\n            }\n\n            internal static DelegateWithHandle Remove(DelegateWithHandle dwh, T del)\n            {\n                if (dwh == null)\n                    return null;\n                switch (dwh.m_DelegateOrList.Reference)\n                {\n                    case null:\n                        return dwh;\n                    case EventWithPerformanceTracker.Entry[] list:\n                    {\n                        for (int i = list.Length - 1; i >= 0; i--)\n                        {\n                            if ((list[i].Reference as T) == del)\n                            {\n                                return RemoveAt(list, i);\n                            }\n                        }\n                        return dwh;\n                    }\n                    default:\n                    {\n                        if ((dwh.m_DelegateOrList.Reference as T) == del)\n                            return null;\n                        return dwh;\n                    }\n                }\n            }\n        }\n    }\n\n    static class EventWithPerformanceTracker\n    {\n        internal struct Entry\n        {\n            internal ulong EditorPerformanceTrackerHandle;\n            internal readonly object Reference;\n\n            public Entry(Delegate del, ulong trackerHandle = EditorPerformanceTracker.InvalidTrackerHandle)\n            {\n                Reference = del;\n                EditorPerformanceTrackerHandle = trackerHandle;\n            }\n\n            public Entry(Entry[] entries)\n            {\n                Reference = entries;\n                EditorPerformanceTrackerHandle = EditorPerformanceTracker.InvalidTrackerHandle;\n            }\n\n            internal int length\n            {\n                get\n                {\n                    if (Reference == null)\n                        return 0;\n                    if (Reference is Entry[] list)\n                        return list.Length;\n                    return 1;\n                }\n            }\n        }\n\n        internal static string GetPerformanceTrackerName(string scope, Delegate d)\n        {\n            if (d.Method.DeclaringType != null)\n            {\n                if (Attribute.IsDefined(d.Method.DeclaringType, typeof(CompilerGeneratedAttribute)))\n                {\n                    // find the outermost type\n                    var type = d.Method.DeclaringType;\n                    while (type.DeclaringType != null)\n                    {\n                        type = type.DeclaringType;\n                    }\n\n                    return $\"{scope}: callback in {type.FullName}\";\n                }\n\n                return $\"{scope}: {d.Method.DeclaringType.FullName}.{d.Method.Name}\";\n            }\n            return scope;\n        }\n\n        internal static ulong GetPerformanceTrackerHandleForEvent(string scope, Delegate d)\n        {\n            var declaringType = d.Method.DeclaringType;\n            if (declaringType != null)\n            {\n                return EditorPerformanceTracker.GetOrCreateTrackerHandle(GetPerformanceTrackerName(scope, d), declaringType);\n            }\n            return EditorPerformanceTracker.GetOrCreateTrackerHandle(GetPerformanceTrackerName(scope, d));\n        }\n    }\n\n    /// <summary>\n    /// Use this to add editor performance trackers to events that are implemented via raw delegates instead of proper\n    /// C# events. Using editor performance trackers means that the pop-up progress bar will provide more helpful information.\n    /// </summary>\n    /// <remarks>\n    /// This delegate should only be invoked on the main thread (because of the performance trackers).\n    ///\n    /// The implementation of this type assumes that the delegate it is wrapping changes infrequently compared to how often\n    /// it is invoked. Invoking the delegate is cheap, but (as with C# delegates) changing the delegate can cause additional\n    /// work as we need to recompute the performance markers.\n    /// </remarks>\n    /// <example>\n    /// <code>\n    /// public static class Events {\n    ///     public static SomeDelegate MyPoorlyImplementedEvent;\n    ///\n    ///     private static void InvokeEvent() {\n    ///         MyPoorlyImplementedEvent?.Invoke(1, 2, 3);\n    ///     }\n    /// }\n    /// </code>\n    /// can be rewritten to this:\n    /// <code>\n    /// public static class Events {\n    ///     public static SomeDelegate MyPoorlyImplementedEvent;\n    ///     private static DelegateWithPerformanceTracker&lt;SomeDelegate&gt; m_MyPoorlyImplementedEvent =\n    ///         new DelegateWithPerformanceTracker&lt;SomeDelegate&gt;($\"{nameof(Events)}.{nameof(MyPoorlyImplementedEvent)}\");\n    ///\n    ///     private static void InvokeEvent() {\n    ///         foreach (var evt in m_MyPoorlyImplementedEvent.UpdateAndInvoke(MyPoorlyImplementedEvent)) {\n    ///             evt.Invoke(1, 2, 3);\n    ///         }\n    ///     }\n    /// }\n    /// </code>\n    /// </example>\n    /// <typeparam name=\"T\">The delegate type.</typeparam>\n    struct DelegateWithPerformanceTracker<T> where T : Delegate\n    {\n        private readonly string m_Scope;\n        // We follow the same pattern as in EventWithPerformanceTracker to allow for re-entrant events.\n        private EventWithPerformanceTracker.Entry m_Delegates;\n        private T m_CachedDelegate;\n\n        public DelegateWithPerformanceTracker(string scope)\n        {\n            m_Scope = scope;\n            m_Delegates = default;\n            m_CachedDelegate = null;\n        }\n\n        /// <summary>\n        /// Update the delegate wrapped by this tracker and acquire an enumerator for invoking it via iteration.\n        /// </summary>\n        /// <param name=\"value\"></param>\n        /// <returns></returns>\n        public Invoker UpdateAndInvoke(T value)\n        {\n            if (!ReferenceEquals(m_CachedDelegate, value))\n            {\n                m_CachedDelegate = value;\n                m_Delegates = EventWithPerformanceTracker<T>.BuildDelegate(m_Scope, value);\n            }\n\n            return new Invoker(ref m_Delegates);\n        }\n\n        internal readonly struct Invoker\n        {\n            private readonly EventWithPerformanceTracker.Entry m_Delegates;\n            public Enumerator GetEnumerator() => new Enumerator(in this);\n\n            public Invoker(ref EventWithPerformanceTracker.Entry dlg)\n            {\n                m_Delegates = dlg;\n            }\n\n            internal struct Enumerator : IEnumerator<T>\n            {\n                private readonly EventWithPerformanceTracker.Entry m_Delegates;\n                private readonly int m_Length;\n                private int m_ActivePerformanceTracker;\n                private int m_CurrentIndex;\n\n                internal Enumerator(in Invoker evt)\n                {\n                    m_Delegates = evt.m_Delegates;\n                    m_Length = evt.m_Delegates.length;\n                    m_ActivePerformanceTracker = -1;\n                    m_CurrentIndex = -1;\n                }\n\n                public void Dispose()\n                {\n                    if (m_ActivePerformanceTracker >= 0)\n                        EditorPerformanceTracker.StopTracker(m_ActivePerformanceTracker);\n                }\n\n                public bool MoveNext()\n                {\n                    if (m_ActivePerformanceTracker >= 0)\n                        EditorPerformanceTracker.StopTracker(m_ActivePerformanceTracker);\n                    m_CurrentIndex++;\n                    if (m_CurrentIndex < m_Length)\n                    {\n                        ulong handle;\n                        if (m_Length == 1)\n                            handle = m_Delegates.EditorPerformanceTrackerHandle;\n                        else\n                            handle = (m_Delegates.Reference as EventWithPerformanceTracker.Entry[])[m_CurrentIndex].EditorPerformanceTrackerHandle;\n                        EditorPerformanceTracker.TryStartTrackerByHandle(handle, out m_ActivePerformanceTracker);\n                    }\n                    else\n                        m_ActivePerformanceTracker = -1;\n                    return m_CurrentIndex < m_Length;\n                }\n\n                public void Reset() => throw new NotImplementedException();\n\n                public T Current\n                {\n                    get\n                    {\n                        if (m_Length == 1)\n                            return m_Delegates.Reference as T;\n                        return (m_Delegates.Reference as EventWithPerformanceTracker.Entry[])[m_CurrentIndex].Reference as T;\n                    }\n                }\n\n                object IEnumerator.Current => (this as IEnumerator<T>).Current;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ExportPackageOptions.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nnamespace UnityEditor\n{\n    // Export package option. Multiple options can be combined together using the | operator.\n    [Flags]\n    public enum ExportPackageOptions\n    {\n        // Default mode. Will not include dependencies or subdirectories nor include Library assets unless specifically included in the asset list.\n        Default = 0,\n\n        // The export operation will be run asynchronously and reveal the exported package file in a file browser window after the export is finished.\n        Interactive = 1,\n\n        // Will recurse through any subdirectories listed and include all assets inside them.\n        Recurse = 2,\n\n        // In addition to the assets paths listed, all dependent assets will be included as well.\n        IncludeDependencies = 4,\n\n        // The exported package will include all library assets, ie. the project settings located in the Library folder of the project.\n        IncludeLibraryAssets = 8\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ExternalPlayModeView/ExternalPlayModeView.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/ExternalPlayModeView.bindings.h\"),\n     StaticAccessor(\"ExternalPlayModeViewBindings\", StaticAccessorType.DoubleColon)]\n    internal partial class ExternalPlayModeView\n    {\n        private static extern IntPtr Internal_InitWindow();\n\n        private static extern void Internal_SetPlayerLaunchPath(IntPtr nativeContextPtr, string pathToExe);\n\n        private static extern void AttachWindow_Native(IntPtr nativeContextPtr, IntPtr hostWindowHandle, Rect position);\n\n        private static extern void ResizeWindow_Native(IntPtr nativeContextPtr, System.IntPtr hostWindowHandle, Rect newPosition);\n\n        private static extern void BeforeRemoveTab_Native(IntPtr nativeContextPtr, System.IntPtr hostWindowHandle);\n\n        private static extern void AddedAsTab_Native(IntPtr nativeContextPtr, System.IntPtr hostWindowHandle, Rect position);\n\n        private static extern void OnBecameVisible_Native(IntPtr nativeContextPtr, System.IntPtr hostWindowHandle, Rect position);\n\n        private static extern void OnBecameInvisible_Native(IntPtr nativeContextPtr, System.IntPtr hostWindowHandle);\n\n        private static extern void DestroyWindow_Native(IntPtr nativeContextPtr, System.IntPtr hostWindowHandle);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ExternalPlayModeView/ExternalPlayModeView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Internal;\n\nnamespace UnityEditor\n{\n    internal partial class ExternalPlayModeView : EditorWindow, IGameViewSizeMenuUser\n    {\n        MonoReloadableIntPtr m_NativeContextPtr;\n\n        public string playerLaunchPath\n        {\n            get { return m_PlayerLaunchPath; }\n            set\n            {\n                m_PlayerLaunchPath = value;\n                Internal_SetPlayerLaunchPath(m_NativeContextPtr.m_IntPtr, m_PlayerLaunchPath);\n            }\n        }\n\n        string m_PlayerLaunchPath;\n\n        static GameViewSizeGroupType currentSizeGroupType => GameViewSizes.instance.currentGroupType;\n\n        private ExternalPlayModeView() {}\n\n        public static ExternalPlayModeView CreateExternalPlayModeView()\n        {\n            ExternalPlayModeView win = EditorWindow.CreateWindow<ExternalPlayModeView>();\n            win.m_NativeContextPtr.m_IntPtr = Internal_InitWindow();\n            return win;\n        }\n\n        public void AttachProcess()\n        {\n            AttachWindow_Native(m_NativeContextPtr.m_IntPtr, m_Parent.nativeHandle, GetTabRect());\n        }\n\n        public void KillProcess()\n        {\n            DestroyWindow_Native(m_NativeContextPtr.m_IntPtr, m_Parent.nativeHandle);\n        }\n\n        /*\n         * Returns the Rect that the external process should render itself in. Must be inside the external playmode view window\n         * and below any controls on the window.\n         */\n        private Rect GetTabRect()\n        {\n            Rect hostWindowScreenPosition = m_Parent.window.position;\n            Rect inTabPosition = m_Parent.windowPosition;\n            Rect usePosition = new Rect(hostWindowScreenPosition);\n\n            usePosition.x += inTabPosition.x;\n            usePosition.y += inTabPosition.y;\n            usePosition.width = inTabPosition.width;\n            usePosition.height = inTabPosition.height;\n\n            float yAdjust = EditorGUI.kTabButtonHeight + EditorGUI.kWindowToolbarHeight + EditorGUI.kSpacing;\n            float borderSize = EditorGUI.kSpacing;\n            usePosition.y += yAdjust;\n            usePosition.height -= (yAdjust + borderSize);\n            usePosition.x += borderSize;\n            usePosition.width -= borderSize * 2;\n\n            if (m_Parent.window.IsMainWindow())\n            {\n                // Need to move farther down when docked with the main editor window. Why?\n                float adjust = EditorGUI.kTabButtonHeight + EditorGUI.kSpacing;\n                usePosition.y += adjust;\n                usePosition.height -= adjust * 2;\n            }\n\n            return usePosition;\n        }\n\n        private void DoToolbarGUI()\n        {\n            GUILayout.BeginHorizontal(EditorStyles.toolbar);\n            {\n                GUILayout.Label(m_PlayerLaunchPath);\n                EditorGUILayout.GameViewSizePopup(currentSizeGroupType, 0, this, EditorStyles.toolbarPopup, GUILayout.Width(160f));\n            }\n            GUILayout.EndHorizontal();\n        }\n\n        private void OnGUI()\n        {\n            DoToolbarGUI();\n        }\n\n        internal override void OnResized()\n        {\n            if (m_Parent.window == null)\n                return;\n\n            ResizeWindow_Native(m_NativeContextPtr.m_IntPtr, m_Parent.nativeHandle, GetTabRect());\n        }\n\n        private void OnDestroy()\n        {\n            DestroyWindow_Native(m_NativeContextPtr.m_IntPtr, m_Parent.nativeHandle);\n        }\n\n        private void OnBecameInvisible()\n        {\n            if (m_Parent.window == null)\n                return;\n            OnBecameInvisible_Native(m_NativeContextPtr.m_IntPtr, m_Parent.nativeHandle);\n        }\n\n        private void OnBecameVisible()\n        {\n            if (m_Parent.window == null)\n                return;\n            OnBecameVisible_Native(m_NativeContextPtr.m_IntPtr, m_Parent.nativeHandle, GetTabRect());\n        }\n\n        private void OnTabNewWindow()\n        {\n            if (m_Parent.window == null)\n                return;\n            AddedAsTab_Native(m_NativeContextPtr.m_IntPtr, m_Parent.nativeHandle, GetTabRect());\n        }\n\n        private void OnAddedAsTab()\n        {\n            if (m_Parent.window == null)\n                return;\n            AddedAsTab_Native(m_NativeContextPtr.m_IntPtr, m_Parent.nativeHandle, GetTabRect());\n        }\n\n        private void OnBeforeRemovedAsTab()\n        {\n            if (m_Parent.window == null)\n                return;\n            BeforeRemoveTab_Native(m_NativeContextPtr.m_IntPtr, m_Parent.nativeHandle);\n        }\n\n        [ExcludeFromDocs]\n        public void SizeSelectionCallback(int indexClicked, object objectSelected)\n        {\n            //TODO handle selection of aspect ratio.\n            // We need to pass a message to our hosted process and tell it to change to a compatible resolution based on our selection.\n        }\n\n        [ExcludeFromDocs]\n        public bool lowResolutionForAspectRatios\n        {\n            get { return true; }\n            set {}\n        }\n\n        [ExcludeFromDocs]\n        public bool forceLowResolutionAspectRatios\n        {\n            get { return false; }\n        }\n\n        [ExcludeFromDocs]\n        public bool vSyncEnabled\n        {\n            get { return false; }\n            set {}\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/FileUtil.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing System.IO;\n\n\nnamespace UnityEditor\n{\n    // Lets you do ''move'', ''copy'', ''delete'' operations over files or directories\n    [NativeHeader(\"Runtime/Utilities/FileUtilities.h\")]\n    [NativeHeader(\"Runtime/Utilities/File.h\")]\n    [NativeHeader(\"Editor/Platform/Interface/EditorUtility.h\")]\n    public partial class FileUtil\n    {\n        // Deletes a file or a directory given a path.\n        public static bool DeleteFileOrDirectory(string path)\n        {\n            if (path is null) throw new ArgumentNullException(\"path\");\n            if (path == string.Empty) throw new ArgumentException(\"path\", \"The path cannot be empty.\");\n\n            return DeleteFileOrDirectoryInternal(path);\n        }\n\n        [FreeFunction(\"DeleteFileOrDirectory\")]\n        private static extern bool DeleteFileOrDirectoryInternal(string path);\n\n        [FreeFunction(\"IsPathCreated\")]\n        private static extern bool PathExists(string path);\n\n        // Copies a file or directory.\n        public static void CopyFileOrDirectory(string source, string dest)\n        {\n            CheckForValidSourceAndDestinationArgumentsAndRaiseAnExceptionWhenNullOrEmpty(source, dest);\n\n            if (PathExists(dest))\n            {\n                throw new System.IO.IOException(string.Format(\n                    \"Failed to Copy File / Directory from '{0}' to '{1}': destination path already exists.\", source, dest));\n            }\n\n            if (!CopyFileOrDirectoryInternal(source, dest))\n            {\n                throw new System.IO.IOException(string.Format(\n                    \"Failed to Copy File / Directory from '{0}' to '{1}'.\", source, dest));\n            }\n        }\n\n        [FreeFunction(\"CopyFileOrDirectory\")]\n        private static extern bool CopyFileOrDirectoryInternal(string source, string dest);\n\n        // Copies the file or directory following symbolic links.\n        public static void CopyFileOrDirectoryFollowSymlinks(string source, string dest)\n        {\n            CheckForValidSourceAndDestinationArgumentsAndRaiseAnExceptionWhenNullOrEmpty(source, dest);\n\n            if (PathExists(dest))\n            {\n                throw new System.IO.IOException(string.Format(\n                    \"Failed to Copy File / Directory from '{0}' to '{1}': destination path already exists.\", source, dest));\n            }\n\n            if (!CopyFileOrDirectoryFollowSymlinksInternal(source, dest))\n            {\n                throw new System.IO.IOException(string.Format(\n                    \"Failed to Copy File / Directory from '{0}' to '{1}'.\", source, dest));\n            }\n        }\n\n        [FreeFunction(\"CopyFileOrDirectoryFollowSymlinks\")]\n        private static extern bool CopyFileOrDirectoryFollowSymlinksInternal(string source, string dest);\n\n        // Moves a file or a directory from a given path to another path.\n        public static void MoveFileOrDirectory(string source, string dest)\n        {\n            CheckForValidSourceAndDestinationArgumentsAndRaiseAnExceptionWhenNullOrEmpty(source, dest);\n\n            if (PathExists(dest))\n            {\n                throw new System.IO.IOException(string.Format(\n                    \"Failed to Copy File / Directory from '{0}' to '{1}': destination path already exists.\", source, dest));\n            }\n\n            if (!MoveFileOrDirectoryInternal(source, dest))\n            {\n                throw new System.IO.IOException(string.Format(\n                    \"Failed to Move File / Directory from '{0}' to '{1}'.\", source, dest));\n            }\n        }\n\n        [FreeFunction(\"MoveFileOrDirectory\")]\n        private static extern bool MoveFileOrDirectoryInternal(string source, string dest);\n\n        private static void CheckForValidSourceAndDestinationArgumentsAndRaiseAnExceptionWhenNullOrEmpty(string source, string dest)\n        {\n            if (source == null) throw new ArgumentNullException(\"source\");\n            if (dest == null) throw new ArgumentNullException(\"dest\");\n\n            if (source == string.Empty) throw new ArgumentException(\"source\", \"The source path cannot be empty.\");\n            if (dest == string.Empty) throw new ArgumentException(\"dest\", \"The destination path cannot be empty.\");\n        }\n\n        // Returns a unique path in the Temp folder within your current project.\n        [FreeFunction]\n        public static extern string GetUniqueTempPathInProject();\n\n        [FreeFunction(\"GetActualPathSlow\")]\n        internal static extern string GetActualPathName(string path);\n\n        //*undocumented*\n        [FreeFunction]\n        public static extern string GetProjectRelativePath(string path);\n\n        [FreeFunction(Name = \"GetLastPathNameComponentManaged\")]\n        internal static extern string GetLastPathNameComponent(string path);\n\n        [FreeFunction(Name = \"DeleteLastPathNameComponentManaged\")]\n        internal static extern string DeleteLastPathNameComponent(string path);\n\n        [FreeFunction(\"GetPathNameExtensionManaged\")]\n        internal static extern string GetPathExtension(string path);\n\n        [FreeFunction(\"DeletePathNameExtensionManaged\")]\n        internal static extern string GetPathWithoutExtension(string path);\n\n        [FreeFunction]\n        internal static extern string ResolveSymlinks(string path);\n\n        [FreeFunction]\n        internal static extern bool IsSymlink(string path);\n\n        [FreeFunction]\n        public static extern string GetLogicalPath(string path);\n\n        [FreeFunction(IsThreadSafe = true)]\n        public static extern string GetPhysicalPath(string path);\n\n        // Replaces a file.\n        public static void ReplaceFile(string src, string dst)\n        {\n            if (File.Exists(dst))\n                FileUtil.DeleteFileOrDirectory(dst);\n\n            FileUtil.CopyFileOrDirectory(src, dst);\n        }\n\n        // Replaces a directory.\n        public static void ReplaceDirectory(string src, string dst)\n        {\n            if (Directory.Exists(dst))\n            {\n                bool succesfullyDeletedDirectory = FileUtil.DeleteFileOrDirectory(dst);\n                if (succesfullyDeletedDirectory == false)\n                    throw new System.IO.IOException(string.Format(\n                        \"Failed to delete directory '{0}'.\", dst));\n            }\n            FileUtil.CopyFileOrDirectory(src, dst);\n        }\n\n        // transform path to absolute, resolving mount points\n        [FreeFunction(\"PathToAbsolutePathFromScript\")]\n        extern internal static string PathToAbsolutePath(string path);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/FileUtil.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Text.RegularExpressions;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    public partial class FileUtil\n    {\n        internal static void ReplaceText(string path, params string[] input)\n        {\n            path = NiceWinPath(path);\n            string[] data = File.ReadAllLines(path);\n\n            for (int i = 0; i < input.Length; i += 2)\n            {\n                for (int q = 0; q < data.Length; ++q)\n                {\n                    data[q] = data[q].Replace(input[i], input[i + 1]);\n                }\n            }\n\n            File.WriteAllLines(path, data);\n        }\n\n        internal static bool ReplaceTextRegex(string path, params string[] input)\n        {\n            bool res = false;\n            path = NiceWinPath(path);\n            string[] data = File.ReadAllLines(path);\n\n            for (int i = 0; i < input.Length; i += 2)\n            {\n                for (int q = 0; q < data.Length; ++q)\n                {\n                    string s = data[q];\n                    data[q] = Regex.Replace(s, input[i], input[i + 1]);\n\n                    if (s != (string)data[q])\n                        res = true;\n                }\n            }\n\n            File.WriteAllLines(path, data);\n            return res;\n        }\n\n        internal static bool AppendTextAfter(string path, string find, string append)\n        {\n            bool res = false;\n            path = NiceWinPath(path);\n            var data = new List<string>(File.ReadAllLines(path));\n\n            for (int q = 0; q < data.Count; ++q)\n            {\n                if (data[q].Contains(find))\n                {\n                    data.Insert(q + 1, append);\n                    res = true;\n                    break;\n                }\n            }\n\n            File.WriteAllLines(path, data.ToArray());\n            return res;\n        }\n\n        internal static void CopyDirectoryRecursive(string source, string target)\n        {\n            CopyDirectoryRecursive(source, target, overwrite: false, ignoreMeta: false);\n        }\n\n        internal static void CopyDirectoryRecursive(string source, string target, bool overwrite)\n        {\n            CopyDirectoryRecursive(source, target, overwrite, ignoreMeta: false);\n        }\n\n        internal static void CopyDirectory(string source, string target, bool overwrite)\n        {\n            CopyDirectoryFiltered(source, target, overwrite, f => true, false);\n        }\n\n        internal static void CopyDirectoryRecursive(string source, string target, bool overwrite, bool ignoreMeta)\n        {\n            CopyDirectoryRecursiveFiltered(source, target, overwrite, ignoreMeta ? @\"\\.meta$\" : null);\n        }\n\n        internal static void CopyDirectoryRecursiveForPostprocess(string source, string target, bool overwrite)\n        {\n            CopyDirectoryRecursiveFiltered(source, target, overwrite, @\".*/\\.+|\\.meta$\");\n        }\n\n        internal static void CopyDirectoryRecursiveFiltered(string source, string target, bool overwrite, string regExExcludeFilter)\n        {\n            CopyDirectoryFiltered(source, target, overwrite, regExExcludeFilter, true);\n        }\n\n        internal static void CopyDirectoryFiltered(string source, string target, bool overwrite, string regExExcludeFilter, bool recursive)\n        {\n            Regex exclude = null;\n            try\n            {\n                if (regExExcludeFilter != null)\n                    exclude = new Regex(regExExcludeFilter);\n            }\n            catch (ArgumentException)\n            {\n                Debug.Log(\"CopyDirectoryRecursive: Pattern '\" + regExExcludeFilter + \"' is not a correct Regular Expression. Not excluding any files.\");\n                return;\n            }\n\n            Func<string, bool> includeCallback = file => (exclude == null || !exclude.IsMatch(file));\n\n            CopyDirectoryFiltered(source, target, overwrite, includeCallback, recursive);\n        }\n\n        internal static void CopyDirectoryFiltered(string source, string target, bool overwrite, Func<string, bool> includeCallback, bool recursive)\n        {\n            // Check if the target directory exists, but dont create it yet until we know there are files to copy.\n            bool createDirectory = !Directory.Exists(target);\n\n            // Copy each file into the new directory.\n            foreach (string fi in Directory.GetFiles(source))\n            {\n                if (!includeCallback(fi))\n                    continue;\n\n                if (createDirectory)\n                {\n                    Directory.CreateDirectory(target);\n                    overwrite = false; // no reason to perform this on subdirs\n                    createDirectory = false;\n                }\n\n                string fname = Path.GetFileName(fi);\n                string targetfname = Path.Combine(target, fname);\n\n                UnityFileCopy(fi, targetfname, overwrite);\n            }\n\n            if (!recursive)\n                return;\n\n            // Copy each subdirectory recursively.\n            foreach (string di in Directory.GetDirectories(source))\n            {\n                if (!includeCallback(di))\n                    continue;\n\n                string fname = Path.GetFileName(di);\n\n                CopyDirectoryFiltered(Path.Combine(source, fname), Path.Combine(target, fname), overwrite, includeCallback, recursive);\n            }\n        }\n\n        internal static void UnityDirectoryDelete(string path)\n        {\n            UnityDirectoryDelete(path, false);\n        }\n\n        internal static void UnityDirectoryDelete(string path, bool recursive)\n        {\n            Directory.Delete(NiceWinPath(path), recursive);\n        }\n\n        // set the System.IO.FileAttributes.Normal recursively on all files in target_dir\n        internal static void UnityDirectoryRemoveReadonlyAttribute(string target_dir)\n        {\n            string[] files = Directory.GetFiles(target_dir);\n            string[] dirs = Directory.GetDirectories(target_dir);\n\n            foreach (string file in files)\n            {\n                File.SetAttributes(file, System.IO.FileAttributes.Normal);\n            }\n\n            foreach (string dir in dirs)\n            {\n                UnityDirectoryRemoveReadonlyAttribute(dir);\n            }\n        }\n\n        internal static void MoveFileIfExists(string src, string dst)\n        {\n            if (File.Exists(src))\n            {\n                DeleteFileOrDirectory(dst);\n                MoveFileOrDirectory(src, dst);\n                File.SetLastWriteTime(dst, DateTime.Now);\n            }\n        }\n\n        internal static void CopyFileIfExists(string src, string dst, bool overwrite)\n        {\n            if (File.Exists(src))\n            {\n                UnityFileCopy(src, dst, overwrite);\n            }\n        }\n\n        internal static void UnityFileCopy(string from, string to, bool overwrite)\n        {\n            File.Copy(NiceWinPath(from), NiceWinPath(to), overwrite);\n        }\n\n\n        internal static bool ReadFileContentBinary(string assetPath, out byte[] fileContent, out string errorMessage)\n        {\n            fileContent = null;\n            errorMessage = null;\n            string absolutePath = FileUtil.PathToAbsolutePath(assetPath);\n            try\n            {\n                fileContent = File.ReadAllBytes(absolutePath);\n            }\n            catch (Exception e)\n            {\n                fileContent = null;\n                errorMessage = e.Message;\n            }\n\n            return fileContent != null;\n        }\n\n        internal static string NiceWinPath(string unityPath)\n        {\n            // IO functions do not like mixing of \\ and / slashes, esp. for windows network paths (\\\\path)\n            return Application.platform == RuntimePlatform.WindowsEditor ? unityPath.Replace(\"/\", @\"\\\") : unityPath;\n        }\n\n        internal static string UnityGetFileNameWithoutExtension(string path)\n        {\n            // this is because on Windows \\\\ means network path, in unity all \\ are converted to /\n            // network paths become // and Path class functions think it's the same as /\n            return Path.GetFileNameWithoutExtension(path.Replace(\"//\", @\"\\\\\")).Replace(@\"\\\\\", \"//\");\n        }\n\n        internal static string UnityGetFileName(string path)\n        {\n            // this is because on Windows \\\\ means network path, in unity all \\ are converted to /\n            // network paths become // and Path class functions think it's the same as /\n            return Path.GetFileName(path.Replace(\"//\", @\"\\\\\")).Replace(@\"\\\\\", \"//\");\n        }\n\n        internal static string UnityGetDirectoryName(string path)\n        {\n            // this is because on Windows \\\\ means network path, in unity all \\ are converted to /\n            // network paths become // and Path class functions think it's the same as /\n            return Path.GetDirectoryName(path.Replace(\"//\", @\"\\\\\")).Replace(@\"\\\\\", \"//\");\n        }\n\n        internal static void UnityFileCopy(string from, string to)\n        {\n            UnityFileCopy(from, to, false);\n        }\n\n        internal static void CreateOrCleanDirectory(string dir)\n        {\n            if (Directory.Exists(dir))\n                Directory.Delete(dir, true);\n            Directory.CreateDirectory(dir);\n        }\n\n        internal static string RemovePathPrefix(string fullPath, string prefix)\n        {\n            var partsOfFull = fullPath.Split(Path.DirectorySeparatorChar);\n            var partsOfPrefix = prefix.Split(Path.DirectorySeparatorChar);\n            int index = 0;\n\n            if (partsOfFull[0] == string.Empty)\n                index = 1;\n\n            while (index < partsOfFull.Length\n                   && index < partsOfPrefix.Length\n                   && partsOfFull[index] == partsOfPrefix[index])\n                ++index;\n\n            if (index == partsOfFull.Length)\n                return \"\";\n\n            return string.Join(Path.DirectorySeparatorChar.ToString(),\n                partsOfFull, index, partsOfFull.Length - index);\n        }\n\n        internal static string CombinePaths(params string[] paths)\n        {\n            if (null == paths)\n                return string.Empty;\n            return string.Join(Path.DirectorySeparatorChar.ToString(), paths);\n        }\n\n        internal static List<string> GetAllFilesRecursive(string path)\n        {\n            List<string> files = new List<string>();\n            WalkFilesystemRecursively(path,\n                (p) => { files.Add(p); },\n                (p) => { return true; });\n            return files;\n        }\n\n        internal static void WalkFilesystemRecursively(string path,\n            Action<string> fileCallback,\n            Func<string, bool> directoryCallback)\n        {\n            foreach (string file in Directory.GetFiles(path))\n                fileCallback(file);\n            foreach (string subdir in Directory.GetDirectories(path))\n            {\n                if (directoryCallback(subdir))\n                    WalkFilesystemRecursively(subdir, fileCallback, directoryCallback);\n            }\n        }\n\n        internal static long GetDirectorySize(string path)\n        {\n            var files = Directory.GetFiles(path, \"*.*\", SearchOption.AllDirectories);\n            long filesSize = 0;\n            foreach (var file in files)\n            {\n                var info = new FileInfo(file);\n                filesSize += info.Length;\n            }\n            return filesSize;\n        }\n\n        internal static bool IsReadOnly(UnityEngine.Object asset)\n        {\n            if (!AssetDatabase.IsOpenForEdit(asset, StatusQueryOptions.UseCachedIfPossible))\n            {\n                return false;\n            }\n\n            string assetPath = AssetDatabase.GetAssetPath(asset);\n            if (!string.IsNullOrEmpty(assetPath))\n            {\n                return (File.GetAttributes(assetPath) & FileAttributes.ReadOnly) != 0;\n            }\n            return false;\n        }\n\n        internal static bool HasReadOnly(IEnumerable<UnityEngine.Object> assets)\n        {\n            foreach (UnityEngine.Object asset in assets)\n                if (IsReadOnly(asset))\n                    return true;\n            return false;\n        }\n\n        [RequiredByNativeCode]\n        internal static bool MakeWritable(string path)\n        {\n            string absolutePath = FileUtil.PathToAbsolutePath(path);\n\n            if (Directory.Exists(absolutePath))\n            {\n                foreach (var file in GetAllFilesRecursive(absolutePath))\n                {\n                    var fileInfo = new FileInfo(file);\n                    fileInfo.IsReadOnly = false;\n                }\n                return true;\n            }\n\n            if (File.Exists(absolutePath))\n            {\n                var fileInfo = new FileInfo(absolutePath);\n                fileInfo.IsReadOnly = false;\n\n                return true;\n            }\n\n            return false;\n        }\n\n        internal static bool WriteTextFileToDisk(string path, string content)\n        {\n            return WriteTextFileToDisk(path, content, out string message);\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal static bool WriteTextFileToDisk(string path, string content, out string message)\n        {\n            if (AssetDatabase.IsOpenForEdit(path, out message) || AssetDatabase.MakeEditable(path))\n            {\n                var fileInfo = new FileInfo(path);\n                if (fileInfo.IsReadOnly)\n                    MakeWritable(path);\n\n                try\n                {\n                    File.WriteAllText(path, content);\n                    return true;\n                }\n                catch (Exception e)\n                {\n                    message = e.Message;\n                }\n            }\n\n            if (string.IsNullOrEmpty(message))\n            {\n                message = \"Failed to write file \" + path + \" to disk.\\nVerify that the file is not read-only or locked.\";\n            }\n\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/FlagSet.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor\n{\n    // Holds a flag set. Can be used with enum flags.\n    // Has semantic value in separating a single value of an enum versus the flag set\n    [Serializable]\n    internal struct FlagSet<T>  where T : IConvertible\n    {\n        private ulong m_Flags;\n\n        public bool HasFlags(T flags)\n        {\n            return (m_Flags & Convert.ToUInt64(flags)) != 0;\n        }\n\n        public void SetFlags(T flags, bool value)\n        {\n            if (value)\n                m_Flags |= Convert.ToUInt64(flags);\n            else\n                m_Flags &= ~Convert.ToUInt64(flags);\n        }\n\n        public FlagSet(T flags)\n        {\n            m_Flags = Convert.ToUInt64(flags);\n        }\n\n        public static implicit operator FlagSet<T>(T flags) {return new FlagSet<T>(flags); }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/DeviceContext.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Runtime.InteropServices;\nusing Unity.Collections;\nusing Unity.Collections.LowLevel.Unsafe;\n\nnamespace UnityEngine.LightTransport\n{\n    [DebuggerDisplay(\"BufferID({Value})\")]\n    public struct BufferID : IEquatable<BufferID>\n    {\n        public UInt64 Value;\n        public BufferID(UInt64 value)\n        {\n            Value = value;\n        }\n\n        public BufferSlice<T> Slice<T>(UInt64 offset = 0)\n            where T : struct\n        {\n            return new BufferSlice<T>(this, offset);\n        }\n\n        // Value type semantics\n        public override int GetHashCode() => Value.GetHashCode();\n        public bool Equals(BufferID other) => other.Value == Value;\n        public override bool Equals(object obj) => obj is BufferID other && Equals(other);\n        public static bool operator ==(BufferID a, BufferID b) => a.Equals(b);\n        public static bool operator !=(BufferID a, BufferID b) => !a.Equals(b);\n    }\n    [DebuggerDisplay(\"BufferSlice(Id: {Id.Value}, Offset: {Offset})\")]\n    public struct BufferSlice<T> : IEquatable<BufferSlice<T>>\n        where T : struct\n    {\n        public BufferSlice(BufferID id, UInt64 offset)\n        {\n            Id = id;\n            Offset = offset;\n        }\n        public BufferID Id;\n        public UInt64 Offset;\n\n        public BufferSlice<U> SafeReinterpret<U>()\n            where U : struct\n        {\n            if (!UnsafeUtility.IsBlittable<U>())\n                throw new ArgumentException($\"Type {typeof(U)} must be blittable. {UnsafeUtility.GetReasonForTypeNonBlittable(typeof(U))}.\");\n\n            int oldSize = UnsafeUtility.SizeOf<T>();\n            int newSize = UnsafeUtility.SizeOf<U>();\n            if (oldSize % newSize != 0)\n                throw new ArgumentException($\"Type {typeof(T)} size must be a multiple of {typeof(U)} size.\");\n\n            return UnsafeReinterpret<U>();\n        }\n\n        public unsafe BufferSlice<U> UnsafeReinterpret<U>()\n            where U : struct\n        {\n            int oldSize = UnsafeUtility.SizeOf<T>();\n            int newSize = UnsafeUtility.SizeOf<U>();\n\n            UInt64 newOffset = (Offset * (UInt64)oldSize) / (UInt64)newSize;\n\n            return new BufferSlice<U>(Id, newOffset);\n        }\n\n        // Value type semantics\n        public override int GetHashCode() => HashCode.Combine(Id, Offset);\n        public bool Equals(BufferSlice<T> other) => other.Id == Id && other.Offset == Offset;\n        public override bool Equals(object obj) => obj is BufferSlice<T> other && Equals(other);\n        public static bool operator ==(BufferSlice<T> a, BufferSlice<T> b) => a.Equals(b);\n        public static bool operator !=(BufferSlice<T> a, BufferSlice<T> b) => !a.Equals(b);\n    }\n    [DebuggerDisplay(\"EventID({Value})\")]\n    public struct EventID : IEquatable<EventID>\n    {\n        public UInt64 Value;\n        public EventID(UInt64 value)\n        {\n            Value = value;\n        }\n\n        // Value type semantics\n        public override int GetHashCode() => Value.GetHashCode();\n        public bool Equals(EventID other) => other.Value == Value;\n        public override bool Equals(object obj) => obj is EventID other && Equals(other);\n        public static bool operator ==(EventID a, EventID b) => a.Equals(b);\n        public static bool operator !=(EventID a, EventID b) => !a.Equals(b);\n    }\n    /// <summary>\n    /// Buffer and command queue abstraction layer hiding the underlying storage\n    /// and compute architecture (CPU or GPU with unified or dedicated memory).\n    /// </summary>\n    public interface IDeviceContext : IDisposable\n    {\n        bool Initialize();\n        BufferID CreateBuffer(UInt64 count, UInt64 stride);\n        void DestroyBuffer(BufferID id);\n        void WriteBuffer<T>(BufferSlice<T> dst, NativeArray<T> src) where T : struct;\n        void ReadBuffer<T>(BufferSlice<T> src, NativeArray<T> dst) where T : struct;\n        void WriteBuffer<T>(BufferSlice<T> dst, NativeArray<T> src, EventID id) where T : struct;\n        void ReadBuffer<T>(BufferSlice<T> src, NativeArray<T> dst, EventID id) where T : struct;\n        EventID CreateEvent();\n        void DestroyEvent(EventID id);\n        bool IsCompleted(EventID id);\n        bool Wait(EventID id);\n        bool Flush();\n    }\n    [StructLayout(LayoutKind.Sequential)]\n    public class ReferenceContext : IDeviceContext\n    {\n        private Dictionary<BufferID, NativeArray<byte>> buffers = new();\n        private uint nextFreeBufferId;\n        private uint nextFreeEventId;\n        public bool Initialize()\n        {\n            return true;\n        }\n        public void Dispose()\n        {\n            foreach (var entry in buffers)\n            {\n                Debug.Assert(entry.Value.IsCreated, \"A buffer was unexpectedly not created.\");\n                entry.Value.Dispose();\n            }\n        }\n        public BufferID CreateBuffer(UInt64 count, UInt64 stride)\n        {\n            Debug.Assert(count != 0, \"Buffer element count cannot be zero.\");\n            Debug.Assert(stride != 0, \"Buffer stride cannot be zero.\");\n            var buffer = new NativeArray<byte>((int)(count * stride), Allocator.Persistent);\n            var idInteger = nextFreeBufferId++;\n            var id = new BufferID(idInteger);\n            buffers[id] = buffer;\n            return id;\n        }\n        public void DestroyBuffer(BufferID id)\n        {\n            Debug.Assert(buffers.ContainsKey(id), \"Invalid buffer ID given.\");\n            buffers[id].Dispose();\n            buffers.Remove(id);\n        }\n        public void WriteBuffer<T>(BufferSlice<T> dst, NativeArray<T> src)\n            where T : struct\n        {\n            Debug.Assert(buffers.ContainsKey(dst.Id), \"Invalid buffer ID given.\");\n            var dstBuffer = buffers[dst.Id].Reinterpret<T>(1);\n            dstBuffer.GetSubArray((int)dst.Offset, dstBuffer.Length - (int)dst.Offset).CopyFrom(src);\n        }\n        public void ReadBuffer<T>(BufferSlice<T> src, NativeArray<T> dst)\n            where T : struct\n        {\n            Debug.Assert(buffers.ContainsKey(src.Id), \"Invalid buffer ID given.\");\n            var srcBuffer = buffers[src.Id].Reinterpret<T>(1);\n            dst.CopyFrom(srcBuffer.GetSubArray((int)src.Offset, srcBuffer.Length - (int)src.Offset));\n        }\n        public void WriteBuffer<T>(BufferSlice<T> dst, NativeArray<T> src, EventID id)\n            where T : struct\n        {\n            WriteBuffer(dst, src);\n        }\n        public void ReadBuffer<T>(BufferSlice<T> src, NativeArray<T> dst, EventID id)\n            where T : struct\n        {\n            ReadBuffer(src, dst);\n        }\n        public EventID CreateEvent()\n        {\n            return new EventID(nextFreeEventId++);\n        }\n        public void DestroyEvent(EventID id)\n        {\n        }\n        public bool IsCompleted(EventID id)\n        {\n            return true;\n        }\n        public bool Wait(EventID id)\n        {\n            return true;\n        }\n        public NativeArray<byte> GetNativeArray(BufferID id)\n        {\n            return buffers[id];\n        }\n\n        public bool Flush()\n        {\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/InputExtraction.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor.LightBaking\n{\n    [NativeHeader(\"Editor/Src/GI/InputExtraction/InputExtraction.Bindings.h\")]\n    [StaticAccessor(\"InputExtractionBindings\", StaticAccessorType.DoubleColon)]\n    internal static class InputExtraction\n    {\n        [StructLayout(LayoutKind.Sequential)]\n        public class SourceMap : IDisposable\n        {\n            internal IntPtr m_Ptr;\n            internal bool m_OwnsPtr;\n\n            public SourceMap()\n            {\n                m_Ptr = Internal_Create();\n                m_OwnsPtr = true;\n            }\n            public SourceMap(IntPtr ptr)\n            {\n                m_Ptr = ptr;\n                m_OwnsPtr = false;\n            }\n            ~SourceMap()\n            {\n                Destroy();\n            }\n\n            public void Dispose()\n            {\n                Destroy();\n                GC.SuppressFinalize(this);\n            }\n\n            void Destroy()\n            {\n                if (m_OwnsPtr && m_Ptr != IntPtr.Zero)\n                {\n                    Internal_Destroy(m_Ptr);\n                    m_Ptr = IntPtr.Zero;\n                }\n            }\n\n            public extern int GetInstanceIndex(int instanceID);\n            public extern int GetInstanceInstanceID(int instanceIndex);\n\n            public extern int GetTreeCount();\n            public extern int GetTreeInstanceIndex(int treeIndex);\n\n            public extern int GetLightIndex(int instanceID);\n            public extern int GetLightInstanceID(int lightIndex);\n\n            static extern IntPtr Internal_Create();\n\n            [NativeMethod(IsThreadSafe = true)]\n            static extern void Internal_Destroy(IntPtr ptr);\n\n            internal static class BindingsMarshaller\n            {\n                public static IntPtr ConvertToNative(SourceMap sourceMap) => sourceMap.m_Ptr;\n            }\n        }\n\n        public static extern bool ExtractFromScene(string outputFolderPath, LightBaker.BakeInput input, LightBaker.LightmapRequests lightmapRequests, LightBaker.LightProbeRequests lightProbeRequests, SourceMap map);\n\n        [NativeMethod(IsThreadSafe = true)]\n        public static extern int[] ComputeOcclusionLightIndicesFromBakeInput(LightBaker.BakeInput bakeInput, UnityEngine.Vector3[] probePositions, uint maxLightsPerProbe);\n\n        [NativeMethod(IsThreadSafe = true)]\n        public static extern int[] GetShadowmaskChannelsFromLightIndices(LightBaker.BakeInput bakeInput, int[] lightIndices);\n\n        private static string LookupGameObjectName(SourceMap map, int instanceIndex)\n        {\n            if (map == null)\n                return \"\";\n            int instanceID = map.GetInstanceInstanceID(instanceIndex);\n            if (instanceID == 0)\n                return \"\";\n            Object obj = EditorUtility.InstanceIDToObject(instanceID);\n            if (obj == null)\n                return \"\";\n            else if (obj is UnityEngine.GameObject go)\n            {\n                return go.name;\n            }\n            else if (obj is UnityEngine.Component component)\n            {\n                return component.gameObject.name;\n            }\n            return \"\";\n        }\n\n        public static string LogInstances(LightBaker.BakeInput bakeInput, SourceMap map)\n        {\n            if (bakeInput is null)\n                return string.Empty;\n            string message = string.Empty;\n            message += $\"      instance count\\t: {bakeInput.instanceCount}\\n\";\n            for (int i = 0; i < bakeInput.instanceCount; ++i)\n            {\n                if (map is null)\n                    message += $\"         Instance [{i}]:\\n\";\n                else\n                    message += $\"         Instance [{i}] [{LookupGameObjectName(map, i)}]:\\n\";\n                LightBaker.Instance instance = bakeInput.instance((uint)i);\n                message += $\"            mesh type\\t\\t\\t: {instance.meshType}\\n\";\n                if (instance.meshType == LightBaker.MeshType.MeshRenderer)\n                    message += $\"            mesh index\\t\\t\\t: {instance.meshIndex}\\n\";\n                else if (instance.meshType == LightBaker.MeshType.Terrain)\n                    message += $\"            terrain index\\t\\t: {instance.terrainIndex}\\n\";\n                message += $\"            transform\\t\\t\\t: {instance.transform.GetRow(0)}\\n\";\n                message += $\"                     \\t\\t\\t: {instance.transform.GetRow(1)}\\n\";\n                message += $\"                     \\t\\t\\t: {instance.transform.GetRow(2)}\\n\";\n                message += $\"                     \\t\\t\\t: {instance.transform.GetRow(3)}\\n\";\n                message += $\"            cast shadows\\t\\t: {instance.castShadows}\\n\";\n                message += $\"            receive shadows\\t: {instance.receiveShadows}\\n\";\n                if (instance.meshType == LightBaker.MeshType.MeshRenderer)\n                {\n                    message += $\"            odd neg scale\\t\\t: {instance.oddNegativeScale}\\n\";\n                    message += $\"            lod group\\t\\t\\t: {instance.lodGroup}\\n\";\n                    message += $\"            lod mask\\t\\t\\t\\t: {instance.lodMask}\\n\";\n                }\n                message += $\"            submesh count\\t\\t: {instance.submeshMaterialIndices.Length}\\n\";\n                string indices = string.Empty;\n                for (int j = 0; j < instance.submeshMaterialIndices.Length; ++j)\n                    indices += instance.submeshMaterialIndices[j] + (j < (instance.submeshMaterialIndices.Length - 1) ? \", \" : \"\");\n                message += $\"            submesh mat idxs\\t: {{{indices}}}\\n\";\n                message += $\"            albedo tex idx\\t\\t: {bakeInput.instanceToAlbedoIndex((uint)i)}\\n\";\n                message += $\"            emissive tex idx\\t: {bakeInput.instanceToEmissiveIndex((uint)i)}\\n\";\n                string transmissiveIndices = string.Empty;\n                for (int j = 0; j < instance.submeshMaterialIndices.Length; ++j)\n                    transmissiveIndices += bakeInput.instanceToTransmissiveIndex((uint)i, (uint)j) + (j < (instance.submeshMaterialIndices.Length - 1) ? \", \" : \"\");\n                message += $\"            trans tex idxs\\t\\t: {{{transmissiveIndices}}}\\n\";\n            }\n            return message;\n        }\n\n        public static string LogSceneMaterials(LightBaker.BakeInput bakeInput)\n        {\n            if (bakeInput is null)\n                return string.Empty;\n            string message = string.Empty;\n            message += $\"      material count\\t\\t: {bakeInput.materialCount}\\n\";\n            for (int i = 0; i < bakeInput.materialCount; ++i)\n            {\n                message += $\"         Material [{i}]:\\n\";\n                message += $\"            doubleSidedGI\\t\\t\\t: {bakeInput.GetMaterial((uint)i).doubleSidedGI}\\n\";\n                message += $\"            transmissionChannels\\t: {bakeInput.GetMaterial((uint)i).transmissionChannels}\\n\";\n                message += $\"            transmissionType\\t\\t: {bakeInput.GetMaterial((uint)i).transmissionType}\\n\";\n            }\n            return message;\n        }\n\n        public static string LogSceneCookies(LightBaker.BakeInput bakeInput)\n        {\n            if (bakeInput is null)\n                return string.Empty;\n            string message = string.Empty;\n\n            message += $\"      cookie tex count\\t: {bakeInput.GetCookieCount()}\\n\";\n            for (int i = 0; i < bakeInput.GetCookieCount(); ++i)\n            {\n                LightBaker.CookieData cookie = bakeInput.GetCookieData((uint)i);\n                message += $\"         CookieTexture [{i}]:\\n\";\n                message += $\"            resolution\\t\\t: {cookie.resolution.width} x {cookie.resolution.height}\\n\";\n                message += $\"            pixelStride\\t\\t: {cookie.pixelStride}\\n\";\n                message += $\"            slices\\t\\t: {cookie.slices}\\n\";\n                message += $\"            repeat\\t\\t: {cookie.repeat}\\n\";\n            }\n            return message;\n        }\n\n        public static string LogSceneLights(LightBaker.BakeInput bakeInput)\n        {\n            if (bakeInput is null)\n                return string.Empty;\n            string message = string.Empty;\n            message += $\"      light count\\t\\t: {bakeInput.GetLightCount()}\\n\";\n            for (int i = 0; i < bakeInput.GetLightCount(); ++i)\n            {\n                LightBaker.Light light = bakeInput.GetLight((uint)i);\n                message += $\"         Light [{i}]:\\n\";\n                message += $\"            color\\t\\t\\t\\t\\t: {light.color}\\n\";\n                message += $\"            indirect color\\t\\t: {light.indirectColor}\\n\";\n                message += $\"            orientation\\t\\t\\t: {light.orientation}\\n\";\n                message += $\"            position\\t\\t\\t\\t: {light.position}\\n\";\n                message += $\"            range\\t\\t\\t\\t\\t: {light.range}\\n\";\n                message += $\"            cookie index\\t\\t: {light.cookieTextureIndex}\\n\";\n                message += $\"            cookie scale\\t\\t: {light.cookieScale}\\n\";\n                message += $\"            cone angle\\t\\t\\t: {light.coneAngle}\\n\";\n                message += $\"            inner cone angle\\t: {light.innerConeAngle}\\n\";\n                message += $\"            shape0\\t\\t\\t\\t: {light.shape0}\\n\";\n                message += $\"            shape1\\t\\t\\t\\t: {light.shape1}\\n\";\n                message += $\"            type\\t\\t\\t\\t\\t: {light.type}\\n\";\n                message += $\"            mode\\t\\t\\t\\t\\t: {light.mode}\\n\";\n                message += $\"            falloff\\t\\t\\t\\t: {light.falloff}\\n\";\n                message += $\"            angular falloff\\t: {light.angularFalloff}\\n\";\n                message += $\"            casts shadows\\t\\t: {light.castsShadows}\\n\";\n                message += $\"            shadowmask chnl\\t: {light.shadowMaskChannel}\\n\";\n            }\n            return message;\n        }\n\n        public static string LogSampleCounts(LightBaker.SampleCount sampleCount)\n        {\n            string message = string.Empty;\n            message += $\"            direct\\t\\t: {sampleCount.directSampleCount}\\n\";\n            message += $\"            indirect\\t\\t: {sampleCount.indirectSampleCount}\\n\";\n            message += $\"            environment\\t: {sampleCount.environmentSampleCount}\\n\";\n            return message;\n        }\n\n        public static string LogSceneSettings(LightBaker.BakeInput bakeInput)\n        {\n            if (bakeInput is null)\n                return string.Empty;\n            var lightingSettings = bakeInput.GetLightingSettings();\n            string message = string.Empty;\n            message += $\"      lighting settings\\t:\\n\";\n            message += $\"         lightmap sample counts:\\n\";\n            message += LogSampleCounts(lightingSettings.lightmapSampleCounts);\n            message += $\"         lightprobe sample counts:\\n\";\n            message += LogSampleCounts(lightingSettings.probeSampleCounts);\n            message += $\"         min bounces\\t\\t\\t\\t: {lightingSettings.minBounces}\\n\";\n            message += $\"         max bounces\\t\\t\\t\\t: {lightingSettings.maxBounces}\\n\";\n            message += $\"         lightmap bake mode\\t: {lightingSettings.lightmapBakeMode}\\n\";\n            message += $\"         mixed lighting mode\\t: {lightingSettings.mixedLightingMode}\\n\";\n            message += $\"         ao enabled\\t\\t\\t\\t: {lightingSettings.aoEnabled}\\n\";\n            message += $\"         ao distance\\t\\t\\t\\t: {lightingSettings.aoDistance}\\n\";\n            return message;\n        }\n\n        public static string LogScene(LightBaker.BakeInput bakeInput, LightBaker.LightmapRequests lightmapRequests, LightBaker.LightProbeRequests lightProbeRequests, SourceMap map)\n        {\n            if (bakeInput is null)\n                return string.Empty;\n            string message = string.Empty;\n            message += LogSceneSettings(bakeInput);\n            message += LogInstances(bakeInput, map);\n            message += $\"      mesh count\\t\\t\\t: {bakeInput.meshCount}\\n\";\n            message += $\"      terrain count\\t\\t: {bakeInput.terrainCount}\\n\";\n            message += $\"      heightmap count\\t: {bakeInput.heightmapCount}\\n\";\n            message += $\"      holemap count\\t\\t: {bakeInput.holemapCount}\\n\";\n            message += LogSceneMaterials(bakeInput);\n            message += $\"      albedo tex count\\t: {bakeInput.albedoTextureCount}\\n\";\n            for (int i = 0; i < bakeInput.albedoTextureCount; ++i)\n            {\n                message += $\"         AlbedoTexture [{i}]:\\n\";\n                message += $\"            resolution\\t\\t: {bakeInput.GetAlbedoTextureData((uint)i).resolution.width} x {bakeInput.GetAlbedoTextureData((uint)i).resolution.height}\\n\";\n            }\n            message += $\"      emissive tex count\\t: {bakeInput.emissiveTextureCount}\\n\";\n            for (int i = 0; i < bakeInput.emissiveTextureCount; ++i)\n            {\n                message += $\"         EmissiveTexture [{i}]:\\n\";\n                message += $\"            resolution\\t\\t: {bakeInput.GetEmissiveTextureData((uint)i).resolution.width} x {bakeInput.GetEmissiveTextureData((uint)i).resolution.height}\\n\";\n            }\n            message += $\"      transmissive tex count\\t: {bakeInput.transmissiveTextureCount}\\n\";\n            for (int i = 0; i < bakeInput.transmissiveTextureCount; ++i)\n            {\n                message += $\"         TransmissiveTexture [{i}]:\\n\";\n                message += $\"            resolution\\t\\t: {bakeInput.GetTransmissiveTextureData((uint)i).resolution.width} x {bakeInput.GetTransmissiveTextureData((uint)i).resolution.height}\\n\";\n            }\n            message += LogSceneCookies(bakeInput);\n            message += LogSceneLights(bakeInput);\n            message += $\"      lightmap count\\t: {lightmapRequests.lightmapCount}\\n\";\n            for (int i = 0; i < lightmapRequests.lightmapCount; ++i)\n            {\n                message += $\"         Lightmap [{i}]:\\n\";\n                message += $\"            resolution\\t\\t: {lightmapRequests.lightmapResolution((uint)i).width} x {lightmapRequests.lightmapResolution((uint)i).height}\\n\";\n                message += $\"            instance count\\t: {lightmapRequests.lightmapInstanceCount((uint)i)}\\n\";\n            }\n            return message;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/InputExtraction.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.LightBaking;\nusing static UnityEditor.LightBaking.LightBaker;\n\nnamespace UnityEngine.LightTransport\n{\n    public static class InputExtraction\n    {\n        // Completely opaque in the public API, this effectively hides internal LightBaker details.\n        public class BakeInput\n        {\n            internal BakeInput(LightBaker.BakeInput editorBakeInput)\n            {\n                bakeInput = editorBakeInput;\n            }\n            internal LightBaker.BakeInput bakeInput { get; }\n\n            // Requests are not exposed in the public API, but we need them in LightBaker.PopulateWorld(). Going forward, requests will be split from the bake input in the public API as well.\n            internal LightmapRequests lightmapRequests { get; set; }\n            internal LightProbeRequests lightProbeRequests { get; set; }\n        }\n\n        public static bool ExtractFromScene(out BakeInput bakeInput)\n        {\n            const string outputFolderPath = \"unused\"; // We are not using disk IO.\n            LightBaker.BakeInput lightBakerBakeInput = new();\n            LightBaker.LightmapRequests lightBakerLightmapRequests = new();\n            LightBaker.LightProbeRequests lightBakerlightProbeRequests = new();\n            UnityEditor.LightBaking.InputExtraction.SourceMap map = new();\n            bool result = UnityEditor.LightBaking.InputExtraction.ExtractFromScene(outputFolderPath, lightBakerBakeInput, lightBakerLightmapRequests, lightBakerlightProbeRequests, map);\n            bakeInput = new BakeInput(lightBakerBakeInput)\n            {\n                lightmapRequests = lightBakerLightmapRequests,\n                lightProbeRequests = lightBakerlightProbeRequests\n            };\n\n            return result;\n        }\n\n        public static bool PopulateWorld(BakeInput bakeInput, BakeProgressState progress, IDeviceContext context, IWorld world)\n        {\n            LightBaker.Result result = LightBaker.PopulateWorld(bakeInput.bakeInput, bakeInput.lightmapRequests, bakeInput.lightProbeRequests, progress, context, world);\n            return result.type == LightBaker.ResultType.Success;\n        }\n\n        // Note that in the non-public API, serialization of bake input does not imply serialization of requests.\n        internal static bool SerializeBakeInput(string path, InputExtraction.BakeInput bakeInput) => LightBaker.Serialize(path, bakeInput.bakeInput);\n\n        // Note that in the non-public API, deserialization of bake input does not imply deserialization of requests.\n        internal static bool DeserializeBakeInput(string path, out InputExtraction.BakeInput bakeInput)\n        {\n            UnityEditor.LightBaking.LightBaker.BakeInput lightBakerBakeInput = new();\n            bakeInput = new BakeInput(lightBakerBakeInput);\n            return LightBaker.Deserialize(path, bakeInput.bakeInput);\n        }\n\n        public static int[] ComputeOcclusionLightIndicesFromBakeInput(BakeInput bakeInput, Vector3[] probePositions, uint maxLightsPerProbe = 4)\n        {\n            return UnityEditor.LightBaking.InputExtraction.ComputeOcclusionLightIndicesFromBakeInput(bakeInput.bakeInput, probePositions, maxLightsPerProbe);\n        }\n\n        public static int[] GetShadowmaskChannelsFromLightIndices(BakeInput bakeInput, int[] lightIndices)\n        {\n            return UnityEditor.LightBaking.InputExtraction.GetShadowmaskChannelsFromLightIndices(bakeInput.bakeInput, lightIndices);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/IntegrationContext.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine.Bindings;\n\nnamespace UnityEngine.LightTransport\n{\n    [StructLayout(LayoutKind.Sequential)]\n    public class IntegrationContext : IDisposable\n    {\n        [NativeMethod(IsThreadSafe = true)]\n        static extern IntPtr Internal_Create();\n\n        [NativeMethod(IsThreadSafe = true)]\n        static extern void Internal_Destroy(IntPtr ptr);\n\n        internal IntPtr m_Ptr;\n        internal bool m_OwnsPtr;\n\n        public IntegrationContext()\n        {\n            m_Ptr = Internal_Create();\n            m_OwnsPtr = true;\n        }\n        public IntegrationContext(IntPtr ptr)\n        {\n            m_Ptr = ptr;\n            m_OwnsPtr = false;\n        }\n        ~IntegrationContext()\n        {\n            Destroy();\n        }\n        public void Dispose()\n        {\n            Destroy();\n            GC.SuppressFinalize(this);\n        }\n        void Destroy()\n        {\n            if (m_OwnsPtr && m_Ptr != IntPtr.Zero)\n            {\n                Internal_Destroy(m_Ptr);\n                m_Ptr = IntPtr.Zero;\n            }\n        }\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(IntegrationContext obj) => obj.m_Ptr;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/InteractiveLightBaking.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/GI/InteractiveLightBaking.Bindings.h\")]\n    internal class InteractiveLightBaking\n    {\n        public struct InteractiveLightmapData\n        {\n            public Int32 numLightmaps;\n            public Int32 lightmapsMode;\n            public Vector4 decodeValues;\n            public Texture2D[] lightmaps;\n            public Texture2D[] directionalities;\n            public Texture2D[] shadowmasks;\n            public LightmapData[] ToLightmapData()\n            {\n                LightmapData[] lightmapData = new LightmapData[numLightmaps];\n                for (int i = 0; i < numLightmaps; i++)\n                {\n                    lightmapData[i] = new LightmapData();\n                    lightmapData[i].lightmapColor = lightmaps[i];\n                    lightmapData[i].lightmapDir = directionalities[i];\n                    lightmapData[i].shadowMask = shadowmasks[i];\n                }\n\n                return lightmapData;\n            }\n        }\n\n        [FreeFunction]\n        public static extern InteractiveLightmapData GetLightmapData();\n        [FreeFunction]\n        public static extern Vector4 GetLightmapSTFromRenderer(int instanceID);\n        [FreeFunction]\n        public static extern ushort GetLightmapIndexFromRenderer(int instanceID);\n        [FreeFunction]\n        public static extern bool IsBakingDone();\n        [FreeFunction]\n        [NativeName(\"GetInteractiveLightingSettings\")]\n        public static extern LightingSettings GetLightingSettings();\n\n        [StaticAccessor(\"InteractiveLightBakingDataManager::Get()\", StaticAccessorType.Dot)]\n        public static extern float lightmapResolutionScale { get; set; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/LightBaker.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.LightTransport;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.LightBaking\n{\n    [NativeHeader(\"Editor/Src/GI/LightBaker/LightBaker.Bindings.h\")]\n    [StaticAccessor(\"LightBakerBindings\", StaticAccessorType.DoubleColon)]\n    internal static partial class LightBaker\n    {\n        public enum ResultType : uint\n        {\n            Success = 0,\n            Cancelled,\n            JobFailed,\n            OutOfMemory,\n            InvalidInput,\n            LowLevelAPIFailure,\n            FailedCreatingJobQueue,\n            IOFailed,\n            ConnectedToBaker,\n            Undefined\n        }\n\n        [RequiredByNativeCode]\n        public struct Result\n        {\n            public ResultType type;\n            public string message;\n            public override string ToString()\n            {\n                if (message.Length == 0)\n                    return $\"Result type: '{type}'\";\n                return $\"Result type: '{type}', message: '{message}'\";\n            }\n\n            public IProbeIntegrator.Result ConvertToIProbeIntegratorResult()\n            {\n                IProbeIntegrator.Result result = new ()\n                {\n                    type = (IProbeIntegrator.ResultType)type,\n                    message = message\n                };\n                return result;\n            }\n        }\n\n        public enum Backend\n        {\n            CPU = 0,\n            GPU = 1,\n            UnityComputeGPU = 2\n        }\n        public enum TransmissionChannels\n        {\n            Red = 0,\n            Alpha = 1,\n            AlphaCutout = 2,\n            RGB = 3,\n            None = 4\n        }\n        public enum TransmissionType\n        {\n            Opacity = 0,\n            Transparency = 1,\n            None = 2\n        }\n        public enum MeshType\n        {\n            Terrain = 0,\n            MeshRenderer = 1\n        }\n        public enum MixedLightingMode\n        {\n            IndirectOnly = 0,\n            Subtractive = 1,\n            Shadowmask = 2,\n        };\n        public enum LightmapBakeMode\n        {\n            NonDirectional = 0,\n            CombinedDirectional = 1\n        };\n        [Flags]\n        public enum ProbeRequestOutputType : uint\n        {\n            RadianceDirect = 1 << 0,\n            RadianceIndirect = 1 << 1,\n            Validity = 1 << 2,\n            MixedLightOcclusion = 1 << 3,\n            LightProbeOcclusion = 1 << 4,\n            EnvironmentOcclusion = 1 << 5,\n            Depth = 1 << 6,\n            All = 0xFFFFFFFF\n        };\n        public struct ProbeRequest\n        {\n            public ProbeRequestOutputType outputTypeMask;\n            public ulong positionOffset;\n            public ulong positionLength;\n            public float pushoff;\n            public string outputFolderPath;\n\n            // Environment occlusion\n            public ulong integrationRadiusOffset;\n            public uint environmentOcclusionSampleCount;\n            public bool ignoreDirectEnvironment;\n            public bool ignoreIndirectEnvironment;\n        };\n        [Flags]\n        public enum LightmapRequestOutputType : uint\n        {\n            IrradianceIndirect = 1 << 0,\n            IrradianceDirect = 1 << 1,\n            IrradianceEnvironment = 1 << 2,\n            Occupancy = 1 << 3,\n            Validity = 1 << 4,\n            DirectionalityIndirect = 1 << 5,\n            DirectionalityDirect = 1 << 6,\n            AmbientOcclusion = 1 << 7,\n            Shadowmask = 1 << 8,\n            Normal = 1 << 9,\n            ChartIndex = 1 << 10,\n            OverlapPixelIndex = 1 << 11,\n            All = 0xFFFFFFFF\n        };\n        public enum TilingMode : byte\n        {   // Assuming a 4k lightmap (16M texels), the tiling will yield the following chunk sizes:\n            None = 0,                 // 4k * 4k =    16M texels\n            Quarter = 1,              // 2k * 2k =     4M texels\n            Sixteenth = 2,            // 1k * 1k =     1M texels\n            Sixtyfourth = 3,          // 512 * 512 = 262k texels\n            TwoHundredFiftySixth = 4, // 256 * 256 =  65k texels\n            Max = TwoHundredFiftySixth,\n            Error = 5                 // Error. We don't want to go lower (GPU occupancy will start to be a problem for smaller atlas sizes).\n        };\n        public struct LightmapRequest\n        {\n            public LightmapRequestOutputType outputTypeMask;\n            public uint lightmapOffset;\n            public uint lightmapCount;\n            public TilingMode tilingMode;\n            public string outputFolderPath;\n            public float pushoff;\n        };\n        public struct Resolution\n        {\n            public Resolution(uint widthIn, uint heightIn)\n            {\n                width = widthIn;\n                height = heightIn;\n            }\n            public uint width;\n            public uint height;\n        }\n\n        public struct TextureData\n        {\n            public TextureData(Resolution resolutionIn)\n            {\n                resolution = resolutionIn;\n                data = new Vector4[resolution.width * resolution.height];\n            }\n            public Resolution resolution;\n            public Vector4[] data;\n        }\n\n        public struct TextureTransform\n        {\n            public Vector2 scale;\n            public Vector2 offset;\n        };\n\n        public struct TextureProperties\n        {\n            public TextureWrapMode wrapModeU;\n            public TextureWrapMode wrapModeV;\n            public FilterMode filterMode;\n            public TextureTransform textureST;\n        };\n\n        public struct CookieData\n        {\n            public CookieData(Resolution resolutionIn, uint pixelStrideIn, uint slicesIn, bool repeatIn)\n            {\n                resolution = resolutionIn;\n                pixelStride = pixelStrideIn;\n                slices = slicesIn;\n                repeat = repeatIn;\n                data = new byte[resolution.width * resolution.height * slices * pixelStride];\n            }\n            public Resolution resolution;\n            public uint pixelStride;\n            public uint slices;\n            public bool repeat;\n            public byte[] data;\n        }\n\n        public struct Instance\n        {\n            public MeshType meshType;\n            public int meshIndex; // index into BakeInput::m_MeshData, -1 for Terrain\n            public int terrainIndex; // index into BakeInput::m_TerrainData, -1 for MeshRenderer\n            public Matrix4x4 transform;\n            public bool castShadows;\n            public bool receiveShadows;\n            public bool oddNegativeScale;\n            public int lodGroup;\n            public byte lodMask;\n            public int[] submeshMaterialIndices;\n        }\n\n        public struct Terrain\n        {\n            public uint heightMapIndex; // index into BakeInput::m_HeightmapData\n            public int terrainHoleIndex; // index into BakeInput::m_TerrainHoleData -1 means no hole data\n            public float outputResolution;\n            public Vector3 heightmapScale;\n            public Vector4 uvBounds;\n        }\n\n        public struct Material\n        {\n            public bool doubleSidedGI;\n            public TransmissionChannels transmissionChannels;\n            public TransmissionType transmissionType;\n        }\n\n        public enum LightType : byte\n        {\n            Directional = 0,\n            Point = 1,\n            Spot = 2,\n            Rectangle = 3,\n            Disc = 4,\n            SpotPyramidShape = 5,\n            SpotBoxShape = 6\n        };\n\n        public enum FalloffType : byte\n        {\n            InverseSquared = 0,\n            InverseSquaredNoRangeAttenuation = 1,\n            Linear = 2,\n            Legacy = 3\n        };\n\n        public enum AngularFalloffType : byte\n        {\n            LUT = 0,\n            AnalyticAndInnerAngle = 1\n        };\n\n        public enum LightMode : byte\n        {\n            Realtime = 0,\n            Mixed = 1,\n            Baked = 2\n        };\n\n        public struct Light\n        {\n            public Vector3 color;\n            public Vector3 indirectColor;\n            public Quaternion orientation;\n            public Vector3 position;\n            public float range;\n            public int cookieTextureIndex;\n            public float cookieScale;\n            public float coneAngle;\n            public float innerConeAngle;\n            public float shape0;\n            public float shape1;\n            public LightType type;\n            public LightMode mode;\n            public FalloffType falloff;\n            public AngularFalloffType angularFalloff;\n            public bool castsShadows;\n            public int shadowMaskChannel;\n        }\n\n        public struct SampleCount\n        {\n            public uint directSampleCount;\n            public uint indirectSampleCount;\n            public uint environmentSampleCount;\n        };\n\n        public struct LightingSettings\n        {\n            public SampleCount lightmapSampleCounts;\n            public SampleCount probeSampleCounts;\n            public uint minBounces;\n            public uint maxBounces;\n            public LightmapBakeMode lightmapBakeMode;\n            public MixedLightingMode mixedLightingMode;\n            public bool aoEnabled;\n            public float aoDistance;\n        };\n\n        [RequiredByNativeCode]\n        [StructLayout(LayoutKind.Sequential)]\n        public class ExternalProcessConnection : IDisposable\n        {\n            private IntPtr _ptr;\n            private readonly bool _ownsPtr;\n\n            public ExternalProcessConnection()\n            {\n                _ptr = Internal_Create();\n                _ownsPtr = true;\n            }\n\n            public ExternalProcessConnection(IntPtr ptr)\n            {\n                _ptr = ptr;\n                _ownsPtr = false;\n            }\n\n            public bool Connect(int bakePortNumber)\n            {\n                return Internal_Connect(bakePortNumber);\n            }\n\n            ~ExternalProcessConnection()\n            {\n                Destroy();\n            }\n\n            public void Dispose()\n            {\n                Destroy();\n                GC.SuppressFinalize(this);\n            }\n\n            void Destroy()\n            {\n                if (_ownsPtr && _ptr != IntPtr.Zero)\n                {\n                    Internal_Destroy(_ptr);\n                    _ptr = IntPtr.Zero;\n                }\n            }\n\n            [NativeMethod(IsThreadSafe = true)]\n            static extern void Internal_Destroy(IntPtr ptr);\n            [NativeMethod(IsThreadSafe = true)]\n            static extern IntPtr Internal_Create();\n            extern bool Internal_Connect(int bakePortNumber);\n\n            internal static class BindingsMarshaller\n            {\n                public static IntPtr ConvertToNative(ExternalProcessConnection connection) => connection._ptr;\n            }\n        }\n\n        [RequiredByNativeCode]\n        [StructLayout(LayoutKind.Sequential)]\n        public class BakeInput : IDisposable\n        {\n            private IntPtr _ptr;\n            private readonly bool _ownsPtr;\n\n            public BakeInput()\n            {\n                _ptr = Internal_Create();\n                _ownsPtr = true;\n            }\n            public BakeInput(IntPtr ptr)\n            {\n                _ptr = ptr;\n                _ownsPtr = false;\n            }\n            ~BakeInput()\n            {\n                Destroy();\n            }\n\n            public void Dispose()\n            {\n                Destroy();\n                GC.SuppressFinalize(this);\n            }\n\n            void Destroy()\n            {\n                if (_ownsPtr && _ptr != IntPtr.Zero)\n                {\n                    Internal_Destroy(_ptr);\n                    _ptr = IntPtr.Zero;\n                }\n            }\n\n            public extern ulong GetByteSize();\n\n            public Texture2D GetAlbedoTexture(uint index)\n            {\n                if (index >= albedoTextureCount)\n                    throw new ArgumentException($\"index must be between 0 and {albedoTextureCount - 1}, but was {index}\");\n                TextureData textureData = GetAlbedoTextureData(index);\n                Texture2D tex = new ((int)textureData.resolution.width, (int)textureData.resolution.height, TextureFormat.RGBAFloat, false);\n                tex.SetPixelData(textureData.data, 0);\n                tex.filterMode = FilterMode.Point;\n                tex.Apply();\n                return tex;\n            }\n\n            public Texture2D GetEmissiveTexture(uint index)\n            {\n                if (index >= emissiveTextureCount)\n                    throw new ArgumentException($\"index must be between 0 and {emissiveTextureCount - 1}, but was {index}\");\n                TextureData textureData = GetEmissiveTextureData(index);\n                Texture2D tex = new ((int)textureData.resolution.width, (int)textureData.resolution.height, TextureFormat.RGBAFloat, false);\n                tex.SetPixelData(textureData.data, 0);\n                tex.filterMode = FilterMode.Point;\n                tex.Apply();\n                return tex;\n            }\n\n            static extern IntPtr Internal_Create();\n            [NativeMethod(IsThreadSafe = true)]\n            static extern void Internal_Destroy(IntPtr ptr);\n\n            extern LightingSettings Internal_GetLightingSettings();\n            public LightingSettings GetLightingSettings()\n            {\n                return Internal_GetLightingSettings();\n            }\n            extern void Internal_SetLightingSettings(LightingSettings lightingSettings);\n            public void SetLightingSettings(LightingSettings lightingSettings)\n            {\n                Internal_SetLightingSettings(lightingSettings);\n            }\n\n            public extern uint instanceCount { get; }\n            extern Instance Internal_Instance(uint index);\n            public Instance instance(uint index)\n            {\n                if (index >= instanceCount)\n                    throw new ArgumentException($\"index must be between 0 and {instanceCount - 1}, but was {index}\");\n                Instance instance = Internal_Instance(index);\n                return instance;\n            }\n            extern void Internal_SetInstance(uint index, Instance instance);\n            public void instance(uint index, Instance instance)\n            {\n                if (index >= instanceCount)\n                    throw new ArgumentException($\"index must be between 0 and {instanceCount - 1}, but was {index}\");\n                Internal_SetInstance(index, instance);\n            }\n\n            public extern uint terrainCount { get; }\n            extern Terrain Internal_GetTerrain(uint index);\n            public Terrain GetTerrain(uint index)\n            {\n                if (index >= terrainCount)\n                    throw new ArgumentException($\"index must be between 0 and {terrainCount - 1}, but was {index}\");\n                Terrain terrain = Internal_GetTerrain(index);\n                return terrain;\n            }\n\n            public extern Vector2[] GetUV1VertexData(uint meshIndex);\n\n            public extern uint meshCount { get; }\n            public extern uint heightmapCount { get; }\n            public extern uint holemapCount { get; }\n            public extern uint materialCount { get; }\n            extern Material Internal_GetMaterial(uint index);\n            extern void Internal_SetMaterial(uint index, Material material);\n            public Material GetMaterial(uint index)\n            {\n                if (index >= materialCount)\n                    throw new ArgumentException($\"index must be between 0 and {materialCount - 1}, but was {index}\");\n                Material material = Internal_GetMaterial(index);\n                return material;\n            }\n            public void SetMaterial(uint index, Material material)\n            {\n                if (index >= materialCount)\n                    throw new ArgumentException($\"index must be between 0 and {materialCount - 1}, but was {index}\");\n                Internal_SetMaterial(index, material);\n            }\n            public int GetMaterialIndex(uint instanceIndex, uint submeshIndex)\n            {\n                if (instanceIndex >= instanceCount)\n                    throw new ArgumentException($\"instanceIndex must be between 0 and {instanceCount - 1}, but was {instanceIndex}\");\n                Instance theInstance = instance(instanceIndex);\n                if (theInstance.submeshMaterialIndices.Length == 0)\n                    throw new ArgumentException($\"instance {instanceIndex} has not materials\");\n                if (submeshIndex >= theInstance.submeshMaterialIndices.Length)\n                    throw new ArgumentException($\"submeshIndex must be between 0 and {theInstance.submeshMaterialIndices.Length - 1}, but was {submeshIndex}\");\n                return theInstance.submeshMaterialIndices[submeshIndex];\n            }\n            extern uint Internal_GetLightCount();\n            public uint GetLightCount()\n            {\n                return Internal_GetLightCount();\n            }\n            extern Light Internal_GetLight(uint index);\n            extern void Internal_SetLight(uint index, Light light);\n            public Light GetLight(uint index)\n            {\n                if (index >= GetLightCount())\n                    throw new ArgumentException($\"index must be between 0 and {GetLightCount() - 1}, but was {index}\");\n                return Internal_GetLight(index);\n            }\n            public void SetLight(uint index, Light light)\n            {\n                if (index >= GetLightCount())\n                    throw new ArgumentException($\"index must be between 0 and {GetLightCount() - 1}, but was {0}\");\n                Internal_SetLight(index, light);\n            }\n\n            extern int Internal_instanceAlbedoEmissiveIndex(uint instanceIndex);\n            extern int Internal_instanceTransmissiveIndex(uint instanceIndex, uint submeshIndex);\n            public int instanceToAlbedoIndex(uint instanceIndex)\n            {\n                if (instanceIndex >= instanceCount)\n                    throw new ArgumentException($\"index must be between 0 and {instanceCount - 1}, but was {instanceIndex}\");\n                return Internal_instanceAlbedoEmissiveIndex(instanceIndex);\n            }\n            public int instanceToEmissiveIndex(uint instanceIndex)\n            {\n                if (instanceIndex >= instanceCount)\n                    throw new ArgumentException($\"index must be between 0 and {instanceCount - 1}, but was {instanceIndex}\");\n                return Internal_instanceAlbedoEmissiveIndex(instanceIndex);\n            }\n            public int instanceToTransmissiveIndex(uint instanceIndex, uint submeshIndex)\n            {\n                if (instanceIndex >= instanceCount)\n                    throw new ArgumentException($\"index must be between 0 and {instanceCount - 1}, but was {instanceIndex}\");\n                Instance inst = instance(instanceIndex);\n                int submeshCount = inst.submeshMaterialIndices.Length;\n                if (submeshIndex >= submeshCount)\n                    throw new ArgumentException($\"submeshIndex must be between 0 and {submeshCount - 1}, but was {submeshIndex}\");\n                int materialIndex = inst.submeshMaterialIndices[submeshIndex];\n                if (materialIndex == -1)\n                    throw new ArgumentException($\"material for submesh {submeshIndex} did not exist.\");\n\n                return Internal_instanceTransmissiveIndex(instanceIndex, submeshIndex);\n            }\n\n            public extern uint albedoTextureCount { get; }\n            extern TextureData Internal_GetAlbedoTextureData(uint index);\n            extern void Internal_SetAlbedoTextureData(uint index, TextureData textureData);\n\n            public TextureData GetAlbedoTextureData(uint index)\n            {\n                if (index >= albedoTextureCount)\n                    throw new ArgumentException($\"index must be between 0 and {albedoTextureCount - 1}, but was {index}\");\n                return Internal_GetAlbedoTextureData(index);\n            }\n            public void SetAlbedoTextureData(uint index, TextureData textureData)\n            {\n                if (index >= albedoTextureCount)\n                    throw new ArgumentException($\"index must be between 0 and {albedoTextureCount - 1}, but was {index}\");\n                Internal_SetAlbedoTextureData(index, textureData);\n            }\n\n            public extern uint emissiveTextureCount { get; }\n            public extern uint transmissiveTextureCount { get; }\n            public extern uint transmissiveTexturePropertiesCount { get; }\n            extern TextureData Internal_GetEmissiveTextureData(uint index);\n            extern void Internal_SetEmissiveTextureData(uint index, TextureData textureData);\n            public TextureData GetEmissiveTextureData(uint index)\n            {\n                if (index >= emissiveTextureCount)\n                    throw new ArgumentException($\"index must be between 0 and {emissiveTextureCount - 1}, but was {index}\");\n                return Internal_GetEmissiveTextureData(index);\n            }\n            public void SetEmissiveTextureData(uint index, TextureData textureData)\n            {\n                if (index >= emissiveTextureCount)\n                    throw new ArgumentException($\"index must be between 0 and {emissiveTextureCount - 1}, but was {index}\");\n                Internal_SetEmissiveTextureData(index, textureData);\n            }\n\n            extern TextureData Internal_GetTransmissiveTextureData(uint index);\n            extern void Internal_SetTransmissiveTextureData(uint index, TextureData textureData);\n            public TextureData GetTransmissiveTextureData(uint index)\n            {\n                if (index >= transmissiveTextureCount)\n                    throw new ArgumentException($\"index must be between 0 and {transmissiveTextureCount - 1}, but was {index}\");\n                return Internal_GetTransmissiveTextureData(index);\n            }\n            public void SetTransmissiveTextureData(uint index, TextureData textureData)\n            {\n                if (index >= emissiveTextureCount)\n                    throw new ArgumentException($\"index must be between 0 and {transmissiveTextureCount - 1}, but was {index}\");\n                Internal_SetTransmissiveTextureData(index, textureData);\n            }\n            extern TextureProperties Internal_GetTransmissiveTextureProperties(uint index);\n            public TextureProperties GetTransmissiveTextureProperties(uint index)\n            {\n                if (index >= transmissiveTexturePropertiesCount)\n                    throw new ArgumentException($\"index must be between 0 and {transmissiveTexturePropertiesCount - 1}, but was {index}\");\n                return Internal_GetTransmissiveTextureProperties(index);\n            }\n            extern void Internal_SetTransmissiveTextureProperties(uint index, TextureProperties textureProperties);\n            public void SetTransmissiveTextureProperties(uint index, TextureProperties textureProperties)\n            {\n                if (index >= transmissiveTexturePropertiesCount)\n                    throw new ArgumentException($\"index must be between 0 and {transmissiveTexturePropertiesCount - 1}, but was {index}\");\n                Internal_SetTransmissiveTextureProperties(index, textureProperties);\n            }\n\n            public extern uint GetCookieCount();\n            extern CookieData Internal_GetCookieData(uint index);\n            extern void Internal_SetCookieData(uint index, CookieData cookieData);\n            public CookieData GetCookieData(uint index)\n            {\n                if (index >= GetCookieCount())\n                    throw new ArgumentException($\"index must be between 0 and {GetCookieCount() - 1}, but was {index}\");\n                return Internal_GetCookieData(index);\n            }\n            public void SetCookieData(uint index, CookieData cookieData)\n            {\n                if (index >= GetCookieCount())\n                    throw new ArgumentException($\"index must be between 0 and {GetCookieCount() - 1}, but was {index}\");\n                Internal_SetCookieData(index, cookieData);\n            }\n            public extern void SetEnvironment(Vector4 color);\n            public extern void SetEnvironmentFromTextures(TextureData posX, TextureData negX, TextureData posY, TextureData negY, TextureData posZ, TextureData negZ);\n            public extern TextureData GetEnvironmentCubeTexture();\n\n            internal static class BindingsMarshaller\n            {\n                public static IntPtr ConvertToNative(BakeInput bakeInput) => bakeInput._ptr;\n            }\n            public extern bool CheckIntegrity();\n        }\n\n        [RequiredByNativeCode]\n        [StructLayout(LayoutKind.Sequential)]\n        public class LightProbeRequests : IDisposable\n        {\n            private IntPtr _ptr;\n            private readonly bool _ownsPtr;\n\n            public LightProbeRequests()\n            {\n                _ptr = Internal_Create();\n                _ownsPtr = true;\n            }\n            public LightProbeRequests(IntPtr ptr)\n            {\n                _ptr = ptr;\n                _ownsPtr = false;\n            }\n            ~LightProbeRequests()\n            {\n                Destroy();\n            }\n\n            public void Dispose()\n            {\n                Destroy();\n                GC.SuppressFinalize(this);\n            }\n\n            void Destroy()\n            {\n                if (_ownsPtr && _ptr != IntPtr.Zero)\n                {\n                    Internal_Destroy(_ptr);\n                    _ptr = IntPtr.Zero;\n                }\n            }\n\n            public extern ulong GetByteSize();\n            static extern IntPtr Internal_Create();\n            [NativeMethod(IsThreadSafe = true)]\n            static extern void Internal_Destroy(IntPtr ptr);\n\n            public void SetIntegrationRadii(float[] positions)\n            {\n                SetIntegrationRadii(positions.AsSpan());\n            }\n            public extern void SetIntegrationRadii(ReadOnlySpan<float> positions);\n            public extern Vector3[] GetProbePositions();\n            public extern float[] GetIntegrationRadii();\n            public extern uint lightProbeCount { get; }\n            public extern ProbeRequest[] GetProbeRequests();\n            public extern void SetLightProbeRequests(ProbeRequest[] requests);\n\n            internal static class BindingsMarshaller\n            {\n                public static IntPtr ConvertToNative(LightProbeRequests lightProbeRequests) => lightProbeRequests._ptr;\n            }\n            public extern bool CheckIntegrity();\n        }\n\n        [RequiredByNativeCode]\n        [StructLayout(LayoutKind.Sequential)]\n        public class LightmapRequests : IDisposable\n        {\n            private IntPtr _ptr;\n            private readonly bool _ownsPtr;\n\n            public LightmapRequests()\n            {\n                _ptr = Internal_Create();\n                _ownsPtr = true;\n            }\n            public LightmapRequests(IntPtr ptr)\n            {\n                _ptr = ptr;\n                _ownsPtr = false;\n            }\n            ~LightmapRequests()\n            {\n                Destroy();\n            }\n\n            public void Dispose()\n            {\n                Destroy();\n                GC.SuppressFinalize(this);\n            }\n\n            void Destroy()\n            {\n                if (_ownsPtr && _ptr != IntPtr.Zero)\n                {\n                    Internal_Destroy(_ptr);\n                    _ptr = IntPtr.Zero;\n                }\n            }\n\n            public extern ulong GetByteSize();\n            static extern IntPtr Internal_Create();\n            [NativeMethod(IsThreadSafe = true)]\n            static extern void Internal_Destroy(IntPtr ptr);\n\n            public extern LightmapRequest[] GetLightmapRequests();\n            public extern void SetLightmapRequests(LightmapRequest[] requests);\n\n            public uint lightmapInstanceCount(uint index)\n            {\n                if (index >= lightmapCount)\n                    throw new ArgumentException($\"index must be between 0 and {lightmapCount - 1}, but was {index}\");\n                return Internal_InstanceCount(index);\n            }\n\n            public extern uint lightmapCount { get; }\n            extern uint Internal_LightmapWidth(uint index);\n            extern uint Internal_LightmapHeight(uint index);\n            extern uint Internal_InstanceCount(uint lightmapIndex);\n            public extern void SetLightmapResolution(Resolution resolution);\n            public extern void SetSingleLightmapResolution(uint index, Resolution resolution);\n            public Resolution lightmapResolution(uint index)\n            {\n                if (index >= lightmapCount)\n                    throw new ArgumentException($\"index must be between 0 and {lightmapCount - 1}, but was {index}\");\n                Resolution resolution;\n                resolution.width = Internal_LightmapWidth(index);\n                resolution.height = Internal_LightmapHeight(index);\n                return resolution;\n            }\n\n            internal static class BindingsMarshaller\n            {\n                public static IntPtr ConvertToNative(LightmapRequests lightmapRequests) => lightmapRequests._ptr;\n            }\n            public extern bool CheckIntegrity();\n        }\n\n        [RequiredByNativeCode]\n        [StructLayout(LayoutKind.Sequential)]\n        public class DeviceSettings : IDisposable\n        {\n            static extern IntPtr Internal_Create();\n            [NativeMethod(IsThreadSafe = true)]\n\n            public extern bool Initialize(Backend backend);\n\n            [NativeMethod(IsThreadSafe = true)]\n            static extern void Internal_Destroy(IntPtr ptr);\n\n            private IntPtr _ptr;\n            private bool _ownsPtr;\n\n            public DeviceSettings()\n            {\n                _ptr = Internal_Create();\n                _ownsPtr = true;\n            }\n            public DeviceSettings(IntPtr ptr)\n            {\n                _ptr = ptr;\n                _ownsPtr = false;\n            }\n            ~DeviceSettings()\n            {\n                Destroy();\n            }\n\n            public void Dispose()\n            {\n                Destroy();\n                GC.SuppressFinalize(this);\n            }\n\n            void Destroy()\n            {\n                if (_ownsPtr && _ptr != IntPtr.Zero)\n                {\n                    Internal_Destroy(_ptr);\n                    _ptr = IntPtr.Zero;\n                }\n            }\n\n            private extern Backend Internal_GetBackend();\n            private extern void Internal_SetBackend(Backend backend);\n\n            internal Backend _backend\n            {\n                get => Internal_GetBackend();\n                set => Internal_SetBackend(value);\n            }\n\n            internal static class BindingsMarshaller\n            {\n                public static IntPtr ConvertToNative(DeviceSettings obj) => obj._ptr;\n            }\n        }\n\n        public static Result PopulateWorld(BakeInput bakeInput, LightmapRequests lightmapRequests, LightProbeRequests lightProbeRequests, BakeProgressState progress,\n            UnityEngine.LightTransport.IDeviceContext context, UnityEngine.LightTransport.IWorld world)\n        {\n            Result result = new ();\n            if (context is RadeonRaysContext radeonRaysContext)\n            {\n                IntegrationContext integrationContext = new ();\n                result = PopulateWorldRadeonRays(bakeInput, lightmapRequests, lightProbeRequests, progress, radeonRaysContext, integrationContext);\n                Debug.Assert(world is RadeonRaysWorld);\n                var rrWorld = world as RadeonRaysWorld;\n                rrWorld.SetIntegrationContext(integrationContext);\n            }\n            else if (context is WintermuteContext wintermuteContext)\n            {\n                IntegrationContext integrationContext = new ();\n                result = PopulateWorldWintermute(bakeInput, lightmapRequests, lightProbeRequests, progress, wintermuteContext, integrationContext);\n                Debug.Assert(world is WintermuteWorld);\n                var wmWorld = world as WintermuteWorld;\n                wmWorld.SetIntegrationContext(integrationContext);\n            }\n            return result;\n        }\n\n        public static extern bool Serialize(string path, BakeInput input);\n        public static extern bool SerializeLightmapRequests(string path, LightmapRequests lightmapRequests);\n        public static extern bool SerializeLightProbeRequests(string path, LightProbeRequests lightProbeRequests);\n        public static extern bool Deserialize(string path, BakeInput input);\n        public static extern bool DeserializeLightmapRequests(string path, LightmapRequests lightmapRequests);\n        public static extern bool DeserializeLightProbeRequests(string path, LightProbeRequests lightProbeRequests);\n\n        public static extern Result Bake(BakeInput input, LightmapRequests lightmapRequest, LightProbeRequests lightProbeRequests, DeviceSettings deviceSettings);\n        public static extern Result BakeOutOfProcess(BakeInput input, LightmapRequests lightmapRequest, LightProbeRequests lightProbeRequests, DeviceSettings deviceSettings);\n        public static extern Result BakeInEditorWorkerProcess(BakeInput input, LightmapRequests lightmapRequest, LightProbeRequests lightProbeRequests, DeviceSettings deviceSettings);\n        public static extern bool ReportResultToParentProcess(Result result, ExternalProcessConnection connection);\n        [NativeMethod(IsThreadSafe = true)]\n        public static extern bool ReportProgressToParentProcess(float progress, ExternalProcessConnection connection);\n        public static extern ulong ConvertExpectedWorkToWorkSteps(BakeInput bakeInput, LightmapRequests lightmapRequests, LightProbeRequests lightProbeRequests, ulong sampleCountPerLightmapTexel, ulong sampleCountPerProbe);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/LightProbeVisualization.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngineInternal;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/LightProbeVisualization.h\")]\n    internal static partial class LightProbeVisualization\n    {\n        internal enum LightProbeVisualizationMode\n        {\n            OnlyProbesUsedBySelection = 0,\n            AllProbesNoCells = 1,\n            AllProbesWithCells = 2,\n            None = 3,\n        }\n\n        [StaticAccessor(\"GetLightProbeVisualizationSettings()\")]\n        public extern static LightProbeVisualizationMode lightProbeVisualizationMode { get; set; }\n\n        [StaticAccessor(\"GetLightProbeVisualizationSettings()\")]\n        public extern static bool showInterpolationWeights { get; set; }\n\n        [StaticAccessor(\"GetLightProbeVisualizationSettings()\")]\n        public extern static bool showOcclusions { get; set; }\n\n        [StaticAccessor(\"GetLightProbeVisualizationSettings()\")]\n        public extern static bool highlightInvalidCells { get; set; }\n\n        [StaticAccessor(\"GetLightProbeVisualizationSettings()\")]\n        public extern static bool dynamicUpdateLightProbes { get; set; }\n\n        [StaticAccessor(\"GetLightProbeVisualizationSettings()\")]\n        internal static extern void DrawPointCloud([NotNull] Vector3[] unselectedPositions, [NotNull] Vector3[] selectedPositions, Color baseColor, Color selectedColor, float scale, Transform cloudTransform);\n\n        [StaticAccessor(\"GetLightProbeVisualizationSettings()\")]\n        internal static extern void DrawTetrahedra(bool shouldRecalculateTetrahedra, Vector3 cameraPosition);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/LightingDataAsset.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Rendering;\nusing UnityEngine.SceneManagement;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/GI/Enlighten/LightingDataAsset.h\")]\n    [ExcludeFromPreset]\n    public sealed partial class LightingDataAsset : Object\n    {\n        private LightingDataAsset() {}\n\n        public LightingDataAsset(Scene scene)\n        {\n            Internal_Create(this, scene);\n        }\n\n        [NativeThrows]\n        private extern static void Internal_Create([Writable] LightingDataAsset self, Scene scene);\n\n        public extern void SetLights(Light[] lights);\n\n        public extern SphericalHarmonicsL2 GetAmbientProbe();\n        public extern void SetAmbientProbe(SphericalHarmonicsL2 probe);\n        public extern Texture GetDefaultReflectionCubemap();\n        public extern void SetDefaultReflectionCubemap(Texture cubemap);\n\n        internal extern bool isValid {[NativeName(\"IsValid\")] get; }\n\n        internal extern string validityErrorMessage { get; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/LightmapEditorSettings.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngineInternal;\nusing UnityEditor.SceneManagement;\nusing UnityEngine.Bindings;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    // Various settings for the bake.\n    [NativeHeader(\"Editor/Src/LightmapEditorSettings.h\")]\n    public static partial class LightmapEditorSettings\n    {\n        [Obsolete(\"LightmapEditorSettings.Lightmapper is obsolete. Use LightingSettings.Lightmapper instead. \", false)]\n        public enum Lightmapper\n        {\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use Lightmapper.ProgressiveCPU instead. (UnityUpgradable) -> UnityEditor.LightmapEditorSettings/Lightmapper.ProgressiveCPU\", true)]\n            Radiosity = 0,\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use Lightmapper.ProgressiveCPU instead. (UnityUpgradable) -> UnityEditor.LightmapEditorSettings/Lightmapper.ProgressiveCPU\", true)]\n            Enlighten = 0,\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use Lightmapper.ProgressiveCPU instead. (UnityUpgradable) -> UnityEditor.LightmapEditorSettings/Lightmapper.ProgressiveCPU\", true)]\n            PathTracer = 1,\n\n            // Lightmaps are baked by the CPU Progressive lightmapper (Wintermute + OpenRL based).\n            ProgressiveCPU = 1,\n\n            // Lightmaps are baked by the GPU Progressive lightmapper (RadeonRays + OpenCL based).\n            ProgressiveGPU = 2\n        }\n\n        [Obsolete(\"LightmapEditorSettings.Sampling is obsolete. Use LightingSettings.Sampling instead. \", false)]\n        public enum Sampling\n        {\n            Auto = 0,\n            Fixed = 1\n        }\n\n        [Obsolete(\"LightmapEditorSettings.FilterMode is obsolete. Use LightingSettings.FilterMode instead. \", false)]\n        public enum FilterMode\n        {\n            None = 0,\n            Auto = 1,\n            Advanced = 2\n        }\n\n        [Obsolete(\"LightmapEditorSettings.DenoiserType is obsolete. Use LightingSettings.DenoiserType instead. \", false)]\n        public enum DenoiserType\n        {\n            None = 0,\n            Optix = 1,\n            OpenImage = 2,\n\n            // The AMD Radeon Image Filter denoiser is not supported in 2023.2 and later.\n            RadeonPro = 3\n        }\n\n        [Obsolete(\"LightmapEditorSettings.FilterType is obsolete. Use LightingSettings.FilterType instead. \", false)]\n        public enum FilterType\n        {\n            Gaussian = 0,\n            ATrous = 1,\n            None = 2\n        }\n\n#pragma warning disable 0618\n        [Obsolete(\"LightmapEditorSettings.lightmapper is obsolete, use LightingSettings.lightmapper instead. \", false)]\n        public static Lightmapper lightmapper\n        {\n            get { return ConvertToOldLightmapperEnum(Lightmapping.GetLightingSettingsOrDefaultsFallback().lightmapper); }\n            set { Lightmapping.GetOrCreateLightingsSettings().lightmapper = ConvertToNewLightmapperEnum(value); }\n        }\n\n        private static Lightmapper ConvertToOldLightmapperEnum(LightingSettings.Lightmapper lightmapper)\n        {\n            switch (lightmapper)\n            {\n                case LightingSettings.Lightmapper.ProgressiveCPU:\n                    return Lightmapper.ProgressiveCPU;\n\n                case LightingSettings.Lightmapper.ProgressiveGPU:\n                    return Lightmapper.ProgressiveGPU;\n\n                default:\n                {\n                    Debug.LogError(\"Unsupported Lightmapper type was added and not handled correctly. \");\n                    return Lightmapper.ProgressiveCPU;\n                }\n            }\n        }\n\n        private static LightingSettings.Lightmapper ConvertToNewLightmapperEnum(Lightmapper lightmapper)\n        {\n            switch (lightmapper)\n            {\n                case Lightmapper.ProgressiveCPU:\n                    return LightingSettings.Lightmapper.ProgressiveCPU;\n\n                case Lightmapper.ProgressiveGPU:\n                    return LightingSettings.Lightmapper.ProgressiveGPU;\n\n                default:\n                {\n                    Debug.LogError(\"Unsupported Lightmapper type was added and not handled correctly. \");\n                    return LightingSettings.Lightmapper.ProgressiveCPU;\n                }\n            }\n        }\n\n#pragma warning restore 0618\n\n        [Obsolete(\"LightmapEditorSettings.lightmapsMode is obsolete, use LightingSettings.directionalityMode instead. \", false)]\n        public static LightmapsMode lightmapsMode\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().directionalityMode; }\n            set { Lightmapping.GetOrCreateLightingsSettings().directionalityMode = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.mixedBakeMode is obsolete, use LightingSettings.mixedBakeMode instead. \", false)]\n        public static MixedLightingMode mixedBakeMode\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().mixedBakeMode; }\n            set { Lightmapping.GetOrCreateLightingsSettings().mixedBakeMode = value; }\n        }\n\n#pragma warning disable 0618\n        [Obsolete(\"LightmapEditorSettings.sampling is obsolete, use LightingSettings.sampling instead. \", false)]\n        public static Sampling sampling\n        {\n            get { return ConvertToOldSamplingEnum(Lightmapping.GetLightingSettingsOrDefaultsFallback().sampling); }\n            set { Lightmapping.GetOrCreateLightingsSettings().sampling = ConvertToNewSamplingEnum(value); }\n        }\n\n        private static Sampling ConvertToOldSamplingEnum(LightingSettings.Sampling lightmapper)\n        {\n            switch (lightmapper)\n            {\n                case LightingSettings.Sampling.Auto:\n                    return Sampling.Auto;\n\n                case LightingSettings.Sampling.Fixed:\n                    return Sampling.Fixed;\n\n                default:\n                {\n                    Debug.LogError(\"Unsupported Sampling type was added and not handled correctly. \");\n                    return Sampling.Fixed;\n                }\n            }\n        }\n\n        private static LightingSettings.Sampling ConvertToNewSamplingEnum(Sampling lightmapper)\n        {\n            switch (lightmapper)\n            {\n                case Sampling.Auto:\n                    return LightingSettings.Sampling.Auto;\n\n                case Sampling.Fixed:\n                    return LightingSettings.Sampling.Fixed;\n\n                default:\n                {\n                    Debug.LogError(\"Unsupported Sampling type was added and not handled correctly. \");\n                    return LightingSettings.Sampling.Fixed;\n                }\n            }\n        }\n\n#pragma warning restore 0618\n\n        [Obsolete(\"LightmapEditorSettings.directSampleCount is obsolete, use LightingSettings.directSampleCount instead. \", false)]\n        public static int directSampleCount\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().directSampleCount; }\n            set { Lightmapping.GetOrCreateLightingsSettings().directSampleCount = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.indirectSampleCount is obsolete, use LightingSettings.indirectSampleCount instead. \", false)]\n        public static int indirectSampleCount\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().indirectSampleCount; }\n            set { Lightmapping.GetOrCreateLightingsSettings().indirectSampleCount = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.bounces is obsolete, use LightingSettings.maxBounces instead. \", false)]\n        public static int bounces\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().maxBounces; }\n            set { Lightmapping.GetOrCreateLightingsSettings().maxBounces = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.prioritizeView is obsolete, use LightingSettings.prioritizeView instead. \", false)]\n        public static bool prioritizeView\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().prioritizeView; }\n            set { Lightmapping.GetOrCreateLightingsSettings().prioritizeView = value; }\n        }\n\n#pragma warning disable 0618\n        [Obsolete(\"LightmapEditorSettings.filteringMode is obsolete, use LightingSettings.filteringMode instead. \", false)]\n        public static FilterMode filteringMode\n        {\n            get { return ConvertToOldFilteringModeEnum(Lightmapping.GetLightingSettingsOrDefaultsFallback().filteringMode); }\n            set { Lightmapping.GetOrCreateLightingsSettings().filteringMode = ConvertToNewFilteringModeEnum(value); }\n        }\n\n        private static FilterMode ConvertToOldFilteringModeEnum(LightingSettings.FilterMode filteringMode)\n        {\n            switch (filteringMode)\n            {\n                case LightingSettings.FilterMode.None:\n                    return FilterMode.None;\n\n                case LightingSettings.FilterMode.Auto:\n                    return FilterMode.Auto;\n\n                case LightingSettings.FilterMode.Advanced:\n                    return FilterMode.Advanced;\n\n                default:\n                {\n                    Debug.LogError(\"Unsupported FilterMode type was added and not handled correctly. \");\n                    return FilterMode.Advanced;\n                }\n            }\n        }\n\n        private static LightingSettings.FilterMode ConvertToNewFilteringModeEnum(FilterMode filteringMode)\n        {\n            switch (filteringMode)\n            {\n                case FilterMode.None:\n                    return LightingSettings.FilterMode.None;\n\n                case FilterMode.Auto:\n                    return LightingSettings.FilterMode.Auto;\n\n                case FilterMode.Advanced:\n                    return LightingSettings.FilterMode.Advanced;\n\n                default:\n                {\n                    Debug.LogError(\"Unsupported FilterMode type was added and not handled correctly. \");\n                    return LightingSettings.FilterMode.Advanced;\n                }\n            }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.denoiserTypeDirect is obsolete, use LightingSettings.denoiserTypeDirect instead. \", false)]\n        public static DenoiserType denoiserTypeDirect\n        {\n            get { return ConvertToOldDenoiserTypeEnum(Lightmapping.GetLightingSettingsOrDefaultsFallback().denoiserTypeDirect); }\n            set { Lightmapping.GetOrCreateLightingsSettings().denoiserTypeDirect = ConvertToNewDenoiserTypeEnum(value); }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.denoiserTypeIndirect is obsolete, use LightingSettings.denoiserTypeIndirect instead. \", false)]\n        public static DenoiserType denoiserTypeIndirect\n        {\n            get { return ConvertToOldDenoiserTypeEnum(Lightmapping.GetLightingSettingsOrDefaultsFallback().denoiserTypeIndirect); }\n            set { Lightmapping.GetOrCreateLightingsSettings().denoiserTypeIndirect = ConvertToNewDenoiserTypeEnum(value); }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.denoiserTypeAO is obsolete, use LightingSettings.denoiserTypeAO instead. \", false)]\n        public static DenoiserType denoiserTypeAO\n        {\n            get { return ConvertToOldDenoiserTypeEnum(Lightmapping.GetLightingSettingsOrDefaultsFallback().denoiserTypeAO); }\n            set { Lightmapping.GetOrCreateLightingsSettings().denoiserTypeAO = ConvertToNewDenoiserTypeEnum(value); }\n        }\n\n        private static DenoiserType ConvertToOldDenoiserTypeEnum(LightingSettings.DenoiserType denoiserType)\n        {\n            switch (denoiserType)\n            {\n                case LightingSettings.DenoiserType.None:\n                    return DenoiserType.None;\n\n                case LightingSettings.DenoiserType.Optix:\n                    return DenoiserType.Optix;\n\n                case LightingSettings.DenoiserType.OpenImage:\n                    return DenoiserType.OpenImage;\n\n                default:\n                {\n                    Debug.LogError(\"Unsupported DenoiserType type was added and not handled correctly. \");\n                    return DenoiserType.None;\n                }\n            }\n        }\n\n        private static LightingSettings.DenoiserType ConvertToNewDenoiserTypeEnum(DenoiserType denoiserType)\n        {\n            switch (denoiserType)\n            {\n                case DenoiserType.None:\n                    return LightingSettings.DenoiserType.None;\n\n                case DenoiserType.Optix:\n                    return LightingSettings.DenoiserType.Optix;\n\n                case DenoiserType.OpenImage:\n                    return LightingSettings.DenoiserType.OpenImage;\n\n                default:\n                {\n                    Debug.LogError(\"Unsupported DenoiserType type was added and not handled correctly. \");\n                    return LightingSettings.DenoiserType.None;\n                }\n            }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.filterTypeDirect is obsolete, use LightingSettings.filterTypeDirect instead. \", false)]\n        public static FilterType filterTypeDirect\n        {\n            get {  return ConvertToOldFilterTypeEnum(Lightmapping.GetLightingSettingsOrDefaultsFallback().filterTypeDirect); }\n            set { Lightmapping.GetOrCreateLightingsSettings().filterTypeDirect = ConvertToNewFilterTypeEnum(value); }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.filterTypeIndirect is obsolete, use LightingSettings.filterTypeIndirect instead. \", false)]\n        public static FilterType filterTypeIndirect\n        {\n            get { return ConvertToOldFilterTypeEnum(Lightmapping.GetLightingSettingsOrDefaultsFallback().filterTypeIndirect); }\n            set { Lightmapping.GetOrCreateLightingsSettings().filterTypeIndirect = ConvertToNewFilterTypeEnum(value); }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.filterTypeAO is obsolete, use LightingSettings.filterTypeAO instead. \", false)]\n        public static FilterType filterTypeAO\n        {\n            get { return ConvertToOldFilterTypeEnum(Lightmapping.GetLightingSettingsOrDefaultsFallback().filterTypeAO); }\n            set { Lightmapping.GetOrCreateLightingsSettings().filterTypeAO = ConvertToNewFilterTypeEnum(value); }\n        }\n\n        private static FilterType ConvertToOldFilterTypeEnum(LightingSettings.FilterType filterType)\n        {\n            switch (filterType)\n            {\n                case LightingSettings.FilterType.Gaussian:\n                    return FilterType.Gaussian;\n\n                case LightingSettings.FilterType.ATrous:\n                    return FilterType.ATrous;\n\n                case LightingSettings.FilterType.None:\n                    return FilterType.None;\n\n                default:\n                {\n                    Debug.LogError(\"Unsupported FilterType type was added and not handled correctly. \");\n                    return FilterType.None;\n                }\n            }\n        }\n\n        private static LightingSettings.FilterType ConvertToNewFilterTypeEnum(FilterType filterType)\n        {\n            switch (filterType)\n            {\n                case FilterType.Gaussian:\n                    return LightingSettings.FilterType.Gaussian;\n\n                case FilterType.ATrous:\n                    return LightingSettings.FilterType.ATrous;\n\n                case FilterType.None:\n                    return LightingSettings.FilterType.None;\n\n                default:\n                {\n                    Debug.LogError(\"Unsupported FilterType type was added and not handled correctly. \");\n                    return LightingSettings.FilterType.None;\n                }\n            }\n        }\n\n#pragma warning restore 0618\n\n        [Obsolete(\"LightmapEditorSettings.filteringGaussRadiusDirect is obsolete, use LightingSettings.filteringGaussianRadiusDirect instead. \", false)]\n        public static int filteringGaussRadiusDirect\n        {\n            get { return (int)Lightmapping.GetLightingSettingsOrDefaultsFallback().filteringGaussianRadiusDirect; }\n            set { Lightmapping.GetOrCreateLightingsSettings().filteringGaussianRadiusDirect = (float)value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.filteringGaussRadiusIndirect is obsolete, use LightingSettings.filteringGaussianRadiusIndirect instead. \", false)]\n        public static int filteringGaussRadiusIndirect\n        {\n            get { return (int)Lightmapping.GetLightingSettingsOrDefaultsFallback().filteringGaussianRadiusIndirect; }\n            set { Lightmapping.GetOrCreateLightingsSettings().filteringGaussianRadiusIndirect = (float)value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.filteringGaussRadiusAO is obsolete, use LightingSettings.filteringGaussianRadiusAO instead. \", false)]\n        public static int filteringGaussRadiusAO\n        {\n            get { return (int)Lightmapping.GetLightingSettingsOrDefaultsFallback().filteringGaussianRadiusAO; }\n            set { Lightmapping.GetOrCreateLightingsSettings().filteringGaussianRadiusAO = (float)value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.filteringAtrousPositionSigmaDirect is obsolete, use LightingSettings.filteringAtrousPositionSigmaDirect instead. \", false)]\n        public static float filteringAtrousPositionSigmaDirect\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().filteringAtrousPositionSigmaDirect; }\n            set { Lightmapping.GetOrCreateLightingsSettings().filteringAtrousPositionSigmaDirect = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.filteringAtrousPositionSigmaIndirect is obsolete, use LightingSettings.filteringAtrousPositionSigmaIndirect instead. \", false)]\n        public static float filteringAtrousPositionSigmaIndirect\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().filteringAtrousPositionSigmaIndirect; }\n            set { Lightmapping.GetOrCreateLightingsSettings().filteringAtrousPositionSigmaIndirect = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.filteringAtrousPositionSigmaIndirect is obsolete, use LightingSettings.filteringAtrousPositionSigmaIndirect instead. \", false)]\n        public static float filteringAtrousPositionSigmaAO\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().filteringAtrousPositionSigmaIndirect; }\n            set { Lightmapping.GetOrCreateLightingsSettings().filteringAtrousPositionSigmaIndirect = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.environmentMIS is obsolete, use LightingSettings.environmentImportanceSampling instead. \", false)]\n        internal static int environmentMIS\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().environmentImportanceSampling ? 1 : 0; }\n            set { Lightmapping.GetOrCreateLightingsSettings().environmentImportanceSampling = value != 0; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.environmentSampleCount is obsolete, use LightingSettings.environmentSampleCount instead. \", false)]\n        public static int environmentSampleCount\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().environmentSampleCount; }\n            set { Lightmapping.GetOrCreateLightingsSettings().environmentSampleCount = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.environmentReferencePointCount is obsolete, use LightingSettings.environmentReferencePointCount instead. \", false)]\n        internal static int environmentReferencePointCount\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().environmentReferencePointCount; }\n            set { Lightmapping.GetOrCreateLightingsSettings().environmentReferencePointCount = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.lightProbeSampleCountMultiplier is obsolete, use LightingSettings.lightProbeSampleCountMultiplier instead. \", false)]\n        internal static float lightProbeSampleCountMultiplier\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().lightProbeSampleCountMultiplier; }\n            set { Lightmapping.GetOrCreateLightingsSettings().lightProbeSampleCountMultiplier = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.maxAtlasSize is obsolete, use LightingSettings.lightmapMaxSize instead. \", false)]\n        public static int maxAtlasSize\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().lightmapMaxSize; }\n            set { Lightmapping.GetOrCreateLightingsSettings().lightmapMaxSize = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.realtimeResolution is obsolete, use LightingSettings.indirectResolution instead. \", false)]\n        public static float realtimeResolution\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().indirectResolution; }\n            set { Lightmapping.GetOrCreateLightingsSettings().indirectResolution = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.bakeResolution is obsolete, use LightingSettings.lightmapResolution instead. \", false)]\n        public static float bakeResolution\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().lightmapResolution; }\n            set { Lightmapping.GetOrCreateLightingsSettings().lightmapResolution = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.textureCompression is obsolete, use LightingSettings.compressLightmaps instead. \", false)]\n        public static bool textureCompression\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().compressLightmaps; }\n            set { Lightmapping.GetOrCreateLightingsSettings().compressLightmaps = value; }\n        }\n\n        [StaticAccessor(\"GetLightmapEditorSettings()\")]\n        [NativeName(\"ReflectionCompression\")]\n        public extern static ReflectionCubemapCompression reflectionCubemapCompression { get; set; }\n\n        [Obsolete(\"LightmapEditorSettings.enableAmbientOcclusion is obsolete, use LightingSettings.ao instead. \", false)]\n        public static bool enableAmbientOcclusion\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().ao; }\n            set { Lightmapping.GetOrCreateLightingsSettings().ao = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.aoMaxDistance is obsolete, use LightingSettings.aoMaxDistance instead. \", false)]\n        public static float aoMaxDistance\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().aoMaxDistance; }\n            set { Lightmapping.GetOrCreateLightingsSettings().aoMaxDistance = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.aoExponentIndirect is obsolete, use LightingSettings.aoExponentIndirect instead. \", false)]\n        public static float aoExponentIndirect\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().aoExponentIndirect; }\n            set { Lightmapping.GetOrCreateLightingsSettings().aoExponentIndirect = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.aoExponentDirect is obsolete, use LightingSettings.aoExponentDirect instead. \", false)]\n        public static float aoExponentDirect\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().aoExponentDirect; }\n            set { Lightmapping.GetOrCreateLightingsSettings().aoExponentDirect = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.padding is obsolete, use LightingSettings.lightmapPadding instead. \", false)]\n        public static int padding\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().lightmapPadding; }\n            set { Lightmapping.GetOrCreateLightingsSettings().lightmapPadding = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.exportTrainingData is obsolete, use LightingSettings.exportTrainingData instead. \", false)]\n        public static bool exportTrainingData\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().exportTrainingData; }\n            set { Lightmapping.GetOrCreateLightingsSettings().exportTrainingData = value; }\n        }\n\n        [Obsolete(\"LightmapEditorSettings.trainingDataDestination is obsolete, use LightingSettings.trainingDataDestination instead. \", false)]\n        public static string trainingDataDestination\n        {\n            get { return Lightmapping.GetLightingSettingsOrDefaultsFallback().trainingDataDestination; }\n            set { Lightmapping.GetOrCreateLightingsSettings().trainingDataDestination = value; }\n        }\n\n        [FreeFunction]\n        [NativeHeader(\"Runtime/Graphics/LightmapSettings.h\")]\n        extern internal static UnityEngine.Object GetLightmapSettings();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/LightmapEditorSettingsDeprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngineInternal;\n\nnamespace UnityEditor\n{\n    [System.Obsolete(\"LightmapBakeQuality has been deprecated.\", false)]\n    public enum LightmapBakeQuality\n    {\n        High = 0,\n        Low = 1,\n    }\n\n    public partial class LightmapEditorSettings\n    {\n        [System.Obsolete(\"LightmapEditorSettings.aoContrast has been deprecated.\", false)]\n        public static float aoContrast\n        {\n            get { return 0; }\n            set {}\n        }\n        [System.Obsolete(\"LightmapEditorSettings.aoAmount has been deprecated.\", false)]\n        public static float aoAmount\n        {\n            get { return 0; }\n            set {}\n        }\n        [System.Obsolete(\"LightmapEditorSettings.lockAtlas has been deprecated.\", false)]\n        public static bool lockAtlas\n        {\n            get { return false; }\n            set {}\n        }\n        [System.Obsolete(\"LightmapEditorSettings.skyLightColor has been deprecated.\", false)]\n        public static Color skyLightColor\n        {\n            get { return Color.black; }\n            set {}\n        }\n        [System.Obsolete(\"LightmapEditorSettings.skyLightIntensity has been deprecated.\", false)]\n        public static float skyLightIntensity\n        {\n            get { return 0; }\n            set {}\n        }\n        [System.Obsolete(\"LightmapEditorSettings.quality has been deprecated.\", false)]\n        public static LightmapBakeQuality quality\n        {\n            get { return 0; }\n            set {}\n        }\n        [System.Obsolete(\"LightmapEditorSettings.bounceBoost has been deprecated.\", false)]\n        public static float bounceBoost\n        {\n            get { return 0; }\n            set {}\n        }\n        [System.Obsolete(\"LightmapEditorSettings.finalGatherRays has been deprecated.\", false)]\n        public static int finalGatherRays\n        {\n            get { return 0; }\n            set {}\n        }\n        [System.Obsolete(\"LightmapEditorSettings.finalGatherContrastThreshold has been deprecated.\", false)]\n        public static float finalGatherContrastThreshold\n        {\n            get { return 0; }\n            set {}\n        }\n        [System.Obsolete(\"LightmapEditorSettings.finalGatherGradientThreshold has been deprecated.\", false)]\n        public static float finalGatherGradientThreshold\n        {\n            get { return 0; }\n            set {}\n        }\n        [System.Obsolete(\"LightmapEditorSettings.finalGatherInterpolationPoints has been deprecated.\", false)]\n        public static int finalGatherInterpolationPoints\n        {\n            get { return 0; }\n            set {}\n        }\n        [System.Obsolete(\"LightmapEditorSettings.lastUsedResolution has been deprecated.\", false)]\n        public static float lastUsedResolution\n        {\n            get { return 0; }\n            set {}\n        }\n        [System.Obsolete(\"LightmapEditorSettings.bounceIntensity has been deprecated.\", false)]\n        public static float bounceIntensity\n        {\n            get { return 0; }\n            set {}\n        }\n        [System.Obsolete(\"resolution is now called realtimeResolution (UnityUpgradable) -> realtimeResolution\", false)]\n        public static float resolution\n        {\n            get { return realtimeResolution; }\n            set { realtimeResolution = value; }\n        }\n        [System.Obsolete(\"GIBakeBackend has been renamed to Lightmapper. (UnityUpgradable)\", true)]\n        public enum GIBakeBackend\n        {\n            Radiosity = 0,\n            PathTracer = 1\n        }\n        [System.Obsolete(\"The giBakeBackend property has been renamed to lightmapper. (UnityUpgradable) -> lightmapper\", false)]\n        public static GIBakeBackend giBakeBackend\n        {\n            get\n            {\n                if (lightmapper == Lightmapper.ProgressiveCPU)\n                    return GIBakeBackend.PathTracer;\n                else\n                    return GIBakeBackend.Radiosity;\n            }\n            set\n            {\n                if (value == GIBakeBackend.PathTracer)\n                    lightmapper = Lightmapper.ProgressiveCPU;\n                else\n                    lightmapper = Lightmapper.Enlighten;\n            }\n        }\n        [System.Obsolete(\"PathTracerSampling has been renamed to Sampling. (UnityUpgradable) -> UnityEditor.LightmapEditorSettings/Sampling\", false)]\n        public enum PathTracerSampling\n        {\n            Auto = 0,\n            Fixed = 1\n        }\n        [System.Obsolete(\"The giPathTracerSampling property has been renamed to sampling. (UnityUpgradable) -> sampling\", false)]\n        public static PathTracerSampling giPathTracerSampling\n        {\n            get\n            {\n                if (sampling == Sampling.Auto)\n                    return PathTracerSampling.Auto;\n                else\n                    return PathTracerSampling.Fixed;\n            }\n            set\n            {\n                if (value == PathTracerSampling.Auto)\n                    sampling = Sampling.Auto;\n                else\n                    sampling = Sampling.Fixed;\n            }\n        }\n        [System.Obsolete(\"PathTracerFilter has been renamed to FilterType. (UnityUpgradable) -> UnityEditor.LightmapEditorSettings/FilterType\", false)]\n        public enum PathTracerFilter\n        {\n            Gaussian = 0,\n            ATrous = 1\n        }\n        [System.Obsolete(\"The giPathTracerFilter property has been deprecated. There are three independent properties to set individual filter types for direct, indirect and AO GI textures: filterTypeDirect, filterTypeIndirect and filterTypeAO.\")]\n        public static PathTracerFilter giPathTracerFilter\n        {\n            get\n            {\n                if (LightmapEditorSettings.filterTypeDirect == FilterType.Gaussian)\n                    return PathTracerFilter.Gaussian;\n                else\n                    return PathTracerFilter.ATrous;\n            }\n            set\n            {\n                LightmapEditorSettings.filterTypeDirect = FilterType.Gaussian;\n                LightmapEditorSettings.filterTypeIndirect = FilterType.Gaussian;\n                LightmapEditorSettings.filterTypeAO = FilterType.Gaussian;\n            }\n        }\n\n        [System.Obsolete(\"LightmapEditorSettings.maxAtlasWidth is now called maxAtlasSize (UnityUpgradable) -> maxAtlasSize\", false)]\n        public static int maxAtlasWidth\n        {\n            get { return maxAtlasSize; }\n            set { maxAtlasSize = value; }\n        }\n\n        private static int m_MaxAtlasHeight = 1024;\n\n        [System.Obsolete(\"LightmapEditorSettings.maxAtlasHeight has been deprecated. Only square atlases are supported, please use the maxAtlasSize instead. \")]\n        public static int maxAtlasHeight\n        {\n            get { return m_MaxAtlasHeight; }\n            set { m_MaxAtlasHeight = value; }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/LightmapParameters.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/GI/Enlighten/LightmapParameters.h\")]\n    [PreventReadOnlyInstanceModificationAttribute]\n    public sealed partial class LightmapParameters : UnityEngine.Object\n    {\n        public LightmapParameters()\n        {\n            Internal_Create(this);\n        }\n\n        [FreeFunction(\"LightmapParametersBindings::Internal_Create\")]\n        private extern static void Internal_Create([UnityEngine.Writable] LightmapParameters self);\n\n        public extern static LightmapParameters GetLightmapParametersForLightingSettings(UnityEngine.LightingSettings lightingSettings);\n        public extern static void SetLightmapParametersForLightingSettings(LightmapParameters parameters, UnityEngine.LightingSettings lightingSettings);\n\n        public void AssignToLightingSettings(UnityEngine.LightingSettings lightingSettings)\n        {\n            SetLightmapParametersForLightingSettings(this, lightingSettings);\n        }\n\n        // Realtime GI\n        public extern float resolution { get; set; }\n        public extern float clusterResolution { get; set; }\n        public extern int irradianceBudget { get; set; }\n        public extern int irradianceQuality { get; set; }\n        public extern float modellingTolerance { get; set; }\n\n        [NativeName(\"EdgeStitching\")]\n        public extern bool stitchEdges { get; set; }\n        public extern bool isTransparent { get; set; }\n        public extern int systemTag { get; set; }\n\n        // Baked GI\n        public extern int blurRadius { get; set; }\n        public extern int antiAliasingSamples { get; set; }\n        public extern int directLightQuality { get; set; }\n        public extern float pushoff { get; set; }\n        public extern int bakedLightmapTag { get; set; }\n        public extern bool limitLightmapCount { get; set; }\n        public extern int maxLightmapCount { get; set; }\n\n        // Baked ao\n        public extern int AOQuality { get; set; }\n        public extern int AOAntiAliasingSamples { get; set; }\n\n        // General GI\n        public extern float backFaceTolerance { get; set; }\n\n        [Obsolete(\"edgeStitching has been deprecated. Use stitchEdges instead\")]\n        public float edgeStitching\n        {\n            get { return stitchEdges ? 1.0f : 0.0f; }\n            set { stitchEdges = (value != 0.0f); }\n        }\n\n        [NativeHeader(\"Runtime/Graphics/LightmapEnums.h\")]\n        public enum AntiAliasingSamples\n        {\n            SSAA1 = 1,\n            SSAA4 = 2,\n            SSAA16 = 4,\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/LightmapSnapshot.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n\nnamespace UnityEditor\n{\n    //Originally class was defined in Lightmapping.bindings\n    [System.Obsolete(\"LightmapSnapshot has been deprecated. Use LightingDataAsset instead (UnityUpgradable) -> LightingDataAsset\", true)]\n    [UnityEngine.NativeClass(null)]\n    public class LightmapSnapshot : UnityEngine.Object // No **partial** needed since it is a **type** rename\n    {\n        //Original class had no public members\n    }\n}\n\n"
  },
  {
    "path": "Editor/Mono/GI/LightmapVisualization.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing GITextureType = UnityEngineInternal.GITextureType;\nusing LightmapType = UnityEngineInternal.LightmapType;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/GI/Enlighten/Visualisers/VisualisationManager.h\")]\n    internal enum GITextureAvailability\n    {\n        GITextureUnknown = 0,\n        GITextureNotAvailable = 1,\n        GITextureLoading = 2,\n        GITextureAvailable = 3,\n        GITextureAvailabilityCount = 4\n    }\n\n    [NativeHeader(\"Editor/Src/GI/Enlighten/Visualisers/VisualisationManager.h\")]\n    internal struct VisualisationGITexture\n    {\n        [NativeName(\"m_Type\")]\n        public GITextureType type;\n        [NativeName(\"m_Availability\")]\n        public GITextureAvailability textureAvailability;\n        [NativeName(\"m_Texture\")]\n        public Texture2D texture;\n        [NativeName(\"m_Hash\")]\n        public Hash128 hash;\n        [NativeName(\"m_ContentsHash\")]\n        public Hash128 contentHash;\n    }\n\n    internal sealed partial class LightmapVisualization\n    {\n        [NativeHeader(\"Editor/Src/EditorSettings.h\")]\n        [StaticAccessor(\"GetEditorSettings()\", StaticAccessorType.Dot)]\n        [NativeName(\"ShowLightmapResolutionOverlay\")]\n        public   static extern bool  showResolution { get; set; }\n\n        [NativeHeader(\"Editor/Src/Lightmapping.h\")]\n        [FreeFunction]\n        [NativeName(\"GetLightmapLODLevelScale_Internal\")]\n        internal extern static float GetLightmapLODLevelScale(UnityEngine.Renderer renderer);\n    }\n\n    internal sealed partial class LightmapVisualizationUtility\n    {\n        static readonly PrefColor kUVColor = new PrefColor(\"Lightmap Preview/UV Color\", 51f / 255f, 111f / 255f, 244f / 255f, 1f);\n        static readonly PrefColor kSelectedUVColor = new PrefColor(\"Lightmap Preview/Selected UV Color\", 250f / 255f, 250f / 255f, 0f, 1f);\n\n        [StaticAccessor(\"VisualisationManager::Get()\", StaticAccessorType.Arrow)]\n        internal extern static bool IsTextureTypeEnabled(GITextureType textureType);\n\n        [StaticAccessor(\"VisualisationManager::Get()\", StaticAccessorType.Arrow)]\n        internal extern static bool IsBakedTextureType(GITextureType textureType);\n\n        [StaticAccessor(\"VisualisationManager::Get()\", StaticAccessorType.Arrow)]\n        internal extern static bool IsAtlasTextureType(GITextureType textureType);\n\n        [StaticAccessor(\"VisualisationManager::Get()\", StaticAccessorType.Arrow)]\n        public   extern static VisualisationGITexture[] GetRealtimeGITextures(GITextureType textureType);\n\n        [StaticAccessor(\"VisualisationManager::Get()\", StaticAccessorType.Arrow)]\n        public   extern static VisualisationGITexture GetRealtimeGITexture(Hash128 inputSystemHash, GITextureType textureType);\n\n        [StaticAccessor(\"VisualisationManager::Get()\", StaticAccessorType.Arrow)]\n        public   extern static VisualisationGITexture GetBakedGITexture(int lightmapIndex, int instanceId, GITextureType textureType, bool useInteractiveLightBakingData);\n\n        [StaticAccessor(\"VisualisationManager::Get()\", StaticAccessorType.Arrow)]\n        public   extern static VisualisationGITexture GetSelectedObjectGITexture(GITextureType textureType);\n\n        [StaticAccessor(\"VisualisationManager::Get()\", StaticAccessorType.Arrow)]\n        public   extern static Hash128 GetBakedGITextureHash(int lightmapIndex, int instanceId, GITextureType textureType, bool useInteractiveLightBakingData);\n\n        [StaticAccessor(\"VisualisationManager::Get()\", StaticAccessorType.Arrow)]\n        public   extern static Hash128 GetRealtimeGITextureHash(Hash128 inputSystemHash, GITextureType textureType);\n\n        [StaticAccessor(\"VisualisationManager::Get()\", StaticAccessorType.Arrow)]\n        public   extern static Hash128 GetSelectedObjectGITextureHash(GITextureType textureType);\n\n        [StaticAccessor(\"VisualisationManager::Get()\", StaticAccessorType.Arrow)]\n        public   extern static GameObject[] GetRealtimeGITextureRenderers(Hash128 inputSystemHash);\n\n        [StaticAccessor(\"VisualisationManager::Get()\", StaticAccessorType.Arrow)]\n        public   extern static GameObject[] GetBakedGITextureRenderers(int lightmapIndex, bool useInteractiveLightBakingData);\n\n        [NativeHeader(\"Runtime/GI/RenderOverlay.h\")]\n        [FreeFunction(\"DrawTextureWithUVOverlay\")]\n        public extern static void DrawTextureWithUVOverlay(Texture2D texture, GameObject selectedGameObject, GameObject[] gameObjects, Rect drawableArea, Rect position, GITextureType textureType, Color uvColor, Color selectedUVColor, float exposure, bool useInteractiveLightBakingData);\n\n        public static void DrawTextureWithUVOverlay(Texture2D texture, GameObject selectedGameObject, GameObject[] gameObjects, Rect drawableArea, Rect position, GITextureType textureType, float exposure, bool useInteractiveLightBakingData)\n        {\n            DrawTextureWithUVOverlay(texture, selectedGameObject, gameObjects, drawableArea, position, textureType, kUVColor, kSelectedUVColor, exposure, useInteractiveLightBakingData);\n        }\n\n        [StaticAccessor(\"VisualisationManager::Get()\", StaticAccessorType.Arrow)]\n        public   extern static LightmapType GetLightmapType(GITextureType textureType);\n\n        [StaticAccessor(\"VisualisationManager::Get()\", StaticAccessorType.Arrow)]\n        [NativeName(\"GetLightmapST\")]\n        public   extern static Vector4 GetLightmapTilingOffset(LightmapType lightmapType);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/Lightmapping.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing UnityEditor.SceneManagement;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing System.Runtime.InteropServices;\nusing Scene = UnityEngine.SceneManagement.Scene;\nusing NativeArrayUnsafeUtility = Unity.Collections.LowLevel.Unsafe.NativeArrayUnsafeUtility;\nusing Unity.Collections;\nusing UnityEditor.LightBaking;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    [UsedByNativeCode]\n    [NativeHeader(\"Editor/Src/GI/Progressive/PVRData.h\")]\n    internal struct LightmapSize\n    {\n        [NativeName(\"m_Width\")]  public int width;\n        [NativeName(\"m_Height\")] public int height;\n    }\n\n    [UsedByNativeCode]\n    [NativeHeader(\"Editor/Src/GI/Progressive/PVRData.h\")]\n    internal struct RunningBakeInfo\n    {\n        [NativeName(\"m_LightmapSizes\")]  public LightmapSize[] lightmapSizes;\n        [NativeName(\"m_ProbePositions\")] public UInt64 probePositions;\n    }\n\n    [UsedByNativeCode]\n    [NativeHeader(\"Editor/Src/GI/Progressive/PVRData.h\")]\n    internal struct LightmapMemory\n    {\n        [NativeName(\"m_LightmapDataSizeCPU\")]   public float lightmapDataSizeCPU;\n        [NativeName(\"m_LightmapTexturesSize\")]  public float lightmapTexturesSize;\n        [NativeName(\"m_LightmapDataSizeGPU\")]   public float lightmapDataSizeGPU;\n    }\n\n    internal struct MemLabels\n    {\n        public string[] labels;\n        public float[] sizes;\n    }\n\n    internal struct GeoMemLabels\n    {\n        public string[] labels;\n        public float[] sizes;\n        public UInt64[] triCounts;\n    }\n\n    internal struct TetrahedralizationData\n    {\n        public int[] indices;\n        public Vector3[] positions;\n    }\n\n    [NativeHeader(\"Editor/Src/GI/Progressive/BakeContextManager.h\")]\n    internal struct EnvironmentSamplesData\n    {\n        public Vector4[] directions;\n        public Vector4[] intensities;\n    }\n\n    [NativeHeader(\"Editor/Src/GI/Progressive/PVRHelpers.h\")]\n    internal struct DeviceAndPlatform\n    {\n        public int deviceId;\n        public int platformId;\n        public string name;\n    };\n\n    [NativeHeader(\"Editor/Mono/GI/Lightmapping.bindings.h\")]\n    public static partial class Lightmapping\n    {\n        [NativeHeader(\"Editor/Src/JobManager/QueueJobTypes.h\")]\n        internal enum ConcurrentJobsType\n        {\n            Min = 0,\n            Low = 1,\n            High = 2,\n        }\n\n        [NativeHeader(\"Runtime/Graphics/LightmapEnums.h\")]\n        public enum GIWorkflowMode\n        {\n            // Data is automatically precomputed for dynamic and static GI.\n            Iterative = 0,\n\n            // Data is only precomputed for dynamic and static GI when the bake button is pressed.\n            OnDemand = 1,\n\n            // Lightmaps are calculated in the same way as in Unity 4.x.\n            Legacy = 2\n        }\n\n        [NativeHeader(\"Runtime/Graphics/LightmapSettings.h\")]\n        public enum BakeOnSceneLoadMode\n        {\n            Never = 0,\n            IfMissingLightingData = 1,\n        };\n\n        // Obsolete, please use Actions instead\n        public delegate void OnStartedFunction();\n        public delegate void OnCompletedFunction();\n\n        [Obsolete(\"Lightmapping.giWorkflowMode is obsolete.\", false)]\n        public static GIWorkflowMode giWorkflowMode\n        {\n            get => GIWorkflowMode.OnDemand;\n            set { }\n        }\n\n//        [Obsolete(\"Lightmapping.realtimeGI is obsolete, use LightingSettings.realtimeGI instead. \", false)]\n        public static bool realtimeGI\n        {\n            get { return GetLightingSettingsOrDefaultsFallback().realtimeGI; }\n            set { GetOrCreateLightingsSettings().realtimeGI = value; }\n        }\n\n//        [Obsolete(\"Lightmapping.bakedGI is obsolete, use LightingSettings.bakedGI instead. \", false)]\n        public static bool bakedGI\n        {\n            get { return GetLightingSettingsOrDefaultsFallback().bakedGI; }\n            set { GetOrCreateLightingsSettings().bakedGI = value; }\n        }\n\n        [Obsolete(\"Lightmapping.indirectOutputScale is obsolete, use LightingSettings.indirectScale instead. \", false)]\n        public static float indirectOutputScale\n        {\n            get { return GetLightingSettingsOrDefaultsFallback().indirectScale; }\n            set { GetOrCreateLightingsSettings().indirectScale = value; }\n        }\n\n        [Obsolete(\"Lightmapping.bounceBoost is obsolete, use LightingSettings.albedoBoost instead. \", false)]\n        public static float bounceBoost\n        {\n            get { return GetLightingSettingsOrDefaultsFallback().albedoBoost; }\n            set { GetOrCreateLightingsSettings().albedoBoost = value; }\n        }\n\n        [RequiredByNativeCode]\n        internal static bool ShouldBakeInteractively()\n        {\n            return SceneView.NeedsInteractiveBaking();\n        }\n\n        internal static bool shouldBakeInteractively\n        {\n            get { return ShouldBakeInteractively(); }\n        }\n\n        [RequiredByNativeCode]\n        internal static void KickSceneViewsOutOfInteractiveMode()\n        {\n            foreach (SceneView sv in SceneView.sceneViews)\n                sv.debugDrawModesUseInteractiveLightBakingData = false;\n        }\n\n        // Set concurrent jobs type. Warning, high priority can impact Editor performance\n        [StaticAccessor(\"EnlightenPrecompManager::Get()\", StaticAccessorType.Arrow)]\n        internal static extern ConcurrentJobsType concurrentJobsType { get; set; }\n\n        // Clears disk cache and recreates cache directories.\n        [StaticAccessor(\"GICache\", StaticAccessorType.DoubleColon)]\n        public static extern void ClearDiskCache();\n\n        // Updates cache path from Editor preferences.\n        [StaticAccessor(\"GICache\", StaticAccessorType.DoubleColon)]\n        internal static extern void UpdateCachePath();\n\n        // Get the disk cache size in Mb.\n        [StaticAccessor(\"GICache\", StaticAccessorType.DoubleColon)]\n        [NativeName(\"LastKnownCacheSize\")]\n        internal static extern long diskCacheSize { get; }\n\n        // Get the disk cache path.\n        [StaticAccessor(\"GICache\", StaticAccessorType.DoubleColon)]\n        [NativeName(\"CachePath\")]\n        internal static extern string diskCachePath { get; }\n\n        [Obsolete(\"Lightmapping.enlightenForceWhiteAlbedo is obsolete, use LightingSettings.realtimeForceWhiteAlbedo instead. \", false)]\n        internal static bool enlightenForceWhiteAlbedo\n        {\n            get { return GetLightingSettingsOrDefaultsFallback().realtimeForceWhiteAlbedo; }\n            set { GetOrCreateLightingsSettings().realtimeForceWhiteAlbedo = value; }\n        }\n\n        [Obsolete(\"Lightmapping.enlightenForceUpdates is obsolete, use LightingSettings.realtimeForceUpdates instead. \", false)]\n        internal static bool enlightenForceUpdates\n        {\n            get { return GetLightingSettingsOrDefaultsFallback().realtimeForceUpdates; }\n            set { GetOrCreateLightingsSettings().realtimeForceUpdates = value; }\n        }\n\n        [Obsolete(\"Lightmapping.filterMode is obsolete, use LightingSettings.lightmapFilterMode instead. \", false)]\n        internal static FilterMode filterMode\n        {\n            get { return GetLightingSettingsOrDefaultsFallback().lightmapFilterMode; }\n            set { GetOrCreateLightingsSettings().lightmapFilterMode = value; }\n        }\n\n        [StaticAccessor(\"BakedGISceneManager::Get()\", StaticAccessorType.Arrow)]\n        internal static extern bool isProgressiveLightmapperDone {[NativeName(\"IsBakedGIDone\")] get; }\n\n        [StaticAccessor(\"BakedGISceneManager::Get()\", StaticAccessorType.Arrow)]\n        internal static extern RunningBakeInfo GetRunningBakeInfo();\n\n        [StaticAccessor(\"BakedGISceneManager::Get()\", StaticAccessorType.Arrow)]\n        internal static extern float ComputeTotalGPUMemoryUsageInBytes();\n\n        [StaticAccessor(\"BakedGISceneManager::Get()\", StaticAccessorType.Arrow)]\n        internal static extern void LogGPUMemoryStatistics();\n\n        [StaticAccessor(\"BakedGISceneManager::Get()\", StaticAccessorType.Arrow)]\n        internal static extern float GetLightmapBakeTimeTotal();\n\n        [StaticAccessor(\"BakedGISceneManager::Get()\", StaticAccessorType.Arrow)]\n        [NativeName(\"GetLightmapBakePerformance\")]\n        internal static extern float GetLightmapBakePerformanceTotal();\n\n        [StaticAccessor(\"BakedGISceneManager::Get()\", StaticAccessorType.Arrow)]\n        internal static extern string GetLightmapBakeGPUDeviceName();\n\n        [StaticAccessor(\"BakedGISceneManager::Get()\", StaticAccessorType.Arrow)]\n        internal static extern int GetLightmapBakeGPUDeviceIndex();\n\n        [StaticAccessor(\"BakedGISceneManager::Get()\", StaticAccessorType.Arrow)]\n        internal static extern DeviceAndPlatform[] GetLightmappingGpuDevices();\n\n        // Exports the current state of the scene to the dynamic GI workflow.\n        [FreeFunction]\n        internal static extern void PrintStateToConsole();\n\n        // Starts an asynchronous bake job.\n        [FreeFunction]\n        internal static extern bool BakeAsyncImpl();\n\n        // Starts a synchronous bake job.\n        [FreeFunction]\n        internal static extern bool BakeImpl();\n                \n        public static bool BakeAsync()\n        {\n            RenderPipelineManager.TryPrepareRenderPipeline(GraphicsSettings.currentRenderPipeline);\n            return BakeAsyncImpl();\n        }\n\n        public static bool Bake()\n        {\n            RenderPipelineManager.TryPrepareRenderPipeline(GraphicsSettings.currentRenderPipeline);\n            return BakeImpl();\n        }\n        \n        // Cancels the currently running asynchronous bake job.\n        [FreeFunction(\"CancelLightmapping\")]\n        public static extern void Cancel();\n\n        // Stops the current bake at the state it has reached so far.\n        [FreeFunction]\n        [System.Obsolete(\"ForceStop is no longer available, use Cancel instead to stop a bake.\", false)]\n        public static extern void ForceStop();\n\n        // Returns true when the bake job is running, false otherwise (RO).\n        public static extern bool isRunning {[FreeFunction(\"IsRunningLightmapping\")] get; }\n\n        [System.Obsolete(\"OnStartedFunction.started is obsolete, please use bakeStarted instead. \", false)]\n        public static event OnStartedFunction started;\n\n        public static event Action bakeStarted;\n\n        private static void OpenNestedSubScenes()\n        {\n            if (SceneHierarchyHooks.provideSubScenes == null)\n                return;\n\n            var subSceneInfos = SceneHierarchyHooks.provideSubScenes();\n            if (subSceneInfos != null)\n            {\n                // Open all nested sub scenes.\n                int subSceneCount = subSceneInfos.Length;\n                foreach (var subSceneInfo in subSceneInfos)\n                {\n                    if (subSceneInfo.scene.isLoaded)\n                        continue;\n\n                    var path = AssetDatabase.GetAssetPath(subSceneInfo.sceneAsset);\n                    var scene = EditorSceneManager.OpenScene(path, OpenSceneMode.Additive);\n                    scene.isSubScene = true;\n                }\n\n                // Keep going deeper until sub scene count has stabilized.\n                subSceneInfos = SceneHierarchyHooks.provideSubScenes();\n                if (subSceneCount != subSceneInfos.Length)\n                    OpenNestedSubScenes();\n            }\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_CallBakeStartedFunctions()\n        {\n            if (bakeStarted != null)\n                bakeStarted();\n\n            // Open all sub scenes before the bake so they can participate in the GI calculations.\n            OpenNestedSubScenes();\n\n#pragma warning disable 0618\n            if (started != null)\n                started();\n#pragma warning restore 0618\n        }\n\n        internal static event Action startedRendering;\n\n        [RequiredByNativeCode]\n        internal static void Internal_CallStartedRenderingFunctions()\n        {\n            if (startedRendering != null)\n                startedRendering();\n        }\n\n        public static event Action lightingDataUpdated;\n\n        [RequiredByNativeCode]\n        internal static void Internal_CallLightingDataUpdatedFunctions()\n        {\n            if (lightingDataUpdated != null)\n                lightingDataUpdated();\n        }\n\n        public static event Action lightingDataCleared;\n\n        [RequiredByNativeCode]\n        internal static void Internal_CallLightingDataCleared()\n        {\n            if (lightingDataCleared != null)\n                lightingDataCleared();\n        }\n\n        public static event Action lightingDataAssetCleared;\n\n        [RequiredByNativeCode]\n        internal static void Internal_CallLightingDataAssetCleared()\n        {\n            if (lightingDataAssetCleared != null)\n                lightingDataAssetCleared();\n        }\n\n        internal static event Action wroteLightingDataAsset;\n\n        [RequiredByNativeCode]\n        internal static void Internal_CallOnWroteLightingDataAsset()\n        {\n            if (wroteLightingDataAsset != null)\n                wroteLightingDataAsset();\n        }\n\n        // This event is fired when BakeInput has been populated, but before passing it to Bake().\n        // Do not store and access BakeInput beyond the call-back.\n        internal static event Action<LightBaker.BakeInput, LightBaker.LightmapRequests, LightBaker.LightProbeRequests, InputExtraction.SourceMap> createdBakeInput;\n\n        internal static void Internal_CallOnCreatedBakeInput(IntPtr p_BakeInput, IntPtr p_LightmapRequests, IntPtr LightProbeRequests, IntPtr p_SourceMap)\n        {\n            if (createdBakeInput != null)\n            {\n                using var bakeInput = new LightBaker.BakeInput(p_BakeInput);\n                using var lightmapRequests = new LightBaker.LightmapRequests(p_LightmapRequests);\n                using var lightProbeRequests = new LightBaker.LightProbeRequests(LightProbeRequests);\n                using var sourceMap = new InputExtraction.SourceMap(p_SourceMap);\n                createdBakeInput(bakeInput, lightmapRequests, lightProbeRequests, sourceMap);\n            }\n        }\n\n        [System.Obsolete(\"OnCompletedFunction.completed is obsolete, please use event bakeCompleted instead. \", false)]\n        public static OnCompletedFunction completed;\n\n        public static event Action bakeCompleted;\n\n        [RequiredByNativeCode]\n        private static void Internal_CallBakeCompletedFunctions()\n        {\n            if (bakeCompleted != null)\n                bakeCompleted();\n\n#pragma warning disable 0618\n            if (completed != null)\n                completed();\n#pragma warning restore 0618\n        }\n\n        public static event Action bakeCancelled;\n\n        private static void Internal_CallBakeCancelledFunctions()\n        {\n            if (bakeCancelled != null)\n                bakeCancelled();\n        }\n\n        internal static event Action<string> bakeAnalytics;\n\n        [RequiredByNativeCode]\n        private static void Internal_CallBakeAnalyticsFunctions(string analytics)\n        {\n            if (bakeAnalytics != null)\n                bakeAnalytics(analytics);\n        }\n\n        // Returns the progress of a build when the bake job is running, returns 0 when no bake job is running.\n        public static extern float buildProgress {[FreeFunction] get; }\n\n        // Deletes all stored runtime lighting data for the current scene, resets environment lighting to default values.\n        [FreeFunction]\n        public static extern void Clear();\n\n        // Deletes the lighting data asset for the current scene.\n        [FreeFunction]\n        public static extern void ClearLightingDataAsset();\n\n        // Calculates a Delaunay Tetrahedralization of the 'positions' point set - the same way the lightmapper\n        public static void Tetrahedralize(Vector3[] positions, out int[] outIndices, out Vector3[] outPositions)\n        {\n            TetrahedralizationData data = TetrahedralizeInternal(positions);\n            outIndices = data.indices;\n            outPositions = data.positions;\n        }\n\n        [NativeName(\"LightProbeUtils::Tetrahedralize\")]\n        [FreeFunction]\n        private static extern TetrahedralizationData TetrahedralizeInternal(Vector3[] positions);\n\n        [FreeFunction]\n        public static extern bool BakeReflectionProbe(ReflectionProbe probe, string path);\n\n        // Used to quickly update baked reflection probes without GI computations.\n        [FreeFunction]\n        internal static extern bool BakeReflectionProbeSnapshot(ReflectionProbe probe);\n\n        // Used to quickly update all baked reflection probes without GI computations.\n        [FreeFunction]\n        internal static extern bool BakeAllReflectionProbesSnapshots();\n\n        // Called when the user changes the Lightmap Encoding option:\n        // - reload shaders to set correct lightmap decoding keyword\n        // - reimport lightmaps with the new encoding\n        // - rebake reflection probes because the lightmaps may look different\n        [FreeFunction]\n        internal static extern void OnUpdateLightmapEncoding(BuildTargetGroup target);\n\n        // Called when the user changes the HDR Cubemap Encoding option,\n        // will reimport HDR cubemaps with the new encoding.\n        [FreeFunction]\n        internal static extern void OnUpdateHDRCubemapEncoding(BuildTargetGroup target);\n\n        // Called when the user changes the Lightmap streaming settings:\n        [FreeFunction]\n        internal static extern void OnUpdateLightmapStreaming(BuildTargetGroup target);\n\n        [FreeFunction]\n        public static extern void GetTerrainGIChunks([NotNull] Terrain terrain, ref int numChunksX, ref int numChunksY);\n\n        [StaticAccessor(\"GetLightmapSettings()\")]\n        public static extern BakeOnSceneLoadMode bakeOnSceneLoad { get; set; }\n\n        [StaticAccessor(\"GetLightmapSettings()\")]\n        public static extern LightingDataAsset lightingDataAsset { get; set; }\n\n        public static bool TryGetLightingSettings(out LightingSettings settings)\n        {\n            settings = lightingSettingsInternal;\n\n            return (settings != null);\n        }\n\n        public static LightingSettings lightingSettings\n        {\n            get\n            {\n                var settings = lightingSettingsInternal;\n\n                if (settings == null)\n                {\n                    throw new Exception(\"Lightmapping.lightingSettings is null. Please assign it to an existing asset or a new instance. \");\n                }\n\n                return settings;\n            }\n            set\n            {\n                lightingSettingsInternal = value;\n            }\n        }\n\n        [StaticAccessor(\"GetLightmapSettings()\")]\n        [NativeName(\"LightingSettings\")]\n        internal static extern LightingSettings lightingSettingsInternal { get; set; }\n\n        [StaticAccessor(\"GetLightmapSettings()\")]\n        [NativeName(\"LightingSettingsDefaults_Scripting\")]\n        public static extern LightingSettings lightingSettingsDefaults { get; }\n\n        // To be used by internal code when just reading settings, not settings them\n        internal static LightingSettings GetLightingSettingsOrDefaultsFallback()\n        {\n            var lightingSettings = Lightmapping.lightingSettingsInternal;\n\n            if (lightingSettings != null)\n                return lightingSettings;\n\n            return Lightmapping.lightingSettingsDefaults;\n        }\n\n        // used to make sure that the old APIs work. The user should not be required to manually create an asset, so we do it for them.\n        internal static LightingSettings GetOrCreateLightingsSettings()\n        {\n            if (Lightmapping.lightingSettingsInternal == null)\n            {\n                Lightmapping.lightingSettingsInternal = new LightingSettings();\n            }\n\n            return Lightmapping.lightingSettingsInternal;\n        }\n\n        [StaticAccessor(\"GetLightmapSettingsManager()\")]\n        [NativeName(\"SetLightingSettingsForScene\")]\n        public static extern void SetLightingSettingsForScene(Scene scene, LightingSettings lightingSettings);\n\n        [StaticAccessor(\"GetLightmapSettingsManager()\")]\n        [NativeName(\"SetLightingSettingsForScenes\")]\n        public static extern void SetLightingSettingsForScenes(Scene[] scenes, LightingSettings lightingSettings);\n\n        [StaticAccessor(\"GetLightmapSettingsManager()\")]\n        [NativeName(\"GetLightingSettingsForScene\")]\n        public static extern LightingSettings GetLightingSettingsForScene(Scene scene);\n\n        [FreeFunction]\n        public static extern LightingDataAsset GetLightingDataAssetForScene(Scene scene);\n\n        [FreeFunction(ThrowsException = true)]\n        public static extern void SetLightingDataAssetForScene(Scene scene, LightingDataAsset lda);\n\n        public static void BakeMultipleScenes(string[] paths)\n        {\n            if (paths.Length == 0)\n                return;\n\n            for (int i = 0; i < paths.Length; i++)\n            {\n                for (int j = i + 1; j < paths.Length; j++)\n                {\n                    if (paths[i] == paths[j])\n                        throw new System.Exception(\"no duplication of scenes is allowed\");\n                }\n            }\n\n            if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())\n                return;\n\n            var sceneSetup = EditorSceneManager.GetSceneManagerSetup();\n\n            // Restore old scene setup once the bake finishes\n            Action OnBakeFinish = null;\n            OnBakeFinish = () =>\n            {\n                EditorSceneManager.SaveOpenScenes();\n                if (sceneSetup.Length > 0)\n                    EditorSceneManager.RestoreSceneManagerSetup(sceneSetup);\n                Lightmapping.bakeCompleted -= OnBakeFinish;\n            };\n\n            // Call BakeAsync when all scenes are loaded and attach cleanup delegate\n            EditorSceneManager.SceneOpenedCallback BakeOnAllOpen = null;\n            BakeOnAllOpen = (UnityEngine.SceneManagement.Scene scene, SceneManagement.OpenSceneMode loadSceneMode) =>\n            {\n                if (SceneManager.loadedSceneCount == paths.Length)\n                {\n                    BakeAsync();\n                    Lightmapping.bakeCompleted += OnBakeFinish;\n                    EditorSceneManager.sceneOpened -= BakeOnAllOpen;\n                }\n            };\n\n            EditorSceneManager.sceneOpened += BakeOnAllOpen;\n\n            EditorSceneManager.OpenScene(paths[0]);\n            for (int i = 1; i < paths.Length; i++)\n                EditorSceneManager.OpenScene(paths[i], OpenSceneMode.Additive);\n        }\n\n        // Reset lightmapping settings\n        [StaticAccessor(\"GetLightingSettings()\")]\n        extern internal static void Reset();\n\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/GI/EditorHelpers.h\")]\n        extern static internal bool IsLightmappedOrDynamicLightmappedForRendering([NotNull] Renderer renderer);\n\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/GI/EditorHelpers.h\")]\n        extern static internal bool IsOptixDenoiserSupported();\n\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/GI/EditorHelpers.h\")]\n        extern static internal bool IsOpenImageDenoiserSupported();\n\n        // Packing for realtime GI may fail of the mesh has zero UV or surface area. This is the outcome for the given renderer.\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/GI/EditorHelpers.h\")]\n        extern static internal bool HasZeroAreaMesh([NotNull] Renderer renderer);\n\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/GI/EditorHelpers.h\")]\n        extern static internal bool HasUVOverlaps([NotNull] Renderer renderer);\n\n        // Packing for realtime GI may clamp the output resolution. This is the outcome for the given renderer.\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/GI/EditorHelpers.h\")]\n        extern static internal bool HasClampedResolution([NotNull] Renderer renderer);\n\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/GI/EditorHelpers.h\")]\n        extern static internal bool GetSystemResolution([NotNull] Renderer renderer, out int width, out int height);\n\n        [FreeFunction(\"GetSystemResolution\")]\n        [NativeHeader(\"Editor/Src/GI/EditorHelpers.h\")]\n        extern static internal bool GetTerrainSystemResolution([NotNull] Terrain terrain, out int width, out int height, out int numChunksInX, out int numChunksInY);\n\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/GI/EditorHelpers.h\")]\n        extern static internal bool GetInstanceResolution([NotNull] Renderer renderer, out int width, out int height);\n\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/GI/EditorHelpers.h\")]\n        extern static internal bool GetInputSystemHash(int instanceID, out Hash128 inputSystemHash);\n\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/GI/EditorHelpers.h\")]\n        extern static internal bool GetLightmapIndex(int instanceID, out int lightmapIndex);\n\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/GI/EditorHelpers.h\")]\n        extern static internal Hash128[] GetMainSystemHashes();\n\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/GI/EditorHelpers.h\")]\n        extern static internal bool GetInstanceHash([NotNull] Renderer renderer, out Hash128 instanceHash);\n\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/GI/EditorHelpers.h\")]\n        extern static internal bool GetGeometryHash([NotNull] Renderer renderer, out Hash128 geometryHash);\n\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/GI/ExtractInstances.h\")]\n        extern static internal bool IsRendererValid([NotNull] Renderer renderer);\n        \n        public delegate void AdditionalBakeDelegate(ref float progress, ref bool done);\n\n        [RequiredByNativeCode]\n        public static void SetAdditionalBakeDelegate(AdditionalBakeDelegate del) { s_AdditionalBakeDelegate = del != null ? del : s_DefaultAdditionalBakeDelegate; }\n\n        [RequiredByNativeCode]\n        public static AdditionalBakeDelegate GetAdditionalBakeDelegate() { return s_AdditionalBakeDelegate; }\n     \n        [RequiredByNativeCode]\n        public static void ResetAdditionalBakeDelegate() { s_AdditionalBakeDelegate = s_DefaultAdditionalBakeDelegate; }\n     \n        [RequiredByNativeCode]\n        internal static void AdditionalBake(ref float progress, ref bool done)\n        {\n            s_AdditionalBakeDelegate(ref progress, ref done);\n        }\n\n        [RequiredByNativeCode]\n        private static readonly AdditionalBakeDelegate s_DefaultAdditionalBakeDelegate = (ref float progress, ref bool done) =>\n        {\n            progress = 100.0f;\n            done = true;\n        };\n        [RequiredByNativeCode]\n        private static AdditionalBakeDelegate s_AdditionalBakeDelegate = s_DefaultAdditionalBakeDelegate;\n    }\n}\n\nnamespace UnityEditor.Experimental\n{\n    public sealed partial class Lightmapping\n    {\n        [StaticAccessor(\"BakedGISceneManager::Get()\", StaticAccessorType.Arrow)]\n        public static extern bool probesIgnoreDirectEnvironment { get; set; }\n\n        [StaticAccessor(\"BakedGISceneManager::Get()\", StaticAccessorType.Arrow)]\n        public static extern bool probesIgnoreIndirectEnvironment { get; set; }\n\n        public static void SetCustomBakeInputs(Vector4[] inputData, int sampleCount)\n        {\n            SetCustomBakeInputs(inputData.AsSpan(), sampleCount);\n        }\n        [StaticAccessor(\"BakedGISceneManager::Get()\", StaticAccessorType.Arrow)]\n        public static extern void SetCustomBakeInputs(ReadOnlySpan<Vector4> inputData, int sampleCount);\n\n        [StaticAccessor(\"BakedGISceneManager::Get()\", StaticAccessorType.Arrow)]\n        private static extern unsafe bool GetCustomBakeResultsCopy(Span<Vector4> results);\n        public static bool GetCustomBakeResults(Span<Vector4> results)\n        {\n            return GetCustomBakeResultsCopy(results);\n        }\n        public static bool GetCustomBakeResults([Out] Vector4[] results)\n        {\n            return GetCustomBakeResults(results.AsSpan());\n        }\n\n        [StaticAccessor(\"BakedGISceneManager::Get()\", StaticAccessorType.Arrow)]\n        public static extern ReadOnlySpan<Vector4> GetCustomBakeResultsNoCopy();\n\n        [Obsolete(\"UnityEditor.Experimental.Lightmapping.extractAmbientOcclusion is obsolete, use LightingSettings.extractAO instead. \", false)]\n        public static bool extractAmbientOcclusion\n        {\n            get { return UnityEditor.Lightmapping.GetLightingSettingsOrDefaultsFallback().extractAO; }\n            set { UnityEditor.Lightmapping.GetOrCreateLightingsSettings().extractAO = value; }\n        }\n\n        public static bool BakeAsync(Scene targetScene)\n        {\n            RenderPipelineManager.TryPrepareRenderPipeline(GraphicsSettings.currentRenderPipeline);\n            return BakeSceneAsync(targetScene);\n        }\n\n        [NativeThrows]\n        [FreeFunction]\n        [NativeName(\"BakeAsync\")]\n        static extern bool BakeSceneAsync(Scene targetScene);\n\n        public static bool Bake(Scene targetScene)\n        {\n            RenderPipelineManager.TryPrepareRenderPipeline(GraphicsSettings.currentRenderPipeline);\n            return BakeScene(targetScene);\n        }\n\n        [NativeThrows]\n        [FreeFunction]\n        [NativeName(\"Bake\")]\n        static extern bool BakeScene(Scene targetScene);\n\n        [Obsolete(\"Please use UnityEngine.LightTransport.IProbeIntegrator instead.\", false)]\n        public static event Action additionalBakedProbesCompleted;\n\n        [RequiredByNativeCode]\n        internal static void Internal_CallAdditionalBakedProbesCompleted()\n        {\n            if (additionalBakedProbesCompleted != null)\n                additionalBakedProbesCompleted();\n        }\n\n        [FreeFunction]\n        internal unsafe static extern bool GetAdditionalBakedProbes(int id, void* outBakedProbeSH, void* outBakedProbeValidity, void* outBakedProbeOctahedralDepth, int outBakedProbeCount);\n\n        [Obsolete(\"Please use UnityEngine.LightTransport.IProbeIntegrator instead.\", false)]\n        public unsafe static bool GetAdditionalBakedProbes(int id, NativeArray<SphericalHarmonicsL2> outBakedProbeSH, NativeArray<float> outBakedProbeValidity)\n        {\n            const int octahedralDepthMapTexelCount = 64; // 8*8\n            var outBakedProbeOctahedralDepth = new NativeArray<float>(outBakedProbeSH.Length * octahedralDepthMapTexelCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);\n            bool success = GetAdditionalBakedProbes(id, outBakedProbeSH, outBakedProbeValidity, outBakedProbeOctahedralDepth);\n            outBakedProbeOctahedralDepth.Dispose();\n            return success;\n        }\n        [Obsolete(\"Please use UnityEngine.LightTransport.IProbeIntegrator instead.\", false)]\n        public unsafe static bool GetAdditionalBakedProbes(int id, Span<SphericalHarmonicsL2> outBakedProbeSH, Span<float> outBakedProbeValidity, Span<float> outBakedProbeOctahedralDepth)\n        {\n            const int octahedralDepthMapTexelCount = 64; // 8*8\n\n            int numEntries = outBakedProbeSH.Length;\n\n            if (outBakedProbeOctahedralDepth.Length != numEntries * octahedralDepthMapTexelCount)\n            {\n                Debug.LogError(\"Octahedral array must provide \" + numEntries * octahedralDepthMapTexelCount + \" floats.\");\n                return false;\n            }\n\n            if (outBakedProbeValidity.Length != numEntries)\n            {\n                Debug.LogError(\"All output arrays must have equal size.\");\n                return false;\n            }\n            fixed (void* shPtr = outBakedProbeSH)\n            fixed (void* validityPtr = outBakedProbeValidity)\n            fixed (void* octahedralDepthPtr = outBakedProbeOctahedralDepth)\n            {\n                return GetAdditionalBakedProbes(id, shPtr, validityPtr, octahedralDepthPtr, outBakedProbeSH.Length);\n            }\n        }\n        [Obsolete(\"Please use UnityEngine.LightTransport.IProbeIntegrator instead.\", false)]\n        public unsafe static bool GetAdditionalBakedProbes(int id, NativeArray<SphericalHarmonicsL2> outBakedProbeSH, NativeArray<float> outBakedProbeValidity, NativeArray<float> outBakedProbeOctahedralDepth)\n        {\n            if (outBakedProbeSH == null || !outBakedProbeSH.IsCreated ||\n                outBakedProbeValidity == null || !outBakedProbeValidity.IsCreated ||\n                outBakedProbeOctahedralDepth == null || !outBakedProbeOctahedralDepth.IsCreated)\n            {\n                Debug.LogError(\"Output arrays need to be properly initialized.\");\n                return false;\n            }\n\n            const int octahedralDepthMapTexelCount = 64; // 8*8\n\n            int numEntries = outBakedProbeSH.Length;\n\n            if (outBakedProbeOctahedralDepth.Length != numEntries * octahedralDepthMapTexelCount)\n            {\n                Debug.LogError(\"Octahedral array must provide \" + numEntries * octahedralDepthMapTexelCount + \" floats.\");\n                return false;\n            }\n\n            if (outBakedProbeValidity.Length != numEntries)\n            {\n                Debug.LogError(\"All output arrays must have equal size.\");\n                return false;\n            }\n\n            void* shPtr = NativeArrayUnsafeUtility.GetUnsafePtr(outBakedProbeSH);\n            void* validityPtr = NativeArrayUnsafeUtility.GetUnsafePtr(outBakedProbeValidity);\n            void* octahedralDepthPtr = NativeArrayUnsafeUtility.GetUnsafePtr(outBakedProbeOctahedralDepth);\n\n            return GetAdditionalBakedProbes(id, shPtr, validityPtr, octahedralDepthPtr, outBakedProbeSH.Length);\n        }\n        [Obsolete(\"Please use UnityEngine.LightTransport.IProbeIntegrator instead.\", false)]\n        public static void SetAdditionalBakedProbes(int id, Vector3[] positions)\n        {\n            SetAdditionalBakedProbes(id, positions.AsSpan(), true);\n        }\n        [Obsolete(\"Please use UnityEngine.LightTransport.IProbeIntegrator instead.\", false)]\n        public static void SetAdditionalBakedProbes(int id, ReadOnlySpan<Vector3> positions)\n        {\n            SetAdditionalBakedProbes(id, positions, true);\n        }\n        [FreeFunction]\n        [Obsolete(\"Please use UnityEngine.LightTransport.IProbeIntegrator instead.\", false)]\n        public static extern void SetAdditionalBakedProbes(int id, ReadOnlySpan<Vector3> positions, bool dering);\n\n        [FreeFunction]\n        public static extern void SetLightDirty(Light light);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/Lightmapping.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n\nusing UnityEngine;\nusing UnityEngineInternal;\n\nnamespace UnityEditor\n{\n    public partial class Lightmapping\n    {\n        [System.Obsolete(\"lightmapSnapshot has been deprecated. Use lightingDataAsset instead (UnityUpgradable) -> lightingDataAsset\", true)]\n        public static LightmapSnapshot lightmapSnapshot\n        {\n            get { return null; }\n            set {}\n        }\n\n        [System.Obsolete(\"BakeSelectedAsync has been deprecated. Use BakeAsync instead (UnityUpgradable) -> BakeAsync()\", true)]\n        public static bool BakeSelectedAsync() { return false; }\n\n        [System.Obsolete(\"BakeSelected has been deprecated. Use Bake instead (UnityUpgradable) -> Bake()\", true)]\n        public static bool BakeSelected() { return false; }\n\n        [System.Obsolete(\"BakeLightProbesOnlyAsync has been deprecated. Use BakeAsync instead (UnityUpgradable) -> BakeAsync()\", true)]\n        public static bool BakeLightProbesOnlyAsync() { return false; }\n\n        [System.Obsolete(\"BakeLightProbesOnly has been deprecated. Use Bake instead (UnityUpgradable) -> Bake()\", true)]\n        public static bool BakeLightProbesOnly() { return false; }\n    }\n}\n\n"
  },
  {
    "path": "Editor/Mono/GI/PostProcessing.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing Unity.Collections;\nusing Unity.Collections.LowLevel.Unsafe;\nusing Unity.Jobs;\nusing UnityEngine.Rendering;\n\nnamespace UnityEngine.LightTransport\n{\n    namespace PostProcessing\n    {\n        public interface IProbePostProcessor : IDisposable\n        {\n            // Initialize the post processor.\n            bool Initialize(IDeviceContext context);\n\n            // Convolve spherical radiance to irradiance.\n            bool ConvolveRadianceToIrradiance(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> radianceIn, BufferSlice<SphericalHarmonicsL2> irradianceOut, int probeCount);\n\n            // Unity expects the following of the irradiance SH coefficients:\n            // 1) For L0 and L1, they must have the SH standard normalization terms folded into them (to avoid doing this multiplication in shader).\n            // 2) They must be divided by Pi for historical reasons.\n            // 3) L1 terms must be in yzx order (rather than standard xyz).\n            //    This is flipped back in GetShaderConstantsFromNormalizedSH before passed to shader.\n            bool ConvertToUnityFormat(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> irradianceIn, BufferSlice<SphericalHarmonicsL2> irradianceOut, int probeCount);\n\n            // Add two sets of SH coefficients together.\n            bool AddSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> A, BufferSlice<SphericalHarmonicsL2> B, BufferSlice<SphericalHarmonicsL2> sum, int probeCount);\n\n            // Uniformly scale all SH coefficients.\n            bool ScaleSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> shIn, BufferSlice<SphericalHarmonicsL2> shOut, int probeCount, float scale);\n\n            // Spherical Harmonics windowing can be used to reduce ringing artifacts.\n            bool WindowSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> shIn, BufferSlice<SphericalHarmonicsL2> shOut, int probeCount);\n\n            // Spherical Harmonics de-ringing can be used to reduce ringing artifacts.\n            bool DeringSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> shIn, BufferSlice<SphericalHarmonicsL2> shOut, int probeCount);\n        }\n\n        struct SH\n        {\n            // Notation:\n            //                       [L00:  DC]\n            //            [L1-1:  x] [L10:   y] [L11:   z]\n            // [L2-2: xy] [L2-1: yz] [L20:  zz] [L21:  xz]  [L22:  xx - yy]\n            // Underscores are meant as a minus sign in the variable names below.\n            public const int L00 = 0;\n            public const int L1_1 = 1;\n            public const int L10 = 2;\n            public const int L11 = 3;\n            public const int L2_2 = 4;\n            public const int L2_1 = 5;\n            public const int L20 = 6;\n            public const int L21 = 7;\n            public const int L22 = 8;\n\n            // Number of coefficients in the SH L2 basis.\n            public const int L2_CoeffCount = 9;\n        }\n\n        struct SphericalRadianceToIrradiance\n        {\n            // aHat is from https://cseweb.ucsd.edu/~ravir/papers/envmap/envmap.pdf and is used to convert spherical radiance to irradiance.\n            public const float aHat0 = 3.1415926535897932384626433832795028841971693993751058209749445923f; // π\n            public const float aHat1 = 2.0943951023931954923084289221863352561314462662500705473166297282f; // 2π/3\n            public const float aHat2 = 0.785398f; // π/4 (see equation 8).\n        }\n\n        //[BurstCompile] // TODO: Use burst once it is supported in the editor or we move to a package.\n        struct ConvolveJob : IJobParallelFor\n        {\n            [ReadOnly] public NativeSlice<SphericalHarmonicsL2> Radiances;\n            [WriteOnly] public NativeSlice<SphericalHarmonicsL2> Irradiances;\n            public void Execute(int probeIdx)\n            {\n                SphericalHarmonicsL2 radiance = Radiances[probeIdx];\n                var irradiance = new SphericalHarmonicsL2();\n                for (int rgb = 0; rgb < 3; rgb++)\n                {\n                    irradiance[rgb, SH.L00] = radiance[rgb, SH.L00] * SphericalRadianceToIrradiance.aHat0;\n                    irradiance[rgb, SH.L1_1] = radiance[rgb, SH.L1_1] * SphericalRadianceToIrradiance.aHat1;\n                    irradiance[rgb, SH.L10] = radiance[rgb, SH.L10] * SphericalRadianceToIrradiance.aHat1;\n                    irradiance[rgb, SH.L11] = radiance[rgb, SH.L11] * SphericalRadianceToIrradiance.aHat1;\n                    irradiance[rgb, SH.L2_2] = radiance[rgb, SH.L2_2] * SphericalRadianceToIrradiance.aHat2;\n                    irradiance[rgb, SH.L2_1] = radiance[rgb, SH.L2_1] * SphericalRadianceToIrradiance.aHat2;\n                    irradiance[rgb, SH.L20] = radiance[rgb, SH.L20] * SphericalRadianceToIrradiance.aHat2;\n                    irradiance[rgb, SH.L21] = radiance[rgb, SH.L21] * SphericalRadianceToIrradiance.aHat2;\n                    irradiance[rgb, SH.L22] = radiance[rgb, SH.L22] * SphericalRadianceToIrradiance.aHat2;\n                };\n                Irradiances[probeIdx] = irradiance;\n            }\n        }\n        //[BurstCompile] // TODO: Use burst once it is supported in the editor or we move to a package.\n        struct UnityfyJob : IJobParallelFor\n        {\n            [ReadOnly] public NativeSlice<SphericalHarmonicsL2> IrradianceIn;\n            [WriteOnly] public NativeSlice<SphericalHarmonicsL2> IrradianceOut;\n            public void Execute(int probeIdx)\n            {\n                float shY0Normalization = Mathf.Sqrt(1.0f / Mathf.PI) / 2.0f;\n\n                float shY1Normalization = Mathf.Sqrt(3.0f / Mathf.PI) / 2.0f;\n\n                float shY2_2Normalization = Mathf.Sqrt(15.0f / Mathf.PI) / 2.0f;\n                float shY2_1Normalization = shY2_2Normalization;\n                float shY20Normalization = Mathf.Sqrt(5.0f / Mathf.PI) / 4.0f;\n                float shY21Normalization = shY2_2Normalization;\n                float shY22Normalization = Mathf.Sqrt(15.0f / Mathf.PI) / 4.0f;\n\n                SphericalHarmonicsL2 irradiance = IrradianceIn[probeIdx];\n                var output = new SphericalHarmonicsL2();\n                for (int rgb = 0; rgb < 3; ++rgb)\n                {\n                    // L0\n                    output[rgb, SH.L00] = irradiance[rgb, SH.L00];\n                    output[rgb, SH.L00] *= shY0Normalization; // 1)\n                    output[rgb, SH.L00] /= Mathf.PI; // 2)\n\n                    // L1\n                    output[rgb, SH.L1_1] = irradiance[rgb, SH.L10]; // 3)\n                    output[rgb, SH.L1_1] *= shY1Normalization; // 1)\n                    output[rgb, SH.L1_1] /= Mathf.PI; // 3 )\n\n                    output[rgb, SH.L10] = irradiance[rgb, SH.L11]; // 3)\n                    output[rgb, SH.L10] *= shY1Normalization; // 1)\n                    output[rgb, SH.L10] /= Mathf.PI; // 2)\n\n                    output[rgb, SH.L11] = irradiance[rgb, SH.L1_1]; // 3)\n                    output[rgb, SH.L11] *= shY1Normalization; // 1)\n                    output[rgb, SH.L11] /= Mathf.PI; // 2)\n\n                    // L2\n                    output[rgb, SH.L2_2] = irradiance[rgb, SH.L2_2];\n                    output[rgb, SH.L2_2] *= shY2_2Normalization; // 1)\n                    output[rgb, SH.L2_2] /= Mathf.PI; // 2)\n\n                    output[rgb, SH.L2_1] = irradiance[rgb, SH.L2_1];\n                    output[rgb, SH.L2_1] *= shY2_1Normalization; // 1)\n                    output[rgb, SH.L2_1] /= Mathf.PI; // 2)\n\n                    output[rgb, SH.L20] = irradiance[rgb, SH.L20];\n                    output[rgb, SH.L20] *= shY20Normalization; // 1)\n                    output[rgb, SH.L20] /= Mathf.PI; // 2)\n\n                    output[rgb, SH.L21] = irradiance[rgb, SH.L21];\n                    output[rgb, SH.L21] *= shY21Normalization; // 1)\n                    output[rgb, SH.L21] /= Mathf.PI; // 2)\n\n                    output[rgb, SH.L22] = irradiance[rgb, SH.L22];\n                    output[rgb, SH.L22] *= shY22Normalization; // 1)\n                    output[rgb, SH.L22] /= Mathf.PI; // 2)\n                }\n                IrradianceOut[probeIdx] = output;\n            }\n        }\n        //[BurstCompile] // TODO: Use burst once it is supported in the editor or we move to a package.\n        struct AddSHJob : IJobParallelFor\n        {\n            [ReadOnly] public NativeSlice<SphericalHarmonicsL2> A;\n            [ReadOnly] public NativeSlice<SphericalHarmonicsL2> B;\n            [WriteOnly] public NativeSlice<SphericalHarmonicsL2> Sum;\n            public void Execute(int probeIdx)\n            {\n                Sum[probeIdx] = A[probeIdx] + B[probeIdx];\n            }\n        }\n        //[BurstCompile] // TODO: Use burst once it is supported in the editor or we move to a package.\n        struct ScaleSHJob : IJobParallelFor\n        {\n            [ReadOnly] public NativeSlice<SphericalHarmonicsL2> Input;\n            [ReadOnly] public float Scale;\n            [WriteOnly] public NativeSlice<SphericalHarmonicsL2> Scaled;\n            public void Execute(int probeIdx)\n            {\n                Scaled[probeIdx] = Input[probeIdx] * Scale;\n            }\n        }\n        //[BurstCompile] // TODO: Use burst once it is supported in the editor or we move to a package.\n        struct WindowSHJob : IJobParallelFor\n        {\n            [ReadOnly] public NativeSlice<SphericalHarmonicsL2> Input;\n            [WriteOnly] public NativeSlice<SphericalHarmonicsL2> Windowed;\n            public void Execute(int probeIdx)\n            {\n                // Windowing constants from WindowDirectSH in SHDering.cpp\n                float[] extraWindow = new float[] { 1.0f, 0.922066f, 0.731864f };\n                \n                // Apply windowing: Essentially SHConv3 times the window constants\n                SphericalHarmonicsL2 sh = Input[probeIdx];\n                for (int coefficientIndex = 0; coefficientIndex < SH.L2_CoeffCount; ++coefficientIndex)\n                {\n                    float window;\n                    if (coefficientIndex == 0)\n                        window = extraWindow[0];\n                    else if (coefficientIndex < 4)\n                        window = extraWindow[1];\n                    else\n                        window = extraWindow[2];\n                    sh[0, coefficientIndex] *= window;\n                    sh[1, coefficientIndex] *= window;\n                    sh[2, coefficientIndex] *= window;\n                }\n                Windowed[probeIdx] = sh;\n            }\n        }\n        //[BurstCompile] // TODO: Use burst once it is supported in the editor or we move to a package.\n        struct DeringSHJob : IJobParallelFor\n        {\n            [ReadOnly] public NativeSlice<SphericalHarmonicsL2> Input;\n            [WriteOnly] public NativeSlice<SphericalHarmonicsL2> Output;\n            public void Execute(int probeIdx)\n            {\n                SphericalHarmonicsL2 sh = Input[probeIdx];\n                SphericalHarmonicsL2 output = new SphericalHarmonicsL2();\n                unsafe\n                {\n                    var shInputPtr = (SphericalHarmonicsL2*)UnsafeUtility.AddressOf(ref sh);\n                    var shOutputPtr = (SphericalHarmonicsL2*)UnsafeUtility.AddressOf(ref output);\n                    bool result = WintermuteContext.DeringSphericalHarmonicsL2Internal(shInputPtr, shOutputPtr, 1);\n                    Debug.Assert(result);\n                }\n                Output[probeIdx] = output;\n            }\n        }\n        public class ReferenceProbePostProcessor : IProbePostProcessor\n        {\n            public bool Initialize(IDeviceContext context)\n            {\n                return true;\n            }\n\n            public bool ConvolveRadianceToIrradiance(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> radianceIn, BufferSlice<SphericalHarmonicsL2> irradianceOut, int probeCount)\n            {\n                Debug.Assert(context is ReferenceContext, \"Expected ReferenceContext but got something else.\");\n                if (context is not ReferenceContext refContext)\n                    return false;\n\n                NativeArray<byte> radianceNativeArray = refContext.GetNativeArray(radianceIn.Id);\n                NativeArray<byte> irradianceNativeArray = refContext.GetNativeArray(irradianceOut.Id);\n                NativeArray<SphericalHarmonicsL2> Radiances = radianceNativeArray.Reinterpret<SphericalHarmonicsL2>(1);\n                NativeArray<SphericalHarmonicsL2> Irradiances = irradianceNativeArray.Reinterpret<SphericalHarmonicsL2>(1);\n                for (int probeIdx = 0; probeIdx < probeCount; ++probeIdx)\n                {\n                    SphericalHarmonicsL2 radiance = Radiances[probeIdx];\n                    var irradiance = new SphericalHarmonicsL2();\n                    for (int rgb = 0; rgb < 3; rgb++)\n                    {\n                        irradiance[rgb, SH.L00] = radiance[rgb, SH.L00] * SphericalRadianceToIrradiance.aHat0;\n                        irradiance[rgb, SH.L1_1] = radiance[rgb, SH.L1_1] * SphericalRadianceToIrradiance.aHat1;\n                        irradiance[rgb, SH.L10] = radiance[rgb, SH.L10] * SphericalRadianceToIrradiance.aHat1;\n                        irradiance[rgb, SH.L11] = radiance[rgb, SH.L11] * SphericalRadianceToIrradiance.aHat1;\n                        irradiance[rgb, SH.L2_2] = radiance[rgb, SH.L2_2] * SphericalRadianceToIrradiance.aHat2;\n                        irradiance[rgb, SH.L2_1] = radiance[rgb, SH.L2_1] * SphericalRadianceToIrradiance.aHat2;\n                        irradiance[rgb, SH.L20] = radiance[rgb, SH.L20] * SphericalRadianceToIrradiance.aHat2;\n                        irradiance[rgb, SH.L21] = radiance[rgb, SH.L21] * SphericalRadianceToIrradiance.aHat2;\n                        irradiance[rgb, SH.L22] = radiance[rgb, SH.L22] * SphericalRadianceToIrradiance.aHat2;\n                    };\n                    Irradiances[probeIdx] = irradiance;\n                }\n                return true;\n            }\n\n            public bool ConvertToUnityFormat(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> irradianceIn, BufferSlice<SphericalHarmonicsL2> irradianceOut, int probeCount)\n            {\n                Debug.Assert(context is ReferenceContext, \"Expected ReferenceContext but got something else.\");\n                if (context is not ReferenceContext refContext)\n                    return false;\n\n                float shY0Normalization = Mathf.Sqrt(1.0f / Mathf.PI) / 2.0f;\n\n                float shY1Normalization = Mathf.Sqrt(3.0f / Mathf.PI) / 2.0f;\n\n                float shY2_2Normalization = Mathf.Sqrt(15.0f / Mathf.PI) / 2.0f;\n                float shY2_1Normalization = shY2_2Normalization;\n                float shY20Normalization = Mathf.Sqrt(5.0f / Mathf.PI) / 4.0f;\n                float shY21Normalization = shY2_2Normalization;\n                float shY22Normalization = Mathf.Sqrt(15.0f / Mathf.PI) / 4.0f;\n\n                NativeArray<byte> irradianceInNativeArray = refContext.GetNativeArray(irradianceIn.Id);\n                NativeArray<byte> irradianceOutNativeArray = refContext.GetNativeArray(irradianceOut.Id);\n                NativeArray<SphericalHarmonicsL2> IrradianceIn = irradianceInNativeArray.Reinterpret<SphericalHarmonicsL2>(1);\n                NativeArray<SphericalHarmonicsL2> IrradianceOut = irradianceOutNativeArray.Reinterpret<SphericalHarmonicsL2>(1);\n                for (int probeIdx = 0; probeIdx < probeCount; ++probeIdx)\n                {\n                    SphericalHarmonicsL2 irradiance = IrradianceIn[probeIdx];\n                    var output = new SphericalHarmonicsL2();\n                    for (int rgb = 0; rgb < 3; ++rgb)\n                    {\n                        // L0\n                        output[rgb, SH.L00] = irradiance[rgb, SH.L00];\n                        output[rgb, SH.L00] *= shY0Normalization; // 1)\n                        output[rgb, SH.L00] /= Mathf.PI; // 2)\n\n                        // L1\n                        output[rgb, SH.L1_1] = irradiance[rgb, SH.L10]; // 3)\n                        output[rgb, SH.L1_1] *= shY1Normalization; // 1)\n                        output[rgb, SH.L1_1] /= Mathf.PI; // 3 )\n\n                        output[rgb, SH.L10] = irradiance[rgb, SH.L11]; // 3)\n                        output[rgb, SH.L10] *= shY1Normalization; // 1)\n                        output[rgb, SH.L10] /= Mathf.PI; // 2)\n\n                        output[rgb, SH.L11] = irradiance[rgb, SH.L1_1]; // 3)\n                        output[rgb, SH.L11] *= shY1Normalization; // 1)\n                        output[rgb, SH.L11] /= Mathf.PI; // 2)\n\n                        // L2\n                        output[rgb, SH.L2_2] = irradiance[rgb, SH.L2_2];\n                        output[rgb, SH.L2_2] *= shY2_2Normalization; // 1)\n                        output[rgb, SH.L2_2] /= Mathf.PI; // 2)\n\n                        output[rgb, SH.L2_1] = irradiance[rgb, SH.L2_1];\n                        output[rgb, SH.L2_1] *= shY2_1Normalization; // 1)\n                        output[rgb, SH.L2_1] /= Mathf.PI; // 2)\n\n                        output[rgb, SH.L20] = irradiance[rgb, SH.L20];\n                        output[rgb, SH.L20] *= shY20Normalization; // 1)\n                        output[rgb, SH.L20] /= Mathf.PI; // 2)\n\n                        output[rgb, SH.L21] = irradiance[rgb, SH.L21];\n                        output[rgb, SH.L21] *= shY21Normalization; // 1)\n                        output[rgb, SH.L21] /= Mathf.PI; // 2)\n\n                        output[rgb, SH.L22] = irradiance[rgb, SH.L22];\n                        output[rgb, SH.L22] *= shY22Normalization; // 1)\n                        output[rgb, SH.L22] /= Mathf.PI; // 2)\n                    }\n                    IrradianceOut[probeIdx] = output;\n                }\n                return true;\n            }\n\n            public bool AddSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> a, BufferSlice<SphericalHarmonicsL2> b, BufferSlice<SphericalHarmonicsL2> sum, int probeCount)\n            {\n                Debug.Assert(context is ReferenceContext, \"Expected ReferenceContext but got something else.\");\n                if (context is not ReferenceContext refContext)\n                    return false;\n\n                NativeArray<byte> A = refContext.GetNativeArray(a.Id);\n                NativeArray<byte> B = refContext.GetNativeArray(b.Id);\n                NativeArray<byte> Sum = refContext.GetNativeArray(sum.Id);\n                NativeArray<SphericalHarmonicsL2> shA = A.Reinterpret<SphericalHarmonicsL2>(1);\n                NativeArray<SphericalHarmonicsL2> shB = B.Reinterpret<SphericalHarmonicsL2>(1);\n                NativeArray<SphericalHarmonicsL2> shSum = Sum.Reinterpret<SphericalHarmonicsL2>(1);\n                for (int probeIdx = 0; probeIdx < probeCount; ++probeIdx)\n                {\n                    shSum[probeIdx] = shA[probeIdx] + shB[probeIdx];\n                }\n                return true;\n            }\n\n            public bool ScaleSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> shIn, BufferSlice<SphericalHarmonicsL2> shOut, int probeCount, float scale)\n            {\n                Debug.Assert(context is ReferenceContext, \"Expected ReferenceContext but got something else.\");\n                if (context is not ReferenceContext refContext)\n                    return false;\n\n                NativeArray<byte> sh = refContext.GetNativeArray(shIn.Id);\n                NativeArray<byte> output = refContext.GetNativeArray(shOut.Id);\n                NativeArray<SphericalHarmonicsL2> shInput = sh.Reinterpret<SphericalHarmonicsL2>(1);\n                NativeArray<SphericalHarmonicsL2> shOutput = output.Reinterpret<SphericalHarmonicsL2>(1);\n                for (int probeIdx = 0; probeIdx < probeCount; ++probeIdx)\n                {\n                    shOutput[probeIdx] = shInput[probeIdx] * scale;\n                }\n                return true;\n            }\n\n            public bool WindowSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> shIn, BufferSlice<SphericalHarmonicsL2> shOut, int probeCount)\n            {\n                Debug.Assert(context is ReferenceContext, \"Expected ReferenceContext but got something else.\");\n                if (context is not ReferenceContext refContext)\n                    return false;\n\n                NativeArray<byte> A = refContext.GetNativeArray(shIn.Id);\n                NativeArray<byte> B = refContext.GetNativeArray(shOut.Id);\n                NativeArray<SphericalHarmonicsL2> shA = A.Reinterpret<SphericalHarmonicsL2>(1);\n                NativeArray<SphericalHarmonicsL2> shB = B.Reinterpret<SphericalHarmonicsL2>(1);\n\n                // Windowing constants from WindowDirectSH in SHDering.cpp\n                float[] extraWindow = new float[] { 1.0f, 0.922066f, 0.731864f };\n\n                // Apply windowing function to SH coefficients.\n                for (int probeIdx = 0; probeIdx < probeCount; ++probeIdx)\n                {\n                    // Apply windowing: Essentially SHConv3 times the window constants\n                    SphericalHarmonicsL2 sh = shA[probeIdx];\n                    for (int coefficientIndex = 0; coefficientIndex < SH.L2_CoeffCount; ++coefficientIndex)\n                    {\n                        float window;\n                        if (coefficientIndex == 0)\n                            window = extraWindow[0];\n                        else if (coefficientIndex < 4)\n                            window = extraWindow[1];\n                        else\n                            window = extraWindow[2];\n                        sh[0, coefficientIndex] *= window;\n                        sh[1, coefficientIndex] *= window;\n                        sh[2, coefficientIndex] *= window;\n                    }\n                    shB[probeIdx] = sh;\n                }\n                return true;\n            }\n\n            public bool DeringSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> shIn, BufferSlice<SphericalHarmonicsL2> shOut, int probeCount)\n            {\n                Debug.Assert(context is ReferenceContext, \"Expected ReferenceContext but got something else.\");\n                if (context is not ReferenceContext refContext)\n                    return false;\n\n                NativeArray<byte> inputSh = refContext.GetNativeArray(shIn.Id);\n                NativeArray<byte> outputSh = refContext.GetNativeArray(shOut.Id);\n                NativeArray<SphericalHarmonicsL2> shInput = inputSh.Reinterpret<SphericalHarmonicsL2>(1);\n                NativeArray<SphericalHarmonicsL2> shOutput = outputSh.Reinterpret<SphericalHarmonicsL2>(1);\n                unsafe\n                {\n                    for (int probeIdx = 0; probeIdx < probeCount; ++probeIdx)\n                    {\n                        SphericalHarmonicsL2 sh = shInput[probeIdx];\n                        SphericalHarmonicsL2 output = new SphericalHarmonicsL2();\n                        var shInputPtr = (SphericalHarmonicsL2*)UnsafeUtility.AddressOf(ref sh);\n                        var shOutputPtr = (SphericalHarmonicsL2*)UnsafeUtility.AddressOf(ref output);\n                        bool result = WintermuteContext.DeringSphericalHarmonicsL2Internal(shInputPtr, shOutputPtr, 1);\n                        Debug.Assert(result);\n                        shOutput[probeIdx] = output;\n                    }\n                }\n                return true;\n            }\n\n            public void Dispose()\n            {\n            }\n        }\n        internal class WintermuteProbePostProcessor : IProbePostProcessor\n        {\n            public bool Initialize(IDeviceContext context)\n            {\n                return true;\n            }\n\n            public bool ConvolveRadianceToIrradiance(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> radianceIn, BufferSlice<SphericalHarmonicsL2> irradianceOut, int probeCount)\n            {\n                Debug.Assert(context is WintermuteContext, \"Expected WintermuteContext but got something else.\");\n                if (context is not WintermuteContext wmContext)\n                    return false;\n\n                NativeArray<byte> radianceInNativeArray = wmContext.GetNativeArray(radianceIn.Id);\n                NativeArray<byte> irradianceOutNativeArray = wmContext.GetNativeArray(irradianceOut.Id);\n                var job = new ConvolveJob\n                {\n                    Radiances = radianceInNativeArray.Reinterpret<SphericalHarmonicsL2>(1),\n                    Irradiances = irradianceOutNativeArray.Reinterpret<SphericalHarmonicsL2>(1)\n                };\n                JobHandle jobHandle = job.Schedule(probeCount, 64);\n                jobHandle.Complete();\n                return true;\n            }\n\n            public bool ConvertToUnityFormat(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> irradianceIn, BufferSlice<SphericalHarmonicsL2> irradianceOut, int probeCount)\n            {\n                Debug.Assert(context is WintermuteContext, \"Expected WintermuteContext but got something else.\");\n                if (context is not WintermuteContext wmContext)\n                    return false;\n\n                NativeArray<byte> irradianceInNativeArray = wmContext.GetNativeArray(irradianceIn.Id);\n                NativeArray<byte> irradianceOutNativeArray = wmContext.GetNativeArray(irradianceOut.Id);\n                var job = new UnityfyJob\n                {\n                    IrradianceIn = irradianceInNativeArray.Reinterpret<SphericalHarmonicsL2>(1),\n                    IrradianceOut = irradianceOutNativeArray.Reinterpret<SphericalHarmonicsL2>(1)\n                };\n                JobHandle jobHandle = job.Schedule(probeCount, 64);\n                jobHandle.Complete();\n                return true;\n            }\n\n            public bool AddSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> a, BufferSlice<SphericalHarmonicsL2> b, BufferSlice<SphericalHarmonicsL2> sum, int probeCount)\n            {\n                Debug.Assert(context is WintermuteContext, \"Expected WintermuteContext but got something else.\");\n                if (context is not WintermuteContext wmContext)\n                    return false;\n\n                NativeArray<byte> A = wmContext.GetNativeArray(a.Id);\n                NativeArray<byte> B = wmContext.GetNativeArray(b.Id);\n                NativeArray<byte> Sum = wmContext.GetNativeArray(sum.Id);\n                var job = new AddSHJob\n                {\n                    A = A.Reinterpret<SphericalHarmonicsL2>(1),\n                    B = B.Reinterpret<SphericalHarmonicsL2>(1),\n                    Sum = Sum.Reinterpret<SphericalHarmonicsL2>(1)\n                };\n                JobHandle jobHandle = job.Schedule(probeCount, 64);\n                jobHandle.Complete();\n                return true;\n            }\n\n            public bool ScaleSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> shIn, BufferSlice<SphericalHarmonicsL2> shOut, int probeCount, float scale)\n            {\n                Debug.Assert(context is WintermuteContext, \"Expected WintermuteContext but got something else.\");\n                if (context is not WintermuteContext wmContext)\n                    return false;\n\n                NativeArray<byte> input = wmContext.GetNativeArray(shIn.Id);\n                NativeArray<byte> output = wmContext.GetNativeArray(shOut.Id);\n                var job = new ScaleSHJob\n                {\n                    Input = input.Reinterpret<SphericalHarmonicsL2>(1),\n                    Scale = scale,\n                    Scaled = output.Reinterpret<SphericalHarmonicsL2>(1)\n                };\n                JobHandle jobHandle = job.Schedule(probeCount, 64);\n                jobHandle.Complete();\n                return true;\n            }\n\n            public bool WindowSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> shIn, BufferSlice<SphericalHarmonicsL2> shOut, int probeCount)\n            {\n                Debug.Assert(context is WintermuteContext, \"Expected WintermuteContext but got something else.\");\n                if (context is not WintermuteContext wmContext)\n                    return false;\n\n                NativeArray<byte> A = wmContext.GetNativeArray(shIn.Id);\n                NativeArray<byte> B = wmContext.GetNativeArray(shOut.Id);\n                var job = new WindowSHJob\n                {\n                    Input = A.Reinterpret<SphericalHarmonicsL2>(1),\n                    Windowed = B.Reinterpret<SphericalHarmonicsL2>(1)\n                };\n                JobHandle jobHandle = job.Schedule(probeCount, 64);\n                jobHandle.Complete();\n                return true;\n            }\n\n            public bool DeringSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> shIn, BufferSlice<SphericalHarmonicsL2> shOut, int probeCount)\n            {\n                Debug.Assert(context is WintermuteContext, \"Expected WintermuteContext but got something else.\");\n                if (context is not WintermuteContext wmContext)\n                    return false;\n\n                NativeArray<byte> A = wmContext.GetNativeArray(shIn.Id);\n                NativeArray<byte> B = wmContext.GetNativeArray(shOut.Id);\n                var job = new DeringSHJob\n                {\n                    Input = A.Reinterpret<SphericalHarmonicsL2>(1),\n                    Output = B.Reinterpret<SphericalHarmonicsL2>(1)\n                };\n                JobHandle jobHandle = job.Schedule(probeCount, 64);\n                jobHandle.Complete();\n                return true;\n            }\n\n            public void Dispose()\n            {\n            }\n        }\n        public class RadeonRaysProbePostProcessor : IProbePostProcessor\n        {\n            private const int sizeofSphericalHarmonicsL2 = 27 * sizeof(float);\n\n            public bool Initialize(IDeviceContext context)\n            {\n                Debug.Assert(context is RadeonRaysContext, \"Expected RadeonRaysContext but got something else.\");\n                var rrContext = context as RadeonRaysContext;\n                return RadeonRaysContext.InitializePostProcessingInternal(rrContext);\n            }\n\n            public bool ConvolveRadianceToIrradiance(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> radianceIn, BufferSlice<SphericalHarmonicsL2> irradianceOut, int probeCount)\n            {\n                Debug.Assert(context is RadeonRaysContext, \"Expected RadeonRaysContext but got something else.\");\n                if (context is not RadeonRaysContext rrContext)\n                    return false;\n\n                return RadeonRaysContext.ConvolveRadianceToIrradianceInternal(rrContext, radianceIn.Id, irradianceOut.Id, probeCount);\n            }\n\n            public bool ConvertToUnityFormat(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> irradianceIn, BufferSlice<SphericalHarmonicsL2> irradianceOut, int probeCount)\n            {\n                Debug.Assert(context is RadeonRaysContext, \"Expected RadeonRaysContext but got something else.\");\n                if (context is not RadeonRaysContext rrContext)\n                    return false;\n\n                return RadeonRaysContext.ConvertToUnityFormatInternal(rrContext, irradianceIn.Id, irradianceOut.Id, probeCount);\n            }\n\n            public bool AddSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> a, BufferSlice<SphericalHarmonicsL2> b, BufferSlice<SphericalHarmonicsL2> sum, int probeCount)\n            {\n                Debug.Assert(context is RadeonRaysContext, \"Expected RadeonRaysContext but got something else.\");\n                if (context is not RadeonRaysContext rrContext)\n                    return false;\n\n                return RadeonRaysContext.AddSphericalHarmonicsL2Internal(rrContext, a.Id, b.Id, sum.Id, probeCount);\n            }\n\n            public bool ScaleSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> shIn, BufferSlice<SphericalHarmonicsL2> shOut, int probeCount, float scale)\n            {\n                Debug.Assert(context is RadeonRaysContext, \"Expected RadeonRaysContext but got something else.\");\n                if (context is not RadeonRaysContext rrContext)\n                    return false;\n\n                return RadeonRaysContext.ScaleSphericalHarmonicsL2Internal(rrContext, shIn.Id, shOut.Id, probeCount, scale);\n            }\n\n            public bool WindowSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> shIn, BufferSlice<SphericalHarmonicsL2> shOut, int probeCount)\n            {\n                Debug.Assert(context is RadeonRaysContext, \"Expected RadeonRaysContext but got something else.\");\n                if (context is not RadeonRaysContext rrContext)\n                    return false;\n\n                return RadeonRaysContext.WindowSphericalHarmonicsL2Internal(rrContext, shIn.Id, shOut.Id, probeCount);\n            }\n\n            public bool DeringSphericalHarmonicsL2(IDeviceContext context, BufferSlice<SphericalHarmonicsL2> shIn, BufferSlice<SphericalHarmonicsL2> shOut, int probeCount)\n            {\n                // Read back from GPU memory into CPU memory.\n                using var shInputBuffer = new NativeArray<SphericalHarmonicsL2>(probeCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n                using var shOutputBuffer = new NativeArray<SphericalHarmonicsL2>(probeCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n                EventID eventId = context.CreateEvent();\n                context.ReadBuffer(shIn, shInputBuffer, eventId);\n\t\t\t\tbool flushResult = context.Flush();\n                Debug.Assert(flushResult, \"Failed to flush context.\");\n                bool waitResult = context.Wait(eventId);\n                Debug.Assert(waitResult, \"Failed to read SH from context.\");\n                context.DestroyEvent(eventId);\n\n                // Currently windowing is done on CPU since the algorithm is not GPU friendly.\n                // Since we aren't attempting to port this to GPU, we are using the jobified CPU version.\n                var job = new DeringSHJob\n                {\n                    Input = shInputBuffer,\n                    Output = shOutputBuffer\n                };\n                JobHandle jobHandle = job.Schedule(probeCount, 64);\n                jobHandle.Complete();\n\n                // Write back to GPU.\n                eventId = context.CreateEvent();\n                context.WriteBuffer(shOut, shOutputBuffer, eventId);\n                waitResult = context.Wait(eventId);\n                Debug.Assert(waitResult, \"Failed to write SH to context.\");\n                context.DestroyEvent(eventId);\n                return true;\n            }\n\n            public void Dispose()\n            {\n            }\n        }\n    }\n}\n\n"
  },
  {
    "path": "Editor/Mono/GI/ProbeIntegrator.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing Unity.Collections;\nusing Unity.Collections.LowLevel.Unsafe;\nusing UnityEditor.LightBaking;\nusing UnityEngine.Rendering;\n\nnamespace UnityEngine.LightTransport\n{\n    public interface IProbeIntegrator : IDisposable\n    {\n        public enum ResultType : uint\n        {\n            Success = 0,\n            Cancelled,\n            JobFailed,\n            OutOfMemory,\n            InvalidInput,\n            LowLevelAPIFailure,\n            IOFailed,\n            Undefined\n        }\n        public struct Result\n        {\n            public Result(ResultType _type, String _message)\n            {\n                type = _type;\n                message = _message;\n            }\n            public ResultType type;\n            public String message;\n            public override string ToString()\n            {\n                if (message.Length == 0)\n                    return $\"Result type: '{type}'\";\n                else\n                    return $\"Result type: '{type}', message: '{message}'\";\n            }\n        }\n        public void Prepare(IDeviceContext context, IWorld world, BufferSlice<Vector3> positions, float pushoff, int bounceCount);\n        public void SetProgressReporter(BakeProgressState progress);\n        public Result IntegrateDirectRadiance(IDeviceContext context, int positionOffset, int positionCount, int sampleCount,\n            bool ignoreEnvironment, BufferSlice<SphericalHarmonicsL2> radianceEstimateOut);\n        public Result IntegrateIndirectRadiance(IDeviceContext context, int positionOffset, int positionCount, int sampleCount,\n            bool ignoreEnvironment, BufferSlice<SphericalHarmonicsL2> radianceEstimateOut);\n        public Result IntegrateValidity(IDeviceContext context, int positionOffset, int positionCount, int sampleCount, BufferSlice<float> validityEstimateOut);\n        public Result IntegrateOcclusion(IDeviceContext context, int positionOffset, int positionCount, int sampleCount,\n            int maxLightsPerProbe, BufferSlice<int> perProbeLightIndices, BufferSlice<float> probeOcclusionEstimateOut);\n    }\n    internal class WintermuteProbeIntegrator : IProbeIntegrator\n    {\n        private IntegrationContext _integrationContext;\n        private BufferSlice<Vector3> _positions;\n        private float _pushoff;\n        private int _bounceCount;\n        private BakeProgressState _progress;\n        private const int SizeOfFloat = 4;\n        private const int SHL2RGBElements = 3 * 9;\n        private const int SizeOfSHL2 = SizeOfFloat * SHL2RGBElements;\n        private const int SizeOfVector3 = SizeOfFloat * 3;\n\n        public void Prepare(IDeviceContext context, IWorld world, BufferSlice<Vector3> positions, float pushoff, int bounceCount)\n        {\n            Debug.Assert(world is WintermuteWorld);\n            var wmWorld = world as WintermuteWorld;\n            _integrationContext = wmWorld.GetIntegrationContext();\n            _positions = positions;\n            _pushoff = pushoff;\n            _bounceCount = bounceCount;\n        }\n        public void SetProgressReporter(BakeProgressState progress)\n        {\n            _progress = progress;\n        }\n        public unsafe IProbeIntegrator.Result IntegrateDirectRadiance(IDeviceContext context, int positionOffset, int positionCount, int sampleCount,\n            bool ignoreEnvironment, BufferSlice<SphericalHarmonicsL2> radianceEstimateOut)\n        {\n            Debug.Assert(context is WintermuteContext, \"Expected WintermuteContext but got something else.\");\n            var wmContext = context as WintermuteContext;\n            using var positions = new NativeArray<Vector3>(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            BufferSlice<Vector3> offsetPositions = _positions;\n            offsetPositions.Offset += (ulong)positionOffset;\n            EventID eventId = context.CreateEvent();\n            context.ReadBuffer(offsetPositions, positions, eventId);\n            bool waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to read positions from context.\");\n            context.DestroyEvent(eventId);\n            var positionsPtr = (Vector3*)positions.GetUnsafePtr();\n            using var radianceBuffer = new NativeArray<Rendering.SphericalHarmonicsL2>(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            void* shPtr = NativeArrayUnsafeUtility.GetUnsafePtr(radianceBuffer);\n            int directSampleCount = sampleCount;\n            int giSampleCount = 0;\n            int envSampleCount = 0;\n            bool ignoreDirectEnvironment = ignoreEnvironment;\n            bool ignoreIndirectEnvironment = ignoreEnvironment;\n            var lightBakerResult = LightBaker.IntegrateProbeDirectRadianceWintermute(positionsPtr, _integrationContext, positionCount, _pushoff,\n                _bounceCount, directSampleCount, giSampleCount, envSampleCount, ignoreDirectEnvironment, ignoreIndirectEnvironment, wmContext, _progress, shPtr);\n\n            // TODO: Fix this in LIGHT-1479, synchronization and read-back should be done by the user.\n            if (lightBakerResult.type != LightBaker.ResultType.Success)\n                return lightBakerResult.ConvertToIProbeIntegratorResult();\n\n            eventId = context.CreateEvent();\n            context.WriteBuffer(radianceEstimateOut, radianceBuffer, eventId);\n            waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to write radiance to context.\");\n            context.DestroyEvent(eventId);\n            if (!waitResult)\n                lightBakerResult = new LightBaker.Result {type = LightBaker.ResultType.IOFailed, message = \"Failed to write radiance to context.\"};\n\n            return lightBakerResult.ConvertToIProbeIntegratorResult();\n        }\n        public unsafe IProbeIntegrator.Result IntegrateIndirectRadiance(IDeviceContext context,\n            int positionOffset, int positionCount, int sampleCount, bool ignoreEnvironment,\n            BufferSlice<SphericalHarmonicsL2> radianceEstimateOut)\n        {\n            Debug.Assert(context is WintermuteContext, \"Expected WintermuteContext but got something else.\");\n            var wmContext = context as WintermuteContext;\n            using var positions = new NativeArray<Vector3>(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            BufferSlice<Vector3> offsetPositions = _positions;\n            offsetPositions.Offset += (ulong)positionOffset;\n            EventID eventId = context.CreateEvent();\n            context.ReadBuffer(offsetPositions, positions, eventId);\n            bool waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to read positions from context.\");\n            context.DestroyEvent(eventId);\n            var positionsPtr = (Vector3*)NativeArrayUnsafeUtility.GetUnsafePtr(positions);\n            using var radianceBuffer = new NativeArray<Rendering.SphericalHarmonicsL2>(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            void* shPtr = NativeArrayUnsafeUtility.GetUnsafePtr(radianceBuffer);\n            int directSampleCount = 0;\n            bool ignoreDirectEnvironment = ignoreEnvironment;\n            bool ignoreIndirectEnvironment = ignoreEnvironment;\n            int giSampleCount = sampleCount;\n            int envSampleCount = sampleCount;\n            var lightBakerResult = LightBaker.IntegrateProbeIndirectRadianceWintermute(positionsPtr, _integrationContext, positionCount, _pushoff,\n                _bounceCount, directSampleCount, giSampleCount, envSampleCount, ignoreDirectEnvironment, ignoreIndirectEnvironment, wmContext, _progress, shPtr);\n\n            // TODO: Fix this in LIGHT-1479, synchronization and read-back should be done by the user.\n            if (lightBakerResult.type != LightBaker.ResultType.Success)\n                return lightBakerResult.ConvertToIProbeIntegratorResult();\n\n            eventId = context.CreateEvent();\n            context.WriteBuffer(radianceEstimateOut, radianceBuffer, eventId);\n            waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to write radiance to context.\");\n            context.DestroyEvent(eventId);\n            if (!waitResult)\n                lightBakerResult = new LightBaker.Result {type = LightBaker.ResultType.IOFailed, message = \"Failed to write radiance to context.\"};\n\n            return lightBakerResult.ConvertToIProbeIntegratorResult();\n        }\n        public unsafe IProbeIntegrator.Result IntegrateValidity(IDeviceContext context,\n            int positionOffset, int positionCount, int sampleCount, BufferSlice<float> validityEstimateOut)\n        {\n            Debug.Assert(context is WintermuteContext, \"Expected RadeonRaysContext but got something else.\");\n            var wmContext = context as WintermuteContext;\n            using var positions = new NativeArray<Vector3>(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            BufferSlice<Vector3> offsetPositions = _positions;\n            offsetPositions.Offset += (ulong)positionOffset;\n            EventID eventId = context.CreateEvent();\n            context.ReadBuffer(offsetPositions, positions, eventId);\n            bool waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to read positions from context.\");\n            context.DestroyEvent(eventId);\n            void* positionsPtr = NativeArrayUnsafeUtility.GetUnsafePtr(positions);\n            using var validityBuffer = new NativeArray<float>(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            void* validityPtr = NativeArrayUnsafeUtility.GetUnsafePtr(validityBuffer);\n            int directSampleCount = 0;\n            int giSampleCount = sampleCount;\n            int envSampleCount = 0;\n            var lightBakerResult = LightBaker.IntegrateProbeValidityWintermute(positionsPtr, _integrationContext, positionCount, _pushoff,\n                _bounceCount, directSampleCount, giSampleCount, envSampleCount, wmContext, _progress, validityPtr);\n            \n            // TODO: Fix this in LIGHT-1479, synchronization and read-back should be done by the user.\n            if (lightBakerResult.type != LightBaker.ResultType.Success)\n                return lightBakerResult.ConvertToIProbeIntegratorResult();\n\n            eventId = context.CreateEvent();\n            context.WriteBuffer(validityEstimateOut, validityBuffer, eventId);\n            waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to write validity to context.\");\n            context.DestroyEvent(eventId);\n            if (!waitResult)\n                lightBakerResult = new LightBaker.Result {type = LightBaker.ResultType.IOFailed, message = \"Failed to write validity to context.\"};\n\n            return lightBakerResult.ConvertToIProbeIntegratorResult();\n        }\n\n        public unsafe IProbeIntegrator.Result IntegrateOcclusion(IDeviceContext context, int positionOffset, int positionCount, int sampleCount,\n            int maxLightsPerProbe, BufferSlice<int> perProbeLightIndices, BufferSlice<float> probeOcclusionEstimateOut)\n        {\n            Debug.Assert(context is WintermuteContext, \"Expected RadeonRaysContext but got something else.\");\n            var wmContext = context as WintermuteContext;\n            Debug.Assert(maxLightsPerProbe == 4, \"WintermuteProbeIntegrator only supports 4 light per probe.\");\n            using var positions = new NativeArray<Vector3>(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            BufferSlice<Vector3> offsetPositions = _positions;\n            offsetPositions.Offset += (ulong)positionOffset;\n            EventID eventId = context.CreateEvent();\n            context.ReadBuffer(offsetPositions, positions, eventId);\n            bool waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to read positions from context.\");\n            context.DestroyEvent(eventId);\n            void* positionsPtr = NativeArrayUnsafeUtility.GetUnsafePtr(positions);\n\n            using var perProbeLightIndicesArray = new NativeArray<int>(positionCount * 4, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            eventId = context.CreateEvent();\n            context.ReadBuffer(perProbeLightIndices, perProbeLightIndicesArray, eventId);\n            waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to read indices from context.\");\n            context.DestroyEvent(eventId);\n            void* perProbeLightIndicesPtr = NativeArrayUnsafeUtility.GetUnsafePtr(perProbeLightIndicesArray);\n\n            using var occlusionBuffer = new NativeArray<float>(positionCount * maxLightsPerProbe, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            void* occlusionPtr = NativeArrayUnsafeUtility.GetUnsafePtr(occlusionBuffer);\n            int directSampleCount = sampleCount;\n            int giSampleCount = 0;\n            int envSampleCount = 0;\n            var lightBakerResult = LightBaker.IntegrateProbeOcclusionWintermute(positionsPtr, perProbeLightIndicesPtr, positionCount,\n                _pushoff, _bounceCount, directSampleCount, giSampleCount, envSampleCount, wmContext, _progress, occlusionPtr);\n\n            // TODO: Fix this in LIGHT-1479, synchronization and read-back should be done by the user.\n            if (lightBakerResult.type != LightBaker.ResultType.Success)\n                return lightBakerResult.ConvertToIProbeIntegratorResult();\n\n            eventId = context.CreateEvent();\n            context.WriteBuffer(probeOcclusionEstimateOut, occlusionBuffer, eventId);\n            waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to write validity to context.\");\n            context.DestroyEvent(eventId);\n            if (!waitResult)\n                lightBakerResult = new LightBaker.Result { type = LightBaker.ResultType.IOFailed, message = \"Failed to write validity to context.\" };\n\n            return lightBakerResult.ConvertToIProbeIntegratorResult();\n        }\n\n        public void Dispose()\n        {\n        }\n    }\n    public class RadeonRaysProbeIntegrator : IProbeIntegrator\n    {\n        private IntegrationContext _integrationContext;\n        private BufferSlice<Vector3> _positions;\n        private float _pushoff;\n        private int _bounceCount;\n        BakeProgressState _progress = null;\n        const int SizeOfFloat = 4;\n        const int SHL2RGBElements = 3 * 9;\n        const int SizeOfSHL2 = SizeOfFloat * SHL2RGBElements;\n        public void Prepare(IDeviceContext context, IWorld world, BufferSlice<Vector3> positions, float pushoff, int bounceCount)\n        {\n            Debug.Assert(world is RadeonRaysWorld);\n            var rrWorld = world as RadeonRaysWorld;\n            _integrationContext = rrWorld.GetIntegrationContext();\n            _positions = positions;\n            _pushoff = pushoff;\n            _bounceCount = bounceCount;\n        }\n        public void SetProgressReporter(BakeProgressState progress)\n        {\n            _progress = progress;\n        }\n        public unsafe IProbeIntegrator.Result IntegrateDirectRadiance(IDeviceContext context, int positionOffset, int positionCount, int sampleCount,\n            bool ignoreEnvironment, BufferSlice<SphericalHarmonicsL2> radianceEstimateOut)\n        {\n            Debug.Assert(context is RadeonRaysContext, \"Expected RadeonRaysContext but got something else.\");\n            var rrContext = context as RadeonRaysContext;\n            using var positions = new NativeArray<Vector3>(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            BufferSlice<Vector3> offsetPositions = _positions;\n            offsetPositions.Offset += (ulong)positionOffset;\n            EventID eventId = context.CreateEvent();\n            context.ReadBuffer(offsetPositions, positions, eventId);\n            bool waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to read positions from context.\");\n            context.DestroyEvent(eventId);\n            UnityEngine.Vector3* positionsPtr = (Vector3*)NativeArrayUnsafeUtility.GetUnsafePtr(positions);\n            using var radianceBuffer = new NativeArray<Rendering.SphericalHarmonicsL2>(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            void* shPtr = NativeArrayUnsafeUtility.GetUnsafePtr(radianceBuffer);\n            int directSampleCount = sampleCount;\n            int giSampleCount = 0;\n            int envSampleCount = 0;\n            bool ignoreDirectEnvironment = ignoreEnvironment;\n            bool ignoreIndirectEnvironment = ignoreEnvironment;\n            var lightBakerResult = LightBaker.IntegrateProbeDirectRadianceRadeonRays(positionsPtr, _integrationContext, positionCount, _pushoff,\n                _bounceCount, directSampleCount, giSampleCount, envSampleCount, ignoreDirectEnvironment, ignoreIndirectEnvironment, rrContext, _progress, shPtr);\n\n            // TODO: Fix this in LIGHT-1479, synchronization and read-back should be done by the user.\n            if (lightBakerResult.type != LightBaker.ResultType.Success)\n                return lightBakerResult.ConvertToIProbeIntegratorResult();\n\n            eventId = context.CreateEvent();\n            context.WriteBuffer(radianceEstimateOut, radianceBuffer, eventId);\n            waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to write radiance to context.\");\n            context.DestroyEvent(eventId);\n            if (!waitResult)\n                lightBakerResult = new LightBaker.Result {type = LightBaker.ResultType.IOFailed, message = \"Failed to write radiance to context.\"};\n\n            return lightBakerResult.ConvertToIProbeIntegratorResult();\n        }\n\n        public unsafe IProbeIntegrator.Result IntegrateIndirectRadiance(IDeviceContext context, int positionOffset, int positionCount, int sampleCount,\n            bool ignoreEnvironment, BufferSlice<SphericalHarmonicsL2> radianceEstimateOut)\n        {\n            Debug.Assert(context is RadeonRaysContext, \"Expected RadeonRaysContext but got something else.\");\n            var rrContext = context as RadeonRaysContext;\n            using var positions = new NativeArray<Vector3>(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            BufferSlice<Vector3> offsetPositions = _positions;\n            offsetPositions.Offset += (ulong)positionOffset;\n            EventID eventId = context.CreateEvent();\n            context.ReadBuffer(offsetPositions, positions, eventId);\n            bool waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to read positions from context.\");\n            context.DestroyEvent(eventId);\n            UnityEngine.Vector3* positionsPtr = (Vector3*)NativeArrayUnsafeUtility.GetUnsafePtr(positions);\n            using var radianceBuffer = new NativeArray<Rendering.SphericalHarmonicsL2>(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            void* shPtr = NativeArrayUnsafeUtility.GetUnsafePtr(radianceBuffer);\n            int directSampleCount = 0;\n            bool ignoreDirectEnvironment = ignoreEnvironment;\n            bool ignoreIndirectEnvironment = ignoreEnvironment;\n            int giSampleCount = sampleCount;\n            int envSampleCount = sampleCount;\n            var lightBakerResult = LightBaker.IntegrateProbeIndirectRadianceRadeonRays(positionsPtr, _integrationContext, positionCount, _pushoff,\n                _bounceCount, directSampleCount, giSampleCount, envSampleCount, ignoreDirectEnvironment, ignoreIndirectEnvironment, rrContext, _progress, shPtr);\n\n            // TODO: Fix this in LIGHT-1479, synchronization and read-back should be done by the user.\n            if (lightBakerResult.type != LightBaker.ResultType.Success)\n                return lightBakerResult.ConvertToIProbeIntegratorResult();\n\n            eventId = context.CreateEvent();\n            context.WriteBuffer(radianceEstimateOut, radianceBuffer, eventId);\n            waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to write radiance to context.\");\n            context.DestroyEvent(eventId);\n            if (!waitResult)\n                lightBakerResult = new LightBaker.Result {type = LightBaker.ResultType.IOFailed, message = \"Failed to write radiance to context.\"};\n\n            return lightBakerResult.ConvertToIProbeIntegratorResult();\n        }\n        public unsafe IProbeIntegrator.Result IntegrateValidity(IDeviceContext context,\n            int positionOffset, int positionCount, int sampleCount, BufferSlice<float> validityEstimateOut)\n        {\n            Debug.Assert(context is RadeonRaysContext, \"Expected RadeonRaysContext but got something else.\");\n            var rrContext = context as RadeonRaysContext;\n            using var positions = new NativeArray<Vector3>(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            BufferSlice<Vector3> offsetPositions = _positions;\n            offsetPositions.Offset += (ulong)positionOffset;\n            EventID eventId = context.CreateEvent();\n            context.ReadBuffer(offsetPositions, positions, eventId);\n            bool waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to read positions from context.\");\n            context.DestroyEvent(eventId);\n            void* positionsPtr = NativeArrayUnsafeUtility.GetUnsafePtr(positions);\n            using var validityBuffer = new NativeArray<float>(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            void* validityPtr = NativeArrayUnsafeUtility.GetUnsafePtr(validityBuffer);\n            int directSampleCount = 0;\n            int giSampleCount = sampleCount;\n            int envSampleCount = 0;\n            var lightBakerResult = LightBaker.IntegrateProbeValidityRadeonRays(positionsPtr, _integrationContext, positionCount, _pushoff,\n                _bounceCount, directSampleCount, giSampleCount, envSampleCount, rrContext, _progress, validityPtr);\n\n            // TODO: Fix this in LIGHT-1479, synchronization and read-back should be done by the user.\n            if (lightBakerResult.type != LightBaker.ResultType.Success)\n                return lightBakerResult.ConvertToIProbeIntegratorResult();\n\n            eventId = context.CreateEvent();\n            context.WriteBuffer(validityEstimateOut, validityBuffer, eventId);\n            waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to write validity to context.\");\n            context.DestroyEvent(eventId);\n            if (!waitResult)\n                lightBakerResult = new LightBaker.Result {type = LightBaker.ResultType.IOFailed, message = \"Failed to write validity to context.\"};\n\n            return lightBakerResult.ConvertToIProbeIntegratorResult();\n        }\n\n        public unsafe IProbeIntegrator.Result IntegrateOcclusion(IDeviceContext context, int positionOffset, int positionCount, int sampleCount,\n            int maxLightsPerProbe, BufferSlice<int> perProbeLightIndices, BufferSlice<float> probeOcclusionEstimateOut)\n        {\n            Debug.Assert(context is RadeonRaysContext, \"Expected RadeonRaysContext but got something else.\");\n            var rrContext = context as RadeonRaysContext;\n            Debug.Assert(maxLightsPerProbe == 4, \"RadeonRaysProbeIntegrator only supports 4 light per probe.\");\n            using var positions = new NativeArray<Vector3>(positionCount, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            BufferSlice<Vector3> offsetPositions = _positions;\n            offsetPositions.Offset += (ulong)positionOffset;\n            EventID eventId = context.CreateEvent();\n            context.ReadBuffer(offsetPositions, positions, eventId);\n            bool waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to read positions from context.\");\n            context.DestroyEvent(eventId);\n            void* positionsPtr = NativeArrayUnsafeUtility.GetUnsafePtr(positions);\n\n            using var perProbeLightIndicesArray = new NativeArray<int>(positionCount * 4, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            eventId = context.CreateEvent();\n            context.ReadBuffer(perProbeLightIndices, perProbeLightIndicesArray, eventId);\n            waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to read indices from context.\");\n            context.DestroyEvent(eventId);\n            void* perProbeLightIndicesPtr = NativeArrayUnsafeUtility.GetUnsafePtr(perProbeLightIndicesArray);\n\n            using var occlusionBuffer = new NativeArray<float>(positionCount * maxLightsPerProbe, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);\n            void* occlusionPtr = NativeArrayUnsafeUtility.GetUnsafePtr(occlusionBuffer);\n            int directSampleCount = sampleCount;\n            int giSampleCount = 0;\n            int envSampleCount = 0;\n            var lightBakerResult = LightBaker.IntegrateProbeOcclusionRadeonRays(positionsPtr, perProbeLightIndicesPtr, positionCount,\n                _pushoff, _bounceCount, directSampleCount, giSampleCount, envSampleCount, rrContext, _progress, occlusionPtr);\n\n            if (lightBakerResult.type != LightBaker.ResultType.Success)\n                return lightBakerResult.ConvertToIProbeIntegratorResult();\n\n            eventId = context.CreateEvent();\n            context.WriteBuffer(probeOcclusionEstimateOut, occlusionBuffer, eventId);\n            // TODO: Fix this in LIGHT-1479, synchronization and read-back should be done by the user.\n            waitResult = context.Wait(eventId);\n            Debug.Assert(waitResult, \"Failed to write validity to context.\");\n            context.DestroyEvent(eventId);\n            if (!waitResult)\n                lightBakerResult = new LightBaker.Result { type = LightBaker.ResultType.IOFailed, message = \"Failed to write validity to context.\" };\n\n            return lightBakerResult.ConvertToIProbeIntegratorResult();\n        }\n\n        public void Dispose()\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/ProgressState.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine.Bindings;\n\nnamespace UnityEngine.LightTransport\n{\n    [StructLayout(LayoutKind.Sequential)]\n    public class BakeProgressState : IDisposable\n    {\n        [NativeMethod(IsThreadSafe = true)]\n        static extern IntPtr Internal_Create();\n\n        [NativeMethod(IsThreadSafe = true)]\n        static extern void Internal_Destroy(IntPtr ptr);\n\n        internal IntPtr m_Ptr;\n        internal bool m_OwnsPtr;\n\n        public BakeProgressState()\n        {\n            m_Ptr = Internal_Create();\n            m_OwnsPtr = true;\n        }\n        private BakeProgressState(IntPtr ptr)\n        {\n            m_Ptr = ptr;\n            m_OwnsPtr = false;\n        }\n        ~BakeProgressState()\n        {\n            Destroy();\n        }\n        public void Dispose()\n        {\n            Destroy();\n            GC.SuppressFinalize(this);\n        }\n        void Destroy()\n        {\n            if (m_OwnsPtr && m_Ptr != IntPtr.Zero)\n            {\n                Internal_Destroy(m_Ptr);\n                m_Ptr = IntPtr.Zero;\n            }\n        }\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(BakeProgressState obj) => obj.m_Ptr;\n        }\n\n        [NativeMethod(IsThreadSafe = true)]\n        public extern void Cancel();\n\n        [NativeMethod(IsThreadSafe = true)]\n        public extern float Progress();\n\n        [NativeMethod(IsThreadSafe = true)]\n        public extern void SetTotalWorkSteps(UInt64 total);\n\n        [NativeMethod(IsThreadSafe = true)]\n        public extern void IncrementCompletedWorkSteps(UInt64 steps);\n\n        [NativeMethod(IsThreadSafe = true)]\n        public extern bool WasCancelled();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/RadeonRaysDeviceContext.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing Unity.Collections;\nusing Unity.Collections.LowLevel.Unsafe;\nusing UnityEngine.Bindings;\n\nnamespace UnityEngine.LightTransport\n{\n    [StructLayout(LayoutKind.Sequential)]\n    public class RadeonRaysContext : IDeviceContext\n    {\n        internal IntPtr m_Ptr;\n        internal bool m_OwnsPtr;\n\n        [NativeMethod(IsThreadSafe = true)]\n        static extern IntPtr Internal_Create();\n\n        [NativeMethod(IsThreadSafe = true)]\n        static extern void Internal_Destroy(IntPtr ptr);\n\n        public RadeonRaysContext()\n        {\n            m_Ptr = Internal_Create();\n            m_OwnsPtr = true;\n        }\n        public RadeonRaysContext(IntPtr ptr)\n        {\n            m_Ptr = ptr;\n            m_OwnsPtr = false;\n        }\n        ~RadeonRaysContext()\n        {\n            Destroy();\n        }\n        public void Dispose()\n        {\n            Destroy();\n            GC.SuppressFinalize(this);\n        }\n        void Destroy()\n        {\n            if (m_OwnsPtr && m_Ptr != IntPtr.Zero)\n            {\n                Internal_Destroy(m_Ptr);\n                m_Ptr = IntPtr.Zero;\n            }\n        }\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(RadeonRaysContext obj) => obj.m_Ptr;\n        }\n\n        [NativeMethod(IsThreadSafe = true)]\n        public extern bool Initialize();\n\n        [NativeMethod(IsThreadSafe = true)]\n        public extern BufferID CreateBuffer(UInt64 count, UInt64 stride);\n\n        [NativeMethod(IsThreadSafe = true)]\n        public extern void DestroyBuffer(BufferID id);\n\n        [NativeMethod(IsThreadSafe = true)]\n        private unsafe extern void EnqueueBufferRead(BufferID id, void* result, UInt64 length, UInt64 offset, EventID* eventId);\n\n        public unsafe void ReadBuffer<T>(BufferSlice<T> src, NativeArray<T> dst)\n            where T: struct\n        {\n            void* ptr = NativeArrayUnsafeUtility.GetUnsafePtr(dst);\n            UInt64 sizeofElem = (UInt64)UnsafeUtility.SizeOf<T>();\n            EnqueueBufferRead(src.Id, ptr, (UInt64)dst.Length * sizeofElem, src.Offset * sizeofElem, null);\n        }\n\n        public unsafe void ReadBuffer<T>(BufferSlice<T> src, NativeArray<T> dst, EventID id)\n            where T : struct\n        {\n            void* ptr = NativeArrayUnsafeUtility.GetUnsafePtr(dst);\n            UInt64 sizeofElem = (UInt64)UnsafeUtility.SizeOf<T>();\n            EnqueueBufferRead(src.Id, ptr, (UInt64)dst.Length * sizeofElem, src.Offset * sizeofElem, &id);\n        }\n\n        [NativeMethod(IsThreadSafe = true)]\n        private extern unsafe void EnqueueBufferWrite(BufferID id, void* result, UInt64 length, UInt64 offset, EventID* eventId);\n\n        public unsafe void WriteBuffer<T>(BufferSlice<T> dst, NativeArray<T> src)\n            where T: struct\n        {\n            void* ptr = NativeArrayUnsafeUtility.GetUnsafePtr(src);\n            UInt64 sizeofElem = (UInt64)UnsafeUtility.SizeOf<T>();\n            EnqueueBufferWrite(dst.Id, ptr, (UInt64)src.Length * sizeofElem, dst.Offset * sizeofElem, null);\n        }\n\n        public unsafe void WriteBuffer<T>(BufferSlice<T> dst, NativeArray<T> src, EventID id)\n            where T : struct\n        {\n            void* ptr = NativeArrayUnsafeUtility.GetUnsafePtr(src);\n            UInt64 sizeofElem = (UInt64)UnsafeUtility.SizeOf<T>();\n            EnqueueBufferWrite(dst.Id, ptr, (UInt64)src.Length * sizeofElem, dst.Offset * sizeofElem, &id);\n        }\n\n        [NativeMethod(IsThreadSafe = true, Name = \"CreateEventInternal\")]\n        public extern EventID CreateEvent();\n\n        [NativeMethod(IsThreadSafe = true)]\n        public extern void DestroyEvent(EventID id);\n\n        [NativeMethod(IsThreadSafe = true)]\n        public extern bool IsCompleted(EventID id);\n\n        [NativeMethod(IsThreadSafe = true)]\n\t\tpublic extern bool Wait(EventID id);\n\n\t\t[NativeMethod(IsThreadSafe = true)]\n        public extern bool Flush();\n\n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern bool InitializePostProcessingInternal(RadeonRaysContext context);\n        \n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern bool ConvolveRadianceToIrradianceInternal(RadeonRaysContext context, BufferID radianceIn, BufferID irradianceOut, int probeCount);\n        \n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern bool ConvertToUnityFormatInternal(RadeonRaysContext context, BufferID irradianceIn, BufferID irradianceOut, int probeCount);\n        \n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern bool AddSphericalHarmonicsL2Internal(RadeonRaysContext context, BufferID a, BufferID b, BufferID sum, int probeCount);\n\n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern bool ScaleSphericalHarmonicsL2Internal(RadeonRaysContext context, BufferID shIn, BufferID shOut, int probeCount, float scale);\n\n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern bool WindowSphericalHarmonicsL2Internal(RadeonRaysContext context, BufferID shIn, BufferID shOut, int probeCount);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/RadeonRaysLightBaker.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor.LightBaking\n{\n    [NativeHeader(\"Editor/Src/GI/LightBaker/LightBaker.Bindings.h\")]\n    internal static partial class LightBaker\n    {\n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern Result PopulateWorldRadeonRays(BakeInput bakeInput, LightmapRequests lightmapRequests, LightProbeRequests lightProbeRequests, UnityEngine.LightTransport.BakeProgressState progress,\n            UnityEngine.LightTransport.RadeonRaysContext context, UnityEngine.LightTransport.IntegrationContext world);\n\n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern unsafe Result IntegrateProbeDirectRadianceRadeonRays(void* positions, UnityEngine.LightTransport.IntegrationContext integrationContext,\n            int positionCount, float pushoff, int bounceCount, int directSampleCount, int giSampleCount, int envSampleCount,\n            bool ignoreDirectEnvironment, bool ignoreIndirectEnvironment,\n            UnityEngine.LightTransport.RadeonRaysContext context, UnityEngine.LightTransport.BakeProgressState progress, void* radianceBufferOut);\n\n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern unsafe Result IntegrateProbeIndirectRadianceRadeonRays(void* positions, UnityEngine.LightTransport.IntegrationContext integrationContext,\n            int positionCount, float pushoff, int bounceCount, int directSampleCount, int giSampleCount, int envSampleCount,\n            bool ignoreDirectEnvironment, bool ignoreIndirectEnvironment,\n            UnityEngine.LightTransport.RadeonRaysContext context, UnityEngine.LightTransport.BakeProgressState progress, void* radianceBufferOut);\n\n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern unsafe Result IntegrateProbeValidityRadeonRays(void* positions, UnityEngine.LightTransport.IntegrationContext integrationContext,\n            int positionCount, float pushoff, int bounceCount, int directSampleCount, int giSampleCount, int envSampleCount,\n            UnityEngine.LightTransport.RadeonRaysContext context, UnityEngine.LightTransport.BakeProgressState progress, void* validityBufferOut);\n\n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern unsafe Result IntegrateProbeOcclusionRadeonRays(void* positions, void* probeLightIndices,\n            int positionCount, float pushoff, int bounceCount, int directSampleCount, int giSampleCount, int envSampleCount,\n            UnityEngine.LightTransport.RadeonRaysContext context, UnityEngine.LightTransport.BakeProgressState progress, void* occlusionBufferOut);       \n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/UnityComputeBake.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Reflection;\nusing System.Threading;\nusing UnityEngine.Assertions;\nusing UnityEngine.LightTransport;\nusing UnityEngine.Scripting;\nusing Debug = UnityEngine.Debug;\nusing static UnityEditor.LightBaking.LightBaker;\n\nnamespace UnityEditor.LightBaking\n{\n    internal static class UnityComputeBake\n    {\n        [RequiredByNativeCode]\n        internal static bool BakeWithDummyProgress(string bakeInputPath, string lightmapRequestsPath, string lightProbeRequestsPath, string bakeOutputFolderPath)\n        {\n            using BakeProgressState dummyProgressState = new();\n            bool success = Bake(bakeInputPath, lightmapRequestsPath, lightProbeRequestsPath, bakeOutputFolderPath, dummyProgressState);\n\n            return success;\n        }\n\n        [RequiredByNativeCode]\n        internal static bool Bake(string bakeInputPath, string lightmapRequestsPath, string lightProbeRequestsPath, string bakeOutputFolderPath, BakeProgressState progressState)\n        {\n            Type strangler = Type.GetType(\"UnityEditor.PathTracing.LightBakerBridge.LightBakerStrangler, Unity.PathTracing.Editor\");\n            if (strangler == null)\n                return false;\n\n            MethodInfo bakeMethod = strangler.GetMethod(\"Bake\", BindingFlags.Static | BindingFlags.NonPublic);\n            if (bakeMethod == null)\n                return false;\n\n            var bakeFunc = (Func<string, string, string, string, BakeProgressState, bool>)Delegate.CreateDelegate(typeof(Func<string, string, string, string, BakeProgressState, bool>), bakeMethod);\n            return bakeFunc(bakeInputPath, lightmapRequestsPath, lightProbeRequestsPath, bakeOutputFolderPath, progressState);\n        }\n\n        [RequiredByNativeCode]\n        internal static bool BakeViaCommandLineParameters()\n        {\n            const string lightBakerWorkerProcess = \"[LightBaker worker process] \";\n\n            using ExternalProcessConnection bakeResultConnection = CreateConnectionToParentProcess(\"-bakePortNumber\");\n            using ExternalProcessConnection progressConnection = CreateConnectionToParentProcess(\"-progressPortNumber\");\n\n            try\n            {\n                // Report that we are connected.\n                ReportResult(new Result { type = ResultType.ConnectedToBaker, message = \"Successfully connected to the parent process.\" }, bakeResultConnection);\n\n                string bakeInputPath = TryFindArgument(\"-bakeInput\");\n                if (string.IsNullOrEmpty(bakeInputPath))\n                    return ReportResult(new Result { type = ResultType.InvalidInput, message = \"No bake input path was passed as an argument.\" }, bakeResultConnection);\n\n                string lightmapRequestsPath = TryFindArgument(\"-lightmapRequests\");\n                if (string.IsNullOrEmpty(lightmapRequestsPath))\n                    return ReportResult(new Result { type = ResultType.InvalidInput, message = \"No lightmap requests path was passed as an argument.\" }, bakeResultConnection);\n\n                string lightProbeRequestsPath = TryFindArgument(\"-lightProbeRequests\");\n                if (string.IsNullOrEmpty(lightProbeRequestsPath))\n                    return ReportResult(new Result { type = ResultType.InvalidInput, message = \"No light probe requests path was passed as an argument.\" }, bakeResultConnection);\n\n                string bakeOutputFolderPath = TryFindArgument(\"-bakeOutputFolderPath\");\n                if (string.IsNullOrEmpty(bakeOutputFolderPath))\n                    return ReportResult(new Result { type = ResultType.InvalidInput, message = \"No bake output folder path was passed as an argument.\" }, bakeResultConnection);\n\n                // Prepare to capture progress work steps.\n                using BakeProgressState progressState = new ();\n\n                // Prepare to report progress.\n                using CancellationTokenSource progressReporterTokenSource = new CancellationTokenSource();\n                Thread progressReporterThread = new (() => ProgressReporterThreadFunction(progressState, progressReporterTokenSource.Token, progressConnection));\n                progressReporterThread.Start();\n\n                Result result = new ()\n                {\n                    type = Bake(bakeInputPath, lightmapRequestsPath, lightProbeRequestsPath, bakeOutputFolderPath, progressState) ? ResultType.Success : ResultType.JobFailed\n                };\n\n                // Report the result after cancel of the progress reporter when we are finished baking.\n                progressReporterTokenSource.Cancel();\n                ReportResult(result, bakeResultConnection);\n            }\n            catch (Exception e)\n            {\n                ReportResult(new Result { type = ResultType.JobFailed, message = $\"An exception was thrown '{e.Message}'.\" }, bakeResultConnection);\n            }\n            finally\n            {\n                const int waitForTheResultToBeReceivedByTheCallerMs = 100;\n                Thread.Sleep(waitForTheResultToBeReceivedByTheCallerMs);\n            }\n\n            return true;\n\n            static ExternalProcessConnection CreateConnectionToParentProcess(string portNumberArgument)\n            {\n                string portNumberArgumentValue = TryFindArgument(portNumberArgument);\n                bool portNumberWasPassed = !string.IsNullOrEmpty(portNumberArgumentValue);\n                Debug.Log($\"{lightBakerWorkerProcess}No '{portNumberArgument}' was passed as an argument, will not report to the parent process.\");\n                if (!portNumberWasPassed)\n                    return null;\n                bool portNumberWasParsed = int.TryParse(portNumberArgumentValue, out int portNumber);\n                Assert.IsTrue(portNumberWasParsed, $\"{lightBakerWorkerProcess}The '{portNumberArgument} passed as an argument was invalid, cannot report to the parent process.\");\n                if (!portNumberWasParsed)\n                    return null;\n                ExternalProcessConnection connection = new();\n                bool connected = connection.Connect(portNumber);\n                if (!connected)\n                    Debug.Log($\"{lightBakerWorkerProcess}Failed to connect to the parent process '{portNumberArgumentValue}'.\");\n\n                return connection;\n            }\n\n            static void ProgressReporterThreadFunction(BakeProgressState bakeProgressState, CancellationToken cancelToken, ExternalProcessConnection connection)\n            {\n                if (connection == null)\n                    return;\n                const int waitBetweenProgressReportsMs = 100;\n                while (!cancelToken.IsCancellationRequested)\n                {\n                    float progress = bakeProgressState.Progress();\n                    ReportProgressToParentProcess(progress, connection);\n                    Thread.Sleep(waitBetweenProgressReportsMs);\n                }\n            }\n\n            static string TryFindArgument(string argument)\n            {\n                string[] args = Environment.GetCommandLineArgs();\n                for (int i = 0; i < args.Length; i++)\n                    if (0 == string.Compare(args[i], argument, StringComparison.InvariantCultureIgnoreCase))\n                        if (i < args.Length - 1 && !args[i + 1].StartsWith(\"-\"))\n                            return args[i + 1];\n\n                return string.Empty;\n            }\n\n            static bool ReportResult(Result result, ExternalProcessConnection connection)\n            {\n                if (connection == null)\n                    return true;\n                if (result.type == ResultType.Success)\n                    if (string.IsNullOrEmpty(result.message))\n                        result.message = \"Success.\";\n                bool sentResult = ReportResultToParentProcess(result, connection);\n                Assert.IsTrue(sentResult, $\"{lightBakerWorkerProcess}Failed to report a result to the parent process.\");\n                Debug.Log($\"{lightBakerWorkerProcess}Reported result to the parent process: ({result.type}, '{result.message}')\");\n\n                return sentResult;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/WintermuteDeviceContext.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing Unity.Collections;\nusing Unity.Collections.LowLevel.Unsafe;\nusing UnityEngine.Bindings;\nusing UnityEngine.Rendering;\n\nnamespace UnityEngine.LightTransport\n{\n    [StructLayout(LayoutKind.Sequential)]\n    internal class WintermuteContext : IDeviceContext\n    {\n        internal IntPtr m_Ptr;\n        internal bool m_OwnsPtr;\n        private Dictionary<BufferID, NativeArray<byte>> buffers = new();\n        private uint nextFreeBufferId;\n        private uint nextFreeEventId;\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(WintermuteContext obj) => obj.m_Ptr;\n        }\n\n        [NativeMethod(IsThreadSafe = true)]\n        static extern IntPtr Internal_Create();\n\n        [NativeMethod(IsThreadSafe = true)]\n        static extern void Internal_Destroy(IntPtr ptr);\n\n        public WintermuteContext()\n        {\n            m_Ptr = Internal_Create();\n            m_OwnsPtr = true;\n        }\n        public WintermuteContext(IntPtr ptr)\n        {\n            m_Ptr = ptr;\n            m_OwnsPtr = false;\n        }\n        ~WintermuteContext()\n        {\n            Destroy();\n        }\n        public void Dispose()\n        {\n            Destroy();\n            GC.SuppressFinalize(this);\n        }\n        void Destroy()\n        {\n            if (m_OwnsPtr && m_Ptr != IntPtr.Zero)\n            {\n                Internal_Destroy(m_Ptr);\n                m_Ptr = IntPtr.Zero;\n            }\n        }\n\n        [NativeMethod(IsThreadSafe = true)]\n        public extern bool Initialize();\n\n        public BufferID CreateBuffer(UInt64 count, UInt64 stride)\n        {\n            Debug.Assert(count != 0, \"Buffer element count cannot be zero.\");\n            Debug.Assert(stride != 0, \"Buffer stride cannot be zero.\");\n            var buffer = new NativeArray<byte>((int)(count * stride), Allocator.Persistent);\n            var idInteger = nextFreeBufferId++;\n            var id = new BufferID(idInteger);\n            buffers[id] = buffer;\n            return id;\n        }\n\n        public void DestroyBuffer(BufferID id)\n        {\n            Debug.Assert(buffers.ContainsKey(id), \"Invalid buffer ID given.\");\n            buffers[id].Dispose();\n            buffers.Remove(id);\n        }\n\n        public void WriteBuffer<T>(BufferSlice<T> dst, NativeArray<T> src)\n            where T : struct\n        {\n            Debug.Assert(buffers.ContainsKey(dst.Id), \"Invalid buffer ID given.\");\n            var dstBuffer = buffers[dst.Id].Reinterpret<T>(1);\n            dstBuffer.GetSubArray((int)dst.Offset, dstBuffer.Length - (int)dst.Offset).CopyFrom(src);\n        }\n\n        public void ReadBuffer<T>(BufferSlice<T> src, NativeArray<T> dst)\n            where T : struct\n        {\n            Debug.Assert(buffers.ContainsKey(src.Id), \"Invalid buffer ID given.\");\n            var srcBuffer = buffers[src.Id].Reinterpret<T>(1);\n            dst.CopyFrom(srcBuffer.GetSubArray((int)src.Offset, srcBuffer.Length - (int)src.Offset));\n        }\n\n        public void WriteBuffer<T>(BufferSlice<T> dst, NativeArray<T> src, EventID id)\n            where T : struct\n        {\n            WriteBuffer(dst, src);\n        }\n\n        public void ReadBuffer<T>(BufferSlice<T> src, NativeArray<T> dst, EventID id)\n            where T : struct\n        {\n            ReadBuffer(src, dst);\n        }\n\n        public EventID CreateEvent()\n        {\n            return new EventID(nextFreeEventId++);\n        }\n\n        public void DestroyEvent(EventID id)\n        {\n        }\n\n        public bool IsCompleted(EventID id)\n        {\n            return true;\n        }\n\n        public bool Wait(EventID id)\n        {\n            return true;\n        }\n\n        public NativeArray<byte> GetNativeArray(BufferID id)\n        {\n            return buffers[id];\n        }\n\n        public bool Flush()\n        {\n            return true;\n        }\n\n        [NativeMethod(IsThreadSafe = true)]\n        internal static unsafe extern bool DeringSphericalHarmonicsL2Internal(SphericalHarmonicsL2* shIn, SphericalHarmonicsL2* shOut, int probeCount);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/WintermuteLightBaker.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor.LightBaking\n{\n    [NativeHeader(\"Editor/Src/GI/LightBaker/LightBaker.Bindings.h\")]\n    internal static partial class LightBaker\n    {\n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern Result PopulateWorldWintermute(BakeInput bakeInput, LightmapRequests lightmapRequests, LightProbeRequests lightProbeRequests, UnityEngine.LightTransport.BakeProgressState progress,\n            UnityEngine.LightTransport.WintermuteContext context, UnityEngine.LightTransport.IntegrationContext world);\n\n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern unsafe Result IntegrateProbeDirectRadianceWintermute(UnityEngine.Vector3* positions, UnityEngine.LightTransport.IntegrationContext integrationContext,\n            int positionCount, float pushoff, int bounceCount, int directSampleCount, int giSampleCount, int envSampleCount,\n            bool ignoreDirectEnvironment, bool ignoreIndirectEnvironment,\n            UnityEngine.LightTransport.WintermuteContext context, UnityEngine.LightTransport.BakeProgressState progress, void* radianceBufferOut);\n\n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern unsafe Result IntegrateProbeIndirectRadianceWintermute(UnityEngine.Vector3* positions, UnityEngine.LightTransport.IntegrationContext integrationContext,\n            int positionCount, float pushoff, int bounceCount, int directSampleCount, int giSampleCount, int envSampleCount,\n            bool ignoreDirectEnvironment, bool ignoreIndirectEnvironment,\n            UnityEngine.LightTransport.WintermuteContext context, UnityEngine.LightTransport.BakeProgressState progress, void* radianceBufferOut);\n\n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern unsafe Result IntegrateProbeValidityWintermute(void* positions, UnityEngine.LightTransport.IntegrationContext integrationContext,\n            int positionCount, float pushoff, int bounceCount, int directSampleCount, int giSampleCount, int envSampleCount,\n            UnityEngine.LightTransport.WintermuteContext context, UnityEngine.LightTransport.BakeProgressState progress, void* validityBufferOut);\n\n        [NativeMethod(IsThreadSafe = true)]\n        internal static extern unsafe Result IntegrateProbeOcclusionWintermute(void* positions, void* probeLightIndices,\n            int positionCount, float pushoff, int bounceCount, int directSampleCount, int giSampleCount, int envSampleCount,\n            UnityEngine.LightTransport.WintermuteContext context, UnityEngine.LightTransport.BakeProgressState progress, void* occlusionBufferOut);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GI/World.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEngine.LightTransport\n{\n    public interface IWorld : IDisposable\n    {\n        // Functionality like AddInstance/RemoveInstance will be added in the future.\n    }\n    internal class WintermuteWorld : IWorld\n    {\n        private IntegrationContext integrationContext;\n\n        public void Dispose()\n        {\n        }\n\n        public IntegrationContext GetIntegrationContext()\n        {\n            return integrationContext;\n        }\n        public void SetIntegrationContext(IntegrationContext context)\n        {\n            integrationContext = context;\n        }\n    }\n    public class RadeonRaysWorld : IWorld\n    {\n        private IntegrationContext integrationContext;\n\n        public void Dispose()\n        {\n        }\n\n        public IntegrationContext GetIntegrationContext()\n        {\n            return integrationContext;\n        }\n        public void SetIntegrationContext(IntegrationContext context)\n        {\n            integrationContext = context;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/AboutWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing UnityEditor.Experimental;\nusing UnityEditorInternal;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    internal class AboutWindow : EditorWindow\n    {\n        const int VersionBoxLineHeight = 13;\n        const int VersionBoxHeight = VersionBoxLineHeight * 4;\n        static readonly Vector2 WindowSize = new Vector2(573, 545);\n        private const string AboutTitle = \"\";\n\n        [RequiredByNativeCode]\n        internal static void ShowAboutWindow()\n        {\n            var mainWindowRect = EditorGUIUtility.GetMainWindowPosition();\n            var aboutRect = EditorGUIUtility.GetCenteredWindowPosition(mainWindowRect, WindowSize);\n\n            AboutWindow w = GetWindowWithRect<AboutWindow>(aboutRect, true, AboutTitle);\n            w.position = aboutRect;\n            w.minSize = w.maxSize = WindowSize;\n            w.m_Parent.window.m_DontSaveToLayout = true;\n        }\n\n        bool m_ShowDetailedVersion = false;\n        private int m_InternalCodeProgress;\n\n\n        private VisualElement buildDetailsContainer;\n        private Label versionLabel;\n        private const string darkClassname = \"dark\";\n\n        void CreateGUI()\n        {\n            rootVisualElement.AddToClassList(\"root-element\");\n\n\n            var layout = EditorResources.Load(\"UXML/About/AboutWindow.uxml\", typeof(UnityEngine.Object)) as VisualTreeAsset;\n\n            string extensionVersion = FormatExtensionVersionString();\n            int t = InternalEditorUtility.GetUnityVersionDate();\n            DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0);\n            string branch = InternalEditorUtility.GetUnityBuildBranch();\n\n\n            if (layout == null)\n            {\n                // We display a minimal layout just in case\n                rootVisualElement.Add(new Label(\"About Unity\"));\n                versionLabel = new Label($\"{InternalEditorUtility.GetUnityDisplayVersion()}{extensionVersion}\");\n                rootVisualElement.Add(versionLabel);\n            }\n            else\n            {\n                layout.CloneTree(rootVisualElement);\n\n                versionLabel = rootVisualElement.Q<Label>(\"version\");\n\n                buildDetailsContainer = rootVisualElement.Q(\"detail-info\");\n                buildDetailsContainer.AddToClassList(\"hide-details\");\n\n                if (EditorGUIUtility.isProSkin)\n                {\n                    rootVisualElement.AddToClassList(darkClassname);\n                    rootVisualElement.Query<VisualElement>(className: \"logo\")\n                        .ForEach((x) => x.AddToClassList(darkClassname));\n                }\n\n                SetLabelValue(\"product-name\", InternalEditorUtility.GetUnityProductName());\n\n                SetLabelValue(\"build-revision\", $\"{branch} {InternalEditorUtility.GetUnityBuildHash()}\");\n                SetLabelValue(\"build-date\", $\"{dt.AddSeconds(t):r}\");\n\n\n                SetLabelValue(\"license-type\", InternalEditorUtility.GetLicenseInfoType());\n                SetLabelValue(\"serial-number\", InternalEditorUtility.GetLicenseInfoSerial());\n                SetLabelValue(\"unity-copyright\", InternalEditorUtility.GetUnityCopyright());\n            }\n\n            rootVisualElement.RegisterCallback<KeyDownEvent>(OnKeyDown, TrickleDown.TrickleDown);\n\n            var contextMenu = new ContextualMenuManipulator((evt) =>\n            {\n                evt.menu.AppendAction(\"Copy Version Info\", (act) => CopyVersionInfoToClipboard());\n                evt.menu.AppendAction(\"Copy License Info\", (act) => CopyLicenseInfoToClipboard());\n            });\n\n            rootVisualElement.AddManipulator(contextMenu);\n            rootVisualElement.focusable = true;\n\n            UpdateVersionLabel();\n\n            rootVisualElement.Focus();\n        }\n\n        void SetLabelValue(string labelName, string text)\n        {\n            var lbl = rootVisualElement.Q<TextElement>(labelName);\n            if(lbl != null)\n                lbl.text = text.Replace(\"(c)\", \"\\u00A9\");\n        }\n\n        void OnKeyDown(KeyDownEvent evt)\n        {\n            bool altPressed = ((int)evt.modifiers & (int)EventModifiers.Alt) == (int)EventModifiers.Alt;\n\n            UpdateOnAlt(altPressed);\n\n            ListenForSecretCodes(evt.character);\n\n            if (evt.keyCode == KeyCode.C)\n            {\n                if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.MacOSX)\n                {\n                    if (evt.modifiers == EventModifiers.Command)\n                    {\n                        CopyVersionInfoToClipboard();\n                    }\n                }\n                else if (evt.modifiers == EventModifiers.Control)\n                {\n                    CopyVersionInfoToClipboard();\n                }\n            }\n        }\n\n        void OnEnable()\n        {\n            EditorApplication.modifierKeysChanged += ModifierKeysChanged;\n        }\n\n        void OnDisable()\n        {\n            EditorApplication.modifierKeysChanged -= ModifierKeysChanged;\n        }\n\n        void ModifierKeysChanged()\n        {\n            // because we show the detailed version string when Option (Alt) is pressed\n            Repaint();\n        }\n\n        public void OnGUI()\n        {\n            var evt = Event.current;\n            UpdateOnAlt(evt.alt);\n        }\n\n        private void UpdateOnAlt(bool altPressed)\n        {\n            if (!m_ShowDetailedVersion && altPressed != m_ShowDetailedVersion)\n            {\n                m_ShowDetailedVersion |= altPressed;\n\n                UpdateVersionLabel();\n            }\n        }\n\n        private void CopyVersionInfoToClipboard()\n        {\n            string extensionVersion = FormatExtensionVersionString();\n\n            if (m_ShowDetailedVersion)\n            {\n                int t = InternalEditorUtility.GetUnityVersionDate();\n                DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0);\n                string branch = InternalEditorUtility.GetUnityBuildBranch();\n                Clipboard.stringValue = $\"{InternalEditorUtility.GetUnityProductName()}\\n\" +\n                                        $\"{InternalEditorUtility.GetUnityDisplayVersionVerbose()}{extensionVersion}\\n\" +\n                                        $\"Revision: {branch} {InternalEditorUtility.GetUnityBuildHash()}\\n\" +\n                                        $\"Built: {dt.AddSeconds(t):r}\";\n            }\n            else\n            {\n                Clipboard.stringValue = $\"{InternalEditorUtility.GetUnityProductName()}\\n\" +\n                                        $\"{InternalEditorUtility.GetUnityDisplayVersion()}{extensionVersion}\";\n            }\n        }\n\n        private void CopyLicenseInfoToClipboard()\n        {\n            Clipboard.stringValue = InternalEditorUtility.GetLicenseInfo().Replace(\"(c)\", \"\\u00A9\");\n        }\n\n        void UpdateVersionLabel()\n        {\n            if (buildDetailsContainer != null)\n            {\n                buildDetailsContainer.EnableInClassList(\"hide-details\", !m_ShowDetailedVersion);\n                buildDetailsContainer.Query<VisualElement>()\n                    .ForEach((x) => x.EnableInClassList(\"hide-details\", !m_ShowDetailedVersion));\n            }\n\n            string extensionVersion = FormatExtensionVersionString();\n\n            if (m_ShowDetailedVersion)\n            {\n                SetLabelValue(\"version\", $\"{InternalEditorUtility.GetUnityDisplayVersionVerbose()}{extensionVersion}\");\n            }\n            else\n            {\n                // The non verbose version should be shorter on public builds\n                SetLabelValue(\"version\", $\"{InternalEditorUtility.GetUnityDisplayVersion()}{extensionVersion}\");\n            }\n\n        }\n\n        private void ListenForSecretCodes(char current)\n        {\n            if (current == '\\0')\n                return;\n\n            if (SecretCodeHasBeenTyped(\"internal\", current, ref m_InternalCodeProgress))\n            {\n                ToggleInternalMode();\n            }\n        }\n\n        private bool SecretCodeHasBeenTyped(string code, char current, ref int characterProgress)\n        {\n            if (characterProgress < 0 || characterProgress >= code.Length || code[characterProgress] != current)\n                characterProgress = 0;\n\n            // Don't use else here. Even if key was mismatch, it should still be recognized as first key of sequence if it matches.\n            if (code[characterProgress] == current)\n            {\n                characterProgress++;\n\n                if (characterProgress >= code.Length)\n                {\n                    characterProgress = 0;\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        private void ToggleInternalMode()\n        {\n            bool enabled = !EditorPrefs.GetBool(\"DeveloperMode\", false);\n            EditorPrefs.SetBool(\"DeveloperMode\", enabled);\n            ShowNotification(new GUIContent(string.Format(L10n.Tr(\"Developer Mode {0}\"), (enabled ? L10n.Tr(\"On\") : L10n.Tr(\"Off\")))));\n            EditorUtility.RequestScriptReload();\n\n            // Repaint all views to show/hide debug repaint indicator\n            InternalEditorUtility.RepaintAllViews();\n        }\n\n        private string FormatExtensionVersionString()\n        {\n            string extStr = EditorUserBuildSettings.selectedBuildTargetGroup.ToString();\n            string ext = Modules.ModuleManager.GetExtensionVersion(extStr);\n\n            if (!string.IsNullOrEmpty(ext))\n                return \" [\" + extStr + \": \" + ext + \"]\";\n\n            return \"\";\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/AngularDial.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class EditorGUILayout\n    {\n        internal static float AngularDial(\n            GUIContent label, float angle, Texture thumbTexture, GUIStyle background, GUIStyle thumb,\n            params GUILayoutOption[] options\n        )\n        {\n            var hasLabel = label != null && label != GUIContent.none;\n            var height = background == null || background.fixedHeight == 0 ?\n                EditorGUIUtility.singleLineHeight : background.fixedHeight;\n            var minWidth = (hasLabel ? EditorGUIUtility.labelWidth : 0f)\n                + (background != null ? background.fixedWidth : 0f);\n            var maxWidth = kLabelFloatMaxW;\n            var rect = GUILayoutUtility.GetRect(minWidth, maxWidth, height, height, background, options);\n            s_LastRect = rect;\n            return EditorGUI.AngularDial(rect, label, angle, thumbTexture, background, thumb);\n        }\n    }\n\n    public sealed partial class EditorGUI\n    {\n        internal static float AngularDial(\n            Rect rect, GUIContent label, float angle, Texture thumbTexture, GUIStyle background, GUIStyle thumb\n        )\n        {\n            var id = GUIUtility.GetControlID(FocusType.Passive);\n            var evt = Event.current;\n\n            if (label != null && label != GUIContent.none)\n                rect = PrefixLabel(rect, id, label);\n\n            var diameter = Mathf.Min(rect.width, rect.height);\n            var thumbDimensions = thumb == null || thumb == GUIStyle.none\n                ? Vector2.zero\n                : thumb.CalcSize(GUIContent.Temp(thumbTexture));\n            var thumbSize = Mathf.Max(thumbDimensions.x, thumbDimensions.y);\n\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (rect.Contains(evt.mousePosition))\n                    {\n                        var p = evt.mousePosition - rect.center;\n                        var r = Mathf.Sqrt(p.x * p.x + p.y * p.y);\n                        if (r < diameter * 0.5f && r > diameter * 0.5f - thumbSize)\n                            return UseAngularDialEventAndGetAngle(id, evt, rect.center, angle);\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                        return UseAngularDialEventAndGetAngle(id, evt, rect.center, angle);\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n                        return UseAngularDialEventAndGetAngle(id, evt, rect.center, angle);\n                    }\n                    break;\n                case EventType.Repaint:\n                    var hover = false;\n                    if (rect.Contains(evt.mousePosition))\n                    {\n                        var p = evt.mousePosition - rect.center;\n                        var r = Mathf.Sqrt(p.x * p.x + p.y * p.y);\n                        hover = r<diameter * 0.5f && r> diameter * 0.5f - thumbSize;\n                    }\n                    var active = GUIUtility.hotControl == id;\n\n                    if (background != null && background != GUIStyle.none)\n                        background.Draw(rect, hover, active, false, false);\n\n                    if (thumb != null && thumb != GUIStyle.none)\n                    {\n                        var thumbCenterRadius = diameter * 0.5f - thumbSize * 0.5f;\n                        // negate angle since gui space goes top to bottom\n                        var radians = -Mathf.Deg2Rad * angle;\n                        var thumbCenter =\n                            new Vector2(Mathf.Cos(radians), Mathf.Sin(radians)) * thumbCenterRadius + rect.center;\n                        var size = thumb.CalcSize(GUIContent.none);\n                        if (thumb.fixedWidth == 0f)\n                            size.x = Mathf.Max(size.x, thumbSize);\n                        if (thumb.fixedHeight == 0f)\n                            size.y = Mathf.Max(size.y, thumbSize);\n                        var thumbRect = new Rect { size = size, center = thumbCenter };\n                        thumbRect.center = thumbCenter;\n\n                        thumb.Draw(thumbRect, thumbTexture, thumbRect.Contains(evt.mousePosition), active, false, false);\n                    }\n                    break;\n            }\n\n            return angle;\n        }\n\n        private static float UseAngularDialEventAndGetAngle(int id, Event evt, Vector2 center, float angle)\n        {\n            GUIUtility.hotControl = evt.type == EventType.MouseUp ? 0 : id;\n            EditorGUIUtility.keyboardControl = 0;\n            GUI.changed = true;\n            evt.Use();\n\n            var normalized = (evt.mousePosition - center).normalized;\n            // negate angle since gui space goes top to bottom\n            var newAngle = -Mathf.Rad2Deg\n                * Mathf.Acos(normalized.x)\n                * Mathf.Sign(Vector2.Dot(Vector2.up, normalized));\n\n            // accumulate delta angle to allow for multiple revolutions\n            return angle + Mathf.DeltaAngle(angle, newAngle);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/AnimatedValues.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Events;\n\nnamespace UnityEditor.AnimatedValues\n{\n    public abstract class BaseAnimValueNonAlloc<T> : BaseAnimValue<T> where T : IEquatable<T>\n    {\n        protected BaseAnimValueNonAlloc(T value) : base(value)\n        {\n        }\n\n        protected BaseAnimValueNonAlloc(T value, UnityAction callback) : base(value, callback)\n        {\n        }\n\n        protected override bool AreEqual(T a, T b)\n        {\n            return a.Equals(b);\n        }\n    }\n\n    public abstract class BaseAnimValue<T> : ISerializationCallbackReceiver\n    {\n        T m_Start;\n\n        [SerializeField]\n        T m_Target;\n\n        double m_LastTime;\n        double m_LerpPosition = 1f;\n\n        float m_Speed;\n        public float speed = 2f;\n\n        [NonSerialized]\n        public UnityEvent valueChanged;\n\n        // Don't have m_Animating survive script reloads, as it could cause the AnimValue to get stuck.\n        // If m_Animating was true after reload but the Update callback registration had been lost,\n        // The value would never change and also never re-register to the Update callback.\n        [NonSerialized]\n        bool m_Animating;\n\n        protected BaseAnimValue(T value)\n        {\n            m_Start = value;\n            m_Target = value;\n            valueChanged = new UnityEvent();\n        }\n\n        protected BaseAnimValue(T value, UnityAction callback)\n        {\n            m_Start = value;\n            m_Target = value;\n            valueChanged = new UnityEvent();\n            valueChanged.AddListener(callback);\n        }\n\n        protected virtual bool AreEqual(T a, T b)\n        {\n            return a.Equals(b);\n        }\n\n        static T2 Clamp<T2>(T2 val, T2 min, T2 max) where T2 : IComparable<T2>\n        {\n            if (val.CompareTo(min) < 0) return min;\n            if (val.CompareTo(max) > 0) return max;\n            return val;\n        }\n\n        protected void BeginAnimating(T newTarget, T newStart)\n        {\n            BeginAnimating(newTarget, newStart, speed);\n        }\n\n        void BeginAnimating(T newTarget, T newStart, float animationSpeed)\n        {\n            m_Speed = animationSpeed;\n            m_Start = newStart;\n            m_Target = newTarget;\n            if (!m_Animating)\n            {\n                EditorApplication.update -= Update;\n                EditorApplication.update += Update;\n            }\n            m_Animating = true;\n            m_LastTime = EditorApplication.timeSinceStartup;\n            m_LerpPosition = 0;\n        }\n\n        public bool isAnimating\n        {\n            get { return m_Animating; }\n        }\n\n        // used by tests to access AnimValue.Update so that we don't have to rely on EditorApplication.Update.\n        internal void Update()\n        {\n            if (!m_Animating)\n            {\n                EditorApplication.update -= Update;\n                return;\n            }\n\n            // update the lerpPosition\n            UpdateLerpPosition();\n\n            if (valueChanged != null)\n                valueChanged.Invoke();\n\n            if (lerpPosition >= 1f)\n            {\n                m_Animating = false;\n                EditorApplication.update -= Update;\n            }\n        }\n\n        protected float lerpPosition\n        {\n            get\n            {\n                var v = 1.0 - m_LerpPosition;\n                var result = 1.0 - v * v * v * v;\n                return (float)result;\n            }\n        }\n\n        void UpdateLerpPosition()\n        {\n            double nowTime = EditorApplication.timeSinceStartup;\n            double deltaTime = nowTime - m_LastTime;\n\n            m_LerpPosition = Clamp(m_LerpPosition + (deltaTime * m_Speed), 0.0, 1.0);\n            m_LastTime = nowTime;\n        }\n\n        protected void StopAnim(T newValue)\n        {\n            // If the new value is different, or we might be in the middle of a fade, we need to refresh.\n            // Checking GetValue is not reliable on its own, since for e.g. bool it'll return the \"closest\" value,\n            // but that doesn't mean the fade is done.\n            bool invoke = (!AreEqual(newValue, GetValue()) || m_LerpPosition < 1) && valueChanged != null;\n\n            m_Target = newValue;\n            m_Start = newValue;\n            m_LerpPosition = 1;\n            m_Animating = false;\n            // Only refresh *after* we set the correct new value.\n            if (invoke)\n                valueChanged.Invoke();\n        }\n\n        protected T start\n        {\n            get { return m_Start; }\n        }\n\n        public T target\n        {\n            get { return m_Target; }\n            set\n            {\n                if (!AreEqual(m_Target, value))\n                    BeginAnimating(value, this.value);\n            }\n        }\n\n        internal void SetTarget(T newTarget, float animationSpeed)\n        {\n            if (!AreEqual(m_Target, value))\n                BeginAnimating(newTarget, value, animationSpeed);\n        }\n\n        public T value\n        {\n            get { return lerpPosition >= 1f ? target : GetValue(); }\n            set { StopAnim(value); }\n        }\n\n        internal void SkipFading()\n        {\n            StopAnim(target);\n        }\n\n        protected abstract T GetValue();\n\n        void ISerializationCallbackReceiver.OnBeforeSerialize() {}\n\n        void ISerializationCallbackReceiver.OnAfterDeserialize()\n        {\n            // Ensure we resume animating after script reload if value differs from target.\n            if (!GetValue().Equals(target) && !m_Animating)\n            {\n                // Shouldn't be necessary to remove first since we use m_Animating\n                // to keep track of it, but it doesn't hurt.\n                EditorApplication.update -= Update;\n                EditorApplication.update += Update;\n                m_Animating = true;\n            }\n        }\n    }\n\n    [Serializable]\n    public class AnimFloat : BaseAnimValueNonAlloc<float>\n    {\n        [SerializeField]\n        private float m_Value;\n\n        public AnimFloat(float value)\n            : base(value)\n        {}\n\n        public AnimFloat(float value, UnityAction callback) : base(value, callback)\n        {}\n\n        protected override float GetValue()\n        {\n            m_Value = Mathf.Lerp(start, target, lerpPosition);\n            return m_Value;\n        }\n    }\n\n    [Serializable]\n    public class AnimVector3 : BaseAnimValueNonAlloc<Vector3>\n    {\n        [SerializeField]\n        private Vector3 m_Value;\n\n        public AnimVector3()\n            : base(Vector3.zero)\n        {}\n\n        public AnimVector3(Vector3 value)\n            : base(value)\n        {}\n\n        public AnimVector3(Vector3 value, UnityAction callback)\n            : base(value, callback)\n        {}\n\n        protected override Vector3 GetValue()\n        {\n            m_Value = Vector3.Lerp(start, target, lerpPosition);\n            return m_Value;\n        }\n    }\n\n    [Serializable]\n    public class AnimBool : BaseAnimValueNonAlloc<bool>\n    {\n        [SerializeField]\n        private float m_Value;\n\n        public AnimBool()\n            : base(false)\n        {}\n\n        public AnimBool(bool value)\n            : base(value)\n        {}\n\n        public AnimBool(UnityAction callback)\n            : base(false, callback)\n        {}\n\n        public AnimBool(bool value, UnityAction callback)\n            : base(value, callback)\n        {}\n\n        public float faded\n        {\n            get\n            {\n                GetValue();\n                return m_Value;\n            }\n        }\n\n        protected override bool GetValue()\n        {\n            float startVal = target ? 0f : 1f;\n            float end = 1f - startVal;\n\n            m_Value = Mathf.Lerp(startVal, end, lerpPosition);\n\n            return m_Value > .5f;\n        }\n\n        public float Fade(float from, float to)\n        {\n            return Mathf.Lerp(from, to, faded);\n        }\n    }\n\n    [Serializable]\n    public class AnimQuaternion : BaseAnimValueNonAlloc<Quaternion>\n    {\n        [SerializeField]\n        private Quaternion m_Value;\n\n\n        public AnimQuaternion(Quaternion value)\n            : base(value)\n        {}\n\n        public AnimQuaternion(Quaternion value, UnityAction callback)\n            : base(value, callback)\n        {}\n\n        protected override Quaternion GetValue()\n        {\n            m_Value = Quaternion.Slerp(start, target, lerpPosition);\n            return m_Value;\n        }\n    }\n}\n//namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/AppStatusBar.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Globalization;\nusing System.Linq;\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    internal class AppStatusBar : GUIView\n    {\n        static readonly NumberFormatInfo percentageFormat = new CultureInfo(\"en-US\", false).NumberFormat;\n\n        internal static class Styles\n        {\n            public const int spacing = 4;\n\n            public static readonly GUILayoutOption progressBarWidth = GUILayout.Width(180);\n            public static readonly GUILayoutOption progressLabelMaxWidth = GUILayout.MaxWidth(230);\n            public static readonly GUIStyle background = \"AppToolbar\";\n            public static readonly GUIStyle statusLabel = EditorStyles.FromUSS(EditorStyles.label, \"status-bar-label\");\n            public static readonly GUIStyle statusIcon = \"StatusBarIcon\";\n\n            public static readonly GUIStyle progressBar = EditorStyles.FromUSS(EditorStyles.progressBarBar, \"status-bar-progress\");\n            public static readonly GUIStyle progressBarAlmostDone = EditorStyles.FromUSS(progressBar, \"status-bar-progress-almost-done\");\n            public static readonly GUIStyle progressBarUnresponsive = EditorStyles.FromUSS(progressBar, \"status-bar-progress-unresponsive\");\n            public static readonly GUIStyle progressBarIndefinite = EditorStyles.FromUSS(progressBar, \"status-bar-progress-indefinite\");\n            public static readonly GUIStyle progressBarBack = EditorStyles.FromUSS(EditorStyles.progressBarBack, \"status-bar-progress-background\");\n            public static readonly GUIStyle progressBarText = EditorStyles.FromUSS(statusLabel, \"status-bar-progress-text\");\n\n            public static readonly GUIContent[] statusWheel;\n            public static readonly GUIContent assemblyLock = EditorGUIUtility.IconContent(\"AssemblyLock\", \"|Assemblies are currently locked. Compilation will resume once they are unlocked\");\n            public static readonly GUIContent progressIcon = EditorGUIUtility.TrIconContent(\"Progress\", \"Show progress details\");\n            public static readonly GUIContent progressHideIcon = EditorGUIUtility.TrIconContent(\"Progress\", \"Hide progress details\");\n\n            static Styles()\n            {\n                percentageFormat.PercentDecimalDigits = 0;\n                statusWheel = new GUIContent[12];\n                for (int i = 0; i < 12; i++)\n                    statusWheel[i] = EditorGUIUtility.IconContent(\"WaitSpin\" + i.ToString(\"00\"));\n            }\n        }\n\n        private static AppStatusBar s_AppStatusBar;\n        private ShortcutHelperBar m_ShortcutHelperBar;\n\n        private string m_MiniMemoryOverview = \"\";\n        private bool m_DrawExtraFeatures;\n        private GUIContent m_ProgressStatus = new GUIContent();\n        private GUIContent m_ProgressPercentageStatus = new GUIContent();\n        private bool m_CurrentProgressNotResponding = false;\n\n        private ManagedDebuggerToggle m_ManagedDebuggerToggle = null;\n        private CacheServerToggle m_CacheServerToggle = null;\n        const double k_CheckUnresponsiveFrequencyInSecond = 0.5;\n        const float k_ShowProgressThreshold = 0.5f;\n        private double m_LastUpdate;\n\n        private bool m_ShowProgress = false;\n        private bool showProgress\n        {\n            get\n            {\n                return m_ShowProgress;\n            }\n        }\n\n        protected override void OnEnable()\n        {\n            base.OnEnable();\n            s_AppStatusBar = this;\n            m_ShortcutHelperBar = new ShortcutHelperBar(this);\n\n            m_ManagedDebuggerToggle = new ManagedDebuggerToggle();\n            m_CacheServerToggle = new CacheServerToggle();\n            m_EventInterests.wantsLessLayoutEvents = true;\n            m_DrawExtraFeatures = ModeService.HasCapability(ModeCapability.StatusBarExtraFeatures, true);\n\n            Progress.added += RefreshProgressBar;\n            Progress.removed += RefreshProgressBar;\n            Progress.updated += RefreshProgressBar;\n        }\n\n        protected override void OnDisable()\n        {\n            m_ShortcutHelperBar.OnDisable();\n            Progress.added -= RefreshProgressBar;\n            Progress.removed -= RefreshProgressBar;\n            Progress.updated -= RefreshProgressBar;\n            EditorApplication.delayCall -= DelayRepaint;\n            base.OnDisable();\n        }\n\n        protected void OnInspectorUpdate()\n        {\n            string miniOverview = UnityEditorInternal.ProfilerDriver.miniMemoryOverview;\n\n            if ((Unsupported.IsDeveloperMode() && m_MiniMemoryOverview != miniOverview))\n            {\n                m_MiniMemoryOverview = miniOverview;\n\n                Repaint();\n            }\n        }\n\n        private void ScheduleCheckProgressUnresponsive()\n        {\n            EditorApplication.tick -= CheckProgressUnresponsive;\n            EditorApplication.tick += CheckProgressUnresponsive;\n        }\n\n        private void CheckProgressUnresponsive()\n        {\n            var now = EditorApplication.timeSinceStartup;\n            if (now - m_LastUpdate < k_CheckUnresponsiveFrequencyInSecond)\n                return;\n\n            EditorApplication.tick -= CheckProgressUnresponsive;\n\n            m_LastUpdate = now;\n            if (Progress.running)\n            {\n                var unresponsiveItem = Progress.EnumerateItems().FirstOrDefault(item => !item.responding);\n                if (unresponsiveItem != null)\n                {\n                    m_CurrentProgressNotResponding = true;\n                    RefreshProgressBar(new[] { unresponsiveItem });\n                }\n                else\n                {\n                    m_CurrentProgressNotResponding = false;\n                    ScheduleCheckProgressUnresponsive();\n                }\n            }\n            else\n            {\n                m_CurrentProgressNotResponding = false;\n            }\n        }\n\n        protected override void OldOnGUI()\n        {\n            ConsoleWindow.LoadIcons();\n\n            GUI.color = EditorApplication.isPlayingOrWillChangePlaymode ? HostView.kPlayModeDarken : Color.white;\n\n            if (Event.current.type == EventType.Layout)\n                m_ShowProgress = Progress.running && Progress.GetMaxElapsedTime() > k_ShowProgressThreshold;\n            else if (Event.current.type == EventType.Repaint)\n                Styles.background.Draw(new Rect(0, 0, position.width, position.height), false, false, false, false);\n\n            GUILayout.BeginHorizontal(GUILayout.MaxWidth(position.width));\n            {\n                GUILayout.Space(2);\n                DrawStatusText();\n\n                if (EditorPrefs.GetBool(\"EnableShortcutHelperBar\", false))\n                    m_ShortcutHelperBar.DrawStatusBarShortcuts();\n                else\n                    GUILayout.FlexibleSpace();\n\n                if (m_DrawExtraFeatures)\n                    DrawSpecialModeLabel();\n\n                DrawProgressBar();\n                DrawDebuggerToggle();\n\n                if (m_DrawExtraFeatures)\n                    DrawCacheServerToggle();\n\n                DrawRefreshStatus();\n            }\n\n            GUILayout.EndHorizontal();\n            EditorGUI.ShowRepaints();\n        }\n\n        private void DrawRefreshStatus()\n        {\n            bool compiling = EditorApplication.isCompiling;\n            bool assembliesLocked = !EditorApplication.CanReloadAssemblies();\n\n            if (compiling)\n            {\n                if (assembliesLocked)\n                {\n                    GUILayout.Button(Styles.assemblyLock, Styles.statusIcon);\n                }\n                else\n                {\n                    int frame = (int)Mathf.Repeat(Time.realtimeSinceStartup * 10, 11.99f);\n                    GUILayout.Button(Styles.statusWheel[frame], Styles.statusIcon);\n                }\n            }\n            else\n            {\n                var canHide = ProgressWindow.canHideDetails;\n                if (GUILayout.Button(canHide ? Styles.progressHideIcon : Styles.progressIcon, Styles.statusIcon))\n                {\n                    if (canHide)\n                        ProgressWindow.HideDetails();\n                    else\n                        Progress.ShowDetails(false);\n                }\n\n                var buttonRect = GUILayoutUtility.GetLastRect();\n                EditorGUIUtility.AddCursorRect(buttonRect, MouseCursor.Link);\n            }\n        }\n\n        private string m_SpecialModeLabel = \"\";\n        private void DrawSpecialModeLabel()\n        {\n            if (Unsupported.IsBleedingEdgeBuild())\n            {\n                GUILayout.Space(k_SpaceBeforeProgress);\n                m_SpecialModeLabel = \"THIS IS AN UNTESTED BLEEDINGEDGE UNITY BUILD\";\n                var backup = GUI.color;\n                GUI.color = Color.yellow;\n                GUILayout.Label(m_SpecialModeLabel);\n                GUI.color = backup;\n            }\n            else if (Unsupported.IsDeveloperMode())\n            {\n                GUILayout.Space(k_SpaceBeforeProgress);\n                m_SpecialModeLabel = m_MiniMemoryOverview;\n                GUILayout.Label(m_SpecialModeLabel, Styles.statusLabel);\n                EditorGUIUtility.CleanCache(m_MiniMemoryOverview);\n            }\n            else\n                m_SpecialModeLabel = \"\";\n        }\n\n        float k_SpaceBeforeProgress = 15;\n        float k_SpaceAfterProgress = 4;\n\n        private void DelayRepaint()\n        {\n            if (!this) // The window could have been destroyed during a reset layout.\n                return;\n            Repaint();\n        }\n\n        private void DrawProgressBar()\n        {\n            if (!showProgress)\n                return;\n\n            GUILayout.Space(k_SpaceBeforeProgress);\n\n            var buttonRect = GUILayoutUtility.GetLastRect();\n            EditorGUIUtility.AddCursorRect(buttonRect, MouseCursor.Link);\n\n            // Define the progress styles to be used based on the current progress state.\n            var globalProgress = Progress.globalProgress;\n            var progressBarStyle = GetProgressBarStyle(globalProgress);\n            var progressBarContent = GetProgressBarContent(m_ProgressStatus);\n            var progressRect = EditorGUILayout.GetControlRect(false, position.height, Styles.progressBarBack, Styles.progressBarWidth);\n            if (EditorGUI.ProgressBar(progressRect, globalProgress, progressBarContent, true,\n                Styles.progressBarBack, progressBarStyle, Styles.progressBarText))\n                Progress.ShowDetails(false);\n\n            if (globalProgress == -1.0f)\n            {\n                EditorApplication.delayCall -= DelayRepaint;\n                EditorApplication.delayCall += DelayRepaint;\n            }\n\n            EditorGUIUtility.AddCursorRect(progressRect, MouseCursor.Link);\n            GUILayout.Space(k_SpaceAfterProgress);\n        }\n\n        private GUIContent GetProgressBarContent(GUIContent defaultContent)\n        {\n            GUIContent progressBarContent = defaultContent;\n            if (m_CurrentProgressNotResponding)\n                progressBarContent = GUIContent.none;\n\n            return progressBarContent;\n        }\n\n        private GUIStyle GetProgressBarStyle(float globalProgress)\n        {\n            var progressBarStyle = Styles.progressBar;\n\n            if (globalProgress == -1.0f)\n                progressBarStyle = Styles.progressBarIndefinite;\n            else if (m_CurrentProgressNotResponding)\n                progressBarStyle = Styles.progressBarUnresponsive;\n            else if (globalProgress >= 0.99f)\n                progressBarStyle = Styles.progressBarAlmostDone;\n\n            return progressBarStyle;\n        }\n\n        void DrawDebuggerToggle()\n        {\n            m_ManagedDebuggerToggle.OnGUI();\n        }\n\n        void DrawCacheServerToggle()\n        {\n            m_CacheServerToggle.OnGUI();\n        }\n\n        private void DrawStatusText()\n        {\n            string statusText = LogEntries.GetStatusText();\n            if (String.IsNullOrEmpty(statusText))\n                return;\n\n            int mask = LogEntries.GetStatusMask();\n            GUIStyle errorStyle = ConsoleWindow.GetStatusStyleForErrorMode(mask);\n\n            Texture2D icon = ConsoleWindow.GetIconForErrorMode(mask, false);\n            GUILayout.Label(icon, errorStyle);\n\n            var iconRect = GUILayoutUtility.GetLastRect();\n\n            GUILayout.Space(2);\n            GUILayout.BeginVertical();\n            GUILayout.Space(1);\n            GUILayout.Label(statusText, errorStyle, GetStatusTextLayoutOption((icon != null ? icon.width : 0) + 6));\n\n            // Handle status bar click\n            if (Event.current.type == EventType.MouseDown)\n            {\n                var labelRect = GUILayoutUtility.GetLastRect();\n                if (iconRect.Contains(Event.current.mousePosition) || labelRect.Contains(Event.current.mousePosition))\n                {\n                    Event.current.Use();\n                    LogEntries.ClickStatusBar(Event.current.clickCount);\n                    GUIUtility.ExitGUI();\n                }\n            }\n\n            GUILayout.EndVertical();\n        }\n\n        private void RefreshProgressBar(Progress.Item[] progressItems)\n        {\n            if (!this)\n                return;\n\n            if (!Progress.running)\n            {\n                // If we enter here, it means the last remaining progresses just finished or paused.\n                ClearProgressStatus();\n                RepaintProgress(progressItems);\n                return;\n            }\n\n            var idleCount = Progress.EnumerateItems().Count(item => item.running && item.priority == (int)Progress.Priority.Idle);\n            var taskCount = Progress.GetRunningProgressCount() - idleCount;\n            if (taskCount == 0)\n            {\n                ClearProgressStatus();\n            }\n            else\n            {\n                var currentItem = progressItems.FirstOrDefault(item => item.priority != (int)Progress.Priority.Idle);\n                if (currentItem != null && !String.IsNullOrEmpty(currentItem.description))\n                    m_ProgressStatus.tooltip = currentItem.name + \"\\r\\n\" + currentItem.description;\n                m_ProgressPercentageStatus.text = Progress.globalProgress.ToString(\"P\", percentageFormat);\n\n                var remainingTimeText = \"\";\n                var runningProgresses = Progress.EnumerateItems().Where(item => item.running);\n                if (Progress.globalRemainingTime.TotalSeconds > 0 && runningProgresses.Any(item => item.timeDisplayMode == Progress.TimeDisplayMode.ShowRemainingTime && item.priority != (int)Progress.Priority.Idle) &&\n                    runningProgresses.All(item => !item.indefinite))\n                {\n                    remainingTimeText = $\" [{Progress.globalRemainingTime:g}]\";\n                }\n\n                if (taskCount > 1)\n                    m_ProgressStatus.text = $\"Multiple tasks ({taskCount}){remainingTimeText}\";\n                else\n                    m_ProgressStatus.text = $\"{currentItem?.name}{remainingTimeText}\";\n\n                ScheduleCheckProgressUnresponsive();\n            }\n\n            RepaintProgress(progressItems);\n        }\n\n        private void RepaintProgress(Progress.Item[] progressItems)\n        {\n            bool hasSynchronous = false;\n            foreach (var item in progressItems)\n            {\n                if ((item.options & Progress.Options.Synchronous) == Progress.Options.Synchronous)\n                {\n                    hasSynchronous = true;\n                    break;\n                }\n            }\n\n            if (hasSynchronous)\n                RepaintImmediately();\n            else\n                Repaint();\n        }\n\n        private void ClearProgressStatus()\n        {\n            m_ProgressStatus.text = String.Empty;\n            m_ProgressPercentageStatus.text = String.Empty;\n        }\n\n        private GUILayoutOption GetStatusTextLayoutOption(float consoleIconWidth)\n        {\n            int iconWidth = 25;\n            float specialModeLabelWidth = Styles.statusLabel.CalcSize(new GUIContent(m_SpecialModeLabel)).x + k_SpaceBeforeProgress + 8;\n            float helperBarWidth = (EditorPrefs.GetBool(\"EnableShortcutHelperBar\", false) ? ShortcutHelperBar.k_HelperBarMinWidth : 0);\n            float statusRightReservedSpace =\n                specialModeLabelWidth +\n                helperBarWidth + // helper bar\n                iconWidth + // script debugger\n                iconWidth + // cache server\n                iconWidth; // progress\n            if (!showProgress)\n                return GUILayout.MaxWidth(position.width - statusRightReservedSpace - consoleIconWidth);\n\n            return GUILayout.MaxWidth(position.width - statusRightReservedSpace - k_SpaceBeforeProgress - 8 - (float)Styles.progressBarWidth.value - k_SpaceAfterProgress - consoleIconWidth);\n        }\n\n        [RequiredByNativeCode]\n        public static void StatusChanged()\n        {\n            if (s_AppStatusBar)\n                s_AppStatusBar.Repaint();\n        }\n\n        [RequiredByNativeCode]\n        internal static void StatusChangedImmediate()\n        {\n            if (s_AppStatusBar)\n                s_AppStatusBar.RepaintImmediately();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/AssetPopupBackend.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Presets;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class AssetPopupBackend\n    {\n        public static void AssetPopup<T>(SerializedProperty serializedProperty, GUIContent label, string fileExtension, string defaultFieldName) where T : Object, new()\n        {\n            bool orignalShowMixedValue = EditorGUI.showMixedValue;\n            EditorGUI.showMixedValue = serializedProperty.hasMultipleDifferentValues;\n\n            var typeName = serializedProperty.objectReferenceTypeString;\n            GUIContent buttonContent;\n            if (serializedProperty.hasMultipleDifferentValues)\n                buttonContent = EditorGUI.mixedValueContent;\n            else if (serializedProperty.objectReferenceValue != null)\n                buttonContent = GUIContent.Temp(serializedProperty.objectReferenceStringValue);\n            else\n                buttonContent = GUIContent.Temp(defaultFieldName);\n\n            Rect buttonRect;\n            if (AudioMixerEffectGUI.PopupButton(label, buttonContent, EditorStyles.popup, out buttonRect)) // move & rename PopupButton..\n                ShowAssetsPopupMenu<T>(buttonRect, typeName, serializedProperty, fileExtension, defaultFieldName);\n\n            EditorGUI.showMixedValue = orignalShowMixedValue;\n        }\n\n        public static void AssetPopup<T>(SerializedProperty serializedProperty, GUIContent label, string fileExtension) where T : Object, new()\n        {\n            AssetPopup<T>(serializedProperty, label, fileExtension, \"Default\");\n        }\n\n        private class DoCreateNewAsset : ProjectWindowCallback.EndNameEditAction\n        {\n            private SerializedObject m_Object;\n            private SerializedProperty m_Property;\n\n            public void SetProperty(SerializedProperty property)\n            {\n                m_Object = new SerializedObject(property.serializedObject.targetObject);\n                m_Property = m_Object.FindProperty(property.propertyPath);\n            }\n\n            public override void Action(int instanceId, string pathName, string resourceFile)\n            {\n                var obj = EditorUtility.InstanceIDToObject(instanceId);\n                AssetDatabase.CreateAsset(obj, AssetDatabase.GenerateUniqueAssetPath(pathName));\n                ProjectWindowUtil.FrameObjectInProjectWindow(instanceId);\n                m_Property.objectReferenceValue = obj;\n                m_Property.serializedObject.ApplyModifiedProperties();\n                m_Property.serializedObject.Dispose();\n                m_Property.Dispose();\n                m_Object.Dispose();\n            }\n\n            public override void Cancelled(int instanceId, string pathName, string resourceFile)\n            {\n                Selection.activeObject = m_Property.serializedObject.targetObject;\n                m_Property.serializedObject.Dispose();\n                m_Property.Dispose();\n                m_Object.Dispose();\n            }\n        }\n\n        internal static void ShowAssetsPopupMenu<T>(Rect buttonRect, string typeName, SerializedProperty serializedProperty, string fileExtension, string defaultFieldName) where T : Object, new()\n        {\n            GenericMenu gm = new GenericMenu();\n\n            int selectedInstanceID = serializedProperty.objectReferenceValue != null ? serializedProperty.objectReferenceValue.GetInstanceID() : 0;\n\n\n            bool foundDefaultAsset = false;\n            var type = UnityEditor.UnityType.FindTypeByName(typeName);\n            int classID = type != null ? type.persistentTypeID : 0;\n            BuiltinResource[] resourceList = null;\n\n            // Check the assets for one that matches the default name.\n            if (classID > 0)\n            {\n                resourceList = EditorGUIUtility.GetBuiltinResourceList(classID);\n                foreach (var resource in resourceList)\n                {\n                    if (resource.m_Name == defaultFieldName)\n                    {\n                        gm.AddItem(new GUIContent(resource.m_Name), resource.m_InstanceID == selectedInstanceID, AssetPopupMenuCallback, new object[] { resource.m_InstanceID, serializedProperty });\n                        resourceList = resourceList.Where(x => x != resource).ToArray();\n                        foundDefaultAsset = true;\n                        break;\n                    }\n                }\n            }\n\n            // If no defalut asset was found, add defualt null value.\n            if (!foundDefaultAsset)\n            {\n                gm.AddItem(new GUIContent(defaultFieldName), selectedInstanceID == 0, AssetPopupMenuCallback, new object[] { 0, serializedProperty });\n            }\n\n            // Add items from asset database\n            foreach (var property in AssetDatabase.FindAllAssets(new SearchFilter() { classNames = new[] { typeName } }))\n            {\n                gm.AddItem(new GUIContent(property.name), property.instanceID == selectedInstanceID, AssetPopupMenuCallback, new object[] { property.instanceID, serializedProperty });\n            }\n\n            // Add builtin items, except for the already added default item.\n            if (classID > 0 && resourceList != null)\n            {\n                foreach (var resource in resourceList)\n                {\n                    gm.AddItem(new GUIContent(resource.m_Name), resource.m_InstanceID == selectedInstanceID, AssetPopupMenuCallback, new object[] { resource.m_InstanceID, serializedProperty });\n                }\n            }\n\n            var target = serializedProperty.serializedObject.targetObject;\n            bool isPreset = Preset.IsEditorTargetAPreset(target);\n\n            // the preset object is destroyed with the inspector, and nothing new can be created that needs this link. Fix for case 1208437\n            if (!isPreset)\n            {\n                // Create item\n                gm.AddSeparator(\"\");\n                gm.AddItem(EditorGUIUtility.TrTextContent(\"Create New...\"), false, delegate\n                {\n                    var newAsset = Activator.CreateInstance<T>();\n                    var doCreate = ScriptableObject.CreateInstance<DoCreateNewAsset>();\n                    doCreate.SetProperty(serializedProperty);\n                    ProjectWindowUtil.StartNameEditingIfProjectWindowExists(newAsset.GetInstanceID(), doCreate, \"New \" + typeName + \".\" + fileExtension, AssetPreview.GetMiniThumbnail(newAsset), null);\n                });\n            }\n\n            gm.DropDown(buttonRect);\n        }\n\n        static void ShowAssetsPopupMenu<T>(Rect buttonRect, string typeName, SerializedProperty serializedProperty, string fileExtension) where T : Object, new()\n        {\n            ShowAssetsPopupMenu<T>(buttonRect, typeName, serializedProperty, fileExtension, \"Default\");\n        }\n\n        static void AssetPopupMenuCallback(object userData)\n        {\n            var data = userData as object[];\n            var instanceID = (int)data[0];\n            var serializedProperty = (SerializedProperty)data[1];\n\n            serializedProperty.objectReferenceValue = EditorUtility.InstanceIDToObject(instanceID);\n            serializedProperty.m_SerializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/AssetSaveDialog.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditorInternal;\nusing UnityEditor.Scripting;\nusing System.Collections.Generic;\nusing System.IO;\n\nnamespace UnityEditor\n{\n    internal class AssetSaveDialog : EditorWindow\n    {\n        class Styles\n        {\n            public GUIStyle selected = \"OL SelectedRow\";\n            public GUIStyle box = \"OL Box\";\n            public GUIStyle button = \"LargeButton\";\n            public GUIStyle labelHeight = \"Label\";\n            public GUIContent saveSelected = EditorGUIUtility.TrTextContent(\"Save Selected\");\n            public GUIContent saveAll = EditorGUIUtility.TrTextContent(\"Save All\");\n            public GUIContent dontSave = EditorGUIUtility.TrTextContent(\"Don't Save\");\n            public GUIContent close = EditorGUIUtility.TrTextContent(\"Close\");\n            public float buttonWidth;\n            public Styles()\n            {\n                labelHeight = new GUIStyle(GUI.skin.label);\n                labelHeight.fixedHeight = 64;\n                buttonWidth = Mathf.Max(Mathf.Max(button.CalcSize(saveSelected).x, button.CalcSize(saveAll).x), button.CalcSize(dontSave).x);\n            }\n        }\n\n        static Styles s_Styles = null;\n        List<string> m_Assets;\n        List<string> m_AssetsToSave;\n        ListViewState m_LV = new ListViewState();\n        int m_InitialSelectedItem = -1;\n        bool[] m_SelectedItems;\n        List<GUIContent> m_Content;\n\n        void SetAssets(string[] assets)\n        {\n            m_Assets = new List<string>(assets);\n            RebuildLists(true);\n            m_AssetsToSave = new List<string>();\n        }\n\n        public static void ShowWindow(string[] inAssets, out string[] assetsThatShouldBeSaved)\n        {\n            int numMetaFiles = 0;\n            foreach (string path in inAssets)\n            {\n                if (path.EndsWith(\"meta\"))\n                    numMetaFiles++;\n            }\n            int numAssets = inAssets.Length - numMetaFiles;\n\n            if (numAssets == 0)\n            {\n                assetsThatShouldBeSaved = inAssets;\n                return;\n            }\n\n            string[] assets = new string[numAssets];\n            string[] metaFiles = new string[numMetaFiles];\n\n            numAssets = 0;\n            numMetaFiles = 0;\n\n            foreach (string path in inAssets)\n            {\n                if (path.EndsWith(\"meta\"))\n                    metaFiles[numMetaFiles++] = path;\n                else\n                    assets[numAssets++] = path;\n            }\n\n            AssetSaveDialog win = EditorWindow.GetWindowDontShow<AssetSaveDialog>();\n            win.titleContent = EditorGUIUtility.TrTextContent(\"Save Assets\");\n            win.SetAssets(assets);\n\n            win.minSize = new Vector2(400, 100);\n            win.maxSize = new Vector2(550, 550);\n\n            win.ShowModal();\n\n            assetsThatShouldBeSaved = new string[win.m_AssetsToSave.Count + numMetaFiles];\n            win.m_AssetsToSave.CopyTo(assetsThatShouldBeSaved, 0);\n            metaFiles.CopyTo(assetsThatShouldBeSaved, win.m_AssetsToSave.Count);\n        }\n\n        public static GUIContent GetContentForAsset(string path)\n        {\n            Texture icon = AssetDatabase.GetCachedIcon(path);\n            if (path.StartsWith(\"Library/\"))\n                path = ObjectNames.NicifyVariableName(AssetDatabase.LoadMainAssetAtPath(path).name);\n\n            if (path.StartsWith(\"Assets/\"))\n                path = path.Substring(7);\n\n            return new GUIContent(path, icon);\n        }\n\n        void OnGUI()\n        {\n            if (s_Styles == null)\n            {\n                s_Styles = new Styles();\n                minSize = new Vector2(500, 300);\n                position = new Rect(position.x, position.y, minSize.x, minSize.y);\n            }\n\n            GUILayout.Space(10);\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(10);\n            GUILayout.Label(\"Unity is about to save the following modified files. Unsaved changes will be lost!\");\n            GUILayout.Space(10);\n            GUILayout.EndHorizontal();\n            GUILayout.Space(10);\n\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(10);\n\n            int prevSelectedRow = m_LV.row;\n            int numSelected = 0;\n            foreach (ListViewElement el in ListViewGUILayout.ListView(m_LV, s_Styles.box))\n            {\n                if (m_SelectedItems[el.row] && Event.current.type == EventType.Repaint)\n                {\n                    Rect box = el.position;\n                    box.x += 1;\n                    box.y += 1;\n                    box.width -= 1;\n                    box.height -= 1;\n                    s_Styles.selected.Draw(box, false, false, false, false);\n                }\n\n                GUILayout.Label(m_Content[el.row], s_Styles.labelHeight);\n\n                if (ListViewGUILayout.HasMouseUp(el.position))\n                {\n                    Event.current.command = true;\n                    Event.current.control = true;\n                    ListViewGUILayout.MultiSelection(prevSelectedRow, el.row, ref m_InitialSelectedItem, ref m_SelectedItems);\n                }\n                if (m_SelectedItems[el.row])\n                    numSelected++;\n            }\n\n            GUILayout.Space(10);\n            GUILayout.EndHorizontal();\n            GUILayout.Space(10);\n\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(10);\n\n            if (GUILayout.Button(s_Styles.close, s_Styles.button, GUILayout.Width(s_Styles.buttonWidth)))\n            {\n                CloseWindow();\n            }\n\n            GUILayout.FlexibleSpace();\n\n            GUI.enabled = numSelected > 0;\n\n            bool allSelected = numSelected == m_Assets.Count;\n\n            if (GUILayout.Button(s_Styles.dontSave, s_Styles.button, GUILayout.Width(s_Styles.buttonWidth)))\n            {\n                IgnoreSelectedAssets();\n            }\n\n            if (GUILayout.Button(allSelected ? s_Styles.saveAll : s_Styles.saveSelected,\n                s_Styles.button, GUILayout.Width(s_Styles.buttonWidth)))\n            {\n                SaveSelectedAssets();\n            }\n\n            GUI.enabled = true;\n\n            GUILayout.Space(10);\n            GUILayout.EndHorizontal();\n\n            GUILayout.Space(10);\n\n            if (m_Assets.Count == 0)\n                CloseWindow();\n        }\n\n        void Cancel()\n        {\n            Close();\n            GUIUtility.ExitGUI();\n        }\n\n        void CloseWindow()\n        {\n            Close();\n            GUIUtility.ExitGUI();\n        }\n\n        void SaveSelectedAssets()\n        {\n            List<string> newAssets = new List<string>();\n            for (int i = 0; i < m_SelectedItems.Length; i++)\n            {\n                if (m_SelectedItems[i])\n                    m_AssetsToSave.Add(m_Assets[i]);\n                else\n                    newAssets.Add(m_Assets[i]);\n            }\n\n            m_Assets = newAssets;\n            RebuildLists(false);\n        }\n\n        void IgnoreSelectedAssets()\n        {\n            List<string> newAssets = new List<string>();\n            for (int i = 0; i < m_SelectedItems.Length; i++)\n            {\n                if (!m_SelectedItems[i])\n                    newAssets.Add(m_Assets[i]);\n            }\n\n            m_Assets = newAssets;\n            RebuildLists(false);\n\n            if (m_Assets.Count == 0)\n                CloseWindow();\n        }\n\n        void RebuildLists(bool selected)\n        {\n            m_LV.totalRows = m_Assets.Count;\n            m_SelectedItems = new bool[m_Assets.Count];\n            m_Content = new List<GUIContent>(m_Assets.Count);\n            for (int i = 0; i < m_Assets.Count; i++)\n            {\n                m_SelectedItems[i] = selected;\n                m_Content.Add(GetContentForAsset(m_Assets[i]));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/BumpMapSettingsFixingWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditorInternal;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    internal class BumpMapSettingsFixingWindow : EditorWindow\n    {\n        [RequiredByNativeCode]\n        public static void ShowSettingsWindow(string[] paths)\n        {\n            BumpMapSettingsFixingWindow win = EditorWindow.GetWindow<BumpMapSettingsFixingWindow>(true);\n            win.SetPaths(paths);\n            win.ShowUtility();\n        }\n\n        class Styles\n        {\n            public GUIStyle selected = \"OL SelectedRow\";\n            public GUIStyle box = \"OL Box\";\n            public GUIStyle button = \"LargeButton\";\n            public GUIContent overviewText = EditorGUIUtility.TrTextContent(\"A Material is using the texture as a normal map.\\nThe texture must be marked as a normal map in the import settings.\");\n        }\n\n        static Styles s_Styles = null;\n\n        ListViewState m_LV = new ListViewState();\n        string[] m_Paths;\n\n        public BumpMapSettingsFixingWindow()\n        {\n            titleContent = EditorGUIUtility.TrTextContent(\"NormalMap settings\");\n        }\n\n        public void SetPaths(string[] paths)\n        {\n            m_Paths = paths;\n            m_LV.totalRows = paths.Length;\n        }\n\n        void OnGUI()\n        {\n            if (s_Styles == null)\n            {\n                s_Styles = new Styles();\n                minSize = new Vector2(400, 300);\n                position = new Rect(position.x, position.y, minSize.x, minSize.y);\n            }\n\n            GUILayout.Space(5);\n            GUILayout.Label(s_Styles.overviewText);\n            GUILayout.Space(10);\n\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(10);\n            foreach (ListViewElement el in ListViewGUILayout.ListView(m_LV, s_Styles.box))\n            {\n                if (el.row == m_LV.row && Event.current.type == EventType.Repaint)\n                    s_Styles.selected.Draw(el.position, false, false, false, false);\n\n                GUILayout.Label(m_Paths[el.row]);\n            }\n            GUILayout.Space(10);\n            GUILayout.EndHorizontal();\n            GUILayout.Space(10);\n\n            GUILayout.BeginHorizontal();\n            GUILayout.FlexibleSpace();\n            if (GUILayout.Button(\"Fix now\", s_Styles.button))\n            {\n                InternalEditorUtility.BumpMapSettingsFixingWindowReportResult(1);\n                Close();\n            }\n\n            if (GUILayout.Button(\"Ignore\", s_Styles.button))\n            {\n                InternalEditorUtility.BumpMapSettingsFixingWindowReportResult(0);\n                Close();\n            }\n            GUILayout.Space(10);\n            GUILayout.EndHorizontal();\n\n            GUILayout.Space(10);\n        }\n\n        void OnDestroy()\n        {\n            InternalEditorUtility.BumpMapSettingsFixingWindowReportResult(0);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ButtonWithAnimatedIcon.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class EditorGUI\n    {\n        internal static bool ButtonWithRotatedIcon(Rect rect, GUIContent guiContent, float iconAngle, bool mouseDownButton, GUIStyle style)\n        {\n            // Button with text and background (no icon - it's rendered separately below)\n            bool buttonPressed;\n            if (mouseDownButton)\n                buttonPressed = DropdownButton(rect, GUIContent.Temp(guiContent.text, guiContent.tooltip), FocusType.Passive, style);\n            else\n                buttonPressed = GUI.Button(rect, GUIContent.Temp(guiContent.text, guiContent.tooltip), style);\n\n            // Icon (rendered left of text)\n            if (Event.current.type == EventType.Repaint && guiContent.image != null)\n            {\n                Vector2 iconSize = EditorGUIUtility.GetIconSize();\n                if (iconSize == Vector2.zero)\n                {\n                    iconSize.x = iconSize.y = rect.height - style.padding.vertical;\n                }\n\n                const float spaceBetweenIconAndText = 3f;\n                const float spaceBetweenIconAndTop = 3f;\n                Rect iconRect = new Rect(rect.x + style.padding.left - spaceBetweenIconAndText - iconSize.x, rect.y + style.padding.top + spaceBetweenIconAndTop, iconSize.x, iconSize.y);\n                if (iconAngle == 0f)\n                {\n                    GUI.DrawTexture(iconRect, guiContent.image);\n                }\n                else\n                {\n                    Matrix4x4 prevMatrix = GUI.matrix;\n                    GUIUtility.RotateAroundPivot(iconAngle, iconRect.center);\n                    GUI.DrawTexture(iconRect, guiContent.image);\n                    GUI.matrix = prevMatrix;\n                }\n            }\n            return buttonPressed;\n        }\n    }\n\n    // Ensure to call Clear() before setting a instance to null to prevent mem leaking\n    // due to CallbackController using a delegate for update calls (if not de-registering this\n    // delegate, it will keep the instance from being gc'ed)\n    internal class ButtonWithAnimatedIconRotation\n    {\n        readonly CallbackController m_CallbackController; // used for continuous repaints\n        readonly Func<float> m_AngleCallback;\n        readonly bool m_MouseDownButton;\n\n        public ButtonWithAnimatedIconRotation(Func<float> angleCallback, Action repaintCallback, float repaintsPerSecond, bool mouseDownButton)\n        {\n            m_CallbackController = new CallbackController(repaintCallback, repaintsPerSecond);\n            m_AngleCallback = angleCallback;\n            m_MouseDownButton = mouseDownButton;\n        }\n\n        public bool OnGUI(Rect rect, GUIContent guiContent, bool animate, GUIStyle style)\n        {\n            if (animate && !m_CallbackController.active)\n                m_CallbackController.Start();\n            if (!animate && m_CallbackController.active)\n                m_CallbackController.Stop();\n\n            float iconAngle = animate ? m_AngleCallback() : 0f;\n            return EditorGUI.ButtonWithRotatedIcon(rect, guiContent, iconAngle, m_MouseDownButton, style);\n        }\n\n        public void Clear()\n        {\n            m_CallbackController.Stop();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/CacheServerToggle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.Experimental;\n\nnamespace UnityEditor\n{\n    internal class CacheServerToggle\n    {\n        private readonly GUIContent m_CacheServerNotEnabledContent;\n        private readonly GUIContent m_CacheServerDisconnectedContent;\n        private readonly GUIContent m_CacheServerConnectedContent;\n        private readonly PopupLocation[] m_PopupLocation;\n\n        static CacheServerToggle()\n        {\n            AssetDatabase.cacheServerConnectionChanged += OnCacherServerConnectionChanged;\n        }\n\n        public CacheServerToggle()\n        {\n            m_CacheServerNotEnabledContent = EditorGUIUtility.TrIconContent(\"CacheServerDisabled\", \"Cache Server disabled\");\n            m_CacheServerDisconnectedContent = EditorGUIUtility.TrIconContent(\"CacheServerDisconnected\", \"Cache Server disconnected\");\n            m_CacheServerConnectedContent = EditorGUIUtility.TrIconContent(\"CacheServerConnected\", \"Cache Server connected\");\n            m_PopupLocation = new[] { PopupLocation.AboveAlignRight };\n        }\n\n        public void OnGUI()\n        {\n            var content = GetStatusContent();\n            var style = AppStatusBar.Styles.statusIcon;\n            var rect = GUILayoutUtility.GetRect(content, style);\n            if (GUI.Button(rect, content, style))\n            {\n                PopupWindow.Show(rect, new CacheServerWindow(), m_PopupLocation);\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        private GUIContent GetStatusContent()\n        {\n            if (!AssetDatabase.IsCacheServerEnabled())\n            {\n                return m_CacheServerNotEnabledContent;\n            }\n\n            if (!AssetDatabase.IsConnectedToCacheServer())\n            {\n                return m_CacheServerDisconnectedContent;\n            }\n\n            return m_CacheServerConnectedContent;\n        }\n\n        private static void OnCacherServerConnectionChanged(CacheServerConnectionChangedParameters param)\n        {\n            AppStatusBar.StatusChanged();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/CacheServerWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.Experimental;\nusing System;\n\nnamespace UnityEditor\n{\n    [InitializeOnLoad]\n    internal class CacheServerWindow : PopupWindowContent\n    {\n        private readonly GUIContent m_StatusMessageDisabled;\n        private readonly GUIContent m_StatusMessageConnected;\n        private readonly GUIContent m_StatusMessageError;\n        private readonly GUIContent m_OpenProjectSettings;\n        private readonly GUIContent m_UploadArtifacts;\n        private readonly GUIContent m_UploadShaderCache;\n        private readonly GUIContent m_UploadAllRevisions;\n        private readonly GUIContent m_RefreshIcon;\n\n        readonly string m_UploadArtifactsDefaultToolip = \"Queues the upload of the current revision of all Artifacts present in the project. Only revisions not found on the Accelerator are uploaded.\";\n        readonly string m_UploadShaderCacheDefaultToolip = \"Queues the upload of all Shaders, and their variants, from the Unity Shader Cache. Only shaders and/or variants not found on the Accelerator are uploaded.\";\n        readonly string m_UploadAllRevisionsDefaultToolip = \"Queues upload of all revisions of every Artifact in the project. Only revisions not found on the Accelerator are uploaded.\";\n        readonly string m_DisabledSettingPrefix = \"Uploading is currently disabled in Project Settings.\";\n\n        private readonly GUIStyle m_WindowStyle;\n\n        public CacheServerWindow()\n        {\n            m_StatusMessageDisabled = EditorGUIUtility.TrTextContent(\"No cache server connected\");\n            m_StatusMessageConnected = EditorGUIUtility.TrTextContent(\"Connected\");\n            m_StatusMessageError = EditorGUIUtility.TrTextContent(\"Attempting to reconnect\");\n            m_OpenProjectSettings = EditorGUIUtility.TrTextContent(\"Open Project Settings...\");\n            m_UploadArtifacts = EditorGUIUtility.TrTextContent(\"Upload Artifacts\", m_UploadArtifactsDefaultToolip);\n            m_UploadShaderCache = EditorGUIUtility.TrTextContent(\"Upload Shader Cache\", m_UploadShaderCacheDefaultToolip);\n            m_UploadAllRevisions = EditorGUIUtility.TrTextContent(\"Upload All Revisions\", m_UploadAllRevisionsDefaultToolip);\n            m_RefreshIcon = EditorGUIUtility.TrIconContent(\"Refresh\", \"Refresh connection\");\n\n            m_WindowStyle = new GUIStyle { padding = new RectOffset(6, 6, 6, 6) };\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            var exit = false;\n\n            bool isCacheConnected = AssetDatabase.IsConnectedToCacheServer();\n\n            bool isCacheEnabled = AssetDatabase.IsCacheServerEnabled();\n            bool isUploadEnabled = AssetDatabase.GetCacheServerEnableUpload();\n\n            GUILayout.BeginArea(rect, m_WindowStyle);\n            // Cache server connection url\n            if (isCacheEnabled)\n            {\n                var iconPosition = new Rect();\n                iconPosition.x = rect.width - (m_RefreshIcon.image.width / (Screen.dpi > 160 ? 2 : 1)) - m_WindowStyle.padding.right;\n                iconPosition.y = m_WindowStyle.padding.top;\n                iconPosition.width = m_RefreshIcon.image.width;\n                iconPosition.height = m_RefreshIcon.image.height;\n                GUIStyle helpIconStyle = EditorStyles.iconButton;\n                if (GUI.Button(iconPosition, m_RefreshIcon, helpIconStyle))\n                {\n                    AssetDatabase.RefreshSettings();\n                }\n\n                GUILayout.BeginHorizontal();\n                var style = new GUIStyle();\n                style.fontStyle = FontStyle.Bold;\n                style.normal.textColor = EditorStyles.boldLabel.normal.textColor;\n                if (!isCacheConnected)\n                {\n                    style.normal.textColor = new Color(0.97f, 0.32f, 0.31f);\n                }\n\n                if (GUILayout.Button(AssetDatabase.GetCacheServerAddress(), style))\n                {\n                    var url = $\"http://{AssetDatabase.GetCacheServerAddress()}:{AssetDatabase.GetCacheServerPort()}\";\n                    Application.OpenURL(url);\n                }\n                GUILayout.EndHorizontal();\n            }\n\n            // Connection status text label\n            GUILayout.BeginHorizontal();\n            var statusTextStyle = new GUIStyle()\n            {\n                normal = { textColor = Color.grey },\n                fontStyle = FontStyle.Italic\n            };\n            EditorGUILayout.LabelField(ConnectionStatusText(), statusTextStyle);\n            GUILayout.EndHorizontal();\n\n            if(isCacheConnected && isCacheEnabled)\n            {\n                // Divider line\n                var actionButtonLine = EditorGUILayout.GetControlRect(GUILayout.Height(1));\n                actionButtonLine.x -= 6;\n                actionButtonLine.width += 12;\n                EditorGUI.DrawRect(actionButtonLine, new Color(0.387f, 0.387f, 0.387f));\n\n                GUILayout.BeginHorizontal();\n                using (new EditorGUI.DisabledScope(!isUploadEnabled || !isCacheEnabled))\n                {\n                    // change tooltip based on Project Settings\n                    m_UploadArtifacts.tooltip = isUploadEnabled ? m_UploadArtifactsDefaultToolip : $\"{m_DisabledSettingPrefix} {m_UploadArtifactsDefaultToolip}\";\n                    m_UploadShaderCache.tooltip = isUploadEnabled ? m_UploadShaderCacheDefaultToolip : $\"{m_DisabledSettingPrefix} {m_UploadShaderCacheDefaultToolip}\";\n                    m_UploadAllRevisions.tooltip = isUploadEnabled ? m_UploadAllRevisionsDefaultToolip : $\"{m_DisabledSettingPrefix} {m_UploadAllRevisionsDefaultToolip}\";\n\n                    if (GUILayout.Button(m_UploadArtifacts, GUILayout.Width(110)))\n                    {\n                        CacheServer.UploadArtifacts();\n                    }\n\n                    if (GUILayout.Button(m_UploadShaderCache, GUILayout.Width(140)))\n                    {\n                        CacheServer.UploadShaderCache();\n                    }\n\n                    if (GUILayout.Button(m_UploadAllRevisions, GUILayout.Width(130)))\n                    {\n                        CacheServer.UploadArtifacts(uploadAllRevisions:true);\n                    }\n                }\n                GUILayout.EndHorizontal();\n            }\n\n            // Divider line\n            var lineRect = EditorGUILayout.GetControlRect(GUILayout.Height(1));\n            lineRect.x -= 6;\n            lineRect.width += 12;\n            EditorGUI.DrawRect(lineRect, new Color(0.387f, 0.387f, 0.387f));\n\n            // Open project settings button/label\n            GUILayout.BeginHorizontal();\n            if (GUILayout.Button(m_OpenProjectSettings, \"ControlLabel\"))\n            {\n                OpenProjectSettings();\n            }\n            GUILayout.EndHorizontal();\n            GUILayout.EndArea();\n\n            exit |= Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape;\n            if (exit)\n            {\n                editorWindow.Close();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        private GUIContent ConnectionStatusText()\n        {\n            GUIContent status = m_StatusMessageConnected;\n            if (!AssetDatabase.IsCacheServerEnabled())\n            {\n                status = m_StatusMessageDisabled;\n            }\n            else if (!AssetDatabase.IsConnectedToCacheServer())\n            {\n                status = m_StatusMessageError;\n            }\n            return status;\n        }\n\n        private void OpenProjectSettings()\n        {\n            var settings = SettingsWindow.Show(SettingsScope.Project, \"Project/Editor\");\n            if (settings == null)\n            {\n                Debug.LogError(\"Could not find Preferences for 'Project/Editor'\");\n            }\n        }\n\n        private void OpenPreferences()\n        {\n            var settings = SettingsWindow.Show(SettingsScope.User, \"Preferences/Cache Server (global)\");\n            if (settings == null)\n            {\n                Debug.LogError(\"Could not find Preferences for 'Preferences/Cache Server (global)'\");\n            }\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            int lines = AssetDatabase.IsCacheServerEnabled() ? 3 : 2;\n            bool isConnected = AssetDatabase.IsConnectedToCacheServer();\n            if (isConnected)\n                lines++;\n\n            int heightOfLines = (int)Math.Ceiling(EditorGUI.kSingleLineHeight * lines);\n            int heightOfWindowPadding = m_WindowStyle.padding.top + m_WindowStyle.padding.bottom;\n            int dividerLine = 2;\n\n            if (isConnected)\n                dividerLine += 2;\n\n            int width = 250;\n            if (isConnected)\n                width = 390;\n\n            return new Vector2(width, heightOfLines + heightOfWindowPadding + dividerLine);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/CallbackController.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class CallbackController\n    {\n        readonly Action m_Callback;\n        readonly float m_CallbacksPerSecond;\n        double m_NextCallback;\n\n        public CallbackController(Action callback, float callbacksPerSecond)\n        {\n            m_Callback = callback;\n            m_CallbacksPerSecond = Mathf.Max(callbacksPerSecond, 1f);\n        }\n\n        public bool active { get; private set; }\n\n        public void Start()\n        {\n            m_NextCallback = 0;\n            EditorApplication.update += Update;\n            active = true;\n        }\n\n        public void Stop()\n        {\n            EditorApplication.update -= Update;\n            active = false;\n        }\n\n        void Update()\n        {\n            double time = EditorApplication.timeSinceStartup;\n            if (time > m_NextCallback)\n            {\n                m_NextCallback = time + (1f / m_CallbacksPerSecond);\n                if (m_Callback != null)\n                    m_Callback();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ColorMutator.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal enum RgbaChannel { R, G, B, A }\n    internal enum HsvChannel { H, S, V }\n\n    // includes color setters for RGB float, RGB byte, and HSV\n    // each mode preserves maximum componential integrity until editing using a different mode\n    // exposure and HDR interfaces assume that the supplied originalColor and all per-channel modifications are in linear space\n    [Serializable]\n    internal class ColorMutator\n    {\n        // specifies the max byte value to use when decomposing a float color into bytes with exposure\n        // this is the value used by Photoshop\n        const byte k_MaxByteForOverexposedColor = 191;\n\n        internal static void DecomposeHdrColor(Color linearColorHdr, out Color32 baseLinearColor, out float exposure)\n        {\n            baseLinearColor = linearColorHdr;\n            var maxColorComponent = linearColorHdr.maxColorComponent;\n            // replicate Photoshops's decomposition behaviour\n            if (maxColorComponent == 0f || maxColorComponent <= 1f && maxColorComponent >= 1 / 255f)\n            {\n                exposure = 0f;\n\n                baseLinearColor.r = (byte)Mathf.RoundToInt(linearColorHdr.r * 255f);\n                baseLinearColor.g = (byte)Mathf.RoundToInt(linearColorHdr.g * 255f);\n                baseLinearColor.b = (byte)Mathf.RoundToInt(linearColorHdr.b * 255f);\n            }\n            else\n            {\n                // calibrate exposure to the max float color component\n                var scaleFactor = k_MaxByteForOverexposedColor / maxColorComponent;\n                exposure = Mathf.Log(255f / scaleFactor) / Mathf.Log(2f);\n\n                // maintain maximal integrity of byte values to prevent off-by-one errors when scaling up a color one component at a time\n                baseLinearColor.r = Math.Min(k_MaxByteForOverexposedColor, (byte)Mathf.CeilToInt(scaleFactor * linearColorHdr.r));\n                baseLinearColor.g = Math.Min(k_MaxByteForOverexposedColor, (byte)Mathf.CeilToInt(scaleFactor * linearColorHdr.g));\n                baseLinearColor.b = Math.Min(k_MaxByteForOverexposedColor, (byte)Mathf.CeilToInt(scaleFactor * linearColorHdr.b));\n            }\n        }\n\n        [SerializeField] private Color m_OriginalColor;\n        [SerializeField] private Color m_HDRBaseColor; // This field is needed to compute the correct exposure value. Without it, the exposure would have rounding errors.\n        [SerializeField] private byte[] m_Color = new byte[4];\n        [SerializeField] private float[] m_ColorHdr = new float[4];\n        [SerializeField] private float[] m_Hsv = new float[3];\n        [SerializeField] private float m_ExposureValue;\n        [SerializeField] private float m_BaseExposureValue;\n\n        public Color originalColor => m_OriginalColor;\n        public Color32 color => new(m_Color[(int)RgbaChannel.R], m_Color[(int)RgbaChannel.G], m_Color[(int)RgbaChannel.B], m_Color[(int)RgbaChannel.A]);\n        public Vector3 colorHsv => new(m_Hsv[(int)HsvChannel.H], m_Hsv[(int)HsvChannel.S], m_Hsv[(int)HsvChannel.V]);\n        public Color exposureAdjustedColor => new(m_ColorHdr[(int)RgbaChannel.R], m_ColorHdr[(int)RgbaChannel.G], m_ColorHdr[(int)RgbaChannel.B], m_ColorHdr[(int)RgbaChannel.A]);\n\n        public float exposureValue\n        {\n            get => m_ExposureValue;\n            set\n            {\n                if (Mathf.Approximately(m_ExposureValue, value))\n                    return;\n                m_ExposureValue = value;\n                var newRgbFloat = m_HDRBaseColor * Mathf.Pow(2f, m_ExposureValue - m_BaseExposureValue);\n                m_ColorHdr[(int)RgbaChannel.R] = FloatClampSafe(newRgbFloat.r);\n                m_ColorHdr[(int)RgbaChannel.G] = FloatClampSafe(newRgbFloat.g);\n                m_ColorHdr[(int)RgbaChannel.B] = FloatClampSafe(newRgbFloat.b);\n            }\n        }\n\n        static float FloatClampSafe(float value)\n        {\n            if (float.IsPositiveInfinity(value) || float.IsNaN(value))\n                return float.MaxValue;\n            if (float.IsNegativeInfinity(value))\n                return float.MinValue;\n            return value;\n        }\n\n        public byte GetColorChannel(RgbaChannel channel)\n        {\n            return m_Color[(int)channel];\n        }\n\n        public float GetColorChannelNormalized(RgbaChannel channel)\n        {\n            return m_Color[(int)channel] / 255f;\n        }\n\n        public void SetColorChannel(RgbaChannel channel, byte value)\n        {\n            var channelIndex = (int)channel;\n            if (m_Color[channelIndex] == value)\n                return;\n            m_Color[channelIndex] = value;\n            m_ColorHdr[channelIndex] = value / 255f;\n            if (channel != RgbaChannel.A)\n                m_ColorHdr[channelIndex] *= Mathf.Pow(2f, m_ExposureValue);\n            m_HDRBaseColor = new Color(m_ColorHdr[0], m_ColorHdr[1], m_ColorHdr[2], m_ColorHdr[3]);\n            Color.RGBToHSV(color, out m_Hsv[(int)HsvChannel.H], out m_Hsv[(int)HsvChannel.S], out m_Hsv[(int)HsvChannel.V]);\n        }\n\n        public void SetColorChannel(RgbaChannel channel, float normalizedValue)\n        {\n            SetColorChannel(channel, (byte)Mathf.RoundToInt(Mathf.Clamp01(normalizedValue) * 255f));\n        }\n\n        public float GetColorChannelHdr(RgbaChannel channel)\n        {\n            return m_ColorHdr[(int)channel];\n        }\n\n        public void SetColorChannelHdr(RgbaChannel channel, float value)\n        {\n            if (Mathf.Approximately(m_ColorHdr[(int)channel], value))\n                return;\n            m_ColorHdr[(int)channel] = value;\n            m_HDRBaseColor = new Color(m_ColorHdr[0], m_ColorHdr[1], m_ColorHdr[2], m_ColorHdr[3]);\n            OnRgbaHdrChannelChanged((int)channel);\n            m_BaseExposureValue = m_ExposureValue;\n        }\n\n        public float GetColorChannel(HsvChannel channel) => m_Hsv[(int)channel];\n\n        public void SetColorChannel(HsvChannel channel, float value)\n        {\n            m_Hsv[(int)channel] = Mathf.Clamp01(value);\n\n            var newColor = Color.HSVToRGB(m_Hsv[(int)HsvChannel.H], m_Hsv[(int)HsvChannel.S], m_Hsv[(int)HsvChannel.V]);\n            m_Color[(int)RgbaChannel.R] = (byte)Mathf.CeilToInt(newColor.r * 255f);\n            m_Color[(int)RgbaChannel.G] = (byte)Mathf.CeilToInt(newColor.g * 255f);\n            m_Color[(int)RgbaChannel.B] = (byte)Mathf.CeilToInt(newColor.b * 255f);\n\n            newColor *= Mathf.Pow(2f, m_ExposureValue);\n            m_ColorHdr[(int)RgbaChannel.R] = newColor.r;\n            m_ColorHdr[(int)RgbaChannel.G] = newColor.g;\n            m_ColorHdr[(int)RgbaChannel.B] = newColor.b;\n            m_HDRBaseColor = new Color(m_ColorHdr[0], m_ColorHdr[1], m_ColorHdr[2], m_ColorHdr[3]);\n        }\n\n        public ColorMutator(Color originalColor)\n        {\n            m_OriginalColor = originalColor;\n            Reset();\n        }\n\n        public void Reset()\n        {\n            if (m_ColorHdr is not { Length: 4 })\n                m_ColorHdr = new float[4];\n            if (m_Color is not { Length: 4 })\n                m_Color = new byte[4];\n\n            m_ColorHdr[(int)RgbaChannel.R] = m_OriginalColor.r;\n            m_ColorHdr[(int)RgbaChannel.G] = m_OriginalColor.g;\n            m_ColorHdr[(int)RgbaChannel.B] = m_OriginalColor.b;\n            m_ColorHdr[(int)RgbaChannel.A] = m_OriginalColor.a;\n            m_HDRBaseColor = new Color(m_ColorHdr[0], m_ColorHdr[1], m_ColorHdr[2], m_ColorHdr[3]);\n\n            OnRgbaHdrChannelChanged(-1);\n            m_BaseExposureValue = m_ExposureValue;\n        }\n\n        void OnRgbaHdrChannelChanged(int channel)\n        {\n            m_Color[(int)RgbaChannel.A] = (byte)Mathf.RoundToInt(Mathf.Clamp01(m_ColorHdr[(int)RgbaChannel.A]) * 255f);\n            if (channel == (int)RgbaChannel.A)\n                return;\n\n            DecomposeHdrColor(exposureAdjustedColor, out var baseColor, out m_ExposureValue);\n\n            m_Color[(int)RgbaChannel.R] = baseColor.r;\n            m_Color[(int)RgbaChannel.G] = baseColor.g;\n            m_Color[(int)RgbaChannel.B] = baseColor.b;\n            Color.RGBToHSV(color, out m_Hsv[(int)HsvChannel.H], out m_Hsv[(int)HsvChannel.S], out m_Hsv[(int)HsvChannel.V]);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ColorPicker.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Accessibility;\n\nnamespace UnityEditor\n{\n    internal class ColorPicker : EditorWindow\n    {\n        private const string k_HeightPrefKey = \"CPickerHeight\";\n        private const string k_ShowDefaultsPrefKey = \"CPDefaultsShow\";\n        private const string k_ShowPresetsPrefKey = \"CPPresetsShow\";\n        // HDR and LDR have different slider mode pref keys because they have different defaults for the sake of discoverability\n        private const string k_SliderModePrefKey = \"CPSliderMode\";\n        private const string k_SliderModeHDRPrefKey = \"CPSliderModeHDR\";\n\n        // the default max amount of stops to use for the intensity slider; same as in Photoshop/Affinity\n        private const float k_DefaultExposureSliderMax = 10f;\n\n        public static string presetsEditorPrefID { get { return \"Color\"; } }\n\n        internal static readonly Color32 SwatchSelectionColor = new Color32(57, 121, 187, 255);\n\n        [SerializeField]\n        bool m_HDR;\n\n        [SerializeField]\n        private ColorMutator m_Color;\n\n        #pragma warning disable 649\n        [SerializeField]\n        Texture2D m_ColorSlider;\n\n        [SerializeField]\n        Color[] m_Colors;\n        const int kHueRes = 64;\n        const int kColorBoxSize = 32;\n        [SerializeField]\n        Texture2D m_ColorBox;\n        static int s_Slider2Dhash = \"Slider2D\".GetHashCode();\n        [SerializeField]\n        bool m_ShowDefaults = true;\n        [SerializeField]\n        bool m_ShowPresets = true;\n\n        [SerializeField]\n        bool m_ShowAlpha = true;\n\n        [SerializeField]\n        Texture2D m_RTexture; float m_RTextureG = -1, m_RTextureB = -1;\n        [SerializeField]\n        Texture2D m_GTexture; float m_GTextureR = -1, m_GTextureB = -1;\n        [SerializeField]\n        Texture2D m_BTexture; float m_BTextureR = -1, m_BTextureG = -1;\n\n        [SerializeField]\n        Texture2D m_HueTexture; float m_HueTextureS = -1, m_HueTextureV = -1;\n        [SerializeField]\n        Texture2D m_SatTexture; float m_SatTextureH = -1, m_SatTextureV = -1;\n        [SerializeField]\n        Texture2D m_ValTexture; float m_ValTextureH = -1, m_ValTextureS = -1;\n\n        [NonSerialized]\n        int m_TextureColorBoxMode = -1;\n        [SerializeField]\n        float m_LastConstant = -1;\n\n        [NonSerialized]\n        bool m_ColorSpaceBoxDirty;\n\n        enum ColorBoxMode { HSV, EyeDropper }\n\n        [SerializeField]\n        ColorBoxMode m_ColorBoxMode = ColorBoxMode.HSV;\n\n        enum SliderMode { RGB, RGBFloat, HSV }\n\n        [SerializeField]\n        SliderMode m_SliderMode = SliderMode.HSV;\n\n        [SerializeField]\n        Texture2D m_AlphaTexture; float m_OldAlpha = -1;\n\n        [SerializeField]\n        GUIView m_DelegateView;\n\n        private Action<Color> m_ColorChangedCallback;\n\n        [SerializeField]\n        int m_ModalUndoGroup = -1;\n\n        // hdr float slider ranges dynamically adjust on mouse up\n        private float m_FloatSliderMaxOnMouseDown;\n        private bool m_DraggingFloatSlider;\n\n        // the exposure slider range can dynamically grow if needed per color picker \"session\"\n        private float m_ExposureSliderMax = k_DefaultExposureSliderMax;\n\n        PresetLibraryEditor<ColorPresetLibrary> m_ColorLibraryEditor;\n        PresetLibraryEditorState m_ColorLibraryEditorState;\n\n        public static Color color\n        {\n            get { return instance.m_Color.exposureAdjustedColor; }\n            set\n            {\n                instance.SetColor(value);\n                instance.Repaint();\n            }\n        }\n\n        public static bool visible\n        {\n            get { return s_Instance != null; }\n        }\n\n        public static ColorPicker instance\n        {\n            get\n            {\n                if (!s_Instance)\n                {\n                    var hmm = Resources.FindObjectsOfTypeAll(typeof(ColorPicker));\n                    if (hmm != null && hmm.Length > 0)\n                        s_Instance = (ColorPicker)hmm[0];\n                    if (!s_Instance)\n                    {\n                        s_Instance = CreateInstance<ColorPicker>();\n                        s_Instance.wantsMouseMove = true;\n                    }\n                }\n                return s_Instance;\n            }\n        }\n        static ColorPicker s_Instance;\n\n        public static int originalKeyboardControl { get; private set; }\n\n        // ------- Soerens 2D slider --------\n\n        static void swap(ref float f1, ref float f2) { float tmp = f1; f1 = f2; f2 = tmp; }\n\n        Vector2 Slider2D(Rect rect, Vector2 value, Vector2 maxvalue, Vector2 minvalue, GUIStyle thumbStyle)\n        {\n            int id = GUIUtility.GetControlID(s_Slider2Dhash, FocusType.Passive);\n\n            // test max and min\n            if (maxvalue.x < minvalue.x) // swap\n                swap(ref maxvalue.x, ref minvalue.x);\n            if (maxvalue.y < minvalue.y)\n                swap(ref maxvalue.y, ref minvalue.y);\n\n            Event e = Event.current;\n\n            switch (e.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                {\n                    if (rect.Contains(e.mousePosition)) // inside this control\n                    {\n                        GUIUtility.hotControl = id;\n                        GUIUtility.keyboardControl = 0;\n                        value.x = (e.mousePosition.x - rect.x) / rect.width * (maxvalue.x - minvalue.x);\n                        value.y = (e.mousePosition.y - rect.y) / rect.height * (maxvalue.y - minvalue.y);\n                        GUI.changed = true;\n\n                        Event.current.Use();\n                    }\n                    break;\n                }\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n                        e.Use();\n                    }\n                    break;\n                case EventType.MouseDrag:\n                {\n                    if (GUIUtility.hotControl != id)\n                        break;\n\n                    // move thumb to mouse position\n                    value.x = (e.mousePosition.x - rect.x) / rect.width * (maxvalue.x - minvalue.x);\n                    value.y = (e.mousePosition.y - rect.y) / rect.height * (maxvalue.y - minvalue.y);\n\n                    // clamp\n                    value.x = Mathf.Clamp(value.x, minvalue.x, maxvalue.x);\n                    value.y = Mathf.Clamp(value.y, minvalue.y, maxvalue.y);\n                    GUI.changed = true;\n                    Event.current.Use();\n                }\n                break;\n\n                case EventType.Repaint:\n                {\n                    // thumb (set to black for light colors to prevent blending with background)\n                    var oldColor = GUI.color;\n                    GUI.color = VisionUtility.ComputePerceivedLuminance(color) > Styles.highLuminanceThreshold ?\n                        Styles.highLuminanceContentColor : Styles.lowLuminanceContentColor;\n\n                    var thumbRect = new Rect\n                    {\n                        size = thumbStyle.CalcSize(GUIContent.none),\n                        center = new Vector2(\n                            value.x / (maxvalue.x - minvalue.x) * rect.width + rect.x,\n                            value.y / (maxvalue.y - minvalue.y) * rect.height + rect.y\n                        )\n                    };\n                    thumbStyle.Draw(thumbRect, GUIContent.none, id);\n\n                    GUI.color = oldColor;\n                }\n                break;\n            }\n            return value;\n        }\n\n        void RGBSliders()\n        {\n            var r = m_Color.GetColorChannelNormalized(RgbaChannel.R);\n            var g = m_Color.GetColorChannelNormalized(RgbaChannel.G);\n            var b = m_Color.GetColorChannelNormalized(RgbaChannel.B);\n\n            m_RTexture = Update1DSlider(m_RTexture, kColorBoxSize, g, b, ref m_RTextureG, ref m_RTextureB, 0, false);\n            m_GTexture = Update1DSlider(m_GTexture, kColorBoxSize, r, b, ref m_GTextureR, ref m_GTextureB, 1, false);\n            m_BTexture = Update1DSlider(m_BTexture, kColorBoxSize, r, g, ref m_BTextureR, ref m_BTextureG, 2, false);\n\n            RGBSlider(\"R\", RgbaChannel.R, m_RTexture);\n            GUILayout.Space(Styles.extraVerticalSpacing);\n            RGBSlider(\"G\", RgbaChannel.G, m_GTexture);\n            GUILayout.Space(Styles.extraVerticalSpacing);\n            RGBSlider(\"B\", RgbaChannel.B, m_BTexture);\n            GUILayout.Space(Styles.extraVerticalSpacing);\n        }\n\n        void RGBSlider(string label, RgbaChannel channel, Texture2D sliderBackground)\n        {\n            float value;\n            switch (m_SliderMode)\n            {\n                case SliderMode.RGB:\n                    value = m_Color.GetColorChannel(channel);\n                    EditorGUI.BeginChangeCheck();\n                    value = EditorGUILayout.SliderWithTexture(\n                        GUIContent.Temp(label), value, 0f, 255f, EditorGUI.kIntFieldFormatString, 0f, 255f, sliderBackground\n                    );\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        m_Color.SetColorChannel(channel, value / 255f);\n                        OnColorChanged();\n                    }\n                    m_DraggingFloatSlider = false;\n                    break;\n                case SliderMode.RGBFloat:\n                    value = m_Color.GetColorChannelHdr(channel);\n                    var maxRgbNormalized = ((Color)m_Color.color).maxColorComponent;\n                    var evtType = Event.current.type;\n                    var sliderMax = m_HDR && m_Color.exposureAdjustedColor.maxColorComponent > 1f ? m_Color.exposureAdjustedColor.maxColorComponent / maxRgbNormalized : 1f;\n                    var textFieldMax = m_HDR ? float.MaxValue : 1f;\n                    EditorGUI.BeginChangeCheck();\n                    value = EditorGUILayout.SliderWithTexture(\n                        GUIContent.Temp(label), value,\n                        0f, m_DraggingFloatSlider ? m_FloatSliderMaxOnMouseDown : sliderMax,\n                        EditorGUI.kFloatFieldFormatString,\n                        0f, textFieldMax,\n                        sliderBackground\n                    );\n                    switch (evtType)\n                    {\n                        case EventType.MouseDown:\n                            m_FloatSliderMaxOnMouseDown = sliderMax;\n                            m_DraggingFloatSlider = true;\n                            break;\n                        case EventType.MouseUp:\n                            m_DraggingFloatSlider = false;\n                            break;\n                    }\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        m_Color.SetColorChannelHdr(channel, value);\n                        OnColorChanged();\n                    }\n                    break;\n            }\n        }\n\n        Texture2D Update1DSlider(\n            Texture2D tex, int xSize, float const1, float const2, ref float oldConst1, ref float oldConst2, int idx, bool hsvSpace\n        )\n        {\n            if (!tex || const1 != oldConst1 || const2 != oldConst2)\n            {\n                if (!tex)\n                    tex = MakeTexture(xSize, 2);\n\n                Color[] colors = new Color[xSize * 2];\n                Color start = Color.black, step = Color.black;\n                switch (idx)\n                {\n                    case 0:\n                        start = new Color(0, const1, const2, 1);\n                        step = new Color(1, 0, 0, 0);\n                        break;\n                    case 1:\n                        start = new Color(const1, 0, const2, 1);\n                        step = new Color(0, 1, 0, 0);\n                        break;\n                    case 2:\n                        start = new Color(const1, const2, 0, 1);\n                        step = new Color(0, 0, 1, 0);\n                        break;\n                    case 3:\n                        start = m_Color.color;\n                        start.a = 0f;\n                        step = new Color(0, 0, 0, 1);\n                        break;\n                }\n                FillArea(xSize, 2, colors, start, step, new Color(0, 0, 0, 0), !hsvSpace && m_HDR);\n                if (hsvSpace)\n                    HSVToRGBArray(colors, m_HDR);\n\n                oldConst1 = const1;\n                oldConst2 = const2;\n                tex.SetPixels(colors);\n                tex.Apply();\n            }\n            return tex;\n        }\n\n        void HSVSliders()\n        {\n            var h = m_Color.GetColorChannel(HsvChannel.H);\n            var s = m_Color.GetColorChannel(HsvChannel.S);\n            var v = m_Color.GetColorChannel(HsvChannel.V);\n\n            m_HueTexture = Update1DSlider(m_HueTexture, kHueRes, 1, 1, ref m_HueTextureS, ref m_HueTextureV, 0, true);\n            m_SatTexture = Update1DSlider(m_SatTexture, kColorBoxSize, h, Mathf.Max(v, .2f), ref m_SatTextureH, ref m_SatTextureV, 1, true);\n            m_ValTexture = Update1DSlider(m_ValTexture, kColorBoxSize, h, s, ref m_ValTextureH, ref m_ValTextureS, 2, true);\n\n            EditorGUI.BeginChangeCheck();\n            h = EditorGUILayout.SliderWithTexture(\n                GUIContent.Temp(\"H\"), h * 360f, 0f, 360f, EditorGUI.kIntFieldFormatString, m_HueTexture\n            );\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_Color.SetColorChannel(HsvChannel.H, h / 360f);\n                OnColorChanged();\n            }\n            GUILayout.Space(Styles.extraVerticalSpacing);\n\n            EditorGUI.BeginChangeCheck();\n            s = EditorGUILayout.SliderWithTexture(\n                GUIContent.Temp(\"S\"), s * 100f, 0f, 100f, EditorGUI.kIntFieldFormatString, m_SatTexture\n            );\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_Color.SetColorChannel(HsvChannel.S, s / 100f);\n                OnColorChanged();\n            }\n            GUILayout.Space(Styles.extraVerticalSpacing);\n\n            EditorGUI.BeginChangeCheck();\n            v = EditorGUILayout.SliderWithTexture(\n                GUIContent.Temp(\"V\"), v * 100f, 0f, 100f, EditorGUI.kIntFieldFormatString, m_ValTexture\n            );\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_Color.SetColorChannel(HsvChannel.V, v / 100f);\n                OnColorChanged();\n            }\n            GUILayout.Space(Styles.extraVerticalSpacing);\n        }\n\n        static void FillArea(int xSize, int ySize, Color[] retval, Color topLeftColor, Color rightGradient, Color downGradient, bool convertToGamma)\n        {\n            // Calc the deltas for stepping.\n            Color rightDelta = new Color(0, 0, 0, 0), downDelta  = new Color(0, 0, 0, 0);\n            if (xSize > 1)\n                rightDelta = rightGradient / (xSize - 1);\n            if (ySize > 1)\n                downDelta = downGradient / (ySize - 1);\n\n            // Assign all colors into the array\n            Color p = topLeftColor;\n            int current = 0;\n            for (int y = 0; y < ySize; y++)\n            {\n                Color p2 = p;\n                for (int x = 0; x < xSize; x++)\n                {\n                    retval[current++] = convertToGamma ? p2.gamma : p2;\n                    p2 += rightDelta;\n                }\n                p += downDelta;\n            }\n        }\n\n        static void HSVToRGBArray(Color[] colors, bool convertToGamma)\n        {\n            int s = colors.Length;\n            for (int i = 0; i < s; i++)\n            {\n                Color c = colors[i];\n                Color c2 = Color.HSVToRGB(c.r, c.g, c.b);\n                c2.a = c.a;\n                colors[i] = convertToGamma ? c2.gamma : c2;\n            }\n        }\n\n        public static Texture2D MakeTexture(int width, int height)\n        {\n            Texture2D tex = new Texture2D(width, height, TextureFormat.RGBA32, false, true)\n            {\n                hideFlags = HideFlags.HideAndDontSave, wrapMode = TextureWrapMode.Clamp\n            };\n            return tex;\n        }\n\n        void DrawColorSpaceBox(Rect colorBoxRect, float constantValue)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            // If we've switched mode, regenerate box\n            if ((int)m_ColorBoxMode != m_TextureColorBoxMode)\n            {\n                int xSize = kColorBoxSize, ySize = kColorBoxSize;\n\n                if (m_ColorBox == null)\n                    m_ColorBox = MakeTexture(xSize, ySize);\n\n                if (m_ColorBox.width != xSize || m_ColorBox.height != ySize)\n                    m_ColorBox.Reinitialize(xSize, ySize);\n            }\n\n            if ((int)m_ColorBoxMode != m_TextureColorBoxMode || m_LastConstant != constantValue || m_ColorSpaceBoxDirty)\n            {\n                m_Colors = m_ColorBox.GetPixels(0);\n                int xSize = m_ColorBox.width;\n                int ySize = m_ColorBox.height;\n\n                FillArea(xSize, ySize, m_Colors, new Color(m_Color.GetColorChannel(HsvChannel.H), 0, 0, 1), new Color(0, 1, 0, 0), new Color(0, 0, 1, 0), false);\n                HSVToRGBArray(m_Colors, m_HDR);\n\n                m_ColorBox.SetPixels(m_Colors, 0);\n                m_ColorBox.Apply(true);\n                m_LastConstant = constantValue;\n                m_TextureColorBoxMode = (int)m_ColorBoxMode;\n            }\n            Graphics.DrawTexture(colorBoxRect, m_ColorBox, new Rect(.5f / m_ColorBox.width, .5f / m_ColorBox.height, 1 - 1f / m_ColorBox.width, 1 - 1f / m_ColorBox.height), 0, 0, 0, 0, new Color(.5f, .5f, .5f, .5f));\n        }\n\n        static class Styles\n        {\n            public const float fixedWindowWidth = 233;\n            public const float hexFieldWidth = 85f;\n            public const float sliderModeFieldWidth = hexFieldWidth;\n            public const float channelSliderLabelWidth = 14f;\n            public const float sliderTextFieldWidth = 45f;\n            public const float highLuminanceThreshold = 0.5f;\n            public const float extraVerticalSpacing = 8f - EditorGUI.kControlVerticalSpacingLegacy;\n\n            public static readonly float hueDialThumbSize;\n\n            public static readonly RectOffset colorBoxPadding = new RectOffset(6, 6, 6, 6);\n\n            public static readonly Color lowLuminanceContentColor = Color.white;\n            public static readonly Color highLuminanceContentColor = Color.black;\n\n            public static readonly GUIStyle originalColorSwatch = \"ColorPickerOriginalColor\";\n            public static readonly GUIStyle currentColorSwatch = \"ColorPickerCurrentColor\";\n            public static readonly GUIStyle colorBoxThumb = \"ColorPicker2DThumb\";\n            public static readonly GUIStyle hueDialBackground = \"ColorPickerHueRing\";\n            public static readonly GUIStyle hueDialBackgroundHDR = \"ColorPickerHueRing HDR\";\n            public static readonly GUIStyle hueDialThumb = \"ColorPickerHueRingThumb\";\n            public static readonly GUIStyle sliderBackground = \"ColorPickerSliderBackground\";\n            public static readonly GUIStyle background = \"ColorPickerBackground\";\n            public static readonly GUIStyle exposureSwatch = \"ColorPickerExposureSwatch\";\n            public static readonly GUIStyle selectedExposureSwatchStroke = \"ColorPickerCurrentExposureSwatchBorder\";\n\n            public static readonly GUIContent eyeDropper = EditorGUIUtility.TrIconContent(\"EyeDropper.Large\", \"Pick a color from the screen.\");\n            public static readonly GUIContent exposureValue = EditorGUIUtility.TrTextContent(\"Intensity\", \"Number of stops to over- or under-expose the color. The intensity calculates each time based on the predefined max color component of 191 (0.749) when Color Picker opens.\");\n            public static readonly GUIContent hexLabel = EditorGUIUtility.TrTextContent(\"Hexadecimal\");\n            public static readonly GUIContent presetsToggle = EditorGUIUtility.TrTextContent(\"Swatches\");\n            public static readonly GUIContent defaultsToggle = EditorGUIUtility.TrTextContent(\"Defaults\");\n\n            public static readonly ScalableGUIContent originalColorSwatchFill =\n                new ScalableGUIContent(string.Empty, \"The original color. Click this swatch to reset the color picker to this value.\", \"ColorPicker-OriginalColor\");\n            public static readonly ScalableGUIContent currentColorSwatchFill =\n                new ScalableGUIContent(string.Empty, \"The new color.\", \"ColorPicker-CurrentColor\");\n            public static readonly ScalableGUIContent hueDialThumbFill = new ScalableGUIContent(\"ColorPicker-HueRing-Thumb-Fill\");\n\n            // force load the checker background from the light skin\n            public static readonly Texture2D alphaSliderCheckerBackground =\n                EditorGUIUtility.LoadRequired(\"Previews/Textures/textureChecker.png\") as Texture2D;\n\n            public static readonly GUIContent RGB0_255Mode = EditorGUIUtility.TrTextContent(\"RGB 0-255\");\n            public static readonly GUIContent RGB0_1Mode = EditorGUIUtility.TrTextContent(\"RGB 0-1.0\");\n            public static readonly GUIContent RGB0_InfMode = EditorGUIUtility.TrTextContent(\"RGB 0-Inf\");\n            public static readonly GUIContent RGBHSVMode = EditorGUIUtility.TrTextContent(\"HSV\");\n\n            public static readonly GUIContent[] sliderLDRModeLabels = new[]\n            {\n                RGB0_255Mode,\n                RGB0_1Mode,\n                RGBHSVMode\n            };\n\n            public static readonly GUIContent[] sliderHDRModeLabels = new[]\n            {\n                RGB0_255Mode,\n                RGB0_InfMode,\n                RGBHSVMode\n            };\n\n            public static readonly int[] sliderModeValues = new[] { 0, 1, 2 };\n\n            static Styles()\n            {\n                var thumbSize = hueDialThumb.CalcSize(hueDialThumbFill);\n                hueDialThumbSize = Mathf.Max(thumbSize.x, thumbSize.y);\n            }\n        }\n\n        public string currentPresetLibrary\n        {\n            get\n            {\n                InitializePresetsLibraryIfNeeded();\n                return m_ColorLibraryEditor.currentLibraryWithoutExtension;\n            }\n            set\n            {\n                InitializePresetsLibraryIfNeeded();\n                m_ColorLibraryEditor.currentLibraryWithoutExtension = value;\n            }\n        }\n\n        void InitializePresetsLibraryIfNeeded()\n        {\n            if (m_ColorLibraryEditorState == null)\n            {\n                m_ColorLibraryEditorState = new PresetLibraryEditorState(presetsEditorPrefID);\n                m_ColorLibraryEditorState.TransferEditorPrefsState(true);\n            }\n\n            if (m_ColorLibraryEditor == null)\n            {\n                var saveLoadHelper = new ScriptableObjectSaveLoadHelper<ColorPresetLibrary>(\"colors\", SaveType.Text);\n                m_ColorLibraryEditor = new PresetLibraryEditor<ColorPresetLibrary>(saveLoadHelper, m_ColorLibraryEditorState, OnClickedPresetSwatch)\n                {\n                    previewAspect = 1f,\n                    minMaxPreviewHeight = new Vector2(ColorPresetLibrary.kSwatchSize, ColorPresetLibrary.kSwatchSize),\n                    settingsMenuRightMargin = 2f,\n                    useOnePixelOverlappedGrid = true,\n                    alwaysShowScrollAreaHorizontalLines = false,\n                    marginsForGrid = new RectOffset(0, 0, 2, 2),\n                    marginsForList = new RectOffset(0, 5, 2, 2)\n                };\n                m_ColorLibraryEditor.InitializeGrid(Styles.fixedWindowWidth - (Styles.background.padding.left + Styles.background.padding.right));\n            }\n        }\n\n        void OnClickedPresetSwatch(int clickCount, object presetObject)\n        {\n            Color color = (Color)presetObject;\n            // extract RGB if not in HDR mode\n            if (!m_HDR && color.maxColorComponent > 1f)\n                color = new ColorMutator(color).color;\n\n            SetColor(color);\n        }\n\n        private Color GetGUIColor(Color color)\n        {\n            return m_HDR ? color.gamma : color;\n        }\n\n        void DoColorSwatchAndEyedropper()\n        {\n            GUILayout.BeginHorizontal();\n\n            var oldGUIColor = GUI.color;\n            GUI.color = Color.white;\n\n            Event evt = Event.current;\n            Rect position = GUILayoutUtility.GetRect(Styles.eyeDropper, GUIStyle.none, GUILayout.Width(40), GUILayout.ExpandWidth(false));\n            bool startEyeDropper = false;\n            if (evt.type == EventType.Repaint || !evt.isDirectManipulationDevice)\n                startEyeDropper = GUI.Button(position, Styles.eyeDropper, GUIStyle.none);\n            // For a direct manipulation device, the color picking is on a drag&drop, so we just need to start the eyeDropper on mouseDown instead of mouseUp\n            else if (evt.type == EventType.MouseDown && position.Contains(evt.mousePosition))\n                startEyeDropper = true;\n\n            if (startEyeDropper)\n            {\n                GUIUtility.keyboardControl = 0;\n                EyeDropper.Start(m_Parent);\n                m_ColorBoxMode = ColorBoxMode.EyeDropper;\n                GUIUtility.ExitGUI();\n            }\n\n            // current swatch and original swatch have the same size, so they can lay out in the same row\n            var rect = GUILayoutUtility.GetRect(Styles.currentColorSwatchFill, Styles.currentColorSwatch, GUILayout.ExpandWidth(true));\n\n            var swatchSize = Styles.currentColorSwatch.CalcSize(Styles.currentColorSwatchFill);\n            var swatchRect = new Rect\n            {\n                size = swatchSize,\n                y = rect.y,\n                x = rect.xMax - swatchSize.x\n            };\n\n            var backgroundColor = GUI.backgroundColor;\n            var contentColor = GUI.contentColor;\n\n            var id = GUIUtility.GetControlID(FocusType.Passive);\n            if (evt.type == EventType.Repaint)\n            {\n                GUI.backgroundColor = m_Color.exposureAdjustedColor.a == 1f ? Color.clear : Color.white;\n                GUI.contentColor = GetGUIColor(m_Color.exposureAdjustedColor);\n                Styles.currentColorSwatch.Draw(swatchRect, Styles.currentColorSwatchFill, id);\n            }\n\n            swatchRect.x -= swatchRect.width;\n            GUI.backgroundColor = m_Color.originalColor.a == 1f ? Color.clear : Color.white;\n            GUI.contentColor = GetGUIColor(m_Color.originalColor);\n            if (GUI.Button(swatchRect, Styles.originalColorSwatchFill, Styles.originalColorSwatch))\n            {\n                m_Color.Reset();\n                evt.Use();\n                OnColorChanged();\n            }\n\n            GUI.backgroundColor = backgroundColor;\n            GUI.contentColor = contentColor;\n            GUI.color = oldGUIColor;\n\n            GUILayout.EndHorizontal();\n        }\n\n        void DoColorSpaceGUI()\n        {\n            var backgroundStyle = m_HDR ? Styles.hueDialBackgroundHDR : Styles.hueDialBackground;\n            var dialSize = backgroundStyle.CalcSize(GUIContent.none);\n            var dialRect = GUILayoutUtility.GetRect(dialSize.x, dialSize.y);\n\n            var oldGUIColor = GUI.color;\n            GUI.color = Color.white;\n\n            switch (m_ColorBoxMode)\n            {\n                case ColorBoxMode.HSV:\n\n                    dialRect.x += (dialRect.width - dialRect.height) * 0.5f;\n                    dialRect.width = dialRect.height;\n                    var hue = m_Color.GetColorChannel(HsvChannel.H);\n                    var oldColor = GUI.contentColor;\n                    GUI.contentColor = GetGUIColor(Color.HSVToRGB(hue, 1f, 1f));\n\n                    EditorGUI.BeginChangeCheck();\n\n                    hue = EditorGUI.AngularDial(\n                        dialRect,\n                        GUIContent.none,\n                        hue * 360f,\n                        ((GUIContent)Styles.hueDialThumbFill).image,\n                        backgroundStyle,\n                        Styles.hueDialThumb\n                    );\n\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        hue = Mathf.Repeat(hue, 360f) / 360f;\n                        m_Color.SetColorChannel(HsvChannel.H, hue);\n                        OnColorChanged();\n                    }\n                    GUI.contentColor = oldColor;\n\n                    var innerRadius = dialRect.width * 0.5f - Styles.hueDialThumbSize;\n                    var size = Mathf.FloorToInt(Mathf.Sqrt(2f) * innerRadius);\n                    if ((size & 1) == 1)\n                        size += 1;\n                    var svRect = new Rect { size = Vector2.one * size, center = dialRect.center };\n                    svRect = Styles.colorBoxPadding.Remove(svRect);\n\n                    DrawColorSpaceBox(svRect, m_Color.GetColorChannel(HsvChannel.H));\n\n                    EditorGUI.BeginChangeCheck();\n\n                    var sv = new Vector2(m_Color.GetColorChannel(HsvChannel.S), 1f - m_Color.GetColorChannel(HsvChannel.V));\n                    sv = Slider2D(svRect, sv, Vector2.zero, Vector2.one, Styles.colorBoxThumb);\n\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        m_Color.SetColorChannel(HsvChannel.S, sv.x);\n                        m_Color.SetColorChannel(HsvChannel.V, 1f - sv.y);\n                        OnColorChanged();\n                    }\n                    break;\n                case ColorBoxMode.EyeDropper:\n                    EyeDropper.DrawPreview(dialRect);\n                    break;\n            }\n\n            GUI.color = oldGUIColor;\n        }\n\n        void DoColorSliders(float availableWidth)\n        {\n            float oldLabelWidth = EditorGUIUtility.labelWidth;\n            float oldFieldWidth = EditorGUIUtility.fieldWidth;\n            EditorGUIUtility.labelWidth = availableWidth - Styles.sliderModeFieldWidth;\n            EditorGUIUtility.fieldWidth = Styles.sliderModeFieldWidth;\n            if(m_HDR && m_Color.exposureAdjustedColor.maxColorComponent > 1f)\n                m_SliderMode = (SliderMode)EditorGUILayout.IntPopup(GUIContent.Temp(\" \"), (int)m_SliderMode, Styles.sliderHDRModeLabels, Styles.sliderModeValues);\n            else\n                m_SliderMode = (SliderMode)EditorGUILayout.IntPopup(GUIContent.Temp(\" \"), (int)m_SliderMode, Styles.sliderLDRModeLabels, Styles.sliderModeValues);\n\n            GUILayout.Space(Styles.extraVerticalSpacing);\n\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n            EditorGUIUtility.fieldWidth = oldFieldWidth;\n\n            EditorGUIUtility.labelWidth = Styles.channelSliderLabelWidth;\n\n            switch (m_SliderMode)\n            {\n                case SliderMode.HSV:\n                    HSVSliders();\n                    break;\n                default:\n                    RGBSliders();\n                    break;\n            }\n\n            if (m_ShowAlpha)\n            {\n                m_AlphaTexture = Update1DSlider(m_AlphaTexture, kColorBoxSize, 0, 0, ref m_OldAlpha, ref m_OldAlpha, 3, false);\n\n                float displayScale = 1f;\n                string formatString = EditorGUI.kFloatFieldFormatString;\n                switch (m_SliderMode)\n                {\n                    case SliderMode.HSV:\n                        displayScale = 100f;\n                        formatString = EditorGUI.kIntFieldFormatString;\n                        break;\n                    case SliderMode.RGB:\n                        displayScale = 255f;\n                        formatString = EditorGUI.kIntFieldFormatString;\n                        break;\n                }\n\n                var rect = EditorGUILayout.GetControlRect(true);\n\n                if (Event.current.type == EventType.Repaint)\n                {\n                    var backgroundRect = rect;\n                    backgroundRect.xMin += EditorGUIUtility.labelWidth + Styles.sliderBackground.padding.horizontal;\n                    backgroundRect.xMax -= EditorGUIUtility.fieldWidth + EditorGUI.kSpacing;\n                    backgroundRect = Styles.sliderBackground.padding.Remove(backgroundRect);\n                    var uvLayout = new Rect\n                    {\n                        x = 0f,\n                        y = 0f,\n                        width = backgroundRect.width / backgroundRect.height, // texture aspect is 1:1\n                        height = 1f\n                    };\n                    Graphics.DrawTexture(backgroundRect, Styles.alphaSliderCheckerBackground, uvLayout, 0, 0, 0, 0);\n                }\n\n                EditorGUI.BeginChangeCheck();\n                var alpha = m_Color.GetColorChannelNormalized(RgbaChannel.A) * displayScale;\n                alpha = EditorGUI.SliderWithTexture(\n                    rect, GUIContent.Temp(\"A\"), alpha, 0f, displayScale, formatString, m_AlphaTexture\n                );\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_Color.SetColorChannel(RgbaChannel.A, alpha / displayScale);\n                    OnColorChanged();\n                }\n                GUILayout.Space(Styles.extraVerticalSpacing);\n            }\n\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n        }\n\n        void DoHexField(float availableWidth)\n        {\n            float oldLabelWidth = EditorGUIUtility.labelWidth;\n            float oldFieldWidth = EditorGUIUtility.fieldWidth;\n            EditorGUIUtility.labelWidth = availableWidth - Styles.hexFieldWidth;\n            EditorGUIUtility.fieldWidth = Styles.hexFieldWidth;\n\n            EditorGUI.BeginChangeCheck();\n            var newColor = EditorGUILayout.HexColorTextField(Styles.hexLabel, m_Color.color, false);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_Color.SetColorChannel(RgbaChannel.R, newColor.r);\n                m_Color.SetColorChannel(RgbaChannel.G, newColor.g);\n                m_Color.SetColorChannel(RgbaChannel.B, newColor.b);\n                OnColorChanged();\n            }\n\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n            EditorGUIUtility.fieldWidth = oldFieldWidth;\n        }\n\n        void DoExposureSlider()\n        {\n            var oldLabelWidth = EditorGUIUtility.labelWidth;\n            EditorGUIUtility.labelWidth =\n                EditorStyles.label.CalcSize(Styles.exposureValue).x\n                + EditorStyles.label.margin.right;\n\n            var sliderPosition = GUILayoutUtility.GetRect(0f, EditorGUIUtility.singleLineHeight);\n\n            EditorGUI.BeginChangeCheck();\n            var exposureValue = EditorGUI.Slider(\n                sliderPosition, Styles.exposureValue, m_Color.exposureValue, -m_ExposureSliderMax, m_ExposureSliderMax, float.MinValue, float.MaxValue\n            );\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_Color.exposureValue = exposureValue;\n                OnColorChanged();\n            }\n\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n        }\n\n        void DoExposureSwatches()\n        {\n            var swatchesRect =\n                GUILayoutUtility.GetRect(GUIContent.none, Styles.exposureSwatch, GUILayout.ExpandWidth(true));\n\n            var numSwatches = 5;\n            var swatchRect = new Rect\n            {\n                x = swatchesRect.x + (swatchesRect.width - numSwatches * Styles.exposureSwatch.fixedWidth) * 0.5f,\n                y = swatchesRect.y,\n                width = Styles.exposureSwatch.fixedWidth,\n                height = Styles.exposureSwatch.fixedHeight\n            };\n            var backgroundColor = GUI.backgroundColor;\n            var contentColor = GUI.contentColor;\n            for (int i = 0; i < numSwatches; ++i)\n            {\n                var stop = i - numSwatches / 2;\n                var col = (m_Color.exposureAdjustedColor * Mathf.Pow(2f, stop)).gamma;\n                col.a = 1f;\n                GUI.backgroundColor = col;\n                GUI.contentColor = VisionUtility.ComputePerceivedLuminance(col) < Styles.highLuminanceThreshold ?\n                    Styles.lowLuminanceContentColor : Styles.highLuminanceContentColor;\n\n                if (\n                    GUI.Button(\n                        swatchRect,\n                        GUIContent.Temp(stop == 0 ? null : (stop < 0 ? stop.ToString() : string.Format(\"+{0}\", stop))),\n                        Styles.exposureSwatch\n                    )\n                )\n                {\n                    m_Color.exposureValue =\n                        Mathf.Clamp(m_Color.exposureValue + stop, -m_ExposureSliderMax, m_ExposureSliderMax);\n                    OnColorChanged();\n                }\n\n                if (stop == 0 && Event.current.type == EventType.Repaint)\n                {\n                    GUI.backgroundColor = GUI.contentColor;\n                    Styles.selectedExposureSwatchStroke.Draw(swatchRect, false, false, false, false);\n                }\n\n                swatchRect.x += swatchRect.width;\n            }\n            GUI.backgroundColor = backgroundColor;\n            GUI.contentColor = contentColor;\n        }\n\n        Texture2D m_SwatchTex;\n        Texture2D m_SelectionTex;\n        void DoDefaultsGUI()\n        {\n            m_ShowDefaults = EditorGUILayout.Foldout(m_ShowDefaults, Styles.defaultsToggle, true);\n\n            if (m_ShowDefaults)\n            {\n                if (m_SwatchTex == null) m_SwatchTex = ColorPresetLibrary.CreateColorSwatchWithBorder(14, 14, false);\n\n                using (new EditorGUILayout.VerticalScope())\n                {\n                    EditorGUILayout.BeginHorizontal();\n                    var i = 0;\n                    foreach (var (color, name) in Color.defaultColorNames)\n                    {\n                        if (i != 0 && i % 15 == 0)\n                        {\n                            GUILayout.FlexibleSpace();\n                            EditorGUILayout.EndHorizontal();\n                            EditorGUILayout.BeginHorizontal();\n                        }\n\n                        using (new GUI.ColorScope(color))\n                        {\n                            string tooltip;\n                            if (m_SliderMode == SliderMode.HSV)\n                            {\n                                Color.RGBToHSV(color, out var h, out var s, out var v);\n                                tooltip = $\"{ObjectNames.CapitaliseFirstLetter(name)} HSVA({Mathf.RoundToInt(h * 360).ToString()}, {Mathf.RoundToInt(s * 100).ToString()}, {Mathf.RoundToInt(v * 100).ToString()}, {Mathf.RoundToInt(color.a * 100).ToString()})\";\n                            }\n                            else if (m_SliderMode == SliderMode.RGB)\n                                tooltip = $\"{ObjectNames.CapitaliseFirstLetter(name)} {((Color32)color).ToString()}\";\n                            else\n                                tooltip = $\"{ObjectNames.CapitaliseFirstLetter(name)} {color.ToString()}\";\n\n                            var clicked = GUILayout.Button(\n                                GUIContent.Temp(m_SwatchTex, tooltip),\n                                GUIStyle.none,\n                                new GUILayoutOption(GUILayoutOption.Type.fixedWidth, 14f));\n\n                            if (m_Color.color.Equals((Color32)color))\n                            {\n                                if (m_SelectionTex == null) m_SelectionTex = ColorPresetLibrary.CreateSelectionTexture(14, 14);\n\n                                using (new GUI.ColorScope(SwatchSelectionColor))\n                                    GUI.DrawTexture(GUILayoutUtility.GetLastRect(), m_SelectionTex);\n                            }\n\n                            if (clicked)\n                                SetColor(color);\n                        }\n\n                        i++;\n                    }\n                    GUILayout.FlexibleSpace();\n                    EditorGUILayout.EndHorizontal();\n                }\n            }\n        }\n\n        void DoPresetsGUI()\n        {\n            var foldoutRect = GUILayoutUtility.GetRect(Styles.presetsToggle, EditorStyles.foldout);\n            foldoutRect.xMax -= 17f; // make room for presets settings menu button\n            m_ShowPresets = EditorGUI.Foldout(foldoutRect, m_ShowPresets, Styles.presetsToggle, true);\n\n            if (m_ShowPresets)\n            {\n                GUILayout.Space(-(EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing)); // pull up to reuse space\n                var presetsRect = GUILayoutUtility.GetRect(0, Mathf.Clamp(m_ColorLibraryEditor.contentHeight, 20f, 250f));\n                m_ColorLibraryEditor.OnGUI(presetsRect, instance.GetGUIColor(color));\n            }\n        }\n\n        void OnGUI()\n        {\n            InitializePresetsLibraryIfNeeded();\n\n            EventType type = Event.current.type;\n\n            if (type == EventType.ExecuteCommand)\n            {\n                switch (Event.current.commandName)\n                {\n                    case EventCommandNames.EyeDropperUpdate:\n                        Repaint();\n                        break;\n                    case EventCommandNames.EyeDropperClicked:\n                        m_ColorBoxMode = ColorBoxMode.HSV;\n                        Color col = EyeDropper.GetLastPickedColor();\n                        if (m_HDR)\n                            col = col.linear;\n                        m_Color.SetColorChannelHdr(RgbaChannel.R, col.r);\n                        m_Color.SetColorChannelHdr(RgbaChannel.G, col.g);\n                        m_Color.SetColorChannelHdr(RgbaChannel.B, col.b);\n                        m_Color.SetColorChannelHdr(RgbaChannel.A, col.a);\n                        OnColorChanged();\n                        break;\n                    case EventCommandNames.EyeDropperCancelled:\n                        OnEyedropperCancelled();\n                        break;\n                }\n            }\n\n            Rect contentRect = EditorGUILayout.BeginVertical(Styles.background);\n\n            // Setup layout values\n            float innerContentWidth = EditorGUILayout.GetControlRect(false, 1, EditorStyles.numberField).width;\n            EditorGUIUtility.labelWidth = innerContentWidth - Styles.sliderTextFieldWidth;\n            EditorGUIUtility.fieldWidth = Styles.sliderTextFieldWidth;\n\n            GUILayout.Space(10);\n            DoColorSwatchAndEyedropper();\n\n            GUILayout.Space(10);\n\n            DoColorSpaceGUI();\n\n            GUILayout.Space(10);\n\n            DoColorSliders(innerContentWidth);\n            if (!m_HDR)\n            {\n                DoHexField(innerContentWidth);\n            }\n\n            GUILayout.Space(Styles.extraVerticalSpacing);\n\n            if (m_HDR)\n            {\n                DoExposureSlider();\n                GUILayout.Space(Styles.extraVerticalSpacing);\n                DoExposureSwatches();\n                GUILayout.Space(Styles.extraVerticalSpacing);\n            }\n\n            DoDefaultsGUI();\n\n            DoPresetsGUI();\n\n            // Call last to ensure we only use the copy paste events if no\n            // other controls wants to use these events\n            HandleCopyPasteEvents();\n\n            EditorGUILayout.EndVertical();\n\n            if (contentRect.height > 0 && Event.current.type == EventType.Repaint)\n            {\n                SetHeight(contentRect.height);\n            }\n\n            if (Event.current.type == EventType.KeyDown)\n            {\n                switch (Event.current.keyCode)\n                {\n                    case KeyCode.Escape:\n                        // eyedropper GUIView never gets keyboard focus from ColorPicker, so esc to exit it must be handled here\n                        if (m_ColorBoxMode == ColorBoxMode.EyeDropper)\n                        {\n                            EyeDropper.End();\n                            OnEyedropperCancelled();\n                        }\n                        else\n                        {\n                            Undo.RevertAllDownToGroup(m_ModalUndoGroup);\n                            m_Color.Reset();\n                            OnColorChanged(false);\n                            Close();\n                            GUIUtility.ExitGUI();\n                        }\n                        break;\n                    case KeyCode.Return:\n                    case KeyCode.KeypadEnter:\n                        Close();\n                        break;\n                }\n            }\n\n            // Cancel EyeDropper if we change focus.\n            if (m_ColorBoxMode == ColorBoxMode.EyeDropper &&\n                Event.current.type == EventType.ExecuteCommand &&\n                Event.current.commandName == EventCommandNames.NewKeyboardFocus)\n            {\n                EyeDropper.End();\n                OnEyedropperCancelled();\n            }\n\n            // Remove keyfocus when clicked outside any control\n            if ((Event.current.type == EventType.MouseDown && Event.current.button != 1) || Event.current.type == EventType.ContextClick)\n            {\n                GUIUtility.keyboardControl = 0;\n                Repaint();\n            }\n        }\n\n        void OnEyedropperCancelled()\n        {\n            Repaint();\n            m_ColorBoxMode = ColorBoxMode.HSV;\n        }\n\n        void SetHeight(float newHeight)\n        {\n            if (newHeight == position.height)\n                return;\n            minSize = new Vector2(Styles.fixedWindowWidth, newHeight);\n            maxSize = new Vector2(Styles.fixedWindowWidth, newHeight);\n        }\n\n        void HandleCopyPasteEvents()\n        {\n            Event evt = Event.current;\n            switch (evt.type)\n            {\n                case EventType.ValidateCommand:\n                    switch (evt.commandName)\n                    {\n                        case EventCommandNames.Copy:\n                        case EventCommandNames.Paste:\n                            evt.Use();\n                            break;\n                    }\n                    break;\n\n                case EventType.ExecuteCommand:\n                    switch (evt.commandName)\n                    {\n                        case EventCommandNames.Copy:\n                            Clipboard.colorValue = color;\n                            evt.Use();\n                            break;\n\n                        case EventCommandNames.Paste:\n                            if (Clipboard.hasColor)\n                            {\n                                Color pasted = Clipboard.colorValue;\n                                if (!m_HDR && pasted.maxColorComponent > 1f)\n                                    pasted = pasted.RGBMultiplied(1f / pasted.maxColorComponent);\n\n                                // Do not change alpha if color field is not showing alpha\n                                if (!m_ShowAlpha)\n                                    pasted.a = m_Color.GetColorChannelNormalized(RgbaChannel.A);\n\n                                SetColor(pasted);\n\n                                GUI.changed = true;\n                                evt.Use();\n                            }\n                            break;\n                    }\n                    break;\n            }\n        }\n\n        static Texture2D s_LeftGradientTexture;\n        static Texture2D s_RightGradientTexture;\n\n        public static Texture2D GetGradientTextureWithAlpha1To0()\n        {\n            return s_LeftGradientTexture ?? (s_LeftGradientTexture = CreateGradientTexture(\"ColorPicker_1To0_Gradient\", 4, 4, new Color(1, 1, 1, 1), new Color(1, 1, 1, 0)));\n        }\n\n        public static Texture2D GetGradientTextureWithAlpha0To1()\n        {\n            return s_RightGradientTexture ?? (s_RightGradientTexture = CreateGradientTexture(\"ColorPicker_0To1_Gradient\", 4, 4, new Color(1, 1, 1, 0), new Color(1, 1, 1, 1)));\n        }\n\n        static Texture2D CreateGradientTexture(string name, int width, int height, Color leftColor, Color rightColor)\n        {\n            var texture = new Texture2D(width, height, TextureFormat.RGBA32, false, true) {name = name, hideFlags = HideFlags.HideAndDontSave};\n            var pixels = new Color[width * height];\n\n            for (int i = 0; i < width; i++)\n            {\n                Color columnColor = Color.Lerp(leftColor, rightColor, i / (float)(width - 1));\n                for (int j = 0; j < height; j++)\n                    pixels[j * width + i] = columnColor;\n            }\n\n            texture.SetPixels(pixels);\n            texture.wrapMode = TextureWrapMode.Clamp;\n            texture.Apply();\n            return texture;\n        }\n\n        void OnColorChanged(bool exitGUI = true)\n        {\n            m_OldAlpha = -1f;\n            m_ColorSpaceBoxDirty = true;\n            m_ExposureSliderMax = Mathf.Max(m_ExposureSliderMax, m_Color.exposureValue);\n            if (m_DelegateView != null)\n            {\n                var e = EditorGUIUtility.CommandEvent(EventCommandNames.ColorPickerChanged);\n                Repaint();\n                m_DelegateView.SendEvent(e);\n                if (exitGUI)\n                    GUIUtility.ExitGUI();\n            }\n            if (m_ColorChangedCallback != null)\n            {\n                m_ColorChangedCallback(color);\n            }\n        }\n\n        private void SetColor(Color c)\n        {\n            m_Color.SetColorChannelHdr(RgbaChannel.R, c.r);\n            m_Color.SetColorChannelHdr(RgbaChannel.G, c.g);\n            m_Color.SetColorChannelHdr(RgbaChannel.B, c.b);\n            m_Color.SetColorChannelHdr(RgbaChannel.A, c.a);\n            OnColorChanged();\n            Repaint();\n        }\n\n        public static void Show(GUIView viewToUpdate, Color col, bool showAlpha = true, bool hdr = false)\n        {\n            Show(viewToUpdate, null, col, showAlpha, hdr);\n        }\n\n        public static void Show(Action<Color> colorChangedCallback, Color col, bool showAlpha = true, bool hdr = false)\n        {\n            Show(null, colorChangedCallback, col, showAlpha, hdr);\n        }\n\n        static void Show(GUIView viewToUpdate, Action<Color> colorChangedCallback, Color col, bool showAlpha, bool hdr)\n        {\n            var cp = instance;\n            cp.m_HDR = hdr;\n            cp.m_Color = new ColorMutator(col);\n            cp.m_ShowAlpha = showAlpha;\n            cp.m_DelegateView = viewToUpdate;\n            cp.m_ColorChangedCallback = colorChangedCallback;\n            cp.m_ModalUndoGroup = Undo.GetCurrentGroup();\n            cp.m_ExposureSliderMax = Mathf.Max(cp.m_ExposureSliderMax, cp.m_Color.exposureValue);\n            originalKeyboardControl = GUIUtility.keyboardControl;\n\n            if (cp.m_HDR)\n            {\n                cp.m_SliderMode = (SliderMode)EditorPrefs.GetInt(k_SliderModeHDRPrefKey, (int)SliderMode.RGB);\n            }\n            else\n            {\n                // If it is not an HDR value we set the exposure back to 0.\n                cp.m_Color.exposureValue = 0;\n            }\n\n            cp.titleContent = hdr ? EditorGUIUtility.TrTextContent(\"HDR Color\") : EditorGUIUtility.TrTextContent(\"Color\");\n            float height = EditorPrefs.GetInt(k_HeightPrefKey, (int)cp.position.height);\n            cp.minSize = new Vector2(Styles.fixedWindowWidth, height);\n            cp.maxSize = new Vector2(Styles.fixedWindowWidth, height);\n            cp.InitializePresetsLibraryIfNeeded(); // Ensure the heavy lifting of loading presets is done before window is visible\n            cp.ShowAuxWindow();\n        }\n\n        void OnEnable()\n        {\n            hideFlags = HideFlags.DontSave;\n            hideFlags = HideFlags.DontSave;\n            EditorGUIUtility.editingTextField = true; // To fix that color values is not directly editable when tabbing (case 557510)\n\n            m_SliderMode = (SliderMode)EditorPrefs.GetInt(k_SliderModePrefKey, (int)SliderMode.RGB);\n            m_ShowPresets = EditorPrefs.GetInt(k_ShowPresetsPrefKey, 1) != 0;\n            m_ShowDefaults = EditorPrefs.GetInt(k_ShowDefaultsPrefKey, 1) != 0;\n        }\n\n        void OnDisable()\n        {\n            EditorPrefs.SetInt(m_HDR ? k_SliderModeHDRPrefKey : k_SliderModePrefKey, (int)m_SliderMode);\n            EditorPrefs.SetInt(k_ShowDefaultsPrefKey, m_ShowDefaults ? 1 : 0);\n            EditorPrefs.SetInt(k_ShowPresetsPrefKey, m_ShowPresets ? 1 : 0);\n            EditorPrefs.SetInt(k_HeightPrefKey, (int)position.height);\n        }\n\n        public void OnDestroy()\n        {\n            Undo.CollapseUndoOperations(m_ModalUndoGroup);\n\n            if (m_ColorSlider)\n                DestroyImmediate(m_ColorSlider);\n            if (m_ColorBox)\n                DestroyImmediate(m_ColorBox);\n            if (m_RTexture)\n                DestroyImmediate(m_RTexture);\n            if (m_GTexture)\n                DestroyImmediate(m_GTexture);\n            if (m_BTexture)\n                DestroyImmediate(m_BTexture);\n            if (m_HueTexture)\n                DestroyImmediate(m_HueTexture);\n            if (m_SatTexture)\n                DestroyImmediate(m_SatTexture);\n            if (m_ValTexture)\n                DestroyImmediate(m_ValTexture);\n            if (m_AlphaTexture)\n                DestroyImmediate(m_AlphaTexture);\n            if (m_SwatchTex)\n                DestroyImmediate(m_SwatchTex);\n            if (m_SelectionTex)\n                DestroyImmediate(m_SelectionTex);\n            s_Instance = null;\n\n            if (m_ColorLibraryEditorState != null)\n                m_ColorLibraryEditorState.TransferEditorPrefsState(false);\n\n            if (m_ColorLibraryEditor != null)\n                m_ColorLibraryEditor.UnloadUsedLibraries();\n\n            GUIUtility.keyboardControl = originalKeyboardControl;\n            originalKeyboardControl = 0;\n        }\n    }\n\n    internal class EyeDropper : GUIView\n    {\n        const int kPixelSize = 10;\n        // Can't be larger right now since OSX Metal surfaces can't be larger than 16384 pixels.\n        // This needs to be changed to a larger size since it will miss mouse events when using multiple 4K monitors\n        private const int kDummyWindowSize = 100;\n        internal static Color s_LastPickedColor;\n        GUIView m_DelegateView;\n        Texture2D m_Preview;\n        static EyeDropper s_Instance;\n        private static Vector2 s_PickCoordinates = Vector2.zero;\n        private bool m_IsOpened;\n        private bool m_IsCancelled;\n        private bool m_Focused = false;\n        private Action<Color> m_ColorPickedCallback;\n\n        public static void Start(GUIView viewToUpdate)\n        {\n            Start(viewToUpdate, null);\n        }\n\n        public static void Start(Action<Color> colorPickedCallback)\n        {\n            Start(null, colorPickedCallback);\n        }\n\n        static void Start(GUIView viewToUpdate, Action<Color> colorPickedCallback)\n        {\n            if(!InternalEditorUtility.IsAllowedToReadPixelOutsideUnity(out var errorMessage))\n                Debug.LogWarning(errorMessage);\n\n            instance.m_DelegateView = viewToUpdate;\n            instance.m_ColorPickedCallback = colorPickedCallback;\n            ContainerWindow win = CreateInstance<ContainerWindow>();\n            win.m_DontSaveToLayout = true;\n            win.title = \"EyeDropper\";\n            win.hideFlags = HideFlags.DontSave;\n            win.rootView = instance;\n            win.Show(ShowMode.PopupMenu, loadPosition: true, displayImmediately: true, setFocus: true);\n            instance.AddToAuxWindowList();\n            win.SetInvisible();\n            instance.SetMinMaxSizes(new Vector2(0, 0), new Vector2(kDummyWindowSize, kDummyWindowSize));\n            Vector2 p = GUIUtility.GUIToScreenPoint(Event.current != null ? Event.current.mousePosition : Vector2.zero);\n            win.position = new Rect(p.x - kDummyWindowSize / 2, p.y - kDummyWindowSize / 2, kDummyWindowSize, kDummyWindowSize);\n            instance.wantsMouseMove = true;\n            instance.Focus();\n            instance.SetEyeDropperOpen(true);\n            instance.StealMouseCapture();\n            instance.m_IsOpened = true;\n            instance.m_IsCancelled = false;\n        }\n\n        public static void End()\n        {\n            if (s_Instance != null)\n            {\n                s_Instance.SetEyeDropperClosed();\n                s_Instance.window.Close();\n                s_Instance = null;\n            }\n        }\n\n        static EyeDropper instance\n        {\n            get\n            {\n                if (!s_Instance)\n                    CreateInstance<EyeDropper>();\n                return s_Instance;\n            }\n        }\n\n        EyeDropper()\n        {\n            s_Instance = this;\n        }\n\n        public static Color GetPickedColor()\n        {\n            return InternalEditorUtility.ReadScreenPixelUnderCursor(s_PickCoordinates, 1, 1)[0];\n        }\n\n        public static Color GetLastPickedColor()\n        {\n            return s_LastPickedColor;\n        }\n\n        public static bool IsOpened => s_Instance?.m_IsOpened == true;\n        public static bool IsCancelled => s_Instance?.m_IsCancelled == true;\n\n        static class Styles\n        {\n            public static readonly GUIStyle eyeDropperHorizontalLine = \"EyeDropperHorizontalLine\";\n            public static readonly GUIStyle eyeDropperVerticalLine = \"EyeDropperVerticalLine\";\n            public static readonly GUIStyle eyeDropperPickedPixel = \"EyeDropperPickedPixel\";\n        }\n\n        public static void DrawPreview(Rect position)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            Texture2D preview = instance.m_Preview;\n            int width = (int)Mathf.Ceil(position.width / kPixelSize);\n            int height = (int)Mathf.Ceil(position.height / kPixelSize);\n            if (preview == null)\n            {\n                instance.m_Preview = preview = ColorPicker.MakeTexture(width, height);\n                preview.filterMode = FilterMode.Point;\n            }\n            if (preview.width != width || preview.height != height)\n            {\n                preview.Reinitialize(width, height);\n            }\n\n            Vector2 p = GUIUtility.GUIToScreenPoint(Event.current.mousePosition);\n            Vector2 mPos = p - new Vector2((width / 2f), (height / 2f));\n            preview.SetPixels(InternalEditorUtility.ReadScreenPixelUnderCursor(p, width, height), 0);\n            preview.Apply(true);\n\n            Graphics.DrawTexture(position, preview);\n\n            // Draw grid on top\n            float xStep = position.width / width;\n            GUIStyle sep = Styles.eyeDropperVerticalLine;\n            for (float x = position.x; x < position.xMax; x += xStep)\n            {\n                Rect r = new Rect(Mathf.Round(x), position.y, xStep, position.height);\n                sep.Draw(r, false, false, false, false);\n            }\n\n            float yStep = position.height / height;\n            sep = Styles.eyeDropperHorizontalLine;\n            for (float y = position.y; y < position.yMax; y += yStep)\n            {\n                Rect r = new Rect(position.x, Mathf.Floor(y), position.width, yStep);\n                sep.Draw(r, false, false, false, false);\n            }\n\n            // Draw selected pixelSize\n            Rect newR = new Rect((p.x - mPos.x) * xStep + position.x, (p.y - mPos.y) * yStep + position.y, xStep, yStep);\n            Styles.eyeDropperPickedPixel.Draw(newR, false, false, false, false);\n        }\n\n        protected override void OldOnGUI()\n        {\n            // On mouse move/click we remember screen coordinates where we are. Then we'll use that\n            // in GetPickedColor to read. The reason is that because GetPickedColor might be called from\n            // an event which is different, so the coordinates would be already wrong.\n            // for direct manipulation devices, it is on mouse drag/up\n            if (Event.current.isDirectManipulationDevice)\n            {\n                switch (Event.current.type)\n                {\n                    case EventType.MouseDrag:\n                        UpdateEyeDropper();\n                        break;\n                    case EventType.MouseUp:\n                        StopEyeDropper();\n                        break;\n                    case EventType.KeyDown:\n                        CancelEyeDropper();\n                        break;\n                }\n            }\n            else\n            {\n                switch (Event.current.type)\n                {\n                    case EventType.MouseMove:\n                        UpdateEyeDropper();\n                        break;\n                    case EventType.MouseDown:\n                        StopEyeDropper();\n                        break;\n                    case EventType.KeyDown:\n                        CancelEyeDropper();\n                        break;\n                }\n            }\n        }\n\n        private void UpdateEyeDropper()\n        {\n            s_PickCoordinates = GUIUtility.GUIToScreenPoint(Event.current.mousePosition);\n\n            StealMouseCapture();\n            SendEvent(EventCommandNames.EyeDropperUpdate, true, false);\n        }\n\n        private void StopEyeDropper()\n        {\n            if (Event.current.button == 0)\n            {\n                s_PickCoordinates = GUIUtility.GUIToScreenPoint(Event.current.mousePosition);\n\n                // We have to close helper window before we read color from screen. On Win\n                // the window covers whole desktop (see Show()) and is black with 0x01 alpha value.\n                // That might cause invalid picked color.\n                this.SetEyeDropperClosed();\n                window.Close();\n                s_LastPickedColor = GetPickedColor();\n                Event.current.Use();\n                SendEvent(EventCommandNames.EyeDropperClicked, true);\n                if (m_ColorPickedCallback != null)\n                {\n                    m_ColorPickedCallback(s_LastPickedColor);\n                }\n            }\n        }\n\n        private void CancelEyeDropper()\n        {\n            if (Event.current.keyCode == KeyCode.Escape)\n            {\n                this.m_IsCancelled = true;\n                this.SetEyeDropperClosed();\n                window.Close();\n                Event.current.Use();\n                SendEvent(EventCommandNames.EyeDropperCancelled, true);\n            }\n        }\n\n        private void SetEyeDropperClosed()\n        {\n            m_IsOpened = false;\n            s_Instance.SetEyeDropperOpen(false);\n        }\n\n        void SendEvent(string eventName, bool exitGUI, bool focusOther = true)\n        {\n            if (m_DelegateView != null)\n            {\n                var e = EditorGUIUtility.CommandEvent(eventName);\n                if (focusOther)\n                    m_DelegateView.Focus();\n                m_DelegateView.SendEvent(e);\n                if (exitGUI)\n                    GUIUtility.ExitGUI();\n            }\n        }\n\n        public new void OnDestroy()\n        {\n            if (m_Preview)\n                DestroyImmediate(m_Preview);\n\n            if (!m_Focused)\n            {\n                // Window closed before it was focused\n                SendEvent(EventCommandNames.EyeDropperCancelled, false);\n            }\n\n            base.OnDestroy();\n        }\n\n        protected override bool OnFocus()\n        {\n            m_Focused = true;\n            return base.OnFocus();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ColorPicker.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [Serializable, Obsolete]\n    public class ColorPickerHDRConfig\n    {\n        public float minBrightness;\n        public float maxBrightness;\n        public float minExposureValue;\n        public float maxExposureValue;\n\n        public ColorPickerHDRConfig(\n            float minBrightness, float maxBrightness, float minExposureValue, float maxExposureValue\n        )\n        {\n            this.minBrightness = minBrightness;\n            this.maxBrightness = maxBrightness;\n            this.minExposureValue = minExposureValue;\n            this.maxExposureValue = maxExposureValue;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ColumnView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class ColumnViewElement\n    {\n        public string name;\n        public object value;\n\n        public ColumnViewElement(string name, object value)\n        {\n            this.name = name;\n            this.value = value;\n        }\n    }\n\n    internal class ColumnView\n    {\n        public class Styles\n        {\n            public GUIStyle background = \"OL Box\";\n            public GUIStyle selected = \"PR Label\";\n\n            // TODO: Make a proper style.\n            public Texture2D categoryArrowIcon = EditorStyles.foldout.normal.background;\n        }\n\n        private static Styles s_Styles;\n        private readonly List<ListViewState> m_ListViewStates;\n        private readonly List<int> m_CachedSelectedIndices;\n        private Vector2 m_ScrollPosition;\n        private string m_SearchText = string.Empty;\n\n        public string searchText\n        {\n            get { return m_SearchText; }\n        }\n\n        public bool isSearching\n        {\n            get { return searchText != string.Empty; }\n        }\n\n        public float columnWidth = 150f;\n        public int minimumNumberOfColumns = 1;\n        private int m_ColumnToFocusKeyboard = -1;\n\n        public delegate void ObjectColumnFunction(object value);\n        public delegate object ObjectColumnGetDataFunction(object value);\n\n        public ColumnView()\n        {\n            m_ListViewStates = new List<ListViewState>();\n            m_CachedSelectedIndices = new List<int>();\n        }\n\n        private static void InitStyles()\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n        }\n\n        public void SetSelected(int column, int selectionIndex)\n        {\n            if (m_ListViewStates.Count == column)\n                m_ListViewStates.Add(new ListViewState());\n\n            if (m_CachedSelectedIndices.Count == column)\n                m_CachedSelectedIndices.Add(-1);\n\n            m_CachedSelectedIndices[column] = selectionIndex;\n            m_ListViewStates[column].row = selectionIndex;\n        }\n\n        public void SetKeyboardFocusColumn(int column)\n        {\n            m_ColumnToFocusKeyboard = column;\n        }\n\n        public void OnGUI(List<ColumnViewElement> elements, ObjectColumnFunction previewColumnFunction)\n        {\n            OnGUI(elements, previewColumnFunction, null, null, null);\n        }\n\n        public void OnGUI(List<ColumnViewElement> elements, ObjectColumnFunction previewColumnFunction, ObjectColumnFunction selectedSearchItemFunction, ObjectColumnFunction selectedRegularItemFunction, ObjectColumnGetDataFunction getDataForDraggingFunction)\n        {\n            InitStyles();\n            m_ScrollPosition = GUILayout.BeginScrollView(m_ScrollPosition);\n            GUILayout.BeginHorizontal();\n\n            var columnElements = elements;\n            object selectedObject;\n            int listViewIndex = 0;\n\n            do\n            {\n                if (m_ListViewStates.Count == listViewIndex)\n                    m_ListViewStates.Add(new ListViewState());\n\n                if (m_CachedSelectedIndices.Count == listViewIndex)\n                    m_CachedSelectedIndices.Add(-1);\n\n                var listView = m_ListViewStates[listViewIndex];\n                listView.totalRows = columnElements.Count;\n\n                if (listViewIndex == 0)\n                    GUILayout.BeginVertical(GUILayout.MaxWidth(columnWidth));\n\n                int selectedIndex = m_CachedSelectedIndices[listViewIndex];\n                selectedIndex = DoListColumn(listView, columnElements, listViewIndex, selectedIndex,\n                    listViewIndex == 0 ? selectedSearchItemFunction : null, selectedRegularItemFunction,\n                    getDataForDraggingFunction);\n\n                if (Event.current.type == EventType.Layout && m_ColumnToFocusKeyboard == listViewIndex)\n                {\n                    m_ColumnToFocusKeyboard = -1;\n                    GUIUtility.keyboardControl = listView.ID;\n                    if (listView.row == -1 && columnElements.Count != 0)\n                        selectedIndex = listView.row = 0;\n                }\n\n                if (listViewIndex == 0)\n                {\n                    // pass some of the keys to the list view, even if something else is active\n                    if (isSearching)\n                    {\n                        var keyCode = StealImportantListviewKeys();\n                        if (keyCode != KeyCode.None)\n                            ListViewShared.SendKey(m_ListViewStates[0], keyCode);\n                    }\n\n                    m_SearchText = EditorGUILayout.ToolbarSearchField(m_SearchText);\n                    GUILayout.EndVertical();\n                }\n\n                if (selectedIndex >= columnElements.Count)\n                    selectedIndex = -1;\n\n                if (Event.current.type == EventType.Layout && m_CachedSelectedIndices[listViewIndex] != selectedIndex &&\n                    m_ListViewStates.Count > listViewIndex + 1)\n                {\n                    int from = listViewIndex + 1;\n                    int range = m_ListViewStates.Count - (listViewIndex + 1);\n                    m_ListViewStates.RemoveRange(from, range);\n                    m_CachedSelectedIndices.RemoveRange(from, range);\n                }\n\n                m_CachedSelectedIndices[listViewIndex] = selectedIndex;\n\n                selectedObject = selectedIndex > -1 ? columnElements[selectedIndex].value : null;\n\n                columnElements = selectedObject as List<ColumnViewElement>;\n                listViewIndex++;\n            }\n            while (columnElements != null);\n\n            for (; listViewIndex < minimumNumberOfColumns; listViewIndex++)\n            {\n                DoDummyColumn();\n            }\n\n            DoPreviewColumn(selectedObject, previewColumnFunction);\n\n            GUILayout.EndHorizontal();\n            GUILayout.EndScrollView();\n        }\n\n        private static void DoItemSelectedEvent(ObjectColumnFunction selectedRegularItemFunction, object value)\n        {\n            if (selectedRegularItemFunction != null)\n                selectedRegularItemFunction(value);\n            Event.current.Use();\n        }\n\n        private void DoSearchItemSelectedEvent(ObjectColumnFunction selectedSearchItemFunction, object value)\n        {\n            m_SearchText = string.Empty;\n            DoItemSelectedEvent(selectedSearchItemFunction, value);\n        }\n\n        private void DoDummyColumn()\n        {\n            // TODO: Don't know why this width needs one more pixel to match the list views. Bug in ScrollViews?\n            GUILayout.Box(GUIContent.none, s_Styles.background, GUILayout.Width(columnWidth + 1));\n        }\n\n        private static void DoPreviewColumn(object selectedObject, ObjectColumnFunction previewColumnFunction)\n        {\n            GUILayout.BeginVertical(s_Styles.background);\n            if (previewColumnFunction != null)\n                previewColumnFunction(selectedObject);\n            GUILayout.EndVertical();\n        }\n\n        private int DoListColumn(ListViewState listView, List<ColumnViewElement> columnViewElements, int columnIndex, int selectedIndex, ObjectColumnFunction selectedSearchItemFunction, ObjectColumnFunction selectedRegularItemFunction, ObjectColumnGetDataFunction getDataForDraggingFunction)\n        {\n            if (Event.current.type == EventType.KeyDown &&\n                Event.current.keyCode == KeyCode.Return && listView.row > -1)\n            {\n                if (isSearching && selectedSearchItemFunction != null)\n                    DoSearchItemSelectedEvent(selectedSearchItemFunction, columnViewElements[selectedIndex].value);\n                if (!isSearching && GUIUtility.keyboardControl == listView.ID && selectedRegularItemFunction != null)\n                    DoItemSelectedEvent(selectedRegularItemFunction, columnViewElements[selectedIndex].value);\n            }\n\n            if (GUIUtility.keyboardControl == listView.ID && Event.current.type == EventType.KeyDown && !isSearching)\n            {\n                switch (Event.current.keyCode)\n                {\n                    case KeyCode.LeftArrow:\n                        m_ColumnToFocusKeyboard = columnIndex - 1;\n                        Event.current.Use();\n                        break;\n                    case KeyCode.RightArrow:\n                        m_ColumnToFocusKeyboard = columnIndex + 1;\n                        Event.current.Use();\n                        break;\n                }\n            }\n\n            foreach (ListViewElement element in ListViewGUILayout.ListView(listView, s_Styles.background, GUILayout.Width(columnWidth)))\n            {\n                var columnViewElement = columnViewElements[element.row];\n\n                if (element.row == listView.row)\n                {\n                    if (Event.current.type == EventType.Repaint)\n                    {\n                        // FIXME: One Pixel offset is required when using OL Box style. Use a different style.\n                        var rect = element.position;\n                        rect.x++;\n                        rect.y++;\n\n                        s_Styles.selected.Draw(rect, false, true, true, GUIUtility.keyboardControl == listView.ID);\n                    }\n                }\n\n                GUILayout.Label(columnViewElement.name);\n\n                if (columnViewElement.value is List<ColumnViewElement>)\n                {\n                    // TODO: Make a proper style.\n                    var arrowRect = element.position;\n                    arrowRect.x = arrowRect.xMax - s_Styles.categoryArrowIcon.width - 5;\n                    arrowRect.y += 2;\n                    GUI.Label(arrowRect, s_Styles.categoryArrowIcon);\n                }\n\n                DoDoubleClick(element, columnViewElement, selectedSearchItemFunction, selectedRegularItemFunction);\n                DoDragAndDrop(listView, element, columnViewElements, getDataForDraggingFunction);\n            }\n\n            if (Event.current.type == EventType.Layout)\n                selectedIndex = listView.row;\n\n            return selectedIndex;\n        }\n\n        private static void DoDragAndDrop(ListViewState listView, ListViewElement element, List<ColumnViewElement> columnViewElements, ObjectColumnGetDataFunction getDataForDraggingFunction)\n        {\n            if (GUIUtility.hotControl == listView.ID && Event.current.type == EventType.MouseDown &&\n                element.position.Contains(Event.current.mousePosition) &&\n                Event.current.button == 0)\n            {\n                var delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), listView.ID);\n                delay.mouseDownPosition = Event.current.mousePosition;\n            }\n\n            if (GUIUtility.hotControl == listView.ID &&\n                Event.current.type == EventType.MouseDrag &&\n                GUIClip.visibleRect.Contains(Event.current.mousePosition))\n            {\n                var delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), listView.ID);\n\n                if (delay.CanStartDrag())\n                {\n                    var data = getDataForDraggingFunction == null ? null :\n                        getDataForDraggingFunction(columnViewElements[listView.row].value);\n\n                    if (data == null)\n                        return;\n\n                    DragAndDrop.PrepareStartDrag();\n                    DragAndDrop.SetGenericData(\"CustomDragData\", data);\n                    DragAndDrop.StartDrag(columnViewElements[listView.row].name);\n\n                    Event.current.Use();\n                }\n            }\n        }\n\n        private void DoDoubleClick(ListViewElement element, ColumnViewElement columnViewElement, ObjectColumnFunction selectedSearchItemFunction, ObjectColumnFunction selectedRegularItemFunction)\n        {\n            if (Event.current.type == EventType.MouseDown &&\n                element.position.Contains(Event.current.mousePosition) &&\n                Event.current.button == 0 && Event.current.clickCount == 2)\n            {\n                if (isSearching)\n                    DoSearchItemSelectedEvent(selectedSearchItemFunction, columnViewElement.value);\n                else\n                    DoItemSelectedEvent(selectedRegularItemFunction, columnViewElement.value);\n            }\n        }\n\n        private static KeyCode StealImportantListviewKeys()\n        {\n            if (Event.current.type == EventType.KeyDown)\n            {\n                var key = Event.current.keyCode;\n                if (key == KeyCode.UpArrow || key == KeyCode.DownArrow || key == KeyCode.PageUp || key == KeyCode.PageDown)\n                {\n                    Event.current.Use();\n                    return key;\n                }\n            }\n\n            return KeyCode.None;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/CreateAssetUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing UnityEditor.ProjectWindowCallback;\nusing UnityEditor.Utils;\nusing UnityEngine;\n\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    internal class CreateAssetUtility\n    {\n        [SerializeField]\n        EndNameEditAction m_EndAction;\n        [SerializeField]\n        int m_InstanceID;\n        [SerializeField]\n        string m_Path = \"\";\n        [SerializeField]\n        Texture2D m_Icon;\n        [SerializeField]\n        string m_ResourceFile;\n\n        public void Clear()\n        {\n            m_EndAction = null;\n            m_InstanceID = 0;\n            m_Path = \"\";\n            m_Icon = null;\n            m_ResourceFile = \"\";\n        }\n\n        public int instanceID\n        {\n            get { return m_InstanceID; }\n        }\n\n        public Texture2D icon\n        {\n            get { return m_Icon; }\n        }\n\n        public string folder\n        {\n            get { return Path.GetDirectoryName(m_Path).ConvertSeparatorsToUnity(); }\n        }\n\n        public string extension\n        {\n            get { return Path.GetExtension(m_Path); }\n        }\n\n        public string originalName\n        {\n            get { return Path.GetFileNameWithoutExtension(m_Path); }\n        }\n\n        public EndNameEditAction endAction\n        {\n            get { return m_EndAction; }\n        }\n\n        static bool IsPathDataValid(string filePath)\n        {\n            // Ensure some path\n            if (string.IsNullOrEmpty(filePath))\n                return false;\n\n            // Ensure valid folder to place the asset in\n            string folder = Path.GetDirectoryName(filePath);\n            int instanceID = AssetDatabase.GetMainAssetInstanceID(folder);\n            return instanceID != 0;\n        }\n\n        // Selection changes when calling BeginNewAsset if it succeeds\n        public bool BeginNewAssetCreation(int instanceID, EndNameEditAction newAssetEndAction, string filePath, Texture2D icon, string newAssetResourceFile, bool selectAssetBeingCreated = true)\n        {\n            //Sanitize input\n            string sanitizedFilePath = filePath != null ? filePath.ConvertSeparatorsToUnity() : filePath;\n            string sanitizedNewAssetResourceFile = newAssetResourceFile != null ? newAssetResourceFile.ConvertSeparatorsToUnity() : newAssetResourceFile;\n\n            string uniquePath;\n            if (!sanitizedFilePath.StartsWith(\"assets/\", System.StringComparison.CurrentCultureIgnoreCase) && !sanitizedFilePath.StartsWith(\"packages/\", System.StringComparison.CurrentCultureIgnoreCase))\n            {\n                // If sanitizedFilePath is not already a full asset path, we need to get the full path\n                uniquePath = AssetDatabase.GetUniquePathNameAtSelectedPath(sanitizedFilePath);\n            }\n            else\n            {\n                uniquePath = AssetDatabase.GenerateUniqueAssetPath(sanitizedFilePath);\n            }\n\n            if (!IsPathDataValid(uniquePath))\n            {\n                Debug.LogErrorFormat(\"Invalid generated unique path '{0}' (input path '{1}')\", uniquePath, sanitizedFilePath);\n                Clear();\n                return false;\n            }\n\n            m_InstanceID = instanceID;\n            m_Path = uniquePath;\n            m_Icon = icon;\n            m_EndAction = newAssetEndAction;\n            m_ResourceFile = sanitizedNewAssetResourceFile;\n\n            if (selectAssetBeingCreated)\n            {\n                // Change selection to none or instanceID\n                Selection.activeObject = EditorUtility.InstanceIDToObject(instanceID);\n            }\n            return true;\n        }\n\n        // The asset is created here\n        public void EndNewAssetCreation(string name)\n        {\n            string path = folder + \"/\" + name;\n            if ((!String.IsNullOrEmpty(extension)) && (!path.EndsWith(extension, System.StringComparison.OrdinalIgnoreCase)))\n                path = path + extension;\n            EndNameEditAction endAction = m_EndAction;\n            int instanceID = m_InstanceID;\n            string resourceFile = m_ResourceFile;\n            Clear(); // Ensure clear if anything goes bad in EndNameEditAction and gui is exited.\n\n            ProjectWindowUtil.EndNameEditAction(endAction, instanceID, path, resourceFile, true);\n        }\n\n        public void EndNewAssetCreationCanceled(string name)\n        {\n            string path = folder + \"/\" + name;\n            if ((!String.IsNullOrEmpty(extension)) && (!path.EndsWith(extension, System.StringComparison.OrdinalIgnoreCase)))\n                path = path + extension;\n            ProjectWindowUtil.EndNameEditAction(m_EndAction, m_InstanceID, path, m_ResourceFile, false);\n        }\n\n        public bool IsCreatingNewAsset()\n        {\n            return !string.IsNullOrEmpty(m_Path);\n        }\n    }\n} // end namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/DockArea.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.StyleSheets;\nusing UnityEditor.Experimental;\nusing UnityEditorInternal;\nusing UnityEngine.XR;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace UnityEditor\n{\n    internal struct GUIContentKey\n    {\n        public bool hasUnsavedChanges;\n        public string text;\n\n        public GUIContentKey(string text, bool hasUnsavedChanges)\n        {\n            this.hasUnsavedChanges = hasUnsavedChanges;\n            this.text = text;\n        }\n    }\n\n    internal class DockArea : HostView, IDropArea\n    {\n        private static class Styles\n        {\n            private static readonly StyleBlock tab = EditorResources.GetStyle(\"tab\");\n            public static readonly GUIStyle background = \"dockarea\";\n            public static readonly float tabMinWidth = tab.GetFloat(StyleCatalogKeyword.minWidth, 50.0f);\n            public static readonly float tabMaxWidth = tab.GetFloat(StyleCatalogKeyword.maxWidth, 150.0f);\n            public static readonly float tabWidthPadding = tab.GetFloat(StyleCatalogKeyword.paddingRight);\n\n            public static readonly float tabDragWidth = EditorResources.GetStyle(\"tab-drag\").GetFloat(StyleCatalogKeyword.width, 100.0f);\n\n            public static readonly GUIStyle tabScrollerPrevButton = new GUIStyle(\"dragtab scroller prev\");\n            public static readonly GUIStyle tabScrollerNextButton = new GUIStyle(\"dragtab scroller next\");\n\n            public static SVC<float> genericMenuTopOffset = new SVC<float>(\"--window-generic-menu-top-offset\", 20f);\n            public static SVC<float> genericMenuFloatingTopOffset = new SVC<float>(\"--window-floating-generic-menu-top-offset\", 20f);\n\n            public static readonly GUIStyle tabLabel = new GUIStyle(\"dragtab\") { name = \"dragtab-label\" };\n            public static readonly GUIStyle dragTab = new GUIStyle(\"dragtab\");\n            public static readonly GUIStyle dragTabFirst = new GUIStyle(\"dragtab first\");\n            public static readonly GUIStyle dockTitleBarStyle = new GUIStyle(\"dockHeader\");\n        }\n\n        internal const int kFloatingWindowTopBorderWidth = 2;\n        internal const float kTabHeight = 25 - 1; // This constant is duplicated in native code. See ContainerWindow.cpp. (Tab height -1)\n        internal const float kDockHeight = 39;\n        internal const float kSideBorders = 1.0f;\n        internal const float kBottomBorders = 2.0f;\n\n        // Which pane window would we drop the currently dragged pane over\n        static int s_PlaceholderPos;\n        // Which pane is currently being dragged around\n        static EditorWindow s_DragPane;\n        // Where did it come from\n        internal static DockArea s_OriginalDragSource;\n\n        // Mouse coords when we started the drag (used to figure out when we should trigger a drag)\n        static Vector2 s_StartDragPosition;\n        // Are we dragging yet?\n        static bool s_IsDragging;\n        // A view that shouldn't be docked to (to make sure we don't attach to a single view with only the tab that we're dragging)\n        static internal View s_IgnoreDockingForView = null;\n\n        private static DropInfo s_DropInfo = null;\n        private static Dictionary<GUIContentKey, GUIContent> s_GUIContents = new Dictionary<GUIContentKey, GUIContent>();\n\n        private static bool? s_HasStaticTabsCapabilityCached;\n        private static bool s_HasStaticTabsCapability\n        {\n            get\n            {\n                if (s_HasStaticTabsCapabilityCached != null)\n                    return (bool)s_HasStaticTabsCapabilityCached;\n\n                s_HasStaticTabsCapabilityCached = ModeService.HasCapability(ModeCapability.StaticTabs, false);\n                ModeService.modeChanged += (_) => s_HasStaticTabsCapabilityCached = ModeService.HasCapability(ModeCapability.StaticTabs, false);\n                return (bool)s_HasStaticTabsCapabilityCached;\n            }\n        }\n\n        [SerializeField] internal List<EditorWindow> m_Panes = new List<EditorWindow>();\n        [SerializeField] internal int m_Selected;\n        [SerializeField] internal int m_LastSelected;\n        [NonSerialized] internal GUIStyle tabStyle = null;\n\n        private bool m_IsBeingDestroyed;\n        private Rect m_ScrollLeftRect;\n        private Rect m_ScrollRightRect;\n        private float m_TotalTabWidth;\n        private float m_ScrollOffset;\n        private float m_HoldScrollOffset;\n        private double m_HoldScrollTimestamp;\n        private Rect m_TabAreaRect = Rect.zero;\n        private int? newlyAddedTabIndex = null;\n\n        internal int pendingSelect = -1;\n        internal int pendingSelectVersion = 0;\n        public int selected\n        {\n            get { return m_Selected; }\n            set { SetSelectedPrivate(value, sendEvents: true); }\n        }\n\n        private void SetSelectedPrivate(int value, bool sendEvents)\n        {\n            if (m_Selected != value)\n                m_LastSelected = m_Selected;\n            m_Selected = value;\n            if (m_Selected >= 0 && m_Selected < m_Panes.Count)\n                SetActualViewInternal(m_Panes[m_Selected], sendEvents);\n        }\n\n        public DockArea()\n        {\n            if (m_Panes != null && m_Panes.Count != 0)\n                Debug.LogError(\"m_Panes is filled in DockArea constructor.\");\n        }\n\n        private void RemoveNullWindows()\n        {\n            m_Panes = m_Panes.Where(w => w).ToList();\n            // Restore dock area actual view if there is no valid pane left.\n            if (m_Panes.Count == 0 && actualView)\n                m_Panes.Add(actualView);\n            s_GUIContents.Clear();\n        }\n\n        protected override void OnDestroy()\n        {\n            // Prevents double-destroy that may be indirectly caused if Close() is called by OnLostFocus()\n            m_IsBeingDestroyed = true;\n\n            if (hasFocus)\n                OnLostFocus();\n\n            actualView = null;\n\n            // Since m_Panes can me modified indirectly by OnDestroy() callbacks, make a copy of it for safe iteration\n            var windows = new List<EditorWindow>(m_Panes);\n\n            foreach (EditorWindow w in windows)\n            {\n                // Avoid destroying a window that has already being destroyed (case 967778)\n                if (w == null)\n                    continue;\n\n                UnityEngine.Object.DestroyImmediate(w, true);\n            }\n\n            m_Panes.Clear();\n            s_GUIContents.Clear();\n\n            base.OnDestroy();\n        }\n\n        protected override void OnEnable()\n        {\n            if (m_Panes != null)\n            {\n                if (m_Panes.Count == 0)\n                    m_Selected = 0;\n                else\n                {\n                    // before fix for case 840151, it is possible that out of range selected index was serialized (e.g., case 846859)\n                    m_Selected = Math.Min(m_Selected, m_Panes.Count - 1);\n                    actualView = m_Panes[m_Selected];\n                }\n            }\n\n            base.OnEnable();\n\n            ((IEditorWindowModel)this).onSplitterGUIHandler = HandleSplitView;\n        }\n\n        internal void ReplaceTab(EditorWindow originalWindow, EditorWindow newWindow)\n        {\n            int idx = m_Panes.IndexOf(originalWindow);\n            AddTab(idx, newWindow);\n            RemoveTab(originalWindow);\n        }\n\n        public void AddTab(EditorWindow pane, bool sendPaneEvents = true)\n        {\n            AddTab(m_Panes.Count, pane, sendPaneEvents);\n        }\n\n        public void AddTab(int idx, EditorWindow pane, bool sendPaneEvents = true)\n        {\n            DeregisterSelectedPane(clearActualView: true, sendEvents: true);\n            m_Panes.Insert(idx, pane);\n            SetSelectedPrivate(idx, sendPaneEvents);\n            s_GUIContents.Clear();\n\n            var sp = parent as SplitView;\n            if (sp)\n                sp.Reflow();\n\n            Invoke(\"OnAddedAsTab\", pane);\n            Repaint();\n            window?.UnsavedStateChanged();\n\n            // Make sure the newly added tab is visible.\n            // We can skip the first one to gain some performance.\n            if (idx > 0)\n                newlyAddedTabIndex = idx;\n        }\n\n        public void RemoveTab(EditorWindow pane) { RemoveTab(pane, killIfEmpty: true); }\n        public void RemoveTab(EditorWindow pane, bool killIfEmpty, bool sendEvents = true)\n        {\n            Invoke(\"OnBeforeRemovedAsTab\", pane);\n\n            if (actualView == pane)\n                DeregisterSelectedPane(clearActualView: true, sendEvents: sendEvents);\n\n            int idx = m_Panes.IndexOf(pane);\n            if (idx == -1)\n                return; // Pane is not in the window\n\n            m_Panes.Remove(pane);\n            s_GUIContents.Clear();\n\n            // Fixup last selected index\n            if (idx == m_LastSelected)\n                m_LastSelected = m_Panes.Count - 1;\n            else if (idx < m_LastSelected || m_LastSelected == m_Panes.Count)\n                --m_LastSelected;\n\n            m_LastSelected = Mathf.Clamp(m_LastSelected, 0, m_Panes.Count - 1);\n\n            // Fixup selected index\n            m_Selected = idx == m_Selected ? m_LastSelected : m_Panes.IndexOf(actualView);\n\n            if (m_Selected >= 0 && m_Selected < m_Panes.Count)\n                actualView = m_Panes[m_Selected];\n\n            UpdateWindowTitle(actualView);\n            UpdateWindowHasUnsavedChanges(actualView);\n\n            Repaint();\n            pane.m_Parent = null;\n            if (killIfEmpty)\n                KillIfEmpty();\n        }\n\n        private static void UpdateWindowTitle(EditorWindow w)\n        {\n            if (w &&\n                w.m_Parent &&\n                w.m_Parent.window &&\n                !w.m_Parent.window.IsMultiplayerClone() &&\n                w.titleContent != null)\n            {\n                w.m_Parent.window.title = w.titleContent.text;\n            }\n        }\n\n        private static void UpdateWindowHasUnsavedChanges(EditorWindow w)\n        {\n            if (w && w.m_Parent && w.m_Parent.window)\n                w.m_Parent.window.UnsavedStateChanged();\n        }\n\n        private void KillIfEmpty()\n        {\n            // if we're empty, remove ourselves\n            if (m_Panes.Count != 0)\n                return;\n\n            if (parent == null)\n            {\n                window?.Close();\n                return;\n            }\n\n            SplitView sw = (SplitView)parent;\n            sw.RemoveChildNice(this);\n\n            if (!m_IsBeingDestroyed)\n                DestroyImmediate(this, true);\n\n            sw.Cleanup();\n        }\n\n        private int FindPaneIndex(EditorWindow window)\n        {\n            for (int i = 0; i < m_Panes.Count; ++i)\n            {\n                if (m_Panes[i] == window)\n                    return i;\n            }\n\n            return -1;\n        }\n\n        public DropInfo DragOver(EditorWindow window, Vector2 mouseScreenPosition)\n        {\n            Rect r = screenPosition;\n            r.height = kDockHeight;\n            if (!r.Contains(mouseScreenPosition))\n                return null;\n\n            Rect scr = Styles.background.margin.Remove(screenPosition);\n            Vector2 pos = mouseScreenPosition - new Vector2(scr.x, scr.y);\n            var tabWidth = GetTabWidth(tabStyle, window);\n            int mPos = GetTabAtMousePos(tabStyle, pos);\n\n            if (s_PlaceholderPos != mPos)\n            {\n                Repaint();\n                s_PlaceholderPos = mPos;\n            }\n\n            var dragTopOffset = floatingWindow && isTop ? 2 : 0;\n            DropInfo di = new DropInfo(this)\n            {\n                type = DropInfo.Type.Tab,\n                rect = new Rect(pos.x - tabWidth * .25f + scr.x, scr.y + dragTopOffset, tabWidth, kTabHeight)\n            };\n\n            return di;\n        }\n\n        public bool PerformDrop(EditorWindow w, DropInfo info, Vector2 screenPos)\n        {\n            // Don't send focus events to the tab being moved\n            s_OriginalDragSource.RemoveTab(w, killIfEmpty: s_OriginalDragSource != this, sendEvents: false);\n            int tabInsertIndex = s_PlaceholderPos == -1 || s_PlaceholderPos > m_Panes.Count ? m_Panes.Count : s_PlaceholderPos;\n            AddTab(tabInsertIndex, w, sendPaneEvents: false);\n            selected = tabInsertIndex;\n            return true;\n        }\n\n        protected bool floatingWindow\n        {\n            get\n            {\n                if (window == null || window.rootView == null)\n                    return false;\n                return window.showMode != ShowMode.MainWindow;\n            }\n        }\n\n        bool isTop => windowPosition.yMin <= 0;\n        protected bool isTopRightPane => windowPosition.xMax >= Mathf.FloorToInt(window.position.width) && isTop;\n\n        protected override void OldOnGUI()\n        {\n            EditorGUIUtility.ResetGUIState();\n\n            // Exit if the window was destroyed after entering play mode or on domain-reload.\n            if (window == null)\n                return;\n\n            if (newlyAddedTabIndex.HasValue)\n            {\n                EnsureNewlyAddedTabIsVisible(newlyAddedTabIndex.Value);\n                newlyAddedTabIndex = null;\n            }\n\n            if (actualView)\n                GUI.color = actualView.rootVisualElement.playModeTintColor;\n\n            var borderSize = GetBorderSize();\n\n            Rect dockAreaRect = new Rect(0, 0, position.width, position.height);\n            Rect containerWindowPosition = window.position;\n            float scale = GetBackingScaleFactor();\n            containerWindowPosition.width = GUIUtility.RoundToPixelGrid(containerWindowPosition.width, scale);\n            containerWindowPosition.height = GUIUtility.RoundToPixelGrid(containerWindowPosition.height, scale);\n\n            DrawDockAreaBackground(dockAreaRect);\n\n            var viewRect = UpdateViewRect(dockAreaRect);\n            var titleBarRect = new Rect(viewRect.x, dockAreaRect.y, viewRect.width, borderSize.top);\n            float genericMenuLeftOffset = GetGenericMenuLeftOffset(floatingWindow && isTopRightPane);\n            m_TabAreaRect = new Rect(titleBarRect.x, viewRect.y - kTabHeight, titleBarRect.width - (GetExtraButtonsWidth() + genericMenuLeftOffset), kTabHeight);\n\n            DrawDockTitleBarBackground(titleBarRect);\n            HandleTabScrolling(m_TabAreaRect);\n\n            float genericMenuTopOffset = Styles.genericMenuTopOffset;\n            if (floatingWindow && isTopRightPane)\n            {\n                genericMenuTopOffset = Styles.genericMenuFloatingTopOffset;\n            }\n            if (!ContainerWindow.s_Modal)\n            {\n                ShowGenericMenu(position.width - genericMenuLeftOffset, m_TabAreaRect.y + genericMenuTopOffset);\n            }\n\n            HandleSplitView(); //fogbugz 1169963: in order to easily use the splitter in the gameView, it must be prioritized over DrawView(). Side effect for touch is that splitter picking zones might overlap other controls but the tabs still have higher priority so the user can undock the window in that case\n            DrawTabs(m_TabAreaRect);\n            DrawView(dockAreaRect);\n\n            DrawTabScrollers(m_TabAreaRect);\n\n            EditorGUI.ShowRepaints();\n        }\n\n        private void DrawView(Rect dockAreaRect)\n        {\n            InvokeOnGUI(dockAreaRect);\n            RenderToHMDIfNecessary();\n        }\n\n        private void DrawTabs(Rect tabAreaRect)\n        {\n            Rect clipRect = tabAreaRect;\n\n            if (floatingWindow && isTop)\n                clipRect.yMin = 0;\n\n            // If the left scroll button is visible then clip the tabs a bit more because of the top left border radius of the scroll left button\n            if (m_ScrollOffset > 0f)\n                clipRect.xMin += 3;\n\n            using (new GUI.ClipScope(clipRect, new Vector2(-m_ScrollOffset - 1f, 0)))\n            {\n                if (tabStyle == null)\n                    tabStyle = Styles.dragTab;\n\n                var firstTabStyle = Styles.dragTabFirst;\n\n                var totalTabWidth = DragTab(tabAreaRect, m_ScrollOffset, tabStyle, firstTabStyle);\n                if (totalTabWidth > 0f)\n                    m_TotalTabWidth = totalTabWidth;\n                tabStyle = Styles.dragTab;\n            }\n        }\n\n        private Rect UpdateViewRect(Rect dockAreaRect)\n        {\n            var border = GetBorderSize();\n\n            var viewRect = new Rect(\n                dockAreaRect.x + border.left,\n                dockAreaRect.y + border.top,\n                dockAreaRect.width - (border.left + border.right),\n                dockAreaRect.height - (border.top + border.bottom));\n\n            if (selected >= 0 && selected < m_Panes.Count)\n                m_Panes[selected].m_Pos = new Rect(GUIUtility.GUIToScreenPoint(Vector2.zero), viewRect.size);\n\n            return viewRect;\n        }\n\n        private void DrawDockAreaBackground(Rect dockAreaRect)\n        {\n            if (Event.current.type == EventType.Repaint)\n            {\n                var backgroundRect = dockAreaRect;\n                backgroundRect.y = 0;\n                Styles.background.Draw(backgroundRect, GUIContent.none, 0);\n            }\n        }\n\n        private void DrawDockTitleBarBackground(Rect titleBarRect)\n        {\n            if (Event.current.type == EventType.Repaint)\n                Styles.dockTitleBarStyle.Draw(titleBarRect, GUIContent.none, 0);\n        }\n\n        private void SetupHoldScrollerUpdate(float clickOffset)\n        {\n            m_HoldScrollOffset = clickOffset;\n            m_HoldScrollTimestamp = EditorApplication.timeSinceStartup;\n            EditorApplication.update += OnMouseDownHoldScroller;\n        }\n\n        private void HandleTabScrolling(Rect tabAreaRect)\n        {\n            if (Event.current.type == EventType.MouseDown)\n            {\n                const float scrollOffsetShift = 20f;\n                if (m_ScrollLeftRect.Contains(Event.current.mousePosition))\n                {\n                    SetupHoldScrollerUpdate(-2f);\n                    m_ScrollOffset = Mathf.Max(0f, m_ScrollOffset - scrollOffsetShift);\n                    Event.current.Use();\n                }\n                else if (m_ScrollRightRect.Contains(Event.current.mousePosition))\n                {\n                    SetupHoldScrollerUpdate(2f);\n                    m_ScrollOffset = Mathf.Min(m_ScrollOffset + scrollOffsetShift, m_TotalTabWidth - tabAreaRect.width);\n                    Event.current.Use();\n                }\n            }\n            else if (Event.current.type == EventType.MouseUp)\n            {\n                m_HoldScrollOffset = 0f;\n                EditorApplication.update -= OnMouseDownHoldScroller;\n            }\n        }\n\n        private void DrawTabScroller(Rect scrollRect, GUIStyle tabScroller)\n        {\n            tabScroller.Draw(scrollRect, scrollRect.Contains(Event.current.mousePosition), false, false, false);\n        }\n\n        private void DrawTabScrollers(Rect tabAreaRect)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            if (m_TotalTabWidth <= tabAreaRect.xMax)\n                m_ScrollOffset = 0;\n\n            float scrollerButtonHeight = tabAreaRect.height;\n            if (m_ScrollOffset > 0f)\n            {\n                m_ScrollLeftRect = new Rect(tabAreaRect.xMin, tabAreaRect.yMin , 16f, scrollerButtonHeight);\n                DrawTabScroller(m_ScrollLeftRect, Styles.tabScrollerPrevButton);\n            }\n            else\n                m_ScrollLeftRect.width = 0;\n\n            if (m_TotalTabWidth > tabAreaRect.width && m_ScrollOffset < (m_TotalTabWidth - tabAreaRect.width))\n            {\n                m_ScrollRightRect = new Rect(tabAreaRect.xMax - 16f, tabAreaRect.yMin, 16f, scrollerButtonHeight);\n                DrawTabScroller(m_ScrollRightRect, Styles.tabScrollerNextButton);\n            }\n            else\n                m_ScrollRightRect.width = 0;\n        }\n\n        private void HandleSplitView()\n        {\n            // Add CursorRects\n            SplitView sp = parent as SplitView;\n\n            if (Event.current.type == EventType.Repaint && sp)\n            {\n                View view = this;\n                while (sp)\n                {\n                    int id = sp.controlID;\n\n                    if (id == GUIUtility.hotControl || GUIUtility.hotControl == 0)\n                    {\n                        int idx = sp.IndexOfChild(view);\n                        if (sp.vertical)\n                        {\n                            if (idx != 0)\n                                EditorGUIUtility.AddCursorRect(new Rect(0, 0, position.width, SplitView.kGrabDist), MouseCursor.SplitResizeUpDown, id);\n                            if (idx != sp.children.Length - 1)\n                                EditorGUIUtility.AddCursorRect(\n                                    new Rect(0, position.height - SplitView.kGrabDist + 1, position.width, SplitView.kGrabDist),\n                                    MouseCursor.SplitResizeUpDown, id);\n                        }\n                        else // horizontal\n                        {\n                            if (idx != 0)\n                                EditorGUIUtility.AddCursorRect(new Rect(0, 0, SplitView.kGrabDist, position.height), MouseCursor.SplitResizeLeftRight,\n                                    id);\n                            if (idx != sp.children.Length - 1)\n                                EditorGUIUtility.AddCursorRect(\n                                    new Rect(position.width - SplitView.kGrabDist + 1, 0, SplitView.kGrabDist, position.height),\n                                    MouseCursor.SplitResizeLeftRight, id);\n                        }\n                    }\n\n                    view = sp;\n                    sp = sp.parent as SplitView;\n                }\n\n                // reset\n                sp = (SplitView)parent;\n            }\n\n            if (sp)\n            {\n                Event e = new Event(Event.current);\n                e.mousePosition += new Vector2(position.x, position.y);\n                sp.SplitGUI(e);\n                if (e.type == EventType.Used)\n                    Event.current.Use();\n            }\n        }\n\n        private void OnMouseDownHoldScroller()\n        {\n            if (m_HoldScrollOffset == 0f)\n                return;\n\n            double timeSinceStartup = EditorApplication.timeSinceStartup;\n            float dt = (float)(timeSinceStartup - m_HoldScrollTimestamp);\n            float maxScrollOffset = m_TotalTabWidth - m_TabAreaRect.width;\n            m_HoldScrollTimestamp = timeSinceStartup;\n            m_ScrollOffset = Mathf.Max(0f, Mathf.Min(m_ScrollOffset + m_HoldScrollOffset * dt * 250.0f, maxScrollOffset));\n            Repaint();\n        }\n\n        private void RenderToHMDIfNecessary()\n        {\n            if (Event.current.type != EventType.Repaint ||\n                !XRSettings.isDeviceActive ||\n                !EditorApplication.isPlaying ||\n                EditorApplication.isPaused ||\n                (actualView is GameView))\n                return;\n\n            foreach (var pane in m_Panes)\n            {\n                if (pane is GameView)\n                {\n                    var gameView = pane as GameView;\n                    gameView.RenderToHMDOnly();\n                }\n            }\n        }\n\n        protected override void SetActualViewPosition(Rect newPos)\n        {\n            //Sit down and let me tell you the intent of this.\n            //the position property should return the \"usable\" dimension of the window\n            //In the case of DockArea i not the whole window, because we reserve some space on the top for the\n            //window tabs. Because of that we want to report a DockArea.position that does not contain the height of that bar.\n            //This is exactly what we try to do here, remove the tab area from the rect passed in.\n            //Note that this code path so far is only used when the HostView, SplitView, or any \"parent\" view changes its dimensions and\n            //tries to propagate that to its \"children\"\n            //There are other code paths that also set the Dockarea.position, that won't go through here.\n            //But its important that they all return the same values.\n            var adjustedDockAreaClientRect = borderSize.Remove(newPos);\n            base.SetActualViewPosition(adjustedDockAreaClientRect);\n\n            foreach (EditorWindow pane in m_Panes)\n            {\n                if (pane != this)\n                    pane.OnBackgroundViewResized(adjustedDockAreaClientRect);\n            }\n        }\n\n        private void Maximize(object userData)\n        {\n            EditorWindow editorWindow = userData as EditorWindow;\n            if (editorWindow != null)\n            {\n                WindowLayout.Maximize(editorWindow);\n            }\n        }\n\n        internal void Close(object userData)\n        {\n            EditorWindow editorWindow = userData as EditorWindow;\n            if (editorWindow != null)\n            {\n                if (ContainerWindow.CanClose(editorWindow))\n                {\n                    editorWindow.Close();\n                }\n            }\n            else\n            {\n                RemoveTab(null, false);\n                KillIfEmpty();\n            }\n        }\n\n        private bool AllowTabAction()\n        {\n            int mainWindowPaneCount = 0;\n\n            ContainerWindow w = ContainerWindow.windows.FirstOrDefault(e => e.showMode == ShowMode.MainWindow);\n            if (w != null)\n            {\n                foreach (View view in w.rootView.allChildren)\n                {\n                    DockArea da = view as DockArea;\n                    if (da != null)\n                    {\n                        mainWindowPaneCount += da.m_Panes.Count;\n                        if (mainWindowPaneCount > 1) return true;\n                    }\n                }\n            }\n\n            return false;\n        }\n\n        protected override void AddDefaultItemsToMenu(GenericMenu menu, EditorWindow view)\n        {\n            base.AddDefaultItemsToMenu(menu, view);\n\n            if (view)\n            {\n                if (parent.window.showMode == ShowMode.MainWindow && view.CanMaximize())\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Maximize\"), !(parent is SplitView), Maximize, view);\n                else\n                    menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Maximize\"));\n            }\n\n            bool closeAllowed = (window.showMode != ShowMode.MainWindow || AllowTabAction());\n            if (closeAllowed)\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Close Tab\"), false, Close, view);\n            else\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Close Tab\"));\n            menu.AddSeparator(\"\");\n\n            IEnumerable<Type> types = GetPaneTypes();\n            GUIContent baseContent = EditorGUIUtility.TrTextContent(\"Add Tab\");\n            foreach (Type t in types)\n            {\n                if (t == null)\n                {\n                    menu.AddSeparator(baseContent.text + \"/\");\n                    continue;\n                }\n\n                GUIContent entry = new GUIContent(EditorWindow.GetLocalizedTitleContentFromType(t)); // make a copy since we modify the text below\n                entry.text = baseContent.text + \"/\" + entry.text;\n                menu.AddItem(entry, false, AddTabToHere, t);\n            }\n\n            menu.AddSeparator(\"\");\n\n            editorWindowBackend?.OnDisplayWindowMenu(menu);\n        }\n\n        void AddTabToHere(object userData)\n        {\n            EditorWindow win = (EditorWindow)CreateInstance((System.Type)userData);\n            AddTab(win);\n        }\n\n        private float GetTabWidth(GUIStyle tabStyle, EditorWindow tabWindow)\n        {\n            float minWidth, expectedWidth;\n            tabStyle.CalcMinMaxWidth(tabWindow.titleContent, out minWidth, out expectedWidth);\n            return Mathf.Max(Mathf.Min(expectedWidth, Styles.tabMaxWidth), Styles.tabMinWidth) + Styles.tabWidthPadding;\n        }\n\n        private float GetTabWidth(GUIStyle tabStyle, int tabIndex)\n        {\n            Debug.Assert(0 <= tabIndex && tabIndex < m_Panes.Count);\n            return GetTabWidth(tabStyle, m_Panes[tabIndex]);\n        }\n\n        private int GetTabAtMousePos(GUIStyle tabStyle, Vector2 mousePos)\n        {\n            return GetTabAtMousePos(tabStyle, mousePos, new Rect(0, 0, position.width, kTabHeight));\n        }\n\n        private int GetTabAtMousePos(GUIStyle tabStyle, Vector2 mousePos, Rect tabAreaRect)\n        {\n            Rect tabRect = Rect.zero;\n            return GetTabAtMousePos(tabStyle, mousePos + new Vector2(m_ScrollOffset, 0), tabAreaRect, 0f, ref tabRect);\n        }\n\n        private int GetTabAtMousePos(GUIStyle tabStyle, Vector2 mousePos, float scrollOffset, Rect tabAreaRect)\n        {\n            Rect tabRect = Rect.zero;\n            return GetTabAtMousePos(tabStyle, mousePos, tabAreaRect, scrollOffset, ref tabRect);\n        }\n\n        private int GetTabAtMousePos(GUIStyle tabStyle, Vector2 mousePos, Rect tabAreaRect, float scrollOffset, ref Rect tabRect)\n        {\n            if (!tabAreaRect.Contains(mousePos - new Vector2(scrollOffset, 0)))\n                return -1;\n\n            float xPos = tabAreaRect.xMin;\n            for (int i = 0; i < m_Panes.Count; i++)\n            {\n                float tabWidth = GetTabWidth(tabStyle, i);\n                if (xPos <= mousePos.x && mousePos.x < xPos + tabWidth)\n                {\n                    tabRect = new Rect(xPos, tabAreaRect.yMin + tabStyle.margin.top, tabWidth, tabAreaRect.height);\n                    return i;\n                }\n\n                xPos += tabWidth;\n            }\n\n            return -1;\n        }\n\n        void EnsureNewlyAddedTabIsVisible(int index)\n        {\n            if (m_TabAreaRect.xMax == 0.0f)\n                return;\n\n            if (index < 0 || index >= m_Panes.Count)\n                return;\n\n            // Get the X position and width of the selected tab.\n            var selectedTabX = CalculateTabXPosition(index);\n            var selectedTabWidth = GetTabWidth(Styles.dragTab, index);\n\n            // Calculate the left and right edges of the tab.\n            var leftEdge = selectedTabX;\n            var rightEdge = selectedTabX + selectedTabWidth;\n\n            // Adjust the scroll offset if the tab is outside the visible range.\n            if (leftEdge < m_TabAreaRect.xMin + m_ScrollOffset)\n            {\n                m_ScrollOffset = leftEdge - m_TabAreaRect.xMin;\n            }\n            else if (rightEdge > m_TabAreaRect.xMax + m_ScrollOffset)\n            {\n                m_ScrollOffset = rightEdge - m_TabAreaRect.xMax;\n            }\n        }\n\n        float CalculateTabXPosition(int index)\n        {\n            var xPos = m_TabAreaRect.xMin;\n            for (var i = 0; i < index; i++)\n            {\n                float tabWidth = GetTabWidth(Styles.dragTab, i);\n                xPos += tabWidth;\n            }\n\n            return xPos;\n        }\n\n        // internal method for testing.\n        internal bool IsTabVisible(int index)\n        {\n            var tabPosition = CalculateTabXPosition(index);\n            var tabWidth = GetTabWidth(Styles.dragTab, index);\n\n            // Calculate the left and right edges of the tab.\n            var leftEdge = tabPosition;\n            var rightEdge = tabPosition + tabWidth;\n\n            if (leftEdge >= m_TabAreaRect.xMin + m_ScrollOffset && rightEdge <= m_TabAreaRect.xMax + m_ScrollOffset)\n                return true;\n\n            return false;\n        }\n\n        // Hack to get around Unity crashing when we have circular references in saved stuff\n        internal override void Initialize(ContainerWindow win)\n        {\n            base.Initialize(win);\n            RemoveNullWindows();\n            foreach (EditorWindow i in m_Panes)\n                i.m_Parent = this;\n        }\n\n        private static void CheckDragWindowExists()\n        {\n            if (s_IsDragging && !PaneDragTab.get.m_Window)\n            {\n                s_OriginalDragSource.RemoveTab(s_DragPane);\n                DestroyImmediate(s_DragPane);\n                PaneDragTab.get.Close();\n                GUIUtility.hotControl = 0;\n                ResetDragVars();\n            }\n        }\n\n        private void OpenTabDelayed(int tabToOpen)\n        {\n            if (tabToOpen == selected)\n            {\n                return;\n            }\n\n            if (tabToOpen == -1)\n            {\n                return;\n            }\n\n            if (Interlocked.Exchange(ref pendingSelect, tabToOpen) == tabToOpen)\n            {\n                return;\n            }\n\n            int pendingVersion = Interlocked.Increment(ref pendingSelectVersion);\n\n            var t = Task.Run(async delegate\n            {\n                await Task.Delay(250);\n                return 0;\n            });\n\n            t.Wait();\n\n            Vector2 mousePos = GUIUtility.ScreenToGUIPoint(Editor.GetCurrentMousePosition());\n            int tabUnderMouse = GetTabAtMousePos(tabStyle, mousePos);\n\n            if (tabUnderMouse != tabToOpen)\n            {\n                Interlocked.CompareExchange(ref pendingSelect, -1, tabToOpen);\n                return;\n            }\n\n            if (pendingVersion != pendingSelectVersion)\n            {\n                return;\n            }\n\n            selected = tabToOpen;\n        }\n\n        private float DragTab(Rect tabAreaRect, float scrollOffset, GUIStyle tabStyle, GUIStyle firstTabStyle)\n        {\n            Event evt = Event.current;\n            int id = GUIUtility.GetControlID(FocusType.Passive);\n\n            // Detect if hotcontrol was cleared while dragging (happens when pressing Esc).\n            // We do not listen for the Escape keydown event because it is sent to the dragged window (not this dockarea)\n            if (s_IsDragging && GUIUtility.hotControl == 0)\n            {\n                PaneDragTab.get.Close();\n                ResetDragVars();\n            }\n\n            float xPos = 0f;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.TouchDown:\n                case EventType.MouseDown:\n\n                    // Handle double click\n                    if (EditorWindow.focusedWindow != null && !s_HasStaticTabsCapability)\n                        WindowMaximizeStateOnDoubleClick(tabAreaRect);\n                    if (GUIUtility.hotControl == 0)\n                    {\n                        int sel = GetTabAtMousePos(tabStyle, evt.mousePosition, scrollOffset, tabAreaRect);\n                        if (sel != -1 && sel < m_Panes.Count)\n                        {\n                            switch (evt.button)\n                            {\n                                case 0:\n                                    if (selected != sel)\n                                        selected = sel;\n\n                                    GUIUtility.hotControl = id;\n                                    s_StartDragPosition = evt.mousePosition;\n                                    s_IsDragging = false;\n                                    evt.Use();\n                                    break;\n                                case 2:\n                                    if (!s_HasStaticTabsCapability)\n                                    {\n                                        Close(m_Panes[sel]);\n                                        evt.Use();\n                                    }\n                                    break;\n                            }\n                        }\n                    }\n                    break;\n                case EventType.ContextClick:\n\n                    if (GUIUtility.hotControl == 0)\n                    {\n                        int sel = GetTabAtMousePos(tabStyle, evt.mousePosition, scrollOffset, tabAreaRect);\n                        var menuPos = new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0);\n                        if (sel != -1 && sel < m_Panes.Count && !ContainerWindow.s_Modal)\n                            PopupGenericMenu(m_Panes[sel], menuPos);\n                        else if (!ContainerWindow.s_Modal && m_Panes.Count == 0) // i.e. all panes have failed to load\n                            PopupGenericMenu(null, menuPos);\n                    }\n                    break;\n                case EventType.TouchMove:\n                case EventType.MouseDrag:\n\n                if (s_HasStaticTabsCapability)\n                    {\n                        break;\n                    }\n\n                    if (evt.pointerType == PointerType.Pen && !evt.penStatus.HasFlag(PenStatus.Contact))\n                        break;\n\n                    if (GUIUtility.hotControl == id)\n                    {\n                        Vector2 delta = evt.mousePosition - s_StartDragPosition;\n                        evt.Use();\n                        Rect screenRect = screenPosition;\n\n                        // if we're not tab dragging yet, check to see if we should start\n\n                        // If modal window exists, disable all tab behavior\n                        if (ContainerWindow.s_Modal) break;\n\n                        // check if we're allowed to drag tab\n                        bool dragAllowed = (window.showMode != ShowMode.MainWindow || AllowTabAction());\n\n                        if (!s_IsDragging && delta.sqrMagnitude > 99 && dragAllowed)\n                        {\n                            s_PlaceholderPos = selected;\n                            s_DragPane = m_Panes[selected];\n\n                            // If we're moving the only editorwindow in this dockarea, we'll be destroyed - so it looks silly if we can attach as children of ourselves\n                            s_IgnoreDockingForView = m_Panes.Count == 1 ? this : null;\n\n                            s_OriginalDragSource = this;\n                            float tabWidth = GetTabWidth(tabStyle, selected);\n\n                            try\n                            {\n                                PaneDragTab.get.Show(\n                                    new Rect(tabAreaRect.x + screenRect.x + tabWidth * selected, tabAreaRect.y + screenRect.y, tabWidth, tabAreaRect.height - 1f),\n                                    s_DragPane.titleContent,\n                                    position.size,\n                                    GUIUtility.GUIToScreenPoint(evt.mousePosition));\n\n                                s_IsDragging = true;\n\n                                EditorApplication.update += CheckDragWindowExists;\n                                Invoke(\"OnTabDragging\", s_DragPane);\n                            }\n                            catch\n                            {\n                                ResetDragVars();\n                                throw;\n                            }\n\n                            // We just showed a window. Exit the GUI because the window might be\n                            // repainting already (esp. on Windows)\n                            GUIUtility.ExitGUI();\n                        }\n                        if (s_IsDragging)\n                        {\n                            // Go over all container windows, ask them to dock the window.\n                            DropInfo di = null;\n                            ContainerWindow[] windows = ContainerWindow.windows;\n                            Vector2 screenMousePos = GUIUtility.GUIToScreenPoint(evt.mousePosition);\n                            ContainerWindow win = null;\n                            foreach (ContainerWindow w in windows)\n                            {\n                                var rootSplitView = w.rootSplitView;\n                                if (rootSplitView == null)\n                                    continue;\n\n                                di = rootSplitView.DragOverRootView(screenMousePos);\n\n                                if (di == null)\n                                {\n                                    foreach (View view in w.rootView.allChildren)\n                                    {\n                                        IDropArea ida = view as IDropArea;\n                                        if (ida != null)\n                                            di = ida.DragOver(s_DragPane, screenMousePos);\n\n                                        if (di != null)\n                                            break;\n                                    }\n                                }\n\n                                if (di != null)\n                                {\n                                    win = w;\n                                    break;\n                                }\n                            }\n                            // Ok, we couldn't find anything, let's create a simplified DropIn\n                            if (di == null)\n                            {\n                                di = new DropInfo(null);\n                            }\n\n                            if (di.type != DropInfo.Type.Tab)\n                                s_PlaceholderPos = -1;\n\n                            s_DropInfo = di;\n\n                            // Handle the window getting closed mid-drag\n                            if (PaneDragTab.get.m_Window)\n                                PaneDragTab.get.SetDropInfo(di, screenMousePos, win);\n                        }\n                    }\n                    break;\n                case EventType.TouchUp:\n                case EventType.MouseUp:\n\n                    if (GUIUtility.hotControl == id)\n                    {\n                        Vector2 screenMousePos = GUIUtility.GUIToScreenPoint(evt.mousePosition);\n                        if (s_IsDragging)\n                        {\n                            // This is where we want to insert it.\n                            s_IsDragging = false;\n                            PaneDragTab.get.Close();\n                            EditorApplication.update -= CheckDragWindowExists;\n\n                            // Try to tell the current DPZ\n                            if (s_DropInfo?.dropArea != null)\n                            {\n                                Invoke(\"OnTabDetached\", s_DragPane);\n                                s_DropInfo.dropArea.PerformDrop(s_DragPane, s_DropInfo, screenMousePos);\n\n                                UpdateWindowTitle(s_DragPane);\n                                UpdateWindowHasUnsavedChanges(s_DragPane);\n                            }\n                            else\n                            {\n                                EditorWindow w = s_DragPane;\n\n                                ResetDragVars();\n\n                                // The active tab that we're moving to the new window stays focused at all times.\n                                // Do not remove focus from the tab being detached.\n                                RemoveTab(w, killIfEmpty: true, sendEvents: false);\n                                Rect wPos = w.position;\n                                wPos.x = screenMousePos.x - wPos.width * .5f;\n                                wPos.y = screenMousePos.y - wPos.height * .5f;\n\n                                // don't put windows top outside of the screen, on mac OS handles this\n                                if (Application.platform == RuntimePlatform.WindowsEditor)\n                                    wPos.y = Mathf.Max(InternalEditorUtility.GetBoundsOfDesktopAtPoint(screenMousePos).y, wPos.y);\n\n                                // Don't call OnFocus on the tab when it is moved to the new window\n                                EditorWindow.CreateNewWindowForEditorWindow(w, loadPosition: false, showImmediately: false, setFocus: false);\n\n                                w.position = ContainerWindow.FitRectToMouseScreen(wPos, true, w.m_Parent.window);\n                                Invoke(\"OnTabNewWindow\", w);\n\n                                GUIUtility.hotControl = 0;\n                                GUIUtility.ExitGUI();\n                            }\n                            ResetDragVars();\n                        }\n\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                    }\n\n                    break;\n\n                case EventType.DragUpdated:\n                case EventType.DragPerform:\n                    {\n                        OpenTabDelayed(GetTabAtMousePos(tabStyle, evt.mousePosition));\n\n                        break;\n                    }\n\n                case EventType.DragExited:\n                    {\n                        Interlocked.Exchange(ref pendingSelect, -1);\n                        break;\n                    }\n\n                case EventType.Repaint:\n                    xPos = tabAreaRect.xMin;\n                    if (actualView)\n                    {\n                        for (int i = 0, drawNum = 0; i < m_Panes.Count; i++)\n                        {\n                            // If we're dragging the tab we're about to draw, don't do that (handled by some window)\n                            if (s_DragPane == m_Panes[i])\n                                continue;\n\n                            // If we need space for inserting a tab here, skip some horizontal\n                            if (s_DropInfo != null && ReferenceEquals(s_DropInfo.dropArea, this) && s_PlaceholderPos == drawNum)\n                                xPos += s_DropInfo.rect.width;\n\n                            var style = i == 0 ? firstTabStyle : tabStyle;\n                            xPos += DrawTab(tabAreaRect, style, i, xPos);\n                            drawNum++;\n                        }\n                    }\n                    else\n                    {\n                        Rect r = new Rect(xPos, tabAreaRect.yMin, Styles.tabDragWidth, tabAreaRect.height);\n                        float roundR = Mathf.Round(r.x);\n                        Rect r2 = new Rect(roundR, r.y, Mathf.Round(r.x + r.width) - roundR, r.height);\n                        tabStyle.Draw(r2, \"Failed to load\", false, true, true, false);\n                    }\n                    break;\n            }\n            selected = Mathf.Clamp(selected, 0, m_Panes.Count - 1);\n\n            return xPos;\n        }\n\n        private GUIContent GetTruncatedTabContent(int tabIndex)\n        {\n            var tabContent = m_Panes[tabIndex].titleContent;\n            bool hasUnsavedChanges = m_Panes[tabIndex].hasUnsavedChanges;\n            string text = tabContent.text;\n            var key = new GUIContentKey(text, hasUnsavedChanges);\n\n            if (s_GUIContents.ContainsKey(key))\n                return s_GUIContents[key];\n\n            // Guarantees the acuracy of the text measurement\n            if (hasUnsavedChanges)\n                text += \"*\";\n\n            int cappedMaxChars = tabStyle.GetNumCharactersThatFitWithinWidth(text, Styles.tabMaxWidth);\n            if (text.Length > cappedMaxChars)\n            {\n                // Save space for the '*'\n                int maxLength = hasUnsavedChanges ? cappedMaxChars - 3 : cappedMaxChars - 2;\n\n                text = text.Substring(0, Math.Max(3, Math.Min(maxLength, text.Length))) + \"\\u2026\";\n\n                // Make sure there is always a '*'\n                if (hasUnsavedChanges)\n                    text += \"*\";\n            }\n\n            GUIContent gc = tabContent;\n\n            // Only update the entry if modified\n            if (text != tabContent.text)\n                gc = new GUIContent(text, tabContent.image, String.IsNullOrEmpty(tabContent.tooltip) ? tabContent.text : tabContent.tooltip);\n\n            s_GUIContents[key] = gc;\n            return gc;\n        }\n\n        private float DrawTab(Rect tabRegionRect, GUIStyle tabStyle, int tabIndex, float xPos)\n        {\n            float tabWidth = GetTabWidth(tabStyle, tabIndex);\n            Rect tabPositionRect = new Rect(xPos, tabRegionRect.yMin + tabStyle.margin.top, tabWidth, tabRegionRect.height);\n            float roundedPosX = Mathf.Round(tabPositionRect.x);\n            float roundedWidth = Mathf.Round(tabPositionRect.x + tabPositionRect.width) - roundedPosX;\n\n            bool isActive = m_Panes[tabIndex] == EditorWindow.focusedWindow;\n\n            if (isActive && !s_HasStaticTabsCapability)\n                UpdateWindowTitle(m_Panes[tabIndex]); // UnsavedChanges decoration already taken care of.\n\n            Rect tabContentRect = new Rect(roundedPosX, tabPositionRect.y, roundedWidth, tabPositionRect.height);\n            tabStyle.Draw(tabContentRect, tabContentRect.Contains(Event.current.mousePosition), isActive, tabIndex == selected, false);\n            GUI.Label(tabPositionRect, GetTruncatedTabContent(tabIndex), Styles.tabLabel);\n\n            var unclippedContentRect = GUIClip.UnclipToWindow(tabContentRect);\n\n            MarkHotRegion(unclippedContentRect);\n\n            return tabWidth;\n        }\n\n        internal RectOffset GetBorderSizeInternal()\n        {\n            if (!window)\n                return m_BorderSize;\n\n            Rect containerWindowPosition = window.position;\n            float scale = GetBackingScaleFactor();\n            containerWindowPosition.width = GUIUtility.RoundToPixelGrid(containerWindowPosition.width, scale);\n            containerWindowPosition.height = GUIUtility.RoundToPixelGrid(containerWindowPosition.height, scale);\n\n            bool customBorder = floatingWindow && windowPosition.y == 0;\n            bool isBottomTab = Mathf.Abs(windowPosition.yMax - containerWindowPosition.height) < 0.02f;\n\n            // Reset\n            m_BorderSize.left = m_BorderSize.right = m_BorderSize.top = m_BorderSize.bottom = 0;\n\n            Rect r = windowPosition;\n            if (r.xMin != 0)\n                m_BorderSize.left += (int)kSideBorders;\n            if (Mathf.Abs(r.xMax - GUIUtility.RoundToPixelGrid(window.position.width, scale)) > 0.02f)\n                m_BorderSize.right += (int)kSideBorders;\n\n            m_BorderSize.top = (int)kTabHeight + (customBorder ? kFloatingWindowTopBorderWidth : 0);\n            m_BorderSize.bottom = isBottomTab ? 0 : (int)kBottomBorders;\n\n            return m_BorderSize;\n        }\n\n        protected override RectOffset GetBorderSize()\n        {\n            return GetBorderSizeInternal();\n        }\n\n        private static void ResetDragVars()\n        {\n            s_DragPane = null;\n            s_DropInfo = null;\n            s_PlaceholderPos = -1;\n            s_IsDragging = false;\n            s_OriginalDragSource = null;\n        }\n\n        internal static bool WindowMaximizeStateOnDoubleClick(Rect rect)\n        {\n            Event evt = Event.current;\n            if (EditorWindow.focusedWindow != null && rect.Contains(evt.mousePosition) && evt.button == 0 && evt.clickCount == 2)\n            {\n                Event.current.Use();\n                bool maximize = !EditorWindow.focusedWindow.maximized;\n                if (maximize)\n                {\n                    EditorApplication.delayCall += () => EditorWindow.focusedWindow.maximized = maximize;\n                    GUIUtility.ExitGUI();\n                }\n                else\n                {\n                    EditorWindow.focusedWindow.maximized = maximize;\n                    InternalEditorUtility.RepaintAllViews();\n                }\n            }\n\n            return EditorWindow.focusedWindow.maximized;\n        }\n    }\n\n    internal class MaximizedHostView : HostView\n    {\n        static class Styles\n        {\n            public static readonly GUIStyle titleBackground = \"dockHeader\";\n            public static readonly GUIStyle titleLabel = new GUIStyle(\"dragtab\") { name = \"dragtab-label\" };\n            public static readonly GUIStyle background = \"dockarea\";\n            public static SVC<float> genericMenuTopOffset = new SVC<float>(\"--window-generic-menu-top-offset\", 20f);\n        }\n\n        protected override void OldOnGUI()\n        {\n            EditorGUIUtility.ResetGUIState();\n\n            if (actualView)\n                GUI.color = actualView.rootVisualElement.playModeTintColor;\n\n            Rect maximizedViewRect = Rect.zero;\n\n            maximizedViewRect.size = position.size;\n            maximizedViewRect = Styles.background.margin.Remove(maximizedViewRect);\n\n            Rect backRect = new Rect(maximizedViewRect.x + 1, maximizedViewRect.y, maximizedViewRect.width - 2, DockArea.kTabHeight);\n            // Return if window is not maximized anymore\n            if (Event.current.type == EventType.MouseDown && EditorWindow.focusedWindow != null && !DockArea.WindowMaximizeStateOnDoubleClick(backRect))\n                return;\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                Styles.background.Draw(maximizedViewRect, GUIContent.none, false, false, false, false);\n                Styles.titleBackground.Draw(backRect, false, false, true, hasFocus);\n\n                var title = GetTitleContent(actualView.titleContent, actualView.hasUnsavedChanges);\n\n                GUI.Label(backRect, title, Styles.titleLabel);\n            }\n\n            if (Event.current.type == EventType.ContextClick && backRect.Contains(Event.current.mousePosition) && !ContainerWindow.s_Modal)\n                PopupGenericMenu(actualView, new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 0, 0));\n\n            // GetGenericMenuLeftOffset false because maximized window are not floating windows\n            ShowGenericMenu(position.width - GetGenericMenuLeftOffset(false), backRect.yMin + Styles.genericMenuTopOffset);\n\n            const float topBottomPadding = 0f;\n            Rect viewRect = maximizedViewRect;\n            viewRect.y = backRect.yMax - topBottomPadding;\n            viewRect.height = position.height - backRect.yMax + topBottomPadding;\n\n            if (actualView)\n                actualView.m_Pos = new Rect(GUIUtility.GUIToScreenPoint(Vector2.zero), viewRect.size);\n\n            InvokeOnGUI(maximizedViewRect);\n        }\n\n        protected override RectOffset GetBorderSize()\n        {\n            m_BorderSize.left = 0;\n            m_BorderSize.right = 0;\n            m_BorderSize.top = (int)DockArea.kTabHeight;\n            // Aras: I don't really know why, but this makes GUI be actually correct.\n            m_BorderSize.bottom = 4;\n\n            return m_BorderSize;\n        }\n\n        void Unmaximize(object userData)\n        {\n            EditorWindow ew = ((EditorWindow)userData);\n            WindowLayout.Unmaximize(ew);\n        }\n\n        protected override void AddDefaultItemsToMenu(GenericMenu menu, EditorWindow window)\n        {\n            base.AddDefaultItemsToMenu(menu, window);\n\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Maximize\"), !(parent is SplitView), Unmaximize, window);\n            menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Close Tab\"));\n            menu.AddSeparator(\"\");\n            IEnumerable<Type> types = GetPaneTypes();\n\n            GUIContent baseContent = EditorGUIUtility.TrTextContent(\"Add Tab\");\n            foreach (Type t in types)\n            {\n                if (t == null)\n                {\n                    menu.AddSeparator(baseContent.text + \"/\");\n                    continue;\n                }\n\n                GUIContent entry = new GUIContent(EditorWindow.GetLocalizedTitleContentFromType(t)); // make a copy since we modify the text below\n                entry.text = baseContent.text + \"/\" + entry.text;\n                menu.AddDisabledItem(entry);\n            }\n\n            menu.AddSeparator(\"\");\n            editorWindowBackend?.OnDisplayWindowMenu(menu);\n        }\n\n        private static Dictionary<GUIContentKey, GUIContent> s_GUIContents = new Dictionary<GUIContentKey, GUIContent>();\n\n        private GUIContent GetTitleContent(GUIContent content, bool hasUnsavedChanges)\n        {\n            string text = content.text;\n            var key = new GUIContentKey(text, hasUnsavedChanges);\n\n            if (s_GUIContents.ContainsKey(key))\n                return s_GUIContents[key];\n\n            if (hasUnsavedChanges)\n                text += \"*\";\n\n            GUIContent gc = content;\n\n            // Only update the entry if modified\n            if (text != content.text)\n                gc = new GUIContent(text, content.image, String.IsNullOrEmpty(content.tooltip) ? content.text : content.tooltip);\n\n            s_GUIContents[key] = gc;\n            return gc;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/DragRect.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditor\n{\n    class DragRectGUI\n    {\n        static int dragRectHash = \"DragRect\".GetHashCode();\n        static int s_DragCandidateState = 0;\n        static float s_DragSensitivity = 1.0f;\n\n        public static int DragRect(Rect position, int value, int minValue, int maxValue)\n        {\n            Event evt = Event.current;\n\n            int id = GUIUtility.GetControlID(dragRectHash, FocusType.Passive, position);\n\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (position.Contains(evt.mousePosition) && evt.button == 0)\n                    {\n                        GUIUtility.hotControl = id;\n                        s_DragCandidateState = 1;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id && s_DragCandidateState != 0)\n                    {\n                        GUIUtility.hotControl = 0;\n                        s_DragCandidateState = 0;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        switch (s_DragCandidateState)\n                        {\n                            case 1:\n                                value += (int)(HandleUtility.niceMouseDelta * s_DragSensitivity);\n                                GUI.changed = true;\n                                evt.Use();\n\n                                if (value < minValue)\n                                    value = minValue;\n                                else if (value > maxValue)\n                                    value = maxValue;\n                                break;\n                        }\n                    }\n                    break;\n                case EventType.Repaint:\n                    EditorGUIUtility.AddCursorRect(position, MouseCursor.SlideArrow);\n                    break;\n            }\n\n            return value;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/EditorApplicationLayout.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing System.IO;\nusing UnityEditorInternal;\n\n// Description:\n// EditorApplicationLayout handles the GUI when playmode changes (on a high level).\n\n// When entering playmode the flow is as follows (also see Application::SetIsPlaying() for actual loading):\n// 1) Calling InitPlaymodeLayout prepares the main gameView WITHOUT rendering it. Sets it up, maximizes it if needed and intitializes its size.\n// 2) The current scene is loaded from Application.cp and initialized (Awake(), OnEnable(), Start() and first Update() is called (this takes time for large projects))\n// 3) Calling FinalizePlaymodeLayout finalizes and renders maximized window (if set).\n\n\nnamespace UnityEditor\n{\n    internal class EditorApplicationLayout\n    {\n        static private PlayModeView m_PlayModeView = null;\n        static private bool m_MaximizePending = false;\n\n\n        static internal bool IsInitializingPlaymodeLayout()\n        {\n            return m_PlayModeView != null;\n        }\n\n        [RequiredByNativeCode]\n        static internal void SetPlaymodeLayout()\n        {\n            InitPlaymodeLayout();\n            FinalizePlaymodeLayout();\n        }\n\n        [RequiredByNativeCode]\n        static internal void SetStopmodeLayout()\n        {\n            WindowLayout.ShowAppropriateViewOnEnterExitPlaymode(false);\n            Toolbar.RepaintToolbar();\n        }\n\n        [RequiredByNativeCode]\n        static internal void SetPausemodeLayout()\n        {\n            // We use the stopmode layout when pausing (maximized windows are unmaximized)\n            SetStopmodeLayout();\n        }\n\n        [RequiredByNativeCode]\n        static internal void InitPlaymodeLayout()\n        {\n            m_PlayModeView = WindowLayout.ShowAppropriateViewOnEnterExitPlaymode(true) as PlayModeView;\n            if (m_PlayModeView == null)\n                return;\n\n            if (m_PlayModeView.enterPlayModeBehavior == PlayModeView.EnterPlayModeBehavior.PlayMaximized)\n            {\n                if (m_PlayModeView.m_Parent is DockArea dockArea)\n                {\n                    m_MaximizePending = WindowLayout.MaximizePrepare(dockArea.actualView);\n\n                    var gameView = dockArea.actualView as GameView;\n                    if (gameView != null)\n                        m_PlayModeView.m_Parent.EnableVSync(gameView.vSyncEnabled);\n                }\n            }\n\n            // Mark this PlayModeView window as the start view so the backend\n            // can set size and mouseoffset properly for this view\n            m_PlayModeView.m_Parent.SetAsStartView();\n            m_PlayModeView.m_Parent.SetAsLastPlayModeView();\n\n            //GameView should be actively focussed If Playmode is entered in maximized state - case 1252097\n            if (m_PlayModeView.maximized)\n                m_PlayModeView.m_Parent.Focus();\n\n            Toolbar.RepaintToolbar();\n        }\n\n        [RequiredByNativeCode]\n        static internal void FinalizePlaymodeLayout()\n        {\n            if (m_PlayModeView != null)\n            {\n                if (m_MaximizePending)\n                    WindowLayout.MaximizePresent(m_PlayModeView);\n\n                m_PlayModeView.m_Parent.ClearStartView();\n            }\n\n            Clear();\n        }\n\n        static private void Clear()\n        {\n            m_MaximizePending = false;\n            m_PlayModeView = null;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/EditorCache.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing UnityEditor;\n\nnamespace UnityEditor\n{\n    [System.Flags]\n    internal enum EditorFeatures\n    {\n        None = 0,\n        PreviewGUI = 1,\n        OnSceneDrag = 4\n    }\n\n    internal class EditorWrapper : System.IDisposable\n    {\n        internal Editor editor;\n\n        public delegate void VoidDelegate(SceneView sceneView, int index);\n\n        public VoidDelegate OnSceneDrag;\n\n        public bool HasPreviewGUI() { return editor.HasPreviewGUI(); }\n        public void OnPreviewSettings() { editor.OnPreviewSettings(); }\n        public void OnPreviewGUI(Rect position, GUIStyle background) { editor.OnPreviewGUI(position, background); }\n        public void OnInteractivePreviewGUI(Rect r, GUIStyle background) { if (editor != null) editor.OnInteractivePreviewGUI(r, background); }\n        internal void OnAssetStoreInspectorGUI() { if (editor != null) editor.OnAssetStoreInspectorGUI(); }\n        public string GetInfoString() { return editor.GetInfoString(); }\n\n        private EditorWrapper() {}\n\n        static public EditorWrapper Make(Object obj, EditorFeatures requirements)\n        {\n            EditorWrapper cp = new EditorWrapper();\n            if (cp.Init(obj, requirements))\n                return cp;\n            else\n            {\n                cp.Dispose();\n                return null;\n            }\n        }\n\n        private bool Init(Object obj, EditorFeatures requirements)\n        {\n            editor = Editor.CreateEditor(obj);\n            if (editor == null)\n                return false;\n\n            if (requirements.HasFlag(EditorFeatures.PreviewGUI) && !editor.HasPreviewGUI())\n                return false;\n\n            const BindingFlags sceneDragReflectionFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;\n\n            var onSceneDragMethodInfo = editor.GetType().GetMethod(\"OnSceneDrag\", sceneDragReflectionFlags);\n\n            if (onSceneDragMethodInfo == null)\n            {\n                var nonRootEditor = RootEditorUtils.CreateNonRootEditor(new[] { obj });\n\n                // Are we dealing with a Root Editor?\n                if (editor.GetType() != nonRootEditor.GetType())\n                {\n                    // Destroy previous editor\n                    UnityEngine.Object.DestroyImmediate(editor);\n                    // Try again, with a non Root editor\n                    editor = nonRootEditor;\n                    onSceneDragMethodInfo = editor.GetType().GetMethod(\"OnSceneDrag\", sceneDragReflectionFlags);\n                }\n                else\n                {\n                    // Destroy unused non Root editor\n                    UnityEngine.Object.DestroyImmediate(nonRootEditor);\n                }\n            }\n\n            if (onSceneDragMethodInfo != null)\n                OnSceneDrag = (VoidDelegate)System.Delegate.CreateDelegate(typeof(VoidDelegate), editor, onSceneDragMethodInfo);\n            else if (requirements.HasFlag(EditorFeatures.OnSceneDrag))\n                return false;\n            else\n                OnSceneDrag = DefaultOnSceneDrag;\n\n            return true;\n        }\n\n        private void DefaultOnSceneDrag(SceneView sceneView, int index) {}\n\n        public string name\n        {\n            get { return editor.target.name; }\n        }\n\n        public void Dispose()\n        {\n            if (editor != null)\n            {\n                OnSceneDrag = null;\n\n                UnityEngine.Object.DestroyImmediate(editor);\n                editor = null;\n            }\n\n            System.GC.SuppressFinalize(this);\n        }\n\n        ~EditorWrapper()\n        {\n            Debug.LogError(\"Failed to dispose EditorWrapper.\");\n        }\n    }\n\n    internal class EditorCache : System.IDisposable\n    {\n        Dictionary<Object, EditorWrapper> m_EditorCache;\n        Dictionary<Object, bool> m_UsedEditors;\n        EditorFeatures m_Requirements;\n\n        public EditorCache() : this(EditorFeatures.None) {}\n\n\n        public EditorCache(EditorFeatures requirements)\n        {\n            m_Requirements = requirements;\n            m_EditorCache = new Dictionary<Object, EditorWrapper>();\n            m_UsedEditors = new Dictionary<Object, bool>();\n        }\n\n        public EditorWrapper this[Object o]\n        {\n            get\n            {\n                m_UsedEditors[o] = true;\n                if (m_EditorCache.ContainsKey(o))\n                    return m_EditorCache[o];\n\n                EditorWrapper w = EditorWrapper.Make(o, m_Requirements);\n                return m_EditorCache[o] = w;\n            }\n        }\n\n        public void CleanupUntouchedEditors()\n        {\n            if (m_EditorCache != null)\n            {\n                List<Object> toDelete = new List<Object>();\n                foreach (Object key in m_EditorCache.Keys)\n                {\n                    if (!m_UsedEditors.ContainsKey(key))\n                        toDelete.Add(key);\n                }\n\n                foreach (Object key in toDelete)\n                {\n                    EditorWrapper ew = m_EditorCache[key];\n                    m_EditorCache.Remove(key);\n\n                    if (ew == null)\n                        continue;\n                    ew.Dispose();\n                }\n            }\n\n            m_UsedEditors.Clear();\n        }\n\n        public void CleanupAllEditors()\n        {\n            m_UsedEditors.Clear();\n            CleanupUntouchedEditors();\n        }\n\n        public void Dispose()\n        {\n            CleanupAllEditors();\n            System.GC.SuppressFinalize(this);\n        }\n\n        ~EditorCache()\n        {\n            Debug.LogError(\"Failed to dispose EditorCache.\");\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/EditorGUIContents.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Reflection;\n\nnamespace UnityEditor\n{\n    public sealed partial class EditorGUI\n    {\n        // Common GUIContents used for EditorGUI controls.\n        internal sealed class GUIContents\n        {\n            // The settings dropdown icon top right in a component\n            [IconName(\"_Popup\")]\n            internal static GUIContent titleSettingsIcon { get; private set; }\n\n            // The help icon in a component\n            [IconName(\"_Help\")]\n            internal static GUIContent helpIcon  { get; private set; }\n\n            // We use a static constructor to lazily initialize all static properties. This is useful because changed image files can then\n            // be picked up on assembly reload.\n            static GUIContents()\n            {\n                // Run through each static property and initialize it using the\n                // filename provided in the IconName Attribute.\n                PropertyInfo[] propertyInfos = typeof(GUIContents).GetProperties(System.Reflection.BindingFlags.Static | BindingFlags.NonPublic);\n                foreach (PropertyInfo property in propertyInfos)\n                {\n                    IconName[] iconNames = (IconName[])property.GetCustomAttributes(typeof(IconName), false);\n                    if (iconNames.Length > 0)\n                    {\n                        string name = iconNames[0].name;\n                        GUIContent content = EditorGUIUtility.IconContent(name);\n                        property.SetValue(null, content, null);\n                    }\n                }\n            }\n\n            private class IconName : System.Attribute\n            {\n                private string m_Name;\n\n                public IconName(string name)\n                {\n                    this.m_Name = name;\n                }\n\n                public virtual string name\n                {\n                    get { return m_Name; }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/EditorGUIInternal.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    //@todo This should be handled through friend assemblies instead\n    internal sealed class EditorGUIInternal : GUI\n    {\n        // Choose how toggles appear when showing mixed values\n        static internal GUIStyle mixedToggleStyle\n        {\n            get { return s_MixedToggleStyle; }\n            set { s_MixedToggleStyle = value; }\n        }\n\n        private static GUIStyle s_MixedToggleStyle = EditorStyles.toggleMixed;\n\n        const float kExposureSliderAbsoluteMax = 23.0f;\n        static readonly GUIContent s_ExposureIcon = EditorGUIUtility.TrIconContent(\"Exposure\", \"Controls the number of stops to over or under expose the texture.\");\n\n        static internal Rect GetTooltipRect() { return tooltipRect; }\n        static internal string GetMouseTooltip() { return mouseTooltip; }\n        internal static bool DoToggleForward(Rect position, int id, bool value, GUIContent content, GUIStyle style, bool expandWidth = true)\n        {\n            Event evt = Event.current;\n\n            if (EditorGUI.showMixedValue)\n                style = mixedToggleStyle;\n\n            // Ignore mouse clicks that are not with the primary (left) mouse button so those can be grabbed by other things later.\n            EventType origType = evt.type;\n            bool nonLeftClick = (evt.type == EventType.MouseDown && evt.button != 0);\n            if (nonLeftClick)\n                evt.type = EventType.Ignore;\n            bool returnValue;\n            bool computedValue = EditorGUI.showMixedValue ? false : value;\n            if (expandWidth)\n            {\n                returnValue = DoToggle(position, id, computedValue, content, style);\n            }\n            else\n            {\n                var toggleSize = style.CalcSize(content);\n                var visibleRect = new Rect(position.position.x, position.position.y, toggleSize.x, position.height);\n                returnValue = DoToggle(visibleRect, id, computedValue, content, style);\n            }\n            if (nonLeftClick)\n                evt.type = origType;\n            else if (evt.type != origType)\n                EditorGUIUtility.keyboardControl = id; // If control used event, give it keyboard focus.\n            return returnValue;\n        }\n\n        internal static Vector2 DoBeginScrollViewForward(Rect position, Vector2 scrollPosition, Rect viewRect, bool alwaysShowHorizontal, bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background)\n        {\n            return DoBeginScrollView(position, scrollPosition, viewRect, alwaysShowHorizontal, alwaysShowVertical, horizontalScrollbar, verticalScrollbar, background);\n        }\n\n        internal static void BeginWindowsForward(int skinMode, int editorWindowInstanceID)\n        {\n            BeginWindows(skinMode, editorWindowInstanceID);\n        }\n\n        internal static void AssetPopup<T>(SerializedProperty serializedProperty, GUIContent content, string fileExtension) where T : Object, new()\n        {\n            AssetPopup<T>(serializedProperty, content, fileExtension, \"Default\");\n        }\n\n        internal static void AssetPopup<T>(SerializedProperty serializedProperty, GUIContent content, string fileExtension, string defaultFieldName) where T : Object, new()\n        {\n            AssetPopupBackend.AssetPopup<T>(serializedProperty, content, fileExtension, defaultFieldName);\n        }\n\n        internal static float ExposureSlider(float value, ref float maxValue, GUIStyle style)\n        {\n            float labelWidth = EditorGUIUtility.labelWidth;\n            EditorGUIUtility.labelWidth = 20;\n            value = EditorGUILayout.Slider(s_ExposureIcon, value, -maxValue, maxValue, -kExposureSliderAbsoluteMax, kExposureSliderAbsoluteMax, style, GUILayout.MaxWidth(64));\n\n            // This will allow the user to set a new max value for the current session\n            if (value >= 0)\n                maxValue = Mathf.Max(maxValue, value);\n            else\n                maxValue = Mathf.Max(maxValue, value * -1);\n\n            EditorGUIUtility.labelWidth = labelWidth;\n\n            return value;\n        }\n    }\n\n    //@todo This should be handled through friend assemblies instead\n    internal sealed class EditorGUILayoutUtilityInternal : GUILayoutUtility\n    {\n        internal new static GUILayoutGroup BeginLayoutArea(GUIStyle style, System.Type LayoutType)\n        {\n            return GUILayoutUtility.DoBeginLayoutArea(style, LayoutType);\n        }\n\n        internal new static GUILayoutGroup topLevel\n        {\n            get { return GUILayoutUtility.topLevel; }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/EditorStyles.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.Experimental;\nusing UnityEditor.StyleSheets;\nusing UnityEngine;\nusing UnityEngine.Internal;\n\n// See Style Guide in wiki for more information on editor styles.\n\nnamespace UnityEditor\n{\n    // Common GUIStyles used for EditorGUI controls.\n    public sealed class EditorStyles\n    {\n        internal const int kInspectorPaddingLeft = 8 + 10;\n        internal const int kInspectorPaddingRight = 4;\n        internal const int kInspectorPaddingTop = 4;\n\n        // Style used for the labeled on all EditorGUI overloads that take a prefix label\n        public static GUIStyle label { get { return s_Current.m_Label; } }\n        internal GUIStyle m_Label;\n\n        // Style for label with small font.\n        public static GUIStyle miniLabel { get { return s_Current.m_MiniLabel; } }\n        private GUIStyle m_MiniLabel;\n\n        // Style for label with large font.\n        public static GUIStyle largeLabel { get { return s_Current.m_LargeLabel; } }\n        private GUIStyle m_LargeLabel;\n\n        // Style for bold label.\n        public static GUIStyle boldLabel { get { return s_Current.m_BoldLabel; } }\n        private GUIStyle m_BoldLabel;\n\n        // Style for mini bold label.\n        public static GUIStyle miniBoldLabel { get { return s_Current.m_MiniBoldLabel; } }\n        private GUIStyle m_MiniBoldLabel;\n\n        // Style for centered grey mini label.\n        public static GUIStyle centeredGreyMiniLabel { get { return s_Current.m_CenteredGreyMiniLabel; } }\n        private GUIStyle m_CenteredGreyMiniLabel;\n\n        // Style for word wrapped mini label.\n        public static GUIStyle wordWrappedMiniLabel { get { return s_Current.m_WordWrappedMiniLabel; } }\n        private GUIStyle m_WordWrappedMiniLabel;\n\n        // Style for word wrapped label.\n        public static GUIStyle wordWrappedLabel { get { return s_Current.m_WordWrappedLabel; } }\n        private GUIStyle m_WordWrappedLabel;\n\n        // Style for link label.\n        public static GUIStyle linkLabel { get { return s_Current.m_LinkLabel; } }\n        private GUIStyle m_LinkLabel;\n\n        // Style for white label.\n        public static GUIStyle whiteLabel { get { return s_Current.m_WhiteLabel; } }\n        private GUIStyle m_WhiteLabel;\n\n        // Style for white mini label.\n        public static GUIStyle whiteMiniLabel { get { return s_Current.m_WhiteMiniLabel; } }\n        private GUIStyle m_WhiteMiniLabel;\n\n        // Style for white large label.\n        public static GUIStyle whiteLargeLabel { get { return s_Current.m_WhiteLargeLabel; } }\n        private GUIStyle m_WhiteLargeLabel;\n\n        // Style for white bold label.\n        public static GUIStyle whiteBoldLabel { get { return s_Current.m_WhiteBoldLabel; } }\n        private GUIStyle m_WhiteBoldLabel;\n\n        // Style used for a radio button\n        public static GUIStyle radioButton { get { return s_Current.m_RadioButton; } }\n        private GUIStyle m_RadioButton;\n\n        // Style used for a standalone small button.\n        public static GUIStyle miniButton { get { return s_Current.m_MiniButton; } }\n        private GUIStyle m_MiniButton;\n\n        // Style used for the leftmost button in a horizontal button group.\n        public static GUIStyle miniButtonLeft { get { return s_Current.m_MiniButtonLeft; } }\n        private GUIStyle m_MiniButtonLeft;\n\n        // Style used for the middle buttons in a horizontal group.\n        public static GUIStyle miniButtonMid { get { return s_Current.m_MiniButtonMid; } }\n        private GUIStyle m_MiniButtonMid;\n\n        // Style used for the rightmost button in a horizontal group.\n        public static GUIStyle miniButtonRight { get { return s_Current.m_MiniButtonRight; } }\n        private GUIStyle m_MiniButtonRight;\n\n        public static GUIStyle miniPullDown { get { return s_Current.m_MiniPullDown; } }\n        private GUIStyle m_MiniPullDown;\n\n        // Style used for EditorGUI::ref::TextField\n        public static GUIStyle textField  { get { return s_Current.m_TextField; } }\n        internal GUIStyle m_TextField;\n\n        // Style used for bold text field\n        internal static GUIStyle boldTextField { get { return s_Current.m_BoldTextField; } }\n        private GUIStyle m_BoldTextField;\n\n        // Style used for EditorGUI::ref::TextArea\n        public static GUIStyle textArea  { get { return s_Current.m_TextArea; } }\n        internal GUIStyle m_TextArea;\n\n        // Smaller text field\n        public static GUIStyle miniTextField  { get { return s_Current.m_MiniTextField; } }\n        private GUIStyle m_MiniTextField;\n\n        // Style used for field editors for numbers\n        public static GUIStyle numberField { get { return s_Current.m_NumberField; }  }\n        private GUIStyle m_NumberField;\n\n        // Style used for EditorGUI::ref::Popup, EditorGUI::ref::EnumPopup,\n        public static GUIStyle popup  { get { return s_Current.m_Popup; }  }\n        private GUIStyle m_Popup;\n\n        // Style used for headings for structures (Vector3, Rect, etc)\n        [System.Obsolete(\"structHeadingLabel is deprecated, use EditorStyles.label instead.\")]\n        public static GUIStyle structHeadingLabel  { get { return s_Current.m_Label; }  }\n\n        // Style used for headings for object fields.\n        public static GUIStyle objectField  { get { return s_Current.m_ObjectField; }  }\n        private GUIStyle m_ObjectField;\n\n        internal static GUIStyle objectFieldButton { get { return s_Current.m_ObjectFieldButton; } }\n        private GUIStyle m_ObjectFieldButton;\n\n        // Style used for headings for the Select button in object fields.\n        public static GUIStyle objectFieldThumb { get { return s_Current.m_ObjectFieldThumb; }  }\n        private GUIStyle m_ObjectFieldThumb;\n\n        // Style used for texture object field with minimal height (useful for single line texture objectfields)\n        public static GUIStyle objectFieldMiniThumb { get { return s_Current.m_ObjectFieldMiniThumb; } }\n        private GUIStyle m_ObjectFieldMiniThumb;\n\n        // Style used for headings for Color fields.\n        public static GUIStyle colorField { get { return s_Current.m_ColorField; }  }\n        private GUIStyle m_ColorField;\n\n        // Style used for headings for Layer masks.\n        public static GUIStyle layerMaskField { get { return s_Current.m_LayerMaskField; } }\n        private GUIStyle m_LayerMaskField;\n\n        // Style used for headings for EditorGUI::ref::Toggle.\n        public static GUIStyle toggle {get { return s_Current.m_Toggle; } }\n        private GUIStyle m_Toggle;\n\n        internal static GUIStyle toggleMixed { get { return s_Current.m_ToggleMixed; } }\n        private GUIStyle m_ToggleMixed;\n\n        // Style used for headings for EditorGUI::ref::Foldout.\n        public static GUIStyle foldout { get { return s_Current.m_Foldout; } }\n        private GUIStyle m_Foldout;\n\n        internal static GUIStyle titlebarFoldout { get { return s_Current.m_TitlebarFoldout; } }\n        private GUIStyle m_TitlebarFoldout;\n\n        // Style used for headings for EditorGUI::ref::Foldout.\n        public static GUIStyle foldoutPreDrop { get { return s_Current.m_FoldoutPreDrop; } }\n        private GUIStyle m_FoldoutPreDrop;\n\n        public static GUIStyle foldoutHeader { get { return s_Current.m_FoldoutHeader;} }\n        GUIStyle m_FoldoutHeader;\n\n        public static GUIStyle foldoutHeaderIcon { get { return s_Current.m_FoldoutHeaderIcon; } }\n        GUIStyle m_FoldoutHeaderIcon;\n\n        internal static GUIStyle optionsButtonStyle { get { return s_Current.m_OptionsButtonStyle; } }\n        GUIStyle m_OptionsButtonStyle;\n\n        // Style used for headings for EditorGUILayout::ref::BeginToggleGroup.\n        public static GUIStyle toggleGroup { get { return s_Current.m_ToggleGroup; }  }\n        private GUIStyle m_ToggleGroup;\n\n        internal static GUIStyle textFieldDropDown { get { return s_Current.m_TextFieldDropDown; } }\n        private GUIStyle m_TextFieldDropDown;\n\n        internal static GUIStyle textFieldDropDownText { get { return s_Current.m_TextFieldDropDownText; } }\n        private GUIStyle m_TextFieldDropDownText;\n\n        internal static GUIStyle overrideMargin { get { return s_Current.m_OverrideMargin; } }\n        private GUIStyle m_OverrideMargin;\n\n        // Standard font.\n        public static Font standardFont  => EditorResources.GetFont(FontDef.Style.Normal);\n\n        // Bold font.\n        public static Font boldFont => EditorResources.GetFont(FontDef.Style.Bold);\n\n        // Mini font.\n        public static Font miniFont => EditorResources.GetFont(FontDef.Style.Small);\n\n        // Mini Bold font.\n        public static Font miniBoldFont => EditorResources.GetFont(FontDef.Style.Bold);\n\n        // Toolbar background from top of windows.\n        public static GUIStyle toolbar { get { return s_Current.m_Toolbar; } }\n        private GUIStyle m_Toolbar;\n        internal static GUIStyle contentToolbar { get { return s_Current.m_ContentToolbar; } }\n        private GUIStyle m_ContentToolbar;\n\n        // Style for Button and Toggles in toolbars.\n        public static GUIStyle toolbarButton { get { return s_Current.m_ToolbarButton; } }\n        private GUIStyle m_ToolbarButton;\n        internal static GUIStyle toolbarButtonLeft { get { return s_Current.m_ToolbarButtonLeft; } }\n        private GUIStyle m_ToolbarButtonLeft;\n\n        internal static GUIStyle toolbarButtonRight { get { return s_Current.m_ToolbarButtonRight; } }\n        private GUIStyle m_ToolbarButtonRight;\n\n        // Toolbar Popup\n        public static GUIStyle toolbarPopup { get { return s_Current.m_ToolbarPopup; } }\n        private GUIStyle m_ToolbarPopup;\n\n        internal static GUIStyle toolbarPopupLeft { get { return s_Current.m_ToolbarPopupLeft; } }\n        private GUIStyle m_ToolbarPopupLeft;\n\n        internal static GUIStyle toolbarPopupRight { get { return s_Current.m_ToolbarPopupRight; } }\n        private GUIStyle m_ToolbarPopupRight;\n\n        internal static GUIStyle toolbarDropDownLeft { get { return s_Current.m_ToolbarDropDownLeft; } }\n        private GUIStyle m_ToolbarDropDownLeft;\n\n        public static GUIStyle toolbarDropDown { get { return s_Current.m_ToolbarDropDown; } }\n        private GUIStyle m_ToolbarDropDown;\n\n        // Toolbar Dropdown Right\n        internal static GUIStyle toolbarDropDownRight { get { return s_Current.m_ToolbarDropDownRight; } }\n        private GUIStyle m_ToolbarDropDownRight;\n\n        // Toolbar Dropdown Toggle\n        internal static GUIStyle toolbarDropDownToggle { get { return s_Current.m_ToolbarDropDownToggle; } }\n        private GUIStyle m_ToolbarDropDownToggle;\n\n        // Toolbar Dropdown Toggle Button\n        internal static GUIStyle toolbarDropDownToggleButton { get { return s_Current.m_ToolbarDropDownToggleButton; } }\n        private GUIStyle m_ToolbarDropDownToggleButton;\n\n        // Toolbar Dropdown Toggle Right\n        internal static GUIStyle toolbarDropDownToggleRight { get { return s_Current.m_ToolbarDropDownToggleRight; } }\n        private GUIStyle m_ToolbarDropDownToggleRight;\n\n        // Toolbar Dropdown\n        internal static GUIStyle toolbarCreateAddNewDropDown { get { return s_Current.m_ToolbarCreateAddNewDropDown; } }\n        private GUIStyle m_ToolbarCreateAddNewDropDown;\n\n        // Toolbar text field\n        public static GUIStyle toolbarTextField { get { return s_Current.m_ToolbarTextField; } }\n        private GUIStyle m_ToolbarTextField;\n\n        internal static GUIStyle toolbarLabel { get { return s_Current.m_ToolbarLabel; } }\n        private GUIStyle m_ToolbarLabel;\n\n        public static GUIStyle inspectorDefaultMargins { get { return s_Current.m_InspectorDefaultMargins; } }\n        private GUIStyle m_InspectorDefaultMargins;\n\n        internal static GUIStyle inspectorHorizontalDefaultMargins => s_Current.m_InspectorHorizontalDefaultMargins;\n        private GUIStyle m_InspectorHorizontalDefaultMargins;\n\n        public static GUIStyle inspectorFullWidthMargins { get { return s_Current.m_InspectorFullWidthMargins; } }\n        private GUIStyle m_InspectorFullWidthMargins;\n\n        internal static GUIStyle defaultContentMargins { get { return s_Current.m_DefaultContentMargins; } }\n        private GUIStyle m_DefaultContentMargins;\n\n        internal static GUIStyle frameBox => s_Current.m_FrameBox;\n        private GUIStyle m_FrameBox;\n\n        public static GUIStyle helpBox { get { return s_Current.m_HelpBox; } }\n        private GUIStyle m_HelpBox;\n\n        internal static GUIStyle helpBoxLabel {\n            get {\n                s_Current.m_HelpBoxLabel.Assign(s_Current.m_HelpBox);\n                s_Current.m_HelpBoxLabel.name = \"HelpBoxLabel\";\n                s_Current.m_HelpBoxLabel.normal.background = null;\n                s_Current.m_HelpBoxLabel.hover.background = null;\n                s_Current.m_HelpBoxLabel.active.background = null;\n                s_Current.m_HelpBoxLabel.focused.background = null;\n                s_Current.m_HelpBoxLabel.onNormal.background = null;\n                s_Current.m_HelpBoxLabel.onHover.background = null;\n                s_Current.m_HelpBoxLabel.onActive.background = null;\n                s_Current.m_HelpBoxLabel.onFocused.background = null;\n                return s_Current.m_HelpBoxLabel;\n            }\n        }\n        private GUIStyle m_HelpBoxLabel;\n\n        public static GUIStyle toolbarSearchField { get { return s_Current.m_ToolbarSearchField; } }\n        private GUIStyle m_ToolbarSearchField;\n\n        internal static GUIStyle toolbarSearchFieldPopup { get { return s_Current.m_ToolbarSearchFieldPopup; } }\n        private GUIStyle m_ToolbarSearchFieldPopup;\n\n        internal static GUIStyle toolbarSearchFieldWithJumpSynced { get { return s_Current.m_ToolbarSearchFieldWithJumpSynced; } }\n        private GUIStyle m_ToolbarSearchFieldWithJumpSynced;\n\n        internal static GUIStyle toolbarSearchFieldWithJumpPopupSynced { get { return s_Current.m_ToolbarSearchFieldWithJumpPopupSynced; } }\n        private GUIStyle m_ToolbarSearchFieldWithJumpPopupSynced;\n\n        internal static GUIStyle toolbarSearchFieldWithJump { get { return s_Current.m_ToolbarSearchFieldWithJump; } }\n        private GUIStyle m_ToolbarSearchFieldWithJump;\n\n        internal static GUIStyle toolbarSearchFieldWithJumpPopup { get { return s_Current.m_ToolbarSearchFieldWithJumpPopup; } }\n        private GUIStyle m_ToolbarSearchFieldWithJumpPopup;\n\n        internal static GUIStyle toolbarSearchFieldJumpButton { get { return s_Current.m_ToolbarSearchFieldJumpButton; } }\n        private GUIStyle m_ToolbarSearchFieldJumpButton;\n\n        internal static GUIStyle toolbarSearchFieldCancelButton { get { return s_Current.m_ToolbarSearchFieldCancelButton; } }\n        private GUIStyle m_ToolbarSearchFieldCancelButton;\n\n        internal static GUIStyle toolbarSearchFieldCancelButtonEmpty { get { return s_Current.m_ToolbarSearchFieldCancelButtonEmpty; } }\n        private GUIStyle m_ToolbarSearchFieldCancelButtonEmpty;\n\n        internal static GUIStyle toolbarSearchFieldCancelButtonWithJump { get { return s_Current.m_ToolbarSearchFieldCancelButtonWithJump; } }\n        private GUIStyle m_ToolbarSearchFieldCancelButtonWithJump;\n\n        internal static GUIStyle toolbarSearchFieldCancelButtonWithJumpEmpty { get { return s_Current.m_ToolbarSearchFieldCancelButtonWithJumpEmpty; } }\n        private GUIStyle m_ToolbarSearchFieldCancelButtonWithJumpEmpty;\n\n        internal static GUIStyle colorPickerBox { get { return s_Current.m_ColorPickerBox; } }\n        private GUIStyle m_ColorPickerBox;\n\n        internal static GUIStyle viewBackground { get { return s_Current.m_ViewBg; } }\n        private GUIStyle m_ViewBg;\n\n        internal static GUIStyle inspectorBig { get { return s_Current.m_InspectorBig; } }\n        private GUIStyle m_InspectorBig;\n\n        internal static GUIStyle inspectorTitlebar { get { return s_Current.m_InspectorTitlebar; } }\n        private GUIStyle m_InspectorTitlebar;\n\n        internal static GUIStyle inspectorTitlebarFlat { get { return s_Current.m_InspectorTitlebarFlat; } }\n        private GUIStyle m_InspectorTitlebarFlat;\n\n        internal static GUIStyle inspectorTitlebarText { get { return s_Current.m_InspectorTitlebarText; } }\n        private GUIStyle m_InspectorTitlebarText;\n\n        internal static GUIStyle foldoutSelected { get { return s_Current.m_FoldoutSelected; } }\n        private GUIStyle m_FoldoutSelected;\n\n        // Style used for a standalone icon button\n        public static GUIStyle iconButton { get { return s_Current.m_IconButton; } }\n        private GUIStyle m_IconButton;\n\n        // Style for tooltips\n        internal static GUIStyle tooltip { get { return s_Current.m_Tooltip; } }\n        private GUIStyle m_Tooltip;\n\n        // Style for notification text.\n        internal static GUIStyle notificationText { get { return s_Current.m_NotificationText; } }\n        private GUIStyle m_NotificationText;\n\n        // Style for notification background area.\n        internal static GUIStyle notificationBackground { get { return s_Current.m_NotificationBackground; } }\n        private GUIStyle m_NotificationBackground;\n\n        internal static GUIStyle assetLabel { get { return s_Current.m_AssetLabel; } }\n        private GUIStyle m_AssetLabel;\n\n        internal static GUIStyle assetLabelPartial { get { return s_Current.m_AssetLabelPartial; } }\n        private GUIStyle m_AssetLabelPartial;\n\n        internal static GUIStyle assetLabelIcon { get { return s_Current.m_AssetLabelIcon; } }\n        private GUIStyle m_AssetLabelIcon;\n\n        internal static GUIStyle searchField { get { return s_Current.m_SearchField; } }\n        private GUIStyle m_SearchField;\n\n        internal static GUIStyle searchFieldCancelButton { get { return s_Current.m_SearchFieldCancelButton; } }\n        private GUIStyle m_SearchFieldCancelButton;\n\n        internal static GUIStyle searchFieldCancelButtonEmpty { get { return s_Current.m_SearchFieldCancelButtonEmpty; } }\n        private GUIStyle m_SearchFieldCancelButtonEmpty;\n\n        public static GUIStyle selectionRect { get { return s_Current.m_SelectionRect; } }\n        private GUIStyle m_SelectionRect;\n\n        internal static GUIStyle toolbarSlider { get { return s_Current.m_ToolbarSlider; } }\n        private GUIStyle m_ToolbarSlider;\n\n        internal static GUIStyle minMaxHorizontalSliderThumb { get { return s_Current.m_MinMaxHorizontalSliderThumb; } }\n        private GUIStyle m_MinMaxHorizontalSliderThumb;\n\n        internal static GUIStyle dropDownList { get { return s_Current.m_DropDownList; } }\n        private GUIStyle m_DropDownList;\n\n        internal static GUIStyle dropDownToggleButton { get { return s_Current.m_DropDownToggleButton; } }\n        private GUIStyle m_DropDownToggleButton;\n        internal static GUIStyle minMaxStateDropdown { get { return s_Current.m_MinMaxStateDropdown; } }\n        private GUIStyle m_MinMaxStateDropdown;\n\n        internal static GUIStyle progressBarBack { get { return s_Current.m_ProgressBarBack; } }\n        internal static GUIStyle progressBarBar { get { return s_Current.m_ProgressBarBar; } }\n        internal static GUIStyle progressBarText { get { return s_Current.m_ProgressBarText; } }\n        private GUIStyle m_ProgressBarBar, m_ProgressBarText, m_ProgressBarBack;\n\n        internal static GUIStyle scrollViewAlt { get { return s_Current.m_ScrollViewAlt; } }\n        private GUIStyle m_ScrollViewAlt;\n\n        internal static Vector2 knobSize {get {return s_Current.m_KnobSize; }}\n        internal static Vector2 miniKnobSize {get {return s_Current.m_MiniKnobSize; }}\n        private Vector2 m_KnobSize = new Vector2(40, 40);\n        private Vector2 m_MiniKnobSize = new Vector2(29, 29);\n\n        // the editor styles currently in use\n        internal static EditorStyles s_Current;\n\n        // the list of editor styles to use\n        private static EditorStyles[] s_CachedStyles = { null, null };\n\n        [ExcludeFromDocs]\n        public static GUIStyle FromUSS(string ussStyleRuleName, string ussInPlaceStyleOverride = null)\n        {\n            return GUIStyleExtensions.FromUSS(ussStyleRuleName, ussInPlaceStyleOverride);\n        }\n\n        [ExcludeFromDocs]\n        public static GUIStyle FromUSS(GUIStyle baseStyle, string ussStyleRuleName, string ussInPlaceStyleOverride = null)\n        {\n            return GUIStyleExtensions.FromUSS(baseStyle, ussStyleRuleName, ussInPlaceStyleOverride);\n        }\n\n        [ExcludeFromDocs]\n        public static GUIStyle ApplyUSS(GUIStyle style, string ussStyleRuleName, string ussInPlaceStyleOverride = null)\n        {\n            return GUIStyleExtensions.ApplyUSS(style, ussStyleRuleName, ussInPlaceStyleOverride);\n        }\n\n        internal static void UpdateSkinCache()\n        {\n            UpdateSkinCache(EditorGUIUtility.skinIndex);\n        }\n\n        internal static void UpdateSkinCache(int skinIndex)\n        {\n            // Don't cache the Game GUISkin styles\n            if (GUIUtility.s_SkinMode == 0)\n                return;\n\n            if (s_CachedStyles[skinIndex] == null)\n            {\n                EditorResources.RefreshSkin();\n\n                s_CachedStyles[skinIndex] = new EditorStyles();\n                s_CachedStyles[skinIndex].InitSharedStyles();\n            }\n\n            s_Current = s_CachedStyles[skinIndex];\n            EditorGUIUtility.s_FontIsBold = -1;\n            EditorGUIUtility.SetBoldDefaultFont(false);\n        }\n\n        private void InitSharedStyles()\n        {\n            m_ColorPickerBox = GetStyle(\"ColorPickerBox\");\n            m_ViewBg = GetStyle(\"TabWindowBackground\");\n\n            m_InspectorBig = GetStyle(\"In BigTitle\");\n            m_MiniLabel = GetStyle(\"MiniLabel\");\n            m_LargeLabel = GetStyle(\"LargeLabel\");\n            m_BoldLabel = GetStyle(\"BoldLabel\");\n            m_MiniBoldLabel = GetStyle(\"MiniBoldLabel\");\n            m_WordWrappedLabel = GetStyle(\"WordWrappedLabel\");\n            m_WordWrappedMiniLabel = GetStyle(\"WordWrappedMiniLabel\");\n            m_WhiteLabel = GetStyle(\"WhiteLabel\");\n            m_WhiteMiniLabel = GetStyle(\"WhiteMiniLabel\");\n            m_WhiteLargeLabel = GetStyle(\"WhiteLargeLabel\");\n            m_WhiteBoldLabel = GetStyle(\"WhiteBoldLabel\");\n            m_MiniTextField = GetStyle(\"MiniTextField\");\n            m_RadioButton = GetStyle(\"Radio\");\n            m_MiniButton = GetStyle(\"miniButton\");\n            m_MiniButtonLeft = GetStyle(\"miniButtonLeft\");\n            m_MiniButtonMid = GetStyle(\"miniButtonMid\");\n            m_MiniButtonRight = GetStyle(\"miniButtonRight\");\n            m_MiniPullDown = GetStyle(\"MiniPullDown\");\n            m_Toolbar = GetStyle(\"toolbar\");\n            m_ContentToolbar = GetStyle(\"contentToolbar\");\n            m_ToolbarButton = GetStyle(\"toolbarbutton\");\n            m_ToolbarButtonLeft = GetStyle(\"toolbarbuttonLeft\");\n            m_ToolbarButtonRight = GetStyle(\"toolbarbuttonRight\");\n            m_ToolbarPopup = GetStyle(\"toolbarPopup\");\n            m_ToolbarPopupLeft = GetStyle(\"toolbarPopupLeft\");\n            m_ToolbarPopupRight = GetStyle(\"toolbarPopupRight\");\n            m_ToolbarDropDown = GetStyle(\"toolbarDropDown\");\n            m_ToolbarDropDownLeft = GetStyle(\"toolbarDropDownLeft\");\n            m_ToolbarDropDownRight = GetStyle(\"toolbarDropDownRight\");\n            m_ToolbarDropDownToggle = GetStyle(\"toolbarDropDownToggle\");\n            m_ToolbarDropDownToggleButton = GetStyle(\"ToolbarDropDownToggleButton\");\n            m_ToolbarDropDownToggleRight = GetStyle(\"toolbarDropDownToggleRight\");\n            m_ToolbarCreateAddNewDropDown = GetStyle(\"ToolbarCreateAddNewDropDown\");\n            m_ToolbarTextField = GetStyle(\"toolbarTextField\");\n            m_ToolbarLabel = GetStyle(\"ToolbarLabel\");\n            m_ToolbarSearchField = GetStyle(\"ToolbarSearchTextField\");\n            m_ToolbarSearchFieldPopup = GetStyle(\"ToolbarSearchTextFieldPopup\");\n            m_ToolbarSearchFieldWithJump = GetStyle(\"ToolbarSearchTextFieldWithJump\");\n            m_ToolbarSearchFieldWithJumpPopup = GetStyle(\"ToolbarSearchTextFieldWithJumpPopup\");\n            m_ToolbarSearchFieldJumpButton = GetStyle(\"ToolbarSearchTextFieldJumpButton\");\n            m_ToolbarSearchFieldCancelButton = GetStyle(\"ToolbarSearchCancelButton\");\n            m_ToolbarSearchFieldCancelButtonEmpty = GetStyle(\"ToolbarSearchCancelButtonEmpty\");\n            m_ToolbarSearchFieldCancelButtonWithJump = GetStyle(\"ToolbarSearchCancelButtonWithJump\");\n            m_ToolbarSearchFieldCancelButtonWithJumpEmpty = GetStyle(\"ToolbarSearchCancelButtonWithJumpEmpty\");\n            m_ToolbarSearchFieldWithJumpSynced = GetStyle(\"ToolbarSearchTextFieldWithJumpSynced\");\n            m_ToolbarSearchFieldWithJumpPopupSynced = GetStyle(\"ToolbarSearchTextFieldWithJumpPopupSynced\");\n            m_SearchField = GetStyle(\"SearchTextField\");\n            m_SearchFieldCancelButton = GetStyle(\"SearchCancelButton\");\n            m_SearchFieldCancelButtonEmpty = GetStyle(\"SearchCancelButtonEmpty\");\n            m_HelpBox = GetStyle(\"HelpBox\");\n            m_FrameBox = GetStyle(\"FrameBox\");\n            m_AssetLabel = GetStyle(\"AssetLabel\");\n            m_AssetLabelPartial = GetStyle(\"AssetLabel Partial\");\n            m_AssetLabelIcon = GetStyle(\"AssetLabel Icon\");\n            m_SelectionRect = GetStyle(\"selectionRect\");\n            m_ToolbarSlider = GetStyle(\"ToolbarSlider\");\n            m_MinMaxHorizontalSliderThumb = GetStyle(\"MinMaxHorizontalSliderThumb\");\n            m_DropDownList = GetStyle(\"DropDownButton\");\n            m_DropDownToggleButton = GetStyle(\"DropDownToggleButton\");\n            m_MinMaxStateDropdown = GetStyle(\"IN MinMaxStateDropdown\");\n            m_ProgressBarBack = GetStyle(\"ProgressBarBack\");\n            m_ProgressBarBar = GetStyle(\"ProgressBarBar\");\n            m_ProgressBarText = GetStyle(\"ProgressBarText\");\n            m_FoldoutPreDrop = GetStyle(\"FoldoutPreDrop\");\n            m_FoldoutHeader = GetStyle(\"FoldoutHeader\");\n            m_FoldoutHeaderIcon = GetStyle(\"FoldoutHeaderIcon\");\n            m_OptionsButtonStyle = GetStyle(\"PaneOptions\");\n            m_InspectorTitlebar = GetStyle(\"IN Title\");\n            m_InspectorTitlebarFlat = GetStyle(\"IN Title Flat\");\n            m_InspectorTitlebarText = GetStyle(\"IN TitleText\");\n            m_ToggleGroup = GetStyle(\"BoldToggle\");\n            m_Tooltip = GetStyle(\"Tooltip\");\n            m_NotificationText = GetStyle(\"NotificationText\");\n            m_NotificationBackground = GetStyle(\"NotificationBackground\");\n            m_ScrollViewAlt = GetStyle(\"ScrollViewAlt\");\n\n            // Former LookLikeControls styles\n            m_Popup = m_LayerMaskField = GetStyle(\"MiniPopup\");\n            m_TextField = m_NumberField = GetStyle(\"TextField\");\n            m_BoldTextField = GetStyle(\"BoldTextFIeld\");\n            m_Label = GetStyle(\"ControlLabel\");\n            m_ObjectField = GetStyle(\"ObjectField\");\n            m_ObjectFieldThumb = GetStyle(\"ObjectFieldThumb\");\n            m_ObjectFieldButton = GetStyle(\"ObjectFieldButton\");\n            m_ObjectFieldMiniThumb = GetStyle(\"ObjectFieldMiniThumb\");\n            m_Toggle = GetStyle(\"Toggle\");\n            m_ToggleMixed = GetStyle(\"ToggleMixed\");\n            m_ColorField = GetStyle(\"ColorField\");\n            m_Foldout = GetStyle(\"Foldout\");\n            m_TitlebarFoldout = GetStyle(\"Titlebar Foldout\");\n            m_FoldoutSelected = GUIStyle.none;\n            m_IconButton = GetStyle(\"IconButton\");\n            m_TextFieldDropDown = GetStyle(\"TextFieldDropDown\");\n            m_TextFieldDropDownText = GetStyle(\"TextFieldDropDownText\");\n\n            m_OverrideMargin = GetStyle(\"OverrideMargin\");\n            m_LinkLabel = GetStyle(\"LinkLabel\");\n\n            // Match selection color which works nicely for both light and dark skins\n\n            m_TextArea = new GUIStyle(m_TextField) {wordWrap = true};\n\n            m_InspectorDefaultMargins = new GUIStyle\n            {\n                padding = new RectOffset(kInspectorPaddingLeft, kInspectorPaddingRight, kInspectorPaddingTop, 0)\n            };\n\n            m_InspectorHorizontalDefaultMargins = new GUIStyle\n            {\n                padding = new RectOffset(kInspectorPaddingLeft, kInspectorPaddingRight, 0, 0)\n            };\n\n            // For the full width margins, use padding from right side in both sides,\n            // though adjust for overdraw by adding one in left side to get even margins.\n            m_InspectorFullWidthMargins = new GUIStyle\n            {\n                padding = new RectOffset(kInspectorPaddingRight + 1, kInspectorPaddingRight, 0, 0)\n            };\n\n            m_DefaultContentMargins = new GUIStyle\n            {\n                padding = new RectOffset(4, 4, 4, 4)\n            };\n\n            // Derive centered grey mini label from base minilabel\n            m_CenteredGreyMiniLabel = new GUIStyle(m_MiniLabel)\n            {\n                alignment = TextAnchor.MiddleCenter,\n                normal = {textColor = Color.grey},\n                hover = { textColor = Color.grey },\n                active = { textColor = Color.grey},\n                focused = { textColor = Color.grey }\n            };\n\n            m_HelpBoxLabel = new GUIStyle(m_HelpBox)\n            {\n                name = \"HelpBoxLabel\"\n            };\n        }\n\n        internal GUIStyle GetStyle(string styleName)\n        {\n            GUIStyle s = GUI.skin.FindStyle(styleName) ?? EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).FindStyle(styleName);\n            if (s == null)\n            {\n                Debug.LogError(\"Missing built-in guistyle \" + styleName);\n                s = GUISkin.error;\n            }\n            return s;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/EditorUpdateWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing System.Collections;\nusing UnityEditor;\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    internal class EditorUpdateWindow : EditorWindow\n    {\n        [RequiredByNativeCode]\n        static void ShowEditorErrorWindow(string errorString)\n        {\n            LoadResources();\n\n            EditorUpdateWindow w = ShowWindow();\n\n            w.s_ErrorString = errorString;\n            w.s_HasConnectionError = true;\n            w.s_HasUpdate = false;\n        }\n\n        [RequiredByNativeCode]\n        static void ShowEditorUpdateWindow(string latestVersionString, string latestVersionMessage, string updateURL)\n        {\n            LoadResources();\n\n            EditorUpdateWindow w = ShowWindow();\n\n            w.s_LatestVersionString = latestVersionString;\n            w.s_LatestVersionMessage = latestVersionMessage;\n            w.s_UpdateURL = updateURL;\n            w.s_HasConnectionError = false;\n            w.s_HasUpdate = updateURL.Length > 0;\n        }\n\n        private static EditorUpdateWindow ShowWindow()\n        {\n            return EditorWindow.GetWindowWithRect(typeof(EditorUpdateWindow), new Rect(100, 100, 570, 400), true, s_Title.text) as EditorUpdateWindow;\n        }\n\n        private static GUIContent s_UnityLogo;\n        private static GUIContent s_Title;\n        private static GUIContent s_TextHasUpdate, s_TextUpToDate;\n        private static GUIContent s_CheckForNewUpdatesText;\n\n        [SerializeField]\n        private string s_ErrorString;\n\n        [SerializeField]\n        private string s_LatestVersionString;\n\n        [SerializeField]\n        private string s_LatestVersionMessage;\n\n        [SerializeField]\n        private string s_UpdateURL;\n\n        [SerializeField]\n        private bool s_HasUpdate;\n\n        [SerializeField]\n        private bool s_HasConnectionError;\n\n        private static bool s_ShowAtStartup;\n        private Vector2 m_ScrollPos;\n\n        private static void LoadResources()\n        {\n            if (s_UnityLogo != null)\n                return;\n\n            s_ShowAtStartup = EditorPrefs.GetBool(\"EditorUpdateShowAtStartup\", true);\n\n            s_Title = EditorGUIUtility.TrTextContent(\"Unity Editor Update Check\");\n\n            s_UnityLogo = EditorGUIUtility.IconContent(\"UnityLogo\");\n            s_TextHasUpdate = EditorGUIUtility.TrTextContent(\"There is a new version of the Unity Editor available for download.\\n\\nCurrently installed version is {0}\\nNew version is {1}\");\n            s_TextUpToDate = EditorGUIUtility.TrTextContent(\"The Unity Editor is up to date. Currently installed version is {0}\");\n\n            s_CheckForNewUpdatesText = EditorGUIUtility.TrTextContent(\"Check for Updates\");\n        }\n\n        public void OnGUI()\n        {\n            LoadResources();\n\n\n            GUILayout.BeginVertical();\n            GUILayout.Space(10);\n            GUI.Box(new Rect(13, 8, s_UnityLogo.image.width, s_UnityLogo.image.height), s_UnityLogo, GUIStyle.none);\n            GUILayout.Space(5);\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(120);\n            GUILayout.BeginVertical();\n\n            if (s_HasConnectionError)\n            {\n                GUILayout.Label(s_ErrorString, \"WordWrappedLabel\", GUILayout.Width(405));\n            }\n            else if (s_HasUpdate)\n            {\n                GUILayout.Label(string.Format(s_TextHasUpdate.text, InternalEditorUtility.GetFullUnityVersion(), s_LatestVersionString), \"WordWrappedLabel\", GUILayout.Width(300));\n\n                GUILayout.Space(20);\n                m_ScrollPos = EditorGUILayout.BeginScrollView(m_ScrollPos, GUILayout.Width(405), GUILayout.Height(200));\n                GUILayout.Label(s_LatestVersionMessage, \"WordWrappedLabel\");\n                EditorGUILayout.EndScrollView();\n\n                GUILayout.Space(20);\n                GUILayout.BeginHorizontal();\n                if (GUILayout.Button(\"Download new version\", GUILayout.Width(200)))\n                    Help.BrowseURL(s_UpdateURL);\n\n                if (GUILayout.Button(\"Skip new version\", GUILayout.Width(200)))\n                {\n                    EditorPrefs.SetString(\"EditorUpdateSkipVersionString\", s_LatestVersionString);\n                    Close();\n                }\n                GUILayout.EndHorizontal();\n            }\n            else\n            {\n                GUILayout.Label(string.Format(s_TextUpToDate.text, Application.unityVersion), \"WordWrappedLabel\", GUILayout.Width(405));\n            }\n\n\n            GUILayout.EndVertical();\n            GUILayout.EndHorizontal();\n\n            GUILayout.Space(8);\n\n\n            GUILayout.FlexibleSpace();\n            GUILayout.BeginHorizontal(GUILayout.Height(20));\n            GUILayout.FlexibleSpace();\n            GUI.changed = false;\n            s_ShowAtStartup = GUILayout.Toggle(s_ShowAtStartup, s_CheckForNewUpdatesText);\n            if (GUI.changed)\n                EditorPrefs.SetBool(\"EditorUpdateShowAtStartup\", s_ShowAtStartup);\n\n            GUILayout.Space(10);\n            GUILayout.EndHorizontal();\n            GUILayout.EndVertical();\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/ExposablePopupMenu.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.IO;\n\nusing UnityEditorInternal;\nusing UnityEngine;\n\n\nnamespace UnityEditor\n{\n    internal class ExposablePopupMenu\n    {\n        public class ItemData\n        {\n            public ItemData(GUIContent content, GUIStyle style, bool on, bool enabled, object userData)\n            {\n                m_GUIContent = content;\n                m_Style = style;\n                m_On = on;\n                m_Enabled = enabled;\n                m_UserData = userData;\n            }\n\n            public GUIContent m_GUIContent;\n            public GUIStyle m_Style;\n            public bool m_On;\n            public bool m_Enabled;\n            public object m_UserData;\n            public float m_Width;\n            public float m_Height;\n        }\n\n        public class PopupButtonData\n        {\n            public PopupButtonData(GUIContent content, GUIStyle style)\n            {\n                m_GUIContent = content;\n                m_Style = style;\n            }\n\n            public GUIContent m_GUIContent;\n            public GUIStyle m_Style;\n        }\n\n        List<ItemData> m_Items;\n\n        float m_ItemSpacing;\n        PopupButtonData m_PopupButtonData;\n        GUIContent m_Label;\n\n        int[] m_ItemControlIDs;\n        int m_DropDownButtonControlID;\n        static readonly int s_ItemHash = \"ItemButton\".GetHashCode();\n        static readonly int m_DropDownButtonHash = \"DropDownButton\".GetHashCode();\n\n        float m_SpacingLabelToButton = 5f;\n        float m_WidthOfLabel;\n        float m_WidthOfButtons;\n        float m_MinWidthOfPopup;\n        Vector2 m_PopupButtonSize = Vector2.zero;\n        System.Action<ItemData> m_SelectionChangedCallback = null; // <userData>\n\n        public float widthOfButtonsAndLabel {  get { return m_WidthOfButtons + labelAndSpacingWidth; } }\n        public float widthOfPopupAndLabel { get { return m_PopupButtonSize.x + labelAndSpacingWidth; } }\n        public bool rightAligned { get; set; }\n        float labelAndSpacingWidth { get { return m_WidthOfLabel > 0 ? m_WidthOfLabel + m_SpacingLabelToButton : 0f; } }\n        bool hasLabel { get { return m_Label != null && m_Label != GUIContent.none;  } }\n\n        public void Init(List<ItemData> items, float itemSpacing, float minWidthOfPopup, PopupButtonData popupButtonData, System.Action<ItemData> selectionChangedCallback)\n        {\n            Init(GUIContent.none, items, itemSpacing, minWidthOfPopup, popupButtonData, selectionChangedCallback);\n        }\n\n        public void Init(GUIContent label, List<ItemData> items, float itemSpacing, float minWidthOfPopup, PopupButtonData popupButtonData,  System.Action<ItemData> selectionChangedCallback)\n        {\n            m_Label = label;\n            m_Items = items;\n            m_ItemSpacing = itemSpacing;\n            m_PopupButtonData = popupButtonData;\n            m_SelectionChangedCallback = selectionChangedCallback;\n            m_MinWidthOfPopup = minWidthOfPopup;\n            CalcWidths();\n        }\n\n        public float OnGUI(Rect rect)\n        {\n            // To ensure we allocate a consistent amount of controlIDs on every OnGUI we preallocate before any logic\n            if (m_Items.Count > 0 && (m_ItemControlIDs == null || m_ItemControlIDs.Length != m_Items.Count))\n                m_ItemControlIDs = new int[m_Items.Count];\n            for (int i = 0; i < m_Items.Count; ++i)\n                m_ItemControlIDs[i] = GUIUtility.GetControlID(s_ItemHash, FocusType.Passive);\n            m_DropDownButtonControlID = GUIUtility.GetControlID(m_DropDownButtonHash, FocusType.Passive);\n\n            if (rect.width >= widthOfButtonsAndLabel && rect.width > m_MinWidthOfPopup)\n            {\n                // Show as buttons\n\n                if (hasLabel)\n                {\n                    Rect labelRect = rect;\n                    labelRect.width = m_WidthOfLabel;\n                    if (rightAligned)\n                        labelRect.x = rect.xMax - widthOfButtonsAndLabel;\n\n                    GUI.Label(labelRect, m_Label, EditorStyles.boldLabel);\n                    rect.xMin += (m_WidthOfLabel + m_SpacingLabelToButton);\n                }\n\n                Rect buttonRect = rect;\n                buttonRect.width = widthOfButtonsAndLabel;\n                if (rightAligned)\n                    buttonRect.x = rect.xMax - m_WidthOfButtons;\n\n                for (int i = 0; i < m_Items.Count; ++i)\n                {\n                    var item = m_Items[i];\n                    buttonRect.width = item.m_Width;\n                    buttonRect.y = rect.y + (rect.height - item.m_Height) / 2;\n                    buttonRect.height = item.m_Height;\n\n                    EditorGUI.BeginChangeCheck();\n\n                    using (new EditorGUI.DisabledScope(!item.m_Enabled))\n                    {\n                        GUI.Toggle(buttonRect, m_ItemControlIDs[i], item.m_On, item.m_GUIContent, item.m_Style);\n                    }\n\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        SelectionChanged(item);\n                        GUIUtility.ExitGUI(); // To make sure we can survive if m_Buttons are reallocated in the callback we exit gui\n                    }\n\n                    buttonRect.x += item.m_Width + m_ItemSpacing;\n                }\n\n                return widthOfButtonsAndLabel;\n            }\n            else\n            {\n                // Show as popup\n\n                var dropDownRect = rect;\n                if (hasLabel)\n                {\n                    Rect labelRect = dropDownRect;\n                    labelRect.width = m_WidthOfLabel;\n                    if (rightAligned)\n                        labelRect.x = rect.xMax - widthOfPopupAndLabel;\n\n                    GUI.Label(labelRect, m_Label, EditorStyles.boldLabel);\n                    dropDownRect.x = labelRect.x + (m_WidthOfLabel + m_SpacingLabelToButton);\n                }\n                else\n                {\n                    if (rightAligned)\n                        dropDownRect.x = rect.xMax - dropDownRect.width;\n                }\n\n                dropDownRect.width = Mathf.Clamp(dropDownRect.width, 0, m_PopupButtonSize.x);\n                dropDownRect.height = m_PopupButtonSize.y;\n                dropDownRect.y = rect.y + (rect.height - dropDownRect.height) / 2;\n\n                if (EditorGUI.DropdownButton(m_DropDownButtonControlID, dropDownRect, m_PopupButtonData.m_GUIContent, m_PopupButtonData.m_Style))\n                    PopUpMenu.Show(dropDownRect, m_Items, this);\n\n                return widthOfPopupAndLabel;\n            }\n        }\n\n        void CalcWidths()\n        {\n            // Buttons\n            m_WidthOfButtons = 0f;\n            foreach (var item in m_Items)\n            {\n                var itemSize = item.m_Style.CalcSize(item.m_GUIContent);\n                item.m_Width = itemSize.x;\n                item.m_Height = itemSize.y;\n\n                m_WidthOfButtons += item.m_Width;\n            }\n            m_WidthOfButtons += (m_Items.Count - 1) * m_ItemSpacing;\n\n            // Popup\n            m_PopupButtonSize = m_PopupButtonData.m_Style.CalcSize(m_PopupButtonData.m_GUIContent);\n\n            // Label\n            m_WidthOfLabel = hasLabel ? EditorStyles.boldLabel.CalcSize(m_Label).x : 0;\n        }\n\n        void SelectionChanged(ItemData item)\n        {\n            if (m_SelectionChangedCallback != null)\n                m_SelectionChangedCallback(item);\n            else\n                Debug.LogError(\"Callback is null\");\n        }\n\n        internal class PopUpMenu\n        {\n            static List<ItemData> m_Data;\n            static ExposablePopupMenu m_Caller;\n\n            static internal void Show(Rect activatorRect, List<ItemData> buttonData, ExposablePopupMenu caller)\n            {\n                m_Data = buttonData;\n                m_Caller = caller;\n\n                GenericMenu menu = new GenericMenu();\n                foreach (ItemData item in m_Data)\n                    if (item.m_Enabled)\n                        menu.AddItem(item.m_GUIContent, item.m_On, SelectionCallback, item);\n                    else\n                        menu.AddDisabledItem(item.m_GUIContent);\n\n                menu.DropDown(activatorRect);\n            }\n\n            static void SelectionCallback(object userData)\n            {\n                ItemData item = (ItemData)userData;\n                m_Caller.SelectionChanged(item);\n\n                // Cleanup\n                m_Caller = null;\n                m_Data = null;\n            }\n        }\n    }\n} // end namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/FallbackEditorWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Reflection;\n\nnamespace UnityEditor\n{\n    internal class FallbackEditorWindow : EditorWindow\n    {\n        FallbackEditorWindow()\n        {\n        }\n\n        void OnEnable()\n        {\n            titleContent = EditorGUIUtility.TrTextContent(\"Failed to load\");\n        }\n\n        void OnGUI()\n        {\n            GUILayout.BeginVertical();\n            GUILayout.FlexibleSpace();\n\n            GUILayout.BeginHorizontal();\n            GUILayout.FlexibleSpace();\n            GUILayout.Label(\"EditorWindow could not be loaded because the script is not found in the project\", \"WordWrapLabel\");\n            GUILayout.FlexibleSpace();\n            GUILayout.EndHorizontal();\n\n            GUILayout.FlexibleSpace();\n            GUILayout.EndVertical();\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\n\nnamespace UnityEditor\n{\n    internal class FlexibleMenu : PopupWindowContent\n    {\n        class Styles\n        {\n            public GUIStyle menuItem = \"MenuItem\";\n            public GUIContent plusButtonText = EditorGUIUtility.TrTextContent(\"\", \"Add New Item\");\n        }\n        static Styles s_Styles;\n\n        IFlexibleMenuItemProvider m_ItemProvider;\n        FlexibleMenuModifyItemUI m_ModifyItemUI;\n        Action<int, object> m_ItemClickedCallback;\n        Vector2 m_ScrollPosition = Vector2.zero;\n        bool m_ShowAddNewPresetItem;\n        int m_ShowEditWindowForIndex = -1;\n        int m_HoverIndex;\n        int[] m_SeperatorIndices;\n        float m_CachedWidth = -1f;\n        float m_MinTextWidth = 200f;\n\n        const float lineHeight = 18f;\n        const float seperatorHeight = 8f;\n        const float leftMargin = 25f;\n        int maxIndex { get { return m_ShowAddNewPresetItem ? m_ItemProvider.Count() : m_ItemProvider.Count() - 1; } }\n        public int selectedIndex { get; set; }\n        protected float minTextWidth { get { return m_MinTextWidth; } set { m_MinTextWidth = value; ClearCachedWidth(); } }\n\n        // Note: 'itemClickedCallback' arguments is clicked index, clicked item object\n        public FlexibleMenu(IFlexibleMenuItemProvider itemProvider, int selectionIndex, Action<int, object> itemClickedCallback)\n        {\n            Init(itemProvider, selectionIndex, null, itemClickedCallback);\n        }\n\n        // itemClickedCallback arguments is clicked index, clicked item object\n        public FlexibleMenu(IFlexibleMenuItemProvider itemProvider, int selectionIndex, FlexibleMenuModifyItemUI modifyItemUi, Action<int, object> itemClickedCallback)\n        {\n            Init(itemProvider, selectionIndex, modifyItemUi, itemClickedCallback);\n        }\n\n        void Init(IFlexibleMenuItemProvider itemProvider, int selectionIndex, FlexibleMenuModifyItemUI modifyItemUi, Action<int, object> itemClickedCallback)\n        {\n            m_ItemProvider = itemProvider;\n            m_ModifyItemUI = modifyItemUi;\n            m_ItemClickedCallback = itemClickedCallback;\n            m_SeperatorIndices = m_ItemProvider.GetSeperatorIndices();\n            selectedIndex = selectionIndex;\n            m_ShowAddNewPresetItem = m_ModifyItemUI != null;\n\n            if (m_SeperatorIndices == null)\n                m_SeperatorIndices = new int[0];\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            return CalcSize();\n        }\n\n        bool IsDeleteModiferPressed()\n        {\n            return Event.current.alt;\n        }\n\n        bool AllowDeleteClick(int index)\n        {\n            return IsDeleteModiferPressed() && m_ItemProvider.IsModificationAllowed(index) && GUIUtility.hotControl == 0;\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            Event evt = Event.current;\n\n            Rect contentRect = new Rect(0, 0, 1, CalcSize().y);\n            m_ScrollPosition = GUI.BeginScrollView(rect, m_ScrollPosition, contentRect);\n            {\n                float curY = 2f;\n                for (int i = 0; i <= maxIndex; ++i)\n                {\n                    int itemControlID = i + 1000000;\n                    Rect itemRect = new Rect(0, curY, rect.width, lineHeight);\n                    bool addSeperator = Array.IndexOf(m_SeperatorIndices, i) >= 0;\n\n                    // Add new preset button\n                    if (m_ShowAddNewPresetItem && i == m_ItemProvider.Count())\n                    {\n                        CreateNewItemButton(itemRect);\n                        continue;\n                    }\n\n                    if (m_ShowEditWindowForIndex == i)\n                    {\n                        m_ShowEditWindowForIndex = -1;\n                        EditExistingItem(itemRect, i);\n                    }\n\n                    // Handle event\n                    switch (evt.type)\n                    {\n                        case EventType.Repaint:\n                            bool hover = false;\n                            if (m_HoverIndex == i)\n                            {\n                                if (itemRect.Contains(evt.mousePosition))\n                                    hover = true;\n                                else\n                                    m_HoverIndex = -1;\n                            }\n\n                            // Overwrite if\n                            if (m_ModifyItemUI != null && m_ModifyItemUI.IsShowing())\n                            {\n                                hover = m_ItemProvider.GetItem(i) == m_ModifyItemUI.m_Object;\n                            }\n\n                            s_Styles.menuItem.Draw(itemRect, GUIContent.Temp(m_ItemProvider.GetName(i)), hover, false, i == selectedIndex, false);\n\n                            if (addSeperator)\n                            {\n                                const float margin = 4f;\n                                Rect seperatorRect = new Rect(itemRect.x + margin, itemRect.y + itemRect.height + seperatorHeight * 0.5f, itemRect.width - 2 * margin, 1);\n                                DrawRect(seperatorRect, (EditorGUIUtility.isProSkin) ? new Color(0.32f, 0.32f, 0.32f, 1.333f) : new Color(0.6f, 0.6f, 0.6f, 1.333f)); // dark : light\n                            }\n\n                            // We delete presets on alt-click\n                            if (AllowDeleteClick(i))\n                                EditorGUIUtility.AddCursorRect(itemRect, MouseCursor.ArrowMinus);\n                            break;\n\n                        case EventType.MouseDown:\n                            if (evt.button == 0 && itemRect.Contains(evt.mousePosition))\n                            {\n                                GUIUtility.hotControl = itemControlID;\n                                if (!IsDeleteModiferPressed() && evt.clickCount == 1)\n                                {\n                                    GUIUtility.hotControl = 0;\n                                    SelectItem(i);\n                                    editorWindow.Close();\n                                    evt.Use();\n                                }\n                            }\n                            break;\n\n                        case EventType.MouseUp:\n                            if (GUIUtility.hotControl == itemControlID)\n                            {\n                                GUIUtility.hotControl = 0;\n                                if (evt.button == 0 && itemRect.Contains(evt.mousePosition))\n                                {\n                                    if (AllowDeleteClick(i))\n                                    {\n                                        DeleteItem(i);\n                                        evt.Use();\n                                    }\n                                }\n                            }\n                            break;\n\n                        case EventType.ContextClick:\n                            if (itemRect.Contains(evt.mousePosition))\n                            {\n                                evt.Use();\n                                if (m_ModifyItemUI != null && m_ItemProvider.IsModificationAllowed(i))\n                                    ItemContextMenu.Show(i, this);\n                            }\n                            break;\n\n                        case EventType.MouseMove:\n                            if (itemRect.Contains(evt.mousePosition))\n                            {\n                                if (m_HoverIndex != i)\n                                {\n                                    m_HoverIndex = i;\n                                    Repaint();\n                                }\n                            }\n                            else if (m_HoverIndex == i)\n                            {\n                                m_HoverIndex = -1;\n                                Repaint();\n                            }\n                            break;\n                    }\n\n                    curY += lineHeight;\n                    if (addSeperator)\n                        curY += seperatorHeight;\n                } // end foreach item\n            } GUI.EndScrollView();\n        }\n\n        void SelectItem(int index)\n        {\n            selectedIndex = index;\n            if (m_ItemClickedCallback != null && index >= 0)\n                m_ItemClickedCallback(index, m_ItemProvider.GetItem(index));\n        }\n\n        protected Vector2 CalcSize()\n        {\n            float height = (maxIndex + 1) * lineHeight + m_SeperatorIndices.Length * seperatorHeight;\n            if (m_CachedWidth < 0)\n                m_CachedWidth = Math.Max(m_MinTextWidth, CalcWidth());\n            return new Vector2(m_CachedWidth, height);\n        }\n\n        void ClearCachedWidth()\n        {\n            m_CachedWidth = -1f;\n        }\n\n        float CalcWidth()\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            float maxWidth = 0;\n            for (int i = 0; i < m_ItemProvider.Count(); ++i)\n            {\n                float w = s_Styles.menuItem.CalcSize(GUIContent.Temp(m_ItemProvider.GetName(i))).x;\n                maxWidth = Mathf.Max(w, maxWidth);\n            }\n\n            const float rightMargin = 6f;\n            return maxWidth + rightMargin;\n        }\n\n        void Repaint()\n        {\n            HandleUtility.Repaint(); // repaints current guiview (needs rename)\n        }\n\n        void CreateNewItemButton(Rect itemRect)\n        {\n            if (m_ModifyItemUI == null)\n                return;\n\n            Rect plusRect = new Rect(itemRect.x + leftMargin, itemRect.y, 15, 15);\n            if (GUI.Button(plusRect, s_Styles.plusButtonText, \"OL Plus\"))\n            {\n                plusRect.y -= 15f;\n                m_ModifyItemUI.Init(FlexibleMenuModifyItemUI.MenuType.Add, m_ItemProvider.Create(),\n                    delegate(object obj)\n                    {\n                        ClearCachedWidth();\n                        int newIndex = m_ItemProvider.Add(obj);\n                        SelectItem(newIndex);\n                        EditorApplication.RequestRepaintAllViews(); // We want to repaint the flexible menu (currently in modifyItemUI)\n                    });\n                PopupWindow.Show(plusRect, m_ModifyItemUI);\n            }\n        }\n\n        void EditExistingItem(Rect itemRect, int index)\n        {\n            if (m_ModifyItemUI == null)\n                return;\n\n            itemRect.y -= itemRect.height;\n            itemRect.x += itemRect.width;\n            m_ModifyItemUI.Init(FlexibleMenuModifyItemUI.MenuType.Edit, m_ItemProvider.GetItem(index),\n                delegate(object obj)\n                {\n                    ClearCachedWidth();\n                    m_ItemProvider.Replace(index, obj);\n                    EditorApplication.RequestRepaintAllViews(); // We want to repaint the flexible menu (currently in modifyItemUI)\n                });\n            PopupWindow.Show(itemRect, m_ModifyItemUI);\n        }\n\n        void DeleteItem(int index)\n        {\n            ClearCachedWidth();\n            m_ItemProvider.Remove(index);\n            selectedIndex = Mathf.Clamp(selectedIndex, 0, m_ItemProvider.Count() - 1); // ensure valid\n        }\n\n        public static void DrawRect(Rect rect, Color color)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            Color orgColor = GUI.color;\n            GUI.color = GUI.color * color;\n            GUI.DrawTexture(rect, EditorGUIUtility.whiteTexture);\n            GUI.color = orgColor;\n        }\n\n        internal static class ItemContextMenu\n        {\n            static FlexibleMenu s_Caller;\n\n            static public void Show(int itemIndex, FlexibleMenu caller)\n            {\n                s_Caller = caller;\n                GenericMenu menu = new GenericMenu();\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Edit...\"), false, Edit, itemIndex);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Delete\"), false, Delete, itemIndex);\n                menu.ShowAsContext();\n                EditorGUIUtility.ExitGUI();\n            }\n\n            private static void Delete(object userData)\n            {\n                int itemIndex = (int)userData;\n                s_Caller.DeleteItem(itemIndex);\n            }\n\n            private static void Edit(object userData)\n            {\n                int itemIndex = (int)userData;\n                s_Caller.m_ShowEditWindowForIndex = itemIndex;\n            }\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/FlexibleMenu/FlexibleMenuModifyItemUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\n\nnamespace UnityEditor\n{\n    abstract class FlexibleMenuModifyItemUI : PopupWindowContent\n    {\n        public enum MenuType { Add, Edit }\n        protected MenuType m_MenuType;\n        public object m_Object;\n        protected Action<object> m_AcceptedCallback;\n        private bool m_IsInitialized;\n\n        public override void OnClose()\n        {\n            m_Object = null;\n            m_AcceptedCallback = null;\n            m_IsInitialized = false;\n            EditorApplication.RequestRepaintAllViews(); // When closed ensure FlexibileMenu gets repainted so hover can be removed\n        }\n\n        public void Init(MenuType menuType, object obj, Action<object> acceptedCallback)\n        {\n            m_MenuType = menuType;\n            m_Object = obj;\n            m_AcceptedCallback = acceptedCallback;\n            m_IsInitialized = true;\n        }\n\n        public void Accepted()\n        {\n            if (m_AcceptedCallback != null)\n                m_AcceptedCallback(m_Object);\n            else\n                Debug.LogError(\"Missing callback. Did you remember to call Init ?\");\n        }\n\n        public bool IsShowing()\n        {\n            return m_IsInitialized;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/FlexibleMenu/IFlexibleMenuItemProvider.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor\n{\n    interface IFlexibleMenuItemProvider\n    {\n        int Count();\n        object GetItem(int index);\n        int Add(object obj);\n        void Replace(int index, object newPresetObject);\n        void Remove(int index);\n        object Create();\n        void Move(int index, int destIndex, bool insertAfterDestIndex);\n        string GetName(int index);\n        bool IsModificationAllowed(int index);\n        int[] GetSeperatorIndices();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/FlowLayout.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing System.Collections;\nusing System.Reflection;\nusing UnityEditorInternal;\n\n\nnamespace UnityEditor\n{\n    class FlowLayout : GUILayoutGroup\n    {\n        struct LineInfo\n        {\n            public float minSize, maxSize;\n            public float start, size;\n            public int topBorder, bottomBorder;\n        }\n\n        int        m_Lines;\n        LineInfo[] m_LineInfo;\n\n        public override void CalcWidth()\n        {\n            bool hasMinWidth = minWidth != 0;\n\n            base.CalcWidth();\n\n            if (isVertical)\n            {\n                // DONT\n            }\n            else\n            {\n                // Margin handling is somewhat different from other controls.\n                // Since we don't know what will wrap where we'll just take the Min margin of all child elements\n                if (!hasMinWidth)\n                {\n                    minWidth = 0;\n                    foreach (GUILayoutEntry i in entries)\n                    {\n                        // Here we should probably include margins of the element, but that does seem kind of annoying\n                        minWidth = Mathf.Max(m_ChildMinWidth, i.minWidth);\n                    }\n                }\n            }\n        }\n\n        public override void SetHorizontal(float x, float width)\n        {\n            // Apply the base. Now everything is in one line (or column), and all we need is to insert the linebreaks\n            base.SetHorizontal(x, width);\n\n            if (resetCoords)\n                x = 0;\n\n            if (isVertical)\n            {\n                Debug.LogError(\"Wordwrapped vertical group. Don't. Just Don't\");\n            }\n            else\n            {  // we're horizontally laid out:\n               // apply margins/padding here\n               // If we have a style, adjust the sizing to take care of padding (if we don't the horizontal margins have been propagated fully up the hierarchy)...\n\n                // Set the positions\n                m_Lines = 0;\n                float pulledOffset = 0;  // How far we need to pull each item back.\n                foreach (GUILayoutEntry i in entries)\n                {\n                    if (i.rect.xMax - pulledOffset > x + width)\n                    {\n                        // TODO: When we move a line back, we should re-expand\n                        pulledOffset = i.rect.x - i.marginLeft;\n                        m_Lines++;\n                    }\n                    i.SetHorizontal(i.rect.x - pulledOffset, i.rect.width);\n                    i.rect.y = m_Lines;\n                }\n                m_Lines++;\n            }\n        }\n\n        public override void CalcHeight()\n        {\n            if (entries.Count == 0)\n            {\n                maxHeight = minHeight = 0;\n                return;\n            }\n            m_ChildMinHeight = m_ChildMaxHeight = 0;\n            int _topMarginMin = 0,  _bottomMarginMin = 0;\n            m_StretchableCountY = 0;\n            if (isVertical)\n            {\n            }\n            else\n            {\n                m_LineInfo = new LineInfo[m_Lines];\n                for (int i = 0; i < m_Lines; i++)\n                {\n                    m_LineInfo[i].topBorder = 10000;\n                    m_LineInfo[i].bottomBorder = 10000;\n                }\n\n                // Figure out border values for each line\n                foreach (GUILayoutEntry i in entries)\n                {\n                    i.CalcHeight();\n                    int j = (int)i.rect.y;\n                    m_LineInfo[j].minSize = Mathf.Max(i.minHeight, m_LineInfo[j].minSize);\n                    m_LineInfo[j].maxSize = Mathf.Max(i.maxHeight, m_LineInfo[j].maxSize);\n                    m_LineInfo[j].topBorder = Mathf.Min(i.marginTop, m_LineInfo[j].topBorder);\n                    m_LineInfo[j].bottomBorder = Mathf.Min(i.marginBottom, m_LineInfo[j].bottomBorder);\n                }\n\n                for (int i = 0; i < m_Lines; i++)\n                {\n                    m_ChildMinHeight += m_LineInfo[i].minSize;\n                    m_ChildMaxHeight += m_LineInfo[i].maxSize;\n                }\n\n                // Add in the the extra lines\n                for (int i = 1; i < m_Lines; i++)\n                {\n                    float space = Mathf.Max(m_LineInfo[i - 1].bottomBorder, m_LineInfo[i].topBorder);\n                    m_ChildMinHeight += space;\n                    m_ChildMaxHeight += space;\n                }\n                _topMarginMin = m_LineInfo[0].topBorder;\n                _bottomMarginMin = m_LineInfo[m_LineInfo.Length - 1].bottomBorder;\n            }\n\n            // Do the dance between children & parent for haggling over how many empty pixels to have\n            float firstPadding, lastPadding;\n\n            m_MarginTop = _topMarginMin;\n            m_MarginBottom = _bottomMarginMin;\n            firstPadding = lastPadding = 0;\n\n            minHeight = Mathf.Max(minHeight, m_ChildMinHeight + firstPadding + lastPadding);\n            if (maxHeight == 0)\n            {\n                stretchHeight += m_StretchableCountY + (style.stretchHeight ? 1 : 0);\n                maxHeight = m_ChildMaxHeight + firstPadding + lastPadding;\n            }\n            else\n            {\n                stretchHeight = 0;\n            }\n            maxHeight = Mathf.Max(maxHeight, minHeight);\n        }\n\n        public override void SetVertical(float y, float height)\n        {\n            if (entries.Count == 0)\n            {\n                base.SetVertical(y, height);\n                return;\n            }\n\n            if (isVertical)\n            {\n                base.SetVertical(y, height);\n            }\n            else\n            {\n                if (resetCoords)\n                    y = 0;\n\n                float clientY, clientHeight;\n                clientY = y - marginTop;\n                clientHeight = y + marginVertical;\n\n                // Figure out how to distribute the elements between the different lines\n                float heightToDistribute = clientHeight - spacing * (m_Lines - 1);\n                float minMaxScale = 0;\n                if (m_ChildMinHeight != m_ChildMaxHeight)\n                    minMaxScale = Mathf.Clamp((heightToDistribute - m_ChildMinHeight) / (m_ChildMaxHeight - m_ChildMinHeight), 0, 1);\n\n                float lineY = clientY;\n                for (int i = 0; i < m_Lines; i++)\n                {\n                    if (i > 0)\n                        lineY += Mathf.Max(m_LineInfo[i].topBorder, m_LineInfo[i - 1].bottomBorder);\n                    m_LineInfo[i].start = lineY;\n                    m_LineInfo[i].size = Mathf.Lerp(m_LineInfo[i].minSize, m_LineInfo[i].maxSize, minMaxScale);\n                    lineY += m_LineInfo[i].size + spacing;\n                }\n\n\n                foreach (GUILayoutEntry i in entries)\n                {\n                    LineInfo li = m_LineInfo[(int)i.rect.y];\n                    if (i.stretchHeight != 0)\n                        i.SetVertical(li.start + i.marginTop, li.size - i.marginVertical);\n                    else\n                        i.SetVertical(li.start + i.marginTop, Mathf.Clamp(li.size - i.marginVertical, i.minHeight, i.maxHeight));\n                }\n            }\n        }\n    }\n\n\n    // @TODO Make this serialize\n    // @TODO Handle animate-from nothing (with fade?)\n    // @TODO Figure out how to implement fade-away of contents\n    // @TODO Switch a bunch of others to use this\n    internal class GUISlideGroup\n    {\n        internal static GUISlideGroup current = null;\n        Dictionary<int, Rect> animIDs = new Dictionary<int, Rect>();\n        const float kLerp = .1f;\n        const float kSnap = .5f;\n\n        public void Begin()\n        {\n            if (current != null)\n            {\n                Debug.LogError(\"You cannot nest animGroups\");\n                return;\n            }\n\n            current = this;\n        }\n\n        public void End()\n        {\n            current = null;\n        }\n\n        public void Reset()\n        {\n            current = null;\n            animIDs.Clear();\n        }\n\n        public Rect BeginHorizontal(int id, params GUILayoutOption[] options)\n        {\n            SlideGroupInternal g = (SlideGroupInternal)GUILayoutUtility.BeginLayoutGroup(GUIStyle.none, options, typeof(SlideGroupInternal));\n            g.SetID(this, id);\n            g.isVertical = false;\n            return g.m_FinalRect;\n        }\n\n        public void EndHorizontal()\n        {\n            GUILayoutUtility.EndLayoutGroup();\n        }\n\n        public Rect GetRect(int id, Rect r)\n        {\n            bool dummy;\n            if (Event.current.type != EventType.Repaint)\n                return r;\n            return GetRect(id, r, out dummy);\n        }\n\n        Rect GetRect(int id, Rect r, out bool changed)\n        {\n            if (!animIDs.ContainsKey(id))\n            {\n                animIDs.Add(id, r);\n                changed = false;\n                return r;\n            }\n\n            Rect current = animIDs[id];\n            if (current.y != r.y || current.height != r.height || current.x != r.x || current.width != r.width)\n            {\n                float lerp = kLerp;\n                if (Mathf.Abs(current.y - r.y) > kSnap)\n                    r.y = Mathf.Lerp(current.y, r.y, lerp);\n                if (Mathf.Abs(current.height - r.height) > kSnap)\n                    r.height = Mathf.Lerp(current.height, r.height, lerp);\n                if (Mathf.Abs(current.x - r.x) > kSnap)\n                    r.x = Mathf.Lerp(current.x, r.x, lerp);\n                if (Mathf.Abs(current.width - r.width) > kSnap)\n                    r.width = Mathf.Lerp(current.width, r.width, lerp);\n                animIDs[id] = r;\n                changed = true;\n                HandleUtility.Repaint();\n            }\n            else\n                changed = false;\n            return r;\n        }\n\n        class SlideGroupInternal : GUILayoutGroup\n        {\n            int           m_ID;\n            GUISlideGroup m_Owner;\n#pragma warning disable 649\n            internal Rect m_FinalRect;\n            public void SetID(GUISlideGroup owner, int id)\n            {\n                m_ID = id;\n                m_Owner = owner;\n            }\n\n            public override void SetHorizontal(float x, float width)\n            {\n                m_FinalRect.x = x;\n                m_FinalRect.width = width;\n                base.SetHorizontal(x, width);\n            }\n\n            public override void SetVertical(float y, float height)\n            {\n                m_FinalRect.y = y;\n                m_FinalRect.height = height;\n\n                Rect r = new Rect(rect.x, y, rect.width, height);\n                bool changed;\n                r = m_Owner.GetRect(m_ID, r, out changed);\n\n                if (changed)\n                    base.SetHorizontal(r.x, r.width);\n                base.SetVertical(r.y, r.height);\n            }\n        }\n    }\n}  // namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/FoldoutHeader.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Internal;\nusing System;\n\nnamespace UnityEditor\n{\n    public sealed partial class EditorGUILayout\n    {\n        public static bool BeginFoldoutHeaderGroup(bool foldout, string content, [DefaultValue(\"EditorStyles.foldoutHeader\")]\n            GUIStyle style = null, Action<Rect> menuAction = null, GUIStyle menuIcon = null)\n        {\n            return BeginFoldoutHeaderGroup(foldout, GUIContent.Temp(content), style, menuAction, menuIcon);\n        }\n\n        public static bool BeginFoldoutHeaderGroup(bool foldout, GUIContent content, [DefaultValue(\"EditorStyles.foldoutHeader\")] GUIStyle style = null, Action<Rect> menuAction = null, GUIStyle menuIcon = null)\n        {\n            if (style == null)\n                style = EditorStyles.foldoutHeader;\n            var backgroundRect = GUILayoutUtility.GetRect(content, style);\n            return EditorGUI.BeginFoldoutHeaderGroup(backgroundRect, foldout, content, style, menuAction, menuIcon);\n        }\n\n        public static void EndFoldoutHeaderGroup()\n        {\n            EditorGUI.EndFoldoutHeaderGroup();\n        }\n    }\n\n    public sealed partial class EditorGUI\n    {\n        static int s_FoldoutHeaderGroupActive;\n        private static readonly int s_FoldoutHeaderHash = \"FoldoutHeader\".GetHashCode();\n\n        public static bool BeginFoldoutHeaderGroup(Rect position, bool foldout, string content, [DefaultValue(\"EditorStyles.foldoutHeader\")]\n            GUIStyle style = null, Action<Rect> menuAction = null, GUIStyle menuIcon = null)\n        {\n            return BeginFoldoutHeaderGroup(position, foldout, GUIContent.Temp(content), style, menuAction, menuIcon);\n        }\n\n        public static bool BeginFoldoutHeaderGroup(Rect position, bool foldout, GUIContent content, [DefaultValue(\"EditorStyles.foldoutHeader\")] GUIStyle style = null, Action<Rect> menuAction = null, GUIStyle menuIcon = null)\n        {\n            // Removing the default margin for inspectors\n            if (EditorGUIUtility.hierarchyMode)\n            {\n                position.xMin -= EditorStyles.inspectorDefaultMargins.padding.left - EditorStyles.inspectorDefaultMargins.padding.right;\n                position.xMax += EditorStyles.inspectorDefaultMargins.padding.right;\n            }\n\n            if (style == null)\n                style = EditorStyles.foldoutHeader;\n\n            s_FoldoutHeaderGroupActive++;\n            if (s_FoldoutHeaderGroupActive > 1)\n            {\n                EditorGUI.HelpBox(position, L10n.Tr(\"You can't nest Foldout Headers, end it with EndFoldoutHeaderGroup.\"), MessageType.Error);\n                return false;\n            }\n\n            const float iconSize = 16;\n            Rect menuRect = new Rect\n            {\n                x = position.xMax - style.padding.right - iconSize,\n                y = position.y + style.padding.top,\n                size = Vector2.one * iconSize\n            };\n\n            bool menuIconHover = menuRect.Contains(Event.current.mousePosition);\n            bool menuIconActive = (menuIconHover && Event.current.type == EventType.MouseDown && Event.current.button == 0);\n            if (menuAction != null && menuIconActive)\n            {\n                menuAction.Invoke(menuRect);\n                Event.current.Use();\n            }\n            int id = GUIUtility.GetControlID(s_FoldoutHeaderHash, FocusType.Keyboard, position);\n\n            if (Event.current.type == EventType.KeyDown && GUIUtility.keyboardControl == id)\n            {\n                KeyCode kc = Event.current.keyCode;\n                if (kc == KeyCode.LeftArrow && foldout || (kc == KeyCode.RightArrow && foldout == false))\n                {\n                    foldout = !foldout;\n                    GUI.changed = true;\n                    Event.current.Use();\n                }\n            }\n            else\n            {\n                foldout = EditorGUIInternal.DoToggleForward(position, id, foldout, content, style);\n            }\n\n            // Menu icon\n            if (menuAction != null && Event.current.type == EventType.Repaint)\n            {\n                if (menuIcon == null)\n                    menuIcon = EditorStyles.foldoutHeaderIcon;\n\n                menuIcon.Draw(menuRect, menuIconHover, menuIconActive, false, false);\n            }\n\n            return foldout;\n        }\n\n        public static void EndFoldoutHeaderGroup()\n        {\n            s_FoldoutHeaderGroupActive--;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/GenericMenu.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    public sealed class GenericMenu\n    {\n        List<MenuItem> m_MenuItems = new List<MenuItem>();\n        public bool allowDuplicateNames {get; set; }\n        internal List<MenuItem> menuItems => m_MenuItems;\n\n        // Callback function, called when a menu item is selected\n        public delegate void MenuFunction();\n\n        // Callback function with user data, called when a menu item is selected\n        public delegate void MenuFunction2(object userData);\n\n        // Add an item to the menu\n        public void AddItem(GUIContent content, bool on, MenuFunction func)\n        {\n            m_MenuItems.Add(new MenuItem(content, false, on, func));\n        }\n\n        // Add an item to the menu\n        public void AddItem(GUIContent content, bool on, MenuFunction2 func, object userData)\n        {\n            m_MenuItems.Add(new MenuItem(content, false, on, func, userData));\n        }\n\n        // Add a disabled item to the menu\n        public void AddDisabledItem(GUIContent content)\n        {\n            m_MenuItems.Add(new MenuItem(content, false, false, null));\n        }\n\n        // Add a disabled item to the menu\n        public void AddDisabledItem(GUIContent content, bool on)\n        {\n            m_MenuItems.Add(new MenuItem(content, false, on, null));\n        }\n\n        // Add a separator item to the menu\n        public void AddSeparator(string path)\n        {\n            m_MenuItems.Add(new MenuItem(new GUIContent(path), true, false, null));\n        }\n\n        // Get number of items in the menu\n        public int GetItemCount()\n        {\n            return m_MenuItems.Count;\n        }\n\n        internal sealed class MenuItem\n        {\n            public GUIContent content;\n            public bool separator;\n            public bool on;\n            public MenuFunction func;\n            public MenuFunction2 func2;\n            public object userData;\n            public MenuItem(GUIContent _content, bool _separator, bool _on, MenuFunction _func)\n            {\n                content = _content;\n                separator = _separator;\n                on = _on;\n                func = _func;\n            }\n\n            public MenuItem(GUIContent _content, bool _separator, bool _on, MenuFunction2 _func, object _userData)\n            {\n                content = _content;\n                separator = _separator;\n                on = _on;\n                func2 = _func;\n                userData = _userData;\n            }\n\n            public override string ToString()\n            {\n                var label = content?.text;\n                if (separator)\n                    return label + \"[separator]\";\n                return label;\n            }\n        }\n\n        /// <summary>\n        /// Show the menu under the mouse when used in an OnGUI callback.\n        /// </summary>\n        public void ShowAsContext()\n        {\n            if (Event.current == null)\n                return;\n            DropDown(new Rect(Event.current.mousePosition, Vector2.zero));\n        }\n\n        /// <summary>\n        /// Show the menu at the given rect relative to the current window in an OnGUI callback.\n        /// </summary>\n        /// <param name=\"position\"></param>\n        public void DropDown(Rect position)\n        {\n            DropDown(position, false);\n        }\n\n        /// <summary>\n        /// Show the menu at the given rect relative to the current window in an OnGUI callback.\n        /// </summary>\n        /// <param name=\"position\"></param>\n        internal void DropDown(Rect position, bool shouldDiscardMenuOnSecondClick)\n        {\n            Vector2 temp = GUIUtility.GUIToScreenPoint(new Vector2(position.x, position.y));\n            position.x = temp.x;\n            position.y = temp.y;\n            DropDownScreenSpace(position, shouldDiscardMenuOnSecondClick);\n        }\n\n        /// <summary>\n        /// Show the menu at the given screen rect.\n        /// </summary>\n        /// <param name=\"position\"></param>\n        internal void DropDownScreenSpace(Rect position, bool shouldDiscardMenuOnSecondClick)\n        {\n            string[] titles = new string[m_MenuItems.Count];\n            bool[] enabled = new bool[m_MenuItems.Count];\n            ArrayList selected = new ArrayList();\n            bool[] separator = new bool[m_MenuItems.Count];\n\n            for (int idx = 0; idx < m_MenuItems.Count; idx++)\n            {\n                MenuItem item = (MenuItem)m_MenuItems[idx];\n                titles[idx] = item.content.text;\n                enabled[idx] = ((item.func != null) || (item.func2 != null));\n                separator[idx] = item.separator;\n                if (item.on)\n                    selected.Add(idx);\n            }\n            \n            EditorUtility.DisplayCustomMenuWithSeparatorsWithScreenSpacePosition(position, titles, enabled, separator, (int[])selected.ToArray(typeof(int)), CatchMenu, null, true, allowDuplicateNames, shouldDiscardMenuOnSecondClick);\n        }\n\n        // Display as a popup with /selectedIndex/. How this behaves depends on the platform (on Mac, it'll try to scroll the menu to the right place)\n        internal void Popup(Rect position, int selectedIndex)\n        {\n            DropDown(position);\n        }\n\n        private void CatchMenu(object userData, string[] options, int selected)\n        {\n            MenuItem i = (MenuItem)m_MenuItems[selected];\n            if (i.func2 != null)\n                i.func2(i.userData);\n            else if (i.func != null)\n                i.func();\n        }\n\n        // Show object context menu with builtin menu items plus the ones from this GenericMenu.\n        internal void ObjectContextDropDown(Rect position, Object[] context, int contextUserData)\n        {\n            string[] titles = new string[m_MenuItems.Count];\n            bool[] enabled = new bool[m_MenuItems.Count];\n            ArrayList selected = new ArrayList();\n            bool[] separator = new bool[m_MenuItems.Count];\n\n            for (int idx = 0; idx < m_MenuItems.Count; idx++)\n            {\n                MenuItem item = (MenuItem)m_MenuItems[idx];\n                titles[idx] = item.content.text;\n                enabled[idx] = ((item.func != null) || (item.func2 != null));\n                separator[idx] = item.separator;\n                if (item.on)\n                    selected.Add(idx);\n            }\n\n            EditorUtility.DisplayObjectContextPopupMenuWithExtraItems(\n                position, context, contextUserData,\n                titles, enabled, separator, (int[])selected.ToArray(typeof(int)), CatchMenu, null, true);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/GradientEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    internal class GradientEditor\n    {\n        class Styles\n        {\n            public GUIStyle upSwatch = \"Grad Up Swatch\";\n            public GUIStyle upSwatchOverlay = \"Grad Up Swatch Overlay\";\n            public GUIStyle downSwatch = \"Grad Down Swatch\";\n            public GUIStyle downSwatchOverlay = \"Grad Down Swatch Overlay\";\n\n            public GUIContent modeText = EditorGUIUtility.TrTextContent(\"Mode\");\n            public GUIContent alphaText = EditorGUIUtility.TrTextContent(\"Alpha\");\n            public GUIContent colorText = EditorGUIUtility.TrTextContent(\"Color\");\n            public GUIContent locationText = EditorGUIUtility.TrTextContent(\"Location\");\n            public GUIContent percentText = new GUIContent(\"%\");\n\n            static GUIStyle GetStyle(string name)\n            {\n                GUISkin s = (GUISkin)EditorGUIUtility.LoadRequired(\"GradientEditor.GUISkin\");\n                return s.GetStyle(name);\n            }\n\n            public readonly GUIContent[] modeTexts =\n            {\n                EditorGUIUtility.TrTextContent(\"Blend (Classic)\"),\n                EditorGUIUtility.TrTextContent(\"Blend (Perceptual)\"),\n                EditorGUIUtility.TrTextContent(\"Fixed\")\n            };\n            public readonly int[] modeValues =\n            {\n                (int)GradientMode.Blend,\n                (int)GradientMode.PerceptualBlend,\n                (int)GradientMode.Fixed\n            };\n        }\n        static Styles s_Styles;\n        static Texture2D s_BackgroundTexture;\n\n        public class Swatch\n        {\n            public float m_Time;\n            public Color m_Value;\n            public bool m_IsAlpha;\n\n            public Swatch(float time, Color value, bool isAlpha)\n            {\n                m_Time = time;\n                m_Value = value;\n                m_IsAlpha = isAlpha;\n            }\n        }\n\n        const int k_MaxNumKeys = 8;\n        List<Swatch> m_RGBSwatches;\n        List<Swatch> m_AlphaSwatches;\n        GradientMode m_GradientMode;\n        [System.NonSerialized]\n        Swatch m_SelectedSwatch;\n        Gradient m_Gradient;\n        int m_NumSteps;\n        bool m_HDR;\n        ColorSpace m_ColorSpace;\n\n        private bool m_DoubleClickDetected;\n\n        // Fixed steps are only used if numSteps > 1\n        public void Init(Gradient gradient, int numSteps, bool hdr, ColorSpace colorSpace)\n        {\n            m_Gradient = gradient;\n            m_NumSteps = numSteps;\n            m_HDR = hdr;\n            m_ColorSpace = colorSpace;\n            m_DoubleClickDetected = false;\n\n            BuildArrays();\n\n            if (m_RGBSwatches.Count > 0)\n                m_SelectedSwatch = m_RGBSwatches[0];\n        }\n\n        /// <summary>\n        /// Called when the Gradient has changed and we need to update the swatches.\n        /// </summary>\n        public void RefreshGradientData()\n        {\n            // If we are already editing a Gradient we need to preserve the selected swatch or dragging may be corrupted.\n            int selectedSwatch = 0;\n            bool selectedIsAlpha = false;\n            if (m_SelectedSwatch != null)\n            {\n                selectedIsAlpha = m_SelectedSwatch.m_IsAlpha;\n                selectedSwatch = selectedIsAlpha ? m_AlphaSwatches.IndexOf(m_SelectedSwatch) : m_RGBSwatches.IndexOf(m_SelectedSwatch);\n            }\n\n            BuildArrays();\n\n            var swatches = selectedIsAlpha ? m_AlphaSwatches : m_RGBSwatches;\n            if (swatches.Count > 0)\n            {\n                if (selectedSwatch > swatches.Count - 1 || selectedSwatch == -1)\n                    selectedSwatch = 0;\n                m_SelectedSwatch = swatches[selectedSwatch];\n            }\n        }\n\n        public Gradient target\n        {\n            get { return m_Gradient; }\n        }\n\n        float GetTime(float actualTime)\n        {\n            actualTime = Mathf.Clamp01(actualTime);\n\n            if (m_NumSteps > 1)\n            {\n                float stepSize = 1.0f / (m_NumSteps - 1);\n                int step = Mathf.RoundToInt(actualTime / stepSize);\n                return step / (float)(m_NumSteps - 1);\n            }\n\n            return actualTime;\n        }\n\n        void BuildArrays()\n        {\n            if (m_Gradient == null)\n                return;\n            GradientColorKey[] colorKeys = m_Gradient.colorKeys;\n            m_RGBSwatches = new List<Swatch>(colorKeys.Length);\n            for (int i = 0; i < colorKeys.Length; i++)\n            {\n                Color color = colorKeys[i].color;\n                color.a = 1f;\n                m_RGBSwatches.Add(new Swatch(colorKeys[i].time, color, false));\n            }\n\n            GradientAlphaKey[] alphaKeys = m_Gradient.alphaKeys;\n            m_AlphaSwatches = new List<Swatch>(alphaKeys.Length);\n            for (int i = 0; i < alphaKeys.Length; i++)\n            {\n                float a = alphaKeys[i].alpha;\n                m_AlphaSwatches.Add(new Swatch(alphaKeys[i].time, new Color(a, a, a, 1), true));\n            }\n            m_GradientMode = m_Gradient.mode;\n        }\n\n        public static void DrawGradientWithBackground(Rect position, Gradient gradient, bool linearGradientKeys)\n        {\n            Texture2D gradientTexture = UnityEditorInternal.GradientPreviewCache.GetGradientPreview(gradient, linearGradientKeys);\n            Rect r2 = new Rect(position.x + 1, position.y + 1, position.width - 2, position.height - 2);\n\n            // Background checkers\n            Texture2D backgroundTexture = GetBackgroundTexture();\n            Rect texCoordsRect = new Rect(0, 0, r2.width / backgroundTexture.width, r2.height / backgroundTexture.height);\n            GUI.DrawTextureWithTexCoords(r2, backgroundTexture, texCoordsRect, false);\n\n            // Outline for Gradinet Texture, used to be Frame over texture.\n            GUI.Box(position, GUIContent.none);\n\n            // Gradient texture\n            Color oldColor = GUI.color;\n            GUI.color = Color.white;            //Dont want the Playmode tint to be applied to gradient textures.\n            if (gradientTexture != null)\n                GUI.DrawTexture(r2, gradientTexture, ScaleMode.StretchToFill, true);\n            GUI.color = oldColor;\n\n            // HDR label\n            float maxColorComponent = GetMaxColorComponent(gradient);\n            if (maxColorComponent > 1.0f)\n            {\n                GUI.Label(new Rect(position.x, position.y, position.width - 3, position.height), \"HDR\", EditorStyles.centeredGreyMiniLabel);\n            }\n        }\n\n        public void OnGUI(Rect position)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            float modeHeight = 24f;\n            float swatchHeight = 16f;\n            float editSectionHeight = 26f;\n            float gradientTextureHeight = position.height - 2 * swatchHeight - editSectionHeight - modeHeight;\n\n            position.height = modeHeight;\n            m_GradientMode = (GradientMode)EditorGUI.IntPopup(position, s_Styles.modeText, (int)m_GradientMode, s_Styles.modeTexts, s_Styles.modeValues);\n            if (m_GradientMode != m_Gradient.mode)\n                AssignBack();\n\n            position.y += modeHeight;\n            position.height = swatchHeight;\n\n            // Alpha swatches (no idea why they're top, but that's what Adobe & Apple seem to agree on)\n            ShowSwatchArray(position, m_AlphaSwatches, true);\n\n            // Gradient texture\n            position.y += swatchHeight;\n            position.height = gradientTextureHeight;\n            DrawGradientWithBackground(position, m_Gradient, m_ColorSpace == ColorSpace.Linear);\n            position.y += gradientTextureHeight;\n            position.height = swatchHeight;\n\n            // Color swatches (bottom)\n            ShowSwatchArray(position, m_RGBSwatches, false);\n\n            if (m_SelectedSwatch != null)\n            {\n                position.y += swatchHeight;\n                position.height = editSectionHeight;\n                position.y += 10;\n\n                float locationWidth = 45;\n                float locationTextWidth = 60;\n                float space = 20;\n                float alphaOrColorTextWidth = 50;\n                float totalLocationWidth = locationTextWidth + space + locationTextWidth + locationWidth;\n\n                // Alpha or Color field\n                Rect rect = position;\n                rect.height = 18;\n                rect.x += 17;\n                rect.width -= totalLocationWidth;\n                EditorGUIUtility.labelWidth = alphaOrColorTextWidth;\n                if (m_SelectedSwatch.m_IsAlpha)\n                {\n                    EditorGUIUtility.fieldWidth = 30;\n                    EditorGUI.BeginChangeCheck();\n                    float sliderValue = EditorGUI.IntSlider(rect, s_Styles.alphaText, (int)(m_SelectedSwatch.m_Value.r * 255), 0, 255) / 255f;\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        sliderValue = Mathf.Clamp01(sliderValue);\n                        m_SelectedSwatch.m_Value.r = m_SelectedSwatch.m_Value.g = m_SelectedSwatch.m_Value.b = sliderValue;\n                        AssignBack();\n                        HandleUtility.Repaint();\n                    }\n                }\n                else\n                {\n                    EditorGUI.BeginChangeCheck();\n                    m_SelectedSwatch.m_Value = EditorGUI.ColorField(rect, s_Styles.colorText, m_SelectedSwatch.m_Value, true, false, m_HDR);\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        AssignBack();\n                        HandleUtility.Repaint();\n                    }\n                }\n\n                // Location of key\n                rect.x += rect.width + space;\n                rect.width = locationWidth + locationTextWidth;\n\n                EditorGUIUtility.labelWidth = locationTextWidth;\n                string orgFormatString = EditorGUI.kFloatFieldFormatString;\n                EditorGUI.kFloatFieldFormatString = \"f1\";\n\n                EditorGUI.BeginChangeCheck();\n                float newLocation = EditorGUI.FloatField(rect, s_Styles.locationText, m_SelectedSwatch.m_Time * 100.0f) / 100.0f;\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_SelectedSwatch.m_Time = Mathf.Clamp(newLocation, 0f, 1f);\n                    AssignBack();\n                }\n\n                EditorGUI.kFloatFieldFormatString = orgFormatString;\n\n                rect.x += rect.width;\n                rect.width = 20;\n                GUI.Label(rect, s_Styles.percentText);\n            }\n        }\n\n        void ShowSwatchArray(Rect position, List<Swatch> swatches, bool isAlpha)\n        {\n            int id = GUIUtility.GetControlID(652347689, FocusType.Passive);\n            Event evt = Event.current;\n\n            float mouseSwatchTime = GetTime((Event.current.mousePosition.x - position.x) / position.width);\n            Vector2 fixedStepMousePosition = new Vector3(position.x + mouseSwatchTime * position.width, Event.current.mousePosition.y);\n\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.Repaint:\n                {\n                    bool hasSelection = false;\n                    foreach (Swatch s in swatches)\n                    {\n                        if (m_SelectedSwatch == s)\n                        {\n                            hasSelection = true;\n                            continue;\n                        }\n                        DrawSwatch(position, s, !isAlpha);\n                    }\n                    // selected swatch drawn last\n                    if (hasSelection && m_SelectedSwatch != null)\n                        DrawSwatch(position, m_SelectedSwatch, !isAlpha);\n                    break;\n                }\n                case EventType.MouseDown:\n                {\n                    Rect clickRect = position;\n\n                    // Swatches have some thickness thus we enlarge the clickable area\n                    clickRect.xMin -= 10;\n                    clickRect.xMax += 10;\n                    if (clickRect.Contains(evt.mousePosition))\n                    {\n                        GUIUtility.hotControl = id;\n                        evt.Use();\n\n                        // Make sure selected is topmost for the click\n                        if (swatches.Contains(m_SelectedSwatch) && !m_SelectedSwatch.m_IsAlpha && CalcSwatchRect(position, m_SelectedSwatch).Contains(evt.mousePosition))\n                        {\n                            if (evt.clickCount == 2)\n                            {\n                                //Storing the double click state to open the color picker on Mouse up event so that the user has completed his interaction with swatch movement/drag.\n                                m_DoubleClickDetected = true;\n                            }\n                            break;\n                        }\n\n                        bool found = false;\n                        foreach (Swatch s in swatches)\n                        {\n                            if (CalcSwatchRect(position, s).Contains(fixedStepMousePosition))\n                            {\n                                found = true;\n                                m_SelectedSwatch = s;\n                                EditorGUI.EndEditingActiveTextField();\n                                break;\n                            }\n                        }\n\n                        if (!found)\n                        {\n                            if (swatches.Count < k_MaxNumKeys)\n                            {\n                                Color currentColor = m_Gradient.Evaluate(mouseSwatchTime);\n                                if (isAlpha)\n                                    currentColor = new Color(currentColor.a, currentColor.a, currentColor.a, 1f);\n                                else\n                                    currentColor.a = 1f;\n                                m_SelectedSwatch = new Swatch(mouseSwatchTime, currentColor, isAlpha);\n                                swatches.Add(m_SelectedSwatch);\n                                AssignBack();\n                            }\n                            else\n                            {\n                                Debug.LogWarning(\"Max \" + k_MaxNumKeys + \" color keys and \" + k_MaxNumKeys + \" alpha keys are allowed in a gradient.\");\n                            }\n                        }\n                    }\n                    break;\n                }\n                case EventType.MouseDrag:\n\n                    if (GUIUtility.hotControl == id && m_SelectedSwatch != null)\n                    {\n                        evt.Use();\n\n                        // If user drags swatch outside in vertical direction, we'll remove the swatch\n                        if ((evt.mousePosition.y + 5 < position.y || evt.mousePosition.y - 5 > position.yMax))\n                        {\n                            if (swatches.Count > 1)\n                            {\n                                swatches.Remove(m_SelectedSwatch);\n                                AssignBack();\n                                break;\n                            }\n                        }\n                        else if (!swatches.Contains(m_SelectedSwatch))\n                            swatches.Add(m_SelectedSwatch);\n\n                        m_SelectedSwatch.m_Time = mouseSwatchTime;\n                        AssignBack();\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n\n                        // If the dragged swatch is NOT in the timeline, it means it was dragged outside.\n                        // We just forget about it and let GC get it later.\n                        if (!swatches.Contains(m_SelectedSwatch))\n                            m_SelectedSwatch = null;\n\n                        // Remove duplicate keys on mouse up so that we do not kill any keys during the drag\n                        RemoveDuplicateOverlappingSwatches();\n                    }\n                    else if (m_DoubleClickDetected)\n                    {\n                        m_DoubleClickDetected = false;\n                        GUIUtility.keyboardControl = id;\n                        ColorPicker.Show(GUIView.current, m_SelectedSwatch.m_Value, false, m_HDR);\n                        GUIUtility.ExitGUI();\n                    }\n                    break;\n\n                case EventType.KeyDown:\n                    if (evt.keyCode == KeyCode.Delete)\n                    {\n                        if (m_SelectedSwatch != null)\n                        {\n                            List<Swatch> listToDeleteFrom;\n                            if (m_SelectedSwatch.m_IsAlpha)\n                                listToDeleteFrom = m_AlphaSwatches;\n                            else\n                                listToDeleteFrom = m_RGBSwatches;\n\n                            if (listToDeleteFrom.Count > 1)\n                            {\n                                listToDeleteFrom.Remove(m_SelectedSwatch);\n                                AssignBack();\n                                HandleUtility.Repaint();\n                            }\n                        }\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.ValidateCommand:\n                    if (evt.commandName == EventCommandNames.Delete)\n                        Event.current.Use();\n                    break;\n\n                case EventType.ExecuteCommand:\n                    if (evt.commandName == EventCommandNames.ColorPickerChanged)\n                    {\n                        GUI.changed = true;\n                        m_SelectedSwatch.m_Value =  ColorPicker.color;\n                        AssignBack();\n                        HandleUtility.Repaint();\n                    }\n                    else if (evt.commandName == EventCommandNames.Delete)\n                    {\n                        if (swatches.Count > 1)\n                        {\n                            swatches.Remove(m_SelectedSwatch);\n                            AssignBack();\n                            HandleUtility.Repaint();\n                        }\n                    }\n                    break;\n            }\n        }\n\n        void DrawSwatch(Rect totalPos, Swatch s, bool upwards)\n        {\n            Color temp = GUI.backgroundColor;\n            Rect r = CalcSwatchRect(totalPos, s);\n            GUI.backgroundColor = m_ColorSpace == ColorSpace.Linear ? s.m_Value.gamma : s.m_Value;\n            GUIStyle back = upwards ? s_Styles.upSwatch : s_Styles.downSwatch;\n            GUIStyle overlay = upwards ? s_Styles.upSwatchOverlay : s_Styles.downSwatchOverlay;\n            back.Draw(r, false, false, m_SelectedSwatch == s, false);\n            GUI.backgroundColor = temp;\n            overlay.Draw(r, false, false, m_SelectedSwatch == s, false);\n        }\n\n        Rect CalcSwatchRect(Rect totalRect, Swatch s)\n        {\n            float time = s.m_Time;\n            return new Rect(totalRect.x + Mathf.Round(totalRect.width * time) - 5, totalRect.y, 10, totalRect.height);\n        }\n\n        int SwatchSort(Swatch lhs, Swatch rhs)\n        {\n            if (lhs.m_Time == rhs.m_Time && lhs == m_SelectedSwatch)\n                return -1;\n            if (lhs.m_Time == rhs.m_Time && rhs == m_SelectedSwatch)\n                return 1;\n\n            return lhs.m_Time.CompareTo(rhs.m_Time);\n        }\n\n        // Assign back all swatches, to target gradient.\n        void AssignBack()\n        {\n            m_RGBSwatches.Sort((a, b) => SwatchSort(a, b));\n            GradientColorKey[] colorKeys = new GradientColorKey[m_RGBSwatches.Count];\n            for (int i = 0; i < m_RGBSwatches.Count; i++)\n            {\n                colorKeys[i].color = m_RGBSwatches[i].m_Value;\n                colorKeys[i].time = m_RGBSwatches[i].m_Time;\n            }\n\n            m_AlphaSwatches.Sort((a, b) => SwatchSort(a, b));\n            GradientAlphaKey[] alphaKeys = new GradientAlphaKey[m_AlphaSwatches.Count];\n            for (int i = 0; i < m_AlphaSwatches.Count; i++)\n            {\n                alphaKeys[i].alpha = m_AlphaSwatches[i].m_Value.r; // we use the red channel (see BuildArrays)\n                alphaKeys[i].time = m_AlphaSwatches[i].m_Time;\n            }\n\n            m_Gradient.colorKeys = colorKeys;\n            m_Gradient.alphaKeys = alphaKeys;\n            m_Gradient.mode = m_GradientMode;\n            m_Gradient.colorSpace = m_ColorSpace;\n\n            GUI.changed = true;\n        }\n\n        // Kill any swatches that are at the same time (For example as the result of dragging a swatch on top of another)\n        void RemoveDuplicateOverlappingSwatches()\n        {\n            bool didRemoveAny = false;\n            for (int i = 1; i < m_RGBSwatches.Count; i++)\n            {\n                if (Mathf.Approximately(m_RGBSwatches[i - 1].m_Time, m_RGBSwatches[i].m_Time))\n                {\n                    m_RGBSwatches.RemoveAt(i);\n                    i--;\n                    didRemoveAny = true;\n                }\n            }\n\n            for (int i = 1; i < m_AlphaSwatches.Count; i++)\n            {\n                if (Mathf.Approximately(m_AlphaSwatches[i - 1].m_Time, m_AlphaSwatches[i].m_Time))\n                {\n                    m_AlphaSwatches.RemoveAt(i);\n                    i--;\n                    didRemoveAny = true;\n                }\n            }\n\n            if (didRemoveAny)\n                AssignBack();\n        }\n\n        public static Texture2D GetBackgroundTexture()\n        {\n            if (s_BackgroundTexture == null)\n                s_BackgroundTexture = GradientEditor.CreateCheckerTexture(32, 4, 4, Color.white, new Color(0.7f, 0.7f, 0.7f));\n            return s_BackgroundTexture;\n        }\n\n        public static Texture2D CreateCheckerTexture(int numCols, int numRows, int cellPixelWidth, Color col1, Color col2)\n        {\n            int height = numRows * cellPixelWidth;\n            int width = numCols * cellPixelWidth;\n\n            Texture2D texture = new Texture2D(width, height, TextureFormat.RGBA32, false);\n            texture.hideFlags = HideFlags.HideAndDontSave;\n            Color[] pixels = new Color[width * height];\n\n            for (int i = 0; i < numRows; i++)\n                for (int j = 0; j < numCols; j++)\n                    for (int ci = 0; ci < cellPixelWidth; ci++)\n                        for (int cj = 0; cj < cellPixelWidth; cj++)\n                            pixels[(i * cellPixelWidth + ci) * width + j * cellPixelWidth + cj] = ((i + j) % 2 == 0) ? col1 : col2;\n\n            texture.SetPixels(pixels);\n            texture.Apply();\n            return texture;\n        }\n\n        // GUI Helpers\n        public static void DrawGradientSwatch(Rect position, Gradient gradient, Color bgColor, ColorSpace colorSpace)\n        {\n            DrawGradientSwatchInternal(position, gradient, null, bgColor, colorSpace);\n        }\n\n        public static void DrawGradientSwatch(Rect position, SerializedProperty property, Color bgColor, ColorSpace colorSpace)\n        {\n            DrawGradientSwatchInternal(position, null, property, bgColor, colorSpace);\n        }\n\n        private static void DrawGradientSwatchInternal(Rect position, Gradient gradient, SerializedProperty property, Color bgColor, ColorSpace colorSpace)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            if (EditorGUI.showMixedValue)\n            {\n                Color oldColor = GUI.color;\n                float a = GUI.enabled ? 1 : 2;\n\n                GUI.color = new Color(0.82f, 0.82f, 0.82f, a) * bgColor;\n                GUIStyle mgs = EditorGUIUtility.whiteTextureStyle;\n                mgs.Draw(position, false, false, false, false);\n\n                EditorGUI.BeginHandleMixedValueContentColor();\n                mgs.Draw(position, EditorGUI.mixedValueContent, false, false, false, false);\n                EditorGUI.EndHandleMixedValueContentColor();\n\n                GUI.color = oldColor;\n                return;\n            }\n\n            // Draw Background\n            Texture2D backgroundTexture = GradientEditor.GetBackgroundTexture();\n            if (backgroundTexture != null)\n            {\n                Color oldColor = GUI.color;\n                GUI.color = bgColor;\n\n                GUIStyle backgroundStyle = EditorGUIUtility.GetBasicTextureStyle(backgroundTexture);\n                backgroundStyle.Draw(position, false, false, false, false);\n\n                GUI.color = oldColor;\n            }\n\n            // DrawTexture\n            Texture2D preview = null;\n            float maxColorComponent;\n\n            bool linearGradientKeys = colorSpace == ColorSpace.Linear;\n            if(colorSpace == ColorSpace.Uninitialized)\n            {\n                Debug.LogError(\"GradientEditor color space is not initialized, assuming linear gradient keys to build the gradient preview.\");\n                linearGradientKeys = true;\n            }\n            if (property != null)\n            {\n                preview = GradientPreviewCache.GetPropertyPreview(property, linearGradientKeys);\n                maxColorComponent = GetMaxColorComponent(property.gradientValue);\n            }\n            else\n            {\n                preview = GradientPreviewCache.GetGradientPreview(gradient, linearGradientKeys);\n                maxColorComponent = GetMaxColorComponent(gradient);\n            }\n\n            if (preview == null)\n            {\n                Debug.Log(\"Warning: Could not create preview for gradient\");\n                return;\n            }\n\n            Color color = GUI.color;\n            GUI.color = Color.white;            //Dont want the Playmode tint to be applied to gradient textures.\n            GUIStyle gs = EditorGUIUtility.GetBasicTextureStyle(preview);\n            gs.Draw(position, false, false, false, false);\n            GUI.color = color;\n\n            // HDR label\n            if (maxColorComponent > 1.0f)\n            {\n                GUI.Label(new Rect(position.x, position.y - 1, position.width - 3, position.height + 2), \"HDR\", EditorStyles.centeredGreyMiniLabel);\n            }\n        }\n\n        private static float GetMaxColorComponent(Gradient gradient)\n        {\n            float maxColorComponent = 0.0f;\n            GradientColorKey[] colorKeys = gradient.colorKeys;\n            for (int i = 0; i < colorKeys.Length; i++)\n            {\n                maxColorComponent = Mathf.Max(maxColorComponent, colorKeys[i].color.maxColorComponent);\n            }\n            return maxColorComponent;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/GradientField.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    public sealed partial class EditorGUILayout\n    {\n        // Gradient versions\n        public static Gradient GradientField(Gradient value, params GUILayoutOption[] options)\n        {\n            Rect r = s_LastRect = GUILayoutUtility.GetRect(EditorGUIUtility.fieldWidth, kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n            return EditorGUI.GradientField(r, value);\n        }\n\n        public static Gradient GradientField(string label, Gradient value, params GUILayoutOption[] options)\n        {\n            Rect r = s_LastRect = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n            return EditorGUI.GradientField(r, label, value);\n        }\n\n        public static Gradient GradientField(GUIContent label, Gradient value, params GUILayoutOption[] options)\n        {\n            Rect r = s_LastRect = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n            return EditorGUI.GradientField(r, label, value);\n        }\n\n        public static Gradient GradientField(GUIContent label, Gradient value, bool hdr, params GUILayoutOption[] options)\n        {\n            Rect r = s_LastRect = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n            return EditorGUI.GradientField(r, label, value, hdr);\n        }\n\n        // SerializedProperty versions\n        internal static Gradient GradientField(SerializedProperty value, params GUILayoutOption[] options)\n        {\n            Rect r = s_LastRect = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n            return EditorGUI.GradientField(r, value);\n        }\n\n        internal static Gradient GradientField(string label, SerializedProperty value, params GUILayoutOption[] options)\n        {\n            Rect r = s_LastRect = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n            return EditorGUI.GradientField(r, label, value);\n        }\n\n        internal static Gradient GradientField(GUIContent label, SerializedProperty value, params GUILayoutOption[] options)\n        {\n            Rect r = s_LastRect = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options);\n            return EditorGUI.GradientField(r, label, value);\n        }\n    }\n\n\n    public sealed partial class EditorGUI\n    {\n        static readonly int s_GradientHash = \"s_GradientHash\".GetHashCode();\n        static int s_GradientID;\n\n        // Gradient versions\n        public static Gradient GradientField(Rect position, Gradient gradient)\n        {\n            int id = EditorGUIUtility.GetControlID(s_GradientHash, FocusType.Keyboard, position);\n            return DoGradientField(position, id, gradient, null, false, ColorSpace.Gamma);\n        }\n\n        public static Gradient GradientField(Rect position, string label, Gradient gradient)\n        {\n            return GradientField(position, EditorGUIUtility.TempContent(label), gradient);\n        }\n\n        public static Gradient GradientField(Rect position, GUIContent label, Gradient gradient)\n        {\n            return GradientField(position, label, gradient, false);\n        }\n\n        public static Gradient GradientField(Rect position, GUIContent label, Gradient gradient, bool hdr)\n        {\n            return GradientField(position, label, gradient, hdr, ColorSpace.Gamma);\n        }\n\n        public static Gradient GradientField(Rect position, GUIContent label, Gradient gradient, bool hdr, ColorSpace colorSpace)\n        {\n            int id = EditorGUIUtility.GetControlID(s_GradientHash, FocusType.Keyboard, position);\n            return DoGradientField(PrefixLabel(position, id, label), id, gradient, null, hdr, colorSpace);\n        }\n\n        // SerializedProperty versions\n        internal static Gradient GradientField(Rect position, SerializedProperty property)\n        {\n            return GradientField(position, property, false);\n        }\n\n        internal static Gradient GradientField(Rect position, SerializedProperty property, bool hdr)\n        {\n            return GradientField(position, property, hdr, ColorSpace.Gamma);\n        }\n\n        internal static Gradient GradientField(Rect position, SerializedProperty property, bool hdr, ColorSpace colorSpace)\n        {\n            int id = EditorGUIUtility.GetControlID(s_GradientHash, FocusType.Keyboard, position);\n            return DoGradientField(position, id, null, property, hdr, colorSpace);\n        }\n\n        internal static Gradient GradientField(Rect position, string label, SerializedProperty property)\n        {\n            return GradientField(position, EditorGUIUtility.TempContent(label), property);\n        }\n\n        internal static Gradient GradientField(Rect position, GUIContent label, SerializedProperty property)\n        {\n            int id = EditorGUIUtility.GetControlID(s_GradientHash, FocusType.Keyboard, position);\n            return DoGradientField(PrefixLabel(position, id, label), id, null, property, false, ColorSpace.Gamma);\n        }\n\n        internal static Gradient DoGradientField(Rect position, int id, Gradient value, SerializedProperty property, bool hdr, ColorSpace space)\n        {\n            Event evt = Event.current;\n\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (position.Contains(evt.mousePosition))\n                    {\n                        if (evt.button == 0)\n                        {\n                            s_GradientID = id;\n                            GUIUtility.keyboardControl = id;\n                            Gradient gradient = property != null ? property.gradientValue : value;\n                            GradientPicker.Show(gradient, hdr, space);\n                            GUIUtility.ExitGUI();\n                        }\n                        else if (evt.button == 1)\n                        {\n                            if (property != null)\n                                GradientContextMenu.Show(property.Copy());\n                            // TODO: make work for Gradient value\n                        }\n                    }\n                    break;\n                case EventType.Repaint:\n                {\n                    Rect r2 = new Rect(position.x + 1, position.y + 1, position.width - 2, position.height - 2);    // Adjust for box drawn on top\n                    if (property != null)\n                        GradientEditor.DrawGradientSwatch(r2, property, Color.white, space);\n                    else\n                        GradientEditor.DrawGradientSwatch(r2, value, Color.white, space);\n                    EditorStyles.colorPickerBox.Draw(position, GUIContent.none, id);\n                    break;\n                }\n                case EventType.ExecuteCommand:\n                    if (s_GradientID == id && evt.commandName == GradientPicker.GradientPickerChangedCommand)\n                    {\n                        GUI.changed = true;\n                        GradientPreviewCache.ClearCache();\n                        HandleUtility.Repaint();\n                        if (property != null)\n                            property.gradientValue = GradientPicker.gradient;\n\n                        return GradientPicker.gradient;\n                    }\n                    break;\n                case EventType.ValidateCommand:\n                    if (s_GradientID == id && evt.commandName == EventCommandNames.UndoRedoPerformed)\n                    {\n                        if (property != null)\n                            GradientPicker.SetCurrentGradient(property.gradientValue);\n                        GradientPreviewCache.ClearCache();\n                        return value;\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (GUIUtility.keyboardControl == id && (evt.keyCode == KeyCode.Space || evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter))\n                    {\n                        Event.current.Use();\n                        Gradient gradient = property != null ? property.gradientValue : value;\n                        GradientPicker.Show(gradient, hdr, space);\n                        GUIUtility.ExitGUI();\n                    }\n                    break;\n            }\n            return value;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/GradientPicker.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class PresetLibraryGradientEditor : PresetLibraryEditor<GradientPresetLibrary>\n    {\n        public PresetLibraryGradientEditor(ScriptableObjectSaveLoadHelper<GradientPresetLibrary> helper,\n                                           PresetLibraryEditorState state,\n                                           System.Action<int, object> itemClickedCallback\n        ) : base(helper, state, itemClickedCallback)\n        {}\n\n        public ColorSpace colorSpace { get; set; }\n\n        protected override void DrawPreset(PresetLibrary lib, Rect rect, object presetObject)\n        {\n            ((GradientPresetLibrary)lib).Draw(rect, presetObject, colorSpace);\n        }\n    }\n    internal class GradientPicker : EditorWindow\n    {\n        private static GradientPicker s_GradientPicker;\n        public static string presetsEditorPrefID { get { return \"Gradient\"; } }\n\n        private GradientEditor m_GradientEditor;\n        private PresetLibraryGradientEditor m_GradientLibraryEditor;\n        [SerializeField]\n        private PresetLibraryEditorState m_GradientLibraryEditorState;\n        private Gradient m_Gradient;\n        private const int k_DefaultNumSteps = 0;\n        private GUIView m_DelegateView;\n        private System.Action<Gradient> m_Delegate;\n        private bool m_HDR;\n        private ColorSpace m_ColorSpace;\n        private bool gradientChanged { get; set; }\n\n        // Static methods\n        public static void Show(Gradient newGradient, bool hdr, ColorSpace colorSpace = ColorSpace.Gamma)\n        {\n            Show(newGradient, hdr, colorSpace, null, GUIView.current);\n        }\n\n        public static void Show(Gradient newGradient, bool hdr, System.Action<Gradient> onGradientChanged)\n        {\n            Show(newGradient, hdr, ColorSpace.Gamma, onGradientChanged, null);\n        }\n\n        public static void Show(Gradient newGradient, bool hdr, ColorSpace colorSpace, System.Action<Gradient> onGradientChanged)\n        {\n            Show(newGradient, hdr, colorSpace, onGradientChanged, null);\n        }\n\n        private static void Show(Gradient newGradient, bool hdr, ColorSpace colorSpace, System.Action<Gradient> onGradientChanged, GUIView currentView)\n        {\n            PrepareShow(hdr, colorSpace);\n            s_GradientPicker.m_DelegateView = currentView;\n            s_GradientPicker.m_Delegate = onGradientChanged;\n            s_GradientPicker.Init(newGradient, hdr, colorSpace);\n\n            GradientPreviewCache.ClearCache();\n        }\n\n        static void PrepareShow(bool hdr, ColorSpace colorSpace)\n        {\n            if (s_GradientPicker == null)\n            {\n                string title = hdr ? \"HDR Gradient Editor\" : \"Gradient Editor\";\n                if (colorSpace == ColorSpace.Linear)\n                {\n                    title += \" (linear)\";\n                }\n                s_GradientPicker = (GradientPicker)GetWindow(typeof(GradientPicker), true, title, false);\n                Vector2 minSize = new Vector2(360, 224);\n                Vector2 maxSize = new Vector2(1900, 3000);\n                s_GradientPicker.minSize = minSize;\n                s_GradientPicker.maxSize = maxSize;\n                s_GradientPicker.wantsMouseMove = true;\n                Undo.undoRedoEvent += s_GradientPicker.OnUndoPerformed;\n            }\n\n            s_GradientPicker.ShowAuxWindow(); // Use this if auto close on lost focus is wanted.\n        }\n\n        public static GradientPicker instance\n        {\n            get\n            {\n                if (!s_GradientPicker)\n                    Debug.LogError(\"Gradient Picker not initalized, did you call Show first?\");\n                return s_GradientPicker;\n            }\n        }\n\n        public string currentPresetLibrary\n        {\n            get\n            {\n                InitIfNeeded();\n                return m_GradientLibraryEditor.currentLibraryWithoutExtension;\n            }\n            set\n            {\n                InitIfNeeded();\n                m_GradientLibraryEditor.currentLibraryWithoutExtension = value;\n            }\n        }\n\n        private void Init(Gradient newGradient, bool hdr, ColorSpace colorSpace)\n        {\n            m_Gradient = newGradient;\n            m_HDR = hdr;\n            m_ColorSpace = colorSpace;\n            if (m_GradientEditor != null)\n                m_GradientEditor.Init(newGradient, k_DefaultNumSteps, m_HDR, m_ColorSpace);\n            Repaint();\n        }\n\n        private void SetGradientData(Gradient gradient)\n        {\n            m_Gradient.colorKeys = gradient.colorKeys;\n            m_Gradient.alphaKeys = gradient.alphaKeys;\n            m_Gradient.mode = gradient.mode;\n            Init(m_Gradient, m_HDR, m_ColorSpace);\n        }\n\n        public static bool visible\n        {\n            get { return s_GradientPicker != null; }\n        }\n\n        public static Gradient gradient\n        {\n            get\n            {\n                if (s_GradientPicker != null)\n                    return s_GradientPicker.m_Gradient;\n                return null;\n            }\n        }\n\n        public void OnEnable()\n        {\n            hideFlags = HideFlags.DontSave;\n            // Use these if window is not an aux window for auto closing on play/stop\n            //EditorApplication.playmodeStateChanged += OnPlayModeStateChanged;\n        }\n\n        public void OnDisable()\n        {\n            //EditorApplication.playmodeStateChanged -= OnPlayModeStateChanged;\n            if (m_GradientLibraryEditorState != null)\n                m_GradientLibraryEditorState.TransferEditorPrefsState(false);\n\n            s_GradientPicker?.UnregisterEvents();\n            s_GradientPicker = null;\n        }\n\n        public void OnDestroy()\n        {\n            this.UnregisterEvents();\n            m_GradientLibraryEditor.UnloadUsedLibraries();\n        }\n\n        void OnPlayModeStateChanged()\n        {\n            Close();\n        }\n\n        void InitIfNeeded()\n        {\n            // Init editor when needed\n            if (m_GradientEditor == null)\n            {\n                m_GradientEditor = new GradientEditor();\n                m_GradientEditor.Init(m_Gradient, k_DefaultNumSteps, m_HDR, m_ColorSpace);\n            }\n\n            if (m_GradientLibraryEditorState == null)\n            {\n                m_GradientLibraryEditorState = new PresetLibraryEditorState(presetsEditorPrefID);\n                m_GradientLibraryEditorState.TransferEditorPrefsState(true);\n            }\n\n            if (m_GradientLibraryEditor == null)\n            {\n                var saveLoadHelper = new ScriptableObjectSaveLoadHelper<GradientPresetLibrary>(\"gradients\", SaveType.Text);\n                m_GradientLibraryEditor = new PresetLibraryGradientEditor(saveLoadHelper, m_GradientLibraryEditorState, PresetClickedCallback);\n                m_GradientLibraryEditor.showHeader = true;\n                m_GradientLibraryEditor.colorSpace = m_ColorSpace;\n                m_GradientLibraryEditor.minMaxPreviewHeight = new Vector2(14f, 14f);\n            }\n        }\n\n        void PresetClickedCallback(int clickCount, object presetObject)\n        {\n            Gradient gradient = presetObject as Gradient;\n            if (gradient == null)\n                Debug.LogError(\"Incorrect object passed \" + presetObject);\n\n            SetCurrentGradient(gradient);\n            UnityEditorInternal.GradientPreviewCache.ClearCache();\n            gradientChanged = true;\n        }\n\n        public void OnGUI()\n        {\n            // When we start play (using shortcut keys) we get two OnGui calls and m_Gradient is null: so early out.\n            if (m_Gradient == null)\n                return;\n\n            InitIfNeeded();\n\n            float gradientEditorHeight = Mathf.Min(position.height, 146);\n            float distBetween = 10f;\n            float presetLibraryHeight = position.height - gradientEditorHeight - distBetween;\n\n            Rect gradientEditorRect = new Rect(10, 10, position.width - 20, gradientEditorHeight - 20);\n            Rect gradientLibraryRect = new Rect(0, gradientEditorHeight + distBetween, position.width, presetLibraryHeight);\n\n            // Separator\n            EditorGUI.DrawRect(new Rect(gradientLibraryRect.x, gradientLibraryRect.y - 1, gradientLibraryRect.width, 1), new Color(0, 0, 0, 0.3f));\n            EditorGUI.DrawRect(new Rect(gradientLibraryRect.x, gradientLibraryRect.y, gradientLibraryRect.width, 1), new Color(1, 1, 1, 0.1f));\n\n            // The meat\n            EditorGUI.BeginChangeCheck();\n            m_GradientEditor.OnGUI(gradientEditorRect);\n            if (EditorGUI.EndChangeCheck())\n                gradientChanged = true;\n            m_GradientLibraryEditor.OnGUI(gradientLibraryRect, m_Gradient);\n            if (gradientChanged)\n            {\n                gradientChanged = false;\n                SendEvent(true);\n            }\n        }\n\n        public const string GradientPickerChangedCommand = \"GradientPickerChanged\";\n\n        void SendEvent(bool exitGUI)\n        {\n            if (m_DelegateView)\n            {\n                Event e = EditorGUIUtility.CommandEvent(GradientPickerChangedCommand);\n                Repaint();\n                m_DelegateView.SendEvent(e);\n                if (exitGUI)\n                    GUIUtility.ExitGUI();\n            }\n            if (m_Delegate != null)\n            {\n                m_Delegate(gradient);\n            }\n        }\n\n        public static void SetCurrentGradient(Gradient gradient)\n        {\n            if (s_GradientPicker == null)\n                return;\n\n            s_GradientPicker.SetGradientData(gradient);\n            GUI.changed = true;\n        }\n\n        public static void RefreshGradientData()\n        {\n            s_GradientPicker?.m_GradientEditor?.RefreshGradientData();\n            RepaintWindow();\n        }\n\n        public static void CloseWindow(bool throwExitGUI = true)\n        {\n            if (s_GradientPicker == null)\n                return;\n\n            s_GradientPicker.UnregisterEvents();\n            s_GradientPicker.Close();\n\n            if (throwExitGUI)\n                GUIUtility.ExitGUI();\n        }\n\n        public static void RepaintWindow()\n        {\n            if (s_GradientPicker == null)\n                return;\n            s_GradientPicker.Repaint();\n        }\n\n        private void UnregisterEvents()\n        {\n            Undo.undoRedoEvent -= this.OnUndoPerformed;\n        }\n\n        private void OnUndoPerformed(in UndoRedoInfo info)\n        {\n            this.Init(this.m_Gradient, this.m_HDR, this.m_ColorSpace);\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/HexColorTextField.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class EditorGUILayout\n    {\n        internal static Color32 HexColorTextField(GUIContent label, Color32 color, bool showAlpha, params GUILayoutOption[] options)\n        {\n            return HexColorTextField(label, color, showAlpha, EditorStyles.textField, options);\n        }\n\n        internal static Color32 HexColorTextField(GUIContent label, Color32 color, bool showAlpha, GUIStyle style, params GUILayoutOption[] options)\n        {\n            Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options);\n            return EditorGUI.HexColorTextField(r, label, color, showAlpha, style);\n        }\n    }\n\n    public sealed partial class EditorGUI\n    {\n        internal static Color32 HexColorTextField(Rect rect, GUIContent label, Color32 color, bool showAlpha)\n        {\n            return HexColorTextField(rect, label, color, showAlpha, EditorStyles.textField);\n        }\n\n        internal static Color32 HexColorTextField(Rect rect, GUIContent label, Color32 color, bool showAlpha, GUIStyle style)\n        {\n            var id = GUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, rect);\n            return DoHexColorTextField(id, PrefixLabel(rect, id, label), color, showAlpha, style);\n        }\n\n        internal static Color32 DoHexColorTextField(int id, Rect rect, Color32 color, bool showAlpha, GUIStyle style)\n        {\n            const string kValidHexChars = \"0123456789ABCDEFabcdef\";\n\n            // Hex field\n            string hex = showAlpha ? ColorUtility.ToHtmlStringRGBA(color) : ColorUtility.ToHtmlStringRGB(color);\n            BeginChangeCheck();\n\n            bool dummy;\n            string newHex = DoTextField(s_RecycledEditor, id, rect, hex, style, kValidHexChars, out dummy, false, false, false);\n\n            if (EndChangeCheck())\n            {\n                newHex = newHex.Trim();\n                s_RecycledEditor.text = s_RecycledEditor.text.ToUpper();\n                if (newHex.Length > 0)\n                {\n                    if (newHex[0] != '#')\n                        newHex = '#' + newHex;\n                }\n\n                Color newColor;\n                if (ColorUtility.TryParseHtmlString(newHex, out newColor))\n                    color = new Color(newColor.r, newColor.g, newColor.b, showAlpha ? newColor.a : color.a);\n            }\n\n            return color;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/IApplyRevertPropertyContextMenuItemProvider.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    /// <summary>\n    /// Context menu apply/revert extension hook for object in prefab editing mode.\n    /// </summary>\n    public interface IApplyRevertPropertyContextMenuItemProvider\n    {\n        /// <summary>\n        /// Called as the context menu is being built to retrieve the method to be called (if any) when the user select the 'revert' menu item.\n        /// </summary>\n        /// <param name=\"property\"></param>\n        /// <param name=\"revertMethod\"></param>\n        /// <returns>false if a revert menu item is not meant to be shown</returns>\n        bool TryGetRevertMethodForFieldName(SerializedProperty property, out Action<SerializedProperty> revertMethod);\n\n        /// <summary>\n        /// Called as the context menu is being built to retrieve the method to be called (if any) when the user select the 'apply' menu item.\n        /// </summary>\n        /// <param name=\"property\"></param>\n        /// <param name=\"applyMethod\"></param>\n        /// <returns>false if an apply menu item is not meant to be shown</returns>\n        bool TryGetApplyMethodForFieldName(SerializedProperty property, out Action<SerializedProperty> applyMethod);\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        string GetSourceTerm();\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <param name=\"comp\"></param>\n        /// <returns></returns>\n        string GetSourceName(Component comp);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/InternalEditorGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing UnityEngine;\nusing System.Collections.Generic;\n\n// NOTE:\n// This file should only contain internal functions of the EditorGUI class\n//\n\nnamespace UnityEditor\n{\n    public sealed partial class EditorGUI\n    {\n        internal static int s_DropdownButtonHash = \"DropdownButton\".GetHashCode();\n        static int s_MouseDeltaReaderHash = \"MouseDeltaReader\".GetHashCode();\n\n        internal static bool Button(Rect position, GUIContent content)\n        {\n            return Button(position, content, EditorStyles.miniButton);\n        }\n\n        // We need an EditorGUI.Button that only reacts to left mouse button (GUI.Button reacts to all mouse buttons), so we\n        // can handle context click events for button areas etc.\n        internal static bool Button(Rect position, GUIContent content, GUIStyle style)\n        {\n            Event evt = Event.current;\n            switch (evt.type)\n            {\n                case EventType.MouseDown:\n                case EventType.MouseUp:\n                    if (evt.button != 0)\n                        return false; // ignore all input from other buttons than the left mouse button\n                    break;\n            }\n\n            return GUI.Button(position, content, style);\n        }\n\n        // Button used for the icon selector where an icon can be selected by pressing and dragging the\n        // mouse cursor around to select different icons\n        internal static bool IconButton(int id, Rect position, GUIContent content, GUIStyle style)\n        {\n            GUIUtility.CheckOnGUI();\n            switch (Event.current.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    // If the mouse is inside the button, we say that we're the hot control\n                    if (position.Contains(Event.current.mousePosition))\n                    {\n                        GUIUtility.hotControl = id;\n                        Event.current.Use();\n                        return true;\n                    }\n                    return false;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n\n                        // If we got the mousedown, the mouseup is ours as well\n                        // (no matter if the click was in the button or not)\n                        Event.current.Use();\n\n                        // But we only return true if the button was actually clicked\n                        return position.Contains(Event.current.mousePosition);\n                    }\n                    return false;\n                case EventType.MouseDrag:\n                    if (position.Contains(Event.current.mousePosition))\n                    {\n                        GUIUtility.hotControl = id;\n                        Event.current.Use();\n                        return true;\n                    }\n                    break;\n                case EventType.Repaint:\n                    style.Draw(position, content, id);\n                    break;\n            }\n            return false;\n        }\n\n        internal static float WidthResizer(Rect position, float width, float minWidth, float maxWidth)\n        {\n            bool hasControl;\n            return Resizer.Resize(position, width, minWidth, maxWidth, true, out hasControl);\n        }\n\n        internal static float WidthResizer(Rect position, float width, float minWidth, float maxWidth, out bool hasControl)\n        {\n            return Resizer.Resize(position, width, minWidth, maxWidth, true, out hasControl);\n        }\n\n        internal static float HeightResizer(Rect position, float height, float minHeight, float maxHeight)\n        {\n            bool hasControl;\n            return Resizer.Resize(position, height, minHeight, maxHeight, false, out hasControl);\n        }\n\n        internal static float HeightResizer(Rect position, float height, float minHeight, float maxHeight, out bool hasControl)\n        {\n            return Resizer.Resize(position, height, minHeight, maxHeight, false, out hasControl);\n        }\n\n        static class Resizer\n        {\n            static float s_StartSize;\n            static Vector2 s_MouseDeltaReaderStartPos;\n            internal static float Resize(Rect position, float size, float minSize, float maxSize, bool horizontal, out bool hasControl)\n            {\n                int id = EditorGUIUtility.GetControlID(s_MouseDeltaReaderHash, FocusType.Passive, position);\n                Event evt = Event.current;\n                switch (evt.GetTypeForControl(id))\n                {\n                    case EventType.MouseDown:\n                        if (GUIUtility.hotControl == 0 && position.Contains(evt.mousePosition) && evt.button == 0)\n                        {\n                            GUIUtility.hotControl = id;\n                            GUIUtility.keyboardControl = 0;\n                            s_MouseDeltaReaderStartPos = GUIClip.Unclip(evt.mousePosition); // We unclip to screenspace to prevent being affected by scrollviews\n                            s_StartSize = size;\n                            evt.Use();\n                        }\n                        break;\n                    case EventType.MouseDrag:\n                        if (GUIUtility.hotControl == id)\n                        {\n                            evt.Use();\n                            Vector2 screenPos = GUIClip.Unclip(evt.mousePosition);  // We unclip to screenspace to prevent being affected by scrollviews\n                            float delta = horizontal ? (screenPos - s_MouseDeltaReaderStartPos).x : (screenPos - s_MouseDeltaReaderStartPos).y;\n                            float newSize = s_StartSize + delta;\n                            if (newSize >= minSize && newSize <= maxSize)\n                                size = newSize;\n                            else\n                                size = Mathf.Clamp(newSize, minSize, maxSize);\n                        }\n                        break;\n                    case EventType.MouseUp:\n                        if (GUIUtility.hotControl == id && evt.button == 0)\n                        {\n                            GUIUtility.hotControl = 0;\n                            evt.Use();\n                        }\n                        break;\n                    case EventType.Repaint:\n                        var cursor = horizontal ? MouseCursor.SplitResizeLeftRight : MouseCursor.SplitResizeUpDown;\n                        EditorGUIUtility.AddCursorRect(position, cursor, id);\n                        break;\n                }\n\n                hasControl = GUIUtility.hotControl == id;\n                return size;\n            }\n        }\n\n\n        // Get mouse delta values in different situations when click-dragging\n        static Vector2 s_MouseDeltaReaderLastPos;\n        internal static Vector2 MouseDeltaReader(Rect position, bool activated)\n        {\n            int id = EditorGUIUtility.GetControlID(s_MouseDeltaReaderHash, FocusType.Passive, position);\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (activated && GUIUtility.hotControl == 0 && GUIUtility.HitTest(position, evt) && evt.button == 0)\n                    {\n                        GUIUtility.hotControl = id;\n                        GUIUtility.keyboardControl = 0;\n                        s_MouseDeltaReaderLastPos = GUIClip.Unclip(evt.mousePosition); // We unclip to screenspace to prevent being affected by scrollviews\n                        evt.Use();\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        Vector2 screenPos = GUIClip.Unclip(evt.mousePosition);  // We unclip to screenspace to prevent being affected by scrollviews\n                        Vector2 delta = (screenPos - s_MouseDeltaReaderLastPos);\n                        s_MouseDeltaReaderLastPos = screenPos;\n                        evt.Use();\n                        return delta;\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id && evt.button == 0)\n                    {\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                    }\n                    break;\n            }\n            return Vector2.zero;\n        }\n\n        private static GUIStyle s_LargeSplitLeftStyle;\n        private static GUIStyle s_LargeSplitRightStyle;\n        public static bool LargeSplitButtonWithDropdownList(GUIContent content, string[] buttonNames, GenericMenu.MenuFunction2 callback)\n        {\n            // Load required styles\n            if (s_LargeSplitLeftStyle == null)\n                s_LargeSplitLeftStyle = new GUIStyle(EditorStyles.miniButtonLeft) { fixedHeight = kLargeButtonHeight };\n\n            if (s_LargeSplitRightStyle == null)\n                s_LargeSplitRightStyle = new GUIStyle(EditorStyles.miniButtonRight) { fixedHeight = kLargeButtonHeight };\n\n            if (s_IconDropDown == null)\n                s_IconDropDown = EditorGUIUtility.IconContent(\"icon dropdown\");\n\n            EditorGUILayout.BeginHorizontal();\n\n            // Main button\n            bool clicked = GUILayout.Button(content, s_LargeSplitLeftStyle);\n\n            // Dropdown\n            const int dropdownAreaWidth = 18;\n            if (GUILayout.Button(s_IconDropDown, s_LargeSplitRightStyle, GUILayout.Width(dropdownAreaWidth)))\n            {\n                var menu = new GenericMenu();\n                for (int i = 0; i != buttonNames.Length; i++)\n                    menu.AddItem(new GUIContent(buttonNames[i]), false, callback, i);\n\n                menu.DropDown(GUILayoutUtility.current.topLevel.GetLast());\n            }\n\n            EditorGUILayout.EndHorizontal();\n            return clicked;\n        }\n\n        public static bool LargeSplitButtonWithDropdownList(GUIContent content, string[] buttonNames, GenericMenu.MenuFunction2 callback, bool disableMainButton)\n        {\n            // Load required styles\n            if (s_LargeSplitLeftStyle == null)\n                s_LargeSplitLeftStyle = new GUIStyle(EditorStyles.miniButtonLeft) { fixedHeight = kLargeButtonHeight };\n\n            if (s_LargeSplitRightStyle == null)\n                s_LargeSplitRightStyle = new GUIStyle(EditorStyles.miniButtonRight) { fixedHeight = kLargeButtonHeight };\n\n            if (s_IconDropDown == null)\n                s_IconDropDown = EditorGUIUtility.IconContent(\"icon dropdown\");\n\n            EditorGUILayout.BeginHorizontal();\n\n            // Main button\n            bool clicked;\n            using (new EditorGUI.DisabledScope(disableMainButton))\n            {\n                clicked = GUILayout.Button(content, s_LargeSplitLeftStyle);\n            }\n\n            // Dropdown\n            const int dropdownAreaWidth = 18;\n            if (GUILayout.Button(s_IconDropDown, s_LargeSplitRightStyle, GUILayout.Width(dropdownAreaWidth)))\n            {\n                var menu = new GenericMenu();\n                for (int i = 0; i != buttonNames.Length; i++)\n                    menu.AddItem(new GUIContent(buttonNames[i]), false, callback, i);\n\n                menu.DropDown(GUILayoutUtility.current.topLevel.GetLast());\n            }\n\n            EditorGUILayout.EndHorizontal();\n            return clicked;\n        }\n\n        // Shows an active button and a triangle button on the right, which expands the dropdown list\n        // Returns true if button was activated, returns false if the the dropdown button was activated or the button was not clicked.\n        internal static bool ButtonWithDropdownList(string buttonName, string[] buttonNames, GenericMenu.MenuFunction2 callback, params GUILayoutOption[] options)\n        {\n            var content = EditorGUIUtility.TempContent(buttonName);\n            return ButtonWithDropdownList(content, buttonNames, callback, options);\n        }\n\n        // Shows an active button and a triangle button on the right, which expands the dropdown list\n        // Returns true if button was activated, returns false if the the dropdown button was activated or the button was not clicked.\n        internal static bool ButtonWithDropdownList(GUIContent content, string[] buttonNames, GenericMenu.MenuFunction2 callback, params GUILayoutOption[] options)\n        {\n            var rect = GUILayoutUtility.GetRect(content, GUI.skin.button, options);\n\n            var dropDownRect = rect;\n            const float kDropDownButtonWidth = 20f;\n            dropDownRect.xMin = dropDownRect.xMax - kDropDownButtonWidth;\n\n            if (Event.current.type == EventType.MouseDown && dropDownRect.Contains(Event.current.mousePosition))\n            {\n                var menu = new GenericMenu();\n                for (int i = 0; i != buttonNames.Length; i++)\n                    menu.AddItem(new GUIContent(buttonNames[i]), false, callback, i);\n\n                menu.DropDown(rect);\n                Event.current.Use();\n\n                return false;\n            }\n\n            return GUI.Button(rect, content, EditorStyles.dropDownList);\n        }\n\n        internal static void GameViewSizePopup(Rect buttonRect, GameViewSizeGroupType groupType, int selectedIndex, IGameViewSizeMenuUser gameView, GUIStyle guiStyle)\n        {\n            var group = GameViewSizes.instance.GetGroup(groupType);\n            var text = \"\";\n            if (selectedIndex >= 0 && selectedIndex < group.GetTotalCount())\n                text = group.GetGameViewSize(selectedIndex).displayText;\n\n            if (DropdownButton(buttonRect, GUIContent.Temp(text, GameView.Styles.k_AspectRatioTooltip), FocusType.Passive, guiStyle))\n            {\n                var menuData = new GameViewSizesMenuItemProvider(groupType);\n                var flexibleMenu = new GameViewSizeMenu(menuData, selectedIndex, new GameViewSizesMenuModifyItemUI(), gameView);\n                PopupWindow.Show(buttonRect, flexibleMenu);\n            }\n        }\n\n        public static void DrawRect(Rect rect, Color color)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            Color orgColor = GUI.color;\n            GUI.color = GUI.color * color;\n            GUI.DrawTexture(rect, EditorGUIUtility.whiteTexture);\n            GUI.color = orgColor;\n        }\n\n        internal static void DrawDelimiterLine(Rect rect)\n        {\n            DrawRect(rect, kSplitLineSkinnedColor.color);\n        }\n\n        internal static void DrawOutline(Rect rect, float size, Color color)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            Color orgColor = GUI.color;\n            GUI.color = GUI.color * color;\n            GUI.DrawTexture(new Rect(rect.x, rect.y, rect.width, size), EditorGUIUtility.whiteTexture);\n            GUI.DrawTexture(new Rect(rect.x, rect.yMax - size, rect.width, size), EditorGUIUtility.whiteTexture);\n            GUI.DrawTexture(new Rect(rect.x, rect.y + 1, size, rect.height - 2 * size), EditorGUIUtility.whiteTexture);\n            GUI.DrawTexture(new Rect(rect.xMax - size, rect.y + 1, size, rect.height - 2 * size), EditorGUIUtility.whiteTexture);\n\n            GUI.color = orgColor;\n        }\n    }\n\n    internal struct PropertyGUIData\n    {\n        public SerializedProperty property;\n        public Rect totalPosition;\n        public bool wasBoldDefaultFont;\n        public bool wasEnabled;\n        public Color color;\n        public PropertyGUIData(SerializedProperty property, Rect totalPosition, bool wasBoldDefaultFont, bool wasEnabled, Color color)\n        {\n            this.property = property;\n            this.totalPosition = totalPosition;\n            this.wasBoldDefaultFont = wasBoldDefaultFont;\n            this.wasEnabled = wasEnabled;\n            this.color = color;\n        }\n    }\n\n    internal class DebugUtils\n    {\n        internal static string ListToString<T>(IEnumerable<T>  list)\n        {\n            if (list == null)\n                return \"[null list]\";\n\n            string r = \"[\";\n            int count = 0;\n            foreach (T item in list)\n            {\n                if (count != 0)\n                    r += \", \";\n                if (item != null)\n                    r += item.ToString();\n                else\n                    r += \"'null'\";\n                count++;\n            }\n            r += \"]\";\n\n            if (count == 0)\n                return \"[empty list]\";\n\n            return \"(\" + count + \") \" + r;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/InternalEditorGUILayout.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\n\n// NOTE:\n// This file should only contain internal functions of the EditorGUILayout class\n\nnamespace UnityEditor\n{\n    public sealed partial class EditorGUILayout\n    {\n        internal static bool IconButton(int id, GUIContent content, GUIStyle style, params GUILayoutOption[] options)\n        {\n            s_LastRect = GUILayoutUtility.GetRect(content, style, options);\n            return EditorGUI.IconButton(id, s_LastRect, content, style);\n        }\n\n        internal static void GameViewSizePopup(GameViewSizeGroupType groupType, int selectedIndex, IGameViewSizeMenuUser gameView, GUIStyle style, params GUILayoutOption[] options)\n        {\n            s_LastRect =  GetControlRect(false, EditorGUI.kSingleLineHeight, style, options);\n            EditorGUI.GameViewSizePopup(s_LastRect, groupType, selectedIndex, gameView, style);\n        }\n\n        internal static void SortingLayerField(GUIContent label, SerializedProperty layerID, GUIStyle style, GUIStyle labelStyle)\n        {\n            s_LastRect = EditorGUILayout.GetControlRect(false, EditorGUI.kSingleLineHeight, style);\n            EditorGUI.SortingLayerField(s_LastRect, label, layerID, style, labelStyle);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/Knob.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing System.Globalization;\n\nnamespace UnityEditor\n{\n    // State for when we're dragging a knob.\n    internal class KnobState\n    {\n        public float dragStartPos;\n        public float dragStartValue;\n        public bool isDragging;\n        public bool isEditing;\n    }\n\n    public sealed partial class EditorGUILayout\n    {\n        public static float Knob(Vector2 knobSize, float value, float minValue, float maxValue, string unit, Color backgroundColor, Color activeColor, bool showValue, params GUILayoutOption[] options)\n        {\n            Rect r = s_LastRect = GetControlRect(false, knobSize.y, options);\n            return EditorGUI.Knob(r, knobSize, value, minValue, maxValue, unit, backgroundColor, activeColor, showValue, GUIUtility.GetControlID(\"Knob\".GetHashCode(), FocusType.Passive, r));\n        }\n    }\n\n    public sealed partial class EditorGUI\n    {\n        internal struct KnobContext\n        {\n            readonly Rect position;\n            readonly Vector2 knobSize;\n            readonly float currentValue;\n            readonly float start;\n            readonly float end;\n            readonly string unit;\n            readonly Color activeColor;\n            readonly Color backgroundColor;\n            readonly bool showValue;\n            readonly int id;\n\n            private const int kPixelRange = 250;\n\n            public KnobContext(Rect position, Vector2 knobSize, float currentValue, float start, float end, string unit, Color backgroundColor, Color activeColor, bool showValue, int id)\n            {\n                this.position = position;\n                this.knobSize = knobSize;\n                this.currentValue = currentValue;\n                this.start = start;\n                this.end = end;\n                this.unit = unit;\n                this.activeColor = activeColor;\n                this.backgroundColor = backgroundColor;\n                this.showValue = showValue;\n                this.id = id;\n            }\n\n            public float Handle()\n            {\n                if (KnobState().isEditing && CurrentEventType() != EventType.Repaint)\n                    return DoKeyboardInput();\n\n                switch (CurrentEventType())\n                {\n                    case EventType.MouseDown:\n                        return OnMouseDown();\n\n                    case EventType.MouseDrag:\n                        return OnMouseDrag();\n\n                    case EventType.MouseUp:\n                        return OnMouseUp();\n\n                    case EventType.Repaint:\n                        return OnRepaint();\n                }\n\n                return currentValue;\n            }\n\n            private EventType CurrentEventType()\n            {\n                return CurrentEvent().type;\n            }\n\n            private bool IsEmptyKnob()\n            {\n                return start == end;\n            }\n\n            private Event CurrentEvent()\n            {\n                return Event.current;\n            }\n\n            private float Clamp(float value)\n            {\n                return Mathf.Clamp(value, MinValue(), MaxValue());\n            }\n\n            private float ClampedCurrentValue()\n            {\n                return Clamp(currentValue);\n            }\n\n            private float MaxValue()\n            {\n                return Mathf.Max(start, end);\n            }\n\n            private float MinValue()\n            {\n                return Mathf.Min(start, end);\n            }\n\n            private float GetCurrentValuePercent()\n            {\n                return (ClampedCurrentValue() - MinValue()) / (MaxValue() - MinValue());\n            }\n\n            private float MousePosition()\n            {\n                return CurrentEvent().mousePosition.y - position.y;\n            }\n\n            private bool WasDoubleClick()\n            {\n                return CurrentEventType() == EventType.MouseDown &&\n                    CurrentEvent().clickCount == 2;\n            }\n\n            private float ValuesPerPixel()\n            {\n                return kPixelRange / (MaxValue() - MinValue());\n            }\n\n            private KnobState KnobState()\n            {\n                return (KnobState)GUIUtility.GetStateObject(typeof(KnobState), id);\n            }\n\n            private void StartDraggingWithValue(float dragStartValue)\n            {\n                var state = KnobState();\n                state.dragStartPos = MousePosition();\n                state.dragStartValue = dragStartValue;\n                state.isDragging = true;\n            }\n\n            private float OnMouseDown()\n            {\n                // if the click is outside this control, just bail out...\n                if (!position.Contains(CurrentEvent().mousePosition) || KnobState().isEditing || IsEmptyKnob())\n                    return currentValue;\n\n                GUIUtility.hotControl = id;\n\n                if (WasDoubleClick())\n                {\n                    KnobState().isEditing = true;\n                }\n                else\n                {\n                    // Record where we're dragging from, so the user can get back.\n                    StartDraggingWithValue(ClampedCurrentValue());\n                }\n\n                CurrentEvent().Use();\n\n                return currentValue;\n            }\n\n            private float OnMouseDrag()\n            {\n                if (GUIUtility.hotControl != id)\n                    return currentValue;\n\n                var state = KnobState();\n                if (!state.isDragging)\n                    return currentValue;\n\n                GUI.changed = true;\n                CurrentEvent().Use();\n\n                // Recalculate the value from the mouse position. this has the side effect that values are relative to the\n                // click point - no matter where inside the trough the original value was. Also means user can get back original value\n                // if he drags back to start position.\n                float deltaPos = state.dragStartPos - MousePosition();\n                var newValue = state.dragStartValue + (deltaPos / ValuesPerPixel());\n                return Clamp(newValue);\n            }\n\n            private float OnMouseUp()\n            {\n                if (GUIUtility.hotControl == id)\n                {\n                    CurrentEvent().Use();\n                    GUIUtility.hotControl = 0;\n                    KnobState().isDragging = false;\n                }\n                return currentValue;\n            }\n\n            private void PrintValue()\n            {\n                Rect textRect = new Rect(position.x + knobSize.x / 2 - 8, position.y + knobSize.y / 2 - 8, position.width, 20);\n                string value = currentValue.ToString(\"0.##\", CultureInfo.InvariantCulture.NumberFormat);  //FIXME: This needs to be done so it can handle any range types.\n                GUI.Label(textRect, value + \" \" + unit);\n            }\n\n            private float DoKeyboardInput()\n            {\n                GUI.SetNextControlName(\"KnobInput\");\n                GUI.FocusControl(\"KnobInput\");\n\n                EditorGUI.BeginChangeCheck();\n                Rect inputRect = new Rect(position.x + knobSize.x / 2 - 6, position.y + knobSize.y / 2 - 7, position.width, 20);\n\n                //FIXME: Hack\n                GUIStyle style = GUIStyle.none;\n                style.normal.textColor = new Color(.703f, .703f, .703f, 1.0f);\n                style.fontStyle = FontStyle.Normal;\n\n                string newStr = EditorGUI.DelayedTextField(inputRect, currentValue.ToString(\"0.##\", CultureInfo.InvariantCulture.NumberFormat), style);\n                if (EditorGUI.EndChangeCheck() && !String.IsNullOrEmpty(newStr))\n                {\n                    KnobState().isEditing = false;\n                    float newValue;\n                    if (float.TryParse(newStr, out newValue) && newValue != currentValue)\n                    {\n                        return Clamp(newValue);\n                    }\n                }\n\n                return currentValue;\n            }\n\n            private static Material knobMaterial;\n            static void CreateKnobMaterial()\n            {\n                if (!knobMaterial)\n                {\n                    // use a regular IMGUI content shader\n                    Shader shader = AssetDatabase.GetBuiltinExtraResource(typeof(Shader), \"Internal-GUITextureClip.shader\") as Shader;\n                    knobMaterial = new Material(shader);\n                    knobMaterial.hideFlags = HideFlags.HideAndDontSave;\n                    knobMaterial.mainTexture = EditorGUIUtility.FindTexture(\"KnobCShape\");\n                    knobMaterial.name = \"Knob Material\";\n                    if (knobMaterial.mainTexture == null)\n                        Debug.Log(\"Did not find 'KnobCShape'\");\n                }\n            }\n\n            Vector3 GetUVForPoint(Vector3 point)\n            {\n                Vector3 uv = new Vector3(\n                    (point.x - position.x) / knobSize.x,\n                    (point.y - position.y - knobSize.y) / -knobSize.y     // we need to flip uv over Y otherwise image is upside-down\n                );\n                return uv;\n            }\n\n            void VertexPointWithUV(Vector3 point)\n            {\n                GL.TexCoord(GetUVForPoint(point));\n                GL.Vertex(point);\n            }\n\n            private void DrawValueArc(float angle)\n            {\n                if (Event.current.type != EventType.Repaint)\n                    return;\n\n                CreateKnobMaterial();\n\n                Vector3 center = new Vector3(position.x + knobSize.x / 2, position.y + knobSize.y / 2, 0);\n                Vector3 centerRight = new Vector3(position.x + knobSize.x, position.y + knobSize.y / 2, 0);\n                Vector3 bottomRight = new Vector3(position.x + knobSize.x, position.y + knobSize.y, 0);\n                Vector3 bottomleft = new Vector3(position.x, position.y + knobSize.y, 0);\n                Vector3 topLeft = new Vector3(position.x, position.y, 0);\n                Vector3 topRight = new Vector3(position.x + knobSize.x, position.y, 0);\n\n                Vector3 lastCorner = bottomRight;\n\n                knobMaterial.SetPass(0);\n                //Background\n                GL.Begin(GL.QUADS);\n                GL.Color(backgroundColor);\n\n                VertexPointWithUV(topLeft);\n                VertexPointWithUV(topRight);\n                VertexPointWithUV(bottomRight);\n                VertexPointWithUV(bottomleft);\n\n                GL.End();\n\n                //Forground\n                GL.Begin(GL.TRIANGLES);\n                GL.Color(activeColor * (GUI.enabled ? 1.0f : 0.5f));\n                if (angle > 0.0f)\n                {\n                    VertexPointWithUV(center);\n                    VertexPointWithUV(centerRight);\n                    VertexPointWithUV(bottomRight);\n                    lastCorner = bottomRight;\n\n                    if (angle > (Mathf.PI / 2.0f))\n                    {\n                        VertexPointWithUV(center);\n                        VertexPointWithUV(bottomRight);\n                        VertexPointWithUV(bottomleft);\n                        lastCorner = bottomleft;\n\n                        if (angle > Mathf.PI)\n                        {\n                            VertexPointWithUV(center);\n                            VertexPointWithUV(bottomleft);\n                            VertexPointWithUV(topLeft);\n                            lastCorner = topLeft;\n                        }\n                    }\n                    if (angle == (Mathf.PI * (3.0f / 2.0f)))\n                    {\n                        VertexPointWithUV(center);\n                        VertexPointWithUV(topLeft);\n                        VertexPointWithUV(topRight);\n                        VertexPointWithUV(center);\n                        VertexPointWithUV(topRight);\n                        VertexPointWithUV(centerRight);\n                    }\n                    else\n                    {\n                        //Project the last segment onto the square and draw it.\n                        Vector3 projection;\n                        float adjustedAngle = angle + Mathf.PI / 4.0f;\n                        if (angle < Mathf.PI / 2.0f)\n                            projection = bottomRight + new Vector3((knobSize.y / 2 * Mathf.Tan(Mathf.PI / 2.0f - adjustedAngle)) - knobSize.x / 2, 0, 0);\n                        else if (angle < Mathf.PI)\n                            projection = bottomleft + new Vector3(0, (knobSize.x / 2 * Mathf.Tan(Mathf.PI - adjustedAngle)) - knobSize.y / 2, 0);\n                        else\n                            projection = topLeft + new Vector3(-(knobSize.y / 2 * Mathf.Tan((Mathf.PI * 3.0f / 2.0f) - adjustedAngle)) + knobSize.x / 2, 0, 0);\n\n                        VertexPointWithUV(center);\n                        VertexPointWithUV(lastCorner);\n                        VertexPointWithUV(projection);\n                    }\n                }\n                GL.End();\n            }\n\n            private float OnRepaint()\n            {\n                DrawValueArc(GetCurrentValuePercent() * Mathf.PI * (3.0f / 2.0f));\n\n                if (KnobState().isEditing)\n                    return DoKeyboardInput();\n\n                if (showValue)\n                    PrintValue();\n\n                return currentValue;\n            }\n        }\n\n        // Show text, fixed Size input\n        internal static float Knob(Rect position, Vector2 knobSize, float currentValue, float start, float end, string unit, Color backgroundColor, Color activeColor, bool showValue, int id)\n        {\n            return new KnobContext(position, knobSize, currentValue, start, end, unit, backgroundColor, activeColor, showValue, id).Handle();\n        }\n\n        internal static float OffsetKnob(Rect position, float currentValue, float start, float end, float median, string unit, Color backgroundColor, Color activeColor, GUIStyle knob, int id)\n        {\n            ///@TODO Implement\n            return 0f;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/LazyLoadReferenceField.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.UIElements;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    //----------------------------------------------------------------------------------------------------------------------\n    // What is this : Custom drawer for fields of type LazyLoadReference<T> that filters presented candidate list to assets of type 'T'.\n    // Motivation(s): default object field drawer is not aware that the generic argument of LazyLoadReference<> should be used\n    //   to filter the list of candidate assets.\n    //----------------------------------------------------------------------------------------------------------------------\n    [CustomPropertyDrawer(typeof(LazyLoadReference<>))]\n    internal sealed class LazyLoadedReferenceField : PropertyDrawer\n    {\n        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n        {\n            System.Type fieldType;\n            ScriptAttributeUtility.GetFieldInfoFromProperty(property, out fieldType);\n\n            EditorGUI.BeginChangeCheck();\n\n            var value = property.objectReferenceValue;\n\n            position = EditorGUI.PrefixLabel(position, label);\n            value = EditorGUI.ObjectField(position, value, fieldType.GetGenericArguments()[0], false);\n\n            if (EditorGUI.EndChangeCheck())\n                property.objectReferenceValue = value;\n        }\n\n        public override VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            ScriptAttributeUtility.GetFieldInfoFromProperty(property, out var fieldType);\n\n            var objectField = new ObjectField(preferredLabel);\n            var genericType = fieldType.GetGenericArguments()[0];\n            objectField.objectType = genericType;\n            objectField.value = property.objectReferenceValue;\n            objectField.bindingPath = property.propertyPath;\n\n            PropertyField.ConfigureFieldStyles<ObjectField, Object>(objectField);\n\n            return objectField;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ListViewElement.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal struct ListViewElement\n    {\n        public int row;\n        public int column;\n        public Rect position;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ListViewGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    /// *undocumented*\n    internal class ListViewGUI\n    {\n        static int[] dummyWidths = new int[1];\n\n        static internal ListViewShared.InternalListViewState ilvState = new ListViewShared.InternalListViewState();\n        static int listViewHash = \"ListView\".GetHashCode();\n\n        static public ListViewShared.ListViewElementsEnumerator ListView(Rect pos, ListViewState state)\n        {\n            return DoListView(pos, state, null, string.Empty);\n        }\n\n        static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, GUIStyle style, params GUILayoutOption[] options)\n        {\n            return ListView(state, 0, null, string.Empty, style, options);\n        }\n\n        static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, int[] colWidths, GUIStyle style, params GUILayoutOption[] options)\n        {\n            return ListView(state, 0, colWidths, string.Empty, style, options);\n        }\n\n        static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, ListViewOptions lvOptions, GUIStyle style, params GUILayoutOption[] options)\n        {\n            return ListView(state, lvOptions, null, string.Empty, style, options);\n        }\n\n        static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, ListViewOptions lvOptions, string dragTitle, GUIStyle style, params GUILayoutOption[] options)\n        {\n            return ListView(state, lvOptions, null, dragTitle, style, options);\n        }\n\n        static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, ListViewOptions lvOptions, int[] colWidths, string dragTitle, GUIStyle style, params GUILayoutOption[] options)\n        {\n            GUILayout.BeginHorizontal(style);\n            state.scrollPos = EditorGUILayout.BeginScrollView(state.scrollPos, options);\n            ilvState.beganHorizontal = true;\n\n            state.draggedFrom = -1;\n            state.draggedTo = -1;\n            state.fileNames = null;\n\n            ilvState.wantsReordering = (lvOptions & ListViewOptions.wantsReordering) != 0;\n            ilvState.wantsExternalFiles = (lvOptions & ListViewOptions.wantsExternalFiles) != 0;\n            ilvState.wantsToStartCustomDrag = (lvOptions & ListViewOptions.wantsToStartCustomDrag) != 0;\n            ilvState.wantsToAcceptCustomDrag = (lvOptions & ListViewOptions.wantsToAcceptCustomDrag) != 0;\n            ilvState.wantsRowMultiSelection = (lvOptions & ListViewOptions.wantsRowMultiSelection) != 0;\n\n            return DoListView(GUILayoutUtility.GetRect(1, state.totalRows * state.rowHeight + 3), state, colWidths, string.Empty);\n        }\n\n        static public ListViewShared.ListViewElementsEnumerator DoListView(Rect pos, ListViewState state, int[] colWidths, string dragTitle)\n        {\n            int id = GUIUtility.GetControlID(listViewHash, FocusType.Passive);\n            state.ID = id;\n\n            state.selectionChanged = false;\n\n            Rect vRect;\n\n            if ((GUIClip.visibleRect.x < 0) || (GUIClip.visibleRect.y < 0)) // TODO: this is needed for simple LVs to work. we are not in a clip at all.\n            {\n                vRect = pos;\n            }\n            else\n                vRect = (pos.y < 0) ? new Rect(0, 0, GUIClip.visibleRect.width, GUIClip.visibleRect.height) : new Rect(0, state.scrollPos.y, GUIClip.visibleRect.width, GUIClip.visibleRect.height); // check if this is custom scroll\n\n            if (vRect.width <= 0) vRect.width = 1;\n            if (vRect.height <= 0) vRect.height = 1;\n\n            ilvState.rect = vRect;\n\n            int invisibleRows = (int)((-pos.y + vRect.yMin) / state.rowHeight);\n            int endRow = invisibleRows + (int)System.Math.Ceiling((((vRect.yMin - pos.y) % state.rowHeight) + vRect.height) / state.rowHeight) - 1;\n\n            if (colWidths == null)\n            {\n                dummyWidths[0] = (int)vRect.width;\n                colWidths = dummyWidths;\n            }\n\n            ilvState.invisibleRows = invisibleRows;\n            ilvState.endRow = endRow;\n            ilvState.rectHeight = (int)vRect.height;\n            ilvState.state = state;\n\n            if (invisibleRows < 0)\n                invisibleRows = 0;\n\n            if (endRow >= state.totalRows)\n                endRow = state.totalRows - 1;\n\n            return new ListViewShared.ListViewElementsEnumerator(ilvState, colWidths, invisibleRows, endRow, dragTitle, new Rect(0, invisibleRows * state.rowHeight, pos.width, state.rowHeight));\n        }\n\n        static public bool MultiSelection(int prevSelected, int currSelected, ref int initialSelected, ref bool[] selectedItems)\n        {\n            return ListViewShared.MultiSelection(ilvState, prevSelected, currSelected, ref initialSelected, ref selectedItems);\n        }\n\n        static public bool HasMouseUp(Rect r)\n        {\n            return ListViewShared.HasMouseUp(ilvState, r, 0);\n        }\n\n        static public bool HasMouseDown(Rect r)\n        {\n            return ListViewShared.HasMouseDown(ilvState, r, 0);\n        }\n\n        static public bool HasMouseDown(Rect r, int button)\n        {\n            return ListViewShared.HasMouseDown(ilvState, r, button);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ListViewGUILayout.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    /// *undocumented*\n    internal class ListViewGUILayout\n    {\n        static int layoutedListViewHash = \"layoutedListView\".GetHashCode();\n\n        static ListViewState lvState = null;\n\n        static int listViewHash = \"ListView\".GetHashCode();\n        static int[] dummyWidths = new int[1];\n\n        static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, GUIStyle style, params GUILayoutOption[] options)\n        {\n            return ListView(state, 0, string.Empty, style, options);\n        }\n\n        static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, string dragTitle, GUIStyle style, params GUILayoutOption[] options)\n        {\n            return ListView(state, 0, dragTitle, style, options);\n        }\n\n        static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, ListViewOptions lvOptions, GUIStyle style, params GUILayoutOption[] options)\n        {\n            return ListView(state, lvOptions, string.Empty, style, options);\n        }\n\n        static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, ListViewOptions lvOptions, string dragTitle, GUIStyle style, params GUILayoutOption[] options)\n        {\n            lvState = state;\n\n            GUILayout.BeginHorizontal(style, options); // no good reason for this here, except drawing LVs background\n\n            state.scrollPos = EditorGUILayout.BeginScrollView(state.scrollPos, options);\n            BeginLayoutedListview(state, GUIStyle.none);\n\n            state.draggedFrom = -1;\n            state.draggedTo = -1;\n            state.fileNames = null;\n\n            state.ilvState.wantsReordering = (lvOptions & ListViewOptions.wantsReordering) != 0;\n            state.ilvState.wantsExternalFiles = (lvOptions & ListViewOptions.wantsExternalFiles) != 0;\n            state.ilvState.wantsToStartCustomDrag = (lvOptions & ListViewOptions.wantsToStartCustomDrag) != 0;\n            state.ilvState.wantsToAcceptCustomDrag = (lvOptions & ListViewOptions.wantsToAcceptCustomDrag) != 0;\n            state.ilvState.wantsRowMultiSelection = (lvOptions & ListViewOptions.wantsRowMultiSelection) != 0;\n\n            return DoListView(state, null, dragTitle);\n        }\n\n        static Rect dummyRect = new Rect(0, 0, 1, 1);\n\n        static private ListViewShared.ListViewElementsEnumerator DoListView(ListViewState state, int[] colWidths, string dragTitle)\n        {\n            Rect vRect = dummyRect;\n            int invisibleRows = 0;\n            int endRow = 0;\n\n            ListViewShared.InternalLayoutedListViewState ilvState = state.ilvState;\n\n            //GUIUtility.CheckOnGUI ();\n            int id = GUIUtility.GetControlID(listViewHash, FocusType.Passive);\n\n            state.ID = id;\n            state.selectionChanged = false;\n            ilvState.state = state;\n\n            if (Event.current.type != EventType.Layout)\n            {\n                vRect = new Rect(0, state.scrollPos.y, GUIClip.visibleRect.width, GUIClip.visibleRect.height);\n\n                if (vRect.width <= 0) vRect.width = 1;\n                if (vRect.height <= 0) vRect.height = 1;\n\n                state.ilvState.rect = vRect;\n\n                invisibleRows = (int)(vRect.yMin) / state.rowHeight;\n                endRow = invisibleRows + (int)System.Math.Ceiling(((vRect.yMin % state.rowHeight) + vRect.height) / state.rowHeight) - 1;\n\n                //if (id == GUIUtility.hotControl)\n                //{\n                //  s = invisibleRows.ToString() + \"::\" + endRow.ToString();\n                //}\n\n                ilvState.invisibleRows = invisibleRows;\n                ilvState.endRow = endRow;\n                ilvState.rectHeight = (int)vRect.height;\n\n                if (invisibleRows < 0)\n                    invisibleRows = 0;\n\n                if (endRow >= state.totalRows)\n                    endRow = state.totalRows - 1;\n            }\n\n            if (colWidths == null)\n            {\n                dummyWidths[0] = (int)vRect.width;\n                colWidths = dummyWidths;\n            }\n\n            return new ListViewShared.ListViewElementsEnumerator(ilvState, colWidths, invisibleRows, endRow, dragTitle, new Rect(0, invisibleRows * state.rowHeight, vRect.width, state.rowHeight));\n        }\n\n        private static void BeginLayoutedListview(ListViewState state, GUIStyle style, params GUILayoutOption[] options)\n        {\n            GUILayoutedListViewGroup g = (GUILayoutedListViewGroup)GUILayoutUtility.BeginLayoutGroup(style, null, typeof(GUILayoutedListViewGroup));\n\n            g.state = state;\n            state.ilvState.group = g;\n\n            GUIUtility.GetControlID(layoutedListViewHash, FocusType.Passive);\n\n            switch (Event.current.type)\n            {\n                case EventType.Layout:\n                {\n                    g.resetCoords = false;\n                    g.isVertical = true;\n                    g.ApplyOptions(options);\n                    break;\n                }\n            }\n        }\n\n        /// *undocumented*\n        internal class GUILayoutedListViewGroup : GUILayoutGroup\n        {\n            internal ListViewState state;\n\n            public override void CalcWidth()\n            {\n                // Make LVs width independent of widths of elements inside it\n                base.CalcWidth();\n                minWidth = 0;\n                maxWidth = 0;\n                stretchWidth = 10000;\n            }\n\n            public override void CalcHeight()\n            {\n                minHeight = 0;\n                maxHeight = 0;\n\n                base.CalcHeight();\n\n                m_MarginTop = 0;\n                m_MarginBottom = 0;\n\n                if (minHeight == 0) // empty lv?\n                {\n                    minHeight = 1;\n                    maxHeight = 1;\n                    state.rowHeight = 1;\n                }\n                else\n                {\n                    state.rowHeight = (int)minHeight;\n                    minHeight *= state.totalRows;\n                    maxHeight *= state.totalRows;\n                }\n            }\n\n            private void AddYRecursive(GUILayoutEntry e, float y)\n            {\n                // this looks kind of bad, but in 99% of cases it would only be one level depth (e.g. few labels inside BeginHorizontal)\n                e.rect.y += y;\n\n                GUILayoutGroup g = e as GUILayoutGroup;\n\n                if (g != null)\n                {\n                    for (int i = 0; i < g.entries.Count; i++)\n                        AddYRecursive((GUILayoutEntry)g.entries[i], y);\n                }\n            }\n\n            public void AddY()\n            {\n                if (entries.Count > 0)\n                    AddYRecursive((GUILayoutEntry)entries[0], ((GUILayoutEntry)entries[0]).minHeight);\n            }\n\n            public void AddY(float val)\n            {\n                if (entries.Count > 0)\n                    AddYRecursive((GUILayoutEntry)entries[0], val);\n            }\n        }\n\n        static public bool MultiSelection(int prevSelected, int currSelected, ref int initialSelected, ref bool[] selectedItems)\n        {\n            return ListViewShared.MultiSelection(lvState.ilvState, prevSelected, currSelected, ref initialSelected, ref selectedItems);\n        }\n\n        static public bool HasMouseUp(Rect r)\n        {\n            return ListViewShared.HasMouseUp(lvState.ilvState, r, 0);\n        }\n\n        static public bool HasMouseDown(Rect r)\n        {\n            return ListViewShared.HasMouseDown(lvState.ilvState, r, 0);\n        }\n\n        static public bool HasMouseDown(Rect r, int button)\n        {\n            return ListViewShared.HasMouseDown(lvState.ilvState, r, button);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ListViewOptions.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor\n{\n    internal enum ListViewOptions { wantsReordering = 1, wantsExternalFiles = 2, wantsToStartCustomDrag = 4, wantsToAcceptCustomDrag = 8, wantsRowMultiSelection = 16 }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ListViewShared.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    /// *undocumented*\n    internal class ListViewShared\n    {\n        public static bool OSX = Application.platform == RuntimePlatform.OSXEditor;\n\n        internal static int dragControlID = -1;\n        internal static bool isDragging = false;\n\n        /// *undocumented*\n        internal class InternalListViewState\n        {\n            public int id = -1;\n            public int invisibleRows;\n            public int endRow;\n            public int rectHeight;\n            public ListViewState state;\n            public bool beganHorizontal = false;\n            public Rect rect;\n            public bool wantsReordering = false;\n            public bool wantsExternalFiles = false;\n            public bool wantsToStartCustomDrag = false;\n            public bool wantsToAcceptCustomDrag = false;\n            public bool wantsRowMultiSelection = false;\n            public int dragItem;\n        }\n\n        /// *undocumented*\n        internal class InternalLayoutedListViewState : InternalListViewState\n        {\n            public ListViewGUILayout.GUILayoutedListViewGroup group;\n        }\n\n        /// *undocumented*\n        internal class Constants\n        {\n            // this should not be pre-setup\n            // different windows (having different styles set) can draw using this\n            public static string insertion = \"PR Insertion\";\n        }\n\n        // Returns if LV selection has changed\n        /// *undocumented*\n        static bool DoLVPageUpDown(InternalListViewState ilvState, ref int selectedRow, ref Vector2 scrollPos, bool up)\n        {\n            int visibleRows = ilvState.endRow - ilvState.invisibleRows;\n\n            if (up)\n            {\n                if (OSX)\n                {\n                    scrollPos.y -= ilvState.state.rowHeight * visibleRows;\n\n                    if (scrollPos.y < 0)\n                        scrollPos.y = 0;\n                }\n                else\n                {\n                    selectedRow -= visibleRows;\n\n                    if (selectedRow < 0)\n                        selectedRow = 0;\n\n                    return true;\n                }\n            }\n            else\n            {\n                if (OSX)\n                {\n                    scrollPos.y += ilvState.state.rowHeight * visibleRows;\n                    //FIXME: does this need an upper bound check?\n                }\n                else\n                {\n                    selectedRow += visibleRows;\n\n                    if (selectedRow >= ilvState.state.totalRows)\n                        selectedRow = ilvState.state.totalRows - 1;\n\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        /// *undocumented*\n        static internal bool ListViewKeyboard(InternalListViewState ilvState, int totalCols)\n        {\n            int totalRows = ilvState.state.totalRows;\n\n            if ((Event.current.type != EventType.KeyDown) || (totalRows == 0))\n                return false;\n\n            if ((GUIUtility.keyboardControl != ilvState.state.ID) ||\n                Event.current.GetTypeForControl(ilvState.state.ID) != EventType.KeyDown)\n                return false;\n\n            return SendKey(ilvState, Event.current.keyCode, totalCols);\n        }\n\n        internal static void SendKey(ListViewState state, KeyCode keyCode)\n        {\n            SendKey(state.ilvState, keyCode, 1);\n        }\n\n        internal static bool SendKey(InternalListViewState ilvState, KeyCode keyCode, int totalCols)\n        {\n            var state = ilvState.state;\n\n            int previousRow = state.row;\n\n            //ilvState.state.row, ref ilvState.state.column, ref ilvState.state.scrollPos\n            switch (keyCode)\n            {\n                case KeyCode.UpArrow:\n                {\n                    if (state.row > 0)\n                        state.row--;\n                    // If nothing is selected, upArrow selects the 1st element\n                    else if (state.row == -1)\n                        state.row = 0;\n                    break;\n                }\n                case KeyCode.DownArrow:\n                {\n                    if (state.row < state.totalRows - 1)\n                        state.row++;\n                    break;\n                }\n                case KeyCode.Home:\n                {\n                    state.row = 0;\n                    break;\n                }\n                case KeyCode.End:\n                {\n                    state.row = state.totalRows - 1;\n                    break;\n                }\n                case KeyCode.LeftArrow:\n                    if (state.column > 0)\n                        state.column--;\n                    break;\n                case KeyCode.RightArrow:\n                    if (state.column < totalCols - 1)\n                        state.column++;\n                    break;\n\n                case KeyCode.PageUp:\n                {\n                    if (!DoLVPageUpDown(ilvState, ref state.row, ref state.scrollPos, true))\n                    {\n                        Event.current.Use();\n                        return false;\n                    }\n                    break;\n                }\n                case KeyCode.PageDown:\n                {\n                    if (!DoLVPageUpDown(ilvState, ref state.row, ref state.scrollPos, false))\n                    {\n                        Event.current.Use();\n                        return false;\n                    }\n                    break;\n                }\n                case KeyCode.A: // must evade the return false and be handled by MultiSelection if needed\n                    if (!(ilvState.wantsRowMultiSelection && EditorGUI.actionKey))\n                        return false;\n                    break;\n                default:\n                    return false;\n            }\n\n            if (ilvState.wantsRowMultiSelection)\n                MultiSelection(ilvState, previousRow); // scrollPos is set during MultiSelection\n            else\n                state.scrollPos = ListViewScrollToRow(ilvState, state.scrollPos, state.row);\n            Event.current.Use();\n            return true;\n        }\n\n        internal static void MultiSelection(InternalListViewState ilvState, int previousRow)\n        {\n            var state = ilvState.state;\n\n            // initializing and updating the array if needed\n            if (state.selectedItems == null)\n                state.selectedItems = new bool[state.totalRows];\n            else if (state.selectedItems.Length != state.totalRows)\n                System.Array.Resize(ref state.selectedItems, state.totalRows);\n\n            MultiSelection(ilvState, previousRow, state.row, ref state.initialRow, ref state.selectedItems);\n        }\n\n        static internal bool HasMouseDown(InternalListViewState ilvState, Rect r)\n        {\n            return HasMouseDown(ilvState, r, 0);\n        }\n\n        static internal bool HasMouseDown(InternalListViewState ilvState, Rect r, int button)\n        {\n            if (Event.current.type == EventType.MouseDown && Event.current.button == button)\n            {\n                if (r.Contains(Event.current.mousePosition))\n                {\n                    GUIUtility.hotControl = ilvState.state.ID;\n                    GUIUtility.keyboardControl = ilvState.state.ID;\n                    ListViewShared.isDragging = false;\n                    Event.current.Use();\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        static internal bool HasMouseUp(InternalListViewState ilvState, Rect r)\n        {\n            return HasMouseUp(ilvState, r, 0);\n        }\n\n        static internal bool HasMouseUp(InternalListViewState ilvState, Rect r, int button)\n        {\n            if (Event.current.type == EventType.MouseUp && Event.current.button == button)\n            {\n                if (r.Contains(Event.current.mousePosition))\n                {\n                    GUIUtility.hotControl = 0;\n                    Event.current.Use();\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        // Returns if selection was actually changed\n        static internal bool MultiSelection(InternalListViewState ilvState, int prevSelected, int currSelected, ref int initialSelected, ref bool[] selectedItems)\n        {\n            bool shiftIsDown = Event.current.shift;\n            bool ctrlIsDown = EditorGUI.actionKey;\n            bool selChanged = false;\n\n            if ((shiftIsDown || ctrlIsDown) && (initialSelected == -1))\n                initialSelected = prevSelected;\n\n            // Select all : Ctrl + A\n            bool selectAll = ctrlIsDown && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.A;\n            int prevInitialSelected = initialSelected;\n            if (selectAll)\n            {\n                shiftIsDown = true;\n\n                initialSelected = selectedItems.Length - 1;\n                currSelected = 0;\n            }\n\n            // multi selection\n            if (shiftIsDown)\n            {\n                int from = System.Math.Min(initialSelected, currSelected);\n                int to = System.Math.Max(initialSelected, currSelected);\n\n                // shift only: remove the items not between the initial and the current\n                if (!ctrlIsDown)\n                {\n                    for (int i = 0; i < from; i++)\n                    {\n                        if (selectedItems[i])\n                            selChanged = true;\n\n                        selectedItems[i] = false;\n                    }\n\n                    for (int i = to + 1; i < selectedItems.Length; i++)\n                    {\n                        if (selectedItems[i])\n                            selChanged = true;\n\n                        selectedItems[i] = false;\n                    }\n                }\n\n                if (from < 0)\n                    from = to;\n                // select the items between the initial and the current\n                for (int i = from; i <= to; i++)\n                {\n                    if (!selectedItems[i])\n                        selChanged = true;\n\n                    selectedItems[i] = true;\n                }\n            }\n            else if (ctrlIsDown)\n            {\n                selectedItems[currSelected] = !selectedItems[currSelected];\n                initialSelected = currSelected;\n                selChanged = true;\n            }\n            else\n            {\n                if (!selectedItems[currSelected])\n                    selChanged = true;\n\n                for (int i = 0; i < selectedItems.Length; i++)\n                {\n                    if (selectedItems[i] && currSelected != i)\n                        selChanged = true;\n\n                    selectedItems[i] = false;\n                }\n\n                initialSelected = -1;\n                selectedItems[currSelected] = true;\n            }\n\n            if (selectAll) // revert the value\n                initialSelected = prevInitialSelected;\n\n            if (ilvState != null)\n                ilvState.state.scrollPos = ListViewScrollToRow(ilvState, currSelected);\n\n            return selChanged;\n        }\n\n        static internal Vector2 ListViewScrollToRow(InternalListViewState ilvState, int row)\n        {\n            return ListViewScrollToRow(ilvState, ilvState.state.scrollPos, row);\n        }\n\n        static internal int ListViewScrollToRow(InternalListViewState ilvState, int currPosY, int row)\n        {\n            return (int)ListViewScrollToRow(ilvState, new Vector2(0, currPosY), row).y;\n        }\n\n        static internal Vector2 ListViewScrollToRow(InternalListViewState ilvState, Vector2 currPos, int row)\n        {\n            if ((ilvState.invisibleRows < row) && (ilvState.endRow > row))\n                return currPos;\n\n            if (row <= ilvState.invisibleRows)\n                currPos.y = ilvState.state.rowHeight * row;\n            else\n                currPos.y = ilvState.state.rowHeight * (row + 1) - ilvState.rectHeight;\n\n            if (currPos.y < 0)\n                currPos.y = 0;\n            else if (currPos.y > ilvState.state.totalRows * ilvState.state.rowHeight - ilvState.rectHeight)\n                currPos.y = ilvState.state.totalRows * ilvState.state.rowHeight - ilvState.rectHeight;\n\n            return currPos;\n        }\n\n        /// *undocumented*\n        internal class ListViewElementsEnumerator : IEnumerator<ListViewElement>\n        {\n            private int[] colWidths;\n            private int xTo;\n            private int yFrom;\n            private int yTo;\n\n            private Rect firstRect;\n            private Rect rect;\n            private int xPos = -1;\n            private int yPos = -1;\n            private ListViewElement element;\n\n            private InternalListViewState ilvState;\n            private InternalLayoutedListViewState ilvStateL;\n\n            private bool quiting;\n            private bool isLayouted;\n\n            private string dragTitle;\n\n            internal ListViewElementsEnumerator(InternalListViewState ilvState, int[] colWidths, int yFrom, int yTo, string dragTitle, Rect firstRect)\n            {\n                this.colWidths = colWidths;\n                this.xTo = colWidths.Length - 1;\n                this.yFrom = yFrom;\n                this.yTo = yTo;\n                this.firstRect = firstRect;\n                this.rect = firstRect;\n                this.quiting = ilvState.state.totalRows == 0;\n\n                this.ilvState = ilvState;\n                this.ilvStateL = ilvState as InternalLayoutedListViewState;\n\n                this.isLayouted = ilvStateL != null;\n\n                this.dragTitle = dragTitle;\n\n                ilvState.state.customDraggedFromID = 0;\n\n                Reset();\n            }\n\n            public bool MoveNext()\n            {\n                if (xPos > -1)\n                {\n                    if (ListViewShared.HasMouseDown(ilvState, rect))\n                    {\n                        var previousRow = ilvState.state.row;\n                        ilvState.state.selectionChanged = true;\n                        ilvState.state.row = yPos;\n                        ilvState.state.column = xPos;\n                        ilvState.state.scrollPos = ListViewShared.ListViewScrollToRow(ilvState, yPos); // this is about clicking on a row that is partially visible\n\n                        if (ilvState.wantsRowMultiSelection)\n                            MultiSelection(ilvState, previousRow);\n\n                        if ((ilvState.wantsReordering || ilvState.wantsToStartCustomDrag) && (GUIUtility.hotControl == ilvState.state.ID))\n                        {\n                            DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), ilvState.state.ID);\n                            delay.mouseDownPosition = Event.current.mousePosition;\n                            ilvState.dragItem = yPos;\n                            dragControlID = ilvState.state.ID;\n                        }\n                    }\n                    // On Mouse drag, start drag & drop\n                    if (!ListViewShared.isDragging &&\n                        (ilvState.wantsReordering || ilvState.wantsToStartCustomDrag) &&\n                        GUIUtility.hotControl == ilvState.state.ID &&\n                        Event.current.type == EventType.MouseDrag &&\n                        GUIClip.visibleRect.Contains(Event.current.mousePosition))\n                    {\n                        DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), ilvState.state.ID);\n\n                        if (delay.CanStartDrag())\n                        {\n                            DragAndDrop.PrepareStartDrag();\n\n                            if (ilvState.wantsReordering)\n                            {\n                                ilvState.state.dropHereRect = new Rect(ilvState.rect.x, 0, ilvState.rect.width, ilvState.state.rowHeight * 2);\n                                DragAndDrop.StartDrag(dragTitle);\n                            }\n                            else if (ilvState.wantsToStartCustomDrag)\n                            {\n                                DragAndDrop.SetGenericData(\"CustomDragID\", ilvState.state.ID);\n                                DragAndDrop.StartDrag(dragTitle);\n                            }\n\n                            ListViewShared.isDragging = true;\n                        }\n\n                        Event.current.Use();\n                    }\n                }\n\n                xPos++;\n\n                if (xPos > xTo)\n                {\n                    xPos = 0;\n                    yPos++;\n\n                    rect.x = firstRect.x;\n                    rect.width = colWidths[0];\n\n                    if (yPos > yTo)\n                    {\n                        quiting = true;\n                    }\n                    else // move vertically\n                    {\n                        rect.y += rect.height;\n                    }\n                }\n                else // move horizontally\n                {\n                    if (xPos >= 1)\n                        rect.x += colWidths[xPos - 1];\n\n                    rect.width = colWidths[xPos];\n                }\n\n                element.row = yPos;\n                element.column = xPos;\n                element.position = rect;\n\n                if (element.row >= ilvState.state.totalRows)\n                    quiting = true;\n\n                if (isLayouted && Event.current.type == EventType.Layout)\n                {\n                    // this is just \"on layout event enumerate just first row\" (so we get height of single row)\n                    if (yFrom + 1 == yPos)\n                    {\n                        quiting = true;\n                    }\n                }\n\n                if (isLayouted && yPos != yFrom)\n                    GUILayout.EndHorizontal();\n\n                if (quiting)\n                {\n                    if (ilvState.state.drawDropHere && Event.current.GetTypeForControl(ilvState.state.ID) == EventType.Repaint)\n                    {\n                        GUIStyle insertion = Constants.insertion;\n                        insertion.Draw(insertion.margin.Remove(ilvState.state.dropHereRect), false, false, false, false);\n                    }\n\n                    if (ListViewShared.ListViewKeyboard(ilvState, colWidths.Length))\n                        ilvState.state.selectionChanged = true;\n\n                    if (Event.current.GetTypeForControl(ilvState.state.ID) == EventType.MouseUp)\n                    {\n                        GUIUtility.hotControl = 0;\n                    }\n\n                    if (ilvState.wantsReordering && (GUIUtility.hotControl == ilvState.state.ID))\n                    {\n                        ListViewState lv = ilvState.state;\n\n                        switch (Event.current.type)\n                        {\n                            case EventType.DragUpdated:\n                            {\n                                DragAndDrop.visualMode = ilvState.rect.Contains(Event.current.mousePosition) ?\n                                    DragAndDropVisualMode.Move : DragAndDropVisualMode.None;\n\n                                Event.current.Use();\n\n                                if (DragAndDrop.visualMode != DragAndDropVisualMode.None)\n                                {\n                                    lv.dropHereRect.y = (Mathf.RoundToInt(Event.current.mousePosition.y / lv.rowHeight) - 1) * lv.rowHeight;\n\n                                    if (lv.dropHereRect.y >= lv.rowHeight * lv.totalRows)\n                                        lv.dropHereRect.y = lv.rowHeight * (lv.totalRows - 1);\n\n                                    lv.drawDropHere = true;\n                                }\n\n                                break;\n                            }\n                            case EventType.DragPerform:\n                            {\n                                if (GUIClip.visibleRect.Contains(Event.current.mousePosition))\n                                {\n                                    ilvState.state.draggedFrom = ilvState.dragItem;\n                                    ilvState.state.draggedTo = Mathf.RoundToInt(Event.current.mousePosition.y / lv.rowHeight);\n\n                                    if (ilvState.state.draggedTo > ilvState.state.totalRows)\n                                        ilvState.state.draggedTo = ilvState.state.totalRows;\n\n                                    // the guy handling this would better actually rearrange items...\n                                    if (ilvState.state.draggedTo > ilvState.state.draggedFrom)\n                                        ilvState.state.row = ilvState.state.draggedTo - 1;\n                                    else\n                                        ilvState.state.row = ilvState.state.draggedTo;\n\n                                    ilvState.state.selectionChanged = true;\n\n                                    DragAndDrop.AcceptDrag();\n                                    Event.current.Use();\n                                    ilvState.wantsReordering = false;\n                                    ilvState.state.drawDropHere = false;\n                                }\n\n                                GUIUtility.hotControl = 0;\n                                break;\n                            }\n                            case EventType.DragExited:\n                            {\n                                ilvState.wantsReordering = false;\n                                ilvState.state.drawDropHere = false;\n\n                                GUIUtility.hotControl = 0;\n                                break;\n                            }\n                        }\n                    }\n                    else if (ilvState.wantsExternalFiles)\n                    {\n                        switch (Event.current.type)\n                        {\n                            case EventType.DragUpdated:\n                            {\n                                if ((GUIClip.visibleRect.Contains(Event.current.mousePosition)) &&\n                                    (DragAndDrop.paths != null) && (DragAndDrop.paths.Length != 0))         // dragging files from somewhere\n                                {\n                                    DragAndDrop.visualMode = ilvState.rect.Contains(Event.current.mousePosition) ?\n                                        DragAndDropVisualMode.Copy : DragAndDropVisualMode.None;\n\n                                    Event.current.Use();\n\n                                    if (DragAndDrop.visualMode != DragAndDropVisualMode.None)\n                                    {\n                                        ilvState.state.dropHereRect = new Rect(ilvState.rect.x,\n                                            (Mathf.RoundToInt(Event.current.mousePosition.y / ilvState.state.rowHeight) - 1) * ilvState.state.rowHeight,\n                                            ilvState.rect.width, ilvState.state.rowHeight);\n\n                                        if (ilvState.state.dropHereRect.y >= ilvState.state.rowHeight * ilvState.state.totalRows)\n                                            ilvState.state.dropHereRect.y = ilvState.state.rowHeight * (ilvState.state.totalRows - 1);\n\n                                        ilvState.state.drawDropHere = true;\n                                    }\n                                }\n                                break;\n                            }\n                            case EventType.DragPerform:\n                            {\n                                if (GUIClip.visibleRect.Contains(Event.current.mousePosition))\n                                {\n                                    ilvState.state.fileNames = DragAndDrop.paths;\n                                    DragAndDrop.AcceptDrag();\n                                    Event.current.Use();\n                                    ilvState.wantsExternalFiles = false;\n                                    ilvState.state.drawDropHere = false;\n                                    ilvState.state.draggedTo = Mathf.RoundToInt(Event.current.mousePosition.y / ilvState.state.rowHeight);\n                                    if (ilvState.state.draggedTo > ilvState.state.totalRows)\n                                        ilvState.state.draggedTo = ilvState.state.totalRows;\n                                    ilvState.state.row = ilvState.state.draggedTo;\n                                }\n\n                                GUIUtility.hotControl = 0;\n\n                                break;\n                            }\n                            case EventType.DragExited:\n                            {\n                                ilvState.wantsExternalFiles = false;\n                                ilvState.state.drawDropHere = false;\n\n                                GUIUtility.hotControl = 0;\n                                break;\n                            }\n                        }\n                    }\n                    else if (ilvState.wantsToAcceptCustomDrag && (dragControlID != ilvState.state.ID))\n                    {\n                        switch (Event.current.type)\n                        {\n                            case EventType.DragUpdated:\n                            {\n                                object data = DragAndDrop.GetGenericData(\"CustomDragID\");\n\n                                if (GUIClip.visibleRect.Contains(Event.current.mousePosition) && data != null)\n                                {\n                                    DragAndDrop.visualMode = ilvState.rect.Contains(Event.current.mousePosition) ?\n                                        DragAndDropVisualMode.Move : DragAndDropVisualMode.None;\n\n                                    Event.current.Use();\n                                }\n                                break;\n                            }\n                            case EventType.DragPerform:\n                            {\n                                object data = DragAndDrop.GetGenericData(\"CustomDragID\");\n\n                                if (GUIClip.visibleRect.Contains(Event.current.mousePosition) && data != null)\n                                {\n                                    ilvState.state.customDraggedFromID = (int)data;\n                                    DragAndDrop.AcceptDrag();\n                                    Event.current.Use();\n                                }\n\n                                GUIUtility.hotControl = 0;\n                                break;\n                            }\n                            case EventType.DragExited:\n                            {\n                                GUIUtility.hotControl = 0;\n                                break;\n                            }\n                        }\n                    }\n\n                    if (ilvState.beganHorizontal)\n                    {\n                        EditorGUILayout.EndScrollView();\n                        GUILayout.EndHorizontal();\n                        ilvState.beganHorizontal = false;\n                    }\n\n                    if (isLayouted)\n                    {\n                        GUILayoutUtility.EndLayoutGroup();\n                        EditorGUILayout.EndScrollView();\n                    }\n\n                    ilvState.wantsReordering = false;\n                    ilvState.wantsExternalFiles = false;\n                }\n                else if (isLayouted)\n                {\n                    if (yPos != yFrom)\n                    {\n                        ilvStateL.group.ResetCursor();\n                        ilvStateL.group.AddY();\n                    }\n                    else\n                        ilvStateL.group.AddY(ilvState.invisibleRows * ilvState.state.rowHeight);\n                }\n\n                if (isLayouted)\n                {\n                    if (!quiting)\n                        GUILayout.BeginHorizontal(GUIStyle.none); // for each row\n                    else\n                        GUILayout.EndHorizontal(); // the one used for drawing LVs background\n                }\n\n                return !quiting;\n            }\n\n            public void Reset()\n            {\n                xPos = -1;\n                yPos = yFrom;\n            }\n\n            ListViewElement IEnumerator<ListViewElement>.Current { get { return element; } }\n            object IEnumerator.Current { get { return element; } }\n\n            public IEnumerator GetEnumerator() { return this; }\n            public void Dispose() {}\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ListViewState.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    /// *undocumented*\n    [System.Serializable]\n    internal class ListViewState\n    {\n        const int c_rowHeight = 16; //TODO:\n        public int row;\n        public bool[] selectedItems;\n        public int initialRow = -1;\n        public int column;\n        public Vector2 scrollPos;\n        public int totalRows;\n        public int rowHeight;\n\n        public int ID;\n        public bool selectionChanged;\n        public int draggedFrom;\n        public int draggedTo;\n        public bool drawDropHere = false;\n        public Rect dropHereRect = new Rect(0, 0, 0, 0);\n        public string[] fileNames = null;\n        public int customDraggedFromID = 0;\n\n        public ListViewState() { Init(0, c_rowHeight); }\n        public ListViewState(int totalRows) { Init(totalRows, c_rowHeight); }\n        public ListViewState(int totalRows, int rowHeight) { Init(totalRows, rowHeight); }\n\n        /// *undocumented*\n        internal ListViewShared.InternalLayoutedListViewState ilvState = new ListViewShared.InternalLayoutedListViewState();\n\n        private void Init(int totalRows, int rowHeight)\n        {\n            this.row = -1;\n            this.column = 0;\n            this.scrollPos = Vector2.zero;\n            this.totalRows = totalRows;\n            this.rowHeight = rowHeight;\n\n            selectionChanged = false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/MainView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class MainView : View, ICleanuppable\n    {\n        internal const float kToolbarHeight = Toolbar.k_ToolbarHeight;\n        internal const float kStatusbarHeight = 20;\n\n        private static readonly Vector2 kMinSize = new Vector2(875, 300);\n        private static readonly Vector2 kMaxSize = new Vector2(10000, 10000);\n\n        [SerializeField] private bool m_UseTopView;\n        [SerializeField] private float m_TopViewHeight;\n        [SerializeField] private bool m_UseBottomView;\n        [SerializeField] private float m_BottomViewHeight;\n\n        public bool useTopView { get => m_UseTopView; set => m_UseTopView = value; }\n        public float topViewHeight { get => m_TopViewHeight; set => m_TopViewHeight = value; }\n\n        public bool useBottomView { get => m_UseBottomView; set => m_UseBottomView = value; }\n        public float bottomViewHeight { get => m_BottomViewHeight; set => m_BottomViewHeight = value; }\n\n        public MainView()\n        {\n            topViewHeight = kToolbarHeight;\n            bottomViewHeight = kStatusbarHeight;\n            useTopView = useBottomView = true;\n        }\n\n        private void OnEnable()\n        {\n            SetMinMaxSizes(kMinSize, kMaxSize);\n        }\n\n        private bool OnUnityWantsToQuit() => ContainerWindow.CanCloseAll(includeMainWindow: true);\n\n        private void Awake()\n        {\n            EditorApplication.wantsToQuit += OnUnityWantsToQuit;\n        }\n\n        protected override void OnDestroy()\n        {\n            EditorApplication.wantsToQuit -= OnUnityWantsToQuit;\n            base.OnDestroy();\n        }\n\n        protected override void SetPosition(Rect newPos)\n        {\n            base.SetPosition(newPos);\n            newPos = position; // base.SetPosition does some sanitization so we have to use the position property instead of the newPos we received\n            if (children.Length == 0)\n                return;\n            if (children.Length > 2)\n            {\n                // toolbar - dock area view - status bar\n                Toolbar t = children[0] as Toolbar;\n                topViewHeight = t != null ? t.CalcHeight() : topViewHeight;\n                children[0].position = new Rect(0, 0, newPos.width, topViewHeight);\n                children[1].position = new Rect(0, topViewHeight, newPos.width, newPos.height - topViewHeight - children[2].position.height);\n                children[2].position = new Rect(0, newPos.height - children[2].position.height, newPos.width, children[2].position.height);\n            }\n            else\n            {\n                // dock area view - status bar\n                if (useBottomView && children.Length >= 2)\n                {\n                    children[0].position = new Rect(0, 0, newPos.width, newPos.height - children[1].position.height);\n                    children[1].position = new Rect(0, newPos.height - children[1].position.height, newPos.width, children[1].position.height);\n                }\n                else if (useTopView && children.Length >= 2)\n                {\n                    Toolbar t = children[0] as Toolbar;\n                    topViewHeight = t != null ? t.CalcHeight() : topViewHeight;\n                    children[0].position = new Rect(0, 0, newPos.width, topViewHeight);\n                    children[1].position = new Rect(0, children[0].position.height, newPos.width, newPos.height - children[0].position.height);\n                }\n                else if (children.Length >= 1)\n                    children[0].position = new Rect(0, 0, newPos.width, newPos.height);\n            }\n        }\n\n        protected override void ChildrenMinMaxChanged()\n        {\n            if (children.Length == 3 && children[0] is Toolbar)\n            {\n                // toolbar - dock area view - status bar\n                Toolbar t = (Toolbar)children[0];\n                var min = new Vector2(minSize.x, Mathf.Max(minSize.y, t.CalcHeight() + bottomViewHeight + children[1].minSize.y));\n                SetMinMaxSizes(min, maxSize);\n            }\n            else if (children.Length == 2)\n            {\n                // dock area view - status bar\n                var min = new Vector2(minSize.x, Mathf.Max(minSize.y, bottomViewHeight + children[1].minSize.y));\n                SetMinMaxSizes(min, maxSize);\n            }\n            base.ChildrenMinMaxChanged();\n        }\n\n        public void Cleanup()\n        {\n            // If we only have one child left, this means all views have been dragged out.\n            // So we resize the window to be just the toolbar\n            // On windows, this might need some special handling for the main menu\n            if (children.Length == 3 && children[1].children.Length == 0)\n            {\n                Rect r = window.position;\n                Toolbar t = children[0] as Toolbar;\n                topViewHeight = t != null ? t.CalcHeight() : topViewHeight;\n                r.height = topViewHeight + bottomViewHeight;\n            }\n        }\n    }\n} //namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/ManagedDebuggerToggle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.Compilation;\nusing UnityEditor.Scripting;\n\nnamespace UnityEditor\n{\n    internal class ManagedDebuggerToggle\n    {\n        private readonly GUIContent m_DebuggerAttachedContent;\n        private readonly GUIContent m_DebuggerDisabledContent;\n        private readonly GUIContent m_DebuggerEnabledContent;\n        private readonly PopupLocation[] m_PopupLocation;\n\n        public ManagedDebuggerToggle()\n        {\n            m_DebuggerAttachedContent = EditorGUIUtility.TrIconContent(\"DebuggerAttached\", \"Debugger Attached\");\n            m_DebuggerDisabledContent = EditorGUIUtility.TrIconContent(\"DebuggerDisabled\", \"Debugger Disabled\");\n            m_DebuggerEnabledContent = EditorGUIUtility.TrIconContent(\"DebuggerEnabled\", \"Debugger Enabled\");\n            m_PopupLocation = new[] { PopupLocation.AboveAlignRight };\n        }\n\n        public void OnGUI()\n        {\n            using (new EditorGUI.DisabledScope(!ManagedDebugger.isEnabled))\n            {\n                var codeOptimization = CompilationPipeline.codeOptimization;\n                var debuggerAttached = ManagedDebugger.isAttached;\n                var content = GetDebuggerContent(debuggerAttached, codeOptimization);\n\n                var style = AppStatusBar.Styles.statusIcon;\n                var rect = GUILayoutUtility.GetRect(content, style);\n                if (GUI.Button(rect, content, style))\n                {\n                    PopupWindow.Show(rect, new ManagedDebuggerWindow(codeOptimization), m_PopupLocation);\n                    GUIUtility.ExitGUI();\n                }\n            }\n        }\n\n        private GUIContent GetDebuggerContent(bool debuggerAttached, CodeOptimization optimization)\n        {\n            if (CodeOptimization.Debug == optimization)\n            {\n                return debuggerAttached ? m_DebuggerAttachedContent : m_DebuggerEnabledContent;\n            }\n\n            return m_DebuggerDisabledContent;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ManagedDebuggerWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.Compilation;\nusing UnityEditor.Scripting;\n\nnamespace UnityEditor\n{\n    [InitializeOnLoad]\n    internal class ManagedDebuggerWindow : PopupWindowContent\n    {\n        private readonly GUIContent m_CodeOptimizationTitleContent;\n        private readonly GUIContent m_CodeOptimizationTextContent;\n        private readonly GUIContent m_CodeOptimizationButtonContent;\n\n        private readonly GUIStyle m_WindowStyle;\n\n        private readonly CodeOptimization m_CodeOptimization;\n\n        private float m_TextRectHeight;\n\n        private const int k_FieldCount = 2;\n        private const int k_FrameWidth = 11;\n        private const int k_WindowWidth = 290;\n        private const int k_WindowHeight = (int)EditorGUI.kSingleLineHeight * k_FieldCount + k_FrameWidth * 2;\n\n        static ManagedDebuggerWindow()\n        {\n            SubscribeToDebuggerAttached();\n        }\n\n        public ManagedDebuggerWindow(CodeOptimization codeOptimization)\n        {\n            m_CodeOptimization = codeOptimization;\n\n            if (CodeOptimization.Debug == m_CodeOptimization)\n            {\n                m_CodeOptimizationTitleContent = EditorGUIUtility.TrTextContent(\"Mode: Debug\");\n                m_CodeOptimizationButtonContent = EditorGUIUtility.TrTextContent(\"Switch to release mode\");\n                m_CodeOptimizationTextContent = (!EditorUtility.scriptCompilationFailed) ?\n                    EditorGUIUtility.TrTextContentWithIcon(\"Release mode disables C# debugging but improves C# performance.\\nSwitching to release mode will recompile and reload all scripts.\", EditorGUIUtility.GetHelpIcon(MessageType.Info)) :\n                    EditorGUIUtility.TrTextContentWithIcon(\"All compiler errors must be fixed before switching to release mode.\", EditorGUIUtility.GetHelpIcon(MessageType.Error));\n            }\n            else\n            {\n                m_CodeOptimizationTitleContent = EditorGUIUtility.TrTextContent(\"Mode: Release\");\n                m_CodeOptimizationButtonContent = EditorGUIUtility.TrTextContent(\"Switch to debug mode\");\n                m_CodeOptimizationTextContent = (!EditorUtility.scriptCompilationFailed) ?\n                    EditorGUIUtility.TrTextContentWithIcon(\"Debug mode enables C# debugging but reduces C# performance.\\nSwitching to debug mode will recompile and reload all scripts.\", EditorGUIUtility.GetHelpIcon(MessageType.Info)) :\n                    EditorGUIUtility.TrTextContentWithIcon(\"All compiler errors must be fixed before switching to debug mode.\", EditorGUIUtility.GetHelpIcon(MessageType.Error));\n            }\n\n            m_TextRectHeight = EditorStyles.helpBox.CalcHeight(m_CodeOptimizationTextContent, k_WindowWidth);\n            m_WindowStyle = new GUIStyle { padding = new RectOffset(10, 10, 10, 10) };\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            var exit = false;\n\n            GUILayout.BeginArea(rect, m_WindowStyle);\n\n            GUILayout.BeginHorizontal();\n            GUILayout.Label(m_CodeOptimizationTitleContent, EditorStyles.boldLabel);\n            GUILayout.EndHorizontal();\n\n            GUILayout.BeginHorizontal();\n            EditorGUILayout.LabelField(GUIContent.none, m_CodeOptimizationTextContent, EditorStyles.helpBox);\n            GUILayout.EndHorizontal();\n\n            using (new EditorGUI.DisabledScope(EditorUtility.scriptCompilationFailed))\n            {\n                GUILayout.BeginHorizontal();\n                if (GUILayout.Button(m_CodeOptimizationButtonContent))\n                {\n                    ToggleDebugState(m_CodeOptimization);\n                    exit = true;\n                }\n                GUILayout.EndHorizontal();\n            }\n\n            GUILayout.EndArea();\n\n            exit |= Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape;\n\n            if (exit)\n            {\n                editorWindow.Close();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            return new Vector2(k_WindowWidth, k_WindowHeight + m_TextRectHeight);\n        }\n\n        private static void OnDebuggerAttached(bool debuggerAttached)\n        {\n            if (debuggerAttached)\n            {\n                if (CodeOptimization.Release == CompilationPipeline.codeOptimization)\n                {\n                    if (EditorUtility.scriptCompilationFailed)\n                    {\n                        EditorUtility.DisplayDialog(\n                            \"C# Debugger Attached\",\n                            \"All compiler errors must be fixed before switching to debug mode.\",\n                            \"OK\");\n                        ManagedDebugger.Disconnect();\n                    }\n                    else\n                    {\n                        int option = EditorUtility.DisplayDialogComplex(\n                            \"C# Debugger Attached\",\n@\"You are trying to attach a debugger, but Debug Mode is switched off in your project.\n\nWhen Unity is in Debug Mode, C# performance is reduced, but you can attach a debugger. Switching to Debug Mode also recompiles and reloads all scripts.\n\nYou can enable Debug Mode temporarily for this Editor session, switch it on for all projects until further notice, or cancel attaching the debugger.\n\nIf you switch it on for all projects, you can change it later in the \"\"Code Optimization on Startup\"\" setting in the Preferences window.\",\n                            \"Enable debugging for this session\",\n                            \"Cancel\",\n                            \"Enable debugging for all projects\");\n\n                        if (option == 0)\n                        {\n                            ToggleDebugState(CompilationPipeline.codeOptimization);\n                        }\n                        else if (option == 2)\n                        {\n                            EditorPrefs.SetBool(\"ScriptDebugInfoEnabled\", true);\n                            ToggleDebugState(CompilationPipeline.codeOptimization);\n                        }\n                        else\n                        {\n                            ManagedDebugger.Disconnect();\n                        }\n                    }\n                }\n            }\n\n            AppStatusBar.StatusChanged();\n        }\n\n        private static void SubscribeToDebuggerAttached()\n        {\n            ManagedDebugger.debuggerAttached += OnDebuggerAttached;\n        }\n\n        private static void ToggleDebugState(CodeOptimization codeOptimization)\n        {\n            if (CodeOptimization.Debug == codeOptimization)\n            {\n                CompilationPipeline.codeOptimization = CodeOptimization.Release;\n            }\n            else\n            {\n                CompilationPipeline.codeOptimization = CodeOptimization.Debug;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/MaskFieldGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Pool;\nusing System.Text;\n\nnamespace UnityEditor\n{\n    // Class for storing state for mask menus so we can get the info back to OnGUI from the user selection\n    internal static class MaskFieldGUI\n    {\n        // Class for storing state for mask menus so we can get the info back to OnGUI from the user selection\n        private class MaskCallbackInfo\n        {\n            // The global shared popup state\n            public static MaskCallbackInfo m_Instance;\n\n            // Name of the command event sent from the popup menu to OnGUI when user has changed selection\n            private const string kMaskMenuChangedMessage = \"MaskMenuChanged\";\n\n            // The control ID of the popup menu that is currently displayed.\n            // Used to pass selection changes back again\n            private readonly int m_ControlID;\n\n            // New mask value\n            private int m_NewMask;\n\n            // Which view should we send it to.\n            private readonly GUIView m_SourceView;\n\n            // Current drop-down reference\n            public MaskFieldDropDown m_DropDown;\n\n            // validation flag for masks that are changed externally\n            private bool m_Validate = false;\n\n            public MaskCallbackInfo(int controlID)\n            {\n                m_ControlID = controlID;\n                m_SourceView = GUIView.current;\n            }\n\n            public static int GetSelectedValueForControl(int controlID, int mask, out int changedFlags, out bool changedToValue)\n            {\n                var evt = Event.current;\n\n                // No flags are changed by default\n                changedFlags = 0;\n                changedToValue = false;\n\n                if (evt.type == EventType.ExecuteCommand && evt.commandName == kMaskMenuChangedMessage)\n                {\n                    if (m_Instance == null)\n                    {\n                        Debug.LogError(\"Mask menu has no instance\");\n                        return mask;\n                    }\n                    if (m_Instance.m_ControlID == controlID)\n                    {\n                        changedFlags = mask ^ m_Instance.m_NewMask;\n                        changedToValue = (m_Instance.m_NewMask & changedFlags) != 0;\n\n                        if (changedFlags != 0 || EditorGUI.showMixedValue)\n                        {\n                            mask = m_Instance.m_NewMask;\n                            GUI.changed = true;\n                        }\n                    }\n                }\n                return mask;\n            }\n\n            internal void SetMaskValueDelegate(object userData, string[] options, int selected)\n            {\n                int[] optionMaskValues = (int[])userData;\n                m_NewMask = optionMaskValues[selected];\n\n                if (m_SourceView)\n                    m_SourceView.SendEvent(EditorGUIUtility.CommandEvent(kMaskMenuChangedMessage));\n            }\n\n            public void UpdateFlagChanges(int controlID, int mask, int[] optionMaskValues)\n            {\n                var evt = Event.current;\n\n                if (evt.type == EventType.ExecuteCommand)\n                {\n                    m_Validate = true;\n                }\n                // This code  is responsible for verifying whether the incoming mask value differs from the one that is currently selected in the dropdown menu.\n                // When these values do not match, it serves as confirmation that the incoming value has been modified.\n                // Subsequently, we proceed to update the dropdown menu to reflect these changes.\n                else if (evt.type == EventType.Repaint && m_Validate)\n                {\n                    if (m_DropDown == null)\n                    {\n                        return;\n                    }\n\n                    if (mask != m_NewMask && m_ControlID == controlID)\n                        m_DropDown.UpdateMaskValues(mask, optionMaskValues);\n\n                    m_Validate = false;\n                }\n            }\n        }\n\n        /// Make a field for a generic mask.\n        internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, GUIStyle style, bool autoSelectEverything = true)\n        {\n            int dummyInt;\n            bool dummyBool;\n            return DoMaskField(position, controlID, mask, flagNames, style, out dummyInt, out dummyBool, autoSelectEverything);\n        }\n\n        internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, int[] flagValues, GUIStyle style, bool autoSelectEverything = true)\n        {\n            int dummyInt;\n            bool dummyBool;\n            return DoMaskField(position, controlID, mask, flagNames, flagValues, style, out dummyInt, out dummyBool, autoSelectEverything: autoSelectEverything);\n        }\n\n        internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, GUIStyle style, out int changedFlags, out bool changedToValue, bool autoSelectEverything = true)\n        {\n            var flagValues = new int[flagNames.Length];\n            for (int i = 0; i < flagValues.Length; ++i)\n                flagValues[i] = (1 << i);\n\n            return DoMaskField(position, controlID, mask, flagNames, flagValues, style, out changedFlags, out changedToValue, autoSelectEverything: autoSelectEverything);\n        }\n\n        internal static void DestroyMaskCallBackInfo()\n        {\n            MaskCallbackInfo.m_Instance = null;\n        }\n\n        /// Make a field for a generic mask.\n        /// This version also gives you back which flags were changed and what they were changed to.\n        /// This is useful if you want to make the same change to multiple objects.\n        internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, int[] flagValues, GUIStyle style, out int changedFlags, out bool changedToValue, Type enumType = null, bool autoSelectEverything = true)\n        {\n            mask = MaskCallbackInfo.GetSelectedValueForControl(controlID, mask, out changedFlags, out changedToValue);\n\n            GetMenuOptions(mask, flagNames, flagValues, out var buttonText, out var buttonTextMixed, out var optionNames, out var optionMaskValues, out _, enumType, autoSelectEverything);\n\n            // This checks and update flags changes that are modified out of dropdown menu\n            if (MaskCallbackInfo.m_Instance != null)\n                MaskCallbackInfo.m_Instance.UpdateFlagChanges(controlID, mask, optionMaskValues);\n\n            Event evt = Event.current;\n            if (evt.type == EventType.Repaint)\n            {\n                var buttonContent = EditorGUI.showMixedValue ? EditorGUI.mixedValueContent : DoMixedLabel(buttonText, buttonTextMixed, position, style);\n                style.Draw(position, buttonContent, controlID, false, position.Contains(evt.mousePosition));\n            }\n            else if ((evt.type == EventType.MouseDown && position.Contains(evt.mousePosition)) || evt.MainActionKeyForControl(controlID))\n            {\n                MaskCallbackInfo.m_Instance = new MaskCallbackInfo(controlID);\n                MaskCallbackInfo.m_Instance.m_DropDown = new MaskFieldDropDown(optionNames, flagValues, optionMaskValues, mask, MaskCallbackInfo.m_Instance.SetMaskValueDelegate, autoSelectEverything);\n                PopupWindow.Show(position, MaskCallbackInfo.m_Instance.m_DropDown);\n            }\n\n            return mask;\n        }\n\n        private static readonly List<string[]> s_OptionNames = new List<string[]>();\n        private static readonly List<int[]> s_OptionValues = new List<int[]>();\n        private static readonly List<int[]> s_SelectedOptions = new List<int[]>();\n        private static readonly HashSet<int> s_SelectedOptionsSet = new HashSet<int>();\n\n        private static T[] GetBuffer<T>(List<T[]> pool, int bufferLength)\n        {\n            for (int i = pool.Count; i <= bufferLength; ++i)\n                pool.Add(null);\n            if (pool[bufferLength] == null)\n                pool[bufferLength] = new T[bufferLength];\n            var buffer = pool[bufferLength];\n            for (int i = 0, length = buffer.Length; i < length; ++i)\n                buffer[i] = default(T);\n            return buffer;\n        }\n\n        internal static void GetMaskButtonValue(int mask, string[] flagNames, int[] flagValues, out string buttonText, out string buttonMixedValuesText)\n        {\n            const int everythingValue = ~0;\n            bool hasNothingName = flagValues[0] == 0;\n            bool hasEverythingName = flagValues[flagValues.Length - 1] == everythingValue;\n\n            var nothingName = (hasNothingName ? flagNames[0] : \"Nothing\");\n            var everythingName = (hasEverythingName ? flagNames[flagValues.Length - 1] : \"Everything\");\n\n            var flagCount = flagNames.Length - (hasNothingName ? 1 : 0) - (hasEverythingName ? 1 : 0);\n\n            var flagStartIndex = (hasNothingName ? 1 : 0);\n            var flagEndIndex = flagStartIndex + flagCount;\n\n            var flagMask = 0; // Disjunction of all flags (except 0 and everythingValue)\n            var intermediateMask = 0; // Mask used to compute new mask value for each options\n            var usedFlags = ListPool<int>.Get();\n\n            buttonText = null;\n            buttonMixedValuesText = null;\n\n            for (var flagIndex = flagStartIndex; flagIndex < flagEndIndex; flagIndex++)\n            {\n                var flagValue = flagValues[flagIndex];\n                flagMask |= flagValue;\n\n                if (mask == flagValues[flagIndex])\n                    buttonText = flagNames[flagIndex];\n\n                if ((mask & flagValue) == flagValue)\n                {\n\n                    intermediateMask |= flagValue;\n                    usedFlags.Add(flagIndex);\n                }\n            }\n\n            if (buttonText == null)\n            {\n                if (flagMask == intermediateMask)\n                {\n                    // If all of the available flags are set then show the Everything name.\n                    buttonText = everythingName;\n                }\n                else if (intermediateMask == 0)\n                {\n                    // If the mask is 0 or none of the actual flags are set we use the nothing name.\n                    buttonText = nothingName;\n                }\n                else\n                {\n                    buttonText = \"Mixed...\";\n\n                    // Extract mixed labels\n                    var sb = GenericPool<StringBuilder>.Get();\n                    sb.Append(flagNames[usedFlags[0]]);\n                    for (int i = 1; i < usedFlags.Count; ++i)\n                    {\n                        sb.Append(\", \");\n                        sb.Append(flagNames[usedFlags[i]]);\n                    }\n                    buttonMixedValuesText = sb.ToString();\n\n                    sb.Clear();\n                    GenericPool<StringBuilder>.Release(sb);\n                }\n            }\n\n            ListPool<int>.Release(usedFlags);\n        }\n\n        internal static GUIContent DoMixedLabel(string label, string mixedLabel, Rect rect, GUIStyle style)\n        {\n            if (mixedLabel == null)\n                return EditorGUIUtility.TempContent(label);\n\n            var content = EditorGUIUtility.TempContent(mixedLabel);\n            var size = style.CalcSize(content);\n\n            // If the label is too large to fit then revert back to the shorter label\n            if (size.x > rect.width)\n                content = EditorGUIUtility.TempContent(label);\n\n            return content;\n        }\n        internal static void CalculateMaskValues(int mask, int[] flagValues, ref int[] optionMaskValues)\n        {\n            uint selectedValue = (uint)mask;\n\n            var flagStartIndex = 0;\n            if (flagValues[0] == 0)\n                flagStartIndex++;\n            if (flagValues.Length > 1 && flagValues[1] == -1)\n                flagStartIndex++;\n\n            if (mask == ~0)\n            {\n                uint allLayersMask = 0;\n                for (var flagIndex = flagStartIndex; flagIndex < flagValues.Length; flagIndex++)\n                {\n                    allLayersMask |= (uint)flagValues[flagIndex];\n                }\n\n                selectedValue = allLayersMask;\n            }\n\n            var flagEndIndex = flagStartIndex + optionMaskValues.Length - 2;\n\n            for (var flagIndex = flagStartIndex; flagIndex < flagEndIndex; flagIndex++)\n            {\n                uint flagValue = (uint)flagValues[flagIndex];\n\n                bool flagSet = ((selectedValue & flagValue) == flagValue);\n\n                optionMaskValues[flagIndex-flagStartIndex+2] = (int)(flagSet ? selectedValue & ~flagValue : selectedValue | flagValue);\n            }\n        }\n\n        internal static void GetMenuOptions(int mask, string[] flagNames, int[] flagValues,\n            out string buttonText, out string buttonMixedValuesText, out string[] optionNames, out int[] optionMaskValues, out int[] selectedOptions, Type enumType = null, bool autoSelectEverything = true)\n        {\n            const int everythingValue = ~0;\n            bool hasNothingName = flagValues[0] == 0;\n            bool hasEverythingName = flagValues[flagValues.Length - 1] == everythingValue;\n\n            var nothingName = (hasNothingName ? flagNames[0] : \"Nothing\");\n            var everythingName = (hasEverythingName ? flagNames[flagValues.Length - 1] : \"Everything\");\n\n            var optionCount = flagNames.Length + (hasNothingName ? 0 : 1) + (hasEverythingName ? 0 : 1);\n            var flagCount = flagNames.Length - (hasNothingName ? 1 : 0) - (hasEverythingName ? 1 : 0);\n\n            // These indices refer to flags that are not 0 and everythingValue\n            var flagStartIndex = (hasNothingName ? 1 : 0);\n            var flagEndIndex = flagStartIndex + flagCount;\n\n            // Options names\n            optionNames = GetBuffer(s_OptionNames, optionCount);\n            optionNames[0] = nothingName;\n            optionNames[1] = everythingName;\n            for (var flagIndex = flagStartIndex; flagIndex < flagEndIndex; flagIndex++)\n            {\n                var optionIndex = flagIndex - flagStartIndex + 2;\n                optionNames[optionIndex] = flagNames[flagIndex];\n            }\n\n            var flagMask = 0; // Disjunction of all flags (except 0 and everythingValue)\n            var intermediateMask = 0; // Mask used to compute new mask value for each options\n\n            // Selected options\n            s_SelectedOptionsSet.Clear();\n            for (var flagIndex = flagStartIndex; flagIndex < flagEndIndex; flagIndex++)\n            {\n                var flagValue = flagValues[flagIndex];\n                flagMask |= flagValue;\n                if ((mask & flagValue) == flagValue)\n                {\n                    var optionIndex = flagIndex - flagStartIndex + 2;\n                    s_SelectedOptionsSet.Add(optionIndex);\n                    intermediateMask |= flagValue;\n                }\n            }\n\n            // Button text\n            buttonText = null;\n            buttonMixedValuesText = null;\n            for (var flagIndex = flagStartIndex; flagIndex < flagEndIndex; flagIndex++)\n            {\n                // Check if a specific value is set.\n                if (mask == flagValues[flagIndex])\n                {\n                    buttonText = flagNames[flagIndex];\n                }\n            }\n\n            if (buttonText == null)\n            {\n                if (flagMask == intermediateMask && autoSelectEverything)\n                {\n                    // If all of the available flags are set then show the Everything name.\n                    s_SelectedOptionsSet.Add(1);\n                    buttonText = everythingName;\n                }\n                else if (mask == 0 || s_SelectedOptionsSet.Count == 0)\n                {\n                    // If the mask is 0 or none of the actual flags are set we use the nothing name.\n                    s_SelectedOptionsSet.Add(0);\n                    buttonText = nothingName;\n                }\n                else\n                {\n                    buttonText = \"Mixed...\";\n\n                    // Extract mixed labels\n                    var sb = GenericPool<StringBuilder>.Get();\n\n                    var iterator = s_SelectedOptionsSet.GetEnumerator();\n                    iterator.MoveNext();\n\n                    sb.Append(flagNames[iterator.Current + flagStartIndex - 2]);\n                    while(iterator.MoveNext())\n                    {\n                        sb.Append(\", \");\n                        sb.Append(flagNames[iterator.Current + flagStartIndex - 2]);\n                    }\n                    buttonMixedValuesText = sb.ToString();\n\n                    sb.Clear();\n                    GenericPool<StringBuilder>.Release(sb);\n                }\n            }\n\n            selectedOptions = GetBuffer(s_SelectedOptions, s_SelectedOptionsSet.Count);\n            var x = 0;\n            foreach (var selected in s_SelectedOptionsSet)\n            {\n                selectedOptions[x] = selected;\n                ++x;\n            }\n\n            // Option mask values\n            optionMaskValues = GetBuffer(s_OptionValues, optionCount);\n            optionMaskValues[0] = 0;\n            optionMaskValues[1] = everythingValue;\n            if (EditorGUI.showMixedValue)\n                intermediateMask = 0;\n\n            CalculateMaskValues(intermediateMask, flagValues, ref optionMaskValues);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ObjectField.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.SceneManagement;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    public sealed partial class EditorGUI\n    {\n        static private GUIContent s_SceneMismatch = EditorGUIUtility.TrTextContent(\"Scene mismatch (cross scene references not supported)\");\n        static private GUIContent s_TypeMismatch = EditorGUIUtility.TrTextContent(\"Type mismatch\");\n        static private GUIContent s_Select = EditorGUIUtility.TrTextContent(\"Select\");\n\n        const float k_NullObjectReferenceOpacity = 0.7f;\n\n        [Flags]\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal enum ObjectFieldValidatorOptions\n        {\n            None = 0,\n            ExactObjectTypeValidation = (1 << 0)\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal delegate Object ObjectFieldValidator(Object[] references, System.Type objType, SerializedProperty property, ObjectFieldValidatorOptions options);\n\n        // Takes object directly, no SerializedProperty.\n        internal static Object DoObjectField(Rect position, Rect dropRect, int id, Object obj, Object objBeingEdited, System.Type objType, ObjectFieldValidator validator, bool allowSceneObjects, GUIStyle style = null)\n        {\n            return DoObjectField(position, dropRect, id, obj, objBeingEdited, objType, null, validator, allowSceneObjects, style != null ? style : EditorStyles.objectField);\n        }\n\n        internal static Object DoObjectField(Rect position, Rect dropRect, int id, Object obj, Object objBeingEdited, System.Type objType, ObjectFieldValidator validator, bool allowSceneObjects, System.Type additionalType, GUIStyle style = null)\n        {\n            return DoObjectField(position, dropRect, id, obj, objBeingEdited, objType, additionalType, null, validator, allowSceneObjects, style != null ? style : EditorStyles.objectField);\n        }\n\n        // Takes SerializedProperty, no direct reference to object.\n        internal static Object DoObjectField(Rect position, Rect dropRect, int id, System.Type objType, SerializedProperty property, ObjectFieldValidator validator, bool allowSceneObjects, GUIStyle style = null)\n        {\n            return DoObjectField(position, dropRect, id, null, null, objType, property, validator, allowSceneObjects, style != null ? style : EditorStyles.objectField);\n        }\n\n        internal enum ObjectFieldVisualType { IconAndText, LargePreview, MiniPreview }\n\n        // when current event is mouse click, this function pings the object, or\n        // if shift/control is pressed and object is a texture, pops up a large texture\n        // preview window\n        internal static void PingObjectOrShowPreviewOnClick(Object targetObject, Rect position)\n        {\n            if (targetObject == null)\n                return;\n\n            Event evt = Event.current;\n            // ping object\n            bool anyModifiersPressed = evt.shift || evt.control;\n            if (!anyModifiersPressed)\n            {\n                EditorGUIUtility.PingObject(targetObject);\n                return;\n            }\n\n            // show large object preview popup; right now only for textures\n            if (targetObject is Texture)\n            {\n                PopupWindowWithoutFocus.Show(\n                    new RectOffset(6, 3, 0, 3).Add(position),\n                    new ObjectPreviewPopup(targetObject),\n                    new[] { PopupLocation.Left, PopupLocation.Below, PopupLocation.Right });\n            }\n        }\n\n        internal static void PingObjectInSceneViewOnClick(Material targetMaterial)\n        {\n            var sceneView = SceneView.lastActiveSceneView;\n            if (sceneView == null || targetMaterial == null)\n                return;\n\n            sceneView.isPingingObject = true;\n            sceneView.pingStartTime = Time.realtimeSinceStartup;\n            sceneView.submeshOutlineMaterialId = targetMaterial.GetInstanceID();\n        }\n\n        static Object AssignSelectedObject(SerializedProperty property, ObjectFieldValidator validator, System.Type objectType, Event evt)\n        {\n            Object[] references = { ObjectSelector.GetCurrentObject() };\n            Object assigned = validator(references, objectType, property, ObjectFieldValidatorOptions.None);\n\n            // Assign the value\n            if (property != null)\n                property.objectReferenceValue = assigned;\n\n            GUI.changed = true;\n            evt.Use();\n            return assigned;\n        }\n\n        static private Rect GetButtonRect(ObjectFieldVisualType visualType, Rect position)\n        {\n            switch (visualType)\n            {\n                case ObjectFieldVisualType.IconAndText:\n                    return new Rect(position.xMax - 19, position.y, 19, position.height);\n                case ObjectFieldVisualType.MiniPreview:\n                    return new Rect(position.xMax - 14, position.y, 14, position.height);\n                case ObjectFieldVisualType.LargePreview:\n                    return new Rect(position.xMax - 36, position.yMax - 14, 36, 14);\n                default:\n                    throw new ArgumentOutOfRangeException();\n            }\n        }\n\n        static bool HasValidScript(UnityEngine.Object obj)\n        {\n            MonoScript script = MonoScript.FromScriptedObject(obj);\n            if (script == null)\n            {\n                return false;\n            }\n            Type type = script.GetClass();\n            if (type == null)\n            {\n                return false;\n            }\n            return true;\n        }\n\n        static bool ValidDroppedObject(Object[] references, System.Type objType, out string errorString)\n        {\n            errorString = \"\";\n            if (references == null || references.Length == 0)\n            {\n                return true;\n            }\n\n            var reference = references[0];\n            Object obj = EditorUtility.InstanceIDToObject(reference.GetInstanceID());\n            if (obj is MonoBehaviour || obj is ScriptableObject)\n            {\n                if (!HasValidScript(obj))\n                {\n                    errorString = $\"Type cannot be found: {reference.GetType()}. Containing file and class name must match.\";\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        // Timeline package is using this internal overload so can't remove until that's fixed.\n        internal static Object DoObjectField(Rect position, Rect dropRect, int id, Object obj, System.Type objType, SerializedProperty property, ObjectFieldValidator validator, bool allowSceneObjects, GUIStyle style)\n        {\n            return DoObjectField(position, dropRect, id, objType, property, validator, allowSceneObjects);\n        }\n\n        // This method takes either object reference directly, or via SerializedObject.\n        // Since it's not easy to know which parameters are mutually exclusively used, this method is\n        // private and internal/public methods instead EITHER take SerializedObject OR direct reference.\n        static Object DoObjectField(Rect position, Rect dropRect, int id, Object obj, Object objBeingEdited, System.Type objType, SerializedProperty property, ObjectFieldValidator validator, bool allowSceneObjects, GUIStyle style)\n        {\n            return DoObjectField(position, dropRect, id, obj, objBeingEdited, objType, null, property, validator, allowSceneObjects, style, EditorStyles.objectFieldButton);\n        }\n\n        static Object DoObjectField(Rect position, Rect dropRect, int id, Object obj, Object objBeingEdited, System.Type objType, System.Type additionalType, SerializedProperty property, ObjectFieldValidator validator, bool allowSceneObjects, GUIStyle style, Action<Object> onObjectSelectorClosed, Action<Object> onObjectSelectedUpdated = null)\n        {\n            return DoObjectField(position, dropRect, id, obj, objBeingEdited, objType, additionalType, property, validator, allowSceneObjects, style, EditorStyles.objectFieldButton, onObjectSelectorClosed, onObjectSelectedUpdated);\n        }\n\n        static Object DoObjectField(Rect position, Rect dropRect, int id, Object obj, Object objBeingEdited, System.Type objType, System.Type additionalType, SerializedProperty property, ObjectFieldValidator validator, bool allowSceneObjects, GUIStyle style)\n        {\n            return DoObjectField(position, dropRect, id, obj, objBeingEdited, objType, additionalType, property, validator, allowSceneObjects, style, EditorStyles.objectFieldButton);\n        }\n\n        static Object DoObjectField(Rect position, Rect dropRect, int id, Object obj, Object objBeingEdited, System.Type objType, System.Type additionalType, SerializedProperty property, ObjectFieldValidator validator, bool allowSceneObjects, GUIStyle style, GUIStyle buttonStyle, Action<Object> onObjectSelectorClosed = null, Action<Object> onObjectSelectedUpdated = null)\n        {\n            if (validator == null)\n                validator = ValidateObjectFieldAssignment;\n            if (property != null)\n                obj = property.objectReferenceValue;\n            Event evt = Event.current;\n            EventType eventType = evt.type;\n\n            // special case test, so we continue to ping/select objects with the object field disabled\n            if (!GUI.enabled && GUIClip.enabled && (Event.current.rawType == EventType.MouseDown))\n                eventType = Event.current.rawType;\n\n            bool hasThumbnail = EditorGUIUtility.HasObjectThumbnail(objType);\n\n            // Determine visual type\n            ObjectFieldVisualType visualType = ObjectFieldVisualType.IconAndText;\n            if (hasThumbnail && position.height <= kObjectFieldMiniThumbnailHeight && position.width <= kObjectFieldMiniThumbnailWidth)\n                visualType = ObjectFieldVisualType.MiniPreview;\n            else if (hasThumbnail && position.height > kSingleLineHeight)\n                visualType = ObjectFieldVisualType.LargePreview;\n\n            Vector2 oldIconSize = EditorGUIUtility.GetIconSize();\n            if (visualType == ObjectFieldVisualType.IconAndText)\n                EditorGUIUtility.SetIconSize(new Vector2(12, 12));  // Have to be this small to fit inside a single line height ObjectField\n            else if (visualType == ObjectFieldVisualType.LargePreview)\n                EditorGUIUtility.SetIconSize(new Vector2(64, 64));\n\n            if ((eventType == EventType.ContextClick && visualType == ObjectFieldVisualType.IconAndText) &&\n                position.Contains(Event.current.mousePosition))\n            {\n                var actualObject = property != null ? property.objectReferenceValue : obj;\n                var contextMenu = new GenericMenu();\n\n                if (FillPropertyContextMenu(property, null, contextMenu) != null)\n                    contextMenu.AddSeparator(\"\");\n                contextMenu.AddItem(GUIContent.Temp(\"Properties...\"), false, () => PropertyEditor.OpenPropertyEditor(actualObject));\n                contextMenu.DropDown(position);\n                Event.current.Use();\n            }\n\n            switch (eventType)\n            {\n                case EventType.DragExited:\n                    if (GUI.enabled)\n                        HandleUtility.Repaint();\n\n                    break;\n                case EventType.DragUpdated:\n                case EventType.DragPerform:\n\n                    if (eventType == EventType.DragPerform)\n                    {\n                        string errorString;\n                        if (!ValidDroppedObject(DragAndDrop.objectReferences, objType, out errorString))\n                        {\n                            Object reference = DragAndDrop.objectReferences[0];\n                            EditorUtility.DisplayDialog(\"Can't assign script\", errorString, \"OK\");\n                            break;\n                        }\n                    }\n\n                    if (dropRect.Contains(Event.current.mousePosition) && GUI.enabled)\n                    {\n                        Object[] references = DragAndDrop.objectReferences;\n                        Object validatedObject = validator(references, objType, property, ObjectFieldValidatorOptions.None);\n\n                        if (validatedObject != null)\n                        {\n                            // If scene objects are not allowed and object is a scene object then clear\n                            if (!allowSceneObjects && !EditorUtility.IsPersistent(validatedObject))\n                                validatedObject = null;\n                        }\n\n                        if (validatedObject != null)\n                        {\n                            if (DragAndDrop.visualMode == DragAndDropVisualMode.None)\n                                DragAndDrop.visualMode = DragAndDropVisualMode.Generic;\n\n                            if (eventType == EventType.DragPerform)\n                            {\n                                if (property != null)\n                                    property.objectReferenceValue = validatedObject;\n                                else\n                                    obj = validatedObject;\n\n                                GUI.changed = true;\n                                DragAndDrop.AcceptDrag();\n                                DragAndDrop.activeControlID = 0;\n                            }\n                            else\n                            {\n                                DragAndDrop.activeControlID = id;\n                            }\n                            Event.current.Use();\n                        }\n                    }\n                    break;\n                case EventType.MouseDown:\n                    if (position.Contains(Event.current.mousePosition) && Event.current.button == 0)\n                    {\n                        // Get button rect for Object Selector\n                        Rect buttonRect = GetButtonRect(visualType, position);\n\n                        EditorGUIUtility.editingTextField = false;\n\n                        if (buttonRect.Contains(Event.current.mousePosition))\n                        {\n                            if (GUI.enabled)\n                            {\n                                GUIUtility.keyboardControl = id;\n                                var types = additionalType == null ? new Type[] {objType} : new Type[] { objType, additionalType };\n                                if (property != null)\n                                    ObjectSelector.get.Show(types, property, allowSceneObjects, onObjectSelectorClosed: onObjectSelectorClosed, onObjectSelectedUpdated: onObjectSelectedUpdated);\n                                else\n                                    ObjectSelector.get.Show(obj, types, objBeingEdited, allowSceneObjects, onObjectSelectorClosed: onObjectSelectorClosed, onObjectSelectedUpdated: onObjectSelectedUpdated);\n                                ObjectSelector.get.objectSelectorID = id;\n\n                                evt.Use();\n                                GUIUtility.ExitGUI();\n                            }\n                        }\n                        else\n                        {\n                            Object actualTargetObject = property != null ? property.objectReferenceValue : obj;\n                            Component com = actualTargetObject as Component;\n                            if (com)\n                                actualTargetObject = com.gameObject;\n                            if (showMixedValue)\n                                actualTargetObject = null;\n\n                            // One click shows where the referenced object is, or pops up a preview\n                            if (Event.current.clickCount == 1)\n                            {\n                                GUIUtility.keyboardControl = id;\n\n                                PingObjectOrShowPreviewOnClick(actualTargetObject, position);\n                                var selectedMaterial = actualTargetObject as Material;\n                                if (selectedMaterial != null)\n                                    PingObjectInSceneViewOnClick(selectedMaterial);\n                                evt.Use();\n                            }\n                            // Double click opens the asset in external app or changes selection to referenced object\n                            else if (Event.current.clickCount == 2)\n                            {\n                                if (actualTargetObject)\n                                {\n                                    AssetDatabase.OpenAsset(actualTargetObject);\n                                    evt.Use();\n                                    GUIUtility.ExitGUI();\n                                }\n                            }\n                        }\n                    }\n                    break;\n                case EventType.ExecuteCommand:\n                    string commandName = evt.commandName;\n                    if (commandName == ObjectSelector.ObjectSelectorUpdatedCommand && ObjectSelector.get.objectSelectorID == id && (property == null || !property.isScript))\n                        return AssignSelectedObject(property, validator, objType, evt);\n                    else if (commandName == ObjectSelector.ObjectSelectorClosedCommand && ObjectSelector.get.objectSelectorID == id && property != null && property.isScript)\n                    {\n                        if (ObjectSelector.get.GetInstanceID() == 0)\n                        {\n                            // User canceled object selection; don't apply\n                            evt.Use();\n                            break;\n                        }\n                        return AssignSelectedObject(property, validator, objType, evt);\n                    }\n                    else if ((evt.commandName == EventCommandNames.Delete || evt.commandName == EventCommandNames.SoftDelete) && GUIUtility.keyboardControl == id)\n                    {\n                        if (property != null)\n                            property.objectReferenceValue = null;\n                        else\n                            obj = null;\n\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.ValidateCommand:\n                    if ((evt.commandName == EventCommandNames.Delete || evt.commandName == EventCommandNames.SoftDelete) &&  GUIUtility.keyboardControl == id)\n                    {\n                        evt.Use();\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (GUIUtility.keyboardControl == id)\n                    {\n                        if (evt.keyCode == KeyCode.Backspace || (evt.keyCode == KeyCode.Delete && (evt.modifiers & EventModifiers.Shift) == 0))\n                        {\n                            if (property != null)\n                            {\n                                if (property.propertyPath.EndsWith(\"]\"))\n                                {\n                                    var parentArrayPropertyPath = property.propertyPath.Substring(0, property.propertyPath.LastIndexOf(\".Array.data[\", StringComparison.Ordinal));\n                                    var parentArrayProperty = property.serializedObject.FindProperty(parentArrayPropertyPath);\n                                    bool isReorderableList = PropertyHandler.s_reorderableLists.ContainsKey(ReorderableListWrapper.GetPropertyIdentifier(parentArrayProperty));\n\n                                    // If it's an element of an non-orderable array and it is displayed inside a list, remove that element from the array (cases 1379541 & 1335322)\n                                    if (!isReorderableList && GUI.isInsideList && GetInsideListDepth() == parentArrayProperty.depth)\n                                        TargetChoiceHandler.DeleteArrayElement(property);\n                                    else\n                                        property.objectReferenceValue = null;\n                                }\n                                else\n                                {\n                                    property.objectReferenceValue = null;\n                                }\n                            }\n                            else\n                                obj = null;\n\n                            GUI.changed = true;\n                            evt.Use();\n                        }\n\n                        // Apparently we have to check for the character being space instead of the keyCode,\n                        // otherwise the Inspector will maximize upon pressing space.\n                        if (evt.MainActionKeyForControl(id))\n                        {\n                            var types = additionalType == null ? new Type[] {objType} : new Type[] { objType, additionalType };\n                            if (property != null)\n                                ObjectSelector.get.Show(types, property, allowSceneObjects);\n                            else\n                                ObjectSelector.get.Show(obj, types, objBeingEdited, allowSceneObjects);\n                            ObjectSelector.get.objectSelectorID = id;\n                            evt.Use();\n                            GUIUtility.ExitGUI();\n                        }\n                    }\n                    break;\n                case EventType.Repaint:\n                    GUIContent temp;\n                    if (showMixedValue)\n                    {\n                        temp = s_MixedValueContent;\n                    }\n                    else\n                    {\n                        temp = EditorGUIUtility.ObjectContent(obj, objType, property, validator);\n                    }\n\n                    var contentColor = GUI.contentColor;\n                    var oldAlpha = contentColor.a;\n                    try\n                    {\n                        // Show label with 70% opacity when null. (UUM-16396)\n                        if (obj == null)\n                        {\n                            contentColor.a = k_NullObjectReferenceOpacity;\n                            GUI.contentColor = contentColor;\n                        }\n                        switch (visualType)\n                        {\n                            case ObjectFieldVisualType.IconAndText:\n                                BeginHandleMixedValueContentColor();\n                                style.Draw(position, temp, id, DragAndDrop.activeControlID == id, position.Contains(Event.current.mousePosition));\n\n                                Rect buttonRect = buttonStyle.margin.Remove(GetButtonRect(visualType, position));\n                                buttonStyle.Draw(buttonRect, GUIContent.none, id, DragAndDrop.activeControlID == id, buttonRect.Contains(Event.current.mousePosition));\n                                EndHandleMixedValueContentColor();\n                                break;\n                            case ObjectFieldVisualType.LargePreview:\n                                DrawObjectFieldLargeThumb(position, id, obj, temp);\n                                break;\n                            case ObjectFieldVisualType.MiniPreview:\n                                DrawObjectFieldMiniThumb(position, id, obj, temp);\n                                break;\n                            default:\n                                throw new ArgumentOutOfRangeException();\n                        }\n                    }\n                    finally\n                    {\n                        contentColor.a = oldAlpha;\n                        GUI.contentColor = contentColor;\n                    }\n                    break;\n            }\n\n            EditorGUIUtility.SetIconSize(oldIconSize);\n\n            return obj;\n        }\n\n        private static void DrawObjectFieldLargeThumb(Rect position, int id, Object obj, GUIContent content)\n        {\n            GUIStyle thumbStyle = EditorStyles.objectFieldThumb;\n            thumbStyle.Draw(position, GUIContent.none, id, DragAndDrop.activeControlID == id, position.Contains(Event.current.mousePosition));\n\n            if (obj != null && !showMixedValue)\n            {\n                Matrix4x4 guiMatrix = GUI.matrix; // Initial matrix is saved in order to be able to reset it to default\n                bool isSprite = obj is Sprite;\n                bool alphaIsTransparencyTex2D = (obj is Texture2D && (obj as Texture2D).alphaIsTransparency);\n                Rect thumbRect = thumbStyle.padding.Remove(position);\n\n                Texture2D t2d = AssetPreview.GetAssetPreview(obj);\n                if (t2d != null)\n                {\n                    // A checkerboard background is drawn behind transparent textures (for visibility)\n                    if (isSprite || t2d.alphaIsTransparency || alphaIsTransparencyTex2D)\n                        GUI.DrawTexture(thumbRect, EditorGUI.transparentCheckerTexture, ScaleMode.StretchToFill, false);\n\n                    // Draw asset preview (scaled to fit inside the frame)\n                    // GUIStyle.none.Draw is used to allow the asset preview to be caught by AutomatedWindow\n                    Vector2 defaultSize = Vector2.one * EditorGUI.kObjectFieldThumbnailHeight;\n                    GUIUtility.ScaleAroundPivot(thumbRect.size / defaultSize, thumbRect.position);\n                    thumbRect.size = defaultSize; // GUIStyle.none.Draw does not scale, the matrix does. Omitting this reports an incorrect Rect size.\n                    GUIStyle.none.Draw(thumbRect, t2d, false, false, false, false);\n                    GUI.matrix = guiMatrix;\n                }\n                else\n                {\n                    // Preview not loaded -> Draw icon\n                    if (isSprite || alphaIsTransparencyTex2D)\n                    {\n                        // A checkerboard background is drawn behind transparent textures (for visibility)\n                        GUI.DrawTexture(thumbRect, EditorGUI.transparentCheckerTexture, ScaleMode.StretchToFill, false);\n                        GUI.DrawTexture(thumbRect, content.image, ScaleMode.StretchToFill, true);\n                    }\n                    else\n                        DrawPreviewTexture(thumbRect, content.image);\n\n                    // Keep repainting until the object field has a proper preview\n                    HandleUtility.Repaint();\n                }\n            }\n            else\n            {\n                GUIStyle s2 = thumbStyle.name + \"Overlay\";\n                BeginHandleMixedValueContentColor();\n\n                s2.Draw(position, content, id);\n                EndHandleMixedValueContentColor();\n            }\n            GUIStyle s3 = thumbStyle.name + \"Overlay2\";\n            s3.Draw(position, s_Select, id);\n        }\n\n        private static void DrawObjectFieldMiniThumb(Rect position, int id, Object obj, GUIContent content)\n        {\n            GUIStyle thumbStyle = EditorStyles.objectFieldMiniThumb;\n            position.width = EditorGUI.kObjectFieldMiniThumbnailWidth;\n            BeginHandleMixedValueContentColor();\n            bool hover = obj != null; // we use hover texture for enhancing the border if we have a reference\n            bool on =  DragAndDrop.activeControlID == id;\n            bool keyFocus = GUIUtility.keyboardControl == id;\n            thumbStyle.Draw(position, hover, false, on, keyFocus);\n            EndHandleMixedValueContentColor();\n\n            if (obj != null && !showMixedValue)\n            {\n                Rect thumbRect = new Rect(position.x + 1, position.y + 1, position.height - 2, position.height - 2); // subtract 1 px border\n                Texture2D t2d = content.image as Texture2D;\n                if (t2d != null && t2d.alphaIsTransparency)\n                    DrawTextureTransparent(thumbRect, t2d);\n                else\n                    DrawPreviewTexture(thumbRect, content.image);\n\n                // Tooltip\n                if (thumbRect.Contains(Event.current.mousePosition))\n                    GUI.Label(thumbRect, GUIContent.Temp(string.Empty, \"Ctrl + Click to show preview\"));\n            }\n        }\n\n        internal static Object DoDropField(Rect position, int id, System.Type objType, ObjectFieldValidator validator, bool allowSceneObjects, GUIStyle style)\n        {\n            if (validator == null)\n                validator = ValidateObjectFieldAssignment;\n            Event evt = Event.current;\n            EventType eventType = evt.type;\n\n            // special case test, so we continue to ping/select objects with the object field disabled\n            if (!GUI.enabled && GUIClip.enabled && (Event.current.rawType == EventType.MouseDown))\n                eventType = Event.current.rawType;\n\n            switch (eventType)\n            {\n                case EventType.DragExited:\n                    if (GUI.enabled)\n                        HandleUtility.Repaint();\n                    break;\n                case EventType.DragUpdated:\n                case EventType.DragPerform:\n\n                    if (position.Contains(Event.current.mousePosition) && GUI.enabled)\n                    {\n                        Object[] references = DragAndDrop.objectReferences;\n                        Object validatedObject = validator(references, objType, null, ObjectFieldValidatorOptions.None);\n\n                        if (validatedObject != null)\n                        {\n                            // If scene objects are not allowed and object is a scene object then clear\n                            if (!allowSceneObjects && !EditorUtility.IsPersistent(validatedObject))\n                                validatedObject = null;\n                        }\n\n                        if (validatedObject != null)\n                        {\n                            DragAndDrop.visualMode = DragAndDropVisualMode.Generic;\n                            if (eventType == EventType.DragPerform)\n                            {\n                                GUI.changed = true;\n                                DragAndDrop.AcceptDrag();\n                                DragAndDrop.activeControlID = 0;\n                                Event.current.Use();\n                                return validatedObject;\n                            }\n                            else\n                            {\n                                DragAndDrop.activeControlID = id;\n                                Event.current.Use();\n                            }\n                        }\n                    }\n                    break;\n                case EventType.Repaint:\n                    style.Draw(position, GUIContent.none, id, DragAndDrop.activeControlID == id);\n                    break;\n            }\n            return null;\n        }\n    }\n\n    internal class ObjectPreviewPopup : PopupWindowContent\n    {\n        readonly Editor m_Editor;\n        readonly GUIContent m_ObjectName;\n        const float kToolbarHeight = 22f;\n\n        internal class Styles\n        {\n            public readonly GUIStyle toolbar = \"preToolbar\";\n            public readonly GUIStyle toolbarText = \"ToolbarBoldLabel\";\n            public GUIStyle background = \"preBackground\";\n        }\n        Styles s_Styles;\n\n        public ObjectPreviewPopup(Object previewObject)\n        {\n            if (previewObject == null)\n            {\n                Debug.LogError(\"ObjectPreviewPopup: Check object is not null, before trying to show it!\");\n                return;\n            }\n            m_ObjectName = new GUIContent(previewObject.name, AssetDatabase.GetAssetPath(previewObject));   // Show path as tooltip on label\n            m_Editor = Editor.CreateEditor(previewObject);\n        }\n\n        public override void OnClose()\n        {\n            if (m_Editor != null)\n                Editor.DestroyImmediate(m_Editor);\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            if (m_Editor == null)\n            {\n                editorWindow.Close();\n                return;\n            }\n\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            // Toolbar\n            Rect toolbarRect = EditorGUILayout.BeginHorizontal(GUIContent.none, s_Styles.toolbar, GUILayout.Height(kToolbarHeight));\n            {\n                GUILayout.FlexibleSpace();\n                Rect contentRect = EditorGUILayout.BeginHorizontal();\n                m_Editor.OnPreviewSettings();\n                EditorGUILayout.EndHorizontal();\n\n                const float kPadding = 5f;\n                Rect labelRect = new Rect(toolbarRect.x + kPadding, toolbarRect.y, toolbarRect.width - contentRect.width - 2 * kPadding, toolbarRect.height);\n                Vector2 labelSize = s_Styles.toolbarText.CalcSize(m_ObjectName);\n                labelRect.width = Mathf.Min(labelRect.width, labelSize.x);\n                m_ObjectName.tooltip = m_ObjectName.text;\n                GUI.Label(labelRect, m_ObjectName, s_Styles.toolbarText);\n            }\n            EditorGUILayout.EndHorizontal();\n\n            // Object preview\n            Rect previewRect = new Rect(rect.x, rect.y + kToolbarHeight, rect.width, rect.height - kToolbarHeight);\n            m_Editor.OnPreviewGUI(previewRect, s_Styles.background);\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            return new Vector2(600f, 300f + kToolbarHeight);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/PackageExport.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEngine.Analytics;\nusing UnityEngine.Scripting;\nusing UnityEngine.UIElements;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    internal class PackageExport : EditorWindow\n    {\n        [SerializeField] private ExportPackageItem[] m_ExportPackageItems;\n        [SerializeField] private bool m_IncludeDependencies = true;\n        [SerializeField] private bool m_IncludeScripts = true;\n        [SerializeField] private TreeViewState m_TreeViewState;\n        [SerializeField] private string[] m_ProjectBrowserSelection;\n        [NonSerialized] private PackageExportTreeView m_Tree;\n        [NonSerialized] private bool m_DidScheduleUpdate = false;\n\n        public ExportPackageItem[] items { get { return m_ExportPackageItems; } }\n\n        internal static class Styles\n        {\n            public static GUIStyle title = \"LargeBoldLabel\";\n            public static GUIStyle bottomBarBg = \"ProjectBrowserBottomBarBg\";\n            public static GUIStyle topBarBg = \"OT TopBar\";\n            public static GUIStyle loadingTextStyle = \"CenteredLabel\";\n            public static GUIContent allText = EditorGUIUtility.TrTextContent(\"All\");\n            public static GUIContent noneText = EditorGUIUtility.TrTextContent(\"None\");\n            public static GUIContent includeDependenciesText = EditorGUIUtility.TrTextContent(\"Include dependencies\", \"Include all dependencies required for the selected items in the export list.\");\n            public static GUIContent includeScriptsText = EditorGUIUtility.TrTextContent(\"Include all scripts\", \"Include all project scripts in the export list to avoid potential compilation errors.\");\n            public static GUIContent header = EditorGUIUtility.TrTextContent(\"Items to Export\");\n        }\n\n        public PackageExport()\n        {\n            // Initial pos and minsize\n            position = new Rect(100, 100, 400, 300);\n            minSize = new Vector2(350, 350);\n        }\n\n        // Called from menu\n        [RequiredByNativeCode]\n        static internal void ShowExportPackage()\n        {\n            GetWindow<PackageExport>(true, \"Exporting package\").RefreshAssetList();\n        }\n\n        internal static IEnumerable<ExportPackageItem> GetAssetItemsForExport(ICollection<string> guids, bool includeDependencies, bool includeScripts)\n        {\n            // if nothing is selected, export all\n            if (0 == guids.Count)\n            {\n                string[] temp = new string[0]; // <--- I dont get this API\n                guids = new HashSet<string>(AssetDatabase.CollectAllChildren(AssetDatabase.assetFolderGUID, temp));\n            }\n\n            ExportPackageItem[] assets = PackageUtility.BuildExportPackageItemsListWithPackageManagerWarning(guids.ToArray(), includeDependencies, true);\n\n            if (includeScripts)\n            {\n                assets = PackageUtility.BuildExportPackageItemsListWithPackageManagerWarning(\n                    guids.Union(UnityEditorInternal.InternalEditorUtility.GetAllScriptGUIDs()).ToArray(), includeDependencies, true);\n            }\n\n            // If the user exports the root Assets folder, we need to remove it from the list\n            // explicitly, as it doesnt make sense\n            assets = assets.Where(val => val.assetPath != \"Assets\").ToArray();\n\n            return assets;\n        }\n\n        void RefreshAssetList()\n        {\n            m_ExportPackageItems = null;\n        }\n\n        bool HasValidAssetList()\n        {\n            return m_ExportPackageItems != null;\n        }\n\n        bool CheckAssetExportList()\n        {\n            if (m_ExportPackageItems.Length == 0)\n            {\n                GUILayout.Space(20f);\n                GUILayout.BeginVertical(EditorStyles.helpBox);\n                GUILayout.Label(\"Nothing to export!\", EditorStyles.boldLabel);\n                GUILayout.Label(\"No assets to export were found in your project.\", \"WordWrappedLabel\");\n                GUILayout.BeginHorizontal();\n                GUILayout.FlexibleSpace();\n                if (GUILayout.Button(\"OK\"))\n                {\n                    Close();\n                    GUIUtility.ExitGUI();\n                }\n                GUILayout.EndHorizontal();\n                GUILayout.EndVertical();\n                return true;\n            }\n\n            return false;\n        }\n\n        public void OnDestroy()\n        {\n            UnscheduleBuildAssetList();\n        }\n\n        public void OnGUI()\n        {\n            if (!HasValidAssetList())\n            {\n                ScheduleBuildAssetList();\n            }\n            else if (CheckAssetExportList())\n            {\n                return;\n            }\n\n            using (new EditorGUI.DisabledScope(!HasValidAssetList()))\n            {\n                TopArea();\n                TopButtonsArea();\n            }\n\n            TreeViewArea(!HasValidAssetList());\n\n            using (new EditorGUI.DisabledScope(!HasValidAssetList()))\n            {\n                BottomArea();\n            }\n        }\n\n        void TopArea()\n        {\n            float totalTopHeight = 53f;\n            Rect r = GUILayoutUtility.GetRect(position.width, totalTopHeight);\n\n            // Background\n            GUI.Label(r, GUIContent.none, Styles.topBarBg);\n\n            // Header\n            Rect titleRect = new Rect(r.x + 5f, r.yMin, r.width, r.height);\n            GUI.Label(titleRect, Styles.header, Styles.title);\n        }\n\n        void TopButtonsArea()\n        {\n            // Background\n            GUILayout.BeginVertical();\n            GUILayout.Space(8);\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(10);\n\n            GUI.enabled = m_Tree != null ? !m_Tree.isAllItemsEnabled : true;\n            if (GUILayout.Button(Styles.allText, GUILayout.Width(50)))\n            {\n                m_Tree.SetAllEnabled(PackageExportTreeView.EnabledState.All);\n                SendAnalyticsEvent(\"selectAll\");\n            }\n            GUI.enabled = true;\n\n            GUI.enabled = m_Tree != null ? m_Tree.isAnyItemEnabled : true;\n            if (GUILayout.Button(Styles.noneText, GUILayout.Width(50)))\n            {\n                m_Tree.SetAllEnabled(PackageExportTreeView.EnabledState.None);\n                SendAnalyticsEvent(\"selectNone\");\n            }\n            GUI.enabled = true;\n\n            GUILayout.Space(10);\n            GUILayout.EndHorizontal();\n            GUILayout.Space(5);\n            GUILayout.EndVertical();\n        }\n\n        void BottomArea()\n        {\n            // Background\n            GUILayout.BeginVertical(Styles.bottomBarBg);\n            GUILayout.Space(8);\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(10);\n\n            EditorGUI.BeginChangeCheck();\n            var includeDependenciesNewValue = GUILayout.Toggle(m_IncludeDependencies, Styles.includeDependenciesText);\n            if (m_IncludeDependencies != includeDependenciesNewValue)\n            {\n                m_IncludeDependencies = includeDependenciesNewValue;\n                SendAnalyticsEvent(\"toggleIncludeDependencies\");\n            }\n\n            GUILayout.Space(5);\n            var includeScriptsNewValue = GUILayout.Toggle(m_IncludeScripts, Styles.includeScriptsText);\n            if (m_IncludeScripts != includeScriptsNewValue)\n            {\n                m_IncludeScripts = includeScriptsNewValue;\n                SendAnalyticsEvent(\"toggleIncludeScripts\");\n            }\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                RefreshAssetList();\n            }\n\n            GUILayout.FlexibleSpace();\n\n            GUI.enabled = m_Tree?.isAnyItemEnabled == true;\n            if (GUILayout.Button(EditorGUIUtility.TrTextContent(\"Export...\")))\n            {\n                string invalidChars = EditorUtility.GetInvalidFilenameChars();\n                var selectedItemWithInvalidChar = m_ExportPackageItems.FirstOrDefault(item => Path.GetFileNameWithoutExtension(item.assetPath).IndexOfAny(invalidChars.ToCharArray()) != -1 && item.enabledStatus > 0);\n                if (selectedItemWithInvalidChar != null && !EditorUtility.DisplayDialog(L10n.Tr(\"Cross platform incompatibility\"), L10n.Tr($\"The asset “{Path.GetFileNameWithoutExtension(selectedItemWithInvalidChar.assetPath)}” contains one or more characters that are not compatible across platforms: {invalidChars}\"), L10n.Tr(\"I understand\"), L10n.Tr(\"Cancel\")))\n                {\n                    GUIUtility.ExitGUI();\n                    SendAnalyticsEvent(\"exportErrorInvalidCharInAssetName\");\n                    return;\n                }\n\n                Export();\n                GUIUtility.ExitGUI();\n            }\n            GUI.enabled = true;\n\n            GUILayout.Space(10);\n            GUILayout.EndHorizontal();\n            GUILayout.Space(5);\n            GUILayout.EndVertical();\n        }\n\n        private void TreeViewArea(bool showLoadingScreen)\n        {\n            Rect treeAreaRect = GUILayoutUtility.GetRect(1, 9999, 1, 99999);\n\n            if (showLoadingScreen)\n            {\n                GUI.Label(treeAreaRect, \"Loading...\", Styles.loadingTextStyle);\n                return;\n            }\n\n            if (m_ExportPackageItems != null && m_ExportPackageItems.Length > 0)\n            {\n                if (m_TreeViewState == null)\n                    m_TreeViewState = new TreeViewState();\n\n                if (m_Tree == null)\n                    m_Tree = new PackageExportTreeView(this, m_TreeViewState, new Rect());\n\n                m_Tree.OnGUI(treeAreaRect);\n            }\n        }\n\n        private void Export()\n        {\n            string fileName = EditorUtility.SaveFilePanel(\"Export package ...\", \"\", \"\", \"unitypackage\");\n            if (fileName != \"\")\n            {\n                // build guid list\n                List<string> guids = new List<string>();\n\n                foreach (ExportPackageItem ai in m_ExportPackageItems)\n                {\n                    if (ai.enabledStatus > 0)\n                        guids.Add(ai.guid);\n                }\n\n                PackageUtility.ExportPackage(guids.ToArray(), fileName);\n                SendAnalyticsEvent(\"exportSuccess\");\n\n                Close();\n                GUIUtility.ExitGUI();\n            }\n            else\n            {\n                SendAnalyticsEvent(\"exportCancelledAtFileSelection\");\n            }\n        }\n\n        private void ScheduleBuildAssetList()\n        {\n            if (!m_DidScheduleUpdate)\n            {\n                EditorApplication.update += BuildAssetList;\n                m_DidScheduleUpdate = true;\n            }\n        }\n\n        private void UnscheduleBuildAssetList()\n        {\n            if (m_DidScheduleUpdate)\n            {\n                m_DidScheduleUpdate = false;\n                EditorApplication.update -= BuildAssetList;\n            }\n        }\n\n        private void BuildAssetList()\n        {\n            UnscheduleBuildAssetList();\n\n            m_ProjectBrowserSelection ??= Selection.assetGUIDsDeepSelection;\n            m_ExportPackageItems = GetAssetItemsForExport(m_ProjectBrowserSelection, m_IncludeDependencies, m_IncludeScripts).ToArray();\n\n            // GUI is reconstructed in OnGUI (when needed)\n            m_Tree = null;\n            m_TreeViewState = null;\n\n            Repaint();\n        }\n\n        private void SendAnalyticsEvent(string action)\n        {\n            var numSelectedAssets = 0;\n            var numTotalAssets = 0;\n            foreach (var i in m_ExportPackageItems)\n            {\n                if (i.isFolder)\n                    continue;\n                numTotalAssets++;\n                if (i.enabledStatus > 0)\n                    numSelectedAssets++;\n            }\n            AssetExportWindowAnalytics.SendEvent(action, numSelectedAssets, numTotalAssets, m_IncludeDependencies);\n        }\n\n        [AnalyticInfo(eventName: k_EventName, vendorKey: k_VendorKey)]\n        internal class AssetExportWindowAnalytics : IAnalytic\n        {\n            private const string k_EventName = \"assetExportWindow\";\n            private const string k_VendorKey = \"unity.package-manager-ui\";\n\n            [Serializable]\n            private class Data : IAnalytic.IData\n            {\n                public string action;\n                public int num_selected_assets;\n                public int num_total_assets;\n                public bool include_dependencies;\n            }\n\n            private Data m_Data;\n            private AssetExportWindowAnalytics(string action, int numSelectedAsset, int numTotalAssets, bool includeDependencies)\n            {\n                m_Data = new Data\n                {\n                    action = action,\n                    num_selected_assets = numSelectedAsset,\n                    num_total_assets = numTotalAssets,\n                    include_dependencies = includeDependencies,\n                };\n            }\n\n            public bool TryGatherData(out IAnalytic.IData data, out Exception error)\n            {\n                error = null;\n                data = m_Data;\n                return data != null;\n            }\n\n            public static void SendEvent(string action, int numSelectedAsset, int numTotalAssets, bool includeDependencies)\n            {\n                EditorAnalytics.SendAnalytic(new AssetExportWindowAnalytics(action, numSelectedAsset, numTotalAssets, includeDependencies));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/PackageExportTreeView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.Utils;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing UnityEditor.Experimental;\n\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewUtility = UnityEditor.IMGUI.Controls.TreeViewUtility<int>;\nusing TreeViewGUI = UnityEditor.IMGUI.Controls.TreeViewGUI<int>;\nusing TreeViewDataSource = UnityEditor.IMGUI.Controls.TreeViewDataSource<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    internal class PackageExportTreeView\n    {\n        TreeViewController m_TreeView;\n        List<PackageExportTreeViewItem> m_Selection = new List<PackageExportTreeViewItem>();\n        static readonly bool s_UseFoldouts = true;\n        public enum EnabledState\n        {\n            NotSet = -1,\n            None = 0,\n            All = 1,\n            Mixed = 2\n        }\n\n        private PackageExport m_PackageExport;\n\n        public ExportPackageItem[] items { get { return m_PackageExport.items; } }\n\n        public bool isAllItemsEnabled { get; private set; }\n        public bool isAnyItemEnabled { get; private set; }\n\n        public PackageExportTreeView(PackageExport packageExport, TreeViewState treeViewState, Rect startRect)\n        {\n            m_PackageExport = packageExport;\n\n            m_TreeView = new TreeViewController(m_PackageExport, treeViewState);\n            var dataSource = new PackageExportTreeViewDataSource(m_TreeView, this);\n            var gui = new PackageExportTreeViewGUI(m_TreeView, this);\n\n            m_TreeView.Init(startRect, dataSource, gui, null);\n            m_TreeView.ReloadData();\n            m_TreeView.selectionChangedCallback += SelectionChanged;\n            gui.itemWasToggled += ItemWasToggled;\n\n            ComputeEnabledStateForFolders();\n\n            RefreshEnabledProperties();\n        }\n\n        void ComputeEnabledStateForFolders()\n        {\n            var root = m_TreeView.data.root as PackageExportTreeViewItem;\n            var done = new HashSet<PackageExportTreeViewItem>();\n            done.Add(root); // Dont compute for root: mark it as done\n            RecursiveComputeEnabledStateForFolders(root, done);\n        }\n\n        void RecursiveComputeEnabledStateForFolders(PackageExportTreeViewItem pitem, HashSet<PackageExportTreeViewItem> done)\n        {\n            if (!pitem.isFolder)\n                return;\n\n            // Depth first recursion to allow parent folders be dependant on child folders\n\n            // Recurse\n            if (pitem.hasChildren)\n            {\n                foreach (var child in pitem.children)\n                {\n                    RecursiveComputeEnabledStateForFolders(child as PackageExportTreeViewItem, done);\n                }\n            }\n\n            // Now do logic\n            if (!done.Contains(pitem))\n            {\n                EnabledState enabledState = GetFolderChildrenEnabledState(pitem);\n                pitem.enabledState = enabledState;\n\n                // If 'item' is mixed then all of its parents will also be mixed\n                if (enabledState == EnabledState.Mixed)\n                {\n                    done.Add(pitem);\n                    var current = pitem.parent as PackageExportTreeViewItem;\n                    while (current != null)\n                    {\n                        if (!done.Contains(current))\n                        {\n                            current.enabledState = EnabledState.Mixed;\n                            done.Add(current);\n                        }\n                        current = current.parent as PackageExportTreeViewItem;\n                    }\n                }\n            }\n        }\n\n        EnabledState GetFolderChildrenEnabledState(PackageExportTreeViewItem folder)\n        {\n            if (!folder.isFolder)\n                Debug.LogError(\"Should be a folder item!\");\n\n            if (!folder.hasChildren)\n                return EnabledState.None;\n\n            EnabledState amount = EnabledState.NotSet;\n\n            var firstChild = folder.children[0] as PackageExportTreeViewItem;\n            EnabledState initial = firstChild.enabledState;\n            for (int i = 1; i < folder.children.Count; ++i)\n            {\n                var child = folder.children[i] as PackageExportTreeViewItem;\n                if (initial != child.enabledState)\n                {\n                    amount = EnabledState.Mixed;\n                    break;\n                }\n            }\n\n            if (amount == EnabledState.NotSet)\n            {\n                amount = initial == EnabledState.All ? EnabledState.All : EnabledState.None;\n            }\n\n            return amount;\n        }\n\n        void SelectionChanged(int[] selectedIDs)\n        {\n            // Cache selected tree view items (from ids)\n            m_Selection = new List<PackageExportTreeViewItem>();\n            var visibleItems = m_TreeView.data.GetRows();\n            foreach (var visibleItem in visibleItems)\n            {\n                if (selectedIDs.Contains(visibleItem.id))\n                {\n                    var pitem = visibleItem as PackageExportTreeViewItem;\n                    if (pitem != null)\n                        m_Selection.Add(pitem);\n                }\n            }\n        }\n\n        public void OnGUI(Rect rect)\n        {\n            int keyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard);\n            m_TreeView.OnGUI(rect, keyboardControlID);\n\n            // Keyboard space toggles selection enabledness\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Space &&\n                m_Selection != null && m_Selection.Count > 0 && GUIUtility.keyboardControl == keyboardControlID)\n            {\n                EnabledState newEnabled = m_Selection[0].enabledState != EnabledState.All ? EnabledState.All : EnabledState.None;\n                m_Selection[0].enabledState = newEnabled;\n                ItemWasToggled(m_Selection[0]);\n\n                Event.current.Use();\n            }\n        }\n\n        public void SetAllEnabled(EnabledState enabled)\n        {\n            EnableChildrenRecursive(m_TreeView.data.root, enabled);\n            ComputeEnabledStateForFolders();\n            RefreshEnabledProperties();\n        }\n\n        void ItemWasToggled(PackageExportTreeViewItem pitem)\n        {\n            if (m_Selection.Count <= 1)\n            {\n                EnableChildrenRecursive(pitem, pitem.enabledState);\n            }\n            else\n            {\n                foreach (var i in m_Selection)\n                    i.enabledState = pitem.enabledState;\n            }\n\n            ComputeEnabledStateForFolders();\n            RefreshEnabledProperties();\n        }\n\n        void EnableChildrenRecursive(TreeViewItem parentItem, EnabledState enabled)\n        {\n            if (!parentItem.hasChildren)\n                return;\n\n            foreach (TreeViewItem tvitem in parentItem.children)\n            {\n                var pitem = tvitem as PackageExportTreeViewItem;\n                pitem.enabledState = enabled;\n                EnableChildrenRecursive(pitem, enabled);\n            }\n        }\n\n        private void RefreshEnabledProperties()\n        {\n            isAllItemsEnabled = !m_TreeView.data.root.Exists(item => ((PackageExportTreeViewItem)item).enabledState != EnabledState.All);\n            isAnyItemEnabled = m_TreeView.data.root.Exists(item => ((PackageExportTreeViewItem)item).enabledState == EnabledState.All ||\n                                                                       ((PackageExportTreeViewItem)item).enabledState == EnabledState.Mixed);\n        }\n\n        // Item\n        private class PackageExportTreeViewItem : TreeViewItem\n        {\n            public ExportPackageItem item { get; set; }\n\n            private EnabledState m_EnabledState = EnabledState.NotSet;\n            public EnabledState enabledState\n            {\n                get { return item != null ? (EnabledState)item.enabledStatus : m_EnabledState; }\n                set { if (item != null) item.enabledStatus = (int)value; else m_EnabledState = value; }\n            }\n\n            // We assume that items that don't have ExportPackageItem assigned, are folders.\n            public bool isFolder\n            {\n                get { return item != null ? item.isFolder : true; }\n            }\n\n            public PackageExportTreeViewItem(ExportPackageItem itemIn, int id, int depth, TreeViewItem parent, string displayName)\n                : base(id, depth, parent, displayName)\n            {\n                item = itemIn;\n            }\n        }\n\n        // Gui\n\n        private class PackageExportTreeViewGUI : TreeViewGUI\n        {\n            internal static class Constants\n            {\n                public static Texture2D folderIcon = EditorGUIUtility.FindTexture(EditorResources.folderIconName);\n            }\n\n            public Action<PackageExportTreeViewItem> itemWasToggled;\n            public int showPreviewForID { get; set; }\n\n            private PackageExportTreeView m_PackageExportView;\n            protected float k_FoldoutWidth = 12f;\n\n            public PackageExportTreeViewGUI(TreeViewController treeView, PackageExportTreeView view)\n                : base(treeView)\n            {\n                m_PackageExportView = view;\n\n                k_BaseIndent = 4f;\n                if (!s_UseFoldouts)\n                    k_FoldoutWidth = 0f;\n            }\n\n            override public void OnRowGUI(Rect rowRect, TreeViewItem tvItem, int row, bool selected, bool focused)\n            {\n                k_IndentWidth = 18;\n                k_FoldoutWidth = 18;\n                const float k_ToggleWidth = 18f;\n\n                var pitem = tvItem as PackageExportTreeViewItem;\n\n                bool repainting = Event.current.type == EventType.Repaint;\n\n                // 0. Selection row rect\n                if (selected && repainting)\n                    selectionStyle.Draw(rowRect, false, false, true, focused);\n\n                // 1. Foldout\n                if (m_TreeView.data.IsExpandable(tvItem))\n                    DoFoldout(rowRect, tvItem, row);\n\n                // 2. Toggle only for items that are actually in the package.\n                Rect toggleRect = new Rect(k_BaseIndent + tvItem.depth * indentWidth + k_FoldoutWidth, rowRect.y, k_ToggleWidth, rowRect.height);\n\n                DoToggle(pitem, toggleRect);\n\n                // 3. Icon & Text\n                // Display folders that will not be included into the package as disabled.\n                using (new EditorGUI.DisabledScope(pitem.item == null))\n                {\n                    Rect contentRect = new Rect(toggleRect.xMax, rowRect.y, rowRect.width, rowRect.height);\n                    DoIconAndText(pitem, contentRect, selected, focused);\n                }\n            }\n\n            static void Toggle(ExportPackageItem[] items, PackageExportTreeViewItem pitem, Rect toggleRect)\n            {\n                bool enabled = pitem.enabledState > EnabledState.None;\n\n                GUIStyle style = EditorStyles.toggle;\n                bool setMixed = pitem.isFolder && (pitem.enabledState == EnabledState.Mixed);\n                if (setMixed)\n                    style = EditorStyles.toggleMixed;\n\n                bool newEnabled = GUI.Toggle(toggleRect, enabled, GUIContent.none, style);\n                if (newEnabled != enabled)\n                    pitem.enabledState = newEnabled ? EnabledState.All : EnabledState.None;\n            }\n\n            void DoToggle(PackageExportTreeViewItem pitem, Rect toggleRect)\n            {\n                // Toggle on/off\n                EditorGUI.BeginChangeCheck();\n                Toggle(m_PackageExportView.items, pitem, toggleRect);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    // Only change selection if we already have single selection (Keep multi-selection when toggling)\n                    if (m_TreeView.GetSelection().Length <= 1 || !m_TreeView.GetSelection().Contains(pitem.id))\n                    {\n                        m_TreeView.SetSelection(new int[] { pitem.id }, false);\n                        m_TreeView.NotifyListenersThatSelectionChanged();\n                    }\n                    if (itemWasToggled != null)\n                        itemWasToggled(pitem);\n                    Event.current.Use();\n                }\n            }\n\n            void DoIconAndText(PackageExportTreeViewItem item, Rect contentRect, bool selected, bool focused)\n            {\n                EditorGUIUtility.SetIconSize(new Vector2(k_IconWidth, k_IconWidth)); // If not set we see icons scaling down if text is being cropped\n                lineStyle = Styles.lineStyle;\n                lineStyle.padding.left = 0; // padding could have been set by other tree views\n                contentRect.height += 5; // with the default row height, underscore and lower parts of characters like g, p, etc. were not visible\n                if (Event.current.type == EventType.Repaint)\n                    lineStyle.Draw(contentRect, GUIContent.Temp(item.displayName, GetIconForItem(item)), false, false, selected, focused);\n                EditorGUIUtility.SetIconSize(Vector2.zero);\n            }\n\n            protected override Texture GetIconForItem(TreeViewItem tItem)\n            {\n                var pItem = tItem as PackageExportTreeViewItem;\n                var item = pItem.item;\n\n                // Undefined items are always folders.\n                if (item == null || item.isFolder)\n                {\n                    return Constants.folderIcon;\n                }\n\n                // We are using this TreeViewGUI when importing and exporting a package, so handle both situations:\n\n                // Exporting a package can use cached icons (icons we generate on import)\n                Texture cachedIcon = AssetDatabase.GetCachedIcon(item.assetPath);\n                if (cachedIcon != null)\n                    return cachedIcon;\n\n                // Importing a package have to use icons based on file extension\n                return InternalEditorUtility.GetIconForFile(item.assetPath);\n            }\n\n            protected override void RenameEnded()\n            {\n            }\n        }\n\n        // Datasource\n\n        private class PackageExportTreeViewDataSource : TreeViewDataSource\n        {\n            private PackageExportTreeView m_PackageExportView;\n\n            public PackageExportTreeViewDataSource(TreeViewController treeView, PackageExportTreeView view)\n                : base(treeView)\n            {\n                m_PackageExportView = view;\n                rootIsCollapsable = false;\n                showRootItem = false;\n            }\n\n            public override bool IsRenamingItemAllowed(TreeViewItem item)\n            {\n                return false;\n            }\n\n            public override bool IsExpandable(TreeViewItem item)\n            {\n                if (!s_UseFoldouts)\n                    return false;\n\n                return base.IsExpandable(item);\n            }\n\n            public override void FetchData()\n            {\n                int rootDepth = -1; // -1 so its children will have 0 depth\n                m_RootItem = new PackageExportTreeViewItem(null, \"Assets\".GetHashCode(), rootDepth, null, \"InvisibleAssetsFolder\");\n\n                bool initExpandedState = true;\n                if (initExpandedState)\n                    m_TreeView.state.expandedIDs.Add(m_RootItem.id);\n\n                ExportPackageItem[] items = m_PackageExportView.items;\n\n                Dictionary<string, PackageExportTreeViewItem> treeViewFolders = new Dictionary<string, PackageExportTreeViewItem>();\n                for (int i = 0; i < items.Length; i++)\n                {\n                    var item = items[i];\n\n                    if (PackageImport.HasInvalidCharInFilePath(item.assetPath))\n                        continue; // Do not add invalid paths (we already warn the user with a dialog in PackageImport.cs)\n\n                    string filename = Path.GetFileName(item.assetPath).ConvertSeparatorsToUnity();\n                    string folderPath = Path.GetDirectoryName(item.assetPath).ConvertSeparatorsToUnity();\n\n                    // Ensure folders. This is for when installed packages have been moved to other folders.\n                    TreeViewItem targetFolder = EnsureFolderPath(folderPath, treeViewFolders, initExpandedState);\n\n                    // Add file to folder\n                    if (targetFolder != null)\n                    {\n                        int id = item.assetPath.GetHashCode();\n                        var newItem = new PackageExportTreeViewItem(item, id, targetFolder.depth + 1, targetFolder, filename);\n                        targetFolder.AddChild(newItem);\n\n                        if (initExpandedState)\n                            m_TreeView.state.expandedIDs.Add(id);\n\n                        // We need to ensure that the folder is available for\n                        // EnsureFolderPath on subsequent iterations.\n                        if (item.isFolder)\n                            treeViewFolders[item.assetPath] = newItem;\n                    }\n                }\n\n                if (initExpandedState)\n                    m_TreeView.state.expandedIDs.Sort();\n            }\n\n            TreeViewItem EnsureFolderPath(string folderPath, Dictionary<string, PackageExportTreeViewItem> treeViewFolders, bool initExpandedState)\n            {\n                // We're in the root folder, so just return the root item as the parent.\n                if (folderPath == \"\")\n                    return m_RootItem;\n\n                // Does folder path exist?\n                int id = folderPath.GetHashCode();\n                TreeViewItem item = TreeViewUtility.FindItem(id, m_RootItem);\n\n                if (item != null)\n                    return item;\n\n                // Add folders as needed\n                string[] splitPath = folderPath.Split('/');\n                string currentPath = \"\";\n                TreeViewItem currentItem = m_RootItem;\n                int folderDepth = -1; // Will be incremented to the right depth in the loop.\n\n                for (int depth = 0; depth < splitPath.Length; ++depth)\n                {\n                    string folder = splitPath[depth];\n                    if (currentPath != \"\")\n                        currentPath += '/';\n\n                    currentPath += folder;\n\n                    // Dont create a 'Assets' folder (we already have that as a hidden root)\n                    if (depth == 0 && currentPath == \"Assets\")\n                        continue;\n\n                    // Only increment the folder depth if we are past the root \"Assets\" folder.\n                    ++folderDepth;\n\n                    id = currentPath.GetHashCode();\n\n                    PackageExportTreeViewItem foundItem;\n                    if (treeViewFolders.TryGetValue(currentPath, out foundItem))\n                    {\n                        currentItem = foundItem;\n                    }\n                    else\n                    {\n                        // If we do not have a tree view item for this folder we create one\n                        var folderItem = new PackageExportTreeViewItem(null, id, folderDepth, currentItem, folder);\n\n                        // Add to children array of the parent\n                        currentItem.AddChild(folderItem);\n                        currentItem = folderItem;\n\n                        // Auto expand all folder items\n                        if (initExpandedState)\n                            m_TreeView.state.expandedIDs.Add(id);\n\n                        // For faster finding of folders\n                        treeViewFolders[currentPath] = folderItem;\n                    }\n                }\n\n                return currentItem;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/PackageImport.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    [UsedByNativeCode]\n    internal class PackageImport : EditorWindow\n    {\n        [SerializeField]  private ImportPackageItem[] m_ImportPackageItems;\n        [SerializeField]  private string              m_PackageName;\n        [SerializeField]  private string              m_PackageIconPath;\n        [SerializeField]  TreeViewState               m_TreeViewState;\n        [NonSerialized]   PackageImportTreeView       m_Tree;\n\n        public ImportPackageItem[] packageItems { get { return m_ImportPackageItems; } }\n\n        private static Texture2D s_PackageIcon;\n        private static Texture2D s_Preview;\n        private static string    s_LastPreviewPath;\n\n        readonly static HashSet<char> s_InvalidPathChars = new HashSet<char>(System.IO.Path.GetInvalidPathChars());\n\n        internal class Constants\n        {\n            public GUIStyle ConsoleEntryBackEven  = \"CN EntryBackEven\";\n            public GUIStyle ConsoleEntryBackOdd   = \"CN EntryBackOdd\";\n            public GUIStyle title                 = \"LargeBoldLabel\";\n            public GUIStyle subtitle              = \"BoldLabel\";\n            public GUIStyle stepInfo              = \"Label\";\n            public GUIStyle bottomBarBg           = \"ProjectBrowserBottomBarBg\";\n            public GUIStyle topBarBg              = \"OT TopBar\";\n            public GUIStyle textureIconDropShadow = \"ProjectBrowserTextureIconDropShadow\";\n            public Color    lineColor;\n\n            public Constants()\n            {\n                lineColor = EditorGUIUtility.isProSkin ? new Color(0.1f, 0.1f, 0.1f) : new Color(0.4f, 0.4f, 0.4f);\n            }\n        }\n        static Constants ms_Constants;\n\n        // Invoked from menu\n        [UsedByNativeCode]\n        public static void ShowImportPackage(string packagePath, ImportPackageItem[] items, string packageIconPath, int productId, string packageName, string packageVersion, int uploadId)\n        {\n            if (!ValidateInput(items))\n                return;\n\n            var origin = new AssetOrigin(productId, packageName, packageVersion, uploadId);\n            PackageImportWizard.instance.StartImport(packagePath, items, packageIconPath, origin);\n        }\n\n        public PackageImport()\n        {\n            minSize = new Vector2(350, 350);\n        }\n\n        void OnDisable()\n        {\n            DestroyCreatedIcons();\n        }\n\n        void DestroyCreatedIcons()\n        {\n            if (s_Preview != null)\n            {\n                DestroyImmediate(s_Preview);\n                s_Preview = null;\n                s_LastPreviewPath = null;\n            }\n\n            if (s_PackageIcon != null)\n            {\n                DestroyImmediate(s_PackageIcon);\n                s_PackageIcon = null;\n            }\n        }\n\n        internal void Init(string packagePath, ImportPackageItem[] items, string packageIconPath)\n        {\n            DestroyCreatedIcons();\n\n            m_TreeViewState      = null;\n            m_Tree               = null;\n            m_ImportPackageItems = items;\n\n            m_PackageName = System.IO.Path.GetFileNameWithoutExtension(packagePath);\n            m_PackageIconPath = packageIconPath;\n\n            Repaint();\n        }\n\n        private bool ShowTreeGUI(ImportPackageItem[] items)\n        {\n            if (items.Length == 0)\n                return false;\n\n            for (int i = 0; i < items.Length; i++)\n            {\n                if (!items[i].isFolder && items[i].assetChanged)\n                    return true;\n            }\n\n            return false;\n        }\n\n        internal override void OnResized()\n        {\n            m_Tree?.OnWindowResized();\n            base.OnResized();\n        }\n\n        public void OnGUI()\n        {\n            if (ms_Constants == null)\n                ms_Constants = new Constants();\n\n            if (m_TreeViewState == null)\n                m_TreeViewState = new TreeViewState();\n\n            if (m_Tree == null)\n                m_Tree = new PackageImportTreeView(this, m_TreeViewState, new Rect());\n\n            if (m_ImportPackageItems != null && ShowTreeGUI(m_ImportPackageItems))\n            {\n                TopArea();\n                TopButtonsArea();\n                m_Tree.OnGUI(GUILayoutUtility.GetRect(1, 9999, 1, 99999));\n                BottomArea();\n            }\n            else\n            {\n                GUILayout.Label(\"Nothing to import!\", EditorStyles.boldLabel);\n                GUILayout.Label(\"All assets from this package are already in your project.\", \"WordWrappedLabel\");\n                GUILayout.FlexibleSpace();\n\n                // Background\n                GUILayout.BeginVertical(ms_Constants.bottomBarBg);\n                GUILayout.Space(8);\n                GUILayout.BeginHorizontal();\n                GUILayout.FlexibleSpace();\n                if (GUILayout.Button(\"OK\"))\n                {\n                    Close();\n                    GUIUtility.ExitGUI();\n                }\n                GUILayout.Space(10);\n                GUILayout.EndHorizontal();\n                GUILayout.Space(5);\n                GUILayout.EndVertical();\n            }\n        }\n\n        void TopArea()\n        {\n            const float margin = 10f;\n            const float imageSize = 64;\n\n            if (s_PackageIcon == null && !string.IsNullOrEmpty(m_PackageIconPath))\n                LoadTexture(m_PackageIconPath, ref s_PackageIcon);\n            bool hasPackageIcon = s_PackageIcon != null;\n\n            float totalTopHeight = hasPackageIcon ? (margin + imageSize + margin) : 52f;\n            Rect r = GUILayoutUtility.GetRect(position.width, totalTopHeight);\n\n            // Background\n            GUI.Label(r, GUIContent.none, ms_Constants.topBarBg);\n\n            Rect titleRect;\n            if (hasPackageIcon)\n            {\n                Rect iconRect = new Rect(r.x + margin, r.y + margin, imageSize, imageSize);\n                DrawTexture(iconRect, s_PackageIcon, true);\n\n                var textContentWidth = r.width - iconRect.width;\n                var textContentX = iconRect.xMax + margin;\n                var packageImportWizard = PackageImportWizard.instance;\n                if (!packageImportWizard.IsMultiStepWizard)\n                    titleRect = new Rect(textContentX, iconRect.yMin, textContentWidth, iconRect.height);\n                else\n                {\n                    titleRect = new Rect(textContentX, iconRect.yMin, textContentWidth, iconRect.height / 3);\n\n                    // Subtitle\n                    var subtitleRect = new Rect(textContentX + 1f, iconRect.yMin + iconRect.height * 0.50f, textContentWidth, iconRect.height / 4);\n                    var subtitleText = packageImportWizard.IsProjectSettingStep ? \"Import Settings Overrides\" : \"Import Content\";\n                    GUI.Label(subtitleRect, EditorGUIUtility.TrTextContent(subtitleText), ms_Constants.subtitle);\n\n                    // \"Step x of y\" label\n                    var stepInfoRect = new Rect(textContentX, iconRect.yMin + iconRect.height * 0.75f, textContentWidth, iconRect.height / 4);\n                    var stepInfoText = packageImportWizard.IsProjectSettingStep ? \"Step 2 of 2\" : \"Step 1 of 2\";\n                    GUI.Label(stepInfoRect, EditorGUIUtility.TrTextContent(stepInfoText), ms_Constants.stepInfo);\n                }\n            }\n            else\n            {\n                titleRect = new Rect(r.x + 5f, r.yMin, r.width, r.height);\n            }\n\n            // Title\n            GUI.Label(titleRect, m_PackageName, ms_Constants.title);\n        }\n\n        void TopButtonsArea()\n        {\n            GUILayout.BeginVertical();\n            GUILayout.Space(8);\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(10);\n\n            GUI.enabled = !m_Tree.isAllItemsEnabled;\n            if (GUILayout.Button(EditorGUIUtility.TrTextContent(\"All\"), GUILayout.Width(50)))\n            {\n                m_Tree.SetAllEnabled(PackageImportTreeView.EnabledState.All);\n            }\n            GUI.enabled = true;\n\n            GUI.enabled = m_Tree.isAnyItemEnabled;\n            if (GUILayout.Button(EditorGUIUtility.TrTextContent(\"None\"), GUILayout.Width(50)))\n            {\n                m_Tree.SetAllEnabled(PackageImportTreeView.EnabledState.None);\n            }\n            GUI.enabled = true;\n\n            GUILayout.Space(10);\n            GUILayout.EndHorizontal();\n            GUILayout.Space(5);\n            GUILayout.EndVertical();\n        }\n\n        void BottomArea()\n        {\n            // Background\n            GUILayout.BeginVertical(ms_Constants.bottomBarBg);\n            GUILayout.Space(8);\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(10);\n\n            var packageImportWizard = PackageImportWizard.instance;\n            GUILayout.FlexibleSpace();\n            if (GUILayout.Button(EditorGUIUtility.TrTextContent(\"Cancel\")))\n            {\n                packageImportWizard.CancelImport();\n            }\n\n            var hasPreviousStep = packageImportWizard.IsMultiStepWizard && packageImportWizard.IsProjectSettingStep;\n            var hasNextStep = packageImportWizard.IsMultiStepWizard && !packageImportWizard.IsProjectSettingStep;\n            var anyElementsSelected = packageImportWizard.AreAnyElementsSelected();\n            if (hasPreviousStep && GUILayout.Button(EditorGUIUtility.TrTextContent(\"Back\")))\n            {\n                packageImportWizard.DoPreviousStep(m_ImportPackageItems);\n            }\n            if (hasNextStep && GUILayout.Button(EditorGUIUtility.TrTextContent(\"Next\")))\n            {\n                packageImportWizard.DoNextStep(m_ImportPackageItems);\n            }\n            GUI.enabled = anyElementsSelected;\n            if (!hasNextStep && GUILayout.Button(EditorGUIUtility.TrTextContent(\"Import\")))\n            {\n                packageImportWizard.DoImportStep(m_ImportPackageItems);\n            }\n            GUI.enabled = true;\n\n            GUILayout.Space(10);\n            GUILayout.EndHorizontal();\n            GUILayout.Space(5);\n            GUILayout.EndVertical();\n        }\n\n        // Reuses old texture if it's created\n        static void LoadTexture(string filepath, ref Texture2D texture)\n        {\n            if (!texture)\n                texture = new Texture2D(128, 128);\n\n            byte[] fileContents = null;\n            try\n            {\n                fileContents = System.IO.File.ReadAllBytes(filepath);\n            }\n            catch\n            {\n                // ignore\n            }\n\n            if (filepath == \"\" || fileContents == null || !texture.LoadImage(fileContents))\n            {\n                Color[] pixels = texture.GetPixels();\n                for (int i = 0; i < pixels.Length; ++i)\n                    pixels[i] = new Color(0.5f, 0.5f, 0.5f, 0f);\n                texture.SetPixels(pixels);\n                texture.Apply();\n            }\n        }\n\n        public static void DrawTexture(Rect r, Texture2D tex, bool useDropshadow)\n        {\n            if (tex == null)\n                return;\n\n            // Clamp size (preserve aspect ratio)\n            float texwidth = tex.width;\n            float texheight = tex.height;\n            if (texwidth >= texheight && texwidth > r.width)\n            {\n                texheight = texheight * r.width / texwidth;\n                texwidth = r.width;\n            }\n            else if (texheight > texwidth && texheight > r.height)\n            {\n                texwidth = texwidth * r.height / texheight;\n                texheight = r.height;\n            }\n\n            // Center\n            float x = r.x + Mathf.Round((r.width - texwidth) / 2.0f);\n            float y = r.y + Mathf.Round((r.height - texheight) / 2.0f);\n\n            r = new Rect(x, y, texwidth, texheight);\n\n            // Dropshadow\n            if (useDropshadow && Event.current.type == EventType.Repaint)\n            {\n                Rect borderPosition = new RectOffset(1, 1, 1, 1).Remove(ms_Constants.textureIconDropShadow.border.Add(r));\n                ms_Constants.textureIconDropShadow.Draw(borderPosition, GUIContent.none, false, false, false, false);\n            }\n\n            GUI.DrawTexture(r, tex, ScaleMode.ScaleToFit, true);\n        }\n\n        public static Texture2D GetPreview(string previewPath)\n        {\n            if (previewPath != s_LastPreviewPath)\n            {\n                s_LastPreviewPath = previewPath;\n                LoadTexture(previewPath, ref s_Preview);\n            }\n\n            return s_Preview;\n        }\n\n        static bool ValidateInput(ImportPackageItem[] items)\n        {\n            string errorMessage;\n            if (!IsAllFilePathsValid(items, out errorMessage))\n            {\n                errorMessage += \"\\nDo you want to import the valid file paths of the package or cancel importing?\";\n                return EditorUtility.DisplayDialog(\"Invalid file path found\", errorMessage, \"Import\", \"Cancel importing\");\n            }\n            return true;\n        }\n\n        static bool IsAllFilePathsValid(ImportPackageItem[] assetItems, out string errorMessage)\n        {\n            foreach (var item in assetItems)\n            {\n                if (item.isFolder)\n                    continue;\n\n                char invalidChar;\n                int invalidCharIndex;\n                if (HasInvalidCharInFilePath(item.destinationAssetPath, out invalidChar, out invalidCharIndex))\n                {\n                    errorMessage = string.Format(\"Invalid character found in file path: '{0}'. Invalid ascii value: {1} (at character index {2}).\", item.destinationAssetPath, (int)invalidChar, invalidCharIndex);\n                    return false;\n                }\n            }\n\n            errorMessage = \"\";\n            return true;\n        }\n\n        static bool HasInvalidCharInFilePath(string filePath, out char invalidChar, out int invalidCharIndex)\n        {\n            for (int i = 0; i < filePath.Length; ++i)\n            {\n                char c = filePath[i];\n                if (s_InvalidPathChars.Contains(c))\n                {\n                    invalidChar = c;\n                    invalidCharIndex = i;\n                    return true;\n                }\n            }\n\n            invalidChar = ' ';\n            invalidCharIndex = -1;\n            return false;\n        }\n\n        public static bool HasInvalidCharInFilePath(string filePath)\n        {\n            char invalidChar;\n            int invalidCharIndex;\n            return HasInvalidCharInFilePath(filePath, out invalidChar, out invalidCharIndex);\n        }\n    }\n\n    [Serializable]\n    internal sealed class PackageImportWizard : ScriptableSingleton<PackageImportWizard>\n    {\n        [SerializeField]\n        private PackageImport m_ImportWindow;\n\n        [SerializeField]\n        private string m_PackagePath;\n        [SerializeField]\n        private string m_PackageIconPath;\n        [SerializeField]\n        private string m_PackageName;\n\n        [SerializeField]\n        private ImportPackageItem[] m_InitialImportItems;\n        [SerializeField]\n        private List<ImportPackageItem> m_AssetContentItems;\n        [SerializeField]\n        private List<ImportPackageItem> m_ProjectSettingItems;\n\n        [SerializeField]\n        private bool m_IsMultiStepWizard;\n        public bool IsMultiStepWizard => m_IsMultiStepWizard;\n        [SerializeField]\n        private bool m_IsProjectSettingStep;\n        public bool IsProjectSettingStep => m_IsProjectSettingStep;\n\n        private AssetOrigin m_AssetOrigin;\n\n        public void StartImport(string packagePath, ImportPackageItem[] items, string packageIconPath, AssetOrigin origin)\n        {\n            ClearImportData();\n\n            m_PackagePath = packagePath;\n            m_PackageIconPath = packageIconPath;\n            m_PackageName = System.IO.Path.GetFileNameWithoutExtension(packagePath);\n            m_AssetOrigin = origin;\n\n            m_InitialImportItems = items;\n            foreach (var item in items)\n            {\n                // We don't want to add `ProjectVersion.txt` since it would override the project Editor version and if it's a lower version, it would be downgraded\n                if (item.destinationAssetPath == \"ProjectSettings/ProjectVersion.txt\")\n                    continue;\n\n                if (item.destinationAssetPath.StartsWith(\"ProjectSettings/\"))\n                    m_ProjectSettingItems.Add(item);\n                else\n                    m_AssetContentItems.Add(item);\n            }\n\n            m_IsMultiStepWizard = m_AssetContentItems.Any() && m_ProjectSettingItems.Any();\n            if (m_AssetContentItems.Any())\n                ShowImportWindow(m_AssetContentItems.ToArray());\n            else if (m_ProjectSettingItems.Any())\n            {\n                m_IsProjectSettingStep = true;\n                ShowImportWindow(m_ProjectSettingItems.ToArray());\n            }\n        }\n\n        public void DoNextStep(ImportPackageItem[] importPackageItems)\n        {\n            if (!IsMultiStepWizard && IsProjectSettingStep)\n                return;\n\n            m_AssetContentItems = new List<ImportPackageItem>(importPackageItems);\n            m_IsProjectSettingStep = true;\n            ShowImportWindow(m_ProjectSettingItems.ToArray());\n        }\n\n        public void DoImportStep(ImportPackageItem[] importPackageItems)\n        {\n            if (IsMultiStepWizard && !IsProjectSettingStep)\n                return;\n\n            m_ProjectSettingItems = new List<ImportPackageItem>(importPackageItems);\n            FinishImport();\n        }\n\n        public void DoPreviousStep(ImportPackageItem[] importPackageItems)\n        {\n            if (!IsProjectSettingStep || !IsMultiStepWizard)\n                return;\n\n            m_ProjectSettingItems = new List<ImportPackageItem>(importPackageItems);\n            m_IsProjectSettingStep = false;\n            ShowImportWindow(m_AssetContentItems.ToArray());\n        }\n\n        public void CancelImport()\n        {\n            PackageUtility.ImportPackageAssetsCancelledFromGUI(m_PackageName, m_InitialImportItems);\n            CloseImportWindow();\n        }\n\n        public void CloseImportWindow()\n        {\n            if (m_ImportWindow != null)\n            {\n                ClearImportData();\n                m_ImportWindow.Close();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        private void ShowImportWindow(ImportPackageItem[] items)\n        {\n            m_ImportWindow = PackageImport.GetWindow<PackageImport>(true, \"Import Unity Package\");\n            m_ImportWindow.Init(m_PackagePath, items, m_PackageIconPath);\n        }\n\n        private void FinishImport()\n        {\n            PackageUtility.ImportPackageAssetsWithOrigin(m_AssetOrigin, m_AssetContentItems.Concat(m_ProjectSettingItems).ToArray());\n            CloseImportWindow();\n        }\n\n        private void ClearImportData()\n        {\n            m_PackagePath = string.Empty;\n            m_PackageIconPath = string.Empty;\n            m_PackageName = string.Empty;\n\n            m_InitialImportItems = null;\n            m_AssetContentItems = new List<ImportPackageItem>();\n            m_ProjectSettingItems = new List<ImportPackageItem>();\n\n            m_IsMultiStepWizard = false;\n            m_IsProjectSettingStep = false;\n        }\n\n        public bool AreAnyElementsSelected()\n        {\n            return m_AssetContentItems.Exists(i => i.enabledStatus == 1) || m_ProjectSettingItems.Exists(i => i.enabledStatus == 1);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/PackageImportTreeView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.Utils;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing UnityEditor.Experimental;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewUtility = UnityEditor.IMGUI.Controls.TreeViewUtility<int>;\nusing TreeViewGUI = UnityEditor.IMGUI.Controls.TreeViewGUI<int>;\nusing TreeViewDataSource = UnityEditor.IMGUI.Controls.TreeViewDataSource<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    internal class PackageImportTreeView\n    {\n        TreeViewController m_TreeView;\n        List<PackageImportTreeViewItem> m_Selection = new List<PackageImportTreeViewItem>();\n        static readonly bool s_UseFoldouts = true;\n        public enum EnabledState\n        {\n            Disabled = -1,\n            None = 0,\n            All = 1,\n            Mixed = 2\n        }\n\n        private PackageImport m_PackageImport;\n\n        public ImportPackageItem[] packageItems { get { return m_PackageImport.packageItems; } }\n\n        public bool isAllItemsEnabled { get; private set; }\n        public bool isAnyItemEnabled { get; private set; }\n\n        public PackageImportTreeView(PackageImport packageImport, TreeViewState treeViewState, Rect startRect)\n        {\n            m_PackageImport = packageImport;\n\n            m_TreeView = new TreeViewController(m_PackageImport, treeViewState);\n            var dataSource = new PackageImportTreeViewDataSource(m_TreeView, this);\n            var gui = new PackageImportTreeViewGUI(m_TreeView, this);\n\n            m_TreeView.Init(startRect, dataSource, gui, null);\n            m_TreeView.ReloadData();\n            m_TreeView.selectionChangedCallback += SelectionChanged;\n            gui.itemWasToggled += ItemWasToggled;\n\n            ComputeEnabledStateForFolders();\n\n            RefreshEnabledProperties();\n        }\n\n        void ComputeEnabledStateForFolders()\n        {\n            var root = m_TreeView.data.root as PackageImportTreeViewItem;\n            var done = new HashSet<PackageImportTreeViewItem>();\n            done.Add(root); // Dont compute for root: mark it as done\n            RecursiveComputeEnabledStateForFolders(root, done);\n        }\n\n        void RecursiveComputeEnabledStateForFolders(PackageImportTreeViewItem pitem, HashSet<PackageImportTreeViewItem> done)\n        {\n            if (pitem.item != null && !pitem.item.isFolder)\n                return;\n\n            // Depth first recursion to allow parent folders be dependant on child folders\n\n            // Recurse\n            if (pitem.hasChildren)\n            {\n                foreach (var child in pitem.children)\n                {\n                    RecursiveComputeEnabledStateForFolders(child as PackageImportTreeViewItem, done);\n                }\n            }\n            else if (pitem.item.isFolder)\n            {\n                // since the folder is empty, we don't need to set the enabled check depending of it's children\n                done.Add(pitem);\n            }\n\n            // Now do logic\n            if (!done.Contains(pitem))\n            {\n                EnabledState amount = GetFolderChildrenEnabledState(pitem);\n                pitem.enableState = amount;\n\n                // If 'item' is mixed then all of its parents will also be mixed\n                if (amount == EnabledState.Mixed)\n                {\n                    done.Add(pitem);\n                    var current = pitem.parent as PackageImportTreeViewItem;\n                    while (current != null)\n                    {\n                        if (!done.Contains(current))\n                        {\n                            current.enableState = EnabledState.Mixed;\n                            done.Add(current);\n                        }\n                        current = current.parent as PackageImportTreeViewItem;\n                    }\n                }\n            }\n        }\n\n        bool ItemShouldBeConsideredForEnabledCheck(PackageImportTreeViewItem pitem)\n        {\n            // Not even an item\n            if (pitem == null)\n                return false;\n\n            // item was a folder that had to be created\n            // in this treeview.\n            if (pitem.item == null)\n                return true;\n\n            // item is disabled\n            if (pitem.enableState == EnabledState.Disabled)\n                return false;\n\n            var item = pitem.item;\n            // Its a package asset or its changed\n            if (item.projectAsset || !(item.isFolder || item.assetChanged))\n                return false;\n\n            return true;\n        }\n\n        EnabledState GetFolderChildrenEnabledState(PackageImportTreeViewItem folder)\n        {\n            if (folder.item != null && !folder.item.isFolder)\n                Debug.LogError(\"Should be a folder item!\");\n\n            if (!folder.hasChildren)\n                return EnabledState.None;\n\n            // item is disabled if none of its children can be considered for enabled check\n            EnabledState amount = EnabledState.Disabled;\n\n            int i = 0;\n            for (; i < folder.children.Count; ++i)\n            {\n                // We dont want to consider project assets in this calculation as they are\n                // ignored\n                var firstValidChild = folder.children[i] as PackageImportTreeViewItem;\n                if (ItemShouldBeConsideredForEnabledCheck(firstValidChild))\n                {\n                    amount = firstValidChild.enableState;\n                    break;\n                }\n            }\n\n            ++i;\n            for (; i < folder.children.Count; ++i)\n            {\n                // We dont want to consider project assets in this calculation as they are\n                // ignored\n                var childItem = folder.children[i] as PackageImportTreeViewItem;\n                if (ItemShouldBeConsideredForEnabledCheck(childItem))\n                {\n                    if (amount != childItem.enableState)\n                    {\n                        amount = EnabledState.Mixed;\n                        break;\n                    }\n                }\n            }\n\n            return amount;\n        }\n\n        void SelectionChanged(int[] selectedIDs)\n        {\n            // Cache selected tree view items (from ids)\n            m_Selection = new List<PackageImportTreeViewItem>();\n            var visibleItems = m_TreeView.data.GetRows();\n            foreach (var visibleItem in visibleItems)\n            {\n                if (selectedIDs.Contains(visibleItem.id))\n                {\n                    var pitem = visibleItem as PackageImportTreeViewItem;\n                    if (pitem != null)\n                        m_Selection.Add(pitem);\n                }\n            }\n\n            // Show preview on selection\n            var selectedItem = m_Selection[0].item;\n            if (m_Selection.Count == 1 && selectedItem != null && !string.IsNullOrEmpty(selectedItem.previewPath))\n            {\n                var gui = m_TreeView.gui as PackageImportTreeViewGUI;\n                gui.showPreviewForID = m_Selection[0].id;\n            }\n            else\n            {\n                PopupWindowWithoutFocus.Hide();\n            }\n        }\n\n        public void OnWindowResized()\n        {\n            if (PopupWindowWithoutFocus.IsVisible())\n                PopupWindowWithoutFocus.Hide();\n        }\n\n        public void OnGUI(Rect rect)\n        {\n            // Remove preview popup on mouse scroll wheel events\n            if (Event.current.type == EventType.ScrollWheel)\n                PopupWindowWithoutFocus.Hide();\n\n            int keyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard);\n            m_TreeView.OnGUI(rect, keyboardControlID);\n\n            // Keyboard space toggles selection enabledness\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Space &&\n                m_Selection != null && m_Selection.Count > 0 && GUIUtility.keyboardControl == keyboardControlID)\n            {\n                var pitem = m_Selection[0];\n                if (pitem != null)\n                {\n                    EnabledState newEnabled = (pitem.enableState == EnabledState.None) ? EnabledState.All : EnabledState.None;\n                    pitem.enableState = newEnabled;\n                    ItemWasToggled(m_Selection[0]);\n                }\n\n                Event.current.Use();\n            }\n        }\n\n        public void SetAllEnabled(EnabledState state)\n        {\n            EnableChildrenRecursive(m_TreeView.data.root, state);\n            ComputeEnabledStateForFolders();\n            RefreshEnabledProperties();\n        }\n\n        void ItemWasToggled(PackageImportTreeViewItem pitem)\n        {\n            if (m_Selection.Count <= 1)\n            {\n                EnableChildrenRecursive(pitem, pitem.enableState);\n            }\n            else\n            {\n                foreach (var childPItem in m_Selection)\n                {\n                    childPItem.enableState = pitem.enableState;\n                }\n            }\n\n            ComputeEnabledStateForFolders();\n            RefreshEnabledProperties();\n        }\n        void EnableChildrenRecursive(TreeViewItem parentItem, EnabledState state)\n        {\n            if (!parentItem.hasChildren)\n                return;\n\n            foreach (TreeViewItem tvitem in parentItem.children)\n            {\n                var pitem = tvitem as PackageImportTreeViewItem;\n                pitem.enableState = state;\n\n                EnableChildrenRecursive(pitem, state);\n            }\n        }\n\n        private void RefreshEnabledProperties()\n        {\n            isAllItemsEnabled = !m_TreeView.data.root.Exists(item => ((PackageImportTreeViewItem)item).enableState != EnabledState.All);\n            isAnyItemEnabled = m_TreeView.data.root.Exists(item => ((PackageImportTreeViewItem)item).enableState == EnabledState.All ||\n                                                                       ((PackageImportTreeViewItem)item).enableState == EnabledState.Mixed);\n        }\n\n        // Item\n\n        private class PackageImportTreeViewItem : TreeViewItem\n        {\n            public ImportPackageItem item { get; set; }\n\n            public EnabledState enableState\n            {\n                get { return m_EnableState; }\n                set\n                {\n                    // We only want to set the enabled state if the item\n                    // is not a project asset.\n                    if (item == null || !item.projectAsset)\n                    {\n                        m_EnableState = value;\n                        if (item != null)\n                            item.enabledStatus = (int)value;\n                    }\n                }\n            }\n\n            public PackageImportTreeViewItem(ImportPackageItem itemIn, int id, int depth, TreeViewItem parent, string displayName)\n                : base(id, depth, parent, displayName)\n            {\n                item = itemIn;\n\n                if (item == null)\n                    m_EnableState = EnabledState.All;\n                else\n                    m_EnableState = (EnabledState)item.enabledStatus;\n            }\n\n            private EnabledState m_EnableState;\n        }\n\n        // Gui\n\n        private class PackageImportTreeViewGUI : TreeViewGUI\n        {\n            internal static class Constants\n            {\n                public static Texture2D folderIcon = EditorGUIUtility.FindTexture(EditorResources.folderIconName);\n                public static GUIContent badgeNew = EditorGUIUtility.TrIconContent(\"PackageBadgeNew\", \"This is a new asset.\");\n                public static GUIContent badgeOverride = EditorGUIUtility.TrIconContent(\"PackageBadgeOverride\", \"This project setting will be overridden!\");\n                public static GUIContent badgeWarnPathConflict = EditorGUIUtility.TrIconContent(\"console.warnicon\", \"Warning: File exists in project, but with different GUID. Will override existing asset which may be undesired.\");\n                public static GUIContent badgeChange = EditorGUIUtility.TrIconContent(\"playLoopOff\", \"This asset is new or has changed.\");\n\n                public static GUIStyle paddinglessStyle;\n\n                static Constants()\n                {\n                    paddinglessStyle = new GUIStyle();\n                    paddinglessStyle.padding = new RectOffset(0, 0, 0, 0);\n                }\n            }\n\n            public Action<PackageImportTreeViewItem> itemWasToggled;\n            public int showPreviewForID { get; set; }\n\n            private PackageImportTreeView m_PackageImportView;\n            protected float k_FoldoutWidth = 12f;\n\n            public PackageImportTreeViewGUI(TreeViewController treeView, PackageImportTreeView view)\n                : base(treeView)\n            {\n                m_PackageImportView = view;\n\n                k_BaseIndent = 4f;\n                if (!s_UseFoldouts)\n                    k_FoldoutWidth = 0f;\n            }\n\n            override public void OnRowGUI(Rect rowRect, TreeViewItem tvItem, int row, bool selected, bool focused)\n            {\n                k_IndentWidth = 18;\n                k_FoldoutWidth = 18;\n                const float k_ToggleWidth = 18f;\n\n                var pitem = tvItem as PackageImportTreeViewItem;\n                var item = pitem.item;\n\n                bool repainting = Event.current.type == EventType.Repaint;\n\n                // 0. Selection row rect\n                if (selected && repainting)\n                    selectionStyle.Draw(rowRect, false, false, true, focused);\n\n                bool validItem = (item != null);\n                bool isDisabled = (item != null) ? item.enabledStatus == (int)EnabledState.Disabled : false;\n                bool isFolder = (item != null) ? item.isFolder : true;\n                bool assetChanged = (item != null) ? item.assetChanged : false;\n                bool pathConflict = (item != null) ? item.pathConflict : false;\n                bool GUIDOverride = (item != null) ? item.existingAssetPath != string.Empty && item.existingAssetPath != item.destinationAssetPath : false;\n                bool exists = (item != null) ? item.exists : true;\n                bool projectAsset = (item != null) ? item.projectAsset : false;\n\n                // 1. Foldout\n                if (m_TreeView.data.IsExpandable(tvItem))\n                    DoFoldout(rowRect, tvItem, row);\n\n                // 2. Toggle only for items that are actually in the package.\n                Rect toggleRect = new Rect(k_BaseIndent + tvItem.depth * indentWidth + k_FoldoutWidth, rowRect.y, k_ToggleWidth, rowRect.height);\n\n                if ((isFolder && !projectAsset) || (validItem && !projectAsset && assetChanged))\n                    DoToggle(pitem, toggleRect);\n\n                using (new EditorGUI.DisabledScope(!validItem || projectAsset))\n                {\n                    // 3. Icon & Text\n                    Rect contentRect = new Rect(toggleRect.xMax, rowRect.y, rowRect.width, rowRect.height);\n                    DoIconAndText(tvItem, contentRect, selected, focused);\n\n                    // 4. Preview popup\n                    DoPreviewPopup(pitem, rowRect);\n\n                    // 4. Warning about file/GUID clashing.\n                    if (!isDisabled && repainting && validItem)\n                    {\n                        if (pathConflict)\n                        {\n                            Rect labelRect = new Rect(rowRect.xMax - 58, rowRect.y, rowRect.height, rowRect.height);\n                            EditorGUIUtility.SetIconSize(new Vector2(rowRect.height, rowRect.height));\n                            GUI.Label(labelRect, Constants.badgeWarnPathConflict, Constants.paddinglessStyle);\n                            EditorGUIUtility.SetIconSize(Vector2.zero);\n                        }\n                        else if (GUIDOverride)\n                        {\n                            Rect labelRect = new Rect(rowRect.xMax - 58, rowRect.y, rowRect.height, rowRect.height);\n                            EditorGUIUtility.SetIconSize(new Vector2(rowRect.height, rowRect.height));\n                            GUIContent badgeWarnGUIDConflict = EditorGUIUtility.TrIconContent(\"console.warnicon\", \"Warning: A file exists in this project with the same GUID. This Asset being imported will be assigned a new GUID. References to the asset being imported in other imported Assets will be replaced with a reference to: \" + item.existingAssetPath);\n                            GUI.Label(labelRect, badgeWarnGUIDConflict, Constants.paddinglessStyle);\n                            EditorGUIUtility.SetIconSize(Vector2.zero);\n                        }\n                    }\n\n                    // 5. Optional badge (\"New\")\n                    if (!isDisabled && repainting && validItem && !(exists || pathConflict))\n                    {\n                        // FIXME: Need to enable tooltips here.\n                        Texture badge = Constants.badgeNew.image;\n                        Rect labelRect = new Rect(rowRect.xMax - badge.width - 6, rowRect.y, badge.width, badge.height);\n                        GUI.Label(labelRect, Constants.badgeNew, Constants.paddinglessStyle);\n                    }\n\n                    // 7. Show what stuff has changed\n                    if (!isDisabled && repainting && validItem && (exists || pathConflict) && assetChanged)\n                    {\n                        if (PackageImportWizard.instance.IsProjectSettingStep)\n                        {\n                            Texture badge = Constants.badgeOverride.image;\n                            Rect labelRect = new Rect(rowRect.xMax - badge.width - 6, rowRect.y, badge.width, badge.height);\n                            GUI.Label(labelRect, Constants.badgeOverride, Constants.paddinglessStyle);\n                        }\n                        else\n                        {\n                            Texture badge = Constants.badgeChange.image;\n                            Rect labelRect = new Rect(rowRect.xMax - badge.width - 6, rowRect.y, rowRect.height, rowRect.height);\n                            GUI.Label(labelRect, Constants.badgeChange, Constants.paddinglessStyle);\n                        }\n                    }\n                }\n            }\n\n            static void Toggle(ImportPackageItem[] items, PackageImportTreeViewItem pitem, Rect toggleRect)\n            {\n                bool enabled = (int)pitem.enableState > 0;\n                bool isFolder = (pitem.item == null) || pitem.item.isFolder;\n\n                GUIStyle style = EditorStyles.toggle;\n                bool setMixed = isFolder && (pitem.enableState == EnabledState.Mixed);\n                if (setMixed)\n                    style = EditorStyles.toggleMixed;\n\n                if (isFolder && (pitem.enableState == EnabledState.Disabled))\n                    GUI.enabled = false;\n\n                bool newEnabled = GUI.Toggle(toggleRect, enabled, GUIContent.none, style);\n                if (newEnabled != enabled)\n                    pitem.enableState = newEnabled ? EnabledState.All : EnabledState.None;\n\n                GUI.enabled = true;\n            }\n\n            void DoToggle(PackageImportTreeViewItem pitem, Rect toggleRect)\n            {\n                // Toggle on/off\n                EditorGUI.BeginChangeCheck();\n                Toggle(m_PackageImportView.packageItems, pitem, toggleRect);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    // Only change selection if we already have single selection (Keep multi-selection when toggling)\n                    if (m_TreeView.GetSelection().Length <= 1 || !m_TreeView.GetSelection().Contains(pitem.id))\n                    {\n                        m_TreeView.SetSelection(new int[] { pitem.id }, false);\n                        m_TreeView.NotifyListenersThatSelectionChanged();\n                    }\n                    if (itemWasToggled != null)\n                        itemWasToggled(pitem);\n                    Event.current.Use();\n                }\n            }\n\n            void DoPreviewPopup(PackageImportTreeViewItem pitem, Rect rowRect)\n            {\n                var item = pitem.item;\n\n                if (item != null)\n                {\n                    // Ensure preview is shown when clicking on an already selected item (the preview might have been closed)\n                    if (Event.current.type == EventType.MouseDown && rowRect.Contains(Event.current.mousePosition) && !PopupWindowWithoutFocus.IsVisible())\n                        showPreviewForID = pitem.id;\n\n                    // Show preview\n                    if (pitem.id == showPreviewForID && Event.current.type != EventType.Layout)\n                    {\n                        showPreviewForID = 0;\n                        if (!string.IsNullOrEmpty(item.previewPath))\n                        {\n                            Texture2D preview = PackageImport.GetPreview(item.previewPath);\n                            Rect buttonRect = rowRect;\n                            buttonRect.width = EditorGUIUtility.currentViewWidth;\n                            PopupWindowWithoutFocus.Show(buttonRect, new PreviewPopup(preview), new[] { PopupLocation.Right, PopupLocation.Left, PopupLocation.Below });\n                        }\n                    }\n                }\n            }\n\n            void DoIconAndText(TreeViewItem item, Rect contentRect, bool selected, bool focused)\n            {\n                EditorGUIUtility.SetIconSize(new Vector2(k_IconWidth, k_IconWidth)); // If not set we see icons scaling down if text is being cropped\n                lineStyle = Styles.lineStyle;\n                lineStyle.padding.left = 0; // padding could have been set by other tree views\n                contentRect.height += 5; // with the default row height, underscore and lower parts of characters like g, p, etc. were not visible\n                if (Event.current.type == EventType.Repaint)\n                    lineStyle.Draw(contentRect, GUIContent.Temp(item.displayName, GetIconForItem(item)), false, false, selected, focused);\n                EditorGUIUtility.SetIconSize(Vector2.zero);\n            }\n\n            protected override Texture GetIconForItem(TreeViewItem tvItem)\n            {\n                var ourItem = tvItem as PackageImportTreeViewItem;\n                var item = ourItem.item;\n\n                // Indefined items are always folders.\n                if (item == null || item.isFolder)\n                {\n                    return Constants.folderIcon;\n                }\n\n                // We are using this TreeViewGUI when importing and exporting a package, so handle both situations:\n\n                // Exporting a package can use cached icons (icons we generate on import)\n                Texture cachedIcon = AssetDatabase.GetCachedIcon(item.destinationAssetPath);\n                if (cachedIcon != null)\n                    return cachedIcon;\n\n                // Importing a package have to use icons based on file extension\n                return InternalEditorUtility.GetIconForFile(item.destinationAssetPath);\n            }\n\n            protected override void RenameEnded()\n            {\n            }\n        }\n\n        // Datasource\n\n        private class PackageImportTreeViewDataSource : TreeViewDataSource\n        {\n            private PackageImportTreeView m_PackageImportView;\n            private const string k_RootTreeItemName = \"InvisibleAssetsFolder\";\n\n            public PackageImportTreeViewDataSource(TreeViewController treeView, PackageImportTreeView view)\n                : base(treeView)\n            {\n                m_PackageImportView = view;\n                rootIsCollapsable = false;\n                showRootItem = false;\n            }\n\n            public override bool IsRenamingItemAllowed(TreeViewItem item)\n            {\n                return false;\n            }\n\n            public override bool IsExpandable(TreeViewItem item)\n            {\n                if (!s_UseFoldouts)\n                    return false;\n\n                return base.IsExpandable(item);\n            }\n\n            public override void FetchData()\n            {\n                int rootDepth = -1; // -1 so its children will have 0 depth\n                m_RootItem = new PackageImportTreeViewItem(null, k_RootTreeItemName.GetHashCode(), rootDepth, null, k_RootTreeItemName);\n\n                bool initExpandedState = true;\n                if (initExpandedState)\n                    m_TreeView.state.expandedIDs.Add(m_RootItem.id);\n\n                ImportPackageItem[] items = m_PackageImportView.packageItems;\n                Dictionary<string, TreeViewItem> treeViewFolders = new Dictionary<string, TreeViewItem>();\n                for (int i = 0; i < items.Length; i++)\n                {\n                    var item = items[i];\n\n                    if (PackageImport.HasInvalidCharInFilePath(item.destinationAssetPath))\n                        continue; // Do not add invalid paths (we already warn the user with a dialog in PackageImport.cs)\n\n                    string filename = Path.GetFileName(item.destinationAssetPath).ConvertSeparatorsToUnity();\n                    string folderPath = Path.GetDirectoryName(item.destinationAssetPath).ConvertSeparatorsToUnity();\n\n                    // Ensure folders. This is for when installed packages have been moved to other folders.\n\n                    TreeViewItem targetFolder;\n                    treeViewFolders.TryGetValue(folderPath, out targetFolder);\n\n                    if (targetFolder == null)\n                    {\n                        targetFolder = EnsureFolderPath(folderPath, treeViewFolders, initExpandedState);\n                    }\n\n                    // Add file to folder\n                    if (targetFolder != null)\n                    {\n                        int id = item.destinationAssetPath.GetHashCode();\n                        var newItem = new PackageImportTreeViewItem(item, id, targetFolder.depth + 1, targetFolder, filename);\n                        targetFolder.AddChild(newItem);\n\n                        if (initExpandedState)\n                            m_TreeView.state.expandedIDs.Add(id);\n\n                        // We need to ensure that the folder is available for\n                        // EnsureFolderPath on subsequent iterations.\n                        if (item.isFolder)\n                            treeViewFolders[item.destinationAssetPath] = newItem;\n                    }\n                }\n\n                if (initExpandedState)\n                    m_TreeView.state.expandedIDs.Sort();\n            }\n\n            TreeViewItem EnsureFolderPath(string folderPath, Dictionary<string, TreeViewItem> treeViewFolders, bool initExpandedState)\n            {\n                //We're in the root folder, so just return the root item as the parent.\n                if (folderPath == \"\")\n                    return m_RootItem;\n\n                // Does folder path exist?\n                int id = folderPath.GetHashCode();\n                TreeViewItem item = TreeViewUtility.FindItem(id, m_RootItem);\n\n                if (item != null)\n                {\n                    return item;\n                }\n\n                // Add folders as needed\n                string[] splitPath = folderPath.Split('/');\n                string currentPath = \"\";\n                TreeViewItem currentItem = m_RootItem;\n                int folderDepth = -1; // Will be incremented to the right depth in the loop.\n\n                for (int depth = 0; depth < splitPath.Length; ++depth)\n                {\n                    string folder = splitPath[depth];\n                    if (currentPath != \"\")\n                        currentPath += '/';\n\n                    currentPath += folder;\n\n                    // Dont create a 'Assets' folder (we already have that as a hidden root)\n                    if (depth == 0 && currentPath == \"Assets\")\n                        continue;\n\n                    // Only increment the folder depth if we are past the root \"Assets\" folder.\n                    ++folderDepth;\n\n                    id = currentPath.GetHashCode();\n\n                    TreeViewItem foundItem;\n                    if (treeViewFolders.TryGetValue(currentPath, out foundItem))\n                    {\n                        currentItem = foundItem;\n                    }\n                    else\n                    {\n                        // If we do not have a tree view item for this folder we create one\n                        var folderItem = new PackageImportTreeViewItem(null, id, folderDepth, currentItem, folder);\n\n                        // Add to children array of the parent\n                        currentItem.AddChild(folderItem);\n                        currentItem = folderItem;\n\n                        // Auto expand all folder items\n                        if (initExpandedState)\n                            m_TreeView.state.expandedIDs.Add(id);\n\n                        // For faster finding of folders\n                        treeViewFolders[currentPath] = folderItem;\n                    }\n                }\n\n                return currentItem;\n            }\n        }\n\n\n        class PreviewPopup : PopupWindowContent\n        {\n            readonly Texture2D m_Preview;\n            readonly Vector2 kPreviewSize = new Vector2(128f, 128f);\n\n            public PreviewPopup(Texture2D preview)\n            {\n                m_Preview = preview;\n            }\n\n            public override void OnGUI(Rect rect)\n            {\n                PackageImport.DrawTexture(rect, m_Preview, false);\n            }\n\n            public override Vector2 GetWindowSize()\n            {\n                return kPreviewSize;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/PaneDragTab.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.StyleSheets;\nusing UnityEditor.Experimental;\n\nnamespace UnityEditor\n{\n    // This uses a normal editor window with a single view inside.\n    internal class PaneDragTab : GUIView\n    {\n        const float kMaxArea = 50000.0f;\n\n#pragma warning disable 169\n\n        private static PaneDragTab s_Get;\n        private float m_TargetAlpha = 1.0f;\n        private DropInfo.Type m_Type = (DropInfo.Type)(-1);\n        private GUIContent m_Content;\n\n        [SerializeField] bool m_Shadow;\n        [SerializeField] Vector2 m_FullWindowSize = new Vector2(80, 60);\n        [SerializeField] Rect m_TargetRect;\n        [SerializeField] internal ContainerWindow m_Window;\n        [SerializeField] ContainerWindow m_InFrontOfWindow = null;\n\n        private static class Styles\n        {\n            private static readonly StyleBlock tab = EditorResources.GetStyle(\"tab\");\n            public static readonly float tabMinWidth = tab.GetFloat(StyleCatalogKeyword.minWidth, 50.0f);\n            public static readonly float tabMaxWidth = tab.GetFloat(StyleCatalogKeyword.maxWidth, 150.0f);\n            public static readonly float tabWidthPadding = tab.GetFloat(StyleCatalogKeyword.paddingRight);\n\n            public static GUIStyle dragtab = \"dragtab\";\n            public static GUIStyle view = \"TabWindowBackground\";\n            public static readonly GUIStyle tabLabel = new GUIStyle(\"dragtab\") { name = \"dragtab-label\" };\n\n            public static readonly SVC<Color> backgroundColor = new SVC<Color>(\"--unity-colors-app_toolbar-background\");\n        }\n\n        static public PaneDragTab get\n        {\n            get\n            {\n                if (!s_Get)\n                {\n                    Object[] objs = Resources.FindObjectsOfTypeAll(typeof(PaneDragTab));\n                    if (objs.Length != 0)\n                        s_Get = (PaneDragTab)objs[0];\n                    if (s_Get)\n                    {\n                        return s_Get;\n                    }\n                    s_Get = ScriptableObject.CreateInstance<PaneDragTab>();\n                }\n                return s_Get;\n            }\n        }\n\n        public void SetDropInfo(DropInfo di, Vector2 mouseScreenPos, ContainerWindow inFrontOf)\n        {\n            if (m_Type != di.type || (di.type == DropInfo.Type.Pane && di.rect != m_TargetRect))\n            {\n                m_Type = di.type;\n\n                switch (di.type)\n                {\n                    case DropInfo.Type.Window:\n                        m_TargetAlpha = 0.6f;\n                        break;\n                    case DropInfo.Type.Pane:\n                    case DropInfo.Type.Tab:\n                        m_TargetAlpha = 1.0f;\n                        break;\n                }\n            }\n\n            switch (di.type)\n            {\n                case DropInfo.Type.Window:\n                    m_TargetRect = new Rect(mouseScreenPos.x - m_FullWindowSize.x / 2, mouseScreenPos.y - m_FullWindowSize.y / 2,\n                        m_FullWindowSize.x, m_FullWindowSize.y);\n                    break;\n                case DropInfo.Type.Pane:\n                case DropInfo.Type.Tab:\n                    m_TargetRect = di.rect;\n                    break;\n            }\n\n            m_TargetRect.x = Mathf.Floor(m_TargetRect.x);\n            m_TargetRect.y = Mathf.Floor(m_TargetRect.y);\n            m_TargetRect.width = Mathf.Floor(m_TargetRect.width);\n            m_TargetRect.height = Mathf.Floor(m_TargetRect.height);\n\n            m_InFrontOfWindow = inFrontOf;\n            m_Window.MoveInFrontOf(m_InFrontOfWindow);\n\n            // On Windows, repainting without setting proper size first results in one garbage frame... For some reason.\n            SetWindowPos(m_TargetRect);\n            // Yes, repaint.\n            Repaint();\n        }\n\n        public void Close()\n        {\n            if (m_Window)\n                m_Window.Close();\n            DestroyImmediate(this, true);\n            s_Get = null;\n        }\n\n        public void Show(Rect pixelPos, GUIContent content, Vector2 viewSize, Vector2 mouseScreenPosition)\n        {\n            m_Content = content;\n            // scale not to be larger then maxArea pixels.\n            var area = viewSize.x * viewSize.y;\n            m_FullWindowSize = viewSize * Mathf.Sqrt(Mathf.Clamp01(kMaxArea / area));\n\n            if (!m_Window)\n            {\n                m_Window = ScriptableObject.CreateInstance<ContainerWindow>();\n                m_Window.m_DontSaveToLayout = true;\n                SetMinMaxSizes(Vector2.zero, new Vector2(10000, 10000));\n                SetWindowPos(pixelPos);\n                m_Window.rootView = this;\n            }\n            else\n            {\n                SetWindowPos(pixelPos);\n            }\n\n            // Do not steal focus from the pane\n            m_Window.Show(ShowMode.NoShadow, loadPosition: true, displayImmediately: false, setFocus: false);\n\n            m_TargetRect = pixelPos;\n        }\n\n        void SetWindowPos(Rect screenPosition)\n        {\n            m_Window.position = screenPosition;\n        }\n\n        protected override void OldOnGUI()\n        {\n            if (!m_Window)\n                return;\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            Rect windowRect = new Rect(0, 0, position.width, position.height);\n\n            if (Event.current.type == EventType.Repaint)\n                GUI.DrawTexture(windowRect, EditorGUIUtility.whiteTexture, ScaleMode.StretchToFill, false, 0f, Styles.backgroundColor, 0, 0);\n            if (m_Type == DropInfo.Type.Tab)\n            {\n                Styles.dragtab.Draw(windowRect, false, true, false, false);\n                GUI.Label(windowRect, m_Content, Styles.tabLabel);\n            }\n            else\n            {\n                const float dragTabOffsetX = 2f;\n                const float dragTabHeight = DockArea.kTabHeight;\n\n                float minWidth, expectedWidth;\n                Styles.dragtab.CalcMinMaxWidth(m_Content, out minWidth, out expectedWidth);\n                float tabWidth = Mathf.Max(Mathf.Min(expectedWidth, Styles.tabMaxWidth), Styles.tabMinWidth) + Styles.tabWidthPadding;\n                Rect tabPositionRect = new Rect(1, 2f, tabWidth, dragTabHeight);\n                float roundedPosX = Mathf.Floor(tabPositionRect.x);\n                float roundedWidth = Mathf.Ceil(tabPositionRect.x + tabPositionRect.width) - roundedPosX;\n                Rect tabContentRect = new Rect(roundedPosX, tabPositionRect.y, roundedWidth, tabPositionRect.height);\n                Rect viewRect = new Rect(dragTabOffsetX, tabContentRect.yMax - 2f,\n                    position.width - dragTabOffsetX * 2, position.height - tabContentRect.yMax);\n\n                Styles.dragtab.Draw(tabContentRect, false, true, false, false);\n                Styles.view.Draw(viewRect, GUIContent.none, false, false, true, true);\n                GUI.Label(tabPositionRect, m_Content, Styles.tabLabel);\n            }\n\n            // We currently only support this on macOS\n            m_Window.SetAlpha(m_TargetAlpha);\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/PingData.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    // Handles a \"ping\" in project/hierarchy windows. Zoom, wait and fadeoff.\n    // Init by setting:\n    // - m_PingStyle: Background style\n    // - m_ContentDraw: Content render callback function  (is rendered on top of background ping style)\n    // - m_ContentRect: Size and position of content that is rendered in m_ContentDraw (is used for calculating the ping background and is passed to m_ContentDraw)\n    class PingData\n    {\n        float m_TimeStart = -1f;\n        bool m_IsPinging = false;\n\n        public float m_ZoomTime = 0.2f;\n        public float m_WaitTime = 2.5f;\n        public float m_FadeOutTime = 1.5f;\n        public float m_PeakScale = 1.75f;\n\n        public System.Action<Rect> m_ContentDraw;\n        public Rect m_ContentRect;                  // Rect passed to m_ContentDraw\n\n        // How wide is the view where we are pinging. Needed for the pivot point trick where pinged content is only partly visible.\n        public float m_AvailableWidth = 100f;\n        public GUIStyle m_PingStyle;\n\n        public bool isPinging\n        {\n            get { return m_IsPinging; }\n            set { m_IsPinging = value; m_TimeStart = -1f; }\n        }\n\n        public void HandlePing()\n        {\n            if (isPinging)\n            {\n                if (m_TimeStart < 0)\n                     m_TimeStart = Time.realtimeSinceStartup;\n                float totalTime = m_ZoomTime + m_WaitTime + m_FadeOutTime;\n                float t = (Time.realtimeSinceStartup - m_TimeStart);\n\n                if (t >= 0.0f && t < totalTime)\n                {\n                    Color c = GUI.color;\n                    Matrix4x4 m = GUI.matrix;\n                    if (t < m_ZoomTime)\n                    {\n                        float peakTime = m_ZoomTime / 2f;\n                        float scale = (m_PeakScale - 1f) * (((m_ZoomTime - Mathf.Abs(peakTime - t)) / peakTime) - 1f) + 1f;\n                        Matrix4x4 mat = GUI.matrix;\n\n                        // If the content is only partly visible, the zoom pivot point is moved to right border. This avoids the nasty artefacts.\n                        Vector2 pivotPoint = m_ContentRect.xMax < m_AvailableWidth ? m_ContentRect.center : new Vector2(m_AvailableWidth, m_ContentRect.center.y);\n                        Vector2 point = GUIClip.Unclip(pivotPoint);\n                        Matrix4x4 newMat = Matrix4x4.TRS(point, Quaternion.identity, new Vector3(scale, scale, 1)) * Matrix4x4.TRS(-point, Quaternion.identity, Vector3.one);\n                        GUI.matrix = newMat * mat;\n                    }\n                    else if (t > m_ZoomTime + m_WaitTime)\n                    {\n                        float alpha = (totalTime - t) / m_FadeOutTime;\n                        GUI.color = new Color(c.r, c.g, c.b, c.a * alpha);\n                    }\n\n                    if (m_ContentDraw != null && Event.current.type == EventType.Repaint)\n                    {\n                        Rect backRect = m_ContentRect;\n                        backRect.x -= m_PingStyle.padding.left / 2f;\n                        backRect.y -= m_PingStyle.padding.top / 2f;\n                        m_PingStyle.Draw(backRect, GUIContent.none, false, false, false, false);\n                        m_ContentDraw(m_ContentRect);\n                    }\n\n                    GUI.matrix = m;\n                    GUI.color = c;\n                }\n                else\n                {\n                    isPinging = false;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/PopupLocation.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n    internal enum PopupLocation\n    {\n        Below,\n        BelowAlignLeft = Below,\n        Above,\n        AboveAlignLeft = Above,\n        Left,\n        Right,\n        Overlay,\n        BelowAlignRight,\n        AboveAlignRight\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/PopupLocationHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\n\n\nnamespace UnityEditor\n{\n    internal static class PopupLocationHelper\n    {\n        public static Rect GetDropDownRect(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow)\n        {\n            return GetDropDownRect(buttonRect, minSize, maxSize, popupContainerWindow, null);\n        }\n\n        public static Rect GetDropDownRect(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow, PopupLocation[] locationPriorityOrder)\n        {\n            if (locationPriorityOrder == null)\n                locationPriorityOrder = new[]\n                {\n                    PopupLocation.Below,\n                    PopupLocation.Above,\n                    PopupLocation.Left,\n                    PopupLocation.Right\n                }; // Default priority order\n\n            List<Rect> croppedRects = new List<Rect>();\n            foreach (PopupLocation location in locationPriorityOrder)\n            {\n                Rect resultRect;\n                switch (location)\n                {\n                    case PopupLocation.BelowAlignLeft:\n                        if (PopupBelowAlignLeft(buttonRect, minSize, maxSize, popupContainerWindow, out resultRect))\n                            return resultRect;\n                        croppedRects.Add(resultRect);\n                        break;\n                    case PopupLocation.BelowAlignRight:\n                        if (PopupBelowAlignRight(buttonRect, minSize, maxSize, popupContainerWindow, out resultRect))\n                            return resultRect;\n                        croppedRects.Add(resultRect);\n                        break;\n                    case PopupLocation.AboveAlignLeft:\n                        if (PopupAboveAlignLeft(buttonRect, minSize, maxSize, popupContainerWindow, out resultRect))\n                            return resultRect;\n                        croppedRects.Add(resultRect);\n                        break;\n                    case PopupLocation.AboveAlignRight:\n                        if (PopupAboveAlignRight(buttonRect, minSize, maxSize, popupContainerWindow, out resultRect))\n                            return resultRect;\n                        croppedRects.Add(resultRect);\n                        break;\n                    case PopupLocation.Left:\n                        if (PopupLeft(buttonRect, minSize, maxSize, popupContainerWindow, out resultRect))\n                            return resultRect;\n                        croppedRects.Add(resultRect);\n                        break;\n                    case PopupLocation.Right:\n                        if (PopupRight(buttonRect, minSize, maxSize, popupContainerWindow, out resultRect))\n                            return resultRect;\n                        croppedRects.Add(resultRect);\n                        break;\n                    case PopupLocation.Overlay:\n                        if (PopupOverlay(buttonRect, minSize, maxSize, popupContainerWindow, out resultRect))\n                            return resultRect;\n                        croppedRects.Add(resultRect);\n                        break;\n                }\n            }\n\n            // Popup did not fit any of the wanted locations. Now find and return the largest cropped rect instead\n            return GetLargestRect(croppedRects);\n        }\n\n        private static Rect FitRect(Rect rect, Vector2 uiPositionToSelectScreen, ContainerWindow popupContainerWindow)\n        {\n            return ContainerWindow.FitRectToScreen(rect, uiPositionToSelectScreen, true, popupContainerWindow);\n        }\n\n        private static bool PopupRight(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow, out Rect resultRect)\n        {\n            // Calculate how much space is available for the window right of the button\n            Rect dropDownRectRight = new Rect(buttonRect.xMax, buttonRect.y, maxSize.x, maxSize.y);\n            float spaceFromRight = 0;\n            dropDownRectRight.xMax += spaceFromRight;\n            dropDownRectRight.height += k_SpaceFromBottom;\n\n            dropDownRectRight = FitRect(dropDownRectRight, buttonRect.center, popupContainerWindow);\n            float availableWidthRight = Mathf.Max(dropDownRectRight.xMax - buttonRect.xMax - spaceFromRight, 0);\n            float windowWidth = Mathf.Min(availableWidthRight, maxSize.x);\n            resultRect = new Rect(dropDownRectRight.x, dropDownRectRight.y, windowWidth, dropDownRectRight.height - k_SpaceFromBottom);\n\n            if (Mathf.Ceil(availableWidthRight) >= minSize.x)\n                return true;\n            return false;\n        }\n\n        private static bool PopupLeft(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow,\n            out Rect resultRect)\n        {\n            // Calculate how much space is available for the window left of the button\n            Rect dropDownRectLeft = new Rect(buttonRect.x - maxSize.x, buttonRect.y, maxSize.x, maxSize.y);\n            float spaceFromLeft = 0;\n            dropDownRectLeft.xMin -= spaceFromLeft;\n            dropDownRectLeft.height += k_SpaceFromBottom;\n\n            dropDownRectLeft = FitRect(dropDownRectLeft, buttonRect.center, popupContainerWindow);\n            float availableWidthLeft = Mathf.Max(buttonRect.x - dropDownRectLeft.x - spaceFromLeft, 0);\n            float windowWidth = Mathf.Min(availableWidthLeft, maxSize.x);\n            resultRect = new Rect(dropDownRectLeft.x, dropDownRectLeft.y, windowWidth, dropDownRectLeft.height - k_SpaceFromBottom);\n\n            if (Mathf.Ceil(availableWidthLeft) >= minSize.x)\n                return true;\n            return false;\n        }\n\n        private static bool PopupAboveAlignLeft(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow,\n            out Rect resultRect)\n        {\n            Rect dropDownRectAbove = new Rect(buttonRect.x, buttonRect.y - maxSize.y, maxSize.x, maxSize.y);\n            return PopupAbove(dropDownRectAbove, buttonRect, minSize, maxSize, popupContainerWindow, out resultRect);\n        }\n\n        private static bool PopupAboveAlignRight(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow,\n            out Rect resultRect)\n        {\n            Rect dropDownRectAbove = new Rect(buttonRect.xMax - maxSize.x, buttonRect.y - maxSize.y, maxSize.x, maxSize.y);\n            return PopupAbove(dropDownRectAbove, buttonRect, minSize, maxSize, popupContainerWindow, out resultRect);\n        }\n\n        private static bool PopupAbove(Rect dropDownRectAbove, Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow,\n            out Rect resultRect)\n        {\n            float spaceFromTop = 0;\n\n            // Expand dropdown height to include empty space above\n            dropDownRectAbove.yMin -= spaceFromTop;\n            // Fit rect to screen\n            dropDownRectAbove = FitRect(dropDownRectAbove, buttonRect.center, popupContainerWindow);\n\n            // Calculate how much space is available for the window above the button\n            float availableHeightAbove = Mathf.Max(buttonRect.y - dropDownRectAbove.y - spaceFromTop, 0);\n            // If there's room for the window at its minimum size above the button, then place it there\n            if (Mathf.Ceil(availableHeightAbove) >= minSize.y)\n            {\n                float windowHeight = Mathf.Min(availableHeightAbove, maxSize.y);\n                {\n                    resultRect = new Rect(dropDownRectAbove.x, buttonRect.y - windowHeight, dropDownRectAbove.width, windowHeight);\n                    return true;\n                }\n            }\n            resultRect = new Rect(dropDownRectAbove.x, buttonRect.y - availableHeightAbove, dropDownRectAbove.width, availableHeightAbove);\n            return false;\n        }\n\n        private static bool PopupBelowAlignLeft(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow,\n            out Rect resultRect)\n        {\n            Rect dropDownRectBelow = new Rect(buttonRect.x, buttonRect.yMax, maxSize.x, maxSize.y);\n            return PopupBelow(dropDownRectBelow, buttonRect, minSize, maxSize, popupContainerWindow, out resultRect);\n        }\n\n        private static bool PopupBelowAlignRight(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow,\n            out Rect resultRect)\n        {\n            Rect dropDownRectBelow = new Rect(buttonRect.xMax - maxSize.x, buttonRect.yMax, maxSize.x, maxSize.y);\n            return PopupBelow(dropDownRectBelow, buttonRect, minSize, maxSize, popupContainerWindow, out resultRect);\n        }\n\n        private static bool PopupBelow(Rect dropDownRectBelow, Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow,\n            out Rect resultRect)\n        {\n            // Expand dropdown height to include empty space below\n            dropDownRectBelow.height += k_SpaceFromBottom;\n            // Fit rect to screen\n            dropDownRectBelow = FitRect(dropDownRectBelow, buttonRect.center, popupContainerWindow);\n\n            // Calculate how much space is available for the window below the button\n            float availableHeightBelow = Mathf.Max(dropDownRectBelow.yMax - buttonRect.yMax - k_SpaceFromBottom, 0);\n            // If there's room for the window at its minimum size below the button, then place it there\n            if (Mathf.Ceil(availableHeightBelow) >= minSize.y)\n            {\n                float windowHeight = Mathf.Min(availableHeightBelow, maxSize.y);\n                resultRect = new Rect(dropDownRectBelow.x, buttonRect.yMax, dropDownRectBelow.width, windowHeight);\n                return true;\n            }\n            if (dropDownRectBelow.yMax - buttonRect.yMax - k_SpaceFromBottom < 0)\n            {\n                resultRect = new Rect(dropDownRectBelow.x, (dropDownRectBelow.yMax + dropDownRectBelow.yMin) / 2 - dropDownRectBelow.height, dropDownRectBelow.width, dropDownRectBelow.height);\n                return true;\n            }\n            resultRect = new Rect(dropDownRectBelow.x, buttonRect.yMax, dropDownRectBelow.width, availableHeightBelow);\n            return false;\n        }\n\n        private static bool PopupOverlay(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow,\n            out Rect resultRect)\n        {\n            //Stretch the popup over the button Rect if it doesn't fit\n            Rect dropDownRectBelow = new Rect(buttonRect.x, buttonRect.yMax, maxSize.x, maxSize.y);\n            resultRect = FitRect(dropDownRectBelow, buttonRect.center, popupContainerWindow);\n            return true;\n        }\n\n        private static Rect GetLargestRect(List<Rect> rects)\n        {\n            Rect max = new Rect();\n            foreach (Rect rect in rects)\n                if (rect.height * rect.width > max.height * max.width)\n                    max = rect;\n            return max;\n        }\n\n        // How much empty space there should be at minimum at the bottom of the screen below the popup\n        private static float k_SpaceFromBottom\n        {\n            get\n            {\n                if (Application.platform == RuntimePlatform.OSXEditor)\n                    return 10f;\n                return 0;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/PopupWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    /*\n     Note that content of PopupWindow do not survive assembly reloading because it derives from interface PopupWindowContent.\n     E.g use it for short lived content where closing on lost focus is ok.\n     */\n    public abstract class PopupWindowContent\n    {\n        public EditorWindow editorWindow { get; internal set; }\n\n        public virtual void OnGUI(Rect rect) { }\n        public virtual VisualElement CreateGUI() => null;\n\n        public virtual Vector2 GetWindowSize()\n        {\n            return new Vector2(200, 200);\n        }\n\n        public virtual void OnOpen() {}\n        public virtual void OnClose() {}\n    }\n\n    public class PopupWindow : EditorWindow\n    {\n        const string k_UssClassName = \"unity-popup-window-root\";\n        const string k_InvalidSizeTemplate = \"Invalid content size: {0}. Specify dimensions greater than zero in <i>CreateGUI</i>.\";\n\n        public static readonly string invalidSizeLabelUssClassName = \"unity-popup-window__invalid-size-label\";\n        static readonly Vector2 k_DefaultWindowSize = new(10, 10);\n\n        PopupWindowContent m_WindowContent;\n        Vector2 m_LastWantedSize;\n        Rect m_ActivatorRect;\n        PopupLocation[] m_LocationPriorityOrder;\n        static double s_LastClosedTime;\n        static Rect s_LastActivatorRect;\n        VisualElement m_UserContent;\n\n        bool UseIMGUI => !UseUIToolkit;\n        bool UseUIToolkit => m_UserContent != null;\n\n        internal PopupWindow()\n        {\n        }\n\n        public static void Show(Rect activatorRect, PopupWindowContent windowContent)\n        {\n            Show(activatorRect, windowContent, null);\n        }\n\n        internal static void Show(Rect activatorRect, PopupWindowContent windowContent, PopupLocation[] locationPriorityOrder)\n        {\n            Show(activatorRect, windowContent, locationPriorityOrder, ShowMode.PopupMenu);\n        }\n\n        // Shown on top of any previous windows\n        internal static void Show(Rect activatorRect, PopupWindowContent windowContent, PopupLocation[] locationPriorityOrder, ShowMode showMode)\n        {\n            // If we already have a popup window showing this type of content, then just close\n            // the existing one.\n            var existingPopup = FindExistingPopupWindow(windowContent);\n            if (existingPopup != null)\n            {\n                existingPopup.CloseWindow();\n                return;\n            }\n\n            if (ShouldShowWindow(activatorRect))\n            {\n                PopupWindow win = CreateInstance<PopupWindow>();\n                if (win != null)\n                {\n                    win.Init(activatorRect, windowContent, locationPriorityOrder, showMode, true);\n                }\n                if (Event.current != null && !GUIUtility.isUITK)\n                {\n                    EditorGUIUtility.ExitGUI(); // Needed to prevent GUILayout errors on OSX\n                }\n            }\n        }\n\n        internal static bool ShouldShowWindow(Rect activatorRect)\n        {\n            const double kJustClickedTime = 0.2;\n            bool justClosed = (EditorApplication.timeSinceStartup - s_LastClosedTime) < kJustClickedTime;\n            if (!justClosed || activatorRect != s_LastActivatorRect)\n            {\n                s_LastActivatorRect = activatorRect;\n                return true;\n            }\n            return false;\n        }\n\n        internal void Init(Rect activatorRect, PopupWindowContent windowContent, PopupLocation[] locationPriorityOrder, ShowMode showMode, bool giveFocus)\n        {\n            hideFlags = HideFlags.DontSave;\n            wantsMouseMove = true;\n            m_WindowContent = windowContent;\n            m_WindowContent.editorWindow = this;\n            m_WindowContent.OnOpen();\n            m_ActivatorRect = GUIUtility.GUIToScreenRect(activatorRect);\n            m_LastWantedSize = Vector2.zero;\n            m_LocationPriorityOrder = locationPriorityOrder;\n\n            ShowAsDropDown(m_ActivatorRect, k_DefaultWindowSize, locationPriorityOrder, showMode, giveFocus);\n\n            if (UseUIToolkit)\n                SetupPopupAutoSize();\n            else\n                FitWindowToContent();\n        }\n\n        internal void OnGUI()\n        {\n            if (UseIMGUI)\n            {\n                FitWindowToContent();\n                Rect windowRect = new Rect(0, 0, position.width, position.height);\n                m_WindowContent.OnGUI(windowRect);\n                GUI.Label(windowRect, GUIContent.none, \"grey_border\");\n                FitWindowToContent();\n            }\n        }\n\n        void CreateGUI()\n        {\n            m_UserContent = m_WindowContent?.CreateGUI();\n            if (m_UserContent != null)\n            {\n                var infiniteCanvas = new VisualElement { style = { position = Position.Absolute } };\n                infiniteCanvas.AddToClassList(k_UssClassName);\n                rootVisualElement.Add(infiniteCanvas);\n                infiniteCanvas.Add(m_UserContent);\n            }\n        }\n\n        void FitWindowToContent()\n        {\n            if (m_WindowContent == null)\n                return;\n            Vector2 wantedSize = m_WindowContent.GetWindowSize();\n            SetWindowSize(wantedSize);\n        }\n\n        void SetWindowSize(Vector2 size)\n        {\n            if (this && m_LastWantedSize != size)\n            {\n                m_LastWantedSize = size;\n                Rect screenRect = m_Parent.window.GetDropDownRect(m_ActivatorRect, size, size, m_LocationPriorityOrder);\n                position = screenRect;\n                minSize = maxSize = new Vector2(screenRect.width, screenRect.height);\n            }\n        }\n\n        void SetupPopupAutoSize()\n        {\n            if (UseUIToolkit && rootVisualElement.panel is Panel panel)\n            {\n                panel.ValidateLayout();\n                var contentSize = m_UserContent.layout.size;\n                if (contentSize.x <= 0f || contentSize.y <= 0f)\n                {\n                    var invalidSizeMessage = string.Format(k_InvalidSizeTemplate, contentSize);\n                    AddInvalidSizeLabel(invalidSizeMessage);\n                    panel.ValidateLayout(); // measure again to get the size of the label\n                }\n\n                var canvasSize = m_UserContent.parent.layout.size;\n                SetWindowSize(canvasSize);\n                m_UserContent.RegisterCallback<GeometryChangedEvent>(OnContentGeometryChanged);\n            }\n        }\n\n        void AddInvalidSizeLabel(string text)\n        {\n            var invalidSizeMessage = new TextElement\n            {\n                text = text,\n                enableRichText = true\n            };\n            invalidSizeMessage.AddToClassList(invalidSizeLabelUssClassName);\n            m_UserContent.Add(invalidSizeMessage);\n        }\n\n        void OnContentGeometryChanged(GeometryChangedEvent evt)\n        {\n            var size = evt.newRect.size;\n\n            // Schedule the size change to avoid multiple layout events in the same frame\n            rootVisualElement.schedule.Execute(() => { SetWindowSize(size); });\n        }\n\n        void CloseWindow()\n        {\n            Close();\n        }\n\n        protected virtual void OnEnable()\n        {\n            AssemblyReloadEvents.beforeAssemblyReload += CloseWindow;\n        }\n\n        protected virtual void OnDisable()\n        {\n            AssemblyReloadEvents.beforeAssemblyReload -= CloseWindow;\n\n            s_LastClosedTime = EditorApplication.timeSinceStartup;\n            CloseContent();\n        }\n\n        private protected void CloseContent()\n        {\n            m_WindowContent?.OnClose();\n            m_UserContent?.UnregisterCallback<GeometryChangedEvent>(OnContentGeometryChanged);\n            m_UserContent = null;\n        }\n\n        static PopupWindow FindExistingPopupWindow(PopupWindowContent windowContent)\n        {\n            var existingWindows = Resources.FindObjectsOfTypeAll(typeof(PopupWindow));\n            if (existingWindows != null && existingWindows.Length > 0)\n            {\n                var existingPopup = existingWindows[0] as PopupWindow;\n                if (existingPopup != null && existingPopup.m_WindowContent != null && windowContent != null)\n                {\n                    if (existingPopup.m_WindowContent.GetType() == windowContent.GetType())\n                    {\n                        return existingPopup;\n                    }\n                }\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/PopupWindowWithoutFocus.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Reflection;\n\nnamespace UnityEditor\n{\n    class PopupWindowWithoutFocus : PopupWindow\n    {\n        static PopupWindowWithoutFocus s_PopupWindowWithoutFocus;\n        bool hasBeenFocused = false;\n\n        public new static void Show(Rect activatorRect, PopupWindowContent windowContent)\n        {\n            Show(activatorRect, windowContent, null);\n        }\n\n        internal new static void Show(Rect activatorRect, PopupWindowContent windowContent, PopupLocation[] locationPriorityOrder)\n        {\n            if (windowContent == null)\n                throw new System.ArgumentNullException(nameof(windowContent));\n\n            if (s_PopupWindowWithoutFocus != null)\n            {\n                s_PopupWindowWithoutFocus.Close();\n                s_PopupWindowWithoutFocus = null;\n            }\n\n            if (ShouldShowWindow(activatorRect))\n            {\n                if (s_PopupWindowWithoutFocus == null)\n                    s_PopupWindowWithoutFocus = CreateInstance<PopupWindowWithoutFocus>();\n\n                s_PopupWindowWithoutFocus.Init(activatorRect, windowContent, locationPriorityOrder, ShowMode.PopupMenu, false);\n            }\n            else\n            {\n                windowContent.OnClose();\n            }\n        }\n\n        public static bool IsVisible()\n        {\n            return s_PopupWindowWithoutFocus != null;\n        }\n\n        [RequiredByNativeCode]\n        public static void Hide()\n        {\n            if (s_PopupWindowWithoutFocus != null)\n                s_PopupWindowWithoutFocus.Close();\n        }\n\n        protected override void OnEnable()\n        {\n            base.OnEnable();\n            hideFlags = HideFlags.DontSave;\n            s_PopupWindowWithoutFocus = this;\n        }\n\n        protected override void OnDisable()\n        {\n            s_PopupWindowWithoutFocus = null;\n            base.OnDisable();\n        }\n\n        // Invoked from C++\n        // If we want to use this paradigm long term, we should consider reducing the overhead of a managed call.\n        // Returns true if we suppress event propagation.\n        [RequiredByNativeCode]\n        static bool OnGlobalMouseOrKeyEvent(EventType type, KeyCode keyCode, Vector2 mousePosition)\n        {\n            bool suppress = false;\n\n            if (s_PopupWindowWithoutFocus == null)\n                return suppress;\n            else if (type == EventType.KeyDown)\n            {\n                if (keyCode == KeyCode.Escape)\n                {\n                    // Always close this window type when escape is pressed, even if never got focus.\n                    // We don't want the esc key propogated to the window with keyboard focus.\n                    s_PopupWindowWithoutFocus.Close();\n                    suppress = true;\n                }\n            }\n            else if (type == EventType.MouseDown && !s_PopupWindowWithoutFocus.hasBeenFocused)\n            {\n                // If the window has been clicked, it becomes a normal popup window that can spawn other windows and be treated as another AuxWindow.\n                // If the click was somewhere else, we assume that the user did not want to see this window anymore, so it should be closed.\n                if (s_PopupWindowWithoutFocus.position.Contains(mousePosition))\n                    s_PopupWindowWithoutFocus.hasBeenFocused = true;\n                else\n                    s_PopupWindowWithoutFocus.Close();\n            }\n\n            return suppress;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/PreviewResizer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    internal class PreviewResizer\n    {\n        // The raw preview size while dragging (not snapped to allowed values) (shared)\n        static float s_DraggedPreviewSize = 0;\n        // The returned preview size while dragging (shared)\n        static float s_CachedPreviewSizeWhileDragging = 0;\n        static float s_MouseDownLocation, s_MouseDownValue;\n        static bool s_MouseDragged;\n\n        // The last saved preview size - only saved when not dragging\n        // The saved value is the size when expanded - when collapsed the value is negative,\n        // so it can be restored when expanded again.\n        [SerializeField]\n        private float m_CachedPref;\n        [SerializeField]\n        private int m_ControlHash;\n        [SerializeField]\n        private string m_PrefName;\n\n        private int m_Id = 0;\n\n        private int id\n        {\n            get\n            {\n                if (m_Id == 0)\n                    m_Id = EditorGUIUtility.GetControlID(m_ControlHash, FocusType.Passive, new Rect());\n                return m_Id;\n            }\n        }\n\n        public bool localFrame { get; set; }\n\n        // Instances of this class should be serialized.\n        // The Init function will only have effect if the serialized values are not already set.\n        public void Init(string prefName)\n        {\n            if (m_ControlHash != 0 && !string.IsNullOrEmpty(m_PrefName))\n                return;\n\n            // The controlHash is set by the calling code\n            // There's one for the Inspector, one for LightmapEditor, etc.\n            m_ControlHash = prefName.GetHashCode();\n\n            // We'll have one pref name per controlHash\n            m_PrefName = \"Preview_\" + prefName;\n\n            // This is the only place the pref is read. This means we can have e.g. multiple\n            // Inspectors that can be controlled individually as long as they're open.\n            m_CachedPref = EditorPrefs.GetFloat(m_PrefName, 1);\n        }\n\n        public float ResizeHandle(Rect windowPosition, float minSize, float minRemainingSize, float resizerHeight)\n        {\n            return ResizeHandle(windowPosition, minSize, minRemainingSize, resizerHeight, new Rect());\n        }\n\n        public float ResizeHandle(Rect windowPosition, float minSize, float minRemainingSize, float resizerHeight, Rect dragRect)\n        {\n            // Sanity check the cached value. It can be positive or negative, but never smaller than the minSize\n            if (Mathf.Abs(m_CachedPref) < minSize)\n                m_CachedPref = minSize * Mathf.Sign(m_CachedPref);\n\n            float maxPreviewSize = windowPosition.height - minRemainingSize;\n            bool dragging = (GUIUtility.hotControl == id);\n\n            float previewSize = (dragging ? s_DraggedPreviewSize : Mathf.Max(0, m_CachedPref));\n            bool expanded = (m_CachedPref > 0);\n            float lastSize = Mathf.Abs(m_CachedPref);\n\n            Rect resizerRect = new Rect(0, windowPosition.height - previewSize - resizerHeight, windowPosition.width, resizerHeight);\n            if (dragRect.width != 0)\n            {\n                resizerRect.x = dragRect.x;\n                resizerRect.width = dragRect.width;\n            }\n\n            bool expandedBefore = expanded;\n            previewSize = -PixelPreciseCollapsibleSlider(id, resizerRect, -previewSize, -maxPreviewSize, -0, ref expanded, localFrame);\n            previewSize = Mathf.Min(previewSize, maxPreviewSize);\n            dragging = (GUIUtility.hotControl == id);\n\n            if (dragging)\n                s_DraggedPreviewSize = previewSize;\n\n            // First snap size between 0 and minimum size\n            if (previewSize < minSize)\n                previewSize = (previewSize < minSize * 0.5f ? 0 : minSize);\n\n            // If user clicked area, adjust size\n            if (expanded != expandedBefore)\n            {\n                previewSize = (expanded ? lastSize : 0);\n                GUI.changed = true;\n            }\n\n            // Determine new expanded state\n            expanded = (previewSize >= minSize / 2);\n\n            // Keep track of last preview size while not dragging or collapsed\n            // Note we don't want to save when dragging preview OR window size,\n            // so just don't save while dragging anything at all\n            if (GUIUtility.hotControl == 0)\n            {\n                if (previewSize > 0)\n                    lastSize = previewSize;\n                float newPref = lastSize * (expanded ? 1 : -1);\n                if (newPref != m_CachedPref)\n                {\n                    // Save the value to prefs\n                    m_CachedPref = newPref;\n                    EditorPrefs.SetFloat(m_PrefName, m_CachedPref);\n                }\n            }\n\n            s_CachedPreviewSizeWhileDragging = previewSize;\n            return previewSize;\n        }\n\n        public float SetExpanded(Rect windowPosition, float minSize, float minRemainingSize, float resizerHeight, Rect dragRect, bool isExpanded)\n        {\n            // Sanity check the cached value. It can be positive or negative, but never smaller than the minSize\n            if (Mathf.Abs(m_CachedPref) < minSize)\n                m_CachedPref = minSize * Mathf.Sign(m_CachedPref);\n\n            float maxPreviewSize = windowPosition.height - minRemainingSize;\n\n            float previewSize = Mathf.Max(0, m_CachedPref);\n            bool expanded = (m_CachedPref > 0);\n            float lastSize = Mathf.Abs(m_CachedPref);\n\n            Rect resizerRect = new Rect(0, windowPosition.height - previewSize - resizerHeight, windowPosition.width, resizerHeight);\n            if (dragRect.width != 0)\n            {\n                resizerRect.x = dragRect.x;\n                resizerRect.width = dragRect.width;\n            }\n\n            bool expandedBefore = expanded;\n            expanded = isExpanded;\n            previewSize = -previewSize;\n            previewSize = Mathf.Min(previewSize, maxPreviewSize);\n\n            // First snap size between 0 and minimum size\n            if (previewSize < minSize)\n                previewSize = (previewSize < minSize * 0.5f ? 0 : minSize);\n\n            // If user clicked area, adjust size\n            if (expanded != expandedBefore)\n            {\n                previewSize = (expanded ? lastSize : 0);\n            }\n\n            // Determine new expanded state\n            expanded = (previewSize >= minSize / 2);\n            if (previewSize > 0)\n                lastSize = previewSize;\n            float newPref = lastSize * (expanded ? 1 : -1);\n            if (newPref != m_CachedPref)\n            {\n                // Save the value to prefs\n                m_CachedPref = newPref;\n                EditorPrefs.SetFloat(m_PrefName, m_CachedPref);\n            }\n\n            s_CachedPreviewSizeWhileDragging = previewSize;\n            return previewSize;\n        }\n\n        // This value will change in realtime while dragging\n        public bool GetExpanded()\n        {\n            if (GUIUtility.hotControl == id)\n                return (s_CachedPreviewSizeWhileDragging > 0);\n            else\n                return (m_CachedPref > 0);\n        }\n\n        public float GetPreviewSize()\n        {\n            if (GUIUtility.hotControl == id)\n                return Mathf.Max(0, s_CachedPreviewSizeWhileDragging);\n            else\n                return Mathf.Max(0, m_CachedPref);\n        }\n\n        // This value won't change until we have stopped dragging again\n        public bool GetExpandedBeforeDragging()\n        {\n            return (m_CachedPref > 0);\n        }\n\n        public void SetExpanded(bool expanded)\n        {\n            if (GetExpanded() == expanded)\n                return;\n            // Set the sign based on whether it's collapsed or not, then save to prefs\n            m_CachedPref = Mathf.Abs(m_CachedPref) * (expanded ? 1 : -1);\n            EditorPrefs.SetFloat(m_PrefName, m_CachedPref);\n\n            if (m_Container != null)\n            {\n                m_Container.style.minHeight = expanded ? containerMinimumHeightExpanded : m_ContainerMinimumHeightCollapsed;\n            }\n        }\n\n        public void ToggleExpanded()\n        {\n            // Reverse the sign, then save to prefs\n            m_CachedPref = -m_CachedPref;\n            EditorPrefs.SetFloat(m_PrefName, m_CachedPref);\n\n            if (m_Container != null)\n            {\n                m_Container.style.minHeight = m_CachedPref > 0 ? containerMinimumHeightExpanded : m_ContainerMinimumHeightCollapsed;\n            }\n        }\n\n        // This is the slider behavior for resizing the preview area\n        public static float PixelPreciseCollapsibleSlider(int id, Rect position, float value, float min, float max,\n            ref bool expanded)\n        {\n            return PixelPreciseCollapsibleSlider(id, position, value, min, max, ref expanded, false);\n        }\n\n        public static float PixelPreciseCollapsibleSlider(int id, Rect position, float value, float min, float max, ref bool expanded, bool localFrame)\n        {\n            Event evt = Event.current;\n\n            if (evt.type == EventType.Layout)\n            {\n                return value;\n            }\n\n            var mousePosition = evt.mousePosition;\n\n            if (localFrame)\n            {\n                mousePosition = GUIClip.UnclipToWindow(evt.mousePosition);\n                mousePosition.y -= Editor.k_HeaderHeight;\n            }\n\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (GUIUtility.hotControl == 0 && evt.button == 0 && position.Contains(mousePosition))\n                    {\n                        GUIUtility.hotControl = id;\n                        s_MouseDownLocation = mousePosition.y;\n                        s_MouseDownValue = value;\n                        s_MouseDragged = false;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        value = Mathf.Clamp(mousePosition.y - s_MouseDownLocation + s_MouseDownValue, min, max - 1);\n                        GUI.changed = true;\n                        s_MouseDragged = true;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n                        if (!s_MouseDragged)\n                            expanded = !expanded;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.Repaint:\n                    float x = position.x;\n                    float y = position.y;\n\n                    if (localFrame)\n                    {\n                        x = 0f;\n                        y = 0f;\n                    }\n\n                    if (GUIUtility.hotControl == 0)\n                    {\n                        EditorGUIUtility.AddCursorRect(new Rect(x, y, position.width, position.height), MouseCursor.SplitResizeUpDown);\n                    }\n\n                    if (GUIUtility.hotControl == id)\n                    {\n                        const int yMove = 100;\n                        const int heightMove = yMove * 2;\n                        EditorGUIUtility.AddCursorRect(new Rect(x, y - yMove, position.width, position.height + heightMove), MouseCursor.SplitResizeUpDown);\n                    }\n                    break;\n            }\n            return value;\n        }\n\n        IMGUIContainer m_Container;\n        internal float containerMinimumHeightExpanded;\n        float m_ContainerMinimumHeightCollapsed;\n\n        internal void SetContainer(IMGUIContainer container, float minimumHeightCollapsed)\n        {\n            m_Container = container;\n            m_ContainerMinimumHeightCollapsed = minimumHeightCollapsed;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/RenameOverlay.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing UnityEngine.Assertions;\nusing UnityEngine.Events;\n\nnamespace UnityEditor\n{\n    // Usage:\n    // BeginRename (string name, int userData, float delay) - Starts a rename\n    // EndRename (bool acceptChanges) - Ends rename and caches state (use property interface for client reaction)\n    // IsRenaming() - Is renaming active (we might still not show anything due to 'delay' parameter in BeginRename)\n    // Clear() - Clears rename state\n    // IMPORTANT:\n    // OnEvent () - Should be called early in an OnGUI of an EditorWindow that is using this RenameOverlay (handles closing if clicking outside and closing while receving any input while delayed, and caches controlID for text field)\n    // OnGUI (GUIStyle textFieldStyle) - Should be called late to ensure rendered on top and early for non-repaint event to handle input before other ui logic\n\n    internal class RenameOverlay : RenameOverlay<int>{}\n\n    [System.Serializable]\n    internal class RenameOverlay<TValue>\n    {\n        [SerializeField]\n        bool m_UserAcceptedRename;\n        [SerializeField]\n        string m_Name;\n        [SerializeField]\n        string m_OriginalName;\n        [SerializeField]\n        Rect m_EditFieldRect;\n        [SerializeField]\n        TValue m_UserData;\n        [SerializeField]\n        bool m_IsWaitingForDelay;\n        [SerializeField]\n        bool m_IsRenaming = false;\n        [SerializeField]\n        EventType m_OriginalEventType = EventType.Ignore;\n        [SerializeField]\n        bool m_IsRenamingFilename = false;\n        [SerializeField]\n        bool m_TrimLeadingAndTrailingWhitespace = false;\n        [SerializeField]\n        GUIView m_ClientGUIView;\n\n        [System.NonSerialized]\n        Rect m_LastScreenPosition;\n        [System.NonSerialized]\n        bool m_UndoRedoWasPerformed;\n\n        string k_RenameOverlayFocusName = \"RenameOverlayField\";\n\n        // property interface\n        public string name { get {return m_Name; } internal set { m_Name = value; } }\n        public string originalName { get {return m_OriginalName; }}\n        public bool userAcceptedRename { get {return m_UserAcceptedRename; }}\n        public TValue userData { get {return m_UserData; }}\n        public bool isWaitingForDelay { get {return m_IsWaitingForDelay; }}\n        public Rect editFieldRect { get {return m_EditFieldRect; } set {m_EditFieldRect = value; }}\n        public bool isRenamingFilename {get {return m_IsRenamingFilename; } set {m_IsRenamingFilename = value; }}\n        public bool trimLeadingAndTrailingWhitespace\n        {\n            get { return m_TrimLeadingAndTrailingWhitespace; }\n            set { m_TrimLeadingAndTrailingWhitespace = value; }\n        }\n\n        private static GUIStyle s_DefaultTextFieldStyle = null;\n        private static int s_TextFieldHash = \"RenameFieldTextField\".GetHashCode();\n        private int m_TextFieldControlID;\n\n        // Returns true if started renaming\n        public bool BeginRename(string name, TValue userData, float delay)\n        {\n            if (m_IsRenaming)\n            {\n                return false;\n            }\n\n            m_Name = name;\n            m_OriginalName = name;\n            m_UserData = userData;\n            m_UserAcceptedRename = false;\n            m_IsWaitingForDelay = delay > 0f;\n            m_IsRenaming = true;\n            m_EditFieldRect = new Rect(0, 0, 0, 0);\n            m_ClientGUIView = GUIView.current;\n\n            if (delay > 0f)\n                EditorApplication.CallDelayed(BeginRenameInternalCallback, delay);\n            else\n                BeginRenameInternalCallback();\n            return true;\n        }\n\n        void BeginRenameInternalCallback()\n        {\n            EditorGUI.s_RecycledEditor.text = m_Name;\n            EditorGUI.s_RecycledEditor.SelectAll();\n            RepaintClientView();\n\n            m_IsWaitingForDelay = false;\n\n            Undo.undoRedoEvent -= UndoRedoWasPerformed;\n            Undo.undoRedoEvent += UndoRedoWasPerformed;\n        }\n\n        public void EndRename(bool acceptChanges)\n        {\n            EditorGUIUtility.editingTextField = false;\n            if (!m_IsRenaming)\n                return;\n\n            EditorGUIUtility.renameWasCompleted = true;\n\n            Undo.undoRedoEvent -= UndoRedoWasPerformed;\n            EditorApplication.update -= BeginRenameInternalCallback;\n\n            RemoveMessage();\n\n            if (isRenamingFilename)\n                m_Name = InternalEditorUtility.RemoveInvalidCharsFromFileName(m_Name, true);\n\n            if (trimLeadingAndTrailingWhitespace)\n            {\n                var trimmedName = m_Name.Trim();\n                if (trimmedName != m_Name)\n                {\n                    m_Name = trimmedName;\n                    ShowMessage(\"Leading/trailing whitespace was removed.\");\n                    TooltipView.AutoCloseAfterDelay(2f);\n                }\n            }\n\n            m_IsRenaming = false;\n            m_IsWaitingForDelay = false;\n            m_UserAcceptedRename = acceptChanges;\n\n            // For issuing event for client to react on end of rename\n            RepaintClientView();\n        }\n\n        private void RepaintClientView()\n        {\n            if (m_ClientGUIView != null)\n                m_ClientGUIView.Repaint();\n        }\n\n        public void Clear()\n        {\n            m_IsRenaming = false;\n            m_UserAcceptedRename = false;\n            m_Name = \"\";\n            m_OriginalName = \"\";\n            m_EditFieldRect = new Rect();\n            m_UserData = default;\n            m_IsWaitingForDelay = false;\n            m_OriginalEventType = EventType.Ignore;\n            Undo.undoRedoEvent -= UndoRedoWasPerformed;\n\n            // m_IsRenamingFilename = false; // Only clear temp data used for renaming not state that we want to persist\n        }\n\n        void UndoRedoWasPerformed(in UndoRedoInfo info)\n        {\n            // If undo/redo was performed then close the rename overlay as it does not support undo/redo\n            // We need to delay the EndRename until next OnGUI as clients poll the state of the rename overlay state there\n            m_UndoRedoWasPerformed = true;\n        }\n\n        public bool HasKeyboardFocus()\n        {\n            return (GUI.GetNameOfFocusedControl() == k_RenameOverlayFocusName);\n        }\n\n        public bool IsRenaming()\n        {\n            return m_IsRenaming;\n        }\n\n        // Should be called as early as possible in an EditorWindow using this RenameOverlay\n        // Returns: false if rename was ended due to input while waiting for delay\n        public bool OnEvent()\n        {\n            if (!m_IsRenaming)\n                return true;\n\n            if (!m_IsWaitingForDelay)\n            {\n                // We get control ID separate from OnGUI because we want to call OnGUI early and late: handle input first but render on top\n                GUIUtility.GetControlID(84895748, FocusType.Passive);\n                GUI.SetNextControlName(k_RenameOverlayFocusName);\n                EditorGUI.FocusTextInControl(k_RenameOverlayFocusName);\n                m_TextFieldControlID = GUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, m_EditFieldRect);\n            }\n\n            // Workaround for Event not having the original eventType stored\n            m_OriginalEventType = Event.current.type;\n\n            // Clear state if necessary while waiting for rename (0.5 second)\n            if (m_IsWaitingForDelay && (m_OriginalEventType == EventType.MouseDown || m_OriginalEventType == EventType.KeyDown))\n            {\n                EndRename(false);\n                return false;\n            }\n\n            return true;\n        }\n\n        public bool OnGUI()\n        {\n            return OnGUI(null);\n        }\n\n        // Should be called when IsRenaming () returns true to draw the overlay and handle events.\n        // Returns true if renaming is still active, false if not (user canceled, accepted, clicked outside edit rect etc).\n        // If textFieldStyle == null then a default style is used.\n        public bool OnGUI(GUIStyle textFieldStyle)\n        {\n            if (m_IsWaitingForDelay)\n            {\n                // Delayed start\n                return true;\n            }\n\n            // Ended from outside\n            if (!m_IsRenaming)\n            {\n                return false;\n            }\n\n            if (m_UndoRedoWasPerformed)\n            {\n                m_UndoRedoWasPerformed = false;\n                EndRename(false);\n                return false;\n            }\n\n            if (m_EditFieldRect.width <= 0 || m_EditFieldRect.height <= 0 || m_TextFieldControlID == 0)\n            {\n                // Due to call order dependency we might not have a valid rect to render yet or have called OnEvent when renaming was active and therefore controlID can be uninitialzied so\n                // we ensure to issue repaints until these states are valid\n                HandleUtility.Repaint();\n                return true;\n            }\n\n            Event evt = Event.current;\n            if (evt.type == EventType.KeyDown)\n            {\n                if (evt.keyCode == KeyCode.Escape)\n                {\n                    evt.Use();\n                    EndRename(false);\n                    return false;\n                }\n                if (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter)\n                {\n                    evt.Use();\n                    EndRename(true);\n                    return false;\n                }\n            }\n\n            // Detect if we clicked outside the text field (must be before text field below which steals keyboard control)\n            // To workaround that, we assume that an used mousedown event means a click outside.\n            if (m_OriginalEventType == EventType.MouseDown && (Event.current.type == EventType.Used || !m_EditFieldRect.Contains(Event.current.mousePosition)))\n            {\n                EndRename(true);\n                return false;\n            }\n\n            m_Name = DoTextField(m_Name, textFieldStyle);\n\n            if (evt.type == EventType.ScrollWheel)\n                evt.Use();\n\n            return true;\n        }\n\n        string DoTextField(string text, GUIStyle textFieldStyle)\n        {\n            if (m_TextFieldControlID == 0)\n                Debug.LogError(\"RenameOverlay: Ensure to call OnEvent() as early as possible in the OnGUI of the current EditorWindow!\");\n\n            if (s_DefaultTextFieldStyle == null)\n                s_DefaultTextFieldStyle = \"PR TextField\";\n\n            if (isRenamingFilename)\n                EatInvalidChars();\n\n            GUI.changed = false;\n            bool dummy;\n\n            // Ensure the rename textfield has keyboardcontrol (Could have been stolen previously in this OnGUI)\n            if (GUIUtility.keyboardControl != m_TextFieldControlID)\n                GUIUtility.keyboardControl = m_TextFieldControlID;\n\n            GUIStyle style = textFieldStyle ?? s_DefaultTextFieldStyle;\n            Rect rect = EditorGUI.IndentedRect(m_EditFieldRect);\n            rect.xMin -= style.padding.left; // Adjust rect so rename text matches client text\n\n            return EditorGUI.DoTextField(EditorGUI.s_RecycledEditor, m_TextFieldControlID, rect, text, style, null, out dummy, false, false, false);\n        }\n\n        void EatInvalidChars()\n        {\n            if (isRenamingFilename)\n            {\n                Event evt = Event.current;\n                if (GUIUtility.keyboardControl == m_TextFieldControlID && evt.GetTypeForControl(m_TextFieldControlID) == EventType.KeyDown)\n                {\n                    string errorMsg = \"\";\n\n                    string invalidChars = EditorUtility.GetInvalidFilenameChars();\n                    if (invalidChars.IndexOf(evt.character) > -1)\n                        errorMsg = \"A file name can't contain any of the following characters:\\t\" + invalidChars;\n\n                    if (errorMsg != \"\")\n                    {\n                        evt.Use();  // Eat character: prevents the textfield from inputting this evt.character\n                        ShowMessage(errorMsg);\n                    }\n                    else\n                    {\n                        RemoveMessage();\n                    }\n                }\n\n                // Remove tooltip if screenpos of overlay has changed (handles the case where the main window is being moved or docked window\n                // is resized)\n                if (evt.type == EventType.Repaint)\n                {\n                    Rect screenPos = GetScreenRect();\n                    if (!Mathf.Approximately(m_LastScreenPosition.x, screenPos.x) || !Mathf.Approximately(m_LastScreenPosition.y, screenPos.y))\n                    {\n                        RemoveMessage();\n                    }\n                    m_LastScreenPosition = screenPos;\n                }\n            }\n        }\n\n        Rect GetScreenRect()\n        {\n            return GUIUtility.GUIToScreenRect(m_EditFieldRect);\n        }\n\n        void ShowMessage(string msg)\n        {\n            TooltipView.Show(msg, GetScreenRect(), null);\n        }\n\n        void RemoveMessage()\n        {\n            TooltipView.ForceClose();\n        }\n    }\n\n    [Serializable]\n    internal class SerializableDelayedCallback : ScriptableObject\n    {\n        [SerializeField]\n        private long m_CallbackTicks;\n\n        [SerializeField]\n        private UnityEvent m_Callback;\n\n        protected SerializableDelayedCallback()\n        {\n            m_Callback = new UnityEvent();\n            EditorApplication.update += Update;\n        }\n\n        public static SerializableDelayedCallback SubscribeCallback(UnityAction action, TimeSpan delayUntilCallback)\n        {\n            var serializableDelayedCallback = ScriptableObject.CreateInstance<SerializableDelayedCallback>();\n            serializableDelayedCallback.m_CallbackTicks = DateTime.UtcNow.Add(delayUntilCallback).Ticks;\n            serializableDelayedCallback.m_Callback.AddPersistentListener(action, UnityEventCallState.EditorAndRuntime);\n            return serializableDelayedCallback;\n        }\n\n        public void Cancel()\n        {\n            EditorApplication.update -= Update;\n        }\n\n        private void Update()\n        {\n            var utcNowTicks = DateTime.UtcNow.Ticks;\n            if (utcNowTicks >= m_CallbackTicks)\n            {\n                EditorApplication.update -= Update;\n                m_Callback.Invoke();\n            }\n        }\n    }\n\n    // [Obsolete(\"Use EditorApplication.CallDelayed or EditorApplication.delayCall instead.\")]\n    internal interface IDelayedCallback\n    {\n        void Clear();\n        void Reset();\n    }\n\n    // [Obsolete(\"Use EditorApplication.CallDelayed or EditorApplication.delayCall instead.\")]\n    internal class DelayedCallback : IDelayedCallback\n    {\n        private System.Action m_Callback;\n        private double m_CallbackTime;\n        private double m_Delay;\n\n        public DelayedCallback(System.Action function, double timeFromNow)\n        {\n            Assert.IsTrue(function != null);\n\n            m_Callback = function;\n            m_CallbackTime = EditorApplication.timeSinceStartup + timeFromNow;\n            m_Delay = timeFromNow;\n            EditorApplication.update += Update;\n        }\n\n        public void Clear()\n        {\n            EditorApplication.update -= Update;\n            m_CallbackTime = 0.0;\n            m_Callback = null;\n        }\n\n        void Update()\n        {\n            if (EditorApplication.timeSinceStartup > m_CallbackTime)\n            {\n                // Clear state before firing callback to ensure reset (callback could call ExitGUI)\n                var callback = m_Callback;\n                Clear();\n\n                callback?.Invoke();\n            }\n        }\n\n        public void Reset()\n        {\n            if (m_Callback != null)\n            {\n                m_CallbackTime = EditorApplication.timeSinceStartup + m_Delay;\n            }\n        }\n    }\n} // end namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/ReorderableList.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Collections.ObjectModel;\nusing Object = UnityEngine.Object;\nusing System.Linq;\nusing System.Reflection;\nusing System.Text.RegularExpressions;\nusing UnityEngine.Pool;\n\nnamespace UnityEditorInternal\n{\n    //TODO: better handling for serializedObjects with mixed values\n    //TODO: make it not rely on GUILayout at all, so its safe to use under PropertyDrawers.\n    public class ReorderableList\n    {\n        public delegate void HeaderCallbackDelegate(Rect rect);\n        public delegate void FooterCallbackDelegate(Rect rect);\n        public delegate void ElementCallbackDelegate(Rect rect, int index, bool isActive, bool isFocused);\n        public delegate float ElementHeightCallbackDelegate(int index);\n        public delegate void DrawNoneElementCallback(Rect rect);\n\n        public delegate void ReorderCallbackDelegateWithDetails(ReorderableList list, int oldIndex, int newIndex);\n        public delegate void ReorderCallbackDelegate(ReorderableList list);\n        public delegate void SelectCallbackDelegate(ReorderableList list);\n        public delegate void AddCallbackDelegate(ReorderableList list);\n        public delegate void AddDropdownCallbackDelegate(Rect buttonRect, ReorderableList list);\n        public delegate void RemoveCallbackDelegate(ReorderableList list);\n        public delegate void ChangedCallbackDelegate(ReorderableList list);\n        public delegate bool CanRemoveCallbackDelegate(ReorderableList list);\n        public delegate bool CanAddCallbackDelegate(ReorderableList list);\n        public delegate void DragCallbackDelegate(ReorderableList list);\n\n        // draw callbacks\n        public HeaderCallbackDelegate drawHeaderCallback;\n        public FooterCallbackDelegate drawFooterCallback = null;\n        public ElementCallbackDelegate drawElementCallback;\n        public ElementCallbackDelegate drawElementBackgroundCallback;\n        public DrawNoneElementCallback drawNoneElementCallback = null;\n\n        // layout callbacks\n        // if supplying own element heights, try to cache the results as this may be called frequently\n        public ElementHeightCallbackDelegate elementHeightCallback;\n\n        // interaction callbacks\n        public ReorderCallbackDelegateWithDetails onReorderCallbackWithDetails;\n        public ReorderCallbackDelegate onReorderCallback;\n        public SelectCallbackDelegate onSelectCallback;\n        public AddCallbackDelegate onAddCallback;\n        public AddDropdownCallbackDelegate onAddDropdownCallback;\n        public RemoveCallbackDelegate onRemoveCallback;\n        public DragCallbackDelegate onMouseDragCallback;\n        public SelectCallbackDelegate onMouseUpCallback;\n        public CanRemoveCallbackDelegate onCanRemoveCallback;\n        public CanAddCallbackDelegate onCanAddCallback;\n        public ChangedCallbackDelegate onChangedCallback;\n\n        internal List<int> m_Selection = new List<int>();\n        private float m_DragOffset = 0;\n        private GUISlideGroup m_SlideGroup;\n\n        private SerializedObject m_SerializedObject;\n        private SerializedProperty m_Elements;\n        private string m_PropertyPath = string.Empty;\n        private IList m_ElementList;\n        private bool m_Draggable;\n        private float m_DraggedY;\n        private bool m_Dragging;\n        private List<int> m_NonDragTargetIndices;\n\n        private bool m_DisplayHeader;\n        public bool displayAdd;\n        public bool displayRemove;\n\n        bool m_scheduleRemove;\n\n        internal bool m_IsEditable;\n        internal bool m_HasPropertyDrawer;\n        internal int m_CacheCount = 0; // This one has to be internal so that we can execute multiple tests in one frame\n\n        private int id = -1;\n\n        bool m_ScheduleGUIChanged = false;\n        internal struct PropertyCacheEntry\n        {\n            public SerializedProperty property;\n            public float height;\n            public float offset;\n            public int controlCount;\n\n            public bool Set(SerializedProperty property, float height, float offset)\n            {\n                bool heightChange = this.height != height;\n\n                this.property = property;\n                this.height = height;\n                this.offset = offset;\n\n                // Schedule recaching if height is changing. Otherwise we might mishandle animated GUI controls\n                return heightChange;\n            }\n        }\n        internal bool m_PropertyCacheValid = false;\n        PropertyCacheEntry[] m_PropertyCache = new PropertyCacheEntry[0];\n        static List<string> m_OutdatedProperties = new List<string>();\n\n        static string GetParentListPath(string propertyPath)\n        {\n            int parentPathLength = propertyPath.LastIndexOf(\".Array.data[\");\n\n            if (parentPathLength < 0) return null;\n\n            return propertyPath.Substring(0, parentPathLength);\n        }\n\n        internal static void InvalidateParentCaches(string propertyPath)\n        {\n            string parentPath = GetParentListPath(propertyPath);\n            while (parentPath != null)\n            {\n                m_OutdatedProperties.Add(parentPath);\n                parentPath = GetParentListPath(parentPath);\n            }\n        }\n\n        bool CheckForChildInvalidation()\n        {\n            if (m_OutdatedProperties.BinarySearch(m_PropertyPath) >= 0)\n            {\n                InvalidateCache();\n                m_OutdatedProperties = m_OutdatedProperties.Where(e => !e.Equals(m_PropertyPath)).ToList();\n                return true;\n            }\n            return false;\n        }\n\n        internal void InvalidateForGUI()\n        {\n            if (!m_SerializedObject?.isEditingMultipleObjects ?? true)\n            {\n                InvalidateCache();\n            }\n            else\n            {\n                InvalidateExistingListCaches();\n                EditorApplication.delayCall += InspectorWindow.RefreshInspectors;\n            }\n        }\n\n        // class for default rendering and behavior of reorderable list - stores styles and is statically available as s_Defaults\n        public class Defaults\n        {\n            public GUIContent iconToolbarPlus = EditorGUIUtility.TrIconContent(\"Toolbar Plus\", \"Add to the list\");\n            public GUIContent iconToolbarPlusMore = EditorGUIUtility.TrIconContent(\"Toolbar Plus More\", \"Choose to add to the list\");\n            public GUIContent iconToolbarMinus = EditorGUIUtility.TrIconContent(\"Toolbar Minus\", \"Remove selection from the list\");\n            public readonly GUIStyle draggingHandle = \"RL DragHandle\";\n            public readonly GUIStyle headerBackground = \"RL Header\";\n            public readonly GUIStyle emptyHeaderBackground = \"RL Empty Header\";\n            public readonly GUIStyle footerBackground = \"RL Footer\";\n            public readonly GUIStyle boxBackground = \"RL Background\";\n            public readonly GUIStyle preButton = \"RL FooterButton\";\n            public readonly GUIStyle elementBackground = \"RL Element\";\n            internal readonly GUIStyle defaultLabel = new GUIStyle(EditorStyles.label);\n            public const int padding = 6;\n            public const int dragHandleWidth = 20;\n            internal const int propertyDrawerPadding = 8;\n            internal const int minHeaderHeight = 2;\n            const float elementPadding = 2;\n            private int ArrayCountInPropertyPath(SerializedProperty prop) => Regex.Matches(prop.propertyPath, \".Array.data\").Count;\n            private float FieldLabelSize(Rect r, SerializedProperty prop) => r.width * 0.45f - 20 - ArrayCountInPropertyPath(prop) * 22 + (prop.depth < 2 ? 7 : 0);\n            private static readonly GUIContent s_ListIsEmpty = EditorGUIUtility.TrTextContent(\"List is Empty\");\n            internal static readonly string undoAdd = \"Add Element To Array\";\n            internal static readonly string undoRemove = \"Remove Element From Array\";\n            internal static readonly string undoMove = \"Reorder Element In Array\";\n            internal static readonly Rect infinityRect = new Rect(float.NegativeInfinity, float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity);\n            internal static float ElementPadding(float height) => height != 0 ? elementPadding : 0;\n\n            public Defaults()\n            {\n                defaultLabel.wordWrap = true;\n                defaultLabel.alignment = TextAnchor.MiddleCenter;\n            }\n\n            private static GUIContent OverMaxMultiEditLimit(int maxMultiEditElementCount) => EditorGUIUtility.TrTextContent($\"This field cannot display arrays with more than {maxMultiEditElementCount} elements when multiple objects are selected.\");\n\n            // draw the default footer\n            public void DrawFooter(Rect rect, ReorderableList list)\n            {\n                float rightEdge = rect.xMax - 10f;\n                float leftEdge = rightEdge - 8f;\n                if (list.displayAdd)\n                    leftEdge -= 25;\n                if (list.displayRemove)\n                    leftEdge -= 25;\n                rect = new Rect(leftEdge, rect.y, rightEdge - leftEdge, rect.height);\n                Rect addRect = new Rect(leftEdge + 4, rect.y, 25, 16);\n                Rect removeRect = new Rect(rightEdge - 29, rect.y, 25, 16);\n                if (Event.current.type == EventType.Repaint)\n                {\n                    footerBackground.Draw(rect, false, false, false, false);\n                }\n                if (list.displayAdd)\n                {\n                    using (new EditorGUI.DisabledScope(\n                        list.onCanAddCallback != null && !list.onCanAddCallback(list) || list.isOverMaxMultiEditLimit))\n                    {\n                        if (GUI.Button(addRect, list.onAddDropdownCallback != null ? iconToolbarPlusMore : iconToolbarPlus, preButton))\n                        {\n                            if (list.onAddDropdownCallback != null)\n                                list.onAddDropdownCallback(addRect, list);\n                            else if (list.onAddCallback != null)\n                                list.onAddCallback(list);\n                            else\n                                DoAddButton(list);\n\n                            list.onChangedCallback?.Invoke(list);\n                            list.InvalidateCacheRecursive();\n                        }\n                    }\n                }\n                if (list.displayRemove)\n                {\n                    using (new EditorGUI.DisabledScope(list.index < 0 || list.index >= list.count\n                        || (list.onCanRemoveCallback != null && !list.onCanRemoveCallback(list))\n                        || list.isOverMaxMultiEditLimit))\n                    {\n                        if (GUI.Button(removeRect, iconToolbarMinus, preButton) || GUI.enabled && list.m_scheduleRemove)\n                        {\n                            if (list.onRemoveCallback == null)\n                            {\n                                DoRemoveButton(list);\n                            }\n                            else\n                                list.onRemoveCallback(list);\n\n                            list.onChangedCallback?.Invoke(list);\n                            list.InvalidateCacheRecursive();\n                            GUI.changed = true;\n                        }\n                    }\n                }\n\n                list.m_scheduleRemove = false;\n            }\n\n            // default add button behavior\n            internal void DoAddButton(ReorderableList list, Object value)\n            {\n                if (GUIUtility.keyboardControl != list.id) list.GrabKeyboardFocus();\n\n                if (list.serializedProperty != null)\n                {\n                    list.serializedProperty = list.serializedProperty.serializedObject.FindProperty(list.m_PropertyPath);\n                    list.serializedProperty.arraySize = list.count + 1;\n                    list.index = list.serializedProperty.arraySize - 1;\n\n                    if (value != null)\n                    {\n                        list.serializedProperty.GetArrayElementAtIndex(list.index).objectReferenceValue = value;\n                    }\n                }\n                else\n                {\n                    // this is ugly but there are a lot of cases like null types and default constructors\n\n                    //GetElementType() returns the Type of the object encompassed or referred to by the current array, pointer, or reference type,\n                    //or null if the current Type is not an array or a pointer, or is not passed by reference,\n                    //or represents a generic type or a type parameter in the definition of a generic type or generic method.\n                    Type listType = list.list.GetType();\n                    Type elementType;\n                    if (listType.IsGenericType)\n                        elementType = listType.GetTypeInfo().GenericTypeArguments[0];\n                    else\n                        elementType = listType.GetElementType();\n                    if (value != null)\n                        list.index = list.list.Add(value);\n                    else if (elementType == typeof(string))\n                        list.index = list.list.Add(\"\");\n                    else if (list.list.GetType().GetGenericArguments()[0] != null)\n                        list.index = list.list.Add(Activator.CreateInstance(list.list.GetType().GetGenericArguments()[0]));\n                    else if (elementType != null && elementType.GetConstructor(Type.EmptyTypes) == null)\n                        Debug.LogError(\"Cannot add element. Type \" + elementType + \" has no default constructor. Implement a default constructor or implement your own add behaviour.\");\n                    else if (elementType != null)\n                        list.index = list.list.Add(Activator.CreateInstance(elementType));\n                    else\n                        Debug.LogError(\"Cannot add element of type Null.\");\n                }\n                Undo.SetCurrentGroupName(undoAdd);\n                list.InvalidateForGUI();\n            }\n\n            public void DoAddButton(ReorderableList list)\n            {\n                DoAddButton(list, null);\n            }\n\n            // default remove button behavior\n            public void DoRemoveButton(ReorderableList list)\n            {\n                if (GUIUtility.keyboardControl != list.id) list.GrabKeyboardFocus();\n\n                int[] deleteIndexes = list.m_Selection.Count > 0 ? list.selectedIndices.Reverse<int>().ToArray() : new[] { list.index };\n                int lastDeletedIndex = -1;\n                // Remove in reverse so we do not need to keep track of changing indexes\n                foreach (var index in deleteIndexes)\n                {\n                    if (index >= list.count)\n                        continue;\n\n                    if (list.serializedProperty != null)\n                    {\n                        list.serializedProperty.DeleteArrayElementAtIndex(index);\n\n                        if (index < list.count - 1)\n                        {\n                            SerializedProperty currentProperty = list.serializedProperty.GetArrayElementAtIndex(index);\n                            for (int i = index + 1; i < list.count; i++)\n                            {\n                                SerializedProperty nextProperty = list.serializedProperty.GetArrayElementAtIndex(i);\n                                currentProperty.isExpanded = nextProperty.isExpanded;\n                                currentProperty = nextProperty;\n                            }\n                        }\n                    }\n                    else\n                    {\n                        list.list.RemoveAt(list.index);\n                    }\n                    lastDeletedIndex = index;\n                }\n                list.index = Mathf.Clamp(lastDeletedIndex - 1, 0, list.count - 1);\n                Undo.SetCurrentGroupName(undoRemove);\n                list.InvalidateForGUI();\n            }\n\n            // draw the default header background\n            public void DrawHeaderBackground(Rect headerRect)\n            {\n                if (Event.current.type == EventType.Repaint)\n                {\n                    // We assume that a height smaller than 5px means a header with no content\n                    if (headerRect.height < 5f)\n                    {\n                        emptyHeaderBackground.Draw(headerRect, false, false, false, false);\n                    }\n                    else\n                    {\n                        headerBackground.Draw(headerRect, false, false, false, false);\n                    }\n                }\n            }\n\n            // draw the default header\n            public void DrawHeader(Rect headerRect, SerializedObject serializedObject, SerializedProperty element, IList elementList)\n            {\n                EditorGUI.LabelField(headerRect, EditorGUIUtility.TempContent((element != null) ? \"Serialized Property\" : \"IList\"));\n            }\n\n            // draw the default element background\n            public void DrawElementBackground(Rect rect, int index, bool selected, bool focused, bool draggable)\n            {\n                if (Event.current.type == EventType.Repaint)\n                {\n                    elementBackground.Draw(rect, false, selected, selected, focused);\n                }\n            }\n\n            public void DrawElementDraggingHandle(Rect rect, int index, bool selected, bool focused, bool draggable)\n            {\n                if (Event.current.type == EventType.Repaint)\n                {\n                    if (draggable)\n                        draggingHandle.Draw(new Rect(rect.x + 5, rect.y + 8, 10, 6), false, false, false, false);\n                }\n            }\n\n            // draw the default element\n            public void DrawElement(Rect rect, SerializedProperty element, System.Object listItem, bool selected, bool focused, bool draggable)\n            {\n                DrawElement(rect, element, listItem, selected, focused, draggable, false);\n            }\n\n            public void DrawElement(Rect rect, SerializedProperty element, System.Object listItem, bool selected, bool focused, bool draggable, bool editable)\n            {\n                rect.y += ElementPadding(rect.height) / 2;\n                var prop = element ?? listItem as SerializedProperty;\n                if (editable)\n                {\n                    float oldLabelWidth = EditorGUIUtility.labelWidth;\n                    EditorGUIUtility.labelWidth = FieldLabelSize(rect, prop);\n\n                    try\n                    {\n                        var handler = ScriptAttributeUtility.GetHandler(prop);\n                        handler.OnGUI(rect, prop, null, true);\n                    }\n                    catch (ObjectDisposedException) { }\n                    if (Event.current.type == EventType.ContextClick && rect.Contains(Event.current.mousePosition)) Event.current.Use();\n\n                    EditorGUIUtility.labelWidth = oldLabelWidth;\n                    return;\n                }\n\n                EditorGUI.LabelField(rect, EditorGUIUtility.TempContent(element?.displayName ?? listItem?.ToString() ?? \"null\"));\n            }\n\n            // draw the default element\n            public void DrawNoneElement(Rect rect, bool draggable)\n            {\n                EditorGUI.LabelField(rect, s_ListIsEmpty);\n            }\n\n            public void DrawOverMaxMultiEditElement(Rect rect, int maxMultiEditElementCount, bool draggable)\n            {\n                EditorGUI.LabelField(rect, OverMaxMultiEditLimit(maxMultiEditElementCount), defaultLabel);\n            }\n        }\n        static Defaults s_Defaults;\n        public static Defaults defaultBehaviours\n        {\n            get\n            {\n                if (s_Defaults == null)\n                    s_Defaults = new Defaults();\n\n                return s_Defaults;\n            }\n        }\n\n        static List<WeakReference<ReorderableList>> s_Instances = new List<WeakReference<ReorderableList>>();\n        internal static void InvalidateExistingListCaches() => s_Instances.ForEach(list =>\n        {\n            if (!list.TryGetTarget(out ReorderableList reorderableList)) return;\n            reorderableList.InvalidateCache();\n        });\n\n        public static ReorderableList GetReorderableListFromSerializedProperty(SerializedProperty prop)\n        {\n            var id = ReorderableListWrapper.GetPropertyIdentifier(prop);\n            ReorderableList list = null;\n            s_Instances?.FirstOrDefault(i =>\n            {\n                ReorderableList list2 = null;\n                if (!(i?.TryGetTarget(out list2) ?? false)) return false;\n                return ReorderableListWrapper.GetPropertyIdentifier(list2?.serializedProperty).Equals(id);\n            })?.TryGetTarget(out list);\n            return list;\n        }\n\n        // constructors\n        public ReorderableList(IList elements, Type elementType)\n        {\n            InitList(null, null, elements, true, true, true, true);\n        }\n\n        public ReorderableList(IList elements, Type elementType, bool draggable, bool displayHeader, bool displayAddButton, bool displayRemoveButton)\n        {\n            InitList(null, null, elements, draggable, displayHeader, displayAddButton, displayRemoveButton);\n        }\n\n        public ReorderableList(SerializedObject serializedObject, SerializedProperty elements)\n        {\n            InitList(serializedObject, elements, null, true, true, true, true);\n        }\n\n        public ReorderableList(SerializedObject serializedObject, SerializedProperty elements, bool draggable, bool displayHeader, bool displayAddButton, bool displayRemoveButton)\n        {\n            InitList(serializedObject, elements, null, draggable, displayHeader, displayAddButton, displayRemoveButton);\n        }\n\n        private void InitList(SerializedObject serializedObject, SerializedProperty elements, IList elementList, bool draggable, bool displayHeader, bool displayAddButton, bool displayRemoveButton)\n        {\n            id = GUIUtility.GetPermanentControlID();\n            m_SerializedObject = serializedObject;\n            m_Elements = elements;\n            m_ElementList = elementList;\n            m_Draggable = draggable;\n            m_Dragging = false;\n            m_SlideGroup = new GUISlideGroup();\n            displayAdd = displayAddButton;\n            m_DisplayHeader = displayHeader;\n            displayRemove = displayRemoveButton;\n            if (m_Elements != null)\n            {\n                m_PropertyPath = m_Elements.propertyPath;\n                if (m_Elements.editable == false) m_Draggable = false;\n                if (m_Elements.isArray == false) Debug.LogError(\"Input elements should be an Array SerializedProperty\");\n            }\n\n            s_Instances.Add(new WeakReference<ReorderableList>(this));\n        }\n\n        public SerializedProperty serializedProperty\n        {\n            get { return m_Elements; }\n            set\n            {\n                m_Elements = value;\n                m_SerializedObject = m_Elements.serializedObject;\n                m_PropertyPath = m_Elements.propertyPath;\n            }\n        }\n\n        public IList list\n        {\n            get { return m_ElementList; }\n            set { m_ElementList = value; }\n        }\n\n        // active element index accessor\n        public int index\n        {\n            get { return m_Selection.Count > 0 ? m_Selection[0] : count - 1; }\n            set { Select(value); }\n        }\n\n        public ReadOnlyCollection<int> selectedIndices => new ReadOnlyCollection<int>(m_Selection);\n\n        public bool multiSelect { get; set; }\n\n        // individual element height accessor\n        public float elementHeight = 21;\n        // header height accessor\n        public float headerHeight = 20;\n        // footer height accessor\n        public float footerHeight = 20;\n        // show default background\n        public bool showDefaultBackground = true;\n\n        private float HeaderHeight { get { return Mathf.Max(m_DisplayHeader ? headerHeight : 0, Defaults.minHeaderHeight); } }\n\n        private float listElementTopPadding => headerHeight > 5 ? 4 : 1; // headerHeight is usually set to 3px when there is no header content. Therefore, we add a 1px top margin to match the 4px bottom margin\n        private const float kListElementBottomPadding = 4;\n\n        bool useCulling => GUI.matrix.rotation == Quaternion.identity && GUI.matrix.lossyScale == Vector3.one;\n\n        // draggable accessor\n        public bool draggable\n        {\n            get { return m_Draggable; }\n            set { m_Draggable = value; }\n        }\n\n        void TryOverrideElementHeightWithPropertyDrawer(SerializedProperty property, ref float height)\n        {\n            if (m_HasPropertyDrawer)\n            {\n                try\n                {\n                    height = ScriptAttributeUtility.GetHandler(property).GetHeight(property, null, true);\n                }\n                catch (ObjectDisposedException)\n                {\n                    // Sometimes we find properties that no longer exist so we don't cache them\n                    height = int.MinValue;\n                    m_Count--;\n                }\n            }\n        }\n\n        internal void CacheIfNeeded()\n        {\n            // Don't allow recaching multiple times in one frame as we won't be able to handle animated foldouts\n            if (isOverMaxMultiEditLimit || m_PropertyCacheValid) return;\n            m_PropertyCacheValid = true;\n            m_CacheCount++;\n\n            Array.Resize(ref m_PropertyCache, count);\n\n            SerializedProperty property = null;\n            float height = 0;\n            float offset = 0;\n\n            if (m_Count > 0)\n            {\n                height = elementHeightCallback?.Invoke(0) ?? elementHeight;\n\n                if (m_Elements != null)\n                {\n                    property = m_Elements.GetArrayElementAtIndex(0);\n                    TryOverrideElementHeightWithPropertyDrawer(property, ref height);\n                }\n\n                if (height > int.MinValue) m_ScheduleGUIChanged |= m_PropertyCache[0].Set(property, height + Defaults.ElementPadding(height), offset);\n            }\n\n            for (int i = 1; i < m_Count; i++)\n            {\n                PropertyCacheEntry lastEntry = m_PropertyCache[i - 1];\n\n                property = null;\n                height = elementHeightCallback?.Invoke(i) ?? elementHeight;\n                offset = lastEntry.offset + lastEntry.height;\n\n                if (m_Elements != null)\n                {\n                    property = lastEntry.property.Copy();\n                    property.Next(false);\n\n                    TryOverrideElementHeightWithPropertyDrawer(property, ref height);\n                }\n\n                if (height > int.MinValue) m_ScheduleGUIChanged |= m_PropertyCache[i].Set(property, height + Defaults.ElementPadding(height), offset);\n            }\n        }\n\n        internal void InvalidateCache()\n        {\n            m_CacheCount = 0;\n            m_PropertyCacheValid = false;\n        }\n\n        internal void InvalidateCacheRecursive()\n        {\n            if (m_Elements != null)\n            {\n                InvalidateCache();\n                PropertyHandler.InvalidateListCacheIncludingChildren(m_Elements);\n            }\n            else\n            {\n                InvalidateCache();\n            }\n        }\n\n        public void ClearSelection()\n        {\n            m_Selection.Clear();\n        }\n\n        public void Select(int index, bool append = false)\n        {\n            int insertionIndex = m_Selection.BinarySearch(index);\n            if (insertionIndex < 0 || append == false && m_Selection.Count > 1)\n            {\n                if (!append)\n                {\n                    m_Selection.Clear();\n                    m_Selection.Add(index);\n                }\n                else\n                {\n                    m_Selection.Insert(~insertionIndex, index);\n                }\n            }\n        }\n\n        public void SelectRange(int indexFrom, int indexTo)\n        {\n            if (!multiSelect) throw new InvalidOperationException(\"Cannot select range when not in multi select mode.\");\n\n            m_Selection.Clear();\n            for (int i = Mathf.Min(indexFrom, indexTo); i <= Mathf.Max(indexFrom, indexTo); ++i)\n            {\n                m_Selection.Add(i);\n            }\n        }\n\n        public bool IsSelected(int index)\n        {\n            return m_Selection.BinarySearch(index) >= 0;\n        }\n\n        public void Deselect(int index)\n        {\n            int foundIndex = m_Selection.BinarySearch(index);\n            if (foundIndex >= 0)\n            {\n                m_Selection.RemoveAt(foundIndex);\n            }\n        }\n\n        private Rect GetContentRect(Rect rect)\n        {\n            Rect r = rect;\n\n            if (draggable)\n                r.xMin += Defaults.dragHandleWidth;\n            else\n                r.xMin += Defaults.padding;\n            if (m_HasPropertyDrawer)\n                r.xMin += Defaults.propertyDrawerPadding;\n            r.xMax -= Defaults.padding;\n            return r;\n        }\n\n        private float GetElementYOffset(int index)\n        {\n            return GetElementYOffset(index, -1);\n        }\n\n        private float GetElementYOffset(int index, int skipIndex)\n        {\n            if (m_PropertyCache.Length <= index) return 0;\n\n            float skipOffset = 0;\n            if (skipIndex >= 0 && skipIndex < index)\n            {\n                skipOffset = m_PropertyCache[skipIndex].height;\n            }\n\n            return m_PropertyCache[index].offset - skipOffset;\n        }\n\n        private float GetElementHeight(int index)\n        {\n            if (m_PropertyCache.Length <= index) return 0;\n            return m_PropertyCache[index].height;\n        }\n\n        private Rect GetRowRect(int index, Rect listRect)\n        {\n            return new Rect(listRect.x, listRect.y + GetElementYOffset(index), listRect.width, GetElementHeight(index));\n        }\n\n        bool isOverMaxMultiEditLimit => m_Elements != null && m_SmallerArraySize > m_Elements.serializedObject.maxArraySizeForMultiEditing && m_Elements.serializedObject.isEditingMultipleObjects;\n\n        public int count\n        {\n            get\n            {\n                if (m_Elements != null)\n                {\n                    m_SmallerArraySize = m_Elements.minArraySize;\n\n                    if (isOverMaxMultiEditLimit) return m_Count = 0;\n\n                    return m_Count = m_SmallerArraySize;\n                }\n                return m_Count = m_ElementList != null ? m_ElementList.Count : 0;\n            }\n        }\n        // Using count getter will automatically cache results here for quick reference;\n        int m_Count;\n        int m_SmallerArraySize;\n\n        public void DoLayoutList() //TODO: better API?\n        {\n            GUILayout.BeginVertical();\n\n            // do the custom or default header GUI\n            Rect headerRect = GUILayoutUtility.GetRect(0, HeaderHeight, GUILayout.ExpandWidth(true));\n            //Elements area\n            Rect listRect = GUILayoutUtility.GetRect(10, GetListElementHeight(), GUILayout.ExpandWidth(true));\n            // do the footer GUI\n            Rect footerRect = GUILayoutUtility.GetRect(4, footerHeight, GUILayout.ExpandWidth(true));\n\n            // do the parts of our list\n            DoListHeader(headerRect);\n            DoListElements(listRect, Defaults.infinityRect);\n            DoListFooter(footerRect);\n\n            GUILayout.EndVertical();\n        }\n\n        public void DoList(Rect rect) => DoList(rect, Defaults.infinityRect);\n\n        public void DoList(Rect rect, Rect visibleRect) //TODO: better API?\n        {\n            // do the custom or default header GUI\n            Rect headerRect = new Rect(rect.x, rect.y, rect.width, HeaderHeight);\n            //Elements area\n            Rect listRect = new Rect(rect.x, headerRect.y + headerRect.height, rect.width, GetListElementHeight());\n            // do the footer GUI\n            Rect footerRect = new Rect(rect.x, listRect.y + listRect.height, rect.width, footerHeight);\n\n            visibleRect.y -= headerRect.height;\n            visibleRect.height -= headerRect.height;\n\n            // do the parts of our list\n            DoListHeader(headerRect);\n            DoListElements(listRect, visibleRect);\n            DoListFooter(footerRect);\n        }\n\n        public float GetHeight()\n        {\n            float totalHeight = 0f;\n            totalHeight += HeaderHeight;\n            totalHeight += GetListElementHeight();\n            totalHeight += footerHeight;\n            return totalHeight;\n        }\n\n        float lastHeight = -1;\n        private float GetListElementHeight()\n        {\n            float height;\n            float listElementPadding = kListElementBottomPadding + listElementTopPadding;\n\n            if (m_CacheCount == 0) CacheIfNeeded();\n\n            if (count <= 0 || isOverMaxMultiEditLimit)\n                height = elementHeight * (isOverMaxMultiEditLimit ? 2 : 1) + listElementPadding;\n            else\n                height = GetElementYOffset(m_Count - 1) + GetElementHeight(m_Count - 1) + listElementPadding;\n\n            if(height != lastHeight)\n            {\n                lastHeight = height;\n                InvalidateCache();\n                height = GetListElementHeight();\n            }\n\n            return height;\n        }\n\n        int recursionCounter = 0;\n        Rect lastRect = Rect.zero;\n        private void DoListElements(Rect listRect, Rect visibleRect)\n        {\n            if ((drawElementCallback != null || m_HasPropertyDrawer) && Event.current.type == EventType.Repaint && listRect != lastRect)\n            {\n                // Recalculate cache values in case their height changed due to window resize\n                lastRect = listRect;\n                InvalidateCacheRecursive();\n            }\n\n            if (m_CacheCount == 0) CacheIfNeeded();\n\n            var prevIndent = EditorGUI.indentLevel;\n            EditorGUI.indentLevel = 0;\n\n            // draw the background in repaint\n            if (showDefaultBackground && Event.current.type == EventType.Repaint)\n                defaultBehaviours.boxBackground.Draw(listRect, false, false, false, false);\n\n            // resize to the area that we want to draw our elements into\n            listRect.yMin += listElementTopPadding; listRect.yMax -= kListElementBottomPadding;\n\n            if (showDefaultBackground)\n            {\n                listRect.xMin += 1;\n                listRect.xMax -= 1;\n            }\n\n            // create the rect for individual elements in the list\n            var elementRect = listRect;\n            elementRect.height = elementHeight;\n\n            // the content rect is what we will actually draw into -- it doesn't include the drag handle or padding\n            var elementContentRect = elementRect;\n\n            bool handlingInput = Event.current.type == EventType.MouseDown;\n\n            // Cache element count so we don't try to draw elements that don't exist\n            _ = count;\n\n            if ((m_Elements != null && m_Elements.isArray || m_ElementList != null) && m_Count > 0 && !isOverMaxMultiEditLimit)\n            {\n                EditorGUI.BeginChangeCheck();\n                // If there are elements, we need to draw them -- we will do this differently depending on if we are dragging or not\n                if (IsDragging() && Event.current.type == EventType.Repaint)\n                {\n                    // we are dragging, so we need to build the new list of target indices\n                    var targetIndex = CalculateRowIndex(listRect);\n\n                    m_NonDragTargetIndices.Clear();\n                    for (var i = 0; i < m_Count; i++)\n                    {\n                        if (i != index)\n                            m_NonDragTargetIndices.Add(i);\n                    }\n                    m_NonDragTargetIndices.Insert(targetIndex, -1);\n\n                    // now draw each element in the list (excluding the active element)\n                    var targetSeen = false;\n                    for (var i = 0; i < m_NonDragTargetIndices.Count; i++)\n                    {\n                        var next = Mathf.Min(i + 1, m_Count - 1);\n                        var previous = Mathf.Max(i - 1, 0);\n\n                        if (useCulling)\n                        {\n                            if (visibleRect.y > GetElementYOffset(next) + GetElementHeight(next)) continue;\n                            if (visibleRect.y + visibleRect.height < GetElementYOffset(previous)) break;\n                        }\n\n                        var nonDragTargetIndex = m_NonDragTargetIndices[i];\n                        if (nonDragTargetIndex != -1)\n                        {\n                            elementRect.height = GetElementHeight(nonDragTargetIndex);\n                            // update the position of the rect (based on element position and accounting for sliding)\n                            elementRect.y = listRect.y + GetElementYOffset(nonDragTargetIndex, index);\n                            if (targetSeen)\n                            {\n                                elementRect.y += GetElementHeight(index);\n                            }\n\n                            Rect r = m_SlideGroup.GetRect(nonDragTargetIndex, elementRect);\n                            elementRect.y = r.y;\n\n                            // actually draw the element\n                            if (drawElementBackgroundCallback == null)\n                                defaultBehaviours.DrawElementBackground(elementRect, nonDragTargetIndex, false, false, m_Draggable);\n                            else\n                                drawElementBackgroundCallback(elementRect, nonDragTargetIndex, false, false);\n\n                            defaultBehaviours.DrawElementDraggingHandle(elementRect, i, false, false, m_Draggable);\n\n                            elementContentRect = GetContentRect(elementRect);\n                            if (drawElementCallback == null)\n                            {\n                                if (m_Elements != null)\n                                    s_Defaults.DrawElement(elementContentRect, m_PropertyCache[nonDragTargetIndex].property, null, false, false, m_Draggable, m_IsEditable);\n                                else\n                                    defaultBehaviours.DrawElement(elementContentRect, null, m_ElementList[nonDragTargetIndex], false, false, m_Draggable, m_IsEditable);\n                            }\n                            else\n                            {\n                                drawElementCallback(elementContentRect, nonDragTargetIndex, false, false);\n                            }\n                        }\n                        else\n                        {\n                            targetSeen = true;\n                        }\n                    }\n\n                    if (index >= 0)\n                    {\n                        // finally get the position of the active element\n                        elementRect.y = GetClampedDragPosition(listRect) - m_DragOffset + listRect.y;\n                        elementRect.height = GetElementHeight(index);\n\n                        // actually draw the element\n                        if (drawElementBackgroundCallback == null)\n                            defaultBehaviours.DrawElementBackground(elementRect, index, true, true, m_Draggable);\n                        else\n                            drawElementBackgroundCallback(elementRect, index, true, true);\n\n                        defaultBehaviours.DrawElementDraggingHandle(elementRect, index, true, true, m_Draggable);\n\n                        elementContentRect = GetContentRect(elementRect);\n\n                        // draw the active element\n                        if (drawElementCallback == null)\n                        {\n                            if (m_Elements != null)\n                                s_Defaults.DrawElement(elementContentRect, m_PropertyCache[index].property, null, true, true, m_Draggable, m_IsEditable);\n                            else\n                                defaultBehaviours.DrawElement(elementContentRect, null, m_ElementList[index], true, true, m_Draggable, m_IsEditable);\n                        }\n                        else\n                        {\n                            drawElementCallback(elementContentRect, index, true, true);\n                        }\n                    }\n                }\n                else\n                {\n                    // if we aren't dragging, we just draw all of the elements in order\n                    for (int i = 0; i < m_Count; i++)\n                    {\n                        if (useCulling)\n                        {\n                            if (visibleRect.y > GetElementYOffset(i) + GetElementHeight(i)) continue;\n                            if (visibleRect.y + visibleRect.height < GetElementYOffset(i > 0 ? i - 1 : i)) break;\n                        }\n\n                        bool activeElement = m_Selection.Any(id => id == i);\n                        bool focusedElement = (activeElement && HasKeyboardControl());\n\n                        // update the position of the element\n                        elementRect.height = GetElementHeight(i);\n                        elementRect.y = listRect.y + GetElementYOffset(i);\n\n                        // draw the background\n                        if (drawElementBackgroundCallback == null)\n                            defaultBehaviours.DrawElementBackground(elementRect, i, activeElement, focusedElement, m_Draggable);\n                        else\n                            drawElementBackgroundCallback(elementRect, i, activeElement, focusedElement);\n                        defaultBehaviours.DrawElementDraggingHandle(elementRect, i, activeElement, focusedElement, m_Draggable);\n\n                        elementContentRect = GetContentRect(elementRect);\n                        int initialControlCount = GUIUtility.s_ControlCount;\n\n                        // do the callback for the element\n                        if (drawElementCallback == null)\n                        {\n                            if (m_Elements != null)\n                            {\n                                if (i < m_PropertyCache.Length && m_PropertyCache[i].property.isValid)\n                                    s_Defaults.DrawElement(elementContentRect, m_PropertyCache[i].property, null, activeElement, focusedElement, m_Draggable, m_IsEditable);\n                            }\n                            else\n                                defaultBehaviours.DrawElement(elementContentRect, null, m_ElementList[i], activeElement, focusedElement, m_Draggable, m_IsEditable);\n                        }\n                        else\n                        {\n                            drawElementCallback(elementContentRect, i, activeElement, focusedElement);\n                        }\n\n                        if (handlingInput && Event.current.type == EventType.Used)\n                        {\n                            index = i;\n                            handlingInput = false;\n                        }\n\n                        // Element drawing could be changed from distant properties or controls\n                        // so if we detect any change in the way the property is drawn, clear cache\n                        int currentControlCount = GUIUtility.s_ControlCount - initialControlCount;\n                        if (i < m_PropertyCache.Length && Event.current.type == EventType.Repaint && m_PropertyCache[i].controlCount != currentControlCount || m_ScheduleGUIChanged)\n                        {\n                            InvalidateCache();\n                            // Extra check here as an exception safeguard against GUIChanged schedule cases\n                            if (i < m_PropertyCache.Length) m_PropertyCache[i].controlCount = currentControlCount;\n                            m_ScheduleGUIChanged = false;\n                        }\n                    }\n                }\n\n                // handle the interaction\n                DoDraggingAndSelection(listRect);\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    InvalidateCacheRecursive();\n                }\n            }\n            else\n            {\n                // there was no content, so we will draw an empty element\n                elementRect.y = listRect.y;\n                // draw the background\n                if (drawElementBackgroundCallback == null)\n                    defaultBehaviours.DrawElementBackground(elementRect, -1, false, false, false);\n                else\n                    drawElementBackgroundCallback(elementRect, -1, false, false);\n                defaultBehaviours.DrawElementDraggingHandle(elementRect, -1, false, false, false);\n\n                elementContentRect = elementRect;\n                elementContentRect.xMin += Defaults.padding;\n                elementContentRect.xMax -= Defaults.padding;\n                if (drawNoneElementCallback == null)\n                {\n                    if (isOverMaxMultiEditLimit)\n                    {\n                        elementContentRect.height *= 2;\n                        defaultBehaviours.DrawOverMaxMultiEditElement(elementContentRect, m_Elements.serializedObject.maxArraySizeForMultiEditing, m_Draggable);\n                    }\n                    else\n                    {\n                        defaultBehaviours.DrawNoneElement(elementContentRect, m_Draggable);\n                    }\n                }\n                else\n                    drawNoneElementCallback(elementContentRect);\n            }\n\n            EditorGUI.indentLevel = prevIndent;\n\n            // Redraw if a change happened that could have changed child size\n            if (CheckForChildInvalidation() && recursionCounter < 2)\n            {\n                recursionCounter++;\n                DoListElements(listRect, visibleRect);\n            }\n\n            m_CacheCount = 0;\n        }\n\n        private void DoListHeader(Rect headerRect)\n        {\n            // Ensure there's proper Prefab and context menu handling for the list as a whole.\n            // This ensures a deleted element in the list is displayed as an override and can\n            // be handled by the user via the context menu. Case 1292522\n            if (m_Elements != null && m_DisplayHeader)\n                EditorGUI.BeginProperty(headerRect, GUIContent.none, m_Elements);\n\n            recursionCounter = 0;\n            // draw the background on repaint\n            if (showDefaultBackground && Event.current.type == EventType.Repaint)\n                defaultBehaviours.DrawHeaderBackground(headerRect);\n\n            // apply the padding to get the internal rect\n            headerRect.xMin += Defaults.padding;\n            headerRect.xMax -= Defaults.padding;\n            headerRect.height -= 2;\n            headerRect.y += 1;\n\n            // perform the default or overridden callback\n            if (drawHeaderCallback != null)\n                drawHeaderCallback(headerRect);\n            else if (m_DisplayHeader)\n                defaultBehaviours.DrawHeader(headerRect, m_SerializedObject, m_Elements, m_ElementList);\n\n            if (m_Elements != null && m_DisplayHeader)\n                EditorGUI.EndProperty();\n        }\n\n        private void DoListFooter(Rect footerRect)\n        {\n            // perform callback or the default footer\n            if (drawFooterCallback != null)\n                drawFooterCallback(footerRect);\n            else if (displayAdd || displayRemove)\n                defaultBehaviours.DrawFooter(footerRect, this); // draw the footer if the add or remove buttons are required\n        }\n\n        private void DoDraggingAndSelection(Rect listRect)\n        {\n            Event evt = Event.current;\n            int oldIndex = index;\n            bool clicked = false;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.KeyDown:\n                    if (GUIUtility.keyboardControl != id || m_Dragging || clicked)\n                        return;\n                    // if we have keyboard focus, arrow through the list\n                    if (evt.keyCode == KeyCode.DownArrow)\n                    {\n                        index += 1;\n                        if (index >= m_Count) index = 0;\n                        evt.Use();\n                    }\n                    if (evt.keyCode == KeyCode.UpArrow)\n                    {\n                        index -= 1;\n                        if (index < 0) index = m_Count - 1;\n                        evt.Use();\n                    }\n                    if (evt.keyCode == KeyCode.LeftArrow)\n                    {\n                        if (m_Elements != null)\n                        {\n                            foreach (var index in m_Selection)\n                            {\n                                if (index < 0) continue;\n\n                                m_Elements.GetArrayElementAtIndex(index).isExpanded = false;\n                            }\n                        }\n                        InvalidateParentCaches(m_PropertyPath);\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                    if (evt.keyCode == KeyCode.RightArrow)\n                    {\n                        if (m_Elements != null)\n                        {\n                            foreach (var index in selectedIndices)\n                            {\n                                if (index < 0) continue;\n\n                                m_Elements.GetArrayElementAtIndex(index).isExpanded = true;\n                            }\n                        }\n                        InvalidateParentCaches(m_PropertyPath);\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n\n                    if (Application.platform != RuntimePlatform.OSXEditor && evt.keyCode == KeyCode.Delete\n                        || Application.platform == RuntimePlatform.OSXEditor && evt.keyCode == KeyCode.Backspace && evt.modifiers.HasFlag(EventModifiers.Command))\n                    {\n                        m_scheduleRemove = true;\n                        InvalidateParentCaches(m_PropertyPath);\n                        evt.Use();\n                    }\n                    if (evt.keyCode == KeyCode.Escape && GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n                        m_Dragging = false;\n                        evt.Use();\n                    }\n                    if (evt.type == EventType.Used)\n                    {\n                        // don't allow arrowing through the ends of the list\n                        m_Selection = m_Selection.Where(i => i >= 0 && i < (m_Elements != null ? m_Elements.arraySize : m_ElementList.Count)).ToList();\n                    }\n                    if (oldIndex != index && PropertyEditor.FocusedPropertyEditor != null)\n                    {\n                        float offset = 0;\n                        if (oldIndex < index) offset = Mathf.Min(GetElementHeight(index), PropertyEditor.FocusedPropertyEditor.scrollViewportRect.height * 0.9f);\n\n                        Vector2 elementPosition = new Vector2(0, listRect.y + GetElementYOffset(index) + offset);\n                        elementPosition = GUIUtility.GUIToScreenPoint(elementPosition) - new Vector2(0, PropertyEditor.FocusedPropertyEditor.m_Pos.y);\n                        PropertyEditor.FocusedPropertyEditor.ScrollTo(elementPosition);\n                    }\n                    break;\n\n                case EventType.MouseDown:\n\n                    if (!listRect.Contains(Event.current.mousePosition)\n                        || Event.current.button > 0)\n                        break;\n\n                    // clicking on the list should end editing any existing edits\n                    EditorGUI.EndEditingActiveTextField();\n                    // pick the active element based on click position\n                    int selected = GetRowIndex(Event.current.mousePosition.y - listRect.y);\n\n                    if (EditorGUI.actionKey && multiSelect) // Toggle selection\n                    {\n                        if (IsSelected(selected))\n                            Deselect(selected);\n                        else\n                            Select(selected, true);\n                    }\n                    else if (evt.shift && multiSelect && selectedIndices.Count > 0) // Select from - to\n                    {\n                        int selectionFromTarget = selected < selectedIndices[0] ? selectedIndices[selectedIndices.Count - 1] : selectedIndices[0];\n                        SelectRange(selectionFromTarget, selected);\n                    }\n                    else\n                    {\n                        Select(selected);\n                    }\n\n                    if (index >= 0 && m_Draggable)\n                    {\n                        float mousePosInList = Event.current.mousePosition.y - listRect.y;\n                        // if we can drag, set the hot control and start dragging (storing the offset)\n                        m_DragOffset = mousePosInList - GetElementYOffset(GetRowIndex(mousePosInList));\n                        UpdateDraggedY(listRect);\n                        GUIUtility.hotControl = id;\n                        m_SlideGroup.Reset();\n                        m_NonDragTargetIndices = new List<int>();\n                    }\n                    GrabKeyboardFocus();\n\n                    evt.Use();\n                    clicked = true;\n                    break;\n\n                case EventType.MouseDrag:\n                    if (!m_Draggable || GUIUtility.hotControl != id || evt.modifiers != EventModifiers.None) // Ignore dragging on the x axis\n                    {\n                        m_Dragging = false;\n                        break;\n                    }\n\n                    // Set m_Dragging state on first MouseDrag event after we got hotcontrol (to prevent animating elements when deleting elements by context menu)\n                    m_Dragging = true;\n\n                    // Clear selection to just the dragged item\n                    if (m_Selection.Count > 1)\n                        index = GetRowIndex(Event.current.mousePosition.y - listRect.y);\n\n                    onMouseDragCallback?.Invoke(this);\n\n                    // if we are dragging, update the position\n                    UpdateDraggedY(listRect);\n\n                    // handle inspector auto-scroll\n                    if (PropertyEditor.HoveredPropertyEditor != null)\n                    {\n                        Vector2 mousePoistion = new Vector2(0, Mathf.Clamp(evt.mousePosition.y, listRect.y, listRect.y + listRect.height));\n                        mousePoistion = GUIUtility.GUIToScreenPoint(mousePoistion) - new Vector2(0, PropertyEditor.HoveredPropertyEditor.m_Pos.y);\n                        PropertyEditor.HoveredPropertyEditor.AutoScroll(mousePoistion);\n                    }\n                    evt.Use();\n                    break;\n\n                case EventType.MouseUp:\n                    clicked = false;\n                    if (!m_Draggable)\n                    {\n                        // if mouse up was on the same index as mouse down we fire a mouse up callback (useful if for beginning renaming on mouseup)\n                        if (onMouseUpCallback != null && IsMouseInsideActiveElement(listRect))\n                        {\n                            // set the keyboard control\n                            onMouseUpCallback(this);\n                        }\n                        break;\n                    }\n\n                    // hot control is only set when list is draggable\n                    if (GUIUtility.hotControl != id)\n                        break;\n\n                    evt.Use();\n\n                    try\n                    {\n                        // What will be the index of this if we release?\n                        int targetIndex = CalculateRowIndex(listRect);\n                        if (index != targetIndex && m_Dragging)\n                        {\n                            // if the target index is different than the current index...\n                            if (m_SerializedObject != null && m_Elements != null)\n                            {\n                                Undo.RegisterCompleteObjectUndo(m_SerializedObject.targetObjects, Defaults.undoMove);\n\n                                // if we are working with Serialized Properties, we can handle it for you\n                                m_Elements.MoveArrayElement(index, targetIndex);\n                            }\n                            else if (m_ElementList != null)\n                            {\n                                // we are working with the IList, which is probably of a fixed length\n                                object tempObject = m_ElementList[index];\n                                for (int i = 0; i < m_ElementList.Count - 1; i++)\n                                {\n                                    if (i >= index)\n                                        m_ElementList[i] = m_ElementList[i + 1];\n                                }\n                                for (int i = m_ElementList.Count - 1; i > 0; i--)\n                                {\n                                    if (i > targetIndex)\n                                        m_ElementList[i] = m_ElementList[i - 1];\n                                }\n                                m_ElementList[targetIndex] = tempObject;\n                            }\n\n                            var oldActiveElement = index;\n                            var newActiveElement = targetIndex;\n\n                            // Array size may have changes so we need to recache array size for isOverMaxMultiEditLimit check\n                            _ = count;\n\n                            // Retain expanded state after reordering properties\n                            if (m_SerializedObject != null && m_Elements != null && !isOverMaxMultiEditLimit)\n                            {\n                                EditorGUIUtility.MoveArrayExpandedState(m_Elements, oldActiveElement, newActiveElement);\n                            }\n\n                            // update the active element, now that we've moved it\n                            index = targetIndex;\n                            // give the user a callback\n                            if (onReorderCallbackWithDetails != null)\n                                onReorderCallbackWithDetails(this, oldActiveElement, newActiveElement);\n                            else onReorderCallback?.Invoke(this);\n\n                            onChangedCallback?.Invoke(this);\n                            GUI.changed = true;\n                        }\n                        else\n                        {\n                            // if mouse up was on the same index as mouse down we fire a mouse up callback (useful if for beginning renaming on mouseup)\n                            onMouseUpCallback?.Invoke(this);\n                        }\n                    }\n                    catch (ObjectDisposedException) { }\n                    finally\n                    {\n                        // It's quite possible a call to EndGUI was made in one of our callbacks\n                        // (and thus an ExitGUIException thrown). We still need to cleanup before\n                        // we exitGUI proper.\n                        GUIUtility.hotControl = 0;\n                        m_NonDragTargetIndices = null;\n                        m_Dragging = false;\n                    }\n                    break;\n            }\n\n            // if the index has changed and there is a selected callback, call it\n            if ((index != oldIndex || clicked) && onSelectCallback != null)\n                onSelectCallback(this);\n        }\n\n        bool IsMouseInsideActiveElement(Rect listRect)\n        {\n            int mouseRowIndex = GetRowIndex(Event.current.mousePosition.y - listRect.y);\n            return IsSelected(mouseRowIndex) && GetRowRect(mouseRowIndex, listRect).Contains(Event.current.mousePosition);\n        }\n\n        private void UpdateDraggedY(Rect listRect)\n        {\n            m_DraggedY = Event.current.mousePosition.y - listRect.y;\n        }\n\n        private float GetClampedDragPosition(Rect listRect)\n        {\n            return Mathf.Clamp(m_DraggedY, m_DragOffset, listRect.height - (GetElementHeight(index)) + m_DragOffset);\n        }\n\n        private int CalculateRowIndex(Rect listRect)\n        {\n            var rowIndex = GetRowIndex(GetClampedDragPosition(listRect) - m_DragOffset, true);\n\n            var activeElementY = m_DraggedY - m_DragOffset;\n            var position = activeElementY - GetElementYOffset(index);\n\n            if (position < 0)\n            {\n                while (rowIndex > 0 && GetElementYOffset(rowIndex - 1) + GetElementHeight(rowIndex - 1) / 2 > activeElementY)\n                    rowIndex--;\n            }\n\n            return rowIndex;\n        }\n\n        // Used to determine the destination index of the dragged element\n        // or indexes of of elements that are not interacted with while drag is happening\n        private int GetRowIndex(float localY, bool skipActiveElement = false)\n        {\n            for (int i = 0; i < m_Count; i++)\n            {\n                float levelOffset = GetElementYOffset(i);\n\n                if (skipActiveElement)\n                {\n                    if (i >= index)\n                    {\n                        levelOffset += -GetElementHeight(index) + GetElementHeight(i) / 2;\n                    }\n                    else if (i < index)\n                    {\n                        levelOffset -= GetElementHeight(i) / 2;\n                    }\n                }\n\n                if (levelOffset > localY)\n                {\n                    return --i;\n                }\n            }\n\n            return m_Count - 1;\n        }\n\n        private bool IsDragging()\n        {\n            return m_Dragging;\n        }\n\n        public void GrabKeyboardFocus()\n        {\n            GUIUtility.keyboardControl = id;\n        }\n\n        public void ReleaseKeyboardFocus()\n        {\n            if (GUIUtility.keyboardControl == id)\n            {\n                GUIUtility.keyboardControl = 0;\n            }\n        }\n\n        public bool HasKeyboardControl()\n        {\n            return GUIUtility.keyboardControl == id && EditorGUIUtility.HasCurrentWindowKeyFocus();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ScalableGUIContent.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.StyleSheets;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [Serializable]\n    internal class ScalableGUIContent\n    {\n        [Serializable]\n        struct TextureResource\n        {\n            public float pixelsPerPoint;\n            public string resourcePath;\n        }\n\n        [SerializeField]\n        private List<TextureResource> m_TextureResources = new List<TextureResource>(2);\n\n        [SerializeField]\n        private string m_CurrentResourcePath;\n\n        [SerializeField]\n        private GUIContent m_GuiContent;\n\n        public string text => asGUIContent()?.text;\n        public Texture image => asGUIContent()?.image;\n        public string tooltip => asGUIContent()?.tooltip;\n\n        public ScalableGUIContent(string resourceName) : this(string.Empty, string.Empty, resourceName)\n        {\n        }\n\n        public ScalableGUIContent(string text, string tooltip, string resourceName)\n        {\n            m_GuiContent = !string.IsNullOrEmpty(text) || !string.IsNullOrEmpty(tooltip) ?\n                EditorGUIUtility.TextContent(string.Format(\"{0}|{1}\", text, tooltip)) :\n                new GUIContent();\n\n            // TODO: make this more sophisticated when/if we have more granular support for different DPI levels\n            m_TextureResources.Add(new TextureResource { pixelsPerPoint = 1f, resourcePath = resourceName});\n            m_TextureResources.Add(new TextureResource { pixelsPerPoint = 2f, resourcePath = string.Format(\"{0}@2x\", resourceName)});\n        }\n\n        public static implicit operator GUIContent(ScalableGUIContent gc)\n        {\n            return gc.asGUIContent();\n        }\n\n        private GUIContent asGUIContent()\n        {\n            var dpi = EditorGUIUtility.pixelsPerPoint;\n            var resourcePath = m_CurrentResourcePath;\n            var resourceDpi = 1.0f;\n            var normalResourcePath = m_TextureResources[0].resourcePath;\n\n            for (int i = 0, count = m_TextureResources.Count; i < count; ++i)\n            {\n                var currentResource = m_TextureResources[i];\n                resourcePath = currentResource.resourcePath;\n                resourceDpi = currentResource.pixelsPerPoint;\n                if (resourceDpi >= dpi)\n                    break;\n            }\n\n            if (resourcePath != m_CurrentResourcePath)\n            {\n                Texture2D loadedResource = EditorGUIUtility.LoadIconRequired(normalResourcePath);\n                loadedResource.pixelsPerPoint = resourceDpi;\n\n                m_GuiContent.image = loadedResource;\n                m_CurrentResourcePath = resourcePath;\n            }\n\n            if (resourceDpi != GUIUtility.pixelsPerPoint)\n            {\n                Texture2D image = m_GuiContent.image as Texture2D;\n                if (image != null)\n                {\n                    image.filterMode = FilterMode.Bilinear;\n                }\n            }\n\n            return m_GuiContent;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/ScreenShotting.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    internal class ScreenShots\n    {\n        public static Color kToolbarBorderColor = new Color(0.54f, 0.54f, 0.54f, 1f);\n        public static Color kWindowBorderColor = new Color(0.51f, 0.51f, 0.51f, 1f);\n        public static bool s_TakeComponentScreenshot = false;\n\n        [MenuItem(\"Window/Internal/Screenshot/Set Window Size %&l\", false, 1000, true, secondaryPriority = 1)]\n        public static void SetMainWindowSize()\n        {\n            var main = Resources.FindObjectsOfTypeAll<MainView>()[0];\n            main.window.position = new Rect(0, 0, 1024, 768);\n        }\n\n        [MenuItem(\"Window/Internal/Screenshot/Set Window Size Small\", false, 1000, true, secondaryPriority = 2)]\n        public static void SetMainWindowSizeSmall()\n        {\n            var main = Resources.FindObjectsOfTypeAll<MainView>()[0];\n            main.window.position = new Rect(0, 0, 800 - 38, 600);\n        }\n\n        [MenuItem(\"Window/Internal/Screenshot/Snap View %&j\", false, 1000, true, secondaryPriority = 3)]\n        public static void Screenshot()\n        {\n            GUIView v = GetMouseOverView();\n            if (v != null)\n            {\n                string name = GetGUIViewName(v);\n                Rect r = v.screenPosition;\n                r.y -= 1;\n                r.height += 2;\n                SaveScreenShot(r, name);\n            }\n        }\n\n        [MenuItem(\"Window/Internal/Screenshot/Snap View Toolbar\", false, 1000, true, secondaryPriority = 4)]\n        public static void ScreenshotToolbar()\n        {\n            GUIView v = GetMouseOverView();\n            if (v != null)\n            {\n                string name = GetGUIViewName(v) + \"Toolbar\";\n                Rect r = v.screenPosition;\n                r.y += 19;\n                r.height = 16;\n                r.width -= 2;\n                SaveScreenShotWithBorder(r, kToolbarBorderColor, name);\n            }\n        }\n\n        [MenuItem(\"Window/Internal/Screenshot/Snap View Extended Right %&k\", false, 1000, true, secondaryPriority = 5)]\n        public static void ScreenshotExtendedRight()\n        {\n            GUIView v = GetMouseOverView();\n            if (v != null)\n            {\n                string name = GetGUIViewName(v) + \"Extended\";\n                var main = Resources.FindObjectsOfTypeAll<MainView>()[0];\n                Rect r = v.screenPosition;\n                r.xMax = main.window.position.xMax;\n                r.y -= 1;\n                r.height += 2;\n                SaveScreenShot(r, name);\n            }\n        }\n\n        [MenuItem(\"Window/Internal/Screenshot/Snap Component\", false, 1000, true, secondaryPriority = 6)]\n        public static void ScreenShotComponent()\n        {\n            s_TakeComponentScreenshot = true;\n        }\n\n        public static void ScreenShotComponent(Rect contentRect, Object target)\n        {\n            s_TakeComponentScreenshot = false;\n\n            contentRect.yMax += 2;\n            contentRect.xMin += 1;\n            ScreenShots.SaveScreenShotWithBorder(contentRect, kWindowBorderColor, target.GetType().Name + \"Inspector\");\n        }\n\n        [MenuItem(\"Window/Internal/Screenshot/Snap Game View Content\", false, 1000, true, secondaryPriority = 7)]\n        public static void ScreenGameViewContent()\n        {\n            string path = GetUniquePathForName(\"ContentExample\");\n            ScreenCapture.CaptureScreenshot(path);\n            Debug.Log(string.Format(\"Saved screenshot at {0}\", path));\n        }\n\n        static GUIView GetMouseOverView()\n        {\n            GUIView v = GUIView.mouseOverView;\n            if (v == null)\n            {\n                EditorApplication.Beep();\n                Debug.LogWarning(\"Could not take screenshot.\");\n            }\n            return v;\n        }\n\n        static string GetGUIViewName(GUIView view)\n        {\n            HostView host = view as HostView;\n            if (host != null)\n                return host.actualView.GetType().Name;\n            return \"Window\";\n        }\n\n        public static void SaveScreenShot(Rect r, string name)\n        {\n            SaveScreenShot((int)r.width, (int)r.height, InternalEditorUtility.ReadScreenPixel(new Vector2(r.x, r.y), (int)r.width, (int)r.height), name);\n        }\n\n        // Adds a gray border around the screenshot\n        // Useful for e.g. toolbars because they don't have a nice border all the way round due to the tabs\n        public static string SaveScreenShotWithBorder(Rect r, Color borderColor, string name)\n        {\n            int w = (int)r.width;\n            int h = (int)r.height;\n            Color[] colors1 = InternalEditorUtility.ReadScreenPixel(new Vector2(r.x, r.y), w, h);\n            Color[] colors2 = new Color[(w + 2) * (h + 2)];\n            for (int x = 0; x < w; x++)\n            {\n                for (int y = 0; y < h; y++)\n                {\n                    colors2[x + 1 + (w + 2) * (y + 1)] = colors1[x + w * y];\n                }\n            }\n            for (int x = 0; x < w + 2; x++)\n            {\n                colors2[x] = borderColor;\n                colors2[x + (w + 2) * (h + 1)] = borderColor;\n            }\n            for (int y = 0; y < h + 2; y++)\n            {\n                colors2[y * (w + 2)] = borderColor;\n                colors2[y * (w + 2) + (w + 1)] = borderColor;\n            }\n\n            return SaveScreenShot((int)(r.width + 2), (int)(r.height + 2), colors2, name);\n        }\n\n        static string SaveScreenShot(int width, int height, Color[] pixels, string name)\n        {\n            Texture2D t = new Texture2D(width, height);\n            t.SetPixels(pixels, 0);\n            t.Apply(true);\n\n            byte[] bytes = t.EncodeToPNG();\n            Object.DestroyImmediate(t, true);\n\n            string path = GetUniquePathForName(name);\n            System.IO.File.WriteAllBytes(path, bytes);\n            Debug.Log(string.Format(\"Saved screenshot at {0}\", path));\n            return path;\n        }\n\n        static string GetUniquePathForName(string name)\n        {\n            string path = string.Format(\"{0}/../../{1}.png\", Application.dataPath, name);\n            int i = 0;\n            while (System.IO.File.Exists(path))\n            {\n                path = string.Format(\"{0}/../../{1}{2:000}.png\", Application.dataPath, name, i);\n                i++;\n            }\n            return path;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/SearchField.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public class SearchField\n    {\n        int m_ControlID;\n        bool m_WantsFocus;\n        bool m_AutoSetFocusOnFindCommand = true;\n        const float kMinWidth = 36f;\n        const float kMaxWidth = 10000000f;\n        const float kMinToolbarWidth = 29f;\n        const float kMaxToolbarWidth = 200f;\n\n        public delegate void SearchFieldCallback();\n        public event SearchFieldCallback downOrUpArrowKeyPressed;\n\n        public SearchField()\n        {\n            m_ControlID = GUIUtility.GetPermanentControlID();\n        }\n\n        public int searchFieldControlID\n        {\n            get { return m_ControlID; }\n            set { m_ControlID = value; }\n        }\n\n        public bool autoSetFocusOnFindCommand\n        {\n            get { return m_AutoSetFocusOnFindCommand; }\n            set { m_AutoSetFocusOnFindCommand = value; }\n        }\n\n        public void SetFocus()\n        {\n            m_WantsFocus = true;\n        }\n\n        public bool HasFocus()\n        {\n            return GUIUtility.keyboardControl == m_ControlID;\n        }\n\n        public string OnGUI(Rect rect, string text, GUIStyle style, GUIStyle cancelButtonStyle, GUIStyle emptyCancelButtonStyle)\n        {\n            CommandEventHandling();\n\n            FocusAndKeyHandling();\n\n            float cancelButtonWidth = cancelButtonStyle.fixedWidth;\n\n            // Cancel button\n            Rect buttonRect = rect;\n            buttonRect.x += rect.width - cancelButtonWidth;\n            buttonRect.width = cancelButtonWidth;\n            if (Event.current.type == EventType.MouseUp && buttonRect.Contains(Event.current.mousePosition))\n            {\n                text = string.Empty;\n                GUIUtility.keyboardControl = 0;\n                GUI.changed = true;\n            }\n\n            // Search field\n            Rect textRect = rect;\n            text = EditorGUI.TextFieldInternal(m_ControlID, textRect, text, style, cancelButtonStyle);\n\n            GUI.Button(buttonRect, GUIContent.none,\n                !string.IsNullOrEmpty(text) ? cancelButtonStyle : emptyCancelButtonStyle);\n            return text;\n        }\n\n        public string OnGUI(Rect rect, string text)\n        {\n            return OnGUI(rect, text, EditorStyles.searchField, EditorStyles.searchFieldCancelButton, EditorStyles.searchFieldCancelButtonEmpty);\n        }\n\n        public string OnGUI(string text, params GUILayoutOption[] options)\n        {\n            Rect rect = GUILayoutUtility.GetRect(kMinWidth, kMaxWidth, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.searchField, options);\n            return OnGUI(rect, text);\n        }\n\n        public string OnToolbarGUI(Rect rect, string text)\n        {\n            return OnGUI(rect, text, EditorStyles.toolbarSearchField, EditorStyles.toolbarSearchFieldCancelButton, EditorStyles.toolbarSearchFieldCancelButtonEmpty);\n        }\n\n        public string OnToolbarGUI(string text, params GUILayoutOption[] options)\n        {\n            Rect rect = GUILayoutUtility.GetRect(kMinToolbarWidth, kMaxToolbarWidth, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.toolbarSearchField, options);\n            return OnToolbarGUI(rect, text);\n        }\n\n        void FocusAndKeyHandling()\n        {\n            Event evt = Event.current;\n            if (m_WantsFocus && evt.type == EventType.Repaint)\n            {\n                GUIUtility.keyboardControl = m_ControlID;\n                EditorGUIUtility.editingTextField = true;\n                m_WantsFocus = false;\n            }\n\n            if (evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.DownArrow || evt.keyCode == KeyCode.UpArrow) &&\n                GUIUtility.keyboardControl == m_ControlID && GUIUtility.hotControl == 0)\n            {\n                if (downOrUpArrowKeyPressed != null)\n                {\n                    downOrUpArrowKeyPressed();\n                    evt.Use();\n                }\n            }\n        }\n\n        void CommandEventHandling()\n        {\n            Event evt = Event.current;\n\n            if (evt.type != EventType.ExecuteCommand && evt.type != EventType.ValidateCommand)\n                return;\n\n            if (m_AutoSetFocusOnFindCommand && evt.commandName == EventCommandNames.Find)\n            {\n                if (evt.type == EventType.ExecuteCommand)\n                    SetFocus();\n                evt.Use();\n            }\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/SliderWithTexture.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class EditorGUILayout\n    {\n        internal static void SliderWithTexture(\n            GUIContent label,\n            SerializedProperty property,\n            float sliderMin, float sliderMax,\n            float power,\n            Texture2D sliderBackground,\n            params GUILayoutOption[] options\n        )\n        {\n            var rect = s_LastRect = GetSliderRect(false, options);\n            EditorGUI.SliderWithTexture(rect, label, property, sliderMin, sliderMax, power, sliderBackground);\n        }\n\n        internal static float SliderWithTexture(\n            GUIContent label,\n            float sliderValue, float sliderMin, float sliderMax,\n            string formatString,\n            Texture2D sliderBackground,\n            params GUILayoutOption[] options\n        )\n        {\n            return SliderWithTexture(\n                label, sliderValue, sliderMin, sliderMax, formatString, sliderMin, sliderMax, sliderBackground\n            );\n        }\n\n        internal static float SliderWithTexture(\n            GUIContent label,\n            float sliderValue, float sliderMin, float sliderMax,\n            string formatString, float textFieldMin, float textFieldMax,\n            Texture2D sliderBackground,\n            params GUILayoutOption[] options\n        )\n        {\n            var rect = s_LastRect = GetSliderRect(false, options);\n            return EditorGUI.SliderWithTexture(\n                rect, label, sliderValue, sliderMin, sliderMax, formatString, textFieldMin, textFieldMax, 1f, sliderBackground\n            );\n        }\n    }\n\n    public sealed partial class EditorGUI\n    {\n        internal static void SliderWithTexture(\n            Rect position,\n            GUIContent label,\n            SerializedProperty property,\n            float sliderMin, float sliderMax,\n            float power,\n            Texture2D sliderBackground\n        )\n        {\n            label = BeginProperty(position, label, property);\n\n            BeginChangeCheck();\n\n            var formatString = property.propertyType == SerializedPropertyType.Integer ?\n                kIntFieldFormatString : kFloatFieldFormatString;\n            var newValue = SliderWithTexture(\n                position, label, property.floatValue, sliderMin, sliderMax, formatString, sliderMin, sliderMax, power, sliderBackground\n            );\n\n            if (EndChangeCheck())\n                property.floatValue = newValue;\n\n            EndProperty();\n        }\n\n        internal static float SliderWithTexture(\n            Rect rect,\n            GUIContent label,\n            float sliderValue, float sliderMin, float sliderMax,\n            string formatString,\n            Texture2D sliderBackground,\n            params GUILayoutOption[] options\n        )\n        {\n            return SliderWithTexture(\n                rect, label, sliderValue, sliderMin, sliderMax, formatString, sliderMin, sliderMax, 1f, sliderBackground\n            );\n        }\n\n        internal static float SliderWithTexture(\n            Rect position,\n            GUIContent label,\n            float sliderValue, float sliderMin, float sliderMax,\n            string formatString, float textFieldMin, float textFieldMax,\n            float power,\n            Texture2D sliderBackground\n        )\n        {\n            int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Keyboard, position);\n            var controlRect = PrefixLabel(position, id, label);\n            var dragZone =\n                LabelHasContent(label)\n                ? EditorGUIUtility.DragZoneRect(position)\n                : default(Rect);         // Ensure dragzone is empty when we have no label\n            return DoSlider(\n                controlRect, dragZone, id, sliderValue, sliderMin, sliderMax, formatString, textFieldMin, textFieldMax, power, 1f,\n                EditorStyles.numberField, \"ColorPickerSliderBackground\", \"ColorPickerHorizThumb\", sliderBackground, null\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/SplitView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    /// orders all children along an axis. Resizing, splitting, etc..\n    class SplitView : View, ICleanuppable, IDropArea\n    {\n        const float kRootDropZoneThickness = 70f;\n        const float kRootDropZoneOffset = 50f;\n        const float kRootDropDestinationThickness = 200f;\n        const float kMaxViewDropZoneThickness = 300f;\n        const float kMinViewDropDestinationThickness = 100f;\n\n        public bool vertical = false;\n        public int controlID = 0;\n        public int draggingID = 0;\n\n        [Flags] internal enum ViewEdge\n        {\n            None = 0,\n            Left = 1 << 0,\n            Bottom = 1 << 1,\n            Top = 1 << 2,\n            Right = 1 << 3,\n            BottomLeft = Bottom | Left,\n            BottomRight = Bottom | Right,\n            TopLeft = Top | Left,\n            TopRight = Top | Right,\n            FitsVertical = Top | Bottom,\n            FitsHorizontal = Left | Right,\n            Before = Top | Left, // \"Before\" in SplitView children\n            After = Bottom | Right // \"After\" in SplitView children\n        }\n\n        private Rect RectFromEdge(Rect rect, ViewEdge edge, float thickness, float offset)\n        {\n            switch (edge)\n            {\n                case ViewEdge.Left:\n                    return new Rect(rect.x - offset, rect.y, thickness, rect.height);\n                case ViewEdge.Right:\n                    return new Rect(rect.xMax - thickness + offset, rect.y, thickness, rect.height);\n                case ViewEdge.Top:\n                    return new Rect(rect.x, rect.y - offset, rect.width, thickness);\n                case ViewEdge.Bottom:\n                    return new Rect(rect.x, rect.yMax - thickness + offset, rect.width, thickness);\n                default:\n                    throw new ArgumentException(\"Specify exactly one edge\");\n            }\n        }\n\n        // Extra info for dropping.\n        internal class ExtraDropInfo\n        {\n            public bool rootWindow;\n            public ViewEdge edge;\n            public int index;\n            public ExtraDropInfo(bool rootWindow, ViewEdge edge, int index)\n            {\n                this.rootWindow = rootWindow;\n                this.edge = edge;\n                this.index = index;\n            }\n        }\n\n        SplitterState splitState = null;\n\n        void SetupSplitter()\n        {\n            float[] actualSizes = new float[children.Length];\n            float[] minSizes = new float[children.Length];\n\n            for (int j = 0; j < children.Length; j++)\n            {\n                View c = (View)children[j];\n                actualSizes[j] = GUIUtility.RoundToPixelGrid(vertical ? c.position.height : c.position.width);\n                minSizes[j] = GUIUtility.RoundToPixelGrid(vertical ? c.minSize.y : c.minSize.x);\n            }\n\n            splitState = SplitterState.FromAbsolute(actualSizes, minSizes, null);\n            splitState.splitSize = 10;\n        }\n\n        void SetupRectsFromSplitter()\n        {\n            if (children.Length == 0)\n                return;\n\n            float cursor = 0;\n\n            float total = 0;\n            foreach (float size in splitState.realSizes)\n            {\n                total += size;\n            }\n            float scale = 1;\n            if (total > (vertical ? position.height : position.width))\n                scale = (vertical ? position.height : position.width) / total;\n\n            // OSX webviews might trigger nested Repaint events when being resized\n            // so we protected the GUI state at this level\n            SavedGUIState state = SavedGUIState.Create();\n\n            for (int i = 0; i < children.Length; i++)\n                cursor += PlaceView(i, cursor, splitState.realSizes[i] * scale);\n\n            state.ApplyAndForget();\n        }\n\n        // 2-part process: recalc children sizes bottomup, the reflow top-down\n        static void RecalcMinMaxAndReflowAll(SplitView start)\n        {\n            // search upwards and find the topmost\n            SplitView root = start, next = start;\n            do\n            {\n                root = next;\n                next = root.parent as SplitView;\n            }\n            while (next);\n\n            RecalcMinMaxRecurse(root);\n            ReflowRecurse(root);\n        }\n\n        static void RecalcMinMaxRecurse(SplitView node)\n        {\n            foreach (View i in node.children)\n            {\n                SplitView sv = i as SplitView;\n                if (sv)\n                    RecalcMinMaxRecurse(sv);\n            }\n            node.ChildrenMinMaxChanged();\n        }\n\n        static void ReflowRecurse(SplitView node)\n        {\n            node.Reflow();\n            foreach (View i in node.children)\n            {\n                SplitView sv = i as SplitView;\n                if (sv)\n                    RecalcMinMaxRecurse(sv);\n            }\n        }\n\n        internal override void Reflow()\n        {\n            SetupSplitter();\n\n            for (int k = 0; k < children.Length - 1; k++)\n                splitState.DoSplitter(k, k + 1, 0);\n            splitState.RelativeToRealSizes(vertical ? GUIUtility.RoundToPixelGrid(position.height) : GUIUtility.RoundToPixelGrid(position.width));\n            SetupRectsFromSplitter();\n        }\n\n        float PlaceView(int i, float pos, float size)\n        {\n            float width = position.width;\n            float height = position.height;\n            float roundPos = GUIUtility.RoundToPixelGrid(pos);\n            float roundSize = GUIUtility.RoundToPixelGrid(pos + size) - roundPos;\n            Rect newRect;\n            if (vertical)\n            {\n                newRect = new Rect(0, roundPos, width, roundSize);\n                if (i == children.Length - 1)\n                    newRect.height = height - roundPos;\n            }\n            else\n            {\n                newRect = new Rect(roundPos, 0, roundSize, height);\n                if (i == children.Length - 1)\n                    newRect.width = width - roundPos;\n            }\n\n            children[i].position = newRect;\n            return vertical ? newRect.height : newRect.width;\n        }\n\n        public override void AddChild(View child, int idx)\n        {\n            base.AddChild(child, idx);\n            ChildrenMinMaxChanged();\n            splitState = null;\n        }\n\n        public void RemoveChildNice(View child)\n        {\n            if (children.Length != 1)\n            {\n                // Make neighbors to grow to take space\n                int idx = IndexOfChild(child);\n                float moveToPos = 0;\n                if (idx == 0)\n                    moveToPos = 0;\n                else if (idx == children.Length - 1)\n                    moveToPos = 1;\n                else\n                    moveToPos = .5f;\n\n                moveToPos = vertical ?\n                    Mathf.Lerp(child.position.yMin, child.position.yMax, moveToPos) :\n                    Mathf.Lerp(child.position.xMin, child.position.xMax, moveToPos);\n\n                if (idx > 0)\n                {\n                    View c = (View)children[idx - 1];\n                    Rect r = c.position;\n                    if (vertical)\n                        r.yMax = moveToPos;\n                    else\n                        r.xMax = moveToPos;\n                    c.position = r;\n\n                    if (c is SplitView)\n                        ((SplitView)c).Reflow();\n                }\n\n                if (idx < children.Length - 1)\n                {\n                    View c = (View)children[idx + 1];\n                    Rect r = c.position;\n                    if (vertical)\n                        c.position = new Rect(r.x, moveToPos, r.width, r.yMax - moveToPos);\n                    else\n                        c.position = new Rect(moveToPos, r.y, r.xMax - moveToPos, r.height);\n\n                    if (c is SplitView)\n                        ((SplitView)c).Reflow();\n                }\n            }\n            RemoveChild(child);\n        }\n\n        public override void RemoveChild(View child)\n        {\n            splitState = null;\n            base.RemoveChild(child);\n        }\n\n        DropInfo RootViewDropZone(ViewEdge edge, Vector2 mousePos, Rect screenRect)\n        {\n            var offset = (edge & ViewEdge.FitsVertical) != 0 ? kRootDropZoneThickness : kRootDropZoneOffset;\n            if (!RectFromEdge(screenRect, edge, kRootDropZoneThickness, offset).Contains(mousePos))\n                return null;\n\n            var dropInfo = new DropInfo(this);\n            dropInfo.type = DropInfo.Type.Pane;\n            dropInfo.userData = new ExtraDropInfo(true, edge, 0);\n            dropInfo.rect = RectFromEdge(screenRect, edge, kRootDropDestinationThickness, 0f);\n            return dropInfo;\n        }\n\n        public DropInfo DragOverRootView(Vector2 mouseScreenPosition)\n        {\n            if (children.Length == 1 && DockArea.s_IgnoreDockingForView == children[0])\n            {\n                return null; // Prevent dragging the view from a single-view window into itself\n            }\n            return RootViewDropZone(ViewEdge.Bottom, mouseScreenPosition, screenPosition)\n                ?? RootViewDropZone(ViewEdge.Top, mouseScreenPosition, screenPosition)\n                ?? RootViewDropZone(ViewEdge.Left, mouseScreenPosition, screenPosition)\n                ?? RootViewDropZone(ViewEdge.Right, mouseScreenPosition, screenPosition);\n        }\n\n        public DropInfo DragOver(EditorWindow w, Vector2 mouseScreenPosition)\n        {\n            for (var childIndex = 0; childIndex < children.Length; ++childIndex)\n            {\n                var child = children[childIndex];\n\n                // skip so you can't dock a view to a subview of itself\n                if (child == DockArea.s_IgnoreDockingForView)\n                    continue;\n\n                // Skip if child is a splitview (it'll handle its rect itself)\n                if (child is SplitView)\n                    continue;\n\n                // Collect flags of which edge zones the mouse is inside\n                var mouseEdges = ViewEdge.None;\n                var childRect = child.screenPosition;\n                var childRectWithoutDock = RectFromEdge(childRect, ViewEdge.Bottom, childRect.height - DockArea.kDockHeight, 0f);\n                var borderWidth = Mathf.Min(Mathf.Round(childRectWithoutDock.width / 3), kMaxViewDropZoneThickness);\n                var borderHeight = Mathf.Min(Mathf.Round(childRectWithoutDock.height / 3), kMaxViewDropZoneThickness);\n                var leftDropZone = RectFromEdge(childRectWithoutDock, ViewEdge.Left, borderWidth, 0f);\n                var rightDropZone = RectFromEdge(childRectWithoutDock, ViewEdge.Right, borderWidth, 0f);\n                var bottomDropZone = RectFromEdge(childRectWithoutDock, ViewEdge.Bottom, borderHeight, 0f);\n                var topDropZone = RectFromEdge(childRectWithoutDock, ViewEdge.Top, borderHeight, 0f);\n\n                if (leftDropZone.Contains(mouseScreenPosition))\n                    mouseEdges |= ViewEdge.Left;\n\n                if (rightDropZone.Contains(mouseScreenPosition))\n                    mouseEdges |= ViewEdge.Right;\n\n                if (bottomDropZone.Contains(mouseScreenPosition))\n                    mouseEdges |= ViewEdge.Bottom;\n\n                if (topDropZone.Contains(mouseScreenPosition))\n                    mouseEdges |= ViewEdge.Top;\n\n                // If mouse is in more than one zone, it is in a corner. Find the corner and divide it diagonally...\n                var mouseToCorner = Vector2.zero;\n                var oppositeToCorner = Vector2.zero;\n                var ccwEdge = mouseEdges;\n                var cwEdge = mouseEdges;\n                switch (mouseEdges)\n                {\n                    case ViewEdge.BottomLeft:\n                        ccwEdge = ViewEdge.Bottom;\n                        cwEdge = ViewEdge.Left;\n                        mouseToCorner = new Vector2(childRectWithoutDock.x, childRectWithoutDock.yMax) - mouseScreenPosition;\n                        oppositeToCorner = new Vector2(-borderWidth, borderHeight);\n                        break;\n                    case ViewEdge.BottomRight:\n                        ccwEdge = ViewEdge.Right;\n                        cwEdge = ViewEdge.Bottom;\n                        mouseToCorner = new Vector2(childRectWithoutDock.xMax, childRectWithoutDock.yMax) - mouseScreenPosition;\n                        oppositeToCorner = new Vector2(borderWidth, borderHeight);\n                        break;\n                    case ViewEdge.TopLeft:\n                        ccwEdge = ViewEdge.Left;\n                        cwEdge = ViewEdge.Top;\n                        mouseToCorner = new Vector2(childRectWithoutDock.x, childRectWithoutDock.y) - mouseScreenPosition;\n                        oppositeToCorner = new Vector2(-borderWidth, -borderHeight);\n                        break;\n                    case ViewEdge.TopRight:\n                        ccwEdge = ViewEdge.Top;\n                        cwEdge = ViewEdge.Right;\n                        mouseToCorner = new Vector2(childRectWithoutDock.xMax, childRectWithoutDock.y) - mouseScreenPosition;\n                        oppositeToCorner = new Vector2(borderWidth, -borderHeight);\n                        break;\n                }\n                // ...then choose the edge based on the half the mouse is in\n                mouseEdges = mouseToCorner.x * oppositeToCorner.y - mouseToCorner.y * oppositeToCorner.x < 0 ? ccwEdge : cwEdge;\n\n                if (mouseEdges != ViewEdge.None) // Valid drop zone\n                {\n                    var targetThickness = Mathf.Round(((mouseEdges & ViewEdge.FitsHorizontal) != 0 ? childRect.width : childRect.height) / 3);\n                    targetThickness = Mathf.Max(targetThickness, kMinViewDropDestinationThickness);\n\n                    var dropInfo = new DropInfo(this);\n                    dropInfo.userData = new ExtraDropInfo(false, mouseEdges, childIndex);\n                    dropInfo.type = DropInfo.Type.Pane;\n                    dropInfo.rect = RectFromEdge(childRect, mouseEdges, targetThickness, 0f);\n                    return dropInfo;\n                }\n            }\n            // Claim the drag if we are the root split view, so it doesn't fall through to obscured windows\n            if (screenPosition.Contains(mouseScreenPosition) && !(parent is SplitView))\n            {\n                return new DropInfo(null);\n            }\n\n            return null;\n        }\n\n        /// Notification so other views can respond to this.\n        protected override void ChildrenMinMaxChanged()\n        {\n            Vector2 min = Vector2.zero, max = Vector2.zero;\n            if (vertical)\n            {\n                foreach (View child in children)\n                {\n                    min.x = Mathf.Max(child.minSize.x, min.x);\n                    max.x = Mathf.Max(child.maxSize.x, max.x);\n                    min.y += child.minSize.y;\n                    max.y += child.maxSize.y;\n                }\n            }\n            else\n            {\n                foreach (View child in children)\n                {\n                    min.x += child.minSize.x;\n                    max.x += child.maxSize.x;\n                    min.y = Mathf.Max(child.minSize.y, min.y);\n                    max.y = Mathf.Max(child.maxSize.y, max.y);\n                }\n            }\n            splitState = null;\n\n            SetMinMaxSizes(min, max);\n        }\n\n        public override string ToString()\n        {\n            return vertical ? \"SplitView (vert)\" : \"SplitView (horiz)\";\n        }\n\n        public bool PerformDrop(EditorWindow dropWindow, DropInfo dropInfo, Vector2 screenPos)\n        {\n            var extraInfo = dropInfo.userData as ExtraDropInfo;\n            var rootWindow = extraInfo.rootWindow;\n            var edge = extraInfo.edge;\n            var dropIndex = extraInfo.index;\n            var dropRect = dropInfo.rect;\n            var beginning = (edge & ViewEdge.Before) != 0;\n            var wantsVertical = (edge & ViewEdge.FitsVertical) != 0;\n            SplitView parentForDrop = null;\n            if (vertical == wantsVertical || children.Length < 2)\n            { // Current view can accommodate desired drop\n                if (!beginning)\n                {\n                    if (rootWindow)\n                        dropIndex = children.Length;\n                    else\n                        ++dropIndex;\n                }\n                parentForDrop = this;\n            }\n            else if (rootWindow)\n            { // Docking to a window: need to insert a parent\n                var newParent = ScriptableObject.CreateInstance<SplitView>();\n                newParent.position = position;\n                if (window.rootView == this)\n                    window.rootView = newParent;\n                else // Main window has MainView as its root\n                    parent.AddChild(newParent, parent.IndexOfChild(this));\n                newParent.AddChild(this);\n                position = new Rect(Vector2.zero, position.size);\n\n                dropIndex = beginning ? 0 : 1;\n                parentForDrop = newParent;\n            }\n            else\n            { // Docking in a view: need to insert a child\n                var newChild = ScriptableObject.CreateInstance<SplitView>();\n\n                newChild.AddChild(children[dropIndex]);\n                AddChild(newChild, dropIndex);\n                newChild.position = newChild.children[0].position;\n                newChild.children[0].position = new Rect(Vector2.zero, newChild.position.size);\n\n                dropIndex = beginning ? 0 : 1;\n                parentForDrop = newChild;\n            }\n            dropRect.position = dropRect.position - screenPosition.position;\n            var newDockArea = ScriptableObject.CreateInstance<DockArea>();\n            parentForDrop.vertical = wantsVertical;\n            parentForDrop.MakeRoomForRect(dropRect);\n            parentForDrop.AddChild(newDockArea, dropIndex);\n            newDockArea.position = dropRect;\n            DockArea.s_OriginalDragSource.RemoveTab(dropWindow, killIfEmpty: true, sendEvents: false);\n            dropWindow.m_Parent = newDockArea;\n            newDockArea.AddTab(dropWindow, sendPaneEvents: false);\n            Reflow();\n            RecalcMinMaxAndReflowAll(this);\n            newDockArea.MakeVistaDWMHappyDance();\n            dropWindow.Focus();\n            return true;\n        }\n\n        void MakeRoomForRect(Rect r)\n        {\n            Rect[] sources = new Rect[children.Length];\n            for (int i = 0; i < sources.Length; i++)\n                sources[i] = children[i].position;\n\n            CalcRoomForRect(sources, r);\n            for (int i = 0; i < sources.Length; i++)\n                children[i].position = sources[i];\n        }\n\n        void CalcRoomForRect(Rect[] sources, Rect r)\n        {\n            float start = vertical ? r.y : r.x;\n            float end = start + (vertical ? r.height : r.width);\n            float mid = (start + end) * .5f;\n\n            // Find out where we should split\n            int splitPos;\n            for (splitPos = 0; splitPos < sources.Length; splitPos++)\n            {\n                float midPos = vertical ?\n                    (sources[splitPos].y + sources[splitPos].height * .5f) :\n                    (sources[splitPos].x + sources[splitPos].width * .5f);\n                if (midPos > mid)\n                    break;\n            }\n\n            float p2 = start;\n            for (int i = splitPos - 1; i >= 0; i--)\n            {\n                if (vertical)\n                {\n                    sources[i].yMax = p2;\n                    if (sources[i].height < children[i].minSize.y)\n                        p2 = sources[i].yMin = sources[i].yMax - children[i].minSize.y;\n                    else\n                        break;\n                }\n                else\n                {\n                    sources[i].xMax = p2;\n                    if (sources[i].width < children[i].minSize.x)\n                        p2 = sources[i].xMin = sources[i].xMax - children[i].minSize.x;\n                    else\n                        break;\n                }\n            }\n            // if we're below zero, move everything forward\n            if (p2 < 0)\n            {\n                float delta = -p2;\n                for (int i = 0; i < splitPos - 1; i++)\n                {\n                    if (vertical)\n                        sources[i].y += delta;\n                    else\n                        sources[i].x += delta;\n                }\n                end += delta;\n            }\n\n            p2 = end;\n            for (int i = splitPos; i < sources.Length; i++)\n            {\n                if (vertical)\n                {\n                    float tmp = sources[i].yMax;\n                    sources[i].yMin = p2;\n                    sources[i].yMax = tmp;\n                    if (sources[i].height < children[i].minSize.y)\n                        p2 = sources[i].yMax = sources[i].yMin + children[i].minSize.y;\n                    else\n                        break;\n                }\n                else\n                {\n                    float tmp = sources[i].xMax;\n                    sources[i].xMin = p2;\n                    sources[i].xMax = tmp;\n                    if (sources[i].width < children[i].minSize.x)\n                        p2 = sources[i].xMax = sources[i].xMin + children[i].minSize.x;\n                    else\n                        break;\n                }\n            }\n            // if we're above max, move everything forward\n            float limit = vertical ? position.height : position.width;\n            if (p2 > limit)\n            {\n                float delta = limit - p2;\n                for (int i = 0; i < splitPos - 1; i++)\n                {\n                    if (vertical)\n                        sources[i].y += delta;\n                    else\n                        sources[i].x += delta;\n                }\n                end += delta;\n            }\n        }\n\n        /// Clean up this view & propagate up.\n        public void Cleanup()\n        {\n            var parentSplitView = parent as SplitView;\n\n            // My parent is a split view, I am a split view with only one child.\n            // We move my child up to my parent and then destroy myself.\n            if (parentSplitView != null && children.Length == 1)\n            {\n                var child = children[0];\n                parentSplitView.AddChild(child, parentSplitView.IndexOfChild(this));\n                parentSplitView.RemoveChild(this);\n                child.position = position;\n\n                if (!Unsupported.IsDestroyScriptableObject(this))\n                    DestroyImmediate(this);\n                parentSplitView.Cleanup(); // Propagate the clean up.\n\n                return;\n            }\n\n            if (parentSplitView != null)\n            {\n                parentSplitView.Cleanup();\n                // The parent might have moved US up and gotten rid of itself. Because we are modifying the\n                // parentSplitView recursively, it might points to a split view that's already been destroyed.\n                parentSplitView = parent as SplitView;\n\n                // If both my parent and I are split views with same orientation, we can move our views up and\n                // destroy ourselves. In the example as shown below, we want to move scene and game to the parent\n                // and then destroy ourselves, to avoid unnecessary nesting.\n                //\n                // SplitView (horizontal)       -- my parent\n                // |_____SplitView (horizontal) -- myself\n                //        |______Scene          -- my child\n                //        |______Game           -- my child\n                if (parentSplitView != null && parentSplitView.vertical == vertical)\n                {\n                    var myChildren = new List<View>(children);\n                    var idx = parent.IndexOfChild(this);\n\n                    foreach (var child in myChildren)\n                    {\n                        RemoveChild(child);\n                        parentSplitView.AddChild(child, idx++);\n                        child.position = new Rect(position.x + child.position.x, position.y + child.position.y,\n                            child.position.width, child.position.height);\n                    }\n\n                    // Don't let this fall through to the `children == 0` case because we don't want to be removed\n                    // \"nicely.\" our children have already been merged to the parent with correct positions, so\n                    // there is no need to recalculate sibling dimensions (and may incorrectly resize views that\n                    // have been recursively cleaned up).\n                    parentSplitView.RemoveChild(this);\n                    if (!Unsupported.IsDestroyScriptableObject(this))\n                        DestroyImmediate(this, true);\n                    parentSplitView.Cleanup();\n\n                    return;\n                }\n            }\n\n            // I am a split view with no children, I need to destroy myself, :(\n            if (children.Length == 0)\n            {\n                if (parent == null && window != null)\n                {\n                    // if we're root in the window, we'll remove ourselves\n                    window.Close();\n                }\n                else\n                {\n                    var ic = parent as ICleanuppable;\n                    if (parent is SplitView parentSplitVIew)\n                    {\n                        parentSplitVIew.RemoveChildNice(this);\n                        if (!Unsupported.IsDestroyScriptableObject(this))\n                            DestroyImmediate(this, true);\n                    }\n                    else\n                    {\n                        // This is we're root in the main window.\n                        // We want to stay, but tell the parent (MainWindow) to Cleanup, so he can reduce us to zero-size\n                        /*                  parent.RemoveChild (this);*/\n                    }\n                    ic?.Cleanup();\n                }\n            }\n            else\n            {\n                splitState = null;\n                Reflow();\n            }\n        }\n\n        internal const float kGrabDist = 5;\n        public void SplitGUI(Event evt)\n        {\n            if (splitState == null)\n                SetupSplitter();\n\n            SplitView sp = parent as SplitView;\n            if (sp)\n            {\n                Event e = new Event(evt);\n                e.mousePosition += new Vector2(position.x, position.y);\n                sp.SplitGUI(e);\n                if (e.type == EventType.Used)\n                    evt.Use();\n            }\n\n            float pos = vertical ? evt.mousePosition.y : evt.mousePosition.x;\n            int id = GUIUtility.GetControlID(546739, FocusType.Passive);\n            controlID = id;\n\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (children.Length != 1) // is there a splitter\n                    {\n                        float cursor = vertical ? children[0].position.y : children[0].position.x;\n                        cursor = GUIUtility.RoundToPixelGrid(cursor);\n\n                        for (int i = 0; i < children.Length - 1; i++)\n                        {\n                            if (i >= splitState.realSizes.Length)\n                            {\n                                DockArea dock = GUIView.current as DockArea;\n                                string name = \"Non-dock area \" + GUIView.current.GetType();\n                                if (dock && dock.m_Selected < dock.m_Panes.Count && dock.m_Panes[dock.m_Selected])\n                                    name = dock.m_Panes[dock.m_Selected].GetType().ToString();\n\n                                if (Unsupported.IsDeveloperMode())\n                                    Debug.LogError(\"Real sizes out of bounds for: \" + name + \" index: \" + i + \" RealSizes: \" + splitState.realSizes.Length);\n\n                                SetupSplitter();\n                            }\n                            Rect splitterRect = vertical ?\n                                new Rect(children[0].position.x, cursor + splitState.realSizes[i] - splitState.splitSize / 2, children[0].position.width, splitState.splitSize) :\n                                new Rect(cursor + splitState.realSizes[i] - splitState.splitSize / 2, children[0].position.y, splitState.splitSize, children[0].position.height);\n\n                            if (GUIUtility.HitTest(splitterRect, evt))\n                            {\n                                splitState.splitterInitialOffset = GUIUtility.RoundToPixelGrid(pos);\n                                splitState.currentActiveSplitter = i;\n                                GUIUtility.hotControl = id;\n                                draggingID = id;\n                                evt.Use();\n                                break;\n                            }\n\n                            cursor += splitState.realSizes[i];\n                        }\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    // NOTE: if we were Drag initiator and our id was changed, update hotcontrol to keep allowing drag.\n                    // Entities (or other package) could be modifying ControlID list when drag starts (see https://jira.unity3d.com/browse/UUM-67862)\n                    if (draggingID != 0 && id != draggingID && draggingID == GUIUtility.hotControl)\n                    {\n                        draggingID = id;\n                        GUIUtility.hotControl = id;\n                    }\n\n                    if (children.Length > 1 && (GUIUtility.hotControl == id) && (splitState.currentActiveSplitter >= 0))\n                    {\n                        float diff = GUIUtility.RoundToPixelGrid(pos) - splitState.splitterInitialOffset;\n                        if (Mathf.Abs(diff) > 0.01f)\n                        {\n                            splitState.splitterInitialOffset = GUIUtility.RoundToPixelGrid(pos);\n                            splitState.DoSplitter(splitState.currentActiveSplitter, splitState.currentActiveSplitter + 1, diff);\n                        }\n\n                        SetupRectsFromSplitter();\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    draggingID = 0;\n                    if (GUIUtility.hotControl == id)\n                        GUIUtility.hotControl = 0;\n                    break;\n            }\n        }\n\n        protected override void SetPosition(Rect newPos)\n        {\n            base.SetPosition(newPos);\n            Reflow();\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/Splitter.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine.Serialization;\n\nnamespace UnityEditor\n{\n    /// *undocumented*\n    [System.Serializable]\n    internal class SplitterState : ISerializationCallbackReceiver\n    {\n        const int defaultSplitSize = 6;\n\n        public int ID;\n        public float splitterInitialOffset;\n        public int currentActiveSplitter = -1;\n\n        public float[] realSizes;\n        public float[] relativeSizes; // these should always add up to 1\n\n        public float[] minSizes;\n        public float[] maxSizes;\n\n        public float lastTotalSize = 0;\n\n        public float splitSize;\n\n        public float xOffset;\n\n        [SerializeField]\n        int m_Version;\n\n#pragma warning disable CS0649\n        [SerializeField]\n        [FormerlySerializedAs(\"realSizes\")]\n        int[] oldRealSizes;\n\n        [SerializeField]\n        [FormerlySerializedAs(\"minSizes\")]\n        int[] oldMinSizes;\n\n        [SerializeField]\n        [FormerlySerializedAs(\"maxSizes\")]\n        int[] oldMaxSizes;\n\n        [SerializeField]\n        [FormerlySerializedAs(\"splitSize\")]\n        int oldSplitSize;\n#pragma warning restore CS0649\n\n        #region Old Constructors\n\n        // In the past, pixelsPerPoint was always 1, so points could be stored as ints. With the introduction of high-dpi\n        // and arbitrary scaling, the implementation has been changed to store floats. For backwards compatibility, the\n        // old constructors remain available but are NOT recommended anymore, since they imply a conversion from int[] to\n        // float[]. Consider using the static functions FromAbsolute and FromRelative instead.\n\n        public SplitterState(params float[] relativeSizes)\n        {\n            InitFromRelative(relativeSizes, null, null, 0);\n        }\n\n        static System.Converter<int, float> s_ConverterDelegate = CastIntToFloat;\n        static float CastIntToFloat(int input) { return (float)input; }\n\n        public SplitterState(int[] realSizes, int[] minSizes, int[] maxSizes)\n        {\n            InitFromAbsolute(\n                System.Array.ConvertAll(realSizes, s_ConverterDelegate),\n                minSizes == null ? null : System.Array.ConvertAll(minSizes, s_ConverterDelegate),\n                maxSizes == null ? null : System.Array.ConvertAll(maxSizes, s_ConverterDelegate));\n        }\n\n        public SplitterState(float[] relativeSizes, int[] minSizes, int[] maxSizes)\n        {\n            InitFromRelative(\n                relativeSizes,\n                minSizes == null ? null : System.Array.ConvertAll(minSizes, s_ConverterDelegate),\n                maxSizes == null ? null : System.Array.ConvertAll(maxSizes, s_ConverterDelegate),\n                0);\n        }\n\n        public SplitterState(float[] relativeSizes, int[] minSizes, int[] maxSizes, int splitSize)\n        {\n            InitFromRelative(\n                relativeSizes,\n                minSizes == null ? null : System.Array.ConvertAll(minSizes, s_ConverterDelegate),\n                maxSizes == null ? null : System.Array.ConvertAll(maxSizes, s_ConverterDelegate),\n                splitSize);\n        }\n\n        #endregion // Old Constructors\n\n        SplitterState(bool useless) {} // A parameterless constructor would conflict with the obsolete params constructor.\n\n        public static SplitterState FromAbsolute(float[] realSizes, float[] minSizes, float[] maxSizes)\n        {\n            var state = new SplitterState(false);\n            state.InitFromAbsolute(realSizes, minSizes, maxSizes);\n            return state;\n        }\n\n        public static SplitterState FromRelative(params float[] relativeSizes)\n        {\n            var state = new SplitterState(false);\n            state.InitFromRelative(relativeSizes, null, null, 0);\n            return state;\n        }\n\n        public static SplitterState FromRelative(float[] relativeSizes, float[] minSizes, float[] maxSizes)\n        {\n            var state = new SplitterState(false);\n            state.InitFromRelative(relativeSizes, minSizes, maxSizes, 0);\n            return state;\n        }\n\n        public static SplitterState FromRelative(float[] relativeSizes, float[] minSizes, float[] maxSizes, int splitSize)\n        {\n            var state = new SplitterState(false);\n            state.InitFromRelative(relativeSizes, minSizes, maxSizes, splitSize);\n            return state;\n        }\n\n        public bool IsValid()\n        {\n            return realSizes != null && minSizes != null && maxSizes != null && relativeSizes != null &&\n                realSizes.Length > 0 && minSizes.Length > 0 && maxSizes.Length > 0 && relativeSizes.Length > 0 &&\n                realSizes.Length == minSizes.Length && minSizes.Length == maxSizes.Length && maxSizes.Length == relativeSizes.Length;\n        }\n\n        void InitFromAbsolute(float[] realSizes, float[] minSizes, float[] maxSizes)\n        {\n            this.realSizes = realSizes;\n            this.minSizes = minSizes ?? new float[realSizes.Length];\n            this.maxSizes = maxSizes ?? new float[realSizes.Length];\n            relativeSizes = new float[realSizes.Length];\n\n            splitSize = splitSize == 0 ? defaultSplitSize : splitSize;\n\n            RealToRelativeSizes();\n        }\n\n        void InitFromRelative(float[] relativeSizes, float[] minSizes, float[] maxSizes, int splitSize)\n        {\n            this.relativeSizes = relativeSizes;\n            this.minSizes = minSizes == null ? new float[relativeSizes.Length] : minSizes;\n            this.maxSizes = maxSizes == null ? new float[relativeSizes.Length] : maxSizes;\n            realSizes = new float[relativeSizes.Length];\n\n            this.splitSize = splitSize == 0 ? defaultSplitSize : splitSize;\n\n            NormalizeRelativeSizes();\n        }\n\n        public void NormalizeRelativeSizes()\n        {\n            float check = 1.0f; // try to avoid rounding issues\n            float total = 0;\n            int k;\n\n            // distribute space relatively\n            for (k = 0; k < relativeSizes.Length; k++)\n                total += relativeSizes[k];\n\n            for (k = 0; k < relativeSizes.Length; k++)\n            {\n                relativeSizes[k] = relativeSizes[k] / total;\n                check -= relativeSizes[k];\n            }\n\n            relativeSizes[relativeSizes.Length - 1] += check;\n        }\n\n        public void RealToRelativeSizes()\n        {\n            if (relativeSizes.Length == 0)\n                return;\n\n            float check = 1.0f; // try to avoid rounding issues\n            float total = 0;\n            int k;\n\n            // distribute space relatively\n            for (k = 0; k < realSizes.Length; k++)\n                total += realSizes[k];\n\n            if (total > 0.001f)\n            {\n                for (k = 0; k < realSizes.Length; k++)\n                {\n                    relativeSizes[k] = realSizes[k] / total;\n                    check -= relativeSizes[k];\n                }\n\n                relativeSizes[relativeSizes.Length - 1] += check;\n            }\n            else\n            {\n                // Distribute evenly\n                float relativeSize = 1f / relativeSizes.Length;\n                for (k = 0; k < relativeSizes.Length; k++)\n                    relativeSizes[k] = relativeSize;\n            }\n        }\n\n        public void RelativeToRealSizes(float totalSpace)\n        {\n            int k;\n            float spaceToShare = totalSpace;\n\n            for (k = 0; k < relativeSizes.Length; k++)\n            {\n                realSizes[k] = GUIUtility.RoundToPixelGrid(relativeSizes[k] * totalSpace);\n\n                if (realSizes[k] < minSizes[k])\n                    realSizes[k] = minSizes[k];\n\n                spaceToShare -= realSizes[k];\n            }\n\n            if (spaceToShare < 0)\n            {\n                for (k = 0; k < relativeSizes.Length; k++)\n                {\n                    if (realSizes[k] > minSizes[k])\n                    {\n                        float spaceInThisOne = realSizes[k] - minSizes[k];\n                        float spaceToTake = -spaceToShare < spaceInThisOne ? -spaceToShare : spaceInThisOne;\n\n                        spaceToShare += spaceToTake;\n                        realSizes[k] -= spaceToTake;\n\n                        if (spaceToShare >= 0)\n                            break;\n                    }\n                }\n            }\n\n            int last = realSizes.Length - 1;\n            if (last >= 0)\n            {\n                realSizes[last] += spaceToShare; // try to avoid rounding issues\n\n                if (realSizes[last] < minSizes[last]) // but never ignore min size!\n                    realSizes[last] = minSizes[last];\n            }\n        }\n\n        public void DoSplitter(int i1, int i2, float diff)\n        {\n            // TODO: This does not handle all cases properly. Theres a hope we will not encounter those cases in the editor.\n            // Needs to be fixed once its passed to users.\n            float h1 = realSizes[i1];\n            float h2 = realSizes[i2];\n            float m1 = minSizes[i1];\n            float m2 = minSizes[i2];\n            float x1 = maxSizes[i1];\n            float x2 = maxSizes[i2];\n\n            bool diffed = false;\n\n            if (m1 == 0) m1 = 16;\n            if (m2 == 0) m2 = 16;\n\n            // min constraint\n            if (h1 + diff < m1)\n            {\n                diff -= m1 - h1;\n                realSizes[i2] += realSizes[i1] - m1;\n                realSizes[i1] = m1;\n\n                if (realSizes[i2] < m2)\n                {\n                    if (i2 != realSizes.Length - 1)\n                        DoSplitter(i2, i2 + 1, diff);\n                    else\n                        realSizes[i2] = m2;\n                }\n\n                if (i1 != 0)\n                    DoSplitter(i1 - 1, i2, diff);\n                else\n                    // can't resize more...\n                    splitterInitialOffset -= diff;\n\n                diffed = true;\n            }\n            else if (h2 - diff < m2)\n            {\n                diff -= h2 - m2;\n                realSizes[i1] += realSizes[i2] - m2;\n                realSizes[i2] = m2;\n\n                if (realSizes[i1] < m1)\n                {\n                    if (i1 != 0)\n                        DoSplitter(i1 - 1, i2, diff);\n                    else\n                        realSizes[i1] = m1;\n                }\n\n                if (i2 != realSizes.Length - 1)\n                    DoSplitter(i1, i2 + 1, diff);\n                else\n                    // can't resize more...\n                    splitterInitialOffset -= diff;\n\n                diffed = true;\n            }\n\n            // max constraint\n            if (!diffed)\n            {\n                if ((x1 != 0) && (h1 + diff > x1))\n                {\n                    diff -= realSizes[i1] - x1;\n                    realSizes[i2] += realSizes[i1] - x1;\n                    realSizes[i1] = x1;\n\n                    if (i1 != 0)\n                        DoSplitter(i1 - 1, i2, diff);\n                    else\n                        // can't resize more...\n                        splitterInitialOffset -= diff;\n\n                    diffed = true;\n                }\n                else if ((x2 != 0) && (h2 - diff > x2))\n                {\n                    diff -= h2 - x2;\n                    realSizes[i1] += realSizes[i2] - x2;\n                    realSizes[i2] = x2;\n\n                    if (i2 != realSizes.Length - 1)\n                        DoSplitter(i1, i2 + 1, diff);\n                    else\n                        // can't resize more...\n                        splitterInitialOffset -= diff;\n\n                    diffed = true;\n                }\n            }\n\n            // normal case - we have space for resizing\n            if (!diffed)\n            {\n                realSizes[i1] += diff;\n                realSizes[i2] -= diff;\n            }\n        }\n\n        public void OnBeforeSerialize()\n        {\n            m_Version = 1;\n        }\n\n        static void ConvertOldArray(int[] oldArray, ref float[] newArray)\n        {\n            if ((newArray == null || newArray.Length == 0) && oldArray != null && oldArray.Length > 0)\n                newArray = System.Array.ConvertAll(oldArray, s_ConverterDelegate);\n        }\n\n        public void OnAfterDeserialize()\n        {\n            if (m_Version == 0)\n            {\n                // Case 1241206: Convert int to float\n                ConvertOldArray(oldMaxSizes, ref maxSizes);\n                ConvertOldArray(oldMinSizes, ref minSizes);\n                ConvertOldArray(oldRealSizes, ref realSizes);\n                splitSize = oldSplitSize;\n            }\n\n            m_Version = 1;\n        }\n    }\n\n    class SplitterGUILayout\n    {\n        static int splitterHash = \"Splitter\".GetHashCode();\n\n        /// *undocumented*\n        internal class GUISplitterGroup : GUILayoutGroup\n        {\n            public SplitterState state;\n\n            public override void SetHorizontal(float x, float width)\n            {\n                if (!isVertical)\n                {\n                    int k;\n\n                    state.xOffset = x;\n\n                    float alignedWidth = GUIUtility.RoundToPixelGrid(width);\n                    if (alignedWidth != state.lastTotalSize)\n                    {\n                        state.RelativeToRealSizes(alignedWidth);\n                        state.lastTotalSize = alignedWidth;\n\n                        // maintain constraints while resizing\n                        for (k = 0; k < state.realSizes.Length - 1; k++)\n                            state.DoSplitter(k, k + 1, 0);\n                    }\n\n                    k = 0;\n\n                    foreach (GUILayoutEntry i in entries)\n                    {\n                        float thisSize = state.realSizes[k];\n\n                        i.SetHorizontal(GUIUtility.RoundToPixelGrid(x), GUIUtility.RoundToPixelGrid(thisSize));\n                        x += thisSize + spacing;\n                        k++;\n                    }\n                }\n                else\n                {\n                    base.SetHorizontal(x, width);\n                }\n            }\n\n            public override void SetVertical(float y, float height)\n            {\n                rect.y = y; rect.height = height;\n\n                RectOffset padding = style.padding;\n\n                if (isVertical)\n                {\n                    // If we have a skin, adjust the sizing to take care of padding (if we don't have a skin the vertical margins have been propagated fully up the hierarchy)...\n                    if (style != GUIStyle.none)\n                    {\n                        float topMar = padding.top, bottomMar = padding.bottom;\n                        if (entries.Count != 0)\n                        {\n                            topMar = Mathf.Max(topMar, ((GUILayoutEntry)entries[0]).marginTop);\n                            bottomMar = Mathf.Max(bottomMar, ((GUILayoutEntry)entries[entries.Count - 1]).marginBottom);\n                        }\n                        y += topMar;\n                        height -= bottomMar + topMar;\n                    }\n\n                    // Set the positions\n                    int k;\n\n                    float alignedHeight = GUIUtility.RoundToPixelGrid(height);\n                    if (alignedHeight != state.lastTotalSize)\n                    {\n                        state.RelativeToRealSizes(alignedHeight);\n                        state.lastTotalSize = alignedHeight;\n\n                        // maintain constraints while resizing\n                        for (k = 0; k < state.realSizes.Length - 1; k++)\n                            state.DoSplitter(k, k + 1, 0);\n                    }\n\n                    k = 0;\n\n                    foreach (GUILayoutEntry i in entries)\n                    {\n                        float thisSize = state.realSizes[k];\n\n                        i.SetVertical(GUIUtility.RoundToPixelGrid(y), GUIUtility.RoundToPixelGrid(thisSize));\n                        y += thisSize + spacing;\n                        k++;\n                    }\n                }\n                else\n                {\n                    // If we have a GUIStyle here, we need to respect the subelements' margins\n                    if (style != GUIStyle.none)\n                    {\n                        foreach (GUILayoutEntry i in entries)\n                        {\n                            float topMar = Mathf.Max(i.marginTop, padding.top);\n                            float thisY = y + topMar;\n                            float thisHeight = height - Mathf.Max(i.marginBottom, padding.bottom) - topMar;\n\n                            if (i.stretchHeight != 0)\n                                i.SetVertical(thisY, thisHeight);\n                            else\n                                i.SetVertical(thisY, Mathf.Clamp(thisHeight, i.minHeight, i.maxHeight));\n                        }\n                    }\n                    else\n                    {\n                        // If not, the subelements' margins have already been propagated upwards to this group, so we can safely ignore them\n                        float thisY = y - marginTop;\n                        float thisHeight = height + marginVertical;\n                        foreach (GUILayoutEntry i in entries)\n                        {\n                            if (i.stretchHeight != 0)\n                                i.SetVertical(thisY + i.marginTop, thisHeight - i.marginVertical);\n                            else\n                                i.SetVertical(thisY + i.marginTop, Mathf.Clamp(thisHeight - i.marginVertical, i.minHeight, i.maxHeight));\n                        }\n                    }\n                }\n            }\n        }\n\n        public static void BeginSplit(SplitterState state, GUIStyle style, bool vertical, params GUILayoutOption[] options)\n        {\n            float pos;\n            var g = (GUISplitterGroup)GUILayoutUtility.BeginLayoutGroup(style, null, typeof(GUISplitterGroup));\n            state.ID = GUIUtility.GetControlID(splitterHash, FocusType.Passive);\n\n            switch (Event.current.GetTypeForControl(state.ID))\n            {\n                case EventType.Layout:\n                {\n                    g.state = state;\n                    g.resetCoords = false;\n                    g.isVertical = vertical;\n                    g.ApplyOptions(options);\n                    break;\n                }\n                case EventType.MouseDown:\n                {\n                    if ((Event.current.button == 0) && (Event.current.clickCount == 1))\n                    {\n                        float cursor = GUIUtility.RoundToPixelGrid(g.isVertical ? g.rect.y : g.rect.x);\n                        pos = GUIUtility.RoundToPixelGrid(g.isVertical ? Event.current.mousePosition.y : Event.current.mousePosition.x);\n\n                        for (int i = 0; i < state.relativeSizes.Length - 1; i++)\n                        {\n                            Rect splitterRect = g.isVertical ?\n                                new Rect(state.xOffset + g.rect.x, cursor + state.realSizes[i] - state.splitSize / 2, g.rect.width, state.splitSize) :\n                                new Rect(state.xOffset + cursor + state.realSizes[i] - state.splitSize / 2, g.rect.y, state.splitSize, g.rect.height);\n\n                            if (GUIUtility.HitTest(splitterRect, Event.current))\n                            {\n                                state.splitterInitialOffset = pos;\n                                state.currentActiveSplitter = i;\n                                GUIUtility.hotControl = state.ID;\n                                Event.current.Use();\n                                break;\n                            }\n\n                            cursor = GUIUtility.RoundToPixelGrid(cursor + state.realSizes[i]);\n                        }\n                    }\n                    break;\n                }\n                case EventType.MouseDrag:\n                {\n                    if ((GUIUtility.hotControl == state.ID) && (state.currentActiveSplitter >= 0))\n                    {\n                        pos = g.isVertical ? Event.current.mousePosition.y : Event.current.mousePosition.x;\n                        GUIUtility.RoundToPixelGrid(pos);\n                        float diff = pos - state.splitterInitialOffset;\n\n                        if (diff != 0)\n                        {\n                            state.splitterInitialOffset = pos;\n                            state.DoSplitter(state.currentActiveSplitter, state.currentActiveSplitter + 1, diff);\n                        }\n\n                        Event.current.Use();\n                    }\n                    break;\n                }\n                case EventType.MouseUp:\n                {\n                    if (GUIUtility.hotControl == state.ID)\n                    {\n                        GUIUtility.hotControl = 0;\n                        state.currentActiveSplitter = -1;\n                        state.RealToRelativeSizes();\n                        Event.current.Use();\n                    }\n                    break;\n                }\n                case EventType.Repaint:\n                {\n                    float cursor = GUIUtility.RoundToPixelGrid(g.isVertical ? g.rect.y : g.rect.x);\n\n                    for (var i = 0; i < state.relativeSizes.Length - 1; i++)\n                    {\n                        var splitterRect = g.isVertical ?\n                            new Rect(state.xOffset + g.rect.x, cursor + state.realSizes[i] - state.splitSize / 2, g.rect.width, state.splitSize) :\n                            new Rect(state.xOffset + cursor + state.realSizes[i] - state.splitSize / 2, g.rect.y, state.splitSize, g.rect.height);\n\n                        EditorGUIUtility.AddCursorRect(splitterRect, g.isVertical ? MouseCursor.ResizeVertical : MouseCursor.SplitResizeLeftRight, state.ID);\n\n                        cursor += state.realSizes[i];\n                    }\n                }\n\n                break;\n            }\n        }\n\n        public static void BeginHorizontalSplit(SplitterState state, params GUILayoutOption[] options)\n        {\n            BeginSplit(state, GUIStyle.none, false, options);\n        }\n\n        public static void BeginVerticalSplit(SplitterState state, params GUILayoutOption[] options)\n        {\n            BeginSplit(state, GUIStyle.none, true, options);\n        }\n\n        public static void BeginHorizontalSplit(SplitterState state, GUIStyle style, params GUILayoutOption[] options)\n        {\n            BeginSplit(state, style, false, options);\n        }\n\n        public static void BeginVerticalSplit(SplitterState state, GUIStyle style, params GUILayoutOption[] options)\n        {\n            BeginSplit(state, style, true, options);\n        }\n\n        public static void EndVerticalSplit()\n        {\n            GUILayoutUtility.EndLayoutGroup();\n        }\n\n        public static void EndHorizontalSplit()\n        {\n            GUILayoutUtility.EndLayoutGroup();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/StructPropertyGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class StructPropertyGUILayout\n    {\n        internal static void GenericStruct(SerializedProperty property, params GUILayoutOption[] options)\n        {\n            float height = EditorGUI.kStructHeaderLineHeight + EditorGUI.kSingleLineHeight * GetChildrenCount(property);\n            Rect rect = GUILayoutUtility.GetRect(EditorGUILayout.kLabelFloatMinW, EditorGUILayout.kLabelFloatMaxW,\n                height, height, EditorStyles.layerMaskField, options);\n\n            StructPropertyGUI.GenericStruct(rect, property);\n        }\n\n        internal static int GetChildrenCount(SerializedProperty property)\n        {\n            int count = 0;\n            SerializedProperty iterator = property.Copy();\n            var end = iterator.GetEndProperty();\n            while (!SerializedProperty.EqualContents(iterator, end))\n            {\n                count++;\n                iterator.NextVisible(true);\n            }\n\n            return count;\n        }\n    }\n\n    internal class StructPropertyGUI\n    {\n        static class Styles\n        {\n            public static readonly GUIStyle sectionLabel = new GUIStyle(EditorStyles.label)\n            {\n                alignment = TextAnchor.UpperLeft\n            };\n        }\n        internal static void GenericStruct(Rect position, SerializedProperty property)\n        {\n            GUI.Label(EditorGUI.IndentedRect(position), property.displayName, Styles.sectionLabel);\n            position.y += EditorGUI.kStructHeaderLineHeight;\n\n            DoChildren(position, property);\n        }\n\n        private static void DoChildren(Rect position, SerializedProperty property)\n        {\n            position.height = EditorGUI.kSingleLineHeight;\n\n            EditorGUI.indentLevel++;\n\n            SerializedProperty iterator = property.Copy();\n            var end = iterator.GetEndProperty();\n            iterator.NextVisible(true);\n            while (!SerializedProperty.EqualContents(iterator, end))\n            {\n                EditorGUI.PropertyField(position, iterator);\n                position.y += EditorGUI.kSingleLineHeight;\n                if (!iterator.NextVisible(false))\n                    break;\n            }\n\n            EditorGUI.indentLevel--;\n\n            EditorGUILayout.Space();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/SubToolbar.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class SubToolbar\n    {\n        public float Width { get; set; }\n\n        public virtual void OnGUI(Rect rect)\n        {\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GUI/TargetChoiceHandler.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing Object = UnityEngine.Object;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System;\n\n// NOTE:\n// This file should only contain internal functions of the EditorGUI class\n//\n\nnamespace UnityEditor\n{\n    internal class TargetChoiceHandler\n    {\n        internal struct PropertyAndSourcePathInfo\n        {\n            public SerializedProperty[] properties;\n            public string assetPath;\n        }\n\n        internal struct ObjectInstanceAndSourcePathInfo\n        {\n            public Object instanceObject;\n            public string assetPath;\n        }\n\n        internal struct ObjectInstanceAndSourceInfo\n        {\n            public Object instanceObject;\n            public Object correspondingObjectInSource;\n        }\n\n        internal delegate void TargetChoiceMenuFunction(SerializedProperty property, Object target);\n\n        internal static bool DuplicateArrayElement(object userData)\n        {\n            SerializedProperty property = (SerializedProperty)userData;\n            bool result = property.DuplicateCommand();\n            property.serializedObject.ApplyModifiedProperties();\n            EditorUtility.ForceReloadInspectors();\n            return result;\n        }\n\n        internal static bool DeleteArrayElement(object userData)\n        {\n            SerializedProperty property = (SerializedProperty)userData;\n            bool result = property.DeleteCommand();\n            property.serializedObject.ApplyModifiedProperties();\n            EditorUtility.ForceReloadInspectors();\n            return result;\n        }\n\n        internal static void ApplyPrefabPropertyOverride(object userData)\n        {\n            PropertyAndSourcePathInfo info = (PropertyAndSourcePathInfo)userData;\n            if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(info.assetPath, PrefabUtility.SaveVerb.Apply))\n                return;\n            for (int i = 0; i < info.properties.Length; i++)\n                PrefabUtility.ApplyPropertyOverride(info.properties[i], info.assetPath, InteractionMode.UserAction);\n            EditorUtility.ForceReloadInspectors();\n        }\n\n        internal static void RevertPrefabPropertyOverride(object userData)\n        {\n            SerializedProperty[] properties = (SerializedProperty[])userData;\n            PrefabUtility.RevertPropertyOverrides(properties, InteractionMode.UserAction);\n            EditorUtility.ForceReloadInspectors();\n        }\n\n        internal static void ApplyPrefabObjectOverride(object userData)\n        {\n            ObjectInstanceAndSourcePathInfo info = (ObjectInstanceAndSourcePathInfo)userData;\n            if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(info.assetPath, PrefabUtility.SaveVerb.Apply))\n                return;\n            PrefabUtility.ApplyObjectOverride(info.instanceObject, info.assetPath, InteractionMode.UserAction);\n            EditorUtility.ForceReloadInspectors();\n        }\n\n        internal static void RevertPrefabObjectOverride(object userData)\n        {\n            Object obj = (Object)userData;\n            PrefabUtility.RevertObjectOverride(obj, InteractionMode.UserAction);\n            EditorUtility.ForceReloadInspectors();\n        }\n\n        internal static void ApplyPrefabAddedComponent(object userData)\n        {\n            ObjectInstanceAndSourcePathInfo info = (ObjectInstanceAndSourcePathInfo)userData;\n            if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(info.assetPath, PrefabUtility.SaveVerb.Apply))\n                return;\n            PrefabUtility.ApplyAddedComponent((Component)info.instanceObject, info.assetPath, InteractionMode.UserAction);\n            EditorUtility.ForceRebuildInspectors();\n        }\n\n        internal static void RevertPrefabAddedComponent(object userData)\n        {\n            Component obj = (Component)userData;\n            PrefabUtility.RevertAddedComponent(obj, InteractionMode.UserAction);\n            EditorUtility.ForceRebuildInspectors();\n        }\n\n        internal static void ApplyPrefabRemovedComponent(object userData)\n        {\n            ObjectInstanceAndSourceInfo info = (ObjectInstanceAndSourceInfo)userData;\n            string path = AssetDatabase.GetAssetPath(info.correspondingObjectInSource);\n            if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(path, PrefabUtility.SaveVerb.Apply))\n                return;\n            PrefabUtility.ApplyRemovedComponent((GameObject)info.instanceObject, (Component)info.correspondingObjectInSource, InteractionMode.UserAction);\n            EditorUtility.ForceRebuildInspectors();\n        }\n\n        internal static void RevertPrefabRemovedComponent(object userData)\n        {\n            ObjectInstanceAndSourceInfo info = (ObjectInstanceAndSourceInfo)userData;\n            PrefabUtility.RevertRemovedComponent((GameObject)info.instanceObject, (Component)info.correspondingObjectInSource, InteractionMode.UserAction);\n            EditorUtility.ForceRebuildInspectors();\n        }\n\n        internal static void ApplyPrefabAddedGameObjects(object userData)\n        {\n            ObjectInstanceAndSourcePathInfo[] infos = (ObjectInstanceAndSourcePathInfo[])userData;\n\n            GameObject[] gameObjects = new GameObject[infos.Length];\n            for (int i = 0; i < infos.Length; i++)\n            {\n                ObjectInstanceAndSourcePathInfo info = infos[i];\n                gameObjects[i] = info.instanceObject as GameObject;\n            }\n\n            if (!PrefabUtility.HasSameParent(gameObjects))\n                throw new ArgumentException(nameof(gameObjects), \"ApplyPrefabAddedGameObjects requires that GameObjects share the same parent.\");\n\n            if (!HasSameAssetPath(infos))\n                throw new ArgumentException(nameof(infos), \"ApplyPrefabAddedGameObjects requires that GameObjects share the same parent asset path.\");\n\n            if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(infos[0].assetPath, PrefabUtility.SaveVerb.Apply))\n                return;\n\n            PrefabUtility.ApplyAddedGameObjects(gameObjects, infos[0].assetPath, InteractionMode.UserAction);\n            EditorUtility.ForceRebuildInspectors();\n        }\n\n        internal static bool HasSameAssetPath(ObjectInstanceAndSourcePathInfo[] infos)\n        {\n            if (infos == null || infos.Length == 0)\n                throw new ArgumentException(nameof(infos), \"Array is invalid.\");\n\n            string assetPath = infos[0].assetPath;\n            for (int i = 1; i < infos.Length; i++)\n            {\n                if (assetPath != infos[i].assetPath)\n                    return false;\n            }\n\n            return true;\n        }\n\n        internal static void RevertPrefabAddedGameObjects(object userData)\n        {\n            GameObject[] gameObjects = (GameObject[])userData;\n\n            foreach (GameObject go in gameObjects)\n                PrefabUtility.RevertAddedGameObject(go, InteractionMode.UserAction);\n\n            EditorUtility.ForceRebuildInspectors();\n        }\n\n        internal static void SetToValueOfTarget(SerializedProperty property, Object target)\n        {\n            property.SetToValueOfTarget(target);\n            property.serializedObject.ApplyModifiedProperties();\n            EditorUtility.ForceReloadInspectors();\n        }\n\n        private static void TargetChoiceForwardFunction(object userData)\n        {\n            var handler = (PropertyAndTargetHandler)userData;\n            handler.function(handler.property, handler.target);\n        }\n\n        static internal void AddSetToValueOfTargetMenuItems(GenericMenu menu, SerializedProperty property, TargetChoiceMenuFunction func)\n        {\n            SerializedProperty propertyWithPath = property.serializedObject.FindProperty(property.propertyPath);\n            Object[] targets = property.serializedObject.targetObjects;\n            List<string> options = new List<string>();\n            foreach (Object target in targets)\n            {\n                string option = string.Format(\"Set to Value of '{0}'\", target.name);\n                if (options.Contains(option))\n                {\n                    for (int i = 1;; i++)\n                    {\n                        option = string.Format(\"Set to Value of '{0}'({1})\", target.name, i);\n                        if (!options.Contains(option))\n                            break;\n                    }\n                }\n                options.Add(option);\n                menu.AddItem(EditorGUIUtility.TextContent(option), false, TargetChoiceForwardFunction, new PropertyAndTargetHandler(propertyWithPath, target, func));\n            }\n        }\n    }\n\n    public sealed partial class EditorGUI\n    {\n        /// Popup to choose which target to pick the value from. Use only when hasMultipleDifferentValues is true.\n        internal static void TargetChoiceField(Rect position, SerializedProperty property, GUIContent label)\n        {\n            TargetChoiceField(position, property, label, TargetChoiceHandler.SetToValueOfTarget);\n        }\n\n        internal static void TargetChoiceField(Rect position, SerializedProperty property, GUIContent label, TargetChoiceHandler.TargetChoiceMenuFunction func)\n        {\n            EditorGUI.BeginProperty(position, label, property);\n            position = EditorGUI.PrefixLabel(position, 0, label);\n            EditorGUI.BeginHandleMixedValueContentColor();\n            if (GUI.Button(position, EditorGUI.mixedValueContent, EditorStyles.popup))\n            {\n                GenericMenu menu = new GenericMenu();\n                TargetChoiceHandler.AddSetToValueOfTargetMenuItems(menu, property, func);\n                menu.DropDown(position);\n            }\n            EditorGUI.EndHandleMixedValueContentColor();\n            EditorGUI.EndProperty();\n        }\n    }\n\n    public sealed partial class EditorGUILayout\n    {\n        /// Popup to choose which target to pick the value from. Use only when hasMultipleDifferentValues is true.\n        internal static void TargetChoiceField(SerializedProperty property, GUIContent label, params GUILayoutOption[] options)\n        {\n            TargetChoiceField(property, label, TargetChoiceHandler.SetToValueOfTarget, options);\n        }\n\n        internal static void TargetChoiceField(SerializedProperty property, GUIContent label, TargetChoiceHandler.TargetChoiceMenuFunction func, params GUILayoutOption[] options)\n        {\n            Rect rect = GUILayoutUtility.GetRect(EditorGUIUtility.fieldWidth, EditorGUILayout.kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.popup, options);\n            EditorGUI.TargetChoiceField(rect, property, label, func);\n        }\n    }\n\n    internal class PropertyAndTargetHandler\n    {\n        public SerializedProperty property;\n        public Object target;\n        public TargetChoiceHandler.TargetChoiceMenuFunction function;\n        public PropertyAndTargetHandler(SerializedProperty property, Object target, TargetChoiceHandler.TargetChoiceMenuFunction function)\n        {\n            this.property = property;\n            this.target = target;\n            this.function = function;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TextFieldDropDown.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing UnityEngine;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    public sealed partial class EditorGUI\n    {\n        private const string kEmptyDropDownElement = \"--empty--\";\n\n        static internal string DoTextFieldDropDown(Rect rect, int id, string text, string[] dropDownElements, bool delayed)\n        {\n            Rect textFieldRect = new Rect(rect.x, rect.y, rect.width - EditorStyles.textFieldDropDown.fixedWidth, rect.height);\n            Rect popupRect = new Rect(textFieldRect.xMax, textFieldRect.y, EditorStyles.textFieldDropDown.fixedWidth, rect.height);\n\n\n            if (delayed)\n            {\n                text = DelayedTextField(textFieldRect, text, EditorStyles.textFieldDropDownText);\n            }\n            else\n            {\n                bool dummy;\n                text = DoTextField(s_RecycledEditor, id, textFieldRect, text, EditorStyles.textFieldDropDownText, null, out dummy, false, false, false);\n            }\n\n\n            EditorGUI.BeginChangeCheck();\n            int oldIndent = EditorGUI.indentLevel;\n            EditorGUI.indentLevel = 0;\n            int parameterIndex = EditorGUI.Popup(popupRect, \"\", -1, dropDownElements.Length > 0 ? dropDownElements : new string[] { kEmptyDropDownElement }, EditorStyles.textFieldDropDown);\n            if (EditorGUI.EndChangeCheck() && dropDownElements.Length > 0)\n            {\n                text = dropDownElements[parameterIndex];\n            }\n            EditorGUI.indentLevel = oldIndent;\n            return text;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/Toolbars/EditorToolbar.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Overlays;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Toolbars\n{\n    sealed class EditorToolbar\n    {\n        public const string elementClassName = \"unity-editor-toolbar-element\";\n        public const string elementIconClassName = elementClassName + \"__icon\";\n        public const string elementLabelClassName = elementClassName + \"__label\";\n        public const string elementTextIconClassName = elementClassName + \"__text-icon\";\n\n        string[] m_ToolbarElements;\n        readonly EditorWindow m_Context;\n        VisualElement m_RootVisualElement;\n\n        public VisualElement rootVisualElement\n        {\n            get\n            {\n                if (m_RootVisualElement != null)\n                    return m_RootVisualElement;\n                return m_RootVisualElement = CreateOverlay(m_ToolbarElements, m_Context);\n            }\n        }\n\n        public EditorToolbar(IEnumerable<string> toolbarElementIds, EditorWindow context = null)\n        {\n            m_Context = context;\n            m_ToolbarElements = toolbarElementIds.ToArray();\n        }\n\n        public static OverlayToolbar CreateOverlay(IEnumerable<string> toolbarElementIds, EditorWindow context = null)\n        {\n            var root = new OverlayToolbar();\n\n            foreach (var id in toolbarElementIds)\n            {\n                if (TryCreateElement(id, context, out var ve))\n                    root.Add(ve);\n            }\n\n            return root;\n        }\n\n        // Used by MainToolbar, as it doesn't use the same Overlay styling\n        internal void LoadToolbarElements(VisualElement root)\n        {\n            if (root == null)\n                throw new ArgumentNullException(nameof(root));\n\n            EditorToolbarUtility.LoadStyleSheets(\"EditorToolbar\", root);\n\n            foreach (var id in m_ToolbarElements)\n            {\n                if(TryCreateElement(id, m_Context, out var ve))\n                    root.Add(ve);\n            }\n        }\n\n        static bool TryCreateElement(string id, EditorWindow ctx, out VisualElement ve)\n        {\n            if (EditorToolbarManager.instance.TryCreateElementFromId(ctx, id, out ve))\n            {\n                if (ve is IAccessContainerWindow visualWithContext)\n                    visualWithContext.containerWindow = ctx;\n                ve.AddToClassList(elementClassName);\n                return true;\n            }\n\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/Toolbars/EditorToolbarElementAttribute.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Toolbars\n{\n    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]\n    public sealed class EditorToolbarElementAttribute : Attribute\n    {\n        public string id { get; }\n        public Type[] targetWindows { get; }\n\n        public EditorToolbarElementAttribute(string id, params Type[] targetWindows)\n        {\n            this.id = id;\n            this.targetWindows = targetWindows;\n        }\n    }\n\n    public interface IAccessContainerWindow\n    {\n        EditorWindow containerWindow { get; set; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/Toolbars/EditorToolbarManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Reflection;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Toolbars\n{\n    readonly struct ToolbarElementDefinition\n    {\n        public string id { get; }\n        public Type elementType { get; }\n        public Type[] targetContexts { get; }\n\n        public ToolbarElementDefinition(string id, Type elementType, Type[] targetContexts)\n        {\n            this.id = id;\n            this.elementType = elementType;\n            this.targetContexts = targetContexts;\n        }\n    }\n\n    sealed class EditorToolbarManager : ScriptableSingleton<EditorToolbarManager>\n    {\n        readonly Dictionary<string, ToolbarElementDefinition> m_IdToDefinition;\n\n        EditorToolbarManager()\n        {\n            var types = TypeCache.GetTypesWithAttribute<EditorToolbarElementAttribute>();\n            m_IdToDefinition = new Dictionary<string, ToolbarElementDefinition>(types.Count);\n\n            for (int i = 0; i < types.Count; ++i)\n            {\n                var type = types[i];\n                if (typeof(VisualElement).IsAssignableFrom(type))\n                {\n                    var attr = (EditorToolbarElementAttribute)type.GetCustomAttributes(\n                        typeof(EditorToolbarElementAttribute), false)[0];\n                    string id = attr.id;\n                    if (Exists(id))\n                    {\n                        Debug.LogWarning(\n                            $\"Editor Toolbar Element with id {id} already exists. The element will be skipped.\");\n                        continue;\n                    }\n\n                    m_IdToDefinition.Add(attr.id, new ToolbarElementDefinition(id, type, attr.targetWindows));\n                }\n            }\n        }\n\n        public bool TryCreateElementFromId(EditorWindow context, string id, out VisualElement element)\n        {\n            if (m_IdToDefinition.TryGetValue(id, out ToolbarElementDefinition definition))\n            {\n                bool inProperContext = false;\n                if (definition.targetContexts == null || definition.targetContexts.Length == 0)\n                {\n                    inProperContext = true;\n                }\n                else\n                {\n                    foreach (var c in definition.targetContexts)\n                    {\n                        //The main toolbar isn't a window but we support DefaultMainToolbar as a valid context for adding elements\n                        if (context == null && (c == null || typeof(MainToolbarVisual).IsAssignableFrom(c))\n                            || c.IsInstanceOfType(context))\n                        {\n                            inProperContext = true;\n                        }\n                    }\n                }\n\n                if (inProperContext)\n                {\n                    try\n                    {\n                        const BindingFlags flags =  BindingFlags.Instance |\n                            BindingFlags.Public |\n                            BindingFlags.NonPublic |\n                            BindingFlags.CreateInstance;\n\n                        element = (VisualElement)Activator.CreateInstance(definition.elementType, flags, (Binder)null,\n                            null, (CultureInfo)null, (object[])null);\n                        element.AddToClassList(EditorToolbar.elementClassName);\n                        return true;\n                    }\n                    catch (Exception e)\n                    {\n                        Debug.LogError($\"Failed creating toolbar element from ID \\\"{id}\\\".\\n{e}\");\n                    }\n                }\n            }\n\n            element = null;\n            return false;\n        }\n\n        public bool Exists(string id)\n        {\n            return m_IdToDefinition.ContainsKey(id);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/Toolbars/EditorToolbarUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Overlays;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Toolbars\n{\n    public static class EditorToolbarUtility\n    {\n        const string k_UxmlPath = \"UXML/Toolbars/\";\n        const string k_StyleSheetsPath = \"StyleSheets/Toolbars/\";\n        internal const string buttonStripClassName = \"unity-editor-toolbar__button-strip\";\n        internal const string stripElementClassName = buttonStripClassName + \"-element\";\n        internal const string leftStripElementClassName = stripElementClassName + \"--left\";\n        internal const string middleStripElementClassName = stripElementClassName + \"--middle\";\n        internal const string rightStripElementClassName = stripElementClassName + \"--right\";\n        internal const string aloneStripElementClassName = stripElementClassName + \"--alone\";\n        static bool IsRendered(VisualElement element) => element.style.display != DisplayStyle.None && element.visible;\n\n        public static void SetupChildrenAsButtonStrip(VisualElement root)\n        {\n            root.AddToClassList(buttonStripClassName);\n            foreach(var child in root.Children())\n                child.AddToClassList(stripElementClassName);\n            ApplyButtonStripStylesToChildren(root);\n        }\n        internal static void ApplyButtonStripStylesToChildren(VisualElement root)\n        {\n            int count = root.hierarchy.childCount;\n\n            int begin = -1, end = -1;\n\n            for (int i = count - 1; end < 0 && i > -1; i--)\n            {\n                if (IsRendered(root.ElementAt(i)))\n                    end = i;\n            }\n\n            for (var i = 0; i < count; ++i)\n            {\n                var element = root.hierarchy.ElementAt(i);\n\n                if (!IsRendered(element))\n                    continue;\n\n                if (begin < 0)\n                    begin = i;\n\n                element.EnableInClassList(aloneStripElementClassName, i == begin && i == end);\n                element.EnableInClassList(leftStripElementClassName, i == begin && i != end);\n                element.EnableInClassList(rightStripElementClassName, i == end && i != begin);\n                element.EnableInClassList(middleStripElementClassName, i != begin && i != end);\n            }\n        }\n        internal static void LoadStyleSheets(string name, VisualElement target)\n        {\n            var path = k_StyleSheetsPath + name;\n\n            var common = EditorGUIUtility.Load($\"{path}Common.uss\") as StyleSheet;\n            if (common != null)\n                target.styleSheets.Add(common);\n\n            var themeSpecificName = EditorGUIUtility.isProSkin ? \"Dark\" : \"Light\";\n            var themeSpecific = EditorGUIUtility.Load($\"{path}{themeSpecificName}.uss\") as StyleSheet;\n            if (themeSpecific != null)\n                target.styleSheets.Add(themeSpecific);\n        }\n\n        internal static VisualTreeAsset LoadUxml(string name)\n        {\n            return EditorGUIUtility.Load($\"{k_UxmlPath}{name}.uxml\") as VisualTreeAsset;\n        }\n\n        internal static void UpdateIconContent(\n        string text,\n        string textIcon,\n        Texture2D icon,\n        TextElement textElement,\n        TextElement textIconElement,\n        Image iconElement)\n        {\n            if (text == string.Empty)\n            {\n                textElement.style.display = DisplayStyle.None;\n                textIconElement.style.display = DisplayStyle.None;\n            }\n            else\n                textElement.style.display = StyleKeyword.Null;\n\n            // First priority: image icon, if available\n            if (icon != null)\n            {\n                if (iconElement != null)\n                {\n                    iconElement.style.display = DisplayStyle.Flex;\n                    iconElement.image = icon;\n                }\n                if (textIconElement != null)\n                    textIconElement.style.display = DisplayStyle.None;\n            }\n            else if (iconElement != null && iconElement.resolvedStyle.backgroundImage != null)\n            {\n                if (textIconElement != null)\n                    textIconElement.style.display = DisplayStyle.None;\n                iconElement.style.display = DisplayStyle.Flex;\n            }\n            // Second priority: text icon, if available\n            else if (!string.IsNullOrEmpty(textIcon))\n            {\n                if (textIconElement != null)\n                {\n                    textIconElement.style.display = DisplayStyle.Flex;\n                    textIconElement.text = OverlayUtilities.GetSignificantLettersForIcon(textIcon);\n                }\n                if (iconElement != null)\n                    iconElement.style.display = DisplayStyle.None;\n            }\n            // Fall back: abbreviation of text.\n            else if (!string.IsNullOrEmpty(text))\n            {\n                if (textIconElement != null)\n                {\n                    textIconElement.style.display = StyleKeyword.Null;\n                    textIconElement.text = OverlayUtilities.GetSignificantLettersForIcon(text);\n                }\n                if (iconElement != null)\n                    iconElement.style.display = DisplayStyle.None;\n            }\n            else\n            {\n                if (iconElement != null)\n                    iconElement.style.display = DisplayStyle.Flex;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/Toolbars/MainToolbarImguiContainer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Toolbars\n{\n    [EditorToolbarElement(\"Editor Utility/Imgui Subtoolbars\", typeof(DefaultMainToolbar))]\n    sealed class MainToolbarImguiContainer : IMGUIContainer\n    {\n        const float k_PaddingBetweenSubToolbar = 4;\n        const string k_USSClassName = \"unity-editor-toolbar-imgui-container\";\n        static readonly List<SubToolbar> s_SubToolbars = new List<SubToolbar>(1);\n        float m_CurrentWidth;\n\n        public static void AddDeprecatedSubToolbar(SubToolbar subToolbar)\n        {\n            s_SubToolbars.Add(subToolbar);\n        }\n\n        public MainToolbarImguiContainer()\n        {\n            AddToClassList(k_USSClassName);\n            onGUIHandler = OnGUI;\n        }\n\n        void OnGUI()\n        {\n            style.display = s_SubToolbars.Count > 0 ? DisplayStyle.Flex : DisplayStyle.None;\n            UpdateContainerWidth();\n            Rect r = rect;\n            foreach (var subToolbar in s_SubToolbars)\n            {\n                r.width = subToolbar.Width;\n                subToolbar.OnGUI(rect);\n                r.x += rect.width + k_PaddingBetweenSubToolbar;\n            }\n        }\n\n        void UpdateContainerWidth()\n        {\n            float targetWidth = 0;\n            foreach (var subToolbar in s_SubToolbars)\n            {\n                targetWidth += subToolbar.Width;\n            }\n\n            targetWidth += (s_SubToolbars.Count - 1) * k_PaddingBetweenSubToolbar;\n\n            if (!Mathf.Approximately(m_CurrentWidth, targetWidth))\n            {\n                m_CurrentWidth = targetWidth;\n                style.width = m_CurrentWidth;\n                // Set the min and max to ensure the specified width is respected as it does not seem to be always the case\n                // for some reason.\n                style.minWidth = m_CurrentWidth;\n                style.maxWidth = m_CurrentWidth;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/Toolbars/Toolbar.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing UnityEditorInternal;\nusing UnityEditor.Toolbars;\nusing UnityEditor.UIElements;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    abstract class MainToolbarVisual\n    {\n        VisualElement m_Root;\n\n        public VisualElement root\n        {\n            get\n            {\n                if (m_Root == null)\n                    m_Root = CreateRoot();\n\n                return m_Root;\n            }\n        }\n\n        protected abstract VisualElement CreateRoot();\n    }\n\n    // The main toolbar\n    class Toolbar : GUIView\n    {\n        public const float k_ToolbarHeight = 36f;\n        private const string k_MainToolbarUSSClassName = \"unity-editor-main-toolbar\";\n\n        static class Styles\n        {\n            public static readonly GUIStyle appToolbar = \"AppToolbar\";\n\n            public static readonly GUIStyle paneOptions = new GUIStyle(\"PaneOptions\")\n            {\n                fixedHeight = k_ToolbarHeight\n            };\n        }\n\n        public static Toolbar get;\n\n        public static bool isLastShowRequestPartial = true;\n\n        MainToolbarVisual m_MainToolbarVisual;\n\n        [SerializeField]\n        string m_LastLoadedLayoutName;\n\n        VisualElement m_Root;\n\n        internal static string lastLoadedLayoutName\n        {\n            get\n            {\n                if (get == null)\n                {\n                    return \"Layout\";\n                }\n                return string.IsNullOrEmpty(get.m_LastLoadedLayoutName) ? \"Layout\" : get.m_LastLoadedLayoutName;\n            }\n            set\n            {\n                if (!get)\n                    return;\n                get.m_LastLoadedLayoutName = value;\n                get.Repaint();\n            }\n        }\n\n        protected override void OnEnable()\n        {\n            base.OnEnable();\n            EditorApplication.modifierKeysChanged += Repaint;\n            get = this;\n            m_EventInterests.wantsLessLayoutEvents = true;\n            CreateContents();\n        }\n\n        void CreateContents()\n        {\n            m_MainToolbarVisual = (MainToolbarVisual)Activator.CreateInstance(typeof(DefaultMainToolbar));\n            m_Root?.RemoveFromHierarchy();\n            m_Root = CreateRoot();\n\n            if (windowBackend?.visualTree is VisualElement visualTree)\n            {\n                visualTree.Add(m_Root);\n                m_Root.Add(m_MainToolbarVisual.root);\n            }\n\n            RepaintToolbar();\n        }\n\n        protected override void OnDisable()\n        {\n            m_Root?.RemoveFromHierarchy();\n            base.OnDisable();\n            EditorApplication.modifierKeysChanged -= Repaint;\n        }\n\n        protected override bool OnFocus()\n        {\n            return false;\n        }\n\n        protected override void OldOnGUI()\n        {\n            if (Event.current.type == EventType.Repaint)\n                Styles.appToolbar.Draw(new Rect(0, 0, position.width, position.height), false, false, false, false);\n        }\n\n        static VisualElement CreateRoot()\n        {\n            var name = VisualElement.k_RootVisualContainerName;\n            var root = new VisualElement()\n            {\n                name = VisualElementUtils.GetUniqueName(name),\n                pickingMode = PickingMode.Ignore, // do not eat events so IMGUI gets them\n                viewDataKey = name,\n                renderHints = RenderHints.ClipWithScissors\n            };\n            root.pseudoStates |= PseudoStates.Root;\n            root.AddToClassList(k_MainToolbarUSSClassName);\n\n            UIElementsEditorUtility.AddDefaultEditorStyleSheets(root);\n            root.StretchToParentSize();\n            root.style.overflow = Overflow.Hidden;\n            return root;\n        }\n\n        protected override void OnBackingScaleFactorChanged()\n        {\n            base.OnBackingScaleFactorChanged();\n            CreateContents();\n        }\n\n        [RequiredByNativeCode]\n        internal static void RepaintToolbar()\n        {\n            if (get != null)\n                get.Repaint();\n        }\n\n        public float CalcHeight()\n        {\n            return k_ToolbarHeight;\n        }\n\n        public Rect GetToolbarPosition()\n        {\n            return position;\n        }\n\n        // @todo Remove when collab updates\n        internal static void AddSubToolbar(SubToolbar subToolbar)\n        {\n            MainToolbarImguiContainer.AddDeprecatedSubToolbar(subToolbar);\n        }\n\n        // Repaints all views, called from C++ when playmode entering is aborted\n        // and when the user clicks on the playmode button.\n        [RequiredByNativeCode]\n        static void InternalWillTogglePlaymode()\n        {\n            InternalEditorUtility.RepaintAllViews();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/AssetOrGameObjectTreeViewDragging.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing UnityEditor.SceneManagement;\nusing UnityEditorInternal;\nusing UnityEngine.Assertions;\nusing Object = UnityEngine.Object;\n\nusing TreeViewDragging = UnityEditor.IMGUI.Controls.TreeViewDragging<int>;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\n\nnamespace UnityEditor\n{\n    // Implements dragging behavior for HierarchyProperty based data: Assets or GameObjects\n\n    internal class AssetsTreeViewDragging : TreeViewDragging\n    {\n        public AssetsTreeViewDragging(TreeViewController treeView)\n            : base(treeView)\n        {\n        }\n\n        public override bool CanStartDrag(TreeViewItem targetItem, List<int> draggedItemIDs, Vector2 mouseDownPosition)\n        {\n            // Prevent dragging of immutable root folder\n            foreach (var draggedItemID in draggedItemIDs)\n            {\n                var path = AssetDatabase.GetAssetPath(draggedItemID);\n                if (AssetDatabase.IsValidFolder(path) && !AssetDatabase.TryGetAssetFolderInfo(path, out _, out _))\n                    return false;\n\n            }\n            return true;\n        }\n\n        public override void StartDrag(TreeViewItem draggedItem, List<int> draggedItemIDs)\n        {\n            DragAndDrop.PrepareStartDrag();\n\n            DragAndDrop.objectReferences = ProjectWindowUtil.GetDragAndDropObjects(draggedItem.id, draggedItemIDs);\n\n            DragAndDrop.paths = ProjectWindowUtil.GetDragAndDropPaths(draggedItem.id, draggedItemIDs);\n            if (DragAndDrop.objectReferences.Length > 1)\n                DragAndDrop.StartDrag(\"<Multiple>\");\n            else\n            {\n                string title = ObjectNames.GetDragAndDropTitle(InternalEditorUtility.GetObjectFromInstanceID(draggedItem.id));\n                DragAndDrop.StartDrag(title);\n            }\n        }\n\n        public override DragAndDropVisualMode DoDrag(TreeViewItem parentItem, TreeViewItem targetItem, bool perform, DropPosition dropPos)\n        {\n            var dragToInstanceId = parentItem?.id ?? 0;\n            return DragAndDrop.DropOnProjectBrowserWindow(dragToInstanceId, AssetDatabase.GetAssetPath(dragToInstanceId), perform);\n        }\n    }\n\n    internal class GameObjectsTreeViewDragging : TreeViewDragging\n    {\n        public delegate DragAndDropVisualMode CustomDraggingDelegate(GameObjectTreeViewItem parentItem, GameObjectTreeViewItem targetItem, DropPosition dropPos, bool perform);\n        CustomDraggingDelegate m_CustomDragHandling;\n        const string kSceneHeaderDragString = \"SceneHeaderList\";\n\n        public Transform parentForDraggedObjectsOutsideItems { get; set; }\n\n        public GameObjectsTreeViewDragging(TreeViewController treeView) : base(treeView) {}\n\n        public void SetCustomDragHandler(CustomDraggingDelegate handler)\n        {\n            m_CustomDragHandling = handler;\n        }\n\n        public override void StartDrag(TreeViewItem draggedItem, List<int> draggedItemIDs)\n        {\n            DragAndDrop.PrepareStartDrag();\n\n            if ((Event.current.control || Event.current.command) && !draggedItemIDs.Contains(draggedItem.id))\n            {\n                draggedItemIDs.Add(draggedItem.id);\n            }\n\n            // Ensure correct order for hierarchy items (to preserve visible order when dropping at new location)\n            draggedItemIDs = m_TreeView.SortIDsInVisiblityOrder(draggedItemIDs);\n\n            if (!draggedItemIDs.Contains(draggedItem.id))\n                draggedItemIDs = new List<int> { draggedItem.id };\n\n            Object[] draggedObjReferences = ProjectWindowUtil.GetDragAndDropObjects(draggedItem.id, draggedItemIDs);\n            DragAndDrop.objectReferences = draggedObjReferences;\n\n            // After introducing multi-scene, UnityEngine.Scene can be selected in HierarchyWindow.\n            // UnityEngine.Scene is not a UnityEngine.Object.\n            // So DragAndDrop.objectReferences can't cover this case.\n            List<Scene> draggedScenes = GetDraggedScenes(draggedItemIDs);\n            if (draggedScenes != null)\n            {\n                DragAndDrop.SetGenericData(kSceneHeaderDragString, draggedScenes);\n\n                List<string> paths = new List<string>();\n                foreach (Scene scene in draggedScenes)\n                {\n                    if (scene.path.Length > 0)\n                        paths.Add(scene.path);\n                }\n                DragAndDrop.paths = paths.ToArray();\n            }\n\n            string title;\n            if (draggedItemIDs.Count > 1)\n                title = \"<Multiple>\";\n            else\n            {\n                if (draggedObjReferences.Length == 1)\n                    title = ObjectNames.GetDragAndDropTitle(draggedObjReferences[0]);\n                else if (draggedScenes != null && draggedScenes.Count == 1)\n                    title = draggedScenes[0].path;\n                else\n                {\n                    title = \"Unhandled dragged item\";\n                    Debug.LogError(\"Unhandled dragged item\");\n                }\n            }\n            DragAndDrop.StartDrag(title);\n\n            dataSource.SetupChildParentReferencesIfNeeded();\n        }\n\n        GameObjectTreeViewDataSource dataSource { get { return (GameObjectTreeViewDataSource)m_TreeView.data; } }\n\n        public override DragAndDropVisualMode DoDrag(TreeViewItem parentItem, TreeViewItem targetItem, bool perform, DropPosition dropPos)\n        {\n            var hierarchyTargetItem = targetItem as GameObjectTreeViewItem;\n\n            // Allow client to handle drag\n            if (m_CustomDragHandling != null)\n            {\n                DragAndDropVisualMode dragResult = m_CustomDragHandling(parentItem as GameObjectTreeViewItem, hierarchyTargetItem, dropPos, perform);\n                if (dragResult != DragAndDropVisualMode.None)\n                    return dragResult;\n            }\n\n            // Scene dragging logic\n            DragAndDropVisualMode dragSceneResult = DoDragScenes(parentItem as GameObjectTreeViewItem, hierarchyTargetItem, perform, dropPos);\n            if (dragSceneResult != DragAndDropVisualMode.None)\n                return dragSceneResult;\n\n            if (targetItem != null && !IsDropTargetUserModifiable(hierarchyTargetItem, dropPos))\n                return DragAndDropVisualMode.Rejected;\n\n            var option = HierarchyDropFlags.None;\n            var searchActive = !string.IsNullOrEmpty(dataSource.searchString);\n            if (searchActive)\n                option |= HierarchyDropFlags.SearchActive;\n            if (parentItem == null || targetItem == null)\n            {\n                // Here we are dragging outside any treeview items:\n\n                if (parentForDraggedObjectsOutsideItems != null)\n                {\n                    // Use specific parent for DragAndDropForwarding\n                    return DragAndDrop.DropOnHierarchyWindow(0, option, parentForDraggedObjectsOutsideItems, perform);\n                }\n                else\n                {\n                    // Simulate drag upon the last loaded scene in the hierarchy (adds as last root sibling of the last scene)\n                    Scene lastScene = dataSource.GetLastScene();\n                    if (!lastScene.IsValid())\n                        return DragAndDropVisualMode.Rejected;\n\n                    option |= HierarchyDropFlags.DropUpon;\n                    return DragAndDrop.DropOnHierarchyWindow(lastScene.handle, option, null, perform);\n                }\n            }\n\n            // Here we are hovering over items\n\n            var draggingUpon = dropPos == TreeViewDragging.DropPosition.Upon;\n\n            if (searchActive && !draggingUpon)\n            {\n                return DragAndDropVisualMode.None;\n            }\n\n            if (draggingUpon)\n            {\n                option |= HierarchyDropFlags.DropUpon;\n            }\n            else\n            {\n                if (dropPos == TreeViewDragging.DropPosition.Above)\n                {\n                    option |= HierarchyDropFlags.DropAbove;\n                }\n\n                option |= HierarchyDropFlags.DropBetween;\n            }\n\n            bool isDroppingBetweenParentAndFirstChild = parentItem != null && targetItem != parentItem && dropPos == DropPosition.Above && parentItem.children[0] == targetItem;\n            if (isDroppingBetweenParentAndFirstChild)\n            {\n                option |= HierarchyDropFlags.DropAfterParent;\n            }\n\n            int gameObjectOrSceneInstanceID = GetDropTargetInstanceID(hierarchyTargetItem, dropPos);\n            if (gameObjectOrSceneInstanceID == 0)\n                return DragAndDropVisualMode.Rejected;\n\n            if (perform && SubSceneGUI.IsUsingSubScenes() && !IsValidSubSceneDropTarget(gameObjectOrSceneInstanceID, dropPos, DragAndDrop.objectReferences))\n                return DragAndDropVisualMode.Rejected;\n\n            GameObject go = EditorUtility.InstanceIDToObject(gameObjectOrSceneInstanceID) as GameObject;\n            if (go != null)\n            {\n                DragAndDropVisualMode visualMode;\n                if (PrefabReplaceUtility.GetDragVisualModeAndShowMenuWithReplaceMenuItemsWhenNeeded(go, draggingUpon, perform, true, true, out visualMode))\n                {\n                    return visualMode;\n                }\n            }\n\n            return DragAndDrop.DropOnHierarchyWindow(gameObjectOrSceneInstanceID, option, null, perform);\n        }\n\n        int GetDropTargetInstanceID(GameObjectTreeViewItem hierarchyTargetItem, DropPosition dropPosition)\n        {\n            if (SubSceneGUI.IsUsingSubScenes())\n            {\n                var gameObjectDropTarget = hierarchyTargetItem.objectPPTR as GameObject;\n                if (gameObjectDropTarget != null)\n                {\n                    if (dropPosition == DropPosition.Above)\n                        return hierarchyTargetItem.id;\n                    if (SubSceneGUI.IsSubSceneHeader(gameObjectDropTarget))\n                    {\n                        Scene subScene = SubSceneGUI.GetSubScene(gameObjectDropTarget);\n                        if (subScene.IsValid())\n                            return subScene.handle;\n                        else\n                            return 0;\n                    }\n                }\n            }\n            return hierarchyTargetItem.id;\n        }\n\n        bool IsValidSubSceneDropTarget(int dropTargetGameObjectOrSceneInstanceID, DropPosition dropPosition, Object[] draggedObjects)\n        {\n            if (draggedObjects == null || draggedObjects.Length == 0)\n                return false;\n\n            Transform parentForDrop = GetTransformParentForDrop(dropTargetGameObjectOrSceneInstanceID, dropPosition);\n            if (parentForDrop == null)\n            {\n                // Drop is on a root scene which is always allowed\n                return true;\n            }\n\n            foreach (var obj in draggedObjects)\n            {\n                var gameObject = obj as GameObject;\n                if (gameObject == null)\n                    continue;\n\n                // Require all dragged objects to be valid (since native cannot filter out invalid sub scene drags currently)\n                if (SubSceneGUI.IsChildOrSameAsOtherTransform(parentForDrop, gameObject.transform))\n                    return false;\n            }\n\n            // Valid drop target for current dragged objects\n            return true;\n        }\n\n        Transform GetTransformParentForDrop(int gameObjectOrSceneInstanceID, DropPosition dropPosition)\n        {\n            var obj = EditorUtility.InstanceIDToObject(gameObjectOrSceneInstanceID);\n            if (obj != null)\n            {\n                // Find transform parent from GameObject\n                var go = obj as GameObject;\n                if (go == null)\n                    throw new InvalidOperationException(\"Unexpected UnityEngine.Object type in Hierarchy \" + obj.GetType());\n\n                switch (dropPosition)\n                {\n                    case DropPosition.Upon:\n                        return go.transform;\n\n                    case DropPosition.Below:\n                    case DropPosition.Above:\n                        if (go.transform.parent == null)\n                        {\n                            var subSceneInfo = SubSceneGUI.GetSubSceneInfo(go.scene);\n                            if (subSceneInfo.isValid)\n                                return subSceneInfo.transform;\n                        }\n                        return go.transform.parent;\n                    default:\n                        throw new InvalidOperationException(\"Unhandled enum \" + dropPosition);\n                }\n            }\n            else\n            {\n                // Find transform parent from Scene\n                var scene = EditorSceneManager.GetSceneByHandle(gameObjectOrSceneInstanceID);\n                var subSceneInfo = SubSceneGUI.GetSubSceneInfo(scene);\n                if (subSceneInfo.isValid)\n                    return subSceneInfo.transform;\n                return null; // root scene has no transform parent\n            }\n        }\n\n        static bool IsDropTargetUserModifiable(GameObjectTreeViewItem targetItem, DropPosition dropPos)\n        {\n            if (targetItem.isSceneHeader && !targetItem.scene.isLoaded)\n                return false;\n\n            switch (dropPos)\n            {\n                case DropPosition.Upon:\n                    if (targetItem.objectPPTR != null)\n                        return IsUserModifiable(targetItem.objectPPTR);\n                    break;\n                case DropPosition.Below:\n                case DropPosition.Above:\n                    var targetParent = targetItem.parent as GameObjectTreeViewItem;\n                    if (targetParent != null && targetParent.objectPPTR != null)\n                        return IsUserModifiable(targetParent.objectPPTR);\n                    break;\n                default:\n                    throw new ArgumentOutOfRangeException(nameof(dropPos), dropPos, null);\n            }\n\n            return true;\n        }\n\n        static bool IsUserModifiable(Object obj)\n        {\n            return (obj.hideFlags & HideFlags.NotEditable) == 0;\n        }\n\n        public override void DragCleanup(bool revertExpanded)\n        {\n            DragAndDrop.SetGenericData(kSceneHeaderDragString, null);\n\n            base.DragCleanup(revertExpanded);\n        }\n\n        private List<Scene> GetDraggedScenes(List<int> draggedItemIDs)\n        {\n            List<Scene> scenes = new List<Scene>();\n            foreach (int id in draggedItemIDs)\n            {\n                Scene scene = EditorSceneManager.GetSceneByHandle(id);\n                if (!SceneHierarchy.IsSceneHeaderInHierarchyWindow(scene))\n                    return null;\n                scenes.Add(scene);\n            }\n\n            return scenes;\n        }\n\n        private DragAndDropVisualMode DoDragScenes(GameObjectTreeViewItem parentItem, GameObjectTreeViewItem targetItem, bool perform, DropPosition dropPos)\n        {\n            // We allow dragging SceneAssets on any game object in the Hierarchy to make it easy to drag in a Scene from\n            // the project browser. If dragging on a game object (not a sceneheader) we place the dropped scene\n            // below the game object's scene\n\n            // Case: 1\n            List<Scene> scenes = DragAndDrop.GetGenericData(kSceneHeaderDragString) as List<Scene>;\n            bool reorderExistingScenes = (scenes != null);\n\n            // Case: 2\n            bool insertNewScenes = false;\n            if (!reorderExistingScenes && DragAndDrop.objectReferences.Length > 0)\n            {\n                int sceneAssetCount = 0;\n                foreach (var dragged in DragAndDrop.objectReferences)\n                {\n                    if (dragged is SceneAsset)\n                        sceneAssetCount++;\n                }\n                insertNewScenes = (sceneAssetCount == DragAndDrop.objectReferences.Length);\n            }\n\n            // Early out if not case 1 or 2\n            if (!reorderExistingScenes && !insertNewScenes)\n                return DragAndDropVisualMode.None;\n\n            if (perform)\n            {\n                List<Scene> scenesToBeMoved = null;\n                if (insertNewScenes)\n                {\n                    List<Scene> insertedScenes = new List<Scene>();\n                    foreach (var sceneAsset in DragAndDrop.objectReferences)\n                    {\n                        string scenePath = AssetDatabase.GetAssetPath(sceneAsset);\n                        Scene scene = SceneManager.GetSceneByPath(scenePath);\n                        if (SceneHierarchy.IsSceneHeaderInHierarchyWindow(scene))\n                            m_TreeView.Frame(scene.handle, true, true);\n                        else\n                        {\n                            bool unloaded = Event.current.alt;\n                            if (unloaded)\n                                scene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.AdditiveWithoutLoading);\n                            else\n                                scene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Additive);\n\n                            if (SceneHierarchy.IsSceneHeaderInHierarchyWindow(scene))\n                                insertedScenes.Add(scene);\n                        }\n                    }\n                    if (targetItem != null)\n                        scenesToBeMoved = insertedScenes;\n\n                    // Select added scenes and frame last scene\n                    if (insertedScenes.Count > 0)\n                    {\n                        Selection.instanceIDs = insertedScenes.Select(x => x.handle).ToArray();\n                        m_TreeView.Frame(insertedScenes.Last().handle, true, false);\n                    }\n                }\n                else // reorderExistingScenes\n                    scenesToBeMoved = scenes;\n\n                if (scenesToBeMoved != null)\n                {\n                    if (targetItem != null)\n                    {\n                        Scene dstScene = targetItem.scene;\n                        if (SceneHierarchy.IsSceneHeaderInHierarchyWindow(dstScene))\n                        {\n                            if (!targetItem.isSceneHeader || dropPos == DropPosition.Upon)\n                                dropPos = DropPosition.Below;\n\n                            if (dropPos == DropPosition.Above)\n                            {\n                                for (int i = 0; i < scenesToBeMoved.Count; i++)\n                                    EditorSceneManager.MoveSceneBefore(scenesToBeMoved[i], dstScene);\n                            }\n                            else if (dropPos == DropPosition.Below)\n                            {\n                                for (int i = scenesToBeMoved.Count - 1; i >= 0; i--)\n                                    EditorSceneManager.MoveSceneAfter(scenesToBeMoved[i], dstScene);\n                            }\n                        }\n                    }\n                    else\n                    {\n                        Scene dstScene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1);\n                        for (int i = scenesToBeMoved.Count - 1; i >= 0; i--)\n                            EditorSceneManager.MoveSceneAfter(scenesToBeMoved[i], dstScene);\n                    }\n                }\n            }\n\n            return DragAndDropVisualMode.Move;\n        }\n    }\n} // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/AssetsTreeViewDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.ProjectWindowCallback;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing UnityEditor.Experimental;\nusing AssetReference = UnityEditorInternal.InternalEditorUtility.AssetReference;\n\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing LazyTreeViewDataSource = UnityEditor.IMGUI.Controls.LazyTreeViewDataSource<int>;\nusing TreeViewUtility = UnityEditor.IMGUI.Controls.TreeViewUtility<int>;\nusing TreeViewSelectState = UnityEditor.IMGUI.Controls.TreeViewSelectState<int>;\n\n\nnamespace UnityEditor\n{\n    // AssetsTreeViewDataSource only fetches current visible items of the asset database tree, because we derive from LazyTreeViewDataSource\n    // Note: every time a Item's expanded state changes FetchData is called\n\n    internal class AssetsTreeViewDataSource : LazyTreeViewDataSource\n    {\n        private class RootItem\n        {\n            public int instanceID { get; }\n            public string displayName { get; }\n            public string path { get; }\n            public bool skipValidation { get; }\n\n            public RootItem(int instanceID, string displayName, string path, bool skipValidation = false)\n            {\n                this.instanceID = instanceID;\n                this.displayName = displayName;\n                this.path = path;\n                this.skipValidation = skipValidation;\n            }\n        }\n\n        public bool skipHiddenPackages { get; set; }\n        public bool foldersOnly { get; set; }\n        public bool foldersFirst { get; set; }\n\n        private Dictionary<string, TreeViewItem> m_RootsTreeViewItem;\n        private bool m_ExpandAtFirstTime;\n        private List<RootItem> m_Roots;\n        private int m_rootInstanceID;\n\n        const HierarchyType k_HierarchyType = HierarchyType.Assets;\n\n        public AssetsTreeViewDataSource(TreeViewController treeView, bool skipHidden = true)\n            : base(treeView)\n        {\n            m_ExpandAtFirstTime = true;\n            showRootItem = false;\n            rootIsCollapsable = false;\n            skipHiddenPackages = skipHidden;\n        }\n\n        public AssetsTreeViewDataSource(TreeViewController treeView, int rootInstanceID)\n            : this(treeView)\n        {\n            m_rootInstanceID = rootInstanceID;\n        }\n\n        public override List<int> GetNewSelection(TreeViewItem clickedItem, TreeViewSelectState selectState)\n        {\n            var assetTreeClickedItem = clickedItem as IAssetTreeViewItem;\n            var clickedEntry = new AssetReference() { instanceID = clickedItem.id };\n            if (clickedItem.id == 0 && assetTreeClickedItem != null)\n                clickedEntry.guid = assetTreeClickedItem.Guid;\n\n            // Get ids from items\n            var visibleRows = GetRows();\n            var allIDs = new List<int>(visibleRows.Count);\n            var allGuids = new List<string>(visibleRows.Count);\n\n            for (int i = 0; i < visibleRows.Count; ++i)\n            {\n                int instanceID = visibleRows[i].id;\n                string guid = null;\n                if (instanceID == 0)\n                {\n                    var assetTreeViewItem = visibleRows[i] as IAssetTreeViewItem;\n                    if (assetTreeViewItem != null)\n                        guid = assetTreeViewItem.Guid;\n                }\n\n                allGuids.Add(guid);\n                allIDs.Add(instanceID);\n            }\n\n            List<int> selectedIDs = selectState.selectedIDs;\n            int lastClickedID = selectState.lastClickedID;\n            bool allowMultiselection = CanBeMultiSelected(clickedItem);\n\n            var result = InternalEditorUtility.GetNewSelection(ref clickedEntry, allIDs, allGuids, selectedIDs, lastClickedID, selectState.keepMultiSelection, selectState.useShiftAsActionKey, allowMultiselection);\n\n            clickedItem.id = clickedEntry.instanceID;\n\n            for (int i = 0; i < allIDs.Count; ++i)\n            {\n                if (allGuids[i] != null && allIDs[i] != 0)\n                    visibleRows[i].id = allIDs[i];\n            }\n\n            return result;\n        }\n\n        static string CreateDisplayName(int instanceID)\n        {\n            return Path.GetFileNameWithoutExtension(AssetDatabase.GetAssetPath(instanceID));\n        }\n\n        private void BuildRoots()\n        {\n            m_Roots = new List<RootItem>();\n\n            if (m_rootInstanceID != 0)\n            {\n                m_Roots.Add(new RootItem(m_rootInstanceID, null, null, true));\n                return;\n            }\n\n            var packagesMountPoint = PackageManager.Folders.GetPackagesPath();\n\n            var assetsFolderInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(\"Assets\");\n            m_Roots.Add(new RootItem(assetsFolderInstanceID, null, null, true));\n\n            var packages = PackageManagerUtilityInternal.GetAllVisiblePackages(skipHiddenPackages);\n            m_Roots.Add(new RootItem(ProjectBrowser.kPackagesFolderInstanceId, packagesMountPoint, packagesMountPoint, true));\n            foreach (var package in packages)\n            {\n                var displayName = !string.IsNullOrEmpty(package.displayName) ? package.displayName : package.name;\n                var packageFolderInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(package.assetPath);\n                if (packageFolderInstanceID == 0)\n                    continue;\n\n                m_Roots.Add(new RootItem(packageFolderInstanceID, displayName, package.assetPath));\n            }\n        }\n\n        public override void ReloadData()\n        {\n            BuildRoots();\n            base.ReloadData();\n        }\n\n        public override void FetchData()\n        {\n            // Create root Item\n            int depth = 0;\n            var multiRoot = (m_Roots.Count > 1);\n            if (multiRoot)\n            {\n                m_RootItem = new TreeViewItem(-1, depth, null, \"Invisible Root Item\");\n                SetExpanded(m_RootItem, true);\n            }\n            else\n            {\n                var rootInstanceID = m_Roots[0].instanceID;\n                var displayName = m_Roots[0].displayName ?? CreateDisplayName(rootInstanceID);\n                m_RootItem = new TreeViewItem(rootInstanceID, depth, null, displayName);\n                SetExpanded(m_RootItem, true);\n            }\n\n            m_Rows = new List<TreeViewItem>(m_Roots.Count * 256);\n            Texture2D folderIcon = EditorGUIUtility.FindTexture(EditorResources.folderIconName);\n            var assetsInstanceIDs = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(\"Assets\");\n            var projectPath = Path.GetFileName(Directory.GetCurrentDirectory());\n\n            // Fetch root Items\n            m_RootsTreeViewItem = new Dictionary<string, TreeViewItem>(m_Roots.Count);\n            foreach (var root in m_Roots)\n            {\n                var rootInstanceID = root.instanceID;\n                var displayName = root.displayName ?? CreateDisplayName(rootInstanceID);\n                var rootPath = root.path ?? AssetDatabase.GetAssetPath(rootInstanceID);\n                var rootGuid = AssetDatabase.AssetPathToGUID(rootPath);\n\n                var property = new HierarchyProperty(rootPath);\n                if (!root.skipValidation && !property.Find(rootInstanceID, null))\n                {\n                    if (rootInstanceID == 0)\n                        Debug.LogError(\"Root Asset with path \" + rootPath + \" not valid!!\");\n                    continue;\n                }\n\n                var minDepth = property.depth;\n                var subDepth = multiRoot ? 0 : -1;\n                TreeViewItem rootItem;\n                if (multiRoot)\n                {\n                    var parentItem = m_RootItem;\n                    var rootDepth = minDepth;\n                    rootDepth++;\n\n                    // Find parent treeView item\n                    var parentPath = Path.GetDirectoryName(rootPath);\n                    // Mono Upgrade note: Directory.GetParent now attempts to resolve the full path as part of the call. This causes Unity's\n                    // path remapping to be triggered which causes Package paths to get remapped to PackageCache.\n                    if (String.IsNullOrEmpty(parentPath))\n                        parentPath = Directory.GetParent(rootPath).Name;\n                    if (parentPath != projectPath)\n                    {\n                        if (!m_RootsTreeViewItem.TryGetValue(parentPath, out parentItem))\n                        {\n                            Debug.LogError(\"Cannot find parent for \" + rootInstanceID);\n                            continue;\n                        }\n\n                        rootDepth++;\n                        subDepth++;\n                    }\n\n                    // Create root item TreeView item\n                    if (subDepth > 0)\n                        rootItem = new FolderTreeItem(rootGuid, !property.hasChildren, rootInstanceID, rootDepth, parentItem, displayName);\n                    else\n                        rootItem = new RootTreeItem(rootInstanceID, rootDepth, parentItem, displayName);\n                    rootItem.icon = folderIcon;\n                    parentItem.AddChild(rootItem);\n                }\n                else\n                {\n                    rootItem = m_RootItem;\n                }\n\n                m_RootsTreeViewItem[rootPath] = rootItem;\n\n                if (!skipHiddenPackages)\n                    property.SetSearchFilter(new SearchFilter {skipHidden = false});\n\n                var expandIDs = GetExpandedIDs();\n                var rows = new List<TreeViewItem>();\n                bool shouldExpandIt = m_ExpandAtFirstTime && (rootItem.id == assetsInstanceIDs);\n                if (IsExpanded(rootItem.id) && (rootItem == m_RootItem || IsExpanded(rootItem.parent.id)) || shouldExpandIt)\n                {\n                    m_ExpandAtFirstTime = false;\n\n                    while (property.NextWithDepthCheck(expandIDs, minDepth))\n                    {\n                        if (!foldersOnly || property.isFolder)\n                        {\n                            depth = property.depth - minDepth;\n                            TreeViewItem item;\n                            if (property.isFolder)\n                                item = new FolderTreeItem(property.guid, !property.hasChildren, property.instanceID, depth + subDepth, null, property.name);\n                            else\n                                item = new NonFolderTreeItem(property.guid, property.GetInstanceIDIfImported(), depth + subDepth, null, property.name);\n\n                            item.icon = property.icon;\n\n                            if (property.hasChildren)\n                            {\n                                item.AddChild(null); // add a dummy child in children list to ensure we show the collapse arrow (because we do not fetch data for collapsed items)\n                            }\n                            rows.Add(item);\n                        }\n                    }\n\n                    // Setup reference between child and parent items\n                    TreeViewUtility.SetChildParentReferences(rows, rootItem);\n                }\n                else\n                {\n                    rootItem.AddChild(null);\n                }\n\n                if (shouldExpandIt && !IsExpanded(rootItem))\n                    SetExpanded(rootItem, true);\n\n                if (multiRoot && IsExpanded(rootItem.parent.id))\n                {\n                    m_Rows.Add(rootItem);\n                }\n\n                ((List<TreeViewItem>)m_Rows).AddRange(rows);\n            }\n\n            if (foldersFirst)\n            {\n                FoldersFirstRecursive(m_RootItem);\n                m_Rows.Clear();\n                GetVisibleItemsRecursive(m_RootItem, m_Rows);\n            }\n\n            // Must be called before InitSelection (it calls GetVisibleItems)\n            m_NeedRefreshRows = false;\n\n            // We want to reset selection on copy/duplication/delete\n            bool frameLastSelected = false; // use false because we might just be expanding/collapsing a Item (which would prevent collapsing a Item with a selected child)\n            m_TreeView.SetSelection(Selection.instanceIDs, frameLastSelected);\n        }\n\n        static void FoldersFirstRecursive(TreeViewItem item)\n        {\n            if (!item.hasChildren)\n                return;\n\n            // Parent child relation is untouched, we simply move child folders to the beginning of\n            // the children array while keeping folders and files sorted.\n            TreeViewItem[] children = item.children.ToArray();\n            for (int nonFolderPos = 0; nonFolderPos < item.children.Count; ++nonFolderPos)\n            {\n                if (children[nonFolderPos] == null)\n                    continue;\n\n                if (children[nonFolderPos] is NonFolderTreeItem)\n                {\n                    for (int folderPos = nonFolderPos + 1; folderPos < children.Length; ++folderPos)\n                    {\n                        if (!(children[folderPos] is FolderTreeItem))\n                            continue;\n\n                        TreeViewItem folderItem = children[folderPos];\n                        int length = folderPos - nonFolderPos;\n                        System.Array.Copy(children, nonFolderPos, children, nonFolderPos + 1, length);\n                        children[nonFolderPos] = folderItem;\n                        break;\n                    }\n                }\n\n                FoldersFirstRecursive(children[nonFolderPos]);\n            }\n            item.children = new List<TreeViewItem>(children);\n        }\n\n        protected override void GetParentsAbove(int id, HashSet<int> parentsAbove)\n        {\n            ProjectWindowUtil.GetAncestors(id, parentsAbove);\n        }\n\n        // Should return the items that have children from id and below\n        protected override void GetParentsBelow(int id, HashSet<int> parentsBelow)\n        {\n            // Add all children expanded ids to hashset\n            if (m_Roots.Count > 1)\n            {\n                var assetsInstanceIDs = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(\"Assets\");\n                if (id != assetsInstanceIDs)\n                {\n                    // Search in created first-level root items\n                    var item = m_RootsTreeViewItem.Values.FirstOrDefault(tvi => tvi.id == id && tvi.depth == 0);\n                    if (item != null)\n                    {\n                        parentsBelow.Add(id);\n                        foreach (var child in item.children)\n                        {\n                            if (child != null && child.hasChildren)\n                                GetParentsBelow(child.id, parentsBelow);\n                        }\n                        return;\n                    }\n                }\n            }\n\n            // Search in all roots\n            foreach (var root in m_Roots)\n            {\n                var rootPath = root.path ?? AssetDatabase.GetAssetPath(root.instanceID);\n                IHierarchyProperty search = new HierarchyProperty(rootPath);\n                if (search.Find(id, null))\n                {\n                    parentsBelow.Add(id);\n\n                    int depth = search.depth;\n                    while (search.Next(null) && search.depth > depth)\n                    {\n                        if (search.hasChildren)\n                            parentsBelow.Add(search.instanceID);\n                    }\n                    break;\n                }\n            }\n        }\n\n        override public void OnExpandedStateChanged()\n        {\n            if (k_HierarchyType == HierarchyType.Assets)\n                InternalEditorUtility.expandedProjectWindowItems = expandedIDs.ToArray(); // Persist expanded state for ProjectBrowsers\n\n            base.OnExpandedStateChanged();\n        }\n\n        override public bool IsRenamingItemAllowed(TreeViewItem item)\n        {\n            // Only main representations can be renamed (currently)\n            // Root items cannot be renamed\n            if (AssetDatabase.IsSubAsset(item.id) || (item.parent == null))\n                return false;\n\n            // Root items cannot be renamed\n            if (item is RootTreeItem)\n                return false;\n\n            return InternalEditorUtility.CanRenameAsset(item.id);\n        }\n\n        protected CreateAssetUtility GetCreateAssetUtility()\n        {\n            return ((TreeViewStateWithAssetUtility)m_TreeView.state).createAssetUtility;\n        }\n\n        public int GetInsertAfterItemIDForNewItem(string newName, TreeViewItem parentItem, bool isCreatingNewFolder, bool foldersFirst)\n        {\n            if (!parentItem.hasChildren)\n                return parentItem.id;\n\n            // Find pos under parent\n            int insertAfterID = parentItem.id;\n            for (int idx = 0; idx < parentItem.children.Count; ++idx)\n            {\n                int instanceID = parentItem.children[idx].id;\n                bool isFolder = parentItem.children[idx] is FolderTreeItem;\n\n                // Skip folders when inserting a normal asset if folders is sorted first\n                if (foldersFirst && isFolder && !isCreatingNewFolder)\n                {\n                    insertAfterID = instanceID;\n                    continue;\n                }\n\n                // When inserting a folder in folders first list break when we reach normal assets\n                if (foldersFirst && !isFolder && isCreatingNewFolder)\n                {\n                    break;\n                }\n\n                // Use same name compare as when we sort in the backend: See AssetDatabase.cpp: SortChildren\n                string propertyPath = AssetDatabase.GetAssetPath(instanceID);\n                if (EditorUtility.NaturalCompare(Path.GetFileNameWithoutExtension(propertyPath), newName) > 0)\n                {\n                    break;\n                }\n\n                insertAfterID = instanceID;\n            }\n            return insertAfterID;\n        }\n\n        override public void InsertFakeItem(int id, int parentID, string name, Texture2D icon)\n        {\n            bool isCreatingNewFolder = GetCreateAssetUtility().endAction is DoCreateFolder;\n\n            TreeViewItem checkItem = FindItem(id);\n            if (checkItem != null)\n            {\n                Debug.LogError(\"Cannot insert fake Item because id is not unique \" + id + \" Item already there: \" + checkItem.displayName);\n                return;\n            }\n\n            if (FindItem(parentID) != null)\n            {\n                // Ensure parent Item's children is visible\n                SetExpanded(parentID, true);\n\n                var visibleRows = GetRows();\n\n                TreeViewItem parentItem;\n                int parentIndex = TreeViewController.GetIndexOfID(visibleRows, parentID);\n                if (parentIndex >= 0)\n                    parentItem = visibleRows[parentIndex];\n                else\n                    parentItem = m_RootItem; // Fallback to root Item as parent\n\n                // Create fake folder for insertion\n                int indentLevel = parentItem.depth + (parentItem == m_RootItem ? 0 : 1);\n                m_FakeItem = new TreeViewItem(id, indentLevel, parentItem, name);\n                m_FakeItem.icon = icon;\n\n                // Find pos under parent\n                int insertAfterID = GetInsertAfterItemIDForNewItem(name, parentItem, isCreatingNewFolder, foldersFirst);\n\n                // Find pos in expanded rows and insert\n                int index = TreeViewController.GetIndexOfID(visibleRows, insertAfterID);\n                if (index >= 0)\n                {\n                    // Ensure to bypass all children of 'insertAfterID'\n                    while (++index < visibleRows.Count)\n                    {\n                        if (visibleRows[index].depth <= indentLevel)\n                            break;\n                    }\n\n                    if (index < visibleRows.Count)\n                        visibleRows.Insert(index, m_FakeItem);\n                    else\n                        visibleRows.Add(m_FakeItem);\n                }\n                else\n                {\n                    // not visible parent: insert as first\n                    if (visibleRows.Count > 0)\n                        visibleRows.Insert(0, m_FakeItem);\n                    else\n                        visibleRows.Add(m_FakeItem);\n                }\n\n                m_NeedRefreshRows = false;\n\n                m_TreeView.Frame(m_FakeItem.id, true, false);\n                m_TreeView.Repaint();\n            }\n            else\n            {\n                Debug.LogError(\"No parent Item found\");\n            }\n        }\n\n        internal class SemiNumericDisplayNameListComparer : IComparer<TreeViewItem>\n        {\n            public int Compare(TreeViewItem x, TreeViewItem y)\n            {\n                if (x == y) return 0;\n                if (x == null) return -1;\n                if (y == null) return 1;\n                return EditorUtility.NaturalCompare(x.displayName, y.displayName);\n            }\n        }\n\n        // Classes used for type checking\n        internal interface IAssetTreeViewItem\n        {\n            string Guid { get; }\n        }\n\n        internal abstract class FolderTreeItemBase : TreeViewItem\n        {\n            public virtual bool IsEmpty\n            {\n                get { return false; }\n            }\n            protected FolderTreeItemBase(int id, int depth, TreeViewItem parent, string displayName)\n                : base(id, depth, parent, displayName)\n            {\n            }\n        }\n\n        internal class RootTreeItem : FolderTreeItemBase\n        {\n            public RootTreeItem(int id, int depth, TreeViewItem parent, string displayName)\n                : base(id, depth, parent, displayName)\n            {\n            }\n        }\n        internal class PackageTreeItem : FolderTreeItemBase\n        {\n            public PackageTreeItem(int id, int depth, TreeViewItem parent, string displayName)\n                : base(id, depth, parent, displayName)\n            {\n            }\n        }\n\n        internal class FolderTreeItem : FolderTreeItemBase, IAssetTreeViewItem\n        {\n            public string Guid { get; }\n            public override bool IsEmpty { get; }\n\n            public FolderTreeItem(string guid, bool isEmpty, int id, int depth, TreeViewItem parent, string displayName)\n                : base(id, depth, parent, displayName)\n            {\n                Guid = guid;\n                IsEmpty = isEmpty;\n            }\n        }\n\n        class NonFolderTreeItem : TreeViewItem, IAssetTreeViewItem\n        {\n            public string Guid { get; }\n            public NonFolderTreeItem(string guid, int id, int depth, TreeViewItem parent, string displayName)\n                : base(id, depth, parent, displayName)\n            {\n                Guid = guid;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/AssetsTreeViewGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.ProjectWindowCallback;\nusing UnityEngine;\nusing UnityEditorInternal.VersionControl;\nusing UnityEditor.VersionControl;\nusing System.Collections.Generic;\nusing UnityEditor.Experimental;\nusing UnityEngine.Assertions;\nusing static UnityEditor.AssetsTreeViewDataSource;\nusing static UnityEditorInternal.InternalEditorUtility;\n\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewGUI = UnityEditor.IMGUI.Controls.TreeViewGUI<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\n\nnamespace UnityEditor\n{\n    internal class AssetsTreeViewGUI : TreeViewGUI\n    {\n        static bool s_VCEnabled;\n        const float k_IconOverlayPadding = 7f;\n\n        internal static ScalableGUIContent s_OpenFolderIcon = new ScalableGUIContent(null, null, EditorResources.openedFolderIconName);\n        internal static ScalableGUIContent s_EmptyFolderIcon = new ScalableGUIContent(null, null, EditorResources.emptyFolderIconName);\n\n        internal static Texture2D openFolderTexture\n        {\n            get\n            {\n                GUIContent folderContent = s_OpenFolderIcon;\n                return folderContent.image as Texture2D;\n            }\n        }\n\n        internal static Texture2D emptyFolderTexture\n        {\n            get\n            {\n                GUIContent folderContent = s_EmptyFolderIcon;\n                return folderContent.image as Texture2D;\n            }\n        }\n\n        internal delegate void OnAssetIconDrawDelegate(Rect iconRect, string guid);\n        internal static event OnAssetIconDrawDelegate postAssetIconDrawCallback = null;\n\n        internal delegate bool OnAssetLabelDrawDelegate(Rect drawRect, string guid);\n        internal static event OnAssetLabelDrawDelegate postAssetLabelDrawCallback = null;\n\n        private static IDictionary<int, string> s_GUIDCache = null;\n        private readonly Action m_TreeViewRepaintAction;\n\n        public AssetsTreeViewGUI(TreeViewController treeView)\n            : base(treeView)\n        {\n            iconOverlayGUI += OnIconOverlayGUI;\n            labelOverlayGUI += OnLabelOverlayGUI;\n            k_TopRowMargin = 4f;\n            m_TreeViewRepaintAction = () => m_TreeView.Repaint();\n        }\n\n        // ---------------------\n        // OnGUI section\n\n        override public void BeginRowGUI()\n        {\n            s_VCEnabled = VersionControlUtils.isVersionControlConnected;\n            iconLeftPadding = iconRightPadding = s_VCEnabled ? k_IconOverlayPadding : 0f;\n            base.BeginRowGUI();\n        }\n\n        //-------------------\n        // Create asset and Rename asset section\n\n        protected CreateAssetUtility GetCreateAssetUtility()\n        {\n            return ((TreeViewStateWithAssetUtility)m_TreeView.state).createAssetUtility;\n        }\n\n        virtual protected bool IsCreatingNewAsset(int instanceID)\n        {\n            return GetCreateAssetUtility().IsCreatingNewAsset() && IsRenaming(instanceID);\n        }\n\n        override protected void ClearRenameAndNewItemState()\n        {\n            GetCreateAssetUtility().Clear();\n            base.ClearRenameAndNewItemState();\n        }\n\n        override protected void RenameEnded()\n        {\n            string name = string.IsNullOrEmpty(GetRenameOverlay().name) ? GetRenameOverlay().originalName : GetRenameOverlay().name;\n            int instanceID = GetRenameOverlay().userData;\n            bool isCreating = GetCreateAssetUtility().IsCreatingNewAsset();\n            bool userAccepted = GetRenameOverlay().userAcceptedRename;\n\n            if (userAccepted)\n            {\n                if (isCreating)\n                {\n                    // Create a new asset\n                    GetCreateAssetUtility().EndNewAssetCreation(name);\n                }\n                else\n                {\n                    // Rename an existing asset\n                    ObjectNames.SetNameSmartWithInstanceID(instanceID, name);\n                }\n            }\n            else if (isCreating)\n                GetCreateAssetUtility().EndNewAssetCreationCanceled(name);\n        }\n\n        override protected void SyncFakeItem()\n        {\n            if (!m_TreeView.data.HasFakeItem() && GetCreateAssetUtility().IsCreatingNewAsset())\n            {\n                int parentInstanceID = AssetDatabase.GetMainAssetInstanceID(GetCreateAssetUtility().folder);\n                m_TreeView.data.InsertFakeItem(GetCreateAssetUtility().instanceID, parentInstanceID, GetCreateAssetUtility().originalName, GetCreateAssetUtility().icon);\n            }\n\n            if (m_TreeView.data.HasFakeItem() && !GetCreateAssetUtility().IsCreatingNewAsset())\n            {\n                m_TreeView.data.RemoveFakeItem();\n            }\n        }\n\n        // Not part of interface because it is very specific to creating assets\n        virtual public void BeginCreateNewAsset(int instanceID, EndNameEditAction endAction, string pathName, Texture2D icon, string resourceFile, bool selectAssetBeingCreated = true)\n        {\n            ClearRenameAndNewItemState();\n\n            if (GetCreateAssetUtility().BeginNewAssetCreation(instanceID, endAction, pathName, icon, resourceFile, selectAssetBeingCreated))\n            {\n                SyncFakeItem();\n\n                // Start nameing the asset\n                bool renameStarted = GetRenameOverlay().BeginRename(GetCreateAssetUtility().originalName, instanceID, 0f);\n                if (!renameStarted)\n                    Debug.LogError(\"Rename not started (when creating new asset)\");\n            }\n        }\n\n        // Handles fetching rename icon or cached asset database icon\n        protected override Texture GetIconForItem(TreeViewItem item)\n        {\n            if (item == null)\n                return null;\n\n            Texture icon = null;\n            if (IsCreatingNewAsset(item.id))\n                icon = GetCreateAssetUtility().icon;\n\n            if (icon == null)\n                icon = item.icon;\n\n            if (icon == null && item.id != 0)\n            {\n                string path = AssetDatabase.GetAssetPath(item.id);\n                icon = AssetDatabase.GetCachedIcon(path);\n            }\n\n            var folderItem = item as AssetsTreeViewDataSource.FolderTreeItemBase;\n            if (folderItem != null)\n            {\n                if (folderItem.IsEmpty)\n                    icon = emptyFolderTexture;\n                else if (m_TreeView.data.IsExpanded(folderItem))\n                    icon = openFolderTexture;\n            }\n\n            return icon;\n        }\n\n        protected override void DoItemGUI(Rect rect, int row, TreeViewItem item, bool selected, bool focused, bool useBoldFont)\n        {\n            if (item is AssetsTreeViewDataSource.RootTreeItem)\n            {\n                useBoldFont = true;\n            }\n\n            var color = ProjectBrowser.GetAssetItemColor(item.id);\n\n            using (new GUI.ColorScope(color))\n                base.DoItemGUI(rect, row, item, selected, focused, useBoldFont);\n        }\n\n        private void OnIconOverlayGUI(TreeViewItem item, Rect overlayRect)\n        {\n            if (!AssetReference.IsAssetImported(item.id))\n            {\n                var assetTreeItem = item as IAssetTreeViewItem;\n                if (assetTreeItem == null)\n                    return;\n\n                OnIconOverlayGUI_ForNonImportAsset(assetTreeItem.Guid, overlayRect, false, m_TreeViewRepaintAction);\n            }\n            else\n                OnIconOverlayGUI(item.id, overlayRect, false, m_TreeViewRepaintAction);\n        }\n\n        internal static void OnIconOverlayGUI_ForNonImportAsset(string guid, Rect overlayRect, bool addPadding, Action repaintAction = null)\n        {\n            if (addPadding)\n            {\n                overlayRect.x -= k_IconOverlayPadding;\n                overlayRect.width += k_IconOverlayPadding * 2;\n            }\n\n            ProjectHooks.OnProjectWindowItem(guid, overlayRect, repaintAction);\n        }\n\n        internal static void OnIconOverlayGUI(int instanceID, Rect overlayRect, bool addPadding, Action repaintAction = null)\n        {\n            if (addPadding)\n            {\n                overlayRect.x -= k_IconOverlayPadding;\n                overlayRect.width += k_IconOverlayPadding * 2;\n            }\n\n            if (postAssetIconDrawCallback != null && AssetDatabase.IsMainAsset(instanceID))\n            {\n                string guid = GetGUIDForInstanceID(instanceID);\n                postAssetIconDrawCallback(overlayRect, guid);\n            }\n\n            // Draw vcs icons\n            if (s_VCEnabled && AssetDatabase.IsMainAsset(instanceID))\n            {\n                string guid = GetGUIDForInstanceID(instanceID);\n                ProjectHooks.OnProjectWindowItem(guid, overlayRect, repaintAction);\n            }\n        }\n\n        private void OnLabelOverlayGUI(TreeViewItem item, Rect labelRect)\n        {\n            if (postAssetLabelDrawCallback != null && AssetDatabase.IsMainAsset(item.id))\n            {\n                string guid = GetGUIDForInstanceID(item.id);\n                postAssetLabelDrawCallback(labelRect, guid);\n            }\n        }\n\n        // Returns a previously stored GUID for the given ID,\n        // else retrieves it from the asset database and stores it.\n        private static string GetGUIDForInstanceID(int instanceID)\n        {\n            if (s_GUIDCache == null)\n            {\n                s_GUIDCache = new Dictionary<int, string>();\n            }\n\n            string GUID = null;\n            if (!s_GUIDCache.TryGetValue(instanceID, out GUID))\n            {\n                string path = AssetDatabase.GetAssetPath(instanceID);\n                GUID = AssetDatabase.AssetPathToGUID(path);\n                Assert.IsTrue(!string.IsNullOrEmpty(GUID));\n                s_GUIDCache.Add(instanceID, GUID);\n            }\n\n            return GUID;\n        }\n    }\n\n\n    [System.Serializable]\n    internal class TreeViewStateWithAssetUtility : TreeViewState\n    {\n        [SerializeField]\n        CreateAssetUtility m_CreateAssetUtility = new CreateAssetUtility();\n\n        internal CreateAssetUtility createAssetUtility { get { return m_CreateAssetUtility; } set { m_CreateAssetUtility = value; } }\n\n        internal override void OnAwake()\n        {\n            base.OnAwake();\n\n            // Clear state that should not survive closing/starting Unity (If TreeViewState is in EditorWindow that are serialized in a layout file)\n            m_CreateAssetUtility.Clear();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/GameObjectTreeViewDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing UnityEditor.SceneManagement;\nusing UnityEditorInternal;\nusing System.Linq;\nusing System.Collections.Generic;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine.Assertions;\nusing UnityEngine.Profiling;\nusing Object = UnityEngine.Object;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing LazyTreeViewDataSource = UnityEditor.IMGUI.Controls.LazyTreeViewDataSource<int>;\nusing TreeViewUtility = UnityEditor.IMGUI.Controls.TreeViewUtility<int>;\nusing TreeViewItemAlphaNumericSort = UnityEditor.IMGUI.Controls.TreeViewItemAlphaNumericSort<int>;\n\nnamespace UnityEditor\n{\n    // GameObjectTreeViewDataSource only fetches current visible items of the scene tree, because we derive from LazyTreeViewDataSource\n    // Note: every time a Item's expanded state changes FetchData is called\n\n    internal class GameObjectTreeViewDataSource : LazyTreeViewDataSource\n    {\n        const double k_LongFetchTime = 0.05; // How much time is considered to be a long fetch\n        const double k_FetchDelta = 0.1; // How much time between long fetches is acceptable.\n        const int k_MaxDelayedFetch = 5; // How many consecutive fetches can be delayed.\n        const HierarchyType k_HierarchyType = HierarchyType.GameObjects;\n        const int k_DefaultStartCapacity = 1000;\n\n        int m_RootInstanceID;\n        string m_SearchString = \"\";\n        readonly SearchService.SceneSearchSessionHandler m_SearchSessionHandler = new SearchService.SceneSearchSessionHandler();\n        SearchableEditorWindow.SearchModeHierarchyWindow m_SearchMode = 0; // 0 = All\n        double m_LastFetchTime = 0.0;\n        int m_DelayedFetches = 0;\n        bool m_NeedsChildParentReferenceSetup;\n        bool m_RowsPartiallyInitialized;\n        int m_RowCount;\n        List<TreeViewItem> m_ListOfRows; // We need the generic List type in this class for Add/RemoveRange and Sorting (m_Rows is IList)\n        List<GameObjectTreeViewItem> m_StickySceneHeaderItems = new List<GameObjectTreeViewItem>();\n        internal event System.Action beforeReloading;\n        public HierarchySorting sortingState = new TransformSorting();\n\n        public List<GameObjectTreeViewItem> sceneHeaderItems { get { return m_StickySceneHeaderItems; } }\n        public string searchString\n        {\n            get\n            {\n                return m_SearchString;\n            }\n            set\n            {\n                if (string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(m_SearchString))\n                    ClearSearchFilter();\n\n                m_SearchString = value;\n            }\n        }\n        public SearchableEditorWindow.SearchModeHierarchyWindow searchMode { get { return m_SearchMode; } set { m_SearchMode = value; } }\n        public bool isFetchAIssue { get { return m_DelayedFetches >= k_MaxDelayedFetch; } }\n\n        public Scene[] scenes { get; set; }\n\n        public GameObjectTreeViewDataSource(TreeViewController treeView, int rootInstanceID, bool showRoot, bool rootItemIsCollapsable)\n            : base(treeView)\n        {\n            m_RootInstanceID = rootInstanceID;\n            showRootItem = showRoot;\n            rootIsCollapsable = rootItemIsCollapsable;\n        }\n\n        internal void SetupChildParentReferencesIfNeeded()\n        {\n            // Ensure all rows are initialized (not only the visible)\n            EnsureFullyInitialized();\n\n            // We delay the calling SetChildParentReferences until needed to ensure fast reloading of\n            // the game object hierarchy (in playmode this prevent hiccups for large scenes)\n            if (m_NeedsChildParentReferenceSetup)\n            {\n                m_NeedsChildParentReferenceSetup = false;\n                TreeViewUtility.SetChildParentReferences(GetRows(), m_RootItem);\n            }\n        }\n\n        public void EnsureFullyInitialized()\n        {\n            if (m_RowsPartiallyInitialized)\n            {\n                InitializeFull();\n                m_RowsPartiallyInitialized = false;\n            }\n        }\n\n        override public int rowCount\n        {\n            get\n            {\n                return m_RowCount;\n            }\n        }\n\n        public override void RevealItem(int itemID)\n        {\n            // Optimization: Only spend time on revealing item if it is part of the Hierarchy\n            if (IsValidHierarchyInstanceID(itemID))\n                base.RevealItem(itemID);\n        }\n\n        public override void RevealItems(int[] itemIDs)\n        {\n            // Optimization: Only spend time on revealing item if it is part of the Hierarchy\n            HashSet<int> validItemIDs = new HashSet<int>();\n            foreach (var itemID in itemIDs)\n            {\n                if (IsValidHierarchyInstanceID(itemID))\n                    validItemIDs.Add(itemID);\n            }\n\n            // Get existing expanded in hashset\n            HashSet<int> expandedSet = new HashSet<int>(expandedIDs);\n            int orgSize = expandedSet.Count;\n\n            IHierarchyProperty propertyIterator = CreateHierarchyProperty();\n            int[] ancestors = propertyIterator.FindAllAncestors(validItemIDs.ToArray());\n\n            // Add all parents above id\n            foreach (var itemID in ancestors)\n            {\n                expandedSet.Add(itemID);\n            }\n\n            if (orgSize != expandedSet.Count)\n            {\n                // Bulk set expanded ids (is sorted in SetExpandedIDs)\n                SetExpandedIDs(expandedSet.ToArray());\n\n                // Refresh immediately if any Item was expanded\n                if (m_NeedRefreshRows)\n                    FetchData();\n            }\n        }\n\n        override public bool IsRevealed(int id)\n        {\n            return GetRow(id) != -1;\n        }\n\n        private bool IsValidHierarchyInstanceID(int instanceID)\n        {\n            //Get is persistent without loading object\n            var obj = InternalEditorUtility.GetObjectFromInstanceID(instanceID);\n            if (obj != null ? EditorUtility.IsPersistent(obj) : AssetDatabase.Contains(instanceID))\n                return false;\n\n            if (SceneHierarchy.IsSceneHeaderInHierarchyWindow(EditorSceneManager.GetSceneByHandle(instanceID)))\n                return true;\n\n            if (InternalEditorUtility.GetTypeWithoutLoadingObject(instanceID) == typeof(GameObject))\n                return true;\n\n            return false;\n        }\n\n        HierarchyProperty FindHierarchyProperty(int instanceID)\n        {\n            // Optimization: Prevent search by early out if 'id' is not a game object (or scene handle)\n            if (!IsValidHierarchyInstanceID(instanceID))\n                return null;\n\n            HierarchyProperty property = CreateHierarchyProperty();\n            if (property.Find(instanceID, m_TreeView.state.expandedIDs.ToArray()))\n                return property;\n\n            return null;\n        }\n\n        override public int GetRow(int id)\n        {\n            bool isSearching = !string.IsNullOrEmpty(m_SearchString);\n            if (isSearching)\n                return base.GetRow(id);\n\n            // We read from the backend directly instead of using GetRows()\n            // because we might not yet have initialized tree view after creating a new\n            // game object. GetRows also needs full init which we want to prevent\n            HierarchyProperty property = FindHierarchyProperty(id);\n            if (property != null)\n                return property.row;\n\n            return -1;\n        }\n\n        override public TreeViewItem GetItem(int row)\n        {\n            return m_Rows[row];\n        }\n\n        public override IList<TreeViewItem> GetRows()\n        {\n            InitIfNeeded();\n            EnsureFullyInitialized();\n\n            return m_Rows;\n        }\n\n        override public TreeViewItem FindItem(int id)\n        {\n            // Since this is a LazyTreeViewDataSource that only knows about expanded items\n            // we need to reveal the item before searching for it (expand its ancestors)\n            RevealItem(id);\n\n            // Since RevealItem can have reloaded data because items was revealed we need to make\n            // sure that parent child references is set up\n            SetupChildParentReferencesIfNeeded();\n\n            return base.FindItem(id);\n        }\n\n        bool AreScenesValid(Scene[] customScenes)\n        {\n            if (customScenes == null)\n                return false;\n\n            foreach (var scene in customScenes)\n                if (!scene.IsValid())\n                    return false;\n\n            return true;\n        }\n\n        internal HierarchyProperty CreateHierarchyProperty()\n        {\n            HierarchyProperty property = new HierarchyProperty(k_HierarchyType);\n            property.alphaSorted = IsUsingAlphaSort();\n            property.showSceneHeaders = ShouldShowSceneHeaders();\n            if (SceneHierarchyHooks.provideSubScenes != null)\n                property.SetSubScenes(SceneHierarchyHooks.provideSubScenes());\n\n            if (AreScenesValid(scenes))\n                property.SetCustomScenes(scenes);\n            return property;\n        }\n\n        internal bool ShouldShowSceneHeaders()\n        {\n            // Don't show headers if there's a single scene and it's a preview scene.\n            return (scenes == null || scenes.Length != 1 || !EditorSceneManager.IsPreviewScene(scenes[0]));\n        }\n\n        void CreateRootItem(HierarchyProperty property)\n        {\n            int rootDepth = 0; // hiddden\n\n            if (property.isValid)\n            {\n                // Game Object sub tree\n                m_RootItem = new GameObjectTreeViewItem(m_RootInstanceID, rootDepth, null, property.name);\n            }\n            else\n            {\n                // All game objects\n                m_RootItem = new GameObjectTreeViewItem(m_RootInstanceID, rootDepth, null, \"RootOfAll\");\n            }\n        }\n\n        void ClearSearchFilter()\n        {\n            var property = CreateHierarchyProperty();\n            property.SetSearchFilter(\"\", 0); // 0 = All\n\n            m_SearchSessionHandler.EndSession();\n        }\n\n        public override void FetchData()\n        {\n            beforeReloading?.Invoke();\n\n            Profiler.BeginSample(\"SceneHierarchyWindow.FetchData\");\n            m_RowsPartiallyInitialized = false;\n            double fetchStartTime = EditorApplication.timeSinceStartup;\n\n            HierarchyProperty property = CreateHierarchyProperty();\n            if (m_RootInstanceID != 0)\n            {\n                bool found = property.Find(m_RootInstanceID, null);\n                if (!found)\n                {\n                    Debug.LogError(\"Root gameobject with id \" + m_RootInstanceID + \" not found!!\");\n                    m_RootInstanceID = 0;\n                    property.Reset();\n                }\n            }\n\n            CreateRootItem(property);\n\n            // Must be set before SetSelection (they calls GetRows which will fetch again if m_NeedRefreshVisibleFolders = true)\n            m_NeedRefreshRows = false;\n\n            m_NeedsChildParentReferenceSetup = true;\n\n            bool subTreeWanted = m_RootInstanceID != 0;\n            bool isSearching = !string.IsNullOrEmpty(m_SearchString);\n\n            if (isSearching)\n            {\n                m_SearchSessionHandler.BeginSession(() => new SearchService.SceneSearchContext {rootProperty = property});\n            }\n\n            if (isSearching || subTreeWanted)\n            {\n                InitializeProgressivly(property, subTreeWanted, isSearching);\n            }\n            else\n            {\n                // We delay the setup of the full data and calling SetChildParentReferences to ensure fast reloading of\n                // the game object hierarchy\n                InitializeMinimal();\n            }\n\n            double fetchEndTime = EditorApplication.timeSinceStartup;\n            double fetchTotalTime = fetchEndTime - fetchStartTime;\n            double fetchDeltaTime = fetchEndTime - m_LastFetchTime;\n\n            // If we have two relatively close consecutive fetches check execution time.\n            if (fetchDeltaTime > k_FetchDelta && fetchTotalTime > k_LongFetchTime)\n                m_DelayedFetches++;\n            else\n                m_DelayedFetches = 0;\n            m_LastFetchTime = fetchStartTime;\n\n            // We want to reset selection on copy/duplication/delete\n            m_TreeView.SetSelection(Selection.instanceIDs, false); // use false because we might just be expanding/collapsing a Item (which would prevent collapsing a Item with a selected child)\n\n            CreateSceneHeaderItems();\n\n            if (SceneHierarchy.s_Debug)\n                Debug.Log(\"Fetch time: \" + fetchTotalTime * 1000.0 + \" ms, alphaSort = \" + IsUsingAlphaSort());\n\n            Profiler.EndSample();\n        }\n\n        public override bool CanBeParent(TreeViewItem item)\n        {\n            // Ensure parent child-parent references are setup if requesting parent information\n            SetupChildParentReferencesIfNeeded();\n\n            return base.CanBeParent(item);\n        }\n\n        bool IsUsingAlphaSort()\n        {\n            return sortingState.GetType() == typeof(AlphabeticalSorting);\n        }\n\n        static void Resize(List<TreeViewItem> list, int count)\n        {\n            int cur = list.Count;\n            if (count < cur)\n                list.RemoveRange(count, cur - count);\n            else if (count > cur)\n            {\n                if (count > list.Capacity) // this bit is purely an optimisation, to avoid multiple automatic capacity changes.\n                    list.Capacity = count + 20; // add some extra to prevent alloc'ing when adding to list\n                list.AddRange(Enumerable.Repeat(default(TreeViewItem), count - cur)); // add range is nulls\n            }\n        }\n\n        private void ResizeItemList(int count)\n        {\n            AllocateBackingArrayIfNeeded();\n\n            if (m_ListOfRows.Count != count)\n            {\n                Resize(m_ListOfRows, count);\n                Assert.AreEqual(m_ListOfRows.Count, count, \"List of rows count incorrect\");\n            }\n        }\n\n        private void AllocateBackingArrayIfNeeded()\n        {\n            if (m_Rows == null)\n            {\n                int startCapacity = m_RowCount > k_DefaultStartCapacity ? m_RowCount : k_DefaultStartCapacity;\n                m_ListOfRows = new List<TreeViewItem>(startCapacity);\n                m_Rows = m_ListOfRows;\n            }\n        }\n\n        private void InitializeMinimal()\n        {\n            int[] expanded = m_TreeView.state.expandedIDs.ToArray();\n\n            HierarchyProperty property = CreateHierarchyProperty();\n            m_RowCount = property.CountRemaining(expanded);\n            ResizeItemList(m_RowCount);\n            property.Reset();\n\n            if (SceneHierarchy.s_Debug)\n                Log(\"Init minimal (\" + m_RowCount + \") num scenes \" + SceneManager.sceneCount);\n\n            int firstRow, lastRow;\n            m_TreeView.gui.GetFirstAndLastRowVisible(out firstRow, out lastRow);\n\n            InitializeRows(property, firstRow, lastRow);\n\n            m_RowsPartiallyInitialized = true;\n        }\n\n        void InitializeFull()\n        {\n            if (SceneHierarchy.s_Debug)\n                Log(\"Init full (\" + m_RowCount + \")\");\n\n            HierarchyProperty property = CreateHierarchyProperty();\n            m_RowCount = property.CountRemaining(m_TreeView.state.expandedIDs.ToArray());\n            ResizeItemList(m_RowCount);\n            property.Reset();\n\n            InitializeRows(property, 0, m_RowCount - 1);\n        }\n\n        // Used for search results, sub tree view (of e.g. a prefab) and custom sorting\n        void InitializeProgressivly(HierarchyProperty property, bool subTreeWanted, bool isSearching)\n        {\n            AllocateBackingArrayIfNeeded();\n\n            int minAllowedDepth = subTreeWanted ? property.depth + 1 : 0;\n\n            if (!isSearching)\n            {\n                // Subtree setup\n                int row = 0;\n                int[] expanded = expandedIDs.ToArray();\n                int subtractDepth = subTreeWanted ? property.depth + 1 : 0;\n\n                while (property.NextWithDepthCheck(expanded, minAllowedDepth))\n                {\n                    var item = EnsureCreatedItem(row);\n                    InitTreeViewItem(item, property, property.hasChildren, property.depth - subtractDepth);\n                    row++;\n                }\n                m_RowCount = row;\n            }\n            else // Searching\n            {\n                m_RowCount = InitializeSearchResults(property, minAllowedDepth);\n            }\n\n            // Now shrink to fit if needed\n            ResizeItemList(m_RowCount);\n        }\n\n        // Returns number of rows in search result\n        int InitializeSearchResults(HierarchyProperty property, int minAllowedDepth)\n        {\n            // Search setup\n            const bool kShowItemHasChildren = false;\n            const int kItemDepth = 0;\n            int currentSceneHandle = -1;\n            int row = 0;\n            var searchFilter = SearchableEditorWindow.CreateFilter(searchString, (SearchableEditorWindow.SearchMode)m_SearchMode);\n            var searchContext = (SearchService.SceneSearchContext)m_SearchSessionHandler.context;\n            searchContext.searchFilter = searchFilter;\n            searchContext.rootProperty = property;\n\n            m_SearchSessionHandler.BeginSearch(searchString);\n\n            var headerRows = new List<int>();\n            while (property.NextWithDepthCheck(null, minAllowedDepth))\n            {\n                if (!m_SearchSessionHandler.Filter(m_SearchString, property))\n                {\n                    property.SetFilteredVisibility(false);\n                    continue;\n                }\n\n                property.SetFilteredVisibility(true);\n                var item = EnsureCreatedItem(row);\n                // Add scene headers when encountering a new scene (and it's not a header in itself)\n                if (AddSceneHeaderToSearchIfNeeded(item, property, ref currentSceneHandle))\n                {\n                    row++;\n                    headerRows.Add(row);\n\n                    if (property.isSceneHeader)\n                        continue; // no need to add it\n\n                    item = EnsureCreatedItem(row); // prepare for item below\n                }\n                InitTreeViewItem(item, property, kShowItemHasChildren, kItemDepth);\n                row++;\n            }\n\n            m_SearchSessionHandler.EndSearch();\n\n            int numRows = row;\n\n            // Now sort scene section\n            if (headerRows.Count > 0)\n            {\n                int currentSortStart = headerRows[0];\n                for (int i = 1; i < headerRows.Count; i++)\n                {\n                    int count = headerRows[i] - currentSortStart - 1;\n                    m_ListOfRows.Sort(currentSortStart, count, new TreeViewItemAlphaNumericSort());\n                    currentSortStart = headerRows[i];\n                }\n\n                // last section\n                m_ListOfRows.Sort(currentSortStart, numRows - currentSortStart, new TreeViewItemAlphaNumericSort());\n            }\n\n\n            return numRows;\n        }\n\n        bool AddSceneHeaderToSearchIfNeeded(GameObjectTreeViewItem item, HierarchyProperty property, ref int currentSceneHandle)\n        {\n            if (PrefabStageUtility.GetCurrentPrefabStage() != null)\n                return false;\n\n            Scene scene = property.GetScene();\n            if (currentSceneHandle != scene.handle)\n            {\n                currentSceneHandle = scene.handle;\n                InitTreeViewItem(item, scene.handle, scene, true, 0, null, false, 0);\n                return true;\n            }\n            return false;\n        }\n\n        GameObjectTreeViewItem EnsureCreatedItem(int row)\n        {\n            if (row >= m_Rows.Count)\n                m_Rows.Add(null);\n\n            var item = (GameObjectTreeViewItem)m_Rows[row];\n            if (item == null)\n            {\n                item = new GameObjectTreeViewItem(0, 0, null, null);\n                m_Rows[row] = item;\n            }\n            return item;\n        }\n\n        void InitializeRows(HierarchyProperty property, int firstRow, int lastRow)\n        {\n            property.Reset();\n\n            int[] expanded = expandedIDs.ToArray();\n\n            // Skip items if needed\n            if (firstRow > 0)\n            {\n                int numRowsToSkip = firstRow;\n                if (!property.Skip(numRowsToSkip, expanded))\n                    Debug.LogError(\"Failed to skip \" + numRowsToSkip);\n            }\n\n            // Fetch visible items\n            int row = firstRow;\n\n            while (property.Next(expanded) && row <= lastRow)\n            {\n                var item = EnsureCreatedItem(row);\n                InitTreeViewItem(item, property, property.hasChildren, property.depth);\n                row++;\n            }\n        }\n\n        private void InitTreeViewItem(GameObjectTreeViewItem item, HierarchyProperty property, bool itemHasChildren, int itemDepth)\n        {\n            InitTreeViewItem(item, property.instanceID, property.GetScene(), property.isSceneHeader, property.colorCode, property.pptrValue, itemHasChildren, itemDepth);\n        }\n\n        private void InitTreeViewItem(GameObjectTreeViewItem item, int itemID, Scene scene, bool isSceneHeader, int colorCode, Object pptrObject, bool hasChildren, int depth)\n        {\n            item.children = null;\n            item.id = itemID;\n            item.depth = depth;\n            item.parent = null;\n            item.icon = null;\n            if (isSceneHeader)\n                item.displayName = string.IsNullOrEmpty(scene.name) ? \"Untitled\" : scene.name;\n            else\n                item.displayName = null; // For GameObject, name is empty as the name gets set from the objectPPTR if the Item is used in GameObjectTreeViewGUI.\n\n            item.colorCode = colorCode;\n            item.objectPPTR = pptrObject;\n            item.isSceneHeader = isSceneHeader;\n            item.scene = scene;\n\n            item.lazyInitializationDone = false;\n            item.showPrefabModeButton = false;\n            item.overlayIcon = null;\n\n            if (hasChildren)\n            {\n                item.children = CreateChildListForCollapsedParent(); // add a dummy child in children list to ensure we show the collapse arrow (because we do not fetch data for collapsed items)\n            }\n        }\n\n        protected override void GetParentsAbove(int id, HashSet<int> parentsAbove)\n        {\n            if (!IsValidHierarchyInstanceID(id))\n                return;\n\n            IHierarchyProperty propertyIterator = CreateHierarchyProperty();\n            if (propertyIterator.Find(id, null))\n            {\n                while (propertyIterator.Parent())\n                {\n                    parentsAbove.Add((propertyIterator.instanceID));\n                }\n            }\n        }\n\n        // Should return the items that have children from id and below\n        protected override void GetParentsBelow(int id, HashSet<int> parentsBelow)\n        {\n            // Add all children expanded ids to hashset\n            if (!IsValidHierarchyInstanceID(id))\n                return;\n\n            IHierarchyProperty search = CreateHierarchyProperty();\n            if (search.Find(id, null))\n            {\n                parentsBelow.Add(id);\n\n                int depth = search.depth;\n                while (search.Next(null) && search.depth > depth)\n                {\n                    if (search.hasChildren)\n                        parentsBelow.Add(search.instanceID);\n                }\n            }\n        }\n\n        static void Log(string text)\n        {\n            //System.Console.WriteLine(text);\n            Debug.Log(text);\n        }\n\n        override public bool IsRenamingItemAllowed(TreeViewItem item)\n        {\n            GameObjectTreeViewItem goItem = item as GameObjectTreeViewItem;\n            if (goItem.isSceneHeader)\n                return false;\n\n            if (SubSceneGUI.IsUsingSubScenes() && SubSceneGUI.IsSubSceneHeader((GameObject)goItem.objectPPTR))\n                return false;\n\n            return true;\n        }\n\n        void CreateSceneHeaderItems()\n        {\n            m_StickySceneHeaderItems.Clear();\n\n            int numScenesInHierarchy = EditorSceneManager.sceneCount;\n\n            if (SubSceneGUI.IsUsingSubScenes())\n            {\n                for (int i = 0; i < numScenesInHierarchy; ++i)\n                {\n                    Scene scene = SceneManager.GetSceneAt(i);\n\n                    var subSceneInfo = SubSceneGUI.GetSubSceneInfo(scene);\n                    if (subSceneInfo.isValid)\n                    {\n                        var item = new GameObjectTreeViewItem(0, 0, null, null);\n                        var transform = subSceneInfo.transform;\n                        GameObject gameObject = transform.gameObject;\n                        int depth = SubSceneGUI.CalculateHierarchyDepthOfSubScene(subSceneInfo);\n                        InitTreeViewItem(item, gameObject.GetInstanceID(), subSceneInfo.scene, false, 0, gameObject, false, depth);\n                        m_StickySceneHeaderItems.Add(item);\n                    }\n                    else\n                    {\n                        var item = new GameObjectTreeViewItem(0, 0, null, null);\n                        InitTreeViewItem(item, scene.handle, scene, true, 0, null, false, 0);\n                        m_StickySceneHeaderItems.Add(item);\n                    }\n                }\n            }\n            else\n            {\n                for (int i = 0; i < numScenesInHierarchy; ++i)\n                {\n                    Scene scene = SceneManager.GetSceneAt(i);\n\n                    var item = new GameObjectTreeViewItem(0, 0, null, null);\n                    InitTreeViewItem(item, scene.handle, scene, true, 0, null, false, 0);\n                    m_StickySceneHeaderItems.Add(item);\n                }\n            }\n        }\n\n        public Scene GetLastScene()\n        {\n            if (scenes != null)\n            {\n                for (int i = scenes.Length - 1; i >= 0; i--)\n                    if (scenes[i].isLoaded && !scenes[i].isSubScene)\n                        return scenes[i];\n            }\n\n            for (int i = SceneManager.sceneCount - 1; i >= 0; i--)\n                if (SceneManager.GetSceneAt(i).isLoaded && !SceneManager.GetSceneAt(i).isSubScene)\n                    return SceneManager.GetSceneAt(i);\n\n            Assert.IsTrue(false, \"No loaded scene could be found\");\n            return new Scene();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/GameObjectTreeViewGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Experimental;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.SceneManagement;\nusing UnityEditor.StyleSheets;\nusing UnityEditor.VersionControl;\nusing UnityEditorInternal.VersionControl;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing Object = UnityEngine.Object;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewGUI = UnityEditor.IMGUI.Controls.TreeViewGUI<int>;\n\n\nnamespace UnityEditor\n{\n    internal class GameObjectTreeViewGUI : TreeViewGUI\n    {\n        enum GameObjectColorType\n        {\n            Normal = 0,\n            Prefab = 1,\n            BrokenPrefab = 2,\n            Count = 3,\n        }\n\n        internal static class GameObjectStyles\n        {\n            public static GUIStyle disabledLabel = new GUIStyle(\"PR DisabledLabel\");\n            public static GUIStyle prefabLabel = \"PR PrefabLabel\";\n            public static GUIStyle disabledPrefabLabel = \"PR DisabledPrefabLabel\";\n            public static GUIStyle brokenPrefabLabel = \"PR BrokenPrefabLabel\";\n            public static GUIStyle disabledBrokenPrefabLabel = \"PR DisabledBrokenPrefabLabel\";\n            public static GUIStyle optionsButtonStyle = \"PaneOptions\";\n            public static GUIStyle sceneHeaderBg = \"SceneTopBarBg\";\n            public static SVC<float> sceneHeaderWidth = new SVC<float>(\"SceneTopBarBg\", \"border-bottom-width\", 1f);\n            public static GUIStyle rightArrow = \"ArrowNavigationRight\";\n            public static GUIStyle overridesHoverHighlight = \"HoverHighlight\";\n            public static GUIStyle hoveredItemBackgroundStyle = \"WhiteBackground\";\n            public static Color hoveredBackgroundColor =\n                EditorResources.GetStyle(\"game-object-tree-view\").GetColor(\"-unity-object-tree-hovered-color\");\n\n            public static Texture2D sceneIcon = (Texture2D)EditorGUIUtility.IconContent(\"SceneAsset Icon\").image;\n\n            static GameObjectStyles()\n            {\n                disabledLabel.fixedHeight = 0;\n                disabledLabel.alignment = TextAnchor.UpperLeft;\n                disabledLabel.padding = Styles.lineBoldStyle.padding;\n            }\n\n            public static readonly int kSceneHeaderIconsInterval = 2;\n        }\n\n        private float m_PrevScollPos;\n        private float m_PrevTotalHeight;\n        internal delegate float OnHeaderGUIDelegate(Rect availableRect, string scenePath);\n        internal static OnHeaderGUIDelegate OnPostHeaderGUI = null;\n\n        // Cache asset paths for managed VCS implementations.\n        private Dictionary<int, string> m_HierarchyPrefabToAssetPathMap;\n        // Cache Asset instances for native VCS implementations which have different API.\n        private Dictionary<int, Asset[]> m_HierarchyPrefabToAssetIDMap;\n\n        internal event Action<bool, int, string, string> renameEnded;\n\n        private static Dictionary<string, int> s_ActiveParentObjectPerSceneGUID;\n\n        internal static void UpdateActiveParentObjectValuesForScene(string sceneGUID, int instanceID)\n        {\n            if (instanceID == 0)\n                s_ActiveParentObjectPerSceneGUID.Remove(sceneGUID);\n            else\n                s_ActiveParentObjectPerSceneGUID[sceneGUID] = instanceID;\n        }\n\n        internal void GetActiveParentObjectValuesFromSessionInfo()\n        {\n            for (int i = 0; i < SceneManager.sceneCount; i++)\n            {\n                var key = SceneManager.GetSceneAt(i).guid;\n                var id = SceneHierarchy.GetDefaultParentForSession(SceneManager.GetSceneAt(i).guid);\n                if (id != 0)\n                    s_ActiveParentObjectPerSceneGUID.Add(key, id);\n            }\n        }\n\n        static bool DetectSceneGuidMismatchInActiveParentState(KeyValuePair<string, int> activeParentObject)\n        {\n            var go = EditorUtility.InstanceIDToObject(activeParentObject.Value) as GameObject;\n            if (go != null && go.scene.guid != activeParentObject.Key)\n            {\n                SceneHierarchy.SetDefaultParentForSession(activeParentObject.Key, 0);\n                return true;\n            }\n\n            return false;\n        }\n\n        internal static void RemoveInvalidActiveParentObjects()\n        {\n            var itemsToRemove = s_ActiveParentObjectPerSceneGUID.Where(activeParent => DetectSceneGuidMismatchInActiveParentState(activeParent)).ToArray();\n            foreach (var itemToRemove in itemsToRemove)\n            {\n                SceneHierarchy.UpdateSessionStateInfoAndActiveParentObjectValuesForScene(itemToRemove.Key, 0);\n            }\n        }\n\n        GameObjectTreeViewDataSource dataSource\n        {\n            get { return (GameObjectTreeViewDataSource)m_TreeView.data; }\n        }\n\n        bool showingSearchResults\n        {\n            get { return !string.IsNullOrEmpty(dataSource.searchString); }\n        }\n\n        public GameObjectTreeViewGUI(TreeViewController treeView, bool useHorizontalScroll)\n            : base(treeView, useHorizontalScroll)\n        {\n            k_TopRowMargin = 0f;\n            m_TreeView.enableItemHovering = true;\n        }\n\n        public override void OnInitialize()\n        {\n            base.OnInitialize();\n\n            SceneVisibilityManager.visibilityChanged += SceneVisibilityManagerOnVisibilityChanged;\n            dataSource.beforeReloading += SubSceneGUI.FetchSubSceneInfo;\n            m_PrevScollPos = m_TreeView.state.scrollPos.y;\n            m_PrevTotalHeight = m_TreeView.GetTotalRect().height;\n            k_BaseIndent = SceneVisibilityHierarchyGUI.utilityBarWidth;\n\n            if (!dataSource.ShouldShowSceneHeaders())\n            {\n                k_BaseIndent += indentWidth;// Add an extra indent to match GameObjects under a SceneHeader as this makes room for additional UI.\n            }\n\n            s_ActiveParentObjectPerSceneGUID = new Dictionary<string, int>();\n            GetActiveParentObjectValuesFromSessionInfo();\n\n            m_HierarchyPrefabToAssetPathMap = new Dictionary<int, string>();\n            m_HierarchyPrefabToAssetIDMap = new Dictionary<int, Asset[]>();\n        }\n\n        private void SceneVisibilityManagerOnVisibilityChanged()\n        {\n            m_TreeView.Repaint();\n        }\n\n        public bool DetectUserInput()\n        {\n            if (DetectScrollChange())\n                return true;\n            if (DetectTotalRectChange())\n                return true;\n            if (DetectMouseDownInTreeViewRect())\n                return true;\n\n            return false;\n        }\n\n        bool DetectScrollChange()\n        {\n            bool changed = false;\n            float curScroll = m_TreeView.state.scrollPos.y;\n            if (!Mathf.Approximately(curScroll, m_PrevScollPos))\n                changed = true;\n            m_PrevScollPos = curScroll;\n            return changed;\n        }\n\n        bool DetectTotalRectChange()\n        {\n            bool changed = false;\n            float curHeight = m_TreeView.GetTotalRect().height;\n            if (!Mathf.Approximately(curHeight, m_PrevTotalHeight))\n                changed = true;\n            m_PrevTotalHeight = curHeight;\n            return changed;\n        }\n\n        bool DetectMouseDownInTreeViewRect()\n        {\n            var evt = Event.current;\n            var mouseEvent = evt.type == EventType.MouseDown || evt.type == EventType.MouseUp;\n            var keyboardEvent = evt.type == EventType.KeyDown || evt.type == EventType.KeyUp;\n            if ((mouseEvent && m_TreeView.GetTotalRect().Contains(evt.mousePosition)) || keyboardEvent)\n                return true;\n            return false;\n        }\n\n        bool showingStickyHeaders { get { return SceneManager.sceneCount > 1; } }\n\n        void DoStickySceneHeaders()\n        {\n            int firstRow, lastRow;\n            GetFirstAndLastRowVisible(out firstRow, out lastRow);\n            if (firstRow >= 0 && lastRow > firstRow)\n            {\n                float scrollY = m_TreeView.state.scrollPos.y;\n                if (firstRow == 0 && scrollY <= topRowMargin)\n                    return; // Do nothing when first row is 0 since we do not need any sticky headers overlay\n\n                var firstItem = (GameObjectTreeViewItem)m_TreeView.data.GetItem(firstRow);\n                var nextItem = (GameObjectTreeViewItem)m_TreeView.data.GetItem(firstRow + 1);\n                bool isFirstItemLastInScene = firstItem.scene != nextItem.scene;\n                float rowWidth = GUIClip.visibleRect.width;\n                Rect rect = GetRowRect(firstRow, rowWidth);\n\n                // Do not do the sticky header if the scene is at top\n                if (firstItem.isSceneHeader && Mathf.Approximately(scrollY, rect.y))\n                    return;\n\n                // Sticky header is achieved by ensuring the header never moves out of\n                // scroll and is aligned with last item in scene list if needed\n                if (!isFirstItemLastInScene)\n                    rect.y = scrollY;\n\n                var sceneHeaderItem = dataSource.sceneHeaderItems.FirstOrDefault(p => p.scene == firstItem.scene);\n                if (sceneHeaderItem != null)\n                {\n                    rect.y = Mathf.Round(rect.y); // Fix vertical render jittering due to fractional scroll values by rounding to nearest whole pixel\n\n                    bool selected = m_TreeView.IsItemDragSelectedOrSelected(sceneHeaderItem);\n                    bool focused = m_TreeView.HasFocus();\n                    bool boldFont = sceneHeaderItem.scene == SceneManager.GetActiveScene();\n                    DoItemGUI(rect, firstRow, sceneHeaderItem, selected, focused, boldFont);\n\n                    if (sceneHeaderItem.scene.isLoaded)\n                        DoStickyHeaderItemFoldout(rect, sceneHeaderItem);\n\n                    m_TreeView.HandleUnusedMouseEventsForItem(rect, sceneHeaderItem, firstRow);\n\n                    HandleStickyHeaderContextClick(rect, sceneHeaderItem);\n\n                    float indent = GetContentIndent(sceneHeaderItem);\n                    Rect indentedRect = new Rect(rect.x + indent, rect.y, rect.width - indent, rect.height);\n                    UserCallbackRowGUI(sceneHeaderItem.id, indentedRect);\n                }\n            }\n        }\n\n        void HandleStickyHeaderContextClick(Rect rect, GameObjectTreeViewItem sceneHeaderItem)\n        {\n            Event evt = Event.current;\n\n            // On OSX manually handle context click for sticky headers here to prevent items beneath the sticky header to also handle the event\n            if (Application.platform == RuntimePlatform.OSXEditor)\n            {\n                bool showContextMenu = (evt.type == EventType.MouseDown && evt.button == 1) || evt.type == EventType.ContextClick; // cmd+left click fires a context click event\n                if (showContextMenu && rect.Contains(Event.current.mousePosition))\n                {\n                    evt.Use();\n                    m_TreeView.contextClickItemCallback(sceneHeaderItem.id);\n                }\n            }\n            else if (Application.platform == RuntimePlatform.WindowsEditor)\n            {\n                if (evt.type == EventType.MouseDown && evt.button == 1 && rect.Contains(Event.current.mousePosition))\n                {\n                    // On Windows prevent right mouse down to propagate to items beneath (which will select items below this item)\n                    evt.Use();\n                }\n            }\n        }\n\n        void DoStickyHeaderItemFoldout(Rect rect, TreeViewItem item)\n        {\n            Rect foldoutRect = new Rect(rect.x + GetFoldoutIndent(item), Mathf.Round(rect.y + customFoldoutYOffset), foldoutStyleWidth, k_LineHeight);\n            var expanded = m_TreeView.data.IsExpanded(item);\n            var newExpanded = DoFoldoutButton(foldoutRect, expanded, foldoutStyle);\n            if (expanded != newExpanded)\n            {\n                m_TreeView.ChangeExpandedState(item, newExpanded, Event.current.alt);\n                m_TreeView.ReloadData();\n                if (!newExpanded)\n                {\n                    m_TreeView.Frame(item.id, true, false);\n                }\n\n                // The TreeView was reloaded with new expanded state so we should not continue iterating visible rows.\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        public override void BeginRowGUI()\n        {\n            if (DetectUserInput())\n            {\n                dataSource.EnsureFullyInitialized();\n            }\n\n            base.BeginRowGUI();\n\n            // Sticky scene headers. Do non repaint events first to receive input first\n            if (showingStickyHeaders && Event.current.type != EventType.Repaint)\n            {\n                DoStickySceneHeaders();\n            }\n        }\n\n        public override void EndRowGUI()\n        {\n            base.EndRowGUI();\n\n            // Sticky scene headers. Do repaint events last to render on top.\n            if (showingStickyHeaders && Event.current.type == EventType.Repaint)\n            {\n                DoStickySceneHeaders();\n            }\n        }\n\n        public override Rect GetRectForFraming(int row)\n        {\n            Rect rect = base.GetRectForFraming(row);\n            if (showingStickyHeaders && row < m_TreeView.data.rowCount)\n            {\n                var item = m_TreeView.data.GetItem(row) as GameObjectTreeViewItem;\n                if (item != null && !item.isSceneHeader)\n                {\n                    // For game objects under a sceneheader we create a larger frame rect to ensure row is shown\n                    // beneath the sticky header (headers have same lineheight as rows)\n                    rect.y -= k_LineHeight;\n                    rect.height = 2 * k_LineHeight;\n                }\n            }\n\n            return rect;\n        }\n\n        //-------------------\n        // Create and Rename GameObject section\n\n        override public bool BeginRename(TreeViewItem item, float delay)\n        {\n            GameObjectTreeViewItem goItem = item as GameObjectTreeViewItem;\n            if (goItem == null)\n                return false;\n            if (goItem.isSceneHeader)\n                return false;\n\n            GameObject gameObject = (GameObject)goItem.objectPPTR;\n            if ((gameObject.hideFlags & HideFlags.NotEditable) != 0)\n            {\n                Debug.LogWarning(\"Unable to rename a GameObject with HideFlags.NotEditable.\");\n                return false;\n            }\n\n            return base.BeginRename(item, delay);\n        }\n\n        override protected void RenameEnded()\n        {\n            bool userAcceptedRename = GetRenameOverlay().userAcceptedRename;\n            int instanceID = GetRenameOverlay().userData;\n            string name = string.IsNullOrEmpty(GetRenameOverlay().name) ? GetRenameOverlay().originalName : GetRenameOverlay().name;\n            string originalname = GetRenameOverlay().originalName;\n            renameEnded?.Invoke(userAcceptedRename, instanceID, name, originalname);\n        }\n\n        private bool isDragging\n        {\n            get\n            {\n                return m_TreeView.isDragging ||\n                    (m_TreeView.dragging != null && m_TreeView.dragging.GetDropTargetControlID() != -1);\n            }\n        }\n\n        override protected void DrawItemBackground(Rect rect, int row, TreeViewItem item, bool selected, bool focused)\n        {\n            var goItem = (GameObjectTreeViewItem)item;\n            if (goItem.isSceneHeader)\n            {\n                GUI.Label(rect, GUIContent.none, GameObjectStyles.sceneHeaderBg);\n            }\n            else\n            {\n                // Don't show indented sub scene header backgrounds when searching (as the texts are not indented here)\n                if (SubSceneGUI.IsUsingSubScenes() && !showingSearchResults)\n                {\n                    var gameObject = (GameObject)goItem.objectPPTR;\n                    if (gameObject != null && SubSceneGUI.IsSubSceneHeader(gameObject))\n                    {\n                        SubSceneGUI.DrawSubSceneHeaderBackground(rect, k_BaseIndent, k_IndentWidth, gameObject);\n                    }\n                }\n            }\n\n            if (m_TreeView.hoveredItem != item)\n                return;\n\n            if (isDragging)\n                return;\n\n            using (new GUI.BackgroundColorScope(GameObjectStyles.hoveredBackgroundColor))\n            {\n                GUI.Label(rect, GUIContent.none, GameObjectStyles.hoveredItemBackgroundStyle);\n            }\n        }\n\n        float m_ContentRectRight;\n\n        override protected void DoItemGUI(Rect rect, int row, TreeViewItem item, bool selected, bool focused, bool useBoldFont)\n        {\n            GameObjectTreeViewItem goItem = item as GameObjectTreeViewItem;\n            if (goItem == null)\n                return;\n\n            EnsureLazyInitialization(goItem); // Needed to ensure item is ready for all ui controls\n\n            if (goItem.isSceneHeader)\n            {\n                useBoldFont = (goItem.scene == SceneManager.GetActiveScene());\n            }\n\n            base.DoItemGUI(rect, row, item, selected, focused, useBoldFont);\n            SceneVisibilityHierarchyGUI.DoItemGUI(rect, goItem, selected && !IsRenaming(item.id), m_TreeView.hoveredItem == goItem, focused, isDragging);\n        }\n\n        internal static void UserCallbackRowGUI(int itemID, Rect rect)\n        {\n            if (EditorApplication.hierarchyWindowItemOnGUI != null)\n            {\n                // Adjust rect for the right aligned column for the prefab isolation button\n                rect.xMax -=\n                    GameObjectStyles.rightArrow.fixedWidth +\n                    GameObjectStyles.rightArrow.margin.horizontal;\n\n                EditorApplication.hierarchyWindowItemOnGUI(itemID, rect);\n            }\n        }\n\n        private void HandlePrefabInstanceOverrideStatus(GameObjectTreeViewItem goItem, Rect rect, bool selected, bool focused)\n        {\n            GameObject go = goItem.objectPPTR as GameObject;\n            if (!go)\n                return;\n\n            if (PrefabUtility.IsOutermostPrefabInstanceRoot(go) && PrefabUtility.HasPrefabInstanceNonDefaultOverridesOrUnusedOverrides_CachedForUI(go))\n            {\n                Rect overridesMarkerRect = new Rect(rect.x + SceneVisibilityHierarchyGUI.utilityBarWidth, rect.y + 1, 2, rect.height - 2);\n\n                Color clr = (selected && focused) ? EditorGUI.k_OverrideMarginColorSelected : EditorGUI.k_OverrideMarginColor;\n\n                EditorGUI.DrawRect(overridesMarkerRect, clr);\n            }\n        }\n\n        static GameObject[] GetOutermostPrefabInstancesFromSelection()\n        {\n            var gos = new List<GameObject>();\n            var gameObjects = Selection.gameObjects;\n            for (int i = 0; i < gameObjects.Length; i++)\n            {\n                var go = gameObjects[i];\n                if (go != null && PrefabUtility.IsPartOfNonAssetPrefabInstance(go) && PrefabUtility.IsOutermostPrefabInstanceRoot(go))\n                    gos.Add(go);\n            }\n\n            return gos.ToArray();\n        }\n\n        protected override void OnAdditionalGUI(Rect rect, int row, TreeViewItem item, bool selected, bool focused)\n        {\n            GameObjectTreeViewItem goItem = item as GameObjectTreeViewItem;\n            if (goItem == null)\n                return;\n\n            m_ContentRectRight = 0;\n\n            if (goItem.isSceneHeader)\n            {\n                m_ContentRectRight = DoAdditionalSceneHeaderGUI(goItem, rect);\n            }\n            else\n            {\n                m_ContentRectRight = PrefabModeButton(goItem, rect);\n                if (SubSceneGUI.IsUsingSubScenes() && !showingSearchResults)\n                {\n                    SubSceneGUI.DrawVerticalLine(rect, k_BaseIndent, k_IndentWidth, (GameObject)goItem.objectPPTR);\n                }\n\n                HandlePrefabInstanceOverrideStatus(goItem, rect, selected, focused);\n            }\n\n            if (SceneHierarchy.s_Debug)\n                GUI.Label(new Rect(rect.xMax - 70, rect.y, 70, rect.height), \"\" + row + \" (\" + goItem.id + \")\", EditorStyles.boldLabel);\n        }\n\n        protected override Rect GetDropTargetRect(Rect rect)\n        {\n            rect.xMin += SceneVisibilityHierarchyGUI.utilityBarWidth;\n\n            return rect;\n        }\n\n        protected float DoAdditionalSceneHeaderGUI(GameObjectTreeViewItem goItem, Rect rect)\n        {\n            const float margin = 4f;\n            Rect buttonRect;\n            if (DoOptionsButton(rect, out buttonRect))\n            {\n                // Ensure item is selected before using context menu (menu logic is based on selection)\n                m_TreeView.SelectionClick(goItem, true);\n                m_TreeView.contextClickItemCallback(goItem.id);\n            }\n\n            float availableRectLeft = buttonRect.xMin;\n            if (null != OnPostHeaderGUI)\n            {\n                float optionsWidth = (rect.width - buttonRect.x);\n                float width = (rect.width - optionsWidth - margin);\n                float x = 0;\n                float y = rect.y;\n                float height = rect.height;\n                Rect availableRect = new Rect(x, y, width, height);\n                availableRectLeft = Math.Min(availableRectLeft, OnPostHeaderGUI(availableRect, goItem.scene.path));\n            }\n\n            return availableRectLeft;\n        }\n\n        internal static bool DoOptionsButton(Rect rect, out Rect buttonRect)\n        {\n            const float optionsButtonWidth = 16f;\n            const float optionsButtonHeight = 16f;\n            const float margin = 4f;\n\n            buttonRect = new Rect(rect.xMax - optionsButtonWidth - margin, rect.y + (rect.height - optionsButtonHeight) * 0.5f, optionsButtonWidth, rect.height);\n\n            if (Event.current.type == EventType.Repaint)\n                GameObjectStyles.optionsButtonStyle.Draw(buttonRect, false, false, false, false);\n\n            // We want larger click area than the button icon\n            buttonRect.y = rect.y;\n            buttonRect.height = rect.height;\n            buttonRect.width = 24f;\n            return EditorGUI.DropdownButton(buttonRect, GUIContent.none, FocusType.Passive, GUIStyle.none);\n        }\n\n        void EnsureLazyInitialization(GameObjectTreeViewItem item)\n        {\n            if (!item.lazyInitializationDone)\n            {\n                item.lazyInitializationDone = true;\n\n                SetItemIcon(item);\n                SetItemSelectedIcon(item);\n                SetItemOverlayIcon(item);\n                SetPrefabModeButtonVisibility(item);\n            }\n        }\n\n        void SetItemIcon(GameObjectTreeViewItem item)\n        {\n            var go = item.objectPPTR as GameObject;\n            if (go == null)\n            {\n                item.icon = GameObjectStyles.sceneIcon;\n            }\n            else\n            {\n                if (SubSceneGUI.IsSubSceneHeader(go))\n                    item.icon = GameObjectStyles.sceneIcon;\n                else\n                    item.icon = PrefabUtility.GetIconForGameObject(go);\n            }\n        }\n\n        void SetItemSelectedIcon(GameObjectTreeViewItem item)\n        {\n            if (item.icon != null)\n            {\n                item.selectedIcon = EditorUtility.GetIconInActiveState(item.icon) as Texture2D;\n            }\n        }\n\n        internal override Texture GetIconForSelectedItem(TreeViewItem item)\n        {\n            GameObjectTreeViewItem goItem = item as GameObjectTreeViewItem;\n\n            if (goItem != null)\n            {\n                return goItem.selectedIcon;\n            }\n\n            return item.icon;\n        }\n\n        void SetItemOverlayIcon(GameObjectTreeViewItem item)\n        {\n            item.overlayIcon = null;\n\n            var go = item.objectPPTR as GameObject;\n            if (go == null)\n                return;\n\n            if (PrefabUtility.IsAddedGameObjectOverride(go))\n                item.overlayIcon = EditorGUIUtility.LoadIcon(\"PrefabOverlayAdded Icon\");\n\n\n            if (!EditorApplication.isPlaying)\n            {\n                var vco = VersionControlManager.activeVersionControlObject;\n                if (vco != null)\n                {\n                    if (!m_HierarchyPrefabToAssetPathMap.ContainsKey(item.id))\n                    {\n                        var guid = GetAssetGUID(item);\n                        if (!string.IsNullOrEmpty(guid))\n                        {\n                            var assetPath = AssetDatabase.GUIDToAssetPath(guid);\n                            if (!string.IsNullOrEmpty(assetPath))\n                                m_HierarchyPrefabToAssetPathMap.Add(item.id, assetPath);\n                        }\n                    }\n                }\n                else\n                {\n                    var asset = GetAsset(item);\n                    if (asset != null && !m_HierarchyPrefabToAssetIDMap.ContainsKey(item.id))\n                    {\n                        var metaPath = asset.path.Trim('/') + \".meta\";\n                        var metaAsset = Provider.GetAssetByPath(metaPath);\n                        var assets = new[] { asset, metaAsset };\n\n                        m_HierarchyPrefabToAssetIDMap.Add(item.id, assets);\n                    }\n                }\n            }\n        }\n\n        void SetPrefabModeButtonVisibility(GameObjectTreeViewItem item)\n        {\n            item.showPrefabModeButton = false;\n\n            GameObject go = item.objectPPTR as GameObject;\n\n            if (go == null)\n                return;\n\n            if (!PrefabUtility.IsPartOfAnyPrefab(go))\n                return;\n\n            if (!PrefabUtility.IsAnyPrefabInstanceRoot(go))\n                return;\n\n            // Don't show button if prefab asset is missing\n            if (PrefabUtility.GetPrefabInstanceStatus(go) == PrefabInstanceStatus.Connected)\n            {\n                var source = PrefabUtility.GetOriginalSourceOrVariantRoot(go);\n                if (source == null)\n                    return;\n\n                // Don't show buttons for model prefabs but allow buttons for other immutables\n                if (PrefabUtility.IsPartOfModelPrefab(source))\n                    return;\n            }\n            else if (PrefabUtility.GetPrefabInstanceHandle(go) == null)\n                return;\n            else\n            {\n                var assetPath = PrefabUtility.GetAssetPathOfSourcePrefab(go);\n                var broken = AssetDatabase.LoadMainAssetAtPath(assetPath) as BrokenPrefabAsset;\n                if (broken == null || !broken.isPrefabFileValid)\n                    return;\n            }\n\n            item.showPrefabModeButton = true;\n        }\n\n        protected override void OnContentGUI(Rect rect, int row, TreeViewItem item, string label, bool selected, bool focused,\n            bool useBoldFont, bool isPinging)\n        {\n            GameObjectTreeViewItem goItem = item as GameObjectTreeViewItem;\n            if (goItem == null)\n                return;\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            EnsureLazyInitialization(goItem); // Needed to ensure icon is initialized if reload happens during DoItemGUI\n\n            rect.xMax = m_ContentRectRight;\n\n            if (goItem.isSceneHeader)\n            {\n                if (goItem.scene.isDirty)\n                    label += \"*\";\n\n                switch (goItem.scene.loadingState)\n                {\n                    case Scene.LoadingState.NotLoaded:\n                        label += \" (not loaded)\";\n                        break;\n                    case Scene.LoadingState.Loading:\n                        label += \" (is loading)\";\n                        break;\n                    case Scene.LoadingState.Unloading:\n                        label += \" (is unloading)\";\n                        break;\n                }\n\n                // Render disabled if scene is unloaded\n                using (new EditorGUI.DisabledScope(!goItem.scene.isLoaded))\n                {\n                    base.OnContentGUI(rect, row, item, label, selected, focused, useBoldFont, isPinging);\n                }\n                return;\n            }\n\n            if (!isPinging)\n            {\n                // The rect is assumed indented and sized after the content when pinging\n                rect.xMin += GetContentIndent(item) + extraSpaceBeforeIconAndLabel;\n            }\n\n            int colorCode = goItem.colorCode;\n            bool renderDisabled = colorCode >= 4;\n\n            lineStyle = Styles.lineStyle;\n\n            if (SubSceneGUI.IsUsingSubScenes())\n                useBoldFont = SubSceneGUI.UseBoldFontForGameObject((GameObject)goItem.objectPPTR);\n\n            if (useBoldFont)\n            {\n                lineStyle = Styles.lineBoldStyle;\n            }\n            else\n            {\n                GameObjectColorType objectColorType = (GameObjectColorType)(colorCode & 3);\n                if (objectColorType == GameObjectColorType.Normal)\n                    lineStyle = (renderDisabled) ? GameObjectStyles.disabledLabel : Styles.lineStyle;\n                else if (objectColorType == GameObjectColorType.Prefab)\n                    lineStyle = (renderDisabled) ? GameObjectStyles.disabledPrefabLabel : GameObjectStyles.prefabLabel;\n                else if (objectColorType == GameObjectColorType.BrokenPrefab)\n                    lineStyle = (renderDisabled) ? GameObjectStyles.disabledBrokenPrefabLabel : GameObjectStyles.brokenPrefabLabel;\n            }\n\n            var sceneGUID = s_ActiveParentObjectPerSceneGUID.FirstOrDefault(x => x.Value == goItem.id).Key;\n            if (!string.IsNullOrEmpty(sceneGUID) && (EditorSceneManager.GetActiveScene().guid == sceneGUID || PrefabStageUtility.GetCurrentPrefabStage() != null))\n            {\n                lineStyle = Styles.lineBoldStyle;\n            }\n\n            lineStyle.padding.left = 0;\n            Texture icon = GetEffectiveIcon(goItem, selected, focused);\n\n            if (icon != null)\n            {\n                Rect iconRect = rect;\n                iconRect.width = k_IconWidth;\n\n                Color col = GUI.color;\n                if (renderDisabled || (CutBoard.hasCutboardData && CutBoard.IsGameObjectPartOfCutAndPaste((GameObject)goItem.objectPPTR)))\n                    col = new Color(1f, 1f, 1f, 0.5f);\n                GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleToFit, true, 0, col, 0, 0);\n\n                if (goItem.overlayIcon != null)\n                    GUI.DrawTexture(iconRect, goItem.overlayIcon, ScaleMode.ScaleToFit, true, 0, col, 0, 0);\n\n                if (!EditorApplication.isPlaying)\n                {\n                    var vco = VersionControlManager.activeVersionControlObject;\n                    if (vco != null)\n                    {\n                        var extension = vco.GetExtension<IIconOverlayExtension>();\n                        if (extension != null && m_HierarchyPrefabToAssetPathMap.TryGetValue(item.id, out var assetPath))\n                        {\n                            iconRect.x -= 10;\n                            iconRect.width += 7 * 2;\n\n                            extension.DrawOverlay(assetPath, IconOverlayType.Hierarchy, iconRect);\n                        }\n                    }\n                    else\n                    {\n                        Asset[] assets;\n                        m_HierarchyPrefabToAssetIDMap.TryGetValue(item.id, out assets);\n                        if (assets != null)\n                        {\n                            iconRect.x -= 10;\n                            iconRect.width += 7 * 2;\n\n                            Overlay.DrawHierarchyOverlay(assets[0], assets[1], iconRect);\n                        }\n                    }\n                }\n\n                rect.xMin += iconTotalPadding + k_IconWidth + k_SpaceBetweenIconAndText;\n            }\n\n            // Draw text\n            lineStyle.Draw(rect, label, false, false, selected, focused);\n        }\n\n        private Asset GetAsset(GameObjectTreeViewItem item)\n        {\n            if (!Provider.isActive)\n                return null;\n\n            var guid = GetAssetGUID(item);\n\n            Asset vcAsset = string.IsNullOrEmpty(guid) ? null : Provider.GetAssetByGUID(guid);\n            return vcAsset;\n        }\n\n        static string GetAssetGUID(GameObjectTreeViewItem item)\n        {\n            var go = (GameObject)item.objectPPTR;\n\n            if (!go || PrefabUtility.GetNearestPrefabInstanceRoot(go) != go)\n                return null;\n\n            var assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(go);\n            return AssetDatabase.AssetPathToGUID(assetPath);\n        }\n\n        public float PrefabModeButton(GameObjectTreeViewItem item, Rect selectionRect)\n        {\n            float contentRectRight = selectionRect.xMax;\n            if (item.showPrefabModeButton)\n            {\n                float yOffset = (selectionRect.height - GameObjectStyles.rightArrow.fixedWidth) / 2;\n                Rect buttonRect = new Rect(\n                    selectionRect.xMax - GameObjectStyles.rightArrow.fixedWidth - GameObjectStyles.rightArrow.margin.right,\n                    selectionRect.y + yOffset,\n                    GameObjectStyles.rightArrow.fixedWidth,\n                    GameObjectStyles.rightArrow.fixedHeight);\n\n                int instanceID = item.id;\n                GUIContent content = buttonRect.Contains(Event.current.mousePosition) ? PrefabStageUtility.GetPrefabButtonContent(instanceID) : GUIContent.none;\n                if (GUI.Button(buttonRect, content, GameObjectStyles.rightArrow))\n                {\n                    GameObject go = EditorUtility.InstanceIDToObject(instanceID) as GameObject;\n                    string assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(go);\n                    if (string.IsNullOrWhiteSpace(assetPath)) //In case its a broken prefab\n                        assetPath = PrefabUtility.GetAssetPathOfSourcePrefab(go);\n\n                    Object originalSource = AssetDatabase.LoadMainAssetAtPath(assetPath);\n                    if (originalSource != null)\n                    {\n                        var prefabStageMode = PrefabStageUtility.GetPrefabStageModeFromModifierKeys();\n                        PrefabStageUtility.OpenPrefab(assetPath, go, prefabStageMode, StageNavigationManager.Analytics.ChangeType.EnterViaInstanceHierarchyRightArrow);\n                    }\n                }\n\n                contentRectRight = buttonRect.xMin;\n            }\n\n            return contentRectRight;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/GameObjectTreeViewItem.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\n\n\nnamespace UnityEditor\n{\n    internal class GameObjectTreeViewItem : TreeViewItem\n    {\n        int m_ColorCode;\n        Object m_ObjectPPTR;\n        Scene m_UnityScene;\n\n        // Lazy initialized together with icon.\n        bool m_LazyInitializationDone;\n        bool m_ShowPrefabModeButton;\n        Texture2D m_OverlayIcon;\n        Texture2D m_SelectedIcon;\n\n        public GameObjectTreeViewItem(int id, int depth, TreeViewItem parent, string displayName)\n            : base(id, depth, parent, displayName)\n        {\n        }\n\n        public override string displayName\n        {\n            get\n            {\n                // Lazy initilize displayName\n                if (base.displayName == null)\n                {\n                    if (SubSceneGUI.IsUsingSubScenes())\n                    {\n                        var subSceneHeaderName = SubSceneGUI.GetSubSceneHeaderText((GameObject)objectPPTR);\n                        if (subSceneHeaderName != null)\n                        {\n                            base.displayName = subSceneHeaderName;\n                            return base.displayName;\n                        }\n                    }\n\n                    if (m_ObjectPPTR != null)\n                        displayName = objectPPTR.name;\n                    else\n                        displayName = \"deleted gameobject\";\n                }\n                return base.displayName;\n            }\n            set { base.displayName = value; }\n        }\n\n        virtual public int colorCode { get { return m_ColorCode; } set { m_ColorCode = value; } }\n        virtual public Object objectPPTR { get { return m_ObjectPPTR; } set { m_ObjectPPTR = value; } }\n        virtual public bool lazyInitializationDone { get { return m_LazyInitializationDone; } set { m_LazyInitializationDone = value; } }\n        virtual public bool showPrefabModeButton { get { return m_ShowPrefabModeButton; } set { m_ShowPrefabModeButton = value; } }\n        virtual public Texture2D overlayIcon { get { return m_OverlayIcon; } set { m_OverlayIcon = value; } }\n        virtual public Texture2D selectedIcon { get { return m_SelectedIcon; } set { m_SelectedIcon = value; } }\n\n        public bool isSceneHeader { get; set; }\n        public Scene scene\n        {\n            get { return m_UnityScene; }\n            set { m_UnityScene = value; }\n        }\n    }\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/ITreeViewDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\n// The TreeView requires implementations from the following three interfaces:\n//  ITreeViewDataSource:    Should handle data fetching, build the tree/data structure and hold expanded state\n//  ITreeViewGUI:           Should handle visual representation of TreeView and input handling\n//  ITreeViewDragging       Should handle dragging, temp expansion of items, allow/disallow dropping\n// The TreeView handles:    Navigation, Item selection and initiates dragging\n\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    // Represents a complete data tree\n    internal interface ITreeViewDataSource<TIdentifier> where TIdentifier : unmanaged, System.IEquatable<TIdentifier>\n    {\n        void OnInitialize();\n\n        // Return root of tree\n        TreeViewItem<TIdentifier> root { get; }\n\n        // For data sources where GetRows() might be an expensive operation\n        int rowCount { get; }\n\n        // Reload data\n        void ReloadData();\n\n        void InitIfNeeded();\n\n        // Find Item by id\n        TreeViewItem<TIdentifier> FindItem(TIdentifier id);\n\n        // Get current row of an item (using the current expanded state in TreeViewState)\n        // Returns -1 if not found\n        int GetRow(TIdentifier id);\n\n        // Check rowCount before requesting\n        TreeViewItem<TIdentifier> GetItem(int row);\n\n        // Get the flattened tree of visible items. If possible use GetItem(int row) instead\n        IList<TreeViewItem<TIdentifier>> GetRows();\n\n        bool IsRevealed(TIdentifier id);\n\n        void RevealItem(TIdentifier id);\n        void RevealItems(TIdentifier[] ids);\n\n        // Expand / collapse interface\n        // The DataSource has the interface for this because it should be able to rebuild\n        // tree when expanding\n        void SetExpandedWithChildren(TreeViewItem<TIdentifier> item, bool expand);\n        void SetExpanded(TreeViewItem<TIdentifier> item, bool expand);\n        bool IsExpanded(TreeViewItem<TIdentifier> item);\n        bool IsExpandable(TreeViewItem<TIdentifier> item);\n        void SetExpandedWithChildren(TIdentifier id, bool expand);\n        TIdentifier[] GetExpandedIDs();\n        void SetExpandedIDs(TIdentifier[] ids);\n        bool SetExpanded(TIdentifier id, bool expand);\n        bool IsExpanded(TIdentifier id);\n\n        // Selection\n        bool CanBeMultiSelected(TreeViewItem<TIdentifier> item);\n        bool CanBeParent(TreeViewItem<TIdentifier> item);\n        List<TIdentifier> GetNewSelection(TreeViewItem<TIdentifier> clickedItem, TreeViewSelectState<TIdentifier> selectState);\n\n        // Renaming\n        bool IsRenamingItemAllowed(TreeViewItem<TIdentifier> item);\n        void InsertFakeItem(TIdentifier id, TIdentifier parentID, string name, Texture2D icon);\n        void RemoveFakeItem();\n        bool HasFakeItem();\n\n        // Search\n        void OnSearchChanged();\n    }\n} // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/ITreeViewDragging.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\n\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    // The TreeView requires implementations from the following three interfaces:\n    //  ITreeViewDataSource:    Should handle data fetching and data structure\n    //  ITreeViewGUI:           Should handle visual representation of TreeView and input handling\n    //  ITreeViewDragging       Should handle dragging, temp expansion of items, allow/disallow dropping\n    // The TreeView handles:    Navigation, Item selection and initiates dragging\n\n\n    // DragNDrop interface for tree views\n    internal interface ITreeViewDragging<TIdentifier>\n    {\n        void OnInitialize();\n        bool CanStartDrag(TreeViewItem<TIdentifier> targetItem, List<TIdentifier> draggedItemIDs, Vector2 mouseDownPosition);\n        void StartDrag(TreeViewItem<TIdentifier> draggedItem, List<TIdentifier> draggedItemIDs);\n        bool DragElement(TreeViewItem<TIdentifier> targetItem, Rect targetItemRect, int row);             // 'targetItem' is null when not hovering over any target Item.  Returns true if drag was handled.\n        void DragCleanup(bool revertExpanded);\n        int GetDropTargetControlID();\n        int GetRowMarkerControlID();\n        bool drawRowMarkerAbove { get; set; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/ITreeViewGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\n// The TreeView requires implementations from the following three interfaces:\n//  ITreeViewDataSource:    Should handle data fetching and data structure\n//  ITreeViewGUI:           Should handle visual representation of TreeView and input handling\n//  ITreeViewDragging       Should handle dragging, temp expansion of items, allow/disallow dropping\n// The TreeView handles:    Navigation, Item selection and initiates dragging\n\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    internal interface ITreeViewGUI<TIdentifier> where TIdentifier : unmanaged, System.IEquatable<TIdentifier>\n    {\n        void OnInitialize();\n\n        // Should return the size of the entire visible content (in pixels).\n        Vector2 GetTotalSize();\n\n        // Should return the row number of the first and last row thats fits between top pixel and the height of the window\n        // If the treeview contains items with varying heights then use the minium height for determining the lastRowVisible\n        // this is needed when animating the treeview to ensure all items are rendered while animating.\n        // Can use TreeView.GetTotalRect and m_TreeView.state.scrollPos.y for calculating first and last values\n        void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible);\n\n        Rect GetRowRect(int row, float rowWidth);\n        Rect GetRectForFraming(int row);\n\n        int GetNumRowsOnPageUpDown(TreeViewItem<TIdentifier> fromItem, bool pageUp, float heightOfTreeView);\n\n        // OnGUI: Implement to handle TreeView OnGUI\n        void OnRowGUI(Rect rowRect, TreeViewItem<TIdentifier> item, int row, bool selected, bool focused);\n        void BeginRowGUI();                                                                     // use for e.g clearing state before OnRowGUI calls\n        void EndRowGUI();                                                                       // use for handling stuff after all rows have had their OnRowGUI\n\n        // Ping Item interface (implement a rendering of a 'ping' for a Item).\n        void BeginPingItem(TreeViewItem<TIdentifier> item, float topPixelOfRow, float availableWidth);\n        void EndPingItem();\n\n        // Rename interface (BeginRename should return true if rename is handled)\n        bool BeginRename(TreeViewItem<TIdentifier> item, float delay);\n        void EndRename();\n        Rect GetRenameRect(Rect rowRect, int row, TreeViewItem<TIdentifier> item);\n\n        float GetContentIndent(TreeViewItem<TIdentifier> item);\n\n        float halfDropBetweenHeight { get; }\n        float topRowMargin { get; }\n        float bottomRowMargin { get; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/LazyTreeViewDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\n\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    // LazyTreeViewDataSource assumes that the Item tree only contains visible items, optimal for large data sets.\n    // Usage:\n    //    - Override FetchData () and build the tree with visible items with m_RootItem as root  (and and populate the m_VisibleRows List)\n    //    - FetchData () is called every time the expanded state changes.\n    //    - Configure showRootItem and rootIsCollapsable as wanted\n    //\n    // Note: if dealing with small trees consider using TreeViewDataSource instead: it assumes that the tree contains all items.\n\n    internal abstract class LazyTreeViewDataSource<TIdentifier> : TreeViewDataSource<TIdentifier> where TIdentifier : unmanaged, System.IEquatable<TIdentifier>\n    {\n        static readonly List<TreeViewItem<TIdentifier>> s_ChildListForCollapsedParent = new List<TreeViewItem<TIdentifier>>();\n\n        public LazyTreeViewDataSource(TreeViewController<TIdentifier> treeView)\n            : base(treeView)\n        {\n        }\n\n        public static List<TreeViewItem<TIdentifier>> CreateChildListForCollapsedParent()\n        {\n            // To mark a collapsed parent we use a list with one element that is null.\n            // The null element in the children list ensures we show the collapse arrow.\n            // Reuse read-only list to prevent allocations.\n            if (s_ChildListForCollapsedParent.Count != 1 || s_ChildListForCollapsedParent[0] != null)\n            {\n                s_ChildListForCollapsedParent.Clear();\n                s_ChildListForCollapsedParent.Add(null);\n            }\n            return s_ChildListForCollapsedParent;\n        }\n\n        public static bool IsChildListForACollapsedParent(IList<TreeViewItem<TIdentifier>> childList)\n        {\n            return (childList != null && childList.Count == 1 && childList[0] == null); // see CreateChildListForCollapsedParent\n        }\n\n        // Return all ancestor items of the Item with 'id'\n        protected abstract void GetParentsAbove(TIdentifier id, HashSet<TIdentifier> parentsAbove);\n\n        // Return all descendant items that have children from the Item with 'id'\n        protected abstract void GetParentsBelow(TIdentifier id, HashSet<TIdentifier> parentsBelow);\n\n        override public void RevealItem(TIdentifier itemID)\n        {\n            // Get existing expanded in hashset\n            HashSet<TIdentifier> expandedSet = new HashSet<TIdentifier>(expandedIDs);\n            int orgSize = expandedSet.Count;\n\n            // Add all parents above id\n            GetParentsAbove(itemID, expandedSet);\n\n            if (orgSize != expandedSet.Count)\n            {\n                // Bulk set expanded ids (is sorted in SetExpandedIDs)\n                SetExpandedIDs(expandedSet.ToArray());\n\n                // Refresh immediately if any Item was expanded\n                if (m_NeedRefreshRows)\n                    FetchData();\n            }\n        }\n\n        override public void RevealItems(TIdentifier[] itemIDs)\n        {\n            // Get existing expanded in hashset\n            HashSet<TIdentifier> expandedSet = new HashSet<TIdentifier>(expandedIDs);\n            int orgSize = expandedSet.Count;\n\n            foreach (var itemID in itemIDs)\n                // Add all parents above id\n                GetParentsAbove(itemID, expandedSet);\n\n            if (orgSize != expandedSet.Count)\n            {\n                // Bulk set expanded ids (is sorted in SetExpandedIDs)\n                SetExpandedIDs(expandedSet.ToArray());\n\n                // Refresh immediately if any Item was expanded\n                if (m_NeedRefreshRows)\n                    FetchData();\n            }\n        }\n\n        override public TreeViewItem<TIdentifier> FindItem(TIdentifier itemID)\n        {\n            // Since this is a LazyTreeViewDataSource that only knows about expanded items\n            // we need to reveal the item before searching for it (expand its ancestors)\n            RevealItem(itemID);\n\n            // Now find the item after we have expanded and created parent items\n            return base.FindItem(itemID);\n        }\n\n        override public void SetExpandedWithChildren(TreeViewItem<TIdentifier> item, bool expand)\n        {\n            SetExpandedWithChildren(item.id, expand);\n        }\n\n        // Override for special handling of recursion\n        // We cannot recurse normally to tree Item children because we have not loaded children of collapsed items\n        // therefore let client implement GetParentsBelow to fetch ids instead\n        override public void SetExpandedWithChildren(TIdentifier id, bool expand)\n        {\n            // Get existing expanded in hashset\n            HashSet<TIdentifier> oldExpandedSet = new HashSet<TIdentifier>(expandedIDs);\n\n            // Add all children expanded ids to hashset\n            HashSet<TIdentifier> candidates = new HashSet<TIdentifier>();\n            GetParentsBelow(id, candidates);\n\n            if (expand)     oldExpandedSet.UnionWith(candidates);\n            else            oldExpandedSet.ExceptWith(candidates);\n\n            // Bulk set expanded ids (is sorted in SetExpandedIDs)\n            SetExpandedIDs(oldExpandedSet.ToArray());\n\n            // Keep for debugging\n            // Debug.Log (\"New expanded state (bulk): \" + DebugUtils.ListToString(new List<int>(expandedIDs)));\n        }\n\n        public override void InitIfNeeded()\n        {\n            // Cached for large trees...\n            if (m_Rows == null || m_NeedRefreshRows)\n            {\n                FetchData(); // Only need to fetch visible data..\n\n                m_NeedRefreshRows = false;\n\n                if (onVisibleRowsChanged != null)\n                    onVisibleRowsChanged();\n\n                m_TreeView.Repaint();\n            }\n        }\n\n        // Get the flattened tree of visible items. Use GetFirstAndLastRowVisible to cull invisible items\n        override public IList<TreeViewItem<TIdentifier>> GetRows()\n        {\n            InitIfNeeded();\n            return m_Rows;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/MultiColumnHeader.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public partial class MultiColumnHeader\n    {\n        MultiColumnHeaderState m_State;\n        float m_DividerWidth = 6;\n        Rect m_PreviousRect;\n        bool m_ResizeToFit = false;\n        GUIView m_GUIView;\n        Rect[] m_ColumnRects;\n\n        int m_SelectedColumnIndex = -1; // Selected/Activated column (could be used to initiate a drag)\n        int m_DraggedColumnIndex = -1;  // Column currently being dragged\n        int m_HeaderButtonsControlID;\n        Rect m_TotalHeaderRect;\n\n        public delegate void HeaderCallback(MultiColumnHeader multiColumnHeader);\n        public event HeaderCallback sortingChanged;\n        public event HeaderCallback visibleColumnsChanged;\n        public event Action<int> columnSettingsChanged;\n        public event Action<int, int> columnsSwapped;\n\n        public float height { get; set; } = DefaultGUI.defaultHeight;\n        public bool canSort { get; set; } = true;\n        protected int currentColumnIndex { get; private set; } = -1;\n        protected bool allowDraggingColumnsToReorder { get; set; } = false;\n\n        public int sortedColumnIndex\n        {\n            get { return state.sortedColumnIndex; }\n            set\n            {\n                if (value != state.sortedColumnIndex)\n                {\n                    state.sortedColumnIndex = value;\n                    OnSortingChanged();\n                }\n            }\n        }\n\n        public MultiColumnHeaderState state\n        {\n            get { return m_State; }\n            set\n            {\n                if (value == null)\n                    throw new ArgumentNullException(\"state\", \"MultiColumnHeader state is not allowed to be null\");\n                m_State = value;\n            }\n        }\n\n        public MultiColumnHeader(MultiColumnHeaderState state)\n        {\n            m_State = state;\n            m_HeaderButtonsControlID = GUIUtility.GetPermanentControlID();\n        }\n\n        public void SetSortingColumns(int[] columnIndices, bool[] sortAscending)\n        {\n            if (columnIndices == null)\n                throw new ArgumentNullException(\"columnIndices\");\n\n            if (sortAscending == null)\n                throw new ArgumentNullException(\"sortAscending\");\n\n            if (columnIndices.Length != sortAscending.Length)\n                throw new ArgumentException(\"Input arrays should have same length\");\n\n            if (columnIndices.Length > state.maximumNumberOfSortedColumns)\n                throw new ArgumentException(\"The maximum number of sorted columns is \" + state.maximumNumberOfSortedColumns + \". Trying to set \" + columnIndices.Length + \" columns.\");\n\n            if (columnIndices.Length != columnIndices.Distinct().Count())\n                throw new ArgumentException(\"Duplicate column indices are not allowed\", \"columnIndices\");\n\n            bool changed = false;\n\n            if (!columnIndices.SequenceEqual(state.sortedColumns))\n            {\n                state.sortedColumns = columnIndices;\n                changed = true;\n            }\n\n            for (int i = 0; i < columnIndices.Length; ++i)\n            {\n                var column = GetColumn(columnIndices[i]);\n                if (column.sortedAscending != sortAscending[i])\n                {\n                    column.sortedAscending = sortAscending[i];\n                    changed = true;\n                }\n            }\n\n            if (changed)\n                OnSortingChanged();\n        }\n\n        public void SetSorting(int columnIndex, bool sortAscending)\n        {\n            bool changed = false;\n            if (state.sortedColumnIndex != columnIndex)\n            {\n                state.sortedColumnIndex = columnIndex;\n                changed = true;\n            }\n\n            var column = GetColumn(columnIndex);\n            if (column.sortedAscending != sortAscending)\n            {\n                column.sortedAscending = sortAscending;\n                changed = true;\n            }\n\n            if (changed)\n                OnSortingChanged();\n        }\n\n        public void SetSortDirection(int columnIndex, bool sortAscending)\n        {\n            var column = GetColumn(columnIndex);\n            if (column.sortedAscending != sortAscending)\n            {\n                column.sortedAscending = sortAscending;\n                OnSortingChanged();\n            }\n        }\n\n        public bool IsSortedAscending(int columnIndex)\n        {\n            return GetColumn(columnIndex).sortedAscending;\n        }\n\n        public MultiColumnHeaderState.Column GetColumn(int columnIndex)\n        {\n            if (columnIndex < 0 || columnIndex >= state.columns.Length)\n                throw new ArgumentOutOfRangeException(\"columnIndex\", string.Format(\"columnIndex {0} is not valid when the current column count is {1}\", columnIndex, state.columns.Length));\n            return state.columns[columnIndex];\n        }\n\n        public bool IsColumnVisible(int columnIndex)\n        {\n            foreach (int vc in state.visibleColumns)\n            {\n                if (vc == columnIndex)\n                    return true;\n            }\n            return false;\n        }\n\n        public int GetVisibleColumnIndex(int columnIndex)\n        {\n            for (int i = 0; i < state.visibleColumns.Length; i++)\n            {\n                if (state.visibleColumns[i] == columnIndex)\n                    return i;\n            }\n            string visibleIndices = string.Join(\", \", state.visibleColumns.Select(t => t.ToString()).ToArray());\n            throw new ArgumentException(string.Format(\"Invalid columnIndex: {0}. The index is not part of the current visible columns: {1}\", columnIndex, visibleIndices), \"columnIndex\");\n        }\n\n        public Rect GetCellRect(int visibleColumnIndex, Rect rowRect)\n        {\n            Rect result = GetColumnRect(visibleColumnIndex);\n            result.y = rowRect.y;\n            result.height = rowRect.height;\n            return result;\n        }\n\n        public Rect GetColumnRect(int visibleColumnIndex)\n        {\n            if (visibleColumnIndex < 0 || visibleColumnIndex >= m_ColumnRects.Length)\n                throw new ArgumentException(string.Format(\"The provided visibleColumnIndex is invalid. Ensure the index ({0}) is within the number of visible columns ({1})\", visibleColumnIndex, m_ColumnRects.Length), \"visibleColumnIndex\");\n\n            return m_ColumnRects[visibleColumnIndex];\n        }\n\n        public void ResizeToFit()\n        {\n            m_ResizeToFit = true;\n            Repaint();\n        }\n\n        void UpdateColumnHeaderRects(Rect totalHeaderRect)\n        {\n            if (m_ColumnRects == null || m_ColumnRects.Length != state.visibleColumns.Length)\n                m_ColumnRects = new Rect[state.visibleColumns.Length];\n\n            Rect curRect = totalHeaderRect;\n            for (int v = 0; v < state.visibleColumns.Length; v++)\n            {\n                int columnIndex = state.visibleColumns[v];\n                MultiColumnHeaderState.Column column = state.columns[columnIndex];\n\n                if (v > 0)\n                    curRect.x += curRect.width;\n                curRect.width = column.width;\n\n                m_ColumnRects[v] = curRect;\n            }\n        }\n\n        // Virtual so clients can override header behavior and rendering entirely\n        public virtual void OnGUI(Rect rect, float xScroll)\n        {\n            Event evt = Event.current;\n\n            if (m_GUIView == null)\n                m_GUIView = GUIView.current;\n\n            DetectSizeChanges(rect);\n\n            if (m_ResizeToFit && evt.type == EventType.Repaint)\n            {\n                m_ResizeToFit = false;\n                ResizeColumnsWidthsProportionally(rect.width - GUI.skin.verticalScrollbar.fixedWidth - state.widthOfAllVisibleColumns);\n            }\n\n            // We create a guiclip to let the header be able to scroll horizontally according to the tree view's horizontal scroll\n            // If the tree view is inside a UI Toolkit scroll view, however, we don't need the x scroll offset.\n            Vector2 scrollOffset = Vector2.zero;\n            var container = UIElementsUtility.GetCurrentIMGUIContainer();\n            var uiScrollView = container?.GetFirstAncestorOfType<ScrollView>();\n            if (uiScrollView == null)\n            {\n                scrollOffset = new Vector2(-xScroll, 0f);\n            }\n            GUIClip.Push(rect, scrollOffset, Vector2.zero, false);\n            {\n                Rect localRect = new Rect(0, 0, rect.width, rect.height);\n                m_TotalHeaderRect = localRect;\n\n                // Background ( We always add the width of the vertical scrollbar to accommodate if this is being shown below e.g by a tree view)\n                float widthOfAllColumns = state.widthOfAllVisibleColumns;\n                float backgroundWidth = (localRect.width > widthOfAllColumns ? localRect.width : widthOfAllColumns) + GUI.skin.verticalScrollbar.fixedWidth;\n                Rect backgroundRect = new Rect(0, 0, backgroundWidth, localRect.height);\n                GUI.Label(backgroundRect, GUIContent.none, DefaultStyles.background);\n\n                // Update column rects (cached for clients to have fast access to column rects by using GetCellRect)\n                UpdateColumnHeaderRects(localRect);\n\n                // Columns\n                for (int v = 0; v < state.visibleColumns.Length; v++)\n                {\n                    currentColumnIndex = state.visibleColumns[v];\n\n                    MultiColumnHeaderState.Column column = state.columns[currentColumnIndex];\n\n                    Rect headerRect = m_ColumnRects[v];\n                    const float limitHeightOfDivider = 4f;\n                    Rect dividerRect = new Rect(headerRect.xMax - 1, headerRect.y + limitHeightOfDivider, 1f, headerRect.height - 2 * limitHeightOfDivider);\n\n                    // Context menu\n                    if (evt.type == EventType.ContextClick && headerRect.Contains(evt.mousePosition))\n                    {\n                        evt.Use();\n                        DoContextMenu();\n                    }\n\n                    // Resize columns logic\n                    Rect dragRect = new Rect(dividerRect.x - m_DividerWidth * 0.5f, localRect.y, m_DividerWidth, localRect.height);\n                    bool hasControl;\n                    var newColumnWidth = EditorGUI.WidthResizer(dragRect, column.width, column.minWidth, column.maxWidth, out hasControl);\n                    if (column.width != newColumnWidth)\n                    {\n                        column.width = newColumnWidth;\n                        columnSettingsChanged?.Invoke(currentColumnIndex);\n                    }\n                    if (hasControl && evt.type == EventType.Repaint)\n                    {\n                        DrawColumnResizing(headerRect, column);\n                    }\n\n                    // Draw divider (can be overridden)\n                    DrawDivider(dividerRect, column);\n\n                    // Draw header (can be overridden)\n                    ColumnHeaderGUI(column, headerRect, currentColumnIndex);\n                }\n\n                currentColumnIndex = -1;\n\n                // Context menu when clicked outside of a column header\n                if (evt.type == EventType.ContextClick && backgroundRect.Contains(evt.mousePosition))\n                {\n                    evt.Use();\n                    DoContextMenu();\n                }\n            }\n            GUIClip.Pop();\n        }\n\n        internal virtual void DrawColumnResizing(Rect headerRect, MultiColumnHeaderState.Column column)\n        {\n            const float margin = 1;\n            headerRect.y += margin;\n            headerRect.width -= margin;\n            headerRect.height -= 2 * margin;\n            EditorGUI.DrawRect(headerRect, new Color(0.5f, 0.5f, 0.5f, 0.1f));\n        }\n\n        internal virtual void DrawDivider(Rect dividerRect, MultiColumnHeaderState.Column column)\n        {\n            EditorGUI.DrawRect(dividerRect, new Color(0.5f, 0.5f, 0.5f, 0.5f));\n        }\n\n        protected virtual void ColumnHeaderClicked(MultiColumnHeaderState.Column column, int columnIndex)\n        {\n            if (state.sortedColumnIndex == columnIndex)\n                column.sortedAscending = !column.sortedAscending;\n            else\n                state.sortedColumnIndex = columnIndex;\n\n            OnSortingChanged();\n        }\n\n        protected virtual void OnSortingChanged()\n        {\n            sortingChanged?.Invoke(this);\n        }\n\n        protected virtual void ColumnHeaderGUI(MultiColumnHeaderState.Column column, Rect headerRect, int columnIndex)\n        {\n            var evt = Event.current;\n            SortingButton(column, headerRect, columnIndex);\n\n            GUIStyle style = GetStyle(column.headerTextAlignment);\n\n            float labelHeight = EditorGUI.kWindowToolbarHeight;\n            Rect labelRect = new Rect(headerRect.x, headerRect.yMax - labelHeight, headerRect.width, labelHeight);\n            GUI.Label(labelRect, column.headerContent, style);\n        }\n\n        protected void SortingButton(MultiColumnHeaderState.Column column, Rect headerRect, int columnIndex)\n        {\n            DoSortingButtonAndColumnHeaderDragging(column, headerRect, columnIndex);\n        }\n\n        private void DoSortingButtonAndColumnHeaderDragging(MultiColumnHeaderState.Column column, Rect headerRect, int columnIndex)\n        {\n            var evt = Event.current;\n\n            switch (evt.GetTypeForControl(m_HeaderButtonsControlID))\n            {\n                case EventType.MouseDown:\n                {\n                    bool canBeInteractedWith = allowDraggingColumnsToReorder || (canSort && column.canSort);\n                    if (canBeInteractedWith && evt.button == 0 && GUIUtility.hotControl == 0)\n                    {\n                        var interactionRect = Inflate(headerRect, -10, -1, -10, -1);\n                        if (interactionRect.Contains(evt.mousePosition))\n                        {\n                            GUIUtility.hotControl = m_HeaderButtonsControlID;\n                            m_SelectedColumnIndex = columnIndex;\n                            evt.Use();\n                        }\n                    }\n                }\n                break;\n\n                case EventType.MouseDrag:\n                    if (allowDraggingColumnsToReorder && GUIUtility.hotControl == m_HeaderButtonsControlID)\n                    {\n                        if (m_DraggedColumnIndex == -1)\n                        {\n                            m_DraggedColumnIndex = m_SelectedColumnIndex;\n                            Repaint();\n                        }\n\n                        if (columnIndex == m_DraggedColumnIndex)\n                            return;\n\n                        var columnCenter = headerRect.center;\n                        float min, max;\n                        if (columnIndex < m_DraggedColumnIndex)\n                        {\n                            min = headerRect.x;\n                            max = columnCenter.x;\n                        }\n                        else\n                        {\n                            min = columnCenter.x;\n                            max = headerRect.xMax;\n                        }\n\n                        int visibleColumnIndex = GetVisibleColumnIndex(columnIndex);\n                        if (visibleColumnIndex == 0)\n                            min = float.MinValue;\n                        if (visibleColumnIndex == state.visibleColumns.Length - 1)\n                            max = float.MaxValue;\n\n                        var mousePosX = evt.mousePosition.x;\n                        var foundDragTargetColumn = mousePosX > min && mousePosX < max;\n\n                        if (foundDragTargetColumn)\n                        {\n                            MoveColumn(m_DraggedColumnIndex, columnIndex);\n                            m_DraggedColumnIndex = m_SelectedColumnIndex = columnIndex;\n                            Repaint();\n                            evt.Use();\n                        }\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == m_HeaderButtonsControlID && m_SelectedColumnIndex == columnIndex)\n                    {\n                        var selectedColumnIndex = m_SelectedColumnIndex;\n                        var dragging = m_DraggedColumnIndex >= 0;\n                        m_DraggedColumnIndex = -1;\n                        m_SelectedColumnIndex = -1;\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n\n                        if (canSort && column.canSort && !dragging)\n                        {\n                            if (selectedColumnIndex == columnIndex && headerRect.Contains(evt.mousePosition))\n                            {\n                                ColumnHeaderClicked(column, columnIndex);\n                            }\n                        }\n                    }\n                    break;\n\n                case EventType.Repaint:\n                    if (m_SelectedColumnIndex == columnIndex)\n                    {\n                        EditorGUI.DrawRect(headerRect, new Color(0.5f, 0.5f, 0.5f, 0.1f));\n                    }\n                    if (m_DraggedColumnIndex == columnIndex)\n                    {\n                        EditorGUIUtility.AddCursorRect(new Rect(-100000, -100000, 200000, 200000), MouseCursor.SlideArrow, m_HeaderButtonsControlID);\n                    }\n\n                    // Draw sorting arrow\n                    if (canSort && column.canSort && columnIndex == state.sortedColumnIndex)\n                    {\n                        var arrowRect = GetArrowRect(column, headerRect);\n\n                        Matrix4x4 normalMatrix = GUI.matrix;\n                        if (column.sortedAscending)\n                            GUIUtility.RotateAroundPivot(180, arrowRect.center - new Vector2(0, 1));\n\n                        GUI.Label(arrowRect, \"\\u25BE\", DefaultStyles.arrowStyle);\n\n                        if (column.sortedAscending)\n                            GUI.matrix = normalMatrix;\n                    }\n\n                    break;\n            }\n        }\n\n        internal void MoveColumn(int columnIndex, int targetColumnIndex)\n        {\n            // Swap columns until we reach our target index\n            int dir = targetColumnIndex > columnIndex ? 1 : -1;\n            int curIndex = columnIndex;\n            int count = 0;\n            while (curIndex != targetColumnIndex && count < 1000)\n            {\n                int next = curIndex + dir;\n                state.SwapColumns(curIndex, next);\n\n                UpdateColumnHeaderRects(m_TotalHeaderRect);\n                columnsSwapped?.Invoke(curIndex, next);\n\n                curIndex = next;\n                count++;\n            }\n        }\n\n        internal virtual Rect GetArrowRect(MultiColumnHeaderState.Column column, Rect headerRect)\n        {\n            float sortingArrowWidth = DefaultStyles.arrowStyle.fixedWidth;\n            float arrowYPos = headerRect.y;\n            float arrowXPos = 0f;\n\n            switch (column.sortingArrowAlignment)\n            {\n                case TextAlignment.Left:\n                    arrowXPos = headerRect.x + DefaultStyles.columnHeader.padding.left;\n                    break;\n                case TextAlignment.Center:\n                    arrowXPos = headerRect.x + headerRect.width * 0.5f - sortingArrowWidth * 0.5f;\n                    break;\n                case TextAlignment.Right:\n                    arrowXPos = headerRect.xMax - DefaultStyles.columnHeader.padding.right - sortingArrowWidth;\n                    break;\n                default:\n                    Debug.LogError(\"Unhandled enum\");\n                    break;\n            }\n\n            Rect arrowRect = new Rect(Mathf.Round(arrowXPos), arrowYPos, sortingArrowWidth, 16f);\n            return arrowRect;\n        }\n\n        GUIStyle GetStyle(TextAlignment alignment)\n        {\n            switch (alignment)\n            {\n                case TextAlignment.Left: return DefaultStyles.columnHeader;\n                case TextAlignment.Center: return DefaultStyles.columnHeaderCenterAligned;\n                case TextAlignment.Right: return DefaultStyles.columnHeaderRightAligned;\n                default: return DefaultStyles.columnHeader;\n            }\n        }\n\n        void DoContextMenu()\n        {\n            var menu = new GenericMenu();\n            AddColumnHeaderContextMenuItems(menu);\n            menu.ShowAsContext();\n        }\n\n        protected virtual void AddColumnHeaderContextMenuItems(GenericMenu menu)\n        {\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Resize to Fit\"), false, ResizeToFit);\n\n            menu.AddSeparator(\"\");\n\n            for (int i = 0; i < state.columns.Length; ++i)\n            {\n                var column = state.columns[i];\n                var menuText = !string.IsNullOrEmpty(column.contextMenuText) ? column.contextMenuText : column.headerContent.text;\n                if (column.allowToggleVisibility)\n                    menu.AddItem(new GUIContent(menuText), state.visibleColumns.Contains(i), ToggleVisibility, i);\n                else\n                    menu.AddDisabledItem(new GUIContent(menuText));\n            }\n        }\n\n        protected virtual void OnVisibleColumnsChanged()\n        {\n            visibleColumnsChanged?.Invoke(this);\n        }\n\n        void ToggleVisibility(object userData)\n        {\n            ToggleVisibility((int)userData);\n        }\n\n        protected virtual void ToggleVisibility(int columnIndex)\n        {\n            var newVisibleColumns = new List<int>(state.visibleColumns);\n            if (newVisibleColumns.Contains(columnIndex))\n            {\n                newVisibleColumns.Remove(columnIndex);\n            }\n            else\n            {\n                newVisibleColumns.Add(columnIndex);\n                newVisibleColumns.Sort();\n            }\n            state.visibleColumns = newVisibleColumns.ToArray();\n            Repaint();\n\n            OnVisibleColumnsChanged();\n        }\n\n        public void Repaint()\n        {\n            if (m_GUIView != null)\n                m_GUIView.Repaint();\n        }\n\n        void DetectSizeChanges(Rect rect)\n        {\n            if (Event.current.type == EventType.Repaint)\n            {\n                if (m_PreviousRect.width > 0f)\n                {\n                    float deltaWidth = Mathf.Round(rect.width - m_PreviousRect.width);\n                    if (deltaWidth != 0f)\n                    {\n                        float tep = GUI.skin.verticalScrollbar.fixedWidth;\n                        bool isColumnsVisible = rect.width - tep > state.widthOfAllVisibleColumns;\n                        if (isColumnsVisible || deltaWidth < 0f)\n                            ResizeColumnsWidthsProportionally(deltaWidth);\n                    }\n                }\n                m_PreviousRect = rect;\n            }\n        }\n\n        void ResizeColumnsWidthsProportionally(float deltaWidth)\n        {\n            // Find auto resizing columns\n            List<MultiColumnHeaderState.Column> autoResizeColumns = null;\n            foreach (int i in state.visibleColumns)\n            {\n                MultiColumnHeaderState.Column column = state.columns[i];\n                if (column.autoResize)\n                {\n                    // Ignore the columns that cannot expand anymore\n                    if (deltaWidth > 0f && column.width >= column.maxWidth)\n                        continue;\n                    // Ignore the columns that cannot shrink anymore\n                    if (deltaWidth < 0f && column.width <= column.minWidth)\n                        continue;\n\n                    if (autoResizeColumns == null)\n                        autoResizeColumns = new List<MultiColumnHeaderState.Column>();\n\n                    autoResizeColumns.Add(column);\n                }\n            }\n\n            // Any auto resizing columns?\n            if (autoResizeColumns == null)\n                return;\n\n            // Sum\n            float totalAutoResizeWidth = autoResizeColumns.Sum(x => x.width);\n\n            // Distribute\n            foreach (var column in autoResizeColumns)\n            {\n                column.width += deltaWidth * (column.width / totalAutoResizeWidth);\n                column.width = Mathf.Clamp(column.width, column.minWidth, column.maxWidth);\n            }\n        }\n\n        private static Rect Inflate(Rect a, float left, float top, float right, float bottom)\n        {\n            return new Rect\n            {\n                xMin = a.xMin - left,\n                yMin = a.yMin - top,\n                xMax = a.xMax + right,\n                yMax = a.yMax + bottom\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/MultiColumnHeaderDefaults.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public partial class MultiColumnHeader\n    {\n        public static class DefaultGUI\n        {\n            public static float defaultHeight { get { return 27f; } }\n            public static float minimumHeight { get { return 20f; } }\n            public static float columnContentMargin { get { return 3f; } }\n            internal static float labelSpaceFromBottom { get { return 3; } }\n        }\n\n        public static class DefaultStyles\n        {\n            // Column header uses same colors as label, but slightly dimmed to let list items stand out more (similar to win 10)\n            // Use middle alignment to ensure labels are aligned regardless of icon size\n            public static GUIStyle columnHeader = \"MultiColumnHeader\";\n            public static GUIStyle columnHeaderRightAligned = \"MultiColumnHeaderRight\";\n            public static GUIStyle columnHeaderCenterAligned = \"MultiColumnHeaderCenter\";\n            public static GUIStyle background = \"MultiColumnTopBar\"; // Use bar background with 1 pixel line at the bottom to let items have someting to clip against when scrolled\n            // Arrow uses same colors as label (derived) aligned at top\n            internal static GUIStyle arrowStyle = \"MultiColumnArrow\";\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/MultiColumnHeaderState.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    [Serializable]\n    public class MultiColumnHeaderState\n    {\n        [SerializeField] Column[] m_Columns;\n        [SerializeField] int[] m_VisibleColumns;\n        [SerializeField] List<int> m_SortedColumns;               // First item is most recent\n        [NonSerialized] int m_MaxNumberOfSortedColumns = 3;\n\n        [Serializable]\n        public class Column\n        {\n            [SerializeField] public float width = 50;\n            [SerializeField] public bool sortedAscending;\n            [SerializeField] public GUIContent headerContent = new GUIContent();\n            [SerializeField] public string contextMenuText;\n            [SerializeField] public TextAlignment headerTextAlignment = TextAlignment.Left;\n            [SerializeField] public TextAlignment sortingArrowAlignment = TextAlignment.Center;\n            [SerializeField] public float minWidth = 20;\n            [SerializeField] public float maxWidth = 1000000f;\n            [SerializeField] public bool autoResize = true;\n            [SerializeField] public bool allowToggleVisibility = true;\n            [SerializeField] public bool canSort = true;\n            [SerializeField] public int userData;\n            [NonSerialized] internal object userDataObj;\n        }\n\n        public static bool CanOverwriteSerializedFields(MultiColumnHeaderState source, MultiColumnHeaderState destination)\n        {\n            if (source == null || destination == null)\n                return false;\n\n            if (source.m_Columns == null || destination.m_Columns == null)\n                return false;\n\n            if (source.m_Columns.GetType() != destination.m_Columns.GetType())\n                return false;\n\n            return source.m_Columns.Length == destination.m_Columns.Length;\n        }\n\n        public static void OverwriteSerializedFields(MultiColumnHeaderState source, MultiColumnHeaderState destination)\n        {\n            if (!CanOverwriteSerializedFields(source, destination))\n            {\n                Debug.LogError(\"MultiColumnHeaderState: Not able to overwrite serialized fields\");\n                return;\n            }\n\n            destination.m_VisibleColumns = source.m_VisibleColumns.ToArray();\n            destination.m_SortedColumns = new List<int>(source.m_SortedColumns);\n\n            for (int i = 0; i < destination.m_Columns.Length; ++i)\n            {\n                destination.m_Columns[i].width = source.m_Columns[i].width;\n                destination.m_Columns[i].sortedAscending = source.m_Columns[i].sortedAscending;\n            }\n        }\n\n        public MultiColumnHeaderState(Column[] columns)\n        {\n            if (columns == null)\n                throw new ArgumentException(\"columns are no allowed to be null\", \"columns\");\n            if (columns.Length == 0)\n                throw new ArgumentException(\"columns array should at least have one column: it is empty\", \"columns\");\n\n            m_Columns = columns;\n            m_SortedColumns = new List<int>();\n\n            // Default to all visible\n            m_VisibleColumns = new int[m_Columns.Length];\n            for (int i = 0; i < m_Columns.Length; ++i)\n                m_VisibleColumns[i] = i;\n        }\n\n        public int sortedColumnIndex\n        {\n            get\n            {\n                return m_SortedColumns.Count > 0 ? m_SortedColumns[0] : -1;\n            }\n            set\n            {\n                int current = m_SortedColumns.Count > 0 ? m_SortedColumns[0] : -1;\n                if (value != current)\n                {\n                    if (value >= 0)\n                    {\n                        m_SortedColumns.Remove(value);\n                        m_SortedColumns.Insert(0, value);\n                    }\n                    else\n                    {\n                        m_SortedColumns.Clear();\n                    }\n                }\n            }\n        }\n\n        internal void SwapColumns(int columnIndex, int targetColumnIndex)\n        {\n            if (Mathf.Abs(columnIndex - targetColumnIndex) != 1)\n                throw new ArgumentException(\"SwapColumn is only supported for columns next to each other otherwise visible columns and sorted columns will be incorrect. Column index \" + columnIndex + \", targetColumnIndex \" + targetColumnIndex);\n\n            // Swap columns\n            var temp = columns[columnIndex];\n            columns[columnIndex] = columns[targetColumnIndex];\n            columns[targetColumnIndex] = temp;\n\n            // Swap visible columns state so it matches swapped columns above\n            for (int i = 0; i < m_VisibleColumns.Length; i++)\n            {\n                if (m_VisibleColumns[i] == columnIndex)\n                    m_VisibleColumns[i] = targetColumnIndex;\n                else if (m_VisibleColumns[i] == targetColumnIndex)\n                    m_VisibleColumns[i] = columnIndex;\n            }\n            var list = new List<int>(m_VisibleColumns);\n            list.Sort();\n            m_VisibleColumns = list.ToArray();\n\n            // Swap sorted column state so it matches swapped columns above\n            for (int i = 0; i < m_SortedColumns.Count; i++)\n            {\n                if (m_SortedColumns[i] == columnIndex)\n                    m_SortedColumns[i] = targetColumnIndex;\n                else if (m_SortedColumns[i] == targetColumnIndex)\n                    m_SortedColumns[i] = columnIndex;\n            }\n        }\n\n        void RemoveInvalidSortingColumnsIndices()\n        {\n            m_SortedColumns.RemoveAll(x => x >= m_Columns.Length);\n            if (m_SortedColumns.Count > m_MaxNumberOfSortedColumns)\n                m_SortedColumns.RemoveRange(m_MaxNumberOfSortedColumns, m_SortedColumns.Count - m_MaxNumberOfSortedColumns);\n        }\n\n        public int maximumNumberOfSortedColumns\n        {\n            get { return m_MaxNumberOfSortedColumns; }\n            set\n            {\n                m_MaxNumberOfSortedColumns = value;\n                RemoveInvalidSortingColumnsIndices();\n            }\n        }\n\n        public int[] sortedColumns\n        {\n            get { return m_SortedColumns.ToArray(); }\n            set\n            {\n                m_SortedColumns = value == null ? new List<int>() : new List<int>(value);\n                RemoveInvalidSortingColumnsIndices();\n            }\n        }\n\n        public Column[] columns\n        {\n            get { return m_Columns; }\n        }\n\n        public int[] visibleColumns\n        {\n            get { return m_VisibleColumns; }\n            set\n            {\n                if (value == null)\n                    throw new ArgumentException(\"visibleColumns should not be set to null\");\n                if (value.Length == 0)\n                    throw new ArgumentException(\"visibleColumns should should not be set to an empty array. At least one visible column is required.\");\n                m_VisibleColumns = value;\n            }\n        }\n\n        public float widthOfAllVisibleColumns\n        {\n            get { return visibleColumns.Sum(t => columns[t].width); }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/SubSceneGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor;\nusing UnityEditor.SceneManagement;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\n\nstatic class SubSceneGUI\n{\n    static Dictionary<GameObject, SceneHierarchyHooks.SubSceneInfo> m_SubSceneHeadersMap = new Dictionary<GameObject, SceneHierarchyHooks.SubSceneInfo>();\n    static Dictionary<Scene, SceneHierarchyHooks.SubSceneInfo> m_SceneToSubSceneMap = new Dictionary<Scene, SceneHierarchyHooks.SubSceneInfo>();\n    static Dictionary<SceneAsset, SceneHierarchyHooks.SubSceneInfo> m_SceneAssetToSubSceneMap = new Dictionary<SceneAsset, SceneHierarchyHooks.SubSceneInfo>();\n    const int kMaxSubSceneIterations = 100;\n    static float s_HalfFoldoutWidth = 6f;\n    static float s_SubSceneHeaderIndentAdjustment = -2f;\n\n    internal static void FetchSubSceneInfo()\n    {\n        if (SceneHierarchyHooks.provideSubScenes != null)\n        {\n            m_SubSceneHeadersMap = new Dictionary<GameObject, SceneHierarchyHooks.SubSceneInfo>();\n            m_SceneToSubSceneMap = new Dictionary<Scene, SceneHierarchyHooks.SubSceneInfo>();\n            m_SceneAssetToSubSceneMap = new Dictionary<SceneAsset, SceneHierarchyHooks.SubSceneInfo>();\n\n            var subSceneInfos = SceneHierarchyHooks.provideSubScenes();\n            foreach (var subSceneInfo in subSceneInfos)\n            {\n                if (subSceneInfo.transform == null)\n                {\n                    Debug.LogError(\"Invalid Transform\");\n                    continue;\n                }\n\n                m_SubSceneHeadersMap[subSceneInfo.transform.gameObject] = subSceneInfo;\n\n                if (subSceneInfo.scene.IsValid())\n                    m_SceneToSubSceneMap[subSceneInfo.scene] = subSceneInfo;\n                if (subSceneInfo.sceneAsset)\n                    m_SceneAssetToSubSceneMap[subSceneInfo.sceneAsset] = subSceneInfo;\n            }\n        }\n    }\n\n    internal static bool IsUsingSubScenes()\n    {\n        return SceneHierarchyHooks.provideSubScenes != null;\n    }\n\n    static Transform GetParentCheckSubScenes(Transform transform)\n    {\n        if (transform.parent == null)\n        {\n            SceneHierarchyHooks.SubSceneInfo subScene;\n            if (m_SceneToSubSceneMap.TryGetValue(transform.gameObject.scene, out subScene))\n                return subScene.transform;\n            else\n                return null; // Reached root of a root scene\n        }\n\n        return transform.parent;\n    }\n\n    internal static bool IsChildOrSameAsOtherTransform(Transform transform, Transform otherTransform)\n    {\n        if (IsUsingSubScenes())\n        {\n            Transform current = transform;\n            int i = 0;\n            while (current != null && i++ < kMaxSubSceneIterations)\n            {\n                if (current == otherTransform)\n                    return true;\n\n                current = GetParentCheckSubScenes(current);\n            }\n\n            if (i >= kMaxSubSceneIterations)\n                Debug.LogError(\"Recursive SubScene setup detected. Report a bug.\");\n        }\n        else\n        {\n            Transform current = transform;\n            while (current != null)\n            {\n                if (current == otherTransform)\n                    return true;\n\n                current = current.parent;\n            }\n        }\n        return false;\n    }\n\n    internal static bool IsSubSceneHeader(GameObject gameObject)\n    {\n        return IsUsingSubScenes() && m_SubSceneHeadersMap.ContainsKey(gameObject);\n    }\n\n    internal static void CreateClosedSubSceneContextClick(GenericMenu menu, SceneHierarchyHooks.SubSceneInfo subScene)\n    {\n        var selectAssetContent = EditorGUIUtility.TrTextContent(\"Select Scene Asset\");\n        if (subScene.sceneAsset)\n            menu.AddItem(selectAssetContent, false, SelectSceneAsset, subScene.sceneAsset);\n        else\n            menu.AddDisabledItem(selectAssetContent);\n    }\n\n    static void SelectSceneAsset(object userData)\n    {\n        SceneAsset sceneAssetObject = (SceneAsset)userData;\n        Selection.activeObject = sceneAssetObject;\n        EditorGUIUtility.PingObject(sceneAssetObject);\n    }\n\n    internal static string GetSubSceneHeaderText(GameObject gameObject)\n    {\n        SceneHierarchyHooks.SubSceneInfo subScene;\n        if (m_SubSceneHeadersMap.TryGetValue(gameObject, out subScene))\n        {\n            if (SceneHierarchyHooks.provideSubSceneName != null)\n                return SceneHierarchyHooks.provideSubSceneName(subScene);\n\n            return subScene.sceneName;\n        }\n\n        return null;\n    }\n\n    internal static bool UseBoldFontForGameObject(GameObject gameObject)\n    {\n        SceneHierarchyHooks.SubSceneInfo subScene;\n        if (m_SubSceneHeadersMap.TryGetValue(gameObject, out subScene))\n        {\n            return subScene.scene == SceneManager.GetActiveScene();\n        }\n        return false;\n    }\n\n    internal static SceneHierarchyHooks.SubSceneInfo GetSubSceneInfo(Scene scene)\n    {\n        SceneHierarchyHooks.SubSceneInfo subScene;\n        if (m_SceneToSubSceneMap.TryGetValue(scene, out subScene))\n            return subScene;\n\n        return default(SceneHierarchyHooks.SubSceneInfo);\n    }\n\n    internal static SceneHierarchyHooks.SubSceneInfo GetSubSceneInfo(SceneAsset sceneAsset)\n    {\n        SceneHierarchyHooks.SubSceneInfo subScene;\n        if (m_SceneAssetToSubSceneMap.TryGetValue(sceneAsset, out subScene))\n            return subScene;\n\n        return default(SceneHierarchyHooks.SubSceneInfo);\n    }\n\n    internal static SceneHierarchyHooks.SubSceneInfo GetSubSceneInfo(GameObject gameObject)\n    {\n        SceneHierarchyHooks.SubSceneInfo subScene;\n        if (gameObject != null && m_SubSceneHeadersMap.TryGetValue(gameObject, out subScene))\n            return subScene;\n\n        return default(SceneHierarchyHooks.SubSceneInfo);\n    }\n\n    internal static Color GetColorForSubScene(Scene scene)\n    {\n        SceneHierarchyHooks.SubSceneInfo subScene;\n        if (m_SceneToSubSceneMap.TryGetValue(scene, out subScene))\n            return subScene.color;\n\n        return Color.grey;\n    }\n\n    internal static Scene GetSubScene(GameObject gameObject)\n    {\n        SceneHierarchyHooks.SubSceneInfo subScene;\n        if (m_SubSceneHeadersMap.TryGetValue(gameObject, out subScene))\n            return subScene.scene;\n\n        return default(Scene);\n    }\n\n    internal static void DrawSubSceneHeaderBackground(Rect rect, float baseIndent, float indentWidth, GameObject gameObject)\n    {\n        float indent = CalcIndentOfSubSceneHeader(gameObject, baseIndent, indentWidth);\n        if (indent < 0)\n        {\n            Debug.LogError(\"Only call DrawSubSceneHeaderBackground if IsSubSceneHeader() is true\");\n            return;\n        }\n        Rect headerRect = rect;\n        headerRect.xMin += indent;\n\n        Color oldColor = GUI.color;\n        GUI.color = GUI.color * new Color(1, 1, 1, 0.9f); // dimmed compared to main scene headers\n        GUI.Label(headerRect, GUIContent.none, GameObjectTreeViewGUI.GameObjectStyles.sceneHeaderBg);\n        GUI.color = oldColor;\n    }\n\n    static float CalcIndentOfSubSceneHeader(GameObject gameObject, float baseIndent, float indentWidth)\n    {\n        SceneHierarchyHooks.SubSceneInfo subSceneInfo;\n        if (gameObject == null || !m_SubSceneHeadersMap.TryGetValue(gameObject, out subSceneInfo))\n            return -1;  // Input is not a sub scene GameObject\n\n        int hierarchyDepth = CalculateHierarchyDepthOfSubScene(subSceneInfo);\n        if (hierarchyDepth > 0)\n        {\n            return baseIndent + s_SubSceneHeaderIndentAdjustment + (hierarchyDepth * indentWidth);\n        }\n        return -1f;\n    }\n\n    // Temp cache for optimizing vertical line drawing\n    static SceneHierarchyHooks.SubSceneInfo s_LastSubSceneInfo;\n    static Rect s_LastRectCalculated;\n\n    internal static Rect GetRectForVerticalLine(Rect rowRect, float baseIndent, float indentWidth, Scene scene)\n    {\n        // Fast path: reuse last rect if same scene\n        if (s_LastSubSceneInfo.isValid && s_LastSubSceneInfo.scene == scene)\n        {\n            s_LastRectCalculated.y = rowRect.y;\n            return s_LastRectCalculated;\n        }\n\n        // Reset and calculate new rect\n        s_LastRectCalculated = new Rect();\n        if (!m_SceneToSubSceneMap.TryGetValue(scene, out s_LastSubSceneInfo))\n            return new Rect();\n\n        if (s_LastSubSceneInfo.color.a == 0)\n            return new Rect();\n\n        float indent = CalcIndentOfVerticalLine(s_LastSubSceneInfo, baseIndent, indentWidth);\n        if (indent < 0)\n            return new Rect();\n\n        s_LastRectCalculated = rowRect;\n        s_LastRectCalculated.x +=  indent;\n        s_LastRectCalculated.width = 1;\n\n        return s_LastRectCalculated;\n    }\n\n    internal static void DrawVerticalLine(Rect rowRect, float baseIndent, float indentWidth, GameObject gameObject)\n    {\n        if (gameObject == null)\n            return;\n\n        if (Event.current.type == EventType.Repaint)\n        {\n            Scene scene = gameObject.scene;\n            Rect lineRect = GetRectForVerticalLine(rowRect, baseIndent, indentWidth, scene);\n            if (lineRect.width > 0f)\n            {\n                Color color = GetColorForSubScene(scene);\n                GUI.DrawTexture(lineRect, EditorGUIUtility.whiteTexture, ScaleMode.StretchToFill, true, 1, color, color, color, color, Vector4.zero, Vector4.zero, false);\n            }\n        }\n    }\n\n    static float CalcIndentOfVerticalLine(SceneHierarchyHooks.SubSceneInfo subSceneInfo, float baseIndent, float indentWidth)\n    {\n        int hierarchyDepth = CalculateHierarchyDepthOfSubScene(subSceneInfo);\n        if (hierarchyDepth > 0)\n        {\n            return baseIndent + hierarchyDepth * indentWidth + s_HalfFoldoutWidth;\n        }\n        return -1f;\n    }\n\n    internal static int CalculateHierarchyDepthOfSubScene(SceneHierarchyHooks.SubSceneInfo subSceneInfo)\n    {\n        if (!subSceneInfo.isValid)\n            return -1;\n\n        int hierarchyDepth = 0;\n        int i = 0;\n        while (i++ < kMaxSubSceneIterations)\n        {\n            hierarchyDepth += FindTransformDepth(subSceneInfo.transform) + 1;  // the +1 is for the SubScene header\n            if (!m_SceneToSubSceneMap.TryGetValue(subSceneInfo.transform.gameObject.scene, out subSceneInfo))\n                break;\n        }\n\n        if (i >= kMaxSubSceneIterations)\n            Debug.LogError(\"Recursive SubScene setup detected. Report a bug.\");\n\n        return hierarchyDepth;\n    }\n\n    static int FindTransformDepth(Transform transform)\n    {\n        var trans = transform.parent;\n        int depth = 0;\n        while (trans != null)\n        {\n            depth++;\n            trans = trans.parent;\n        }\n        return depth;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/ToggleTreeView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Text.RegularExpressions;\nusing UnityEditor;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing TreeView = UnityEditor.IMGUI.Controls.TreeView<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\ninternal abstract class ToggleTreeViewItem : TreeViewItem\n{\n    public abstract bool nodeState { get; set; }\n}\n\ninternal class ToggleTreeView<T> : TreeView where T : ToggleTreeViewItem, new()\n{\n    static class Styles\n    {\n        public static readonly GUIContent toggleAll = EditorGUIUtility.TrTextContent(\"Toggle All\");\n        public static readonly GUIContent expandAll = EditorGUIUtility.TrTextContent(\"Expand All\");\n        public static readonly GUIContent collapseAll = EditorGUIUtility.TrTextContent(\"Collapse All\");\n        public static readonly GUIContent toggle = EditorGUIUtility.TrTextContent(\"\", \"Maintain Alt/Option key to enable or disable all children\");\n        public static readonly GUIContent filterSelected = new GUIContent(EditorGUIUtility.FindTexture(\"FilterSelectedOnly\"), \"Filter selected only\");\n    }\n\n    static string s_Regex = \"(?:(.*) |^)(s:)(false|true)(?: (.*)|$)\";\n\n    Func<T> m_RebuildRoot;\n    List<TreeViewItem> m_DefaultRows;\n\n    public enum Column\n    {\n        Enabled,\n        Name,\n    }\n\n    public ToggleTreeView(TreeViewState state, MultiColumnHeader multiColumnHeader, Func<T> rebuildRoot)\n        : base(state, multiColumnHeader)\n    {\n        m_RebuildRoot = rebuildRoot;\n        columnIndexForTreeFoldouts = 1;\n        useScrollView = false;\n        multiColumnHeader.canSort = false;\n        multiColumnHeader.height = 18f;\n        showBorder = true;\n        showAlternatingRowBackgrounds = true;\n\n        foldoutOverride = DoFoldoutButtonOverride;\n\n        Reload();\n    }\n\n    bool hasNodes => rootItem != null && rootItem.hasChildren;\n\n    public float totalHeightIncludingSearchBarAndBottomBar => totalHeight + 18f + EditorGUI.kSingleLineHeight;\n\n    protected override IList<TreeViewItem> BuildRows(TreeViewItem root)\n    {\n        // Reuse cached list (for capacity)\n        if (m_DefaultRows == null)\n            m_DefaultRows = new List<TreeViewItem>(100);\n        m_DefaultRows.Clear();\n\n        if (hasSearch)\n            SearchFullTree(m_DefaultRows);\n        else\n            AddExpandedRows(root, m_DefaultRows);\n        return m_DefaultRows;\n    }\n\n    void SearchFullTree(List<TreeViewItem> rows)\n    {\n        if (rows == null)\n            throw new ArgumentException(\"Invalid list: cannot be null\", nameof(rows));\n\n        var search = searchString;\n        bool searchEnabledState = false;\n        bool searchedEnabledState = false;\n        var match = Regex.Match(search, s_Regex);\n        if (match.Success)\n        {\n            search = match.Groups[1].Value + match.Groups[4].Value;\n            searchEnabledState = true;\n            searchedEnabledState = match.Groups[3].Value == \"true\";\n        }\n\n        var stack = new Stack<TreeViewItem>();\n        stack.Push(rootItem);\n        while (stack.Count > 0)\n        {\n            TreeViewItem current = stack.Pop();\n            if (current.children != null)\n            {\n                foreach (var child in current.children)\n                {\n                    if (child != null)\n                    {\n                        if (!searchEnabledState || ((ToggleTreeViewItem)child).nodeState == searchedEnabledState)\n                            if (DoesItemMatchSearch(child, search))\n                                rows.Add(child);\n\n                        stack.Push(child);\n                    }\n                }\n            }\n        }\n\n        rows.Sort((x, y) => EditorUtility.NaturalCompare(x.displayName, y.displayName));\n    }\n\n    protected override bool DoesItemMatchSearch(TreeViewItem item, string search)\n    {\n        return string.IsNullOrEmpty(search) || base.DoesItemMatchSearch(item, search);\n    }\n\n    public override void OnGUI(Rect rect)\n    {\n        using (new EditorGUILayout.VerticalScope())\n        {\n            DrawSearchField();\n            DrawTreeViewGUI();\n            BottomGUI();\n        }\n    }\n\n    void DrawTreeViewGUI()\n    {\n        base.OnGUI(GUILayoutUtility.GetRect(0, totalHeight));\n        if (HasFocus() && Event.current.type == EventType.KeyDown\n            && (Event.current.keyCode == KeyCode.Space || Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter))\n        {\n            Event.current.Use();\n            var nodes = GetSelection();\n            if (nodes.Count > 0)\n            {\n                var firstNode = (T)FindItem(nodes[0], rootItem);\n                bool value = !firstNode.nodeState;\n                firstNode.nodeState = value;\n                for (var i = 1; i < nodes.Count; i++)\n                {\n                    var node = (T)FindItem(nodes[i], rootItem);\n                    node.nodeState = value;\n                }\n            }\n        }\n    }\n\n    void DrawSearchField()\n    {\n        using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox, GUILayout.MaxHeight(EditorGUI.kWindowToolbarHeight)))\n        {\n            EditorGUI.BeginChangeCheck();\n            var search = EditorGUILayout.ToolbarSearchField(searchString);\n            if (EditorGUI.EndChangeCheck())\n            {\n                bool wasSearching = hasSearch;\n                searchString = search;\n                if (wasSearching && !hasSearch)\n                {\n                    foreach (var item in GetSelection())\n                    {\n                        FrameItem(item);\n                    }\n                }\n            }\n\n            using (new EditorGUI.DisabledScope(Regex.IsMatch(searchString, s_Regex)))\n            {\n                if (GUILayout.Button(Styles.filterSelected, EditorStyles.miniButton, GUILayout.MaxWidth(24f)))\n                    searchString = \"s:true \" + searchString;\n            }\n        }\n    }\n\n    protected virtual void BottomGUI()\n    {\n        using (new EditorGUILayout.HorizontalScope())\n        using (new EditorGUI.DisabledScope(!hasNodes))\n        {\n            if (GUILayout.Button(Styles.toggleAll, EditorStyles.miniButton))\n                ToggleAll();\n\n            var enabledGUI = GUI.enabled;\n            GUI.enabled = hasNodes;\n            if (GUILayout.Button(Styles.collapseAll, EditorStyles.miniButton))\n                CollapseAll();\n\n            if (GUILayout.Button(Styles.expandAll, EditorStyles.miniButton))\n                ExpandAll();\n\n            GUI.enabled = enabledGUI;\n        }\n    }\n\n    protected virtual void ToggleAll()\n    {\n        if (!hasNodes) return;\n        bool value = !((T)rootItem.children[0]).nodeState;\n        PropagateValue((T)rootItem, value);\n    }\n\n    protected override TreeViewItem BuildRoot()\n    {\n        return m_RebuildRoot == null ? new T() { depth = -1, id = 0, displayName = \"\", children = new List<TreeViewItem>() } : m_RebuildRoot();\n    }\n\n    protected override void RowGUI(RowGUIArgs args)\n    {\n        if (!hasNodes)\n        {\n            base.RowGUI(args);\n            return;\n        }\n\n        for (var i = 0; i < args.GetNumVisibleColumns(); ++i)\n        {\n            CellGUI(args.GetCellRect(i), (Column)args.GetColumn(i), (T)args.item, ref args);\n        }\n    }\n\n    void CellGUI(Rect cellRect, Column column, T node, ref RowGUIArgs args)\n    {\n        CenterRectUsingSingleLineHeight(ref cellRect);\n        switch (column)\n        {\n            case Column.Enabled:\n                EnabledGUI(cellRect, node, ref args);\n                break;\n            case Column.Name:\n                NameGUI(cellRect, node, ref args);\n                break;\n        }\n    }\n\n    protected virtual void EnabledGUI(Rect cellRect, T node, ref RowGUIArgs args)\n    {\n        using (var change = new EditorGUI.ChangeCheckScope())\n        {\n            bool isActive = node.nodeState;\n\n            // center the toggle button in the cell\n            cellRect.xMin = cellRect.xMin + cellRect.width / 2f - 8f;\n            isActive = GUI.Toggle(cellRect, isActive, Styles.toggle);\n            if (change.changed)\n            {\n                var selection = GetSelection();\n                if (selection.Contains(node.id))\n                {\n                    var propagate = selection.Count == 1 && Event.current.alt;\n                    foreach (var i in selection)\n                    {\n                        var item = (T)FindItem(i, rootItem);\n                        item.nodeState = isActive;\n                        if (propagate)\n                        {\n                            PropagateValue(item, isActive);\n                        }\n                    }\n                }\n                else\n                {\n                    node.nodeState = isActive;\n                    if (Event.current.alt)\n                    {\n                        PropagateValue(node, isActive);\n                    }\n                }\n            }\n        }\n    }\n\n    protected static void PropagateValue(T node, bool value)\n    {\n        if (node.children == null)\n            return;\n        foreach (var treeViewItem in node.children)\n        {\n            var child = (T)treeViewItem;\n            child.nodeState = value;\n            PropagateValue(child, value);\n        }\n    }\n\n    private static bool DoFoldoutButtonOverride(Rect foldoutRect, bool expandedState, GUIStyle foldoutStyle)\n    {\n        // We need to make sure hierarchyMode is false before drawing the Foldout\n        // or the foldout will be offsetted if the TreeView is inside an inspector.\n        var hierarchy = EditorGUIUtility.hierarchyMode;\n        EditorGUIUtility.hierarchyMode = false;\n        // We need to make sure the indentLevel is 0 before drawing the Foldout\n        // because we want it to ignore current indent level as it was already calculated by the TreeView.\n        var indent = EditorGUI.indentLevel;\n        EditorGUI.indentLevel = 0;\n        // Using EditorGUI.Foldout to keep the foldout active even when the GUI is disabled.\n        var newExpandedValue = EditorGUI.Foldout(foldoutRect, expandedState, GUIContent.none, foldoutStyle);\n        // Restore previous values after the Foldout has been draw.\n        EditorGUI.indentLevel = indent;\n        EditorGUIUtility.hierarchyMode = hierarchy;\n        return newExpandedValue;\n    }\n\n    protected virtual void NameGUI(Rect position, T node, ref RowGUIArgs args)\n    {\n        args.rowRect = position;\n        base.RowGUI(args);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControl.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEngine;\nusing Debug = UnityEngine.Debug;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    // The TreeView is a wrapper for the internal treeview system (wraps the TreeViewController and its 3\n    // interfaces: ITreeViewDataSource, ITreeViewGUI, ITreeViewDragging)\n    // - It is intended for traditional treeviews and listviews (and supports multiple columns)\n    // - Usage:\n    //   - Inherit from TreeView and implement the abtract methods.\n    //   - Override the virtual methods for further customization (rendering, dragging, renaming etc)\n    //   - Adjust layout properties\n\n    public abstract partial class TreeView<TIdentifier> where TIdentifier : unmanaged, System.IEquatable<TIdentifier>\n    {\n        public delegate bool DoFoldoutCallback(Rect position, bool expandedState, GUIStyle style);\n        public delegate List<TIdentifier> GetNewSelectionFunction(TreeViewItem<TIdentifier> clickedItem, bool keepMultiSelection, bool useActionKeyAsShift);\n\n        protected GetNewSelectionFunction getNewSelectionOverride\n        {\n            set { m_TreeView.getNewSelectionOverride = (x, y, z) => value(x, y, z); }\n        }\n\n        internal bool deselectOnUnhandledMouseDown\n        {\n            set\n            {\n                if (m_TreeView != null)\n                    m_TreeView.deselectOnUnhandledMouseDown = value;\n            }\n        }\n\n        internal TreeViewController<TIdentifier> m_TreeView;\n        TreeViewControlDataSource m_DataSource;\n        TreeViewControlGUI m_GUI;\n        TreeViewControlDragging m_Dragging;\n        MultiColumnHeader m_MultiColumnHeader;\n        List<TreeViewItem<TIdentifier>> m_DefaultRows;\n        int m_TreeViewKeyControlID;\n\n        OverriddenMethods m_OverriddenMethods;\n        protected DoFoldoutCallback foldoutOverride { get; set; }\n\n        public TreeView(TreeViewState<TIdentifier> state)\n        {\n            Init(state);\n        }\n\n        public TreeView(TreeViewState<TIdentifier> state, MultiColumnHeader multiColumnHeader)\n        {\n            m_MultiColumnHeader = multiColumnHeader;\n            Init(state);\n        }\n\n        void Init(TreeViewState<TIdentifier> state)\n        {\n            if (state == null)\n                throw new ArgumentNullException(\"state\", \"Invalid TreeViewState: it is null\");\n\n            m_TreeView = new TreeViewController<TIdentifier>(null, state);\n            m_DataSource = new TreeViewControlDataSource(m_TreeView, this);\n            m_GUI = new TreeViewControlGUI(m_TreeView, this);\n            m_Dragging = new TreeViewControlDragging(m_TreeView, this);\n            m_TreeView.Init(new Rect(), m_DataSource, m_GUI, m_Dragging);\n\n            m_TreeView.searchChanged += SearchChanged;\n            m_TreeView.selectionChangedCallback += SelectionChanged;\n            m_TreeView.itemSingleClickedCallback += SingleClickedItem;\n            m_TreeView.itemDoubleClickedCallback += DoubleClickedItem;\n            m_TreeView.contextClickItemCallback += ContextClickedItem;\n            m_TreeView.contextClickOutsideItemsCallback += ContextClicked;\n            m_TreeView.expandedStateChanged += ExpandedStateChanged;\n            m_TreeView.keyboardInputCallback += KeyEvent;\n\n            m_TreeViewKeyControlID = GUIUtility.GetPermanentControlID();\n        }\n\n        // The TreeView can be initialized in two ways:\n        // 1) Full tree: simplest conceptually and requires the least code. Just create the full tree\n        //    in BuildRoot and return the root of tree.\n        // 2) For very large trees that often needs rebuilding of the tree structure it is more\n        //    performant to just create the expanded rows and omitting all items under collapsed items.\n        //    This can be achieved by:\n        //    a) Just create the root item in BuildRoot (no descendants)\n        //    b) Override BuildRows to handle how the rows are generated: Create the rows list\n        //       only visiting expanded items. Also override GetAncestors and GetDescendantsWithChildren\n        //       to use the backend data to fetch this information (since it might not be available in the TreeView)\n        protected abstract TreeViewItem<TIdentifier> BuildRoot();\n\n\n        // Default implementation of BuildRows assumes full tree was built in BuildRoot. With full tree we can also support search out of the box\n        protected virtual IList<TreeViewItem<TIdentifier>> BuildRows(TreeViewItem<TIdentifier> root) => BuildRowsInternal(root);\n        internal virtual IList<TreeViewItem<TIdentifier>> BuildRowsInternal(TreeViewItem<TIdentifier> root)\n        {\n            // Reuse cached list (for capacity)\n            if (m_DefaultRows == null)\n                m_DefaultRows = new List<TreeViewItem<TIdentifier>>(100);\n            m_DefaultRows.Clear();\n\n            if (hasSearch)\n                m_DataSource.SearchFullTree(searchString, m_DefaultRows);\n            else\n                AddExpandedRows(root, m_DefaultRows);\n            return m_DefaultRows;\n        }\n\n        public void Reload()\n        {\n            if (m_OverriddenMethods == null)\n                m_OverriddenMethods = new OverriddenMethods(this);\n            m_TreeView.ReloadData();\n        }\n\n        public void Repaint()\n        {\n            m_TreeView.Repaint();\n        }\n\n        public TreeViewState<TIdentifier> state { get { return m_TreeView.state; } }\n        public MultiColumnHeader multiColumnHeader { get { return m_MultiColumnHeader; } set { m_MultiColumnHeader = value; }}\n\n        // internal for testing\n        internal TreeViewController<TIdentifier> controller => m_TreeView;\n\n        protected TreeViewItem<TIdentifier> rootItem\n        {\n            get { return m_TreeView.data.root; }\n        }\n\n        protected TreeViewItem<TIdentifier> hoveredItem\n        {\n            get { return m_TreeView.hoveredItem; }\n        }\n\n        protected bool enableItemHovering\n        {\n            get { return m_TreeView.enableItemHovering; }\n            set { m_TreeView.enableItemHovering = value; }\n        }\n\n        protected bool isInitialized\n        {\n            get { return m_DataSource.isInitialized; }\n        }\n\n        // Layout variables\n        protected Rect treeViewRect\n        {\n            get { return m_TreeView.GetTotalRect(); }\n            set { m_TreeView.SetTotalRect(value); }\n        }\n\n        protected float baseIndent\n        {\n            get { return m_GUI.k_BaseIndent; }\n            set { m_GUI.k_BaseIndent = value; }\n        }\n\n        internal bool drawSelection\n        {\n            get => m_GUI.drawSelection;\n            set => m_GUI.drawSelection = value;\n        }\n\n        protected float foldoutWidth\n        {\n            get { return m_GUI.foldoutWidth; }\n        }\n\n        protected float extraSpaceBeforeIconAndLabel\n        {\n            get { return m_GUI.extraSpaceBeforeIconAndLabel; }\n            set { m_GUI.extraSpaceBeforeIconAndLabel = value; }\n        }\n\n        protected float customFoldoutYOffset\n        {\n            get { return m_GUI.customFoldoutYOffset; }\n            set { m_GUI.customFoldoutYOffset = value; }\n        }\n\n        protected int columnIndexForTreeFoldouts\n        {\n            get { return m_GUI.columnIndexForTreeFoldouts; }\n            set\n            {\n                if (multiColumnHeader == null)\n                    throw new InvalidOperationException(\"Setting columnIndexForTreeFoldouts can only be set when using TreeView with a MultiColumnHeader\");\n\n                if (value < 0 || value >= multiColumnHeader.state.columns.Length)\n                    throw new ArgumentOutOfRangeException(\"value\", string.Format(\"Invalid index for columnIndexForTreeFoldouts: {0}. Number of available columns: {1}\", value, multiColumnHeader.state.columns.Length));\n\n                m_GUI.columnIndexForTreeFoldouts = value;\n            }\n        }\n\n        protected bool useScrollView\n        {\n            get { return m_TreeView.useScrollView; }\n            set { m_TreeView.useScrollView = value; }\n        }\n\n        protected Rect GetCellRectForTreeFoldouts(Rect rowRect)\n        {\n            if (multiColumnHeader == null)\n                throw new InvalidOperationException(\"GetCellRect can only be called when 'multiColumnHeader' has been set\");\n\n            int columnIndex = columnIndexForTreeFoldouts;\n            int visibleColumnIndex = multiColumnHeader.GetVisibleColumnIndex(columnIndex);\n            return multiColumnHeader.GetCellRect(visibleColumnIndex, rowRect);\n        }\n\n        protected float depthIndentWidth\n        {\n            get { return m_GUI.k_IndentWidth; }\n            set { m_GUI.k_IndentWidth = value; }\n        }\n\n        protected bool showAlternatingRowBackgrounds { get; set; }\n        protected bool showBorder { get; set; }\n        protected bool showingHorizontalScrollBar { get { return m_TreeView.showingHorizontalScrollBar; }}\n        protected bool showingVerticalScrollBar { get { return m_TreeView.showingVerticalScrollBar; } }\n\n        protected float cellMargin\n        {\n            get { return m_GUI.cellMargin; }\n            set { m_GUI.cellMargin = value; }\n        }\n\n        public float totalHeight\n        {\n            get { return m_GUI.totalHeight + (showBorder ? m_GUI.borderWidth * 2 : 0f); }\n        }\n\n        protected float rowHeight\n        {\n            get { return m_GUI.k_LineHeight; }\n            set { m_GUI.k_LineHeight = Mathf.Max(value, EditorGUIUtility.singleLineHeight); }\n        }\n\n        public int treeViewControlID\n        {\n            get { return m_TreeViewKeyControlID; }\n            set { m_TreeViewKeyControlID = value; }\n        }\n\n        protected bool isDragging\n        {\n            get { return m_TreeView.isDragging; }\n        }\n\n        protected Rect GetRowRect(int row)\n        {\n            return m_TreeView.gui.GetRowRect(row, GUIClip.visibleRect.width);\n        }\n\n        public virtual IList<TreeViewItem<TIdentifier>> GetRows() => GetRowsInternal();\n\n        internal virtual IList<TreeViewItem<TIdentifier>> GetRowsInternal()\n        {\n            if (!isInitialized)\n                return null;\n\n            return m_TreeView.data.GetRows();\n        }\n\n        protected IList<TreeViewItem<TIdentifier>> FindRows(IList<TIdentifier> ids)\n        {\n            return GetRows().Where(item => ids.Contains(item.id)).ToList();\n        }\n\n        protected TreeViewItem<TIdentifier> FindItem(TIdentifier id, TreeViewItem<TIdentifier> searchFromThisItem)\n        {\n            return TreeViewUtility<TIdentifier>.FindItem(id, searchFromThisItem);\n        }\n\n        protected int FindRowOfItem(TreeViewItem<TIdentifier> item)\n        {\n            return GetRows().IndexOf(item);\n        }\n\n        protected void GetFirstAndLastVisibleRows(out int firstRowVisible, out int lastRowVisible)\n        {\n            m_GUI.GetFirstAndLastRowVisible(out firstRowVisible, out lastRowVisible);\n        }\n\n        // Expanded interface\n        public void ExpandAll()\n        {\n            SetExpandedRecursive(rootItem.id, true);\n        }\n\n        public void CollapseAll()\n        {\n            SetExpanded(new TIdentifier[0]);\n        }\n\n        public void SetExpandedRecursive(TIdentifier id, bool expanded)\n        {\n            m_DataSource.SetExpandedWithChildren(id, expanded);\n        }\n\n        public bool SetExpanded(TIdentifier id, bool expanded)\n        {\n            return m_DataSource.SetExpanded(id, expanded);\n        }\n\n        public void SetExpanded(IList<TIdentifier> ids)\n        {\n            m_DataSource.SetExpandedIDs(ids.ToArray());\n        }\n\n        public IList<TIdentifier> GetExpanded()\n        {\n            return m_DataSource.GetExpandedIDs();\n        }\n\n        public bool IsExpanded(TIdentifier id)\n        {\n            return m_DataSource.IsExpanded(id);\n        }\n\n        // Search interface\n        public bool hasSearch\n        {\n            get { return !string.IsNullOrEmpty(searchString); }\n        }\n\n        public string searchString\n        {\n            get { return m_TreeView.searchString; }\n            set { m_TreeView.searchString = value; }\n        }\n\n        // Selection interface\n        public IList<TIdentifier> GetSelection()\n        {\n            return m_TreeView.GetSelection();\n        }\n\n        public void SetSelection(IList<TIdentifier> selectedIDs)\n        {\n            SetSelection(selectedIDs, TreeViewSelectionOptions.None);\n        }\n\n        public void SetSelection(IList<TIdentifier> selectedIDs, TreeViewSelectionOptions options)\n        {\n            bool fireSelectionChanged = (options & TreeViewSelectionOptions.FireSelectionChanged) != 0;\n            bool revealSelectionAndFrameLastSelected = (options & TreeViewSelectionOptions.RevealAndFrame) != 0;\n            bool animatedFraming = false;\n\n            m_TreeView.SetSelection(selectedIDs.ToArray(), revealSelectionAndFrameLastSelected, animatedFraming);\n            if (fireSelectionChanged)\n                m_TreeView.NotifyListenersThatSelectionChanged();\n        }\n\n        public bool IsSelected(TIdentifier id)\n        {\n            return m_TreeView.IsSelected(id);\n        }\n\n        public bool HasSelection()\n        {\n            return m_TreeView.HasSelection();\n        }\n\n        public bool HasFocus()\n        {\n            return m_TreeView.HasFocus();\n        }\n\n        public void SetFocus()\n        {\n            GUIUtility.keyboardControl = m_TreeViewKeyControlID;\n            EditorGUIUtility.editingTextField = false;\n        }\n\n        public void SetFocusAndEnsureSelectedItem()\n        {\n            SetFocus();\n\n            if (GetRows().Count > 0)\n            {\n                if (m_TreeView.IsLastClickedPartOfRows())\n                    FrameItem(state.lastClickedID);\n                else\n                    SetSelection(new[] { GetRows()[0].id }, TreeViewSelectionOptions.FireSelectionChanged | TreeViewSelectionOptions.RevealAndFrame);\n            }\n        }\n\n        protected void SelectionClick(TreeViewItem<TIdentifier> item, bool keepMultiSelection)\n        {\n            m_TreeView.SelectionClick(item, keepMultiSelection);\n        }\n\n        // Rename interface\n        public bool BeginRename(TreeViewItem<TIdentifier> item)\n        {\n            return BeginRename(item, 0f);\n        }\n\n        public bool BeginRename(TreeViewItem<TIdentifier> item, float delay)\n        {\n            return m_GUI.BeginRename(item, delay);\n        }\n\n        public void EndRename()\n        {\n            m_GUI.EndRename();\n        }\n\n        // Frame interface\n        public void FrameItem(TIdentifier id)\n        {\n            bool animated = false;\n            m_TreeView.Frame(id, true, false, animated);\n        }\n\n        bool m_WarnedUser;\n        bool ValidTreeView()\n        {\n            if (isInitialized)\n                return true;\n\n            if (!m_WarnedUser)\n            {\n                Debug.LogError(\"TreeView has not been properly intialized yet. Ensure to call Reload() before using the tree view.\");\n                m_WarnedUser = true;\n            }\n            return false;\n        }\n\n        // OnGUI entry\n        public virtual void OnGUI(Rect rect)\n        {\n            if (!ValidTreeView())\n                return;\n\n            m_TreeView.OnEvent();\n\n            if (showBorder)\n                rect = m_GUI.DoBorder(rect);\n\n            if (m_MultiColumnHeader != null)\n                TreeViewWithMultiColumnHeader(rect);\n            else\n                m_TreeView.OnGUI(rect, m_TreeViewKeyControlID);\n\n            CommandEventHandling();\n        }\n\n        public void SelectAllRows()\n        {\n            var rows = GetRows();\n            var allowedSelection = (from treeViewItem in rows where CanMultiSelect(treeViewItem) select treeViewItem.id).ToList();\n            SetSelection(allowedSelection, TreeViewSelectionOptions.FireSelectionChanged);\n        }\n\n        void TreeViewWithMultiColumnHeader(Rect rect)\n        {\n            Rect columnHeaderRect = new Rect(rect.x, rect.y, rect.width, m_MultiColumnHeader.height);\n            Rect treeRect = new Rect(rect.x, columnHeaderRect.yMax, rect.width, rect.height - columnHeaderRect.height);\n\n            float scrollX = Mathf.Max(m_TreeView.state.scrollPos.x, 0f); // Ensure positive scroll values (work around an issue in the scroll view that when using mousescroll it returns invalid negative values)\n\n            Event evt = Event.current;\n            if (evt.type == EventType.MouseDown && columnHeaderRect.Contains(evt.mousePosition))\n                GUIUtility.keyboardControl = m_TreeViewKeyControlID;\n\n            m_MultiColumnHeader.OnGUI(columnHeaderRect, scrollX);\n            m_TreeView.OnGUI(treeRect, m_TreeViewKeyControlID);\n        }\n\n        // GUI helper methods (for custon drawing)\n\n        protected float GetFoldoutIndent(TreeViewItem<TIdentifier> item)\n        {\n            return m_GUI.GetFoldoutIndent(item);\n        }\n\n        protected float GetContentIndent(TreeViewItem<TIdentifier> item)\n        {\n            return m_GUI.GetContentIndent(item);\n        }\n\n        protected IList<TIdentifier> SortItemIDsInRowOrder(IList<TIdentifier> ids)\n        {\n            return m_TreeView.SortIDsInVisiblityOrder(ids);\n        }\n\n        protected void CenterRectUsingSingleLineHeight(ref Rect rect)\n        {\n            float singleLineHeight = EditorGUIUtility.singleLineHeight;\n            if (rect.height > singleLineHeight)\n            {\n                rect.y += (rect.height - singleLineHeight) * 0.5f;\n                rect.height = singleLineHeight;\n            }\n        }\n\n        protected void AddExpandedRows(TreeViewItem<TIdentifier> root, IList<TreeViewItem<TIdentifier>> rows)\n        {\n            if (root == null)\n                throw new ArgumentNullException(\"root\", \"root is null\");\n\n            if (rows == null)\n                throw new ArgumentNullException(\"rows\", \"rows is null\");\n\n            if (root.hasChildren)\n                foreach (TreeViewItem<TIdentifier> child in root.children)\n                    GetExpandedRowsRecursive(child, rows);\n        }\n\n        void GetExpandedRowsRecursive(TreeViewItem<TIdentifier> item, IList<TreeViewItem<TIdentifier>> expandedRows)\n        {\n            if (item == null)\n                Debug.LogError(\"Found a TreeViewItem<TIdentifier> that is null. Invalid use of AddExpandedRows(): This method is only valid to call if you have built the full tree of TreeViewItems.\");\n\n            expandedRows.Add(item);\n\n            if (item.hasChildren && IsExpanded(item.id))\n                foreach (TreeViewItem<TIdentifier> child in item.children)\n                    GetExpandedRowsRecursive(child, expandedRows);\n        }\n\n        protected virtual void SelectionChanged(IList<TIdentifier> selectedIds)\n        {\n        }\n\n        protected virtual void SingleClickedItem(TIdentifier id)\n        {\n        }\n\n        protected virtual void DoubleClickedItem(TIdentifier id)\n        {\n        }\n\n        protected virtual void ContextClickedItem(TIdentifier id)\n        {\n        }\n\n        protected virtual void ContextClicked()\n        {\n        }\n\n        protected virtual void ExpandedStateChanged()\n        {\n        }\n\n        protected virtual void SearchChanged(string newSearch)\n        {\n        }\n\n        protected virtual void KeyEvent()\n        {\n        }\n\n        // Used to reveal an item\n        protected virtual IList<TIdentifier> GetAncestors(TIdentifier id)\n        {\n            var item = FindItem(id);\n            if (item == null)\n                return new List<TIdentifier>();\n\n            // Default behavior assumes complete tree\n            HashSet<TIdentifier> parentsAbove = new HashSet<TIdentifier>();\n            TreeViewUtility<TIdentifier>.GetParentsAboveItem(item, parentsAbove);\n            return parentsAbove.ToArray();\n        }\n\n        // Used to expand children recursively below an item\n        protected virtual IList<TIdentifier> GetDescendantsThatHaveChildren(TIdentifier id)\n        {\n            // Default behavior assumes complete tree\n            HashSet<TIdentifier> parentsBelow = new HashSet<TIdentifier>();\n            TreeViewUtility<TIdentifier>.GetParentsBelowItem(FindItem(id), parentsBelow);\n            return parentsBelow.ToArray();\n        }\n\n        TreeViewItem<TIdentifier> FindItem(TIdentifier id)\n        {\n            if (rootItem == null)\n                throw new InvalidOperationException(\"FindItem failed: root item has not been created yet\");\n\n            return TreeViewUtility<TIdentifier>.FindItem(id, rootItem);\n        }\n\n        // Selection\n        protected virtual bool CanMultiSelect(TreeViewItem<TIdentifier> item) => CanMultiSelectInternal(item);\n\n        internal virtual bool CanMultiSelectInternal(TreeViewItem<TIdentifier> item)\n        {\n            return true; // default behavior\n        }\n\n        // Renaming\n        protected virtual bool CanRename(TreeViewItem<TIdentifier> item) => CanRenameInternal(item);\n\n        internal virtual bool CanRenameInternal(TreeViewItem<TIdentifier> item)\n        {\n            return false; // Default to false so user have to enable renaming if wanted\n        }\n\n        protected virtual void RenameEnded(RenameEndedArgs args)\n        {\n        }\n\n        // Dragging\n        protected virtual bool CanStartDrag(CanStartDragArgs args) => CanStartDragInternal(args);\n\n        internal virtual bool CanStartDragInternal(CanStartDragArgs args)\n        {\n            return false;\n        }\n\n        protected virtual void SetupDragAndDrop(SetupDragAndDropArgs args)\n        {\n        }\n\n        protected virtual DragAndDropVisualMode HandleDragAndDrop(DragAndDropArgs args) => HandleDragAndDropInternal(args);\n        internal virtual DragAndDropVisualMode HandleDragAndDropInternal(DragAndDropArgs args)\n        {\n            return DragAndDropVisualMode.None;\n        }\n\n        protected virtual bool CanBeParent(TreeViewItem<TIdentifier> item) => CanBeParentInternal(item);\n\n        internal virtual bool CanBeParentInternal(TreeViewItem<TIdentifier> item)\n        {\n            return true; // default behavior\n        }\n\n        protected virtual bool CanChangeExpandedState(TreeViewItem<TIdentifier> item) => CanChangeExpandedStateInternal(item);\n\n        internal virtual bool CanChangeExpandedStateInternal(TreeViewItem<TIdentifier> item)\n        {\n            // Default: Ignore expansion (foldout arrow) when showing search results\n            if (m_TreeView.isSearching)\n                return false;\n            return item.hasChildren;\n        }\n\n        protected virtual bool DoesItemMatchSearch(TreeViewItem<TIdentifier> item, string search) => DoesItemMatchSearchInternal(item, search);\n\n        internal virtual bool DoesItemMatchSearchInternal(TreeViewItem<TIdentifier> item, string search)\n        {\n            return item.displayName.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0;\n        }\n\n        // Custom GUI\n        protected virtual void RowGUI(RowGUIArgs args) => RowGUIInternal(args);\n\n        internal virtual void RowGUIInternal(RowGUIArgs args)\n        {\n            m_GUI.DefaultRowGUI(args);\n        }\n\n        protected virtual void BeforeRowsGUI()\n        {\n            if (showAlternatingRowBackgrounds)\n                m_GUI.DrawAlternatingRowBackgrounds();\n        }\n\n        protected virtual void AfterRowsGUI()\n        {\n        }\n\n        protected virtual void RefreshCustomRowHeights()\n        {\n            if (!m_OverriddenMethods.hasGetCustomRowHeight)\n                throw new InvalidOperationException(\"Only call RefreshCustomRowHeights if you have overridden GetCustomRowHeight to customize the height of each row.\");\n            m_GUI.RefreshRowRects(GetRows());\n        }\n\n        protected virtual float GetCustomRowHeight(int row, TreeViewItem<TIdentifier> item) => GetCustomRowHeightInternal(row, item);\n\n        internal virtual float GetCustomRowHeightInternal(int row, TreeViewItem<TIdentifier> item)\n        {\n            return rowHeight;\n        }\n\n        protected virtual Rect GetRenameRect(Rect rowRect, int row, TreeViewItem<TIdentifier> item) => GetRenameRectInternal(rowRect, row, item);\n\n        internal virtual Rect GetRenameRectInternal(Rect rowRect, int row, TreeViewItem<TIdentifier> item)\n        {\n            return m_GUI.DefaultRenameRect(rowRect, row, item);\n        }\n\n        protected virtual void CommandEventHandling()\n        {\n            Event evt = Event.current;\n\n            if (evt.type != EventType.ExecuteCommand && evt.type != EventType.ValidateCommand)\n                return;\n\n            bool execute = evt.type == EventType.ExecuteCommand;\n\n            if (HasFocus() && evt.commandName == EventCommandNames.SelectAll)\n            {\n                if (execute)\n                    SelectAllRows();\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n\n            if (evt.commandName == EventCommandNames.FrameSelected)\n            {\n                if (execute)\n                {\n                    if (hasSearch)\n                        searchString = string.Empty;\n\n                    if (HasSelection())\n                        FrameItem(GetSelection()[0]);\n                }\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        protected static void SetupParentsAndChildrenFromDepths(TreeViewItem<TIdentifier> root, IList<TreeViewItem<TIdentifier>> rows)\n        {\n            TreeViewUtility<TIdentifier>.SetChildParentReferences(rows, root);\n        }\n\n        protected static void SetupDepthsFromParentsAndChildren(TreeViewItem<TIdentifier> root)\n        {\n            TreeViewUtility<TIdentifier>.SetDepthValuesForItems(root);\n        }\n\n        protected static List<TreeViewItem<TIdentifier>> CreateChildListForCollapsedParent()\n        {\n            return LazyTreeViewDataSource<TIdentifier>.CreateChildListForCollapsedParent();\n        }\n\n        protected static bool IsChildListForACollapsedParent(IList<TreeViewItem<TIdentifier>> childList)\n        {\n            return LazyTreeViewDataSource<TIdentifier>.IsChildListForACollapsedParent(childList);\n        }\n\n        class OverriddenMethods\n        {\n            public readonly bool hasRowGUI;\n            public readonly bool hasHandleDragAndDrop;\n            public readonly bool hasGetRenameRect;\n            public readonly bool hasBuildRows;\n            public readonly bool hasGetCustomRowHeight;\n\n            public OverriddenMethods(TreeView<TIdentifier> treeView)\n            {\n                Type type = treeView.GetType();\n                var methods = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);\n                bool hasCanRename = false, hasRenameEnded = false;\n                bool hasCanStartDragAndDrop = false, hasSetupDragAndDrop = false;\n\n                foreach (var method in methods)\n                {\n                    if (method.GetBaseDefinition().DeclaringType == method.DeclaringType)\n                        continue;\n\n                    switch (method.Name)\n                    {\n                        case \"RowGUI\":\n                        {\n                            hasRowGUI = true;\n                            break;\n                        }\n                        case \"HandleDragAndDrop\":\n                        {\n                            hasHandleDragAndDrop = true;\n                            break;\n                        }\n                        case \"GetRenameRect\":\n                        {\n                            hasGetRenameRect = true;\n                            break;\n                        }\n                        case \"BuildRows\":\n                        {\n                            hasBuildRows = true;\n                            break;\n                        }\n                        case \"GetCustomRowHeight\":\n                        {\n                            hasGetCustomRowHeight = true;\n                            break;\n                        }\n                        case \"CanRename\":\n                        {\n                            hasCanRename = true;\n                            break;\n                        }\n                        case \"RenameEnded\":\n                        {\n                            hasRenameEnded = true;\n                            break;\n                        }\n                        case \"CanStartDrag\":\n                        {\n                            hasCanStartDragAndDrop = true;\n                            break;\n                        }\n                        case \"SetupDragAndDrop\":\n                        {\n                            hasSetupDragAndDrop = true;\n                            break;\n                        }\n                    }\n                }\n\n                if (hasRenameEnded != hasCanRename)\n                {\n                    if (hasCanRename)\n                        Debug.LogError(type.Name + \": If you are overriding CanRename you should also override RenameEnded (to handle the renaming).\");\n\n                    if (hasRenameEnded)\n                        Debug.LogError(type.Name + \": If you are overriding RenameEnded you should also override CanRename (to allow renaming).\");\n                }\n\n                if (hasCanStartDragAndDrop != hasSetupDragAndDrop)\n                {\n                    if (hasCanStartDragAndDrop)\n                        Debug.LogError(type.Name + \": If you are overriding CanStartDrag you should also override SetupDragAndDrop (to setup the drag).\");\n\n                    if (hasSetupDragAndDrop)\n                        Debug.LogError(type.Name + \": If you are overriding SetupDragAndDrop you should also override CanStartDrag (to allow dragging).\");\n                }\n            }\n        }\n\n        // Nested because they are used by protected methods\n        protected internal struct RowGUIArgs\n        {\n            public TreeViewItem<TIdentifier> item;\n            public string label;\n            public Rect rowRect;\n            public int row;\n            public bool selected;\n            public bool focused;\n            public bool isRenaming;\n            internal MultiColumnInfo columnInfo { get; set; }\n\n            public int GetNumVisibleColumns()\n            {\n                if (!HasMultiColumnInfo())\n                    throw new NotSupportedException(\"Only call this method if you are using a MultiColumnHeader with the TreeView.\");\n\n                return columnInfo.multiColumnHeaderState.visibleColumns.Length;\n            }\n\n            public int GetColumn(int visibleColumnIndex)\n            {\n                if (!HasMultiColumnInfo())\n                    throw new NotSupportedException(\"Only call this method if you are using a MultiColumnHeader with the TreeView.\");\n\n                return columnInfo.multiColumnHeaderState.visibleColumns[visibleColumnIndex];\n            }\n\n            public Rect GetCellRect(int visibleColumnIndex)\n            {\n                if (!HasMultiColumnInfo())\n                    throw new NotSupportedException(\"Only call this method if you are using a MultiColumnHeader with the TreeView.\");\n\n                return columnInfo.cellRects[visibleColumnIndex];\n            }\n\n            internal bool HasMultiColumnInfo()\n            {\n                return columnInfo.multiColumnHeaderState != null;\n            }\n\n            internal struct MultiColumnInfo\n            {\n                internal MultiColumnInfo(MultiColumnHeaderState multiColumnHeaderState, Rect[] cellRects)\n                {\n                    this.multiColumnHeaderState = multiColumnHeaderState;\n                    this.cellRects = cellRects;\n                }\n\n                public MultiColumnHeaderState multiColumnHeaderState;\n                public Rect[] cellRects;\n            }\n        }\n\n        protected internal struct DragAndDropArgs\n        {\n            public DragAndDropPosition dragAndDropPosition;\n            public TreeViewItem<TIdentifier> parentItem;\n            public int insertAtIndex;\n            public bool performDrop;\n        }\n\n        protected struct SetupDragAndDropArgs\n        {\n            public IList<TIdentifier> draggedItemIDs;\n        }\n\n        protected internal struct CanStartDragArgs\n        {\n            public TreeViewItem<TIdentifier> draggedItem;\n            public IList<TIdentifier> draggedItemIDs;\n        }\n\n        protected struct RenameEndedArgs\n        {\n            public bool acceptedRename;\n            public TIdentifier itemID;\n            public string originalName;\n            public string newName;\n        }\n\n        protected internal enum DragAndDropPosition\n        {\n            UponItem,\n            BetweenItems,\n            OutsideItems\n        }\n    }\n\n    [Flags]\n    public enum TreeViewSelectionOptions\n    {\n        None = 0,\n        FireSelectionChanged = 1,\n        RevealAndFrame = 2\n    }\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public partial class TreeView<TIdentifier> where TIdentifier : unmanaged, System.IEquatable<TIdentifier>\n    {\n        internal class TreeViewControlDataSource : LazyTreeViewDataSource<TIdentifier>\n        {\n            readonly TreeView<TIdentifier> m_Owner;\n\n            public TreeViewControlDataSource(TreeViewController<TIdentifier> treeView, TreeView<TIdentifier> owner) : base(treeView)\n            {\n                m_Owner = owner;\n\n                // The user should just create the visible rows, we create the hidden root\n                showRootItem = false;\n            }\n\n            public override void ReloadData()\n            {\n                // Clear root item to ensure client gets a call to BuildRoot every time Reload is called\n                m_RootItem = null;\n                base.ReloadData();\n            }\n\n            void ValidateRootItem()\n            {\n                if (m_RootItem == null)\n                {\n                    throw new NullReferenceException(\"BuildRoot should set a valid root item.\");\n                }\n                if (m_RootItem.depth != -1)\n                {\n                    Debug.LogError(\"BuildRoot should ensure the root item has a depth == -1. The visible items start at depth == 0.\");\n                    m_RootItem.depth = -1;\n                }\n                if (m_RootItem.children == null && !m_Owner.m_OverriddenMethods.hasBuildRows)\n                {\n                    throw new InvalidOperationException(\"TreeView: 'rootItem.children == null'. Did you forget to add children? If you intend to only create the list of rows (not the full tree) then you need to override: BuildRows, GetAncestors and GetDescendantsThatHaveChildren.\");\n                }\n            }\n\n            public override void FetchData()\n            {\n                // Set before BuildRoot and BuildRows so we can call GetRows in them without recursion\n                m_NeedRefreshRows = false;\n\n                // Root\n                if (m_RootItem == null)\n                {\n                    m_RootItem = m_Owner.BuildRoot();\n                    ValidateRootItem();\n                }\n\n                // Rows\n                m_Rows = m_Owner.BuildRows(m_RootItem);\n                if (m_Rows == null)\n                    throw new NullReferenceException(\"RefreshRows should set valid list of rows.\");\n\n                // Custom row rects\n                if (m_Owner.m_OverriddenMethods.hasGetCustomRowHeight)\n                    m_Owner.m_GUI.RefreshRowRects(m_Rows);\n            }\n\n            public void SearchFullTree(string search, List<TreeViewItem<TIdentifier>> result)\n            {\n                if (string.IsNullOrEmpty(search))\n                    throw new ArgumentException(\"Invalid search: cannot be null or empty\", \"search\");\n\n                if (result == null)\n                    throw new ArgumentException(\"Invalid list: cannot be null\", \"result\");\n\n                var stack = new Stack<TreeViewItem<TIdentifier>>();\n                stack.Push(m_RootItem);\n                while (stack.Count > 0)\n                {\n                    TreeViewItem<TIdentifier> current = stack.Pop();\n                    if (current.children != null)\n                    {\n                        foreach (var child in current.children)\n                        {\n                            if (child != null)\n                            {\n                                if (m_Owner.DoesItemMatchSearch(child, search))\n                                    result.Add(child);\n\n                                stack.Push(child);\n                            }\n                        }\n                    }\n                }\n\n                result.Sort((x, y) => EditorUtility.NaturalCompare(x.displayName, y.displayName));\n            }\n\n            protected override void GetParentsAbove(TIdentifier id, HashSet<TIdentifier> ancestors)\n            {\n                foreach (var ancestor in m_Owner.GetAncestors(id))\n                    ancestors.Add(ancestor);\n            }\n\n            protected override void GetParentsBelow(TIdentifier id, HashSet<TIdentifier> children)\n            {\n                foreach (var child in m_Owner.GetDescendantsThatHaveChildren(id))\n                    children.Add(child);\n            }\n\n            public override bool IsExpandable(TreeViewItem<TIdentifier> item)\n            {\n                return m_Owner.CanChangeExpandedState(item);\n            }\n\n            public override bool CanBeMultiSelected(TreeViewItem<TIdentifier> item)\n            {\n                return m_Owner.CanMultiSelect(item);\n            }\n\n            public override bool CanBeParent(TreeViewItem<TIdentifier> item)\n            {\n                return m_Owner.CanBeParent(item);\n            }\n\n            public override bool IsRenamingItemAllowed(TreeViewItem<TIdentifier> item)\n            {\n                return m_Owner.CanRename(item);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDefaults.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public partial class TreeView<TIdentifier> where TIdentifier : unmanaged, System.IEquatable<TIdentifier>\n    {\n        public static class DefaultGUI\n        {\n            public static void FoldoutLabel(Rect rect, string label, bool selected, bool focused)\n            {\n                if (Event.current.type == EventType.Repaint)\n                    DefaultStyles.foldoutLabel.Draw(rect, GUIContent.Temp(label), false, false, selected, focused);\n            }\n\n            public static void Label(Rect rect, string label, bool selected, bool focused)\n            {\n                if (Event.current.type == EventType.Repaint)\n                    DefaultStyles.label.Draw(rect, GUIContent.Temp(label), false, false, selected, focused);\n            }\n\n            public static void LabelRightAligned(Rect rect, string label, bool selected, bool focused)\n            {\n                if (Event.current.type == EventType.Repaint)\n                    DefaultStyles.labelRightAligned.Draw(rect, GUIContent.Temp(label), false, false, selected, focused);\n            }\n\n            public static void BoldLabel(Rect rect, string label, bool selected, bool focused)\n            {\n                if (Event.current.type == EventType.Repaint)\n                    DefaultStyles.boldLabel.Draw(rect, GUIContent.Temp(label), false, false, selected, focused);\n            }\n\n            public static void BoldLabelRightAligned(Rect rect, string label, bool selected, bool focused)\n            {\n                if (Event.current.type == EventType.Repaint)\n                    DefaultStyles.boldLabelRightAligned.Draw(rect, GUIContent.Temp(label), false, false, selected, focused);\n            }\n\n            internal static float contentLeftMargin\n            {\n                get { return DefaultStyles.foldoutLabel.margin.left; }\n            }\n        }\n\n        public static class DefaultStyles\n        {\n            public static GUIStyle foldoutLabel;\n            public static GUIStyle label;\n            public static GUIStyle labelRightAligned;\n\n            public static GUIStyle boldLabel;\n            public static GUIStyle boldLabelRightAligned;\n\n            public static GUIStyle backgroundEven = \"OL EntryBackEven\";\n            public static GUIStyle backgroundOdd = \"OL EntryBackOdd\";\n\n            static DefaultStyles()\n            {\n                // Make a copy of lineStyle since left padding is being dynamically changed on that\n                // Note the left padding of 0 for exact placement of content after foldout or icon\n                foldoutLabel = new GUIStyle(TreeViewGUI<TIdentifier>.Styles.lineStyle);\n                foldoutLabel.padding.left = 0;\n\n                // For generic labels use same padding values as the standard EditorStyles.label for consistency\n                label = new GUIStyle(foldoutLabel);\n                label.padding.left = 2;\n                label.padding.right = 2;\n\n                labelRightAligned = new GUIStyle(label);\n                labelRightAligned.alignment = TextAnchor.UpperRight;\n\n                boldLabel = new GUIStyle(label);\n                boldLabel.font = EditorStyles.boldLabel.font;\n                boldLabel.fontStyle = EditorStyles.boldLabel.fontStyle;\n\n                boldLabelRightAligned = new GUIStyle(boldLabel);\n                boldLabelRightAligned.alignment = TextAnchor.UpperRight;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDragging.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\n\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public partial class TreeView<TIdentifier> where TIdentifier : unmanaged, System.IEquatable<TIdentifier>\n    {\n        private class TreeViewControlDragging : TreeViewDragging<TIdentifier>\n        {\n            private TreeView<TIdentifier> m_Owner;\n\n            public TreeViewControlDragging(TreeViewController<TIdentifier> treeView, TreeView<TIdentifier> owner)\n                : base(treeView)\n            {\n                m_Owner = owner;\n            }\n\n            public override bool CanStartDrag(TreeViewItem<TIdentifier> targetItem, List<TIdentifier> draggedItemIDs, Vector2 mouseDownPosition)\n            {\n                return m_Owner.CanStartDrag(new CanStartDragArgs { draggedItem = targetItem, draggedItemIDs = draggedItemIDs });\n            }\n\n            public override void StartDrag(TreeViewItem<TIdentifier> draggedItem, List<TIdentifier> draggedItemIDs)\n            {\n                m_Owner.SetupDragAndDrop(new SetupDragAndDropArgs { draggedItemIDs = draggedItemIDs});\n            }\n\n            public override DragAndDropVisualMode DoDrag(TreeViewItem<TIdentifier> parentItem, TreeViewItem<TIdentifier> targetItem, bool perform, DropPosition dropPosition)\n            {\n                if (m_Owner.m_OverriddenMethods.hasHandleDragAndDrop)\n                {\n                    var args = new DragAndDropArgs\n                    {\n                        dragAndDropPosition = GetDragAndDropPosition(parentItem, targetItem),\n                        insertAtIndex = GetInsertionIndex(parentItem, targetItem, dropPosition),\n                        parentItem = parentItem,\n                        performDrop = perform\n                    };\n\n                    return m_Owner.HandleDragAndDrop(args);\n                }\n\n                return DragAndDropVisualMode.None;\n            }\n\n            DragAndDropPosition GetDragAndDropPosition(TreeViewItem<TIdentifier> parentItem, TreeViewItem<TIdentifier> targetItem)\n            {\n                if (parentItem == null)\n                    return DragAndDropPosition.OutsideItems;\n\n                if (parentItem == targetItem)\n                    return DragAndDropPosition.UponItem;\n\n                return DragAndDropPosition.BetweenItems;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public partial class TreeView<TIdentifier> where TIdentifier : unmanaged, System.IEquatable<TIdentifier>\n    {\n        class TreeViewControlGUI : TreeViewGUI<TIdentifier>\n        {\n            readonly TreeView<TIdentifier> m_Owner;\n            List<Rect> m_RowRects;                           // If m_RowRects is null fixed row height is used\n            Rect[] m_CellRects;                              // Allocated once and reused\n            const float k_BackgroundWidth = 100000f;         // The TreeView can have a horizontal scrollbar so ensure to fill out the entire width of the background\n            public float borderWidth = 1f;\n\n            public TreeViewControlGUI(TreeViewController<TIdentifier> treeView, TreeView<TIdentifier> owner)\n                : base(treeView)\n            {\n                m_Owner = owner;\n                cellMargin = MultiColumnHeader.DefaultGUI.columnContentMargin;\n            }\n\n            public void RefreshRowRects(IList<TreeViewItem<TIdentifier>> rows)\n            {\n                if (m_RowRects == null)\n                    m_RowRects = new List<Rect>(rows.Count);\n\n                if (m_RowRects.Capacity < rows.Count)\n                    m_RowRects.Capacity = rows.Count;\n\n                m_RowRects.Clear();\n                float curY = k_TopRowMargin;\n                for (int row = 0; row < rows.Count; ++row)\n                {\n                    float height = m_Owner.GetCustomRowHeight(row, rows[row]);\n                    m_RowRects.Add(new Rect(0f, curY, 1f, height)); // row width is updatd to the actual visibleRect of the TreeView's scrollview on the fly\n                    curY += height;\n                }\n            }\n\n            public float cellMargin { get; set; }\n\n            public float foldoutWidth\n            {\n                get { return foldoutStyleWidth; }\n            }\n\n            public int columnIndexForTreeFoldouts { get; set; } // column 0 is the default column for the tree foldouts\n\n            public float totalHeight\n            {\n                get { return (useCustomRowRects ? customRowsTotalHeight : base.GetTotalSize().y) + (m_Owner.multiColumnHeader != null ? m_Owner.multiColumnHeader.height : 0f); }\n            }\n\n            public override Vector2 GetTotalSize()\n            {\n                Vector2 contentSize = useCustomRowRects ? new Vector2(1, customRowsTotalHeight) : base.GetTotalSize();\n\n                // If we have multi column state we use the width of the columns so we show the horizontal scrollbar if needed\n                if (m_Owner.multiColumnHeader != null)\n                    contentSize.x = Mathf.Floor(m_Owner.multiColumnHeader.state.widthOfAllVisibleColumns);\n                return contentSize;\n            }\n\n            bool useCustomRowRects\n            {\n                get { return m_RowRects != null; }\n            }\n\n            float customRowsTotalHeight\n            {\n                get\n                {\n                    return\n                        (m_RowRects.Count > 0 ? m_RowRects[m_RowRects.Count - 1].yMax : 0f) + k_BottomRowMargin\n                        - (m_TreeView.expansionAnimator.isAnimating ? m_TreeView.expansionAnimator.deltaHeight : 0f);\n                }\n            }\n\n            // We only override DrawIconAndLabel (and not OnRowGUI) so the user only have to care about item content rendering; and not drag marker rendering, renaming and foldout button\n            protected override void OnContentGUI(Rect rect, int row, TreeViewItem<TIdentifier> item, string label, bool selected, bool focused, bool useBoldFont, bool isPinging)\n            {\n                // We do not support pinging in the TreeView (to simplify api)\n                if (isPinging)\n                    return;\n\n                // Make sure the GUI contents for each row is starting with its own controlID unique to its item. This prevents key-focus of a control (e.g a float field)\n                // to jump from row to row when mouse scrolling (due to culling of rows and the assigning of controlIDs in call-order)\n                GUIUtility.GetControlID(TreeViewController<TIdentifier>.GetItemControlID(item), FocusType.Passive);\n\n                if (m_Owner.m_OverriddenMethods.hasRowGUI)\n                {\n                    var args = new RowGUIArgs\n                    {\n                        rowRect = rect,\n                        row = row,\n                        item = item,\n                        label = label,\n                        selected = selected,\n                        focused = focused,\n                        isRenaming = IsRenaming(item.id),\n                    };\n\n                    // For multi column header we call OnRowGUI for each cell with the cell rect\n                    if (m_Owner.multiColumnHeader != null)\n                    {\n                        //args.columnInfo = m_ColumnInfo;\n                        var visibleColumns = m_Owner.multiColumnHeader.state.visibleColumns;\n                        if (m_CellRects == null || m_CellRects.Length != visibleColumns.Length)\n                            m_CellRects = new Rect[visibleColumns.Length];\n\n                        var columns = m_Owner.multiColumnHeader.state.columns;\n                        var columnRect = args.rowRect;\n                        for (int i = 0; i < visibleColumns.Length; ++i)\n                        {\n                            var columnData = columns[visibleColumns[i]];\n                            columnRect.width = columnData.width;\n\n                            m_CellRects[i] = columnRect;\n\n                            // Use cell margins for all columns except the column with the tree view foldouts\n                            // since that column assumes full cell rect for rename overlay placement\n                            if (columnIndexForTreeFoldouts != visibleColumns[i])\n                            {\n                                m_CellRects[i].x += cellMargin;\n                                m_CellRects[i].width -= 2 * cellMargin;\n                            }\n\n                            columnRect.x += columnData.width;\n                        }\n\n                        args.columnInfo = new RowGUIArgs.MultiColumnInfo(m_Owner.multiColumnHeader.state, m_CellRects);\n                    }\n\n                    m_Owner.RowGUI(args);\n                }\n                else\n                {\n                    // Default item gui\n                    base.OnContentGUI(rect, row, item, label, selected, focused, useBoldFont, false);\n                }\n            }\n\n            internal void DefaultRowGUI(RowGUIArgs args)\n            {\n                base.OnContentGUI(args.rowRect, args.row, args.item, args.label, args.selected, args.focused, false, false);\n            }\n\n            protected override Rect DoFoldout(Rect rowRect, TreeViewItem<TIdentifier> item, int row)\n            {\n                // For multicolumn setup we need to ensure foldouts are clipped so they are not in the next column\n                if (m_Owner.multiColumnHeader != null)\n                    return DoMultiColumnFoldout(rowRect, item, row);\n\n                return base.DoFoldout(rowRect, item, row);\n            }\n\n            Rect DoMultiColumnFoldout(Rect rowRect, TreeViewItem<TIdentifier> item, int row)\n            {\n                if (!m_Owner.multiColumnHeader.IsColumnVisible(columnIndexForTreeFoldouts))\n                    return new Rect();\n\n                Rect cellRect = m_Owner.GetCellRectForTreeFoldouts(rowRect);\n\n                // Clip foldout arrow if the cell is not big enough\n                if (GetContentIndent(item) > cellRect.width)\n                {\n                    GUIClip.Push(cellRect, Vector2.zero, Vector2.zero, false);\n                    cellRect.x = cellRect.y = 0f; // set guiclip coords\n                    Rect foldoutRect = base.DoFoldout(cellRect, item, row);\n                    GUIClip.Pop();\n                    return foldoutRect;\n                }\n\n                return base.DoFoldout(cellRect, item, row);\n            }\n\n            public override Rect GetRenameRect(Rect rowRect, int row, TreeViewItem<TIdentifier> item)\n            {\n                if (m_Owner.m_OverriddenMethods.hasGetRenameRect)\n                {\n                    return m_Owner.GetRenameRect(rowRect, row, item);\n                }\n\n                return base.GetRenameRect(rowRect, row, item);\n            }\n\n            public Rect DefaultRenameRect(Rect rowRect, int row, TreeViewItem<TIdentifier> item)\n            {\n                return base.GetRenameRect(rowRect, row, item);\n            }\n\n            public override void BeginRowGUI()\n            {\n                base.BeginRowGUI();\n\n                if (m_Owner.isDragging && m_Owner.multiColumnHeader != null && columnIndexForTreeFoldouts > 0)\n                {\n                    // Adjust insertion marker for multi column setups\n                    int visibleColumnIndex = m_Owner.multiColumnHeader.GetVisibleColumnIndex(columnIndexForTreeFoldouts);\n                    extraInsertionMarkerIndent = m_Owner.multiColumnHeader.GetColumnRect(visibleColumnIndex).x;\n                }\n\n                m_Owner.BeforeRowsGUI();\n            }\n\n            public override void EndRowGUI()\n            {\n                base.EndRowGUI();\n                m_Owner.AfterRowsGUI();\n            }\n\n            protected override void RenameEnded()\n            {\n                var renameState = m_TreeView.state.renameOverlay;\n                var renameEndedArgs = new RenameEndedArgs\n                {\n                    acceptedRename = renameState.userAcceptedRename,\n                    itemID = renameState.userData,\n                    originalName = renameState.originalName,\n                    newName = renameState.name\n                };\n                m_Owner.RenameEnded(renameEndedArgs);\n            }\n\n            public override Rect GetRowRect(int row, float rowWidth)\n            {\n                if (!useCustomRowRects)\n                {\n                    return base.GetRowRect(row, rowWidth);\n                }\n\n                if (row < 0 || row >= m_RowRects.Count)\n                {\n                    throw new ArgumentOutOfRangeException(\"row\", string.Format(\"Input row index: {0} is invalid. Number of rows rects: {1}. (Number of rows: {2})\", row, m_RowRects.Count, m_Owner.m_DataSource.rowCount));\n                }\n\n                Rect rowRect = m_RowRects[row];\n                rowRect.width = rowWidth;\n                return rowRect;\n            }\n\n            public override Rect GetRectForFraming(int row)\n            {\n                return GetRowRect(row, 1);\n            }\n\n            // Should return the row number of the first and last row thats fits in the pixel rect defined by top and height\n            public override void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible)\n            {\n                if (!useCustomRowRects)\n                {\n                    base.GetFirstAndLastRowVisible(out firstRowVisible, out lastRowVisible);\n                    return;\n                }\n\n                if (m_TreeView.data.rowCount == 0)\n                {\n                    firstRowVisible = lastRowVisible = -1;\n                    return;\n                }\n\n                var rowCount = m_TreeView.data.rowCount;\n                if (rowCount != m_RowRects.Count)\n                {\n                    var errorMessage = string.Format(\n                        \"Number of rows does not match number of row rects. Did you remember to update the row rects when BuildRootAndRows was called? Number of rows: {0}, number of custom row rects: {1}. Falling back to fixed row height.\",\n                        rowCount, m_RowRects.Count);\n                    m_RowRects = null;\n                    throw new InvalidOperationException(errorMessage);\n                }\n\n                float topPixel = m_TreeView.state.scrollPos.y;\n                float heightInPixels = m_TreeView.GetTotalRect().height;\n\n                int firstVisible = -1;\n                int lastVisible = -1;\n                for (int i = 0; i < m_RowRects.Count; ++i)\n                {\n                    bool visible =  ((m_RowRects[i].y > topPixel && (m_RowRects[i].y < topPixel + heightInPixels))) ||\n                        ((m_RowRects[i].yMax > topPixel && (m_RowRects[i].yMax < topPixel + heightInPixels)));\n\n                    if (visible)\n                    {\n                        if (firstVisible == -1)\n                            firstVisible = i;\n                        lastVisible = i;\n                    }\n                }\n\n                if (firstVisible != -1 && lastVisible != -1)\n                {\n                    firstRowVisible = firstVisible;\n                    lastRowVisible = lastVisible;\n                }\n                else\n                {\n                    firstRowVisible = 0;\n                    lastRowVisible = rowCount - 1;\n                }\n            }\n\n            protected override void DrawItemBackground(Rect rect, int row, TreeViewItem<TIdentifier> item, bool selected, bool focused)\n            {\n                base.DrawItemBackground(rect, row, item, selected, focused);\n\n                // To ensure backgrounds are also animated when animating expansion we render the rows backgrounds individually here. When not animating expansion the backgrounds\n                // are rendered in one go in DrawAlternatingRowBackgrounds() which also handles background outside rows\n                if (m_Owner.showAlternatingRowBackgrounds && m_TreeView.animatingExpansion)\n                {\n                    rect.width = k_BackgroundWidth;\n                    var bgStyle = row % 2 == 0 ? DefaultStyles.backgroundEven : DefaultStyles.backgroundOdd;\n                    bgStyle.Draw(rect, false, false, false, false);\n                }\n            }\n\n            public void DrawAlternatingRowBackgrounds()\n            {\n                if (Event.current.rawType != EventType.Repaint)\n                    return;\n\n                // Render entire bg\n                float contentYMax = m_Owner.treeViewRect.height + m_Owner.state.scrollPos.y;\n\n                DefaultStyles.backgroundOdd.Draw(new Rect(0, 0, k_BackgroundWidth, contentYMax), false, false, false, false);\n\n                int first = 0;\n                var numRows = m_Owner.GetRows().Count;\n                if (numRows > 0)\n                {\n                    int last;\n                    GetFirstAndLastRowVisible(out first, out last);\n                    if (first < 0 || first >= numRows)\n                        return;\n                }\n\n                // Render every 2nd row for the entire background (we also show alternating colors below the last item)\n                Rect rowRect = new Rect(0, 0, 0, m_Owner.rowHeight);\n                for (int row = first; rowRect.yMax < contentYMax; row++)\n                {\n                    if (row % 2 == 1)\n                        continue;\n\n                    if (row < numRows)\n                        rowRect = m_Owner.GetRowRect(row);\n                    else if (row > 0)\n                        rowRect.y += rowRect.height * 2;\n                    rowRect.width = k_BackgroundWidth;\n\n                    DefaultStyles.backgroundEven.Draw(rowRect, false, false, false, false);\n                }\n            }\n\n            protected override bool DoFoldoutButton(Rect foldoutRect, bool expandedState, GUIStyle foldoutStyle)\n            {\n                if (m_Owner.foldoutOverride != null)\n                    return m_Owner.foldoutOverride(foldoutRect, expandedState, foldoutStyle);\n                return base.DoFoldoutButton(foldoutRect, expandedState, foldoutStyle);\n            }\n\n            // Returns the rect available within the borders\n            public Rect DoBorder(Rect rect)\n            {\n                EditorGUI.DrawOutline(rect, borderWidth, EditorGUI.kSplitLineSkinnedColor.color);\n                return new Rect(rect.x + borderWidth, rect.y + borderWidth, rect.width - 2 * borderWidth, rect.height - 2 * borderWidth);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewOld.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls;\n\n[Obsolete(\"TreeView is now deprecated. You can likely now use TreeView<int> instead and not think more about it. But if you were using that identifier to store InstanceID data, you should instead opt to upgrade your TreeViews to use TreeView<InstanceID> to get the proper typing.\")]\npublic abstract partial class TreeView : TreeViewInternal\n{\n    protected TreeView(TreeViewState state)\n        : base(state) { }\n\n    protected TreeView(TreeViewState state, MultiColumnHeader multiColumnHeader)\n        : base(state, multiColumnHeader) { }\n\n    protected new struct RowGUIArgs\n    {\n        public TreeViewItem item;\n        public string label;\n        public Rect rowRect;\n        public int row;\n        public bool selected;\n        public bool focused;\n        public bool isRenaming;\n        internal TreeView<int>.RowGUIArgs.MultiColumnInfo columnInfo;\n\n        public int GetNumVisibleColumns()=> ((TreeView<int>.RowGUIArgs)this).GetNumVisibleColumns();\n        public int GetColumn(int visibleColumnIndex) => ((TreeView<int>.RowGUIArgs)this).GetColumn(visibleColumnIndex);\n        public Rect GetCellRect(int visibleColumnIndex) => ((TreeView<int>.RowGUIArgs)this).GetCellRect(visibleColumnIndex);\n\n        // a cast from RowGUIArgs to TreeView<int>.RowGUIArgs\n        public static implicit operator TreeView<int>.RowGUIArgs(RowGUIArgs args) => new()\n        {\n            item = args.item,\n            label = args.label,\n            rowRect = args.rowRect,\n            row = args.row,\n            selected = args.selected,\n            focused = args.focused,\n            isRenaming = args.isRenaming,\n            columnInfo = args.columnInfo\n        };\n\n        public static implicit operator RowGUIArgs(TreeView<int>.RowGUIArgs args) => new()\n        {\n            item = args.item as TreeViewItem,\n            label = args.label,\n            rowRect = args.rowRect,\n            row = args.row,\n            selected = args.selected,\n            focused = args.focused,\n            isRenaming = args.isRenaming,\n            columnInfo = args.columnInfo\n        };\n    }\n\n    protected new struct DragAndDropArgs\n    {\n        public DragAndDropPosition dragAndDropPosition;\n        public TreeViewItem parentItem;\n        public int insertAtIndex;\n        public bool performDrop;\n\n        // a cast from DragAndDropArgs to TreeView<int>.DragAndDropArgs\n        public static implicit operator TreeView<int>.DragAndDropArgs(DragAndDropArgs args)\n        {\n            return new TreeView<int>.DragAndDropArgs\n            {\n                dragAndDropPosition = args.dragAndDropPosition,\n                parentItem = args.parentItem,\n                insertAtIndex = args.insertAtIndex,\n                performDrop = args.performDrop\n            };\n        }\n        public static implicit operator DragAndDropArgs(TreeView<int>.DragAndDropArgs args)\n        {\n            return new DragAndDropArgs\n            {\n                dragAndDropPosition = args.dragAndDropPosition,\n                parentItem = args.parentItem as TreeViewItem,\n                insertAtIndex = args.insertAtIndex,\n                performDrop = args.performDrop\n            };\n        }\n    }\n\n    protected new struct CanStartDragArgs\n    {\n        public TreeViewItem draggedItem;\n        public IList<int> draggedItemIDs;\n\n        // a cast from CanStartDragArgs to TreeView<TIdentifier>.CanStartDragArgs\n        public static implicit operator TreeView<int>.CanStartDragArgs(CanStartDragArgs args)\n        {\n            return new TreeView<int>.CanStartDragArgs\n            {\n                draggedItem = args.draggedItem,\n                draggedItemIDs = args.draggedItemIDs\n            };\n        }\n\n        public static implicit operator CanStartDragArgs(TreeView<int>.CanStartDragArgs args)\n        {\n            return new CanStartDragArgs\n            {\n                draggedItem = args.draggedItem as TreeViewItem,\n                draggedItemIDs = args.draggedItemIDs\n            };\n        }\n    }\n\n    public new delegate List<int> GetNewSelectionFunction(TreeViewItem clickedItem, bool keepMultiSelection, bool useActionKeyAsShift);\n\n    protected new GetNewSelectionFunction getNewSelectionOverride\n    {\n        set\n        {\n            m_TreeView.getNewSelectionOverride = (x, y, z) => value(x as TreeViewItem, y, z);\n        }\n    }\n\n    protected new abstract TreeViewItem BuildRoot();\n\n    internal override TreeViewItem BuildRootInternal() => BuildRoot();\n\n    internal override IList<TreeViewItem<int>> BuildRowsInternal(TreeViewItem<int> root) => BuildRows(root as TreeViewItem).ToGenericIList();\n    protected virtual IList<TreeViewItem> BuildRows(TreeViewItem root) => base.BuildRowsInternal(root).ToNonGenericIList();\n\n    public new TreeViewState state => base.state as TreeViewState;\n    protected new TreeViewItem rootItem => base.rootItem as TreeViewItem;\n    protected new TreeViewItem hoveredItem => base.hoveredItem as TreeViewItem;\n\n    public new virtual IList<TreeViewItem> GetRows() => base.GetRowsInternal().ToNonGenericIList();\n    internal override IList<TreeViewItem<int>> GetRowsInternal() => GetRows().ToGenericIList();\n\n    protected new IList<TreeViewItem> FindRows(IList<int> ids) => base.FindRows(ids).ToNonGenericIList();\n    protected TreeViewItem FindItem(int id, TreeViewItem searchFromThisItem) => base.FindItem(id, searchFromThisItem) as TreeViewItem;\n    protected int FindRowOfItem(TreeViewItem item) => base.FindRowOfItem(item);\n    protected void SelectionClick(TreeViewItem item, bool keepMultiSelection) => base.SelectionClick(item, keepMultiSelection);\n    public bool BeginRename(TreeViewItem item) => base.BeginRename(item);\n    public bool BeginRename(TreeViewItem item, float delay) => base.BeginRename(item, delay);\n    protected float GetFoldoutIndent(TreeViewItem item) => base.GetFoldoutIndent(item);\n    protected float GetContentIndent(TreeViewItem item) => base.GetContentIndent(item);\n    protected void AddExpandedRows(TreeViewItem root, IList<TreeViewItem> rows) => base.AddExpandedRows(root, rows.ToGenericIList());\n\n    protected virtual bool CanMultiSelect(TreeViewItem item) => base.CanMultiSelectInternal(item);\n    internal override bool CanMultiSelectInternal(TreeViewItem<int> item) => CanMultiSelect(item as TreeViewItem);\n    protected virtual bool CanRename(TreeViewItem item) => base.CanRenameInternal(item);\n    internal override bool CanRenameInternal(TreeViewItem<int> item) => CanRename(item as TreeViewItem);\n\n    protected virtual bool CanStartDrag(CanStartDragArgs args) => base.CanStartDragInternal(args);\n\n    internal override bool CanStartDragInternal(TreeView<int>.CanStartDragArgs args) => CanStartDrag(args);\n    protected virtual DragAndDropVisualMode HandleDragAndDrop(DragAndDropArgs args) => base.HandleDragAndDropInternal(args);\n    internal override DragAndDropVisualMode HandleDragAndDropInternal(TreeView<int>.DragAndDropArgs args) => HandleDragAndDrop(args);\n    protected virtual bool CanBeParent(TreeViewItem item) => base.CanBeParentInternal(item);\n    internal override bool CanBeParentInternal(TreeViewItem<int> item) => CanBeParent(item as TreeViewItem);\n    protected virtual bool CanChangeExpandedState(TreeViewItem item) => base.CanChangeExpandedStateInternal(item);\n    internal override bool CanChangeExpandedStateInternal(TreeViewItem<int> item) => CanChangeExpandedState(item as TreeViewItem);\n    protected virtual bool DoesItemMatchSearch(TreeViewItem item, string search) => base.DoesItemMatchSearchInternal(item, search);\n    internal override bool DoesItemMatchSearchInternal(TreeViewItem<int> item, string search) => DoesItemMatchSearch(item as TreeViewItem, search);\n    protected virtual void RowGUI(RowGUIArgs args) => base.RowGUIInternal(args);\n    internal override void RowGUIInternal(TreeView<int>.RowGUIArgs args) => RowGUI(args);\n    protected virtual float GetCustomRowHeight(int row, TreeViewItem item) => base.GetCustomRowHeightInternal(row, item);\n    internal override float GetCustomRowHeightInternal(int row, TreeViewItem<int> item) => GetCustomRowHeight(row, item as TreeViewItem);\n    protected virtual Rect GetRenameRect(Rect rowRect, int row, TreeViewItem item) => base.GetRenameRectInternal(rowRect, row, item);\n    internal override Rect GetRenameRectInternal(Rect rowRect, int row, TreeViewItem<int> item) => GetRenameRect(rowRect, row, item as TreeViewItem);\n    protected static void SetupParentsAndChildrenFromDepths(TreeViewItem root, IList<TreeViewItem> rows) => TreeView<int>.SetupParentsAndChildrenFromDepths(root, rows.ToGenericIList());\n    protected static void SetupDepthsFromParentsAndChildren(TreeViewItem root) => TreeView<int>.SetupDepthsFromParentsAndChildren(root);\n    protected new static List<TreeViewItem> CreateChildListForCollapsedParent() => TreeView<int>.CreateChildListForCollapsedParent().ToNonGenericList();\n    protected static bool IsChildListForACollapsedParent(IList<TreeViewItem> childList) => TreeView<int>.IsChildListForACollapsedParent(childList.ToGenericIList());\n}\n\n[Obsolete(\"TreeView is now deprecated. You can likely now use TreeView<int> instead and not think more about it. But if you were using that identifier to store InstanceID data, you should instead opt to upgrade your TreeViews to use TreeView<InstanceID> to get the proper typing.\")]\npublic abstract class TreeViewInternal : TreeView<int>\n{\n    protected TreeViewInternal(TreeViewState state)\n        : base(state) { }\n\n    protected TreeViewInternal(TreeViewState state, MultiColumnHeader multiColumnHeader)\n        : base(state, multiColumnHeader) { }\n\n    protected override TreeViewItem<int> BuildRoot() => BuildRootInternal();\n\n    internal abstract TreeViewItem BuildRootInternal();\n}\n\n[Obsolete]\nstatic class TreeViewItemConvertUtility {\n    public static List<TreeViewItem> ToNonGenericList(this List<TreeViewItem<int>> items) => (GenericTreeViewItemToNonGenericTreeViewItemList)items;\n    public static List<TreeViewItem<int>> ToGenericList(this List<TreeViewItem> items) => (GenericTreeViewItemToNonGenericTreeViewItemList)items;\n    public static IList<TreeViewItem> ToNonGenericIList(this IList<TreeViewItem<int>> items) => new GenericTreeViewItemToNonGenericTreeViewItemIList(items).nonGeneric;\n    public static IList<TreeViewItem<int>> ToGenericIList(this IList<TreeViewItem> items) => new GenericTreeViewItemToNonGenericTreeViewItemIList(items).generic;\n}\n\n[StructLayout(LayoutKind.Explicit)]\n[Obsolete]\nstruct GenericTreeViewItemToNonGenericTreeViewItemList\n{\n    [FieldOffset(0)] public List<TreeViewItem> nonGeneric;\n    [FieldOffset(0)] public List<TreeViewItem<int>> generic;\n\n    public static implicit operator GenericTreeViewItemToNonGenericTreeViewItemList(List<TreeViewItem> items) => new() {nonGeneric=items};\n    public static implicit operator GenericTreeViewItemToNonGenericTreeViewItemList(List<TreeViewItem<int>> items) => new() {generic = items};\n    public static implicit operator List<TreeViewItem>(GenericTreeViewItemToNonGenericTreeViewItemList value) => value.nonGeneric;\n    public static implicit operator List<TreeViewItem<int>>(GenericTreeViewItemToNonGenericTreeViewItemList value) => value.generic;\n}\n\n[StructLayout(LayoutKind.Explicit)]\n[Obsolete]\nstruct GenericTreeViewItemToNonGenericTreeViewItemIList\n{\n    [FieldOffset(0)] public IList<TreeViewItem> nonGeneric;\n    [FieldOffset(0)] public IList<TreeViewItem<int>> generic;\n\n    public GenericTreeViewItemToNonGenericTreeViewItemIList(IList<TreeViewItem> items)\n    {\n        generic = null;\n        nonGeneric=items;\n    }\n\n    public GenericTreeViewItemToNonGenericTreeViewItemIList(IList<TreeViewItem<int>> items)\n    {\n        nonGeneric = null;\n        generic = items;\n    }\n}\n\n[Obsolete(\"TreeViewItem is now deprecated. You can likely now use TreeViewItem<int> instead and not think more about it. But if you were using that identifier to store InstanceID data, you should instead opt to upgrade your TreeViews to use TreeViewItem<InstanceID> to get the proper typing.\")]\npublic class TreeViewItem : TreeViewItem<int>\n{\n    public new virtual List<TreeViewItem> children\n    {\n        get => base.childrenInternal.ToNonGenericList();\n        set => base.childrenInternal = value.ToGenericList();\n    }\n    internal override List<TreeViewItem<int>> childrenInternal\n    {\n        get => children.ToGenericList();\n        set => children = value.ToNonGenericList();\n    }\n\n\n    internal override TreeViewItem<int> ParentInternal\n    {\n        get => parent;\n        set => parent = value as TreeViewItem;\n    }\n\n    public new virtual TreeViewItem parent { get { return base.ParentInternal as TreeViewItem; } set { base.ParentInternal = value; } }\n\n    public void AddChild(TreeViewItem child) => base.AddChild(child);\n\n\n    internal override int CompareToInternal(TreeViewItem<int> other) => CompareTo(other as TreeViewItem);\n\n    public virtual int CompareTo(TreeViewItem other) => base.CompareToInternal(other);\n\n    public TreeViewItem() { }\n\n    public TreeViewItem(int id) : base(id){}\n    public TreeViewItem(int id, int depth): base(id, depth) { }\n    public TreeViewItem(int id, int depth, string displayName) : base(id, depth, displayName) { }\n    internal TreeViewItem(int id, int depth, TreeViewItem parent, string displayName) : base(id, depth, parent, displayName) { }\n}\n\n[Obsolete(\"TreeViewState is now deprecated. You can likely now use TreeViewState<int> instead and not think more about it. But if you were using that identifier to store InstanceID data, you should instead opt to upgrade your TreeViews to use TreeViewState<InstanceID> to get the proper typing.\")]\npublic class TreeViewState : TreeViewState<int> {}\n\n[Obsolete]\ninternal class TreeViewController : TreeViewController<int>\n{\n    public TreeViewController(EditorWindow editorWindow, TreeViewState treeViewState) : base(editorWindow, treeViewState)\n    {\n\n    }\n\n    public void Init(Rect rect, ITreeViewDataSource data, ITreeViewGUI gui, ITreeViewDragging<int> dragging) => base.Init(rect, data, new TreeViewGUIAbstract(gui), dragging);\n    public new ITreeViewDataSource data { get =>base.data as ITreeViewDataSource; set => base.data = value; }\n    public new TreeViewState state { get =>base.state as TreeViewState; set => base.state = value; }\n}\n\n[Obsolete]\ninternal abstract class TreeViewDataSource : TreeViewDataSource<int>, ITreeViewDataSource\n{\n    protected TreeViewDataSource(TreeViewController treeView)\n        : base(treeView) { }\n\n    public new TreeViewItem root => base.root as TreeViewItem;\n    public new virtual IList<TreeViewItem> GetRows() => base.GetRowsInternal().ToNonGenericIList();\n    public override IList<TreeViewItem<int>> GetRowsInternal() => GetRows().ToGenericIList();\n    protected new TreeViewItem m_RootItem { get => base.m_RootItem as TreeViewItem; set => base.m_RootItem = value; }\n    protected new TreeViewController m_TreeView { get => m_TreeViewInternal as TreeViewController; set => m_TreeViewInternal = value; }\n    public virtual bool IsExpanded(TreeViewItem item) => base.IsExpandedInternal(item);\n    public override bool IsExpandedInternal(TreeViewItem<int> item) => IsExpanded(item as TreeViewItem);\n    public virtual bool IsExpandable(TreeViewItem item) => base.IsExpandableInternal(item);\n    public override bool IsExpandableInternal(TreeViewItem<int> item) => IsExpandable(item as TreeViewItem);\n    public virtual bool CanBeParent(TreeViewItem item) => base.CanBeParentInternal(item);\n    public override bool CanBeParentInternal(TreeViewItem<int> item) => CanBeParent(item as TreeViewItem);\n}\n\n[Obsolete]\ninternal abstract class TreeViewDragging : TreeViewDragging<int>\n{\n    public TreeViewDragging(TreeViewController<int> treeView) : base(treeView)\n    {\n    }\n\n    public virtual bool CanStartDrag(TreeViewItem targetItem, List<int> draggedItemIDs, Vector2 mouseDownPosition) => base.CanStartDragInternal(targetItem, draggedItemIDs, mouseDownPosition);\n    public override bool CanStartDragInternal(TreeViewItem<int> targetItem, List<int> draggedItemIDs, Vector2 mouseDownPosition)=> CanStartDrag(targetItem as TreeViewItem, draggedItemIDs, mouseDownPosition);\n    public override void StartDragInternal(TreeViewItem<int> draggedItem, List<int> draggedItemIDs) => StartDrag(draggedItem as TreeViewItem, draggedItemIDs);\n    public virtual void StartDrag(TreeViewItem draggedItem, List<int> draggedItemIDs) => base.StartDragInternal(draggedItem, draggedItemIDs);\n    public virtual DragAndDropVisualMode DoDrag(TreeViewItem parentItem, TreeViewItem targetItem, bool perform, DropPosition dropPosition) => base.DoDragInternal(parentItem, targetItem, perform, dropPosition);\n    public override DragAndDropVisualMode DoDragInternal(TreeViewItem<int> parentItem, TreeViewItem<int> targetItem, bool perform, DropPosition dropPosition) => DoDrag(parentItem as TreeViewItem, targetItem as TreeViewItem, perform, dropPosition);\n    public virtual bool DragElement(TreeViewItem targetItem, Rect targetItemRect, int row) => base.DragElementInternal(targetItem, targetItemRect, row);\n    public override bool DragElementInternal(TreeViewItem<int> targetItem, Rect targetItemRect, int row) => DragElement(targetItem as TreeViewItem, targetItemRect, row);\n}\n\n[Obsolete]\ninternal interface ITreeViewGUI\n{\n    void OnInitialize();\n    Vector2 GetTotalSize();\n    void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible);\n    Rect GetRowRect(int row, float rowWidth);\n    Rect GetRectForFraming(int row);\n\n    void BeginPingItem(TreeViewItem item, float topPixelOfRow, float availableWidth);\n    void EndPingItem();\n    bool BeginRename(TreeViewItem item, float delay);\n    void EndRename();\n    float GetContentIndent(TreeViewItem item);\n    int GetNumRowsOnPageUpDown(TreeViewItem fromItem, bool pageUp, float heightOfTreeView);\n    Rect GetRenameRect(Rect rect, int row, TreeViewItem item);\n    void OnRowGUI(Rect rect, TreeViewItem item, int row, bool selected, bool focused);\n    void BeginRowGUI();                                                                     // use for e.g clearing state before OnRowGUI calls\n    void EndRowGUI();                                                                       // use for handling stuff after all rows have had their OnRowGUI\n    float halfDropBetweenHeight { get; }\n    float topRowMargin { get; }\n    float bottomRowMargin { get; }\n}\n\n[Obsolete]\ninternal class TreeViewGUIAbstract : ITreeViewGUI<int>\n{\n    ITreeViewGUI treeViewGUI;\n\n    public TreeViewGUIAbstract(ITreeViewGUI treeViewGUI)\n    {\n        this.treeViewGUI = treeViewGUI;\n    }\n\n    public void OnInitialize() => treeViewGUI.OnInitialize();\n    public Vector2 GetTotalSize() => treeViewGUI.GetTotalSize();\n    public void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible) => treeViewGUI.GetFirstAndLastRowVisible(out firstRowVisible, out lastRowVisible);\n    public Rect GetRowRect(int row, float rowWidth) => treeViewGUI.GetRowRect(row, rowWidth);\n    public Rect GetRectForFraming(int row) => treeViewGUI.GetRectForFraming(row);\n    public int GetNumRowsOnPageUpDown(TreeViewItem<int> fromItem, bool pageUp, float heightOfTreeView) => treeViewGUI.GetNumRowsOnPageUpDown(fromItem as TreeViewItem, pageUp, heightOfTreeView);\n    public void OnRowGUI(Rect rowRect, TreeViewItem<int> item, int row, bool selected, bool focused) => treeViewGUI.OnRowGUI(rowRect, item as TreeViewItem, row, selected, focused);\n    public void BeginRowGUI() => treeViewGUI.BeginRowGUI();\n    public void EndRowGUI() => treeViewGUI.EndRowGUI();\n    public void BeginPingItem(TreeViewItem<int> item, float topPixelOfRow, float availableWidth) => treeViewGUI.BeginPingItem(item as TreeViewItem, topPixelOfRow, availableWidth);\n    public void EndPingItem() => treeViewGUI.EndPingItem();\n    public bool BeginRename(TreeViewItem<int> item, float delay) => treeViewGUI.BeginRename(item as TreeViewItem, delay);\n    public void EndRename() => treeViewGUI.EndRename();\n    public Rect GetRenameRect(Rect rowRect, int row, TreeViewItem<int> item) => treeViewGUI.GetRenameRect(rowRect, row, item as TreeViewItem);\n    public float GetContentIndent(TreeViewItem<int> item) => treeViewGUI.GetContentIndent(item as TreeViewItem);\n    public float halfDropBetweenHeight => treeViewGUI.halfDropBetweenHeight;\n    public float topRowMargin => treeViewGUI.topRowMargin;\n    public float bottomRowMargin => treeViewGUI.bottomRowMargin;\n}\n\n[Obsolete]\ninternal abstract class TreeViewGUI : TreeViewGUI<int>\n{\n    protected TreeViewGUI(TreeViewController<int> treeView)\n        : base(treeView) { }\n\n    protected TreeViewGUI(TreeViewController<int> treeView, bool useHorizontalScroll)\n        : base(treeView, useHorizontalScroll) { }\n\n    public new System.Action<TreeViewItem, Rect> iconOverlayGUI { get; set; }\n\n    virtual public void OnRowGUI(Rect rowRect, TreeViewItem  item, int row, bool selected, bool focused) => base.OnRowGUIInternal(rowRect, item, row, selected, focused);\n    override public void OnRowGUIInternal(Rect rowRect, TreeViewItem<int>  item, int row, bool selected, bool focused) => OnRowGUI(rowRect, item as TreeViewItem, row, selected, focused);\n    virtual public bool BeginRename(TreeViewItem  item, float delay) => base.BeginRenameInternal(item, delay);\n    override public bool BeginRenameInternal(TreeViewItem<int>  item, float delay) => BeginRename(item as TreeViewItem, delay);\n    protected virtual Texture GetIconForItem(TreeViewItem  item) => base.GetIconForItemInternal(item);\n    protected override Texture GetIconForItemInternal(TreeViewItem<int>  item) => GetIconForItem(item as TreeViewItem);\n}\n\n[Obsolete]\ninternal interface ITreeViewDataSource : ITreeViewDataSource<int>\n{\n    new TreeViewItem root { get; }\n    new IList<TreeViewItem> GetRows();\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewController.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.AnimatedValues;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    /*\n     Description:\n\n     The TreeViewController requires implementations from the following three interfaces:\n        ITreeViewDataSource:    Should handle data fetching and data structure\n        ITreeViewGUI:           Should handle visual representation of TreeView and mouse input on row controls\n        ITreeViewDragging:      Should handle dragging, temp expansion of items, allow/disallow dropping\n        The TreeViewController handles: Navigation, Item selection and initiates dragging\n\n     Important concepts:\n     1) The Item Tree: the DataSource should create the tree structure of items with parent and children references\n     2) Rows: the DataSource should be able to provide the visible items; a simple list that will become the rows we render.\n     3) The root item might not be visible; its up to the data source to deliver a set of visible items from the tree\n\n     */\n\n    [System.Serializable]\n    public class TreeViewState<TIdentifier> where TIdentifier : unmanaged, System.IEquatable<TIdentifier>\n    {\n        public List<TIdentifier> selectedIDs { get { return m_SelectedIDs; } set { m_SelectedIDs = value; } }\n        public TIdentifier lastClickedID { get { return m_LastClickedID; } set { m_LastClickedID = value; } }\n        public List<TIdentifier> expandedIDs { get { return m_ExpandedIDs; } set { m_ExpandedIDs = value; } }\n        internal RenameOverlay<TIdentifier> renameOverlay { get { return m_RenameOverlay; } set { m_RenameOverlay = value; } }\n\n        public string searchString { get { return m_SearchString; } set { m_SearchString = value; } }\n        public Vector2 scrollPos;\n\n        // Selection state\n        [SerializeField] private List<TIdentifier> m_SelectedIDs = new List<TIdentifier>();\n        [SerializeField] private TIdentifier m_LastClickedID; // used for navigation\n\n        // Expanded state (assumed sorted)\n        [SerializeField] private List<TIdentifier> m_ExpandedIDs = new List<TIdentifier>();\n\n        // Rename and create asset state\n        [SerializeField] private RenameOverlay<TIdentifier> m_RenameOverlay = new RenameOverlay<TIdentifier>();\n\n        // Search state (can be used by Datasource to filter tree when reloading)\n        [SerializeField] private string m_SearchString;\n\n        internal virtual void OnAwake()\n        {\n            // Clear state that should not survive closing/starting Unity (If TreeViewState is in EditorWindow that are serialized in a layout file)\n            m_RenameOverlay.Clear();\n        }\n    }\n\n    internal struct TreeViewSelectState<TIdentifier>\n    {\n        public List<TIdentifier> selectedIDs;\n        public TIdentifier lastClickedID;\n        public bool keepMultiSelection;\n        public bool useShiftAsActionKey;\n    }\n\n    internal class TreeViewController<TIdentifier> where TIdentifier : unmanaged, System.IEquatable<TIdentifier>\n    {\n        public System.Action<TIdentifier[]> selectionChangedCallback { get; set; } // ids\n        public System.Action<TIdentifier> itemSingleClickedCallback { get; set; } // id\n        public System.Action<TIdentifier> itemDoubleClickedCallback { get; set; } // id\n        public System.Action<TIdentifier[], bool> dragEndedCallback { get; set; } // dragged ids, if null then drag was not allowed, bool == true if dragging tree view items from own treeview, false if drag was started outside\n        public System.Action<TIdentifier> contextClickItemCallback { get; set; } // clicked item id\n        public System.Action contextClickOutsideItemsCallback { get; set; }\n        public System.Action keyboardInputCallback { get; set; }\n        public System.Action expandedStateChanged { get; set; }\n        public System.Action<string> searchChanged { get; set; }\n        public System.Action<Vector2> scrollChanged { get; set; }\n        public System.Action<TIdentifier, Rect> onGUIRowCallback { get; set; }  // <id, Rect of row>\n\n        internal System.Action<TIdentifier, Rect> onFoldoutButton { get; set; }  // <id, Rect of row>\n\n        // Main state\n        GUIView m_GUIView;                                              // Containing view for this tree: used for checking if we have focus and for requesting repaints\n        public ITreeViewDataSource<TIdentifier> data { get; set; }                   // Data provider for this tree: handles data fetching\n        public ITreeViewDragging<TIdentifier> dragging { get; set; }                 // Handle dragging\n        public ITreeViewGUI<TIdentifier> gui { get; set; }                           // Handles GUI (input and rendering)\n        public TreeViewState<TIdentifier> state { get; set; }                        // State that persists script reloads\n        public GUIStyle horizontalScrollbarStyle { get; set; }\n        public GUIStyle verticalScrollbarStyle { get; set; }\n        public GUIStyle scrollViewStyle { get; set; }\n        public TreeViewItemExpansionAnimator<TIdentifier> expansionAnimator { get { return m_ExpansionAnimator; } }\n        readonly TreeViewItemExpansionAnimator<TIdentifier> m_ExpansionAnimator = new TreeViewItemExpansionAnimator<TIdentifier>();\n        AnimFloat m_FramingAnimFloat;\n\n        bool m_StopIteratingItems;\n\n        public bool deselectOnUnhandledMouseDown { get; set; }\n        public bool enableItemHovering { get; set; }\n\n        IntegerCache m_DragSelection = new IntegerCache();\n        IntegerCache m_CachedSelection = new IntegerCache();\n\n        struct IntegerCache\n        {\n            List<TIdentifier> m_List;\n            HashSet<TIdentifier> m_HashSet;\n\n            public bool Contains(TIdentifier id)\n            {\n                if (m_HashSet == null)\n                    return false;\n\n                return m_HashSet.Contains(id);\n            }\n\n            public void Set(List<TIdentifier> list)\n            {\n                if (list == null)\n                    throw new ArgumentNullException(nameof(list));\n\n                if (!Equals(list))\n                {\n                    m_List = new List<TIdentifier>(list);\n                    m_HashSet = new HashSet<TIdentifier>(list);\n                }\n            }\n\n            public List<TIdentifier> Get()\n            {\n                return m_List;\n            }\n\n            public void Clear()\n            {\n                if (m_List == null)\n                    return;\n\n                m_List.Clear();\n                m_HashSet.Clear();\n            }\n\n            public bool HasValues()\n            {\n                if (m_List == null)\n                    return false;\n\n                return m_List.Count > 0;\n            }\n\n            bool Equals(List<TIdentifier> list)\n            {\n                if (m_List == null || list == null)\n                    return false;\n\n                int count = m_List.Count;\n                if (count != list.Count)\n                    return false;\n\n                for (int i = 0; i < count; ++i)\n                {\n                    if (!list[i].Equals(m_List[i]))\n                        return false;\n                }\n\n                return true;\n            }\n        }\n\n        bool m_UseScrollView = true;                                    // Internal scrollview can be omitted when e.g mulitple tree views in one scrollview is wanted\n        bool m_ConsumeKeyDownEvents = true;\n        bool m_AllowRenameOnMouseUp = true;\n\n        internal const string kExpansionAnimationPrefKey = \"TreeViewExpansionAnimation\";\n        bool m_UseExpansionAnimation = EditorPrefs.GetBool(kExpansionAnimationPrefKey, true);\n        public bool useExpansionAnimation { get { return m_UseExpansionAnimation; } set { m_UseExpansionAnimation = value; } }\n\n        // Cached values during one event (for convenience)\n        bool m_GrabKeyboardFocus;\n        Rect m_TotalRect;\n        Rect m_VisibleRect;\n        Rect m_ContentRect;\n        bool m_HadFocusLastEvent;                           // Cached from last event for keyboard focus changed event\n        int m_KeyboardControlID;\n\n        const double kSlowSelectTimeout = 0.2;\n        const float kSpaceForScrollBar = 16f;\n        public TreeViewItem<TIdentifier> hoveredItem { get; set; }\n\n        public TreeViewController(EditorWindow editorWindow, TreeViewState<TIdentifier> treeViewState)\n        {\n            m_GUIView = editorWindow ? editorWindow.m_Parent : GUIView.current;\n            state = treeViewState;\n        }\n\n        public void Init(Rect rect, ITreeViewDataSource<TIdentifier> data, ITreeViewGUI<TIdentifier> gui, ITreeViewDragging<TIdentifier> dragging)\n        {\n            this.data = data;\n            this.gui = gui;\n            this.dragging = dragging;\n            m_VisibleRect = m_TotalRect = rect; // We initialize the total rect because it might be needed for framing selection when reloading data the first time.\n\n            // Allow sub systems to set up delegates etc after treeview references have been set up\n            data.OnInitialize();\n            gui.OnInitialize();\n            if (dragging != null)\n                dragging.OnInitialize();\n\n            expandedStateChanged += ExpandedStateHasChanged;\n\n            m_FramingAnimFloat = new AnimFloat(state.scrollPos.y, AnimatedScrollChanged);\n        }\n\n        void ExpandedStateHasChanged()\n        {\n            m_StopIteratingItems = true;\n        }\n\n        public bool isSearching\n        {\n            get { return !string.IsNullOrEmpty(state.searchString); }\n        }\n\n        public bool isDragging\n        {\n            get { return m_DragSelection.HasValues(); }\n        }\n\n        public bool IsDraggingItem(TreeViewItem<TIdentifier> item)\n        {\n            return m_DragSelection.Contains(item.id);\n        }\n\n        public bool showingVerticalScrollBar\n        {\n            get { return m_VisibleRect.height > 0 && m_ContentRect.height > m_VisibleRect.height; }\n        }\n\n        public bool showingHorizontalScrollBar\n        {\n            get { return m_VisibleRect.width > 0 && m_ContentRect.width > m_VisibleRect.width; }\n        }\n\n        public string searchString\n        {\n            get\n            {\n                return state.searchString;\n            }\n            set\n            {\n                if (string.ReferenceEquals(state.searchString, value))\n                    return;\n\n                if (state.searchString == value)\n                    return;\n\n                state.searchString = value;\n                data.OnSearchChanged();\n                if (searchChanged != null)\n                    searchChanged(state.searchString);\n            }\n        }\n\n        public bool useScrollView\n        {\n            get { return m_UseScrollView; }\n            set { m_UseScrollView = value; }\n        }\n\n        public Rect visibleRect\n        {\n            get { return m_VisibleRect; }\n        }\n\n        public bool IsSelected(TIdentifier id)\n        {\n            return state.selectedIDs.Contains(id);\n        }\n\n        public bool HasSelection()\n        {\n            return state.selectedIDs.Count > 0;\n        }\n\n        public TIdentifier[] GetSelection()\n        {\n            return state.selectedIDs.ToArray();\n        }\n\n        public TIdentifier[] GetRowIDs()\n        {\n            return (from item in data.GetRows() select item.id).ToArray();\n        }\n\n        public void SetSelection(TIdentifier[] selectedIDs, bool revealSelectionAndFrameLastSelected)\n        {\n            const bool animatedFraming = false;\n            SetSelection(selectedIDs, revealSelectionAndFrameLastSelected, animatedFraming);\n        }\n\n        public void SetSelection(TIdentifier[] selectedIDs, bool revealSelectionAndFrameLastSelected, bool animatedFraming)\n        {\n            // Keep for debugging\n            //Debug.Log (\"SetSelection: new selection: \" + DebugUtils.ListToString(new List<int>(selectedIDs)));\n\n            // Init new state\n            if (selectedIDs.Length > 0)\n            {\n                if (revealSelectionAndFrameLastSelected)\n                {\n                    data.RevealItems(selectedIDs);\n                }\n\n                state.selectedIDs = new List<TIdentifier>(selectedIDs);\n\n                // Ensure that our key navigation is setup\n                bool hasLastClicked = state.selectedIDs.IndexOf(state.lastClickedID) >= 0;\n                if (!hasLastClicked)\n                {\n                    // See if we can find a valid id, we check the last selected (selectedids might contain invalid ids e.g scene objects in project browser and vice versa)\n                    TIdentifier lastSelectedID = selectedIDs.Last();\n                    if (data.GetRow(lastSelectedID) != -1)\n                    {\n                        state.lastClickedID = lastSelectedID;\n                        hasLastClicked = true;\n                    }\n                    else\n                        state.lastClickedID = default;\n                }\n\n                if (revealSelectionAndFrameLastSelected && hasLastClicked)\n                    Frame(state.lastClickedID, true, false, animatedFraming);\n            }\n            else\n            {\n                state.selectedIDs.Clear();\n                state.lastClickedID = default;\n            }\n\n            // Should not fire callback since this is called from outside\n            // NotifyListenersThatSelectionChanged ()\n        }\n\n        public TreeViewItem<TIdentifier> FindItem(TIdentifier id)\n        {\n            return data.FindItem(id);\n        }\n\n        [System.Obsolete(\"SetUseScrollView has been deprecated. Use property useScrollView instead.\")]\n        public void SetUseScrollView(bool useScrollView)\n        {\n            m_UseScrollView = useScrollView;\n        }\n\n        public void SetConsumeKeyDownEvents(bool consume)\n        {\n            m_ConsumeKeyDownEvents = consume;\n        }\n\n        public void Repaint()\n        {\n            if (m_GUIView != null)\n                m_GUIView.Repaint();\n        }\n\n        public void ReloadData()\n        {\n            // Do not clear rename data here, we could be reloading due to assembly reload\n            // and we want to let our rename session survive that\n\n            data.ReloadData();\n            Repaint();\n\n            m_StopIteratingItems = true;\n        }\n\n        public bool HasFocus()\n        {\n            bool hasKeyFocus = (m_GUIView != null) ? m_GUIView.hasFocus : EditorGUIUtility.HasCurrentWindowKeyFocus();\n            return hasKeyFocus && (GUIUtility.keyboardControl == m_KeyboardControlID);\n        }\n\n        static internal int GetItemControlID(TreeViewItem<TIdentifier> item)\n        {\n            return ((item != null) ? item.id.GetHashCode() : 0) + 10000000;\n        }\n\n        public void HandleUnusedMouseEventsForItem(Rect rect, TreeViewItem<TIdentifier> item, int row)\n        {\n            int itemControlID = GetItemControlID(item);\n\n            Event evt = Event.current;\n\n            switch (evt.GetTypeForControl(itemControlID))\n            {\n                case EventType.MouseDown:\n                    if (rect.Contains(Event.current.mousePosition))\n                    {\n                        // Handle mouse down on entire line\n                        if (Event.current.button == 0)\n                        {\n                            // Grab keyboard\n                            GUIUtility.keyboardControl = m_KeyboardControlID;\n                            Repaint(); // Ensure repaint so we can show we have keyboard focus\n\n                            // Let client handle double click\n                            if (Event.current.clickCount == 2)\n                            {\n                                if (itemDoubleClickedCallback != null)\n                                    itemDoubleClickedCallback(item.id);\n                            }\n                            else\n                            {\n                                double selectStartTime = Time.realtimeSinceStartup;\n                                var dragSelection = GetNewSelection(item, true, false);\n                                bool dragAbortedBySlowSelect = (Time.realtimeSinceStartup - selectStartTime) > kSlowSelectTimeout;\n\n                                bool canStartDrag = !dragAbortedBySlowSelect && dragging != null && dragSelection.Count != 0 && dragging.CanStartDrag(item, dragSelection, Event.current.mousePosition);\n                                if (canStartDrag)\n                                {\n                                    // Prepare drag and drop delay (we start the drag after a couple of pixels mouse drag: See the case MouseDrag below)\n                                    m_DragSelection.Set(dragSelection);\n                                    DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), GetItemControlID(item));\n                                    delay.mouseDownPosition = Event.current.mousePosition;\n                                }\n                                else\n                                {\n                                    // If dragging is not supported or not allowed for the drag selection then handle selection on mouse down\n                                    // (when dragging is handled we handle selection on mouse up to e.g allow to drag to object fields in the inspector)\n                                    m_DragSelection.Clear();\n\n                                    if (m_AllowRenameOnMouseUp)\n                                        m_AllowRenameOnMouseUp = (state.selectedIDs.Count == 1 && state.selectedIDs[0].Equals(item.id)); // If first time selection then prevent starting a rename on the following mouse up after this mouse down\n\n                                    SelectionClick(item, false);\n\n                                    // Notify about single click\n                                    if (itemSingleClickedCallback != null)\n                                        itemSingleClickedCallback(item.id);\n                                }\n\n                                GUIUtility.hotControl = GetItemControlID(item);\n                            }\n                            evt.Use();\n                        }\n                        else if (Event.current.button == 1)\n                        {\n                            // Right mouse down selects;\n                            bool keepMultiSelection = true;\n                            SelectionClick(item, keepMultiSelection);\n                        }\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == itemControlID && dragging != null && m_DragSelection.HasValues())\n                    {\n                        DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), itemControlID);\n                        if (delay.CanStartDrag() && dragging.CanStartDrag(item, m_DragSelection.Get(), delay.mouseDownPosition))\n                        {\n                            dragging.StartDrag(item, m_DragSelection.Get());\n                            GUIUtility.hotControl = 0;\n                        }\n\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == itemControlID)\n                    {\n                        // When having the temp dragging selection delay the the selection until mouse up\n                        bool useMouseUpSelection = m_DragSelection.HasValues();\n\n                        // Clear state before SelectionClick since it can ExitGUI early\n                        GUIUtility.hotControl = 0;\n                        m_DragSelection.Clear();\n                        evt.Use();\n\n                        // On Mouse up either start name editing or change selection (if not done on mouse down)\n                        if (rect.Contains(evt.mousePosition))\n                        {\n                            Rect renameActivationRect = gui.GetRenameRect(rect, row, item);\n                            List<TIdentifier> selected = state.selectedIDs;\n                            if (m_AllowRenameOnMouseUp && selected != null && selected.Count == 1 && selected[0].Equals(item.id) && renameActivationRect.Contains(evt.mousePosition) && !EditorGUIUtility.HasHolddownKeyModifiers(evt))\n                            {\n                                BeginNameEditing(0.5f);\n                            }\n                            else if (useMouseUpSelection)\n                            {\n                                SelectionClick(item, false);\n\n                                // Notify about single click\n                                if (itemSingleClickedCallback != null)\n                                    itemSingleClickedCallback(item.id);\n                            }\n                        }\n                    }\n                    break;\n\n                case EventType.DragUpdated:\n                case EventType.DragPerform:\n                {\n                    //bool firstItem = row == 0;\n                    if (dragging != null && dragging.DragElement(item, rect, row))\n                        GUIUtility.hotControl = 0;\n                }\n                break;\n\n                case EventType.ContextClick:\n                    if (rect.Contains(evt.mousePosition))\n                    {\n                        // Do not use the event so the client can react to the context click (here we just handled the treeview selection)\n                        if (contextClickItemCallback != null)\n                            contextClickItemCallback(item.id);\n                    }\n                    break;\n            }\n        }\n\n        public void GrabKeyboardFocus()\n        {\n            m_GrabKeyboardFocus = true;\n        }\n\n        public void NotifyListenersThatSelectionChanged()\n        {\n            if (selectionChangedCallback != null)\n                selectionChangedCallback(state.selectedIDs.ToArray());\n        }\n\n        public void NotifyListenersThatDragEnded(TIdentifier[] draggedIDs, bool draggedItemsFromOwnTreeView)\n        {\n            if (dragEndedCallback != null)\n                dragEndedCallback(draggedIDs, draggedItemsFromOwnTreeView);\n        }\n\n        public Vector2 GetContentSize()\n        {\n            return gui.GetTotalSize();\n        }\n\n        public Rect GetTotalRect()\n        {\n            return m_TotalRect;\n        }\n\n        public void SetTotalRect(Rect rect)\n        {\n            m_TotalRect = rect;\n        }\n\n        public bool IsItemDragSelectedOrSelected(TreeViewItem<TIdentifier> item)\n        {\n            return m_DragSelection.HasValues() ? m_DragSelection.Contains(item.id) : m_CachedSelection.Contains(item.id);\n        }\n\n        public bool animatingExpansion { get { return m_UseExpansionAnimation && m_ExpansionAnimator.isAnimating; } }\n\n        void DoItemGUI(TreeViewItem<TIdentifier> item, int row, float rowWidth, bool hasFocus)\n        {\n            // Check valid row\n            if (row < 0 || row >= data.rowCount)\n            {\n                Debug.LogError(\"Invalid. Org row: \" + (row) + \" Num rows \" + data.rowCount);\n                return;\n            }\n\n            bool selected = IsItemDragSelectedOrSelected(item);\n\n            Rect rowRect = gui.GetRowRect(row, rowWidth);\n\n            // 1. Before row GUI\n            if (animatingExpansion)\n                rowRect = m_ExpansionAnimator.OnBeginRowGUI(row, rowRect);\n\n            // 2. Do row GUI\n            if (animatingExpansion)\n                m_ExpansionAnimator.OnRowGUI(row);\n            gui.OnRowGUI(rowRect, item, row, selected, hasFocus);\n\n            // 3. Draw extra gui callbacks\n            if (onGUIRowCallback != null)\n            {\n                float indent = gui.GetContentIndent(item);\n                Rect indentedRect = new Rect(rowRect.x + indent, rowRect.y, rowRect.width - indent, rowRect.height);\n                onGUIRowCallback(item.id, indentedRect);\n            }\n\n            // 4. After row GUI\n            if (animatingExpansion)\n                m_ExpansionAnimator.OnEndRowGUI(row);\n\n            HandleUnusedMouseEventsForItem(rowRect, item, row);\n        }\n\n        public void OnGUI(Rect rect, int keyboardControlID)\n        {\n            m_KeyboardControlID = keyboardControlID;\n\n            Event evt = Event.current;\n            if (evt.type == EventType.Repaint)\n            {\n                m_TotalRect = rect;\n                m_CachedSelection.Set(state.selectedIDs);\n            }\n\n            m_GUIView = GUIView.current;\n\n            // End rename if the window do not have focus\n            if (m_GUIView != null && !m_GUIView.hasFocus && state.renameOverlay.IsRenaming())\n            {\n                EndNameEditing(true);\n            }\n\n            // Grab keyboard focus if requested\n            if (m_GrabKeyboardFocus)\n            {\n                m_GrabKeyboardFocus = false;\n                GUIUtility.keyboardControl = m_KeyboardControlID;\n                Repaint(); // Ensure repaint so we can show we have keyboard focus\n            }\n\n            bool isMouseDownInTotalRect = evt.type == EventType.MouseDown && m_TotalRect.Contains(evt.mousePosition);\n            if (isMouseDownInTotalRect)\n            {\n                m_AllowRenameOnMouseUp = true; // reset value (can be changed later in this event if the TreeView gets focus)\n            }\n\n            // Might change expanded state so call before InitIfNeeded (delayed collapse until animation is done)\n            if (animatingExpansion)\n                m_ExpansionAnimator.OnBeforeAllRowsGUI();\n\n            data.InitIfNeeded();\n\n            // Calc content size\n            Vector2 contentSize = gui.GetTotalSize();\n            m_ContentRect = new Rect(0, 0, contentSize.x, contentSize.y);\n\n            if (m_UseScrollView)\n            {\n                state.scrollPos = GUI.BeginScrollView(m_TotalRect, state.scrollPos, m_ContentRect, false, false,\n                    horizontalScrollbarStyle != null ? horizontalScrollbarStyle : GUI.skin.horizontalScrollbar,\n                    verticalScrollbarStyle != null ? verticalScrollbarStyle : GUI.skin.verticalScrollbar, scrollViewStyle != null ? scrollViewStyle : EditorStyles.scrollViewAlt);\n            }\n            else\n                GUI.BeginClip(m_TotalRect);\n\n            if (evt.type == EventType.Repaint)\n            {\n                if (m_UseScrollView)\n                {\n                    m_VisibleRect = GUI.GetTopScrollView().visibleRect;\n                }\n                else\n                {\n                    // We may be inside of a scroll view.\n                    var scrollView = GUI.GetTopScrollView();\n                    if (scrollView != null)\n                    {\n                        // Calculate the visible area of the TreeView inside of the ScrollView taking into account\n                        // that the TreeView may not be contained within the whole ScrollView area.\n                        state.scrollPos = Vector2.Max(Vector2.zero, scrollView.scrollPosition - m_TotalRect.min - scrollView.position.min);\n                        m_VisibleRect = scrollView.visibleRect;\n                        m_VisibleRect.size = Vector2.Max(Vector2.zero, Vector2.Min(m_VisibleRect.size, (m_TotalRect.size - state.scrollPos)));\n                    }\n                    else\n                    {\n                        // If this is contained withing something from UI Toolkit (e.g. the Inspector window), the scroll\n                        // will be controlled by UI Toolkit itself so we need to make sure to only show what we need to\n                        // show, otherwise things can become really slow.\n                        var container = UIElementsUtility.GetCurrentIMGUIContainer();\n                        var uiScrollView = container?.GetFirstAncestorOfType<ScrollView>();\n                        if (uiScrollView != null)\n                        {\n                            // We use the viewport of the UI Toolkit scroll view to calculate the visible area.\n                            var viewport = uiScrollView.Q(\"unity-content-viewport\");\n                            var viewportWorldBound = viewport.worldBound;\n                            var viewportRectWorld = GUIClip.Unclip(viewportWorldBound);\n                            var treeViewRectWindow = GUIClip.UnclipToWindow(m_TotalRect);\n\n                            float visibleHeight = (viewportRectWorld.y + viewportRectWorld.height) - treeViewRectWindow.y;\n                            float visibleWidth = (viewportRectWorld.x + viewportRectWorld.width) - treeViewRectWindow.x;\n                            float scrollPosY = 0f, scrollPosX = 0f;\n\n                            if (visibleHeight > viewportRectWorld.height)\n                            {\n                                visibleHeight = viewportRectWorld.height;\n                                scrollPosY = viewportRectWorld.y - treeViewRectWindow.y;\n                            }\n\n                            if (visibleWidth > viewportRectWorld.width)\n                            {\n                                visibleWidth = viewportRectWorld.width;\n                                scrollPosX = viewportRectWorld.x - treeViewRectWindow.x;\n                            }\n\n                            if (scrollPosX == 0 && scrollPosY == 0)\n                            {\n                                // Avoids newing a Vector2 if we don't need a scroll position.\n                                state.scrollPos = Vector2.zero;\n                            }\n                            else\n                            {\n                                state.scrollPos = new Vector2(scrollPosX, scrollPosY);\n                            }\n                            m_VisibleRect = new Rect(0f, 0f, visibleWidth, visibleHeight);\n                        }\n                        else\n                        {\n                            m_VisibleRect = m_TotalRect;\n                        }\n                    }\n                }\n            }\n\n            gui.BeginRowGUI();\n\n            // Iterate visible items\n            int firstRow, lastRow;\n            gui.GetFirstAndLastRowVisible(out firstRow, out lastRow);\n            if (lastRow >= 0)\n            {\n                int numVisibleRows = lastRow - firstRow + 1;\n                float rowWidth = Mathf.Max(GUIClip.visibleRect.width, m_ContentRect.width);\n\n                IterateVisibleItems(firstRow, numVisibleRows, rowWidth, HasFocus());\n            }\n\n            // Call before gui.EndRowGUI() so stuff we render in EndRowGUI does not end up\n            // in the the animation clip rect\n            if (animatingExpansion)\n                m_ExpansionAnimator.OnAfterAllRowsGUI();\n\n            gui.EndRowGUI();\n\n            // Keep inside clip region so callbacks that might want to get\n            // rects of rows have correct context.\n            KeyboardGUI();\n\n            if (m_UseScrollView)\n                GUI.EndScrollView(showingVerticalScrollBar || showingHorizontalScrollBar);\n            else\n                GUI.EndClip();\n\n            HandleUnusedEvents();\n\n            // Call after iterating rows since selecting a row takes keyboard focus\n            HandleTreeViewGotFocus(isMouseDownInTotalRect);\n\n            // Prevent controlID inconsistency for the controls following this tree view: We use the hint parameter of GetControlID to\n            // fast forward to a fixed entry in the id list so the following controls always start from there regardless of the rows that have been\n            // culled.\n            GUIUtility.GetControlID(33243602, FocusType.Passive);\n\n            if (Event.current.type == EventType.MouseLeaveWindow)\n                hoveredItem = null;\n        }\n\n        void HandleTreeViewGotFocus(bool isMouseDownInTotalRect)\n        {\n            if (Event.current.type == EventType.Layout)\n                return;\n\n            // Detect if TreeView got keyboard focus (ignore layout event which gets fired infront of mousedown)\n            bool hasFocus = HasFocus();\n            if (hasFocus != m_HadFocusLastEvent)\n            {\n                m_HadFocusLastEvent = hasFocus;\n\n                if (hasFocus && isMouseDownInTotalRect)\n                {\n                    // If we got focus this event by mouse down then we do not want to begin renaming\n                    // if clicking on an already selected item in the up coming MouseUp event.\n                    m_AllowRenameOnMouseUp = false;\n                }\n            }\n        }\n\n        void IterateVisibleItems(int firstRow, int numVisibleRows, float rowWidth, bool hasFocus)\n        {\n            // We stop iterating items if datasource state changes while iterating its items.\n            // This can happen e.g when dragging items or items are expanding/collapsing.\n            m_StopIteratingItems = false;\n\n            TreeViewItem<TIdentifier> currentHoveredItem = null;\n\n            int rowOffset = 0;\n            for (int i = 0; i < numVisibleRows; ++i)\n            {\n                int row = firstRow + i;\n\n                if (animatingExpansion)\n                {\n                    // If we are animating expansion/collapsing then ensure items\n                    // that are culled by the animation clip rect gets 'converted' into\n                    // items after the expanding/collapsing items. When no more items can get culled\n                    // then keep adding the offset (to not handle already handled items).\n                    int endAnimRow = m_ExpansionAnimator.endRow;\n                    if (m_ExpansionAnimator.CullRow(row, gui))\n                    {\n                        rowOffset++;\n                        row = endAnimRow + rowOffset;\n                    }\n                    else\n                    {\n                        row += rowOffset;\n                    }\n\n                    // Ensure row is still valid after adding the rowOffset?\n                    if (row >= data.rowCount)\n                    {\n                        continue;\n                    }\n                }\n                else\n                {\n                    // When not animating cull rows outside scroll rect\n                    float screenSpaceRowY = gui.GetRowRect(row, rowWidth).y - state.scrollPos.y;\n                    if (screenSpaceRowY > m_TotalRect.height)\n                    {\n                        continue;\n                    }\n                }\n\n                if (enableItemHovering)\n                {\n                    Rect rowRect = gui.GetRowRect(row, showingVerticalScrollBar ? rowWidth - kSpaceForScrollBar : rowWidth);\n                    if (rowRect.Contains(Event.current.mousePosition) && GUIView.mouseOverView == GUIView.current)\n                        currentHoveredItem = data.GetItem(row);\n                    m_GUIView.MarkHotRegion(GUIClip.UnclipToWindow(rowRect));\n                }\n\n                // Item GUI\n                // Note that DoItemGUI() needs to be called right before checking m_StopIteratingItems since\n                // UI in the current row can issue a reload of the TreeView data\n                DoItemGUI(data.GetItem(row), row, rowWidth, hasFocus);\n\n                if (m_StopIteratingItems)\n                    break;\n            }\n\n            hoveredItem = currentHoveredItem;\n        }\n\n        private void ExpansionAnimationEnded(TreeViewAnimationInput<TIdentifier> setup)\n        {\n            // When collapsing we delay the actual collapse until the animation is done\n            if (!setup.expanding)\n            {\n                ChangeExpandedState(setup.item, false, setup.includeChildren);\n            }\n        }\n\n        float GetAnimationDuration(float height)\n        {\n            // Speed up animation linearly for heights below kThreshold.\n            // We have found from usability testing that for smaller height changes (e.g 3-4 rows)\n            // we want a faster animation\n            const float kThreshold = 60f;\n            const float kMaxDuration = 0.07f;\n            return (height > kThreshold) ? kMaxDuration : (height * kMaxDuration / kThreshold);\n        }\n\n        public void UserInputChangedExpandedState(TreeViewItem<TIdentifier> item, int row, bool expand)\n        {\n            var includeChildren = Event.current.alt;\n            if (useExpansionAnimation)\n            {\n                // We need to expand prior to starting animation so we have the expanded state ready\n                if (expand)\n                    ChangeExpandedState(item, true, includeChildren);\n\n                int rowStart = row + 1;\n                int rowEnd = GetLastChildRowUnder(row);\n                float rowWidth = GUIClip.visibleRect.width;\n                Rect allRowsRect = GetRectForRows(rowStart, rowEnd, rowWidth);\n\n                float duration = GetAnimationDuration(allRowsRect.height);\n                var input = new TreeViewAnimationInput<TIdentifier>\n                {\n                    animationDuration = duration,\n                    startRow = rowStart,\n                    endRow = rowEnd,\n                    startRowRect = gui.GetRowRect(rowStart, rowWidth),\n                    rowsRect = allRowsRect,\n                    expanding = expand,\n                    includeChildren = includeChildren,\n                    animationEnded = ExpansionAnimationEnded,\n                    item = item,\n                    treeView = this\n                };\n\n                expansionAnimator.BeginAnimating(input);\n            }\n            else\n            {\n                ChangeExpandedState(item, expand, includeChildren);\n            }\n        }\n\n        internal void ChangeExpandedState(TreeViewItem<TIdentifier> item, bool expand, bool includeChildren)\n        {\n            if (includeChildren)\n                data.SetExpandedWithChildren(item, expand);\n            else\n                data.SetExpanded(item, expand);\n        }\n\n        int GetLastChildRowUnder(int row)\n        {\n            var rows = data.GetRows();\n            int rowDepth = rows[row].depth;\n            for (int i = row + 1; i < rows.Count; ++i)\n                if (rows[i].depth <= rowDepth)\n                    return i - 1;\n\n            return rows.Count - 1; // end row\n        }\n\n        protected virtual Rect GetRectForRows(int startRow, int endRow, float rowWidth)\n        {\n            Rect startRect = gui.GetRowRect(startRow, rowWidth);\n            Rect endRect = gui.GetRowRect(endRow, rowWidth);\n            return new Rect(startRect.x, startRect.y, rowWidth, endRect.yMax - startRect.yMin);\n        }\n\n        void HandleUnusedEvents()\n        {\n            switch (Event.current.type)\n            {\n                case EventType.DragUpdated:\n                    if (dragging != null && m_TotalRect.Contains(Event.current.mousePosition))\n                    {\n                        dragging.DragElement(null, new Rect(), -1);\n                        Repaint();\n                        Event.current.Use();\n                    }\n                    break;\n\n                case EventType.DragPerform:\n                    if (dragging != null && m_TotalRect.Contains(Event.current.mousePosition))\n                    {\n                        m_DragSelection.Clear();\n                        dragging.DragElement(null, new Rect(), -1);\n                        Repaint();\n                        Event.current.Use();\n                    }\n                    break;\n\n                case EventType.DragExited:\n                    if (dragging != null)\n                    {\n                        m_DragSelection.Clear();\n                        dragging.DragCleanup(true);\n                        Repaint();\n                    }\n                    break;\n\n                case EventType.MouseDown:\n                    bool containsMouse = m_TotalRect.Contains(Event.current.mousePosition);\n                    if (containsMouse)\n                    {\n                        GUIUtility.keyboardControl = m_KeyboardControlID;\n                        Repaint();\n                    }\n                    if (deselectOnUnhandledMouseDown && containsMouse && Event.current.button == 0 && state.selectedIDs.Count > 0)\n                    {\n                        SetSelection(new TIdentifier[0], false);\n                        NotifyListenersThatSelectionChanged();\n                    }\n\n                    break;\n                case EventType.ContextClick:\n                    if (m_TotalRect.Contains(Event.current.mousePosition))\n                    {\n                        if (contextClickOutsideItemsCallback != null)\n                            contextClickOutsideItemsCallback();\n                    }\n                    break;\n            }\n        }\n\n        public void OnEvent()\n        {\n            state.renameOverlay.OnEvent();\n        }\n\n        public bool BeginNameEditing(float delay)\n        {\n            // No items selected for rename\n            if (state.selectedIDs.Count == 0)\n                return false;\n\n            var visibleItems = data.GetRows();\n            TreeViewItem<TIdentifier> visibleAndSelectedItem = null;\n\n            foreach (TIdentifier id in state.selectedIDs)\n            {\n                TreeViewItem<TIdentifier> item = visibleItems.FirstOrDefault(i => i.id.Equals(id));\n                if (visibleAndSelectedItem == null)\n                    visibleAndSelectedItem = item;\n                else if (item != null)\n                    return false; // Don't allow rename if more than one item is both visible and selected\n            }\n\n            if (visibleAndSelectedItem != null && data.IsRenamingItemAllowed(visibleAndSelectedItem))\n                return gui.BeginRename(visibleAndSelectedItem, delay);\n\n            return false;\n        }\n\n        // Let client end renaming from outside\n        public void EndNameEditing(bool acceptChanges)\n        {\n            if (state.renameOverlay.IsRenaming())\n            {\n                state.renameOverlay.EndRename(acceptChanges);\n                gui.EndRename();\n            }\n        }\n\n        TreeViewItem<TIdentifier> GetItemAndRowIndex(TIdentifier id, out int row)\n        {\n            row = data.GetRow(id);\n            if (row == -1)\n                return null;\n            return data.GetItem(row);\n        }\n\n        void HandleFastCollapse(TreeViewItem<TIdentifier> item, int row)\n        {\n            if (item.depth == 0)\n            {\n                // At depth 0 traverse upwards until a parent is found and select that item\n                for (int i = row - 1; i >= 0; --i)\n                {\n                    if (data.GetItem(i).hasChildren)\n                    {\n                        OffsetSelection(i - row);\n                        return;\n                    }\n                }\n            }\n            else if (item.depth > 0)\n            {\n                // Traverse upwards until parent of item is found and select that parent (users want this behavior)\n                for (int i = row - 1; i >= 0; --i)\n                {\n                    if (data.GetItem(i).depth < item.depth)\n                    {\n                        OffsetSelection(i - row);\n                        return;\n                    }\n                }\n            }\n        }\n\n        void HandleFastExpand(TreeViewItem<TIdentifier> item, int row)\n        {\n            int rowCount = data.rowCount;\n\n            // Traverse downwards until a parent is found and select that parent\n            for (int i = row + 1; i < rowCount; ++i)\n            {\n                if (data.GetItem(i).hasChildren)\n                {\n                    OffsetSelection(i - row);\n                    break;\n                }\n            }\n        }\n\n        private void ChangeFolding(TIdentifier[] ids, bool expand)\n        {\n            // Handle folding of single item and multiple items separately\n            // Animation is only supported for folding of single item\n            if (ids.Length == 1)\n                ChangeFoldingForSingleItem(ids[0], expand);\n            else if (ids.Length > 1)\n                ChangeFoldingForMultipleItems(ids, expand);\n        }\n\n        private void ChangeFoldingForSingleItem(TIdentifier id, bool expand)\n        {\n            // Skip any ongoing animation first because it could affect the row count.\n            // I.e. if the item to be collapsed is in a row that no longer exists after the animation is done and the rows refreshed in InitIfNeeded, skiping the animation later would cause an IndexOufOfBounds in HandleFastCollapse\n            // if no animation is happening, this is just a null check so moving it later for performance reasons makes little sense.\n            expansionAnimator.SkipAnimating();\n\n            int row;\n            TreeViewItem<TIdentifier> item = GetItemAndRowIndex(id, out row);\n            if (item != null)\n            {\n                if (data.IsExpandable(item) && data.IsExpanded(item) != expand)\n                    UserInputChangedExpandedState(item, row, expand);\n                else\n                {\n                    if (expand)\n                        HandleFastExpand(item, row); // Move selection to next parent\n                    else\n                        HandleFastCollapse(item, row); // Move selection to parent\n                }\n            }\n        }\n\n        private void ChangeFoldingForMultipleItems(TIdentifier[] ids, bool expand)\n        {\n            // Collect items that should be expanded/collapsed\n            var parents = new HashSet<TIdentifier>();\n            foreach (var id in ids)\n            {\n                int row;\n                TreeViewItem<TIdentifier> item = GetItemAndRowIndex(id, out row);\n                if (item != null)\n                {\n                    if (data.IsExpandable(item) && data.IsExpanded(item) != expand)\n                        parents.Add(id);\n                }\n            }\n\n            // Expand/collapse all collected items\n            if (Event.current.alt)\n            {\n                // Also expand/collapse children of selected items\n                foreach (var id in parents)\n                    data.SetExpandedWithChildren(id, expand);\n            }\n            else\n            {\n                var expandedIDs = new HashSet<TIdentifier>(data.GetExpandedIDs());\n                if (expand)\n                    expandedIDs.UnionWith(parents);\n                else\n                    expandedIDs.ExceptWith(parents);\n                data.SetExpandedIDs(expandedIDs.ToArray());\n            }\n        }\n\n        void KeyboardGUI()\n        {\n            if (m_KeyboardControlID != GUIUtility.keyboardControl || !GUI.enabled)\n                return;\n\n            // Let client handle keyboard first\n            if (keyboardInputCallback != null)\n                keyboardInputCallback();\n\n            if (!m_ConsumeKeyDownEvents)\n                return;\n\n            if (Event.current.type == EventType.KeyDown)\n            {\n                switch (Event.current.keyCode)\n                {\n                    // Fold in\n                    case KeyCode.LeftArrow:\n                        ChangeFolding(state.selectedIDs.ToArray(), false);\n                        Event.current.Use();\n                        break;\n\n                    // Fold out\n                    case KeyCode.RightArrow:\n                        ChangeFolding(state.selectedIDs.ToArray(), true);\n                        Event.current.Use();\n                        break;\n\n                    case KeyCode.UpArrow:\n                        Event.current.Use();\n                        OffsetSelection(-1);\n                        break;\n\n                    // Select next or first\n                    case KeyCode.DownArrow:\n                        Event.current.Use();\n                        OffsetSelection(1);\n                        break;\n\n                    case KeyCode.Home:\n                        Event.current.Use();\n                        OffsetSelection(-1000000);\n                        break;\n\n                    case KeyCode.End:\n                        Event.current.Use();\n                        OffsetSelection(1000000);\n                        break;\n\n                    case KeyCode.PageUp:\n                    {\n                        Event.current.Use();\n                        TreeViewItem<TIdentifier> lastClickedItem = data.FindItem(state.lastClickedID);\n                        if (lastClickedItem != null)\n                        {\n                            int numRowsPageUp = gui.GetNumRowsOnPageUpDown(lastClickedItem, true, m_TotalRect.height);\n                            OffsetSelection(-numRowsPageUp);\n                        }\n                    }\n                    break;\n\n                    case KeyCode.PageDown:\n                    {\n                        Event.current.Use();\n                        TreeViewItem<TIdentifier> lastClickedItem = data.FindItem(state.lastClickedID);\n                        if (lastClickedItem != null)\n                        {\n                            int numRowsPageDown = gui.GetNumRowsOnPageUpDown(lastClickedItem, true, m_TotalRect.height);\n                            OffsetSelection(numRowsPageDown);\n                        }\n                    }\n                    break;\n\n                    case KeyCode.Return:\n                    case KeyCode.KeypadEnter:\n                        if (Application.platform == RuntimePlatform.OSXEditor)\n                            if (BeginNameEditing(0f))\n                                Event.current.Use();\n                        break;\n\n                    case KeyCode.F2:\n                        if (Application.platform != RuntimePlatform.OSXEditor)\n                            if (BeginNameEditing(0f))\n                                Event.current.Use();\n                        break;\n\n                    default:\n                        if (Event.current.keyCode > KeyCode.A && Event.current.keyCode < KeyCode.Z)\n                        {\n                            // TODO: jump to folder with char?\n                        }\n                        break;\n                }\n            }\n        }\n\n        static internal int GetIndexOfID(IList<TreeViewItem<TIdentifier>> items, TIdentifier id)\n        {\n            for (int i = 0; i < items.Count; ++i)\n                if (items[i].id.Equals(id))\n                    return i;\n            return -1;\n        }\n\n        public bool IsLastClickedPartOfRows()\n        {\n            var visibleRows = data.GetRows();\n            if (visibleRows.Count == 0)\n                return false;\n\n            return GetIndexOfID(visibleRows, state.lastClickedID) >= 0;\n        }\n\n        public void OffsetSelection(int offset)\n        {\n            expansionAnimator.SkipAnimating();\n            var visibleRows = data.GetRows();\n\n            if (visibleRows.Count == 0)\n                return;\n\n            Event.current?.Use();\n            int index = GetIndexOfID(visibleRows, state.lastClickedID);\n            int newIndex = Mathf.Clamp(index + offset, 0, visibleRows.Count - 1);\n            EnsureRowIsVisible(newIndex, false);\n            SelectionByKey(visibleRows[newIndex]);\n        }\n\n        public Func<TreeViewItem<TIdentifier>, bool, bool, List<TIdentifier>> getNewSelectionOverride { private get; set; }\n\n        // Returns list of selected ids\n        List<TIdentifier> GetNewSelection(TreeViewItem<TIdentifier> clickedItem, bool keepMultiSelection, bool useShiftAsActionKey)\n        {\n            if (getNewSelectionOverride != null)\n                return getNewSelectionOverride(clickedItem, keepMultiSelection, useShiftAsActionKey);\n\n            var selectState = new TreeViewSelectState<TIdentifier>() {\n                selectedIDs = state.selectedIDs,\n                lastClickedID = state.lastClickedID,\n                keepMultiSelection = keepMultiSelection,\n                useShiftAsActionKey = useShiftAsActionKey\n            };\n\n            return data.GetNewSelection(clickedItem, selectState);\n        }\n\n        void SelectionByKey(TreeViewItem<TIdentifier> itemSelected)\n        {\n            var newSelection = GetNewSelection(itemSelected, false, true);\n            NewSelectionFromUserInteraction(newSelection, itemSelected.id);\n        }\n\n        public void SelectionClick(TreeViewItem<TIdentifier> itemClicked, bool keepMultiSelection)\n        {\n            var newSelection = GetNewSelection(itemClicked, keepMultiSelection, false);\n            NewSelectionFromUserInteraction(newSelection, itemClicked != null ? itemClicked.id : default);\n        }\n\n        void NewSelectionFromUserInteraction(List<TIdentifier> newSelection, TIdentifier itemID)\n        {\n            state.lastClickedID = itemID;\n\n            bool selectionChanged = !state.selectedIDs.SequenceEqual(newSelection);\n            if (selectionChanged)\n            {\n                state.selectedIDs = newSelection;\n                NotifyListenersThatSelectionChanged();\n                Repaint();\n            }\n        }\n\n        public void RemoveSelection()\n        {\n            if (state.selectedIDs.Count > 0)\n            {\n                state.selectedIDs.Clear();\n                NotifyListenersThatSelectionChanged();\n            }\n        }\n\n        float GetTopPixelOfRow(int row)\n        {\n            return gui.GetRowRect(row, 1).y;\n        }\n\n        void EnsureRowIsVisible(int row, bool animated)\n        {\n            // We don't want to change the scroll to make the row visible,\n            // if it's disabled: Causes content to be moved/rendered out of bounds.\n            if (!m_UseScrollView)\n                return;\n\n            if (row >= 0)\n            {\n                // Adjusting for when the horizontal scrollbar is being shown. Before the TreeView has repainted\n                // once the m_VisibleRect is not valid, then we use m_TotalRect which is passed when initialized\n                float visibleHeight = m_VisibleRect.height > 0 ? m_VisibleRect.height : m_TotalRect.height;\n\n                Rect frameRect = gui.GetRectForFraming(row);\n                float scrollTop = frameRect.y;\n                float scrollBottom = frameRect.yMax - visibleHeight;\n\n                if (state.scrollPos.y < scrollBottom)\n                    ChangeScrollValue(scrollBottom, animated);\n                else if (state.scrollPos.y > scrollTop)\n                    ChangeScrollValue(scrollTop, animated);\n            }\n        }\n\n        void AnimatedScrollChanged()\n        {\n            Repaint();\n            state.scrollPos.y = m_FramingAnimFloat.value;\n        }\n\n        void ChangeScrollValue(float targetScrollPos, bool animated)\n        {\n            if (m_UseExpansionAnimation && animated)\n            {\n                m_FramingAnimFloat.value = state.scrollPos.y;\n                m_FramingAnimFloat.target = targetScrollPos;\n                m_FramingAnimFloat.speed = 3f;\n            }\n            else\n            {\n                state.scrollPos.y = targetScrollPos;\n            }\n        }\n\n        public void Frame(TIdentifier id, bool frame, bool ping)\n        {\n            const bool animated = false;\n            Frame(id, frame, ping, animated);\n        }\n\n        public void Frame(TIdentifier id, bool frame, bool ping, bool animated)\n        {\n            float topPixelOfRow = -1f;\n\n            if (frame)\n            {\n                data.RevealItem(id);\n\n                int row = data.GetRow(id);\n                if (row >= 0)\n                {\n                    topPixelOfRow = GetTopPixelOfRow(row);\n                    EnsureRowIsVisible(row, animated);\n                }\n            }\n\n            if (ping)\n            {\n                int row = data.GetRow(id);\n                if (topPixelOfRow == -1f)\n                {\n                    // Was not framed first so we need to calc it here\n                    if (row >= 0)\n                        topPixelOfRow = GetTopPixelOfRow(row);\n                }\n\n                if (topPixelOfRow >= 0f && row >= 0 && row < data.rowCount)\n                {\n                    TreeViewItem<TIdentifier> item = data.GetRows()[row];\n                    float scrollBarOffset = GetContentSize().y > m_TotalRect.height ? -kSpaceForScrollBar : 0f;\n                    gui.BeginPingItem(item, topPixelOfRow, m_TotalRect.width + scrollBarOffset);\n                }\n            }\n        }\n\n        public void EndPing()\n        {\n            gui.EndPingItem();\n        }\n\n        // Item holding most basic data for TreeView event handling\n        // Extend this class to hold your specific tree data and make your DataSource\n        // create items of your type. During e.g OnGUI you can the cast Item to your own type when needed.\n\n\n        // Hidden items (under collapsed items) are added last\n        public List<TIdentifier> SortIDsInVisiblityOrder(IList<TIdentifier> ids)\n        {\n            if (ids.Count <= 1)\n                return ids.ToList(); // no sorting needed\n\n            var visibleRows = data.GetRows();\n            List<TIdentifier> sorted = new List<TIdentifier>();\n            for (int i = 0; i < visibleRows.Count; ++i)\n            {\n                var id = visibleRows[i].id;\n                for (int j = 0; j < ids.Count; ++j)\n                {\n                    if (ids[j].Equals(id))\n                    {\n                        sorted.Add(id);\n                        break;\n                    }\n                }\n            }\n\n            // Some rows with selection are collapsed (not visible) so add those to the end\n            if (ids.Count != sorted.Count)\n            {\n                sorted.AddRange(ids.Except(sorted));\n                if (ids.Count != sorted.Count)\n                    Debug.LogError(\"SortIDsInVisiblityOrder failed: \" + ids.Count + \" != \" + sorted.Count);\n            }\n\n            return sorted;\n        }\n    }\n} // end namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditorInternal;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    // TreeViewDataSource is a base abstract class for a data source for a TreeView.\n    // Usage:\n    //   Override FetchData () and build the entire tree with m_RootItem as root.\n    //   Configure showRootItem and rootIsCollapsable as wanted\n    //\n    // Note: if dealing with very large trees use LazyTreeViewDataSource instead: it assumes that tree only contains visible items.\n\ninternal abstract class TreeViewDataSource<TIdentifier> : ITreeViewDataSource<TIdentifier> where TIdentifier : unmanaged, System.IEquatable<TIdentifier>\n    {\n        protected TreeViewController<TIdentifier> m_TreeView { get { return m_TreeViewInternal; } set { m_TreeViewInternal = value; } } // TreeView using this data source\n        protected TreeViewController<TIdentifier> m_TreeViewInternal;                   // TreeView using this data source\n        protected TreeViewItem<TIdentifier> m_RootItem;\n        protected IList<TreeViewItem<TIdentifier>> m_Rows;\n        protected bool m_NeedRefreshRows = true;\n        protected TreeViewItem<TIdentifier> m_FakeItem;\n\n        public bool showRootItem { get; set; }\n        public bool rootIsCollapsable { get; set; }\n        public bool alwaysAddFirstItemToSearchResult { get; set; } // is only used in searches when showRootItem is false. It Doesn't make sense for visible roots\n        public TreeViewItem<TIdentifier> root { get { return m_RootItem; } }\n        public System.Action onVisibleRowsChanged;\n\n        protected List<TIdentifier> expandedIDs\n        {\n            get {return m_TreeView.state.expandedIDs; }\n            set { m_TreeView.state.expandedIDs = value; }\n        }\n\n        public TreeViewDataSource(TreeViewController<TIdentifier> treeView)\n        {\n            m_TreeView = treeView;\n            showRootItem = true;\n            rootIsCollapsable = false;\n            m_RootItem = null;\n            onVisibleRowsChanged = null;\n        }\n\n        virtual public void OnInitialize()\n        {\n        }\n\n        // Implement this function and build entire tree with m_RootItem as root\n        public abstract void FetchData();\n\n        public virtual void ReloadData()\n        {\n            m_FakeItem = null;\n            FetchData();\n        }\n\n        virtual public TreeViewItem<TIdentifier> FindItem(TIdentifier id)\n        {\n            return TreeViewUtility<TIdentifier>.FindItem(id, m_RootItem);\n        }\n\n        virtual public bool IsRevealed(TIdentifier id)\n        {\n            IList<TreeViewItem<TIdentifier>> rows = GetRows();\n            return TreeViewController<TIdentifier>.GetIndexOfID(rows, id) >= 0;\n        }\n\n        virtual public void RevealItem(TIdentifier id)\n        {\n            if (IsRevealed(id))\n                return;\n\n            // Reveal (expand parents up to root)\n            TreeViewItem<TIdentifier> item = FindItem(id);\n            if (item != null)\n            {\n                TreeViewItem<TIdentifier> parent = item.parent;\n                while (parent != null)\n                {\n                    SetExpanded(parent, true);\n                    parent = parent.parent;\n                }\n            }\n        }\n\n        virtual public void RevealItems(TIdentifier[] ids)\n        {\n            HashSet<TIdentifier> expandedSet = new HashSet<TIdentifier>(expandedIDs);\n            int orgSize = expandedSet.Count;\n\n            // Add all parents above id\n            foreach (var id in ids)\n            {\n                if (IsRevealed(id))\n                    continue;\n                // Reveal (expand parents up to root)\n                TreeViewItem<TIdentifier> item = FindItem(id);\n                if (item != null)\n                {\n                    TreeViewItem<TIdentifier> parent = item.parent;\n                    while (parent != null)\n                    {\n                        expandedSet.Add(parent.id);\n                        parent = parent.parent;\n                    }\n                }\n            }\n\n            if (orgSize != expandedSet.Count)\n            {\n                // Bulk set expanded ids (is sorted in SetExpandedIDs)\n                SetExpandedIDs(expandedSet.ToArray());\n\n                // Refresh immediately if any Item was expanded\n                if (m_NeedRefreshRows)\n                    FetchData();\n            }\n        }\n\n        virtual public void OnSearchChanged()\n        {\n            m_NeedRefreshRows = true;\n        }\n\n        //----------------------------\n        // Visible Item section\n\n        protected void GetVisibleItemsRecursive(TreeViewItem<TIdentifier> item, IList<TreeViewItem<TIdentifier>> items)\n        {\n            if (item != m_RootItem || showRootItem)\n                items.Add(item);\n\n            if (item.hasChildren && IsExpanded(item))\n                foreach (TreeViewItem<TIdentifier> child in item.children)\n                    GetVisibleItemsRecursive(child, items);\n        }\n\n        protected void SearchRecursive(TreeViewItem<TIdentifier> item, string search, IList<TreeViewItem<TIdentifier>> searchResult)\n        {\n            if (item.displayName.ToLower().Contains(search))\n                searchResult.Add(item);\n\n            if (item.children != null)\n                foreach (TreeViewItem<TIdentifier> child in item.children)\n                    SearchRecursive(child, search, searchResult);\n        }\n\n        virtual protected List<TreeViewItem<TIdentifier>> ExpandedRows(TreeViewItem<TIdentifier> root)\n        {\n            var result = new List<TreeViewItem<TIdentifier>>();\n            GetVisibleItemsRecursive(m_RootItem, result);\n            return result;\n        }\n\n        // Searches the current tree by displayName.\n        virtual protected List<TreeViewItem<TIdentifier>> Search(TreeViewItem<TIdentifier> root, string search)\n        {\n            var result = new List<TreeViewItem<TIdentifier>>();\n\n            if (showRootItem)\n            {\n                SearchRecursive(root, search, result);\n                result.Sort(new TreeViewItemAlphaNumericSort<TIdentifier>());\n            }\n            else\n            {\n                int startIndex = alwaysAddFirstItemToSearchResult ? 1 : 0;\n\n                if (root.hasChildren)\n                {\n                    for (int i = startIndex; i < root.children.Count; ++i)\n                    {\n                        SearchRecursive(root.children[i], search, result);\n                    }\n                    result.Sort(new TreeViewItemAlphaNumericSort<TIdentifier>());\n\n                    if (alwaysAddFirstItemToSearchResult)\n                        result.Insert(0, root.children[0]);\n                }\n            }\n\n            return result;\n        }\n\n        virtual public int rowCount\n        {\n            get\n            {\n                return GetRows().Count;\n            }\n        }\n\n        virtual public int GetRow(TIdentifier id)\n        {\n            var rows = GetRows();\n            for (int row = 0; row < rows.Count; ++row)\n            {\n                if (rows[row].id.Equals(id))\n                    return row;\n            }\n            return -1;\n        }\n\n        virtual public TreeViewItem<TIdentifier> GetItem(int row)\n        {\n            return GetRows()[row];\n        }\n\n        // Get the flattend tree of visible items.\n        virtual public IList<TreeViewItem<TIdentifier>> GetRows() => GetRowsInternal();\n        virtual public IList<TreeViewItem<TIdentifier>> GetRowsInternal()\n        {\n            InitIfNeeded();\n            return m_Rows;\n        }\n\n        virtual public void InitIfNeeded()\n        {\n            // Cached for large trees...\n            if (m_Rows == null || m_NeedRefreshRows)\n            {\n                if (m_RootItem != null)\n                {\n                    if (m_TreeView.isSearching)\n                        m_Rows = Search(m_RootItem, m_TreeView.searchString.ToLower());\n                    else\n                        m_Rows = ExpandedRows(m_RootItem);\n                }\n                else\n                {\n                    Debug.LogError(\"TreeView root item is null. Ensure that your TreeViewDataSource sets up at least a root item.\");\n                    m_Rows = new List<TreeViewItem<TIdentifier>>();\n                }\n\n                m_NeedRefreshRows = false;\n\n                // TODO: This should be named something like: 'onVisibleRowsReloaded'\n                if (onVisibleRowsChanged != null)\n                    onVisibleRowsChanged();\n\n                // Expanded state has changed ensure that we repaint\n                m_TreeView.Repaint();\n            }\n        }\n\n        public bool isInitialized\n        {\n            get { return m_RootItem != null && m_Rows != null; }\n        }\n\n        //----------------------------\n        // Expanded/collapsed section\n\n        virtual public TIdentifier[] GetExpandedIDs()\n        {\n            return expandedIDs.ToArray();\n        }\n\n        virtual public void SetExpandedIDs(TIdentifier[] ids)\n        {\n            expandedIDs = new List<TIdentifier>(ids);\n            expandedIDs.Sort();\n            m_NeedRefreshRows = true;\n            OnExpandedStateChanged();\n        }\n\n        virtual public bool IsExpanded(TIdentifier id)\n        {\n            return expandedIDs.BinarySearch(id) >= 0;\n        }\n\n        virtual public bool SetExpanded(TIdentifier id, bool expand)\n        {\n            bool expanded = IsExpanded(id);\n            if (expand != expanded)\n            {\n                if (expand)\n                {\n                    System.Diagnostics.Debug.Assert(!expandedIDs.Contains(id));\n                    expandedIDs.Add(id);\n                    expandedIDs.Sort();\n                }\n                else\n                {\n                    expandedIDs.Remove(id);\n                }\n                m_NeedRefreshRows = true;\n                OnExpandedStateChanged();\n                return true;\n            }\n            return false;\n        }\n\n        virtual public void SetExpandedWithChildren(TIdentifier id, bool expand)\n        {\n            SetExpandedWithChildren(FindItem(id), expand);\n        }\n\n        virtual public void SetExpandedWithChildren(TreeViewItem<TIdentifier> fromItem, bool expand)\n        {\n            if (fromItem == null)\n            {\n                Debug.LogError(\"item is null\");\n                return;\n            }\n\n            HashSet<TIdentifier> parents = new HashSet<TIdentifier>();\n            TreeViewUtility<TIdentifier>.GetParentsBelowItem(fromItem, parents);\n\n            // Get existing expanded in hashset\n            HashSet<TIdentifier> oldExpandedSet = new HashSet<TIdentifier>(expandedIDs);\n\n            if (expand)\n                oldExpandedSet.UnionWith(parents);\n            else\n                oldExpandedSet.ExceptWith(parents);\n\n            // Bulk set expanded ids (is sorted in SetExpandedIDs)\n            SetExpandedIDs(oldExpandedSet.ToArray());\n        }\n\n        virtual public void SetExpanded(TreeViewItem<TIdentifier> item, bool expand)\n        {\n            SetExpanded(item.id, expand);\n        }\n\n        virtual public bool IsExpanded(TreeViewItem<TIdentifier> item) => IsExpandedInternal(item);\n        virtual public bool IsExpandedInternal(TreeViewItem<TIdentifier> item)\n        {\n            return IsExpanded(item.id);\n        }\n\n        virtual public bool IsExpandable(TreeViewItem<TIdentifier> item) => IsExpandableInternal(item);\n        virtual public bool IsExpandableInternal(TreeViewItem<TIdentifier> item)\n        {\n            // Ignore expansion (foldout arrow) when showing search results\n            if (m_TreeView.isSearching)\n                return false;\n            return item.hasChildren;\n        }\n\n        virtual public bool CanBeMultiSelected(TreeViewItem<TIdentifier> item)\n        {\n            return true;\n        }\n\n        virtual public bool CanBeParent(TreeViewItem<TIdentifier> item) => CanBeParentInternal(item);\n        virtual public bool CanBeParentInternal(TreeViewItem<TIdentifier> item)\n        {\n            return true;\n        }\n\n        virtual public List<TIdentifier> GetNewSelection(TreeViewItem<TIdentifier> clickedItem, TreeViewSelectState<TIdentifier> selectState)\n        {\n            // Get ids from items\n            var visibleRows = GetRows();\n            List<TIdentifier> allIDs = new List<TIdentifier>(visibleRows.Count);\n            for (int i = 0; i < visibleRows.Count; ++i)\n                allIDs.Add(visibleRows[i].id);\n\n            bool allowMultiselection = CanBeMultiSelected(clickedItem);\n\n            // todo: add support for other types of TIdentifier, Importantly 'InstanceID'\n            if (clickedItem.id is int clickedIntID && selectState.lastClickedID is int lastClickedIntID)\n                return  InternalEditorUtility.GetNewSelection(\n                    clickedIntID, allIDs as List<int>,\n                    selectState.selectedIDs as List<int>,\n                    lastClickedIntID, selectState.keepMultiSelection, selectState.useShiftAsActionKey, allowMultiselection\n                ) as List<TIdentifier>;\n\n            throw new System.NotImplementedException(\"InternalEditorUtility.GetNewSelection not implemented for type \" + clickedItem.id.GetType());\n        }\n\n        virtual public void OnExpandedStateChanged()\n        {\n            if (m_TreeView.expandedStateChanged != null)\n                m_TreeView.expandedStateChanged();\n        }\n\n        //----------------------------\n        // Renaming section\n\n        virtual public bool IsRenamingItemAllowed(TreeViewItem<TIdentifier> item)\n        {\n            return true;\n        }\n\n        //----------------------------\n        // Insert tempoary Item section\n\n        // Fake Item should be inserted into the m_VisibleRows (not the tree itself).\n        virtual public void InsertFakeItem(TIdentifier id, TIdentifier parentID, string name, Texture2D icon)\n        {\n            Debug.LogError(\"InsertFakeItem missing implementation\");\n        }\n\n        virtual public bool HasFakeItem()\n        {\n            return m_FakeItem != null;\n        }\n\n        virtual public void RemoveFakeItem()\n        {\n            if (!HasFakeItem())\n                return;\n\n            var visibleRows = GetRows();\n            int index = TreeViewController<TIdentifier>.GetIndexOfID(visibleRows, m_FakeItem.id);\n            if (index != -1)\n            {\n                visibleRows.RemoveAt(index);\n            }\n            m_FakeItem = null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewDragging.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.Assertions;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    // Abstract base class for common dragging behavior\n    // Usage:\n    //   - Override StartDrag\n    //   - Override DoDrag\n    // Features:\n    //   - Expands items with children on hover (after ca 0.7 seconds)\n    //\n\n\n    internal abstract class TreeViewDragging<TIdentifier> : ITreeViewDragging<TIdentifier> where TIdentifier : unmanaged, IEquatable<TIdentifier>\n    {\n        protected TreeViewController<TIdentifier> m_TreeView;\n\n        protected class DropData\n        {\n            public TIdentifier[] expandedArrayBeforeDrag;\n            public int lastControlID = -1;\n            public int dropTargetControlID = -1;\n            public int rowMarkerControlID = -1;\n            public int ancestorControlID;\n            public double expandItemBeginTimer;\n            public Vector2 expandItemBeginPosition;\n            public float insertionMarkerYPosition;\n            public TreeViewItem<TIdentifier> insertRelativeToSibling;\n\n            public void ClearPerEventState()\n            {\n                dropTargetControlID = -1;\n                rowMarkerControlID = -1;\n                ancestorControlID = -1;\n                insertionMarkerYPosition = -1f;\n                insertRelativeToSibling = null;\n            }\n        }\n\n        public enum DropPosition\n        {\n            Upon = 0,\n            Below = 1,\n            Above = 2\n        }\n\n        protected DropData m_DropData = new DropData();\n        const double k_DropExpandTimeout = 0.7;\n\n        static class Constants\n        {\n            public const string GetInsertionIndexNotFound = \"Did not find targetItem,; should be a child of parentItem\";\n        }\n\n        public TreeViewDragging(TreeViewController<TIdentifier> treeView)\n        {\n            m_TreeView = treeView;\n        }\n\n        virtual public void OnInitialize()\n        {\n        }\n\n        public int GetDropTargetControlID()\n        {\n            return m_DropData.dropTargetControlID;\n        }\n\n        public int GetRowMarkerControlID()\n        {\n            return m_DropData.rowMarkerControlID;\n        }\n\n        public int GetAncestorControlID()\n        {\n            return m_DropData.ancestorControlID;\n        }\n\n        public bool drawRowMarkerAbove { get; set; }\n        public float insertionMarkerYPosition { get { return m_DropData.insertionMarkerYPosition; } }\n        public TreeViewItem<TIdentifier> insertRelativeToSibling { get { return m_DropData.insertRelativeToSibling; } }\n\n        public Func<int> getIndentLevelForMouseCursor;\n\n        public virtual bool CanStartDrag(TreeViewItem<TIdentifier> targetItem, List<TIdentifier> draggedItemIDs, Vector2 mouseDownPosition) => CanStartDragInternal(targetItem, draggedItemIDs, mouseDownPosition);\n        public virtual bool CanStartDragInternal(TreeViewItem<TIdentifier> targetItem, List<TIdentifier> draggedItemIDs, Vector2 mouseDownPosition)\n        {\n            return true;\n        }\n\n        // This method is called from TreeView when a drag is started\n        // Client should setup the drag data\n        public virtual void StartDragInternal(TreeViewItem<TIdentifier> draggedItem, List<TIdentifier> draggedItemIDs){}\n        public virtual void StartDrag(TreeViewItem<TIdentifier> draggedItem, List<TIdentifier> draggedItemIDs) => StartDragInternal(draggedItem, draggedItemIDs);\n\n        // This method is called from within DragElement when it has determined what is the parent item of the current targetItem\n        // (This depends on if dropPosition is above, below or upon)\n        // Implemented by client code to decide what should happen when the drag is e.g performed (e.g change the backend state of the tree view)\n        // Notes on arguments:\n        // When hovering outside any items: target and parent is null, dropPos is invalid\n        // If parentItem and targetItem is the same then insert as first child of parent, dropPos is invalid\n        // If parentItem and targetItem is different then use dropPos to insert dragged items relative to targetItem\n        // parentItem can be null when root is visible and hovering above or below the root\n\n        // if targetItem is null then parent can be null if root is visible\n        // if targetitem is null then parent might be valid if root is hidden\n        public virtual DragAndDropVisualMode DoDrag(TreeViewItem<TIdentifier> parentItem, TreeViewItem<TIdentifier> targetItem, bool perform, DropPosition dropPosition) => DoDragInternal(parentItem, targetItem, perform, dropPosition);\n        public virtual DragAndDropVisualMode DoDragInternal(TreeViewItem<TIdentifier> parentItem, TreeViewItem<TIdentifier> targetItem, bool perform, DropPosition dropPosition) => throw new NotImplementedException();\n\n        protected float GetDropBetweenHalfHeight(TreeViewItem<TIdentifier> item, Rect itemRect)\n        {\n            return m_TreeView.data.CanBeParent(item) ? m_TreeView.gui.halfDropBetweenHeight : itemRect.height * 0.5f;\n        }\n\n        void GetPreviousAndNextItemsIgnoringDraggedItems(int targetRow, DropPosition dropPosition, out TreeViewItem<TIdentifier> previousItem, out TreeViewItem<TIdentifier> nextItem)\n        {\n            if (dropPosition != DropPosition.Above && dropPosition != DropPosition.Below)\n                throw new ArgumentException(\"Invalid argument: \" + dropPosition);\n\n            previousItem = nextItem = null;\n            int curPrevRow = (dropPosition == DropPosition.Above) ? targetRow - 1 : targetRow;\n            int curNextRow = (dropPosition == DropPosition.Above) ? targetRow : targetRow + 1;\n\n            while (curPrevRow >= 0)\n            {\n                var curPreviousItem = m_TreeView.data.GetItem(curPrevRow);\n                if (!m_TreeView.IsDraggingItem(curPreviousItem))\n                {\n                    previousItem = curPreviousItem;\n                    break;\n                }\n                curPrevRow--;\n            }\n\n            while (curNextRow < m_TreeView.data.rowCount)\n            {\n                var curNextItem = m_TreeView.data.GetItem(curNextRow);\n                if (!m_TreeView.IsDraggingItem(curNextItem))\n                {\n                    nextItem = curNextItem;\n                    break;\n                }\n                curNextRow++;\n            }\n        }\n\n        internal void HandleSiblingInsertionAtAvailableDepthsAndChangeTargetIfNeeded(ref TreeViewItem<TIdentifier> targetItem, int targetItemRow, ref DropPosition dropPosition, int cursorDepth, out bool didChangeTargetToAncestor)\n        {\n            if (dropPosition != DropPosition.Above && dropPosition != DropPosition.Below)\n                throw new ArgumentException(\"Invalid argument: \" + dropPosition);\n\n            didChangeTargetToAncestor = false;\n\n            TreeViewItem<TIdentifier> prevItem, nextItem;\n            GetPreviousAndNextItemsIgnoringDraggedItems(targetItemRow, dropPosition, out prevItem, out nextItem);\n\n            if (prevItem == null)\n                return; // Above first row so keep targetItem\n\n            bool hoveringBetweenExpandedParentAndFirstChild = prevItem.hasChildren && m_TreeView.data.IsExpanded(prevItem.id);\n            int minDepth = nextItem != null ? nextItem.depth : 0;\n            int maxDepth = prevItem.depth + (hoveringBetweenExpandedParentAndFirstChild ? 1 : 0);\n\n            // Change targetItem and dropPosition\n            targetItem = prevItem;\n            dropPosition = DropPosition.Below;\n\n            if (maxDepth <= minDepth)\n            {\n                if (hoveringBetweenExpandedParentAndFirstChild)\n                {\n                    targetItem = prevItem.children[0];\n                    dropPosition = DropPosition.Above;\n                }\n                return; // The nextItem is a descendant of previous item so keep targetItem\n            }\n\n            if (cursorDepth >= maxDepth)\n            {\n                if (hoveringBetweenExpandedParentAndFirstChild)\n                {\n                    targetItem = prevItem.children[0];\n                    dropPosition = DropPosition.Above;\n                }\n                return; // No need to change targetItem if same or higher depth\n            }\n\n            // Search through parents for a new target that matches the cursor\n            var target = targetItem;\n            while (target.depth > minDepth)\n            {\n                if (target.depth == cursorDepth)\n                    break;\n                target = target.parent;\n            }\n\n            didChangeTargetToAncestor = target != targetItem;\n\n            // Change to new targetItem\n            targetItem = target;\n        }\n\n        protected bool TryGetDropPosition(TreeViewItem<TIdentifier> item, Rect itemRect, int row, out DropPosition dropPosition)\n        {\n            Vector2 currentMousePos = Event.current.mousePosition;\n\n            if (itemRect.Contains(currentMousePos))\n            {\n                float dropBetweenHalfHeight = GetDropBetweenHalfHeight(item, itemRect);\n                if (currentMousePos.y >= itemRect.yMax - dropBetweenHalfHeight)\n                    dropPosition = DropPosition.Below;\n                else if (currentMousePos.y <= itemRect.yMin + dropBetweenHalfHeight)\n                    dropPosition = DropPosition.Above;\n                else\n                    dropPosition = DropPosition.Upon;\n                return true;\n            }\n            else\n            {\n                // Check overlap with next item (if any)\n                float nextOverlap = m_TreeView.gui.halfDropBetweenHeight;\n                int nextRow = row + 1;\n                if (nextRow < m_TreeView.data.rowCount)\n                {\n                    Rect nextRect = m_TreeView.gui.GetRowRect(nextRow, itemRect.width);\n                    bool nextCanBeParent = m_TreeView.data.CanBeParent(m_TreeView.data.GetItem(nextRow));\n                    if (nextCanBeParent)\n                        nextOverlap = m_TreeView.gui.halfDropBetweenHeight;\n                    else\n                        nextOverlap = nextRect.height * 0.5f;\n                }\n                Rect nextOverlapRect = itemRect;\n                nextOverlapRect.y = itemRect.yMax;\n                nextOverlapRect.height = nextOverlap;\n                if (nextOverlapRect.Contains(currentMousePos))\n                {\n                    dropPosition = DropPosition.Below;\n                    return true;\n                }\n\n                // Check overlap above first item\n                if (row == 0)\n                {\n                    Rect overlapUpwards = itemRect;\n                    overlapUpwards.yMin -= m_TreeView.gui.halfDropBetweenHeight;\n                    overlapUpwards.height = m_TreeView.gui.halfDropBetweenHeight;\n                    if (overlapUpwards.Contains(currentMousePos))\n                    {\n                        dropPosition = DropPosition.Above;\n                        return true;\n                    }\n                }\n            }\n\n            dropPosition = DropPosition.Below;\n            return false;\n        }\n\n        // This method is called from TreeView and handles:\n        // - Where the dragged items are dropped (above, below or upon)\n        // - Auto expansion of collapsed items when hovering over them\n        // - Setting up the render markers for drop location (horizontal lines)\n        // 'targetItem' is null when not hovering over any target Item, if so the rest of the arguments are invalid\n        public virtual bool DragElement(TreeViewItem<TIdentifier> targetItem, Rect targetItemRect, int row) => DragElementInternal(targetItem, targetItemRect, row);\n        public virtual bool DragElementInternal(TreeViewItem<TIdentifier> targetItem, Rect targetItemRect, int row)\n        {\n            bool perform = Event.current.type == EventType.DragPerform;\n\n            // Are we dragging outside any items\n            if (targetItem == null)\n            {\n                // If so clear any drop markers\n                if (m_DropData != null)\n                {\n                    m_DropData.ClearPerEventState();\n                }\n\n                // And let client decide what happens when dragging outside items\n                DragAndDrop.visualMode = DoDrag(null, null, perform, DropPosition.Below);\n                if (DragAndDrop.visualMode != DragAndDropVisualMode.None && perform)\n                    FinalizeDragPerformed(true);\n\n                return false;\n            }\n\n            DropPosition dropPosition;\n            if (!TryGetDropPosition(targetItem, targetItemRect, row, out dropPosition))\n                return false;\n\n            TreeViewItem<TIdentifier> parentItem = null;\n            TreeViewItem<TIdentifier> dropRelativeToItem = targetItem;\n            bool didChangeTargetToAncestor = false;\n            DropPosition originalDropPosition = dropPosition;\n            switch (dropPosition)\n            {\n                case DropPosition.Upon:\n                    // Parent change: Client must decide what happens when dropping upon: e.g: insert last or first in child list\n                    parentItem = dropRelativeToItem;\n                    break;\n\n                case DropPosition.Below:\n                case DropPosition.Above:\n                    // Sibling change\n                    if (getIndentLevelForMouseCursor != null)\n                    {\n                        int cursorDepth = getIndentLevelForMouseCursor();\n                        HandleSiblingInsertionAtAvailableDepthsAndChangeTargetIfNeeded(ref dropRelativeToItem, row, ref dropPosition, cursorDepth, out didChangeTargetToAncestor);\n                    }\n                    else\n                    {\n                        if (dropPosition == DropPosition.Below && m_TreeView.data.IsExpanded(dropRelativeToItem) && dropRelativeToItem.hasChildren)\n                        {\n                            // When hovering between an expanded parent and its first child then make sure we change state to match that\n                            dropPosition = DropPosition.Above;\n                            dropRelativeToItem = dropRelativeToItem.children[0];\n                        }\n                    }\n                    parentItem = dropRelativeToItem.parent;\n                    break;\n\n                default:\n                    Debug.LogError(\"Unhandled enum. Report a bug.\");\n                    break;\n            }\n\n            if (perform)\n            {\n                DragAndDropVisualMode mode = DragAndDropVisualMode.None;\n                // Try Drop upon target item\n                if (dropPosition == DropPosition.Upon)\n                    mode = DoDrag(dropRelativeToItem, dropRelativeToItem, true, dropPosition);\n\n                // Drop between items\n                if (mode == DragAndDropVisualMode.None && parentItem != null)\n                {\n                    mode = DoDrag(parentItem, dropRelativeToItem, true, dropPosition);\n                }\n\n                // Finalize drop\n                if (mode != DragAndDropVisualMode.None)\n                {\n                    FinalizeDragPerformed(false);\n                }\n                else\n                {\n                    DragCleanup(true);\n                    m_TreeView.NotifyListenersThatDragEnded(null, false);\n                }\n            }\n            else // DragUpdate\n            {\n                if (m_DropData == null)\n                    m_DropData = new DropData();\n                m_DropData.ClearPerEventState();\n\n                // Try drop on top of items\n                if (dropPosition == DropPosition.Upon)\n                {\n                    int itemControlID = TreeViewController<TIdentifier>.GetItemControlID(dropRelativeToItem);\n                    HandleAutoExpansion(itemControlID, dropRelativeToItem, targetItemRect);\n\n                    var mode = DoDrag(dropRelativeToItem, dropRelativeToItem, false, dropPosition);\n                    if (mode != DragAndDropVisualMode.None)\n                    {\n                        m_DropData.dropTargetControlID = itemControlID;\n                        DragAndDrop.visualMode = mode;\n                    }\n                }\n                // Drop between items\n                else if (dropRelativeToItem != null && parentItem != null)\n                {\n                    var mode = DoDrag(parentItem, dropRelativeToItem, false, dropPosition);\n                    if (mode != DragAndDropVisualMode.None)\n                    {\n                        drawRowMarkerAbove = dropPosition == DropPosition.Above;\n                        m_DropData.rowMarkerControlID = TreeViewController<TIdentifier>.GetItemControlID(dropRelativeToItem);\n                        m_DropData.insertionMarkerYPosition = originalDropPosition == DropPosition.Above ? targetItemRect.y : targetItemRect.yMax;\n                        m_DropData.insertRelativeToSibling = dropRelativeToItem;\n                        if (didChangeTargetToAncestor)\n                        {\n                            m_DropData.ancestorControlID = TreeViewController<TIdentifier>.GetItemControlID(dropRelativeToItem);\n                        }\n\n                        DragAndDrop.visualMode = mode;\n                    }\n                }\n            }\n\n            Event.current.Use();\n            return true;\n        }\n\n        void FinalizeDragPerformed(bool revertExpanded)\n        {\n            string undoActionName = \"Drag and Drop Multiple Objects\";\n\n            DragCleanup(revertExpanded);\n            DragAndDrop.AcceptDrag();\n\n            if (m_TreeView is TreeViewController<int> instanceIDTreeView) // todo: change to EntityId\n            {\n                List<UnityEngine.Object> objs = new List<UnityEngine.Object>(DragAndDrop.objectReferences); // TODO, what about when dragging non objects...\n\n                bool draggedItemsFromOwnTreeView = true;\n                if (objs.Count > 0 && objs[0] != null && TreeViewUtility<int>.FindItemInList(objs[0].GetInstanceID(), instanceIDTreeView.data.GetRows()) == null)\n                    draggedItemsFromOwnTreeView = false;\n\n                int[] newSelection = new int[objs.Count];\n                for (int i = 0; i < objs.Count; ++i)\n                {\n                    if (objs[i] == null)\n                        continue;\n\n                    newSelection[i] = (objs[i].GetInstanceID());\n                }\n\n                instanceIDTreeView.NotifyListenersThatDragEnded(newSelection, draggedItemsFromOwnTreeView);\n                if (objs.Count == 1)\n                    undoActionName = \"Drag and Drop \" + objs[0].name;\n            }\n\n            Undo.SetCurrentGroupName(undoActionName);\n        }\n\n        protected virtual void HandleAutoExpansion(int itemControlID, TreeViewItem<TIdentifier> targetItem, Rect targetItemRect)\n        {\n            Vector2 currentMousePos = Event.current.mousePosition;\n\n            // Handle auto expansion\n            float targetItemIndent = m_TreeView.gui.GetContentIndent(targetItem);\n            float betweenHalfHeight = GetDropBetweenHalfHeight(targetItem, targetItemRect);\n            Rect indentedContentRect = new Rect(targetItemRect.x + targetItemIndent, targetItemRect.y + betweenHalfHeight, targetItemRect.width - targetItemIndent, targetItemRect.height - betweenHalfHeight * 2);\n            bool hoveringOverIndentedContent = indentedContentRect.Contains(currentMousePos);\n\n            if (itemControlID != m_DropData.lastControlID || !hoveringOverIndentedContent || m_DropData.expandItemBeginPosition != currentMousePos)\n            {\n                m_DropData.lastControlID = itemControlID;\n                m_DropData.expandItemBeginTimer = Time.realtimeSinceStartup;\n                m_DropData.expandItemBeginPosition = currentMousePos;\n            }\n\n            bool expandTimerExpired = Time.realtimeSinceStartup - m_DropData.expandItemBeginTimer > k_DropExpandTimeout;\n            bool mayExpand = hoveringOverIndentedContent && expandTimerExpired;\n\n            // Auto open folders we are about to drag into\n            if (targetItem != null && mayExpand && targetItem.hasChildren && !m_TreeView.data.IsExpanded(targetItem))\n            {\n                // Store the expanded array prior to drag so we can revert it with a delay later\n                if (m_DropData.expandedArrayBeforeDrag == null)\n                {\n                    List<TIdentifier> expandedIDs = GetCurrentExpanded();\n                    m_DropData.expandedArrayBeforeDrag = expandedIDs.ToArray();\n                }\n\n                m_TreeView.data.SetExpanded(targetItem, true);\n                m_DropData.expandItemBeginTimer = Time.realtimeSinceStartup;\n                m_DropData.lastControlID = 0;\n            }\n        }\n\n        public virtual void DragCleanup(bool revertExpanded)\n        {\n            if (m_DropData != null)\n            {\n                if (m_DropData.expandedArrayBeforeDrag != null && revertExpanded)\n                {\n                    RestoreExpanded(new List<TIdentifier>(m_DropData.expandedArrayBeforeDrag));\n                }\n                m_DropData = new DropData();\n            }\n        }\n\n        public List<TIdentifier> GetCurrentExpanded()\n        {\n            var visibleItems = m_TreeView.data.GetRows();\n            List<TIdentifier> expandedIDs = (from item in visibleItems\n                where m_TreeView.data.IsExpanded(item)\n                select item.id).ToList();\n            return expandedIDs;\n        }\n\n        // We assume that we can only have expanded items during dragging\n        public void RestoreExpanded(List<TIdentifier> ids)\n        {\n            var visibleItems = m_TreeView.data.GetRows();\n            foreach (TreeViewItem<TIdentifier> item in visibleItems)\n                m_TreeView.data.SetExpanded(item, ids.Contains(item.id));\n        }\n\n        internal static int GetInsertionIndex(TreeViewItem<TIdentifier> parentItem, TreeViewItem<TIdentifier> targetItem, DropPosition dropPosition)\n        {\n            if (parentItem == null)\n                return -1;\n\n            int insertionIndex;\n            if (parentItem == targetItem)\n            {\n                // Let user decide what index item should be added to when dropping upon\n                insertionIndex = -1;\n                Assert.AreEqual(DropPosition.Upon, dropPosition);\n            }\n            else\n            {\n                int index = parentItem.children.IndexOf(targetItem);\n                if (index >= 0)\n                {\n                    if (dropPosition == DropPosition.Below)\n                        insertionIndex = index + 1;\n                    else\n                        insertionIndex = index;\n                }\n                else\n                {\n                    Debug.LogError(Constants.GetInsertionIndexNotFound);\n                    insertionIndex = -1;\n                }\n            }\n            return insertionIndex;\n        }\n    }\n} // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewExpandAnimator.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Globalization;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    // Setup animation, tracks animation, fires callback when done (fully expanded/collapsed)\n    //\n\n    internal class TreeViewItemExpansionAnimator<TIdentifier> where TIdentifier : unmanaged, System.IEquatable<TIdentifier>\n    {\n        TreeViewAnimationInput<TIdentifier> m_Setup; // when null we are not animating\n        bool m_InsideGUIClip;\n        Rect m_CurrentClipRect;\n        static bool s_Debug = false;\n\n        public void BeginAnimating(TreeViewAnimationInput<TIdentifier> setup)\n        {\n            if (m_Setup != null)\n            {\n                if (m_Setup.item.id.Equals(setup.item.id) && m_Setup.expanding != setup.expanding)\n                {\n                    // If same item (changed expand/collapse while animating) then just change direction, but skip the time that already passed\n                    if (m_Setup.elapsedTime >= 0)\n                    {\n                        setup.elapsedTime = m_Setup.animationDuration - m_Setup.elapsedTime;\n                    }\n                    else\n                        Debug.LogError(\"Invalid duration \" + m_Setup.elapsedTime);\n\n                    m_Setup = setup;\n                }\n                else\n                {\n                    // Ensure current animation ends before starting a new (just finish it immediately)\n                    SkipAnimating();\n                    m_Setup = setup;\n                }\n\n                m_Setup.expanding = setup.expanding;\n            }\n\n            m_Setup = setup;\n            if (m_Setup == null)\n                Debug.LogError(\"Setup is null\");\n\n            if (printDebug)\n                Console.WriteLine(\"Begin animating: \" + m_Setup);\n\n            m_CurrentClipRect = GetCurrentClippingRect();\n        }\n\n        public void SkipAnimating()\n        {\n            if (m_Setup != null)\n            {\n                m_Setup.FireAnimationEndedEvent();\n                m_Setup = null;\n            }\n        }\n\n        // Returns true if row should be culled\n        public bool CullRow(int row, ITreeViewGUI<TIdentifier> gui)\n        {\n            if (!isAnimating)\n            {\n                return false;\n            }\n\n            if (printDebug && row == 0)\n                Console.WriteLine(\"--------\");\n\n            // Check rows that are inside animation clip rect if they can be culled\n            if (row > m_Setup.startRow && row <= m_Setup.endRow)\n            {\n                Rect rowRect = gui.GetRowRect(row, 1); // we do not care about the width\n\n                // Check row Y local to clipRect\n                float rowY = rowRect.y - m_Setup.startRowRect.y;\n\n                if (rowY > m_CurrentClipRect.height)\n                {\n                    // Ensure to end animation clip since items after\n                    // culling should be rendered normally\n                    if (m_InsideGUIClip)\n                    {\n                        EndClip();\n                    }\n\n                    return true;\n                }\n            }\n\n            // Row is not culled\n            return false;\n        }\n\n        public void OnRowGUI(int row)\n        {\n            if (printDebug)\n                Console.WriteLine(row + \" Do item \" + DebugItemName(row));\n        }\n\n        // Call before of TreeViewGUI's OnRowGUI (Needs to be called for all items (changes rects for rows comming after the animating rows)\n        public Rect OnBeginRowGUI(int row, Rect rowRect)\n        {\n            if (!isAnimating)\n                return rowRect;\n\n            if (row == m_Setup.startRow)\n            {\n                BeginClip();\n            }\n\n            // Make row rect local to guiclip if animating\n            if (row >= m_Setup.startRow && row <= m_Setup.endRow)\n            {\n                rowRect.y -= m_Setup.startRowRect.y;\n            }\n            // rows following the animation snap to cliprect bottom\n            else if (row > m_Setup.endRow)\n            {\n                rowRect.y -= m_Setup.rowsRect.height - m_CurrentClipRect.height;\n            }\n\n            return rowRect;\n        }\n\n        // Call at the after TreeViewGUI's OnRowGUI\n        public void OnEndRowGUI(int row)\n        {\n            if (!isAnimating)\n                return;\n\n            if (m_InsideGUIClip && row == m_Setup.endRow)\n            {\n                EndClip();\n            }\n        }\n\n        // Call before all items are being handling\n\n\n        private void BeginClip()\n        {\n            GUI.BeginClip(m_CurrentClipRect);\n            m_InsideGUIClip = true;\n            if (printDebug)\n                Console.WriteLine(\"BeginClip startRow: \" + m_Setup.startRow);\n        }\n\n        private void EndClip()\n        {\n            GUI.EndClip();\n            m_InsideGUIClip = false;\n            if (printDebug)\n                Console.WriteLine(\"EndClip endRow: \" + m_Setup.endRow);\n        }\n\n        public void OnBeforeAllRowsGUI()\n        {\n            if (!isAnimating)\n                return;\n\n            // Cache to ensure consistent across all rows (it is dependant on time)\n            m_CurrentClipRect = GetCurrentClippingRect();\n\n            // Stop animation when duration has passed\n            if (m_Setup.elapsedTime > m_Setup.animationDuration)\n            {\n                m_Setup.FireAnimationEndedEvent();\n                m_Setup = null;\n\n                if (printDebug)\n                    Debug.Log(\"Animation ended\");\n            }\n        }\n\n        public void OnAfterAllRowsGUI()\n        {\n            // Ensure to end clip if not done in CullRow (while iterating rows)\n            if (m_InsideGUIClip)\n            {\n                EndClip();\n            }\n\n            // Capture time at intervals to ensure that expansion value is consistent across layout and repaint.\n            // This fixes that the scroll view showed its scrollbars during expansion since using realtime\n            // would give higher values on repaint than on layout event.\n            if (isAnimating && Event.current.type == EventType.Repaint)\n            {\n                HandleUtility.Repaint();\n                m_Setup.CaptureTime();\n            }\n        }\n\n        public bool IsAnimating(TIdentifier itemID)\n        {\n            if (!isAnimating)\n                return false;\n\n            return m_Setup.item.id.Equals(itemID);\n        }\n\n        // 1 fully expanded, 0 fully collapsed\n        public float expandedValueNormalized\n        {\n            get\n            {\n                float frac = m_Setup.elapsedTimeNormalized;\n                return m_Setup.expanding ? frac : (1.0f - frac);\n            }\n        }\n\n        public int startRow\n        {\n            get { return m_Setup.startRow; }\n        }\n\n        public int endRow\n        {\n            get { return m_Setup.endRow; }\n        }\n\n        public float deltaHeight\n        {\n            get { return Mathf.Floor(m_Setup.rowsRect.height - m_Setup.rowsRect.height * expandedValueNormalized); }\n        }\n\n        public bool isAnimating\n        {\n            get { return m_Setup != null; }\n        }\n\n        public bool isExpanding\n        {\n            get { return m_Setup.expanding; }\n        }\n\n        Rect GetCurrentClippingRect()\n        {\n            Rect rect = m_Setup.rowsRect;\n            rect.height *= expandedValueNormalized;\n            return rect;\n        }\n\n        bool printDebug\n        {\n            get { return s_Debug && (m_Setup != null) && (m_Setup.treeView != null) && (Event.current.type == EventType.Repaint); }\n        }\n\n        string DebugItemName(int row)\n        {\n            return m_Setup.treeView.data.GetRows()[row].displayName;\n        }\n    }\n\n    internal class TreeViewAnimationInput<TIdentifier> where TIdentifier : unmanaged, System.IEquatable<TIdentifier>\n    {\n        public TreeViewAnimationInput()\n        {\n            startTime = timeCaptured = EditorApplication.timeSinceStartup;\n        }\n\n        public void CaptureTime()\n        {\n            timeCaptured = EditorApplication.timeSinceStartup;\n        }\n\n        public float elapsedTimeNormalized\n        {\n            get\n            {\n                return Mathf.Clamp01((float)elapsedTime / (float)animationDuration);\n            }\n        }\n\n        public double elapsedTime\n        {\n            get\n            {\n                return timeCaptured - startTime;\n            }\n\n            set\n            {\n                startTime = timeCaptured - value;\n            }\n        }\n\n        public int startRow { get; set; }\n        public int endRow { get; set; }\n        public Rect rowsRect {get; set; } // the rect encapsulating startrow and endrow\n\n        public Rect startRowRect {get; set; }\n        public double startTime { get; set; }\n        public double timeCaptured { get; set; }\n        public double animationDuration { get; set; }\n        public bool expanding { get; set; }\n        public bool includeChildren { get; set; }\n        public TreeViewItem<TIdentifier> item { get; set; }\n        public TreeViewController<TIdentifier> treeView { get; set; }\n\n        public System.Action<TreeViewAnimationInput<TIdentifier>> animationEnded; // set to get a callback when animation ends\n\n        public void FireAnimationEndedEvent()\n        {\n            if (animationEnded != null)\n                animationEnded(this);\n        }\n\n        public override string ToString()\n        {\n            return \"Input: startRow \" + startRow + \" endRow \" + endRow + \" rowsRect \" + rowsRect + \" startTime \" + startTime.ToString(CultureInfo.InvariantCulture.NumberFormat) + \" anitmationDuration\" + animationDuration + \" \" + expanding + \" \" + item.displayName;\n        }\n    }\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEditor.Experimental;\nusing UnityEditor.StyleSheets;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    internal abstract class TreeViewGUI<TIdentifier> : ITreeViewGUI<TIdentifier> where TIdentifier : unmanaged, IEquatable<TIdentifier>\n    {\n        protected TreeViewController<TIdentifier>  m_TreeView;\n        protected PingData m_Ping = new PingData();\n        protected Rect m_DraggingInsertionMarkerRect;\n        protected Rect m_DraggingAncestorMarkerRect;\n        protected bool m_UseHorizontalScroll;\n\n        // Icon overlay\n        public float iconLeftPadding { get; set; }\n        public float iconRightPadding { get; set; }\n        public float iconTotalPadding { get { return iconLeftPadding + iconRightPadding; } }\n        public System.Action<TreeViewItem<TIdentifier> , Rect> iconOverlayGUI { get; set; } // Rect includes iconLeftPadding and iconRightPadding\n        public System.Action<TreeViewItem<TIdentifier> , Rect> labelOverlayGUI { get; set; }\n\n        private bool m_AnimateScrollBarOnExpandCollapse = true;\n\n        // Layout\n        private float m_LineHeight = -1;\n        public float k_LineHeight\n        {\n            get\n            {\n                if (m_LineHeight < 0)\n                    m_LineHeight = new SVC<float>(\"--treeview-line-height\", 16f);\n\n                return m_LineHeight;\n            }\n            set { m_LineHeight = value; }\n        }\n        public float k_BaseIndent = 2f;\n        public float k_IndentWidth = 14f;\n        public float k_IconWidth = 16f;\n        public float k_SpaceBetweenIconAndText = 2f;\n        public float k_TopRowMargin = 0f;\n        public float k_BottomRowMargin = 0f;\n        public float indentWidth { get { return k_IndentWidth + iconTotalPadding; } }\n        public float k_HalfDropBetweenHeight = 4f;\n        public float customFoldoutYOffset = 0f;\n        public float extraInsertionMarkerIndent = 0f;\n        public float extraSpaceBeforeIconAndLabel { get; set; }\n        public bool drawSelection { get; set; } = true;\n        public float halfDropBetweenHeight { get { return k_HalfDropBetweenHeight; } }\n\n        public virtual float topRowMargin { get { return k_TopRowMargin; } }\n        public virtual float bottomRowMargin { get { return k_BottomRowMargin; } }\n\n        // Styles\n        internal static class Styles\n        {\n            public static GUIStyle foldout = \"IN Foldout\";\n            public static GUIStyle insertion = \"TV Insertion\";\n            public static GUIStyle insertionRelativeToSibling = \"TV InsertionRelativeToSibling\";\n            public static GUIStyle ping = \"TV Ping\";\n            public static GUIStyle toolbarButton = \"ToolbarButton\";\n            public static GUIStyle lineStyle = \"TV Line\";\n            public static GUIStyle lineBoldStyle = \"TV LineBold\";\n            public static GUIStyle selectionStyle = \"TV Selection\";\n            public static GUIContent content = new GUIContent(EditorGUIUtility.FindTexture(EditorResources.folderIconName));\n        }\n\n        private GUIStyle m_FoldoutStyle;\n        protected GUIStyle foldoutStyle\n        {\n            get\n            {\n                return m_FoldoutStyle ?? Styles.foldout;\n            }\n            set { m_FoldoutStyle = value; }\n        }\n\n        private GUIStyle m_InsertionStyle;\n        protected GUIStyle insertionStyle\n        {\n            get\n            {\n                return m_InsertionStyle ?? Styles.insertion;\n            }\n            set { m_InsertionStyle = value; }\n        }\n\n        private GUIStyle m_InsertionRelativeToSiblingStyle;\n        protected GUIStyle insertionRelativeToSiblingStyle\n        {\n            get\n            {\n                return m_InsertionRelativeToSiblingStyle ?? Styles.insertionRelativeToSibling;\n            }\n            set { m_InsertionRelativeToSiblingStyle = value; }\n        }\n\n        private GUIStyle m_PingStyle;\n        protected GUIStyle pingStyle\n        {\n            get\n            {\n                return m_PingStyle ?? Styles.ping;\n            }\n            set { m_PingStyle = value; }\n        }\n        private GUIStyle m_ToolbarButtonStyle;\n        protected GUIStyle toolbarButtonStyle\n        {\n            get\n            {\n                return m_ToolbarButtonStyle ?? Styles.toolbarButton;\n            }\n            set { m_ToolbarButtonStyle = value; }\n        }\n        private GUIStyle m_LineStyle;\n        protected GUIStyle lineStyle\n        {\n            get\n            {\n                return m_LineStyle ?? Styles.lineStyle;\n            }\n            set { m_LineStyle = value; }\n        }\n        private GUIStyle m_SelectionStyle;\n        protected GUIStyle selectionStyle\n        {\n            get\n            {\n                return m_SelectionStyle ?? Styles.selectionStyle;\n            }\n            set { m_SelectionStyle = value; }\n        }\n\n        private GUIStyle renameStyle\n        {\n            get\n            {\n                GUIStyle renameStyle = new GUIStyle(\"PR TextField\");\n                renameStyle.fontSize = lineStyle.fontSize; // the textField should have the same text size as the line\n\n                return renameStyle;\n            }\n        }\n        protected float foldoutStyleWidth\n        {\n            get { return foldoutStyle.fixedWidth; }\n        }\n\n        public TreeViewGUI(TreeViewController<TIdentifier>  treeView)\n        {\n            m_TreeView = treeView;\n        }\n\n        public TreeViewGUI(TreeViewController<TIdentifier>  treeView, bool useHorizontalScroll)\n        {\n            m_TreeView = treeView;\n            m_UseHorizontalScroll = useHorizontalScroll;\n        }\n\n        virtual public void OnInitialize()\n        {\n            var dragging = m_TreeView.dragging as TreeViewDragging<TIdentifier> ;\n            if (dragging != null)\n                dragging.getIndentLevelForMouseCursor = GetIndentLevelForMouseCursor;\n        }\n\n        int GetIndentLevelForMouseCursor()\n        {\n            float contentStartX = k_BaseIndent + extraInsertionMarkerIndent + foldoutStyleWidth + lineStyle.margin.left;\n            float mousePosX = Event.current.mousePosition.x;\n            return Mathf.FloorToInt((mousePosX - contentStartX) / indentWidth);\n        }\n\n        internal Texture GetEffectiveIcon(TreeViewItem<TIdentifier>  item, bool selected, bool focused)\n        {\n            var icon = GetIconForItem(item);\n\n            if (selected && focused)\n            {\n                var selIcon = GetIconForSelectedItem(item);\n\n                if (selIcon != null)\n                    return selIcon;\n            }\n\n            return icon;\n        }\n\n        protected virtual Texture GetIconForItem(TreeViewItem<TIdentifier>  item) => GetIconForItemInternal(item);\n        protected virtual Texture GetIconForItemInternal(TreeViewItem<TIdentifier>  item)\n        {\n            return item.icon;\n        }\n\n        internal virtual Texture GetIconForSelectedItem(TreeViewItem<TIdentifier>  item)\n        {\n            return EditorUtility.GetIconInActiveState(GetIconForItem(item));\n        }\n\n        // ------------------\n        // Size section\n\n        // Calc correct width if horizontal scrollbar is wanted return new Vector2(1, height)\n        virtual public Vector2 GetTotalSize()\n        {\n            // Width is 1 to prevent showing horizontal scrollbar\n            float width = 1f;\n            if (m_UseHorizontalScroll)\n            {\n                var rows = m_TreeView.data.GetRows();\n                width = GetMaxWidth(rows);\n            }\n\n            // Height\n            float height = m_TreeView.data.rowCount * k_LineHeight + topRowMargin + bottomRowMargin;\n\n\n            if (m_AnimateScrollBarOnExpandCollapse && m_TreeView.expansionAnimator.isAnimating)\n            {\n                height -= m_TreeView.expansionAnimator.deltaHeight;\n            }\n\n            return new Vector2(width, height);\n        }\n\n        protected float GetMaxWidth(IList<TreeViewItem<TIdentifier>> rows)\n        {\n            float maxWidth = 1f;\n\n            foreach (TreeViewItem<TIdentifier>  item in rows)\n            {\n                float width = 0f;\n\n                width += GetContentIndent(item);\n\n                if (item.icon != null)\n                    width += k_IconWidth;\n\n                float minNameWidth, maxNameWidth;\n                lineStyle.CalcMinMaxWidth(GUIContent.Temp(item.displayName), out minNameWidth, out maxNameWidth);\n                width += maxNameWidth;\n\n                // Add some padding to the back\n                width += k_BaseIndent;\n\n                if (width > maxWidth)\n                    maxWidth = width;\n            }\n\n            return maxWidth;\n        }\n\n        virtual public int GetNumRowsOnPageUpDown(TreeViewItem<TIdentifier>  fromItem, bool pageUp, float heightOfTreeView)\n        {\n            return (int)Mathf.Floor(heightOfTreeView / k_LineHeight);\n        }\n\n        // Should return the row index of the first and last row thats fits in the pixel rect defined by top and height\n        virtual public void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible)\n        {\n            if (m_TreeView.data.rowCount == 0 || Mathf.Approximately(m_TreeView.visibleRect.height, 0.0f))\n            {\n                firstRowVisible = lastRowVisible = -1;\n                return;\n            }\n\n            float topPixel = m_TreeView.state.scrollPos.y;\n            float heightInPixels = m_TreeView.visibleRect.height;\n            firstRowVisible = (int)Mathf.Floor((topPixel - topRowMargin) / k_LineHeight);\n            lastRowVisible = firstRowVisible + (int)Mathf.Ceil(heightInPixels / k_LineHeight);\n\n            firstRowVisible = Mathf.Max(firstRowVisible, 0);\n            lastRowVisible = Mathf.Min(lastRowVisible, m_TreeView.data.rowCount - 1);\n\n            // Validate\n            if (firstRowVisible >= m_TreeView.data.rowCount && firstRowVisible > 0)\n            {\n                // Reset scroll if it was invalid, this can be the case if scroll y value was serialized and loading new tree data\n                m_TreeView.state.scrollPos.y = 0f;\n                GetFirstAndLastRowVisible(out firstRowVisible, out lastRowVisible);\n            }\n        }\n\n        // ---------------------\n        // OnGUI section\n\n        virtual public void BeginRowGUI()\n        {\n            // Reset\n            m_DraggingInsertionMarkerRect.x = -1;\n            m_DraggingAncestorMarkerRect.x = -1;\n\n            SyncFakeItem(); // After domain reload we ensure to reconstruct new Item state\n\n            // Input for rename overlay (repainted in EndRowGUI to ensure rendered on top)\n            if (Event.current.type != EventType.Repaint)\n                DoRenameOverlay();\n        }\n\n        void DrawDraggingInsertionMarkerIfNeeded()\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            // If an inheriting class already set the m_DraggingInsertionMarkerRect we don't overwrite it\n            var dragging = m_TreeView.dragging as TreeViewDragging<TIdentifier>;\n            if (dragging != null && dragging.insertionMarkerYPosition > 0 && m_DraggingInsertionMarkerRect.x == -1)\n            {\n                float xPos = GetContentIndent(dragging.insertRelativeToSibling) + extraInsertionMarkerIndent;\n                float yPos = dragging.insertionMarkerYPosition - insertionStyle.fixedHeight * 0.5f;\n                m_DraggingInsertionMarkerRect = new Rect(xPos, yPos, GUIClip.visibleRect.width - xPos, insertionStyle.fixedHeight);\n            }\n\n            // Draw row marker when dragging\n            if (m_DraggingInsertionMarkerRect.x >= 0)\n            {\n                insertionStyle.Draw(m_DraggingInsertionMarkerRect, false, false, false, false);\n            }\n\n            if (m_DraggingAncestorMarkerRect.x >= 0)\n            {\n                insertionRelativeToSiblingStyle.Draw(m_DraggingAncestorMarkerRect, GUIContent.none, false, false, false, false);\n            }\n        }\n\n        virtual public void EndRowGUI()\n        {\n            DrawDraggingInsertionMarkerIfNeeded();\n\n            // Render rename overlay last (input is handled in BeginRowGUI)\n            if (Event.current.type == EventType.Repaint)\n                DoRenameOverlay();\n\n            // Ping a Item\n            HandlePing();\n        }\n\n        virtual public void OnRowGUI(Rect rowRect, TreeViewItem<TIdentifier>  item, int row, bool selected, bool focused) => OnRowGUIInternal(rowRect, item, row, selected, focused);\n        virtual public void OnRowGUIInternal(Rect rowRect, TreeViewItem<TIdentifier>  item, int row, bool selected, bool focused)\n        {\n            DoItemGUI(rowRect, row, item, selected, focused, false);\n        }\n\n        // Override this method for custom rendering of background behind selection and drop effect rendering\n        protected virtual void DrawItemBackground(Rect rect, int row, TreeViewItem<TIdentifier>  item, bool selected, bool focused)\n        {\n            if (item == m_TreeView.hoveredItem)\n            {\n                using (new GUI.BackgroundColorScope(GameObjectTreeViewGUI.GameObjectStyles.hoveredBackgroundColor))\n                {\n                    GUI.Label(rect, GUIContent.none, GameObjectTreeViewGUI.GameObjectStyles.hoveredItemBackgroundStyle);\n                }\n            }\n        }\n\n        public virtual Rect GetRenameRect(Rect rowRect, int row, TreeViewItem<TIdentifier>  item)\n        {\n            float offset = GetContentIndent(item) + extraSpaceBeforeIconAndLabel;\n\n            if (GetIconForItem(item) != null)\n                offset += k_SpaceBetweenIconAndText + k_IconWidth + iconTotalPadding;\n\n            // By default we top align the rename rect to follow the label style, foldout and controls alignment\n            return new Rect(rowRect.x + offset, rowRect.y, rowRect.width - offset,\n                rowRect.height);\n        }\n\n        virtual protected void DoItemGUI(Rect rect, int row, TreeViewItem<TIdentifier>  item, bool selected, bool focused, bool useBoldFont)\n        {\n            EditorGUIUtility.SetIconSize(new Vector2(k_IconWidth, k_IconWidth)); // If not set we see icons scaling down if text is being cropped\n\n            int itemControlID = TreeViewController<TIdentifier>.GetItemControlID(item);\n\n            bool isRenamingThisItem = IsRenaming(item.id);\n            bool showFoldout = m_TreeView.data.IsExpandable(item);\n\n            // Adjust edit field if needed (on repaint since on layout rect.width is invalid when using GUILayout)\n            if (isRenamingThisItem && Event.current.type == EventType.Repaint)\n            {\n                GetRenameOverlay().editFieldRect = GetRenameRect(rect, row, item);\n            }\n\n            string label = item.displayName;\n            if (isRenamingThisItem)\n            {\n                selected = false;\n                label = \"\";\n            }\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                // Draw background (can be overridden)\n                DrawItemBackground(rect, row, item, selected, focused);\n\n                // Draw selection\n                if (selected && drawSelection)\n                    selectionStyle.Draw(rect, false, false, true, focused);\n\n                bool hasDragHandling = m_TreeView.dragging != null;\n                if (hasDragHandling)\n                {\n                    // Draw drop marker\n                    if (m_TreeView.dragging.GetDropTargetControlID() == itemControlID && m_TreeView.data.CanBeParent(item))\n                    {\n                        Styles.lineStyle.Draw(GetDropTargetRect(rect), GUIContent.none, true, true, false, false);\n                    }\n\n                    // Ancestor item marker is rendered after all rows in RowEndGUI - extra visual helper marker when previous sibling is far away from the cursor\n                    var dragging = m_TreeView.dragging as TreeViewDragging<TIdentifier>;\n                    if (dragging != null && dragging.GetAncestorControlID() == itemControlID && dragging.insertRelativeToSibling != null)\n                    {\n                        m_DraggingAncestorMarkerRect = rect;\n                        m_DraggingAncestorMarkerRect.xMin += extraInsertionMarkerIndent + GetContentIndent(item);\n                        m_DraggingAncestorMarkerRect.y = rect.yMax - insertionRelativeToSiblingStyle.fixedHeight * 0.5f;\n                    }\n                }\n            }\n\n            // Do additional ui controls (menu button, prefab arrow etc)\n            OnAdditionalGUI(rect, row, item, selected, focused);\n\n            // Do row content (icon, label, controls etc)\n            OnContentGUI(rect, row, item, label, selected, focused, useBoldFont, false);\n\n            // Do foldout\n            if (showFoldout)\n            {\n                DoFoldout(rect, item, row);\n            }\n\n            EditorGUIUtility.SetIconSize(Vector2.zero);\n        }\n\n        protected virtual Rect GetDropTargetRect(Rect rect)\n        {\n            return rect;\n        }\n\n        float GetTopPixelOfRow(int row)\n        {\n            return row * k_LineHeight + topRowMargin;\n        }\n\n        public virtual Rect GetRowRect(int row, float rowWidth)\n        {\n            return new Rect(0, GetTopPixelOfRow(row), rowWidth, k_LineHeight);\n        }\n\n        public virtual Rect GetRectForFraming(int row)\n        {\n            return GetRowRect(row, 1); // We ignore width by default when framing (only y scroll is affected)\n        }\n\n        float GetFoldoutYPosition(float rectY)\n        {\n            // By default the arrow is aligned to the top to match text rendering\n            return rectY + customFoldoutYOffset;\n        }\n\n        protected virtual Rect DoFoldout(Rect rect, TreeViewItem<TIdentifier>  item, int row)\n        {\n            float indent = GetFoldoutIndent(item);\n            Rect foldoutRect = new Rect(rect.x + indent, GetFoldoutYPosition(rect.y), foldoutStyleWidth, k_LineHeight);\n            FoldoutButton(foldoutRect, item, row, foldoutStyle);\n            return foldoutRect;\n        }\n\n        protected virtual void FoldoutButton(Rect foldoutRect, TreeViewItem<TIdentifier>  item, int row, GUIStyle foldoutStyle)\n        {\n            var expansionAnimator = m_TreeView.expansionAnimator;\n\n            bool newExpandedValue;\n            EditorGUI.BeginChangeCheck();\n            {\n                bool expandedState = expansionAnimator.IsAnimating(item.id) ? expansionAnimator.isExpanding : m_TreeView.data.IsExpanded(item);\n                newExpandedValue = DoFoldoutButton(foldoutRect, expandedState, foldoutStyle);\n            }\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_TreeView.UserInputChangedExpandedState(item, row, newExpandedValue);\n            }\n        }\n\n        protected virtual bool DoFoldoutButton(Rect foldoutRect, bool expandedState, GUIStyle foldoutStyle)\n        {\n            return GUI.Toggle(foldoutRect, expandedState, GUIContent.none, foldoutStyle);\n        }\n\n        protected virtual void OnAdditionalGUI(Rect rect, int row, TreeViewItem<TIdentifier>  item, bool selected, bool focused)\n        {\n        }\n\n        protected virtual void OnContentGUI(Rect rect, int row, TreeViewItem<TIdentifier>  item, string label, bool selected, bool focused, bool useBoldFont, bool isPinging)\n        {\n            if (Event.current.rawType != EventType.Repaint)\n                return;\n\n            if (!isPinging)\n            {\n                // The rect is assumed indented and sized after the content when pinging\n                float indent = GetContentIndent(item) + extraSpaceBeforeIconAndLabel;\n                rect.xMin += indent;\n            }\n\n            lineStyle = useBoldFont ? Styles.lineBoldStyle : Styles.lineStyle;\n\n            // Draw icon\n            Rect iconRect = rect;\n            iconRect.width = k_IconWidth;\n            iconRect.x += iconLeftPadding;\n\n            Texture icon = GetEffectiveIcon(item, selected, focused);\n            if (icon != null)\n            {\n                var iconColor = GUI.color.AlphaMultiplied(GUI.enabled ? 1f : 0.5f);\n                GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleToFit, true, 0, iconColor, 0, 0);\n            }\n\n            if (iconOverlayGUI != null)\n            {\n                Rect iconOverlayRect = rect;\n                iconOverlayRect.width = k_IconWidth + iconTotalPadding;\n                iconOverlayGUI(item, iconOverlayRect);\n            }\n\n            // Draw text\n            if (icon != null)\n                rect.xMin += k_IconWidth + iconTotalPadding + k_SpaceBetweenIconAndText;\n            lineStyle.Draw(rect, label, false, false, selected, focused);\n\n            if (labelOverlayGUI != null)\n            {\n                labelOverlayGUI(item, rect);\n            }\n        }\n\n        // Ping Item\n        // -------------\n\n        virtual public void BeginPingItem(TreeViewItem<TIdentifier>  item, float topPixelOfRow, float availableWidth)\n        {\n            if (item == null)\n                return;\n\n            // Setup ping\n            if (topPixelOfRow >= 0f)\n            {\n                m_Ping.isPinging = true;\n                m_Ping.m_PingStyle = pingStyle;\n\n                GUIContent cont = GUIContent.Temp(item.displayName);\n                Vector2 contentSize = m_Ping.m_PingStyle.CalcSize(cont);\n\n                m_Ping.m_ContentRect = new Rect(GetContentIndent(item) + extraSpaceBeforeIconAndLabel,\n                    topPixelOfRow,\n                    k_IconWidth + k_SpaceBetweenIconAndText + contentSize.x + iconTotalPadding,\n                    contentSize.y);\n\n                m_Ping.m_AvailableWidth = availableWidth;\n\n                int row = m_TreeView.data.GetRow(item.id);\n\n                bool useBoldFont = item.displayName.Equals(\"Assets\");\n                m_Ping.m_ContentDraw = (Rect r) =>\n                {\n                    // get Item parameters from closure\n                    OnContentGUI(r, row, item, item.displayName, false, false, useBoldFont, true);\n                };\n\n                m_TreeView.Repaint();\n            }\n        }\n\n        virtual public void EndPingItem()\n        {\n            m_Ping.isPinging = false;\n        }\n\n        void HandlePing()\n        {\n            m_Ping.HandlePing();\n\n            if (m_Ping.isPinging)\n                m_TreeView.Repaint();\n        }\n\n        //-------------------\n        // Rename section\n\n        protected RenameOverlay<TIdentifier> GetRenameOverlay()\n        {\n            return m_TreeView.state.renameOverlay;\n        }\n\n        virtual protected bool IsRenaming(TIdentifier id)\n        {\n            return GetRenameOverlay().IsRenaming() && GetRenameOverlay().userData.Equals(id) && !GetRenameOverlay().isWaitingForDelay;\n        }\n\n        virtual public bool BeginRename(TreeViewItem<TIdentifier>  item, float delay) => BeginRenameInternal(item, delay);\n        virtual public bool BeginRenameInternal(TreeViewItem<TIdentifier>  item, float delay)\n        {\n            return GetRenameOverlay().BeginRename(item.displayName, item.id, delay);\n        }\n\n        virtual public void EndRename()\n        {\n            // We give keyboard focus back to our tree view because the rename utility stole it (now we give it back)\n            if (GetRenameOverlay().HasKeyboardFocus())\n                m_TreeView.GrabKeyboardFocus();\n\n            RenameEnded();\n            ClearRenameAndNewItemState(); // Ensure clearing if RenameEnden is overrided\n        }\n\n        virtual protected void RenameEnded() {}\n\n        virtual public void DoRenameOverlay()\n        {\n            if (GetRenameOverlay().IsRenaming())\n                if (!GetRenameOverlay().OnGUI(renameStyle))\n                    EndRename();\n        }\n\n        virtual protected void SyncFakeItem() {}\n\n\n        virtual protected void ClearRenameAndNewItemState()\n        {\n            m_TreeView.data.RemoveFakeItem();\n            GetRenameOverlay().Clear();\n        }\n\n        virtual public float GetFoldoutIndent(TreeViewItem<TIdentifier>  item)\n        {\n            // Ignore depth when showing search results\n            if (m_TreeView.isSearching)\n                return k_BaseIndent;\n\n            return k_BaseIndent + item.depth * indentWidth;\n        }\n\n        virtual public float GetContentIndent(TreeViewItem<TIdentifier>  item)\n        {\n            return GetFoldoutIndent(item) + foldoutStyleWidth + lineStyle.margin.left;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewGUIWithCustomItemHeights.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\n\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing ITreeViewGUI = UnityEditor.IMGUI.Controls.ITreeViewGUI<int>;\n\n\nnamespace UnityEditor\n{\n    // Total size: 1) When changing: non changing rows + changing rows fraction, 2) When not changing sum of rows\n    // Size of changing rows fraction used for finding new endRow after last changing row\n\n    internal abstract class TreeViewGUIWithCustomItemsHeights : ITreeViewGUI\n    {\n        private List<Rect> m_RowRects = new List<Rect>();\n        private float m_MaxWidthOfRows;\n        protected readonly TreeViewController m_TreeView;\n\n        public TreeViewGUIWithCustomItemsHeights(TreeViewController treeView)\n        {\n            m_TreeView = treeView;\n        }\n\n        public virtual void OnInitialize()\n        {\n        }\n\n        public Rect GetRowRect(int row, float rowWidth)\n        {\n            if (m_RowRects.Count == 0)\n            {\n                Debug.LogError(\"Ensure precalc rects\");\n                return new Rect();\n            }\n\n            return m_RowRects[row];\n        }\n\n        public Rect GetRenameRect(Rect rowRect, int row, TreeViewItem item)\n        {\n            return new Rect();\n        }\n\n        public Rect GetRectForFraming(int row)\n        {\n            return GetRowRect(row, 1);\n        }\n\n        public abstract void OnRowGUI(Rect rowRect, TreeViewItem item, int row, bool selected, bool focused);\n\n        protected virtual float AddSpaceBefore(TreeViewItem item)\n        {\n            return 0;\n        }\n\n        protected virtual Vector2 GetSizeOfRow(TreeViewItem item)\n        {\n            return new Vector2(m_TreeView.GetTotalRect().width, 16);\n        }\n\n        public void CalculateRowRects()\n        {\n            if (m_TreeView.isSearching)\n                return;\n            const float startY = 2f;\n            var rows = m_TreeView.data.GetRows();\n            m_RowRects = new List<Rect>(rows.Count);\n            float curY = startY;\n            m_MaxWidthOfRows = 1f;\n            for (int i = 0; i < rows.Count; ++i)\n            {\n                TreeViewItem item = rows[i];\n                float space = AddSpaceBefore(item);\n                curY += space;\n                Vector2 rowSize = GetSizeOfRow(item);\n                m_RowRects.Add(new Rect(0, curY, rowSize.x, rowSize.y));\n                curY += rowSize.y;\n                if (rowSize.x > m_MaxWidthOfRows)\n                    m_MaxWidthOfRows = rowSize.x;\n            }\n        }\n\n        // Calc correct width if horizontal scrollbar is wanted return new Vector2(1, height)\n        public Vector2 GetTotalSize()\n        {\n            if (m_RowRects.Count == 0)\n                return new Vector2(0, 0);\n\n            return new Vector2(m_MaxWidthOfRows, m_RowRects[m_RowRects.Count - 1].yMax);\n        }\n\n        public int GetNumRowsOnPageUpDown(TreeViewItem fromItem, bool pageUp, float heightOfTreeView)\n        {\n            Debug.LogError(\"GetNumRowsOnPageUpDown: Not impemented\");\n            return (int)Mathf.Floor(heightOfTreeView / 30); // return something\n        }\n\n        // Should return the row number of the first and last row thats fits in the pixel rect defined by top and height\n        public void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible)\n        {\n            float topPixel = m_TreeView.state.scrollPos.y;\n            float heightInPixels = m_TreeView.GetTotalRect().height;\n\n            var rowCount = m_TreeView.data.rowCount;\n            if (rowCount != m_RowRects.Count)\n            {\n                Debug.LogError(\"Mismatch in state: rows vs cached rects. Did you remember to hook up: dataSource.onVisibleRowsChanged += gui.CalculateRowRects ?\");\n                CalculateRowRects();\n            }\n\n            int firstVisible = -1;\n            int lastVisible = -1;\n\n            for (int i = 0; i < m_RowRects.Count; ++i)\n            {\n                bool visible = ((m_RowRects[i].y > topPixel && (m_RowRects[i].y < topPixel + heightInPixels))) ||\n                    ((m_RowRects[i].yMax > topPixel && (m_RowRects[i].yMax < topPixel + heightInPixels)));\n\n                if (visible)\n                {\n                    if (firstVisible == -1)\n                        firstVisible = i;\n                    lastVisible = i;\n                }\n            }\n\n            if (firstVisible != -1 && lastVisible != -1)\n            {\n                firstRowVisible = firstVisible;\n                lastRowVisible = lastVisible;\n            }\n            else\n            {\n                firstRowVisible = 0;\n                lastRowVisible = rowCount - 1;\n            }\n        }\n\n        public virtual void BeginRowGUI()\n        {\n        }\n\n        public virtual void EndRowGUI()\n        {\n        }\n\n        public virtual void BeginPingItem(TreeViewItem item, float topPixelOfRow, float availableWidth)\n        {\n            throw new NotImplementedException();\n        }\n\n        public virtual void EndPingItem()\n        {\n            throw new NotImplementedException();\n        }\n\n        public virtual bool BeginRename(TreeViewItem item, float delay)\n        {\n            throw new NotImplementedException();\n        }\n\n        public virtual void EndRename()\n        {\n            throw new NotImplementedException();\n        }\n\n        public virtual float halfDropBetweenHeight\n        {\n            get { return 8f; }\n        }\n        public virtual float topRowMargin { get; private set; }\n        public virtual float bottomRowMargin { get; private set; }\n\n        protected float m_BaseIndent = 2f;\n        protected float m_IndentWidth = 14f;\n        protected float m_FoldoutWidth = 12f;\n        protected float indentWidth { get { return m_IndentWidth; } }\n\n        virtual public float GetFoldoutIndent(TreeViewItem item)\n        {\n            // Ignore depth when showing search results\n            if (m_TreeView.isSearching)\n                return m_BaseIndent;\n\n            return m_BaseIndent + item.depth * indentWidth;\n        }\n\n        virtual public float GetContentIndent(TreeViewItem item)\n        {\n            return GetFoldoutIndent(item) + m_FoldoutWidth;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewItem.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public class TreeViewItem<TIdentifier> : System.IComparable<TreeViewItem<TIdentifier>>\n    {\n        TIdentifier m_ID; // The id should be unique for all items in TreeView because it is used for searching, selection etc.\n        TreeViewItem<TIdentifier> m_Parent;\n        List<TreeViewItem<TIdentifier>> m_Children = null;\n        int m_Depth;\n        string m_DisplayName;\n        Texture2D m_Icon;\n\n        public TreeViewItem() { }\n\n        public TreeViewItem(TIdentifier id)\n        {\n            m_ID = id;\n        }\n\n        public TreeViewItem(TIdentifier id, int depth)\n        {\n            m_ID = id;\n            m_Depth = depth;\n        }\n\n        public TreeViewItem(TIdentifier id, int depth, string displayName)\n        {\n            m_Depth = depth;\n            m_ID = id;\n            m_DisplayName = displayName;\n        }\n\n        internal TreeViewItem(TIdentifier id, int depth, TreeViewItem<TIdentifier> parent, string displayName)\n        {\n            m_Depth = depth;\n            m_Parent = parent;\n            m_ID = id;\n            m_DisplayName = displayName;\n        }\n\n        public virtual TIdentifier id { get { return m_ID; } set { m_ID = value; } }\n        public virtual string displayName { get { return m_DisplayName; } set { m_DisplayName = value; } }\n        public virtual int depth { get { return m_Depth; } set { m_Depth = value; } }\n        public virtual bool hasChildren { get { return m_Children != null && m_Children.Count > 0; } }\n\n        internal virtual List<TreeViewItem<TIdentifier>> childrenInternal { get { return m_Children; } set { m_Children = value; } }\n\n        public virtual List<TreeViewItem<TIdentifier>> children { get { return childrenInternal; } set { childrenInternal = value; } }\n\n        internal virtual TreeViewItem<TIdentifier> ParentInternal { get { return m_Parent; } set { m_Parent = value; } }\n\n        public virtual TreeViewItem<TIdentifier> parent { get => ParentInternal; set { ParentInternal = value; } }\n\n        public virtual Texture2D icon { get { return m_Icon; } set { m_Icon = value; } }\n\n        public void AddChild(TreeViewItem<TIdentifier> child)\n        {\n            if (m_Children == null)\n                m_Children = new List<TreeViewItem<TIdentifier>>();\n\n            m_Children.Add(child);\n\n            if (child != null)\n                child.parent = this;\n        }\n\n        internal virtual int CompareToInternal(TreeViewItem<TIdentifier> other)\n        {\n            return displayName.CompareTo(other.displayName);\n        }\n\n        public virtual int CompareTo(TreeViewItem<TIdentifier> other)\n        {\n            return CompareToInternal(other);\n        }\n\n        public override string ToString()\n        {\n            return string.Format(\"Item: '{0}' ({1}), has {2} children, depth {3}, parent id {4}\", displayName, id, hasChildren ? children.Count : 0, depth, (parent != null) ? parent.id : -1);\n        }\n    }\n\n    internal static class TreeViewItemExtension\n    {\n        internal static bool Exists<TIdentifier>(this TreeViewItem<TIdentifier> parentItem, Func<TreeViewItem<TIdentifier>, bool> condition)\n        {\n            foreach (TreeViewItem<TIdentifier> tvitem in parentItem.hasChildren ? parentItem.children : new List<TreeViewItem<TIdentifier>>())\n            {\n                if (condition(tvitem))\n                    return true;\n\n                if (tvitem.Exists(condition))\n                    return true;\n            }\n            return false;\n        }\n    }\n\n    class TreeViewItemAlphaNumericSort<TIdentifier> : IComparer<TreeViewItem<TIdentifier>>\n    {\n        public int Compare(TreeViewItem<TIdentifier> lhs, TreeViewItem<TIdentifier> rhs)\n        {\n            if (lhs == rhs) return 0;\n            if (lhs == null) return -1;\n            if (rhs == null) return 1;\n\n            return EditorUtility.NaturalCompare(lhs.displayName, rhs.displayName);\n        }\n    }\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTest.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEngine.Profiling;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing ITreeViewGUI = UnityEditor.IMGUI.Controls.ITreeViewGUI<int>;\nusing ITreeViewDragging = UnityEditor.IMGUI.Controls.ITreeViewDragging<int>;\nusing ITreeViewDataSource = UnityEditor.IMGUI.Controls.ITreeViewDataSource<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor.TreeViewExamples\n{\n    internal class TreeViewStateWithColumns : TreeViewState\n    {\n        [SerializeField]\n        public float[] columnWidths;\n    }\n\n    internal class TreeViewTest\n    {\n        private BackendData m_BackendData;\n        private TreeViewController m_TreeView;\n        private EditorWindow m_EditorWindow;\n        private bool m_Lazy;\n        private TreeViewColumnHeader m_ColumnHeader;\n        private GUIStyle m_HeaderStyle;\n        private GUIStyle m_HeaderStyleRightAligned;\n\n        public int GetNumItemsInData()\n        {\n            return m_BackendData.IDCounter;\n        }\n\n        public int GetNumItemsInTree()\n        {\n            var data = m_TreeView.data as LazyTestDataSource;\n            if (data != null)\n                return data.itemCounter;\n\n            var data2 = m_TreeView.data as TestDataSource;\n            if (data2 != null)\n                return data2.itemCounter;\n\n            return -1;\n        }\n\n        public TreeViewTest(EditorWindow editorWindow, bool lazy)\n        {\n            m_EditorWindow = editorWindow;\n            m_Lazy = lazy;\n        }\n\n        public void Init(Rect rect, BackendData backendData)\n        {\n            if (m_TreeView != null)\n                return;\n\n            m_BackendData = backendData;\n\n            var state = new TreeViewStateWithColumns();\n            state.columnWidths = new float[] {250f, 90f, 93f, 98f, 74f, 78f};\n\n            m_TreeView = new TreeViewController(m_EditorWindow, state);\n            ITreeViewGUI gui = new TestGUI(m_TreeView);\n            ITreeViewDragging dragging = new TestDragging(m_TreeView, m_BackendData);\n            ITreeViewDataSource dataSource;\n            if (m_Lazy) dataSource = new LazyTestDataSource(m_TreeView, m_BackendData);\n            else        dataSource = new TestDataSource(m_TreeView, m_BackendData);\n            m_TreeView.Init(rect, dataSource, gui, dragging);\n\n\n            m_ColumnHeader = new TreeViewColumnHeader();\n            m_ColumnHeader.columnWidths = state.columnWidths;\n            m_ColumnHeader.minColumnWidth = 30f;\n            m_ColumnHeader.columnRenderer += OnColumnRenderer;\n        }\n\n        void OnColumnRenderer(int column, Rect rect)\n        {\n            if (m_HeaderStyle == null)\n            {\n                m_HeaderStyle = new GUIStyle(EditorStyles.toolbarButton);\n                m_HeaderStyle.padding.left = 4;\n                m_HeaderStyle.alignment = TextAnchor.MiddleLeft;\n\n                m_HeaderStyleRightAligned = new GUIStyle(EditorStyles.toolbarButton);\n                m_HeaderStyleRightAligned.padding.right = 4;\n                m_HeaderStyleRightAligned.alignment = TextAnchor.MiddleRight;\n            }\n\n            string[] headers = new[] { \"Name\", \"Date Modified\", \"Size\", \"Kind\", \"Author\", \"Platform\", \"Faster\", \"Slower\" };\n            GUI.Label(rect, headers[column], (column % 2 == 0) ? m_HeaderStyle : m_HeaderStyleRightAligned);\n        }\n\n        public void OnGUI(Rect rect)\n        {\n            int keyboardControl = GUIUtility.GetControlID(FocusType.Keyboard, rect);\n\n            const float kHeaderHeight = 17f;\n            const float kBottomHeight = 20f;\n            Rect headerRect = new Rect(rect.x, rect.y, rect.width, kHeaderHeight);\n            Rect bottomRect = new Rect(rect.x, rect.yMax - kBottomHeight, rect.width, kBottomHeight);\n\n            // Header\n            GUI.Label(headerRect, \"\", EditorStyles.toolbar);\n            m_ColumnHeader.OnGUI(headerRect);\n\n            Profiler.BeginSample(\"TREEVIEW\");\n\n            // TreeView\n            rect.y += headerRect.height;\n            rect.height -= headerRect.height + bottomRect.height;\n            m_TreeView.OnEvent();\n            m_TreeView.OnGUI(rect, keyboardControl);\n\n            Profiler.EndSample();\n\n            // BottomBar\n            GUILayout.BeginArea(bottomRect, GetHeader(), EditorStyles.helpBox);\n            GUILayout.BeginHorizontal();\n            GUILayout.FlexibleSpace();\n            m_BackendData.m_RecursiveFindParentsBelow = GUILayout.Toggle(m_BackendData.m_RecursiveFindParentsBelow, GUIContent.Temp(\"Recursive\"));\n            if (GUILayout.Button(\"Ping\", EditorStyles.miniButton))\n            {\n                int id = GetNumItemsInData() / 2;\n                m_TreeView.Frame(id, true, true);\n                m_TreeView.SetSelection(new[] {id}, false);\n            }\n            if (GUILayout.Button(\"Frame\", EditorStyles.miniButton))\n            {\n                int id = GetNumItemsInData() / 10;\n                m_TreeView.Frame(id, true, false);\n                m_TreeView.SetSelection(new[] { id }, false);\n            }\n            GUILayout.EndHorizontal();\n            GUILayout.EndArea();\n        }\n\n        private string GetHeader()\n        {\n            return (m_Lazy ? \"LAZY: \" : \"FULL: \") + \"GUI items: \" + GetNumItemsInTree() + \"  (data items: \" + GetNumItemsInData() + \")\";\n        }\n    }\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestBackEnd.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\n\n\nnamespace UnityEditor.TreeViewExamples\n{\n    internal class BackendData\n    {\n        public class Foo\n        {\n            public Foo(string name, int depth, int id)\n            {\n                this.name = name;\n                this.depth = depth;  this.id = id;\n            }\n\n            public string name { get; set; }\n            public int id { get; set; }\n            public int depth { get; set; }\n            public Foo parent { get; set; }\n            public List<Foo> children { get; set; }\n            public bool hasChildren { get { return children != null && children.Count > 0; } }\n        }\n\n        public Foo root { get { return m_Root; } }\n\n        private Foo m_Root;\n        public bool m_RecursiveFindParentsBelow = true;\n        public int IDCounter { get; private set; }\n        private int m_MaxItems = 10000;\n        private const int k_MinChildren = 3;\n        private const int k_MaxChildren = 15;\n        private const float k_ProbOfLastDescendent = 0.5f;\n        private const int k_MaxDepth = 12;\n\n        public void GenerateData(int maxNumItems)\n        {\n            m_MaxItems = maxNumItems;\n            IDCounter = 1;\n            m_Root = new Foo(\"Root\", 0, 0);\n            for (int i = 0; i < 10; ++i)\n                AddChildrenRecursive(m_Root, UnityEngine.Random.Range(k_MinChildren, k_MaxChildren), true);\n        }\n\n        public Foo Find(int id)\n        {\n            return FindRecursive(id, m_Root);\n        }\n\n        public Foo FindRecursive(int id, Foo parent)\n        {\n            if (!parent.hasChildren)\n                return null;\n\n            foreach (var child in parent.children)\n            {\n                if (child.id == id)\n                    return child;\n\n                var result = FindRecursive(id, child);\n                if (result != null)\n                    return result;\n            }\n\n            return null;\n        }\n\n        public void GetParentsBelow(int id, HashSet<int> parentsBelow)\n        {\n            Foo searchFromThis = FindItemRecursive(root, id);\n            if (searchFromThis == null)\n                return;\n\n            if (m_RecursiveFindParentsBelow)\n            {\n                GetParentsBelowRecursive(searchFromThis, parentsBelow);\n                return;\n            }\n\n            GetParentsBelowStackBased(searchFromThis, parentsBelow);\n        }\n\n        private void GetParentsBelowStackBased(Foo searchFromThis, HashSet<int> parentsBelow)\n        {\n            Stack<Foo> stack = new Stack<Foo>();\n            stack.Push(searchFromThis);\n\n            while (stack.Count > 0)\n            {\n                Foo current = stack.Pop();\n                if (current.hasChildren)\n                {\n                    parentsBelow.Add(current.id);\n                    foreach (var foo in current.children)\n                    {\n                        stack.Push(foo);\n                    }\n                }\n            }\n        }\n\n        private static void GetParentsBelowRecursive(Foo item, HashSet<int> parentIDs)\n        {\n            if (!item.hasChildren)\n                return;\n            parentIDs.Add(item.id);\n            foreach (var child in item.children)\n                GetParentsBelowRecursive(child, parentIDs);\n        }\n\n        public void ReparentSelection(Foo parentItem, int insertionIndex, List<Foo> draggedItems)\n        {\n            // Invalid reparenting input\n            if (parentItem == null)\n                return;\n\n            // We are moving items so we adjust the insertion index to accomodate that any items above the insertion index is removed before inserting\n            if (insertionIndex > 0)\n                insertionIndex -= parentItem.children.GetRange(0, insertionIndex).Count(draggedItems.Contains);\n\n            // Remove draggedItems from their parents\n            foreach (var draggedItem in draggedItems)\n            {\n                draggedItem.parent.children.Remove(draggedItem);    // remove from old parent\n                draggedItem.parent = parentItem;                    // set new parent\n            }\n\n            if (!parentItem.hasChildren)\n                parentItem.children = new List<Foo>();\n            var newChildren = new List<Foo>(parentItem.children);\n\n            // If insertionIndex is -1 then item was dropped upon the parent: client have to decide where to place the dragged items. We add as the first.\n            if (insertionIndex == -1)\n                insertionIndex = 0;\n\n            // Insert dragged items under new parent\n            newChildren.InsertRange(insertionIndex, draggedItems);\n            parentItem.children = newChildren;\n        }\n\n        void AddChildrenRecursive(Foo foo, int numChildren, bool force)\n        {\n            if (IDCounter > m_MaxItems)\n                return;\n\n            if (foo.depth >= k_MaxDepth)\n                return;\n\n            if (!force && UnityEngine.Random.value < k_ProbOfLastDescendent)\n                return;\n\n            if (foo.children == null)\n                foo.children = new List<Foo>(numChildren);\n            for (int i = 0; i < numChildren; ++i)\n            {\n                Foo child = new Foo(\"Tud\" + IDCounter, foo.depth + 1, ++IDCounter);\n                child.parent = foo;\n                foo.children.Add(child);\n            }\n\n            if (IDCounter > m_MaxItems)\n                return;\n\n            foreach (var child in foo.children)\n            {\n                AddChildrenRecursive(child, UnityEngine.Random.Range(k_MinChildren, k_MaxChildren), false);\n            }\n        }\n\n        public static Foo FindItemRecursive(Foo item, int id)\n        {\n            if (item == null)\n                return null;\n\n            if (item.id == id)\n                return item;\n\n            if (item.children == null)\n                return null;\n\n            foreach (Foo child in item.children)\n            {\n                Foo result = FindItemRecursive(child, id);\n                if (result != null)\n                    return result;\n            }\n            return null;\n        }\n    }\n\n    internal class TreeViewColumnHeader\n    {\n        public float[] columnWidths { get; set; }\n        public float minColumnWidth { get; set; }\n        public float dragWidth { get; set; }\n        public Action<int, Rect> columnRenderer { get; set; }\n\n        public TreeViewColumnHeader()\n        {\n            minColumnWidth = 10;\n            dragWidth = 6f;\n        }\n\n        public void OnGUI(Rect rect)\n        {\n            const float dragAreaWidth = 3f;\n            float columnPos = rect.x;\n            for (int i = 0; i < columnWidths.Length; ++i)\n            {\n                Rect columnRect = new Rect(columnPos, rect.y, columnWidths[i], rect.height);\n                columnPos += columnWidths[i];\n                Rect dragRect = new Rect(columnPos - dragWidth / 2, rect.y, dragAreaWidth, rect.height);\n                float deltaX = EditorGUI.MouseDeltaReader(dragRect, true).x;\n                if (deltaX != 0f)\n                {\n                    columnWidths[i] += deltaX;\n                    columnWidths[i] = Mathf.Max(columnWidths[i], minColumnWidth);\n                }\n\n                if (columnRenderer != null)\n                    columnRenderer(i, columnRect);\n\n                if (Event.current.type == EventType.Repaint)\n                    EditorGUIUtility.AddCursorRect(dragRect, MouseCursor.SplitResizeLeftRight);\n            }\n        }\n    }\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor.IMGUI.Controls;\n\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewDataSource = UnityEditor.IMGUI.Controls.TreeViewDataSource<int>;\n\nnamespace UnityEditor.TreeViewExamples\n{\n    class TestDataSource : TreeViewDataSource\n    {\n        private BackendData m_Backend;\n        public int itemCounter { get; private set; }\n\n        public TestDataSource(TreeViewController treeView, BackendData data) : base(treeView)\n        {\n            m_Backend = data;\n            FetchData();\n        }\n\n        public override void FetchData()\n        {\n            itemCounter = 1;\n            m_RootItem = new FooTreeViewItem(m_Backend.root.id, 0, null, m_Backend.root.name, m_Backend.root);\n            AddChildrenRecursive(m_Backend.root, m_RootItem);\n            m_NeedRefreshRows = true;\n        }\n\n        void AddChildrenRecursive(BackendData.Foo source, TreeViewItem dest)\n        {\n            if (source.hasChildren)\n            {\n                dest.children = new List<TreeViewItem>(source.children.Count);\n                for (int i = 0; i < source.children.Count; ++i)\n                {\n                    BackendData.Foo s = source.children[i];\n                    dest.children.Add(new FooTreeViewItem(s.id, dest.depth + 1, dest, s.name, s));\n                    itemCounter++;\n                    AddChildrenRecursive(s, dest.children[i]);\n                }\n            }\n        }\n\n        public override bool CanBeParent(TreeViewItem item)\n        {\n            return true;\n        }\n    }\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestDragging.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\n\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewUtility = UnityEditor.IMGUI.Controls.TreeViewUtility<int>;\nusing TreeViewDragging = UnityEditor.IMGUI.Controls.TreeViewDragging<int>;\n\nnamespace UnityEditor.TreeViewExamples\n{\n    internal class TestDragging : TreeViewDragging\n    {\n        private const string k_GenericDragID = \"FooDragging\";\n        private BackendData m_BackendData;\n\n\n        class FooDragData\n        {\n            public FooDragData(List<TreeViewItem> draggedItems)\n            {\n                m_DraggedItems = draggedItems;\n            }\n\n            public List<TreeViewItem> m_DraggedItems;\n        }\n\n        public TestDragging(TreeViewController treeView, BackendData data)\n            : base(treeView)\n        {\n            m_BackendData = data;\n        }\n\n        public override void StartDrag(TreeViewItem draggedItem, List<int> draggedItemIDs)\n        {\n            DragAndDrop.PrepareStartDrag();\n            DragAndDrop.SetGenericData(k_GenericDragID, new FooDragData(GetItemsFromIDs(draggedItemIDs)));\n            string title = draggedItemIDs.Count + \" Foo\" + (draggedItemIDs.Count > 1 ? \"s\" : \"\"); // title is only shown on OSX (at the cursor)\n            DragAndDrop.StartDrag(title);\n        }\n\n        public override DragAndDropVisualMode DoDrag(TreeViewItem parentItem, TreeViewItem targetItem, bool perform, DropPosition dropPos)\n        {\n            var dragData = DragAndDrop.GetGenericData(k_GenericDragID) as FooDragData;\n            var fooParent = parentItem as FooTreeViewItem;\n            if (fooParent != null && dragData != null)\n            {\n                bool validDrag = ValidDrag(parentItem, dragData.m_DraggedItems);\n                if (perform && validDrag)\n                {\n                    // Do reparenting here\n                    List<BackendData.Foo> draggedFoos = (from x in dragData.m_DraggedItems where x is FooTreeViewItem select((FooTreeViewItem)x).foo).ToList();\n                    var selectedIDs = (from x in dragData.m_DraggedItems where x is FooTreeViewItem select((FooTreeViewItem)x).id).ToArray();\n                    int insertionIndex = GetInsertionIndex(parentItem, targetItem, dropPos);\n                    m_BackendData.ReparentSelection(fooParent.foo, insertionIndex, draggedFoos);\n                    m_TreeView.ReloadData();\n                    m_TreeView.SetSelection(selectedIDs, true);\n                }\n                return validDrag ? DragAndDropVisualMode.Move : DragAndDropVisualMode.None;\n            }\n            return DragAndDropVisualMode.None;\n        }\n\n        bool ValidDrag(TreeViewItem parent, List<TreeViewItem> draggedItems)\n        {\n            TreeViewItem currentParent = parent;\n            while (currentParent != null)\n            {\n                if (draggedItems.Contains(currentParent))\n                    return false;\n                currentParent = currentParent.parent;\n            }\n            return true;\n        }\n\n        private List<TreeViewItem> GetItemsFromIDs(IEnumerable<int> draggedItemIDs)\n        {\n            // Note we only drag visible items here...\n            return TreeViewUtility.FindItemsInList(draggedItemIDs, m_TreeView.data.GetRows());\n        }\n    }\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.Experimental;\nusing UnityEngine;\n\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewGUI = UnityEditor.IMGUI.Controls.TreeViewGUI<int>;\n\n\nnamespace UnityEditor.TreeViewExamples\n{\n    internal class FooTreeViewItem : TreeViewItem\n    {\n        public BackendData.Foo foo { get; private set; }\n        public FooTreeViewItem(int id, int depth, TreeViewItem parent, string displayName, BackendData.Foo foo)\n            : base(id, depth, parent, displayName)\n        {\n            this.foo = foo;\n        }\n    }\n\n\n    class TestGUI : TreeViewGUI\n    {\n        private Texture2D m_FolderIcon = EditorGUIUtility.FindTexture(EditorResources.folderIconName);\n        private Texture2D m_Icon = EditorGUIUtility.FindTexture(\"boo Script Icon\");\n        private GUIStyle m_LabelStyleRightAlign;\n        private bool m_StyleInitialized;\n\n        public TestGUI(TreeViewController treeView)\n            : base(treeView)\n        {\n        }\n\n        protected override Texture GetIconForItem(TreeViewItem item)\n        {\n            return (item.hasChildren) ? m_FolderIcon : m_Icon;\n        }\n\n        protected override void RenameEnded()\n        {\n        }\n\n        protected override void SyncFakeItem()\n        {\n        }\n\n        float[] columnWidths { get { return ((TreeViewStateWithColumns)m_TreeView.state).columnWidths; } }\n\n        protected override void OnContentGUI(Rect rect, int row, TreeViewItem item, string label, bool selected, bool focused, bool useBoldFont, bool isPinging)\n        {\n            if (Event.current.rawType != EventType.Repaint)\n                return;\n\n            if (!m_StyleInitialized)\n            {\n                lineStyle = new GUIStyle(Styles.lineStyle);\n                lineStyle.padding.left = lineStyle.padding.right = 6;\n\n                m_LabelStyleRightAlign = new GUIStyle(Styles.lineStyle);\n                m_LabelStyleRightAlign.padding.right = m_LabelStyleRightAlign.padding.left = 6;\n                m_LabelStyleRightAlign.alignment = TextAnchor.MiddleRight;\n\n                m_StyleInitialized = true;\n            }\n\n            if (selected)\n                selectionStyle.Draw(rect, false, false, true, focused);\n\n            // If pinging just render main label and icon (not columns)\n            if (isPinging || columnWidths == null || columnWidths.Length == 0)\n            {\n                base.OnContentGUI(rect, row, item, label, selected, focused, useBoldFont, isPinging);\n                return;\n            }\n\n            Rect columnRect = rect;\n            for (int i = 0; i < columnWidths.Length; ++i)\n            {\n                columnRect.width = columnWidths[i];\n                if (i == 0)\n                    base.OnContentGUI(columnRect, row, item, label, selected, focused, useBoldFont, isPinging);\n                else\n                    GUI.Label(columnRect, \"Zksdf SDFS DFASDF \", (i % 2 == 0) ? lineStyle : m_LabelStyleRightAlign);\n                columnRect.x += columnRect.width;\n            }\n        }\n    }\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestGUICustom.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.ComponentModel;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\n\n\nnamespace UnityEditor.TreeViewExamples\n{\n    class TestGUICustomItemHeights : TreeViewGUIWithCustomItemsHeights\n    {\n        internal class Styles\n        {\n            public static GUIStyle foldout = \"IN Foldout\";\n        }\n\n        private float m_Column1Width = 300;\n        protected Rect m_DraggingInsertionMarkerRect;\n\n        public TestGUICustomItemHeights(TreeViewController treeView)\n            : base(treeView)\n        {\n            m_FoldoutWidth = Styles.foldout.fixedWidth;\n        }\n\n        protected override Vector2 GetSizeOfRow(TreeViewItem item)\n        {\n            return new Vector2(m_TreeView.GetTotalRect().width, item.hasChildren ? 20 : 36f);\n        }\n\n        public override void BeginRowGUI()\n        {\n            // Reset\n            m_DraggingInsertionMarkerRect.x = -1;\n        }\n\n        public override void EndRowGUI()\n        {\n            base.EndRowGUI();\n\n            // Draw row marker when dragging\n            if (m_DraggingInsertionMarkerRect.x >= 0 && Event.current.type == EventType.Repaint)\n            {\n                Rect insertionRect = m_DraggingInsertionMarkerRect;\n                insertionRect.height = 2f;\n                insertionRect.y -= insertionRect.height / 2;\n                if (!m_TreeView.dragging.drawRowMarkerAbove)\n                    insertionRect.y += m_DraggingInsertionMarkerRect.height;\n\n                EditorGUI.DrawRect(insertionRect, Color.white);\n            }\n        }\n\n        public override void OnRowGUI(Rect rowRect, TreeViewItem item, int row, bool selected, bool focused)\n        {\n            rowRect.height -= 1f;\n            Rect column1Rect = rowRect;\n            Rect column2Rect = rowRect;\n            column1Rect.width = m_Column1Width;\n            column1Rect.xMin += GetFoldoutIndent(item);\n            column2Rect.xMin += m_Column1Width + 1;\n\n            float indent = GetFoldoutIndent(item);\n            Rect tmpRect = rowRect;\n\n            int itemControlID = TreeViewController.GetItemControlID(item);\n\n            bool isDropTarget = false;\n            if (m_TreeView.dragging != null)\n                isDropTarget = m_TreeView.dragging.GetDropTargetControlID() == itemControlID && m_TreeView.data.CanBeParent(item);\n            bool showFoldout = m_TreeView.data.IsExpandable(item);\n\n\n            Color selectedColor = new Color(0.0f, 0.22f, 0.44f);\n            Color normalColor = new Color(0.1f, 0.1f, 0.1f);\n\n            EditorGUI.DrawRect(column1Rect, selected ? selectedColor : normalColor);\n            EditorGUI.DrawRect(column2Rect, selected ? selectedColor : normalColor);\n\n            if (isDropTarget)\n            {\n                EditorGUI.DrawRect(new Rect(rowRect.x, rowRect.y, 3, rowRect.height), Color.yellow);\n            }\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                Rect labelRect = column1Rect;\n                labelRect.xMin += m_FoldoutWidth;\n\n                GUI.Label(labelRect, item.displayName, EditorStyles.largeLabel);\n                if (rowRect.height > 20f)\n                {\n                    labelRect.y += 16f;\n                    GUI.Label(labelRect, \"Ut tincidunt tortor. Donec nonummy, enim in lacinia pulvinar\", EditorStyles.miniLabel);\n                }\n            }\n\n            // Draw foldout (after text content above to ensure drop down icon is rendered above selection highlight)\n            if (showFoldout)\n            {\n                tmpRect.x = indent;\n                tmpRect.width = m_FoldoutWidth;\n                EditorGUI.BeginChangeCheck();\n                bool newExpandedValue = GUI.Toggle(tmpRect, m_TreeView.data.IsExpanded(item), GUIContent.none, Styles.foldout);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_TreeView.UserInputChangedExpandedState(item, row, newExpandedValue);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestLazyDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor.IMGUI.Controls;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing LazyTreeViewDataSource = UnityEditor.IMGUI.Controls.LazyTreeViewDataSource<int>;\n\nnamespace UnityEditor.TreeViewExamples\n{\n    class LazyTestDataSource : LazyTreeViewDataSource\n    {\n        private BackendData m_Backend;\n        public int itemCounter { get; private set; }\n\n        public LazyTestDataSource(TreeViewController treeView, BackendData data)\n            : base(treeView)\n        {\n            m_Backend = data;\n            FetchData();\n        }\n\n        public override void FetchData()\n        {\n            // For LazyTreeViewDataSources we just generate the 'm_VisibleRows' items:\n            itemCounter = 1;\n            m_RootItem = new FooTreeViewItem(m_Backend.root.id, 0, null, m_Backend.root.name, m_Backend.root);\n            AddVisibleChildrenRecursive(m_Backend.root, m_RootItem);\n\n            m_Rows = new List<TreeViewItem>();\n            GetVisibleItemsRecursive(m_RootItem, m_Rows);\n            m_NeedRefreshRows = false;\n        }\n\n        void AddVisibleChildrenRecursive(BackendData.Foo source, TreeViewItem dest)\n        {\n            if (IsExpanded(source.id))\n            {\n                if (source.children != null && source.children.Count > 0)\n                {\n                    dest.children = new List<TreeViewItem>(source.children.Count);\n                    for (int i = 0; i < source.children.Count; ++i)\n                    {\n                        BackendData.Foo s = source.children[i];\n                        dest.children.Add(new FooTreeViewItem(s.id, dest.depth + 1, dest, s.name, s));\n                        ++itemCounter;\n                        AddVisibleChildrenRecursive(s, dest.children[i]);\n                    }\n                }\n            }\n            else\n            {\n                if (source.hasChildren)\n                {\n                    dest.children = CreateChildListForCollapsedParent(); // ensure we show the collapse arrow (because we do not fetch data for collapsed items)\n                }\n            }\n        }\n\n        public override bool CanBeParent(TreeViewItem item)\n        {\n            return item.hasChildren;\n        }\n\n        protected override void GetParentsAbove(int id, HashSet<int> parentsAbove)\n        {\n            BackendData.Foo target = BackendData.FindItemRecursive(m_Backend.root, id);\n\n            while (target != null)\n            {\n                if (target.parent != null)\n                    parentsAbove.Add(target.parent.id);\n                target = target.parent;\n            }\n        }\n\n        protected override void GetParentsBelow(int id, HashSet<int> parentsBelow)\n        {\n            m_Backend.GetParentsBelow(id, parentsBelow);\n        }\n    }\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\n\nnamespace UnityEditor.TreeViewExamples\n{\n    internal class TreeViewTestWindow : EditorWindow, IHasCustomMenu\n    {\n        // Test 1\n        private BackendData m_BackendData;\n        private TreeViewTest m_TreeViewTest;\n        private TreeViewTest m_TreeViewTest2;\n\n        // Test 2\n        private BackendData m_BackendData2;\n        private TreeViewTestWithCustomHeight m_TreeViewWithCustomHeight;\n\n        private TestType m_TestType = TestType.LargeTreesWithStandardGUI;\n\n        enum TestType\n        {\n            LargeTreesWithStandardGUI,\n            TreeWithCustomItemHeight\n        }\n\n        public TreeViewTestWindow()\n        {\n            titleContent = EditorGUIUtility.TrTextContent(\"TreeView Test\");\n        }\n\n        void OnEnable()\n        {\n            position = new Rect(100, 100, 600, 600);\n        }\n\n        void OnGUI()\n        {\n            switch (m_TestType)\n            {\n                case TestType.LargeTreesWithStandardGUI:\n                    TestLargeTreesWithFixedItemHeightAndPingingAndFraming();\n                    break;\n                case TestType.TreeWithCustomItemHeight:\n                    TestTreeWithCustomItemHeights();\n                    break;\n            }\n        }\n\n        void TestTreeWithCustomItemHeights()\n        {\n            Rect rect = new Rect(0, 0, position.width, position.height);\n            if (m_TreeViewWithCustomHeight == null)\n            {\n                m_BackendData2 = new BackendData();\n                m_BackendData2.GenerateData(300);\n\n                m_TreeViewWithCustomHeight = new TreeViewTestWithCustomHeight(this, m_BackendData2, rect);\n            }\n\n            m_TreeViewWithCustomHeight.OnGUI(rect);\n        }\n\n        void TestLargeTreesWithFixedItemHeightAndPingingAndFraming()\n        {\n            Rect leftRect = new Rect(0, 0, position.width / 2, position.height);\n            Rect rightRect = new Rect(position.width / 2, 0, position.width / 2, position.height);\n            if (m_TreeViewTest == null)\n            {\n                m_BackendData = new BackendData();\n                m_BackendData.GenerateData(1000000);\n\n                bool lazy = false;\n                m_TreeViewTest = new TreeViewTest(this, lazy);\n                m_TreeViewTest.Init(leftRect, m_BackendData);\n\n                lazy = true;\n                m_TreeViewTest2 = new TreeViewTest(this, lazy);\n                m_TreeViewTest2.Init(rightRect, m_BackendData);\n            }\n\n            m_TreeViewTest.OnGUI(leftRect);\n            m_TreeViewTest2.OnGUI(rightRect);\n            EditorGUI.DrawRect(new Rect(leftRect.xMax - 1, 0, 2, position.height), new Color(0.4f, 0.4f, 0.4f, 0.8f));\n        }\n\n        public virtual void AddItemsToMenu(GenericMenu menu)\n        {\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Large TreeView\"), m_TestType == TestType.LargeTreesWithStandardGUI, () => m_TestType = TestType.LargeTreesWithStandardGUI);\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Custom Item Height TreeView\"), m_TestType == TestType.TreeWithCustomItemHeight, () => m_TestType = TestType.TreeWithCustomItemHeight);\n        }\n    }\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestWithCustomHeight.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor.TreeViewExamples\n{\n    internal class TreeViewTestWithCustomHeight\n    {\n        private BackendData m_BackendData;\n        private TreeViewController m_TreeView;\n\n        public TreeViewTestWithCustomHeight(EditorWindow editorWindow, BackendData backendData, Rect rect)\n        {\n            m_BackendData = backendData;\n\n            var state = new TreeViewState();\n\n            m_TreeView = new TreeViewController(editorWindow, state);\n            var gui = new TestGUICustomItemHeights(m_TreeView);\n            var dragging = new TestDragging(m_TreeView, m_BackendData);\n            var dataSource = new TestDataSource(m_TreeView, m_BackendData);\n            dataSource.onVisibleRowsChanged += gui.CalculateRowRects;\n            m_TreeView.Init(rect, dataSource, gui, dragging);\n            dataSource.SetExpanded(dataSource.root, true);\n        }\n\n        public void OnGUI(Rect rect)\n        {\n            int keyboardControl = GUIUtility.GetControlID(FocusType.Keyboard, rect);\n            m_TreeView.OnGUI(rect, keyboardControl);\n        }\n    }\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/TreeView/TreeViewUtililty.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    internal static class TreeViewUtility<TIdentifier> where TIdentifier : unmanaged, IEquatable<TIdentifier>\n    {\n        internal static void SetParentAndChildrenForItems(IList<TreeViewItem<TIdentifier>> rows, TreeViewItem<TIdentifier> root)\n        {\n            SetChildParentReferences(rows, root);\n        }\n\n        // For setting depths values based on children state of the items\n        internal static void SetDepthValuesForItems(TreeViewItem<TIdentifier> root)\n        {\n            if (root == null)\n                throw new ArgumentNullException(\"root\", \"The root is null\");\n\n            Stack<TreeViewItem<TIdentifier>> stack = new Stack<TreeViewItem<TIdentifier>>();\n            stack.Push(root);\n            while (stack.Count > 0)\n            {\n                TreeViewItem<TIdentifier> current = stack.Pop();\n                if (current.children != null)\n                {\n                    foreach (var child in current.children)\n                    {\n                        if (child != null)\n                        {\n                            child.depth = current.depth + 1;\n                            stack.Push(child);\n                        }\n                    }\n                }\n            }\n        }\n\n        internal static List<TreeViewItem<TIdentifier>> FindItemsInList(IEnumerable<TIdentifier> itemIDs, IList<TreeViewItem<TIdentifier>> treeViewItems)\n        {\n            return (from x in treeViewItems where itemIDs.Contains(x.id) select x).ToList();\n        }\n\n        internal static TreeViewItem<TIdentifier> FindItemInList<T>(TIdentifier id, IList<T> treeViewItems) where T : TreeViewItem<TIdentifier>\n        {\n            return treeViewItems.FirstOrDefault(t => t.id.Equals(id));\n        }\n\n        // Assumes full tree\n        internal static TreeViewItem<TIdentifier> FindItem(TIdentifier id, TreeViewItem<TIdentifier> searchFromThisItem)\n        {\n            return FindItemRecursive(id, searchFromThisItem);\n        }\n\n        static TreeViewItem<TIdentifier> FindItemRecursive(TIdentifier id, TreeViewItem<TIdentifier> item)\n        {\n            if (item == null)\n                return null;\n\n            if (item.id.Equals(id))\n                return item;\n\n            if (!item.hasChildren)\n                return null;\n\n            foreach (TreeViewItem<TIdentifier> child in item.children)\n            {\n                TreeViewItem<TIdentifier> result = FindItemRecursive(id, child);\n                if (result != null)\n                    return result;\n            }\n            return null;\n        }\n\n        // Assumes full tree\n        internal static void GetParentsAboveItem(TreeViewItem<TIdentifier> fromItem, HashSet<TIdentifier> parentsAbove)\n        {\n            if (fromItem == null)\n                throw new ArgumentNullException(\"fromItem\");\n\n            TreeViewItem<TIdentifier> parent = fromItem.parent;\n            while (parent != null)\n            {\n                parentsAbove.Add(parent.id);\n                parent = parent.parent;\n            }\n        }\n\n        // Assumes full tree\n        internal static void GetParentsBelowItem(TreeViewItem<TIdentifier> fromItem, HashSet<TIdentifier> parentsBelow)\n        {\n            if (fromItem == null)\n                throw new ArgumentNullException(\"fromItem\");\n\n            Stack<TreeViewItem<TIdentifier>> stack = new Stack<TreeViewItem<TIdentifier>>();\n            stack.Push(fromItem);\n\n            while (stack.Count > 0)\n            {\n                TreeViewItem<TIdentifier> current = stack.Pop();\n                if (current.hasChildren)\n                {\n                    parentsBelow.Add(current.id);\n                    if (LazyTreeViewDataSource<TIdentifier>.IsChildListForACollapsedParent(current.children))\n                        throw new InvalidOperationException(\"Invalid tree for finding descendants: Ensure a complete tree when using this utillity method.\");\n\n                    foreach (var foo in current.children)\n                    {\n                        stack.Push(foo);\n                    }\n                }\n            }\n        }\n\n        internal static void DebugPrintToEditorLogRecursive(TreeViewItem<TIdentifier> item)\n        {\n            if (item == null)\n                return;\n            System.Console.WriteLine(new System.String(' ', item.depth * 3) + item.displayName);\n\n            if (!item.hasChildren)\n                return;\n\n            foreach (TreeViewItem<TIdentifier> child in item.children)\n            {\n                DebugPrintToEditorLogRecursive(child);\n            }\n        }\n\n        // Setup child and parent references based on the depth of the tree view items in 'visibleItems'\n        internal static void SetChildParentReferences(IList<TreeViewItem<TIdentifier>> visibleItems, TreeViewItem<TIdentifier> root)\n        {\n            for (int i = 0; i < visibleItems.Count; i++)\n                visibleItems[i].parent = null;\n\n            // Set child and parent references using depth info\n            int rootChildCount = 0;\n            for (int i = 0; i < visibleItems.Count; i++)\n            {\n                SetChildParentReferences(i, visibleItems);\n\n                if (visibleItems[i].parent == null)\n                    rootChildCount++;\n            }\n\n            // Ensure items without a parent gets 'root' as parent\n            if (rootChildCount > 0)\n            {\n                var rootChildren = new List<TreeViewItem<TIdentifier>>(rootChildCount);\n                for (int i = 0; i < visibleItems.Count; i++)\n                {\n                    if (visibleItems[i].parent == null)\n                    {\n                        rootChildren.Add(visibleItems[i]);\n                        visibleItems[i].parent = root;\n                    }\n                }\n                root.children = rootChildren;\n            }\n            else\n                root.children = new List<TreeViewItem<TIdentifier>>();\n        }\n\n        static void SetChildren(TreeViewItem<TIdentifier> item, List<TreeViewItem<TIdentifier>> newChildList)\n        {\n            // Do not touch children if we have a LazyParent and did not find any children == keep lazy children\n            if (LazyTreeViewDataSource<TIdentifier>.IsChildListForACollapsedParent(item.children) && newChildList == null)\n                return;\n\n            item.children = newChildList;\n        }\n\n        static void SetChildParentReferences(int parentIndex, IList<TreeViewItem<TIdentifier>> visibleItems)\n        {\n            TreeViewItem<TIdentifier> parent = visibleItems[parentIndex];\n            bool alreadyHasValidChildren = parent.children != null && parent.children.Count > 0 && parent.children[0] != null;\n            if (alreadyHasValidChildren)\n                return;\n\n            int parentDepth = parent.depth;\n            int childCount = 0;\n\n            // Count children based depth value, we are looking at children until it's the same depth as this object\n            for (int i = parentIndex + 1; i < visibleItems.Count; i++)\n            {\n                if (visibleItems[i].depth == parentDepth + 1)\n                    childCount++;\n                if (visibleItems[i].depth <= parentDepth)\n                    break;\n            }\n\n            // Fill child array\n            List<TreeViewItem<TIdentifier>> childList = null;\n            if (childCount != 0)\n            {\n                childList = new List<TreeViewItem<TIdentifier>>(childCount); // Allocate once\n                childCount = 0;\n                for (int i = parentIndex + 1; i < visibleItems.Count; i++)\n                {\n                    if (visibleItems[i].depth == parentDepth + 1)\n                    {\n                        visibleItems[i].parent = parent;\n                        childList.Add(visibleItems[i]);\n                        childCount++;\n                    }\n\n                    if (visibleItems[i].depth <= parentDepth)\n                        break;\n                }\n            }\n\n            SetChildren(parent, childList);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/VUMeter.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class EditorGUI\n    {\n        internal class VUMeter\n        {\n            static Texture2D s_VerticalVUTexture;\n            static Texture2D s_HorizontalVUTexture;\n            const float VU_SPLIT = 0.9f;\n\n            public struct SmoothingData\n            {\n                public float lastValue;\n                public float peakValue;\n                public float peakValueTime;\n            }\n\n            public static Texture2D verticalVUTexture\n            {\n                get\n                {\n                    if (s_VerticalVUTexture == null)\n                        s_VerticalVUTexture = EditorGUIUtility.LoadIcon(\"VUMeterTextureVertical\");\n                    return s_VerticalVUTexture;\n                }\n            }\n\n            public static Texture2D horizontalVUTexture\n            {\n                get\n                {\n                    if (s_HorizontalVUTexture == null)\n                        s_HorizontalVUTexture = EditorGUIUtility.LoadIcon(\"VUMeterTextureHorizontal\");\n                    return s_HorizontalVUTexture;\n                }\n            }\n\n            public static void HorizontalMeter(Rect position, float value, float peak, Texture2D foregroundTexture, Color peakColor)\n            {\n                if (Event.current.type != EventType.Repaint)\n                    return;\n\n                Color temp = GUI.color;\n\n                // Draw background\n                EditorStyles.progressBarBack.Draw(position, false, false, false, false);\n\n                // Draw foreground\n                GUI.color = new Color(1f, 1f, 1f, GUI.enabled ? 1 : 0.5f);\n                float width = position.width * value - 2;\n                if (width < 2)\n                    width = 2;\n                Rect newRect = new Rect(position.x + 1, position.y + 1, width, position.height - 2);\n                Rect uvRect = new Rect(0, 0, value, 1);\n                GUI.DrawTextureWithTexCoords(newRect, foregroundTexture, uvRect);\n\n                // Draw peak indicator\n                GUI.color = peakColor;\n                float peakpos = position.width * peak - 2;\n                if (peakpos < 2)\n                    peakpos = 2;\n                newRect = new Rect(position.x + peakpos, position.y + 1, 1, position.height - 2);\n                GUI.DrawTexture(newRect, EditorGUIUtility.whiteTexture, ScaleMode.StretchToFill);\n\n                // Reset color\n                GUI.color = temp;\n            }\n\n            public static void VerticalMeter(Rect position, float value, float peak, Texture2D foregroundTexture, Color peakColor)\n            {\n                if (Event.current.type != EventType.Repaint)\n                    return;\n\n                Color temp = GUI.color;\n\n                // Draw background\n                EditorStyles.progressBarBack.Draw(position, false, false, false, false);\n\n                // Draw foreground\n                GUI.color = new Color(1f, 1f, 1f, GUI.enabled ? 1 : 0.5f);\n                float height = (position.height - 2) * value;\n                if (height < 2)\n                    height = 2;\n                Rect newRect = new Rect(position.x + 1, (position.y + position.height - 1) - height, position.width - 2, height);\n                Rect uvRect = new Rect(0, 0, 1, value);\n                GUI.DrawTextureWithTexCoords(newRect, foregroundTexture, uvRect);\n\n                // Draw peak indicator\n                GUI.color = peakColor;\n                float peakpos = (position.height - 2) * peak;\n                if (peakpos < 2)\n                    peakpos = 2;\n                newRect = new Rect(position.x + 1, (position.y + position.height - 1) - peakpos, position.width - 2, 1);\n                GUI.DrawTexture(newRect, EditorGUIUtility.whiteTexture, ScaleMode.StretchToFill);\n\n                // Reset color\n                GUI.color = temp;\n            }\n\n            // Auto smoothing version\n            public static void HorizontalMeter(Rect position, float value, ref SmoothingData data, Texture2D foregroundTexture, Color peakColor)\n            {\n                if (Event.current.type != EventType.Repaint)\n                    return;\n\n                float renderValue, renderPeak;\n                SmoothVUMeterData(ref value, ref data, out renderValue, out renderPeak);\n                HorizontalMeter(position, renderValue, renderPeak, foregroundTexture, peakColor);\n            }\n\n            // Auto smoothing version\n            public static void VerticalMeter(Rect position, float value, ref SmoothingData data, Texture2D foregroundTexture, Color peakColor)\n            {\n                if (Event.current.type != EventType.Repaint)\n                    return;\n\n                float renderValue, renderPeak;\n                SmoothVUMeterData(ref value, ref data, out renderValue, out renderPeak);\n                VerticalMeter(position, renderValue, renderPeak, foregroundTexture, peakColor);\n            }\n\n            static void SmoothVUMeterData(ref float value, ref SmoothingData data, out float renderValue, out float renderPeak)\n            {\n                if (value <= data.lastValue)\n                {\n                    value = Mathf.Lerp(data.lastValue, value, Time.smoothDeltaTime * 7.0f);\n                }\n                else\n                {\n                    value = Mathf.Lerp(value, data.lastValue, Time.smoothDeltaTime * 2.0f);\n                    data.peakValue = value;\n                    data.peakValueTime = Time.realtimeSinceStartup;\n                }\n\n                if (value > 1.0f / VU_SPLIT)\n                    value = 1.0f / VU_SPLIT;\n                if (data.peakValue > 1.0f / VU_SPLIT)\n                    data.peakValue = 1.0f / VU_SPLIT;\n\n                renderValue = value * VU_SPLIT;\n                renderPeak = data.peakValue * VU_SPLIT;\n\n                data.lastValue = value;\n            }\n        } // VUMeter\n    } // UnityGUI\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/GUI/VerticalGrid.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Globalization;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class VerticalGrid\n    {\n        int m_Columns = 1;\n        int m_Rows;\n        float m_Height;\n        float m_HorizontalSpacing;\n\n        public int columns { get  {return m_Columns; } }\n        public int rows { get {return m_Rows; } }\n        public float height { get {return m_Height; }  }\n        public float horizontalSpacing { get {return m_HorizontalSpacing; } }\n\n        // Adjust grid values\n        public float fixedWidth { get; set; }\n        public Vector2 itemSize { get; set; }\n        public float verticalSpacing { get; set; }      // spacing between each row of items\n        public float minHorizontalSpacing { get; set; } // minimum spacing between each column in grid\n        public float topMargin { get; set; }\n        public float bottomMargin { get; set; }\n        public float rightMargin { get; set; }\n        public float leftMargin { get; set; }\n        public float fixedHorizontalSpacing {get; set; }\n        public bool useFixedHorizontalSpacing {get; set; }\n\n        // Call after setting parameters above and before using CalcRect\n        public void InitNumRowsAndColumns(int itemCount, int maxNumRows)\n        {\n            if (useFixedHorizontalSpacing)\n            {\n                // Set columns (with an excess of 1 fixedHorizontalSpacing)\n                m_Columns = CalcColumns();\n\n                // Set horizontal spacing\n                m_HorizontalSpacing = fixedHorizontalSpacing;\n\n                // Set rows\n                m_Rows = Mathf.Min(maxNumRows, CalcRows(itemCount));\n\n                // Set height\n                m_Height = m_Rows * (itemSize.y + verticalSpacing) - verticalSpacing + topMargin + bottomMargin;\n            }\n            else // center columns\n            {\n                // Set columns (with an excess of 1 minHorizontalSpacing)\n                m_Columns = CalcColumns();\n\n                // Set horizontal spacing\n                m_HorizontalSpacing = Mathf.Max(0f, (fixedWidth - (m_Columns * itemSize.x + leftMargin + rightMargin)) / (m_Columns));\n\n                // Set rows\n                m_Rows = Mathf.Min(maxNumRows, CalcRows(itemCount));\n\n                if (m_Rows == 1)\n                    m_HorizontalSpacing = minHorizontalSpacing;\n\n                // Set height\n                m_Height = m_Rows * (itemSize.y + verticalSpacing) - verticalSpacing + topMargin + bottomMargin;\n            }\n        }\n\n        public int CalcColumns()\n        {\n            float horizontalSpacing = useFixedHorizontalSpacing ? fixedHorizontalSpacing : minHorizontalSpacing;\n            int cols = (int)Mathf.Floor((fixedWidth - leftMargin - rightMargin) / (itemSize.x + horizontalSpacing));\n            cols = Mathf.Max(cols, 1);\n            return cols;\n        }\n\n        public int CalcRows(int itemCount)\n        {\n            int t = (int)Mathf.Ceil(itemCount / (float)CalcColumns());\n            if (t < 0)\n                return int.MaxValue;\n            return t;\n        }\n\n        public Rect CalcRect(int itemIdx, float yOffset)\n        {\n            float row = Mathf.Floor(itemIdx / columns);\n            float column = itemIdx - row * columns;\n\n            if (useFixedHorizontalSpacing)\n            {\n                return new Rect(leftMargin + column * (itemSize.x + fixedHorizontalSpacing),\n                    row * (itemSize.y + verticalSpacing) + topMargin + yOffset,\n                    itemSize.x,\n                    itemSize.y);\n            }\n            else\n            {\n                return new Rect(leftMargin + horizontalSpacing * 0.5f + column * (itemSize.x + horizontalSpacing),\n                    row * (itemSize.y + verticalSpacing) + topMargin + yOffset,\n                    itemSize.x,\n                    itemSize.y);\n            }\n        }\n\n        public int GetMaxVisibleItems(float height)\n        {\n            int visibleRows = (int)Mathf.Ceil((height - topMargin - bottomMargin) / (itemSize.y + verticalSpacing));\n            return visibleRows * columns;\n        }\n\n        public bool IsVisibleInScrollView(float scrollViewHeight, float scrollPos, float gridStartY, int maxIndex, out int startIndex, out int endIndex)\n        {\n            startIndex = endIndex = 0;\n\n            // In grid coordinates\n\n            float scrollViewStart = scrollPos;\n            float scrollViewEnd = scrollPos + scrollViewHeight;\n\n            float offsetY = gridStartY + topMargin;\n\n            // Entirely below view\n            if (offsetY > scrollViewEnd)\n                return false;\n\n            // Entirely above view\n            if (offsetY + height < scrollViewStart)\n                return false;\n\n            float itemHeightAndSpacing = itemSize.y + verticalSpacing;\n\n            // startRow can be negative if grid is starting in the middle of the view\n            int startRow = Mathf.FloorToInt((scrollViewStart - offsetY) / itemHeightAndSpacing);\n            startIndex = startRow * columns;\n            startIndex = Mathf.Clamp(startIndex, 0, maxIndex);\n\n            // endRow can be negative if grid is starting in the middle of the view\n            int endRow = Mathf.FloorToInt((scrollViewEnd - offsetY) / itemHeightAndSpacing);\n            endIndex = (endRow + 1) * columns - 1;\n            endIndex = Mathf.Clamp(endIndex, 0, maxIndex);\n\n            return true;\n        }\n\n        public override string ToString()\n        {\n            return string.Format(\"VerticalGrid: rows {0}, columns {1}, fixedWidth {2}, itemSize {3}\", rows, columns, fixedWidth, itemSize);\n        }\n    }\n\n\n    internal class VerticalGridWithSplitter\n    {\n        int m_Columns = 1;\n        int m_Rows;\n        float m_Height;\n        float m_HorizontalSpacing;\n\n        public int columns { get  {return m_Columns; } }\n        public int rows { get {return m_Rows; } }\n        public float height { get {return m_Height; }  }\n        public float horizontalSpacing { get {return m_HorizontalSpacing; } }\n\n        // Adjust grid values\n        public float fixedWidth { get; set; }\n        public Vector2 itemSize { get; set; }\n        public float verticalSpacing { get; set; }      // spacing between each row of items\n        public float minHorizontalSpacing { get; set; } // minimum spacing between each column in grid\n        public float topMargin { get; set; }\n        public float bottomMargin { get; set; }\n        public float rightMargin { get; set; }\n        public float leftMargin { get; set; }\n\n        // Call after setting parameters above and before using CalcRect\n        public void InitNumRowsAndColumns(int itemCount, int maxNumRows)\n        {\n            // Set columns (with an excess of 1 minHorizontalSpacing)\n            m_Columns = (int)Mathf.Floor((fixedWidth - leftMargin - rightMargin) / (itemSize.x + minHorizontalSpacing));\n            m_Columns = Mathf.Max(m_Columns, 1);\n\n            // Set horizontal spacing\n            m_HorizontalSpacing = 0f;\n            if (m_Columns > 1)\n                m_HorizontalSpacing = (fixedWidth - (m_Columns * itemSize.x + leftMargin + rightMargin)) / (m_Columns - 1);\n\n            // Set rows\n            m_Rows = Mathf.Min(maxNumRows, (int)Mathf.Ceil(itemCount / (float)m_Columns));\n\n            // Set height\n            m_Height = m_Rows * (itemSize.y + verticalSpacing) - verticalSpacing + topMargin + bottomMargin;\n        }\n\n        public Rect CalcRect(int itemIdx, float yOffset)\n        {\n            float row = Mathf.Floor(itemIdx / columns);\n            float column = itemIdx - row * columns;\n\n            return new Rect(column * (itemSize.x + horizontalSpacing) + leftMargin,\n                row * (itemSize.y + verticalSpacing) + topMargin + yOffset,\n                itemSize.x,\n                itemSize.y);\n        }\n\n        public int GetMaxVisibleItems(float height)\n        {\n            int visibleRows = (int)Mathf.Ceil((height - topMargin - bottomMargin) / (itemSize.y + verticalSpacing));\n            return visibleRows * columns;\n        }\n\n        int m_SplitAfterRow;\n        float m_CurrentSplitHeight;\n        float m_LastSplitUpdate;\n        float m_TargetSplitHeight;\n\n        public void ResetSplit()\n        {\n            m_SplitAfterRow = -1;\n            m_CurrentSplitHeight = 0f;\n            m_LastSplitUpdate = -1f;\n            m_TargetSplitHeight = 0f;\n        }\n\n        public void OpenSplit(int splitAfterRowIndex, int numItems)\n        {\n            int numRows = (int)Mathf.Ceil(numItems / (float)m_Columns);\n            float splitHeight = numRows * (itemSize.y + verticalSpacing) - verticalSpacing + topMargin + bottomMargin;\n            m_SplitAfterRow = splitAfterRowIndex;\n            m_TargetSplitHeight = splitHeight;\n            m_LastSplitUpdate = Time.realtimeSinceStartup;\n        }\n\n        // Returns Rect of split content starting from index 0\n        public Rect CalcSplitRect(int splitIndex, float yOffset)\n        {\n            Rect rect = new Rect(0, 0, 0, 0);\n\n            return rect;\n        }\n\n        public void CloseSplit()\n        {\n            m_TargetSplitHeight = 0f;\n        }\n\n        // Returns true if animating (client should ensure to repaint in this case)\n        public bool UpdateSplitAnimationOnGUI()\n        {\n            if (m_SplitAfterRow != -1)\n            {\n                float delta =  Time.realtimeSinceStartup - m_LastSplitUpdate;\n                m_CurrentSplitHeight = delta * m_TargetSplitHeight;\n\n                m_LastSplitUpdate = Time.realtimeSinceStartup;\n\n                // Animate\n                if (m_CurrentSplitHeight != m_TargetSplitHeight && Event.current.type == EventType.Repaint)\n                {\n                    m_CurrentSplitHeight = Mathf.MoveTowards(m_CurrentSplitHeight, m_TargetSplitHeight, 0.03f);\n                    if (m_CurrentSplitHeight == 0 && m_TargetSplitHeight == 0)\n                    {\n                        ResetSplit();\n                    }\n                    return true;\n                }\n            }\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUI/WindowLayout.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing JetBrains.Annotations;\nusing UnityEditor.ShortcutManagement;\nusing UnityEditor.VersionControl;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Pool;\nusing UnityEngine.Scripting;\nusing Directory = System.IO.Directory;\nusing UnityObject = UnityEngine.Object;\nusing JSONObject = System.Collections.IDictionary;\n\nnamespace UnityEditor\n{\n    class LayoutException : Exception\n    {\n        public LayoutException()\n        {\n        }\n\n        public LayoutException(string message)\n            : base(message)\n        {\n        }\n    }\n\n    [InitializeOnLoad]\n    internal static class WindowLayout\n    {\n        struct LayoutViewInfo\n        {\n            public LayoutViewInfo(object key, float defaultSize, bool usedByDefault)\n            {\n                this.key = key;\n                used = usedByDefault;\n                this.defaultSize = defaultSize;\n\n                className = string.Empty;\n                type = null;\n                isContainer = false;\n                extendedData = null;\n            }\n\n            public object key;\n            public string className;\n            public Type type;\n            public bool used;\n            public float defaultSize;\n            public bool isContainer;\n            public JSONObject extendedData;\n\n            public float size\n            {\n                get\n                {\n                    if (!used)\n                        return 0;\n                    return defaultSize;\n                }\n            }\n        }\n\n        const string tabsLayoutKey = \"tabs\";\n        const string verticalLayoutKey = \"vertical\";\n        const string horizontalLayoutKey = \"horizontal\";\n\n        const string k_TopViewClassName = \"top_view\";\n        const string k_CenterViewClassName = \"center_view\";\n        const string k_BottomViewClassName = \"bottom_view\";\n\n        // used by tests\n        internal const string kMaximizeRestoreFile = \"CurrentMaximizeLayout.dwlt\";\n        private const string kDefaultLayoutName = \"Default.wlt\";\n        internal static string layoutResourcesPath => Path.Combine(EditorApplication.applicationContentsPath, \"Resources/Layouts\");\n        internal static string layoutsPreferencesPath => FileUtil.CombinePaths(InternalEditorUtility.unityPreferencesFolder, \"Layouts\");\n        internal static string layoutsModePreferencesPath => FileUtil.CombinePaths(layoutsPreferencesPath, ModeService.currentId);\n        internal static string layoutsDefaultModePreferencesPath => FileUtil.CombinePaths(layoutsPreferencesPath, \"default\");\n        internal static string layoutsCurrentModePreferencesPath => FileUtil.CombinePaths(layoutsPreferencesPath, \"current\");\n        internal static string layoutsProjectPath => FileUtil.CombinePaths(\"UserSettings\", \"Layouts\");\n        internal static string ProjectLayoutPath => GetProjectLayoutPerMode(ModeService.currentId);\n        internal static string currentLayoutName => GetLayoutFileName(ModeService.currentId, Application.unityVersionVer);\n\n        [UsedImplicitly, RequiredByNativeCode]\n        public static void LoadDefaultWindowPreferences()\n        {\n            LoadCurrentModeLayout(keepMainWindow: FindMainWindow());\n            ModeService.InitializeCurrentMode();\n        }\n\n        public static void LoadCurrentModeLayout(bool keepMainWindow)\n        {\n            InitializeLayoutPreferencesFolder();\n            var dynamicLayout = ModeService.GetDynamicLayout();\n            if (dynamicLayout == null)\n                LoadLastUsedLayoutForCurrentMode(keepMainWindow);\n            else\n            {\n                var projectLayoutExists = File.Exists(ProjectLayoutPath);\n                if ((projectLayoutExists && Convert.ToBoolean(dynamicLayout[\"restore_saved_layout\"]))\n                    || !LoadModeDynamicLayout(keepMainWindow, dynamicLayout))\n                    LoadLastUsedLayoutForCurrentMode(keepMainWindow);\n            }\n        }\n\n        private static bool LoadModeDynamicLayout(bool keepMainWindow, JSONObject layoutData)\n        {\n            LayoutViewInfo topViewInfo = new LayoutViewInfo(k_TopViewClassName, MainView.kToolbarHeight, true);\n            LayoutViewInfo bottomViewInfo = new LayoutViewInfo(k_BottomViewClassName, MainView.kStatusbarHeight, true);\n            LayoutViewInfo centerViewInfo = new LayoutViewInfo(k_CenterViewClassName, 0, true);\n\n            var availableEditorWindowTypes = TypeCache.GetTypesDerivedFrom<EditorWindow>().ToArray();\n\n            if (!GetLayoutViewInfo(layoutData, availableEditorWindowTypes, ref centerViewInfo))\n                return false;\n\n            GetLayoutViewInfo(layoutData, availableEditorWindowTypes, ref topViewInfo);\n            GetLayoutViewInfo(layoutData, availableEditorWindowTypes, ref bottomViewInfo);\n\n            var mainWindow = FindMainWindow();\n            if (keepMainWindow && mainWindow == null)\n            {\n                Debug.LogWarning($\"No main window to restore layout from while loading dynamic layout for mode {ModeService.currentId}\");\n                return false;\n            }\n\n            var mainViewID = $\"MainView_{ModeService.currentId}\";\n            InitContainerWindow(ref mainWindow, mainViewID, layoutData);\n            GenerateLayout(mainWindow, ShowMode.MainWindow, availableEditorWindowTypes, centerViewInfo, topViewInfo, bottomViewInfo, layoutData);\n            mainWindow.m_DontSaveToLayout = !Convert.ToBoolean(layoutData[\"restore_saved_layout\"]);\n            return true;\n        }\n\n        private static View LoadLayoutView<T>(Type[] availableEditorWindowTypes, LayoutViewInfo viewInfo, float width, float height) where T : View\n        {\n            if (!viewInfo.used)\n                return null;\n\n            View view = null;\n            if (viewInfo.isContainer)\n            {\n                bool useTabs = viewInfo.extendedData.Contains(tabsLayoutKey) && Convert.ToBoolean(viewInfo.extendedData[tabsLayoutKey]);\n                bool useSplitter = viewInfo.extendedData.Contains(verticalLayoutKey) || viewInfo.extendedData.Contains(horizontalLayoutKey);\n                bool isVertical = viewInfo.extendedData.Contains(verticalLayoutKey) && Convert.ToBoolean(viewInfo.extendedData[verticalLayoutKey]);\n\n                if (useTabs && useSplitter)\n                    Debug.LogWarning($\"{ModeService.currentId} defines both tabs and splitter (horizontal or vertical) layouts.\\n You can only define one to true (i.e. tabs = true) in the editor mode file.\");\n\n                if (useSplitter)\n                {\n                    var splitView = ScriptableObject.CreateInstance<SplitView>();\n                    splitView.vertical = isVertical;\n                    view = splitView;\n                }\n                else if (useTabs)\n                {\n                    var dockAreaView = ScriptableObject.CreateInstance<DockArea>();\n                    view = dockAreaView;\n                }\n\n                view.position = new Rect(0, 0, width, height);\n\n                var childrenData = viewInfo.extendedData[\"children\"] as IList;\n                if (childrenData == null)\n                    throw new LayoutException(\"Invalid split view data\");\n\n                int childIndex = 0;\n                foreach (var childData in childrenData)\n                {\n                    var lvi = new LayoutViewInfo(childIndex, useTabs ? 1f : 1f / childrenData.Count, true);\n                    if (!ParseViewData(availableEditorWindowTypes, childData, ref lvi))\n                        continue;\n\n                    var cw = useTabs ? width : (isVertical ? width : width * lvi.size);\n                    var ch = useTabs ? height : (isVertical ? height * lvi.size : height);\n                    if (useTabs && view is DockArea da)\n                    {\n                        da.AddTab((EditorWindow)ScriptableObject.CreateInstance(lvi.type));\n                    }\n                    else\n                    {\n                        view.AddChild(LoadLayoutView<HostView>(availableEditorWindowTypes, lvi, cw, ch));\n                        view.children[childIndex].position = new Rect(0, 0, cw, ch);\n                    }\n\n                    childIndex++;\n                }\n            }\n            else\n            {\n                if (viewInfo.type != null)\n                {\n                    var hostView = ScriptableObject.CreateInstance<HostView>();\n                    hostView.SetActualViewInternal(ScriptableObject.CreateInstance(viewInfo.type) as EditorWindow, true);\n                    view = hostView;\n                }\n                else\n                    view = ScriptableObject.CreateInstance<T>();\n            }\n\n            return view;\n        }\n\n        internal static void InitContainerWindow(ref ContainerWindow window, string windowId, JSONObject layoutData)\n        {\n            if (window == null)\n            {\n\n                window = ScriptableObject.CreateInstance<ContainerWindow>();\n\n                var windowMinSize = new Vector2(120, 80);\n                var windowMaxSize = new Vector2(8192, 8192);\n                if (layoutData.Contains(\"min_width\"))\n                {\n                    windowMinSize.x = Convert.ToSingle(layoutData[\"min_width\"]);\n                }\n                if (layoutData.Contains(\"min_height\"))\n                {\n                    windowMinSize.y = Convert.ToSingle(layoutData[\"min_height\"]);\n                }\n                if (layoutData.Contains(\"max_width\"))\n                {\n                    windowMaxSize.x = Convert.ToSingle(layoutData[\"max_width\"]);\n                }\n                if (layoutData.Contains(\"max_height\"))\n                {\n                    windowMaxSize.y = Convert.ToSingle(layoutData[\"max_height\"]);\n                }\n                window.SetMinMaxSizes(windowMinSize, windowMaxSize);\n            }\n\n            var hasMainViewGeometrySettings = EditorPrefs.HasKey($\"{windowId}h\");\n            window.windowID = windowId;\n            var loadInitialWindowGeometry = Convert.ToBoolean(layoutData[\"restore_layout_dimension\"]);\n            if (loadInitialWindowGeometry && hasMainViewGeometrySettings)\n                window.LoadGeometry(true);\n        }\n\n        internal static ContainerWindow FindMainWindow()\n        {\n            return Resources.FindObjectsOfTypeAll<ContainerWindow>().FirstOrDefault(w => w.showMode == ShowMode.MainWindow);\n        }\n\n        internal static ContainerWindow ShowWindowWithDynamicLayout(string windowId, string layoutDataPath)\n        {\n            try\n            {\n                ContainerWindow.SetFreezeDisplay(true);\n                if (!File.Exists(layoutDataPath))\n                {\n                    Debug.LogError($\"Failed to find layout data file at path {layoutDataPath}\");\n                    return null;\n                }\n\n                var layoutDataJson = File.ReadAllText(layoutDataPath);\n                var layoutData = SJSON.LoadString(layoutDataJson);\n\n                var availableEditorWindowTypes = TypeCache.GetTypesDerivedFrom<EditorWindow>().ToArray();\n\n                LayoutViewInfo topViewInfo = new LayoutViewInfo(k_TopViewClassName, MainView.kToolbarHeight, false);\n                LayoutViewInfo bottomViewInfo = new LayoutViewInfo(k_BottomViewClassName, MainView.kStatusbarHeight, false);\n\n                // Supports both view and center_view.\n                var centerViewKey = \"view\";\n                if (!layoutData.Contains(centerViewKey))\n                {\n                    centerViewKey = \"center_view\";\n                }\n                LayoutViewInfo centerViewInfo = new LayoutViewInfo(centerViewKey, 0, true);\n                if (!GetLayoutViewInfo(layoutData, availableEditorWindowTypes, ref centerViewInfo))\n                {\n                    Debug.LogError(\"Failed to load window layout; no view defined\");\n                    return null;\n                }\n\n                GetLayoutViewInfo(layoutData, availableEditorWindowTypes, ref topViewInfo);\n                GetLayoutViewInfo(layoutData, availableEditorWindowTypes, ref bottomViewInfo);\n\n                var window = Resources.FindObjectsOfTypeAll<ContainerWindow>().FirstOrDefault(w => w.windowID == windowId);\n                InitContainerWindow(ref window, windowId, layoutData);\n                GenerateLayout(window, ShowMode.Utility, availableEditorWindowTypes, centerViewInfo, topViewInfo, bottomViewInfo, layoutData);\n                window.m_DontSaveToLayout = !Convert.ToBoolean(layoutData[\"restore_saved_layout\"]);\n                return window;\n            }\n            finally\n            {\n                ContainerWindow.SetFreezeDisplay(false);\n            }\n        }\n\n        private static void GenerateLayout(ContainerWindow window, ShowMode showMode, Type[] availableEditorWindowTypes,\n            LayoutViewInfo center, LayoutViewInfo top, LayoutViewInfo bottom, JSONObject layoutData)\n        {\n            try\n            {\n                ContainerWindow.SetFreezeDisplay(true);\n                var width = window.position.width;\n                var height = window.position.height;\n\n                // Create center view\n                View centerView = LoadLayoutView<DockArea>(availableEditorWindowTypes, center, width, height);\n                var topView = LoadLayoutView<Toolbar>(availableEditorWindowTypes, top, width, height);\n                var bottomView = LoadLayoutView<AppStatusBar>(availableEditorWindowTypes, bottom, width, height);\n\n                var main = ScriptableObject.CreateInstance<MainView>();\n                main.useTopView = top.used;\n                main.useBottomView = bottom.used;\n                main.topViewHeight = top.size;\n                main.bottomViewHeight = bottom.size;\n\n                // Top View\n                if (topView)\n                {\n                    topView.position = new Rect(0, 0, width, top.size);\n                    main.AddChild(topView);\n                }\n\n                // Center View\n                var centerViewHeight = height - bottom.size - top.size;\n                centerView.position = new Rect(0, top.size, width, centerViewHeight);\n                main.AddChild(centerView);\n\n                // Bottom View\n                if (bottomView)\n                {\n                    bottomView.position = new Rect(0, height - bottom.size, width, bottom.size);\n                    main.AddChild(bottomView);\n                }\n\n                if (window.rootView)\n                    ScriptableObject.DestroyImmediate(window.rootView, true);\n\n                window.rootView = main;\n                window.rootView.position = new Rect(0, 0, width, height);\n                window.Show(showMode, true, true, true);\n                window.DisplayAllViews();\n            }\n            finally\n            {\n                ContainerWindow.SetFreezeDisplay(false);\n            }\n        }\n\n        private static bool GetLayoutViewInfo(JSONObject layoutData, Type[] availableEditorWindowTypes, ref LayoutViewInfo viewInfo)\n        {\n            if (!layoutData.Contains(viewInfo.key))\n                return false;\n\n            var viewData = layoutData[viewInfo.key];\n            return ParseViewData(availableEditorWindowTypes, viewData, ref viewInfo);\n        }\n\n        private static bool ParseViewData(Type[] availableEditorWindowTypes, object viewData, ref LayoutViewInfo viewInfo)\n        {\n            if (viewData is string)\n            {\n                viewInfo.className = Convert.ToString(viewData);\n                viewInfo.used = !string.IsNullOrEmpty(viewInfo.className);\n                if (!viewInfo.used)\n                    return true;\n            }\n            else if (viewData is JSONObject viewExpandedData)\n            {\n                if (viewExpandedData.Contains(\"children\")\n                    || viewExpandedData.Contains(verticalLayoutKey)\n                    || viewExpandedData.Contains(horizontalLayoutKey)\n                    || viewExpandedData.Contains(tabsLayoutKey))\n                {\n                    viewInfo.isContainer = true;\n                    viewInfo.className = string.Empty;\n                }\n                else\n                {\n                    viewInfo.isContainer = false;\n                    viewInfo.className = Convert.ToString(viewExpandedData[\"class_name\"]);\n                }\n\n                if (viewExpandedData.Contains(\"size\"))\n                    viewInfo.defaultSize = Convert.ToSingle(viewExpandedData[\"size\"]);\n                viewInfo.extendedData = viewExpandedData;\n                viewInfo.used = true;\n            }\n            else\n            {\n                viewInfo.className = string.Empty;\n                viewInfo.type = null;\n                viewInfo.used = false;\n                return true;\n            }\n\n            if (string.IsNullOrEmpty(viewInfo.className))\n                return true;\n\n            foreach (var t in availableEditorWindowTypes)\n            {\n                if (t.Name != viewInfo.className)\n                    continue;\n                viewInfo.type = t;\n                break;\n            }\n\n            if (viewInfo.type == null)\n            {\n                Debug.LogWarning($\"Invalid layout view {viewInfo.key} with type {viewInfo.className} for mode {ModeService.currentId}\");\n                return false;\n            }\n\n            return true;\n        }\n\n        // Used by tests\n        internal static string GetLayoutFileName(string mode, int version) => $\"{mode}-{version}.dwlt\";\n\n        static IEnumerable<string> GetCurrentModeLayouts()\n        {\n            var layouts = ModeService.GetModeDataSection(ModeService.currentIndex, ModeDescriptor.LayoutsKey);\n\n            if (layouts is IList<object> modeLayoutPaths)\n            {\n                foreach (var layoutPath in modeLayoutPaths.Cast<string>())\n                {\n                    if (!File.Exists(layoutPath))\n                        continue;\n                    yield return layoutPath;\n                }\n            }\n        }\n\n        // Iterate through potential layouts in descending order of precedence.\n        // 1. Last loaded layout in project for matching Unity version\n        // 2. Last loaded layout in project for any Unity version, in descending alphabetical order\n        // 3. Last loaded layout in global preferences for matching Unity version\n        // 4. Last loaded layout in global preferences for any Unity version, in descending alphabetical order\n        // 5. Any available layouts specified by the EditorMode, if EditorMode supplies layouts\n        // 6. The factory default layout\n        private static void LoadLastUsedLayoutForCurrentMode(bool keepMainWindow)\n        {\n            // steps 1-4\n            foreach (var layout in GetLastLayout())\n                if (LoadWindowLayout_Internal(layout, layout != ProjectLayoutPath, false, keepMainWindow, false))\n                    return;\n\n            // step 5\n            foreach (var layout in GetCurrentModeLayouts())\n                if (LoadWindowLayout_Internal(layout, layout != ProjectLayoutPath, false, keepMainWindow, false))\n                    return;\n\n            // It is not mandatory that modes define a layout. In that case, skip right to the default layout.\n            if (!string.IsNullOrEmpty(ModeService.GetDefaultModeLayout())\n                && LoadWindowLayout_Internal(ModeService.GetDefaultModeLayout(), true, false, keepMainWindow, false))\n                return;\n\n            // If all else fails, load the default layout that ships with the editor. If that fails, prompt the user to\n            // restore the default layouts.\n            if (!LoadWindowLayout_Internal(GetDefaultLayoutPath(), true, false, keepMainWindow, false))\n            {\n                int option = 0;\n\n                if (!Application.isTestRun && Application.isHumanControllingUs)\n                {\n                    option = EditorUtility.DisplayDialogComplex(\"Missing Default Layout\", \"No valid user created or \" +\n                        \"default window layout found. Please revert factory settings to restore the default layouts.\",\n                        \"Quit\", \"Revert Factory Settings\", \"\");\n                }\n                else\n                {\n                    ResetUserLayouts();\n                }\n\n                switch (option)\n                {\n                    case 0:\n                        EditorApplication.Exit(0);\n                        break;\n                    case 1:\n                        ResetFactorySettings();\n                        break;\n                }\n            }\n        }\n\n        [UsedImplicitly, RequiredByNativeCode]\n        public static void SaveDefaultWindowPreferences()\n        {\n            // Do not save layout to default if running tests\n            if (!InternalEditorUtility.isHumanControllingUs)\n                return;\n\n            SaveCurrentLayoutPerMode(ModeService.currentId);\n        }\n\n        internal static void SaveCurrentLayoutPerMode(string modeId)\n        {\n            // Save the layout in two places. Once in the Project/UserSettings directory, then again the global\n            // preferences. The latter is used when opening a new project (or any case where UserSettings/Layouts/ does\n            // not exist).\n            SaveWindowLayout(FileUtil.CombinePaths(Directory.GetCurrentDirectory(), GetProjectLayoutPerMode(modeId)));\n            SaveWindowLayout(Path.Combine(layoutsCurrentModePreferencesPath, GetLayoutFileName(modeId, Application.unityVersionVer)));\n        }\n\n        // Iterate through potential layout files, prioritizing exact match followed by descending unity version.\n        // IMPORTANT: This function is \"dumb\" in that it does not do any kind of sophisticated version comparison. If the\n        // naming scheme for current layouts is changed, or this function is called on to sort user saved layouts, you will\n        // need to add more sophisticated filtering.\n        public static IEnumerable<string> GetLastLayout(string directory, string mode, int version)\n        {\n            var currentModeAndVersionLayout = GetLayoutFileName(mode, version);\n            string layoutSearchPattern = $\"{mode}-*.*wlt\";\n\n            // first try the exact match\n            var preferred = Path.Combine(directory, currentModeAndVersionLayout);\n\n            if(File.Exists(preferred))\n                yield return preferred;\n\n            // if that fails, fall back to layouts for this mode from other unity versions in descending order\n            if (Directory.Exists(directory))\n            {\n                var paths = Directory.GetFiles(directory, layoutSearchPattern)\n                                     .Where(p => string.Compare(p, preferred, StringComparison.OrdinalIgnoreCase) != 0)\n                                     .OrderByDescending(p => p, StringComparer.OrdinalIgnoreCase);\n\n                foreach (var path in paths)\n                    yield return path;\n            }\n        }\n\n        // used by Tests/EditModeAndPlayModeTests/EditorModes\n        internal static IEnumerable<string> GetLastLayout()\n        {\n            var mode = ModeService.currentId;\n            var version = Application.unityVersionVer;\n            foreach (var layout in GetLastLayout(layoutsProjectPath, mode, version))\n                yield return layout;\n            foreach (var layout in GetLastLayout(layoutsCurrentModePreferencesPath, mode, version))\n                yield return layout;\n        }\n\n        internal static string GetCurrentLayoutPath()\n        {\n            var currentLayoutPath = ProjectLayoutPath;\n\n            // Make sure we have a current layout file created\n            if (!File.Exists(ProjectLayoutPath))\n                currentLayoutPath = GetDefaultLayoutPath();\n\n            return currentLayoutPath;\n        }\n\n        internal static string GetDefaultLayoutPath()\n        {\n            return Path.Combine(layoutsModePreferencesPath, kDefaultLayoutName);\n        }\n\n        internal static string GetProjectLayoutPerMode(string modeId)\n        {\n            return FileUtil.CombinePaths(layoutsProjectPath, GetLayoutFileName(modeId, Application.unityVersionVer));\n        }\n\n        private static void InitializeLayoutPreferencesFolder()\n        {\n            string defaultLayoutPath = GetDefaultLayoutPath();\n\n            if (!Directory.Exists(layoutsPreferencesPath))\n                Directory.CreateDirectory(layoutsPreferencesPath);\n\n            if (!Directory.Exists(layoutsModePreferencesPath))\n            {\n                Console.WriteLine($\"[LAYOUT] {layoutsModePreferencesPath} does not exist. Copying base layouts.\");\n                // Make sure we have a valid default mode folder initialized with the proper default layouts.\n                if (layoutsDefaultModePreferencesPath == layoutsModePreferencesPath)\n                {\n                    // Backward compatibility: if the default layout folder doesn't exists but some layouts have been\n                    // saved be sure to copy them to the \"default layout per mode folder\".\n                    FileUtil.CopyFileOrDirectory(layoutResourcesPath, layoutsDefaultModePreferencesPath);\n                    var defaultModeUserLayouts = Directory.GetFiles(layoutsPreferencesPath, \"*.wlt\");\n                    foreach (var layoutPath in defaultModeUserLayouts)\n                    {\n                        var fileName = Path.GetFileName(layoutPath);\n                        var dst = Path.Combine(layoutsDefaultModePreferencesPath, fileName);\n                        if (!File.Exists(dst))\n                            FileUtil.CopyFileIfExists(layoutPath, dst, false);\n                    }\n                }\n                else\n                {\n                    Directory.CreateDirectory(layoutsModePreferencesPath);\n                }\n            }\n\n            // Make sure we have the default layout file in the preferences folder\n            if (!File.Exists(defaultLayoutPath))\n            {\n                var defaultModeLayoutPath = ModeService.GetDefaultModeLayout();\n                if (!File.Exists(defaultModeLayoutPath))\n                {\n                    // No mode default layout, use the editor_resources Default:\n                    defaultModeLayoutPath = Path.Combine(layoutResourcesPath, kDefaultLayoutName);\n                }\n                Console.WriteLine($\"[LAYOUT] Copying {defaultModeLayoutPath} to {defaultLayoutPath}\");\n                // If not copy our default file to the preferences folder\n                FileUtil.CopyFileOrDirectory(defaultModeLayoutPath, defaultLayoutPath);\n            }\n            Debug.Assert(File.Exists(defaultLayoutPath));\n        }\n\n        static WindowLayout()\n        {\n            EditorApplication.CallDelayed(UpdateWindowLayoutMenu);\n        }\n\n        internal static void UpdateWindowLayoutMenu()\n        {\n            if (!ModeService.HasCapability(ModeCapability.LayoutWindowMenu, true))\n                return;\n            ReloadWindowLayoutMenu();\n        }\n\n        internal static void ReloadWindowLayoutMenu()\n        {\n            Menu.RemoveMenuItem(\"Window/Layouts\");\n\n            if (!ModeService.HasCapability(ModeCapability.LayoutWindowMenu, true))\n                return;\n\n            int layoutMenuItemPriority = -20;\n\n            // Get user saved layouts\n            string[] layoutPaths = new string[0];\n            if (Directory.Exists(layoutsModePreferencesPath))\n            {\n                layoutPaths = Directory.GetFiles(layoutsModePreferencesPath).Where(path => path.EndsWith(\".wlt\")).ToArray();\n                foreach (var layoutPath in layoutPaths)\n                {\n                    var name = Path.GetFileNameWithoutExtension(layoutPath);\n                    Menu.AddMenuItem(\"Window/Layouts/\" + name, \"\", false, layoutMenuItemPriority++, () => TryLoadWindowLayout(layoutPath, false, true, true, true), null);\n                }\n\n                layoutMenuItemPriority += 500;\n            }\n\n            // Get all version current layouts\n            AddLegacyLayoutMenuItems(ref layoutMenuItemPriority);\n\n            // Get mode layouts\n            var modeLayoutPaths = ModeService.GetModeDataSection(ModeService.currentIndex, ModeDescriptor.LayoutsKey) as IList<object>;\n            if (modeLayoutPaths != null)\n            {\n                foreach (var layoutPath in modeLayoutPaths.Cast<string>())\n                {\n                    if (!File.Exists(layoutPath))\n                        continue;\n                    var name = Path.GetFileNameWithoutExtension(layoutPath);\n                    Menu.AddMenuItem(\"Window/Layouts/\" + name, \"\", Toolbar.lastLoadedLayoutName == name, layoutMenuItemPriority++, () => TryLoadWindowLayout(layoutPath, false), null);\n                }\n            }\n\n            layoutMenuItemPriority += 500;\n\n            Menu.AddMenuItem(\"Window/Layouts/Save Layout...\", \"\", false, layoutMenuItemPriority++, SaveGUI, null);\n            Menu.AddMenuItem(\"Window/Layouts/Save Layout to File...\", \"\", false, layoutMenuItemPriority++, SaveToFile, null);\n            Menu.AddMenuItem(\"Window/Layouts/Load Layout from File...\", \"\", false, layoutMenuItemPriority++, LoadFromFile, null);\n            Menu.AddMenuItem(\"Window/Layouts/Delete Layout/\", \"\", false, layoutMenuItemPriority++, null, null);\n            foreach (var layoutPath in layoutPaths)\n            {\n                var name = Path.GetFileNameWithoutExtension(layoutPath);\n                Menu.AddMenuItem(\"Window/Layouts/Delete Layout/\" + name, \"\", false, layoutMenuItemPriority++, () => DeleteWindowLayout(layoutPath), null);\n            }\n            Menu.AddMenuItem(\"Window/Layouts/Reset All Layouts\", \"\", false, layoutMenuItemPriority++, () => ResetAllLayouts(false), null);\n        }\n\n        private static void AddLegacyLayoutMenuItems(ref int layoutMenuItemPriority)\n        {\n            const string legacyRootMenu = \"Window/Layouts/Other Versions\";\n            const string legacyCurrentLayoutPath = \"Library/CurrentLayout-default.dwlt\";\n            if (File.Exists(legacyCurrentLayoutPath))\n                Menu.AddMenuItem($\"{legacyRootMenu}/Default (2020)\", \"\", false, layoutMenuItemPriority++, () => TryLoadWindowLayout(legacyCurrentLayoutPath, false, true, false, true), null);\n\n            if (!Directory.Exists(layoutsProjectPath))\n                return;\n\n            var currentMaximizeLayoutPath = FileUtil.CombinePaths(layoutsProjectPath, kMaximizeRestoreFile);\n            using var pooled = HashSetPool<string>.Get(out var forbiddenPaths);\n            forbiddenPaths.Add(GetCurrentLayoutPath());\n            forbiddenPaths.Add(currentMaximizeLayoutPath);\n            foreach (var layoutPath in Directory.GetFiles(layoutsProjectPath, \"*.dwlt\"))\n            {\n                if (forbiddenPaths.Contains(layoutPath))\n                    continue;\n                var name = Path.GetFileNameWithoutExtension(layoutPath);\n                var names = Path.GetFileName(name).Split('-');\n                var menuName = $\"{legacyRootMenu}/{name}\";\n                if (names.Length == 2)\n                {\n                    name = ObjectNames.NicifyVariableName(names[0]);\n                    menuName = $\"{legacyRootMenu}/{name} ({names[1]})\";\n                }\n                Menu.AddMenuItem(menuName, \"\", false, layoutMenuItemPriority++, () => TryLoadWindowLayout(layoutPath, false, true, false, true), null);\n            }\n        }\n\n        internal static EditorWindow FindEditorWindowOfType(Type type)\n        {\n            UnityObject[] obj = Resources.FindObjectsOfTypeAll(type);\n            if (obj.Length > 0)\n                return obj[0] as EditorWindow;\n            return null;\n        }\n\n        internal static void CheckWindowConsistency()\n        {\n            UnityObject[] wins = Resources.FindObjectsOfTypeAll(typeof(EditorWindow));\n\n            foreach (EditorWindow win in wins)\n            {\n                if (win.m_Parent == null)\n                {\n                    Debug.LogErrorFormat(\n                        \"Invalid editor window of type: {0}, title: {1}\",\n                        win.GetType(), win.titleContent.text);\n                }\n            }\n        }\n\n        internal static EditorWindow TryGetLastFocusedWindowInSameDock()\n        {\n            // Get type of window that was docked together with game view and was focused before play mode\n            Type type = null;\n            string windowTypeName = WindowFocusState.instance.m_LastWindowTypeInSameDock;\n            if (windowTypeName != \"\")\n                type = Type.GetType(windowTypeName);\n\n            // Also get the PlayModeView Window\n            var playModeView = PlayModeView.GetMainPlayModeView();\n            if (type != null && playModeView && playModeView != null && playModeView.m_Parent is DockArea)\n            {\n                // Get all windows of that type\n                object[] potentials = Resources.FindObjectsOfTypeAll(type);\n\n                DockArea dock = playModeView.m_Parent as DockArea;\n\n                // Find the one that is actually docked together with the GameView\n                for (int i = 0; i < potentials.Length; i++)\n                {\n                    EditorWindow window = potentials[i] as EditorWindow;\n                    if (window && window.m_Parent == dock)\n                        return window;\n                }\n            }\n\n            return null;\n        }\n\n        internal static void SaveCurrentFocusedWindowInSameDock(EditorWindow windowToBeFocused)\n        {\n            if (windowToBeFocused.m_Parent != null && windowToBeFocused.m_Parent is DockArea)\n            {\n                DockArea dock = windowToBeFocused.m_Parent as DockArea;\n\n                // Get currently focused window/tab in that dock\n                EditorWindow actualView = dock.actualView;\n                if (actualView)\n                    WindowFocusState.instance.m_LastWindowTypeInSameDock = actualView.GetType().ToString();\n            }\n        }\n\n        internal static void FindFirstGameViewAndSetToMaximizeOnPlay()\n        {\n            GameView gameView = (GameView)FindEditorWindowOfType(typeof(GameView));\n            if (gameView)\n                gameView.enterPlayModeBehavior = PlayModeView.EnterPlayModeBehavior.PlayMaximized;\n        }\n\n        internal static void FindFirstGameViewAndSetToPlayFocused()\n        {\n            GameView gameView = (GameView)FindEditorWindowOfType(typeof(GameView));\n            if (gameView)\n                gameView.enterPlayModeBehavior = PlayModeView.EnterPlayModeBehavior.PlayFocused;\n        }\n\n        internal static EditorWindow TryFocusAppropriateWindow(bool enteringPlaymode)\n        {\n            // If PlayModeView behavior is set to 'Do Nothing' ignore focusing windows when entering/exiting PlayMode\n            var playModeView = PlayModeView.GetCorrectPlayModeViewToFocus();\n            bool shouldFocusView = playModeView && playModeView.enterPlayModeBehavior != PlayModeView.EnterPlayModeBehavior.PlayUnfocused;\n\n            if (enteringPlaymode)\n            {\n                if (shouldFocusView)\n                {\n                    SaveCurrentFocusedWindowInSameDock(playModeView);\n                    playModeView.Focus();\n                }\n\n                return playModeView;\n            }\n            else\n            {\n                // If we can retrieve what window type was active when we went into play mode,\n                // go back to focus a window of that type if needed.\n                if (shouldFocusView)\n                {\n                    EditorWindow window = TryGetLastFocusedWindowInSameDock();\n                    if (window)\n                        window.ShowTab();\n                    return window;\n                }\n\n                return EditorWindow.focusedWindow;\n            }\n        }\n\n        internal static EditorWindow GetMaximizedWindow()\n        {\n            UnityObject[] maximized = Resources.FindObjectsOfTypeAll(typeof(MaximizedHostView));\n            if (maximized.Length != 0)\n            {\n                MaximizedHostView maximizedView = maximized[0] as MaximizedHostView;\n                if (maximizedView.actualView)\n                    return maximizedView.actualView;\n            }\n\n            return null;\n        }\n\n        internal static EditorWindow ShowAppropriateViewOnEnterExitPlaymode(bool entering)\n        {\n            // Prevent trying to go into the same state as we're already in, as it will break things\n            if (WindowFocusState.instance.m_CurrentlyInPlayMode == entering)\n                return null;\n\n            WindowFocusState.instance.m_CurrentlyInPlayMode = entering;\n\n            EditorWindow window = null;\n            EditorWindow maximized = GetMaximizedWindow();\n\n            if (entering)\n            {\n                if (!GameView.openWindowOnEnteringPlayMode && !(PlayModeView.GetCorrectPlayModeViewToFocus() is PlayModeView))\n                    return null;\n\n                WindowFocusState.instance.m_WasMaximizedBeforePlay = (maximized != null);\n\n                // If a view is already maximized before entering play mode,\n                // just keep that maximized view, no matter if it's the game view or some other.\n                // Trust that user has a good reason (desire by Ethan etc.)\n                if (maximized != null)\n                    return maximized;\n            }\n            else\n            {\n                // If a view was already maximized before entering play mode,\n                // then it was kept when switching to play mode, and can simply still be kept when exiting\n                if (WindowFocusState.instance.m_WasMaximizedBeforePlay)\n                    return maximized;\n            }\n\n            // Unmaximize if maximized\n            if (maximized)\n                Unmaximize(maximized);\n\n            // When the playmode behaviour is set to Play Unfocused\n            if (entering)\n            {\n                var playmodeView = PlayModeView.GetCorrectPlayModeViewToFocus();\n                if (playmodeView != null && playmodeView.enterPlayModeBehavior == PlayModeView.EnterPlayModeBehavior.PlayUnfocused)\n                {\n                    playmodeView.m_Parent.OnLostFocus();\n                    return playmodeView;\n                }\n            }\n\n            // Try finding and focusing appropriate window/tab\n            window = TryFocusAppropriateWindow(entering);\n            if (window)\n                return window;\n\n            // If we are entering Play more and no Game View was found, create one\n            if (entering && PlayModeView.openWindowOnEnteringPlayMode)\n            {\n                // Try to create and focus a Game View tab docked together with the Scene View tab\n                EditorWindow sceneView = FindEditorWindowOfType(typeof(SceneView));\n                GameView gameView;\n                if (sceneView && sceneView.m_Parent is DockArea)\n                {\n                    DockArea dock = sceneView.m_Parent as DockArea;\n                    if (dock)\n                    {\n                        WindowFocusState.instance.m_LastWindowTypeInSameDock = sceneView.GetType().ToString();\n                        gameView = ScriptableObject.CreateInstance<GameView>();\n                        dock.AddTab(gameView);\n                        return gameView;\n                    }\n                }\n\n                // If no Scene View was found at all, just create a floating Game View\n                gameView = ScriptableObject.CreateInstance<GameView>();\n                gameView.Show(true);\n                gameView.Focus();\n\n                return gameView;\n            }\n\n            return window;\n        }\n\n        internal static bool IsMaximized(EditorWindow window)\n        {\n            return window.m_Parent is MaximizedHostView;\n        }\n\n        public static void Unmaximize(EditorWindow win)\n        {\n            HostView maximizedHostView = win.m_Parent;\n            if (maximizedHostView == null)\n            {\n                Debug.LogError(\"Host view was not found\");\n                ResetAllLayouts();\n                return;\n            }\n\n            var restoreLayout = Path.Combine(layoutsProjectPath, kMaximizeRestoreFile);\n            UnityObject[] newWindows = InternalEditorUtility.LoadSerializedFileAndForget(restoreLayout);\n\n            if (newWindows.Length < 2)\n            {\n                Debug.LogError(\"Maximized serialized file backup not found.\");\n                ResetAllLayouts();\n                return;\n            }\n\n            SplitView oldRoot = newWindows[0] as SplitView;\n            EditorWindow oldWindow = newWindows[1] as EditorWindow;\n\n            if (oldRoot == null)\n            {\n                Debug.LogError(\"Maximization failed because the root split view was not found.\");\n                ResetAllLayouts();\n                return;\n            }\n\n            ContainerWindow parentWindow = win.m_Parent.window;\n            if (parentWindow == null)\n            {\n                Debug.LogError(\"Maximization failed because the root split view has no container window.\");\n                ResetAllLayouts();\n                return;\n            }\n\n            try\n            {\n                ContainerWindow.SetFreezeDisplay(true);\n\n                // Put the loaded SplitView where the MaximizedHostView was\n                if (maximizedHostView.parent)\n                {\n                    int i = maximizedHostView.parent.IndexOfChild(maximizedHostView);\n                    Rect r = maximizedHostView.position;\n                    View parent = maximizedHostView.parent;\n                    parent.RemoveChild(i);\n                    parent.AddChild(oldRoot, i);\n                    oldRoot.position = r;\n\n                    // Move the Editor Window to the right spot in the\n                    DockArea newDockArea = oldWindow.m_Parent as DockArea;\n\n                    int oldDockAreaIndex = newDockArea.m_Panes.IndexOf(oldWindow);\n\n                    maximizedHostView.actualView = null;\n                    win.m_Parent = null;\n                    newDockArea.AddTab(oldDockAreaIndex, win);\n                    newDockArea.RemoveTab(oldWindow);\n                    UnityObject.DestroyImmediate(oldWindow);\n\n                    foreach (UnityObject o in newWindows)\n                    {\n                        EditorWindow curWin = o as EditorWindow;\n                        if (curWin != null)\n                            curWin.MakeParentsSettingsMatchMe();\n                    }\n\n                    parent.Initialize(parent.window);\n\n                    //If parent window had to be resized, call this to make sure new size gets propagated\n                    parent.position = parent.position;\n                    oldRoot.Reflow();\n                }\n                else\n                {\n                    throw new LayoutException(\"No parent view\");\n                }\n\n                // Kill the maximizedMainView\n                UnityObject.DestroyImmediate(maximizedHostView);\n\n                win.Focus();\n\n                var gv = win as GameView;\n                if (gv != null)\n                    gv.m_Parent.EnableVSync(gv.vSyncEnabled);\n\n                parentWindow.DisplayAllViews();\n                win.m_Parent.MakeVistaDWMHappyDance();\n            }\n            catch (Exception ex)\n            {\n                Debug.Log(\"Maximization failed: \" + ex);\n                ResetAllLayouts();\n            }\n\n            try\n            {\n                // Weird bug on AMD graphic cards under OSX Lion: Sometimes when unmaximizing we get stray white rectangles.\n                // work around that by issuing an extra repaint (case 438764)\n                if (Application.platform == RuntimePlatform.OSXEditor && SystemInfo.operatingSystem.Contains(\"10.7\") && SystemInfo.graphicsDeviceVendor.Contains(\"ATI\"))\n                {\n                    foreach (GUIView v in Resources.FindObjectsOfTypeAll(typeof(GUIView)))\n                        v.Repaint();\n                }\n            }\n            finally\n            {\n                ContainerWindow.SetFreezeDisplay(false);\n            }\n        }\n\n        internal static void MaximizeGestureHandler()\n        {\n            if (Event.current.type != EditorGUIUtility.magnifyGestureEventType || GUIUtility.hotControl != 0)\n                return;\n\n            var mouseOverWindow = EditorWindow.mouseOverWindow;\n            if (mouseOverWindow == null)\n                return;\n\n            var args = new ShortcutArguments { stage = ShortcutStage.End };\n            if (IsMaximized(mouseOverWindow))\n                args.context = Event.current.delta.x < -0.05f ? mouseOverWindow : null;\n            else\n                args.context = Event.current.delta.x > 0.05f ? mouseOverWindow : null;\n\n            if (args.context != null)\n                MaximizeKeyHandler(args);\n        }\n\n        [Shortcut(\"Window/Maximize View\", KeyCode.Space, ShortcutModifiers.Shift)]\n        [FormerlyPrefKeyAs(\"Window/Maximize View\", \"# \")]\n        internal static void MaximizeKeyHandler(ShortcutArguments args)\n        {\n            if (args.context is PreviewWindow)\n                return;\n\n            var mouseOverWindow = EditorWindow.mouseOverWindow;\n\n            if (mouseOverWindow != null)\n            {\n                if (IsMaximized(mouseOverWindow))\n                    Unmaximize(mouseOverWindow);\n                else\n                    Maximize(mouseOverWindow);\n            }\n        }\n\n        private static View FindRootSplitView(EditorWindow win)\n        {\n            View itor = win.m_Parent.parent;\n            View rootSplit = itor;\n            while (itor is SplitView)\n            {\n                rootSplit = itor;\n                itor = itor.parent;\n            }\n\n            return rootSplit;\n        }\n\n        public static void AddSplitViewAndChildrenRecurse(View splitview, ArrayList list)\n        {\n            list.Add(splitview);\n            DockArea dock = splitview as DockArea;\n            if (dock != null)\n            {\n                list.AddRange(dock.m_Panes);\n                list.Add(dock.actualView);\n            }\n\n            foreach (View child in splitview.children)\n                AddSplitViewAndChildrenRecurse(child, list);\n        }\n\n        public static void SaveSplitViewAndChildren(View splitview, EditorWindow win, string path)\n        {\n            ArrayList all = new ArrayList();\n\n            AddSplitViewAndChildrenRecurse(splitview, all);\n            all.Remove(splitview);\n            all.Remove(win);\n            all.Insert(0, splitview);\n            all.Insert(1, win);\n\n            if (EnsureDirectoryCreated(path))\n                InternalEditorUtility.SaveToSerializedFileAndForget(all.ToArray(typeof(UnityObject)) as UnityObject[], path, true);\n        }\n\n        static bool EnsureDirectoryCreated(string path)\n        {\n            var parentFolderPath = Path.GetDirectoryName(path);\n            if (string.IsNullOrEmpty(parentFolderPath))\n                return false;\n\n            if (!Directory.Exists(parentFolderPath))\n                Directory.CreateDirectory(parentFolderPath);\n            return true;\n        }\n\n        public static void Maximize(EditorWindow win)\n        {\n            bool maximizePending = MaximizePrepare(win);\n            if (maximizePending)\n                MaximizePresent(win);\n        }\n\n        public static bool MaximizePrepare(EditorWindow win)\n        {\n            View rootSplit = FindRootSplitView(win);\n            //Some windows such as pop up windows might not have a split view\n            if (rootSplit == null)\n                return false;\n            View itor = rootSplit.parent;\n\n            // Make sure it has a dockarea\n            DockArea dockArea = win.m_Parent as DockArea;\n            if (dockArea == null)\n                return false;\n\n            if (itor == null)\n                return false;\n\n            var mainView = rootSplit.parent as MainView;\n            if (mainView == null)\n                return false;\n\n            ContainerWindow parentWindow = win.m_Parent.window;\n            if (parentWindow == null)\n                return false;\n\n            int oldDockIndex = dockArea.m_Panes.IndexOf(win);\n            if (oldDockIndex == -1)\n                return false;\n\n            if (!parentWindow.CanCloseAllExcept(win))\n                return false;\n\n            dockArea.selected = oldDockIndex;\n\n            // Save current state to disk\n            SaveSplitViewAndChildren(rootSplit, win, Path.Combine(layoutsProjectPath, kMaximizeRestoreFile));\n\n            // Remove the window from the HostView now in order to invoke OnBecameInvisible before OnBecameVisible\n            dockArea.actualView = null;\n\n            dockArea.m_Panes[oldDockIndex] = null;\n\n            MaximizedHostView maximizedHostView = ScriptableObject.CreateInstance<MaximizedHostView>();\n\n            int i = itor.IndexOfChild(rootSplit);\n            Rect p = rootSplit.position;\n            itor.RemoveChild(rootSplit);\n            itor.AddChild(maximizedHostView, i);\n\n            maximizedHostView.actualView = win;\n            maximizedHostView.position = p; // Must be set after actualView so that value is propagated\n\n            var gv = win as GameView;\n            if (gv != null)\n                maximizedHostView.EnableVSync(gv.vSyncEnabled);\n\n            UnityObject.DestroyImmediate(rootSplit, true);\n            return true;\n        }\n\n        public static void MaximizePresent(EditorWindow win)\n        {\n            ContainerWindow.SetFreezeDisplay(true);\n\n            win.Focus();\n\n            CheckWindowConsistency();\n\n            ContainerWindow parentWindow = win.m_Parent.window;\n            parentWindow.DisplayAllViews();\n\n            win.m_Parent.MakeVistaDWMHappyDance();\n\n            ContainerWindow.SetFreezeDisplay(false);\n\n            win.OnMaximized();\n        }\n\n        static void DeleteWindowLayout(string path)\n        {\n            var name = Path.GetFileNameWithoutExtension(path);\n            if (!EditorUtility.DisplayDialog(\"Delete Layout\", $\"Delete window layout '{name}'?\", \"Delete\", \"Cancel\"))\n                return;\n\n            DeleteWindowLayoutImpl(name, path);\n        }\n\n        [UsedImplicitly] // used by SaveLayoutTests.cs\n        internal static void DeleteNamedWindowLayoutNoDialog(string name)\n        {\n            var path = Path.Combine(layoutsModePreferencesPath, name + \".wlt\");\n            DeleteWindowLayoutImpl(name, path);\n        }\n\n        static void DeleteWindowLayoutImpl(string name, string path)\n        {\n            if (Toolbar.lastLoadedLayoutName == name)\n                Toolbar.lastLoadedLayoutName = null;\n\n            File.Delete(path);\n            ReloadWindowLayoutMenu();\n            EditorUtility.Internal_UpdateAllMenus();\n            ShortcutIntegration.instance.RebuildShortcuts();\n        }\n\n        // Attempts to load a layout. If unsuccessful, restores the previous layout.\n        public static bool TryLoadWindowLayout(string path, bool newProjectLayoutWasCreated)\n        {\n            var flags = GetLoadWindowLayoutFlags(newProjectLayoutWasCreated, true, false, true);\n            return TryLoadWindowLayout(path, flags);\n        }\n\n        // Attempts to load a layout. If unsuccessful, restores the previous layout.\n        public static bool TryLoadWindowLayout(string path, bool newProjectLayoutWasCreated, bool setLastLoadedLayoutName, bool keepMainWindow, bool logErrorsToConsole)\n        {\n            var flags = GetLoadWindowLayoutFlags(newProjectLayoutWasCreated, setLastLoadedLayoutName, keepMainWindow, logErrorsToConsole);\n            return TryLoadWindowLayout(path, flags);\n        }\n\n        // Attempts to load a layout. If unsuccessful, restores the previous layout.\n        public static bool TryLoadWindowLayout(string path, LoadWindowLayoutFlags flags)\n        {\n            if (LoadWindowLayout_Internal(path, flags))\n                return true;\n            LoadCurrentModeLayout(FindMainWindow());\n            return false;\n        }\n\n        [Flags]\n        public enum LoadWindowLayoutFlags\n        {\n            None = 0,\n            NewProjectCreated = 1 << 0,\n            SetLastLoadedLayoutName = 1 << 1,\n            KeepMainWindow = 1 << 2,\n            LogsErrorToConsole = 1 << 3,\n            NoMainWindowSupport = 1 << 4,\n            SaveLayoutPreferences = 1 << 5\n        }\n\n        // This method is public only because some packages have internal access and use it.\n        [Obsolete(\"Do not use this method. Use TryLoadWindowLayout instead.\")]\n        public static bool LoadWindowLayout(string path, bool newProjectLayoutWasCreated, bool setLastLoadedLayoutName, bool keepMainWindow, bool logErrorsToConsole)\n        {\n            return TryLoadWindowLayout(path, newProjectLayoutWasCreated, setLastLoadedLayoutName, keepMainWindow, logErrorsToConsole);\n        }\n\n        // This method is public only because some packages have internal access and use it.\n        [Obsolete(\"Do not use this method. Use TryLoadWindowLayout instead.\")]\n        public static bool LoadWindowLayout(string path, LoadWindowLayoutFlags flags)\n        {\n            return TryLoadWindowLayout(path, flags);\n        }\n\n        // IMPORTANT: Do not expose this method outside WindowLayout. Do not use this method as the entry point to load a layout.\n        // Use TryLoadWindowLayout instead. It can put us in a state that is unrecoverable where all windows are gone but Unity\n        // still lives as a background process. Only use this method from another method that handles the recovery process in case\n        // of failure.\n        static bool LoadWindowLayout_Internal(string path, bool newProjectLayoutWasCreated, bool setLastLoadedLayoutName, bool keepMainWindow, bool logErrorsToConsole)\n        {\n            var flags = GetLoadWindowLayoutFlags(newProjectLayoutWasCreated, setLastLoadedLayoutName, keepMainWindow, logErrorsToConsole);\n            return LoadWindowLayout_Internal(path, flags);\n        }\n\n        static LoadWindowLayoutFlags GetLoadWindowLayoutFlags(bool newProjectLayoutWasCreated, bool setLastLoadedLayoutName, bool keepMainWindow, bool logErrorsToConsole)\n        {\n            var flags = LoadWindowLayoutFlags.SaveLayoutPreferences;\n            if (newProjectLayoutWasCreated)\n                flags |= LoadWindowLayoutFlags.NewProjectCreated;\n            if (setLastLoadedLayoutName)\n                flags |= LoadWindowLayoutFlags.SetLastLoadedLayoutName;\n            if (keepMainWindow)\n                flags |= LoadWindowLayoutFlags.KeepMainWindow;\n            if (logErrorsToConsole)\n                flags |= LoadWindowLayoutFlags.LogsErrorToConsole;\n            return flags;\n        }\n\n        // IMPORTANT: Do not expose this method outside WindowLayout. Do not use this method as the entry point to load a layout.\n        // Use TryLoadWindowLayout instead. It can put us in a state that is unrecoverable where all windows are gone but Unity\n        // still lives as a background process. Only use this method from another method that handles the recovery process in case\n        // of failure.\n        static bool LoadWindowLayout_Internal(string path, LoadWindowLayoutFlags flags)\n        {\n            Console.WriteLine($\"[LAYOUT] About to load {path}, keepMainWindow={flags.HasFlag(LoadWindowLayoutFlags.KeepMainWindow)}\");\n\n            if (!Application.isTestRun && !ContainerWindow.CanCloseAll(flags.HasFlag(LoadWindowLayoutFlags.KeepMainWindow)))\n                return false;\n\n            bool mainWindowMaximized = ContainerWindow.mainWindow?.maximized ?? false;\n            Rect mainWindowPosition = ContainerWindow.mainWindow?.position ?? new Rect();\n\n            // Load new windows and show them\n            try\n            {\n                ContainerWindow.SetFreezeDisplay(true);\n\n                CloseWindows(flags.HasFlag(LoadWindowLayoutFlags.KeepMainWindow));\n\n                ContainerWindow mainWindowToSetSize = null;\n                ContainerWindow mainWindow = null;\n\n                UnityObject[] remainingContainers = Resources.FindObjectsOfTypeAll(typeof(ContainerWindow));\n                foreach (ContainerWindow window in remainingContainers)\n                {\n                    if (mainWindow == null && window.showMode == ShowMode.MainWindow)\n                        mainWindow = window;\n                    else\n                        window.Close();\n                }\n\n                // Load data\n                UnityObject[] loadedWindows = InternalEditorUtility.LoadSerializedFileAndForget(path);\n\n                if (loadedWindows == null || loadedWindows.Length == 0)\n                    throw new LayoutException(\"No windows found in layout.\");\n\n                List<UnityObject> newWindows = new List<UnityObject>();\n\n                // At this point, unparented editor windows are neither desired nor desirable.\n                // This can be caused by (legacy) serialization of FallbackEditorWindows or\n                // other serialization hiccups (note that unparented editor windows should not exist in theory).\n                // Same goes for empty DockAreas (no panes).  Leave them behind.\n                for (int i = 0; i < loadedWindows.Length; i++)\n                {\n                    UnityObject o = loadedWindows[i];\n\n                    if (o is EditorWindow editorWin)\n                    {\n                        if (!editorWin || !editorWin.m_Parent || !editorWin.m_Parent.window)\n                        {\n                            Console.WriteLine($\"[LAYOUT] Removed un-parented EditorWindow while reading window layout\" +\n                                              $\" window #{i}, type={o.GetType()} instanceID={o.GetInstanceID()}\");\n                            UnityObject.DestroyImmediate(editorWin, true);\n                            continue;\n                        }\n                    }\n                    else\n                    {\n                        if (o is ContainerWindow cw && cw.rootView == null)\n                        {\n                            cw.Close();\n                            UnityObject.DestroyImmediate(cw, true);\n                            continue;\n                        }\n                        else if (o is DockArea dockArea && dockArea.m_Panes.Count == 0)\n                        {\n                            dockArea.Close(null);\n                            UnityObject.DestroyImmediate(dockArea, true);\n                            continue;\n                        }\n                        else if (o is HostView hostview && hostview.actualView == null)\n                        {\n                            UnityObject.DestroyImmediate(hostview, true);\n                            continue;\n                        }\n                    }\n\n                    newWindows.Add(o);\n                }\n\n                for (int i = 0; i < newWindows.Count; i++)\n                {\n                    ContainerWindow cur = newWindows[i] as ContainerWindow;\n                    if (cur != null && cur.showMode == ShowMode.MainWindow)\n                    {\n                        if (mainWindow == null)\n                        {\n                            mainWindow = cur;\n                        }\n                        else\n                        {\n                            mainWindow.rootView = cur.rootView;\n                            UnityObject.DestroyImmediate(cur, true);\n                            cur = mainWindow;\n                            newWindows[i] = null;\n                        }\n\n                        if (mainWindowPosition.width != 0.0)\n                        {\n                            mainWindowToSetSize = cur;\n                            // This is the same reference as the mainwindow, so need to freeze it too on for Linux during reload.\n                            mainWindowToSetSize.SetFreeze(true);\n                            mainWindowToSetSize.position = mainWindowPosition;\n                        }\n\n                        break;\n                    }\n                }\n\n                for (int i = 0; i < newWindows.Count; i++)\n                {\n                    UnityObject o = newWindows[i];\n                    if (!o)\n                        continue;\n\n                    if (flags.HasFlag(LoadWindowLayoutFlags.NewProjectCreated))\n                    {\n                        MethodInfo method = o.GetType().GetMethod(\"OnNewProjectLayoutWasCreated\", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);\n                        method?.Invoke(o, null);\n                    }\n                }\n\n                if (mainWindowToSetSize)\n                {\n                    mainWindowToSetSize.SetFreeze(true);\n                    mainWindowToSetSize.position = mainWindowPosition;\n                }\n                // Always show main window before other windows. So that other windows can\n                // get their parent/owner.\n                if (mainWindow)\n                {\n                    // If at this point the mainWindow still doesn't have a rootView, it probably means we loaded a layout without a main window.\n                    // Delete the current mainWindow so that we can load back the previous layout otherwise every attemp at loading a layout will fail.\n                    if (mainWindow.rootView == null || !mainWindow.rootView)\n                    {\n                        mainWindow.Close();\n                        UnityObject.DestroyImmediate(mainWindow, true);\n                        throw new LayoutException(\"Error while reading window layout: no root view on main window.\");\n                    }\n\n                    // Don't adjust height to prevent main window shrink during layout on Linux.\n                    mainWindow.SetFreeze(true);\n                    mainWindow.Show(mainWindow.showMode, loadPosition: true, displayImmediately: true, setFocus: true);\n                    if (mainWindowToSetSize && mainWindow.maximized != mainWindowMaximized)\n                        mainWindow.ToggleMaximize();\n                    // Unfreeze to make sure resize work properly.\n                    mainWindow.SetFreeze(false);\n\n                    // Make sure to restore the save to layout flag when loading a layout from a file.\n                    if (flags.HasFlag(LoadWindowLayoutFlags.KeepMainWindow))\n                        mainWindow.m_DontSaveToLayout = false;\n                }\n                else if (!flags.HasFlag(LoadWindowLayoutFlags.NoMainWindowSupport))\n                {\n                    throw new LayoutException(\"Error while reading window layout: no main window found\");\n                }\n\n                // Show other windows\n                for (int i = 0; i < newWindows.Count; i++)\n                {\n                    if (newWindows[i] == null)\n                        continue;\n\n                    EditorWindow win = newWindows[i] as EditorWindow;\n                    if (win)\n                        win.minSize = win.minSize; // Causes minSize to be propagated upwards to parents!\n\n                    ContainerWindow containerWindow = newWindows[i] as ContainerWindow;\n                    if (containerWindow && containerWindow != mainWindow)\n                    {\n                        containerWindow.Show(containerWindow.showMode, loadPosition: false, displayImmediately: true, setFocus: true);\n                        if (flags.HasFlag(LoadWindowLayoutFlags.NoMainWindowSupport))\n                        {\n                            containerWindow.m_DontSaveToLayout = mainWindow != null;\n                        }\n                    }\n                }\n\n                // Un-maximize maximized PlayModeView window if maximize on play is enabled\n                PlayModeView playModeView = GetMaximizedWindow() as PlayModeView;\n                if (playModeView != null && playModeView.enterPlayModeBehavior == PlayModeView.EnterPlayModeBehavior.PlayMaximized)\n                    Unmaximize(playModeView);\n            }\n            catch (Exception ex)\n            {\n                // When loading a new project we don't want to log an error if one of the last saved layouts throws.\n                // There isn't anything useful a user can do about it, and we can gracefully recover. However when a\n                // layout is loaded from the menu or a mode change, we do want to let the user know about layout loading\n                // problems because they can act on it by either deleting the layout or importing whatever asset is\n                // missing.\n                var error = $\"Failed to load window layout \\\"{path}\\\": {ex}\";\n                if(flags.HasFlag(LoadWindowLayoutFlags.LogsErrorToConsole))\n                    Debug.LogError(error);\n                else\n                    Console.WriteLine($\"[LAYOUT] {error}\");\n                return false;\n            }\n            finally\n            {\n                ContainerWindow.SetFreezeDisplay(false);\n\n                if (flags.HasFlag(LoadWindowLayoutFlags.SetLastLoadedLayoutName) && Path.GetExtension(path) == \".wlt\")\n                    Toolbar.lastLoadedLayoutName = Path.GetFileNameWithoutExtension(path);\n                else\n                    Toolbar.lastLoadedLayoutName = null;\n            }\n\n            if (flags.HasFlag(LoadWindowLayoutFlags.SaveLayoutPreferences))\n                SaveDefaultWindowPreferences();\n\n            return true;\n        }\n\n        internal static void LoadDefaultLayout()\n        {\n            InitializeLayoutPreferencesFolder();\n\n            FileUtil.DeleteFileOrDirectory(ProjectLayoutPath);\n\n            if (EnsureDirectoryCreated(ProjectLayoutPath))\n            {\n                Console.WriteLine($\"[LAYOUT] LoadDefaultLayout: Copying Project Current Layout: {ProjectLayoutPath} from {GetDefaultLayoutPath()}\");\n                FileUtil.CopyFileOrDirectory(GetDefaultLayoutPath(), ProjectLayoutPath);\n            }\n            Debug.Assert(File.Exists(ProjectLayoutPath));\n\n            LoadWindowLayout_Internal(ProjectLayoutPath, true, true, false, false);\n        }\n\n        public static void CloseWindows()\n        {\n            CloseWindows(false);\n        }\n\n        private static void CloseWindows(bool keepMainWindow)\n        {\n            try\n            {\n                // ForceClose any existing tooltips\n                TooltipView.ForceClose();\n            }\n            catch (Exception)\n            {\n                // ignored\n            }\n\n            // ForceClose all container windows\n            ContainerWindow mainWindow = null;\n            UnityObject[] containers = Resources.FindObjectsOfTypeAll(typeof(ContainerWindow));\n            foreach (ContainerWindow window in containers)\n            {\n                try\n                {\n                    if (window.showMode != ShowMode.MainWindow || !keepMainWindow || mainWindow != null)\n                    {\n                        window.Close();\n                        UnityObject.DestroyImmediate(window, true);\n                    }\n                    else\n                    {\n                        UnityObject.DestroyImmediate(window.rootView, true);\n                        window.rootView = null;\n                        mainWindow = window;\n                    }\n                }\n                catch (Exception)\n                {\n                    // ignored\n                }\n            }\n\n            // Double check correct closing\n            UnityObject[] oldWindows = Resources.FindObjectsOfTypeAll(typeof(EditorWindow));\n            if (oldWindows.Length != 0)\n            {\n                string output = \"\";\n                foreach (EditorWindow killme in oldWindows)\n                {\n                    output += $\"{killme.GetType().Name} {killme.name} {killme.titleContent.text} [{killme.GetInstanceID()}]\\r\\n\";\n                    UnityObject.DestroyImmediate(killme, true);\n                }\n            }\n\n            UnityObject[] oldViews = Resources.FindObjectsOfTypeAll(typeof(View));\n            if (oldViews.Length != 0)\n            {\n                foreach (View killme in oldViews)\n                    UnityObject.DestroyImmediate(killme, true);\n            }\n        }\n\n        internal static void SaveWindowLayout(string path)\n        {\n            SaveWindowLayout(path, true);\n        }\n\n        public static void SaveWindowLayout(string path, bool reportErrors)\n        {\n            if (!EnsureDirectoryCreated(path))\n                return;\n\n            Console.WriteLine($\"[LAYOUT] About to save layout {path}\");\n            TooltipView.ForceClose();\n\n            UnityObject[] windows = Resources.FindObjectsOfTypeAll(typeof(EditorWindow));\n            UnityObject[] containers = Resources.FindObjectsOfTypeAll(typeof(ContainerWindow));\n            UnityObject[] views = Resources.FindObjectsOfTypeAll(typeof(View));\n\n            var all = new List<UnityObject>();\n            var ignoredViews = new List<ScriptableObject>();\n            foreach (ContainerWindow w in containers)\n            {\n                // skip ContainerWindows that are \"dont save me\"\n                if (!w || w.m_DontSaveToLayout)\n                    ignoredViews.Add(w);\n                else\n                    all.Add(w);\n            }\n\n            foreach (View w in views)\n            {\n                // skip Views that belong to \"dont save me\" container\n                if (!w || !w.window || ignoredViews.Contains(w.window))\n                    ignoredViews.Add(w);\n                else\n                    all.Add(w);\n            }\n\n            foreach (EditorWindow w in windows)\n            {\n                // skip EditorWindows that belong to \"dont save me\" container\n                if (!w || !w.m_Parent || ignoredViews.Contains(w.m_Parent))\n                {\n                    if (reportErrors && w)\n                        Debug.LogWarning($\"Cannot save invalid window {w.titleContent.text} {w} to layout.\");\n                    continue;\n                }\n                all.Add(w);\n            }\n\n            if (all.Any())\n                InternalEditorUtility.SaveToSerializedFileAndForget(all.Where(o => o).ToArray(), path, true);\n        }\n\n        // ReSharper disable once MemberCanBePrivate.Global - used by SaveLayoutTests.cs\n        internal static void SaveGUI()\n        {\n            UnityEditor.SaveWindowLayout.ShowWindow();\n        }\n\n        public static void LoadFromFile()\n        {\n            var layoutFilePath = EditorUtility.OpenFilePanelWithFilters(\"Load layout from disk...\", \"\", new[] {\"Layout\", \"wlt\"});\n            if (string.IsNullOrEmpty(layoutFilePath))\n                return;\n            TryLoadWindowLayout(layoutFilePath, false);\n        }\n\n        public static void SaveToFile()\n        {\n            var layoutFilePath = EditorUtility.SaveFilePanel(\"Save layout to disk...\", \"\", \"layout\", \"wlt\");\n            if (String.IsNullOrEmpty(layoutFilePath))\n                return;\n\n            SaveWindowLayout(layoutFilePath);\n            EditorUtility.RevealInFinder(layoutFilePath);\n        }\n\n        private static void ResetUserLayouts()\n        {\n            // Copy installation layouts to user global layouts and overwrite any existing ones.\n            var layoutPaths = Directory.GetFiles(layoutResourcesPath, \"*.wlt\");\n            foreach (var installationLayoutPath in layoutPaths)\n            {\n                var layoutFilename = Path.GetFileName(installationLayoutPath);\n                var userLayoutDstPath = FileUtil.CombinePaths(layoutsDefaultModePreferencesPath, layoutFilename);\n                FileUtil.CopyFileIfExists(installationLayoutPath, userLayoutDstPath, overwrite: true);\n            }\n\n            // delete per-project layouts\n            if (Directory.Exists(layoutsProjectPath))\n                Directory.Delete(layoutsProjectPath, true);\n\n            // delete per-user layouts\n            if (Directory.Exists(layoutsCurrentModePreferencesPath))\n                Directory.Delete(layoutsCurrentModePreferencesPath, true);\n        }\n\n\n        public static void ResetAllLayouts(bool quitOnCancel = true)\n        {\n            if (!Application.isTestRun && !EditorUtility.DisplayDialog(\"Revert All Window Layouts\",\n                \"Unity is about to delete all window layouts and restore them to the default settings.\",\n                \"Continue\", quitOnCancel ? \"Quit\" : \"Cancel\"))\n            {\n                if (quitOnCancel)\n                    EditorApplication.Exit(0);\n                return;\n            }\n\n            if (!ContainerWindow.CanCloseAll(false))\n                return;\n\n            ResetFactorySettings();\n        }\n\n        public static void ResetFactorySettings()\n        {\n            // Reset user layouts\n            ResetUserLayouts();\n\n            // Reset mode settings\n            ModeService.ChangeModeById(\"default\");\n\n            LoadCurrentModeLayout(keepMainWindow: false);\n            ReloadWindowLayoutMenu();\n            EditorUtility.Internal_UpdateAllMenus();\n            ShortcutIntegration.instance.RebuildShortcuts();\n        }\n    }\n\n    [EditorWindowTitle(title = \"Save Layout\")]\n    internal class SaveWindowLayout : EditorWindow\n    {\n        bool m_DidFocus;\n        const int k_Width = 200;\n        const int k_Height = 48;\n        const int k_HelpBoxHeight = 40;\n        const int k_MaxLayoutNameLength = 128;\n\n        static readonly string k_InvalidChars = EditorUtility.GetInvalidFilenameChars();\n        static readonly string s_InvalidCharsFormatString = L10n.Tr(\"Invalid characters: {0}\");\n        string m_CurrentInvalidChars = \"\";\n        string m_LayoutName = Toolbar.lastLoadedLayoutName;\n\n        internal static SaveWindowLayout ShowWindow()\n        {\n            SaveWindowLayout w = GetWindowDontShow<SaveWindowLayout>();\n            w.minSize = w.maxSize = new Vector2(k_Width, k_Height);\n            w.m_Pos = new Rect(0, 0,k_Width, k_Height);\n            w.ShowAuxWindow();\n            return w;\n        }\n\n        void UpdateCurrentInvalidChars()\n        {\n            m_CurrentInvalidChars = new string(m_LayoutName.Intersect(k_InvalidChars).Distinct().ToArray());\n        }\n\n        void OnEnable()\n        {\n            titleContent = GetLocalizedTitleContent();\n        }\n\n        void OnGUI()\n        {\n            GUILayout.Space(5);\n            Event evt = Event.current;\n            bool hitEnter = evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter);\n            bool hitEscape = evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.Escape);\n            if (hitEscape)\n            {\n                Close();\n                GUIUtility.ExitGUI();\n            }\n            GUI.SetNextControlName(\"m_PreferencesName\");\n            EditorGUI.BeginChangeCheck();\n            m_LayoutName = EditorGUILayout.TextField(m_LayoutName);\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (m_LayoutName.Length > k_MaxLayoutNameLength)\n                {\n                    m_LayoutName = m_LayoutName.Substring(0, k_MaxLayoutNameLength);\n                }\n                m_LayoutName = m_LayoutName.TrimEnd();\n                UpdateCurrentInvalidChars();\n            }\n\n            if (!m_DidFocus)\n            {\n                m_DidFocus = true;\n                EditorGUI.FocusTextInControl(\"m_PreferencesName\");\n            }\n\n            if (m_CurrentInvalidChars.Length != 0)\n            {\n                EditorGUILayout.HelpBox(string.Format(s_InvalidCharsFormatString, m_CurrentInvalidChars), MessageType.Warning);\n                minSize = new Vector2(k_Width, k_Height + k_HelpBoxHeight);\n            }\n            else\n            {\n                minSize = new Vector2(k_Width, k_Height);\n            }\n\n            bool canSaveLayout = m_LayoutName.Length > 0 && m_CurrentInvalidChars.Length == 0;\n            EditorGUI.BeginDisabled(!canSaveLayout);\n\n            if (GUILayout.Button(\"Save\") || hitEnter && canSaveLayout)\n            {\n                Close();\n\n                if (!Directory.Exists(WindowLayout.layoutsModePreferencesPath))\n                    Directory.CreateDirectory(WindowLayout.layoutsModePreferencesPath);\n\n                string path = Path.Combine(WindowLayout.layoutsModePreferencesPath, m_LayoutName + \".wlt\");\n                if (File.Exists(path))\n                {\n                    if (!EditorUtility.DisplayDialog(\"Overwrite layout?\",\n                        \"Do you want to overwrite '\" + m_LayoutName + \"' layout?\",\n                        \"Overwrite\", \"Cancel\"))\n                        GUIUtility.ExitGUI();\n                }\n\n                Toolbar.lastLoadedLayoutName = m_LayoutName;\n                WindowLayout.SaveWindowLayout(path);\n                WindowLayout.ReloadWindowLayoutMenu();\n                EditorUtility.Internal_UpdateAllMenus();\n                ShortcutIntegration.instance.RebuildShortcuts();\n                GUIUtility.ExitGUI();\n            }\n            else\n            {\n                m_DidFocus = false;\n            }\n\n            EditorGUI.EndDisabled();\n        }\n    }\n\n    internal static class CreateBuiltinWindows\n    {\n        [MenuItem(\"Window/General/Scene %1\", false, 1)]\n        static void ShowSceneView()\n        {\n            EditorWindow.GetWindowWithExactType<SceneView>();\n        }\n\n        [MenuItem(\"Window/General/Game %2\", false, 2)]\n        static void ShowGameView()\n        {\n            EditorWindow.GetWindow<GameView>();\n        }\n\n        [MenuItem(\"Window/General/Inspector %3\", false, 3)]\n        static void ShowInspector()\n        {\n            EditorWindow.GetWindow<InspectorWindow>();\n        }\n\n        [MenuItem(\"Window/General/Hierarchy %4\", false, 4)]\n        static void ShowNewHierarchy()\n        {\n            EditorWindow.GetWindow<SceneHierarchyWindow>();\n        }\n\n        [MenuItem(\"Window/General/Project %5\", false, 5)]\n        static void ShowProject()\n        {\n            EditorWindow.GetWindow<ProjectBrowser>();\n        }\n\n        [MenuItem(\"Window/Animation/Animation %6\", false, 1)]\n        static void ShowAnimationWindow()\n        {\n            EditorWindow.GetWindow<AnimationWindow>();\n        }\n\n        [MenuItem(\"Window/Audio/Audio Random Container\", false, 1)]\n        static void ShowAudioRandomContainerWindow()\n        {\n            AudioContainerWindow.CreateAudioRandomContainerWindow();\n        }\n\n        [MenuItem(\"Window/Audio/Audio Mixer %8\", false, 2)]\n        static void ShowAudioMixer()\n        {\n            AudioMixerWindow.CreateAudioMixerWindow();\n        }\n\n        // Version Control is registered from native code (EditorWindowController.cpp), for license check\n        [RequiredByNativeCode]\n        static void ShowVersionControl()\n        {\n            EditorWindow.GetWindow<WindowPending>();\n        }\n\n        [MenuItem(\"Window/General/Console %#c\", false, 6)]\n        static void ShowConsole()\n        {\n            EditorWindow.GetWindow<ConsoleWindow>();\n        }\n    }\n\n    internal class WindowFocusState : ScriptableObject\n    {\n        private static WindowFocusState m_Instance;\n\n        internal string m_LastWindowTypeInSameDock = \"\";\n        internal bool m_WasMaximizedBeforePlay = false;\n        internal bool m_CurrentlyInPlayMode = false;\n\n        internal static WindowFocusState instance\n        {\n            get\n            {\n                if (m_Instance == null)\n                    m_Instance = FindFirstObjectByType(typeof(WindowFocusState)) as WindowFocusState;\n                if (m_Instance == null)\n                    m_Instance = CreateInstance<WindowFocusState>();\n                return m_Instance;\n            }\n        }\n\n        void OnEnable()\n        {\n            hideFlags = HideFlags.HideAndDontSave;\n            m_Instance = this;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GUID.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    [Serializable]\n    [RequiredByNativeCode]\n    [NativeHeader(\"Runtime/Utilities/GUID.h\")]\n    public partial struct GUID : IComparable, IComparable<GUID>, IEquatable<GUID>\n    {\n        private uint m_Value0, m_Value1, m_Value2, m_Value3;\n\n        public GUID(string hexRepresentation)\n        {\n            m_Value0 = 0;\n            m_Value1 = 0;\n            m_Value2 = 0;\n            m_Value3 = 0;\n            TryParse(hexRepresentation, out this);\n        }\n\n        public static bool operator==(GUID x, GUID y)\n        {\n            return x.m_Value0 == y.m_Value0 && x.m_Value1 == y.m_Value1 && x.m_Value2 == y.m_Value2 && x.m_Value3 == y.m_Value3;\n        }\n\n        public static bool operator!=(GUID x, GUID y)\n        {\n            return !(x == y);\n        }\n\n        public static bool operator<(GUID x, GUID y)\n        {\n            if (x.m_Value0 != y.m_Value0)\n                return x.m_Value0 < y.m_Value0;\n            if (x.m_Value1 != y.m_Value1)\n                return x.m_Value1 < y.m_Value1;\n            if (x.m_Value2 != y.m_Value2)\n                return x.m_Value2 < y.m_Value2;\n            return x.m_Value3 < y.m_Value3;\n        }\n\n        public static bool operator>(GUID x, GUID y)\n        {\n            if (x < y)\n                return false;\n            if (x == y)\n                return false;\n            return true;\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj == null || !(obj is GUID))\n                return false;\n\n            return Equals((GUID)obj);\n        }\n\n        public bool Equals(GUID obj)\n        {\n            return this == obj;\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                var hashCode = (int)m_Value0;\n                hashCode = (hashCode * 397) ^ (int)m_Value1;\n                hashCode = (hashCode * 397) ^ (int)m_Value2;\n                hashCode = (hashCode * 397) ^ (int)m_Value3;\n                return hashCode;\n            }\n        }\n\n        public int CompareTo(object obj)\n        {\n            if (obj == null)\n                return 1;\n\n            GUID rhs = (GUID)obj;\n            return this.CompareTo(rhs);\n        }\n\n        public int CompareTo(GUID rhs)\n        {\n            if (this < rhs)\n                return -1;\n            if (this > rhs)\n                return 1;\n            return 0;\n        }\n\n        public bool Empty()\n        {\n            return m_Value0 == 0 && m_Value1 == 0 && m_Value2 == 0 && m_Value3 == 0;\n        }\n\n        [Obsolete(\"Use TryParse instead\")]\n        public bool ParseExact(string hex)\n        {\n            return TryParse(hex, out this);\n        }\n\n        public static bool TryParse(string hex, out GUID result)\n        {\n            result = HexToGUIDInternal(hex);\n            return !result.Empty();\n        }\n\n        public static GUID Generate()\n        {\n            return GenerateGUIDInternal();\n        }\n\n        public override string ToString()\n        {\n            return GUIDToHexInternal(ref this);\n        }\n\n        //Thread safety verified, only safe static methods are used.\n        [NativeMethod(Name = \"GUIDToString\", IsFreeFunction = true, IsThreadSafe = true)]\n        extern private static string GUIDToHexInternal(ref GUID value);\n\n        //Thread safety verified, native method modified to not lazy init global lookup table.\n        [NativeMethod(Name = \"StringToGUID\", IsFreeFunction = true, IsThreadSafe = true)]\n        extern private static GUID HexToGUIDInternal(string hex);\n\n        [NativeMethod(Name = \"GenerateGUID\", IsFreeFunction = true)]\n        extern private static GUID GenerateGUIDInternal();\n\n        [NativeMethod(Name = \"CreateGUIDFromSInt64\", IsFreeFunction = true)]\n        extern internal static GUID CreateGUIDFromSInt64(long value);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUIDebugger/BaseInspectView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Globalization;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal interface IBaseInspectView\n    {\n        void UpdateInstructions();\n        void DrawInstructionList();\n        void DrawSelectedInstructionDetails(float availableWidth);\n        void ShowOverlay();\n        void SelectRow(int index);\n        void ClearRowSelection();\n    }\n\n    internal abstract class BaseInspectView : IBaseInspectView\n    {\n        protected static class Styles\n        {\n            public static readonly GUIContent instructionsLabel = EditorGUIUtility.TrTextContent(\"Instructions\");\n            public static readonly GUIContent emptyViewLabel = EditorGUIUtility.TrTextContent(\"Select an Instruction on the left to see details\");\n\n            public static readonly GUIStyle centeredLabel = \"IN CenteredLabel\";\n        }\n\n        protected ListViewState listViewState => m_ListViewState;\n\n        [NonSerialized]\n        readonly ListViewState m_ListViewState = new ListViewState();\n        protected GUIViewDebuggerWindow debuggerWindow => m_DebuggerWindow;\n        private readonly GUIViewDebuggerWindow m_DebuggerWindow;\n        Vector2 m_InstructionDetailsScrollPos = new Vector2();\n        readonly SplitterState m_InstructionDetailStacktraceSplitter = SplitterState.FromRelative(new float[] { 80, 20 }, new float[] { 100, 100 }, null);\n\n        protected BaseInspectView(GUIViewDebuggerWindow guiViewDebuggerWindow)\n        {\n            m_DebuggerWindow = guiViewDebuggerWindow;\n        }\n\n        public abstract void UpdateInstructions();\n\n        public virtual void DrawInstructionList()\n        {\n            Event evt = Event.current;\n            m_ListViewState.totalRows = GetInstructionCount();\n\n            EditorGUILayout.BeginVertical(GUIViewDebuggerWindow.Styles.listBackgroundStyle);\n            GUILayout.Label(Styles.instructionsLabel);\n\n            int id = GUIUtility.GetControlID(FocusType.Keyboard);\n            foreach (var element in ListViewGUI.ListView(m_ListViewState, GUIViewDebuggerWindow.Styles.listBackgroundStyle))\n            {\n                ListViewElement listViewElement = (ListViewElement)element;\n                if (evt.type == EventType.MouseDown && evt.button == 0 && listViewElement.position.Contains(evt.mousePosition))\n                {\n                    if (evt.clickCount == 2)\n                    {\n                        OnDoubleClickInstruction(listViewElement.row);\n                    }\n                }\n                // Paint list view element\n                if (evt.type == EventType.Repaint && listViewElement.row < GetInstructionCount())\n                {\n                    DoDrawInstruction(listViewElement, id);\n                }\n            }\n            EditorGUILayout.EndVertical();\n        }\n\n        public virtual void DrawSelectedInstructionDetails(float availableWidth)\n        {\n            if (m_ListViewState.selectionChanged)\n                OnSelectedInstructionChanged(m_ListViewState.row);\n            else if (m_ListViewState.row >= GetInstructionCount())\n                OnSelectedInstructionChanged(-1);\n\n            if (!isInstructionSelected)\n            {\n                DoDrawNothingSelected();\n                return;\n            }\n\n            SplitterGUILayout.BeginVerticalSplit(m_InstructionDetailStacktraceSplitter);\n\n            m_InstructionDetailsScrollPos = EditorGUILayout.BeginScrollView(m_InstructionDetailsScrollPos, GUIViewDebuggerWindow.Styles.boxStyle);\n\n            DoDrawSelectedInstructionDetails(m_ListViewState.row);\n            EditorGUILayout.EndScrollView();\n\n            DrawInspectedStacktrace(availableWidth);\n            SplitterGUILayout.EndVerticalSplit();\n        }\n\n        public abstract void ShowOverlay();\n\n        public virtual void SelectRow(int index)\n        {\n            if (index >= 0 && index < m_ListViewState.totalRows)\n            {\n                m_ListViewState.row = index;\n                m_ListViewState.selectionChanged = true;\n                m_ListViewState.scrollPos = new Vector2(m_ListViewState.scrollPos.x, index * GUIViewDebuggerWindow.Styles.listItem.fixedHeight);\n            }\n        }\n\n        public virtual void ClearRowSelection()\n        {\n            m_ListViewState.row = -1;\n            m_ListViewState.selectionChanged = true;\n        }\n\n        protected abstract int GetInstructionCount();\n        protected abstract void DoDrawInstruction(ListViewElement el, int controlId);\n        protected abstract void DrawInspectedStacktrace(float availableWidth);\n\n        protected virtual bool isInstructionSelected => m_ListViewState.row >= 0 && m_ListViewState.row < GetInstructionCount();\n\n        protected void DrawStackFrameList(StackFrame[] stackframes, float availableWidth)\n        {\n            if (stackframes != null)\n            {\n                var callstack = \"\";\n                foreach (var stackframe in stackframes)\n                {\n                    if (string.IsNullOrEmpty(stackframe.sourceFile))\n                        continue;\n\n                    var cpos = stackframe.signature.IndexOf('(');\n                    var signature = stackframe.signature.Substring(0, cpos != -1 ? cpos : stackframe.signature.Length);\n\n                    callstack += string.Format(\"{0} [<a href=\\\"{1}\\\" line=\\\"{2}\\\">{1}:{2}</a>]\\n\", signature,\n                        stackframe.sourceFile, stackframe.lineNumber);\n                }\n\n                float height = GUIViewDebuggerWindow.Styles.messageStyle.CalcHeight(GUIContent.Temp(callstack), availableWidth);\n                EditorGUILayout.SelectableLabel(callstack, GUIViewDebuggerWindow.Styles.messageStyle,\n                    GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true), GUILayout.MinHeight(height));\n            }\n        }\n\n        protected void DrawInspectedRect(Rect instructionRect)\n        {\n            var totalRect = GUILayoutUtility.GetRect(0, 100);\n\n            var reserveTopFieldHeight = Mathf.CeilToInt(EditorGUI.kSingleLineHeight * 2 + EditorGUI.kControlVerticalSpacing);\n            var reserveBottomFieldHeight = Mathf.CeilToInt(EditorGUI.kSingleLineHeight);\n            var reserveFieldWidth = 100;\n            var fieldsArea = new RectOffset(50, reserveFieldWidth, reserveTopFieldHeight, reserveBottomFieldHeight);\n            var visualRect = fieldsArea.Remove(totalRect);\n\n            float aspectRatio = instructionRect.width / instructionRect.height;\n            var aspectedRect = new Rect();\n            var dummy = new Rect();\n\n            GUI.CalculateScaledTextureRects(visualRect, ScaleMode.ScaleToFit, aspectRatio, ref aspectedRect, ref dummy);\n            visualRect = aspectedRect;\n            visualRect.width = Mathf.Max(80, visualRect.width);\n            visualRect.height = Mathf.Max(EditorGUI.kSingleLineHeight + 10, visualRect.height);\n\n            var startPointFieldRect = new Rect {height = EditorGUI.kSingleLineHeight, width = fieldsArea.left * 2, y = visualRect.y - fieldsArea.top};\n            startPointFieldRect.x = visualRect.x - startPointFieldRect.width / 2f;\n\n            var endPointFieldRect = new Rect\n            {\n                height = EditorGUI.kSingleLineHeight,\n                width = fieldsArea.right * 2,\n                y = visualRect.yMax\n            };\n            endPointFieldRect.x = visualRect.xMax - endPointFieldRect.width / 2f;\n\n            var widthMarkersArea = new Rect\n            {\n                x = visualRect.x,\n                y = startPointFieldRect.yMax + EditorGUI.kControlVerticalSpacing,\n                width = visualRect.width,\n                height = EditorGUI.kSingleLineHeight\n            };\n\n            var widthFieldRect = widthMarkersArea;\n            widthFieldRect.width = widthMarkersArea.width / 3;\n            widthFieldRect.x = widthMarkersArea.x + (widthMarkersArea.width - widthFieldRect.width) / 2f;\n\n            var heightMarkerArea = visualRect;\n            heightMarkerArea.x = visualRect.xMax;\n            heightMarkerArea.width = EditorGUI.kSingleLineHeight;\n\n            var heightFieldRect = heightMarkerArea;\n            heightFieldRect.height = EditorGUI.kSingleLineHeight;\n            heightFieldRect.width = fieldsArea.right;\n            heightFieldRect.y = heightFieldRect.y + (heightMarkerArea.height - heightFieldRect.height) / 2f;\n\n            //Draw TopLeft point\n            GUI.Label(startPointFieldRect, string.Format(\"({0},{1})\", instructionRect.x, instructionRect.y), Styles.centeredLabel);\n\n            Handles.color = new Color(1, 1, 1, 0.5f);\n            //Draw Width markers and value\n            var startP = new Vector3(widthMarkersArea.x, widthFieldRect.y);\n            var endP = new Vector3(widthMarkersArea.x, widthFieldRect.yMax);\n            Handles.DrawLine(startP, endP);\n\n            startP.x = endP.x = widthMarkersArea.xMax;\n            Handles.DrawLine(startP, endP);\n\n            startP.x = widthMarkersArea.x;\n            startP.y = endP.y = Mathf.Lerp(startP.y, endP.y, .5f);\n            endP.x = widthFieldRect.x;\n            Handles.DrawLine(startP, endP);\n\n            startP.x = widthFieldRect.xMax;\n            endP.x = widthMarkersArea.xMax;\n            Handles.DrawLine(startP, endP);\n\n            GUI.Label(widthFieldRect, instructionRect.width.ToString(CultureInfo.InvariantCulture), Styles.centeredLabel);\n\n            //Draw Height markers and value\n            startP = new Vector3(heightMarkerArea.x, heightMarkerArea.y);\n            endP = new Vector3(heightMarkerArea.xMax, heightMarkerArea.y);\n            Handles.DrawLine(startP, endP);\n\n            startP.y = endP.y = heightMarkerArea.yMax;\n            Handles.DrawLine(startP, endP);\n\n            startP.x = endP.x = Mathf.Lerp(startP.x, endP.x, .5f);\n            startP.y = heightMarkerArea.y;\n            endP.y = heightFieldRect.y;\n            Handles.DrawLine(startP, endP);\n\n            startP.y = heightFieldRect.yMax;\n            endP.y = heightMarkerArea.yMax;\n            Handles.DrawLine(startP, endP);\n\n            GUI.Label(heightFieldRect, instructionRect.height.ToString(CultureInfo.InvariantCulture));\n\n            GUI.Label(endPointFieldRect, string.Format(\"({0},{1})\", instructionRect.xMax, instructionRect.yMax), Styles.centeredLabel);\n\n            //Draws the rect\n            GUI.Box(visualRect, GUIContent.none);\n        }\n\n        protected void DoSelectableInstructionDataField(string label, string instructionData)\n        {\n            var rect = EditorGUILayout.GetControlRect(true);\n            EditorGUI.LabelField(rect, label);\n            rect.xMin += EditorGUIUtility.labelWidth;\n            EditorGUI.SelectableLabel(rect, instructionData);\n        }\n\n        internal abstract void DoDrawSelectedInstructionDetails(int selectedInstructionIndex);\n\n        internal abstract string GetInstructionListName(int index);\n\n        internal abstract void OnDoubleClickInstruction(int index);\n\n        internal abstract void OnSelectedInstructionChanged(int newSelectionIndex);\n\n        void DoDrawNothingSelected()\n        {\n            EditorGUILayout.BeginVertical();\n            GUILayout.FlexibleSpace();\n            GUILayout.Label(Styles.emptyViewLabel, GUIViewDebuggerWindow.Styles.centeredText);\n            GUILayout.FlexibleSpace();\n            EditorGUILayout.EndVertical();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUIDebugger/ElementHighlighter.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    internal class ElementHighlighter\n    {\n        internal static readonly Color kSizePaddingSecondaryColor = new Color(194f / 255, 237f / 255, 138f / 255);\n        internal static readonly Color kSizeSecondaryColor = new Color(139f / 255, 181f / 255, 192f / 255);\n\n        private VisualElement m_PaddingHighlighter;\n        private VisualElement m_ContentHighlighter;\n\n        public bool IsEnabled { get; set; }\n\n        public ElementHighlighter()\n        {\n            IsEnabled = true;\n        }\n\n        public void ClearElement()\n        {\n            if (m_PaddingHighlighter != null && m_PaddingHighlighter.hierarchy.parent != null)\n            {\n                var parent = m_PaddingHighlighter.hierarchy.parent;\n\n                m_PaddingHighlighter.RemoveFromHierarchy();\n                m_ContentHighlighter.RemoveFromHierarchy();\n\n                parent.MarkDirtyRepaint();\n            }\n        }\n\n        public void HighlightElement(VisualElement rootElement, Rect elementRect, GUIStyle style = null)\n        {\n            if (!IsEnabled)\n                return;\n\n            ClearElement();\n\n            if (m_PaddingHighlighter == null)\n            {\n                var borderWidth = 1f;\n                m_PaddingHighlighter = new VisualElement();\n                m_PaddingHighlighter.style.borderLeftColor = kSizePaddingSecondaryColor;\n                m_PaddingHighlighter.style.borderTopColor = kSizePaddingSecondaryColor;\n                m_PaddingHighlighter.style.borderRightColor = kSizePaddingSecondaryColor;\n                m_PaddingHighlighter.style.borderBottomColor = kSizePaddingSecondaryColor;\n                m_PaddingHighlighter.style.borderLeftWidth = borderWidth;\n                m_PaddingHighlighter.style.borderRightWidth = borderWidth;\n                m_PaddingHighlighter.style.borderTopWidth = borderWidth;\n                m_PaddingHighlighter.style.borderBottomWidth = borderWidth;\n                m_PaddingHighlighter.pickingMode = PickingMode.Ignore;\n                m_ContentHighlighter = new VisualElement();\n                m_ContentHighlighter.style.borderLeftColor = kSizeSecondaryColor;\n                m_ContentHighlighter.style.borderTopColor = kSizeSecondaryColor;\n                m_ContentHighlighter.style.borderRightColor = kSizeSecondaryColor;\n                m_ContentHighlighter.style.borderBottomColor = kSizeSecondaryColor;\n                m_ContentHighlighter.style.borderLeftWidth = borderWidth;\n                m_ContentHighlighter.style.borderRightWidth = borderWidth;\n                m_ContentHighlighter.style.borderTopWidth = borderWidth;\n                m_ContentHighlighter.style.borderBottomWidth = borderWidth;\n                m_ContentHighlighter.pickingMode = PickingMode.Ignore;\n            }\n\n            m_PaddingHighlighter.layout = elementRect;\n            rootElement.Add(m_PaddingHighlighter);\n            if (style != null)\n                elementRect = style.padding.Remove(elementRect);\n            m_ContentHighlighter.layout = elementRect;\n            rootElement.Add(m_ContentHighlighter);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUIDebugger/GUIClipInspectView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class GUIClipInspectView : BaseInspectView\n    {\n        Vector2 m_StacktraceScrollPos =  new Vector2();\n\n        List<IMGUIClipInstruction> m_ClipList = new List<IMGUIClipInstruction>();\n\n        public GUIClipInspectView(GUIViewDebuggerWindow guiViewDebuggerWindow) : base(guiViewDebuggerWindow)\n        {\n        }\n\n        public override void UpdateInstructions()\n        {\n            //TODO: find a better approach instead of getting the whole list everyframe.\n            m_ClipList.Clear();\n            GUIViewDebuggerHelper.GetClipInstructions(m_ClipList);\n        }\n\n        public override void ShowOverlay()\n        {\n            if (!isInstructionSelected)\n            {\n                debuggerWindow.ClearInstructionHighlighter();\n                return;\n            }\n\n            var clipInstruction = m_ClipList[listViewState.row];\n            debuggerWindow.HighlightInstruction(debuggerWindow.inspected, clipInstruction.unclippedScreenRect, GUIStyle.none);\n        }\n\n        protected override int GetInstructionCount()\n        {\n            return m_ClipList.Count;\n        }\n\n        protected override void DoDrawInstruction(ListViewElement el, int id)\n        {\n            var clipInstruction = m_ClipList[el.row];\n            var niceName = GetInstructionListName(el.row);\n\n            GUIContent tempContent = GUIContent.Temp(niceName);\n\n            var rect = el.position;\n            rect.xMin += clipInstruction.level * 12;\n\n            GUIViewDebuggerWindow.Styles.listItemBackground.Draw(el.position, false, false, listViewState.row == el.row, false);\n            GUIViewDebuggerWindow.Styles.listItem.Draw(rect, tempContent, id, listViewState.row == el.row);\n        }\n\n        protected override void DrawInspectedStacktrace(float availableWidth)\n        {\n            var clipInstruction = m_ClipList[listViewState.row];\n            m_StacktraceScrollPos = EditorGUILayout.BeginScrollView(m_StacktraceScrollPos, GUIViewDebuggerWindow.Styles.stacktraceBackground, GUILayout.ExpandHeight(false));\n            DrawStackFrameList(clipInstruction.pushStacktrace, availableWidth);\n            EditorGUILayout.EndScrollView();\n        }\n\n        internal override void DoDrawSelectedInstructionDetails(int selectedInstructionIndex)\n        {\n            var clipInstruction = m_ClipList[selectedInstructionIndex];\n\n            DoSelectableInstructionDataField(\"RenderOffset\", clipInstruction.renderOffset.ToString());\n            DoSelectableInstructionDataField(\"ResetOffset\", clipInstruction.resetOffset.ToString());\n            DoSelectableInstructionDataField(\"screenRect\", clipInstruction.screenRect.ToString());\n            DoSelectableInstructionDataField(\"scrollOffset\", clipInstruction.scrollOffset.ToString());\n        }\n\n        internal override string GetInstructionListName(int index)\n        {\n            var clipInstruction = m_ClipList[index];\n            var stacktrace = clipInstruction.pushStacktrace;\n\n            if (stacktrace.Length == 0)\n                return \"Empty\";\n\n            int frameIndex = GetInterestingFrameIndex(stacktrace);\n\n            StackFrame interestingFrame = stacktrace[frameIndex];\n            string methodName = interestingFrame.methodName;\n            return methodName;\n        }\n\n        internal override void OnDoubleClickInstruction(int index) {}\n\n        internal override void OnSelectedInstructionChanged(int index)\n        {\n            listViewState.row = index;\n            ShowOverlay();\n        }\n\n        int GetInterestingFrameIndex(StackFrame[] stacktrace)\n        {\n            string currentProjectPath = Application.dataPath;\n\n            int index = -1;\n\n            for (int i = 0; i < stacktrace.Length; ++i)\n            {\n                StackFrame sf = stacktrace[i];\n                if (string.IsNullOrEmpty(sf.sourceFile))\n                    continue;\n                if (sf.signature.StartsWith(\"UnityEngine.GUIClip\"))\n                    continue;\n\n                if (index == -1)\n                    index = i;\n\n                if (sf.sourceFile.StartsWith(currentProjectPath))\n                    return i;\n            }\n\n            if (index != -1)\n                return index;\n\n            return stacktrace.Length - 1;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUIDebugger/GUILayoutInspectView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class GUILayoutInspectView : BaseInspectView\n    {\n        Vector2 m_StacktraceScrollPos = new Vector2();\n\n        readonly List<IMGUILayoutInstruction> m_LayoutInstructions = new List<IMGUILayoutInstruction>();\n\n        GUIStyle m_FakeMarginStyleForOverlay = new GUIStyle();\n\n        public GUILayoutInspectView(GUIViewDebuggerWindow guiViewDebuggerWindow) : base(guiViewDebuggerWindow)\n        {\n        }\n\n        public override void UpdateInstructions()\n        {\n            m_LayoutInstructions.Clear();\n            GUIViewDebuggerHelper.GetLayoutInstructions(m_LayoutInstructions);\n        }\n\n        public override void ShowOverlay()\n        {\n            if (!isInstructionSelected)\n            {\n                debuggerWindow.ClearInstructionHighlighter();\n                return;\n            }\n\n            IMGUILayoutInstruction instruction = m_LayoutInstructions[listViewState.row];\n\n            RectOffset offset = new RectOffset();\n            offset.left = instruction.marginLeft;\n            offset.right = instruction.marginRight;\n            offset.top = instruction.marginTop;\n            offset.bottom = instruction.marginBottom;\n\n            //TODO: right now the overlay only know about padding\n            //For now we just save margin into padding\n            //while the overlay isn't improved.\n            m_FakeMarginStyleForOverlay.padding = offset;\n\n            Rect rect = instruction.unclippedRect;\n\n            rect = offset.Add(rect);\n\n            debuggerWindow.HighlightInstruction(debuggerWindow.inspected, rect, m_FakeMarginStyleForOverlay);\n        }\n\n        protected override int GetInstructionCount()\n        {\n            return m_LayoutInstructions.Count;\n        }\n\n        protected override void DoDrawInstruction(ListViewElement el, int id)\n        {\n            IMGUILayoutInstruction instruction = m_LayoutInstructions[el.row];\n\n            GUIContent tempContent = GUIContent.Temp(GetInstructionListName(el.row));\n\n            var rect = el.position;\n            rect.xMin += instruction.level * 10;\n\n            GUIViewDebuggerWindow.Styles.listItemBackground.Draw(rect, false, false, listViewState.row == el.row, false);\n            GUIViewDebuggerWindow.Styles.listItem.Draw(rect, tempContent, id, listViewState.row == el.row);\n        }\n\n        protected override void DrawInspectedStacktrace(float availableWidth)\n        {\n            IMGUILayoutInstruction instruction = m_LayoutInstructions[listViewState.row];\n\n            m_StacktraceScrollPos = EditorGUILayout.BeginScrollView(m_StacktraceScrollPos, GUIViewDebuggerWindow.Styles.stacktraceBackground, GUILayout.ExpandHeight(false));\n            DrawStackFrameList(instruction.stack, availableWidth);\n            EditorGUILayout.EndScrollView();\n        }\n\n        internal override void DoDrawSelectedInstructionDetails(int selectedInstructionIndex)\n        {\n            IMGUILayoutInstruction instruction = m_LayoutInstructions[selectedInstructionIndex];\n\n            using (new EditorGUI.DisabledScope(true))\n                DrawInspectedRect(instruction.unclippedRect);\n\n            DoSelectableInstructionDataField(\"margin.left\", instruction.marginLeft.ToString());\n            DoSelectableInstructionDataField(\"margin.top\", instruction.marginTop.ToString());\n            DoSelectableInstructionDataField(\"margin.right\", instruction.marginRight.ToString());\n            DoSelectableInstructionDataField(\"margin.bottom\", instruction.marginBottom.ToString());\n\n            if (instruction.style != null)\n                DoSelectableInstructionDataField(\"Style Name\", instruction.style.name);\n\n            if (instruction.isGroup == 1)\n                return;\n\n            DoSelectableInstructionDataField(\"IsVertical\", (instruction.isVertical == 1).ToString());\n        }\n\n        internal override string GetInstructionListName(int index)\n        {\n            IMGUILayoutInstruction instruction = m_LayoutInstructions[index];\n            var stacktrace = instruction.stack;\n\n            int frameIndex = GetInterestingFrameIndex(stacktrace);\n\n            if (frameIndex > 0)\n                --frameIndex;\n\n            StackFrame interestingFrame = stacktrace[frameIndex];\n            string methodName = interestingFrame.methodName;\n            return methodName;\n        }\n\n        internal override void OnDoubleClickInstruction(int index) {}\n\n        internal override void OnSelectedInstructionChanged(int index)\n        {\n            listViewState.row = index;\n            ShowOverlay();\n        }\n\n        int GetInterestingFrameIndex(StackFrame[] stacktrace)\n        {\n            //We try to find the first frame that belongs to the user project.\n            //If there is no frame inside the user project, we will return the first frame outside any class starting with:\n            // - UnityEngine.GUILayoutUtility\n            string currentProjectPath = Application.dataPath;\n\n            int index = -1;\n\n            for (int i = 0; i < stacktrace.Length; ++i)\n            {\n                StackFrame sf = stacktrace[i];\n                if (string.IsNullOrEmpty(sf.sourceFile))\n                    continue;\n                if (sf.signature.StartsWith(\"UnityEngine.GUIDebugger\"))\n                    continue;\n                if (sf.signature.StartsWith(\"UnityEngine.GUILayoutUtility\"))\n                    continue;\n\n                if (index == -1)\n                    index = i;\n\n                if (sf.sourceFile.StartsWith(currentProjectPath))\n                    return i;\n            }\n\n            if (index != -1)\n                return index;\n\n            return stacktrace.Length - 1;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUIDebugger/GUINamedControlInspectView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class GUINamedControlInspectView : BaseInspectView\n    {\n        private readonly List<IMGUINamedControlInstruction> m_NamedControlInstructions = new List<IMGUINamedControlInstruction>();\n\n        private GUIStyle m_FakeMargingStyleForOverlay = new GUIStyle();\n\n        public GUINamedControlInspectView(GUIViewDebuggerWindow guiViewDebuggerWindow) : base(guiViewDebuggerWindow)\n        {\n        }\n\n        public override void UpdateInstructions()\n        {\n            m_NamedControlInstructions.Clear();\n            GUIViewDebuggerHelper.GetNamedControlInstructions(m_NamedControlInstructions);\n        }\n\n        protected override int GetInstructionCount()\n        {\n            return m_NamedControlInstructions.Count;\n        }\n\n        protected override void DoDrawInstruction(ListViewElement el, int id)\n        {\n            GUIContent tempContent = GUIContent.Temp(GetInstructionListName(el.row));\n\n            var rect = el.position;\n\n            GUIViewDebuggerWindow.Styles.listItemBackground.Draw(rect, false, false, listViewState.row == el.row, false);\n            GUIViewDebuggerWindow.Styles.listItem.Draw(rect, tempContent, id, listViewState.row == el.row);\n        }\n\n        internal override string GetInstructionListName(int index)\n        {\n            IMGUINamedControlInstruction instruction = m_NamedControlInstructions[index];\n            return \"\\\"\" + instruction.name + \"\\\"\";\n        }\n\n        internal override void OnDoubleClickInstruction(int index) {}\n\n        protected override void DrawInspectedStacktrace(float availableWidth)\n        {\n        }\n\n        internal override void DoDrawSelectedInstructionDetails(int index)\n        {\n            var instruction = m_NamedControlInstructions[listViewState.row];\n\n            using (new EditorGUI.DisabledScope(true))\n                DrawInspectedRect(instruction.rect);\n            DoSelectableInstructionDataField(\"Name\", instruction.name);\n            DoSelectableInstructionDataField(\"ID\", instruction.id.ToString());\n        }\n\n        internal override void OnSelectedInstructionChanged(int index)\n        {\n            listViewState.row = index;\n            ShowOverlay();\n        }\n\n        public override void ShowOverlay()\n        {\n            if (!isInstructionSelected)\n            {\n                debuggerWindow.ClearInstructionHighlighter();\n                return;\n            }\n\n            var instruction = m_NamedControlInstructions[listViewState.row];\n\n            debuggerWindow.HighlightInstruction(debuggerWindow.inspected, instruction.rect, m_FakeMargingStyleForOverlay);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUIDebugger/GUIPropertyInspectView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class GUIPropertyInspectView : BaseInspectView\n    {\n        Vector2 m_StacktraceScrollPos =  new Vector2();\n        private GUIStyle m_FakeMargingStyleForOverlay = new GUIStyle();\n\n        List<IMGUIPropertyInstruction> m_PropertyList = new List<IMGUIPropertyInstruction>();\n\n        public GUIPropertyInspectView(GUIViewDebuggerWindow guiViewDebuggerWindow) : base(guiViewDebuggerWindow)\n        {\n        }\n\n        public override void UpdateInstructions()\n        {\n            //TODO: find a better approach instead of getting the whole list everyframe.\n            m_PropertyList.Clear();\n            GUIViewDebuggerHelper.GetPropertyInstructions(m_PropertyList);\n        }\n\n        public override void ShowOverlay()\n        {\n            if (!isInstructionSelected)\n            {\n                debuggerWindow.ClearInstructionHighlighter();\n                return;\n            }\n\n            var property = m_PropertyList[listViewState.row];\n            debuggerWindow.HighlightInstruction(debuggerWindow.inspected, property.rect, m_FakeMargingStyleForOverlay);\n        }\n\n        protected override int GetInstructionCount()\n        {\n            return m_PropertyList.Count;\n        }\n\n        protected override void DoDrawInstruction(ListViewElement el, int id)\n        {\n            GUIContent tempContent = GUIContent.Temp(GetInstructionListName(el.row));\n\n            var rect = el.position;\n\n            GUIViewDebuggerWindow.Styles.listItemBackground.Draw(rect, false, false, listViewState.row == el.row, false);\n            GUIViewDebuggerWindow.Styles.listItem.Draw(rect, tempContent, id, listViewState.row == el.row);\n        }\n\n        protected override void DrawInspectedStacktrace(float availableWidth)\n        {\n            var clipInstruction = m_PropertyList[listViewState.row];\n            m_StacktraceScrollPos = EditorGUILayout.BeginScrollView(m_StacktraceScrollPos, GUIViewDebuggerWindow.Styles.stacktraceBackground, GUILayout.ExpandHeight(false));\n            DrawStackFrameList(clipInstruction.beginStacktrace, availableWidth);\n            EditorGUILayout.EndScrollView();\n        }\n\n        internal override void DoDrawSelectedInstructionDetails(int selectedInstructionIndex)\n        {\n            var property = m_PropertyList[listViewState.row];\n\n            using (new EditorGUI.DisabledScope(true))\n                DrawInspectedRect(property.rect);\n\n            DoSelectableInstructionDataField(\"Target Type Name\", property.targetTypeName);\n            DoSelectableInstructionDataField(\"Path\", property.path);\n        }\n\n        internal override string GetInstructionListName(int index)\n        {\n            var clipInstruction = m_PropertyList[index];\n            return clipInstruction.path;\n        }\n\n        internal override void OnDoubleClickInstruction(int index) {}\n\n        internal override void OnSelectedInstructionChanged(int index)\n        {\n            listViewState.row = index;\n            ShowOverlay();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUIDebugger/GUIViewDebuggerHelper.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\nusing System;\nnamespace UnityEditor\n{\n    [RequiredByNativeCode]\n    internal struct IMGUIDrawInstruction\n    {\n        public Rect         rect;\n        public Rect         visibleRect;\n        public GUIStyle     usedGUIStyle;\n        public GUIContent   usedGUIContent;\n        public string       label;\n        public StackFrame[] stackframes;\n\n        public void Reset()\n        {\n            rect = new Rect();\n            visibleRect = new Rect();\n            usedGUIStyle = GUIStyle.none;\n            usedGUIContent = GUIContent.none;\n        }\n    }\n    [RequiredByNativeCode]\n    internal struct IMGUIClipInstruction\n    {\n        public Rect screenRect;\n        public Rect unclippedScreenRect;\n        public Vector2 scrollOffset;\n        public Vector2 renderOffset;\n        public bool resetOffset;\n        public int level;\n\n        public StackFrame[] pushStacktrace;\n        public StackFrame[] popStacktrace;\n    }\n\n    [RequiredByNativeCode]\n    internal struct IMGUILayoutInstruction\n    {\n        public int level;\n        public Rect unclippedRect;\n\n        public int marginLeft;\n        public int marginRight;\n        public int marginTop;\n        public int marginBottom;\n\n        public GUIStyle style;\n\n\n        public StackFrame[] stack;\n\n        public int isGroup;\n        public int isVertical;\n    }\n\n    [RequiredByNativeCode]\n    internal struct IMGUINamedControlInstruction\n    {\n        public string name;\n        public Rect rect;\n        public int id;\n    }\n\n    [RequiredByNativeCode]\n    internal struct IMGUIPropertyInstruction\n    {\n        public string targetTypeName;\n        public string path;\n        public Rect rect;\n        public StackFrame[] beginStacktrace;\n        public StackFrame[] endStacktrace;\n    }\n\n    //unified\n    internal enum InstructionType\n    {\n        kStyleDraw = 1,\n        kClipPush = 2,\n        kClipPop = 3,\n        kLayoutBeginGroup = 4,\n        kLayoutEndGroup = 5,\n        kLayoutEntry = 6,\n        kPropertyBegin = 7,\n        kPropertyEnd = 8,\n        kLayoutNamedControl = 9\n    }\n\n    //TODO: we are symbolicating the stacktraces of all instructions,\n    //and even worse, we do it everyframe.\n    //We should load the stacktrace info lazily.\n\n    [RequiredByNativeCode]\n    internal struct IMGUIInstruction\n    {\n        public InstructionType type;\n        public int level;\n        public Rect unclippedRect;\n        public StackFrame[] stack;\n\n        public int typeInstructionIndex;\n        public bool enabled;\n    }\n\n    [NativeHeader(\"Editor/Mono/GUIDebugger/GUIViewDebuggerHelper.bindings.h\")]\n    [UsedByNativeCode]\n    internal static partial class GUIViewDebuggerHelper\n    {\n        [NativeThrows]\n        static internal extern void GetViews(List<GUIView> views);\n\n        static internal extern void DebugWindow([Unmarshalled] GUIView view);\n\n        [FreeFunction(\"GetGUIDebuggerManager().StopDebuggingAll\")]\n        static internal extern void StopDebugging();\n\n        [RequiredByNativeCode]\n        private static GUIContent CreateGUIContent(string text, Texture image, string tooltip)\n        {\n            return new GUIContent(text, image, tooltip);\n        }\n\n        internal static extern void GetDrawInstructions(List<IMGUIDrawInstruction> drawInstructions, bool includeStackTraces = true);\n\n        internal static extern void GetClipInstructions(List<IMGUIClipInstruction> clipInstructions, bool includeStackTraces = true);\n\n        internal static extern void GetNamedControlInstructions(List<IMGUINamedControlInstruction> namedControlInstructions);\n\n        internal static extern void GetPropertyInstructions(List<IMGUIPropertyInstruction> namedControlInstructions, bool includeStackTraces = true);\n\n        internal static extern void GetLayoutInstructions(List<IMGUILayoutInstruction> layoutInstructions, bool includeStackTraces = true);\n\n        internal static extern void GetUnifiedInstructions(List<IMGUIInstruction> layoutInstructions, bool includeStackTraces = true);\n\n        [FreeFunction(\"GetGUIDebuggerManager().ClearInstructions\")]\n        internal static extern void ClearInstructions();\n    }\n} //namespace\n"
  },
  {
    "path": "Editor/Mono/GUIDebugger/GUIViewDebuggerWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    class GUIViewDebuggerWindow : EditorWindow\n    {\n        enum InstructionType\n        {\n            Draw,\n            Clip,\n            Layout,\n            NamedControl,\n            Property,\n            Unified,\n        }\n\n        internal static class Styles\n        {\n            public static readonly string defaultWindowPopupText = \"<Please Select>\";\n\n            public static readonly GUIContent inspectedWindowLabel = EditorGUIUtility.TrTextContent(\"Inspected View: \");\n            public static readonly GUIContent pickStyleLabel = EditorGUIUtility.TrTextContent(\"Pick Style\");\n            public static readonly GUIContent pickingStyleLabel = EditorGUIUtility.TrTextContent(\"Picking   \");\n\n            public static readonly GUIStyle listItem = \"PR Label\";\n            public static readonly GUIStyle listItemBackground = \"CN EntryBackOdd\";\n            public static readonly GUIStyle listBackgroundStyle = \"ScrollViewAlt\";\n            public static readonly GUIStyle boxStyle = \"CN Box\";\n            public static readonly GUIStyle messageStyle = \"CN Message\";\n            public static readonly GUIStyle stackframeStyle = \"CN StacktraceStyle\";\n            public static readonly GUIStyle stacktraceBackground = \"CN StacktraceBackground\";\n            public static readonly GUIStyle centeredText = \"CN CenteredText\";\n\n            public static readonly Color contentHighlighterColor = new Color(0.62f, 0.77f, 0.90f, 0.5f);\n            public static readonly Color paddingHighlighterColor = new Color(0.76f, 0.87f, 0.71f, 0.5f);\n        }\n\n        static GUIViewDebuggerWindow s_ActiveInspector;\n\n        static EditorWindow GetEditorWindow(GUIView view)\n        {\n            var hostView = view as HostView;\n            if (hostView != null)\n                return hostView.actualView;\n\n            return null;\n        }\n\n        static string GetViewName(GUIView view)\n        {\n            var editorWindow = GetEditorWindow(view);\n            if (editorWindow != null)\n                return editorWindow.titleContent.text;\n\n            return view.GetType().Name;\n        }\n\n        public GUIView inspected\n        {\n            get\n            {\n                if (m_Inspected != null || m_InspectedEditorWindow == null)\n                    return m_Inspected;\n                // continue inspecting the same window if its dock area is destroyed by e.g., docking or undocking it\n                return inspected = m_InspectedEditorWindow.m_Parent;\n            }\n            private set\n            {\n                if (m_Inspected != value)\n                {\n                    ClearInstructionHighlighter();\n\n                    m_Inspected = value;\n                    if (m_Inspected != null)\n                    {\n                        m_InspectedEditorWindow = (m_Inspected is HostView) ? ((HostView)m_Inspected).actualView : null;\n                        if (!m_StylePicker.IsPicking)\n                            GUIViewDebuggerHelper.DebugWindow(m_Inspected);\n                        m_Inspected.Repaint();\n                    }\n                    else\n                    {\n                        m_InspectedEditorWindow = null;\n                        GUIViewDebuggerHelper.StopDebugging();\n                    }\n                    if (instructionModeView != null)\n                        instructionModeView.ClearRowSelection();\n\n                    OnInspectedViewChanged();\n                }\n            }\n        }\n        [SerializeField]\n        GUIView m_Inspected;\n        EditorWindow m_InspectedEditorWindow;\n        ElementHighlighter m_Highlighter;\n        StylePicker m_StylePicker;\n\n        public IBaseInspectView instructionModeView { get { return m_InstructionModeView; } }\n        IBaseInspectView m_InstructionModeView;\n\n        protected GUIViewDebuggerWindow()\n        {\n            m_InstructionModeView = new StyleDrawInspectView(this);\n            m_Highlighter = new ElementHighlighter();\n            m_StylePicker = new StylePicker(this, m_Highlighter);\n            m_StylePicker.CanInspectView = CanInspectView;\n        }\n\n        public void ClearInstructionHighlighter()\n        {\n            if (m_StylePicker != null && !m_StylePicker.IsPicking)\n                m_Highlighter.ClearElement();\n        }\n\n        public void HighlightInstruction(GUIView view, Rect instructionRect, GUIStyle style)\n        {\n            if (!m_ShowHighlighter)\n                return;\n\n            ClearInstructionHighlighter();\n\n            var visualElement = view.windowBackend.visualTree as VisualElement;\n            if (visualElement == null)\n                return;\n            m_Highlighter.HighlightElement(visualElement, instructionRect, style);\n        }\n\n        InstructionType instructionType\n        {\n            get { return m_InstructionType; }\n            set\n            {\n                if (m_InstructionType != value || m_InstructionModeView == null)\n                {\n                    m_InstructionType = value;\n                    switch (m_InstructionType)\n                    {\n                        case InstructionType.Clip:\n                            m_InstructionModeView = new GUIClipInspectView(this);\n                            break;\n                        case InstructionType.Draw:\n                            m_InstructionModeView = new StyleDrawInspectView(this);\n                            break;\n                        case InstructionType.Layout:\n                            m_InstructionModeView = new GUILayoutInspectView(this);\n                            break;\n                        case InstructionType.NamedControl:\n                            m_InstructionModeView = new GUINamedControlInspectView(this);\n                            break;\n                        case InstructionType.Property:\n                            m_InstructionModeView = new GUIPropertyInspectView(this);\n                            break;\n                        case InstructionType.Unified:\n                            m_InstructionModeView = new UnifiedInspectView(this);\n                            break;\n                    }\n                    m_InstructionModeView.UpdateInstructions();\n                }\n            }\n        }\n        [SerializeField]\n        InstructionType m_InstructionType = InstructionType.Draw;\n\n        [SerializeField]\n        bool m_ShowHighlighter = true;\n\n        [SerializeField]\n        private bool m_InspectOptimizedGUIBlocks = false;\n\n        //TODO: figure out proper minimum values and make sure the window also has compatible minimum size\n        readonly SplitterState m_InstructionListDetailSplitter = SplitterState.FromRelative(new float[] { 30, 70 }, new float[] { 32, 32 }, null);\n\n        [RequiredByNativeCode]\n        [MenuItem(\"Window/Analysis/IMGUI Debugger\", false, 20002, false)]\n        static void InitDebuggerWindow()\n        {\n            // Get existing open window or if none, make a new one:\n            if (s_ActiveInspector == null)\n            {\n                GUIViewDebuggerWindow window = (GUIViewDebuggerWindow)GetWindow(typeof(GUIViewDebuggerWindow));\n                s_ActiveInspector = window;\n            }\n            s_ActiveInspector.Show();\n        }\n\n        void OnEnable()\n        {\n            titleContent =  EditorGUIUtility.TrTextContent(\"IMGUI Debugger\");\n            GUIViewDebuggerHelper.onViewInstructionsChanged += OnInspectedViewChanged;\n            GUIViewDebuggerHelper.onDebuggingViewchanged += OnDebuggedViewChanged;\n            GUIView serializedInspected = m_Inspected;\n            inspected = null;\n            inspected = serializedInspected;\n            m_InstructionModeView = null;\n            instructionType = m_InstructionType;\n        }\n\n        void OnDestroy()\n        {\n            if (m_StylePicker != null)\n            {\n                m_StylePicker.StopExploreStyle();\n                m_StylePicker = null;\n            }\n        }\n\n        void OnDisable()\n        {\n            GUIViewDebuggerHelper.onViewInstructionsChanged -= OnInspectedViewChanged;\n            GUIViewDebuggerHelper.onDebuggingViewchanged -= OnDebuggedViewChanged;\n            inspected = null;\n            if (m_StylePicker != null)\n                m_StylePicker.StopExploreStyle();\n        }\n\n        void OnBecameVisible()\n        {\n            OnShowOverlayChanged();\n        }\n\n        void OnBecameInvisible()\n        {\n            ClearInstructionHighlighter();\n        }\n\n        void OnGUI()\n        {\n            HandleStylePicking();\n            DoToolbar();\n            ShowDrawInstructions();\n        }\n\n        private bool m_FlushingOptimizedGUIBlock;\n\n        void OnDebuggedViewChanged(GUIView view, bool isDebugged)\n        {\n            if (!m_StylePicker.IsPicking && isDebugged && inspected != view)\n            {\n                inspected = view;\n            }\n        }\n\n        void OnInspectedViewChanged()\n        {\n            if (m_InspectOptimizedGUIBlocks && !m_FlushingOptimizedGUIBlock)\n            {\n                var inspector = m_InspectedEditorWindow as InspectorWindow;\n                if (inspector != null && inspector.tracker != null)\n                {\n                    m_FlushingOptimizedGUIBlock = true;\n                    foreach (var editor in inspector.tracker.activeEditors)\n                        editor.isInspectorDirty = true;\n                    inspector.Repaint();\n                }\n            }\n            m_FlushingOptimizedGUIBlock = false;\n            RefreshData();\n            Repaint();\n        }\n\n        void HandleStylePicking()\n        {\n            if (m_StylePicker != null && m_StylePicker.IsPicking)\n            {\n                m_StylePicker.OnGUI();\n                if (Event.current.type == EventType.Ignore || Event.current.type == EventType.MouseUp)\n                {\n                    m_StylePicker.StopExploreStyle();\n                }\n\n                if (m_StylePicker.ExploredView != null && inspected != m_StylePicker.ExploredView)\n                {\n                    inspected = m_StylePicker.ExploredView;\n                }\n            }\n        }\n\n        void DoToolbar()\n        {\n            GUILayout.BeginHorizontal(EditorStyles.toolbar);\n\n            DoWindowPopup();\n            DoInspectTypePopup();\n            DoInstructionOverlayToggle();\n            DoOptimizedGUIBlockToggle();\n            DoStylePicker();\n\n            GUILayout.EndHorizontal();\n        }\n\n        bool CanInspectView(GUIView view)\n        {\n            if (view == null)\n                return false;\n\n            EditorWindow editorWindow = GetEditorWindow(view);\n            if (editorWindow == null)\n                return true;\n\n            if (editorWindow == this)\n                return false;\n\n            return true;\n        }\n\n        void DoWindowPopup()\n        {\n            string selectedName = inspected == null ? Styles.defaultWindowPopupText : GetViewName(inspected);\n\n            GUILayout.Label(Styles.inspectedWindowLabel, GUILayout.ExpandWidth(false));\n\n            Rect popupPosition = GUILayoutUtility.GetRect(GUIContent.Temp(selectedName), EditorStyles.toolbarDropDown, GUILayout.ExpandWidth(true));\n            if (GUI.Button(popupPosition, GUIContent.Temp(selectedName), EditorStyles.toolbarDropDown))\n            {\n                List<GUIView> views = new List<GUIView>();\n                GUIViewDebuggerHelper.GetViews(views);\n\n                List<GUIContent> options = new List<GUIContent>(views.Count + 1);\n\n                options.Add(EditorGUIUtility.TrTextContent(\"None\"));\n\n                int selectedIndex = 0;\n                List<GUIView> selectableViews = new List<GUIView>(views.Count + 1);\n                for (int i = 0; i < views.Count; ++i)\n                {\n                    GUIView view = views[i];\n\n                    //We can't inspect ourselves, otherwise we get infinite recursion.\n                    //Also avoid the InstructionOverlay\n                    if (!CanInspectView(view))\n                        continue;\n\n                    GUIContent label = new GUIContent(string.Format(\"{0}. {1}\", options.Count,  GetViewName(view)));\n                    options.Add(label);\n                    selectableViews.Add(view);\n\n                    if (view == inspected)\n                        selectedIndex = selectableViews.Count;\n                }\n                //TODO: convert this to a Unity Window style popup. This way we could highlight the window on hover ;)\n                EditorUtility.DisplayCustomMenu(popupPosition, options.ToArray(), selectedIndex, OnWindowSelected, selectableViews);\n            }\n        }\n\n        void DoInspectTypePopup()\n        {\n            EditorGUI.BeginChangeCheck();\n            var newInstructionType = (InstructionType)EditorGUILayout.EnumPopup(m_InstructionType, EditorStyles.toolbarDropDown);\n            if (EditorGUI.EndChangeCheck())\n                instructionType = newInstructionType;\n        }\n\n        void DoInstructionOverlayToggle()\n        {\n            EditorGUI.BeginChangeCheck();\n            m_ShowHighlighter = GUILayout.Toggle(m_ShowHighlighter, GUIContent.Temp(\"Show Overlay\"), EditorStyles.toolbarButton);\n            if (EditorGUI.EndChangeCheck())\n            {\n                OnShowOverlayChanged();\n            }\n        }\n\n        void DoOptimizedGUIBlockToggle()\n        {\n            EditorGUI.BeginChangeCheck();\n            m_InspectOptimizedGUIBlocks = GUILayout.Toggle(m_InspectOptimizedGUIBlocks, GUIContent.Temp(\"Force Inspect Optimized GUI Blocks\"), EditorStyles.toolbarButton);\n            if (EditorGUI.EndChangeCheck())\n                OnInspectedViewChanged();\n        }\n\n        void DoStylePicker()\n        {\n            var pickerRect = GUILayoutUtility.GetRect(Styles.pickStyleLabel, EditorStyles.toolbarButtonRight);\n            if (!m_StylePicker.IsPicking && Event.current.isMouse && Event.current.type == EventType.MouseDown && pickerRect.Contains(Event.current.mousePosition))\n            {\n                m_StylePicker.StartExploreStyle();\n            }\n            GUI.Toggle(pickerRect, m_StylePicker.IsPicking, m_StylePicker.IsPicking ? Styles.pickingStyleLabel : Styles.pickStyleLabel, EditorStyles.toolbarButtonRight);\n        }\n\n        void OnShowOverlayChanged()\n        {\n            if (m_ShowHighlighter == false)\n            {\n                ClearInstructionHighlighter();\n            }\n            else\n            {\n                if (inspected != null)\n                {\n                    instructionModeView.ShowOverlay();\n                }\n            }\n        }\n\n        void OnWindowSelected(object userdata, string[] options, int selected)\n        {\n            selected--;\n            inspected = selected < 0 ? null : ((List<GUIView>)userdata)[selected];\n        }\n\n        void RefreshData()\n        {\n            instructionModeView.UpdateInstructions();\n        }\n\n        void ShowDrawInstructions()\n        {\n            if (inspected == null)\n            {\n                ClearInstructionHighlighter();\n                return;\n            }\n\n            SplitterGUILayout.BeginHorizontalSplit(m_InstructionListDetailSplitter);\n\n            instructionModeView.DrawInstructionList();\n\n            EditorGUILayout.BeginVertical();\n            {\n                if (m_StylePicker.IsPicking &&\n                    m_StylePicker.ExploredDrawInstructionIndex != -1 &&\n                    m_InstructionType == InstructionType.Draw)\n                {\n                    m_InstructionModeView.ClearRowSelection();\n                    m_InstructionModeView.SelectRow(m_StylePicker.ExploredDrawInstructionIndex);\n                }\n                instructionModeView.DrawSelectedInstructionDetails(position.width - m_InstructionListDetailSplitter.realSizes[0]);\n            }\n            EditorGUILayout.EndVertical();\n\n            SplitterGUILayout.EndHorizontalSplit();\n\n            EditorGUIUtility.DrawHorizontalSplitter(new Rect(m_InstructionListDetailSplitter.realSizes[0] + 1, EditorGUI.kWindowToolbarHeight, 1, position.height));\n        }\n    }\n\n    //This needs to match ManagedStackFrameToMono in native\n    [StructLayout(LayoutKind.Sequential)]\n    struct StackFrame\n    {\n        public uint   lineNumber;\n        public string sourceFile;\n        public string methodName;\n        public string signature;\n        public string moduleName; //TODO: we only get \"Mono JIT Code\" or \"wrapper something\", can we get the actual assembly name?\n    }\n\n    internal static partial class GUIViewDebuggerHelper\n    {\n        internal static event Action onViewInstructionsChanged = null;\n        internal static event Action<GUIView, bool> onDebuggingViewchanged = null;\n\n        [RequiredByNativeCode]\n        private static void CallOnViewInstructionsChanged()\n        {\n            onViewInstructionsChanged?.Invoke();\n        }\n\n        [RequiredByNativeCode]\n        private static void CallDebuggingViewChanged(GUIView view, bool isBeingDebugged)\n        {\n            onDebuggingViewchanged?.Invoke(view, isBeingDebugged);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUIDebugger/StyleDrawInspectView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    //The only purpose of this class is to enable us to view the used GUIStyle\n    //using Serialized Properties.\n    class GUIStyleHolder : ScriptableObject\n    {\n        public GUIStyle inspectedStyle;\n\n        protected GUIStyleHolder() {}\n    }\n\n    class StyleDrawInspectView : BaseInspectView\n    {\n        [Serializable]\n        class CachedInstructionInfo\n        {\n            public SerializedObject        styleContainerSerializedObject = null;\n            public SerializedProperty      styleSerializedProperty = null;\n            public readonly GUIStyleHolder styleContainer;\n\n            public CachedInstructionInfo()\n            {\n                styleContainer = ScriptableObject.CreateInstance<GUIStyleHolder>();\n            }\n        }\n\n        Vector2 m_StacktraceScrollPos =  new Vector2();\n\n        [NonSerialized] List<IMGUIDrawInstruction> m_Instructions = new List<IMGUIDrawInstruction>();\n        [NonSerialized] IMGUIDrawInstruction m_Instruction;\n        [NonSerialized] CachedInstructionInfo m_CachedInstructionInfo;\n\n        public StyleDrawInspectView(GUIViewDebuggerWindow guiViewDebuggerWindow) : base(guiViewDebuggerWindow)\n        {\n        }\n\n        public override void UpdateInstructions()\n        {\n            m_Instructions.Clear();\n            GUIViewDebuggerHelper.GetDrawInstructions(m_Instructions);\n        }\n\n        public override void ClearRowSelection()\n        {\n            base.ClearRowSelection();\n            m_CachedInstructionInfo = null;\n        }\n\n        public override void ShowOverlay()\n        {\n            if (m_CachedInstructionInfo != null)\n                debuggerWindow.HighlightInstruction(debuggerWindow.inspected, m_Instruction.rect, m_Instruction.usedGUIStyle);\n        }\n\n        protected override int GetInstructionCount()\n        {\n            return m_Instructions.Count;\n        }\n\n        protected override void DoDrawInstruction(ListViewElement el, int id)\n        {\n            string listDisplayName = GetInstructionListName(el.row);\n            GUIContent tempContent = GUIContent.Temp(listDisplayName);\n\n            GUIViewDebuggerWindow.Styles.listItemBackground.Draw(el.position, false, false, listViewState.row == el.row, false);\n\n            GUIViewDebuggerWindow.Styles.listItem.Draw(el.position, tempContent, id, listViewState.row == el.row);\n        }\n\n        protected override void DrawInspectedStacktrace(float availableWidth)\n        {\n            m_StacktraceScrollPos = EditorGUILayout.BeginScrollView(m_StacktraceScrollPos, GUIViewDebuggerWindow.Styles.stacktraceBackground, GUILayout.ExpandHeight(false));\n            DrawStackFrameList(m_Instruction.stackframes, availableWidth);\n            EditorGUILayout.EndScrollView();\n        }\n\n        protected override bool isInstructionSelected { get { return m_CachedInstructionInfo != null; } }\n\n        internal override void DoDrawSelectedInstructionDetails(int selectedInstructionIndex)\n        {\n            using (new EditorGUI.DisabledScope(true))\n                DrawInspectedRect(m_Instruction.rect);\n\n            DoSelectableInstructionDataField(\"VisibleRect\", m_Instruction.visibleRect.ToString());\n            EditorGUILayout.Space();\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_CachedInstructionInfo.styleSerializedProperty, GUIContent.Temp(\"Style\"), true);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_CachedInstructionInfo.styleContainerSerializedObject.ApplyModifiedPropertiesWithoutUndo();\n                debuggerWindow.inspected.Repaint();\n            }\n\n            GUILayout.Label(GUIContent.Temp(\"GUIContent\"));\n            using (new EditorGUI.IndentLevelScope())\n            {\n                DoSelectableInstructionDataField(\"Text\", m_Instruction.usedGUIContent.text);\n                DoSelectableInstructionDataField(\"Tooltip\", m_Instruction.usedGUIContent.tooltip);\n                using (new EditorGUI.DisabledScope(true))\n                    EditorGUILayout.ObjectField(\"Icon\", m_Instruction.usedGUIContent.image, typeof(Texture2D), false);\n            }\n        }\n\n        internal override string GetInstructionListName(int index)\n        {\n            //This means we will resolve the stack trace for all instructions.\n            //TODO: make sure only visible items do this. Also, cache so we don't have to do everyframe.\n            var methodName = GetInstructionListName(m_Instructions[index].stackframes);\n            var label = m_Instructions[index].label;\n            if (String.IsNullOrEmpty(label))\n                return string.Format(\"{0}. {1}\", index, methodName);\n            else\n                return string.Format(\"{0}. {2} ({1})\", index, label, methodName);\n        }\n\n        string GetInstructionListName(StackFrame[] stacktrace)\n        {\n            int frameIndex = GetInterestingFrameIndex(stacktrace);\n            StackFrame interestingFrame = stacktrace[frameIndex];\n            return interestingFrame.methodName;\n        }\n\n        internal override void OnDoubleClickInstruction(int index)\n        {\n            ShowInstructionInExternalEditor(m_Instructions[index].stackframes);\n        }\n\n        internal override void OnSelectedInstructionChanged(int index)\n        {\n            listViewState.row = index;\n\n            if (listViewState.row >= 0 && index < m_Instructions.Count)\n            {\n                if (m_CachedInstructionInfo == null)\n                {\n                    m_CachedInstructionInfo = new CachedInstructionInfo();\n                }\n\n                m_Instruction = m_Instructions[listViewState.row];\n\n                //updated Cached data related to the Selected Instruction\n                m_CachedInstructionInfo.styleContainer.inspectedStyle = m_Instruction.usedGUIStyle;\n                m_CachedInstructionInfo.styleContainerSerializedObject = null;\n                m_CachedInstructionInfo.styleSerializedProperty = null;\n                GetSelectedStyleProperty(out m_CachedInstructionInfo.styleContainerSerializedObject, out m_CachedInstructionInfo.styleSerializedProperty);\n\n                //Hightlight the item\n                debuggerWindow.HighlightInstruction(debuggerWindow.inspected, m_Instruction.rect, m_Instruction.usedGUIStyle);\n            }\n            else\n            {\n                m_CachedInstructionInfo = null;\n\n                debuggerWindow.ClearInstructionHighlighter();\n            }\n        }\n\n        int GetInterestingFrameIndex(StackFrame[] stacktrace)\n        {\n            //We try to find the first frame that belongs to the user project.\n            //If there is no frame inside the user project, we will return the first frame outside any class starting with:\n            //UnityEngine.GUI or UnityEditor.EditorGUI, this should include:\n            // - UnityEngine.GUIStyle\n            // - UnityEngine.GUILayout\n            // - UnityEngine.GUI\n            // - UnityEditor.EditorGUI\n            // - UnityEditor.EditorGUILayout\n            string currentProjectPath = Application.dataPath;\n\n            int index = -1;\n\n            for (int i = 0; i < stacktrace.Length; ++i)\n            {\n                StackFrame sf = stacktrace[i];\n                if (string.IsNullOrEmpty(sf.sourceFile))\n                    continue;\n                if (sf.signature.StartsWith(\"UnityEngine.GUI\") ||\n                    sf.signature.StartsWith(\"UnityEngine.GUIStyle\") ||\n                    sf.signature.StartsWith(\"UnityEditor.StyleSheets\") ||\n                    sf.signature.StartsWith(\"UnityEditor.EditorGUILayout\"))\n                    continue;\n\n                if (index == -1)\n                    index = i;\n\n                if (sf.sourceFile.StartsWith(currentProjectPath))\n                    return i - 1;\n            }\n\n            if (index != -1)\n                return index;\n\n            return stacktrace.Length - 1;\n        }\n\n        void GetSelectedStyleProperty(out SerializedObject serializedObject, out SerializedProperty styleProperty)\n        {\n            //GUISkin[] guiskins = FindObjectsOfType<GUISkin>();\n            GUISkin guiskin = null;\n            //foreach (GUISkin gs in guiskins)\n            var gs = GUISkin.current;\n            {\n                GUIStyle style = gs.FindStyle(m_Instruction.usedGUIStyle.name);\n                if (style != null && style == m_Instruction.usedGUIStyle)\n                {\n                    guiskin = gs;\n                    //break;\n                }\n            }\n            styleProperty = null;\n\n            if (guiskin != null)\n            {\n                serializedObject = new SerializedObject(guiskin);\n                SerializedProperty property = serializedObject.GetIterator();\n                bool expanded = true;\n                while (property.NextVisible(expanded))\n                {\n                    if (property.type == \"GUIStyle\")\n                    {\n                        expanded = false;\n                        SerializedProperty spt = property.FindPropertyRelative(\"m_Name\");\n                        if (spt.stringValue == m_Instruction.usedGUIStyle.name)\n                        {\n                            styleProperty = property;\n                            return;\n                        }\n                    }\n                    else\n                    {\n                        expanded = true;\n                    }\n\n                    //EditorGUILayout.PropertyField(property, true);\n                }\n                Debug.Log(string.Format(\"Showing editable Style from GUISkin: {0}, IsPersistant: {1}\", guiskin.name, EditorUtility.IsPersistent(guiskin)));\n            }\n\n            //Could not find the styles in the GUISkin.\n            serializedObject = new SerializedObject(m_CachedInstructionInfo.styleContainer);\n            styleProperty = serializedObject.FindProperty(\"inspectedStyle\");\n        }\n\n        void ShowInstructionInExternalEditor(StackFrame[] frames)\n        {\n            int frameIndex = GetInterestingFrameIndex(frames);\n            StackFrame frame = frames[frameIndex];\n\n            InternalEditorUtility.OpenFileAtLineExternal(frame.sourceFile, (int)frame.lineNumber, -1);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUIDebugger/StylePicker.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Assertions;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    internal class StylePicker\n    {\n        List<GUIView> m_ExploredViews = new List<GUIView>();\n        GUIView m_ExploredView;\n        EditorWindow m_BoundWindow;\n\n        bool m_UpdateExploredGUIStyle;\n        Vector2 m_MouseCursorScreenPos;\n\n        public GUIView ExploredView => m_ExploredView;\n        public GUIStyle ExploredStyle { get; set; }\n        public int ExploredDrawInstructionIndex { get; private set; }\n        public bool IsPicking { get; set; }\n        public ElementHighlighter Highlighter { get; private set; }\n        public Func<GUIView, bool> CanInspectView { get; set; }\n\n        public StylePicker(EditorWindow window, ElementHighlighter highlighter = null)\n        {\n            m_BoundWindow = window;\n            Highlighter = highlighter;\n            CanInspectView = view => true;\n        }\n\n        public void StartExploreStyle()\n        {\n            // Debug.Log(\"Start Style Explorer\");\n            Assert.IsFalse(IsPicking);\n            IsPicking = true;\n            EditorApplication.update += FindStyleUnderMouse;\n            GUIViewDebuggerHelper.GetViews(m_ExploredViews);\n        }\n\n        public void StopExploreStyle()\n        {\n            // Debug.Log(\"Start Style Explorer\");\n            IsPicking = false;\n            EditorApplication.update -= FindStyleUnderMouse;\n            m_ExploredViews.Clear();\n            m_ExploredView = null;\n            ExploredStyle = null;\n            ExploredDrawInstructionIndex = -1;\n            m_UpdateExploredGUIStyle = false;\n\n            if (Highlighter != null)\n            {\n                Highlighter.ClearElement();\n            }\n\n            m_BoundWindow.Repaint();\n        }\n\n        public void OnGUI()\n        {\n            m_UpdateExploredGUIStyle = false;\n            if (!IsPicking)\n                return;\n\n            // NOTE: we can only StopDebugging and StartDebugging OUTSIDE of OnGUI or else we crash (popclip/pushclip mismatch)\n            // Only keep the data necessary to Start/Stop Debug in next Update tick.\n            m_MouseCursorScreenPos = GUIUtility.GUIToScreenPoint(Event.current.mousePosition);\n            m_UpdateExploredGUIStyle = true;\n        }\n\n        private void UpdateExploredGUIStyle(Vector2 screenPos)\n        {\n            GUIView mouseUnderView = GetViewUnderMouse(screenPos, m_ExploredViews);\n            ExploredDrawInstructionIndex = -1;\n            ExploredStyle = null;\n            if (mouseUnderView != m_ExploredView)\n            {\n                if (m_ExploredView)\n                {\n                    GUIViewDebuggerHelper.StopDebugging();\n                    // Debug.Log(\"Stop debugging: \" + GetViewName(m_ExploredView));\n                }\n\n                m_ExploredView = CanInspectView(mouseUnderView) ? mouseUnderView : null;\n\n                if (m_ExploredView)\n                {\n                    // Start debugging\n                    GUIViewDebuggerHelper.DebugWindow(m_ExploredView);\n                    // Debug.Log(\"Start debugging: \" + GetViewName(m_ExploredView));\n\n                    // Since we have attached the debugger, this view hasn't logged its repaint steps yet.\n                    m_ExploredView.Repaint();\n                }\n            }\n\n            if (m_ExploredView)\n            {\n                var drawInstructions = new List<IMGUIDrawInstruction>();\n                GUIViewDebuggerHelper.GetDrawInstructions(drawInstructions);\n\n                var localPosition = new Vector2(screenPos.x - mouseUnderView.screenPosition.x,\n                    screenPos.y - mouseUnderView.screenPosition.y);\n                GUIStyle mouseUnderStyle = null;\n\n                /** Note: no perfect way to find the style under cursor:\n                    - Lots of style rect overlap\n                    - by starting with the end, we hope to follow the \"Last drawn instruction is the one on top\"\n                    - Some styles are \"transparent\" and drawn last (TabWindowBackground and such)\n                    - We try to go with the smallest rect that fits\n                */\n                Rect styleRect = new Rect(0, 0, 10000, 10000);\n                var smallestRectArea = styleRect.width * styleRect.height;\n                for (var i = drawInstructions.Count - 1; i >= 0; --i)\n                {\n                    var instr = drawInstructions[i];\n                    if (instr.rect.Contains(localPosition) && smallestRectArea > instr.rect.width * instr.rect.height)\n                    {\n                        mouseUnderStyle = instr.usedGUIStyle;\n                        styleRect = instr.rect;\n                        smallestRectArea = instr.rect.width * instr.rect.height;\n                        ExploredDrawInstructionIndex = i;\n\n                        // Debug.Log(GetViewName(m_ExploredView) + \" - Found Style: \" + instr.usedGUIStyle.name);\n                    }\n                }\n\n                if (Highlighter != null && mouseUnderStyle != null)\n                {\n                    var visualElement = m_ExploredView.windowBackend.visualTree as VisualElement;\n                    if (visualElement != null)\n                    {\n                        // Debug.Log(GetViewName(m_ExploredView) + \" - Highlight Style: \" + mouseUnderStyle.name);\n                        Highlighter.HighlightElement(visualElement, styleRect, mouseUnderStyle);\n                    }\n                }\n\n                ExploredStyle = mouseUnderStyle;\n            }\n        }\n\n        private void FindStyleUnderMouse()\n        {\n            // Keep sending Repaint to the master view so it can update the mouse position\n            m_BoundWindow.Repaint();\n\n            if (m_UpdateExploredGUIStyle)\n            {\n                UpdateExploredGUIStyle(m_MouseCursorScreenPos);\n            }\n        }\n\n        internal static GUIView GetViewUnderMouse(Vector2 mouseScreenPos, List<GUIView> views)\n        {\n            var windowUnderMouse = EditorWindow.mouseOverWindow;\n            if (windowUnderMouse)\n            {\n                return views.Find(v => GetEditorWindow(v) == windowUnderMouse);\n            }\n\n            return views.Find(v => v.screenPosition.Contains(mouseScreenPos));\n        }\n\n        internal static EditorWindow GetEditorWindow(GUIView view)\n        {\n            var hostView = view as HostView;\n            if (hostView != null)\n                return hostView.actualView;\n\n            return null;\n        }\n\n        internal static string GetViewName(GUIView view)\n        {\n            var editorWindow = GetEditorWindow(view);\n            if (editorWindow != null)\n                return editorWindow.titleContent.text;\n\n            return view.GetType().Name;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUIDebugger/UnifiedInspectView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class UnifiedInspectView : BaseInspectView\n    {\n        Vector2 m_StacktraceScrollPos =  new Vector2();\n\n        readonly List<IMGUIInstruction> m_Instructions = new List<IMGUIInstruction>();\n        BaseInspectView m_InstructionClipView;\n        BaseInspectView m_InstructionStyleView;\n        BaseInspectView m_InstructionPropertyView;\n        BaseInspectView m_InstructionLayoutView;\n        private BaseInspectView m_InstructionNamedControlView;\n\n        public UnifiedInspectView(GUIViewDebuggerWindow guiViewDebuggerWindow) : base(guiViewDebuggerWindow)\n        {\n            m_InstructionClipView = new GUIClipInspectView(guiViewDebuggerWindow);\n            m_InstructionStyleView = new StyleDrawInspectView(guiViewDebuggerWindow);\n            m_InstructionLayoutView = new GUILayoutInspectView(guiViewDebuggerWindow);\n            m_InstructionPropertyView = new GUIPropertyInspectView(guiViewDebuggerWindow);\n            m_InstructionNamedControlView = new GUINamedControlInspectView(guiViewDebuggerWindow);\n        }\n\n        public override void UpdateInstructions()\n        {\n            m_InstructionClipView.UpdateInstructions();\n            m_InstructionStyleView.UpdateInstructions();\n            m_InstructionLayoutView.UpdateInstructions();\n            m_InstructionPropertyView.UpdateInstructions();\n            m_InstructionNamedControlView.UpdateInstructions();\n\n            /*\n            This is an expensive operation, it will resolve the callstacks for all instructions.\n            Currently we marshall all instructions for every GUI Event.\n            This works okay for windows that doesn't repaint automatically.\n            We can optmize by only marshalling the visible instructions and caching it.\n            But I don't really think its needed right now.\n            */\n            m_Instructions.Clear();\n            GUIViewDebuggerHelper.GetUnifiedInstructions(m_Instructions);\n        }\n\n        public override void ShowOverlay()\n        {\n            if (!isInstructionSelected)\n            {\n                debuggerWindow.ClearInstructionHighlighter();\n                return;\n            }\n\n            IMGUIInstruction instruction = m_Instructions[listViewState.row];\n            var viewForType = GetInspectViewForType(instruction.type);\n            viewForType.ShowOverlay();\n        }\n\n        protected override int GetInstructionCount()\n        {\n            return m_Instructions.Count;\n        }\n\n        protected override void DoDrawInstruction(ListViewElement el, int controlId)\n        {\n            IMGUIInstruction instruction = m_Instructions[el.row];\n\n            string listDisplayName = GetInstructionListName(el.row);\n            GUIContent tempContent = GUIContent.Temp(listDisplayName);\n\n            var rect = el.position;\n            rect.xMin += instruction.level * 10;\n\n            GUIViewDebuggerWindow.Styles.listItemBackground.Draw(rect, false, false, listViewState.row == el.row, false);\n\n            GUIViewDebuggerWindow.Styles.listItem.Draw(rect, tempContent, controlId, listViewState.row == el.row);\n        }\n\n        protected override void DrawInspectedStacktrace(float availableWidth)\n        {\n            IMGUIInstruction instruction = m_Instructions[listViewState.row];\n\n            m_StacktraceScrollPos = EditorGUILayout.BeginScrollView(m_StacktraceScrollPos, GUIViewDebuggerWindow.Styles.stacktraceBackground, GUILayout.ExpandHeight(false));\n            DrawStackFrameList(instruction.stack, availableWidth);\n            EditorGUILayout.EndScrollView();\n        }\n\n        internal override void DoDrawSelectedInstructionDetails(int selectedInstructionIndex)\n        {\n            IMGUIInstruction instruction = m_Instructions[selectedInstructionIndex];\n\n            var viewForType = GetInspectViewForType(instruction.type);\n            viewForType.DoDrawSelectedInstructionDetails(instruction.typeInstructionIndex);\n        }\n\n        internal override string GetInstructionListName(int index)\n        {\n            IMGUIInstruction instruction = m_Instructions[index];\n\n            //string listDisplayName = instruction.type + \" #\" + instruction.typeInstructionIndex;\n            //return listDisplayName;\n\n            var viewForType = GetInspectViewForType(instruction.type);\n            return viewForType.GetInstructionListName(instruction.typeInstructionIndex);\n        }\n\n        internal override void OnSelectedInstructionChanged(int index)\n        {\n            listViewState.row = index;\n\n            if (listViewState.row >= -0)\n            {\n                IMGUIInstruction instruction = m_Instructions[listViewState.row];\n\n                var viewForType = GetInspectViewForType(instruction.type);\n                viewForType.OnSelectedInstructionChanged(instruction.typeInstructionIndex);\n\n                ShowOverlay();\n            }\n            else\n            {\n                debuggerWindow.ClearInstructionHighlighter();\n            }\n        }\n\n        internal override void OnDoubleClickInstruction(int index)\n        {\n            IMGUIInstruction instruction = m_Instructions[index];\n\n            var viewForType = GetInspectViewForType(instruction.type);\n            viewForType.OnDoubleClickInstruction(instruction.typeInstructionIndex);\n        }\n\n        BaseInspectView GetInspectViewForType(InstructionType type)\n        {\n            switch (type)\n            {\n                case InstructionType.kStyleDraw:\n                    return m_InstructionStyleView;\n\n                case InstructionType.kClipPop:\n                case InstructionType.kClipPush:\n                    return m_InstructionClipView;\n\n                case InstructionType.kLayoutBeginGroup:\n                case InstructionType.kLayoutEndGroup:\n                case InstructionType.kLayoutEntry:\n                    return m_InstructionLayoutView;\n                case InstructionType.kPropertyBegin:\n                case InstructionType.kPropertyEnd:\n                    return m_InstructionPropertyView;\n                case InstructionType.kLayoutNamedControl:\n                    return m_InstructionNamedControlView;\n                default:\n                    throw new NotImplementedException(\"Unhandled InstructionType\");\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUIView.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    [UsedByNativeCode,\n     NativeHeader(\"Runtime/Misc/InputEvent.h\"),\n     NativeHeader(\"Runtime/Graphics/RenderTexture.h\"),\n     NativeHeader(\"Editor/Src/Windowing/GUIView.bindings.h\"),\n     NativeHeader(\"Editor/Src/Windowing/ContainerWindow.bindings.h\")]\n    [UnityEngine.Bindings.VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n    internal partial class GUIView\n    {\n        public static extern GUIView current {[NativeMethod(\"GetCurrentGUIView\")] get; }\n        public static extern GUIView focusedView {[NativeMethod(\"GetFocusedGUIView\")] get; }\n        public static extern GUIView mouseOverView {[NativeMethod(\"GetMouseOverGUIView\")] get; }\n\n        public extern bool hasFocus {[NativeMethod(\"IsViewFocused\")] get; }\n\n        public extern void Repaint();\n\n        [UnityEngine.Bindings.VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        public extern void Focus();\n        public extern void RepaintImmediately();\n        public extern void CaptureRenderDocScene();\n        public extern void CaptureRenderDocFullContent();\n        public extern void BeginCaptureRenderDoc();\n        public extern void EndCaptureRenderDoc();\n\n        internal extern bool vSyncEnabled {[NativeMethod(\"IsVSyncEnabled\")] get; }\n\n        internal extern void RenderCurrentSceneForCapture();\n\n\n        internal extern bool mouseRayInvisible {[NativeMethod(\"IsMouseRayInvisible\")] get; [NativeMethod(\"SetMouseRayInvisible\")] set; }\n        internal extern bool disableInputEvents {[NativeMethod(\"AreInputEventsDisabled\")] get; [NativeMethod(\"SetDisableInputEvents\")] set; }\n\n        internal extern bool hdrActive {[NativeMethod(\"IsHDRActive\")] get; }\n\n        internal extern void SetTitle(string title);\n        internal extern void AddToAuxWindowList();\n        internal extern void SetInternalGameViewDimensions(Rect rect, Rect clippedRect, Vector2 targetSize);\n        internal extern void SetMainPlayModeViewSize(Vector2 targetSize);\n        internal extern void SetDisplayViewSize(int displayId, Vector2 targetSize);\n        internal extern Vector2 GetDisplayViewSize(int displayId);\n        internal extern void SetAsStartView();\n        internal extern void SetAsLastPlayModeView();\n        internal extern void SetPlayModeView(bool value);\n        internal extern void ClearStartView();\n        internal extern void MakeVistaDWMHappyDance();\n        internal extern void SetEyeDropperOpen(bool isOpen);\n        internal extern void StealMouseCapture();\n        internal extern void ClearKeyboardControl();\n        internal extern void SetKeyboardControl(int id);\n        internal extern int GetKeyboardControl();\n        internal extern void GrabPixels(RenderTexture rd, Rect rect);\n        internal extern float GetBackingScaleFactor();\n        internal extern void MarkHotRegion(Rect hotRegionRect);\n        internal extern void EnableVSync(bool value);\n        internal extern void SetActualViewName(string viewName);\n        internal extern System.IntPtr nativeHandle\n        {\n            [NativeMethod(\"GetGUIViewHandle\")]\n            get;\n        }\n\n        protected extern void Internal_SetAsActiveWindow();\n\n        [NativeMethod(ThrowsException = true)]\n        private extern void Internal_Init(int depthBits, int antiAliasing, bool isPlayModeView);\n        private extern void Internal_Recreate(int depthBits, int antiAliasing);\n        private extern void Internal_Close();\n        private extern bool Internal_SendEvent(Event e);\n        private extern void Internal_SetWantsMouseMove(bool wantIt);\n        private extern void Internal_SetWantsMouseEnterLeaveWindow(bool wantIt);\n        private extern void Internal_SetAutoRepaint(bool doit);\n        private extern void Internal_SetWindow(ScriptableObject win);\n        private extern void Internal_UnsetWindow(ScriptableObject win);\n        private extern void Internal_SetPosition(Rect windowPosition);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GUIView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Runtime.InteropServices;\nusing System;\nusing UnityEngine.Scripting;\n\nusing FrameCapture = UnityEngine.Apple.FrameCapture;\nusing FrameCaptureDestination = UnityEngine.Apple.FrameCaptureDestination;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    // This is what we (not users) derive from to create various views. (Main Toolbar, etc.)\n    [StructLayout(LayoutKind.Sequential)]\n    internal partial class GUIView : View, IWindowModel\n    {\n        internal static event Action<GUIView> positionChanged = null;\n\n        int m_DepthBufferBits = 0;\n        int m_AntiAliasing = 1;\n        bool m_ResetPanelRenderingOnAssetChange = true;\n        bool m_AutoRepaintOnSceneChange = false;\n        private IWindowBackend m_WindowBackend;\n\n        protected EventInterests m_EventInterests;\n\n        internal bool SendEvent(Event e)\n        {\n            int depth = SavedGUIState.Internal_GetGUIDepth();\n            if (depth > 0)\n            {\n                SavedGUIState oldState = SavedGUIState.Create();\n                var retval = Internal_SendEvent(e);\n                oldState.ApplyAndForget();\n                return retval;\n            }\n\n            {\n                var retval = Internal_SendEvent(e);\n                return retval;\n            }\n        }\n\n        // Call into C++ here to move the underlying NSViews around\n        internal override void SetWindow(ContainerWindow win)\n        {\n            ContainerWindow oldWindow = this.window;\n            base.SetWindow(win); // Sets this.window(m_Window) to win\n\n            try\n            {\n                bool isPlayModeView = false;\n\n                if (this is HostView h)\n                    isPlayModeView = h.actualView is PlayModeView;\n\n                Internal_Init(m_DepthBufferBits, m_AntiAliasing, isPlayModeView);\n            }\n            catch\n            {\n                parent?.RemoveChild(this);\n                throw;\n            }\n\n            if (!win)\n            {\n                // Tell the native ContainerWindow we were attached to that we\n                // are no longer attached to it.\n                Internal_UnsetWindow(oldWindow);\n            }\n            else\n            {\n                Internal_SetWindow(win);\n            }\n\n            Internal_SetAutoRepaint(m_AutoRepaintOnSceneChange);\n            Internal_SetPosition(windowPosition);\n            Internal_SetWantsMouseMove(m_EventInterests.wantsMouseMove);\n            Internal_SetWantsMouseEnterLeaveWindow(m_EventInterests.wantsMouseMove);\n\n            windowBackend?.SizeChanged();\n        }\n\n        internal void RecreateContext()\n        {\n            Internal_Recreate(m_DepthBufferBits, m_AntiAliasing);\n        }\n\n        Vector2 IWindowModel.size => windowPosition.size;\n        protected VisualElement visualTree => (VisualElement)(windowBackend?.visualTree);\n\n        public EventInterests eventInterests\n        {\n            get { return m_EventInterests; }\n            set\n            {\n                m_EventInterests = value;\n\n                windowBackend?.EventInterestsChanged();\n\n                Internal_SetWantsMouseMove(wantsMouseMove);\n                Internal_SetWantsMouseEnterLeaveWindow(wantsMouseEnterLeaveWindow);\n            }\n        }\n\n        Action IWindowModel.onGUIHandler => OldOnGUI;\n\n        public bool wantsMouseMove\n        {\n            get { return m_EventInterests.wantsMouseMove; }\n            set\n            {\n                m_EventInterests.wantsMouseMove = value;\n                windowBackend?.EventInterestsChanged();\n                Internal_SetWantsMouseMove(wantsMouseMove);\n            }\n        }\n\n        public bool wantsMouseEnterLeaveWindow\n        {\n            get { return m_EventInterests.wantsMouseEnterLeaveWindow; }\n            set\n            {\n                m_EventInterests.wantsMouseEnterLeaveWindow = value;\n                windowBackend?.EventInterestsChanged();\n                Internal_SetWantsMouseEnterLeaveWindow(wantsMouseEnterLeaveWindow);\n            }\n        }\n\n        public bool autoRepaintOnSceneChange\n        {\n            get { return m_AutoRepaintOnSceneChange; }\n            set { m_AutoRepaintOnSceneChange = value; Internal_SetAutoRepaint(m_AutoRepaintOnSceneChange); }\n        }\n\n        public int depthBufferBits\n        {\n            get { return m_DepthBufferBits; }\n            set { m_DepthBufferBits = value; }\n        }\n\n        public int antiAliasing\n        {\n            get { return m_AntiAliasing; }\n            set { m_AntiAliasing = value; }\n        }\n\n        [Obsolete(\"AA is not supported on GUIViews\", false)]\n        public int antiAlias\n        {\n            get { return 1; }\n            set { throw new NotSupportedException(\"AA is not supported on GUIViews\"); }\n        }\n\n        public bool resetPanelRenderingOnAssetChange\n        {\n            get => m_ResetPanelRenderingOnAssetChange;\n            set\n            {\n                if (m_ResetPanelRenderingOnAssetChange != value)\n                {\n                    m_ResetPanelRenderingOnAssetChange = value;\n                    windowBackend?.ResetPanelRenderingOnAssetChangeChanged();\n                }\n            }\n        }\n\n        internal IWindowBackend windowBackend\n        {\n            get { return m_WindowBackend; }\n            set\n            {\n                if (m_WindowBackend != null)\n                    m_WindowBackend.OnDestroy(this);\n\n                m_WindowBackend = value;\n                m_WindowBackend?.OnCreate(this);\n                // When the native side has triggered OnBackingScaleFactorChanged, it will not send it again even if we are adding view to a hostView.\n                // (Docking, domain reload)\n                // It also occurs that the event is sent when the backend is not yet set in the view\n                // lets trigger the sizeChanged and OnBackingScaleFactorChanged to remedy any scenario\n                windowBackend?.SizeChanged();\n            }\n        }\n\n        IWindowBackend IWindowModel.windowBackend\n        {\n            get { return windowBackend; }\n            set { windowBackend = value; }\n        }\n\n        protected virtual void OnEnable()\n        {\n            windowBackend = EditorWindowBackendManager.GetBackend(this);\n        }\n\n        protected virtual void OnDisable()\n        {\n            windowBackend = null;\n        }\n\n        internal void ValidateWindowBackendForCurrentView()\n        {\n            if (!EditorWindowBackendManager.IsBackendCompatible(windowBackend, this))\n            {\n                //We create a new compatible backend\n                windowBackend = EditorWindowBackendManager.GetBackend(this);\n            }\n        }\n\n        protected virtual void OldOnGUI() {}\n\n        // Without leaving this in here for MonoBehaviour::DoGUI(), GetMethod(MonoScriptCache::kGUI) will return null.\n        // In that case, commands are not delegated (e.g., keyboard-based delete in Hierarchy/Project)\n        protected virtual void OnGUI() {}\n\n        protected virtual void OnBackingScaleFactorChanged()\n        {\n            windowBackend?.OnBackingScaleFactorChanged();\n        }\n\n        protected override void SetPosition(Rect newPos)\n        {\n            Rect oldWinPos = windowPosition;\n\n            base.SetPosition(newPos);\n            if (oldWinPos == windowPosition)\n            {\n                Internal_SetPosition(windowPosition);\n                return;\n            }\n\n            Internal_SetPosition(windowPosition);\n\n            windowBackend?.SizeChanged();\n\n            positionChanged?.Invoke(this);\n\n            Repaint();\n        }\n\n        protected override void OnDestroy()\n        {\n            Internal_Close();\n\n            base.OnDestroy();\n        }\n\n        [RequiredByNativeCode]\n        internal string GetViewName()\n        {\n            var hostView = this as HostView;\n            if (hostView != null && hostView.actualView != null)\n                return hostView.actualView.GetType().Name;\n\n            return GetType().Name;\n        }\n\n        [RequiredByNativeCode]\n        internal static string GetTypeNameOfMostSpecificActiveView()\n        {\n            var currentView = current;\n            if (currentView == null)\n                return string.Empty;\n\n            var hostView = currentView as HostView;\n            if (hostView != null && hostView.actualView != null)\n                return hostView.actualView.GetType().FullName;\n\n            return currentView.GetType().FullName;\n        }\n\n        public static void BeginOffsetArea(Rect screenRect, GUIContent content, GUIStyle style)\n        {\n            GUILayoutGroup g = EditorGUILayoutUtilityInternal.BeginLayoutArea(style, typeof(GUILayoutGroup));\n            switch (Event.current.type)\n            {\n                case EventType.Layout:\n                    g.resetCoords = false;\n                    g.minWidth = g.maxWidth = screenRect.width;\n                    g.minHeight = g.maxHeight = screenRect.height;\n                    g.rect = Rect.MinMaxRect(0, 0, g.rect.xMax, g.rect.yMax);\n                    break;\n            }\n            GUI.BeginGroup(screenRect, content, style);\n        }\n\n        public static void EndOffsetArea()\n        {\n            GUI.EndGroup();\n            GUILayoutUtility.EndLayoutGroup();\n        }\n\n        // we already have renderdoc integration done in GUIView but in cpp\n        // for metal we need a bit more convoluted logic and we can push more things to cs\n        internal void CaptureMetalScene()\n        {\n            if (FrameCapture.IsDestinationSupported(FrameCaptureDestination.DevTools))\n            {\n                FrameCapture.BeginCaptureToXcode();\n                RenderCurrentSceneForCapture();\n                FrameCapture.EndCapture();\n            }\n            else if (FrameCapture.IsDestinationSupported(FrameCaptureDestination.GPUTraceDocument))\n            {\n                string path = EditorUtility.SaveFilePanel(\"Save Metal GPU Capture\", \"\", PlayerSettings.productName + \".gputrace\", \"gputrace\");\n                if (System.String.IsNullOrEmpty(path))\n                    return;\n\n                FrameCapture.BeginCaptureToFile(path);\n                RenderCurrentSceneForCapture();\n                FrameCapture.EndCapture();\n\n                System.Console.WriteLine(\"Metal capture saved to \" + path);\n                System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName(path));\n            }\n        }\n\n        static readonly Action<TextElement, VersionChangeType> k_QueryIncrementVersion = IncrementVersion;\n\n        static void IncrementVersion(TextElement te, VersionChangeType changeType)\n        {\n            te.IncrementVersion(changeType);\n        }\n\n        internal void IncrementVersionForUITKText(VersionChangeType changeType)\n        {\n            visualTree.Query<TextElement>().ForEach((te) => k_QueryIncrementVersion(te, changeType));\n        }\n\n        internal void UpdateEditorTextRenderingMode(EditorTextRenderingMode mode)\n        {\n            visualTree.style.unityEditorTextRenderingMode = mode;\n        }\n\n        [RequiredByNativeCode]\n        private void SetActiveWindowAsPresented()\n        {\n            if ((this is HostView h) && h.actualView)\n            {\n                h.actualView.m_IsPresented = true;\n            }\n        }\n    }\n} //namespace\n"
  },
  {
    "path": "Editor/Mono/GameObjectChangeTracker.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing System;\nusing System.Runtime.InteropServices;\nusing Unity.Collections;\nusing Unity.Collections.LowLevel.Unsafe;\nusing Unity.Burst;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/Utility/GameObjectChangeTracker.h\")]\n    internal static class GameObjectChangeTracker\n    {\n        static GameObjectChangeTracker() => Init();\n\n        [StaticAccessor(\"GameObjectChangeTracker\", StaticAccessorType.DoubleColon)]\n        extern static void Init();\n\n        public static event GameObjectChangeTrackerEventHandler GameObjectsChanged\n        {\n            add => m_GameObjectsChanged.Add(value);\n            remove => m_GameObjectsChanged.Remove(value);\n        }\n\n        public static unsafe void PublishEvents(NativeArray<GameObjectChangeTrackerEvent> events)\n            => OnGameObjectsChanged((IntPtr)events.GetUnsafeReadOnlyPtr(), events.Length);\n\n        private static EventWithPerformanceTracker<GameObjectChangeTrackerEventHandler> m_GameObjectsChanged = new EventWithPerformanceTracker<GameObjectChangeTrackerEventHandler>($\"{nameof(GameObjectChangeTracker)}.{nameof(GameObjectsChanged)}\");\n\n        [RequiredByNativeCode(GenerateProxy = true)]\n        static unsafe void OnGameObjectsChanged(IntPtr events, int eventsCount)\n        {\n            if (!m_GameObjectsChanged.hasSubscribers || eventsCount == 0)\n                return;\n\n            var nativeArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<GameObjectChangeTrackerEvent>(events.ToPointer(), eventsCount, Allocator.Invalid);\n\n            var ash = AtomicSafetyHandle.Create();\n            InitStaticSafetyId(ref ash);\n            NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref nativeArray, ash);\n            try\n            {\n                foreach (var evt in m_GameObjectsChanged)\n                    evt(nativeArray);\n            }\n            finally\n            {\n                var result = AtomicSafetyHandle.EnforceAllBufferJobsHaveCompletedAndRelease(ash);\n                if (result == EnforceJobResult.DidSyncRunningJobs)\n                {\n                    UnityEngine.Debug.LogError(\n                        $\"You cannot use the {nameof(GameObjectChangeTracker)} instance provided by {nameof(GameObjectsChanged)} in a job unless you complete the job before your callback finishes.\");\n                }\n            }\n        }\n\n        // TODO: Once Burst supports internal/external functions in static initializers, this can become\n        //   static readonly int s_staticSafetyId = AtomicSafetyHandle.NewStaticSafetyId<GameObjectChangeTrackerEvents>();\n        // and InitStaticSafetyId() can be replaced with a call to AtomicSafetyHandle.SetStaticSafetyId();\n        static int s_staticSafetyId;\n        [BurstDiscard]\n        static void InitStaticSafetyId(ref AtomicSafetyHandle handle1)\n        {\n            if (s_staticSafetyId == 0)\n                s_staticSafetyId = AtomicSafetyHandle.NewStaticSafetyId<GameObjectChangeTrackerEvent>();\n            AtomicSafetyHandle.SetStaticSafetyId(ref handle1, s_staticSafetyId);\n        }\n\n    }\n\n    internal delegate void GameObjectChangeTrackerEventHandler(in NativeArray<GameObjectChangeTrackerEvent> events);\n\n    [StructLayout(layoutKind: LayoutKind.Sequential)]\n    internal readonly struct GameObjectChangeTrackerEvent\n    {\n        public GameObjectChangeTrackerEvent(int instanceId, GameObjectChangeTrackerEventType eventType)\n        {\n            InstanceId = instanceId;\n            EventType = eventType;\n        }\n\n        public GameObjectChangeTrackerEvent(GameObjectChangeTrackerEventType eventType)\n        {\n            InstanceId = 0;\n            EventType = eventType;\n        }\n\n        public readonly int InstanceId;\n        public readonly GameObjectChangeTrackerEventType EventType;\n    }\n\n    [Flags]\n    internal enum GameObjectChangeTrackerEventType : ushort\n    {\n        CreatedOrChanged = 1 << 0,\n        Destroyed = 1 << 1,\n        OrderChanged = 1 << 2,\n        ChangedParent = 1 << 3,\n        ChangedScene = 1 << 4,\n        SceneOrderChanged = 1 << 5\n    }\n\n}\n"
  },
  {
    "path": "Editor/Mono/GameObjectUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.SceneManagement;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Mono/GameObjectUtility.bindings.h\")]\n    [NativeHeader(\"Editor/Src/CommandImplementation.h\")]\n    public sealed partial class GameObjectUtility\n    {\n        public static extern StaticEditorFlags GetStaticEditorFlags(GameObject go);\n        public static extern void SetStaticEditorFlags(GameObject go, StaticEditorFlags flags);\n        public static extern bool AreStaticEditorFlagsSet(GameObject go, StaticEditorFlags flags);\n\n        internal static extern string GetFirstItemPathAfterGameObjectCreationMenuItems();\n\n        public static extern string GetUniqueNameForSibling(Transform parent, string name);\n\n        public static extern void EnsureUniqueNameForSibling(GameObject self);\n\n        internal static bool ContainsStatic(GameObject[] objects)\n        {\n            if (objects == null || objects.Length == 0)\n                return false;\n            for (int i = 0; i < objects.Length; i++)\n            {\n                if (objects[i] != null && objects[i].isStatic)\n                    return true;\n            }\n            return false;\n        }\n\n        internal static bool ContainsMainStageGameObjects(GameObject[] objects)\n        {\n            if (objects == null || objects.Length == 0)\n                return false;\n            for (int i = 0; i < objects.Length; i++)\n            {\n                if (objects[i] != null && StageUtility.GetStageHandle(objects[i]).isMainStage)\n                    return true;\n            }\n            return false;\n        }\n\n        internal static bool HasChildren(IEnumerable<GameObject> gameObjects)\n        {\n            return gameObjects.Any(go => go.transform.childCount > 0);\n        }\n\n        internal enum ShouldIncludeChildren\n        {\n            HasNoChildren = -1,\n            IncludeChildren = 0,\n            DontIncludeChildren = 1,\n            Cancel = 2\n        }\n\n        internal static ShouldIncludeChildren DisplayUpdateChildrenDialogIfNeeded(IEnumerable<GameObject> gameObjects,\n            string title, string message)\n        {\n            if (!HasChildren(gameObjects))\n                return ShouldIncludeChildren.HasNoChildren;\n\n            return\n                (ShouldIncludeChildren)\n                EditorUtility.DisplayDialogComplex(title, message, L10n.Tr(\"Yes, change children\"), L10n.Tr(\"No, this object only\"), L10n.Tr(\"Cancel\"));\n        }\n\n        public static void SetParentAndAlign(GameObject child, GameObject parent)\n        {\n            if (parent == null)\n                return;\n\n            child.transform.SetParent(parent.transform, false);\n\n            RectTransform rectTransform = child.transform as RectTransform;\n            if (rectTransform)\n            {\n                rectTransform.anchoredPosition = Vector2.zero;\n                Vector3 localPosition = rectTransform.localPosition;\n                localPosition.z = 0;\n                rectTransform.localPosition = localPosition;\n            }\n            else\n            {\n                child.transform.localPosition = Vector3.zero;\n            }\n            child.transform.localRotation = Quaternion.identity;\n            child.transform.localScale = Vector3.one;\n\n            SetLayerRecursively(child, parent.layer);\n        }\n\n        internal static void SetDefaultParentForNewObject(GameObject gameObject, Transform parent = null, bool align = false)\n        {\n            if (parent == null && (parent = SceneView.GetDefaultParentObjectIfSet()) == null)\n            {\n                return;\n            }\n\n            if(align)\n            {\n                GameObjectUtility.SetParentAndAlign(gameObject, parent?.gameObject);\n            }\n            else\n            {\n                gameObject.transform.SetParent(parent);\n            }\n        }\n\n        private static void SetLayerRecursively(GameObject go, int layer)\n        {\n            go.layer = layer;\n            Transform t = go.transform;\n            for (int i = 0; i < t.childCount; i++)\n                SetLayerRecursively(t.GetChild(i).gameObject, layer);\n        }\n\n        [FreeFunction]\n        public static extern int GetMonoBehavioursWithMissingScriptCount([NotNull] GameObject go);\n\n        [FreeFunction]\n        public static extern int RemoveMonoBehavioursWithMissingScript([NotNull] GameObject go);\n\n        public static ulong ModifyMaskIfGameObjectIsHiddenForPrefabModeInContext(ulong sceneCullingMask, GameObject gameObject)\n        {\n            if (!IsPrefabInstanceHiddenForInContextEditing(gameObject))\n                return sceneCullingMask;\n            return sceneCullingMask & ~SceneManagement.SceneCullingMasks.MainStageExcludingPrefabInstanceObjectsOpenInPrefabMode;\n        }\n\n        internal static extern bool IsPrefabInstanceHiddenForInContextEditing([NotNull] GameObject go);\n\n        public static GameObject[] DuplicateGameObjects(GameObject[] gameObjects)\n        {\n            if (gameObjects == null)\n                throw new System.ArgumentNullException(\"gameObjects array is null\");\n\n            if (gameObjects.Length == 0)\n                return new GameObject[0];\n\n            foreach (GameObject go in gameObjects)\n            {\n                if (go == null)\n                    throw new System.ArgumentNullException(\"GameObject in gameObjects array is null\");\n\n                if (EditorUtility.IsPersistent(go))\n                    throw new System.ArgumentException(\"Duplicating Assets is unsupported by this function. Use AssetDatabase.CopyAsset to duplicate Assets.\");\n            }\n\n            return DuplicateGameObjects_Internal(gameObjects);\n        }\n\n        public static GameObject DuplicateGameObject(GameObject gameObject)\n        {\n            if (gameObject == null)\n                throw new System.ArgumentNullException(\"gameObject is null\");\n\n            if (EditorUtility.IsPersistent(gameObject))\n                throw new System.ArgumentException(\"Duplicating Assets is unsupported by this function. Use AssetDatabase.CopyAsset to duplicate Assets.\");\n\n            var gameObjects = DuplicateGameObjects_Internal(new[] { gameObject });\n\n            if (gameObjects.Length != 0)\n                return gameObjects[0];\n            else\n                return null;\n        }\n\n        [NativeMethod(\"DuplicateGameObjects\", IsFreeFunction = true)]\n        extern private static GameObject[] DuplicateGameObjects_Internal(GameObject[] gameObjects);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GameObjectUtility.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Mono/GameObjectUtility.bindings.h\")]\n    public sealed partial class GameObjectUtility\n    {\n        [System.Obsolete(\"GetNavMeshArea has been deprecated. To relate a GameObject to an area type and retrieve their relation later, create a NavMeshBuildMarkup and pass it into UnityEngine.AI.NavMeshBuilder.CollectSources().\")]\n        public static extern int GetNavMeshArea(GameObject go);\n\n        [System.Obsolete(\"SetNavMeshArea has been deprecated. To relate a GameObject to an area type, create a NavMeshBuildMarkup and pass it into UnityEngine.AI.NavMeshBuilder.CollectSources().\")]\n        public static extern void SetNavMeshArea(GameObject go, int areaIndex);\n\n        [System.Obsolete(\"GetNavMeshAreaFromName has been deprecated. Use NavMesh.GetAreaFromName instead. (UnityUpgradable) -> [UnityEngine] UnityEngine.AI.NavMesh.GetAreaFromName(*)\")]\n        [StaticAccessor(\"GetNavMeshProjectSettings()\")]\n        [NativeName(\"GetAreaFromName\")]\n        public static extern int GetNavMeshAreaFromName(string name);\n\n        [System.Obsolete(\"GetNavMeshAreaNames has been deprecated. Use NavMesh.GetAreaNames instead. (UnityUpgradable) -> [UnityEngine] UnityEngine.AI.NavMesh.GetAreaNames()\")]\n        [StaticAccessor(\"GetNavMeshProjectSettings()\")]\n        [NativeName(\"GetAreaNames\")]\n        public static extern string[] GetNavMeshAreaNames();\n\n        [System.Obsolete(\"GetNavMeshLayer has been deprecated. To relate a GameObject to an area type and retrieve their relation later, create a NavMeshBuildMarkup and pass it into UnityEngine.AI.NavMeshBuilder.CollectSources(). (UnityUpgradable) -> GetNavMeshArea(*)\")]\n        [NativeName(\"GetNavMeshArea\")]\n        public static extern int GetNavMeshLayer(GameObject go);\n\n        [System.Obsolete(\"SetNavMeshLayer has been deprecated. To relate a GameObject to an area type, create a NavMeshBuildMarkup and pass it into UnityEngine.AI.NavMeshBuilder.CollectSources(). (UnityUpgradable) -> SetNavMeshArea(*)\")]\n        [NativeName(\"SetNavMeshArea\")]\n        public static extern void SetNavMeshLayer(GameObject go, int areaIndex);\n\n        [System.Obsolete(\"GetNavMeshLayerFromName has been deprecated. Use NavMesh.GetAreaFromName instead. (UnityUpgradable) -> [UnityEngine] UnityEngine.AI.NavMesh.GetAreaFromName(*)\")]\n        [StaticAccessor(\"GetNavMeshProjectSettings()\")]\n        [NativeName(\"GetAreaFromName\")]\n        public static extern int GetNavMeshLayerFromName(string name);\n\n        [System.Obsolete(\"GetNavMeshLayerNames has been deprecated. Use NavMesh.GetAreaNames instead. (UnityUpgradable) -> [UnityEngine] UnityEngine.AI.NavMesh.GetAreaNames()\")]\n        [StaticAccessor(\"GetNavMeshProjectSettings()\")]\n        [NativeName(\"GetAreaNames\")]\n        public static extern string[] GetNavMeshLayerNames();\n\n        [System.Obsolete(\"use AnimatorUtility.OptimizeTransformHierarchy instead.\")]\n        static void OptimizeTransformHierarchy(GameObject go)\n        {\n            AnimatorUtility.OptimizeTransformHierarchy(go, null);\n        }\n\n        [System.Obsolete(\"use AnimatorUtility.DeoptimizeTransformHierarchy instead.\")]\n        static void DeoptimizeTransformHierarchy(GameObject go)\n        {\n            AnimatorUtility.DeoptimizeTransformHierarchy(go);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GameView/GameView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEditorInternal;\nusing UnityEditor.SceneManagement;\nusing UnityEditor.Modules;\nusing System.Globalization;\nusing UnityEngine.Rendering;\nusing System.Linq;\nusing System.Collections.Generic;\nusing JetBrains.Annotations;\nusing UnityEditorInternal.VR;\nusing UnityEngine.XR;\nusing FrameCapture = UnityEngine.Apple.FrameCapture;\nusing FrameCaptureDestination = UnityEngine.Apple.FrameCaptureDestination;\nusing UnityEditor.ShortcutManagement;\n\n/*\nThe main GameView can be in the following states when entering playmode.\nThese states should be tested when changing the behavior when entering playmode.\n\n\n GameView docked and visible\n GameView docked and visible and maximizeOnPlay\n GameView docked and hidden\n GameView docked and hidden and maximizeOnPlay\n GameView docked and hidden and resized\n Maximized GameView (maximized from start)\n No GameView but a SceneView exists\n No GameView and no SceneView exists\n Floating GameView in separate window\n*/\n\nnamespace UnityEditor\n{\n    [EditorWindowTitle(title = \"Game\", useTypeNameAsIconName = true)]\n    [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n    internal class GameView : PlayModeView, IHasCustomMenu, IGameViewSizeMenuUser\n    {\n        const int kScaleSliderMinWidth = 30;\n        const int kScaleSliderMaxWidth = 150;\n        const int kScaleSliderSnapThreshold = 4;\n        const int kScaleLabelWidth = 40;\n        readonly Vector2 kWarningSize = new Vector2(400f, 140f);\n        readonly Color kClearBlack = new Color(0, 0 , 0, 0);\n        const float kMinScale = 1f;\n        const float kMaxScale = 5f;\n        const float kScrollZoomSnapDelay = 0.2f;\n        // This will save the previous state which will be useful in case of platform switch\n        int prevSizeGroupType;\n\n        //Take the backing scale from the window if it is available as this values is valid outside of OnGUI methods\n        float backingScale => m_Parent?.GetBackingScaleFactor() ?? EditorGUIUtility.pixelsPerPoint;\n        float minScale\n        {\n            get\n            {\n                var clampedMinScale = Mathf.Min(kMinScale, ScaleThatFitsTargetInView(targetRenderSize, viewInWindow.size));\n                if (m_LowResolutionForAspectRatios[(int)currentSizeGroupType] && currentGameViewSize.sizeType == GameViewSizeType.AspectRatio)\n                    clampedMinScale = Mathf.Max(clampedMinScale, backingScale);\n                return clampedMinScale;\n            }\n        }\n        float maxScale\n        {\n            get { return Mathf.Max(kMaxScale * backingScale, ScaleThatFitsTargetInView(targetRenderSize, viewInWindow.size)); }\n        }\n\n        [SerializeField] bool m_VSyncEnabled;\n        [SerializeField] bool m_Gizmos;\n        [SerializeField] bool m_Stats;\n        [SerializeField] int[] m_SelectedSizes = new int[0]; // We have a selection for each game view size group (e.g standalone, android etc)\n\n        [SerializeField] ZoomableArea m_ZoomArea;\n        [SerializeField] float m_defaultScale = -1f;\n        bool m_TargetClamped;\n\n        [SerializeField] Vector2 m_LastWindowPixelSize;\n\n        [SerializeField] bool m_ClearInEditMode = true;\n        [SerializeField] bool m_NoCameraWarning = true;\n        [SerializeField] bool[] m_LowResolutionForAspectRatios = new bool[0];\n        [SerializeField] int m_XRRenderMode = 0;\n        [SerializeField] RenderTexture m_RenderTexture;\n        [SerializeField] bool m_showToolbar = true;\n\n        int m_SizeChangeID = int.MinValue;\n\n        List<XRDisplaySubsystem> m_DisplaySubsystems = new List<XRDisplaySubsystem>();\n        PlayModeStateChange latestState = PlayModeStateChange.EnteredEditMode;\n\n        internal override bool liveReloadPreferenceDefault => true;\n\n        // Added for tests\n        internal Vector2 zoomAreaScale => m_ZoomArea?.scale ?? Vector2.zero;\n\n        internal static class Styles\n        {\n            public static GUIContent gizmosContent = EditorGUIUtility.TrTextContent(\"Gizmos\", \"Activate / Deactivate gizmos in the GameView\");\n            public static GUIContent zoomSliderContent = EditorGUIUtility.TrTextContent(\"Scale\", \"Size of the game view on the screen.\");\n            public static GUIContent muteOffContent = EditorGUIUtility.TrIconContent(\"GameViewAudio On\", \"Mute Audio\");\n            public static GUIContent muteOnContent = EditorGUIUtility.TrIconContent(\"GameViewAudio\", \"Mute Audio\");\n            public static GUIContent shortcutsOnContent = EditorGUIUtility.TrIconContent(\"Keyboard\", \"Unity Shortcuts\");\n            public static GUIContent shortcutsOffContent = EditorGUIUtility.TrIconContent(\"KeyboardShortcutsDisabled\", \"Unity Shortcuts\");\n            public static GUIContent statsContent = EditorGUIUtility.TrTextContent(\"Stats\");\n            public static GUIContent frameDebuggerOnContent = EditorGUIUtility.TrTextContent(\"Frame Debugger On\");\n            public static GUIContent noCameraWarningContextMenuContent = EditorGUIUtility.TrTextContent(\"Warn if No Cameras Rendering\");\n            public static GUIContent clearEveryFrameContextMenuContent = EditorGUIUtility.TrTextContent(\"Clear Every Frame in Edit Mode\");\n            public static GUIContent lowResAspectRatiosContextMenuContent = EditorGUIUtility.TrTextContent(\"Low Resolution Aspect Ratios\");\n            public static GUIContent metalFrameCaptureContent = EditorGUIUtility.TrIconContent(\"FrameCapture\", \"Capture the current view and open in Xcode frame debugger\");\n            public static GUIContent frameDebuggerContent = EditorGUIUtility.TrIconContent(\"Debug\", \"Opens the Frame Debugger\");\n\n            public const string k_StatsShortcutID = \"Game View/Toggle Stats\";\n            public const string k_StatsTooltip = \"View general rendering information\";\n            public const string k_AspectRatioTooltip = \"Change aspect ratios, emulate low pixel density, allow VSync\";\n\n            public static GUIContent renderdocContent;\n            public static GUIStyle gameViewBackgroundStyle;\n\n            // The ordering here must correspond with ordering in UnityEngine.XR.GameViewRenderMode\n            public static GUIContent[] xrRenderingModes = { EditorGUIUtility.TextContent(\"Left Eye|Left eye is displayed in play mode.\"), EditorGUIUtility.TextContent(\"Right Eye|Right eye is displayed in play mode.\"), EditorGUIUtility.TextContent(\"Both Eyes|Both eyes are displayed in play mode.\"), EditorGUIUtility.TextContent(\"Occlusion Mesh|Both eyes are displayed in play mode along with the occlusion mesh.\") };\n\n            static Styles()\n            {\n                gameViewBackgroundStyle = \"GameViewBackground\";\n                renderdocContent = EditorGUIUtility.TrIconContent(\"FrameCapture\", RenderDocUtil.openInRenderDocTooltip);\n            }\n        }\n\n        static double s_LastScrollTime;\n\n        public GameView()\n        {\n            autoRepaintOnSceneChange = true;\n            InitializeZoomArea();\n            playModeViewName = \"GameView\";\n            clearColor = kClearBlack;\n            showGizmos = m_Gizmos;\n            targetDisplay = 0;\n            targetSize = new Vector2(640f, 480f);\n            textureFilterMode = FilterMode.Point;\n            textureHideFlags = HideFlags.HideAndDontSave;\n        }\n\n        public bool lowResolutionForAspectRatios\n        {\n            get\n            {\n                EnsureSelectedSizeAreValid();\n                return m_LowResolutionForAspectRatios[(int)currentSizeGroupType];\n            }\n            set\n            {\n                EnsureSelectedSizeAreValid();\n                if (value != m_LowResolutionForAspectRatios[(int)currentSizeGroupType])\n                {\n                    m_LowResolutionForAspectRatios[(int)currentSizeGroupType] = value;\n                    UpdateZoomAreaAndParent();\n\n                    if (currentGameViewSize.sizeType == GameViewSizeType.AspectRatio)\n                        SnapZoom(minScale);\n                }\n            }\n        }\n\n        public bool forceLowResolutionAspectRatios => backingScale == 1f;\n\n        public bool vSyncEnabled\n        {\n            get { return m_VSyncEnabled; }\n            set\n            {\n                if (value == m_VSyncEnabled)\n                    return;\n\n                SetVSync(value);\n                m_VSyncEnabled = value;\n            }\n        }\n\n        public int selectedSizeIndex\n        {\n            get\n            {\n                EnsureSelectedSizeAreValid();\n                return m_SelectedSizes[(int)currentSizeGroupType];\n            }\n            set\n            {\n                EnsureSelectedSizeAreValid();\n                m_SelectedSizes[(int)currentSizeGroupType] = value;\n            }\n        }\n\n        //This has been added to accomodate the test in PR for case 991291.\n        internal void SetTargetDisplay(int id)\n        {\n            if (id < 0 || id > 7)\n                return;\n            targetDisplay = id;\n            SetDisplayViewSize(id, targetSize);\n        }\n\n        static GameViewSizeGroupType currentSizeGroupType => GameViewSizes.instance.currentGroupType;\n\n        GameViewSize currentGameViewSize => GameViewSizes.instance.currentGroup.GetGameViewSize(selectedSizeIndex);\n\n        Rect GetViewInWindow(Rect pos)\n        {\n            if (showToolbar)\n                return new Rect(0, EditorGUI.kWindowToolbarHeight, pos.width, pos.height - EditorGUI.kWindowToolbarHeight);\n\n            return new Rect(0, 0, pos.width, pos.height);\n        }\n\n        Rect GetViewPixelRect(Rect viewRectInWindow)\n        {\n            return lowResolutionForAspectRatios? viewRectInWindow : EditorGUIUtility.PointsToPixels(viewRectInWindow);\n        }\n\n        // The area of the window that the rendered game view is limited to\n        Rect viewInWindow\n        {\n            get\n            {\n                return GetViewInWindow(position);\n            }\n        }\n\n        internal Vector2 targetRenderSize // Size of render target in pixels\n        {\n            get\n            {\n                var viewPixelRect = GetViewPixelRect(viewInWindow);\n                return GameViewSizes.GetRenderTargetSize(viewPixelRect, currentSizeGroupType, selectedSizeIndex, out m_TargetClamped);\n            }\n        }\n\n        // Area of the render target in zoom content space (it is centered in content space)\n        Rect targetInContent\n        {\n            get\n            {\n                var targetSizeCached = targetRenderSize;\n                return EditorGUIUtility.PixelsToPoints(new Rect(-0.5f * targetSizeCached, targetSizeCached));\n            }\n        }\n\n        Rect targetInView // Area of the render target in zoom view space\n        {\n            get\n            {\n                var targetInContentCached = targetInContent;\n                return new Rect(\n                    m_ZoomArea.DrawingToViewTransformPoint(targetInContentCached.position),\n                    m_ZoomArea.DrawingToViewTransformVector(targetInContentCached.size)\n                );\n            }\n        }\n\n        // The final image needs to be flipped upside-down if we use coordinates with zero at the top\n        Rect deviceFlippedTargetInView\n        {\n            get\n            {\n                if (!SystemInfo.graphicsUVStartsAtTop)\n                    return targetInView;\n                else\n                {\n                    var flippedTarget = targetInView;\n                    flippedTarget.y += flippedTarget.height;\n                    flippedTarget.height = -flippedTarget.height;\n                    return flippedTarget;\n                }\n            }\n        }\n\n        Rect viewInParent // The view area in parent view space\n        {\n            get\n            {\n                var viewInParent = viewInWindow;\n                var parentBorder = m_Parent.borderSize;\n                viewInParent.x += parentBorder.left;\n                // Note: DockArea has extra space on top of the tab area which is accounted for strangely.\n                // It is stored in borderSize.bottom but it should be added to the top instead\n                // @TODO: Make DockArea.borderSize more sensible (requires fixing all usages)\n                viewInParent.y += parentBorder.top + parentBorder.bottom;\n                return viewInParent;\n            }\n        }\n\n        Rect targetInParent // Area of the render target in parent view space\n        {\n            get\n            {\n                var targetInViewCached = targetInView;\n                return new Rect(targetInViewCached.position + viewInParent.position, targetInViewCached.size);\n            }\n        }\n\n        // Area for warnings such as no cameras rendering\n        Rect warningPosition => new Rect(\n            Mathf.Max((viewInWindow.size.x - kWarningSize.x) * 0.5f, viewInWindow.x),\n            Mathf.Max((viewInWindow.size.y - kWarningSize.y) * 0.5f, viewInWindow.y),\n            kWarningSize.x,\n            kWarningSize.y);\n\n        Vector2 gameMouseOffset { get { return -viewInWindow.position - targetInView.position; } }\n\n        float gameMouseScale { get { return backingScale / m_ZoomArea.scale.y; } }\n\n        private bool showToolbar\n        {\n            get => m_showToolbar;\n            set => m_showToolbar = value;\n        }\n\n        internal bool drawGizmos\n        {\n            get => m_Gizmos;\n            set => m_Gizmos = value;\n        }\n\n        void InitializeZoomArea()\n        {\n            m_ZoomArea = new ZoomableArea(true, false) {uniformScale = true, upDirection = ZoomableArea.YDirection.Negative};\n        }\n\n        private void UndoRedoPerformed(in UndoRedoInfo info)\n        {\n            Repaint();\n        }\n\n        public void OnEnable()\n        {\n            wantsLessLayoutEvents = true;\n            prevSizeGroupType = (int)currentSizeGroupType;\n            titleContent = GetLocalizedTitleContent();\n            UpdateZoomAreaAndParent();\n            showToolbar = ModeService.HasCapability(ModeCapability.GameViewToolbar, true);\n\n            ModeService.modeChanged += OnEditorModeChanged;\n            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;\n            Undo.undoRedoEvent += UndoRedoPerformed;\n\n            targetSize = targetRenderSize;\n            PlayModeAnalytics.GameViewEnableEvent();\n        }\n\n        public void OnDisable()\n        {\n            ModeService.modeChanged -= OnEditorModeChanged;\n            EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;\n            Undo.undoRedoEvent -= UndoRedoPerformed;\n\n            if (m_RenderTexture)\n            {\n                DestroyImmediate(m_RenderTexture);\n            }\n\n            PlayModeAnalytics.GameViewDisableEvent();\n        }\n\n        [UsedImplicitly] // This is here because NGUI uses it via reflection (noted in https://confluence.hq.unity3d.com/display/DEV/Game+View+Bucket)\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal static Vector2 GetSizeOfMainGameView()\n        {\n            return GetMainPlayModeViewTargetSize();\n        }\n\n        private void UpdateZoomAreaAndParent()\n        {\n            // Configure ZoomableArea for new resolution so that old resolution doesn't restrict scale\n            bool oldScaleWasDefault = Mathf.Approximately(m_ZoomArea.scale.y, m_defaultScale);\n            ConfigureZoomArea();\n            m_defaultScale = DefaultScaleForTargetInView(targetRenderSize, viewInWindow.size);\n            if (oldScaleWasDefault)\n            {\n                m_ZoomArea.SetTransform(Vector2.zero, Vector2.one * m_defaultScale);\n                EnforceZoomAreaConstraints();\n            }\n\n            m_LastWindowPixelSize = position.size * backingScale;\n            EditorApplication.SetSceneRepaintDirty();\n\n            // update the scale according to new resolution\n            m_ZoomArea.UpdateZoomScale(maxScale, minScale);\n        }\n\n        protected void AllowCursorLockAndHide(bool enable)\n        {\n            Unsupported.SetAllowCursorLock(enable, Unsupported.DisallowCursorLockReasons.Other);\n            Unsupported.SetAllowCursorHide(enable);\n        }\n\n        private void OnFocus()\n        {\n            SetFocus(true);\n            targetSize = targetRenderSize;\n        }\n\n        private void OnLostFocus()\n        {\n            // We unlock the cursor when the game view loses focus to allow the user to regain cursor control.\n            // Fix for 389362: Ensure that we do not unlock cursor during init of play mode. Because we could\n            // be maximizing game view, which causes a lostfocus on the original game view, in these situations we do\n            // not unlock cursor.\n            if (!EditorApplicationLayout.IsInitializingPlaymodeLayout())\n            {\n                AllowCursorLockAndHide(false);\n            }\n            SetFocus(false);\n        }\n\n        internal override void OnResized()\n        {\n            targetSize = targetRenderSize;\n        }\n\n        internal override void OnBackgroundViewResized(Rect pos)\n        {\n            // If we are switching from GameView to Simulator, this call will overwrite the value already written\n            //   by the SimulatorView since both tabs exist for a brief period of time. Don't do anything here\n            //   if this view is the one being switched out.\n            if (m_SwitchingPlayModeViewType)\n            {\n                return;\n            }\n\n            // Should only update the game view size if it's in Aspect Ratio mode, otherwise\n            // we keep the static size\n            Rect viewInWindow = GetViewInWindow(pos);\n            Rect viewPixelRect = GetViewPixelRect(viewInWindow);\n            var newTargetSize =\n                GameViewSizes.GetRenderTargetSize(viewPixelRect, currentSizeGroupType, selectedSizeIndex, out m_TargetClamped);\n\n            if (newTargetSize == GetDisplayViewSize(targetDisplay) && currentGameViewSize.sizeType != GameViewSizeType.AspectRatio)\n                return;\n            SetDisplayViewSize(targetDisplay, new Vector2(newTargetSize.x, newTargetSize.y));\n            UpdateZoomAreaAndParent();\n        }\n\n        // Call when number of available aspects can have changed (after deserialization or gui change)\n        private void EnsureSelectedSizeAreValid()\n        {\n            // Early out if no change was recorded\n            if (GameViewSizes.instance.GetChangeID() == m_SizeChangeID)\n                return;\n\n            m_SizeChangeID = GameViewSizes.instance.GetChangeID();\n\n            var sizeGroupTypes = System.Enum.GetValues(typeof(GameViewSizeGroupType));\n            // Ensure deserialized array is resized if needed\n            if (m_SelectedSizes.Length != sizeGroupTypes.Length)\n                System.Array.Resize(ref m_SelectedSizes, sizeGroupTypes.Length);\n\n            // Ensure deserialized selection index for each group is within valid range\n            foreach (GameViewSizeGroupType groupType in sizeGroupTypes)\n            {\n                var gvsg = GameViewSizes.instance.GetGroup(groupType);\n                var index = (int)groupType;\n                m_SelectedSizes[index] = Mathf.Clamp(m_SelectedSizes[index], 0, gvsg.GetTotalCount() - 1);\n            }\n\n            // Resize low resolution array as necessary, and fill in new indices with defaults\n            var lowResolutionSettingsLength = m_LowResolutionForAspectRatios.Length;\n            if (m_LowResolutionForAspectRatios.Length != sizeGroupTypes.Length)\n                System.Array.Resize(ref m_LowResolutionForAspectRatios, sizeGroupTypes.Length);\n            for (var groupIndex = lowResolutionSettingsLength; groupIndex < sizeGroupTypes.Length; ++groupIndex)\n                m_LowResolutionForAspectRatios[groupIndex] = GameViewSizes.DefaultLowResolutionSettingForSizeGroupType((GameViewSizeGroupType)sizeGroupTypes.GetValue(groupIndex));\n        }\n\n        private void OnSelectionChange()\n        {\n            if (m_Gizmos)\n                Repaint();\n        }\n\n        public virtual void AddItemsToMenu(GenericMenu menu)\n        {\n            if (RenderDoc.IsInstalled() && !RenderDoc.IsLoaded())\n            {\n                menu.AddItem(RenderDocUtil.LoadRenderDocMenuItem, false, RenderDoc.LoadRenderDoc);\n            }\n            menu.AddItem(Styles.noCameraWarningContextMenuContent, m_NoCameraWarning, ToggleNoCameraWarning);\n            menu.AddItem(Styles.clearEveryFrameContextMenuContent, m_ClearInEditMode, ToggleClearInEditMode);\n        }\n\n        private void ToggleNoCameraWarning()\n        {\n            m_NoCameraWarning = !m_NoCameraWarning;\n        }\n\n        private void ToggleClearInEditMode()\n        {\n            m_ClearInEditMode = !m_ClearInEditMode;\n        }\n\n        public void SizeSelectionCallback(int indexClicked, object objectSelected)\n        {\n            if (indexClicked != selectedSizeIndex)\n            {\n                selectedSizeIndex = indexClicked;\n                UpdateZoomAreaAndParent();\n                targetSize = targetRenderSize;\n                SceneView.RepaintAll();\n            }\n        }\n\n        void SnapZoomDelayed()\n        {\n            if (EditorApplication.timeSinceStartup > s_LastScrollTime + kScrollZoomSnapDelay)\n            {\n                EditorApplication.update -= SnapZoomDelayed;\n                SnapZoom(m_ZoomArea.scale.y);\n                Repaint();\n            }\n        }\n\n        void SnapZoom(float newZoom)\n        {\n            var logScale = Mathf.Log10(newZoom);\n            var logMin = Mathf.Log10(minScale);\n            var logMax = Mathf.Log10(maxScale);\n            var shortestSliderDistance = System.Single.MaxValue;\n            if (logScale > logMin && logScale < logMax)\n            {\n                for (var i = 1; i <= maxScale; ++i)\n                {\n                    // Snap distance is defined in points, so convert difference back to UI space\n                    var sliderDistanceToI = kScaleSliderMaxWidth * Mathf.Abs(logScale - Mathf.Log10(i)) / (logMax - logMin);\n                    if (sliderDistanceToI < kScaleSliderSnapThreshold && sliderDistanceToI < shortestSliderDistance)\n                    {\n                        newZoom = i;\n                        shortestSliderDistance = sliderDistanceToI;\n                    }\n                }\n            }\n\n            var areaInMargins = m_ZoomArea.shownAreaInsideMargins;\n            var focalPoint = areaInMargins.position + areaInMargins.size * 0.5f;\n            m_ZoomArea.SetScaleFocused(focalPoint, Vector2.one * newZoom);\n        }\n\n        void DoZoomSlider()\n        {\n            GUILayout.Label(Styles.zoomSliderContent);\n            EditorGUI.BeginChangeCheck();\n            // Zooming feels more natural on a log scale\n            var logScale = Mathf.Log10(m_ZoomArea.scale.y);\n            var logMin = Mathf.Log10(minScale);\n            var logMax = Mathf.Log10(maxScale);\n            logScale = GUILayout.HorizontalSlider(logScale, logMin, logMax, GUILayout.MaxWidth(kScaleSliderMaxWidth), GUILayout.MinWidth(kScaleSliderMinWidth));\n            if (EditorGUI.EndChangeCheck())\n            {\n                var newZoom = Mathf.Pow(10f, logScale);\n                SnapZoom(newZoom);\n            }\n            var scaleContent = EditorGUIUtility.TempContent(string.Format(\"{0}x\", (m_ZoomArea.scale.y).ToString(\"G2\", CultureInfo.InvariantCulture.NumberFormat)));\n            scaleContent.tooltip = Styles.zoomSliderContent.tooltip;\n            GUILayout.Label(scaleContent, GUILayout.Width(kScaleLabelWidth));\n            scaleContent.tooltip = string.Empty;\n        }\n\n        private bool ShouldShowMetalFrameCaptureGUI()\n        {\n            return FrameCapture.IsDestinationSupported(FrameCaptureDestination.DevTools)\n                || FrameCapture.IsDestinationSupported(FrameCaptureDestination.GPUTraceDocument);\n        }\n\n        private void DoToolbarGUI()\n        {\n            if (Event.current.isKey || Event.current.type == EventType.Used)\n                return;\n\n            GameViewSizes.instance.RefreshStandaloneAndRemoteDefaultSizes();\n\n            GUILayout.BeginHorizontal(EditorStyles.toolbar);\n            {\n                var availableTypes = GetAvailableWindowTypes();\n                if (availableTypes.Count > 1)\n                {\n                    var typeNames = availableTypes.Values.ToList();\n                    var types = availableTypes.Keys.ToList();\n                    int viewIndex = EditorGUILayout.Popup(typeNames.IndexOf(titleContent.text), typeNames.ToArray(),\n                        EditorStyles.toolbarPopup,\n                        GUILayout.Width(90));\n                    if (viewIndex == -1)\n                        viewIndex = 0;\n\n                    EditorGUILayout.Space();\n                    if (types[viewIndex] != typeof(GameView))\n                    {\n                        SwapMainWindow(types[viewIndex]);\n                    }\n                }\n\n                if (ModuleManager.ShouldShowMultiDisplayOption())\n                {\n                    int display = EditorGUILayout.Popup(targetDisplay, DisplayUtility.GetDisplayNames(), EditorStyles.toolbarPopupLeft, GUILayout.Width(80));\n                    if (display != targetDisplay)\n                    {\n                        targetDisplay = display;\n                        Display.activeEditorGameViewTarget  = targetDisplay;\n                        UpdateZoomAreaAndParent();\n                    }\n                }\n                EditorGUILayout.GameViewSizePopup(currentSizeGroupType, selectedSizeIndex, this, EditorStyles.toolbarPopup, GUILayout.Width(160f));\n\n                DoZoomSlider();\n                // If the previous platform and current does not match, update the scale\n                if ((int)currentSizeGroupType != prevSizeGroupType)\n                {\n                    UpdateZoomAreaAndParent();\n                    // Update the platform to the recent one\n                    prevSizeGroupType = (int)currentSizeGroupType;\n                }\n\n                if (FrameDebugger.IsLocalEnabled())\n                {\n                    GUILayout.FlexibleSpace();\n                    Color oldCol = GUI.color;\n                    // This has nothing to do with animation recording.  Can we replace this color with something else?\n                    GUI.color *= AnimationMode.recordedPropertyColor;\n                    GUILayout.Label(Styles.frameDebuggerOnContent, EditorStyles.toolbarLabel);\n                    GUI.color = oldCol;\n                    // Make frame debugger windows repaint after each time game view repaints.\n                    // We want them to always display the latest & greatest game view\n                    // rendering state.\n                    if (Event.current.type == EventType.Repaint)\n                        FrameDebuggerWindow.RepaintAll();\n                }\n\n                GUILayout.FlexibleSpace();\n                using (new EditorGUI.DisabledScope(EditorApplication.isPlaying && !EditorApplication.isPaused))\n                {\n                    enterPlayModeBehavior = (EnterPlayModeBehavior)EditorGUILayout.EnumPopup(enterPlayModeBehavior, EditorStyles.toolbarDropDown, GUILayout.Width(110));\n                }\n\n                if (ShouldShowMetalFrameCaptureGUI())\n                {\n                    if (GUILayout.Button(Styles.metalFrameCaptureContent, EditorStyles.toolbarButton))\n                        m_Parent.CaptureMetalScene();\n                }\n\n                if (GUILayout.Button(Styles.frameDebuggerContent, EditorStyles.toolbarButton))\n                    FrameDebuggerWindow.OpenWindowAndToggleEnabled();\n\n                if (RenderDoc.IsLoaded())\n                {\n                    using (new EditorGUI.DisabledScope(!RenderDoc.IsSupported()))\n                    {\n                        if (GUILayout.Button(Styles.renderdocContent, EditorStyles.toolbarButton))\n                        {\n                            RenderDoc.CaptureRenderDoc();\n                            GUIUtility.ExitGUI();\n                        }\n                    }\n                }\n\n                SubsystemManager.GetSubsystems(m_DisplaySubsystems);\n                // Allow the user to select how the XR device will be rendered during \"Play In Editor\"\n                if (m_DisplaySubsystems.Count != 0)\n                {\n                    if (m_DisplaySubsystems[0].disableLegacyRenderer)\n                    {\n                        // Handles the case where XRSDK is being used without the shim layer\n                        EditorGUI.BeginChangeCheck();\n                        int currentMirrorViewBlitMode = m_DisplaySubsystems[0].GetPreferredMirrorBlitMode();\n                        int currentRenderMode = XRTranslateMirrorViewBlitModeToRenderMode(currentMirrorViewBlitMode);\n                        int selectedRenderMode = EditorGUILayout.Popup(Mathf.Clamp(currentRenderMode, 0, Styles.xrRenderingModes.Length - 1), Styles.xrRenderingModes, EditorStyles.toolbarPopup, GUILayout.Width(80));\n                        int selectedMirrorViewBlitMode = XRTranslateRenderModeToMirrorViewBlitMode(selectedRenderMode);\n                        if (EditorGUI.EndChangeCheck() || currentMirrorViewBlitMode == 0)\n                        {\n                            m_DisplaySubsystems[0].SetPreferredMirrorBlitMode(selectedMirrorViewBlitMode);\n                            if (selectedMirrorViewBlitMode != m_XRRenderMode)\n                                ClearTargetTexture();\n\n                            m_XRRenderMode = selectedMirrorViewBlitMode;\n                        }\n                    }\n                    else\n                    {\n                        EditorGUI.BeginChangeCheck();\n                        GameViewRenderMode currentGameViewRenderMode = UnityEngine.XR.XRSettings.gameViewRenderMode;\n                        int selectedRenderMode = EditorGUILayout.Popup(Mathf.Clamp(((int)currentGameViewRenderMode) - 1, 0, Styles.xrRenderingModes.Length - 1), Styles.xrRenderingModes, EditorStyles.toolbarPopup, GUILayout.Width(80));\n                        if (EditorGUI.EndChangeCheck() && currentGameViewRenderMode != GameViewRenderMode.None)\n                        {\n                            SetXRRenderMode(selectedRenderMode);\n                        }\n                    }\n                }\n                GUILayout.FlexibleSpace();\n\n                EditorUtility.audioMasterMute = GUILayout.Toggle(EditorUtility.audioMasterMute,\n                    EditorUtility.audioMasterMute ? Styles.muteOnContent : Styles.muteOffContent, EditorStyles.toolbarButton);\n\n                ShortcutIntegration.ignoreWhenPlayModeFocused = GUILayout.Toggle(ShortcutIntegration.ignoreWhenPlayModeFocused,\n                    ShortcutIntegration.ignoreWhenPlayModeFocused ? Styles.shortcutsOffContent : Styles.shortcutsOnContent, EditorStyles.toolbarButton);\n\n                Styles.statsContent.tooltip = Styles.k_StatsTooltip;\n                var shortcutString = KeyCombination.SequenceToString(ShortcutManager.instance.GetShortcutBinding(Styles.k_StatsShortcutID).keyCombinationSequence);\n                if(!string.IsNullOrWhiteSpace(shortcutString))\n                    Styles.statsContent.tooltip += $\" ({shortcutString})\";\n\n                m_Stats = GUILayout.Toggle(m_Stats, Styles.statsContent, EditorStyles.toolbarButton);\n\n                if (EditorGUILayout.DropDownToggle(ref m_Gizmos, Styles.gizmosContent, EditorStyles.toolbarDropDownToggleRight))\n                {\n                    Rect rect = GUILayoutUtility.topLevel.GetLast();\n                    if (AnnotationWindow.ShowAtPosition(rect, true))\n                    {\n                        GUIUtility.ExitGUI();\n                    }\n                }\n            }\n            GUILayout.EndHorizontal();\n        }\n\n        [GameViewShortcut(Styles.k_StatsShortcutID)]\n        static void ToggleStats()\n        {\n            var gameView = GetLastFocusedPlayModeView() as GameView;\n            gameView.m_Stats = !gameView.m_Stats;\n            gameView.Repaint();\n        }\n\n        private int XRTranslateMirrorViewBlitModeToRenderMode(int mirrorViewBlitMode)\n        {\n            switch (mirrorViewBlitMode)\n            {\n                default:\n                    return 0;\n                case XRMirrorViewBlitMode.RightEye:\n                    return 1;\n                case XRMirrorViewBlitMode.SideBySide:\n                    return 2;\n                case XRMirrorViewBlitMode.SideBySideOcclusionMesh:\n                    return 3;\n                case XRMirrorViewBlitMode.MotionVectors:\n                    return 4;\n            }\n        }\n\n        private int XRTranslateRenderModeToMirrorViewBlitMode(int renderMode)\n        {\n            switch (renderMode)\n            {\n                default: // or 0\n                    return XRMirrorViewBlitMode.LeftEye;\n                case 1:\n                    return XRMirrorViewBlitMode.RightEye;\n                case 2:\n                    return XRMirrorViewBlitMode.SideBySide;\n                case 3:\n                    return XRMirrorViewBlitMode.SideBySideOcclusionMesh;\n                case 4:\n                    return XRMirrorViewBlitMode.MotionVectors;\n            }\n        }\n\n        private void SetXRRenderMode(int mode)\n        {\n            switch (mode)\n            {\n                default: // or 0\n                    UnityEngine.XR.XRSettings.gameViewRenderMode = UnityEngine.XR.GameViewRenderMode.LeftEye;\n                    break;\n                case 1:\n                    UnityEngine.XR.XRSettings.gameViewRenderMode = UnityEngine.XR.GameViewRenderMode.RightEye;\n                    break;\n                case 2:\n                    UnityEngine.XR.XRSettings.gameViewRenderMode = UnityEngine.XR.GameViewRenderMode.BothEyes;\n                    break;\n                case 3:\n                    UnityEngine.XR.XRSettings.gameViewRenderMode = UnityEngine.XR.GameViewRenderMode.OcclusionMesh;\n                    break;\n                case 4:\n                    UnityEngine.XR.XRSettings.gameViewRenderMode = UnityEngine.XR.GameViewRenderMode.MotionVectors;\n                    break;\n            }\n\n            if (mode != m_XRRenderMode)\n                ClearTargetTexture();\n\n            m_XRRenderMode = mode;\n        }\n\n        private void ClearTargetTexture()\n        {\n            if (m_RenderTexture && m_RenderTexture.IsCreated())\n            {\n                var previousTarget = RenderTexture.active;\n                RenderTexture.active = m_RenderTexture;\n                GL.Clear(true, true, kClearBlack);\n                RenderTexture.active = previousTarget;\n            }\n        }\n\n        private float ScaleThatFitsTargetInView(Vector2 targetInPixels, Vector2 viewInPoints)\n        {\n            var targetInPoints = EditorGUIUtility.PixelsToPoints(targetInPixels);\n            var viewToTargetRatio = new Vector2(viewInPoints.x / targetInPoints.x, viewInPoints.y / targetInPoints.y);\n            return Mathf.Min(viewToTargetRatio.x, viewToTargetRatio.y);\n        }\n\n        private float DefaultScaleForTargetInView(Vector2 targetToFit, Vector2 viewSize)\n        {\n            var scale = ScaleThatFitsTargetInView(targetToFit, viewSize);\n            if (scale > 1f)\n            {\n                scale = Mathf.Min(maxScale * backingScale, Mathf.FloorToInt(scale));\n            }\n            return scale;\n        }\n\n        private void ConfigureZoomArea()\n        {\n            m_ZoomArea.rect = viewInWindow;\n            // Sliders are sized with respect to canvas\n            var targetInContentCached = targetInContent;\n            m_ZoomArea.hBaseRangeMin = targetInContentCached.xMin;\n            m_ZoomArea.vBaseRangeMin = targetInContentCached.yMin;\n            m_ZoomArea.hBaseRangeMax = targetInContentCached.xMax;\n            m_ZoomArea.vBaseRangeMax = targetInContentCached.yMax;\n            // Restrict zooming\n            m_ZoomArea.hScaleMin = m_ZoomArea.vScaleMin = minScale;\n            m_ZoomArea.hScaleMax = m_ZoomArea.vScaleMax = maxScale;\n        }\n\n        private void EnforceZoomAreaConstraints()\n        {\n            var shownArea = m_ZoomArea.shownArea;\n            var targetInContentCached = targetInContent;\n\n            // When zoomed out, we disallow panning by automatically centering the view\n            if (shownArea.width > targetInContentCached.width)\n            {\n                shownArea.x = -0.5f * shownArea.width;\n            }\n            else\n            // When zoomed in, we prevent panning outside the render area\n            {\n                shownArea.x = Mathf.Clamp(shownArea.x, targetInContentCached.xMin, targetInContentCached.xMax - shownArea.width);\n            }\n            // Horizontal and vertical are separated because otherwise we get weird behaviour when only one is zoomed out\n            if (shownArea.height > targetInContent.height)\n            {\n                shownArea.y = -0.5f * shownArea.height;\n            }\n            else\n            {\n                shownArea.y = Mathf.Clamp(shownArea.y, targetInContentCached.yMin, targetInContentCached.yMax - shownArea.height);\n            }\n\n            m_ZoomArea.shownArea = shownArea;\n        }\n\n        public void RenderToHMDOnly()\n        {\n            var mousePos = Vector2.zero;\n            targetDisplay = 0;\n            targetSize = targetRenderSize;\n            showGizmos = false;\n            renderIMGUI = false;\n\n            m_RenderTexture = RenderView(mousePos, clearTexture: false);\n        }\n\n        private void OnPlayModeStateChanged(PlayModeStateChange state)\n        {\n            latestState = state;\n            if (state == PlayModeStateChange.EnteredPlayMode)\n            {\n                // Enable vsync in play mode to get as much as possible frame rate consistency\n                m_Parent.EnableVSync(m_VSyncEnabled);\n            }\n            else if (state == PlayModeStateChange.ExitingPlayMode)\n            {\n                m_Parent.EnableVSync(false);\n            }\n            else if (state == PlayModeStateChange.EnteredEditMode)\n            {\n                // UUM-76326 - Ensure CursorLock is disabled in EditMode in case a script locks it while\n                // exiting PlayMode. In this scenario, the cursor lock state is maintained and will re-engage\n                // in the next PlayMode session.\n                // NOTE: For safety the user must still click the GameView before cursor lock is allowed again.\n                AllowCursorLockAndHide(false);\n            }\n        }\n\n        void OnBecameVisible()\n        {\n            if (latestState == PlayModeStateChange.EnteredPlayMode)\n                m_Parent.EnableVSync(m_VSyncEnabled);\n\n            EditorApplication.update += RepaintIfNeeded;\n        }\n\n        void OnBecameInvisible()\n        {\n            EditorApplication.update -= RepaintIfNeeded;\n        }\n\n        void OnAddedAsTab()\n        {\n            if (latestState == PlayModeStateChange.EnteredPlayMode)\n                m_Parent.EnableVSync(m_VSyncEnabled);\n        }\n\n        void RepaintIfNeeded()\n        {\n            if (LODUtility.IsLODAnimatingOnDisplay(targetDisplay))\n                Repaint();\n        }\n\n        private void OnEditorModeChanged(ModeService.ModeChangedArgs args)\n        {\n            showToolbar = ModeService.HasCapability(ModeCapability.GameViewToolbar, true);\n            Repaint();\n        }\n\n        private bool HandleCommand(Event evt)\n        {\n            if (!EditorApplication.isPlayingOrWillChangePlaymode)\n                return false;\n\n            if (evt.type != EventType.ValidateCommand && evt.type != EventType.ExecuteCommand)\n                return false;\n\n            // Disable certain commands when in play mode with GameView focused. Executing commands has a noticeable\n            // impact on performance, especially when the default global shortcut is a single alphanumeric key.\n            switch (evt.commandName)\n            {\n                case EventCommandNames.FrameSelected:\n                case EventCommandNames.FrameSelectedWithLock:\n                    evt.Use();\n                    return true;\n\n                default:\n                    return false;\n            }\n        }\n\n        private void OnGUI()\n        {\n            Event evt = Event.current;\n            EventType type = evt.type;\n\n            if (HandleCommand(evt))\n                return;\n\n            if (position.size * backingScale != m_LastWindowPixelSize) // pixelsPerPoint only reliable in OnGUI()\n            {\n                UpdateZoomAreaAndParent();\n            }\n\n            if (showToolbar)\n                DoToolbarGUI();\n\n            if (type == EventType.MouseDown || type == EventType.MouseUp)\n            {\n                EditorApplication.globalEventHandler?.Invoke();\n                EditorApplication.shortcutHelperBarEventHandler?.Invoke();\n            }\n\n            // This isn't ideal. Custom Cursors set by editor extensions for other windows can leak into the game view.\n            // To fix this we should probably stop using the global custom cursor (intended for runtime) for custom editor cursors.\n            // This has been noted for Cursors tech debt.\n            if (EditorApplication.isPlayingOrWillChangePlaymode)\n                EditorGUIUtility.AddCursorRect(viewInWindow, MouseCursor.CustomCursor);\n\n            var playing = EditorApplication.isPlaying && !EditorApplication.isPaused;\n\n            // Gain mouse lock when clicking on game view content, unless game is paused\n            if (playing && type == EventType.MouseDown && viewInWindow.Contains(Event.current.mousePosition))\n            {\n                AllowCursorLockAndHide(true);\n            }\n            // Lose mouse lock when pressing escape\n            else if (type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)\n            {\n                AllowCursorLockAndHide(false);\n            }\n\n            // We hide sliders when playing, and also when we are zoomed out beyond canvas edges\n            var targetInContentCached = targetInContent;\n            m_ZoomArea.hSlider = !playing && m_ZoomArea.shownArea.width < targetInContentCached.width;\n            m_ZoomArea.vSlider = !playing && m_ZoomArea.shownArea.height < targetInContentCached.height;\n            m_ZoomArea.enableMouseInput = !playing;\n            ConfigureZoomArea();\n\n            // We don't want controls inside the GameView (e.g. the toolbar) to have keyboard focus while playing.\n            // The game should get the keyboard events.\n            if (playing)\n                EditorGUIUtility.keyboardControl = 0;\n\n            GUI.color = Color.white; // Get rid of play mode tint\n\n            var originalEventType = Event.current.type;\n\n            m_ZoomArea.BeginViewGUI();\n\n            // Window size might change on Layout event\n            if (type == EventType.Layout)\n                targetSize = targetRenderSize;\n\n            // Setup game view dimensions, so that player loop can use it for input\n            var gameViewTarget = GUIClip.UnclipToWindow(m_ZoomArea.drawRect);\n            if (m_Parent)\n            {\n                var zoomedTarget = new Rect(targetInView.position + gameViewTarget.position, targetInView.size);\n                SetParentGameViewDimensions(zoomedTarget, gameViewTarget, targetRenderSize);\n            }\n\n            var editorMousePosition = Event.current.mousePosition;\n            var gameMousePosition = (editorMousePosition + gameMouseOffset) * gameMouseScale;\n\n            if (type == EventType.Repaint)\n            {\n                GUI.Box(m_ZoomArea.drawRect, GUIContent.none, Styles.gameViewBackgroundStyle);\n\n                // Tonemapping for HDR targets\n                EditorGUIUtility.PerformTonemappingForGameView();\n\n                Vector2 oldOffset = GUIUtility.s_EditorScreenPointOffset;\n                GUIUtility.s_EditorScreenPointOffset = Vector2.zero;\n                SavedGUIState oldState = SavedGUIState.Create();\n\n                var clearTexture = m_ClearInEditMode && !EditorApplication.isPlaying;\n\n                var currentTargetDisplay = 0;\n                if (ModuleManager.ShouldShowMultiDisplayOption())\n                {\n                    // Display Targets can have valid targets from 0 to 7.\n                    System.Diagnostics.Debug.Assert(targetDisplay < 8, \"Display Target is Out of Range\");\n                    currentTargetDisplay = targetDisplay;\n                }\n\n                targetDisplay = currentTargetDisplay;\n                targetSize = targetRenderSize;\n                showGizmos = m_Gizmos;\n                clearColor = kClearBlack;\n                renderIMGUI = true;\n                viewPadding = targetInParent.position;\n                viewMouseScale = gameMouseScale;\n\n                if (renderViewCallNeededInOnGUI)\n                    m_RenderTexture = RenderView(gameMousePosition, clearTexture);\n\n                if (m_TargetClamped)\n                    Debug.LogWarningFormat(\"GameView reduced to a reasonable size for this system ({0}x{1})\", targetSize.x, targetSize.y);\n                EditorGUIUtility.SetupWindowSpaceAndVSyncInternal(GUIClip.Unclip(viewInWindow));\n\n                if (m_RenderTexture != null && m_RenderTexture.IsCreated())\n                {\n                    oldState.ApplyAndForget();\n                    GUIUtility.s_EditorScreenPointOffset = oldOffset;\n\n                    GUI.BeginGroup(m_ZoomArea.drawRect);\n                    // Actually draw the game view to the screen, without alpha blending\n                    Rect drawRect = deviceFlippedTargetInView;\n                    drawRect.x = Mathf.Round(drawRect.x);\n                    drawRect.y = Mathf.Round(drawRect.y);\n                    EditorGUIUtility.DrawTextureHdrSupport(drawRect, m_RenderTexture, new Rect(0, 0, 1, 1), 0, 0, 0, 0, GUI.color, GUI.blitMaterial, -1, true);\n                    GUI.EndGroup();\n                }\n            }\n            else if (type != EventType.Layout && type != EventType.Used)\n            {\n                if (Event.current.isKey && (!EditorApplication.isPlaying || EditorApplication.isPaused))\n                    return;\n\n                bool mousePosInGameViewRect = viewInWindow.Contains(Event.current.mousePosition);\n\n                // MouseDown events outside game view rect are not send to scripts but MouseUp events are (see below)\n                if (Event.current.rawType == EventType.MouseDown && !mousePosInGameViewRect)\n                    return;\n\n                var originalDisplayIndex = Event.current.displayIndex;\n\n                // Transform events into local space, so the mouse position is correct\n                // Then queue it up for playback during playerloop\n                Event.current.mousePosition = gameMousePosition;\n                Event.current.displayIndex = targetDisplay;\n\n                EditorGUIUtility.QueueGameViewInputEvent(Event.current);\n\n                // Placed after event queueing above to ensure scripts can react on mouse up events.\n                bool isKey = Event.current.rawType == EventType.KeyDown || Event.current.rawType == EventType.KeyUp;\n                bool useEvent = mousePosInGameViewRect || isKey;\n\n                // Don't use command events, or they won't be sent to other views.\n                if (type == EventType.ExecuteCommand || type == EventType.ValidateCommand)\n                    useEvent = false;\n\n                if (useEvent)\n                    Event.current.Use();\n                else\n                    Event.current.mousePosition = editorMousePosition;\n\n                // Reset display index\n                Event.current.displayIndex = originalDisplayIndex;\n            }\n\n            m_ZoomArea.EndViewGUI();\n\n            if (originalEventType == EventType.ScrollWheel && Event.current.type == EventType.Used)\n            {\n                EditorApplication.update -= SnapZoomDelayed;\n                EditorApplication.update += SnapZoomDelayed;\n                s_LastScrollTime = EditorApplication.timeSinceStartup;\n            }\n\n            EnforceZoomAreaConstraints();\n\n            if (m_RenderTexture)\n            {\n                if (m_ZoomArea.scale.y < 1f)\n                {\n                    m_RenderTexture.filterMode = FilterMode.Bilinear;\n                }\n                else\n                {\n                    m_RenderTexture.filterMode = FilterMode.Point;\n                }\n            }\n\n            if (m_NoCameraWarning && !EditorGUIUtility.IsDisplayReferencedByCameras(targetDisplay))\n            {\n                GUI.Label(warningPosition, GUIContent.none, EditorStyles.notificationBackground);\n                var displayName = ModuleManager.ShouldShowMultiDisplayOption() ? DisplayUtility.GetDisplayNames()[targetDisplay].text : string.Empty;\n                var cameraWarning = string.Format(\"{0}\\nNo cameras rendering\", displayName);\n                EditorGUI.DoDropShadowLabel(warningPosition, EditorGUIUtility.TempContent(cameraWarning), EditorStyles.notificationText, .3f);\n            }\n\n            if (m_Stats)\n                GameViewGUI.GameViewStatsGUI();\n        }\n\n        internal void SetCustomResolution(Vector2 res, string baseName)\n        {\n            GameViewSize customSize = null;\n            var idx = -1;\n            var sizes = GameViewSizes.instance.currentGroup;\n            for (var i = 0; i < sizes.GetTotalCount(); ++i)\n            {\n                var sz = sizes.GetGameViewSize(i);\n                if (sz.displayText.StartsWith(baseName))\n                {\n                    customSize= sz;\n                    idx = i;\n                    sz.width = (int)res.x;\n                    sz.height = (int)res.y;\n                    break;\n                }\n            }\n\n            if (customSize == null)\n            {\n                customSize = new GameViewSize(GameViewSizeType.FixedResolution, (int)res.x, (int) res.y, baseName);\n                idx = sizes.GetTotalCount();\n                sizes.AddCustomSize(customSize);\n            }\n\n            GameViewSizes.instance.SaveToHDD();\n\n            selectedSizeIndex = idx;\n            UpdateZoomAreaAndParent();\n            targetSize = targetRenderSize;\n            SceneView.RepaintAll();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GameView/GameViewSize.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\n\nnamespace UnityEditor\n{\n    internal enum GameViewSizeType\n    {\n        AspectRatio,\n        FixedResolution\n    }\n\n    [Serializable]\n    internal class GameViewSize\n    {\n        [SerializeField] string m_BaseText;\n        [SerializeField] GameViewSizeType m_SizeType;\n        [SerializeField] int m_Width;\n        [SerializeField] int m_Height;\n        [NonSerialized] string m_CachedDisplayText;\n        const int kMaxBaseTextLength = 40;\n        const int kMinResolution = 10;\n        const int kMinAspect = 0;\n        const int kMaxResolutionOrAspect = 99999;\n\n        public string baseText\n        {\n            get {return m_BaseText; }\n            set\n            {\n                var oldBaseText = m_BaseText;\n                m_BaseText = value;\n                if (m_BaseText.Length > kMaxBaseTextLength)\n                    m_BaseText = m_BaseText.Substring(0, kMaxBaseTextLength);\n                if (m_BaseText != oldBaseText)\n                    Changed();\n            }\n        }\n        public GameViewSizeType sizeType\n        {\n            get { return m_SizeType; }\n            set\n            {\n                var oldSizeType = m_SizeType;\n                m_SizeType = value;\n                Clamp();\n                if (m_SizeType != oldSizeType)\n                    Changed();\n            }\n        }\n        public int width\n        {\n            get { return m_Width; }\n            set\n            {\n                var oldWidth = m_Width;\n                m_Width = value;\n                Clamp();\n                if (m_Width != oldWidth)\n                    Changed();\n            }\n        }\n        public int height\n        {\n            get { return m_Height; }\n            set\n            {\n                var oldHeight = m_Height;\n                m_Height = value;\n                Clamp();\n                if (m_Height != oldHeight)\n                    Changed();\n            }\n        }\n\n        void Clamp()\n        {\n            int minValue = 0;\n            switch (sizeType)\n            {\n                case GameViewSizeType.AspectRatio:\n                    minValue = kMinAspect;\n                    break;\n                case GameViewSizeType.FixedResolution:\n                    minValue = kMinResolution;\n                    break;\n                default:\n                    Debug.LogError(\"Unhandled enum!\");\n                    break;\n            }\n\n            m_Width = Mathf.Clamp(m_Width, minValue, kMaxResolutionOrAspect);\n            m_Height = Mathf.Clamp(m_Height, minValue, kMaxResolutionOrAspect);\n        }\n\n        public GameViewSize(GameViewSizeType type, int width, int height, string baseText)\n        {\n            this.sizeType = type;\n            this.width = width;\n            this.height = height;\n            this.baseText = baseText;\n        }\n\n        public GameViewSize(GameViewSize other)\n        {\n            Set(other);\n        }\n\n        public void Set(GameViewSize other)\n        {\n            sizeType = other.sizeType;\n            width = other.width;\n            height = other.height;\n            baseText = other.baseText;\n        }\n\n        public bool isFreeAspectRatio\n        {\n            get { return (width == 0); }\n        }\n\n        public float aspectRatio\n        {\n            get\n            {\n                if (height == 0)\n                    return 0f;\n                return width / (float)height;\n            }\n        }\n\n        public string displayText\n        {\n            get { return m_CachedDisplayText ?? (m_CachedDisplayText = ComposeDisplayString()); }\n        }\n\n        private string sizeText\n        {\n            get\n            {\n                if (sizeType == GameViewSizeType.AspectRatio)\n                    return string.Format(\"{0}:{1} Aspect\", width, height);\n                else if (sizeType == GameViewSizeType.FixedResolution)\n                    return string.Format(\"{0}x{1}\", width, height);\n\n                Debug.LogError(\"Unhandled game view size type\");\n                return \"\";\n            }\n        }\n\n        private string ComposeDisplayString()\n        {\n            if (width == 0 && height == 0)\n                return baseText;\n\n            var size = sizeText;\n            if (string.IsNullOrEmpty(baseText))\n                return size;\n\n            // if base text already contains what we would append, there's no point in\n            // appending it again\n            if (sizeType == GameViewSizeType.FixedResolution)\n            {\n                if (baseText.Contains($\"{width}x{height}\") || baseText.Contains($\"{height}x{width}\"))\n                    return baseText;\n            }\n            if (sizeType == GameViewSizeType.AspectRatio)\n            {\n                if (baseText.Contains($\"{width}:{height}\") || baseText.Contains($\"{height}:{width}\"))\n                    return baseText;\n            }\n\n            return baseText + \" (\" + size + \")\";\n        }\n\n        private void Changed()\n        {\n            m_CachedDisplayText = null;\n            GameViewSizes.instance.Changed();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GameView/GameViewSizeGroup.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    internal class GameViewSizeGroup\n    {\n        [System.NonSerialized]\n        private List<GameViewSize> m_Builtin = new List<GameViewSize>();\n\n        [SerializeField]\n        private List<GameViewSize> m_Custom = new List<GameViewSize>();\n\n        // Builtin sizes first then custom sizes\n        public GameViewSize GetGameViewSize(int index)\n        {\n            if (index < m_Builtin.Count)\n                return m_Builtin[index];\n\n            index -= m_Builtin.Count;\n\n            if (index >= 0 && index < m_Custom.Count)\n                return m_Custom[index];\n\n            Debug.LogError(\"Invalid index \" + (index + m_Builtin.Count) +  \" \" + m_Builtin.Count + \" \" + m_Custom.Count);\n            return new GameViewSize(GameViewSizeType.AspectRatio, 0, 0, \"\");\n        }\n\n        public string[] GetDisplayTexts()\n        {\n            List<string> displayList = new List<string>();\n            foreach (GameViewSize size in m_Builtin)\n                displayList.Add(size.displayText);\n            foreach (GameViewSize size in m_Custom)\n                displayList.Add(size.displayText);\n            return displayList.ToArray();\n        }\n\n        public int GetTotalCount()\n        {\n            return m_Builtin.Count + m_Custom.Count;\n        }\n\n        public int GetBuiltinCount()\n        {\n            return m_Builtin.Count;\n        }\n\n        public int GetCustomCount()\n        {\n            return m_Custom.Count;\n        }\n\n        public void AddBuiltinSizes(params GameViewSize[] sizes)\n        {\n            for (int i = 0; i < sizes.Length; i++)\n                AddBuiltinSize(sizes[i]);\n        }\n\n        public void AddBuiltinSize(GameViewSize size)\n        {\n            m_Builtin.Add(size);\n            GameViewSizes.instance.Changed();\n        }\n\n        public void AddCustomSizes(params GameViewSize[] sizes)\n        {\n            for (int i = 0; i < sizes.Length; i++)\n                AddCustomSize(sizes[i]);\n        }\n\n        public void AddCustomSize(GameViewSize size)\n        {\n            m_Custom.Add(size);\n            GameViewSizes.instance.Changed();\n        }\n\n        public void RemoveCustomSize(int index)\n        {\n            int customIndex = TotalIndexToCustomIndex(index);\n            if (customIndex >= 0 && customIndex < m_Custom.Count)\n            {\n                m_Custom.RemoveAt(customIndex);\n                GameViewSizes.instance.Changed();\n            }\n            else\n            {\n                Debug.LogError(\"Invalid index \" + index + \" \" + m_Builtin.Count + \" \" + m_Custom.Count);\n            }\n        }\n\n        public bool IsCustomSize(int index)\n        {\n            if (index < m_Builtin.Count)\n                return false;\n            return true;\n        }\n\n        public int TotalIndexToCustomIndex(int index)\n        {\n            return index - m_Builtin.Count;\n        }\n\n        public int IndexOf(GameViewSize view)\n        {\n            int index = m_Builtin.IndexOf(view);\n            if (index >= 0)\n                return index;\n\n            return m_Custom.IndexOf(view);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GameView/GameViewSizeMenu.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\n\nnamespace UnityEditor\n{\n    // Resolution/Aspect ratio menu for the GameView, with an optional toggle for low-resolution aspect ratios\n    internal class GameViewSizeMenu : FlexibleMenu\n    {\n        static class Styles\n        {\n            public static GUIContent vSyncToggleContent = EditorGUIUtility.TrTextContent(\"VSync (Game view only)\", \"Enable VSync only for the game view while in playmode.\");\n        }\n        readonly Vector3 kMargins = new (9f, 7f);\n        IGameViewSizeMenuUser m_GameView;\n\n        float frameHeight { get { return kMargins.y * 2 + EditorGUI.kSingleLineHeight * (IsVSyncToggleVisible() ? 2 : 1);}}\n        float contentOffset { get { return frameHeight + EditorGUI.kControlVerticalSpacing; } }\n\n        public GameViewSizeMenu(IFlexibleMenuItemProvider itemProvider, int selectionIndex, FlexibleMenuModifyItemUI modifyItemUi, IGameViewSizeMenuUser gameView)\n            : base(itemProvider, selectionIndex, modifyItemUi, gameView.SizeSelectionCallback)\n        {\n            m_GameView = gameView;\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            var lowAspectRatiosContentSize = EditorStyles.toggle.CalcSize(GameView.Styles.lowResAspectRatiosContextMenuContent);\n            var size = CalcSize();\n            size.x = Mathf.Max(size.x, lowAspectRatiosContentSize.x + kMargins.x * 2);\n            size.y += frameHeight + EditorGUI.kControlVerticalSpacing + kMargins.y;\n            return size;\n        }\n\n        private bool IsVSyncToggleVisible()\n        {\n            // Only show the vsync toggle for editor supported gfx device backend.\n            var gfxDeviceType = SystemInfo.graphicsDeviceType;\n            return gfxDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Metal ||\n                gfxDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Vulkan ||\n                gfxDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Direct3D11 ||\n                gfxDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Direct3D12 ||\n                gfxDeviceType == UnityEngine.Rendering.GraphicsDeviceType.OpenGLCore;\n        }\n\n \n        private void DoVSyncToggle(Rect rect)\n        {\n            if (!IsVSyncToggleVisible())\n                return;\n            var toggleRect = new Rect(rect.xMin, rect.yMax + 2, rect.width, EditorGUI.kSingleLineHeight);\n            m_GameView.vSyncEnabled = GUI.Toggle(toggleRect, m_GameView.vSyncEnabled, Styles.vSyncToggleContent);\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            var frameRect = new Rect(rect.x, rect.y, rect.width, frameHeight);\n            GUI.Label(frameRect, \"\", EditorStyles.viewBackground);\n\n            GUI.enabled = !m_GameView.forceLowResolutionAspectRatios;\n\n            var toggleRect = new Rect(kMargins.x, kMargins.y, rect.width, EditorGUI.kSingleLineHeight);\n            m_GameView.lowResolutionForAspectRatios = GUI.Toggle(toggleRect, m_GameView.forceLowResolutionAspectRatios || m_GameView.lowResolutionForAspectRatios, GameView.Styles.lowResAspectRatiosContextMenuContent);\n\n            GUI.enabled = true;\n            DoVSyncToggle(toggleRect);\n\n            rect.height = rect.height - contentOffset;\n            rect.y = rect.y + contentOffset;\n            base.OnGUI(rect);\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/GameView/GameViewSizes.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditorInternal;\nusing System;\nusing UnityEditor.Callbacks;\n\nnamespace UnityEditor\n{\n    public enum GameViewSizeGroupType\n    {\n        Standalone,\n        [System.Obsolete(\"WebPlayer has been removed in 5.4\")]\n        WebPlayer,\n        iOS,\n        Android,\n        [System.Obsolete(\"PS3 has been removed in 5.5\", false)]\n        PS3,\n        [System.Obsolete(\"Wii U support was removed in 2018.1\", false)]\n        WiiU,\n        [System.Obsolete(\"Tizen has been removed in 2017.3\", false)]\n        Tizen,\n        [System.Obsolete(\"Windows Phone 8 was removed in 5.3\", false)]\n        WP8,\n        [System.Obsolete(\"Nintendo 3DS support is unavailable since 2018.1\")]\n        N3DS,\n        HMD\n    }\n\n    [FilePathAttribute(\"GameViewSizes.asset\", FilePathAttribute.Location.PreferencesFolder)]\n    internal class GameViewSizes : ScriptableSingleton<GameViewSizes>\n    {\n        // Written out to make it easy to find in text file (instead of an array)\n        [SerializeField] GameViewSizeGroup m_Standalone = new GameViewSizeGroup();\n        [SerializeField] GameViewSizeGroup m_iOS = new GameViewSizeGroup();\n        [SerializeField] GameViewSizeGroup m_Android = new GameViewSizeGroup();\n        [SerializeField] GameViewSizeGroup m_HMD = new GameViewSizeGroup();\n\n        [NonSerialized] GameViewSize m_Remote = null;\n        [NonSerialized] Vector2 m_LastRemoteScreenSize = new Vector2(-1, -1);\n        [NonSerialized] int m_ChangeID = 0;\n        [NonSerialized] static GameViewSizeGroupType s_GameViewSizeGroupType;\n\n        public GameViewSizeGroupType currentGroupType\n        {\n            get { return s_GameViewSizeGroupType; }\n        }\n\n        public GameViewSizeGroup currentGroup\n        {\n            get {return GetGroup(s_GameViewSizeGroupType); }\n        }\n\n        private void OnEnable()\n        {\n            RefreshGameViewSizeGroupType(BuildTarget.NoTarget, EditorUserBuildSettings.activeBuildTarget);\n        }\n\n        public GameViewSizeGroup GetGroup(GameViewSizeGroupType gameViewSizeGroupType)\n        {\n            InitBuiltinGroups();\n            switch (gameViewSizeGroupType)\n            {\n#pragma warning disable 618\n                case GameViewSizeGroupType.WebPlayer:\n                case GameViewSizeGroupType.WP8:\n                case GameViewSizeGroupType.PS3:\n                case GameViewSizeGroupType.Tizen:\n                case GameViewSizeGroupType.WiiU:\n                case GameViewSizeGroupType.N3DS:\n#pragma warning restore 618\n                case GameViewSizeGroupType.Standalone:\n                    return m_Standalone;\n                case GameViewSizeGroupType.iOS:\n                    return m_iOS;\n                case GameViewSizeGroupType.Android:\n                    return m_Android;\n                case GameViewSizeGroupType.HMD:\n                    return m_HMD;\n                default:\n                    Debug.LogError(\"Unhandled group enum! \" + gameViewSizeGroupType);\n                    break;\n            }\n            return m_Standalone;\n        }\n\n        public void SaveToHDD()\n        {\n            bool saveAsText = true;\n            Save(saveAsText);\n        }\n\n        public bool IsRemoteScreenSize(GameViewSizeGroupType gameViewSizeGroupType, int index)\n        {\n            return GetGroup(gameViewSizeGroupType).IndexOf(m_Remote) == index;\n        }\n\n        // returns true if screen size was changed\n        public void RefreshStandaloneAndRemoteDefaultSizes()\n        {\n            if (InternalEditorUtility.remoteScreenWidth != m_LastRemoteScreenSize.x ||\n                InternalEditorUtility.remoteScreenHeight != m_LastRemoteScreenSize.y)\n            {\n                m_LastRemoteScreenSize = new Vector2(InternalEditorUtility.remoteScreenWidth,\n                    InternalEditorUtility.remoteScreenHeight);\n                RefreshRemoteScreenSize((int)m_LastRemoteScreenSize.x, (int)m_LastRemoteScreenSize.y);\n            }\n\n            if (UnityEngine.XR.XRSettings.isDeviceActive &&\n                m_Remote.width != UnityEngine.XR.XRSettings.eyeTextureWidth &&\n                m_Remote.height != UnityEngine.XR.XRSettings.eyeTextureHeight)\n            {\n                RefreshRemoteScreenSize(UnityEngine.XR.XRSettings.eyeTextureWidth, UnityEngine.XR.XRSettings.eyeTextureHeight);\n            }\n        }\n\n        public void RefreshRemoteScreenSize(int width, int height)\n        {\n            m_Remote.width = width;\n            m_Remote.height = height;\n            if (width > 0 && height > 0)\n                m_Remote.baseText = \"Remote\";\n            else\n                m_Remote.baseText = \"Remote (Not Connected)\";\n            Changed();\n        }\n\n        public void Changed()\n        {\n            m_ChangeID++;\n        }\n\n        public int GetChangeID()\n        {\n            return m_ChangeID;\n        }\n\n        private void InitBuiltinGroups()\n        {\n            bool isInitialized = m_Standalone.GetBuiltinCount() > 0;\n            if (isInitialized)\n                return;\n\n            m_Remote = new GameViewSize(GameViewSizeType.FixedResolution, 0, 0, \"Remote (Not Connected)\");\n\n            // Standalone\n            GameViewSize kFree = new GameViewSize(GameViewSizeType.AspectRatio, 0, 0, \"Free Aspect\");\n            GameViewSize k16_10 = new GameViewSize(GameViewSizeType.AspectRatio, 16, 10, \"\");\n            GameViewSize k16_9 = new GameViewSize(GameViewSizeType.AspectRatio, 16, 9, \"\");\n            GameViewSize k_PC_1920x1080 = new GameViewSize(GameViewSizeType.FixedResolution, 1920, 1080, \"Full HD\");\n            GameViewSize k_PC_1366x768 = new GameViewSize(GameViewSizeType.FixedResolution, 1366, 768, \"WXGA\");\n            GameViewSize k_PC_2560x1440 = new GameViewSize(GameViewSizeType.FixedResolution, 2560, 1440, \"QHD\");\n            GameViewSize k_PC_3840x2160 = new GameViewSize(GameViewSizeType.FixedResolution, 3840, 2160, \"4K UHD\");\n\n            // all mobiles\n            GameViewSize k_4_3_Portrait = new GameViewSize(GameViewSizeType.AspectRatio, 3, 4, \"4:3 Portrait\");\n            GameViewSize k_4_3_Landscape = new GameViewSize(GameViewSizeType.AspectRatio, 4, 3, \"4:3 Landscape\");\n            GameViewSize k_16_9_Portrait = new GameViewSize(GameViewSizeType.AspectRatio, 9, 16, \"16:9 Portrait\");\n            GameViewSize k_16_9_Landscape = new GameViewSize(GameViewSizeType.AspectRatio, 16, 9, \"16:9 Landscape\");\n            GameViewSize k_18_9_Portrait = new GameViewSize(GameViewSizeType.AspectRatio, 9, 18, \"18:9 Portrait\");\n            GameViewSize k_18_9_Landscape = new GameViewSize(GameViewSizeType.AspectRatio, 18, 9, \"18:9 Landscape\");\n\n            GameViewSize k_1080p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1080, 1920, \"1920x1080 Portrait\");\n            GameViewSize k_1080p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 1920, 1080, \"1920x1080 Landscape\");\n            GameViewSize k_720p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 720, 1280, \"1280x720 Portrait\");\n            GameViewSize k_720p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 1280, 720, \"1280x720 Landscape\");\n\n            // iOS\n            // iPhone 5, 5c, 5s, SE (1st gen)\n            GameViewSize k_iPhone_640p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 640, 1136, \"iPhone SE (1st gen)   1136x640 Portrait\");\n            GameViewSize k_iPhone_640p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 1136, 640, \"iPhone SE (1st gen)   1136x640 Landscape\");\n            // iPhone 6, 6s, 7, 8, SE (2nd gen)\n            GameViewSize k_iPhone_750p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 750, 1334, \"iPhone SE (2nd gen)   1334x750 Portrait\");\n            GameViewSize k_iPhone_750p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 1334, 750, \"iPhone SE (2nd gen)   1334x750 Landscape\");\n            // iPhone XR, 11\n            GameViewSize k_iPhone_828p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 828, 1792, \"iPhone 11   1792x828 Portrait\");\n            GameViewSize k_iPhone_828p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 1792, 828, \"iPhone 11   1792x828 Landscape\");\n            // iPhone iPhone 6 Plus, 6s Plus, 7 Plus, 8 Plus\n            GameViewSize k_iPhone_1080p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1080, 1920, \"iPhone 8 Plus   1920x1080 Portrait\");\n            GameViewSize k_iPhone_1080p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 1920, 1080, \"iPhone 8 Plus   1920x1080 Landscape\");\n            // iPhone 12 mini\n            GameViewSize k_iPhone_2340x1080_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1080, 2340, \"iPhone 12 mini   2340x1080 Portrait\");\n            GameViewSize k_iPhone_2340x1080_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2340, 1080, \"iPhone 12 mini   2340x1080 Landscape\");\n            // iPhone X, XS, 11 Pro\n            GameViewSize k_iPhone_1125p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1125, 2436, \"iPhone 11 Pro   2436x1125 Portrait\");\n            GameViewSize k_iPhone_1125p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2436, 1125, \"iPhone 11 Pro   2436x1125 Landscape\");\n            // iPhone 12, 12 Pro\n            GameViewSize k_iPhone_1170p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1170, 2532, \"iPhone 12 Pro   2532x1170 Portrait\");\n            GameViewSize k_iPhone_1170p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2532, 1170, \"iPhone 12 Pro   2532x1170 Landscape\");\n            // iPhone XS Max, 11 Pro Max\n            GameViewSize k_iPhone_1242p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1242, 2688, \"iPhone 11 Pro Max   2688x1242 Portrait\");\n            GameViewSize k_iPhone_1242p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2688, 1242, \"iPhone 11 Pro Max   2688x1242 Landscape\");\n            // iPhone 12 Pro Max\n            GameViewSize k_iPhone_1284p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1284, 2778, \"iPhone 12 Pro Max   2778x1284 Portrait\");\n            GameViewSize k_iPhone_1284p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2778, 1284, \"iPhone 12 Pro Max   2778x1284 Landscape\");\n\n            // iPad Pro 9.7-inch, iPad (3rd-6th gen), Air 1-2, Mini (2-5th gen)\n            GameViewSize k_iPad_1536p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1536, 2048, \"iPad Pro 9.7\\\"   2048x1536 Portrait\");\n            GameViewSize k_iPad_1536p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2048, 1536, \"iPad Pro 9.7\\\"   2048x1536 Landscape\");\n            // iPad (7th-8th gen)\n            GameViewSize k_iPad_1620p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1620, 2160, \"iPad (8th gen)   2160x1620 Portrait\");\n            GameViewSize k_iPad_1620p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2160, 1620, \"iPad (8th gen)   2160x1620 Landscape\");\n            // iPad Air (4th gen)\n            GameViewSize k_iPad_1640p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1640, 2360, \"iPad Air (4th gen)   2360x1640 Portrait\");\n            GameViewSize k_iPad_1640p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2360, 1640, \"iPad Air (4th gen)   2360x1640 Landscape\");\n            // iPad Pro 10.5-inch, Air (3rd gen)\n            GameViewSize k_iPad_2224x1668_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1668, 2224, \"iPad Pro 10.5\\\"   2224x1668 Portrait\");\n            GameViewSize k_iPad_2224x1668_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2224, 1668, \"iPad Pro 10.5\\\"   2224x1668 Landscape\");\n            // iPad Pro 11-inch\n            GameViewSize k_iPad_2388x1668_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1668, 2388, \"iPad Pro 11\\\"   2388x1668 Portrait\");\n            GameViewSize k_iPad_2388x1668_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2388, 1668, \"iPad Pro 11\\\"   2388x1668 Landscape\");\n            // iPad Pro 12.9-inch\n            GameViewSize k_iPad_2048p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 2048, 2732, \"iPad Pro 12.9\\\"   2732x2048 Portrait\");\n            GameViewSize k_iPad_2048p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2732, 2048, \"iPad Pro 12.9\\\"   2732x2048 Landscape\");\n\n            // Android\n            GameViewSize k_800x480_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 480, 800, \"800x480 Portrait\");\n            GameViewSize k_800x480_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 800, 480, \"800x480 Landscape\");\n            GameViewSize k_2160x1080_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1080, 2160, \"2160x1080 Portrait\");\n            GameViewSize k_2160x1080_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2160, 1080, \"2160x1080 Landscape\");\n            GameViewSize k_2560x1440_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1440, 2560, \"2560x1440 Portrait\");\n            GameViewSize k_2560x1440_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2560, 1440, \"2560x1440 Landscape\");\n            GameViewSize k_2960x1440_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1440, 2960, \"2960x1440 Portrait\");\n            GameViewSize k_2960x1440_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2960, 1440, \"2960x1440 Landscape\");\n\n\n            m_Standalone.AddBuiltinSizes(kFree, k16_9, k16_10, k_PC_1920x1080, k_PC_1366x768, k_PC_2560x1440, k_PC_3840x2160);\n\n            m_iOS.AddBuiltinSizes(kFree,\n                k_iPhone_640p_Portrait, k_iPhone_640p_Landscape,\n                k_iPhone_750p_Portrait, k_iPhone_750p_Landscape,\n                k_iPhone_828p_Portrait, k_iPhone_828p_Landscape,\n                k_iPhone_1080p_Portrait, k_iPhone_1080p_Landscape,\n                k_iPhone_2340x1080_Portrait, k_iPhone_2340x1080_Landscape,\n                k_iPhone_1125p_Portrait, k_iPhone_1125p_Landscape,\n                k_iPhone_1170p_Portrait, k_iPhone_1170p_Landscape,\n                k_iPhone_1242p_Portrait, k_iPhone_1242p_Landscape,\n                k_iPhone_1284p_Portrait, k_iPhone_1284p_Landscape,\n                k_iPad_1536p_Portrait, k_iPad_1536p_Landscape,\n                k_iPad_1620p_Portrait, k_iPad_1620p_Landscape,\n                k_iPad_1640p_Portrait, k_iPad_1640p_Landscape,\n                k_iPad_2224x1668_Portrait, k_iPad_2224x1668_Landscape,\n                k_iPad_2388x1668_Portrait, k_iPad_2388x1668_Landscape,\n                k_iPad_2048p_Portrait, k_iPad_2048p_Landscape,\n                k_16_9_Portrait, k_16_9_Landscape,\n                k_4_3_Portrait, k_4_3_Landscape,\n                m_Remote);\n\n            m_Android.AddBuiltinSizes(kFree,\n                k_800x480_Portrait, k_800x480_Landscape,\n                k_720p_Portrait, k_720p_Landscape,\n                k_1080p_Portrait, k_1080p_Landscape,\n                k_2160x1080_Portrait, k_2160x1080_Landscape,\n                k_2560x1440_Portrait, k_2560x1440_Landscape,\n                k_2960x1440_Portrait, k_2960x1440_Landscape,\n                k_16_9_Portrait, k_16_9_Landscape,\n                k_18_9_Portrait, k_18_9_Landscape,\n                m_Remote);\n\n            m_HMD.AddBuiltinSizes(kFree, m_Remote);\n        }\n\n        internal static bool DefaultLowResolutionSettingForStandalone()\n        {\n            return GUIUtility.pixelsPerPoint <= 1.0f;\n        }\n\n        internal static bool DefaultLowResolutionSettingForSizeGroupType(GameViewSizeGroupType sizeGroupType)\n        {\n            switch (sizeGroupType)\n            {\n                case GameViewSizeGroupType.Standalone:\n                    return DefaultLowResolutionSettingForStandalone();\n                case GameViewSizeGroupType.iOS:\n                case GameViewSizeGroupType.Android:\n                default:\n                    return false;\n            }\n        }\n\n        private static void RefreshDerivedGameViewSize(GameViewSizeGroupType groupType, int gameViewSizeIndex, GameViewSize gameViewSize)\n        {\n            if (GameViewSizes.instance.IsRemoteScreenSize(groupType, gameViewSizeIndex))\n            {\n                int width = 0;\n                int height = 0;\n                if (UnityEngine.XR.XRSettings.isDeviceActive)\n                {\n                    width = UnityEngine.XR.XRSettings.eyeTextureWidth;\n                    height = UnityEngine.XR.XRSettings.eyeTextureHeight;\n                }\n                else\n                {\n                    width = (int)InternalEditorUtility.remoteScreenWidth;\n                    height = (int)InternalEditorUtility.remoteScreenHeight;\n                }\n\n                if (width > 0 && height > 0)\n                {\n                    gameViewSize.sizeType = GameViewSizeType.FixedResolution;\n                    gameViewSize.width = width;\n                    gameViewSize.height = height;\n                }\n                else\n                {\n                    // Free aspect if invalid remote width or height\n                    gameViewSize.sizeType = GameViewSizeType.AspectRatio;\n                    gameViewSize.width = gameViewSize.height = 0;\n                }\n            }\n        }\n\n        public static Rect GetConstrainedRect(Rect startRect, GameViewSizeGroupType groupType, int gameViewSizeIndex, out bool fitsInsideRect)\n        {\n            fitsInsideRect = true;\n            Rect constrainedRect = startRect;\n            GameViewSize gameViewSize = GameViewSizes.instance.GetGroup(groupType).GetGameViewSize(gameViewSizeIndex);\n            RefreshDerivedGameViewSize(groupType, gameViewSizeIndex, gameViewSize);\n\n            if (gameViewSize.isFreeAspectRatio)\n            {\n                return startRect;\n            }\n\n            float newRatio = 0;\n            bool useRatio;\n            switch (gameViewSize.sizeType)\n            {\n                case GameViewSizeType.AspectRatio:\n                {\n                    newRatio = gameViewSize.aspectRatio;\n                    useRatio = true;\n                }\n                break;\n                case GameViewSizeType.FixedResolution:\n                {\n                    if (gameViewSize.height > startRect.height || gameViewSize.width > startRect.width)\n                    {\n                        newRatio = gameViewSize.aspectRatio;\n                        useRatio = true;\n                        fitsInsideRect = false;\n                    }\n                    else\n                    {\n                        constrainedRect.height = gameViewSize.height;\n                        constrainedRect.width = gameViewSize.width;\n                        useRatio = false;\n                    }\n                }\n                break;\n                default:\n                    throw new ArgumentException(\"Unrecognized size type\");\n            }\n\n            if (useRatio)\n            {\n                constrainedRect.height = (constrainedRect.width / newRatio) > startRect.height\n                    ? (startRect.height)\n                    : (constrainedRect.width / newRatio);\n                constrainedRect.width = (constrainedRect.height * newRatio);\n            }\n\n            // clamp\n            constrainedRect.height = Mathf.Clamp(constrainedRect.height, 0f, startRect.height);\n            constrainedRect.width = Mathf.Clamp(constrainedRect.width, 0f, startRect.width);\n\n            // center\n            constrainedRect.y = (startRect.height * 0.5f - constrainedRect.height * 0.5f) + startRect.y;\n            constrainedRect.x = (startRect.width * 0.5f - constrainedRect.width * 0.5f) + startRect.x;\n\n            // Round to whole pixels - actually is important for correct rendering of game view!\n            constrainedRect.width = Mathf.Floor(constrainedRect.width + 0.5f);\n            constrainedRect.height = Mathf.Floor(constrainedRect.height + 0.5f);\n            constrainedRect.x = Mathf.Floor(constrainedRect.x + 0.5f);\n            constrainedRect.y = Mathf.Floor(constrainedRect.y + 0.5f);\n\n            return constrainedRect;\n        }\n\n        public static Vector2 GetRenderTargetSize(Rect startRect, GameViewSizeGroupType groupType, int gameViewSizeIndex, out bool clamped)\n        {\n            GameViewSize gameViewSize = GameViewSizes.instance.GetGroup(groupType).GetGameViewSize(gameViewSizeIndex);\n            RefreshDerivedGameViewSize(groupType, gameViewSizeIndex, gameViewSize);\n            Vector2 targetSize;\n            clamped = false;\n\n            // Free aspect takes up all available pixels by default\n            if (gameViewSize.isFreeAspectRatio)\n            {\n                targetSize = startRect.size;\n            }\n            else\n            {\n                switch (gameViewSize.sizeType)\n                {\n                    // Aspect ratio is enforced, but fills up as much game view as it can\n                    case GameViewSizeType.AspectRatio:\n                    {\n                        if (startRect.height == 0f || gameViewSize.aspectRatio == 0f)\n                        {\n                            targetSize = Vector2.zero;\n                            break;\n                        }\n                        var startRatio = startRect.width / startRect.height;\n                        if (startRatio < gameViewSize.aspectRatio)\n                        {\n                            targetSize = new Vector2(startRect.width, Mathf.Round(startRect.width / gameViewSize.aspectRatio));\n                        }\n                        else\n                        {\n                            targetSize = new Vector2(Mathf.Round(startRect.height * gameViewSize.aspectRatio), startRect.height);\n                        }\n                    }\n                    break;\n                    // Fixed resolution is fixed, but scaled down to fit, or scaled up to largest possible integer\n                    case GameViewSizeType.FixedResolution:\n                    {\n                        targetSize = new Vector2(gameViewSize.width, gameViewSize.height);\n                    }\n                    break;\n                    default:\n                        throw new ArgumentException(\"Unrecognized size type\");\n                }\n            }\n\n            // Prevent ludicrous render target sizes. Heuristics based on:\n            // - GPU supported max. texture size\n            // - \"should be enough for anyone\" (i.e. more than 8K resolution)\n            // - Available VRAM\n            //\n            // The reason is that while GPUs support large textures (e.g. 16k x 16k), trying to\n            // actually create one will just make you run out of memory. VRAM size estimate that we\n            // have is also only very approximate.\n            // Let's assume we can use 20% of VRAM for game view render target;\n            // and that we need 12 bytes/pixel (4 for color, double buffered, 4 for depth).\n            // Figure out what's the max texture area that fits there.\n            var maxVRAMArea = SystemInfo.graphicsMemorySize * 0.20f / 12f * 1024f * 1024f;\n\n            var targetArea = targetSize.x * targetSize.y;\n            if (targetArea > maxVRAMArea)\n            {\n                var aspect = targetSize.y / targetSize.x;\n                targetSize.x = Mathf.Sqrt(maxVRAMArea * aspect);\n                targetSize.y = aspect * targetSize.x;\n                clamped = true;\n            }\n\n            // Over 8K resolution (7680x4320) should be enough for anyone (tm)\n            var maxResolutionSize = 8192f;\n            var maxSize = Mathf.Min(SystemInfo.maxRenderTextureSize, maxResolutionSize);\n\n            if (targetSize.x > maxSize || targetSize.y > maxSize)\n            {\n                if (targetSize.x > targetSize.y)\n                    targetSize *= maxSize / targetSize.x;\n                else\n                    targetSize *= maxSize / targetSize.y;\n                clamped = true;\n            }\n\n            return targetSize;\n        }\n\n        class BuildTargetChangedHandler : Build.IActiveBuildTargetChanged\n        {\n            public int callbackOrder { get { return 0; } }\n\n            public void OnActiveBuildTargetChanged(BuildTarget oldTarget, BuildTarget newTarget)\n            {\n                RefreshGameViewSizeGroupType(oldTarget, newTarget);\n            }\n        }\n\n        static void RefreshGameViewSizeGroupType(BuildTarget oldTarget, BuildTarget newTarget)\n        {\n            s_GameViewSizeGroupType = BuildTargetGroupToGameViewSizeGroup(newTarget);\n        }\n\n        public static GameViewSizeGroupType BuildTargetGroupToGameViewSizeGroup(BuildTarget buildTarget)\n        {\n            if (UnityEngine.XR.XRSettings.enabled && UnityEngine.XR.XRSettings.showDeviceView)\n                return GameViewSizeGroupType.HMD;\n\n            if (BuildTargetDiscovery.TryGetBuildTarget(buildTarget, out IBuildTarget iBuildTarget))\n                return iBuildTarget.UIPlatformProperties?.GameViewSizeGroupType ?? GameViewSizeGroupType.Standalone;\n\n            return GameViewSizeGroupType.Standalone;\n        }\n    }\n}\n\n// namespace\n"
  },
  {
    "path": "Editor/Mono/GameView/GameViewSizesMenuItemProvider.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class GameViewSizesMenuItemProvider : IFlexibleMenuItemProvider\n    {\n        private readonly GameViewSizeGroup m_GameViewSizeGroup;\n\n        public GameViewSizesMenuItemProvider(GameViewSizeGroupType gameViewSizeGroupType)\n        {\n            m_GameViewSizeGroup = GameViewSizes.instance.GetGroup(gameViewSizeGroupType);\n        }\n\n        public int Count()\n        {\n            return m_GameViewSizeGroup.GetTotalCount();\n        }\n\n        public object GetItem(int index)\n        {\n            return m_GameViewSizeGroup.GetGameViewSize(index);\n        }\n\n        public int Add(object obj)\n        {\n            GameViewSize gameViewSize = CastToGameViewSize(obj);\n            if (gameViewSize == null)\n                return -1;\n\n            m_GameViewSizeGroup.AddCustomSize(gameViewSize);\n            GameViewSizes.instance.SaveToHDD();\n            return Count() - 1; // assumes that custom sizes is after builtin sizes\n        }\n\n        public void Replace(int index, object obj)\n        {\n            GameViewSize newResolution = CastToGameViewSize(obj);\n            if (newResolution == null)\n                return;\n\n            if (index < m_GameViewSizeGroup.GetBuiltinCount())\n            {\n                Debug.LogError(\"Only custom game view sizes can be changed\");\n                return;\n            }\n\n            GameViewSize gameViewSize = m_GameViewSizeGroup.GetGameViewSize(index);\n            if (gameViewSize != null)\n            {\n                gameViewSize.Set(newResolution);\n                GameViewSizes.instance.SaveToHDD();\n            }\n        }\n\n        public void Remove(int index)\n        {\n            if (index < m_GameViewSizeGroup.GetBuiltinCount())\n            {\n                Debug.LogError(\"Only custom game view sizes can be changed\");\n                return;\n            }\n\n            m_GameViewSizeGroup.RemoveCustomSize(index);\n            GameViewSizes.instance.SaveToHDD();\n        }\n\n        public object Create()\n        {\n            return new GameViewSize(GameViewSizeType.FixedResolution, 0, 0, \"\");\n        }\n\n        public void Move(int index, int destIndex, bool insertAfterDestIndex)\n        {\n            Debug.LogError(\"Missing impl\");\n        }\n\n        public string GetName(int index)\n        {\n            GameViewSize gameViewSize = m_GameViewSizeGroup.GetGameViewSize(index);\n            if (gameViewSize != null)\n                return gameViewSize.displayText;\n            return \"\";\n        }\n\n        public bool IsModificationAllowed(int index)\n        {\n            return m_GameViewSizeGroup.IsCustomSize(index); // builtin sizes cannot be modified\n        }\n\n        public int[] GetSeperatorIndices()\n        {\n            return new int[] {m_GameViewSizeGroup.GetBuiltinCount() - 1};\n        }\n\n        // Private section\n\n        private static GameViewSize CastToGameViewSize(object obj)\n        {\n            GameViewSize newResolution = obj as GameViewSize;\n            if (newResolution == null)\n                Debug.LogError(\"Incorrect input\");\n            return newResolution;\n        }\n    }\n}\n\n// namespace\n"
  },
  {
    "path": "Editor/Mono/GameView/GameViewSizesMenuModifyItemUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.StyleSheets;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class GameViewSizesMenuModifyItemUI : FlexibleMenuModifyItemUI\n    {\n        private static class Styles\n        {\n            public static GUIContent headerAdd = EditorGUIUtility.TrTextContent(\"Add\");\n            public static GUIContent headerEdit = EditorGUIUtility.TrTextContent(\"Edit\");\n            public static GUIContent typeName = EditorGUIUtility.TrTextContent(\"Type\");\n            public static GUIContent widthHeightText = EditorGUIUtility.TrTextContent(\"Width & Height\");\n            public static GUIContent optionalText = EditorGUIUtility.TrTextContent(\"Label\");\n            public static GUIContent ok = EditorGUIUtility.TrTextContent(\"OK\");\n            public static GUIContent cancel = EditorGUIUtility.TrTextContent(\"Cancel\");\n            public static GUIContent[] typeNames = new[] {EditorGUIUtility.TrTextContent(\"Aspect Ratio\"), EditorGUIUtility.TrTextContent(\"Fixed Resolution\")};\n\n            public static SVC<float> windowWidth = new SVC<float>(\"GameView\", \"--sizes-menu-modify-item-window-width\", 230f);\n            public static SVC<float> windowHeight = new SVC<float>(\"GameView\", \"--sizes-menu-modify-item-window-height\", 140f);\n            public static SVC<float> windowBottomPadding = new SVC<float>(\"GameView\", \"--window-bottom-padding\");\n            public static SVC<float> spaceBetweenOkCancelButtons = new SVC<float>(\"GameView\", \"--space-between-ok-cancel-buttons\", 10f);\n        }\n\n        private GameViewSize m_GameViewSize;\n\n        public override void OnClose()\n        {\n            m_GameViewSize = null;\n            base.OnClose();\n        }\n\n        override public Vector2 GetWindowSize()\n        {\n            return new Vector2(Styles.windowWidth, Styles.windowHeight);\n        }\n\n        override public void OnGUI(Rect rect)\n        {\n            GameViewSize gameViewSizeState = m_Object as GameViewSize;\n            if (gameViewSizeState == null)\n            {\n                Debug.LogError(\"Invalid object\");\n                return;\n            }\n\n            // We use a local gameviewsize to ensure we do not edit the original state (if user presses cancel state is not changed)\n            if (m_GameViewSize == null)\n                m_GameViewSize = new GameViewSize(gameViewSizeState);\n\n            bool validSettings = m_GameViewSize.width > 0 && m_GameViewSize.height > 0;\n            const float kColumnWidth = 90f;\n            const float kSpacing = 10f;\n\n            GUILayout.Space(3);\n            GUILayout.Label(m_MenuType == MenuType.Add ? Styles.headerAdd : Styles.headerEdit,\n                EditorStyles.boldLabel);\n\n            Rect seperatorRect = GUILayoutUtility.GetRect(1, 1);\n            FlexibleMenu.DrawRect(seperatorRect,\n                (EditorGUIUtility.isProSkin)\n                ? new Color(0.32f, 0.32f, 0.32f, 1.333f)\n                : new Color(0.6f, 0.6f, 0.6f, 1.333f));                      // dark : light\n            GUILayout.Space(4);\n\n            EditorGUIUtility.labelWidth = kSpacing + kColumnWidth;\n\n            // Optional text\n            m_GameViewSize.baseText = EditorGUILayout.TextField(Styles.optionalText, m_GameViewSize.baseText);\n\n            // Drop list (aspect / fixed res)\n            m_GameViewSize.sizeType = (GameViewSizeType)EditorGUILayout.Popup(Styles.typeName, (int)m_GameViewSize.sizeType, Styles.typeNames);\n\n            var wideMode = EditorGUIUtility.wideMode;\n            EditorGUIUtility.wideMode = true;\n            GUILayout.BeginHorizontal();\n            EditorGUILayout.PrefixLabel(Styles.widthHeightText);\n            var widthAndHeight = new Vector2Int(m_GameViewSize.width, m_GameViewSize.height);\n            widthAndHeight = EditorGUILayout.Vector2IntField(GUIContent.none, widthAndHeight, GUILayout.MaxWidth(Styles.windowWidth - EditorGUIUtility.labelWidth - EditorStyles.textField.padding.horizontal));\n            m_GameViewSize.width = widthAndHeight.x;\n            m_GameViewSize.height = widthAndHeight.y;\n            EditorGUIUtility.wideMode = wideMode;\n            GUILayout.EndHorizontal();\n\n            GUILayout.Space(Styles.spaceBetweenOkCancelButtons);\n\n            // Displayed text\n            float margin = 10f;\n            float cropWidth = rect.width - 2 * margin;\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(margin);\n            GUILayout.FlexibleSpace();\n            string displayText = m_GameViewSize.displayText;\n            using (new EditorGUI.DisabledScope(string.IsNullOrEmpty(displayText)))\n            {\n                if (string.IsNullOrEmpty(displayText))\n                    displayText = \"Result\";\n\n                var clipping = EditorStyles.label.clipping;\n                EditorStyles.label.clipping = TextClipping.Ellipsis;\n                GUILayout.Label(GUIContent.Temp(displayText), EditorStyles.label, GUILayout.MaxWidth(cropWidth));\n                EditorStyles.label.clipping = clipping;\n            }\n            GUILayout.FlexibleSpace();\n            GUILayout.Space(margin);\n            GUILayout.EndHorizontal();\n\n            EditorGUIUtility.labelWidth = 0;\n\n            GUILayout.Space(5f);\n\n            // Cancel, Ok\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(10);\n            if (GUILayout.Button(Styles.cancel))\n            {\n                editorWindow.Close();\n            }\n\n            using (new EditorGUI.DisabledScope(!validSettings))\n            {\n                if (GUILayout.Button(Styles.ok))\n                {\n                    gameViewSizeState.Set(m_GameViewSize);\n                    Accepted();\n                    editorWindow.Close();\n                }\n            }\n            GUILayout.Space(10);\n            GUILayout.EndHorizontal();\n\n            GUILayout.Space(Styles.windowBottomPadding);\n        }\n    }\n}\n\n// namespace\n"
  },
  {
    "path": "Editor/Mono/GameView/GameviewGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing System.Text;\nusing UnityEngine.Scripting;\nusing System.Globalization;\n\nnamespace UnityEditor\n{\n    internal class GameViewGUI\n    {\n        private static string FormatNumber(long num)\n        {\n            if (num < 1000)\n                return num.ToString(CultureInfo.InvariantCulture.NumberFormat);\n            if (num < 1000000)\n                return (num * 0.001).ToString(\"f1\", CultureInfo.InvariantCulture.NumberFormat) + \"k\";\n            return (num * 0.000001).ToString(\"f1\", CultureInfo.InvariantCulture.NumberFormat) + \"M\";\n        }\n\n        private static int m_FrameCounter = 0;\n        private static float m_ClientTimeAccumulator = 0.0f;\n        private static float m_RenderTimeAccumulator = 0.0f;\n        private static float m_MaxTimeAccumulator = 0.0f;\n        private static float m_ClientFrameTime = 0.0f;\n        private static float m_RenderFrameTime = 0.0f;\n        private static float m_MaxFrameTime = 0.0f;\n        private static GUIContent s_GraphicsText = EditorGUIUtility.TextContent(\"Graphics:\");\n\n        // Create label style from scene skin; add rich text support\n        private static GUIStyle s_LabelStyle;\n        private static GUIStyle labelStyle\n        {\n            get\n            {\n                if (s_LabelStyle == null)\n                {\n                    s_LabelStyle = new GUIStyle(\"label\");\n                    s_LabelStyle.richText = true;\n                }\n                return s_LabelStyle;\n            }\n        }\n\n        // Time per frame varies wildly, so we average a bit and display that.\n        private static void UpdateFrameTime()\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            float frameTime = UnityStats.frameTime;\n            float renderTime = UnityStats.renderTime;\n            m_ClientTimeAccumulator += frameTime;\n            m_RenderTimeAccumulator += renderTime;\n            if (Application.targetFrameRate <= 0 || !Unsupported.IsEditorPlayerLoopWaiting())\n                m_MaxTimeAccumulator += Mathf.Max(frameTime, renderTime);\n            else\n                m_MaxTimeAccumulator += Unsupported.GetFrameTimeCalculatedForEachEditorPlayerLoop();\n            ++m_FrameCounter;\n\n            bool needsTime = m_ClientFrameTime == 0.0f && m_RenderFrameTime == 0.0f;\n            bool resetTime = m_FrameCounter > 30 || m_ClientTimeAccumulator > 0.3f || m_RenderTimeAccumulator > 0.3f;\n\n            if (needsTime || resetTime)\n            {\n                m_ClientFrameTime = m_ClientTimeAccumulator / m_FrameCounter;\n                m_RenderFrameTime = m_RenderTimeAccumulator / m_FrameCounter;\n                m_MaxFrameTime = m_MaxTimeAccumulator / m_FrameCounter;\n            }\n            if (resetTime)\n            {\n                m_ClientTimeAccumulator = 0.0f;\n                m_RenderTimeAccumulator = 0.0f;\n                m_MaxTimeAccumulator = 0.0f;\n                m_FrameCounter = 0;\n            }\n        }\n\n        private static string FormatDb(float vol)\n        {\n            if (vol == 0.0f)\n                return \"-\\u221E dB\";\n            return string.Format(\"{0:F1} dB\", 20.0f * Mathf.Log10(vol));\n        }\n\n        [RequiredByNativeCode]\n        public static void GameViewStatsGUI()\n        {\n            var evt = Event.current;\n\n            if (evt.type != EventType.Layout && evt.type != EventType.Repaint)\n                return;\n\n            float w = 300, h = 229;\n\n            GUILayout.BeginArea(new Rect(GUIView.current.position.width - w - 10, 27, w, h), \"Statistics\", GUI.skin.window);\n\n            // Audio stats\n            bool audioOutputSuspended = UnityStats.audioOutputSuspended;\n            GUILayout.Label((audioOutputSuspended) ? \"Audio (suspended):\" : \"Audio:\", EditorStyles.boldLabel);\n            using (new EditorGUI.DisabledScope(audioOutputSuspended))\n            {\n                StringBuilder audioStats = new StringBuilder(400);\n                float audioLevel = UnityStats.audioLevel;\n                audioStats.Append(\"  Level: \" + FormatDb(audioLevel) + (EditorUtility.audioMasterMute ? \" (MUTED)\\n\" : \"\\n\"));\n                audioStats.Append(string.Format(\"  Clipping: {0:F1}%\", 100.0f * UnityStats.audioClippingAmount));\n                GUILayout.Label(audioStats.ToString());\n            }\n\n            GUI.Label(new Rect(170, 40, 120, 20), string.Format(\"DSP load: {0:F1}%\", 100.0f * UnityStats.audioDSPLoad));\n            GUI.Label(new Rect(170, 53, 120, 20), string.Format(\"Stream load: {0:F1}%\", 100.0f * UnityStats.audioStreamLoad));\n\n            EditorGUILayout.Space();\n\n            // Graphics stats\n            Rect graphicsLabelRect = GUILayoutUtility.GetRect(s_GraphicsText, EditorStyles.boldLabel);\n            GUI.Label(graphicsLabelRect, s_GraphicsText, EditorStyles.boldLabel);\n\n            // Time stats\n            UpdateFrameTime();\n\n            string timeStats = string.Format(\"- FPS (Playmode Off)\");\n            if (EditorApplication.isPlaying)\n            {\n                timeStats = string.Format(\"{0:F1} FPS ({1:F1}ms)\",\n                    1.0f / Mathf.Max(m_MaxFrameTime, 1.0e-5f), m_MaxFrameTime * 1000.0f);\n            }\n            GUI.Label(new Rect(170, graphicsLabelRect.y, 120, 20), timeStats);\n\n            int screenBytes = UnityStats.screenBytes;\n            int batchesSavedByDynamicBatching = UnityStats.dynamicBatchedDrawCalls - UnityStats.dynamicBatches;\n            int batchesSavedByStaticBatching = UnityStats.staticBatchedDrawCalls - UnityStats.staticBatches;\n            int batchesSavedByInstancing = UnityStats.instancedBatchedDrawCalls - UnityStats.instancedBatches;\n\n            StringBuilder gfxStats = new StringBuilder(400);\n            if (m_ClientFrameTime > m_RenderFrameTime)\n                gfxStats.Append(string.Format(\"  CPU: main <b>{0:F1}</b>ms  render thread {1:F1}ms\\n\", m_ClientFrameTime * 1000.0f, m_RenderFrameTime * 1000.0f));\n            else\n                gfxStats.Append(string.Format(\"  CPU: main {0:F1}ms  render thread <b>{1:F1}</b>ms\\n\", m_ClientFrameTime * 1000.0f, m_RenderFrameTime * 1000.0f));\n\n            gfxStats.Append(string.Format(\"  Batches: <b>{0}</b> \\tSaved by batching: {1}\\n\", UnityStats.batches, batchesSavedByDynamicBatching + batchesSavedByStaticBatching + batchesSavedByInstancing));\n            gfxStats.Append(string.Format(\"  Tris: {0} \\tVerts: {1} \\n\", FormatNumber(UnityStats.trianglesLong), FormatNumber(UnityStats.verticesLong)));\n            gfxStats.Append(string.Format(\"  Screen: {0} - {1}\\n\", UnityStats.screenRes, EditorUtility.FormatBytes(screenBytes)));\n            gfxStats.Append(string.Format(\"  SetPass calls: {0} \\tShadow casters: {1} \\n\", UnityStats.setPassCalls, UnityStats.shadowCasters));\n            gfxStats.Append(string.Format(\"  Visible skinned meshes: {0}\\n\", UnityStats.visibleSkinnedMeshes));\n            gfxStats.Append(string.Format(\"  Animation components playing: {0} \\n\", UnityStats.animationComponentsPlaying));\n            gfxStats.Append(string.Format(\"  Animator components playing: {0}\", UnityStats.animatorComponentsPlaying));\n            GUILayout.Label(gfxStats.ToString(), labelStyle);\n\n            GUILayout.EndArea();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GameView/IGameViewOnPlayMenuUser.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor\n{\n    internal interface IGameViewOnPlayMenuUser\n    {\n        void OnPlayPopupSelection(int indexClicked, object objectSelected);\n        bool playFocused { get; set; }\n        bool vSyncEnabled { get; set; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GameView/IGameViewSizeMenuUser.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor\n{\n    internal interface IGameViewSizeMenuUser\n    {\n        void SizeSelectionCallback(int indexClicked, object objectSelected);\n        bool lowResolutionForAspectRatios { get; set; }\n        bool forceLowResolutionAspectRatios { get; }\n        bool vSyncEnabled { get; set; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GenerateIconsWithMipLevels.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing UnityEditor;\nusing UnityEditor.Experimental;\nusing System.IO;\nusing System.Collections.Generic;\nusing UnityEngine.Experimental.Rendering;\n\n/* Some notes on icon caches and loading\n *\n *\n * Caches:\n *       Icon name to Texture2D:\n *          gNamedTextures (ObjectImages::Texture2DNamed): string to Texture2D\n *\n *      InstanceID to Image\n *          gCachedThumbnails (AssetImporter::GetThumbnailForInstanceID) : where image is retrieved from Texture from gNamedTextures\n *          Used for setting icon for hierarchyProperty\n *\n *      InstanceID to Texture2D\n *          ms_HackedCache (AssetDatabaseProperty::GetCachedAssetDatabaseIcon) : where tetxure2D icon is generated from the image from gCachedThumbnails\n *          Cache max size: 200\n *          Called from C# by AssetDatabase.GetCachedIcon (string assetpath)\n *\n *\n *\n *\n    Icon loading in editor_resources project:\n    - Texture2DNamed handles reading local files instead of editor resources bundle\n\n    Icon loading in other projects\n    - When reimport of asset (cpp): AssetDatabase::ImportAsset -> MonoImporter::GenerateAssetData -> ImageForMonoScript -> GetImageNames -> ObjectImages::Texture2DNamed\n    - IconContent -> LoadIconRequired -> LoadIcon -> LoadIconForSkin -> Load (EditorResources.iconsPath + name) as Texture2D;\n    - AssetDatabase.GetCachedIcon (assetpath) -> CPP -> AssetDatabaseProperty::GetCachedAssetDatabaseIcon\n    - InternalEditorUtility.GetIconForFile (filename) -> EditorGUIUtility.FindTexture(\"boo Script Icon\") -> CPP -> ObjectImages::Texture2DNamed(cpp)\n\n    */\n\nnamespace UnityEditorInternal\n{\n    public class GenerateIconsWithMipLevels\n    {\n        private const string k_IconSourceFolder = \"Assets/MipLevels For Icons/\";\n        private const string k_IconTargetFolder = \"Assets/Editor Default Resources/Icons/Processed\";\n        private const string k_IconMipIdentifier = \"@\";\n\n        class InputData\n        {\n            public string sourceFolder;\n            public string targetFolder;\n            public string mipIdentifier;\n            public string mipFileExtension;\n            public readonly List<string> generatedFileNames = new List<string>(); // for internal use\n        }\n\n        private static InputData GetInputData()\n        {\n            return new InputData\n            {\n                sourceFolder = EditorResources.ExpandPath(k_IconSourceFolder),\n                targetFolder = EditorResources.ExpandPath(k_IconTargetFolder),\n                mipIdentifier = k_IconMipIdentifier,\n                mipFileExtension = \"png\"\n            };\n        }\n\n        // Called from BuildEditorAssetBundles\n        [RequiredByNativeCode]\n        public static void GenerateAllIconsWithMipLevels()\n        {\n            var data = GetInputData();\n\n            EnsureFolderIsCreated(data.targetFolder);\n\n            float startTime = Time.realtimeSinceStartup;\n            GenerateIconsWithMips(data);\n            Debug.Log(string.Format(\"Generated {0} icons with mip levels in {1} seconds\", data.generatedFileNames.Count, Time.realtimeSinceStartup - startTime));\n\n            RemoveUnusedFiles(data.generatedFileNames);\n            AssetDatabase.Refresh(); // For some reason we creash if we dont refresh twice...\n            InternalEditorUtility.RepaintAllViews();\n        }\n\n        public static bool VerifyIconPath(string assetPath, bool logError)\n        {\n            if (string.IsNullOrEmpty(assetPath))\n            {\n                return false;\n            }\n            else if (assetPath.IndexOf(k_IconSourceFolder, StringComparison.Ordinal) < 0)\n            {\n                if (logError)\n                    Debug.Log(\"Selection is not a valid mip texture, it should be located in: \" + k_IconSourceFolder);\n                return false;\n            }\n            else if (assetPath.IndexOf(k_IconMipIdentifier, StringComparison.Ordinal) < 0)\n            {\n                if (logError)\n                    Debug.Log(\"Selection does not have a valid mip identifier \" + assetPath + \"  \" + k_IconMipIdentifier);\n                return false;\n            }\n            return true;\n        }\n\n        // Refresh just one icon (Used in Editor Resources project, find it in Tools/)\n        [RequiredByNativeCode]\n        public static void GenerateSelectedIconsWithMips()\n        {\n            // If no selection do all\n            if (Selection.activeInstanceID == 0)\n            {\n                Debug.Log(\"Ensure to select a mip texture...\" + Selection.activeInstanceID);\n                return;\n            }\n\n            int instanceID = Selection.activeInstanceID;\n            string assetPath = AssetDatabase.GetAssetPath(instanceID);\n\n            GenerateIconWithMipLevels(assetPath, null, null);\n        }\n\n        // Refresh just one icon with provided mip levels\n        public static void GenerateIconWithMipLevels(string assetPath, Dictionary<int, Texture2D> mipTextures, FileInfo fileInfo)\n        {\n            if (!VerifyIconPath(assetPath, true))\n                return;\n\n            float startTime = Time.realtimeSinceStartup;\n            var data = GetInputData();\n            string baseName = assetPath.Replace(data.sourceFolder, \"\");\n            baseName = baseName.Substring(0, baseName.LastIndexOf(data.mipIdentifier, StringComparison.Ordinal));\n\n            string cwd = new DirectoryInfo(data.sourceFolder).FullName;\n            List<string> assetPaths = GetIconAssetPaths(cwd, data.sourceFolder, data.mipIdentifier, data.mipFileExtension);\n\n            EnsureFolderIsCreated(data.targetFolder);\n            if (GenerateIcon(data, baseName, assetPaths, mipTextures, fileInfo))\n                Debug.Log(string.Format(\"Generated {0} icon with mip levels in {1} seconds\", baseName, Time.realtimeSinceStartup - startTime));\n            InternalEditorUtility.RepaintAllViews();\n        }\n\n        // Search for the mip level encoded in the asset path\n        public static int MipLevelForAssetPath(string assetPath, string separator)\n        {\n            if (string.IsNullOrEmpty(assetPath) || string.IsNullOrEmpty(separator))\n                return -1;\n\n            int separatorIndex = assetPath.IndexOf(separator, StringComparison.Ordinal);\n            if (separatorIndex == -1)\n            {\n                Debug.LogError(\"\\\"\" + separator + \"\\\" could not be found in asset path: \" + assetPath);\n                return -1;\n            }\n\n            int startIndex = separatorIndex + separator.Length;\n            int endIndex = assetPath.IndexOf(\".\", startIndex, StringComparison.Ordinal);\n            if (endIndex == -1)\n            {\n                Debug.LogError(\"Could not find path extension in asset path: \" + assetPath);\n                return -1;\n            }\n\n            return Int32.Parse(assetPath.Substring(startIndex, endIndex - startIndex));\n        }\n\n        // Private section\n        //----------------\n        private static void GenerateIconsWithMips(InputData inputData)\n        {\n            string cwd = new DirectoryInfo(inputData.sourceFolder).FullName;\n            List<string> files = GetIconAssetPaths(cwd, inputData.sourceFolder, inputData.mipIdentifier, inputData.mipFileExtension);\n\n            if (files.Count == 0)\n            {\n                Debug.LogWarning(\"No mip files found for generating icons! Searching in: \" + inputData.sourceFolder + \", for files with extension: \" + inputData.mipFileExtension);\n            }\n\n            string[] baseNames = GetBaseNames(inputData, files);\n\n            // Base name is assumed to be like: \"Assets/Icons/...\"\n            foreach (string baseName in baseNames)\n                GenerateIcon(inputData, baseName, files, null, null);\n        }\n\n        private static bool GenerateIcon(InputData inputData, string baseName, List<string> assetPathsOfAllIcons, Dictionary<int, Texture2D> mipTextures, FileInfo sourceFileInfo)\n        {\n            //We need to create the folder before we Create the Asset.\n            //AssetDatabase.CreateFolder will trigger a Asset Garbage Collection and stack items are not preserved.\n            string generatedPath = inputData.targetFolder + \"/\" + baseName + \" Icon\" + \".asset\";\n\n            if (sourceFileInfo != null && File.Exists(generatedPath))\n            {\n                var fileInfo = new FileInfo(generatedPath);\n                if (fileInfo.LastWriteTime > sourceFileInfo.LastWriteTime)\n                {\n                    // The resulting MIPS is newer than the source. Nothing to do.\n                    return false;\n                }\n            }\n\n            Debug.Log(\"Generating MIP levels for \" + generatedPath);\n\n            EnsureFolderIsCreatedRecursively(Path.GetDirectoryName(generatedPath));\n\n            Texture2D iconWithMips = CreateIconWithMipLevels(inputData, baseName, assetPathsOfAllIcons, mipTextures);\n            if (iconWithMips == null)\n            {\n                Debug.Log(\"CreateIconWithMipLevels failed\");\n                return false;\n            }\n\n            iconWithMips.name = baseName + \" Icon\" + \".png\"; // asset name must have .png as extension (used when loading the icon, search for LoadIconForSkin)\n            // Write texture to disk\n\n\n            AssetDatabase.CreateAsset(iconWithMips, generatedPath);\n            inputData.generatedFileNames.Add(generatedPath);\n\n            return true;\n        }\n\n        private static Texture2D CreateIconWithMipLevels(InputData inputData, string baseName, List<string> assetPathsOfAllIcons, Dictionary<int, Texture2D> mipTextures)\n        {\n            List<string> allMipPaths = assetPathsOfAllIcons.FindAll(o => o.IndexOf('/' + baseName + inputData.mipIdentifier, StringComparison.Ordinal) >= 0);\n            List<Texture2D> allMips = new List<Texture2D>();\n            foreach (string path in allMipPaths)\n            {\n                int mipLevel = MipLevelForAssetPath(path, inputData.mipIdentifier);\n\n                Texture2D mip;\n                if (mipTextures != null && mipTextures.ContainsKey(mipLevel))\n                    mip = mipTextures[mipLevel];\n                else\n                    mip = GetTexture2D(path);\n\n                if (mip != null)\n                    allMips.Add(mip);\n                else\n                    Debug.LogError(\"Mip not found \" + path);\n            }\n\n            // Sort the mips by size (largest mip first)\n            allMips.Sort(delegate(Texture2D first, Texture2D second)\n            {\n                if (first.width == second.width)\n                    return 0;\n                else if (first.width < second.width)\n                    return 1;\n                else\n                    return -1;\n            });\n\n            int minResolution = 99999;\n            int maxResolution = 0;\n\n            foreach (Texture2D mip in allMips)\n            {\n                int width = mip.width;\n                if (width > maxResolution)\n                    maxResolution = width;\n                if (width < minResolution)\n                    minResolution = width;\n            }\n\n            if (maxResolution == 0)\n                return null;\n\n            // Create our icon\n            Texture2D iconWithMips = new Texture2D(maxResolution, maxResolution, GraphicsFormat.R8G8B8A8_SRGB, -1, TextureCreationFlags.MipChain);\n\n            // Add max mip\n            if (BlitMip(iconWithMips, allMips, 0))\n                iconWithMips.Apply(true);\n            else\n                return iconWithMips; // ERROR\n\n            // Keep for debugging\n            //Debug.Log (\"Processing max mip file: \" + inputData.GetMipFileName (baseName, maxResolution) );\n\n            // Now add the rest\n            int resolution = maxResolution;\n            for (int i = 1; i < iconWithMips.mipmapCount; i++)\n            {\n                resolution /= 2;\n                if (resolution < minResolution)\n                    break;\n\n                BlitMip(iconWithMips, allMips, i);\n            }\n            iconWithMips.Apply(false, true);\n\n\n            return iconWithMips;\n        }\n\n        private static bool BlitMip(Texture2D iconWithMips, List<Texture2D> sortedTextures, int mipLevel)\n        {\n            if (mipLevel < 0 || mipLevel >= sortedTextures.Count)\n            {\n                Debug.LogError(\"Invalid mip level: \" + mipLevel);\n                return false;\n            }\n\n            Texture2D tex = sortedTextures[mipLevel];\n            if (tex)\n            {\n                Blit(tex, iconWithMips, mipLevel);\n                return true;\n            }\n            else\n            {\n                Debug.LogError(\"No texture at mip level: \" + mipLevel);\n            }\n\n            return false;\n        }\n\n        private static Texture2D GetTexture2D(string path)\n        {\n            return AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D;\n        }\n\n        static List<string> GetIconAssetPaths(string absolute, string folderPath, string mustHaveIdentifier, string extension)\n        {\n            Uri absoluteUri = new Uri(absolute);\n            List<string> files =  new List<string>(Directory.GetFiles(absolute, \"*.\" + extension, SearchOption.AllDirectories));\n            files.RemoveAll(o => o.IndexOf(mustHaveIdentifier, StringComparison.Ordinal) < 0); // // Remove all files that do not have the 'mustHaveIdentifier'\n            for (int i = 0; i < files.Count; ++i)\n            {\n                Uri fileUri = new Uri(files[i]);\n                Uri relativeUri = absoluteUri.MakeRelativeUri(fileUri);\n                files[i] = Uri.UnescapeDataString(folderPath + relativeUri);\n            }\n            return files;\n        }\n\n        static void Blit(Texture2D source, Texture2D dest, int mipLevel)\n        {\n            Color32[] pixels = source.GetPixels32();\n            for (int i = 0; i < pixels.Length; i++)\n            {\n                Color32 p = pixels[i];\n                if (p.a >= 3)\n                    p.a -= 3;\n                pixels[i] = p;\n            }\n            dest.SetPixels32(pixels, mipLevel);\n        }\n\n        private static void EnsureFolderIsCreatedRecursively(string targetFolder)\n        {\n            if (AssetDatabase.GetMainAssetInstanceID(targetFolder) == 0)\n            {\n                EnsureFolderIsCreatedRecursively(Path.GetDirectoryName(targetFolder));\n                Debug.Log(\"Created target folder \" + targetFolder);\n                AssetDatabase.CreateFolder(Path.GetDirectoryName(targetFolder), Path.GetFileName(targetFolder));\n            }\n        }\n\n        private static void EnsureFolderIsCreated(string targetFolder)\n        {\n            if (AssetDatabase.GetMainAssetInstanceID(targetFolder) == 0)\n            {\n                Debug.Log(\"Created target folder \" + targetFolder);\n                AssetDatabase.CreateFolder(Path.GetDirectoryName(targetFolder), Path.GetFileName(targetFolder));\n            }\n        }\n\n        static void DeleteFile(string file)\n        {\n            if (AssetDatabase.GetMainAssetInstanceID(file) != 0)\n            {\n                Debug.Log(\"Deleted unused file: \" + file);\n                AssetDatabase.DeleteAsset(file);\n            }\n        }\n\n        // Get rid of old icons in the Icons folder (with same filename as a generated icon)\n        static void RemoveUnusedFiles(List<string> generatedFiles)\n        {\n            foreach (string file in generatedFiles)\n            {\n                string deleteFile = file.Replace(\"Icons/Processed\", \"Icons\");\n                deleteFile = deleteFile.Replace(\".asset\", \".png\");\n                DeleteFile(deleteFile);\n\n                // Remove the d_ version as well\n                string fileName = Path.GetFileNameWithoutExtension(deleteFile);\n                if (!fileName.StartsWith(\"d_\"))\n                {\n                    deleteFile = deleteFile.Replace(fileName, (\"d_\" + fileName));\n                    DeleteFile(deleteFile);\n                }\n            }\n            AssetDatabase.Refresh();\n        }\n\n        private static string[] GetBaseNames(InputData inputData, List<string> files)\n        {\n            string[] baseNames = new string[files.Count];\n            int startPos = inputData.sourceFolder.Length;\n            for (int i = 0; i < files.Count; ++i)\n            {\n                baseNames[i] = files[i].Substring(startPos, files[i].IndexOf(inputData.mipIdentifier, StringComparison.Ordinal) - startPos);\n            }\n            HashSet<string> hashset = new HashSet<string>(baseNames);\n            baseNames = new string[hashset.Count];\n            hashset.CopyTo(baseNames);\n\n            return baseNames;\n        }\n    }\n} // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/Gizmos/DrawGizmo.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor\n{\n    // Determines how a gizmo is drawn or picked in the Unity editor.\n    [Flags]\n    public enum GizmoType\n    {\n        // The gizmo can be picked in the editor.\n        Pickable = 1,\n\n        // Draw the gizmo if it is not selected or child of the selection.\n        NotInSelectionHierarchy = 2,\n\n        // Draw the gizmo if it is not selected.\n        NonSelected = 32,\n\n        // Draw the gizmo if it is selected.\n        Selected = 4,\n\n        // Draw the gizmo if it is active (shown in the inspector).\n        Active = 8,\n\n        // Draw the gizmo if it is selected or a child of the selection.\n        InSelectionHierarchy = 16,\n\n        [Obsolete(\"Use NotInSelectionHierarchy instead (UnityUpgradable) -> NotInSelectionHierarchy\")]\n        NotSelected = -127,\n\n        [Obsolete(\"Use InSelectionHierarchy instead (UnityUpgradable) -> InSelectionHierarchy\")]\n        SelectedOrChild = -127,\n    }\n\n    // The DrawGizmo attribute allows you to supply a gizmo renderer for any [[Component]].\n    public sealed class DrawGizmo : Attribute\n    {\n        // Defines when the gizmo should be invoked for drawing.\n        public DrawGizmo(GizmoType gizmo)\n        {\n            drawOptions = gizmo;\n        }\n\n        // Same as above. /drawnGizmoType/ determines of what type the object we are drawing the gizmo of has to be.\n        public DrawGizmo(GizmoType gizmo, Type drawnGizmoType)\n        {\n            drawnType = drawnGizmoType;\n            drawOptions = gizmo;\n        }\n\n        //*undocumented\n        public Type drawnType;\n\n        //*undocumented\n        public GizmoType drawOptions;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GlobalObjectId.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEditor.Experimental;\n\n#pragma warning disable 649\n#pragma warning disable 169\nnamespace UnityEditor\n{\n    [Serializable]\n    [NativeHeader(\"Editor/Src/GlobalObjectId.h\")]\n    public struct GlobalObjectId : IEquatable<GlobalObjectId>, IComparable<GlobalObjectId>\n    {\n        internal SceneObjectIdentifier  m_SceneObjectIdentifier;\n        internal GUID                   m_AssetGUID;\n        internal int                    m_IdentifierType;\n\n        internal enum IdentifierType { NullIdentifier = 0, ImportedAsset = 1, SceneObject = 2, SourceAsset = 3, BuiltInAsset = 4 };\n\n        public ulong targetObjectId { get { return m_SceneObjectIdentifier.TargetObject; } }\n        public ulong targetPrefabId { get { return m_SceneObjectIdentifier.TargetPrefab; } }\n        public GUID assetGUID { get { return m_AssetGUID; } }\n        public int identifierType { get { return m_IdentifierType; } }\n\n        // Converts an Object reference to a global unique ID\n        [FreeFunction]\n        extern public static GlobalObjectId GetGlobalObjectIdSlow(UnityEngine.Object targetObject);\n\n        [FreeFunction]\n        extern public static void GetGlobalObjectIdsSlow(UnityEngine.Object[] objects, [Out] GlobalObjectId[] outputIdentifiers);\n\n        // Converts an Object reference to a global unique ID\n        public static GlobalObjectId GetGlobalObjectIdSlow(int instanceId)\n        {\n            return GetGlobalObjectIdFromInstanceIdSlow(instanceId);\n        }\n\n        public static void GetGlobalObjectIdsSlow(int[] instanceIds, [Out] GlobalObjectId[] outputIdentifiers)\n        {\n            GetGlobalObjectIdsFromInstanceIdsSlow(instanceIds, outputIdentifiers);\n        }\n\n        // Converts an Object reference to a global unique ID\n        [FreeFunction]\n        extern static GlobalObjectId GetGlobalObjectIdFromInstanceIdSlow(int instanceId);\n\n        [FreeFunction]\n        extern static void GetGlobalObjectIdsFromInstanceIdsSlow(int[] instanceIds, [Out] GlobalObjectId[] outputIdentifiers);\n\n        override public string ToString()\n        {\n            return string.Format(\"GlobalObjectId_V1-{0}-{1}-{2}-{3}\", m_IdentifierType, m_AssetGUID, m_SceneObjectIdentifier.TargetObject, m_SceneObjectIdentifier.TargetPrefab);\n        }\n\n        public bool Equals(GlobalObjectId other)\n        {\n            return m_SceneObjectIdentifier.Equals(other.m_SceneObjectIdentifier) &&\n                m_AssetGUID == other.m_AssetGUID &&\n                m_IdentifierType == other.m_IdentifierType;\n        }\n\n        public int CompareTo(GlobalObjectId other)\n        {\n            if (m_AssetGUID != other.m_AssetGUID)\n                return m_AssetGUID.CompareTo(other.assetGUID);\n            if (!m_SceneObjectIdentifier.Equals(other.m_SceneObjectIdentifier))\n                return m_SceneObjectIdentifier.CompareTo(other.m_SceneObjectIdentifier);\n            if (m_IdentifierType != other.m_IdentifierType)\n                return m_IdentifierType.CompareTo(m_IdentifierType);\n            return 0;\n        }\n\n        public static bool TryParse(string stringValue, out GlobalObjectId id)\n        {\n            id = new GlobalObjectId();\n            string[] tokens = stringValue.Split('-');\n            if (tokens.Length != 5 || !string.Equals(tokens[0], \"GlobalObjectId_V1\", StringComparison.Ordinal))\n                return false;\n\n            if (!int.TryParse(tokens[1], out var identifierType) ||\n                !GUID.TryParse(tokens[2], out var assetGUID) ||\n                !ulong.TryParse(tokens[3], out var targetObject) ||\n                !ulong.TryParse(tokens[4], out var targetPrefab))\n                return false;\n\n            id.m_IdentifierType = identifierType;\n            id.m_AssetGUID = assetGUID;\n            id.m_SceneObjectIdentifier = new SceneObjectIdentifier\n            {\n                TargetObject = targetObject,\n                TargetPrefab = targetPrefab\n            };\n\n            return true;\n        }\n\n        // Converting one object at a time is incredibly slow. (Have to iterate whole scene to grab one object...)\n        // Always prefer using batch API when multiple objects need to be looked up.\n        [FreeFunction]\n        extern public static UnityEngine.Object GlobalObjectIdentifierToObjectSlow(GlobalObjectId id);\n        [FreeFunction]\n        extern public static void GlobalObjectIdentifiersToObjectsSlow(GlobalObjectId[] identifiers, [Out] UnityEngine.Object[] outputObjects);\n\n        // Converting one object at a time is incredibly slow. (Have to iterate whole scene to grab one object...)\n        // Always prefer using batch API when multiple objects need to be looked up.\n        [FreeFunction]\n        extern public static int GlobalObjectIdentifierToInstanceIDSlow(GlobalObjectId id);\n        [FreeFunction]\n        extern public static void GlobalObjectIdentifiersToInstanceIDsSlow(GlobalObjectId[] identifiers, [Out] int[] outputInstanceIDs);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/GradientPreviewCache.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEditor;\n\nnamespace UnityEditorInternal\n{\n    [NativeHeader(\"Editor/Mono/GradientPreviewCache.bindings.h\")]\n    internal partial class GradientPreviewCache\n    {\n        public static extern Texture2D GenerateGradientPreview(Gradient gradient, Texture2D existingTexture, bool linearGradientKeys);\n\n        [StaticAccessor(\"GradientPreviewCache::Get()\", StaticAccessorType.Dot)]\n        public static extern void ClearCache();\n\n        [FreeFunction(\"GradientPreviewCache_GetPreview_Internal<SerializedProperty>\")]\n        public static extern Texture2D GetPropertyPreview(SerializedProperty property, bool linearGradientKeys);\n\n        [FreeFunction(\"GradientPreviewCache_GetPreview_Internal<Gradient>\")]\n        public static extern Texture2D GetGradientPreview(Gradient curve, bool linearGradientKeys);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Graphics/Analytics/GraphicsToolLifetimeAnalytic.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing UnityEngine;\nusing UnityEngine.Analytics;\n\nnamespace UnityEditor.Rendering.Analytics\n{\n    // schema = com.unity3d.data.schemas.editor.analytics.uGraphicsToolLifetimeAnalytic_v2\n    // taxonomy = editor.analytics.uGraphicsToolLifetimeAnalytic.v2\n    public class GraphicsToolLifetimeAnalytic\n    {\n        static bool IsInternalAssembly(Type type)\n        {\n            var assemblyName = type.Assembly.FullName;\n            if (assemblyName.StartsWith(\"UnityEditor.\", StringComparison.InvariantCultureIgnoreCase) ||\n                assemblyName.StartsWith(\"Unity.\", StringComparison.InvariantCultureIgnoreCase))\n                return true;\n            return false;\n        }\n\n        static List<string> GatherCurrentlyOpenWindowNames(Type editorWindowType)\n        {\n            var openWindows = Resources.FindObjectsOfTypeAll(typeof(EditorWindow));\n            var openWindowNames = new List<string>(openWindows.Length);\n            foreach (var w in openWindows)\n            {\n                var currentWindowType = w.GetType();\n                if (IsInternalAssembly(currentWindowType) && currentWindowType != editorWindowType)\n                {\n                    openWindowNames.Add((w as EditorWindow).titleContent.text);\n                }\n            }\n            return openWindowNames;\n        }\n\n        static string[] UnionWithoutLinq(List<string> a, List<string> b)\n        {\n            HashSet<string> aAndB = new HashSet<string>(a);\n            aAndB.UnionWith(b);\n            String[] aAndBArray = new String[aAndB.Count];\n            aAndB.CopyTo(aAndBArray);\n            return aAndBArray;\n        }\n\n        [AnalyticInfo(eventName: \"uGraphicsToolLifetimeAnalytic\", vendorKey: \"unity.graphics\", version: 2, maxEventsPerHour: 100, maxNumberOfElements: 1000)]\n        internal class Analytic : IAnalytic\n        {\n            public Analytic(WindowOpenedMetadata windowOpenedMetadata)\n            {\n                List<string> currentlyOpenEditorWindows = GatherCurrentlyOpenWindowNames(windowOpenedMetadata.editorWindowType);\n                var elapsed = DateTime.Now - windowOpenedMetadata.openedTime;\n                using (UnityEngine.Pool.GenericPool<Data>.Get(out var data))\n                {\n                    data.window_id = windowOpenedMetadata.editorWindowType.Name;\n                    data.seconds_opened = elapsed.Seconds;\n                    data.other_open_windows = UnionWithoutLinq(currentlyOpenEditorWindows, windowOpenedMetadata.openEditorWindows);\n\n                    m_Data = data;\n                }\n            }\n\n            [DebuggerDisplay(\"[{window_id}] Open time: {seconds_opened} - Other Windows Count: {other_open_windows.Length}\")]\n            [Serializable]\n            class Data : IAnalytic.IData\n            {\n                // Naming convention for analytics data is lower case and and connecting with _\n                public string window_id;\n                public int seconds_opened;\n                public string[] other_open_windows;\n            }\n\n            public bool TryGatherData(out IAnalytic.IData data, out Exception error)\n            {\n                data = m_Data;\n                error = null;\n                return true;\n            }\n\n            Data m_Data;\n        }\n\n        internal struct WindowOpenedMetadata\n        {\n            public Type editorWindowType;\n            public List<string> openEditorWindows;\n            public DateTime openedTime;\n        }\n\n        static Dictionary<Type, WindowOpenedMetadata> s_WindowOpenedMetadata = new Dictionary<Type, WindowOpenedMetadata>();\n\n        public static void WindowOpened<T>()\n            where T : EditorWindow\n        {\n            if (!s_WindowOpenedMetadata.TryGetValue(typeof(T), out var metadata))\n            {\n                metadata = new WindowOpenedMetadata\n                {\n                    editorWindowType = typeof(T),\n                    openEditorWindows = GatherCurrentlyOpenWindowNames(typeof(T)),\n                    openedTime = DateTime.Now\n                };\n\n                s_WindowOpenedMetadata.Add(typeof(T), metadata);\n            }\n        }\n\n        public static void WindowClosed<T>()\n            where T : EditorWindow\n        {\n            if (s_WindowOpenedMetadata.TryGetValue(typeof(T), out var metadata))\n            {\n                EditorAnalytics.SendAnalytic(new Analytic(metadata));\n                s_WindowOpenedMetadata.Remove(typeof(T));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Graphics/Analytics/GraphicsToolUsageAnalytic.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing UnityEngine;\nusing UnityEngine.Analytics;\n\nnamespace UnityEditor.Rendering.Analytics\n{\n    // schema = com.unity3d.data.schemas.editor.analytics.uGraphicsToolUsageAnalytic_v1\n    // taxonomy = editor.analytics.uGraphicsToolUsageAnalytic.v1\n    public class GraphicsToolUsageAnalytic\n    {\n        [AnalyticInfo(eventName: \"uGraphicsToolUsageAnalytic\", vendorKey: \"unity.graphics\", version: 1, maxEventsPerHour: 100, maxNumberOfElements: 1000)]\n        internal class Analytic<T> : IAnalytic\n        {\n            public Analytic(string action, string[] context)\n            {\n                using (UnityEngine.Pool.GenericPool<Data>.Get(out var data))\n                {\n                    data.window_id = typeof(T).Name;\n                    data.action = action;\n                    data.context = context;\n\n                    m_Data = data;\n                }\n            }\n\n            [DebuggerDisplay(\"[{window_id}] Action: {action} - Context: {context}\")]\n            [Serializable]\n            class Data : IAnalytic.IData\n            {\n                // Naming convention for analytics data is lower case and and connecting with _\n                public string window_id;\n                public string action;\n                public string[] context;\n            }\n\n            public bool TryGatherData(out IAnalytic.IData data, out Exception error)\n            {\n                data = m_Data;\n                error = null;\n                return true;\n            }\n\n            Data m_Data;\n        }\n\n        public static void ActionPerformed<T>(string action, string[] context)\n            where T : EditorWindow\n        {\n            if (string.IsNullOrEmpty(action))\n                return;\n\n            EditorAnalytics.SendAnalytic(new Analytic<T>(action, context));\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Graphics/EditorMaterialUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Runtime/Shaders/Material.h\"), StaticAccessor(\"Material\", StaticAccessorType.DoubleColon)]\n    [NativeHeader(\"Editor/Mono/Graphics/EditorMaterialUtility.bindings.h\")]\n    [NativeHeader(\"Runtime/Shaders/MaterialIsBackground.h\")]\n    public sealed partial class EditorMaterialUtility\n    {\n        [NativeProperty(\"disableApplyMaterialPropertyDrawers\", false, TargetType.Field)]\n        extern internal static bool disableApplyMaterialPropertyDrawers { get; set; }\n\n        [FreeFunction(\"EditorMaterialUtilityBindings::ResetDefaultTextures\")]\n        extern public static void ResetDefaultTextures([NotNull] Material material, bool overrideSetTextures);\n\n        [FreeFunction]\n        extern public static bool IsBackgroundMaterial([NotNull] Material material);\n\n        [FreeFunction(\"EditorMaterialUtilityBindings::SetShaderDefaults\")]\n        extern public static void SetShaderDefaults([NotNull] Shader shader, string[] name, Texture[] textures);\n\n        [FreeFunction(\"EditorMaterialUtilityBindings::SetShaderNonModifiableDefaults\")]\n        extern public static void SetShaderNonModifiableDefaults([NotNull] Shader shader, string[] name, Texture[] textures);\n\n        [FreeFunction(\"EditorMaterialUtilityBindings::GetShaderDefaultTexture\")]\n        extern internal static Texture GetShaderDefaultTexture([NotNull] Shader shader, string name);\n\n        [FreeFunction(\"EditorMaterialUtilityBindings::GetMaterialParentFromFile\")]\n        extern internal static GUID GetMaterialParentFromFile(string assetPath);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Graphics/GraphicsStateCollectionImporter.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.AssetImporters;\nusing UnityEngine.Rendering;\nusing UnityEngine.Experimental.Rendering;\n\nnamespace UnityEditor.Experimental.Rendering\n{\n    [ScriptedImporter(version: 1, ext: \"graphicsstate\")]\n    [ExcludeFromPreset]\n    class GraphicsStateCollectionImporter : ScriptedImporter\n    {\n        public RuntimePlatform runtimePlatform;\n        public GraphicsDeviceType graphicsDeviceType;\n        public int version;\n        public string qualityLevelName;\n        public int shaderVariantCount;\n        public int graphicsStateCount;\n\n        public override void OnImportAsset(AssetImportContext ctx)\n        {\n            GraphicsStateCollection asset = new GraphicsStateCollection(ctx.assetPath);\n            Texture2D icon = EditorGUIUtility.FindTexture(typeof(DefaultAsset));\n            ctx.AddObjectToAsset(\"graphicsstatecollection\", asset, icon);\n            ctx.SetMainObject(asset);\n\n            // Gather information about collection to display in inspector\n            runtimePlatform = asset.runtimePlatform;\n            graphicsDeviceType = asset.graphicsDeviceType;\n            version = asset.version;\n            qualityLevelName = asset.qualityLevelName;\n            shaderVariantCount = asset.variantCount;\n            graphicsStateCount = asset.totalGraphicsStateCount;\n        }\n    }\n\n    [CustomEditor(typeof(GraphicsStateCollectionImporter))]\n    class GraphicsStateCollectionImporterEditor : ScriptedImporterEditor\n    {\n        SerializedProperty m_RuntimePlatform;\n        SerializedProperty m_GraphicsDeviceType;\n        SerializedProperty m_Version;\n        SerializedProperty m_QualityLevelName;\n        SerializedProperty m_ShaderVariantCount;\n        SerializedProperty m_GraphicsStateCount;\n\n        public override bool showImportedObject => false;\n        protected override bool needsApplyRevert => false;\n\n        public override void OnEnable()\n        {\n            base.OnEnable();\n\n            m_RuntimePlatform = serializedObject.FindProperty(\"runtimePlatform\");\n            m_GraphicsDeviceType = serializedObject.FindProperty(\"graphicsDeviceType\");\n            m_Version = serializedObject.FindProperty(\"version\");\n            m_QualityLevelName = serializedObject.FindProperty(\"qualityLevelName\");\n            m_ShaderVariantCount = serializedObject.FindProperty(\"shaderVariantCount\");\n            m_GraphicsStateCount = serializedObject.FindProperty(\"graphicsStateCount\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            using (new EditorGUI.DisabledScope(true))\n            {\n                EditorGUILayout.PropertyField(m_RuntimePlatform);\n                EditorGUILayout.PropertyField(m_GraphicsDeviceType);\n                EditorGUILayout.PropertyField(m_Version);\n                EditorGUILayout.PropertyField(m_QualityLevelName, new GUIContent(\"Quality Level\"));\n                EditorGUILayout.PropertyField(m_ShaderVariantCount);\n                EditorGUILayout.PropertyField(m_GraphicsStateCount);\n            }\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Graphics/RenderPipelineGlobalSettingsPostprocessor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor.Rendering\n{\n    class RenderPipelineGlobalSettingsAssetProcessor : AssetModificationProcessor\n    {\n        public static bool s_CheckDelete = true;\n        public static Lazy<bool> s_RunningTestsOrBatchMode = new Lazy<bool>(() => Environment.CommandLine.Contains(\"-testResults\") || Application.isBatchMode);\n\n        public static AssetDeleteResult OnWillDeleteAsset(string assetPath, RemoveAssetOptions option)\n        {\n            if (s_RunningTestsOrBatchMode.Value || !s_CheckDelete)\n                return AssetDeleteResult.DidNotDelete;\n\n            if (GraphicsSettings.TryGetCurrentRenderPipelineGlobalSettings(out var renderPipelineGlobalSettings))\n            {\n                string currentInstanceAssetPath = AssetDatabase.GetAssetPath(renderPipelineGlobalSettings);\n                if (assetPath.Equals(currentInstanceAssetPath, StringComparison.InvariantCultureIgnoreCase))\n                {\n                    if (!EditorUtility.DisplayDialog($\"Deleting current {nameof(RenderPipelineGlobalSettings)}\",\n                        $@\"This asset is assigned to the currently active {GraphicsSettings.currentRenderPipeline.GetType().Name}. Unity will recreate the asset with the default values. \nAre you sure you want to proceed?\",\n                        \"Yes\", \"No\"))\n                    {\n                        return AssetDeleteResult.FailedDelete;\n                    }\n                }\n            }\n\n            return AssetDeleteResult.DidNotDelete;\n        }\n    }\n\n    class RenderPipelineGlobalSettingsPostprocessor : AssetPostprocessor\n    {\n        public static bool TryFindPath(string[] importedAssets, string pathToFind)\n        {\n            for (var index = 0; index < importedAssets.Length; index++)\n            {\n                var path = importedAssets[index];\n                if (path.Equals(pathToFind, StringComparison.InvariantCultureIgnoreCase))\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        const string k_GraphicsSettingsPath = \"ProjectSettings/GraphicsSettings.asset\";\n\n        public static bool RecreateGlobalSettingsNeed(string[] importedAssets, RenderPipelineAsset renderPipelineAsset)\n        {\n            // if the graphics settings has been imported, potentially the asset reference has been modified\n            if (TryFindPath(importedAssets, k_GraphicsSettingsPath))\n                return true;\n\n            int id = renderPipelineAsset.pipelineType != null ?\n                EditorGraphicsSettings.Internal_GetSettingsInstanceIDForRenderPipeline(renderPipelineAsset.pipelineType.FullName) : 0;\n            if (id != 0)\n            {\n                string currentInstanceAssetPath = AssetDatabase.GetAssetPath(id);\n\n                // Global settings asset has been deleted as the instance id is not null, but the asset does not longer exist\n                // or the current global settings asset is on the imported assets because some modification has been done\n                if (string.IsNullOrEmpty(currentInstanceAssetPath) || TryFindPath(importedAssets, currentInstanceAssetPath))\n                    return true;\n            }\n\n            return false;\n        }\n\n        static void OnPostprocessAllAssets(string[] importedAssets, string[] _, string[] ___, string[] ____, bool didDomainReload)\n        {\n            var rpAsset = GraphicsSettings.currentRenderPipeline;\n            if (rpAsset == null)\n                return;\n\n            if (RecreateGlobalSettingsNeed(importedAssets, rpAsset))\n                RenderPipelineManager.RecreateCurrentPipeline(RenderPipelineManager.currentPipelineAsset);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Graphics/RenderPipelineGraphicsSettingsEditorUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Reflection;\nusing UnityEditor.Inspector.GraphicsSettingsInspectors;\nusing UnityEditor.Rendering.Settings;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor.Rendering\n{\n    public static class RenderPipelineGraphicsSettingsEditorUtility\n    {\n        internal const string undoRebindName = \"Update IRenderPipelineGraphicsSettings: \";\n\n        public static void ForEachFieldOfType<T>(this IRenderPipelineResources resource, Action<T> callback, BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)\n        {\n            if (resource == null)\n                return;\n\n            var fields = resource.GetType().GetFields(flags);\n            foreach (var fieldInfo in fields)\n                if (fieldInfo.GetValue(resource) is T fieldValue)\n                    callback(fieldValue);\n        }\n\n        public static void RecreateRenderPipelineMatchingSettings(IRenderPipelineGraphicsSettings settings)\n        {\n            if (settings == null || RenderPipelineManager.currentPipeline == null)\n                return;\n\n            var renderPipelineType = RenderPipelineManager.currentPipeline.GetType();\n            var renderPipelineGlobalSettings = EditorGraphicsSettings.GetRenderPipelineGlobalSettingsAsset(renderPipelineType);\n            if (!renderPipelineGlobalSettings.TryGet(settings.GetType(), out var srpGraphicSetting))\n                return;\n\n            if (Object.ReferenceEquals(srpGraphicSetting, settings))\n                RenderPipelineManager.RecreateCurrentPipeline(RenderPipelineManager.currentPipelineAsset);\n        }\n\n        [InitializeOnLoadMethod]\n        static void OnLoad()\n        {\n            GraphicsSettings.OnIRenderPipelineGraphicsSettingsChange -= Callback;\n            GraphicsSettings.OnIRenderPipelineGraphicsSettingsChange += Callback;\n        }\n\n        static void Callback(IRenderPipelineGraphicsSettings instance, string propertyName)\n        {\n            if (instance\n                .GetType()\n                .GetField(propertyName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)\n                ?.GetCustomAttribute<RecreatePipelineOnChangeAttribute>() == null)\n                return;\n\n            RecreateRenderPipelineMatchingSettings(instance);\n        }\n\n        public static void RemoveRenderPipelineGraphicsSettingsWithMissingScript()\n        {\n            EditorGraphicsSettings.ForEachPipelineSettings((settings) => settings.CleanNullSettings());\n        }\n\n        public static void Rebind(IRenderPipelineGraphicsSettings settings, Type renderPipelineType)\n        {\n            if (settings == null || renderPipelineType == null || !typeof(RenderPipeline).IsAssignableFrom(renderPipelineType))\n                return;\n\n            var renderPipelineGlobalSettings = EditorGraphicsSettings.GetRenderPipelineGlobalSettingsAsset(renderPipelineType);\n            var serializedGlobalSettings = new SerializedObject(renderPipelineGlobalSettings);\n            var settingsIterator = serializedGlobalSettings.FindProperty(RenderPipelineGraphicsSettingsManager.serializationPathToCollection);\n            var end = settingsIterator.GetEndProperty();\n            settingsIterator.NextVisible(true); //enter the collection\n            while (true)\n            {\n                if (SerializedProperty.EqualContents(settingsIterator, end))\n                    return;\n\n                if (settingsIterator.boxedValue?.GetType() == settings.GetType())\n                    break;\n\n                settingsIterator.NextVisible(false);\n            }\n            \n            using (var notifier = new Notifier.Scope(settingsIterator))\n            {\n                settingsIterator.boxedValue = settings;\n                if (serializedGlobalSettings.ApplyModifiedProperties())\n                    Undo.SetCurrentGroupName($\"{undoRebindName}{settings.GetType().Name}\");\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "Editor/Mono/Graphics/RenderingLayersLimitSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n﻿using System;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor.Rendering\n{\n    public abstract class RenderingLayersLimitSettings : IRenderPipelineGraphicsSettings\n    {\n        #region Version\n\n        internal enum Version\n        {\n            Initial = 0,\n        }\n\n        [SerializeField] [HideInInspector] Version m_Version = Version.Initial;\n\n        /// <summary>Current version.</summary>\n        public int version => (int)m_Version;\n\n        #endregion\n\n        protected abstract int maxRenderingLayersForPipeline { get; }\n\n        public int maxSupportedRenderingLayers => maxRenderingLayersForPipeline is > 1 and <= 32 ? maxRenderingLayersForPipeline : 32;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Graphics/ShaderCompilerData.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Rendering;\nusing UnityEngine.Scripting;\nusing System.Runtime.InteropServices;\n\nnamespace UnityEditor.Rendering\n{\n    [StructLayout(LayoutKind.Sequential)]\n    [UsedByNativeCode]\n    public struct ShaderSnippetData\n    {\n        private ShaderType m_ShaderType;\n        private PassType m_PassType;\n        private string m_PassName;\n        private PassIdentifier m_PassIdentifier;\n\n        public ShaderType shaderType\n        {\n            get { return m_ShaderType; }\n        }\n\n        public PassType passType\n        {\n            get { return m_PassType; }\n        }\n\n        public string passName\n        {\n            get { return m_PassName; }\n        }\n\n        public PassIdentifier pass { get { return m_PassIdentifier; } }\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    [UsedByNativeCode]\n    public struct ShaderCompilerData\n    {\n        public ShaderKeywordSet shaderKeywordSet;\n        public PlatformKeywordSet platformKeywordSet; // C++ side is PlatformCapKeywords\n        private ShaderRequirements m_ShaderRequirements;\n        private GraphicsTier m_GraphicsTier;\n        private ShaderCompilerPlatform m_ShaderCompilerPlatform;\n        private BuildTarget m_BuildTarget;\n\n        public ShaderRequirements shaderRequirements\n        {\n            get { return m_ShaderRequirements; }\n        }\n\n        public GraphicsTier graphicsTier\n        {\n            get { return m_GraphicsTier; }\n        }\n\n        public ShaderCompilerPlatform shaderCompilerPlatform\n        {\n            get { return m_ShaderCompilerPlatform; }\n        }\n\n        public BuildTarget buildTarget { get { return m_BuildTarget; } }\n    }\n\n    public enum ShaderCompilerPlatform\n    {\n        None            = 0, // For non initialized variable.\n        D3D             = 4, // Direct3D 11 (FL10.0 and up) and Direct3D 12, compiled with MS D3DCompiler\n        [System.Obsolete(@\"OpenGL ES 2.0 is no longer supported since Unity 2023.1\")]\n        GLES20          = 5, // OpenGL ES 2.0 / WebGL 1.0, compiled with MS D3DCompiler + HLSLcc\n        GLES3x          = 9, // OpenGL ES 3.0+ / WebGL 2.0, compiled with MS D3DCompiler + HLSLcc\n        PS4             = 11, // Sony PS4\n        XboxOneD3D11    = 12, // MS XboxOne\n        Metal           = 14, // Apple Metal, compiled with MS D3DCompiler + HLSLcc\n        OpenGLCore      = 15, // Desktop OpenGL 3+, compiled with MS D3DCompiler + HLSLcc\n        Vulkan          = 18, // Vulkan SPIR-V, compiled with MS D3DCompiler + HLSLcc\n        Switch          = 19, // Nintendo Switch (NVN)\n        XboxOneD3D12    = 20, // Xbox One D3D12\n        GameCoreXboxOne = 21, // Game Core Xbox One\n        GameCoreXboxSeries= 22, // Game Core Scarlett\n        PS5             = 23, // PS5\n        PS5NGGC         = 24,  // PS5 NGGC\n        [System.Obsolete(@\"GameCore  is deprecated, please use GameCoreXboxOne (UnityUpgradable) -> GameCoreXboxOne \", true)]\n        GameCore = 25, // Game Core deprecated as single platform\n        WebGPU          = 26, // WebGPU\n        ReservedCFE     = 27,\n    }\n\n    public enum ShaderCompilerMessageSeverity\n    {\n        Error,\n        Warning\n    }\n\n    [Flags]\n    public enum ShaderRequirements : long\n    {\n        None                        = 0,\n        BaseShaders                 = (1 << 0), // Basic \"can have shaders\" (SM2.0 level) capability\n        Interpolators10             = (1 << 1), // 10 interpolators/varyings\n        Interpolators32             = (1 << 2), // 32 interpolators/varyings\n        MRT4                        = (1 << 3), // Multiple render targets, at least 4 (ability for fragment shader to output up to 4 colors)\n        MRT8                        = (1 << 4), // Multiple render targets, at least 8 (ability for fragment shader to output up to 8 colors)\n        Derivatives                 = (1 << 5), // Derivative (ddx/ddy) instructions in the fragment shader\n        SampleLOD                   = (1 << 6), // Ability to sample textures in fragment shader with explicit LOD level\n        FragCoord                   = (1 << 7), // Pixel position (VPOS/SV_Position/gl_FragCoord) input in fragment shader\n        FragClipDepth               = (1 << 8), // Pixel depth (SV_Position.zw/gl_FragCoord.zw) input in fragment shader\n        Interpolators15Integers     = (1 << 9), // Integers + Interpolators15. We bundle them together since extremely unlikely a GPU/API will ever exist that only has part of that.\n        Texture2DArray              = (1 << 10), // 2DArray textures\n        Instancing                  = (1 << 11), // SV_InstanceID shader input\n        Geometry                    = (1 << 12), // Geometry shaders\n        CubeArray                   = (1 << 13), // Cubemap arrays\n        Compute                     = (1 << 14), // Compute shaders\n        RandomWrite                 = (1 << 15), // Random-write textures (UAVs) from shader stages\n        TessellationCompute         = (1 << 16), // Tessellator hardware, i.e. Metal style\n        TessellationShaders         = (1 << 17), // Tessellation shaders, i.e. DX11 style (hull/domain shader stages)\n        SparseTexelResident         = (1 << 18), // Sparse textures with sampling instructions that return residency info\n        FramebufferFetch            = (1 << 19), // Framebuffer fetch (ability to have in+out fragment shader color params)\n        MSAATextureSamples          = (1 << 20), // Access to MSAA'd texture samples in shaders (e.g. HLSL Texture2DMS)\n        SetRTArrayIndexFromAnyShader = (1 << 21) // Must support setting the render target array index from any shader and not just the geometry shader\n    }\n\n    public enum ShaderType\n    {\n        Vertex      = 1,\n        Fragment    = 2,\n        Geometry    = 3,\n        Hull        = 4,\n        Domain      = 5,\n        Surface     = 6,\n        RayTracing  = 7,\n        Count       = 7\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Graphics/StaticBatchingEditorHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Runtime/Graphics/Mesh/StaticBatching.h\")]\n    internal struct StaticBatchingEditorHelper\n    {\n        [FreeFunction(\"StaticBatching::CombineAllStaticMeshesInSceneForStaticBatching\")]\n        extern internal static void CombineAllStaticMeshesForScenePostProcessing(ulong sceneHash, UnityEngine.SceneManagement.Scene scene);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Graphics/VulkanDeviceFilterListsEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Text;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing static UnityEditor.EditorGUI;\n\nnamespace UnityEditor\n{\n    internal static class DeviceFilterUI\n    {\n        internal static class Styles\n        {\n            public const uint kNumItemsInFilter = 7;\n            public const float kHeightBetweenFields = 3.0f;\n            public const float kHeightBetweenRows = 10.0f;\n\n            public static readonly GUIContent conversionButton = EditorGUIUtility.TrTextContent(\"Import Legacy Player Settings Filter Lists\", \"Imports the 'Android Vulkan Deny Filter List' and 'Android Vulkan Allow Filter List' Player Settings fields to a standalone Vulkan Device Filtering Asset. Once imported, this button and the Android Vulkan Deny/Allow Filter List fields will be disabled.\");\n\n            public static readonly GUIContent preferredGraphicsJobsMode = EditorGUIUtility.TrTextContent(\"Preferred Graphics Jobs Mode\", \"Indicates which graphics jobs mode this filter will enforce at runtime.\");\n\n            public static readonly GUIContent filterList = EditorGUIUtility.TrTextContent(\"Filters\", \"List of filters\");\n            public static readonly GUIContent vendor = EditorGUIUtility.TrTextContent(\"Vendor\", \"Use a regular expression to specify the vendor name of a device\");\n            public static readonly GUIContent deviceName = EditorGUIUtility.TrTextContent(\"Device Name\", \"Use a regular expression to specify the device name of a device\");\n            public static readonly GUIContent brand = EditorGUIUtility.TrTextContent(\"Brand\", \"Use a regular expression to specify the device brand of a device\");\n            public static readonly GUIContent product = EditorGUIUtility.TrTextContent(\"Product Name\", \"Use a regular expression to specify the product name of a device\");\n            public static readonly GUIContent osVersion =\n                EditorGUIUtility.TrTextContent(\"Android OS Version\", \"Use a regular expression to specify the OS version of a device\");\n            public static readonly GUIContent vulkanApiVersion =\n                EditorGUIUtility.TrTextContent(\"Vulkan API Version\", \"Specify the Vulkan API version for a device using the format MajorVersion.MinorVersion(optional).PatchVersion(optional)\");\n            public static readonly GUIContent driverVersion =\n                EditorGUIUtility.TrTextContent(\"Driver Version\", \"Specify the driver version for a device using the format MajorVersion.MinorVersion(optional).PatchVersion(optional)\");\n\n            // Text\n            public static readonly string filterText = \"filter\";\n            public static readonly string preferredGraphicsJobsModeText = \"preferredMode\";\n            public static readonly string vendorText = \"vendorName\";\n            public static readonly string deviceNameText = \"deviceName\";\n            public static readonly string brandText = \"brandName\";\n            public static readonly string productText = \"productName\";\n            public static readonly string androidOsVersionText = \"androidOsVersionString\";\n            public static readonly string vulkanApiVersionText = \"vulkanApiVersionString\";\n            public static readonly string driverVersionText = \"driverVersionString\";\n\n            public static float kElementHeighWithSpace => EditorGUIUtility.singleLineHeight + kHeightBetweenFields;\n        }\n\n        internal static class Utils\n        {\n            private static bool DrawRegexWithErrorCheck(string name, SerializedProperty prop, GUIContent standardContent, string text, ref Rect elementRect, StringBuilder errorBuilder)\n            {\n                prop.stringValue = EditorGUI.TextField(elementRect, standardContent, prop.stringValue);\n                if (VulkanDeviceFilterUtils.HasErrorRegex(prop.stringValue, text, out var errorString))\n                {\n                    errorBuilder.Append($\"\\n{name}: {errorString}\");\n                    return false;\n                }\n                return true;\n            }\n\n            private static bool DrawVersionWithErrorCheck(string name, SerializedProperty prop, GUIContent standardContent, string text, ref Rect elementRect, StringBuilder errorBuilder)\n            {\n                prop.stringValue = EditorGUI.TextField(elementRect, standardContent, prop.stringValue);\n                if (VulkanDeviceFilterUtils.HasErrorVersion(prop.stringValue, text, out var errorString))\n                {\n                    errorBuilder.Append($\"\\n{name}: {errorString}\");\n                    return false;\n                }\n                return true;\n            }\n\n            public static void DrawDeviceFilterList(SerializedProperty filterListProp, int index, ref Rect elementRect, bool hasPreviousPropFields = false)\n            {\n                var vendorProp = filterListProp.FindPropertyRelative(Styles.vendorText);\n                var deviceNameProp = filterListProp.FindPropertyRelative(Styles.deviceNameText);\n                var brandProp = filterListProp.FindPropertyRelative(Styles.brandText);\n                var productProp = filterListProp.FindPropertyRelative(Styles.productText);\n                var osVersionProp = filterListProp.FindPropertyRelative(Styles.androidOsVersionText);\n                var vulkanApiVersionProp = filterListProp.FindPropertyRelative(Styles.vulkanApiVersionText);\n                var driverVersionProp = filterListProp.FindPropertyRelative(Styles.driverVersionText);\n\n                if (hasPreviousPropFields)\n                    elementRect.y += DeviceFilterUI.Styles.kElementHeighWithSpace;\n\n                var errorBuilder = new StringBuilder($\"Errors Detected at index {index}:\");\n\n                var result = DrawRegexWithErrorCheck(\"Vendor\", vendorProp, DeviceFilterUI.Styles.vendor, DeviceFilterUI.Styles.vendorText, ref elementRect, errorBuilder);\n                elementRect.y += DeviceFilterUI.Styles.kElementHeighWithSpace;\n\n                result &= DrawRegexWithErrorCheck(\"Device Name\", deviceNameProp, DeviceFilterUI.Styles.deviceName, DeviceFilterUI.Styles.deviceNameText, ref elementRect, errorBuilder);\n                elementRect.y += DeviceFilterUI.Styles.kElementHeighWithSpace;\n\n                result &= DrawRegexWithErrorCheck(\"Brand\", brandProp, DeviceFilterUI.Styles.brand, DeviceFilterUI.Styles.brandText, ref elementRect, errorBuilder);\n                elementRect.y += DeviceFilterUI.Styles.kElementHeighWithSpace;\n\n                result &= DrawRegexWithErrorCheck(\"Product Name\", productProp, DeviceFilterUI.Styles.product, DeviceFilterUI.Styles.productText, ref elementRect, errorBuilder);\n                elementRect.y += DeviceFilterUI.Styles.kElementHeighWithSpace;\n\n                result &= DrawRegexWithErrorCheck(\"Android OS Version\", osVersionProp, DeviceFilterUI.Styles.osVersion, DeviceFilterUI.Styles.androidOsVersionText, ref elementRect, errorBuilder);\n                elementRect.y += DeviceFilterUI.Styles.kElementHeighWithSpace;\n\n                result &= DrawVersionWithErrorCheck(\"Vulkan API Version\", vulkanApiVersionProp, DeviceFilterUI.Styles.vulkanApiVersion, DeviceFilterUI.Styles.vulkanApiVersionText, ref elementRect, errorBuilder);\n                elementRect.y += DeviceFilterUI.Styles.kElementHeighWithSpace;\n\n                result &= DrawVersionWithErrorCheck(\"Driver Version\", driverVersionProp, DeviceFilterUI.Styles.driverVersion, DeviceFilterUI.Styles.driverVersionText, ref elementRect, errorBuilder);\n\n                if (!result)\n                    GUILayout.Label(EditorGUIUtility.TempContent(errorBuilder.ToString(), EditorGUIUtility.GetHelpIcon(MessageType.Error)), EditorStyles.helpBox);\n            }\n\n            public static void ClearNewElement(SerializedProperty filterListProp)\n            {\n                filterListProp.FindPropertyRelative(Styles.vendorText).stringValue = null;\n                filterListProp.FindPropertyRelative(Styles.deviceNameText).stringValue = null;\n                filterListProp.FindPropertyRelative(Styles.brandText).stringValue = null;\n                filterListProp.FindPropertyRelative(Styles.productText).stringValue = null;\n                filterListProp.FindPropertyRelative(Styles.androidOsVersionText).stringValue = null;\n                filterListProp.FindPropertyRelative(Styles.vulkanApiVersionText).stringValue = null;\n                filterListProp.FindPropertyRelative(Styles.driverVersionText).stringValue = null;\n            }\n        }\n    }\n\n    [CustomEditor(typeof(UnityEngine.VulkanDeviceFilterLists))]\n    internal class VulkanDeviceFilterListsEditor : Editor\n    {\n        internal class ReorderableFilterList\n        {\n            public delegate void ElementCallbackDelegate(\n                ReorderableList list,\n                Rect rect, int index, bool isActive, bool isFocused);\n            public delegate void AddCallbackDelegate(ReorderableList list);\n\n            public SerializedObject serializedObject { get; private set; }\n            public SerializedProperty serializedProperty { get; private set; }\n            public ReorderableList reorderableList { get; private set; }\n\n            private ElementCallbackDelegate m_DrawElementCallback;\n            private AddCallbackDelegate m_AddElementCallback;\n\n            public ReorderableFilterList(\n                SerializedObject serializedObject, string propertyName,\n                ElementCallbackDelegate drawElementCallback, AddCallbackDelegate onAddCallback,\n                float elementHeight, float headerHeight = 0.0f)\n            {\n                this.serializedObject = serializedObject;\n                this.serializedProperty = serializedObject.FindProperty(propertyName);\n                this.reorderableList = new ReorderableList(serializedObject, serializedProperty, true, false, true, true);\n                m_DrawElementCallback = drawElementCallback;\n                this.reorderableList.drawElementCallback = DrawListElement;\n                m_AddElementCallback = onAddCallback;\n                this.reorderableList.onAddCallback = AddElement;\n                this.reorderableList.onReorderCallback = (_)=>{};\n                this.reorderableList.elementHeight = elementHeight;\n                this.reorderableList.headerHeight = headerHeight;\n            }\n\n            public void DoList(Rect listRect)\n            {\n                reorderableList.DoList(listRect);\n            }\n\n            private void DrawListElement(Rect rect, int index, bool isActive, bool isFocused)\n            {\n                m_DrawElementCallback(reorderableList, rect, index, isActive, isFocused);\n            }\n\n            private void AddElement(ReorderableList filterList)\n            {\n                m_AddElementCallback(filterList);\n            }\n        }\n\n        VulkanDeviceFilterLists assetObject => serializedObject.targetObject as VulkanDeviceFilterLists;\n\n        ReorderableFilterList m_AllowReorderableFilterList;\n        ReorderableFilterList m_DenyReorderableFilterList;\n        ReorderableFilterList m_GfxJobsReorderableFilterList;\n\n        bool m_ShowAllow = false;\n        bool m_ShowDeny = false;\n        bool m_ShowGfxJobs = false;\n\n        private void DrawDeviceFilterListElement(ReorderableList list, Rect rect, int index, bool isActive, bool isFocused)\n        {\n            var filterListProp = list.serializedProperty.GetArrayElementAtIndex(index);\n\n            var elementRect = new Rect(rect);\n            elementRect.height = EditorGUIUtility.singleLineHeight;\n            elementRect.y += DeviceFilterUI.Styles.kHeightBetweenFields;\n\n            DeviceFilterUI.Utils.DrawDeviceFilterList(filterListProp, index, ref elementRect);\n        }\n\n        private void AddDeviceFilterListElement(ReorderableList filterList)\n        {\n            var list = filterList.serializedProperty;\n            var index = list.arraySize++;\n            filterList.index = index;\n            var filterListProp = list.GetArrayElementAtIndex(index);\n\n            // Helper for clearing the regex strings\n            DeviceFilterUI.Utils.ClearNewElement(filterListProp);\n        }\n\n        private void DrawGfxJobsFilterListElement(ReorderableList list, Rect rect, int index, bool isActive, bool isFocused)\n        {\n            var filterListProp = list.serializedProperty.GetArrayElementAtIndex(index);\n\n            var elementRect = new Rect(rect);\n            elementRect.height = EditorGUIUtility.singleLineHeight;\n            elementRect.y += DeviceFilterUI.Styles.kHeightBetweenFields;\n\n            var graphicsJobsPreferenceProp = filterListProp.FindPropertyRelative(DeviceFilterUI.Styles.preferredGraphicsJobsModeText);\n            GraphicsJobsFilterMode mode = (GraphicsJobsFilterMode)graphicsJobsPreferenceProp.enumValueFlag;\n\n            mode = (GraphicsJobsFilterMode)EditorGUI.EnumPopup(\n                elementRect, DeviceFilterUI.Styles.preferredGraphicsJobsMode, mode);\n            graphicsJobsPreferenceProp.intValue = (int)mode;\n\n            var filterProp = filterListProp.FindPropertyRelative(DeviceFilterUI.Styles.filterText);\n\n            // Helper for drawing the actual filter list\n            DeviceFilterUI.Utils.DrawDeviceFilterList(filterProp, index, ref elementRect, true);\n        }\n\n        private void AddGfxJobsFilterListElement(ReorderableList filterList)\n        {\n            var list = filterList.serializedProperty;\n            var index = list.arraySize++;\n            filterList.index = index;\n            var filterListProp = list.GetArrayElementAtIndex(index);\n\n            var graphicsJobsPreferenceProp = filterListProp.FindPropertyRelative(DeviceFilterUI.Styles.preferredGraphicsJobsModeText).enumValueFlag = 0x0;\n\n            // Helper for clearing the regex strings\n            DeviceFilterUI.Utils.ClearNewElement(filterListProp.FindPropertyRelative(DeviceFilterUI.Styles.filterText));\n        }\n\n        public void OnEnable()\n        {\n            var allowDenyListElementHeight = DeviceFilterUI.Styles.kElementHeighWithSpace * DeviceFilterUI.Styles.kNumItemsInFilter + DeviceFilterUI.Styles.kHeightBetweenFields;\n            m_AllowReorderableFilterList = new ReorderableFilterList(\n                serializedObject,  \"m_VulkanAllowFilterList\", DrawDeviceFilterListElement, AddDeviceFilterListElement, allowDenyListElementHeight);\n            m_DenyReorderableFilterList = new ReorderableFilterList(\n                serializedObject,  \"m_VulkanDenyFilterList\", DrawDeviceFilterListElement, AddDeviceFilterListElement, allowDenyListElementHeight);\n\n            var gfxJobsElementHeight = DeviceFilterUI.Styles.kElementHeighWithSpace * (DeviceFilterUI.Styles.kNumItemsInFilter + 1) + DeviceFilterUI.Styles.kHeightBetweenFields;\n            m_GfxJobsReorderableFilterList = new ReorderableFilterList(\n                serializedObject,  \"m_GfxJobFilterList\", DrawGfxJobsFilterListElement, AddGfxJobsFilterListElement, gfxJobsElementHeight);\n        }\n\n        struct ErrorInfo\n        {\n            public bool hasErrors;\n            public string errorString;\n\n            ErrorInfo(bool hasErrors, string errorString)\n            {\n                this.hasErrors = hasErrors;\n                this.errorString = errorString;\n            }\n        };\n\n        private float DoListInternal(ReorderableFilterList list, float startingHeight)\n        {\n            var listRect = GUILayoutUtility.GetRect(startingHeight, list.reorderableList.GetHeight(), GUILayout.ExpandWidth(true));\n            listRect.x += EditorGUI.kIndentPerLevel;\n            listRect.width -= EditorGUI.kIndentPerLevel;\n            list.DoList(listRect);\n            return list.reorderableList.GetHeight();\n        }\n\n        private float DoList(ReorderableFilterList list, string name, ref bool showPosition, float startingHeight, Func<float, float> onBeforeListDraw = null, Func<float, float> onAfterListDraw = null)\n        {\n            var height = startingHeight;\n            showPosition = EditorGUILayout.BeginFoldoutHeaderGroup(showPosition, name);\n            if (showPosition)\n            {\n                using (var scopedHeight = new IndentLevelScope())\n                {\n                    height += onBeforeListDraw?.Invoke(height) ?? 0.0f;\n                    height += DoListInternal(list, height);\n                    height += onAfterListDraw?.Invoke(height) ?? 0.0f;\n                }\n            }\n            EditorGUILayout.EndFoldoutHeaderGroup();\n            return height;\n        }\n\n        private float DrawGfxJobsExtraNotice(float startingHeight)\n        {\n            var content = EditorGUIUtility.TempContent(\"The order of the Graphics Jobs Filters is important. Filtering will use the first passing filter to determine Graphics Jobs Mode at runtime.\", EditorGUIUtility.GetHelpIcon(MessageType.Info));\n\n            var rect = GUILayoutUtility.GetRect(startingHeight, 1.0f, GUILayout.ExpandWidth(true));\n            rect.x += EditorGUI.kIndentPerLevel;\n            rect.width -= EditorGUI.kIndentPerLevel;\n            var height = EditorStyles.helpBox.CalcHeight(content, rect.width) + (DeviceFilterUI.Styles.kElementHeighWithSpace * 2);\n\n            rect = GUILayoutUtility.GetRect(startingHeight, height, GUILayout.ExpandWidth(true));\n            rect.x += EditorGUI.kIndentPerLevel;\n            rect.width -= EditorGUI.kIndentPerLevel;\n\n            EditorGUI.HelpBox(rect, content);\n            return height;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n            var targetObj = serializedObject.targetObject as VulkanDeviceFilterLists;\n\n            if (targetObj == null)\n                throw new InvalidCastException(\"Unable to case object to VulkanDeviceFilterLists!\");\n\n            using (var changed = new ChangeCheckScope())\n            {\n                var height = 0.0f;\n\n// Disable obsolete warning. Users should see obsolete warnings when trying to use the API but\n// this is to ensure the user is warned that the settings are going to be ignored and that they\n// should perform the conversion.\n#pragma warning disable 612, 618\n                var allowListCount = PlayerSettings.Android.androidVulkanAllowFilterList.Length;\n                var denyListCount = PlayerSettings.Android.androidVulkanDenyFilterList.Length;\n\n                if (allowListCount + denyListCount > 0)\n                {\n                    var buttonPressed = GUILayout.Button(DeviceFilterUI.Styles.conversionButton);\n                    if (buttonPressed)\n                        assetObject.ImportPlayerSettingsFiltersToAsset();\n                }\n#pragma warning restore 612, 618\n\n                height = DoList(m_AllowReorderableFilterList, \"Allow Filters\", ref m_ShowAllow, height);\n                height = DoList(m_DenyReorderableFilterList, \"Deny Filters\", ref m_ShowDeny, height);\n                height = DoList(m_GfxJobsReorderableFilterList, \"Preferred Graphics Jobs Filters\", ref m_ShowGfxJobs, height, DrawGfxJobsExtraNotice);\n\n                if (changed.changed)\n                    serializedObject.ApplyModifiedProperties();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Grids/EditorSnap.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing UnityEditor.EditorTools;\n\nnamespace UnityEditor\n{\n    [FilePath(\"Library/EditorSnapSettings.asset\", FilePathAttribute.Location.ProjectFolder)]\n    class EditorSnapSettingsData : ScriptableSingleton<EditorSnapSettingsData>\n    {\n        [SerializeField]\n        bool m_SnapEnabled;\n\n        [SerializeField]\n        SnapSettings m_SnapSettings = new SnapSettings();\n\n        internal bool snapEnabled\n        {\n            get { return m_SnapEnabled; }\n            set { m_SnapEnabled = value; }\n        }\n\n        internal SnapSettings snapSettings\n        {\n            get { return m_SnapSettings; }\n            set { m_SnapSettings = value; }\n        }\n\n        void OnDisable()\n        {\n            Save();\n        }\n\n        internal void Save()\n        {\n            Save(true);\n        }\n    }\n\n    // Most of EditorSnapSettings is private for now because we are just hard-coding grid snap and incremental snap.\n    // in the near future, we will be extending support for multiple snapping modes and this API will change.\n    // ex, snap modes will likely be implemented as objects that can be registered to this class, making user-implemented\n    // snapping behaviours possible.\n    public static class EditorSnapSettings\n    {\n        static EditorSnapSettingsData instance\n        {\n            get { return EditorSnapSettingsData.instance; }\n        }\n\n        internal static bool activeToolGridSnapEnabled\n        {\n            get => ToolManager.activeToolType != null && EditorToolManager.activeTool.gridSnapEnabled;\n        }\n\n        // gridSnapEnabled controls whether objects are rounded to absolute positions on the grid, as opposed to\n        // incremental rounding from translation origin. this option is only applicable when the handle rotation\n        // is set to \"Global.\"\n        public static bool gridSnapEnabled\n        {\n            get => instance.snapSettings.snapToGrid;\n            set\n            {\n                instance.snapSettings.snapToGrid = value;\n                gridSnapEnabledChanged?.Invoke();\n            }\n        }\n\n        // snapEnabled is the general \"is snap on\" toggle. it controls all snapping; grid, increment, rotation, scale.\n        public static bool snapEnabled\n        {\n            get { return EditorGUI.actionKey ? !instance.snapEnabled : instance.snapEnabled; }\n            set\n            {\n                if (snapEnabled != value)\n                {\n                    instance.snapEnabled = value;\n                    snapEnabledChanged?.Invoke();\n                }\n            }\n        }\n\n        // where the 'snapEnabled' properties are preference toggles, the 'snapActive' properties are what tells tools\n        // when and which snapping modes should be be applied.\n        public static bool gridSnapActive => activeToolGridSnapEnabled && gridSnapEnabled && snapEnabled;\n\n        // callback invoked when grid snapping is enabled or disabled\n        public static event Action gridSnapEnabledChanged;\n\n        public static event Action snapEnabledChanged;\n\n        internal static bool vertexSnapActive => Tools.vertexDragging;\n\n        // Used by 2D package\n        internal static bool hotkeyActive => EditorGUI.actionKey;\n\n        public static bool incrementalSnapActive => !gridSnapActive && snapEnabled;\n\n        public static Vector3 gridSize\n        {\n            get => GridSettings.size;\n            set\n            {\n                if (GridSettings.size != value)\n                    GridSettings.size = value;\n            }\n        }\n\n        internal static Action<float> rotateChanged;\n        internal static Action<float> scaleChanged;\n\n        public static Vector3 move\n        {\n            get => gridSize;\n            set => gridSize = value;\n        }\n\n        public static float rotate\n        {\n            get { return instance.snapSettings.rotation; }\n            set\n            {\n                if (instance.snapSettings.rotation != value)\n                {\n                    instance.snapSettings.rotation = value;\n                    rotateChanged?.Invoke(value);\n                }\n            }\n        }\n\n        public static float scale\n        {\n            get { return instance.snapSettings.scale; }\n            set\n            {\n                if (instance.snapSettings.scale != value)\n                {\n                    instance.snapSettings.scale = value;\n                    scaleChanged?.Invoke(value);\n                }\n            }\n        }\n\n        public static void ResetSnapSettings()\n        {\n            instance.snapSettings = new SnapSettings();\n        }\n\n        internal static void Save()\n        {\n            instance.Save();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Grids/GridShortcuts.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\n\nnamespace UnityEditor.Snap\n{\n    static class Shortcuts\n    {\n        [Shortcut(\"Grid and Snap/Toggle Snapping\", typeof(SceneView), KeyCode.Backslash)]\n        internal static void ToggleGridSnap()\n        {\n            EditorSnapSettings.snapEnabled = !EditorSnapSettings.snapEnabled;\n        }\n\n        [Shortcut(\"Grid and Snap/Increase Grid Size\", typeof(SceneView), KeyCode.RightBracket, ShortcutModifiers.Action)]\n        internal static void IncreaseGridSize()\n        {\n            GridSettings.sizeMultiplier++;\n            SceneView.RepaintAll();\n        }\n\n        [Shortcut(\"Grid and Snap/Decrease Grid Size\", typeof(SceneView), KeyCode.LeftBracket, ShortcutModifiers.Action)]\n        internal static void DecreaseGridSize()\n        {\n            GridSettings.sizeMultiplier--;\n            SceneView.RepaintAll();\n        }\n\n        [Shortcut(\"Grid and Snap/Reset Grid\", typeof(SceneView))]\n        internal static void ResetGrid()\n        {\n            MenuNudgePerspectiveReset();\n            GridSettings.ResetGridSettings();\n            SceneView.RepaintAll();\n        }\n\n        [Shortcut(\"Grid and Snap/Nudge Grid Backward\", typeof(SceneView))]\n        internal static void MenuNudgePerspectiveBackward()\n        {\n            SceneView sv = SceneView.lastActiveSceneView;\n            SceneViewGrid.GridRenderAxis axis = sv.sceneViewGrids.gridAxis;\n            Vector3 v = sv.sceneViewGrids.GetPivot(axis);\n            Vector3 gridSize = GridSettings.size;\n\n            switch (axis)\n            {\n                case SceneViewGrid.GridRenderAxis.X:\n                    v -= Vector3.right * gridSize.x;\n                    break;\n                case SceneViewGrid.GridRenderAxis.Y:\n                    v -= Vector3.up * gridSize.y;\n                    break;\n                case SceneViewGrid.GridRenderAxis.Z:\n                    v -= Vector3.forward * gridSize.z;\n                    break;\n            }\n\n            sv.sceneViewGrids.SetPivot(axis, v);\n            sv.Repaint();\n        }\n\n        [Shortcut(\"Grid and Snap/Nudge Grid Forward\", typeof(SceneView))]\n        internal static void MenuNudgePerspectiveForward()\n        {\n            SceneView sv = SceneView.lastActiveSceneView;\n            SceneViewGrid.GridRenderAxis axis = sv.sceneViewGrids.gridAxis;\n            Vector3 v = sv.sceneViewGrids.GetPivot(axis);\n            Vector3 gridSize = GridSettings.size;\n\n            switch (axis)\n            {\n                case SceneViewGrid.GridRenderAxis.X:\n                    v += Vector3.right * gridSize.x;\n                    break;\n                case SceneViewGrid.GridRenderAxis.Y:\n                    v += Vector3.up * gridSize.y;\n                    break;\n                case SceneViewGrid.GridRenderAxis.Z:\n                    v += Vector3.forward * gridSize.z;\n                    break;\n            }\n\n            sv.sceneViewGrids.SetPivot(axis, v);\n            sv.Repaint();\n        }\n\n        [Shortcut(\"Grid and Snap/Push To Grid\", typeof(SceneView), KeyCode.Backslash, ShortcutModifiers.Action)]\n        internal static void PushToGrid()\n        {\n            GridSnapping.SnapSelectionToGrid();\n        }\n\n        internal static void MenuNudgePerspectiveReset()\n        {\n            SceneView sv = SceneView.lastActiveSceneView;\n            sv.ResetGridPivot();\n            sv.Repaint();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Grids/GridSnapping.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    static class GridSnapping\n    {\n        public static Func<Vector3, Vector3> snapPosition = null;\n        public static Func<bool> activeFunc = null;\n\n        public static bool active\n        {\n            get { return (activeFunc != null ? activeFunc() : false); }\n        }\n\n        public static Vector3 Snap(Vector3 position)\n        {\n            if (snapPosition != null)\n                return snapPosition(position);\n            return position;\n        }\n\n        public static void SnapSelectionToGrid(SnapAxis axis = SnapAxis.All)\n        {\n            var selections = Selection.transforms;\n            if (selections != null && selections.Length > 0)\n            {\n                Undo.RecordObjects(selections, L10n.Tr(\"Snap to Grid\"));\n                Handles.SnapToGrid(selections, axis);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Grids/SnapSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [Serializable]\n    class SnapSettings\n    {\n        public const bool defaultGridSnapEnabled = true;\n        public const float defaultRotation = 15f;\n        public const float defaultScale = 1f;\n\n        [SerializeField]\n        bool m_SnapToGrid = defaultGridSnapEnabled;\n\n        [SerializeField]\n        float m_Rotation = defaultRotation;\n\n        [SerializeField]\n        float m_Scale = defaultScale;\n\n        public bool snapToGrid\n        {\n            get => m_SnapToGrid;\n            set => m_SnapToGrid = value;\n        }\n\n        public float rotation\n        {\n            get { return m_Rotation; }\n            set { m_Rotation = value; }\n        }\n\n        public float scale\n        {\n            get { return m_Scale; }\n            set { m_Scale = value; }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/ArcHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor.Snap;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public class ArcHandle\n    {\n        static readonly float s_DefaultAngleHandleSize = 0.08f;\n        static readonly float s_DefaultAngleHandleSizeRatio = 1.25f;\n\n        static readonly float s_DefaultRadiusHandleSize = 0.03f;\n\n        static readonly Dictionary<int, Quaternion> s_MostRecentValidAngleHandleOrientations =\n            new Dictionary<int, Quaternion>();\n\n        // only used inside of DefaultAngleHandleDrawFunction to look up and store the most recent valid orientation per handle\n        // done so that DefaultAngleHandleDrawFunction can be a static method, which makes angleHandleDrawFunction more usable by sub-classes\n        static int s_CurrentlyDrawingAngleHandleHash;\n\n        public static void DefaultAngleHandleDrawFunction(\n            int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType\n        )\n        {\n            Handles.DrawLine(Vector3.zero, position);\n\n            // draw a cylindrical \"hammer head\" to indicate the direction the handle will move\n            Vector3 worldPosition = Handles.matrix.MultiplyPoint3x4(position);\n            Vector3 normal = worldPosition - Handles.matrix.MultiplyPoint3x4(Vector3.zero);\n            Vector3 tangent = Handles.matrix.MultiplyVector(Quaternion.AngleAxis(90f, Vector3.up) * position);\n            Quaternion mostRecentValidOrientation;\n            if (!s_MostRecentValidAngleHandleOrientations.TryGetValue(s_CurrentlyDrawingAngleHandleHash, out mostRecentValidOrientation))\n                mostRecentValidOrientation = Quaternion.identity;\n            rotation = Mathf.Approximately(tangent.sqrMagnitude, 0f) ?\n                mostRecentValidOrientation : Quaternion.LookRotation(tangent, normal);\n            s_MostRecentValidAngleHandleOrientations[s_CurrentlyDrawingAngleHandleHash] = rotation;\n            Matrix4x4 matrix =\n                Matrix4x4.TRS(worldPosition, rotation, (Vector3.one + Vector3.forward * s_DefaultAngleHandleSizeRatio));\n            using (new Handles.DrawingScope(matrix))\n                Handles.CylinderHandleCap(controlID, Vector3.zero, Quaternion.identity, size, eventType);\n            s_CurrentlyDrawingAngleHandleHash = 0;\n        }\n\n        public static float DefaultAngleHandleSizeFunction(Vector3 position)\n        {\n            return HandleUtility.GetHandleSize(position) * s_DefaultAngleHandleSize;\n        }\n\n        public static float DefaultRadiusHandleSizeFunction(Vector3 position)\n        {\n            return HandleUtility.GetHandleSize(position) * s_DefaultRadiusHandleSize;\n        }\n\n        private bool m_ControlIDsReserved = false;\n        private int m_AngleHandleControlID;\n        private int[] m_RadiusHandleControlIDs = new int[4];\n\n        public float angle { get; set; }\n\n        public float radius { get; set; }\n\n        public Color angleHandleColor { get; set; }\n\n        public Color radiusHandleColor { get; set; }\n\n        public Color fillColor { get; set; }\n\n        public Color wireframeColor { get; set; }\n\n        public Handles.CapFunction angleHandleDrawFunction { get; set; }\n\n        public Handles.SizeFunction angleHandleSizeFunction { get; set; }\n\n        public Handles.CapFunction radiusHandleDrawFunction { get; set; }\n\n        public Handles.SizeFunction radiusHandleSizeFunction { get; set; }\n\n        public ArcHandle()\n        {\n            radius = 1f;\n            SetColorWithoutRadiusHandle(Color.white, 0.1f);\n            angleHandleDrawFunction = DefaultAngleHandleDrawFunction;\n            angleHandleSizeFunction = DefaultAngleHandleSizeFunction;\n            radiusHandleDrawFunction = Handles.DotHandleCap;\n            radiusHandleSizeFunction = DefaultRadiusHandleSizeFunction;\n        }\n\n        ~ArcHandle()\n        {\n            s_MostRecentValidAngleHandleOrientations.Remove(GetHashCode());\n        }\n\n        public void SetColorWithoutRadiusHandle(Color color, float fillColorAlpha)\n        {\n            SetColorWithRadiusHandle(color, fillColorAlpha);\n            radiusHandleColor = Color.clear;\n            wireframeColor = color;\n        }\n\n        public void SetColorWithRadiusHandle(Color color, float fillColorAlpha)\n        {\n            fillColor = color * new Color(1f, 1f, 1f, fillColorAlpha);\n            angleHandleColor = color;\n            radiusHandleColor = color;\n            wireframeColor = color;\n        }\n\n        public void DrawHandle()\n        {\n            if (!m_ControlIDsReserved)\n                GetControlIDs();\n            m_ControlIDsReserved = false;\n\n            if (Handles.color.a == 0f)\n                return;\n\n            Vector3 scale = Handles.matrix.MultiplyPoint3x4(Vector3.one) - Handles.matrix.MultiplyPoint3x4(Vector3.zero);\n            if (scale.x == 0f && scale.z == 0f)\n                return;\n\n            Vector3 angleHandlePosition = Quaternion.AngleAxis(angle, Vector3.up) * Vector3.forward * radius;\n\n            float absAngle = Mathf.Abs(angle);\n            float excessAngle = angle % 360f;\n\n            using (new Handles.DrawingScope(Handles.color * fillColor))\n            {\n                if (Handles.color.a > 0f)\n                {\n                    for (int i = 0, revolutions = (int)absAngle / 360; i < revolutions; ++i)\n                        Handles.DrawSolidArc(Vector3.zero, Vector3.up, Vector3.forward, 360f, radius);\n                    Handles.DrawSolidArc(Vector3.zero, Vector3.up, Vector3.forward, excessAngle, radius);\n                }\n            }\n\n            using (new Handles.DrawingScope(Handles.color * wireframeColor))\n            {\n                if (Handles.color.a > 0f)\n                {\n                    Handles.DrawWireArc(\n                        Vector3.zero, Vector3.up, Vector3.forward, absAngle >= 360f ? 360f : excessAngle, radius\n                    );\n                }\n            }\n\n            // unless holding alt while already manipulating a control, exit before drawing control handles when holding alt, since alt-click will rotate scene view\n            if (Event.current.alt)\n            {\n                bool exit = true;\n                foreach (var id in m_RadiusHandleControlIDs)\n                {\n                    if (id == GUIUtility.hotControl)\n                    {\n                        exit = false;\n                        break;\n                    }\n                }\n                if (exit && GUIUtility.hotControl != m_AngleHandleControlID)\n                    return;\n            }\n\n            using (new Handles.DrawingScope(Handles.color * radiusHandleColor))\n            {\n                if (Handles.color.a > 0f)\n                {\n                    // draw one radius handle in each cardinal direction encompassed by the arc (i.e. every 90 degrees)\n                    float direction = Mathf.Sign(angle);\n                    int numRadiusHandles = Mathf.Min(1 + (int)(Mathf.Min(360f, absAngle) * 0.01111111111f), 4);\n                    for (int i = 0; i < numRadiusHandles; ++i)\n                    {\n                        Quaternion handleOrientation = Quaternion.AngleAxis(i * 90f * direction, Vector3.up);\n                        using (new Handles.DrawingScope(Handles.matrix * Matrix4x4.TRS(Vector3.zero, handleOrientation, Vector3.one)))\n                        {\n                            Vector3 radiusHandlePosition = Vector3.forward * radius;\n                            Vector3 newPosition;\n                            EditorGUI.BeginChangeCheck();\n                            {\n                                var size = radiusHandleSizeFunction == null ? 0f : radiusHandleSizeFunction(radiusHandlePosition);\n                                newPosition = Handles.Slider(\n                                    m_RadiusHandleControlIDs[i],\n                                    radiusHandlePosition,\n                                    Vector3.forward,\n                                    size,\n                                    radiusHandleDrawFunction,\n                                    EditorSnapSettings.move.z\n                                );\n                            }\n                            if (EditorGUI.EndChangeCheck())\n                            {\n                                radius += (newPosition - radiusHandlePosition).z;\n                            }\n                        }\n                    }\n                }\n            }\n\n            // draw angle handle last so it will always take precedence when overlapping a radius handle\n            using (new Handles.DrawingScope(Handles.color * angleHandleColor))\n            {\n                if (Handles.color.a > 0f && angleHandleDrawFunction != null)\n                {\n                    EditorGUI.BeginChangeCheck();\n                    {\n                        var size = angleHandleSizeFunction == null ? 0f : angleHandleSizeFunction(angleHandlePosition);\n                        s_CurrentlyDrawingAngleHandleHash = GetHashCode();\n                        angleHandlePosition = Handles.Slider2D(\n                            m_AngleHandleControlID,\n                            angleHandlePosition,\n                            Vector3.up,\n                            Vector3.forward,\n                            Vector3.right,\n                            size,\n                            angleHandleDrawFunction,\n                            Vector2.zero\n                        );\n                    }\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        float newAngle = Vector3.Angle(Vector3.forward, angleHandlePosition) *\n                            Mathf.Sign(Vector3.Dot(Vector3.right, angleHandlePosition));\n                        angle += Mathf.DeltaAngle(angle, newAngle);\n                        angle = Handles.SnapValue(angle, EditorSnapSettings.rotate);\n                    }\n                }\n            }\n        }\n\n        internal void GetControlIDs()\n        {\n            m_AngleHandleControlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive);\n            for (int i = 0; i < m_RadiusHandleControlIDs.Length; ++i)\n                m_RadiusHandleControlIDs[i] = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive);\n            m_ControlIDsReserved = true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/BoneHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\n\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    public sealed partial class Handles\n    {\n        internal sealed class BoneRenderer\n        {\n            private List<Matrix4x4> m_BoneMatrices;\n            private List<Vector4> m_BoneColors;\n            private List<Matrix4x4> m_BoneLeafMatrices;\n            private List<Vector4> m_BoneLeafColors;\n\n            private static Mesh s_Mesh;\n            private static Material s_Material;\n\n            private const float k_Epsilon = 1e-5f;\n            private const float k_BoneScale = 0.08f;\n            private const float k_BoneLeafScale = 0.24f;\n            private const int k_BoneVertexCount = 4;\n            private const int k_BoneLeafDiscResolution = 30;\n\n            public enum SubMeshType\n            {\n                BoneFaces,\n                BoneWire,\n                BoneLeafWire,\n                Count\n            }\n\n            public BoneRenderer()\n            {\n                m_BoneMatrices = new List<Matrix4x4>();\n                m_BoneColors = new List<Vector4>();\n                m_BoneLeafMatrices = new List<Matrix4x4>();\n                m_BoneLeafColors = new List<Vector4>();\n            }\n\n            public void AddBoneInstance(Vector3 start, Vector3 end, Color color)\n            {\n                float length = (end - start).magnitude;\n                if (length < k_Epsilon)\n                    return;\n\n                m_BoneMatrices.Add(ComputeBoneMatrix(start, end, length));\n                m_BoneColors.Add(new Vector4(color.r, color.g, color.b, color.a));\n            }\n\n            public void AddBoneLeafInstance(Vector3 position, Quaternion rotation, float radius, Color color)\n            {\n                radius *= k_BoneLeafScale;\n                if (radius < k_Epsilon)\n                    return;\n\n                m_BoneLeafMatrices.Add(Matrix4x4.TRS(position, rotation, new Vector3(radius, radius, radius)));\n                m_BoneLeafColors.Add(new Vector4(color.r, color.g, color.b, color.a));\n            }\n\n            public void ClearInstances()\n            {\n                m_BoneMatrices.Clear();\n                m_BoneColors.Clear();\n                m_BoneLeafMatrices.Clear();\n                m_BoneLeafColors.Clear();\n            }\n\n            public static Material material\n            {\n                get\n                {\n                    if (!s_Material)\n                    {\n                        Shader shader = (Shader)EditorGUIUtility.LoadRequired(\"SceneView/BoneHandles.shader\");\n                        s_Material = new Material(shader);\n                        s_Material.enableInstancing = true;\n                    }\n\n                    return s_Material;\n                }\n            }\n\n            public static Mesh mesh\n            {\n                get\n                {\n                    if (!s_Mesh)\n                    {\n                        s_Mesh = new Mesh();\n                        s_Mesh.name = \"BoneRendererMesh\";\n                        s_Mesh.subMeshCount = (int)SubMeshType.Count;\n                        s_Mesh.hideFlags = HideFlags.DontSave;\n\n                        // Bone vertices\n                        List<Vector3> vertices = new List<Vector3>(k_BoneVertexCount + k_BoneLeafDiscResolution * 3);\n                        vertices.Add(new Vector3(0.0f, 1.0f, 0.0f));\n                        vertices.Add(new Vector3(0.0f, 0.0f, -1.0f));\n                        vertices.Add(new Vector3(-0.9f, 0.0f, 0.5f));\n                        vertices.Add(new Vector3(0.9f, 0.0f, 0.5f));\n\n                        // Bone leaf vertices\n                        Vector3[] tmp = new Vector3[k_BoneLeafDiscResolution];\n                        Handles.SetDiscSectionPoints(tmp, Vector3.zero, Vector3.up, Vector3.right, 360f, 1f);\n                        vertices.AddRange(tmp);\n                        Handles.SetDiscSectionPoints(tmp, Vector3.zero, Vector3.right, Vector3.up, 360f, 1f);\n                        vertices.AddRange(tmp);\n                        Handles.SetDiscSectionPoints(tmp, Vector3.zero, Vector3.forward, Vector3.up, 360f, 1f);\n                        vertices.AddRange(tmp);\n                        s_Mesh.vertices = vertices.ToArray();\n\n                        // Build indices for different sub meshes\n                        int[] boneFaceIndices = new int[]\n                        {\n                            0, 2, 1,\n                            0, 1, 3,\n                            0, 3, 2,\n                            1, 2, 3\n                        };\n                        s_Mesh.SetIndices(boneFaceIndices, MeshTopology.Triangles, (int)SubMeshType.BoneFaces);\n\n                        int[] boneWireIndices = new int[]\n                        {\n                            0, 1, 0, 2, 0, 3, 1, 2, 2, 3, 3, 1\n                        };\n                        s_Mesh.SetIndices(boneWireIndices, MeshTopology.Lines, (int)SubMeshType.BoneWire);\n\n                        int counter = 0;\n                        int[] boneLeafWireIndices = new int[(vertices.Count - k_BoneVertexCount - 3) * 2];\n                        for (int i = k_BoneVertexCount + 1; i < vertices.Count; ++i)\n                        {\n                            if (((i - k_BoneVertexCount) % k_BoneLeafDiscResolution) == 0)\n                                continue;\n\n                            boneLeafWireIndices[counter++] = i - 1;\n                            boneLeafWireIndices[counter++] = i;\n                        }\n                        s_Mesh.SetIndices(boneLeafWireIndices, MeshTopology.Lines, (int)SubMeshType.BoneLeafWire);\n                    }\n\n                    return s_Mesh;\n                }\n            }\n\n            public int boneCount\n            {\n                get { return m_BoneMatrices.Count; }\n            }\n\n            public int boneLeafCount\n            {\n                get { return m_BoneLeafMatrices.Count; }\n            }\n\n            private static Matrix4x4 ComputeBoneMatrix(Vector3 start, Vector3 end, float length)\n            {\n                Vector3 direction = (end - start) / length;\n                Vector3 tangent = Vector3.Cross(direction, Vector3.up);\n                if (Vector3.SqrMagnitude(tangent) < 0.1f)\n                    tangent = Vector3.Cross(direction, Vector3.right);\n                tangent.Normalize();\n                Vector3 bitangent = Vector3.Cross(direction, tangent);\n\n                float scale = length * k_BoneScale;\n\n                return new Matrix4x4(\n                    new Vector4(tangent.x   * scale,  tangent.y   * scale,  tangent.z   * scale , 0f),\n                    new Vector4(direction.x * length, direction.y * length, direction.z * length, 0f),\n                    new Vector4(bitangent.x * scale,  bitangent.y * scale,  bitangent.z * scale , 0f),\n                    new Vector4(start.x, start.y, start.z, 1f));\n            }\n\n            private static int RenderChunkCount(int totalCount)\n            {\n                return Mathf.CeilToInt((totalCount / (float)Graphics.kMaxDrawMeshInstanceCount));\n            }\n\n            private static T[] GetRenderChunk<T>(List<T> array, int chunkIndex)\n            {\n                int rangeCount = (chunkIndex < (RenderChunkCount(array.Count) - 1)) ?\n                    Graphics.kMaxDrawMeshInstanceCount : array.Count - (chunkIndex * Graphics.kMaxDrawMeshInstanceCount);\n\n                return array.GetRange(chunkIndex * Graphics.kMaxDrawMeshInstanceCount, rangeCount).ToArray();\n            }\n\n            public static Vector3[] GetBoneWireVertices(Vector3 start, Vector3 end)\n            {\n                float length = (end - start).magnitude;\n                if (length < k_Epsilon)\n                    return null;\n\n                Matrix4x4 matrix = ComputeBoneMatrix(start, end, length);\n\n                Vector3[] pts = new Vector3[k_BoneVertexCount];\n                for (int i = 0; i < k_BoneVertexCount; ++i)\n                    pts[i] = matrix.MultiplyPoint3x4(mesh.vertices[i]);\n\n                int[] boneLines = mesh.GetIndices((int)SubMeshType.BoneWire);\n                Vector3[] lines = new Vector3[boneLines.Length];\n                for (int i = 0; i < boneLines.Length; ++i)\n                    lines[i] = pts[boneLines[i]];\n\n                return lines;\n            }\n\n            public void Render()\n            {\n                if (boneCount == 0)\n                    return;\n\n                Material mat = material;\n                mat.SetPass(0);\n\n                MaterialPropertyBlock propertyBlock = new MaterialPropertyBlock();\n                CommandBuffer cb = new CommandBuffer();\n\n                Matrix4x4[] matrices = null;\n\n                int chunkCount = RenderChunkCount(boneCount);\n                for (int i = 0; i < chunkCount; ++i)\n                {\n                    cb.Clear();\n                    matrices = GetRenderChunk(m_BoneMatrices, i);\n                    propertyBlock.SetVectorArray(\"_Color\", GetRenderChunk(m_BoneColors, i));\n\n                    material.DisableKeyword(\"WIRE_ON\");\n                    cb.DrawMeshInstanced(mesh, (int)SubMeshType.BoneFaces, material, 0, matrices, matrices.Length, propertyBlock);\n                    Graphics.ExecuteCommandBuffer(cb);\n\n                    cb.Clear();\n                    material.EnableKeyword(\"WIRE_ON\");\n                    cb.DrawMeshInstanced(mesh, (int)SubMeshType.BoneWire, material, 0, matrices, matrices.Length, propertyBlock);\n                    Graphics.ExecuteCommandBuffer(cb);\n                }\n\n                if (boneLeafCount == 0)\n                    return;\n\n                chunkCount = RenderChunkCount(boneLeafCount);\n                cb.Clear();\n                material.EnableKeyword(\"WIRE_ON\");\n\n                for (int i = 0; i < chunkCount; ++i)\n                {\n                    matrices = GetRenderChunk(m_BoneLeafMatrices, i);\n                    propertyBlock.SetVectorArray(\"_Color\", GetRenderChunk(m_BoneLeafColors, i));\n                    cb.DrawMeshInstanced(mesh, (int)SubMeshType.BoneLeafWire, material, 0, matrices, matrices.Length, propertyBlock);\n                }\n                Graphics.ExecuteCommandBuffer(cb);\n            }\n        }\n\n        internal static float DistanceToPolygone(Vector3[] vertices)\n        {\n            return HandleUtility.DistanceToPolyLine(vertices);\n        }\n\n        internal static void DoBoneHandle(Transform target, BoneRenderer renderer)\n        {\n            DoBoneHandle(target, null, renderer);\n        }\n\n        internal static void DoBoneHandle(Transform target, Dictionary<Transform, bool> validBones, BoneRenderer renderer)\n        {\n            int id = target.name.GetHashCode();\n            Event evt = Event.current;\n\n            bool hasValidChildBones = false;\n            if (validBones != null)\n            {\n                foreach (Transform child in target)\n                {\n                    if (validBones.ContainsKey(child))\n                    {\n                        hasValidChildBones = true;\n                        break;\n                    }\n                }\n            }\n\n            Vector3 basePoint = target.position;\n\n            List<Vector3> endPoints = new List<Vector3>();\n            // [case 525602] do not draw root.\n            if (!hasValidChildBones && target.parent != null)\n            {\n                endPoints.Add(target.position + (target.position - target.parent.position) * 0.4f);\n            }\n            else\n            {\n                foreach (Transform child in target)\n                {\n                    // Only render bone connections to valid bones\n                    // (except if no child bones are valid - then draw all connections)\n                    if (validBones != null && !validBones.ContainsKey(child))\n                        continue;\n\n                    endPoints.Add(child.position);\n                }\n            }\n\n            for (int i = 0; i < endPoints.Count; i++)\n            {\n                Vector3 endPoint = endPoints[i];\n\n\n                switch (evt.GetTypeForControl(id))\n                {\n                    case EventType.Layout:\n                    case EventType.MouseMove:\n                    {\n                        // TODO : This is slow and should be revisited prior to exposing bone handles\n                        Vector3[] vertices = BoneRenderer.GetBoneWireVertices(basePoint, endPoint);\n                        if (vertices != null)\n                            HandleUtility.AddControl(id, DistanceToPolygone(vertices));\n\n                        break;\n                    }\n                    case EventType.MouseDown:\n                    {\n                        // am I closest to the thingy?\n                        if (!evt.alt  && HandleUtility.nearestControl == id && evt.button == 0)\n                        {\n                            GUIUtility.hotControl = id; // Grab mouse focus\n                            if (evt.shift)\n                            {\n                                Object[] selected = Selection.objects;\n                                if (ArrayUtility.Contains(selected, target) == false)\n                                {\n                                    ArrayUtility.Add(ref selected, target);\n                                    Selection.objects = selected;\n                                }\n                            }\n                            else\n                                Selection.activeObject = target;\n\n                            EditorGUIUtility.PingObject(target);\n\n                            evt.Use();\n                        }\n                        break;\n                    }\n                    case EventType.MouseDrag:\n                    {\n                        if (!evt.alt && GUIUtility.hotControl == id)\n                        {\n                            DragAndDrop.PrepareStartDrag();\n                            DragAndDrop.objectReferences = new UnityEngine.Object[] {target};\n                            DragAndDrop.StartDrag(ObjectNames.GetDragAndDropTitle(target));\n\n                            // having a hot control set during drag makes the control eat the drag events\n                            // and dragging of bones no longer works over the avatar configure window\n                            // see case 912016\n                            GUIUtility.hotControl = 0;\n\n                            evt.Use();\n                        }\n                        break;\n                    }\n                    case EventType.MouseUp:\n                    {\n                        if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))\n                        {\n                            GUIUtility.hotControl = 0;\n                            evt.Use();\n                        }\n                        break;\n                    }\n                    case EventType.Repaint:\n                    {\n                        color = GUIUtility.hotControl == 0 && HandleUtility.nearestControl == id ? Handles.preselectionColor : color;\n                        if (hasValidChildBones)\n                            renderer.AddBoneInstance(basePoint, endPoint, color);\n                        else\n                            renderer.AddBoneLeafInstance(basePoint, target.rotation, (endPoint - basePoint).magnitude, color);\n                    }\n                    break;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/BoundsHandle/BoxBoundsHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public class BoxBoundsHandle : PrimitiveBoundsHandle\n    {\n        [Obsolete(\"Use parameterless constructor instead.\")]\n        public BoxBoundsHandle(int controlIDHint) : base(controlIDHint) {}\n\n        public BoxBoundsHandle() : base() {}\n\n        public UnityEngine.Vector3 size { get { return GetSize(); } set { SetSize(value); } }\n\n        protected override void DrawWireframe()\n        {\n            Handles.DrawWireCube(center, size);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/BoundsHandle/CapsuleBoundsHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public class CapsuleBoundsHandle : PrimitiveBoundsHandle\n    {\n        public enum HeightAxis { X, Y, Z }\n\n        private const int k_DirectionX = 0;\n        private const int k_DirectionY = 1;\n        private const int k_DirectionZ = 2;\n\n        private static readonly Vector3[] s_HeightAxes = new[] { Vector3.right, Vector3.up, Vector3.forward };\n        private static readonly int[] s_NextAxis = new[] { 1, 2, 0 };\n\n        public HeightAxis heightAxis\n        {\n            get { return (HeightAxis)m_HeightAxis; }\n            set\n            {\n                int newValue = (int)value;\n                if (m_HeightAxis == newValue)\n                    return;\n                Vector3 size = Vector3.one * radius * 2f;\n                size[newValue] = GetSize()[m_HeightAxis];\n                m_HeightAxis = newValue;\n                SetSize(size);\n            }\n        }\n        private int m_HeightAxis = k_DirectionY;\n\n        public float height\n        {\n            get\n            {\n                // zero out height if height axis is disabled\n                return !IsAxisEnabled(m_HeightAxis) ? 0f : Mathf.Max(GetSize()[m_HeightAxis], 2f * radius);\n            }\n            set\n            {\n                // height cannot be less than diameter\n                value = Mathf.Max(Mathf.Abs(value), 2f * radius);\n                if (height == value)\n                    return;\n                Vector3 size = GetSize();\n                size[m_HeightAxis] = value;\n                SetSize(size);\n            }\n        }\n\n        public float radius\n        {\n            get\n            {\n                int radiusAxis;\n                // return 0 if only enabled axis is a single radius axis\n                if (GetRadiusAxis(out radiusAxis) || IsAxisEnabled(m_HeightAxis))\n                    return 0.5f * GetSize()[radiusAxis];\n                else\n                    return 0f;\n            }\n            set\n            {\n                Vector3 size = GetSize();\n                float diameter = 2f * value;\n                // height cannot be less than diameter\n                for (int axis = 0; axis < 3; ++axis)\n                    size[axis] = axis == m_HeightAxis ? Mathf.Max(size[axis], diameter) : diameter;\n                SetSize(size);\n            }\n        }\n\n        [Obsolete(\"Use parameterless constructor instead.\")]\n        public CapsuleBoundsHandle(int controlIDHint) : base(controlIDHint) {}\n\n        public CapsuleBoundsHandle() : base() {}\n\n        protected override void DrawWireframe()\n        {\n            HeightAxis radAxis1 = HeightAxis.Y;\n            HeightAxis radAxis2 = HeightAxis.Z;\n            switch (heightAxis)\n            {\n                case HeightAxis.Y:\n                    radAxis1 = HeightAxis.Z;\n                    radAxis2 = HeightAxis.X;\n                    break;\n                case HeightAxis.Z:\n                    radAxis1 = HeightAxis.X;\n                    radAxis2 = HeightAxis.Y;\n                    break;\n            }\n            bool doHeightAxis = IsAxisEnabled((int)heightAxis);\n            bool doRadiusAxis1 = IsAxisEnabled((int)radAxis1);\n            bool doRadiusAxis2 = IsAxisEnabled((int)radAxis2);\n\n            Vector3 hgtAx = s_HeightAxes[m_HeightAxis];\n            Vector3 radAx1 = s_HeightAxes[s_NextAxis[m_HeightAxis]];\n            Vector3 radAx2 = s_HeightAxes[s_NextAxis[s_NextAxis[m_HeightAxis]]];\n            float rad = radius;\n            float hgt = height;\n            Vector3 top = center + hgtAx * (hgt * 0.5f - rad);\n            Vector3 bottom = center - hgtAx * (hgt * 0.5f - rad);\n\n            // draw caps and connecting lines for each enabled axis if height axis is enabled\n            if (doHeightAxis)\n            {\n                if (doRadiusAxis2)\n                {\n                    Handles.DrawWireArc(top, radAx1, radAx2, 180f, rad);\n                    Handles.DrawWireArc(bottom, radAx1, radAx2, -180f, rad);\n                    Handles.DrawLine(top + radAx2 * rad, bottom + radAx2 * rad);\n                    Handles.DrawLine(top - radAx2 * rad, bottom - radAx2 * rad);\n                }\n                if (doRadiusAxis1)\n                {\n                    Handles.DrawWireArc(top, radAx2, radAx1, -180f, rad);\n                    Handles.DrawWireArc(bottom, radAx2, radAx1, 180f, rad);\n                    Handles.DrawLine(top + radAx1 * rad, bottom + radAx1 * rad);\n                    Handles.DrawLine(top - radAx1 * rad, bottom - radAx1 * rad);\n                }\n            }\n\n            // do cross-section if both radius axes are enabled\n            if (doRadiusAxis1 && doRadiusAxis2)\n            {\n                Handles.DrawWireArc(top, hgtAx, radAx1, 360f, rad);\n                Handles.DrawWireArc(bottom, hgtAx, radAx1, -360f, rad);\n            }\n        }\n\n        protected override Bounds OnHandleChanged(HandleDirection handle, Bounds boundsOnClick, Bounds newBounds)\n        {\n            int changedAxis = k_DirectionX;\n            switch (handle)\n            {\n                case HandleDirection.NegativeY:\n                case HandleDirection.PositiveY:\n                    changedAxis = k_DirectionY;\n                    break;\n                case HandleDirection.NegativeZ:\n                case HandleDirection.PositiveZ:\n                    changedAxis = k_DirectionZ;\n                    break;\n            }\n\n            Vector3 upperBound = newBounds.max;\n            Vector3 lowerBound = newBounds.min;\n\n            // ensure height cannot be made less than diameter\n            if (changedAxis == m_HeightAxis)\n            {\n                int radiusAxis;\n                GetRadiusAxis(out radiusAxis);\n                float diameter = upperBound[radiusAxis] - lowerBound[radiusAxis];\n                float newHeight = upperBound[m_HeightAxis] - lowerBound[m_HeightAxis];\n                if (newHeight < diameter)\n                {\n                    if (handle == HandleDirection.PositiveX || handle == HandleDirection.PositiveY || handle == HandleDirection.PositiveZ)\n                        upperBound[m_HeightAxis] = lowerBound[m_HeightAxis] + diameter;\n                    else\n                        lowerBound[m_HeightAxis] = upperBound[m_HeightAxis] - diameter;\n                }\n            }\n            // ensure radius changes uniformly and enlarges the height if necessary\n            else\n            {\n                // try to return height to its value at the time handle was clicked\n                upperBound[m_HeightAxis] = boundsOnClick.center[m_HeightAxis] + 0.5f * boundsOnClick.size[m_HeightAxis];\n                lowerBound[m_HeightAxis] = boundsOnClick.center[m_HeightAxis] - 0.5f * boundsOnClick.size[m_HeightAxis];\n\n                float rad = 0.5f * (upperBound[changedAxis] - lowerBound[changedAxis]);\n                float halfCurrentHeight = 0.5f * (upperBound[m_HeightAxis] - lowerBound[m_HeightAxis]);\n                for (int axis = 0; axis < 3; ++axis)\n                {\n                    if (axis == changedAxis)\n                        continue;\n                    float amt = axis == m_HeightAxis ? Mathf.Max(halfCurrentHeight, rad) : rad;\n                    lowerBound[axis] = center[axis] - amt;\n                    upperBound[axis] = center[axis] + amt;\n                }\n            }\n            return new Bounds((upperBound + lowerBound) * 0.5f, upperBound - lowerBound);\n        }\n\n        // returns true only if both radius axes are enabled\n        private bool GetRadiusAxis(out int radiusAxis)\n        {\n            radiusAxis = s_NextAxis[m_HeightAxis];\n            if (!IsAxisEnabled(radiusAxis))\n            {\n                radiusAxis = s_NextAxis[radiusAxis];\n                return false;\n            }\n            return IsAxisEnabled(s_NextAxis[radiusAxis]);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/BoundsHandle/PrimitiveBoundsHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing UnityEditor.Snap;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public abstract class PrimitiveBoundsHandle\n    {\n        [Flags]\n        public enum Axes\n        {\n            None = 0,\n            X = 1 << 0,\n            Y = 1 << 1,\n            Z = 1 << 2,\n            All = X | Y | Z\n        }\n\n        protected enum HandleDirection\n        {\n            PositiveX,\n            NegativeX,\n            PositiveY,\n            NegativeY,\n            PositiveZ,\n            NegativeZ\n        }\n\n        private static readonly float s_DefaultMidpointHandleSize = 0.03f;\n        private static readonly int[] s_NextAxis = new[] { 1, 2, 0 };\n\n        internal static GUIContent editModeButton\n        {\n            get\n            {\n                if (s_EditModeButton == null)\n                {\n                    s_EditModeButton = new GUIContent(\n                        EditorGUIUtility.IconContent(\"EditCollider\").image,\n                        EditorGUIUtility.TrTextContent(\"Edit bounding volume.\\n\\n - Hold Alt after clicking control handle to pin center in place.\\n - Hold Shift after clicking control handle to scale uniformly.\").text\n                    );\n                }\n                return s_EditModeButton;\n            }\n        }\n        private static GUIContent s_EditModeButton;\n\n        public static float DefaultMidpointHandleSizeFunction(Vector3 position)\n        {\n            return HandleUtility.GetHandleSize(position) * s_DefaultMidpointHandleSize;\n        }\n\n        private int[] m_ControlIDs = new int[6] { 0, 0, 0, 0, 0, 0 };\n        private Bounds m_Bounds;\n        private Bounds m_BoundsOnClick;\n\n        public Vector3 center\n        {\n            get { return m_Bounds.center; }\n            set { m_Bounds.center = value; }\n        }\n\n        public Axes axes { get; set; }\n\n        public Color handleColor { get; set; }\n\n        public Color wireframeColor { get; set; }\n\n        public Handles.CapFunction midpointHandleDrawFunction { get; set; }\n\n        public Handles.SizeFunction midpointHandleSizeFunction { get; set; }\n\n        [Obsolete(\"Use parameterless constructor instead.\")]\n        public PrimitiveBoundsHandle(int controlIDHint) : this() {}\n\n        public PrimitiveBoundsHandle()\n        {\n            handleColor = Color.white;\n            wireframeColor = Color.white;\n            axes = Axes.X | Axes.Y | Axes.Z;\n            midpointHandleDrawFunction = Handles.DotHandleCap;\n            midpointHandleSizeFunction = DefaultMidpointHandleSizeFunction;\n        }\n\n        public void SetColor(Color color)\n        {\n            handleColor = color;\n            wireframeColor = color;\n        }\n\n        public void DrawHandle()\n        {\n            for (int i = 0, count = m_ControlIDs.Length; i < count; ++i)\n                m_ControlIDs[i] = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive);\n\n            // wireframe (before handles so handles are rendered top most)\n            using (new Handles.DrawingScope(Handles.color * wireframeColor))\n                DrawWireframe();\n\n            // unless holding alt to pin center, exit before drawing control handles when holding alt, since alt-click will rotate scene view\n            if (Event.current.alt)\n            {\n                bool exit = true;\n                foreach (var id in m_ControlIDs)\n                {\n                    if (id == GUIUtility.hotControl)\n                    {\n                        exit = false;\n                        break;\n                    }\n                }\n                if (exit)\n                    return;\n            }\n\n            // bounding box extents\n            Vector3 minPos = m_Bounds.min;\n            Vector3 maxPos = m_Bounds.max;\n\n            // handles\n            int prevHotControl = GUIUtility.hotControl;\n            bool isCameraInsideBox = Camera.current != null\n                && m_Bounds.Contains(Handles.inverseMatrix.MultiplyPoint(Camera.current.transform.position));\n            EditorGUI.BeginChangeCheck();\n            using (new Handles.DrawingScope(Handles.color * handleColor))\n            {\n                if (Handles.color.a > 0)\n                    MidpointHandles(ref minPos, ref maxPos, isCameraInsideBox);\n            }\n            bool changed = EditorGUI.EndChangeCheck();\n\n            // detect if any handles got hotControl\n            if (prevHotControl != GUIUtility.hotControl && GUIUtility.hotControl != 0)\n            {\n                m_BoundsOnClick = m_Bounds;\n            }\n\n            // update if changed\n            if (changed)\n            {\n                // determine which handle changed to apply any further modifications\n                m_Bounds.center = (maxPos + minPos) * 0.5f;\n                m_Bounds.size = maxPos - minPos;\n                for (int i = 0, count = m_ControlIDs.Length; i < count; ++i)\n                {\n                    if (GUIUtility.hotControl == m_ControlIDs[i])\n                        m_Bounds = OnHandleChanged((HandleDirection)i, m_BoundsOnClick, m_Bounds);\n                }\n\n                // shift scales uniformly\n                if (Event.current.shift)\n                {\n                    int hotControl = GUIUtility.hotControl;\n                    Vector3 size = m_Bounds.size;\n                    int scaleAxis = 0;\n                    if (hotControl == m_ControlIDs[(int)HandleDirection.PositiveY] || hotControl == m_ControlIDs[(int)HandleDirection.NegativeY])\n                    {\n                        scaleAxis = 1;\n                    }\n                    if (hotControl == m_ControlIDs[(int)HandleDirection.PositiveZ] || hotControl == m_ControlIDs[(int)HandleDirection.NegativeZ])\n                    {\n                        scaleAxis = 2;\n                    }\n\n                    if (Mathf.Approximately(m_BoundsOnClick.size[scaleAxis], 0f))\n                    {\n                        if (m_BoundsOnClick.size == Vector3.zero)\n                            size = Vector3.one * size[scaleAxis];\n                    }\n                    else\n                    {\n                        var scaleFactor = size[scaleAxis] / m_BoundsOnClick.size[scaleAxis];\n                        var nextAxis = s_NextAxis[scaleAxis];\n                        size[nextAxis] = scaleFactor * m_BoundsOnClick.size[nextAxis];\n                        nextAxis = s_NextAxis[nextAxis];\n                        size[nextAxis] = scaleFactor * m_BoundsOnClick.size[nextAxis];\n                    }\n                    m_Bounds.size = size;\n                }\n\n                // alt scales from the center\n                if (Event.current.alt)\n                    m_Bounds.center = m_BoundsOnClick.center;\n            }\n        }\n\n        protected abstract void DrawWireframe();\n\n        protected virtual Bounds OnHandleChanged(HandleDirection handle, Bounds boundsOnClick, Bounds newBounds)\n        {\n            return newBounds;\n        }\n\n        protected Vector3 GetSize()\n        {\n            Vector3 size = m_Bounds.size;\n            // zero out size on disabled axes\n            for (int axis = 0; axis < 3; ++axis)\n            {\n                if (!IsAxisEnabled(axis))\n                    size[axis] = 0f;\n            }\n            return size;\n        }\n\n        protected void SetSize(Vector3 size)\n        {\n            m_Bounds.size = new Vector3(Mathf.Abs(size.x), Mathf.Abs(size.y), Mathf.Abs(size.z));\n        }\n\n        protected bool IsAxisEnabled(Axes axis)\n        {\n            return (axes & axis) == axis;\n        }\n\n        protected bool IsAxisEnabled(int vector3Axis)\n        {\n            switch (vector3Axis)\n            {\n                case 0:\n                    return IsAxisEnabled(Axes.X);\n                case 1:\n                    return IsAxisEnabled(Axes.Y);\n                case 2:\n                    return IsAxisEnabled(Axes.Z);\n                default:\n                    throw new ArgumentOutOfRangeException(\"vector3Axis\", \"Must be 0, 1, or 2\");\n            }\n        }\n\n        private void MidpointHandles(ref Vector3 minPos, ref Vector3 maxPos, bool isCameraInsideBox)\n        {\n            Vector3 xAxis = Vector3.right;\n            Vector3 yAxis = Vector3.up;\n            Vector3 zAxis = Vector3.forward;\n            Vector3 middle = (maxPos + minPos) * 0.5f;\n\n            Vector3 localPos, newPos;\n            if (IsAxisEnabled(Axes.X))\n            {\n                // +X\n                localPos = new Vector3(maxPos.x, middle.y, middle.z);\n                newPos = MidpointHandle(m_ControlIDs[(int)HandleDirection.PositiveX], localPos, yAxis, zAxis, isCameraInsideBox);\n                maxPos.x = Mathf.Max(newPos.x, minPos.x);\n\n                // -X\n                localPos = new Vector3(minPos.x, middle.y, middle.z);\n                newPos = MidpointHandle(m_ControlIDs[(int)HandleDirection.NegativeX], localPos, yAxis, -zAxis, isCameraInsideBox);\n                minPos.x = Mathf.Min(newPos.x, maxPos.x);\n            }\n\n            if (IsAxisEnabled(Axes.Y))\n            {\n                // +Y\n                localPos = new Vector3(middle.x, maxPos.y, middle.z);\n                newPos = MidpointHandle(m_ControlIDs[(int)HandleDirection.PositiveY], localPos, xAxis, -zAxis, isCameraInsideBox);\n                maxPos.y = Mathf.Max(newPos.y, minPos.y);\n\n                // -Y\n                localPos = new Vector3(middle.x, minPos.y, middle.z);\n                newPos = MidpointHandle(m_ControlIDs[(int)HandleDirection.NegativeY], localPos, xAxis, zAxis, isCameraInsideBox);\n                minPos.y = Mathf.Min(newPos.y, maxPos.y);\n            }\n\n            if (IsAxisEnabled(Axes.Z))\n            {\n                // +Z\n                localPos = new Vector3(middle.x, middle.y, maxPos.z);\n                newPos = MidpointHandle(m_ControlIDs[(int)HandleDirection.PositiveZ], localPos, yAxis, -xAxis, isCameraInsideBox);\n                maxPos.z = Mathf.Max(newPos.z, minPos.z);\n\n                // -Z\n                localPos = new Vector3(middle.x, middle.y, minPos.z);\n                newPos = MidpointHandle(m_ControlIDs[(int)HandleDirection.NegativeZ], localPos, yAxis, xAxis, isCameraInsideBox);\n                minPos.z = Mathf.Min(newPos.z, maxPos.z);\n            }\n        }\n\n        private Vector3 MidpointHandle(int id, Vector3 localPos, Vector3 localTangent, Vector3 localBinormal, bool isCameraInsideBox)\n        {\n            Color oldColor = Handles.color;\n\n            AdjustMidpointHandleColor(localPos, localTangent, localBinormal, isCameraInsideBox);\n\n            if (Handles.color.a > 0f && midpointHandleDrawFunction != null)\n            {\n                Vector3 localDir = Vector3.Cross(localTangent, localBinormal).normalized;\n\n                var size = midpointHandleSizeFunction == null ? 0f : midpointHandleSizeFunction(localPos);\n\n                localPos = UnityEditorInternal.Slider1D.Do(id, localPos, localDir, size, midpointHandleDrawFunction, EditorSnapSettings.scale);\n            }\n\n            Handles.color = oldColor;\n            return localPos;\n        }\n\n        private void AdjustMidpointHandleColor(Vector3 localPos, Vector3 localTangent, Vector3 localBinormal, bool isCameraInsideBox)\n        {\n            float alphaMultiplier = 1f;\n\n            // if inside the box then ignore back facing alpha multiplier (otherwise all handles will look disabled)\n            if (!isCameraInsideBox && axes == (Axes.X | Axes.Y | Axes.Z))\n            {\n                // use tangent and binormal to calculate normal in case handle matrix is skewed\n                Vector3 worldTangent = Handles.matrix.MultiplyVector(localTangent);\n                Vector3 worldBinormal = Handles.matrix.MultiplyVector(localBinormal);\n                Vector3 worldDir = Vector3.Cross(worldTangent, worldBinormal).normalized;\n\n                // adjust color if handle is back facing\n                float cosV;\n\n                if (Camera.current.orthographic)\n                    cosV = Vector3.Dot(-Camera.current.transform.forward, worldDir);\n                else\n                    cosV = Vector3.Dot((Camera.current.transform.position - Handles.matrix.MultiplyPoint(localPos)).normalized, worldDir);\n\n                if (cosV < -0.0001f)\n                    alphaMultiplier *= Handles.backfaceAlphaMultiplier;\n            }\n\n            Handles.color *= new Color(1f, 1f, 1f, alphaMultiplier);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/BoundsHandle/SphereBoundsHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public class SphereBoundsHandle : PrimitiveBoundsHandle\n    {\n        [Obsolete(\"Use parameterless constructor instead.\")]\n        public SphereBoundsHandle(int controlIDHint) : base(controlIDHint) {}\n\n        public SphereBoundsHandle() : base() {}\n\n        public float radius\n        {\n            get\n            {\n                Vector3 size = GetSize();\n                float diameter = 0f;\n                for (int axis = 0; axis < 3; ++axis)\n                {\n                    // only consider size values on enabled axes\n                    if (IsAxisEnabled(axis))\n                        diameter = Mathf.Max(diameter, Mathf.Abs(size[axis]));\n                }\n                return diameter * 0.5f;\n            }\n            set { SetSize(2f * value * Vector3.one); }\n        }\n\n        protected override void DrawWireframe()\n        {\n            bool x = IsAxisEnabled(Axes.X);\n            bool y = IsAxisEnabled(Axes.Y);\n            bool z = IsAxisEnabled(Axes.Z);\n            if (x && y)\n                Handles.DrawWireArc(center, Vector3.forward, Vector3.up, 360f, radius);\n            if (x && z)\n                Handles.DrawWireArc(center, Vector3.up, Vector3.right, 360f, radius);\n            if (y && z)\n                Handles.DrawWireArc(center, Vector3.right, Vector3.forward, 360f, radius);\n            if (x && !y && !z)\n                Handles.DrawLine(Vector3.right * radius, Vector3.left * radius);\n            if (!x && y && !z)\n                Handles.DrawLine(Vector3.up * radius, Vector3.down * radius);\n            if (!x && !y && z)\n                Handles.DrawLine(Vector3.forward * radius, Vector3.back * radius);\n        }\n\n        protected override Bounds OnHandleChanged(HandleDirection handle, Bounds boundsOnClick, Bounds newBounds)\n        {\n            Vector3 upperBound = newBounds.max;\n            Vector3 lowerBound = newBounds.min;\n            // ensure radius changes uniformly\n            int changedAxis = 0;\n            switch (handle)\n            {\n                case HandleDirection.NegativeY:\n                case HandleDirection.PositiveY:\n                    changedAxis = 1;\n                    break;\n                case HandleDirection.NegativeZ:\n                case HandleDirection.PositiveZ:\n                    changedAxis = 2;\n                    break;\n            }\n            float rad = 0.5f * (upperBound[changedAxis] - lowerBound[changedAxis]);\n            for (int axis = 0; axis < 3; ++axis)\n            {\n                if (axis == changedAxis)\n                    continue;\n                lowerBound[axis] = center[axis] - rad;\n                upperBound[axis] = center[axis] + rad;\n            }\n            return new Bounds((upperBound + lowerBound) * 0.5f, upperBound - lowerBound);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/Button.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    internal class Button\n    {\n        internal static bool Do(int id, Vector3 position, Quaternion direction, float size, float pickSize, Handles.CapFunction capFunction, bool useLayoutAndMouseMove)\n        {\n            if(!useLayoutAndMouseMove)\n            {\n                Event evt = Event.current;\n                if(evt.type == EventType.Layout || evt.type == EventType.MouseMove)\n                {\n                    //Consuming event id\n                    evt.GetTypeForControl(id);\n                    return false;\n                }\n            }\n\n            return Do(id, position, direction, size, pickSize, capFunction);\n        }\n\n        public static bool Do(int id, Vector3 position, Quaternion direction, float size, float pickSize, Handles.CapFunction capFunction)\n        {\n            Event evt = Event.current;\n\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.Layout:\n                    if (GUI.enabled)\n                        capFunction(id, position, direction, pickSize, EventType.Layout);\n                    break;\n                case EventType.MouseMove:\n                    if (HandleUtility.nearestControl == id)\n                        HandleUtility.Repaint();\n                    break;\n                case EventType.MouseDown:\n                    // am I closest to the thingy?\n                    if (HandleUtility.nearestControl == id && ((evt.button == 0 || evt.button == 2) && !evt.alt))\n                    {\n                        GUIUtility.hotControl = id; // Grab mouse focus\n                        evt.Use();\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))\n                    {\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n\n                        if (HandleUtility.nearestControl == id)\n                            return true;\n                    }\n                    break;\n                case EventType.Repaint:\n                    Color origColor = Handles.color;\n                    if (HandleUtility.nearestControl == id && GUI.enabled && GUIUtility.hotControl == 0 && !evt.alt)\n                        Handles.color = Handles.preselectionColor;\n\n                    capFunction(id, position, direction, size, EventType.Repaint);\n\n                    Handles.color = origColor;\n                    break;\n            }\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/ConeFrustrumHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class Handles\n    {\n        [Flags]\n        internal enum ConeHandles\n        {\n            Radius = (1 << 0),\n            Angle = (1 << 1),\n            Range = (1 << 2),\n\n            All = (Radius | Angle | Range)\n        }\n\n        // Description\n        // 'radius' is near-radius at start of cone frustrum (far-radius is derived from 'angle' and near-radius)\n        // 'angle' is cone angle from near disc of conefrustrum (if near-radius is 0 then angle is the half angle of view frustrum)\n        // 'range' is height of conefrustrum\n        internal static Vector3 DoConeFrustrumHandle(Quaternion rotation, Vector3 position, Vector3 radiusAngleRange, ConeHandles showHandles)\n        {\n            if (Event.current.alt)\n                showHandles = 0;\n\n            Vector3 forward = rotation * Vector3.forward;\n            Vector3 up = rotation * Vector3.up;\n            Vector3 right = rotation * Vector3.right;\n\n            float nearRadius = radiusAngleRange.x;\n            float angle = radiusAngleRange.y;\n            float range = radiusAngleRange.z;\n\n            angle = Mathf.Max(0.0f, angle);\n\n            // Range handle at the center of the cone (allow negative range)\n            if ((showHandles & ConeHandles.Range) != 0)\n            {\n                bool temp = GUI.changed;\n                range = SizeSlider(position, forward, range);\n                GUI.changed |= temp;\n            }\n\n            // Near plane of cone frustrum\n            if ((showHandles & ConeHandles.Radius) != 0)\n            {\n                bool temp = GUI.changed;\n                GUI.changed = false;\n                nearRadius = SizeSlider(position, up, nearRadius);\n                nearRadius = SizeSlider(position, -up, nearRadius);\n                nearRadius = SizeSlider(position, right, nearRadius);\n                nearRadius = SizeSlider(position, -right, nearRadius);\n                if (GUI.changed)\n                    nearRadius = Mathf.Max(0.0f, nearRadius);\n                GUI.changed |= temp;\n            }\n\n            // Far plane of cone frustrum\n            float farRadius = Mathf.Min(1000f, Mathf.Abs(range * Mathf.Tan(Mathf.Deg2Rad * angle)) + nearRadius);\n            if ((showHandles & ConeHandles.Angle) != 0)\n            {\n                bool temp = GUI.changed;\n                GUI.changed = false;\n                farRadius = SizeSlider(position + forward * range, up, farRadius);\n                farRadius = SizeSlider(position + forward * range, -up, farRadius);\n                farRadius = SizeSlider(position + forward * range, right, farRadius);\n                farRadius = SizeSlider(position + forward * range, -right, farRadius);\n                if (GUI.changed)\n                    angle = Mathf.Clamp((Mathf.Rad2Deg * Mathf.Atan((farRadius - nearRadius) / Mathf.Abs(range))), 0.0F, 90f);\n                GUI.changed |= temp;\n            }\n\n            // Draw\n            if (nearRadius > 0)\n                DrawWireDisc(position, forward, nearRadius);\n\n            if (farRadius > 0)\n                DrawWireDisc(position + range * forward, forward, farRadius);\n\n            DrawLine(position + up * nearRadius, (position + forward * range) + up * farRadius);\n            DrawLine(position - up * nearRadius, (position + forward * range) - up * farRadius);\n            DrawLine(position + right * nearRadius, (position + forward * range) + right * farRadius);\n            DrawLine(position - right * nearRadius, (position + forward * range) - right * farRadius);\n\n            return new Vector3(nearRadius, angle, range);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/ConeHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class Handles\n    {\n        static readonly int[] k_HandleIndices = { 0, 1, 0, 2, 0, 3, 0, 4 };\n        static Vector3[] s_HandlePoints = new Vector3[5];\n\n        internal static Vector2 DoConeHandle(Quaternion rotation, Vector3 position, Vector2 angleAndRange, float angleScale, float rangeScale, bool handlesOnly)\n        {\n            float spotAngle = angleAndRange.x;\n            float range = angleAndRange.y;\n            float actualRange = range * rangeScale;\n\n            Vector3 forward = rotation * Vector3.forward;\n            Vector3 up = rotation * Vector3.up;\n            Vector3 right = rotation * Vector3.right;\n\n            // Range handle at the center of the circle\n            bool temp = GUI.changed;\n            GUI.changed = false;\n            actualRange = SizeSlider(position, forward, actualRange);\n            if (GUI.changed)\n                range = Mathf.Max(0.0F, actualRange / rangeScale);\n            GUI.changed |= temp;\n\n            // Angle handles on circle\n            temp = GUI.changed;\n            GUI.changed = false;\n\n            var centerPos = position + forward * actualRange;\n            float lightDisc = actualRange * Mathf.Tan(Mathf.Deg2Rad * spotAngle / 2.0f) * angleScale;\n            lightDisc = SizeSlider(centerPos, up, lightDisc);\n            lightDisc = SizeSlider(centerPos, -up, lightDisc);\n            lightDisc = SizeSlider(centerPos, right, lightDisc);\n            lightDisc = SizeSlider(centerPos, -right, lightDisc);\n            if (GUI.changed)\n                spotAngle = Mathf.Clamp((Mathf.Rad2Deg * Mathf.Atan(lightDisc / (actualRange * angleScale)) * 2), 0.0F, 179F);\n            GUI.changed |= temp;\n\n            // Draw disc\n            if (!handlesOnly && Event.current.type == EventType.Repaint)\n            {\n                s_HandlePoints[0] = centerPos;\n                s_HandlePoints[1] = centerPos + up * lightDisc;\n                s_HandlePoints[2] = centerPos - up * lightDisc;\n                s_HandlePoints[3] = centerPos + right * lightDisc;\n                s_HandlePoints[4] = centerPos - right * lightDisc;\n\n                DrawLines(s_HandlePoints, k_HandleIndices);\n                DrawWireDisc(centerPos, forward, lightDisc);\n            }\n\n            return new Vector2(spotAngle, range);\n        }\n\n        static internal float SizeSlider(Vector3 p, Vector3 d, float r)\n        {\n            Vector3 position = p + d * r;\n            float size = HandleUtility.GetHandleSize(position);\n            bool temp = GUI.changed;\n            GUI.changed = false;\n            position = Handles.Slider(position, d, size * 0.03f, Handles.DotHandleCap, 0f);\n            if (GUI.changed)\n                r = Vector3.Dot(position - p, d);\n            GUI.changed |= temp;\n            return r;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/Disc.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    internal class Disc\n    {\n        const int k_MaxSnapMarkers = 360 / 5;\n        const float k_RotationUnitSnapMajorMarkerStep = 45;\n        const float k_RotationUnitSnapMarkerSize = 0.1f;\n        const float k_RotationUnitSnapMajorMarkerSize = 0.2f;\n        const float k_GrabZoneScale = 0.3f;\n\n        static Vector2 s_StartMousePosition, s_CurrentMousePosition;\n        static Vector3 s_StartPosition, s_StartAxis;\n        static Quaternion s_StartRotation;\n        static float s_RotationDist;\n\n        public static Quaternion Do(int id, Quaternion rotation, Vector3 position, Vector3 axis, float size, bool cutoffPlane, float snap)\n        {\n            return Do(id, rotation, position, axis, size, cutoffPlane, snap, true, true, Handles.secondaryColor);\n        }\n\n        public static Quaternion Do(int id, Quaternion rotation, Vector3 position, Vector3 axis, float size, bool cutoffPlane, float snap, bool enableRayDrag, bool showHotArc, Color fillColor)\n        {\n            var cam = Handles.inverseMatrix.MultiplyVector(Camera.current != null ? Camera.current.transform.forward : Vector3.forward);\n\n            if (Mathf.Abs(Vector3.Dot(cam, axis)) > .999f)\n                cutoffPlane = false;\n\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                {\n                    float d;\n                    if (cutoffPlane)\n                    {\n                        Vector3 from = Vector3.Cross(axis, cam).normalized;\n                        d = HandleUtility.DistanceToArc(position, axis, from, 180, size) * k_GrabZoneScale;\n                    }\n                    else\n                    {\n                        d = HandleUtility.DistanceToDisc(position, axis, size) * k_GrabZoneScale;\n                    }\n\n                    HandleUtility.AddControl(id, d);\n                    break;\n                }\n                case EventType.MouseDown:\n                    // am I closest to the thingy?\n                    if (HandleUtility.nearestControl == id && evt.button == 0 && !evt.alt)\n                    {\n                        GUIUtility.hotControl = id;    // Grab mouse focus\n                        Tools.LockHandlePosition();\n                        if (cutoffPlane)\n                        {\n                            Vector3 from = Vector3.Cross(axis, cam).normalized;\n                            s_StartPosition = HandleUtility.ClosestPointToArc(position, axis, from, 180, size);\n                        }\n                        else\n                        {\n                            s_StartPosition = HandleUtility.ClosestPointToDisc(position, axis, size);\n                        }\n                        s_RotationDist = 0;\n                        s_StartRotation = rotation;\n                        s_StartAxis = axis;\n                        s_CurrentMousePosition = s_StartMousePosition = Event.current.mousePosition;\n                        evt.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(1);\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        // handle look to point rotation\n                        bool rayDrag = EditorGUI.actionKey && evt.shift && enableRayDrag;\n                        if (rayDrag)\n                        {\n                            if (HandleUtility.ignoreRaySnapObjects == null)\n                                Handles.SetupIgnoreRaySnapObjects();\n                            object hit = HandleUtility.RaySnap(HandleUtility.GUIPointToWorldRay(evt.mousePosition));\n                            if (hit != null && Vector3.Dot(axis.normalized, rotation * Vector3.forward) < 0.999)\n                            {\n                                RaycastHit rh = (RaycastHit)hit;\n                                Vector3 lookPoint = rh.point - position;\n                                Vector3 lookPointProjected = lookPoint - Vector3.Dot(lookPoint, axis.normalized) * axis.normalized;\n                                rotation = Quaternion.LookRotation(lookPointProjected, rotation * Vector3.up);\n                            }\n                        }\n                        else\n                        {\n                            Vector3 direction = Vector3.Cross(axis, position - s_StartPosition).normalized;\n                            s_CurrentMousePosition += evt.delta;\n                            s_RotationDist = HandleUtility.CalcLineTranslation(s_StartMousePosition, s_CurrentMousePosition, s_StartPosition, direction) / size * 30;\n                            // Not using Handles.SnapValue because that checks incrementalSnapEnabled. For rotation we\n                            // don't make any distinction between world snap and incremental. In cases where the tool\n                            // supports grid snapping for translation or scale _and_ rotation, we need to explicitly\n                            // ignore the gridSnapActive check that is implicit in incrementSnapEnabled.\n                            if(EditorSnapSettings.snapEnabled)\n                                s_RotationDist =  Snapping.Snap(s_RotationDist, snap);\n                            rotation = Quaternion.AngleAxis(s_RotationDist * -1, s_StartAxis) * s_StartRotation;\n                        }\n\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))\n                    {\n                        Tools.UnlockHandlePosition();\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(0);\n                    }\n                    break;\n\n                case EventType.KeyDown:\n                    if (evt.keyCode == KeyCode.Escape && GUIUtility.hotControl == id)\n                    {\n                        // We do not use the event nor clear hotcontrol to ensure auto revert value kicks in from native side\n                        Tools.UnlockHandlePosition();\n                        EditorGUIUtility.SetWantsMouseJumping(0);\n                    }\n                    break;\n\n                case EventType.Repaint:\n                    Handles.SetupHandleColor(id, evt, out var prevColor, out var thickness);\n\n                    // If we're dragging it, we'll go a bit further and draw a selection pie\n                    if (GUIUtility.hotControl == id)\n                    {\n                        Color t = Handles.color;\n                        Vector3 from = (s_StartPosition - position).normalized;\n                        Handles.color = fillColor;\n                        Handles.DrawLine(position, position + from * size);\n                        var d = -Mathf.Sign(s_RotationDist) * Mathf.Repeat(Mathf.Abs(s_RotationDist), 360);\n                        Vector3 to = Quaternion.AngleAxis(d, axis) * from;\n                        Handles.DrawLine(position, position + to * size);\n\n                        Handles.color = fillColor * new Color(1, 1, 1, .2f);\n                        for (int i = 0, revolutions = (int)Mathf.Abs(s_RotationDist * 0.002777777778f); i < revolutions; ++i)\n                            Handles.DrawSolidDisc(position, axis, size);\n                        Handles.DrawSolidArc(position, axis, from, d, size);\n\n                        // Draw snap markers\n                        if (EditorSnapSettings.snapEnabled && snap > 0)\n                        {\n                            DrawRotationUnitSnapMarkers(position, axis, size, k_RotationUnitSnapMarkerSize, snap, @from);\n                            DrawRotationUnitSnapMarkers(position, axis, size, k_RotationUnitSnapMajorMarkerSize, k_RotationUnitSnapMajorMarkerStep, @from);\n                        }\n                        Handles.color = t;\n                    }\n\n                    if (showHotArc && GUIUtility.hotControl == id || GUIUtility.hotControl != id && !cutoffPlane)\n                        Handles.DrawWireDisc(position, axis, size, thickness);\n                    else if (GUIUtility.hotControl != id && cutoffPlane)\n                    {\n                        Vector3 from = Vector3.Cross(axis, cam).normalized;\n                        Handles.DrawWireArc(position, axis, from, 180, size, thickness);\n                    }\n\n                    Handles.color = prevColor;\n                    break;\n            }\n\n            return rotation;\n        }\n\n        static void DrawRotationUnitSnapMarkers(Vector3 position, Vector3 axis, float handleSize, float markerSize, float snap, Vector3 @from)\n        {\n            var iterationCount = Mathf.FloorToInt(360 / snap);\n            var performFading = iterationCount > k_MaxSnapMarkers;\n            var limitedIterationCount = Mathf.Min(iterationCount, k_MaxSnapMarkers);\n\n            // center the markers around the current angle\n            var count = Mathf.RoundToInt(limitedIterationCount * 0.5f);\n\n            for (var i = -count; i < count; ++i)\n            {\n                var rot = Quaternion.AngleAxis(i * snap, axis);\n                var u = rot * @from;\n                var startPoint = position + (1 - markerSize) * handleSize * u;\n                var endPoint = position + 1 * handleSize * u;\n                Handles.color = Handles.selectedColor;\n                if (performFading)\n                {\n                    var alpha = 1 - Mathf.SmoothStep(0, 1, Mathf.Abs(i / ((float)limitedIterationCount - 1) - 0.5f) * 2);\n                    Handles.color = new Color(Handles.color.r, Handles.color.g, Handles.color.b, alpha);\n                }\n                Handles.DrawLine(startPoint, endPoint);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/FreeMove.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEditor.Snap;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    internal class FreeMove\n    {\n        private static Vector2 s_StartMousePosition, s_CurrentMousePosition, s_CurrentMousePositionScreen;\n        private static Vector3 s_StartPosition;\n\n        [Obsolete(\"Rotation parameter is obsolete.\")]\n        public static Vector3 Do(int id, Vector3 position, Quaternion rotation, float size, Vector3 snap, Handles.CapFunction handleFunction)\n        {\n            return Do(id, position, size, snap, handleFunction);\n        }\n\n        public static Vector3 Do(int id, Vector3 position, float size, Vector3 snap, Handles.CapFunction handleFunction)\n        {\n            Vector3 worldPosition = Handles.matrix.MultiplyPoint(position);\n            Matrix4x4 origMatrix = Handles.matrix;\n\n            VertexSnapping.HandleMouseMove(id);\n\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseMove:\n                case EventType.Layout:\n                    // We only want the position to be affected by the Handles.matrix.\n                    Handles.matrix = Matrix4x4.identity;\n                    handleFunction(id, worldPosition, Camera.current.transform.rotation, size, EventType.Layout);\n                    Handles.matrix = origMatrix;\n                    break;\n\n                case EventType.MouseDown:\n                    // am I closest to the thingy?\n                    if (HandleUtility.nearestControl == id && evt.button == 0)\n                    {\n                        GUIUtility.hotControl = id;     // Grab mouse focus\n                        s_CurrentMousePosition = s_CurrentMousePositionScreen = s_StartMousePosition = evt.mousePosition;\n                        s_StartPosition = position;\n                        HandleUtility.ignoreRaySnapObjects = null;\n                        evt.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(1);\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        bool rayDrag = EditorGUI.actionKey && evt.shift;\n                        if (rayDrag)\n                        {\n                            if (HandleUtility.ignoreRaySnapObjects == null)\n                                Handles.SetupIgnoreRaySnapObjects();\n\n                            if (HandleUtility.PlaceObject(evt.mousePosition, out Vector3 point, out Vector3 normal))\n                            {\n                                float offset = 0;\n                                if (Tools.pivotMode == PivotMode.Center && !Tools.vertexDragging)\n                                {\n                                    float geomOffset = HandleUtility.CalcRayPlaceOffset(HandleUtility.ignoreRaySnapObjects, normal);\n                                    if (geomOffset != Mathf.Infinity)\n                                    {\n                                        offset = Vector3.Dot(position, normal) - geomOffset;\n                                    }\n                                }\n                                position = Handles.inverseMatrix.MultiplyPoint(point + (normal * offset));\n                            }\n                            else\n                            {\n                                rayDrag = false;\n                            }\n                        }\n\n                        if (!rayDrag)\n                        {\n                            // normal drag\n                            Vector2 mouseDelta = evt.mousePosition - s_CurrentMousePositionScreen;\n                            s_CurrentMousePositionScreen += mouseDelta;\n                            s_CurrentMousePosition += new Vector2(mouseDelta.x, -mouseDelta.y) * EditorGUIUtility.pixelsPerPoint;\n                            Vector3 screenPos = Camera.current.WorldToScreenPoint(Handles.matrix.MultiplyPoint(s_StartPosition));\n                            screenPos += (Vector3)(s_CurrentMousePosition - s_StartMousePosition);\n                            position = Handles.inverseMatrix.MultiplyPoint(Camera.current.ScreenToWorldPoint(screenPos));\n\n                            if (Tools.vertexDragging)\n                            {\n                                if (HandleUtility.ignoreRaySnapObjects == null)\n                                    Handles.SetupIgnoreRaySnapObjects();\n                                Vector3 near;\n                                if (HandleUtility.FindNearestVertex(evt.mousePosition, null, out near))\n                                {\n                                    position = Handles.inverseMatrix.MultiplyPoint(near);\n                                }\n                            }\n                            else\n                            if (EditorSnapSettings.incrementalSnapActive && !evt.shift)\n                            {\n                                Vector3 delta = position - s_StartPosition;\n                                delta = Handles.SnapValue(delta, snap);\n                                position = s_StartPosition + delta;\n                            }\n                        }\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))\n                    {\n                        GUIUtility.hotControl = 0;\n                        HandleUtility.ignoreRaySnapObjects = null;\n                        evt.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(0);\n                    }\n                    break;\n\n                case EventType.Repaint:\n                    Handles.SetupHandleColor(id, evt, out var prevColor, out var thickness);\n                    // We only want the position to be affected by the Handles.matrix.\n                    Handles.matrix = Matrix4x4.identity;\n                    handleFunction(id, worldPosition, Camera.current.transform.rotation, size, EventType.Repaint);\n                    Handles.matrix = origMatrix;\n                    Handles.color = prevColor;\n                    break;\n            }\n            return position;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/FreeRotate.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    internal class FreeRotate\n    {\n        static readonly Color s_DimmingColor = new Color(0f, 0f, 0f, 0.078f);\n        private static Vector2 s_CurrentMousePosition;\n\n        public static Quaternion Do(int id, Quaternion rotation, Vector3 position, float size)\n        {\n            return Do(id, rotation, position, size, true);\n        }\n\n        internal static Quaternion Do(int id, Quaternion rotation, Vector3 position, float size, bool drawCircle)\n        {\n            Vector3 worldPosition = Handles.matrix.MultiplyPoint(position);\n            Matrix4x4 origMatrix = Handles.matrix;\n\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    // We only want the position to be affected by the Handles.matrix.\n                    Handles.matrix = Matrix4x4.identity;\n                    HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(worldPosition, size) + HandleUtility.kPickDistance);\n                    Handles.matrix = origMatrix;\n                    break;\n                case EventType.MouseDown:\n                    // am I closest to the thingy?\n                    if (HandleUtility.nearestControl == id && evt.button == 0 && !evt.alt)\n                    {\n                        GUIUtility.hotControl = id; // Grab mouse focus\n                        Tools.LockHandlePosition();\n                        s_CurrentMousePosition = evt.mousePosition;\n                        HandleUtility.ignoreRaySnapObjects = null;\n                        evt.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(1);\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        // rayDrag rotates object to look at ray hit\n                        bool rayDrag = EditorGUI.actionKey && evt.shift;\n                        if (rayDrag)\n                        {\n                            if (HandleUtility.ignoreRaySnapObjects == null)\n                                Handles.SetupIgnoreRaySnapObjects();\n\n                            object hit = HandleUtility.RaySnap(HandleUtility.GUIPointToWorldRay(evt.mousePosition));\n                            if (hit != null)\n                            {\n                                RaycastHit rh = (RaycastHit)hit;\n                                Quaternion newRotation = Quaternion.LookRotation(rh.point - position);\n                                if (Tools.pivotRotation == PivotRotation.Global)\n                                {\n                                    Transform t = Selection.activeTransform;\n                                    if (t)\n                                    {\n                                        Quaternion delta = Quaternion.Inverse(t.rotation) * rotation;\n                                        newRotation = newRotation * delta;\n                                    }\n                                }\n                                rotation = newRotation;\n                            }\n                        }\n                        else\n                        {\n                            s_CurrentMousePosition += evt.delta;\n                            Vector3 rotDir = Camera.current.transform.TransformDirection(new Vector3(-evt.delta.y, -evt.delta.x, 0));\n                            rotation = Quaternion.AngleAxis(evt.delta.magnitude, rotDir.normalized) * rotation;\n                        }\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))\n                    {\n                        Tools.UnlockHandlePosition();\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(0);\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (evt.keyCode == KeyCode.Escape && GUIUtility.hotControl == id)\n                    {\n                        // We do not use the event nor clear hotcontrol to ensure auto revert value kicks in from native side\n                        Tools.UnlockHandlePosition();\n                        EditorGUIUtility.SetWantsMouseJumping(0);\n                    }\n                    break;\n                case EventType.Repaint:\n                    Handles.SetupHandleColor(id, evt, out var prevColor, out var thickness);\n                    var isHot = id == GUIUtility.hotControl;\n                    var isHover = Handles.IsHovering(id, evt);\n\n                    // We only want the position to be affected by the Handles.matrix.\n                    Handles.matrix = Matrix4x4.identity;\n                    if (drawCircle)\n                        Handles.DrawWireDisc(worldPosition, Camera.current.transform.forward, size, thickness);\n                    if (isHover || isHot)\n                    {\n                        Handles.color = s_DimmingColor;\n                        Handles.DrawSolidDisc(worldPosition, Camera.current.transform.forward, size);\n                    }\n                    Handles.matrix = origMatrix;\n                    Handles.color = prevColor;\n                    break;\n            }\n            return rotation;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/HandleUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Mono/Handles/HandleUtility.bindings.h\")]\n    [StaticAccessor(\"HandleUtilityBindings\", StaticAccessorType.DoubleColon)]\n    public sealed partial class HandleUtility\n    {\n        // Calculate distance between a point and a bezier\n        public static extern float DistancePointBezier(Vector3 point, Vector3 startPosition, Vector3 endPosition, Vector3 startTangent, Vector3 endTangent);\n\n        internal static extern GameObject[] Internal_PickRectObjects(Camera cam, Rect rect, bool selectPrefabRoots, bool drawGizmos);\n\n        internal static extern GameObject Internal_FindNearestVertex(Camera cam, Vector2 screenPoint, Transform[] objectsToSearch, Transform[] ignoreObjects, out Vector3 vertex, out bool found);\n\n        internal static extern uint Internal_GetClosestPickingID(\n            Camera cam,\n            int layers,\n            Vector2 position,\n            PickingObject[] ignore,\n            PickingObject[] filter,\n            bool drawGizmos,\n            ref int materialIndex,\n            ref bool isEntity);\n\n        private static extern void Internal_SetHandleWireTextureIndex(int textureIndex, int samplerIndex);\n\n        internal static extern float CalcRayPlaceOffset(Transform[] objects, Vector3 normal);\n\n        private static extern void Internal_Repaint();\n\n        // Register a callback for GfxDevice cleanup event. It checks if the callback wasn't already registered in native code.\n        private static extern void RegisterGfxDeviceCleanupIfNeeded();\n\n        // Test a mesh for intersection against a ray\n        internal static extern bool IntersectRayMesh(Ray ray, Mesh mesh, Matrix4x4 matrix, out RaycastHit hit);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/HandleUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing Unity.Profiling;\nusing UnityEngine;\nusing UnityEngine.Internal;\nusing UnityEngine.Rendering;\nusing UnityEngine.Scripting;\nusing UnityEditor.SceneManagement;\nusing UnityObject = UnityEngine.Object;\nusing System.Linq;\nusing Unity.Collections;\nusing Unity.Collections.LowLevel.Unsafe;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    public enum RenderPickingType\n    {\n        RenderFromIgnoreSet,\n        RenderFromFilterSet\n    }\n\n    public readonly struct RenderPickingArgs\n    {\n        public int pickingIndex { get; }\n        public RenderPickingType renderPickingType { get; }\n        public IReadOnlyCollection<GameObject> renderObjectSet { get; }\n\n        internal RenderPickingArgs(int pickingIndex, RenderPickingType renderPickingType, HashSet<GameObject> renderObjectSet)\n        {\n            this.pickingIndex = pickingIndex;\n            this.renderPickingType = renderPickingType;\n            this.renderObjectSet = renderObjectSet;\n        }\n\n        public bool RenderObjectSetContains(GameObject go)\n            => renderObjectSet != null && ((HashSet<GameObject>)renderObjectSet).Contains(go);\n\n        public bool NeedToRenderForPicking(GameObject go)\n        {\n            var contained = RenderObjectSetContains(go);\n            return renderPickingType == RenderPickingType.RenderFromFilterSet ? contained : !contained;\n       }\n    }\n\n    public readonly struct RenderPickingResult\n    {\n        public int renderedPickingIndexCount { get; }\n        public HandleUtility.ResolvePickingCallback resolver { get; }\n        public HandleUtility.ResolvePickingWithWorldPositionCallback resolverWithWorldPos { get; }\n\n        public static readonly RenderPickingResult NoOperation = default;\n\n        public RenderPickingResult(int renderedPickingIndexCount, HandleUtility.ResolvePickingCallback resolver)\n        {\n            if (renderedPickingIndexCount < 0)\n                throw new ArgumentOutOfRangeException(nameof(renderedPickingIndexCount), $\"The value ({renderedPickingIndexCount}) must not be negative\");\n            if (resolver == null)\n                throw new ArgumentNullException(nameof(resolver));\n\n            this.renderedPickingIndexCount = renderedPickingIndexCount;\n            this.resolver = resolver;\n            this.resolverWithWorldPos = null;\n        }\n\n        public RenderPickingResult(int renderedPickingIndexCount, HandleUtility.ResolvePickingWithWorldPositionCallback resolver)\n        {\n            if (renderedPickingIndexCount < 0)\n                throw new ArgumentOutOfRangeException(nameof(renderedPickingIndexCount), $\"The value ({renderedPickingIndexCount}) must not be negative\");\n            if (resolver == null)\n                throw new ArgumentNullException(nameof(resolver));\n\n            this.renderedPickingIndexCount = renderedPickingIndexCount;\n            this.resolverWithWorldPos = resolver;\n            this.resolver = null;\n        }\n    }\n\n    // Helper functions for Scene View style 3D GUI\n    public sealed partial class HandleUtility\n    {\n        // Helper function for doing arrows.\n        public static float CalcLineTranslation(Vector2 src, Vector2 dest, Vector3 srcPosition, Vector3 constraintDir)\n        {\n            // Apply handle matrix\n            srcPosition = Handles.matrix.MultiplyPoint(srcPosition);\n            constraintDir = Handles.matrix.MultiplyVector(constraintDir);\n\n\n            // The constrained direction is facing towards the camera, THATS BAD when the handle is close to the camera\n            // The srcPosition  goes through to the other side of the camera\n            float invert = 1.0F;\n            Vector3 cameraForward = Camera.current == null ? Vector3.forward : Camera.current.transform.forward;\n            if (Vector3.Dot(constraintDir, cameraForward) < 0.0F)\n                invert = -1.0F;\n\n            // Ok - Get the parametrization of the line\n            // p1 = src position, p2 = p1 + ConstraintDir.\n            // we then parametrise the perpendicular position of dest into the line (p1-p2)\n            Vector3 cd = constraintDir;\n            cd.y = -cd.y;\n            Camera cam = Camera.current;\n            // if camera is null, then we are drawing in OnGUI, where y-coordinate goes top-to-bottom\n            Vector2 p1 = cam == null\n                ? Vector2.Scale(srcPosition, new Vector2(1f, -1f))\n                : EditorGUIUtility.PixelsToPoints(cam.WorldToScreenPoint(srcPosition));\n            Vector2 p2 = cam == null\n                ? Vector2.Scale(srcPosition + constraintDir * invert, new Vector2(1f, -1f))\n                : EditorGUIUtility.PixelsToPoints(cam.WorldToScreenPoint(srcPosition + constraintDir * invert));\n            Vector2 p3 = dest;\n            Vector2 p4 = src;\n\n            if (p1 == p2)\n                return 0;\n\n            p3.y = -p3.y;\n            p4.y = -p4.y;\n            float t0 = GetParametrization(p4, p1, p2);\n            float t1 = GetParametrization(p3, p1, p2);\n\n            float output = (t1 - t0) * invert;\n            return output;\n        }\n\n        internal static float GetParametrization(Vector2 x0, Vector2 x1, Vector2 x2)\n        {\n            return -(Vector2.Dot(x1 - x0, x2 - x1) / (x2 - x1).sqrMagnitude);\n        }\n\n        // This limits the \"shoot off into infinity\" factor when the cursor ray and constraint are near parallel.\n        // Increase this value to more conservatively restrict movement, lower to allow more extreme values.\n        // Ex, with a camera roughly 30 degrees to the handle a value of .1 restricts translation to ~1500m, whereas a\n        // value of .01 will allow closer to 50000 units of movement.\n        const float k_MinRayConstraintDot = .05f;\n\n        // constraintOrigin and constraintDir are expected to be in Handle space (ie, origin and direction are\n        // pre-multiplied by the Handles.matrix)\n        internal static bool CalcPositionOnConstraint(Camera camera, Vector2 guiPosition, Vector3 constraintOrigin, Vector3 constraintDir, out Vector3 position)\n        {\n            if (CalcParamOnConstraint(camera, guiPosition, constraintOrigin, constraintDir, out float pointOnLineParam))\n            {\n                position = constraintOrigin + constraintDir * pointOnLineParam;\n                return true;\n            }\n\n            position = Vector3.zero;\n            return false;\n        }\n\n        internal static bool CalcParamOnConstraint(Camera camera, Vector2 guiPosition, Vector3 constraintOrigin, Vector3 constraintDir, out float parameterization)\n        {\n            Vector3 constraintToCameraTangent = Vector3.Cross(constraintDir, camera.transform.position - constraintOrigin);\n            Vector3 constraintPlaneNormal = Vector3.Cross(constraintDir, constraintToCameraTangent);\n            Plane plane = new Plane(constraintPlaneNormal, constraintOrigin);\n            var ray = GUIPointToWorldRay(guiPosition);\n\n            if (Vector3.Dot(ray.direction, plane.normal) > k_MinRayConstraintDot && plane.Raycast(ray, out float distance))\n            {\n                var pointOnPlane = ray.GetPoint(distance);\n                parameterization = PointOnLineParameter(pointOnPlane, constraintOrigin, constraintDir);\n                return !float.IsInfinity(parameterization);\n            }\n\n            parameterization = 0f;\n            return false;\n        }\n\n        // Returns the parameter for the projection of the /point/ on the given line\n        public static float PointOnLineParameter(Vector3 point, Vector3 linePoint, Vector3 lineDirection)\n        {\n            return (Vector3.Dot(lineDirection, (point - linePoint))) / lineDirection.sqrMagnitude;\n        }\n\n        // Project /point/ onto a line.\n        public static Vector3 ProjectPointLine(Vector3 point, Vector3 lineStart, Vector3 lineEnd)\n        {\n            Vector3 relativePoint = point - lineStart;\n            Vector3 lineDirection = lineEnd - lineStart;\n            float length = lineDirection.magnitude;\n            Vector3 normalizedLineDirection = lineDirection;\n            if (length > .000001f)\n                normalizedLineDirection /= length;\n\n            float dot = Vector3.Dot(normalizedLineDirection, relativePoint);\n            dot = Mathf.Clamp(dot, 0.0F, length);\n\n            return lineStart + normalizedLineDirection * dot;\n        }\n\n        // Calculate distance between a point and a line.\n        public static float DistancePointLine(Vector3 point, Vector3 lineStart, Vector3 lineEnd)\n        {\n            return Vector3.Magnitude(ProjectPointLine(point, lineStart, lineEnd) - point);\n        }\n\n        // Get standard acceleration for dragging values (RO).\n        public static float acceleration { get { return NumericFieldDraggerUtility.Acceleration(Event.current.shift, Event.current.alt); } }\n\n        // Get nice mouse delta to use for dragging a float value (RO).\n        public static float niceMouseDelta { get { return NumericFieldDraggerUtility.NiceDelta(Event.current.delta, acceleration); } }\n\n        // Get nice mouse delta to use for zooming (RO).\n        public static float niceMouseDeltaZoom\n        {\n            get\n            {\n                Vector2 d = -Event.current.delta;\n\n                // Decide which direction the mouse delta goes.\n                // Problem is that when the user zooms horizontal and vertical, it can jitter back and forth.\n                // So we only update from which axis we pick the sign if x and y\n                // movement is not very close to each other\n                if (Mathf.Abs(Mathf.Abs(d.x) - Mathf.Abs(d.y)) / Mathf.Max(Mathf.Abs(d.x), Mathf.Abs(d.y)) > .1f)\n                {\n                    if (Mathf.Abs(d.x) > Mathf.Abs(d.y))\n                        s_UseYSignZoom = false;\n                    else\n                        s_UseYSignZoom = true;\n                }\n\n                if (s_UseYSignZoom)\n                    return Mathf.Sign(d.y) * d.magnitude * acceleration;\n                return Mathf.Sign(d.x) * d.magnitude * acceleration;\n            }\n        }\n        static bool s_UseYSignZoom;\n\n        // Pixel distance from mouse pointer to line.\n        public static float DistanceToLine(Vector3 p1, Vector3 p2)\n        {\n            p1 = WorldToGUIPoint(p1);\n            p2 = WorldToGUIPoint(p2);\n\n            Vector2 point = Event.current.mousePosition;\n\n            return DistanceToLineInternal(point, p1, p2);\n        }\n\n        internal static float DistanceToLineInternal(Vector3 point, Vector3 p1, Vector3 p2)\n        {\n            float retval = DistancePointLine(point, p1, p2);\n            if (retval < 0)\n                retval = 0.0f;\n            return retval;\n        }\n\n        // Pixel distance from mouse pointer to camera facing circle.\n        public static float DistanceToCircle(Vector3 position, float radius)\n        {\n            Vector2 screenCenter = WorldToGUIPoint(position);\n            Camera cam = Camera.current;\n            if (cam)\n            {\n                var screenEdge = WorldToGUIPoint(position + cam.transform.right * radius);\n                radius = (screenCenter - screenEdge).magnitude;\n            }\n            float dist = (screenCenter - Event.current.mousePosition).magnitude;\n            if (dist < radius)\n                return 0;\n            return dist - radius;\n        }\n\n        // Pixel distance from mouse pointer to camera facing circle.\n        public static float DistanceToCircle(CameraProjectionCache projection, Vector3 position, float radius)\n        {\n            Vector2 screenCenter = projection.WorldToGUIPoint(position);\n            Camera cam = Camera.current;\n            if (cam)\n            {\n                var screenEdge = projection.WorldToGUIPoint(position + cam.transform.right * radius);\n                radius = (screenCenter - screenEdge).magnitude;\n            }\n            float dist = (screenCenter - Event.current.mousePosition).magnitude;\n            if (dist < radius)\n                return 0;\n            return dist - radius;\n        }\n\n        // Pixel distance from mouse pointer to cone projection on screen\n        static ProfilerMarker s_DistanceToConeMarker = new ProfilerMarker(\"Handles.DistanceToCone\");\n        static readonly Vector3[] s_DistanceToConePoints = new Vector3[7];\n        public static float DistanceToCone(Vector3 position, Quaternion rotation, float size)\n        {\n            using (s_DistanceToConeMarker.Auto())\n            {\n                // our handles cone mesh is along Z axis:\n                // base at Z=-0.5 with radius 0.4, and apex at Z=0.7\n                var baseZ = -0.5f * size;\n                var apexZ = 0.7f * size;\n                var baseR = 0.4f * size;\n\n                // approximate the cone with a six-sided base\n                var baseR60x = baseR * 0.5f; // cos 60\n                var baseR60y = baseR * 0.866f; // sin 60\n                var mat = Matrix4x4.TRS(position, rotation, Vector3.one);\n                s_DistanceToConePoints[0] = mat.MultiplyPoint(new Vector3(0, 0, apexZ));\n                s_DistanceToConePoints[1] = mat.MultiplyPoint(new Vector3(+baseR, 0, baseZ));\n                s_DistanceToConePoints[2] = mat.MultiplyPoint(new Vector3(-baseR, 0, baseZ));\n                s_DistanceToConePoints[3] = mat.MultiplyPoint(new Vector3(+baseR60x, +baseR60y, baseZ));\n                s_DistanceToConePoints[4] = mat.MultiplyPoint(new Vector3(-baseR60x, +baseR60y, baseZ));\n                s_DistanceToConePoints[5] = mat.MultiplyPoint(new Vector3(+baseR60x, -baseR60y, baseZ));\n                s_DistanceToConePoints[6] = mat.MultiplyPoint(new Vector3(-baseR60x, -baseR60y, baseZ));\n\n                return DistanceToPointCloudConvexHull(s_DistanceToConePoints);\n            }\n        }\n\n        // Pixel distance from mouse pointer to cube projection on screen\n        static ProfilerMarker s_DistanceToCubeMarker = new ProfilerMarker(\"Handles.DistanceToCube\");\n        static readonly Vector3[] s_DistanceToCubePoints = new Vector3[8];\n        public static float DistanceToCube(Vector3 position, Quaternion rotation, float size)\n        {\n            using (s_DistanceToCubeMarker.Auto())\n            {\n                var s = size * 0.5f;\n                var mat = Matrix4x4.TRS(position, rotation, Vector3.one);\n                s_DistanceToCubePoints[0] = mat.MultiplyPoint(new Vector3(+s, +s, +s));\n                s_DistanceToCubePoints[1] = mat.MultiplyPoint(new Vector3(-s, +s, +s));\n                s_DistanceToCubePoints[2] = mat.MultiplyPoint(new Vector3(+s, -s, +s));\n                s_DistanceToCubePoints[3] = mat.MultiplyPoint(new Vector3(-s, -s, +s));\n                s_DistanceToCubePoints[4] = mat.MultiplyPoint(new Vector3(+s, +s, -s));\n                s_DistanceToCubePoints[5] = mat.MultiplyPoint(new Vector3(-s, +s, -s));\n                s_DistanceToCubePoints[6] = mat.MultiplyPoint(new Vector3(+s, -s, -s));\n                s_DistanceToCubePoints[7] = mat.MultiplyPoint(new Vector3(-s, -s, -s));\n                return DistanceToPointCloudConvexHull(s_DistanceToCubePoints);\n            }\n        }\n\n        // Pixel distance from mouse pointer to a rectangle on screen\n        static Vector3[] s_Points = { Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero };\n        public static float DistanceToRectangle(Vector3 position, Quaternion rotation, float size)\n        {\n            return DistanceToRectangleInternal(position, rotation, new Vector2(size, size));\n        }\n\n        // Pixel distance from mouse pointer to a rectangle on screen.\n        // The method is stable in pixel space but fails when one or more corners of the rectangle is behind the camera.\n        internal static float DistanceToRectangleInternal(Vector3 position, Quaternion rotation, Vector2 size)\n        {\n            Vector3 sideways = rotation * new Vector3(size.x, 0, 0);\n            Vector3 up = rotation * new Vector3(0, size.y, 0);\n            s_Points[0] = WorldToGUIPoint(position + sideways + up);\n            s_Points[1] = WorldToGUIPoint(position + sideways - up);\n            s_Points[2] = WorldToGUIPoint(position - sideways - up);\n            s_Points[3] = WorldToGUIPoint(position - sideways + up);\n            s_Points[4] = s_Points[0];\n\n            Vector2 pos = Event.current.mousePosition;\n            bool oddNodes = false;\n            int j = 4;\n            for (int i = 0; i < 5; i++)\n            {\n                if ((s_Points[i].y > pos.y) != (s_Points[j].y > pos.y))\n                {\n                    if (pos.x < (s_Points[j].x - s_Points[i].x) * (pos.y - s_Points[i].y) / (s_Points[j].y - s_Points[i].y) + s_Points[i].x)\n                    {\n                        oddNodes = !oddNodes;\n                    }\n                }\n                j = i;\n            }\n            if (!oddNodes)\n            {\n                // Distance to closest edge (not so fast)\n                float closestDist = -1f;\n                j = 1;\n                for (int i = 0; i < 4; i++)\n                {\n                    var dist = DistancePointToLineSegment(pos, s_Points[i], s_Points[j++]);\n                    if (dist < closestDist || closestDist < 0)\n                        closestDist = dist;\n                }\n                return closestDist;\n            }\n            return 0;\n        }\n\n        // Pixel distance from mouse pointer to a rectangle on screen.\n        // Tests if mouse ray intersects the rectangle performed in world space first,\n        // then the distance between nearest point on the rectangle and mouse position calculated in pixel space.\n        // This method is more stable than DistanceToRectangleInternal for cases when one or more corners of the rectangle is behind the camera.\n        // But at the same time it is less stable than DistanceToRectangleInternal in pixel space when the rectangle plane is parallel to cameras forward direction.\n        internal static float DistanceToRectangleInternalWorldSpace(Vector3 position, Quaternion rotation, Vector2 size)\n        {\n            Quaternion invRotation = Quaternion.Inverse(rotation);\n\n            Ray ray = GUIPointToWorldRay(Event.current.mousePosition);\n            ray.origin = invRotation * (ray.origin - position);\n            ray.direction = invRotation * ray.direction;\n\n            Plane plane = new Plane(Vector3.forward, Vector3.zero);\n\n            float enter;\n            if (plane.Raycast(ray, out enter))\n            {\n                Vector3 hitPoint = ray.GetPoint(enter);\n\n                Vector3 d = new Vector3(\n                    Mathf.Max(Mathf.Abs(hitPoint.x) - size.x, 0.0f) * Mathf.Sign(hitPoint.x),\n                    Mathf.Max(Mathf.Abs(hitPoint.y) - size.y, 0.0f) * Mathf.Sign(hitPoint.y),\n                    0.0f);\n\n                Vector3 nearestPoint = hitPoint - d;\n\n                hitPoint = rotation * hitPoint + position;\n                nearestPoint = rotation * nearestPoint + position;\n\n                return Vector2.Distance(WorldToGUIPoint(hitPoint), WorldToGUIPoint(nearestPoint));\n            }\n\n            return float.PositiveInfinity;\n        }\n\n        internal static float DistanceToDiamond(Vector3 position, Quaternion rotation, float size)\n        {\n            return DistanceToDiamondInternal(position, rotation, size, Event.current.mousePosition);\n        }\n\n        internal static float DistanceToDiamondInternal(Vector3 position, Quaternion rotation, float size, Vector2 mousePosition)\n        {\n            Vector3 sideways = rotation * new Vector3(size, 0, 0);\n            Vector3 up = rotation * new Vector3(0, size, 0);\n            s_Points[0] = WorldToGUIPoint(position + sideways);\n            s_Points[1] = WorldToGUIPoint(position - up);\n            s_Points[2] = WorldToGUIPoint(position - sideways);\n            s_Points[3] = WorldToGUIPoint(position + up);\n            s_Points[4] = s_Points[0];\n\n            Vector2 pos = mousePosition;\n            bool oddNodes = false;\n            int j = 4;\n            for (int i = 0; i < 5; i++)\n            {\n                if ((s_Points[i].y > pos.y) != (s_Points[j].y > pos.y))\n                {\n                    if (pos.x < (s_Points[j].x - s_Points[i].x) * (pos.y - s_Points[i].y) / (s_Points[j].y - s_Points[i].y) + s_Points[i].x)\n                    {\n                        oddNodes = !oddNodes;\n                    }\n                }\n                j = i;\n            }\n            if (!oddNodes)\n            {\n                // Distance to closest edge (not so fast)\n                float dist, closestDist = -1f;\n                j = 1;\n                for (int i = 0; i < 4; i++)\n                {\n                    dist = DistancePointToLineSegment(pos, s_Points[i], s_Points[j++]);\n                    if (dist < closestDist || closestDist < 0)\n                        closestDist = dist;\n                }\n                return closestDist;\n            }\n            return 0;\n        }\n\n        // Distance from a point /p/ in 2d to a line defined by two s_Points /a/ and /b/\n        public static float DistancePointToLine(Vector2 p, Vector2 a, Vector2 b)\n        {\n            return Mathf.Abs((b.x - a.x) * (a.y - p.y) - (a.x - p.x) * (b.y - a.y)) / (b - a).magnitude;\n        }\n\n        // Distance from a point /p/ in 2d to a line segment defined by two s_Points /a/ and /b/\n        public static float DistancePointToLineSegment(Vector2 p, Vector2 a, Vector2 b)\n        {\n            float l2 = (b - a).sqrMagnitude;    // i.e. |b-a|^2 -  avoid a sqrt\n            if (l2 == 0.0)\n                return (p - a).magnitude;       // a == b case\n            float t = Vector2.Dot(p - a, b - a) / l2;\n            if (t < 0.0)\n                return (p - a).magnitude;       // Beyond the 'a' end of the segment\n            if (t > 1.0)\n                return (p - b).magnitude;         // Beyond the 'b' end of the segment\n            Vector2 projection = a + t * (b - a); // Projection falls on the segment\n            return (p - projection).magnitude;\n        }\n\n        // Pixel distance from mouse pointer to a 3D disc.\n        public static float DistanceToDisc(Vector3 center, Vector3 normal, float radius)\n        {\n            Vector3 tangent = Vector3.Cross(normal, Vector3.up);\n            if (tangent.sqrMagnitude < .001f)\n                tangent = Vector3.Cross(normal, Vector3.right);\n            return DistanceToArc(center, normal, tangent, 360, radius);\n        }\n\n        // Get the nearest 3D point.\n        public static Vector3 ClosestPointToDisc(Vector3 center, Vector3 normal, float radius)\n        {\n            Vector3 tangent = Vector3.Cross(normal, Vector3.up);\n            if (tangent.sqrMagnitude < .001f)\n                tangent = Vector3.Cross(normal, Vector3.right);\n            return ClosestPointToArc(center, normal, tangent, 360, radius);\n        }\n\n        static Vector3[] m_ArcPointsBuffer = new Vector3[60];\n\n        // Pixel distance from mouse pointer to a 3D section of a disc.\n        public static float DistanceToArc(Vector3 center, Vector3 normal, Vector3 from, float angle, float radius)\n        {\n            Handles.SetDiscSectionPoints(m_ArcPointsBuffer, center, normal, from, angle, radius);\n            return DistanceToPolyLine(m_ArcPointsBuffer, false, out _);\n        }\n\n        // Get the nearest 3D point.\n        public static Vector3 ClosestPointToArc(Vector3 center, Vector3 normal, Vector3 from, float angle, float radius)\n        {\n            Handles.SetDiscSectionPoints(m_ArcPointsBuffer, center, normal, from, angle, radius);\n            return ClosestPointToPolyLine(m_ArcPointsBuffer);\n        }\n\n        // Pixel distance from mouse pointer to a polyline.\n        public static float DistanceToPolyLine(params Vector3[] points)\n        {\n            Matrix4x4 handleMatrix = Handles.matrix;\n            CameraProjectionCache cam = new CameraProjectionCache(Camera.current);\n            Vector2 mouse = Event.current.mousePosition;\n\n            Vector2 p1 = cam.WorldToGUIPoint(handleMatrix.MultiplyPoint3x4(points[0]));\n            Vector2 p2 = cam.WorldToGUIPoint(handleMatrix.MultiplyPoint3x4(points[1]));\n            float dist = DistanceToLineInternal(mouse, p1, p2);\n\n            for (int i = 2; i < points.Length; i++)\n            {\n                p1 = p2;\n                p2 = cam.WorldToGUIPoint(handleMatrix.MultiplyPoint3x4(points[i]));\n                float d = DistanceToLineInternal(mouse, p1, p2);\n                if (d < dist)\n                    dist = d;\n            }\n\n            return dist;\n        }\n\n        // Pixel distance from mouse pointer to a polyline.\n        internal static float DistanceToPolyLine(Vector3[] points, bool loop, out int index)\n        {\n            Matrix4x4 handleMatrix = Handles.matrix;\n            CameraProjectionCache cam = new CameraProjectionCache(Camera.current);\n            Vector2 mouse = Event.current.mousePosition;\n\n            Vector2 p1 = cam.WorldToGUIPoint(handleMatrix.MultiplyPoint3x4(points[0]));\n            Vector2 p2 = cam.WorldToGUIPoint(handleMatrix.MultiplyPoint3x4(points[1]));\n            float dist = DistanceToLineInternal(mouse, p1, p2);\n            index = 0;\n\n            for (int i = 2, c = points.Length; i < (loop ? c + 1 : c); i++)\n            {\n                p1 = p2;\n                p2 = cam.WorldToGUIPoint(handleMatrix.MultiplyPoint3x4(points[i % c]));\n                float d = DistanceToLineInternal(mouse, p1, p2);\n                if (d < dist)\n                {\n                    index = i - 1;\n                    dist = d;\n                }\n            }\n\n            return dist;\n        }\n\n        // Get the nearest 3D point.\n        public static Vector3 ClosestPointToPolyLine(params Vector3[] vertices)\n        {\n            float dist = DistanceToLine(vertices[0], vertices[1]);\n            int nearest = 0;// Which segment we're closest to\n            for (int i = 2; i < vertices.Length; i++)\n            {\n                float d = DistanceToLine(vertices[i - 1], vertices[i]);\n                if (d < dist)\n                {\n                    dist = d;\n                    nearest = i - 1;\n                }\n            }\n\n            Vector3 lineStart = vertices[nearest];\n            Vector3 lineEnd = vertices[nearest + 1];\n\n            Vector2 relativePoint = Event.current.mousePosition - WorldToGUIPoint(lineStart);\n            Vector2 lineDirection = WorldToGUIPoint(lineEnd) - WorldToGUIPoint(lineStart);\n            float length = lineDirection.magnitude;\n            float dot = Vector3.Dot(lineDirection, relativePoint);\n            if (length > .000001f)\n                dot /= length * length;\n            dot = Mathf.Clamp01(dot);\n\n            return Vector3.Lerp(lineStart, lineEnd, dot);\n        }\n\n        static float CalcPointSide(Vector2 l0, Vector2 l1, Vector2 point)\n        {\n            return (l1.y - l0.y) * (point.x - l0.x) - (l1.x - l0.x) * (point.y - l0.y);\n        }\n\n        static float DistancePointToConvexHull(Vector2 p, List<Vector2> hull)\n        {\n            var distance = float.PositiveInfinity;\n            if (hull == null || hull.Count == 0)\n                return distance;\n\n            var inside = hull.Count > 1;\n            var sideSign = 0;\n            for (var i = 0; i < hull.Count; ++i)\n            {\n                // get the line segment\n                var j = i == 0 ? hull.Count - 1 : i - 1;\n                var pt1 = hull[i];\n                var pt2 = hull[j];\n\n                // for point to be inside the hull, \"side\"\n                // signs must be the same for all edges.\n                var thisSide = CalcPointSide(pt1, pt2, p);\n                var thisSideSign = thisSide >= 0 ? 1 : -1;\n                if (sideSign == 0)\n                    sideSign = thisSideSign;\n                else if (thisSideSign != sideSign)\n                    inside = false;\n\n                // get minimum distance to each segment\n                var thisDistance = DistancePointToLineSegment(p, pt1, pt2);\n                distance = Mathf.Min(distance, thisDistance);\n            }\n            if (inside)\n                distance = 0;\n            return distance;\n        }\n\n        static void RemoveInsidePoints(int countLimit, Vector2 pt, List<Vector2> hull)\n        {\n            while (hull.Count >= countLimit && CalcPointSide(hull[hull.Count - 2], hull[hull.Count - 1], pt) <= 0)\n                hull.RemoveAt(hull.Count - 1);\n        }\n\n        // Note: .z components of input points are ignored; result is a 2D hull on .xy\n        static void CalcConvexHull2D(Vector3[] points, List<Vector2> outHull)\n        {\n            outHull.Clear();\n            if (points == null || points.Length == 0)\n                return;\n            var needCapacity = points.Length + 1;\n            if (outHull.Capacity < needCapacity)\n                outHull.Capacity = needCapacity;\n            if (points.Length == 1)\n            {\n                outHull.Add(points[0]);\n                return;\n            }\n\n            // Andrew's monotone chain algorithm:\n            // First sort the input points\n            Array.Sort(points, (a, b) =>\n            {\n                var ca = a.x.CompareTo(b.x);\n                return ca != 0 ? ca : a.y.CompareTo(b.y);\n            });\n\n            // Build lower hull\n            for (int i = 0; i < points.Length; ++i)\n            {\n                Vector2 pt = points[i];\n                RemoveInsidePoints(2, pt, outHull);\n                outHull.Add(pt);\n            }\n\n            // Build upper hull\n            for (int i = points.Length - 2, j = outHull.Count + 1; i >= 0; --i)\n            {\n                Vector2 pt = points[i];\n                RemoveInsidePoints(j, pt, outHull);\n                outHull.Add(pt);\n            }\n\n            // Remove last point (it's the same as the first one)\n            outHull.RemoveAt(outHull.Count - 1);\n        }\n\n        // Note: modifies input points array\n        static void CalcPointCloudConvexHull(Vector3[] points, List<Vector2> outHull)\n        {\n            outHull.Clear();\n            if (points == null || points.Length == 0)\n                return;\n\n            // project point cloud into 2D GUI space\n            var handleMatrix = Handles.matrix;\n            var cam = new CameraProjectionCache(Camera.current);\n            for (var i = 0; i < points.Length; ++i)\n                points[i] = cam.WorldToGUIPoint(handleMatrix.MultiplyPoint3x4(points[i]));\n\n            // calculate 2D convex hull\n            CalcConvexHull2D(points, outHull);\n        }\n\n        // Note: input array contents are modified\n        static readonly List<Vector2> s_PointCloudConvexHull = new List<Vector2>();\n        static float DistanceToPointCloudConvexHull(params Vector3[] points)\n        {\n            if (points == null || points.Length == 0 || Camera.current == null)\n                return float.PositiveInfinity;\n\n            var mousePos = Event.current.mousePosition;\n            CalcPointCloudConvexHull(points, s_PointCloudConvexHull);\n            return DistancePointToConvexHull(mousePos, s_PointCloudConvexHull);\n        }\n\n        // Record a distance measurement from a handle.\n        public static void AddControl(int controlId, float distance)\n        {\n            if (distance < s_CustomPickDistance && distance > kPickDistance)\n                distance = kPickDistance;\n\n            if (distance <= s_NearestDistance)\n            {\n                s_NearestDistance = distance;\n                s_NearestControl = controlId;\n            }\n        }\n\n        // Add the ID for a default control. This will be picked if nothing else is\n        public static void AddDefaultControl(int controlId)\n        {\n            AddControl(controlId, kPickDistance);\n        }\n\n        static int s_PreviousNearestControl;\n        static int s_NearestControl;\n        static float s_NearestDistance;\n        static Camera s_PreviousCamera;\n        internal const float kPickDistance = 5.0f;\n        internal static float s_CustomPickDistance = kPickDistance;\n\n        public static int nearestControl { get { return s_NearestDistance <= kPickDistance ? s_NearestControl : 0; } set { s_NearestControl = value; } }\n\n        [RequiredByNativeCode]\n        internal static void BeginHandles()\n        {\n            Handles.Init();\n            switch (Event.current.type)\n            {\n                case EventType.Layout:\n                    s_NearestControl = 0;\n                    s_NearestDistance = kPickDistance;\n                    break;\n            }\n            Handles.lighting = true;\n            Handles.color = Color.white;\n            Handles.zTest = CompareFunction.Always;\n            s_CustomPickDistance = kPickDistance;\n\n            if (null != Camera.current)\n            {\n                s_PreviousCamera = Camera.current;\n            }\n\n            Handles.Internal_SetCurrentCamera(null);\n            EditorGUI.s_DelayedTextEditor.BeginGUI();\n        }\n\n        [RequiredByNativeCode]\n        internal static void EndHandles()\n        {\n            if (s_PreviousNearestControl != s_NearestControl\n                && s_NearestControl != 0\n                && Event.current.type != EventType.Layout)\n            {\n                s_PreviousNearestControl = s_NearestControl;\n                Repaint();\n            }\n\n            if (null != s_PreviousCamera)\n            {\n                Handles.Internal_SetCurrentCamera(s_PreviousCamera);\n                s_PreviousCamera = null;\n            }\n\n            // Give the delayed text editor a chance to notice that it lost focus.\n            EditorGUI.s_DelayedTextEditor.EndGUI(Event.current.type);\n        }\n\n        const float k_KHandleSize = 80.0f;\n\n        // Get world space size of a manipulator handle at given position.\n        public static float GetHandleSize(Vector3 position)\n        {\n            Camera cam = Camera.current;\n            position = Handles.matrix.MultiplyPoint(position);\n            if (cam)\n            {\n                Transform tr = cam.transform;\n                Vector3 camPos = tr.position;\n                float distance = Vector3.Dot(position - camPos, tr.TransformDirection(new Vector3(0, 0, 1)));\n                Vector3 screenPos = cam.WorldToScreenPoint(camPos + tr.TransformDirection(new Vector3(0, 0, distance)));\n                Vector3 screenPos2 = cam.WorldToScreenPoint(camPos + tr.TransformDirection(new Vector3(1, 0, distance)));\n                float screenDist = (screenPos - screenPos2).magnitude;\n                return (k_KHandleSize / Mathf.Max(screenDist, 0.0001f)) * EditorGUIUtility.pixelsPerPoint;\n            }\n            return 20.0f;\n        }\n\n        static float renderingViewHeight\n        {\n            get { return Camera.current == null ? Screen.height : Camera.current.pixelHeight; }\n        }\n\n        // Convert world space point to a 2D GUI position.\n        public static Vector2 WorldToGUIPoint(Vector3 world)\n        {\n            return WorldToGUIPointWithDepth(world);\n        }\n\n        // Convert world space point to a 2D GUI position.\n        public static Vector3 WorldToGUIPointWithDepth(Vector3 world)\n        {\n            return WorldToGUIPointWithDepth(Camera.current, world);\n        }\n\n        // Convert world space point to a 2D GUI position.\n        // Use this version in critical loops.\n        public static Vector3 WorldToGUIPointWithDepth(Camera camera, Vector3 world)\n        {\n            world = Handles.matrix.MultiplyPoint(world);\n\n            if (camera)\n            {\n                Vector3 pos = camera.WorldToScreenPoint(world);\n                pos.y = camera.pixelHeight - pos.y;\n                Vector2 points = EditorGUIUtility.PixelsToPoints(pos);\n                return new Vector3(points.x, points.y, pos.z);\n            }\n\n            return world;\n        }\n\n        public static Vector2 GUIPointToScreenPixelCoordinate(Vector2 guiPoint)\n        {\n            var unclippedPosition = GUIClip.Unclip(guiPoint);\n            var screenPixelPos = EditorGUIUtility.PointsToPixels(unclippedPosition);\n            screenPixelPos.y = renderingViewHeight - screenPixelPos.y;\n            return screenPixelPos;\n        }\n\n        // Convert 2D GUI position to a world space ray.\n        public static Ray GUIPointToWorldRay(Vector2 position)\n        {\n            return GUIPointToWorldRayPrecise(position);\n        }\n\n        private static Ray GUIPointToWorldRayPrecise(Vector2 position, float startZ = float.NegativeInfinity)\n        {\n            Camera camera = Camera.current;\n\n            if (!camera && SceneView.lastActiveSceneView != null)\n                camera = SceneView.lastActiveSceneView.camera;\n\n            if (!camera)\n            {\n                Debug.LogError(\"Unable to convert GUI point to world ray if a camera has not been set up!\");\n                return new Ray(Vector3.zero, Vector3.forward);\n            }\n\n            if (float.IsNegativeInfinity(startZ))\n                startZ = camera.nearClipPlane;\n\n            Vector2 screenPixelPos = GUIPointToScreenPixelCoordinate(position);\n            Rect viewport = camera.pixelRect;\n\n            Matrix4x4 camToWorld = camera.cameraToWorldMatrix;\n            Matrix4x4 camToClip = camera.projectionMatrix;\n            Matrix4x4 clipToCam = camToClip.inverse;\n\n            // calculate ray origin and direction in world space\n            Vector3 rayOriginWorldSpace;\n            Vector3 rayDirectionWorldSpace;\n\n            // first construct an arbitrary point that is on the ray through this screen pixel (remap screen pixel point to clip space [-1, 1])\n            Vector3 rayPointClipSpace = new Vector3(\n                (screenPixelPos.x - viewport.x) * 2.0f / viewport.width - 1.0f,\n                (screenPixelPos.y - viewport.y) * 2.0f / viewport.height - 1.0f,\n                0.95f\n            );\n\n            // and convert that point to camera space\n            Vector3 rayPointCameraSpace = clipToCam.MultiplyPoint(rayPointClipSpace);\n\n            if (camera.orthographic)\n            {\n                // ray direction is always 'camera forward' in orthographic mode\n                Vector3 rayDirectionCameraSpace = new Vector3(0.0f, 0.0f, -1.0f);\n                rayDirectionWorldSpace = camToWorld.MultiplyVector(rayDirectionCameraSpace);\n                rayDirectionWorldSpace.Normalize();\n\n                // in camera space, the ray origin has the same XY coordinates as ANY point on the ray\n                // so we just need to override the Z coordinate to startZ to get the correct starting point\n                // (assuming camToWorld is a pure rotation/offset, with no scale)\n                Vector3 rayOriginCameraSpace = rayPointCameraSpace;\n                // The camera/projection matrices follow OpenGL convention: positive Z is towards the viewer.\n                // So negate it to get into Unity convention.\n                rayOriginCameraSpace.z = -startZ;\n\n                // move it to world space\n                rayOriginWorldSpace = camToWorld.MultiplyPoint(rayOriginCameraSpace);\n            }\n            else\n            {\n                // in projective mode, the ray passes through the origin in camera space\n                // so the ray direction is just (ray point - origin) == (ray point)\n                Vector3 rayDirectionCameraSpace = rayPointCameraSpace;\n                rayDirectionCameraSpace.Normalize();\n\n                rayDirectionWorldSpace = camToWorld.MultiplyVector(rayDirectionCameraSpace);\n\n                // calculate the correct startZ offset from the camera by moving a distance along the ray direction\n                // this assumes camToWorld is a pure rotation/offset, with no scale, so we can use rayDirection.z to calculate how far we need to move\n                Vector3 cameraPositionWorldSpace = camToWorld.MultiplyPoint(Vector3.zero);\n                // The camera/projection matrices follow OpenGL convention: positive Z is towards the viewer.\n                // So negate it to get into Unity convention.\n                Vector3 originOffsetWorldSpace = rayDirectionWorldSpace * -startZ / rayDirectionCameraSpace.z;\n                rayOriginWorldSpace = cameraPositionWorldSpace + originOffsetWorldSpace;\n            }\n\n            return new Ray(rayOriginWorldSpace, rayDirectionWorldSpace);\n        }\n\n        // Figure out a rectangle to display a 2D GUI element in 3D space.\n        public static Rect WorldPointToSizedRect(Vector3 position, GUIContent content, GUIStyle style)\n        {\n            Vector2 screenpos = WorldToGUIPoint(position);\n            Vector2 size = style.CalcSize(content);\n            Rect rect = new Rect(screenpos.x, screenpos.y, size.x, size.y);\n            switch (style.alignment)\n            {\n                case TextAnchor.UpperCenter:\n                    rect.x -= rect.width * 0.5f;\n                    break;\n                case TextAnchor.UpperRight:\n                    rect.x -= rect.width;\n                    break;\n                case TextAnchor.MiddleLeft:\n                    rect.y -= rect.height * 0.5f;\n                    break;\n                case TextAnchor.MiddleCenter:\n                    rect.x -= rect.width * 0.5f;\n                    rect.y -= rect.height * 0.5f;\n                    break;\n                case TextAnchor.MiddleRight:\n                    rect.x -= rect.width;\n                    rect.y -= rect.height * 0.5f;\n                    break;\n                case TextAnchor.LowerLeft:\n                    rect.y -= rect.height;\n                    break;\n                case TextAnchor.LowerCenter:\n                    rect.x -= rect.width * 0.5f;\n                    rect.y -= rect.height;\n                    break;\n                case TextAnchor.LowerRight:\n                    rect.x -= rect.width;\n                    rect.y -= rect.height;\n                    break;\n            }\n\n            return style.padding.Add(rect);\n        }\n\n        // Pick game object in specified rectangle\n        public static GameObject[] PickRectObjects(Rect rect)\n        {\n            return PickRectObjects(rect, true);\n        }\n\n        // *undocumented*\n        public static GameObject[] PickRectObjects(Rect rect, bool selectPrefabRootsOnly)\n        {\n            Camera cam = Camera.current;\n            rect = EditorGUIUtility.PointsToPixels(rect);\n            rect.x /= cam.pixelWidth;\n            rect.width /= cam.pixelWidth;\n            rect.y /= cam.pixelHeight;\n            rect.height /= cam.pixelHeight;\n            bool allowGizmos = SceneView.lastActiveSceneView == null || SceneView.lastActiveSceneView.drawGizmos;\n            return Internal_PickRectObjects(cam, rect, selectPrefabRootsOnly, allowGizmos);\n        }\n\n        public static bool FindNearestVertex(Vector2 guiPoint, out Vector3 vertex, out GameObject gameObject)\n        {\n            return FindNearestVertex(guiPoint, null, ignoreRaySnapObjects, out vertex, out gameObject);\n        }\n\n        public static bool FindNearestVertex(Vector2 guiPoint, Transform[] objectsToSearch, out Vector3 vertex, out GameObject gameObject)\n        {\n            return FindNearestVertex(guiPoint, objectsToSearch, ignoreRaySnapObjects, out vertex, out gameObject);\n        }\n\n        public static bool FindNearestVertex(Vector2 guiPoint, Transform[] objectsToSearch, Transform[] objectsToIgnore, out Vector3 vertex, out GameObject gameObject)\n        {\n            Camera cam = Camera.current;\n            var screenPoint = EditorGUIUtility.PointsToPixels(guiPoint);\n            screenPoint.y = cam.pixelRect.yMax - screenPoint.y;\n            gameObject = Internal_FindNearestVertex(cam, screenPoint, objectsToSearch, objectsToIgnore, out vertex, out bool found);\n            return found;\n        }\n\n        public static bool FindNearestVertex(Vector2 guiPoint, out Vector3 vertex)\n        {\n            return FindNearestVertex(guiPoint, null, ignoreRaySnapObjects, out vertex);\n        }\n\n        public static bool FindNearestVertex(Vector2 guiPoint, Transform[] objectsToSearch, out Vector3 vertex)\n        {\n            return FindNearestVertex(guiPoint, objectsToSearch, ignoreRaySnapObjects, out vertex);\n        }\n\n        public static bool FindNearestVertex(Vector2 guiPoint, Transform[] objectsToSearch, Transform[] objectsToIgnore, out Vector3 vertex)\n        {\n            Camera cam = Camera.current;\n            var screenPoint = EditorGUIUtility.PointsToPixels(guiPoint);\n            screenPoint.y = cam.pixelRect.yMax - screenPoint.y;\n            Internal_FindNearestVertex(cam, screenPoint, objectsToSearch, objectsToIgnore, out vertex, out bool found);\n            return found;\n        }\n\n        // Until `pickGameObjectCustomPasses` can handle sorting priority correctly, we need a way to override the\n        // picking action treating the override pass as topmost. This is used for things like Physics Debugger, where\n        // picking should always select the debug volumes first.\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        internal delegate GameObject PickClosestGameObjectFunc(Camera cam, int layers, Vector2 position, GameObject[] ignore, GameObject[] filter, out int materialIndex);\n\n        // Important! Where possible you should prefer to use pickGameObjectCustomPasses. See above for explanation.\n        internal static PickClosestGameObjectFunc pickClosestGameObjectDelegate;\n\n        // Add the ability to select objects that are not selectable through the usual rendering method\n        public delegate GameObject PickGameObjectCallback(Camera cam, int layers, Vector2 position, GameObject[] ignore, GameObject[] filter, out int materialIndex);\n        public static event PickGameObjectCallback pickGameObjectCustomPasses;\n\n        static List<PickingObject> s_IgnorePickResultsCache = new List<PickingObject>();\n        static List<PickingObject> s_FilterPickResultsCache = new List<PickingObject>();\n\n        static void SetPickingObjectList<T>(List<PickingObject> list, T[] array) where T : UnityObject\n        {\n            list.Clear();\n            for (int i = 0, c = array?.Length ?? 0; i < c; ++i)\n                list.Add(new PickingObject(array[i]));\n        }\n\n        static GameObject[] CreatePickingObjectArray(List<PickingObject> list)\n        {\n            if (list == null || list.Count < 1)\n                return null;\n\n            int c = list.Count, n = 0;\n            var array = new GameObject[c];\n            for (int i = 0; i < c; ++i)\n                if (list[i].TryGetGameObject(out var go))\n                    array[n++] = go;\n            if (n < c)\n                Array.Resize(ref array, n);\n            return array;\n        }\n\n        public static GameObject PickGameObject(Vector2 position, out int materialIndex)\n        {\n            return PickGameObject(position, false, null, null, out materialIndex);\n        }\n\n        public static GameObject PickGameObject(Vector2 position, GameObject[] ignore, out int materialIndex)\n        {\n            return PickGameObject(position, false, ignore, null, out materialIndex);\n        }\n\n        public static GameObject PickGameObject(Vector2 position, bool selectPrefabRoot)\n        {\n            return PickGameObject(position, selectPrefabRoot, null, null, out _);\n        }\n\n        public static GameObject PickGameObject(Vector2 position, bool selectPrefabRoot, GameObject[] ignore)\n        {\n            return PickGameObject(position, selectPrefabRoot, ignore, null, out _);\n        }\n\n        public static GameObject PickGameObject(Vector2 position, bool selectPrefabRoot, GameObject[] ignore, GameObject[] filter)\n        {\n            return PickGameObject(position, selectPrefabRoot, ignore, filter, out _);\n        }\n\n        public static GameObject PickGameObject(Vector2 position, GameObject[] ignore, GameObject[] selection, out int materialIndex)\n        {\n            return PickGameObject(position, false, ignore, selection, out materialIndex);\n        }\n\n        public static GameObject PickGameObject(Vector2 position, bool selectPrefabRoot, GameObject[] ignore, GameObject[] filter, out int materialIndex)\n        {\n            SetPickingObjectList(s_IgnorePickResultsCache, ignore);\n            SetPickingObjectList(s_FilterPickResultsCache, filter);\n            var res = PickObject(position, selectPrefabRoot, s_IgnorePickResultsCache, s_FilterPickResultsCache);\n            res.TryGetGameObject(out var gameObject);\n            s_IgnorePickResultsCache.Clear();\n            s_FilterPickResultsCache.Clear();\n            materialIndex = res.materialIndex;\n            return gameObject;\n        }\n\n        public static void PickAllObjects(Vector2 position, List<UnityObject> results)\n        {\n            results.Clear();\n            var overlapping = SceneViewPicking.GetAllOverlapping(position);\n            foreach (var obj in overlapping)\n                results.Add(obj.target);\n        }\n\n        static GameObject[] s_PickingGameObjectIgnore = new GameObject[16];\n        static GameObject[] s_PickingGameObjectFilter = new GameObject[16];\n\n        // this exists to pass picking parameters to hybrid renderer. these fields are only valid within the scope of\n        // the PickObject method\n        static List<PickingObject> s_PickingInclude, s_PickingExclude;\n        static List<int> s_RendererIncludeBuffer = new List<int>(), s_EntityIncludeBuffer = new List<int>();\n        static List<int> s_RendererExcludeBuffer = new List<int>(), s_EntityExcludeBuffer = new List<int>();\n\n        public static PickingIncludeExcludeList GetPickingIncludeExcludeList(Allocator allocator = Allocator.Persistent)\n        {\n            s_RendererIncludeBuffer.Clear();\n            s_RendererExcludeBuffer.Clear();\n            s_EntityIncludeBuffer.Clear();\n            s_EntityExcludeBuffer.Clear();\n            GetPickingIds(s_PickingInclude, s_RendererIncludeBuffer, s_EntityIncludeBuffer);\n            GetPickingIds(s_PickingExclude, s_RendererExcludeBuffer, s_EntityExcludeBuffer);\n            return new PickingIncludeExcludeList(s_RendererIncludeBuffer, s_RendererExcludeBuffer, s_EntityIncludeBuffer, s_EntityExcludeBuffer, allocator);\n        }\n\n        public static PickingIncludeExcludeList GetSelectionOutlineIncludeExcludeList(Allocator allocator = Allocator.Persistent)\n        {\n            s_RendererIncludeBuffer.Clear();\n            s_RendererExcludeBuffer.Clear();\n            s_EntityIncludeBuffer.Clear();\n            s_EntityExcludeBuffer.Clear();\n            GetPickingIds(Selection.objects, s_RendererIncludeBuffer, s_EntityIncludeBuffer);\n            return new PickingIncludeExcludeList(s_RendererIncludeBuffer, null, s_EntityIncludeBuffer, null, allocator);\n        }\n\n        internal static PickingObject PickObject(Vector2 guiPosition,\n            bool selectPrefabRoot = false,\n            List<PickingObject> ignore = null,\n            List<PickingObject> filter = null)\n        {\n            Camera cam = Camera.current;\n            int layers = cam.cullingMask;\n            var screenPosition = GUIPointToScreenPixelCoordinate(guiPosition);\n            var sceneView = SceneView.lastActiveSceneView;\n            bool drawGizmos = sceneView != null && sceneView.drawGizmos;\n            PickingObject picked = PickingObject.Empty;\n\n            s_PickingInclude = filter;\n            s_PickingExclude = ignore;\n\n            if (pickClosestGameObjectDelegate != null)\n            {\n                // todo remove callbacks accepting GameObject[] arrays\n                s_PickingGameObjectIgnore = CreatePickingObjectArray(ignore);\n                s_PickingGameObjectFilter = CreatePickingObjectArray(filter);\n\n                var gameObject = pickClosestGameObjectDelegate(cam,\n                    layers,\n                    screenPosition,\n                    s_PickingGameObjectIgnore,\n                    s_PickingGameObjectFilter,\n                    out int materialIndex);\n\n                picked = new PickingObject(gameObject, materialIndex);\n            }\n\n            if (picked == PickingObject.Empty)\n            {\n                int materialIndex = 0;\n                bool isEntity = false;\n                uint pickingID = Internal_GetClosestPickingID(cam,\n                        layers,\n                        screenPosition,\n                        NoAllocHelpers.ExtractArrayFromList(ignore),\n                        NoAllocHelpers.ExtractArrayFromList(filter),\n                        drawGizmos,\n                        ref materialIndex,\n                        ref isEntity);\n\n                if (pickingID != 0)\n                {\n                    UnityObject pickedObject;\n\n                    if (isEntity)\n                    {\n                        // The render target stores entityIndex + 1\n                        int entityIndex = (int)pickingID - 1;\n                        pickedObject = GetAuthoringObjectForEntity(entityIndex);\n                    }\n                    else\n                    {\n                        int instanceID = (int)pickingID;\n                        pickedObject = EditorUtility.InstanceIDToObject(instanceID);\n                    }\n\n                    picked = new PickingObject(pickedObject, materialIndex);\n                }\n\n                s_PickingInclude = null;\n                s_PickingExclude = null;\n            }\n\n            if (picked == PickingObject.Empty && pickGameObjectCustomPasses != null)\n            {\n                s_PickingGameObjectIgnore = CreatePickingObjectArray(ignore);\n                s_PickingGameObjectFilter = CreatePickingObjectArray(filter);\n\n                foreach (var method in pickGameObjectCustomPasses.GetInvocationList())\n                {\n                    var gameObject = ((PickGameObjectCallback)method)(cam, layers, screenPosition, s_PickingGameObjectIgnore, s_PickingGameObjectFilter, out int materialIndex);\n\n                    // don't trust this method to respect the ignore or filter argument, because in the event that it\n                    // does not it will break pick cycling in SceneViewPicking.GetAllOverlapping.\n                    if (gameObject != null)\n                    {\n                        var tmp = new PickingObject(gameObject, materialIndex);\n\n                        if ((ignore == null || !ignore.Contains(tmp)) && (filter == null || filter.Contains(tmp)))\n                        {\n                            picked = tmp;\n                            break;\n                        }\n                    }\n                }\n            }\n\n            // for now selectPrefabRoot won't be respected for entities\n            if (selectPrefabRoot && picked.TryGetGameObject(out var go))\n            {\n                GameObject selectionBase = FindSelectionBaseForPicking(go);\n                GameObject pickedRoot = selectionBase != null ? selectionBase : go;\n                Transform atc = Selection.activeTransform;\n\n                GameObject selectionRoot = null;\n                if (atc != null)\n                {\n                    GameObject atcSelectionBase = FindSelectionBaseForPicking(atc.gameObject);\n                    selectionRoot = atcSelectionBase != null ? atcSelectionBase : atc.gameObject;\n                }\n\n                if (pickedRoot == selectionRoot)\n                    return picked;\n                return new PickingObject(pickedRoot);\n            }\n\n            return picked;\n        }\n\n        static void GetPickingIds(List<PickingObject> objects, List<int> ren, List<int> ent)\n        {\n            if (objects == null)\n                return;\n\n            for (int i = 0; i < objects.Count; ++i)\n            {\n                if (objects[i] == null)\n                    continue;\n\n                // If the object is represented by entities, they take priority\n                if (GetEntitiesForAuthoringObject(objects[i].target, ent) > 0)\n                    continue;\n\n                // Otherwise, use the Renderer component, if any\n                if (objects[i].target is GameObject gameObject && gameObject.TryGetComponent<Renderer>(out var renderer))\n                    ren.Add(renderer.GetInstanceID());\n            }\n        }\n\n        static void GetPickingIds(UnityEngine.Object[] objects, List<int> ren, List<int> ent)\n        {\n            if (objects == null)\n                return;\n\n            for (int i = 0; i < objects.Length; ++i)\n            {\n                if (objects[i] == null)\n                    continue;\n\n                // If the object is represented by entities, they take priority\n                if (GetEntitiesForAuthoringObject(objects[i], ent) > 0)\n                    continue;\n\n                // Otherwise, use the Renderer component, if any\n                if (objects[i] is GameObject gameObject && gameObject.TryGetComponent<Renderer>(out var renderer))\n                    ren.Add(renderer.GetInstanceID());\n            }\n        }\n\n        public static event Func<UnityEngine.Object, IEnumerable<int>> getEntitiesForAuthoringObject = default;\n\n        public static event Func<int, UnityEngine.Object> getAuthoringObjectForEntity = default;\n\n        static UnityEngine.Object GetAuthoringObjectForEntity(int entityIndex)\n        {\n            var delegates = getAuthoringObjectForEntity?.GetInvocationList();\n\n            if (delegates == null)\n                return null;\n\n            foreach (var del in delegates)\n            {\n                var ret = ((Func<int, UnityEngine.Object>)del)(entityIndex);\n                if (ret != null)\n                    return ret;\n            }\n\n            return null;\n        }\n\n        static int GetEntitiesForAuthoringObject(UnityEngine.Object authoring, List<int> entities)\n        {\n            int numEntities = 0;\n            var delegates = getEntitiesForAuthoringObject?.GetInvocationList();\n\n            if (delegates == null)\n                return 0;\n\n            foreach (var del in delegates)\n            {\n                foreach (var ent in ((Func<UnityEngine.Object, IEnumerable<int>>)del)(authoring))\n                {\n                    entities.Add(ent);\n                    ++numEntities;\n                }\n            }\n\n            return numEntities;\n        }\n\n        // Get the selection base object, taking into account user enabled picking filter\n        internal static GameObject FindSelectionBaseForPicking(Transform transform)\n        {\n            if (transform == null)\n                return null;\n            return FindSelectionBaseForPicking(transform.gameObject);\n        }\n\n        internal static GameObject FindSelectionBaseForPicking(GameObject go)\n        {\n            if (go == null)\n                return null;\n\n            // Find prefab based base\n            Transform prefabBase = null;\n\n            var isPrefabPart = PrefabUtility.IsPartOfNonAssetPrefabInstance(go);\n            if (isPrefabPart)\n            {\n                prefabBase = PrefabUtility.GetOutermostPrefabInstanceRoot(go).transform;\n\n                if (go.transform.parent == null || go.transform.parent.gameObject == null)\n                    return null;\n\n                var parentgo = go.transform.parent.gameObject;\n                //The current go is part of a prefab and its parent is part of another prefab\n                //this avoid to select the parent prefab instead of the current one\n                if (PrefabUtility.IsPartOfNonAssetPrefabInstance(parentgo) &&\n                    prefabBase != PrefabUtility.GetOutermostPrefabInstanceRoot(parentgo).transform)\n                    return null;\n            }\n\n            // Walk up the hierarchy to find the outermost prefab instance root that is not marked as non-pickable, or\n            // alternatively a GameObject with the SelectionBaseAttribute assigned.\n            Transform tr = go.transform;\n            GameObject outerMostSelectableRoot = null;\n            GameObject prefabBaseGo = null;\n\n            while (tr != null)\n            {\n                if (!SceneVisibilityState.IsGameObjectPickingDisabled(tr.gameObject))\n                {\n                    // If we come across the prefab base, we still need to make sure there are no\n                    // go with the SelectionBaseAttribute assigned before returning prefabBaseGo.\n                    if (tr == prefabBase && prefabBaseGo == null)\n                    {\n                        prefabBaseGo = tr.gameObject;\n                        continue;\n                    }\n\n                    // Only test again nested prefab if go is already part of a prefab to avoid selecting a\n                    // parent prefab is the current go is only child of this prefab but does not belong to it\n                    if (isPrefabPart)\n                    {\n                        // If prefabBase is not pickable, we want to select the nearest pickable root to the base\n                        GameObject nestedRoot = PrefabUtility.GetNearestPrefabInstanceRoot(tr);\n\n                        if (nestedRoot != null && tr == nestedRoot.transform)\n                            outerMostSelectableRoot = tr.gameObject;\n                    }\n\n                    // If a SelectionBaseAttribute is found, select the nearest to the picked GameObject.\n                    // GameObjects with the SelectionBaseAttribute should have priority over all others.\n                    if (AttributeHelper.GameObjectContainsAttribute<SelectionBaseAttribute>(tr.gameObject))\n                        return tr.gameObject;\n                }\n\n                tr = tr.parent;\n            }\n\n            if (prefabBaseGo != null)\n                return prefabBaseGo;\n\n            return outerMostSelectableRoot;\n        }\n\n        // The materials used to draw handles - Don't use unless you're Nicholas.\n        public static Material handleMaterial\n        {\n            get\n            {\n                if (!s_HandleMaterial)\n                {\n                    s_HandleMaterial = (Material)EditorGUIUtility.Load(\"SceneView/Handles.mat\");\n                }\n                return s_HandleMaterial;\n            }\n        }\n        static Material s_HandleMaterial;\n\n        // Called by native code\n        [RequiredByNativeCode]\n        static void CleanupHandleMaterials()\n        {\n            DisposeArcIndexBuffer();\n            // This is enough for all of them to get re-fetched in next call to InitHandleMaterials()\n            s_HandleWireMaterial = null;\n        }\n\n        static GraphicsBuffer s_ArcIndexBuffer;\n\n        static void DisposeArcIndexBuffer()\n        {\n            s_ArcIndexBuffer?.Dispose();\n            s_ArcIndexBuffer = null;\n        }\n\n        static internal GraphicsBuffer GetArcIndexBuffer(int segments, int sides)\n        {\n            int indexCount = (segments - 1) * sides * 2 * 3;\n            if (s_ArcIndexBuffer != null && s_ArcIndexBuffer.count == indexCount)\n                return s_ArcIndexBuffer;\n\n            s_ArcIndexBuffer?.Dispose();\n            AssemblyReloadEvents.beforeAssemblyReload += DisposeArcIndexBuffer;\n            EditorApplication.quitting += DisposeArcIndexBuffer;\n\n            s_ArcIndexBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Index, indexCount, 2);\n            ushort[] ib = new ushort[indexCount];\n            var idx = 0;\n            for (var seg = 0; seg < segments - 1; ++seg)\n            {\n                for (var side = 0; side < sides; ++side)\n                {\n                    var idx00 = seg * sides + side;\n                    var idx01 = seg * sides + (side + 1) % sides;\n                    var idx10 = (seg + 1) * sides + side;\n                    var idx11 = (seg + 1) * sides + (side + 1) % sides;\n                    ib[idx + 0] = (ushort)idx00;\n                    ib[idx + 1] = (ushort)idx10;\n                    ib[idx + 2] = (ushort)idx01;\n                    ib[idx + 3] = (ushort)idx01;\n                    ib[idx + 4] = (ushort)idx10;\n                    ib[idx + 5] = (ushort)idx11;\n                    idx += 6;\n                }\n            }\n            s_ArcIndexBuffer.SetData(ib);\n            return s_ArcIndexBuffer;\n        }\n\n        static void InitHandleMaterials()\n        {\n            if (!s_HandleWireMaterial)\n            {\n                RegisterGfxDeviceCleanupIfNeeded();\n\n                s_HandleWireMaterial = (Material)EditorGUIUtility.LoadRequired(\"SceneView/HandleLines.mat\");\n                s_HandleWireMaterial2D = (Material)EditorGUIUtility.LoadRequired(\"SceneView/2DHandleLines.mat\");\n                s_HandleWireTextureIndex = ShaderUtil.GetTextureBindingIndex(s_HandleWireMaterial.shader, Shader.PropertyToID(\"_MainTex\"));\n                s_HandleWireTextureIndex2D = ShaderUtil.GetTextureBindingIndex(s_HandleWireMaterial2D.shader, Shader.PropertyToID(\"_MainTex\"));\n                s_HandleWireTextureSamplerIndex = ShaderUtil.GetTextureSamplerBindingIndex(s_HandleWireMaterial.shader, Shader.PropertyToID(\"_MainTex\"));\n                s_HandleWireTextureSamplerIndex2D = ShaderUtil.GetTextureSamplerBindingIndex(s_HandleWireMaterial2D.shader, Shader.PropertyToID(\"_MainTex\"));\n\n                s_HandleDottedWireMaterial = (Material)EditorGUIUtility.LoadRequired(\"SceneView/HandleDottedLines.mat\");\n                s_HandleDottedWireMaterial2D = (Material)EditorGUIUtility.LoadRequired(\"SceneView/2DHandleDottedLines.mat\");\n                s_HandleDottedWireTextureIndex = ShaderUtil.GetTextureBindingIndex(s_HandleDottedWireMaterial.shader, Shader.PropertyToID(\"_MainTex\"));\n                s_HandleDottedWireTextureIndex2D = ShaderUtil.GetTextureBindingIndex(s_HandleDottedWireMaterial2D.shader, Shader.PropertyToID(\"_MainTex\"));\n                s_HandleDottedWireTextureSamplerIndex = ShaderUtil.GetTextureSamplerBindingIndex(s_HandleDottedWireMaterial.shader, Shader.PropertyToID(\"_MainTex\"));\n                s_HandleDottedWireTextureSamplerIndex2D = ShaderUtil.GetTextureSamplerBindingIndex(s_HandleDottedWireMaterial2D.shader, Shader.PropertyToID(\"_MainTex\"));\n\n                s_HandleArcMaterial = (Material)EditorGUIUtility.LoadRequired(\"SceneView/CircularArc.mat\");\n            }\n        }\n\n        // Material used to draw \"lines\" and other wireframe-like stuff.\n        // Private for a reason; always use ApplyWireMaterial to set it up for rendering!\n        // It needs to remember texture binding index so that DrawAA* functions can properly\n        // set the anti-aliasing texture.\n        static Material handleWireMaterial\n        {\n            get\n            {\n                InitHandleMaterials();\n                return Camera.current ? s_HandleWireMaterial : s_HandleWireMaterial2D;\n            }\n        }\n\n        // Material used to draw lines like above, only \"dotted\"\n        static Material handleDottedWireMaterial\n        {\n            get\n            {\n                InitHandleMaterials();\n                return Camera.current ? s_HandleDottedWireMaterial : s_HandleDottedWireMaterial2D;\n            }\n        }\n\n        static internal Material handleArcMaterial\n        {\n            get\n            {\n                InitHandleMaterials();\n                return s_HandleArcMaterial;\n            }\n        }\n\n        static Material s_HandleWireMaterial;\n        static Material s_HandleWireMaterial2D;\n        static int s_HandleWireTextureIndex;\n        static int s_HandleWireTextureSamplerIndex;\n        static int s_HandleWireTextureIndex2D;\n        static int s_HandleWireTextureSamplerIndex2D;\n\n        static Material s_HandleDottedWireMaterial;\n        static Material s_HandleDottedWireMaterial2D;\n        static int s_HandleDottedWireTextureIndex;\n        static int s_HandleDottedWireTextureSamplerIndex;\n        static int s_HandleDottedWireTextureIndex2D;\n        static int s_HandleDottedWireTextureSamplerIndex2D;\n\n        static Material s_HandleArcMaterial;\n\n        // Setup shader for later drawing of lines / anti-aliased lines.\n        internal static void ApplyWireMaterial([DefaultValue(\"UnityEngine.Rendering.CompareFunction.Always\")] CompareFunction zTest)\n        {\n            Material mat = handleWireMaterial;\n            // Note: important to call this from C# side, so that it tracks \"scripting channels\"\n            // for any later GL.Begin calls.\n            mat.SetFloat(\"_HandleZTest\", (float)zTest);\n            mat.SetPass(0);\n            int textureIndex = Camera.current ? s_HandleWireTextureIndex : s_HandleWireTextureIndex2D;\n            int samplerIndex = Camera.current ? s_HandleWireTextureSamplerIndex : s_HandleWireTextureSamplerIndex2D;\n            Internal_SetHandleWireTextureIndex(textureIndex, samplerIndex);\n        }\n\n        [ExcludeFromDocs]\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal static void ApplyWireMaterial()\n        {\n            CompareFunction zTest = CompareFunction.Always;\n            ApplyWireMaterial(zTest);\n        }\n\n        internal static void ApplyDottedWireMaterial([DefaultValue(\"UnityEngine.Rendering.CompareFunction.Always\")] CompareFunction zTest)\n        {\n            Material mat = handleDottedWireMaterial;\n            // Note: important to call this from C# side, so that it tracks \"scripting channels\"\n            // for any later GL.Begin calls.\n            mat.SetFloat(\"_HandleZTest\", (float)zTest);\n            mat.SetPass(0);\n            int textureIndex = Camera.current ? s_HandleDottedWireTextureIndex : s_HandleDottedWireTextureIndex2D;\n            int samplerIndex = Camera.current ? s_HandleDottedWireTextureSamplerIndex : s_HandleDottedWireTextureSamplerIndex2D;\n            Internal_SetHandleWireTextureIndex(textureIndex, samplerIndex);\n        }\n\n        [ExcludeFromDocs]\n        internal static void ApplyDottedWireMaterial()\n        {\n            CompareFunction zTest = CompareFunction.Always;\n            ApplyDottedWireMaterial(zTest);\n        }\n\n        // Store all camera settings\n        public static void PushCamera(Camera camera)\n        {\n            s_SavedCameras.Push(new SavedCamera(camera));\n        }\n\n        // Retrieve all camera settings\n        public static void PopCamera(Camera camera)\n        {\n            SavedCamera cam = (SavedCamera)s_SavedCameras.Pop();\n            cam.Restore(camera);\n        }\n\n        sealed class SavedCamera\n        {\n            float near, far;\n            Rect pixelRect;\n            Vector3 pos;\n            Quaternion rot;\n            CameraClearFlags clearFlags;\n            int cullingMask;\n            float fov;\n            float orthographicSize;\n            bool isOrtho;\n\n            internal SavedCamera(Camera source)\n            {\n                near = source.nearClipPlane;\n                far = source.farClipPlane;\n                pixelRect = source.pixelRect;\n                pos = source.transform.position;\n                rot = source.transform.rotation;\n                clearFlags = source.clearFlags;\n                cullingMask = source.cullingMask;\n                fov = source.fieldOfView;\n                orthographicSize = source.orthographicSize;\n                isOrtho = source.orthographic;\n            }\n\n            internal void Restore(Camera dest)\n            {\n                dest.nearClipPlane = near;\n                dest.farClipPlane = far;\n                dest.pixelRect = pixelRect;\n                dest.transform.position = pos;\n                dest.transform.rotation = rot;\n                dest.clearFlags = clearFlags;\n                dest.fieldOfView = fov;\n                dest.orthographicSize = orthographicSize;\n                dest.orthographic = isOrtho;\n                dest.cullingMask = cullingMask;\n            }\n        }\n\n        static Stack s_SavedCameras = new Stack();\n\n        // Objects to ignore when raysnapping (typically the objects being dragged by the handles)\n        internal static Transform[] ignoreRaySnapObjects = null;\n        static RaycastHit[] s_RaySnapHits = new RaycastHit[100];\n\n        static bool TryRaySnap(Ray ray, out RaycastHit resultHit)\n        {\n            object result = RaySnap(ray);\n            if (result == null)\n            {\n                resultHit = default(RaycastHit);\n                resultHit.distance = Mathf.Infinity;\n                return false;\n            }\n\n            resultHit = (RaycastHit)result;\n            return true;\n        }\n\n        // Casts /ray/ against the scene.\n        public static object RaySnap(Ray ray)\n        {\n            Camera cam = Camera.current;\n\n            if (cam == null)\n                return null;\n\n            ulong sceneCullingMask = cam.sceneCullingMask;\n            int layerCullingMask = cam.cullingMask;\n\n            bool hitAny = false;\n            RaycastHit raycastHit = default(RaycastHit);\n            raycastHit.distance = Mathf.Infinity;\n\n            if (sceneCullingMask == SceneCullingMasks.MainStageSceneViewObjects)\n            {\n                // Default code path for Scene view that is just displaying the Main Stage.\n                // Note that even if Prefab Mode is open, special Scene views can still show the Main Stage!\n                // We only check against default physics scene here, and shouldn't ignore Prefab instances\n                // that are opened in Prefab Mode in Context.\n                hitAny |= GetNearestHitFromPhysicsScene(ray, Physics.defaultPhysicsScene, layerCullingMask, false, ref raycastHit);\n            }\n            else\n            {\n                // Code path is Scene view is displaying a Prefab Stage.\n                // Here we dig down from the top of the stage history stack and continue\n                // including each stage as long as they are displayed as context. Prefab instances\n                // that are hidden due to being opened in Prefab Mode in Context should be ignored.\n                var stageHistory = StageNavigationManager.instance.stageHistory;\n                for (int i = stageHistory.Count - 1; i >= 0; i--)\n                {\n                    Stage stage = stageHistory[i];\n                    var previewSceneStage = stage as PreviewSceneStage;\n                    PhysicsScene physics = previewSceneStage != null ? previewSceneStage.scene.GetPhysicsScene() : Physics.defaultPhysicsScene;\n                    hitAny |= GetNearestHitFromPhysicsScene(ray, physics, layerCullingMask, true, ref raycastHit);\n                    var prefabStage = previewSceneStage as PrefabStage;\n                    if (prefabStage == null ||\n                        prefabStage.mode == PrefabStage.Mode.InIsolation ||\n                        StageNavigationManager.instance.contextRenderMode == StageUtility.ContextRenderMode.Hidden)\n                        break;\n                }\n            }\n\n            if (hitAny)\n                return raycastHit;\n            return null;\n        }\n\n        static bool GetNearestHitFromPhysicsScene(Ray ray, PhysicsScene physicsScene, int cullingMask, bool ignorePrefabInstance, ref RaycastHit raycastHit)\n        {\n            float maxDist = raycastHit.distance;\n            int numHits = physicsScene.Raycast(ray.origin, ray.direction, s_RaySnapHits, maxDist, cullingMask, QueryTriggerInteraction.Ignore);\n\n            // We are not sure at this point if the hits returned from RaycastAll are sorted or not, so go through them all\n            float nearestHitDist = maxDist;\n            int nearestHitIndex = -1;\n            if (ignoreRaySnapObjects != null)\n            {\n                for (int i = 0; i < numHits; i++)\n                {\n                    if (s_RaySnapHits[i].distance < nearestHitDist)\n                    {\n                        Transform tr = s_RaySnapHits[i].transform;\n                        if (SceneVisibilityManager.instance.IsHidden(tr.gameObject))\n                            continue;\n\n                        if (ignorePrefabInstance && GameObjectUtility.IsPrefabInstanceHiddenForInContextEditing(tr.gameObject))\n                            continue;\n\n                        bool ignore = false;\n                        for (int j = 0; j < ignoreRaySnapObjects.Length; j++)\n                        {\n                            if (tr == ignoreRaySnapObjects[j])\n                            {\n                                ignore = true;\n                                break;\n                            }\n                        }\n                        if (ignore)\n                            continue;\n\n                        nearestHitDist = s_RaySnapHits[i].distance;\n                        nearestHitIndex = i;\n                    }\n                }\n            }\n            else\n            {\n                for (int i = 0; i < numHits; i++)\n                {\n                    RaycastHit raySnapHit = s_RaySnapHits[i];\n                    if (SceneVisibilityManager.instance.IsHidden(raySnapHit.transform.gameObject))\n                        continue;\n\n                    if (raySnapHit.distance < nearestHitDist)\n                    {\n                        nearestHitDist = s_RaySnapHits[i].distance;\n                        nearestHitIndex = i;\n                    }\n                }\n            }\n\n            if (nearestHitIndex >= 0)\n            {\n                raycastHit = s_RaySnapHits[nearestHitIndex];\n                return true;\n            }\n            else\n            {\n                return false;\n            }\n        }\n\n        public delegate bool PlaceObjectDelegate(Vector2 guiPosition, out Vector3 position, out Vector3 normal);\n        public static event PlaceObjectDelegate placeObjectCustomPasses;\n\n        public static bool PlaceObject(Vector2 guiPosition, out Vector3 position, out Vector3 normal)\n        {\n            Ray ray = GUIPointToWorldRay(guiPosition);\n            //1- Trying to snap on scene object -> TryRaySnap\n            //2- If no object has been found for placement,\n            //fallback to place object on the scene grids -> TryPlaceOnGrid\n            RaycastHit hit;\n            bool positionFound = TryRaySnap(ray, out hit) || TryPlaceOnGrid(ray, out hit);\n\n            float bestDistance = positionFound ? hit.distance : Mathf.Infinity;\n            position = positionFound ? ray.GetPoint(hit.distance) : Vector3.zero;\n            normal = positionFound ? hit.normal : Vector3.up;\n\n            if (placeObjectCustomPasses != null)\n            {\n                foreach (var del in placeObjectCustomPasses.GetInvocationList())\n                {\n                    Vector3 pos, nrm;\n\n                    if (((PlaceObjectDelegate)del)(guiPosition, out pos, out nrm))\n                    {\n                        var dst = Vector3.Distance(ray.origin, pos);\n                        if (dst < bestDistance)\n                        {\n                            positionFound = true;\n                            bestDistance = dst;\n                            position = pos;\n                            normal = nrm;\n                        }\n                    }\n                }\n            }\n\n            return positionFound;\n        }\n\n        static bool TryPlaceOnGrid(Ray ray, out RaycastHit resultHit)\n        {\n            resultHit = default(RaycastHit);\n            resultHit.distance = Mathf.Infinity;\n            resultHit.normal = Vector3.up;\n\n            Plane targetPlane;\n            if (!TryGetPlane(out targetPlane))\n                return false;\n\n            float hitDistance;\n            if (targetPlane.Raycast(ray, out hitDistance))\n            {\n                resultHit.distance = hitDistance;\n                resultHit.normal = targetPlane.normal;\n                return true;\n            }\n\n            return false;\n        }\n\n        static bool TryGetPlane(out Plane plane)\n        {\n            plane = new Plane();\n\n            var sceneView = SceneView.lastActiveSceneView;\n            var cameraTransform = sceneView.camera.transform;\n            if (SceneView.lastActiveSceneView.showGrid)\n            {\n                var axis = sceneView.sceneViewGrids.gridAxis;\n                var point = sceneView.sceneViewGrids.GetPivot(axis);\n\n                var normal = sceneView.in2DMode ?\n                    Vector3.forward :\n                    new Vector3(\n                    axis == SceneViewGrid.GridRenderAxis.X ? 1 : 0,\n                    axis == SceneViewGrid.GridRenderAxis.Y ? 1 : 0,\n                    axis == SceneViewGrid.GridRenderAxis.Z ? 1 : 0\n                    );\n\n                //Invert normal if camera is facing the other side of the plane\n                if (Vector3.Dot(cameraTransform.forward, normal) > 0)\n                    normal *= -1f;\n\n                plane = new Plane(normal, point);\n\n                //If the camera if on the right side of the plane, return this plane\n                if (plane.GetSide(cameraTransform.position))\n                    return true;\n            }\n\n            return false;\n        }\n\n        internal static void FilterRendererIDs(Renderer[] renderers, out int[] parentRendererIDs, out int[] childRendererIDs)\n        {\n            if (renderers == null)\n            {\n                Debug.LogWarning(\"The Renderer array is null. Handles.DrawOutline will not be rendered.\");\n                parentRendererIDs = new int[0];\n                childRendererIDs = new int[0];\n                return;\n            }\n\n            var parentIndex = 0;\n            parentRendererIDs = new int[renderers.Length];\n\n            foreach (var renderer in renderers)\n                parentRendererIDs[parentIndex++] = renderer.GetInstanceID();\n\n            var tempChildRendererIDs = new HashSet<int>();\n            foreach (var renderer in renderers)\n            {\n                var children = renderer.GetComponentsInChildren<Renderer>();\n                for (int i = 1; i < children.Length; i++)\n                {\n                    var id = children[i].GetInstanceID();\n                    if (!HasMatchingInstanceID(parentRendererIDs, id, parentIndex))\n                        tempChildRendererIDs.Add(id);\n                }\n            }\n\n            childRendererIDs = tempChildRendererIDs.ToArray();\n        }\n\n        internal static void FilterInstanceIDs(IEnumerable<GameObject> gameObjects, out int[] parentInstanceIDs, out int[] childInstanceIDs, out HashSet<int> childInstanceIDsHashSet)\n        {\n            if (gameObjects.Count() == 0)\n            {\n                parentInstanceIDs = new int[0];\n                childInstanceIDs = new int[0];\n                childInstanceIDsHashSet = null;\n                return;\n            }\n\n            var tempParentInstanceIDs = new HashSet<int>();\n            foreach (var go in gameObjects)\n            {\n                if (go.TryGetComponent(out Renderer renderer))\n                    tempParentInstanceIDs.Add(renderer.GetInstanceID());\n                else if (go.TryGetComponent(out Terrain terrain))\n                    tempParentInstanceIDs.Add(terrain.GetInstanceID());\n                // Render commands from the Graphics API can use the gameobject instance ID for selection and outline rendering\n                tempParentInstanceIDs.Add(go.GetInstanceID());\n            }\n\n            childInstanceIDsHashSet = new HashSet<int>();\n            foreach (var go in gameObjects)\n            {\n                var childRenderers = go.GetComponentsInChildren<Renderer>();\n                for (int i = 0; i < childRenderers.Length; i++)\n                {\n                    var id = childRenderers[i].GetInstanceID();\n                    if (!tempParentInstanceIDs.Contains(id))\n                        childInstanceIDsHashSet.Add(id);\n                }\n\n                var childTerrains = go.GetComponentsInChildren<Terrain>();\n                for (int i = 0; i < childTerrains.Length; i++)\n                {\n                    var id = childTerrains[i].GetInstanceID();\n                    if (!tempParentInstanceIDs.Contains(id))\n                        childInstanceIDsHashSet.Add(id);\n                }\n\n                // Script components can issue Render commands that are rendered in the outline so we need to take that in account\n                var userScriptObjects = go.GetComponentsInChildren<MonoBehaviour>();\n                for (int i = 0; i < userScriptObjects.Length; i++)\n                {\n                    var script = userScriptObjects[i];\n                    if (script == null)\n                        continue;\n                    var id = script.gameObject.GetInstanceID();\n                    if (!tempParentInstanceIDs.Contains(id))\n                        childInstanceIDsHashSet.Add(id);\n                }\n            }\n\n            parentInstanceIDs = tempParentInstanceIDs.ToArray();\n            childInstanceIDs = childInstanceIDsHashSet.ToArray();\n        }\n\n        static bool HasMatchingInstanceID(int[] ids, int id, int cutoff)\n        {\n            for (int i = 0; i < ids.Length; i++)\n            {\n                if (ids[i] == id)\n                    return true;\n                if (i > cutoff)\n                    return false;\n            }\n            return false;\n        }\n\n        // Repaint the current view\n        public static void Repaint()\n        {\n            Internal_Repaint();\n        }\n\n        public delegate UnityObject ResolvePickingCallback(int localPickingIndex);\n        public delegate UnityObject ResolvePickingWithWorldPositionCallback(int localPickingIndex, Vector3 worldPos, float depth);\n        public delegate RenderPickingResult RenderPickingCallback(in RenderPickingArgs args);\n\n        private static readonly List<RenderPickingCallback> s_RenderPickingCallbacks = new();\n        private static readonly List<(int PickingIndexBegin, int PickingIndexEnd, ResolvePickingCallback Resolver, ResolvePickingWithWorldPositionCallback ResolverWithWorldPos)> s_RenderPickingResults = new();\n\n        public static bool RegisterRenderPickingCallback(RenderPickingCallback renderPickingCallback)\n        {\n            if (renderPickingCallback == null)\n                throw new ArgumentNullException(nameof(renderPickingCallback));\n            if (s_InPickingRendering)\n                throw new InvalidOperationException($\"{nameof(RegisterRenderPickingCallback)} cannot be called during picking rendering\");\n\n            foreach (var registered in s_RenderPickingCallbacks)\n            {\n                if (registered == renderPickingCallback)\n                    return false;\n            }\n\n            s_RenderPickingCallbacks.Add(renderPickingCallback);\n            return true;\n        }\n\n        public static bool UnregisterRenderPickingCallback(RenderPickingCallback renderPickingCallback)\n        {\n            if (renderPickingCallback == null)\n                throw new ArgumentNullException(nameof(renderPickingCallback));\n            if (s_InPickingRendering)\n                throw new InvalidOperationException($\"{nameof(UnregisterRenderPickingCallback)} cannot be called during picking rendering\");\n\n            for (int i = 0; i < s_RenderPickingCallbacks.Count; ++i)\n            {\n                var registered = s_RenderPickingCallbacks[i];\n                if (registered == renderPickingCallback)\n                {\n                    s_RenderPickingCallbacks.RemoveAt(i);\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        // todo this will need to be an int or tuple<int,int> when we support non-object selection\n        // todo refactor picking code to remove all the static collections that ferry around include/exclude lists\n        static readonly HashSet<GameObject> s_PickingIncludeSet = new HashSet<GameObject>();\n        static readonly HashSet<GameObject> s_PickingExcludeSet = new HashSet<GameObject>();\n\n        private static bool s_InPickingRendering = false;\n\n        // Returns true if any of the resolver function uses depth or reconstructed world space position.\n        [RequiredByNativeCode]\n        static bool DoRenderPicking(int pickingIndex)\n        {\n            s_PickingIncludeSet.Clear();\n            s_PickingExcludeSet.Clear();\n\n            if (s_PickingInclude != null)\n            {\n                foreach (var o in s_PickingInclude)\n                    if (o.TryGetGameObject(out var go))\n                        s_PickingIncludeSet.Add(go);\n            }\n\n            if (s_PickingExclude != null)\n            {\n                foreach (var o in s_PickingExclude)\n                {\n                    if (o.TryGetGameObject(out var go))\n                    {\n                        if (s_PickingInclude != null)\n                            s_PickingIncludeSet.Remove(go);\n                        else\n                            s_PickingExcludeSet.Add(go);\n                    }\n                }\n            }\n\n            if (s_PickingInclude != null && s_PickingIncludeSet.Count == 0)\n                return false;\n\n            var nextPickingIndex = pickingIndex;\n            var renderPickingType = s_PickingInclude != null ? RenderPickingType.RenderFromFilterSet : RenderPickingType.RenderFromIgnoreSet;\n            var renderPickingObjectSet = s_PickingInclude != null ? s_PickingIncludeSet : s_PickingExcludeSet;\n            Debug.Assert(s_RenderPickingResults.Count == 0);\n            s_InPickingRendering = true;\n            bool needDepth = false;\n            try\n            {\n                var pickingBuffer = RenderTexture.active;\n                foreach (var cb in s_RenderPickingCallbacks)\n                {\n                    var result = cb(new RenderPickingArgs(nextPickingIndex, renderPickingType, renderPickingObjectSet));\n\n                    if (RenderTexture.active != pickingBuffer)\n                        RenderTexture.active = pickingBuffer;\n\n                    if (result.renderedPickingIndexCount <= 0\n                        || result.resolver == null && result.resolverWithWorldPos == null)\n                        continue;\n\n                    needDepth |= result.resolverWithWorldPos != null;\n                    s_RenderPickingResults.Add((nextPickingIndex, nextPickingIndex + result.renderedPickingIndexCount, result.resolver, result.resolverWithWorldPos));\n                    nextPickingIndex += result.renderedPickingIndexCount;\n                }\n            }\n            finally\n            {\n                s_InPickingRendering = false;\n            }\n\n            return needDepth;\n        }\n\n        [RequiredByNativeCode]\n        static int ResolvePickingObject(int pickingIndex, Vector3 worldPos, float depth)\n        {\n            foreach (var (begin, end, resolver, resolverWithWorldPos) in s_RenderPickingResults)\n            {\n                if (pickingIndex >= begin && pickingIndex < end)\n                {\n                    Debug.Assert((resolver == null) != (resolverWithWorldPos == null));\n                    var obj = resolver != null ? resolver(pickingIndex - begin) : resolverWithWorldPos(pickingIndex - begin, worldPos, depth);\n                    return obj != null ? obj.GetInstanceID() : 0;\n                }\n            }\n            return 0;\n        }\n\n        [RequiredByNativeCode]\n        static void CleanupPicking()\n        {\n            s_RenderPickingResults.Clear();\n        }\n\n        // Must match the logic in `ColorRGBA32 PickingEncodeIndex(UInt32 index)` in picking.cpp\n        public static Vector4 EncodeSelectionId(int pickingIndex)\n        {\n            uint index = (uint)pickingIndex;\n\n            return new Vector4(\n                (byte)(index & 0xFF),\n                (byte)((index >> 8) & 0xFF),\n                (byte)((index >> 16) & 0xFF),\n                (byte)((index >> 24) & 0xFF)) / 255.0f;\n        }\n\n        // Must match the inverse logic in `ColorRGBA32 PickingEncodeIndex(UInt32 index)` in picking.cpp\n        public static int DecodeSelectionId(Vector4 selectionId)\n        {\n            return (int)(selectionId.x * 255) +\n                  ((int)(selectionId.y * 255) << 8) +\n                  ((int)(selectionId.z * 255) << 16) +\n                  ((int)(selectionId.w * 255) << 24);\n        }\n\n        public static void GetOverlappingObjects(Vector2 position, List<UnityObject> outObjectList)\n        {\n            outObjectList.Clear();\n            foreach (var pobj in SceneViewPicking.GetAllOverlapping(position))\n                outObjectList.Add(pobj.target);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/Handles.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Internal;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    [Flags]\n    internal enum OutlineDrawMode\n    {\n        SelectionOutline = 1 << 0,\n        SelectionWire = 1 << 1,\n    }\n\n    [NativeHeader(\"Editor/Src/Handles/Handles.bindings.h\")]\n    public sealed partial class Handles\n    {\n        // Are handles lit?\n        [NativeProperty(\"handles::g_HandleLighting\", true, TargetType.Field)]\n        public static extern bool lighting { get; set; }\n\n        // Colors of the handles\n        [NativeProperty(\"handles::g_HandleColor\", true, TargetType.Field)]\n        public static extern Color color { get; set; }\n\n        // ZTest of the handles\n        [NativeProperty(\"handles::g_HandleZTest\", true, TargetType.Field)]\n        public static extern CompareFunction zTest { get; set; }\n\n        // Matrix for all handle operations\n        public static extern Matrix4x4 matrix\n        {\n            [FreeFunction(\"Internal_GetMatrix\")] get;\n            [FreeFunction(\"Internal_SetMatrix\")] set;\n        }\n\n        [NativeProperty(\"handles::g_HandleInverseMatrix\", true, TargetType.Field)]\n        public static extern Matrix4x4 inverseMatrix { get; }\n\n        [FreeFunction(\"handles::ClearHandles\")]\n        internal static extern void ClearHandles();\n\n        [FreeFunction(\"Internal_DrawGizmos\")]\n        internal static extern void Internal_DoDrawGizmos([NotNull] Camera camera);\n\n        [FreeFunction(\"Internal_IsCameraDrawModeSupported\")]\n        internal static extern bool IsCameraDrawModeSupported([NotNull] Camera camera, DrawCameraMode drawMode);\n\n        [FreeFunction(\"Internal_IsCameraDrawModeEnabled\")]\n        internal static extern bool IsCameraDrawModeEnabled([NotNull] Camera camera, DrawCameraMode drawMode);\n\n        [FreeFunction]\n        static extern void Internal_DrawCameraWithGrid([NotNull] Camera cam, DrawCameraMode renderMode, ref DrawGridParameters gridParam, bool drawGizmos, bool drawSelection);\n\n        [FreeFunction]\n        internal static extern void Internal_DrawOutline(Color parentNodeColor, Color childNodeColor, EntityId submeshOutlineMaterialId, EntityId[] parentRenderers, EntityId[] childRenderers, OutlineDrawMode outlineMode, float parentOutlineAlpha = 0, float childOutlineAlpha = 0);\n\n        [FreeFunction]\n        static extern void Internal_DrawCamera([NotNull] Camera cam, DrawCameraMode renderMode, bool drawGizmos, bool drawSelection);\n\n        [FreeFunction]\n        static extern void Internal_DrawCameraWithFilter([NotNull] Camera cam, DrawCameraMode renderMode, bool drawGizmos, bool drawSelection, GameObject[] filter);\n\n        [FreeFunction]\n        internal static extern void Internal_FinishDrawingCamera([NotNull] Camera cam, [DefaultValue(\"true\")] bool drawGizmos);\n        static void Internal_FinishDrawingCamera(Camera cam) { Internal_FinishDrawingCamera(cam, true); }\n\n        [FreeFunction]\n        static extern void Internal_ClearCamera([NotNull] Camera cam);\n\n        [FreeFunction]\n        internal static extern void Internal_SetCurrentCamera(Camera cam);\n\n        [FreeFunction(\"Internal_SetSceneViewColors\")]\n        internal static extern void SetSceneViewColors(Color wire, Color wireOverlay, Color selectedOutline, Color selectedChildrenOutline, Color selectedWire);\n\n        [FreeFunction(\"Internal_SetSceneViewModeGIContributorsReceiversColors\")]\n        internal static extern void SetSceneViewModeGIContributorsReceiversColors(Color noContributeGI, Color receiveGILightmaps, Color receiveGILightProbesColor);\n\n        [FreeFunction(\"Internal_EnableCameraFx\")]\n        internal static extern void EnableCameraFx([NotNull] Camera cam, bool fx);\n\n        [FreeFunction(\"Internal_EnableCameraFlares\")]\n        internal static extern void EnableCameraFlares([NotNull] Camera cam, bool flares);\n\n        [FreeFunction(\"Internal_EnableCameraSkybox\")]\n        internal static extern void EnableCameraSkybox([NotNull] Camera cam, bool skybox);\n\n        // Setup viewport and stuff for a current camera.\n        [FreeFunction]\n        static extern void Internal_SetupCamera([NotNull] Camera cam);\n\n        [FreeFunction]\n        static extern void Internal_DrawAAPolyLine(Color[] colors, Vector3[] points, Color defaultColor, int actualNumberOfPoints, Texture2D texture, float width, Matrix4x4 toWorld);\n\n        [FreeFunction]\n        static extern void Internal_DrawAAConvexPolygon(Vector3[] points, Color defaultColor, int actualNumberOfPoints, Matrix4x4 toWorld);\n\n        [FreeFunction]\n        static extern void Internal_DrawBezier(Vector3 startPosition, Vector3 endPosition, Vector3 startTangent, Vector3 endTangent, Color color, Texture2D texture, float width, Matrix4x4 toWorld);\n\n        [FreeFunction(\"Internal_SetDiscSectionPoints\")]\n        internal static extern void SetDiscSectionPoints(Vector3[] dest, Vector3 center, Vector3 normal, Vector3 from, float angle, float radius);\n\n        [FreeFunction(\"Internal_EmitGUIGeometryForCamera\")]\n        internal static extern void EmitGUIGeometryForCamera([NotNull] Camera source, Camera dest);\n\n        [FreeFunction(\"Internal_SetCameraFilterMode\")]\n        internal static extern void SetCameraFilterMode([NotNull] Camera camera, CameraFilterMode mode);\n\n        [FreeFunction(\"Internal_GetCameraFilterMode\")]\n        internal static extern CameraFilterMode GetCameraFilterMode([NotNull] Camera camera);\n\n        [FreeFunction(\"Internal_DrawCameraFade\")]\n        internal static extern void DrawCameraFade([NotNull] Camera camera, float fade);\n\n        [FreeFunction]\n        [return:Unmarshalled]\n        static extern Vector3[] Internal_MakeBezierPoints(Vector3 startPosition, Vector3 endPosition, Vector3 startTangent, Vector3 endTangent, int division);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/Handles.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Internal;\n\nnamespace UnityEditor\n{\n    // Grid drawing params for Handles.DrawCamera.\n    [StructLayout(LayoutKind.Sequential)]\n    struct DrawGridParameters\n    {\n        public int          gridID;\n        public Vector3      pivot;\n        public Color        color;\n        public Vector2      size;\n    }\n\n    public sealed partial class Handles\n    {\n        // Color of the X axis handle\n        internal static PrefColor s_XAxisColor = new PrefColor(\"Scene/X Axis\", 219f / 255, 62f / 255, 29f / 255, .93f);\n        public static Color xAxisColor { get { return s_XAxisColor; } }\n        // Color of the Y axis handle\n        internal static PrefColor s_YAxisColor = new PrefColor(\"Scene/Y Axis\", 154f / 255, 243f / 255, 72f / 255, .93f);\n        public static Color yAxisColor { get { return s_YAxisColor; } }\n        // Color of the Z axis handle\n        internal static PrefColor s_ZAxisColor = new PrefColor(\"Scene/Z Axis\", 58f / 255, 122f / 255, 248f / 255, .93f);\n        public static Color zAxisColor { get { return s_ZAxisColor; } }\n        // Color of the Constrain Proportions scale handles\n        internal static PrefColor constrainProportionsScaleHandleColor = new PrefColor(\"Scene/Constrain Proportions Scale Handle\", 190f / 255, 190f / 255, 190f / 255, 1f);\n        // Color of the center handle\n        internal static PrefColor s_CenterColor = new PrefColor(\"Scene/Center Axis\", .8f, .8f, .8f, .93f);\n        public static Color centerColor { get { return s_CenterColor; } }\n        // color for handles the currently active handle\n        internal static PrefColor s_SelectedColor = new PrefColor(\"Scene/Selected Axis\", 246f / 255, 242f / 255, 50f / 255, .89f);\n        public static Color selectedColor { get { return s_SelectedColor; } }\n        // color for handles the currently hovered handle\n        internal static PrefColor s_PreselectionColor = new PrefColor(\"Scene/Preselection Highlight\", 201f / 255, 200f / 255, 144f / 255, 0.89f);\n        public static Color preselectionColor { get { return s_PreselectionColor; } }\n        // soft color for general stuff - used to draw e.g. the arc selection while dragging\n        internal static PrefColor s_SecondaryColor = new PrefColor(\"Scene/Guide Line\", .5f, .5f, .5f, .2f);\n        public static Color secondaryColor { get { return s_SecondaryColor; } }\n        // internal color for static handles\n        internal static Color staticColor = new Color(.5f, .5f, .5f, 0f);\n        // internal blend ratio for static colors\n        internal static float staticBlend = 0.6f;\n\n        static PrefColor s_ElementColor => new PrefColor(\"Scene/Element Default\", 0f, 224f / 255f, 1f, 1f);\n        static PrefColor s_ElementPreselectionColor => new PrefColor(\"Scene/Element Preselection\", 1f, 207f / 255f, 112f / 255f, 1f);\n        static PrefColor s_ElementSelectionColor => new PrefColor(\"Scene/Element Selection\",  1f, 182f / 255f, 40f / 255f, 1f);\n\n        public static Color elementColor => s_ElementColor;\n        public static Color elementPreselectionColor => s_ElementPreselectionColor;\n        public static Color elementSelectionColor => s_ElementSelectionColor;\n\n        internal static float backfaceAlphaMultiplier = 0.2f;\n        internal static Color s_ColliderHandleColor = new Color(145f, 244f, 139f, 210f) / 255;\n        internal static Color s_ColliderHandleColorDisabled = new Color(84, 200f, 77f, 140f) / 255;\n        internal static Color s_BoundingBoxHandleColor = new Color(255, 255, 255, 150) / 255;\n\n        // Should match s_ColliderHandleColor to start unless the user overrides the color. As Gizmos are drawn from CPP there is no way currently to hook the ColliderHandleColor up properly.\n        public static Color UIColliderHandleColor { get { return s_UIColliderHandleColor; } }\n        internal static PrefColor s_UIColliderHandleColor = new PrefColor(\"Scene/UI Collider Handle\", 145f / 255, 244f / 255, 139f / 255, 210f / 255);\n\n        internal readonly static GUIContent s_StaticLabel = EditorGUIUtility.TrTextContent(\"Static\");\n        internal readonly static GUIContent s_PrefabLabel = EditorGUIUtility.TrTextContent(\"Prefab\");\n\n        internal static int s_SliderHash = \"SliderHash\".GetHashCode();\n        internal static int s_Slider2DHash = \"Slider2DHash\".GetHashCode();\n        internal static int s_FreeRotateHandleHash = \"FreeRotateHandleHash\".GetHashCode();\n        internal static int s_RadiusHandleHash = \"RadiusHandleHash\".GetHashCode();\n        internal static int s_xAxisMoveHandleHash  = \"xAxisFreeMoveHandleHash\".GetHashCode();\n        internal static int s_yAxisMoveHandleHash  = \"yAxisFreeMoveHandleHash\".GetHashCode();\n        internal static int s_zAxisMoveHandleHash  = \"zAxisFreeMoveHandleHash\".GetHashCode();\n        internal static int s_FreeMoveHandleHash  = \"FreeMoveHandleHash\".GetHashCode();\n        internal static int s_xzAxisMoveHandleHash = \"xzAxisFreeMoveHandleHash\".GetHashCode();\n        internal static int s_xyAxisMoveHandleHash = \"xyAxisFreeMoveHandleHash\".GetHashCode();\n        internal static int s_yzAxisMoveHandleHash = \"yzAxisFreeMoveHandleHash\".GetHashCode();\n        internal static int s_xAxisScaleHandleHash = \"xAxisScaleHandleHash\".GetHashCode();\n        internal static int s_yAxisScaleHandleHash = \"yAxisScaleHandleHash\".GetHashCode();\n        internal static int s_zAxisScaleHandleHash = \"zAxisScaleHandleHash\".GetHashCode();\n        internal static int s_ScaleSliderHash = \"ScaleSliderHash\".GetHashCode();\n        internal static int s_ScaleValueHandleHash = \"ScaleValueHandleHash\".GetHashCode();\n        internal static int s_DiscHash = \"DiscHash\".GetHashCode();\n        internal static int s_ButtonHash = \"ButtonHash\".GetHashCode();\n\n        static readonly int kPropUseGuiClip = Shader.PropertyToID(\"_UseGUIClip\");\n        static readonly int kPropHandleZTest = Shader.PropertyToID(\"_HandleZTest\");\n        static readonly int kPropColor = Shader.PropertyToID(\"_Color\");\n        static readonly int kPropArcCenterRadius = Shader.PropertyToID(\"_ArcCenterRadius\");\n        static readonly int kPropArcNormalAngle = Shader.PropertyToID(\"_ArcNormalAngle\");\n        static readonly int kPropArcFromCount = Shader.PropertyToID(\"_ArcFromCount\");\n        static readonly int kPropArcThicknessSides = Shader.PropertyToID(\"_ArcThicknessSides\");\n        static readonly int kPropHandlesMatrix = Shader.PropertyToID(\"_HandlesMatrix\");\n\n        public struct DrawingScope : IDisposable\n        {\n            private bool m_Disposed;\n\n            public Color originalColor { get { return m_OriginalColor; } }\n            private Color m_OriginalColor;\n\n            public Matrix4x4 originalMatrix { get { return m_OriginalMatrix; } }\n            private Matrix4x4 m_OriginalMatrix;\n\n            public DrawingScope(Color color) : this(color, Handles.matrix) {}\n\n            public DrawingScope(Matrix4x4 matrix) : this(Handles.color, matrix) {}\n\n            public DrawingScope(Color color, Matrix4x4 matrix)\n            {\n                m_Disposed = false;\n                m_OriginalColor = Handles.color;\n                m_OriginalMatrix = Handles.matrix;\n                Handles.matrix = matrix;\n                Handles.color = color;\n            }\n\n            public void Dispose()\n            {\n                if (m_Disposed)\n                    return;\n                m_Disposed = true;\n                Handles.color = m_OriginalColor;\n                Handles.matrix = m_OriginalMatrix;\n            }\n        }\n\n        internal static Mesh cubeMesh\n        {\n            get\n            {\n                if (s_CubeMesh == null)\n                    Init();\n                return s_CubeMesh;\n            }\n        }\n\n        internal static Mesh coneMesh\n        {\n            get\n            {\n                if (s_ConeMesh == null)\n                    Init();\n                return s_ConeMesh;\n            }\n        }\n\n        internal static Mesh cylinderMesh\n        {\n            get\n            {\n                if (s_CylinderMesh == null)\n                    Init();\n                return s_CylinderMesh;\n            }\n        }\n\n        internal static Mesh sphereMesh\n        {\n            get\n            {\n                if (s_SphereMesh == null)\n                    Init();\n                return s_SphereMesh;\n            }\n        }\n\n        internal static Mesh quadMesh\n        {\n            get\n            {\n                if (s_QuadMesh == null)\n                    Init();\n                return s_QuadMesh;\n            }\n        }\n\n        internal static int s_xRotateHandleHash = \"xRotateHandleHash\".GetHashCode();\n        internal static int s_yRotateHandleHash = \"yRotateHandleHash\".GetHashCode();\n        internal static int s_zRotateHandleHash = \"zRotateHandleHash\".GetHashCode();\n        internal static int s_cameraAxisRotateHandleHash = \"cameraAxisRotateHandleHash\".GetHashCode();\n        internal static int s_xyzRotateHandleHash = \"xyzRotateHandleHash\".GetHashCode();\n        internal static int s_xScaleHandleHash = \"xScaleHandleHash\".GetHashCode();\n        internal static int s_yScaleHandleHash = \"yScaleHandleHash\".GetHashCode();\n        internal static int s_zScaleHandleHash = \"zScaleHandleHash\".GetHashCode();\n        internal static int s_xyzScaleHandleHash = \"xyzScaleHandleHash\".GetHashCode();\n\n        private static Color lineTransparency = new Color(1, 1, 1, 0.75f);\n\n        internal static SavedFloat s_LineThickness = new SavedFloat(\"SceneView.handleLineThickness\", 2.0f);\n        public static float lineThickness => s_LineThickness.value;\n\n        // When hovering over some handle axis/control, this is the indication that it would\n        // get picked on mouse press:\n        // Color gets a bit more bright and less opaque,\n        internal static Color s_HoverIntensity = new Color(1.0f, 1.0f, 1.0f, 1.33f);\n        // Handle lines get more thick,\n        internal static float s_HoverExtraThickness = 1.0f;\n        // 3D handle elements (caps) get slightly larger.\n        internal static float s_HoverExtraScale = 1.05f;\n\n        // When axis is looking away from camera, fade it out along 25 -> 15 degrees range\n        static readonly float kCameraViewLerpStart1 = Mathf.Cos(Mathf.Deg2Rad * 25.0f);\n        static readonly float kCameraViewLerpEnd1 = Mathf.Cos(Mathf.Deg2Rad * 15.0f);\n        // When axis is looking towards the camera, fade it out along 170 -> 175 degrees range\n        static readonly float kCameraViewLerpStart2 = Mathf.Cos(Mathf.Deg2Rad * 170.0f);\n        static readonly float kCameraViewLerpEnd2 = Mathf.Cos(Mathf.Deg2Rad * 175.0f);\n\n        // Hide & disable axis if they have faded out more than 60%\n        internal const float kCameraViewThreshold = 0.6f;\n\n        // The function for calling AddControl in Layout event and draw the handle in Repaint event.\n        public delegate void CapFunction(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType);\n\n        public delegate float SizeFunction(Vector3 position);\n\n        static PrefColor[] s_AxisColor = { s_XAxisColor, s_YAxisColor, s_ZAxisColor };\n        static Vector3[] s_AxisVector = { Vector3.right, Vector3.up, Vector3.forward };\n\n        internal static Color s_DisabledHandleColor = new Color(0.5f, 0.5f, 0.5f, 0.5f);\n\n        internal static Color GetColorByAxis(int axis)\n        {\n            return s_AxisColor[axis];\n        }\n\n        internal static Color ToActiveColorSpace(Color color)\n        {\n            return (QualitySettings.activeColorSpace == ColorSpace.Linear) ? color.linear : color;\n        }\n\n        static Vector3 GetAxisVector(int axis)\n        {\n            return s_AxisVector[axis];\n        }\n\n        internal static bool IsHovering(int controlID, Event evt)\n        {\n            // If the mouse position is over an overlay, return false since we don't want to indicate interactivity with any handles.\n            if (SceneView.lastActiveSceneView == null || SceneView.lastActiveSceneView.sceneViewMotion == null)\n                return false;\n            if (!SceneView.lastActiveSceneView.sceneViewMotion.viewportsUnderMouse)\n                return false;\n\n            return controlID == HandleUtility.nearestControl && GUIUtility.hotControl == 0 && !Tools.viewToolActive;\n        }\n\n        static internal void SetupHandleColor(int controlID, Event evt, out Color prevColor, out float thickness)\n        {\n            prevColor = Handles.color;\n            thickness = Handles.lineThickness;\n            if (controlID == GUIUtility.hotControl)\n            {\n                Handles.color = Handles.selectedColor;\n            }\n            else if (IsHovering(controlID, evt))\n            {\n                var col = Handles.color * s_HoverIntensity;\n                // make sure colors never go outside of 0..1 range\n                col.r = Mathf.Clamp01(col.r);\n                col.g = Mathf.Clamp01(col.g);\n                col.b = Mathf.Clamp01(col.b);\n                col.a = Mathf.Clamp01(col.a);\n                Handles.color = col;\n                thickness += s_HoverExtraThickness;\n            }\n        }\n\n        static void Swap(ref Vector3 v, int[] indices, int a, int b)\n        {\n            var f = v[a];\n            v[a] = v[b];\n            v[b] = f;\n\n            var t = indices[a];\n            indices[a] = indices[b];\n            indices[b] = t;\n        }\n\n        // Given view direction in handle space, calculate\n        // back-to-front order in which handle axes should be drawn.\n        // The array should be [3] size, and will contain axis indices\n        // from (0,1,2) set.\n        static void CalcDrawOrder(Vector3 viewDir, int[] ordering)\n        {\n            ordering[0] = 0;\n            ordering[1] = 1;\n            ordering[2] = 2;\n            // essentially an unrolled bubble sort for 3 elements\n            if (viewDir.y > viewDir.x) Swap(ref viewDir, ordering, 1, 0);\n            if (viewDir.z > viewDir.y) Swap(ref viewDir, ordering, 2, 1);\n            if (viewDir.y > viewDir.x) Swap(ref viewDir, ordering, 1, 0);\n        }\n\n        private static bool BeginLineDrawing(Matrix4x4 matrix, bool dottedLines, int mode)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return false;\n\n            Color col = color * lineTransparency;\n            if (dottedLines)\n                HandleUtility.ApplyDottedWireMaterial(zTest);\n            else\n                HandleUtility.ApplyWireMaterial(zTest);\n            GL.PushMatrix();\n            GL.MultMatrix(matrix);\n            GL.Begin(mode);\n            GL.Color(col);\n            return true;\n        }\n\n        private static void EndLineDrawing()\n        {\n            GL.End();\n            GL.PopMatrix();\n        }\n\n        public static void DrawPolyLine(params Vector3[] points)\n        {\n            if (!BeginLineDrawing(matrix, false, GL.LINE_STRIP))\n                return;\n            for (int i = 0; i < points.Length; i++)\n            {\n                GL.Vertex(points[i]);\n            }\n            EndLineDrawing();\n        }\n\n        [ExcludeFromDocs]\n        public static void DrawLine(Vector3 p1, Vector3 p2)\n        {\n            DrawLine(p1, p2, false);\n        }\n\n        internal static void DrawLine(Vector3 p1, Vector3 p2, bool dottedLine)\n        {\n            if (!BeginLineDrawing(matrix, dottedLine, GL.LINES))\n                return;\n            GL.Vertex(p1);\n            GL.Vertex(p2);\n            EndLineDrawing();\n        }\n\n        static float ThicknessToPixels(float thickness)\n        {\n            var halfThicknessPixels = thickness * EditorGUIUtility.pixelsPerPoint * 0.5f;\n            if (halfThicknessPixels < 0.9f)\n                halfThicknessPixels = 0;\n            return halfThicknessPixels;\n        }\n\n        public static void DrawLine(Vector3 p1, Vector3 p2, [DefaultValue(\"0.0f\")] float thickness)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n            thickness = ThicknessToPixels(thickness);\n            if (thickness <= 0)\n            {\n                DrawLine(p1, p2);\n                return;\n            }\n\n            var mat = SetupArcMaterial();\n            if (mat == null) // can't do thick lines\n            {\n                DrawLine(p1, p2);\n                return;\n            }\n            mat.SetVector(kPropArcCenterRadius, new Vector4(p1.x, p1.y, p1.z, 0));\n            mat.SetVector(kPropArcFromCount, new Vector4(p2.x, p2.y, p2.z, 0));\n            mat.SetVector(kPropArcThicknessSides, new Vector4(thickness, kArcSides, 0, 0));\n            mat.SetPass(1);\n\n            var indexBuffer = HandleUtility.GetArcIndexBuffer(kArcSegments, kArcSides);\n            Graphics.DrawProceduralNow(MeshTopology.Triangles, indexBuffer, kArcSides * 6);\n        }\n\n        public static void DrawLines(Vector3[] lineSegments)\n        {\n            if (!BeginLineDrawing(matrix, false, GL.LINES))\n                return;\n            try\n            {\n                for (int i = 0; i < lineSegments.Length; i += 2)\n                {\n                    var p1 = lineSegments[i + 0];\n                    var p2 = lineSegments[i + 1];\n                    GL.Vertex(p1);\n                    GL.Vertex(p2);\n                }\n            }\n            finally\n            {\n                EndLineDrawing();\n            }\n        }\n\n        public static void DrawLines(Vector3[] points, int[] segmentIndices)\n        {\n            if (!BeginLineDrawing(matrix, false, GL.LINES))\n                return;\n            try\n            {\n                for (int i = 0; i < segmentIndices.Length; i += 2)\n                {\n                    var p1 = points[segmentIndices[i + 0]];\n                    var p2 = points[segmentIndices[i + 1]];\n                    GL.Vertex(p1);\n                    GL.Vertex(p2);\n                }\n            }\n            finally\n            {\n                EndLineDrawing();\n            }\n        }\n\n        public static void DrawDottedLine(Vector3 p1, Vector3 p2, float screenSpaceSize)\n        {\n            if (!BeginLineDrawing(matrix, true, GL.LINES))\n                return;\n            var dashSize = screenSpaceSize * EditorGUIUtility.pixelsPerPoint;\n            GL.MultiTexCoord(1, p1); GL.MultiTexCoord2(2, dashSize, 0); GL.Vertex(p1);\n            GL.MultiTexCoord(1, p1); GL.MultiTexCoord2(2, dashSize, 0); GL.Vertex(p2);\n            EndLineDrawing();\n        }\n\n        public static void DrawDottedLines(Vector3[] lineSegments, float screenSpaceSize)\n        {\n            if (!BeginLineDrawing(matrix, true, GL.LINES))\n                return;\n            var dashSize = screenSpaceSize * EditorGUIUtility.pixelsPerPoint;\n            try\n            {\n                for (int i = 0; i < lineSegments.Length; i += 2)\n                {\n                    var p1 = lineSegments[i + 0];\n                    var p2 = lineSegments[i + 1];\n                    GL.MultiTexCoord(1, p1); GL.MultiTexCoord2(2, dashSize, 0); GL.Vertex(p1);\n                    GL.MultiTexCoord(1, p1); GL.MultiTexCoord2(2, dashSize, 0); GL.Vertex(p2);\n                }\n            }\n            finally\n            {\n                EndLineDrawing();\n            }\n        }\n\n        public static void DrawDottedLines(Vector3[] points, int[] segmentIndices, float screenSpaceSize)\n        {\n            if (!BeginLineDrawing(matrix, true, GL.LINES))\n                return;\n            var dashSize = screenSpaceSize * EditorGUIUtility.pixelsPerPoint;\n            try\n            {\n                for (int i = 0; i < segmentIndices.Length; i += 2)\n                {\n                    var p1 = points[segmentIndices[i + 0]];\n                    var p2 = points[segmentIndices[i + 1]];\n                    GL.MultiTexCoord(1, p1); GL.MultiTexCoord2(2, dashSize, 0); GL.Vertex(p1);\n                    GL.MultiTexCoord(1, p1); GL.MultiTexCoord2(2, dashSize, 0); GL.Vertex(p2);\n                }\n            }\n            finally\n            {\n                EndLineDrawing();\n            }\n        }\n\n        public static void DrawWireCube(Vector3 center, Vector3 size)\n        {\n            if (Event.current.type != EventType.Repaint || lineTransparency.a <= 0)\n                return;\n\n            HandleUtility.ApplyWireMaterial(zTest);\n            GL.PushMatrix();\n            GL.MultMatrix(matrix);\n\n            GL.Begin(GL.LINE_STRIP);\n            GL.Color(color * lineTransparency);\n            Vector3 p1, p2, p3, p6, p7, p8;\n            {\n                Vector3 halfsize = size * 0.5f;\n                GL.Vertex(center + new Vector3(-halfsize.x, -halfsize.y, -halfsize.z));\n                p1 = center + new Vector3(-halfsize.x, halfsize.y, -halfsize.z);\n                GL.Vertex(p1);\n                p2 = center + new Vector3(halfsize.x, halfsize.y, -halfsize.z);\n                GL.Vertex(p2);\n                p3 = center + new Vector3(halfsize.x, -halfsize.y, -halfsize.z);\n                GL.Vertex(p3);\n                GL.Vertex(center + new Vector3(-halfsize.x, -halfsize.y, -halfsize.z));\n                GL.Vertex(center + new Vector3(-halfsize.x, -halfsize.y, halfsize.z));\n\n                p6 = center + new Vector3(-halfsize.x, halfsize.y, halfsize.z);\n                GL.Vertex(p6);\n                p7 = center + new Vector3(halfsize.x, halfsize.y, halfsize.z);\n                GL.Vertex(p7);\n                p8 = center + new Vector3(halfsize.x, -halfsize.y, halfsize.z);\n                GL.Vertex(p8);\n                GL.Vertex(center + new Vector3(-halfsize.x, -halfsize.y, halfsize.z));\n            }\n            GL.End();\n            GL.Begin(GL.LINES);\n            GL.Color(color * lineTransparency);\n            GL.Vertex(p1);\n            GL.Vertex(p6);\n            GL.Vertex(p2);\n            GL.Vertex(p7);\n            GL.Vertex(p3);\n            GL.Vertex(p8);\n            GL.End();\n\n            GL.PopMatrix();\n        }\n\n        public static bool ShouldRenderGizmos()\n        {\n            var playModeView = PlayModeView.GetRenderingView();\n            SceneView sv = SceneView.currentDrawingSceneView;\n\n            if (playModeView != null)\n                return playModeView.IsShowingGizmos();\n\n            if (sv != null)\n                return sv.drawGizmos;\n\n            return false;\n        }\n\n        public static void DrawGizmos(Camera camera)\n        {\n            if (ShouldRenderGizmos())\n                Internal_DoDrawGizmos(camera);\n        }\n\n        // Make a 3D slider\n        public static Vector3 Slider(Vector3 position, Vector3 direction)\n        {\n            return Slider(position, direction, HandleUtility.GetHandleSize(position), ArrowHandleCap, -1);\n        }\n\n        public static Vector3 Slider(Vector3 position, Vector3 direction, float size, CapFunction capFunction, float snap)\n        {\n            int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Passive);\n            return UnityEditorInternal.Slider1D.Do(id, position, direction, size, capFunction, snap);\n        }\n\n        public static Vector3 Slider(int controlID, Vector3 position, Vector3 direction, float size, CapFunction capFunction, float snap)\n        {\n            return UnityEditorInternal.Slider1D.Do(controlID, position, direction, size, capFunction, snap);\n        }\n\n        public static Vector3 Slider(int controlID, Vector3 position, Vector3 offset, Vector3 direction, float size, CapFunction capFunction, float snap)\n        {\n            return UnityEditorInternal.Slider1D.Do(controlID, position, offset, direction, direction, size, capFunction, snap);\n        }\n\n        [Obsolete(\"Rotation parameter is obsolete. (UnityUpgradable) -> !1\")]\n        public static Vector3 FreeMoveHandle(Vector3 position, Quaternion rotation, float size, Vector3 snap, CapFunction capFunction)\n        {\n            int id = GUIUtility.GetControlID(s_FreeMoveHandleHash, FocusType.Passive);\n            return UnityEditorInternal.FreeMove.Do(id, position, rotation, size, snap, capFunction);\n        }\n\n        [Obsolete(\"Rotation parameter is obsolete. (UnityUpgradable) -> !2\")]\n        public static Vector3 FreeMoveHandle(int controlID, Vector3 position, Quaternion rotation, float size, Vector3 snap, CapFunction capFunction)\n        {\n            return UnityEditorInternal.FreeMove.Do(controlID, position, rotation, size, snap, capFunction);\n        }\n\n        public static Vector3 FreeMoveHandle(Vector3 position, float size, Vector3 snap, CapFunction capFunction)\n        {\n            int id = GUIUtility.GetControlID(s_FreeMoveHandleHash, FocusType.Passive);\n            return UnityEditorInternal.FreeMove.Do(id, position, size, snap, capFunction);\n        }\n\n        public static Vector3 FreeMoveHandle(int controlID, Vector3 position, float size, Vector3 snap, CapFunction capFunction)\n        {\n            return UnityEditorInternal.FreeMove.Do(controlID, position, size, snap, capFunction);\n        }\n\n        // Make a single-float draggable handle.\n        public static float ScaleValueHandle(float value, Vector3 position, Quaternion rotation, float size, CapFunction capFunction, float snap)\n        {\n            int id = GUIUtility.GetControlID(s_ScaleValueHandleHash, FocusType.Passive);\n            return UnityEditorInternal.SliderScale.DoCenter(id, value, position, rotation, size, capFunction, snap);\n        }\n\n        public static float ScaleValueHandle(int controlID, float value, Vector3 position, Quaternion rotation, float size, CapFunction capFunction, float snap)\n        {\n            return UnityEditorInternal.SliderScale.DoCenter(controlID, value, position, rotation, size, capFunction, snap);\n        }\n\n        // Make a 3D Button.\n        public static bool Button(Vector3 position, Quaternion direction, float size, float pickSize, CapFunction capFunction)\n        {\n            int id = GUIUtility.GetControlID(s_ButtonHash, FocusType.Passive);\n            return UnityEditorInternal.Button.Do(id, position, direction, size, pickSize, capFunction);\n        }\n\n        internal static bool Button(int controlID, Vector3 position, Quaternion direction, float size, float pickSize, CapFunction capFunction)\n        {\n            return UnityEditorInternal.Button.Do(controlID, position, direction, size, pickSize, capFunction);\n        }\n\n        internal static bool Button(int controlID, Vector3 position, Quaternion direction, float size, float pickSize, CapFunction capFunction, bool checkMouseProximity)\n        {\n            return UnityEditorInternal.Button.Do(controlID, position, direction, size, pickSize, capFunction, checkMouseProximity);\n        }\n\n        // Draw a cube. Pass this into handle functions.\n        public static void CubeHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)\n        {\n            switch (eventType)\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    HandleUtility.AddControl(controlID, HandleUtility.DistanceToCube(position, rotation, size));\n                    break;\n                case (EventType.Repaint):\n                    Graphics.DrawMeshNow(cubeMesh, StartCapDraw(position, rotation, size));\n                    break;\n            }\n        }\n\n        // Draw a Sphere. Pass this into handle functions.\n        public static void SphereHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)\n        {\n            switch (eventType)\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    // TODO: Create DistanceToCube\n                    HandleUtility.AddControl(controlID, HandleUtility.DistanceToCircle(position, size));\n                    break;\n                case (EventType.Repaint):\n                    Graphics.DrawMeshNow(sphereMesh, StartCapDraw(position, rotation, size));\n                    break;\n            }\n        }\n\n        // Draw a Cone. Pass this into handle functions.\n        public static void ConeHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)\n        {\n            switch (eventType)\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    HandleUtility.AddControl(controlID, HandleUtility.DistanceToCone(position, rotation, size));\n                    break;\n                case EventType.Repaint:\n                    Graphics.DrawMeshNow(coneMesh, StartCapDraw(position, rotation, size));\n                    break;\n            }\n        }\n\n        // Draw a Cylinder. Pass this into handle functions.\n        public static void CylinderHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)\n        {\n            switch (eventType)\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    // TODO: Create DistanceToCylinder\n                    HandleUtility.AddControl(controlID, HandleUtility.DistanceToCircle(position, size));\n                    break;\n                case (EventType.Repaint):\n                    Graphics.DrawMeshNow(cylinderMesh, StartCapDraw(position, rotation, size));\n                    break;\n            }\n        }\n\n        // Draw a camera-facing Rectangle. Pass this into handle functions.\n        static Vector3[] s_RectangleHandlePointsCache = new Vector3[5];\n        public static void RectangleHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)\n        {\n            RectangleHandleCap(controlID, position, rotation, new Vector2(size, size), eventType);\n        }\n\n        public static void RectangleHandleCap(int controlID, Vector3 position, Quaternion rotation, Vector2 size, EventType eventType)\n        {\n            switch (eventType)\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    // TODO: Create DistanceToRectangle\n                    HandleUtility.AddControl(controlID, HandleUtility.DistanceToRectangleInternal(position, rotation, size));\n                    break;\n                case (EventType.Repaint):\n                    Vector3 sideways = rotation * new Vector3(size.x, 0, 0);\n                    Vector3 up = rotation * new Vector3(0, size.y, 0);\n                    s_RectangleHandlePointsCache[0] = position + sideways + up;\n                    s_RectangleHandlePointsCache[1] = position + sideways - up;\n                    s_RectangleHandlePointsCache[2] = position - sideways - up;\n                    s_RectangleHandlePointsCache[3] = position - sideways + up;\n                    s_RectangleHandlePointsCache[4] = position + sideways + up;\n                    Handles.DrawPolyLine(s_RectangleHandlePointsCache);\n                    break;\n            }\n        }\n\n        internal static void RectangleHandleCapWorldSpace(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)\n        {\n            RectangleHandleCapWorldSpace(controlID, position, rotation, new Vector2(size, size), eventType);\n        }\n\n        internal static void RectangleHandleCapWorldSpace(int controlID, Vector3 position, Quaternion rotation, Vector2 size, EventType eventType)\n        {\n            switch (eventType)\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    HandleUtility.AddControl(controlID, HandleUtility.DistanceToRectangleInternalWorldSpace(position, rotation, size));\n                    break;\n                case (EventType.Repaint):\n                    Vector3 sideways = rotation * new Vector3(size.x, 0, 0);\n                    Vector3 up = rotation * new Vector3(0, size.y, 0);\n                    s_RectangleHandlePointsCache[0] = position + sideways + up;\n                    s_RectangleHandlePointsCache[1] = position + sideways - up;\n                    s_RectangleHandlePointsCache[2] = position - sideways - up;\n                    s_RectangleHandlePointsCache[3] = position - sideways + up;\n                    s_RectangleHandlePointsCache[4] = position + sideways + up;\n                    Handles.DrawPolyLine(s_RectangleHandlePointsCache);\n                    break;\n            }\n        }\n\n        // Draw a camera-facing dot. Pass this into handle functions.\n        public static void DotHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)\n        {\n            switch (eventType)\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    HandleUtility.AddControl(controlID, HandleUtility.DistanceToRectangle(position, rotation, size));\n                    break;\n                case (EventType.Repaint):\n                    // Only apply matrix to the position because DotCap is camera facing\n                    position = matrix.MultiplyPoint(position);\n\n                    Vector3 sideways = (Camera.current == null ? Vector3.right : Camera.current.transform.right) * size;\n                    Vector3 up = (Camera.current == null ? Vector3.up : Camera.current.transform.up) * size;\n\n                    Color col = color * new Color(1, 1, 1, 0.99f);\n                    HandleUtility.ApplyWireMaterial(Handles.zTest);\n                    GL.Begin(GL.QUADS);\n                    GL.Color(col);\n                    GL.Vertex(position + sideways + up);\n                    GL.Vertex(position + sideways - up);\n                    GL.Vertex(position - sideways - up);\n                    GL.Vertex(position - sideways + up);\n                    GL.End();\n                    break;\n            }\n        }\n\n        // Draw a camera-facing Circle. Pass this into handle functions.\n        public static void CircleHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)\n        {\n            switch (eventType)\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    HandleUtility.AddControl(controlID, HandleUtility.DistanceToRectangle(position, rotation, size));\n                    break;\n                case (EventType.Repaint):\n                    StartCapDraw(position, rotation, size);\n                    Vector3 forward = rotation * new Vector3(0, 0, 1);\n                    Handles.DrawWireDisc(position, forward, size);\n                    break;\n            }\n        }\n\n        // Draw an arrow like those used by the move tool.\n        public static void ArrowHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)\n        {\n            ArrowHandleCap(controlID, position, rotation, size, eventType, Vector3.zero);\n        }\n\n        internal static void ArrowHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType, Vector3 coneOffset)\n        {\n            switch (eventType)\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                {\n                    Vector3 direction = rotation * Vector3.forward;\n                    HandleUtility.AddControl(controlID, HandleUtility.DistanceToLine(position, position + (direction + coneOffset) * (size * .9f)));\n                    HandleUtility.AddControl(controlID, HandleUtility.DistanceToCone(position + (direction + coneOffset) * size, rotation, size * .2f));\n                    break;\n                }\n                case EventType.Repaint:\n                {\n                    Vector3 direction = rotation * Vector3.forward;\n                    float thickness = Handles.lineThickness;\n                    float coneSize = size * .2f;\n                    if (IsHovering(controlID, Event.current))\n                    {\n                        thickness += s_HoverExtraThickness;\n                        coneSize *= s_HoverExtraScale;\n                    }\n                    var camera = Camera.current;\n                    var viewDir = camera != null ? camera.transform.forward : -direction;\n                    var facingAway = Vector3.Dot(viewDir, direction) < 0.0f;\n                    var conePos = position + (direction + coneOffset) * size;\n                    var linePos = position + (direction + coneOffset) * (size * .9f);\n                    // draw line vs cone in the appropriate order based on viewing\n                    // direction, for correct transparency sorting\n                    if (facingAway)\n                    {\n                        DrawLine(position, linePos, thickness);\n                        ConeHandleCap(controlID, conePos, rotation, coneSize, eventType);\n                    }\n                    else\n                    {\n                        ConeHandleCap(controlID, conePos, rotation, coneSize, eventType);\n                        DrawLine(position, linePos, thickness);\n                    }\n                    break;\n                }\n            }\n        }\n\n        // Draw a camera facing selection frame.\n        public static void DrawSelectionFrame(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)\n        {\n            if (eventType != EventType.Repaint)\n                return;\n\n            Handles.StartCapDraw(position, rotation, size);\n            Vector3 sideways = rotation * new Vector3(size, 0, 0);\n            Vector3 up = rotation * new Vector3(0, size, 0);\n\n            var point1 = position - sideways + up;\n            var point2 = position + sideways + up;\n            var point3 = position + sideways - up;\n            var point4 = position - sideways - up;\n\n            Handles.DrawLine(point1, point2);\n            Handles.DrawLine(point2, point3);\n            Handles.DrawLine(point3, point4);\n            Handles.DrawLine(point4, point1);\n        }\n\n        internal static Color GetFadedAxisColor(Color col, float fade, int id)\n        {\n            // never fade out axes that are being hover-highlighted or currently interacted with\n            if (id != 0 && id == GUIUtility.hotControl || id == HandleUtility.nearestControl)\n                fade = 0;\n            col = Color.Lerp(col, Color.clear, fade);\n            return col;\n        }\n\n        internal static float GetCameraViewLerpForWorldAxis(Vector3 viewVector, Vector3 axis)\n        {\n            var dot = Vector3.Dot(viewVector, axis);\n            var l1 = Mathf.InverseLerp(kCameraViewLerpStart1, kCameraViewLerpEnd1, dot);\n            var l2 = Mathf.InverseLerp(kCameraViewLerpStart2, kCameraViewLerpEnd2, dot);\n            return Mathf.Max(l1, l2);\n        }\n\n        internal static Vector3 GetCameraViewFrom(Vector3 position, Matrix4x4 matrix)\n        {\n            Camera camera = Camera.current;\n            return camera.orthographic\n                ? matrix.MultiplyVector(camera.transform.forward).normalized\n                : matrix.MultiplyVector(position - camera.transform.position).normalized;\n        }\n\n        // Make a 3D Scene view position handle.\n        public static Vector3 PositionHandle(Vector3 position, Quaternion rotation)\n        {\n            return DoPositionHandle(position, rotation);\n        }\n\n        public static Vector3 PositionHandle(PositionHandleIds ids, Vector3 position, Quaternion rotation)\n        {\n            return DoPositionHandle(ids, position, rotation);\n        }\n\n        // Make a Scene view rotation handle.\n        public static Quaternion RotationHandle(Quaternion rotation, Vector3 position)\n        {\n            return DoRotationHandle(rotation, position);\n        }\n\n        public static Quaternion RotationHandle(RotationHandleIds ids, Quaternion rotation, Vector3 position)\n        {\n            return DoRotationHandle(ids, rotation, position, RotationHandleParam.Default);\n        }\n\n\n        // Make a Scene view scale handle\n        public static Vector3 ScaleHandle(Vector3 scale, Vector3 position, Quaternion rotation)\n        {\n            return DoScaleHandle(scale, position, rotation, HandleUtility.GetHandleSize(position));\n        }\n\n        // Make a Scene view scale handle\n        public static Vector3 ScaleHandle(Vector3 scale, Vector3 position, Quaternion rotation, float size)\n        {\n            return DoScaleHandle(scale, position, rotation, size, false);\n        }\n\n        internal static Vector3 ScaleHandle(Vector3 scale, Vector3 position, Quaternion rotation, float size, bool isProportionalScale)\n        {\n            return DoScaleHandle(scale, position, rotation, size, isProportionalScale);\n        }\n\n        ///*listonly*\n        public static float RadiusHandle(Quaternion rotation, Vector3 position, float radius, bool handlesOnly)\n        {\n            return DoRadiusHandle(rotation, position, radius, handlesOnly);\n        }\n\n        // Make a Scene view radius handle\n        public static float RadiusHandle(Quaternion rotation, Vector3 position, float radius)\n        {\n            return DoRadiusHandle(rotation, position, radius, false);\n        }\n\n        // Make a Scene View cone handle\n        internal static Vector2 ConeHandle(Quaternion rotation, Vector3 position, Vector2 angleAndRange, float angleScale, float rangeScale, bool handlesOnly)\n        {\n            return DoConeHandle(rotation, position, angleAndRange, angleScale, rangeScale, handlesOnly);\n        }\n\n        // Make a Scene View cone frustrum handle\n        internal static Vector3 ConeFrustrumHandle(Quaternion rotation, Vector3 position, Vector3 radiusAngleRange, ConeHandles showHandles = ConeHandles.All)\n        {\n            return DoConeFrustrumHandle(rotation, position, radiusAngleRange, showHandles);\n        }\n\n        // Slide a handle in a 2D plane\n        public static Vector3 Slider2D(int id, Vector3 handlePos, Vector3 offset, Vector3 handleDir, Vector3 slideDir1, Vector3 slideDir2, float handleSize, CapFunction capFunction, Vector2 snap)\n        {\n            return Slider2D(id, handlePos, offset, handleDir, slideDir1, slideDir2, handleSize, capFunction, snap, false);\n        }\n\n        public static Vector3 Slider2D(int id, Vector3 handlePos, Vector3 offset, Vector3 handleDir, Vector3 slideDir1, Vector3 slideDir2, float handleSize, CapFunction capFunction, Vector2 snap, [DefaultValue(\"false\")] bool drawHelper)\n        {\n            return UnityEditorInternal.Slider2D.Do(id, handlePos, offset, handleDir, slideDir1, slideDir2, handleSize, capFunction, snap, drawHelper);\n        }\n\n        /// *listonly*\n        public static Vector3 Slider2D(Vector3 handlePos, Vector3 handleDir, Vector3 slideDir1, Vector3 slideDir2, float handleSize, CapFunction capFunction, Vector2 snap)\n        {\n            return Slider2D(handlePos, handleDir, slideDir1, slideDir2, handleSize, capFunction, snap, false);\n        }\n\n        public static Vector3 Slider2D(Vector3 handlePos, Vector3 handleDir, Vector3 slideDir1, Vector3 slideDir2, float handleSize, CapFunction capFunction, Vector2 snap, [DefaultValue(\"false\")] bool drawHelper)\n        {\n            int id = GUIUtility.GetControlID(s_Slider2DHash, FocusType.Passive);\n            return UnityEditorInternal.Slider2D.Do(id, handlePos, new Vector3(0, 0, 0), handleDir, slideDir1, slideDir2, handleSize, capFunction, snap, drawHelper);\n        }\n\n        /// *listonly*\n        public static Vector3 Slider2D(int id, Vector3 handlePos, Vector3 handleDir, Vector3 slideDir1, Vector3 slideDir2, float handleSize, CapFunction capFunction, Vector2 snap)\n        {\n            return Slider2D(id, handlePos, handleDir, slideDir1, slideDir2, handleSize, capFunction, snap, false);\n        }\n\n        public static Vector3 Slider2D(int id, Vector3 handlePos, Vector3 handleDir, Vector3 slideDir1, Vector3 slideDir2, float handleSize, CapFunction capFunction, Vector2 snap, [DefaultValue(\"false\")] bool drawHelper)\n        {\n            return UnityEditorInternal.Slider2D.Do(id, handlePos, new Vector3(0, 0, 0), handleDir, slideDir1, slideDir2, handleSize, capFunction, snap, drawHelper);\n        }\n\n        /// *listonly*\n        public static Vector3 Slider2D(Vector3 handlePos, Vector3 handleDir, Vector3 slideDir1, Vector3 slideDir2, float handleSize, CapFunction capFunction, float snap)\n        {\n            return Slider2D(handlePos, handleDir, slideDir1, slideDir2, handleSize, capFunction, snap, false);\n        }\n\n        public static Vector3 Slider2D(Vector3 handlePos, Vector3 handleDir, Vector3 slideDir1, Vector3 slideDir2, float handleSize, CapFunction capFunction, float snap, [DefaultValue(\"false\")] bool drawHelper)\n        {\n            int id = GUIUtility.GetControlID(s_Slider2DHash, FocusType.Passive);\n            return Slider2D(id, handlePos, new Vector3(0, 0, 0), handleDir, slideDir1, slideDir2, handleSize, capFunction, new Vector2(snap, snap), drawHelper);\n        }\n\n        // Make an unconstrained rotation handle.\n        public static Quaternion FreeRotateHandle(int id, Quaternion rotation, Vector3 position, float size)\n        {\n            return UnityEditorInternal.FreeRotate.Do(id, rotation, position, size);\n        }\n\n        public static Quaternion FreeRotateHandle(Quaternion rotation, Vector3 position, float size)\n        {\n            int id = GUIUtility.GetControlID(s_FreeRotateHandleHash, FocusType.Passive);\n            return UnityEditorInternal.FreeRotate.Do(id, rotation, position, size);\n        }\n\n        // Make a directional scale slider\n        public static float ScaleSlider(int id, float scale, Vector3 position, Vector3 direction, Quaternion rotation, float size, float snap)\n        {\n            return UnityEditorInternal.SliderScale.DoAxis(id, scale, position, direction, rotation, size, snap);\n        }\n\n        public static float ScaleSlider(float scale, Vector3 position, Vector3 direction, Quaternion rotation, float size, float snap)\n        {\n            int id = GUIUtility.GetControlID(s_ScaleSliderHash, FocusType.Passive);\n            return UnityEditorInternal.SliderScale.DoAxis(id, scale, position, direction, rotation, size, snap);\n        }\n\n        // Make a 3D disc that can be dragged with the mouse\n        public static Quaternion Disc(int id, Quaternion rotation, Vector3 position, Vector3 axis, float size, bool cutoffPlane, float snap)\n        {\n            return UnityEditorInternal.Disc.Do(id, rotation, position, axis, size, cutoffPlane, snap);\n        }\n\n        public static Quaternion Disc(Quaternion rotation, Vector3 position, Vector3 axis, float size, bool cutoffPlane, float snap)\n        {\n            int id = GUIUtility.GetControlID(s_DiscHash, FocusType.Passive);\n            return UnityEditorInternal.Disc.Do(id, rotation, position, axis, size, cutoffPlane, snap);\n        }\n\n        internal static void SetupIgnoreRaySnapObjects()\n        {\n            HandleUtility.ignoreRaySnapObjects = Selection.GetTransforms(SelectionMode.Editable | SelectionMode.Deep);\n        }\n\n        // If snapping is active, return a new value rounded to the nearest increment of snap.\n        public static float SnapValue(float value, float snap)\n        {\n            if (EditorSnapSettings.incrementalSnapActive)\n                return Snapping.Snap(value, snap);\n            return value;\n        }\n\n        // If snapping is active, return a new value rounded to the nearest increment of snap.\n        public static Vector2 SnapValue(Vector2 value, Vector2 snap)\n        {\n            if (EditorSnapSettings.incrementalSnapActive)\n                return Snapping.Snap(value, snap);\n            return value;\n        }\n\n        // If snapping is active, return a new value rounded to the nearest increment of snap.\n        public static Vector3 SnapValue(Vector3 value, Vector3 snap)\n        {\n            if (EditorSnapSettings.incrementalSnapActive)\n                return Snapping.Snap(value, snap);\n            return value;\n        }\n\n        // Snap all transform positions to the grid\n        public static void SnapToGrid(Transform[] transforms, SnapAxis axis = SnapAxis.All)\n        {\n            if (transforms != null && transforms.Length > 0)\n            {\n                foreach (var t in transforms)\n                {\n                    if (t != null)\n                        t.position = Snapping.Snap(t.position, Vector3.Scale(GridSettings.size, new SnapAxisFilter(axis)));\n                }\n            }\n        }\n\n        // Snap all positions to the grid\n        public static void SnapToGrid(Vector3[] positions, SnapAxis axis = SnapAxis.All)\n        {\n            if (positions != null && positions.Length > 0)\n            {\n                for(int i = 0; i<positions.Length; i++)\n                {\n                    positions[i] = Snapping.Snap(positions[i], Vector3.Scale(GridSettings.size, new SnapAxisFilter(axis)));\n                }\n            }\n        }\n\n        // The camera used for deciding where 3D handles end up\n        public static Camera currentCamera { get { return Camera.current; } set { Internal_SetCurrentCamera(value); } }\n\n\n        internal static Color realHandleColor { get { return color * new Color(1, 1, 1, .5f) + (lighting ? new Color(0, 0, 0, .5f) : new Color(0, 0, 0, 0)); } }\n\n\n        // Draw two-shaded wire-disc that is fully shadowed\n        internal static void DrawTwoShadedWireDisc(Vector3 position, Vector3 axis, float radius)\n        {\n            Color col = Handles.color;\n            Color origCol = col;\n            col.a *= backfaceAlphaMultiplier;\n            Handles.color = col;\n            Handles.DrawWireDisc(position, axis, radius);\n            Handles.color = origCol;\n        }\n\n        // Draw two-shaded wire-disc with from and degrees specifying the lit part and the rest being shadowed\n        internal static void DrawTwoShadedWireDisc(Vector3 position, Vector3 axis, Vector3 from, float degrees, float radius)\n        {\n            Handles.DrawWireArc(position, axis, from, degrees, radius);\n            Color col = Handles.color;\n            Color origCol = col;\n            col.a *= backfaceAlphaMultiplier;\n            Handles.color = col;\n            Handles.DrawWireArc(position, axis, from, degrees - 360, radius);\n            Handles.color = origCol;\n        }\n\n        // Sets up matrix\n        internal static Matrix4x4 StartCapDraw(Vector3 position, Quaternion rotation, float size)\n        {\n            Shader.SetGlobalColor(\"_HandleColor\", realHandleColor);\n            Shader.SetGlobalFloat(\"_HandleSize\", size);\n            Matrix4x4 mat = matrix * Matrix4x4.TRS(position, rotation, Vector3.one);\n            Shader.SetGlobalMatrix(\"_ObjectToWorld\", mat);\n            HandleUtility.handleMaterial.SetFloat(\"_HandleZTest\", (float)zTest);\n            HandleUtility.handleMaterial.SetPass(0);\n            return mat;\n        }\n\n        // Draw a camera-facing Rectangle. Pass this into handle functions.\n        static Vector3[] s_RectangleCapPointsCache = new Vector3[5];\n\n        internal static void RectangleCap(int controlID, Vector3 position, Quaternion rotation, Vector2 size)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n            Vector3 sideways = rotation * new Vector3(size.x, 0, 0);\n            Vector3 up = rotation * new Vector3(0, size.y, 0);\n            s_RectangleCapPointsCache[0] = position + sideways + up;\n            s_RectangleCapPointsCache[1] = position + sideways - up;\n            s_RectangleCapPointsCache[2] = position - sideways - up;\n            s_RectangleCapPointsCache[3] = position - sideways + up;\n            s_RectangleCapPointsCache[4] = position + sideways + up;\n            Handles.DrawPolyLine(s_RectangleCapPointsCache);\n        }\n\n        // Draw a camera facing selection frame.\n        public static void SelectionFrame(int controlID, Vector3 position, Quaternion rotation, float size)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n            Handles.StartCapDraw(position, rotation, size);\n            Vector3 sideways = rotation * new Vector3(size, 0, 0);\n            Vector3 up = rotation * new Vector3(0, size, 0);\n\n            var point1 = position - sideways + up;\n            var point2 = position + sideways + up;\n            var point3 = position + sideways - up;\n            var point4 = position - sideways - up;\n\n            Handles.DrawLine(point1, point2);\n            Handles.DrawLine(point2, point3);\n            Handles.DrawLine(point3, point4);\n            Handles.DrawLine(point4, point1);\n        }\n\n        /// *listonly*\n        public static void DrawAAPolyLine(Color[] colors, Vector3[] points)                { DoDrawAAPolyLine(colors, points, -1, null, 2, 0.75f); }\n        /// *listonly*\n        public static void DrawAAPolyLine(float width, Color[] colors, Vector3[] points)   { DoDrawAAPolyLine(colors, points, -1, null, width, 0.75f); }\n        /// *listonly*\n        public static void DrawAAPolyLine(params Vector3[] points)                       { DoDrawAAPolyLine(null, points, -1, null, 2, 0.75f); }\n        /// *listonly*\n        public static void DrawAAPolyLine(float width, params Vector3[] points)          { DoDrawAAPolyLine(null, points, -1, null, width, 0.75f); }\n        /// *listonly*\n        public static void DrawAAPolyLine(Texture2D lineTex, params Vector3[] points)    { DoDrawAAPolyLine(null, points, -1, lineTex, lineTex.height / 2, 0.99f); }\n        /// *listonly*\n        public static void DrawAAPolyLine(float width, int actualNumberOfPoints, params Vector3[] points) { DoDrawAAPolyLine(null, points, actualNumberOfPoints, null, width, 0.75f); }\n\n        // Draw anti-aliased line specified with point array and width.\n        public static void DrawAAPolyLine(Texture2D lineTex, float width, params Vector3[] points) {  DoDrawAAPolyLine(null, points, -1, lineTex, width, 0.99f); }\n\n\n        static void DoDrawAAPolyLine(Color[] colors, Vector3[] points, int actualNumberOfPoints, Texture2D lineTex, float width, float alpha)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n            HandleUtility.ApplyWireMaterial(zTest);\n\n            Color defaultColor = new Color(1, 1, 1, alpha);\n            Internal_DrawAAPolyLine(colors, points, defaultColor, actualNumberOfPoints, lineTex, width, matrix);\n        }\n\n        // Draw anti-aliased convex polygon specified with point array.\n        public static void DrawAAConvexPolygon(params Vector3[] points) {  DoDrawAAConvexPolygon(points, -1, 1.0f); }\n\n        static void DoDrawAAConvexPolygon(Vector3[] points, int actualNumberOfPoints, float alpha)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            HandleUtility.ApplyWireMaterial(zTest);\n\n            Color defaultColor = new Color(1, 1, 1, alpha) * color;\n            Internal_DrawAAConvexPolygon(points, defaultColor, actualNumberOfPoints, matrix);\n        }\n\n        // Draw textured bezier line through start and end points with the given tangents.  To get an anti-aliased effect use a texture that is 1x2 pixels with one transparent white pixel and one opaque white pixel.  The bezier curve will be swept using this texture.\n        public static void DrawBezier(Vector3 startPosition, Vector3 endPosition, Vector3 startTangent, Vector3 endTangent, Color color, Texture2D texture, float width)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            HandleUtility.ApplyWireMaterial(zTest);\n            Internal_DrawBezier(startPosition, endPosition, startTangent, endTangent, color, texture, width, matrix);\n        }\n\n        // Draw the outline of a flat disc in 3D space.\n        [ExcludeFromDocs]\n        public static void DrawWireDisc(Vector3 center, Vector3 normal, float radius)\n        {\n            DrawWireDisc(center, normal, radius, 0.0f);\n        }\n\n        public static void DrawWireDisc(Vector3 center, Vector3 normal, float radius, [DefaultValue(\"0.0f\")] float thickness)\n        {\n            Vector3 tangent = Vector3.Cross(normal, Vector3.up);\n            if (tangent.sqrMagnitude < .001f)\n                tangent = Vector3.Cross(normal, Vector3.right);\n            DrawWireArc(center, normal, tangent, 360, radius, thickness);\n        }\n\n        private static readonly Vector3[] s_WireArcPoints = new Vector3[60];\n\n        // Draw a circular arc in 3D space.\n        [ExcludeFromDocs]\n        public static void DrawWireArc(Vector3 center, Vector3 normal, Vector3 from, float angle, float radius)\n        {\n            DrawWireArc(center, normal, from, angle, radius, 0.0f);\n        }\n\n        static Material SetupArcMaterial()\n        {\n            var mat = HandleUtility.handleArcMaterial;\n            if (!mat.shader.isSupported) // can happen when editor is actually using OpenGL ES 2 (no instancing)\n                return null;\n            var col = color * lineTransparency;\n            mat.SetFloat(kPropUseGuiClip, Camera.current ? 0.0f : 1.0f);\n            mat.SetFloat(kPropHandleZTest, (float)zTest);\n            mat.SetColor(kPropColor, col);\n            mat.SetMatrix(kPropHandlesMatrix, matrix);\n            return mat;\n        }\n\n        const int kArcSegments = 60;\n        const int kArcSides = 8;\n\n        public static void DrawWireArc(Vector3 center, Vector3 normal, Vector3 from, float angle, float radius, [DefaultValue(\"0.0f\")] float thickness)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            thickness = ThicknessToPixels(thickness);\n\n            var mat = SetupArcMaterial();\n            if (mat == null) // can't do arcs or thick lines (only on GLES2), fallback to thin arc via CPU path\n            {\n                SetDiscSectionPoints(s_WireArcPoints, center, normal, from, angle, radius);\n                DrawPolyLine(s_WireArcPoints);\n                return;\n            }\n\n            mat.SetVector(kPropArcCenterRadius, new Vector4(center.x, center.y, center.z, radius));\n            mat.SetVector(kPropArcNormalAngle, new Vector4(normal.x, normal.y, normal.z, angle * Mathf.Deg2Rad));\n            mat.SetVector(kPropArcFromCount, new Vector4(from.x, from.y, from.z, kArcSegments));\n            mat.SetVector(kPropArcThicknessSides, new Vector4(thickness, kArcSides, 0, 0));\n            mat.SetPass(0);\n\n            if (thickness <= 0.0f)\n                Graphics.DrawProceduralNow(MeshTopology.LineStrip, kArcSegments);\n            else\n            {\n                var indexBuffer = HandleUtility.GetArcIndexBuffer(kArcSegments, kArcSides);\n                Graphics.DrawProceduralNow(MeshTopology.Triangles, indexBuffer, indexBuffer.count);\n            }\n        }\n\n        public static void DrawSolidRectangleWithOutline(Rect rectangle, Color faceColor, Color outlineColor)\n        {\n            Vector3[] points =\n            {\n                new Vector3(rectangle.xMin, rectangle.yMin, 0.0f),\n                new Vector3(rectangle.xMax, rectangle.yMin, 0.0f),\n                new Vector3(rectangle.xMax, rectangle.yMax, 0.0f),\n                new Vector3(rectangle.xMin, rectangle.yMax, 0.0f)\n            };\n\n            Handles.DrawSolidRectangleWithOutline(points, faceColor, outlineColor);\n        }\n\n        // Draw a solid outlined rectangle in 3D space.\n        public static void DrawSolidRectangleWithOutline(Vector3[] verts, Color faceColor, Color outlineColor)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            HandleUtility.ApplyWireMaterial(zTest);\n\n            GL.PushMatrix();\n            GL.MultMatrix(matrix);\n\n            // Triangles (Draw it twice to ensure render of both front and back faces)\n            if (faceColor.a > 0)\n            {\n                Color col = faceColor * color;\n                GL.Begin(GL.TRIANGLES);\n                for (int i = 0; i < 2; i++)\n                {\n                    GL.Color(col);\n                    GL.Vertex(verts[i * 2 + 0]);\n                    GL.Vertex(verts[i * 2 + 1]);\n                    GL.Vertex(verts[(i * 2 + 2) % 4]);\n\n                    GL.Vertex(verts[i * 2 + 0]);\n                    GL.Vertex(verts[(i * 2 + 2) % 4]);\n                    GL.Vertex(verts[i * 2 + 1]);\n                }\n                GL.End();\n            }\n\n            // Outline\n            if (outlineColor.a > 0)\n            {\n                //HandleUtility.ApplyWireMaterial ();\n                Color col = outlineColor * color;\n                GL.Begin(GL.LINES);\n                GL.Color(col);\n                for (int i = 0; i < 4; i++)\n                {\n                    GL.Vertex(verts[i]);\n                    GL.Vertex(verts[(i + 1) % 4]);\n                }\n                GL.End();\n            }\n\n            GL.PopMatrix();\n        }\n\n        // Draw a solid flat disc in 3D space.\n        public static void DrawSolidDisc(Vector3 center, Vector3 normal, float radius)\n        {\n            Vector3 tangent = Vector3.Cross(normal, Vector3.up);\n            if (tangent.sqrMagnitude < .001f)\n                tangent = Vector3.Cross(normal, Vector3.right);\n            DrawSolidArc(center, normal, tangent, 360, radius);\n        }\n\n        // Draw a circular sector (pie piece) in 3D space.\n        public static void DrawSolidArc(Vector3 center, Vector3 normal, Vector3 from, float angle, float radius)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n            SetDiscSectionPoints(s_WireArcPoints, center, normal, from, angle, radius);\n\n            Shader.SetGlobalColor(\"_HandleColor\", color * new Color(1, 1, 1, .5f));\n            Shader.SetGlobalFloat(\"_HandleSize\", 1);\n\n            HandleUtility.ApplyWireMaterial(zTest);\n\n            // Draw it twice to ensure backface culling doesn't hide any of the faces\n            GL.PushMatrix();\n            GL.MultMatrix(matrix);\n            GL.Begin(GL.TRIANGLES);\n            for (int i = 1, count = s_WireArcPoints.Length; i < count; ++i)\n            {\n                GL.Color(color);\n                GL.Vertex(center);\n                GL.Vertex(s_WireArcPoints[i - 1]);\n                GL.Vertex(s_WireArcPoints[i]);\n                GL.Vertex(center);\n                GL.Vertex(s_WireArcPoints[i]);\n                GL.Vertex(s_WireArcPoints[i - 1]);\n            }\n            GL.End();\n            GL.PopMatrix();\n        }\n\n        internal static Mesh s_CubeMesh, s_SphereMesh, s_ConeMesh, s_CylinderMesh, s_QuadMesh;\n        internal static void Init()\n        {\n            if (!s_CubeMesh)\n            {\n                GameObject handleGo = (GameObject)EditorGUIUtility.Load(\"SceneView/HandlesGO.fbx\");\n                if (!handleGo)\n                {\n                    Debug.Log(\"Couldn't find SceneView/HandlesGO.fbx\");\n                }\n                // @TODO: temp workaround to make it not render in the scene\n                handleGo.SetActive(false);\n\n                const string k_AssertMessage = \"mesh is null. A problem has occurred with `SceneView/HandlesGO.fbx`\";\n\n                foreach (Transform t in handleGo.transform)\n                {\n                    var meshFilter = t.GetComponent<MeshFilter>();\n                    switch (t.name)\n                    {\n                        case \"Cube\":\n                            s_CubeMesh = meshFilter.sharedMesh;\n                            Debug.AssertFormat(s_CubeMesh != null, k_AssertMessage);\n                            break;\n                        case \"Sphere\":\n                            s_SphereMesh = meshFilter.sharedMesh;\n                            Debug.AssertFormat(s_SphereMesh != null, k_AssertMessage);\n                            break;\n                        case \"Cone\":\n                            s_ConeMesh = meshFilter.sharedMesh;\n                            Debug.AssertFormat(s_ConeMesh != null, k_AssertMessage);\n                            break;\n                        case \"Cylinder\":\n                            s_CylinderMesh = meshFilter.sharedMesh;\n                            Debug.AssertFormat(s_CylinderMesh != null, k_AssertMessage);\n                            break;\n                        case \"Quad\":\n                            s_QuadMesh = meshFilter.sharedMesh;\n                            Debug.AssertFormat(s_QuadMesh != null, k_AssertMessage);\n                            break;\n                    }\n                }\n            }\n        }\n\n        /// *listonly*\n        public static void Label(Vector3 position, string text)                          { Label(position, EditorGUIUtility.TempContent(text), GUI.skin.label); }\n        /// *listonly*\n        public static void Label(Vector3 position, Texture image)                        { Label(position, EditorGUIUtility.TempContent(image), GUI.skin.label); }\n        /// *listonly*\n        public static void Label(Vector3 position, GUIContent content)                   { Label(position, content, GUI.skin.label); }\n        /// *listonly*\n        public static void Label(Vector3 position, string text, GUIStyle style)              { Label(position, EditorGUIUtility.TempContent(text), style); }\n        // Make a text label positioned in 3D space.\n        public static void Label(Vector3 position, GUIContent content, GUIStyle style)\n        {\n            Vector3 screenPoint = HandleUtility.WorldToGUIPointWithDepth(position);\n            if (screenPoint.z < 0)\n                return; //label is behind camera\n\n            Handles.BeginGUI();\n            GUI.Label(HandleUtility.WorldPointToSizedRect(position, content, style), content, style);\n            Handles.EndGUI();\n        }\n\n        // Returns actual rectangle where the camera will be rendered\n        internal static Rect GetCameraRect(Rect position)\n        {\n            Rect screenRect = GUIClip.Unclip(position);\n            Rect cameraRect = new Rect(screenRect.xMin, Screen.height - screenRect.yMax, screenRect.width, screenRect.height);\n            return cameraRect;\n        }\n\n        // Get the size of the main playModeView window\n        public static Vector2 GetMainGameViewSize()\n        {\n            return PlayModeView.GetMainPlayModeViewTargetSize();\n        }\n\n        public static void DrawOutline(int[] parentRenderers, int[] childRenderers, Color parentNodeColor, Color childNodeColor, float fillOpacity = 0)\n        {\n            if(Event.current.type != EventType.Repaint)\n                return;\n            Internal_DrawOutline(parentNodeColor, childNodeColor, 0, parentRenderers.ToEntityIdArray(), childRenderers.ToEntityIdArray(), OutlineDrawMode.SelectionOutline, fillOpacity, fillOpacity);\n            Internal_FinishDrawingCamera(Camera.current, true);\n        }\n\n        public static void DrawOutline(int[] renderers, Color color, float fillOpacity = 0) =>\n            DrawOutline(renderers, null, color, color, fillOpacity);\n\n        public static void DrawOutline(Renderer[] renderers, Color parentNodeColor, Color childNodeColor, float fillOpacity = 0)\n        {\n            int[] parentRenderers, childRenderers;\n            HandleUtility.FilterRendererIDs(renderers, out parentRenderers, out childRenderers);\n            DrawOutline(parentRenderers, childRenderers, parentNodeColor, childNodeColor, fillOpacity);\n        }\n\n        public static void DrawOutline(Renderer[] renderers, Color color, float fillOpacity = 0) =>\n            DrawOutline(renderers, color, color, fillOpacity);\n\n        public static void DrawOutline(GameObject[] objects, Color parentNodeColor, Color childNodeColor, float fillOpacity = 0)\n        {\n            int[] parentRenderers, childRenderers;\n            HandleUtility.FilterInstanceIDs(objects, out parentRenderers, out childRenderers, out _);\n            DrawOutline(parentRenderers, childRenderers, parentNodeColor, childNodeColor, fillOpacity);\n        }\n\n        public static void DrawOutline(GameObject[] objects, Color color, float fillOpacity = 0)\n        {\n            var index = 0;\n            var ids = new int[objects.Length];\n            foreach (var go in objects)\n                if (go.TryGetComponent(out Renderer renderer))\n                    ids[index++] = renderer.GetInstanceID();\n            DrawOutline(ids, null, color, color, fillOpacity);\n        }\n\n        public static void DrawOutline(List<GameObject> objects, Color parentNodeColor, Color childNodeColor, float fillOpacity = 0)\n        {\n            int[] parentRenderers, childRenderers;\n            HandleUtility.FilterInstanceIDs((GameObject[])NoAllocHelpers.ExtractArrayFromList(objects), out parentRenderers, out childRenderers, out _);\n            DrawOutline(parentRenderers, childRenderers, parentNodeColor, childNodeColor, fillOpacity);\n        }\n\n        public static void DrawOutline(List<GameObject> objects, Color color, float fillOpacity = 0)\n        {\n            var index = 0;\n            var ids = new int[objects.Count];\n            foreach (var go in objects)\n            {\n                if (go.TryGetComponent(out Renderer renderer))\n                    ids[index++] = renderer.GetInstanceID();\n            }\n            DrawOutline(ids, null, color, color, fillOpacity);\n        }\n\n        internal static void DrawOutlineOrWireframeInternal(Color parentNodeColor, Color childNodeColor, float outlineAlpha, int[] parentRenderers, int[] childRenderers, OutlineDrawMode outlineMode)\n        {\n            // RenderOutline will swap color.a and outlineAlpha so we reverse it here to preserve correct behavior wrt Color settings in Preferences\n            var parentOutlineAlpha = parentNodeColor.a;\n            var childOutlineAlpha = childNodeColor.a;\n            parentNodeColor.a = outlineAlpha;\n            childNodeColor.a = outlineAlpha;\n            Internal_DrawOutline(parentNodeColor, childNodeColor, 0, parentRenderers.ToEntityIdArray(), childRenderers.ToEntityIdArray(), outlineMode, parentOutlineAlpha, childOutlineAlpha);\n        }\n\n        internal static void DrawSubmeshOutline(Color parentNodeColor, Color childNodeColor, float outlineAlpha, int submeshOutlineMaterialId)\n        {\n            int[] parentRenderers, childRenderers;\n            HandleUtility.FilterInstanceIDs(Selection.gameObjects, out parentRenderers, out childRenderers, out _);\n\n            // RenderOutline will swap color.a and outlineAlpha so we reverse it here to preserve correct behavior wrt Color settings in Preferences\n            var parentOutlineAlpha = parentNodeColor.a;\n            var childOutlineAlpha = childNodeColor.a;\n            parentNodeColor.a = outlineAlpha;\n            childNodeColor.a = outlineAlpha;\n\n            Internal_DrawOutline(parentNodeColor, childNodeColor, submeshOutlineMaterialId, parentRenderers.ToEntityIdArray(), childRenderers.ToEntityIdArray(), OutlineDrawMode.SelectionOutline, parentOutlineAlpha, childOutlineAlpha);\n            Internal_FinishDrawingCamera(Camera.current, true);\n        }\n\n        // Clears the camera.\n        public static void ClearCamera(Rect position, Camera camera)\n        {\n            Event evt = Event.current;\n            if (camera.targetTexture == null)\n            {\n                Rect screenRect = GUIClip.Unclip(position);\n                screenRect = EditorGUIUtility.PointsToPixels(screenRect);\n                Rect cameraRect = new Rect(screenRect.xMin, Screen.height - screenRect.yMax, screenRect.width, screenRect.height);\n                camera.pixelRect = cameraRect;\n            }\n            else\n            {\n                camera.rect = new Rect(0, 0, 1, 1);\n            }\n            if (evt.type == EventType.Repaint)\n                Internal_ClearCamera(camera);\n            else\n                Internal_SetCurrentCamera(camera);\n        }\n\n        internal static void DrawCameraImpl(Rect position,\n            Camera camera,\n            DrawCameraMode drawMode,\n            bool drawGrid,\n            DrawGridParameters gridParam,\n            bool finish,\n            bool renderGizmos = true,\n            bool renderSelection = true,\n            GameObject[] filter = null\n        )\n        {\n            Event evt = Event.current;\n\n            if (evt.type == EventType.Repaint)\n            {\n                if (camera.targetTexture == null)\n                {\n                    Rect screenRect = GUIClip.Unclip(position);\n                    screenRect = EditorGUIUtility.PointsToPixels(screenRect);\n                    camera.pixelRect = new Rect(screenRect.xMin, Screen.height - screenRect.yMax, screenRect.width, screenRect.height);\n                }\n                else\n                {\n                    camera.rect = new Rect(0, 0, 1, 1);\n                }\n                if (drawMode == DrawCameraMode.Normal)\n                {\n                    RenderTexture temp = camera.targetTexture;\n                    camera.targetTexture = RenderTexture.active;\n                    camera.Render();\n                    camera.targetTexture = temp;\n                }\n                else\n                {\n                    if (drawGrid)\n                        Internal_DrawCameraWithGrid(camera, drawMode, ref gridParam, renderGizmos, renderSelection);\n                    else\n                        Internal_DrawCameraWithFilter(camera, drawMode, renderGizmos, renderSelection, filter);\n\n                    // VR scene cameras finish drawing with each eye render\n                    if (finish && camera.cameraType != CameraType.VR)\n                        Internal_FinishDrawingCamera(camera, renderGizmos);\n                }\n            }\n            else\n                Internal_SetCurrentCamera(camera);\n        }\n\n        // Draws a camera inside a rectangle.\n        // It also sets up the (for now, anyways) undocumented Event.current.mouseRay and Event.current.lastMouseRay for handleutility functions.\n        //\n        internal static void DrawCamera(Rect position, Camera camera, DrawCameraMode drawMode, DrawGridParameters gridParam)\n        {\n            DrawCameraImpl(position, camera, drawMode, true, gridParam, true);\n        }\n\n        internal static void DrawCameraStep1(Rect position, Camera camera, DrawCameraMode drawMode, DrawGridParameters gridParam, bool drawGizmos, bool drawSelection)\n        {\n            DrawCameraImpl(position, camera, drawMode, true, gridParam, false, drawGizmos, drawSelection);\n        }\n\n        internal static void DrawCameraStep2(Camera camera, DrawCameraMode drawMode, bool drawGizmos)\n        {\n            if (Event.current.type == EventType.Repaint && drawMode != DrawCameraMode.Normal)\n                Internal_FinishDrawingCamera(camera, drawGizmos);\n        }\n\n        // Draws a camera inside a rectangle.\n        // It also sets up the (for now, anyways) undocumented Event.current.mouseRay and Event.current.lastMouseRay for handleutility functions.\n        //\n        public static void DrawCamera(Rect position, Camera camera)\n        {\n            DrawCamera(position, camera, DrawCameraMode.Normal);\n        }\n\n        public static void DrawCamera(Rect position, Camera camera, [DefaultValue(\"UnityEditor.DrawCameraMode.Normal\")] DrawCameraMode drawMode)\n        {\n            DrawCamera(position, camera, drawMode, true);\n        }\n\n        public static void DrawCamera(Rect position, Camera camera, [DefaultValue(\"UnityEditor.DrawCameraMode.Normal\")] DrawCameraMode drawMode, bool drawGizmos)\n        {\n            DrawGridParameters nullGridParam = new DrawGridParameters();\n            DrawCameraImpl(position, camera, drawMode, false, nullGridParam, true, drawGizmos);\n        }\n\n        internal enum CameraFilterMode\n        {\n            Off = 0,\n            ShowFiltered = 1\n        }\n\n        /// *listonly*\n        public static void SetCamera(Camera camera)\n        {\n            if (Event.current == null)\n                return;\n            if (Event.current.type == EventType.Repaint)\n                Internal_SetupCamera(camera);\n            else\n                Internal_SetCurrentCamera(camera);\n        }\n\n        // Set the current camera so all Handles and Gizmos are draw with its settings.\n        public static void SetCamera(Rect position, Camera camera)\n        {\n            if (camera.targetTexture == null)\n            {\n                Rect screenRect = GUIClip.Unclip(position);\n                screenRect = EditorGUIUtility.PointsToPixels(screenRect);\n                Rect cameraRect = new Rect(screenRect.xMin, Screen.height - screenRect.yMax, screenRect.width,\n                    screenRect.height);\n                camera.pixelRect = cameraRect;\n            }\n\n            Event evt = Event.current;\n\n            if (evt.type == EventType.Repaint)\n                Internal_SetupCamera(camera);\n            else\n                Internal_SetCurrentCamera(camera);\n        }\n\n        ///*listonly*\n        public static void BeginGUI()\n        {\n            if (Camera.current && Event.current.type == EventType.Repaint)\n            {\n                GUIClip.Reapply();\n            }\n        }\n\n        // Begin a 2D GUI block inside the 3D handle GUI.\n        [Obsolete(\"Please use BeginGUI() with GUILayout.BeginArea(position) / GUILayout.EndArea()\")]\n        public static void BeginGUI(Rect position)\n        {\n            GUILayout.BeginArea(position);\n        }\n\n        // End a 2D GUI block and get back to the 3D handle GUI.\n        public static void EndGUI()\n        {\n            Camera cam = Camera.current;\n            if (cam && Event.current.type == EventType.Repaint)\n                Internal_SetupCamera(cam);\n        }\n\n        internal static void ShowSceneViewLabel(Vector3 pos, GUIContent label)\n        {\n            Handles.color = Color.white;\n            Handles.zTest = UnityEngine.Rendering.CompareFunction.Always;\n            GUIStyle style = \"SC ViewAxisLabel\";\n            style.alignment = TextAnchor.MiddleLeft;\n            style.fixedWidth = 0;\n            Handles.BeginGUI();\n            Rect rect = HandleUtility.WorldPointToSizedRect(pos, label, style);\n            rect.x += 10;\n            rect.y += 10;\n            GUI.Label(rect, label, style);\n            Handles.EndGUI();\n        }\n\n        public static Vector3[] MakeBezierPoints(Vector3 startPosition, Vector3 endPosition, Vector3 startTangent, Vector3 endTangent, int division)\n        {\n            if (division < 1)\n                throw new ArgumentOutOfRangeException(\"division\", \"Must be greater than zero\");\n            return Internal_MakeBezierPoints(startPosition, endPosition, startTangent, endTangent, division);\n        }\n\n        public static void DrawTexture3DSDF(Texture texture,\n            [DefaultValue(\"1.0f\")] float stepScale = 1.0f,\n            [DefaultValue(\"0.0f\")] float surfaceOffset = 0.0f,\n            [DefaultValue(\"null\")] Gradient customColorRamp = null)\n        {\n            Vector3 localScale = new Vector3(matrix.GetColumn(0).magnitude, matrix.GetColumn(1).magnitude, matrix.GetColumn(2).magnitude);\n            Texture3DPreview.PrepareSDFPreview(Texture3DPreview.Materials.SDF, texture, localScale, stepScale, surfaceOffset, customColorRamp);\n            Texture3DPreview.Materials.SDF.SetPass(0);\n            Graphics.DrawMeshNow(cubeMesh, matrix);\n        }\n\n        public static void DrawTexture3DSlice(Texture texture, Vector3 slicePositions,\n            [DefaultValue(\"FilterMode.Bilinear\")] FilterMode filterMode = FilterMode.Bilinear,\n            [DefaultValue(\"false\")] bool useColorRamp = false,\n            [DefaultValue(\"null\")] Gradient customColorRamp = null)\n        {\n            Vector3 localScale = new Vector3(matrix.GetColumn(0).magnitude, matrix.GetColumn(1).magnitude, matrix.GetColumn(2).magnitude);\n            Texture3DPreview.PrepareSlicePreview(Texture3DPreview.Materials.Slice, texture, slicePositions, filterMode, useColorRamp, customColorRamp);\n            Texture3DPreview.Materials.Slice.SetPass(0);\n            Graphics.DrawMeshNow(cubeMesh, matrix);\n        }\n\n        public static void DrawTexture3DVolume(Texture texture,\n            [DefaultValue(\"1.0f\")] float opacity = 1.0f,\n            [DefaultValue(\"1.0f\")] float qualityModifier = 1.0f,\n            [DefaultValue(\"FilterMode.Bilinear\")] FilterMode filterMode = FilterMode.Bilinear,\n            [DefaultValue(\"false\")] bool useColorRamp = false,\n            [DefaultValue(\"null\")] Gradient customColorRamp = null)\n        {\n            Vector3 localScale = new Vector3(matrix.GetColumn(0).magnitude, matrix.GetColumn(1).magnitude, matrix.GetColumn(2).magnitude);\n            int sampleCount = Texture3DPreview.PrepareVolumePreview(Texture3DPreview.Materials.Volume, texture, localScale, opacity,\n                filterMode, useColorRamp, customColorRamp, Camera.current, matrix, qualityModifier);\n            Texture3DPreview.Materials.Volume.SetPass(0);\n            Graphics.DrawProceduralNow(MeshTopology.Quads, 4, sampleCount);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/PositionHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class Handles\n    {\n        /// <summary>\n        /// Set of IDs corresponding to the handles of Handles.PositionHandle.\n        /// </summary>\n        public struct PositionHandleIds\n        {\n            /// <summary>\n            /// Default set of IDs to pass to Handles.PositionHandle.\n            /// </summary>\n            public static PositionHandleIds @default\n            {\n                get\n                {\n                    return new PositionHandleIds(\n                        GUIUtility.GetControlID(s_xAxisMoveHandleHash, FocusType.Passive),\n                        GUIUtility.GetControlID(s_yAxisMoveHandleHash, FocusType.Passive),\n                        GUIUtility.GetControlID(s_zAxisMoveHandleHash, FocusType.Passive),\n                        GUIUtility.GetControlID(s_xyAxisMoveHandleHash, FocusType.Passive),\n                        GUIUtility.GetControlID(s_xzAxisMoveHandleHash, FocusType.Passive),\n                        GUIUtility.GetControlID(s_yzAxisMoveHandleHash, FocusType.Passive),\n                        GUIUtility.GetControlID(s_FreeMoveHandleHash, FocusType.Passive)\n                    );\n                }\n            }\n\n            public readonly int x, y, z, xy, yz, xz, xyz;\n\n            internal int this[int index]\n            {\n                get\n                {\n                    switch (index)\n                    {\n                        case 0: return x;\n                        case 1: return y;\n                        case 2: return z;\n                        case 3: return xy;\n                        case 4: return yz;\n                        case 5: return xz;\n                        case 6: return xyz;\n                    }\n                    return -1;\n                }\n            }\n\n            internal bool Has(int id)\n            {\n                return x == id\n                    || y == id\n                    || z == id\n                    || xy == id\n                    || yz == id\n                    || xz == id\n                    || xyz == id;\n            }\n\n            internal PositionHandleIds(int x, int y, int z, int xy, int xz, int yz, int xyz)\n            {\n                this.x = x;\n                this.y = y;\n                this.z = z;\n                this.xy = xy;\n                this.yz = yz;\n                this.xz = xz;\n                this.xyz = xyz;\n            }\n\n            public override int GetHashCode()\n            {\n                return x ^ y ^ z ^ xy ^ xz ^ yz ^ xyz;\n            }\n\n            public override bool Equals(object obj)\n            {\n                if (!(obj is PositionHandleIds))\n                    return false;\n\n                var o = (PositionHandleIds)obj;\n                return o.x == x && o.y == y && o.z == z\n                    && o.xy == xy && o.xz == xz && o.yz == yz\n                    && o.xyz == xyz;\n            }\n        }\n\n        internal struct PositionHandleParam\n        {\n            public static PositionHandleParam DefaultHandle = new PositionHandleParam(\n                Handle.X | Handle.Y | Handle.Z | Handle.XY | Handle.XZ | Handle.YZ,\n                Vector3.zero, Vector3.one, Vector3.zero, Vector3.one * 0.25f,\n                Orientation.Signed, Orientation.Camera);\n            public static PositionHandleParam DefaultFreeMoveHandle = new PositionHandleParam(\n                Handle.X | Handle.Y | Handle.Z | Handle.XYZ,\n                Vector3.zero, Vector3.one, Vector3.zero, Vector3.one * 0.25f,\n                Orientation.Signed, Orientation.Signed);\n\n            [Flags]\n            public enum Handle\n            {\n                None = 0,\n                X = 1 << 0,\n                Y = 1 << 1,\n                Z = 1 << 2,\n                XY = 1 << 3,\n                YZ = 1 << 4,\n                XZ = 1 << 5,\n                XYZ = 1 << 6,\n                All = ~None\n            }\n\n            public enum Orientation\n            {\n                Signed,\n                Camera\n            }\n\n            public readonly Vector3 axisOffset;\n            public readonly Vector3 axisSize;\n            public readonly Vector3 planeOffset;\n            public readonly Vector3 planeSize;\n            public readonly Handle handles;\n            public readonly Orientation axesOrientation;\n            public readonly Orientation planeOrientation;\n\n            public bool ShouldShow(int axis)\n            {\n                return (handles & (Handle)(1 << axis)) != 0;\n            }\n\n            public bool ShouldShow(Handle handle)\n            {\n                return (handles & handle) != 0;\n            }\n\n            public PositionHandleParam(\n                Handle handles,\n                Vector3 axisOffset,\n                Vector3 axisSize,\n                Vector3 planeOffset,\n                Vector3 planeSize,\n                Orientation axesOrientation,\n                Orientation planeOrientation)\n            {\n                this.axisOffset = axisOffset;\n                this.axisSize = axisSize;\n                this.planeOffset = planeOffset;\n                this.planeSize = planeSize;\n                this.handles = handles;\n                this.axesOrientation = axesOrientation;\n                this.planeOrientation = planeOrientation;\n            }\n        }\n\n        static Vector3[] verts = {Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero};\n\n        const float kFreeMoveHandleSizeFactor = 0.15f;\n\n        // While the user has Free Move mode turned on by holding 'shift' or 'V' (for Vertex Snapping),\n        // this variable will be set to True.\n        static bool s_FreeMoveMode = false;\n\n        // Which octant the planar move handles are in.\n        static Vector3 s_PlanarHandlesOctant = Vector3.one;\n        static Vector3 s_DoPositionHandle_AxisHandlesOctant = Vector3.one;\n\n        // If the user is currently mouse dragging then this value will be True\n        // and will disallow toggling Free Move mode on or off, or changing the octant of the planar handles.\n        static bool currentlyDragging { get { return EditorGUIUtility.hotControl != 0; } }\n\n        static Vector3 s_DoPositionHandle_ArrowCapConeOffset = Vector3.zero;\n\n        public static Vector3 DoPositionHandle(Vector3 position, Quaternion rotation)\n        {\n            return DoPositionHandle(PositionHandleIds.@default, position, rotation);\n        }\n\n        internal static Vector3 DoPositionHandle(PositionHandleIds ids, Vector3 position, Quaternion rotation)\n        {\n            Event evt = Event.current;\n            switch (evt.type)\n            {\n                case EventType.KeyDown:\n                    // Holding 'V' turns on the FreeMove transform gizmo and enables vertex snapping.\n                    if (evt.keyCode == Tools.vertexDraggingShortcutEvent.keyCode\n                        && evt.modifiers == Tools.vertexDraggingShortcutEvent.modifiers\n                        && !currentlyDragging)\n                    {\n                        s_FreeMoveMode = true;\n                    }\n                    break;\n\n                case EventType.KeyUp:\n                    // If the user has released the 'V' key, then rendering the transform gizmo\n                    // one last time with Free Move mode off is technically incorrect since it can\n                    // add one additional frame of input with FreeMove enabled, but the\n                    // implementation is a fair bit simpler this way.\n                    // Basic idea: Leave this call above the 'if' statement.\n                    position = DoPositionHandle_Internal(ids, position, rotation, PositionHandleParam.DefaultHandle);\n                    if (evt.keyCode == Tools.vertexDraggingShortcutEvent.keyCode\n                        && evt.modifiers == Tools.vertexDraggingShortcutEvent.modifiers\n                        && !evt.shift && !currentlyDragging)\n                    {\n                        s_FreeMoveMode = false;\n                    }\n                    return position;\n\n                case EventType.Layout:\n                    if (Tools.vertexDragging && !s_FreeMoveMode)\n                    {\n                        s_FreeMoveMode = true;\n                    }\n                    if (!currentlyDragging && !Tools.vertexDragging)\n                    {\n                        s_FreeMoveMode = evt.shift;\n                    }\n                    break;\n            }\n\n            var param = s_FreeMoveMode ? PositionHandleParam.DefaultFreeMoveHandle : PositionHandleParam.DefaultHandle;\n\n            return DoPositionHandle_Internal(ids, position, rotation, param);\n        }\n\n        static float[] s_DoPositionHandle_Internal_CameraViewLerp = new float[6];\n        static string[] s_DoPositionHandle_Internal_AxisNames = { \"xAxis\", \"yAxis\", \"zAxis\" };\n        static int[] s_DoPositionHandle_Internal_NextIndex = { 1, 2, 0 };\n        static int[] s_DoPositionHandle_Internal_PrevIndex = { 2, 0, 1 };\n        static int[] s_DoPositionHandle_Internal_PrevPlaneIndex = { 5, 3, 4 };\n        static int[] s_DoPositionHandle_Internal_AxisDrawOrder = { 0, 1, 2 };\n\n        static Vector3 DoPositionHandle_Internal(PositionHandleIds ids, Vector3 position, Quaternion rotation, PositionHandleParam param)\n        {\n            Color temp = color;\n\n            bool isDisabled = !GUI.enabled;\n\n            // Calculate the camera view vector in Handle draw space\n            // this handle the case where the matrix is skewed\n            var handlePosition = matrix.MultiplyPoint3x4(position);\n            var drawToWorldMatrix = matrix * Matrix4x4.TRS(position, rotation, Vector3.one);\n            var invDrawToWorldMatrix = drawToWorldMatrix.inverse;\n            var viewVectorDrawSpace = GetCameraViewFrom(handlePosition, invDrawToWorldMatrix);\n\n            var size = HandleUtility.GetHandleSize(position);\n\n            // Calculate per axis camera lerp\n            for (var i = 0; i < 3; ++i)\n                s_DoPositionHandle_Internal_CameraViewLerp[i] = ids[i] == GUIUtility.hotControl ? 0 : GetCameraViewLerpForWorldAxis(viewVectorDrawSpace, GetAxisVector(i));\n            // Calculate per plane camera lerp (xy, yz, xz)\n            for (var i = 0; i < 3; ++i)\n                s_DoPositionHandle_Internal_CameraViewLerp[3 + i] = Mathf.Max(s_DoPositionHandle_Internal_CameraViewLerp[i], s_DoPositionHandle_Internal_CameraViewLerp[(i + 1) % 3]);\n\n            var isHot = ids.Has(GUIUtility.hotControl);\n            var axisOffset = param.axisOffset;\n            var planeOffset = param.planeOffset;\n            if (isHot)\n            {\n                axisOffset = Vector3.zero;\n                planeOffset = Vector3.zero;\n            }\n\n            // Draw plane handles (xy, yz, xz)\n            var planeSize = isHot ? param.planeSize + param.planeOffset : param.planeSize;\n            for (var i = 0; i < 3; ++i)\n            {\n                if (!param.ShouldShow(3 + i) || isHot && ids[3 + i] != GUIUtility.hotControl)\n                    continue;\n\n                var cameraLerp = isHot ? 0 : s_DoPositionHandle_Internal_CameraViewLerp[3 + i];\n                if (cameraLerp <= kCameraViewThreshold)\n                {\n                    var offset = planeOffset * size;\n                    offset[s_DoPositionHandle_Internal_PrevIndex[i]] = 0;\n                    var planarSize = Mathf.Max(planeSize[i], planeSize[s_DoPositionHandle_Internal_NextIndex[i]]);\n                    position = DoPlanarHandle(ids[3 + i], i, position, offset, rotation, size * planarSize, cameraLerp, viewVectorDrawSpace, param.planeOrientation);\n                }\n            }\n\n            // Draw axis sliders last to have priority over the planes\n            CalcDrawOrder(viewVectorDrawSpace, s_DoPositionHandle_Internal_AxisDrawOrder);\n            for (var ii = 0; ii < 3; ++ii)\n            {\n                int i = s_DoPositionHandle_Internal_AxisDrawOrder[ii];\n\n                if (!param.ShouldShow(i))\n                    continue;\n\n                if (!currentlyDragging)\n                {\n                    switch (param.axesOrientation)\n                    {\n                        case PositionHandleParam.Orientation.Camera:\n                            s_DoPositionHandle_AxisHandlesOctant[i] = viewVectorDrawSpace[i] > 0.01f ? -1 : 1;\n                            break;\n                        case PositionHandleParam.Orientation.Signed:\n                            s_DoPositionHandle_AxisHandlesOctant[i] = 1;\n                            break;\n                    }\n                }\n\n                var isThisAxisHot = isHot && ids[i] == GUIUtility.hotControl;\n\n                var axisColor = GetColorByAxis(i);\n                color = isDisabled ? Color.Lerp(axisColor, staticColor, staticBlend) : axisColor;\n                GUI.SetNextControlName(s_DoPositionHandle_Internal_AxisNames[i]);\n\n                // if we are hot here, the hot handle must be opaque\n                var cameraLerp = isThisAxisHot ? 0 : s_DoPositionHandle_Internal_CameraViewLerp[i];\n\n                if (cameraLerp <= kCameraViewThreshold)\n                {\n                    color = GetFadedAxisColor(color, cameraLerp, ids[i]);\n                    var axisVector = GetAxisVector(i);\n                    var dir = rotation * axisVector;\n                    var offset = dir * axisOffset[i] * size;\n\n                    dir *= s_DoPositionHandle_AxisHandlesOctant[i];\n                    offset *= s_DoPositionHandle_AxisHandlesOctant[i];\n\n                    if (isHot && !isThisAxisHot)\n                        color = s_DisabledHandleColor;\n\n                    // A plane with this axis is hot\n                    if (isHot && (ids[s_DoPositionHandle_Internal_PrevPlaneIndex[i]] == GUIUtility.hotControl || ids[i + 3] == GUIUtility.hotControl))\n                        color = selectedColor;\n\n                    color = ToActiveColorSpace(color);\n\n                    s_DoPositionHandle_ArrowCapConeOffset = isHot\n                        ? rotation * Vector3.Scale(Vector3.Scale(axisVector, param.axisOffset), s_DoPositionHandle_AxisHandlesOctant)\n                        : Vector3.zero;\n\n                    position = Slider(ids[i], position, offset, dir, size * param.axisSize[i], DoPositionHandle_ArrowCap, GridSnapping.active ? 0f : EditorSnapSettings.move[i]);\n                }\n            }\n\n            VertexSnapping.HandleMouseMove(ids.xyz);\n            if (param.ShouldShow(PositionHandleParam.Handle.XYZ) && (ids.xyz == GUIUtility.hotControl || !isHot))\n            {\n                color = ToActiveColorSpace(centerColor);\n                GUI.SetNextControlName(\"FreeMoveAxis\");\n                position = FreeMoveHandle(ids.xyz, position, size * kFreeMoveHandleSizeFactor, GridSnapping.active ? Vector3.zero : EditorSnapSettings.move, RectangleHandleCap);\n            }\n\n            if (GridSnapping.active)\n                position = GridSnapping.Snap(position);\n\n            color = temp;\n\n            return position;\n        }\n\n        static Vector3 DoPlanarHandle(\n            int id,\n            int planePrimaryAxis,\n            Vector3 position,\n            Vector3 offset,\n            Quaternion rotation,\n            float handleSize,\n            float cameraLerp,\n            Vector3 viewVectorDrawSpace,\n            PositionHandleParam.Orientation orientation)\n        {\n            var positionOffset = offset;\n\n            var axis1index = planePrimaryAxis;\n            var axis2index = (axis1index + 1) % 3;\n            var axisNormalIndex = (axis1index  + 2) % 3;\n\n            Color prevColor = Handles.color;\n\n            bool isDisabled = !GUI.enabled;\n            color = isDisabled ? staticColor : GetColorByAxis(axisNormalIndex);\n            color = GetFadedAxisColor(color, cameraLerp, id);\n\n            float faceOpacity = 0.8f;\n            if (GUIUtility.hotControl == id)\n                color = selectedColor;\n            else if (IsHovering(id, Event.current))\n                faceOpacity = 0.4f;\n            else\n                faceOpacity = 0.1f;\n\n            color = ToActiveColorSpace(color);\n\n\n            // NOTE: The planar transform handles always face toward the camera so they won't\n            // obscure each other (unlike the X, Y, and Z axis handles which always face in the\n            // positive axis directions). Whenever the octant that the camera is in (relative to\n            // to the transform tool) changes, we need to move the planar transform handle\n            // positions to the correct octant.\n\n            // Comments below assume axis1 is X and axis2 is Z to make it easier to visualize things.\n\n            // Shift the planar transform handle in the positive direction by half its\n            // handleSize so that it doesn't overlap in the center of the transform gizmo,\n            // and also move the handle origin into the octant that the camera is in.\n            // Don't update the actant while dragging to avoid too much distraction.\n            if (!currentlyDragging)\n            {\n                switch (orientation)\n                {\n                    case PositionHandleParam.Orientation.Camera:\n                        // Offset the X position of the handle in negative direction if camera is in the -X octants; otherwise positive.\n                        // Test against -0.01 instead of 0 to give a little bias to the positive quadrants. This looks better in axis views.\n                        s_PlanarHandlesOctant[axis1index] = (viewVectorDrawSpace[axis1index] > 0.01f ? -1 : 1);\n                        // Likewise with the other axis.\n                        s_PlanarHandlesOctant[axis2index] = (viewVectorDrawSpace[axis2index] > 0.01f ? -1 : 1);\n                        break;\n                    case PositionHandleParam.Orientation.Signed:\n                        s_PlanarHandlesOctant[axis1index] = 1;\n                        s_PlanarHandlesOctant[axis2index] = 1;\n                        break;\n                }\n            }\n            Vector3 handleOffset = s_PlanarHandlesOctant;\n            // Zero out the offset along the normal axis.\n            handleOffset[axisNormalIndex] = 0;\n            positionOffset = rotation * Vector3.Scale(positionOffset, handleOffset);\n            // Rotate and scale the offset\n            handleOffset = rotation * (handleOffset * handleSize * 0.5f);\n\n            // Calculate 3 axes\n            Vector3 axis1 = Vector3.zero;\n            Vector3 axis2 = Vector3.zero;\n            Vector3 axisNormal = Vector3.zero;\n            axis1[axis1index] = 1;\n            axis2[axis2index] = 1;\n            axisNormal[axisNormalIndex] = 1;\n            axis1 = rotation * axis1;\n            axis2 = rotation * axis2;\n            axisNormal = rotation * axisNormal;\n\n            // Draw the \"filler\" color for the handle\n            verts[0] = position + positionOffset + handleOffset + (axis1 + axis2) * handleSize * 0.5f;\n            verts[1] = position + positionOffset + handleOffset + (-axis1 + axis2) * handleSize * 0.5f;\n            verts[2] = position + positionOffset + handleOffset + (-axis1 - axis2) * handleSize * 0.5f;\n            verts[3] = position + positionOffset + handleOffset + (axis1 - axis2) * handleSize * 0.5f;\n            Color faceColor = new Color(color.r, color.g, color.b, color.a * faceOpacity);\n            Handles.DrawSolidRectangleWithOutline(verts, faceColor, Color.clear);\n\n            // And then render the handle itself (this is the colored outline)\n            position = Slider2D(id,\n                position,\n                handleOffset + positionOffset,\n                axisNormal,\n                axis1, axis2,\n                handleSize * 0.5f,\n                RectangleHandleCap,\n                GridSnapping.active ? Vector2.zero : new Vector2(EditorSnapSettings.move[axis1index], EditorSnapSettings.move[axis2index]),\n                false);\n\n            Handles.color = prevColor;\n\n            return position;\n        }\n\n        static void DoPositionHandle_ArrowCap(int controlId, Vector3 position, Quaternion rotation, float size, EventType eventType)\n        {\n            ArrowHandleCap(controlId, position, rotation, size, eventType, s_DoPositionHandle_ArrowCapConeOffset);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/RadiusHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class Handles\n    {\n        internal static float DoRadiusHandle(Quaternion rotation, Vector3 position, float radius, bool handlesOnly)\n        {\n            Vector3 planeNormal;\n            float frontAngle = 90;\n            Vector3[] dirs = new[]\n            {\n                rotation * Vector3.right,\n                      rotation * Vector3.up,\n                      rotation * Vector3.forward,\n                      rotation * -Vector3.right,\n                      rotation * -Vector3.up,\n                      rotation * -Vector3.forward\n            };\n\n            if (Camera.current.orthographic)\n            {\n                planeNormal = Camera.current.transform.forward;\n\n                if (!handlesOnly)\n                {\n                    // Draw periphery circle\n                    DrawWireDisc(position, planeNormal, radius);\n\n                    // Draw two-shaded axis-aligned circles\n                    for (int i = 0; i < 3; i++)\n                    {\n                        Vector3 from = Vector3.Cross(dirs[i], planeNormal).normalized;\n                        DrawTwoShadedWireDisc(position, dirs[i], from, 180, radius);\n                    }\n                }\n            }\n            else\n            {\n                // Since the geometry is transfromed by Handles.matrix during rendering, we transform the camera position\n                // by the inverse matrix so that the two-shaded wireframe will have the proper orientation.\n                Matrix4x4 invMatrix = Matrix4x4.Inverse(Handles.matrix);\n\n                planeNormal = position - invMatrix.MultiplyPoint(Camera.current.transform.position); // vector from camera to center\n                float sqrDist = planeNormal.sqrMagnitude; // squared distance from camera to center\n                float sqrRadius = radius * radius; // squared radius\n                float sqrOffset = sqrRadius * sqrRadius / sqrDist; // squared distance from actual center to drawn disc center\n                float insideAmount = sqrOffset / sqrRadius;\n\n                // If we are not inside the sphere, calculate where to draw the periphery\n                if (insideAmount < 1)\n                {\n                    float drawnRadius = Mathf.Sqrt(sqrRadius - sqrOffset); // the radius of the drawn disc\n                    frontAngle = Mathf.Atan2(drawnRadius, Mathf.Sqrt(sqrOffset)) * Mathf.Rad2Deg;\n\n                    // Draw periphery circle\n                    if (!handlesOnly)\n                        DrawWireDisc(position - sqrRadius * planeNormal / sqrDist, planeNormal, drawnRadius);\n                }\n                else\n                {\n                    frontAngle = -1000;\n                }\n\n                if (!handlesOnly)\n                {\n                    // Draw two-shaded axis-aligned circles\n                    for (int i = 0; i < 3; i++)\n                    {\n                        if (insideAmount < 1)\n                        {\n                            float Q = Vector3.Angle(planeNormal, dirs[i]);\n                            Q = 90 - Mathf.Min(Q, 180 - Q);\n                            float f = Mathf.Tan(Q * Mathf.Deg2Rad);\n                            float g = Mathf.Sqrt(sqrOffset + f * f * sqrOffset) / radius;\n                            if (g < 1)\n                            {\n                                float e = Mathf.Asin(g) * Mathf.Rad2Deg;\n                                Vector3 from = Vector3.Cross(dirs[i], planeNormal).normalized;\n                                from = Quaternion.AngleAxis(e, dirs[i]) * from;\n                                DrawTwoShadedWireDisc(position, dirs[i], from, (90 - e) * 2, radius);\n                            }\n                            else\n                            {\n                                DrawTwoShadedWireDisc(position, dirs[i], radius);\n                            }\n                        }\n                        else\n                        {\n                            DrawTwoShadedWireDisc(position, dirs[i], radius);\n                        }\n                    }\n                }\n            }\n\n            Color origCol = color;\n\n            // Draw handles\n            for (int i = 0; i < 6; i++)\n            {\n                // Get the id no matter if we're drawing the slider or not,\n                // in order to not corrupt the id order when slider handles pop in and out.\n                int id = GUIUtility.GetControlID(s_RadiusHandleHash, FocusType.Passive);\n\n                // The angle between the axis and the center-camera vector\n                float angle = Vector3.Angle(dirs[i], -planeNormal);\n\n                // Don't make the slider if the axis is pointing almost towards or away from the camera,\n                // but always draw it if the user is already dragging it.\n                if ((angle > 5 && angle < 175) || GUIUtility.hotControl == id)\n                {\n                    // Give handles twice the alpha of the lines.\n                    // If handle is not on front side of sphere, make it dimmer.\n                    Color col = origCol;\n                    if (angle > frontAngle + 5f)\n                        col.a = Mathf.Clamp01(backfaceAlphaMultiplier * origCol.a * 2);\n                    else\n                        col.a = Mathf.Clamp01(origCol.a * 2);\n                    color = ToActiveColorSpace(col);\n\n                    Vector3 pos = position + radius * dirs[i];\n                    bool temp = GUI.changed;\n                    GUI.changed = false;\n                    pos = Slider1D.Do(id, pos, dirs[i], HandleUtility.GetHandleSize(pos) * 0.03f, DotHandleCap, 0);\n\n\n                    if (GUI.changed)\n                        radius = Vector3.Distance(pos, position);\n                    GUI.changed |= temp;\n                }\n            }\n\n            color = origCol;\n\n            return radius;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/RectHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class Handles\n    {\n        internal static Vector2 DoRectHandles(Quaternion rotation, Vector3 position, Vector2 size, bool handlesOnly)\n        {\n            Vector3 up = rotation * Vector3.up;\n            Vector3 right = rotation * Vector3.right;\n\n            float halfWidth = 0.5f * size.x;\n            float halfHeight = 0.5f * size.y;\n\n            if (!handlesOnly)\n            {\n                Vector3 topRight = position + up * halfHeight + right * halfWidth;\n                Vector3 bottomRight = position - up * halfHeight + right * halfWidth;\n                Vector3 bottomLeft = position - up * halfHeight - right * halfWidth;\n                Vector3 topLeft = position + up * halfHeight - right * halfWidth;\n\n                // Draw rectangle\n                DrawLine(topRight, bottomRight);\n                DrawLine(bottomRight, bottomLeft);\n                DrawLine(bottomLeft, topLeft);\n                DrawLine(topLeft, topRight);\n            }\n\n            // Give handles twice the alpha of the lines\n            Color origCol = color;\n            Color col = color;\n            col.a = Mathf.Clamp01(color.a * 2);\n            color = ToActiveColorSpace(col);\n\n            // Draw handles\n            halfHeight = SizeSlider(position, up, halfHeight);\n            halfHeight = SizeSlider(position, -up, halfHeight);\n            halfWidth = SizeSlider(position, right, halfWidth);\n            halfWidth = SizeSlider(position, -right, halfWidth);\n\n            size.x = Mathf.Max(0f, 2.0f * halfWidth);\n            size.y = Mathf.Max(0f, 2.0f * halfHeight);\n\n            color = origCol;\n\n            return size;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/RotationHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.Snap;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class Handles\n    {\n        /// <summary>\n        /// Set of IDs corresponding to the handles of Handles.RotationHandle.\n        /// </summary>\n        public struct RotationHandleIds\n        {\n            /// <summary>\n            /// Default set of IDs to pass to Handles.RotationHandle.\n            /// </summary>\n            public static RotationHandleIds @default\n            {\n                get\n                {\n                    return new RotationHandleIds(\n                        GUIUtility.GetControlID(s_xRotateHandleHash, FocusType.Passive),\n                        GUIUtility.GetControlID(s_yRotateHandleHash, FocusType.Passive),\n                        GUIUtility.GetControlID(s_zRotateHandleHash, FocusType.Passive),\n                        GUIUtility.GetControlID(s_cameraAxisRotateHandleHash, FocusType.Passive),\n                        GUIUtility.GetControlID(s_xyzRotateHandleHash, FocusType.Passive)\n                    );\n                }\n            }\n\n            public readonly int x, y, z, cameraAxis, xyz;\n\n            internal int this[int index]\n            {\n                get\n                {\n                    switch (index)\n                    {\n                        case 0: return x;\n                        case 1: return y;\n                        case 2: return z;\n                        case 3: return cameraAxis;\n                        case 4: return xyz;\n                    }\n                    return -1;\n                }\n            }\n\n            internal bool Has(int id)\n            {\n                return x == id\n                    || y == id\n                    || z == id\n                    || cameraAxis == id\n                    || xyz == id;\n            }\n\n            internal RotationHandleIds(int x, int y, int z, int cameraAxis, int xyz)\n            {\n                this.x = x;\n                this.y = y;\n                this.z = z;\n                this.cameraAxis = cameraAxis;\n                this.xyz = xyz;\n            }\n\n            public override int GetHashCode()\n            {\n                return x ^ y ^ z ^ cameraAxis ^ xyz;\n            }\n\n            public override bool Equals(object obj)\n            {\n                if (!(obj is RotationHandleIds))\n                    return false;\n\n                var o = (RotationHandleIds)obj;\n                return o.x == x && o.y == y && o.z == z\n                    && o.cameraAxis == cameraAxis && o.xyz == xyz;\n            }\n        }\n\n        internal struct RotationHandleParam\n        {\n            [Flags]\n            public enum Handle\n            {\n                None = 0,\n                X = 1 << 0,\n                Y = 1 << 1,\n                Z = 1 << 2,\n                CameraAxis = 1 << 3,\n                XYZ = 1 << 4,\n                All = ~None\n            }\n\n            static RotationHandleParam s_Default = new RotationHandleParam((Handle)(-1), Vector3.one, 1f, 1.1f, true, true);\n            public static RotationHandleParam Default { get { return s_Default; } set { s_Default = value; } }\n\n            public readonly Vector3 axisSize;\n            public readonly float cameraAxisSize;\n            public readonly float xyzSize;\n            public readonly Handle handles;\n            public readonly bool enableRayDrag;\n            public readonly bool displayXYZCircle;\n\n            public bool ShouldShow(int axis)\n            {\n                return (handles & (Handle)(1 << axis)) != 0;\n            }\n\n            public bool ShouldShow(Handle handle)\n            {\n                return (handles & handle) != 0;\n            }\n\n            public RotationHandleParam(Handle handles, Vector3 axisSize, float xyzSize, float cameraAxisSize, bool enableRayDrag, bool displayXYZCircle)\n            {\n                this.axisSize = axisSize;\n                this.xyzSize = xyzSize;\n                this.handles = handles;\n                this.cameraAxisSize = cameraAxisSize;\n                this.enableRayDrag = enableRayDrag;\n                this.displayXYZCircle = displayXYZCircle;\n            }\n        }\n\n        static readonly Color k_RotationPieColor = new Color(246f / 255, 242f / 255, 50f / 255, .89f);\n\n        public static Quaternion DoRotationHandle(Quaternion rotation, Vector3 position)\n        {\n            return DoRotationHandle(RotationHandleIds.@default, rotation, position, RotationHandleParam.Default);\n        }\n\n        internal static Quaternion DoRotationHandle(RotationHandleIds ids, Quaternion rotation, Vector3 position, RotationHandleParam param)\n        {\n            var evt = Event.current;\n            var camForward = Handles.inverseMatrix.MultiplyVector(Camera.current != null ? Camera.current.transform.forward : Vector3.forward);\n\n            var size = HandleUtility.GetHandleSize(position);\n            var temp = color;\n            bool isDisabled = !GUI.enabled;\n\n            var isHot = ids.Has(GUIUtility.hotControl);\n\n            VertexSnapping.HandleMouseMove(ids.xyz);\n\n            // Draw free rotation first to give it the lowest priority\n            if (!isDisabled\n                && param.ShouldShow(RotationHandleParam.Handle.XYZ)\n                && (ids.xyz == GUIUtility.hotControl || !isHot))\n            {\n                color = new Color(0, 0, 0, 0.3f);\n                rotation = UnityEditorInternal.FreeRotate.Do(ids.xyz, rotation, position, size * param.xyzSize, param.displayXYZCircle);\n            }\n\n            for (var i = 0; i < 3; ++i)\n            {\n                if (!param.ShouldShow(i))\n                    continue;\n\n                var axisColor = GetColorByAxis(i);\n                color = isDisabled ? Color.Lerp(axisColor, staticColor, staticBlend) : axisColor;\n                color = ToActiveColorSpace(color);\n                var axisDir = GetAxisVector(i);\n\n                var radius = size * param.axisSize[i];\n                rotation = UnityEditorInternal.Disc.Do(ids[i], rotation, position, rotation * axisDir, radius, true, EditorSnapSettings.rotate, param.enableRayDrag, true, k_RotationPieColor);\n            }\n\n            // while dragging any rotation handles, draw a gray disc outline\n            if (isHot && evt.type == EventType.Repaint)\n            {\n                color = ToActiveColorSpace(s_DisabledHandleColor);\n                Handles.DrawWireDisc(position, camForward, size * param.axisSize[0], Handles.lineThickness);\n            }\n\n            if (!isDisabled\n                && param.ShouldShow(RotationHandleParam.Handle.CameraAxis)\n                && (ids.cameraAxis == GUIUtility.hotControl || !isHot))\n            {\n                color = ToActiveColorSpace(centerColor);\n                rotation = UnityEditorInternal.Disc.Do(ids.cameraAxis, rotation, position, camForward, size * param.cameraAxisSize, false, 0, param.enableRayDrag, true, k_RotationPieColor);\n            }\n\n            color = temp;\n            return rotation;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/ScaleHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class Handles\n    {\n        internal struct ScaleHandleIds\n        {\n            public static ScaleHandleIds @default\n            {\n                get\n                {\n                    return new ScaleHandleIds(\n                        GUIUtility.GetControlID(s_xScaleHandleHash, FocusType.Passive),\n                        GUIUtility.GetControlID(s_yScaleHandleHash, FocusType.Passive),\n                        GUIUtility.GetControlID(s_zScaleHandleHash, FocusType.Passive),\n                        GUIUtility.GetControlID(s_xyzScaleHandleHash, FocusType.Passive)\n                    );\n                }\n            }\n\n            public readonly int x, y, z, xyz;\n\n            public int this[int index]\n            {\n                get\n                {\n                    switch (index)\n                    {\n                        case 0: return x;\n                        case 1: return y;\n                        case 2: return z;\n                        case 3: return xyz;\n                    }\n                    return -1;\n                }\n            }\n\n            public bool Has(int id)\n            {\n                return x == id\n                    || y == id\n                    || z == id\n                    || xyz == id;\n            }\n\n            public ScaleHandleIds(int x, int y, int z, int xyz)\n            {\n                this.x = x;\n                this.y = y;\n                this.z = z;\n                this.xyz = xyz;\n            }\n\n            public override int GetHashCode()\n            {\n                return x ^ y ^ z ^ xyz;\n            }\n\n            public override bool Equals(object obj)\n            {\n                if (!(obj is ScaleHandleIds))\n                    return false;\n\n                var o = (ScaleHandleIds)obj;\n                return o.x == x && o.y == y && o.z == z\n                    && o.xyz == xyz;\n            }\n        }\n\n        internal struct ScaleHandleParam\n        {\n            [Flags]\n            public enum Handle\n            {\n                None = 0,\n                X = 1 << 0,\n                Y = 1 << 1,\n                Z = 1 << 2,\n                XYZ = 1 << 3,\n                All = ~None\n            }\n\n            public enum Orientation\n            {\n                Signed,\n                Camera\n            }\n\n            static ScaleHandleParam s_Default = new ScaleHandleParam((Handle)(-1), Vector3.zero, Vector3.one, Vector3.one, 1, Orientation.Signed);\n            public static ScaleHandleParam Default { get { return s_Default; } set { s_Default = value; } }\n\n            public readonly Vector3 axisOffset;\n            public readonly Vector3 axisSize;\n            public readonly Vector3 axisLineScale;\n            public readonly float xyzSize;\n            public readonly Handle handles;\n            public readonly Orientation orientation;\n\n            public bool ShouldShow(int axis)\n            {\n                return (handles & (Handle)(1 << axis)) != 0;\n            }\n\n            public bool ShouldShow(Handle handle)\n            {\n                return (handles & handle) != 0;\n            }\n\n            public ScaleHandleParam(Handle handles, Vector3 axisOffset, Vector3 axisSize, Vector3 axisLineScale, float xyzSize, Orientation orientation)\n            {\n                this.axisOffset = axisOffset;\n                this.axisSize = axisSize;\n                this.axisLineScale = axisLineScale;\n                this.xyzSize = xyzSize;\n                this.handles = handles;\n                this.orientation = orientation;\n            }\n        }\n\n        static Vector3 s_DoScaleHandle_AxisHandlesOctant = Vector3.one;\n        static int[] s_DoScaleHandle_AxisDrawOrder = { 0, 1, 2 };\n        static float s_CurrentMultiplier;\n        static Vector3 s_InitialScale;\n        internal static float handleLength { get; set;}\n        internal static bool proportionalScale { get; set; }\n\n        public static Vector3 DoScaleHandle(Vector3 scale, Vector3 position, Quaternion rotation, float size)\n        {\n            return DoScaleHandle(ScaleHandleIds.@default, scale, position, rotation, size, ScaleHandleParam.Default, false);\n        }\n\n        internal static Vector3 DoScaleHandle(Vector3 scale, Vector3 position, Quaternion rotation, float size, bool isProportionalScale)\n        {\n            return DoScaleHandle(ScaleHandleIds.@default, scale, position, rotation, size, ScaleHandleParam.Default, isProportionalScale);\n        }\n\n        internal static Vector3 DoScaleHandle(ScaleHandleIds ids, Vector3 scale, Vector3 position, Quaternion rotation, float handleSize, ScaleHandleParam param, bool isProportionalScale = false)\n        {\n            // Calculate the camera view vector in Handle draw space\n            // this handle the case where the matrix is skewed\n            var handlePosition = matrix.MultiplyPoint3x4(position);\n            var drawToWorldMatrix = matrix * Matrix4x4.TRS(position, rotation, Vector3.one);\n            var invDrawToWorldMatrix = drawToWorldMatrix.inverse;\n            var viewVectorDrawSpace = GetCameraViewFrom(handlePosition, invDrawToWorldMatrix);\n\n            var isDisabled = !GUI.enabled;\n\n            var isHot = ids.Has(GUIUtility.hotControl);\n\n            var axisOffset = param.axisOffset;\n            var axisLineScale = param.axisLineScale;\n            // When an axis is hot, draw the line from the center to the handle\n            // So ignore the offset\n            if (isHot)\n            {\n                axisLineScale += axisOffset;\n                axisOffset = Vector3.zero;\n            }\n\n            var isCenterIsHot = ids.xyz == GUIUtility.hotControl;\n            VertexSnapping.HandleMouseMove(ids.xyz);\n\n            switch (Event.current.type)\n            {\n                case EventType.MouseDown:\n                    s_InitialScale = scale == Vector3.zero ? Vector3.one : scale;\n                    s_CurrentMultiplier = 1.0f;\n                    break;\n                case EventType.MouseDrag:\n                    if (isProportionalScale)\n                        proportionalScale = true;\n                    break;\n                case EventType.MouseUp:\n                    proportionalScale = false;\n                    break;\n            }\n\n            CalcDrawOrder(viewVectorDrawSpace, s_DoScaleHandle_AxisDrawOrder);\n            for (var ii = 0; ii < 3; ++ii)\n            {\n                int i = s_DoScaleHandle_AxisDrawOrder[ii];\n                int axisIndex = i;\n                if (!param.ShouldShow(i))\n                    continue;\n\n                if (!currentlyDragging)\n                {\n                    switch (param.orientation)\n                    {\n                        case ScaleHandleParam.Orientation.Signed:\n                            s_DoScaleHandle_AxisHandlesOctant[i] = 1;\n                            break;\n                        case ScaleHandleParam.Orientation.Camera:\n                            s_DoScaleHandle_AxisHandlesOctant[i] = viewVectorDrawSpace[i] > 0.01f ? -1 : 1;\n                            break;\n                    }\n                }\n\n\n                var id = ids[i];\n                var isThisAxisHot = isHot && id == GUIUtility.hotControl;\n\n                var axisDir = GetAxisVector(i);\n                var axisColor = isProportionalScale ? constrainProportionsScaleHandleColor : GetColorByAxis(i);\n                var offset = axisOffset[i];\n                var cameraLerp = id == GUIUtility.hotControl ? 0 : GetCameraViewLerpForWorldAxis(viewVectorDrawSpace, axisDir);\n                // If we are here and is hot, then this axis is hot and must be opaque\n                cameraLerp = isHot ? 0 : cameraLerp;\n                color = isDisabled ? Color.Lerp(axisColor, staticColor, staticBlend) : axisColor;\n\n                axisDir *= s_DoScaleHandle_AxisHandlesOctant[i];\n\n                if (cameraLerp <= kCameraViewThreshold)\n                {\n                    color = GetFadedAxisColor(color, cameraLerp, id);\n\n                    if (isHot && !isThisAxisHot)\n                        color = isProportionalScale ? selectedColor : s_DisabledHandleColor;\n\n                    if (isCenterIsHot)\n                        color = selectedColor;\n\n                    color = ToActiveColorSpace(color);\n\n                    if (isProportionalScale)\n                        axisIndex = 0;\n\n                    scale = UnityEditorInternal.SliderScale.DoAxis(\n                        id,\n                        scale,\n                        axisIndex,\n                        position,\n                        rotation * axisDir,\n                        rotation,\n                        handleSize * param.axisSize[axisIndex],\n                        EditorSnapSettings.scale,\n                        offset,\n                        axisLineScale[axisIndex],\n                        s_InitialScale,\n                        isProportionalScale);\n                }\n            }\n\n            if (param.ShouldShow(ScaleHandleParam.Handle.XYZ) && (ids.xyz == GUIUtility.hotControl || !isHot))\n            {\n                color = isProportionalScale ? constrainProportionsScaleHandleColor : ToActiveColorSpace(centerColor);\n                if (isDisabled)\n                    color = Color.Lerp(color, staticColor, staticBlend);\n                proportionalScale = false;\n                EditorGUI.BeginChangeCheck();\n                s_CurrentMultiplier = ScaleValueHandle(ids.xyz, s_CurrentMultiplier, position, rotation, handleSize * param.xyzSize, CubeHandleCap, EditorSnapSettings.scale);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    scale = s_InitialScale * s_CurrentMultiplier;\n                }\n            }\n\n            return scale;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/SimpleRadiusHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class Handles\n    {\n        internal static float DoSimpleEdgeHandle(Quaternion rotation, Vector3 position, float radius, bool editable = true)\n        {\n            if (Event.current.alt)\n                editable = false;\n\n            Vector3 right = rotation * Vector3.right;\n\n            if (editable)\n            {\n                // Radius handles at ends\n                EditorGUI.BeginChangeCheck();\n                radius = SizeSlider(position, right, radius);\n                radius = SizeSlider(position, -right, radius);\n                if (EditorGUI.EndChangeCheck())\n                    radius = Mathf.Max(0.0f, radius);\n            }\n\n            // Draw gizmo\n            if (radius > 0)\n                DrawLine(position - right * radius, position + right * radius);\n\n            return radius;\n        }\n\n        internal static float DoSimpleRadiusHandle(Quaternion rotation, Vector3 position, float radius, bool hemisphere, float arc = 360.0f, bool editable = true)\n        {\n            if (Event.current.alt)\n                editable = false;\n\n            Vector3 forward = rotation * Vector3.forward;\n            Vector3 up = rotation * Vector3.up;\n            Vector3 right = rotation * Vector3.right;\n\n            if (editable)\n            {\n                // Radius handle in zenith\n                bool temp = GUI.changed;\n                GUI.changed = false;\n                radius = SizeSlider(position, forward, radius);\n                if (!hemisphere)\n                    radius = SizeSlider(position, -forward, radius);\n                if (GUI.changed)\n                    radius = Mathf.Max(0.0f, radius);\n                GUI.changed |= temp;\n\n                // Radius handles at disc\n                temp = GUI.changed;\n                GUI.changed = false;\n                radius = SizeSlider(position, right, radius);\n                if (arc >= 90.0f)\n                    radius = SizeSlider(position, up, radius);\n                if (arc >= 180.0f)\n                    radius = SizeSlider(position, -right, radius);\n                if (arc >= 270.0f)\n                    radius = SizeSlider(position, -up, radius);\n                if (GUI.changed)\n                    radius = Mathf.Max(0.0f, radius);\n                GUI.changed |= temp;\n            }\n\n            // Draw gizmo\n            if (radius > 0)\n            {\n                DrawWireArc(position, forward, right, arc, radius);\n                DrawWireArc(position, up, forward, hemisphere ? 90 : 180, radius);\n\n                for (int quarter = 0; quarter < 4; quarter++)\n                {\n                    if (arc >= (90.0f * quarter))\n                    {\n                        Vector3 normal = Matrix4x4.Rotate(Quaternion.Euler(0.0f, 0.0f, 90.0f * quarter)) * up;\n                        DrawWireArc(position, normal, forward, hemisphere ? 90 : 180, radius);\n                    }\n                }\n\n                Vector3 capNormal = Matrix4x4.Rotate(Quaternion.Euler(0.0f, 0.0f, arc)) * up;\n                DrawWireArc(position, capNormal, forward, hemisphere ? 90 : 180, radius);\n            }\n            return radius;\n        }\n\n        //  static void DrawHemispherePeriphery (Vector3 position, float radius)\n        //  {\n        //      Vector3 planeNormal = position - Camera.current.transform.position; // vector from camera to center\n        //      float sqrDist = planeNormal.sqrMagnitude; // squared distance from camera to center\n        //      float sqrRadius = radius * radius; // squared radius\n        //      float sqrOffset = sqrRadius * sqrRadius / sqrDist; // squared distance from actual center to drawn disc center\n        //      float insideAmount = sqrOffset / sqrRadius;\n        //\n        //      // If we are not inside the sphere, calculate where to draw the periphery\n        //      if (insideAmount < 1)\n        //      {\n        //          float drawnRadius = Mathf.Sqrt(sqrRadius - sqrOffset); // the radius of the drawn disc\n        //\n        //          // Draw periphery circle\n        //          Vector3 tangent = Vector3.Cross(planeNormal, Vector3.up);\n        //          if (tangent.sqrMagnitude < .001f)\n        //              tangent = Vector3.Cross(planeNormal, Vector3.right);\n        //          DrawWireArc(position - sqrRadius * planeNormal / sqrDist, planeNormal, tangent, -180, drawnRadius);\n        //      }\n        //  }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/Slider1D.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    internal class Slider1D\n    {\n        // Used for plane intersection translation\n        static Vector3 s_ConstraintOrigin, s_ConstraintDirection, s_HandleOffset;\n        static float s_StartHandleSize;\n        static Matrix4x4 s_StartInverseHandleMatrix;\n\n        // Used for 2D translation (fallback when ray plane intersection fails)\n        static Vector2 s_StartMousePosition;\n        static Vector3 s_StartPosition;\n\n        internal static Vector3 Do(int id, Vector3 position, Vector3 direction, float size, Handles.CapFunction capFunction, float snap)\n        {\n            return Do(id, position, Vector3.zero, direction, direction, size, capFunction, snap);\n        }\n\n        private static Quaternion ToQuaternion(Vector3 direction)\n        {\n            if (direction == Vector3.zero)\n            {\n                return Quaternion.identity;\n            }\n            return Quaternion.LookRotation(direction);\n        }\n\n        internal static Vector3 Do(int id, Vector3 position, Vector3 offset, Vector3 handleDirection, Vector3 slideDirection, float size, Handles.CapFunction capFunction, float snap)\n        {\n            Event evt = Event.current;\n            var eventType = evt.GetTypeForControl(id);\n            switch (eventType)\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    if (capFunction != null)\n                        capFunction(id, position + offset, ToQuaternion(handleDirection), size, EventType.Layout);\n                    else\n                        HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(position + offset, size * .2f));\n                    break;\n\n                case EventType.MouseDown:\n                    // am I closest to the thingy?\n                    if (HandleUtility.nearestControl == id && evt.button == 0 && GUIUtility.hotControl == 0 && !evt.alt)\n                    {\n                        GUIUtility.hotControl = id;    // Grab mouse focus\n                        s_StartMousePosition = evt.mousePosition;\n                        s_ConstraintOrigin = Handles.matrix.MultiplyPoint3x4(position);\n                        s_StartPosition = position;\n                        s_ConstraintDirection = Handles.matrix.MultiplyVector(slideDirection);\n                        s_HandleOffset = HandleUtility.CalcPositionOnConstraint(Camera.current, evt.mousePosition, s_ConstraintOrigin, s_ConstraintDirection, out Vector3 point)\n                            ? s_ConstraintOrigin - point\n                            : Vector3.zero;\n                        evt.Use();\n                        s_StartHandleSize = HandleUtility.GetHandleSize(point);\n                        s_StartInverseHandleMatrix = Handles.inverseMatrix;\n                    }\n\n                    break;\n\n                case EventType.MouseDrag:\n\n                    capFunction?.Invoke(id, position + offset, ToQuaternion(handleDirection), size, EventType.Layout);\n\n                    if (GUIUtility.hotControl == id)\n                    {\n                        // First try to calculate the translation by casting a mouse ray against a world position plane\n                        // oriented towards the camera. This gives more accurate results than doing the line translation\n                        // in 2D space, but is more prone towards skewing extreme values when the ray is near parallel\n                        // to the plane. To address this, CalcPositionOnConstraint will fail if the mouse ray is close\n                        // to parallel (see HandleUtility.k_MinRayConstraintDot) and fall back to 2D based movement.\n                        if (HandleUtility.CalcPositionOnConstraint(Camera.current, evt.mousePosition, s_ConstraintOrigin, s_ConstraintDirection, out Vector3 worldPosition))\n                        {\n                            var handleOffset = s_HandleOffset * (HandleUtility.GetHandleSize(worldPosition) / s_StartHandleSize);\n                            worldPosition += handleOffset;\n\n                            if (EditorSnapSettings.incrementalSnapActive)\n                            {\n                                Vector3 dir = worldPosition - s_ConstraintOrigin;\n                                float dist = Handles.SnapValue(dir.magnitude, snap) * Mathf.Sign(Vector3.Dot(s_ConstraintDirection, dir));\n                                worldPosition = s_ConstraintOrigin + s_ConstraintDirection.normalized * dist;\n                            }\n                            else if (EditorSnapSettings.gridSnapActive)\n                            {\n                                worldPosition = Snapping.Snap(worldPosition, GridSettings.size, (SnapAxis) new SnapAxisFilter(s_ConstraintDirection));\n                            }\n\n                            position = s_StartInverseHandleMatrix.MultiplyPoint(worldPosition);\n\n                            s_StartPosition = position;\n                            s_StartMousePosition = evt.mousePosition;\n                        }\n                        else\n                        {\n                            // Unlike HandleUtility.CalcPositionOnConstraint, CalcLineTranslation _does_ multiply constraint\n                            // origin and direction by Handles.matrix, so make sure to pass in unmodified vectors here\n                            float dist = HandleUtility.CalcLineTranslation(s_StartMousePosition, evt.mousePosition, s_StartPosition, slideDirection);\n                            dist = Handles.SnapValue(dist, snap);\n                            worldPosition = Handles.matrix.MultiplyPoint(s_StartPosition) + s_ConstraintDirection * dist;\n                            if (EditorSnapSettings.gridSnapActive)\n                                worldPosition = Snapping.Snap(worldPosition, GridSettings.size, (SnapAxis) new SnapAxisFilter(s_ConstraintDirection));\n                            position = Handles.inverseMatrix.MultiplyPoint(worldPosition);\n                        }\n\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))\n                    {\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.Repaint:\n                    Handles.SetupHandleColor(id, evt, out var prevColor, out var thickness);\n                    capFunction(id, position + offset, ToQuaternion(handleDirection), size, EventType.Repaint);\n                    Handles.color = prevColor;\n                    break;\n            }\n            return position;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/Slider2D.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    internal class Slider2D\n    {\n        private static Vector2 s_CurrentMousePosition;\n        private static Vector3 s_StartPosition;\n        private static Vector2 s_StartPlaneOffset;\n\n        // Returns the new handlePos\n        public static Vector3 Do(\n            int id,\n            Vector3 handlePos,\n            Vector3 handleDir,\n            Vector3 slideDir1,\n            Vector3 slideDir2,\n            float handleSize,\n            Handles.CapFunction capFunction,\n            float snap,\n            bool drawHelper)\n        {\n            return Do(id, handlePos, new Vector3(0, 0, 0), handleDir, slideDir1, slideDir2, handleSize, capFunction, new Vector2(snap, snap), drawHelper);\n        }\n\n        // Returns the new handlePos\n        public static Vector3 Do(\n            int id,\n            Vector3 handlePos,\n            Vector3 offset,\n            Vector3 handleDir,\n            Vector3 slideDir1,\n            Vector3 slideDir2,\n            float handleSize,\n            Handles.CapFunction capFunction,\n            float snap,\n            bool drawHelper)\n        {\n            return Do(id, handlePos, offset, handleDir, slideDir1, slideDir2, handleSize, capFunction, new Vector2(snap, snap), drawHelper);\n        }\n\n        // Returns the new handlePos\n        public static Vector3 Do(\n            int id,\n            Vector3 handlePos,\n            Vector3 offset,\n            Vector3 handleDir,\n            Vector3 slideDir1,\n            Vector3 slideDir2,\n            float handleSize,\n            Handles.CapFunction capFunction,\n            Vector2 snap,\n            bool drawHelper)\n        {\n            bool orgGuiChanged = GUI.changed;\n            GUI.changed = false;\n\n            Vector2 delta = CalcDeltaAlongDirections(id, handlePos, offset, handleDir, slideDir1, slideDir2, handleSize, capFunction, snap, drawHelper);\n            if (GUI.changed)\n            {\n                handlePos = s_StartPosition + slideDir1 * delta.x + slideDir2 * delta.y;\n\n                if (EditorSnapSettings.gridSnapActive)\n                {\n                    var normal = Vector3.Cross(slideDir1, slideDir2);\n\n                    if (Snapping.IsCardinalDirection(normal))\n                    {\n                        var worldSpace = Handles.matrix.MultiplyPoint(handlePos);\n                        worldSpace = Snapping.Snap(worldSpace, GridSettings.size, (SnapAxis) ~new SnapAxisFilter(normal));\n                        handlePos = Handles.inverseMatrix.MultiplyPoint(worldSpace);\n                    }\n                }\n            }\n\n            GUI.changed |= orgGuiChanged;\n            return handlePos;\n        }\n\n        // Returns the distance the new position has moved along slideDir1 and slideDir2\n        private static Vector2 CalcDeltaAlongDirections(\n            int id,\n            Vector3 handlePos,\n            Vector3 offset,\n            Vector3 handleDir,\n            Vector3 slideDir1,\n            Vector3 slideDir2,\n            float handleSize,\n            Handles.CapFunction capFunction,\n            Vector2 snap,\n            bool drawHelper)\n        {\n            Vector3 position = handlePos + offset;\n            Quaternion rotation = Quaternion.LookRotation(handleDir, slideDir1);\n            Vector2 deltaDistanceAlongDirections = new Vector2(0, 0);\n\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    if (capFunction != null)\n                        capFunction(id, position, rotation, handleSize, EventType.Layout);\n                    else\n                        HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(handlePos + offset, handleSize * .5f));\n                    break;\n\n                case EventType.MouseDown:\n                    // am I closest to the thingy?\n                    if (HandleUtility.nearestControl == id && evt.button == 0 && GUIUtility.hotControl == 0 && !evt.alt)\n                    {\n                        s_CurrentMousePosition = evt.mousePosition;\n                        bool success = true;\n                        Vector3 localMousePoint = Handles.inverseMatrix.MultiplyPoint(GetMousePosition(handleDir, handlePos, ref success));\n                        if (success)\n                        {\n                            GUIUtility.hotControl = id; // Grab mouse focus\n                            s_StartPosition = handlePos;\n\n                            Vector3 clickOffset = localMousePoint - handlePos;\n                            s_StartPlaneOffset.x = Vector3.Dot(clickOffset, slideDir1);\n                            s_StartPlaneOffset.y = Vector3.Dot(clickOffset, slideDir2);\n\n                            evt.Use();\n                            EditorGUIUtility.SetWantsMouseJumping(1);\n                        }\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n\n                    capFunction?.Invoke(id, position, rotation, handleSize, EventType.Layout);\n\n                    if (GUIUtility.hotControl == id)\n                    {\n                        Vector2 mouseDelta = evt.mousePosition - s_CurrentMousePosition;\n                        s_CurrentMousePosition += mouseDelta;\n                        bool success = true;\n                        Vector3 localMousePoint = Handles.inverseMatrix.MultiplyPoint(GetMousePosition(handleDir, handlePos, ref success));\n                        if (success)\n                        {\n                            // Determine hitpos projection onto slideDirs\n                            deltaDistanceAlongDirections.x = HandleUtility.PointOnLineParameter(localMousePoint, s_StartPosition, slideDir1);\n                            deltaDistanceAlongDirections.y = HandleUtility.PointOnLineParameter(localMousePoint, s_StartPosition, slideDir2);\n                            deltaDistanceAlongDirections -= s_StartPlaneOffset;\n                            deltaDistanceAlongDirections.x = Handles.SnapValue(deltaDistanceAlongDirections.x, snap.x);\n                            deltaDistanceAlongDirections.y = Handles.SnapValue(deltaDistanceAlongDirections.y, snap.y);\n\n                            GUI.changed = true;\n                        }\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))\n                    {\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(0);\n                    }\n                    break;\n\n                case EventType.Repaint:\n                {\n                    if (capFunction == null)\n                        break;\n\n                    Handles.SetupHandleColor(id, evt, out var prevColor, out var thickness);\n                    capFunction(id, position, rotation, handleSize, EventType.Repaint);\n                    Handles.color = prevColor;\n\n                    // Draw a helper rectangle to show what plane we are dragging in\n                    if (drawHelper && GUIUtility.hotControl == id)\n                    {\n                        Vector3[] verts = new Vector3[4];\n                        float helperSize = handleSize * 10.0f;\n                        verts[0] = position + (slideDir1 * helperSize + slideDir2 * helperSize);\n                        verts[1] = verts[0] - slideDir1 * helperSize * 2.0f;\n                        verts[2] = verts[1] - slideDir2 * helperSize * 2.0f;\n                        verts[3] = verts[2] + slideDir1 * helperSize * 2.0f;\n                        Handles.color = Color.white;\n                        float outline = 0.6f;\n                        Handles.DrawSolidRectangleWithOutline(verts, new Color(1, 1, 1, 0.05f), new Color(outline, outline, outline, 0.4f));\n                        Handles.color = prevColor;\n                    }\n                }\n\n                break;\n            }\n\n            return deltaDistanceAlongDirections;\n        }\n\n        private static Vector3 GetMousePosition(Vector3 handleDirection, Vector3 handlePosition, ref bool success)\n        {\n            if (Camera.current != null)\n            {\n                Plane plane = new Plane(Handles.matrix.MultiplyVector(handleDirection), Handles.matrix.MultiplyPoint(handlePosition));\n                Ray mouseRay = HandleUtility.GUIPointToWorldRay(s_CurrentMousePosition);\n                float dist = 0.0f;\n                success = plane.Raycast(mouseRay, out dist);\n                return mouseRay.GetPoint(dist);\n            }\n            else\n            {\n                success = true;\n                return s_CurrentMousePosition;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/SliderScale.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEditor.Snap;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    internal class SliderScale\n    {\n        private static float s_StartScale, s_ScaleDrawLength = 1.0f;\n        private static Vector2 s_StartMousePosition, s_CurrentMousePosition;\n        private static Vector3 s_Direction;\n\n        public static float DoAxis(int id, float scale, Vector3 position, Vector3 direction, Quaternion rotation, float size, float snap)\n        {\n            return DoAxis(id, scale, position, direction, rotation, size, snap, 0, 1);\n        }\n\n        internal static Vector3 DoAxis(int id, Vector3 scale, int scaleItemIndex, Vector3 position, Vector3 direction, Quaternion rotation, float size, float snap, float handleOffset, float lineScale, Vector3 initialScale, bool constrainProportionsScaling)\n        {\n            // If constrainProportionsScaling enabled, transforms behave the same way as Cube Handle does\n            if (constrainProportionsScaling)\n            {\n                var value = DoAxis(id, scale.x, position, direction, rotation, size, EditorSnapSettings.scale, handleOffset, lineScale);\n                return initialScale * DoCenter(id, value, position, rotation, size, Handles.CubeHandleCap, snap);\n            }\n            else\n            {\n                scale[scaleItemIndex] = DoAxis(id, scale[scaleItemIndex], position, direction, rotation, size, snap, handleOffset, lineScale);\n            }\n\n            return scale;\n        }\n\n        internal static float DoAxis(int id, float scale, Vector3 position, Vector3 direction, Quaternion rotation, float size, float snap, float handleOffset, float lineScale)\n        {\n            if (GUIUtility.hotControl == id)\n                Handles.handleLength = size * scale / s_StartScale;\n            var positionOffset = direction * size * handleOffset;\n            var s = GUIUtility.hotControl == id || Handles.proportionalScale\n                ? Handles.handleLength\n                : size;\n            var startPosition = position + positionOffset;\n            var cubePosition = position + direction * (s * s_ScaleDrawLength * lineScale) + positionOffset;\n\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseMove:\n                case EventType.Layout:\n                    HandleUtility.AddControl(id, HandleUtility.DistanceToLine(startPosition, cubePosition));\n                    HandleUtility.AddControl(id, HandleUtility.DistanceToCube(cubePosition, rotation, size * .1f));\n                    break;\n\n                case EventType.MouseDown:\n                    // am I closest to the thingy?\n                    if (HandleUtility.nearestControl == id && evt.button == 0 && !evt.alt)\n                    {\n                        GUIUtility.hotControl = id;    // Grab mouse focus\n                        s_CurrentMousePosition = s_StartMousePosition = evt.mousePosition;\n                        s_StartScale = scale;\n                        evt.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(1);\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        s_CurrentMousePosition += evt.delta;\n                        var dist = 1 + HandleUtility.CalcLineTranslation(s_StartMousePosition, s_CurrentMousePosition, position, direction) / size;\n                        dist = Handles.SnapValue(dist, snap);\n                        scale = s_StartScale * dist;\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(0);\n                    }\n                    break;\n\n                case EventType.Repaint:\n                    Handles.SetupHandleColor(id, evt, out var prevColor, out var thickness);\n                    float capSize = size * .1f;\n                    if (Handles.IsHovering(id, evt))\n                        capSize *= Handles.s_HoverExtraScale;\n\n                    var camera = Camera.current;\n                    var viewDir = camera != null ? camera.transform.forward : -direction;\n                    var facingAway = Vector3.Dot(viewDir, direction) < 0.0f;\n                    // draw line vs cube in the appropriate order based on viewing\n                    // direction, for correct transparency sorting\n                    var lineEndPos = position + direction * (s * s_ScaleDrawLength * lineScale - capSize * 0.5f) + positionOffset;\n                    if (facingAway)\n                    {\n                        Handles.DrawLine(startPosition, lineEndPos, thickness);\n                        Handles.CubeHandleCap(id, cubePosition, rotation, capSize, EventType.Repaint);\n                    }\n                    else\n                    {\n                        Handles.CubeHandleCap(id, cubePosition, rotation, capSize, EventType.Repaint);\n                        Handles.DrawLine(startPosition, lineEndPos, thickness);\n                    }\n                    Handles.color = prevColor;\n                    break;\n            }\n\n            return scale;\n        }\n\n        public static float DoCenter(int id, float value, Vector3 position, Quaternion rotation, float size, Handles.CapFunction capFunction, float snap)\n        {\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseMove:\n                case EventType.Layout:\n                    capFunction(id, position, rotation, size * .15f, EventType.Layout);\n                    break;\n\n                case EventType.MouseDown:\n                    // am I closest to the thingy?\n                    if (HandleUtility.nearestControl == id && evt.button == 0 && !evt.alt)\n                    {\n                        GUIUtility.hotControl = id;     // Grab mouse focus\n                        Tools.LockHandlePosition();\n                        s_StartScale = value;\n                        s_CurrentMousePosition = s_StartMousePosition = evt.mousePosition;\n\n                        var camera = SceneView.lastActiveSceneView.camera;\n                        s_Direction = camera == null? Vector3.one : (camera.transform.right + camera.transform.up).normalized;\n                        evt.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(1);\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        s_CurrentMousePosition += evt.delta;\n                        var dist = HandleUtility.CalcLineTranslation(s_StartMousePosition, s_CurrentMousePosition, position, s_Direction) / size;\n                        value = (Handles.SnapValue(dist, snap) + 1.0f) * s_StartScale;\n                        s_ScaleDrawLength = value;\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.KeyDown:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        // Cancel dragging on ESC\n                        if (evt.keyCode == KeyCode.Escape)\n                        {\n                            Tools.UnlockHandlePosition();\n                            s_ScaleDrawLength = 1.0f;\n                        }\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == id)\n                    {\n                        GUIUtility.hotControl = 0;\n                        Tools.UnlockHandlePosition();\n                        s_ScaleDrawLength = 1.0f;\n                        evt.Use();\n                        EditorGUIUtility.SetWantsMouseJumping(0);\n                    }\n                    break;\n\n                case EventType.Repaint:\n                    Handles.SetupHandleColor(id, evt, out var prevColor, out var thickness);\n                    float capSize = size * .15f;\n                    if (Handles.IsHovering(id, evt))\n                        capSize *= Handles.s_HoverExtraScale;\n                    capFunction(id, position, rotation, capSize, EventType.Repaint);\n                    Handles.color = prevColor;\n                    break;\n            }\n\n            return value;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/TransformHandle.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class Handles\n    {\n        internal struct TransformHandleIds\n        {\n            static readonly int s_TransformTranslationXHash = \"TransformTranslationXHash\".GetHashCode();\n            static readonly int s_TransformTranslationYHash = \"TransformTranslationYHash\".GetHashCode();\n            static readonly int s_TransformTranslationZHash = \"TransformTranslationZHash\".GetHashCode();\n            static readonly int s_TransformTranslationXYHash = \"TransformTranslationXYHash\".GetHashCode();\n            static readonly int s_TransformTranslationXZHash = \"TransformTranslationXZHash\".GetHashCode();\n            static readonly int s_TransformTranslationYZHash = \"TransformTranslationYZHash\".GetHashCode();\n            static readonly int s_TransformTranslationXYZHash = \"TransformTranslationXYZHash\".GetHashCode();\n            static readonly int s_TransformRotationXHash = \"TransformRotationXHash\".GetHashCode();\n            static readonly int s_TransformRotationYHash = \"TransformRotationYHash\".GetHashCode();\n            static readonly int s_TransformRotationZHash = \"TransformRotationZHash\".GetHashCode();\n            static readonly int s_TransformRotationCameraAxisHash = \"TransformRotationCameraAxisHash\".GetHashCode();\n            static readonly int s_TransformRotationXYZHash = \"TransformRotationXYZHash\".GetHashCode();\n            static readonly int s_TransformScaleXHash = \"TransformScaleXHash\".GetHashCode();\n            static readonly int s_TransformScaleYHash = \"TransformScaleYHash\".GetHashCode();\n            static readonly int s_TransformScaleZHash = \"TransformScaleZHash\".GetHashCode();\n            static readonly int s_TransformScaleXYZHash = \"TransformScaleXYZHash\".GetHashCode();\n\n            public static TransformHandleIds Default\n            {\n                get\n                {\n                    return new TransformHandleIds(\n                        new PositionHandleIds(\n                            GUIUtility.GetControlID(s_TransformTranslationXHash, FocusType.Passive),\n                            GUIUtility.GetControlID(s_TransformTranslationYHash, FocusType.Passive),\n                            GUIUtility.GetControlID(s_TransformTranslationZHash, FocusType.Passive),\n                            GUIUtility.GetControlID(s_TransformTranslationXYHash, FocusType.Passive),\n                            GUIUtility.GetControlID(s_TransformTranslationXZHash, FocusType.Passive),\n                            GUIUtility.GetControlID(s_TransformTranslationYZHash, FocusType.Passive),\n                            GUIUtility.GetControlID(s_TransformTranslationXYZHash, FocusType.Passive)\n                        ),\n                        new RotationHandleIds(\n                            GUIUtility.GetControlID(s_TransformRotationXHash, FocusType.Passive),\n                            GUIUtility.GetControlID(s_TransformRotationYHash, FocusType.Passive),\n                            GUIUtility.GetControlID(s_TransformRotationZHash, FocusType.Passive),\n                            GUIUtility.GetControlID(s_TransformRotationCameraAxisHash, FocusType.Passive),\n                            GUIUtility.GetControlID(s_TransformRotationXYZHash, FocusType.Passive)\n                        ),\n                        new ScaleHandleIds(\n                            GUIUtility.GetControlID(s_TransformScaleXHash, FocusType.Passive),\n                            GUIUtility.GetControlID(s_TransformScaleYHash, FocusType.Passive),\n                            GUIUtility.GetControlID(s_TransformScaleZHash, FocusType.Passive),\n                            GUIUtility.GetControlID(s_TransformScaleXYZHash, FocusType.Passive)\n                        )\n                    );\n                }\n            }\n\n            public readonly PositionHandleIds position;\n            public readonly RotationHandleIds rotation;\n            public readonly ScaleHandleIds scale;\n\n            public bool Has(int id)\n            {\n                return position.Has(id)\n                    || rotation.Has(id)\n                    || scale.Has(id);\n            }\n\n            public TransformHandleIds(PositionHandleIds position, RotationHandleIds rotation, ScaleHandleIds scale)\n            {\n                this.position = position;\n                this.rotation = rotation;\n                this.scale = scale;\n            }\n        }\n\n        internal struct TransformHandleParam\n        {\n            static TransformHandleParam s_Default = new TransformHandleParam(\n                // Global\n                new PositionHandleParam(\n                    PositionHandleParam.Handle.X | PositionHandleParam.Handle.Y | PositionHandleParam.Handle.Z\n                    | PositionHandleParam.Handle.XY | PositionHandleParam.Handle.XZ | PositionHandleParam.Handle.YZ,\n                    Vector3.one * 0.15f,\n                    Vector3.one,\n                    Vector3.zero,\n                    Vector3.one * 0.375f,\n                    PositionHandleParam.Orientation.Signed,\n                    PositionHandleParam.Orientation.Camera\n                ),\n                new RotationHandleParam(\n                    RotationHandleParam.Handle.X | RotationHandleParam.Handle.Y | RotationHandleParam.Handle.Z\n                    | RotationHandleParam.Handle.CameraAxis | RotationHandleParam.Handle.XYZ,\n                    Vector3.one * 1.4f,\n                    1.4f,\n                    1.5f,\n                    false,\n                    true\n                ),\n                new ScaleHandleParam(\n                    ScaleHandleParam.Handle.XYZ,\n                    Vector3.zero,\n                    Vector3.one,\n                    Vector3.one,\n                    1,\n                    ScaleHandleParam.Orientation.Signed\n                ),\n\n                // Camera aligned\n                new PositionHandleParam(\n                    PositionHandleParam.Handle.X | PositionHandleParam.Handle.Y | PositionHandleParam.Handle.XY,\n                    Vector3.one * 0.15f,\n                    Vector3.one,\n                    Vector3.zero,\n                    Vector3.one * 0.375f,\n                    PositionHandleParam.Orientation.Signed,\n                    PositionHandleParam.Orientation.Signed\n                ),\n                new RotationHandleParam(\n                    RotationHandleParam.Handle.Z | RotationHandleParam.Handle.XYZ,\n                    Vector3.one * 1.4f,\n                    1.4f,\n                    1.5f,\n                    false,\n                    false\n                ),\n                new ScaleHandleParam(\n                    ScaleHandleParam.Handle.XYZ,\n                    Vector3.zero,\n                    Vector3.one,\n                    Vector3.one,\n                    1,\n                    ScaleHandleParam.Orientation.Signed\n                ),\n\n                // Local\n                new PositionHandleParam(\n                    PositionHandleParam.Handle.X | PositionHandleParam.Handle.Y | PositionHandleParam.Handle.Z\n                    | PositionHandleParam.Handle.XY | PositionHandleParam.Handle.XZ | PositionHandleParam.Handle.YZ,\n                    Vector3.one * 0.15f,\n                    Vector3.one,\n                    Vector3.zero,\n                    Vector3.one * 0.375f,\n                    PositionHandleParam.Orientation.Signed,\n                    PositionHandleParam.Orientation.Camera\n                ),\n                new RotationHandleParam(\n                    RotationHandleParam.Handle.X | RotationHandleParam.Handle.Y | RotationHandleParam.Handle.Z\n                    | RotationHandleParam.Handle.CameraAxis | RotationHandleParam.Handle.XYZ,\n                    Vector3.one * 1.4f,\n                    1.4f,\n                    1.5f,\n                    false,\n                    true\n                ),\n                new ScaleHandleParam(\n                    ScaleHandleParam.Handle.XYZ | ScaleHandleParam.Handle.X | ScaleHandleParam.Handle.Y | ScaleHandleParam.Handle.Z,\n                    Vector3.one * 1.5f,\n                    Vector3.one,\n                    Vector3.one * 0.25f,\n                    1,\n                    ScaleHandleParam.Orientation.Signed\n                )\n                ,\n\n                // Vertex Snapping\n                new PositionHandleParam(\n                    PositionHandleParam.Handle.X | PositionHandleParam.Handle.Y | PositionHandleParam.Handle.Z\n                    | PositionHandleParam.Handle.XYZ,\n                    Vector3.one * 0.15f,\n                    Vector3.one,\n                    Vector3.zero,\n                    Vector3.one * 0.375f,\n                    PositionHandleParam.Orientation.Signed,\n                    PositionHandleParam.Orientation.Signed\n                ),\n                new RotationHandleParam(\n                    0,\n                    Vector3.one * 1.4f,\n                    1.4f,\n                    1.5f,\n                    false,\n                    true\n                ),\n                new ScaleHandleParam(\n                    0,\n                    Vector3.one * 1.5f,\n                    Vector3.one,\n                    Vector3.one * 0.25f,\n                    1,\n                    ScaleHandleParam.Orientation.Signed\n                )\n            );\n            public static TransformHandleParam Default { get { return s_Default; } set { s_Default = value; } }\n\n            public readonly PositionHandleParam position;\n            public readonly RotationHandleParam rotation;\n            public readonly ScaleHandleParam scale;\n            public readonly PositionHandleParam cameraAlignedPosition;\n            public readonly RotationHandleParam cameraAlignedRotation;\n            public readonly ScaleHandleParam cameraAlignedScale;\n            public readonly PositionHandleParam localPosition;\n            public readonly RotationHandleParam localRotation;\n            public readonly ScaleHandleParam localScale;\n            public readonly PositionHandleParam vertexSnappingPosition;\n            public readonly RotationHandleParam vertexSnappingRotation;\n            public readonly ScaleHandleParam vertexSnappingScale;\n\n            public TransformHandleParam(\n                PositionHandleParam position,\n                RotationHandleParam rotation,\n                ScaleHandleParam scale,\n                PositionHandleParam cameraAlignedPosition,\n                RotationHandleParam cameraAlignedRotation,\n                ScaleHandleParam cameraAlignedScale,\n                PositionHandleParam localPosition,\n                RotationHandleParam localRotation,\n                ScaleHandleParam localScale,\n                PositionHandleParam vertexSnappingPosition,\n                RotationHandleParam vertexSnappingRotation,\n                ScaleHandleParam vertexSnappingScale)\n            {\n                this.position = position;\n                this.rotation = rotation;\n                this.scale = scale;\n                this.cameraAlignedPosition = cameraAlignedPosition;\n                this.cameraAlignedRotation = cameraAlignedRotation;\n                this.cameraAlignedScale = cameraAlignedScale;\n                this.localPosition = localPosition;\n                this.localRotation = localRotation;\n                this.localScale = localScale;\n                this.vertexSnappingPosition = vertexSnappingPosition;\n                this.vertexSnappingRotation = vertexSnappingRotation;\n                this.vertexSnappingScale = vertexSnappingScale;\n            }\n\n            public TransformHandleParam Without(PositionHandleParam.Handle handles)\n            {\n                return new TransformHandleParam(\n                    RemoveHandles(position, handles),\n                    rotation,\n                    scale,\n                    RemoveHandles(cameraAlignedPosition, handles),\n                    cameraAlignedRotation,\n                    cameraAlignedScale,\n                    RemoveHandles(localPosition, handles),\n                    localRotation,\n                    localScale,\n                    RemoveHandles(vertexSnappingPosition, handles),\n                    vertexSnappingRotation,\n                    vertexSnappingScale\n                );\n            }\n\n            static PositionHandleParam RemoveHandles(PositionHandleParam p, PositionHandleParam.Handle handles)\n            {\n                return new PositionHandleParam(p.handles & ~handles, p.axisOffset, p.axisSize, p.planeOffset, p.planeSize, p.axesOrientation, p.planeOrientation);\n            }\n\n            public TransformHandleParam Without(RotationHandleParam.Handle handles)\n            {\n                return new TransformHandleParam(\n                    position,\n                    RemoveHandles(rotation, handles),\n                    scale,\n                    cameraAlignedPosition,\n                    RemoveHandles(cameraAlignedRotation, handles),\n                    cameraAlignedScale,\n                    localPosition,\n                    RemoveHandles(localRotation, handles),\n                    localScale,\n                    vertexSnappingPosition,\n                    RemoveHandles(vertexSnappingRotation, handles),\n                    vertexSnappingScale\n                );\n            }\n\n            static RotationHandleParam RemoveHandles(RotationHandleParam r, RotationHandleParam.Handle handles)\n            {\n                return new RotationHandleParam(r.handles & ~handles, r.axisSize, r.xyzSize, r.cameraAxisSize, r.enableRayDrag, r.displayXYZCircle);\n            }\n\n            public TransformHandleParam Without(ScaleHandleParam.Handle handles)\n            {\n                return new TransformHandleParam(\n                    position,\n                    rotation,\n                    RemoveHandles(scale, handles),\n                    cameraAlignedPosition,\n                    cameraAlignedRotation,\n                    RemoveHandles(cameraAlignedScale, handles),\n                    localPosition,\n                    localRotation,\n                    RemoveHandles(localScale, handles),\n                    vertexSnappingPosition,\n                    vertexSnappingRotation,\n                    RemoveHandles(vertexSnappingScale, handles)\n                );\n            }\n\n            static ScaleHandleParam RemoveHandles(ScaleHandleParam s, ScaleHandleParam.Handle handles)\n            {\n                return new ScaleHandleParam(s.handles & ~handles, s.axisOffset, s.axisSize, s.axisLineScale, s.xyzSize, s.orientation);\n            }\n\n            public TransformHandleParam WithSoloPositionManipulatorSize()\n            {\n                return new TransformHandleParam(\n                    CopyDefaultSize(position),\n                    rotation,\n                    scale,\n                    CopyDefaultSize(cameraAlignedPosition),\n                    cameraAlignedRotation,\n                    cameraAlignedScale,\n                    CopyDefaultSize(localPosition),\n                    localRotation,\n                    localScale,\n                    CopyDefaultSize(vertexSnappingPosition),\n                    vertexSnappingRotation,\n                    vertexSnappingScale\n                );\n            }\n\n            static PositionHandleParam CopyDefaultSize(PositionHandleParam p)\n            {\n                var d = PositionHandleParam.DefaultHandle;\n                return new PositionHandleParam(p.handles, d.axisOffset, d.axisSize, d.planeOffset, d.planeSize, p.axesOrientation, p.planeOrientation);\n            }\n\n            public TransformHandleParam WithSoloRotationManipulatorSize()\n            {\n                return new TransformHandleParam(\n                    position,\n                    CopyDefaultSize(rotation),\n                    scale,\n                    cameraAlignedPosition,\n                    CopyDefaultSize(cameraAlignedRotation),\n                    cameraAlignedScale,\n                    localPosition,\n                    CopyDefaultSize(localRotation),\n                    localScale,\n                    vertexSnappingPosition,\n                    CopyDefaultSize(vertexSnappingRotation),\n                    vertexSnappingScale\n                );\n            }\n\n            static RotationHandleParam CopyDefaultSize(RotationHandleParam r)\n            {\n                var d = RotationHandleParam.Default;\n                return new RotationHandleParam(r.handles, d.axisSize, d.xyzSize, d.cameraAxisSize, r.enableRayDrag, r.displayXYZCircle);\n            }\n\n            public TransformHandleParam WithSoloScaleManipulatorSize()\n            {\n                return new TransformHandleParam(\n                    position,\n                    rotation,\n                    CopyDefaultSize(scale),\n                    cameraAlignedPosition,\n                    cameraAlignedRotation,\n                    CopyDefaultSize(cameraAlignedScale),\n                    localPosition,\n                    localRotation,\n                    CopyDefaultSize(localScale),\n                    vertexSnappingPosition,\n                    vertexSnappingRotation,\n                    CopyDefaultSize(vertexSnappingScale)\n                );\n            }\n\n            static ScaleHandleParam CopyDefaultSize(ScaleHandleParam s)\n            {\n                var d = ScaleHandleParam.Default;\n                return new ScaleHandleParam(s.handles, d.axisOffset, d.axisSize, d.axisLineScale, s.xyzSize, s.orientation);\n            }\n        }\n\n        struct RotationHandleData\n        {\n            public bool rotationStarted;\n            public Quaternion initialRotation;\n        }\n\n        // non-uniform scale\n        public static void TransformHandle(ref Vector3 position, ref Quaternion rotation, ref Vector3 scale)\n        {\n            TransformHandle(\n                TransformHandleIds.Default, ref position, ref rotation, ref scale, TransformHandleParam.Default\n            );\n        }\n\n        public static void TransformHandle(ref Vector3 position, Quaternion rotation, ref Vector3 scale)\n        {\n            TransformHandle(\n                TransformHandleIds.Default, ref position, ref rotation, ref scale,\n                TransformHandleParam.Default.Without(RotationHandleParam.Handle.All)\n            );\n        }\n\n        public static void TransformHandle(Vector3 position, ref Quaternion rotation, ref Vector3 scale)\n        {\n            TransformHandle(\n                TransformHandleIds.Default, ref position, ref rotation, ref scale,\n                TransformHandleParam.Default.Without(PositionHandleParam.Handle.All)\n            );\n        }\n\n        // uniform scale\n        public static void TransformHandle(ref Vector3 position, ref Quaternion rotation, ref float uniformScale)\n        {\n            var s = Vector3.one * uniformScale;\n            TransformHandle(\n                TransformHandleIds.Default, ref position, ref rotation, ref s,\n                TransformHandleParam.Default\n                    .Without(ScaleHandleParam.Handle.X | ScaleHandleParam.Handle.Y | ScaleHandleParam.Handle.Z)\n            );\n            uniformScale = s.x;\n        }\n\n        public static void TransformHandle(ref Vector3 position, Quaternion rotation, ref float uniformScale)\n        {\n            var s = Vector3.one * uniformScale;\n            TransformHandle(\n                TransformHandleIds.Default, ref position, ref rotation, ref s,\n                TransformHandleParam.Default\n                    .Without(RotationHandleParam.Handle.All)\n                    .Without(ScaleHandleParam.Handle.X | ScaleHandleParam.Handle.Y | ScaleHandleParam.Handle.Z)\n            );\n            uniformScale = s.x;\n        }\n\n        public static void TransformHandle(Vector3 position, ref Quaternion rotation, ref float uniformScale)\n        {\n            var s = Vector3.one * uniformScale;\n            TransformHandle(\n                TransformHandleIds.Default, ref position, ref rotation, ref s,\n                TransformHandleParam.Default\n                    .Without(PositionHandleParam.Handle.All)\n                    .Without(ScaleHandleParam.Handle.X | ScaleHandleParam.Handle.Y | ScaleHandleParam.Handle.Z)\n            );\n            uniformScale = s.x;\n        }\n\n        // only position and rotation\n        public static void TransformHandle(ref Vector3 position, ref Quaternion rotation)\n        {\n            var s = Vector3.one;\n            TransformHandle(\n                TransformHandleIds.Default, ref position, ref rotation, ref s,\n                TransformHandleParam.Default.Without(ScaleHandleParam.Handle.All)\n            );\n        }\n\n        // only position\n        static void TransformHandle(ref Vector3 position, Quaternion rotation)\n        {\n            var s = Vector3.one;\n            TransformHandle(\n                TransformHandleIds.Default, ref position, ref rotation, ref s,\n                TransformHandleParam.Default.Without(ScaleHandleParam.Handle.All).WithSoloPositionManipulatorSize()\n            );\n        }\n\n        // only rotation\n        static void TransformHandle(Vector3 position, ref Quaternion rotation)\n        {\n            var s = Vector3.one;\n            TransformHandle(\n                TransformHandleIds.Default, ref position, ref rotation, ref s,\n                TransformHandleParam.Default.Without(ScaleHandleParam.Handle.All).WithSoloRotationManipulatorSize()\n            );\n        }\n\n        // only scale\n        static void TransformHandle(Vector3 position, Quaternion rotation, ref Vector3 scale)\n        {\n            TransformHandle(\n                TransformHandleIds.Default, ref position, ref rotation, ref scale,\n                TransformHandleParam.Default\n                    .Without(PositionHandleParam.Handle.All)\n                    .Without(RotationHandleParam.Handle.All)\n                    .WithSoloScaleManipulatorSize()\n            );\n        }\n\n        static void TransformHandle(Vector3 position, Quaternion rotation, ref float uniformScale)\n        {\n            var s = Vector3.one * uniformScale;\n            TransformHandle(\n                TransformHandleIds.Default, ref position, ref rotation, ref s,\n                TransformHandleParam.Default\n                    .Without(PositionHandleParam.Handle.All)\n                    .Without(RotationHandleParam.Handle.All)\n                    .Without(ScaleHandleParam.Handle.X | ScaleHandleParam.Handle.Y | ScaleHandleParam.Handle.Z)\n                    .WithSoloScaleManipulatorSize()\n            );\n            uniformScale = s.x;\n        }\n\n        static bool s_IsHotInCameraAlignedMode = false;\n        static Dictionary<RotationHandleIds, RotationHandleData> s_TransformHandle_RotationData = new Dictionary<RotationHandleIds, RotationHandleData>();\n        internal static void TransformHandle(TransformHandleIds ids, ref Vector3 position, ref Quaternion rotation, ref Vector3 scale, TransformHandleParam param)\n        {\n            var workingRotation = rotation;\n            var pParam = param.position;\n            var rParam = param.rotation;\n            var sParam = param.scale;\n\n            var isHot = ids.Has(GUIUtility.hotControl);\n            var cameraAligned = (isHot && s_IsHotInCameraAlignedMode || !isHot && Event.current.shift);\n            if (Tools.vertexDragging)\n            {\n                pParam = param.vertexSnappingPosition;\n                rParam = param.vertexSnappingRotation;\n                sParam = param.vertexSnappingScale;\n            }\n            else if (cameraAligned)\n            {\n                workingRotation = Camera.current.transform.rotation;\n\n                pParam = param.cameraAlignedPosition;\n                rParam = param.cameraAlignedRotation;\n                sParam = param.cameraAlignedScale;\n            }\n            else if (Tools.pivotRotation == PivotRotation.Local)\n            {\n                pParam = param.localPosition;\n                rParam = param.localRotation;\n                sParam = param.localScale;\n            }\n\n            // Draw only the hot control\n            if (ids.Has(GUIUtility.hotControl))\n            {\n                if (ids.position.Has(GUIUtility.hotControl))\n                {\n                    position = DoPositionHandle_Internal(ids.position, position, workingRotation, pParam);\n                }\n                else if (ids.rotation.Has(GUIUtility.hotControl))\n                {\n                    var endRotation = DoRotationHandle(ids.rotation, workingRotation, position, rParam);\n\n                    if (cameraAligned)\n                    {\n                        // For camera aligned axis rotation, we need to store the initial rotation to rotate only the delta\n                        if (!s_TransformHandle_RotationData.ContainsKey(ids.rotation))\n                        {\n                            s_TransformHandle_RotationData[ids.rotation] = new RotationHandleData\n                            {\n                                rotationStarted = true,\n                                initialRotation = rotation\n                            };\n                        }\n\n                        // For freemove rotation, we already have the delta rotation properly\n                        var initialRotation = ids.rotation.xyz != GUIUtility.hotControl\n                            ? s_TransformHandle_RotationData[ids.rotation].initialRotation\n                            : rotation;\n                        var d = endRotation * Quaternion.Inverse(workingRotation);\n                        float angle;\n                        Vector3 axis;\n                        d.ToAngleAxis(out angle, out axis);\n                        rotation = Quaternion.AngleAxis(angle, axis) * initialRotation;\n                    }\n                    else\n                        rotation = endRotation;\n                }\n                else if (ids.scale.Has(GUIUtility.hotControl))\n                    scale = DoScaleHandle(ids.scale, scale, position, workingRotation, HandleUtility.GetHandleSize(position), sParam);\n            }\n            else\n            {\n                s_TransformHandle_RotationData.Remove(ids.rotation);\n\n                // Drawing only\n                DoRotationHandle(ids.rotation, workingRotation, position, rParam);\n                // Draw scale position last so axes have priority\n                DoPositionHandle_Internal(ids.position, position, workingRotation, pParam);\n                DoScaleHandle(ids.scale, scale, position, workingRotation, HandleUtility.GetHandleSize(position), sParam);\n            }\n\n            var nowIsHot = ids.Has(GUIUtility.hotControl);\n            if (nowIsHot && !isHot && cameraAligned)\n                s_IsHotInCameraAlignedMode = true;\n            else if (s_IsHotInCameraAlignedMode && (!isHot || !nowIsHot))\n                s_IsHotInCameraAlignedMode = false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Handles/VertexSnapping.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.ShortcutManagement;\n\nnamespace UnityEditor\n{\n    internal class VertexSnapping\n    {\n        internal const string k_VertexSnappingShortcut = \"Scene View/Vertex Snapping\";\n        internal const string k_VertexSnappingToggleShortcut = \"Scene View/Toggle Vertex Snapping\";\n        private static Vector3 s_VertexSnappingOffset = Vector3.zero;\n\n        [Shortcut(k_VertexSnappingToggleShortcut, typeof(SceneView), KeyCode.V, ShortcutModifiers.Shift)]\n        private static void ToggleVertexSnappingViaShortcut()\n        {\n            int id = GUIUtility.hotControl;\n            if (Tools.vertexDragging)\n                DisableVertexSnapping(id);\n            else\n                EnableVertexSnapping(id);\n        }\n\n        [ClutchShortcut(k_VertexSnappingShortcut, typeof(SceneView), KeyCode.V)]\n        private static void ToggleVertexSnappingViaClutchShortcut(ShortcutArguments arguments)\n        {\n            int id = GUIUtility.hotControl;\n            if (arguments.stage == ShortcutStage.Begin)\n                EnableVertexSnapping(id);\n            else\n                DisableVertexSnapping(id);\n        }\n\n        // This method handles MouseMove for doing vertex snapping.\n        // To ensure correct behaviour the caller must do on it's own:\n        // - On MouseDown and MouseUp (if event is ours to use):\n        //      HandleUtility.ignoreRaySnapObjects = null;\n        // - On MouseDrag (if event is ours to use):\n        //      if (Tools.vertexDragging)\n        //      {\n        //          if (HandleUtility.ignoreRaySnapObjects == null)\n        //              Handles.SetupIgnoreRaySnapObjects ();\n        //          Vector3 near;\n        //          if (HandleUtility.FindNearestVertex (evt.mousePosition, null, out near))\n        //          {\n        //              // Snap position based on found near vertex\n        //          }\n        //      }\n        //\n        // This is not the most elegant code-reuse solution,\n        // but still a step up from the copy-pasted code that was used before.\n        public static void HandleMouseMove(int id)\n        {\n            var evt = Event.current;\n            if (evt.GetTypeForControl(id) == EventType.MouseMove && Tools.vertexDragging)\n            {\n                EnableVertexSnapping(id);\n                evt.Use();\n            }\n        }\n\n        private static void EnableVertexSnapping(int id)\n        {\n            Tools.vertexDragging = true;\n            if (GUIUtility.hotControl != 0 && GUIUtility.hotControl == id)\n            {\n                Tools.handleOffset = s_VertexSnappingOffset;\n            }\n            else\n            {\n                UpdateVertexSnappingOffset();\n                s_VertexSnappingOffset = Tools.handleOffset;\n            }\n        }\n\n        //Used in tests\n        internal static void DisableVertexSnapping_Internal()\n        {\n            Tools.vertexDragging = false;\n            Tools.handleOffset = Vector3.zero;\n            s_VertexSnappingOffset = Vector3.zero;\n        }\n\n        private static void DisableVertexSnapping(int id)\n        {\n            Tools.vertexDragging = false;\n            Tools.handleOffset = Vector3.zero;\n            if (GUIUtility.hotControl != id)\n                s_VertexSnappingOffset = Vector3.zero;\n        }\n\n        // Iterates over selected objects, finds nearest vertex or pivot and sets Tools.handleOffset accordingly\n        private static void UpdateVertexSnappingOffset()\n        {\n            Event evt = Event.current;\n\n            // If pressing ctrl/cmd key while using vertex snapping,\n            // then the pivot should be used to snap on vertices\n            if(EditorGUI.actionKey &&! evt.shift)\n            {\n                Tools.InvalidateHandlePosition();\n                Tools.handleOffset = Vector3.zero;\n                return;\n            }\n\n            Tools.vertexDragging = true;\n            Vector3 nearestVertex;\n            Transform[] selection = Selection.GetTransforms(SelectionMode.Deep | SelectionMode.ExcludePrefab | SelectionMode.Editable);\n\n            // Make sure we're not ignoring any objects, that other handles may have set to ignore and forgot to reset.\n            HandleUtility.ignoreRaySnapObjects = null;\n\n            Vector3 nearestPivot = FindNearestPivot(selection, evt.mousePosition);\n            bool foundVertex = HandleUtility.FindNearestVertex(evt.mousePosition, selection, out nearestVertex);\n\n            Vector3 near;\n\n            // Is nearest vertex closer than nearest pivot?\n            float distanceToNearestVertex = (HandleUtility.WorldToGUIPoint(nearestVertex) - evt.mousePosition).magnitude;\n            float distanceToNearestPivot = (HandleUtility.WorldToGUIPoint(nearestPivot) - evt.mousePosition).magnitude;\n\n            if (foundVertex && (distanceToNearestVertex < distanceToNearestPivot))\n                near = nearestVertex;\n            else\n                near = nearestPivot;\n\n            // Important to reset handleOffset before querying handlePosition,\n            // since handlePosition depends on handleOffset.\n            Tools.InvalidateHandlePosition();\n            Tools.handleOffset = Vector3.zero;\n            Tools.handleOffset = near - Tools.handlePosition;\n        }\n\n        private static Vector3 FindNearestPivot(Transform[] transforms, Vector2 screenPosition)\n        {\n            bool foundPivot = false;\n            Vector3 pivot = Vector3.zero;\n\n            foreach (Transform transform in transforms)\n            {\n                Vector3 worldPosition = ScreenToWorld(screenPosition, transform);\n                if (!foundPivot || (pivot - worldPosition).magnitude > (transform.position - worldPosition).magnitude)\n                {\n                    pivot = transform.position;\n                    foundPivot = true;\n                }\n            }\n            return pivot;\n        }\n\n        private static Vector3 ScreenToWorld(Vector2 screen, Transform target)\n        {\n            Ray mouseRay = HandleUtility.GUIPointToWorldRay(screen);\n            float dist = 0.0f;\n            new Plane(target.forward, target.position).Raycast(mouseRay, out dist);\n            return mouseRay.GetPoint(dist);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Hardware.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Hardware\n{\n    [RequiredByNativeCode(GenerateProxy = true)]\n    [StructLayout(LayoutKind.Sequential)]\n    public struct UsbDevice\n    {\n        readonly public int vendorId;\n        readonly public int productId;\n        readonly public int revision;\n        readonly public string udid;\n        readonly public string name;\n\n        public override string ToString()\n        {\n            return name + \" (udid:\" + udid + \", vid: \" + vendorId.ToString(\"X4\") + \", pid: \" + productId.ToString(\"X4\") + \", rev: \" + revision.ToString(\"X4\") + \")\";\n        }\n    }\n\n    public sealed class Usb\n    {\n        public delegate void OnDevicesChangedHandler(UsbDevice[] devices);\n\n        public static event OnDevicesChangedHandler DevicesChanged;\n\n        [RequiredByNativeCode]\n        public static void OnDevicesChanged(UsbDevice[] devices)\n        {\n            if ((DevicesChanged != null) && (devices != null))\n                DevicesChanged(devices);\n        }\n    }\n\n    // Keep in sync with DevDeviceState enum in DevDevice.h\n    public enum DevDeviceState\n    {\n        Disconnected = 0,\n        Connected = 1,\n    }\n\n    // Keep in sync with DevDeviceFeatures enum in DevDevice.h\n    [Flags]\n    public enum DevDeviceFeatures\n    {\n        None = 0,\n        PlayerConnection = 1 << 0,\n        RemoteConnection = 1 << 1,\n    }\n\n    [RequiredByNativeCode]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct DevDevice\n    {\n        readonly public string id;\n        readonly public string name;\n        readonly public string type;\n        readonly public string module;\n        readonly public DevDeviceState state;\n        readonly public DevDeviceFeatures features;\n\n        public bool isConnected { get { return state == DevDeviceState.Connected; } }\n\n        public static DevDevice none { get { return new DevDevice(\"None\", \"None\", \"none\", \"internal\", DevDeviceState.Disconnected, DevDeviceFeatures.None); } }\n\n        public override string ToString()\n        {\n            return name + \" (id:\" + id + \", type: \" + type + \", module: \" + module + \", state: \" + state + \", features: \" + features + \")\";\n        }\n\n        public DevDevice(string id, string name, string type, string module, DevDeviceState state, DevDeviceFeatures features)\n        {\n            this.id = id;\n            this.name = name;\n            this.type = type;\n            this.module = module;\n            this.state = state;\n            this.features = features;\n        }\n    }\n\n    [NativeHeader(\"Editor/Src/Devices/DevDevice.h\")]\n    public sealed class DevDeviceList\n    {\n        public delegate void OnChangedHandler();\n        public static event OnChangedHandler Changed;\n\n        public static void OnChanged()\n        {\n            if (Changed != null)\n                Changed();\n        }\n\n        public static bool FindDevice(string deviceId, out DevDevice device)\n        {\n            foreach (var d in GetDevices())\n            {\n                if (d.id == deviceId)\n                {\n                    device = d;\n                    return true;\n                }\n            }\n\n            device = new DevDevice();\n            return false;\n        }\n\n        internal static void Update(string target, DevDevice[] devices)\n        {\n            UpdateInternal(target, devices);\n            OnChanged();\n        }\n\n        [FreeFunction(\"GetDeviceList\")]\n        public static extern DevDevice[] GetDevices();\n\n        [FreeFunction(\"UpdateDeviceList\")]\n        internal static extern void UpdateInternal(string target, DevDevice[] devices);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Help.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    // Helper class to access Unity documentation.\n    [NativeHeader(\"Editor/Src/Panels/HelpPanel.h\")]\n    [NativeHeader(\"Editor/Platform/Interface/EditorUtility.h\")]\n    [NativeHeader(\"Editor/Src/Utility/DocUtilities.h\")]\n    public partial class Help\n    {\n        [FreeFunction]\n        internal static extern void SendHelpRequestedUsabilityEvent(long start, long duration, UnityEngine.Object contextObject, string url);\n\n        [FreeFunction(\"DocUtilities::GetDocumentationAbsolutePath\")]\n        private static extern string GetDocumentationAbsolutePath_Internal();\n\n        [UnityEngine.Scripting.RequiredByNativeCode]\n        internal static void ShowNamedHelp(string topic)\n        {\n            ShowHelpPage(topic);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Help.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\nusing System.Collections.Generic;\nusing System.IO;\nusing UnityEditor.Audio;\nusing UnityEditorInternal;\nusing UnityEngine.Networking;\nusing System.Text.RegularExpressions;\nusing UnityEditor.Presets;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    // Helper class to access Unity documentation.\n    public partial class Help\n    {\n        private const string k_MonoScriptReference = \"file:///unity/ScriptReference/MonoBehaviour.html\";\n        private static Dictionary<string, string> m_UrlCache = new Dictionary<string, string>();\n        private const string k_AbsoluteURI = \"file:///unity/\";\n        private const string k_AbsoluteFileRef = \"file:///\";\n        private const string k_ManualSection = \"manual\";\n        private const string k_ApiSection = \"api\";\n        private static string m_BaseDocumentationUrl;\n        private static Dictionary<string, object> m_LocalRedirectionMapping = new Dictionary<string, object>();\n        private const string k_RedirectManifest = \"redirect.json\";\n\n        private static string[] k_DocRedirectServer =\n        {\n            \"\",\n            \"https://docs-redirects.test.it.unity3d.com\",\n            \"https://docs-redirects.stg.it.unity3d.com\",\n            \"https://docs-redirects.prd.it.unity3d.com\",\n            \"https://docs-redirects.unity.com\"\n        };\n\n        internal static string k_AlphaReleaseNotesUrlBase = \"https://unity3d.com/unity/alpha/\";\n        internal static string k_BetaReleaseNotesUrlBase = \"https://unity3d.com/unity/beta/\";\n        internal static string k_ReleaseNotesUrlBase = \"https://unity3d.com/unity/whats-new/\";\n\n        internal enum DocRedirectionServer\n        {\n            None,\n            Test,\n            Staging,\n            Production,\n            PublicRedirect\n        }\n\n        internal static DocRedirectionServer docRedirectionServer\n        {\n            get => (DocRedirectionServer)EditorPrefs.GetInt(\"Help.docRedirectionServer\", (int)DocRedirectionServer.PublicRedirect);\n            set\n            {\n                EditorPrefs.SetInt(\"Help.docRedirectionServer\", (int)value);\n                m_BaseDocumentationUrl = null;\n                ClearCache();\n            }\n        }\n\n        internal static string baseDocumentationUrl\n        {\n            get\n            {\n                if (m_BaseDocumentationUrl == null)\n                {\n                    baseDocumentationUrl = GetDocumentationAbsolutePath_Internal();\n                }\n\n                return m_BaseDocumentationUrl;\n            }\n\n            set\n            {\n                m_BaseDocumentationUrl = value;\n                InitDocumentation();\n            }\n        }\n\n        public static bool HasHelpForObject(Object obj)\n        {\n            return HasHelpForObject(obj, true);\n        }\n\n        public static string GetHelpURLForObject(Object obj)\n        {\n            return GetHelpURLForObject(obj, true);\n        }\n\n        public static void ShowHelpForObject(Object obj)\n        {\n            var startTick = DateTime.Now.Ticks;\n            var url = GetHelpURLForObject(obj, true);\n            if (string.IsNullOrEmpty(url))\n                return;\n\n            BrowseURL(url);\n\n            SendHelpRequestedUsabilityEvent(startTick, DateTime.Now.Ticks - startTick, obj, url);\n        }\n\n        public static void ShowHelpPage(string page)\n        {\n            var startTick = DateTime.Now.Ticks;\n\n            var topicUri = new Uri(page);\n            var topic = topicUri.GetLeftPart(UriPartial.Path);\n            var anchor = topicUri.Fragment;\n            var path = FindHelpNamed(topic);\n\n            bool isUrl = Uri.IsWellFormedUriString(path, UriKind.Absolute);\n\n            if (anchor != \"\")\n            {\n                path = $\"{path}{anchor}\";\n                if (!isUrl)\n                    path = \"file://\" + path;\n            }\n\n            BrowseURL(path);\n\n            SendHelpRequestedUsabilityEvent(startTick, DateTime.Now.Ticks - startTick, null, path);\n        }\n\n        public static void BrowseURL(string url)\n        {\n            if (string.IsNullOrEmpty(url))\n                return;\n\n            if (Uri.IsWellFormedUriString(url, UriKind.Absolute))\n                Application.OpenURL(url);\n            else\n                Application.OpenURL($\"file://{url}\");\n        }\n\n        internal static bool HasHelpForObject(Object obj, bool defaultToMonoBehaviour)\n        {\n            return !string.IsNullOrEmpty(GetHelpURLForObject(obj, defaultToMonoBehaviour));\n        }\n\n        internal static string GetNiceHelpNameForObject(Object obj)\n        {\n            return GetNiceHelpNameForObject(obj, true);\n        }\n\n        internal static string GetNiceHelpNameForObject(Object obj, bool defaultToMonoBehaviour)\n        {\n            var helpTopic = HelpFileNameForObject(obj);\n            if (!defaultToMonoBehaviour || HasNamedHelp(helpTopic))\n            {\n                var dashIndex = helpTopic.IndexOf(\"-\");\n                if (dashIndex != -1)\n                {\n                    return helpTopic.Substring(dashIndex + 1);\n                }\n\n                switch (obj)\n                {\n                    case SceneAsset:\n                        return nameof(SceneAsset);\n                    case LightingDataAsset:\n                        return nameof(LightingDataAsset);\n                }\n            }\n            else\n            {\n                if (obj is Component || obj is MonoScript)\n                {\n                    return \"MonoBehaviour\";\n                }\n            }\n\n            return helpTopic;\n        }\n\n        internal static string GetHelpURLForObject(Object obj, bool defaultToMonoBehaviour)\n        {\n            if (obj == null || !obj)\n                return \"\";\n\n            var attrs = obj.GetType().GetCustomAttributes(typeof(HelpURLAttribute), true);\n            if (attrs.Length > 0)\n            {\n                var attr = (HelpURLAttribute)attrs[0];\n                var url = attr.URL;\n                if (!string.IsNullOrEmpty(attr.m_DispatchingFieldName))\n                {\n                    var field = obj.GetType().GetField(attr.m_DispatchingFieldName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);\n                    if (field != null)\n                    {\n                        var value = field.GetValue(obj);\n                        if (value != null)\n                        {\n                            var valueAttrs = value.GetType().GetCustomAttributes(typeof(HelpURLAttribute), true);\n                            if (valueAttrs.Length > 0)\n                            {\n                                var targetUrl = ((HelpURLAttribute)valueAttrs[0]).m_Url;\n                                if (!string.IsNullOrEmpty(targetUrl))\n                                {\n                                    url = targetUrl;\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (IsURL(url))\n                    return url;\n\n                // Assume url is a topic that needs to be properly formatted:\n                return FindHelpNamed(url);\n            }\n\n            var topicForObject = HelpFileNameForObject(obj);\n            if (HasNamedHelp(topicForObject))\n            {\n                return FindHelpNamed(topicForObject);\n            }\n\n            if (defaultToMonoBehaviour)\n            {\n                if (obj is Component || obj is MonoScript)\n                {\n                    return FindHelpNamed(k_MonoScriptReference);\n                }\n            }\n\n            return \"\";\n        }\n\n        internal static void ClearCache()\n        {\n            m_UrlCache.Clear();\n        }\n\n        internal static string TranslateURIForRedirection(string uri)\n        {\n            if (docRedirectionServer != DocRedirectionServer.None && IsLocalPath(uri) == false)\n            {\n                var version = InternalEditorUtility.GetUnityVersion();\n                //case 1300346: The redirection server that launched with 2020.2 badly redirects Manual/index.html and ScriptReference/index.html resulting in a 404\n                //Even without the 404, the Manual/index.html and ScriptReference/index.html need the version parameter to be redirected to the matching docs for this version\n                if (uri.Equals(string.Join(\"/\", new string[] { baseDocumentationUrl, \"Manual\", \"index.html\" }), StringComparison.OrdinalIgnoreCase))\n                    uri = $\"{baseDocumentationUrl}/?section=manual&version={version.Major}.{version.Minor}\";\n                if (uri.Equals(string.Join(\"/\", new string[] { baseDocumentationUrl, \"ScriptReference\", \"index.html\" }), StringComparison.OrdinalIgnoreCase))\n                    uri = $\"{baseDocumentationUrl}/?section=api&version={version.Major}.{version.Minor}\";\n            }\n            return uri;\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal static string FindHelpNamed(string topic)\n        {\n            if (m_UrlCache.ContainsKey(topic))\n            {\n                return m_UrlCache[topic];\n            }\n\n            var documentPath = \"\";\n            if (topic.StartsWith(k_AbsoluteURI))\n            {\n                documentPath = GetURLPath(true, baseDocumentationUrl, topic.Substring(k_AbsoluteURI.Length));\n            }\n            else if (topic.StartsWith(k_AbsoluteFileRef))\n            {\n                documentPath = topic.Substring(k_AbsoluteFileRef.Length);\n            }\n            else if (IsLocalPath(topic) == false)\n            {\n                documentPath = topic;\n            }\n            else\n            {\n                topic = UnityWebRequest.UnEscapeURL(topic);\n                if (IsLocalPath(baseDocumentationUrl))\n                {\n                    if (!TryRedirect(ref topic))\n                    {\n                        topic = $\"Manual/{topic}\";\n                    }\n                    documentPath = GetURLPath(true, baseDocumentationUrl, topic);\n                }\n                else if (docRedirectionServer == DocRedirectionServer.None)\n                {\n                    topic = $\"Manual/{topic}\";\n                    documentPath = GetURLPath(true, baseDocumentationUrl, topic);\n                }\n                else\n                {\n                    documentPath = GetURLPath(false, baseDocumentationUrl, topic);\n                    var version = InternalEditorUtility.GetUnityVersion();\n                    documentPath += $\"?version={version.Major}.{version.Minor}\";\n                }\n            }\n\n            if (IsLocalPath(documentPath))\n            {\n                documentPath = Uri.UnescapeDataString(documentPath);\n\n                if (!File.Exists(documentPath))\n                {\n                    documentPath = \"\";\n                }\n            }\n\n            documentPath = TranslateURIForRedirection(documentPath);\n\n            m_UrlCache[topic] = documentPath;\n\n            return documentPath;\n        }\n\n        internal static bool TryRedirect(ref string topicName)\n        {\n            if (m_LocalRedirectionMapping.ContainsKey(topicName))\n            {\n                topicName = m_LocalRedirectionMapping[topicName].ToString();\n                return true;\n            }\n\n            return false;\n        }\n\n        internal static string HelpFileNameForObject(Object obj)\n        {\n            if (obj.GetType().IsSubclassOf(typeof(MonoBehaviour)))\n            {\n                return $\"script-{obj.GetType().Name}\";\n            }\n\n            return obj switch\n            {\n                Terrain => \"script-Terrain\",\n                AudioMixerController or AudioMixerGroupController => \"class-AudioMixer\",\n                AudioImporter => \"class-AudioClip\", // UUM-96832: We don't have an entry in the manual for the audio importer.\n                VideoClipImporter => \"class-VideoClip\", // We don't have an entry in the manual for the video clip importer.\n                EditorSettings => \"class-EditorManager\",\n                SceneAsset => \"CreatingScenes\",\n                LightingDataAsset => \"LightmapSnapshot\",\n                PrefabImporter => \"Prefabs\",\n                Preset => \"Presets\",\n                MonoImporter => \"ScriptedImporters\",\n                MonoScript => \"class-TextAsset\",\n                DefaultAsset => \"\",\n                _ => $\"class-{obj.GetType().Name}\",\n            };\n        }\n\n        [UnityEngine.Scripting.RequiredByNativeCode]\n        internal static void OpenReleaseNotes()\n        {\n            var releaseNotesUrl = GetReleaseNotesUrl(InternalEditorUtility.GetUnityVersionDigits(), InternalEditorUtility.GetUnityDisplayVersion());\n            Application.OpenURL(releaseNotesUrl);\n        }\n\n        internal static string GetReleaseNotesUrl(string digitsOnlyVersion, string displayVersion)\n        {\n            var url = \"http://unity3d.com/whatsnew.html\";\n            var isUnreleased = displayVersion.Contains(\"a\") || displayVersion.Contains(\"b\");\n            if (isUnreleased)\n            {\n                var displayVersionWithBuildNumber = new Regex(@\"(\\d+\\.\\d+\\.[a-z0-9]+)\\.\\d+\");\n                var m = displayVersionWithBuildNumber.Match(displayVersion);\n                if (m.Success)\n                {\n                    displayVersion = m.Groups[1].Value;\n                }\n\n                if (displayVersion.Contains(\"a\"))\n                {\n                    url = $\"{k_AlphaReleaseNotesUrlBase}{displayVersion}\";\n                }\n                else\n                {\n                    url = $\"{k_BetaReleaseNotesUrlBase}{displayVersion}\";\n                }\n            }\n            else\n            {\n                url = $\"{k_ReleaseNotesUrlBase}{digitsOnlyVersion}\";\n            }\n\n            return url;\n        }\n\n        internal static string GetShortReleaseVersion()\n        {\n            var version = InternalEditorUtility.GetUnityVersion();\n            return $\"{version.Major}.{version.Minor}\";\n        }\n\n        private static void InitDocumentation()\n        {\n            ClearCache();\n            if (!IsLocalPath(m_BaseDocumentationUrl) && docRedirectionServer != DocRedirectionServer.None)\n            {\n                m_BaseDocumentationUrl = k_DocRedirectServer[(int)docRedirectionServer];\n            }\n            else\n            {\n                m_LocalRedirectionMapping = new Dictionary<string, object>();\n                var redirectFile = Path.Combine(m_BaseDocumentationUrl, k_RedirectManifest);\n                if (File.Exists(redirectFile))\n                {\n                    try\n                    {\n                        var content = File.ReadAllText(redirectFile);\n                        if (Json.Deserialize(content) is Dictionary<string, object> jsonData &&\n                            jsonData.ContainsKey(\"redirects\") &&\n                            jsonData[\"redirects\"] is Dictionary<string, object> redirectManifest)\n                        {\n                            m_LocalRedirectionMapping = redirectManifest;\n                        }\n                    }\n                    catch (Exception)\n                    {\n                        Debug.LogError($\"Cannot load redirect manifest: {redirectFile}\");\n                    }\n                }\n            }\n        }\n\n        private static bool IsURL(string path)\n        {\n            return path.StartsWith(\"http://\") || path.StartsWith(\"https://\") || path.StartsWith(k_AbsoluteFileRef);\n        }\n\n        private static bool IsLocalPath(string path)\n        {\n            return !path.StartsWith(\"http://\") && !path.StartsWith(\"https://\");\n        }\n\n        private static bool IsApiTopic(string topic)\n        {\n            return topic.StartsWith(\"class-\") || topic.StartsWith(\"script-\");\n        }\n\n        private static string GetURLPath(bool forceHtml, params string[] tokens)\n        {\n            var path = string.Join(\"/\", tokens);\n            if (forceHtml && !path.EndsWith(\".html\"))\n                path += \".html\";\n            return path;\n        }\n\n        private static bool HasNamedHelp(string topic)\n        {\n            if (string.IsNullOrEmpty(topic))\n                return false;\n            return !string.IsNullOrEmpty(FindHelpNamed(topic));\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/HierarchyProperty.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Text.RegularExpressions;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing Object = UnityEngine.Object;\nusing UnityEditor.SceneManagement;\nusing UnityEditor.AssetImporters;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    public enum InspectorMode\n    {\n        Normal = 0,\n        Debug = 1,\n        DebugInternal = 2\n    }\n\n    public enum HierarchyType\n    {\n        Assets = 1,\n        GameObjects = 2,\n    }\n\n    public enum IconDrawStyle\n    {\n        NonTexture = 0,\n        Texture = 1,\n    }\n\n    interface IHierarchyProperty\n    {\n        void Reset();\n        int instanceID { get; }\n        Object pptrValue { get; }\n        string name { get; }\n        bool hasChildren { get; }\n        int depth { get; }\n        int row { get; }\n        int colorCode { get; }\n        string guid { get; }\n        Texture2D icon { get; }\n        bool isValid { get; }\n        bool isMainRepresentation { get; }\n        bool hasFullPreviewImage { get; }\n        IconDrawStyle iconDrawStyle { get; }\n        bool isFolder { get; }\n        GUID[] dynamicDependencies { get; }\n\n        bool IsExpanded(int[] expanded);\n        bool Next(int[] expanded);\n        bool NextWithDepthCheck(int[] expanded, int minDepth);\n        bool Previous(int[] expanded);\n        bool Parent();\n\n        int[] ancestors { get; }\n\n        bool Find(int instanceID, int[] expanded);\n        int[] FindAllAncestors(int[] instanceIDs);\n\n        bool Skip(int count, int[] expanded);\n        int CountRemaining(int[] expanded);\n        int GetInstanceIDIfImported();\n    }\n\n    [NativeHeader(\"Editor/Src/Utility/HierarchyProperty.bindings.h\")]\n    [StructLayout(LayoutKind.Sequential)]\n    public sealed class HierarchyProperty : IHierarchyProperty\n    {\n        IntPtr m_Ptr;\n\n        public HierarchyProperty(HierarchyType hierarchyType)\n            : this(hierarchyType, \"Assets\", true)\n        {\n        }\n\n        public HierarchyProperty(HierarchyType hierarchyType, bool forceImport)\n            : this(hierarchyType, \"Assets\", forceImport)\n        {\n        }\n\n        public HierarchyProperty(string rootPath)\n            : this(HierarchyType.Assets, rootPath, true)\n        {\n        }\n\n        public HierarchyProperty(string rootPath, bool forceImport)\n            : this(HierarchyType.Assets, rootPath, forceImport)\n        {\n        }\n\n        public HierarchyProperty(HierarchyType hierarchyType, string rootPath, bool forceImport)\n        {\n            m_Ptr = Internal_Create(hierarchyType, rootPath, forceImport);\n        }\n\n        [FreeFunction(\"HierarchyPropertyBindings::Internal_Create\")]\n        static extern IntPtr Internal_Create(HierarchyType hierarchyType, string rootPath, bool forceImport);\n\n        internal void SetCustomScenes(Scene[] scenes)\n        {\n            if (scenes == null)\n                throw new ArgumentNullException(nameof(scenes));\n            SetCustomScenes(scenes.Select(s => s.handle).ToArray());\n        }\n\n        [FreeFunction(\"HierarchyPropertyBindings::SetCustomScenes\", HasExplicitThis = true)]\n        public extern void SetCustomScenes([NotNull] int[] sceneHandles);\n        [FreeFunction(\"HierarchyPropertyBindings::SetSubScenes\", HasExplicitThis = true)]\n        public extern void SetSubScenes([NotNull] SceneHierarchyHooks.SubSceneInfo[] subScenes);\n        public extern void Reset();\n\n        [FreeFunction(\"HierarchyPropertyBindings::Internal_Destroy\", IsThreadSafe = true)]\n        static extern void Internal_Destroy(IntPtr ptr);\n\n        void Dispose(bool disposing)\n        {\n            if (m_Ptr != IntPtr.Zero)\n            {\n                Internal_Destroy(m_Ptr);\n                m_Ptr = IntPtr.Zero;\n            }\n        }\n\n        void Dispose()\n        {\n            Dispose(true);\n            GC.SuppressFinalize(this);\n        }\n\n        ~HierarchyProperty() { Dispose(false); }\n\n        public extern int instanceID { get; }\n        public extern Object pptrValue { [FreeFunction(\"HierarchyPropertyBindings::PPtrValue\", HasExplicitThis = true)] get; }\n        public extern string name { get; }\n\n        [FreeFunction(\"HierarchyPropertyBindings::GetScene\", HasExplicitThis = true, ThrowsException = true)]\n        public extern Scene GetScene();\n\n        public extern bool hasChildren { [NativeName(\"HasChildren\")] get; }\n        public extern int depth { get; }\n        public extern int[] ancestors { get; }\n        public extern int row { get; }\n        public extern int colorCode { get; }\n\n        [FreeFunction(\"HierarchyPropertyBindings::IsExpanded\", HasExplicitThis = true)]\n        private extern bool IsExpanded_internal(int[] expanded, bool nonNullEmptyArray);\n\n        public bool IsExpanded(int[] expanded) => IsExpanded_internal(expanded, expanded != null && expanded.Length == 0);\n\n        public extern string guid { [FreeFunction(\"HierarchyPropertyBindings::GetGuid\", HasExplicitThis = true)] get; }\n        public extern bool alphaSorted { [NativeName(\"IsAlphaSorted\")] get; set; }\n        public extern bool showSceneHeaders { [NativeName(\"IsShowingSceneHeaders\")] get; [NativeName(\"SetShowingSceneHeaders\")] set; }\n        public extern bool isSceneHeader { [NativeName(\"IsSceneHeader\")] get; }\n        public extern bool isValid { [NativeName(\"IsValid\")] get; }\n        public extern bool isMainRepresentation { [NativeName(\"IsMainAssetRepresentation\")] get; }\n        public extern bool hasFullPreviewImage { [NativeName(\"HasFullPreviewImage\")] get; }\n        public extern IconDrawStyle iconDrawStyle { get; }\n        public extern bool isFolder { [NativeName(\"IsFolder\")] get; }\n        public extern GUID[] dynamicDependencies { get; }\n\n        [FreeFunction(\"HierarchyPropertyBindings::Next\", HasExplicitThis = true)]\n        private extern bool Next_internal(int[] expanded, bool nonNullEmptyArray);\n        public bool Next(int[] expanded) => Next_internal(expanded, expanded != null && expanded.Length == 0);\n        [FreeFunction(\"HierarchyPropertyBindings::NextWithDepthCheck\", HasExplicitThis = true)]\n        private extern bool NextWithDepthCheck_internal(int[] expanded, int minDepth, bool nonNullEmptyArray);\n        public bool NextWithDepthCheck(int[] expanded, int minDepth) => NextWithDepthCheck_internal(expanded, minDepth, expanded != null && expanded.Length == 0);\n        [FreeFunction(\"HierarchyPropertyBindings::Previous\", HasExplicitThis = true)]\n        private extern bool Previous_internal(int[] expanded, bool nonNullEmptyArray);\n        public bool Previous(int[] expanded) => Previous_internal(expanded, expanded != null && expanded.Length == 0);\n        public extern bool Parent();\n        [FreeFunction(\"HierarchyPropertyBindings::Find\", HasExplicitThis = true)]\n        private extern bool Find_internal(int instanceID, int[] expanded, bool nonNullEmptyArray);\n        public bool Find(int instanceID, int[] expanded) => Find_internal(instanceID, expanded, expanded != null && expanded.Length == 0);\n        [FreeFunction(\"HierarchyPropertyBindings::Skip\", HasExplicitThis = true)]\n        private extern bool Skip_internal(int count, int[] expanded, bool nonNullEmptyArray);\n        public bool Skip(int count, int[] expanded) =>Skip_internal(count, expanded, expanded != null && expanded.Length == 0);\n        [FreeFunction(\"HierarchyPropertyBindings::CountRemaining\", HasExplicitThis = true)]\n        private extern int CountRemaining_internal(int[] expanded, bool nonNullEmptyArray);\n        public int CountRemaining(int[] expanded) => CountRemaining_internal(expanded, expanded != null && expanded.Length == 0);\n\n        public extern int GetInstanceIDIfImported();\n\n        public extern Texture2D icon { [NativeName(\"GetCachedIcon\")] get; }\n\n        [RequiredByNativeCode]\n        static void SetFilter(HierarchyProperty hierarchy, string filter)\n        {\n            SearchFilter search = new SearchFilter();\n            SearchUtility.ParseSearchString(filter, search);\n            hierarchy.SetSearchFilter(search);\n        }\n\n        // Pre 4.0 interface (kept for backwards compability)\n        public void SetSearchFilter(string searchString, int mode)\n        {\n            SearchFilter filter = SearchableEditorWindow.CreateFilter(searchString, (SearchableEditorWindow.SearchMode)mode);\n            SetSearchFilter(filter);\n        }\n\n        // 4.0 interface (made internal for now)\n        internal void SetSearchFilter(SearchFilter filter)\n        {\n            SetSearchFilterImpl(SearchFilter.Split(filter.nameFilter), filter.classNames, filter.assetLabels, filter.assetBundleNames, new string[0], new string[0], filter.referencingInstanceIDs, filter.sceneHandles, filter.GlobToRegex().ToArray(), filter.productIds, filter.anyWithAssetOrigin, filter.showAllHits, filter.importLogFlags, filter.filterByTypeIntersection);\n        }\n\n        internal void CopySearchFilterFrom(HierarchyProperty other)\n        {\n            if (other == null)\n                throw new ArgumentNullException(nameof(other));\n            CopySearchFilterImpl(other);\n        }\n\n        [FreeFunction(\"HierarchyPropertyBindings::SetSearchFilterImpl\", HasExplicitThis = true)]\n        extern void SetSearchFilterImpl(string[] nameFilters, string[] classNames, string[] assetLabels, string[] assetBundleNames, string[] versionControlStates, string[] softLockControlStates, int[] referencingInstanceIDs, int[] sceneHandles, string[] regex, int[] productIds, bool anyWithAssetOrigin, bool showAllHits, ImportLogFlags importLogFlags, bool filterByTypeIntersection);\n\n        [FreeFunction(\"HierarchyPropertyBindings::CopySearchFilterImpl\", HasExplicitThis = true)]\n        extern void CopySearchFilterImpl(HierarchyProperty other);\n\n        [FreeFunction(\"HierarchyPropertyBindings::FindAllAncestors\", HasExplicitThis = true)]\n        public extern int[] FindAllAncestors(int[] instanceIDs);\n        [FreeFunction(\"HierarchyPropertyBindings::ClearSceneObjectsFilter\")]\n        public static extern void ClearSceneObjectsFilter();\n\n        internal static void ClearSceneObjectsFilterInScene(Scene[] scenes)\n        {\n            if (scenes == null)\n                throw new ArgumentNullException(nameof(scenes));\n            ClearSceneObjectsFilterInScene(scenes.Select(s => s.handle).ToArray());\n        }\n\n        [FreeFunction(\"HierarchyPropertyBindings::ClearSceneObjectsFilterInScene\")]\n        internal static extern void ClearSceneObjectsFilterInScene([NotNull] int[] sceneHandles);\n\n        [FreeFunction(\"HierarchyPropertyBindings::FilterSingleSceneObject\")]\n        public static extern void FilterSingleSceneObject(int instanceID, bool otherVisibilityState);\n\n        internal static void FilterSingleSceneObjectInScene(int instanceID, bool otherVisibilityState, Scene[] scenes)\n        {\n            if (scenes == null)\n                throw new ArgumentNullException(nameof(scenes));\n            FilterSingleSceneObjectInScene(instanceID, otherVisibilityState, scenes.Select(s => s.handle).ToArray());\n        }\n\n        [FreeFunction(\"HierarchyPropertyBindings::FilterSingleSceneObjectInScene\")]\n        internal static extern void FilterSingleSceneObjectInScene(int instanceID, bool otherVisibilityState, [NotNull] int[] sceneHandles);\n\n        [FreeFunction(\"HierarchyPropertyBindings::SetFilteredVisibility\", HasExplicitThis = true)]\n        internal extern void SetFilteredVisibility(bool visible);\n\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(HierarchyProperty prop) => prop.m_Ptr;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/HomeWindow.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/HomeWindow/HomeWindow.h\")]\n    static class HomeWindow\n    {\n        // NOTE: Keep in sync with enum in Editor/Src/HomeWindow/HomeWindow.h\n        public enum HomeMode\n        {\n            Login,\n            License,\n            Launching,\n            NewProjectOnly,\n            OpenProjectOnly,\n            ManageLicense,\n            Welcome,\n            Tutorial,\n            Logout\n        }\n\n        [NativeMethod(\"StaticShow\")]\n        public static extern bool Show(HomeMode mode);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/HostView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Data.Common;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEditor.Overlays;\nusing UnityEditor.ShortcutManagement;\nusing UnityEditor.StyleSheets;\nusing UnityEditor.UIElements;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [UnityEngine.Bindings.VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n    internal class HostView : GUIView, IEditorWindowModel\n    {\n        static class Styles\n        {\n            public const float iconMargin = 1f;\n\n            public static readonly GUIStyle background = new GUIStyle(\"hostview\");\n            public static readonly GUIStyle overlay = \"dockareaoverlay\";\n            public static readonly GUIStyle menuButton = \"WindowMenuButton\";\n            public static readonly GUIStyle tabWindowBackground = \"TabWindowBackground\";\n\n            public static class DataModes\n            {\n                public const float switchButtonWidth = 16.0f;\n\n                static readonly string k_AutomaticAuthoringString = L10n.Tr(\"Automatic (Authoring)\");\n                static readonly string k_AutomaticMixedString = L10n.Tr(\"Automatic (Mixed)\");\n                static readonly string k_AutomaticRuntimeString = L10n.Tr(\"Automatic (Runtime)\");\n                static readonly string k_AuthoringString = L10n.Tr(\"Authoring\");\n                static readonly string k_MixedString = L10n.Tr(\"Mixed\");\n                static readonly string k_RuntimeString = L10n.Tr(\"Runtime\");\n                static readonly string k_DisabledString = L10n.Tr(\"Disabled\");\n\n                // Auto data mode icons\n                static readonly Texture2D k_AuthoringModeIcon = EditorGUIUtility.LoadIcon(\"DataMode.Authoring\");\n                static readonly Texture2D k_MixedModeIcon = EditorGUIUtility.LoadIcon(\"DataMode.Mixed\");\n                static readonly Texture2D k_RuntimeModeIcon = EditorGUIUtility.LoadIcon(\"DataMode.Runtime\");\n\n                public static readonly GUIContent authoringModeContent = EditorGUIUtility.TrIconContent(k_AuthoringModeIcon, k_AutomaticAuthoringString);\n                public static readonly GUIContent mixedModeContent = EditorGUIUtility.TrIconContent(k_MixedModeIcon, k_AutomaticMixedString);\n                public static readonly GUIContent runtimeModeContent = EditorGUIUtility.TrIconContent(k_RuntimeModeIcon, k_AutomaticRuntimeString);\n\n                // Sticky data mode icons\n                static readonly Texture2D k_StickyAuthoringModeIcon = EditorGUIUtility.LoadIcon(\"DataMode.Authoring.Sticky\");\n                static readonly Texture2D k_StickyMixedModeIcon = EditorGUIUtility.LoadIcon(\"DataMode.Mixed.Sticky\");\n                static readonly Texture2D k_StickyRuntimeModeIcon = EditorGUIUtility.LoadIcon(\"DataMode.Runtime.Sticky\");\n\n                public static readonly GUIContent stickyAuthoringModeContent = EditorGUIUtility.TrIconContent(k_StickyAuthoringModeIcon, k_AuthoringString);\n                public static readonly GUIContent stickyMixedModeContent = EditorGUIUtility.TrIconContent(k_StickyMixedModeIcon, k_MixedString);\n                public static readonly GUIContent stickyRuntimeModeContent = EditorGUIUtility.TrIconContent(k_StickyRuntimeModeIcon, k_RuntimeString);\n\n                // Use an empty style to avoid the hover effect of normal buttons\n                public static readonly GUIStyle switchStyle = new GUIStyle();\n\n                public static readonly Dictionary<DataMode, GUIContent> dataModeNameLabels =\n                    new Dictionary<DataMode, GUIContent>\n                    {\n                        { DataMode.Disabled,  EditorGUIUtility.TextContent(k_DisabledString)  },\n                        { DataMode.Authoring, EditorGUIUtility.TextContent(k_AuthoringString) },\n                        { DataMode.Mixed,     EditorGUIUtility.TextContent(k_MixedString)     },\n                        { DataMode.Runtime,   EditorGUIUtility.TextContent(k_RuntimeString)   }\n                    };\n            }\n\n            static Styles()\n            {\n                // Fix annoying GUILayout issue: When using GUILayout in Utility windows there\n                // was always padded 10 px at the top! Todo: Fix this in EditorResources\n                background.padding.top = 0;\n            }\n        }\n\n        static string kPlayModeDarkenKey = \"Playmode tint\";\n        internal static PrefColor kPlayModeDarken = new PrefColor(kPlayModeDarkenKey, .8f, .8f, .8f, 1);\n        internal static event Action<HostView> actualViewChanged;\n        internal static event Action<GenericMenu, EditorWindow> populateDefaultMenuItems;\n\n        [SerializeField] private EditorWindow m_ActualView;\n        [NonSerialized] protected readonly RectOffset m_BorderSize = new RectOffset();\n        internal bool showGenericMenu { get; set; } = true;\n\n        protected delegate void EditorWindowDelegate();\n        protected delegate void EditorWindowShowButtonDelegate(Rect rect);\n\n        protected EditorWindowDelegate m_OnGUI;\n        protected EditorWindowDelegate m_OnFocus;\n        protected EditorWindowDelegate m_OnLostFocus;\n        protected EditorWindowDelegate m_OnProjectChange;\n        protected EditorWindowDelegate m_OnSelectionChange;\n        protected EditorWindowDelegate m_OnDidOpenScene;\n        protected EditorWindowDelegate m_OnInspectorUpdate;\n        protected EditorWindowDelegate m_OnHierarchyChange;\n        protected EditorWindowDelegate m_OnBecameVisible;\n        protected EditorWindowDelegate m_OnBecameInvisible;\n        protected EditorWindowDelegate m_Update;\n        protected EditorWindowDelegate m_ModifierKeysChanged;\n        protected EditorWindowShowButtonDelegate m_ShowButton;\n\n        private bool m_IsLosingFocus = false;\n\n        internal EditorWindow actualView\n        {\n            [UnityEngine.Bindings.VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n            get { return m_ActualView; }\n            set { SetActualViewInternal(value, sendEvents: true); }\n        }\n\n        static readonly Vector2 k_DockedMinSize = new Vector2(100, 50);\n        static readonly Vector2 k_DockedMaxSize = new Vector2(8096, 8096);\n        public override Vector2 minSize { get => (actualView?.docked ?? false) ? k_DockedMinSize : base.minSize; }\n        public override Vector2 maxSize { get => (actualView?.docked ?? false) ? k_DockedMaxSize : base.maxSize; }\n\n        internal void SetActualViewInternal(EditorWindow value, bool sendEvents)\n        {\n            if (m_ActualView == value)\n                return;\n\n            DeregisterSelectedPane(clearActualView: true, sendEvents: true, isSwitchingTab: value != null);\n            m_ActualView = value;\n            m_ActualViewName = null;\n\n            CreateDelegates();\n\n            name = GetViewName();\n            SetActualViewName(name);\n            RegisterSelectedPane(sendEvents);\n            actualViewChanged?.Invoke(this);\n        }\n\n        private void CreateDelegates()\n        {\n            m_OnGUI = CreateDelegate(\"OnGUI\");\n            m_OnFocus = CreateDelegate(\"OnFocus\");\n            m_OnLostFocus = CreateDelegate(\"OnLostFocus\");\n            m_OnProjectChange = CreateDelegate(\"OnProjectChange\");\n            m_OnSelectionChange = CreateDelegate(\"OnSelectionChange\");\n            m_OnDidOpenScene = CreateDelegate(\"OnDidOpenScene\");\n            m_OnInspectorUpdate = CreateDelegate(\"OnInspectorUpdate\");\n            m_OnHierarchyChange = CreateDelegate(\"OnHierarchyChange\");\n            m_OnBecameVisible = CreateDelegate(\"OnBecameVisible\");\n            m_OnBecameInvisible = CreateDelegate(\"OnBecameInvisible\");\n            m_Update = CreateDelegate(\"Update\");\n            m_ModifierKeysChanged = CreateDelegate(\"ModifierKeysChanged\");\n            var methodInfo = GetPaneMethod(\"ShowButton\");\n            if (methodInfo != null)\n                m_ShowButton = (EditorWindowShowButtonDelegate)Delegate.CreateDelegate(typeof(EditorWindowShowButtonDelegate), m_ActualView, methodInfo);\n            else\n                m_ShowButton = null;\n        }\n\n        private void ClearDelegates()\n        {\n            m_OnGUI = null;\n            m_OnFocus = null;\n            m_OnLostFocus = null;\n            m_OnProjectChange = null;\n            m_OnSelectionChange = null;\n            m_OnDidOpenScene = null;\n            m_OnInspectorUpdate = null;\n            m_OnHierarchyChange = null;\n            m_OnBecameVisible = null;\n            m_OnBecameInvisible = null;\n            m_Update = null;\n            m_ModifierKeysChanged = null;\n            m_ShowButton = null;\n        }\n\n        internal void ResetActiveView()\n        {\n            DeregisterSelectedPane(clearActualView: false, sendEvents: true);\n            RegisterSelectedPane(sendEvents: true);\n            actualViewChanged?.Invoke(this);\n        }\n\n        internal void UpdateMargins(EditorWindow window)\n        {\n            UpdateViewMargins(window);\n        }\n\n        RectOffset IEditorWindowModel.viewMargins => GetBorderSize();\n\n        Action IEditorWindowModel.onSplitterGUIHandler { get; set; }\n\n        protected void UpdateViewMargins(EditorWindow view)\n        {\n            if (view == null)\n                return;\n\n            editorWindowBackend?.ViewMarginsChanged();\n        }\n\n        protected override void SetPosition(Rect newPos)\n        {\n            base.SetPosition(newPos);\n            SetActualViewPosition(newPos);\n        }\n\n        protected virtual void SetActualViewPosition(Rect newPos)\n        {\n            if (m_ActualView != null)\n            {\n                m_ActualView.m_Pos = newPos;\n                UpdateViewMargins(m_ActualView);\n                m_ActualView.OnResized();\n            }\n        }\n\n        internal override void SetWindow(ContainerWindow win)\n        {\n            base.SetWindow(win);\n            if (m_ActualView != null)\n            {\n                UpdateViewMargins(m_ActualView);\n            }\n        }\n\n        protected override void OnEnable()\n        {\n            CreateDelegates();\n            EditorPrefs.onValueWasUpdated += PlayModeTintColorChangedCallback;\n            base.OnEnable();\n\n            RegisterSelectedPane(sendEvents: true);\n\n            showGenericMenu = ModeService.HasCapability(ModeCapability.HostViewGenericMenu, true);\n            ModeService.modeChanged += OnEditorModeChanged;\n        }\n\n        protected override void OnDisable()\n        {\n            ModeService.modeChanged -= OnEditorModeChanged;\n            EditorPrefs.onValueWasUpdated -= PlayModeTintColorChangedCallback;\n            base.OnDisable();\n            DeregisterSelectedPane(clearActualView: false, sendEvents: true);\n            // Host views are destroyed in the middle of an OnGUI loop, so we need to ensure that we're not invoking\n            // OnGUI on destroyed instances.\n            m_OnGUI = null;\n            m_Update = null;\n        }\n\n        private void OnEditorModeChanged(ModeService.ModeChangedArgs args)\n        {\n            if (!this)\n                return;\n            showGenericMenu = ModeService.HasCapability(ModeCapability.HostViewGenericMenu, true);\n            Repaint();\n        }\n\n        private void HandleSplitView()\n        {\n            SplitView sp = parent as SplitView;\n            if (Event.current.type == EventType.Repaint && sp)\n            {\n                View view = this;\n                while (sp)\n                {\n                    int id = sp.controlID;\n\n                    if (id == GUIUtility.hotControl || GUIUtility.hotControl == 0)\n                    {\n                        int idx = sp.IndexOfChild(view);\n                        if (sp.vertical)\n                        {\n                            if (idx != 0)\n                                EditorGUIUtility.AddCursorRect(new Rect(0, 0, position.width, SplitView.kGrabDist), MouseCursor.SplitResizeUpDown, id);\n                            else if (idx != sp.children.Length - 1)\n                                EditorGUIUtility.AddCursorRect(new Rect(0, position.height - SplitView.kGrabDist, position.width, SplitView.kGrabDist), MouseCursor.SplitResizeUpDown, id);\n                        }\n                        else // horizontal\n                        {\n                            if (idx != 0)\n                                EditorGUIUtility.AddCursorRect(new Rect(0, 0, SplitView.kGrabDist, position.height), MouseCursor.SplitResizeLeftRight, id);\n                            else if (idx != sp.children.Length - 1)\n                                EditorGUIUtility.AddCursorRect(new Rect(position.width - SplitView.kGrabDist, 0, SplitView.kGrabDist, position.height), MouseCursor.SplitResizeLeftRight, id);\n                        }\n                    }\n\n                    view = sp;\n                    sp = sp.parent as SplitView;\n                }\n\n                sp = (SplitView)parent;\n            }\n\n            if (sp)\n            {\n                Event e = new Event(Event.current);\n                e.mousePosition += new Vector2(position.x, position.y);\n                sp.SplitGUI(e);\n                if (e.type == EventType.Used)\n                    Event.current.Use();\n            }\n        }\n\n        protected override void OldOnGUI()\n        {\n            EditorGUIUtility.ResetGUIState();\n\n            if (actualView)\n                GUI.color = actualView.rootVisualElement.playModeTintColor;\n\n            using (new GUILayout.VerticalScope(Styles.background))\n            {\n                if (actualView)\n                    actualView.m_Pos = screenPosition;\n\n                try\n                {\n                    HandleSplitView();\n                    m_OnGUI?.Invoke();\n                }\n                finally\n                {\n                    CheckNotificationStatus();\n\n                    EditorGUI.ShowRepaints();\n                }\n            }\n        }\n\n        protected override bool OnFocus()\n        {\n            m_OnFocus?.Invoke();\n            EditorWindow.OnWindowFocusChanged();\n\n            // Callback could have killed us. If so, die now...\n            if (!this)\n                return false;\n\n            editorWindowBackend?.Focused();\n\n            Repaint();\n            return true;\n        }\n\n        internal void OnLostFocus()\n        {\n            // Avoid calling OnLostFocus script callback if we are already processing the focus lost.\n            // This can happen when user scripts call Close() in OnLostFocus() callback.\n            if (m_IsLosingFocus)\n                return;\n\n            EditorGUI.EndEditingActiveTextField();\n\n            try\n            {\n                m_IsLosingFocus = true;\n                m_OnLostFocus?.Invoke();\n            }\n            finally\n            {\n                m_IsLosingFocus = false;\n            }\n\n            // Callback could have killed us\n            if (!this)\n                return;\n\n            editorWindowBackend?.Blurred();\n\n            Repaint();\n        }\n\n        protected override void OnBackingScaleFactorChanged()\n        {\n            base.OnBackingScaleFactorChanged();\n            if (m_ActualView != null)\n                m_ActualView.OnBackingScaleFactorChangedInternal();\n        }\n\n        protected override void OnDestroy()\n        {\n            if (m_ActualView)\n                DestroyImmediate(m_ActualView, true);\n            base.OnDestroy();\n        }\n\n        private static readonly Type[] k_PaneTypes =\n        {\n            typeof(SceneView),\n            typeof(GameView),\n            typeof(InspectorWindow),\n            typeof(SceneHierarchyWindow),\n            typeof(ProjectBrowser),\n            typeof(ProfilerWindow),\n            typeof(AnimationWindow)\n        };\n\n        private static IEnumerable<Type> GetCurrentModePaneTypes(string modePaneTypeSectionName)\n        {\n            var modePaneTypes = ModeService.GetModeDataSectionList<string>(ModeService.currentIndex, modePaneTypeSectionName);\n            var editorWindowTypes = TypeCache.GetTypesDerivedFrom<EditorWindow>();\n            foreach (var paneTypeName in modePaneTypes)\n            {\n                var paneType = editorWindowTypes.FirstOrDefault(t => t.Name.EndsWith(paneTypeName));\n                if (paneType != null)\n                    yield return paneType;\n                else\n                    Debug.LogWarning($\"Cannot find editor window pane type {paneTypeName} for editor mode {ModeService.currentId}.\");\n            }\n        }\n\n        private static IEnumerable<Type> GetDefaultPaneTypes()\n        {\n            const string k_PaneTypesSectionName = \"pane_types\";\n            if (!ModeService.HasSection(ModeService.currentIndex, k_PaneTypesSectionName))\n                return k_PaneTypes;\n            return GetCurrentModePaneTypes(k_PaneTypesSectionName);\n        }\n\n        protected IEnumerable<Type> GetPaneTypes()\n        {\n            foreach (var paneType in GetDefaultPaneTypes())\n                yield return paneType;\n\n            var extraPaneTypes = m_ActualView.GetExtraPaneTypes().ToList();\n            if (extraPaneTypes.Count > 0)\n            {\n                yield return null; // for spacer\n                foreach (var paneType in extraPaneTypes)\n                    yield return paneType;\n            }\n        }\n\n        // Messages sent by Unity to editor windows today.\n        // The implementation is not very good, but oh well... it gets the message across.\n\n        internal void OnProjectChange()\n        {\n            m_OnProjectChange?.Invoke();\n        }\n\n        internal void OnSelectionChange()\n        {\n            m_OnSelectionChange?.Invoke();\n        }\n\n        internal void OnDidOpenScene()\n        {\n            m_OnDidOpenScene?.Invoke();\n        }\n\n        internal void OnInspectorUpdate()\n        {\n            m_OnInspectorUpdate?.Invoke();\n        }\n\n        internal void OnHierarchyChange()\n        {\n            m_OnHierarchyChange?.Invoke();\n        }\n\n        EditorWindowDelegate CreateDelegate(string methodName)\n        {\n            var methodInfo = GetPaneMethod(methodName);\n            if (methodInfo != null)\n                return (EditorWindowDelegate)Delegate.CreateDelegate(typeof(EditorWindowDelegate), m_ActualView, methodInfo);\n            return null;\n        }\n\n        MethodInfo GetPaneMethod(string methodName)\n        {\n            return GetPaneMethod(methodName, m_ActualView);\n        }\n\n        protected MethodInfo GetPaneMethod(string methodName, object obj)\n        {\n            if (obj == null)\n                return null;\n\n            Type t = obj.GetType();\n\n            while (t != null)\n            {\n                var method = t.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);\n                if (method != null)\n                    return method;\n\n                t = t.BaseType;\n            }\n            return null;\n        }\n\n        private string m_ActualViewName;\n        private string GetActualViewName()\n        {\n            if (m_ActualViewName != null)\n                return m_ActualViewName;\n            m_ActualViewName = actualView != null ? actualView.GetType().Name : GetType().Name;\n            return m_ActualViewName;\n        }\n\n        public void InvokeOnGUI(Rect onGUIPosition)\n        {\n            if (!this)\n                return;\n\n            //We backup and restore the group count to properly identify the ongui method where the unbalance occurs.\n            int backup = GUILayoutUtility.unbalancedgroupscount;\n\n            GUILayoutUtility.unbalancedgroupscount = 0;\n            BeginOffsetArea(m_ActualView.rootVisualElement.worldBound, GUIContent.none, Styles.tabWindowBackground);\n\n            EditorGUIUtility.ResetGUIState();\n            if (actualView)\n                GUI.color = actualView.rootVisualElement.playModeTintColor;\n\n            bool isExitGUIException = false;\n            try\n            {\n                m_OnGUI?.Invoke();\n            }\n            catch (TargetInvocationException e)\n            {\n                Exception exception = e;\n                while (exception is TargetInvocationException && exception.InnerException != null)\n                    exception = exception.InnerException;\n\n                isExitGUIException = exception is ExitGUIException;\n\n                throw;\n            }\n            catch(ExitGUIException)\n            {\n                isExitGUIException = true;\n                throw;\n            }\n            finally\n            {\n                // We explicitly called BeginOffsetArea outside this try-catch scope,\n                // so we need to always explicitly end it as well just like all other\n                // GUI scopes are responsible for dealing with ExitGUI properly.\n                EndOffsetArea();\n\n                // We can't reset gui state after ExitGUI we just want to bail completely\n                if (!(isExitGUIException || GUIUtility.guiIsExiting))\n                {\n                    CheckNotificationStatus();\n\n                    if (GUILayoutUtility.unbalancedgroupscount != 0)\n                    {\n                        Debug.LogError(\"GUI Error: Invalid GUILayout state in \" + GetActualViewName() + \" view. Verify that all layout Begin/End calls match\");\n                    }\n\n                    EditorGUIUtility.ResetGUIState();\n                    if (actualView)\n                        GUI.color = actualView.rootVisualElement.playModeTintColor;\n\n                    if (Event.current != null && Event.current.type == EventType.Repaint)\n                        Styles.overlay.Draw(onGUIPosition, GUIContent.none, 0);\n                }\n\n                GUILayoutUtility.unbalancedgroupscount = backup;\n            }\n        }\n\n        ///  TODO: Optimize with Delegate.CreateDelegate\n        protected void Invoke(string methodName)\n        {\n            Invoke(methodName, m_ActualView);\n        }\n\n        protected void Invoke(string methodName, object obj)\n        {\n            MethodInfo mi = GetPaneMethod(methodName, obj);\n            mi?.Invoke(obj, null);\n        }\n\n        EditorWindow IEditorWindowModel.window => m_ActualView;\n\n        public IEditorWindowBackend editorWindowBackend\n        {\n            get { return windowBackend as IEditorWindowBackend; }\n            set { windowBackend = value; }\n        }\n\n        protected void RegisterSelectedPane(bool sendEvents)\n        {\n            if (!m_ActualView)\n                return;\n\n            m_ActualView.m_Parent = this;\n\n            ValidateWindowBackendForCurrentView();\n\n            editorWindowBackend?.OnRegisterWindow();\n\n            if (GetPaneMethod(\"Update\") != null)\n            {\n                EditorApplication.update -= SendUpdate;\n                EditorApplication.update += SendUpdate;\n            }\n\n            if (GetPaneMethod(\"ModifierKeysChanged\") != null)\n            {\n                EditorApplication.modifierKeysChanged -= SendModKeysChanged;\n                EditorApplication.modifierKeysChanged += SendModKeysChanged;\n            }\n\n            m_ActualView.MakeParentsSettingsMatchMe();\n\n            if (m_ActualView.m_FadeoutTime != 0)\n            {\n                EditorApplication.update -= m_ActualView.CheckForWindowRepaint;\n                EditorApplication.update += m_ActualView.CheckForWindowRepaint;\n            }\n\n            if (sendEvents)\n            {\n                try\n                {\n                    m_OnBecameVisible?.Invoke();\n                    m_OnFocus?.Invoke();\n                    EditorWindow.OnWindowFocusChanged();\n                }\n                catch (TargetInvocationException ex)\n                {\n                    // We need to catch these so the window initialization doesn't get screwed\n                    if (ex.InnerException != null)\n                        Debug.LogError(ex.InnerException.GetType().Name + \":\" + ex.InnerException.Message);\n                }\n            }\n\n            UpdateViewMargins(m_ActualView);\n        }\n\n        protected void DeregisterSelectedPane(bool clearActualView, bool sendEvents, bool isSwitchingTab = false)\n        {\n            if (!m_ActualView)\n                return;\n\n            if (m_Update != null)\n                EditorApplication.update -= SendUpdate;\n\n            if (m_ModifierKeysChanged != null)\n                EditorApplication.modifierKeysChanged -= SendModKeysChanged;\n\n            if (m_ActualView.m_FadeoutTime != 0)\n            {\n                EditorApplication.update -= m_ActualView.CheckForWindowRepaint;\n            }\n\n            // UUM-57083. Allow Blur events to take effect when switching tab.\n            if (isSwitchingTab)\n            {\n                UnityEngine.UIElements.EventDispatcher.editorDispatcher.PushDispatcherContext();\n            }\n\n            if (clearActualView)\n            {\n                var onBecameInvisible = m_OnBecameInvisible;\n\n                if (sendEvents)\n                {\n                    OnLostFocus();\n                    onBecameInvisible?.Invoke();\n                }\n\n                ClearDelegates();\n            }\n\n            editorWindowBackend?.OnUnregisterWindow();\n\n            if (isSwitchingTab)\n            {\n                UnityEngine.UIElements.EventDispatcher.editorDispatcher.PopDispatcherContext();\n            }\n\n            if (clearActualView)\n            {\n                m_ActualView = null;\n            }\n        }\n\n        private bool m_NotificationIsVisible;\n\n        bool IEditorWindowModel.notificationVisible => m_NotificationIsVisible;\n\n        protected void CheckNotificationStatus()\n        {\n            if (m_ActualView != null && m_ActualView.m_FadeoutTime != 0)\n            {\n                if (!m_NotificationIsVisible)\n                {\n                    m_NotificationIsVisible = true;\n                    editorWindowBackend?.NotificationVisibilityChanged();\n                }\n            }\n            else if (m_NotificationIsVisible)\n            {\n                m_NotificationIsVisible = false;\n                editorWindowBackend?.NotificationVisibilityChanged();\n            }\n        }\n\n        void SendUpdate()\n        {\n            m_Update?.Invoke();\n        }\n\n        void SendModKeysChanged()\n        {\n            m_ModifierKeysChanged?.Invoke();\n        }\n\n        internal RectOffset borderSize => GetBorderSize();\n\n        protected virtual RectOffset GetBorderSize() { return m_BorderSize; }\n\n        private static WindowAction[] s_windowActions;\n        private static WindowAction[] windowActions\n        {\n            get\n            {\n                if (s_windowActions == null)\n                {\n                    s_windowActions = FetchWindowActionFromAttribute();\n                }\n                return s_windowActions;\n            }\n        }\n\n        public static SVC<float> genericMenuLeftOffset = new SVC<float>(\"--window-generic-menu-left-offset\", 20f);\n        public static SVC<float> genericMenuFloatingLeftOffset = new SVC<float>(\"--window-floating-generic-menu-left-offset\", 20f);\n        internal static float GetGenericMenuLeftOffset(bool addFloatingWindowButtonsTopRight)\n        {\n            if (addFloatingWindowButtonsTopRight)\n                return genericMenuFloatingLeftOffset + ContainerWindow.buttonStackWidth;\n            else\n                return genericMenuLeftOffset;\n        }\n\n        internal float GetExtraButtonsWidth()\n        {\n            float extraWidth = 0;\n\n            // Generally reserved for the lock icon\n            if (m_ShowButton != null)\n                extraWidth += ContainerWindow.kButtonWidth;\n\n            if (m_ActualView.GetDataModeController_Internal().ShouldDrawDataModesSwitch())\n                extraWidth += Styles.DataModes.switchButtonWidth + Styles.iconMargin;\n\n            foreach (var item in windowActions)\n            {\n                if (item != null && (item.validateHandler == null || item.validateHandler(actualView, item)) && item.width.HasValue)\n                    extraWidth += item.width.Value + Styles.iconMargin;\n            }\n            return extraWidth;\n        }\n\n        protected void ShowGenericMenu(float leftOffset, float topOffset)\n        {\n            if (showGenericMenu)\n            {\n                Rect paneMenu = new Rect(leftOffset, topOffset, Styles.menuButton.fixedWidth, Styles.menuButton.fixedHeight);\n                if (EditorGUI.DropdownButton(paneMenu, GUIContent.none, FocusType.Passive, Styles.menuButton))\n                    PopupGenericMenu(m_ActualView, paneMenu);\n\n                if (m_ShowButton != null)\n                    leftOffset -= paneMenu.width + Styles.iconMargin;\n            }\n\n            // Give panes an option of showing a small button next to the generic menu (used for inspector lock icon)\n            if (m_ShowButton != null)\n                m_ShowButton.Invoke(new Rect(leftOffset, topOffset, ContainerWindow.kButtonWidth, ContainerWindow.kButtonHeight));\n\n            var dataModeControllerInternal = m_ActualView.GetDataModeController_Internal();\n            if (dataModeControllerInternal.ShouldDrawDataModesSwitch())\n            {\n                var isClientInAutomaticDataMode = dataModeControllerInternal.isAutomatic;\n                var switchContent = dataModeControllerInternal.dataMode switch\n                {\n                    DataMode.Authoring => isClientInAutomaticDataMode? Styles.DataModes.authoringModeContent : Styles.DataModes.stickyAuthoringModeContent,\n                    DataMode.Mixed => isClientInAutomaticDataMode? Styles.DataModes.mixedModeContent : Styles.DataModes.stickyMixedModeContent,\n                    DataMode.Runtime => isClientInAutomaticDataMode? Styles.DataModes.runtimeModeContent : Styles.DataModes.stickyRuntimeModeContent,\n                    _ => default\n                };\n\n                // Last chance to bail in case something weird happened\n                if (switchContent != default)\n                {\n                    leftOffset -= Styles.DataModes.switchButtonWidth + Styles.iconMargin;\n                    var switchRect = new Rect(leftOffset, topOffset, Styles.DataModes.switchButtonWidth, ContainerWindow.kButtonHeight);\n\n                    if (EditorGUI.Button(switchRect, switchContent, Styles.DataModes.switchStyle))\n                    {\n                        var evt = Event.current;\n\n                        if (evt.button == 0 || evt.button == 1) // left click or right click\n                        {\n                            var menu = new GenericMenu();\n                            PopulateDataModeDropdown(dataModeControllerInternal, menu);\n                            menu.DropDown(switchRect);\n                        }\n                    }\n                }\n            }\n\n            foreach (var item in windowActions)\n            {\n                if (item != null && (item.validateHandler == null || item.validateHandler(actualView, item)) && item.width.HasValue)\n                {\n                    leftOffset -= item.width.Value + Styles.iconMargin;\n                    Rect itemRect = new Rect(leftOffset, topOffset, item.width.Value, ContainerWindow.kButtonHeight);\n                    if (item.drawHandler != null)\n                    {\n                        if (item.drawHandler(actualView, item, itemRect))\n                            item.executeHandler(actualView, item);\n                    }\n                    else if (item.icon != null)\n                    {\n                        if (EditorGUI.Button(itemRect, EditorGUIUtility.TrIconContent(item.icon, item.menuPath), EditorStyles.iconButton))\n                            item.executeHandler(actualView, item);\n                    }\n                }\n            }\n        }\n\n        void PopulateDataModeDropdown(DataModeController clientDataModeController, GenericMenu menu)\n        {\n            var autoLabel = !clientDataModeController.isAutomatic\n                ? L10n.Tr($\"Automatic ({clientDataModeController.preferredDataMode})\")\n                : L10n.Tr($\"Automatic ({clientDataModeController.dataMode})\");\n\n            menu.AddItem(new GUIContent(autoLabel),\n                clientDataModeController.isAutomatic,\n                () => clientDataModeController.SwitchToAutomatic());\n\n            menu.AddSeparator(\"\");\n\n            foreach (var mode in clientDataModeController.supportedDataModes)\n            {\n                menu.AddItem(Styles.DataModes.dataModeNameLabels[mode],\n                    !clientDataModeController.isAutomatic && clientDataModeController.dataMode == mode,\n                    () => clientDataModeController.SwitchToStickyDataMode(mode));\n            }\n        }\n\n        private static WindowAction[] FetchWindowActionFromAttribute()\n        {\n            var methods = AttributeHelper.GetMethodsWithAttribute<WindowActionAttribute>();\n            return methods.methodsWithAttributes.Select(method =>\n            {\n                try\n                {\n                    var callback = Delegate.CreateDelegate(typeof(Func<WindowAction>), method.info) as Func<WindowAction>;\n                    return callback?.Invoke();\n                }\n                catch (Exception)\n                {\n                    Debug.LogError(\"Cannot create Window Action for: \" + method.info.Name);\n                }\n                return null;\n            }).OrderBy(a => a.priority).ToArray();\n        }\n\n        private static void FlushView(EditorWindow view)\n        {\n            if (view == null)\n                return;\n\n            int totalFrames = Math.Max(2, QualitySettings.maxQueuedFrames);\n            for (int i = 0; i < totalFrames; ++i)\n                view.RepaintImmediately();\n        }\n\n        public void PopupGenericMenu(EditorWindow view, Rect pos)\n        {\n            if (!showGenericMenu)\n                return;\n\n            FlushView(view);\n\n            GenericMenu menu = new GenericMenu();\n\n            IHasCustomMenu menuProvider = view as IHasCustomMenu;\n            if (menuProvider != null)\n                menuProvider.AddItemsToMenu(menu);\n\n            AddDefaultItemsToMenu(menu, view);\n\n            if (view != null)\n                AddWindowActionMenu(menu, view);\n\n            menu.DropDown(pos);\n            Event.current.Use();\n        }\n\n        internal static void AddWindowActionMenu(GenericMenu menu, EditorWindow view)\n        {\n            bool itemAdded = false;\n            int previousItemPriority = 0;\n            foreach (var item in windowActions)\n            {\n                if (item != null && (item.validateHandler == null || item.validateHandler(view, item)) && !string.IsNullOrEmpty(item.menuPath))\n                {\n                    if (!itemAdded)\n                    {\n                        menu.AddSeparator(\"\");\n                        itemAdded = true;\n                    }\n                    else if (item.priority >= previousItemPriority + 10)\n                        menu.AddSeparator(\"\");\n\n                    menu.AddItem(new GUIContent(item.menuPath, item.icon), false, () => item.executeHandler(view, item));\n                    previousItemPriority = item.priority;\n                }\n            }\n        }\n\n        private void Inspect(object userData)\n        {\n            Selection.activeObject = (Object)userData;\n        }\n\n        [UnityEngine.Bindings.VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal void Reload(object userData)\n        {\n            EditorWindow window = userData as EditorWindow;\n            if (window == null)\n                return;\n\n            var saveWindowPath = $\"Temp/{Guid.NewGuid().ToString(\"N\")}\";\n            InternalEditorUtility.SaveToSerializedFileAndForget(new[] { window }, saveWindowPath, true);\n\n            DockArea dockArea = window.m_Parent as DockArea;\n            if (dockArea != null)\n            {\n                int windowIndex = dockArea.m_Panes.IndexOf(window);\n\n                // Destroy window.\n                dockArea.RemoveTab(window, false); // Don't kill dock if empty.\n                DestroyImmediate(window, true);\n\n                // Reload window.\n                var objs = InternalEditorUtility.LoadSerializedFileAndForget(saveWindowPath);\n                if (objs[0] is EditorWindow win)\n                    dockArea.AddTab(windowIndex, win);\n            }\n            else\n            {\n                // Close the existing window.\n                window.Close();\n\n                // Reload window\n                var objs = InternalEditorUtility.LoadSerializedFileAndForget(saveWindowPath);\n                if (objs[0] is EditorWindow win)\n                    win.Show();\n            }\n\n            File.Delete(saveWindowPath);\n        }\n\n\n        protected virtual void AddDefaultItemsToMenu(GenericMenu menu, EditorWindow window)\n        {\n            if (menu.GetItemCount() != 0)\n                menu.AddSeparator(\"\");\n\n            populateDefaultMenuItems?.Invoke(menu, window);\n\n            if (window && Unsupported.IsDeveloperMode())\n            {\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Inspect Window\"), false, Inspect, window);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Inspect View\"), false, Inspect, window.m_Parent);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Reload Window _f5\"), false, Reload, window);\n\n                menu.AddSeparator(\"\");\n            }\n        }\n\n        Color IEditorWindowModel.playModeTintColor => kPlayModeDarken.Color;\n\n        private void PlayModeTintColorChangedCallback(string key)\n        {\n            if (key == kPlayModeDarkenKey)\n            {\n                editorWindowBackend?.PlayModeTintColorChanged();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/HyperLinkClickedEventArgs.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    public class HyperLinkClickedEventArgs\n    {\n        public Dictionary<string, string> hyperLinkData { get; private set; }\n\n        internal HyperLinkClickedEventArgs(Dictionary<string, string> hyperLinkData)\n        {\n            this.hyperLinkData = hyperLinkData;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/IAudioPlatformProperties.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor;\n\ninternal interface IAudioPlatformProperties : IPlatformProperties\n{\n    // The AudioImporterInspector.OnSampleSettingGUI method uses this property to determine whether or not to display UI\n    // to set sample rates.  This property is true for all build targets except WebGL.\n    bool HasSampleRateSettings => true;\n}\n"
  },
  {
    "path": "Editor/Mono/IBuildPlatformProperties.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor;\n\ninternal interface IBuildPlatformProperties : IPlatformProperties\n{\n    // The BuildPlayerWindow.ActiveBuildTargetsGUI method uses this property to determine whether or not to display certain\n    // build options based on whether or not the desired build target is compatible with the OS on which the editor is running.\n    bool CanBuildOnCurrentHostPlatform => true;\n\n    // The BuildEventsHandlerPostProcess.OnPostprocessBuild method uses this method to report permissions for a build target.\n    // This method replaces the BuildEventsHandlerPostProcess.ReportBuildTargetPermissions private method.\n    public void ReportBuildTargetPermissions(BuildOptions buildOptions) {}\n\n    // The BuildPlayerWindow.BuildPlayerAndRun method uses this method to set the build location for those build targets\n    // that require special handling.  Only the stand-alone Windows build targets implement this method.\n    public string ValidateBuildLocation() => null;\n\n    // The BuildProfileWindow uses this property to determine if required packages should be installed\n    // when activating the classic platform for a given build target.\n    public bool ShouldInstallRequiredPackagesOnActivationOfClassicPlatform => false;\n\n    // Determines whether to apply/respect the Android.UserBuildSettings.linkTimeOptimization value in the build pipeline.\n    public bool SupportLinkTimeOptimization => false;\n}\n"
  },
  {
    "path": "Editor/Mono/IBuildTarget.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal interface IBuildTarget\n    {\n        // The DesktopPluginImporterExtension.OnPlatformSettingsGUI method and the PlayerSettingsEditor.GraphicsAPIsGUI method\n        // use this property to determine what name to display for a build target.  This is often the same as the TargetName\n        // property but is different for several targets, such as \"Embedded Linux\" instead of \"EmbeddedLinux\".\n        string DisplayName { get; }\n\n        // The BuildTargetConverter.TryConvertToRuntimePlatform method uses this property to convert a build target into a\n        // runtime platform.  This method is used only for testing.\n        RuntimePlatform RuntimePlatform { get; }\n\n        // This property contains the canonical name of the build target.  Many methods throughout the editor code base make\n        // use of this property.\n        string TargetName { get; }\n\n        // This property is the unique identifier for the BuildTarget. This should be used for any access identification and serilization.\n        GUID Guid { get; }\n\n        // This property is used as a suffix for il2cpp profiles. Should a more suited place for it exist, move it\n        string RootSystemType { get; }\n\n        // This function allows to retrieve BuildPlatformProperties derived from IPlatformProperties as quick access\n        IBuildPlatformProperties BuildPlatformProperties { get; }\n\n        // This function allows to retrieve GraphicsPlatformProperties derived from IPlatformProperties as quick access\n        IGraphicsPlatformProperties GraphicsPlatformProperties { get; }\n\n        // This function allows to retrieve PlayerConnectionPlatformProperties derived from IPlatformProperties as quick access\n        IPlayerConnectionPlatformProperties PlayerConnectionPlatformProperties { get; }\n\n        // This function allows to retrieve IconPlatformProperties derived from IPlatformProperties as quick access\n        IIconPlatformProperties IconPlatformProperties { get; }\n\n        // This function allows to retrieve UIPlatformProperties derived from IPlatformProperties as quick access\n        IUIPlatformProperties UIPlatformProperties { get; }\n\n        // This function allows to retrieve AudioPlatformProperties derived from IPlatformProperties as quick access\n        IAudioPlatformProperties AudioPlatformProperties { get; }\n\n        // This function allows to retrieve AudioPlatformProperties derived from IPlatformProperties as quick access\n        IVRPlatformProperties VRPlatformProperties { get; }\n        // This function retrieves the texture subtarget derived from IPlatformProperties. It should be the same as\n        // the native subtarget used for each build target with a subtarget related to texture. Note this is different\n        // from a StandaloneSubtarget.\n        ISubtargetPlatformProperties TextureSubtargetPlatformProperties { get; }\n\n        // This function allows to retrieve properties of a give type, derived from IPlatformProperties\n        // if they are available.\n        bool TryGetProperties<T>(out T properties) where T: IPlatformProperties;\n\n        // This functions allows to access the old BuildTarget enum value for a build target when instantiated.\n        int GetLegacyId { get; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ICleanuppable.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor\n{\n    internal interface ICleanuppable\n    {\n        void Cleanup();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/IDerivedBuildTarget.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor\n{\n    using DiscoveredTargetInfo = BuildTargetDiscovery.DiscoveredTargetInfo;\n\n    internal interface IDerivedBuildTarget : IBuildTarget\n    {\n        GUID BaseGuid { get; }\n        DiscoveredTargetInfo GetDerivedBuildTargetInfo(DiscoveredTargetInfo baseBuildTargetInfo);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/IDerivedBuildTargetProvider.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor.Modules;\n\nnamespace UnityEditor\n{\n    using DiscoveredTargetInfo = BuildTargetDiscovery.DiscoveredTargetInfo;\n\n    internal interface IDerivedBuildTargetProvider\n    {\n        GUID GetBasePlatformGuid();\n        IEnumerable<IDerivedBuildTarget> GetDerivedBuildTargets();\n        IBuildProfileExtension CreateBuildProfileExtension(GUID buildTarget);\n        ISettingEditorExtension CreateSettingsEditorExtension(GUID buildTarget);\n        bool TryGetDiscoveredTargetInfo(GUID buildTarget, out DiscoveredTargetInfo discoveredTargetInfo);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/IDropArea.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditor\n{\n    // Interface for drag-dropping windows over each other.\n    // Must be implemented by anyone who can handle a dragged tab.\n    internal interface IDropArea\n    {\n        // Fill out a dropinfo class telling what should be done.\n        // NULL if no action\n        DropInfo DragOver(EditorWindow w, Vector2 screenPos);\n\n        // If the client returned a DropInfo from the DragOver, they will get this call when the user releases the mouse\n        bool PerformDrop(EditorWindow w, DropInfo dropInfo, Vector2 screenPos);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/IGraphicsPlatformProperties.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing GraphicsDeviceType = UnityEngine.Rendering.GraphicsDeviceType;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor;\n\ninternal interface IGraphicsPlatformProperties : IPlatformProperties\n{\n    // The QualitySettingsEditor.OnInspectorGUI method uses this property to determine whether or not to display a help\n    // box about ignoring the vertical sync count property.\n    bool IgnoresVSyncCount => false;\n\n    // The Modules.ModuleManager.ShouldShowMultiDisplayOption method uses this property to determine whether or not client\n    // code will show a multi-display option.  There are about half a dozen such clients in the editor code base.\n    bool HasMultiDisplayOption => false;\n\n    // The TextureImporterInspector uses this property to determine whether or not the default texture importer is using ETC. \n    bool IsETCUsedAsDefaultTextureImporter(TextureCompressionFormat defaultTexCompressionFormat) => defaultTexCompressionFormat == TextureCompressionFormat.ETC;\n\n    // The PlayerSettings uses this property to determine whether or not the graphics jobs are experimental\n    bool AreGraphicsJobsExperimental => false;\n\n    // The PlayerSettingsEditor.OtherSectionRenderingGUI method uses this property to determine whether or not to display unsupportedMSAAFallback\n    bool HasUnsupportedMSAAFallback => false;\n\n    // The PlayerSettingsEditor.OtherSectionRenderingGUI method uses this property to determine whether or not to display colorGamut\n    bool SupportsColorGamut => false;\n\n    // The PlayerSettings.ResolutionSectionGUI method uses this property to determine whether or not to display retina support\n    bool RetinaSupport => false;\n}\n"
  },
  {
    "path": "Editor/Mono/IHasCustomMenu.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\n\nnamespace UnityEditor\n{\n    public interface IHasCustomMenu\n    {\n        void AddItemsToMenu(GenericMenu menu);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/IIconPlatformProperties.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nnamespace UnityEditor;\n\ninternal enum IconSettings\n{\n    // The build target has no icon settings\n    None = 0,\n\n    // The build target uses the standard icon settings UI, common for all platforms\n    StandardIcons = 1 << 0,\n\n    // The build target handles the icon settings UI itself\n    CustomIcons = 1 << 1,\n}\n\ninternal interface IIconPlatformProperties : IPlatformProperties\n{\n    // The PlayerSettingsIconsEditor.IconSectionGUI method uses this property to determine what options to display in the UI.\n    IconSettings IconUISettings => IconSettings.StandardIcons;\n\n    IReadOnlyDictionary<PlatformIconKind, PlatformIcon[]> GetRequiredPlatformIcons() => null;\n    PlatformIconKind GetPlatformIconKindFromEnumValue(IconKind kind) => null;\n}\n"
  },
  {
    "path": "Editor/Mono/IInsightsPlatformProperties.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor;\n\n[VisibleToOtherModules]\ninternal interface IInsightsPlatformProperties : IPlatformProperties\n{\n}\n"
  },
  {
    "path": "Editor/Mono/IPlatformProperties.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor;\n\ninternal interface IPlatformProperties\n{\n    // empty\n}\n"
  },
  {
    "path": "Editor/Mono/IPlayerConnectionPlatformProperties.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor;\n\ninternal interface IPlayerConnectionPlatformProperties : IPlatformProperties\n{\n    // The BuildPipeline.DoesBuildTargetSupportPlayerConnectionPlayerToEditor method uses\n    // this property to determine if the player of a given build target supports connecting\n    // back to the editor\n    public bool SupportsConnect => false;\n\n    // The BuildPipeline.DoesBuildTargetSupportPlayerConnectionListening method uses this\n    // property to determine if the player of a given build target supports listening for a\n    // connection from the editor.\n    public bool SupportsListen => true;\n\n    // The BuildPlayerWindow.DefaultBuildMethods.GetBuildPlayerOptionsInternal method uses this property to determine\n    // whether or not to provide the \"connect with profiler\" option.\n    bool ForceAllowProfilerConnection => false;\n}\n"
  },
  {
    "path": "Editor/Mono/ISubtargetPlatformProperties.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.Build.Profile;\n\nnamespace UnityEditor;\n\ninternal interface ISubtargetPlatformProperties : IPlatformProperties\n{\n    int GetSubtargetFromPlatformSettings(BuildProfilePlatformSettingsBase platformSettings = null) => -1;\n}\n"
  },
  {
    "path": "Editor/Mono/IUIPlatformProperties.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor;\n\ninternal interface IUIPlatformProperties : IPlatformProperties\n{\n    // The GameViewSizes.BuildTargetGroupToGameViewSizeGroup method uses this property to set that class's GameViewSizeGroup\n    // static variable.\n    GameViewSizeGroupType GameViewSizeGroupType => GameViewSizeGroupType.Standalone;\n}\n"
  },
  {
    "path": "Editor/Mono/IVRPlatformProperties.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor;\n\ninternal interface IVRPlatformProperties : IPlatformProperties\n{\n    bool SupportSinglePassStereoRendering => false;\n    bool SupportStereoInstancingRendering => false;\n    bool SupportStereoMultiviewRendering  => false;\n    bool SupportStereo360Capture          => false;\n}\n"
  },
  {
    "path": "Editor/Mono/IconSelector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class IconSelector : EditorWindow\n    {\n        public delegate void MonoScriptIconChangedCallback(MonoScript monoScript);\n        class Styles\n        {\n            public GUIStyle background = \"sv_iconselector_back\";\n            public GUIStyle seperator = \"sv_iconselector_sep\";\n            public GUIStyle selection = \"sv_iconselector_selection\";\n            public GUIStyle selectionLabel = \"sv_iconselector_labelselection\";\n            public GUIStyle noneButton = \"sv_iconselector_button\";\n        }\n\n        static IconSelector s_IconSelector = null;\n        static long s_LastClosedTime = 0;\n        static int s_LastInstanceHash = -1;\n        static int s_HashIconSelector = \"IconSelector\".GetHashCode();\n        static Styles m_Styles;\n        static GUIContent s_Other = EditorGUIUtility.TrTextContent(\"Other...\");\n\n        Object m_TargetObject;\n        Object[] m_TargetObjectList;\n        bool m_MultipleSelectedIcons;\n        Texture2D m_StartIcon;\n        bool m_ShowLabelIcons;\n        private GUIContent[] m_LabelLargeIcons;\n        private GUIContent[] m_LabelIcons;\n        private GUIContent[] m_LargeIcons;\n        private GUIContent[] m_SmallIcons;\n        private GUIContent m_NoneButtonContent;\n        private MonoScriptIconChangedCallback m_MonoScriptIconChangedCallback;\n\n        private GUIContent[] GetTextures(string baseName, string postFix, int startIndex, int count)\n        {\n            GUIContent[] textures = new GUIContent[count];\n            for (int i = 0; i < count; ++i)\n                textures[i] = EditorGUIUtility.IconContent(baseName + (startIndex + i) + postFix);\n            return textures;\n        }\n\n        void OnEnable()\n        {\n            hideFlags = HideFlags.DontSave;\n        }\n\n        void OnDisable()\n        {\n            SaveIconChanges();\n\n            s_LastClosedTime = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond;\n            s_IconSelector = null;\n        }\n\n        void SaveIconChanges()\n        {\n            Texture2D currentIcon = EditorGUIUtility.GetIconForObject(m_TargetObject);\n\n            // Only save if we had any changes\n            if (currentIcon != m_StartIcon)\n            {\n                MonoScript monoScript = m_TargetObject as MonoScript;\n                if (monoScript != null)\n                {\n                    // If callback is set then it is the callback owner's responsiblity to copy the script icon to the importer\n                    if (m_MonoScriptIconChangedCallback != null)\n                        m_MonoScriptIconChangedCallback(monoScript);\n                    else\n                        CopyIconToImporter(monoScript);\n                }\n            }\n        }\n\n        // Returns true if shown\n        internal static bool ShowAtPosition(Object targetObj, Rect activatorRect, bool showLabelIcons)\n        {\n            return ShowAtPosition(new Object[] { targetObj }, activatorRect, showLabelIcons);\n        }\n\n        // Returns true if shown\n        internal static bool ShowAtPosition(Object[] targetObjects, Rect activatorRect, bool showLabelIcons)\n        {\n            int instanceHash = targetObjects.GetHashCode();\n            // We could not use realtimeSinceStartUp since it is resetted when entering playmode, we assume an increasing time when comparing time.\n            long nowMilliSeconds = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond;\n            bool justClosed = nowMilliSeconds < s_LastClosedTime + 50;\n            if (instanceHash != s_LastInstanceHash || !justClosed)\n            {\n                Event.current.Use();\n                s_LastInstanceHash = instanceHash;\n                if (s_IconSelector == null)\n                    s_IconSelector = ScriptableObject.CreateInstance<IconSelector>();\n                s_IconSelector.Init(targetObjects, activatorRect, showLabelIcons);\n                return true;\n            }\n\n            return false;\n        }\n\n        internal static void SetMonoScriptIconChangedCallback(MonoScriptIconChangedCallback callback)\n        {\n            if (s_IconSelector != null)\n                s_IconSelector.m_MonoScriptIconChangedCallback = callback;\n            else\n                Debug.Log(\"ERROR: setting callback on hidden IconSelector\");\n        }\n\n        internal static void CopyIconToImporter(MonoScript monoScript)\n        {\n            // update the icon on the importer (requires a reimport)\n            var icon = EditorGUIUtility.GetIconForObject(monoScript);\n            var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(monoScript));\n            var monoImporter = importer as MonoImporter;\n            var pluginImporter = importer as PluginImporter;\n            if (monoImporter)\n            {\n                monoImporter.SetIcon(icon);\n                monoImporter.SaveAndReimport();\n            }\n            else if (pluginImporter)\n            {\n                pluginImporter.SetIcon(monoScript.GetClass().FullName, icon);\n                pluginImporter.SaveAndReimport();\n            }\n        }\n\n        void Init(Object[] targetObjects, Rect activatorRect, bool showLabelIcons)\n        {\n            m_TargetObject = targetObjects[0];\n            m_TargetObjectList = targetObjects;\n            m_StartIcon = EditorGUIUtility.GetIconForObject(m_TargetObject);\n            m_ShowLabelIcons = showLabelIcons;\n            Rect screenActivatorRect = GUIUtility.GUIToScreenRect(activatorRect);\n\n            SetMultipleSelectedIcons();\n\n            // Remove any keyboard control when opening this window\n            GUIUtility.keyboardControl = 0;\n\n            // Init GUIContents\n            m_LabelLargeIcons = GetTextures(\"sv_label_\", \"\", 0, 8);\n            m_LabelIcons = GetTextures(\"sv_icon_name\", \"\", 0, 8);\n            m_SmallIcons = GetTextures(\"sv_icon_dot\", \"_sml\", 0, 16);\n            m_LargeIcons = GetTextures(\"sv_icon_dot\", \"_pix16_gizmo\", 0, 16);\n            m_NoneButtonContent = EditorGUIUtility.IconContent(\"sv_icon_none\");\n            m_NoneButtonContent.text = \"None\";\n\n            // Deal with window size\n            float k_Width = 140;\n            float k_Height = 86;\n            if (m_ShowLabelIcons)\n                k_Height = 126;\n\n            ShowAsDropDown(screenActivatorRect, new Vector2(k_Width, k_Height));\n        }\n\n        void SetMultipleSelectedIcons()\n        {\n            m_MultipleSelectedIcons = false;\n            Texture2D firstIcon = EditorGUIUtility.GetIconForObject(m_TargetObjectList[0]);\n\n            foreach (var target in m_TargetObjectList)\n            {\n                Texture2D icon = EditorGUIUtility.GetIconForObject(target);\n                if (icon != firstIcon)\n                {\n                    m_MultipleSelectedIcons = true;\n                    break;\n                }\n            }\n        }\n\n        private Texture2D ConvertLargeIconToSmallIcon(Texture2D largeIcon, ref bool isLabelIcon)\n        {\n            if (largeIcon == null)\n                return null;\n\n            isLabelIcon = true;\n            for (int i = 0; i < m_LabelLargeIcons.Length; ++i)\n                if (m_LabelLargeIcons[i].image == largeIcon)\n                    return (Texture2D)m_LabelIcons[i].image;\n\n            isLabelIcon = false;\n            for (int i = 0; i < m_LargeIcons.Length; ++i)\n                if (m_LargeIcons[i].image == largeIcon)\n                    return (Texture2D)m_SmallIcons[i].image;\n\n            return largeIcon;\n        }\n\n        private Texture2D ConvertSmallIconToLargeIcon(Texture2D smallIcon, bool labelIcon)\n        {\n            if (labelIcon)\n            {\n                for (int i = 0; i < m_LabelIcons.Length; ++i)\n                    if (m_LabelIcons[i].image == smallIcon)\n                        return (Texture2D)m_LabelLargeIcons[i].image;\n            }\n            else\n            {\n                for (int i = 0; i < m_SmallIcons.Length; ++i)\n                    if (m_SmallIcons[i].image == smallIcon)\n                        return (Texture2D)m_LargeIcons[i].image;\n            }\n            return smallIcon;\n        }\n\n        void DoButton(GUIContent content, Texture2D selectedIcon, bool labelIcon)\n        {\n            int controlID = GUIUtility.GetControlID(s_HashIconSelector, FocusType.Keyboard);\n\n            // Draw selection background if this is the selected icon\n            if (content.image == selectedIcon)\n            {\n                // When placing our selection background we assume that icons rendered from top left corner\n                Rect rect = GUILayoutUtility.topLevel.PeekNext();\n                float pad = 2;\n                rect.x -= pad;\n                rect.y -= pad;\n                rect.width = selectedIcon.width + 2 * pad;\n                rect.height = selectedIcon.height + 2 * pad;\n                GUI.Label(rect, GUIContent.none, labelIcon ? m_Styles.selectionLabel : m_Styles.selection);\n            }\n\n            // Do icon\n            if (EditorGUILayout.IconButton(controlID, content, GUIStyle.none))\n            {\n                // Map to new icon\n                Texture2D largeIcon = ConvertSmallIconToLargeIcon((Texture2D)content.image, labelIcon);\n                SetIconForSelectedObjects(largeIcon);\n\n                // Close on double click\n                if (Event.current.clickCount == 2)\n                    CloseWindow();\n            }\n        }\n\n        void SetIconForSelectedObjects(Texture2D icon)\n        {\n            Undo.RecordObjects(m_TargetObjectList, \"Set Icon On GameObject\");\n\n            foreach (var target in m_TargetObjectList)\n            {\n                EditorGUIUtility.SetIconForObject(target, icon);\n            }\n            SetMultipleSelectedIcons();\n            EditorUtility.ForceReloadInspectors();\n            AnnotationWindow.IconChanged();\n        }\n\n        void DoTopSection(bool anySelected)\n        {\n            Rect selectIconRect = new Rect(6, 4, 110, 20);\n            GUI.Label(selectIconRect, \"Select Icon\");\n\n            // Draw selection background if none is selected\n            using (new EditorGUI.DisabledScope(!anySelected))\n            {\n                Rect noneButtonRect = new Rect(93, 6, 43, 12);\n                if (GUI.Button(noneButtonRect, m_NoneButtonContent, m_Styles.noneButton))\n                    SetIconForSelectedObjects(null);\n            }\n        }\n\n        private void CloseWindow()\n        {\n            Close();\n            GUI.changed = true;\n            GUIUtility.ExitGUI();\n        }\n\n        internal void OnGUI()\n        {\n            // Here due to static vars being thrown out when reloading assemblies\n            if (m_Styles == null)\n                m_Styles = new Styles();\n\n            // Escape pressed?\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)\n            {\n                CloseWindow();\n            }\n\n            Texture2D selectedIcon = m_MultipleSelectedIcons ? null : EditorGUIUtility.GetIconForObject(m_TargetObject);\n            bool isSelectionALabelIcon = false;\n            if (Event.current.type == EventType.Repaint)\n            {\n                selectedIcon = ConvertLargeIconToSmallIcon(selectedIcon, ref isSelectionALabelIcon);\n            }\n\n            Event evt = Event.current;\n            EventType eventType = evt.type;\n\n            GUI.BeginGroup(new Rect(0, 0, position.width, position.height), m_Styles.background);\n\n            DoTopSection(selectedIcon != null || m_MultipleSelectedIcons);\n\n            GUILayout.Space(22);\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(1);\n            GUI.enabled = false;\n            GUILayout.Label(\"\", m_Styles.seperator);\n            GUI.enabled = true;\n            GUILayout.Space(1);\n            GUILayout.EndHorizontal();\n            GUILayout.Space(3);\n\n            if (m_ShowLabelIcons)\n            {\n                // Label icons\n                GUILayout.BeginHorizontal();\n                GUILayout.Space(6);\n                for (int i = 0; i < m_LabelIcons.Length / 2; ++i)\n                    DoButton(m_LabelIcons[i], selectedIcon, true);\n                GUILayout.EndHorizontal();\n\n                GUILayout.Space(5);\n\n                GUILayout.BeginHorizontal();\n                GUILayout.Space(6);\n                for (int i = m_LabelIcons.Length / 2; i < m_LabelIcons.Length; ++i)\n                    DoButton(m_LabelIcons[i], selectedIcon, true);\n                GUILayout.EndHorizontal();\n\n                GUILayout.Space(3);\n                GUILayout.BeginHorizontal();\n                GUILayout.Space(1);\n                GUI.enabled = false;\n                GUILayout.Label(\"\", m_Styles.seperator);\n                GUI.enabled = true;\n                GUILayout.Space(1);\n                GUILayout.EndHorizontal();\n                GUILayout.Space(3);\n            }\n\n            // Small icons\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(9);\n            for (int i = 0; i < m_SmallIcons.Length / 2; ++i)\n                DoButton(m_SmallIcons[i], selectedIcon, false);\n            GUILayout.Space(3);\n            GUILayout.EndHorizontal();\n\n            GUILayout.Space(6);\n\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(9);\n            for (int i = m_SmallIcons.Length / 2; i < m_SmallIcons.Length; ++i)\n                DoButton(m_SmallIcons[i], selectedIcon, false);\n            GUILayout.Space(3);\n            GUILayout.EndHorizontal();\n            GUILayout.Space(6);\n\n            // Object selector section\n            GUI.backgroundColor = new Color(1, 1, 1, 0.7f);\n            bool clicked = false;\n            int id = GUIUtility.GetControlID(s_HashIconSelector, FocusType.Keyboard);\n            if (GUILayout.Button(s_Other))\n            {\n                GUIUtility.keyboardControl = id;\n                clicked = true;\n            }\n            GUI.backgroundColor = new Color(1, 1, 1, 1);\n            GUI.EndGroup();\n\n            if (clicked)\n            {\n                ObjectSelector.get.Show(m_TargetObject, typeof(Texture2D), null, false);\n                ObjectSelector.get.objectSelectorID = id;\n                GUI.backgroundColor = new Color(1, 1, 1, 0.7f);\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n\n            // Check for icon selected from ObjectSelector\n            switch (eventType)\n            {\n                case EventType.ExecuteCommand:\n                    string commandName = evt.commandName;\n                    if (commandName == ObjectSelector.ObjectSelectorUpdatedCommand && ObjectSelector.get.objectSelectorID == id && GUIUtility.keyboardControl == id)\n                    {\n                        Texture2D icon =  ObjectSelector.GetCurrentObject() as Texture2D;\n                        SetIconForSelectedObjects(icon);\n\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.ValidateCommand:\n                    if (evt.commandName == EventCommandNames.UndoRedoPerformed)\n                    {\n                        CloseWindow();\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                    break;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ImportSettings/AnimationClipInfoProperties.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class AnimationClipInfoProperties\n    {\n        SerializedProperty m_Property;\n\n        public AnimationClipInfoProperties(SerializedProperty prop)\n        {\n            m_Property = prop;\n            Editor.AssignCachedProperties(this, prop);\n        }\n\n#pragma warning disable 0649\n        [CacheProperty(\"name\")]\n        SerializedProperty m_Name;\n        [CacheProperty(\"takeName\")]\n        SerializedProperty m_TakeName;\n        [CacheProperty(\"internalID\")]\n        SerializedProperty m_InternalId;\n        [CacheProperty(\"firstFrame\")]\n        SerializedProperty m_FirstFrame;\n        [CacheProperty(\"lastFrame\")]\n        SerializedProperty m_LastFrame;\n        [CacheProperty(\"wrapMode\")]\n        SerializedProperty m_WrapMode;\n        [CacheProperty(\"loop\")]\n        SerializedProperty m_Loop;\n        [CacheProperty(\"orientationOffsetY\")]\n        SerializedProperty m_OrientationOffsetY;\n        [CacheProperty(\"level\")]\n        SerializedProperty m_Level;\n        [CacheProperty(\"cycleOffset\")]\n        SerializedProperty m_CycleOffset;\n        [CacheProperty(\"additiveReferencePoseFrame\")]\n        SerializedProperty m_AdditiveReferencePoseFrame;\n        [CacheProperty(\"hasAdditiveReferencePose\")]\n        SerializedProperty m_HasAdditiveReferencePose;\n        [CacheProperty(\"loopTime\")]\n        SerializedProperty m_LoopTime;\n        [CacheProperty(\"loopBlend\")]\n        SerializedProperty m_LoopBlend;\n        [CacheProperty(\"loopBlendOrientation\")]\n        SerializedProperty m_LoopBlendOrientation;\n        [CacheProperty(\"loopBlendPositionY\")]\n        SerializedProperty m_LoopBlendPositionY;\n        [CacheProperty(\"loopBlendPositionXZ\")]\n        SerializedProperty m_LoopBlendPositionXZ;\n        [CacheProperty(\"keepOriginalOrientation\")]\n        SerializedProperty m_KeepOriginalOrientation;\n        [CacheProperty(\"keepOriginalPositionY\")]\n        SerializedProperty m_KeepOriginalPositionY;\n        [CacheProperty(\"keepOriginalPositionXZ\")]\n        SerializedProperty m_KeepOriginalPositionXZ;\n        [CacheProperty(\"heightFromFeet\")]\n        SerializedProperty m_HeightFromFeet;\n        [CacheProperty(\"mirror\")]\n        SerializedProperty m_Mirror;\n        [CacheProperty(\"maskType\")]\n        SerializedProperty m_MaskType;\n        [CacheProperty(\"maskSource\")]\n        SerializedProperty m_MaskSource;\n        [CacheProperty(\"bodyMask\")]\n        SerializedProperty m_BodyMask;\n        [CacheProperty(\"transformMask\")]\n        SerializedProperty m_TransformMask;\n        [CacheProperty(\"curves\")]\n        SerializedProperty m_Curves;\n        [CacheProperty(\"events\")]\n        SerializedProperty m_Events;\n#pragma warning restore 0649\n\n        public string name      { get { return m_Name.stringValue;      } set { m_Name.stringValue = value;      } }\n        public string takeName  { get { return m_TakeName.stringValue;  } set { m_TakeName.stringValue = value;  } }\n        public long internalID  { get { return m_InternalId.longValue;  } set { m_InternalId.longValue = value;  } }\n        public float firstFrame { get { return m_FirstFrame.floatValue; } set { m_FirstFrame.floatValue = value; } }\n        public float lastFrame  { get { return m_LastFrame.floatValue;  } set { m_LastFrame.floatValue = value;  } }\n        public int wrapMode     { get { return m_WrapMode.intValue;     } set { m_WrapMode.intValue = value;     } }\n        public bool loop        { get { return m_Loop.boolValue;        } set { m_Loop.boolValue = value;        } }\n\n        // Mecanim animation properties\n        public float orientationOffsetY         { get { return m_OrientationOffsetY.floatValue;         } set { m_OrientationOffsetY.floatValue = value;         } }\n        public float level                      { get { return m_Level.floatValue;                      } set { m_Level.floatValue = value;                      } }\n        public float cycleOffset                { get { return m_CycleOffset.floatValue;                } set { m_CycleOffset.floatValue = value;                } }\n        public float additiveReferencePoseFrame { get { return m_AdditiveReferencePoseFrame.floatValue; } set { m_AdditiveReferencePoseFrame.floatValue = value; } }\n        public bool  hasAdditiveReferencePose   { get { return m_HasAdditiveReferencePose.boolValue;    } set { m_HasAdditiveReferencePose.boolValue = value;    } }\n        public bool  loopTime                   { get { return m_LoopTime.boolValue;                    } set { m_LoopTime.boolValue = value;                    } }\n        public bool  loopBlend                  { get { return m_LoopBlend.boolValue;                   } set { m_LoopBlend.boolValue = value;                   } }\n        public bool  loopBlendOrientation       { get { return m_LoopBlendOrientation.boolValue;        } set { m_LoopBlendOrientation.boolValue = value;        } }\n        public bool  loopBlendPositionY         { get { return m_LoopBlendPositionY.boolValue;          } set { m_LoopBlendPositionY.boolValue = value;          } }\n        public bool  loopBlendPositionXZ        { get { return m_LoopBlendPositionXZ.boolValue;         } set { m_LoopBlendPositionXZ.boolValue = value;         } }\n        public bool  keepOriginalOrientation    { get { return m_KeepOriginalOrientation.boolValue;     } set { m_KeepOriginalOrientation.boolValue = value;     } }\n        public bool  keepOriginalPositionY      { get { return m_KeepOriginalPositionY.boolValue;       } set { m_KeepOriginalPositionY.boolValue = value;       } }\n        public bool  keepOriginalPositionXZ     { get { return m_KeepOriginalPositionXZ.boolValue;      } set { m_KeepOriginalPositionXZ.boolValue = value;      } }\n        public bool  heightFromFeet             { get { return m_HeightFromFeet.boolValue;              } set { m_HeightFromFeet.boolValue = value;              } }\n        public bool  mirror                     { get { return m_Mirror.boolValue;                      } set { m_Mirror.boolValue = value;                      } }\n        public ClipAnimationMaskType maskType   { get { return (ClipAnimationMaskType)m_MaskType.intValue;    } set { m_MaskType.intValue = (int)value;          } }\n        public AvatarMask maskSource            { get { return (AvatarMask)m_MaskSource.objectReferenceValue; } set { m_MaskSource.objectReferenceValue = value; } }\n\n        public SerializedProperty maskTypeProperty      => m_MaskType;\n        public SerializedProperty maskSourceProperty    => m_MaskSource;\n        public SerializedProperty bodyMaskProperty      => m_BodyMask;\n        public SerializedProperty transformMaskProperty => m_TransformMask;\n\n        public void ApplyModifiedProperties()\n        {\n            m_Property.serializedObject.ApplyModifiedProperties();\n        }\n\n        public bool MaskNeedsUpdating()\n        {\n            AvatarMask mask = maskSource;\n            if (mask == null)\n                return false;\n\n            using (SerializedObject source = new SerializedObject(mask))\n            {\n                if (!SerializedProperty.DataEquals(bodyMaskProperty, source.FindProperty(\"m_Mask\")))\n                    return true;\n\n                if (!SerializedProperty.DataEquals(transformMaskProperty, source.FindProperty(\"m_Elements\")))\n                    return true;\n            }\n\n            return false;\n        }\n\n        public void MaskFromClip(AvatarMask mask)\n        {\n            SerializedProperty bodyMask = bodyMaskProperty;\n\n            if (bodyMask != null && bodyMask.isArray)\n            {\n                for (AvatarMaskBodyPart i = 0; i < AvatarMaskBodyPart.LastBodyPart; i++)\n                {\n                    mask.SetHumanoidBodyPartActive(i, bodyMask.GetArrayElementAtIndex((int)i).intValue != 0);\n                }\n            }\n\n            var transformMask = transformMaskProperty;\n\n            if (transformMask != null && transformMask.isArray)\n            {\n                if (transformMask.arraySize > 0 && (mask.transformCount != transformMask.arraySize))\n                    mask.transformCount = transformMask.arraySize;\n\n                int size = transformMask.arraySize;\n                if (size == 0)\n                    return;\n\n                SerializedProperty prop = transformMask.GetArrayElementAtIndex(0);\n\n                for (int i = 0; i < size; i++)\n                {\n                    SerializedProperty pathProperty = prop.FindPropertyRelative(\"m_Path\");\n                    SerializedProperty weightProperty = prop.FindPropertyRelative(\"m_Weight\");\n                    mask.SetTransformPath(i, pathProperty.stringValue);\n                    mask.SetTransformActive(i, weightProperty.floatValue > 0.5);\n                    prop.Next(false);\n                }\n            }\n        }\n\n        public void MaskToClip(AvatarMask mask)\n        {\n            SerializedProperty bodyMask = bodyMaskProperty;\n\n            if (bodyMask != null && bodyMask.isArray)\n            {\n                for (AvatarMaskBodyPart i = 0; i < AvatarMaskBodyPart.LastBodyPart; i++)\n                {\n                    if ((int)i >= bodyMask.arraySize) bodyMask.InsertArrayElementAtIndex((int)i);\n                    bodyMask.GetArrayElementAtIndex((int)i).intValue = mask.GetHumanoidBodyPartActive(i) ? 1 : 0;\n                }\n            }\n\n            SerializedProperty transformMask = transformMaskProperty;\n            ModelImporter.UpdateTransformMask(mask, transformMask);\n        }\n\n        public void ClearCurves()\n        {\n            SerializedProperty curves = m_Curves;\n\n            if (curves != null && curves.isArray)\n            {\n                curves.ClearArray();\n            }\n        }\n\n        public int GetCurveCount()\n        {\n            int ret = 0;\n\n            SerializedProperty curves = m_Curves;\n\n            if (curves != null && curves.isArray)\n            {\n                ret = curves.arraySize;\n            }\n\n            return ret;\n        }\n\n        public SerializedProperty GetCurveProperty(int index)\n        {\n            SerializedProperty ret = null;\n\n            SerializedProperty curves = m_Curves;\n\n            if (curves != null && curves.isArray)\n            {\n                ret = curves.GetArrayElementAtIndex(index).FindPropertyRelative(\"curve\");\n            }\n\n            return ret;\n        }\n\n        public string GetCurveName(int index)\n        {\n            string ret = \"\";\n\n            SerializedProperty curves = m_Curves;\n\n            if (curves != null && curves.isArray)\n            {\n                ret = curves.GetArrayElementAtIndex(index).FindPropertyRelative(\"name\").stringValue;\n            }\n\n            return ret;\n        }\n\n        public void SetCurveName(int index, string name)\n        {\n            SerializedProperty curves = m_Curves;\n\n            if (curves != null && curves.isArray)\n            {\n                curves.GetArrayElementAtIndex(index).FindPropertyRelative(\"name\").stringValue = name;\n            }\n        }\n\n        public AnimationCurve GetCurve(int index)\n        {\n            AnimationCurve ret = null;\n\n            SerializedProperty curve = GetCurveProperty(index);\n\n            if (curve != null)\n            {\n                ret = curve.animationCurveValue;\n            }\n\n            return ret;\n        }\n\n        public void SetCurve(int index, AnimationCurve curveValue)\n        {\n            SerializedProperty curve = GetCurveProperty(index);\n\n            if (curve != null)\n            {\n                curve.animationCurveValue = curveValue;\n            }\n        }\n\n        public void AddCurve()\n        {\n            SerializedProperty curves = m_Curves;\n\n            if (curves != null && curves.isArray)\n            {\n                curves.InsertArrayElementAtIndex(curves.arraySize);\n                curves.GetArrayElementAtIndex(curves.arraySize - 1).FindPropertyRelative(\"name\").stringValue = \"Curve\";\n                AnimationCurve newCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(1, 0));\n                newCurve.preWrapMode = WrapMode.Default;\n                newCurve.postWrapMode = WrapMode.Default;\n                curves.GetArrayElementAtIndex(curves.arraySize - 1).FindPropertyRelative(\"curve\").animationCurveValue = newCurve;\n            }\n        }\n\n        public void RemoveCurve(int index)\n        {\n            SerializedProperty curves = m_Curves;\n\n            if (curves != null && curves.isArray)\n            {\n                curves.DeleteArrayElementAtIndex(index);\n            }\n        }\n\n        public AnimationEvent GetEvent(int index)\n        {\n            AnimationEvent evt = new AnimationEvent();\n            SerializedProperty events = m_Events;\n\n            if (events != null && events.isArray)\n            {\n                if (index < events.arraySize)\n                {\n                    evt.floatParameter = events.GetArrayElementAtIndex(index).FindPropertyRelative(\"floatParameter\").floatValue;\n                    evt.functionName = events.GetArrayElementAtIndex(index).FindPropertyRelative(\"functionName\").stringValue;\n                    evt.intParameter = events.GetArrayElementAtIndex(index).FindPropertyRelative(\"intParameter\").intValue;\n                    evt.objectReferenceParameter = events.GetArrayElementAtIndex(index).FindPropertyRelative(\"objectReferenceParameter\").objectReferenceValue;\n                    evt.stringParameter = events.GetArrayElementAtIndex(index).FindPropertyRelative(\"data\").stringValue;\n                    evt.time = events.GetArrayElementAtIndex(index).FindPropertyRelative(\"time\").floatValue;\n                }\n                else\n                {\n                    Debug.LogWarning(\"Invalid Event Index\");\n                }\n            }\n\n            return evt;\n        }\n\n        public void SetEvent(int index, AnimationEvent animationEvent)\n        {\n            SerializedProperty events = m_Events;\n\n            if (events != null && events.isArray)\n            {\n                if (index < events.arraySize)\n                {\n                    events.GetArrayElementAtIndex(index).FindPropertyRelative(\"floatParameter\").floatValue = animationEvent.floatParameter;\n                    events.GetArrayElementAtIndex(index).FindPropertyRelative(\"functionName\").stringValue = animationEvent.functionName;\n                    events.GetArrayElementAtIndex(index).FindPropertyRelative(\"intParameter\").intValue = animationEvent.intParameter;\n                    events.GetArrayElementAtIndex(index).FindPropertyRelative(\"objectReferenceParameter\").objectReferenceValue = animationEvent.objectReferenceParameter;\n                    events.GetArrayElementAtIndex(index).FindPropertyRelative(\"data\").stringValue = animationEvent.stringParameter;\n                    events.GetArrayElementAtIndex(index).FindPropertyRelative(\"time\").floatValue = animationEvent.time;\n                }\n                else\n                {\n                    Debug.LogWarning(\"Invalid Event Index\");\n                }\n            }\n        }\n\n        public void ClearEvents()\n        {\n            SerializedProperty events = m_Events;\n\n            if (events != null && events.isArray)\n            {\n                events.ClearArray();\n            }\n        }\n\n        public int GetEventCount()\n        {\n            int ret = 0;\n\n            SerializedProperty curves = m_Events;\n\n            if (curves != null && curves.isArray)\n            {\n                ret = curves.arraySize;\n            }\n\n            return ret;\n        }\n\n        public void AddEvent(float time)\n        {\n            SerializedProperty events = m_Events;\n\n            if (events != null && events.isArray)\n            {\n                events.InsertArrayElementAtIndex(events.arraySize);\n                events.GetArrayElementAtIndex(events.arraySize - 1).FindPropertyRelative(\"functionName\").stringValue = \"NewEvent\";\n                events.GetArrayElementAtIndex(events.arraySize - 1).FindPropertyRelative(\"time\").floatValue = time;\n            }\n        }\n\n        public void RemoveEvent(int index)\n        {\n            SerializedProperty events = m_Events;\n\n            if (events != null && events.isArray)\n            {\n                events.DeleteArrayElementAtIndex(index);\n            }\n        }\n\n        public void SetEvents(AnimationEvent[] newEvents)\n        {\n            SerializedProperty events = m_Events;\n\n            if (events != null && events.isArray)\n            {\n                events.ClearArray();\n\n                foreach (AnimationEvent evt in newEvents)\n                {\n                    events.InsertArrayElementAtIndex(events.arraySize);\n                    SetEvent(events.arraySize - 1, evt);\n                }\n            }\n        }\n\n        public AnimationEvent[] GetEvents()\n        {\n            AnimationEvent[]  ret  = new AnimationEvent[GetEventCount()];\n            SerializedProperty events = m_Events;\n\n            if (events != null && events.isArray)\n            {\n                for (int i = 0; i < GetEventCount(); ++i)\n                {\n                    ret[i] = GetEvent(i);\n                }\n            }\n\n            return ret;\n        }\n\n        public void AssignToPreviewClip(AnimationClip clip)\n        {\n            AnimationClipSettings info = new AnimationClipSettings();\n\n            info.startTime = firstFrame / clip.frameRate;\n            info.stopTime = lastFrame / clip.frameRate;\n            info.orientationOffsetY = orientationOffsetY;\n            info.level = level;\n            info.cycleOffset = cycleOffset;\n            info.loopTime = loopTime;\n            info.loopBlend = loopBlend;\n            info.loopBlendOrientation = loopBlendOrientation;\n            info.loopBlendPositionY = loopBlendPositionY;\n            info.loopBlendPositionXZ = loopBlendPositionXZ;\n            info.keepOriginalOrientation = keepOriginalOrientation;\n            info.keepOriginalPositionY = keepOriginalPositionY;\n            info.keepOriginalPositionXZ = keepOriginalPositionXZ;\n            info.heightFromFeet = heightFromFeet;\n            info.mirror = mirror;\n            info.hasAdditiveReferencePose = hasAdditiveReferencePose;\n            info.additiveReferencePoseTime = additiveReferencePoseFrame / clip.frameRate;\n\n            AnimationUtility.SetAnimationClipSettingsNoDirty(clip, info);\n        }\n\n        private float FixPrecisionErrors(float f)\n        {\n            float rounded = Mathf.Round(f);\n            if (Mathf.Abs(f - rounded) < 0.0001f)\n                return rounded;\n            return f;\n        }\n\n        public void ExtractFromPreviewClip(AnimationClip clip)\n        {\n            AnimationClipSettings info = AnimationUtility.GetAnimationClipSettings(clip);\n\n            // Ensure that we don't accidentally dirty settings due to floating point precision in the multiply / divide\n            if (firstFrame / clip.frameRate != info.startTime)\n                firstFrame = FixPrecisionErrors(info.startTime * clip.frameRate);\n            if (lastFrame / clip.frameRate != info.stopTime)\n                lastFrame = FixPrecisionErrors(info.stopTime * clip.frameRate);\n\n            orientationOffsetY = info.orientationOffsetY;\n            level = info.level;\n            cycleOffset = info.cycleOffset;\n            loopTime = info.loopTime;\n            loopBlend = info.loopBlend;\n            loopBlendOrientation = info.loopBlendOrientation;\n            loopBlendPositionY = info.loopBlendPositionY;\n            loopBlendPositionXZ = info.loopBlendPositionXZ;\n            keepOriginalOrientation = info.keepOriginalOrientation;\n            keepOriginalPositionY = info.keepOriginalPositionY;\n            keepOriginalPositionXZ = info.keepOriginalPositionXZ;\n            heightFromFeet = info.heightFromFeet;\n            mirror = info.mirror;\n\n            hasAdditiveReferencePose = info.hasAdditiveReferencePose;\n\n            if (additiveReferencePoseFrame / clip.frameRate != info.additiveReferencePoseTime)\n                additiveReferencePoseFrame = FixPrecisionErrors(info.additiveReferencePoseTime * clip.frameRate);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ImportSettings/BaseSpeedTreeImporterTabUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor.AssetImporters;\n\nnamespace UnityEditor\n{\n    internal abstract class BaseSpeedTreeImporterTabUI : BaseAssetImporterTabUI\n    {\n        internal BaseSpeedTreeImporterTabUI(AssetImporterEditor panelContainer)\n            : base(panelContainer)\n        {\n        }\n\n        protected IEnumerable<SpeedTreeImporter> importers\n        {\n            get { return (panelContainer as SpeedTreeImporterInspector).importers; }\n        }\n\n        protected bool upgradeMaterials\n        {\n            get { return (panelContainer as SpeedTreeImporterInspector).upgradeMaterials; }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Text.RegularExpressions;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor.Modules;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class DesktopPluginImporterExtension : DefaultPluginImporterExtension\n    {\n        internal enum DesktopPluginCPUArchitecture\n        {\n            None,\n            AnyCPU,\n            x86,\n            x86_64,\n            ARM64\n        }\n\n        internal class DesktopSingleCPUProperty : Property\n        {\n            public DesktopSingleCPUProperty(BuildTarget buildTarget, DesktopPluginCPUArchitecture architecture)\n                : base(EditorGUIUtility.TrTextContent(GetArchitectureNameInGUI(buildTarget, architecture)), cpuKey, architecture, BuildPipeline.GetBuildTargetName(buildTarget))\n            {\n            }\n\n            public DesktopSingleCPUProperty(GUIContent name, BuildTarget buildTarget)\n                : base(name, cpuKey, DesktopPluginCPUArchitecture.AnyCPU, BuildPipeline.GetBuildTargetName(buildTarget))\n            {\n            }\n\n            internal bool IsTargetEnabled(PluginImporterInspector inspector)\n            {\n                PluginImporterInspector.Compatibility compatibililty = inspector.GetPlatformCompatibility(platformName);\n                if (compatibililty == PluginImporterInspector.Compatibility.Mixed)\n                    throw new Exception(\"Unexpected mixed value for '\" + inspector.importer.assetPath + \"', platform: \" + platformName);\n                if (compatibililty != PluginImporterInspector.Compatibility.Compatible)\n                    return false;\n\n                var pluginCPU = value as DesktopPluginCPUArchitecture ? ?? DesktopPluginCPUArchitecture.None;\n                return pluginCPU == (DesktopPluginCPUArchitecture)defaultValue || pluginCPU == DesktopPluginCPUArchitecture.AnyCPU;\n            }\n\n            internal override void OnGUI(PluginImporterInspector inspector)\n            {\n                EditorGUILayout.BeginHorizontal();\n                GUILayout.Space(10);\n                EditorGUI.BeginChangeCheck();\n\n                // This toggle controls two things:\n                // * Is platform enabled/disabled?\n                // * Platform CPU value\n                bool isTargetEnabled = EditorGUILayout.Toggle(name, IsTargetEnabled(inspector));\n                if (EditorGUI.EndChangeCheck())\n                {\n                    value = isTargetEnabled ? defaultValue : DesktopPluginCPUArchitecture.None;\n                    inspector.SetPlatformCompatibility(platformName, isTargetEnabled);\n                }\n                EditorGUILayout.EndHorizontal();\n            }\n        }\n\n        class DesktopMultiCPUProperty : Property\n        {\n            private readonly DesktopPluginCPUArchitecture[] m_SupportedArchitectures;\n            private readonly GUIContent[] m_SupportedArchitectureNames;\n\n            public DesktopMultiCPUProperty(BuildTarget buildTarget, params DesktopPluginCPUArchitecture[] supportedArchitectures) :\n                base(cpuKey, cpuKey, DesktopPluginCPUArchitecture.None, BuildPipeline.GetBuildTargetName(buildTarget))\n            {\n                // Add \"None\" and \"AnyCPU\" architectures to the supported architecture list\n                m_SupportedArchitectures = new DesktopPluginCPUArchitecture[supportedArchitectures.Length + 2];\n                m_SupportedArchitectures[0] = DesktopPluginCPUArchitecture.None;\n\n                var architectureCount = supportedArchitectures.Length;\n                for (int i = 0; i < architectureCount; i++)\n                    m_SupportedArchitectures[i + 1] = supportedArchitectures[i];\n\n                m_SupportedArchitectures[m_SupportedArchitectures.Length - 1] = DesktopPluginCPUArchitecture.AnyCPU;\n\n                architectureCount = m_SupportedArchitectures.Length;\n                m_SupportedArchitectureNames = new GUIContent[architectureCount];\n                for (int i = 0; i < architectureCount; i++)\n                    m_SupportedArchitectureNames[i] = EditorGUIUtility.TrTextContent(GetArchitectureNameInGUI(buildTarget, m_SupportedArchitectures[i]));\n            }\n\n            DesktopPluginCPUArchitecture GetCurrentArchitecture(PluginImporterInspector inspector)\n            {\n                if (inspector.GetPlatformCompatibility(platformName) != PluginImporterInspector.Compatibility.Compatible)\n                    return DesktopPluginCPUArchitecture.None;\n\n                // Previous Unity versions had only two states: enabled or disabled. If it was enabled, then it means\n                // it was compatible with x64 as that was the only architecture available at the time.\n                var architecture = value as DesktopPluginCPUArchitecture ? ;\n                if (architecture == null || architecture == DesktopPluginCPUArchitecture.None)\n                    return DesktopPluginCPUArchitecture.x86_64;\n\n                return architecture.Value;\n            }\n\n            int GetArchitectureIndex(DesktopPluginCPUArchitecture architecture)\n            {\n                for (int i = 0; i < m_SupportedArchitectures.Length; i++)\n                {\n                    if (architecture == m_SupportedArchitectures[i])\n                        return i;\n                }\n\n                if (architecture == DesktopPluginCPUArchitecture.None)\n                    throw new InvalidOperationException(\"Supported architectures did not contain DesktopPluginCPUArchitecture.None!\");\n\n                // If current architecture is something that's not in supported list, we treat it as the plugin is set to \"No architecture\".\n                return GetArchitectureIndex(DesktopPluginCPUArchitecture.None);\n            }\n\n            internal override void OnGUI(PluginImporterInspector inspector)\n            {\n                EditorGUILayout.BeginHorizontal();\n                GUILayout.Space(10);\n                EditorGUI.BeginChangeCheck();\n\n                int selectedIndex = GetArchitectureIndex(GetCurrentArchitecture(inspector));\n                selectedIndex = EditorGUILayout.Popup(name, selectedIndex, m_SupportedArchitectureNames);\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    value = m_SupportedArchitectures[selectedIndex];\n                    inspector.SetPlatformCompatibility(platformName, m_SupportedArchitectures[selectedIndex] != DesktopPluginCPUArchitecture.None);\n                }\n                EditorGUILayout.EndHorizontal();\n            }\n        }\n\n        // Windows has 2 build targets. One build target for 32bit that supports 1 CPU architectue. The other for 64 bit that supports multiple 64 bit architectures (x64 and ARM64).\n        private readonly DesktopSingleCPUProperty m_Windows32;\n        private readonly DesktopMultiCPUProperty m_Windows64;\n\n        // Linux has 1 build target and 1 supported CPU architecture\n        private readonly DesktopSingleCPUProperty m_Linux;\n\n        // macOS has multiple architectures, but one target.\n        private readonly DesktopMultiCPUProperty m_MacOS;\n\n        // For Managed plugins the only options for CPU architecture should be \"None\" or \"AnyCPU\", so it can be DesktopSingleCPUProperty\n        private readonly DesktopSingleCPUProperty m_Windows32Managed;\n        private readonly DesktopSingleCPUProperty m_Windows64Managed;\n        private readonly DesktopSingleCPUProperty m_LinuxManaged;\n        private readonly DesktopSingleCPUProperty m_MacOSManaged;\n\n        private Property[] nativeProperties = null;\n        private Property[] managedProperties = null;\n\n        public DesktopPluginImporterExtension()\n            : base(null)\n        {\n            m_Windows32 = new DesktopSingleCPUProperty(BuildTarget.StandaloneWindows, DesktopPluginCPUArchitecture.x86);\n            m_Windows64 = new DesktopMultiCPUProperty(BuildTarget.StandaloneWindows64, DesktopPluginCPUArchitecture.x86_64, DesktopPluginCPUArchitecture.ARM64);\n\n            m_Linux = new DesktopSingleCPUProperty(BuildTarget.StandaloneLinux64, DesktopPluginCPUArchitecture.x86_64);\n            m_MacOS = new DesktopMultiCPUProperty(BuildTarget.StandaloneOSX, DesktopPluginCPUArchitecture.x86_64, DesktopPluginCPUArchitecture.ARM64);\n\n            // Windows 32-bit (x86) and Windows 64-bit (ARM64/x86_64) are separate targets, so they have separate checkboxes\n            // Linux only has x64 architecture and Mac has a single target for both 64-bit architectures (ARM64/Intel-64bit)\n            m_Windows32Managed = new DesktopSingleCPUProperty(EditorGUIUtility.TrTextContent(\"Windows x86\"), BuildTarget.StandaloneWindows);\n            m_Windows64Managed = new DesktopSingleCPUProperty(EditorGUIUtility.TrTextContent(\"Windows 64-bit\"), BuildTarget.StandaloneWindows64);\n            m_LinuxManaged = new DesktopSingleCPUProperty(EditorGUIUtility.TrTextContent(\"Linux x64\"),BuildTarget.StandaloneLinux64);\n            m_MacOSManaged = new DesktopSingleCPUProperty(EditorGUIUtility.TrTextContent(\"macOS 64-bit\"),BuildTarget.StandaloneOSX);\n\n            nativeProperties = new Property[]\n            {\n                m_Windows32,\n                m_Windows64,\n                m_Linux,\n                m_MacOS,\n            };\n\n            managedProperties = new Property[]\n            {\n                m_Windows32Managed,\n                m_Windows64Managed,\n                m_LinuxManaged,\n                m_MacOSManaged\n            };\n        }\n\n        private bool IsUsableOnWindows(PluginImporter imp)\n        {\n            if (!imp.isNativePlugin)\n                return true;\n\n            string ext = Path.GetExtension(imp.assetPath).ToLower();\n            return ext == \".dll\" || IsCppPluginFile(imp.assetPath);\n        }\n\n        private bool IsUsableOnOSX(PluginImporter imp)\n        {\n            if (!imp.isNativePlugin)\n                return true;\n\n            string ext = FileUtil.GetPathExtension(imp.assetPath).ToLower();\n            return ext == \"bundle\" || ext == \"dylib\" || ext == \"xcprivacy\" || IsLinuxLibrary(imp.assetPath) || IsCppPluginFile(imp.assetPath);\n        }\n\n        private bool IsUsableOnLinux(PluginImporter imp)\n        {\n            if (!imp.isNativePlugin)\n                return true;\n\n            return IsLinuxLibrary(imp.assetPath) || IsCppPluginFile(imp.assetPath);\n        }\n\n        protected override Property[] GetPropertiesForInspector(PluginImporterInspector inspector)\n        {\n            return inspector.importer.isNativePlugin ? nativeProperties : managedProperties;\n        }\n\n        public override void OnPlatformSettingsGUI(PluginImporterInspector inspector)\n        {\n            PluginImporter imp = inspector.importer;\n            EditorGUI.BeginChangeCheck();\n            // skip CPU property for things that aren't native libs\n            if (imp.isNativePlugin)\n            {\n                if (IsUsableOnWindows(imp))\n                {\n                    EditorGUILayout.LabelField(EditorGUIUtility.TrTextContent(\"Windows\"), EditorStyles.boldLabel);\n                    m_Windows32.OnGUI(inspector);\n                    m_Windows64.OnGUI(inspector);\n                    EditorGUILayout.Space();\n                }\n\n                if (IsUsableOnLinux(imp))\n                {\n                    EditorGUILayout.LabelField(EditorGUIUtility.TrTextContent(\"Linux\"), EditorStyles.boldLabel);\n                    m_Linux.OnGUI(inspector);\n                    EditorGUILayout.Space();\n                }\n\n                if (IsUsableOnOSX(imp))\n                {\n                    EditorGUILayout.LabelField(EditorGUIUtility.TrTextContent(\"macOS\"), EditorStyles.boldLabel);\n                    m_MacOS.OnGUI(inspector);\n                    EditorGUILayout.Space();\n                }\n            }\n            else\n            {\n                // Managed plugins are usable on all platforms\n                m_Windows32Managed.OnGUI(inspector);\n                m_Windows64Managed.OnGUI(inspector);\n                EditorGUILayout.Space();\n\n                m_LinuxManaged.OnGUI(inspector);\n                EditorGUILayout.Space();\n\n                m_MacOSManaged.OnGUI(inspector);\n                EditorGUILayout.Space();\n            }\n\n            if (EditorGUI.EndChangeCheck())\n                hasModified = true;\n        }\n\n        public void ValidateSingleCPUTargets(PluginImporterInspector inspector)\n        {\n            var singleCPUTargets = GetPropertiesForInspector(inspector).OfType<DesktopSingleCPUProperty>();\n\n            foreach (var target in singleCPUTargets)\n            {\n                target.value = target.IsTargetEnabled(inspector) ? target.defaultValue : DesktopPluginCPUArchitecture.None;\n\n                foreach (var importer in inspector.importers)\n                {\n                    importer.SetPlatformData(target.platformName, cpuKey, target.value.ToString());\n                }\n            }\n        }\n\n        public override string CalculateFinalPluginPath(string platformName, PluginImporter imp)\n        {\n            BuildTarget target = BuildPipeline.GetBuildTargetByName(platformName);\n            bool pluginForWindows = target == BuildTarget.StandaloneWindows || target == BuildTarget.StandaloneWindows64;\n#pragma warning disable 612, 618\n            bool pluginForOSX = target == BuildTarget.StandaloneOSXIntel || target == BuildTarget.StandaloneOSXIntel64 || target == BuildTarget.StandaloneOSX;\n            bool pluginForLinux = target == BuildTarget.StandaloneLinux || target == BuildTarget.StandaloneLinux64 || target == BuildTarget.StandaloneLinuxUniversal || target == BuildTarget.LinuxHeadlessSimulation;\n#pragma warning restore 612, 618\n\n            if (!pluginForLinux && !pluginForOSX && !pluginForWindows)\n                throw new Exception(string.Format(\"Failed to resolve standalone platform, platform string '{0}', resolved target '{1}'\",\n                    platformName, target.ToString()));\n\n            if (pluginForWindows && !IsUsableOnWindows(imp))\n                return string.Empty;\n            if (pluginForOSX && !IsUsableOnOSX(imp))\n                return string.Empty;\n            if (pluginForLinux && !IsUsableOnLinux(imp))\n                return string.Empty;\n\n            string cpu = imp.GetPlatformData(platformName, cpuKey);\n\n            if (string.Compare(cpu, \"None\", true) == 0)\n                return string.Empty;\n\n            if (pluginForWindows)\n            {\n                if (string.Compare(cpu, nameof(DesktopPluginCPUArchitecture.ARM64), true) == 0)\n                {\n                    return Path.Combine(cpu, Path.GetFileName(imp.assetPath));\n                }\n\n                // Fix case 1185926: plugins for x86_64 are supposed to be copied to Plugins/x86_64\n                // Plugins for x86 are supposed to be copied to Plugins/x86\n                var cpuName = target == BuildTarget.StandaloneWindows ? nameof(DesktopPluginCPUArchitecture.x86) : nameof(DesktopPluginCPUArchitecture.x86_64);\n                return Path.Combine(cpuName, Path.GetFileName(imp.assetPath));\n            }\n\n            if (pluginForOSX)\n            {\n                // Add the correct architecture if not AnyCPU\n                return base.CalculateFinalPluginPath(platformName, imp);\n            }\n\n            // For files this will return filename, for directories, this will return last path component\n            return Path.GetFileName(imp.assetPath);\n        }\n\n        // Regex that matchers strings ending in \".so\" or \".so.12\" or \".so.4.7\" and so on.\n        private static Regex LinuxLibraryRegex = new Regex(@\"\\.so(\\.[0-9]+)*$\", RegexOptions.Compiled | RegexOptions.IgnoreCase);\n        internal static bool IsLinuxLibrary(string assetPath)\n        {\n            return LinuxLibraryRegex.IsMatch(assetPath);\n        }\n\n        internal static bool IsCppPluginFile(string assetPath)\n        {\n            var extension = Path.GetExtension(assetPath).ToLower();\n            return extension == \".cpp\" || extension == \".c\" || extension == \".h\" || extension == \".mm\" || extension == \".m\";\n        }\n\n        static string GetArchitectureNameInGUI(BuildTarget buildTarget, DesktopPluginCPUArchitecture architecture)\n        {\n            switch (architecture)\n            {\n                case DesktopPluginCPUArchitecture.None :\n                    return \"None\";\n\n                case DesktopPluginCPUArchitecture.x86 :\n                    return buildTarget == BuildTarget.StandaloneOSX ? \"Intel 32-bit\" : \"x86\";\n\n                case DesktopPluginCPUArchitecture.x86_64:\n                    return buildTarget == BuildTarget.StandaloneOSX ? \"Intel 64-bit\" : \"x64\";\n\n                case DesktopPluginCPUArchitecture.ARM64:\n                    return buildTarget == BuildTarget.StandaloneOSX ? \"Apple silicon\" : \"ARM64\";\n\n                case DesktopPluginCPUArchitecture.AnyCPU:\n                    return \"Any CPU\";\n\n                default:\n                    throw new NotSupportedException(\"Unknown DesktopPluginCPUArchitecture value: \" + architecture);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ImportSettings/EditorPluginImporterExtension.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Text;\nusing System.Text.RegularExpressions;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditor.Modules;\n\nnamespace UnityEditor\n{\n    internal class EditorPluginImporterExtension : DefaultPluginImporterExtension\n    {\n        internal enum EditorPluginCPUArchitecture\n        {\n            AnyCPU = 0,\n            x86_64,\n            ARM64\n        }\n\n        internal enum EditorPluginOSArchitecture\n        {\n            AnyOS,\n            [InspectorName(\"macOS\")]\n            OSX,\n            Windows,\n            Linux\n        }\n\n        internal class EditorProperty : Property\n        {\n            public EditorProperty(GUIContent name, string key, object defaultValue)\n                : base(name, key, defaultValue, BuildPipeline.GetEditorTargetName())\n            {\n            }\n\n            internal override void Reset(PluginImporterInspector inspector)\n            {\n                string valueString = inspector.importer.GetEditorData(key);\n                ParseStringValue(inspector, valueString);\n            }\n\n            internal override void Apply(PluginImporterInspector inspector)\n            {\n                inspector.importer.SetEditorData(key, value.ToString());\n            }\n        }\n\n        internal class CPUProperty : Property\n        {\n            private readonly Func<Enum, bool> validArch;\n            private EditorPluginOSArchitecture currentOS;\n            private readonly GUIContent[] m_ArchitectureNames;\n\n            public CPUProperty(GUIContent name, string key, EditorPluginCPUArchitecture defaultValue, Func<Enum, bool> validArch)\n                : base(name, key, defaultValue, BuildPipeline.GetEditorTargetName())\n            {\n                this.validArch = validArch;\n                this.currentOS = EditorPluginOSArchitecture.AnyOS;\n                int enumLength = Enum.GetNames(typeof(EditorPluginCPUArchitecture)).Length;\n                m_ArchitectureNames = new GUIContent[enumLength];\n                for (int i = 0; i < enumLength; i++)\n                {\n                    m_ArchitectureNames[i] = EditorGUIUtility.TrTextContent(GetArchitectureName(currentOS, (EditorPluginCPUArchitecture)i));\n                }\n            }\n\n            internal override void Reset(PluginImporterInspector inspector)\n            {\n                string valueString = inspector.importer.GetEditorData(key);\n                ParseStringValue(inspector, valueString);\n            }\n\n            internal override void Apply(PluginImporterInspector inspector)\n            {\n                inspector.importer.SetEditorData(key, value.ToString());\n            }\n\n            internal override void OnGUI(PluginImporterInspector inspector)\n            {\n                EditorGUILayout.BeginHorizontal();\n                EditorGUI.BeginChangeCheck();\n                int selectedIndex = (int)GetCurrentArchitecture(inspector);\n                selectedIndex = EditorGUILayout.Popup(name, selectedIndex, m_ArchitectureNames);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    value = (EditorPluginCPUArchitecture)selectedIndex;\n                }\n                EditorGUILayout.EndHorizontal();\n            }\n\n            private EditorPluginCPUArchitecture GetCurrentArchitecture(PluginImporterInspector inspector)\n            {\n                var arch = value as EditorPluginCPUArchitecture?;\n                if (arch == null)\n                {\n                    return EditorPluginCPUArchitecture.AnyCPU;\n                }\n                return arch.Value;\n            }\n\n            public void UpdateArchitectureNames(EditorPluginOSArchitecture osValue)\n            {\n                if (currentOS != osValue)\n                {\n                    int enumLength = Enum.GetNames(typeof(EditorPluginCPUArchitecture)).Length;\n                    for (int i = 0; i < enumLength; i++)\n                    {\n                        m_ArchitectureNames[i] = EditorGUIUtility.TrTextContent(GetArchitectureName(osValue, (EditorPluginCPUArchitecture)i));\n                    }\n                    currentOS = osValue;\n                }\n            }\n\n            static string GetArchitectureName(EditorPluginOSArchitecture os, EditorPluginCPUArchitecture architecture)\n            {\n                switch (architecture)\n                {\n                    case EditorPluginCPUArchitecture.x86_64:\n                        return os == EditorPluginOSArchitecture.OSX ? \"Intel 64-bit\" : \"x64\";\n\n                    case EditorPluginCPUArchitecture.ARM64:\n                        return os == EditorPluginOSArchitecture.OSX ? \"Apple silicon\" : \"Arm64\";\n\n                    case EditorPluginCPUArchitecture.AnyCPU:\n                        return \"Any CPU\";\n\n                    default:\n                        throw new NotSupportedException(\"Unknown EditorPluginCPUArchitecture value: \" + architecture);\n                }\n            }\n        }\n\n        private CPUProperty editorCPUProperty;\n        private EditorProperty editorOSProperty;\n\n        public EditorPluginImporterExtension() : base(null)\n        {\n            editorCPUProperty = new CPUProperty(EditorGUIUtility.TrTextContent(\"CPU\", \"The processor architectiure that this plugin is compatible with\"), \"CPU\", EditorPluginCPUArchitecture.AnyCPU, (Enum e) => CanSelectArch(e));\n            editorOSProperty = new EditorProperty(EditorGUIUtility.TrTextContent(\"OS\", \"The Editor operating system that this plugin is compatible with\"), \"OS\", EditorPluginOSArchitecture.AnyOS);\n\n            properties = new Property[] { editorOSProperty, editorCPUProperty };\n        }\n\n        public override void OnPlatformSettingsGUI(PluginImporterInspector inspector)\n        {\n            EditorGUI.BeginChangeCheck();\n\n            editorOSProperty.OnGUI(inspector);\n            editorCPUProperty.UpdateArchitectureNames((EditorPluginOSArchitecture)editorOSProperty.value);\n            editorCPUProperty.OnGUI(inspector);\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (!CanSelectArch(editorCPUProperty.value as Enum))\n                    editorCPUProperty.value = EditorPluginCPUArchitecture.AnyCPU;\n\n                hasModified = true;\n            }\n        }\n\n        private bool CanSelectArch(Enum value)\n        {\n            var arch = (EditorPluginCPUArchitecture)value;\n            var os = (EditorPluginOSArchitecture)editorOSProperty.value;\n\n            switch (os)\n            {\n                case EditorPluginOSArchitecture.AnyOS:\n                    return arch == EditorPluginCPUArchitecture.AnyCPU;\n                case EditorPluginOSArchitecture.OSX:\n                case EditorPluginOSArchitecture.Windows:\n                    return true;\n                case EditorPluginOSArchitecture.Linux:\n                    return arch != EditorPluginCPUArchitecture.ARM64;\n                default:\n                    return false;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ImportSettings/ExposeTransformEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewUtility = UnityEditor.IMGUI.Controls.TreeViewUtility<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    internal class ExposeTransformEditor\n    {\n        private static class Styles\n        {\n            // TreeView column\n            public static GUIContent TransformName = EditorGUIUtility.TrTextContent(\"Node Name\");\n            public static GUIContent EnableName = EditorGUIUtility.TrTextContent(\"Use\", \"Maintain Alt/Option key to enable or disable all children\");\n        }\n\n\n        // TreeView\n        private string[] m_TransformPaths;\n        private SerializedProperty m_ExtraExposedTransformPaths;\n        List<string> m_ExtraExposedTransformPathsList;\n        TreeViewState m_TreeViewState;\n        MultiColumnHeaderState m_ViewHeaderState;\n        private OptimizeGameObjectTreeView m_ExposeTransformEditor;\n\n        public void OnEnable(string[] transformPaths, SerializedObject serializedObject)\n        {\n            m_TransformPaths = transformPaths;\n            m_ExtraExposedTransformPaths = serializedObject.FindProperty(\"m_ExtraExposedTransformPaths\");\n\n            SetupOptimizeGameObjectTreeView();\n\n            ResetExposedTransformList();\n        }\n\n        public void ResetExposedTransformList()\n        {\n            int exposedNodeCount = m_ExtraExposedTransformPaths.arraySize;\n            m_ExtraExposedTransformPathsList = new List<string>(exposedNodeCount);\n            if (exposedNodeCount > 0)\n            {\n                var nodeIterator = m_ExtraExposedTransformPaths.GetArrayElementAtIndex(0);\n                for (int i = 0; i < exposedNodeCount; ++i)\n                {\n                    m_ExtraExposedTransformPathsList.Add(nodeIterator.stringValue);\n                    nodeIterator.Next(false);\n                }\n            }\n        }\n\n        public void OnGUI()\n        {\n            var listRect = GUILayoutUtility.GetRect(0, 0, GUILayout.ExpandWidth(true));\n            m_ExposeTransformEditor.OnGUI(listRect);\n        }\n\n        void SetupOptimizeGameObjectTreeView()\n        {\n            if (m_TreeViewState == null)\n                m_TreeViewState = new TreeViewState();\n            var columns = new[]\n            {\n                new MultiColumnHeaderState.Column\n                {\n                    headerContent = Styles.EnableName,\n                    headerTextAlignment = TextAlignment.Center,\n                    canSort = false,\n                    width = 31f, minWidth = 31f, maxWidth = 31f,\n                    autoResize = true, allowToggleVisibility = false\n                },\n                new MultiColumnHeaderState.Column\n                {\n                    headerContent = Styles.TransformName,\n                    headerTextAlignment = TextAlignment.Left,\n                    canSort = false,\n                    autoResize = true, allowToggleVisibility = false,\n                }\n            };\n            var newHeader = new MultiColumnHeaderState(columns);\n            if (m_ViewHeaderState != null)\n            {\n                MultiColumnHeaderState.OverwriteSerializedFields(m_ViewHeaderState, newHeader);\n            }\n            m_ViewHeaderState = newHeader;\n            var multiColumnHeader = new MultiColumnHeader(m_ViewHeaderState);\n            multiColumnHeader.ResizeToFit();\n            m_ExposeTransformEditor = new OptimizeGameObjectTreeView(m_TreeViewState, multiColumnHeader, FillNodeInfos);\n            if (m_ExposeTransformEditor.searchString == null)\n                m_ExposeTransformEditor.searchString = string.Empty;\n        }\n\n        SerializedNodeInfo FillNodeInfos()\n        {\n            var rootNode = new SerializedNodeInfo() { depth = -1, displayName = \"\", id = 0, children = new List<TreeViewItem>(0) };\n            if (m_TransformPaths == null || m_TransformPaths.Length < 1)\n            {\n                return rootNode;\n            }\n\n            var nodesCount = m_TransformPaths.Length;\n            var nodeInfos = new List<SerializedNodeInfo>(nodesCount - 1);\n            Stack<string> depth = new Stack<string>(nodesCount);\n            string currentPath = String.Empty;\n\n            // skip the first index as it is the empty root of the gameObject\n            for (int i = 1; i < nodesCount; i++)\n            {\n                var newNode = new SerializedNodeInfo();\n                newNode.id = i;\n                newNode.path = m_TransformPaths[i];\n                newNode.getNodeState = GetNodeState;\n                newNode.setNodeState = SetNodeState;\n\n                var newPath = newNode.path;\n                while (!string.IsNullOrEmpty(currentPath) && !newPath.StartsWith(currentPath + \"/\", StringComparison.InvariantCulture))\n                {\n                    // we are in a new node, lets unstack until we reach the correct hierarchy\n                    var oldParent = depth.Pop();\n                    var index = currentPath.LastIndexOf(oldParent, StringComparison.InvariantCulture);\n                    if (index > 0)\n                        index--;\n                    currentPath = currentPath.Remove(index);\n                }\n                var nodeName = newPath;\n                if (!string.IsNullOrEmpty(currentPath))\n                    nodeName = nodeName.Remove(0, currentPath.Length + 1);\n\n                newNode.depth = depth.Count;\n                newNode.displayName = nodeName;\n\n                depth.Push(nodeName);\n                currentPath = newPath;\n\n                nodeInfos.Add(newNode);\n            }\n\n            TreeViewUtility.SetChildParentReferences(nodeInfos.Cast<TreeViewItem>().ToList(), rootNode);\n            return rootNode;\n        }\n\n        private bool GetNodeState(string nodePath)\n        {\n            return m_ExtraExposedTransformPathsList.Contains(nodePath);\n        }\n\n        private void SetNodeState(string nodePath, bool state)\n        {\n            if (GetNodeState(nodePath) != state)\n            {\n                if (state)\n                {\n                    m_ExtraExposedTransformPaths.InsertArrayElementAtIndex(m_ExtraExposedTransformPaths.arraySize);\n                    m_ExtraExposedTransformPaths.GetArrayElementAtIndex(m_ExtraExposedTransformPaths.arraySize - 1).stringValue = nodePath;\n                    m_ExtraExposedTransformPathsList.Add(nodePath);\n                }\n                else\n                {\n                    var index = m_ExtraExposedTransformPathsList.IndexOf(nodePath);\n                    m_ExtraExposedTransformPaths.DeleteArrayElementAtIndex(index);\n                    m_ExtraExposedTransformPathsList.RemoveAt(index);\n                }\n            }\n        }\n    }\n\n    internal class OptimizeGameObjectTreeView : ToggleTreeView<SerializedNodeInfo>\n    {\n        public OptimizeGameObjectTreeView(TreeViewState state, MultiColumnHeader multiColumnHeader, Func<SerializedNodeInfo> rebuildRoot)\n            : base(state, multiColumnHeader, rebuildRoot)\n        {\n        }\n    }\n\n    internal class SerializedNodeInfo : ToggleTreeViewItem\n    {\n        public string path;\n        public Func<string, bool> getNodeState;\n        public Action<string, bool> setNodeState;\n\n        public override bool nodeState\n        {\n            get { return getNodeState != null && getNodeState(path); }\n\n            set\n            {\n                setNodeState?.Invoke(path, value);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ImportSettings/IHVImageFormatImporterInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.AssetImporters;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(IHVImageFormatImporter))]\n    [CanEditMultipleObjects]\n    internal class IHVImageFormatImporterInspector : AssetImporterEditor\n    {\n        public override bool showImportedObject { get { return false; } }\n\n        SerializedProperty  m_IsReadable;\n        SerializedProperty  m_sRGBTexture;\n        SerializedProperty  m_FilterMode;\n        SerializedProperty  m_WrapU;\n        SerializedProperty  m_WrapV;\n        SerializedProperty  m_WrapW;\n        SerializedProperty  m_StreamingMipmaps;\n        SerializedProperty  m_StreamingMipmapsPriority;\n        SerializedProperty m_IgnoreMipmapLimit;\n        SerializedProperty m_MipmapLimitGroupName;\n\n        internal class Styles\n        {\n            // copy pasted from TextureImporterInspector.TextureSettingsGUI()\n            public static readonly GUIContent readWrite     = EditorGUIUtility.TrTextContent(\"Read/Write\", \"Enable to be able to access the raw pixel data from code.\");\n            public static readonly GUIContent sRGBTexture   = EditorGUIUtility.TrTextContent(\"sRGB (Color Texture)\", \"Texture content is stored in gamma space. Non-HDR color textures should enable this flag (except if used for IMGUI).\");\n            public static readonly GUIContent wrapMode      = EditorGUIUtility.TrTextContent(\"Wrap Mode\");\n            public static readonly GUIContent filterMode    = EditorGUIUtility.TrTextContent(\"Filter Mode\");\n            public static readonly GUIContent streamingMipmaps = EditorGUIUtility.TrTextContent(\"Stream Mipmap Levels\", \"Only load larger mipmap levels as needed to render the current game cameras.\");\n            public static readonly GUIContent streamingMipmapsPriority = EditorGUIUtility.TrTextContent(\"Priority\", \"Mipmap streaming priority when there's contention for resources. Positive numbers represent higher priority. Valid range is -128 to 127.\");\n\n            public static readonly int[] filterModeValues           =\n            { (int)FilterMode.Point, (int)FilterMode.Bilinear, (int)FilterMode.Trilinear };\n            public static readonly GUIContent[] filterModeOptions   =\n            { EditorGUIUtility.TrTextContent(\"Point (no filter)\"), EditorGUIUtility.TrTextContent(\"Bilinear\"), EditorGUIUtility.TrTextContent(\"Trilinear\") };\n        }\n\n\n        public override void OnEnable()\n        {\n            base.OnEnable();\n\n            m_IsReadable    = serializedObject.FindProperty(\"m_IsReadable\");\n            m_sRGBTexture   = serializedObject.FindProperty(\"m_sRGBTexture\");\n            m_FilterMode    = serializedObject.FindProperty(\"m_TextureSettings.m_FilterMode\");\n            m_WrapU         = serializedObject.FindProperty(\"m_TextureSettings.m_WrapU\");\n            m_WrapV         = serializedObject.FindProperty(\"m_TextureSettings.m_WrapV\");\n            m_WrapW         = serializedObject.FindProperty(\"m_TextureSettings.m_WrapW\");\n            m_StreamingMipmaps         = serializedObject.FindProperty(\"m_StreamingMipmaps\");\n            m_StreamingMipmapsPriority = serializedObject.FindProperty(\"m_StreamingMipmapsPriority\");\n            m_IgnoreMipmapLimit        = serializedObject.FindProperty(\"m_IgnoreMipmapLimit\");\n            m_MipmapLimitGroupName     = serializedObject.FindProperty(\"m_MipmapLimitGroupName\");\n        }\n\n        // alas it looks impossible to share code so we copy paste from TextureImporterInspector.TextureSettingsGUI()\n\n        bool m_ShowPerAxisWrapModes = false;\n        public void TextureSettingsGUI()\n        {\n            // NOTE: once we get ability to have 3D/Volume texture shapes, should pass true for isVolume based on m_TextureShape\n            // Also, always consider we may have a volume if we don't know the target.\n            bool isVolume = assetTarget == null;\n            TextureInspector.WrapModePopup(m_WrapU, m_WrapV, m_WrapW, isVolume, ref m_ShowPerAxisWrapModes, assetTarget == null);\n\n            Rect rect = EditorGUILayout.GetControlRect();\n            EditorGUI.BeginProperty(rect, Styles.filterMode, m_FilterMode);\n            EditorGUI.BeginChangeCheck();\n            FilterMode filter = (FilterMode)EditorGUI.IntPopup(rect, Styles.filterMode, m_FilterMode.intValue, Styles.filterModeOptions, Styles.filterModeValues);\n            if (EditorGUI.EndChangeCheck())\n                m_FilterMode.intValue = (int)filter;\n            EditorGUI.EndProperty();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n            EditorGUILayout.PropertyField(m_IsReadable, Styles.readWrite);\n            EditorGUILayout.PropertyField(m_sRGBTexture, Styles.sRGBTexture);\n\n            EditorGUI.BeginChangeCheck();\n            TextureSettingsGUI();\n            if (EditorGUI.EndChangeCheck())\n            {\n                // copy pasted from TextureImporterInspector.TextureSettingsGUI()\n                foreach (AssetImporter importer in targets)\n                {\n                    Texture tex = AssetDatabase.LoadMainAssetAtPath(importer.assetPath) as Texture;\n                    if (tex != null)\n                    {\n                        TextureUtil.SetFilterModeNoDirty(tex, (FilterMode)m_FilterMode.intValue);\n\n                        if (!m_WrapU.hasMultipleDifferentValues && !m_WrapV.hasMultipleDifferentValues && !m_WrapW.hasMultipleDifferentValues)\n                        {\n                            TextureUtil.SetWrapModeNoDirty(tex, (TextureWrapMode)m_WrapU.intValue, (TextureWrapMode)m_WrapV.intValue, (TextureWrapMode)m_WrapW.intValue);\n                        }\n                    }\n                }\n                SceneView.RepaintAll();\n            }\n\n            EditorGUILayout.PropertyField(m_StreamingMipmaps, Styles.streamingMipmaps);\n\n            if (m_StreamingMipmaps.boolValue && !m_StreamingMipmaps.hasMultipleDifferentValues)\n            {\n                EditorGUI.indentLevel++;\n                EditorGUILayout.PropertyField(m_StreamingMipmapsPriority, Styles.streamingMipmapsPriority);\n                EditorGUI.indentLevel--;\n            }\n\n            TextureImporterInspector.DoMipmapLimitsGUI(m_IgnoreMipmapLimit, m_MipmapLimitGroupName);\n\n            serializedObject.ApplyModifiedProperties();\n            ApplyRevertGUI();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ImportSettings/ImportSettingsInternalID.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEngine;\nusing System;\nusing System.Collections.Generic;\n\ninternal class ImportSettingInternalID\n{\n    static public void RegisterInternalID(SerializedObject serializedObject, UnityType type, long id, string name)\n    {\n        SerializedProperty internalIDMap = serializedObject.FindProperty(\"m_InternalIDToNameTable\");\n        internalIDMap.arraySize++;\n        SerializedProperty newEntry = internalIDMap.GetArrayElementAtIndex(internalIDMap.arraySize - 1);\n        SerializedProperty first = newEntry.FindPropertyRelative(\"first\");\n        SerializedProperty cid = first.FindPropertyRelative(\"first\");\n        SerializedProperty lid = first.FindPropertyRelative(\"second\");\n        cid.intValue = type.persistentTypeID;\n        lid.longValue = id;\n        SerializedProperty sname = newEntry.FindPropertyRelative(\"second\");\n        sname.stringValue = name;\n    }\n\n    static public void RegisterInternalID(SerializedObject serializedObject, UnityType type, ICollection<long> ids, ICollection<string> names)\n    {\n        if (ids.Count != names.Count)\n            return;\n\n        SerializedProperty internalIDMap = serializedObject.FindProperty(\"m_InternalIDToNameTable\");\n        var startIdx = internalIDMap.arraySize;\n        internalIDMap.arraySize += ids.Count;\n        var id = ids.GetEnumerator();\n        id.Reset(); id.MoveNext();\n        var name = names.GetEnumerator();\n        name.Reset(); name.MoveNext();\n        if (internalIDMap.arraySize > 0)\n        {\n            SerializedProperty newEntry = internalIDMap.GetArrayElementAtIndex(startIdx);\n            for (int i = 0; i < ids.Count; ++i, id.MoveNext(), name.MoveNext())\n            {\n                SerializedProperty first = newEntry.FindPropertyRelative(\"first\");\n                SerializedProperty cid = first.FindPropertyRelative(\"first\");\n                SerializedProperty lid = first.FindPropertyRelative(\"second\");\n                cid.intValue = type.persistentTypeID;\n                lid.longValue = id.Current;\n                SerializedProperty sname = newEntry.FindPropertyRelative(\"second\");\n                sname.stringValue = name.Current;\n                newEntry.Next(false);\n            }\n        }\n    }\n\n    static public bool RemoveEntryFromInternalIDTable(SerializedObject serializedObject, UnityType type, long id,\n        string name)\n    {\n        int classID = type.persistentTypeID;\n        SerializedProperty internalIDMap = serializedObject.FindProperty(\"m_InternalIDToNameTable\");\n        bool found = false;\n        int index = 0;\n        foreach (SerializedProperty element in internalIDMap)\n        {\n            SerializedProperty first = element.FindPropertyRelative(\"first\");\n            SerializedProperty cid = first.FindPropertyRelative(\"first\");\n            if (cid.intValue == classID)\n            {\n                SerializedProperty second = element.FindPropertyRelative(\"second\");\n                SerializedProperty lid = first.FindPropertyRelative(\"second\");\n                string foundName = second.stringValue;\n                long localid = lid.longValue;\n\n                if (foundName == name && localid == id)\n                {\n                    found = true;\n                    internalIDMap.DeleteArrayElementAtIndex(index);\n                    return found;\n                }\n            }\n\n            index++;\n        }\n        return found;\n    }\n\n    static public long FindInternalID(SerializedObject serializedObject, UnityType type, string name)\n    {\n        long id = 0;\n        SerializedProperty internalIDMap = serializedObject.FindProperty(\"m_InternalIDToNameTable\");\n        foreach (SerializedProperty element in internalIDMap)\n        {\n            SerializedProperty first = element.FindPropertyRelative(\"first\");\n            SerializedProperty cid = first.FindPropertyRelative(\"first\");\n            if (cid.intValue == type.persistentTypeID)\n            {\n                SerializedProperty second = element.FindPropertyRelative(\"second\");\n                if (second.stringValue == name)\n                {\n                    SerializedProperty lid = first.FindPropertyRelative(\"second\");\n                    id = lid.longValue;\n                    return id;\n                }\n            }\n        }\n\n        return id;\n    }\n\n    static public long MakeInternalID(SerializedObject serializedObject, UnityType type, string name)\n    {\n        long id = ImportSettingInternalID.FindInternalID(serializedObject, type, name);\n        if (id == 0L)\n        {\n            id = AssetImporter.MakeLocalFileIDWithHash(type.persistentTypeID, name, 0);\n            RegisterInternalID(serializedObject, type, id, name);\n        }\n        return id;\n    }\n\n    static public void Rename(SerializedObject serializedObject, UnityType type, string oldName, string newName)\n    {\n        RenameMultiple(serializedObject, type, new string[] { oldName }, new string[] { newName });\n    }\n\n    // Rename multiple entries at once to avoid situations where swapping names of two entries would break references\n    static public void RenameMultiple(SerializedObject serializedObject, UnityType type, string[] oldNames, string[] newNames)\n    {\n        int classID = type.persistentTypeID;\n\n        int left = oldNames.Length;\n\n        SerializedProperty recycleMap = serializedObject.FindProperty(\"m_InternalIDToNameTable\");\n        foreach (SerializedProperty element in recycleMap)\n        {\n            SerializedProperty first = element.FindPropertyRelative(\"first\");\n            SerializedProperty cid = first.FindPropertyRelative(\"first\");\n            if (cid.intValue == classID)\n            {\n                SerializedProperty second = element.FindPropertyRelative(\"second\");\n                int idx = Array.IndexOf(oldNames, second.stringValue);\n                if (idx >= 0)\n                {\n                    second.stringValue = newNames[idx];\n                    if (--left == 0)\n                        break;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ImportSettings/SpeedTreeImporterInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(SpeedTreeImporter))]\n    [CanEditMultipleObjects]\n    internal class SpeedTreeImporterInspector : AssetImporterTabbedEditor\n    {\n        private static class Styles\n        {\n            public static GUIContent ApplyAndGenerate = EditorGUIUtility.TrTextContent(\"Apply & Generate Materials\", \"Apply current importer settings and generate materials with new settings.\");\n            public static GUIContent Regenerate = EditorGUIUtility.TrTextContent(\"Regenerate Materials\", \"Regenerate materials from the current importer settings.\");\n            public static GUIContent RegenerateRemapped = EditorGUIUtility.TrTextContent(\"Regenerate Materials\", \"Regenerate the remapped materials from the current import settings.\");\n            public static GUIContent ApplyAndGenerateRemapped = EditorGUIUtility.TrTextContent(\"Apply & Generate Materials\", \"Apply current importer settings and regenerate the remapped materials with new settings.\");\n        }\n\n        private SerializedProperty m_MaterialLocation;\n        private SerializedProperty m_Materials;\n        private bool m_HasRemappedMaterials = false;\n\n        public override void OnEnable()\n        {\n            m_MaterialLocation = serializedObject.FindProperty(\"m_MaterialLocation\");\n            m_Materials = serializedObject.FindProperty(\"m_Materials\");\n\n            if (tabs == null)\n            {\n                tabs = new BaseAssetImporterTabUI[] { new SpeedTreeImporterModelEditor(this), new SpeedTreeImporterMaterialEditor(this) };\n                m_TabNames = new string[] { \"Model\", \"Materials\" };\n            }\n            base.OnEnable();\n        }\n\n        public override void OnDisable()\n        {\n            foreach (var tab in tabs)\n            {\n                tab.OnDisable();\n            }\n            base.OnDisable();\n        }\n\n        //None of the ModelImporter sub editors support multi preview\n        public override bool HasPreviewGUI()\n        {\n            return base.HasPreviewGUI() && targets.Length < 2;\n        }\n\n        public override GUIContent GetPreviewTitle()\n        {\n            var tab = activeTab as ModelImporterClipEditor;\n            if (tab != null)\n                return new GUIContent(tab.selectedClipName);\n\n            return base.GetPreviewTitle();\n        }\n\n        // Only show the imported GameObject when the Model tab is active\n        public override bool showImportedObject { get { return activeTab is SpeedTreeImporterModelEditor; } }\n\n        internal IEnumerable<SpeedTreeImporter> importers\n        {\n            get { return targets.Cast<SpeedTreeImporter>(); }\n        }\n\n        internal bool upgradeMaterials\n        {\n            get { return importers.Any(i => i.materialsShouldBeRegenerated); }\n        }\n\n        internal GUIContent GetGenButtonText(bool modified, bool upgrade)\n        {\n            if (modified || upgrade)\n            {\n                if (m_MaterialLocation.intValue == (int)SpeedTreeImporter.MaterialLocation.External)\n                    return Styles.ApplyAndGenerate;\n                else\n                    return Styles.ApplyAndGenerateRemapped;\n            }\n            else\n            {\n                if (m_MaterialLocation.intValue == (int)SpeedTreeImporter.MaterialLocation.External)\n                    return Styles.Regenerate;\n                else\n                    return Styles.RegenerateRemapped;\n            }\n        }\n\n        protected override bool OnApplyRevertGUI()\n        {\n            bool applied = base.OnApplyRevertGUI();\n\n            bool hasModified = HasModified();\n            if (tabs == null) // Hitting apply, we lose the tabs object within base.OnApplyRevertGUI()\n            {\n                if(hasModified)\n                    Apply();\n                return applied;\n            }\n\n            bool doMatsHaveDifferentShaders = (tabs[0] as SpeedTreeImporterModelEditor).doMaterialsHaveDifferentShader;\n\n            if (HasRemappedMaterials() || doMatsHaveDifferentShaders)\n            {\n                // Force material upgrade when a custom render pipeline is active so that render pipeline-specific material\n                // modifications may be applied.\n                bool upgrade = upgradeMaterials || (UnityEngine.Rendering.GraphicsSettings.currentRenderPipeline != null);\n                if (GUILayout.Button(GetGenButtonText(hasModified, upgrade)))\n                {\n                    // Apply the changes and generate the materials before importing so that asset previews are up-to-date.\n                    if (hasModified)\n                        Apply();\n\n                    if (upgrade)\n                    {\n                        foreach (var importer in importers)\n                            importer.SetMaterialVersionToCurrent();\n                    }\n\n                    GenerateMaterials();\n\n                    if (hasModified || upgrade)\n                    {\n                        SaveChanges();\n                        applied = true;\n                    }\n                }\n            }\n\n            return applied;\n        }\n\n        private void GenerateMaterials()\n        {\n            var matFolders = importers.Where(im => im.materialLocation == SpeedTreeImporter.MaterialLocation.External).Select(im => im.materialFolderPath).ToList();\n            var guids = AssetDatabase.FindAssets(\"t:Material\", matFolders.ToArray());\n            var paths = guids.Select(guid => AssetDatabase.GUIDToAssetPath(guid)).ToList();\n\n            var importersWithEmbeddedMaterials = importers.Where(im => im.materialLocation == SpeedTreeImporter.MaterialLocation.InPrefab);\n            foreach (var importer in importersWithEmbeddedMaterials)\n            {\n                var remappedAssets = importer.GetExternalObjectMap();\n                var materials = remappedAssets.Where(kv => kv.Value is Material && kv.Value != null).Select(kv => kv.Value);\n                foreach (var material in materials)\n                {\n                    var path = AssetDatabase.GetAssetPath(material);\n                    paths.Add(path);\n                    matFolders.Add(FileUtil.DeleteLastPathNameComponent(path));\n                }\n            }\n\n            bool doGenerate = true;\n            if (paths.Count > 0)\n                doGenerate = AssetDatabase.MakeEditable(paths.ToArray(), $\"Materials will be checked out in:\\n{string.Join(\"\\n\", matFolders.ToArray())}\");\n\n            if (doGenerate)\n            {\n                foreach (var importer in importers)\n                    importer.GenerateMaterials();\n            }\n        }\n\n        private bool HasRemappedMaterials()\n        {\n            if (m_MaterialLocation.intValue == 0)\n            {\n                m_HasRemappedMaterials = true;\n            }\n\n            if (m_Materials.arraySize == 0)\n                return true;\n\n            // if the m_ExternalObjecs map has any unapplied changes, keep the state of the button as is\n            if (serializedObject.hasModifiedProperties)\n                return m_HasRemappedMaterials;\n\n            m_HasRemappedMaterials = true;\n            foreach (var importer in importers)\n            {\n                var externalObjectMap = importer.GetExternalObjectMap();\n                var materialsList = importer.sourceMaterials;\n\n                int remappedMaterialCount = 0;\n                foreach (var entry in externalObjectMap)\n                {\n                    if (entry.Key.type == typeof(Material) && Array.Exists(materialsList, x => x.name == entry.Key.name))\n                        ++remappedMaterialCount;\n                }\n\n                m_HasRemappedMaterials = m_HasRemappedMaterials && remappedMaterialCount != 0;\n                if (!m_HasRemappedMaterials)\n                    break;\n            }\n            return m_HasRemappedMaterials;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ImportSettings/SpeedTreeImporterMaterialEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.AssetImporters;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class SpeedTreeImporterMaterialEditor : BaseSpeedTreeImporterTabUI\n    {\n        private static class Styles\n        {\n            public static GUIContent MaterialLocation = EditorGUIUtility.TrTextContent(\"Location\");\n            public static GUIContent[] MaterialLocationOpt =\n            {\n                EditorGUIUtility.TrTextContent(\"Use External Materials (Legacy)\", \"Use external materials if found in the project.\"),\n                EditorGUIUtility.TrTextContent(\"Use Embedded Materials\", \"Embed the material inside the imported asset.\")\n            };\n\n            public static GUIContent RemapOptions = EditorGUIUtility.TrTextContent(\"On Demand Remap\");\n            public static GUIContent RemapMaterialsInProject = EditorGUIUtility.TrTextContent(\"Search and Remap...\", \"Click on this button to search and remap the materials from the project.\");\n\n            public static GUIContent ExternalMaterialMappings = EditorGUIUtility.TrTextContent(\"Remapped Materials\", \"External materials to use for each embedded material.\");\n            public static GUIContent NoMaterialMappingsHelp = EditorGUIUtility.TrTextContent(\"Re-import the asset to see the list of used materials.\");\n\n            public static GUIContent Materials = EditorGUIUtility.TrTextContent(\"Materials\");\n            public static GUIContent ExtractEmbeddedMaterials = EditorGUIUtility.TrTextContent(\"Extract Materials...\", \"Click on this button to extract the embedded materials.\");\n\n            public static GUIContent InternalMaterialHelp = EditorGUIUtility.TrTextContent(\"Materials are embedded inside the imported asset.\");\n            public static GUIContent MaterialAssignmentsHelp = EditorGUIUtility.TrTextContent(\"Material assignments can be remapped below.\");\n\n            public static GUIContent ExternalMaterialSearchHelp = EditorGUIUtility.TrTextContent(\"Searches the user provided directory and matches the materials that share the same name and LOD with the originally imported material.\");\n\n            public static GUIContent SelectMaterialFolder = EditorGUIUtility.TrTextContent(\"Select Materials Folder\");\n        }\n\n        private SerializedProperty m_MaterialLocation;\n        private SerializedProperty m_Materials;\n        private SerializedProperty m_ExternalObjects;\n\n        private SerializedProperty m_SupportsEmbeddedMaterials;\n\n        private bool m_ShowMaterialRemapOptions = false;\n        private bool m_HasEmbeddedMaterials = false;\n\n        public SpeedTreeImporterMaterialEditor(AssetImporterEditor panelContainer)\n            : base(panelContainer)\n        {}\n\n        private bool HasEmbeddedMaterials()\n        {\n            if (m_Materials.arraySize == 0)\n                return false;\n\n            // if the m_ExternalObjecs map has any unapplied changes, keep the state of the button as is\n            if (m_ExternalObjects.serializedObject.hasModifiedProperties)\n                return m_HasEmbeddedMaterials;\n\n            m_HasEmbeddedMaterials = true;\n            foreach (var t in m_ExternalObjects.serializedObject.targetObjects)\n            {\n                var importer = t as SpeedTreeImporter;\n                var externalObjectMap = importer.GetExternalObjectMap();\n                var materialsList = importer.sourceMaterials;\n\n                int remappedMaterialCount = 0;\n                foreach (var entry in externalObjectMap)\n                {\n                    if (entry.Key.type == typeof(Material) && Array.Exists(materialsList, x => x.name == entry.Key.name))\n                        ++remappedMaterialCount;\n                }\n\n                m_HasEmbeddedMaterials = m_HasEmbeddedMaterials && remappedMaterialCount != materialsList.Length;\n            }\n            return m_HasEmbeddedMaterials;\n        }\n\n        internal override void OnEnable()\n        {\n            m_MaterialLocation = serializedObject.FindProperty(\"m_MaterialLocation\");\n\n            m_Materials = serializedObject.FindProperty(\"m_Materials\");\n            m_ExternalObjects = serializedObject.FindProperty(\"m_ExternalObjects\");\n\n            m_SupportsEmbeddedMaterials = serializedObject.FindProperty(\"m_SupportsEmbeddedMaterials\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            ShowMaterialGUI();\n        }\n\n        private void ShowMaterialGUI()\n        {\n            serializedObject.UpdateIfRequiredOrScript();\n\n            EditorGUILayout.Popup(m_MaterialLocation, Styles.MaterialLocationOpt, Styles.MaterialLocation);\n\n            string materialHelp = string.Empty;\n            if (!m_MaterialLocation.hasMultipleDifferentValues)\n            {\n                if (m_Materials.arraySize > 0 && HasEmbeddedMaterials())\n                {\n                    // we're generating materials inside the prefab\n                    materialHelp = Styles.InternalMaterialHelp.text;\n                }\n\n                if (targets.Length == 1 && m_Materials.arraySize > 0 && m_MaterialLocation.intValue != 0)\n                {\n                    materialHelp += \" \" + Styles.MaterialAssignmentsHelp.text;\n                }\n\n                // display the extract buttons\n                if (m_MaterialLocation.intValue != 0)\n                {\n                    if (ExtractMaterialsGUI())\n                        return;\n                }\n            }\n\n            if (!string.IsNullOrEmpty(materialHelp))\n            {\n                EditorGUILayout.HelpBox(materialHelp, MessageType.Info);\n            }\n\n            if ((targets.Length == 1 || m_SupportsEmbeddedMaterials.hasMultipleDifferentValues == false) && m_SupportsEmbeddedMaterials.boolValue == false\n                && m_MaterialLocation.intValue != 0 && !m_MaterialLocation.hasMultipleDifferentValues)\n            {\n                EditorGUILayout.Space();\n                EditorGUILayout.HelpBox(Styles.NoMaterialMappingsHelp.text, MessageType.Warning);\n            }\n\n            // The material remap list\n            if (targets.Length == 1 && m_Materials.arraySize > 0 && m_MaterialLocation.intValue != 0 && !m_MaterialLocation.hasMultipleDifferentValues)\n            {\n                GUILayout.Label(Styles.ExternalMaterialMappings, EditorStyles.boldLabel);\n\n                if (MaterialRemapOptons())\n                    return;\n\n                // The list of material names is immutable, whereas the map of external objects can change based on user actions.\n                // For each material name, map the external object associated with it.\n                // The complexity comes from the fact that we may not have an external object in the map, so we can't make a property out of it\n                for (int materialIdx = 0; materialIdx < m_Materials.arraySize; ++materialIdx)\n                {\n                    var id = m_Materials.GetArrayElementAtIndex(materialIdx);\n                    var name = id.FindPropertyRelative(\"name\").stringValue;\n                    var type = id.FindPropertyRelative(\"type\").stringValue;\n                    var assembly = id.FindPropertyRelative(\"assembly\").stringValue;\n\n                    SerializedProperty materialProp = null;\n                    Material material = null;\n                    var propertyIdx = 0;\n\n                    for (int externalObjectIdx = 0, count = m_ExternalObjects.arraySize; externalObjectIdx < count; ++externalObjectIdx)\n                    {\n                        var pair = m_ExternalObjects.GetArrayElementAtIndex(externalObjectIdx);\n                        var externalName = pair.FindPropertyRelative(\"first.name\").stringValue;\n                        var externalType = pair.FindPropertyRelative(\"first.type\").stringValue;\n\n                        if (externalName == name && externalType == type)\n                        {\n                            materialProp = pair.FindPropertyRelative(\"second\");\n                            material = materialProp != null ? materialProp.objectReferenceValue as Material : null;\n                            propertyIdx = externalObjectIdx;\n                            break;\n                        }\n                    }\n\n                    GUIContent nameLabel = EditorGUIUtility.TextContent(name);\n                    nameLabel.tooltip = name;\n                    if (materialProp != null)\n                    {\n                        EditorGUI.BeginChangeCheck();\n                        EditorGUILayout.ObjectField(materialProp, typeof(Material), nameLabel);\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            if (materialProp.objectReferenceValue == null)\n                            {\n                                m_ExternalObjects.DeleteArrayElementAtIndex(propertyIdx);\n                            }\n                        }\n                    }\n                    else\n                    {\n                        EditorGUI.BeginChangeCheck();\n                        material = EditorGUILayout.ObjectField(nameLabel, material, typeof(Material), false) as Material;\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            if (material != null)\n                            {\n                                var newIndex = m_ExternalObjects.arraySize++;\n                                var pair = m_ExternalObjects.GetArrayElementAtIndex(newIndex);\n                                pair.FindPropertyRelative(\"first.name\").stringValue = name;\n                                pair.FindPropertyRelative(\"first.type\").stringValue = type;\n                                pair.FindPropertyRelative(\"first.assembly\").stringValue = assembly;\n                                pair.FindPropertyRelative(\"second\").objectReferenceValue = material;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        private bool ExtractMaterialsGUI()\n        {\n            using (new EditorGUILayout.HorizontalScope())\n            {\n                EditorGUILayout.PrefixLabel(Styles.Materials);\n                using (new EditorGUI.DisabledScope(!HasEmbeddedMaterials()))\n                {\n                    if (GUILayout.Button(Styles.ExtractEmbeddedMaterials))\n                    {\n                        // use the first target for selecting the destination folder, but apply that path for all targets\n                        string destinationPath = (target as SpeedTreeImporter).assetPath;\n                        destinationPath = EditorUtility.SaveFolderPanel(Styles.SelectMaterialFolder.text,\n                            FileUtil.DeleteLastPathNameComponent(destinationPath), \"\");\n                        if (string.IsNullOrEmpty(destinationPath))\n                        {\n                            // cancel the extraction if the user did not select a folder\n                            return false;\n                        }\n                        destinationPath = FileUtil.GetProjectRelativePath(destinationPath);\n\n                        try\n                        {\n                            // batch the extraction of the textures\n                            AssetDatabase.StartAssetEditing();\n\n                            PrefabUtility.ExtractMaterialsFromAsset(targets, destinationPath);\n                        }\n                        finally\n                        {\n                            AssetDatabase.StopAssetEditing();\n                        }\n\n                        // AssetDatabase.StopAssetEditing() invokes OnEnable(), which invalidates all the serialized properties, so we must return.\n                        return true;\n                    }\n                }\n            }\n\n            return false;\n        }\n\n        private bool MaterialRemapOptons()\n        {\n            m_ShowMaterialRemapOptions = EditorGUILayout.Foldout(m_ShowMaterialRemapOptions, Styles.RemapOptions);\n            if (m_ShowMaterialRemapOptions)\n            {\n                EditorGUI.indentLevel++;\n\n                EditorGUILayout.HelpBox(Styles.ExternalMaterialSearchHelp.text, MessageType.Info);\n\n                EditorGUI.indentLevel--;\n\n                using (new EditorGUILayout.HorizontalScope())\n                {\n                    GUILayout.FlexibleSpace();\n                    using (new EditorGUI.DisabledScope(assetTarget == null))\n                    {\n                        if (GUILayout.Button(Styles.RemapMaterialsInProject))\n                        {\n                            bool bStartedAssetEditing = false;\n                            try\n                            {\n                                foreach (var t in targets)\n                                {\n                                    SpeedTreeImporter importer = t as SpeedTreeImporter;\n                                    string folderToSearch = importer.materialFolderPath;\n                                    folderToSearch = EditorUtility.OpenFolderPanel(Styles.SelectMaterialFolder.text, importer.materialFolderPath, \"\");\n\n                                    bool bUserSelectedAFolder = folderToSearch != \"\"; // folderToSearch is empty if the user cancels the window\n                                    if (bUserSelectedAFolder)\n                                    {\n                                        string projectRelativePath = FileUtil.GetProjectRelativePath(folderToSearch);\n                                        bool bRelativePathIsNotEmpty = projectRelativePath != \"\";\n                                        if (bRelativePathIsNotEmpty)\n                                        {\n                                            AssetDatabase.StartAssetEditing();\n                                            bStartedAssetEditing = true;\n                                            importer.SearchAndRemapMaterials(projectRelativePath);\n\n                                            AssetDatabase.WriteImportSettingsIfDirty(importer.assetPath);\n                                            AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate);\n                                        }\n                                        else\n                                        {\n                                            Debug.LogWarning(\"Selected folder is outside of the project's folder hierarchy, please provide a folder from the project.\\n\");\n                                        }\n                                    }\n                                }\n                            }\n                            finally\n                            {\n                                if (bStartedAssetEditing)\n                                {\n                                    AssetDatabase.StopAssetEditing();\n                                }\n                            }\n\n                            return true;\n                        }\n                    }\n                }\n                EditorGUILayout.Space();\n            }\n\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ImportSettings/SpeedTreeImporterModelEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor.AnimatedValues;\nusing UnityEditor.AssetImporters;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    internal class SpeedTreeImporterModelEditor : BaseSpeedTreeImporterTabUI\n    {\n        private class Styles\n        {\n            public static GUIContent MeshesHeader = EditorGUIUtility.TrTextContent(\"Meshes\");\n            public static GUIContent UnitConversion = EditorGUIUtility.TrTextContent(\"Unit Conversion\", \"Select the unit conversion to apply to the imported SpeedTree asset\");\n            public static GUIContent ScaleFactor = EditorGUIUtility.TrTextContent(\"Scale Factor\", \"How much to scale the tree model, interpreting the exported units as meters. Must be positive.\");\n\n            public static GUIContent EnableColorVariation = EditorGUIUtility.TrTextContent(\"Color Variation\", \"Color is determined by linearly interpolating between the Main Color & Color Variation values based on the world position X, Y and Z values\");\n            public static GUIContent EnableBump = EditorGUIUtility.TrTextContent(\"Normal Map\", \"Enable normal mapping (aka Bump mapping).\");\n            public static GUIContent EnableSubsurface = EditorGUIUtility.TrTextContent(\"Subsurface Scattering\", \"Enable subsurface scattering effects.\");\n            public static GUIContent MainColor = EditorGUIUtility.TrTextContent(\"Main Color\", \"The color modulating the diffuse lighting component.\");\n            public static GUIContent HueVariation = EditorGUIUtility.TrTextContent(\"Variation Color (RGB), Intensity (A)\", \"Tint the tree with the Variation Color\");\n            public static GUIContent AlphaTestRef = EditorGUIUtility.TrTextContent(\"Alpha Cutoff\", \"The alpha-test reference value.\");\n\n            public static GUIContent LightingHeader = EditorGUIUtility.TrTextContent(\"Lighting\");\n            public static GUIContent CastShadows = EditorGUIUtility.TrTextContent(\"Cast Shadows\", \"The tree casts shadow\");\n            public static GUIContent ReceiveShadows = EditorGUIUtility.TrTextContent(\"Receive Shadows\", \"The tree receives shadow\");\n            public static GUIContent UseLightProbes = EditorGUIUtility.TrTextContent(\"Light Probes\", \"The tree uses light probe for lighting\"); // TODO: update help text\n            public static GUIContent UseReflectionProbes = EditorGUIUtility.TrTextContent(\"Reflection Probes\", \"The tree uses reflection probe for rendering\"); // TODO: update help text\n\n            public static GUIContent AdditionalSettingsHeader = EditorGUIUtility.TrTextContent(\"Additional Settings\");\n            public static GUIContent MotionVectorMode = EditorGUIUtility.TrTextContent(\"Motion Vectors\", \"Motion vector mode to set for the mesh renderer of each LOD object\");\n            public static GUIContent GenerateRigidBody = EditorGUIUtility.TrTextContent(\"Generate Rigidbody\", \"Generates a Rigidbody in the root game object\");\n            public static GUIContent GenerateColliders  = EditorGUIUtility.TrTextContent(\"Generate Colliders\", \"Generates mesh colliders for the LOD objects\");\n\n            public static GUIContent WindHeader = EditorGUIUtility.TrTextContent(\"Wind\");\n            public static GUIContent WindQuality = EditorGUIUtility.TrTextContent(\"Wind Quality\", \"Controls the wind effect's quality.\");\n\n            public static GUIContent LODHeader = EditorGUIUtility.TrTextContent(\"LOD\");\n            public static GUIContent ResetLOD = EditorGUIUtility.TrTextContent(\"Reset LOD to...\", \"Unify the LOD settings for all selected assets\");\n            public static GUIContent SmoothLOD = EditorGUIUtility.TrTextContent(\"Smooth Transitions\", \"Toggles smooth LOD transitions\");\n            public static GUIContent AnimateCrossFading = EditorGUIUtility.TrTextContent(\"Animate Cross-fading\", \"Cross-fading is animated instead of being calculated by distance\");\n            public static GUIContent CrossFadeWidth = EditorGUIUtility.TrTextContent(\"Crossfade Width\", \"Proportion of the last 3D mesh LOD region width which is used for cross-fading to billboard tree\");\n            public static GUIContent FadeOutWidth = EditorGUIUtility.TrTextContent(\"Fade Out Width\", \"Proportion of the billboard LOD region width which is used for fading out the billboard\");\n\n            public static GUIContent EnableLodCustomizationsWarn = EditorGUIUtility.TrTextContent(\"Customizing LOD options may help with tuning the GPU performance but will likely negatively impact the instanced draw batching, i.e. CPU performance.\\nPlease use the per-LOD customizations with careful memory and performance profiling for both CPU and GPU and remember that these options are a trade-off rather than a free win.\");\n            public static GUIContent BillboardSettingsHelp = EditorGUIUtility.TrTextContent(\"Billboard options are separate from the 3D model options shown above.\\nChange the options below for influencing billboard rendering.\");\n\n            public static GUIContent ApplyAndGenerate = EditorGUIUtility.TrTextContent(\"Apply & Generate Materials\", \"Apply current importer settings and generate asset materials with the new settings.\");\n            public static GUIContent Regenerate = EditorGUIUtility.TrTextContent(\"Regenerate Materials\", \"Regenerate materials using the current import settings.\");\n\n            public static GUIContent[] ReflectionProbeUsageNames = (Enum.GetNames(typeof(ReflectionProbeUsage)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray()).Select(x => new GUIContent(x)).ToArray();\n            public static GUIContent[] WindQualityNames = SpeedTreeImporter.windQualityNames.Select(s => new GUIContent(s)).ToArray();\n            public static GUIContent[] UnitConversionNames =\n            {\n                  new GUIContent(\"Leave As Is\")\n                , new GUIContent(\"ft to m\")\n                , new GUIContent(\"cm to m\")\n                , new GUIContent(\"inch to m\")\n                , new GUIContent(\"Custom\")\n            };\n            public static GUIContent[] MotionVectorModeNames =  // Match SharedRendererDataTypes.h / enum MotionVectorGenerationMode\n            {\n                  new GUIContent(\"Camera Motion Only\")  // kMotionVectorCamera = 0,    // Use camera motion for motion vectors\n                , new GUIContent(\"Per Object Motion\")   // kMotionVectorObject,        // Use a per object motion vector pass for this object\n                , new GUIContent(\"Force No Motion\")     // kMotionVectorForceNoMotion, // Force no motion for this object (0 into motion buffer)\n            };\n        }\n\n        //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n        // DATA\n        //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n        // mesh\n        private SerializedProperty m_ScaleFactor;\n        private SerializedProperty m_UnitConversionEnumValue;\n        private SerializedProperty m_MotionVectorModeEnumValue;\n\n        // material\n        private SerializedProperty m_MainColor;\n        private SerializedProperty m_EnableHueVariation;\n        private SerializedProperty m_HueVariation;\n        private SerializedProperty m_AlphaTestRef;\n        private SerializedProperty m_EnableBumpMapping;\n        private SerializedProperty m_EnableSubsurfaceScattering;\n\n        // lighting\n        private SerializedProperty m_EnableShadowCasting;\n        private SerializedProperty m_EnableShadowReceiving;\n        private SerializedProperty m_EnableLightProbeUsage;\n        private SerializedProperty m_ReflectionProbeUsage;\n\n        // wind\n        private SerializedProperty m_HighestWindQuality;\n        private SerializedProperty m_SelectedWindQuality;\n\n        // lod\n        private SerializedProperty m_LODSettings;\n        private SerializedProperty m_EnableSmoothLOD;\n        private SerializedProperty m_AnimateCrossFading;\n        private SerializedProperty m_BillboardTransitionCrossFadeWidth;\n        private SerializedProperty m_FadeOutWidth;\n\n        // physics\n        private SerializedProperty m_GenerateRigidbody;\n        private SerializedProperty m_GenerateColliders;\n\n        private bool m_AllAreV8;\n        private bool m_AllAreNotV8;\n\n        // LODGroup GUI\n        private int m_SelectedLODSlider = -1;\n        private int m_SelectedLODRange = 0;\n        private SavedBool[] m_LODGroupFoldoutHeaderValues = null;\n        private Texture2D[] m_LODColorTextures;\n\n        private readonly AnimBool m_ShowSmoothLODOptions = new AnimBool();\n        private readonly AnimBool m_ShowCrossFadeWidthOptions = new AnimBool();\n\n        public bool doMaterialsHaveDifferentShader = false;\n\n        //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n        // INTERFACE\n        //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n        public SpeedTreeImporterModelEditor(AssetImporterEditor panelContainer)\n            : base(panelContainer)\n        {}\n\n        internal override void OnEnable()\n        {\n            m_ScaleFactor = serializedObject.FindProperty(\"m_ScaleFactor\");\n            m_UnitConversionEnumValue = serializedObject.FindProperty(\"m_UnitConversionEnumValue\");\n            m_MotionVectorModeEnumValue = serializedObject.FindProperty(\"m_MotionVectorModeEnumValue\");\n\n            m_MainColor = serializedObject.FindProperty(\"m_MainColor\");\n            m_EnableHueVariation = serializedObject.FindProperty(\"m_EnableHueVariation\");\n            m_HueVariation = serializedObject.FindProperty(\"m_HueVariation\");\n            m_AlphaTestRef = serializedObject.FindProperty(\"m_AlphaTestRef\");\n            m_EnableBumpMapping = serializedObject.FindProperty(\"m_EnableBumpMapping\");\n            m_EnableSubsurfaceScattering = serializedObject.FindProperty(\"m_EnableSubsurfaceScattering\");\n\n            m_EnableShadowCasting = serializedObject.FindProperty(\"m_EnableShadowCasting\");\n            m_EnableShadowReceiving = serializedObject.FindProperty(\"m_EnableShadowReceiving\");\n            m_EnableLightProbeUsage = serializedObject.FindProperty(\"m_EnableLightProbes\");\n            m_ReflectionProbeUsage = serializedObject.FindProperty(\"m_ReflectionProbeEnumValue\");\n\n            m_HighestWindQuality = serializedObject.FindProperty(\"m_BestWindQuality\");\n            m_SelectedWindQuality = serializedObject.FindProperty(\"m_SelectedWindQuality\");\n\n            m_LODSettings = serializedObject.FindProperty(\"m_LODSettings\");\n            m_EnableSmoothLOD = serializedObject.FindProperty(\"m_EnableSmoothLODTransition\");\n            m_AnimateCrossFading = serializedObject.FindProperty(\"m_AnimateCrossFading\");\n            m_BillboardTransitionCrossFadeWidth = serializedObject.FindProperty(\"m_BillboardTransitionCrossFadeWidth\");\n            m_FadeOutWidth = serializedObject.FindProperty(\"m_FadeOutWidth\");\n\n            m_GenerateRigidbody = serializedObject.FindProperty(\"m_GenerateRigidbody\");\n            m_GenerateColliders = serializedObject.FindProperty(\"m_GenerateColliders\");\n\n            m_ShowSmoothLODOptions.value = m_EnableSmoothLOD.hasMultipleDifferentValues || m_EnableSmoothLOD.boolValue;\n            m_ShowSmoothLODOptions.valueChanged.AddListener(Repaint);\n            m_ShowCrossFadeWidthOptions.value = m_AnimateCrossFading.hasMultipleDifferentValues || !m_AnimateCrossFading.boolValue;\n            m_ShowCrossFadeWidthOptions.valueChanged.AddListener(Repaint);\n\n            m_AllAreV8 = importers.All(im => im.isV8);\n            m_AllAreNotV8 = importers.All(im => !im.isV8);\n\n            ResetFoldoutLists();\n        }\n\n        internal override void OnDisable()\n        {\n            base.OnDisable();\n\n            m_ShowSmoothLODOptions.valueChanged.RemoveListener(Repaint);\n            m_ShowCrossFadeWidthOptions.valueChanged.RemoveListener(Repaint);\n        }\n\n        internal List<LODGroupGUI.LODInfo> GetLODInfoArray(Rect area)\n        {\n            int lodCount = m_LODSettings.arraySize;\n            return LODGroupGUI.CreateLODInfos(\n                lodCount, area,\n                i => i == lodCount - 1 && (target as SpeedTreeImporter).hasBillboard ? \"Billboard\" : String.Format(\"LOD {0}\", i),\n                i => m_LODSettings.GetArrayElementAtIndex(i).FindPropertyRelative(\"height\").floatValue);\n        }\n        private void ExpandSelectedHeaderAndCloseRemaining(int index)\n        {\n            // need this to safeguard against drag & drop on Culled section\n            // as that sets the LOD index to 8 which is outside of the total\n            // allowed LOD range\n            if (index >= m_LODSettings.arraySize)\n                return;\n\n            Array.ForEach(m_LODGroupFoldoutHeaderValues, el => el.value = false);\n            m_LODGroupFoldoutHeaderValues[index].value = true;\n        }\n        void InitAndSetFoldoutLabelTextures()\n        {\n            m_LODColorTextures = new Texture2D[m_LODSettings.arraySize];\n            for (int i = 0; i < m_LODColorTextures.Length; i++)\n            {\n                m_LODColorTextures[i] = new Texture2D(1, 1);\n                m_LODColorTextures[i].SetPixel(0, 0, LODGroupGUI.kLODColors[i]);\n            }\n        }\n        void ResetFoldoutLists()\n        {\n            int lodArraySize = m_LODSettings.arraySize;\n            m_LODGroupFoldoutHeaderValues = new SavedBool[lodArraySize];\n            for (int i = 0; i < lodArraySize; i++)\n            {\n                m_LODGroupFoldoutHeaderValues[i] = new SavedBool($\"{target.GetType()}.lodFoldout{i}\", false);\n            }\n            InitAndSetFoldoutLabelTextures();\n        }\n\n        public bool HasSameLODConfig()\n        {\n            if (serializedObject.FindProperty(\"m_HasBillboard\").hasMultipleDifferentValues)\n                return false;\n            if (m_LODSettings.FindPropertyRelative(\"Array.size\").hasMultipleDifferentValues)\n                return false;\n            for (int i = 0; i < m_LODSettings.arraySize; ++i)\n            {\n                if (m_LODSettings.GetArrayElementAtIndex(i).FindPropertyRelative(\"height\").hasMultipleDifferentValues)\n                    return false;\n            }\n            return true;\n        }\n\n        public bool CanUnifyLODConfig()\n        {\n            // differs only in LOD heights\n            return !serializedObject.FindProperty(\"m_HasBillboard\").hasMultipleDifferentValues\n                && !m_LODSettings.FindPropertyRelative(\"Array.size\").hasMultipleDifferentValues;\n        }\n\n        private bool DoMaterialsHaveDifferentShader()\n        {\n            if(assetTargets is null || assetTargets.Length == 0)\n            {\n                return false;\n            }\n\n            // Check whether the imported asset is a valid one.\n            // GameObject cast will fail for non-geometry SpeedTree files\n            // such as collections on some v7 assets. If the object is not valid,\n            // the IEnumerable<GameObject>::ToArray() function call below will throw\n            // an InvalidType exception, hence we do an explicit source check here.\n            GameObject obj = assetTargets[0] as GameObject;\n            if (obj == null)\n            {\n                return false;\n            }\n\n            var prefabs = assetTargets?.Cast<GameObject>()?.ToArray();\n            var importerArray = importers.ToArray();\n\n            // In tests assetTargets can become null\n            for (int i = 0; i < Math.Min(importerArray.Length, prefabs?.Length ?? 0); ++i)\n            {\n                var im = importerArray[i];\n                var defaultShader = im.defaultShader;\n                var defaultBillboardShader = im.defaultBillboardShader;\n\n                foreach (var mr in prefabs[i].transform.GetComponentsInChildren<MeshRenderer>())\n                {\n                    foreach (var mat in mr.sharedMaterials)\n                    {\n                        if (mat?.shader != defaultShader)\n                            return true;\n                    }\n                }\n\n                if (defaultBillboardShader != null)\n                {\n                    foreach (var br in prefabs[i].transform.GetComponentsInChildren<BillboardRenderer>())\n                    {\n                        if (br.billboard.material?.shader != defaultBillboardShader)\n                            return true;\n                    }\n                }\n            }\n\n            return false;\n        }\n\n        private void ShowAdditionalSettingsGUI()\n        {\n            // motion vectors\n            GUILayout.Label(Styles.AdditionalSettingsHeader, EditorStyles.boldLabel);\n            EditorGUILayout.Popup(m_MotionVectorModeEnumValue, Styles.MotionVectorModeNames, Styles.MotionVectorMode);\n\n            EditorGUILayout.Space();\n\n            GUILayout.Label(\"Physics\", EditorStyles.boldLabel);\n            EditorGUILayout.PropertyField(m_GenerateRigidbody , Styles.GenerateRigidBody);\n            EditorGUILayout.PropertyField(m_GenerateColliders, Styles.GenerateColliders);\n\n            EditorGUILayout.Space();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            // settings GUIs\n            ShowMeshGUI();\n            ShowMaterialGUI();\n            ShowLightingGUI();\n            ShowAdditionalSettingsGUI();\n            ShowWindGUI();\n            ShowLODGUI();\n\n            EditorGUILayout.Space();\n\n            bool materialsNeedToBeUpgraded = upgradeMaterials;\n            doMaterialsHaveDifferentShader = !materialsNeedToBeUpgraded && DoMaterialsHaveDifferentShader();\n\n            if (materialsNeedToBeUpgraded)\n            {\n                EditorGUILayout.HelpBox(\n                    String.Format(\"SpeedTree materials need to be upgraded. Please back them up (if modified manually) then hit the \\\"{0}\\\" button below.\", Styles.ApplyAndGenerate.text)\n                    , MessageType.Warning\n                );\n            }\n\n            if (doMaterialsHaveDifferentShader)\n            {\n                EditorGUILayout.HelpBox(\n                    String.Format(\"There is a different SpeedTree shader provided by the current render pipeline which probably is more suitable for rendering. Hit the \\\"{0}\\\" button to regenerate the materials.\"\n                        , (panelContainer as SpeedTreeImporterInspector).GetGenButtonText(HasModified()\n                        , materialsNeedToBeUpgraded).text\n                    )\n                    , MessageType.Warning\n                );\n            }\n        }\n\n        private void ShowMeshGUI()\n        {\n            GUILayout.Label(Styles.MeshesHeader, EditorStyles.boldLabel);\n\n            EditorGUILayout.Popup(m_UnitConversionEnumValue, Styles.UnitConversionNames, Styles.UnitConversion);\n\n            bool bShowCustomScaleFactor = m_UnitConversionEnumValue.intValue == Styles.UnitConversionNames.Length-1;\n            if (bShowCustomScaleFactor)\n            {\n                EditorGUILayout.PropertyField(m_ScaleFactor, Styles.ScaleFactor);\n                if (m_ScaleFactor.floatValue < 0f)\n                {\n                    m_ScaleFactor.floatValue = 0f;\n                }\n                if (m_ScaleFactor.floatValue == 0f)\n                {\n                    EditorGUILayout.HelpBox(\"Scale factor must be positive.\", MessageType.Warning);\n                }\n            }\n\n            EditorGUILayout.Space();\n        }\n\n        bool ShouldRenderHueVariationDropdown()\n        {\n            SpeedTreeImporter importer = importers.First();\n\n            if (importer.enableHueByDefault)\n            {\n                return true;\n            }\n\n            for (int i = 0; i < importer.enableHue.Length; ++i)\n            {\n                if (importer.enableSettingOverride[i] && importer.enableHue[i])\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        public void ShowMaterialGUI()\n        {\n            EditorGUILayout.LabelField(\"Material\", EditorStyles.boldLabel);\n\n            EditorGUILayout.PropertyField(m_MainColor, Styles.MainColor);\n            EditorGUILayout.PropertyField(m_EnableHueVariation, Styles.EnableColorVariation);\n\n\n            if (ShouldRenderHueVariationDropdown())\n            {\n                EditorGUILayout.PropertyField(m_HueVariation, Styles.HueVariation);\n            }\n\n            if (m_AllAreNotV8)\n                EditorGUILayout.Slider(m_AlphaTestRef, 0f, 1f, Styles.AlphaTestRef);\n\n            EditorGUILayout.PropertyField(m_EnableBumpMapping, Styles.EnableBump);\n            EditorGUILayout.PropertyField(m_EnableSubsurfaceScattering, Styles.EnableSubsurface);\n\n            EditorGUILayout.Space();\n        }\n\n        private void ShowLightingGUI()\n        {\n            GUILayout.Label(Styles.LightingHeader, EditorStyles.boldLabel);\n\n            EditorGUILayout.PropertyField(m_EnableShadowCasting, Styles.CastShadows);\n\n            // from the docs page: https://docs.unity3d.com/Manual/SpeedTree.html\n            // Known issues: As with any other renderer, the Receive Shadows option has no effect while using deferred rendering.\n            // TODO: test and conditionally expose this field\n            using (new EditorGUI.DisabledScope(!UnityEngine.Rendering.SupportedRenderingFeatures.active.receiveShadows))\n            {\n                EditorGUILayout.PropertyField(m_EnableShadowReceiving, Styles.ReceiveShadows);\n            }\n\n            EditorGUILayout.PropertyField(m_EnableLightProbeUsage, Styles.UseLightProbes);\n\n\n            EditorGUILayout.Space();\n        }\n\n\n        private void ShowWindGUI()\n        {\n            GUILayout.Label(Styles.WindHeader, EditorStyles.boldLabel);\n            int NumAvailableWindQualityOptions = 1 + m_HighestWindQuality.intValue; // 0 is None, we want at least 1 value\n            ArraySegment<GUIContent> availableWindQualityOptions = new ArraySegment<GUIContent>(Styles.WindQualityNames, 0, NumAvailableWindQualityOptions);\n            EditorGUILayout.Popup(m_SelectedWindQuality, availableWindQualityOptions.ToArray(), Styles.WindQuality);\n            EditorGUILayout.Space();\n        }\n\n        private void ShowLODGUI()\n        {\n            m_ShowSmoothLODOptions.target = m_EnableSmoothLOD.hasMultipleDifferentValues || m_EnableSmoothLOD.boolValue;\n            m_ShowCrossFadeWidthOptions.target = m_AnimateCrossFading.hasMultipleDifferentValues || !m_AnimateCrossFading.boolValue;\n\n            // label\n            GUILayout.Label(Styles.LODHeader, EditorStyles.boldLabel);\n\n            // LOD Transitions\n            {\n                EditorGUILayout.PropertyField(m_EnableSmoothLOD, Styles.SmoothLOD);\n                EditorGUI.indentLevel++;\n                if (EditorGUILayout.BeginFadeGroup(m_ShowSmoothLODOptions.faded))\n                {\n                    EditorGUILayout.PropertyField(m_AnimateCrossFading, Styles.AnimateCrossFading);\n                    if (EditorGUILayout.BeginFadeGroup(m_ShowCrossFadeWidthOptions.faded))\n                    {\n                        EditorGUILayout.Slider(m_BillboardTransitionCrossFadeWidth, 0.0f, 1.0f, Styles.CrossFadeWidth);\n                        EditorGUILayout.Slider(m_FadeOutWidth, 0.0f, 1.0f, Styles.FadeOutWidth);\n                    }\n                    EditorGUILayout.EndFadeGroup();\n                }\n                EditorGUILayout.EndFadeGroup();\n                EditorGUI.indentLevel--;\n            }\n\n            EditorGUILayout.Space();\n\n            // LOD slider + Customizations\n            if (HasSameLODConfig())\n            {\n                var area = GUILayoutUtility.GetRect(0, LODGroupGUI.kSliderBarHeight, GUILayout.ExpandWidth(true));\n                var lods = GetLODInfoArray(area);\n                bool bDrawLODCustomizationGUI = m_SelectedLODRange != -1 && lods.Count > 0;\n\n                EditorGUILayout.Space();\n\n                DrawLODLevelSlider(area, lods);\n\n                if (bDrawLODCustomizationGUI)\n                {\n                    GUILayout.Space(5);\n                    DrawLODGroupFoldouts(lods);\n                }\n            }\n\n            //  Mixed Value LOD Slider\n            else\n            {\n                if (CanUnifyLODConfig())\n                {\n                    EditorGUILayout.BeginHorizontal();\n                    GUILayout.FlexibleSpace();\n                    Rect buttonRect = GUILayoutUtility.GetRect(Styles.ResetLOD, EditorStyles.miniButton);\n                    if (GUI.Button(buttonRect, Styles.ResetLOD, EditorStyles.miniButton))\n                    {\n                        var dropDownMenu = new GenericMenu();\n                        foreach (var importer in targets.Cast<SpeedTreeImporter>())\n                        {\n                            var menuText = String.Format(\"{0}: {1}\",\n                                Path.GetFileNameWithoutExtension(importer.assetPath),\n                                String.Join(\" | \", importer.LODHeights.Select(height => string.Format(\"{0:0}%\", height * 100)).ToArray()));\n                            dropDownMenu.AddItem(new GUIContent(menuText), false, OnResetLODMenuClick, importer);\n                        }\n                        dropDownMenu.DropDown(buttonRect);\n                    }\n                    EditorGUILayout.EndHorizontal();\n                }\n                var area = GUILayoutUtility.GetRect(0, LODGroupGUI.kSliderBarHeight, GUILayout.ExpandWidth(true));\n                if (Event.current.type == EventType.Repaint)\n                    LODGroupGUI.DrawMixedValueLODSlider(area);\n            }\n\n            EditorGUILayout.Space();\n        }\n\n        private readonly int m_LODSliderId = \"LODSliderIDHash\".GetHashCode();\n        private void DrawLODLevelSlider(Rect sliderPosition, List<LODGroupGUI.LODInfo> lods)\n        {\n            int sliderId = GUIUtility.GetControlID(m_LODSliderId, FocusType.Passive);\n            Event evt = Event.current;\n\n            switch (evt.GetTypeForControl(sliderId))\n            {\n                case EventType.Repaint:\n                {\n                    LODGroupGUI.DrawLODSlider(sliderPosition, lods, m_SelectedLODRange);\n                    break;\n                }\n                case EventType.MouseDown:\n                {\n                    // Slightly grow position on the x because edge buttons overflow by 5 pixels\n                    var barPosition = sliderPosition;\n                    barPosition.x -= 5;\n                    barPosition.width += 10;\n\n                    if (barPosition.Contains(evt.mousePosition))\n                    {\n                        evt.Use();\n                        GUIUtility.hotControl = sliderId;\n\n                        // Check for button click\n                        var clickedButton = false;\n\n                        // case:464019 have to re-sort the LOD array for these buttons to get the overlaps in the right order...\n                        var lodsLeft = lods.Where(lod => lod.ScreenPercent > 0.5f).OrderByDescending(x => x.LODLevel);\n                        var lodsRight = lods.Where(lod => lod.ScreenPercent <= 0.5f).OrderBy(x => x.LODLevel);\n\n                        var lodButtonOrder = new List<LODGroupGUI.LODInfo>();\n                        lodButtonOrder.AddRange(lodsLeft);\n                        lodButtonOrder.AddRange(lodsRight);\n\n                        foreach (var lod in lodButtonOrder)\n                        {\n                            if (lod.m_ButtonPosition.Contains(evt.mousePosition))\n                            {\n                                m_SelectedLODSlider = lod.LODLevel;\n                                m_SelectedLODRange = lod.LODLevel;\n                                clickedButton = true;\n                                break;\n                            }\n                        }\n\n                        if (!clickedButton)\n                        {\n                            // Check for range click\n                            foreach (var lod in lodButtonOrder)\n                            {\n                                if (lod.m_RangePosition.Contains(evt.mousePosition))\n                                {\n                                    m_SelectedLODSlider = -1;\n                                    m_SelectedLODRange = lod.LODLevel;\n                                    ExpandSelectedHeaderAndCloseRemaining(m_SelectedLODRange);\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                    break;\n                }\n                case EventType.MouseUp:\n                {\n                    if (GUIUtility.hotControl == sliderId)\n                    {\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                    }\n                    break;\n                }\n                case EventType.MouseDrag:\n                {\n                    if (GUIUtility.hotControl == sliderId && m_SelectedLODSlider >= 0 && lods[m_SelectedLODSlider] != null)\n                    {\n                        evt.Use();\n\n                        var cameraPercent = LODGroupGUI.GetCameraPercent(evt.mousePosition, sliderPosition);\n                        // Bias by 0.1% so that there is no skipping when sliding\n                        LODGroupGUI.SetSelectedLODLevelPercentage(cameraPercent - 0.001f, m_SelectedLODSlider, lods);\n                        m_LODSettings.GetArrayElementAtIndex(m_SelectedLODSlider).FindPropertyRelative(\"height\").floatValue = lods[m_SelectedLODSlider].RawScreenPercent;\n                    }\n                    break;\n                }\n            }\n        }\n\n        private void DrawLODGroupFoldouts(List<LODGroupGUI.LODInfo> lods)\n        {\n            // check camera and bail if null\n            Camera camera = null;\n            if (SceneView.lastActiveSceneView && SceneView.lastActiveSceneView.camera)\n                camera = SceneView.lastActiveSceneView.camera;\n            if (camera == null)\n                return;\n\n            // draw lod foldouts\n            for (int i = 0; i < m_LODSettings.arraySize; i++)\n            {\n                DrawLODGroupFoldout(camera, i, ref m_LODGroupFoldoutHeaderValues[i], lods);\n            }\n        }\n\n        static private string GetLODSubmeshAndTriCountLabel(int numLODs, int lodGroupIndex, SpeedTreeImporter im, LODGroup lodGroup)\n        {\n            LOD[] lods = lodGroup.GetLODs();\n            Debug.Assert(lods.Length == numLODs);\n\n            int[][] primitiveCounts = new int[numLODs][];\n            int[] submeshCounts = new int[numLODs];\n            for (int i = 0; i < lods.Length; i++)\n            {\n                Renderer[] renderers = lods[i].renderers;\n                primitiveCounts[i] = new int[renderers.Length];\n\n                for (int j = 0; j < renderers.Length; j++)\n                {\n                    bool hasMismatchingSubMeshTopologyTypes = LODGroupEditor.CheckIfMeshesHaveMatchingTopologyTypes(renderers);\n\n                    Mesh rendererMesh = LODGroupEditor.GetMeshFromRendererIfAvailable(renderers[j]);\n                    if (rendererMesh == null)\n                        continue;\n\n                    submeshCounts[i] += rendererMesh.subMeshCount;\n\n                    if (hasMismatchingSubMeshTopologyTypes)\n                    {\n                        primitiveCounts[i][j] = rendererMesh.vertexCount;\n                    }\n                    else\n                    {\n                        for (int subMeshIndex = 0; subMeshIndex < rendererMesh.subMeshCount; subMeshIndex++)\n                        {\n                            primitiveCounts[i][j] += (int)rendererMesh.GetIndexCount(subMeshIndex) / 3;\n                        }\n                    }\n                }\n            }\n\n            int totalTriCount = (primitiveCounts.Length > 0 && primitiveCounts[lodGroupIndex] != null)\n                ? primitiveCounts[lodGroupIndex].Sum()\n                : 0;\n            int lod0TriCount = primitiveCounts[0].Sum();\n            var triCountChange = lod0TriCount != 0 ? (float)totalTriCount / lod0TriCount * 100 : 0;\n            string triangleChangeLabel = lodGroupIndex > 0 && lod0TriCount != 0 ? $\"({triCountChange.ToString(\"f2\")}% LOD0)\" : \"\";\n\n            bool wideInspector = Screen.width >= 480;\n            triangleChangeLabel = wideInspector ? triangleChangeLabel : \"\";\n            string submeshCountLabel = wideInspector ? $\"- {submeshCounts[lodGroupIndex]} Sub Mesh(es)\" : \"\";\n\n            return $\"{totalTriCount} {LODGroupGUI.GUIStyles.m_TriangleCountLabel.text} {triangleChangeLabel} {submeshCountLabel}\";\n        }\n        private void DrawLODGroupFoldout(Camera camera, int lodGroupIndex, ref SavedBool foldoutState, List<LODGroupGUI.LODInfo> lodInfoList)\n        {\n            GameObject[] prefabs = assetTargets?.Cast<GameObject>().ToArray(); // In tests assetTargets can become null\n            SpeedTreeImporter[] importerArray = importers.ToArray();\n            int numSelectedAssets = Math.Min(importerArray.Length, prefabs?.Length ?? 0);\n            bool isDrawingSelectedLODGroup = m_SelectedLODRange == lodGroupIndex;\n\n            // even though multiple assets may be selected, this code path\n            // ensures the numLODs match for all the selected assets (see HasSameLODConfig() calls)\n            int numLODs = m_LODSettings.arraySize;\n\n            string LODFoldoutHeaderLabel = (importerArray[0].hasBillboard && lodGroupIndex == m_LODSettings.arraySize - 1)\n                ? \"Billboard\"\n                : $\"LOD {lodGroupIndex}\";\n\n            // primitive and submesh counts are displayed only when a single asset is selected\n            string LODFoldoutHeaderGroupAdditionalText = numSelectedAssets == 1\n                ? GetLODSubmeshAndTriCountLabel(numLODs, lodGroupIndex, importerArray[0], prefabs[0].GetComponentInChildren<LODGroup>())\n                : \"\";\n\n            // ------------------------------------------------------------------------------------------------------------------------------\n\n            if (isDrawingSelectedLODGroup)\n                LODGroupGUI.DrawRoundedBoxAroundLODDFoldout(lodGroupIndex, m_SelectedLODRange);\n            else\n                EditorGUILayout.BeginVertical(EditorStyles.helpBox);\n\n            foldoutState.value = LODGroupGUI.FoldoutHeaderGroupInternal(\n                GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebarFlat)\n                , foldoutState.value\n                , LODFoldoutHeaderLabel\n                , m_LODColorTextures[lodGroupIndex]\n                , LODGroupGUI.kLODColors[lodGroupIndex] * 0.6f // 0.5f magic number is copied from LODGroupsGUI.cs\n                , LODFoldoutHeaderGroupAdditionalText\n            );\n\n            if (foldoutState.value) // expanded LOD-specific options panel\n            {\n                DrawLODSettingCustomizationGUI(lodInfoList, lodGroupIndex);\n            }\n\n            if (isDrawingSelectedLODGroup)\n                GUILayoutUtility.EndLayoutGroup();\n            else\n                EditorGUILayout.EndVertical();\n        }\n\n        private void DrawLODSettingCustomizationGUI(List<LODGroupGUI.LODInfo> lods, int lodIndex)\n        {\n            bool isBillboard = (lodIndex == lods.Count - 1) && importers.First().hasBillboard;\n            int windQuality = m_HighestWindQuality.intValue;\n            if (isBillboard)\n            {\n                windQuality = 1; // billboard has only one level of wind quality\n            }\n\n\n            SerializedProperty selectedLODProp = m_LODSettings.GetArrayElementAtIndex(lodIndex);\n            SerializedProperty lodSettingOverride = selectedLODProp.FindPropertyRelative(\"enableSettingOverride\");\n\n            // We don't want to clutter the GUI with same options but for billboards, instead\n            // we treat the Billboard LOD level as always 'overrideSettings' and display the\n            // billboard options below without the 'enableSettingOverride' warning text.\n            if (isBillboard)\n            {\n                EditorGUILayout.LabelField(\"Billboard Options\", EditorStyles.boldLabel);\n                EditorGUILayout.HelpBox(Styles.BillboardSettingsHelp.text, MessageType.Info);\n            }\n            else\n            {\n                // Toggle\n                GUIContent customizationLabel = EditorGUIUtility.TrTextContent(String.Format(\"Customize {0} options\", lods[lodIndex].LODName), \"To override options for a certain LOD, check this box and select the LOD from the LOD slider above\");\n                EditorGUILayout.PropertyField(lodSettingOverride, customizationLabel);\n\n                // Warning\n                if (lodSettingOverride.boolValue)\n                {\n                    EditorGUILayout.HelpBox(Styles.EnableLodCustomizationsWarn.text, MessageType.Warning);\n                }\n            }\n            EditorGUILayout.Space();\n\n            // settings\n            using (new EditorGUI.DisabledScope(!lodSettingOverride.boolValue))\n            {\n                EditorGUILayout.Space();\n                EditorGUILayout.LabelField(\"Lighting\", EditorStyles.boldLabel);\n                EditorGUILayout.PropertyField(selectedLODProp.FindPropertyRelative(\"castShadows\"), Styles.CastShadows);\n\n                using (new EditorGUI.DisabledScope(!UnityEngine.Rendering.SupportedRenderingFeatures.active.receiveShadows))\n                {\n                    EditorGUILayout.PropertyField(selectedLODProp.FindPropertyRelative(\"receiveShadows\"), Styles.ReceiveShadows);\n                }\n\n                var useLightProbes = selectedLODProp.FindPropertyRelative(\"useLightProbes\");\n                EditorGUILayout.PropertyField(useLightProbes, Styles.UseLightProbes);\n                if (!useLightProbes.hasMultipleDifferentValues && useLightProbes.boolValue && isBillboard)\n                    EditorGUILayout.HelpBox(\"Enabling Light Probe for billboards breaks batched rendering and may cause performance problem.\", MessageType.Warning);\n\n                // TODO: reflection probe support when PBS is implemented\n                //EditorGUILayout.PropertyField(SelectedLODProp.FindPropertyRelative(\"useReflectionProbes\"), Styles.UseReflectionProbes);\n\n                EditorGUILayout.Space();\n                EditorGUILayout.LabelField(\"Wind\", EditorStyles.boldLabel);\n                EditorGUILayout.Popup(\n                    selectedLODProp.FindPropertyRelative(\"windQuality\"),\n                    SpeedTreeImporter.windQualityNames.Take(windQuality + 1).Select(s => new GUIContent(s)).ToArray(),\n                    Styles.WindQuality);\n\n\n                EditorGUILayout.Space();\n                EditorGUILayout.LabelField(\"Material\", EditorStyles.boldLabel);\n                EditorGUILayout.PropertyField(selectedLODProp.FindPropertyRelative(\"enableHue\"), Styles.EnableColorVariation);\n                EditorGUILayout.PropertyField(selectedLODProp.FindPropertyRelative(\"enableBump\"), Styles.EnableBump);\n\n                if (m_AllAreV8)\n                    EditorGUILayout.PropertyField(selectedLODProp.FindPropertyRelative(\"enableSubsurface\"), Styles.EnableSubsurface);\n            }\n        }\n\n\n        private void OnResetLODMenuClick(object userData)\n        {\n            var toHeights = (userData as SpeedTreeImporter).LODHeights;\n            for (int i = 0; i < toHeights.Length; ++i)\n                m_LODSettings.GetArrayElementAtIndex(i).FindPropertyRelative(\"height\").floatValue = toHeights[i];\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ImportSettings/TextureImportPlatformSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing System.Linq;\nusing UnityEditor.Build;\nusing System.Collections.Generic;\nusing UnityEditor.Modules;\n\nnamespace UnityEditor\n{\n    internal abstract class BaseTextureImportPlatformSettings\n    {\n        static class Styles\n        {\n            static public readonly GUIContent overrideFor = EditorGUIUtility.TrTextContent(\"Override For {0}\");\n        }\n\n        public abstract bool textureTypeHasMultipleDifferentValues { get; }\n        public abstract TextureImporterType textureType { get; }\n        public abstract SpriteImportMode spriteImportMode { get; }\n        public abstract int GetTargetCount();\n        public abstract bool ShowPresetSettings();\n        public abstract TextureImporterSettings GetImporterSettings(int i);\n        public abstract bool IsSourceTextureHDR(int i);\n        public abstract TextureImportPlatformSettingsData model { get; }\n        public abstract bool DoesSourceTextureHaveAlpha(int i);\n        public abstract TextureImporterPlatformSettings GetPlatformTextureSettings(int i, string name);\n        public abstract BaseTextureImportPlatformSettings GetDefaultImportSettings();\n        public abstract void SetPlatformTextureSettings(int i, TextureImporterPlatformSettings platformSettings);\n\n        public BaseTextureImportPlatformSettings(string name, BuildTarget target)\n        {\n            model.platformTextureSettings.name = name;\n            model.buildTarget = target;\n            model.platformTextureSettings.overridden = false;\n        }\n\n        protected void Init()\n        {\n            for (int i = 0; i < GetTargetCount(); i++)\n            {\n                TextureImporterPlatformSettings curPlatformSettings = GetPlatformTextureSettings(i, model.platformTextureSettings.name);\n                if (i == 0)\n                {\n                    model.platformTextureSettings = curPlatformSettings;\n                }\n                else\n                {\n                    if (curPlatformSettings.overridden != model.platformTextureSettings.overridden)\n                        model.overriddenIsDifferent = true;\n                    if (curPlatformSettings.format != model.platformTextureSettings.format)\n                        model.textureFormatIsDifferent = true;\n                    if (curPlatformSettings.maxTextureSize != model.platformTextureSettings.maxTextureSize)\n                        model.maxTextureSizeIsDifferent = true;\n                    if (curPlatformSettings.resizeAlgorithm != model.platformTextureSettings.resizeAlgorithm)\n                        model.resizeAlgorithmIsDifferent = true;\n                    if (curPlatformSettings.textureCompression != model.platformTextureSettings.textureCompression)\n                        model.textureCompressionIsDifferent = true;\n                    if (curPlatformSettings.compressionQuality != model.platformTextureSettings.compressionQuality)\n                        model.compressionQualityIsDifferent = true;\n                    if (curPlatformSettings.crunchedCompression != model.platformTextureSettings.crunchedCompression)\n                        model.crunchedCompressionIsDifferent = true;\n                    if (curPlatformSettings.allowsAlphaSplitting != model.platformTextureSettings.allowsAlphaSplitting)\n                        model.allowsAlphaSplitIsDifferent = true;\n                    if (curPlatformSettings.androidETC2FallbackOverride !=\n                        model.platformTextureSettings.androidETC2FallbackOverride)\n                        model.androidETC2FallbackOverrideIsDifferent = true;\n                }\n            }\n\n            Sync();\n        }\n\n        public void Sync()\n        {\n            if ((model.platformTextureSettings.overridden || model.overriddenIsDifferent) && model.platformTextureSettings.format < 0)\n            {\n                var showSettingsForPreset = ShowPresetSettings();\n\n                model.platformTextureSettings.format = TextureImporter.DefaultFormatFromTextureParameters(\n                    GetImporterSettings(0),\n                    model.platformTextureSettings,\n                    showSettingsForPreset || DoesSourceTextureHaveAlpha(0),\n                    showSettingsForPreset || IsSourceTextureHDR(0),\n                    model.buildTarget\n                );\n                model.textureFormatIsDifferent = false;\n\n                for (int i = 1; i < GetTargetCount(); i++)\n                {\n                    TextureImporterSettings settings = GetImporterSettings(i);\n\n                    TextureImporterFormat format = TextureImporter.DefaultFormatFromTextureParameters(settings,\n                        model.platformTextureSettings,\n                        showSettingsForPreset || DoesSourceTextureHaveAlpha(i),\n                        showSettingsForPreset || IsSourceTextureHDR(i),\n                        model.buildTarget\n                    );\n                    if (format != model.platformTextureSettings.format)\n                        model.textureFormatIsDifferent = true;\n                }\n            }\n        }\n\n        public void Apply()\n        {\n            for (int i = 0; i < GetTargetCount(); i++)\n            {\n                TextureImporterPlatformSettings platformSettings = GetPlatformTextureSettings(i, model.platformTextureSettings.name);\n\n                // Overwrite with inspector properties if same for all targets\n                if (!model.overriddenIsDifferent)\n                    platformSettings.overridden = model.platformTextureSettings.overridden;\n                if (!model.textureFormatIsDifferent)\n                    platformSettings.format = model.platformTextureSettings.format;\n                if (!model.maxTextureSizeIsDifferent)\n                    platformSettings.maxTextureSize = model.platformTextureSettings.maxTextureSize;\n                if (!model.resizeAlgorithmIsDifferent)\n                    platformSettings.resizeAlgorithm = model.platformTextureSettings.resizeAlgorithm;\n                if (!model.textureCompressionIsDifferent)\n                    platformSettings.textureCompression = model.platformTextureSettings.textureCompression;\n                if (!model.compressionQualityIsDifferent)\n                    platformSettings.compressionQuality = model.platformTextureSettings.compressionQuality;\n                if (!model.crunchedCompressionIsDifferent)\n                    platformSettings.crunchedCompression = model.platformTextureSettings.crunchedCompression;\n                if (!model.allowsAlphaSplitIsDifferent)\n                    platformSettings.allowsAlphaSplitting = model.platformTextureSettings.allowsAlphaSplitting;\n                if (!model.androidETC2FallbackOverrideIsDifferent)\n                    platformSettings.androidETC2FallbackOverride = model.platformTextureSettings.androidETC2FallbackOverride;\n\n                platformSettings.forceMaximumCompressionQuality_BC6H_BC7 = model.platformTextureSettings.forceMaximumCompressionQuality_BC6H_BC7;\n\n                SetPlatformTextureSettings(i, platformSettings);\n            }\n\n            model.SetChanged(false);\n        }\n\n        public static BuildPlatform[] GetBuildPlayerValidPlatforms()\n        {\n            List<BuildPlatform> validPlatforms = BuildPlatforms.instance.GetValidPlatforms();\n\n            // The Dedicated Server is a subtarget of Standalone, textures are generally stripped from server builds,\n            // so overriding the texture settings for the Dedicated Server is a rare case that doesn't add much value.\n            // Supporting texture overrides for Dedicated Server is possible, but as importer dependencies cannot distinguish\n            // today between Standalone-Server and Standalone-Non-Server, such support means that textures would reimport on\n            // switching, for instance, between Standalone-Win and Standalon-OSX. That would represent a performance regression\n            // and so, we have opted to not support texture overrides for Dedicated Server.\n            validPlatforms.Remove(BuildPlatforms.instance.BuildPlatformFromNamedBuildTarget(NamedBuildTarget.Server));\n\n            return validPlatforms.ToArray();\n        }\n\n        [Obsolete(\"A single call to ShowPlatformSpecificSettings is deprecated. Please use ShowPlatformSpecificSettings for showing the platform settings, and BeginPlatformGrouping to show the platform selection\")]\n        internal static void ShowPlatformSpecificSettings(List<BaseTextureImportPlatformSettings> platformSettings)\n        {\n            BuildPlatform[] validPlatforms = GetBuildPlayerValidPlatforms();\n            GUILayout.Space(10);\n            int shownTextureFormatPage = EditorGUILayout.BeginPlatformGrouping(validPlatforms, EditorGUIUtility.TrTextContent(\"Default\"));\n            ShowPlatformSpecificSettings(platformSettings, shownTextureFormatPage);\n        }\n\n        internal static void ShowPlatformSpecificSettings(List<BaseTextureImportPlatformSettings> platformSettings, int selected)\n        {\n            BaseTextureImportPlatformSettings realPS = platformSettings[selected + 1];\n\n            if (!realPS.model.isDefault)\n            {\n                BuildPlatform[] validPlatforms = GetBuildPlayerValidPlatforms();\n                string title = string.Format(Styles.overrideFor.text, validPlatforms[selected].title.text);\n                Rect controlRect = EditorGUILayout.GetControlRect(true);\n                GUIContent label = GUIContent.Temp(title);\n                if (realPS.model.overriddenProperty != null)\n                {\n                    label = EditorGUI.BeginProperty(controlRect, label, realPS.model.overriddenProperty);\n                }\n\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = realPS.model.overriddenIsDifferent;\n                bool newOverride = EditorGUI.ToggleLeft(controlRect, label, realPS.model.platformTextureSettings.overridden);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    realPS.model.SetOverriddenForAll(newOverride);\n                    SyncPlatformSettings(platformSettings);\n                }\n                if (realPS.model.overriddenProperty != null)\n                {\n                    EditorGUI.EndProperty();\n                }\n            }\n\n            // Disable size and format GUI if not overwritten for all objects\n            bool notAllOverriddenForThisPlatform = (!realPS.model.isDefault && !realPS.model.allAreOverridden);\n            using (new EditorGUI.DisabledScope(notAllOverriddenForThisPlatform))\n            {\n                // acquire the platform support module for this platform, and present the appropriate UI\n                ITextureImportSettingsExtension textureSettingsExtension = ModuleManager.GetTextureImportSettingsExtension(realPS.model.buildTarget);\n                textureSettingsExtension.ShowImportSettings(realPS);\n\n                //just do this once, regardless of whether things changed\n                SyncPlatformSettings(platformSettings);\n            }\n\n            EditorGUILayout.EndPlatformGrouping();\n        }\n\n        internal static void SyncPlatformSettings(List<BaseTextureImportPlatformSettings> platformSettings)\n        {\n            foreach (BaseTextureImportPlatformSettings ps in platformSettings)\n                ps.Sync();\n        }\n\n        internal static void InitPlatformSettings(List<BaseTextureImportPlatformSettings> platformSettings)\n        {\n            foreach (BaseTextureImportPlatformSettings ps in platformSettings)\n                ps.Init();\n        }\n\n        internal static void ApplyPlatformSettings(List<BaseTextureImportPlatformSettings> platformSettings)\n        {\n            SyncPlatformSettings(platformSettings);\n            foreach (BaseTextureImportPlatformSettings ps in platformSettings)\n                ps.Apply();\n        }\n    }\n\n    [System.Serializable]\n    internal class TextureImportPlatformSettingsData\n    {\n        [SerializeField]\n        private TextureImporterPlatformSettings m_PlatformSettings = new TextureImporterPlatformSettings();\n\n        public TextureImporterPlatformSettings platformTextureSettings\n        {\n            get { return m_PlatformSettings; }\n            set { m_PlatformSettings = value; }\n        }\n\n        [SerializeField]\n        private SerializedProperty m_SerializedPlatformSettings = null;\n\n        public SerializedProperty platformTextureSettingsProp\n        {\n            get { return m_SerializedPlatformSettings; }\n            set { m_SerializedPlatformSettings = value; }\n        }\n\n        [SerializeField] private bool m_OverriddenIsDifferent = false;\n        public bool overriddenIsDifferent\n        {\n            get { return m_OverriddenIsDifferent; }\n            set { m_OverriddenIsDifferent = value; }\n        }\n\n        [SerializeField] private SerializedProperty m_OverriddenProperty = null;\n        public SerializedProperty overriddenProperty\n        {\n            get { return m_OverriddenProperty; }\n            set { m_OverriddenProperty = value; }\n        }\n\n        public bool allAreOverridden\n        {\n            get { return isDefault || (platformTextureSettings.overridden && !overriddenIsDifferent); }\n        }\n        public bool isDefault\n        {\n            get { return platformTextureSettings.name == TextureImporterInspector.s_DefaultPlatformName; }\n        }\n\n        // Maximum texture size\n        [SerializeField] private bool m_MaxTextureSizeIsDifferent = false;\n        public bool maxTextureSizeIsDifferent\n        {\n            get { return m_MaxTextureSizeIsDifferent; }\n            set { m_MaxTextureSizeIsDifferent = value; }\n        }\n\n        [SerializeField] private SerializedProperty m_MaxTextureSizeProperty = null;\n        public SerializedProperty maxTextureSizeProperty\n        {\n            get { return m_MaxTextureSizeProperty; }\n            set { m_MaxTextureSizeProperty = value; }\n        }\n\n        // Resize Algorithm\n        [SerializeField] private bool m_ResizeAlgorithmIsDifferent = false;\n        public bool resizeAlgorithmIsDifferent\n        {\n            get { return m_ResizeAlgorithmIsDifferent; }\n            set { m_ResizeAlgorithmIsDifferent = value; }\n        }\n\n        [SerializeField] private SerializedProperty m_ResizeAlgorithmProperty = null;\n        public SerializedProperty resizeAlgorithmProperty\n        {\n            get { return m_ResizeAlgorithmProperty; }\n            set { m_ResizeAlgorithmProperty = value; }\n        }\n\n        // Texture compression\n        [SerializeField] private bool m_TextureCompressionIsDifferent = false;\n        public bool textureCompressionIsDifferent\n        {\n            get { return m_TextureCompressionIsDifferent; }\n            set { m_TextureCompressionIsDifferent = value; }\n        }\n\n        [SerializeField] private SerializedProperty m_TextureCompressionProperty = null;\n        public SerializedProperty textureCompressionProperty\n        {\n            get { return m_TextureCompressionProperty; }\n            set { m_TextureCompressionProperty = value; }\n        }\n\n        // Compression rate\n        [SerializeField] private bool m_CompressionQualityIsDifferent = false;\n        public bool compressionQualityIsDifferent\n        {\n            get { return m_CompressionQualityIsDifferent; }\n            set { m_CompressionQualityIsDifferent = value; }\n        }\n\n        [SerializeField] private SerializedProperty m_CompressionQualityProperty = null;\n        public SerializedProperty compressionQualityProperty\n        {\n            get { return m_CompressionQualityProperty; }\n            set { m_CompressionQualityProperty = value; }\n        }\n\n        // Crunched compression\n        [SerializeField] private bool m_CrunchedCompressionIsDifferent = false;\n        public bool crunchedCompressionIsDifferent\n        {\n            get { return m_CrunchedCompressionIsDifferent; }\n            set { m_CrunchedCompressionIsDifferent = value; }\n        }\n\n        [SerializeField] private SerializedProperty m_CrunchedCompressionProperty = null;\n        public SerializedProperty crunchedCompressionProperty\n        {\n            get { return m_CrunchedCompressionProperty; }\n            set { m_CrunchedCompressionProperty = value; }\n        }\n\n        // Texture format\n        [SerializeField] private bool m_TextureFormatIsDifferent = false;\n        public bool textureFormatIsDifferent\n        {\n            get { return m_TextureFormatIsDifferent; }\n            set { m_TextureFormatIsDifferent = value; }\n        }\n\n        [SerializeField] private SerializedProperty m_TextureFormatProperty = null;\n        public SerializedProperty textureFormatProperty\n        {\n            get { return m_TextureFormatProperty; }\n            set { m_TextureFormatProperty = value; }\n        }\n\n        // Alpha splitting\n        [SerializeField] private bool m_AlphaSplitIsDifferent = false;\n        public bool allowsAlphaSplitIsDifferent\n        {\n            get { return m_AlphaSplitIsDifferent; }\n            set { m_AlphaSplitIsDifferent = value; }\n        }\n\n        [SerializeField] private SerializedProperty m_AlphaSplitProperty = null;\n        public SerializedProperty alphaSplitProperty\n        {\n            get { return m_AlphaSplitProperty; }\n            set { m_AlphaSplitProperty = value; }\n        }\n\n        // Android fallback format in case ETC2 is not supported\n        [SerializeField] private bool m_AndroidETC2FallbackOverrideIsDifferent = false;\n\n        public bool androidETC2FallbackOverrideIsDifferent\n        {\n            get { return m_AndroidETC2FallbackOverrideIsDifferent; }\n            set { m_AndroidETC2FallbackOverrideIsDifferent = value; }\n        }\n\n        [SerializeField] private SerializedProperty m_AndroidETC2FallbackOverrideProperty = null;\n        public SerializedProperty androidETC2FallbackOverrideProperty\n        {\n            get { return m_AndroidETC2FallbackOverrideProperty; }\n            set { m_AndroidETC2FallbackOverrideProperty = value; }\n        }\n\n        public void SetAndroidETC2FallbackOverrideForAll(AndroidETC2FallbackOverride value)\n        {\n            Debug.Assert(allAreOverridden,\n                \"Attempting to set android ETC2 fallback format for all platforms even though settings are not overridden for all platforms.\");\n            m_PlatformSettings.androidETC2FallbackOverride = value;\n            m_AndroidETC2FallbackOverrideIsDifferent = false;\n            SetChanged();\n        }\n\n        [SerializeField] public BuildTarget m_Target;\n        [SerializeField] bool m_HasChanged = false;\n\n\n        public void SetChanged(bool value = true)\n        {\n            m_HasChanged = value;\n        }\n\n        public bool HasChanged()\n        {\n            return m_HasChanged;\n        }\n\n        public BuildTarget buildTarget\n        {\n            get { return m_Target; }\n            set { m_Target = value; }\n        }\n\n        public void SetOverriddenForAll(bool overridden)\n        {\n            platformTextureSettings.overridden = overridden;\n            overriddenIsDifferent = false;\n            SetChanged();\n        }\n\n        public void SetMaxTextureSizeForAll(int maxTextureSize)\n        {\n            Debug.Assert(allAreOverridden,\n                \"Attempting to set max texture size for all platforms even though settings are not overridden for all platforms.\");\n            platformTextureSettings.maxTextureSize = maxTextureSize;\n            maxTextureSizeIsDifferent = false;\n            SetChanged();\n        }\n\n        public void SetResizeAlgorithmForAll(TextureResizeAlgorithm algorithm)\n        {\n            Debug.Assert(allAreOverridden,\n                \"Attempting to set resize algorithm for all platforms even though settings are not overridden for all platforms.\");\n            platformTextureSettings.resizeAlgorithm = algorithm;\n            resizeAlgorithmIsDifferent = false;\n            SetChanged();\n        }\n\n        public void SetTextureCompressionForAll(TextureImporterCompression textureCompression)\n        {\n            Debug.Assert(allAreOverridden,\n                \"Attempting to set texture compression for all platforms even though settings are not overridden for all platforms.\");\n            platformTextureSettings.textureCompression = textureCompression;\n            textureCompressionIsDifferent = false;\n            SetChanged();\n        }\n\n        public void SetCompressionQualityForAll(int quality)\n        {\n            Debug.Assert(allAreOverridden,\n                \"Attempting to set texture compression quality for all platforms even though settings are not overridden for all platforms.\");\n            platformTextureSettings.compressionQuality = quality;\n            compressionQualityIsDifferent = false;\n            platformTextureSettings.forceMaximumCompressionQuality_BC6H_BC7 = 0;\n            SetChanged();\n        }\n\n        internal bool forceMaximumCompressionQuality_BC6H_BC7\n        {\n            get { return platformTextureSettings.forceMaximumCompressionQuality_BC6H_BC7 != 0; }\n            set { platformTextureSettings.forceMaximumCompressionQuality_BC6H_BC7 = value ? 1 : 0; }\n        }\n\n        public void SetCrunchedCompressionForAll(bool crunched)\n        {\n            Debug.Assert(allAreOverridden,\n                \"Attempting to set texture crunched compression for all platforms even though settings are not overridden for all platforms.\");\n            platformTextureSettings.crunchedCompression = crunched;\n            crunchedCompressionIsDifferent = false;\n            SetChanged();\n        }\n\n        public void SetTextureFormatForAll(TextureImporterFormat format)\n        {\n            Debug.Assert(allAreOverridden,\n                \"Attempting to set texture format for all platforms even though settings are not overridden for all platforms.\");\n            platformTextureSettings.format = format;\n            textureFormatIsDifferent = false;\n            SetChanged();\n        }\n\n        public void GetValidTextureFormatsAndStrings(TextureImporterType textureType, out int[] formatValues, out string[] formatStrings)\n        {\n            if (isDefault)\n                TextureImportValidFormats.GetDefaultTextureFormatValuesAndStrings(textureType, out formatValues,\n                    out formatStrings);\n            else\n                TextureImportValidFormats.GetPlatformTextureFormatValuesAndStrings(textureType, buildTarget, out formatValues,\n                    out formatStrings);\n        }\n\n        public void SetAllowsAlphaSplitForAll(bool value)\n        {\n            Debug.Assert(allAreOverridden,\n                \"Attempting to set alpha splitting for all platforms even though settings are not overridden for all platforms.\");\n            platformTextureSettings.allowsAlphaSplitting = value;\n            allowsAlphaSplitIsDifferent = false;\n            SetChanged();\n        }\n    }\n\n    [System.Serializable]\n    internal class TextureImportPlatformSettings : BaseTextureImportPlatformSettings\n    {\n        [SerializeField] TextureImporter[] m_Importers;\n        public TextureImporter[] importers\n        {\n            get { return m_Importers; }\n        }\n\n        [SerializeField] TextureImporterInspector m_Inspector;\n\n        [SerializeField] TextureImportPlatformSettingsData m_Data = new TextureImportPlatformSettingsData();\n        public override TextureImportPlatformSettingsData model\n        {\n            get\n            {\n                return m_Data;\n            }\n        }\n\n        public override bool textureTypeHasMultipleDifferentValues\n        {\n            get\n            {\n                return m_Inspector.textureTypeHasMultipleDifferentValues;\n            }\n        }\n\n        public override TextureImporterType textureType\n        {\n            get\n            {\n                return m_Inspector.textureType;\n            }\n        }\n\n        public override SpriteImportMode spriteImportMode\n        {\n            get\n            {\n                return m_Inspector.spriteImportMode;\n            }\n        }\n\n        public TextureImportPlatformSettings(string name, BuildTarget target, TextureImporterInspector inspector) : base(name, target)\n        {\n            m_Inspector = inspector;\n            m_Importers = inspector.targets.Select(x => x as TextureImporter).ToArray();\n            Init();\n        }\n\n        public void ResetSerializedProperties()\n        {\n            model.platformTextureSettingsProp = null;\n            model.alphaSplitProperty = null;\n            model.androidETC2FallbackOverrideProperty = null;\n            model.compressionQualityProperty = null;\n            model.crunchedCompressionProperty = null;\n            model.maxTextureSizeProperty = null;\n            model.overriddenProperty = null;\n            model.resizeAlgorithmProperty = null;\n            model.textureCompressionProperty = null;\n            model.textureFormatProperty = null;\n        }\n\n        public void CacheSerializedProperties(SerializedProperty platformSettingsArray)\n        {\n            // When multi-selecting texture importers, depending on the number of stored platform settings + their order,\n            // we may end up in a situation where it is impossible to find the correct platform settings property.\n            // This is because the SerializedProperty system can only get elements that are found in all selected objects.\n            // Until a better solution comes around, keep this locked off.\n            if (platformSettingsArray.hasMultipleDifferentValues)\n            {\n                ResetSerializedProperties();\n                return;\n            }\n\n            if (model.platformTextureSettingsProp != null && model.platformTextureSettingsProp.isValid &&\n                model.platformTextureSettingsProp.FindPropertyRelative(\"m_BuildTarget\").stringValue == model.platformTextureSettings.name)\n            {\n                return; // We've already cached the appropriate PlatformTextureSettings property, don't update.\n            }\n\n            // Below: retrieve the appropriate properties for the chosen BuildTarget.\n            if (platformSettingsArray.arraySize <= 0)\n            {\n                // This should not happen, all known valid platforms should have\n                // been created in advance, including the Default Platform.\n                ResetSerializedProperties();\n                throw new UnityException(\"Cannot find any Platform Settings, including the Default Platform. This is incorrect, please report a bug.\");\n            }\n            else\n            {\n                // Fetch the matching platform settings property.\n                // Do not skip element 0, the Default Platform is a valid choice.\n                for (int i = 0; i < platformSettingsArray.arraySize; ++i)\n                {\n                    SerializedProperty serializedProperty = platformSettingsArray.GetArrayElementAtIndex(i);\n                    if (serializedProperty.FindPropertyRelative(\"m_BuildTarget\").stringValue == model.platformTextureSettings.name)\n                    {\n                        model.platformTextureSettingsProp = serializedProperty;\n                        break;\n                    }\n                }\n\n                // Since we ensure that all known valid platforms are created in advance,\n                // we should be able to find the currently selected platform. If not, fail.\n                if (model.platformTextureSettingsProp is null)\n                {\n                    ResetSerializedProperties();\n                    throw new UnityException($\"Could not find the requested Platform Texture Settings ('{model.platformTextureSettings.name}'). This is incorrect, please report a bug.\");\n                }\n            }\n\n            model.alphaSplitProperty = model.platformTextureSettingsProp.FindPropertyRelative(\"m_AllowsAlphaSplitting\");\n            model.androidETC2FallbackOverrideProperty = model.platformTextureSettingsProp.FindPropertyRelative(\"m_AndroidETC2FallbackOverride\");\n            model.compressionQualityProperty = model.platformTextureSettingsProp.FindPropertyRelative(\"m_CompressionQuality\");\n            model.crunchedCompressionProperty = model.platformTextureSettingsProp.FindPropertyRelative(\"m_CrunchedCompression\");\n            model.maxTextureSizeProperty = model.platformTextureSettingsProp.FindPropertyRelative(\"m_MaxTextureSize\");\n            model.overriddenProperty = model.platformTextureSettingsProp.FindPropertyRelative(\"m_Overridden\");\n            model.resizeAlgorithmProperty = model.platformTextureSettingsProp.FindPropertyRelative(\"m_ResizeAlgorithm\");\n            model.textureCompressionProperty = model.platformTextureSettingsProp.FindPropertyRelative(\"m_TextureCompression\");\n            model.textureFormatProperty = model.platformTextureSettingsProp.FindPropertyRelative(\"m_TextureFormat\");\n        }\n\n        public override int GetTargetCount()\n        {\n            return m_Importers.Length;\n        }\n\n        public override bool ShowPresetSettings()\n        {\n            return m_Inspector.assetTarget == null;\n        }\n\n        public override TextureImporterSettings GetImporterSettings(int i)\n        {\n            TextureImporterSettings settings = new TextureImporterSettings();\n            // Get import settings for this importer\n            m_Importers[i].ReadTextureSettings(settings);\n            // Get settings that have been changed in the inspector\n            m_Inspector.GetSerializedPropertySettings(settings);\n            return settings;\n        }\n\n        public override bool IsSourceTextureHDR(int i)\n        {\n            return m_Importers[i].IsSourceTextureHDR();\n        }\n\n        public override bool DoesSourceTextureHaveAlpha(int i)\n        {\n            return m_Importers[i].DoesSourceTextureHaveAlpha();\n        }\n\n        public override TextureImporterPlatformSettings GetPlatformTextureSettings(int i, string name)\n        {\n            return m_Importers[i].GetPlatformTextureSettings(name);\n        }\n\n        public override BaseTextureImportPlatformSettings GetDefaultImportSettings()\n        {\n            return m_Inspector.m_PlatformSettings[0];\n        }\n\n        public override void SetPlatformTextureSettings(int i, TextureImporterPlatformSettings platformSettings)\n        {\n            m_Importers[i].SetPlatformTextureSettings(platformSettings);\n        }\n\n        public static readonly int[] kAndroidETC2FallbackOverrideValues =\n        {\n            (int)AndroidETC2FallbackOverride.UseBuildSettings,\n            (int)AndroidETC2FallbackOverride.Quality32Bit,\n            (int)AndroidETC2FallbackOverride.Quality16Bit,\n            (int)AndroidETC2FallbackOverride.Quality32BitDownscaled,\n        };\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ImportSettings/TextureImportValidFormats.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.Experimental.Rendering;\n\nnamespace UnityEditor\n{\n    internal static class TextureImportValidFormats\n    {\n        private struct TextureTypeAndBuildTarget\n        {\n            private TextureImporterType textureType;\n            private BuildTarget target;\n\n            public TextureTypeAndBuildTarget(TextureImporterType textureType, BuildTarget target)\n            {\n                this.textureType = textureType;\n                this.target = target;\n            }\n\n            public override int GetHashCode()\n            {\n                return textureType.GetHashCode() ^ target.GetHashCode();\n            }\n\n            public override bool Equals(object obj)\n            {\n                if (!(obj is TextureTypeAndBuildTarget))\n                    return false;\n\n                var textureTypeAndBuildTarget = (TextureTypeAndBuildTarget)obj;\n\n                return ((this.textureType == textureTypeAndBuildTarget.textureType) &&\n                    (this.target == textureTypeAndBuildTarget.target));\n            }\n        }\n\n        private struct Value\n        {\n            public int[] formatValues;\n            public string[] formatStrings;\n\n            public Value(int[] formatValues, string[] formatStrings)\n            {\n                this.formatValues = formatValues;\n                this.formatStrings = formatStrings;\n            }\n        }\n\n        private static Dictionary<TextureTypeAndBuildTarget, Value> s_ValidTextureFormats;\n        private static Dictionary<TextureImporterType, Value> s_ValidDefaultTextureFormats;\n\n        private static string[] BuildTextureStrings(int[] texFormatValues)\n        {\n            string[] retval = new string[texFormatValues.Length];\n            for (int i = 0; i < texFormatValues.Length; i++)\n            {\n                int val = texFormatValues[i];\n                retval[i] = (val < 0 ? \"Automatic\" : GraphicsFormatUtility.GetFormatString((TextureFormat)val));\n            }\n            return retval;\n        }\n\n        private static void BuildValidFormats()\n        {\n            if (s_ValidTextureFormats != null)\n                return;\n\n            s_ValidTextureFormats = new Dictionary<TextureTypeAndBuildTarget, Value>();\n            s_ValidDefaultTextureFormats = new Dictionary<TextureImporterType, Value>();\n\n            foreach (var textureTypeName in Enum.GetNames(typeof(TextureImporterType)))\n            {\n                var textureTypeField = typeof(TextureImporterType).GetField(textureTypeName);\n                if (textureTypeField.IsDefined(typeof(ObsoleteAttribute), false))\n                    continue;\n\n                var textureType = (TextureImporterType)Enum.Parse(typeof(TextureImporterType), textureTypeName);\n\n                List<int> defaultFormats = null;\n\n                foreach (var targetName in Enum.GetNames(typeof(BuildTarget)))\n                {\n                    var targetField = typeof(BuildTarget).GetField(targetName);\n                    if (targetField.IsDefined(typeof(ObsoleteAttribute), false))\n                        continue;\n\n                    var target = (BuildTarget)Enum.Parse(typeof(BuildTarget), targetName);\n\n                    var Key = new TextureTypeAndBuildTarget(textureType, target);\n\n                    var validFormats = Array.ConvertAll(TextureImporter.RecommendedFormatsFromTextureTypeAndPlatform(textureType, target), value => (int)value);\n                    Array.Sort(validFormats, SortTextureFormats);\n                    s_ValidTextureFormats.Add(Key, new Value(validFormats, BuildTextureStrings(validFormats)));\n\n                    defaultFormats = defaultFormats?.Intersect(validFormats).ToList() ?? validFormats.ToList();\n                }\n\n                // need \"Auto\" as the first entry for defaults\n                defaultFormats.Insert(0, -1);\n                var defaultFormatsArray = defaultFormats.ToArray();\n                s_ValidDefaultTextureFormats[textureType] = new Value(defaultFormatsArray, BuildTextureStrings(defaultFormatsArray));\n            }\n        }\n\n        // formats with higher sorting code appear first on the dropdown lists\n        static uint GetSortCodeForFormat(TextureFormat fmt)\n        {\n            var f = GraphicsFormatUtility.GetGraphicsFormat(fmt, false);\n\n            // first by: normalized, floating point, integer\n            uint type;\n            if (GraphicsFormatUtility.IsNormFormat(f))\n                type = 3;\n            else if (GraphicsFormatUtility.IsHalfFormat(f) || GraphicsFormatUtility.IsFloatFormat(f))\n                type = 2;\n            else if (GraphicsFormatUtility.IsIntegerFormat(f))\n                type = 1;\n            else\n                type = 0;\n\n            // then by component count: RGBA, RGB, RG, R/A\n            var components = GraphicsFormatUtility.GetComponentCount(f);\n\n            // then compression: first compressed regular, then compressed Crunch, then uncompressed\n            uint compression = 0;\n            if (GraphicsFormatUtility.IsCompressedFormat(f))\n            {\n                compression++;\n                if (!GraphicsFormatUtility.IsCrunchFormat(fmt))\n                    compression++;\n            }\n\n            return (type << 24) | (components << 16) | (compression << 8);\n        }\n\n        static int SortTextureFormats(int fmta, int fmtb)\n        {\n            var sortA = GetSortCodeForFormat((TextureFormat)fmta);\n            var sortB = GetSortCodeForFormat((TextureFormat)fmtb);\n            if (sortA != sortB)\n                return sortB.CompareTo(sortA);\n\n            return fmtb.CompareTo(fmta);\n        }\n\n        public static void GetPlatformTextureFormatValuesAndStrings(TextureImporterType textureType, BuildTarget target, out int[] formatValues, out string[] formatStrings)\n        {\n            BuildValidFormats();\n\n            var key = new TextureTypeAndBuildTarget(textureType, target);\n            formatValues = s_ValidTextureFormats[key].formatValues;\n            formatStrings = s_ValidTextureFormats[key].formatStrings;\n        }\n\n        public static void GetDefaultTextureFormatValuesAndStrings(TextureImporterType textureType, out int[] formatValues, out string[] formatStrings)\n        {\n            BuildValidFormats();\n\n            formatValues = s_ValidDefaultTextureFormats[textureType].formatValues;\n            formatStrings = s_ValidDefaultTextureFormats[textureType].formatStrings;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ImportSettings/TextureImporterInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.AnimatedValues;\nusing UnityEngine;\nusing UnityEditor.Build;\nusing System.Collections.Generic;\nusing System;\nusing UnityEditor.AssetImporters;\nusing UnityEngine.Experimental.Rendering;\nusing Object = UnityEngine.Object;\nusing VirtualTexturing = UnityEngine.Rendering.VirtualTexturing;\n\nnamespace UnityEditor\n{\n    // Cubemap convolution mode\n    public enum TextureImporterCubemapConvolution\n    {\n        // Do not convolve cubemap (default).\n        None = 0,\n        // Convolve for specular reflections with varying roughness.\n        Specular = 1,\n        // Convolve for diffuse-only reflection (irradiance cubemap).\n        Diffuse = 2\n    }\n\n    // Kept for backward compatibility\n    public enum TextureImporterRGBMMode\n    {\n        Auto = 0,\n        On = 1,\n        Off = 2,\n        Encoded = 3,\n    }\n\n    [CustomEditor(typeof(TextureImporter))]\n    [CanEditMultipleObjects]\n    internal class TextureImporterInspector : AssetImporterEditor\n    {\n        public static string s_DefaultPlatformName = \"DefaultTexturePlatform\";\n\n        [Flags]\n        private enum TextureInspectorGUIElement\n        {\n            None = 0,\n            PowerOfTwo = 1 << 0,\n            Readable = 1 << 1,\n            AlphaHandling = 1 << 2,\n            ColorSpace = 1 << 3,\n            MipMaps = 1 << 4,\n            NormalMap = 1 << 5,\n            Sprite = 1 << 6,\n            Cookie = 1 << 7,\n            CubeMapConvolution = 1 << 8,\n            CubeMapping = 1 << 9,\n            SingleChannelComponent = 1 << 11,\n            PngGamma = 1 << 12,\n            VTOnly = 1 << 13,\n            ElementsAtlas = 1 << 14,\n            Swizzle = 1 << 15,\n        }\n\n        private struct TextureInspectorTypeGUIProperties\n        {\n            public TextureInspectorGUIElement   commonElements;\n            public TextureInspectorGUIElement   advancedElements;\n            public TextureImporterShape         shapeCaps;\n\n            public TextureInspectorTypeGUIProperties(TextureInspectorGUIElement _commonElements, TextureInspectorGUIElement _advancedElements, TextureImporterShape _shapeCaps)\n            {\n                commonElements          = _commonElements;\n                advancedElements        = _advancedElements;\n                shapeCaps               = _shapeCaps;\n            }\n        }\n\n        SerializedProperty m_TextureType;\n        internal TextureImporterType textureType\n        {\n            get\n            {\n                if (m_TextureType.hasMultipleDifferentValues)\n                    return (TextureImporterType)0;\n                return (TextureImporterType)(m_TextureType.intValue);\n            }\n        }\n\n        private delegate void GUIMethod(TextureInspectorGUIElement guiElements);\n        private Dictionary<TextureInspectorGUIElement, GUIMethod> m_GUIElementMethods = new Dictionary<TextureInspectorGUIElement, GUIMethod>();\n\n\n        internal bool textureTypeHasMultipleDifferentValues\n        {\n            get { return m_TextureType.hasMultipleDifferentValues; }\n        }\n\n        public override void OnDisable()\n        {\n            base.OnDisable();\n\n            EditorPrefs.SetBool(\"TextureImporterShowAdvanced\", m_ShowAdvanced);\n            EditorPrefs.SetBool(\"TextureImporterShowMipmapGenerationSettings\", m_ShowMipmapGenerationSettings);\n        }\n\n        // Don't show the imported texture as a separate editor\n        public override bool showImportedObject { get { return false; } }\n\n        public static bool IsCompressedDXTTextureFormat(TextureImporterFormat format)\n        {\n            return (format == TextureImporterFormat.DXT1 || format == TextureImporterFormat.DXT5);\n        }\n\n        // Which platforms should we display?\n        // For each of these, what are the formats etc. to display?\n        [SerializeField]\n        internal List<TextureImportPlatformSettings> m_PlatformSettings;\n\n        TextureInspector textureInspector\n        {\n            get => preview as TextureInspector;\n        }\n\n        internal static readonly TextureImporterFormat[] kFormatsWithCompressionSettings =\n        {\n            TextureImporterFormat.DXT1Crunched,\n            TextureImporterFormat.DXT5Crunched,\n            TextureImporterFormat.ETC_RGB4Crunched,\n            TextureImporterFormat.ETC2_RGBA8Crunched,\n#pragma warning disable CS0618 // TextureImporterFormat.PVRTC_* members are obsolete\n            TextureImporterFormat.PVRTC_RGB2,\n            TextureImporterFormat.PVRTC_RGB4,\n            TextureImporterFormat.PVRTC_RGBA2,\n            TextureImporterFormat.PVRTC_RGBA4,\n#pragma warning restore CS0618\n            TextureImporterFormat.ETC_RGB4,\n            TextureImporterFormat.ETC2_RGB4,\n            TextureImporterFormat.ETC2_RGB4_PUNCHTHROUGH_ALPHA,\n            TextureImporterFormat.ETC2_RGBA8,\n            TextureImporterFormat.ASTC_4x4,\n            TextureImporterFormat.ASTC_5x5,\n            TextureImporterFormat.ASTC_6x6,\n            TextureImporterFormat.ASTC_8x8,\n            TextureImporterFormat.ASTC_10x10,\n            TextureImporterFormat.ASTC_12x12,\n            TextureImporterFormat.ASTC_HDR_4x4,\n            TextureImporterFormat.ASTC_HDR_5x5,\n            TextureImporterFormat.ASTC_HDR_6x6,\n            TextureImporterFormat.ASTC_HDR_8x8,\n            TextureImporterFormat.ASTC_HDR_10x10,\n            TextureImporterFormat.ASTC_HDR_12x12,\n            TextureImporterFormat.BC6H,\n            TextureImporterFormat.BC7\n        };\n\n        readonly AnimBool m_ShowBumpGenerationSettings = new AnimBool();\n        readonly AnimBool m_ShowCubeMapSettings = new AnimBool();\n        readonly AnimBool m_ShowElementsAtlasSettings = new AnimBool();\n        readonly AnimBool m_ShowGenericSpriteSettings = new AnimBool();\n        readonly AnimBool m_ShowMipMapSettings = new AnimBool();\n        readonly AnimBool m_ShowSpriteMeshTypeOption = new AnimBool();\n        readonly GUIContent m_EmptyContent = new GUIContent(\" \");\n\n        readonly int[] m_FilterModeOptions = (int[])(Enum.GetValues(typeof(FilterMode)));\n\n        string  m_ImportWarning = null;\n        private void UpdateImportWarning()\n        {\n            TextureImporter importer = target as TextureImporter;\n            m_ImportWarning = importer ? importer.GetImportWarnings() : null;\n        }\n\n        internal class Styles\n        {\n            public readonly GUIContent textureTypeTitle = EditorGUIUtility.TrTextContent(\"Texture Type\", \"What will this texture be used for?\");\n            public readonly GUIContent[] textureTypeOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Default\", \"Texture is a normal image such as a diffuse texture or other.\"),\n                EditorGUIUtility.TrTextContent(\"Normal map\", \"Texture is a bump or normal map.\"),\n                EditorGUIUtility.TrTextContent(\"Editor GUI and Legacy GUI\", \"Texture is used for a GUI element.\"),\n                EditorGUIUtility.TrTextContent(\"Sprite (2D and UI)\", \"Texture is used for a sprite.\"),\n                EditorGUIUtility.TrTextContent(\"Cursor\", \"Texture is used for a cursor.\"),\n                EditorGUIUtility.TrTextContent(\"Cookie\", \"Texture is a cookie you put on a light.\"),\n                EditorGUIUtility.TrTextContent(\"Lightmap\", \"Texture is a lightmap.\"),\n                EditorGUIUtility.TrTextContent(\"Directional Lightmap\", \"Texture is a directional lightmap.\"),\n                EditorGUIUtility.TrTextContent(\"Shadowmask\", \"Texture is a shadowmask texture.\"),\n                EditorGUIUtility.TrTextContent(\"Single Channel\", \"Texture is a one component texture.\"),\n            };\n            public readonly int[] textureTypeValues =\n            {\n                (int)TextureImporterType.Default,\n                (int)TextureImporterType.NormalMap,\n                (int)TextureImporterType.GUI,\n                (int)TextureImporterType.Sprite,\n                (int)TextureImporterType.Cursor,\n                (int)TextureImporterType.Cookie,\n                (int)TextureImporterType.Lightmap,\n                (int)TextureImporterType.DirectionalLightmap,\n                (int)TextureImporterType.Shadowmask,\n                (int)TextureImporterType.SingleChannel,\n            };\n\n            public readonly GUIContent textureShape = EditorGUIUtility.TrTextContent(\"Texture Shape\", \"What shape is this texture?\");\n            readonly GUIContent textureShape2D = EditorGUIUtility.TrTextContent(\"2D\", \"Texture is 2D.\");\n            readonly GUIContent textureShapeCube = EditorGUIUtility.TrTextContent(\"Cube\", \"Texture is a Cubemap.\");\n            readonly GUIContent textureShape2DArray = EditorGUIUtility.TrTextContent(\"2D Array\", \"Texture is a 2D Array.\");\n            readonly GUIContent textureShape3D = EditorGUIUtility.TrTextContent(\"3D\", \"Texture is 3D.\");\n            public readonly Dictionary<TextureImporterShape, GUIContent[]> textureShapeOptionsDictionnary = new Dictionary<TextureImporterShape, GUIContent[]>();\n            public readonly Dictionary<TextureImporterShape, int[]> textureShapeValuesDictionnary = new Dictionary<TextureImporterShape, int[]>();\n\n            public readonly GUIContent defaultPlatform = EditorGUIUtility.TrTextContent(\"Default\");\n\n            public readonly GUIContent filterMode = EditorGUIUtility.TrTextContent(\"Filter Mode\");\n            public readonly GUIContent[] filterModeOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Point (no filter)\"),\n                EditorGUIUtility.TrTextContent(\"Bilinear\"),\n                EditorGUIUtility.TrTextContent(\"Trilinear\")\n            };\n\n            public readonly GUIContent cookieType = EditorGUIUtility.TrTextContent(\"Light Type\");\n            public readonly GUIContent[] cookieOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Spot Light\"),\n                EditorGUIUtility.TrTextContent(\"Directional Light\"),\n                EditorGUIUtility.TrTextContent(\"Point Light\"),\n            };\n            public readonly GUIContent generateFromBump = EditorGUIUtility.TrTextContent(\"Create from Grayscale\", \"The grayscale of the image is used as a heightmap for generating the normal map.\");\n            public readonly GUIContent bumpiness = EditorGUIUtility.TrTextContent(\"Bumpiness\");\n            public readonly GUIContent bumpFiltering = EditorGUIUtility.TrTextContent(\"Filtering\");\n            public readonly GUIContent[] bumpFilteringOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Sharp\"),\n                EditorGUIUtility.TrTextContent(\"Smooth\"),\n            };\n\n            public readonly GUIContent flipGreenChannel = EditorGUIUtility.TrTextContent(\"Flip Green Channel\",\n                \"Invert values in the normal map green (Y) channel. Use on normal maps that were produced for non-Unity normal orientation convention.\");\n            public readonly GUIContent swizzle = EditorGUIUtility.TrTextContent(\"Swizzle\",\n                \"Reorder and invert texture color channels. For each of R,G,B,A channels pick where the channel data comes from.\");\n\n            public readonly GUIContent cubemap = EditorGUIUtility.TrTextContent(\"Mapping\");\n            public readonly GUIContent[] cubemapOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Auto\"),\n                EditorGUIUtility.TrTextContent(\"6 Frames Layout (Cubic Environment)\", \"Texture contains 6 images arranged in one of the standard cubemap layouts - cross or sequence (+x, -x, +y, -y, +z, -z). Texture can be in vertical or horizontal orientation.\"),\n                EditorGUIUtility.TrTextContent(\"Latitude-Longitude Layout (Cylindrical)\", \"Texture contains an image of a ball unwrapped such that latitude and longitude are mapped to horizontal and vertical dimensions (as on a globe).\"),\n                EditorGUIUtility.TrTextContent(\"Mirrored Ball (Spheremap)\", \"Texture contains an image of a mirrored ball.\")\n            };\n            public readonly int[] cubemapValues2 =\n            {\n                (int)TextureImporterGenerateCubemap.AutoCubemap,\n                (int)TextureImporterGenerateCubemap.FullCubemap,\n                (int)TextureImporterGenerateCubemap.Cylindrical,\n                (int)TextureImporterGenerateCubemap.Spheremap\n            };\n\n            public readonly GUIContent cubemapConvolution = EditorGUIUtility.TrTextContent(\"Convolution Type\");\n            public readonly GUIContent[] cubemapConvolutionOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"None\"),\n                EditorGUIUtility.TrTextContent(\"Specular (Glossy Reflection)\", \"Convolve cubemap for specular reflections with varying smoothness (Glossy Reflections).\"),\n                EditorGUIUtility.TrTextContent(\"Diffuse (Irradiance)\", \"Convolve cubemap for diffuse-only reflection (Irradiance Cubemap).\")\n            };\n            public readonly int[] cubemapConvolutionValues =\n            {\n                (int)TextureImporterCubemapConvolution.None,\n                (int)TextureImporterCubemapConvolution.Specular,\n                (int)TextureImporterCubemapConvolution.Diffuse\n            };\n\n            public readonly GUIContent seamlessCubemap = EditorGUIUtility.TrTextContent(\"Fixup Edge Seams\", \"Enable if this texture is used for glossy reflections.\");\n            public readonly GUIContent textureFormat = EditorGUIUtility.TrTextContent(\"Format\");\n\n            public readonly GUIContent mipmapFadeOutToggle = EditorGUIUtility.TrTextContent(\"Fadeout to Gray\");\n            public readonly GUIContent mipmapFadeStartMip = EditorGUIUtility.TrTextContent(\"Fade Start Mip\");\n            public readonly GUIContent mipmapFadeEndMip = EditorGUIUtility.TrTextContent(\"Fade End Mip\");\n            public readonly GUIContent mipmapFadeOut = EditorGUIUtility.TrTextContent(\"Fade Range\");\n            public readonly GUIContent readWrite = EditorGUIUtility.TrTextContent(\"Read/Write\", \"Enable to be able to access the raw pixel data from code.\");\n            public readonly GUIContent useMipmapLimits = EditorGUIUtility.TrTextContent(\"Mipmap Limit\", \"Disable this if the number of mipmap levels to upload should not be limited by the quality settings. (effectively: always upload at full resolution, regardless of the global mipmap limit or mipmap limit groups)\");\n            public readonly GUIContent mipmapLimitGroupName = EditorGUIUtility.TrTextContent(\"Mipmap Limit Group\", \"Select a Mipmap Limit Group for this texture. If you do not add this texture to a Mipmap Limit Group, or Unity cannot find the group name you provide, Unity limits the number of mipmap levels it uploads to the maximum defined by the Global Texture Mipmap Limit (see Quality Settings). If Unity can find the Mipmap Limit Group you specify, it respects that group's limit.\");\n            public readonly GUIContent mipmapLimitGroupWarning = EditorGUIUtility.TrTextContent(\"This texture takes the default mipmap limit settings because Unity cannot find the mipmap limit group you have designated. Consult your project's Quality Settings for a list of mipmap limit groups.\");\n            public readonly GUIContent streamingMipmaps = EditorGUIUtility.TrTextContent(\"Stream Mipmap Levels\", \"Only load larger mipmap levels as needed to render the current game cameras. Requires Texture Mipmap Streaming to be enabled in quality settings.\");\n            public readonly GUIContent streamingMipmapsPriority = EditorGUIUtility.TrTextContent(\"Priority\", \"Mipmap streaming priority when there's contention for resources. Positive numbers represent higher priority. Valid range is -128 to 127.\");\n            public readonly GUIContent vtOnly = EditorGUIUtility.TrTextContent(\"Virtual Texture Only\", \"Texture is optimized for use as a virtual texture and can only be used as a virtual texture.\");\n\n            public readonly GUIContent alphaSource = EditorGUIUtility.TrTextContent(\"Alpha Source\", \"How is the alpha generated for the imported texture.\");\n            public readonly GUIContent[] alphaSourceOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"None\", \"No Alpha will be used.\"),\n                EditorGUIUtility.TrTextContent(\"Input Texture Alpha\", \"Use Alpha from the input texture if one is provided.\"),\n                EditorGUIUtility.TrTextContent(\"From Gray Scale\", \"Generate Alpha from image gray scale.\"),\n            };\n            public readonly int[] alphaSourceValues =\n            {\n                (int)TextureImporterAlphaSource.None,\n                (int)TextureImporterAlphaSource.FromInput,\n                (int)TextureImporterAlphaSource.FromGrayScale,\n            };\n\n            public readonly GUIContent singleChannelComponent = EditorGUIUtility.TrTextContent(\"Channel\", \"As which color/alpha component the single channel texture is treated.\");\n            public readonly GUIContent[] singleChannelComponentOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Alpha\", \"Use the alpha channel (compression not supported).\"),\n                EditorGUIUtility.TrTextContent(\"Red\", \"Use the red color component.\"),\n            };\n            public readonly int[] singleChannelComponentValues =\n            {\n                (int)TextureImporterSingleChannelComponent.Alpha,\n                (int)TextureImporterSingleChannelComponent.Red,\n            };\n\n            public readonly GUIContent generateMipMaps = EditorGUIUtility.TrTextContent(\"Generate Mipmap\", \"Create progressively smaller versions of the texture, for reduced texture shimmering and better GPU performance when the texture is viewed at a distance.\");\n            public readonly GUIContent showMipmapGenerationSettings = EditorGUIUtility.TrTextContent(\"Generation Settings\", \"Set up how the mipmap levels are generated from the imported image.\");\n            public readonly GUIContent sRGBTexture = EditorGUIUtility.TrTextContent(\"sRGB (Color Texture)\", \"Texture content is stored in gamma space. Non-HDR color textures should enable this flag (except if used for IMGUI).\");\n            public readonly GUIContent sRGBForEtc1Warning = EditorGUIUtility.TrTextContent(\"Unity does not support importing textures as ETC when that texture is in the sRGB color space and the project is set to use a Linear color space. One or more of the textures you have selected are imported as ETC2 instead.\");\n            public readonly GUIContent borderMipMaps = EditorGUIUtility.TrTextContent(\"Replicate Border\", \"Replicate pixel values from texture borders into smaller mipmap levels. Mostly used for Cookie texture types.\");\n            public readonly GUIContent mipMapsPreserveCoverage = EditorGUIUtility.TrTextContent(\"Preserve Coverage\", \"The alpha channel of generated mipmaps will preserve coverage for the alpha test. Useful for foliage textures.\");\n            public readonly GUIContent alphaTestReferenceValue = EditorGUIUtility.TrTextContent(\"Alpha Cutoff\", \"The reference value used during the alpha test. Controls mipmap coverage.\");\n            public readonly GUIContent mipMapFilter = EditorGUIUtility.TrTextContent(\"Mipmap Filtering\");\n            public readonly GUIContent[] mipMapFilterOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Box\"),\n                EditorGUIUtility.TrTextContent(\"Kaiser\"),\n            };\n            public readonly GUIContent npot = EditorGUIUtility.TrTextContent(\"Non-Power of 2\", \"How non-power-of-two textures are scaled on import.\");\n            public readonly GUIContent generateCubemap = EditorGUIUtility.TrTextContent(\"Generate Cubemap\");\n\n            public readonly GUIContent spriteMode = EditorGUIUtility.TrTextContent(\"Sprite Mode\");\n            public readonly GUIContent[] spriteModeOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Single\"),\n                EditorGUIUtility.TrTextContent(\"Multiple\"),\n                EditorGUIUtility.TrTextContent(\"Polygon\"),\n            };\n            public readonly GUIContent[] spriteMeshTypeOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Full Rect\"),\n                EditorGUIUtility.TrTextContent(\"Tight\"),\n            };\n\n            public readonly GUIContent spritePixelsPerUnit = EditorGUIUtility.TrTextContent(\"Pixels Per Unit\", \"How many pixels in the sprite correspond to one unit in the world.\");\n            public readonly GUIContent spriteExtrude = EditorGUIUtility.TrTextContent(\"Extrude Edges\", \"How much empty area to leave around the sprite in the generated mesh.\");\n            public readonly GUIContent spriteMeshType = EditorGUIUtility.TrTextContent(\"Mesh Type\", \"Type of sprite mesh to generate.\");\n            public readonly GUIContent spriteAlignment = EditorGUIUtility.TrTextContent(\"Pivot\", \"Sprite pivot point in its localspace. May be used for syncing animation frames of different sizes.\");\n            public readonly GUIContent[] spriteAlignmentOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Center\"),\n                EditorGUIUtility.TrTextContent(\"Top Left\"),\n                EditorGUIUtility.TrTextContent(\"Top\"),\n                EditorGUIUtility.TrTextContent(\"Top Right\"),\n                EditorGUIUtility.TrTextContent(\"Left\"),\n                EditorGUIUtility.TrTextContent(\"Right\"),\n                EditorGUIUtility.TrTextContent(\"Bottom Left\"),\n                EditorGUIUtility.TrTextContent(\"Bottom\"),\n                EditorGUIUtility.TrTextContent(\"Bottom Right\"),\n                EditorGUIUtility.TrTextContent(\"Custom\"),\n            };\n            public readonly GUIContent spriteGenerateFallbackPhysicsShape = EditorGUIUtility.TrTextContent(\"Generate Physics Shape\", \"Generates a default physics shape from the outline of the Sprite/s when a physics shape has not been set in the Sprite Editor.\");\n            public readonly GUIContent applyAndContinueToSpriteEditor = EditorGUIUtility.TrTextContent(\"Unapplied import settings for \\'{0}\\'.\\n Apply changes and continue to Sprite Editor Window?\");\n            public readonly GUIContent unappliedImportSettings = EditorGUIUtility.TrTextContent(\"Unapplied import settings\");\n            public readonly GUIContent yes = EditorGUIUtility.TrTextContent(\"Yes\");\n            public readonly GUIContent no = EditorGUIUtility.TrTextContent(\"No\");\n\n            public readonly GUIContent alphaIsTransparency = EditorGUIUtility.TrTextContent(\"Alpha Is Transparency\", \"If the alpha channel of your texture represents transparency, enable this property to dilate the color channels of visible texels into fully transparent areas. This effectively adds padding around transparent areas that prevents filtering artifacts from forming on their edges. Unity does not support this property for HDR textures. \\n\\nThis property makes the color data of invisible texels undefined. Disable this property to preserve invisible texels' original color data.\");\n\n            public readonly GUIContent showAdvanced = EditorGUIUtility.TrTextContent(\"Advanced\", \"Show advanced settings.\");\n\n            public readonly GUIContent psdRemoveMatte = EditorGUIUtility.TrTextContent(\"Remove PSD Matte\", \"Enable special processing for PSD that has transparency, as color pixels will be tweaked (blended with white color).\");\n\n            public readonly GUIContent ignorePngGamma = EditorGUIUtility.TrTextContent(\"Ignore PNG Gamma\", \"Ignore the Gamma attribute value in PNG files.\");\n            public readonly GUIContent readWriteWarning = EditorGUIUtility.TrTextContent(\"When you enable Read/Write, Unity stores an additional copy of your textures in CPU-addressable memory. One or more of the textures you have selected use a considerable amount of memory (more than 512MB).\");\n\n            public readonly GUIContent flipbookColumns = EditorGUIUtility.TrTextContent(\"Columns\", \"Source image is divided into this amount of columns.\");\n            public readonly GUIContent flipbookRows = EditorGUIUtility.TrTextContent(\"Rows\", \"Source image is divided into this amount of rows.\");\n\n            public Styles()\n            {\n                // This is far from ideal, but it's better than having tons of logic in the GUI code itself.\n                // The combination should not grow too much.\n                GUIContent[] s2D_Options = { textureShape2D };\n                GUIContent[] sCube_Options = { textureShapeCube };\n                GUIContent[] s2D_Cube_Options = { textureShape2D, textureShapeCube };\n                GUIContent[] sAll_Options = { textureShape2D, textureShapeCube, textureShape2DArray, textureShape3D };\n                textureShapeOptionsDictionnary.Add(TextureImporterShape.Texture2D, s2D_Options);\n                textureShapeOptionsDictionnary.Add(TextureImporterShape.TextureCube, sCube_Options);\n                textureShapeOptionsDictionnary.Add(TextureImporterShape.Texture2D | TextureImporterShape.TextureCube, s2D_Cube_Options);\n                textureShapeOptionsDictionnary.Add(TextureImporterShape.Texture2D | TextureImporterShape.TextureCube | TextureImporterShape.Texture2DArray | TextureImporterShape.Texture3D, sAll_Options);\n\n                int[] s2D_Values = { (int)TextureImporterShape.Texture2D };\n                int[] sCube_Values = { (int)TextureImporterShape.TextureCube };\n                int[] s2D_Cube_Values = { (int)TextureImporterShape.Texture2D, (int)TextureImporterShape.TextureCube };\n                int[] sAll_Values = { (int)TextureImporterShape.Texture2D, (int)TextureImporterShape.TextureCube, (int)TextureImporterShape.Texture2DArray, (int)TextureImporterShape.Texture3D };\n                textureShapeValuesDictionnary.Add(TextureImporterShape.Texture2D, s2D_Values);\n                textureShapeValuesDictionnary.Add(TextureImporterShape.TextureCube, sCube_Values);\n                textureShapeValuesDictionnary.Add(TextureImporterShape.Texture2D | TextureImporterShape.TextureCube, s2D_Cube_Values);\n                textureShapeValuesDictionnary.Add(TextureImporterShape.Texture2D | TextureImporterShape.TextureCube | TextureImporterShape.Texture2DArray | TextureImporterShape.Texture3D, sAll_Values);\n            }\n        }\n\n        internal static Styles s_Styles;\n\n        TextureInspectorTypeGUIProperties[] m_TextureTypeGUIElements = new TextureInspectorTypeGUIProperties[Enum.GetValues(typeof(TextureImporterType)).Length];\n        List<TextureInspectorGUIElement>    m_GUIElementsDisplayOrder = new List<TextureInspectorGUIElement>();\n\n\n        void ToggleFromInt(SerializedProperty property, GUIContent label)\n        {\n            var content = EditorGUI.BeginProperty(EditorGUILayout.BeginHorizontal(), label, property);\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = property.hasMultipleDifferentValues;\n            int value = EditorGUILayout.Toggle(content, property.intValue > 0) ? 1 : 0;\n            EditorGUI.showMixedValue = false;\n            if (EditorGUI.EndChangeCheck())\n                property.intValue = value;\n            EditorGUILayout.EndHorizontal();\n            EditorGUI.EndProperty();\n        }\n\n        void EnumPopup(SerializedProperty property, System.Type type, GUIContent label)\n        {\n            EditorGUILayout.IntPopup(property,\n                EditorGUIUtility.TempContent(System.Enum.GetNames(type)),\n                System.Enum.GetValues(type) as int[],\n                label);\n        }\n\n        SerializedProperty m_AlphaSource;\n        SerializedProperty m_ConvertToNormalMap;\n        SerializedProperty m_HeightScale;\n        SerializedProperty m_NormalMapFilter;\n        SerializedProperty m_FlipGreenChannel;\n        SerializedProperty m_Swizzle;\n        SerializedProperty m_GenerateCubemap;\n        SerializedProperty m_CubemapConvolution;\n        SerializedProperty m_SeamlessCubemap;\n        SerializedProperty m_BorderMipMap;\n        SerializedProperty m_MipMapsPreserveCoverage;\n        SerializedProperty m_AlphaTestReferenceValue;\n        SerializedProperty m_NPOTScale;\n        SerializedProperty m_IsReadable;\n        SerializedProperty m_StreamingMipmaps;\n        SerializedProperty m_StreamingMipmapsPriority;\n        SerializedProperty m_IgnoreMipmapLimit;\n        SerializedProperty m_MipmapLimitGroupName;\n\n        SerializedProperty m_VTOnly;\n        SerializedProperty m_sRGBTexture;\n        SerializedProperty m_EnableMipMap;\n        SerializedProperty m_MipMapMode;\n        SerializedProperty m_FadeOut;\n        SerializedProperty m_MipMapFadeDistanceStart;\n        SerializedProperty m_MipMapFadeDistanceEnd;\n\n        SerializedProperty m_Aniso;\n        SerializedProperty m_FilterMode;\n        SerializedProperty m_WrapU;\n        SerializedProperty m_WrapV;\n        SerializedProperty m_WrapW;\n\n        SerializedProperty m_SpritePixelsToUnits;\n        SerializedProperty m_SpriteExtrude;\n        SerializedProperty m_SpriteMeshType;\n        SerializedProperty m_Alignment;\n        SerializedProperty m_SpritePivot;\n        SerializedProperty m_SpriteGenerateFallbackPhysicsShape;\n\n        SerializedProperty m_AlphaIsTransparency;\n        SerializedProperty m_IgnorePngGamma;\n        SerializedProperty m_PSDRemoveMatte;\n\n        SerializedProperty m_TextureShape;\n\n        SerializedProperty m_SpriteMode;\n\n        SerializedProperty m_FlipbookRows;\n        SerializedProperty m_FlipbookColumns;\n\n        SerializedProperty m_SingleChannelComponent;\n\n        SerializedProperty m_CookieLightType;\n\n        SerializedProperty m_PlatformSettingsArrProp;\n\n        List<TextureImporterType> m_TextureTypes;\n        internal SpriteImportMode spriteImportMode\n        {\n            get\n            {\n                return (SpriteImportMode)m_SpriteMode.intValue;\n            }\n        }\n\n        bool m_ShowAdvanced = false;\n        bool m_ShowMipmapGenerationSettings = true;\n\n        int     m_TextureWidth = 0;\n        int     m_TextureHeight = 0;\n        bool    m_IsPOT = false;\n        bool    m_IsPNG, m_IsPSD;\n\n        void CacheSerializedProperties()\n        {\n            m_AlphaSource = serializedObject.FindProperty(\"m_AlphaUsage\");\n            m_ConvertToNormalMap = serializedObject.FindProperty(\"m_ConvertToNormalMap\");\n            m_HeightScale = serializedObject.FindProperty(\"m_HeightScale\");\n            m_NormalMapFilter = serializedObject.FindProperty(\"m_NormalMapFilter\");\n            m_FlipGreenChannel = serializedObject.FindProperty(\"m_FlipGreenChannel\");\n            m_Swizzle = serializedObject.FindProperty(\"m_Swizzle\");\n            m_GenerateCubemap = serializedObject.FindProperty(\"m_GenerateCubemap\");\n            m_SeamlessCubemap = serializedObject.FindProperty(\"m_SeamlessCubemap\");\n            m_BorderMipMap = serializedObject.FindProperty(\"m_BorderMipMap\");\n            m_MipMapsPreserveCoverage = serializedObject.FindProperty(\"m_MipMapsPreserveCoverage\");\n            m_AlphaTestReferenceValue = serializedObject.FindProperty(\"m_AlphaTestReferenceValue\");\n            m_NPOTScale = serializedObject.FindProperty(\"m_NPOTScale\");\n            m_IsReadable = serializedObject.FindProperty(\"m_IsReadable\");\n            m_StreamingMipmaps = serializedObject.FindProperty(\"m_StreamingMipmaps\");\n            m_StreamingMipmapsPriority = serializedObject.FindProperty(\"m_StreamingMipmapsPriority\");\n            m_IgnoreMipmapLimit = serializedObject.FindProperty(\"m_IgnoreMipmapLimit\");\n            m_MipmapLimitGroupName = serializedObject.FindProperty(\"m_MipmapLimitGroupName\");\n            m_VTOnly = serializedObject.FindProperty(\"m_VTOnly\");\n            m_sRGBTexture = serializedObject.FindProperty(\"m_sRGBTexture\");\n            m_EnableMipMap = serializedObject.FindProperty(\"m_EnableMipMap\");\n            m_MipMapMode = serializedObject.FindProperty(\"m_MipMapMode\");\n            m_FadeOut = serializedObject.FindProperty(\"m_FadeOut\");\n            m_MipMapFadeDistanceStart = serializedObject.FindProperty(\"m_MipMapFadeDistanceStart\");\n            m_MipMapFadeDistanceEnd = serializedObject.FindProperty(\"m_MipMapFadeDistanceEnd\");\n\n            m_Aniso = serializedObject.FindProperty(\"m_TextureSettings.m_Aniso\");\n            m_FilterMode = serializedObject.FindProperty(\"m_TextureSettings.m_FilterMode\");\n            m_WrapU = serializedObject.FindProperty(\"m_TextureSettings.m_WrapU\");\n            m_WrapV = serializedObject.FindProperty(\"m_TextureSettings.m_WrapV\");\n            m_WrapW = serializedObject.FindProperty(\"m_TextureSettings.m_WrapW\");\n\n            m_CubemapConvolution = serializedObject.FindProperty(\"m_CubemapConvolution\");\n\n            m_SpriteMode = serializedObject.FindProperty(\"m_SpriteMode\");\n            m_SpritePixelsToUnits = serializedObject.FindProperty(\"m_SpritePixelsToUnits\");\n            m_SpriteExtrude = serializedObject.FindProperty(\"m_SpriteExtrude\");\n            m_SpriteMeshType = serializedObject.FindProperty(\"m_SpriteMeshType\");\n            m_Alignment = serializedObject.FindProperty(\"m_Alignment\");\n            m_SpritePivot = serializedObject.FindProperty(\"m_SpritePivot\");\n            m_SpriteGenerateFallbackPhysicsShape = serializedObject.FindProperty(\"m_SpriteGenerateFallbackPhysicsShape\");\n\n            m_AlphaIsTransparency = serializedObject.FindProperty(\"m_AlphaIsTransparency\");\n            m_IgnorePngGamma = serializedObject.FindProperty(\"m_IgnorePngGamma\");\n            m_PSDRemoveMatte = serializedObject.FindProperty(\"m_PSDRemoveMatte\");\n\n            m_TextureType = serializedObject.FindProperty(\"m_TextureType\");\n            m_TextureShape = serializedObject.FindProperty(\"m_TextureShape\");\n\n            m_SingleChannelComponent = serializedObject.FindProperty(\"m_SingleChannelComponent\");\n\n            m_FlipbookRows = serializedObject.FindProperty(\"m_FlipbookRows\");\n            m_FlipbookColumns = serializedObject.FindProperty(\"m_FlipbookColumns\");\n\n            m_CookieLightType = serializedObject.FindProperty(\"m_CookieLightType\");\n\n            m_PlatformSettingsArrProp = serializedObject.FindProperty(\"m_PlatformSettings\");\n\n            m_TextureTypes = new List<TextureImporterType>();\n            foreach (var o in targets)\n            {\n                var targetObject = (TextureImporter)o;\n                m_TextureTypes.Add(targetObject.textureType);\n            }\n        }\n\n        void InitializeGUI()\n        {\n            // This is where we decide what GUI elements are displayed depending on the texture type.\n            // TODO: Maybe complement the bitfield with a list to add a concept of order in the display. Not sure if necessary...\n            TextureImporterShape shapeCapsAll =\n                TextureImporterShape.Texture2D |\n                TextureImporterShape.TextureCube |\n                TextureImporterShape.Texture2DArray |\n                TextureImporterShape.Texture3D;\n\n            var sharedAdvanced = TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps | TextureInspectorGUIElement.PngGamma | TextureInspectorGUIElement.Swizzle;\n\n            m_TextureTypeGUIElements[(int)TextureImporterType.Default]      = new TextureInspectorTypeGUIProperties(\n                TextureInspectorGUIElement.ColorSpace | TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.CubeMapConvolution | TextureInspectorGUIElement.CubeMapping | TextureInspectorGUIElement.ElementsAtlas,\n                sharedAdvanced\n                | TextureInspectorGUIElement.VTOnly\n                , shapeCapsAll);\n            m_TextureTypeGUIElements[(int)TextureImporterType.NormalMap]    = new TextureInspectorTypeGUIProperties(\n                TextureInspectorGUIElement.NormalMap | TextureInspectorGUIElement.CubeMapping | TextureInspectorGUIElement.ElementsAtlas,\n                sharedAdvanced\n                | TextureInspectorGUIElement.VTOnly\n                , shapeCapsAll);\n            m_TextureTypeGUIElements[(int)TextureImporterType.Sprite]       = new TextureInspectorTypeGUIProperties(\n                TextureInspectorGUIElement.Sprite,\n                TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.MipMaps | TextureInspectorGUIElement.ColorSpace,\n                TextureImporterShape.Texture2D);\n            m_TextureTypeGUIElements[(int)TextureImporterType.Cookie]       = new TextureInspectorTypeGUIProperties(\n                TextureInspectorGUIElement.Cookie | TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.CubeMapping,\n                sharedAdvanced,\n                TextureImporterShape.Texture2D | TextureImporterShape.TextureCube);\n            m_TextureTypeGUIElements[(int)TextureImporterType.SingleChannel] = new TextureInspectorTypeGUIProperties(\n                TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.SingleChannelComponent | TextureInspectorGUIElement.CubeMapping | TextureInspectorGUIElement.ElementsAtlas,\n                sharedAdvanced\n                , shapeCapsAll);\n            m_TextureTypeGUIElements[(int)TextureImporterType.GUI]          = new TextureInspectorTypeGUIProperties(\n                0,\n                TextureInspectorGUIElement.AlphaHandling | sharedAdvanced,\n                TextureImporterShape.Texture2D);\n            m_TextureTypeGUIElements[(int)TextureImporterType.Cursor]       = new TextureInspectorTypeGUIProperties(\n                0,\n                TextureInspectorGUIElement.AlphaHandling | sharedAdvanced,\n                TextureImporterShape.Texture2D);\n            m_TextureTypeGUIElements[(int)TextureImporterType.Lightmap]     = new TextureInspectorTypeGUIProperties(\n                0,\n                sharedAdvanced\n                , TextureImporterShape.Texture2D);\n            m_TextureTypeGUIElements[(int)TextureImporterType.DirectionalLightmap] = new TextureInspectorTypeGUIProperties(\n                0,\n                sharedAdvanced\n                , TextureImporterShape.Texture2D);\n            m_TextureTypeGUIElements[(int)TextureImporterType.Shadowmask]   = new TextureInspectorTypeGUIProperties(\n                0,\n                sharedAdvanced\n                , TextureImporterShape.Texture2D);\n\n            m_GUIElementMethods.Clear();\n            m_GUIElementMethods.Add(TextureInspectorGUIElement.PowerOfTwo, this.POTScaleGUI);\n            m_GUIElementMethods.Add(TextureInspectorGUIElement.Readable, this.ReadableGUI);\n            m_GUIElementMethods.Add(TextureInspectorGUIElement.VTOnly, this.VTOnlyGUI);\n            m_GUIElementMethods.Add(TextureInspectorGUIElement.ColorSpace, this.ColorSpaceGUI);\n            m_GUIElementMethods.Add(TextureInspectorGUIElement.AlphaHandling, this.AlphaHandlingGUI);\n            m_GUIElementMethods.Add(TextureInspectorGUIElement.PngGamma, this.PngGammaGUI);\n            m_GUIElementMethods.Add(TextureInspectorGUIElement.MipMaps, this.MipMapGUI);\n            m_GUIElementMethods.Add(TextureInspectorGUIElement.NormalMap, this.BumpGUI);\n            m_GUIElementMethods.Add(TextureInspectorGUIElement.Sprite, this.SpriteGUI);\n            m_GUIElementMethods.Add(TextureInspectorGUIElement.Cookie, this.CookieGUI);\n            m_GUIElementMethods.Add(TextureInspectorGUIElement.CubeMapping, this.CubemapMappingGUI);\n            m_GUIElementMethods.Add(TextureInspectorGUIElement.ElementsAtlas, this.ElementsAtlasGui);\n            m_GUIElementMethods.Add(TextureInspectorGUIElement.Swizzle, this.SwizzleGui);\n\n            // This list dictates the order in which the GUI Elements are displayed.\n            // It could be different for each TextureImporterType but let's keep it simple for now.\n            m_GUIElementsDisplayOrder.Clear();\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.ElementsAtlas);\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.CubeMapping);\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.CubeMapConvolution);\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.Cookie);\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.ColorSpace);\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.AlphaHandling);\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.SingleChannelComponent);\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.NormalMap);\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.Sprite);\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.PowerOfTwo);\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.Readable);\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.VTOnly);\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.MipMaps);\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.PngGamma);\n            m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.Swizzle);\n\n            UnityEngine.Debug.Assert(m_GUIElementsDisplayOrder.Count == (Enum.GetValues(typeof(TextureInspectorGUIElement)).Length - 1), \"Some GUIElement are not present in the list.\"); // -1 because TextureInspectorGUIElement.None\n        }\n\n        public override void OnEnable()\n        {\n            base.OnEnable();\n            Initialize();\n        }\n\n        void Initialize()\n        {\n            s_DefaultPlatformName = TextureImporter.defaultPlatformName; // Can't be called everywhere so we save it here for later use.\n\n            m_ShowAdvanced = EditorPrefs.GetBool(\"TextureImporterShowAdvanced\", m_ShowAdvanced);\n            m_ShowMipmapGenerationSettings = EditorPrefs.GetBool(\"TextureImporterShowMipmapGenerationSettings\", m_ShowMipmapGenerationSettings);\n\n            CacheSerializedProperties();\n\n            BuildTargetList();\n\n            m_ShowBumpGenerationSettings.valueChanged.AddListener(Repaint);\n            m_ShowBumpGenerationSettings.value = m_ConvertToNormalMap.intValue > 0;\n            m_ShowCubeMapSettings.valueChanged.AddListener(Repaint);\n            m_ShowCubeMapSettings.value = (TextureImporterShape)m_TextureShape.intValue == TextureImporterShape.TextureCube;\n            m_ShowElementsAtlasSettings.valueChanged.AddListener(Repaint);\n            m_ShowElementsAtlasSettings.value = (TextureImporterShape)m_TextureShape.intValue == TextureImporterShape.Texture2DArray || (TextureImporterShape)m_TextureShape.intValue == TextureImporterShape.Texture3D;\n            //@TODO change to use spriteMode enum when available\n            m_ShowGenericSpriteSettings.valueChanged.AddListener(Repaint);\n            m_ShowGenericSpriteSettings.value = m_SpriteMode.intValue != 0;\n            m_ShowSpriteMeshTypeOption.valueChanged.AddListener(Repaint);\n            m_ShowSpriteMeshTypeOption.value = ShouldShowSpriteMeshTypeOption();\n            m_ShowMipMapSettings.valueChanged.AddListener(Repaint);\n            m_ShowMipMapSettings.value = m_EnableMipMap.boolValue && (TextureImporterShape)m_TextureShape.intValue != TextureImporterShape.Texture3D;\n\n            InitializeGUI();\n\n            var importer = target as TextureImporter;\n            if (importer == null)\n                return;\n\n            importer.GetWidthAndHeight(ref m_TextureWidth, ref m_TextureHeight);\n            m_IsPOT = IsPowerOfTwo(m_TextureWidth) && IsPowerOfTwo(m_TextureHeight);\n            var ext = FileUtil.GetPathExtension(importer.assetPath).ToLowerInvariant();\n            m_IsPSD = ext == \"psd\";\n            m_IsPNG = ext == \"png\";\n        }\n\n        void SetSerializedPropertySettings(TextureImporterSettings settings)\n        {\n            m_AlphaSource.intValue = (int)settings.alphaSource;\n            m_ConvertToNormalMap.intValue = settings.convertToNormalMap ? 1 : 0;\n            m_HeightScale.floatValue = settings.heightmapScale;\n            m_NormalMapFilter.intValue = (int)settings.normalMapFilter;\n            m_FlipGreenChannel.intValue = settings.flipGreenChannel ? 1 : 0;\n            m_Swizzle.uintValue = settings.swizzleRaw;\n            m_GenerateCubemap.intValue = (int)settings.generateCubemap;\n            m_CubemapConvolution.intValue = (int)settings.cubemapConvolution;\n            m_SeamlessCubemap.intValue = settings.seamlessCubemap ? 1 : 0;\n            m_BorderMipMap.intValue = settings.borderMipmap ? 1 : 0;\n            m_MipMapsPreserveCoverage.intValue = settings.mipMapsPreserveCoverage ? 1 : 0;\n            m_AlphaTestReferenceValue.floatValue = settings.alphaTestReferenceValue;\n            m_NPOTScale.intValue = (int)settings.npotScale;\n            m_IsReadable.intValue = settings.readable ? 1 : 0;\n            m_StreamingMipmaps.intValue = settings.streamingMipmaps ? 1 : 0;\n            m_StreamingMipmapsPriority.intValue = settings.streamingMipmapsPriority;\n            m_IgnoreMipmapLimit.intValue = settings.ignoreMipmapLimit ? 1 : 0;\n            m_VTOnly.intValue = settings.vtOnly ? 1 : 0;\n            m_EnableMipMap.intValue = settings.mipmapEnabled ? 1 : 0;\n            m_sRGBTexture.intValue = settings.sRGBTexture ? 1 : 0;\n            m_MipMapMode.intValue = (int)settings.mipmapFilter;\n            m_FadeOut.intValue = settings.fadeOut ? 1 : 0;\n            m_MipMapFadeDistanceStart.intValue = settings.mipmapFadeDistanceStart;\n            m_MipMapFadeDistanceEnd.intValue = settings.mipmapFadeDistanceEnd;\n\n            m_SpriteMode.intValue = settings.spriteMode;\n            m_SpritePixelsToUnits.floatValue = settings.spritePixelsPerUnit;\n            m_SpriteExtrude.intValue = (int)settings.spriteExtrude;\n            m_SpriteMeshType.intValue = (int)settings.spriteMeshType;\n            m_Alignment.intValue = settings.spriteAlignment;\n            m_SpriteGenerateFallbackPhysicsShape.intValue = settings.spriteGenerateFallbackPhysicsShape ? 1 : 0;\n\n            m_WrapU.intValue = (int)settings.wrapMode;\n            m_WrapV.intValue = (int)settings.wrapMode;\n            m_FilterMode.intValue = (int)settings.filterMode;\n            m_Aniso.intValue = settings.aniso;\n\n            m_AlphaIsTransparency.intValue = settings.alphaIsTransparency ? 1 : 0;\n            m_IgnorePngGamma.intValue = settings.ignorePngGamma ? 1 : 0;\n\n            m_TextureType.intValue = (int)settings.textureType;\n            m_TextureShape.intValue = (int)settings.textureShape;\n\n            m_SingleChannelComponent.intValue = (int)settings.singleChannelComponent;\n\n            m_FlipbookRows.intValue = settings.flipbookRows;\n            m_FlipbookColumns.intValue = settings.flipbookColumns;\n        }\n\n        internal TextureImporterSettings GetSerializedPropertySettings()\n        {\n            return GetSerializedPropertySettings(new TextureImporterSettings());\n        }\n\n        internal TextureImporterSettings GetSerializedPropertySettings(TextureImporterSettings settings)\n        {\n            if (!m_AlphaSource.hasMultipleDifferentValues)\n                settings.alphaSource = (TextureImporterAlphaSource)m_AlphaSource.intValue;\n\n            if (!m_ConvertToNormalMap.hasMultipleDifferentValues)\n                settings.convertToNormalMap = m_ConvertToNormalMap.intValue > 0;\n\n            if (!m_HeightScale.hasMultipleDifferentValues)\n                settings.heightmapScale = m_HeightScale.floatValue;\n\n            if (!m_NormalMapFilter.hasMultipleDifferentValues)\n                settings.normalMapFilter = (TextureImporterNormalFilter)m_NormalMapFilter.intValue;\n            if (!m_FlipGreenChannel.hasMultipleDifferentValues)\n                settings.flipGreenChannel = m_FlipGreenChannel.intValue > 0;\n            if (!m_Swizzle.hasMultipleDifferentValues)\n                settings.swizzleRaw = m_Swizzle.uintValue;\n\n            if (!m_GenerateCubemap.hasMultipleDifferentValues)\n                settings.generateCubemap = (TextureImporterGenerateCubemap)m_GenerateCubemap.intValue;\n\n            if (!m_CubemapConvolution.hasMultipleDifferentValues)\n                settings.cubemapConvolution = (TextureImporterCubemapConvolution)m_CubemapConvolution.intValue;\n\n            if (!m_SeamlessCubemap.hasMultipleDifferentValues)\n                settings.seamlessCubemap = m_SeamlessCubemap.intValue > 0;\n\n            if (!m_BorderMipMap.hasMultipleDifferentValues)\n                settings.borderMipmap = m_BorderMipMap.intValue > 0;\n\n            if (!m_MipMapsPreserveCoverage.hasMultipleDifferentValues)\n                settings.mipMapsPreserveCoverage = m_MipMapsPreserveCoverage.intValue > 0;\n\n            if (!m_AlphaTestReferenceValue.hasMultipleDifferentValues)\n                settings.alphaTestReferenceValue = m_AlphaTestReferenceValue.floatValue;\n\n            if (!m_NPOTScale.hasMultipleDifferentValues)\n                settings.npotScale = (TextureImporterNPOTScale)m_NPOTScale.intValue;\n\n            if (!m_IsReadable.hasMultipleDifferentValues)\n                settings.readable = m_IsReadable.intValue > 0;\n\n            if (!m_StreamingMipmaps.hasMultipleDifferentValues)\n                settings.streamingMipmaps = m_StreamingMipmaps.intValue > 0;\n            if (!m_StreamingMipmapsPriority.hasMultipleDifferentValues)\n                settings.streamingMipmapsPriority = m_StreamingMipmapsPriority.intValue;\n            if (!m_IgnoreMipmapLimit.hasMultipleDifferentValues)\n                settings.ignoreMipmapLimit = m_IgnoreMipmapLimit.intValue > 0;\n\n            if (!m_VTOnly.hasMultipleDifferentValues)\n                settings.vtOnly = m_VTOnly.intValue > 0;\n\n            if (!m_sRGBTexture.hasMultipleDifferentValues)\n                settings.sRGBTexture = m_sRGBTexture.intValue > 0;\n\n            if (!m_EnableMipMap.hasMultipleDifferentValues)\n                settings.mipmapEnabled = m_EnableMipMap.intValue > 0;\n\n            if (!m_MipMapMode.hasMultipleDifferentValues)\n                settings.mipmapFilter = (TextureImporterMipFilter)m_MipMapMode.intValue;\n\n            if (!m_FadeOut.hasMultipleDifferentValues)\n                settings.fadeOut = m_FadeOut.intValue > 0;\n\n            if (!m_MipMapFadeDistanceStart.hasMultipleDifferentValues)\n                settings.mipmapFadeDistanceStart = m_MipMapFadeDistanceStart.intValue;\n\n            if (!m_MipMapFadeDistanceEnd.hasMultipleDifferentValues)\n                settings.mipmapFadeDistanceEnd = m_MipMapFadeDistanceEnd.intValue;\n\n            if (!m_SpriteMode.hasMultipleDifferentValues)\n                settings.spriteMode = m_SpriteMode.intValue;\n\n            if (!m_SpritePixelsToUnits.hasMultipleDifferentValues)\n                settings.spritePixelsPerUnit = m_SpritePixelsToUnits.floatValue;\n\n            if (!m_SpriteExtrude.hasMultipleDifferentValues)\n                settings.spriteExtrude = (uint)m_SpriteExtrude.intValue;\n\n            if (!m_SpriteMeshType.hasMultipleDifferentValues)\n                settings.spriteMeshType = (SpriteMeshType)m_SpriteMeshType.intValue;\n\n            if (!m_Alignment.hasMultipleDifferentValues)\n                settings.spriteAlignment = m_Alignment.intValue;\n\n            if (!m_SpritePivot.hasMultipleDifferentValues)\n                settings.spritePivot = m_SpritePivot.vector2Value;\n\n            if (!m_SpriteGenerateFallbackPhysicsShape.hasMultipleDifferentValues)\n                settings.spriteGenerateFallbackPhysicsShape = m_SpriteGenerateFallbackPhysicsShape.intValue > 0;\n\n            if (!m_WrapU.hasMultipleDifferentValues)\n                settings.wrapModeU = (TextureWrapMode)m_WrapU.intValue;\n            if (!m_WrapV.hasMultipleDifferentValues)\n                settings.wrapModeU = (TextureWrapMode)m_WrapV.intValue;\n            if (!m_WrapW.hasMultipleDifferentValues)\n                settings.wrapModeU = (TextureWrapMode)m_WrapW.intValue;\n\n            if (!m_FilterMode.hasMultipleDifferentValues)\n                settings.filterMode = (FilterMode)m_FilterMode.intValue;\n\n            if (!m_Aniso.hasMultipleDifferentValues)\n                settings.aniso = m_Aniso.intValue;\n\n\n            if (!m_AlphaIsTransparency.hasMultipleDifferentValues)\n                settings.alphaIsTransparency = m_AlphaIsTransparency.intValue > 0;\n\n            if (!m_TextureType.hasMultipleDifferentValues)\n                settings.textureType = (TextureImporterType)m_TextureType.intValue;\n\n            if (!m_TextureShape.hasMultipleDifferentValues)\n                settings.textureShape = (TextureImporterShape)m_TextureShape.intValue;\n\n            if (!m_SingleChannelComponent.hasMultipleDifferentValues)\n                settings.singleChannelComponent = (TextureImporterSingleChannelComponent)m_SingleChannelComponent.intValue;\n\n            if (!m_IgnorePngGamma.hasMultipleDifferentValues)\n                settings.ignorePngGamma = m_IgnorePngGamma.intValue > 0;\n\n            if (!m_FlipbookRows.hasMultipleDifferentValues)\n                settings.flipbookRows = m_FlipbookRows.intValue;\n            if (!m_FlipbookColumns.hasMultipleDifferentValues)\n                settings.flipbookColumns = m_FlipbookColumns.intValue;\n\n            return settings;\n        }\n\n        void CookieGUI(TextureInspectorGUIElement guiElements)\n        {\n            EditorGUI.BeginChangeCheck();\n\n            EditorGUILayout.Popup(m_CookieLightType, s_Styles.cookieOptions, s_Styles.cookieType);\n\n            if (EditorGUI.EndChangeCheck())\n                SetCookieLightTypeDefaults((TextureImporterCookieLightType)m_CookieLightType.intValue);\n        }\n\n        void CubemapMappingGUI(TextureInspectorGUIElement guiElements)\n        {\n            m_ShowCubeMapSettings.target = (TextureImporterShape)m_TextureShape.intValue == TextureImporterShape.TextureCube;\n            if (EditorGUILayout.BeginFadeGroup(m_ShowCubeMapSettings.faded))\n            {\n                if ((TextureImporterShape)m_TextureShape.intValue == TextureImporterShape.TextureCube)\n                {\n                    Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup);\n                    GUIContent label = EditorGUI.BeginProperty(controlRect, s_Styles.cubemap, m_GenerateCubemap);\n\n                    EditorGUI.showMixedValue = m_GenerateCubemap.hasMultipleDifferentValues || m_SeamlessCubemap.hasMultipleDifferentValues;\n\n                    EditorGUI.BeginChangeCheck();\n\n                    int value = EditorGUI.IntPopup(controlRect, label, m_GenerateCubemap.intValue, s_Styles.cubemapOptions, s_Styles.cubemapValues2);\n                    if (EditorGUI.EndChangeCheck())\n                        m_GenerateCubemap.intValue = value;\n\n                    EditorGUI.EndProperty();\n                    EditorGUI.indentLevel++;\n\n                    // Convolution\n                    if (ShouldDisplayGUIElement(guiElements, TextureInspectorGUIElement.CubeMapConvolution))\n                    {\n                        EditorGUILayout.IntPopup(m_CubemapConvolution,\n                            s_Styles.cubemapConvolutionOptions,\n                            s_Styles.cubemapConvolutionValues,\n                            s_Styles.cubemapConvolution);\n                    }\n\n                    ToggleFromInt(m_SeamlessCubemap, s_Styles.seamlessCubemap);\n\n                    EditorGUI.indentLevel--;\n                    EditorGUILayout.Space();\n                }\n            }\n            EditorGUILayout.EndFadeGroup();\n        }\n\n        void ElementsAtlasGui(TextureInspectorGUIElement guiElements)\n        {\n            var shape = (TextureImporterShape)m_TextureShape.intValue;\n            var isLayerShape = shape == TextureImporterShape.Texture2DArray || shape == TextureImporterShape.Texture3D;\n            m_ShowElementsAtlasSettings.target = isLayerShape;\n            if (EditorGUILayout.BeginFadeGroup(m_ShowElementsAtlasSettings.faded) && isLayerShape)\n            {\n                var isEditorTargetPreset = Presets.Preset.IsEditorTargetAPreset(target);\n\n                EditorGUI.indentLevel++;\n                EditorGUI.BeginChangeCheck();\n                EditorGUILayout.PropertyField(m_FlipbookColumns, s_Styles.flipbookColumns);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    var val = m_FlipbookColumns.intValue;\n\n                    // It happens when we are directly changing a TextureImporter preset and not an ImportSettings (targetting a 2D texture).\n                    // We don't wanna clamp the value to 'm_TextureWidth', or it will always be set to -1 since there's no texture targeted.\n                    val = Mathf.Clamp(val, 1, !isEditorTargetPreset ? m_TextureWidth : val);\n                    m_FlipbookColumns.intValue = val;\n                }\n                if (!isEditorTargetPreset && m_TextureWidth % m_FlipbookColumns.intValue != 0)\n                    EditorGUILayout.HelpBox($\"Image width {m_TextureWidth} does not divide into {m_FlipbookColumns.intValue} columns exactly\", MessageType.Warning, true);\n\n                EditorGUI.BeginChangeCheck();\n                EditorGUILayout.PropertyField(m_FlipbookRows, s_Styles.flipbookRows);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    var val = m_FlipbookRows.intValue;\n\n                    // It happens when we are directly changing a TextureImporter preset and not an ImportSettings (targetting a 2D texture).\n                    // We don't wanna clamp the value to 'm_TextureHeight', or it will always be set to -1 since there's no texture targeted.\n                    val = Mathf.Clamp(val, 1, !isEditorTargetPreset ? m_TextureHeight : val);\n                    m_FlipbookRows.intValue = val;\n                }\n                if (!isEditorTargetPreset && m_TextureHeight % m_FlipbookRows.intValue != 0)\n                    EditorGUILayout.HelpBox($\"Image height {m_TextureHeight} does not divide into {m_FlipbookRows.intValue} rows exactly\", MessageType.Warning, true);\n                EditorGUI.indentLevel--;\n            }\n            EditorGUILayout.EndFadeGroup();\n        }\n\n        bool ShouldDisplaySRGBForEtc1Warning()\n        {\n            if (PlayerSettings.colorSpace == ColorSpace.Gamma)\n            {\n                return false;\n            }\n\n            BuildTarget buildTarget = EditorUserBuildSettings.activeBuildTarget;\n            string platformName = BuildPipeline.GetBuildTargetName(buildTarget);\n            for (int i = 0; i < targets.Length; i++)\n            {\n                TextureImporter t = (TextureImporter)targets[i];\n                if (!t.sRGBTexture)\n                {\n                    continue;\n                }\n                TextureImporterPlatformSettings settings = t.GetPlatformTextureSettings(platformName);\n                if (!settings.overridden)\n                {\n                    settings = t.GetDefaultPlatformTextureSettings();\n                    platformName = settings.name;\n                }\n\n                TextureImporterFormat textureImporterFormat = t.GetPlatformTextureSettings(platformName).format;\n                TextureFormat textureFormat;\n                // If Automatic+Compressed is used, we cannot determine if ETC1 -> ETC2 conversion occurred using only the Texture / TexImporter.\n                // Instead, let's check PlayerSettings / BuildSettings.\n                if (textureImporterFormat == TextureImporterFormat.Automatic && t.textureCompression != TextureImporterCompression.Uncompressed)\n                {\n                    TextureCompressionFormat defaultTexCompressionFormat = PlayerSettings.GetDefaultTextureCompressionFormat(buildTarget);\n                    if (BuildTargetDiscovery.TryGetBuildTarget(buildTarget, out IBuildTarget iBuildTarget))\n                        if (iBuildTarget.GraphicsPlatformProperties?.IsETCUsedAsDefaultTextureImporter(defaultTexCompressionFormat) ?? false)\n                            return true;\n\n                    continue; // ETC is not being used as default texture compression format.\n                }\n\n                textureFormat = (TextureFormat)textureImporterFormat;\n                if (textureFormat == TextureFormat.ETC_RGB4 || textureFormat == TextureFormat.ETC_RGB4Crunched)\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        void ColorSpaceGUI(TextureInspectorGUIElement guiElements)\n        {\n            if (CountImportersWithHDR(targets, out int countHDR) && countHDR == 0)\n            {\n                ToggleFromInt(m_sRGBTexture, s_Styles.sRGBTexture);\n\n                if (ShouldDisplaySRGBForEtc1Warning())\n                {\n                    // ETC1 + sRGB does not exist. In order to provide sRGB regardless, the TextureImporter upgrades the chosen import format\n                    // to an ETC2 equivalent. This is safe to do: ETC2 is backwards compatible with ETC1 and all the platforms that\n                    // support ETC1 also support ETC2. Regardless, let's warn users that this is happening.\n                    EditorGUILayout.HelpBox(s_Styles.sRGBForEtc1Warning.text, MessageType.Warning);\n                }\n            }\n        }\n\n        void POTScaleGUI(TextureInspectorGUIElement guiElements)\n        {\n            // Cubemap face sizes are calculated using the original file's width/height + the cubemap generation mode.\n            // Currently, the calculation always outputs POT face sizes: displaying this control is thus unnecessary.\n            if ((TextureImporterShape)m_TextureShape.intValue == TextureImporterShape.TextureCube)\n            {\n                return;\n            }\n\n            using (new EditorGUI.DisabledScope(m_IsPOT))\n            {\n                EnumPopup(m_NPOTScale, typeof(TextureImporterNPOTScale), s_Styles.npot);\n            }\n        }\n\n        void ReadableGUI(TextureInspectorGUIElement guiElements)\n        {\n            ToggleFromInt(m_IsReadable, s_Styles.readWrite);\n\n            if (m_IsReadable.intValue > 0 && !m_IsReadable.hasMultipleDifferentValues && ShouldShowWarningForReadWrite())\n            {\n                EditorGUILayout.HelpBox(s_Styles.readWriteWarning.text, MessageType.Info, true);\n            }\n        }\n\n        void MipmapGenerationGUI()\n        {\n            EditorGUILayout.Popup(m_MipMapMode, s_Styles.mipMapFilterOptions, s_Styles.mipMapFilter);\n\n            ToggleFromInt(m_MipMapsPreserveCoverage, s_Styles.mipMapsPreserveCoverage);\n            if (m_MipMapsPreserveCoverage.intValue != 0 && !m_MipMapsPreserveCoverage.hasMultipleDifferentValues)\n            {\n                EditorGUI.indentLevel++;\n                EditorGUILayout.PropertyField(m_AlphaTestReferenceValue, s_Styles.alphaTestReferenceValue);\n                EditorGUI.indentLevel--;\n            }\n\n            ToggleFromInt(m_BorderMipMap, s_Styles.borderMipMaps);\n\n            // Mipmap fadeout\n            ToggleFromInt(m_FadeOut, s_Styles.mipmapFadeOutToggle);\n            if (m_FadeOut.intValue > 0)\n            {\n                const int minLimit = 0;\n                const int maxLimit = 10;\n\n                // For presets, we need two separate controls as we have 2 separate SerializedProperties.\n                EditorGUI.indentLevel++;\n                if (Presets.Preset.IsEditorTargetAPreset(target))\n                {\n                    // Fade Start\n                    EditorGUI.BeginChangeCheck();\n                    EditorGUILayout.PropertyField(m_MipMapFadeDistanceStart, s_Styles.mipmapFadeStartMip);\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        m_MipMapFadeDistanceStart.intValue = Math.Clamp(m_MipMapFadeDistanceStart.intValue, minLimit, m_MipMapFadeDistanceEnd.intValue);\n                    }\n\n                    // Fade End\n                    EditorGUI.BeginChangeCheck();\n                    EditorGUILayout.PropertyField(m_MipMapFadeDistanceEnd, s_Styles.mipmapFadeEndMip);\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        m_MipMapFadeDistanceEnd.intValue = Math.Clamp(m_MipMapFadeDistanceEnd.intValue, m_MipMapFadeDistanceStart.intValue, maxLimit);\n                    }\n                }\n                else\n                {\n                    // Fade Range\n                    EditorGUI.BeginChangeCheck();\n                    float min = m_MipMapFadeDistanceStart.intValue;\n                    float max = m_MipMapFadeDistanceEnd.intValue;\n                    EditorGUILayout.MinMaxSlider(s_Styles.mipmapFadeOut, ref min, ref max, minLimit, maxLimit);\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        m_MipMapFadeDistanceStart.intValue = Mathf.RoundToInt(min);\n                        m_MipMapFadeDistanceEnd.intValue = Mathf.RoundToInt(max);\n                    }\n                }\n                EditorGUI.indentLevel--;\n            }\n        }\n\n        void StreamingMipmapsGUI()\n        {\n            // only 2D & Cubemap shapes support streaming mipmaps right now\n            var shape = (TextureImporterShape)m_TextureShape.intValue;\n            var shapeHasStreaming = shape == TextureImporterShape.Texture2D || shape == TextureImporterShape.TextureCube;\n            if (!shapeHasStreaming)\n                return;\n\n            // some texture types are not relevant for mip streaming\n            var type = textureType;\n            if (type == TextureImporterType.Cookie || type == TextureImporterType.GUI || type == TextureImporterType.Cursor)\n                return;\n\n            ToggleFromInt(m_StreamingMipmaps, s_Styles.streamingMipmaps);\n            if (m_StreamingMipmaps.boolValue && !m_StreamingMipmaps.hasMultipleDifferentValues)\n            {\n                EditorGUI.indentLevel++;\n                EditorGUILayout.PropertyField(m_StreamingMipmapsPriority, s_Styles.streamingMipmapsPriority);\n                EditorGUI.indentLevel--;\n            }\n        }\n\n        void VTOnlyGUI(TextureInspectorGUIElement guiElements)\n        {\n            // only 2D shape supports VT right now\n            var shape = (TextureImporterShape)m_TextureShape.intValue;\n            var shapeHasVT = shape == TextureImporterShape.Texture2D;\n            if (!shapeHasVT)\n                return;\n            ToggleFromInt(m_VTOnly, s_Styles.vtOnly);\n        }\n\n\n        void AlphaHandlingGUI(TextureInspectorGUIElement guiElements)\n        {\n            bool showAlphaSource = true;\n            if (ShouldDisplayGUIElement(guiElements, TextureInspectorGUIElement.SingleChannelComponent))\n            {\n                EditorGUILayout.IntPopup(m_SingleChannelComponent, s_Styles.singleChannelComponentOptions, s_Styles.singleChannelComponentValues, s_Styles.singleChannelComponent);\n\n                showAlphaSource = (m_SingleChannelComponent.intValue == (int)TextureImporterSingleChannelComponent.Alpha);\n            }\n\n            if (showAlphaSource)\n            {\n                int countWithAlpha = 0;\n                int countHDR = 0;\n\n                bool success = CountImportersWithAlpha(targets, out countWithAlpha);\n                success = success && CountImportersWithHDR(targets, out countHDR);\n\n                EditorGUILayout.IntPopup(m_AlphaSource, s_Styles.alphaSourceOptions, s_Styles.alphaSourceValues, s_Styles.alphaSource);\n\n                bool showAlphaIsTransparency = success && (TextureImporterAlphaSource)m_AlphaSource.intValue != TextureImporterAlphaSource.None && countHDR == 0; // AlphaIsTransparency is not properly implemented for HDR texture yet.\n                using (new EditorGUI.DisabledScope(assetTarget != null && !showAlphaIsTransparency))\n                {\n                    ToggleFromInt(m_AlphaIsTransparency, s_Styles.alphaIsTransparency);\n                }\n            }\n\n            // This is pure backward compatibility codepath. It can be removed when we decide that the time has come\n            if (m_IsPSD)\n            {\n                EditorGUILayout.PropertyField(m_PSDRemoveMatte, s_Styles.psdRemoveMatte);\n            }\n        }\n\n        private bool ShouldShowSpriteMeshTypeOption()\n        {\n            return m_SpriteMode.intValue != (int)SpriteImportMode.Polygon && !m_SpriteMode.hasMultipleDifferentValues;\n        }\n\n        private void SpriteGUI(TextureInspectorGUIElement guiElements)\n        {\n            // Sprite mode selection\n            EditorGUI.BeginChangeCheck();\n\n            EditorGUILayout.IntPopup(m_SpriteMode, s_Styles.spriteModeOptions, new[] { 1, 2, 3 }, s_Styles.spriteMode);\n\n            // Ensure that PropertyField focus will be cleared when we change spriteMode.\n            if (EditorGUI.EndChangeCheck())\n            {\n                GUIUtility.keyboardControl = 0;\n            }\n\n            EditorGUI.indentLevel++;\n\n            // Show generic attributes\n            m_ShowGenericSpriteSettings.target = (m_SpriteMode.intValue != 0);\n            if (EditorGUILayout.BeginFadeGroup(m_ShowGenericSpriteSettings.faded))\n            {\n                EditorGUILayout.PropertyField(m_SpritePixelsToUnits, s_Styles.spritePixelsPerUnit);\n\n                m_ShowSpriteMeshTypeOption.target = ShouldShowSpriteMeshTypeOption();\n                if (EditorGUILayout.BeginFadeGroup(m_ShowSpriteMeshTypeOption.faded))\n                {\n                    EditorGUILayout.IntPopup(m_SpriteMeshType, s_Styles.spriteMeshTypeOptions, new[] { 0, 1 }, s_Styles.spriteMeshType);\n                }\n                EditorGUILayout.EndFadeGroup();\n\n                EditorGUILayout.IntSlider(m_SpriteExtrude, 0, 32, s_Styles.spriteExtrude);\n\n                if (m_SpriteMode.intValue == (int)SpriteImportMode.Single)\n                {\n                    EditorGUILayout.Popup(m_Alignment, s_Styles.spriteAlignmentOptions, s_Styles.spriteAlignment);\n\n                    if (m_Alignment.intValue == (int)SpriteAlignment.Custom)\n                    {\n                        GUILayout.BeginHorizontal();\n                        EditorGUILayout.PropertyField(m_SpritePivot, m_EmptyContent);\n                        GUILayout.EndHorizontal();\n                    }\n                }\n\n                if (m_SpriteMode.intValue != (int)SpriteImportMode.Polygon)\n                    ToggleFromInt(m_SpriteGenerateFallbackPhysicsShape, s_Styles.spriteGenerateFallbackPhysicsShape);\n\n                EditorGUI.indentLevel--;\n                using (new EditorGUI.DisabledScope(targets.Length != 1))\n                {\n                    if (SpriteUtilityWindow.DoOpenSpriteEditorWindowUI())\n                    {\n                        if (HasModified())\n                        {\n                            // To ensure Sprite Editor Window to have the latest texture import setting,\n                            // We must applied those modified values first.\n                            var dialogText = string.Format(s_Styles.applyAndContinueToSpriteEditor.text, ((TextureImporter)target).assetPath);\n                            if (EditorUtility.DisplayDialog(s_Styles.unappliedImportSettings.text, dialogText, s_Styles.yes.text, s_Styles.no.text))\n                            {\n                                SaveChanges();\n                                SpriteUtilityWindow.ShowSpriteEditorWindow(this.assetTarget);\n\n                                // We reimported the asset which destroyed the editor, so we can't keep running the UI here.\n                                GUIUtility.ExitGUI();\n                            }\n                        }\n                        else\n                        {\n                            SpriteUtilityWindow.ShowSpriteEditorWindow(this.assetTarget);\n                        }\n                    }\n                }\n            }\n\n            EditorGUILayout.EndFadeGroup();\n        }\n\n        internal static void DoMipmapLimitsGUI(SerializedProperty ignoreMipmapLimitProp, SerializedProperty groupNameProp)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            // The property itself is \"ignoreMipmapLimit\". However, in the UI, we display it\n            // as \"use\" Mipmap Limit as it makes more sense to hide the group names dropdown\n            // when \"Mipmap Limit\" is toggled off rather than when \"Ignore Mipmap Limit\"\n            // is toggled on.\n            Rect rect = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight);\n            GUIContent label = EditorGUI.BeginProperty(rect, s_Styles.useMipmapLimits, ignoreMipmapLimitProp);\n            bool useMipmapLimits = ignoreMipmapLimitProp.propertyType == SerializedPropertyType.Integer ? ignoreMipmapLimitProp.intValue == 0 : !ignoreMipmapLimitProp.boolValue;\n            using (var changed = new EditorGUI.ChangeCheckScope())\n            {\n                useMipmapLimits = EditorGUI.Toggle(rect, label, useMipmapLimits);\n                if (changed.changed)\n                {\n                    if (ignoreMipmapLimitProp.propertyType == SerializedPropertyType.Integer)\n                    {\n                        ignoreMipmapLimitProp.intValue = useMipmapLimits ? 0 : 1;\n                    }\n                    else\n                    {\n                        ignoreMipmapLimitProp.boolValue = !useMipmapLimits;\n                    }\n                }\n            }\n            EditorGUI.EndProperty();\n\n            if (useMipmapLimits)\n            {\n                using (new EditorGUI.IndentLevelScope())\n                {\n                    List<string> options = new List<string>();\n                    options.Add(L10n.Tr(\"None (Use Global Mipmap Limit)\"));\n\n                    // Add all known groups\n                    var groupNames = TextureMipmapLimitGroups.GetGroups();\n                    if (groupNames.Length > 0)\n                    {\n                        options.Add(string.Empty); // Separator\n                        options.AddRange(groupNames);\n                    }\n\n                    // If a group is not known, make sure to add it to the options anyway\n                    if (groupNameProp.stringValue != string.Empty && !options.Contains(groupNameProp.stringValue))\n                    {\n                        options.Add(string.Empty); // Seperator\n                        options.Add(groupNameProp.stringValue);\n                    }\n\n                    rect = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight);\n                    label = EditorGUI.BeginProperty(rect, s_Styles.mipmapLimitGroupName, groupNameProp);\n                    using (var changed = new EditorGUI.ChangeCheckScope())\n                    {\n                        int selectedIndex = groupNameProp.hasMultipleDifferentValues ? -1 : ((groupNameProp.stringValue == string.Empty) ? 0 : options.IndexOf(groupNameProp.stringValue));\n                        selectedIndex = EditorGUI.Popup(rect, label, selectedIndex, options.ToArray());\n                        if (changed.changed)\n                        {\n                            groupNameProp.stringValue = selectedIndex == 0 ? string.Empty : options[selectedIndex];\n                        }\n                    }\n                    EditorGUI.EndProperty();\n\n                    bool displayGroupNameWarning = groupNameProp.stringValue.Length > 0 && !TextureMipmapLimitGroups.HasGroup(groupNameProp.stringValue);\n                    if (displayGroupNameWarning)\n                    {\n                        EditorGUILayout.HelpBox(s_Styles.mipmapLimitGroupWarning.text, MessageType.Warning, true);\n                    }\n                }\n            }\n        }\n\n        void MipMapGUI(TextureInspectorGUIElement guiElements)\n        {\n            ToggleFromInt(m_EnableMipMap, s_Styles.generateMipMaps);\n\n            m_ShowMipMapSettings.target =\n                m_EnableMipMap.boolValue &&\n                !m_EnableMipMap.hasMultipleDifferentValues &&\n                // 3D textures don't use any of mipmap settings, just the \"yes/no\" flag\n                (TextureImporterShape)m_TextureShape.intValue != TextureImporterShape.Texture3D;\n\n            if (EditorGUILayout.BeginFadeGroup(m_ShowMipMapSettings.faded))\n            {\n                EditorGUI.indentLevel++;\n\n                m_ShowMipmapGenerationSettings = EditorGUILayout.Foldout(m_ShowMipmapGenerationSettings, s_Styles.showMipmapGenerationSettings, true);\n                if (m_ShowMipmapGenerationSettings)\n                {\n                    EditorGUI.indentLevel++;\n                    MipmapGenerationGUI();\n                    EditorGUI.indentLevel--;\n                }\n\n                bool supportsMipmapLimits =\n                    ((TextureImporterShape)m_TextureShape.intValue == TextureImporterShape.Texture2D && !m_VTOnly.boolValue) // If VTOnly, then we don't show the MipmapLimits GUI since its values are ignored anyway\n                    || (TextureImporterShape)m_TextureShape.intValue == TextureImporterShape.Texture2DArray;\n\n                if (supportsMipmapLimits)\n                {\n                    DoMipmapLimitsGUI(m_IgnoreMipmapLimit, m_MipmapLimitGroupName);\n                }\n\n                StreamingMipmapsGUI();\n\n                EditorGUI.indentLevel--;\n            }\n            EditorGUILayout.EndFadeGroup();\n        }\n\n        void PngGammaGUI(TextureInspectorGUIElement guiElements)\n        {\n            if (m_IsPNG)\n                ToggleFromInt(m_IgnorePngGamma, s_Styles.ignorePngGamma);\n        }\n\n        void BumpGUI(TextureInspectorGUIElement guiElements)\n        {\n            EditorGUI.BeginChangeCheck();\n\n            ToggleFromInt(m_ConvertToNormalMap, s_Styles.generateFromBump);\n            m_ShowBumpGenerationSettings.target = m_ConvertToNormalMap.intValue > 0;\n            if (EditorGUILayout.BeginFadeGroup(m_ShowBumpGenerationSettings.faded))\n            {\n                EditorGUI.indentLevel++;\n                EditorGUILayout.Slider(m_HeightScale, 0.0F, 0.3F, s_Styles.bumpiness);\n                EditorGUILayout.Popup(m_NormalMapFilter, s_Styles.bumpFilteringOptions, s_Styles.bumpFiltering);\n                EditorGUI.indentLevel--;\n            }\n            EditorGUILayout.EndFadeGroup();\n            ToggleFromInt(m_FlipGreenChannel, s_Styles.flipGreenChannel);\n\n            if (EditorGUI.EndChangeCheck())\n                BaseTextureImportPlatformSettings.SyncPlatformSettings(m_PlatformSettings.ConvertAll<BaseTextureImportPlatformSettings>(x => x as BaseTextureImportPlatformSettings));\n        }\n\n        // A label, and then four dropdown popups to pick RGBA swizzle sources.\n        // Code flow modeled similar to a Vector4Field.\n        static readonly int s_SwizzleFieldHash = \"SwizzleField\".GetHashCode();\n        static readonly string[] s_SwizzleOptions = new[] {\"R\",\"G\",\"B\",\"A\", \"1-R\",\"1-G\",\"1-B\",\"1-A\", \"0\",\"1\" };\n        static uint SwizzleField(GUIContent label, uint swizzle)\n        {\n            var rect = EditorGUILayout.s_LastRect = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector4, label), EditorStyles.numberField);\n            var id = GUIUtility.GetControlID(s_SwizzleFieldHash, FocusType.Keyboard, rect);\n            rect = EditorGUI.MultiFieldPrefixLabel(rect, id, label, 4);\n            rect.height = EditorGUI.kSingleLineHeight;\n\n            float w = (rect.width - 3 * EditorGUI.kSpacingSubLabel) / 4;\n            var subRect = new Rect(rect) {width = w};\n            var oldIndent = EditorGUI.indentLevel;\n            EditorGUI.indentLevel = 0;\n            for (int i = 0; i < 4; i++)\n            {\n                int shift = 8 * i;\n                uint swz = (swizzle >> shift) & 0xFF;\n                swz = (uint)EditorGUI.Popup(subRect, (int)swz, s_SwizzleOptions);\n                swizzle &= ~(0xFFu << shift);\n                swizzle |= swz << shift;\n                subRect.x += w + EditorGUI.kSpacingSubLabel;\n            }\n            EditorGUI.indentLevel = oldIndent;\n            return swizzle;\n        }\n\n        static void SwizzleField(SerializedProperty property, GUIContent label)\n        {\n            EditorGUI.BeginProperty(EditorGUILayout.BeginHorizontal(), label, property);\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = property.hasMultipleDifferentValues;\n            var value = SwizzleField(label, property.uintValue);\n            EditorGUI.showMixedValue = false;\n            if (EditorGUI.EndChangeCheck())\n                property.uintValue = value;\n            EditorGUILayout.EndHorizontal();\n            EditorGUI.EndProperty();\n        }\n\n        void SwizzleGui(TextureInspectorGUIElement guiElements)\n        {\n            SwizzleField(m_Swizzle, s_Styles.swizzle);\n        }\n\n        bool m_ShowPerAxisWrapModes = false;\n\n        private bool TargetsHaveNPOTTextures()\n        {\n            foreach (var target in targets)\n            {\n                int w = -1, h = -1;\n                var imp = (TextureImporter)target;\n                imp.GetWidthAndHeight(ref w, ref h);\n                if (!Mathf.IsPowerOfTwo(w) || !Mathf.IsPowerOfTwo(h))\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        void TextureSettingsGUI()\n        {\n            // Wrap mode\n            // NOTE: once we get ability to have 3D/Volume texture shapes, should pass true for isVolume based on m_TextureShape\n            bool isVolume = false;\n            TextureInspector.WrapModePopup(m_WrapU, m_WrapV, m_WrapW, isVolume, ref m_ShowPerAxisWrapModes, assetTarget == null);\n\n            // Display warning about repeat wrap mode on restricted npot emulation\n            if (m_NPOTScale.intValue == (int)TextureImporterNPOTScale.None &&\n                (m_WrapU.intValue == (int)TextureWrapMode.Repeat || m_WrapV.intValue == (int)TextureWrapMode.Repeat) &&\n                !ShaderUtil.hardwareSupportsFullNPOT)\n            {\n                bool displayWarning = TargetsHaveNPOTTextures();\n                if (displayWarning)\n                {\n                    GUIContent c = EditorGUIUtility.TrTextContent(\"Graphics device doesn't support Repeat wrap mode on NPOT textures. Falling back to Clamp.\");\n                    EditorGUILayout.HelpBox(c.text, MessageType.Warning, true);\n                }\n            }\n\n            // Filter mode\n            EditorGUILayout.IntPopup(m_FilterMode, s_Styles.filterModeOptions, m_FilterModeOptions, s_Styles.filterMode);\n\n            // Aniso\n            bool showAniso = (FilterMode)m_FilterMode.intValue != FilterMode.Point\n                && m_EnableMipMap.intValue > 0\n                && (TextureImporterShape)m_TextureShape.intValue != TextureImporterShape.TextureCube\n                && (TextureImporterShape)m_TextureShape.intValue != TextureImporterShape.Texture3D;\n            using (new EditorGUI.DisabledScope(!showAniso))\n            {\n                EditorGUILayout.IntSlider(m_Aniso, 0, 16, \"Aniso Level\");\n\n                TextureInspector.DoAnisoGlobalSettingNote(m_Aniso.intValue);\n            }\n        }\n\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            bool wasEnabled = GUI.enabled;\n\n            EditorGUILayout.Space();\n\n            // Texture Usage\n            int oldTextureType = m_TextureType.intValue;\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.IntPopup(m_TextureType, s_Styles.textureTypeOptions, s_Styles.textureTypeValues, s_Styles.textureTypeTitle);\n            // (case 857001) EndChangeCheck will return true even if the same value is selected.\n            // Consequently the sprite will be reset to Single mode and looks very confusing to the user.\n            int newTextureType = m_TextureType.intValue;\n            if (EditorGUI.EndChangeCheck() && (oldTextureType != newTextureType))\n            {\n                // please note that in GetSerializedPropertySettings() we will init TextureImporterSettings from current state\n                //   and at this point m_TextureType still has *old* value\n                // meaning that we still need to change TextureImporterSettings textureType manually\n                // NB we do these weird things partly because ApplyTextureType has early out\n                // NB hence we want settings to have *old* textureType when calling it\n                TextureImporterSettings settings = GetSerializedPropertySettings();\n                settings.textureType = (TextureImporterType)oldTextureType;\n                settings.ApplyTextureType((TextureImporterType)newTextureType);\n                settings.textureType = (TextureImporterType)newTextureType;\n\n                SetSerializedPropertySettings(settings);\n\n                BaseTextureImportPlatformSettings.SyncPlatformSettings(m_PlatformSettings.ConvertAll<BaseTextureImportPlatformSettings>(x => x as BaseTextureImportPlatformSettings));\n            }\n\n            // Texture Shape\n            int[] shapeArray = s_Styles.textureShapeValuesDictionnary[m_TextureTypeGUIElements[(int)newTextureType].shapeCaps];\n            using (new EditorGUI.DisabledScope(shapeArray.Length == 1 || m_TextureType.intValue == (int)TextureImporterType.Cookie)) // Cookie is a special case because the cookie type drives the shape of the texture\n            {\n                EditorGUILayout.IntPopup(m_TextureShape, s_Styles.textureShapeOptionsDictionnary[m_TextureTypeGUIElements[(int)newTextureType].shapeCaps], s_Styles.textureShapeValuesDictionnary[m_TextureTypeGUIElements[(int)newTextureType].shapeCaps], s_Styles.textureShape);\n            }\n\n            // Switching usage can lead to a subset of the current available shapes.\n            if (Array.IndexOf(shapeArray, m_TextureShape.intValue) == -1)\n            {\n                m_TextureShape.intValue = shapeArray[0];\n            }\n\n            EditorGUILayout.Space();\n\n            // Show advanced settings for texture types that have the same subset of advanced settings (rather than just those that are exactly the same type)\n            bool showAdvanced = false;\n            if (m_TextureType.hasMultipleDifferentValues)\n            {\n                showAdvanced = true;\n                int iteratedTextureType = (int)m_TextureTypes[0];\n                TextureInspectorGUIElement firstAdvancedElements = m_TextureTypeGUIElements[iteratedTextureType].advancedElements;\n                for (int selectionIndex = 1; selectionIndex < m_TextureTypes.Count; selectionIndex++)\n                {\n                    iteratedTextureType = (int)m_TextureTypes[selectionIndex];\n                    if (firstAdvancedElements != m_TextureTypeGUIElements[iteratedTextureType].advancedElements)\n                    {\n                        showAdvanced = false;\n                        break;\n                    }\n                }\n            }\n            else\n            {\n                showAdvanced = true;\n            }\n\n            if (showAdvanced)\n            {\n                DoGUIElements(m_TextureTypeGUIElements[newTextureType].commonElements, m_GUIElementsDisplayOrder);\n                if (m_TextureTypeGUIElements[newTextureType].advancedElements != 0)\n                {\n                    EditorGUILayout.Space();\n\n                    m_ShowAdvanced = EditorGUILayout.Foldout(m_ShowAdvanced, s_Styles.showAdvanced, true);\n                    if (m_ShowAdvanced)\n                    {\n                        EditorGUI.indentLevel++;\n                        DoGUIElements(m_TextureTypeGUIElements[newTextureType].advancedElements, m_GUIElementsDisplayOrder);\n                        EditorGUI.indentLevel--;\n                    }\n                }\n            }\n\n            EditorGUILayout.Space();\n\n            // Filter mode, aniso, and wrap mode GUI\n            TextureSettingsGUI();\n\n            BaseTextureImportPlatformSettings.InitPlatformSettings(m_PlatformSettings.ConvertAll<BaseTextureImportPlatformSettings>(x => x as BaseTextureImportPlatformSettings));\n            m_PlatformSettings.ForEach(settings => settings.CacheSerializedProperties(m_PlatformSettingsArrProp));\n            GUILayout.Space(10);\n\n            //Show platform grouping\n            int selectedPage = EditorGUILayout.BeginPlatformGrouping(BaseTextureImportPlatformSettings.GetBuildPlayerValidPlatforms(), s_Styles.defaultPlatform, EditorStyles.frameBox, idx =>\n            {\n                var ps = m_PlatformSettings[idx + 1];\n                var model = ps.model;\n                if (model.isDefault)\n                    return false;\n                if (model.overriddenIsDifferent || model.allAreOverridden)\n                    return true;\n                return false;\n            });\n\n\n            //Show platform settings\n            using (var changed = new EditorGUI.ChangeCheckScope())\n            {\n                BaseTextureImportPlatformSettings.ShowPlatformSpecificSettings(m_PlatformSettings.ConvertAll<BaseTextureImportPlatformSettings>(x => x as BaseTextureImportPlatformSettings), selectedPage);\n                // Doing it this way is slow, but it ensure Presets get updated correctly whenever the UI is being changed.\n                if (changed.changed)\n                {\n                    Undo.RegisterCompleteObjectUndo(targets, \"Inspector\");\n                    BaseTextureImportPlatformSettings.ApplyPlatformSettings(m_PlatformSettings.ConvertAll<BaseTextureImportPlatformSettings>(x => x as BaseTextureImportPlatformSettings));\n                }\n            }\n\n            serializedObject.ApplyModifiedProperties();\n\n            ApplyRevertGUI();\n\n            // screw this - after lots of retries i have no idea how to poll it only when we change related stuff\n            UpdateImportWarning();\n            if (!string.IsNullOrEmpty(m_ImportWarning))\n                EditorGUILayout.HelpBox(m_ImportWarning, MessageType.Warning);\n\n            GUI.enabled = wasEnabled;\n        }\n\n        bool ShouldDisplayGUIElement(TextureInspectorGUIElement guiElements, TextureInspectorGUIElement guiElement)\n        {\n            return ((guiElements & guiElement) == guiElement);\n        }\n\n        private void DoGUIElements(TextureInspectorGUIElement guiElements, List<TextureInspectorGUIElement> guiElementsDisplayOrder)\n        {\n            foreach (TextureInspectorGUIElement guiElement in guiElementsDisplayOrder)\n            {\n                if (ShouldDisplayGUIElement(guiElements, guiElement) && m_GUIElementMethods.ContainsKey(guiElement))\n                {\n                    m_GUIElementMethods[guiElement](guiElements);\n                }\n            }\n        }\n\n        // Returns false if method fails to get info\n        static bool CountImportersWithAlpha(Object[] importers, out int count)\n        {\n            // DoesSourceTextureHaveAlpha will throw exception on importer reset (593478).\n            try\n            {\n                count = 0;\n                foreach (Object t in importers)\n                    if ((t as TextureImporter).DoesSourceTextureHaveAlpha())\n                        count++;\n                return true;\n            }\n            catch\n            {\n                count = importers.Length;\n                return false;\n            }\n        }\n\n        static bool CountImportersWithHDR(Object[] importers, out int count)\n        {\n            // DoesSourceTextureHaveAlpha will throw exception on importer reset (593478).\n            try\n            {\n                count = 0;\n                foreach (Object t in importers)\n                    if ((t as TextureImporter).IsSourceTextureHDR())\n                        count++;\n                return true;\n            }\n            catch\n            {\n                count = importers.Length;\n                return false;\n            }\n        }\n\n        void SetCookieLightTypeDefaults(TextureImporterCookieLightType cookieLightType)\n        {\n            // Note that, out of all of these, only the TextureShape is truly strongly enforced.\n            // The other settings are nothing more than recommended defaults and can be modified\n            // by the user at any time.\n            switch (cookieLightType)\n            {\n                case TextureImporterCookieLightType.Spot:\n                    m_BorderMipMap.intValue = 1;\n                    m_WrapU.intValue = m_WrapV.intValue = m_WrapW.intValue = (int)TextureWrapMode.Clamp;\n                    m_GenerateCubemap.intValue = (int)TextureImporterGenerateCubemap.AutoCubemap;\n                    m_TextureShape.intValue = (int)TextureImporterShape.Texture2D;\n                    break;\n                case TextureImporterCookieLightType.Point:\n                    m_BorderMipMap.intValue = 0;\n                    m_WrapU.intValue = m_WrapV.intValue = m_WrapW.intValue = (int)TextureWrapMode.Clamp;\n                    m_GenerateCubemap.intValue = (int)TextureImporterGenerateCubemap.Spheremap;\n                    m_TextureShape.intValue = (int)TextureImporterShape.TextureCube;\n                    break;\n                case TextureImporterCookieLightType.Directional:\n                    m_BorderMipMap.intValue = 0;\n                    m_WrapU.intValue = m_WrapV.intValue = m_WrapW.intValue = (int)TextureWrapMode.Repeat;\n                    m_GenerateCubemap.intValue = (int)TextureImporterGenerateCubemap.AutoCubemap;\n                    m_TextureShape.intValue = (int)TextureImporterShape.Texture2D;\n                    break;\n            }\n        }\n\n        internal static string[] BuildTextureStrings(int[] texFormatValues)\n        {\n            string[] retval = new string[texFormatValues.Length];\n            for (int i = 0; i < texFormatValues.Length; i++)\n            {\n                int val = texFormatValues[i];\n                retval[i] = \" \" + (val < 0 ? \"Auto\" : GraphicsFormatUtility.GetFormatString((TextureFormat)val));\n            }\n            return retval;\n        }\n\n        internal static bool IsFormatRequireCompressionSetting(TextureImporterFormat format)\n        {\n            return ArrayUtility.Contains<TextureImporterFormat>(TextureImporterInspector.kFormatsWithCompressionSettings, format);\n        }\n\n        private static bool IsPowerOfTwo(int f)\n        {\n            return ((f & (f - 1)) == 0);\n        }\n\n        bool ShouldShowWarningForReadWrite()\n        {\n            const int maxRecommendedSize = 536870912; // 512 MB\n\n            if (textureInspector && textureInspector.targets != null)\n            {\n                foreach (Texture texture in textureInspector.targets)\n                {\n                    if (texture)\n                    {\n                        if (TextureUtil.GetStorageMemorySizeLong(texture) > maxRecommendedSize)\n                        {\n                            return true;\n                        }\n                    }\n                }\n            }\n            return false;\n        }\n\n        public virtual void BuildTargetList()\n        {\n            BuildPlatform[] validPlatforms = BaseTextureImportPlatformSettings.GetBuildPlayerValidPlatforms();\n\n            m_PlatformSettings = new List<TextureImportPlatformSettings>();\n            m_PlatformSettings.Add(new TextureImportPlatformSettings(s_DefaultPlatformName, BuildTarget.StandaloneWindows, this));\n\n            foreach (BuildPlatform bp in validPlatforms)\n                m_PlatformSettings.Add(new TextureImportPlatformSettings(bp.name, bp.defaultTarget, this));\n        }\n\n        public override bool HasModified()\n        {\n            if (base.HasModified())\n                return true;\n\n            foreach (TextureImportPlatformSettings ps in m_PlatformSettings)\n            {\n                if (ps.model.HasChanged())\n                    return true;\n            }\n\n            return false;\n        }\n\n\n        [Obsolete(\"UnityUpgradeable () -> DiscardChanges\")]\n        protected override void ResetValues()\n        {\n            DiscardChanges();\n        }\n\n        public override void DiscardChanges()\n        {\n            base.DiscardChanges();\n\n            CacheSerializedProperties();\n\n            BuildTargetList();\n            System.Diagnostics.Debug.Assert(!HasModified(), \"TextureImporter settings are marked as modified after calling Reset.\");\n        }\n\n        protected override void Apply()\n        {\n            SpriteUtilityWindow.ApplySpriteEditorWindow();\n            base.Apply();\n            RefreshPreviewChannelSelection();\n            BaseTextureImportPlatformSettings.ApplyPlatformSettings(m_PlatformSettings.ConvertAll<BaseTextureImportPlatformSettings>(x => x as BaseTextureImportPlatformSettings));\n        }\n\n        public override void DrawPreview(Rect previewArea)\n        {\n            base.DrawPreview(previewArea);\n\n            //Drawing texture previewers for VT only textures will have generated texture tile request.\n            //We need to update the VT system to actually stream these tiles into VRAM and render the textures correctly.\n            if (textureInspector != null && textureInspector.hasTargetUsingVTMaterial)\n                VirtualTexturing.System.Update();\n        }\n\n        internal override void PostSerializedObjectCreation()\n        {\n            base.PostSerializedObjectCreation();\n            Initialize();\n        }\n\n        private void RefreshPreviewChannelSelection()\n        {\n            //If the Preview is null or NOT the TextureInspector (e.g. ObjectPreview) then return, we do not need to refresh the preview channel selection\n            if (!(preview is TextureInspector))\n                return;\n\n            string platformName = BuildPipeline.GetBuildTargetName(EditorUserBuildSettings.activeBuildTarget);\n            for (int i = 0; i < targets.Length; i++)\n            {\n                //Is preview currently Alpha-only format? Skip if not.\n                bool wasAlphaOnlyTextureFormat = textureInspector.targets[i] is Texture2D texture && GraphicsFormatUtility.IsAlphaOnlyFormat(texture.format);\n                if (!wasAlphaOnlyTextureFormat)\n                    continue;\n\n                //Get the Texture Importer\n                TextureImporter t = (TextureImporter)targets[i];\n\n                //Are we about to set the preview to an Alpha-only format?\n                TextureImporterFormat textureImporterFormat = t.GetPlatformTextureSettings(platformName).format;\n                TextureFormat textureFormat = textureImporterFormat == TextureImporterFormat.Automatic ? (TextureFormat)t.GetAutomaticFormat(platformName) : (TextureFormat)textureImporterFormat;\n\n                //Where the preview is no-longer alpha only, reset all previews to RGB - Note: It is not possible to mix channel selection in TextureInspector.\n                if (!GraphicsFormatUtility.IsAlphaOnlyFormat(textureFormat))\n                {\n                    textureInspector.m_PreviewMode = TextureInspector.PreviewMode.RGB;\n                    break;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/InSceneAssetUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.SceneManagement;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/InSceneAssetUtility.h\")]\n    public struct InSceneAssetInformation\n    {\n        [NativeName(\"inSceneAsset\")]\n        Object m_InSceneAsset;\n\n        [NativeName(\"referencingObjects\")]\n        Object[] m_ReferencingObjects;\n\n        public Object inSceneAsset\n        {\n            get { return m_InSceneAsset; }\n            set { m_InSceneAsset = value; }\n        }\n\n        public Object[] referencingObjects\n        {\n            get { return m_ReferencingObjects; }\n            set { m_ReferencingObjects = value; }\n        }\n    }\n\n    [NativeHeader(\"Editor/Src/InSceneAssetUtility.h\")]\n    public static class InSceneAssetUtility\n    {\n        [FreeFunction(\"CollectInSceneAssetsFromGameObjectsInternal\")]\n        static extern InSceneAssetInformation[] CollectInSceneAssetsFromGameObjectsInternal(GameObject[] gameObjects);\n\n        [FreeFunction(\"CollectInSceneAssetsFromSceneInternal\")]\n        static extern InSceneAssetInformation[] CollectInSceneAssetsFromSceneInternal(Scene scene);\n\n        [FreeFunction(\"IsInSceneAsset\")]\n        public static extern bool IsInSceneAsset(Object sourceObject);\n\n        public static InSceneAssetInformation[] CollectInSceneAssets(GameObject[] gameObjects)\n        {\n            return CollectInSceneAssetsFromGameObjectsInternal(gameObjects);\n        }\n\n        public static InSceneAssetInformation[] CollectInSceneAssets(Scene scene)\n        {\n            return CollectInSceneAssetsFromSceneInternal(scene);\n        }\n\n        [FreeFunction(\"CreateAssetFromInSceneAsset\")]\n        public static extern bool CreateAssetFromInSceneAsset(Object inSceneAsset, string filePath);\n\n        [FreeFunction(\"CreateInSceneAssetFromAsset\")]\n        public static extern Object CreateInSceneAssetFromAsset(Object asset, GameObject gameObjectReferencingAsset);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AimConstraintEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Animations;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AimConstraint))]\n    [CanEditMultipleObjects]\n    internal class AimConstraintEditor : ConstraintEditorBase\n    {\n        private SerializedProperty m_RotationAtRest;\n        private SerializedProperty m_RotationOffset;\n        private SerializedProperty m_AimVector;\n        private SerializedProperty m_UpVector;\n        private SerializedProperty m_WorldUpVector;\n        private SerializedProperty m_WorldUpObject;\n        private SerializedProperty m_WorldUpType;\n        private SerializedProperty m_Weight;\n        private SerializedProperty m_IsContraintActive;\n        private SerializedProperty m_IsLocked;\n        private SerializedProperty m_Sources;\n\n        internal override SerializedProperty atRest { get { return m_RotationAtRest; } }\n        internal override SerializedProperty offset { get { return m_RotationOffset; } }\n        internal override SerializedProperty weight { get { return m_Weight; } }\n        internal override SerializedProperty isContraintActive { get { return m_IsContraintActive; } }\n        internal override SerializedProperty isLocked { get { return m_IsLocked; } }\n        internal override SerializedProperty sources { get { return m_Sources; } }\n\n        private class Styles : ConstraintStyleBase\n        {\n            GUIContent m_RotationAtRest = EditorGUIUtility.TrTextContent(\"Rotation At Rest\", \"The orientation of the constrained object when the weights of the sources add up to zero or when all the rotation axes are disabled.\");\n            GUIContent m_RotationOffset = EditorGUIUtility.TrTextContent(\"Rotation Offset\", \"The offset from the constrained orientation.\");\n\n            GUIContent m_RotationAxes = EditorGUIUtility.TrTextContent(\"Freeze Rotation Axes\", \"The axes along which the constraint is applied.\");\n\n            GUIContent m_AimVector = EditorGUIUtility.TrTextContent(\"Aim Vector\", \"Specifies which axis of the constrained object should aim at the target.\");\n            GUIContent m_UpVector = EditorGUIUtility.TrTextContent(\"Up Vector\", \"Specifies the direction of the up vector in local space.\");\n            GUIContent m_WorldUpVector = EditorGUIUtility.TrTextContent(\"World Up Vector\", \"Specifies the direction of the global up vector.\");\n            GUIContent m_WorldUpObject = EditorGUIUtility.TrTextContent(\"World Up Object\", \"The reference object when the World Up Type is either Object Up or Object Rotation Up.\");\n            GUIContent m_WorldUpType = EditorGUIUtility.TrTextContent(\"World Up Type\", \"Specifies how the world up vector should be computed.\");\n            GUIContent[] m_WorldUpTypes =\n            {\n                EditorGUIUtility.TrTextContent(\"Scene Up\", \"Use the Y axis as the world up vector.\"),\n                EditorGUIUtility.TrTextContent(\"Object Up\", \"Use a vector that points to the reference object as the world up vector.\"),\n                EditorGUIUtility.TrTextContent(\"Object Rotation Up\", \"Use a vector defined in the reference object's local space as the world up vector.\"),\n                EditorGUIUtility.TrTextContent(\"Vector\", \"The world up vector is user defined.\"),\n                EditorGUIUtility.TrTextContent(\"None\", \"The world up vector is ignored.\")\n            };\n            public override GUIContent AtRest { get { return m_RotationAtRest; } }\n            public override GUIContent Offset { get { return m_RotationOffset; } }\n            public GUIContent FreezeAxes { get { return m_RotationAxes; } }\n            public GUIContent AimVector { get { return m_AimVector; } }\n            public GUIContent UpVector { get { return m_UpVector; } }\n            public GUIContent WorldUpVector { get { return m_WorldUpVector; } }\n            public GUIContent WorldUpObject { get { return m_WorldUpObject; } }\n            public GUIContent WorldUpType { get { return m_WorldUpType; } }\n            public GUIContent[] WorldUpTypes { get { return m_WorldUpTypes; } }\n        }\n\n        private static Styles s_Style = null;\n\n        public void OnEnable()\n        {\n            if (s_Style == null)\n                s_Style = new Styles();\n\n            m_RotationAtRest = serializedObject.FindProperty(\"m_RotationAtRest\");\n            m_RotationOffset = serializedObject.FindProperty(\"m_RotationOffset\");\n\n            m_AimVector = serializedObject.FindProperty(\"m_AimVector\");\n            m_UpVector = serializedObject.FindProperty(\"m_UpVector\");\n            m_WorldUpVector = serializedObject.FindProperty(\"m_WorldUpVector\");\n            m_WorldUpObject = serializedObject.FindProperty(\"m_WorldUpObject\");\n            m_WorldUpType = serializedObject.FindProperty(\"m_UpType\");\n\n            m_Weight = serializedObject.FindProperty(\"m_Weight\");\n            m_IsContraintActive = serializedObject.FindProperty(\"m_Active\");\n            m_IsLocked = serializedObject.FindProperty(\"m_IsLocked\");\n            m_Sources = serializedObject.FindProperty(\"m_Sources\");\n\n            OnEnable(s_Style);\n        }\n\n        internal override void OnValueAtRestChanged()\n        {\n            foreach (var t in targets)\n                (t as AimConstraint).transform.SetLocalEulerAngles(atRest.vector3Value, RotationOrder.OrderZXY);\n        }\n\n        internal override void ShowOffset<T>(ConstraintStyleBase style)\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(offset, style.Offset);\n            if (EditorGUI.EndChangeCheck())\n            {\n                foreach (var t in targets)\n                    (t as T).UserUpdateOffset();\n            }\n        }\n\n        internal override void ShowCustomProperties()\n        {\n            EditorGUILayout.PropertyField(m_AimVector, s_Style.AimVector);\n            EditorGUILayout.PropertyField(m_UpVector, s_Style.UpVector);\n            EditorGUILayout.Popup(m_WorldUpType, s_Style.WorldUpTypes, s_Style.WorldUpType);\n\n            var worldUpType = (AimConstraint.WorldUpType)m_WorldUpType.intValue;\n            using (new EditorGUI.DisabledGroupScope(worldUpType != AimConstraint.WorldUpType.ObjectRotationUp && worldUpType != AimConstraint.WorldUpType.Vector))\n            {\n                EditorGUILayout.PropertyField(m_WorldUpVector, s_Style.WorldUpVector);\n            }\n\n            using (new EditorGUI.DisabledGroupScope(worldUpType != AimConstraint.WorldUpType.ObjectUp && worldUpType != AimConstraint.WorldUpType.ObjectRotationUp))\n            {\n                EditorGUILayout.PropertyField(m_WorldUpObject, s_Style.WorldUpObject);\n            }\n        }\n\n        internal override void ShowFreezeAxesControl()\n        {\n            Rect drawRect = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, s_Style.FreezeAxes), EditorStyles.toggle);\n            EditorGUI.MultiPropertyField(drawRect, s_Style.Axes, serializedObject.FindProperty(\"m_AffectRotationX\"), s_Style.FreezeAxes);\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (s_Style == null)\n                s_Style = new Styles();\n\n            serializedObject.Update();\n\n            ShowConstraintEditor<AimConstraint>(s_Style);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AnimationClipEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.Animations;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Object = UnityEngine.Object;\nusing System.Globalization;\nusing UnityEditorInternal;\nusing AnimatorController = UnityEditor.Animations.AnimatorController;\nusing AnimatorControllerLayer = UnityEditor.Animations.AnimatorControllerLayer;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AnimationClip))]\n    [CanEditMultipleObjects]\n    internal class AnimationClipEditor : Editor\n    {\n        internal static void EditWithImporter(AnimationClip clip)\n        {\n            ModelImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(clip)) as ModelImporter;\n\n            if (importer)\n            {\n                Selection.activeObject = AssetDatabase.LoadMainAssetAtPath(importer.assetPath);\n                ModelImporterEditor inspector = Editor.CreateEditor(importer) as ModelImporterEditor;\n                EditorPrefs.SetInt(inspector.GetType().Name + \"ActiveEditorIndex\", 2);\n                Object.DestroyImmediate(inspector);\n\n                int clipIndex = 0;\n                //The ModelImporter handles \"ClipAnimations\" and \"DefaultClipAnimations\" independently, where there are no user specified clips, this clip must be a default clip.\n                var clipAnimations = importer.clipAnimations.Any() ? importer.clipAnimations : importer.defaultClipAnimations;\n                for (int i = 0; i < clipAnimations.Length; i++)\n                {\n                    if (clipAnimations[i].name == clip.name)\n                    {\n                        clipIndex = i;\n                        break;\n                    }\n                }\n\n                EditorPrefs.SetInt(ModelImporterClipEditor.ActiveClipIndex, clipIndex);\n            }\n        }\n\n        internal static class Styles\n        {\n            public static GUIContent StartFrame = EditorGUIUtility.TrTextContent(\"Start\", \"Start frame of the clip.\");\n            public static GUIContent EndFrame = EditorGUIUtility.TrTextContent(\"End\", \"End frame of the clip.\");\n            public static string AverageVelocity = L10n.Tr(\"Average Velocity: {0}\\nAverage Angular Y Speed: {1} deg/s\");\n\n            public static GUIContent HasAdditiveReferencePose = EditorGUIUtility.TrTextContent(\"Additive Reference Pose\", \"Enable to define the additive reference pose frame.\");\n            public static GUIContent AdditiveReferencePoseFrame = EditorGUIUtility.TrTextContent(\"Pose Frame\", \"Pose Frame.\");\n            public static GUIContent LoopTime = EditorGUIUtility.TrTextContent(\"Loop Time\", \"Enable to make the animation play through and then restart when the end is reached.\");\n            public static GUIContent LoopPose = EditorGUIUtility.TrTextContent(\"Loop Pose\", \"Enable to make the animation loop seamlessly.\");\n            public static GUIContent LoopCycleOffset = EditorGUIUtility.TrTextContent(\"Cycle Offset\", \"Offset to the cycle of a looping animation, if we want to start it at a different time.\");\n            public static GUIContent RootTransformRotation = EditorGUIUtility.TrTextContent(\"Root Transform Rotation\");\n            public static GUIContent RootTransformRotationY = EditorGUIUtility.TrTextContent(\"Root Transform Position (Y)\");\n            public static GUIContent RootTransformPositionXZ = EditorGUIUtility.TrTextContent(\"Root Transform Position (XZ)\");\n\n            public static GUIContent BakeIntoPoseOrientation = EditorGUIUtility.TrTextContent(\"Bake Into Pose\", \"Enable to make root rotation be baked into the movement of the bones. Disable to make root rotation be stored as root motion.\");\n            public static GUIContent OrientationOffsetY = EditorGUIUtility.TrTextContent(\"Offset\", \"Offset to the root rotation (in degrees).\");\n\n            public static GUIContent BasedUponOrientation = EditorGUIUtility.TrTextContent(\"Based Upon\", \"What the root rotation is based upon.\");\n            public static GUIContent BasedUponStartOrientation = EditorGUIUtility.TrTextContent(\"Based Upon (at Start)\", \"What the root rotation is based upon.\");\n\n            public static GUIContent[] BasedUponRotationHumanOpt =\n            {\n                EditorGUIUtility.TrTextContent(\"Original\", \"Keeps the rotation as it is authored in the source file.\"),\n                EditorGUIUtility.TrTextContent(\"Body Orientation\", \"Keeps the upper body pointing forward.\")\n            };\n\n            public static GUIContent[] BasedUponRotationOpt =\n            {\n                EditorGUIUtility.TrTextContent(\"Original\", \"Keeps the rotation as it is authored in the source file.\"),\n                EditorGUIUtility.TrTextContent(\"Root Node Rotation\", \"Keeps the upper body pointing forward.\")\n            };\n\n            public static GUIContent BakeIntoPosePositionY = EditorGUIUtility.TrTextContent(\"Bake Into Pose\", \"Enable to make vertical root motion be baked into the movement of the bones. Disable to make vertical root motion be stored as root motion.\");\n            public static GUIContent PositionOffsetY = EditorGUIUtility.TrTextContent(\"Offset\", \"Offset to the vertical root position.\");\n\n            public static GUIContent BasedUponPositionY = EditorGUIUtility.TrTextContent(\"Based Upon\", \"What the vertical root position is based upon.\");\n            public static GUIContent BasedUponStartPositionY = EditorGUIUtility.TrTextContent(\"Based Upon (at Start)\", \"What the vertical root position is based upon.\");\n\n\n            public static GUIContent[] BasedUponPositionYHumanOpt =\n            {\n                EditorGUIUtility.TrTextContent(\"Original\", \"Keeps the vertical position as it is authored in the source file.\"),\n                EditorGUIUtility.TrTextContent(\"Center of Mass\", \"Keeps the center of mass aligned with root transform position.\"),\n                EditorGUIUtility.TrTextContent(\"Feet\", \"Keeps the feet aligned with the root transform position.\")\n            };\n\n            public static GUIContent[] BasedUponPositionYOpt =\n            {\n                EditorGUIUtility.TrTextContent(\"Original\", \"Keeps the vertical position as it is authored in the source file.\"),\n                EditorGUIUtility.TrTextContent(\"Root Node Position\")\n            };\n\n            public static GUIContent BakeIntoPosePositionXZ = EditorGUIUtility.TrTextContent(\"Bake Into Pose\", \"Enable to make horizontal root motion be baked into the movement of the bones. Disable to make horizontal root motion be stored as root motion.\");\n\n            public static GUIContent BasedUponPositionXZ = EditorGUIUtility.TrTextContent(\"Based Upon\", \"What the horizontal root position is based upon.\");\n            public static GUIContent BasedUponStartPositionXZ = EditorGUIUtility.TrTextContent(\"Based Upon (at Start)\", \"What the horizontal root position is based upon.\");\n\n            public static GUIContent[] BasedUponPositionXZHumanOpt =\n            {\n                EditorGUIUtility.TrTextContent(\"Original\", \"Keeps the horizontal position as it is authored in the source file.\"),\n                EditorGUIUtility.TrTextContent(\"Center of Mass\", \"Keeps the center of mass aligned with root transform position.\")\n            };\n\n            public static GUIContent[] BasedUponPositionXZOpt =\n            {\n                EditorGUIUtility.TrTextContent(\"Original\", \"Keeps the horizontal position as it is authored in the source file.\"),\n                EditorGUIUtility.TrTextContent(\"Root Node Position\")\n            };\n\n            public static GUIContent Mirror = EditorGUIUtility.TrTextContent(\"Mirror\", \"Mirror left and right in this clip.\");\n\n            public static GUIContent Curves = EditorGUIUtility.TrTextContent(\"Curves\", \"Parameter-related curves.\");\n            public static GUIContent Length = EditorGUIUtility.TrTextContent(\"Length\");\n            public static GUIContent AddLoopFrame = EditorGUIUtility.TrTextContent(\"Add Loop Frame\");\n            public static GUIContent WrapMode = EditorGUIUtility.TrTextContent(\"Wrap Mode\");\n            public static GUIContent Events = EditorGUIUtility.TrTextContent(\"Events\");\n            public static GUIContent LoopMatch = EditorGUIUtility.TrTextContent(\"loop match\");\n\n            public static string InvalidMultiSelection = L10n.Tr(\"Both legacy and non legacy Animation Clips have been selected. This combination cannot be edited together. Select either legacy or non legacy Animation Clips.\");\n\n            public static GUIContent AddEventContent = EditorGUIUtility.TrIconContent(\"Animation.AddEvent\", \"Add Event.\");\n\n            public static GUIContent GreenLightIcon = EditorGUIUtility.IconContent(\"lightMeter/greenLight\");\n            public static GUIContent LightRimIcon = EditorGUIUtility.IconContent(\"lightMeter/lightRim\");\n            public static GUIContent OrangeLightIcon = EditorGUIUtility.IconContent(\"lightMeter/orangeLight\");\n            public static GUIContent RedLightIcon = EditorGUIUtility.IconContent(\"lightMeter/redLight\");\n\n            public static GUIContent PrevKeyContent = EditorGUIUtility.TrIconContent(\"Animation.PrevKey\", \"Go to previous key frame.\");\n            public static GUIContent NextKeyContent = EditorGUIUtility.TrIconContent(\"Animation.NextKey\", \"Go to next key frame.\");\n            public static GUIContent AddKeyframeContent = EditorGUIUtility.TrIconContent(\"Animation.AddKeyframe\", \"Add Keyframe.\");\n\n            public static GUIContent AddEvent = EditorGUIUtility.TrTextContent(\"Add Animation Event\");\n            public static GUIContent DeleteEvents = EditorGUIUtility.TrTextContent(\"Delete Animation Events\");\n            public static GUIContent DeleteEvent = EditorGUIUtility.TrTextContent(\"Delete Animation Event\");\n            public static GUIContent CopyEvents = EditorGUIUtility.TrTextContent(\"Copy Animation Events\");\n            public static GUIContent PasteEvents = EditorGUIUtility.TrTextContent(\"Paste Animation Events\");\n        }\n\n        static string s_LoopMeterStr = \"LoopMeter\";\n        static int s_LoopMeterHint = s_LoopMeterStr.GetHashCode();\n\n        static string s_LoopOrientationMeterStr = \"LoopOrientationMeter\";\n        static int s_LoopOrientationMeterHint = s_LoopOrientationMeterStr.GetHashCode();\n\n        static string s_LoopPositionYMeterStr = \"LoopPostionYMeter\";\n        static int s_LoopPositionYMeterHint = s_LoopPositionYMeterStr.GetHashCode();\n\n        static string s_LoopPositionXZMeterStr = \"LoopPostionXZMeter\";\n        static int s_LoopPositionXZMeterHint = s_LoopPositionXZMeterStr.GetHashCode();\n\n        static public float s_EventTimelineMax = 1.05f;\n\n        // Update the ClipInfo if needed.\n        // Needed because of the dummy serialized property (m_DefaultClipsSerializedObject) TransferDefaultClipsToCustomClips\n        private void UpdateEventsPopupClipInfo(AnimationClipInfoProperties info)\n        {\n            if (m_EventManipulationHandler != null)\n                m_EventManipulationHandler.UpdateEvents(info);\n        }\n\n        private AvatarMask m_Mask = null;\n        public AvatarMask mask\n        {\n            get { return m_Mask; }\n            set { m_Mask = value; }\n        }\n\n        private AnimationClipInfoProperties m_ClipInfo = null;\n        public void ShowRange(AnimationClipInfoProperties info)\n        {\n            UpdateEventsPopupClipInfo(info);\n            m_ClipInfo = info;\n            info.AssignToPreviewClip(m_Clips[0]);\n        }\n\n        public string[] takeNames { get; set; }\n        public int takeIndex { get; set; }\n        private AnimationClip[] m_Clips = null;\n        private AnimatorController m_Controller = null;\n        private AnimatorStateMachine m_StateMachine;\n        private AnimatorState m_State;\n\n        private AvatarPreview m_AvatarPreview = null;\n\n        private TimeArea m_TimeArea;\n        private TimeArea m_EventTimeArea;\n\n        private SerializedProperty m_WrapModeProperty;\n        private SerializedProperty m_ClipSettingsProperty;\n        private SerializedProperty m_LoopTimeProperty;\n        private SerializedProperty m_LoopBlendProperty;\n        private SerializedProperty m_CycleOffsetProperty;\n        private SerializedProperty m_LoopBlendOrientationProperty;\n        private SerializedProperty m_KeepOriginalOrientationProperty;\n        private SerializedProperty m_OrientationOffsetYProperty;\n        private SerializedProperty m_LoopBlendPositionYProperty;\n        private SerializedProperty m_KeepOriginalPositionYProperty;\n        private SerializedProperty m_HeightFromFeetProperty;\n        private SerializedProperty m_LevelProperty;\n        private SerializedProperty m_LoopBlendPositionXZProperty;\n        private SerializedProperty m_KeepOriginalPositionXZProperty;\n        private SerializedProperty m_MirrorProperty;\n\n        private bool m_DraggingRange = false;\n        private bool m_DraggingRangeBegin = false;\n        private bool m_DraggingRangeEnd = false;\n        private float m_DraggingStartFrame = 0;\n        private float m_DraggingStopFrame = 0;\n        private float m_DraggingAdditivePoseFrame = 0;\n\n        private bool m_LoopTime = false;\n        private bool m_LoopBlend = false;\n        private bool m_LoopBlendOrientation = false;\n        private bool m_LoopBlendPositionY = false;\n        private bool m_LoopBlendPositionXZ = false;\n        private float m_StartFrame = 0;\n        private float m_StopFrame = 1;\n        private float m_AdditivePoseFrame = 0;\n        private float m_InitialClipLength = 0;\n\n        static private bool m_ShowCurves = false;\n\n        private EventManipulationHandler m_EventManipulationHandler;\n        static private bool m_ShowEvents = false;\n\n        bool m_NeedsToGenerateClipInfo = false;\n        bool m_IsSelectingMultipleClips = false;\n\n        public bool needsToGenerateClipInfo\n        {\n            get { return m_NeedsToGenerateClipInfo; }\n            set { m_NeedsToGenerateClipInfo = value; }\n        }\n\n        const int kSamplesPerSecond = 60;\n        const int kPose = 0;\n        const int kRotation = 1;\n        const int kHeight = 2;\n        const int kPosition = 3;\n        Vector2[][][] m_QualityCurves = new Vector2[4][][];\n        bool m_DirtyQualityCurves = false;\n        bool m_FirstInitialization = true;\n\n        private void InitController()\n        {\n            if (m_Clips[0].legacy)\n                return;\n\n            if (m_AvatarPreview != null && m_AvatarPreview.Animator != null)\n            {\n                bool wasInitialized = true;\n                if (m_Controller == null)\n                {\n                    m_Controller = new AnimatorController();\n                    m_Controller.pushUndo = false;\n                    m_Controller.hideFlags = HideFlags.HideAndDontSave;\n                    m_Controller.AddLayer(\"preview\");\n\n                    m_StateMachine = m_Controller.layers[0].stateMachine;\n                    m_StateMachine.pushUndo = false;\n                    m_StateMachine.hideFlags = HideFlags.HideAndDontSave;\n\n                    if (mask != null)\n                    {\n                        AnimatorControllerLayer[] layers = m_Controller.layers;\n                        layers[0].avatarMask = mask;\n                        m_Controller.layers = layers;\n                    }\n                    wasInitialized = false;\n                }\n\n                if (m_State == null)\n                {\n                    m_State = m_StateMachine.AddState(\"preview\");\n                    m_State.pushUndo = false;\n                    AnimatorControllerLayer[] layers = m_Controller.layers;\n                    m_State.motion = m_Clips[0];\n                    m_Controller.layers = layers;\n\n                    m_State.iKOnFeet = m_AvatarPreview.IKOnFeet;\n                    m_State.hideFlags = HideFlags.HideAndDontSave;\n                    wasInitialized = false;\n                }\n\n\n                AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);\n                if (AnimatorController.GetEffectiveAnimatorController(m_AvatarPreview.Animator) != m_Controller)\n                {\n                    AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);\n                }\n                if (!wasInitialized)\n                {\n                    m_AvatarPreview.Animator.Play(0, 0, 0);\n                    m_AvatarPreview.Animator.Update(0);\n\n                    if (m_FirstInitialization)\n                    {\n                        m_AvatarPreview.ResetPreviewFocus();\n                        m_FirstInitialization = false;\n                    }\n                }\n            }\n        }\n\n        internal override bool IsEnabled()\n        {\n            if (FileUtil.IsReadOnly(m_Clips[0]))\n                return false;\n            return base.IsEnabled();\n        }\n\n        internal override void OnHeaderIconGUI(Rect iconRect)\n        {\n            // It doesn't make sense to try and use the preview\n            Texture2D icon = null;\n            bool isLoadingAssetPreview = AssetPreview.IsLoadingAssetPreview(target.GetInstanceID());\n            icon = AssetPreview.GetAssetPreview(target);\n            if (!icon)\n            {\n                // We have a static preview it just hasn't been loaded yet. Repaint until we have it loaded.\n                if (isLoadingAssetPreview)\n                    Repaint();\n                icon = AssetPreview.GetMiniThumbnail(target);\n            }\n\n            GUI.DrawTexture(iconRect, icon);\n        }\n\n        internal override void OnHeaderTitleGUI(Rect titleRect, string header)\n        {\n            if (m_ClipInfo != null)\n                m_ClipInfo.name = EditorGUI.DelayedTextField(titleRect, m_ClipInfo.name, EditorStyles.textField);\n            else\n                base.OnHeaderTitleGUI(titleRect, header);\n        }\n\n        internal override void OnHeaderControlsGUI()\n        {\n            if (m_ClipInfo != null && takeNames != null && takeNames.Length > 1)\n            {\n                EditorGUIUtility.labelWidth = 80;\n                takeIndex = EditorGUILayout.Popup(\"Source Take\", takeIndex, takeNames);\n            }\n            else\n            {\n                base.OnHeaderControlsGUI();\n\n                ModelImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(target)) as ModelImporter;\n                if (importer != null && m_ClipInfo == null)\n                {\n                    if (GUILayout.Button(\"Edit...\", EditorStyles.miniButton, GUILayout.ExpandWidth(false)))\n                    {\n                        EditWithImporter(target as AnimationClip);\n                    }\n                }\n            }\n        }\n\n        private void DestroyController()\n        {\n            if (m_AvatarPreview != null && m_AvatarPreview.Animator != null)\n            {\n                AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, null);\n            }\n\n            Object.DestroyImmediate(m_Controller);\n            Object.DestroyImmediate(m_State);\n            m_Controller = null;\n            m_StateMachine = null;\n            m_State = null;\n        }\n\n        private void SetPreviewAvatar()\n        {\n            DestroyController();\n            InitController();\n        }\n\n        void InitPreview()\n        {\n            if (m_AvatarPreview == null)\n            {\n                m_AvatarPreview = new AvatarPreview(null, target as Motion);\n                m_AvatarPreview.OnAvatarChangeFunc = SetPreviewAvatar;\n                m_AvatarPreview.fps = Mathf.RoundToInt((target as AnimationClip).frameRate);\n                m_AvatarPreview.ShowIKOnFeetButton = (target as Motion).isHumanMotion;\n                m_AvatarPreview.ResetPreviewFocus();\n            }\n\n            // force an update on timeControl if AvatarPreviewer is closed when creating/editing animation curves\n            // prevent from having a nomralizedTime == -inf\n            if (m_AvatarPreview.timeControl.currentTime == Mathf.NegativeInfinity)\n                m_AvatarPreview.timeControl.Update();\n        }\n\n        public void InitClipTime()\n        {\n            //case 790259: The length of the clip will be changed by this inspector, so we can't use it for sampling\n            m_InitialClipLength = m_Clips[0].stopTime - m_Clips[0].startTime;\n\n            if (m_TimeArea == null)\n            {\n                m_TimeArea = new TimeArea(true);\n                m_TimeArea.hRangeLocked = false;\n                m_TimeArea.vRangeLocked = true;\n                m_TimeArea.hSlider = true;\n                m_TimeArea.vSlider = false;\n                m_TimeArea.hRangeMin = m_Clips[0].startTime;\n                m_TimeArea.hRangeMax = m_Clips[0].stopTime;\n                m_TimeArea.margin = 10;\n                m_TimeArea.scaleWithWindow = true;\n                m_TimeArea.minWidth = 1.0f / m_Clips[0].frameRate;\n                m_TimeArea.SetShownHRangeInsideMargins(m_Clips[0].startTime, m_Clips[0].stopTime);\n                m_TimeArea.hTicks.SetTickModulosForFrameRate(m_Clips[0].frameRate);\n                m_TimeArea.ignoreScrollWheelUntilClicked = true;\n            }\n\n            if (m_EventTimeArea == null)\n            {\n                m_EventTimeArea = new TimeArea(true);\n                m_EventTimeArea.hRangeLocked = true;\n                m_EventTimeArea.vRangeLocked = true;\n                m_EventTimeArea.hSlider = false;\n                m_EventTimeArea.vSlider = false;\n                m_EventTimeArea.hRangeMin = 0;\n                m_EventTimeArea.hRangeMax = s_EventTimelineMax;\n                m_EventTimeArea.margin = 10;\n                m_EventTimeArea.scaleWithWindow = true;\n                m_EventTimeArea.SetShownHRangeInsideMargins(0, s_EventTimelineMax);\n                m_EventTimeArea.hTicks.SetTickModulosForFrameRate(60);\n                m_EventTimeArea.ignoreScrollWheelUntilClicked = true;\n            }\n\n            if (m_EventManipulationHandler == null)\n                m_EventManipulationHandler = new EventManipulationHandler(m_EventTimeArea);\n        }\n\n        internal void OnEnable()\n        {\n            m_Clips = new AnimationClip[targets.Length];\n            for (var i = 0; i < targets.Length; ++i)\n                m_Clips[i] = targets[i] as AnimationClip;\n\n            m_IsSelectingMultipleClips = m_Clips.Length > 1;\n            InitSerializedProperties();\n\n            Undo.undoRedoEvent += OnUndoRedoPerformed;\n        }\n\n        void InitSerializedProperties()\n        {\n            m_WrapModeProperty = serializedObject.FindProperty(\"m_WrapMode\");\n            m_ClipSettingsProperty = serializedObject.FindProperty(\"m_AnimationClipSettings\");\n            m_LoopTimeProperty = m_ClipSettingsProperty.FindPropertyRelative(\"m_LoopTime\");\n            m_LoopBlendProperty = m_ClipSettingsProperty.FindPropertyRelative(\"m_LoopBlend\");\n            m_CycleOffsetProperty = m_ClipSettingsProperty.FindPropertyRelative(\"m_CycleOffset\");\n            m_LoopBlendOrientationProperty = m_ClipSettingsProperty.FindPropertyRelative(\"m_LoopBlendOrientation\");\n            m_KeepOriginalOrientationProperty = m_ClipSettingsProperty.FindPropertyRelative(\"m_KeepOriginalOrientation\");\n            m_OrientationOffsetYProperty = m_ClipSettingsProperty.FindPropertyRelative(\"m_OrientationOffsetY\");\n            m_LoopBlendPositionYProperty = m_ClipSettingsProperty.FindPropertyRelative(\"m_LoopBlendPositionY\");\n            m_KeepOriginalPositionYProperty = m_ClipSettingsProperty.FindPropertyRelative(\"m_KeepOriginalPositionY\");\n            m_HeightFromFeetProperty = m_ClipSettingsProperty.FindPropertyRelative(\"m_HeightFromFeet\");\n            m_LevelProperty = m_ClipSettingsProperty.FindPropertyRelative(\"m_Level\");\n            m_LoopBlendPositionXZProperty = m_ClipSettingsProperty.FindPropertyRelative(\"m_LoopBlendPositionXZ\");\n            m_KeepOriginalPositionXZProperty = m_ClipSettingsProperty.FindPropertyRelative(\"m_KeepOriginalPositionXZ\");\n            m_MirrorProperty = m_ClipSettingsProperty.FindPropertyRelative(\"m_Mirror\");\n        }\n\n        void OnDisable()\n        {\n            DestroyController();\n            if (m_AvatarPreview != null)\n            {\n                m_AvatarPreview.OnDisable();\n                m_AvatarPreview = null;\n            }\n\n            Undo.undoRedoEvent -= OnUndoRedoPerformed;\n        }\n\n        void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            if (!m_IsSelectingMultipleClips)\n                return;\n\n            for (var i = 0; i < m_Clips.Length; ++i)\n                AnimationUtility.RebuildMecanimData(m_Clips[i]);\n        }\n\n        public override bool HasPreviewGUI()\n        {\n            if (m_IsSelectingMultipleClips)\n                return false;\n\n            InitPreview();\n            return m_AvatarPreview != null;\n        }\n\n        public override void OnPreviewSettings()\n        {\n            m_AvatarPreview.DoPreviewSettings();\n        }\n\n        void CalculateQualityCurves()\n        {\n            for (int i = 0; i < 4; i++)\n                m_QualityCurves[i] = new Vector2[2][];\n\n            for (int q = 0; q < 2; q++)\n            {\n                // [case 491172]\n                // There is no need to sample the quality curve outside of the animation range [m_Clip.startTime, m_Clip.stopTime] because the Time area show only the animation range anyway\n                // so it not possible for the user to see curve outside of this range.\n                float clipStartTime = Mathf.Clamp(m_ClipInfo.firstFrame / m_Clips[0].frameRate, m_Clips[0].startTime, m_Clips[0].stopTime);\n                float clipStopTime = Mathf.Clamp(m_ClipInfo.lastFrame / m_Clips[0].frameRate, m_Clips[0].startTime, m_Clips[0].stopTime);\n\n                float fixedTime = (q == 0 ? clipStopTime : clipStartTime);\n                float startTime = (q == 0 ? 0 : clipStartTime);\n                float stopTime = (q == 0 ? clipStopTime : m_Clips[0].stopTime);\n                // Start sample may be a bit before start time; stop sample may be a bit after stop time\n                int startSample = Mathf.FloorToInt(startTime * kSamplesPerSecond);\n                int stopSample = Mathf.CeilToInt(stopTime * kSamplesPerSecond);\n\n                m_QualityCurves[kPose][q] = new Vector2[stopSample - startSample + 1];\n                m_QualityCurves[kRotation][q] = new Vector2[stopSample - startSample + 1];\n                m_QualityCurves[kHeight][q] = new Vector2[stopSample - startSample + 1];\n                m_QualityCurves[kPosition][q] = new Vector2[stopSample - startSample + 1];\n\n                QualityCurvesTime qualityCurvesTime = new QualityCurvesTime();\n                qualityCurvesTime.fixedTime = fixedTime;\n                qualityCurvesTime.variableEndStart = startTime;\n                qualityCurvesTime.variableEndEnd = stopTime;\n                qualityCurvesTime.q = q;\n\n                MuscleClipUtility.CalculateQualityCurves(m_Clips[0], qualityCurvesTime,\n                    m_QualityCurves[kPose][q], m_QualityCurves[kRotation][q],\n                    m_QualityCurves[kHeight][q], m_QualityCurves[kPosition][q]);\n            }\n            m_DirtyQualityCurves = false;\n        }\n\n        public override void OnInteractivePreviewGUI(Rect r, GUIStyle background)\n        {\n            bool isRepaint = (Event.current.type == EventType.Repaint);\n\n            InitController();\n\n            if (isRepaint)\n                m_AvatarPreview.timeControl.Update();\n\n            // Set to full take range\n            AnimationClip clip = target as AnimationClip;\n            AnimationClipSettings previewInfo = AnimationUtility.GetAnimationClipSettings(clip);\n\n            // Set settings\n            m_AvatarPreview.timeControl.loop = true; // always looping, waiting for UI ctrl...\n\n            // Sample Animation\n            if (isRepaint && m_AvatarPreview.PreviewObject != null)\n            {\n                if (clip.legacy == false && m_AvatarPreview.Animator != null)\n                {\n                    if (m_State != null)\n                        m_State.iKOnFeet = m_AvatarPreview.IKOnFeet;\n\n                    float normalizedTime = previewInfo.stopTime - previewInfo.startTime != 0 ? (m_AvatarPreview.timeControl.currentTime - previewInfo.startTime) / (previewInfo.stopTime - previewInfo.startTime) : 0.0f;\n                    m_AvatarPreview.Animator.Play(0, 0, normalizedTime);\n                    m_AvatarPreview.Animator.Update(m_AvatarPreview.timeControl.deltaTime);\n                }\n                else\n                {\n                    clip.SampleAnimation(m_AvatarPreview.PreviewObject, m_AvatarPreview.timeControl.currentTime);\n                }\n            }\n\n            m_AvatarPreview.DoAvatarPreview(r, background);\n        }\n\n        public void ClipRangeGUI(ref float startFrame, ref float stopFrame, out bool changedStart, out bool changedStop, bool showAdditivePoseFrame, ref float additivePoseframe, out bool changedAdditivePoseframe)\n        {\n            changedStart = false;\n            changedStop = false;\n            changedAdditivePoseframe = false;\n\n            m_DraggingRangeBegin = false;\n            m_DraggingRangeEnd = false;\n\n            bool invalidRange = (\n                startFrame + 0.01f < m_Clips[0].startTime * m_Clips[0].frameRate ||\n                startFrame - 0.01f > m_Clips[0].stopTime * m_Clips[0].frameRate ||\n                stopFrame + 0.01f < m_Clips[0].startTime * m_Clips[0].frameRate ||\n                stopFrame - 0.01f > m_Clips[0].stopTime * m_Clips[0].frameRate);\n            bool fixRange = false;\n            if (invalidRange)\n            {\n                GUILayout.BeginHorizontal(EditorStyles.helpBox);\n                GUILayout.Label(\"The clip range is outside of the range of the source take.\", EditorStyles.wordWrappedMiniLabel);\n                GUILayout.FlexibleSpace();\n                GUILayout.BeginVertical();\n                GUILayout.Space(5);\n                if (GUILayout.Button(\"Clamp Range\"))\n                    fixRange = true;\n                GUILayout.EndVertical();\n                GUILayout.EndHorizontal();\n            }\n\n            // Time line\n            Rect timeRect = GUILayoutUtility.GetRect(10, 18 + 15);\n            GUI.Label(timeRect, \"\", \"TE Toolbar\");\n            if (Event.current.type == EventType.Repaint)\n                m_TimeArea.rect = timeRect;\n            m_TimeArea.BeginViewGUI();\n            m_TimeArea.EndViewGUI();\n            timeRect.height -= 15;\n\n            // Start and stop markers\n            int startHandleId = GUIUtility.GetControlID(3126789, FocusType.Passive);\n            int stopHandleId = GUIUtility.GetControlID(3126789, FocusType.Passive);\n            int additiveHandleId = GUIUtility.GetControlID(3126789, FocusType.Passive);\n            GUI.BeginGroup(new Rect(timeRect.x + 1, timeRect.y + 1, timeRect.width - 2, timeRect.height - 2));\n            {\n                timeRect.x = timeRect.y = -1;\n\n                // Draw selected range as blue tint\n                float startPixel = m_TimeArea.FrameToPixel(startFrame, m_Clips[0].frameRate, timeRect);\n                float stopPixel = m_TimeArea.FrameToPixel(stopFrame, m_Clips[0].frameRate, timeRect);\n                GUI.Label(new Rect(startPixel, timeRect.y, stopPixel - startPixel, timeRect.height), \"\", EditorStyles.selectionRect);\n\n                // Draw time ruler\n                m_TimeArea.TimeRuler(timeRect, m_Clips[0].frameRate);\n                // Current time indicator\n                TimeArea.DrawPlayhead(m_TimeArea.TimeToPixel(m_AvatarPreview.timeControl.currentTime, timeRect), timeRect.yMin, timeRect.yMax, 2f, 1f);\n\n                using (new EditorGUI.DisabledScope(invalidRange))\n                {\n                    // Range handles\n                    float startTime = startFrame / m_Clips[0].frameRate;\n                    TimeArea.TimeRulerDragMode inPoint = m_TimeArea.BrowseRuler(timeRect, startHandleId, ref startTime, 0, false, \"TL InPoint\");\n                    if (inPoint == TimeArea.TimeRulerDragMode.Cancel)\n                    {\n                        startFrame = m_DraggingStartFrame;\n                    }\n                    else if (inPoint != TimeArea.TimeRulerDragMode.None)\n                    {\n                        startFrame = startTime * m_Clips[0].frameRate;\n                        // Snapping bias. Snap to whole frames when zoomed out.\n                        startFrame = MathUtils.RoundBasedOnMinimumDifference(startFrame, m_TimeArea.PixelDeltaToTime(timeRect) * m_Clips[0].frameRate * 10);\n                        changedStart = true;\n                    }\n                    float stopTime = stopFrame / m_Clips[0].frameRate;\n\n                    TimeArea.TimeRulerDragMode outPoint = m_TimeArea.BrowseRuler(timeRect, stopHandleId, ref stopTime, 0, false, \"TL OutPoint\");\n                    if (outPoint == TimeArea.TimeRulerDragMode.Cancel)\n                    {\n                        stopFrame = m_DraggingStopFrame;\n                    }\n                    else if (outPoint != TimeArea.TimeRulerDragMode.None)\n                    {\n                        stopFrame = stopTime * m_Clips[0].frameRate;\n                        // Snapping bias. Snap to whole frames when zoomed out.\n                        stopFrame = MathUtils.RoundBasedOnMinimumDifference(stopFrame, m_TimeArea.PixelDeltaToTime(timeRect) * m_Clips[0].frameRate * 10);\n                        changedStop = true;\n                    }\n\n                    // Additive pose frame Handle\n                    if (showAdditivePoseFrame)\n                    {\n                        float additivePoseTime = additivePoseframe / m_Clips[0].frameRate;\n                        TimeArea.TimeRulerDragMode additivePoint = m_TimeArea.BrowseRuler(timeRect, additiveHandleId, ref additivePoseTime, 0, false, \"TL playhead\");\n                        if (additivePoint == TimeArea.TimeRulerDragMode.Cancel)\n                        {\n                            additivePoseframe = m_DraggingAdditivePoseFrame;\n                        }\n                        else if (additivePoint != TimeArea.TimeRulerDragMode.None)\n                        {\n                            additivePoseframe = additivePoseTime * m_Clips[0].frameRate;\n                            // Snapping bias. Snap to whole frames when zoomed out.\n                            additivePoseframe = MathUtils.RoundBasedOnMinimumDifference(additivePoseframe, m_TimeArea.PixelDeltaToTime(timeRect) * m_Clips[0].frameRate * 10);\n                            changedAdditivePoseframe = true;\n                        }\n                    }\n                }\n\n                if (EditorGUIUtility.hotControl == startHandleId)\n                    changedStart = true;\n                if (EditorGUIUtility.hotControl == stopHandleId)\n                    changedStop = true;\n                if (EditorGUIUtility.hotControl == additiveHandleId)\n                    changedAdditivePoseframe = true;\n            }\n            GUI.EndGroup();\n\n            // Start and stop time float fields\n            using (new EditorGUI.DisabledScope(invalidRange))\n            {\n                EditorGUILayout.BeginHorizontal();\n                {\n                    EditorGUI.BeginChangeCheck();\n                    startFrame = EditorGUILayout.FloatField(Styles.StartFrame, Mathf.Round(startFrame * 1000) / 1000);\n                    if (EditorGUI.EndChangeCheck())\n                        changedStart = true;\n\n                    GUILayout.FlexibleSpace();\n\n                    EditorGUI.BeginChangeCheck();\n                    stopFrame = EditorGUILayout.FloatField(Styles.EndFrame, Mathf.Round(stopFrame * 1000) / 1000);\n                    if (EditorGUI.EndChangeCheck())\n                        changedStop = true;\n                }\n                EditorGUILayout.EndHorizontal();\n            }\n\n            changedStart |= fixRange;\n            changedStop |= fixRange;\n\n            // Start and stop time value clamping\n            if (changedStart)\n                startFrame = Mathf.Clamp(startFrame, m_Clips[0].startTime * m_Clips[0].frameRate, Mathf.Clamp(stopFrame, m_Clips[0].startTime * m_Clips[0].frameRate, stopFrame));\n\n            if (changedStop)\n                stopFrame = Mathf.Clamp(stopFrame, startFrame, m_Clips[0].stopTime * m_Clips[0].frameRate);\n\n            if (changedAdditivePoseframe)\n                additivePoseframe = Mathf.Clamp(additivePoseframe, m_Clips[0].startTime * m_Clips[0].frameRate, m_Clips[0].stopTime * m_Clips[0].frameRate);\n\n            // Keep track of whether we're currently dragging the range or not\n            if (changedStart || changedStop || changedAdditivePoseframe)\n            {\n                if (!m_DraggingRange)\n                    m_DraggingRangeBegin = true;\n                m_DraggingRange = true;\n            }\n            else if (m_DraggingRange && EditorGUIUtility.hotControl == 0 && Event.current.type == EventType.Repaint)\n            {\n                m_DraggingRangeEnd = true;\n                m_DraggingRange = false;\n                m_DirtyQualityCurves = true;\n                Repaint();\n            }\n\n            GUILayout.Space(10);\n        }\n\n        string GetStatsText()\n        {\n            string statsText = \"\";\n\n            bool IsHumanClip = targets.Length == 1 ? (target as Motion).isHumanMotion : false;\n\n            // Muscle clip info is currently only available for humanoid\n            if (IsHumanClip)\n            {\n                statsText = string.Format(Styles.AverageVelocity, m_Clips[0].averageSpeed.ToString(\"0.000\"), (m_Clips[0].averageAngularSpeed * 180.0f / Mathf.PI).ToString(\"0.0\", CultureInfo.InvariantCulture.NumberFormat));\n            }\n\n            // Only show stats in final clip not for the preview clip\n            if (m_ClipInfo == null)\n            {\n                AnimationClipStats stats = new AnimationClipStats();\n                stats.Reset();\n                for (int clipIter = 0; clipIter < targets.Length; clipIter++)\n                {\n                    AnimationClip clip = targets[clipIter] as AnimationClip;\n                    if (clip != null)\n                    {\n                        AnimationClipStats clipStats = AnimationUtility.GetAnimationClipStats(clip);\n                        stats.Combine(clipStats);\n                    }\n                }\n\n                if (statsText.Length != 0)\n                    statsText += '\\n';\n\n                float constantRatio = (float)stats.constantCurves / (float)stats.totalCurves * 100.0f;\n                float denseRatio = (float)stats.denseCurves / (float)stats.totalCurves * 100.0f;\n                float streamRatio = (float)stats.streamCurves / (float)stats.totalCurves * 100.0f;\n\n\n                statsText += string.Format(\"Curves Pos: {0} Quaternion: {1} Euler: {2} Scale: {3} Muscles: {4} Generic: {5} PPtr: {6}\\n\", stats.positionCurves, stats.quaternionCurves, stats.eulerCurves, stats.scaleCurves, stats.muscleCurves, stats.genericCurves, stats.pptrCurves);\n                statsText += string.Format(\"Curves Total: {0}, Constant: {1} ({2}%) Dense: {3} ({4}%) Stream: {5} ({6}%)\\n\", stats.totalCurves, stats.constantCurves, constantRatio.ToString(\"0.0\", CultureInfo.InvariantCulture.NumberFormat), stats.denseCurves, denseRatio.ToString(\"0.0\", CultureInfo.InvariantCulture.NumberFormat), stats.streamCurves, streamRatio.ToString(\"0.0\", CultureInfo.InvariantCulture.NumberFormat));\n\n                statsText += EditorUtility.FormatBytes(stats.size);\n            }\n\n            return statsText;\n        }\n\n        private float GetClipLength(int clipIndex)\n        {\n            if (m_ClipInfo == null)\n                return m_Clips[clipIndex].length;\n            else\n                return (m_ClipInfo.lastFrame - m_ClipInfo.firstFrame) / m_Clips[clipIndex].frameRate;\n        }\n\n        // A minimal list of settings to be shown in the Asset Store preview inspector\n        internal override void OnAssetStoreInspectorGUI()\n        {\n            OnInspectorGUI();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            EditorGUIUtility.labelWidth = 50;\n            EditorGUIUtility.fieldWidth = 30;\n\n            EditorGUILayout.BeginHorizontal();\n            {\n                using (new EditorGUI.DisabledScope(true))\n                {\n                    var hasSameClipLength = true;\n                    var hasSameFrameRate = true;\n                    var firstClipLength = GetClipLength(0);\n                    var firstClipFrameRate = m_Clips[0].frameRate;\n                    for (var i = 1; i < m_Clips.Length; ++i)\n                    {\n                        if (Mathf.Abs(GetClipLength(i) - firstClipLength) > Mathf.Epsilon)\n                            hasSameClipLength = false;\n                        if (Mathf.Abs(m_Clips[i].frameRate - firstClipFrameRate) > Mathf.Epsilon)\n                            hasSameFrameRate = false;\n                    }\n\n                    GUILayout.Label(Styles.Length, EditorStyles.label, GUILayout.Width(50 - 4));\n                    var clipLengthStr = hasSameClipLength ? firstClipLength.ToString(\"0.000\", CultureInfo.InvariantCulture.NumberFormat) : \"-\";\n                    GUILayout.Label(clipLengthStr, EditorStyles.label);\n\n                    GUILayout.FlexibleSpace();\n\n                    var clipFrameRateStr = hasSameFrameRate ? firstClipFrameRate.ToString() : \"-\";\n                    GUILayout.Label(clipFrameRateStr + \" FPS\", EditorStyles.label);\n                }\n            }\n            EditorGUILayout.EndHorizontal();\n\n            if (m_IsSelectingMultipleClips)\n                MultiClipInspectorGUI();\n            else\n                SingleClipInspectorGUI();\n        }\n\n        private void MultiClipInspectorGUI()\n        {\n            var sameTypeOfClip = true;\n            for (var i = 1; i < m_Clips.Length; ++i)\n            {\n                if (m_Clips[i].legacy != m_Clips[0].legacy)\n                {\n                    sameTypeOfClip = false;\n                    break;\n                }\n            }\n\n            if (!sameTypeOfClip)\n            {\n                EditorGUILayout.HelpBox(Styles.InvalidMultiSelection, MessageType.Error);\n                return;\n            }\n\n            if (m_Clips[0].legacy)\n                MultiLegacyClipGUI();\n            else\n                MultiMuscleClipGUI();\n        }\n\n        private void MultiLegacyClipGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUIUtility.labelWidth = 0;\n            EditorGUIUtility.fieldWidth = 0;\n\n            EditorGUI.BeginChangeCheck();\n\n            var wrapMode = serializedObject.FindProperty(\"m_WrapMode\");\n            EditorGUILayout.PropertyField(wrapMode, Styles.WrapMode);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        private void MultiMuscleClipGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUIUtility.labelWidth = 0;\n            EditorGUIUtility.fieldWidth = 0;\n\n            var toggleLoopTimeRect = EditorGUILayout.GetControlRect();\n            EditorGUI.PropertyField(toggleLoopTimeRect, m_LoopTimeProperty, Styles.LoopTime);\n\n            using (new EditorGUI.DisabledScope(!m_LoopTimeProperty.boolValue))\n            {\n                EditorGUI.indentLevel++;\n\n                var toggleLoopPoseRect = EditorGUILayout.GetControlRect();\n                EditorGUI.PropertyField(toggleLoopPoseRect, m_LoopBlendProperty, Styles.LoopPose);\n                EditorGUILayout.PropertyField(m_CycleOffsetProperty, Styles.LoopCycleOffset);\n\n                EditorGUI.indentLevel--;\n            }\n\n            EditorGUILayout.Space();\n\n            var areAllClipsEitherHumanOrNonHuman = true;\n            var isSelectionHumanClip = true;\n            var doesSelectionHaveRootCurves = true;\n            var doesSelectionHaveMotionCurves = false;\n            for (var i = 0; i < m_Clips.Length; ++i)\n            {\n                if (m_Clips[0].isHumanMotion != m_Clips[i])\n                    areAllClipsEitherHumanOrNonHuman = false;\n                if (!m_Clips[i].isHumanMotion)\n                    isSelectionHumanClip = false;\n                if (!m_Clips[i].hasRootCurves)\n                    doesSelectionHaveRootCurves = false;\n                if (m_Clips[i].hasMotionCurves)\n                    doesSelectionHaveMotionCurves = true;\n            }\n\n            if (doesSelectionHaveRootCurves && !doesSelectionHaveMotionCurves)\n            {\n                // Rotation\n                GUILayout.Label(Styles.RootTransformRotation, EditorStyles.label);\n                EditorGUI.indentLevel++;\n\n                // Toggle\n                var toggleRotRect = EditorGUILayout.GetControlRect();\n                EditorGUI.PropertyField(toggleRotRect, m_LoopBlendOrientationProperty, Styles.BakeIntoPoseOrientation);\n\n                // Reference\n                BoolPropertyPopup(m_KeepOriginalOrientationProperty,\n                    m_LoopBlendOrientationProperty.boolValue ? Styles.BasedUponOrientation : Styles.BasedUponStartOrientation,\n                    m_KeepOriginalOrientationProperty.boolValue ? 0 : 1,\n                    isSelectionHumanClip ? Styles.BasedUponRotationHumanOpt : Styles.BasedUponRotationOpt);\n\n                // Offset\n                EditorGUILayout.PropertyField(m_OrientationOffsetYProperty, Styles.OrientationOffsetY);\n                EditorGUI.indentLevel--;\n\n                EditorGUILayout.Space();\n\n                // Position Y\n                GUILayout.Label(Styles.RootTransformRotationY, EditorStyles.label);\n                EditorGUI.indentLevel++;\n\n                // Toggle\n                var toggleYRect = EditorGUILayout.GetControlRect();\n                EditorGUI.PropertyField(toggleYRect, m_LoopBlendPositionYProperty, Styles.BakeIntoPosePositionY);\n\n                // Reference\n                if (isSelectionHumanClip && areAllClipsEitherHumanOrNonHuman)\n                {\n                    int offsetHeight;\n                    if (m_KeepOriginalPositionYProperty.boolValue)\n                        offsetHeight = 0;\n                    else if (m_HeightFromFeetProperty.boolValue)\n                        offsetHeight = 2;\n                    else\n                        offsetHeight = 1;\n\n                    var showMixedValueDefault = EditorGUI.showMixedValue;\n                    EditorGUI.showMixedValue = m_KeepOriginalPositionYProperty.hasMultipleDifferentValues || m_HeightFromFeetProperty.hasMultipleDifferentValues;\n\n                    offsetHeight =\n                        EditorGUILayout.Popup(\n                            m_LoopBlendPositionYProperty.boolValue ? Styles.BasedUponStartPositionY : Styles.BasedUponPositionY,\n                            offsetHeight,\n                            Styles.BasedUponPositionYHumanOpt);\n\n                    EditorGUI.showMixedValue = showMixedValueDefault;\n\n                    if (offsetHeight == 0)\n                    {\n                        m_KeepOriginalPositionYProperty.boolValue = true;\n                        m_HeightFromFeetProperty.boolValue = false;\n                    }\n                    else if (offsetHeight == 1)\n                    {\n                        m_KeepOriginalPositionYProperty.boolValue = false;\n                        m_HeightFromFeetProperty.boolValue = false;\n                    }\n                    else\n                    {\n                        m_KeepOriginalPositionYProperty.boolValue = false;\n                        m_HeightFromFeetProperty.boolValue = true;\n                    }\n                }\n                else if (areAllClipsEitherHumanOrNonHuman)\n                {\n                    BoolPropertyPopup(m_KeepOriginalPositionYProperty,\n                        m_LoopBlendPositionYProperty.boolValue ? Styles.BasedUponStartPositionY : Styles.BasedUponPositionY,\n                        m_KeepOriginalPositionYProperty.boolValue ? 0 : 1,\n                        Styles.BasedUponPositionYOpt);\n                }\n\n                // Offset\n                EditorGUILayout.PropertyField(m_LevelProperty, Styles.PositionOffsetY);\n                EditorGUI.indentLevel--;\n\n                EditorGUILayout.Space();\n\n                // Position XZ\n                GUILayout.Label(Styles.RootTransformPositionXZ, EditorStyles.label);\n                EditorGUI.indentLevel++;\n\n                // Toggle\n                var toggleXZRect = EditorGUILayout.GetControlRect();\n                EditorGUI.PropertyField(toggleXZRect, m_LoopBlendPositionXZProperty, Styles.BakeIntoPosePositionXZ);\n\n                // Reference\n                BoolPropertyPopup(m_KeepOriginalPositionXZProperty,\n                    m_LoopBlendPositionXZProperty.boolValue ? Styles.BasedUponStartPositionXZ : Styles.BasedUponPositionXZ,\n                    m_KeepOriginalPositionXZProperty.boolValue ? 0 : 1,\n                    isSelectionHumanClip ? Styles.BasedUponPositionXZHumanOpt : Styles.BasedUponPositionXZOpt);\n\n                EditorGUI.indentLevel--;\n\n                EditorGUILayout.Space();\n            }\n\n            if (isSelectionHumanClip)\n            {\n                EditorGUILayout.PropertyField(m_MirrorProperty, Styles.Mirror);\n            }\n\n            if (serializedObject.hasModifiedProperties)\n            {\n                serializedObject.ApplyModifiedProperties();\n                foreach(var clip in m_Clips)\n                    AnimationUtility.RebuildMecanimData(clip);\n            }\n        }\n\n        private static void BoolPropertyPopup(SerializedProperty property, GUIContent label, int selectedIndex, GUIContent[] displayOptions)\n        {\n            var showMixedValueDefault = EditorGUI.showMixedValue;\n\n            var hasMultipleDifferentValues = property.hasMultipleDifferentValues;\n            EditorGUI.showMixedValue = hasMultipleDifferentValues;\n\n            EditorGUI.BeginChangeCheck();\n            selectedIndex = EditorGUILayout.Popup(label, hasMultipleDifferentValues ? -1 : selectedIndex, displayOptions);\n\n            if (EditorGUI.EndChangeCheck())\n                property.boolValue = (selectedIndex == 0);\n\n            EditorGUI.showMixedValue = showMixedValueDefault;\n        }\n\n        private void SingleClipInspectorGUI()\n        {\n            InitPreview();\n\n            if (!m_Clips[0].legacy)\n                MuscleClipGUI();\n            else\n                AnimationClipGUI();\n        }\n\n        private void AnimationClipGUI()\n        {\n            if (m_ClipInfo != null)\n            {\n                float startFrame = m_ClipInfo.firstFrame;\n                float stopFrame = m_ClipInfo.lastFrame;\n                float additivePoseFrame = 0;\n                bool changedStart = false;\n                bool changedStop = false;\n                bool changedAdditivePoseFrame = false;\n                ClipRangeGUI(ref startFrame, ref stopFrame, out changedStart, out changedStop, false, ref additivePoseFrame, out changedAdditivePoseFrame);\n                if (changedStart)\n                    m_ClipInfo.firstFrame = startFrame;\n                if (changedStop)\n                    m_ClipInfo.lastFrame = stopFrame;\n\n                m_AvatarPreview.timeControl.startTime = startFrame / m_Clips[0].frameRate;\n                m_AvatarPreview.timeControl.stopTime = stopFrame / m_Clips[0].frameRate;\n            }\n            else\n            {\n                m_AvatarPreview.timeControl.startTime = 0;\n                m_AvatarPreview.timeControl.stopTime = m_Clips[0].length;\n            }\n\n            EditorGUIUtility.labelWidth = 0;\n            EditorGUIUtility.fieldWidth = 0;\n\n            if (m_ClipInfo != null)\n                m_ClipInfo.loop = EditorGUILayout.Toggle(Styles.AddLoopFrame, m_ClipInfo.loop);\n\n            EditorGUI.BeginChangeCheck();\n            int wrap = m_ClipInfo != null ? m_ClipInfo.wrapMode : (int)m_Clips[0].wrapMode;\n            wrap = (int)(WrapModeFixed)EditorGUILayout.EnumPopup(Styles.WrapMode, (WrapModeFixed)wrap);\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (m_ClipInfo != null)\n                    m_ClipInfo.wrapMode = wrap;\n                else\n                    m_Clips[0].wrapMode = (WrapMode)wrap;\n            }\n        }\n\n        void CurveGUI()\n        {\n            if (m_ClipInfo == null)\n                return;\n\n            float time = m_AvatarPreview.timeControl.normalizedTime;\n\n            for (int i = 0; i < m_ClipInfo.GetCurveCount(); i++)\n            {\n                GUILayout.Space(5);\n\n                GUILayout.BeginHorizontal();\n                {\n                    if (GUILayout.Button(GUIContent.none, \"OL Minus\", GUILayout.Width(17))) m_ClipInfo.RemoveCurve(i);\n                    else\n                    {\n                        GUILayout.BeginVertical(GUILayout.Width(125));\n\n                        string prevName = m_ClipInfo.GetCurveName(i);\n                        string newName = EditorGUILayout.DelayedTextField(prevName, EditorStyles.textField);\n\n                        if (prevName != newName)\n                            m_ClipInfo.SetCurveName(i, newName);\n\n                        SerializedProperty curveProperty = m_ClipInfo.GetCurveProperty(i);\n                        AnimationCurve curve = curveProperty.animationCurveValue;\n\n                        int keyCount = curve.length;\n                        bool isKey = false;\n                        int keyIndex = keyCount - 1;\n\n                        Keyframe[] keys = curve.keys;\n                        for (int keyIter = 0; keyIter < keyCount; keyIter++)\n                        {\n                            if (Mathf.Abs(keys[keyIter].time - time) < 0.0001f)\n                            {\n                                isKey = true;\n                                keyIndex = keyIter;\n                                break;\n                            }\n                            else if (keys[keyIter].time > time)\n                            {\n                                keyIndex = keyIter;\n                                break;\n                            }\n                        }\n\n                        GUILayout.BeginHorizontal();\n\n                        if (GUILayout.Button(Styles.PrevKeyContent))\n                        {\n                            if (keyIndex > 0)\n                            {\n                                keyIndex--;\n                                m_AvatarPreview.timeControl.normalizedTime = keys[keyIndex].time;\n                            }\n                        }\n\n                        if (GUILayout.Button(Styles.NextKeyContent))\n                        {\n                            if (isKey && keyIndex < keyCount - 1) keyIndex++;\n                            m_AvatarPreview.timeControl.normalizedTime = keys[keyIndex].time;\n                        }\n\n                        float val, newVal;\n                        using (new EditorGUI.DisabledScope(!isKey))\n                        {\n                            string orgFormat = EditorGUI.kFloatFieldFormatString;\n                            EditorGUI.kFloatFieldFormatString = \"n3\";\n\n                            try\n                            {\n                                val = curve.Evaluate(time);\n                                newVal = EditorGUILayout.FloatField(val, GUILayout.Width(60));\n                            }\n                            finally\n                            {\n                                EditorGUI.kFloatFieldFormatString = orgFormat;\n                            }\n                        }\n\n                        bool addKey = false;\n\n                        if (val != newVal)\n                        {\n                            if (isKey) curve.RemoveKey(keyIndex);\n\n                            addKey = true;\n                        }\n\n                        using (new EditorGUI.DisabledScope(isKey))\n                        {\n                            if (GUILayout.Button(Styles.AddKeyframeContent))\n                            {\n                                addKey = true;\n                            }\n                        }\n\n                        if (addKey)\n                        {\n                            Keyframe key = new Keyframe();\n                            key.time = time;\n                            key.value = newVal;\n                            key.inTangent = 0;\n                            key.outTangent = 0;\n                            curve.AddKey(key);\n                            keys = curve.keys;\n                            m_ClipInfo.SetCurve(i, curve);\n                            UnityEditorInternal.AnimationCurvePreviewCache.ClearCache();\n                        }\n\n                        GUILayout.EndHorizontal();\n\n                        GUILayout.EndVertical();\n\n                        EditorGUILayout.CurveField(curveProperty, EditorGUI.kCurveColor, new Rect(), GUIContent.none, GUILayout.Height(40));\n\n                        Rect curveRect = GUILayoutUtility.GetLastRect();\n\n                        keyCount = curve.length;\n\n                        TimeArea.DrawPlayhead(curveRect.x + time * curveRect.width, curveRect.yMin, curveRect.yMax, 1f, 1f);\n\n                        for (int keyIter = 0; keyIter < keyCount; keyIter++)\n                        {\n                            float keyTime = keys[keyIter].time;\n\n                            Handles.color = Color.white;\n                            Handles.DrawLine(new Vector3(curveRect.x + keyTime * curveRect.width, curveRect.y + curveRect.height - 10, 0), new Vector3(curveRect.x + keyTime * curveRect.width, curveRect.y + curveRect.height, 0));\n                        }\n                    }\n\n                    GUILayout.EndHorizontal();\n                }\n            }\n\n            GUILayout.BeginHorizontal();\n            if (GUILayout.Button(GUIContent.none, \"OL Plus\", GUILayout.Width(17))) m_ClipInfo.AddCurve();\n            GUILayout.EndHorizontal();\n        }\n\n        private void EventsGUI()\n        {\n            if (m_ClipInfo == null)\n                return;\n\n            var currentTime = Mathf.Clamp01(m_AvatarPreview.timeControl.normalizedTime);\n\n            GUILayout.BeginHorizontal();\n            if (GUILayout.Button(Styles.AddEventContent, GUILayout.Width(25)))\n            {\n                m_ClipInfo.AddEvent(currentTime);\n                m_EventManipulationHandler.SelectEvent(m_ClipInfo.GetEvents(), m_ClipInfo.GetEventCount() - 1, m_ClipInfo);\n                needsToGenerateClipInfo = true;\n            }\n\n            Rect timeRect = GUILayoutUtility.GetRect(10, 18 + 15);\n            timeRect.xMin += 5;\n            timeRect.xMax -= 4;\n            GUI.Label(timeRect, \"\", \"TE Toolbar\");\n\n            if (Event.current.type == EventType.Repaint)\n                m_EventTimeArea.rect = timeRect;\n            timeRect.height -= 15;\n            m_EventTimeArea.TimeRuler(timeRect, 100.0f);\n\n\n            GUI.BeginGroup(new Rect(timeRect.x + 1, timeRect.y + 1, timeRect.width - 2, timeRect.height - 2));\n            {\n                Rect localTimeRect = new Rect(-1, -1, timeRect.width, timeRect.height);\n\n                AnimationEvent[] events = m_ClipInfo.GetEvents();\n\n                if (m_EventManipulationHandler.HandleEventManipulation(localTimeRect, ref events, m_ClipInfo, currentTime)) // had changed\n                {\n                    m_ClipInfo.SetEvents(events);\n                }\n\n                // Current time indicator\n                TimeArea.DrawPlayhead(m_EventTimeArea.TimeToPixel(currentTime, localTimeRect), localTimeRect.yMin, localTimeRect.yMax, 2f, 1f);\n            }\n\n\n            GUI.EndGroup();\n\n            GUILayout.EndHorizontal();\n\n            m_EventManipulationHandler.Draw(timeRect);\n        }\n\n        private void MuscleClipGUI()\n        {\n            EditorGUI.BeginChangeCheck();\n\n            InitController();\n\n            AnimationClipSettings animationClipSettings = AnimationUtility.GetAnimationClipSettings(m_Clips[0]);\n\n            m_StartFrame = m_DraggingRange ? m_StartFrame : animationClipSettings.startTime * m_Clips[0].frameRate;\n            m_StopFrame = m_DraggingRange ? m_StopFrame : animationClipSettings.stopTime * m_Clips[0].frameRate;\n            m_AdditivePoseFrame = m_DraggingRange ? m_AdditivePoseFrame : animationClipSettings.additiveReferencePoseTime * m_Clips[0].frameRate;\n\n            float startTime = m_StartFrame / m_Clips[0].frameRate;\n            float stopTime = m_StopFrame / m_Clips[0].frameRate;\n            float additivePoseTime = m_AdditivePoseFrame / m_Clips[0].frameRate;\n\n            MuscleClipQualityInfo clipQualityInfo = MuscleClipUtility.GetMuscleClipQualityInfo(m_Clips[0], startTime,\n                stopTime);\n\n            bool IsHumanClip = (target as Motion).isHumanMotion;\n            bool hasMotionCurves = m_Clips[0].hasMotionCurves;\n            bool hasRootCurves = m_Clips[0].hasRootCurves;\n            bool hasGenericRootTransform = m_Clips[0].hasGenericRootTransform;\n            bool hasMotionFloatCurves = m_Clips[0].hasMotionFloatCurves;\n            bool hasAnyRootCurves = hasRootCurves || hasMotionCurves;\n\n            bool changedStart = false;\n            bool changedStop = false;\n            bool changedAdditivePoseFrame = false;\n\n            if (m_ClipInfo != null)\n            {\n                if (hasAnyRootCurves)\n                {\n                    if (m_DirtyQualityCurves)\n                        CalculateQualityCurves();\n\n                    // Calculate curves AFTER first repaint to be more responsive.\n                    if (m_QualityCurves[0] == null && Event.current.type == EventType.Repaint)\n                    {\n                        m_DirtyQualityCurves = true;\n                        Repaint();\n                    }\n                }\n\n                ClipRangeGUI(ref m_StartFrame, ref m_StopFrame, out changedStart, out changedStop, animationClipSettings.hasAdditiveReferencePose, ref m_AdditivePoseFrame, out changedAdditivePoseFrame);\n            }\n\n            // Update range info\n            if (!m_DraggingRange)\n            {\n                animationClipSettings.startTime = startTime;\n                animationClipSettings.stopTime = stopTime;\n                animationClipSettings.additiveReferencePoseTime = additivePoseTime;\n            }\n\n            m_AvatarPreview.timeControl.startTime = startTime;\n            m_AvatarPreview.timeControl.stopTime = stopTime;\n\n            // While dragging, only update the preview\n            if (changedStart)\n                m_AvatarPreview.timeControl.nextCurrentTime = startTime;\n            if (changedStop)\n                m_AvatarPreview.timeControl.nextCurrentTime = stopTime;\n            if (changedAdditivePoseFrame)\n                m_AvatarPreview.timeControl.nextCurrentTime = additivePoseTime;\n\n            EditorGUIUtility.labelWidth = 0;\n            EditorGUIUtility.fieldWidth = 0;\n\n\n            // Loop time\n            // Toggle\n            Rect toggleLoopTimeRect = EditorGUILayout.GetControlRect();\n            LoopToggle(toggleLoopTimeRect, Styles.LoopTime, ref animationClipSettings.loopTime);\n\n            Rect toggleLoopPoseRect;\n            using (new EditorGUI.DisabledScope(!animationClipSettings.loopTime))\n            {\n                EditorGUI.indentLevel++;\n\n                // Loop pose\n                // Toggle\n                toggleLoopPoseRect = EditorGUILayout.GetControlRect();\n                LoopToggle(toggleLoopPoseRect, Styles.LoopPose, ref animationClipSettings.loopBlend);\n\n                // Offset\n                animationClipSettings.cycleOffset = EditorGUILayout.FloatField(Styles.LoopCycleOffset, animationClipSettings.cycleOffset);\n\n                EditorGUI.indentLevel--;\n            }\n\n            EditorGUILayout.Space();\n\n            bool showCurves = IsHumanClip && (changedStart || changedStop);\n\n            if (hasRootCurves && !hasMotionCurves)\n            {\n                // Rotation\n                GUILayout.Label(Styles.RootTransformRotation, EditorStyles.label);\n                EditorGUI.indentLevel++;\n                // Toggle\n                Rect toggleRotRect = EditorGUILayout.GetControlRect();\n                LoopToggle(toggleRotRect, Styles.BakeIntoPoseOrientation, ref animationClipSettings.loopBlendOrientation);\n                // Reference\n                int offsetRotation = (animationClipSettings.keepOriginalOrientation ? 0 : 1);\n\n                offsetRotation =\n                    EditorGUILayout.Popup(\n                        animationClipSettings.loopBlendOrientation\n                        ? Styles.BasedUponOrientation\n                        : Styles.BasedUponStartOrientation,\n                        offsetRotation, IsHumanClip ? Styles.BasedUponRotationHumanOpt : Styles.BasedUponRotationOpt);\n\n                animationClipSettings.keepOriginalOrientation = (offsetRotation == 0);\n                // Offset\n                if (showCurves)\n                    EditorGUILayout.GetControlRect();\n                else\n                    animationClipSettings.orientationOffsetY = EditorGUILayout.FloatField(Styles.OrientationOffsetY,\n                        animationClipSettings\n                            .orientationOffsetY);\n                EditorGUI.indentLevel--;\n\n                EditorGUILayout.Space();\n\n                // Position Y\n                GUILayout.Label(Styles.RootTransformRotationY, EditorStyles.label);\n                EditorGUI.indentLevel++;\n                // Toggle\n                Rect toggleYRect = EditorGUILayout.GetControlRect();\n                LoopToggle(toggleYRect, Styles.BakeIntoPosePositionY, ref animationClipSettings.loopBlendPositionY);\n                // Reference\n                if (IsHumanClip)\n                {\n                    int offsetHeight;\n                    if (animationClipSettings.keepOriginalPositionY)\n                        offsetHeight = 0;\n                    else if (animationClipSettings.heightFromFeet)\n                        offsetHeight = 2;\n                    else\n                        offsetHeight = 1;\n\n                    offsetHeight =\n                        EditorGUILayout.Popup(\n                            animationClipSettings.loopBlendPositionY\n                            ? Styles.BasedUponStartPositionY\n                            : Styles.BasedUponPositionY,\n                            offsetHeight, Styles.BasedUponPositionYHumanOpt);\n\n                    if (offsetHeight == 0)\n                    {\n                        animationClipSettings.keepOriginalPositionY = true;\n                        animationClipSettings.heightFromFeet = false;\n                    }\n                    else if (offsetHeight == 1)\n                    {\n                        animationClipSettings.keepOriginalPositionY = false;\n                        animationClipSettings.heightFromFeet = false;\n                    }\n                    else\n                    {\n                        animationClipSettings.keepOriginalPositionY = false;\n                        animationClipSettings.heightFromFeet = true;\n                    }\n                }\n                else\n                {\n                    int offsetHeight = (animationClipSettings.keepOriginalPositionY ? 0 : 1);\n                    offsetHeight =\n                        EditorGUILayout.Popup(\n                            animationClipSettings.loopBlendPositionY\n                            ? Styles.BasedUponStartPositionY\n                            : Styles.BasedUponPositionY,\n                            offsetHeight, Styles.BasedUponPositionYOpt);\n                    animationClipSettings.keepOriginalPositionY = (offsetHeight == 0);\n                }\n                // Offset\n                if (showCurves)\n                    EditorGUILayout.GetControlRect();\n                else\n                    animationClipSettings.level = EditorGUILayout.FloatField(Styles.PositionOffsetY,\n                        animationClipSettings.level);\n                EditorGUI.indentLevel--;\n\n                EditorGUILayout.Space();\n\n                // Position XZ\n                GUILayout.Label(Styles.RootTransformPositionXZ, EditorStyles.label);\n                EditorGUI.indentLevel++;\n                // Toggle\n                Rect toggleXZRect = EditorGUILayout.GetControlRect();\n                LoopToggle(toggleXZRect, Styles.BakeIntoPosePositionXZ, ref animationClipSettings.loopBlendPositionXZ);\n                // Reference\n                int offsetPosition = (animationClipSettings.keepOriginalPositionXZ ? 0 : 1);\n                offsetPosition =\n                    EditorGUILayout.Popup(\n                        animationClipSettings.loopBlendPositionXZ\n                        ? Styles.BasedUponStartPositionXZ\n                        : Styles.BasedUponPositionXZ,\n                        offsetPosition, IsHumanClip ? Styles.BasedUponPositionXZHumanOpt : Styles.BasedUponPositionXZOpt);\n                animationClipSettings.keepOriginalPositionXZ = (offsetPosition == 0);\n                EditorGUI.indentLevel--;\n\n                EditorGUILayout.Space();\n\n                if (hasAnyRootCurves)\n                {\n                    // Lamps and toggles drawn later to make them be drawn on top\n                    if (IsHumanClip)\n                    {\n                        LoopQualityLampAndCurve(toggleLoopPoseRect, clipQualityInfo.loop, s_LoopMeterHint, changedStart,\n                            changedStop,\n                            m_QualityCurves[kPose]);\n                    }\n\n                    LoopQualityLampAndCurve(toggleRotRect, clipQualityInfo.loopOrientation, s_LoopOrientationMeterHint,\n                        changedStart,\n                        changedStop, m_QualityCurves[kRotation]);\n                    LoopQualityLampAndCurve(toggleYRect, clipQualityInfo.loopPositionY, s_LoopPositionYMeterHint, changedStart,\n                        changedStop, m_QualityCurves[kHeight]);\n                    LoopQualityLampAndCurve(toggleXZRect, clipQualityInfo.loopPositionXZ, s_LoopPositionXZMeterHint,\n                        changedStart,\n                        changedStop, m_QualityCurves[kPosition]);\n                }\n            }\n\n            if (IsHumanClip)\n            {\n                if (hasMotionCurves)\n                {\n                    LoopQualityLampAndCurve(toggleLoopPoseRect, clipQualityInfo.loop, s_LoopMeterHint, changedStart,\n                        changedStop,\n                        m_QualityCurves[kPose]);\n                }\n                animationClipSettings.mirror = EditorGUILayout.Toggle(Styles.Mirror, animationClipSettings.mirror);\n            }\n\n            if (m_ClipInfo != null)\n            {\n                animationClipSettings.hasAdditiveReferencePose = EditorGUILayout.Toggle(Styles.HasAdditiveReferencePose, animationClipSettings.hasAdditiveReferencePose);\n                using (new EditorGUI.DisabledScope(!animationClipSettings.hasAdditiveReferencePose))\n                {\n                    EditorGUI.indentLevel++;\n\n                    m_AdditivePoseFrame = EditorGUILayout.FloatField(Styles.AdditiveReferencePoseFrame, m_AdditivePoseFrame);\n                    m_AdditivePoseFrame = Mathf.Clamp(m_AdditivePoseFrame, m_Clips[0].startTime * m_Clips[0].frameRate, m_Clips[0].stopTime * m_Clips[0].frameRate);\n\n                    animationClipSettings.additiveReferencePoseTime = m_AdditivePoseFrame / m_Clips[0].frameRate;\n                    EditorGUI.indentLevel--;\n                }\n            }\n\n            if (hasGenericRootTransform && hasMotionFloatCurves)\n            {\n                EditorGUILayout.HelpBox(\"Root contains both root motion and transform curves\", MessageType.Warning);\n            }\n            else if (hasMotionFloatCurves)\n            {\n                EditorGUILayout.HelpBox(\"Root contains root motion curves\", MessageType.Info);\n            }\n            else if (hasGenericRootTransform)\n            {\n                EditorGUILayout.HelpBox(\"Root contains position and rotation curves\", MessageType.Info);\n            }\n\n            // Stats\n            string statsText = GetStatsText();\n            if (statsText != \"\")\n                GUILayout.Label(statsText, EditorStyles.helpBox);\n\n            EditorGUILayout.Space();\n\n            bool wasChanged;\n\n            // Additional curves\n            if (m_ClipInfo != null)\n            {\n                // Don't make toggling foldout cause GUI.changed to be true (shouldn't cause undoable action etc.)\n                wasChanged = GUI.changed;\n                m_ShowCurves = EditorGUILayout.Foldout(m_ShowCurves, Styles.Curves, true);\n                GUI.changed = wasChanged;\n                if (m_ShowCurves)\n                    CurveGUI();\n            }\n\n            if(m_ClipInfo != null && m_ClipInfo.hasAdditiveReferencePose && m_ClipInfo.GetCurveCount() > 0 &&\n               (m_ClipInfo.additiveReferencePoseFrame < m_ClipInfo.firstFrame || m_ClipInfo.additiveReferencePoseFrame > m_ClipInfo.lastFrame))\n            {\n                EditorGUILayout.HelpBox(\"Additional curves will be compared to zero values instead of the source clip's curves. \"+\n                    \"This is because the source clip doesn't include these specific curves. \" +\n                    \"To ensure accurate comparisons, consider using a reference pose frame within the clip's start and end frames.\", MessageType.Warning);\n            }\n\n            if (m_ClipInfo != null)\n            {\n                wasChanged = GUI.changed;\n                m_ShowEvents = EditorGUILayout.Foldout(m_ShowEvents, Styles.Events, true);\n                GUI.changed = wasChanged;\n                if (m_ShowEvents)\n                    EventsGUI();\n            }\n\n            if (m_DraggingRangeBegin)\n            {\n                m_LoopTime = animationClipSettings.loopTime;\n                m_LoopBlend = animationClipSettings.loopBlend;\n                m_LoopBlendOrientation = animationClipSettings.loopBlendOrientation;\n                m_LoopBlendPositionY = animationClipSettings.loopBlendPositionY;\n                m_LoopBlendPositionXZ = animationClipSettings.loopBlendPositionXZ;\n\n                animationClipSettings.loopTime = false;\n                animationClipSettings.loopBlend = false;\n                animationClipSettings.loopBlendOrientation = false;\n                animationClipSettings.loopBlendPositionY = false;\n                animationClipSettings.loopBlendPositionXZ = false;\n\n                m_DraggingStartFrame = animationClipSettings.startTime * m_Clips[0].frameRate;\n                m_DraggingStopFrame = animationClipSettings.stopTime * m_Clips[0].frameRate;\n                m_DraggingAdditivePoseFrame = animationClipSettings.additiveReferencePoseTime * m_Clips[0].frameRate;\n\n                //case 790259: The length of the clip will be changed by this inspector, so we can't use it for sampling\n                animationClipSettings.startTime = 0;\n                animationClipSettings.stopTime = m_InitialClipLength;\n\n                AnimationUtility.SetAnimationClipSettingsNoDirty(m_Clips[0], animationClipSettings);\n\n                DestroyController();\n            }\n\n            if (m_DraggingRangeEnd)\n            {\n                animationClipSettings.loopTime = m_LoopTime;\n                animationClipSettings.loopBlend = m_LoopBlend;\n                animationClipSettings.loopBlendOrientation = m_LoopBlendOrientation;\n                animationClipSettings.loopBlendPositionY = m_LoopBlendPositionY;\n                animationClipSettings.loopBlendPositionXZ = m_LoopBlendPositionXZ;\n            }\n\n            if (EditorGUI.EndChangeCheck() || m_DraggingRangeEnd)\n            {\n                if (!m_DraggingRange)\n                {\n                    Undo.RegisterCompleteObjectUndo(m_Clips, \"Muscle Clip Edit\");\n                    AnimationUtility.SetAnimationClipSettingsNoDirty(m_Clips[0], animationClipSettings);\n                    EditorUtility.SetDirty(m_Clips[0]);\n                    DestroyController();\n                }\n            }\n        }\n\n        private void LoopToggle(Rect r, GUIContent content, ref bool val)\n        {\n            if (!m_DraggingRange)\n                val = EditorGUI.Toggle(r, content, val);\n            else\n            {\n                EditorGUI.LabelField(r, content, GUIContent.none);\n                using (new EditorGUI.DisabledScope(true))\n                {\n                    EditorGUI.Toggle(r, \" \", false);\n                }\n            }\n        }\n\n        private void LoopQualityLampAndCurve(Rect position, float value, int lightMeterHint, bool changedStart, bool changedStop, Vector2[][] curves)\n        {\n            if (m_ClipInfo == null)\n                return;\n\n            GUIStyle style = new GUIStyle(EditorStyles.miniLabel);\n            style.alignment = TextAnchor.MiddleRight;\n\n            Rect labelPosition = position;\n            labelPosition.xMax -= 20;\n            labelPosition.xMin += EditorGUIUtility.labelWidth;\n            GUI.Label(labelPosition, Styles.LoopMatch, style);\n\n            Event evt = Event.current;\n            int id = GUIUtility.GetControlID(lightMeterHint, FocusType.Passive, position);\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.Repaint:\n                {\n                    const int lampSize = 22;\n                    Rect lampPosition = position;\n                    float overflow = (lampSize - lampPosition.height) / 2;\n                    lampPosition.y -= overflow;\n                    lampPosition.xMax += overflow;\n                    lampPosition.height = lampSize;\n                    lampPosition.xMin = lampPosition.xMax - lampSize;\n\n                    if (value < .33f)\n                        GUI.DrawTexture(lampPosition, Styles.RedLightIcon.image);\n                    else if (value < .66f)\n                        GUI.DrawTexture(lampPosition, Styles.OrangeLightIcon.image);\n                    else\n                        GUI.DrawTexture(lampPosition, Styles.GreenLightIcon.image);\n                    GUI.DrawTexture(lampPosition, Styles.LightRimIcon.image);\n                    break;\n                }\n            }\n\n            if (changedStart || changedStop)\n            {\n                Rect r = position;\n                r.y += r.height + 1;\n                r.height = 18;\n\n                // Draw border for quality curve\n                GUI.color = new Color(0, 0, 0, !EditorGUIUtility.isProSkin ? 0.8f : 0.3f);\n                GUI.DrawTexture(r, EditorGUIUtility.whiteTexture);\n\n                // Subtract 1 pixel so curve is drawn inside border\n                r = new RectOffset(-1, -1, -1, -1).Add(r);\n\n                // Draw background for quality curve\n                if (!EditorGUIUtility.isProSkin)\n                    GUI.color = new Color(90f / 255f, 90f / 255f, 90f / 255f, 1);\n                else\n                    GUI.color = new Color(65f / 255f, 65f / 255f, 65f / 255f, 1);\n                GUI.DrawTexture(r, EditorGUIUtility.whiteTexture);\n\n\n                GUI.color = Color.white;\n\n                GUI.BeginGroup(r);\n                {\n                    // Calculate matrix to apply to points\n                    Matrix4x4 matrix = m_TimeArea.drawingToViewMatrix;\n                    matrix.m00 = r.width / m_TimeArea.shownArea.width;\n                    matrix.m11 = r.height - 1;\n                    matrix.m03 = -m_TimeArea.shownArea.x * r.width / m_TimeArea.shownArea.width;\n                    matrix.m13 = 0;\n\n                    // Apply matrix and assign color for each sample\n                    Vector2[] keys = curves[changedStart ? 0 : 1];\n                    Vector3[] points = new Vector3[keys.Length];\n                    Color[] colors = new Color[keys.Length];\n                    Color curveColorRed = new Color(1.0f, 0.3f, 0.3f);\n                    Color curveColorOrange = new Color(1.0f, 0.8f, 0.0f);\n                    Color curveColorGreen = new Color(0.0f, 1.0f, 0.0f);\n                    for (int i = 0; i < points.Length; i++)\n                    {\n                        points[i] = keys[i];\n                        points[i] = matrix.MultiplyPoint3x4(points[i]);\n                        if (1 - keys[i].y < .33f)\n                            colors[i] = curveColorRed;\n                        else if (1 - keys[i].y < .66f)\n                            colors[i] = curveColorOrange;\n                        else\n                            colors[i] = curveColorGreen;\n                    }\n\n                    // Draw curve based on calculated points and colors\n                    Handles.DrawAAPolyLine(colors, points);\n\n                    // Draw start and end markers\n                    GUI.color = new Color(0.3f, 0.6f, 1.0f);\n                    // Draw marker for moving end\n                    float timePixel = matrix.MultiplyPoint3x4(new Vector3((changedStart ? m_StartFrame : m_StopFrame) / m_Clips[0].frameRate, 0, 0)).x;\n                    GUI.DrawTexture(new Rect(timePixel, 0, 1, r.height), EditorGUIUtility.whiteTexture);\n                    // Draw marker for static end\n                    timePixel = matrix.MultiplyPoint3x4(new Vector3((changedStart ? m_StopFrame : m_StartFrame) / m_Clips[0].frameRate, 0, 0)).x;\n                    GUI.DrawTexture(new Rect(timePixel, 0, 1, r.height), EditorGUIUtility.whiteTexture);\n                    GUI.color = Color.white;\n                }\n                GUI.EndGroup();\n            }\n        }\n    }\n\n    // TODO merge this with AnimationWindow once its re-done for 2D\n    internal class EventManipulationHandler\n    {\n        private Rect[] m_EventRects = new Rect[0];\n        private static AnimationEvent[] m_EventsAtMouseDown;\n        private static float[] m_EventTimes;\n        private int m_HoverEvent = -1;\n\n        private string m_InstantTooltipText = null;\n        private Vector2 m_InstantTooltipPoint = Vector2.zero;\n\n        private bool[] m_EventsSelected;\n        private AnimationWindowEvent[] m_Events;\n\n        private TimeArea m_Timeline;\n        private AnimationEventEditorState m_EventEditorState = new();\n\n        public EventManipulationHandler(TimeArea timeArea)\n        {\n            m_Timeline = timeArea;\n        }\n\n        public void SelectEvent(AnimationEvent[] events, int index, AnimationClipInfoProperties clipInfo)\n        {\n            m_EventsSelected = new bool[events.Length];\n            m_EventsSelected[index] = true;\n\n            EditEvents(clipInfo, m_EventsSelected);\n        }\n\n        public bool HandleEventManipulation(Rect rect, ref AnimationEvent[] events, AnimationClipInfoProperties clipInfo, float currentTime)\n        {\n            Texture eventMarker = EditorGUIUtility.IconContent(\"Animation.EventMarker\").image;\n\n            bool hasChanged = false;\n\n            // Calculate rects\n            Rect[] hitRects = new Rect[events.Length];\n            Rect[] drawRects = new Rect[events.Length];\n            int shared = 1;\n            int sharedLeft = 0;\n            for (int i = 0; i < events.Length; i++)\n            {\n                AnimationEvent evt = events[i];\n\n                if (sharedLeft == 0)\n                {\n                    shared = 1;\n                    while (i + shared < events.Length && events[i + shared].time == evt.time)\n                        shared++;\n                    sharedLeft = shared;\n                }\n                sharedLeft--;\n\n                // Important to take floor of positions of GUI stuff to get pixel correct alignment of\n                // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time.\n                float keypos = Mathf.Floor(m_Timeline.TimeToPixel(evt.time, rect));\n                int sharedOffset = 0;\n                if (shared > 1)\n                {\n                    float spread = Mathf.Min((shared - 1) * (eventMarker.width - 1), (int)(1.0f / m_Timeline.PixelDeltaToTime(rect) - eventMarker.width * 2));\n                    sharedOffset = Mathf.FloorToInt(Mathf.Max(0, spread - (eventMarker.width - 1) * (sharedLeft)));\n                }\n\n                // UUM-49717\n                // Depending on the resolution and the scale of the display, the icon size could be greater than the visible height of the timeline.\n                // We divide it so that it fits.\n                float absRectHeight = Mathf.Abs(rect.height);\n                int divider = absRectHeight > 0 && absRectHeight < eventMarker.height ? Mathf.CeilToInt(eventMarker.height / absRectHeight) : 1;\n\n                Rect r = new Rect(\n                    keypos + sharedOffset - eventMarker.width / (2 * divider),\n                    (rect.height - 10) * (float)(sharedLeft - shared + 1) / Mathf.Max(1, shared - 1),\n                    eventMarker.width / divider,\n                    eventMarker.height / divider);\n\n                hitRects[i] = r;\n                drawRects[i] = r;\n            }\n\n            // Store rects used for tooltip testing\n            m_EventRects = new Rect[hitRects.Length];\n            for (int i = 0; i < hitRects.Length; i++)\n                m_EventRects[i] = new Rect(hitRects[i].x + rect.x, hitRects[i].y + rect.y, hitRects[i].width, hitRects[i].height);\n\n            // Selection control\n            if (m_EventsSelected == null || m_EventsSelected.Length != events.Length || m_EventsSelected.Length == 0)\n            {\n                m_EventsSelected = new bool[events.Length];\n                m_Events = null;\n            }\n\n            Vector2 offset = Vector2.zero;\n            int clickedIndex;\n            float startSelection, endSelection;\n\n            // TODO: GUIStyle.none has hopping margins that need to be fixed\n            HighLevelEvent hEvent = EditorGUIExt.MultiSelection(\n                rect,\n                drawRects,\n                new GUIContent(eventMarker),\n                hitRects,\n                ref m_EventsSelected,\n                null,\n                out clickedIndex,\n                out offset,\n                out startSelection,\n                out endSelection,\n                GUIStyle.none\n            );\n\n\n            if (hEvent != HighLevelEvent.None)\n            {\n                switch (hEvent)\n                {\n                    case HighLevelEvent.BeginDrag:\n                        m_EventsAtMouseDown = events;\n                        m_EventTimes = new float[events.Length];\n                        for (int i = 0; i < events.Length; i++)\n                            m_EventTimes[i] = events[i].time;\n                        break;\n                    case HighLevelEvent.SelectionChanged:\n                        EditEvents(clipInfo, m_EventsSelected);\n                        break;\n                    case HighLevelEvent.Delete:\n                        hasChanged = DeleteEvents(ref events, m_EventsSelected);\n                        break;\n                    case HighLevelEvent.Copy:\n                        AnimationWindowEventsClipboard.CopyEvents(events, m_EventsSelected);\n                        break;\n                    case HighLevelEvent.Paste:\n                        hasChanged = PasteEvents(ref events, ref m_EventsSelected, currentTime);\n                        if (hasChanged)\n                            EditEvents(clipInfo, m_EventsSelected);\n                        break;\n                    case HighLevelEvent.Drag:\n                        for (int i = events.Length - 1; i >= 0; i--)\n                        {\n                            if (m_EventsSelected[i])\n                            {\n                                AnimationEvent evt = m_EventsAtMouseDown[i];\n                                evt.time = Mathf.Clamp01(m_EventTimes[i] + (offset.x / rect.width));\n                            }\n                        }\n                        int[] order = new int[m_EventsSelected.Length];\n                        for (int i = 0; i < order.Length; i++)\n                        {\n                            order[i] = i;\n                        }\n                        System.Array.Sort(m_EventsAtMouseDown, order, new AnimationEventTimeLine.EventComparer());\n                        bool[] selectedOld = (bool[])m_EventsSelected.Clone();\n                        float[] timesOld = (float[])m_EventTimes.Clone();\n                        for (int i = 0; i < order.Length; i++)\n                        {\n                            m_EventsSelected[i] = selectedOld[order[i]];\n                            m_EventTimes[i] = timesOld[order[i]];\n                        }\n\n                        events = m_EventsAtMouseDown;\n                        hasChanged = true;\n                        break;\n\n                    case HighLevelEvent.ContextClick:\n                        CreateContextMenu(clipInfo, events[clickedIndex].time, clickedIndex, m_EventsSelected);\n                        // Mouse may move while context menu is open - make sure instant tooltip is handled\n                        m_InstantTooltipText = null;\n                        break;\n                }\n            }\n\n            // Bring up menu when context-clicking on an empty timeline area (context-clicking on events is handled above)\n            if (Event.current.type == EventType.ContextClick && rect.Contains(Event.current.mousePosition))\n            {\n                Event.current.Use();\n                float mousePosTime = Mathf.Max(m_Timeline.PixelToTime(Event.current.mousePosition.x, rect), 0.0f);\n                CreateContextMenu(clipInfo, mousePosTime, -1, m_EventsSelected);\n                // Mouse may move while context menu is open - make sure instant tooltip is handled\n                m_InstantTooltipText = null;\n            }\n\n            CheckRectsOnMouseMove(rect, events, hitRects);\n\n            return hasChanged;\n        }\n\n        void CreateContextMenu(AnimationClipInfoProperties info, float time, int eventIndex, bool[] selectedEvents)\n        {\n            GenericMenu menu = new GenericMenu();\n            var ctx = new EventModificationContextMenuObject(info, time, eventIndex, selectedEvents);\n            var selectedCount = selectedEvents.Count(selected => selected);\n\n            menu.AddItem(AnimationClipEditor.Styles.AddEvent, false, EventLineContextMenuAdd, ctx);\n            if (selectedCount > 0 || eventIndex != -1)\n            {\n                menu.AddItem(selectedCount > 1 ? AnimationClipEditor.Styles.DeleteEvents : AnimationClipEditor.Styles.DeleteEvent, false, EventLineContextMenuDelete, ctx);\n                menu.AddItem(AnimationClipEditor.Styles.CopyEvents, false, EventLineContextMenuCopy, ctx);\n            }\n            else\n            {\n                menu.AddDisabledItem(AnimationClipEditor.Styles.DeleteEvents);\n                menu.AddDisabledItem(AnimationClipEditor.Styles.CopyEvents);\n            }\n            if (AnimationWindowEventsClipboard.CanPaste())\n                menu.AddItem(AnimationClipEditor.Styles.PasteEvents, false, EventLineContextMenuPaste, ctx);\n            else\n                menu.AddDisabledItem(AnimationClipEditor.Styles.PasteEvents);\n            menu.ShowAsContext();\n        }\n\n        private class EventModificationContextMenuObject\n        {\n            public AnimationClipInfoProperties m_Info;\n            public float m_Time;\n            public int m_Index;\n            public bool[] m_Selected;\n\n            public EventModificationContextMenuObject(AnimationClipInfoProperties info, float time, int index, bool[] selected)\n            {\n                m_Info = info;\n                m_Time = time;\n                m_Index = index;\n                m_Selected = selected;\n            }\n        }\n\n        public void EventLineContextMenuAdd(object obj)\n        {\n            EventModificationContextMenuObject context = (EventModificationContextMenuObject)obj;\n\n            context.m_Info.AddEvent(context.m_Time);\n            context.m_Info.ApplyModifiedProperties();\n            SelectEvent(context.m_Info.GetEvents(), context.m_Info.GetEventCount() - 1, context.m_Info);\n        }\n\n        public void EventLineContextMenuDelete(object obj)\n        {\n            EventModificationContextMenuObject context = (EventModificationContextMenuObject)obj;\n\n            if (Array.Exists(context.m_Selected, selected => selected))\n            {\n                for (int i = context.m_Selected.Length - 1; i >= 0; --i)\n                {\n                    if (context.m_Selected[i])\n                        context.m_Info.RemoveEvent(i);\n                }\n            }\n            else if (context.m_Index >= 0)\n            {\n                context.m_Info.RemoveEvent(context.m_Index);\n            }\n            context.m_Info.ApplyModifiedProperties();\n        }\n\n        static void EventLineContextMenuCopy(object obj)\n        {\n            var ctx = (EventModificationContextMenuObject)obj;\n            AnimationWindowEventsClipboard.CopyEvents(ctx.m_Info.GetEvents(), ctx.m_Selected, ctx.m_Index);\n        }\n\n        void EventLineContextMenuPaste(object obj)\n        {\n            var ctx = (EventModificationContextMenuObject)obj;\n            var events = ctx.m_Info.GetEvents();\n            var changed = PasteEvents(ref events, ref ctx.m_Selected, ctx.m_Time);\n            if (changed)\n            {\n                ctx.m_Info.SetEvents(events);\n                ctx.m_Info.ApplyModifiedProperties();\n                m_EventsSelected = ctx.m_Selected;\n                EditEvents(ctx.m_Info, ctx.m_Selected);\n            }\n        }\n\n        private void CheckRectsOnMouseMove(Rect eventLineRect, AnimationEvent[] events, Rect[] hitRects)\n        {\n            Vector2 mouse = Event.current.mousePosition;\n            bool hasFound = false;\n            m_InstantTooltipText = \"\";\n\n            if (events.Length == hitRects.Length)\n            {\n                for (int i = hitRects.Length - 1; i >= 0; i--)\n                {\n                    if (hitRects[i].Contains(mouse))\n                    {\n                        hasFound = true;\n                        if (m_HoverEvent != i)\n                        {\n                            m_HoverEvent = i;\n                            m_InstantTooltipText = events[m_HoverEvent].functionName;\n                            m_InstantTooltipPoint = new Vector2(mouse.x, mouse.y);\n                        }\n                    }\n                }\n            }\n            if (!hasFound)\n                m_HoverEvent = -1;\n        }\n\n        public void Draw(Rect window)\n        {\n            EditorGUI.indentLevel++;\n            if (m_Events != null && m_Events.Length > 0)\n                AnimationWindowEventInspector.OnEditAnimationEvents(m_Events, m_EventEditorState);\n            else\n                AnimationWindowEventInspector.OnDisabledAnimationEvent();\n\n            EditorGUI.indentLevel--;\n\n            if (!string.IsNullOrEmpty(m_InstantTooltipText))\n            {\n                // Draw body of tooltip\n                GUIStyle style = (GUIStyle)\"AnimationEventTooltip\";\n                Vector2 size = style.CalcSize(new GUIContent(m_InstantTooltipText));\n                Rect rect = new Rect(window.x + m_InstantTooltipPoint.x, window.y + m_InstantTooltipPoint.y, size.x, size.y);\n\n                // Right align tooltip rect if it would otherwise exceed the bounds of the window\n                if (rect.xMax > window.width)\n                    rect.x = window.width - rect.width;\n\n                GUI.Label(rect, m_InstantTooltipText, style);\n            }\n        }\n\n        public bool DeleteEvents(ref AnimationEvent[] eventList, bool[] deleteIndices)\n        {\n            bool deletedAny = false;\n\n            for (int i = eventList.Length - 1; i >= 0; i--)\n            {\n                if (deleteIndices[i])\n                {\n                    ArrayUtility.RemoveAt(ref eventList, i);\n                    deletedAny = true;\n                }\n            }\n\n            if (deletedAny)\n            {\n                m_EventsSelected = new bool[eventList.Length];\n                m_Events = null;\n            }\n\n            return deletedAny;\n        }\n\n        static bool PasteEvents(ref AnimationEvent[] eventList, ref bool[] selected, float time)\n        {\n            var newEvents = AnimationWindowEventsClipboard.AddPastedEvents(eventList, time, out var newSelected);\n            if (newEvents == null)\n                return false;\n            eventList = newEvents;\n            selected = newSelected;\n            return true;\n        }\n\n        public void EditEvents(AnimationClipInfoProperties clipInfo, bool[] selectedIndices)\n        {\n            List<AnimationWindowEvent> awEvents = new List<AnimationWindowEvent>();\n\n            for (int index = 0; index < selectedIndices.Length; ++index)\n            {\n                if (selectedIndices[index])\n                    awEvents.Add(AnimationWindowEvent.Edit(clipInfo, index));\n            }\n\n            m_Events = awEvents.ToArray();\n        }\n\n        public void UpdateEvents(AnimationClipInfoProperties clipInfo)\n        {\n            if (m_Events == null)\n                return;\n\n            foreach (AnimationWindowEvent awEvent in m_Events)\n            {\n                awEvent.clipInfo = clipInfo;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AnimationEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(Animation))]\n    [CanEditMultipleObjects]\n    internal class AnimationEditor : Editor\n    {\n        private int m_PrePreviewAnimationArraySize = -1;\n\n        public void OnEnable()\n        {\n            m_PrePreviewAnimationArraySize = -1;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            SerializedProperty clipProperty = serializedObject.FindProperty(\"m_Animation\");\n\n            EditorGUILayout.PropertyField(clipProperty, true);\n            int newAnimID = clipProperty.objectReferenceInstanceIDValue;\n\n            SerializedProperty arrProperty = serializedObject.FindProperty(\"m_Animations\");\n            int arrSize = arrProperty.arraySize;\n\n            // Remember the array size when ObjectSelector becomes visible\n            if (ObjectSelector.isVisible && m_PrePreviewAnimationArraySize == -1)\n                m_PrePreviewAnimationArraySize = arrSize;\n\n            // Make sure the array is the original array size + 1 at max (+1 for the ObjectSelector preview slot)\n            if (m_PrePreviewAnimationArraySize != -1)\n            {\n                // Always resize if the last anim element is not the current animation\n                int lastAnimID = arrSize > 0 ? arrProperty.GetArrayElementAtIndex(arrSize - 1).objectReferenceInstanceIDValue : -1;\n                if (lastAnimID != newAnimID)\n                    arrProperty.arraySize = m_PrePreviewAnimationArraySize;\n                if (!ObjectSelector.isVisible)\n                    m_PrePreviewAnimationArraySize = -1;\n            }\n\n            DrawPropertiesExcluding(serializedObject, \"m_Animation\", \"m_UserAABB\");\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        // A minimal list of settings to be shown in the Asset Store preview inspector\n        internal override void OnAssetStoreInspectorGUI()\n        {\n            OnInspectorGUI();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AnimatorInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditorInternal;\nusing UnityEditor.AnimatedValues;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(Animator))]\n    [CanEditMultipleObjects]\n    internal class AnimatorInspector : Editor\n    {\n        SerializedProperty m_Avatar;\n        SerializedProperty m_Controller;\n        SerializedProperty m_ApplyRootMotion;\n        SerializedProperty m_AnimatePhysics;\n        SerializedProperty m_CullingMode;\n        SerializedProperty m_UpdateMode;\n        SerializedProperty m_WarningMessage;\n\n        AnimBool m_ShowWarningMessage = new AnimBool();\n        bool m_IsRootPositionOrRotationControlledByCurves;\n\n        private bool IsWarningMessageEmpty { get { return m_WarningMessage != null && m_WarningMessage.stringValue.Length > 0; } }\n        private string WarningMessage { get { return m_WarningMessage != null ? m_WarningMessage.stringValue : \"\"; } }\n\n        class Styles\n        {\n            public GUIContent applyRootMotion = new GUIContent(EditorGUIUtility.TrTextContent(\"Apply Root Motion\"));\n            public GUIContent updateMode = new GUIContent(EditorGUIUtility.TrTextContent(\"Update Mode\"));\n            public GUIContent cullingMode = new GUIContent(EditorGUIUtility.TrTextContent(\"Culling Mode\"));\n            public GUIContent animatePhysics = new GUIContent(EditorGUIUtility.TrTextContent(\"Animate Physics\"));\n\n            public Styles()\n            {\n                applyRootMotion.tooltip = \"Automatically move the object using the root motion from the animations\";\n                updateMode.tooltip = \"Controls when and how often the Animator is updated\";\n                cullingMode.tooltip = \"Controls what is updated when the object has been culled\";\n                animatePhysics.tooltip = \"Notify physics system of animated transforms.\";\n            }\n        }\n        static Styles styles;\n\n        private void Init()\n        {\n            if (styles == null)\n            {\n                styles = new Styles();\n            }\n            InitShowOptions();\n        }\n\n        private void InitShowOptions()\n        {\n            m_ShowWarningMessage.value = IsWarningMessageEmpty;\n\n            m_ShowWarningMessage.valueChanged.AddListener(Repaint);\n        }\n\n        private void UpdateShowOptions()\n        {\n            m_ShowWarningMessage.target = IsWarningMessageEmpty;\n        }\n\n        void OnEnable()\n        {\n            m_Avatar = serializedObject.FindProperty(\"m_Avatar\");\n            m_ApplyRootMotion = serializedObject.FindProperty(\"m_ApplyRootMotion\");\n            m_AnimatePhysics = serializedObject.FindProperty(\"m_AnimatePhysics\");\n            m_Controller = serializedObject.FindProperty(\"m_Controller\");\n            m_CullingMode = serializedObject.FindProperty(\"m_CullingMode\");\n            m_UpdateMode = serializedObject.FindProperty(\"m_UpdateMode\");\n            m_WarningMessage = serializedObject.FindProperty(\"m_WarningMessage\");\n\n\n            Init();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            bool isEditingMultipleObjects = targets.Length > 1;\n\n            bool cullingModeChanged = false;\n            bool updateModeChanged = false;\n\n            Animator firstAnimator = target as Animator;\n\n            serializedObject.UpdateIfRequiredOrScript();\n\n            UpdateShowOptions();\n\n            EditorGUI.BeginChangeCheck();\n            //Collect the previous AnimatorControllers\n\n            EditorGUILayout.ObjectField(m_Controller);\n\n\n            var controller = m_Controller.objectReferenceValue as RuntimeAnimatorController;\n            if (EditorGUI.EndChangeCheck())\n            {\n                var controllers = new List<RuntimeAnimatorController>();\n                foreach (Animator animator in targets)\n                {\n                    controllers.Add(animator.runtimeAnimatorController);\n                }\n                serializedObject.ApplyModifiedProperties();\n                AnimationWindowUtility.ControllerChanged();\n            }\n\n            EditorGUILayout.PropertyField(m_Avatar);\n            if (firstAnimator.supportsOnAnimatorMove && !isEditingMultipleObjects)\n            {\n                EditorGUILayout.LabelField(\"Apply Root Motion\", \"Handled by Script\");\n            }\n            else\n            {\n                EditorGUILayout.PropertyField(m_ApplyRootMotion, styles.applyRootMotion);\n\n                // This might change between layout & repaint so we have local cached value to only update on layout\n                if (Event.current.type == EventType.Layout)\n                    m_IsRootPositionOrRotationControlledByCurves = firstAnimator.isRootPositionOrRotationControlledByCurves;\n\n                if (!m_ApplyRootMotion.boolValue && m_IsRootPositionOrRotationControlledByCurves)\n                {\n                    EditorGUILayout.HelpBox(\"Root position or rotation are controlled by curves\", MessageType.Info, true);\n                }\n            }\n\n            EditorGUILayout.PropertyField(m_AnimatePhysics, styles.animatePhysics);\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_UpdateMode, styles.updateMode);\n            updateModeChanged =  EditorGUI.EndChangeCheck();\n\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_CullingMode, styles.cullingMode);\n            cullingModeChanged =  EditorGUI.EndChangeCheck();\n\n\n            if (!isEditingMultipleObjects)\n                EditorGUILayout.HelpBox(firstAnimator.GetStats(), MessageType.Info, true);\n\n            if (EditorGUILayout.BeginFadeGroup(m_ShowWarningMessage.faded))\n            {\n                EditorGUILayout.HelpBox(WarningMessage, MessageType.Warning, true);\n            }\n            EditorGUILayout.EndFadeGroup();\n\n\n            serializedObject.ApplyModifiedProperties();\n\n            foreach (Animator animator in targets)\n            {\n                if (cullingModeChanged)\n                    animator.OnCullingModeChanged();\n\n                if (updateModeChanged)\n                    animator.OnUpdateModeChanged();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AnimatorOverrideControllerInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditorInternal;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class AnimationClipOverrideComparer : IComparer<KeyValuePair<AnimationClip, AnimationClip>>\n    {\n        public int Compare(KeyValuePair<AnimationClip, AnimationClip> x, KeyValuePair<AnimationClip, AnimationClip> y)\n        {\n            return string.Compare(x.Key.name, y.Key.name, System.StringComparison.OrdinalIgnoreCase);\n        }\n    }\n\n    [CustomEditor(typeof(AnimatorOverrideController))]\n    internal class AnimatorOverrideControllerInspector : Editor\n    {\n        SerializedProperty m_Controller;\n\n        private List<KeyValuePair<AnimationClip, AnimationClip>> m_Clips;\n\n        ReorderableList m_ClipList;\n        string m_Search;\n\n        void OnEnable()\n        {\n            AnimatorOverrideController animatorOverrideController = target as AnimatorOverrideController;\n\n            m_Controller = serializedObject.FindProperty(\"m_Controller\");\n            m_Search = \"\";\n\n            if (m_Clips == null)\n                m_Clips = new List<KeyValuePair<AnimationClip, AnimationClip>>();\n\n            if (m_ClipList == null)\n            {\n                animatorOverrideController.GetOverrides(m_Clips);\n\n                m_Clips.Sort(new AnimationClipOverrideComparer());\n\n                m_ClipList = new ReorderableList(m_Clips, typeof(KeyValuePair<AnimationClip, AnimationClip>), false, true, false, false);\n                m_ClipList.drawElementCallback = DrawClipElement;\n                m_ClipList.drawHeaderCallback = DrawClipHeader;\n                m_ClipList.onSelectCallback = SelectClip;\n                m_ClipList.elementHeight = 16;\n            }\n            animatorOverrideController.OnOverrideControllerDirty += Repaint;\n        }\n\n        void OnDisable()\n        {\n            AnimatorOverrideController animatorOverrideController = target as AnimatorOverrideController;\n            if (animatorOverrideController != null)\n                animatorOverrideController.OnOverrideControllerDirty -= Repaint;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            bool isEditingMultipleObjects = targets.Length > 1;\n            bool changeCheck = false;\n\n            serializedObject.UpdateIfRequiredOrScript();\n\n            AnimatorOverrideController animatorOverrideController = target as AnimatorOverrideController;\n            RuntimeAnimatorController  runtimeAnimatorController  = m_Controller.hasMultipleDifferentValues ? null : animatorOverrideController.runtimeAnimatorController;\n\n            EditorGUI.BeginChangeCheck();\n            runtimeAnimatorController = EditorGUILayout.ObjectField(\"Controller\", runtimeAnimatorController, typeof(Animations.AnimatorController), false) as RuntimeAnimatorController;\n            if (EditorGUI.EndChangeCheck())\n            {\n                for (int i = 0; i < targets.Length; i++)\n                {\n                    AnimatorOverrideController controller = targets[i] as AnimatorOverrideController;\n                    controller.runtimeAnimatorController = runtimeAnimatorController;\n                }\n\n                changeCheck = true;\n            }\n\n            {\n                GUI.SetNextControlName(\"OverridesSearch\");\n\n                if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape && GUI.GetNameOfFocusedControl() == \"OverridesSearch\")\n                    m_Search = \"\";\n\n                EditorGUI.BeginChangeCheck();\n                string newSearch = EditorGUILayout.ToolbarSearchField(m_Search);\n                if (EditorGUI.EndChangeCheck())\n                    m_Search = newSearch;\n            }\n\n\n            using (new EditorGUI.DisabledScope(m_Controller == null || (isEditingMultipleObjects && m_Controller.hasMultipleDifferentValues) || runtimeAnimatorController == null))\n            {\n                EditorGUI.BeginChangeCheck();\n                animatorOverrideController.GetOverrides(m_Clips);\n\n                if (m_Search.Length > 0)\n                    FilterOverrides();\n                else // If there is not filter simply sort all the list.\n                    m_Clips.Sort(new AnimationClipOverrideComparer());\n\n                m_ClipList.list = m_Clips;\n                m_ClipList.DoLayoutList();\n                if (EditorGUI.EndChangeCheck())\n                {\n                    for (int i = 0; i < targets.Length; i++)\n                    {\n                        AnimatorOverrideController controller = targets[i] as AnimatorOverrideController;\n                        controller.ApplyOverrides(m_Clips);\n                    }\n                    changeCheck = true;\n                }\n            }\n\n            if (changeCheck)\n                animatorOverrideController.PerformOverrideClipListCleanup();\n        }\n\n        private void FilterOverrides()\n        {\n            if (m_Search.Length == 0)\n                return;\n\n            // Support multiple search words separated by spaces.\n            string[] searchWords = m_Search.ToLower().Split(' ');\n\n            // We keep two lists. Matches that matches the start of an item always get first priority.\n            List<KeyValuePair<AnimationClip, AnimationClip>> matchesStart = new List<KeyValuePair<AnimationClip, AnimationClip>>();\n            List<KeyValuePair<AnimationClip, AnimationClip>> matchesWithin = new List<KeyValuePair<AnimationClip, AnimationClip>>();\n            foreach (KeyValuePair<AnimationClip, AnimationClip> kvp in m_Clips)\n            {\n                string name = kvp.Key.name;\n                name = name.ToLower().Replace(\" \", \"\");\n\n                bool didMatchAll = true;\n                bool didMatchStart = false;\n\n                // See if we match ALL the search words.\n                for (int w = 0; w < searchWords.Length; w++)\n                {\n                    string search = searchWords[w];\n                    if (name.Contains(search))\n                    {\n                        // If the start of the item matches the first search word, make a note of that.\n                        if (w == 0 && name.StartsWith(search))\n                            didMatchStart = true;\n                    }\n                    else\n                    {\n                        // As soon as any word is not matched, we disregard this item.\n                        didMatchAll = false;\n                        break;\n                    }\n                }\n                // We always need to match all search words.\n                // If we ALSO matched the start, this item gets priority.\n                if (didMatchAll)\n                {\n                    if (didMatchStart)\n                        matchesStart.Add(kvp);\n                    else\n                        matchesWithin.Add(kvp);\n                }\n            }\n\n            m_Clips.Clear();\n\n            matchesStart.Sort(new AnimationClipOverrideComparer());\n            matchesWithin.Sort(new AnimationClipOverrideComparer());\n\n            // Add search results\n            m_Clips.AddRange(matchesStart);\n            m_Clips.AddRange(matchesWithin);\n        }\n\n        private void DrawClipElement(Rect rect, int index, bool selected, bool focused)\n        {\n            AnimationClip originalClip = m_Clips[index].Key;\n            AnimationClip overrideClip = m_Clips[index].Value;\n\n            rect.xMax = rect.xMax / 2.0f;\n            GUI.Label(rect, originalClip.name, EditorStyles.label);\n            rect.xMin = rect.xMax;\n            rect.xMax *= 2.0f;\n\n            EditorGUI.BeginChangeCheck();\n            overrideClip = EditorGUI.ObjectField(rect, \"\", overrideClip, typeof(AnimationClip), false) as AnimationClip;\n            if (EditorGUI.EndChangeCheck())\n                m_Clips[index] = new KeyValuePair<AnimationClip, AnimationClip>(originalClip, overrideClip);\n        }\n\n        private void DrawClipHeader(Rect rect)\n        {\n            rect.xMax = rect.xMax / 2.0f;\n            GUI.Label(rect, \"Original\", EditorStyles.label);\n            rect.xMin = rect.xMax;\n            rect.xMax *= 2.0f;\n            GUI.Label(rect, \"Override\", EditorStyles.label);\n        }\n\n        private void SelectClip(ReorderableList list)\n        {\n            if (0 <= list.index && list.index < m_Clips.Count)\n                EditorGUIUtility.PingObject(m_Clips[list.index].Key);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor.Compilation;\nusing UnityEditor.AssetImporters;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing AssemblyFlags = UnityEditor.Scripting.ScriptCompilation.AssemblyFlags;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AssemblyDefinitionImporter))]\n    [CanEditMultipleObjects]\n    internal class AssemblyDefinitionImporterInspector : AssetImporterEditor\n    {\n        internal class Styles\n        {\n            public static readonly GUIContent name = EditorGUIUtility.TrTextContent(\"Name\", \"The assembly name is used to generate a <name>.dll file on you disk.\");\n            public static readonly GUIContent rootNamespace = EditorGUIUtility.TrTextContent(\"Root Namespace\", \"Specify the root namespace of the assembly.\");\n            public static readonly GUIContent defineConstraints = EditorGUIUtility.TrTextContent(\"Define Constraints\", \"Specify constraints which determine if the assembly will be compiled or not. The assembly will compile whenever all constraints are met.\");\n            public static readonly GUIContent versionDefines = EditorGUIUtility.TrTextContent(\"Version Defines\", \"Specify preprocessor symbols to define based on package, module or Unity versions.\");\n            public static readonly GUIContent resource = EditorGUIUtility.TrTextContent(\"If resource\", \"Select 'Unity' or the package or module that you want to set a define for.\");\n            public static readonly GUIContent version = EditorGUIUtility.TrTextContent(\"version is\", \"Specify the semantic version of your chosen module, package or Unity Version. You must use mathematical interval notation.\");\n            public static readonly GUIContent define = EditorGUIUtility.TrTextContent(\"set define\", \"Specify the name you want this define to have. This define is only set if the expression's condition is satisfied.\");\n            public static readonly GUIContent expressionOutcome = EditorGUIUtility.TrTextContent(\"Version expression outcome\", \"Shows the mathematical equation applied to the version number used determine if the symbol should be defined.\");\n            public static readonly GUIContent references = EditorGUIUtility.TrTextContent(\"Assembly Definition References\", \"The list of assembly files that this assembly definition should reference.\");\n            public static readonly GUIContent precompiledReferences = EditorGUIUtility.TrTextContent(\"Assembly References\", \"The list of Precompiled assemblies that this assembly definition should reference.\");\n            public static readonly GUIContent generalOptions = EditorGUIUtility.TrTextContent(\"General Options\");\n            public static readonly GUIContent allowUnsafeCode = EditorGUIUtility.TrTextContent(\"Allow 'unsafe' Code\", \"When enabled, the C# compiler for this assembly includes types or members that have the `unsafe` keyword.\");\n            public static readonly GUIContent overrideReferences = EditorGUIUtility.TrTextContent(\"Override References\", \"When enabled, you can select which specific precompiled assemblies to refer to via a drop-down list that appears. When not enabled, this assembly definition refers to all auto-referenced precompiled assemblies.\");\n            public static readonly GUIContent autoReferenced = EditorGUIUtility.TrTextContent(\"Auto Referenced\", \"When enabled, this assembly definition is automatically referenced in predefined assemblies.\");\n            public static readonly GUIContent useGUIDs = EditorGUIUtility.TrTextContent(\"Use GUIDs\", \"Use GUIDs instead of assembly names for Assembly Definition References. Allows referenced assemblies to be renamed without having to update references.\");\n            public static readonly GUIContent platforms = EditorGUIUtility.TrTextContent(\"Platforms\", \"Select which platforms include or exclude in the build that this assembly definition file is for.\");\n            public static readonly GUIContent anyPlatform = EditorGUIUtility.TrTextContent(\"Any Platform\");\n            public static readonly GUIContent includePlatforms = EditorGUIUtility.TrTextContent(\"Include Platforms\");\n            public static readonly GUIContent excludePlatforms = EditorGUIUtility.TrTextContent(\"Exclude Platforms\");\n            public static readonly GUIContent selectAll = EditorGUIUtility.TrTextContent(\"Select all\");\n            public static readonly GUIContent deselectAll = EditorGUIUtility.TrTextContent(\"Deselect all\");\n            public static readonly GUIContent loadError = EditorGUIUtility.TrTextContent(\"Load error\");\n            public static readonly GUIContent noEngineReferences = EditorGUIUtility.TrTextContent(\"No Engine References\", \"When enabled, references to UnityEngine/UnityEditor will not be added when compiling this assembly.\");\n\n            // This is used to make everything in reorderable list elements centered vertically.\n            public const int kCenterHeightOffset = 1;\n\n            public const int kValidityIconHeight = 16;\n            public const int kValidityIconWidth = 16;\n            static readonly Texture2D kValidDefineConstraint = EditorGUIUtility.FindTexture(\"Valid\");\n            static readonly Texture2D kValidDefineConstraintHighDpi = EditorGUIUtility.FindTexture(\"Valid@2x\");\n            static readonly Texture2D kInvalidDefineConstraint = EditorGUIUtility.FindTexture(\"Invalid\");\n            static readonly Texture2D kInvalidDefineConstraintHighDpi = EditorGUIUtility.FindTexture(\"Invalid@2x\");\n\n            public static Texture2D validDefineConstraint => EditorGUIUtility.pixelsPerPoint > 1 ? kValidDefineConstraintHighDpi : kValidDefineConstraint;\n            public static Texture2D invalidDefineConstraint => EditorGUIUtility.pixelsPerPoint > 1 ? kInvalidDefineConstraintHighDpi : kInvalidDefineConstraint;\n\n            static string kCompatibleTextTitle = L10n.Tr(\"Define constraints are met.\");\n            static string kIncompatibleTextTitle = L10n.Tr(\"One or more define constraints are invalid or not met.\");\n\n            public static string GetTitleTooltipFromDefineConstraintCompatibility(bool compatible)\n            {\n                return compatible ? kCompatibleTextTitle : kIncompatibleTextTitle;\n            }\n\n            static string kCompatibleTextIndividual = L10n.Tr(\"Define constraint is met.\");\n            static string kIncompatibleTextIndividual = L10n.Tr(\"Define constraint is not met.\");\n            static string kInvalidTextIndividual = L10n.Tr(\"Define constraint is invalid.\");\n\n            public static string GetIndividualTooltipFromDefineConstraintStatus(DefineConstraintsHelper.DefineConstraintStatus status)\n            {\n                switch (status)\n                {\n                    case DefineConstraintsHelper.DefineConstraintStatus.Compatible:\n                        return kCompatibleTextIndividual;\n                    case DefineConstraintsHelper.DefineConstraintStatus.Incompatible:\n                        return kIncompatibleTextIndividual;\n                    default:\n                        return kInvalidTextIndividual;\n                }\n            }\n        }\n\n        GUIStyle m_TextStyle;\n\n        [Serializable]\n        internal class DefineConstraint\n        {\n            public string name;\n        }\n\n        [Serializable]\n        internal class AssemblyDefinitionReference\n        {\n            public string name;\n            public string serializedReference;\n            public AssemblyDefinitionAsset asset;\n\n            public void Load(string reference, bool useGUID)\n            {\n                var referencePath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyReference(reference);\n                if (!string.IsNullOrEmpty(referencePath))\n                {\n                    asset = AssetDatabase.LoadAssetAtPath<AssemblyDefinitionAsset>(referencePath);\n\n                    if (useGUID)\n                    {\n                        var fileData = CustomScriptAssemblyData.FromJson(asset.text);\n                        name = fileData.name;\n                    }\n                }\n            }\n        }\n\n        [Serializable]\n        internal class PrecompiledReference\n        {\n            public string path = \"\";\n            public string fileName = \"\";\n            public string name = \"\";\n        }\n\n        class AssemblyDefinitionState : ScriptableObject\n        {\n            public string path => AssetDatabase.GetAssetPath(asset);\n\n            public string assemblyName;\n            public string rootNamespace;\n            public AssemblyDefinitionAsset asset;\n            public List<AssemblyDefinitionReference> references;\n            public List<PrecompiledReference> precompiledReferences;\n            public List<DefineConstraint> defineConstraints;\n            public List<VersionDefine> versionDefines;\n            public bool allowUnsafeCode;\n            public bool overrideReferences;\n            public bool useGUIDs;\n            public bool autoReferenced;\n            public bool compatibleWithAnyPlatform;\n            public bool[] platformCompatibility;\n            public bool noEngineReferences;\n        }\n\n        public static string UnityVersionTypeName\n        {\n            // This string must stay in sync with the native kUnityVersionTypeName in ScriptCompilationPipeline.cpp\n            get { return \"Unity\"; }\n        }\n        private readonly CachedVersionRangesFactory<SemVersion> m_SemVersionRanges = new CachedVersionRangesFactory<SemVersion>();\n        private readonly CachedVersionRangesFactory<UnityVersion> m_UnityVersionRanges = new CachedVersionRangesFactory<UnityVersion>();\n\n        ReorderableList m_ReferencesList;\n        ReorderableList m_PrecompiledReferencesList;\n        ReorderableList m_VersionDefineList;\n        ReorderableList m_DefineConstraints;\n\n        SerializedProperty m_AssemblyName;\n        SerializedProperty m_RootNamespace;\n        SerializedProperty m_AllowUnsafeCode;\n        SerializedProperty m_UseGUIDs;\n        SerializedProperty m_AutoReferenced;\n        SerializedProperty m_OverrideReferences;\n        SerializedProperty m_CompatibleWithAnyPlatform;\n        SerializedProperty m_PlatformCompatibility;\n        SerializedProperty m_NoEngineReferences;\n        private bool m_AssetIsReadonly;\n\n        Exception initializeException;\n        PrecompiledAssemblyProviderBase m_AssemblyProvider;\n\n        public override bool showImportedObject => false;\n\n        public override void OnEnable()\n        {\n            base.OnEnable();\n\n            //Ensure UIElements handles the IMGUI container with margins\n            alwaysAllowExpansion = true;\n\n            m_AssemblyName = extraDataSerializedObject.FindProperty(\"assemblyName\");\n            InitializeReorderableLists();\n            m_SemVersionRanges.Clear();\n            m_UnityVersionRanges.Clear();\n            m_RootNamespace = extraDataSerializedObject.FindProperty(\"rootNamespace\");\n            m_AllowUnsafeCode = extraDataSerializedObject.FindProperty(\"allowUnsafeCode\");\n            m_UseGUIDs = extraDataSerializedObject.FindProperty(\"useGUIDs\");\n            m_AutoReferenced = extraDataSerializedObject.FindProperty(\"autoReferenced\");\n            m_OverrideReferences = extraDataSerializedObject.FindProperty(\"overrideReferences\");\n            m_CompatibleWithAnyPlatform = extraDataSerializedObject.FindProperty(\"compatibleWithAnyPlatform\");\n            m_PlatformCompatibility = extraDataSerializedObject.FindProperty(\"platformCompatibility\");\n            m_NoEngineReferences = extraDataSerializedObject.FindProperty(\"noEngineReferences\");\n            m_AssemblyProvider = EditorCompilationInterface.Instance.PrecompiledAssemblyProvider;\n            m_AssetIsReadonly = false;\n            foreach (var assetPath in targets.OfType<AssetImporter>().Select(i => i.assetPath))\n            {\n                try\n                {\n                    using (var fs = File.Open(assetPath, FileMode.Open, FileAccess.Write)) { }\n                }\n                catch\n                {\n                    // can't open in write mode, must be readonly\n                    m_AssetIsReadonly = true;\n                }\n            }\n\n            AssemblyReloadEvents.afterAssemblyReload += AfterAssemblyReload;\n        }\n\n        public override void OnDisable()\n        {\n            base.OnDisable();\n            AssemblyReloadEvents.afterAssemblyReload -= AfterAssemblyReload;\n        }\n\n        void AfterAssemblyReload()\n        {\n            var selector = (ObjectSelector)WindowLayout.FindEditorWindowOfType(typeof(ObjectSelector));\n            if (selector != null && selector.hasFocus)\n                selector.Close();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (initializeException != null)\n            {\n                ShowLoadErrorExceptionGUI(initializeException);\n                ApplyRevertGUI();\n                return;\n            }\n\n            extraDataSerializedObject.Update();\n\n            var platforms = CompilationPipeline.GetAssemblyDefinitionPlatforms();\n            using (new EditorGUI.DisabledScope(m_AssetIsReadonly))\n            {\n                if (targets.Length > 1)\n                {\n                    if (m_AssetIsReadonly)\n                    {\n                        EditorGUILayout.LabelField(\"One of the selected assembly definition files is read-only.\");\n                    }\n                    using (new EditorGUI.DisabledScope(true))\n                    {\n                        var value = string.Join(\", \", extraDataTargets.Select(t => t.name).ToArray());\n                        EditorGUILayout.TextField(Styles.name, value, EditorStyles.textField);\n                    }\n                }\n                else\n                {\n                    if (m_AssetIsReadonly)\n                    {\n                        EditorGUILayout.LabelField(\"The selected assembly definition file is read-only.\");\n                    }\n                    EditorGUILayout.PropertyField(m_AssemblyName, Styles.name);\n                }\n\n                GUILayout.Space(6f);\n\n                // General Options\n                GUILayout.Label(Styles.generalOptions, EditorStyles.boldLabel);\n\n                EditorGUILayout.BeginVertical(GUI.skin.box);\n                EditorGUILayout.PropertyField(m_AllowUnsafeCode, Styles.allowUnsafeCode);\n                EditorGUILayout.PropertyField(m_AutoReferenced, Styles.autoReferenced);\n                EditorGUILayout.PropertyField(m_NoEngineReferences, Styles.noEngineReferences);\n                EditorGUILayout.PropertyField(m_OverrideReferences, Styles.overrideReferences);\n                EditorGUILayout.PropertyField(m_RootNamespace, Styles.rootNamespace);\n                EditorGUILayout.EndVertical();\n\n                GUILayout.Space(6f);\n\n                // ASMDEF References\n                GUILayout.Label(Styles.references, EditorStyles.boldLabel);\n\n                EditorGUILayout.BeginVertical(GUI.skin.box);\n                EditorGUI.BeginDisabled(m_ReferencesList.serializedProperty.arraySize == 0);\n                EditorGUILayout.PropertyField(m_UseGUIDs, Styles.useGUIDs);\n                EditorGUI.EndDisabled();\n                EditorGUILayout.EndVertical();\n\n                m_ReferencesList.DoLayoutList();\n\n                if (extraDataTargets.Any(data => ((AssemblyDefinitionState)data).references != null && ((AssemblyDefinitionState)data).references.Any(x => x.asset == null)))\n                {\n                    EditorGUILayout.HelpBox(\"The grayed out assembly references are missing and will not be referenced during compilation.\", MessageType.Info);\n                }\n\n                if (m_OverrideReferences.boolValue && !m_OverrideReferences.hasMultipleDifferentValues)\n                {\n                    GUILayout.Label(Styles.precompiledReferences, EditorStyles.boldLabel);\n\n                    UpdatePrecompiledReferenceListEntry();\n                    m_PrecompiledReferencesList.DoLayoutList();\n\n                    if (extraDataTargets.Any(data => ((AssemblyDefinitionState)data).precompiledReferences.Any(x => string.IsNullOrEmpty(x.path) && !string.IsNullOrEmpty(x.name))))\n                    {\n                        EditorGUILayout.HelpBox(\"The grayed out assembly references are missing and will not be referenced during compilation.\", MessageType.Info);\n                    }\n                }\n\n                GUILayout.Space(6f);\n\n                // Platforms\n                GUILayout.Label(Styles.platforms, EditorStyles.boldLabel);\n                EditorGUILayout.BeginVertical(GUI.skin.box);\n\n                using (var change = new EditorGUI.ChangeCheckScope())\n                {\n                    EditorGUILayout.PropertyField(m_CompatibleWithAnyPlatform, Styles.anyPlatform);\n                    if (change.changed)\n                    {\n                        // Invert state include/exclude compatibility of states that have the opposite compatibility,\n                        // so all states are either include or exclude.\n                        var compatibleWithAny = m_CompatibleWithAnyPlatform.boolValue;\n                        var needToSwap = extraDataTargets.Cast<AssemblyDefinitionState>().Where(p => p.compatibleWithAnyPlatform != compatibleWithAny).ToList();\n                        extraDataSerializedObject.ApplyModifiedProperties();\n                        foreach (var state in needToSwap)\n                        {\n                            InversePlatformCompatibility(state);\n                        }\n\n                        extraDataSerializedObject.Update();\n                    }\n                }\n\n                if (!m_CompatibleWithAnyPlatform.hasMultipleDifferentValues)\n                {\n                    GUILayout.Label(m_CompatibleWithAnyPlatform.boolValue ? Styles.excludePlatforms : Styles.includePlatforms, EditorStyles.boldLabel);\n\n                    for (int i = 0; i < platforms.Length; ++i)\n                    {\n                        SerializedProperty property;\n                        if (i >= m_PlatformCompatibility.arraySize)\n                        {\n                            m_PlatformCompatibility.arraySize++;\n                            property = m_PlatformCompatibility.GetArrayElementAtIndex(i);\n                            property.boolValue = false;\n                        }\n                        else\n                        {\n                            property = m_PlatformCompatibility.GetArrayElementAtIndex(i);\n                        }\n\n                        EditorGUILayout.PropertyField(property, new GUIContent(platforms[i].DisplayName));\n                    }\n\n                    EditorGUILayout.Space();\n\n                    GUILayout.BeginHorizontal();\n\n                    if (GUILayout.Button(Styles.selectAll))\n                    {\n                        var prop = m_PlatformCompatibility.GetArrayElementAtIndex(0);\n                        var end = m_PlatformCompatibility.GetEndProperty();\n                        do\n                        {\n                            prop.boolValue = true;\n                        }\n                        while (prop.Next(false) && !SerializedProperty.EqualContents(prop, end));\n                    }\n\n                    if (GUILayout.Button(Styles.deselectAll))\n                    {\n                        var prop = m_PlatformCompatibility.GetArrayElementAtIndex(0);\n                        var end = m_PlatformCompatibility.GetEndProperty();\n                        do\n                        {\n                            prop.boolValue = false;\n                        }\n                        while (prop.Next(false) && !SerializedProperty.EqualContents(prop, end));\n                    }\n\n                    GUILayout.FlexibleSpace();\n                    GUILayout.EndHorizontal();\n                }\n                EditorGUILayout.EndVertical();\n\n                GUILayout.Space(6f);\n\n                // Define Constraints\n                EditorGUILayout.BeginHorizontal();\n                GUILayout.Label(Styles.defineConstraints, EditorStyles.boldLabel);\n                GUILayout.FlexibleSpace();\n                EditorGUILayout.EndHorizontal();\n\n                if (m_DefineConstraints.serializedProperty.arraySize > 0)\n                {\n                    var defineConstraintsCompatible = true;\n\n                    var defines = GetDefines();\n\n                    if (defines != null)\n                    {\n                        for (var i = 0; i < m_DefineConstraints.serializedProperty.arraySize && defineConstraintsCompatible; ++i)\n                        {\n                            var defineConstraint = m_DefineConstraints.serializedProperty.GetArrayElementAtIndex(i).FindPropertyRelative(\"name\").stringValue;\n\n                            if (DefineConstraintsHelper.GetDefineConstraintCompatibility(defines, defineConstraint) != DefineConstraintsHelper.DefineConstraintStatus.Compatible)\n                            {\n                                defineConstraintsCompatible = false;\n                            }\n                        }\n\n                        var constraintValidityRect = new Rect(GUILayoutUtility.GetLastRect());\n                        constraintValidityRect.x = constraintValidityRect.width - Styles.kValidityIconWidth / 4;\n                        var image = defineConstraintsCompatible ? Styles.validDefineConstraint : Styles.invalidDefineConstraint;\n                        var tooltip = Styles.GetTitleTooltipFromDefineConstraintCompatibility(defineConstraintsCompatible);\n                        var content = new GUIContent(image, tooltip);\n\n                        constraintValidityRect.width = Styles.kValidityIconWidth;\n                        constraintValidityRect.height = Styles.kValidityIconHeight;\n                        EditorGUI.LabelField(constraintValidityRect, content);\n                    }\n                }\n\n                m_DefineConstraints.DoLayoutList();\n\n                GUILayout.Space(6f);\n\n                // Version Defines\n                EditorGUILayout.BeginVertical(GUI.skin.box);\n                GUILayout.Label(Styles.versionDefines, EditorStyles.boldLabel);\n                m_VersionDefineList.DoLayoutList();\n                EditorGUILayout.EndVertical();\n            }\n\n            extraDataSerializedObject.ApplyModifiedProperties();\n\n            ApplyRevertGUI();\n        }\n\n        protected override void Apply()\n        {\n            base.Apply();\n\n            // Do not write back to the asset if no asset can be found.\n            if (targets != null)\n                SaveAndUpdateAssemblyDefinitionStates(extraDataTargets.Cast<AssemblyDefinitionState>().ToArray());\n        }\n\n        static void InversePlatformCompatibility(AssemblyDefinitionState state)\n        {\n            var platforms = CompilationPipeline.GetAssemblyDefinitionPlatforms();\n            for (int i = 0; i < platforms.Length; ++i)\n                state.platformCompatibility[i] = !state.platformCompatibility[i];\n        }\n\n        void ShowLoadErrorExceptionGUI(Exception e)\n        {\n            if (m_TextStyle == null)\n                m_TextStyle = \"ScriptText\";\n\n            GUILayout.Label(Styles.loadError, EditorStyles.boldLabel);\n            Rect rect = GUILayoutUtility.GetRect(EditorGUIUtility.TempContent(e.Message), m_TextStyle);\n            EditorGUI.HelpBox(rect, e.Message, MessageType.Error);\n        }\n\n        protected override Type extraDataType => typeof(AssemblyDefinitionState);\n\n        protected override void InitializeExtraDataInstance(Object extraTarget, int targetIndex)\n        {\n            try\n            {\n                LoadAssemblyDefinitionState((AssemblyDefinitionState)extraTarget, ((AssetImporter)targets[targetIndex]).assetPath);\n                initializeException = null;\n            }\n            catch (Exception e)\n            {\n                initializeException = e;\n            }\n        }\n\n        void InitializeReorderableLists()\n        {\n            // Disable reordering for multi-editing for asmdefs\n            bool enableReordering = targets.Length == 1;\n\n            m_ReferencesList = new ReorderableList(extraDataSerializedObject, extraDataSerializedObject.FindProperty(\"references\"), enableReordering, false, true, true);\n            m_ReferencesList.drawElementCallback = DrawReferenceListElement;\n            m_ReferencesList.onAddCallback += AddReferenceListElement;\n\n            m_ReferencesList.elementHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;\n            m_ReferencesList.headerHeight = 3;\n\n            m_DefineConstraints = new ReorderableList(extraDataSerializedObject, extraDataSerializedObject.FindProperty(\"defineConstraints\"), enableReordering, false, true, true);\n            m_DefineConstraints.drawElementCallback = DrawDefineConstraintListElement;\n\n            m_DefineConstraints.elementHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;\n            m_DefineConstraints.headerHeight = 3;\n\n            m_PrecompiledReferencesList = new ReorderableList(extraDataSerializedObject, extraDataSerializedObject.FindProperty(\"precompiledReferences\"), enableReordering, false, true, true);\n            m_PrecompiledReferencesList.drawElementCallback = DrawPrecompiledReferenceListElement;\n            m_PrecompiledReferencesList.onAddCallback = AddPrecompiledReferenceListElement;\n            m_PrecompiledReferencesList.elementHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;\n            m_PrecompiledReferencesList.headerHeight = 3;\n\n            m_VersionDefineList = new ReorderableList(extraDataSerializedObject, extraDataSerializedObject.FindProperty(\"versionDefines\"), enableReordering, false, true, true);\n            m_VersionDefineList.drawElementCallback = DrawVersionDefineListElement;\n            m_VersionDefineList.elementHeight = EditorGUIUtility.singleLineHeight * 4 + EditorGUIUtility.standardVerticalSpacing;\n            m_VersionDefineList.headerHeight = 3;\n        }\n\n        private void DrawDefineConstraintListElement(Rect rect, int index, bool isactive, bool isfocused)\n        {\n            var list = m_DefineConstraints.serializedProperty;\n            var defineConstraint = list.GetArrayElementAtIndex(index).FindPropertyRelative(\"name\");\n\n            rect.height -= EditorGUIUtility.standardVerticalSpacing;\n\n            var textFieldRect = new Rect(rect.x, rect.y + Styles.kCenterHeightOffset, rect.width - ReorderableList.Defaults.dragHandleWidth, rect.height);\n\n            string noValue = L10n.Tr(\"(Missing)\");\n\n            var label = string.IsNullOrEmpty(defineConstraint.stringValue) ? noValue : defineConstraint.stringValue;\n            bool mixed = defineConstraint.hasMultipleDifferentValues;\n            EditorGUI.showMixedValue = mixed;\n            var textFieldValue = EditorGUI.TextField(textFieldRect, mixed ? L10n.Tr(\"(Multiple Values)\") : label);\n            EditorGUI.showMixedValue = false;\n\n            var defines = GetDefines();\n\n            if (defines != null)\n            {\n                var status = DefineConstraintsHelper.GetDefineConstraintCompatibility(defines, defineConstraint.stringValue);\n                var image = status == DefineConstraintsHelper.DefineConstraintStatus.Compatible ? Styles.validDefineConstraint : Styles.invalidDefineConstraint;\n\n                var content = new GUIContent(image, Styles.GetIndividualTooltipFromDefineConstraintStatus(status));\n\n                var constraintValidityRect = new Rect(rect.width + ReorderableList.Defaults.dragHandleWidth + Styles.kValidityIconWidth / 4, rect.y + Styles.kCenterHeightOffset, Styles.kValidityIconWidth, Styles.kValidityIconHeight);\n                EditorGUI.LabelField(constraintValidityRect, content);\n            }\n\n            if (!string.IsNullOrEmpty(textFieldValue) && textFieldValue != noValue)\n            {\n                defineConstraint.stringValue = textFieldValue;\n            }\n        }\n\n        private string[] GetDefines()\n        {\n            var responseFileDefinesFromAssemblyName = CompilationPipeline.GetResponseFileDefinesFromAssemblyName(m_AssemblyName.stringValue) ?? new string[0];\n            var definesFromAssemblyName = CompilationPipeline.GetDefinesFromAssemblyName(m_AssemblyName.stringValue) ?? new string[0];\n            var defines = definesFromAssemblyName.Concat(responseFileDefinesFromAssemblyName);\n\n            return defines.Distinct().ToArray();\n        }\n\n        private List<VersionMetaData> BuildListOfVersionDefineResourceOptions(string preselectedResourceName)\n        {\n            var versionDefineResourceOptions = EditorCompilationInterface.Instance.GetVersionMetaDatas().Values.ToList();\n\n            if (!string.IsNullOrEmpty(preselectedResourceName) && !versionDefineResourceOptions.Where(x => x.Name == preselectedResourceName).Any())\n            {\n                versionDefineResourceOptions.Add(new VersionMetaData(preselectedResourceName));\n            }\n\n            versionDefineResourceOptions.Insert(0, new VersionMetaData(\"Select...\"));\n\n            // Make sure Unity is always second option (index 1).\n            for (int i = versionDefineResourceOptions.Count - 1; i >= 2; --i)\n            {\n                if (versionDefineResourceOptions[i].Name == UnityVersionTypeName)\n                {\n                    var tmp = versionDefineResourceOptions[i];\n                    versionDefineResourceOptions.RemoveAt(i);\n                    versionDefineResourceOptions.Insert(1, tmp);\n                    break;\n                }\n            }\n\n            return versionDefineResourceOptions;\n        }\n\n        private void DrawVersionDefineListElement(Rect rect, int index, bool isactive, bool isfocused)\n        {\n            var list = m_VersionDefineList.serializedProperty;\n            var versionDefineProp = list.GetArrayElementAtIndex(index);\n            var nameProp = versionDefineProp.FindPropertyRelative(\"name\");\n            var expressionProp = versionDefineProp.FindPropertyRelative(\"expression\");\n            var defineProp = versionDefineProp.FindPropertyRelative(\"define\");\n\n            rect.height -= EditorGUIUtility.standardVerticalSpacing;\n\n            var versionedResourceOptions = BuildListOfVersionDefineResourceOptions(nameProp.stringValue);\n\n            int indexOfSelected = 0;\n            if (!string.IsNullOrEmpty(nameProp.stringValue))\n            {\n                indexOfSelected = versionedResourceOptions.IndexOf(versionedResourceOptions.Where(x => x.Name == nameProp.stringValue).First());\n            }\n\n            bool mixed = versionDefineProp.hasMultipleDifferentValues;\n            EditorGUI.showMixedValue = mixed;\n\n            string[] versionedResourceOptionsStrings = new string[versionedResourceOptions.Count];\n\n            for (int i = 0; i < versionedResourceOptions.Count; ++i)\n            {\n                if (string.IsNullOrEmpty(versionedResourceOptions[i].Version))\n                {\n                    versionedResourceOptionsStrings[i] = versionedResourceOptions[i].Name;\n                }\n                else\n                {\n                    versionedResourceOptionsStrings[i] = $\"{versionedResourceOptions[i].Name} ({versionedResourceOptions[i].Version})\";\n                }\n            }\n\n            var elementRect = new Rect(rect);\n            elementRect.height = EditorGUIUtility.singleLineHeight;\n            elementRect.y += 1;\n\n            var prefixLabel = EditorGUI.PrefixLabel(elementRect, Styles.resource);\n\n            int popupIndex = EditorGUI.AdvancedPopup(prefixLabel, indexOfSelected, versionedResourceOptionsStrings);\n\n            nameProp.stringValue = versionedResourceOptions[popupIndex].Name;\n\n            elementRect.y += EditorGUIUtility.singleLineHeight;\n            expressionProp.stringValue = EditorGUI.TextField(elementRect, Styles.version, expressionProp.stringValue);\n\n            elementRect.y += EditorGUIUtility.singleLineHeight;\n            defineProp.stringValue = EditorGUI.TextField(elementRect, Styles.define, defineProp.stringValue);\n\n            string expressionOutcome = null;\n            if (!string.IsNullOrEmpty(expressionProp.stringValue))\n            {\n                try\n                {\n                    if (!string.IsNullOrEmpty(nameProp.stringValue) &&\n                        nameProp.stringValue.Equals(UnityVersionTypeName, StringComparison.Ordinal))\n                    {\n                        var expression = m_UnityVersionRanges.GetExpression(expressionProp.stringValue);\n                        expressionOutcome = expression.Expression.AppliedRule;\n                    }\n                    else\n                    {\n                        var expression = m_SemVersionRanges.GetExpression(expressionProp.stringValue);\n                        expressionOutcome = expression.Expression.AppliedRule;\n                    }\n                }\n                catch (Exception)\n                {\n                    expressionOutcome = \"Invalid\";\n                }\n            }\n\n            elementRect.y += EditorGUIUtility.singleLineHeight;\n            EditorGUI.LabelField(elementRect, Styles.expressionOutcome, GUIContent.Temp(expressionOutcome));\n\n            EditorGUI.showMixedValue = false;\n        }\n\n        List<string> m_PrecompileReferenceListEntry;\n\n        private void UpdatePrecompiledReferenceListEntry()\n        {\n            var precompiledAssemblyNames = CompilationPipeline.GetPrecompiledAssemblyNames().ToList();\n            var currentReferencesProp = extraDataSerializedObject.FindProperty(\"precompiledReferences\");\n            if (currentReferencesProp.arraySize > 0)\n            {\n                var prop = currentReferencesProp.GetArrayElementAtIndex(0);\n                var end = currentReferencesProp.GetEndProperty();\n                do\n                {\n                    var fileName = prop.FindPropertyRelative(\"fileName\").stringValue;\n                    if (!string.IsNullOrEmpty(fileName))\n                        precompiledAssemblyNames.Remove(fileName);\n                }\n                while (prop.Next(false) && !SerializedProperty.EqualContents(prop, end));\n            }\n\n            m_PrecompileReferenceListEntry = precompiledAssemblyNames\n                .OrderBy(x => x).ToList();\n        }\n\n        private void DrawPrecompiledReferenceListElement(Rect rect, int index, bool isactive, bool isfocused)\n        {\n            var precompiledReference = m_PrecompiledReferencesList.serializedProperty.GetArrayElementAtIndex(index);\n            var nameProp = precompiledReference.FindPropertyRelative(\"name\");\n            var pathProp = precompiledReference.FindPropertyRelative(\"path\");\n            var fileNameProp = precompiledReference.FindPropertyRelative(\"fileName\");\n\n            rect.height -= EditorGUIUtility.standardVerticalSpacing;\n            GUIContent label = GUIContent.Temp(nameProp.stringValue);\n\n            bool mixed = nameProp.hasMultipleDifferentValues;\n            EditorGUI.showMixedValue = mixed;\n\n            bool hasValue = !string.IsNullOrEmpty(pathProp.stringValue);\n            if (!hasValue)\n            {\n                m_PrecompileReferenceListEntry.Insert(0, L10n.Tr(\"None\"));\n\n                if (m_PrecompileReferenceListEntry.Count == 1)\n                {\n                    label = EditorGUIUtility.TrTempContent(\"No possible references\");\n                }\n                else\n                {\n                    label = EditorGUIUtility.TrTempContent(\"None\");\n                }\n            }\n            else\n            {\n                m_PrecompileReferenceListEntry.Insert(0, fileNameProp.stringValue);\n            }\n\n            int currentlySelectedIndex = 0;\n            EditorGUI.BeginDisabled(!hasValue && !string.IsNullOrEmpty(nameProp.stringValue));\n            int selectedIndex = EditorGUI.Popup(rect, label, currentlySelectedIndex, m_PrecompileReferenceListEntry.ToArray());\n            EditorGUI.EndDisabled();\n\n\n            if (selectedIndex > 0)\n            {\n                var selectedAssemblyName = m_PrecompileReferenceListEntry[selectedIndex];\n                var assembly = m_AssemblyProvider.GetPrecompiledAssemblies(\n                    EditorScriptCompilationOptions.BuildingForEditor | EditorScriptCompilationOptions.BuildingWithAsserts,\n                    EditorUserBuildSettings.activeBuildTarget)\n                    .First(x => AssetPath.GetFileName(x.Path) == selectedAssemblyName);\n                nameProp.stringValue = selectedAssemblyName;\n                pathProp.stringValue = assembly.Path;\n                fileNameProp.stringValue = AssetPath.GetFileName(assembly.Path);\n            }\n\n            m_PrecompileReferenceListEntry.RemoveAt(0);\n\n            EditorGUI.showMixedValue = false;\n        }\n\n        [MenuItem(\"CONTEXT/AssemblyDefinitionImporter/Reset\", secondaryPriority = 8)]\n        internal static void ContextReset(MenuCommand command)\n        {\n            var templatePath = AssetsMenuUtility.GetScriptTemplatePath(ScriptTemplate.AsmDef_NewAssembly);\n            Debug.Assert(!string.IsNullOrEmpty(templatePath));\n\n            var templateContent = File.ReadAllText(templatePath);\n            var importer = command.context as AssemblyDefinitionImporter;\n\n            if (importer != null)\n            {\n                var assetPath = importer.assetPath;\n                templateContent = ProjectWindowUtil.PreprocessScriptAssetTemplate(assetPath, templateContent);\n                File.WriteAllText(assetPath, templateContent);\n                AssetDatabase.ImportAsset(assetPath);\n            }\n        }\n\n        static void AddPrecompiledReferenceListElement(ReorderableList list)\n        {\n            list.serializedProperty.arraySize += 1;\n            var newProp = list.serializedProperty.GetArrayElementAtIndex(list.serializedProperty.arraySize - 1);\n            newProp.FindPropertyRelative(\"name\").stringValue = string.Empty;\n            newProp.FindPropertyRelative(\"path\").stringValue = string.Empty;\n            newProp.FindPropertyRelative(\"fileName\").stringValue = string.Empty;\n        }\n\n        static void LoadAssemblyDefinitionState(AssemblyDefinitionState state, string path)\n        {\n            var asset = AssetDatabase.LoadAssetAtPath<AssemblyDefinitionAsset>(path);\n            if (asset == null)\n                return;\n\n            var data = CustomScriptAssemblyData.FromJsonNoFieldValidation(asset.text);\n\n            if (data == null)\n                return;\n\n            try\n            {\n                data.ValidateFields();\n            }\n            catch (Exception e)\n            {\n                Debug.LogException(e, asset);\n            }\n\n            state.asset = asset;\n            state.assemblyName = data.name;\n            state.rootNamespace = data.rootNamespace;\n            state.references = new List<AssemblyDefinitionReference>();\n            state.precompiledReferences = new List<PrecompiledReference>();\n            state.defineConstraints = new List<DefineConstraint>();\n            state.versionDefines = new List<VersionDefine>();\n            state.autoReferenced = data.autoReferenced;\n            state.allowUnsafeCode = data.allowUnsafeCode;\n            state.overrideReferences = data.overrideReferences;\n            state.noEngineReferences = data.noEngineReferences;\n\n            // If the .asmdef has no references (true for newly created .asmdef), then use GUIDs.\n            // Otherwise do not use GUIDs. This value might be changed below if any reference is a GUID.\n            state.useGUIDs = (data.references == null || data.references.Length == 0);\n\n            if (data.versionDefines != null)\n            {\n                foreach (var versionDefine in data.versionDefines)\n                {\n                    state.versionDefines.Add(versionDefine);\n                }\n            }\n\n            if (data.defineConstraints != null)\n            {\n                foreach (var defineConstraint in data.defineConstraints)\n                {\n                    state.defineConstraints.Add(new DefineConstraint\n                    {\n                        name = defineConstraint,\n                    });\n                }\n            }\n\n            if (data.references != null)\n            {\n                foreach (var reference in data.references)\n                {\n                    try\n                    {\n                        var assemblyDefinitionFile = new AssemblyDefinitionReference\n                        {\n                            name = reference,\n                            serializedReference = reference\n                        };\n\n                        // If any references is a GUID, use GUIDs.\n                        var isGuid = CompilationPipeline.GetAssemblyDefinitionReferenceType(reference) == AssemblyDefinitionReferenceType.Guid;\n                        if (isGuid)\n                        {\n                            state.useGUIDs = true;\n                        }\n\n                        assemblyDefinitionFile.Load(reference, isGuid);\n                        state.references.Add(assemblyDefinitionFile);\n                    }\n                    catch (AssemblyDefinitionException e)\n                    {\n                        Debug.LogException(e, asset);\n                        state.references.Add(new AssemblyDefinitionReference());\n                    }\n                }\n            }\n\n            var nameToPrecompiledReference = EditorCompilationInterface.Instance.PrecompiledAssemblyProvider\n                .GetPrecompiledAssemblies(\n                    EditorScriptCompilationOptions.BuildingForEditor | EditorScriptCompilationOptions.BuildingWithAsserts,\n                    EditorUserBuildSettings.activeBuildTarget)\n                .Where(x => (x.Flags & AssemblyFlags.UserAssembly) == AssemblyFlags.UserAssembly)\n                .Distinct()\n                .ToDictionary(x => AssetPath.GetFileName(x.Path), x => x);\n            foreach (var precompiledReferenceName in data.precompiledReferences ?? Enumerable.Empty<String>())\n            {\n                try\n                {\n                    var precompiledReference = new PrecompiledReference\n                    {\n                        name = precompiledReferenceName,\n                    };\n\n                    PrecompiledAssembly assembly;\n                    if (nameToPrecompiledReference.TryGetValue(precompiledReferenceName, out assembly))\n                    {\n                        precompiledReference.path = assembly.Path;\n                        precompiledReference.fileName = AssetPath.GetFileName(assembly.Path);\n                    }\n\n                    state.precompiledReferences.Add(precompiledReference);\n                }\n                catch (AssemblyDefinitionException e)\n                {\n                    Debug.LogException(e, asset);\n                    state.precompiledReferences.Add(new PrecompiledReference());\n                }\n            }\n\n            var platforms = CompilationPipeline.GetAssemblyDefinitionPlatforms();\n            state.platformCompatibility = new bool[platforms.Length];\n\n            state.compatibleWithAnyPlatform = true;\n            string[] dataPlatforms = null;\n\n            if (data.includePlatforms != null && data.includePlatforms.Length > 0)\n            {\n                state.compatibleWithAnyPlatform = false;\n                dataPlatforms = data.includePlatforms;\n            }\n            else if (data.excludePlatforms != null && data.excludePlatforms.Length > 0)\n            {\n                state.compatibleWithAnyPlatform = true;\n                dataPlatforms = data.excludePlatforms;\n            }\n\n            if (dataPlatforms != null)\n                foreach (var platform in dataPlatforms)\n                {\n                    var platformIndex = GetPlatformIndex(platforms, platform);\n                    state.platformCompatibility[platformIndex] = true;\n                }\n        }\n\n        static void SaveAndUpdateAssemblyDefinitionStates(AssemblyDefinitionState[] states)\n        {\n            foreach (var state in states)\n            {\n                SaveAssemblyDefinitionState(state);\n            }\n        }\n\n        static void SaveAssemblyDefinitionState(AssemblyDefinitionState state)\n        {\n            var references = state.references;\n            var platforms = CompilationPipeline.GetAssemblyDefinitionPlatforms();\n\n            CustomScriptAssemblyData data = new CustomScriptAssemblyData();\n\n            data.name = state.assemblyName;\n            data.rootNamespace = state.rootNamespace;\n\n            if (state.useGUIDs)\n            {\n                data.references = references.Select(r =>\n                {\n                    var guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(r.asset));\n\n                    if (string.IsNullOrEmpty(guid))\n                        return r.serializedReference;\n\n                    return CompilationPipeline.GUIDToAssemblyDefinitionReferenceGUID(guid);\n                }).ToArray();\n            }\n            else\n            {\n                data.references = references.Select(r => r.name).ToArray();\n            }\n\n            data.defineConstraints = state.defineConstraints\n                .Where(x => !string.IsNullOrEmpty(x.name))\n                .Select(r => r.name)\n                .ToArray();\n\n            data.versionDefines = state.versionDefines.ToArray();\n            data.autoReferenced = state.autoReferenced;\n            data.overrideReferences = state.overrideReferences;\n\n            data.precompiledReferences = state.precompiledReferences\n                .Select(r => r.name).ToArray();\n\n            data.allowUnsafeCode = state.allowUnsafeCode;\n            data.noEngineReferences = state.noEngineReferences;\n\n            List<string> dataPlatforms = new List<string>();\n\n            for (int i = 0; i < platforms.Length; ++i)\n            {\n                if (state.platformCompatibility[i])\n                    dataPlatforms.Add(platforms[i].Name);\n            }\n\n            if (dataPlatforms.Any())\n            {\n                if (state.compatibleWithAnyPlatform)\n                    data.excludePlatforms = dataPlatforms.ToArray();\n                else\n                    data.includePlatforms = dataPlatforms.ToArray();\n            }\n\n            var json = CustomScriptAssemblyData.ToJson(data);\n            File.WriteAllText(state.path, json);\n\n            AssetDatabase.ImportAsset(state.path);\n        }\n\n        static int GetPlatformIndex(AssemblyDefinitionPlatform[] platforms, string name)\n        {\n            for (int i = 0; i < platforms.Length; ++i)\n            {\n                if (string.Equals(platforms[i].Name, name, System.StringComparison.InvariantCultureIgnoreCase))\n                    return i;\n            }\n\n            throw new System.ArgumentException(string.Format(\"Unknown platform '{0}'\", name), name);\n        }\n\n        void DrawReferenceListElement(Rect rect, int index, bool selected, bool focused)\n        {\n            var assemblyDefinitionFile = m_ReferencesList.serializedProperty.GetArrayElementAtIndex(index);\n            var nameProp = assemblyDefinitionFile.FindPropertyRelative(\"name\");\n            var assetProp = assemblyDefinitionFile.FindPropertyRelative(\"asset\");\n\n            rect.height -= EditorGUIUtility.standardVerticalSpacing;\n            var label = string.IsNullOrEmpty(nameProp.stringValue) ? L10n.Tr(\"(Missing Reference)\") : nameProp.stringValue;\n            using (var change = new EditorGUI.ChangeCheckScope())\n            {\n                EditorGUI.showMixedValue = assetProp.hasMultipleDifferentValues;\n                EditorGUI.BeginDisabled(!string.IsNullOrEmpty(nameProp.stringValue) && assetProp.objectReferenceValue == null);\n                var obj = EditorGUI.ObjectField(rect, EditorGUI.showMixedValue ? GUIContent.Temp(\"(Multiple Values)\") : GUIContent.Temp(label), assetProp.objectReferenceValue, typeof(AssemblyDefinitionAsset), false);\n                EditorGUI.showMixedValue = false;\n                EditorGUI.EndDisabled();\n\n                if (change.changed && obj != null)\n                {\n                    assetProp.objectReferenceValue = obj;\n                    var data = CustomScriptAssemblyData.FromJson(((AssemblyDefinitionAsset)assetProp.objectReferenceValue).text);\n                    nameProp.stringValue = data.name;\n                }\n                else if (change.changed && obj == null)\n                {\n                    assetProp.objectReferenceValue = obj;\n                    nameProp.stringValue = \"\";\n                }\n            }\n        }\n\n        void AddReferenceListElement(ReorderableList list)\n        {\n            list.serializedProperty.arraySize += 1;\n            var newProp = list.serializedProperty.GetArrayElementAtIndex(list.serializedProperty.arraySize - 1);\n            newProp.FindPropertyRelative(\"name\").stringValue = string.Empty;\n            newProp.FindPropertyRelative(\"asset\").objectReferenceValue = null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AssemblyDefinitionReferenceImporterInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor.Compilation;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing UnityEditor.AssetImporters;\nusing UnityEditor.Scripting.ScriptCompilation;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AssemblyDefinitionReferenceImporter))]\n    [CanEditMultipleObjects]\n    internal class AssemblyDefinitionReferenceImporterInspector : AssetImporterEditor\n    {\n        internal class Styles\n        {\n            public static readonly GUIContent assemblyDefinition = EditorGUIUtility.TrTextContent(\"Assembly Definition\");\n            public static readonly GUIContent loadError = EditorGUIUtility.TrTextContent(\"Load error\");\n            public static readonly GUIContent useGUID = EditorGUIUtility.TrTextContent(\"Use GUID\", \"Use the Assembly Definition asset GUID instead of name for referencing. Allows the referenced assembly to be renamed without having to update references.\");\n        }\n\n        GUIStyle m_TextStyle;\n\n        class AssemblyDefinitionReferenceState : ScriptableObject\n        {\n            public string path\n            {\n                get { return AssetDatabase.GetAssetPath(asset); }\n            }\n\n            public AssemblyDefinitionReferenceAsset asset;\n            public AssemblyDefinitionImporterInspector.AssemblyDefinitionReference reference;\n            public bool useGUIDs;\n        }\n\n        SerializedProperty m_Reference;\n        SerializedProperty m_ReferenceName;\n        SerializedProperty m_ReferenceAsset;\n        SerializedProperty m_UseGUIDs;\n\n        Exception extraDataInitializeException;\n\n        public override bool showImportedObject { get { return false; } }\n\n        public override void OnEnable()\n        {\n            base.OnEnable();\n\n            //Ensure UIElements handles the IMGUI container with margins\n            alwaysAllowExpansion = true;\n\n            m_Reference = extraDataSerializedObject.FindProperty(\"reference\");\n            m_ReferenceName = m_Reference.FindPropertyRelative(\"name\");\n            m_ReferenceAsset = m_Reference.FindPropertyRelative(\"asset\");\n            m_UseGUIDs = extraDataSerializedObject.FindProperty(\"useGUIDs\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (extraDataInitializeException != null)\n            {\n                ShowLoadErrorExceptionGUI(extraDataInitializeException);\n                ApplyRevertGUI();\n                return;\n            }\n\n            extraDataSerializedObject.Update();\n            EditorGUI.BeginDisabled(m_ReferenceAsset.objectReferenceValue == null);\n            EditorGUILayout.PropertyField(m_UseGUIDs, Styles.useGUID);\n            EditorGUI.EndDisabled();\n\n            EditorGUI.BeginChangeCheck();\n            var obj = EditorGUILayout.ObjectField(Styles.assemblyDefinition, m_ReferenceAsset.objectReferenceValue, typeof(AssemblyDefinitionAsset), false);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_ReferenceAsset.objectReferenceValue = obj;\n                if (m_ReferenceAsset.objectReferenceValue != null)\n                {\n                    var data = CustomScriptAssemblyData.FromJson(((AssemblyDefinitionAsset)obj).text);\n                    m_ReferenceName.stringValue = data.name;\n                }\n                else\n                {\n                    m_ReferenceName.stringValue = string.Empty;\n                }\n            }\n\n            extraDataSerializedObject.ApplyModifiedProperties();\n\n            ApplyRevertGUI();\n        }\n\n        protected override void Apply()\n        {\n            base.Apply();\n            SaveAndUpdateAssemblyDefinitionReferenceStates(extraDataTargets.Cast<AssemblyDefinitionReferenceState>().ToArray());\n        }\n\n        void ShowLoadErrorExceptionGUI(Exception e)\n        {\n            if (m_TextStyle == null)\n                m_TextStyle = \"ScriptText\";\n\n            GUILayout.Label(Styles.loadError, EditorStyles.boldLabel);\n            Rect rect = GUILayoutUtility.GetRect(EditorGUIUtility.TempContent(e.Message), m_TextStyle);\n            EditorGUI.HelpBox(rect, e.Message, MessageType.Error);\n        }\n\n        protected override Type extraDataType => typeof(AssemblyDefinitionReferenceState);\n\n        protected override void InitializeExtraDataInstance(UnityEngine.Object extraData, int targetIndex)\n        {\n            try\n            {\n                LoadAssemblyDefinitionReferenceState((AssemblyDefinitionReferenceState)extraData, ((AssetImporter)targets[targetIndex]).assetPath);\n                extraDataInitializeException = null;\n            }\n            catch (Exception e)\n            {\n                extraDataInitializeException = e;\n            }\n        }\n\n        [MenuItem(\"CONTEXT/AssemblyDefinitionReferenceImporter/Reset\", secondaryPriority = 9)]\n        internal static void ContextReset(MenuCommand command)\n        {\n            var templatePath = AssetsMenuUtility.GetScriptTemplatePath(ScriptTemplate.AsmRef_NewAssemblyReference);\n            Debug.Assert(!string.IsNullOrEmpty(templatePath));\n\n            var templateContent = File.ReadAllText(templatePath);\n            var importer = command.context as AssemblyDefinitionReferenceImporter;\n\n            if (importer != null)\n            {\n                var assetPath = importer.assetPath;\n                templateContent = ProjectWindowUtil.PreprocessScriptAssetTemplate(assetPath, templateContent);\n                File.WriteAllText(assetPath, templateContent);\n                AssetDatabase.ImportAsset(assetPath);\n            }\n        }\n\n        static void LoadAssemblyDefinitionReferenceState(AssemblyDefinitionReferenceState state, string path)\n        {\n            var asset = AssetDatabase.LoadAssetAtPath<AssemblyDefinitionReferenceAsset>(path);\n            if (asset == null)\n                return;\n\n            var data = CustomScriptAssemblyReferenceData.FromJson(asset.text);\n            if (data == null)\n                return;\n\n            state.asset = asset;\n            state.useGUIDs = string.IsNullOrEmpty(data.reference) || CompilationPipeline.GetAssemblyDefinitionReferenceType(data.reference) == AssemblyDefinitionReferenceType.Guid;\n            state.reference = new AssemblyDefinitionImporterInspector.AssemblyDefinitionReference { name = data.reference, serializedReference = data.reference };\n            state.reference.Load(data.reference, state.useGUIDs);\n        }\n\n        static void SaveAndUpdateAssemblyDefinitionReferenceStates(AssemblyDefinitionReferenceState[] states)\n        {\n            foreach (var state in states)\n            {\n                SaveAndUpdateAssemblyDefinitionReferenceState(state);\n            }\n        }\n\n        static void SaveAndUpdateAssemblyDefinitionReferenceState(AssemblyDefinitionReferenceState state)\n        {\n            CustomScriptAssemblyReferenceData data = new CustomScriptAssemblyReferenceData();\n            if (state.asset != null)\n            {\n                data.reference = state.useGUIDs ? CompilationPipeline.GUIDToAssemblyDefinitionReferenceGUID(AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(state.reference.asset))) : state.reference.name;\n            }\n\n            var json = CustomScriptAssemblyReferenceData.ToJson(data);\n            File.WriteAllText(state.path, json);\n            AssetDatabase.ImportAsset(state.path);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AssetBundleNameGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing System.Text.RegularExpressions;\nusing System.Linq;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class AssetBundleNameGUI\n    {\n        static private readonly GUIContent kAssetBundleName = EditorGUIUtility.TrTextContent(\"AssetBundle\");\n        static private readonly int kAssetBundleNameFieldIdHash = \"AssetBundleNameFieldHash\".GetHashCode();\n\n        static private readonly int kAssetBundleVariantFieldIdHash = \"AssetBundleVariantFieldHash\".GetHashCode();\n\n        private static class Styles\n        {\n            public static GUIStyle label = \"ControlLabel\";\n            public static GUIStyle popup = \"MiniPopup\";\n            public static GUIStyle textField = \"textField\";\n        }\n\n        private bool m_ShowAssetBundleNameTextField = false;\n        private bool m_ShowAssetBundleVariantTextField = false;\n\n        public void OnAssetBundleNameGUI(IEnumerable<Object> assets)\n        {\n            float oldLabelWidth = EditorGUIUtility.labelWidth;\n            EditorGUIUtility.labelWidth = 90f;\n\n            Rect bundleRect  = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight);\n            Rect variantRect = bundleRect;\n\n            bundleRect.width *= 0.8f;\n            variantRect.xMin += bundleRect.width + EditorGUI.kSpacing;\n\n\n            int id = GUIUtility.GetControlID(kAssetBundleNameFieldIdHash, FocusType.Passive, bundleRect);\n\n            bundleRect = EditorGUI.PrefixLabel(bundleRect, id, kAssetBundleName, Styles.label);\n            if (m_ShowAssetBundleNameTextField)\n                AssetBundleTextField(bundleRect, id, assets, false);\n            else\n                AssetBundlePopup(bundleRect, id, assets, false);\n\n            id = GUIUtility.GetControlID(kAssetBundleVariantFieldIdHash, FocusType.Passive, variantRect);\n\n            if (m_ShowAssetBundleVariantTextField)\n                AssetBundleTextField(variantRect, id, assets, true);\n            else\n                AssetBundlePopup(variantRect, id, assets, true);\n\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n        }\n\n        private void ShowNewAssetBundleField(bool isVariant)\n        {\n            m_ShowAssetBundleNameTextField = !isVariant;\n            m_ShowAssetBundleVariantTextField = isVariant;\n\n            EditorGUIUtility.editingTextField = true;\n        }\n\n        private void AssetBundleTextField(Rect rect, int id, IEnumerable<Object> assets, bool isVariant)\n        {\n            EditorGUI.BeginChangeCheck();\n            string temp = EditorGUI.DelayedTextFieldInternal(rect, id, GUIContent.none, \"\", null, Styles.textField);\n            if (EditorGUI.EndChangeCheck())\n            {\n                SetAssetBundleForAssets(assets, temp, isVariant);\n                ShowAssetBundlePopup();\n            }\n\n            // editing was cancelled\n            if (EditorGUI.IsEditingTextField() == false && Event.current.type != EventType.Layout)\n                ShowAssetBundlePopup();\n        }\n\n        private void ShowAssetBundlePopup()\n        {\n            m_ShowAssetBundleNameTextField = false;\n            m_ShowAssetBundleVariantTextField = false;\n        }\n\n        private void AssetBundlePopup(Rect rect, int id, IEnumerable<Object> assets, bool isVariant)\n        {\n            List<string> displayedOptions = new List<string>();\n            displayedOptions.Add(\"None\");\n            displayedOptions.Add(\"\");  // seperator\n\n            // Anyway to optimize this by caching GetAssetBundleNameFromAssets() and GetAllAssetBundleNames() when they actually change?\n            // As we can change the assetBundle name by script, the UI needs to detect this kind of change.\n            bool mixedValue;\n            IEnumerable<string> assetBundleFromAssets = GetAssetBundlesFromAssets(assets, isVariant, out mixedValue);\n\n            string[] assetBundles = isVariant ? AssetDatabase.GetAllAssetBundleVariants() : AssetDatabase.GetAllAssetBundleNamesWithoutVariant();\n            displayedOptions.AddRange(assetBundles);\n\n            displayedOptions.Add(\"\");  // seperator\n            int newAssetBundleIndex = displayedOptions.Count;\n            displayedOptions.Add(\"New...\");\n\n            // These two options are invalid for variant, so skip them for variant.\n            int removeUnusedIndex = -1;\n            int filterSelectedIndex = -1;\n            if (!isVariant)\n            {\n                removeUnusedIndex = displayedOptions.Count;\n                displayedOptions.Add(\"Remove Unused Names\");\n                filterSelectedIndex = displayedOptions.Count;\n                if (assetBundleFromAssets.Count() != 0)\n                    displayedOptions.Add(\"Filter Selected Name\" + (mixedValue ? \"s\" : \"\"));\n            }\n\n            int selectedIndex = 0;\n            string firstAssetBundle = assetBundleFromAssets.FirstOrDefault();\n            if (!String.IsNullOrEmpty(firstAssetBundle))\n                selectedIndex = displayedOptions.IndexOf(firstAssetBundle);\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = mixedValue;\n            selectedIndex = EditorGUI.DoPopup(rect, id, selectedIndex, EditorGUIUtility.TempContent(displayedOptions.ToArray()), Styles.popup);\n            EditorGUI.showMixedValue = false;\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (selectedIndex == 0) // None\n                    SetAssetBundleForAssets(assets, null, isVariant);\n                else if (selectedIndex == newAssetBundleIndex) // New...\n                    ShowNewAssetBundleField(isVariant);\n                else if (selectedIndex == removeUnusedIndex) // Remove Unused Names\n                    AssetDatabase.RemoveUnusedAssetBundleNames();\n                else if (selectedIndex == filterSelectedIndex) // Filter Selected Name(s)\n                    FilterSelected(assetBundleFromAssets);\n                else\n                    SetAssetBundleForAssets(assets, displayedOptions[selectedIndex], isVariant);\n            }\n        }\n\n        private void FilterSelected(IEnumerable<string> assetBundleNames)\n        {\n            var searchFilter = new SearchFilter();\n            searchFilter.assetBundleNames = assetBundleNames.Where(name => !String.IsNullOrEmpty(name)).ToArray();\n\n            if (ProjectBrowser.s_LastInteractedProjectBrowser != null)\n                ProjectBrowser.s_LastInteractedProjectBrowser.SetSearch(searchFilter);\n            else\n                Debug.LogWarning(\"No Project Browser found to apply AssetBundle filter.\");\n        }\n\n        private IEnumerable<string> GetAssetBundlesFromAssets(IEnumerable<Object> assets, bool isVariant, out bool isMixed)\n        {\n            var assetBundles = new HashSet<string>();\n            string lastAssetBundle = null;\n            isMixed = false;\n\n            foreach (Object obj in assets)\n            {\n                if (obj is MonoScript)\n                    continue;\n\n                AssetImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(obj));\n                if (importer == null)\n                    continue;\n\n                string currentAssetBundle = isVariant ? importer.assetBundleVariant : importer.assetBundleName;\n\n                if (lastAssetBundle != null && lastAssetBundle != currentAssetBundle)\n                    isMixed = true;\n                lastAssetBundle = currentAssetBundle;\n\n                if (!String.IsNullOrEmpty(currentAssetBundle))\n                    assetBundles.Add(currentAssetBundle);\n            }\n\n            return assetBundles;\n        }\n\n        private void SetAssetBundleForAssets(IEnumerable<Object> assets, string name, bool isVariant)\n        {\n            bool assetBundleNameChanged = false;\n            foreach (Object obj in assets)\n            {\n                if (obj is MonoScript)\n                    continue;\n\n                AssetImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(obj));\n                if (importer == null)\n                    continue;\n\n                if (isVariant)\n                    importer.assetBundleVariant = name;\n                else\n                    importer.assetBundleName = name;\n\n                assetBundleNameChanged = true;\n            }\n\n            if (assetBundleNameChanged)\n            {\n                EditorApplication.Internal_CallAssetBundleNameChanged();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AudioChorusFilterEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AudioChorusFilter))]\n    class AudioChorusFilterEditor : Editor\n    {\n        private SerializedProperty m_DryMix;\n        private SerializedProperty m_WetMix1;\n        private SerializedProperty m_WetMix2;\n        private SerializedProperty m_WetMix3;\n        private SerializedProperty m_Delay;\n        private SerializedProperty m_Rate;\n        private SerializedProperty m_Depth;\n\n        private static class Styles\n        {\n            public static readonly GUIContent DryMixTooltip = EditorGUIUtility.TrTextContent(\"Dry Mix\", \"Volume of original signal to pass to output\");\n            public static readonly GUIContent WetMix1Tooltip = EditorGUIUtility.TrTextContent(\"Wet Mix 1\", \"Volume of 1st chorus tap\");\n            public static readonly GUIContent WetMix2Tooltip = EditorGUIUtility.TrTextContent(\"Wet Mix 2\", \"Volume of 2nd chorus tap\");\n            public static readonly GUIContent WetMix3Tooltip = EditorGUIUtility.TrTextContent(\"Wet Mix 3\", \"Volume of 3rd chorus tap\");\n            public static readonly GUIContent DelayTooltip = EditorGUIUtility.TrTextContent(\"Delay\", \"Chorus delay in ms\");\n            public static readonly GUIContent RateTooltip = EditorGUIUtility.TrTextContent(\"Rate\", \"Chorus modulation rate in hz\");\n            public static readonly GUIContent DepthTooltip = EditorGUIUtility.TrTextContent(\"Depth\", \"Chorus modulation depth\");\n        }\n\n        private void OnEnable()\n        {\n            m_DryMix = serializedObject.FindProperty(\"m_DryMix\");\n            m_WetMix1 = serializedObject.FindProperty(\"m_WetMix1\");\n            m_WetMix2 = serializedObject.FindProperty(\"m_WetMix2\");\n            m_WetMix3 = serializedObject.FindProperty(\"m_WetMix3\");\n            m_Delay = serializedObject.FindProperty(\"m_Delay\");\n            m_Rate = serializedObject.FindProperty(\"m_Rate\");\n            m_Depth = serializedObject.FindProperty(\"m_Depth\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUILayout.PropertyField(m_DryMix, Styles.DryMixTooltip);\n            EditorGUILayout.PropertyField(m_WetMix1, Styles.WetMix1Tooltip);\n            EditorGUILayout.PropertyField(m_WetMix2, Styles.WetMix2Tooltip);\n            EditorGUILayout.PropertyField(m_WetMix3, Styles.WetMix3Tooltip);\n            EditorGUILayout.PropertyField(m_Delay, Styles.DelayTooltip);\n            EditorGUILayout.PropertyField(m_Rate, Styles.RateTooltip);\n            EditorGUILayout.PropertyField(m_Depth, Styles.DepthTooltip);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AudioClipInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AudioClip))]\n    [CanEditMultipleObjects]\n    internal class AudioClipInspector : Editor\n    {\n        private PreviewRenderUtility m_PreviewUtility;\n        private AudioClip m_Clip;\n        private bool playing => s_PlayingInstance == this && m_Clip != null && AudioUtil.IsPreviewClipPlaying();\n        Vector2 m_Position = Vector2.zero;\n        private bool m_MultiEditing;\n\n        static GUIStyle s_PreButton;\n\n        static Rect s_WantedRect;\n        static bool s_AutoPlay;\n        static bool s_Loop;\n        static bool s_PlayFirst;\n        static AudioClipInspector s_PlayingInstance;\n\n        static GUIContent s_PlayIcon;\n        static GUIContent s_AutoPlayIcon;\n        static GUIContent s_LoopIcon;\n\n        static private string s_PreviewDisabledMessage = \"AudioClip preview not available when Unity Audio is disabled in Project Settings\";\n        static private string s_TrPreviewDisabledMessage = L10n.Tr(s_PreviewDisabledMessage);\n\n        static Texture2D s_DefaultIcon;\n\n        private Material m_HandleLinesMaterial;\n\n        public override void OnInspectorGUI()\n        {\n            // We can't always check this from preview methods\n            m_MultiEditing = targets.Length > 1;\n            // Override with inspector that doesn't show anything\n        }\n\n        static void Init()\n        {\n            if (s_PreButton != null)\n                return;\n            s_PreButton = \"preButton\";\n\n            s_AutoPlay = EditorPrefs.GetBool(\"AutoPlayAudio\", false);\n            s_Loop = false;\n\n            var unityAudioDisabled = AudioSettings.unityAudioDisabled;\n\n            s_AutoPlayIcon = EditorGUIUtility.TrIconContent(\"preAudioAutoPlayOff\", unityAudioDisabled ? s_PreviewDisabledMessage : \"Turn Auto Play on/off\");\n            s_PlayIcon = EditorGUIUtility.TrIconContent(\"PlayButton\", unityAudioDisabled ? s_PreviewDisabledMessage : \"Play\");\n            s_LoopIcon = EditorGUIUtility.TrIconContent(\"preAudioLoopOff\", unityAudioDisabled ? s_PreviewDisabledMessage : \"Loop on/off\");\n\n            s_DefaultIcon = EditorGUIUtility.LoadIcon(\"Profiler.Audio\");\n        }\n\n        public void OnDisable()\n        {\n            if (s_PlayingInstance == this)\n            {\n                AudioUtil.StopAllPreviewClips();\n                s_PlayingInstance = null;\n            }\n\n            EditorPrefs.SetBool(\"AutoPlayAudio\", s_AutoPlay);\n\n            if (m_PreviewUtility != null)\n            {\n                m_PreviewUtility.Cleanup();\n                m_PreviewUtility = null;\n            }\n\n            m_HandleLinesMaterial = null;\n        }\n\n        public void OnEnable()\n        {\n            s_AutoPlay = EditorPrefs.GetBool(\"AutoPlayAudio\", false);\n            if (s_AutoPlay)\n                s_PlayFirst = true;\n\n            m_HandleLinesMaterial = EditorGUIUtility.LoadRequired(\"SceneView/HandleLines.mat\") as Material;\n        }\n\n        public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height)\n        {\n            AudioClip clip = target as AudioClip;\n\n            AssetImporter importer = AssetImporter.GetAtPath(assetPath);\n            AudioImporter audioImporter = importer as AudioImporter;\n\n            if (audioImporter == null || !ShaderUtil.hardwareSupportsRectRenderTexture)\n                return null;\n\n            if (m_PreviewUtility == null)\n                m_PreviewUtility = new PreviewRenderUtility();\n\n            m_PreviewUtility.BeginStaticPreview(new Rect(0, 0, width, height));\n            m_HandleLinesMaterial.SetPass(0);\n\n            // We're drawing into an offscreen here which will have a resolution defined by EditorGUIUtility.pixelsPerPoint. This is different from the DoRenderPreview call below where we draw directly to the screen, so we need to take\n            // the higher resolution into account when drawing into the offscreen, otherwise only the upper-left quarter of the preview texture will be drawn.\n            DoRenderPreview(false, clip, audioImporter, new Rect(0.05f * width * EditorGUIUtility.pixelsPerPoint, 0.05f * width * EditorGUIUtility.pixelsPerPoint, 1.9f * width * EditorGUIUtility.pixelsPerPoint, 1.9f * height * EditorGUIUtility.pixelsPerPoint), 1.0f);\n\n            return m_PreviewUtility.EndStaticPreview();\n        }\n\n        public override bool HasPreviewGUI()\n        {\n            return (targets != null);\n        }\n\n        public override void OnPreviewSettings()\n        {\n            if (s_DefaultIcon == null) Init();\n\n            AudioClip clip = target as AudioClip;\n            m_MultiEditing = targets.Length > 1;\n\n            using (new EditorGUI.DisabledScope(AudioSettings.unityAudioDisabled))\n            {\n                using (new EditorGUI.DisabledScope(m_MultiEditing && !playing))\n                {\n                    bool newPlaying = GUILayout.Toggle(playing, s_PlayIcon, EditorStyles.toolbarButton);\n\n                    if (newPlaying != playing)\n                    {\n                        if (newPlaying)\n                            PlayClip(clip, 0, s_Loop);\n                        else\n                        {\n                            AudioUtil.StopAllPreviewClips();\n                            m_Clip = null;\n                        }\n                    }\n                }\n\n                using (new EditorGUI.DisabledScope(m_MultiEditing))\n                {\n                    s_AutoPlay = s_AutoPlay && !m_MultiEditing;\n                    s_AutoPlay = GUILayout.Toggle(s_AutoPlay, s_AutoPlayIcon, EditorStyles.toolbarButton);\n                }\n\n                bool loop = s_Loop;\n                s_Loop = GUILayout.Toggle(s_Loop, s_LoopIcon, EditorStyles.toolbarButton);\n                if ((loop != s_Loop) && playing)\n                    AudioUtil.LoopPreviewClip(s_Loop);\n            }\n        }\n\n        void PlayClip(AudioClip clip, int startSample = 0, bool loop = false)\n        {\n            AudioUtil.StopAllPreviewClips();\n            AudioUtil.PlayPreviewClip(clip, startSample, loop);\n            m_Clip = clip;\n            s_PlayingInstance = this;\n        }\n\n        // Passing in clip and importer separately as we're not completely done with the asset setup at the time we're asked to generate the preview.\n        private void DoRenderPreview(bool setMaterial, AudioClip clip, AudioImporter audioImporter, Rect wantedRect, float scaleFactor)\n        {\n            scaleFactor *= 0.95f; // Reduce amplitude slightly to make highly compressed signals fit.\n            float[] minMaxData = (audioImporter == null) ? null : AudioUtil.GetMinMaxData(audioImporter);\n            int numChannels = clip.channels;\n            int numSamples = (minMaxData == null) ? 0 : (minMaxData.Length / (2 * numChannels));\n            float h = (float)wantedRect.height / (float)numChannels;\n            for (int channel = 0; channel < numChannels; channel++)\n            {\n                Rect channelRect = new Rect(wantedRect.x, wantedRect.y + h * channel, wantedRect.width, h);\n                Color curveColor = new Color(1.0f, 140.0f / 255.0f, 0.0f, 1.0f);\n\n                AudioCurveRendering.AudioMinMaxCurveAndColorEvaluator dlg = delegate(float x, out Color col, out float minValue, out float maxValue)\n                {\n                    col = curveColor;\n                    if (numSamples <= 0)\n                    {\n                        minValue = 0.0f;\n                        maxValue = 0.0f;\n                    }\n                    else\n                    {\n                        float p = Mathf.Clamp(x * (numSamples - 2), 0.0f, numSamples - 2);\n                        int i = (int)Mathf.Floor(p);\n                        int offset1 = (i * numChannels + channel) * 2;\n                        int offset2 = offset1 + numChannels * 2;\n                        minValue = Mathf.Min(minMaxData[offset1 + 1], minMaxData[offset2 + 1]) * scaleFactor;\n                        maxValue = Mathf.Max(minMaxData[offset1 + 0], minMaxData[offset2 + 0]) * scaleFactor;\n                        if (minValue > maxValue) { float tmp = minValue; minValue = maxValue; maxValue = tmp; }\n                    }\n                };\n\n                if (setMaterial)\n                    AudioCurveRendering.DrawMinMaxFilledCurve(channelRect, dlg);\n                else\n                    AudioCurveRendering.DrawMinMaxFilledCurveInternal(channelRect, dlg);\n            }\n        }\n\n        public override void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            if (s_DefaultIcon == null) Init();\n\n            AudioClip clip = target as AudioClip;\n\n            Event evt = Event.current;\n            if (evt.type != EventType.Repaint && evt.type != EventType.Layout && evt.type != EventType.Used)\n            {\n                switch (evt.type)\n                {\n                    case EventType.MouseDrag:\n                    case EventType.MouseDown:\n                    {\n                        if (r.Contains(evt.mousePosition))\n                        {\n                            var startSample = (int)(evt.mousePosition.x * (AudioUtil.GetSampleCount(clip) / (int)r.width));\n                            if (!AudioUtil.IsPreviewClipPlaying() || clip != m_Clip)\n                                PlayClip(clip, startSample, s_Loop);\n                            else\n                                AudioUtil.SetPreviewClipSamplePosition(clip, startSample);\n                            evt.Use();\n                        }\n                    }\n                    break;\n                }\n                return;\n            }\n\n            if (Event.current.type == EventType.Repaint)\n                background.Draw(r, false, false, false, false);\n\n            int c = AudioUtil.GetChannelCount(clip);\n            s_WantedRect = new Rect(r.x, r.y , r.width, r.height);\n            float sec2px = ((float)s_WantedRect.width / clip.length);\n\n            bool previewAble = AudioUtil.HasPreview(clip) || !(AudioUtil.IsTrackerFile(clip));\n            if (!previewAble)\n            {\n                float labelY = (r.height > 150) ? r.y + (r.height / 2) - 10 :  r.y +  (r.height / 2) - 25;\n                if (r.width > 64)\n                {\n                    if (AudioUtil.IsTrackerFile(clip))\n                    {\n                        EditorGUI.DropShadowLabel(new Rect(r.x, labelY, r.width, 20), string.Format(\"Module file with \" + AudioUtil.GetMusicChannelCount(clip) + \" channels.\"));\n                    }\n                    else\n                        EditorGUI.DropShadowLabel(new Rect(r.x, labelY, r.width, 20), \"Can not show PCM data for this file\");\n                }\n\n                if (m_Clip == clip && playing)\n                {\n                    float t = AudioUtil.GetPreviewClipPosition();\n\n                    System.TimeSpan ts = new System.TimeSpan(0, 0, 0, 0, (int)(t * 1000.0f));\n\n                    EditorGUI.DropShadowLabel(new Rect(s_WantedRect.x, s_WantedRect.y, s_WantedRect.width, 20), string.Format(\"Playing - {0:00}:{1:00}.{2:000}\", ts.Minutes, ts.Seconds, ts.Milliseconds));\n                }\n            }\n            else\n            {\n                PreviewGUI.BeginScrollView(s_WantedRect, m_Position, s_WantedRect, \"PreHorizontalScrollbar\", \"PreHorizontalScrollbarThumb\");\n\n                if (Event.current.type == EventType.Repaint)\n                {\n                    DoRenderPreview(true, clip, AudioUtil.GetImporterFromClip(clip), s_WantedRect, 1.0f);\n                }\n\n                for (int i = 0; i < c; ++i)\n                {\n                    if (c > 1 && r.width > 64)\n                    {\n                        var labelRect = new Rect(s_WantedRect.x + 5, s_WantedRect.y + (s_WantedRect.height / c) * i, 30, 20);\n                        EditorGUI.DropShadowLabel(labelRect, \"ch \" + (i + 1));\n                    }\n                }\n\n                if (m_Clip == clip && playing)\n                {\n                    float t = AudioUtil.GetPreviewClipPosition();\n\n                    System.TimeSpan ts = new System.TimeSpan(0, 0, 0, 0, (int)(t * 1000.0f));\n\n                    GUI.DrawTexture(new Rect(s_WantedRect.x + (int)(sec2px * t), s_WantedRect.y, 2, s_WantedRect.height), EditorGUIUtility.whiteTexture);\n                    if (r.width > 64)\n                        EditorGUI.DropShadowLabel(new Rect(s_WantedRect.x, s_WantedRect.y, s_WantedRect.width, 20), string.Format(\"{0:00}:{1:00}.{2:000}\", ts.Minutes, ts.Seconds, ts.Milliseconds));\n                    else\n                        EditorGUI.DropShadowLabel(new Rect(s_WantedRect.x, s_WantedRect.y, s_WantedRect.width, 20), string.Format(\"{0:00}:{1:00}\", ts.Minutes, ts.Seconds));\n                }\n\n                PreviewGUI.EndScrollView();\n            }\n\n\n            if (!m_MultiEditing && (s_PlayFirst || (s_AutoPlay && m_Clip != clip)))\n            {\n                // Autoplay preview\n                PlayClip(clip, 0, s_Loop);\n                s_PlayFirst = false;\n            }\n\n            if (AudioSettings.unityAudioDisabled)\n            {\n                EditorGUILayout.HelpBox(s_TrPreviewDisabledMessage, MessageType.Info);\n            }\n\n            // force update GUI\n            if (playing && GUIView.current != null)\n                GUIView.current.Repaint();\n        }\n\n        public override string GetInfoString()\n        {\n            AudioClip clip = target as AudioClip;\n            int c = AudioUtil.GetChannelCount(clip);\n            string ch = c == 1 ? \"Mono\" : c == 2 ? \"Stereo\" : (c - 1) + \".1\";\n            AudioCompressionFormat platformFormat = AudioUtil.GetTargetPlatformSoundCompressionFormat(clip);\n            AudioCompressionFormat editorFormat = AudioUtil.GetSoundCompressionFormat(clip);\n            string s = platformFormat.ToString();\n            if (platformFormat != editorFormat)\n                s += \" (\" + editorFormat + \" in editor\" + \")\";\n            s += \", \" + AudioUtil.GetFrequency(clip) + \" Hz, \" + ch + \", \";\n\n            System.TimeSpan ts = new System.TimeSpan(0, 0, 0, 0, (int)AudioUtil.GetDuration(clip));\n\n            if ((uint)AudioUtil.GetDuration(clip) == 0xffffffff)\n                s += \"Unlimited\";\n            else\n                s += string.Format(\"{0:00}:{1:00}.{2:000}\", ts.Minutes, ts.Seconds, ts.Milliseconds);\n\n            return s;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AudioDistortionFilterInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AudioDistortionFilter))]\n    class AudioDistortionFilterEditor : Editor\n    {\n        private SerializedProperty m_DistortionLevel;\n\n        private static class Styles\n        {\n            public static readonly GUIContent DistortionLevelTooltip = EditorGUIUtility.TrTextContent(\"Distortion Level\", \"Distortion value\");\n        }\n\n        private void OnEnable()\n        {\n            m_DistortionLevel = serializedObject.FindProperty(\"m_DistortionLevel\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n            EditorGUILayout.PropertyField(m_DistortionLevel, Styles.DistortionLevelTooltip);\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AudioEchoFilterInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AudioEchoFilter))]\n    class AudioEchoFilterEditor : Editor\n    {\n        private SerializedProperty m_Delay;\n        private SerializedProperty m_DecayRatio;\n        private SerializedProperty m_DryMix;\n        private SerializedProperty m_WetMix;\n\n        private static class Styles\n        {\n            public static readonly GUIContent DelayTooltip = EditorGUIUtility.TrTextContent(\"Delay\", \"Echo delay in ms\");\n            public static readonly GUIContent DecayRatioTooltip = EditorGUIUtility.TrTextContent(\"Decay Ratio\", \"Echo decay per delay\");\n            public static readonly GUIContent DryMixTooltip = EditorGUIUtility.TrTextContent(\"Dry Mix\", \"Volume of original signal to pass to output\");\n            public static readonly GUIContent WetMixTooltip = EditorGUIUtility.TrTextContent(\"Wet Mix\", \"Volume of echo signal to pass to output\");\n        }\n\n        private void OnEnable()\n        {\n            m_Delay = serializedObject.FindProperty(\"m_Delay\");\n            m_DecayRatio = serializedObject.FindProperty(\"m_DecayRatio\");\n            m_DryMix = serializedObject.FindProperty(\"m_DryMix\");\n            m_WetMix = serializedObject.FindProperty(\"m_WetMix\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUILayout.PropertyField(m_Delay, Styles.DelayTooltip);\n            EditorGUILayout.PropertyField(m_DecayRatio, Styles.DecayRatioTooltip);\n            EditorGUILayout.PropertyField(m_DryMix, Styles.DryMixTooltip);\n            EditorGUILayout.PropertyField(m_WetMix, Styles.WetMixTooltip);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AudioFilterGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class AudioFilterGUI\n    {\n        private EditorGUI.VUMeter.SmoothingData[] dataOut;\n\n        public void DrawAudioFilterGUI(MonoBehaviour behaviour)\n        {\n            int channelCount = AudioUtil.GetCustomFilterChannelCount(behaviour);\n\n            if (channelCount > 0)\n            {\n                if (dataOut == null)\n                {\n                    dataOut = new EditorGUI.VUMeter.SmoothingData[channelCount];\n                }\n\n                double ms = (double)AudioUtil.GetCustomFilterProcessTime(behaviour) / 1000000.0; // ms\n                float limit = (float)ms / ((float)AudioSettings.outputSampleRate / 1024.0f / (float)channelCount);\n\n                GUILayout.BeginHorizontal();\n                GUILayout.Space(13);\n                GUILayout.BeginVertical();\n                EditorGUILayout.Space();\n                for (int c = 0; c < channelCount; ++c)\n                {\n                    EditorGUILayout.VUMeterHorizontal(AudioUtil.GetCustomFilterMaxOut(behaviour, c), ref dataOut[c], GUILayout.MinWidth(50), GUILayout.Height(5));\n                }\n                GUILayout.EndVertical();\n                Color old = GUI.color;\n                GUI.color = new Color(limit, 1.0f - limit, 0.0f, 1.0f);\n                GUILayout.Box(string.Format(\"{0:00.00}ms\", ms), GUILayout.MinWidth(40), GUILayout.Height(20));\n                GUI.color = old;\n\n                GUILayout.EndHorizontal();\n                EditorGUILayout.Space();\n\n                // force repaint\n                GUIView.current.Repaint();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AudioHighPassFilterInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AudioHighPassFilter))]\n    [CanEditMultipleObjects]\n    class AudioHighPassFilterEditor : Editor\n    {\n        SerializedProperty m_HighpassResonanceQ;\n        SerializedProperty m_CutoffFrequency;\n\n        private static class Styles\n        {\n            public static readonly GUIContent HighpassResonanceQTooltip = EditorGUIUtility.TrTextContent(\"Highpass Resonance Q\", \"Determines how much the filter's self-resonance is dampened\");\n            public static readonly GUIContent CutoffFrequencyTooltip = EditorGUIUtility.TrTextContent(\"Cutoff Frequency\", \"Highpass cutoff frequency in Hz\");\n        }\n\n        void OnEnable()\n        {\n            m_HighpassResonanceQ = serializedObject.FindProperty(\"m_HighpassResonanceQ\");\n            m_CutoffFrequency = serializedObject.FindProperty(\"m_CutoffFrequency\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUILayout.Slider(m_CutoffFrequency, 10.0f, 22000.0f, Styles.CutoffFrequencyTooltip);\n            EditorGUILayout.PropertyField(m_HighpassResonanceQ, Styles.HighpassResonanceQTooltip);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AudioLowPassFilterInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AudioLowPassFilter))]\n    [CanEditMultipleObjects]\n    internal class AudioLowPassFilterInspector : Editor\n    {\n        SerializedProperty m_LowpassResonanceQ;\n        SerializedProperty m_LowpassLevelCustomCurve;\n\n        private static class Styles\n        {\n            public static readonly GUIContent LowpassResonanceQTooltip = EditorGUIUtility.TrTextContent(\"Lowpass Resonance Q\", \"Determines how much the filter's self-resonance is dampened\");\n            public static readonly GUIContent LowpassLevelCustomCurveTooltip = EditorGUIUtility.TrTextContent(\"Cutoff Frequency\", \"Lowpass cutoff frequency in Hz\");\n        }\n\n        void OnEnable()\n        {\n            m_LowpassResonanceQ = serializedObject.FindProperty(\"m_LowpassResonanceQ\");\n            m_LowpassLevelCustomCurve = serializedObject.FindProperty(\"lowpassLevelCustomCurve\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            AudioSourceInspector.AnimProp(\n                Styles.LowpassLevelCustomCurveTooltip,\n                m_LowpassLevelCustomCurve,\n                10.0f, AudioSourceInspector.kMaxCutoffFrequency, true);\n\n            EditorGUILayout.PropertyField(m_LowpassResonanceQ, Styles.LowpassResonanceQTooltip);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AudioManagerInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditorInternal;\n\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AudioManager))]\n    internal class AudioManagerInspector : ProjectSettingsBaseEditor\n    {\n        private class Styles\n        {\n            public static GUIContent Volume                 = EditorGUIUtility.TrTextContent(\"Global Volume\", \"Initial volume multiplier (AudioListener.volume)\");\n            public static GUIContent RolloffScale           = EditorGUIUtility.TrTextContent(\"Volume Rolloff Scale\", \"Global volume rolloff multiplier (applies only to logarithmic volume curves).\");\n            public static GUIContent DopplerFactor          = EditorGUIUtility.TrTextContent(\"Doppler Factor\", \"Global Doppler speed multiplier for sounds in motion.\");\n            public static GUIContent DefaultSpeakerMode     = EditorGUIUtility.TrTextContent(\"Default Speaker Mode\", \"Speaker mode at start of the game. This may be changed at runtime using the AudioSettings.Reset function.\");\n            public static GUIContent SampleRate             = EditorGUIUtility.TrTextContent(\"System Sample Rate\", \"Sample rate at which the output device of the audio system runs. Individual sounds may run at different sample rates and will be slowed down/sped up accordingly to match the output rate.\");\n            public static GUIContent DSPBufferSize          = EditorGUIUtility.TrTextContent(\"DSP Buffer Size\", \"Length of mixing buffer. This determines the output latency of the game.\");\n            public static GUIContent VirtualVoiceCount      = EditorGUIUtility.TrTextContent(\"Max Virtual Voices\", \"Maximum number of sounds managed by the system. Even though at most RealVoiceCount of the loudest sounds will be physically playing, the remaining sounds will still be updating their play position.\");\n            public static GUIContent RealVoiceCount         = EditorGUIUtility.TrTextContent(\"Max Real Voices\", \"Maximum number of actual simultaneously playing sounds.\");\n            public static GUIContent SpatializerPlugin      = EditorGUIUtility.TrTextContent(\"Spatializer Plugin\", \"Native audio plugin performing spatialized filtering of 3D sources.\");\n            public static GUIContent AmbisonicDecoderPlugin = EditorGUIUtility.TrTextContent(\"Ambisonic Decoder Plugin\", \"Native audio plugin performing ambisonic-to-binaural filtering of sources.\");\n            public static GUIContent DisableAudio           = EditorGUIUtility.TrTextContent(\"Disable Unity Audio\", \"Prevent allocating the output device in the runtime. Use this if you want to use other sound systems than the built-in one.\");\n            public static GUIContent VirtualizeEffects      = EditorGUIUtility.TrTextContent(\"Virtualize Effects\", \"When enabled, dynamically turn off effects and spatializers on AudioSources that are culled in order to save CPU.\");\n            public static GUIContent EnableOutputSuspension = EditorGUIUtility.TrTextContent(\"Enable Output Suspension (editor only)\", \"When enabled automatically suspends audio output after detecting that the output has been silent for a long duration (editor only). Suspending the audio system disables a mechanism in the operating system that prevents the computer from going into sleep mode.\");\n\n            public static GUIContent DSPBufferSizeInfo = EditorGUIUtility.TrTextContent(\"The requested buffer size ({0}) has been overridden to {1} by the operating system\");\n        }\n\n        private SerializedProperty m_Volume;\n        private SerializedProperty m_RolloffScale;\n        private SerializedProperty m_DopplerFactor;\n        private SerializedProperty m_DefaultSpeakerMode;\n        private SerializedProperty m_SampleRate;\n        private SerializedProperty m_RequestedDSPBufferSize;\n        private SerializedProperty m_ActualDSPBufferSize;\n        private SerializedProperty m_VirtualVoiceCount;\n        private SerializedProperty m_RealVoiceCount;\n        private SerializedProperty m_SpatializerPlugin;\n        private SerializedProperty m_AmbisonicDecoderPlugin;\n        private SerializedProperty m_DisableAudio;\n        private SerializedProperty m_VirtualizeEffects;\n        private SerializedProperty m_EnableOutputSuspension;\n\n        private void OnEnable()\n        {\n            m_Volume                    = serializedObject.FindProperty(\"m_Volume\");\n            m_RolloffScale              = serializedObject.FindProperty(\"Rolloff Scale\");\n            m_DopplerFactor             = serializedObject.FindProperty(\"Doppler Factor\");\n            m_DefaultSpeakerMode        = serializedObject.FindProperty(\"Default Speaker Mode\");\n            m_SampleRate                = serializedObject.FindProperty(\"m_SampleRate\");\n            m_RequestedDSPBufferSize    = serializedObject.FindProperty(\"m_RequestedDSPBufferSize\");\n            m_ActualDSPBufferSize       = serializedObject.FindProperty(\"m_DSPBufferSize\");\n            m_VirtualVoiceCount         = serializedObject.FindProperty(\"m_VirtualVoiceCount\");\n            m_RealVoiceCount            = serializedObject.FindProperty(\"m_RealVoiceCount\");\n            m_SpatializerPlugin         = serializedObject.FindProperty(\"m_SpatializerPlugin\");\n            m_AmbisonicDecoderPlugin    = serializedObject.FindProperty(\"m_AmbisonicDecoderPlugin\");\n            m_DisableAudio              = serializedObject.FindProperty(\"m_DisableAudio\");\n            m_VirtualizeEffects         = serializedObject.FindProperty(\"m_VirtualizeEffects\");\n            m_EnableOutputSuspension    = serializedObject.FindProperty(\"m_EnableOutputSuspension\");\n        }\n\n        //This function assumes that index 0 is None...\n        private int FindPluginStringIndex(string[] strs, string element)\n        {\n            //Skip past the first \"None\" entry\n            for (int i = 1; i < strs.Length; i++)\n            {\n                if (element == strs[i])\n                    return i;\n            }\n\n            return 0;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUILayout.PropertyField(m_Volume, Styles.Volume);\n            EditorGUILayout.PropertyField(m_RolloffScale, Styles.RolloffScale);\n            EditorGUILayout.PropertyField(m_DopplerFactor, Styles.DopplerFactor);\n            EditorGUILayout.PropertyField(m_DefaultSpeakerMode, Styles.DefaultSpeakerMode);\n            EditorGUILayout.PropertyField(m_SampleRate, Styles.SampleRate);\n            EditorGUILayout.PropertyField(m_RequestedDSPBufferSize, Styles.DSPBufferSize);\n            if (m_RequestedDSPBufferSize.intValue != m_ActualDSPBufferSize.intValue)\n                EditorGUILayout.HelpBox(\n                    string.Format(Styles.DSPBufferSizeInfo.text,\n                        m_RequestedDSPBufferSize.intValue == 0 ? \"default\" : m_RequestedDSPBufferSize.intValue.ToString(),\n                        m_ActualDSPBufferSize.intValue),\n                    MessageType.Info);\n            EditorGUILayout.PropertyField(m_VirtualVoiceCount, Styles.VirtualVoiceCount);\n            EditorGUILayout.PropertyField(m_RealVoiceCount, Styles.RealVoiceCount);\n\n            List<string> plugins = new List<string>(AudioSettings.GetSpatializerPluginNames());\n            plugins.Insert(0, \"None\");\n            string[] pluginsArray = plugins.ToArray();\n\n            List<GUIContent> pluginsGUIContent = new List<GUIContent>();\n            foreach (var s in pluginsArray)\n                pluginsGUIContent.Add(new GUIContent(s));\n\n            List<string> ambisonicDecoderPlugins = new List<string>(AudioUtil.GetAmbisonicDecoderPluginNames());\n            ambisonicDecoderPlugins.Insert(0, \"None\");\n            string[] ambisonicDecoderPluginsArray = ambisonicDecoderPlugins.ToArray();\n\n            List<GUIContent> ambisonicDecoderPluginsGUIContent = new List<GUIContent>();\n            foreach (var s in ambisonicDecoderPluginsArray)\n                ambisonicDecoderPluginsGUIContent.Add(new GUIContent(s));\n\n            EditorGUI.BeginChangeCheck();\n            int pluginIndex = FindPluginStringIndex(pluginsArray, m_SpatializerPlugin.stringValue);\n            pluginIndex = EditorGUILayout.Popup(Styles.SpatializerPlugin, pluginIndex, pluginsGUIContent.ToArray());\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (pluginIndex == 0)\n                    m_SpatializerPlugin.stringValue = \"\";\n                else\n                    m_SpatializerPlugin.stringValue = pluginsArray[pluginIndex];\n            }\n\n            EditorGUI.BeginChangeCheck();\n            pluginIndex = FindPluginStringIndex(ambisonicDecoderPluginsArray, m_AmbisonicDecoderPlugin.stringValue);\n            pluginIndex = EditorGUILayout.Popup(Styles.AmbisonicDecoderPlugin, pluginIndex, ambisonicDecoderPluginsGUIContent.ToArray());\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (pluginIndex == 0)\n                    m_AmbisonicDecoderPlugin.stringValue = \"\";\n                else\n                    m_AmbisonicDecoderPlugin.stringValue = ambisonicDecoderPluginsArray[pluginIndex];\n            }\n\n            EditorGUI.BeginChangeCheck();\n\n            EditorGUILayout.PropertyField(m_DisableAudio, Styles.DisableAudio);\n\n            if (EditorGUI.EndChangeCheck() && m_DisableAudio.boolValue.Equals(true))\n            {\n                AudioUtil.StopAllPreviewClips();\n            }\n\n            EditorGUILayout.PropertyField(m_EnableOutputSuspension, Styles.EnableOutputSuspension);\n\n            EditorGUILayout.PropertyField(m_VirtualizeEffects, Styles.VirtualizeEffects);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        [SettingsProvider]\n        static SettingsProvider CreateProjectSettingsProvider()\n        {\n            var provider = AssetSettingsProvider.CreateProviderFromAssetPath(\n                \"Project/Audio\", \"ProjectSettings/AudioManager.asset\",\n                SettingsProvider.GetSearchKeywordsFromGUIContentProperties<Styles>());\n            return provider;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AudioMixerControllerInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.Audio;\nusing UnityEngine.Audio;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AudioMixerController))]\n    [CanEditMultipleObjects]\n    internal class AudioMixerControllerInspector : Editor\n    {\n        static class Texts\n        {\n            public static GUIContent m_EnableSuspendLabel = EditorGUIUtility.TrTextContent(\"Auto Mixer Suspend\", \"Enables/disables suspending of processing in order to save CPU when the RMS signal level falls under the defined threshold (in dB). Mixers resume processing when an AudioSource referencing them starts playing again.\");\n            public static GUIContent m_SuspendThresholdLabel = EditorGUIUtility.TrTextContent(\"    Threshold Volume\", \"The level of the Master Group at which the mixer suspends processing in order to save CPU. Mixers resume processing when an AudioSource referencing them starts playing again.\");\n            public static GUIContent m_UpdateModeLabel = EditorGUIUtility.TrTextContent(\"Update Mode\", \"Update AudioMixer transitions with game time or unscaled realtime.\");\n            public static string dB = \"dB\";\n        }\n\n        SerializedProperty m_EnableSuspend;\n        SerializedProperty m_SuspendThreshold;\n        SerializedProperty m_UpdateMode;\n\n        public void OnEnable()\n        {\n            m_SuspendThreshold = serializedObject.FindProperty(\"m_SuspendThreshold\");\n            m_EnableSuspend = serializedObject.FindProperty(\"m_EnableSuspend\");\n            m_UpdateMode = serializedObject.FindProperty(\"m_UpdateMode\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n            EditorGUILayout.PropertyField(m_EnableSuspend, Texts.m_EnableSuspendLabel);\n            using (new EditorGUI.DisabledScope(!m_EnableSuspend.boolValue || m_EnableSuspend.hasMultipleDifferentValues))\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.s_UnitString = Texts.dB;\n                float displayValue = m_SuspendThreshold.floatValue;\n                displayValue = EditorGUILayout.PowerSlider(Texts.m_SuspendThresholdLabel, displayValue, AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume(), 1.0f);\n                EditorGUI.s_UnitString = null;\n                if (EditorGUI.EndChangeCheck())\n                    m_SuspendThreshold.floatValue = displayValue;\n            }\n            EditorGUILayout.PropertyField(m_UpdateMode, Texts.m_UpdateModeLabel);\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n\n    // Here we need an inspector for runtime objects that are loaded in the editor (via asset bundles)\n    // We need to inform the user that such objects are not editable in the editor.\n    [CustomEditor(typeof(AudioMixer))]\n    [CanEditMultipleObjects]\n    internal class AudioMixerInspector : Editor\n    {\n        public override void OnInspectorGUI()\n        {\n            GUILayout.Space(10);\n            EditorGUILayout.HelpBox(\"Modification and inspection of built AudioMixer assets is disabled. Please modify the source asset and re-build.\", MessageType.Info);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AudioMixerGroupEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Security.Permissions;\nusing UnityEngine;\nusing UnityEditor.Audio;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AudioMixerGroupController))]\n    internal class AudioMixerGroupEditor : Editor\n    {\n        private AudioMixerEffectView m_EffectView = null;\n        private readonly TickTimerHelper m_Ticker = new TickTimerHelper(1.0 / 20.0);\n        public static readonly string kPrefKeyForShowCpuUsage = \"AudioMixerShowCPU\";\n\n        void OnEnable()\n        {\n            EditorApplication.update += Update;\n        }\n\n        void OnDisable()\n        {\n            EditorApplication.update -= Update;\n        }\n\n        public void Update()\n        {\n            if (EditorApplication.isPlaying && m_Ticker.DoTick())\n            {\n                Repaint();  // Ensure repaint to update vu meters and effects in playmode\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            AudioMixerDrawUtils.InitStyles();\n            if (m_EffectView == null)\n                m_EffectView = new AudioMixerEffectView();\n\n            AudioMixerGroupController group = target as AudioMixerGroupController;\n            m_EffectView.OnGUI(group);\n        }\n\n        public override bool UseDefaultMargins()\n        {\n            // Makes inspector be full width\n            return false;\n        }\n\n        internal override Rect DrawHeaderHelpAndSettingsGUI(Rect r)\n        {\n            if (m_EffectView == null)\n                return new Rect(r.xMax, r.y, 0, r.height);\n\n            AudioMixerGroupController group = target as AudioMixerGroupController;\n\n            var helpAndSettingsRect = base.DrawHeaderHelpAndSettingsGUI(r);\n            float rectX = r.x + 44f;\n            float rectWidth = (helpAndSettingsRect.x - r.x) - 44f;\n            Rect rect = new Rect(rectX, r.yMax - 20f, rectWidth, 15f);\n            GUI.Label(rect, GUIContent.Temp(group.controller.name), EditorStyles.miniLabel);\n\n            return helpAndSettingsRect; // Return the helpAndSettings part, not the label under\n        }\n\n        // Add item to the context menu of the AudioMixerGroupController inspector header\n        [MenuItem(\"CONTEXT/AudioMixerGroupController/Copy all effect settings to all snapshots\", secondaryPriority = 10)]\n        static void CopyAllEffectToSnapshots(MenuCommand command)\n        {\n            AudioMixerGroupController group = command.context as AudioMixerGroupController;\n            AudioMixerController controller = group.controller;\n            if (controller == null)\n                return;\n\n            Undo.RecordObject(controller, \"Copy all effect settings to all snapshots\");\n            controller.CopyAllSettingsToAllSnapshots(group, controller.TargetSnapshot);\n        }\n\n        [MenuItem(\"CONTEXT/AudioMixerGroupController/Toggle CPU usage display (only available on first editor instance)\", secondaryPriority = 11)]\n        static void ShowCPUUsage(MenuCommand command)\n        {\n            bool value = EditorPrefs.GetBool(kPrefKeyForShowCpuUsage, false);\n            EditorPrefs.SetBool(kPrefKeyForShowCpuUsage, !value);\n        }\n    }\n\n    [CustomEditor(typeof(AudioMixerSnapshotController))]\n    [CanEditMultipleObjects]\n    internal class AudioMixerSnapshotControllerInspector : Editor\n    {\n        public override void OnInspectorGUI()\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AudioRandomContainerInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n﻿using System;\nusing UnityEngine;\nusing UnityEngine.Audio;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor;\n\n[CustomEditor(typeof(AudioRandomContainer))]\n[CanEditMultipleObjects]\nsealed class AudioRandomContainerInspector : Editor\n{\n    private StyleLength margin = 5;\n\n    private Button button;\n\n    public override VisualElement CreateInspectorGUI()\n    {\n        button = new Button();\n\n        button.text = \"Edit Audio Random Container\";\n        button.style.marginBottom = margin;\n        button.style.marginTop = margin;\n        button.style.marginLeft = 0;\n        button.style.marginRight = 0;\n        button.style.height = 24;\n        button.clicked += () => { EditorWindow.GetWindow<AudioContainerWindow>(); };\n\n        return button;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AudioReverbFilterEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AudioReverbFilter))]\n    [CanEditMultipleObjects]\n    class AudioReverbFilterEditor : Editor\n    {\n        SerializedProperty m_ReverbPreset;\n\n        SerializedProperty  m_DryLevel; // room effect level (at mid frequencies)\n        SerializedProperty  m_Room; // room effect level (at mid frequencies)\n        SerializedProperty  m_RoomHF; // relative room effect level at high frequencies\n        SerializedProperty  m_RoomLF; // relative room effect level at low frequencies\n        SerializedProperty  m_DecayTime; // reverberation decay time at mid frequencies\n        SerializedProperty  m_DecayHFRatio; //  high-frequency to mid-frequency decay time ratio\n        SerializedProperty  m_ReflectionsLevel; // early reflections level relative to room effect\n        SerializedProperty  m_ReflectionsDelay; //  initial reflection delay time\n        SerializedProperty  m_ReverbLevel; //  late reverberation level relative to room effect\n        SerializedProperty  m_ReverbDelay; //  late reverberation delay time relative to initial reflection\n        SerializedProperty  m_HFReference; // reference high frequency (hz)\n        SerializedProperty  m_LFReference; // reference low frequency (hz)\n        SerializedProperty  m_Diffusion; //  Value that controls the echo density in the late reverberation decay\n        SerializedProperty  m_Density; // Value that controls the modal density in the late reverberation decay\n\n\n        void OnEnable()\n        {\n            m_ReverbPreset = serializedObject.FindProperty(\"m_ReverbPreset\");\n            m_DryLevel = serializedObject.FindProperty(\"m_DryLevel\"); // room effect level (at mid frequencies)\n            m_Room = serializedObject.FindProperty(\"m_Room\"); // room effect level (at mid frequencies)\n            m_RoomHF = serializedObject.FindProperty(\"m_RoomHF\"); // relative room effect level at high frequencies\n            m_RoomLF = serializedObject.FindProperty(\"m_RoomLF\"); // relative room effect level at low frequencies\n            m_DecayTime = serializedObject.FindProperty(\"m_DecayTime\"); // reverberation decay time at mid frequencies\n            m_DecayHFRatio = serializedObject.FindProperty(\"m_DecayHFRatio\"); //  high-frequency to mid-frequency decay time ratio\n            m_ReflectionsLevel = serializedObject.FindProperty(\"m_ReflectionsLevel\"); // early reflections level relative to room effect\n            m_ReflectionsDelay = serializedObject.FindProperty(\"m_ReflectionsDelay\"); //  initial reflection delay time\n            m_ReverbLevel = serializedObject.FindProperty(\"m_ReverbLevel\"); //  late reverberation level relative to room effect\n            m_ReverbDelay = serializedObject.FindProperty(\"m_ReverbDelay\"); //  late reverberation delay time relative to initial reflection\n            m_HFReference = serializedObject.FindProperty(\"m_HFReference\"); // reference high frequency (hz)\n            m_LFReference = serializedObject.FindProperty(\"m_LFReference\"); // reference low frequency (hz)\n            m_Diffusion = serializedObject.FindProperty(\"m_Diffusion\"); //  Value that controls the echo density in the late reverberation decay\n            m_Density = serializedObject.FindProperty(\"m_Density\"); // Value that controls the modal density in the late reverberation decay\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_ReverbPreset);\n            if (EditorGUI.EndChangeCheck())\n                serializedObject.SetIsDifferentCacheDirty();\n\n            using (new EditorGUI.DisabledScope(m_ReverbPreset.enumValueIndex != 27 || m_ReverbPreset.hasMultipleDifferentValues))\n            {\n                EditorGUILayout.Slider(m_DryLevel, -10000, 0);\n                EditorGUILayout.Slider(m_Room, -10000, 0);\n                EditorGUILayout.Slider(m_RoomHF, -10000, 0);\n                EditorGUILayout.Slider(m_RoomLF, -10000, 0);\n                EditorGUILayout.Slider(m_DecayTime, 0.1f, 20.0f);\n                EditorGUILayout.Slider(m_DecayHFRatio, 0.1f, 2.0f);\n                EditorGUILayout.Slider(m_ReflectionsLevel, -10000, 1000);\n                EditorGUILayout.Slider(m_ReflectionsDelay, 0.0f, 0.3f);\n                EditorGUILayout.Slider(m_ReverbLevel, -10000, 2000);\n                EditorGUILayout.Slider(m_ReverbDelay, 0.0f, 0.1f);\n                EditorGUILayout.Slider(m_HFReference, 1000.0f, 20000.0f);\n                EditorGUILayout.Slider(m_LFReference, 20.0f, 1000.0f);\n                EditorGUILayout.Slider(m_Diffusion, 0.0f, 100.0f);\n                EditorGUILayout.Slider(m_Density, 0.0f, 100.0f);\n            }\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AudioReverbZoneEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AudioReverbZone))]\n    [CanEditMultipleObjects]\n    class AudioReverbZoneEditor : Editor\n    {\n        SerializedProperty m_MinDistance;\n        SerializedProperty m_MaxDistance;\n        SerializedProperty m_ReverbPreset;\n\n        SerializedProperty  m_Room; // room effect level (at mid frequencies)\n        SerializedProperty  m_RoomHF; // relative room effect level at high frequencies\n        SerializedProperty  m_RoomLF; // relative room effect level at low frequencies\n        SerializedProperty  m_DecayTime; // reverberation decay time at mid frequencies\n        SerializedProperty  m_DecayHFRatio; //  high-frequency to mid-frequency decay time ratio\n        SerializedProperty  m_Reflections; // early reflections level relative to room effect\n        SerializedProperty  m_ReflectionsDelay; //  initial reflection delay time\n        SerializedProperty  m_Reverb; //  late reverberation level relative to room effect\n        SerializedProperty  m_ReverbDelay; //  late reverberation delay time relative to initial reflection\n        SerializedProperty  m_HFReference; // reference high frequency (hz)\n        SerializedProperty  m_LFReference; // reference low frequency (hz)\n        SerializedProperty  m_Diffusion; //  Value that controls the echo density in the late reverberation decay\n        SerializedProperty  m_Density; // Value that controls the modal density in the late reverberation decay\n\n        private static class Styles\n        {\n            public static readonly GUIContent MinDistanceTooltip = EditorGUIUtility.TrTextContent(\"MinDistance\", \"The distance from the centerpoint that the reverb will have full effect at\");\n            public static readonly GUIContent MaxDistanceTooltip = EditorGUIUtility.TrTextContent(\"MaxDistance\", \"The distance from the centerpoint that the reverb will not have any effect\");\n            public static readonly GUIContent ReverbPresetTooltip = EditorGUIUtility.TrTextContent(\"ReverbPreset\", \"The reverb preset\");\n            public static readonly GUIContent RoomTooltip = EditorGUIUtility.TrTextContent(\"Room\", \"Room effect level (at mid frequencies)\");\n            public static readonly GUIContent RoomHFTooltip = EditorGUIUtility.TrTextContent(\"Room HF\", \"Relative room effect level at high frequencies\");\n            public static readonly GUIContent RoomLFTooltip = EditorGUIUtility.TrTextContent(\"Room LF\", \"Relative room effect level at low frequencies\");\n            public static readonly GUIContent DecayTimeTooltip = EditorGUIUtility.TrTextContent(\"Decay Time\", \"Reverberation decay time at mid frequencies\");\n            public static readonly GUIContent DecayHFRatioTooltip = EditorGUIUtility.TrTextContent(\"Decay HF Ratio\", \"High-frequency to mid-frequency decay time ratio\");\n            public static readonly GUIContent ReflectionsTooltip = EditorGUIUtility.TrTextContent(\"Reflections\", \"Early reflections level relative to room effect\");\n            public static readonly GUIContent ReflectionsDelayTooltip = EditorGUIUtility.TrTextContent(\"Reflections Delay\", \"Initial reflection delay time\");\n            public static readonly GUIContent ReverbTooltip = EditorGUIUtility.TrTextContent(\"Reverb\", \"Late reverberation level relative to room effect\");\n            public static readonly GUIContent ReverbDelayTooltip = EditorGUIUtility.TrTextContent(\"Reverb Delay\", \"Late reverberation delay time relative to initial reflection\");\n            public static readonly GUIContent HFReferenceTooltip = EditorGUIUtility.TrTextContent(\"HF Reference\", \"Reference high frequency (Hz)\");\n            public static readonly GUIContent LFReferenceTooltip = EditorGUIUtility.TrTextContent(\"LF Reference\", \"Reference low frequency (Hz)\");\n            public static readonly GUIContent DiffusionTooltip = EditorGUIUtility.TrTextContent(\"Diffusion\", \"Value that controls the echo density in the late reverberation decay\");\n            public static readonly GUIContent DensityTooltip = EditorGUIUtility.TrTextContent(\"Density\", \"Value that controls the modal density in the late reverberation decay\");\n        }\n\n\n        void OnEnable()\n        {\n            m_MinDistance = serializedObject.FindProperty(\"m_MinDistance\");\n            m_MaxDistance = serializedObject.FindProperty(\"m_MaxDistance\");\n            m_ReverbPreset = serializedObject.FindProperty(\"m_ReverbPreset\");\n            m_Room = serializedObject.FindProperty(\"m_Room\"); // room effect level (at mid frequencies)\n            m_RoomHF = serializedObject.FindProperty(\"m_RoomHF\"); // relative room effect level at high frequencies\n            m_RoomLF = serializedObject.FindProperty(\"m_RoomLF\"); // relative room effect level at low frequencies\n            m_DecayTime = serializedObject.FindProperty(\"m_DecayTime\"); // reverberation decay time at mid frequencies\n            m_DecayHFRatio = serializedObject.FindProperty(\"m_DecayHFRatio\"); //  high-frequency to mid-frequency decay time ratio\n            m_Reflections = serializedObject.FindProperty(\"m_Reflections\"); // early reflections level relative to room effect\n            m_ReflectionsDelay = serializedObject.FindProperty(\"m_ReflectionsDelay\"); //  initial reflection delay time\n            m_Reverb = serializedObject.FindProperty(\"m_Reverb\"); //  late reverberation level relative to room effect\n            m_ReverbDelay = serializedObject.FindProperty(\"m_ReverbDelay\"); //  late reverberation delay time relative to initial reflection\n            m_HFReference = serializedObject.FindProperty(\"m_HFReference\"); // reference high frequency (hz)\n            m_LFReference = serializedObject.FindProperty(\"m_LFReference\"); // reference low frequency (hz)\n            m_Diffusion = serializedObject.FindProperty(\"m_Diffusion\"); //  Value that controls the echo density in the late reverberation decay\n            m_Density = serializedObject.FindProperty(\"m_Density\"); // Value that controls the modal density in the late reverberation decay\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUILayout.PropertyField(m_MinDistance, Styles.MinDistanceTooltip);\n            EditorGUILayout.PropertyField(m_MaxDistance, Styles.MaxDistanceTooltip);\n\n            EditorGUILayout.Space();\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_ReverbPreset, Styles.ReverbPresetTooltip);\n            // Changing the preset changes all the other properties as well, so we need to do a full refresh afterwards\n            if (EditorGUI.EndChangeCheck())\n                serializedObject.SetIsDifferentCacheDirty();\n\n            using (new EditorGUI.DisabledScope(m_ReverbPreset.enumValueIndex != 27 || m_ReverbPreset.hasMultipleDifferentValues))\n            {\n                EditorGUILayout.IntSlider(m_Room, -10000, 0, Styles.RoomTooltip);\n                EditorGUILayout.IntSlider(m_RoomHF, -10000, 0, Styles.RoomHFTooltip);\n                EditorGUILayout.IntSlider(m_RoomLF, -10000, 0, Styles.RoomLFTooltip);\n                EditorGUILayout.Slider(m_DecayTime, 0.1f, 20.0f, Styles.DecayTimeTooltip);\n                EditorGUILayout.Slider(m_DecayHFRatio, 0.1f, 2.0f, Styles.DecayHFRatioTooltip);\n                EditorGUILayout.IntSlider(m_Reflections, -10000, 1000, Styles.ReflectionsTooltip);\n                EditorGUILayout.Slider(m_ReflectionsDelay, 0.0f, 0.3f, Styles.ReflectionsDelayTooltip);\n                EditorGUILayout.IntSlider(m_Reverb, -10000, 2000, Styles.ReverbTooltip);\n                EditorGUILayout.Slider(m_ReverbDelay, 0.0f, 0.1f, Styles.ReverbDelayTooltip);\n                EditorGUILayout.Slider(m_HFReference, 1000.0f, 20000.0f, Styles.HFReferenceTooltip);\n                EditorGUILayout.Slider(m_LFReference, 20.0f, 1000.0f, Styles.LFReferenceTooltip);\n                EditorGUILayout.Slider(m_Diffusion, 0.0f, 100.0f, Styles.DiffusionTooltip);\n                EditorGUILayout.Slider(m_Density, 0.0f, 100.0f, Styles.DensityTooltip);\n            }\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        void OnSceneGUI()\n        {\n            if (!target)\n                return;\n            AudioReverbZone zone = (AudioReverbZone)target;\n\n            Color tempColor = Handles.color;\n            if (zone.enabled)\n                Handles.color = new Color(0.50f, 0.70f, 1.00f, 0.5f);\n            else\n                Handles.color = new Color(0.30f, 0.40f, 0.60f, 0.5f);\n\n            Vector3 position = zone.transform.position;\n\n            EditorGUI.BeginChangeCheck();\n            float minDistance = Handles.RadiusHandle(Quaternion.identity, position, zone.minDistance, true);\n            float maxDistance = Handles.RadiusHandle(Quaternion.identity, position, zone.maxDistance, true);\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                Undo.RecordObject(zone, \"Reverb Distance\");\n                zone.minDistance = minDistance;\n                zone.maxDistance = maxDistance;\n            }\n\n            Handles.color = tempColor;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AudioSourceInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine.Audio;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(AudioSource))]\n    [CanEditMultipleObjects]\n    sealed class AudioSourceInspector : Editor\n    {\n        SerializedProperty m_AudioResource;\n        SerializedProperty m_PlayOnAwake;\n        SerializedProperty m_Volume;\n        SerializedProperty m_Pitch;\n        SerializedProperty m_Loop;\n        SerializedProperty m_Mute;\n        SerializedProperty m_Spatialize;\n        SerializedProperty m_SpatializePostEffects;\n        SerializedProperty m_Priority;\n        SerializedProperty m_DopplerLevel;\n        SerializedProperty m_MinDistance;\n        SerializedProperty m_MaxDistance;\n        SerializedProperty m_Pan2D;\n        SerializedProperty m_RolloffMode;\n        SerializedProperty m_BypassEffects;\n        SerializedProperty m_BypassListenerEffects;\n        SerializedProperty m_BypassReverbZones;\n        SerializedProperty m_OutputAudioMixerGroup;\n        SerializedObject m_LowpassObject;\n\n        class AudioCurveWrapper\n        {\n            public AudioCurveType type;\n            public GUIContent legend;\n            public int id;\n            public Color color;\n            public SerializedProperty curveProp;\n            public float rangeMin;\n            public float rangeMax;\n            public AudioCurveWrapper(AudioCurveType type, string legend, int id, Color color, SerializedProperty curveProp, float rangeMin, float rangeMax)\n            {\n                this.type = type;\n                this.legend = new GUIContent(legend);\n                this.id = id;\n                this.color = color;\n                this.curveProp = curveProp;\n                this.rangeMin = rangeMin;\n                this.rangeMax = rangeMax;\n            }\n        }\n        private AudioCurveWrapper[] m_AudioCurves;\n\n        CurveEditor m_CurveEditor = null;\n        Vector3 m_LastSourcePosition;\n        Vector3 m_LastListenerPosition;\n\n        const int kRolloffCurveID = 0;\n        const int kSpatialBlendCurveID = 1;\n        const int kSpreadCurveID = 2;\n        const int kLowPassCurveID = 3;\n        const int kReverbZoneMixCurveID = 4;\n        internal const float kMaxCutoffFrequency = 22000.0f;\n        const float EPSILON = 0.0001f;\n\n\n        static CurveEditorSettings m_CurveEditorSettings = new CurveEditorSettings();\n        internal static Color kRolloffCurveColor  = new Color(0.90f, 0.30f, 0.20f, 1.0f);\n        internal static Color kSpatialCurveColor = new Color(0.25f, 0.70f, 0.20f, 1.0f);\n        internal static Color kSpreadCurveColor   = new Color(0.25f, 0.55f, 0.95f, 1.0f);\n        internal static Color kLowPassCurveColor  = new Color(0.80f, 0.25f, 0.90f, 1.0f);\n        internal static Color kReverbZoneMixCurveColor = new Color(0.70f, 0.70f, 0.20f, 1.0f);\n\n        internal bool[] m_SelectedCurves = new bool[0];\n\n        private enum AudioCurveType { Volume, SpatialBlend, Lowpass, Spread, ReverbZoneMix }\n\n        private bool m_Expanded3D = false;\n\n        internal static class Styles\n        {\n            public static GUIStyle labelStyle = \"ProfilerBadge\";\n            public static GUIContent rolloffLabel =  EditorGUIUtility.TrTextContent(\"Volume Rolloff\", \"Which type of rolloff curve to use\");\n            public static string controlledByCurveLabel = \"Controlled by curve\";\n            public static GUIContent audioResourceLabel = EditorGUIUtility.TrTextContent(\"Audio Resource\", \"The AudioResource asset played by the AudioSource. Can be undefined if the AudioSource is generating a live stream of audio via OnAudioFilterRead.\");\n            public static GUIContent panStereoLabel = EditorGUIUtility.TrTextContent(\"Stereo Pan\", \"Only valid for Mono and Stereo AudioClips. Mono sounds will be panned at constant power left and right. Stereo sounds will have each left/right value faded up and down according to the specified pan value.\");\n            public static GUIContent spatialBlendLabel = EditorGUIUtility.TrTextContent(\"Spatial Blend\", \"Sets how much this AudioSource is treated as a 3D source. 3D sources are affected by spatial position and spread. If 3D Pan Level is 0, all spatial attenuation is ignored.\");\n            public static GUIContent reverbZoneMixLabel = EditorGUIUtility.TrTextContent(\"Reverb Zone Mix\", \"Sets how much of the signal this AudioSource is mixing into the global reverb associated with the zones. [0, 1] is a linear range (like volume) while [1, 1.1] lets you boost the reverb mix by 10 dB.\");\n            public static GUIContent dopplerLevelLabel = EditorGUIUtility.TrTextContent(\"Doppler Level\", \"Specifies how much the pitch is changed based on the relative velocity between AudioListener and AudioSource.\");\n            public static GUIContent spreadLabel = EditorGUIUtility.TrTextContent(\"Spread\", \"Sets the spread of a 3d sound in speaker space\");\n            public static GUIContent outputMixerGroupLabel = EditorGUIUtility.TrTextContent(\"Output\", \"Set whether the sound should play through an Audio Mixer first or directly to the Audio Listener\");\n            public static GUIContent volumeLabel = EditorGUIUtility.TrTextContent(\"Volume\", \"Sets the overall volume of the sound.\");\n            public static GUIContent pitchLabel = EditorGUIUtility.TrTextContent(\"Pitch\", \"Sets the frequency of the sound. Use this to slow down or speed up the sound.\");\n            public static GUIContent priorityLabel = EditorGUIUtility.TrTextContent(\"Priority\", \"Sets the priority of the source. Note that a sound with a larger priority value will more likely be stolen by sounds with smaller priority values.\");\n            public static GUIContent spatializeLabel = EditorGUIUtility.TrTextContent(\"Spatialize\", \"Enables or disables custom spatialization for the AudioSource.\");\n            public static GUIContent spatializePostEffectsLabel = EditorGUIUtility.TrTextContent(\"Spatialize Post Effects\", \"Determines if the custom spatializer is applied before or after the effect filters attached to the AudioSource. This flag only has an effect if the spatialize flag is enabled on the AudioSource.\");\n            public static GUIContent priorityLeftLabel = EditorGUIUtility.TrTextContent(\"High\");\n            public static GUIContent priorityRightLabel = EditorGUIUtility.TrTextContent(\"Low\");\n            public static GUIContent spatialLeftLabel = EditorGUIUtility.TrTextContent(\"2D\");\n            public static GUIContent spatialRightLabel = EditorGUIUtility.TrTextContent(\"3D\");\n            public static GUIContent panLeftLabel = EditorGUIUtility.TrTextContent(\"Left\");\n            public static GUIContent panRightLabel = EditorGUIUtility.TrTextContent(\"Right\");\n            public static string xAxisLabel = L10n.Tr(\"Distance\");\n        }\n\n        Vector3 GetSourcePos(Object target)\n        {\n            AudioSource source = (AudioSource)target;\n            if (source == null)\n                return new Vector3(0.0f, 0.0f, 0.0f);\n            return source.transform.position;\n        }\n\n        void OnEnable()\n        {\n            m_AudioResource = serializedObject.FindProperty(\"m_Resource\");\n            m_PlayOnAwake = serializedObject.FindProperty(\"m_PlayOnAwake\");\n            m_Volume = serializedObject.FindProperty(\"m_Volume\");\n            m_Pitch = serializedObject.FindProperty(\"m_Pitch\");\n            m_Loop = serializedObject.FindProperty(\"Loop\");\n            m_Mute = serializedObject.FindProperty(\"Mute\");\n            m_Spatialize = serializedObject.FindProperty(\"Spatialize\");\n            m_SpatializePostEffects = serializedObject.FindProperty(\"SpatializePostEffects\");\n            m_Priority = serializedObject.FindProperty(\"Priority\");\n            m_DopplerLevel = serializedObject.FindProperty(\"DopplerLevel\");\n            m_MinDistance = serializedObject.FindProperty(\"MinDistance\");\n            m_MaxDistance = serializedObject.FindProperty(\"MaxDistance\");\n            m_Pan2D = serializedObject.FindProperty(\"Pan2D\");\n            m_RolloffMode = serializedObject.FindProperty(\"rolloffMode\");\n            m_BypassEffects = serializedObject.FindProperty(\"BypassEffects\");\n            m_BypassListenerEffects = serializedObject.FindProperty(\"BypassListenerEffects\");\n            m_BypassReverbZones = serializedObject.FindProperty(\"BypassReverbZones\");\n            m_OutputAudioMixerGroup = serializedObject.FindProperty(\"OutputAudioMixerGroup\");\n\n            m_AudioCurves = new AudioCurveWrapper[]\n            {\n                new AudioCurveWrapper(AudioCurveType.Volume, \"Volume\", kRolloffCurveID, kRolloffCurveColor, serializedObject.FindProperty(\"rolloffCustomCurve\"), 0, 1),\n                new AudioCurveWrapper(AudioCurveType.SpatialBlend, \"Spatial Blend\", kSpatialBlendCurveID, kSpatialCurveColor, serializedObject.FindProperty(\"panLevelCustomCurve\"), 0, 1),\n                new AudioCurveWrapper(AudioCurveType.Spread, \"Spread\", kSpreadCurveID, kSpreadCurveColor, serializedObject.FindProperty(\"spreadCustomCurve\"), 0, 1),\n                new AudioCurveWrapper(AudioCurveType.Lowpass, \"Low-Pass\", kLowPassCurveID, kLowPassCurveColor, null, 0, 1),\n                new AudioCurveWrapper(AudioCurveType.ReverbZoneMix, \"Reverb Zone Mix\", kReverbZoneMixCurveID, kReverbZoneMixCurveColor, serializedObject.FindProperty(\"reverbZoneMixCustomCurve\"), 0, 1.1f)\n            };\n\n            m_CurveEditorSettings.hRangeMin = 0.0f;\n            m_CurveEditorSettings.vRangeMin = 0.0f;\n            m_CurveEditorSettings.vRangeMax = 1.1f;\n            m_CurveEditorSettings.hRangeMax = 1.0f;\n            m_CurveEditorSettings.vSlider = false;\n            m_CurveEditorSettings.hSlider = false;\n\n            TickStyle hTS = new TickStyle();\n            hTS.tickColor.color = new Color(0.0f, 0.0f, 0.0f, 0.15f);\n            hTS.distLabel = 30;\n            m_CurveEditorSettings.hTickStyle = hTS;\n            TickStyle vTS = new TickStyle();\n            vTS.tickColor.color = new Color(0.0f, 0.0f, 0.0f, 0.15f);\n            vTS.distLabel = 20;\n            m_CurveEditorSettings.vTickStyle = vTS;\n\n            m_CurveEditorSettings.undoRedoSelection = true;\n\n            m_CurveEditor = new CurveEditor(new Rect(0, 0, 1000, 100), new CurveWrapper[0], false);\n            m_CurveEditor.settings = m_CurveEditorSettings;\n            m_CurveEditor.margin = 25;\n            m_CurveEditor.SetShownHRangeInsideMargins(0.0f, 1.0f);\n            m_CurveEditor.SetShownVRangeInsideMargins(0.0f, 1.1f);\n            m_CurveEditor.ignoreScrollWheelUntilClicked = true;\n\n            m_LastSourcePosition = GetSourcePos(target);\n            m_LastListenerPosition = AudioUtil.GetListenerPos();\n            EditorApplication.update += Update;\n\n            m_Expanded3D = EditorPrefs.GetBool(\"AudioSourceExpanded3D\", m_Expanded3D);\n        }\n\n        void OnDisable()\n        {\n            m_CurveEditor.OnDisable();\n\n            EditorApplication.update -= Update;\n\n            EditorPrefs.SetBool(\"AudioSourceExpanded3D\", m_Expanded3D);\n        }\n\n        CurveWrapper[] GetCurveWrapperArray()\n        {\n            List<CurveWrapper> wrappers = new List<CurveWrapper>();\n\n            foreach (AudioCurveWrapper audioCurve in m_AudioCurves)\n            {\n                if (audioCurve.curveProp == null)\n                    continue;\n\n                bool includeCurve = false;\n                AnimationCurve curve = audioCurve.curveProp.animationCurveValue;\n\n                // Special handling of volume rolloff curve\n                if (audioCurve.type == AudioCurveType.Volume)\n                {\n                    AudioRolloffMode mode = (AudioRolloffMode)m_RolloffMode.enumValueIndex;\n                    if (m_RolloffMode.hasMultipleDifferentValues)\n                    {\n                        includeCurve = false;\n                    }\n                    else if (mode == AudioRolloffMode.Custom)\n                    {\n                        includeCurve = !audioCurve.curveProp.hasMultipleDifferentValues;\n                    }\n                    else\n                    {\n                        includeCurve = !m_MinDistance.hasMultipleDifferentValues && !m_MaxDistance.hasMultipleDifferentValues;\n                        if (mode == AudioRolloffMode.Linear)\n                            curve = AnimationCurve.Linear(m_MinDistance.floatValue / m_MaxDistance.floatValue, 1.0f, 1.0f, 0.0f);\n                        else if (mode == AudioRolloffMode.Logarithmic)\n                            curve = Logarithmic(m_MinDistance.floatValue / m_MaxDistance.floatValue, 1.0f, 1.0f);\n                    }\n                }\n                // All other curves\n                else\n                {\n                    includeCurve = !audioCurve.curveProp.hasMultipleDifferentValues;\n                }\n\n                if (includeCurve)\n                {\n                    if (curve.length == 0)\n                        Debug.LogError(audioCurve.legend.text + \" curve has no keys!\");\n                    else\n                        wrappers.Add(GetCurveWrapper(curve, audioCurve));\n                }\n            }\n\n            return wrappers.ToArray();\n        }\n\n        private CurveWrapper GetCurveWrapper(AnimationCurve curve, AudioCurveWrapper audioCurve)\n        {\n            float colorMultiplier = !EditorGUIUtility.isProSkin ? 0.9f : 1.0f;\n            Color colorMult = new Color(colorMultiplier, colorMultiplier, colorMultiplier, 1);\n\n            CurveWrapper wrapper = new CurveWrapper();\n            wrapper.id = audioCurve.id;\n            wrapper.groupId = -1;\n            wrapper.color = audioCurve.color * colorMult;\n            wrapper.hidden = false;\n            wrapper.readOnly = false;\n            wrapper.renderer = new NormalCurveRenderer(curve);\n            wrapper.renderer.SetCustomRange(0.0f, 1.0f);\n            wrapper.getAxisUiScalarsCallback = GetAxisScalars;\n            wrapper.useScalingInKeyEditor = true;\n            wrapper.xAxisLabel = Styles.xAxisLabel;\n            wrapper.yAxisLabel = audioCurve.legend.text;\n            return wrapper;\n        }\n\n        // Callback for Curve Editor to get axis labels\n        public Vector2 GetAxisScalars()\n        {\n            return new Vector2(m_MaxDistance.floatValue, 1);\n        }\n\n        private static float LogarithmicValue(float distance, float minDistance, float rolloffScale)\n        {\n            if ((distance > minDistance) && (rolloffScale != 1.0f))\n            {\n                distance -= minDistance;\n                distance *= rolloffScale;\n                distance += minDistance;\n            }\n            if (distance < .000001f)\n                distance = .000001f;\n            return minDistance / distance;\n        }\n\n        /// A logarithmic curve starting at /timeStart/, /valueStart/ and ending at /timeEnd/, /valueEnd/\n        private static AnimationCurve Logarithmic(float timeStart, float timeEnd, float logBase)\n        {\n            float value, slope, s;\n            List<Keyframe> keys = new List<Keyframe>();\n            // Just plain set the step to 2 always. It can't really be any less,\n            // or the curvature will end up being imprecise in certain edge cases.\n            float step = 2;\n            timeStart = Mathf.Max(timeStart, 0.0001f);\n            for (float d = timeStart; d < timeEnd; d *= step)\n            {\n                // Add key w. sensible tangents\n                value = LogarithmicValue(d, timeStart, logBase);\n                s = d / 50.0f;\n                slope = (LogarithmicValue(d + s, timeStart, logBase) - LogarithmicValue(d - s, timeStart, logBase)) / (s * 2);\n                keys.Add(new Keyframe(d, value, slope, slope));\n            }\n\n            // last key\n            value = LogarithmicValue(timeEnd, timeStart, logBase);\n            s = timeEnd / 50.0f;\n            slope = (LogarithmicValue(timeEnd + s, timeStart, logBase) - LogarithmicValue(timeEnd - s, timeStart, logBase)) / (s * 2);\n            keys.Add(new Keyframe(timeEnd, value, slope, slope));\n\n            return new AnimationCurve(keys.ToArray());\n        }\n\n        private void Update()\n        {\n            // listener moved?\n            Vector3 sourcePos = GetSourcePos(target);\n            Vector3 listenerPos = AudioUtil.GetListenerPos();\n            if ((m_LastSourcePosition - sourcePos).sqrMagnitude > EPSILON || (m_LastListenerPosition - listenerPos).sqrMagnitude > EPSILON)\n            {\n                m_LastSourcePosition = sourcePos;\n                m_LastListenerPosition = listenerPos;\n                Repaint();\n            }\n        }\n\n        private void HandleLowPassFilter()\n        {\n            AudioCurveWrapper audioCurve = m_AudioCurves[kLowPassCurveID];\n\n            // Low pass filter present for all targets?\n            AudioLowPassFilter[] filterArray = new AudioLowPassFilter[targets.Length];\n            for (int i = 0; i < targets.Length; i++)\n            {\n                filterArray[i] = ((AudioSource)targets[i]).GetComponent<AudioLowPassFilter>();\n                if (filterArray[i] == null)\n                {\n                    m_LowpassObject = null;\n                    audioCurve.curveProp = null;\n                    // Return if any of the GameObjects don't have an AudioLowPassFilter\n                    return;\n                }\n            }\n\n            // All the GameObjects have an AudioLowPassFilter.\n            // If we don't have the corresponding SerializedObject and SerializedProperties, create them.\n            if (audioCurve.curveProp == null)\n            {\n                m_LowpassObject = new SerializedObject(filterArray);\n                audioCurve.curveProp = m_LowpassObject.FindProperty(\"lowpassLevelCustomCurve\");\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            //Bug fix: 1018456 Moved the HandleLowPassFilter method before updating the serializedObjects\n            HandleLowPassFilter();\n\n            serializedObject.Update();\n\n            if (m_LowpassObject != null)\n                m_LowpassObject.Update();\n\n            UpdateWrappersAndLegend();\n\n            EditorGUILayout.Space();\n            EditorGUILayout.PropertyField(m_AudioResource, Styles.audioResourceLabel);\n\n            EditorGUILayout.PropertyField(m_OutputAudioMixerGroup, Styles.outputMixerGroupLabel);\n            EditorGUILayout.PropertyField(m_Mute);\n\n            if (AudioUtil.canUseSpatializerEffect)\n            {\n                EditorGUILayout.PropertyField(m_Spatialize, Styles.spatializeLabel);\n                using (new EditorGUI.DisabledScope(!m_Spatialize.boolValue))\n                {\n                    EditorGUILayout.PropertyField(m_SpatializePostEffects, Styles.spatializePostEffectsLabel);\n                }\n            }\n            EditorGUILayout.PropertyField(m_BypassEffects);\n            if (targets.Any(t => (t as AudioSource).outputAudioMixerGroup != null))\n            {\n                using (new EditorGUI.DisabledScope(true))\n                {\n                    EditorGUILayout.PropertyField(m_BypassListenerEffects);\n                }\n            }\n            else\n            {\n                EditorGUILayout.PropertyField(m_BypassListenerEffects);\n            }\n            EditorGUILayout.PropertyField(m_BypassReverbZones);\n\n            EditorGUILayout.PropertyField(m_PlayOnAwake);\n            EditorGUILayout.PropertyField(m_Loop);\n\n            EditorGUILayout.Space();\n            EditorGUIUtility.sliderLabels.SetLabels(Styles.priorityLeftLabel, Styles.priorityRightLabel);\n            EditorGUILayout.IntSlider(m_Priority, 0, 256, Styles.priorityLabel);\n            EditorGUIUtility.sliderLabels.SetLabels(null, null);\n            EditorGUILayout.Space();\n            EditorGUILayout.Slider(m_Volume, 0f, 1.0f, Styles.volumeLabel);\n            EditorGUILayout.Space();\n\n            var resource = m_AudioResource.objectReferenceValue as AudioResource;\n            if (resource is AudioRandomContainer)\n                {\n                    EditorGUILayout.Slider(m_Pitch, EPSILON, 3.0f, Styles.pitchLabel);\n\n                }\n                else\n                {\n                    EditorGUILayout.Slider(m_Pitch, -3.0f, 3.0f, Styles.pitchLabel);\n                }\n\n            EditorGUILayout.Space();\n\n            EditorGUIUtility.sliderLabels.SetLabels(Styles.panLeftLabel, Styles.panRightLabel);\n            EditorGUILayout.Slider(m_Pan2D, -1f, 1f, Styles.panStereoLabel);\n            EditorGUIUtility.sliderLabels.SetLabels(null, null);\n            EditorGUILayout.Space();\n\n            // 3D Level control\n            EditorGUIUtility.sliderLabels.SetLabels(Styles.spatialLeftLabel, Styles.spatialRightLabel);\n            AnimProp(Styles.spatialBlendLabel, m_AudioCurves[kSpatialBlendCurveID].curveProp, 0.0f, 1.0f, false);\n            EditorGUIUtility.sliderLabels.SetLabels(null, null);\n            EditorGUILayout.Space();\n\n            // 3D Level control\n            AnimProp(Styles.reverbZoneMixLabel, m_AudioCurves[kReverbZoneMixCurveID].curveProp, 0.0f, 1.1f, false);\n            EditorGUILayout.Space();\n\n            m_Expanded3D = EditorGUILayout.Foldout(m_Expanded3D, \"3D Sound Settings\", true);\n            if (m_Expanded3D)\n            {\n                EditorGUI.indentLevel++;\n                Audio3DGUI();\n                EditorGUI.indentLevel--;\n            }\n\n            serializedObject.ApplyModifiedProperties();\n\n            if (m_LowpassObject != null)\n                m_LowpassObject.ApplyModifiedProperties();\n        }\n\n        private static void SetRolloffToTarget(SerializedProperty property, Object target)\n        {\n            property.SetToValueOfTarget(target);\n            property.serializedObject.FindProperty(\"rolloffMode\").SetToValueOfTarget(target);\n            property.serializedObject.ApplyModifiedProperties();\n            EditorUtility.ForceReloadInspectors();\n        }\n\n        private void Audio3DGUI()\n        {\n            EditorGUILayout.Slider(m_DopplerLevel, 0.0f, 5.0f, Styles.dopplerLevelLabel);\n\n            // Spread control\n            AnimProp(Styles.spreadLabel, m_AudioCurves[kSpreadCurveID].curveProp, 0.0f, 360.0f, true);\n\n            // Rolloff mode\n            if (m_RolloffMode.hasMultipleDifferentValues ||\n                (m_RolloffMode.enumValueIndex == (int)AudioRolloffMode.Custom && m_AudioCurves[kRolloffCurveID].curveProp.hasMultipleDifferentValues)\n            )\n            {\n                EditorGUILayout.TargetChoiceField(m_AudioCurves[kRolloffCurveID].curveProp, Styles.rolloffLabel , SetRolloffToTarget);\n            }\n            else\n            {\n                EditorGUILayout.PropertyField(m_RolloffMode, Styles.rolloffLabel);\n\n                if ((AudioRolloffMode)m_RolloffMode.enumValueIndex != AudioRolloffMode.Custom)\n                {\n                    EditorGUI.BeginChangeCheck();\n                    EditorGUILayout.PropertyField(m_MinDistance);\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        m_MinDistance.floatValue = Mathf.Clamp(m_MinDistance.floatValue, 0, m_MaxDistance.floatValue / 1.01f);\n                    }\n                }\n                else\n                {\n                    using (new EditorGUI.DisabledScope(true))\n                    {\n                        EditorGUILayout.LabelField(m_MinDistance.displayName, Styles.controlledByCurveLabel);\n                    }\n                }\n            }\n\n            // Max distance control\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_MaxDistance);\n            if (EditorGUI.EndChangeCheck())\n                m_MaxDistance.floatValue = Mathf.Min(Mathf.Max(Mathf.Max(m_MaxDistance.floatValue, 0.01f), m_MinDistance.floatValue * 1.01f), 1000000.0f);\n\n            Rect r = GUILayoutUtility.GetAspectRect(1.333f, GUI.skin.textField);\n            r.xMin += EditorGUI.indent;\n            if (Event.current.type != EventType.Layout && Event.current.type != EventType.Used)\n            {\n                m_CurveEditor.rect = new Rect(r.x, r.y, r.width, r.height);\n            }\n\n            // Draw Curve Editor\n            UpdateWrappersAndLegend();\n            GUI.Label(m_CurveEditor.drawRect, GUIContent.none, \"TextField\");\n\n            m_CurveEditor.hRangeLocked = Event.current.shift;\n            m_CurveEditor.vRangeLocked = EditorGUI.actionKey;\n\n            m_CurveEditor.OnGUI();\n\n            // Draw current listener position\n            if (targets.Length == 1)\n            {\n                AudioSource t = (AudioSource)target;\n                AudioListener audioListener = (AudioListener)FindFirstObjectByType(typeof(AudioListener));\n                if (audioListener != null)\n                {\n                    float distToListener = (AudioUtil.GetListenerPos() - t.transform.position).magnitude;\n                    DrawLabel(\"Listener\", distToListener, r);\n                }\n            }\n\n            // Draw legend\n            DrawLegend();\n\n            if (!m_CurveEditor.InLiveEdit())\n            {\n                // Check if any of the curves changed\n                foreach (AudioCurveWrapper audioCurve in m_AudioCurves)\n                {\n                    if ((m_CurveEditor.GetCurveWrapperFromID(audioCurve.id) != null) && (m_CurveEditor.GetCurveWrapperFromID(audioCurve.id).changed))\n                    {\n                        AnimationCurve changedCurve = m_CurveEditor.GetCurveWrapperFromID(audioCurve.id).curve;\n\n                        // Never save a curve with no keys\n                        if (changedCurve.length > 0)\n                        {\n                            audioCurve.curveProp.animationCurveValue = changedCurve;\n                            m_CurveEditor.GetCurveWrapperFromID(audioCurve.id).changed = false;\n\n                            // Volume curve special handling\n                            if (audioCurve.type == AudioCurveType.Volume)\n                                m_RolloffMode.enumValueIndex = (int)AudioRolloffMode.Custom;\n                        }\n                    }\n                }\n            }\n        }\n\n        void UpdateWrappersAndLegend()\n        {\n            if (m_CurveEditor.InLiveEdit())\n                return;\n\n            // prevent rebuilding wrappers if any curve has changes\n            if (m_CurveEditor.animationCurves != null)\n            {\n                for (int i = 0; i < m_CurveEditor.animationCurves.Length; i++)\n                {\n                    if (m_CurveEditor.animationCurves[i].changed)\n                        return;\n                }\n            }\n\n            m_CurveEditor.animationCurves = GetCurveWrapperArray();\n            SyncShownCurvesToLegend(GetShownAudioCurves());\n        }\n\n        void DrawLegend()\n        {\n            List<Rect> legendRects = new List<Rect>();\n            List<AudioCurveWrapper> curves = GetShownAudioCurves();\n            Rect legendRect = GUILayoutUtility.GetRect(10, 40 * EditorGUIUtility.pixelsPerPoint);\n            legendRect.x += 4 + EditorGUI.indent;\n            legendRect.width -= 8 + EditorGUI.indent;\n            // Graph's position acts as reference for Legends\n            legendRect.y = m_CurveEditor.rect.y + m_CurveEditor.rect.height + 20;\n            int width = Mathf.Min(75, Mathf.FloorToInt(legendRect.width / curves.Count));\n            for (int i = 0; i < curves.Count; i++)\n            {\n                legendRects.Add(new Rect(legendRect.x + width * i, legendRect.y, width, legendRect.height));\n            }\n\n            bool resetSelections = false;\n            if (curves.Count != m_SelectedCurves.Length)\n            {\n                m_SelectedCurves = new bool[curves.Count];\n                resetSelections = true;\n            }\n\n            if (EditorGUIExt.DragSelection(legendRects.ToArray(), ref m_SelectedCurves, GUIStyle.none) || resetSelections)\n            {\n                // If none are selected, select all\n                bool someSelected = false;\n                for (int i = 0; i < curves.Count; i++)\n                {\n                    if (m_SelectedCurves[i])\n                        someSelected = true;\n                }\n                if (!someSelected)\n                {\n                    for (int i = 0; i < curves.Count; i++)\n                    {\n                        m_SelectedCurves[i] = true;\n                    }\n                }\n\n                SyncShownCurvesToLegend(curves);\n            }\n\n            for (int i = 0; i < curves.Count; i++)\n            {\n                EditorGUI.DrawLegend(legendRects[i], curves[i].color, curves[i].legend.text, m_SelectedCurves[i]);\n                if (curves[i].curveProp.hasMultipleDifferentValues)\n                {\n                    GUI.Button(new Rect(legendRects[i].x, legendRects[i].y + 20, legendRects[i].width, 20), \"Different\");\n                }\n            }\n        }\n\n        private List<AudioCurveWrapper> GetShownAudioCurves()\n        {\n            return m_AudioCurves.Where(f => m_CurveEditor.GetCurveWrapperFromID(f.id) != null).ToList();\n        }\n\n        private void SyncShownCurvesToLegend(List<AudioCurveWrapper> curves)\n        {\n            if (curves.Count != m_SelectedCurves.Length)\n                return; // Selected curves in sync'ed later in this frame\n\n            for (int i = 0; i < curves.Count; i++)\n                m_CurveEditor.GetCurveWrapperFromID(curves[i].id).hidden = !m_SelectedCurves[i];\n\n            // Need to apply animation curves again to synch selections\n            m_CurveEditor.animationCurves = m_CurveEditor.animationCurves;\n        }\n\n        void DrawLabel(string label, float value, Rect r)\n        {\n            Vector2 size = Styles.labelStyle.CalcSize(new GUIContent(label));\n            size.x += 2;\n            Vector2 posA = m_CurveEditor.DrawingToViewTransformPoint(new Vector2(value / m_MaxDistance.floatValue, 0));\n            Vector2 posB = m_CurveEditor.DrawingToViewTransformPoint(new Vector2(value / m_MaxDistance.floatValue, 1));\n            GUI.BeginGroup(r);\n            Color temp = Handles.color;\n            Handles.color = new Color(1, 0, 0, 0.3f);\n            Handles.DrawLine(new Vector3(posA.x  , posA.y, 0), new Vector3(posB.x  , posB.y, 0));\n            Handles.DrawLine(new Vector3(posA.x + 1, posA.y, 0), new Vector3(posB.x + 1, posB.y, 0));\n            Handles.color = temp;\n            GUI.Label(new Rect(Mathf.Floor(posB.x - size.x / 2), 2, size.x, 15), label, Styles.labelStyle);\n            GUI.EndGroup();\n        }\n\n        internal static void AnimProp(GUIContent label, SerializedProperty prop, float min, float max, bool useNormalizedValue)\n        {\n            if (prop.hasMultipleDifferentValues)\n            {\n                EditorGUILayout.TargetChoiceField(prop, label);\n                return;\n            }\n\n            AnimationCurve curve = prop.animationCurveValue;\n            if (curve == null)\n            {\n                Debug.LogError(label.text + \" curve is null!\");\n                return;\n            }\n            else if (curve.length == 0)\n            {\n                Debug.LogError(label.text + \" curve has no keys!\");\n                return;\n            }\n\n            Rect position = EditorGUILayout.GetControlRect();\n            EditorGUI.BeginProperty(position, label, prop);\n            if (curve.length != 1)\n            {\n                using (new EditorGUI.DisabledScope(true))\n                {\n                    EditorGUI.LabelField(position, label.text, Styles.controlledByCurveLabel);\n                }\n            }\n            else\n            {\n                float f = useNormalizedValue ? Mathf.Lerp(min, max, curve.keys[0].value) : curve.keys[0].value;\n                f = MathUtils.DiscardLeastSignificantDecimal(f);\n                EditorGUI.BeginChangeCheck();\n                if (max > min)\n                    f = EditorGUI.Slider(position, label, f, min, max);\n                else\n                    f = EditorGUI.Slider(position, label, f, max, min);\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    Keyframe kf = curve.keys[0];\n                    kf.time = 0.0f;\n                    kf.value = useNormalizedValue ? Mathf.InverseLerp(min, max, f) : f;\n                    curve.MoveKey(0, kf);\n                }\n            }\n            EditorGUI.EndProperty();\n\n            prop.animationCurveValue = curve;\n        }\n\n        void OnSceneGUI()\n        {\n            if (!target)\n                return;\n            AudioSource source = (AudioSource)target;\n\n            Color tempColor = Handles.color;\n            if (source.enabled)\n                Handles.color = new Color(0.50f, 0.70f, 1.00f, 0.5f);\n            else\n                Handles.color = new Color(0.30f, 0.40f, 0.60f, 0.5f);\n\n            Vector3 position = source.transform.position;\n\n            EditorGUI.BeginChangeCheck();\n            float minDistance = Handles.RadiusHandle(Quaternion.identity, position, source.minDistance, true);\n            float maxDistance = Handles.RadiusHandle(Quaternion.identity, position, source.maxDistance, true);\n            if (EditorGUI.EndChangeCheck())\n            {\n                Undo.RecordObject(source, \"AudioSource Distance\");\n                source.minDistance = minDistance;\n                source.maxDistance = maxDistance;\n            }\n\n            Handles.color = tempColor;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AutodeskInteractiveShaderGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class AutodeskInteractiveShaderGUI : ShaderGUI\n    {\n        public enum BlendMode\n        {\n            Opaque,\n            Cutout,\n            Fade,   // Old school alpha-blending mode, fresnel does not affect amount of transparency\n            Transparent // Physically plausible transparency mode, implemented as alpha pre-multiply\n        }\n\n        private static class Styles\n        {\n            public static GUIContent uvSetLabel = EditorGUIUtility.TrTextContent(\"UV Set\");\n\n            public static GUIContent albedoText = EditorGUIUtility.TrTextContent(\"Albedo\", \"Albedo (RGB) and Transparency (A)\");\n            public static GUIContent alphaCutoffText = EditorGUIUtility.TrTextContent(\"Alpha Cutoff\", \"Threshold for alpha cutoff\");\n            public static GUIContent metallicMapText = EditorGUIUtility.TrTextContent(\"Metallic\", \"Metallic (R) and Smoothness (A)\");\n            public static GUIContent roughnessText = EditorGUIUtility.TrTextContent(\"Roughness\", \"Roughness value\");\n            public static GUIContent highlightsText = EditorGUIUtility.TrTextContent(\"Specular Highlights\", \"Specular Highlights\");\n            public static GUIContent reflectionsText = EditorGUIUtility.TrTextContent(\"Reflections\", \"Glossy Reflections\");\n            public static GUIContent normalMapText = EditorGUIUtility.TrTextContent(\"Normal Map\", \"Normal Map\");\n            public static GUIContent heightMapText = EditorGUIUtility.TrTextContent(\"Height Map\", \"Height Map (G)\");\n            public static GUIContent occlusionText = EditorGUIUtility.TrTextContent(\"Occlusion\", \"Occlusion (G)\");\n            public static GUIContent emissionText = EditorGUIUtility.TrTextContent(\"Color\", \"Emission (RGB)\");\n            public static GUIContent detailMaskText = EditorGUIUtility.TrTextContent(\"Detail Mask\", \"Mask for Secondary Maps (A)\");\n            public static GUIContent detailAlbedoText = EditorGUIUtility.TrTextContent(\"Detail Albedo x2\", \"Albedo (RGB) multiplied by 2\");\n            public static GUIContent detailNormalMapText = EditorGUIUtility.TrTextContent(\"Normal Map\", \"Normal Map\");\n\n            public static string primaryMapsText = \"Main Maps\";\n            public static string secondaryMapsText = \"Secondary Maps\";\n            public static string forwardText = \"Forward Rendering Options\";\n            public static string renderingMode = \"Rendering Mode\";\n            public static string advancedText = \"Advanced Options\";\n            public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode));\n        }\n\n        MaterialProperty blendMode = null;\n        MaterialProperty albedoMap = null;\n        MaterialProperty albedoColor = null;\n        MaterialProperty alphaCutoff = null;\n        MaterialProperty metallicMap = null;\n        MaterialProperty metallic = null;\n        MaterialProperty roughness = null;\n        MaterialProperty roughnessMap = null;\n        MaterialProperty highlights = null;\n        MaterialProperty reflections = null;\n        MaterialProperty bumpScale = null;\n        MaterialProperty bumpMap = null;\n        MaterialProperty occlusionStrength = null;\n        MaterialProperty occlusionMap = null;\n        MaterialProperty heigtMapScale = null;\n        MaterialProperty heightMap = null;\n        MaterialProperty emissionColorForRendering = null;\n        MaterialProperty emissionMap = null;\n        MaterialProperty detailMask = null;\n        MaterialProperty detailAlbedoMap = null;\n        MaterialProperty detailNormalMapScale = null;\n        MaterialProperty detailNormalMap = null;\n        MaterialProperty uvSetSecondary = null;\n\n        MaterialEditor m_MaterialEditor;\n\n        public void FindProperties(MaterialProperty[] props)\n        {\n            blendMode = FindProperty(\"_Mode\", props);\n            albedoMap = FindProperty(\"_MainTex\", props);\n            albedoColor = FindProperty(\"_Color\", props);\n            alphaCutoff = FindProperty(\"_Cutoff\", props);\n            metallicMap = FindProperty(\"_MetallicGlossMap\", props, false);\n            metallic = FindProperty(\"_Metallic\", props, false);\n            roughness = FindProperty(\"_Glossiness\", props);\n            roughnessMap = FindProperty(\"_SpecGlossMap\", props);\n            highlights = FindProperty(\"_SpecularHighlights\", props, false);\n            reflections = FindProperty(\"_GlossyReflections\", props, false);\n            bumpScale = FindProperty(\"_BumpScale\", props);\n            bumpMap = FindProperty(\"_BumpMap\", props);\n            heigtMapScale = FindProperty(\"_Parallax\", props);\n            heightMap = FindProperty(\"_ParallaxMap\", props);\n            occlusionStrength = FindProperty(\"_OcclusionStrength\", props);\n            occlusionMap = FindProperty(\"_OcclusionMap\", props);\n            emissionColorForRendering = FindProperty(\"_EmissionColor\", props);\n            emissionMap = FindProperty(\"_EmissionMap\", props);\n            detailMask = FindProperty(\"_DetailMask\", props);\n            detailAlbedoMap = FindProperty(\"_DetailAlbedoMap\", props);\n            detailNormalMapScale = FindProperty(\"_DetailNormalMapScale\", props);\n            detailNormalMap = FindProperty(\"_DetailNormalMap\", props);\n            uvSetSecondary = FindProperty(\"_UVSec\", props);\n        }\n\n        public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)\n        {\n            FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly\n            m_MaterialEditor = materialEditor;\n            Material material = materialEditor.target as Material;\n\n            ShaderPropertiesGUI(material);\n        }\n\n        public void ShaderPropertiesGUI(Material material)\n        {\n            // Use default labelWidth\n            EditorGUIUtility.labelWidth = 0f;\n\n            {\n                BlendModePopup();\n\n                // Primary properties\n                GUILayout.Label(Styles.primaryMapsText, EditorStyles.boldLabel);\n                DoAlbedoArea(material);\n                m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap, metallicMap.textureValue != null ? null : metallic);\n                m_MaterialEditor.TexturePropertySingleLine(Styles.roughnessText, roughnessMap, roughnessMap.textureValue != null ? null : roughness);\n                m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null);\n                m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightMap.textureValue != null ? heigtMapScale : null);\n                m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null);\n                m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask);\n                DoEmissionArea(material);\n                EditorGUI.BeginChangeCheck();\n                m_MaterialEditor.TextureScaleOffsetProperty(albedoMap);\n                if (EditorGUI.EndChangeCheck())\n                    emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake\n\n                EditorGUILayout.Space();\n\n                // Secondary properties\n                GUILayout.Label(Styles.secondaryMapsText, EditorStyles.boldLabel);\n                m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlbedoText, detailAlbedoMap);\n                m_MaterialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale);\n                m_MaterialEditor.TextureScaleOffsetProperty(detailAlbedoMap);\n                m_MaterialEditor.ShaderProperty(uvSetSecondary, Styles.uvSetLabel.text);\n\n                // Third properties\n                GUILayout.Label(Styles.forwardText, EditorStyles.boldLabel);\n                if (highlights != null)\n                    m_MaterialEditor.ShaderProperty(highlights, Styles.highlightsText);\n                if (reflections != null)\n                    m_MaterialEditor.ShaderProperty(reflections, Styles.reflectionsText);\n            }\n\n            EditorGUILayout.Space();\n\n            // NB renderqueue editor is not shown on purpose: we want to override it based on blend mode\n            GUILayout.Label(Styles.advancedText, EditorStyles.boldLabel);\n            m_MaterialEditor.EnableInstancingField();\n            m_MaterialEditor.DoubleSidedGIField();\n        }\n\n        public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)\n        {\n            // _Emission property is lost after assigning Standard shader to the material\n            // thus transfer it before assigning the new shader\n            if (material.HasProperty(\"_Emission\"))\n            {\n                material.SetColor(\"_EmissionColor\", material.GetColor(\"_Emission\"));\n            }\n\n            base.AssignNewShaderToMaterial(material, oldShader, newShader);\n\n            if (oldShader == null || !oldShader.name.Contains(\"Legacy Shaders/\"))\n            {\n                SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat(\"_Mode\"));\n                return;\n            }\n\n            BlendMode blendMode = BlendMode.Opaque;\n            if (oldShader.name.Contains(\"/Transparent/Cutout/\"))\n            {\n                blendMode = BlendMode.Cutout;\n            }\n            else if (oldShader.name.Contains(\"/Transparent/\"))\n            {\n                // NOTE: legacy shaders did not provide physically based transparency\n                // therefore Fade mode\n                blendMode = BlendMode.Fade;\n            }\n            material.SetFloat(\"_Mode\", (float)blendMode);\n\n            SetupMaterialWithBlendMode(material, blendMode);\n        }\n\n        void BlendModePopup()\n        {\n            MaterialEditor.BeginProperty(blendMode);\n            var mode = (BlendMode)blendMode.floatValue;\n\n            EditorGUI.BeginChangeCheck();\n            mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_MaterialEditor.RegisterPropertyChangeUndo(\"Rendering Mode\");\n                blendMode.floatValue = (float)mode;\n            }\n\n            MaterialEditor.EndProperty();\n        }\n\n        void DoAlbedoArea(Material material)\n        {\n            m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor);\n            if (((BlendMode)material.GetFloat(\"_Mode\") == BlendMode.Cutout))\n            {\n                m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);\n            }\n        }\n\n        void DoEmissionArea(Material material)\n        {\n            // Emission for GI?\n            if (m_MaterialEditor.EmissionEnabledProperty())\n            {\n                bool hadEmissionTexture = emissionMap.textureValue != null;\n\n                // Texture and HDR color controls\n                m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, false);\n\n                // If texture was assigned and color was black set color to white\n                float brightness = emissionColorForRendering.colorValue.maxColorComponent;\n                if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f)\n                    emissionColorForRendering.colorValue = Color.white;\n\n                // change the GI flag and fix it up with emissive as black if necessary\n                m_MaterialEditor.LightmapEmissionFlagsProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel, true);\n            }\n        }\n\n        public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode)\n        {\n            switch (blendMode)\n            {\n                case BlendMode.Opaque:\n                    material.SetOverrideTag(\"RenderType\", \"\");\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.One);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.Zero);\n                    material.SetFloat(\"_ZWrite\", 1.0f);\n                    material.DisableKeyword(\"_ALPHATEST_ON\");\n                    material.DisableKeyword(\"_ALPHABLEND_ON\");\n                    material.DisableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    material.renderQueue = -1;\n                    break;\n                case BlendMode.Cutout:\n                    material.SetOverrideTag(\"RenderType\", \"TransparentCutout\");\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.One);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.Zero);\n                    material.SetFloat(\"_ZWrite\", 1.0f);\n                    material.EnableKeyword(\"_ALPHATEST_ON\");\n                    material.DisableKeyword(\"_ALPHABLEND_ON\");\n                    material.DisableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;\n                    break;\n                case BlendMode.Fade:\n                    material.SetOverrideTag(\"RenderType\", \"Transparent\");\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);\n                    material.SetFloat(\"_ZWrite\", 0.0f);\n                    material.DisableKeyword(\"_ALPHATEST_ON\");\n                    material.EnableKeyword(\"_ALPHABLEND_ON\");\n                    material.DisableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;\n                    break;\n                case BlendMode.Transparent:\n                    material.SetOverrideTag(\"RenderType\", \"Transparent\");\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.One);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);\n                    material.SetFloat(\"_ZWrite\", 0.0f);\n                    material.DisableKeyword(\"_ALPHATEST_ON\");\n                    material.DisableKeyword(\"_ALPHABLEND_ON\");\n                    material.EnableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;\n                    break;\n            }\n        }\n\n        static void SetMaterialKeywords(Material material)\n        {\n            // Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation\n            // (MaterialProperty value might come from renderer material property block)\n            SetKeyword(material, \"_NORMALMAP\", material.GetTexture(\"_BumpMap\") || material.GetTexture(\"_DetailNormalMap\"));\n            SetKeyword(material, \"_SPECGLOSSMAP\", material.GetTexture(\"_SpecGlossMap\"));\n            SetKeyword(material, \"_METALLICGLOSSMAP\", material.GetTexture(\"_MetallicGlossMap\"));\n            SetKeyword(material, \"_PARALLAXMAP\", material.GetTexture(\"_ParallaxMap\"));\n            SetKeyword(material, \"_DETAIL_MULX2\", material.GetTexture(\"_DetailAlbedoMap\") || material.GetTexture(\"_DetailNormalMap\"));\n\n            // A material's GI flag internally keeps track of whether emission is enabled at all, it's enabled but has no effect\n            // or is enabled and may be modified at runtime. This state depends on the values of the current flag and emissive color.\n            // The fixup routine makes sure that the material is in the correct state if/when changes are made to the mode or color.\n            MaterialEditor.FixupEmissiveFlag(material);\n            bool shouldEmissionBeEnabled = (material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0;\n            SetKeyword(material, \"_EMISSION\", shouldEmissionBeEnabled);\n        }\n\n        override public void ValidateMaterial(Material material)\n        {\n            SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat(\"_Mode\"));\n\n            SetMaterialKeywords(material);\n        }\n\n        static void SetKeyword(Material m, string keyword, bool state)\n        {\n            if (state)\n                m.EnableKeyword(keyword);\n            else\n                m.DisableKeyword(keyword);\n        }\n    }\n} // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/Inspector/Avatar/AvatarAutoMapper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing System.Globalization;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class AvatarAutoMapper\n    {\n        private enum Side { None, Left, Right }\n\n        private struct BoneMappingItem\n        {\n            public int parent;\n            public int bone;\n            public int minStep;\n            public int maxStep;\n            public float lengthRatio;\n            public Vector3 dir;\n            public Side side;\n            public bool optional;\n            public bool alwaysInclude;\n            public string[] keywords;\n            private int[] children;\n\n            public BoneMappingItem(int parent, int bone, int minStep, int maxStep, float lengthRatio, Vector3 dir, Side side, bool optional, bool alwaysInclude, params string[] keywords)\n            {\n                this.parent = parent;\n                this.bone = bone;\n                this.minStep = minStep;\n                this.maxStep = maxStep;\n                this.lengthRatio = lengthRatio;\n                this.dir = dir;\n                this.side = side;\n                this.optional = optional;\n                this.alwaysInclude = alwaysInclude;\n                this.keywords = keywords;\n                this.children = null;\n            }\n\n            public BoneMappingItem(int parent, int bone, int minStep, int maxStep, float lengthRatio, Side side, bool optional, bool alwaysInclude, params string[] keywords)\n                : this(parent, bone, minStep, maxStep, lengthRatio, Vector3.zero, side, optional, alwaysInclude, keywords) {}\n\n            public BoneMappingItem(int parent, int bone, int minStep, int maxStep, float lengthRatio, Vector3 dir, Side side, params string[] keywords)\n                : this(parent, bone, minStep, maxStep, lengthRatio, dir, side, false, false, keywords) {}\n\n            public BoneMappingItem(int parent, int bone, int minStep, int maxStep, float lengthRatio, Side side, params string[] keywords)\n                : this(parent, bone, minStep, maxStep, lengthRatio, Vector3.zero, side, false, false, keywords) {}\n\n            public int[] GetChildren(BoneMappingItem[] mappingData)\n            {\n                if (children == null)\n                {\n                    List<int> list = new List<int>();\n                    for (int i = 0; i < mappingData.Length; i++)\n                        if (mappingData[i].parent == bone)\n                            list.Add(i);\n                    children = list.ToArray();\n                }\n                return children;\n            }\n        }\n\n        private class BoneMatch : IComparable<BoneMatch>\n        {\n            public BoneMatch parent;\n            public List<BoneMatch> children = new List<BoneMatch>();\n            public bool doMap = false;\n            public BoneMatch humanBoneParent\n            {\n                get\n                {\n                    BoneMatch p = parent;\n                    while (p.parent != null && (p.item.bone < 0))\n                        p = p.parent;\n                    return p;\n                }\n            }\n            public BoneMappingItem item;\n            public Transform bone;\n            public float score;\n            public float siblingScore;\n            public float totalSiblingScore { get { return score + siblingScore; } }\n            public List<string> debugTracker = new List<string>();\n            public BoneMatch(BoneMatch parent, Transform bone, BoneMappingItem item)\n            {\n                this.parent = parent;\n                this.bone = bone;\n                this.item = item;\n            }\n\n            public int CompareTo(BoneMatch other)\n            {\n                if (other == null)\n                    return 1;\n                return other.totalSiblingScore.CompareTo(totalSiblingScore);\n            }\n        }\n\n        private struct QueuedBone\n        {\n            public Transform bone;\n            public int level;\n            public QueuedBone(Transform bone, int level) { this.bone = bone; this.level = level; }\n        }\n\n        private static bool kDebug = false;\n\n        private static string[] kShoulderKeywords = {\"shoulder\", \"collar\", \"clavicle\"};\n        private static string[] kUpperArmKeywords = {\"up\"};\n        private static string[] kLowerArmKeywords = {\"lo\", \"fore\", \"elbow\"};\n        private static string[] kHandKeywords = {\"hand\", \"wrist\"};\n\n        private static string[] kUpperLegKeywords = {\"up\", \"thigh\"};\n        private static string[] kLowerLegKeywords = {\"lo\", \"calf\", \"knee\", \"shin\"};\n        private static string[] kFootKeywords = {\"foot\", \"ankle\"};\n        private static string[] kToeKeywords = {\"toe\", \"!end\", \"!top\", \"!nub\"};\n\n        private static string[] kNeckKeywords = {\"neck\"};\n        private static string[] kHeadKeywords = {\"head\"};\n        private static string[] kJawKeywords = {\"jaw\", \"open\", \"!teeth\", \"!tongue\", \"!pony\", \"!braid\", \"!end\", \"!top\", \"!nub\"};\n        private static string[] kEyeKeywords = {\"eye\", \"ball\", \"!brow\", \"!lid\", \"!pony\", \"!braid\", \"!end\", \"!top\", \"!nub\"};\n\n        private static string[] kThumbKeywords =        {\"thu\",          \"!palm\", \"!wrist\", \"!end\", \"!top\", \"!nub\"};\n        private static string[] kIndexFingerKeywords =  {\"ind\", \"point\", \"!palm\", \"!wrist\", \"!end\", \"!top\", \"!nub\"};\n        private static string[] kMiddleFingerKeywords = {\"mid\", \"long\",  \"!palm\", \"!wrist\", \"!end\", \"!top\", \"!nub\"};\n        private static string[] kRingFingerKeywords =   {\"rin\",          \"!palm\", \"!wrist\", \"!end\", \"!top\", \"!nub\"};\n        private static string[] kLittleFingerKeywords = {\"lit\", \"pin\",   \"!palm\", \"!wrist\", \"!end\", \"!top\", \"!nub\"};\n\n        private static BoneMappingItem[] s_MappingDataBody = new BoneMappingItem[]\n        {\n            new BoneMappingItem(-1,                                (int)HumanBodyBones.Hips,           1, 3, 0.0f, Side.None),\n\n            new BoneMappingItem((int)HumanBodyBones.Hips,          (int)HumanBodyBones.RightUpperLeg,  1, 2, 0.0f, Vector3.right, Side.Right, kUpperLegKeywords),\n            new BoneMappingItem((int)HumanBodyBones.RightUpperLeg, (int)HumanBodyBones.RightLowerLeg,  1, 2, 3.0f, -Vector3.up, Side.Right, kLowerLegKeywords),\n            new BoneMappingItem((int)HumanBodyBones.RightLowerLeg, (int)HumanBodyBones.RightFoot,      1, 2, 1.0f, -Vector3.up, Side.Right, kFootKeywords),\n            new BoneMappingItem((int)HumanBodyBones.RightFoot,     (int)HumanBodyBones.RightToes,      1, 2, 0.5f, Vector3.forward, Side.Right, true, true, kToeKeywords),\n\n            new BoneMappingItem((int)HumanBodyBones.Hips,          (int)HumanBodyBones.Spine,          1, 3, 0.0f, Vector3.up, Side.None),\n            new BoneMappingItem((int)HumanBodyBones.Spine,         (int)HumanBodyBones.Chest,          0, 3, 1.4f, Vector3.up, Side.None, true, false),\n            new BoneMappingItem((int)HumanBodyBones.Chest,         (int)HumanBodyBones.UpperChest,     0, 3, 1.4f, Vector3.up, Side.None, true, false),\n\n            new BoneMappingItem((int)HumanBodyBones.UpperChest,    (int)HumanBodyBones.RightShoulder,  1, 3, 0.0f, Vector3.right, Side.Right, true, false, kShoulderKeywords),\n            new BoneMappingItem((int)HumanBodyBones.RightShoulder, (int)HumanBodyBones.RightUpperArm,  0, 2, 0.5f, Vector3.right, Side.Right, kUpperArmKeywords),\n            new BoneMappingItem((int)HumanBodyBones.RightUpperArm, (int)HumanBodyBones.RightLowerArm,  1, 2, 2.0f, Vector3.right, Side.Right, kLowerArmKeywords),\n            new BoneMappingItem((int)HumanBodyBones.RightLowerArm, (int)HumanBodyBones.RightHand,      1, 2, 1.0f, Vector3.right, Side.Right, kHandKeywords),\n\n            new BoneMappingItem((int)HumanBodyBones.UpperChest,    (int)HumanBodyBones.Neck,           1, 3, 1.8f, Vector3.up, Side.None, true, false, kNeckKeywords),\n            new BoneMappingItem((int)HumanBodyBones.Neck,          (int)HumanBodyBones.Head,           0, 2, 0.3f, Vector3.up, Side.None, kHeadKeywords),\n\n            new BoneMappingItem((int)HumanBodyBones.Head,          (int)HumanBodyBones.Jaw,            1, 2, 0.0f, Vector3.forward, Side.None, true, false, kJawKeywords),\n            new BoneMappingItem((int)HumanBodyBones.Head,          (int)HumanBodyBones.RightEye,       1, 2, 0.0f, new Vector3(1, 1, 1), Side.Right, true, false, kEyeKeywords),\n\n            new BoneMappingItem((int)HumanBodyBones.RightHand,     -2,     1, 2, 0.0f, new Vector3(1, -1, 2), Side.Right, true, false, kThumbKeywords),\n            new BoneMappingItem((int)HumanBodyBones.RightHand,     -3,     1, 2, 0.0f, new Vector3(3, 0, 1), Side.Right, true, false, kIndexFingerKeywords),\n        };\n\n        private static BoneMappingItem[] s_LeftMappingDataHand = new BoneMappingItem[]\n        {\n            new BoneMappingItem(-2,                                        -1,                                         1, 2, 0.0f, Side.None),\n\n            new BoneMappingItem(-1,                                        (int)HumanBodyBones.LeftThumbProximal,      1, 3, 0.0f, new Vector3(2, 0, 1), Side.None, kThumbKeywords),\n            new BoneMappingItem(-1,                                        (int)HumanBodyBones.LeftIndexProximal,      1, 3, 0.0f, new Vector3(4, 0, 1), Side.None, kIndexFingerKeywords),\n            new BoneMappingItem(-1,                                        (int)HumanBodyBones.LeftMiddleProximal,     1, 3, 0.0f, new Vector3(4, 0, 0), Side.None, kMiddleFingerKeywords),\n            new BoneMappingItem(-1,                                        (int)HumanBodyBones.LeftRingProximal,       1, 3, 0.0f, new Vector3(4, 0, -1), Side.None, kRingFingerKeywords),\n            new BoneMappingItem(-1,                                        (int)HumanBodyBones.LeftLittleProximal,     1, 3, 0.0f, new Vector3(4, 0, -2), Side.None, kLittleFingerKeywords),\n\n            new BoneMappingItem((int)HumanBodyBones.LeftThumbProximal,     (int)HumanBodyBones.LeftThumbIntermediate,  1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.LeftIndexProximal,     (int)HumanBodyBones.LeftIndexIntermediate,  1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.LeftMiddleProximal,    (int)HumanBodyBones.LeftMiddleIntermediate, 1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.LeftRingProximal,      (int)HumanBodyBones.LeftRingIntermediate,   1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.LeftLittleProximal,    (int)HumanBodyBones.LeftLittleIntermediate, 1, 1, 0.0f, Side.None, false, true),\n\n            new BoneMappingItem((int)HumanBodyBones.LeftThumbIntermediate, (int)HumanBodyBones.LeftThumbDistal,        1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.LeftIndexIntermediate, (int)HumanBodyBones.LeftIndexDistal,        1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.LeftMiddleIntermediate, (int)HumanBodyBones.LeftMiddleDistal,       1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.LeftRingIntermediate,  (int)HumanBodyBones.LeftRingDistal,         1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.LeftLittleIntermediate, (int)HumanBodyBones.LeftLittleDistal,       1, 1, 0.0f, Side.None, false, true),\n        };\n\n        private static BoneMappingItem[] s_RightMappingDataHand = new BoneMappingItem[]\n        {\n            new BoneMappingItem(-2,                                        -1,                                         1, 2, 0.0f, Side.None),\n\n            new BoneMappingItem(-1,                                            (int)HumanBodyBones.RightThumbProximal,     1, 3, 0.0f, new Vector3(2, 0, 1), Side.None, kThumbKeywords),\n            new BoneMappingItem(-1,                                            (int)HumanBodyBones.RightIndexProximal,     1, 3, 0.0f, new Vector3(4, 0, 1), Side.None, kIndexFingerKeywords),\n            new BoneMappingItem(-1,                                            (int)HumanBodyBones.RightMiddleProximal,    1, 3, 0.0f, new Vector3(4, 0, 0), Side.None, kMiddleFingerKeywords),\n            new BoneMappingItem(-1,                                            (int)HumanBodyBones.RightRingProximal,      1, 3, 0.0f, new Vector3(4, 0, -1), Side.None, kRingFingerKeywords),\n            new BoneMappingItem(-1,                                            (int)HumanBodyBones.RightLittleProximal,    1, 3, 0.0f, new Vector3(4, 0, -2), Side.None, kLittleFingerKeywords),\n\n            new BoneMappingItem((int)HumanBodyBones.RightThumbProximal,        (int)HumanBodyBones.RightThumbIntermediate, 1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.RightIndexProximal,        (int)HumanBodyBones.RightIndexIntermediate, 1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.RightMiddleProximal,       (int)HumanBodyBones.RightMiddleIntermediate, 1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.RightRingProximal,         (int)HumanBodyBones.RightRingIntermediate,  1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.RightLittleProximal,       (int)HumanBodyBones.RightLittleIntermediate, 1, 1, 0.0f, Side.None, false, true),\n\n            new BoneMappingItem((int)HumanBodyBones.RightThumbIntermediate,    (int)HumanBodyBones.RightThumbDistal,       1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.RightIndexIntermediate,    (int)HumanBodyBones.RightIndexDistal,       1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.RightMiddleIntermediate,   (int)HumanBodyBones.RightMiddleDistal,      1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.RightRingIntermediate,     (int)HumanBodyBones.RightRingDistal,        1, 1, 0.0f, Side.None, false, true),\n            new BoneMappingItem((int)HumanBodyBones.RightLittleIntermediate,   (int)HumanBodyBones.RightLittleDistal,      1, 1, 0.0f, Side.None, false, true),\n        };\n\n        private static bool s_DidPerformInit = false;\n\n        private Dictionary<Transform, bool> m_ValidBones;\n        private bool m_TreatDummyBonesAsReal = false;\n\n        private Quaternion m_Orientation;\n        private int m_MappingIndexOffset = 0;\n        private BoneMappingItem[] m_MappingData;\n\n        private Dictionary<string, int> m_BoneHasKeywordDict;\n        private Dictionary<string, int> m_BoneHasBadKeywordDict;\n        private Dictionary<int, BoneMatch> m_BoneMatchDict;\n\n        private static int GetLeftBoneIndexFromRight(int rightIndex)\n        {\n            if (rightIndex < 0)\n            {\n                return rightIndex;\n            }\n            else if (rightIndex < (int)HumanBodyBones.LastBone)\n            {\n                string name = Enum.GetName(typeof(HumanBodyBones), rightIndex);\n                name = name.Replace(\"Right\", \"Left\");\n                return (int)(HumanBodyBones)Enum.Parse(typeof(HumanBodyBones), name);\n            }\n\n            return -1;\n        }\n\n        public static void InitGlobalMappingData()\n        {\n            if (s_DidPerformInit)\n                return;\n\n            List<BoneMappingItem> mappingData = new List<BoneMappingItem>(s_MappingDataBody);\n\n            // Add left side bones to match right side ones.\n            int size = mappingData.Count;\n            for (int i = 0; i < size; i++)\n            {\n                BoneMappingItem item = mappingData[i];\n                if (item.side == Side.Right)\n                {\n                    // Get left HumanBodyBones that mirrors right one.\n                    int bone = GetLeftBoneIndexFromRight(item.bone);\n                    // Get left parent HumanBodyBones that mirrors parent of right one\n                    int parentBone = GetLeftBoneIndexFromRight(item.parent);\n                    // Add left BoneMappingItem that mirrors right one.\n                    mappingData.Add(new BoneMappingItem(parentBone, bone, item.minStep, item.maxStep, item.lengthRatio, new Vector3(-item.dir.x, item.dir.y, item.dir.z), Side.Left, item.optional, item.alwaysInclude, item.keywords));\n                }\n            }\n\n            s_MappingDataBody = mappingData.ToArray();\n\n            // Cache children for each BoneMappingItem\n            for (int i = 0; i < s_MappingDataBody.Length; i++)\n                s_MappingDataBody[i].GetChildren(s_MappingDataBody);\n            for (int i = 0; i < s_LeftMappingDataHand.Length; i++)\n                s_LeftMappingDataHand[i].GetChildren(s_LeftMappingDataHand);\n            for (int i = 0; i < s_RightMappingDataHand.Length; i++)\n                s_RightMappingDataHand[i].GetChildren(s_RightMappingDataHand);\n\n            s_DidPerformInit = true;\n        }\n\n        public static Dictionary<int, Transform> MapBones(Transform root, Dictionary<Transform, bool> validBones)\n        {\n            AvatarAutoMapper mapper = new AvatarAutoMapper(validBones);\n            return mapper.MapBones(root);\n        }\n\n        public AvatarAutoMapper(Dictionary<Transform, bool> validBones)\n        {\n            m_BoneHasKeywordDict = new Dictionary<string, int>();\n            m_BoneHasBadKeywordDict = new Dictionary<string, int>();\n            m_BoneMatchDict = new Dictionary<int, BoneMatch>();\n            m_ValidBones = validBones;\n        }\n\n        public Dictionary<int, Transform> MapBones(Transform root)\n        {\n            InitGlobalMappingData();\n\n            Dictionary<int, Transform> mapping = new Dictionary<int, Transform>();\n\n            // Perform body mapping\n            {\n                m_Orientation = Quaternion.identity;\n                m_MappingData = s_MappingDataBody;\n                m_MappingIndexOffset = 0;\n                m_BoneMatchDict.Clear();\n                BoneMatch rootMatch = new BoneMatch(null, root, m_MappingData[0]);\n\n                m_TreatDummyBonesAsReal = false;\n                MapBonesFromRootDown(rootMatch, mapping);\n                // There are 15 required bones. If we mapped less than that, check if we can do better.\n                if (mapping.Count < 15)\n                {\n                    m_TreatDummyBonesAsReal = true;\n                    MapBonesFromRootDown(rootMatch, mapping);\n                }\n\n                // Check if character has correct alignment\n                if (mapping.ContainsKey((int)HumanBodyBones.LeftUpperLeg) && mapping.ContainsKey((int)HumanBodyBones.RightUpperLeg) &&\n                    mapping.ContainsKey((int)HumanBodyBones.LeftUpperArm) && mapping.ContainsKey((int)HumanBodyBones.RightUpperArm))\n                {\n                    m_Orientation = AvatarSetupTool.AvatarComputeOrientation(\n                        mapping[(int)HumanBodyBones.LeftUpperLeg].position, mapping[(int)HumanBodyBones.RightUpperLeg].position,\n                        mapping[(int)HumanBodyBones.LeftUpperArm].position, mapping[(int)HumanBodyBones.RightUpperArm].position);\n\n                    // If not standard aligned, try to map again with correct alignment assumptions\n                    if (Vector3.Angle(m_Orientation * Vector3.up, Vector3.up) > 20 || Vector3.Angle(m_Orientation * Vector3.forward, Vector3.forward) > 20)\n                    {\n                        if (kDebug)\n                            Debug.Log(\"*** Mapping with new computed orientation\");\n                        mapping.Clear();\n                        m_BoneMatchDict.Clear();\n                        MapBonesFromRootDown(rootMatch, mapping);\n                    }\n                }\n\n                // For models that don't have meshes, all bones are marked valid; even the root.\n                // So we use this to check if this model has meshes or not.\n                bool modelHasMeshes = !(m_ValidBones.ContainsKey(root) && m_ValidBones[root] == true);\n\n                // Fix up hips to be valid bone closest to the root\n                // For models with meshes, valid bones further up are mapped to part of the mesh (otherwise they wouldn't be valid).\n                // For models with no meshes we don't know which transforms are valid bones and which aren't\n                // so we skip this step and use the found hips bone as-is.\n                if (modelHasMeshes && mapping.Count > 0 && mapping.ContainsKey((int)HumanBodyBones.Hips))\n                {\n                    while (true)\n                    {\n                        Transform parent = mapping[(int)HumanBodyBones.Hips].parent;\n                        if (parent != null && parent != rootMatch.bone && m_ValidBones.ContainsKey(parent) && m_ValidBones[parent] == true)\n                            mapping[(int)HumanBodyBones.Hips] = parent;\n                        else\n                            break;\n                    }\n                }\n\n                // Move upper chest to chest if no chest was found\n                if (!mapping.ContainsKey((int)HumanBodyBones.Chest) &&\n                    mapping.ContainsKey((int)HumanBodyBones.UpperChest))\n                {\n                    mapping.Add((int)HumanBodyBones.Chest, mapping[(int)HumanBodyBones.UpperChest]);\n                    mapping.Remove((int)HumanBodyBones.UpperChest);\n                }\n            }\n\n            int kMinFingerBones = 3;\n\n            Quaternion bodyOrientation = m_Orientation;\n\n            // Perform left hand mapping\n            if (mapping.ContainsKey((int)HumanBodyBones.LeftHand))\n            {\n                Transform lowerArm = mapping[(int)HumanBodyBones.LeftLowerArm];\n                Transform hand = mapping[(int)HumanBodyBones.LeftHand];\n\n                // Use reference orientation based on lower arm for mapping hand\n                m_Orientation = Quaternion.FromToRotation(bodyOrientation * -Vector3.right, hand.position - lowerArm.position) * bodyOrientation;\n\n                m_MappingData = s_LeftMappingDataHand;\n                m_MappingIndexOffset = (int)HumanBodyBones.LeftThumbProximal;\n                m_BoneMatchDict.Clear();\n                BoneMatch rootMatch = new BoneMatch(null, lowerArm, m_MappingData[0]);\n                m_TreatDummyBonesAsReal = true;\n\n                int mappingCountBefore = mapping.Count;\n                MapBonesFromRootDown(rootMatch, mapping);\n\n                // If we only mapped 2 finger bones or less, then cancel mapping of fingers\n                if (mapping.Count < mappingCountBefore + kMinFingerBones)\n                {\n                    for (int i = (int)HumanBodyBones.LeftThumbProximal; i <= (int)HumanBodyBones.LeftLittleDistal; i++)\n                        mapping.Remove(i);\n                }\n            }\n\n            // Perform right hand mapping\n            if (mapping.ContainsKey((int)HumanBodyBones.RightHand))\n            {\n                Transform lowerArm = mapping[(int)HumanBodyBones.RightLowerArm];\n                Transform hand = mapping[(int)HumanBodyBones.RightHand];\n\n                // Use reference orientation based on lower arm for mapping hand\n                m_Orientation = Quaternion.FromToRotation(bodyOrientation * Vector3.right, hand.position - lowerArm.position) * bodyOrientation;\n\n                m_MappingData = s_RightMappingDataHand;\n                m_MappingIndexOffset = (int)HumanBodyBones.RightThumbProximal;\n                m_BoneMatchDict.Clear();\n                BoneMatch rootMatch = new BoneMatch(null, lowerArm, m_MappingData[0]);\n                m_TreatDummyBonesAsReal = true;\n\n                int mappingCountBefore = mapping.Count;\n                MapBonesFromRootDown(rootMatch, mapping);\n\n                // If we only mapped 2 finger bones or less, then cancel mapping of fingers\n                if (mapping.Count < mappingCountBefore + kMinFingerBones)\n                {\n                    for (int i = (int)HumanBodyBones.RightThumbProximal; i <= (int)HumanBodyBones.RightLittleDistal; i++)\n                        mapping.Remove(i);\n                }\n            }\n\n            return mapping;\n        }\n\n        private void MapBonesFromRootDown(BoneMatch rootMatch, Dictionary<int, Transform> mapping)\n        {\n            // Perform mapping\n            List<BoneMatch> childMatches = RecursiveFindPotentialBoneMatches(rootMatch, m_MappingData[0], true);\n            if (childMatches != null && childMatches.Count > 0)\n            {\n                if (kDebug)\n                {\n                    EvaluateBoneMatch(childMatches[0], true);\n                }\n                ApplyMapping(childMatches[0], mapping);\n            }\n        }\n\n        private void ApplyMapping(BoneMatch match, Dictionary<int, Transform> mapping)\n        {\n            if (match.doMap)\n                mapping[match.item.bone] = match.bone;\n            foreach (BoneMatch child in match.children)\n                ApplyMapping(child, mapping);\n        }\n\n        private string GetStrippedAndNiceBoneName(Transform bone)\n        {\n            string[] strings = bone.name.Split(':');\n            return ObjectNames.NicifyVariableName(strings[strings.Length - 1]);\n        }\n\n        private int BoneHasBadKeyword(Transform bone, params string[] keywords)\n        {\n            string key = bone.GetInstanceID() + \":\" + String.Concat(keywords);\n            if (m_BoneHasBadKeywordDict.ContainsKey(key))\n                return m_BoneHasBadKeywordDict[key];\n\n            int score = 0;\n            string boneName;\n\n            // If parent transform has any of keywords, don't accept.\n            Transform parent = bone.parent;\n            while (parent.parent != null && m_ValidBones.ContainsKey(parent) && !m_ValidBones[parent])\n                parent = parent.parent;\n            boneName = GetStrippedAndNiceBoneName(parent).ToLower();\n            foreach (string word in keywords)\n                if (word[0] != '!' && boneName.Contains(word))\n                {\n                    score = -20;\n                    m_BoneHasBadKeywordDict[key] = score;\n                    return score;\n                }\n\n            // If this transform has any of the illegal keywords, don't accept.\n            boneName = GetStrippedAndNiceBoneName(bone).ToLower();\n            foreach (string word in keywords)\n                if (word[0] == '!' && boneName.Contains(word.Substring(1)))\n                {\n                    score = -1000;\n                    m_BoneHasBadKeywordDict[key] = score;\n                    return score;\n                }\n\n            m_BoneHasBadKeywordDict[key] = score;\n            return score;\n        }\n\n        private int BoneHasKeyword(Transform bone, params string[] keywords)\n        {\n            string key = bone.GetInstanceID() + \":\" + String.Concat(keywords);\n            if (m_BoneHasKeywordDict.ContainsKey(key))\n                return m_BoneHasKeywordDict[key];\n\n            int score = 0;\n\n            // If this transform has any of the keywords, accept.\n            string boneName = GetStrippedAndNiceBoneName(bone).ToLower();\n            foreach (string word in keywords)\n                if (word[0] != '!' && boneName.Contains(word))\n                {\n                    score = 20;\n                    m_BoneHasKeywordDict[key] = score;\n                    return score;\n                }\n\n            m_BoneHasKeywordDict[key] = score;\n            return score;\n        }\n\n        private const string kLeftMatch  = @\"(^|.*[ \\.:_-])[lL]($|[ \\.:_-].*)\";\n        private const string kRightMatch = @\"(^|.*[ \\.:_-])[rR]($|[ \\.:_-].*)\";\n        private bool MatchesSideKeywords(string boneName, bool left)\n        {\n            if (boneName.ToLower().Contains(left ? \"left\" : \"right\"))\n                return true;\n\n            if (System.Text.RegularExpressions.Regex.Match(boneName, left ? kLeftMatch : kRightMatch).Length > 0)\n                return true;\n\n            return false;\n        }\n\n        private int GetBoneSideMatchPoints(BoneMatch match)\n        {\n            string boneName = match.bone.name;\n            if (match.item.side == Side.None)\n                if (MatchesSideKeywords(boneName, false) || MatchesSideKeywords(boneName, true))\n                    return -1000;\n\n            bool left = (match.item.side == Side.Left);\n            if (MatchesSideKeywords(boneName, left))\n                return 15;\n            if (MatchesSideKeywords(boneName, !left))\n                return -1000;\n\n            return 0;\n        }\n\n        private int GetMatchKey(BoneMatch parentMatch, Transform t, BoneMappingItem goalItem)\n        {\n            SimpleProfiler.Begin(\"GetMatchKey\");\n            int key = goalItem.bone;\n            key += t.GetInstanceID() * 1000;\n            if (parentMatch != null)\n            {\n                key += parentMatch.bone.GetInstanceID() * 1000000;\n                if (parentMatch.parent != null)\n                    key += parentMatch.parent.bone.GetInstanceID() * 1000000000;\n            }\n            SimpleProfiler.End();\n            return key;\n        }\n\n        // Returns possible matches sorted with best-scoring ones first in the list\n        private List<BoneMatch> RecursiveFindPotentialBoneMatches(BoneMatch parentMatch, BoneMappingItem goalItem, bool confirmedChoice)\n        {\n            List<BoneMatch> matches = new List<BoneMatch>();\n\n            // We want to search with breadh first search so we have to use a queue\n            Queue<QueuedBone> queue = new Queue<QueuedBone>();\n\n            // Find matches\n            queue.Enqueue(new QueuedBone(parentMatch.bone, 0));\n            while (queue.Count > 0)\n            {\n                QueuedBone current = queue.Dequeue();\n                Transform t = current.bone;\n                if (current.level >= goalItem.minStep && (m_TreatDummyBonesAsReal || m_ValidBones == null || (m_ValidBones.ContainsKey(t) && m_ValidBones[t])))\n                {\n                    BoneMatch match;\n                    var key = GetMatchKey(parentMatch, t, goalItem);\n                    if (m_BoneMatchDict.ContainsKey(key))\n                    {\n                        match = m_BoneMatchDict[key];\n                    }\n                    else\n                    {\n                        match = new BoneMatch(parentMatch, t, goalItem);\n\n                        // RECURSIVE CALL\n                        EvaluateBoneMatch(match, false);\n                        m_BoneMatchDict[key] = match;\n                    }\n\n                    if (match.score > 0 || kDebug)\n                        matches.Add(match);\n                }\n                SimpleProfiler.Begin(\"Queue\");\n                if (current.level < goalItem.maxStep)\n                {\n                    foreach (Transform child in t)\n                        if (m_ValidBones == null || m_ValidBones.ContainsKey(child))\n                            if (!m_TreatDummyBonesAsReal && m_ValidBones != null && !m_ValidBones[child])\n                                queue.Enqueue(new QueuedBone(child, current.level));\n                            else\n                                queue.Enqueue(new QueuedBone(child, current.level + 1));\n                }\n                SimpleProfiler.End();\n            }\n\n            if (matches.Count == 0)\n                return null;\n\n            // Sort by match score with best matches first\n            SimpleProfiler.Begin(\"SortAndTrim\");\n            matches.Sort();\n            if (matches[0].score <= 0)\n                return null;\n\n            if (kDebug && confirmedChoice)\n                DebugMatchChoice(matches);\n\n            // Keep top 3 priorities only for optimization\n            while (matches.Count > 3)\n                matches.RemoveAt(matches.Count - 1);\n            matches.TrimExcess();\n            SimpleProfiler.End();\n\n            return matches;\n        }\n\n        private string GetNameOfBone(int boneIndex)\n        {\n            if (boneIndex < 0)\n                return \"\" + boneIndex;\n\n            return \"\" + (HumanBodyBones)boneIndex;\n        }\n\n        private string GetMatchString(BoneMatch match)\n        {\n            return GetNameOfBone(match.item.bone) + \":\" + (match.bone == null ? \"null\" : match.bone.name);\n        }\n\n        private void DebugMatchChoice(List<BoneMatch> matches)\n        {\n            string str = GetNameOfBone(matches[0].item.bone) + \" preferred order: \";\n            for (int i = 0; i < matches.Count; i++)\n                str += matches[i].bone.name + \" (\" + matches[i].score.ToString(\"0.0\", CultureInfo.InvariantCulture.NumberFormat) + \" / \" + matches[i].totalSiblingScore.ToString(\"0.0\", CultureInfo.InvariantCulture.NumberFormat) + \"), \";\n            foreach (BoneMatch m in matches)\n            {\n                str += \"\\n   Match \" + m.bone.name + \" (\" + m.score.ToString(\"0.0\", CultureInfo.InvariantCulture.NumberFormat) + \" / \" + m.totalSiblingScore.ToString(\"0.0\", CultureInfo.InvariantCulture.NumberFormat) + \"):\";\n                foreach (string s in m.debugTracker)\n                    str += \"\\n    - \" + s;\n            }\n            Debug.Log(str);\n        }\n\n        private bool IsParentOfOther(Transform knownCommonParent, Transform potentialParent, Transform potentialChild)\n        {\n            Transform t = potentialChild;\n            while (t != knownCommonParent)\n            {\n                if (t == potentialParent)\n                    return true;\n                if (t == knownCommonParent)\n                    return false;\n                t = t.parent;\n            }\n            return false;\n        }\n\n        private bool ShareTransformPath(Transform commonParent, Transform childA, Transform childB)\n        {\n            return IsParentOfOther(commonParent, childA, childB) || IsParentOfOther(commonParent, childB, childA);\n        }\n\n        private List<BoneMatch> GetBestChildMatches(BoneMatch parentMatch, List<List<BoneMatch>> childMatchesLists)\n        {\n            List<BoneMatch> bestMatches = new List<BoneMatch>();\n            if (childMatchesLists.Count == 1)\n            {\n                bestMatches.Add(childMatchesLists[0][0]);\n                return bestMatches;\n            }\n\n            int[] choices = new int[childMatchesLists.Count];\n            float dummyScore;\n            choices = GetBestChildMatchChoices(parentMatch, childMatchesLists, choices, out dummyScore);\n            for (int i = 0; i < choices.Length; i++)\n            {\n                if (choices[i] >= 0)\n                    bestMatches.Add(childMatchesLists[i][choices[i]]);\n            }\n            return bestMatches;\n        }\n\n        private int[] GetBestChildMatchChoices(BoneMatch parentMatch, List<List<BoneMatch>> childMatchesLists, int[] choices, out float score)\n        {\n            // See if any choices share the same transform path.\n            List<int> sharedIndices = new List<int>();\n            for (int i = 0; i < choices.Length; i++)\n            {\n                if (choices[i] < 0)\n                    continue;\n                sharedIndices.Clear();\n                sharedIndices.Add(i);\n                for (int j = i + 1; j < choices.Length; j++)\n                {\n                    if (choices[j] < 0)\n                        continue;\n                    if (ShareTransformPath(parentMatch.bone, childMatchesLists[i][choices[i]].bone, childMatchesLists[j][choices[j]].bone))\n                        sharedIndices.Add(j);\n                }\n\n                if (sharedIndices.Count > 1)\n                    break;\n            }\n\n            if (sharedIndices.Count <= 1)\n            {\n                // If no shared transform paths, calculate score and return choices.\n                score = 0;\n                for (int i = 0; i < choices.Length; i++)\n                    if (choices[i] >= 0)\n                        score += childMatchesLists[i][choices[i]].totalSiblingScore;\n                return choices;\n            }\n            else\n            {\n                // If transform paths are shared by multiple choices, call function recursively.\n                float bestScore = 0;\n                int[] bestChoices = choices;\n                for (int i = 0; i < sharedIndices.Count; i++)\n                {\n                    int[] altChoices = new int[choices.Length];\n                    Array.Copy(choices, altChoices, choices.Length);\n                    // In each call, one of the choices retains their priority while the remaining are bumped one priority down.\n                    for (int j = 0; j < sharedIndices.Count; j++)\n                    {\n                        if (i != j)\n                        {\n                            if (sharedIndices[j] >= altChoices.Length)\n                                Debug.LogError(\"sharedIndices[j] (\" + sharedIndices[j] + \") >= altChoices.Length (\" + altChoices.Length + \")\");\n                            if (sharedIndices[j] >= childMatchesLists.Count)\n                                Debug.LogError(\"sharedIndices[j] (\" + sharedIndices[j] + \") >= childMatchesLists.Count (\" + childMatchesLists.Count + \")\");\n                            if (altChoices[sharedIndices[j]] < childMatchesLists[sharedIndices[j]].Count - 1)\n                                altChoices[sharedIndices[j]]++;\n                            else\n                                altChoices[sharedIndices[j]] = -1;\n                        }\n                    }\n                    float altScore;\n                    altChoices = GetBestChildMatchChoices(parentMatch, childMatchesLists, altChoices, out altScore);\n                    if (altScore > bestScore)\n                    {\n                        bestScore = altScore;\n                        bestChoices = altChoices;\n                    }\n                }\n                // Return the choices with the best score\n                score = bestScore;\n                return bestChoices;\n            }\n        }\n\n        private void EvaluateBoneMatch(BoneMatch match, bool confirmedChoice)\n        {\n            match.score = 0;\n            match.siblingScore = 0;\n\n            // Things to copy from identical match: score, siblingScore, children, doMap\n\n            // Iterate child BoneMappingitems\n            List<List<BoneMatch>> childMatchesLists = new List<List<BoneMatch>>();\n            int intendedChildCount = 0;\n            foreach (int c in match.item.GetChildren(m_MappingData))\n            {\n                BoneMappingItem i = m_MappingData[c];\n                if (i.parent == match.item.bone)\n                {\n                    intendedChildCount++;\n                    // RECURSIVE CALL\n                    List<BoneMatch> childMatches = RecursiveFindPotentialBoneMatches(match, i, confirmedChoice);\n                    if (childMatches == null || childMatches.Count == 0)\n                        continue;\n                    childMatchesLists.Add(childMatches);\n                }\n            }\n\n            // Best best child matches\n            bool sameAsParentOrChild = (match.bone == match.humanBoneParent.bone);\n            if (childMatchesLists.Count > 0)\n            {\n                SimpleProfiler.Begin(\"GetBestChildMatches\");\n                match.children = GetBestChildMatches(match, childMatchesLists);\n                SimpleProfiler.End();\n\n                // Handle child matches\n                foreach (BoneMatch childMatch in match.children)\n                {\n                    // RECURSIVE CALL for debugging purposes\n                    if (kDebug && confirmedChoice)\n                        EvaluateBoneMatch(childMatch, confirmedChoice);\n\n                    // Transfer info from best child match to parent\n                    match.score += childMatch.score;\n                    if (kDebug)\n                        match.debugTracker.AddRange(childMatch.debugTracker);\n                    if (childMatch.bone == match.bone && childMatch.item.bone >= 0)\n                        sameAsParentOrChild = true;\n                }\n            }\n\n            SimpleProfiler.Begin(\"ScoreBoneMatch\");\n            // Keyword score the bone if it's not optional or if it's different from both parent bone and all child bones\n            if (!match.item.optional || !sameAsParentOrChild)\n                ScoreBoneMatch(match);\n            SimpleProfiler.End();\n\n            // Rate bone according to how well it matches goal direction\n            SimpleProfiler.Begin(\"MatchesDir\");\n            if (match.item.dir != Vector3.zero)\n            {\n                Vector3 goalDir = match.item.dir;\n                if (m_MappingIndexOffset >= (int)HumanBodyBones.LeftThumbProximal && m_MappingIndexOffset < (int)HumanBodyBones.RightThumbProximal)\n                    goalDir.x *= -1;\n                Vector3 dir = (match.bone.position - match.humanBoneParent.bone.position).normalized;\n                dir = Quaternion.Inverse(m_Orientation) * dir;\n                float dirMatchingScore = Vector3.Dot(dir, goalDir) * (match.item.optional ? 5 : 10);\n\n                match.siblingScore += dirMatchingScore;\n                if (kDebug)\n                    match.debugTracker.Add(\"* \" + dirMatchingScore + \": \" + GetMatchString(match) + \" matched dir (\" + (match.bone.position - match.humanBoneParent.bone.position).normalized + \" , \" + goalDir + \")\");\n\n                if (dirMatchingScore > 0)\n                {\n                    match.score += 10;\n                    if (kDebug)\n                        match.debugTracker.Add(10 + \": \" + GetMatchString(match) + \" matched dir (\" + (match.bone.position - match.humanBoneParent.bone.position).normalized + \" , \" + goalDir + \")\");\n                }\n            }\n            SimpleProfiler.End();\n\n            // Give small score if bone matches side it belongs to.\n            SimpleProfiler.Begin(\"MatchesSide\");\n            if (m_MappingIndexOffset == 0)\n            {\n                int sideMatchingScore = GetBoneSideMatchPoints(match);\n                if (match.parent.item.side == Side.None || sideMatchingScore < 0)\n                {\n                    match.siblingScore += sideMatchingScore;\n                    if (kDebug)\n                        match.debugTracker.Add(\"* \" + sideMatchingScore + \": \" + GetMatchString(match) + \" matched side\");\n                }\n            }\n            SimpleProfiler.End();\n\n            // These criteria can not push a bone above the threshold, but they can help to break ties.\n            if (match.score > 0)\n            {\n                // Reward optional bones being included\n                if (match.item.optional && !sameAsParentOrChild)\n                {\n                    match.score += 5;\n                    if (kDebug)\n                        match.debugTracker.Add(5 + \": \" + GetMatchString(match) + \" optional bone is included\");\n                }\n\n                // Handle end bones\n                if (intendedChildCount == 0 && match.bone.childCount > 0)\n                {\n                    // Reward end bones having a dummy child transform\n                    match.score += 1;\n                    if (kDebug)\n                        match.debugTracker.Add(1 + \": \" + GetMatchString(match) + \" has dummy child bone\");\n                }\n\n                // Give score to bones length ratio according to match with goal ratio.\n                SimpleProfiler.Begin(\"LengthRatio\");\n                if (match.item.lengthRatio != 0)\n                {\n                    float parentLength = Vector3.Distance(match.bone.position, match.humanBoneParent.bone.position);\n                    if (parentLength == 0 && match.bone != match.humanBoneParent.bone)\n                    {\n                        match.score -= 1000;\n                        if (kDebug)\n                            match.debugTracker.Add((-1000) + \": \" + GetMatchString(match.humanBoneParent) + \" has zero length\");\n                    }\n\n                    float grandParentLength = Vector3.Distance(match.humanBoneParent.bone.position, match.humanBoneParent.humanBoneParent.bone.position);\n                    if (grandParentLength > 0)\n                    {\n                        float logRatio = Mathf.Log(parentLength / grandParentLength, 2);\n                        float logGoalRatio = Mathf.Log(match.item.lengthRatio, 2);\n                        float ratioScore = 10 * Mathf.Clamp(1 - 0.6f * Mathf.Abs(logRatio - logGoalRatio), 0, 1);\n                        match.score += ratioScore;\n                        if (kDebug)\n                            match.debugTracker.Add(ratioScore + \": parent \" + GetMatchString(match.humanBoneParent) + \" matched lengthRatio - \" + parentLength + \" / \" + grandParentLength + \" = \" + (parentLength / grandParentLength) + \" (\" + logRatio + \") goal: \" + match.item.lengthRatio + \" (\" + logGoalRatio + \")\");\n                    }\n                }\n                SimpleProfiler.End();\n            }\n\n            // Only map optional bones if they're not the same as the parent or child.\n            if (match.item.bone >= 0 && (!match.item.optional || !sameAsParentOrChild))\n                match.doMap = true;\n        }\n\n        private void ScoreBoneMatch(BoneMatch match)\n        {\n            int badKeywordScore = BoneHasBadKeyword(match.bone, match.item.keywords);\n            match.score += badKeywordScore;\n            if (kDebug && badKeywordScore != 0)\n                match.debugTracker.Add(badKeywordScore + \": \" + GetMatchString(match) + \" matched bad keywords\");\n            if (badKeywordScore < 0)\n                return;\n\n            int keywordScore = BoneHasKeyword(match.bone, match.item.keywords);\n            match.score += keywordScore;\n            if (kDebug && keywordScore != 0)\n                match.debugTracker.Add(keywordScore + \": \" + GetMatchString(match) + \" matched keywords\");\n\n            // If child bone with no required keywords, give a minimal score so it can still be included in mapping\n            if (match.item.keywords.Length == 0 && match.item.alwaysInclude)\n            {\n                match.score += 1;\n                if (kDebug)\n                    match.debugTracker.Add(1 + \": \" + GetMatchString(match) + \" always-include point\");\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Avatar/AvatarBipedMapper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\nusing System.Linq;\n\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class AvatarBipedMapper\n    {\n        private struct BipedBone\n        {\n            public string name;\n            public int index;\n\n            public BipedBone(string name, int index)\n            {\n                this.name = name;\n                this.index = index;\n            }\n        }\n\n        private static BipedBone[] s_BipedBones = new BipedBone[]\n        {\n            // body\n            new BipedBone(\"Pelvis\",        (int)HumanBodyBones.Hips),\n            new BipedBone(\"L Thigh\",       (int)HumanBodyBones.LeftUpperLeg),\n            new BipedBone(\"R Thigh\",       (int)HumanBodyBones.RightUpperLeg),\n            new BipedBone(\"L Calf\",        (int)HumanBodyBones.LeftLowerLeg),\n            new BipedBone(\"R Calf\",        (int)HumanBodyBones.RightLowerLeg),\n            new BipedBone(\"L Foot\",        (int)HumanBodyBones.LeftFoot),\n            new BipedBone(\"R Foot\",        (int)HumanBodyBones.RightFoot),\n            new BipedBone(\"Spine\",         (int)HumanBodyBones.Spine),\n            new BipedBone(\"Spine1\",        (int)HumanBodyBones.Chest),\n            new BipedBone(\"Spine2\",        (int)HumanBodyBones.UpperChest),\n            new BipedBone(\"Neck\",          (int)HumanBodyBones.Neck),\n            new BipedBone(\"Head\",          (int)HumanBodyBones.Head),\n            new BipedBone(\"L Clavicle\",    (int)HumanBodyBones.LeftShoulder),\n            new BipedBone(\"R Clavicle\",    (int)HumanBodyBones.RightShoulder),\n            new BipedBone(\"L UpperArm\",    (int)HumanBodyBones.LeftUpperArm),\n            new BipedBone(\"R UpperArm\",    (int)HumanBodyBones.RightUpperArm),\n            new BipedBone(\"L Forearm\",     (int)HumanBodyBones.LeftLowerArm),\n            new BipedBone(\"R Forearm\",     (int)HumanBodyBones.RightLowerArm),\n            new BipedBone(\"L Hand\",        (int)HumanBodyBones.LeftHand),\n            new BipedBone(\"R Hand\",        (int)HumanBodyBones.RightHand),\n            new BipedBone(\"L Toe0\",        (int)HumanBodyBones.LeftToes),\n            new BipedBone(\"R Toe0\",        (int)HumanBodyBones.RightToes),\n            // Left Hand\n            new BipedBone(\"L Finger0\",     (int)HumanBodyBones.LeftThumbProximal),\n            new BipedBone(\"L Finger01\",    (int)HumanBodyBones.LeftThumbIntermediate),\n            new BipedBone(\"L Finger02\",    (int)HumanBodyBones.LeftThumbDistal),\n            new BipedBone(\"L Finger1\",     (int)HumanBodyBones.LeftIndexProximal),\n            new BipedBone(\"L Finger11\",    (int)HumanBodyBones.LeftIndexIntermediate),\n            new BipedBone(\"L Finger12\",    (int)HumanBodyBones.LeftIndexDistal),\n            new BipedBone(\"L Finger2\",     (int)HumanBodyBones.LeftMiddleProximal),\n            new BipedBone(\"L Finger21\",    (int)HumanBodyBones.LeftMiddleIntermediate),\n            new BipedBone(\"L Finger22\",    (int)HumanBodyBones.LeftMiddleDistal),\n            new BipedBone(\"L Finger3\",     (int)HumanBodyBones.LeftRingProximal),\n            new BipedBone(\"L Finger31\",    (int)HumanBodyBones.LeftRingIntermediate),\n            new BipedBone(\"L Finger32\",    (int)HumanBodyBones.LeftRingDistal),\n            new BipedBone(\"L Finger4\",     (int)HumanBodyBones.LeftLittleProximal),\n            new BipedBone(\"L Finger41\",    (int)HumanBodyBones.LeftLittleIntermediate),\n            new BipedBone(\"L Finger42\",    (int)HumanBodyBones.LeftLittleDistal),\n            // Right Hand\n            new BipedBone(\"R Finger0\",     (int)HumanBodyBones.RightThumbProximal),\n            new BipedBone(\"R Finger01\",    (int)HumanBodyBones.RightThumbIntermediate),\n            new BipedBone(\"R Finger02\",    (int)HumanBodyBones.RightThumbDistal),\n            new BipedBone(\"R Finger1\",     (int)HumanBodyBones.RightIndexProximal),\n            new BipedBone(\"R Finger11\",    (int)HumanBodyBones.RightIndexIntermediate),\n            new BipedBone(\"R Finger12\",    (int)HumanBodyBones.RightIndexDistal),\n            new BipedBone(\"R Finger2\",     (int)HumanBodyBones.RightMiddleProximal),\n            new BipedBone(\"R Finger21\",    (int)HumanBodyBones.RightMiddleIntermediate),\n            new BipedBone(\"R Finger22\",    (int)HumanBodyBones.RightMiddleDistal),\n            new BipedBone(\"R Finger3\",     (int)HumanBodyBones.RightRingProximal),\n            new BipedBone(\"R Finger31\",    (int)HumanBodyBones.RightRingIntermediate),\n            new BipedBone(\"R Finger32\",    (int)HumanBodyBones.RightRingDistal),\n            new BipedBone(\"R Finger4\",     (int)HumanBodyBones.RightLittleProximal),\n            new BipedBone(\"R Finger41\",    (int)HumanBodyBones.RightLittleIntermediate),\n            new BipedBone(\"R Finger42\",    (int)HumanBodyBones.RightLittleDistal)\n        };\n\n        public static bool IsBiped(Transform root, List<string> report)\n        {\n            if (report != null)\n            {\n                report.Clear();\n            }\n\n            Transform[] humanToTransform = new Transform[HumanTrait.BoneCount];\n            return MapBipedBones(root, ref humanToTransform, report);\n        }\n\n        public static Dictionary<int, Transform> MapBones(Transform root)\n        {\n            Dictionary<int, Transform> ret = new Dictionary<int, Transform>();\n\n            Transform[] humanToTransform = new Transform[HumanTrait.BoneCount];\n\n            if (MapBipedBones(root, ref humanToTransform, null))\n            {\n                for (int boneIter = 0; boneIter < HumanTrait.BoneCount; boneIter++)\n                {\n                    if (humanToTransform[boneIter] != null)\n                    {\n                        ret.Add(boneIter, humanToTransform[boneIter]);\n                    }\n                }\n            }\n\n            // Move upper chest to chest if no chest was found\n            if (!ret.ContainsKey((int)HumanBodyBones.Chest) &&\n                ret.ContainsKey((int)HumanBodyBones.UpperChest))\n            {\n                ret.Add((int)HumanBodyBones.Chest, ret[(int)HumanBodyBones.UpperChest]);\n                ret.Remove((int)HumanBodyBones.UpperChest);\n            }\n\n            return ret;\n        }\n\n        private static bool MapBipedBones(Transform root, ref Transform[] humanToTransform, List<string> report)\n        {\n            for (int bipedBoneIter = 0; bipedBoneIter < s_BipedBones.Length; bipedBoneIter++)\n            {\n                int boneIndex = s_BipedBones[bipedBoneIter].index;\n\n                int parentIndex = HumanTrait.GetParentBone(boneIndex);\n\n                bool required = HumanTrait.RequiredBone(boneIndex);\n                bool parentRequired = parentIndex != -1 ? HumanTrait.RequiredBone(parentIndex) : true;\n\n                Transform parentTransform = parentIndex != -1 ? humanToTransform[parentIndex] : root;\n\n                if (parentTransform == null && !parentRequired)\n                {\n                    parentIndex = HumanTrait.GetParentBone(parentIndex);\n                    parentRequired = parentIndex != -1 ? HumanTrait.RequiredBone(parentIndex) : true;\n                    parentTransform = parentIndex != -1 ? humanToTransform[parentIndex] : null;\n\n                    if (parentTransform == null && !parentRequired)\n                    {\n                        parentIndex = HumanTrait.GetParentBone(parentIndex);\n                        parentTransform = parentIndex != -1 ? humanToTransform[parentIndex] : null;\n                    }\n                }\n\n                humanToTransform[boneIndex] = MapBipedBone(bipedBoneIter, parentTransform, parentTransform, report);\n\n                if (humanToTransform[boneIndex] == null && required)\n                {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        private static Transform MapBipedBone(int bipedBoneIndex, Transform transform, Transform parentTransform, List<string> report)\n        {\n            Transform ret = null;\n\n            if (transform != null)\n            {\n                int childCount = transform.childCount;\n\n                for (int childIter = 0; ret == null && childIter < childCount; childIter++)\n                {\n                    string boneName = s_BipedBones[bipedBoneIndex].name;\n                    int boneIndex = s_BipedBones[bipedBoneIndex].index;\n\n                    if (transform.GetChild(childIter).name.EndsWith(boneName))\n                    {\n                        ret = transform.GetChild(childIter);\n\n                        if (ret != null && report != null && boneIndex != (int)HumanBodyBones.Hips && transform != parentTransform)\n                        {\n                            string current = \"- Invalid parent for \" + ret.name + \". Expected \" + parentTransform.name + \", but found \" + transform.name + \".\";\n\n                            if (boneIndex == (int)HumanBodyBones.LeftUpperLeg || boneIndex == (int)HumanBodyBones.RightUpperLeg)\n                            {\n                                current += \" Disable Triangle Pelvis\";\n                            }\n                            else if (boneIndex == (int)HumanBodyBones.LeftShoulder || boneIndex == (int)HumanBodyBones.RightShoulder)\n                            {\n                                current += \" Enable Triangle Neck\";\n                            }\n                            else if (boneIndex == (int)HumanBodyBones.Neck)\n                            {\n                                current += \" Preferred is three Spine Links\";\n                            }\n                            else if (boneIndex == (int)HumanBodyBones.Head)\n                            {\n                                current += \" Preferred is one Neck Links\";\n                            }\n\n                            current += \"\\n\";\n\n                            report.Add(current);\n                        }\n                    }\n                }\n\n                for (int childIter = 0; ret == null && childIter < childCount; childIter++)\n                {\n                    ret = MapBipedBone(bipedBoneIndex, transform.GetChild(childIter), parentTransform, report);\n                }\n            }\n\n            return ret;\n        }\n\n        internal static void BipedPose(GameObject go, AvatarSetupTool.BoneWrapper[] bones)\n        {\n            BipedPose(go.transform, true);\n\n            // Orient Biped\n            Quaternion rot = AvatarSetupTool.AvatarComputeOrientation(bones);\n            go.transform.rotation = Quaternion.Inverse(rot) * go.transform.rotation;\n\n            // Move Biped feet to ground plane\n            AvatarSetupTool.MakeCharacterPositionValid(bones);\n        }\n\n        private static void BipedPose(Transform t, bool ignore)\n        {\n            if (t.name.EndsWith(\"Pelvis\"))\n            {\n                t.localRotation = Quaternion.Euler(270, 90, 0);\n                ignore = false;\n            }\n            else if (t.name.EndsWith(\"Thigh\"))\n            {\n                t.localRotation = Quaternion.Euler(0, 180, 0);\n            }\n            else if (t.name.EndsWith(\"Toe0\"))\n            {\n                t.localRotation = Quaternion.Euler(0, 0, 270);\n            }\n            else if (t.name.EndsWith(\"L Clavicle\"))\n            {\n                t.localRotation = Quaternion.Euler(0, 270, 180);\n            }\n            else if (t.name.EndsWith(\"R Clavicle\"))\n            {\n                t.localRotation = Quaternion.Euler(0, 90, 180);\n            }\n            else if (t.name.EndsWith(\"L Hand\"))\n            {\n                t.localRotation = Quaternion.Euler(270, 0, 0);\n            }\n            else if (t.name.EndsWith(\"R Hand\"))\n            {\n                t.localRotation = Quaternion.Euler(90, 0, 0);\n            }\n            else if (t.name.EndsWith(\"L Finger0\"))\n            {\n                t.localRotation = Quaternion.Euler(0, 315, 0);\n            }\n            else if (t.name.EndsWith(\"R Finger0\"))\n            {\n                t.localRotation = Quaternion.Euler(0, 45, 0);\n            }\n            else if (!ignore)\n            {\n                t.localRotation = Quaternion.identity;\n            }\n\n            foreach (Transform child in t)\n            {\n                BipedPose(child, ignore);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Avatar/AvatarControl.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    public enum BodyPart\n    {\n        None = -1,\n        Avatar = 0,\n        Body,\n        Head,\n        LeftArm,\n        LeftFingers,\n        RightArm,\n        RightFingers,\n        LeftLeg,\n        RightLeg,\n        Last\n    }\n\n    internal class AvatarControl\n    {\n        class Styles\n        {\n            // IF you change the order of this array, please update:\n            // BodyPartMapping\n            // m_BodyPartHumanBone\n            // BodyPart\n\n            public GUIContent[] Silhouettes =\n            {\n                EditorGUIUtility.IconContent(\"AvatarInspector/BodySilhouette\"),\n                EditorGUIUtility.IconContent(\"AvatarInspector/HeadZoomSilhouette\"),\n                EditorGUIUtility.IconContent(\"AvatarInspector/LeftHandZoomSilhouette\"),\n                EditorGUIUtility.IconContent(\"AvatarInspector/RightHandZoomSilhouette\")\n            };\n\n            public GUIContent[,] BodyPart =\n            {\n                {\n                    null,\n                    EditorGUIUtility.IconContent(\"AvatarInspector/Torso\"),\n                    EditorGUIUtility.IconContent(\"AvatarInspector/Head\"),\n                    EditorGUIUtility.IconContent(\"AvatarInspector/LeftArm\"),\n                    EditorGUIUtility.IconContent(\"AvatarInspector/LeftFingers\"),\n                    EditorGUIUtility.IconContent(\"AvatarInspector/RightArm\"),\n                    EditorGUIUtility.IconContent(\"AvatarInspector/RightFingers\"),\n                    EditorGUIUtility.IconContent(\"AvatarInspector/LeftLeg\"),\n                    EditorGUIUtility.IconContent(\"AvatarInspector/RightLeg\")\n                },\n                {\n                    null,\n                    null,\n                    EditorGUIUtility.IconContent(\"AvatarInspector/HeadZoom\"),\n                    null,\n                    null,\n                    null,\n                    null,\n                    null,\n                    null\n                },\n                {\n                    null,\n                    null,\n                    null,\n                    null,\n                    EditorGUIUtility.IconContent(\"AvatarInspector/LeftHandZoom\"),\n                    null,\n                    null,\n                    null,\n                    null\n                },\n                {\n                    null,\n                    null,\n                    null,\n                    null,\n                    null,\n                    null,\n                    EditorGUIUtility.IconContent(\"AvatarInspector/RightHandZoom\"),\n                    null,\n                    null\n                },\n            };\n        }\n\n        static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } }\n        static Styles s_Styles;\n\n        public enum BodyPartColor\n        {\n            Off = 0x00,\n            Green = 0x01 << 0,\n            Red = 0x01 << 1,\n            IKGreen = 0x01 << 2,\n            IKRed = 0x01 << 3,\n        }\n\n        public delegate BodyPartColor BodyPartFeedback(BodyPart bodyPart);\n\n        static public int ShowBoneMapping(int shownBodyView, BodyPartFeedback bodyPartCallback, AvatarSetupTool.BoneWrapper[] bones, SerializedObject serializedObject, AvatarMappingEditor editor)\n        {\n            GUILayout.BeginHorizontal();\n            {\n                GUILayout.FlexibleSpace();\n\n                if (styles.Silhouettes[shownBodyView].image)\n                {\n                    Rect rect = GUILayoutUtility.GetRect(styles.Silhouettes[shownBodyView], GUIStyle.none, GUILayout.MaxWidth(styles.Silhouettes[shownBodyView].image.width));\n                    DrawBodyParts(rect, shownBodyView, bodyPartCallback);\n\n                    for (int i = 0; i < bones.Length; i++)\n                        DrawBone(shownBodyView, i, rect, bones[i], serializedObject, editor);\n                }\n                else\n                    GUILayout.Label(\"texture missing,\\nfix me!\");\n\n                GUILayout.FlexibleSpace();\n            }\n            GUILayout.EndHorizontal();\n\n            // Body view buttons\n            Rect buttonsRect = GUILayoutUtility.GetLastRect();\n            const float buttonHeight = 18;\n            string[] labels = new string[] { \"Body\", \"Head\", \"Left Hand\", \"Right Hand\"};\n            buttonsRect.x += 5;\n            buttonsRect.width = 80;\n            buttonsRect.yMin = buttonsRect.yMax - (buttonHeight * 4 + 5);\n            buttonsRect.height = buttonHeight;\n            for (int i = 0; i < labels.Length; i++)\n            {\n                if (GUI.Toggle(buttonsRect, shownBodyView == i, labels[i], EditorStyles.miniButton))\n                    shownBodyView = i;\n                buttonsRect.y += buttonHeight;\n            }\n\n            return shownBodyView;\n        }\n\n        static public void DrawBodyParts(Rect rect, int shownBodyView, BodyPartFeedback bodyPartCallback)\n        {\n            GUI.color = new Color(0.2f, 0.2f, 0.2f, 1.0f);\n            if (styles.Silhouettes[shownBodyView] != null)\n                GUI.DrawTexture(rect, styles.Silhouettes[shownBodyView].image);\n            for (int i = 1; i < (int)BodyPart.Last; i++)\n                DrawBodyPart(shownBodyView, i, rect, bodyPartCallback((BodyPart)i));\n        }\n\n        static protected void DrawBodyPart(int shownBodyView, int i, Rect rect, BodyPartColor bodyPartColor)\n        {\n            if (styles.BodyPart[shownBodyView, i] != null && styles.BodyPart[shownBodyView, i].image != null)\n            {\n                if ((bodyPartColor & BodyPartColor.Green) == BodyPartColor.Green)\n                    GUI.color = Color.green;\n                else if ((bodyPartColor & BodyPartColor.Red) == BodyPartColor.Red)\n                    GUI.color = Color.red;\n                else\n                    GUI.color = Color.gray;\n                GUI.DrawTexture(rect, styles.BodyPart[shownBodyView, i].image);\n                GUI.color = Color.white;\n            }\n        }\n\n        static Vector2[,] s_BonePositions = new Vector2[4, HumanTrait.BoneCount];\n\n        public static List<int> GetViewsThatContainBone(int bone)\n        {\n            List<int> views = new List<int>();\n\n            if (bone < 0 || bone >= HumanTrait.BoneCount)\n                return views;\n\n            for (int i = 0; i < 4; i++)\n            {\n                if (s_BonePositions[i, bone] != Vector2.zero)\n                    views.Add(i);\n            }\n            return views;\n        }\n\n        static AvatarControl()\n        {\n            // Body view\n            int view = 0;\n            // hips\n            s_BonePositions[view,  (int)HumanBodyBones.Hips] = new Vector2(0.00f, 0.08f);\n\n            // upper leg\n            s_BonePositions[view,  (int)HumanBodyBones.LeftUpperLeg] = new Vector2(0.16f, 0.01f);\n            s_BonePositions[view,  (int)HumanBodyBones.RightUpperLeg] = new Vector2(-0.16f, 0.01f);\n\n            // lower leg\n            s_BonePositions[view,  (int)HumanBodyBones.LeftLowerLeg] = new Vector2(0.21f, -0.40f);\n            s_BonePositions[view,  (int)HumanBodyBones.RightLowerLeg] = new Vector2(-0.21f, -0.40f);\n\n            // foot\n            s_BonePositions[view,  (int)HumanBodyBones.LeftFoot] = new Vector2(0.23f, -0.80f);\n            s_BonePositions[view,  (int)HumanBodyBones.RightFoot] = new Vector2(-0.23f, -0.80f);\n\n            // spine - head\n            s_BonePositions[view,  (int)HumanBodyBones.Spine] = new Vector2(0.00f, 0.20f);\n            s_BonePositions[view,  (int)HumanBodyBones.Chest] = new Vector2(0.00f, 0.35f);\n            s_BonePositions[view,  (int)HumanBodyBones.UpperChest] = new Vector2(0.00f, 0.50f);\n            s_BonePositions[view, (int)HumanBodyBones.Neck] = new Vector2(0.00f, 0.66f);\n            s_BonePositions[view, (int)HumanBodyBones.Head] = new Vector2(0.00f, 0.76f);\n\n            // shoulder\n            s_BonePositions[view, (int)HumanBodyBones.LeftShoulder] = new Vector2(0.14f, 0.60f);\n            s_BonePositions[view, (int)HumanBodyBones.RightShoulder] = new Vector2(-0.14f, 0.60f);\n\n            // upper arm\n            s_BonePositions[view, (int)HumanBodyBones.LeftUpperArm] = new Vector2(0.30f, 0.57f);\n            s_BonePositions[view, (int)HumanBodyBones.RightUpperArm] = new Vector2(-0.30f, 0.57f);\n\n            // lower arm\n            s_BonePositions[view, (int)HumanBodyBones.LeftLowerArm] = new Vector2(0.48f, 0.30f);\n            s_BonePositions[view, (int)HumanBodyBones.RightLowerArm] = new Vector2(-0.48f, 0.30f);\n\n            // hand\n            s_BonePositions[view, (int)HumanBodyBones.LeftHand] = new Vector2(0.66f, 0.03f);\n            s_BonePositions[view, (int)HumanBodyBones.RightHand] = new Vector2(-0.66f, 0.03f);\n\n            // toe\n            s_BonePositions[view, (int)HumanBodyBones.LeftToes] = new Vector2(0.25f, -0.89f);\n            s_BonePositions[view, (int)HumanBodyBones.RightToes] = new Vector2(-0.25f, -0.89f);\n\n            // Head view\n            view = 1;\n            // neck - head\n            s_BonePositions[view, (int)HumanBodyBones.Neck] = new Vector2(-0.20f, -0.62f);\n            s_BonePositions[view, (int)HumanBodyBones.Head] = new Vector2(-0.15f, -0.30f);\n            // left, right eye\n            s_BonePositions[view, (int)HumanBodyBones.LeftEye] = new Vector2(0.63f, 0.16f);\n            s_BonePositions[view, (int)HumanBodyBones.RightEye] = new Vector2(0.15f, 0.16f);\n            // jaw\n            s_BonePositions[view, (int)HumanBodyBones.Jaw] = new Vector2(0.45f, -0.40f);\n\n            // Left hand view\n            view = 2;\n            // finger bases, thumb - little\n            s_BonePositions[view, (int)HumanBodyBones.LeftThumbProximal] = new Vector2(-0.35f, 0.11f);\n            s_BonePositions[view, (int)HumanBodyBones.LeftIndexProximal] = new Vector2(0.19f, 0.11f);\n            s_BonePositions[view, (int)HumanBodyBones.LeftMiddleProximal] = new Vector2(0.22f, 0.00f);\n            s_BonePositions[view, (int)HumanBodyBones.LeftRingProximal] = new Vector2(0.16f, -0.12f);\n            s_BonePositions[view, (int)HumanBodyBones.LeftLittleProximal] = new Vector2(0.09f, -0.23f);\n\n            // finger tips, thumb - little\n            s_BonePositions[view, (int)HumanBodyBones.LeftThumbDistal] = new Vector2(-0.03f, 0.33f);\n            s_BonePositions[view, (int)HumanBodyBones.LeftIndexDistal] = new Vector2(0.65f, 0.16f);\n            s_BonePositions[view, (int)HumanBodyBones.LeftMiddleDistal] = new Vector2(0.74f, 0.00f);\n            s_BonePositions[view, (int)HumanBodyBones.LeftRingDistal] = new Vector2(0.66f, -0.14f);\n            s_BonePositions[view, (int)HumanBodyBones.LeftLittleDistal] = new Vector2(0.45f, -0.25f);\n\n            // finger middles, thumb - little\n            for (int i = 0; i < 5; i++)\n                s_BonePositions[view, (int)HumanBodyBones.LeftThumbIntermediate + i * 3] = Vector2.Lerp(s_BonePositions[view, (int)HumanBodyBones.LeftThumbProximal + i * 3], s_BonePositions[view, (int)HumanBodyBones.LeftThumbDistal + i * 3], 0.58f);\n\n            // Right hand view\n            view = 3;\n            for (int i = 0; i < 15; i++)\n                s_BonePositions[view, (int)HumanBodyBones.LeftThumbProximal + i + 15] = Vector2.Scale(s_BonePositions[view - 1, (int)HumanBodyBones.LeftThumbProximal + i], new Vector2(-1, 1));\n        }\n\n        static protected void DrawBone(int shownBodyView, int i, Rect rect, AvatarSetupTool.BoneWrapper bone, SerializedObject serializedObject, AvatarMappingEditor editor)\n        {\n            if (s_BonePositions[shownBodyView, i] == Vector2.zero)\n                return;\n\n            Vector2 pos = s_BonePositions[shownBodyView, i];\n            pos.y *= -1; // because higher values should be up\n            pos.Scale(new Vector2(rect.width * 0.5f, rect.height * 0.5f));\n            pos = rect.center + pos;\n            int kIconSize = AvatarSetupTool.BoneWrapper.kIconSize;\n            Rect r = new Rect(pos.x - kIconSize * 0.5f, pos.y - kIconSize * 0.5f, kIconSize, kIconSize);\n            bone.BoneDotGUI(r, r, i, true, true, true, serializedObject, editor);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Avatar/AvatarEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.SceneManagement;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    internal class AvatarSubEditor : ScriptableObject\n    {\n        /*\n        // Will be used to patch animation when handiness changes.\n        public class AvatarSetter : AssetPostprocessor\n        {\n            public void OnPostprocessModel(GameObject go)\n            {\n                ModelImporter modelImporter = (ModelImporter)assetImporter;\n                ModelImporterEditor inspector = ActiveEditorTracker.MakeCustomEditor(modelImporter) as ModelImporterEditor;\n\n                SerializedProperty humanDescription = inspector.serializedObject.FindProperty(\"m_HumanDescription\");\n\n                Avatar avatar = AssetDatabase.LoadAssetAtPath(\"Assets/1_Characters/Dude/Dude.fbx\", typeof(UnityEngine.Avatar)) as Avatar;\n                if (avatar == null)\n                    Debug.Log(\"Could not find avatar when importing : \" + modelImporter.assetPath);\n\n                if (avatar != null && modelImporter != null)\n                    modelImporter.UpdateHumanDescription(avatar, humanDescription);\n\n                EditorUtility.SetDirty(inspector);\n                EditorUtility.SetDirty(modelImporter);\n            }\n        }\n        */\n\n        /*[MenuItem (\"Mecanim/Write All Assets\")]\n        static void DoWriteAllAssets()\n        {\n            UnityEngine.Object[] objects = Resources.FindObjectsOfTypeAll(typeof(UnityEngine.Object));\n            foreach (UnityEngine.Object asset in objects)\n            {\n                if (AssetDatabase.Contains(asset))\n                    EditorUtility.SetDirty(asset);\n            }\n            AssetDatabase.SaveAssets();\n        }*/\n\n        protected AvatarEditor m_Inspector;\n        protected GameObject gameObject { get { return m_Inspector.m_GameObject; } }\n        protected GameObject prefab { get { return m_Inspector.prefab; } }\n        protected Dictionary<Transform, bool> modelBones { get { return m_Inspector.m_ModelBones; } }\n        protected Transform root { get { return gameObject == null ? null : gameObject.transform; } }\n        protected SerializedObject serializedObject { get { return m_Inspector.serializedAssetImporter; } }\n        protected Avatar avatarAsset { get { return m_Inspector.avatar; } }\n\n        public virtual void Enable(AvatarEditor inspector)\n        {\n            this.m_Inspector = inspector;\n        }\n\n        public virtual void Disable()\n        {\n        }\n\n        public virtual void OnDestroy()\n        {\n            if (HasModified())\n            {\n                AssetImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(avatarAsset));\n                if (importer)\n                {\n                    if (EditorUtility.DisplayDialog(\"Unapplied import settings\", \"Unapplied import settings for \\'\" + importer.assetPath + \"\\'\", \"Apply\", \"Revert\"))\n                        ApplyAndImport();\n                    else\n                        ResetValues();\n                }\n            }\n        }\n\n        public virtual void OnInspectorGUI()\n        {\n        }\n\n        public virtual void OnSceneGUI()\n        {\n        }\n\n        protected bool HasModified()\n        {\n            if (!m_Inspector)\n                return false;\n            if (serializedObject != null && serializedObject.hasModifiedProperties)\n                return true;\n\n            return false;\n        }\n\n        protected virtual void ResetValues()\n        {\n            serializedObject.Update();\n        }\n\n        protected void Apply()\n        {\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        public void ApplyAndImport()\n        {\n            Apply();\n\n            string assetPath = AssetDatabase.GetAssetPath(avatarAsset);\n            AssetDatabase.ImportAsset(assetPath);\n\n            ResetValues();\n        }\n\n        protected void ApplyRevertGUI()\n        {\n            EditorGUILayout.Space();\n\n            using (new GUILayout.HorizontalScope())\n            {\n                using (new EditorGUI.DisabledScope(!HasModified()))\n                {\n                    GUILayout.FlexibleSpace();\n                    if (GUILayout.Button(\"Revert\"))\n                    {\n                        ResetValues();\n                        System.Diagnostics.Debug.Assert(!HasModified(), \"Avatar settings are marked as modified after calling Reset.\");\n                    }\n\n                    if (GUILayout.Button(\"Apply\"))\n                    {\n                        ApplyAndImport();\n                    }\n                }\n\n                if (GUILayout.Button(\"Done\"))\n                {\n                    m_Inspector.SwitchToAssetMode();\n                    GUIUtility.ExitGUI();\n                }\n            }\n        }\n    }\n\n    [CustomEditor(typeof(Avatar))]\n    internal class AvatarEditor : Editor\n    {\n        private class Styles\n        {\n            public GUIContent[] tabs =\n            {\n                EditorGUIUtility.TrTextContent(\"Mapping\"),\n                EditorGUIUtility.TrTextContent(\"Muscles & Settings\"),\n                //EditorGUIUtility.TrTextContent (\"Handle\"),\n                //EditorGUIUtility.TrTextContent (\"Collider\")\n            };\n\n            public GUIContent editCharacter = EditorGUIUtility.TrTextContent(\"Configure Avatar\");\n\n            public GUIContent reset = EditorGUIUtility.TrTextContent(\"Reset\");\n        }\n\n        static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } }\n        static Styles s_Styles;\n\n        enum EditMode\n        {\n            NotEditing,\n            Starting,\n            Editing,\n            Stopping\n        }\n\n        protected int m_TabIndex;\n        internal GameObject m_GameObject;\n        internal Dictionary<Transform, bool> m_ModelBones = null;\n        private EditMode m_EditMode = EditMode.NotEditing;\n        internal bool m_CameFromImportSettings = false;\n        private bool m_SwitchToEditMode = false;\n        internal static bool s_EditImmediatelyOnNextOpen = false;\n\n        // These member are used when the avatar is part of an asset\n\n        // This is used as a backend by the AvatarSubEditors to serialize\n        // only the FBXImporter part and not mess up with the Editor's serializedObject.\n        internal SerializedObject m_SerializedAssetImporter = null;\n        public SerializedObject serializedAssetImporter\n        {\n            get\n            {\n                // TODO find a better sync for that and be in better control of the lifetime\n                if (m_SerializedAssetImporter == null)\n                {\n                    m_SerializedAssetImporter = CreateSerializedImporterForTarget(target);\n                }\n                return m_SerializedAssetImporter;\n            }\n        }\n\n        internal Avatar avatar\n        {\n            get\n            {\n                var r = target as Avatar;\n                return r;\n            }\n        }\n\n        protected bool m_InspectorLocked;\n\n        // We'd prefer to have just one AvatarEditor member but due to Serialization issues,\n        // we need to keep one of each type. It should still be treated as a single one though.\n        // I.e. only one should be used at a time; the rest should be null.\n        protected AvatarSubEditor editor\n        {\n            get\n            {\n                switch (m_TabIndex)\n                {\n                    case sMuscleTab: return m_MuscleEditor;\n                    default:\n                    case sMappingTab: return m_MappingEditor;\n                }\n            }\n            set\n            {\n                switch (m_TabIndex)\n                {\n                    case sMuscleTab: m_MuscleEditor = value as AvatarMuscleEditor; break;\n                    default:\n                    case sMappingTab: m_MappingEditor = value as AvatarMappingEditor; break;\n                }\n            }\n        }\n        private AvatarMuscleEditor m_MuscleEditor;\n        private AvatarMappingEditor m_MappingEditor;\n\n        const int sMappingTab = 0;\n        const int sMuscleTab = 1;\n\n        public GameObject prefab\n        {\n            get\n            {\n                string path = AssetDatabase.GetAssetPath(target);\n                return AssetDatabase.LoadMainAssetAtPath(path) as GameObject;\n            }\n        }\n\n        static private SerializedObject CreateSerializedImporterForTarget(UnityEngine.Object target)\n        {\n            SerializedObject so = null;\n\n            AssetImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(target));\n            if (importer != null)\n            {\n                so = new SerializedObject(importer);\n            }\n            return so;\n        }\n\n        void OnEnable()\n        {\n            EditorApplication.update += Update;\n            SceneView.duringSceneGui += OnSceneGUI;\n\n            m_SwitchToEditMode = false;\n            if (m_EditMode == EditMode.Editing)\n            {\n                m_ModelBones = AvatarSetupTool.GetModelBones(m_GameObject.transform, false, null);\n                editor.Enable(this);\n            }\n            else if (m_EditMode == EditMode.NotEditing)\n            {\n                editor = null;\n\n                if (s_EditImmediatelyOnNextOpen)\n                {\n                    m_CameFromImportSettings = true;\n                    s_EditImmediatelyOnNextOpen = false;\n                }\n            }\n        }\n\n        void OnDisable()\n        {\n            SceneView.duringSceneGui -= OnSceneGUI;\n\n            if (m_EditMode == EditMode.Editing)\n                editor.Disable();\n\n            EditorApplication.update -= Update;\n\n            if (m_SerializedAssetImporter != null)\n            {\n                m_SerializedAssetImporter.Cache(GetInstanceID());\n                m_SerializedAssetImporter = null;\n            }\n        }\n\n        bool IsPartOfLockedInspector()\n        {\n            foreach (InspectorWindow i in InspectorWindow.GetAllInspectorWindows())\n            {\n                ActiveEditorTracker activeEditor = i.tracker;\n                foreach (Editor e in activeEditor.activeEditors)\n                {\n                    if (e == this && i.isLocked)\n                    {\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        void OnDestroy()\n        {\n            // If multiple Inspectors are open we want to prevent an unlocked Inspector from\n            // closing the Avatar stage on selection change therefore we only return to\n            // the main stage if a locked Inspector is destroyed (case 1330120).\n            if (IsPartOfLockedInspector())\n            {\n                // If AvatarEditor is destroyed for some other reason than exiting\n                // avatar configuration explicitly - this can for example happen\n                // when entering or exiting Play Mode, since this rebuilds all\n                // editors in the Inspector - ensure we exit the\n                // Avatar Configuration Stage if it's still open.\n                // This will also trigger cleanup of the editor.\n                if (StageNavigationManager.instance.currentStage is AvatarConfigurationStage)\n                    StageUtility.GoToMainStage();\n            }\n        }\n\n        void SelectAsset()\n        {\n            UnityEngine.Object obj;\n            if (m_CameFromImportSettings)\n            {\n                string path = AssetDatabase.GetAssetPath(target);\n                obj = AssetDatabase.LoadMainAssetAtPath(path);\n            }\n            else\n                obj = target;\n\n            Selection.activeObject = obj;\n        }\n\n        protected void CreateEditor()\n        {\n            switch (m_TabIndex)\n            {\n                case sMuscleTab: editor = ScriptableObject.CreateInstance<AvatarMuscleEditor>(); break;\n                default:\n                case sMappingTab: editor = ScriptableObject.CreateInstance<AvatarMappingEditor>(); break;\n            }\n\n            editor.hideFlags = HideFlags.HideAndDontSave;\n            editor.Enable(this);\n        }\n\n        protected void DestroyEditor()\n        {\n            editor.OnDestroy();\n            editor = null;\n        }\n\n        // @TODO@MECANIM: Implement context Reset - probably best in C++\n        /*[MenuItem (\"CONTEXT/Avatar/Reset\")]\n        static void ResetValues (MenuCommand command)\n        {\n            Debug.Log (\"Reset\");\n\n            AssetImporter importer = AssetImporter.GetAtPath (AssetDatabase.GetAssetPath (command.context));\n            SerializedObject serializedObject = new SerializedObject (importer);\n\n            if (importer && serializedObject != null)\n            {\n                string sHuman = \"m_HumanDescription.m_Human\";\n                string sSkeleton = \"m_HumanDescription.m_Skeleton\";\n                SerializedProperty human = serializedObject.FindProperty (sHuman);\n                if (human != null && human.isArray)\n                    human.ClearArray ();\n\n                SerializedProperty skeleton = serializedObject.FindProperty (sSkeleton);\n                if (skeleton != null && skeleton.isArray)\n                    skeleton.ClearArray ();\n\n                if (GetCurrentEditor () != null)\n                {\n                    GetCurrentEditor ().ApplyAndImport ();\n                    GetCurrentEditor ().OnEnable (this);\n                }\n            }\n        }*/\n\n        public override bool UseDefaultMargins() { return false; }\n\n        public override void OnInspectorGUI()\n        {\n            GUI.enabled = true;\n\n            using (new EditorGUILayout.VerticalScope(EditorStyles.inspectorFullWidthMargins))\n            {\n                if (m_EditMode == EditMode.Editing)\n                {\n                    EditingGUI();\n                }\n                else if (!m_CameFromImportSettings)\n                {\n                    EditButtonGUI();\n                }\n                else\n                {\n                    if (m_EditMode == EditMode.NotEditing && Event.current.type == EventType.Repaint)\n                    {\n                        m_SwitchToEditMode = true;\n                    }\n                }\n            }\n        }\n\n        void EditButtonGUI()\n        {\n            if (avatar == null || !avatar.isHuman)\n                return;\n\n            // Can only edit avatar from a model importer\n            string assetPath = AssetDatabase.GetAssetPath(avatar);\n            ModelImporter modelImporter = AssetImporter.GetAtPath(assetPath) as ModelImporter;\n            if (modelImporter == null)\n                return;\n\n            using (new EditorGUILayout.HorizontalScope())\n            {\n                GUILayout.FlexibleSpace();\n                if (GUILayout.Button(styles.editCharacter, GUILayout.Width(120)))\n                {\n                    SwitchToEditMode();\n                    GUIUtility.ExitGUI();\n                }\n\n                GUILayout.FlexibleSpace();\n            }\n        }\n\n        void EditingGUI()\n        {\n            using (new EditorGUILayout.HorizontalScope())\n            {\n                GUILayout.FlexibleSpace();\n                {\n                    int tabIndex = m_TabIndex;\n                    bool wasEnable = GUI.enabled;\n                    GUI.enabled = !(avatar == null || !avatar.isHuman);\n                    tabIndex = GUILayout.Toolbar(tabIndex, styles.tabs, \"LargeButton\",\n                        GUI.ToolbarButtonSize.FitToContents);\n                    GUI.enabled = wasEnable;\n                    if (tabIndex != m_TabIndex)\n                    {\n                        DestroyEditor();\n                        if (avatar != null && avatar.isHuman)\n                            m_TabIndex = tabIndex;\n\n                        CreateEditor();\n                    }\n                }\n                GUILayout.FlexibleSpace();\n            }\n\n            editor.OnInspectorGUI();\n        }\n\n        public void OnSceneGUI(SceneView view)\n        {\n            if (m_EditMode == EditMode.Editing)\n                editor.OnSceneGUI();\n        }\n\n        internal void SwitchToEditMode()\n        {\n            // Lock inspector\n            ChangeInspectorLock(true);\n\n            string assetPath = AssetDatabase.GetAssetPath(target);\n            AvatarConfigurationStage stage = AvatarConfigurationStage.CreateStage(assetPath, this);\n            StageUtility.GoToStage(stage, true);\n\n            m_EditMode = EditMode.Starting;\n\n            // Instantiate character\n            m_GameObject = stage.gameObject;\n            if (serializedAssetImporter.FindProperty(\"m_OptimizeGameObjects\").boolValue)\n                AnimatorUtility.DeoptimizeTransformHierarchy(m_GameObject);\n\n            SerializedProperty humanBoneArray = serializedAssetImporter.FindProperty(\"m_HumanDescription.m_Human\");\n\n            // First get all available modelBones\n            Dictionary<Transform, bool> modelBones = AvatarSetupTool.GetModelBones(m_GameObject.transform, true, null);\n            AvatarSetupTool.BoneWrapper[] humanBones = AvatarSetupTool.GetHumanBones(humanBoneArray, modelBones);\n\n            m_ModelBones = AvatarSetupTool.GetModelBones(m_GameObject.transform, false, humanBones);\n\n            // Unfold all nodes in hierarchy\n            // TODO@MECANIM: Only expand actual bones\n            foreach (SceneHierarchyWindow shw in Resources.FindObjectsOfTypeAll(typeof(SceneHierarchyWindow)))\n                shw.SetExpandedRecursive(m_GameObject.GetInstanceID(), true);\n\n            CreateEditor();\n\n            m_EditMode = EditMode.Editing;\n        }\n\n        internal void SwitchToAssetMode()\n        {\n            StageUtility.GoToMainStage();\n        }\n\n        internal void CleanupEditor()\n        {\n            bool selectAvatarAsset = StageUtility.GetCurrentStageHandle() == StageUtility.GetMainStageHandle();\n\n            m_EditMode = EditMode.Stopping;\n\n            DestroyEditor();\n\n            ChangeInspectorLock(m_InspectorLocked);\n\n            EditorApplication.CallbackFunction CleanUpOnDestroy = null;\n            CleanUpOnDestroy = () =>\n            {\n                // Make sure that we restore the \"original\" selection if we exit Avatar Editing mode\n                // from the avatar tooling itself (e.g by clicking done).\n                if (selectAvatarAsset)\n                    SelectAsset();\n\n                if (!m_CameFromImportSettings)\n                    m_EditMode = EditMode.NotEditing;\n\n                EditorApplication.update -= CleanUpOnDestroy;\n            };\n\n            EditorApplication.update += CleanUpOnDestroy;\n\n            // Reset back the Edit Mode specific states (they probably should be better encapsulated)\n            m_GameObject = null;\n            m_ModelBones = null;\n        }\n\n        void ChangeInspectorLock(bool locked)\n        {\n            foreach (InspectorWindow i in InspectorWindow.GetAllInspectorWindows())\n            {\n                ActiveEditorTracker activeEditor = i.tracker;\n                foreach (Editor e in activeEditor.activeEditors)\n                {\n                    if (e == this)\n                    {\n                        m_InspectorLocked = i.isLocked;\n                        i.isLocked = locked;\n                    }\n                }\n            }\n        }\n\n        public void Update()\n        {\n            if (m_SwitchToEditMode)\n            {\n                m_SwitchToEditMode = false;\n                SwitchToEditMode();\n\n                Repaint();\n            }\n\n            if (m_EditMode == EditMode.Editing)\n            {\n                if (m_GameObject == null || m_ModelBones == null)\n                    SwitchToAssetMode();\n\n                else if (m_ModelBones != null)\n                {\n                    foreach (KeyValuePair<Transform, bool> pair in m_ModelBones)\n                    {\n                        if (pair.Key == null)\n                        {\n                            SwitchToAssetMode();\n                            return;\n                        }\n                    }\n                }\n            }\n        }\n\n        public bool HasFrameBounds()\n        {\n            if (m_ModelBones != null)\n            {\n                foreach (KeyValuePair<Transform, bool> pair in m_ModelBones)\n                {\n                    if (pair.Key == Selection.activeTransform)\n                        return true;\n                }\n            }\n\n            return false;\n        }\n\n        public Bounds OnGetFrameBounds()\n        {\n            Transform bone = Selection.activeTransform;\n            Bounds bounds = new Bounds(bone.position, new Vector3(0, 0, 0));\n            foreach (Transform child in bone)\n                bounds.Encapsulate(child.position);\n\n            if (bone.parent) bounds.Encapsulate(bone.parent.position);\n\n            return bounds;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\nusing System.Linq;\n\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    public enum BoneState\n    {\n        None,\n        NotFound,\n        Duplicate,\n        InvalidHierarchy,\n        BoneLenghtIsZero,\n        Valid\n    }\n\n    [System.Serializable]\n    internal class AvatarMappingEditor : AvatarSubEditor\n    {\n        internal class Styles\n        {\n            public GUIContent[] BodyPartMapping =\n            {\n                EditorGUIUtility.TrTextContent(\"Avatar\"),\n                EditorGUIUtility.TrTextContent(\"Body\"),\n                EditorGUIUtility.TrTextContent(\"Head\"),\n                EditorGUIUtility.TrTextContent(\"Left Arm\"),\n                EditorGUIUtility.TrTextContent(\"Left Fingers\"),\n                EditorGUIUtility.TrTextContent(\"Right Arm\"),\n                EditorGUIUtility.TrTextContent(\"Right Fingers\"),\n                EditorGUIUtility.TrTextContent(\"Left Leg\"),\n                EditorGUIUtility.TrTextContent(\"Right Leg\")\n            };\n\n            public GUIContent RequiredBone = EditorGUIUtility.TrTextContent(\"Optional Bones\");\n            public GUIContent DoneCharacter = EditorGUIUtility.TrTextContent(\"Done\");\n\n            public GUIContent mapping = EditorGUIUtility.TrTextContent(\"Mapping\");\n            public GUIContent clearMapping = EditorGUIUtility.TrTextContent(\"Clear\");\n            public GUIContent autoMapping = EditorGUIUtility.TrTextContent(\"Automap\");\n            public GUIContent bipedMapping = EditorGUIUtility.TrTextContent(\"Biped\");\n            public GUIContent loadMapping = EditorGUIUtility.TrTextContent(\"Load\");\n            public GUIContent saveMapping = EditorGUIUtility.TrTextContent(\"Save\");\n\n            public GUIContent pose = EditorGUIUtility.TrTextContent(\"Pose\");\n            public GUIContent resetPose = EditorGUIUtility.TrTextContent(\"Reset\");\n            public GUIContent sampleBindPose = EditorGUIUtility.TrTextContent(\"Sample Bind-Pose\");\n            public GUIContent enforceTPose = EditorGUIUtility.TrTextContent(\"Enforce T-Pose\");\n            public GUIContent bipedPose = EditorGUIUtility.TrTextContent(\"Biped Pose\");\n\n            public GUIContent ShowError = EditorGUIUtility.TrTextContent(\"Show Error(s)...\");\n            public GUIContent CloseError = EditorGUIUtility.TrTextContent(\"Close Error(s)\");\n\n            public GUIContent dotFill = EditorGUIUtility.IconContent(\"AvatarInspector/DotFill\");\n            public GUIContent dotFrame = EditorGUIUtility.IconContent(\"AvatarInspector/DotFrame\");\n            public GUIContent dotFrameDotted = EditorGUIUtility.IconContent(\"AvatarInspector/DotFrameDotted\");\n            public GUIContent dotSelection = EditorGUIUtility.IconContent(\"AvatarInspector/DotSelection\");\n\n            public GUIStyle box = \"AvatarMappingBox\";\n            public GUIStyle toolbar = \"TE Toolbar\";\n            public GUIStyle toolbarDropDown = \"TE ToolbarDropDown\";\n\n            public GUIStyle errorLabel = \"AvatarMappingErrorLabel\";\n        }\n\n        internal static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } }\n        static Styles s_Styles;\n\n        private SerializedProperty m_HumanBoneArray;\n        private SerializedProperty m_Skeleton;\n        private SerializedProperty m_AutoGenerateAvatarMappingIfUnspecified;\n\n        protected bool[]        m_BodyPartToggle;\n        protected bool[]        m_BodyPartFoldout;\n        protected int m_BodyView = 0;\n\n        [SerializeField]\n        protected AvatarSetupTool.BoneWrapper[] m_Bones;\n        internal static int s_SelectedBoneIndex = -1;\n        internal static bool s_DirtySelection = false;\n        internal static int s_KeyboardControl = 0;\n        protected bool m_HasSkinnedMesh;\n        bool m_IsBiped;\n\n        Editor m_CurrentTransformEditor;\n        bool m_CurrentTransformEditorFoldout;\n\n        private readonly Handles.BoneRenderer m_BoneRenderer = new Handles.BoneRenderer();\n\n        // This list containt the mecanim's human bones id for each body part\n        protected int[][] m_BodyPartHumanBone =\n        {\n            new int[] {-1},\n            new int[] { (int)HumanBodyBones.Hips, (int)HumanBodyBones.Spine, (int)HumanBodyBones.Chest, (int)HumanBodyBones.UpperChest},\n            new int[] { (int)HumanBodyBones.Neck, (int)HumanBodyBones.Head, (int)HumanBodyBones.LeftEye, (int)HumanBodyBones.RightEye, (int)HumanBodyBones.Jaw},\n            new int[] { (int)HumanBodyBones.LeftShoulder, (int)HumanBodyBones.LeftUpperArm, (int)HumanBodyBones.LeftLowerArm, (int)HumanBodyBones.LeftHand},\n            new int[]\n            {\n                (int)HumanBodyBones.LeftThumbProximal , (int)HumanBodyBones.LeftThumbIntermediate, (int)HumanBodyBones.LeftThumbDistal,\n                (int)HumanBodyBones.LeftIndexProximal , (int)HumanBodyBones.LeftIndexIntermediate, (int)HumanBodyBones.LeftIndexDistal,\n                (int)HumanBodyBones.LeftMiddleProximal , (int)HumanBodyBones.LeftMiddleIntermediate, (int)HumanBodyBones.LeftMiddleDistal,\n                (int)HumanBodyBones.LeftRingProximal , (int)HumanBodyBones.LeftRingIntermediate, (int)HumanBodyBones.LeftRingDistal,\n                (int)HumanBodyBones.LeftLittleProximal , (int)HumanBodyBones.LeftLittleIntermediate, (int)HumanBodyBones.LeftLittleDistal\n            },\n            new int[] { (int)HumanBodyBones.RightShoulder, (int)HumanBodyBones.RightUpperArm, (int)HumanBodyBones.RightLowerArm, (int)HumanBodyBones.RightHand},\n            new int[]\n            {\n                (int)HumanBodyBones.RightThumbProximal , (int)HumanBodyBones.RightThumbIntermediate, (int)HumanBodyBones.RightThumbDistal,\n                (int)HumanBodyBones.RightIndexProximal , (int)HumanBodyBones.RightIndexIntermediate, (int)HumanBodyBones.RightIndexDistal,\n                (int)HumanBodyBones.RightMiddleProximal , (int)HumanBodyBones.RightMiddleIntermediate, (int)HumanBodyBones.RightMiddleDistal,\n                (int)HumanBodyBones.RightRingProximal , (int)HumanBodyBones.RightRingIntermediate, (int)HumanBodyBones.RightRingDistal,\n                (int)HumanBodyBones.RightLittleProximal , (int)HumanBodyBones.RightLittleIntermediate, (int)HumanBodyBones.RightLittleDistal\n            },\n            new int[] { (int)HumanBodyBones.LeftUpperLeg, (int)HumanBodyBones.LeftLowerLeg, (int)HumanBodyBones.LeftFoot, (int)HumanBodyBones.LeftToes},\n            new int[] { (int)HumanBodyBones.RightUpperLeg, (int)HumanBodyBones.RightLowerLeg, (int)HumanBodyBones.RightFoot, (int)HumanBodyBones.RightToes}\n        };\n\n        public AvatarMappingEditor()\n        {\n            m_BodyPartToggle = new bool[(int)BodyPart.Last];\n            m_BodyPartFoldout = new bool[(int)BodyPart.Last];\n            for (int i = 0; i < (int)BodyPart.Last; i++)\n            {\n                m_BodyPartToggle[i] = false;\n                m_BodyPartFoldout[i] = true;\n            }\n        }\n\n        public override void Enable(AvatarEditor inspector)\n        {\n            base.Enable(inspector);\n            Init();\n        }\n\n        public override void Disable()\n        {\n            if (m_CurrentTransformEditor != null)\n                DestroyImmediate(m_CurrentTransformEditor);\n\n            base.Disable();\n        }\n\n        public override void OnDestroy()\n        {\n            if (m_CurrentTransformEditor != null)\n                DestroyImmediate(m_CurrentTransformEditor);\n            base.OnDestroy();\n        }\n\n        protected void Init()\n        {\n            if (gameObject == null)\n                return;\n\n            m_HumanBoneArray = serializedObject.FindProperty(\"m_HumanDescription.m_Human\");\n            m_Skeleton = serializedObject.FindProperty(\"m_HumanDescription.m_Skeleton\");\n            m_AutoGenerateAvatarMappingIfUnspecified = serializedObject.FindProperty(\"m_AutoGenerateAvatarMappingIfUnspecified\");\n\n            m_IsBiped = AvatarBipedMapper.IsBiped(gameObject.transform, null);\n\n            // Handle human bones\n            if (m_Bones == null)\n                m_Bones = AvatarSetupTool.GetHumanBones(m_HumanBoneArray, modelBones);\n            ValidateMapping();\n\n            if (m_CurrentTransformEditor != null)\n            {\n                DestroyImmediate(m_CurrentTransformEditor);\n                m_CurrentTransformEditor = null;\n            }\n            m_CurrentTransformEditorFoldout = true;\n            m_HasSkinnedMesh = (gameObject.GetComponentInChildren<SkinnedMeshRenderer>() != null);\n\n            // Handle pose\n            InitPose();\n\n            // Repaint\n            SceneView.RepaintAll();\n        }\n\n        protected override void ResetValues()\n        {\n            base.ResetValues();\n            ResetBones();\n            Init();\n        }\n\n        protected void ResetBones()\n        {\n            for (int i = 0; i < m_Bones.Length; i++)\n                m_Bones[i].Reset(m_HumanBoneArray, modelBones);\n        }\n\n        protected bool IsValidHuman()\n        {\n            Animator animator = gameObject.GetComponent<Animator>();\n            if (animator == null)\n                return false;\n\n            Avatar avatar = animator.avatar;\n            return avatar != null && avatar.isHuman;\n        }\n\n        protected void InitPose()\n        {\n            if (IsValidHuman())\n            {\n                Animator animator = gameObject.GetComponent<Animator>();\n                animator.WriteDefaultPose();\n                AvatarSetupTool.TransferDescriptionToPose(serializedObject, root);\n            }\n        }\n\n        protected void ValidateMapping()\n        {\n            for (int i = 0; i < m_Bones.Length; i++)\n            {\n                string error;\n                m_Bones[i].state = GetBoneState(i, out error);\n                m_Bones[i].error = error;\n            }\n        }\n\n        private void EnableBodyParts(bool[] toggles, params int[] parts)\n        {\n            for (int i = 0; i < m_BodyPartToggle.Length; i++)\n                toggles[i] = false;\n            foreach (int i in parts)\n                toggles[i] = true;\n        }\n\n        private void HandleBodyView(int bodyView)\n        {\n            if (bodyView == 0)\n                EnableBodyParts(m_BodyPartToggle, 1, 3, 5, 7, 8);\n            if (bodyView == 1)\n                EnableBodyParts(m_BodyPartToggle, 2);\n            if (bodyView == 2)\n                EnableBodyParts(m_BodyPartToggle, 4);\n            if (bodyView == 3)\n                EnableBodyParts(m_BodyPartToggle, 6);\n        }\n\n        Vector2 m_FoldoutScroll = Vector2.zero;\n\n        private void SetupInternalProperties()\n        {\n            m_HumanBoneArray = serializedObject.FindProperty(\"m_HumanDescription.m_Human\");\n            m_Skeleton = serializedObject.FindProperty(\"m_HumanDescription.m_Skeleton\");\n        }\n\n        private void HandleUndoPerformed()\n        {\n            if (Event.current.type == EventType.ValidateCommand && Event.current.commandName == EventCommandNames.UndoRedoPerformed)\n            {\n                SetupInternalProperties();\n\n                AvatarSetupTool.TransferPoseToDescription(m_Skeleton, root);\n                for (int i = 0; i < m_Bones.Length; i++)\n                    m_Bones[i].Serialize(m_HumanBoneArray);\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            HandleUndoPerformed();\n            UpdateSelectedBone();\n\n            // case 837655.  GUI.keyboardControl is overriden when changing scene selection.\n            // Late update here to bypass this issue.\n            if (s_KeyboardControl != 0)\n            {\n                GUIUtility.keyboardControl = s_KeyboardControl;\n                s_KeyboardControl = 0;\n            }\n\n            GUILayout.BeginVertical();\n            {\n                EditorGUI.BeginChangeCheck();\n\n                GUILayout.BeginVertical(\"\", \"TE NodeBackground\");\n                {\n                    m_BodyView = AvatarControl.ShowBoneMapping(m_BodyView, new AvatarControl.BodyPartFeedback(this.IsValidBodyPart), m_Bones, serializedObject, this);\n                    HandleBodyView(m_BodyView);\n                }\n                GUILayout.EndVertical();\n\n                m_FoldoutScroll = GUILayout.BeginScrollView(m_FoldoutScroll, styles.box, GUILayout.MinHeight(80), GUILayout.MaxHeight(510), GUILayout.ExpandHeight(true));\n                {\n                    DisplayFoldout();\n                    GUILayout.FlexibleSpace();\n                }\n                GUILayout.EndScrollView();\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    ValidateMapping();\n                    SceneView.RepaintAll();\n                }\n\n                DisplayMappingButtons();\n            }\n            GUILayout.EndVertical();\n\n            if (EditorGUIUtility.hotControl == 0)\n                TransferPoseIfChanged();\n\n            //DebugPoseButtons ();\n\n            ApplyRevertGUI();\n\n            if (Selection.activeTransform != null)\n            {\n                // Selection is changing, clean up before we create a new editor\n                if (m_CurrentTransformEditor != null && m_CurrentTransformEditor.target != Selection.activeTransform)\n                    DestroyImmediate(m_CurrentTransformEditor);\n\n                if (m_CurrentTransformEditor == null)\n                    m_CurrentTransformEditor = Editor.CreateEditor(Selection.activeTransform);\n\n                EditorGUILayout.Space();\n                m_CurrentTransformEditorFoldout = EditorGUILayout.InspectorTitlebar(m_CurrentTransformEditorFoldout, Selection.activeTransform, true);\n\n                if (m_CurrentTransformEditorFoldout && m_CurrentTransformEditor != null)\n                    m_CurrentTransformEditor.OnInspectorGUI();\n            }\n            else if (m_CurrentTransformEditor != null)\n            {\n                DestroyImmediate(m_CurrentTransformEditor);\n                m_CurrentTransformEditor = null;\n            }\n        }\n\n        protected void DebugPoseButtons()\n        {\n            if (GUILayout.Button(\"Default Pose\") && IsValidHuman())\n            {\n                Animator animator = gameObject.GetComponent<Animator>();\n                animator.WriteDefaultPose();\n            }\n            if (GUILayout.Button(\"Description Pose\"))\n                AvatarSetupTool.TransferDescriptionToPose(serializedObject, root);\n        }\n\n        protected void TransferPoseIfChanged()\n        {\n            foreach (GameObject selected in Selection.gameObjects)\n            {\n                if (TransformChanged(selected.transform))\n                {\n                    AvatarSetupTool.TransferPoseToDescription(m_Skeleton, root);\n                    m_Inspector.Repaint();\n                    break;\n                }\n            }\n        }\n\n        protected void DisplayMappingButtons()\n        {\n            GUILayout.BeginHorizontal(\"\", styles.toolbar, GUILayout.ExpandWidth(true));\n            {\n                Rect r;\n\n                // Mapping\n                r = GUILayoutUtility.GetRect(styles.mapping, styles.toolbarDropDown);\n                if (GUI.Button(r, styles.mapping, styles.toolbarDropDown))\n                {\n                    GenericMenu menu = new GenericMenu();\n                    menu.AddItem(styles.clearMapping, false, ClearMapping);\n                    if (m_IsBiped)\n                        menu.AddItem(styles.bipedMapping, false, PerformBipedMapping);\n                    menu.AddItem(styles.autoMapping, false, PerformAutoMapping);\n                    menu.AddItem(styles.loadMapping, false, ApplyTemplate);\n                    menu.AddItem(styles.saveMapping, false, SaveHumanTemplate);\n                    menu.DropDown(r);\n                }\n\n                // Pose\n                r = GUILayoutUtility.GetRect(styles.pose, styles.toolbarDropDown);\n                if (GUI.Button(r, styles.pose, styles.toolbarDropDown))\n                {\n                    GenericMenu menu = new GenericMenu();\n                    menu.AddItem(styles.resetPose, false, CopyPrefabPose);\n                    if (m_IsBiped)\n                        menu.AddItem(styles.bipedPose, false, BipedPose);\n                    if (m_HasSkinnedMesh)\n                        menu.AddItem(styles.sampleBindPose, false, SampleBindPose);\n                    else\n                        menu.AddItem(styles.sampleBindPose, false, null);\n                    menu.AddItem(styles.enforceTPose, false, MakePoseValid);\n                    menu.DropDown(r);\n                }\n\n                GUILayout.FlexibleSpace();\n            }\n            GUILayout.EndHorizontal();\n        }\n\n        protected void CopyPrefabPose()\n        {\n            AvatarSetupTool.CopyPose(gameObject, prefab);\n            AvatarSetupTool.TransferPoseToDescription(m_Skeleton, root);\n            m_Inspector.Repaint();\n        }\n\n        protected void SampleBindPose()\n        {\n            AvatarSetupTool.SampleBindPose(gameObject);\n            AvatarSetupTool.TransferPoseToDescription(m_Skeleton, root);\n            m_Inspector.Repaint();\n        }\n\n        protected void BipedPose()\n        {\n            AvatarBipedMapper.BipedPose(gameObject, m_Bones);\n\n            AvatarSetupTool.TransferPoseToDescription(m_Skeleton, root);\n            m_Inspector.Repaint();\n        }\n\n        protected void MakePoseValid()\n        {\n            AvatarSetupTool.MakePoseValid(m_Bones);\n            AvatarSetupTool.TransferPoseToDescription(m_Skeleton, root);\n            m_Inspector.Repaint();\n        }\n\n        protected void PerformAutoMapping()\n        {\n            AutoMapping();\n            ValidateMapping();\n            SceneView.RepaintAll();\n        }\n\n        protected void PerformBipedMapping()\n        {\n            BipedMapping();\n            ValidateMapping();\n            SceneView.RepaintAll();\n        }\n\n        protected void AutoMapping()\n        {\n            Dictionary<int, Transform> mapping = AvatarAutoMapper.MapBones(gameObject.transform, modelBones);\n            foreach (KeyValuePair<int, Transform> kvp in mapping)\n            {\n                AvatarSetupTool.BoneWrapper bone = m_Bones[kvp.Key];\n                bone.bone = kvp.Value;\n                bone.Serialize(m_HumanBoneArray);\n            }\n            m_AutoGenerateAvatarMappingIfUnspecified.boolValue = false;\n        }\n\n        protected void BipedMapping()\n        {\n            Dictionary<int, Transform> mapping = AvatarBipedMapper.MapBones(gameObject.transform);\n            foreach (KeyValuePair<int, Transform> kvp in mapping)\n            {\n                AvatarSetupTool.BoneWrapper bone = m_Bones[kvp.Key];\n                bone.bone = kvp.Value;\n                bone.Serialize(m_HumanBoneArray);\n            }\n            m_AutoGenerateAvatarMappingIfUnspecified.boolValue = false;\n        }\n\n        protected void ClearMapping()\n        {\n            if (serializedObject != null)\n            {\n                Undo.RegisterCompleteObjectUndo(this, \"Clear Mapping\");\n                AvatarSetupTool.ClearHumanBoneArray(m_HumanBoneArray);\n                ResetBones();\n                ValidateMapping();\n                m_AutoGenerateAvatarMappingIfUnspecified.boolValue = false;\n                SceneView.RepaintAll();\n            }\n        }\n\n        protected Vector4 QuaternionToVector4(Quaternion rot)\n        {\n            return new Vector4(rot.x, rot.y, rot.z, rot.w);\n        }\n\n        protected Quaternion Vector4ToQuaternion(Vector4 rot)\n        {\n            return new Quaternion(rot.x, rot.y, rot.z, rot.w);\n        }\n\n        protected bool IsAnyBodyPartActive()\n        {\n            // Avatar body part has nothing to show\n            for (int i = 1; i < m_BodyPartToggle.Length; i++)\n            {\n                if (m_BodyPartToggle[i])\n                    return true;\n            }\n            return false;\n        }\n\n        private void UpdateSelectedBone()\n        {\n            // Look for selected bone slot\n            int oldSelectedBoneIndex = s_SelectedBoneIndex;\n            if (s_SelectedBoneIndex < 0 || s_SelectedBoneIndex >= m_Bones.Length || m_Bones[s_SelectedBoneIndex].bone != Selection.activeTransform)\n            {\n                s_SelectedBoneIndex = -1;\n                if (Selection.activeTransform != null)\n                {\n                    for (int i = 0; i < m_Bones.Length; i++)\n                    {\n                        if (m_Bones[i].bone == Selection.activeTransform)\n                        {\n                            s_SelectedBoneIndex = i;\n                            break;\n                        }\n                    }\n                }\n            }\n            if (s_SelectedBoneIndex != oldSelectedBoneIndex)\n            {\n                // If selected bone changed, change visual to show image that contains that bone.\n                List<int> views = AvatarControl.GetViewsThatContainBone(s_SelectedBoneIndex);\n                if (views.Count > 0 && !views.Contains(m_BodyView))\n                    m_BodyView = views[0];\n            }\n        }\n\n        protected void DisplayFoldout()\n        {\n            Dictionary<Transform, bool> bones = modelBones;\n\n            EditorGUIUtility.SetIconSize(Vector2.one * 16);\n\n            // Legend\n            EditorGUILayout.BeginHorizontal();\n            GUI.color = Color.grey;\n            GUILayout.Label(styles.dotFrameDotted.image, GUILayout.ExpandWidth(false));\n            GUI.color = Color.white;\n            GUILayout.Label(\"Optional Bone\", GUILayout.ExpandWidth(true));\n            EditorGUILayout.EndHorizontal();\n\n            // Avatar body part has nothing to show\n            for (int i = 1; i < m_BodyPartToggle.Length; i++)\n            {\n                if (m_BodyPartToggle[i])\n                {\n                    //  Unfold body part ui whenever a new selection is made.\n                    if ((s_DirtySelection == true) && (m_BodyPartFoldout[i] == false))\n                    {\n                        for (int j = 0; j < m_BodyPartHumanBone[i].Length; j++)\n                        {\n                            int boneIndex = m_BodyPartHumanBone[i][j];\n                            if (s_SelectedBoneIndex == boneIndex)\n                                m_BodyPartFoldout[i] = true;\n                        }\n                    }\n\n                    m_BodyPartFoldout[i] = GUILayout.Toggle(m_BodyPartFoldout[i], styles.BodyPartMapping[i], EditorStyles.foldout);\n                    EditorGUI.indentLevel++;\n                    if (m_BodyPartFoldout[i])\n                    {\n                        for (int j = 0; j < m_BodyPartHumanBone[i].Length; j++)\n                        {\n                            int boneIndex = m_BodyPartHumanBone[i][j];\n                            if (boneIndex == -1)\n                                continue;\n\n                            AvatarSetupTool.BoneWrapper bone = m_Bones[boneIndex];\n                            string displayBoneName = bone.humanBoneName;\n\n                            // @TODO@MECANIM: do properly\n                            if ((BodyPart)i == BodyPart.RightArm || (BodyPart)i == BodyPart.RightFingers || (BodyPart)i == BodyPart.RightLeg)\n                                displayBoneName = displayBoneName.Replace(\"Right\", \"\");\n                            if ((BodyPart)i == BodyPart.LeftArm || (BodyPart)i == BodyPart.LeftFingers || (BodyPart)i == BodyPart.LeftLeg)\n                                displayBoneName = displayBoneName.Replace(\"Left\", \"\");\n\n                            displayBoneName = ObjectNames.NicifyVariableName(displayBoneName);\n\n                            Rect r = EditorGUILayout.GetControlRect();\n\n                            Rect selectRect = r;\n                            selectRect.width -= 15;\n\n                            Rect rect = new Rect(r.x + EditorGUI.indent, r.y - 1, AvatarSetupTool.BoneWrapper.kIconSize, AvatarSetupTool.BoneWrapper.kIconSize);\n\n                            bone.BoneDotGUI(rect, selectRect, boneIndex, true, false, true, serializedObject, this);\n                            r.xMin += AvatarSetupTool.BoneWrapper.kIconSize;\n\n                            Transform newBoneTransform = EditorGUI.ObjectField(r, new GUIContent(displayBoneName), bone.bone, typeof(Transform), true) as Transform;\n                            if (newBoneTransform != bone.bone)\n                            {\n                                Undo.RegisterCompleteObjectUndo(this, \"Avatar mapping modified\");\n                                bone.bone = newBoneTransform;\n                                bone.Serialize(m_HumanBoneArray);\n\n                                // User adding a bone manually, if it not in the modelBones dict, we must explictly add it\n                                if (newBoneTransform != null && !bones.ContainsKey(newBoneTransform))\n                                    bones[newBoneTransform] = true;\n                            }\n\n                            if (!string.IsNullOrEmpty(bone.error))\n                            {\n                                GUILayout.BeginHorizontal();\n                                GUILayout.Space(EditorGUI.indent + AvatarSetupTool.BoneWrapper.kIconSize + 4);\n                                GUILayout.Label(bone.error, s_Styles.errorLabel);\n                                GUILayout.EndHorizontal();\n                            }\n                        }\n                    }\n                    EditorGUI.indentLevel--;\n                }\n            }\n\n            s_DirtySelection = false;\n\n            EditorGUIUtility.SetIconSize(Vector2.zero);\n        }\n\n        bool TransformChanged(Transform tr)\n        {\n            SerializedProperty bone = AvatarSetupTool.FindSkeletonBone(serializedObject, tr, false, false);\n            if (bone != null)\n            {\n                SerializedProperty positionP = bone.FindPropertyRelative(AvatarSetupTool.sPosition);\n                if (positionP != null && positionP.vector3Value != tr.localPosition)\n                    return true;\n\n                SerializedProperty rotationP = bone.FindPropertyRelative(AvatarSetupTool.sRotation);\n                if (rotationP != null && rotationP.quaternionValue != tr.localRotation)\n                    return true;\n\n                SerializedProperty scaleP = bone.FindPropertyRelative(AvatarSetupTool.sScale);\n                if (scaleP != null && scaleP.vector3Value != tr.localScale)\n                    return true;\n            }\n            return false;\n        }\n\n        protected BoneState GetBoneState(int i, out string error)\n        {\n            error = string.Empty;\n            AvatarSetupTool.BoneWrapper bone = m_Bones[i];\n\n            if (bone.bone == null)\n                return BoneState.None;\n\n            int ancestorIndex = AvatarSetupTool.GetFirstHumanBoneAncestor(m_Bones, i);\n\n            AvatarSetupTool.BoneWrapper ancestor = m_Bones[ancestorIndex > 0 ? ancestorIndex : 0];\n\n            if (i == 0 && bone.bone.parent == null)\n            {\n                error = bone.messageName + \" cannot be the root transform\";\n                return BoneState.InvalidHierarchy;\n            }\n\n            if (ancestor.bone != null && !bone.bone.IsChildOf(ancestor.bone))\n            {\n                error = bone.messageName + \" is not a child of \" + ancestor.messageName + \".\";\n                return BoneState.InvalidHierarchy;\n            }\n\n            if (i == (int)HumanBodyBones.UpperChest)\n            {\n                AvatarSetupTool.BoneWrapper chest = m_Bones[(int)HumanBodyBones.Chest];\n\n                if (chest.bone == null)\n                {\n                    error = \"Chest must be assigned before assigning UpperChest.\";\n                    return BoneState.InvalidHierarchy;\n                }\n            }\n\n            // Hips bone is a special case, for hips GetFirstAnscestor return hips\n            if (i != (int)HumanBodyBones.Jaw && ancestor.bone != null && ancestor.bone != bone.bone && (bone.bone.position - ancestor.bone.position).sqrMagnitude < Mathf.Epsilon)\n            {\n                error = bone.messageName + \" has bone length of zero.\";\n                return BoneState.BoneLenghtIsZero;\n            }\n\n            // Does this transfrom is already set\n            //List<BoneWrapper> match = ArrayUtility.FindAll (m_BoneWrappers, delegate (Transform t) { return t == m_BoneWrappers[i].bone; });\n            IEnumerable<AvatarSetupTool.BoneWrapper> match = m_Bones.Where(f => f.bone == bone.bone);\n            // when we search in the list we must add 1 because the bone is in this list\n            if (match.Count() > 1)\n            {\n                error = bone.messageName + \" is also assigned to \";\n                bool first = true;\n                for (int j = 0; j < m_Bones.Length; j++)\n                {\n                    if (i != j && m_Bones[i].bone == m_Bones[j].bone)\n                    {\n                        if (first)\n                            first = false;\n                        else\n                            error += \", \";\n                        error += ObjectNames.NicifyVariableName(m_Bones[j].humanBoneName);\n                    }\n                }\n                error += \".\";\n                return BoneState.Duplicate;\n            }\n            else\n                return BoneState.Valid;\n        }\n\n        protected AvatarControl.BodyPartColor IsValidBodyPart(BodyPart bodyPart)\n        {\n            AvatarControl.BodyPartColor ik = AvatarControl.BodyPartColor.Off;\n            bool hasAnyBone = false;\n\n            int idx = (int)bodyPart;\n            if (bodyPart != BodyPart.LeftFingers && bodyPart != BodyPart.RightFingers)\n            {\n                int i;\n                for (i = 0; i < m_BodyPartHumanBone[idx].Length; i++)\n                {\n                    if (m_BodyPartHumanBone[idx][i] != -1)\n                    {\n                        BoneState state = m_Bones[m_BodyPartHumanBone[idx][i]].state;\n                        hasAnyBone |= state == BoneState.Valid;\n\n                        // if it a required bone and no bone is set this body part is not valid\n                        if (HumanTrait.RequiredBone(m_BodyPartHumanBone[idx][i]) == true && state == BoneState.None)\n                            return AvatarControl.BodyPartColor.Red;\n                        else if (state != BoneState.Valid && state != BoneState.None)\n                            return AvatarControl.BodyPartColor.Red;\n                    }\n                }\n            }\n            else\n            {\n                bool hasAllFinger = true;\n\n                int i;\n                int phalangeCount = 3;\n                for (i = 0; i < m_BodyPartHumanBone[idx].Length / phalangeCount; i++)\n                {\n                    bool hasFinger = false;\n                    int fingerIndex = i * phalangeCount;\n                    int j;\n                    for (j = phalangeCount - 1; j >= 0; j--)\n                    {\n                        bool hasBone = m_Bones[m_BodyPartHumanBone[idx][fingerIndex + j]].state == BoneState.Valid;\n                        hasAllFinger &= hasBone;\n                        if (hasFinger)\n                        {\n                            if (!hasBone)\n                                return AvatarControl.BodyPartColor.Red | AvatarControl.BodyPartColor.IKRed;\n                        }\n                        else\n                            hasAnyBone |= hasFinger = !hasFinger && hasBone;\n                    }\n                }\n\n                ik = hasAllFinger ? AvatarControl.BodyPartColor.IKGreen : AvatarControl.BodyPartColor.IKRed;\n            }\n\n            if (!hasAnyBone)\n                return AvatarControl.BodyPartColor.Off | AvatarControl.BodyPartColor.IKRed;\n\n            return AvatarControl.BodyPartColor.Green | ik;\n        }\n\n        private HumanTemplate OpenHumanTemplate()\n        {\n            string assetsDirectory = \"Assets/\";\n\n            // Go forward with presenting user a save clip dialog\n            string templatePath = EditorUtility.OpenFilePanel(\"Open Human Template\", assetsDirectory, \"ht\");\n\n            // If user canceled or save path is invalid, we can't create a template\n            if (templatePath == \"\")\n                return null;\n\n            // At this point we know that we can create a template\n            string relativeTemplatePath = FileUtil.GetProjectRelativePath(templatePath);\n            HumanTemplate template = AssetDatabase.LoadMainAssetAtPath(relativeTemplatePath) as HumanTemplate;\n\n            // Asset not found in project, try to import it into the project\n            if (template == null)\n            {\n                if (EditorUtility.DisplayDialog(\"Human Template not found in project\", \"Import asset \\'\" + templatePath + \"\\' into project\", \"Yes\", \"No\"))\n                {\n                    string newFileName = assetsDirectory + FileUtil.GetLastPathNameComponent(templatePath);\n\n                    newFileName = AssetDatabase.GenerateUniqueAssetPath(newFileName);\n\n                    // Copy file\n                    FileUtil.CopyFileOrDirectory(templatePath, newFileName);\n\n                    AssetDatabase.Refresh();\n\n                    template = AssetDatabase.LoadMainAssetAtPath(newFileName) as HumanTemplate;\n\n                    if (template == null)\n                    {\n                        Debug.Log(\"Failed importing file \\'\" + templatePath + \"\\' to \\'\" + newFileName + \"\\'\");\n                    }\n                }\n            }\n            return template;\n        }\n\n        static public bool MatchName(string transformName, string boneName)\n        {\n            string delimStr = \":\";\n            char[] delimiter = delimStr.ToCharArray();\n\n            string[] transformSplit = transformName.Split(delimiter);\n            string[] boneSplit = boneName.Split(delimiter);\n\n            return transformName == boneName ||\n                (transformSplit.Length > 1 && transformSplit[1] == boneName) ||  // transform does have a prefix\n                (boneSplit.Length > 1 && transformName == boneSplit[1]) ||  // boneName does have a prefix\n                (transformSplit.Length > 1 && boneSplit.Length > 1 && transformSplit[1] == boneSplit[1]);  // both have a different prefix\n        }\n\n        protected void ApplyTemplate()\n        {\n            Undo.RegisterCompleteObjectUndo(this, \"Apply Template\");\n\n            HumanTemplate humanTemplate = OpenHumanTemplate();\n            if (humanTemplate == null)\n                return;\n\n            for (int i = 0; i < m_Bones.Length; i++)\n            {\n                string boneName = humanTemplate.Find(m_Bones[i].humanBoneName);\n                if (boneName.Length > 0)\n                {\n                    Transform transform = modelBones.Keys.FirstOrDefault(f => AvatarMappingEditor.MatchName(f.name, boneName));\n                    m_Bones[i].bone = transform;\n                }\n                else\n                {\n                    m_Bones[i].bone = null;\n                }\n                m_Bones[i].Serialize(m_HumanBoneArray);\n            }\n\n            ValidateMapping();\n            SceneView.RepaintAll();\n        }\n\n        private void SaveHumanTemplate()\n        {\n            // Go forward with presenting user a save clip dialog\n            string newTemplatePath = EditorUtility.SaveFilePanelInProject(\"Create New Human Template\", \"New Human Template\", \"ht\", \"Create a new human template\");\n\n            // If user canceled or save path is invalid, we can't create a template\n            if (newTemplatePath == \"\")\n                return;\n\n            // At this point we know that we can create a template\n            HumanTemplate humanTemplate = new HumanTemplate();\n            humanTemplate.ClearTemplate();\n\n            for (int i = 0; i < m_Bones.Length; i++)\n            {\n                if (m_Bones[i].bone != null)\n                    humanTemplate.Insert(m_Bones[i].humanBoneName, m_Bones[i].bone.name);\n            }\n\n            AssetDatabase.CreateAsset(humanTemplate, newTemplatePath);\n        }\n\n        public override void OnSceneGUI()\n        {\n            // It seems styles can't safely be created from inside OnSceneGUI so not much we can do here. :(\n            if (s_Styles == null)\n                return;\n\n            AvatarSkeletonDrawer.DrawSkeleton(root, modelBones, m_Bones, m_BoneRenderer);\n\n            if (EditorGUIUtility.hotControl == 0)\n                TransferPoseIfChanged();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Avatar/AvatarMuscleEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    internal class AvatarMuscleEditor : AvatarSubEditor\n    {\n        class Styles\n        {\n            public GUIContent[] muscleBodyGroup =\n            {\n                EditorGUIUtility.TrTextContent(\"Body\"),\n                EditorGUIUtility.TrTextContent(\"Head\"),\n                EditorGUIUtility.TrTextContent(\"Left Arm\"),\n                EditorGUIUtility.TrTextContent(\"Left Fingers\"),\n                EditorGUIUtility.TrTextContent(\"Right Arm\"),\n                EditorGUIUtility.TrTextContent(\"Right Fingers\"),\n                EditorGUIUtility.TrTextContent(\"Left Leg\"),\n                EditorGUIUtility.TrTextContent(\"Right Leg\")\n            };\n\n            public GUIContent[] muscleTypeGroup =\n            {\n                EditorGUIUtility.TrTextContent(\"Open Close\"),\n                EditorGUIUtility.TrTextContent(\"Left Right\"),\n                EditorGUIUtility.TrTextContent(\"Roll Left Right\"),\n                EditorGUIUtility.TrTextContent(\"In Out\"),\n                EditorGUIUtility.TrTextContent(\"Roll In Out\"),\n                EditorGUIUtility.TrTextContent(\"Finger Open Close\"),\n                EditorGUIUtility.TrTextContent(\"Finger In Out\")\n            };\n\n            public GUIContent armTwist = EditorGUIUtility.TrTextContent(\"Upper Arm Twist\");\n            public GUIContent foreArmTwist = EditorGUIUtility.TrTextContent(\"Lower Arm Twist\");\n            public GUIContent upperLegTwist = EditorGUIUtility.TrTextContent(\"Upper Leg Twist\");\n            public GUIContent legTwist = EditorGUIUtility.TrTextContent(\"Lower Leg Twist\");\n            public GUIContent armStretch = EditorGUIUtility.TrTextContent(\"Arm Stretch\");\n            public GUIContent legStretch = EditorGUIUtility.TrTextContent(\"Leg Stretch\");\n            public GUIContent feetSpacing = EditorGUIUtility.TrTextContent(\"Feet Spacing\");\n            public GUIContent hasTranslationDoF = EditorGUIUtility.TrTextContent(\"Translation DoF\");\n\n            public GUIStyle box = \"OL box noexpand\";\n            public GUIStyle title = \"OL TITLE\";\n\n            public GUIStyle toolbar = \"TE Toolbar\";\n            public GUIStyle toolbarDropDown = \"TE ToolbarDropDown\";\n\n            public GUIContent muscle = EditorGUIUtility.TrTextContent(\"Muscles\");\n            public GUIContent resetMuscle = EditorGUIUtility.TrTextContent(\"Reset\");\n        }\n\n        static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } }\n        static Styles s_Styles;\n\n        // This list containt the mecanim's musle id for each muscle group\n        protected int[][] m_Muscles =\n        {\n            new int[] { (int)Dof.BodyDofStart + (int)BodyDof.SpineFrontBack,\n                        (int)Dof.BodyDofStart + (int)BodyDof.SpineLeftRight,\n                        (int)Dof.BodyDofStart + (int)BodyDof.SpineRollLeftRight,\n                        (int)Dof.BodyDofStart + (int)BodyDof.ChestFrontBack,\n                        (int)Dof.BodyDofStart + (int)BodyDof.ChestLeftRight,\n                        (int)Dof.BodyDofStart + (int)BodyDof.ChestRollLeftRight,\n                        (int)Dof.BodyDofStart + (int)BodyDof.UpperChestFrontBack,\n                        (int)Dof.BodyDofStart + (int)BodyDof.UpperChestLeftRight,\n                        (int)Dof.BodyDofStart + (int)BodyDof.UpperChestRollLeftRight},\n\n            new int[] { (int)Dof.HeadDofStart + (int)HeadDof.NeckFrontBack,\n                        (int)Dof.HeadDofStart + (int)HeadDof.NeckLeftRight,\n                        (int)Dof.HeadDofStart + (int)HeadDof.NeckRollLeftRight,\n                        (int)Dof.HeadDofStart + (int)HeadDof.HeadFrontBack,\n                        (int)Dof.HeadDofStart + (int)HeadDof.HeadLeftRight,\n                        (int)Dof.HeadDofStart + (int)HeadDof.HeadRollLeftRight,\n                        (int)Dof.HeadDofStart + (int)HeadDof.LeftEyeDownUp,\n                        (int)Dof.HeadDofStart + (int)HeadDof.LeftEyeInOut,\n                        (int)Dof.HeadDofStart + (int)HeadDof.RightEyeDownUp,\n                        (int)Dof.HeadDofStart + (int)HeadDof.RightEyeInOut,\n                        (int)Dof.HeadDofStart + (int)HeadDof.JawDownUp,\n                        (int)Dof.HeadDofStart + (int)HeadDof.JawLeftRight},\n\n            new int[] { (int)Dof.LeftArmDofStart + (int)ArmDof.ShoulderDownUp,\n                        (int)Dof.LeftArmDofStart + (int)ArmDof.ShoulderFrontBack,\n                        (int)Dof.LeftArmDofStart + (int)ArmDof.ArmDownUp,\n                        (int)Dof.LeftArmDofStart + (int)ArmDof.ArmFrontBack,\n                        (int)Dof.LeftArmDofStart + (int)ArmDof.ArmRollInOut,\n                        (int)Dof.LeftArmDofStart + (int)ArmDof.ForeArmCloseOpen,\n                        (int)Dof.LeftArmDofStart + (int)ArmDof.ForeArmRollInOut,\n                        (int)Dof.LeftArmDofStart + (int)ArmDof.HandDownUp,\n                        (int)Dof.LeftArmDofStart + (int)ArmDof.HandInOut},\n\n            new int[]\n            {\n                (int)Dof.LeftThumbDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.LeftThumbDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.LeftThumbDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.LeftThumbDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.LeftIndexDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.LeftIndexDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.LeftIndexDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.LeftIndexDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.LeftMiddleDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.LeftMiddleDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.LeftMiddleDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.LeftMiddleDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.LeftRingDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.LeftRingDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.LeftRingDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.LeftRingDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.LeftLittleDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.LeftLittleDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.LeftLittleDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.LeftLittleDofStart + (int)FingerDof.DistalCloseOpen\n            },\n\n            new int[] { (int)Dof.RightArmDofStart + (int)ArmDof.ShoulderDownUp,\n                        (int)Dof.RightArmDofStart + (int)ArmDof.ShoulderFrontBack,\n                        (int)Dof.RightArmDofStart + (int)ArmDof.ArmDownUp,\n                        (int)Dof.RightArmDofStart + (int)ArmDof.ArmFrontBack,\n                        (int)Dof.RightArmDofStart + (int)ArmDof.ArmRollInOut,\n                        (int)Dof.RightArmDofStart + (int)ArmDof.ForeArmCloseOpen,\n                        (int)Dof.RightArmDofStart + (int)ArmDof.ForeArmRollInOut,\n                        (int)Dof.RightArmDofStart + (int)ArmDof.HandDownUp,\n                        (int)Dof.RightArmDofStart + (int)ArmDof.HandInOut},\n\n            new int[]\n            {\n                (int)Dof.RightThumbDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.RightThumbDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.RightThumbDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.RightThumbDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.RightIndexDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.RightIndexDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.RightIndexDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.RightIndexDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.RightMiddleDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.RightMiddleDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.RightMiddleDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.RightMiddleDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.RightRingDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.RightRingDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.RightRingDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.RightRingDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.RightLittleDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.RightLittleDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.RightLittleDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.RightLittleDofStart + (int)FingerDof.DistalCloseOpen\n            },\n\n            new int[]\n            {\n                (int)Dof.LeftLegDofStart + (int)LegDof.UpperLegFrontBack,\n                (int)Dof.LeftLegDofStart + (int)LegDof.UpperLegInOut,\n                (int)Dof.LeftLegDofStart + (int)LegDof.UpperLegRollInOut,\n                (int)Dof.LeftLegDofStart + (int)LegDof.LegCloseOpen,\n                (int)Dof.LeftLegDofStart + (int)LegDof.LegRollInOut,\n                (int)Dof.LeftLegDofStart + (int)LegDof.FootCloseOpen,\n                (int)Dof.LeftLegDofStart + (int)LegDof.FootInOut,\n                (int)Dof.LeftLegDofStart + (int)LegDof.ToesUpDown,\n            },\n\n            new int[]\n            {\n                (int)Dof.RightLegDofStart + (int)LegDof.UpperLegFrontBack,\n                (int)Dof.RightLegDofStart + (int)LegDof.UpperLegInOut,\n                (int)Dof.RightLegDofStart + (int)LegDof.UpperLegRollInOut,\n                (int)Dof.RightLegDofStart + (int)LegDof.LegCloseOpen,\n                (int)Dof.RightLegDofStart + (int)LegDof.LegRollInOut,\n                (int)Dof.RightLegDofStart + (int)LegDof.FootCloseOpen,\n                (int)Dof.RightLegDofStart + (int)LegDof.FootInOut,\n                (int)Dof.RightLegDofStart + (int)LegDof.ToesUpDown,\n            }\n        };\n\n        protected int[][] m_MasterMuscle =\n        {\n            // Body open close\n            new int[]\n            {\n                (int)Dof.BodyDofStart + (int)BodyDof.SpineFrontBack,\n                (int)Dof.BodyDofStart + (int)BodyDof.ChestFrontBack,\n                (int)Dof.BodyDofStart + (int)BodyDof.UpperChestFrontBack,\n                (int)Dof.HeadDofStart + (int)HeadDof.NeckFrontBack,\n                (int)Dof.HeadDofStart + (int)HeadDof.HeadFrontBack,\n\n                (int)Dof.LeftLegDofStart + (int)LegDof.UpperLegFrontBack,\n                (int)Dof.LeftLegDofStart + (int)LegDof.LegCloseOpen,\n                (int)Dof.LeftLegDofStart + (int)LegDof.FootCloseOpen,\n                (int)Dof.RightLegDofStart + (int)LegDof.UpperLegFrontBack,\n                (int)Dof.RightLegDofStart + (int)LegDof.LegCloseOpen,\n                (int)Dof.RightLegDofStart + (int)LegDof.FootCloseOpen,\n\n                (int)Dof.LeftArmDofStart + (int)ArmDof.ShoulderDownUp,\n                (int)Dof.LeftArmDofStart + (int)ArmDof.ArmDownUp,\n                (int)Dof.LeftArmDofStart + (int)ArmDof.ForeArmCloseOpen,\n                (int)Dof.LeftArmDofStart + (int)ArmDof.HandDownUp,\n\n                (int)Dof.RightArmDofStart + (int)ArmDof.ShoulderDownUp,\n                (int)Dof.RightArmDofStart + (int)ArmDof.ArmDownUp,\n                (int)Dof.RightArmDofStart + (int)ArmDof.ForeArmCloseOpen,\n                (int)Dof.RightArmDofStart + (int)ArmDof.HandDownUp\n            },\n\n            // Body Left Right\n            new int[]\n            {\n                (int)Dof.BodyDofStart + (int)BodyDof.SpineLeftRight,\n                (int)Dof.BodyDofStart + (int)BodyDof.ChestLeftRight,\n                (int)Dof.BodyDofStart + (int)BodyDof.UpperChestLeftRight,\n                (int)Dof.HeadDofStart + (int)HeadDof.NeckLeftRight,\n                (int)Dof.HeadDofStart + (int)HeadDof.HeadLeftRight,\n            },\n\n            // Roll Left Right\n            new int[]\n            {\n                (int)Dof.BodyDofStart + (int)BodyDof.SpineRollLeftRight,\n                (int)Dof.BodyDofStart + (int)BodyDof.ChestRollLeftRight,\n                (int)Dof.BodyDofStart + (int)BodyDof.UpperChestRollLeftRight,\n                (int)Dof.HeadDofStart + (int)HeadDof.NeckRollLeftRight,\n                (int)Dof.HeadDofStart + (int)HeadDof.HeadRollLeftRight,\n            },\n\n            // In Out\n            new int[]\n            {\n                (int)Dof.LeftLegDofStart + (int)LegDof.UpperLegInOut,\n                (int)Dof.LeftLegDofStart + (int)LegDof.FootInOut,\n                (int)Dof.RightLegDofStart + (int)LegDof.UpperLegInOut,\n                (int)Dof.RightLegDofStart + (int)LegDof.FootInOut,\n                (int)Dof.LeftArmDofStart + (int)ArmDof.ShoulderFrontBack,\n                (int)Dof.LeftArmDofStart + (int)ArmDof.ArmFrontBack,\n                (int)Dof.LeftArmDofStart + (int)ArmDof.HandInOut,\n                (int)Dof.RightArmDofStart + (int)ArmDof.ShoulderFrontBack,\n                (int)Dof.RightArmDofStart + (int)ArmDof.ArmFrontBack,\n                (int)Dof.RightArmDofStart + (int)ArmDof.HandInOut\n            },\n\n            // Roll In Out\n            new int[]\n            {\n                (int)Dof.LeftLegDofStart + (int)LegDof.UpperLegRollInOut,\n                (int)Dof.LeftLegDofStart + (int)LegDof.LegRollInOut,\n                (int)Dof.RightLegDofStart + (int)LegDof.UpperLegRollInOut,\n                (int)Dof.RightLegDofStart + (int)LegDof.LegRollInOut,\n                (int)Dof.LeftArmDofStart + (int)ArmDof.ArmRollInOut,\n                (int)Dof.LeftArmDofStart + (int)ArmDof.ForeArmRollInOut,\n                (int)Dof.RightArmDofStart + (int)ArmDof.ArmRollInOut,\n                (int)Dof.RightArmDofStart + (int)ArmDof.ForeArmRollInOut\n            },\n\n            // Finger open close\n            new int[]\n            {\n                (int)Dof.LeftThumbDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.LeftThumbDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.LeftThumbDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.LeftIndexDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.LeftIndexDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.LeftIndexDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.LeftMiddleDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.LeftMiddleDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.LeftMiddleDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.LeftRingDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.LeftRingDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.LeftRingDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.LeftLittleDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.LeftLittleDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.LeftLittleDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.RightThumbDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.RightThumbDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.RightThumbDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.RightIndexDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.RightIndexDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.RightIndexDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.RightMiddleDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.RightMiddleDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.RightMiddleDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.RightRingDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.RightRingDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.RightRingDofStart + (int)FingerDof.DistalCloseOpen,\n\n                (int)Dof.RightLittleDofStart + (int)FingerDof.ProximalDownUp,\n                (int)Dof.RightLittleDofStart + (int)FingerDof.IntermediateCloseOpen,\n                (int)Dof.RightLittleDofStart + (int)FingerDof.DistalCloseOpen\n            },\n\n            // Finger In Out\n            new int[]\n            {\n                (int)Dof.LeftThumbDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.LeftIndexDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.LeftMiddleDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.LeftRingDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.LeftLittleDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.RightThumbDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.RightIndexDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.RightMiddleDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.RightRingDofStart + (int)FingerDof.ProximalInOut,\n                (int)Dof.RightLittleDofStart + (int)FingerDof.ProximalInOut,\n            }\n        };\n\n\n        bool[] m_MuscleBodyGroupToggle;\n        bool[] m_MuscleToggle;\n\n        int m_FocusedMuscle;\n\n        [SerializeField]\n        float[] m_MuscleValue = null;\n\n        [SerializeField]\n        float[] m_MuscleMasterValue = null;\n\n        [SerializeField]\n        protected float m_ArmTwistFactor;\n\n        [SerializeField]\n        protected float m_ForeArmTwistFactor;\n\n        [SerializeField]\n        protected float m_UpperLegTwistFactor;\n\n        [SerializeField]\n        protected float m_LegTwistFactor;\n\n        [SerializeField]\n        protected float m_ArmStretchFactor;\n\n        [SerializeField]\n        protected float m_LegStretchFactor;\n\n        [SerializeField]\n        protected float m_FeetSpacingFactor;\n\n        [SerializeField]\n        protected bool m_HasTranslationDoF;\n\n        string[] m_MuscleName = null;\n        int m_MuscleCount = 0;\n\n        SerializedProperty[] m_MuscleMin = null;\n        SerializedProperty[] m_MuscleMax = null;\n\n        [SerializeField]\n        float[] m_MuscleMinEdit = null;\n\n        [SerializeField]\n        float[] m_MuscleMaxEdit = null;\n\n        SerializedProperty[] m_Modified = null;\n\n        // These member are used when the avatar is part of an asset\n        SerializedProperty m_ArmTwistProperty;\n        SerializedProperty m_ForeArmTwistProperty;\n        SerializedProperty m_UpperLegTwistProperty;\n        SerializedProperty m_LegTwistProperty;\n\n        SerializedProperty m_ArmStretchProperty;\n        SerializedProperty m_LegStretchProperty;\n\n        SerializedProperty m_FeetSpacingProperty;\n\n        SerializedProperty m_HasTranslationDoFProperty;\n        SerializedProperty m_HumanBoneArrayProperty;\n\n        const string sMinX = \"m_Limit.m_Min.x\";\n        const string sMinY = \"m_Limit.m_Min.y\";\n        const string sMinZ = \"m_Limit.m_Min.z\";\n\n        const string sMaxX = \"m_Limit.m_Max.x\";\n        const string sMaxY = \"m_Limit.m_Max.y\";\n        const string sMaxZ = \"m_Limit.m_Max.z\";\n        const string sModified = \"m_Limit.m_Modified\";\n\n        const string sArmTwist = \"m_HumanDescription.m_ArmTwist\";\n        const string sForeArmTwist = \"m_HumanDescription.m_ForeArmTwist\";\n        const string sUpperLegTwist = \"m_HumanDescription.m_UpperLegTwist\";\n        const string sLegTwist = \"m_HumanDescription.m_LegTwist\";\n\n        const string sArmStretch = \"m_HumanDescription.m_ArmStretch\";\n        const string sLegStretch = \"m_HumanDescription.m_LegStretch\";\n\n        const string sFeetSpacing = \"m_HumanDescription.m_FeetSpacing\";\n\n        const string sHasTranslationDoF = \"m_HumanDescription.m_HasTranslationDoF\";\n\n        const string sHumanBoneArray = \"m_HumanDescription.m_Human\";\n\n        const float sMuscleMin = -180.0f;\n        const float sMuscleMax = 180.0f;\n\n        const float kPreviewWidth = 80;\n        const float kNumberWidth = 38;\n        const float kLineHeight = 18;\n\n        private readonly Handles.BoneRenderer m_BoneRenderer = new Handles.BoneRenderer();\n\n        static Rect GetSettingsRect(Rect wholeWidthRect)\n        {\n            wholeWidthRect.xMin += (kPreviewWidth + 3);\n            wholeWidthRect.width -= 4;\n            return wholeWidthRect;\n        }\n\n        static Rect GetSettingsRect()\n        {\n            return GetSettingsRect(GUILayoutUtility.GetRect(10, kLineHeight));\n        }\n\n        static Rect GetPreviewRect(Rect wholeWidthRect)\n        {\n            wholeWidthRect.width = kPreviewWidth - 9;\n            wholeWidthRect.x += 5;\n            wholeWidthRect.height = kLineHeight;\n            return wholeWidthRect;\n        }\n\n        void HeaderGUI(string h1, string h2)\n        {\n            GUILayout.BeginHorizontal();\n            GUILayout.Label(h1, styles.title, GUILayout.Width(kPreviewWidth));\n            GUILayout.Label(h2, styles.title, GUILayout.ExpandWidth(true));\n            GUILayout.EndHorizontal();\n        }\n\n        static float PreviewSlider(Rect position, float val)\n        {\n            val = GUI.HorizontalSlider(GetPreviewRect(position), val, -1, 1);\n            if (val > -0.1f && val < 0.1f)\n                val = 0;\n            return val;\n        }\n\n        protected AvatarSetupTool.BoneWrapper[] m_Bones;\n\n        internal void ResetValuesFromProperties()\n        {\n            m_ArmTwistFactor = m_ArmTwistProperty.floatValue;\n            m_ForeArmTwistFactor = m_ForeArmTwistProperty.floatValue;\n            m_UpperLegTwistFactor = m_UpperLegTwistProperty.floatValue;\n            m_LegTwistFactor = m_LegTwistProperty.floatValue;\n            m_ArmStretchFactor = m_ArmStretchProperty.floatValue;\n            m_LegStretchFactor = m_LegStretchProperty.floatValue;\n            m_FeetSpacingFactor = m_FeetSpacingProperty.floatValue;\n            m_HasTranslationDoF = m_HasTranslationDoFProperty.boolValue;\n\n            // limit is a special case, because they are added dynamicly by the editor\n            // all the default value are wrong, we must explictly query mecanim to get the default value when\n            // m_Modified is set to false.\n            for (int i = 0; i < m_Bones.Length; i++)\n            {\n                if (m_Modified[i] != null)\n                {\n                    bool modified = m_Modified[i].boolValue;\n\n                    int dx = HumanTrait.MuscleFromBone(i, 0);\n                    int dy = HumanTrait.MuscleFromBone(i, 1);\n                    int dz = HumanTrait.MuscleFromBone(i, 2);\n                    if (dx != -1)\n                    {\n                        m_MuscleMinEdit[dx] = modified ? m_MuscleMin[dx].floatValue : HumanTrait.GetMuscleDefaultMin(dx);\n                        m_MuscleMaxEdit[dx] = modified ? m_MuscleMax[dx].floatValue : HumanTrait.GetMuscleDefaultMax(dx);\n                    }\n\n                    if (dy != -1)\n                    {\n                        m_MuscleMinEdit[dy] = modified ? m_MuscleMin[dy].floatValue : HumanTrait.GetMuscleDefaultMin(dy);\n                        m_MuscleMaxEdit[dy] = modified ? m_MuscleMax[dy].floatValue : HumanTrait.GetMuscleDefaultMax(dy);\n                    }\n\n                    if (dz != -1)\n                    {\n                        m_MuscleMinEdit[dz] = modified ? m_MuscleMin[dz].floatValue : HumanTrait.GetMuscleDefaultMin(dz);\n                        m_MuscleMaxEdit[dz] = modified ? m_MuscleMax[dz].floatValue : HumanTrait.GetMuscleDefaultMax(dz);\n                    }\n                }\n            }\n        }\n\n        internal void InitializeProperties()\n        {\n            m_ArmTwistProperty = serializedObject.FindProperty(sArmTwist);\n            m_ForeArmTwistProperty = serializedObject.FindProperty(sForeArmTwist);\n            m_UpperLegTwistProperty = serializedObject.FindProperty(sUpperLegTwist);\n            m_LegTwistProperty = serializedObject.FindProperty(sLegTwist);\n            m_ArmStretchProperty = serializedObject.FindProperty(sArmStretch);\n            m_LegStretchProperty = serializedObject.FindProperty(sLegStretch);\n            m_FeetSpacingProperty = serializedObject.FindProperty(sFeetSpacing);\n            m_HasTranslationDoFProperty = serializedObject.FindProperty(sHasTranslationDoF);\n            m_HumanBoneArrayProperty = serializedObject.FindProperty(sHumanBoneArray);\n\n            for (int i = 0; i < m_Bones.Length; i++)\n            {\n                SerializedProperty bone = m_Bones[i].GetSerializedProperty(m_HumanBoneArrayProperty, false);\n                if (bone != null)\n                {\n                    m_Modified[i] = bone.FindPropertyRelative(sModified);\n\n                    int dx = HumanTrait.MuscleFromBone(i, 0);\n                    int dy = HumanTrait.MuscleFromBone(i, 1);\n                    int dz = HumanTrait.MuscleFromBone(i, 2);\n\n\n                    if (dx != -1)\n                    {\n                        m_MuscleMin[dx] = bone.FindPropertyRelative(sMinX);\n                        m_MuscleMax[dx] = bone.FindPropertyRelative(sMaxX);\n                    }\n\n                    if (dy != -1)\n                    {\n                        m_MuscleMin[dy] = bone.FindPropertyRelative(sMinY);\n                        m_MuscleMax[dy] = bone.FindPropertyRelative(sMaxY);\n                    }\n\n                    if (dz != -1)\n                    {\n                        m_MuscleMin[dz] = bone.FindPropertyRelative(sMinZ);\n                        m_MuscleMax[dz] = bone.FindPropertyRelative(sMaxZ);\n                    }\n                }\n            }\n        }\n\n        internal void Initialize()\n        {\n            // initialize the necessary serialized property\n            if (m_HumanBoneArrayProperty == null)\n                m_HumanBoneArrayProperty = serializedObject.FindProperty(sHumanBoneArray);\n\n            // Handle human bones\n            if (m_Bones == null)\n                m_Bones = AvatarSetupTool.GetHumanBones(m_HumanBoneArrayProperty, modelBones);\n\n            m_FocusedMuscle = -1;\n\n            m_MuscleBodyGroupToggle = new bool[m_Muscles.Length];\n            for (int i = 0; i < m_Muscles.Length; i++)\n            {\n                m_MuscleBodyGroupToggle[i] = false;\n            }\n\n            m_MuscleName = HumanTrait.MuscleName;\n            for (int i = 0; i < m_MuscleName.Length; i++)\n            {\n                if (m_MuscleName[i].StartsWith(\"Right\"))\n                    m_MuscleName[i] = m_MuscleName[i].Substring(5).Trim();\n                if (m_MuscleName[i].StartsWith(\"Left\"))\n                    m_MuscleName[i] = m_MuscleName[i].Substring(4).Trim();\n            }\n            m_MuscleCount = HumanTrait.MuscleCount;\n\n            m_MuscleToggle = new bool[m_MuscleCount];\n            m_MuscleValue = new float[m_MuscleCount];\n            m_MuscleMin = new SerializedProperty[m_MuscleCount];\n            m_MuscleMax = new SerializedProperty[m_MuscleCount];\n\n            m_MuscleMinEdit = new float[m_MuscleCount];\n            m_MuscleMaxEdit = new float[m_MuscleCount];\n\n            for (int i = 0; i < m_MuscleCount; i++)\n            {\n                m_MuscleToggle[i] = false;\n                m_MuscleValue[i] = 0;\n                m_MuscleMin[i] = null;\n                m_MuscleMin[i] = null;\n            }\n\n            m_Modified = new SerializedProperty[m_Bones.Length];\n            for (int i = 0; i < m_Bones.Length; i++)\n            {\n                m_Modified[i] = null;\n            }\n\n            InitializeProperties();\n            ResetValuesFromProperties();\n\n            m_MuscleMasterValue = new float[m_MasterMuscle.Length];\n            for (int i = 0; i < m_MasterMuscle.Length; i++)\n            {\n                m_MuscleMasterValue[i] = 0;\n            }\n        }\n\n        public override void Enable(AvatarEditor inspector)\n        {\n            base.Enable(inspector);\n\n            Initialize();\n\n            WritePose();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (Event.current.type == EventType.ValidateCommand && Event.current.commandName == EventCommandNames.UndoRedoPerformed)\n            {\n                WritePose();\n            }\n\n            if (avatarAsset == null)\n            {\n                return;\n            }\n\n            using (new EditorGUI.DisabledScope(!avatarAsset.isHuman))\n            {\n                EditorGUIUtility.labelWidth = 110;\n                EditorGUIUtility.fieldWidth = 40;\n\n                GUILayout.BeginHorizontal();\n                GUILayout.BeginVertical();\n\n                MuscleGroupGUI();\n                EditorGUILayout.Space();\n                MuscleGUI();\n                EditorGUILayout.Space();\n                PropertiesGUI();\n\n                GUILayout.EndVertical();\n                GUILayout.Space(1);\n                GUILayout.EndHorizontal();\n\n                DisplayMuscleButtons();\n\n                ApplyRevertGUI();\n            }\n        }\n\n        protected void DisplayMuscleButtons()\n        {\n            GUILayout.BeginHorizontal(\"\", styles.toolbar, GUILayout.ExpandWidth(true));\n            {\n                Rect r;\n\n                // Muscle\n                r = GUILayoutUtility.GetRect(styles.muscle, styles.toolbarDropDown);\n                if (GUI.Button(r, styles.muscle, styles.toolbarDropDown))\n                {\n                    GenericMenu menu = new GenericMenu();\n                    menu.AddItem(styles.resetMuscle, false, ResetMuscleToDefault);\n                    menu.DropDown(r);\n                }\n\n                GUILayout.FlexibleSpace();\n            }\n            GUILayout.EndHorizontal();\n        }\n\n        protected override void ResetValues()\n        {\n            serializedObject.Update();\n            ResetValuesFromProperties();\n        }\n\n        protected void ResetMuscleToDefault()\n        {\n            Avatar avatar = null;\n            // For live update, update instanciate avatar to adjust pose\n            if (gameObject != null)\n            {\n                Animator animator = gameObject.GetComponent(typeof(Animator)) as Animator;\n                avatar = animator.avatar;\n            }\n\n            for (int i = 0; i < m_MuscleCount; i++)\n            {\n                float min = HumanTrait.GetMuscleDefaultMin(i);\n                float max = HumanTrait.GetMuscleDefaultMax(i);\n\n                if (m_MuscleMin[i] != null && m_MuscleMax[i] != null)\n                {\n                    m_MuscleMin[i].floatValue = m_MuscleMinEdit[i] = min;\n                    m_MuscleMax[i].floatValue = m_MuscleMaxEdit[i] = max;\n                }\n\n                int humanId = HumanTrait.BoneFromMuscle(i);\n                if (m_Modified[humanId] != null && humanId != -1)\n                    m_Modified[humanId].boolValue = false;\n\n                if (avatar != null)\n                    avatar.SetMuscleMinMax(i, min, max);\n            }\n\n            WritePose();\n        }\n\n        protected void UpdateAvatarParameter(HumanParameter parameterId, float value)\n        {\n            // For live update, update instanciate avatar to adjust pose\n            if (gameObject != null)\n            {\n                Animator animator = gameObject.GetComponent(typeof(Animator)) as Animator;\n                Avatar avatar = animator.avatar;\n                avatar.SetParameter((int)parameterId, value);\n            }\n        }\n\n        protected bool UpdateMuscle(int muscleId, float min, float max)\n        {\n            Undo.RegisterCompleteObjectUndo(this, \"Updated muscle range\");\n            m_MuscleMin[muscleId].floatValue = min;\n            m_MuscleMax[muscleId].floatValue = max;\n\n            int humanId = HumanTrait.BoneFromMuscle(muscleId);\n            if (humanId != -1)\n            {\n                if (!m_Modified[humanId].boolValue)\n                {\n                    int mx = HumanTrait.MuscleFromBone(humanId, 0);\n                    int my = HumanTrait.MuscleFromBone(humanId, 1);\n                    int mz = HumanTrait.MuscleFromBone(humanId, 2);\n\n                    if (mx != -1 && mx != muscleId)\n                    {\n                        m_MuscleMin[mx].floatValue = HumanTrait.GetMuscleDefaultMin(mx);\n                        m_MuscleMax[mx].floatValue = HumanTrait.GetMuscleDefaultMax(mx);\n                    }\n\n                    if (my != -1 && my != muscleId)\n                    {\n                        m_MuscleMin[my].floatValue = HumanTrait.GetMuscleDefaultMin(my);\n                        m_MuscleMax[my].floatValue = HumanTrait.GetMuscleDefaultMax(my);\n                    }\n\n                    if (mz != -1 && mz != muscleId)\n                    {\n                        m_MuscleMin[mz].floatValue = HumanTrait.GetMuscleDefaultMin(mz);\n                        m_MuscleMax[mz].floatValue = HumanTrait.GetMuscleDefaultMax(mz);\n                    }\n                }\n\n                m_Modified[humanId].boolValue = true;\n            }\n\n            // OnSceneGUI need focused muscle to know which one to draw\n            m_FocusedMuscle = muscleId;\n\n            // For live update, update instanciate avatar to adjust pose\n            if (gameObject != null)\n            {\n                Animator animator = gameObject.GetComponent(typeof(Animator)) as Animator;\n                Avatar avatar = animator.avatar;\n                avatar.SetMuscleMinMax(muscleId, min, max);\n            }\n\n            // Need to repaint scene to update muscle range handle\n            SceneView.RepaintAll();\n\n            return gameObject != null;\n        }\n\n        protected void MuscleGroupGUI()\n        {\n            bool recomputePose = false;\n\n            HeaderGUI(\"Preview\", \"Muscle Group Preview\");\n            GUILayout.BeginVertical(styles.box);\n            {\n                {\n                    Rect r = GUILayoutUtility.GetRect(10, kLineHeight);\n                    Rect settingsRect = GetSettingsRect(r);\n                    Rect previewRect = GetPreviewRect(r);\n                    if (GUI.Button(previewRect, \"Reset All\", EditorStyles.miniButton))\n                    {\n                        for (int i = 0; i < m_MuscleMasterValue.Length; i++)\n                            m_MuscleMasterValue[i] = 0;\n                        for (int i = 0; i < m_MuscleValue.Length; i++)\n                            m_MuscleValue[i] = 0;\n                        recomputePose = true;\n                    }\n\n                    GUI.Label(settingsRect, \"Reset All Preview Values\", EditorStyles.label);\n                }\n\n                for (int i = 0; i < m_MasterMuscle.Length; i++)\n                {\n                    Rect r = GUILayoutUtility.GetRect(10, kLineHeight);\n                    Rect settingsRect = GetSettingsRect(r);\n\n                    float oldValue = m_MuscleMasterValue[i];\n                    m_MuscleMasterValue[i] = PreviewSlider(r, m_MuscleMasterValue[i]);\n                    if (m_MuscleMasterValue[i] != oldValue)\n                    {\n                        Undo.RegisterCompleteObjectUndo(this, \"Muscle preview\");\n                        for (int j = 0; j < m_MasterMuscle[i].Length; j++)\n                        {\n                            if (m_MasterMuscle[i][j] != -1)\n                            {\n                                m_MuscleValue[m_MasterMuscle[i][j]] = m_MuscleMasterValue[i];\n                            }\n                        }\n                    }\n                    // Muscle value changed and we do have a game object to update\n                    recomputePose |= m_MuscleMasterValue[i] != oldValue && gameObject != null;\n\n                    GUI.Label(settingsRect, styles.muscleTypeGroup[i], EditorStyles.label);\n                }\n            }\n            GUILayout.EndVertical();\n\n            if (recomputePose)\n                WritePose();\n        }\n\n        protected void MuscleGUI()\n        {\n            bool recomputePose = false;\n\n            HeaderGUI(\"Preview\", \"Per-Muscle Settings\");\n            GUILayout.BeginVertical(styles.box);\n            {\n                Rect r, settingsRect;\n                const int indentPerLevel = 15;\n                for (int i = 0; i < m_MuscleBodyGroupToggle.Length; i++)\n                {\n                    r = GUILayoutUtility.GetRect(10, kLineHeight);\n                    settingsRect = GetSettingsRect(r);\n                    m_MuscleBodyGroupToggle[i] = GUI.Toggle(settingsRect, m_MuscleBodyGroupToggle[i], styles.muscleBodyGroup[i], EditorStyles.foldout);\n                    if (m_MuscleBodyGroupToggle[i])\n                    {\n                        for (int j = 0; j < m_Muscles[i].Length; j++)\n                        {\n                            int muscleId = m_Muscles[i][j];\n                            // Some muscle can be optionnal like Toes, if this bone is not characterized you can't edit this muscle\n                            if (muscleId != -1 && m_MuscleMin[muscleId] != null && m_MuscleMax[muscleId] != null)\n                            {\n                                bool expanded = m_MuscleToggle[muscleId];\n\n                                r = GUILayoutUtility.GetRect(10, expanded ? kLineHeight * 2 : kLineHeight);\n                                settingsRect = GetSettingsRect(r);\n                                settingsRect.xMin += indentPerLevel;\n\n                                // Foldout\n                                settingsRect.height = kLineHeight;\n                                m_MuscleToggle[muscleId] = GUI.Toggle(settingsRect, m_MuscleToggle[muscleId], m_MuscleName[muscleId], EditorStyles.foldout);\n\n                                // Preview slider\n                                float value = PreviewSlider(r, m_MuscleValue[muscleId]);\n                                // OnSceneGUI need focused muscle to know which one to draw\n                                if (m_MuscleValue[muscleId] != value)\n                                {\n                                    Undo.RegisterCompleteObjectUndo(this, \"Muscle preview\");\n                                    m_FocusedMuscle = muscleId;\n                                    m_MuscleValue[muscleId] = value;\n                                    recomputePose |= (gameObject != null);\n                                }\n\n                                if (expanded)\n                                {\n                                    bool muscleChanged = false;\n\n                                    settingsRect.xMin += indentPerLevel;\n                                    settingsRect.y += kLineHeight;\n\n                                    Rect sliderRect = settingsRect;\n\n                                    if (settingsRect.width > 160)\n                                    {\n                                        Rect numberRect = settingsRect;\n                                        numberRect.width = kNumberWidth;\n\n                                        EditorGUI.BeginChangeCheck();\n                                        m_MuscleMinEdit[muscleId] = EditorGUI.FloatField(numberRect, m_MuscleMinEdit[muscleId]);\n                                        muscleChanged |= EditorGUI.EndChangeCheck();\n\n                                        numberRect.x = settingsRect.xMax - kNumberWidth;\n\n                                        EditorGUI.BeginChangeCheck();\n                                        m_MuscleMaxEdit[muscleId] = EditorGUI.FloatField(numberRect, m_MuscleMaxEdit[muscleId]);\n                                        muscleChanged |= EditorGUI.EndChangeCheck();\n\n                                        sliderRect.xMin += (kNumberWidth + 5);\n                                        sliderRect.xMax -= (kNumberWidth + 5);\n                                    }\n\n                                    EditorGUI.BeginChangeCheck();\n                                    EditorGUI.MinMaxSlider(sliderRect, ref m_MuscleMinEdit[muscleId], ref m_MuscleMaxEdit[muscleId], sMuscleMin, sMuscleMax);\n                                    muscleChanged |= EditorGUI.EndChangeCheck();\n\n                                    if (muscleChanged)\n                                    {\n                                        m_MuscleMinEdit[muscleId] = Mathf.Clamp(m_MuscleMinEdit[muscleId], sMuscleMin, 0);\n                                        m_MuscleMaxEdit[muscleId] = Mathf.Clamp(m_MuscleMaxEdit[muscleId], 0, sMuscleMax);\n                                        recomputePose |= UpdateMuscle(muscleId, m_MuscleMinEdit[muscleId], m_MuscleMaxEdit[muscleId]);\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            GUILayout.EndVertical();\n\n            if (recomputePose)\n                WritePose();\n        }\n\n        protected void PropertiesGUI()\n        {\n            bool recomputePose = false;\n\n            HeaderGUI(\"\", \"Additional Settings\");\n            GUILayout.BeginVertical(styles.box);\n            {\n                m_ArmTwistFactor = EditorGUI.Slider(GetSettingsRect(), styles.armTwist, m_ArmTwistFactor, 0, 1,\n                    EditorStyles.miniTextField);\n                if (m_ArmTwistProperty.floatValue != m_ArmTwistFactor)\n                {\n                    Undo.RegisterCompleteObjectUndo(this, \"Upper arm twist\");\n                    m_ArmTwistProperty.floatValue = m_ArmTwistFactor;\n                    UpdateAvatarParameter(HumanParameter.UpperArmTwist, m_ArmTwistFactor);\n                    recomputePose = true;\n                }\n\n                m_ForeArmTwistFactor = EditorGUI.Slider(GetSettingsRect(), styles.foreArmTwist, m_ForeArmTwistFactor, 0, 1,\n                    EditorStyles.miniTextField);\n                if (m_ForeArmTwistProperty.floatValue != m_ForeArmTwistFactor)\n                {\n                    Undo.RegisterCompleteObjectUndo(this, \"Lower arm twist\");\n                    m_ForeArmTwistProperty.floatValue = m_ForeArmTwistFactor;\n                    UpdateAvatarParameter(HumanParameter.LowerArmTwist, m_ForeArmTwistFactor);\n                    recomputePose = true;\n                }\n\n                m_UpperLegTwistFactor = EditorGUI.Slider(GetSettingsRect(), styles.upperLegTwist, m_UpperLegTwistFactor, 0, 1,\n                    EditorStyles.miniTextField);\n                if (m_UpperLegTwistProperty.floatValue != m_UpperLegTwistFactor)\n                {\n                    Undo.RegisterCompleteObjectUndo(this, \"Upper leg twist\");\n                    m_UpperLegTwistProperty.floatValue = m_UpperLegTwistFactor;\n                    UpdateAvatarParameter(HumanParameter.UpperLegTwist, m_UpperLegTwistFactor);\n                    recomputePose = true;\n                }\n\n                m_LegTwistFactor = EditorGUI.Slider(GetSettingsRect(), styles.legTwist, m_LegTwistFactor, 0, 1,\n                    EditorStyles.miniTextField);\n                if (m_LegTwistProperty.floatValue != m_LegTwistFactor)\n                {\n                    Undo.RegisterCompleteObjectUndo(this, \"Lower leg twist\");\n                    m_LegTwistProperty.floatValue = m_LegTwistFactor;\n                    UpdateAvatarParameter(HumanParameter.LowerLegTwist, m_LegTwistFactor);\n                    recomputePose = true;\n                }\n\n                m_ArmStretchFactor = EditorGUI.Slider(GetSettingsRect(), styles.armStretch, m_ArmStretchFactor, 0, 1,\n                    EditorStyles.miniTextField);\n                if (m_ArmStretchProperty.floatValue != m_ArmStretchFactor)\n                {\n                    Undo.RegisterCompleteObjectUndo(this, \"Arm stretch\");\n                    m_ArmStretchProperty.floatValue = m_ArmStretchFactor;\n                    UpdateAvatarParameter(HumanParameter.ArmStretch, m_ArmStretchFactor);\n                    recomputePose = true;\n                }\n\n                m_LegStretchFactor = EditorGUI.Slider(GetSettingsRect(), styles.legStretch, m_LegStretchFactor, 0, 1,\n                    EditorStyles.miniTextField);\n                if (m_LegStretchProperty.floatValue != m_LegStretchFactor)\n                {\n                    Undo.RegisterCompleteObjectUndo(this, \"Leg stretch\");\n                    m_LegStretchProperty.floatValue = m_LegStretchFactor;\n                    UpdateAvatarParameter(HumanParameter.LegStretch, m_LegStretchFactor);\n                    recomputePose = true;\n                }\n\n                m_FeetSpacingFactor = EditorGUI.Slider(GetSettingsRect(), styles.feetSpacing, m_FeetSpacingFactor, 0, 1,\n                    EditorStyles.miniTextField);\n                if (m_FeetSpacingProperty.floatValue != m_FeetSpacingFactor)\n                {\n                    Undo.RegisterCompleteObjectUndo(this, \"Feet spacing\");\n                    m_FeetSpacingProperty.floatValue = m_FeetSpacingFactor;\n                    UpdateAvatarParameter(HumanParameter.FeetSpacing, m_FeetSpacingFactor);\n                    recomputePose = true;\n                }\n\n                m_HasTranslationDoF = EditorGUI.Toggle(GetSettingsRect(), styles.hasTranslationDoF, m_HasTranslationDoF);\n                if (m_HasTranslationDoFProperty.boolValue != m_HasTranslationDoF)\n                {\n                    Undo.RegisterCompleteObjectUndo(this, \"Translation DoF\");\n                    m_HasTranslationDoFProperty.boolValue = m_HasTranslationDoF;\n                }\n            }\n            GUILayout.EndVertical();\n\n            if (recomputePose)\n                WritePose();\n        }\n\n        protected void WritePose()\n        {\n            if (gameObject)\n            {\n                Animator animator = gameObject.GetComponent(typeof(Animator)) as Animator;\n                if (animator != null)\n                {\n                    Avatar avatar = animator.avatar;\n                    if (avatar != null && avatar.isValid && avatar.isHuman)\n                    {\n                        AvatarUtility.SetHumanPose(animator, m_MuscleValue);\n                        SceneView.RepaintAll();\n                    }\n                }\n            }\n        }\n\n        public void DrawMuscleHandle(Transform t, int humanId)\n        {\n            Animator animator = gameObject.GetComponent(typeof(Animator)) as Animator;\n            Avatar avatar = animator.avatar;\n\n            int mx = HumanTrait.MuscleFromBone(humanId, 0);\n            int my = HumanTrait.MuscleFromBone(humanId, 1);\n            int mz = HumanTrait.MuscleFromBone(humanId, 2);\n\n            float axisLen = avatar.GetAxisLength(humanId);\n            Quaternion preQ = avatar.GetPreRotation(humanId);\n            Quaternion postQ = avatar.GetPostRotation(humanId);\n\n            preQ = t.parent.rotation * preQ;\n            postQ = t.rotation * postQ;\n\n            Vector3 normal;\n            Vector3 from;\n\n            Color alpha = new Color(1, 1, 1, 0.5f);\n            Quaternion zyRoll = avatar.GetZYRoll(humanId, Vector3.zero);\n            Vector3 sign = avatar.GetLimitSign(humanId);\n\n            // Draw axis\n            normal = postQ * Vector3.right;\n            Vector3 axisEnd = t.position + (normal * axisLen);\n            Handles.color = Color.white;\n            Handles.DrawLine(t.position, axisEnd);\n\n            if (mx != -1)\n            {\n                Quaternion zyPostQ = avatar.GetZYPostQ(humanId, t.parent.rotation, t.rotation);\n\n                float minx = m_MuscleMinEdit[mx];\n                float maxx = m_MuscleMaxEdit[mx];\n\n                normal = postQ * Vector3.right;\n                from = zyPostQ * Vector3.forward;\n\n                Handles.color = Color.black;\n                //Handles.DrawLine (t.position, t.position + (from * axisLen * 0.75f));\n\n                Vector3 xDoF = t.position + (normal * axisLen * 0.75f);\n\n                normal = postQ * Vector3.right * sign.x;\n                Quaternion q = Quaternion.AngleAxis(minx, normal);\n                from = q * from;\n\n                Handles.color = Color.yellow;\n                //Handles.DrawLine (t.position, t.position + (from * axisLen * 0.75f));\n\n                // Draw Muscle range\n                Handles.color = Handles.xAxisColor * alpha;\n                Handles.DrawSolidArc(xDoF, normal, from, maxx - minx, axisLen * 0.25f);\n\n                from = postQ * Vector3.forward;\n                Handles.color = Handles.centerColor;\n                Handles.DrawLine(xDoF, xDoF + (from * axisLen * 0.25f));\n            }\n\n            if (my != -1)\n            {\n                float miny = m_MuscleMinEdit[my];\n                float maxy = m_MuscleMaxEdit[my];\n\n                normal = preQ * Vector3.up * sign.y;\n                from = preQ * zyRoll * Vector3.right;\n\n                Handles.color = Color.black;\n                //Handles.DrawLine (t.position, t.position + (from * axisLen * 0.75f));\n\n                Quaternion q = Quaternion.AngleAxis(miny, normal);\n                from = q * from;\n\n                Handles.color = Color.yellow;\n                //Handles.DrawLine (t.position, t.position + (from * axisLen * 0.75f));\n\n                // Draw Muscle range\n                Handles.color = Handles.yAxisColor * alpha;\n                Handles.DrawSolidArc(t.position, normal, from, maxy - miny, axisLen * 0.25f);\n            }\n            if (mz != -1)\n            {\n                float minz = m_MuscleMinEdit[mz];\n                float maxz = m_MuscleMaxEdit[mz];\n\n                normal = preQ * Vector3.forward * sign.z;\n                from = preQ * zyRoll * Vector3.right;\n\n                Handles.color = Color.black;\n                //Handles.DrawLine (t.position, t.position + (from * axisLen * 0.75f));\n\n                Quaternion q = Quaternion.AngleAxis(minz, normal);\n                from = q * from;\n\n                Handles.color = Color.yellow;\n                //Handles.DrawLine (t.position, t.position + (from * axisLen * 0.75f));\n\n                // Draw Muscle range\n                Handles.color = Handles.zAxisColor * alpha;\n                Handles.DrawSolidArc(t.position, normal, from, maxz - minz, axisLen * 0.25f);\n            }\n        }\n\n        public override void OnSceneGUI()\n        {\n            AvatarSkeletonDrawer.DrawSkeleton(root, modelBones, m_BoneRenderer);\n\n            if (gameObject == null)\n                return;\n\n            Animator animator = gameObject.GetComponent(typeof(Animator)) as Animator;\n            if (m_FocusedMuscle == -1 || animator == null)\n                return;\n\n            int humanId = HumanTrait.BoneFromMuscle(m_FocusedMuscle);\n            if (humanId != -1)\n            {\n                DrawMuscleHandle(m_Bones[humanId].bone, humanId);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Avatar/AvatarSetupTool.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal static class AvatarSetupTool\n    {\n        [System.Serializable]\n        internal class BoneWrapper\n        {\n            private string m_HumanBoneName;\n            public string humanBoneName { get { return m_HumanBoneName; } }\n            public string error = string.Empty;\n            public Transform bone;\n            public BoneState state;\n\n            public string messageName\n            {\n                get\n                {\n                    return ObjectNames.NicifyVariableName(m_HumanBoneName) + \" Transform '\" + (bone ? bone.name : \"None\") + \"'\";\n                }\n            }\n\n            public BoneWrapper(string humanBoneName, Transform bone)\n            {\n                this.m_HumanBoneName = humanBoneName;\n                this.bone = bone;\n                this.state = BoneState.Valid;\n            }\n\n            public void Reset(SerializedProperty humanBoneArray, Dictionary<Transform, bool> bones)\n            {\n                bone = null;\n                SerializedProperty property = GetSerializedProperty(humanBoneArray, false);\n                if (property != null)\n                {\n                    string boneName = property.FindPropertyRelative(sBoneName).stringValue;\n                    bone = bones.Keys.FirstOrDefault(b => (b != null && b.name == boneName));\n                }\n                state = BoneState.Valid;\n            }\n\n            public void Serialize(SerializedProperty humanBoneArray)\n            {\n                if (bone == null)\n                {\n                    DeleteSerializedProperty(humanBoneArray);\n                }\n                else\n                {\n                    SerializedProperty property = GetSerializedProperty(humanBoneArray, true);\n                    if (property != null)\n                        property.FindPropertyRelative(sBoneName).stringValue = bone.name;\n                }\n            }\n\n            protected void DeleteSerializedProperty(SerializedProperty humanBoneArray)\n            {\n                if (humanBoneArray == null || !humanBoneArray.isArray)\n                    return;\n\n                for (int i = 0; i < humanBoneArray.arraySize; i++)\n                {\n                    SerializedProperty humanNameP = humanBoneArray.GetArrayElementAtIndex(i).FindPropertyRelative(sHumanName);\n                    if (humanNameP.stringValue == humanBoneName)\n                    {\n                        humanBoneArray.DeleteArrayElementAtIndex(i);\n                        break;\n                    }\n                }\n            }\n\n            public SerializedProperty GetSerializedProperty(SerializedProperty humanBoneArray, bool createIfMissing)\n            {\n                if (humanBoneArray == null || !humanBoneArray.isArray)\n                    return null;\n\n                for (int i = 0; i < humanBoneArray.arraySize; i++)\n                {\n                    SerializedProperty humanNameP = humanBoneArray.GetArrayElementAtIndex(i).FindPropertyRelative(sHumanName);\n                    if (humanNameP.stringValue == humanBoneName)\n                        return humanBoneArray.GetArrayElementAtIndex(i);\n                }\n\n                if (createIfMissing)\n                {\n                    humanBoneArray.arraySize++;\n                    SerializedProperty bone = humanBoneArray.GetArrayElementAtIndex(humanBoneArray.arraySize - 1);\n                    if (bone != null)\n                    {\n                        bone.FindPropertyRelative(sHumanName).stringValue = humanBoneName;\n                        return bone;\n                    }\n                }\n\n                return null;\n            }\n\n            public const int kIconSize = 19;\n\n            static Color kBoneValid = new Color(0, 0.75f, 0, 1.0f);\n            static Color kBoneInvalid = new Color(1.0f, 0.3f, 0.25f, 1.0f);\n            static Color kBoneInactive = Color.gray;\n            static Color kBoneSelected = new Color(0.4f, 0.7f, 1.0f, 1.0f);\n            static Color kBoneDrop = new Color(0.1f, 0.7f, 1.0f, 1.0f);\n            public void BoneDotGUI(Rect rect, Rect selectRect, int boneIndex, bool doClickSelect, bool doDragDrop, bool doDeleteKey, SerializedObject serializedObject, AvatarMappingEditor editor)\n            {\n                int id = GUIUtility.GetControlID(FocusType.Passive, rect);\n                int keyboardID = GUIUtility.GetControlID(FocusType.Keyboard, selectRect);\n\n                if (doClickSelect)\n                    HandleClickSelection(keyboardID, selectRect, boneIndex);\n\n                if (doDeleteKey)\n                    HandleDeleteSelection(keyboardID, serializedObject, editor);\n\n                if (doDragDrop)\n                    HandleDragDrop(rect, boneIndex, id, serializedObject, editor);\n\n                Color old = GUI.color;\n\n                // Selection\n                if (AvatarMappingEditor.s_SelectedBoneIndex == boneIndex)\n                {\n                    GUI.color = kBoneSelected;\n                    GUI.DrawTexture(rect, AvatarMappingEditor.styles.dotSelection.image);\n                }\n\n                // State color\n                if (DragAndDrop.activeControlID == id)\n                    GUI.color = kBoneDrop;\n                else if (state == BoneState.Valid)\n                    GUI.color = kBoneValid;\n                else if (state == BoneState.None)\n                    GUI.color = kBoneInactive;\n                else\n                    GUI.color = kBoneInvalid;\n\n                // Frame\n                Texture tex;\n                if (HumanTrait.RequiredBone(boneIndex))\n                    tex = AvatarMappingEditor.styles.dotFrame.image;\n                else\n                    tex = AvatarMappingEditor.styles.dotFrameDotted.image;\n                GUI.DrawTexture(rect, tex);\n\n                // Fill\n                if (bone != null || DragAndDrop.activeControlID == id)\n                    GUI.DrawTexture(rect, AvatarMappingEditor.styles.dotFill.image);\n\n                GUI.color = old;\n            }\n\n            public void HandleClickSelection(int keyboardID, Rect selectRect, int boneIndex)\n            {\n                Event evt = Event.current;\n                if (evt.type == EventType.MouseDown && selectRect.Contains(evt.mousePosition))\n                {\n                    AvatarMappingEditor.s_SelectedBoneIndex = boneIndex;\n                    AvatarMappingEditor.s_DirtySelection = true;\n                    // case 837655.  Late update GUIUtility.keyboardControl to avoid it being overriden during scene selection.\n                    AvatarMappingEditor.s_KeyboardControl = keyboardID;\n                    Selection.activeTransform = bone;\n                    if (bone != null)\n                        EditorGUIUtility.PingObject(bone);\n                    evt.Use();\n                }\n            }\n\n            public void HandleDeleteSelection(int keyboardID, SerializedObject serializedObject, AvatarMappingEditor editor)\n            {\n                Event evt = Event.current;\n                if (evt.type == EventType.KeyDown)\n                {\n                    if (GUIUtility.keyboardControl == keyboardID)\n                    {\n                        if ((evt.keyCode == KeyCode.Backspace) || (evt.keyCode == KeyCode.Delete))\n                        {\n                            Undo.RegisterCompleteObjectUndo(editor, \"Avatar mapping modified\");\n\n                            //  Unreference transform component in selected bone.\n                            bone = null;\n                            state = BoneState.None;\n                            SerializedProperty humanBoneArray = serializedObject.FindProperty(sHuman);\n                            Serialize(humanBoneArray);\n\n                            //  Clear scene selection.\n                            Selection.activeTransform = null;\n\n                            GUI.changed = true;\n                            evt.Use();\n                        }\n                    }\n                }\n            }\n\n            private void HandleDragDrop(Rect dropRect, int boneIndex, int id, SerializedObject serializedObject, AvatarMappingEditor editor)\n            {\n                EventType eventType = Event.current.type;\n                switch (eventType)\n                {\n                    case EventType.DragExited:\n                        if (GUI.enabled)\n                            HandleUtility.Repaint();\n                        break;\n                    case EventType.DragUpdated:\n                    case EventType.DragPerform:\n                        if (dropRect.Contains(Event.current.mousePosition) && GUI.enabled)\n                        {\n                            Object[] references = DragAndDrop.objectReferences;\n                            Object validatedObject = references.Length == 1 ? references[0] : null;\n                            if (validatedObject != null)\n                            {\n                                if (!(validatedObject is Transform || validatedObject is GameObject) || EditorUtility.IsPersistent(validatedObject))\n                                    validatedObject = null;\n                            }\n                            if (validatedObject != null)\n                            {\n                                DragAndDrop.visualMode = DragAndDropVisualMode.Generic;\n                                if (eventType == EventType.DragPerform)\n                                {\n                                    Undo.RegisterCompleteObjectUndo(editor, \"Avatar mapping modified\");\n\n                                    if (validatedObject is GameObject)\n                                        bone = (validatedObject as GameObject).transform;\n                                    else\n                                        bone = validatedObject as Transform;\n\n                                    SerializedProperty humanBoneArray = serializedObject.FindProperty(sHuman);\n                                    Serialize(humanBoneArray);\n\n                                    GUI.changed = true;\n                                    DragAndDrop.AcceptDrag();\n                                    DragAndDrop.activeControlID = 0;\n                                }\n                                else\n                                {\n                                    DragAndDrop.activeControlID = id;\n                                }\n                                Event.current.Use();\n                            }\n                        }\n                        break;\n                }\n            }\n        }\n\n        private class BonePoseData\n        {\n            public Vector3 direction = Vector3.zero;\n            public bool compareInGlobalSpace = false;\n            public float maxAngle;\n            public int[] childIndices = null;\n            public Vector3 planeNormal = Vector3.zero;\n            public BonePoseData(Vector3 dir, bool globalSpace, float maxAngleDiff)\n            {\n                direction = (dir == Vector3.zero ? dir : dir.normalized);\n                compareInGlobalSpace = globalSpace;\n                maxAngle = maxAngleDiff;\n            }\n\n            public BonePoseData(Vector3 dir, bool globalSpace, float maxAngleDiff, int[] children) : this(dir, globalSpace, maxAngleDiff)\n            {\n                childIndices = children;\n            }\n\n            public BonePoseData(Vector3 dir, bool globalSpace, float maxAngleDiff, Vector3 planeNormal, int[] children) : this(dir, globalSpace, maxAngleDiff, children)\n            {\n                this.planeNormal = planeNormal;\n            }\n        }\n\n        private static string sHuman = \"m_HumanDescription.m_Human\";\n\n        internal static string sSkeleton = \"m_HumanDescription.m_Skeleton\";\n        internal static string sName = \"m_Name\";\n        internal static string sParentName = \"m_ParentName\";\n        internal static string sPosition = \"m_Position\";\n        internal static string sRotation = \"m_Rotation\";\n        internal static string sScale = \"m_Scale\";\n        internal static string sHumanName = \"m_HumanName\";\n        internal static string sBoneName = \"m_BoneName\";\n\n        private static BonePoseData[] sBonePoses = new BonePoseData[]\n        {\n            new BonePoseData(Vector3.up, true, 15),  // Hips,\n            new BonePoseData(new Vector3(-0.05f, -1, 0),      true, 15),   // LeftUpperLeg,\n            new BonePoseData(new Vector3(0.05f, -1, 0),      true, 15),    // RightUpperLeg,\n            new BonePoseData(new Vector3(-0.05f, -1, -0.15f), true, 20),   // LeftLowerLeg,\n            new BonePoseData(new Vector3(0.05f, -1, -0.15f), true, 20),    // RightLowerLeg,\n            new BonePoseData(new Vector3(-0.05f, 0, 1),       true, 20, Vector3.up, null),   // LeftFoot,\n            new BonePoseData(new Vector3(0.05f, 0, 1),       true, 20, Vector3.up, null),    // RightFoot,\n            new BonePoseData(Vector3.up, true, 30, new int[] {(int)HumanBodyBones.Chest, (int)HumanBodyBones.UpperChest, (int)HumanBodyBones.Neck, (int)HumanBodyBones.Head}),  // Spine,\n            new BonePoseData(Vector3.up, true, 30, new int[] {(int)HumanBodyBones.UpperChest, (int)HumanBodyBones.Neck, (int)HumanBodyBones.Head}),  // Chest,\n            new BonePoseData(Vector3.up, true, 30),  // Neck,\n            null, // Head,\n            new BonePoseData(-Vector3.right, true, 20),  // LeftShoulder,\n            new BonePoseData(Vector3.right, true, 20),   // RightShoulder,\n            new BonePoseData(-Vector3.right, true, 05),  // LeftArm,\n            new BonePoseData(Vector3.right, true, 05),   // RightArm,\n            new BonePoseData(-Vector3.right, true, 05),  // LeftForeArm,\n            new BonePoseData(Vector3.right, true, 05),   // RightForeArm,\n            new BonePoseData(-Vector3.right, false, 10, Vector3.forward, new int[] {(int)HumanBodyBones.LeftMiddleProximal}),  // LeftHand,\n            new BonePoseData(Vector3.right, false, 10, Vector3.forward, new int[] {(int)HumanBodyBones.RightMiddleProximal}),   // RightHand,\n            null, // LeftToes,\n            null, // RightToes,\n            null, // LeftEye,\n            null, // RightEye,\n            null, // Jaw,\n            new BonePoseData(new Vector3(-1, 0, 1), false, 10), // Left Thumb\n            new BonePoseData(new Vector3(-1, 0, 1), false, 05),\n            new BonePoseData(new Vector3(-1, 0, 1), false, 05),\n            new BonePoseData(-Vector3.right, false, 10),  // Left Index\n            new BonePoseData(-Vector3.right, false, 05),\n            new BonePoseData(-Vector3.right, false, 05),\n            new BonePoseData(-Vector3.right, false, 10),  // Left Middle\n            new BonePoseData(-Vector3.right, false, 05),\n            new BonePoseData(-Vector3.right, false, 05),\n            new BonePoseData(-Vector3.right, false, 10),  // Left Ring\n            new BonePoseData(-Vector3.right, false, 05),\n            new BonePoseData(-Vector3.right, false, 05),\n            new BonePoseData(-Vector3.right, false, 10),  // Left Little\n            new BonePoseData(-Vector3.right, false, 05),\n            new BonePoseData(-Vector3.right, false, 05),\n            new BonePoseData(new Vector3(1, 0, 1), false, 10),  // Right Thumb\n            new BonePoseData(new Vector3(1, 0, 1), false, 05),\n            new BonePoseData(new Vector3(1, 0, 1), false, 05),\n            new BonePoseData(Vector3.right, false, 10),   // Right Index\n            new BonePoseData(Vector3.right, false, 05),\n            new BonePoseData(Vector3.right, false, 05),\n            new BonePoseData(Vector3.right, false, 10),   // Right Middle\n            new BonePoseData(Vector3.right, false, 05),\n            new BonePoseData(Vector3.right, false, 05),\n            new BonePoseData(Vector3.right, false, 10),   // Right Ring\n            new BonePoseData(Vector3.right, false, 05),\n            new BonePoseData(Vector3.right, false, 05),\n            new BonePoseData(Vector3.right, false, 10),   // Right Little\n            new BonePoseData(Vector3.right, false, 05),\n            new BonePoseData(Vector3.right, false, 05),\n            new BonePoseData(Vector3.up, true, 30, new int[] {(int)HumanBodyBones.Neck, (int)HumanBodyBones.Head}),  // UpperChest,\n        };\n\n        public static Dictionary<Transform, bool> GetModelBones(Transform root, bool includeAll, BoneWrapper[] humanBones)\n        {\n            if (root == null)\n                return null;\n\n            // Find out which transforms are actual bones and which are parents of actual bones\n            Dictionary<Transform, bool> bones = new Dictionary<Transform, bool>();\n            List<Transform> skinnedBones = new List<Transform>();\n\n            if (!includeAll)\n            {\n                // Find out in advance which bones are used by SkinnedMeshRenderers\n                SkinnedMeshRenderer[] skinnedMeshRenderers = root.GetComponentsInChildren<SkinnedMeshRenderer>();\n\n                foreach (SkinnedMeshRenderer rend in skinnedMeshRenderers)\n                {\n                    Transform[] meshBones = rend.bones;\n                    bool[] meshBonesUsed = new bool[meshBones.Length];\n                    BoneWeight[] weights = rend.sharedMesh.boneWeights;\n                    foreach (BoneWeight w in weights)\n                    {\n                        if (w.weight0 != 0)\n                            meshBonesUsed[w.boneIndex0] = true;\n                        if (w.weight1 != 0)\n                            meshBonesUsed[w.boneIndex1] = true;\n                        if (w.weight2 != 0)\n                            meshBonesUsed[w.boneIndex2] = true;\n                        if (w.weight3 != 0)\n                            meshBonesUsed[w.boneIndex3] = true;\n                    }\n                    for (int i = 0; i < meshBones.Length; i++)\n                    {\n                        if (meshBonesUsed[i])\n                            if (!skinnedBones.Contains(meshBones[i]))\n                                skinnedBones.Add(meshBones[i]);\n                    }\n                }\n\n                // Recursive call\n                DetermineIsActualBone(root, bones, skinnedBones, false, humanBones);\n            }\n\n            // If not enough bones were found, fallback to treating all transforms as bones\n            if (bones.Count < HumanTrait.RequiredBoneCount)\n            {\n                bones.Clear();\n                skinnedBones.Clear();\n                DetermineIsActualBone(root, bones, skinnedBones, true, humanBones);\n            }\n\n            return bones;\n        }\n\n        private static bool DetermineIsActualBone(Transform tr, Dictionary<Transform, bool> bones, List<Transform> skinnedBones, bool includeAll, BoneWrapper[] humanBones)\n        {\n            bool actualBone = includeAll;\n            bool boneParent = false;\n            bool boneChild = false;\n\n            // Actual bone parent if any of children are bones\n            int childBones = 0;\n            foreach (Transform child in tr)\n                if (DetermineIsActualBone(child, bones, skinnedBones, includeAll, humanBones))\n                    childBones++;\n\n            if (childBones > 0)\n                boneParent = true;\n            if (childBones > 1)\n                actualBone = true;\n\n            // Actual bone if used by skinned mesh\n            if (!actualBone)\n                if (skinnedBones.Contains(tr))\n                    actualBone = true;\n\n            // Actual bone if contains component other than transform\n            if (!actualBone)\n            {\n                Component[] components = tr.GetComponents<Component>();\n                if (components.Length > 1)\n                {\n                    foreach (Component comp in components)\n                    {\n                        if ((comp is Renderer) && !(comp is SkinnedMeshRenderer))\n                        {\n                            Bounds bounds = (comp as Renderer).bounds;\n\n                            // Double size of bounds in order to still make bone valid\n                            // if its pivot is just slightly outside of renderer bounds.\n                            bounds.extents = bounds.size;\n\n                            // If the parent is inside the bounds, this transform is probably\n                            // just a geometry dummy for the parent bone\n                            if (tr.childCount == 0 && tr.parent && bounds.Contains(tr.parent.position))\n                            {\n                                if (tr.parent.GetComponent<Renderer>() != null)\n                                    actualBone = true;\n                                else\n                                    boneChild = true;\n                            }\n                            // if not, give transform itself a chance.\n                            // If pivot is way outside of bounds, it's not an actual bone.\n                            else if (bounds.Contains(tr.position))\n                            {\n                                actualBone = true;\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Actual bone if the bone is define in human definition.\n            if (!actualBone && humanBones != null)\n            {\n                foreach (var boneWrapper in humanBones)\n                {\n                    if (tr == boneWrapper.bone)\n                    {\n                        actualBone = true;\n                        break;\n                    }\n                }\n            }\n\n            if (actualBone)\n                bones[tr] = true;\n            else if (boneParent)\n            {\n                if (!bones.ContainsKey(tr))\n                    bones[tr] = false;\n            }\n            else if (boneChild)\n                bones[tr.parent] = true;\n\n            return bones.ContainsKey(tr);\n        }\n\n        public static int GetFirstHumanBoneAncestor(BoneWrapper[] bones, int boneIndex)\n        {\n            boneIndex = HumanTrait.GetParentBone(boneIndex);\n            while (boneIndex > 0 && bones[boneIndex].bone == null)\n                boneIndex = HumanTrait.GetParentBone(boneIndex);\n            return boneIndex;\n        }\n\n        public static int GetHumanBoneChild(BoneWrapper[] bones, int boneIndex)\n        {\n            for (int i = 0; i < HumanTrait.BoneCount; i++)\n                if (HumanTrait.GetParentBone(i) == boneIndex)\n                    return i;\n            return -1;\n        }\n\n        public static BoneWrapper[] GetHumanBones(SerializedProperty humanBoneArray, Dictionary<Transform, bool> actualBones)\n        {\n            // cache the (human bone name, bone name) mapping,\n            // since accessing a dictionary is much faster than iterating over the serialized properties\n            Dictionary<string, string> existingMappings = new Dictionary<string, string>();\n            for (int j = 0; j < humanBoneArray?.arraySize; ++j)\n            {\n                var prop = humanBoneArray.GetArrayElementAtIndex(j);\n                SerializedProperty humanNameP = prop.FindPropertyRelative(sHumanName);\n                SerializedProperty boneNameP = prop.FindPropertyRelative(sBoneName);\n\n                existingMappings[humanNameP.stringValue] = boneNameP.stringValue;\n            }\n\n            return GetHumanBones(existingMappings, actualBones);\n        }\n\n        public static BoneWrapper[] GetHumanBones(Dictionary<string, string> existingMappings, Dictionary<Transform, bool> actualBones)\n        {\n            string[] humanBoneNames = HumanTrait.BoneName;\n            BoneWrapper[] bones = new BoneWrapper[humanBoneNames.Length];\n            for (int i = 0; i < humanBoneNames.Length; i++)\n            {\n                Transform bone = null;\n\n                var humanBoneName = humanBoneNames[i];\n                if (existingMappings?.ContainsKey(humanBoneName) == true)\n                {\n                    string boneName = existingMappings[humanBoneName];\n                    bone = actualBones.Keys.FirstOrDefault(b => (b?.name == boneName));\n                }\n\n                bones[i] = new BoneWrapper(humanBoneName, bone);\n            }\n            return bones;\n        }\n\n        public static void ClearAll(SerializedProperty humanBoneArray, SerializedProperty humanSkeletonArray)\n        {\n            ClearHumanBoneArray(humanBoneArray);\n            ClearSkeletonBoneArray(humanSkeletonArray);\n        }\n\n        public static void ClearHumanBoneArray(SerializedProperty humanBody)\n        {\n            if (humanBody != null && humanBody.isArray)\n                humanBody.ClearArray();\n        }\n\n        public static void ClearSkeletonBoneArray(SerializedProperty skeleton)\n        {\n            if (skeleton != null && skeleton.isArray)\n                skeleton.ClearArray();\n        }\n\n        public static bool IsPoseValidOnInstance(GameObject modelPrefab, SerializedObject modelImporterSerializedObject)\n        {\n            GameObject instance = GameObject.Instantiate(modelPrefab) as GameObject;\n            instance.hideFlags = HideFlags.HideAndDontSave;\n\n            Dictionary<Transform, bool> modelBones = GetModelBones(instance.transform, false, null);\n            SerializedProperty humanBoneArray = modelImporterSerializedObject.FindProperty(sHuman);\n            BoneWrapper[] humanBones = GetHumanBones(humanBoneArray, modelBones);\n\n            TransferDescriptionToPose(modelImporterSerializedObject, instance.transform);\n            bool valid = IsPoseValid(humanBones);\n\n            GameObject.DestroyImmediate(instance);\n            return valid;\n        }\n\n        /// <summary>\n        /// Gets the human bone mappings and the skeleton.\n        ///\n        /// We need to call this method when importing humanoids, in order to have a valid avatar during the import process.\n        /// </summary>\n        [RequiredByNativeCode]\n        private static void SetupHumanSkeleton(GameObject modelPrefab, ref HumanBone[] humanBoneMappingArray, out SkeletonBone[] skeletonBones, out bool hasTranslationDoF)\n        {\n            SimpleProfiler.Begin(\"MapHumanBones Total\");\n\n            hasTranslationDoF = false;\n\n            var modelInstance = GameObject.Instantiate(modelPrefab);\n\n            SimpleProfiler.Begin(\"IsBiped\");\n            bool isBiped = AvatarBipedMapper.IsBiped(modelInstance.transform, null);\n            SimpleProfiler.End();\n\n            SimpleProfiler.Begin(\"SampleBindPose\");\n            SampleBindPose(modelInstance);\n            SimpleProfiler.End();\n\n            // Perform auto-mapping and get back mapping\n            SimpleProfiler.Begin(\"GetModelBones\");\n            Dictionary<Transform, bool> modelBones = GetModelBones(modelInstance.transform, false, null);\n            SimpleProfiler.End();\n\n            Dictionary<int, Transform> mapping = null;\n\n            if (isBiped)\n            {\n                SimpleProfiler.Begin(\"MapBipedBones\");\n                mapping = AvatarBipedMapper.MapBones(modelInstance.transform);\n                SimpleProfiler.End();\n            }\n            else\n            {\n                SimpleProfiler.Begin(\"MapBones\");\n                mapping = AvatarAutoMapper.MapBones(modelInstance.transform, modelBones);\n                SimpleProfiler.End();\n            }\n\n            // Apply mapping to SerializedObject\n            SimpleProfiler.Begin(\"ApplyMapping\");\n\n            Dictionary<string, string> existingMappings = null;\n            if (humanBoneMappingArray != null && humanBoneMappingArray.Length > 0)\n            {\n                existingMappings = new Dictionary<string, string>();\n                for (var i = 0; i < humanBoneMappingArray.Length; ++i)\n                    existingMappings[humanBoneMappingArray[i].humanName] = humanBoneMappingArray[i].boneName;\n            }\n            List<HumanBone> humanBoneMappings = new List<HumanBone>();\n            BoneWrapper[] humanBones = GetHumanBones(existingMappings, modelBones);\n            for (int i = 0; i < humanBones.Length; ++i)\n            {\n                BoneWrapper bone = humanBones[i];\n                if (mapping.ContainsKey(i))\n                {\n                    humanBoneMappings.Add(\n                        new HumanBone()\n                        {\n                            boneName = mapping[i].name,\n                            humanName = bone.humanBoneName,\n                            limit = new HumanLimit() { useDefaultValues = true }\n                        });\n                    humanBones[i].bone = mapping[i];\n                }\n            }\n            humanBoneMappingArray = humanBoneMappings.ToArray();\n            SimpleProfiler.End();\n\n            if (!isBiped)\n            {\n                // Check error of current pose (bind pose)\n                float bindPoseError = GetPoseError(humanBones);\n\n                // Check error of reset pose\n                CopyPose(modelInstance, modelPrefab);\n                float resetPoseError = GetPoseError(humanBones);\n\n                // If the bind pose was better, sample the bind pose again to use that as a starting point for the T-pose.\n                // Otherwise use the reset pose as starting point.\n                if (bindPoseError < resetPoseError)\n                    SampleBindPose(modelInstance);\n\n                // Move bones into valid T-pose\n                SimpleProfiler.Begin(\"MakePoseValid\");\n                MakePoseValid(humanBones);\n                SimpleProfiler.End();\n            }\n            else\n            {\n                SimpleProfiler.Begin(\"SetBipedPose\");\n                AvatarBipedMapper.BipedPose(modelInstance, humanBones);\n                SimpleProfiler.End();\n\n                hasTranslationDoF = true;\n            }\n\n            // Apply pose to SerializedObject\n            SimpleProfiler.Begin(\"TransferPose\");\n            skeletonBones = GetSkeletonBones(modelInstance.transform);\n            SimpleProfiler.End();\n\n            GameObject.DestroyImmediate(modelInstance);\n\n            SimpleProfiler.End(); // MapHumanBones Total\n        }\n\n        public static bool TestAndValidateAutoSetup(GameObject modelAsset)\n        {\n            // Sanity check\n            if (modelAsset == null)\n            {\n                Debug.LogError(\"GameObject is null\");\n                return false;\n            }\n            if (!(PrefabUtility.IsPartOfModelPrefab(modelAsset) && PrefabUtility.IsPartOfPrefabAsset(modelAsset)))\n            {\n                Debug.LogError(modelAsset.name + \": GameObject is not a ModelPrefab\", modelAsset);\n                return false;\n            }\n            if (modelAsset.transform.parent != null)\n            {\n                Debug.LogError(modelAsset.name + \": GameObject is not the root\", modelAsset);\n                return false;\n            }\n\n            // Get importer\n            string path = AssetDatabase.GetAssetPath(modelAsset);\n            ModelImporter importer = AssetImporter.GetAtPath(path) as ModelImporter;\n            if (importer == null)\n            {\n                Debug.LogError(modelAsset.name + \": Could not load ModelImporter (path:\" + path + \")\", modelAsset);\n                return false;\n            }\n\n            using (var serializedObject = new SerializedObject(importer))\n            {\n                // Get CreateAvatar property\n                SerializedProperty humanBoneArray = serializedObject.FindProperty(sHuman);\n                SerializedProperty humanSkeletonArray = serializedObject.FindProperty(sSkeleton);\n                SerializedProperty animationType = serializedObject.FindProperty(\"m_AnimationType\");\n                if (animationType == null)\n                {\n                    Debug.LogError(modelAsset.name + \": Could not find property m_AnimationType on ModelImporter\", modelAsset);\n                    return false;\n                }\n\n                // Clear avatar import settings and reimport\n                animationType.intValue = 2;\n                ClearAll(humanBoneArray, humanSkeletonArray);\n                serializedObject.ApplyModifiedProperties();\n                AssetDatabase.ImportAsset(path);\n\n                // Setup avatar import settings and reimport\n                animationType.intValue = 3;\n                serializedObject.ApplyModifiedProperties();\n                // the humanoid avatar is set up during import\n                AssetDatabase.ImportAsset(path);\n\n                // Check if Avatar is valid\n                Avatar avatar = AssetDatabase.LoadAssetAtPath(path, typeof(Avatar)) as Avatar;\n                if (avatar == null)\n                {\n                    Debug.LogError(modelAsset.name + \": Did not find Avatar after reimport with CreateAvatar enabled\", modelAsset);\n                    return false;\n                }\n                if (!avatar.isHuman)\n                {\n                    Debug.LogError(modelAsset.name + \": Avatar is not valid after reimport\", modelAsset);\n                    return false;\n                }\n                if (!IsPoseValidOnInstance(modelAsset, serializedObject))\n                {\n                    Debug.LogError(modelAsset.name + \": Avatar has invalid pose after reimport\", modelAsset);\n                    return false;\n                }\n\n                // Check that mapping matches reference mapping\n                string pathWithoutExtension = path.Substring(0, path.Length - System.IO.Path.GetExtension(path).Length);\n\n                // Get reference template\n                string templatePath = pathWithoutExtension + \".ht\";\n                HumanTemplate humanTemplate = AssetDatabase.LoadMainAssetAtPath(templatePath) as HumanTemplate;\n                if (humanTemplate == null)\n                    Debug.LogWarning(modelAsset.name + \": Didn't find template at path \" + templatePath);\n                else\n                {\n                    // Get file with bones to ignore, if present\n                    List<string> ignoreBones = null;\n                    string ignorePath = pathWithoutExtension + \".ignore\";\n                    if (System.IO.File.Exists(ignorePath))\n                        ignoreBones = new List<string>(System.IO.File.ReadAllLines(ignorePath));\n\n                    // Create instance\n                    GameObject instance = GameObject.Instantiate(modelAsset);\n                    instance.hideFlags = HideFlags.HideAndDontSave;\n\n                    // Get BoneWrapper array\n                    Dictionary<Transform, bool> modelBones = GetModelBones(instance.transform, false, null);\n                    BoneWrapper[] humanBones = GetHumanBones(humanBoneArray, modelBones);\n\n                    // Test that bone mapping match the one in the reference\n                    bool mismatch = false;\n                    for (int i = 0; i < humanBones.Length; i++)\n                    {\n                        // Ignore bones in the ignore file\n                        if (ignoreBones != null && ignoreBones.Contains(humanBones[i].humanBoneName))\n                            continue;\n\n                        string referenceBoneName = humanTemplate.Find(humanBones[i].humanBoneName);\n                        string actualBoneName = (humanBones[i].bone == null ? \"\" : humanBones[i].bone.name);\n                        if (!AvatarMappingEditor.MatchName(actualBoneName, referenceBoneName))\n                        {\n                            mismatch = true;\n                            Debug.LogError(modelAsset.name + \": Avatar has bone \" + humanBones[i].humanBoneName + \" mapped to \\\"\" + actualBoneName + \"\\\" but expected \\\"\" + referenceBoneName + \"\\\"\", modelAsset);\n                        }\n                    }\n\n                    GameObject.DestroyImmediate(instance);\n\n                    if (mismatch)\n                        return false;\n                }\n            }\n\n            return true;\n        }\n\n        public static void DebugTransformTree(Transform tr, Dictionary<Transform, bool> bones, int level)\n        {\n            string pre = \"  \";\n            if (bones.ContainsKey(tr))\n                if (bones[tr])\n                    pre = \"* \";\n                else\n                    pre = \". \";\n            Debug.Log(\"                                             \".Substring(0, level * 2) + pre + tr.name + \"\\n\\n\");\n            foreach (Transform child in tr)\n                DebugTransformTree(child, bones, level + 1);\n        }\n\n        public static SerializedProperty FindSkeletonBone(SerializedObject serializedObject, Transform t, bool createMissing, bool isRoot)\n        {\n            SerializedProperty skeletonBoneArray = serializedObject.FindProperty(sSkeleton);\n            if (skeletonBoneArray == null || !skeletonBoneArray.isArray)\n                return null;\n            return FindSkeletonBone(skeletonBoneArray, t, createMissing, isRoot);\n        }\n\n        public static SerializedProperty FindSkeletonBone(SerializedProperty skeletonBoneArray, Transform t, bool createMissing, bool isRoot)\n        {\n            if (isRoot && skeletonBoneArray.arraySize > 0)\n            {\n                SerializedProperty boneP = skeletonBoneArray.GetArrayElementAtIndex(0);\n                SerializedProperty boneNameP = boneP.FindPropertyRelative(sName);\n                if (boneNameP.stringValue == t.name)\n                    return boneP;\n            }\n            else\n            {\n                // So root object name is not unique among all his child\n                // so we always need to skip the first element which is the root\n                for (int i = 1; i < skeletonBoneArray.arraySize; i++)\n                {\n                    SerializedProperty boneP = skeletonBoneArray.GetArrayElementAtIndex(i);\n                    SerializedProperty boneNameP = boneP.FindPropertyRelative(sName);\n                    if (boneNameP.stringValue == t.name)\n                        return boneP;\n                }\n            }\n\n            if (createMissing)\n            {\n                skeletonBoneArray.arraySize++;\n                SerializedProperty bone = skeletonBoneArray.GetArrayElementAtIndex(skeletonBoneArray.arraySize - 1);\n                if (bone != null)\n                {\n                    bone.FindPropertyRelative(sName).stringValue = t.name;\n                    bone.FindPropertyRelative(sParentName).stringValue = isRoot ? \"\" : t.parent.name;\n\n                    bone.FindPropertyRelative(sPosition).vector3Value = t.localPosition;\n                    bone.FindPropertyRelative(sRotation).quaternionValue = t.localRotation;\n                    bone.FindPropertyRelative(sScale).vector3Value = t.localScale;\n                    return bone;\n                }\n            }\n            return null;\n        }\n\n        public static void CopyPose(GameObject go, GameObject source)\n        {\n            GameObject instance = GameObject.Instantiate(source);\n            instance.hideFlags = HideFlags.HideAndDontSave;\n            AnimatorUtility.DeoptimizeTransformHierarchy(instance);\n            CopyPose(go.transform, instance.transform);\n            GameObject.DestroyImmediate(instance);\n        }\n\n        private static void CopyPose(Transform t, Transform source)\n        {\n            t.localPosition = source.localPosition;\n            t.localRotation = source.localRotation;\n            t.localScale = source.localScale;\n            foreach (Transform child in t)\n            {\n                Transform sourceChild = source.Find(child.name);\n                if (sourceChild)\n                    CopyPose(child, sourceChild);\n            }\n        }\n\n        public static void GetBindPoseBonePositionRotation(Matrix4x4 skinMatrix, Matrix4x4 boneMatrix, Transform bone, out Vector3 position, out Quaternion rotation)\n        {\n            // Get global matrix for bone\n            Matrix4x4 bindMatrixGlobal = skinMatrix * boneMatrix.inverse;\n\n            // Get local X, Y, Z, and position of matrix\n            Vector3 mX = new Vector3(bindMatrixGlobal.m00, bindMatrixGlobal.m10, bindMatrixGlobal.m20);\n            Vector3 mY = new Vector3(bindMatrixGlobal.m01, bindMatrixGlobal.m11, bindMatrixGlobal.m21);\n            Vector3 mZ = new Vector3(bindMatrixGlobal.m02, bindMatrixGlobal.m12, bindMatrixGlobal.m22);\n            Vector3 mP = new Vector3(bindMatrixGlobal.m03, bindMatrixGlobal.m13, bindMatrixGlobal.m23);\n\n            // Set position\n            // Adjust scale of matrix to compensate for difference in binding scale and model scale\n            float bindScale = mZ.magnitude;\n            float modelScale = Mathf.Abs(bone.lossyScale.z);\n            position = mP * (modelScale / bindScale);\n\n            // Set rotation\n            // Check if scaling is negative and handle accordingly\n            if (Vector3.Dot(Vector3.Cross(mX, mY), mZ) >= 0)\n                rotation = Quaternion.LookRotation(mZ, mY);\n            else\n                rotation = Quaternion.LookRotation(-mZ, -mY);\n        }\n\n        public static void SampleBindPose(GameObject go)\n        {\n            List<SkinnedMeshRenderer> skins = new List<SkinnedMeshRenderer>(go.GetComponentsInChildren<SkinnedMeshRenderer>());\n            skins.Sort(new SkinTransformHierarchySorter());\n            foreach (SkinnedMeshRenderer skin in skins)\n            {\n                //Debug.Log (\"Sampling skinning of SkinnedMeshRenderer \"+skin.name);\n                Matrix4x4 goMatrix = skin.transform.localToWorldMatrix;\n                List<Transform> bones = new List<Transform>(skin.bones);\n                Vector3[] backupLocalPosition = new Vector3[bones.Count];\n\n                // backup local position of bones. Only use rotation given by bind pose\n                for (int i = 0; i < bones.Count; i++)\n                {\n                    backupLocalPosition[i] = bones[i].localPosition;\n                }\n\n                // Set all parents to be null to be able to set global alignments of bones without affecting their children.\n                Dictionary<Transform, Transform> parents = new Dictionary<Transform, Transform>();\n                foreach (Transform bone in bones)\n                {\n                    parents[bone] = bone.parent;\n                    bone.parent = null;\n                }\n\n                // Set global space position and rotation of each bone\n                for (int i = 0; i < bones.Count; i++)\n                {\n                    Vector3 position;\n                    Quaternion rotation;\n                    GetBindPoseBonePositionRotation(goMatrix, skin.sharedMesh.bindposes[i], bones[i], out position, out rotation);\n                    bones[i].position = position;\n                    bones[i].rotation = rotation;\n                }\n\n                // Reconnect bones in their original hierarchy\n                foreach (Transform bone in bones)\n                    bone.parent = parents[bone];\n\n                // put back local postion of bones\n                for (int i = 0; i < bones.Count; i++)\n                {\n                    bones[i].localPosition = backupLocalPosition[i];\n                }\n            }\n        }\n\n        public static void ShowBindPose(SkinnedMeshRenderer skin)\n        {\n            Matrix4x4 goMatrix = skin.transform.localToWorldMatrix;\n            for (int i = 0; i < skin.bones.Length; i++)\n            {\n                Vector3 position;\n                Quaternion rotation;\n                GetBindPoseBonePositionRotation(goMatrix, skin.sharedMesh.bindposes[i], skin.bones[i], out position, out rotation);\n                float size = HandleUtility.GetHandleSize(position);\n                Handles.color = Handles.xAxisColor;\n                Handles.DrawLine(position, position + rotation * Vector3.right * 0.3f * size);\n                Handles.color = Handles.yAxisColor;\n                Handles.DrawLine(position, position + rotation * Vector3.up * 0.3f * size);\n                Handles.color = Handles.zAxisColor;\n                Handles.DrawLine(position, position + rotation * Vector3.forward * 0.3f * size);\n            }\n        }\n\n        private class SkinTransformHierarchySorter : IComparer<SkinnedMeshRenderer>\n        {\n            public int Compare(SkinnedMeshRenderer skinA, SkinnedMeshRenderer skinB)\n            {\n                Transform a = skinA.transform;\n                Transform b = skinB.transform;\n                while (true)\n                {\n                    if (a == null)\n                        if (b == null)\n                            return 0;\n                        else\n                            return -1;\n                    if (b == null)\n                        return 1;\n                    a = a.parent;\n                    b = b.parent;\n                }\n            }\n        }\n\n        public static void TransferPoseToDescription(SerializedProperty skeletonBoneArray, Transform root)\n        {\n            SkeletonBone[] skeletonBones = GetSkeletonBones(root);\n\n            ModelImporter.UpdateSkeletonPose(skeletonBones, skeletonBoneArray);\n        }\n\n        public static SkeletonBone[] GetSkeletonBones(Transform root)\n        {\n            List<SkeletonBone> skeletonBones = new List<SkeletonBone>();\n            if (root)\n                TransferPoseToDescription(root, true, skeletonBones);\n\n            return skeletonBones.ToArray();\n        }\n\n        private static void TransferPoseToDescription(Transform transform, bool isRoot, List<SkeletonBone> skeletonBones)\n        {\n            SkeletonBone skeletonBone = new SkeletonBone();\n\n            skeletonBone.name = transform.name;\n            skeletonBone.parentName = isRoot ? \"\" : transform.parent.name;\n            skeletonBone.position = transform.localPosition;\n            skeletonBone.rotation = transform.localRotation;\n            skeletonBone.scale = transform.localScale;\n\n            skeletonBones.Add(skeletonBone);\n\n            foreach (Transform child in transform)\n                TransferPoseToDescription(child, false, skeletonBones);\n        }\n\n        public static void TransferDescriptionToPose(SerializedObject serializedObject, Transform root)\n        {\n            if (root != null)\n                TransferDescriptionToPose(serializedObject, root, true);\n        }\n\n        private static void TransferDescriptionToPose(SerializedObject serializedObject, Transform transform, bool isRoot)\n        {\n            SerializedProperty bone = FindSkeletonBone(serializedObject, transform, false, isRoot);\n            if (bone != null)\n            {\n                SerializedProperty positionP = bone.FindPropertyRelative(sPosition);\n                SerializedProperty rotationP = bone.FindPropertyRelative(sRotation);\n                SerializedProperty scaleP = bone.FindPropertyRelative(sScale);\n                transform.localPosition = positionP.vector3Value;\n                transform.localRotation = rotationP.quaternionValue;\n                transform.localScale = scaleP.vector3Value;\n            }\n\n            foreach (Transform child in transform)\n                TransferDescriptionToPose(serializedObject, child, false);\n        }\n\n        // BONE ALIGNMENT HANDLING\n\n        public static bool IsPoseValid(BoneWrapper[] bones)\n        {\n            return (GetPoseError(bones) == 0);\n        }\n\n        public static float GetPoseError(BoneWrapper[] bones)\n        {\n            Quaternion orientation = AvatarComputeOrientation(bones);\n            float error = 0;\n\n            for (int i = 0; i < sBonePoses.Length; i++)\n                error += GetBoneAlignmentError(bones, orientation, i);\n\n            error += GetCharacterPositionError(bones);\n\n            return error;\n        }\n\n        // Enforces TPose T-Pose\n        public static void MakePoseValid(BoneWrapper[] bones)\n        {\n            Quaternion orientation = AvatarComputeOrientation(bones);\n            for (int i = 0; i < sBonePoses.Length; i++)\n            {\n                MakeBoneAlignmentValid(bones, orientation, i);\n                // Recalculate orientation after handling hips since they may have changed it\n                if (i == (int)HumanBodyBones.Hips)\n                    orientation = AvatarComputeOrientation(bones);\n            }\n\n            // Move feet to ground plane\n            MakeCharacterPositionValid(bones);\n        }\n\n        public static float GetBoneAlignmentError(BoneWrapper[] bones, Quaternion avatarOrientation, int boneIndex)\n        {\n            if (boneIndex < 0 || boneIndex >= sBonePoses.Length)\n                return 0;\n\n            BoneWrapper bone = bones[boneIndex];\n            BonePoseData pose = sBonePoses[boneIndex];\n            if (bone.bone == null || pose == null)\n                return 0;\n\n            if (boneIndex == (int)HumanBodyBones.Hips)\n            {\n                float angleX = Vector3.Angle(avatarOrientation * Vector3.right, Vector3.right);\n                float angleY = Vector3.Angle(avatarOrientation * Vector3.up, Vector3.up);\n                float angleZ = Vector3.Angle(avatarOrientation * Vector3.forward, Vector3.forward);\n                return Mathf.Max(0, Mathf.Max(angleX, angleY, angleZ) - pose.maxAngle);\n            }\n\n            Vector3 dir = GetBoneAlignmentDirection(bones, avatarOrientation, boneIndex);\n            if (dir == Vector3.zero)\n                return 0;\n            Quaternion space = GetRotationSpace(bones, avatarOrientation, boneIndex);\n            Vector3 goalDir = space * pose.direction;\n            if (pose.planeNormal != Vector3.zero)\n                dir = Vector3.ProjectOnPlane(dir, space * pose.planeNormal);\n\n            // Check if the bone direction is not close enough to the target direction\n            return Mathf.Max(0, Vector3.Angle(dir, goalDir) - pose.maxAngle);\n        }\n\n        public static void MakeBoneAlignmentValid(BoneWrapper[] bones, Quaternion avatarOrientation, int boneIndex)\n        {\n            if (boneIndex < 0 || boneIndex >= sBonePoses.Length || boneIndex >= bones.Length)\n                return;\n\n            BoneWrapper bone = bones[boneIndex];\n            BonePoseData pose = sBonePoses[boneIndex];\n            if (bone.bone == null || pose == null)\n                return;\n\n            if (boneIndex == (int)HumanBodyBones.Hips)\n            {\n                float angleX = Vector3.Angle(avatarOrientation * Vector3.right, Vector3.right);\n                float angleY = Vector3.Angle(avatarOrientation * Vector3.up, Vector3.up);\n                float angleZ = Vector3.Angle(avatarOrientation * Vector3.forward, Vector3.forward);\n                if (angleX > pose.maxAngle || angleY > pose.maxAngle || angleZ > pose.maxAngle)\n                    bone.bone.rotation = Quaternion.Inverse(avatarOrientation) * bone.bone.rotation;\n                return;\n            }\n\n            Vector3 dir = GetBoneAlignmentDirection(bones, avatarOrientation, boneIndex);\n            if (dir == Vector3.zero)\n                return;\n            Quaternion space = GetRotationSpace(bones, avatarOrientation, boneIndex);\n            Vector3 goalDir = space * pose.direction;\n            if (pose.planeNormal != Vector3.zero)\n                dir = Vector3.ProjectOnPlane(dir, space * pose.planeNormal);\n\n            // If the bone direction is not close enough to the target direction,\n            // rotate it so it matches the target direction.\n            float deltaAngle = Vector3.Angle(dir, goalDir);\n            if (deltaAngle > pose.maxAngle * 0.99f)\n            {\n                Quaternion adjust = Quaternion.FromToRotation(dir, goalDir);\n\n                // If this bone is hip or knee, remember global foor rotation and apply it after this adjustment\n                Transform footBone = null;\n                Quaternion footRot = Quaternion.identity;\n                if (boneIndex == (int)HumanBodyBones.LeftUpperLeg || boneIndex == (int)HumanBodyBones.LeftLowerLeg)\n                    footBone = bones[(int)HumanBodyBones.LeftFoot].bone;\n                if (boneIndex == (int)HumanBodyBones.RightUpperLeg || boneIndex == (int)HumanBodyBones.RightLowerLeg)\n                    footBone = bones[(int)HumanBodyBones.RightFoot].bone;\n                if (footBone != null)\n                    footRot = footBone.rotation;\n\n                // Adjust only enough to fall within maxAngle\n                float adjustAmount = Mathf.Clamp01(1.05f - (pose.maxAngle / deltaAngle));\n                adjust = Quaternion.Slerp(Quaternion.identity, adjust, adjustAmount);\n\n                bone.bone.rotation = adjust * bone.bone.rotation;\n\n                // Revert foot rotation to what it was\n                if (footBone != null)\n                    footBone.rotation = footRot;\n            }\n        }\n\n        private static Quaternion GetRotationSpace(BoneWrapper[] bones, Quaternion avatarOrientation, int boneIndex)\n        {\n            Quaternion parentDelta = Quaternion.identity;\n            BonePoseData pose = sBonePoses[boneIndex];\n            if (!pose.compareInGlobalSpace)\n            {\n                int parentIndex = HumanTrait.GetParentBone(boneIndex);\n\n                if (parentIndex > 0)\n                {\n                    BonePoseData parentPose = sBonePoses[parentIndex];\n                    if (bones[parentIndex].bone != null && parentPose != null)\n                    {\n                        Vector3 parentDir = GetBoneAlignmentDirection(bones, avatarOrientation, parentIndex);\n                        if (parentDir != Vector3.zero)\n                        {\n                            Vector3 parentPoseDir = avatarOrientation * parentPose.direction;\n                            parentDelta = Quaternion.FromToRotation(parentPoseDir, parentDir);\n                        }\n                    }\n                }\n            }\n\n            return parentDelta * avatarOrientation;\n        }\n\n        private static Vector3 GetBoneAlignmentDirection(BoneWrapper[] bones, Quaternion avatarOrientation, int boneIndex)\n        {\n            if (sBonePoses[boneIndex] == null)\n                return Vector3.zero;\n\n            BoneWrapper bone = bones[boneIndex];\n            Vector3 dir;\n\n            // Get the child bone\n            BonePoseData pose = sBonePoses[boneIndex];\n            int childBoneIndex = -1;\n            if (pose.childIndices != null)\n            {\n                foreach (int i in pose.childIndices)\n                {\n                    if (bones[i].bone != null)\n                    {\n                        childBoneIndex = i;\n                        break;\n                    }\n                }\n            }\n            else\n            {\n                childBoneIndex = GetHumanBoneChild(bones, boneIndex);\n            }\n\n            // TODO@MECANIM Something si wrong with the indexes\n            //if (boneIndex == (int)HumanBodyBones.LeftHand)\n            //  Debug.Log (\"Child bone for left hand: \"+childBoneIndex);\n\n            if (childBoneIndex >= 0 && bones[childBoneIndex] != null && bones[childBoneIndex].bone != null)\n            {\n                // Get direction from bone to child\n                BoneWrapper childBone = bones[childBoneIndex];\n                dir = childBone.bone.position - bone.bone.position;\n\n                // TODO@MECANIM Something si wrong with the indexes\n                //if (boneIndex == (int)HumanBodyBones.LeftHand)\n                //  Debug.Log (\" - \"+childBone.humanBoneName + \" - \" +childBone.bone.name);\n            }\n            else\n            {\n                if (bone.bone.childCount != 1)\n                    return Vector3.zero;\n\n                dir = Vector3.zero;\n                // Get direction from bone to child\n                foreach (Transform child in bone.bone)\n                {\n                    dir = child.position - bone.bone.position;\n                    break;\n                }\n            }\n\n            return dir.normalized;\n        }\n\n        public static Quaternion AvatarComputeOrientation(BoneWrapper[] bones)\n        {\n            Transform leftUpLeg = bones[(int)HumanBodyBones.LeftUpperLeg].bone;\n            Transform rightUpLeg = bones[(int)HumanBodyBones.RightUpperLeg].bone;\n            Transform leftArm = bones[(int)HumanBodyBones.LeftUpperArm].bone;\n            Transform rightArm = bones[(int)HumanBodyBones.RightUpperArm].bone;\n            if (leftUpLeg != null && rightUpLeg != null && leftArm != null && rightArm != null)\n                return AvatarComputeOrientation(leftUpLeg.position, rightUpLeg.position, leftArm.position, rightArm.position);\n            else\n                return Quaternion.identity;\n        }\n\n        public static Quaternion AvatarComputeOrientation(Vector3 leftUpLeg, Vector3 rightUpLeg, Vector3 leftArm, Vector3 rightArm)\n        {\n            Vector3 legsRightDir = Vector3.Normalize(rightUpLeg - leftUpLeg);\n            Vector3 armsRightDir = Vector3.Normalize(rightArm - leftArm);\n            Vector3 torsoRightDir = Vector3.Normalize(legsRightDir + armsRightDir);\n\n            // Find out if torso right dir seems sensible or completely arbitrary.\n            // It's sensible if it's aligned along some axis.\n            bool sensibleOrientation =\n                Mathf.Abs(torsoRightDir.x * torsoRightDir.y) < 0.05f &&\n                Mathf.Abs(torsoRightDir.y * torsoRightDir.z) < 0.05f &&\n                Mathf.Abs(torsoRightDir.z * torsoRightDir.x) < 0.05f;\n\n            Vector3 legsAvgPos = (leftUpLeg + rightUpLeg) * 0.5f;\n            Vector3 armsAvgPos = (leftArm + rightArm) * 0.5f;\n            Vector3 torsoUpDir = Vector3.Normalize(armsAvgPos - legsAvgPos);\n\n            // If the orientation is sensible, assume character up vector is aligned along x, y, or z axis, so fix it to closest axis\n            if (sensibleOrientation)\n            {\n                int axisIndex = 0;\n                for (int i = 1; i < 3; i++)\n                    if (Mathf.Abs(torsoUpDir[i]) > Mathf.Abs(torsoUpDir[axisIndex]))\n                        axisIndex = i;\n                float sign = Mathf.Sign(torsoUpDir[axisIndex]);\n                torsoUpDir = Vector3.zero;\n                torsoUpDir[axisIndex] = sign;\n            }\n\n            Vector3 torsoForwardDir = Vector3.Cross(torsoRightDir, torsoUpDir);\n\n            if (torsoForwardDir == Vector3.zero || torsoUpDir == Vector3.zero)\n                return Quaternion.identity;\n\n            return Quaternion.LookRotation(torsoForwardDir, torsoUpDir);\n        }\n\n        private static float GetCharacterPositionError(BoneWrapper[] bones)\n        {\n            float error;\n            GetCharacterPositionAdjustVector(bones, out error);\n            return error;\n        }\n\n        internal static void MakeCharacterPositionValid(BoneWrapper[] bones)\n        {\n            float error;\n            Vector3 adjustVector = GetCharacterPositionAdjustVector(bones, out error);\n            if (adjustVector != Vector3.zero)\n                bones[(int)HumanBodyBones.Hips].bone.position += adjustVector;\n        }\n\n        private static Vector3 GetCharacterPositionAdjustVector(BoneWrapper[] bones, out float error)\n        {\n            error = 0;\n\n            // Get hip bones\n            Transform leftUpLeg = bones[(int)HumanBodyBones.LeftUpperLeg].bone;\n            Transform rightUpLeg = bones[(int)HumanBodyBones.RightUpperLeg].bone;\n            if (leftUpLeg == null || rightUpLeg == null)\n                return Vector3.zero;\n            Vector3 avgHipPos = (leftUpLeg.position + rightUpLeg.position) * 0.5f;\n\n            // Get foot bones\n            // Prefer toe bones but use foot bones if toes are not mapped\n            bool usingToes = true;\n            Transform leftFoot = bones[(int)HumanBodyBones.LeftToes].bone;\n            Transform rightFoot = bones[(int)HumanBodyBones.RightToes].bone;\n            if (leftFoot == null || rightFoot == null)\n            {\n                usingToes = false;\n                leftFoot = bones[(int)HumanBodyBones.LeftFoot].bone;\n                rightFoot = bones[(int)HumanBodyBones.RightFoot].bone;\n            }\n            if (leftFoot == null || rightFoot == null)\n                return Vector3.zero;\n            Vector3 avgFootPos = (leftFoot.position + rightFoot.position) * 0.5f;\n\n            // Get approximate length of legs\n            float hipsHeight = avgHipPos.y - avgFootPos.y;\n            if (hipsHeight <= 0)\n                return Vector3.zero;\n\n            Vector3 adjustVector = Vector3.zero;\n\n            // We can force the feet to be at an approximate good height.\n            // But the feet might be at a perfect height from the start if the bind pose is good.\n            // So only do it if the feet look like they're not at a good position from the beginning.\n            // Check if feet are already at height that looks about right.\n            if (avgFootPos.y < 0 || avgFootPos.y > hipsHeight * (usingToes ? 0.1f : 0.3f))\n            {\n                // Current height is not good, so adjust it using best guess based on human anatomy.\n                float estimatedFootBottomHeight = avgHipPos.y - hipsHeight * (usingToes ? 1.03f : 1.13f);\n                adjustVector.y = -estimatedFootBottomHeight;\n            }\n\n            // Move the avg hip pos to the center on the left-right axis if it's not already there.\n            if (Mathf.Abs(avgHipPos.x) > 0.01f * hipsHeight)\n                adjustVector.x = -avgHipPos.x;\n\n            // Move the avg hip pos to the center on the front-back axis if it's not already approximately there.\n            if (Mathf.Abs(avgHipPos.z) > 0.2f * hipsHeight)\n                adjustVector.z = -avgHipPos.z;\n\n            error = adjustVector.magnitude * 100 / hipsHeight;\n            return adjustVector;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Avatar/AvatarSkeletonDrawer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\nusing System.Linq;\n\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class AvatarSkeletonDrawer\n    {\n        private static bool sPoseError;\n\n        private static Color kSkeletonColor = new Color(103.0f / 255.0f, 103.0f / 255.0f, 103.0f / 255.0f, 0.5f);\n        private static Color kDummyColor = new Color(60.0f / 255.0f, 60.0f / 255.0f, 60.0f / 255.0f, 0.5f);\n        private static Color kHumanColor = new Color(0, 210.0f / 255.0f, 74.0f / 255.0f, 0.5f);\n        private static Color kErrorColor = new Color(1, 0, 0, 0.5f);\n        private static Color kErrorMessageColor = new Color(1, 0, 0, 0.75f);\n        private static Color kSelectedColor = new Color(128.0f / 255.0f, 192.0f / 255.0f, 255.0f / 255.0f, 0.30f);\n\n        public static void DrawSkeleton(Transform reference, Dictionary<Transform, bool> actualBones, Handles.BoneRenderer boneRenderer)\n        {\n            DrawSkeleton(reference, actualBones, null, boneRenderer);\n        }\n\n        public static void DrawSkeleton(Transform reference, Dictionary<Transform, bool> actualBones, AvatarSetupTool.BoneWrapper[] bones, Handles.BoneRenderer boneRenderer)\n        {\n            // it can happen when the avatar tool is in edit mode and the user exit the tool in an unsual way\n            //  new scene\n            //  delete GO\n            //  press play\n            if (reference == null || actualBones == null)\n                return;\n\n            sPoseError = false;\n\n            Bounds meshBounds = new Bounds();\n            Renderer[] renderers = reference.root.GetComponentsInChildren<Renderer>();\n            if (renderers != null)\n            {\n                foreach (Renderer renderer in renderers)\n                {\n                    meshBounds.Encapsulate(renderer.bounds.min);\n                    meshBounds.Encapsulate(renderer.bounds.max);\n                }\n            }\n\n            Quaternion orientation = Quaternion.identity;\n            if (bones != null)\n                orientation = AvatarSetupTool.AvatarComputeOrientation(bones);\n\n            boneRenderer.ClearInstances();\n            DrawSkeletonSubTree(actualBones, bones, orientation, reference, meshBounds, boneRenderer);\n            boneRenderer.Render();\n\n            Camera camera = Camera.current;\n            if (sPoseError && camera != null)\n            {\n                GUIStyle style = new GUIStyle(GUI.skin.label);\n                style.normal.textColor = Color.red;\n                style.wordWrap = false;\n                style.alignment = TextAnchor.MiddleLeft;\n                style.fontSize = 20;\n\n                GUIContent content = EditorGUIUtility.TrTextContent(\"Character is not in T pose\");\n\n                Rect rect = GUILayoutUtility.GetRect(content, style);\n\n                rect.x = 30;\n                rect.y = 30; //camera.pixelHeight;\n\n                Handles.BeginGUI();\n                GUI.Label(rect, content, style);\n                Handles.EndGUI();\n            }\n        }\n\n        private static bool DrawSkeletonSubTree(Dictionary<Transform, bool> actualBones, AvatarSetupTool.BoneWrapper[] bones, Quaternion orientation, Transform tr, Bounds bounds, Handles.BoneRenderer boneRenderer)\n        {\n            // if this transform is not a valid bone\n            if (!actualBones.ContainsKey(tr))\n                return false;\n\n            int drawnChildren = 0;\n            foreach (Transform child in tr)\n                if (DrawSkeletonSubTree(actualBones, bones, orientation, child, bounds, boneRenderer))\n                    drawnChildren++;\n\n            if (!actualBones[tr] && drawnChildren <= 1)\n                return false;\n\n            int index = -1;\n            if (bones != null)\n            {\n                for (int i = 0; i < bones.Length; i++)\n                {\n                    if (bones[i].bone == tr)\n                    {\n                        index = i;\n                        break;\n                    }\n                }\n            }\n\n            // There is no need to check for a pose error if the avatar is not yet valid or tools is not the active one\n            bool poseError = AvatarSetupTool.GetBoneAlignmentError(bones, orientation, index) > 0;\n            sPoseError |= poseError;\n\n            if (poseError)\n            {\n                DrawPoseError(tr, bounds);\n                Handles.color = kErrorColor;\n            }\n            else if (index != -1)\n                Handles.color = kHumanColor;\n            else if (!actualBones[tr])\n                Handles.color = kDummyColor;\n            else\n                Handles.color = kSkeletonColor;\n\n            // Override color if bone is selected\n            if (Selection.activeObject == tr)\n                Handles.color = kSelectedColor;\n\n            Handles.DoBoneHandle(tr, actualBones, boneRenderer);\n\n            return true;\n        }\n\n        private static void DrawPoseError(Transform node, Bounds bounds)\n        {\n            Camera camera = Camera.current;\n            if (camera)\n            {\n                GUIStyle style = new GUIStyle(GUI.skin.label);\n                style.normal.textColor = Color.red;\n                style.wordWrap = false;\n                style.alignment = TextAnchor.MiddleLeft;\n\n                Vector3 start = node.position;\n                Vector3 end = node.position + Vector3.up * 0.20f;\n                if (node.position.x <= node.root.position.x)\n                    end.x = bounds.min.x;\n                else\n                    end.x = bounds.max.x;\n\n                GUIContent content = new GUIContent(node.name);\n                Rect rect = HandleUtility.WorldPointToSizedRect(end, content, style);\n                rect.x += 2;\n                if (node.position.x > node.root.position.x)\n                    rect.x -= rect.width;\n\n                Handles.BeginGUI();\n                rect.y -= style.CalcSize(content).y / 4;\n                GUI.Label(rect, content, style);\n                Handles.EndGUI();\n\n                Handles.color = kErrorMessageColor;\n                Handles.DrawLine(start, end);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AvatarMaskInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine.Profiling;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewUtility = UnityEditor.IMGUI.Controls.TreeViewUtility<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    internal class BodyMaskEditor\n    {\n        static class Styles\n        {\n            public static GUIContent UnityDude = EditorGUIUtility.IconContent(\"AvatarInspector/BodySIlhouette\");\n            public static GUIContent PickingTexture = EditorGUIUtility.IconContent(\"AvatarInspector/BodyPartPicker\");\n\n            public static GUIContent[] BodyPart =\n            {\n                EditorGUIUtility.IconContent(\"AvatarInspector/MaskEditor_Root\"),\n                EditorGUIUtility.IconContent(\"AvatarInspector/Torso\"),\n\n                EditorGUIUtility.IconContent(\"AvatarInspector/Head\"),\n\n                EditorGUIUtility.IconContent(\"AvatarInspector/LeftLeg\"),\n                EditorGUIUtility.IconContent(\"AvatarInspector/RightLeg\"),\n\n                EditorGUIUtility.IconContent(\"AvatarInspector/LeftArm\"),\n                EditorGUIUtility.IconContent(\"AvatarInspector/RightArm\"),\n\n                EditorGUIUtility.IconContent(\"AvatarInspector/LeftFingers\"),\n                EditorGUIUtility.IconContent(\"AvatarInspector/RightFingers\"),\n\n                EditorGUIUtility.IconContent(\"AvatarInspector/LeftFeetIk\"),\n                EditorGUIUtility.IconContent(\"AvatarInspector/RightFeetIk\"),\n\n                EditorGUIUtility.IconContent(\"AvatarInspector/LeftFingersIk\"),\n                EditorGUIUtility.IconContent(\"AvatarInspector/RightFingersIk\"),\n            };\n        }\n\n        protected static Color[] m_MaskBodyPartPicker =\n        {\n            new Color(255 / 255.0f,   144 / 255.0f,     0 / 255.0f), // root\n            new Color(0 / 255.0f, 174 / 255.0f, 240 / 255.0f), // body\n            new Color(171 / 255.0f, 160 / 255.0f,   0 / 255.0f), // head\n\n            new Color(0 / 255.0f, 255 / 255.0f,     255 / 255.0f), // ll\n            new Color(247 / 255.0f,   151 / 255.0f, 121 / 255.0f), // rl\n\n            new Color(0 / 255.0f, 255 / 255.0f, 0 / 255.0f), // la\n            new Color(86 / 255.0f, 116 / 255.0f, 185 / 255.0f), // ra\n\n            new Color(255 / 255.0f,   255 / 255.0f,     0 / 255.0f), // lh\n            new Color(130 / 255.0f,   202 / 255.0f, 156 / 255.0f), // rh\n\n            new Color(82 / 255.0f,    82 / 255.0f,      82 / 255.0f), // lfi\n            new Color(255 / 255.0f,   115 / 255.0f,     115 / 255.0f), // rfi\n            new Color(159 / 255.0f,   159 / 255.0f,     159 / 255.0f), // lhi\n            new Color(202 / 255.0f,   202 / 255.0f, 202 / 255.0f), // rhi\n\n            new Color(101 / 255.0f,   101 / 255.0f, 101 / 255.0f), // hi\n        };\n\n        static string sAvatarBodyMaskStr = \"AvatarMask\";\n        static int s_Hint = sAvatarBodyMaskStr.GetHashCode();\n\n        public static void Show(SerializedProperty bodyMask, int count)\n        {\n            if (Styles.UnityDude.image)\n            {\n                Rect rect = GUILayoutUtility.GetRect(Styles.UnityDude, GUIStyle.none, GUILayout.MaxWidth(Styles.UnityDude.image.width));\n                rect.x += (GUIView.current.position.width - rect.width) / 2;\n\n                Color oldColor = GUI.color;\n\n                GUI.color = bodyMask.GetArrayElementAtIndex(0).intValue == 1 ? Color.green : Color.red;\n\n                if (Styles.BodyPart[0].image)\n                    GUI.DrawTexture(rect, Styles.BodyPart[0].image);\n\n                GUI.color = new Color(0.2f, 0.2f, 0.2f, 1.0f);\n                GUI.DrawTexture(rect, Styles.UnityDude.image);\n\n                for (int i = 1; i < count; i++)\n                {\n                    GUI.color = bodyMask.GetArrayElementAtIndex(i).intValue == 1 ? Color.green : Color.red;\n                    if (Styles.BodyPart[i].image)\n                        GUI.DrawTexture(rect, Styles.BodyPart[i].image);\n                }\n                GUI.color = oldColor;\n\n                DoPicking(rect, bodyMask, count);\n            }\n        }\n\n        protected static void DoPicking(Rect rect, SerializedProperty bodyMask, int count)\n        {\n            if (Styles.PickingTexture.image)\n            {\n                int id = GUIUtility.GetControlID(s_Hint, FocusType.Passive, rect);\n\n                Event evt = Event.current;\n\n                switch (evt.GetTypeForControl(id))\n                {\n                    case EventType.MouseDown:\n                    {\n                        if (rect.Contains(evt.mousePosition))\n                        {\n                            evt.Use();\n\n                            // Texture coordinate start at 0,0 at bottom, left\n                            // Screen coordinate start at 0,0 at top, left\n                            // So we need to convert from screen coord to texture coord\n                            int top = (int)evt.mousePosition.x - (int)rect.x;\n                            int left = Styles.UnityDude.image.height - ((int)evt.mousePosition.y - (int)rect.y);\n\n                            Texture2D pickTexture = Styles.PickingTexture.image as Texture2D;\n                            Color color = pickTexture.GetPixel(top, left);\n\n                            bool anyBodyPartPick = false;\n                            for (int i = 0; i < count; i++)\n                            {\n                                if (m_MaskBodyPartPicker[i] == color)\n                                {\n                                    GUI.changed = true;\n                                    bodyMask.GetArrayElementAtIndex(i).intValue = bodyMask.GetArrayElementAtIndex(i).intValue == 1 ? 0 : 1;\n                                    anyBodyPartPick = true;\n                                }\n                            }\n\n                            if (!anyBodyPartPick)\n                            {\n                                bool atLeastOneSelected = false;\n\n                                for (int i = 0; i < count && !atLeastOneSelected; i++)\n                                {\n                                    atLeastOneSelected = bodyMask.GetArrayElementAtIndex(i).intValue == 1;\n                                }\n\n                                for (int i = 0; i < count; i++)\n                                {\n                                    bodyMask.GetArrayElementAtIndex(i).intValue = !atLeastOneSelected ? 1 : 0;\n                                }\n                                GUI.changed = true;\n                            }\n                        }\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    [CustomEditor(typeof(AvatarMask))]\n    internal class AvatarMaskInspector : Editor\n    {\n        private static class Styles\n        {\n            // Model Importer related options\n            public static GUIContent MaskDefinition = EditorGUIUtility.TrTextContent(\"Definition\", \"Choose between Create From This Model, Copy From Other Avatar. The first one creates a Mask for this file and the second one uses a Mask from another file to import animation.\");\n            public static GUIContent[] MaskDefinitionOpt =\n            {\n                EditorGUIUtility.TrTextContent(\"Create From This Model\", \"Create a Mask based on the model from this file. For Humanoid rig all the human transforms are always imported and converted to muscle curve, thus they cannot be unchecked.\"),\n                EditorGUIUtility.TrTextContent(\"Copy From Other Mask\", \"Copy a Mask from another file to import animation clip.\"),\n                EditorGUIUtility.TrTextContent(\"None \", \" Import Everything\")\n            };\n            public static GUIContent CopyFromOtherSource = EditorGUIUtility.TrTextContent(\"Source\", \"Select from which AvatarMask the animation should take the mask information\");\n            public static GUIContent CreateMask = EditorGUIUtility.TrTextContent(\"Create Mask\", \"Create a new mask from this model avatar.\");\n\n            // Avatar mask options\n            public static GUIContent SelectAvatarReference = EditorGUIUtility.TrTextContent(\"Use skeleton from\", \"The selected avatar is never linked here and only used to populate the list of transform.\");\n            public static GUIContent ImportAvatarReference = EditorGUIUtility.TrTextContent(\"Import skeleton\", \"Generates new transform data based on the selected avatar skeleton\");\n\n            // Avatar mask foldouts\n            public static GUIContent BodyMask = EditorGUIUtility.TrTextContent(\"Humanoid\", \"Define which body part are active. Also define which animation curves will be imported for an Animation Clip.\");\n            public static GUIContent TransformMask = EditorGUIUtility.TrTextContent(\"Transform\", \"Define which transform are active. Also define which animation curves will be imported for an Animation Clip.\");\n\n            // TreeView columns\n            public static GUIContent TransformName = EditorGUIUtility.TrTextContent(\"Node Name\");\n            public static GUIContent EnableName = EditorGUIUtility.TrTextContent(\"Use\", \"Maintain Alt/Option key to enable or disable all children\");\n        }\n\n        // Body mask data\n        private bool m_ShowBodyMask = true;\n        private bool m_BodyMaskFoldout = false;\n        private SerializedProperty m_BodyMask = null;\n\n        // Transform data\n        private SerializedProperty m_TransformMask = null;\n        private string[] m_TransformPaths = null;\n\n        [SerializeField] TreeViewState m_TreeViewState;\n        [SerializeField] MultiColumnHeaderState m_ViewHeaderState;\n        //The TreeView is not serializable, so it should be reconstructed from the tree data.\n        AvatarMaskTreeView m_SimpleTreeView;\n\n        // Importer specific data\n        private bool m_CanImport = true;\n        public bool canImport\n        {\n            get { return m_CanImport; }\n            set { m_CanImport = value; }\n        }\n\n        private SerializedProperty m_AnimationType = null;\n        private AnimationClipInfoProperties m_ClipInfo = null;\n        public AnimationClipInfoProperties clipInfo\n        {\n            get { return m_ClipInfo;  }\n            set\n            {\n                m_ClipInfo = value;\n                if (m_ClipInfo != null)\n                {\n                    m_ClipInfo.MaskFromClip(target as AvatarMask);\n                    SerializedObject so = m_ClipInfo.maskTypeProperty.serializedObject;\n                    m_AnimationType = so.FindProperty(\"m_AnimationType\");\n\n                    ModelImporter modelImporter = (ModelImporter)so.targetObject;\n                    m_TransformPaths = modelImporter.transformPaths;\n                }\n                else\n                {\n                    m_TransformPaths = null;\n                    m_AnimationType = null;\n                }\n\n                InitializeSerializedProperties();\n            }\n        }\n\n        private ModelImporterAnimationType animationType\n        {\n            get\n            {\n                if (m_AnimationType != null)\n                    return (ModelImporterAnimationType)m_AnimationType.intValue;\n                else\n                    return ModelImporterAnimationType.None;\n            }\n        }\n\n        private Avatar m_RefAvatar;\n        private ModelImporter m_RefImporter;\n        private bool m_TransformMaskFoldout = false;\n        private string[] m_HumanTransform = null;\n\n        private void OnEnable()\n        {\n            // The AvatarMaskInspector is instantiated in the ModelImporterClipEditor, which does not derive from the Editor class anymore.\n            // All editors are added to a list so that OnEnable() and other methods can be called on them at certain times.\n            // When going in game while having settings pending to be applied, at some point the target (ModelImporterClipEditor.m_Mask) becomes null,\n            // since the parent becomes updated before this class.\n            if (target == null)\n            {\n                return;\n            }\n\n            InitTreeView();\n            InitializeSerializedProperties();\n        }\n\n        public void UpdateTransformInfos()\n        {\n            m_SimpleTreeView.Reload();\n        }\n\n        public bool showBody\n        {\n            get { return m_ShowBodyMask; }\n            set { m_ShowBodyMask = value; }\n        }\n\n        public string[] humanTransforms\n        {\n            get\n            {\n                if (animationType == ModelImporterAnimationType.Human && clipInfo != null)\n                {\n                    if (m_HumanTransform == null)\n                    {\n                        SerializedObject so = clipInfo.maskTypeProperty.serializedObject;\n                        ModelImporter modelImporter = so.targetObject as ModelImporter;\n\n                        m_HumanTransform = AvatarMaskUtility.GetAvatarHumanTransform(so, modelImporter.transformPaths);\n                    }\n                }\n                else\n                    m_HumanTransform = null;\n                return m_HumanTransform;\n            }\n        }\n\n        private ClipAnimationMaskType IndexToMaskType(int index)\n        {\n            ClipAnimationMaskType ret;\n            switch (index)\n            {\n                case 2:\n                    ret = ClipAnimationMaskType.None;\n                    break;\n                default:\n                    ret = (ClipAnimationMaskType)index;\n                    break;\n            }\n            return ret;\n        }\n\n        private int MaskTypeToIndex(ClipAnimationMaskType maskType)\n        {\n            int ret;\n            switch (maskType)\n            {\n                case ClipAnimationMaskType.None:\n                    ret = 2;\n                    break;\n                default:\n                    ret = (int)maskType;\n                    break;\n            }\n            return ret;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            Profiler.BeginSample(\"AvatarMaskInspector.OnInspectorGUI()\");\n            if (clipInfo != null)\n                InspectorGUIWithClipInfo();\n            else\n                InspectorGUIWithNoClipInfo();\n            Profiler.EndSample();\n        }\n\n        void InspectorGUIWithNoClipInfo()\n        {\n            serializedObject.Update();\n\n            OnBodyInspectorGUI();\n            OnTransformInspectorGUI();\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        void InspectorGUIWithClipInfo()\n        {\n            using (var change = new EditorGUI.ChangeCheckScope())\n            {\n                int maskType = MaskTypeToIndex(clipInfo.maskType);\n                EditorGUI.showMixedValue = clipInfo.maskTypeProperty.hasMultipleDifferentValues;\n                maskType = EditorGUILayout.Popup(Styles.MaskDefinition, maskType, Styles.MaskDefinitionOpt);\n                EditorGUI.showMixedValue = false;\n                if (change.changed)\n                {\n                    clipInfo.maskType = IndexToMaskType(maskType);\n                    UpdateMask(clipInfo.maskType);\n                }\n            }\n\n            var showCopyFromOtherGUI = clipInfo.maskType == ClipAnimationMaskType.CopyFromOther;\n            if (showCopyFromOtherGUI)\n                CopyFromOtherGUI();\n\n            using (new EditorGUI.DisabledScope(showCopyFromOtherGUI))\n            {\n                using (var change = new EditorGUI.ChangeCheckScope())\n                {\n                    OnBodyInspectorGUI();\n                    OnTransformInspectorGUI();\n                    if (change.changed)\n                    {\n                        AvatarMask mask = target as AvatarMask;\n                        clipInfo.MaskFromClip(mask);\n                    }\n                }\n            }\n        }\n\n        void CopyFromOtherGUI()\n        {\n            EditorGUILayout.BeginHorizontal();\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(clipInfo.maskSourceProperty, Styles.CopyFromOtherSource);\n            AvatarMask maskSource = clipInfo.maskSourceProperty.objectReferenceValue as AvatarMask;\n            if (EditorGUI.EndChangeCheck() && maskSource != null)\n                UpdateMask(clipInfo.maskType);\n\n            EditorGUILayout.EndHorizontal();\n        }\n\n        public bool IsMaskEmpty()\n        {\n            return !m_SimpleTreeView.rootNode.hasChildren;\n        }\n\n        public bool IsMaskUpToDate()\n        {\n            if (clipInfo == null)\n                return false;\n\n            if (m_SimpleTreeView.rootNode.DeepCount != m_TransformPaths.Length)\n                return false;\n\n            if (m_TransformPaths.Length > 0)\n            {\n                return CheckNodesPaths(m_SimpleTreeView.rootNode);\n            }\n\n            return true;\n        }\n\n        bool CheckNodesPaths(SerializedNodeInfo parent)\n        {\n            if (parent.children != null)\n            {\n                foreach (var treeViewItem in parent.children)\n                {\n                    var node = (SerializedNodeInfo)treeViewItem;\n                    if (!CheckNodesPaths(node))\n                        return false;\n                }\n            }\n\n            if (parent.m_Path != null)\n            {\n                string path = parent.m_Path.stringValue;\n                return ArrayUtility.FindIndex(m_TransformPaths, s => s == path) != -1;\n            }\n\n            return true;\n        }\n\n        internal void UpdateMask(ClipAnimationMaskType maskType)\n        {\n            if (clipInfo == null)\n                return;\n\n            if (maskType == ClipAnimationMaskType.CreateFromThisModel)\n            {\n                SerializedObject so = clipInfo.maskTypeProperty.serializedObject;\n                ModelImporter modelImporter = so.targetObject as ModelImporter;\n\n                AvatarMaskUtility.UpdateTransformMask(m_TransformMask, modelImporter.transformPaths, humanTransforms);\n                UpdateTransformInfos();\n            }\n            else if (maskType == ClipAnimationMaskType.CopyFromOther)\n            {\n                AvatarMask maskSource = clipInfo.maskSourceProperty.objectReferenceValue as AvatarMask;\n                if (maskSource != null)\n                {\n                    AvatarMask maskDest = target as AvatarMask;\n                    maskDest.Copy(maskSource);\n\n                    // If this is a human clip make sure that all human transform path are set to true\n                    if (humanTransforms != null)\n                        AvatarMaskUtility.SetActiveHumanTransforms(maskDest, humanTransforms);\n\n                    clipInfo.MaskToClip(maskDest);\n                    UpdateTransformInfos();\n                }\n            }\n            else if (maskType == ClipAnimationMaskType.None)\n            {\n                var emptyMask = new AvatarMask();\n                ModelImporter.UpdateTransformMask(emptyMask, clipInfo.transformMaskProperty);\n            }\n\n            AvatarMask mask = target as AvatarMask;\n            clipInfo.MaskFromClip(mask);\n        }\n\n        public void OnBodyInspectorGUI()\n        {\n            if (m_ShowBodyMask)\n            {\n                // Don't make toggling foldout cause GUI.changed to be true (shouldn't cause undoable action etc.)\n                bool wasChanged = GUI.changed;\n                m_BodyMaskFoldout = EditorGUILayout.Foldout(m_BodyMaskFoldout, Styles.BodyMask, true);\n                GUI.changed = wasChanged;\n                if (m_BodyMaskFoldout)\n                    BodyMaskEditor.Show(m_BodyMask, (int)AvatarMaskBodyPart.LastBodyPart);\n            }\n        }\n\n        public void OnTransformInspectorGUI()\n        {\n            // Don't make toggling foldout cause GUI.changed to be true (shouldn't cause undoable action etc.)\n            bool wasChanged = GUI.changed;\n            m_TransformMaskFoldout = EditorGUILayout.Foldout(m_TransformMaskFoldout, Styles.TransformMask, true);\n            GUI.changed = wasChanged;\n            if (m_TransformMaskFoldout)\n            {\n                if (canImport)\n                    ImportAvatarReference();\n\n                if (m_SimpleTreeView.rootNode == null || m_TransformMask.arraySize != m_SimpleTreeView.rootNode.DeepCount)\n                    UpdateTransformInfos();\n\n                if (IsMaskEmpty())\n                {\n                    GUILayout.BeginVertical();\n                    GUILayout.BeginHorizontal(EditorStyles.helpBox);\n                    string message;\n                    if (animationType == ModelImporterAnimationType.Generic)\n                    {\n                        message = \"No transform mask defined, everything will be imported\";\n                    }\n                    else if (animationType == ModelImporterAnimationType.Human)\n                    {\n                        message = \"No transform mask defined, only human curves will be imported\";\n                    }\n                    else\n                    {\n                        message = \"No transform mask defined\";\n                    }\n\n                    GUILayout.Label(message,\n                        EditorStyles.wordWrappedMiniLabel);\n\n                    GUILayout.EndHorizontal();\n\n                    if (!canImport && clipInfo.maskType == ClipAnimationMaskType.CreateFromThisModel)\n                    {\n                        GUILayout.BeginHorizontal();\n                        GUILayout.FlexibleSpace();\n                        if (GUILayout.Button(Styles.CreateMask))\n                            UpdateMask(clipInfo.maskType);\n                        GUILayout.EndHorizontal();\n                    }\n                    GUILayout.EndVertical();\n                }\n                else\n                {\n                    m_SimpleTreeView.OnGUI(Rect.zero);\n                }\n            }\n        }\n\n        private void ImportAvatarReference()\n        {\n            EditorGUI.BeginChangeCheck();\n            m_RefAvatar = EditorGUILayout.ObjectField(Styles.SelectAvatarReference, m_RefAvatar, typeof(Avatar), target) as Avatar;\n            if (EditorGUI.EndChangeCheck())\n                m_RefImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(m_RefAvatar)) as ModelImporter;\n\n            using (new EditorGUI.DisabledScope(m_RefImporter == null))\n            {\n                if (GUILayout.Button(Styles.ImportAvatarReference))\n                    AvatarMaskUtility.UpdateTransformMask(m_TransformMask, m_RefImporter.transformPaths, null);\n            }\n        }\n\n        private void InitializeSerializedProperties()\n        {\n            if (clipInfo != null)\n            {\n                m_BodyMask = clipInfo.bodyMaskProperty;\n                m_TransformMask = clipInfo.transformMaskProperty;\n            }\n            else\n            {\n                m_BodyMask = serializedObject.FindProperty(\"m_Mask\");\n                m_TransformMask = serializedObject.FindProperty(\"m_Elements\");\n            }\n\n            UpdateTransformInfos();\n        }\n\n        private SerializedNodeInfo FillNodeInfos()\n        {\n            var rootNode = new SerializedNodeInfo() { depth = -1, displayName = \"\", id = 0, children = new List<TreeViewItem>(0) };\n            if (m_TransformMask == null || m_TransformMask.arraySize == 0)\n            {\n                return rootNode;\n            }\n\n            var nodesCount = m_TransformMask.arraySize;\n            var nodeInfos = new List<SerializedNodeInfo>(nodesCount);\n            SerializedProperty prop = m_TransformMask.GetArrayElementAtIndex(0);\n            prop.Next(false);\n            Stack<string> depth = new Stack<string>(nodesCount);\n            string currentPath = String.Empty;\n\n            for (int i = 1; i < nodesCount; i++)\n            {\n                var newNode = new SerializedNodeInfo();\n                newNode.id = i;\n                newNode.m_Path = prop.FindPropertyRelative(\"m_Path\");\n                newNode.m_Weight = prop.FindPropertyRelative(\"m_Weight\");\n\n                var newPath = newNode.m_Path.stringValue;\n                while (!string.IsNullOrEmpty(currentPath) && !newPath.StartsWith(currentPath + \"/\"))\n                {\n                    // we are in a new node, lets unstack until we reach the correct hierarchy\n                    var oldParent = depth.Pop();\n                    var index = currentPath.LastIndexOf(oldParent);\n                    if (index > 0)\n                        index--;\n                    currentPath = currentPath.Remove(index);\n                }\n                var nodeName = newPath;\n                if (!string.IsNullOrEmpty(currentPath))\n                    nodeName = nodeName.Remove(0, currentPath.Length + 1);\n\n                if (m_CanImport)\n                {\n                    // in avatar mask inspector UI,everything is enabled.\n                    newNode.m_State = SerializedNodeInfo.State.Enabled;\n                }\n                else if (humanTransforms != null)\n                {\n                    //  Enable only transforms that are not human. Human transforms in this case are handled by muscle curves and cannot be imported.\n                    if (ArrayUtility.FindIndex(humanTransforms, s => newPath == s) == -1)\n                    {\n                        if (m_TransformPaths != null && ArrayUtility.FindIndex(m_TransformPaths, s => newPath == s) == -1)\n                            newNode.m_State = SerializedNodeInfo.State.Invalid;\n                        else\n                            newNode.m_State = SerializedNodeInfo.State.Enabled;\n                    }\n                    else\n                    {\n                        newNode.m_State = SerializedNodeInfo.State.Disabled;\n                    }\n                }\n                else if (m_TransformPaths != null && ArrayUtility.FindIndex(m_TransformPaths, s => newPath == s) == -1)\n                {\n                    // mask does not map to an existing hierarchy node. It's invalid.\n                    newNode.m_State = SerializedNodeInfo.State.Invalid;\n                }\n                else\n                {\n                    newNode.m_State = SerializedNodeInfo.State.Enabled;\n                }\n\n                newNode.depth = depth.Count;\n                newNode.displayName = nodeName;\n                depth.Push(nodeName);\n                currentPath = newPath;\n                nodeInfos.Add(newNode);\n                prop.Next(false);\n            }\n\n            TreeViewUtility.SetChildParentReferences(nodeInfos.Cast<TreeViewItem>().ToList(), rootNode);\n            return rootNode;\n        }\n\n        private void InitTreeView()\n        {\n            if (m_TreeViewState == null)\n                m_TreeViewState = new TreeViewState();\n            var columns = new[]\n            {\n                new MultiColumnHeaderState.Column\n                {\n                    headerContent = Styles.EnableName,\n                    headerTextAlignment = TextAlignment.Center,\n                    canSort = false,\n                    width = 31f, minWidth = 31f, maxWidth = 31f,\n                    autoResize = true, allowToggleVisibility = false\n                },\n                new MultiColumnHeaderState.Column\n                {\n                    headerContent = Styles.TransformName,\n                    headerTextAlignment = TextAlignment.Left,\n                    canSort = false,\n                    autoResize = true, allowToggleVisibility = false,\n                }\n            };\n            var newHeader = new MultiColumnHeaderState(columns);\n            if (m_ViewHeaderState != null)\n            {\n                MultiColumnHeaderState.OverwriteSerializedFields(m_ViewHeaderState, newHeader);\n            }\n            m_ViewHeaderState = newHeader;\n            var multiColumnHeader = new MultiColumnHeader(m_ViewHeaderState);\n            multiColumnHeader.ResizeToFit();\n            m_SimpleTreeView = new AvatarMaskTreeView(m_TreeViewState, multiColumnHeader, FillNodeInfos);\n            if (m_SimpleTreeView.searchString == null)\n                m_SimpleTreeView.searchString = string.Empty;\n        }\n\n        private class SerializedNodeInfo : ToggleTreeViewItem\n        {\n            public enum State { Disabled, Enabled, Invalid }\n            public State m_State;\n\n            // SerializedProperties\n            public SerializedProperty m_Path;\n            public SerializedProperty m_Weight;\n\n            public override bool nodeState\n            {\n                get { return m_Weight.floatValue == 1f; }\n                set\n                {\n                    if (m_State != State.Disabled)\n                        m_Weight.floatValue = value ? 1f : 0f;\n                }\n            }\n\n            public int DeepCount\n            {\n                get\n                {\n                    var count = 1;\n                    if (hasChildren)\n                        foreach (var treeViewItem in children)\n                        {\n                            var child = (SerializedNodeInfo)treeViewItem;\n                            count += child.DeepCount;\n                        }\n                    return count;\n                }\n            }\n        }\n\n        private class AvatarMaskTreeView : ToggleTreeView<SerializedNodeInfo>\n        {\n            public AvatarMaskTreeView(TreeViewState state, MultiColumnHeader multiColumnHeader, Func<SerializedNodeInfo> rebuildRoot)\n                : base(state, multiColumnHeader, rebuildRoot) {}\n\n            protected override void EnabledGUI(Rect cellRect, SerializedNodeInfo node, ref RowGUIArgs args)\n            {\n                var serializedNode = node;\n                EditorGUI.BeginDisabled(serializedNode.m_State == SerializedNodeInfo.State.Disabled);\n                base.EnabledGUI(cellRect, node, ref args);\n                EditorGUI.EndDisabled();\n            }\n\n            protected override void NameGUI(Rect position, SerializedNodeInfo node, ref RowGUIArgs args)\n            {\n                var serializedNode = node;\n                var color = GUI.contentColor;\n                color = serializedNode.m_State == SerializedNodeInfo.State.Invalid ? new Color(1f, 0f, 0f, 0.66f) : color;\n                base.NameGUI(position, node, ref args);\n                GUI.contentColor = color;\n            }\n\n            protected override void ToggleAll()\n            {\n                bool value;\n                GetFirstActiveValue((SerializedNodeInfo)rootItem, out value);\n                PropagateValue((SerializedNodeInfo)rootItem, !value);\n            }\n\n            static bool GetFirstActiveValue(SerializedNodeInfo parent, out bool value)\n            {\n                if (parent.children != null)\n                {\n                    foreach (var treeViewItem in parent.children)\n                    {\n                        var child = (SerializedNodeInfo)treeViewItem;\n                        if (child.m_State != SerializedNodeInfo.State.Disabled)\n                        {\n                            value = child.nodeState;\n                            return true;\n                        }\n                        if (GetFirstActiveValue(child, out value))\n                            return true;\n                    }\n                }\n                value = false;\n                return false;\n            }\n\n            public SerializedNodeInfo rootNode => (SerializedNodeInfo)rootItem;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AvatarMaskUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing System.Linq;\n\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    internal class AvatarMaskUtility\n    {\n        private static string sHuman = \"m_HumanDescription.m_Human\";\n        private static string sBoneName = \"m_BoneName\";\n\n        static public string[] GetAvatarHumanTransform(SerializedObject so, string[] refTransformsPath)\n        {\n            SerializedProperty humanBoneArray = so.FindProperty(sHuman);\n            if (humanBoneArray == null || !humanBoneArray.isArray)\n                return null;\n\n            List<string> humanTransforms = new List<string>();\n            for (int i = 0; i < humanBoneArray.arraySize; i++)\n            {\n                SerializedProperty transformNameP = humanBoneArray.GetArrayElementAtIndex(i).FindPropertyRelative(sBoneName);\n                humanTransforms.Add(transformNameP.stringValue);\n            }\n\n            return TokeniseHumanTransformsPath(refTransformsPath, humanTransforms.ToArray());\n        }\n\n        static public string[] GetAvatarHumanAndActiveExtraTransforms(SerializedObject so, SerializedProperty transformMaskProperty, string[] refTransformsPath)\n        {\n            SerializedProperty humanBoneArray = so.FindProperty(sHuman);\n            if (humanBoneArray == null || !humanBoneArray.isArray)\n                return null;\n\n            List<string> humanTransforms = new List<string>();\n            for (int i = 0; i < humanBoneArray.arraySize; i++)\n            {\n                SerializedProperty transformNameP = humanBoneArray.GetArrayElementAtIndex(i).FindPropertyRelative(sBoneName);\n                humanTransforms.Add(transformNameP.stringValue);\n            }\n\n            List<string> values = new List<string>(TokeniseHumanTransformsPath(refTransformsPath, humanTransforms.ToArray()));\n\n            for (int i = 0; i < transformMaskProperty.arraySize; i++)\n            {\n                float weight = transformMaskProperty.GetArrayElementAtIndex(i).FindPropertyRelative(\"m_Weight\").floatValue;\n                string transformName = transformMaskProperty.GetArrayElementAtIndex(i).FindPropertyRelative(\"m_Path\").stringValue;\n\n                if (weight > 0.0f &&  !values.Contains(transformName))\n                {\n                    values.Add(transformName);\n                }\n            }\n\n            return values.ToArray();\n        }\n\n        static public string[] GetAvatarInactiveTransformMaskPaths(SerializedProperty transformMaskProperty)\n        {\n            if (transformMaskProperty == null || !transformMaskProperty.isArray)\n                return null;\n\n            List<string> transformPaths = new List<string>();\n            for (int i = 0; i < transformMaskProperty.arraySize; i++)\n            {\n                SerializedProperty weight = transformMaskProperty.GetArrayElementAtIndex(i).FindPropertyRelative(\"m_Weight\");\n                if (weight.floatValue < 0.5f)\n                {\n                    SerializedProperty transformNameP = transformMaskProperty.GetArrayElementAtIndex(i).FindPropertyRelative(\"m_Path\");\n                    transformPaths.Add(transformNameP.stringValue);\n                }\n            }\n\n            return transformPaths.ToArray();\n        }\n\n        static public void UpdateTransformMask(AvatarMask mask, string[] refTransformsPath, string[] humanTransforms)\n        {\n            mask.transformCount = refTransformsPath.Length;\n            for (int i = 0; i < refTransformsPath.Length; i++)\n            {\n                mask.SetTransformPath(i, refTransformsPath[i]);\n\n                bool isActiveTransform = humanTransforms == null\n                    ? true\n                    : ArrayUtility.FindIndex(humanTransforms, s => refTransformsPath[i] == s) != -1;\n                mask.SetTransformActive(i, isActiveTransform);\n            }\n        }\n\n        static public void UpdateTransformMask(SerializedProperty transformMask, string[] refTransformsPath, string[] currentPaths, bool areActivePaths = true)\n        {\n            // if areActivePaths=true, currentPaths is treated as the list of active transform paths\n            // else, currentPaths is treated as the list of inactive transform paths\n            AvatarMask refMask = new AvatarMask();\n\n            refMask.transformCount = refTransformsPath.Length;\n\n            for (int i = 0; i < refTransformsPath.Length; i++)\n            {\n                bool isActiveTransform;\n                if (currentPaths == null)\n                    isActiveTransform = true;\n                else if (areActivePaths)\n                    isActiveTransform = ArrayUtility.FindIndex(currentPaths, s => refTransformsPath[i] == s) != -1;\n                else\n                    isActiveTransform = ArrayUtility.FindIndex(currentPaths, s => refTransformsPath[i] == s) == -1;\n\n                refMask.SetTransformPath(i, refTransformsPath[i]);\n                refMask.SetTransformActive(i, isActiveTransform);\n            }\n            ModelImporter.UpdateTransformMask(refMask, transformMask);\n        }\n\n        static public void SetActiveHumanTransforms(AvatarMask mask, string[] humanTransforms)\n        {\n            for (int i = 0; i < mask.transformCount; i++)\n            {\n                string path = mask.GetTransformPath(i);\n                if (ArrayUtility.FindIndex(humanTransforms, s => path == s) != -1)\n                    mask.SetTransformActive(i, true);\n            }\n        }\n\n        static private string[] TokeniseHumanTransformsPath(string[] refTransformsPath, string[] humanTransforms)\n        {\n            if (humanTransforms == null)\n                return null;\n\n            // all list must always include the string \"\" which is the root game object\n            string[] tokeniseTransformsPath = new string[] {\"\"};\n\n            for (int i = 0; i < humanTransforms.Length; i++)\n            {\n                int index1 = ArrayUtility.FindIndex(refTransformsPath, s => humanTransforms[i] == FileUtil.GetLastPathNameComponent(s));\n                if (index1 != -1)\n                {\n                    int insertIndex = tokeniseTransformsPath.Length;\n\n                    string path = refTransformsPath[index1];\n                    while (path.Length > 0)\n                    {\n                        int index2 = ArrayUtility.FindIndex(tokeniseTransformsPath, s => path == s);\n                        if (index2 == -1)\n                            ArrayUtility.Insert(ref tokeniseTransformsPath, insertIndex, path);\n\n                        int lastIndex = path.LastIndexOf('/');\n                        path = path.Substring(0, lastIndex != -1 ? lastIndex : 0);\n                    }\n                }\n            }\n\n            return tokeniseTransformsPath;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/AvatarPreview.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Globalization;\nusing UnityEngine;\nusing UnityEngine.Assertions;\nusing UnityEngine.Rendering;\nusing UnityEngine.Animations;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class AvatarPreview\n    {\n        const string kDefaultAvatarPreviewOption = \"DefaultAvatarPreviewOption\";\n        const string kIkPref = \"AvatarpreviewShowIK\";\n        const string k2DPref = \"Avatarpreview2D\";\n        const string kReferencePref = \"AvatarpreviewShowReference\";\n        const string kSpeedPref = \"AvatarpreviewSpeed\";\n        const float kTimeControlRectHeight = 20;\n\n        public delegate void OnAvatarChange();\n        OnAvatarChange m_OnAvatarChangeFunc = null;\n\n        private class ObjectSelectorOperation : ObjectSelectorReceiver\n        {\n            public static void Start(AvatarPreview owner)\n            {\n                var operation = ScriptableObject.CreateInstance<ObjectSelectorOperation>();\n                operation.m_Owner = owner;\n                operation.m_Selector = ObjectSelector.get;\n                operation.Execute();\n            }\n\n            AvatarPreview m_Owner;\n            ObjectSelector m_Selector;\n\n            bool IsValid()\n            {\n                return m_Owner != null;\n            }\n\n            private void Execute()\n            {\n                if (m_Selector)\n                {\n                    m_Selector.Show(null, typeof(GameObject), null, false);\n                    m_Selector.objectSelectorReceiver = this;\n                }\n            }\n\n            public override void OnSelectionChanged(Object selection)\n            {\n                if (IsValid())\n                {\n                    m_Owner.SetPreview(ObjectSelector.GetCurrentObject() as GameObject);\n                    InspectorWindow.RepaintAllInspectors();\n                }\n            }\n\n            public override void OnSelectionClosed(Object selection)\n            {\n                if (IsValid())\n                {\n                    m_Owner.SetPreview(ObjectSelector.GetCurrentObject() as GameObject);\n                }\n\n                m_Selector.objectSelectorReceiver = null;\n            }\n        }\n\n        public OnAvatarChange OnAvatarChangeFunc\n        {\n            set { m_OnAvatarChangeFunc = value; }\n        }\n\n        public bool IKOnFeet\n        {\n            get { return m_IKOnFeet; }\n        }\n\n        public bool ShowIKOnFeetButton\n        {\n            get { return m_ShowIKOnFeetButton; }\n            set { m_ShowIKOnFeetButton = value; }\n        }\n\n        public bool is2D\n        {\n            get { return m_2D; }\n            set\n            {\n                m_2D = value;\n                if (m_2D)\n                {\n                    m_PreviewDir = new Vector2();\n                }\n            }\n        }\n\n        public Animator Animator\n        {\n            get { return m_PreviewInstance != null ? m_PreviewInstance.GetComponent(typeof(Animator)) as Animator : null; }\n        }\n\n        public GameObject PreviewObject\n        {\n            get { return m_PreviewInstance; }\n        }\n\n        public ModelImporterAnimationType animationClipType\n        {\n            get { return GetAnimationType(m_SourcePreviewMotion); }\n        }\n\n        public Vector3 bodyPosition\n        {\n            get\n            {\n                if (Animator && Animator.isHuman)\n                    return Animator.bodyPositionInternal;\n\n                if (m_PreviewInstance != null)\n                    return GameObjectInspector.GetRenderableCenterRecurse(m_PreviewInstance, 1, 8);\n\n                return Vector3.zero;\n            }\n        }\n\n        public Vector3 rootPosition\n        {\n            get { return m_PreviewInstance ? m_PreviewInstance.transform.position : Vector3.zero; }\n        }\n\n\n        public TimeControl timeControl;\n\n        // 60 is the default framerate for animations created inside Unity so as good a default as any.\n        public int fps = 60;\n\n        private Material     m_FloorMaterial;\n        private Material     m_FloorMaterialSmall;\n        private Material     m_ShadowMaskMaterial;\n        private Material     m_ShadowPlaneMaterial;\n\n        PreviewRenderUtility        m_PreviewUtility;\n        GameObject                  m_PreviewInstance;\n        GameObject                  m_ReferenceInstance;\n        GameObject                  m_DirectionInstance;\n        GameObject                  m_PivotInstance;\n        GameObject                  m_RootInstance;\n        IAnimationPreviewable[]     m_Previewables;\n        float                       m_BoundingVolumeScale;\n        Motion                      m_SourcePreviewMotion;\n        Animator                    m_SourceScenePreviewAnimator;\n\n        const string                s_PreviewStr = \"Preview\";\n        int                         m_PreviewHint = s_PreviewStr.GetHashCode();\n\n        const string                s_PreviewSceneStr = \"PreviewSene\";\n        int                         m_PreviewSceneHint = s_PreviewSceneStr.GetHashCode();\n\n        Texture2D                   m_FloorTexture;\n        Mesh                        m_FloorPlane;\n\n        bool                        m_ShowReference = false;\n\n        bool                        m_IKOnFeet = false;\n        bool                        m_ShowIKOnFeetButton = true;\n\n        bool                        m_2D;\n\n        bool                        m_IsValid;\n        bool                        m_IsCurrentPreviewInstanceFallback = false;\n\n        private const float kFloorFadeDuration = 0.2f;\n        private const float kFloorScale = 5;\n        private const float kFloorScaleSmall = 0.2f;\n        private const float kFloorTextureScale = 4;\n        private const float kFloorAlpha = 0.5f;\n        private const float kFloorShadowAlpha = 0.3f;\n        private const float kDefaultIntensity = 1.4f;\n\n        private const int kDefaultLayer = 0; // Must match kDefaultLayer in TagTypes.h\n\n        private float m_PrevFloorHeight = 0;\n        private float m_NextFloorHeight = 0;\n\n        private Vector2 m_PreviewDir = new Vector2(120, -20);\n        private float m_AvatarScale = 1.0f;\n        private float m_ZoomFactor = 1.0f;\n        private Vector3 m_PivotPositionOffset = Vector3.zero;\n\n        private class Styles\n        {\n            public GUIContent pivot = EditorGUIUtility.TrIconContent(\"AvatarPivot\", \"Displays avatar's pivot and mass center\");\n            public GUIContent ik = EditorGUIUtility.TrTextContent(\"IK\", \"Toggles feet IK preview\");\n            public GUIContent is2D = EditorGUIUtility.TrIconContent(\"SceneView2D\", \"Toggles 2D preview mode\");\n            public GUIContent avatarIcon = EditorGUIUtility.TrIconContent(\"AvatarSelector\", \"Changes the model to use for previewing.\");\n\n            public GUIStyle preButton = \"toolbarbutton\";\n            public GUIStyle preSlider = \"preSlider\";\n            public GUIStyle preSliderThumb = \"preSliderThumb\";\n        }\n        private static Styles s_Styles;\n\n        void SetPreviewCharacterEnabled(bool enabled, bool showReference)\n        {\n            if (m_PreviewInstance != null)\n                PreviewRenderUtility.SetEnabledRecursive(m_PreviewInstance, enabled);\n            PreviewRenderUtility.SetEnabledRecursive(m_ReferenceInstance, showReference && enabled);\n            PreviewRenderUtility.SetEnabledRecursive(m_DirectionInstance, showReference && enabled);\n            PreviewRenderUtility.SetEnabledRecursive(m_PivotInstance, showReference && enabled);\n            PreviewRenderUtility.SetEnabledRecursive(m_RootInstance, showReference && enabled);\n        }\n\n        static AnimationClip GetFirstAnimationClipFromMotion(Motion motion)\n        {\n            AnimationClip clip = motion as AnimationClip;\n            if (clip)\n                return clip;\n\n            Animations.BlendTree blendTree = motion as Animations.BlendTree;\n            if (blendTree)\n            {\n                AnimationClip[] clips = blendTree.GetAnimationClipsFlattened();\n                if (clips.Length > 0)\n                    return clips[0];\n            }\n\n            return null;\n        }\n\n        static public ModelImporterAnimationType GetAnimationType(GameObject go)\n        {\n            Animator animator = go.GetComponent<Animator>();\n            if (animator)\n            {\n                Avatar avatar = animator.avatar;\n                if (avatar && avatar.isHuman)\n                    return ModelImporterAnimationType.Human;\n                else\n                    return ModelImporterAnimationType.Generic;\n            }\n            else if (go.GetComponent<Animation>() != null)\n            {\n                return ModelImporterAnimationType.Legacy;\n            }\n            else\n                return ModelImporterAnimationType.None;\n        }\n\n        static public ModelImporterAnimationType GetAnimationType(Motion motion)\n        {\n            AnimationClip clip = GetFirstAnimationClipFromMotion(motion);\n            if (clip)\n            {\n                if (clip.legacy)\n                    return ModelImporterAnimationType.Legacy;\n                else if (clip.humanMotion)\n                    return ModelImporterAnimationType.Human;\n                else\n                    return ModelImporterAnimationType.Generic;\n            }\n            else\n                return ModelImporterAnimationType.None;\n        }\n\n        static public bool IsValidPreviewGameObject(GameObject target, ModelImporterAnimationType requiredClipType)\n        {\n            if (target != null && !target.activeSelf)\n                Debug.LogWarning(\"Can't preview inactive object, using fallback object\");\n\n            return target != null && target.activeSelf && GameObjectInspector.HasRenderableParts(target) &&\n                !(requiredClipType != ModelImporterAnimationType.None && GetAnimationType(target) != requiredClipType);\n        }\n\n        static public GameObject FindBestFittingRenderableGameObjectFromModelAsset(Object asset, ModelImporterAnimationType animationType)\n        {\n            if (asset == null)\n                return null;\n\n            ModelImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(asset)) as ModelImporter;\n            if (importer == null)\n                return null;\n\n            string assetPath = importer.CalculateBestFittingPreviewGameObject();\n            GameObject tempGO = AssetDatabase.LoadMainAssetAtPath(assetPath) as GameObject;\n\n            // We should also check for isHumanClip matching the animationclip requiremenets...\n            if (IsValidPreviewGameObject(tempGO, ModelImporterAnimationType.None))\n                return tempGO;\n            else\n                return null;\n        }\n\n        static GameObject CalculatePreviewGameObject(Animator selectedAnimator, Motion motion, ModelImporterAnimationType animationType)\n        {\n            AnimationClip sourceClip = GetFirstAnimationClipFromMotion(motion);\n\n            // Use selected preview\n            GameObject selected = AvatarPreviewSelection.GetPreview(animationType);\n            if (IsValidPreviewGameObject(selected, ModelImporterAnimationType.None))\n                return selected;\n\n            if (selectedAnimator != null && IsValidPreviewGameObject(selectedAnimator.gameObject, animationType))\n                return selectedAnimator.gameObject;\n\n            // Find the best fitting preview game object for the asset we are viewing (Handles @ convention, will pick base path for you)\n            selected = FindBestFittingRenderableGameObjectFromModelAsset(sourceClip, animationType);\n            if (selected != null)\n                return selected;\n\n            if (animationType == ModelImporterAnimationType.Human)\n                return GetHumanoidFallback();\n            else if (animationType == ModelImporterAnimationType.Generic)\n                return GetGenericAnimationFallback();\n\n            return null;\n        }\n\n        static GameObject GetGenericAnimationFallback()\n        {\n            return (GameObject)EditorGUIUtility.Load(\"Avatar/DefaultGeneric.fbx\");\n        }\n\n        static GameObject GetHumanoidFallback()\n        {\n            return (GameObject)EditorGUIUtility.Load(\"Avatar/DefaultAvatar.fbx\");\n        }\n\n        public void ResetPreviewInstance()\n        {\n            Object.DestroyImmediate(m_PreviewInstance);\n            GameObject go = CalculatePreviewGameObject(m_SourceScenePreviewAnimator, m_SourcePreviewMotion, animationClipType);\n            SetupBounds(go);\n        }\n\n        void SetupBounds(GameObject go)\n        {\n            bool isGenericAnimationFallback = go == GetGenericAnimationFallback();\n            m_IsCurrentPreviewInstanceFallback = isGenericAnimationFallback || go == GetHumanoidFallback();\n            m_IsValid = go != null && !isGenericAnimationFallback;\n\n            if (go != null)\n            {\n                m_PreviewInstance = EditorUtility.InstantiateForAnimatorPreview(go);\n                previewUtility.AddSingleGO(m_PreviewInstance);\n\n                m_Previewables = m_PreviewInstance.GetComponentsInChildren<IAnimationPreviewable>();\n                var bounds = GameObjectInspector.GetRenderableBounds(m_PreviewInstance);\n\n                m_BoundingVolumeScale = Mathf.Max(bounds.size.x, Mathf.Max(bounds.size.y, bounds.size.z));\n\n\n                if (Animator && Animator.isHuman)\n                    m_AvatarScale = m_ZoomFactor = Animator.humanScale;\n                else\n                    m_AvatarScale = m_ZoomFactor = m_BoundingVolumeScale / 2;\n            }\n        }\n\n        void InitInstance(Animator scenePreviewObject, Motion motion)\n        {\n            m_SourcePreviewMotion = motion;\n            m_SourceScenePreviewAnimator = scenePreviewObject;\n\n            if (m_PreviewInstance == null)\n            {\n                GameObject go = CalculatePreviewGameObject(scenePreviewObject, motion, animationClipType);\n                SetupBounds(go);\n            }\n\n            if (timeControl == null)\n            {\n                timeControl = new TimeControl();\n            }\n\n            if (m_ReferenceInstance == null)\n            {\n                GameObject referenceGO = (GameObject)EditorGUIUtility.Load(\"Avatar/dial_flat.prefab\");\n                m_ReferenceInstance = (GameObject)Object.Instantiate(referenceGO, Vector3.zero, Quaternion.identity);\n                EditorUtility.InitInstantiatedPreviewRecursive(m_ReferenceInstance);\n                previewUtility.AddSingleGO(m_ReferenceInstance);\n            }\n\n            if (m_DirectionInstance == null)\n            {\n                GameObject directionGO = (GameObject)EditorGUIUtility.Load(\"Avatar/arrow.fbx\");\n                m_DirectionInstance = (GameObject)Object.Instantiate(directionGO, Vector3.zero, Quaternion.identity);\n                EditorUtility.InitInstantiatedPreviewRecursive(m_DirectionInstance);\n                previewUtility.AddSingleGO(m_DirectionInstance);\n            }\n\n            if (m_PivotInstance == null)\n            {\n                GameObject pivotGO = (GameObject)EditorGUIUtility.Load(\"Avatar/root.fbx\");\n                m_PivotInstance = (GameObject)Object.Instantiate(pivotGO, Vector3.zero, Quaternion.identity);\n                EditorUtility.InitInstantiatedPreviewRecursive(m_PivotInstance);\n                previewUtility.AddSingleGO(m_PivotInstance);\n            }\n\n            if (m_RootInstance == null)\n            {\n                GameObject rootGO = (GameObject)EditorGUIUtility.Load(\"Avatar/root.fbx\");\n                m_RootInstance = (GameObject)Object.Instantiate(rootGO, Vector3.zero, Quaternion.identity);\n                EditorUtility.InitInstantiatedPreviewRecursive(m_RootInstance);\n                previewUtility.AddSingleGO(m_RootInstance);\n            }\n\n            // Load preview settings from prefs\n            m_IKOnFeet = EditorPrefs.GetBool(kIkPref, false);\n            m_ShowReference = EditorPrefs.GetBool(kReferencePref, true);\n            is2D = EditorPrefs.GetBool(k2DPref, EditorSettings.defaultBehaviorMode == EditorBehaviorMode.Mode2D);\n            timeControl.playbackSpeed = EditorPrefs.GetFloat(kSpeedPref, 1f);\n\n            SetPreviewCharacterEnabled(false, false);\n\n            //Fix for FogBugz case : 1364821 Inspector Model Preview orientation is reversed when Bake Axis Conversion is enabled\n            var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(motion)) as ModelImporter;\n            if (importer && importer.bakeAxisConversion)\n            {\n                m_PreviewDir += new Vector2(180,0);\n            }\n\n            m_PivotPositionOffset = Vector3.zero;\n        }\n\n        private PreviewRenderUtility previewUtility\n        {\n            get\n            {\n                if (m_PreviewUtility == null)\n                {\n                    m_PreviewUtility = new PreviewRenderUtility();\n                    m_PreviewUtility.camera.fieldOfView = 30.0f;\n                    m_PreviewUtility.camera.allowHDR = false;\n                    m_PreviewUtility.camera.allowMSAA = false;\n                    m_PreviewUtility.ambientColor = new Color(.1f, .1f, .1f, 0);\n                    m_PreviewUtility.lights[0].intensity = kDefaultIntensity;\n                    m_PreviewUtility.lights[0].transform.rotation = Quaternion.Euler(40f, 40f, 0);\n                    m_PreviewUtility.lights[1].intensity = kDefaultIntensity;\n                }\n                return m_PreviewUtility;\n            }\n        }\n\n        private void Init()\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            if (m_FloorPlane == null)\n            {\n                m_FloorPlane = Resources.GetBuiltinResource(typeof(Mesh), \"New-Plane.fbx\") as Mesh;\n            }\n\n            if (m_FloorTexture == null)\n            {\n                m_FloorTexture = (Texture2D)EditorGUIUtility.Load(\"Avatar/Textures/AvatarFloor.png\");\n            }\n\n            if (m_FloorMaterial == null)\n            {\n                Shader shader = EditorGUIUtility.LoadRequired(\"Previews/PreviewPlaneWithShadow.shader\") as Shader;\n                m_FloorMaterial = new Material(shader);\n                m_FloorMaterial.mainTexture = m_FloorTexture;\n                m_FloorMaterial.mainTextureScale = Vector2.one * kFloorScale * kFloorTextureScale;\n                m_FloorMaterial.SetVector(\"_Alphas\", new Vector4(kFloorAlpha, kFloorShadowAlpha, 0, 0));\n                m_FloorMaterial.hideFlags = HideFlags.HideAndDontSave;\n\n                m_FloorMaterialSmall = new Material(m_FloorMaterial);\n                m_FloorMaterialSmall.mainTextureScale = Vector2.one * kFloorScaleSmall * kFloorTextureScale;\n                m_FloorMaterialSmall.hideFlags = HideFlags.HideAndDontSave;\n            }\n\n            if (m_ShadowMaskMaterial == null)\n            {\n                Shader shader = EditorGUIUtility.LoadRequired(\"Previews/PreviewShadowMask.shader\") as Shader;\n                m_ShadowMaskMaterial = new Material(shader);\n                m_ShadowMaskMaterial.hideFlags = HideFlags.HideAndDontSave;\n            }\n\n            if (m_ShadowPlaneMaterial == null)\n            {\n                Shader shader = EditorGUIUtility.LoadRequired(\"Previews/PreviewShadowPlaneClip.shader\") as Shader;\n                m_ShadowPlaneMaterial = new Material(shader);\n                m_ShadowPlaneMaterial.hideFlags = HideFlags.HideAndDontSave;\n            }\n        }\n\n        public void OnDisable()\n        {\n            if (m_PreviewUtility != null)\n            {\n                m_PreviewUtility.Cleanup();\n                m_PreviewUtility = null;\n            }\n\n            if (timeControl != null)\n                timeControl.OnDisable();\n        }\n\n        public void DoSelectionChange()\n        {\n            m_OnAvatarChangeFunc();\n        }\n\n        public AvatarPreview(Animator previewObjectInScene, Motion objectOnSameAsset)\n        {\n            InitInstance(previewObjectInScene, objectOnSameAsset);\n        }\n\n        float PreviewSlider(Rect rect, float val, float snapThreshold)\n        {\n            val = GUI.HorizontalSlider(rect, val, 0.1f, 2.0f, s_Styles.preSlider, s_Styles.preSliderThumb);//, GUILayout.MaxWidth(64));\n            if (val > 0.25f - snapThreshold && val < 0.25f + snapThreshold)\n                val = 0.25f;\n            else if (val > 0.5f - snapThreshold && val < 0.5f + snapThreshold)\n                val = 0.5f;\n            else if (val > 0.75f - snapThreshold && val < 0.75f + snapThreshold)\n                val = 0.75f;\n            else if (val > 1.0f - snapThreshold && val < 1.0f + snapThreshold)\n                val = 1.0f;\n            else if (val > 1.25f - snapThreshold && val < 1.25f + snapThreshold)\n                val = 1.25f;\n            else if (val > 1.5f - snapThreshold && val < 1.5f + snapThreshold)\n                val = 1.5f;\n            else if (val > 1.75f - snapThreshold && val < 1.75f + snapThreshold)\n                val = 1.75f;\n\n            return val;\n        }\n\n        public void DoPreviewSettings()\n        {\n            Init();\n\n            if (m_ShowIKOnFeetButton)\n            {\n                EditorGUI.BeginChangeCheck();\n                m_IKOnFeet = GUILayout.Toggle(m_IKOnFeet, s_Styles.ik, s_Styles.preButton);\n                if (EditorGUI.EndChangeCheck())\n                    EditorPrefs.SetBool(kIkPref, m_IKOnFeet);\n            }\n\n            EditorGUI.BeginChangeCheck();\n            GUILayout.Toggle(is2D, s_Styles.is2D, s_Styles.preButton);\n            if (EditorGUI.EndChangeCheck())\n            {\n                is2D = !is2D;\n                EditorPrefs.SetBool(k2DPref, is2D);\n            }\n\n            EditorGUI.BeginChangeCheck();\n            m_ShowReference = GUILayout.Toggle(m_ShowReference, s_Styles.pivot, s_Styles.preButton);\n            if (EditorGUI.EndChangeCheck())\n                EditorPrefs.SetBool(kReferencePref, m_ShowReference);\n\n            if (EditorGUILayout.DropdownButton(s_Styles.avatarIcon, FocusType.Passive, EditorStyles.toolbarDropDownRight))\n            {\n                GenericMenu menu = new GenericMenu();\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Auto\"), false, SetPreviewAvatarOption, PreviewPopupOptions.Auto);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Unity Model\"), false, SetPreviewAvatarOption, PreviewPopupOptions.DefaultModel);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Other...\"), false, SetPreviewAvatarOption, PreviewPopupOptions.Other);\n                menu.ShowAsContext();\n            }\n        }\n\n        private RenderTexture RenderPreviewShadowmap(Light light, float scale, Vector3 center, Vector3 floorPos, out Matrix4x4 outShadowMatrix)\n        {\n            Assert.IsTrue(Event.current.type == EventType.Repaint);\n\n            // Set ortho camera and position it\n            var cam = previewUtility.camera;\n            cam.orthographic = true;\n            cam.orthographicSize = scale * 2.0f;\n            cam.nearClipPlane = 1 * scale;\n            cam.farClipPlane = 25 * scale;\n            cam.transform.rotation = is2D ? Quaternion.identity : light.transform.rotation;\n            cam.transform.position = center - light.transform.forward * (scale * 5.5f);\n\n            // Clear to black\n            CameraClearFlags oldFlags = cam.clearFlags;\n            cam.clearFlags = CameraClearFlags.SolidColor;\n            Color oldColor = cam.backgroundColor;\n            cam.backgroundColor = new Color(0, 0, 0, 0);\n\n            // Create render target for shadow map\n            const int kShadowSize = 256;\n            RenderTexture oldRT = cam.targetTexture;\n            RenderTexture rt = RenderTexture.GetTemporary(kShadowSize, kShadowSize, 16);\n            rt.isPowerOfTwo = true;\n            rt.wrapMode = TextureWrapMode.Clamp;\n            rt.filterMode = FilterMode.Bilinear;\n            cam.targetTexture = rt;\n\n            // Enable character and render with camera into the shadowmap\n            SetPreviewCharacterEnabled(true, false);\n            m_PreviewUtility.camera.Render();\n\n            // Draw a quad, with shader that will produce white color everywhere\n            // where something was rendered (via inverted depth test)\n            RenderTexture.active = rt;\n            GL.PushMatrix();\n            GL.LoadOrtho();\n            m_ShadowMaskMaterial.SetPass(0);\n            GL.Begin(GL.QUADS);\n            GL.Vertex3(0, 0, -99.0f);\n            GL.Vertex3(1, 0, -99.0f);\n            GL.Vertex3(1, 1, -99.0f);\n            GL.Vertex3(0, 1, -99.0f);\n            GL.End();\n\n            // Render floor with black color, to mask out any shadow from character\n            // parts that are under the preview plane\n            GL.LoadProjectionMatrix(cam.projectionMatrix);\n            GL.LoadIdentity();\n            GL.MultMatrix(cam.worldToCameraMatrix);\n            m_ShadowPlaneMaterial.SetPass(0);\n            GL.Begin(GL.QUADS);\n            float sc = kFloorScale * scale;\n            GL.Vertex(floorPos + new Vector3(-sc, 0, -sc));\n            GL.Vertex(floorPos + new Vector3(sc, 0, -sc));\n            GL.Vertex(floorPos + new Vector3(sc, 0, sc));\n            GL.Vertex(floorPos + new Vector3(-sc, 0, sc));\n            GL.End();\n\n            GL.PopMatrix();\n\n            // Shadowmap sampling matrix, from world space into shadowmap space\n            Matrix4x4 texMatrix = Matrix4x4.TRS(new Vector3(0.5f, 0.5f, 0.5f), Quaternion.identity,\n                new Vector3(0.5f, 0.5f, 0.5f));\n            outShadowMatrix = texMatrix * cam.projectionMatrix * cam.worldToCameraMatrix;\n\n            // Restore previous camera parameters\n            cam.orthographic = false;\n            cam.clearFlags = oldFlags;\n            cam.backgroundColor = oldColor;\n            cam.targetTexture = oldRT;\n\n            return rt;\n        }\n\n        public void DoRenderPreview(Rect previewRect, GUIStyle background)\n        {\n            var probe = RenderSettings.ambientProbe;\n            previewUtility.BeginPreview(previewRect, background);\n\n            Quaternion bodyRot;\n            Quaternion rootRot;\n            Vector3 rootPos;\n            Vector3 bodyPos = rootPosition;\n            Vector3 pivotPos;\n\n            if (Animator && Animator.isHuman)\n            {\n                rootRot = Animator.rootRotation;\n                rootPos = Animator.rootPosition;\n\n                bodyRot = Animator.bodyRotation;\n\n                pivotPos = Animator.pivotPosition;\n            }\n            else if (Animator && Animator.hasRootMotion)\n            {\n                rootRot = Animator.rootRotation;\n                rootPos = Animator.rootPosition;\n\n                bodyRot = Quaternion.identity;\n\n                pivotPos = Vector3.zero;\n            }\n            else\n            {\n                rootRot = Quaternion.identity;\n                rootPos = Vector3.zero;\n\n                bodyRot = Quaternion.identity;\n\n                pivotPos = Vector3.zero;\n            }\n\n            SetupPreviewLightingAndFx(probe);\n\n            Vector3 direction = bodyRot * Vector3.forward;\n            direction[1] = 0;\n            Quaternion directionRot = Quaternion.LookRotation(direction);\n            Vector3 directionPos = rootPos;\n\n            Quaternion pivotRot = rootRot;\n\n            // Scale all Preview Objects to fit avatar size.\n            PositionPreviewObjects(pivotRot, pivotPos, bodyRot, bodyPosition, directionRot, rootRot, rootPos, directionPos, m_AvatarScale);\n\n            bool dynamicFloorHeight = is2D ? false : Mathf.Abs(m_NextFloorHeight - m_PrevFloorHeight) > m_ZoomFactor * 0.01f;\n\n            // Calculate floor height and alpha\n            float mainFloorHeight, mainFloorAlpha;\n            if (dynamicFloorHeight)\n            {\n                float fadeMoment = m_NextFloorHeight < m_PrevFloorHeight ? kFloorFadeDuration : (1 - kFloorFadeDuration);\n                mainFloorHeight = timeControl.normalizedTime < fadeMoment ? m_PrevFloorHeight : m_NextFloorHeight;\n                mainFloorAlpha = Mathf.Clamp01(Mathf.Abs(timeControl.normalizedTime - fadeMoment) / kFloorFadeDuration);\n            }\n            else\n            {\n                mainFloorHeight = m_PrevFloorHeight;\n                mainFloorAlpha = is2D ? 0.5f : 1;\n            }\n\n            Quaternion floorRot = is2D ? Quaternion.Euler(-90, 0, 0) : Quaternion.identity;\n            Vector3 floorPos = m_ReferenceInstance.transform.position;\n            floorPos.y = mainFloorHeight;\n\n            // Render shadow map\n            Matrix4x4 shadowMatrix;\n            RenderTexture shadowMap = RenderPreviewShadowmap(previewUtility.lights[0], m_BoundingVolumeScale / 2, bodyPosition, floorPos, out shadowMatrix);\n\n            // SRP might initialize the light settings during the first frame of rendering\n            // (e.g HDRP is overriding the intensity value during 'InitDefaultHDAdditionalLightData').\n            // So this call is necessary to avoid a flickering when selecting an animation clip.\n            if (previewUtility.lights[0].intensity != kDefaultIntensity || previewUtility.lights[1].intensity != kDefaultIntensity)\n            {\n                SetupPreviewLightingAndFx(probe);\n            }\n\n            float tempZoomFactor = (is2D ? 1.0f : m_ZoomFactor);\n            // Position camera\n            previewUtility.camera.orthographic = is2D;\n            if (is2D)\n                previewUtility.camera.orthographicSize = 2.0f * m_ZoomFactor;\n            previewUtility.camera.nearClipPlane = 0.5f * tempZoomFactor;\n            previewUtility.camera.farClipPlane = 100.0f * m_AvatarScale;\n            Quaternion camRot = Quaternion.Euler(-m_PreviewDir.y, -m_PreviewDir.x, 0);\n\n            // Add panning offset\n            Vector3 camPos = camRot * (Vector3.forward * -5.5f * tempZoomFactor) + bodyPos + m_PivotPositionOffset;\n            previewUtility.camera.transform.position = camPos;\n            previewUtility.camera.transform.rotation = camRot;\n\n\n            SetPreviewCharacterEnabled(true, m_ShowReference);\n            foreach (var previewable in m_Previewables)\n                previewable.OnPreviewUpdate();\n            previewUtility.Render(!m_IsCurrentPreviewInstanceFallback);\n            SetPreviewCharacterEnabled(false, false);\n\n            // Texture offset - negative in order to compensate the floor movement.\n            Vector2 textureOffset = -new Vector2(floorPos.x, is2D ? floorPos.y : floorPos.z);\n\n            // Render main floor\n            {\n                Material mat = m_FloorMaterial;\n                Matrix4x4 matrix = Matrix4x4.TRS(floorPos, floorRot, Vector3.one * kFloorScale * m_AvatarScale);\n\n                mat.mainTextureOffset = textureOffset * kFloorScale * 0.08f * (1.0f / m_AvatarScale);\n                mat.SetTexture(\"_ShadowTexture\", shadowMap);\n                mat.SetMatrix(\"_ShadowTextureMatrix\", shadowMatrix);\n                mat.SetVector(\"_Alphas\", new Vector4(kFloorAlpha * mainFloorAlpha, kFloorShadowAlpha * mainFloorAlpha, 0, 0));\n                mat.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Background;\n\n                Graphics.DrawMesh(m_FloorPlane, matrix, mat, kDefaultLayer, previewUtility.camera, 0);\n            }\n\n            // Render small floor\n            if (dynamicFloorHeight)\n            {\n                bool topIsNext = m_NextFloorHeight > m_PrevFloorHeight;\n                float floorHeight = topIsNext ? m_NextFloorHeight : m_PrevFloorHeight;\n                float otherFloorHeight = topIsNext ? m_PrevFloorHeight : m_NextFloorHeight;\n                float floorAlpha = (floorHeight == mainFloorHeight ? 1 - mainFloorAlpha : 1) * Mathf.InverseLerp(otherFloorHeight, floorHeight, rootPos.y);\n                floorPos.y = floorHeight;\n\n                Material mat = m_FloorMaterialSmall;\n                mat.mainTextureOffset = textureOffset * kFloorScaleSmall * 0.08f;\n                mat.SetTexture(\"_ShadowTexture\", shadowMap);\n                mat.SetMatrix(\"_ShadowTextureMatrix\", shadowMatrix);\n                mat.SetVector(\"_Alphas\", new Vector4(kFloorAlpha * floorAlpha, 0, 0, 0));\n                Matrix4x4 matrix = Matrix4x4.TRS(floorPos, floorRot, Vector3.one * kFloorScaleSmall * m_AvatarScale);\n                Graphics.DrawMesh(m_FloorPlane, matrix, mat, kDefaultLayer, previewUtility.camera, 0);\n            }\n\n            var clearMode = previewUtility.camera.clearFlags;\n            previewUtility.camera.clearFlags = CameraClearFlags.Nothing;\n            previewUtility.Render(false);\n            previewUtility.camera.clearFlags = clearMode;\n            RenderTexture.ReleaseTemporary(shadowMap);\n        }\n\n        private void SetupPreviewLightingAndFx(SphericalHarmonicsL2 probe)\n        {\n            previewUtility.lights[0].intensity = kDefaultIntensity;\n            previewUtility.lights[0].transform.rotation = Quaternion.Euler(40f, 40f, 0);\n            previewUtility.lights[1].intensity = kDefaultIntensity;\n            RenderSettings.ambientMode = AmbientMode.Custom;\n            RenderSettings.ambientLight = new Color(0.1f, 0.1f, 0.1f, 1.0f);\n            RenderSettings.ambientProbe = probe;\n        }\n\n        private float m_LastNormalizedTime = -1000;\n        private float m_LastStartTime = -1000;\n        private float m_LastStopTime = -1000;\n        private bool m_NextTargetIsForward = true;\n        private void PositionPreviewObjects(Quaternion pivotRot, Vector3 pivotPos, Quaternion bodyRot, Vector3 bodyPos,\n            Quaternion directionRot, Quaternion rootRot, Vector3 rootPos, Vector3 directionPos,\n            float scale)\n        {\n            m_ReferenceInstance.transform.position = rootPos;\n            m_ReferenceInstance.transform.rotation = rootRot;\n            m_ReferenceInstance.transform.localScale = Vector3.one * scale * 1.25f;\n\n            m_DirectionInstance.transform.position = directionPos;\n            m_DirectionInstance.transform.rotation = directionRot;\n            m_DirectionInstance.transform.localScale = Vector3.one * scale * 2;\n\n            m_PivotInstance.transform.position = pivotPos;\n            m_PivotInstance.transform.rotation = pivotRot;\n            m_PivotInstance.transform.localScale = Vector3.one * scale * 0.1f;\n\n            m_RootInstance.transform.position = bodyPos;\n            m_RootInstance.transform.rotation = bodyRot;\n            m_RootInstance.transform.localScale = Vector3.one * scale * 0.25f;\n\n            if (Animator)\n            {\n                float normalizedTime = timeControl.normalizedTime;\n                float normalizedDelta = timeControl.deltaTime / (timeControl.stopTime - timeControl.startTime);\n\n                // Always set last height to next height after wrapping the time.\n                if (normalizedTime - normalizedDelta < 0 || normalizedTime - normalizedDelta >= 1)\n                    m_PrevFloorHeight = m_NextFloorHeight;\n\n                // Check that AvatarPreview is getting reliable info about time and deltaTime.\n                if (m_LastNormalizedTime != -1000 && timeControl.startTime == m_LastStartTime && timeControl.stopTime == m_LastStopTime)\n                {\n                    float difference = normalizedTime - normalizedDelta - m_LastNormalizedTime;\n                    if (difference > 0.5f)\n                        difference -= 1;\n                    else if (difference < -0.5f)\n                        difference += 1;\n                }\n                m_LastNormalizedTime = normalizedTime;\n                m_LastStartTime = timeControl.startTime;\n                m_LastStopTime = timeControl.stopTime;\n\n                // Alternate getting the height for next time and previous time.\n                if (m_NextTargetIsForward)\n                    m_NextFloorHeight = Animator.targetPosition.y;\n                else\n                    m_PrevFloorHeight = Animator.targetPosition.y;\n\n                // Flip next target time.\n                m_NextTargetIsForward = !m_NextTargetIsForward;\n                Animator.SetTarget(AvatarTarget.Root, m_NextTargetIsForward ? 1 : 0);\n            }\n        }\n\n        public void AvatarTimeControlGUI(Rect rect)\n        {\n            const float kSliderWidth = 150f;\n            const float kSpacing = 4f;\n            Rect timeControlRect = rect;\n\n            // background\n            GUI.Box(rect, GUIContent.none, EditorStyles.toolbar);\n\n            timeControlRect.height = kTimeControlRectHeight;\n            timeControlRect.xMax -= kSliderWidth;\n\n            Rect sliderControlRect = rect;\n            sliderControlRect.height = kTimeControlRectHeight;\n            sliderControlRect.yMin += 1;\n            sliderControlRect.yMax -= 1;\n            sliderControlRect.xMin = sliderControlRect.xMax - kSliderWidth + kSpacing;\n\n            timeControl.DoTimeControl(timeControlRect);\n            Rect labelRect = new Rect(new Vector2(rect.x, rect.y), EditorStyles.toolbarLabel.CalcSize(EditorGUIUtility.TrTempContent(\"xxxxxx\")));;\n            labelRect.x = rect.xMax - labelRect.width;\n            labelRect.yMin = rect.yMin;\n            labelRect.yMax = rect.yMax;\n\n            sliderControlRect.xMax = labelRect.xMin;\n\n            EditorGUI.BeginChangeCheck();\n            timeControl.playbackSpeed = PreviewSlider(sliderControlRect, timeControl.playbackSpeed, 0.03f);\n            if (EditorGUI.EndChangeCheck())\n                EditorPrefs.SetFloat(kSpeedPref, timeControl.playbackSpeed);\n            GUI.Label(labelRect, timeControl.playbackSpeed.ToString(\"f2\", CultureInfo.InvariantCulture.NumberFormat) + \"x\", EditorStyles.toolbarLabel);\n\n            // Show current time in seconds:frame and in percentage\n            rect.y = rect.yMax - 24;\n            float time = timeControl.currentTime - timeControl.startTime;\n            EditorGUI.DropShadowLabel(new Rect(rect.x, rect.y, rect.width, 20),\n                string.Format(\"{0,2}:{1:00} ({2:000.0%}) Frame {3}\", (int)time, Repeat(Mathf.FloorToInt(time * fps), fps), timeControl.normalizedTime, Mathf.FloorToInt(timeControl.currentTime * fps))\n            );\n        }\n\n        enum PreviewPopupOptions : int\n        {\n            Auto = 0,\n            DefaultModel = 1,\n            Other = 2\n        }\n\n        protected enum ViewTool { None, Pan, Zoom, Orbit }\n        protected ViewTool m_ViewTool = ViewTool.None;\n        protected ViewTool viewTool\n        {\n            get\n            {\n                Event evt = Event.current;\n                if (m_ViewTool == ViewTool.None)\n                {\n                    bool controlKeyOnMac = (evt.control && Application.platform == RuntimePlatform.OSXEditor);\n\n                    // actionKey could be command key on mac or ctrl on windows\n                    bool actionKey = EditorGUI.actionKey;\n\n                    bool noModifiers = (!actionKey && !controlKeyOnMac && !evt.alt);\n\n                    if ((evt.button <= 0 && noModifiers) || (evt.button <= 0 && actionKey) || evt.button == 2)\n                        m_ViewTool = ViewTool.Pan;\n                    else if ((evt.button <= 0 && controlKeyOnMac) || (evt.button == 1 && evt.alt))\n                        m_ViewTool = ViewTool.Zoom;\n                    else if (evt.button <= 0 && evt.alt || evt.button == 1)\n                        m_ViewTool = ViewTool.Orbit;\n                }\n                return m_ViewTool;\n            }\n        }\n\n        protected MouseCursor currentCursor\n        {\n            get\n            {\n                switch (m_ViewTool)\n                {\n                    case ViewTool.Orbit: return MouseCursor.Orbit;\n                    case ViewTool.Pan: return MouseCursor.Pan;\n                    case ViewTool.Zoom: return MouseCursor.Zoom;\n                    default: return MouseCursor.Arrow;\n                }\n            }\n        }\n\n\n        protected void HandleMouseDown(Event evt, int id, Rect previewRect)\n        {\n            if (viewTool != ViewTool.None && previewRect.Contains(evt.mousePosition))\n            {\n                EditorGUIUtility.SetWantsMouseJumping(1);\n                evt.Use();\n                GUIUtility.hotControl = id;\n            }\n        }\n\n        protected void HandleMouseUp(Event evt, int id)\n        {\n            if (GUIUtility.hotControl == id)\n            {\n                m_ViewTool = ViewTool.None;\n\n                GUIUtility.hotControl = 0;\n                EditorGUIUtility.SetWantsMouseJumping(0);\n                evt.Use();\n            }\n        }\n\n        protected void HandleMouseDrag(Event evt, int id, Rect previewRect)\n        {\n            if (m_PreviewInstance == null)\n                return;\n\n            if (GUIUtility.hotControl == id)\n            {\n                switch (m_ViewTool)\n                {\n                    case ViewTool.Orbit:    DoAvatarPreviewOrbit(evt, previewRect); break;\n                    case ViewTool.Pan:      DoAvatarPreviewPan(evt); break;\n\n                    // case 605415 invert zoom delta to match scene view zooming\n                    case ViewTool.Zoom:     DoAvatarPreviewZoom(evt, -HandleUtility.niceMouseDeltaZoom * (evt.shift ? 2.0f : 0.5f)); break;\n                    default:                Debug.Log(\"Enum value not handled\"); break;\n                }\n            }\n        }\n\n        protected void HandleViewTool(Event evt, EventType eventType, int id, Rect previewRect)\n        {\n            switch (eventType)\n            {\n                case EventType.ScrollWheel: DoAvatarPreviewZoom(evt, HandleUtility.niceMouseDeltaZoom * (evt.shift ? 2.0f : 0.5f)); break;\n                case EventType.MouseDown:   HandleMouseDown(evt, id, previewRect); break;\n                case EventType.MouseUp:     HandleMouseUp(evt, id); break;\n                case EventType.MouseDrag:   HandleMouseDrag(evt, id, previewRect); break;\n            }\n        }\n\n        public void DoAvatarPreviewDrag(Event evt, EventType type)\n        {\n            if (type == EventType.DragUpdated)\n            {\n                DragAndDrop.visualMode = DragAndDropVisualMode.Link;\n                evt.Use();\n            }\n            else if (type == EventType.DragPerform)\n            {\n                DragAndDrop.visualMode = DragAndDropVisualMode.Link;\n                GameObject newPreviewObject = DragAndDrop.objectReferences[0] as GameObject;\n\n                if (newPreviewObject)\n                {\n                    DragAndDrop.AcceptDrag();\n                    SetPreview(newPreviewObject);\n                }\n\n                evt.Use();\n            }\n        }\n\n        public void DoAvatarPreviewOrbit(Event evt, Rect previewRect)\n        {\n            //Reset 2D on Orbit\n            if (is2D)\n            {\n                is2D = false;\n            }\n            m_PreviewDir -= evt.delta * (evt.shift ? 3 : 1) / Mathf.Min(previewRect.width, previewRect.height) * 140.0f;\n            m_PreviewDir.y = Mathf.Clamp(m_PreviewDir.y, -90, 90);\n            evt.Use();\n        }\n\n        public void DoAvatarPreviewPan(Event evt)\n        {\n            Camera cam = previewUtility.camera;\n            Vector3 screenPos = cam.WorldToScreenPoint(bodyPosition + m_PivotPositionOffset);\n            Vector3 delta = new Vector3(-evt.delta.x, evt.delta.y, 0);\n            // delta panning is scale with the zoom factor to allow fine tuning when user is zooming closely.\n            screenPos += delta * Mathf.Lerp(0.25f, 2.0f, m_ZoomFactor * 0.5f);\n            Vector3 worldDelta = cam.ScreenToWorldPoint(screenPos) - (bodyPosition + m_PivotPositionOffset);\n            m_PivotPositionOffset += worldDelta;\n            evt.Use();\n        }\n\n        public void ResetPreviewFocus()\n        {\n            m_PivotPositionOffset = bodyPosition - rootPosition;\n        }\n\n        public void DoAvatarPreviewFrame(Event evt, EventType type, Rect previewRect)\n        {\n            if (type == EventType.KeyDown && evt.keyCode == KeyCode.F)\n            {\n                ResetPreviewFocus();\n                m_ZoomFactor = m_AvatarScale;\n                evt.Use();\n            }\n\n            if (type == EventType.KeyDown && Event.current.keyCode == KeyCode.G)\n            {\n                m_PivotPositionOffset = GetCurrentMouseWorldPosition(evt, previewRect) - bodyPosition;\n                evt.Use();\n            }\n        }\n\n        protected Vector3 GetCurrentMouseWorldPosition(Event evt, Rect previewRect)\n        {\n            Camera cam = previewUtility.camera;\n\n            float scaleFactor = previewUtility.GetScaleFactor(previewRect.width, previewRect.height);\n            Vector3 mouseLocal = new Vector3((evt.mousePosition.x - previewRect.x) * scaleFactor, (previewRect.height - (evt.mousePosition.y - previewRect.y)) * scaleFactor, 0);\n            mouseLocal.z = Vector3.Distance(bodyPosition, cam.transform.position);\n            return cam.ScreenToWorldPoint(mouseLocal);\n        }\n\n        public void DoAvatarPreviewZoom(Event evt, float delta)\n        {\n            float zoomDelta = -delta * 0.05f;\n            m_ZoomFactor += m_ZoomFactor * zoomDelta;\n\n            // zoom is clamp too 10 time closer than the original zoom\n            m_ZoomFactor = Mathf.Max(m_ZoomFactor, m_AvatarScale / 10.0f);\n            evt.Use();\n        }\n\n        public void DoAvatarPreview(Rect rect, GUIStyle background)\n        {\n            Init();\n\n            Rect choserRect = new Rect(rect.xMax - 16, rect.yMax - 16, 16, 16);\n            if (EditorGUI.DropdownButton(choserRect, GUIContent.none, FocusType.Passive, GUIStyle.none))\n            {\n                GenericMenu menu = new GenericMenu();\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Auto\"), false, SetPreviewAvatarOption, PreviewPopupOptions.Auto);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Unity Model\"), false, SetPreviewAvatarOption, PreviewPopupOptions.DefaultModel);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Other...\"), false, SetPreviewAvatarOption, PreviewPopupOptions.Other);\n                menu.ShowAsContext();\n            }\n\n            Rect previewRect = rect;\n            previewRect.yMin += kTimeControlRectHeight;\n            previewRect.height = Mathf.Max(previewRect.height, 64f);\n\n            int previewID = GUIUtility.GetControlID(m_PreviewHint, FocusType.Passive, previewRect);\n            Event evt = Event.current;\n            EventType type = evt.GetTypeForControl(previewID);\n\n            if (type == EventType.Repaint && m_IsValid)\n            {\n                DoRenderPreview(previewRect, background);\n                previewUtility.EndAndDrawPreview(previewRect);\n            }\n\n            AvatarTimeControlGUI(rect);\n\n\n            int previewSceneID = GUIUtility.GetControlID(m_PreviewSceneHint, FocusType.Passive);\n            type = evt.GetTypeForControl(previewSceneID);\n\n            DoAvatarPreviewDrag(evt, type);\n            HandleViewTool(evt, type, previewSceneID, previewRect);\n            DoAvatarPreviewFrame(evt, type, previewRect);\n\n            if (!m_IsValid)\n            {\n                Rect warningRect = previewRect;\n                warningRect.yMax -= warningRect.height / 2 - 16;\n                EditorGUI.DropShadowLabel(\n                    warningRect,\n                    \"No model is available for preview.\\nPlease drag a model into this Preview Area.\");\n            }\n\n            // Apply the current cursor\n            if (evt.type == EventType.Repaint)\n                EditorGUIUtility.AddCursorRect(previewRect, currentCursor);\n        }\n\n        private PreviewPopupOptions option\n        {\n            get => (PreviewPopupOptions) EditorPrefs.GetInt(kDefaultAvatarPreviewOption);\n            set => EditorPrefs.SetInt(kDefaultAvatarPreviewOption, (int)value);\n        }\n\n        void SetPreviewAvatarOption(object obj)\n        {\n            var newSelectedOption = (PreviewPopupOptions)obj;\n\n            if (option != newSelectedOption)\n            {\n                option = newSelectedOption;\n\n                switch (option)\n                {\n                    case PreviewPopupOptions.Auto:\n                        SetPreview(null);\n                        break;\n                    case PreviewPopupOptions.DefaultModel:\n                        SetPreview(GetHumanoidFallback());\n                        break;\n                    case PreviewPopupOptions.Other:\n                        ObjectSelectorOperation.Start(this);\n                        break;\n                }\n            }\n        }\n\n        void SetPreview(GameObject gameObject)\n        {\n            AvatarPreviewSelection.SetPreview(animationClipType, gameObject);\n\n            Object.DestroyImmediate(m_PreviewInstance);\n            InitInstance(m_SourceScenePreviewAnimator, m_SourcePreviewMotion);\n\n            if (m_OnAvatarChangeFunc != null)\n                m_OnAvatarChangeFunc();\n        }\n\n        int Repeat(int t, int length)\n        {\n            // Have to do double modulo in order to work for negative numbers.\n            // This is quicker than a branch to test for negative number.\n            return ((t % length) + length) % length;\n        }\n    } // class AvatarPreview\n} // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/Inspector/AvatarPreviewSelection.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditorInternal;\nusing System.Reflection;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class AvatarPreviewSelection : ScriptableSingleton<AvatarPreviewSelection>\n    {\n        [SerializeField]\n        GameObject[] m_PreviewModels;\n\n        void Awake()\n        {\n            int length = (int)ModelImporterAnimationType.Human + 1;\n            if (m_PreviewModels == null || m_PreviewModels.Length != length)\n                m_PreviewModels = new GameObject[length];\n        }\n\n        static public void SetPreview(ModelImporterAnimationType type, GameObject go)\n        {\n            if (!System.Enum.IsDefined(typeof(ModelImporterAnimationType), type))\n                return;\n\n            if (instance.m_PreviewModels[(int)type] != go)\n            {\n                instance.m_PreviewModels[(int)type] = go;\n            }\n        }\n\n        static public GameObject GetPreview(ModelImporterAnimationType type)\n        {\n            if (!System.Enum.IsDefined(typeof(ModelImporterAnimationType), type))\n                return null;\n\n            return instance.m_PreviewModels[(int)type];\n        }\n    } // class AvatarPreviewSelection\n} // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/Inspector/BillboardAssetInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nusing UnityEngine;\nusing UnityEditorInternal;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(BillboardAsset))]\n    [CanEditMultipleObjects]\n    internal class BillboardAssetInspector : Editor\n    {\n        private SerializedProperty m_Width;\n        private SerializedProperty m_Height;\n        private SerializedProperty m_Bottom;\n        private SerializedProperty m_Images;\n        private SerializedProperty m_Vertices;\n        private SerializedProperty m_Indices;\n        private SerializedProperty m_Material;\n\n        private bool m_PreviewShaded = true;\n        private PreviewRenderUtility m_PreviewUtility;\n        private Mesh m_ShadedMesh;\n        private Mesh m_GeometryMesh;\n        private MaterialPropertyBlock m_ShadedMaterialProperties;\n        private Material m_GeometryMaterial;\n\n        MeshPreview.Settings m_Settings;\n\n        private class GUIStyles\n        {\n            public readonly GUIContent m_Shaded = EditorGUIUtility.TrTextContent(\"Shaded\");\n            public readonly GUIContent m_Geometry = EditorGUIUtility.TrTextContent(\"Geometry\");\n            public readonly GUIStyle m_DropdownButton = \"MiniPopup\";\n        }\n\n        private static GUIStyles s_Styles = null;\n        private static GUIStyles Styles\n        {\n            get\n            {\n                if (s_Styles == null)\n                    s_Styles = new GUIStyles();\n                return s_Styles;\n            }\n        }\n\n        private void OnEnable()\n        {\n            m_Width = serializedObject.FindProperty(\"width\");\n            m_Height = serializedObject.FindProperty(\"height\");\n            m_Bottom = serializedObject.FindProperty(\"bottom\");\n            m_Images = serializedObject.FindProperty(\"imageTexCoords\");\n            m_Vertices = serializedObject.FindProperty(\"vertices\");\n            m_Indices = serializedObject.FindProperty(\"indices\");\n            m_Material = serializedObject.FindProperty(\"material\");\n\n            m_Settings = new MeshPreview.Settings();\n            m_Settings.previewDir = new Vector2(-120, 20);\n        }\n\n        private void OnDisable()\n        {\n            m_Settings?.Dispose();\n\n            if (m_PreviewUtility != null)\n            {\n                m_PreviewUtility.Cleanup();\n                m_PreviewUtility = null;\n                DestroyImmediate(m_ShadedMesh, true);\n                DestroyImmediate(m_GeometryMesh, true);\n                m_GeometryMaterial = null;\n            }\n        }\n\n        private void InitPreview()\n        {\n            if (m_PreviewUtility == null)\n            {\n                m_PreviewUtility = new PreviewRenderUtility();\n                m_ShadedMesh = new Mesh();\n                m_ShadedMesh.hideFlags = HideFlags.HideAndDontSave;\n                m_ShadedMesh.MarkDynamic();\n                m_GeometryMesh = new Mesh();\n                m_GeometryMesh.hideFlags = HideFlags.HideAndDontSave;\n                m_GeometryMesh.MarkDynamic();\n                m_ShadedMaterialProperties = new MaterialPropertyBlock();\n                m_GeometryMaterial = Material.GetDefaultMaterial();\n                EditorUtility.SetCameraAnimateMaterials(m_PreviewUtility.camera, true);\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUILayout.PropertyField(m_Width);\n            EditorGUILayout.PropertyField(m_Height);\n            EditorGUILayout.PropertyField(m_Bottom);\n            EditorGUILayout.PropertyField(m_Material);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        public override bool HasPreviewGUI()\n        {\n            return (target != null);\n        }\n\n        public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height)\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture)\n                return null;\n\n            InitPreview();\n\n            m_PreviewUtility.BeginStaticPreview(new Rect(0, 0, width, height));\n\n            DoRenderPreview(true);\n\n            return m_PreviewUtility.EndStaticPreview();\n        }\n\n        public override void OnPreviewSettings()\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture)\n                return;\n\n            bool switchable = m_Material.objectReferenceValue != null;\n            GUI.enabled = switchable;\n            if (!switchable)\n                m_PreviewShaded = false;\n\n            var content = m_PreviewShaded ? Styles.m_Shaded : Styles.m_Geometry;\n            var rect = GUILayoutUtility.GetRect(content, Styles.m_DropdownButton, GUILayout.Width(75));\n\n            if (EditorGUI.DropdownButton(rect, content, FocusType.Passive, Styles.m_DropdownButton))\n            {\n                GUIUtility.hotControl = 0;\n                var dropDownMenu = new GenericMenu();\n                dropDownMenu.AddItem(Styles.m_Shaded, m_PreviewShaded, () => m_PreviewShaded = true);\n                dropDownMenu.AddItem(Styles.m_Geometry, !m_PreviewShaded, () => m_PreviewShaded = false);\n                dropDownMenu.DropDown(rect);\n            }\n        }\n\n        public override void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture)\n            {\n                if (Event.current.type == EventType.Repaint)\n                    EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), \"Preview requires\\nrender texture support\");\n                return;\n            }\n\n            InitPreview();\n\n            m_Settings.previewDir = PreviewGUI.Drag2D(m_Settings.previewDir, r);\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            m_PreviewUtility.BeginPreview(r,  background);\n\n            DoRenderPreview(m_PreviewShaded);\n\n            m_PreviewUtility.EndAndDrawPreview(r);\n        }\n\n        public override string GetInfoString()\n        {\n            string info = String.Format(\"{0} verts, {1} tris, {2} images\",\n                m_Vertices.arraySize,\n                m_Indices.arraySize / 3,\n                m_Images.arraySize);\n            return info;\n        }\n\n        // Make a mesh out of the BillboardAsset that is used for rendering by SpeedTree billboard shader.\n        // Vertices are expanded by the shader therefore the mesh vertices are not used (filled by zeroes).\n        internal static void MakeRenderMesh(Mesh mesh, BillboardAsset billboard)\n        {\n            mesh.SetVertices(Enumerable.Repeat(Vector3.zero, billboard.vertexCount).ToList());\n            mesh.SetColors(Enumerable.Repeat(Color.black, billboard.vertexCount).ToList());\n            mesh.SetUVs(0, billboard.GetVertices().ToList());\n            mesh.SetUVs(1, Enumerable.Repeat(new Vector4(1.0f, 1.0f, 0.0f, 0.0f), billboard.vertexCount).ToList());\n            mesh.SetTriangles(billboard.GetIndices().Select(v => (int)v).ToList(), 0);\n        }\n\n        // Make a mesh out of the BillboardAsset that is suitable for previewing the geometry.\n        // The vertices are expanded and made double-face.\n        private void MakePreviewMesh(Mesh mesh, BillboardAsset billboard)\n        {\n            float width = billboard.width;\n            float height = billboard.height;\n            float bottom = billboard.bottom;\n            mesh.SetVertices(Enumerable.Repeat(\n                billboard.GetVertices().Select(v => new Vector3(\n                    (v.x - 0.5f) * width,\n                    v.y * height + bottom,\n                    0)),\n                // Repeat the sequence twice\n                2).SelectMany(s => s).ToList());\n\n            // (0,0,1) for the front-facing vertices and (0,0,-1) for the back-facing vertices\n            mesh.SetNormals(\n                Enumerable.Repeat(Vector3.forward, billboard.vertexCount).Concat(\n                    Enumerable.Repeat(-Vector3.forward, billboard.vertexCount)).ToList());\n\n            // make a new triangle list with second half triangles flipped\n            var indices = new int[billboard.indexCount * 2];\n            var billboardIndices = billboard.GetIndices();\n            for (int i = 0; i < billboard.indexCount / 3; ++i)\n            {\n                indices[i * 3 + 0] = billboardIndices[i * 3 + 0];\n                indices[i * 3 + 1] = billboardIndices[i * 3 + 1];\n                indices[i * 3 + 2] = billboardIndices[i * 3 + 2];\n                indices[i * 3 + 0 + billboard.indexCount] = billboardIndices[i * 3 + 2];\n                indices[i * 3 + 1 + billboard.indexCount] = billboardIndices[i * 3 + 1];\n                indices[i * 3 + 2 + billboard.indexCount] = billboardIndices[i * 3 + 0];\n            }\n            mesh.SetTriangles(indices, 0);\n        }\n\n        private void DoRenderPreview(bool shaded)\n        {\n            var billboard = target as BillboardAsset;\n\n            Bounds bounds = new Bounds(\n                new Vector3(0, (m_Height.floatValue + m_Bottom.floatValue) * 0.5f, 0),\n                new Vector3(m_Width.floatValue, m_Height.floatValue, m_Width.floatValue));\n\n            float halfSize = bounds.extents.magnitude;\n            float distance = 8.0f * halfSize;\n\n            var rotation = Quaternion.Euler(-m_Settings.previewDir.y, -m_Settings.previewDir.x, 0);\n            m_PreviewUtility.camera.transform.rotation = rotation;\n            m_PreviewUtility.camera.transform.position = rotation * (-Vector3.forward * distance);\n            m_PreviewUtility.camera.nearClipPlane = distance - halfSize * 1.1f;\n            m_PreviewUtility.camera.farClipPlane = distance + halfSize * 1.1f;\n\n            m_PreviewUtility.lights[0].intensity = 1.4f;\n            m_PreviewUtility.lights[0].transform.rotation = rotation * Quaternion.Euler(40f, 40f, 0);\n            m_PreviewUtility.lights[1].intensity = 1.4f;\n            m_PreviewUtility.ambientColor = new Color(.1f, .1f, .1f, 0);\n\n            var tempPreviewDir = m_Settings.previewDir;\n            m_Settings.previewDir = new Vector2(0, 0);\n            if (shaded)\n            {\n                MakeRenderMesh(m_ShadedMesh, billboard);\n                billboard.MakeMaterialProperties(m_ShadedMaterialProperties, m_PreviewUtility.camera);\n                m_Settings.activeMaterial = billboard.material;\n                MeshPreview.RenderMeshPreviewSkipCameraAndLighting(m_ShadedMesh, bounds, m_PreviewUtility, m_Settings, m_ShadedMaterialProperties, -1);\n            }\n            else\n            {\n                MakePreviewMesh(m_GeometryMesh, billboard);\n                m_Settings.activeMaterial = m_GeometryMaterial;\n                MeshPreview.RenderMeshPreviewSkipCameraAndLighting(m_GeometryMesh, bounds, m_PreviewUtility, m_Settings, null, -1);\n            }\n            m_Settings.previewDir = tempPreviewDir;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/BillboardRendererInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(BillboardRenderer))]\n    [CanEditMultipleObjects]\n    internal class BillboardRendererInspector : RendererEditorBase\n    {\n        class Styles\n        {\n            public static readonly GUIContent billboard = EditorGUIUtility.TrTextContent(\"Billboard\");\n        }\n\n        private SerializedProperty m_Billboard;\n\n        public override void OnEnable()\n        {\n            base.OnEnable();\n\n            m_Billboard = serializedObject.FindProperty(\"m_Billboard\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUILayout.PropertyField(m_Billboard, Styles.billboard);\n\n            LightingSettingsGUI(false);\n            OtherSettingsGUI(true);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/BlendTreeInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.AnimatedValues;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditor.Animations;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\n\nusing Object = UnityEngine.Object;\nusing System.Globalization;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(BlendTree))]\n    internal class BlendTreeInspector : Editor\n    {\n        class Styles\n        {\n            public readonly GUIStyle background = \"MeBlendBackground\";\n            public readonly GUIStyle triangleLeft = \"MeBlendTriangleLeft\";\n            public readonly GUIStyle triangleRight = \"MeBlendTriangleRight\";\n            public readonly GUIStyle blendPosition = \"MeBlendPosition\";\n            public GUIStyle clickDragFloatFieldLeft = new GUIStyle(EditorStyles.miniTextField);\n            public GUIStyle clickDragFloatFieldRight = new GUIStyle(EditorStyles.miniTextField);\n            public GUIStyle clickDragFloatLabelLeft = new GUIStyle(EditorStyles.miniLabel);\n            public GUIStyle clickDragFloatLabelRight = new GUIStyle(EditorStyles.miniLabel);\n            public GUIStyle headerIcon = new GUIStyle();\n            public GUIStyle errorStyle = new GUIStyle(EditorStyles.wordWrappedLabel);\n            public GUIContent speedIcon = new GUIContent(EditorGUIUtility.IconContent(\"SpeedScale\"));\n            public GUIContent mirrorIcon = new GUIContent(EditorGUIUtility.IconContent(\"Mirror\"));\n            public Texture2D pointIcon = EditorGUIUtility.LoadIcon(\"blendKey\");\n            public Texture2D pointIconSelected = EditorGUIUtility.LoadIcon(\"blendKeySelected\");\n            public Texture2D pointIconOverlay = EditorGUIUtility.LoadIcon(\"blendKeyOverlay\");\n            public Texture2D samplerIcon = EditorGUIUtility.LoadIcon(\"blendSampler\");\n\n            public Color visBgColor;\n            public Color visWeightColor;\n            public Color visWeightShapeColor;\n            public Color visWeightLineColor;\n            public Color visPointColor;\n            public Color visPointEmptyColor;\n            public Color visPointOverlayColor;\n            public Color visSamplerColor;\n\n            public Styles()\n            {\n                errorStyle.alignment = TextAnchor.MiddleCenter;\n                speedIcon.tooltip = \"Changes animation speed.\";\n                mirrorIcon.tooltip = \"Mirror animation.\";\n                headerIcon.alignment = TextAnchor.MiddleCenter;\n\n                clickDragFloatFieldLeft.alignment = TextAnchor.MiddleLeft;\n                clickDragFloatFieldRight.alignment = TextAnchor.MiddleRight;\n                clickDragFloatLabelLeft.alignment = TextAnchor.MiddleLeft;\n                clickDragFloatLabelRight.alignment = TextAnchor.MiddleRight;\n\n                visBgColor          = !EditorGUIUtility.isProSkin ? new Color(0.95f, 0.95f, 1.00f)        : new Color(0.20f, 0.20f, 0.20f);\n                visWeightColor      = !EditorGUIUtility.isProSkin ? new Color(0.50f, 0.60f, 0.90f, 0.80f) : new Color(0.65f, 0.75f, 1.00f, 0.65f);\n                visWeightShapeColor = !EditorGUIUtility.isProSkin ? new Color(0.40f, 0.65f, 1.00f, 0.15f) : new Color(0.40f, 0.65f, 1.00f, 0.12f);\n                visWeightLineColor  = !EditorGUIUtility.isProSkin ? new Color(0    , 0    , 0    , 0.30f) : new Color(1    , 1    , 1    , 0.60f);\n                visPointColor       = new Color(0.50f, 0.70f, 1.00f);\n                visPointEmptyColor  = !EditorGUIUtility.isProSkin ? new Color(0.80f, 0.80f, 0.80f)        : new Color(0.60f, 0.60f, 0.60f);\n                visPointOverlayColor = !EditorGUIUtility.isProSkin ? new Color(0    , 0    , 0    , 0.20f) : new Color(1    , 1    , 1    , 0.40f);\n                visSamplerColor     = new Color(1.00f, 0.40f, 0.40f);\n            }\n        }\n        static Styles styles;\n        internal static AnimatorController currentController = null;\n        internal static Animator currentAnimator = null;\n        internal static BlendTree parentBlendTree = null;\n        internal static Action<BlendTree> blendParameterInputChanged = null;\n        private readonly int m_BlendAnimationID = \"BlendAnimationIDHash\".GetHashCode();\n        private readonly int m_ClickDragFloatID = \"ClickDragFloatIDHash\".GetHashCode();\n        private float m_DragAndDropDelta;\n        private float m_OriginMin;\n        private float m_OriginMax;\n        private UnityEditorInternal.ReorderableList m_ReorderableList;\n        private SerializedProperty m_Childs;\n        private SerializedProperty m_BlendParameter;\n        private SerializedProperty m_BlendParameterY;\n        private BlendTree m_BlendTree;\n        private SerializedProperty m_UseAutomaticThresholds;\n        private SerializedProperty m_NormalizedBlendValues;\n\n        private SerializedProperty m_MinThreshold;\n        private SerializedProperty m_MaxThreshold;\n        private SerializedProperty m_Name;\n\n        private SerializedProperty m_BlendType;\n\n        private AnimBool m_ShowGraph = new AnimBool();\n        private AnimBool m_ShowCompute = new AnimBool();\n        private AnimBool m_ShowAdjust = new AnimBool();\n        private bool m_ShowGraphValue = false;\n        private bool m_BlendValueManipulated = false;\n\n        private float[] m_Weights;\n        private const int kVisResolution = 64;\n        private Texture2D m_BlendTex = null;\n        private List<Texture2D> m_WeightTexs = new List<Texture2D>();\n        private string m_WarningMessage = null;\n\n        private PreviewBlendTree m_PreviewBlendTree;\n        private VisualizationBlendTree m_VisBlendTree;\n        private GameObject m_VisInstance = null;\n\n        private int ParameterCount { get { return m_BlendType.intValue > (int)BlendTreeType.Simple1D ? (m_BlendType.intValue < (int)BlendTreeType.Direct ? 2 : 0) : 1; } }\n\n        static internal void SetParameterValue(Animator animator, BlendTree blendTree, BlendTree parentBlendTree, string parameterName, float parameterValue)\n        {\n            bool liveLink = EditorApplication.isPlaying && animator != null && animator.enabled && animator.gameObject.activeInHierarchy;\n\n            if (liveLink)\n                animator.SetFloat(parameterName, parameterValue);\n\n            blendTree.SetInputBlendValue(parameterName, parameterValue);\n            if (blendParameterInputChanged != null)\n                blendParameterInputChanged(blendTree);\n\n            if (parentBlendTree != null)\n            {\n                parentBlendTree.SetInputBlendValue(parameterName, parameterValue);\n                if (blendParameterInputChanged != null)\n                    blendParameterInputChanged(parentBlendTree);\n            }\n        }\n\n        static internal float GetParameterValue(Animator animator, BlendTree blendTree, string parameterName)\n        {\n            bool liveLink = EditorApplication.isPlaying && animator != null && animator.enabled && animator.gameObject.activeInHierarchy;\n\n            if (liveLink)\n            {\n                return animator.GetFloat(parameterName);\n            }\n            else\n            {\n                return blendTree.GetInputBlendValue(parameterName);\n            }\n        }\n\n        public void OnEnable()\n        {\n            m_Name = serializedObject.FindProperty(\"m_Name\");\n            m_BlendParameter = serializedObject.FindProperty(\"m_BlendParameter\");\n            m_BlendParameterY = serializedObject.FindProperty(\"m_BlendParameterY\");\n            m_UseAutomaticThresholds = serializedObject.FindProperty(\"m_UseAutomaticThresholds\");\n            m_NormalizedBlendValues = serializedObject.FindProperty(\"m_NormalizedBlendValues\");\n            m_MinThreshold = serializedObject.FindProperty(\"m_MinThreshold\");\n            m_MaxThreshold = serializedObject.FindProperty(\"m_MaxThreshold\");\n            m_BlendType = serializedObject.FindProperty(\"m_BlendType\");\n        }\n\n        void Init()\n        {\n            if (styles == null)\n                styles = new Styles();\n            if (m_BlendTree == null)\n                m_BlendTree = target as BlendTree;\n            if (styles == null)\n                styles = new Styles();\n            if (m_PreviewBlendTree == null)\n                m_PreviewBlendTree = new PreviewBlendTree();\n            if (m_VisBlendTree == null)\n                m_VisBlendTree = new VisualizationBlendTree();\n            if (m_Childs == null)\n            {\n                m_Childs = serializedObject.FindProperty(\"m_Childs\");\n                m_ReorderableList = new UnityEditorInternal.ReorderableList(serializedObject, m_Childs);\n                m_ReorderableList.drawHeaderCallback = DrawHeader;\n                m_ReorderableList.drawElementCallback = DrawChild;\n                m_ReorderableList.onReorderCallback = EndDragChild;\n                m_ReorderableList.onAddDropdownCallback = AddButton;\n                m_ReorderableList.onRemoveCallback = RemoveButton;\n                if (m_BlendType.intValue == (int)BlendTreeType.Simple1D)\n                    SortByThreshold();\n                m_ShowGraphValue = m_BlendType.intValue == (int)BlendTreeType.Direct ? m_Childs.arraySize >= 1 : m_Childs.arraySize >= 2;\n                m_ShowGraph.value = m_ShowGraphValue;\n                m_ShowAdjust.value = AllMotions();\n                m_ShowCompute.value = !m_UseAutomaticThresholds.boolValue;\n\n                m_ShowGraph.valueChanged.AddListener(Repaint);\n                m_ShowAdjust.valueChanged.AddListener(Repaint);\n                m_ShowCompute.valueChanged.AddListener(Repaint);\n            }\n\n            m_PreviewBlendTree.Init(m_BlendTree, currentAnimator);\n\n            bool hasInitVisIntance = false;\n            if (m_VisInstance == null)\n            {\n                GameObject go = (GameObject)EditorGUIUtility.Load(\"Avatar/DefaultAvatar.fbx\");\n                m_VisInstance = (GameObject)EditorUtility.InstantiateForAnimatorPreview(go);\n\n                foreach (Renderer renderer in m_VisInstance.GetComponentsInChildren<Renderer>())\n                    renderer.enabled = false;\n\n                hasInitVisIntance = true;\n            }\n            m_VisBlendTree.Init(m_BlendTree, m_VisInstance.GetComponent<Animator>());\n\n            if (hasInitVisIntance &&\n                (m_BlendType.intValue == (int)BlendTreeType.SimpleDirectional2D ||\n                 m_BlendType.intValue == (int)BlendTreeType.FreeformDirectional2D ||\n                 m_BlendType.intValue == (int)BlendTreeType.FreeformCartesian2D))\n            {\n                UpdateBlendVisualization();\n                ValidatePositions();\n            }\n        }\n\n        internal override void OnHeaderIconGUI(Rect iconRect)\n        {\n            Texture2D icon = AssetPreview.GetMiniThumbnail(target);\n            GUI.Label(iconRect, icon);\n        }\n\n        internal override void OnHeaderTitleGUI(Rect titleRect, string header)\n        {\n            serializedObject.Update();\n\n            Rect textFieldRect = titleRect;\n            textFieldRect.height = EditorGUI.kSingleLineHeight;\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = m_Name.hasMultipleDifferentValues;\n            string newName = EditorGUI.DelayedTextField(textFieldRect, m_Name.stringValue, EditorStyles.textField);\n            EditorGUI.showMixedValue = false;\n            if (EditorGUI.EndChangeCheck() && !String.IsNullOrEmpty(newName))\n            {\n                foreach (Object obj in targets)\n                    ObjectNames.SetNameSmart(obj, newName);\n            }\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        internal override void OnHeaderControlsGUI()\n        {\n            EditorGUIUtility.labelWidth = 80;\n            serializedObject.Update();\n            EditorGUILayout.PropertyField(m_BlendType);\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        private List<string> CollectParameters(AnimatorController controller)\n        {\n            List<string> parameterList = new List<string>();\n            if (controller != null)\n            {\n                AnimatorControllerParameter[] parameters = controller.parameters;\n                for (int i = 0; i < parameters.Length; i++)\n                {\n                    AnimatorControllerParameter animatorParameter = parameters[i];\n                    // only deal with floats\n                    if (animatorParameter.type == AnimatorControllerParameterType.Float)\n                    {\n                        parameterList.Add(animatorParameter.name);\n                    }\n                }\n            }\n\n            return parameterList;\n        }\n\n        private void ParameterGUI()\n        {\n            EditorGUILayout.BeginHorizontal();\n\n            // Label\n            if (ParameterCount > 1)\n                EditorGUILayout.PrefixLabel(EditorGUIUtility.TempContent(\"Parameters\"));\n            else\n                EditorGUILayout.PrefixLabel(EditorGUIUtility.TempContent(\"Parameter\"));\n\n            serializedObject.Update();\n\n            // Available parameters\n            // Populate parameters list and find indexes of used blend parameters\n            string currentParameter = m_BlendTree.blendParameter;\n            string currentParameterY = m_BlendTree.blendParameterY;\n\n            List<string> parameters = CollectParameters(currentController);\n\n            EditorGUI.BeginChangeCheck();\n            currentParameter = EditorGUILayout.DelayedTextFieldDropDown(currentParameter, parameters.ToArray());\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_BlendParameter.stringValue = currentParameter;\n            }\n\n            if (ParameterCount > 1)\n            {\n                // Show second blend parameter\n                EditorGUI.BeginChangeCheck();\n                currentParameterY = EditorGUILayout.TextFieldDropDown(currentParameterY, parameters.ToArray());\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_BlendParameterY.stringValue = currentParameterY;\n                }\n            }\n\n            serializedObject.ApplyModifiedProperties();\n\n            EditorGUILayout.EndHorizontal();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            Init();\n            serializedObject.Update();\n\n            if (m_BlendType.intValue != (int)BlendTreeType.Direct)\n            {\n                // Parameters\n                ParameterGUI();\n            }\n\n            m_ShowGraphValue = m_BlendType.intValue == (int)BlendTreeType.Direct ? m_Childs.arraySize >= 1 : m_Childs.arraySize >= 2;\n            m_ShowGraph.target = m_ShowGraphValue;\n\n            m_UseAutomaticThresholds = serializedObject.FindProperty(\"m_UseAutomaticThresholds\");\n            GUI.enabled = true;\n            if (EditorGUILayout.BeginFadeGroup(m_ShowGraph.faded))\n            {\n                if (m_BlendType.intValue == (int)BlendTreeType.Simple1D)\n                {\n                    BlendGraph(EditorGUILayout.GetControlRect(false, 40, styles.background));\n                    ThresholdValues();\n                }\n                else if (m_BlendType.intValue == (int)BlendTreeType.Direct)\n                {\n                    for (int i = 0; i < m_BlendTree.recursiveBlendParameterCount; i++)\n                    {\n                        string eventName = m_BlendTree.GetRecursiveBlendParameter(i);\n                        float eventMin = m_BlendTree.GetRecursiveBlendParameterMin(i);\n                        float eventMax = m_BlendTree.GetRecursiveBlendParameterMax(i);\n\n                        EditorGUI.BeginChangeCheck();\n                        float eventValue = EditorGUILayout.Slider(eventName, GetParameterValue(currentAnimator, m_BlendTree, eventName), eventMin, eventMax);\n                        if (EditorGUI.EndChangeCheck())\n                            SetParameterValue(currentAnimator, m_BlendTree, parentBlendTree, eventName, eventValue);\n                    }\n                }\n                else // 2D blend tree types\n                {\n                    GUILayout.Space(1);\n                    GUILayout.BeginHorizontal();\n                    GUILayout.FlexibleSpace();\n                    Rect graphRect = GUILayoutUtility.GetAspectRect(1, GUILayout.MaxWidth(235));\n                    GUI.Label(new Rect(graphRect.x - 1, graphRect.y - 1, graphRect.width + 2, graphRect.height + 2), GUIContent.none, EditorStyles.textField);\n                    GUI.BeginGroup(graphRect);\n                    graphRect.x = 0;\n                    graphRect.y = 0;\n                    BlendGraph2D(graphRect);\n                    GUI.EndGroup();\n                    GUILayout.FlexibleSpace();\n                    GUILayout.EndHorizontal();\n                }\n\n                GUILayout.Space(5);\n            }\n\n            EditorGUILayout.EndFadeGroup();\n            if (m_ReorderableList != null)\n            {\n                m_ReorderableList.DoLayoutList();\n            }\n\n            if (m_BlendType.intValue == (int)BlendTreeType.Direct)\n            {\n                EditorGUILayout.PropertyField(m_NormalizedBlendValues, EditorGUIUtility.TempContent(\"Normalized Blend Values\"));\n            }\n\n            if (m_ShowGraphValue)\n            {\n                GUILayout.Space(10);\n                AutoCompute();\n            }\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        private void SetMinMaxThresholds()\n        {\n            float min = Mathf.Infinity;\n            float max = Mathf.NegativeInfinity;\n            for (int i = 0; i < m_Childs.arraySize; i++)\n            {\n                SerializedProperty child = m_Childs.GetArrayElementAtIndex(i);\n                SerializedProperty threshold = child.FindPropertyRelative(\"m_Threshold\");\n                min = (threshold.floatValue < min) ? threshold.floatValue : min;\n                max = (threshold.floatValue > max) ? threshold.floatValue : max;\n            }\n            m_MinThreshold.floatValue = m_Childs.arraySize > 0 ? min : 0;\n            m_MaxThreshold.floatValue = m_Childs.arraySize > 0 ? max : 1;\n        }\n\n        private void BoundBlendParameter(string paramName)\n        {\n            // Ensures that the blend parameter is bounded between the root blend tree min and max\n            if (parentBlendTree != null)\n            {\n                for (int i = 0; i < parentBlendTree.recursiveBlendParameterCount; ++i)\n                {\n                    if (parentBlendTree.GetRecursiveBlendParameter(i) != paramName)\n                        continue;\n\n                    float value = GetParameterValue(currentAnimator, m_BlendTree, paramName);\n                    float min = parentBlendTree.GetRecursiveBlendParameterMin(i);\n                    float max = parentBlendTree.GetRecursiveBlendParameterMax(i);\n                    value = Mathf.Clamp(value, min, max);\n                    SetParameterValue(currentAnimator, m_BlendTree, parentBlendTree, paramName, value);\n                }\n            }\n        }\n\n        private void ThresholdValues()\n        {\n            Rect r = EditorGUILayout.GetControlRect();\n            Rect r1 = r;\n            Rect r2 = r;\n            r1.width /= 4;\n            r2.width /= 4;\n            r2.x = r.x + r.width - r2.width;\n\n            float min = m_MinThreshold.floatValue;\n            float max = m_MaxThreshold.floatValue;\n\n            EditorGUI.BeginChangeCheck();\n            min = ClickDragFloat(r1, min);\n            max = ClickDragFloat(r2, max, true);\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                float newMin = Mathf.Min(min, max);\n                float newMax = Mathf.Max(min, max);\n\n                if (m_Childs.arraySize >= 2)\n                {\n                    // Get first and last threshold properties.\n                    SerializedProperty firstChild = m_Childs.GetArrayElementAtIndex(0);\n                    SerializedProperty lastChild = m_Childs.GetArrayElementAtIndex(m_Childs.arraySize - 1);\n                    SerializedProperty firstThreshold = firstChild.FindPropertyRelative(\"m_Threshold\");\n                    SerializedProperty lastThreshold = lastChild.FindPropertyRelative(\"m_Threshold\");\n\n                    // Store previous values.\n                    float previousMin = firstThreshold.floatValue;\n                    float previousMax = lastThreshold.floatValue;\n\n                    // Set the new thresholds.\n                    firstThreshold.floatValue = newMin;\n                    lastThreshold.floatValue = newMax;\n\n                    if (!m_UseAutomaticThresholds.boolValue)\n                    {\n                        // Since this isn't being automatically calculated, we need to scale the values.\n                        int arraySize = m_Childs.arraySize;\n                        for (int i = 1; i < arraySize - 1; ++i)\n                        {\n                            SerializedProperty child = m_Childs.GetArrayElementAtIndex(i);\n                            SerializedProperty threshold = child.FindPropertyRelative(\"m_Threshold\");\n                            float ratio = Mathf.InverseLerp(previousMin, previousMax, threshold.floatValue);\n                            threshold.floatValue = Mathf.Lerp(newMin, newMax, ratio);\n                        }\n                    }\n\n                    // Clamp the current blend value within the new boundaries.\n                    float blendValue = GetParameterValue(currentAnimator, m_BlendTree, m_BlendTree.blendParameter);\n                    blendValue = Mathf.Clamp(blendValue, newMin, newMax);\n                    SetParameterValue(currentAnimator, m_BlendTree, parentBlendTree, m_BlendTree.blendParameter, blendValue);\n                }\n\n                // Set the new min/max thresholds.\n                m_MinThreshold.floatValue = newMin;\n                m_MaxThreshold.floatValue = newMax;\n            }\n        }\n\n        private static bool s_ClickDragFloatDragged;\n        private static float s_ClickDragFloatDistance;\n        public float ClickDragFloat(Rect position, float value)\n        {\n            return ClickDragFloat(position, value, false);\n        }\n\n        public float ClickDragFloat(Rect position, float value, bool alignRight)\n        {\n            bool changed;\n\n            // TODO: Why does the cursor change to arrow when editing the text?\n\n            string allowedCharacters = \"inftynaeINFTYNAE0123456789.,-\";\n            int id = EditorGUIUtility.GetControlID(m_ClickDragFloatID, FocusType.Keyboard, position);\n            Event evt = Event.current;\n            string str;\n            switch (evt.type)\n            {\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl != id)\n                        break;\n                    evt.Use();\n                    if (position.Contains(evt.mousePosition) && !s_ClickDragFloatDragged)\n                    {\n                        EditorGUIUtility.editingTextField = true;\n                    }\n                    else\n                    {\n                        GUIUtility.keyboardControl = 0;\n                        GUIUtility.hotControl = 0;\n                        s_ClickDragFloatDragged = false;\n                    }\n                    break;\n                case EventType.MouseDown:\n                    if (GUIUtility.keyboardControl == id && EditorGUIUtility.editingTextField)\n                        break;\n                    if (position.Contains(evt.mousePosition))\n                    {\n                        evt.Use();\n                        s_ClickDragFloatDragged = false;\n                        s_ClickDragFloatDistance = 0f;\n                        GUIUtility.hotControl = id;\n                        GUIUtility.keyboardControl = id;\n                        EditorGUIUtility.editingTextField = false;\n                    }\n                    else\n                    {\n                        GUIUtility.keyboardControl = 0;\n                        GUIUtility.hotControl = 0;\n                        s_ClickDragFloatDragged = false;\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl != id || EditorGUIUtility.editingTextField)\n                        break;\n                    s_ClickDragFloatDistance += Mathf.Abs(HandleUtility.niceMouseDelta);\n                    if (s_ClickDragFloatDistance >= 5f)\n                    {\n                        s_ClickDragFloatDragged = true;\n                        value += HandleUtility.niceMouseDelta * .03f;\n                        value = MathUtils.RoundBasedOnMinimumDifference(value, .03f);\n                        GUI.changed = true;\n                    }\n                    evt.Use();\n                    break;\n            }\n\n            GUIStyle style = (GUIUtility.keyboardControl == id && EditorGUIUtility.editingTextField) ?\n                (alignRight ? styles.clickDragFloatFieldRight : styles.clickDragFloatFieldLeft) :\n                (alignRight ? styles.clickDragFloatLabelRight : styles.clickDragFloatLabelLeft);\n            if (GUIUtility.keyboardControl == id)\n            {\n                if (!EditorGUI.s_RecycledEditor.IsEditingControl(id))\n                {\n                    str = EditorGUI.s_RecycledCurrentEditingString = value.ToString(\"g7\", CultureInfo.InvariantCulture.NumberFormat);\n                }\n                else\n                {\n                    str = EditorGUI.s_RecycledCurrentEditingString;\n                    if (evt.type == EventType.ValidateCommand && evt.commandName == EventCommandNames.UndoRedoPerformed)\n                        str = value.ToString(\"g7\", CultureInfo.InvariantCulture.NumberFormat);\n                }\n\n                str = EditorGUI.DoTextField(EditorGUI.s_RecycledEditor, id, position, str, style , allowedCharacters, out changed, false, false, false);\n                if (changed)\n                {\n                    GUI.changed = true;\n                    EditorGUI.s_RecycledCurrentEditingString = str;\n                    string lowered = str.ToLower();\n                    if (lowered == \"inf\" || lowered == \"infinity\")\n                    {\n                        value = Mathf.Infinity;\n                    }\n                    else if (lowered == \"-inf\" || lowered == \"-infinity\")\n                    {\n                        value = Mathf.NegativeInfinity;\n                    }\n                    else\n                    {\n                        str = str.Replace(',', '.');\n                        if (!float.TryParse(str, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out value))\n                        {\n                            value = 0;\n                            return value;\n                        }\n                        if (System.Single.IsNaN(value))\n                            value = 0;\n                    }\n                }\n            }\n            else\n            {\n                str = value.ToString(\"g7\", CultureInfo.InvariantCulture.NumberFormat);\n                str = EditorGUI.DoTextField(EditorGUI.s_RecycledEditor, id, position, str, style, allowedCharacters, out changed, false, false, false);\n            }\n            return value;\n        }\n\n        private void BlendGraph(Rect area)\n        {\n            // Adjust padding for rect\n            // (This is normally not needed anymore, but this style has some overdraw that needs to be compensated.)\n            area.xMin += 1;\n            area.xMax -= 1;\n\n            int sliderId = GUIUtility.GetControlID(m_BlendAnimationID, FocusType.Passive);\n\n            // get points array from child objects\n            int childCount = m_Childs.arraySize;\n            float[] points = new float[childCount];\n            for (int i = 0; i < childCount; i++)\n            {\n                SerializedProperty child = m_Childs.GetArrayElementAtIndex(i);\n                SerializedProperty threshold = child.FindPropertyRelative(\"m_Threshold\");\n                points[i] = threshold.floatValue;\n            }\n\n            // move points to GUI space\n            float min = Mathf.Min(points);\n            float max = Mathf.Max(points);\n            for (int i = 0; i < points.Length; i++)\n            {\n                points[i] = area.x + (Mathf.InverseLerp(min, max, points[i]) * area.width);\n            }\n\n            // get blend bar info\n            string currentParameter = m_BlendTree.blendParameter;\n            float blendBar = area.x + (Mathf.InverseLerp(min, max, GetParameterValue(currentAnimator, m_BlendTree, currentParameter)) * area.width);\n            Rect barRect = new Rect(blendBar - 4f, area.y, 9f, 42f);\n\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(sliderId))\n            {\n                case EventType.Repaint:\n                    styles.background.Draw(area, GUIContent.none, false, false, false, false);\n                    if (m_Childs.arraySize >= 2)\n                    {\n                        for (int i = 0; i < points.Length; i++)\n                        {\n                            // draw the animation triangle\n                            float last = (i == 0) ? points[i] : points[i - 1];\n                            float next = (i == points.Length - 1) ? points[i] : points[i + 1];\n                            bool drawSelected = (m_ReorderableList.index == i);\n                            DrawAnimation(points[i], last, next, drawSelected, area);\n                        }\n                        Color oldColor = Handles.color;\n                        Handles.color = new Color(0f, 0f, 0f, 0.25f);\n                        Handles.DrawLine(new Vector3(area.x, area.y + area.height, 0f), new Vector3(area.x + area.width, area.y + area.height, 0f));\n                        Handles.color = oldColor;\n                        // draw the current input bar\n                        styles.blendPosition.Draw(barRect, GUIContent.none, false, false, false, false);\n                    }\n                    else\n                    {\n                        GUI.Label(area, EditorGUIUtility.TempContent(\"Please Add Motion Fields or Blend Trees\"), styles.errorStyle);\n                    }\n                    break;\n                case EventType.MouseDown:\n                    float curBlendValue = 0.0f;\n                    if (barRect.Contains(evt.mousePosition))\n                    {\n                        evt.Use();\n                        GUIUtility.hotControl = sliderId;\n                        m_BlendValueManipulated = true;\n\n                        // Get current blend value.\n                        curBlendValue = GetParameterValue(currentAnimator, m_BlendTree, currentParameter);\n                    }\n                    else if (area.Contains(evt.mousePosition))\n                    {\n                        evt.Use();\n                        GUIUtility.hotControl = sliderId;\n                        GUIUtility.keyboardControl = sliderId;\n\n                        // determine closest animation or blend tree\n                        float clickPosition = evt.mousePosition.x;\n                        float distance = Mathf.Infinity;\n\n                        m_BlendValueManipulated = true;\n                        for (int i = 0; i < points.Length; i++)\n                        {\n                            float last = (i == 0) ? points[i] : points[i - 1];\n                            float next = (i == points.Length - 1) ? points[i] : points[i + 1];\n                            if (Mathf.Abs(clickPosition - points[i]) < distance)\n                            {\n                                if (clickPosition < next && clickPosition > last)\n                                {\n                                    distance = Mathf.Abs(clickPosition - points[i]);\n                                    m_ReorderableList.index = i;\n                                    m_BlendValueManipulated = false;\n                                }\n                            }\n                        }\n\n                        // turn off automatic thresholds\n                        m_UseAutomaticThresholds.boolValue = false;\n\n                        // Get current blend value.\n                        if (!m_BlendValueManipulated)\n                        {\n                            SerializedProperty child = m_Childs.GetArrayElementAtIndex(m_ReorderableList.index);\n                            SerializedProperty threshold = child.FindPropertyRelative(\"m_Threshold\");\n                            curBlendValue = threshold.floatValue;\n                        }\n                    }\n\n                    // Get drag'n'drop infos.\n                    float mouseBlendValue = (evt.mousePosition.x - area.x) / area.width;\n                    mouseBlendValue = Mathf.LerpUnclamped(min, max, mouseBlendValue);\n                    m_DragAndDropDelta = mouseBlendValue - curBlendValue;\n                    m_OriginMin = min;\n                    m_OriginMax = max;\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl != sliderId)\n                        break;\n\n                    evt.Use();\n\n                    // Convert mouse position to blend space.\n                    float newMouseBlendValue = (evt.mousePosition.x - area.x) / area.width;\n                    newMouseBlendValue = Mathf.LerpUnclamped(m_OriginMin, m_OriginMax, newMouseBlendValue);\n                    float newBlendValue = newMouseBlendValue - m_DragAndDropDelta;\n\n                    if (m_BlendValueManipulated)\n                    {\n                        // the user is dragging the blend position\n                        newBlendValue = Mathf.Clamp(newBlendValue, min, max);\n                        SetParameterValue(currentAnimator, m_BlendTree, parentBlendTree, currentParameter, newBlendValue);\n                    }\n                    else\n                    {\n                        // set the new threshold based on mousePosition\n                        SerializedProperty child = m_Childs.GetArrayElementAtIndex(m_ReorderableList.index);\n                        SerializedProperty threshold = child.FindPropertyRelative(\"m_Threshold\");\n\n                        // get neighboring thresholds\n                        SerializedProperty lastChild = (m_ReorderableList.index <= 0) ?  child : m_Childs.GetArrayElementAtIndex(m_ReorderableList.index - 1);\n                        SerializedProperty nextChild = (m_ReorderableList.index == m_Childs.arraySize - 1) ?  child : m_Childs.GetArrayElementAtIndex(m_ReorderableList.index + 1);\n                        SerializedProperty lastThreshold = lastChild.FindPropertyRelative(\"m_Threshold\");\n                        SerializedProperty nextThreshold = nextChild.FindPropertyRelative(\"m_Threshold\");\n\n                        // change threshold value\n                        threshold.floatValue = newBlendValue;\n\n                        // reorder if dragged beyond range\n                        if (threshold.floatValue < lastThreshold.floatValue && m_ReorderableList.index != 0)\n                        {\n                            m_Childs.MoveArrayElement(m_ReorderableList.index, m_ReorderableList.index - 1);\n                            m_ReorderableList.index -= 1;\n                        }\n                        if (threshold.floatValue > nextThreshold.floatValue && m_ReorderableList.index < m_Childs.arraySize - 1)\n                        {\n                            m_Childs.MoveArrayElement(m_ReorderableList.index, m_ReorderableList.index + 1);\n                            m_ReorderableList.index += 1;\n                        }\n\n                        // snap to near thresholds\n                        float snapThreshold = 3f * ((max - min) / area.width);\n                        if (threshold.floatValue - lastThreshold.floatValue <= snapThreshold)\n                        {\n                            threshold.floatValue = lastThreshold.floatValue;\n                        }\n                        else if (nextThreshold.floatValue - threshold.floatValue <= snapThreshold)\n                        {\n                            threshold.floatValue = nextThreshold.floatValue;\n                        }\n                        SetMinMaxThresholds();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == sliderId)\n                    {\n                        evt.Use();\n                        GUIUtility.hotControl = 0;\n                        m_BlendValueManipulated = true;\n                    }\n                    break;\n            }\n        }\n\n        private void UpdateBlendVisualization()\n        {\n            Vector2[] points = GetActiveMotionPositions();\n\n            if (m_BlendTex == null)\n            {\n                m_BlendTex = new Texture2D(kVisResolution, kVisResolution, TextureFormat.RGBA32, false);\n                m_BlendTex.hideFlags = HideFlags.HideAndDontSave;\n                m_BlendTex.wrapMode = TextureWrapMode.Clamp;\n            }\n            while (m_WeightTexs.Count < points.Length)\n            {\n                Texture2D tex = new Texture2D(kVisResolution, kVisResolution, TextureFormat.RGBA32, false);\n                tex.wrapMode = TextureWrapMode.Clamp;\n                tex.hideFlags = HideFlags.HideAndDontSave;\n                m_WeightTexs.Add(tex);\n            }\n            while (m_WeightTexs.Count > points.Length)\n            {\n                DestroyImmediate(m_WeightTexs[m_WeightTexs.Count - 1]);\n                m_WeightTexs.RemoveAt(m_WeightTexs.Count - 1);\n            }\n\n            // Calculate min and max for all the points\n            if (GUIUtility.hotControl == 0)\n                m_BlendRect = Get2DBlendRect(GetMotionPositions());\n\n            m_VisBlendTree.Reset();\n\n            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();\n            watch.Start();\n            Texture2D[] textures = m_WeightTexs.ToArray();\n            // While dragging, only update the weight texture that's being dragged.\n            if (GUIUtility.hotControl != 0 && !m_BlendValueManipulated)\n            {\n                int[] indices = GetMotionToActiveMotionIndices();\n                for (int i = 0; i < textures.Length; i++)\n                    if (indices[m_ReorderableList.index] != i)\n                        textures[i] = null;\n            }\n            UnityEditorInternal.BlendTreePreviewUtility.CalculateBlendTexture(m_VisBlendTree.animator, 0, m_VisBlendTree.animator.GetCurrentAnimatorStateInfo(0).fullPathHash,\n                m_BlendTex, textures, m_BlendRect);\n            watch.Stop();\n\n            //Debug.Log (\"CalculateBlendTexture took \"+watch.ElapsedMilliseconds+\" ms\");\n        }\n\n        private Vector2[] GetMotionPositions()\n        {\n            int childCount = m_Childs.arraySize;\n            Vector2[] points = new Vector2[childCount];\n            for (int i = 0; i < childCount; i++)\n            {\n                SerializedProperty child = m_Childs.GetArrayElementAtIndex(i);\n                SerializedProperty position = child.FindPropertyRelative(\"m_Position\");\n                points[i] = position.vector2Value;\n            }\n            return points;\n        }\n\n        private Vector2[] GetActiveMotionPositions()\n        {\n            List<Vector2> points = new List<Vector2>();\n            int childCount = m_Childs.arraySize;\n            for (int i = 0; i < childCount; i++)\n            {\n                SerializedProperty child = m_Childs.GetArrayElementAtIndex(i);\n                SerializedProperty motion = child.FindPropertyRelative(\"m_Motion\");\n                if (motion.objectReferenceValue != null)\n                {\n                    SerializedProperty position = child.FindPropertyRelative(\"m_Position\");\n                    points.Add(position.vector2Value);\n                }\n            }\n            return points.ToArray();\n        }\n\n        private int[] GetMotionToActiveMotionIndices()\n        {\n            int childCount = m_Childs.arraySize;\n            int[] indices = new int[childCount];\n            int activeMotion = 0;\n            for (int i = 0; i < childCount; i++)\n            {\n                SerializedProperty child = m_Childs.GetArrayElementAtIndex(i);\n                SerializedProperty motion = child.FindPropertyRelative(\"m_Motion\");\n                if (motion.objectReferenceValue == null)\n                    indices[i] = -1;\n                else\n                {\n                    indices[i] = activeMotion;\n                    activeMotion++;\n                }\n            }\n            return indices;\n        }\n\n        private Rect Get2DBlendRect(Vector2[] points)\n        {\n            Vector2 center = Vector2.zero;\n            float maxDist = 0;\n\n            if (points.Length == 0)\n            {\n                return new Rect();\n            }\n\n            if (m_BlendType.intValue == (int)BlendTreeType.FreeformCartesian2D)\n            {\n                // Make min and max rect with center at the bounds center\n                Vector2 min = points[0];\n                Vector2 max = points[0];\n                for (int i = 1; i < points.Length; i++)\n                {\n                    max.x = Mathf.Max(max.x, points[i].x);\n                    max.y = Mathf.Max(max.y, points[i].y);\n                    min.x = Mathf.Min(min.x, points[i].x);\n                    min.y = Mathf.Min(min.y, points[i].y);\n                }\n                center = (min + max) * 0.5f;\n                maxDist = Mathf.Max(max.x - min.x, max.y - min.y) * 0.5f;\n            }\n            else\n            {\n                // Make min and max a rect with the origin in the center\n                for (int i = 0; i < points.Length; i++)\n                {\n                    maxDist = Mathf.Max(maxDist, points[i].x);\n                    maxDist = Mathf.Max(maxDist, -points[i].x);\n                    maxDist = Mathf.Max(maxDist, points[i].y);\n                    maxDist = Mathf.Max(maxDist, -points[i].y);\n                }\n            }\n\n            if (maxDist == 0)\n                maxDist = 1;\n            maxDist *= 1.35f;\n            return new Rect(center.x - maxDist, center.y - maxDist, maxDist * 2, maxDist * 2);\n        }\n\n        private Rect m_BlendRect;\n        private int m_SelectedPoint = -1;\n        private bool s_DraggingPoint = false;\n\n        private float ConvertFloat(float input, float fromMin, float fromMax, float toMin, float toMax)\n        {\n            float lerp = (input - fromMin) / (fromMax - fromMin);\n            return toMin * (1 - lerp) + toMax * lerp;\n        }\n\n        private void BlendGraph2D(Rect area)\n        {\n            if (m_VisBlendTree.controllerDirty)\n            {\n                UpdateBlendVisualization();\n                ValidatePositions();\n            }\n\n            // Get points array from child objects\n            Vector2[] points = GetMotionPositions();\n            int[] presences = GetMotionToActiveMotionIndices();\n\n            Vector2 min = new Vector2(m_BlendRect.xMin, m_BlendRect.yMin);\n            Vector2 max = new Vector2(m_BlendRect.xMax, m_BlendRect.yMax);\n\n            // Move points to GUI space\n            for (int i = 0; i < points.Length; i++)\n            {\n                points[i].x = ConvertFloat(points[i].x, min.x, max.x, area.xMin, area.xMax);\n                points[i].y = ConvertFloat(points[i].y, min.y, max.y, area.yMax, area.yMin);\n            }\n\n            // Get the input blend info\n            string currentParameterX = m_BlendTree.blendParameter;\n            string currentParameterY = m_BlendTree.blendParameterY;\n            float inputX = GetParameterValue(currentAnimator, m_BlendTree, currentParameterX);\n            float inputY = GetParameterValue(currentAnimator, m_BlendTree, currentParameterY);\n\n            // Get child weights\n            int activeChildCount = GetActiveMotionPositions().Length;\n            if (m_Weights == null || activeChildCount != m_Weights.Length)\n                m_Weights = new float[activeChildCount];\n\n            UnityEditorInternal.BlendTreePreviewUtility.CalculateRootBlendTreeChildWeights(m_VisBlendTree.animator, 0, m_VisBlendTree.animator.GetCurrentAnimatorStateInfo(0).fullPathHash, m_Weights, inputX, inputY);\n\n            // Move input into GUI space\n            inputX = area.x + Mathf.InverseLerp(min.x, max.x, inputX) * area.width;\n            inputY = area.y + (1 - Mathf.InverseLerp(min.y, max.y, inputY)) * area.height;\n            Rect inputRect = new Rect(inputX - 5, inputY - 5, 11, 11);\n\n            int drag2dId = GUIUtility.GetControlID(m_BlendAnimationID, FocusType.Passive);\n\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(drag2dId))\n            {\n                case EventType.Repaint:\n                    GUI.color = styles.visBgColor;\n                    GUI.DrawTexture(area, EditorGUIUtility.whiteTexture);\n\n                    // Draw weight texture\n                    if (m_BlendValueManipulated || m_ReorderableList.index >= presences.Length)\n                    {\n                        Color col = styles.visWeightColor;\n                        col.a *= 0.75f;\n                        GUI.color = col;\n                        GUI.DrawTexture(area, m_BlendTex);\n                    }\n                    else if (presences[m_ReorderableList.index] >= 0)\n                    {\n                        GUI.color = styles.visWeightColor;\n                        GUI.DrawTexture(area, m_WeightTexs[presences[m_ReorderableList.index]]);\n                    }\n                    GUI.color = Color.white;\n\n                    // Draw the weight circles\n                    if (!s_DraggingPoint)\n                    {\n                        for (int i = 0; i < points.Length; i++)\n                            if (presences[i] >= 0)\n                                DrawWeightShape(points[i], m_Weights[presences[i]], 0);\n                        for (int i = 0; i < points.Length; i++)\n                            if (presences[i] >= 0)\n                                DrawWeightShape(points[i], m_Weights[presences[i]], 1);\n                    }\n\n                    // Draw the animation points\n                    for (int i = 0; i < points.Length; i++)\n                    {\n                        Rect pointRect = new Rect(points[i].x - 6, points[i].y - 6, 13, 13);\n                        bool drawSelected = (m_ReorderableList.index == i);\n\n                        if (presences[i] < 0)\n                            GUI.color = styles.visPointEmptyColor;\n                        else\n                            GUI.color = styles.visPointColor;\n                        GUI.DrawTexture(pointRect, drawSelected ? styles.pointIconSelected : styles.pointIcon);\n\n                        if (drawSelected)\n                        {\n                            GUI.color = styles.visPointOverlayColor;\n                            GUI.DrawTexture(pointRect, styles.pointIconOverlay);\n                        }\n                    }\n\n                    // Draw the input (sampler) point\n                    if (!s_DraggingPoint)\n                    {\n                        GUI.color = styles.visSamplerColor;\n                        GUI.DrawTexture(inputRect, styles.samplerIcon);\n                    }\n                    GUI.color = Color.white;\n\n                    break;\n                case EventType.MouseDown:\n                    if (inputRect.Contains(evt.mousePosition))\n                    {\n                        evt.Use();\n                        GUIUtility.hotControl = drag2dId;\n                        m_SelectedPoint = -1;\n                    }\n                    else if (area.Contains(evt.mousePosition))\n                    {\n                        m_BlendValueManipulated = true;\n\n                        for (int i = 0; i < points.Length; i++)\n                        {\n                            Rect pointRect = new Rect(points[i].x - 4, points[i].y - 4, 9, 9);\n                            if (pointRect.Contains(evt.mousePosition))\n                            {\n                                evt.Use();\n                                GUIUtility.hotControl = drag2dId;\n                                m_SelectedPoint = i;\n                                m_ReorderableList.index = i;\n                                m_BlendValueManipulated = false;\n                            }\n                        }\n\n                        // Use in any case so we deselect point and get repaint.\n                        evt.Use();\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl != drag2dId)\n                        break;\n\n                    if (m_SelectedPoint == -1)\n                    {\n                        // Convert mouse position to point in blend space\n                        Vector2 mousePosition;\n                        mousePosition.x = ConvertFloat(evt.mousePosition.x, area.xMin, area.xMax, min.x, max.x);\n                        mousePosition.y = ConvertFloat(evt.mousePosition.y, area.yMax, area.yMin, min.y, max.y);\n\n                        // Set blend values\n                        SetParameterValue(currentAnimator, m_BlendTree, parentBlendTree, currentParameterX, mousePosition.x);\n                        SetParameterValue(currentAnimator, m_BlendTree, parentBlendTree, currentParameterY, mousePosition.y);\n\n                        evt.Use();\n                    }\n                    else\n                    {\n                        for (int i = 0; i < points.Length; i++)\n                        {\n                            if (m_SelectedPoint == i)\n                            {\n                                // Convert mouse position to point in blend space\n                                Vector2 mousePosition;\n                                mousePosition.x = ConvertFloat(evt.mousePosition.x, area.xMin, area.xMax, min.x, max.x);\n                                mousePosition.y = ConvertFloat(evt.mousePosition.y, area.yMax, area.yMin, min.y, max.y);\n\n                                float minDiff = (max.x - min.x) / area.width;\n                                mousePosition.x = MathUtils.RoundBasedOnMinimumDifference(mousePosition.x, minDiff);\n                                mousePosition.y = MathUtils.RoundBasedOnMinimumDifference(mousePosition.y, minDiff);\n                                mousePosition.x = Mathf.Clamp(mousePosition.x, -10000, 10000);\n                                mousePosition.y = Mathf.Clamp(mousePosition.y, -10000, 10000);\n\n                                SerializedProperty child = m_Childs.GetArrayElementAtIndex(i);\n                                SerializedProperty position = child.FindPropertyRelative(\"m_Position\");\n                                position.vector2Value = mousePosition;\n\n                                evt.Use();\n                                s_DraggingPoint = true;\n                            }\n                        }\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl != drag2dId)\n                        break;\n\n                    evt.Use();\n                    GUIUtility.hotControl = 0;\n                    s_DraggingPoint = false;\n\n                    break;\n            }\n\n            // Draw message\n            if (m_ReorderableList.index >= 0 && m_ReorderableList.index < presences.Length && presences[m_ReorderableList.index] < 0)\n                ShowHelp(area, EditorGUIUtility.TempContent(\"The selected child has no Motion assigned.\"));\n            else if (m_WarningMessage != null)\n                ShowHelp(area, EditorGUIUtility.TempContent(m_WarningMessage));\n        }\n\n        private void ShowHelp(Rect area, GUIContent content)\n        {\n            float height = EditorStyles.helpBox.CalcHeight(content, area.width);\n            GUI.Label(new Rect(area.x, area.y, area.width, height), content, EditorStyles.helpBox);\n        }\n\n        private void ValidatePositions()\n        {\n            m_WarningMessage = null;\n            Vector2[] points = GetMotionPositions();\n\n            // Check for duplicate positions (relevant for all blend types)\n            bool duplicatePositions = m_BlendRect.width == 0 || m_BlendRect.height == 0;\n            for (int i = 0; i < points.Length; i++)\n            {\n                for (int j = 0; j < i && !duplicatePositions; j++)\n                {\n                    if (((points[i] - points[j]) / m_BlendRect.height).sqrMagnitude < 0.0001f)\n                    {\n                        duplicatePositions = true;\n                        break;\n                    }\n                }\n            }\n            if (duplicatePositions)\n            {\n                m_WarningMessage = \"Two or more of the positions are too close to each other.\";\n                return;\n            }\n\n            // Checks for individual blend types below\n\n            if (m_BlendType.intValue == (int)BlendTreeType.SimpleDirectional2D)\n            {\n                List<float> angles = points.Where(e => e != Vector2.zero).Select(e => Mathf.Atan2(e.y, e.x)).OrderBy(e => e).ToList();\n                float maxAngle = 0;\n                float minAngle = 180;\n                for (int i = 0; i < angles.Count; i++)\n                {\n                    float angle = angles[(i + 1) % angles.Count] - angles[i];\n                    if (i == angles.Count - 1)\n                        angle += Mathf.PI * 2;\n                    if (angle > maxAngle)\n                        maxAngle = angle;\n                    if (angle < minAngle)\n                        minAngle = angle;\n                }\n                if (maxAngle * Mathf.Rad2Deg >= 180)\n                    m_WarningMessage = \"Simple Directional blend should have motions with directions less than 180 degrees apart.\";\n                else if (minAngle * Mathf.Rad2Deg < 2)\n                    m_WarningMessage = \"Simple Directional blend should not have multiple motions in almost the same direction.\";\n            }\n            else if (m_BlendType.intValue == (int)BlendTreeType.FreeformDirectional2D)\n            {\n                // Check if this blend type has a motion in the center.\n                bool hasCenter = false;\n                for (int i = 0; i < points.Length; i++)\n                {\n                    if (points[i] == Vector2.zero)\n                    {\n                        hasCenter = true;\n                        break;\n                    }\n                }\n                if (!hasCenter)\n                    m_WarningMessage = \"Freeform Directional blend should have one motion at position (0,0) to avoid discontinuities.\";\n            }\n        }\n\n        private int kNumCirclePoints = 20;\n        private void DrawWeightShape(Vector2 point, float weight, int pass)\n        {\n            if (weight <= 0)\n                return;\n            point.x = Mathf.Round(point.x);\n            point.y = Mathf.Round(point.y);\n            float radius = 20 * Mathf.Sqrt(weight);\n\n            // Calculate points in a circle\n            Vector3[] points = new Vector3[kNumCirclePoints + 2];\n            for (int i = 0; i < kNumCirclePoints; i++)\n            {\n                float v = (float)i / kNumCirclePoints;\n                points[i + 1] = new Vector3(point.x + 0.5f, point.y + 0.5f, 0) + new Vector3(Mathf.Sin(v * 2 * Mathf.PI), Mathf.Cos(v * 2 * Mathf.PI), 0) * radius;\n            }\n            // First and last point have to meet each other in a straight line; otherwise we'll get a gap\n            points[0] = points[kNumCirclePoints + 1] = (points[1] + points[kNumCirclePoints]) * 0.5f;\n\n            if (pass == 0)\n            {\n                // Draw disc\n                Handles.color = styles.visWeightShapeColor;\n                Handles.DrawSolidDisc(point + new Vector2(0.5f, 0.5f), -Vector3.forward, radius);\n            }\n            else\n            {\n                // Draw outline\n                Handles.color = styles.visWeightLineColor;\n                Handles.DrawAAPolyLine(points);\n            }\n        }\n\n        private void DrawAnimation(float val, float min, float max, bool selected, Rect area)\n        {\n            float top = area.y;\n            Rect leftRect = new Rect(min, top, val - min, area.height);\n            Rect rightRect = new Rect(val, top, max - val, area.height);\n            styles.triangleLeft.Draw(leftRect, selected, selected, false, false);\n            styles.triangleRight.Draw(rightRect, selected, selected, false, false);\n            area.height -= 1;\n            Color oldColor = Handles.color;\n            Color newColor = selected ? new Color(1f, 1f, 1f, 0.6f) : new Color(1f, 1f, 1f, 0.4f);\n            Handles.color = newColor;\n            if (selected)\n                Handles.DrawLine(new Vector3(val, top, 0), new Vector3(val, top + area.height, 0));\n            Vector3[] points = new Vector3[2] {new Vector3(min, top + area.height, 0f), new Vector3(val, top, 0f)};\n            Handles.DrawAAPolyLine(points);\n            points = new Vector3[2] {new Vector3(val, top, 0f), new Vector3(max, top + area.height, 0f)};\n            Handles.DrawAAPolyLine(points);\n            Handles.color = oldColor;\n        }\n\n        public void EndDragChild(UnityEditorInternal.ReorderableList list)\n        {\n            List<float> dragThresholds = new List<float>();\n            for (int i = 0; i < m_Childs.arraySize; i++)\n            {\n                SerializedProperty child = m_Childs.GetArrayElementAtIndex(i);\n                SerializedProperty threshold = child.FindPropertyRelative(\"m_Threshold\");\n                dragThresholds.Add(threshold.floatValue);\n            }\n            dragThresholds.Sort();\n            for (int i = 0; i < m_Childs.arraySize; i++)\n            {\n                SerializedProperty child = m_Childs.GetArrayElementAtIndex(i);\n                SerializedProperty threshold = child.FindPropertyRelative(\"m_Threshold\");\n                threshold.floatValue = dragThresholds[i];\n            }\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        private void DrawHeader(Rect headerRect)\n        {\n            headerRect.xMin += 14; // Ignore width used by drag-handles while calculating column widths.\n            headerRect.y++;\n            headerRect.height = 16;\n\n            Rect[] rects = GetRowRects(headerRect, m_BlendType.intValue);\n            int col = 0;\n\n            rects[col].xMin = rects[col].xMin - 14; // Make first column extend into space of drag-handles.\n            GUI.Label(rects[col], EditorGUIUtility.TempContent(\"Motion\"), EditorStyles.label);\n            col++;\n            if (m_Childs.arraySize >= 1)\n            {\n                if (m_BlendType.intValue == (int)BlendTreeType.Simple1D)\n                {\n                    GUI.Label(rects[col], EditorGUIUtility.TempContent(\"Threshold\"), EditorStyles.label);\n                    col++;\n                }\n                else if (m_BlendType.intValue == (int)BlendTreeType.Direct)\n                {\n                    GUI.Label(rects[col], EditorGUIUtility.TempContent(\"Parameter\"), EditorStyles.label);\n                    col++;\n                }\n                else\n                {\n                    GUI.Label(rects[col], EditorGUIUtility.TempContent(\"Pos X\"), EditorStyles.label);\n                    col++;\n                    GUI.Label(rects[col], EditorGUIUtility.TempContent(\"Pos Y\"), EditorStyles.label);\n                    col++;\n                }\n\n                GUI.Label(rects[col], styles.speedIcon, styles.headerIcon);\n                col++;\n                GUI.Label(rects[col], styles.mirrorIcon, styles.headerIcon);\n            }\n        }\n\n        public void AddButton(Rect rect, UnityEditorInternal.ReorderableList list)\n        {\n            GenericMenu menu = new GenericMenu();\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Add Motion Field\"), false, AddChildAnimation);\n            menu.AddItem(EditorGUIUtility.TempContent(\"New Blend Tree\"), false, AddBlendTreeCallback);\n            menu.Popup(rect, 0);\n        }\n\n        public static bool DeleteBlendTreeDialog(string toDelete)\n        {\n            string title = \"Delete selected Blend Tree asset?\";\n\n            string subTitle = toDelete;\n\n            return EditorUtility.DisplayDialog(title, subTitle, \"Delete\", \"Cancel\");\n        }\n\n        public void RemoveButton(UnityEditorInternal.ReorderableList list)\n        {\n            SerializedProperty child = m_Childs.GetArrayElementAtIndex(list.index);\n            SerializedProperty motion = child.FindPropertyRelative(\"m_Motion\");\n\n            Motion actualMotion = motion.objectReferenceValue as Motion;\n\n            if (actualMotion == null || DeleteBlendTreeDialog(actualMotion.name))\n            {\n                m_Childs.DeleteArrayElementAtIndex(list.index);\n                if (list.index >= m_Childs.arraySize)\n                    list.index = m_Childs.arraySize - 1;\n                SetMinMaxThresholds();\n\n                serializedObject.ApplyModifiedProperties();\n            }\n        }\n\n        private Rect[] GetRowRects(Rect r, int blendType)\n        {\n            int rowCount = blendType > (int)BlendTreeType.Simple1D && blendType < (int)BlendTreeType.Direct ? 2 : 1;\n            Rect[] rects = new Rect[3 + rowCount];\n\n            float remainingWidth = r.width;\n            float mirrorWidth = 16;\n            remainingWidth -= mirrorWidth;\n            remainingWidth -= 8 + 8 + 8 + (4 * (rowCount - 1));\n            float numberWidth = Mathf.FloorToInt(remainingWidth * 0.2f);\n            float motionWidth = remainingWidth - numberWidth * (rowCount + 1);\n\n            float x = r.x;\n            int col = 0;\n\n            rects[col] = new Rect(x, r.y, motionWidth, r.height);\n            x += motionWidth + 8;\n            col++;\n\n            for (int i = 0; i < rowCount; i++)\n            {\n                rects[col] = new Rect(x, r.y, numberWidth, r.height);\n                x += numberWidth + 4;\n                col++;\n            }\n            x += 4;\n\n            rects[col] = new Rect(x, r.y, numberWidth, r.height);\n            x += numberWidth + 8;\n            col++;\n\n            rects[col] = new Rect(x, r.y, mirrorWidth, r.height);\n\n            return rects;\n        }\n\n        public void DrawChild(Rect r, int index, bool isActive, bool isFocused)\n        {\n            SerializedProperty child = m_Childs.GetArrayElementAtIndex(index);\n            SerializedProperty motion = child.FindPropertyRelative(\"m_Motion\");\n\n            r.y++;\n            r.height = EditorGUI.kSingleLineHeight;\n            Rect[] rects = GetRowRects(r, m_BlendType.intValue);\n            int col = 0;\n\n            // show a property field for the motion clip\n            EditorGUI.BeginChangeCheck();\n\n            Motion prevMotion = m_BlendTree.children[index].motion;\n            EditorGUI.PropertyField(rects[col], motion, GUIContent.none);\n            col++;\n            if (EditorGUI.EndChangeCheck())\n            {\n                // [case 1028113] Delete previous Motion only if it serialized in the same asset file\n                if (prevMotion is BlendTree && prevMotion != (motion.objectReferenceValue as Motion) && MecanimUtilities.AreSameAsset(m_BlendTree, prevMotion))\n                {\n                    if (EditorUtility.DisplayDialog(\"Changing BlendTree will delete previous BlendTree\", \"You cannot undo this action.\", \"Delete\", \"Cancel\"))\n                    {\n                        MecanimUtilities.DestroyBlendTreeRecursive(prevMotion as BlendTree);\n                    }\n                    else\n                    {\n                        motion.objectReferenceValue = prevMotion;\n                    }\n                }\n            }\n\n            // use a delayed text field and force re-sort if value is manually changed\n            if (m_BlendType.intValue == (int)BlendTreeType.Simple1D)\n            {\n                // Threshold in 1D blending\n                SerializedProperty threshold = child.FindPropertyRelative(\"m_Threshold\");\n                using (new EditorGUI.DisabledScope(m_UseAutomaticThresholds.boolValue))\n                {\n                    float nr = threshold.floatValue;\n                    EditorGUI.BeginChangeCheck();\n                    nr = EditorGUI.DelayedFloatField(rects[col], \"\", nr, EditorStyles.textField);\n                    col++;\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        threshold.floatValue = nr;\n                        serializedObject.ApplyModifiedProperties();\n                        m_BlendTree.SortChildren();\n                        SetMinMaxThresholds();\n                        BoundBlendParameter(m_BlendTree.blendParameter);\n                        GUI.changed = true;\n                    }\n                }\n            }\n            else if (m_BlendType.intValue == (int)BlendTreeType.Direct)\n            {\n                List<string> parameters = CollectParameters(currentController);\n                Animations.ChildMotion[] childs = m_BlendTree.children;\n\n                string directParam = childs[index].directBlendParameter;\n\n                EditorGUI.BeginChangeCheck();\n                directParam = EditorGUI.TextFieldDropDown(rects[col], directParam, parameters.ToArray());\n                col++;\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    childs[index].directBlendParameter = directParam;\n                    m_BlendTree.children = childs;\n                }\n            }\n            else\n            {\n                // Position in 2D blending\n                SerializedProperty position = child.FindPropertyRelative(\"m_Position\");\n                Vector2 pos = position.vector2Value;\n                for (int i = 0; i < 2; i++)\n                {\n                    EditorGUI.BeginChangeCheck();\n                    float coord = EditorGUI.DelayedFloatField(rects[col], \"\", pos[i], EditorStyles.textField);\n                    col++;\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        pos[i] = Mathf.Clamp(coord, -10000, 10000);\n                        position.vector2Value = pos;\n                        serializedObject.ApplyModifiedProperties();\n                        BoundBlendParameter(i == 0 ? m_BlendTree.blendParameter : m_BlendTree.blendParameterY);\n                        GUI.changed = true;\n                    }\n                }\n            }\n\n            // If this is an animation, include the time scale.\n            if (motion.objectReferenceValue is AnimationClip)\n            {\n                SerializedProperty timeScale = child.FindPropertyRelative(\"m_TimeScale\");\n                float timeScaleValue = timeScale.floatValue;\n                EditorGUI.BeginChangeCheck();\n                timeScaleValue = EditorGUI.DelayedFloatField(rects[col], \"\", timeScaleValue, EditorStyles.textField);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    timeScale.floatValue = timeScaleValue;\n                    serializedObject.ApplyModifiedProperties();\n                    GUI.changed = true;\n                }\n            }\n            else\n            {\n                // Otherwise show disabled dummy field with default value of 1.\n                using (new EditorGUI.DisabledScope(true))\n                {\n                    EditorGUI.IntField(rects[col], 1);\n                }\n            }\n            col++;\n\n            // If this is a humanoid animation, include the mirror toggle.\n            if (motion.objectReferenceValue is AnimationClip && (motion.objectReferenceValue as AnimationClip).isHumanMotion)\n            {\n                SerializedProperty mirror = child.FindPropertyRelative(\"m_Mirror\");\n                EditorGUI.PropertyField(rects[col], mirror, GUIContent.none);\n\n                SerializedProperty cycle = child.FindPropertyRelative(\"m_CycleOffset\");\n                cycle.floatValue = mirror.boolValue ? 0.5f : 0.0f;\n            }\n            else\n            {\n                // Otherwise show disabled dummy toggle that's disabled.\n                using (new EditorGUI.DisabledScope(true))\n                {\n                    EditorGUI.Toggle(rects[col], false);\n                }\n            }\n        }\n\n        private bool AllMotions()\n        {\n            bool allClips = true;\n            for (int i = 0; i < m_Childs.arraySize && allClips; i++)\n            {\n                SerializedProperty motion = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative(\"m_Motion\");\n                allClips = motion.objectReferenceValue is AnimationClip;\n            }\n            return allClips;\n        }\n\n        private void AutoCompute()\n        {\n            if (m_BlendType.intValue == (int)BlendTreeType.Simple1D)\n            {\n                EditorGUILayout.PropertyField(m_UseAutomaticThresholds, EditorGUIUtility.TempContent(\"Automate Thresholds\"));\n                m_ShowCompute.target = !m_UseAutomaticThresholds.boolValue;\n            }\n            else if (m_BlendType.intValue == (int)BlendTreeType.Direct)\n            {\n                m_ShowCompute.target = false;\n            }\n            else\n            {\n                m_ShowCompute.target = true;\n            }\n\n            m_ShowAdjust.target = AllMotions();\n\n            if (EditorGUILayout.BeginFadeGroup(m_ShowCompute.faded))\n            {\n                Rect controlRect = EditorGUILayout.GetControlRect();\n                GUIContent label = (ParameterCount == 1) ?\n                    EditorGUIUtility.TempContent(\"Compute Thresholds\") :\n                    EditorGUIUtility.TempContent(\"Compute Positions\");\n                controlRect = EditorGUI.PrefixLabel(controlRect, 0, label);\n\n                if (EditorGUI.DropdownButton(controlRect, EditorGUIUtility.TempContent(\"Select\"), FocusType.Passive, EditorStyles.popup))\n                {\n                    GenericMenu menu = new GenericMenu();\n                    if (ParameterCount == 1)\n                    {\n                        AddComputeMenuItems(menu, string.Empty, ChildPropertyToCompute.Threshold);\n                    }\n                    else\n                    {\n                        menu.AddItem(EditorGUIUtility.TrTextContent(\"Velocity XZ\"), false, ComputePositionsFromVelocity);\n                        menu.AddItem(EditorGUIUtility.TrTextContent(\"Speed And Angular Speed\"), false, ComputePositionsFromSpeedAndAngularSpeed);\n                        AddComputeMenuItems(menu, \"X Position From/\", ChildPropertyToCompute.PositionX);\n                        AddComputeMenuItems(menu, \"Y Position From/\", ChildPropertyToCompute.PositionY);\n                    }\n                    menu.DropDown(controlRect);\n                }\n            }\n            EditorGUILayout.EndFadeGroup();\n\n            if (EditorGUILayout.BeginFadeGroup(m_ShowAdjust.faded))\n            {\n                Rect controlRect = EditorGUILayout.GetControlRect();\n                controlRect = EditorGUI.PrefixLabel(controlRect, 0, EditorGUIUtility.TempContent(\"Adjust Time Scale\"));\n\n                if (EditorGUI.DropdownButton(controlRect, EditorGUIUtility.TempContent(\"Select\"), FocusType.Passive, EditorStyles.popup))\n                {\n                    GenericMenu menu = new GenericMenu();\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Homogeneous Speed\"), false, ComputeTimeScaleFromSpeed);\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Reset Time Scale\"), false, ResetTimeScale);\n                    menu.DropDown(controlRect);\n                }\n            }\n            EditorGUILayout.EndFadeGroup();\n        }\n\n        enum ChildPropertyToCompute\n        {\n            Threshold,\n            PositionX,\n            PositionY\n        }\n\n        delegate float GetFloatFromMotion(Motion motion, float mirrorMultiplier);\n\n        void AddComputeMenuItems(GenericMenu menu, string menuItemPrefix, ChildPropertyToCompute prop)\n        {\n            menu.AddItem(new GUIContent(menuItemPrefix + \"Speed\"), false, ComputeFromSpeed, prop);\n            menu.AddItem(new GUIContent(menuItemPrefix + \"Velocity X\"), false, ComputeFromVelocityX, prop);\n            menu.AddItem(new GUIContent(menuItemPrefix + \"Velocity Y\"), false, ComputeFromVelocityY, prop);\n            menu.AddItem(new GUIContent(menuItemPrefix + \"Velocity Z\"), false, ComputeFromVelocityZ, prop);\n            menu.AddItem(new GUIContent(menuItemPrefix + \"Angular Speed (Rad)\"), false, ComputeFromAngularSpeedRadians, prop);\n            menu.AddItem(new GUIContent(menuItemPrefix + \"Angular Speed (Deg)\"), false, ComputeFromAngularSpeedDegrees, prop);\n        }\n\n        private void ComputeFromSpeed(object obj)\n        {\n            ChildPropertyToCompute prop = (ChildPropertyToCompute)obj;\n            ComputeProperty((Motion m, float mirrorMultiplier) => m.apparentSpeed, prop);\n        }\n\n        private void ComputeFromVelocityX(object obj)\n        {\n            ChildPropertyToCompute prop = (ChildPropertyToCompute)obj;\n            ComputeProperty((Motion m, float mirrorMultiplier) => m.averageSpeed.x * mirrorMultiplier, prop);\n        }\n\n        private void ComputeFromVelocityY(object obj)\n        {\n            ChildPropertyToCompute prop = (ChildPropertyToCompute)obj;\n            ComputeProperty((Motion m, float mirrorMultiplier) => m.averageSpeed.y, prop);\n        }\n\n        private void ComputeFromVelocityZ(object obj)\n        {\n            ChildPropertyToCompute prop = (ChildPropertyToCompute)obj;\n            ComputeProperty((Motion m, float mirrorMultiplier) => m.averageSpeed.z, prop);\n        }\n\n        private void ComputeFromAngularSpeedDegrees(object obj)\n        {\n            ChildPropertyToCompute prop = (ChildPropertyToCompute)obj;\n            ComputeProperty((Motion m, float mirrorMultiplier) => m.averageAngularSpeed * 180.0f / Mathf.PI * mirrorMultiplier, prop);\n        }\n\n        private void ComputeFromAngularSpeedRadians(object obj)\n        {\n            ChildPropertyToCompute prop = (ChildPropertyToCompute)obj;\n            ComputeProperty((Motion m, float mirrorMultiplier) => m.averageAngularSpeed * mirrorMultiplier, prop);\n        }\n\n        private void ComputeProperty(GetFloatFromMotion func, ChildPropertyToCompute prop)\n        {\n            float mean = 0.0f;\n            float[] values = new float[m_Childs.arraySize];\n\n            m_UseAutomaticThresholds.boolValue = false;\n            for (int i = 0; i < m_Childs.arraySize; i++)\n            {\n                SerializedProperty motion = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative(\"m_Motion\");\n                SerializedProperty mirror = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative(\"m_Mirror\");\n                Motion motionObj = motion.objectReferenceValue as Motion;\n                if (motionObj != null)\n                {\n                    float val = func(motionObj, mirror.boolValue ? -1 : 1);\n                    values[i] = val;\n                    mean += val;\n                    if (prop == ChildPropertyToCompute.Threshold)\n                    {\n                        SerializedProperty threshold = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative(\"m_Threshold\");\n                        threshold.floatValue = val;\n                    }\n                    else\n                    {\n                        SerializedProperty position = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative(\"m_Position\");\n                        Vector2 pos = position.vector2Value;\n                        if (prop == ChildPropertyToCompute.PositionX)\n                            pos.x = val;\n                        else\n                            pos.y = val;\n                        position.vector2Value = pos;\n                    }\n                }\n            }\n\n            mean /= (float)m_Childs.arraySize;\n            float variance = 0.0f;\n            for (int i = 0; i < values.Length; i++)\n            {\n                variance += Mathf.Pow(values[i] - mean, 2.0f);\n            }\n            variance /=  values.Length;\n\n            if (variance < Mathf.Epsilon)\n            {\n                Debug.LogWarning($\"Can't distribute the motions of '{m_BlendTree.name}', they all have the same threshold value.\");\n                m_SerializedObject.Update();\n            }\n            else\n            {\n                m_SerializedObject.ApplyModifiedProperties();\n                if (prop == ChildPropertyToCompute.Threshold)\n                {\n                    SortByThreshold();\n                    SetMinMaxThreshold();\n                }\n            }\n        }\n\n        private void ComputePositionsFromVelocity()\n        {\n            ComputeFromVelocityX(ChildPropertyToCompute.PositionX);\n            ComputeFromVelocityZ(ChildPropertyToCompute.PositionY);\n        }\n\n        private void ComputePositionsFromSpeedAndAngularSpeed()\n        {\n            ComputeFromAngularSpeedRadians(ChildPropertyToCompute.PositionX);\n            ComputeFromSpeed(ChildPropertyToCompute.PositionY);\n        }\n\n        private void ComputeTimeScaleFromSpeed()\n        {\n            float apparentSpeed = m_BlendTree.apparentSpeed;\n            for (int i = 0; i < m_Childs.arraySize; i++)\n            {\n                SerializedProperty motion = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative(\"m_Motion\");\n                AnimationClip clip = motion.objectReferenceValue as AnimationClip;\n                if (clip != null)\n                {\n                    if (!clip.legacy)\n                    {\n                        if (clip.apparentSpeed < Mathf.Epsilon)\n                        {\n                            Debug.LogWarning(\"Could not adjust time scale for \" + clip.name + \" because it has no speed\");\n                        }\n                        else\n                        {\n                            SerializedProperty timeScale = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative(\"m_TimeScale\");\n                            timeScale.floatValue = apparentSpeed / clip.apparentSpeed;\n                        }\n                    }\n                    else\n                    {\n                        Debug.LogWarning(\"Could not adjust time scale for \" + clip.name + \" because it is not a muscle clip\");\n                    }\n                }\n            }\n            m_SerializedObject.ApplyModifiedProperties();\n        }\n\n        private void ResetTimeScale()\n        {\n            for (int i = 0; i < m_Childs.arraySize; i++)\n            {\n                SerializedProperty motion = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative(\"m_Motion\");\n                AnimationClip clip = motion.objectReferenceValue as AnimationClip;\n                if (clip != null && !clip.legacy)\n                {\n                    SerializedProperty timeScale = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative(\"m_TimeScale\");\n                    timeScale.floatValue = 1;\n                }\n            }\n            m_SerializedObject.ApplyModifiedProperties();\n        }\n\n        private void SortByThreshold()\n        {\n            m_SerializedObject.Update();\n            for (int i = 0; i < m_Childs.arraySize; i++)\n            {\n                float minThreshold = Mathf.Infinity;\n                int minIndex = -1;\n                for (int j = i; j < m_Childs.arraySize; j++)\n                {\n                    SerializedProperty testElement = m_Childs.GetArrayElementAtIndex(j);\n                    float testThreshold = testElement.FindPropertyRelative(\"m_Threshold\").floatValue;\n                    if (testThreshold < minThreshold)\n                    {\n                        minThreshold = testThreshold;\n                        minIndex = j;\n                    }\n                }\n                if (minIndex != i)\n                    m_Childs.MoveArrayElement(minIndex, i);\n            }\n\n            m_SerializedObject.ApplyModifiedProperties();\n        }\n\n        private void SetMinMaxThreshold()\n        {\n            m_SerializedObject.Update();\n            SerializedProperty minThreshold = m_Childs.GetArrayElementAtIndex(0).FindPropertyRelative(\"m_Threshold\");\n            SerializedProperty maxThreshold = m_Childs.GetArrayElementAtIndex(m_Childs.arraySize - 1).FindPropertyRelative(\"m_Threshold\");\n            m_MinThreshold.floatValue = Mathf.Min(minThreshold.floatValue, maxThreshold.floatValue);\n            m_MaxThreshold.floatValue = Mathf.Max(minThreshold.floatValue, maxThreshold.floatValue);\n            m_SerializedObject.ApplyModifiedProperties();\n        }\n\n        void AddChildAnimation()\n        {\n            m_BlendTree.AddChild(null);\n            int numChildren = m_BlendTree.children.Length;\n            if (currentController != null)\n            {\n                m_BlendTree.SetDirectBlendTreeParameter(numChildren - 1, currentController.GetDefaultBlendTreeParameter());\n            }\n            SetNewThresholdAndPosition(numChildren - 1);\n            m_ReorderableList.index = numChildren - 1;\n        }\n\n        void AddBlendTreeCallback()\n        {\n            BlendTree tree = m_BlendTree.CreateBlendTreeChild(0);\n            ChildMotion[] children = m_BlendTree.children;\n            int numChildren = children.Length;\n\n            if (currentController != null)\n            {\n                tree.blendParameter = m_BlendTree.blendParameter;\n                m_BlendTree.SetDirectBlendTreeParameter(numChildren - 1, currentController.GetDefaultBlendTreeParameter());\n            }\n\n            SetNewThresholdAndPosition(numChildren - 1);\n            m_ReorderableList.index = m_Childs.arraySize - 1;\n        }\n\n        void SetNewThresholdAndPosition(int index)\n        {\n            serializedObject.Update();\n\n            // Set new threshold\n            if (!m_UseAutomaticThresholds.boolValue)\n            {\n                float newThreshold = 0f;\n                if (m_Childs.arraySize >= 3 && index == m_Childs.arraySize - 1)\n                {\n                    float threshold1 = m_Childs.GetArrayElementAtIndex(index - 2).FindPropertyRelative(\"m_Threshold\").floatValue;\n                    float threshold2 = m_Childs.GetArrayElementAtIndex(index - 1).FindPropertyRelative(\"m_Threshold\").floatValue;\n                    newThreshold = threshold2 + (threshold2 - threshold1);\n                }\n                else\n                {\n                    if (m_Childs.arraySize == 1)\n                        newThreshold = 0;\n                    else\n                        newThreshold = m_Childs.GetArrayElementAtIndex(m_Childs.arraySize - 1).FindPropertyRelative(\"m_Threshold\").floatValue + 1;\n                }\n                SerializedProperty addedThreshold = m_Childs.GetArrayElementAtIndex(index).FindPropertyRelative(\"m_Threshold\");\n                addedThreshold.floatValue = newThreshold;\n                SetMinMaxThresholds();\n            }\n\n            // Set new position\n            Vector2 newPosition = Vector2.zero;\n            if (m_Childs.arraySize >= 1)\n            {\n                Vector2 center = m_BlendRect.center;\n                Vector2[] points = GetMotionPositions();\n                float goodMinDist = m_BlendRect.width * 0.07f;\n                bool satisfied = false;\n                // Try to place new point along circle around center until successful\n                for (int iter = 0; iter < 24; iter++)\n                {\n                    satisfied = true;\n                    for (int i = 0; i < points.Length && satisfied; i++)\n                        if (i != index && Vector2.Distance(points[i], newPosition) < goodMinDist)\n                            satisfied = false;\n\n                    if (satisfied)\n                        break;\n\n                    float radians = iter * 15 * Mathf.Deg2Rad;\n                    newPosition = center + new Vector2(-Mathf.Cos(radians), Mathf.Sin(radians)) * 0.37f * m_BlendRect.width;\n                    newPosition.x = MathUtils.RoundBasedOnMinimumDifference(newPosition.x, m_BlendRect.width * 0.005f);\n                    newPosition.y = MathUtils.RoundBasedOnMinimumDifference(newPosition.y, m_BlendRect.width * 0.005f);\n                }\n            }\n            SerializedProperty addedPosition = m_Childs.GetArrayElementAtIndex(index).FindPropertyRelative(\"m_Position\");\n            addedPosition.vector2Value = newPosition;\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        public override bool HasPreviewGUI()\n        {\n            return true;\n        }\n\n        public override void OnPreviewSettings()\n        {\n            if (m_PreviewBlendTree != null)\n                m_PreviewBlendTree.OnPreviewSettings();\n        }\n\n        public override void OnInteractivePreviewGUI(Rect r, GUIStyle background)\n        {\n            if (m_PreviewBlendTree != null)\n                m_PreviewBlendTree.OnInteractivePreviewGUI(r, background);\n        }\n\n        public void OnDisable()\n        {\n            if (m_PreviewBlendTree != null)\n                m_PreviewBlendTree.OnDisable();\n\n            if (m_VisBlendTree != null)\n                m_VisBlendTree.Reset();\n        }\n\n        public void OnDestroy()\n        {\n            if (m_VisBlendTree != null)\n                m_VisBlendTree.Destroy();\n            if (m_VisInstance != null)\n                DestroyImmediate(m_VisInstance);\n            for (int i = 0; i < m_WeightTexs.Count; i++)\n                DestroyImmediate(m_WeightTexs[i]);\n            if (m_BlendTex != null)\n                DestroyImmediate(m_BlendTex);\n        }\n    }\n\n    class VisualizationBlendTree\n    {\n        private AnimatorController m_Controller;\n        private AnimatorStateMachine m_StateMachine;\n        private AnimatorState m_State;\n        private BlendTree m_BlendTree;\n        private Animator m_Animator;\n        private bool m_ControllerIsDirty = false;\n\n        public Animator animator { get { return m_Animator; } }\n\n        public void Init(BlendTree blendTree, Animator animator)\n        {\n            m_BlendTree = blendTree;\n            m_Animator = animator;\n            m_Animator.logWarnings = false;\n            m_Animator.fireEvents = false;\n            m_Animator.enabled = false;\n            m_Animator.cullingMode = AnimatorCullingMode.AlwaysAnimate;\n            CreateStateMachine();\n        }\n\n        public bool controllerDirty\n        {\n            get\n            {\n                return m_ControllerIsDirty;\n            }\n        }\n        protected virtual void ControllerDirty()\n        {\n            m_ControllerIsDirty = true;\n        }\n\n        private void CreateParameters()\n        {\n            for (int i = 0; i < m_BlendTree.recursiveBlendParameterCount; i++)\n                m_Controller.AddParameter(m_BlendTree.GetRecursiveBlendParameter(i), AnimatorControllerParameterType.Float);\n        }\n\n        private void CreateStateMachine()\n        {\n            if (m_Controller == null)\n            {\n                m_Controller = new AnimatorController();\n                m_Controller.pushUndo = false;\n                m_Controller.AddLayer(\"viz\");\n                m_StateMachine = m_Controller.layers[0].stateMachine;\n                m_StateMachine.pushUndo = false;\n                CreateParameters();\n                m_State = m_StateMachine.AddState(\"viz\");\n                m_State.pushUndo = false;\n                m_State.motion = m_BlendTree;\n                m_State.iKOnFeet = false;\n\n                m_State.hideFlags = HideFlags.HideAndDontSave;\n                m_StateMachine.hideFlags = HideFlags.HideAndDontSave;\n                m_Controller.hideFlags = HideFlags.HideAndDontSave;\n\n                AnimatorController.SetAnimatorController(m_Animator, m_Controller);\n\n                m_Controller.OnAnimatorControllerDirty += ControllerDirty;\n                m_ControllerIsDirty = false;\n            }\n        }\n\n        private void ClearStateMachine()\n        {\n            if (m_Animator != null)\n                AnimatorController.SetAnimatorController(m_Animator, null);\n\n            if (m_Controller != null)\n                m_Controller.OnAnimatorControllerDirty -= ControllerDirty;\n\n            Object.DestroyImmediate(m_Controller);\n            Object.DestroyImmediate(m_State);\n            m_StateMachine = null;\n            m_Controller = null;\n            m_State = null;\n        }\n\n        public void Reset()\n        {\n            ClearStateMachine();\n            CreateStateMachine();\n        }\n\n        public void Destroy()\n        {\n            ClearStateMachine();\n        }\n\n        public void Update()\n        {\n            if (m_ControllerIsDirty)\n                Reset();\n\n            int count = m_BlendTree.recursiveBlendParameterCount;\n            if (m_Controller.parameters.Length < count)\n                return;\n\n            for (int i = 0; i < count; i++)\n            {\n                string blendParameter = m_BlendTree.GetRecursiveBlendParameter(i);\n                float value = BlendTreeInspector.GetParameterValue(animator, m_BlendTree, blendParameter);\n                animator.SetFloat(blendParameter, value);\n            }\n            animator.EvaluateController();\n        }\n    }\n\n    class PreviewBlendTree\n    {\n        private AnimatorController m_Controller;\n        private AvatarPreview m_AvatarPreview;\n        private AnimatorStateMachine m_StateMachine;\n        private AnimatorState m_State;\n        private BlendTree m_BlendTree;\n\n\n        private bool m_ControllerIsDirty = false;\n        protected virtual void ControllerDirty()\n        {\n            m_ControllerIsDirty = true;\n        }\n\n        bool m_PrevIKOnFeet;\n\n        public Animator PreviewAnimator { get { return m_AvatarPreview.Animator; } }\n\n        public void Init(BlendTree blendTree, Animator animator)\n        {\n            m_BlendTree = blendTree;\n            if (m_AvatarPreview == null)\n            {\n                m_AvatarPreview = new AvatarPreview(animator, m_BlendTree);\n                m_AvatarPreview.OnAvatarChangeFunc = OnPreviewAvatarChanged;\n                m_AvatarPreview.ResetPreviewFocus();\n                m_PrevIKOnFeet = m_AvatarPreview.IKOnFeet;\n            }\n\n            CreateStateMachine();\n        }\n\n        public void CreateParameters()\n        {\n            for (int i = 0; i < m_BlendTree.recursiveBlendParameterCount; i++)\n            {\n                m_Controller.AddParameter(m_BlendTree.GetRecursiveBlendParameter(i), AnimatorControllerParameterType.Float);\n            }\n        }\n\n        private void CreateStateMachine()\n        {\n            if (m_AvatarPreview != null && m_AvatarPreview.Animator != null)\n            {\n                if (m_Controller == null)\n                {\n                    m_Controller = new AnimatorController();\n                    m_Controller.pushUndo = false;\n                    m_Controller.AddLayer(\"preview\");\n                    m_StateMachine = m_Controller.layers[0].stateMachine;\n                    m_StateMachine.pushUndo = false;\n                    CreateParameters();\n\n                    m_State = m_StateMachine.AddState(\"preview\");\n                    m_State.pushUndo = false;\n                    m_State.motion = m_BlendTree;\n                    m_State.iKOnFeet = m_AvatarPreview.IKOnFeet;\n\n                    m_State.hideFlags = HideFlags.HideAndDontSave;\n                    m_Controller.hideFlags = HideFlags.HideAndDontSave;\n                    m_StateMachine.hideFlags = HideFlags.HideAndDontSave;\n\n                    AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);\n                    m_Controller.OnAnimatorControllerDirty += ControllerDirty;\n\n                    m_ControllerIsDirty = false;\n                }\n\n                if (AnimatorController.GetEffectiveAnimatorController(m_AvatarPreview.Animator) != m_Controller)\n                    AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);\n            }\n        }\n\n        private void ClearStateMachine()\n        {\n            if (m_AvatarPreview != null && m_AvatarPreview.Animator != null) AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, null);\n\n            if (m_Controller != null)\n                m_Controller.OnAnimatorControllerDirty -= ControllerDirty;\n\n            Object.DestroyImmediate(m_Controller);\n            Object.DestroyImmediate(m_State);\n            m_StateMachine = null;\n            m_Controller = null;\n            m_State = null;\n        }\n\n        private void OnPreviewAvatarChanged()\n        {\n            ResetStateMachine();\n        }\n\n        public void ResetStateMachine()\n        {\n            ClearStateMachine();\n            CreateStateMachine();\n        }\n\n        public void OnDisable()\n        {\n            ClearStateMachine();\n            if (m_AvatarPreview != null)\n            {\n                m_AvatarPreview.OnDisable();\n                m_AvatarPreview = null;\n            }\n        }\n\n        private void UpdateAvatarState()\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            if (m_AvatarPreview.PreviewObject == null || m_ControllerIsDirty)\n            {\n                m_AvatarPreview.ResetPreviewInstance();\n                if (m_AvatarPreview.PreviewObject)\n                    ResetStateMachine();\n            }\n\n            if (m_AvatarPreview.Animator)\n            {\n                if (m_PrevIKOnFeet != m_AvatarPreview.IKOnFeet)\n                {\n                    m_PrevIKOnFeet = m_AvatarPreview.IKOnFeet;\n                    Vector3 prevPos = m_AvatarPreview.Animator.rootPosition;\n                    Quaternion prevRotation = m_AvatarPreview.Animator.rootRotation;\n                    ResetStateMachine();\n                    m_AvatarPreview.Animator.Update(m_AvatarPreview.timeControl.currentTime);\n                    m_AvatarPreview.Animator.Update(0); // forces deltaPos/Rot to 0,0,0\n                    m_AvatarPreview.Animator.rootPosition = prevPos;\n                    m_AvatarPreview.Animator.rootRotation = prevRotation;\n                }\n\n                if (m_AvatarPreview.Animator)\n                {\n                    for (int i = 0; i < m_BlendTree.recursiveBlendParameterCount; i++)\n                    {\n                        string blendParameter = m_BlendTree.GetRecursiveBlendParameter(i);\n                        float value = BlendTreeInspector.GetParameterValue(m_AvatarPreview.Animator, m_BlendTree, blendParameter);\n                        m_AvatarPreview.Animator.SetFloat(blendParameter, value);\n                    }\n                }\n\n                m_AvatarPreview.timeControl.loop = true;\n\n                float stateLength = 1.0f;\n                float stateTime = 0.0f;\n\n                if (m_AvatarPreview.Animator.layerCount > 0)\n                {\n                    AnimatorStateInfo stateInfo = m_AvatarPreview.Animator.GetCurrentAnimatorStateInfo(0);\n                    stateLength = stateInfo.length;\n                    stateTime = stateInfo.normalizedTime;\n                }\n\n                m_AvatarPreview.timeControl.startTime = 0.0f;\n                m_AvatarPreview.timeControl.stopTime = stateLength;\n\n                m_AvatarPreview.timeControl.Update();\n\n                float deltaTime = m_AvatarPreview.timeControl.deltaTime;\n\n                if (!m_BlendTree.isLooping)\n                {\n                    if (stateTime >= 1.0f)\n                    {\n                        deltaTime -= stateLength;\n                    }\n                    else if (stateTime < 0.0f)\n                    {\n                        deltaTime += stateLength;\n                    }\n                }\n\n                m_AvatarPreview.Animator.Update(deltaTime);\n            }\n        }\n\n        public void TestForReset()\n        {\n            if ((m_State != null && m_AvatarPreview != null && m_State.iKOnFeet != m_AvatarPreview.IKOnFeet))\n            {\n                ResetStateMachine();\n            }\n        }\n\n        public void OnPreviewSettings()\n        {\n            m_AvatarPreview.DoPreviewSettings();\n        }\n\n        public void OnInteractivePreviewGUI(Rect r, GUIStyle background)\n        {\n            UpdateAvatarState();\n\n            m_AvatarPreview.DoAvatarPreview(r, background);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/CameraEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Text;\nusing UnityEditor.Inspector;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEngine.XR;\nusing AnimatedBool = UnityEditor.AnimatedValues.AnimBool;\nusing UnityEngine.Scripting;\nusing UnityEditor.Modules;\nusing UnityEditor.Overlays;\nusing UnityEditor.UIElements;\nusing UnityEditorInternal.VR;\nusing UnityEngine.UIElements;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(Camera))]\n    [CanEditMultipleObjects]\n    public class CameraEditor : Editor\n    {\n        internal static class Styles\n        {\n            public static readonly GUIContent iconRemove = EditorGUIUtility.TrIconContent(\"Toolbar Minus\", \"Remove command buffer\");\n            public static readonly GUIContent clearFlags = EditorGUIUtility.TrTextContent(\"Clear Flags\", \"What to display in empty areas of this Camera's view.\\n\\nChoose Skybox to display a skybox in empty areas, defaulting to a background color if no skybox is found.\\n\\nChoose Solid Color to display a background color in empty areas.\\n\\nChoose Depth Only to display nothing in empty areas.\\n\\nChoose Don't Clear to display whatever was displayed in the previous frame in empty areas.\");\n            public static readonly GUIContent background = EditorGUIUtility.TrTextContent(\"Background\", \"The Camera clears the screen to this color before rendering.\");\n            public static readonly GUIContent cullingMask = EditorGUIUtility.TrTextContent(\"Culling Mask\");\n            public static readonly GUIContent projection = EditorGUIUtility.TrTextContent(\"Projection\", \"How the Camera renders perspective.\\n\\nChoose Perspective to render objects with perspective.\\n\\nChoose Orthographic to render objects uniformly, with no sense of perspective.\");\n            public static readonly GUIContent size = EditorGUIUtility.TrTextContent(\"Size\", \"The vertical size of the camera view.\");\n            public static readonly GUIContent fieldOfView = EditorGUIUtility.TrTextContent(\"Field of View\", \"The camera's view angle measured in degrees along the selected axis.\");\n            public static readonly GUIContent viewportRect = EditorGUIUtility.TrTextContent(\"Viewport Rect\", \"Four values that indicate where on the screen this camera view will be drawn. Measured in Viewport Coordinates (values 0-1).\");\n            public static readonly GUIContent sensorSize = EditorGUIUtility.TrTextContent(\"Sensor Size\", \"The size of the camera sensor in millimeters.\");\n            public static readonly GUIContent lensShift = EditorGUIUtility.TrTextContent(\"Lens Shift\", \"Offset from the camera sensor. Use these properties to simulate a shift lens. Measured as a multiple of the sensor size.\");\n            public static readonly GUIContent iso = EditorGUIUtility.TrTextContent(\"ISO\", \"The sensor sensitivity (ISO).\");\n            public static readonly GUIContent shutterSpeed = EditorGUIUtility.TrTextContent(\"Shutter Speed\", \"The exposure time, in second.\");\n            public static readonly GUIContent aperture = EditorGUIUtility.TrTextContent(\"Aperture\", \"The aperture number, in f-stop.\");\n            public static readonly GUIContent focusDistance = EditorGUIUtility.TrTextContent(\"Focus Distance\", \"The focus distance of the lens. The Depth of Field Volume override uses this value if you set focusDistanceMode to FocusDistanceMode.Camera.\");\n            public static readonly GUIContent bladeCount = EditorGUIUtility.TrTextContent(\"Blade Count\", \"The number of diaphragm blades.\");\n            public static readonly GUIContent curvature = EditorGUIUtility.TrTextContent(\"Curvature\", \"Maps an aperture range to blade curvature.\");\n            public static readonly GUIContent barrelClipping = EditorGUIUtility.TrTextContent(\"Barrel Clipping\", \"The strength of the \\\"cat eye\\\" effect on bokeh (optical vignetting).\");\n            public static readonly GUIContent anamorphism = EditorGUIUtility.TrTextContent(\"Anamorphism\", \"Stretches the sensor to simulate an anamorphic look. Positive values distort the Camera vertically, negative will distort the Camera horizontally.\");\n            public static readonly GUIContent physicalCamera = EditorGUIUtility.TrTextContent(\"Physical Camera\", \"Enables Physical camera mode. When checked, the field of view is calculated from properties for simulating physical attributes (focal length, sensor size, and lens shift)\");\n            public static readonly GUIContent cameraType = EditorGUIUtility.TrTextContent(\"Sensor Type\", \"Common sensor sizes. Choose an item to set Sensor Size, or edit Sensor Size for your custom settings.\");\n            public static readonly GUIContent renderingPath = EditorGUIUtility.TrTextContent(\"Rendering Path\", \"Choose a rendering method for this camera.\\n\\nUse Graphics Settings to use the rendering path specified in graphics settings.\\n\\nUse Forward to render all objects with one pass per light.\\n\\nUse Deferred to draw all objects once without lighting and then draw the lighting of all objects at the end of the render queue.\\n\\nUse Legacy Vertex Lit to render all lights in a single pass, calculated at vertices.\");\n            public static readonly GUIContent focalLength = EditorGUIUtility.TrTextContent(\"Focal Length\", \"The simulated distance between the lens and the sensor of the physical camera. Larger values give a narrower field of view.\");\n            public static readonly GUIContent allowOcclusionCulling = EditorGUIUtility.TrTextContent(\"Occlusion Culling\", \"Occlusion Culling disables rendering of objects when they are not currently seen by the camera because they are obscured (occluded) by other objects.\");\n            public static readonly GUIContent allowHDR = EditorGUIUtility.TrTextContent(\"HDR\", \"High Dynamic Range gives you a wider range of light intensities, so your lighting looks more realistic. With it, you can still see details and experience less saturation even with bright light.\");\n            public static readonly GUIContent allowMSAA = EditorGUIUtility.TrTextContent(\"MSAA\", \"Use Multi Sample Anti-aliasing to reduce aliasing.\");\n            public static readonly GUIContent gateFit = EditorGUIUtility.TrTextContent(\"Gate Fit\", \"Determines how the rendered area (resolution gate) fits into the sensor area (film gate).\");\n            public static readonly GUIContent allowDynamicResolution = EditorGUIUtility.TrTextContent(\"Allow Dynamic Resolution\", \"Scales render textures to support dynamic resolution if the target platform/graphics API supports it.\");\n            public static readonly GUIContent FOVAxisMode = EditorGUIUtility.TrTextContent(\"FOV Axis\", \"Field of view axis.\");\n            public static readonly GUIContent targetDisplay = EditorGUIUtility.TrTextContent(\"Target Display\", \"Set the target display for this camera.\");\n            public static readonly GUIContent xrTargetEye = EditorGUIUtility.TrTextContent(\"Target Eye\", \"Allows XR rendering for target eye. This disables stereo rendering and only works for the selected eye.\");\n\n            public static readonly GUIContent orthoDeferredWarning = EditorGUIUtility.TrTextContent(\"Deferred rendering does not work with Orthographic camera, will use Forward.\");\n            public static readonly GUIContent orthoXRWarning = EditorGUIUtility.TrTextContent(\"Orthographic projection is not supported when running in XR.\", \"One or more XR Plug-in providers were detected in your project. Using Orthographic projection is not supported when running in XR and enabling this may cause problems.\", EditorGUIUtility.warningIcon);\n            public static readonly GUIContent deferredMSAAWarning = EditorGUIUtility.TrTextContent(\"The target texture is using MSAA. Note that this will not affect MSAA behaviour of this camera. MSAA rendering for cameras is configured through the 'MSAA' camera setting and related project settings. The target texture will always contain resolved pixel data.\");\n            public static readonly GUIContent dynamicResolutionTimingWarning = EditorGUIUtility.TrTextContent(\"It is recommended to enable Frame Timing Statistics under Rendering Player Settings when using dynamic resolution cameras.\");\n\n            public static GUIStyle invisibleButton;\n\n            public const string k_CameraEditorUxmlPath = \"UXML/InspectorWindow/CameraEditor.uxml\";\n\n            public const string k_ClearFlagsElementName = \"clear-flags\";\n            public const string k_BackgroundElementName = \"background\";\n            public const string k_CullingMaskElementName = \"culling-mask\";\n            public const string k_ClippingPlanesElementName = \"clipping-planes\";\n            public const string k_ViewportRectElementName = \"viewport-rect\";\n            public const string k_DepthElementName = \"depth\";\n            public const string k_RenderingPathElementName = \"rendering-path\";\n            public const string k_OrthographicDeferredWarningElementName = \"orthographic-deferred-warning\";\n            public const string k_DeferredMsaaWarningElementName = \"deferred-msaa-warning\";\n            public const string k_TargetTextureElementName = \"target-texture\";\n            public const string k_OcclusionCullingElementName = \"occlusion-culling\";\n            public const string k_HdrElementName = \"hdr\";\n            public const string k_MsaaElementName = \"msaa\";\n            public const string k_DynamicResolution = \"dynamic-resolution\";\n            public const string k_DynamicResolutionTimingWarningElementName = \"dynamic-resolution-timing-warning\";\n            public const string k_CameraWarningsElementName = \"camera-warnings\";\n            public const string k_VrGroupElementName = \"vr-group\";\n            public const string k_TargetDisplayElementName = \"target-display\";\n            public const string k_TargetEyeElementName = \"target-eye\";\n            public const string k_DepthTextureModeElementName = \"depth-texture-mode\";\n            public const string k_CommandBuffersElementName = \"command-buffers\";\n            public const string k_CommandBuffersListElementName = \"list\";\n            public const string k_CommandBuffersRemoveAllElementName = \"remove-all\";\n\n            public const string k_PerspectiveGroupElementName = \"perspective-group\";\n            public const string k_OrthographicGroupElementName = \"orthographic-group\";\n            public const string k_ProjectionTypeElementName = \"projection-type\";\n            public const string k_FovAxisModeElementName = \"fov-axis-mode\";\n            public const string k_FieldOfViewElementName = \"field-of-view\";\n            public const string k_PhysicalCameraGroupElementName = \"physical-camera-group\";\n            public const string k_PhysicalCameraElementName = \"physical-camera\";\n            public const string k_IsoElementName = \"iso\";\n            public const string k_ShutterSpeedElementName = \"shutter-speed\";\n            public const string k_ApertureElementName = \"aperture\";\n            public const string k_FocusDistanceElementName = \"focus-distance\";\n            public const string k_BladeCountElementName = \"blade-count\";\n            public const string k_CurvatureElementName = \"curvature\";\n            public const string k_BarrelClippingElementName = \"barrel-clipping\";\n            public const string k_AnamorphismElementName = \"anamorphism\";\n            public const string k_FocalLengthElementName = \"focal-length\";\n            public const string k_SensorTypeElementName = \"sensor-type\";\n            public const string k_SensorSizeElementName = \"sensor-size\";\n            public const string k_LensShiftElementName = \"lens-shift\";\n            public const string k_GateFitElementName = \"gate-fit\";\n            public const string k_OrthographicSizeElementName = \"orthographic-size\";\n            public const string k_OrthographicXrWarningElementName = \"orthographic-xr-warning\";\n\n            public const string commandBufferUssClassName = \"camera-editor__command-buffer__line\";\n            public const string commandBufferLabelUssClassName = \"camera-editor__command-buffer__label\";\n            public const string commandBufferRemoveButtonUssClassName = \"camera-editor__command-buffer__remove-button\";\n        }\n\n        public sealed class Settings\n        {\n            readonly SerializedObject m_SerializedObject;\n\n            public Settings(SerializedObject so)\n            {\n                m_SerializedObject = so;\n            }\n\n            public static IEnumerable<string> ApertureFormatNames => k_ApertureFormats;\n\n            internal static readonly string[] k_ApertureFormats =\n            {\n                \"8mm\",\n                \"Super 8mm\",\n                \"16mm\",\n                \"Super 16mm\",\n                \"35mm 2-perf\",\n                \"35mm Academy\",\n                \"Super-35\",\n                \"35mm TV Projection\",\n                \"35mm Full Aperture\",\n                \"35mm 1.85 Projection\",\n                \"35mm Anamorphic\",\n                \"65mm ALEXA\",\n                \"70mm\",\n                \"70mm IMAX\",\n                \"Custom\"\n            };\n\n            public static IEnumerable<Vector2> ApertureFormatValues => k_ApertureFormatValues;\n\n            internal static readonly Vector2[] k_ApertureFormatValues =\n            {\n                new(4.8f, 3.5f), // 8mm\n                new(5.79f, 4.01f), // Super 8mm\n                new(10.26f, 7.49f), // 16mm\n                new(12.522f, 7.417f), // Super 16mm\n                new(21.95f, 9.35f), // 35mm 2-perf\n                new(21.946f, 16.002f), // 35mm academy\n                new(24.89f, 18.66f), // Super-35\n                new(20.726f, 15.545f), // 35mm TV Projection\n                new(24.892f, 18.669f), // 35mm Full Aperture\n                new(20.955f, 11.328f), // 35mm 1.85 Projection\n                new(21.946f, 18.593f), // 35mm Anamorphic\n                new(54.12f, 25.59f), // 65mm ALEXA\n                new(52.476f, 23.012f), // 70mm\n                new(70.41f, 52.63f), // 70mm IMAX\n            };\n\n            // Manually entered rendering path names/values, since we want to show them\n            // in different order than they appear in the enum.\n            internal static readonly GUIContent[] k_CameraRenderPaths =\n            {\n                EditorGUIUtility.TrTextContent(\"Use Graphics Settings\"),\n                EditorGUIUtility.TrTextContent(\"Forward\"),\n                EditorGUIUtility.TrTextContent(\"Deferred\"),\n                EditorGUIUtility.TrTextContent(\"Legacy Vertex Lit\")\n            };\n\n            internal static readonly int[] k_CameraRenderPathValues =\n            {\n                (int)RenderingPath.UsePlayerSettings,\n                (int)RenderingPath.Forward,\n                (int)RenderingPath.DeferredShading,\n                (int)RenderingPath.VertexLit\n            };\n\n            internal static readonly GUIContent[] k_DefaultOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Off\"),\n                EditorGUIUtility.TrTextContent(\"Use Graphics Settings\"),\n            };\n\n            internal static readonly int[] k_DefaultOptionValues =\n            {\n                0,\n                1\n            };\n\n            internal static readonly GUIContent[] k_TargetEyes =\n            {\n                EditorGUIUtility.TrTextContent(\"Both\"),\n                EditorGUIUtility.TrTextContent(\"Left\"),\n                EditorGUIUtility.TrTextContent(\"Right\"),\n                EditorGUIUtility.TrTextContent(\"None (Main Display)\"),\n            };\n\n            internal static readonly int[] k_TargetEyeValues =\n            {\n                (int)StereoTargetEyeMask.Both,\n                (int)StereoTargetEyeMask.Left,\n                (int)StereoTargetEyeMask.Right,\n                (int)StereoTargetEyeMask.None\n            };\n\n            public SerializedProperty clearFlags { get; private set; }\n            public SerializedProperty backgroundColor { get; private set; }\n            public SerializedProperty normalizedViewPortRect { get; private set; }\n            internal SerializedProperty projectionMatrixMode { get; private set; }\n            public SerializedProperty iso { get; private set; }\n            public SerializedProperty shutterSpeed { get; private set; }\n            public SerializedProperty aperture { get; private set; }\n            public SerializedProperty focusDistance { get; private set; }\n            public SerializedProperty focalLength { get; private set; }\n            public SerializedProperty bladeCount { get; private set; }\n            public SerializedProperty curvature { get; private set; }\n            public SerializedProperty barrelClipping { get; private set; }\n            public SerializedProperty anamorphism { get; private set; }\n            public SerializedProperty sensorSize { get; private set; }\n            public SerializedProperty lensShift { get; private set; }\n            public SerializedProperty gateFit { get; private set; }\n            public SerializedProperty verticalFOV { get; private set; }\n            public SerializedProperty orthographic { get; private set; }\n            public SerializedProperty orthographicSize { get; private set; }\n            public SerializedProperty depth { get; private set; }\n            public SerializedProperty cullingMask { get; private set; }\n            public SerializedProperty renderingPath { get; private set; }\n            public SerializedProperty occlusionCulling { get; private set; }\n            public SerializedProperty targetTexture { get; private set; }\n            public SerializedProperty HDR { get; private set; }\n            public SerializedProperty allowMSAA { get; private set; }\n            public SerializedProperty allowDynamicResolution { get; private set; }\n            public SerializedProperty stereoConvergence { get; private set; }\n            public SerializedProperty stereoSeparation { get; private set; }\n            public SerializedProperty nearClippingPlane { get; private set; }\n            public SerializedProperty farClippingPlane { get; private set; }\n            public SerializedProperty fovAxisMode { get; private set; }\n\n            public SerializedProperty targetDisplay { get; private set; }\n\n            public SerializedProperty targetEye { get; private set; }\n\n            public void OnEnable()\n            {\n                clearFlags = m_SerializedObject.FindProperty(\"m_ClearFlags\");\n                backgroundColor = m_SerializedObject.FindProperty(\"m_BackGroundColor\");\n                normalizedViewPortRect = m_SerializedObject.FindProperty(\"m_NormalizedViewPortRect\");\n                iso = m_SerializedObject.FindProperty(\"m_Iso\");\n                shutterSpeed = m_SerializedObject.FindProperty(\"m_ShutterSpeed\");\n                aperture = m_SerializedObject.FindProperty(\"m_Aperture\");\n                focusDistance = m_SerializedObject.FindProperty(\"m_FocusDistance\");\n                focalLength = m_SerializedObject.FindProperty(\"m_FocalLength\");\n                bladeCount = m_SerializedObject.FindProperty(\"m_BladeCount\");\n                curvature = m_SerializedObject.FindProperty(\"m_Curvature\");\n                barrelClipping = m_SerializedObject.FindProperty(\"m_BarrelClipping\");\n                anamorphism = m_SerializedObject.FindProperty(\"m_Anamorphism\");\n                sensorSize = m_SerializedObject.FindProperty(\"m_SensorSize\");\n                lensShift = m_SerializedObject.FindProperty(\"m_LensShift\");\n                gateFit = m_SerializedObject.FindProperty(\"m_GateFitMode\");\n                projectionMatrixMode = m_SerializedObject.FindProperty(\"m_projectionMatrixMode\");\n                nearClippingPlane = m_SerializedObject.FindProperty(\"near clip plane\");\n                farClippingPlane = m_SerializedObject.FindProperty(\"far clip plane\");\n                verticalFOV = m_SerializedObject.FindProperty(\"field of view\");\n                fovAxisMode = m_SerializedObject.FindProperty(\"m_FOVAxisMode\");\n                orthographic = m_SerializedObject.FindProperty(\"orthographic\");\n                orthographicSize = m_SerializedObject.FindProperty(\"orthographic size\");\n                depth = m_SerializedObject.FindProperty(\"m_Depth\");\n                cullingMask = m_SerializedObject.FindProperty(\"m_CullingMask\");\n                renderingPath = m_SerializedObject.FindProperty(\"m_RenderingPath\");\n                occlusionCulling = m_SerializedObject.FindProperty(\"m_OcclusionCulling\");\n                targetTexture = m_SerializedObject.FindProperty(\"m_TargetTexture\");\n                HDR = m_SerializedObject.FindProperty(\"m_HDR\");\n                allowMSAA = m_SerializedObject.FindProperty(\"m_AllowMSAA\");\n                allowDynamicResolution = m_SerializedObject.FindProperty(\"m_AllowDynamicResolution\");\n\n                stereoConvergence = m_SerializedObject.FindProperty(\"m_StereoConvergence\");\n                stereoSeparation = m_SerializedObject.FindProperty(\"m_StereoSeparation\");\n\n                targetDisplay = m_SerializedObject.FindProperty(\"m_TargetDisplay\");\n\n                targetEye = m_SerializedObject.FindProperty(\"m_TargetEye\");\n            }\n\n            public void Update()\n            {\n                m_SerializedObject.Update();\n            }\n\n            public void ApplyModifiedProperties()\n            {\n                m_SerializedObject.ApplyModifiedProperties();\n            }\n\n            public void DrawClearFlags()\n            {\n                EditorGUILayout.PropertyField(clearFlags, Styles.clearFlags);\n            }\n\n            public void DrawBackgroundColor()\n            {\n                EditorGUILayout.PropertyField(backgroundColor, Styles.background);\n            }\n\n            public void DrawCullingMask()\n            {\n                EditorGUILayout.PropertyField(cullingMask);\n            }\n\n            public void DrawProjection()\n            {\n                var projectionType = orthographic.boolValue ? ProjectionType.Orthographic : ProjectionType.Perspective;\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = orthographic.hasMultipleDifferentValues;\n\n                var controlRect = EditorGUILayout.GetControlRect();\n                var label = EditorGUI.BeginProperty(controlRect, Styles.projection, orthographic);\n\n                projectionType = (ProjectionType)EditorGUI.EnumPopup(controlRect, label, projectionType);\n                EditorGUI.showMixedValue = false;\n                if (EditorGUI.EndChangeCheck())\n                    orthographic.boolValue = (projectionType == ProjectionType.Orthographic);\n                EditorGUI.EndProperty();\n\n                if (!orthographic.hasMultipleDifferentValues)\n                {\n                    if (projectionType == ProjectionType.Orthographic)\n                        EditorGUILayout.PropertyField(orthographicSize, Styles.size);\n                    else\n                    {\n                        float fovCurrentValue;\n                        var multipleDifferentFovValues = false;\n                        var isPhysicalCamera = projectionMatrixMode.intValue == (int)Camera.ProjectionMatrixMode.PhysicalPropertiesBased;\n\n                        var rect = EditorGUILayout.GetControlRect();\n                        var guiContent = EditorGUI.BeginProperty(rect, Styles.FOVAxisMode, fovAxisMode);\n                        EditorGUI.showMixedValue = fovAxisMode.hasMultipleDifferentValues;\n\n                        EditorGUI.BeginChangeCheck();\n                        var fovAxisNewVal = (int)(Camera.FieldOfViewAxis)EditorGUI.EnumPopup(rect, guiContent, (Camera.FieldOfViewAxis)fovAxisMode.intValue);\n                        if (EditorGUI.EndChangeCheck())\n                            fovAxisMode.intValue = fovAxisNewVal;\n                        EditorGUI.EndProperty();\n\n                        var fovAxisVertical = fovAxisMode.intValue == 0;\n                        var targets = m_SerializedObject.targetObjects;\n                        var camera0 = targets[0] as Camera;\n                        var aspectRatio = isPhysicalCamera ? sensorSize.vector2Value.x / sensorSize.vector2Value.y : camera0.aspect;\n\n                        if (!fovAxisVertical && !fovAxisMode.hasMultipleDifferentValues)\n                        {\n                            // camera.aspect is not serialized so we have to check all targets.\n                            fovCurrentValue = Camera.VerticalToHorizontalFieldOfView(camera0.fieldOfView, aspectRatio);\n                            if (m_SerializedObject.targetObjectsCount > 1)\n                            {\n                                foreach (Camera camera in targets)\n                                {\n                                    if (camera.fieldOfView != fovCurrentValue)\n                                    {\n                                        multipleDifferentFovValues = true;\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                        else\n                        {\n                            fovCurrentValue = verticalFOV.floatValue;\n                            multipleDifferentFovValues = fovAxisMode.hasMultipleDifferentValues;\n                        }\n\n                        EditorGUI.showMixedValue = multipleDifferentFovValues;\n                        var content = EditorGUI.BeginProperty(EditorGUILayout.BeginHorizontal(), Styles.fieldOfView, verticalFOV);\n                        EditorGUI.BeginDisabled(projectionMatrixMode.hasMultipleDifferentValues || isPhysicalCamera && (sensorSize.hasMultipleDifferentValues || fovAxisMode.hasMultipleDifferentValues));\n                        EditorGUI.BeginChangeCheck();\n                        var fovMinValue = fovAxisVertical ? 0.00001f : Camera.VerticalToHorizontalFieldOfView(0.00001f, aspectRatio);\n                        var fovMaxValue = fovAxisVertical ? 179.0f : Camera.VerticalToHorizontalFieldOfView(179.0f, aspectRatio);\n                        var fovNewValue = EditorGUILayout.Slider(content, fovCurrentValue, fovMinValue, fovMaxValue);\n                        var fovChanged = EditorGUI.EndChangeCheck();\n                        EditorGUI.EndDisabled();\n                        EditorGUILayout.EndHorizontal();\n                        EditorGUI.EndProperty();\n                        EditorGUI.showMixedValue = false;\n\n                        content = EditorGUI.BeginProperty(EditorGUILayout.BeginHorizontal(), Styles.physicalCamera, projectionMatrixMode);\n                        EditorGUI.showMixedValue = projectionMatrixMode.hasMultipleDifferentValues;\n\n                        EditorGUI.BeginChangeCheck();\n                        isPhysicalCamera = EditorGUILayout.Toggle(content, isPhysicalCamera);\n                        if (EditorGUI.EndChangeCheck())\n                            projectionMatrixMode.intValue = isPhysicalCamera ? (int)Camera.ProjectionMatrixMode.PhysicalPropertiesBased : (int)Camera.ProjectionMatrixMode.Implicit;\n                        EditorGUILayout.EndHorizontal();\n                        EditorGUI.EndProperty();\n\n                        EditorGUI.showMixedValue = false;\n                        if (isPhysicalCamera && !projectionMatrixMode.hasMultipleDifferentValues)\n                        {\n                            using (new EditorGUI.IndentLevelScope())\n                            {\n                                EditorGUILayout.PropertyField(iso, Styles.iso);\n                                EditorGUILayout.PropertyField(shutterSpeed, Styles.shutterSpeed);\n                                EditorGUILayout.PropertyField(aperture, Styles.aperture);\n                                EditorGUILayout.PropertyField(focusDistance, Styles.focusDistance);\n                                EditorGUILayout.PropertyField(bladeCount, Styles.bladeCount);\n                                EditorGUILayout.PropertyField(curvature, Styles.curvature);\n                                EditorGUILayout.PropertyField(barrelClipping, Styles.barrelClipping);\n                                EditorGUILayout.PropertyField(anamorphism, Styles.anamorphism);\n\n                                using (var horizontal = new EditorGUILayout.HorizontalScope())\n                                using (new EditorGUI.PropertyScope(horizontal.rect, Styles.focalLength, focalLength))\n                                using (var checkScope = new EditorGUI.ChangeCheckScope())\n                                {\n                                    EditorGUI.showMixedValue = focalLength.hasMultipleDifferentValues;\n                                    var sensorLength = fovAxisVertical ? sensorSize.vector2Value.y : sensorSize.vector2Value.x;\n                                    var focalLengthVal = fovChanged ? Camera.FieldOfViewToFocalLength(fovNewValue, sensorLength) : focalLength.floatValue;\n                                    focalLengthVal = EditorGUILayout.FloatField(Styles.focalLength, focalLengthVal);\n                                    if (checkScope.changed || fovChanged)\n                                        focalLength.floatValue = focalLengthVal;\n                                }\n\n                                EditorGUI.showMixedValue = sensorSize.hasMultipleDifferentValues;\n                                EditorGUI.BeginChangeCheck();\n                                var filmGateIndex = Array.IndexOf(k_ApertureFormatValues, new Vector2((float)Math.Round(sensorSize.vector2Value.x, 3), (float)Math.Round(sensorSize.vector2Value.y, 3)));\n                                if (filmGateIndex == -1)\n                                    filmGateIndex = EditorGUILayout.Popup(Styles.cameraType, k_ApertureFormats.Length - 1, k_ApertureFormats);\n                                else\n                                    filmGateIndex = EditorGUILayout.Popup(Styles.cameraType, filmGateIndex, k_ApertureFormats);\n                                EditorGUI.showMixedValue = false;\n                                if (EditorGUI.EndChangeCheck() && filmGateIndex < k_ApertureFormatValues.Length)\n                                {\n                                    sensorSize.vector2Value = k_ApertureFormatValues[filmGateIndex];\n                                }\n\n                                EditorGUILayout.PropertyField(sensorSize, Styles.sensorSize);\n                                EditorGUILayout.PropertyField(lensShift, Styles.lensShift);\n\n                                using (var horizontal = new EditorGUILayout.HorizontalScope())\n                                using (var propertyScope = new EditorGUI.PropertyScope(horizontal.rect, Styles.gateFit, gateFit))\n                                using (var checkScope = new EditorGUI.ChangeCheckScope())\n                                {\n                                    var gateValue = (int)(Camera.GateFitMode)EditorGUILayout.EnumPopup(propertyScope.content, (Camera.GateFitMode)gateFit.intValue);\n                                    if (checkScope.changed)\n                                        gateFit.intValue = gateValue;\n                                }\n                            }\n                        }\n                        else if (fovChanged)\n                        {\n                            verticalFOV.floatValue = fovAxisVertical ? fovNewValue : Camera.HorizontalToVerticalFieldOfView(fovNewValue, (m_SerializedObject.targetObjects[0] as Camera).aspect);\n                        }\n\n                        EditorGUILayout.Space();\n                    }\n                }\n            }\n\n            public void DrawClippingPlanes()\n            {\n                EditorGUILayout.PropertiesField(EditorGUI.s_ClipingPlanesLabel, new[] { nearClippingPlane, farClippingPlane }, EditorGUI.s_NearAndFarLabels, EditorGUI.kNearFarLabelsWidth);\n            }\n\n            public void DrawNormalizedViewPort()\n            {\n                EditorGUILayout.PropertyField(normalizedViewPortRect, Styles.viewportRect);\n            }\n\n            public void DrawDepth()\n            {\n                EditorGUILayout.PropertyField(depth);\n            }\n\n            public void DrawRenderingPath()\n            {\n                EditorGUILayout.IntPopup(renderingPath, k_CameraRenderPaths, k_CameraRenderPathValues, Styles.renderingPath);\n            }\n\n            public void DrawTargetTexture(bool deferred)\n            {\n                EditorGUILayout.PropertyField(targetTexture);\n\n                // show warning if we have deferred but manual MSAA set\n                // only do this if the m_TargetTexture has the same values across all target cameras\n                if (!deferred || targetTexture.hasMultipleDifferentValues)\n                    return;\n\n                var renderTexture = this.targetTexture.objectReferenceValue as RenderTexture;\n                if (renderTexture && renderTexture.antiAliasing > 1)\n                    EditorGUILayout.HelpBox(Styles.deferredMSAAWarning.text, MessageType.Warning, true);\n            }\n\n            public void DrawOcclusionCulling()\n            {\n                EditorGUILayout.PropertyField(occlusionCulling, Styles.allowOcclusionCulling);\n            }\n\n            public void DrawHDR()\n            {\n                var rect = EditorGUILayout.GetControlRect(true);\n                EditorGUI.BeginProperty(rect, Styles.allowHDR, HDR);\n                var value = HDR.boolValue ? 1 : 0;\n                value = EditorGUI.IntPopup(rect, Styles.allowHDR, value, k_DefaultOptions, k_DefaultOptionValues);\n                HDR.boolValue = value == 1;\n                EditorGUI.EndProperty();\n            }\n\n            public void DrawMSAA()\n            {\n                var rect = EditorGUILayout.GetControlRect(true);\n                EditorGUI.BeginProperty(rect, Styles.allowMSAA, allowMSAA);\n                var value = allowMSAA.boolValue ? 1 : 0;\n                value = EditorGUI.IntPopup(rect, Styles.allowMSAA, value, k_DefaultOptions, k_DefaultOptionValues);\n                allowMSAA.boolValue = value == 1;\n                EditorGUI.EndProperty();\n            }\n\n            public void DrawDynamicResolution()\n            {\n                EditorGUILayout.PropertyField(allowDynamicResolution, Styles.allowDynamicResolution);\n                if ((allowDynamicResolution.boolValue || allowDynamicResolution.hasMultipleDifferentValues) && !PlayerSettings.enableFrameTimingStats)\n                    EditorGUILayout.HelpBox(Styles.dynamicResolutionTimingWarning.text, MessageType.Warning, true);\n            }\n\n            [Obsolete(\"This API is deprecated and will be removed. Please use XRManagement package instead.\", false)]\n            public void DrawVR()\n            {\n            }\n\n            public void DrawMultiDisplay()\n            {\n                if (!showMultiDisplayOptions)\n                    return;\n\n                var prevDisplay = targetDisplay.intValue;\n                EditorGUILayout.IntPopup(targetDisplay, DisplayUtility.GetDisplayNames(), DisplayUtility.GetDisplayIndices(), Styles.targetDisplay);\n                if (prevDisplay != targetDisplay.intValue)\n                    PlayModeView.RepaintAll();\n            }\n\n            public void DrawTargetEye()\n            {\n                EditorGUILayout.IntPopup(targetEye, k_TargetEyes, k_TargetEyeValues, Styles.xrTargetEye);\n            }\n\n            public static void DrawCameraWarnings(Camera camera)\n            {\n                var warnings = camera.GetCameraBufferWarnings();\n                if (warnings.Length > 0)\n                    EditorGUILayout.HelpBox(string.Join(\"\\n\\n\", warnings), MessageType.Info, true);\n            }\n        }\n\n        readonly AnimatedBool m_ShowBGColorOptions = new();\n        readonly AnimatedBool m_ShowOrthoOptions = new();\n        readonly AnimatedBool m_ShowTargetEyeOption = new();\n\n        Camera camera => target as Camera;\n\n        Camera m_PreviewCamera;\n\n        [Obsolete(\"Preview camera is obsolete, use Overlays to create a Camera preview.\")]\n        protected Camera previewCamera\n        {\n            get\n            {\n                if (m_PreviewCamera == null)\n                {\n                    // Only log a warning once when creating the camera so that we don't flood the console with\n                    // redundant logs.\n                    Debug.LogWarning(\"Preview camera is obsolete, use Overlays to create a Camera preview.\");\n                    m_PreviewCamera = EditorUtility.CreateGameObjectWithHideFlags(\"Preview Camera\", HideFlags.HideAndDontSave, typeof(Camera), typeof(Skybox)).GetComponent<Camera>();\n                }\n\n                m_PreviewCamera.enabled = false;\n                return m_PreviewCamera;\n            }\n        }\n\n        static bool showMultiDisplayOptions\n        {\n            get => ModuleManager.ShouldShowMultiDisplayOption();\n        }\n\n        bool wantsDeferredRendering\n        {\n            get\n            {\n                var isCamDeferred = camera.renderingPath == RenderingPath.DeferredShading;\n                var isTierDeferred = Rendering.EditorGraphicsSettings.GetCurrentTierSettings().renderingPath == RenderingPath.DeferredShading;\n                return isCamDeferred || (camera.renderingPath == RenderingPath.UsePlayerSettings && isTierDeferred);\n            }\n        }\n\n        internal bool showBackgroundColorOptions => !settings.clearFlags.hasMultipleDifferentValues && camera.clearFlags is CameraClearFlags.SolidColor or CameraClearFlags.Skybox;\n\n        internal bool showOrthographicOptions => !settings.orthographic.hasMultipleDifferentValues && settings.orthographic.boolValue;\n\n        internal bool showPerspectiveOptions => !settings.orthographic.hasMultipleDifferentValues && !settings.orthographic.boolValue;\n\n        internal bool showPhysicalCameraOptions => settings.projectionMatrixMode.intValue == (int)Camera.ProjectionMatrixMode.PhysicalPropertiesBased;\n\n        internal bool showOrthographicXRWarning => k_DisplayDescriptors.Count > 0 && settings.targetEye.intValue != (int)StereoTargetEyeMask.None && camera.orthographic && camera.targetTexture == null;\n\n        internal bool showOrthographicDeferredWarning => showOrthographicOptions && wantsDeferredRendering;\n\n        internal bool showDeferredMSAAWarning\n        {\n            get\n            {\n                // show warning if we have deferred but manual MSAA set\n                // only do this if the m_TargetTexture has the same values across all target cameras\n                var singleValue = !settings.targetTexture.hasMultipleDifferentValues;\n                var targetTextureValue = settings.targetTexture.objectReferenceValue as RenderTexture;\n                var wantsAntiAliasing = targetTextureValue != null && targetTextureValue.antiAliasing > 1;\n                return singleValue && wantsAntiAliasing && wantsDeferredRendering;\n            }\n        }\n\n        internal bool showDynamicResolutionTimingWarning => (settings.allowDynamicResolution.boolValue || settings.allowDynamicResolution.hasMultipleDifferentValues) && !PlayerSettings.enableFrameTimingStats;\n\n        bool showTargetEyeOption => settings.targetEye.intValue != (int)StereoTargetEyeMask.Both || k_DisplayDescriptors.Count > 0;\n\n        // Camera's depth texture mode is not serialized data, so can't get to it through\n        // serialized property (hence no multi-edit).\n        internal bool showDepthTextureMode => targets.Length == 1 && target is Camera { depthTextureMode: not DepthTextureMode.None };\n\n        // Command buffers are not serialized data, so can't get to them through\n        // serialized property (hence no multi-edit).\n        internal bool showCommandBufferGUI => targets.Length == 1 && target is Camera { commandBufferCount: > 0 };\n\n        internal enum ProjectionType\n        {\n            Perspective,\n            Orthographic\n        }\n\n        bool m_CommandBuffersShown = true;\n\n        Settings m_Settings;\n        protected internal Settings settings => m_Settings ??= new Settings(serializedObject);\n\n        internal static readonly List<XRDisplaySubsystemDescriptor> k_DisplayDescriptors = new();\n\n        uint m_LastNonSerializedVersion;\n        internal event Action onSettingsChanged;\n\n        static void OnReloadSubsystemsComplete()\n        {\n            SubsystemManager.GetSubsystemDescriptors(k_DisplayDescriptors);\n        }\n\n        public void OnEnable()\n        {\n            settings.OnEnable();\n\n            var c = (Camera)target;\n            m_ShowBGColorOptions.value = showBackgroundColorOptions;\n            m_ShowOrthoOptions.value = showOrthographicOptions;\n            m_ShowTargetEyeOption.value = showTargetEyeOption;\n\n            m_ShowBGColorOptions.valueChanged.AddListener(Repaint);\n            m_ShowOrthoOptions.valueChanged.AddListener(Repaint);\n            m_ShowTargetEyeOption.valueChanged.AddListener(Repaint);\n\n            SubsystemManager.GetSubsystemDescriptors(k_DisplayDescriptors);\n            SubsystemManager.afterReloadSubsystems += OnReloadSubsystemsComplete;\n        }\n\n        public void OnDestroy()\n        {\n            if (m_PreviewCamera != null)\n                DestroyImmediate(m_PreviewCamera.gameObject, true);\n        }\n\n        public void OnDisable()\n        {\n            m_ShowBGColorOptions.valueChanged.RemoveListener(Repaint);\n            m_ShowOrthoOptions.valueChanged.RemoveListener(Repaint);\n            m_ShowTargetEyeOption.valueChanged.RemoveListener(Repaint);\n        }\n\n        bool TryGetDepthTextureModeString(out string depthTextureModeString)\n        {\n            depthTextureModeString = string.Empty;\n\n            var buffers = new List<string>();\n            if ((camera.depthTextureMode & DepthTextureMode.Depth) != 0)\n                buffers.Add(\"Depth\");\n            if ((camera.depthTextureMode & DepthTextureMode.DepthNormals) != 0)\n                buffers.Add(\"DepthNormals\");\n            if ((camera.depthTextureMode & DepthTextureMode.MotionVectors) != 0)\n                buffers.Add(\"MotionVectors\");\n\n            if (buffers.Count == 0)\n                return false;\n\n            var sb = new StringBuilder(\"Info: renders \");\n            for (var i = 0; i < buffers.Count; ++i)\n            {\n                if (i != 0)\n                    sb.Append(\" & \");\n\n                sb.Append(buffers[i]);\n            }\n\n            sb.Append(buffers.Count > 1 ? \" textures\" : \" texture\");\n            depthTextureModeString = sb.ToString();\n            return true;\n        }\n\n        void DepthTextureModeGUI()\n        {\n            if (!showDepthTextureMode || !TryGetDepthTextureModeString(out var depthTextureModeInfo))\n                return;\n\n            EditorGUILayout.HelpBox(depthTextureModeInfo, MessageType.None, true);\n        }\n\n        static Rect GetRemoveButtonRect(Rect r)\n        {\n            var buttonSize = Styles.invisibleButton.CalcSize(Styles.iconRemove);\n            return new Rect(r.xMax - buttonSize.x, r.y + (int)(r.height / 2 - buttonSize.y / 2), buttonSize.x, buttonSize.y);\n        }\n\n        /**\n         * Draws the 2D bounds of the camera when in 2D mode.\n         */\n        [DrawGizmo(GizmoType.NonSelected)]\n        static void DrawCameraBound(Camera camera, GizmoType gizmoType)\n        {\n            if (!(SceneView.currentDrawingSceneView?.in2DMode ?? false))\n                return;\n\n            if (camera == Camera.main && camera.orthographic)\n                RenderGizmo(camera);\n        }\n\n        void CommandBufferGUI()\n        {\n            if(!showCommandBufferGUI)\n                return;\n\n            m_CommandBuffersShown = GUILayout.Toggle(m_CommandBuffersShown, GUIContent.Temp(camera.commandBufferCount + \" command buffers\"), EditorStyles.foldout);\n            if (!m_CommandBuffersShown)\n                return;\n            EditorGUI.indentLevel++;\n            foreach (var ce in (CameraEvent[])Enum.GetValues(typeof(CameraEvent)))\n            {\n                var cbs = camera.GetCommandBuffers(ce);\n                foreach (var cb in cbs)\n                {\n                    using (new GUILayout.HorizontalScope())\n                    {\n                        // row with event & command buffer information label\n                        var rowRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.miniLabel);\n                        rowRect.xMin += EditorGUI.indent;\n                        var minusRect = GetRemoveButtonRect(rowRect);\n                        rowRect.xMax = minusRect.x;\n                        GUI.Label(rowRect, string.Format(\"{0}: {1} ({2})\", ce, cb.name, EditorUtility.FormatBytes(cb.sizeInBytes)), EditorStyles.miniLabel);\n                        // and a button to remove it\n                        Styles.invisibleButton ??= new GUIStyle(\"InvisibleButton\");\n                        if (GUI.Button(minusRect, Styles.iconRemove, Styles.invisibleButton))\n                        {\n                            camera.RemoveCommandBuffer(ce, cb);\n                            SceneView.RepaintAll();\n                            PlayModeView.RepaintAll();\n                            GUIUtility.ExitGUI();\n                        }\n                    }\n                }\n            }\n\n            // \"remove all\" button\n            using (new GUILayout.HorizontalScope())\n            {\n                GUILayout.FlexibleSpace();\n                if (GUILayout.Button(\"Remove all\", EditorStyles.miniButton))\n                {\n                    camera.RemoveAllCommandBuffers();\n                    SceneView.RepaintAll();\n                    PlayModeView.RepaintAll();\n                }\n            }\n\n            EditorGUI.indentLevel--;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            settings.Update();\n\n            var c = (Camera)target;\n            m_ShowBGColorOptions.target = showBackgroundColorOptions;\n            m_ShowOrthoOptions.target = showOrthographicOptions;\n            m_ShowTargetEyeOption.target = showTargetEyeOption;\n\n            settings.DrawClearFlags();\n\n            if (EditorGUILayout.BeginFadeGroup(m_ShowBGColorOptions.faded))\n                settings.DrawBackgroundColor();\n            EditorGUILayout.EndFadeGroup();\n\n            settings.DrawCullingMask();\n\n            EditorGUILayout.Space();\n\n            settings.DrawProjection();\n\n            if (showOrthographicXRWarning)\n                GUILayout.Label(Styles.orthoXRWarning);\n\n            settings.DrawClippingPlanes();\n\n            settings.DrawNormalizedViewPort();\n\n            EditorGUILayout.Space();\n            settings.DrawDepth();\n            settings.DrawRenderingPath();\n\n            if (showOrthographicDeferredWarning)\n                EditorGUILayout.HelpBox(Styles.orthoDeferredWarning.text, MessageType.Warning, true);\n\n            settings.DrawTargetTexture(wantsDeferredRendering);\n            settings.DrawOcclusionCulling();\n            settings.DrawHDR();\n            settings.DrawMSAA();\n            settings.DrawDynamicResolution();\n\n            foreach (Camera camera in targets)\n            {\n                if (camera != null)\n                {\n                    Settings.DrawCameraWarnings(camera);\n                }\n            }\n\n            EditorGUILayout.Space();\n            settings.DrawMultiDisplay();\n\n            if (EditorGUILayout.BeginFadeGroup(m_ShowTargetEyeOption.faded))\n                settings.DrawTargetEye();\n            EditorGUILayout.EndFadeGroup();\n\n            DepthTextureModeGUI();\n            CommandBufferGUI();\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        // marked obsolete @karlh 2021/02/13\n        [Obsolete(\"OnOverlayGUI is obsolete. Use global Cameras Overlay instead.\")]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public virtual void OnOverlayGUI(Object target, SceneView sceneView)\n        {\n        }\n\n        // marked obsolete @thomastu 2023/04/05\n        [Obsolete(\"CreatePreviewOverlay is obsolete. Use global Cameras Overlay instead.\", false)]\n        public virtual Overlay CreatePreviewOverlay(Camera cam) => SceneViewCameraOverlay.GetOrCreateCameraOverlay(cam);\n\n        [RequiredByNativeCode]\n        internal static float GetGameViewAspectRatio()\n        {\n            var gameViewSize = PlayModeView.GetMainPlayModeViewTargetSize();\n            if (gameViewSize.x < 0f)\n            {\n                // Fallback to Scene View of not a valid game view size\n                gameViewSize.x = Screen.width;\n                gameViewSize.y = Screen.height;\n            }\n\n            return gameViewSize.x / gameViewSize.y;\n        }\n\n        [RequiredByNativeCode]\n        internal static void GetMainPlayModeViewSize(out Vector2 size)\n        {\n            size = PlayModeView.GetMainPlayModeViewTargetSize();\n        }\n\n        // Called from C++ when we need to render a Camera's gizmo\n        [RequiredByNativeCode]\n        internal static void RenderGizmo(Camera camera) => CameraEditorUtils.DrawFrustumGizmo(camera);\n\n        static Vector2 s_PreviousMainPlayModeViewTargetSize;\n\n        public virtual void OnSceneGUI()\n        {\n            if (!target)\n                return;\n            var c = (Camera)target;\n\n            if (!CameraEditorUtils.IsViewportRectValidToRender(c.rect))\n                return;\n\n            var currentMainPlayModeViewTargetSize = PlayModeView.GetMainPlayModeViewTargetSize();\n            if (s_PreviousMainPlayModeViewTargetSize != currentMainPlayModeViewTargetSize)\n            {\n                // a gameView size change can affect horizontal FOV, refresh the inspector when that happens.\n                Repaint();\n                s_PreviousMainPlayModeViewTargetSize = currentMainPlayModeViewTargetSize;\n            }\n\n            CameraEditorUtils.HandleFrustum(c, referenceTargetIndex);\n        }\n\n        static T ExtendedQuery<T>(VisualElement editor, string elementName, SerializedProperty property) where T : VisualElement\n        {\n            var content = EditorGUIUtility.TrTextContent(property.displayName, property.tooltip);\n            return ExtendedQuery<T>(editor, elementName, content);\n        }\n\n        static T ExtendedQuery<T>(VisualElement editor, string elementName, GUIContent content) where T : VisualElement\n        {\n            var result = editor.MandatoryQ<T>(elementName);\n\n            switch (result)\n            {\n                case PropertyField field:\n                    field.label = content.text;\n                    break;\n\n                case DropdownField field:\n                    field.label = content.text;\n                    break;\n\n                case EnumField field:\n                    field.label = content.text;\n                    break;\n\n                case Toggle toggle:\n                    toggle.label = content.text;\n                    break;\n\n                case Slider slider:\n                    slider.label = content.text;\n                    break;\n\n                case FloatField field:\n                    field.label = content.text;\n                    break;\n\n                case ClippingPlanes planes:\n                    planes.label = content.text;\n                    break;\n\n                case HelpBox box:\n                    box.text = content.text;\n                    break;\n            }\n\n            result.tooltip = content.tooltip;\n            return result;\n        }\n\n        public override VisualElement CreateInspectorGUI()\n        {\n            var editor = new VisualElement();\n            var c = (Camera)target;\n            \n            var visualTree = EditorGUIUtility.Load(Styles.k_CameraEditorUxmlPath) as VisualTreeAsset;\n            visualTree?.CloneTree(editor);\n\n            var clearFlags = ExtendedQuery<PropertyField>(editor, Styles.k_ClearFlagsElementName, Styles.clearFlags);\n            var backgroundColor = ExtendedQuery<PropertyField>(editor, Styles.k_BackgroundElementName, Styles.background);\n            ExtendedQuery<PropertyField>(editor, Styles.k_CullingMaskElementName, Styles.cullingMask);\n\n            var backgroundCheck = UIElementsEditorUtility.CreateDynamicVisibilityCallback(backgroundColor, () => showBackgroundColorOptions);\n            clearFlags.RegisterValueChangeCallback(e => backgroundCheck.Invoke());\n\n            SetupProjectionParameters(editor);\n\n            var clippingPlanes = ExtendedQuery<ClippingPlanes>(editor, Styles.k_ClippingPlanesElementName, EditorGUI.s_ClipingPlanesLabel);\n            clippingPlanes.nearClip = settings.nearClippingPlane;\n            clippingPlanes.farClip = settings.farClippingPlane;\n\n            ExtendedQuery<PropertyField>(editor, Styles.k_ViewportRectElementName, Styles.viewportRect);\n            ExtendedQuery<PropertyField>(editor, Styles.k_DepthElementName, settings.depth);\n\n            var renderingPath = ExtendedQuery<DropdownField>(editor, Styles.k_RenderingPathElementName, Styles.renderingPath);\n            var renderingPathUpdate = UIElementsEditorUtility.BindSerializedProperty(renderingPath, settings.renderingPath, Settings.k_CameraRenderPaths, Settings.k_CameraRenderPathValues);\n\n            var orthographicDeferredWarning = ExtendedQuery<HelpBox>(editor, Styles.k_OrthographicDeferredWarningElementName, Styles.orthoDeferredWarning);\n            var orthographicDeferrednCheck = UIElementsEditorUtility.CreateDynamicVisibilityCallback(orthographicDeferredWarning, () => showOrthographicDeferredWarning);\n\n            var deferredMSAAWarning = ExtendedQuery<HelpBox>(editor, Styles.k_DeferredMsaaWarningElementName, Styles.deferredMSAAWarning);\n            var deferredMSAACheck = UIElementsEditorUtility.CreateDynamicVisibilityCallback(deferredMSAAWarning, () => showDeferredMSAAWarning);\n\n            ExtendedQuery<PropertyField>(editor, Styles.k_TargetTextureElementName, settings.targetTexture);\n            ExtendedQuery<PropertyField>(editor, Styles.k_OcclusionCullingElementName, Styles.allowOcclusionCulling);\n\n            var hdr = ExtendedQuery<DropdownField>(editor, Styles.k_HdrElementName, Styles.allowHDR);\n            var msaa = ExtendedQuery<DropdownField>(editor, Styles.k_MsaaElementName, Styles.allowMSAA);\n            var hdrUpdate = UIElementsEditorUtility.BindSerializedProperty(hdr, settings.HDR, Settings.k_DefaultOptions, Settings.k_DefaultOptionValues);\n            var msaaUpdate = UIElementsEditorUtility.BindSerializedProperty(msaa, settings.allowMSAA, Settings.k_DefaultOptions, Settings.k_DefaultOptionValues);\n\n            ExtendedQuery<PropertyField>(editor, Styles.k_DynamicResolution, Styles.allowDynamicResolution);\n\n            var dynamicResolutionTimingWarning = ExtendedQuery<HelpBox>(editor, Styles.k_DynamicResolutionTimingWarningElementName, Styles.dynamicResolutionTimingWarning);\n            var dynamicResolutionTimingCheck = UIElementsEditorUtility.CreateDynamicVisibilityCallback(dynamicResolutionTimingWarning, () => showDynamicResolutionTimingWarning);\n\n            var cameraWarnings = editor.MandatoryQ<VisualElement>(Styles.k_CameraWarningsElementName);\n            var cameraWarningsUpdate = UIElementsEditorUtility.CreateDynamicVisibilityCallback(cameraWarnings, () =>\n            {\n                var visible = false;\n                cameraWarnings.Clear();\n\n                foreach (var target in targets)\n                {\n                    if (target is not Camera camera)\n                        continue;\n\n                    var warnings = camera.GetCameraBufferWarnings();\n\n                    if (warnings.Length == 0)\n                        continue;\n\n                    cameraWarnings.Add(new HelpBox(string.Join(\"\\n\\n\", warnings), HelpBoxMessageType.Warning));\n                    visible = true;\n                }\n\n                return visible;\n            });\n\n            Action targetDisplayCheck;\n            Action targetDisplayUpdate;\n            var targetDisplay = ExtendedQuery<DropdownField>(editor, Styles.k_TargetDisplayElementName, Styles.targetDisplay);\n            var choiceContents = DisplayUtility.GetDisplayNames();\n            targetDisplay.choices = new List<string>(choiceContents.Length);\n\n            foreach (var choiceContent in choiceContents)\n                targetDisplay.choices.Add(choiceContent.text);\n\n            targetDisplayCheck = UIElementsEditorUtility.CreateDynamicVisibilityCallback(targetDisplay, () => showMultiDisplayOptions);\n            targetDisplayUpdate = UIElementsEditorUtility.BindSerializedProperty(targetDisplay, settings.targetDisplay, DisplayUtility.GetDisplayNames(), DisplayUtility.GetDisplayIndices());\n            \n            var targetEye = ExtendedQuery<DropdownField>(editor, Styles.k_TargetEyeElementName, Styles.xrTargetEye);\n            var targetEyeCheck = UIElementsEditorUtility.CreateDynamicVisibilityCallback(targetEye, () => showTargetEyeOption);\n            var targetEyeUpdate = UIElementsEditorUtility.BindSerializedProperty(targetEye, settings.targetEye, Settings.k_TargetEyes, Settings.k_TargetEyeValues);\n\n            var depthTextureMode = editor.MandatoryQ<HelpBox>(Styles.k_DepthTextureModeElementName);\n            var depthTextureModeCheck = UIElementsEditorUtility.CreateDynamicVisibilityCallback(depthTextureMode, () =>\n            {\n                if (!showDepthTextureMode || !TryGetDepthTextureModeString(out var info))\n                    return false;\n\n                depthTextureMode.text = info;\n                return true;\n            });\n\n            var buffers = new List<CommandBuffer>();\n            var bufferEvents = new Dictionary<CommandBuffer, CameraEvent>();\n            var commandBuffers = editor.MandatoryQ<Foldout>(Styles.k_CommandBuffersElementName);\n            var list = commandBuffers.MandatoryQ<ListView>(Styles.k_CommandBuffersListElementName);\n\n            var commandBuffersUpdate = UIElementsEditorUtility.CreateDynamicVisibilityCallback(commandBuffers, () =>\n            {\n                commandBuffers.text = L10n.Tr($\"{c.commandBufferCount} command buffers\");\n\n                buffers.Clear();\n                bufferEvents.Clear();\n                foreach (var ce in (CameraEvent[])Enum.GetValues(typeof(CameraEvent)))\n                {\n                    var cbs = camera.GetCommandBuffers(ce);\n                    foreach (var cb in cbs)\n                    {\n                        buffers.Add(cb);\n                        bufferEvents[cb] = ce;\n                    }\n                }\n                list.Rebuild();\n\n                return showCommandBufferGUI;\n            });\n            list.makeItem = () =>\n            {\n                var entry = new VisualElement();\n                entry.AddToClassList(Styles.commandBufferUssClassName);\n\n                var label = new Label();\n                label.AddToClassList(Styles.commandBufferLabelUssClassName);\n\n                var button = new VisualElement();\n                button.AddToClassList(Styles.commandBufferRemoveButtonUssClassName);\n                button.RegisterCallback<ClickEvent>(e =>\n                {\n                    var cameraEvent = (CameraEvent)entry.userData;\n                    var commandBuffer = (CommandBuffer)label.userData;\n\n                    camera.RemoveCommandBuffer(cameraEvent, commandBuffer);\n                    SceneView.RepaintAll();\n                    PlayModeView.RepaintAll();\n\n                    commandBuffersUpdate?.Invoke();\n                });\n\n                entry.Add(label);\n                entry.Add(button);\n                return entry;\n            };\n            list.bindItem = (v, i) =>\n            {\n                var cb = buffers[i];\n                var ce = bufferEvents[cb];\n\n                var label = v.Q<Label>();\n                label.text = $\"{ce}: {cb.name} ({EditorUtility.FormatBytes(cb.sizeInBytes)})\";\n                label.userData = cb;\n                v.userData = ce;\n            };\n            list.itemsSource = buffers;\n\n            var removeAll = editor.MandatoryQ<Button>(Styles.k_CommandBuffersRemoveAllElementName);\n            removeAll.RegisterCallback<ClickEvent>(e =>\n            {\n                c.RemoveAllCommandBuffers();\n                SceneView.RepaintAll();\n                PlayModeView.RepaintAll();\n\n                commandBuffersUpdate?.Invoke();\n            });\n\n            onSettingsChanged += () =>\n            {\n                clippingPlanes.Update();\n\n                renderingPathUpdate?.Invoke();\n                hdrUpdate?.Invoke();\n                msaaUpdate?.Invoke();\n                targetDisplayUpdate?.Invoke();\n                targetEyeUpdate?.Invoke();\n\n                orthographicDeferrednCheck?.Invoke();\n                deferredMSAACheck?.Invoke();\n                dynamicResolutionTimingCheck?.Invoke();\n                depthTextureModeCheck?.Invoke();\n                cameraWarningsUpdate?.Invoke();\n\n                targetDisplayCheck?.Invoke();\n                targetEyeCheck?.Invoke();\n                commandBuffersUpdate?.Invoke();\n            };\n\n            editor.RegisterCallback<AttachToPanelEvent>(e => EditorApplication.tick += UpdateNonSerializedIfNeeded);\n            editor.RegisterCallback<DetachFromPanelEvent>(e => EditorApplication.tick -= UpdateNonSerializedIfNeeded);\n            editor.TrackSerializedObjectValue(serializedObject, (so) => onSettingsChanged?.Invoke());\n\n            return editor;\n        }\n\n        void UpdateNonSerializedIfNeeded()\n        {\n            if (m_LastNonSerializedVersion == camera.m_NonSerializedVersion)\n                return;\n\n            onSettingsChanged?.Invoke();\n            m_LastNonSerializedVersion = camera.m_NonSerializedVersion;\n        }\n\n        void SetupProjectionParameters(VisualElement contents)\n        {\n            var perspectiveGroup = contents.MandatoryQ<VisualElement>(Styles.k_PerspectiveGroupElementName);\n            var perspectiveGroupCheck = UIElementsEditorUtility.CreateDynamicVisibilityCallback(perspectiveGroup, () => showPerspectiveOptions);\n\n            var orthographicGroup = contents.MandatoryQ<VisualElement>(Styles.k_OrthographicGroupElementName);\n            var orthographicGroupCheck = UIElementsEditorUtility.CreateDynamicVisibilityCallback(orthographicGroup, () => showOrthographicOptions);\n\n            var projectionType = ExtendedQuery<EnumField>(contents, Styles.k_ProjectionTypeElementName, Styles.projection);\n            var projectionTypeUpdate = UIElementsEditorUtility.BindSerializedProperty<ProjectionType>(projectionType, settings.orthographic, _ =>\n            {\n                orthographicGroupCheck?.Invoke();\n                perspectiveGroupCheck?.Invoke();\n            });\n\n            var fovAxisMode = ExtendedQuery<EnumField>(contents, Styles.k_FovAxisModeElementName, Styles.FOVAxisMode);\n            var fovAxisModeUpdate = UIElementsEditorUtility.BindSerializedProperty<Camera.FieldOfViewAxis>(fovAxisMode, settings.fovAxisMode);\n\n            var fieldOfView = ExtendedQuery<Slider>(contents, Styles.k_FieldOfViewElementName, Styles.fieldOfView);\n            fieldOfView.SetEnabled(!fovAxisMode.showMixedValue);\n\n            var physicalCameraGroup = contents.MandatoryQ<VisualElement>(Styles.k_PhysicalCameraGroupElementName);\n            var physicalCameraGroupCheck = UIElementsEditorUtility.CreateDynamicVisibilityCallback(physicalCameraGroup, () => showPhysicalCameraOptions);\n\n            var physicalCamera = ExtendedQuery<Toggle>(contents, Styles.k_PhysicalCameraElementName, Styles.physicalCamera);\n            var physicalCameraUpdate = UIElementsEditorUtility.BindSerializedProperty(physicalCamera, settings.projectionMatrixMode,\n                p => p.intValue == (int)Camera.ProjectionMatrixMode.PhysicalPropertiesBased,\n                (v, p) =>\n                {\n                    p.intValue = (int)(v ? Camera.ProjectionMatrixMode.PhysicalPropertiesBased : Camera.ProjectionMatrixMode.Implicit);\n                    p.serializedObject.ApplyModifiedProperties();\n                    physicalCameraGroupCheck?.Invoke();\n                });\n\n            ExtendedQuery<PropertyField>(contents, Styles.k_IsoElementName, Styles.iso);\n            ExtendedQuery<PropertyField>(contents, Styles.k_ShutterSpeedElementName, Styles.shutterSpeed);\n            ExtendedQuery<PropertyField>(contents, Styles.k_ApertureElementName, Styles.aperture);\n            ExtendedQuery<PropertyField>(contents, Styles.k_FocusDistanceElementName, Styles.focusDistance);\n            ExtendedQuery<PropertyField>(contents, Styles.k_BladeCountElementName, Styles.bladeCount);\n            ExtendedQuery<PropertyField>(contents, Styles.k_CurvatureElementName, Styles.curvature);\n            ExtendedQuery<PropertyField>(contents, Styles.k_BarrelClippingElementName, Styles.barrelClipping);\n            ExtendedQuery<PropertyField>(contents, Styles.k_AnamorphismElementName, Styles.anamorphism);\n\n            var fieldOfViewUpdate = UIElementsEditorUtility.BindSerializedProperty(fieldOfView, settings.verticalFOV,\n                p =>\n                {\n                    var isPhysicalCamera = settings.projectionMatrixMode.intValue == (int)Camera.ProjectionMatrixMode.PhysicalPropertiesBased;\n                    var fovAxisVertical = settings.fovAxisMode.intValue == (int)Camera.FieldOfViewAxis.Vertical;\n                    var aspectRatio = isPhysicalCamera ? settings.sensorSize.vector2Value.x / settings.sensorSize.vector2Value.y : camera.aspect;\n                    \n                    fieldOfView.lowValue = fovAxisVertical ? 0.00001f : Camera.VerticalToHorizontalFieldOfView(0.00001f, aspectRatio);\n                    fieldOfView.highValue = fovAxisVertical ? 179.0f : Camera.VerticalToHorizontalFieldOfView(179.0f, aspectRatio);\n                    return fovAxisVertical ? settings.verticalFOV.floatValue : Camera.VerticalToHorizontalFieldOfView(settings.verticalFOV.floatValue, aspectRatio);\n                },\n                (fov, p) =>\n                {\n                    var isPhysicalCamera = settings.projectionMatrixMode.intValue == (int)Camera.ProjectionMatrixMode.PhysicalPropertiesBased;\n                    var fovAxisVertical = settings.fovAxisMode.intValue == (int)Camera.FieldOfViewAxis.Vertical;\n                    var aspectRatio = isPhysicalCamera ? settings.sensorSize.vector2Value.x / settings.sensorSize.vector2Value.y : camera.aspect;\n\n                    p.floatValue = fovAxisVertical ? fov : Camera.HorizontalToVerticalFieldOfView(fov, aspectRatio);\n                    p.serializedObject.ApplyModifiedProperties();\n                });\n\n            var focalLength = ExtendedQuery<FloatField>(contents, Styles.k_FocalLengthElementName, Styles.focalLength);\n            var focalLengthUpdate = UIElementsEditorUtility.BindSerializedProperty(focalLength, settings.focalLength,\n                p =>\n                {\n                    var fovAxisVertical = settings.fovAxisMode.intValue == (int)Camera.FieldOfViewAxis.Vertical;\n                    var sensorLength = fovAxisVertical ? settings.sensorSize.vector2Value.y : settings.sensorSize.vector2Value.x;\n                    return Camera.FieldOfViewToFocalLength(fieldOfView.value, sensorLength);\n                },\n                (v, p) =>\n                {\n                    var isPhysicalCamera = settings.projectionMatrixMode.intValue == (int)Camera.ProjectionMatrixMode.PhysicalPropertiesBased;\n\n                    if (!isPhysicalCamera)\n                        return;\n\n                    p.floatValue = v;\n                    p.serializedObject.ApplyModifiedProperties();\n                });\n\n            var sensorType = ExtendedQuery<DropdownField>(contents, Styles.k_SensorTypeElementName, Styles.cameraType);\n            sensorType.choices = new List<string>(Settings.k_ApertureFormats.Length);\n\n            foreach (var apertureFormat in Settings.k_ApertureFormats)\n                sensorType.choices.Add(apertureFormat);\n\n            var sensorTypeUpdate = UIElementsEditorUtility.BindSerializedProperty(sensorType, settings.sensorSize,\n                p =>\n                {\n                    var approximateApertureFormat = new Vector2((float)Math.Round(p.vector2Value.x, 3), (float)Math.Round(p.vector2Value.y, 3));\n                    var index = Array.IndexOf(Settings.k_ApertureFormatValues, approximateApertureFormat);\n                    return index >= 0 ? index : Settings.k_ApertureFormatValues.Length;\n                },\n                (i, p) =>\n                {\n                    if (i < 0 || i >= Settings.k_ApertureFormatValues.Length)\n                        return;\n\n                    p.vector2Value = Settings.k_ApertureFormatValues[i];\n                    p.serializedObject.ApplyModifiedProperties();\n                });\n\n            ExtendedQuery<PropertyField>(contents, Styles.k_SensorSizeElementName, Styles.sensorSize);\n            ExtendedQuery<PropertyField>(contents, Styles.k_LensShiftElementName, Styles.lensShift);\n\n            var gateFit = ExtendedQuery<EnumField>(contents, Styles.k_GateFitElementName, Styles.gateFit);\n            var gateFitUpdate = UIElementsEditorUtility.BindSerializedProperty<Camera.GateFitMode>(gateFit, settings.gateFit);\n\n            // Cannot bind serialized properties with spaces in them via UI Builder\n            var orthographicSize = ExtendedQuery<PropertyField>(contents, Styles.k_OrthographicSizeElementName, Styles.size);\n            orthographicSize.BindProperty(settings.orthographicSize);\n\n            var orthographicXRWarning = ExtendedQuery<HelpBox>(contents, Styles.k_OrthographicXrWarningElementName, Styles.orthoXRWarning);\n            var orthographicXRCheck = UIElementsEditorUtility.CreateDynamicVisibilityCallback(orthographicXRWarning, () => showOrthographicXRWarning);\n\n            onSettingsChanged += () =>\n            {\n                projectionTypeUpdate?.Invoke();\n                fovAxisModeUpdate?.Invoke();\n                physicalCameraUpdate?.Invoke();\n                fieldOfViewUpdate?.Invoke();\n                focalLengthUpdate?.Invoke();\n                sensorTypeUpdate?.Invoke();\n                gateFitUpdate?.Invoke();\n\n                orthographicXRCheck?.Invoke();\n                physicalCameraGroupCheck?.Invoke();\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/CameraEditorUtils.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Experimental.Rendering;\nusing UnityEngine.SceneManagement;\nusing UnityEngine.Rendering;\nusing System;\n\nnamespace UnityEditor\n{\n    public static class CameraEditorUtils\n    {\n        static readonly Color k_ColorThemeCameraGizmo = new Color(233f / 255f, 233f / 255f, 233f / 255f, 128f / 255f);\n        static readonly Color k_ColorThemeCameraSensorGizmo = new Color(180f / 255f, 180f / 255f, 180f / 255f, 128f / 255f);\n\n        public static float GameViewAspectRatio => CameraEditor.GetGameViewAspectRatio();\n\n        static int s_MovingHandleId = 0;\n        static Vector3 s_InitialFarMid;\n        static readonly int[] s_FrustumHandleIds =\n        {\n            \"CameraEditor_FrustumHandleTop\".GetHashCode(),\n            \"CameraEditor_FrustumHandleBottom\".GetHashCode(),\n            \"CameraEditor_FrustumHandleLeft\".GetHashCode(),\n            \"CameraEditor_FrustumHandleRight\".GetHashCode()\n        };\n\n        public static Func<Camera> virtualCameraPreviewInstantiator\n        {\n            get => CameraPreviewUtils.s_VirtualCameraPreviewInstantiator;\n            set => CameraPreviewUtils.s_VirtualCameraPreviewInstantiator = value;\n        }\n\n        public static void HandleFrustum(Camera c, int cameraEditorTargetIndex)\n        {\n            bool ContainsHandleId(int targetId)\n            {\n                foreach (int id in s_FrustumHandleIds)\n                    if (id == targetId)\n                        return true;\n                return false;\n            }\n\n            if (c.projectionMatrixMode == Camera.ProjectionMatrixMode.Explicit)\n                return;\n            Color orgHandlesColor = Handles.color;\n            Color slidersColor = k_ColorThemeCameraGizmo;\n            slidersColor.a *= 2f;\n            Handles.color = slidersColor;\n\n            // get the corners of the far clip plane in world space\n            var far = new Vector3[4];\n            float frustumAspect;\n            if (c.usePhysicalProperties)\n            {\n                if (!TryGetSensorGateFrustum(c, null, far, out frustumAspect))\n                    return;\n            }\n            else\n            {\n                if (!TryGetFrustum(c, null, far, out frustumAspect))\n                    return;\n            }\n\n            var leftBottomFar = far[0];\n            var leftTopFar = far[1];\n            var rightTopFar = far[2];\n            var rightBottomFar = far[3];\n\n            // manage our own gui changed state, so we can use it for individual slider changes\n            bool guiChanged = GUI.changed;\n\n            Vector3 farMid = Vector3.Lerp(leftBottomFar, rightTopFar, 0.5f);\n            if (s_MovingHandleId != 0)\n            {\n                if (!ContainsHandleId(GUIUtility.hotControl - cameraEditorTargetIndex))\n                    s_MovingHandleId = GUIUtility.hotControl;\n                else\n                    farMid = s_InitialFarMid;\n            }\n            else if (ContainsHandleId(GUIUtility.hotControl - cameraEditorTargetIndex))\n            {\n                s_MovingHandleId = GUIUtility.hotControl;\n                s_InitialFarMid = farMid;\n            }\n\n            // FOV handles\n            // Top and bottom handles\n            float halfHeight = -1.0f;\n            Vector3 changedPosition = MidPointPositionSlider(s_FrustumHandleIds[0] + cameraEditorTargetIndex, leftTopFar, rightTopFar, c.transform.up);\n            if (!GUI.changed)\n                changedPosition = MidPointPositionSlider(s_FrustumHandleIds[1] + cameraEditorTargetIndex, leftBottomFar, rightBottomFar, -c.transform.up);\n            if (GUI.changed)\n                halfHeight = (changedPosition - farMid).magnitude;\n\n            // Left and right handles\n            GUI.changed = false;\n            changedPosition = MidPointPositionSlider(s_FrustumHandleIds[2] + cameraEditorTargetIndex, rightBottomFar, rightTopFar, c.transform.right);\n            if (!GUI.changed)\n                changedPosition = MidPointPositionSlider(s_FrustumHandleIds[3] + cameraEditorTargetIndex, leftBottomFar, leftTopFar, -c.transform.right);\n            if (GUI.changed)\n                halfHeight = (changedPosition - farMid).magnitude / frustumAspect;\n\n            // Update camera settings if changed\n            if (halfHeight >= 0.0f)\n            {\n                Undo.RecordObject(c, \"Adjust Camera\");\n                if (c.orthographic)\n                {\n                    c.orthographicSize = halfHeight;\n                }\n                else\n                {\n                    Vector3 posUp = farMid + c.transform.up * halfHeight;\n                    Vector3 posDown = farMid - c.transform.up * halfHeight;\n                    Vector3 nearMid = farMid - c.transform.forward * c.farClipPlane;\n                    c.fieldOfView = Vector3.Angle((posDown - nearMid), (posUp - nearMid));\n                }\n                guiChanged = true;\n            }\n\n            GUI.changed = guiChanged;\n            Handles.color = orgHandlesColor;\n        }\n\n        public static void DrawFrustumGizmo(Camera camera)\n        {\n            var near = new Vector3[4];\n            var far = new Vector3[4];\n            float frustumAspect;\n            if (camera.usePhysicalProperties)\n            {\n                if (TryGetSensorGateFrustum(camera, null, far, out frustumAspect))\n                {\n                    Color orgColor = Handles.color;\n                    Handles.color = k_ColorThemeCameraSensorGizmo;\n                    for (int i = 0; i < 4; ++i)\n                    {\n                        Handles.DrawLine(far[i], far[(i + 1) % 4]);\n                    }\n                    Handles.color = orgColor;\n                }\n                if (TryGetFrustum(camera, near, far, out frustumAspect))\n                {\n                    Color orgColor = Handles.color;\n                    Handles.color = k_ColorThemeCameraGizmo;\n                    for (int i = 0; i < 4; ++i)\n                    {\n                        Handles.DrawLine(far[i], far[(i + 1) % 4]);\n                        Handles.DrawLine(near[i], far[i]);\n                        Handles.DrawLine(near[i], near[(i + 1) % 4]);\n                    }\n                    Handles.color = orgColor;\n                }\n            }\n            else if (TryGetFrustum(camera, near, far, out frustumAspect))\n            {\n                Color orgColor = Handles.color;\n                Handles.color = k_ColorThemeCameraGizmo;\n                for (int i = 0; i < 4; ++i)\n                {\n                    Handles.DrawLine(near[i], near[(i + 1) % 4]);\n                    Handles.DrawLine(far[i], far[(i + 1) % 4]);\n                    Handles.DrawLine(near[i], far[i]);\n                }\n                Handles.color = orgColor;\n            }\n        }\n\n        // Returns near- and far-corners in this order: leftBottom, leftTop, rightTop, rightBottom\n        // Assumes input arrays are of length 4 (if allocated)\n        public static bool TryGetSensorGateFrustum(Camera camera, Vector3[] near, Vector3[] far, out float frustumAspect)\n        {\n            frustumAspect = GetFrustumAspectRatio(camera);\n            if (frustumAspect < 0)\n                return false;\n\n            if (far != null)\n            {\n                Vector2 planeSize;\n                planeSize.y = camera.farClipPlane * Mathf.Tan(Mathf.Deg2Rad * camera.fieldOfView * 0.5f);\n                planeSize.x = planeSize.y * camera.sensorSize.x / camera.sensorSize.y;\n\n                Vector3 rightOffset = camera.gameObject.transform.right * planeSize.x;\n                Vector3 upOffset = camera.gameObject.transform.up * planeSize.y;\n                Vector3 localAim = camera.GetLocalSpaceAim() * camera.farClipPlane;\n                localAim.z = -localAim.z;\n\n                Vector3 planePosition = camera.cameraToWorldMatrix.MultiplyPoint(localAim);\n\n                far[0] = planePosition - rightOffset - upOffset; // leftBottom\n                far[1] = planePosition - rightOffset + upOffset; // leftTop\n                far[2] = planePosition + rightOffset + upOffset; // rightTop\n                far[3] = planePosition + rightOffset - upOffset; // rightBottom\n            }\n\n            if (near != null)\n            {\n                Vector2 planeSize;\n                planeSize.y = camera.nearClipPlane * Mathf.Tan(Mathf.Deg2Rad * camera.fieldOfView * 0.5f);\n                planeSize.x = planeSize.y * camera.sensorSize.x / camera.sensorSize.y;\n\n                Vector3 rightOffset = camera.gameObject.transform.right * planeSize.x;\n                Vector3 upOffset = camera.gameObject.transform.up * planeSize.y;\n                Vector3 localAim = camera.GetLocalSpaceAim() * camera.nearClipPlane;\n                localAim.z = -localAim.z;\n\n                Vector3 planePosition = camera.cameraToWorldMatrix.MultiplyPoint(localAim);\n\n                near[0] = planePosition - rightOffset - upOffset; // leftBottom\n                near[1] = planePosition - rightOffset + upOffset; // leftTop\n                near[2] = planePosition + rightOffset + upOffset; // rightTop\n                near[3] = planePosition + rightOffset - upOffset; // rightBottom\n            }\n            return true;\n        }\n\n        // Returns near- and far-corners in this order: leftBottom, leftTop, rightTop, rightBottom\n        // Assumes input arrays are of length 4 (if allocated)\n        public static bool TryGetFrustum(Camera camera, Vector3[] near, Vector3[] far, out float frustumAspect)\n        {\n            frustumAspect = GetFrustumAspectRatio(camera);\n            if (frustumAspect < 0)\n                return false;\n\n            if (far != null)\n            {\n                if (camera.projectionMatrixMode == (int)Camera.ProjectionMatrixMode.Explicit)\n                {\n                    far[0] = new Vector3(0, 0, camera.farClipPlane); // leftBottomFar\n                    far[1] = new Vector3(0, 1, camera.farClipPlane); // leftTopFar\n                    far[2] = new Vector3(1, 1, camera.farClipPlane); // rightTopFar\n                    far[3] = new Vector3(1, 0, camera.farClipPlane); // rightBottomFar\n                    for (int i = 0; i < 4; ++i)\n                        far[i] = camera.ViewportToWorldPoint(far[i]);\n                }\n                else\n                {\n                    CalculateFrustumPlaneAt(camera, camera.farClipPlane, far);\n                }\n            }\n\n            if (near != null)\n            {\n                if (camera.projectionMatrixMode == (int)Camera.ProjectionMatrixMode.Explicit)\n                {\n                    near[0] = new Vector3(0, 0, camera.nearClipPlane); // leftBottomNear\n                    near[1] = new Vector3(0, 1, camera.nearClipPlane); // leftTopNear\n                    near[2] = new Vector3(1, 1, camera.nearClipPlane); // rightTopNear\n                    near[3] = new Vector3(1, 0, camera.nearClipPlane); // rightBottomNear\n                    for (int i = 0; i < 4; ++i)\n                        near[i] = camera.ViewportToWorldPoint(near[i]);\n                }\n                else\n                {\n                    CalculateFrustumPlaneAt(camera, camera.nearClipPlane, near);\n                }\n            }\n            return true;\n        }\n\n        private static void CalculateFrustumPlaneAt(Camera camera, float distance, Vector3[] plane)\n        {\n            Vector2 planeSize = camera.GetFrustumPlaneSizeAt(distance) * .5f;\n            Vector3 rightOffset = camera.gameObject.transform.right * planeSize.x;\n            Vector3 upOffset = camera.gameObject.transform.up * planeSize.y;\n            Vector3 localAim = camera.GetLocalSpaceAim() * distance;\n            localAim.z = -localAim.z;\n\n            Vector3 planePosition = camera.cameraToWorldMatrix.MultiplyPoint(localAim);\n\n            plane[0] = planePosition - rightOffset - upOffset; // leftBottom\n            plane[1] = planePosition - rightOffset + upOffset; // leftTop\n            plane[2] = planePosition + rightOffset + upOffset; // rightTop\n            plane[3] = planePosition + rightOffset - upOffset; // rightBottom\n        }\n\n        public static bool IsViewportRectValidToRender(Rect normalizedViewPortRect)\n        {\n            if (normalizedViewPortRect.width <= 0f || normalizedViewPortRect.height <= 0f)\n                return false;\n            if (normalizedViewPortRect.x >= 1f || normalizedViewPortRect.xMax <= 0f)\n                return false;\n            if (normalizedViewPortRect.y >= 1f || normalizedViewPortRect.yMax <= 0f)\n                return false;\n            return true;\n        }\n\n        public static float GetFrustumAspectRatio(Camera camera)\n        {\n            var normalizedViewPortRect = camera.rect;\n            if (normalizedViewPortRect.width <= 0f || normalizedViewPortRect.height <= 0f)\n                return -1f;\n\n            return camera.usePhysicalProperties ?\n                camera.sensorSize.x / camera.sensorSize.y : GameViewAspectRatio * normalizedViewPortRect.width / normalizedViewPortRect.height;\n        }\n\n        public static Vector3 PerspectiveClipToWorld(Matrix4x4 clipToWorld, Vector3 viewPositionWS, Vector3 positionCS)\n        {\n            var tempCS = new Vector3(positionCS.x, positionCS.y, 0.95f);\n            var result = clipToWorld.MultiplyPoint(tempCS);\n            var r = result - viewPositionWS;\n            return r.normalized * positionCS.z + viewPositionWS;\n        }\n\n        public static void GetFrustumPlaneAt(Matrix4x4 clipToWorld, Vector3 viewPosition, float distance, Vector3[] points)\n        {\n            points[0] = new Vector3(-1, -1, distance); // leftBottomFar\n            points[1] = new Vector3(-1, 1, distance); // leftTopFar\n            points[2] = new Vector3(1, 1, distance); // rightTopFar\n            points[3] = new Vector3(1, -1, distance); // rightBottomFar\n            for (var i = 0; i < 4; ++i)\n                points[i] = PerspectiveClipToWorld(clipToWorld, viewPosition, points[i]);\n        }\n\n        static Vector3 MidPointPositionSlider(int controlID, Vector3 position1, Vector3 position2, Vector3 direction)\n        {\n            Vector3 midPoint = Vector3.Lerp(position1, position2, 0.5f);\n            return Handles.Slider(controlID, midPoint, direction, HandleUtility.GetHandleSize(midPoint) * 0.03f, Handles.DotHandleCap, 0f);\n        }\n    }\n\n    internal static class CameraPreviewUtils\n    {\n        static Camera s_PreviewCamera;\n        static RenderTexture s_PreviewTexture;\n\n        internal static Func<Camera> s_VirtualCameraPreviewInstantiator;\n\n        internal struct PreviewSettings\n        {\n            public Vector2 size;\n            public ulong overrideSceneCullingMask;\n            public Scene scene;\n            public bool useHDR;\n\n            public float aspect => size.x / size.y;\n\n            internal PreviewSettings(Vector2 previewSize)\n            {\n                size = previewSize;\n                overrideSceneCullingMask = 0;\n                scene = default;\n                useHDR = false;\n            }\n        }\n\n        class SavedStateForCameraPreview : IDisposable\n        {\n            Camera m_Target;\n\n            public CameraType cameraType;\n            public ulong overrideSceneCullingMask;\n            public RenderTexture renderTarget;\n            public Scene scene;\n\n            public SavedStateForCameraPreview()\n            {\n                m_Target = null;\n                renderTarget = null;\n                overrideSceneCullingMask = 0;\n                cameraType = CameraType.Game;\n                scene = default;\n            }\n\n            public SavedStateForCameraPreview(Camera source)\n            {\n                m_Target = source;\n\n                renderTarget = source.targetTexture;\n                overrideSceneCullingMask = source.overrideSceneCullingMask;\n                cameraType = source.cameraType;\n                scene = source.scene;\n            }\n\n            public void Dispose()\n            {\n                m_Target.targetTexture = renderTarget;\n                m_Target.overrideSceneCullingMask = overrideSceneCullingMask;\n                m_Target.cameraType = cameraType;\n                m_Target.scene = scene;\n            }\n        }\n\n        static RenderTexture GetPreviewTexture(int width,  int height, bool hdr)\n        {\n            if (s_PreviewTexture != null\n                && (s_PreviewTexture.width != width || s_PreviewTexture.height != height))\n            {\n                s_PreviewTexture.Release();\n\n                s_PreviewTexture.width = width;\n                s_PreviewTexture.height = height;\n            }\n\n            if (s_PreviewTexture == null)\n            {\n                GraphicsFormat format = (hdr) ? SystemInfo.GetGraphicsFormat(DefaultFormat.HDR) : SystemInfo.GetGraphicsFormat(DefaultFormat.LDR);\n                s_PreviewTexture = new RenderTexture(width, height, 24, format);\n            }\n\n            if (GraphicsSettings.currentRenderPipeline == null)\n            {\n                // Built-in Render Pipeline, ensure that antiAliasing is set to 1 or more\n                s_PreviewTexture.antiAliasing = Math.Max(1, QualitySettings.antiAliasing);\n            }\n            else\n            {\n                // SRPs\n                s_PreviewTexture.enableRandomWrite = true;\n            }\n\n            return s_PreviewTexture;\n        }\n\n        static Camera previewCamera\n        {\n            get\n            {\n                if (s_PreviewCamera == null && CameraEditorUtils.virtualCameraPreviewInstantiator != null)\n                    s_PreviewCamera = CameraEditorUtils.virtualCameraPreviewInstantiator();\n\n                if (s_PreviewCamera == null)\n                {\n                    s_PreviewCamera = EditorUtility.CreateGameObjectWithHideFlags(\"Preview Camera\",\n                        HideFlags.HideAndDontSave,\n                        typeof(Camera)).GetComponent<Camera>();\n\n                    s_PreviewCamera.enabled = false;\n                    s_PreviewCamera.cameraType = CameraType.Preview;\n                }\n                return s_PreviewCamera;\n            }\n        }\n\n        internal static RenderTexture GetPreview(Camera camera, PreviewSettings settings)\n        {\n            if (RenderPipeline.SupportsRenderRequest(camera, new RenderPipeline.StandardRequest()))\n                return RenderInternal(camera, settings);\n            return RenderPreviewWithCameraCopy(camera, settings);\n        }\n\n        internal static RenderTexture GetPreview(IViewpoint virtualCameraSource, PreviewSettings settings)\n        {\n            var sourceCamera = virtualCameraSource.TargetObject as Camera;\n            if (sourceCamera)\n                return GetPreview(sourceCamera, settings);\n\n            // Viewpoint represents a virtual camera.\n            ViewpointUtility.ApplyTransformData(virtualCameraSource, previewCamera.gameObject.transform);\n            ViewpointUtility.ApplyCameraLensData(virtualCameraSource as ICameraLensData, previewCamera);\n\n            return RenderInternal(previewCamera, settings);\n        }\n\n        static RenderTexture RenderPreviewWithCameraCopy(Camera sourceCamera, PreviewSettings settings)\n        {\n            previewCamera.CopyFrom(sourceCamera);\n\n            // Only for Legacy/Built-in Render Pipeline.\n            if (GraphicsSettings.currentRenderPipeline == null)\n            {\n                // Make sure to sync any Skybox component on the preview camera\n                var dstSkybox = previewCamera.GetComponent<Skybox>();\n                if (dstSkybox == null)\n                    dstSkybox = previewCamera.gameObject.AddComponent<Skybox>();\n\n                var srcSkybox = sourceCamera.GetComponent<Skybox>();\n                if (srcSkybox && srcSkybox.enabled)\n                {\n                    dstSkybox.enabled = true;\n                    dstSkybox.material = srcSkybox.material;\n                }\n                else\n                {\n                    dstSkybox.enabled = false;\n                }\n            }\n\n            Handles.EmitGUIGeometryForCamera(sourceCamera, previewCamera);\n\n            return RenderInternal(previewCamera, settings);\n        }\n\n        static RenderTexture RenderInternal(Camera cameraToRender, PreviewSettings settings)\n        {\n            var rt = GetPreviewTexture((int)settings.size.x, (int)settings.size.y, settings.useHDR);\n\n            // When sensor size is reduced, the previous frame is still visible behind so we need to clear the texture before rendering.\n            if (cameraToRender.usePhysicalProperties)\n            {\n                RenderTexture oldRt = RenderTexture.active;\n                RenderTexture.active = rt;\n                GL.Clear(false, true, Color.clear);\n                RenderTexture.active = oldRt;\n            }\n\n            // Honor async shader compilation editor settings for this preview\n            bool oldShaderAsyncState = ShaderUtil.allowAsyncCompilation;\n            ShaderUtil.allowAsyncCompilation = EditorSettings.asyncShaderCompilation;\n\n            using (new SavedStateForCameraPreview(cameraToRender))\n            {\n                // make sure the preview camera is rendering the same stage as the SceneView is\n                if (settings.overrideSceneCullingMask != 0)\n                    cameraToRender.overrideSceneCullingMask = settings.overrideSceneCullingMask;\n                else\n                    cameraToRender.scene = settings.scene;\n\n                RenderPipeline.StandardRequest request = new RenderPipeline.StandardRequest()\n                {\n                    destination = rt,\n                };\n\n                // Use RenderRequest API when the active SRP supports it for implementation-agnostic rendering.\n                if (RenderPipeline.SupportsRenderRequest(cameraToRender, request))\n                    cameraToRender.SubmitRenderRequest<RenderPipeline.StandardRequest>(request);\n                else\n                {\n                    // Built-in RP and SRPs that don't support the RenderRequest API will\n                    // render the old way.\n                    previewCamera.targetTexture = rt;\n                    previewCamera.Render();\n                }\n            }\n\n            ShaderUtil.allowAsyncCompilation = oldShaderAsyncState;\n            return rt;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/CameraOverlay.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Overlays;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing static UnityEditor.CameraPreviewUtils;\n\nnamespace UnityEditor\n{\n    // marked obsolete @thomastu 2023/04/05\n    [Obsolete(\"This Overlay is obsolete. Use the global Cameras Overlay instead.\", false)]\n    [Overlay(id = k_OverlayID, displayName = k_DisplayName, defaultDisplay = false)]\n    [Icon(\"Icons/Overlays/CameraPreview.png\")]\n    class SceneViewCameraOverlay : IMGUIOverlay\n    {\n        internal static bool forceDisable = false;\n\n        // should match color in GizmosDrawers.cpp\n        const float kPreviewNormalizedSize = 0.2f;\n        const string k_OverlayID = \"Scene View/Camera\";\n        const string k_DisplayName = \"Camera Preview\";\n\n        Camera m_SelectedCamera;\n        Camera selectedCamera => m_SelectedCamera;\n\n        static Dictionary<Camera, (SceneViewCameraOverlay overlay, int count)> s_CameraOverlays = new Dictionary<Camera, (SceneViewCameraOverlay, int)>();\n\n        SceneViewCameraOverlay(Camera camera)\n        {\n            minSize = new Vector2(40, 40);\n            maxSize = new Vector2(4000, 4000);\n            defaultSize = new Vector2(240, 135);\n            m_SelectedCamera = camera;\n            displayName = selectedCamera == null || string.IsNullOrEmpty(selectedCamera.name)\n                ? \"Camera Preview\"\n                : selectedCamera.name;\n\n            s_CameraOverlays.Add(camera, (this ,1));\n        }\n\n        public static SceneViewCameraOverlay GetOrCreateCameraOverlay(Camera camera)\n        {\n            if (s_CameraOverlays.ContainsKey(camera))\n            {\n                var value = s_CameraOverlays[camera];\n                value.count += 1;\n                s_CameraOverlays[camera] = value;\n                return value.overlay;\n            }\n\n            var overlay = new SceneViewCameraOverlay(camera);\n            SceneView.AddOverlayToActiveView(overlay);\n            return overlay;\n        }\n\n        public static void DisableCameraOverlay(Camera cam)\n        {\n            if (s_CameraOverlays.ContainsKey(cam))\n            {\n                var value = s_CameraOverlays[cam];\n                value.count -= 1;\n                if (value.count == 0)\n                {\n                    s_CameraOverlays.Remove(cam);\n                    SceneView.RemoveOverlayFromActiveView(value.overlay);\n                }\n                else\n                    s_CameraOverlays[cam] = value;\n            }\n        }\n\n        void UpdateSize()\n        {\n            if (!sizeOverridden)\n                size = new Vector2(240, 135);\n        }\n\n        public override void OnGUI()\n        {\n            if (selectedCamera == null)\n            {\n                GUILayout.Label(\"No camera selected\", EditorStyles.centeredGreyMiniLabel);\n                return;\n            }\n\n            if (!CameraEditorUtils.IsViewportRectValidToRender(selectedCamera.rect))\n                return;\n\n            imguiContainer.style.flexGrow = 1;\n            var sceneView = SceneView.lastActiveSceneView;\n\n            // Do not render the Camera Preview overlay if the target camera GameObject is not part of the objects the\n            // SceneView is rendering\n            if (!sceneView.IsGameObjectInThisSceneView(selectedCamera.gameObject))\n                return;\n\n            var cameraRect = imguiContainer.rect;\n            cameraRect.width = Mathf.Floor(cameraRect.width);\n\n            if (cameraRect.width < 1 || cameraRect.height < 1 || float.IsNaN(cameraRect.width) || float.IsNaN(cameraRect.height))\n                return;\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                Graphics.DrawTexture(cameraRect, Texture2D.whiteTexture, new Rect(0, 0, 1, 1), 0, 0, 0, 0, Color.black);\n\n                Vector2 previewSize = selectedCamera.targetTexture\n                    ? new Vector2(selectedCamera.targetTexture.width, selectedCamera.targetTexture.height)\n                    : PlayModeView.GetMainPlayModeViewTargetSize();\n\n                if (previewSize.x < 0f)\n                {\n                    // Fallback to Scene View of not a valid game view size\n                    previewSize.x = sceneView.position.width;\n                    previewSize.y = sceneView.position.height;\n                }\n\n                float rectAspect = cameraRect.width / cameraRect.height;\n                float previewAspect = previewSize.x / previewSize.y;\n                Rect previewRect = cameraRect;\n                if (rectAspect > previewAspect)\n                {\n                    float stretch = previewAspect / rectAspect;\n                    previewRect = new Rect(cameraRect.xMin + cameraRect.width * (1.0f - stretch) * .5f, cameraRect.yMin, stretch * cameraRect.width, cameraRect.height);\n                }\n                else\n                {\n                    float stretch = rectAspect / previewAspect;\n                    previewRect = new Rect(cameraRect.xMin, cameraRect.yMin + cameraRect.height * (1.0f - stretch) * .5f, cameraRect.width, stretch * cameraRect.height);\n                }\n\n                var settings = new PreviewSettings(new Vector2((int)previewRect.width, (int)previewRect.height));\n                settings.overrideSceneCullingMask = sceneView.overrideSceneCullingMask;\n                settings.scene = sceneView.customScene;\n\n                var previewTexture = CameraPreviewUtils.GetPreview(selectedCamera, settings);\n\n                Graphics.DrawTexture(previewRect, previewTexture, new Rect(0, 0, 1, 1), 0, 0, 0, 0, GUI.color, EditorGUIUtility.GUITextureBlit2SRGBMaterial);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/CanvasEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.AnimatedValues;\nusing UnityEditorInternal.VR;\nusing System.Linq;\n\nnamespace UnityEditor\n{\n    /// <summary>\n    /// Editor class used to edit UI Canvases.\n    /// </summary>\n\n    [CanEditMultipleObjects]\n    [CustomEditor(typeof(Canvas))]\n    internal class CanvasEditor : Editor\n    {\n        SerializedProperty m_RenderMode;\n        SerializedProperty m_Camera;\n        SerializedProperty m_PixelPerfect;\n        SerializedProperty m_PixelPerfectOverride;\n        SerializedProperty m_PlaneDistance;\n        SerializedProperty m_SortingLayerID;\n        SerializedProperty m_SortingOrder;\n        SerializedProperty m_TargetDisplay;\n        SerializedProperty m_OverrideSorting;\n        SerializedProperty m_ShaderChannels;\n        SerializedProperty m_UpdateRectTransformForStandalone;\n        SerializedProperty m_VertexColorAlwaysGammaSpace;\n\n        AnimBool m_OverlayMode;\n        AnimBool m_CameraMode;\n        AnimBool m_WorldMode;\n\n        AnimBool m_SortingOverride;\n\n        private static class Styles\n        {\n            public static GUIContent eventCamera = EditorGUIUtility.TrTextContent(\"Event Camera\", \"The Camera which the events are triggered through. This is used to determine clicking and hover positions if the Canvas is in World Space render mode.\");\n            public static GUIContent renderCamera = EditorGUIUtility.TrTextContent(\"Render Camera\", \"The Camera which will render the canvas. This is also the camera used to send events.\");\n            public static GUIContent sortingOrder = EditorGUIUtility.TrTextContent(\"Sort Order\", \"The order in which Screen Space - Overlay canvas will render\");\n            public static string s_RootAndNestedMessage = \"Cannot multi-edit root Canvas together with nested Canvas.\";\n            public static GUIContent m_SortingLayerStyle = EditorGUIUtility.TrTextContent(\"Sorting Layer\", \"Name of the Renderer's sorting layer\");\n            public static GUIContent targetDisplay = EditorGUIUtility.TrTextContent(\"Target Display\", \"Display on which to render the canvas when in overlay mode\");\n            public static GUIContent m_SortingOrderStyle = EditorGUIUtility.TrTextContent(\"Order in Layer\", \"Renderer's order within a sorting layer\");\n            public static GUIContent m_ShaderChannel = EditorGUIUtility.TrTextContent(\"Additional Shader Channels\");\n            public static GUIContent pixelPerfectContent = EditorGUIUtility.TrTextContent(\"Pixel Perfect\");\n            public static GUIContent standaloneRenderResize = EditorGUIUtility.TrTextContent(\"Resize Canvas\", \"For manual Camera.Render calls should the canvas resize to match the destination target.\");\n            public static GUIContent vertexColorAlwaysGammaSpace = EditorGUIUtility.TrTextContent(\"Vertex Color Always In Gamma Color Space\", \"UI vertex colors are always in gamma color space disregard of the player settings\");\n        }\n\n        private bool m_AllNested = false;\n        private bool m_AllRoot = false;\n\n        private bool m_AllOverlay = false;\n        private bool m_NoneOverlay = false;\n\n        private string[] shaderChannelOptions = { \"TexCoord1\", \"TexCoord2\", \"TexCoord3\", \"Normal\", \"Tangent\" };\n\n\n        enum PixelPerfect\n        {\n            Inherit,\n            On,\n            Off\n        }\n\n        private PixelPerfect pixelPerfect = PixelPerfect.Inherit;\n\n        void OnEnable()\n        {\n            m_RenderMode = serializedObject.FindProperty(\"m_RenderMode\");\n            m_Camera = serializedObject.FindProperty(\"m_Camera\");\n            m_PixelPerfect = serializedObject.FindProperty(\"m_PixelPerfect\");\n            m_PlaneDistance = serializedObject.FindProperty(\"m_PlaneDistance\");\n\n            m_SortingLayerID = serializedObject.FindProperty(\"m_SortingLayerID\");\n            m_SortingOrder = serializedObject.FindProperty(\"m_SortingOrder\");\n            m_TargetDisplay = serializedObject.FindProperty(\"m_TargetDisplay\");\n            m_OverrideSorting = serializedObject.FindProperty(\"m_OverrideSorting\");\n            m_PixelPerfectOverride = serializedObject.FindProperty(\"m_OverridePixelPerfect\");\n            m_ShaderChannels = serializedObject.FindProperty(\"m_AdditionalShaderChannelsFlag\");\n            m_UpdateRectTransformForStandalone = serializedObject.FindProperty(\"m_UpdateRectTransformForStandalone\");\n            m_VertexColorAlwaysGammaSpace = serializedObject.FindProperty(\"m_VertexColorAlwaysGammaSpace\");\n\n            m_OverlayMode = new AnimBool(m_RenderMode.intValue == 0);\n            m_OverlayMode.valueChanged.AddListener(Repaint);\n\n            m_CameraMode = new AnimBool(m_RenderMode.intValue == 1);\n            m_CameraMode.valueChanged.AddListener(Repaint);\n\n            m_WorldMode = new AnimBool(m_RenderMode.intValue == 2);\n            m_WorldMode.valueChanged.AddListener(Repaint);\n\n            m_SortingOverride = new AnimBool(m_OverrideSorting.boolValue);\n            m_SortingOverride.valueChanged.AddListener(Repaint);\n\n            if (m_PixelPerfectOverride.boolValue)\n                pixelPerfect = m_PixelPerfect.boolValue ? PixelPerfect.On : PixelPerfect.Off;\n            else\n                pixelPerfect = PixelPerfect.Inherit;\n\n            m_AllNested = true;\n            m_AllRoot = true;\n            m_AllOverlay = true;\n            m_NoneOverlay = true;\n\n            for (int i = 0; i < targets.Length; i++)\n            {\n                Canvas canvas = targets[i] as Canvas;\n                Canvas[] parentCanvas = canvas.transform.parent != null ? canvas.transform.parent.GetComponentsInParent<Canvas>(true) : null;\n\n                if (canvas.transform.parent == null || (parentCanvas != null && parentCanvas.Length == 0))\n                    m_AllNested = false;\n                else\n                    m_AllRoot = false;\n\n                RenderMode renderMode = canvas.renderMode;\n\n                if (parentCanvas != null && parentCanvas.Length > 0)\n                    renderMode = parentCanvas[parentCanvas.Length - 1].renderMode;\n\n                if (renderMode == RenderMode.ScreenSpaceOverlay)\n                    m_NoneOverlay = false;\n                else\n                    m_AllOverlay = false;\n            }\n        }\n\n        void OnDisable()\n        {\n            m_OverlayMode.valueChanged.RemoveListener(Repaint);\n            m_CameraMode.valueChanged.RemoveListener(Repaint);\n            m_WorldMode.valueChanged.RemoveListener(Repaint);\n            m_SortingOverride.valueChanged.RemoveListener(Repaint);\n        }\n\n        private void AllRootCanvases()\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_RenderMode);\n            if (EditorGUI.EndChangeCheck())\n            {\n                var rectTransforms = targets.Select(c => (c as Canvas).transform).ToArray();\n                Undo.RegisterCompleteObjectUndo(rectTransforms, \"Modified RectTransform Values\");\n                serializedObject.ApplyModifiedProperties();\n                foreach (Canvas canvas in targets)\n                {\n                    canvas.UpdateCanvasRectTransform(true);\n                }\n                GUIUtility.ExitGUI();\n            }\n\n            m_OverlayMode.target = m_RenderMode.intValue == 0;\n            m_CameraMode.target = m_RenderMode.intValue == 1;\n            m_WorldMode.target = m_RenderMode.intValue == 2;\n\n            EditorGUI.indentLevel++;\n            if (EditorGUILayout.BeginFadeGroup(m_OverlayMode.faded))\n            {\n                DoPixelPerfectGUIForRoot();\n\n                EditorGUILayout.PropertyField(m_SortingOrder, Styles.sortingOrder);\n                GUIContent[] displayNames = DisplayUtility.GetDisplayNames();\n                EditorGUILayout.IntPopup(m_TargetDisplay, displayNames, DisplayUtility.GetDisplayIndices(), Styles.targetDisplay);\n            }\n            EditorGUILayout.EndFadeGroup();\n\n            if (EditorGUILayout.BeginFadeGroup(m_CameraMode.faded))\n            {\n                DoPixelPerfectGUIForRoot();\n\n                EditorGUILayout.PropertyField(m_Camera, Styles.renderCamera);\n\n                if (Event.current.type != EventType.ExecuteCommand && // UUM-64603: make sure the HelpBox addition doesn't collide with other UI changes and causes UI to fail to update properly\n                    m_Camera.objectReferenceValue == null)\n                {\n                    EditorGUILayout.HelpBox(\n                        \"A Screen Space Canvas with no specified camera acts like an Overlay Canvas.\",\n                        MessageType.Warning);\n                }\n\n                if (m_Camera.objectReferenceValue != null)\n                {\n                    EditorGUILayout.PropertyField(m_PlaneDistance);\n                    EditorGUILayout.PropertyField(m_UpdateRectTransformForStandalone, Styles.standaloneRenderResize);\n                }\n\n                EditorGUILayout.Space();\n\n                if (m_Camera.objectReferenceValue != null)\n                    EditorGUILayout.SortingLayerField(Styles.m_SortingLayerStyle, m_SortingLayerID, EditorStyles.popup, EditorStyles.label);\n                EditorGUILayout.PropertyField(m_SortingOrder, Styles.m_SortingOrderStyle);\n            }\n            EditorGUILayout.EndFadeGroup();\n\n            if (EditorGUILayout.BeginFadeGroup(m_WorldMode.faded))\n            {\n                EditorGUILayout.PropertyField(m_Camera, Styles.eventCamera);\n\n                if (Event.current.type != EventType.ExecuteCommand && // UUM-64603: make sure the HelpBox addition doesn't collide with other UI changes and causes UI to fail to update properly\n                    m_Camera.objectReferenceValue == null)\n                {\n                    EditorGUILayout.HelpBox(\n                        \"A World Space Canvas with no specified Event Camera may not register UI events correctly.\",\n                        MessageType.Warning);\n                }\n\n                EditorGUILayout.Space();\n                EditorGUILayout.SortingLayerField(Styles.m_SortingLayerStyle, m_SortingLayerID, EditorStyles.popup);\n                EditorGUILayout.PropertyField(m_SortingOrder, Styles.m_SortingOrderStyle);\n            }\n            EditorGUILayout.EndFadeGroup();\n            EditorGUI.indentLevel--;\n        }\n\n        private void DoPixelPerfectGUIForRoot()\n        {\n            bool pixelPerfectValue = m_PixelPerfect.boolValue;\n\n            EditorGUI.BeginChangeCheck();\n            var rect = EditorGUILayout.GetControlRect();\n            EditorGUI.BeginProperty(rect, Styles.pixelPerfectContent, m_PixelPerfect);\n            pixelPerfectValue = EditorGUI.Toggle(rect, Styles.pixelPerfectContent, pixelPerfectValue);\n            EditorGUI.EndProperty();\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                for (int i = 0; i < targets.Length; i++)\n                {\n                    Canvas canvas = targets[i] as Canvas;\n\n                    Undo.RecordObject(canvas, \"Set Pixel Perfect\");\n                    canvas.pixelPerfect = pixelPerfectValue;\n                }\n            }\n        }\n\n        private void DoPixelPerfectGUIForNested()\n        {\n            EditorGUI.BeginChangeCheck();\n            pixelPerfect = (PixelPerfect)EditorGUILayout.EnumPopup(Styles.pixelPerfectContent, pixelPerfect);\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (pixelPerfect == PixelPerfect.Inherit)\n                {\n                    m_PixelPerfectOverride.boolValue = false;\n                }\n                else\n                {\n                    m_PixelPerfectOverride.boolValue = true;\n                    for (int i = 0; i < targets.Length; i++)\n                    {\n                        Canvas canvas = targets[i] as Canvas;\n\n                        Undo.RecordObject(canvas, \"Set Pixel Perfect\");\n                        canvas.pixelPerfect = pixelPerfect == PixelPerfect.On;\n                    }\n                }\n            }\n        }\n\n        private void AllNestedCanvases()\n        {\n            DoPixelPerfectGUIForNested();\n\n            EditorGUILayout.PropertyField(m_OverrideSorting);\n            m_SortingOverride.target = m_OverrideSorting.boolValue;\n\n            if (EditorGUILayout.BeginFadeGroup(m_SortingOverride.faded))\n            {\n                GUIContent sortingOrderStyle = null;\n                if (m_AllOverlay)\n                {\n                    sortingOrderStyle = Styles.sortingOrder;\n                }\n                else if (m_NoneOverlay)\n                {\n                    sortingOrderStyle = Styles.m_SortingOrderStyle;\n                    EditorGUILayout.SortingLayerField(Styles.m_SortingLayerStyle, m_SortingLayerID, EditorStyles.popup);\n                }\n                if (sortingOrderStyle != null)\n                {\n                    EditorGUILayout.PropertyField(m_SortingOrder, sortingOrderStyle);\n                }\n            }\n            EditorGUILayout.EndFadeGroup();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            if (m_AllRoot || m_AllNested)\n            {\n                if (m_AllRoot)\n                {\n                    AllRootCanvases();\n                }\n                else if (m_AllNested)\n                {\n                    AllNestedCanvases();\n                }\n\n                EditorGUI.BeginChangeCheck();\n                var rect = EditorGUILayout.GetControlRect();\n                EditorGUI.BeginProperty(rect, Styles.m_ShaderChannel, m_ShaderChannels);\n                var newShaderChannelValue = EditorGUI.MaskField(rect, Styles.m_ShaderChannel, m_ShaderChannels.intValue, shaderChannelOptions);\n                EditorGUI.EndProperty();\n\n                if (EditorGUI.EndChangeCheck())\n                    m_ShaderChannels.intValue = newShaderChannelValue;\n\n                if (m_RenderMode.intValue == 0) // Overlay canvas\n                {\n                    if (Event.current.type != EventType.ExecuteCommand && // UUM-64603: make sure the HelpBox addition doesn't collide with other UI changes and causes UI to fail to update properly\n                        ((newShaderChannelValue & (int)AdditionalCanvasShaderChannels.Normal) | (newShaderChannelValue & (int)AdditionalCanvasShaderChannels.Tangent)) != 0)\n                    {\n                        EditorGUILayout.HelpBox(\n                            \"Shader channels Normal and Tangent are most often used with lighting, which an Overlay canvas does not support. Its likely these channels are not needed.\",\n                            MessageType.Warning);\n                    }\n                }\n\n                EditorGUILayout.PropertyField(m_VertexColorAlwaysGammaSpace, Styles.vertexColorAlwaysGammaSpace);\n\n                if (PlayerSettings.colorSpace == ColorSpace.Linear)\n                {\n                    if (Event.current.type != EventType.ExecuteCommand // UUM-64603: make sure the HelpBox addition doesn't collide with other UI changes and causes UI to fail to update properly\n                        && !m_VertexColorAlwaysGammaSpace.boolValue)\n                    {\n                        EditorGUILayout.HelpBox(\n                            \"Keep vertex color in Gamma space to allow gamma to linear color space conversion to happen in UI shaders. This will enhance UI color precision in linear color space.\",\n                            MessageType.Warning);\n                    }\n                }\n            }\n            else\n            {\n                GUILayout.Label(Styles.s_RootAndNestedMessage, EditorStyles.helpBox);\n            }\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/CanvasRendererEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(CanvasRenderer))]\n    [CanEditMultipleObjects]\n    internal class CanvasRendererEditor : Editor\n    {\n        class Styles\n        {\n            public static readonly GUIContent cullTransparentMeshContent = EditorGUIUtility.TrTextContent(\"Cull Transparent Mesh\", \"Cull if the vertex color alpha is close to zero for every vertex of the mesh.\");\n        }\n\n        private SerializedProperty m_CullTransparentMeshProperty;\n\n        void OnEnable()\n        {\n            m_CullTransparentMeshProperty = serializedObject.FindProperty(\"m_CullTransparentMesh\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUILayout.PropertyField(m_CullTransparentMeshProperty, Styles.cullTransparentMeshContent);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ColliderEditorBase.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal abstract class ColliderEditorBase : Editor\n    {\n        protected virtual void OnEditStart() {}\n        protected virtual void OnEditEnd() {}\n\n        public bool editingCollider\n        {\n            get { return EditMode.editMode == EditMode.SceneViewEditMode.Collider && EditMode.IsOwner(this); }\n        }\n\n        public virtual void OnEnable()\n        {\n            EditMode.editModeStarted += OnEditModeStart;\n            EditMode.editModeEnded += OnEditModeEnd;\n        }\n\n        public virtual void OnDisable()\n        {\n            EditMode.editModeStarted -= OnEditModeStart;\n            EditMode.editModeEnded -= OnEditModeEnd;\n        }\n\n        protected virtual GUIContent editModeButton { get { return EditorGUIUtility.IconContent(\"EditCollider\"); } }\n\n        protected void InspectorEditButtonGUI()\n        {\n            EditMode.DoEditModeInspectorModeButton(\n                EditMode.SceneViewEditMode.Collider,\n                \"Edit Collider\",\n                editModeButton,\n                this\n            );\n        }\n\n        internal override Bounds GetWorldBoundsOfTarget(Object targetObject)\n        {\n            if (targetObject is Collider2D)\n                return ((Collider2D)targetObject).bounds;\n            else if (targetObject is Collider)\n                return ((Collider)targetObject).bounds;\n            else\n                return base.GetWorldBoundsOfTarget(targetObject);\n        }\n\n        protected void OnEditModeStart(IToolModeOwner owner, EditMode.SceneViewEditMode mode)\n        {\n            if (mode == EditMode.SceneViewEditMode.Collider && owner == (IToolModeOwner)this)\n                OnEditStart();\n        }\n\n        protected void OnEditModeEnd(IToolModeOwner owner)\n        {\n            if (owner == (IToolModeOwner)this)\n                OnEditEnd();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ColorPresetLibraryInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(ColorPresetLibrary))]\n    internal class ColorPresetLibraryEditor : Editor\n    {\n        private GenericPresetLibraryInspector<ColorPresetLibrary> m_GenericPresetLibraryInspector;\n\n        public void OnEnable()\n        {\n            m_GenericPresetLibraryInspector = new GenericPresetLibraryInspector<ColorPresetLibrary>(target, \"Color Preset Library\", OnEditButtonClicked);\n            m_GenericPresetLibraryInspector.useOnePixelOverlappedGrid = true;\n            m_GenericPresetLibraryInspector.maxShowNumPresets = 2000; // does not use a preview cache so show many\n        }\n\n        public void OnDestroy()\n        {\n            if (m_GenericPresetLibraryInspector != null)\n                m_GenericPresetLibraryInspector.OnDestroy();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (m_GenericPresetLibraryInspector == null)\n                return;\n            m_GenericPresetLibraryInspector.itemViewMode = PresetLibraryEditorState.GetItemViewMode(ColorPicker.presetsEditorPrefID); // ensure in-sync\n            m_GenericPresetLibraryInspector.OnInspectorGUI();\n        }\n\n        private void OnEditButtonClicked(string libraryPath)\n        {\n            ColorPicker.Show(GUIView.current, Color.white);\n            ColorPicker.instance.currentPresetLibrary = libraryPath;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Inspector/ComputeShaderImporterInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditor.AssetImporters;\nusing System.Linq;\nusing UnityEditor.VersionControl;\nusing UnityEngine.Rendering;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(ComputeShaderImporter))]\n    internal class ComputeShaderImporterInspector : AssetImporterEditor\n    {\n        internal class Styles\n        {\n            public static GUIContent overridePreprocessor = EditorGUIUtility.TrTextContent(\"Override preprocessor\", \"Select preprocessor to use for this shader.\");\n        }\n\n        internal override void OnHeaderControlsGUI()\n        {\n            GUILayout.FlexibleSpace();\n            ShowOpenButton(new[] { assetTarget });\n        }\n\n        public override void OnEnable()\n        {\n            base.OnEnable();\n        }\n\n        protected override void Apply()\n        {\n            base.Apply();\n\n            var importer = target as ComputeShaderImporter;\n            if (importer == null)\n                return;\n\n            AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(importer));\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            ApplyRevertGUI();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ComputeShaderInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing System.Collections.Generic;\nusing System.Globalization;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(ComputeShader))]\n    internal class ComputeShaderInspector : Editor\n    {\n        private const float kSpace = 5f;\n        Vector2 m_ScrollPosition = Vector2.zero;\n\n        private static bool s_PreprocessOnly = false;\n        private static bool s_StripLineDirectives = true;\n\n        // Compute kernel information is stored split by platform, then by kernels;\n        // but for the inspector we want to show kernels, then platforms they are in.\n        class KernelInfo\n        {\n            internal string name;\n            internal List<string> platforms;\n        }\n\n        internal class Styles\n        {\n            public static GUIContent togglePreprocess = EditorGUIUtility.TrTextContent(\"Preprocess only\", \"Show preprocessor output instead of compiled shader code\");\n            public static GUIContent toggleStripLineDirective = EditorGUIUtility.TrTextContent(\"Strip #line directives\", \"Strip #line directives from preprocessor output\");\n            public static GUIContent showCompiled = EditorGUIUtility.TrTextContent(\"Show compiled code\");\n            public static GUIContent kernelsHeading = EditorGUIUtility.TrTextContent(\"Kernels:\");\n        }\n\n        static List<KernelInfo> GetKernelDisplayInfo(ComputeShader cs)\n        {\n            var kernelInfo = new List<KernelInfo>();\n            var platformCount = ShaderUtil.GetComputeShaderPlatformCount(cs);\n            for (var i = 0; i < platformCount; ++i)\n            {\n                var platform = ShaderUtil.GetComputeShaderPlatformType(cs, i);\n                var kernelCount = ShaderUtil.GetComputeShaderPlatformKernelCount(cs, i);\n                for (var j = 0; j < kernelCount; ++j)\n                {\n                    var kernelName = ShaderUtil.GetComputeShaderPlatformKernelName(cs, i, j);\n                    var found = false;\n                    foreach (var ki in kernelInfo)\n                    {\n                        if (ki.name == kernelName)\n                        {\n                            ki.platforms.Add(platform.ToString());\n                            found = true;\n                        }\n                    }\n                    if (!found)\n                    {\n                        var ki = new KernelInfo();\n                        ki.name = kernelName;\n                        ki.platforms = new List<string>();\n                        ki.platforms.Add(platform.ToString());\n                        kernelInfo.Add(ki);\n                    }\n                }\n            }\n            return kernelInfo;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            var cs = target as ComputeShader;\n            if (cs == null)\n                return;\n\n            GUI.enabled = true;\n\n            EditorGUI.indentLevel = 0;\n\n            ShowKernelInfoSection(cs);\n            ShowCompiledCodeSection(cs);\n            ShowShaderErrors(cs);\n        }\n\n        private void ShowKernelInfoSection(ComputeShader cs)\n        {\n            GUILayout.Label(Styles.kernelsHeading, EditorStyles.boldLabel);\n            var kernelInfo = GetKernelDisplayInfo(cs);\n            foreach (var ki in kernelInfo)\n            {\n                ki.platforms.Sort();\n                var sorted = System.String.Join(\" \", ki.platforms.ToArray());\n                EditorGUILayout.LabelField(ki.name, sorted);\n            }\n        }\n\n        private void ShowCompiledCodeSection(ComputeShader cs)\n        {\n            ComputeShaderImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(cs.GetInstanceID())) as ComputeShaderImporter;\n\n            s_PreprocessOnly = EditorGUILayout.Toggle(Styles.togglePreprocess, s_PreprocessOnly);\n            if (s_PreprocessOnly)\n                s_StripLineDirectives = EditorGUILayout.Toggle(Styles.toggleStripLineDirective, s_StripLineDirectives);\n\n            GUILayout.Space(kSpace);\n            if (GUILayout.Button(Styles.showCompiled, EditorStyles.miniButton, GUILayout.ExpandWidth(false)))\n            {\n                ShaderUtil.OpenCompiledComputeShader(cs, true, s_PreprocessOnly, s_StripLineDirectives);\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        ShaderMessage[] m_ShaderMessages;\n        private void ShowShaderErrors(ComputeShader s)\n        {\n            if (Event.current.type == EventType.Layout)\n            {\n                int n = ShaderUtil.GetComputeShaderMessageCount(s);\n                m_ShaderMessages = null;\n                if (n >= 1)\n                {\n                    m_ShaderMessages = ShaderUtil.GetComputeShaderMessages(s);\n                }\n            }\n\n            if (m_ShaderMessages == null)\n                return;\n            ShaderInspector.ShaderErrorListUI(s, m_ShaderMessages, ref m_ScrollPosition);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ConstrainProportionsTransformScale.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing JetBrains.Annotations;\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class ConstrainProportionsTransformScale\n    {\n        bool m_ConstrainProportionsScale;\n        internal static bool m_IsAnimationPreview;\n        Vector3 m_InitialScale;\n\n        static bool s_IsPropertyPaste;\n\n        internal bool constrainProportionsScale { get => m_ConstrainProportionsScale; set => m_ConstrainProportionsScale = value; }\n\n        internal ConstrainProportionsTransformScale(Vector3 previousScale)\n        {\n            m_InitialScale = previousScale != Vector3.zero ? previousScale : Vector3.one;\n            s_IsPropertyPaste = false;\n        }\n\n        internal Vector3 DoGUI(Rect rect, GUIContent scaleContent, Vector3 value,  UnityEngine.Object[] targetObjects, ref int axisModified, SerializedProperty property = null, SerializedProperty constrainProportionsProperty = null)\n        {\n            bool previousIsProportionalScale = m_ConstrainProportionsScale;\n            uint mixedValues = property != null ? GetMixedValueFields(property) : 0;\n            Vector3 scale = EditorGUI.LinkedVector3Field(rect,\n                scaleContent, EditorGUIUtility.TrTextContent(\"\", (constrainProportionsScale ? \"Disable\" : \"Enable\") + \" constrained proportions\"), value,\n                ref m_ConstrainProportionsScale, m_InitialScale, mixedValues, ref axisModified, property, constrainProportionsProperty);\n\n            if (previousIsProportionalScale != m_ConstrainProportionsScale)\n            {\n                // Every time scale becomes proportional, update initial scale value\n                if (m_ConstrainProportionsScale && !m_IsAnimationPreview)\n                {\n                    m_InitialScale = value != Vector3.zero ? value : Vector3.one;\n                }\n\n                SetConstrainProportions(targetObjects, m_ConstrainProportionsScale);\n            }\n\n            return scale;\n        }\n\n        [Shortcut(\"Transform/Toggle Constrain Proportions for Scale\")]\n        static void ToggleConstrainProportionsScale()\n        {\n            GameObject[] selected = Selection.gameObjects;\n\n            if (selected == null || selected.Length == 0)\n                return;\n\n            bool isProportionalScale = !Selection.DoAllGOsHaveConstrainProportionsEnabled(selected);\n\n            SetConstrainProportions(selected, isProportionalScale);\n\n            // To make sure all inspector windows have a proper greyout if initial values are zero, rebuild.\n            EditorUtility.ForceRebuildInspectors();\n        }\n\n        internal static void SetConstrainProportions([NotNull] Object[] objects, bool value)\n        {\n            foreach (var obj in objects)\n            {\n                Transform t = obj?.GetType() == typeof(GameObject)? (obj as GameObject)?.transform : obj as Transform;\n\n                if (t == null)\n                    continue;\n\n                Undo.RecordObject(t, \"Proportional Scale Toggle Changed\");\n                t.constrainProportionsScale = value;\n            }\n        }\n\n        internal static Vector3 GetVector3WithRatio(Vector3 vector, float ratio)\n        {\n            //If there are any fields with the same values, use already precalculated values\n            float xValue = vector.x * ratio;\n            float yValue = vector.y * ratio;\n\n            return new Vector3(\n                xValue,\n                Mathf.Approximately(vector.y, vector.x) ? xValue : yValue,\n                Mathf.Approximately(vector.z, vector.x) ? xValue : Mathf.Approximately(vector.z, vector.y) ? yValue : vector.z * ratio\n            );\n        }\n\n        internal static Vector3 DoScaleProportions(Vector3 value, Vector3 previousValue, Vector3 initialScale, ref int axisModified)\n        {\n            float ratio = 1;\n            bool ratioChanged = false;\n\n            if (!Selection.DoAllGOsHaveConstrainProportionsEnabled(Selection.gameObjects))\n                return value;\n\n            if (previousValue != value)\n            {\n                if (m_IsAnimationPreview && initialScale == Vector3.zero)\n                    initialScale = Vector3.one;\n\n                // Check which axis was modified and set locked fields and ratio\n                //AxisModified values [-1;2] : [none, x, y, z]\n                // X axis\n                ratio = SetRatio(value.x, previousValue.x, initialScale.x);\n                axisModified = ratio != 1 || !Mathf.Approximately(value.x, previousValue.x) ? 0 : -1;\n                // Y axis\n                if (axisModified == -1)\n                {\n                    ratio = SetRatio(value.y, previousValue.y, initialScale.y);\n                    axisModified = ratio != 1 || !Mathf.Approximately(value.y, previousValue.y) ? 1 : -1;\n                }\n                // Z axis\n                if (axisModified == -1)\n                {\n                    ratio = SetRatio(value.z, previousValue.z, initialScale.z);\n                    axisModified = ratio != 1 || !Mathf.Approximately(value.z, previousValue.z) ? 2 : -1;\n                }\n\n                ratioChanged = true;\n            }\n            // If customer has pasted a scale property via a context menu, we might need to enforce proportions\n            else if (s_IsPropertyPaste)\n            {\n                s_IsPropertyPaste = false;\n                // Catch if any value has changed by checking scale based on X axis\n                if (initialScale * (previousValue.x / initialScale.x) != value)\n                {\n                    Vector3 axisRatios = new Vector3(previousValue.x / initialScale.x, previousValue.y / initialScale.y,\n                        previousValue.z / initialScale.z);\n\n                    if (axisRatios.x != axisRatios.y && axisRatios.x != axisRatios.z && IsValidRatio(axisRatios.x))\n                    {\n                        axisModified = 0;\n                        ratio = axisRatios.x;\n                    }\n                    else if (axisRatios.y != axisRatios.x && axisRatios.y != axisRatios.z && IsValidRatio(axisRatios.y))\n                    {\n                        axisModified = 1;\n                        ratio = axisRatios.y;\n                    }\n                    else if (axisRatios.z != axisRatios.x && axisRatios.z != axisRatios.y && IsValidRatio(axisRatios.z))\n                    {\n                        axisModified = 2;\n                        ratio = axisRatios.z;\n                    }\n\n                    ratioChanged = axisModified != -1;\n                }\n            }\n\n            return ratioChanged ? GetVector3WithRatio(initialScale, ratio) : value;\n        }\n\n        static float SetRatio(float value, float previousValue, float initialValue)\n        {\n            return Mathf.Approximately(value, previousValue) ? 1 : Mathf.Approximately(initialValue, 0) ? 0 : value / initialValue;\n        }\n\n        internal static bool HandleMultiSelectionScaleChanges(Vector3 mScale, Vector3 currentScale, bool constrainProportionsScale, Object[] targetObjects, ref int axisModified)\n        {\n            bool xModified, yModified, zModified;\n            Vector3 goScale;\n\n            if (constrainProportionsScale)\n            {\n                xModified = axisModified == 0;\n                yModified = axisModified == 1;\n                zModified = axisModified == 2;\n\n                foreach (var obj in targetObjects)\n                {\n                    var tr = obj as Transform;\n                    if (tr == null)\n                        continue;\n\n                    Undo.RecordObject(tr, \"Scale changed\");\n                    goScale = tr.localScale;\n\n                    var ratio = xModified ? currentScale.x / goScale.x : yModified ? currentScale.y / goScale.y :  zModified ? currentScale.z / goScale.z : 1;\n                    if (Mathf.Approximately(ratio, 0))\n                        ratio = 1;\n\n                    tr.localScale = GetVector3WithRatio(goScale, ratio);\n                }\n\n                axisModified = -1;\n                return true;\n            }\n            else\n            {\n                xModified = !Mathf.Approximately(currentScale.x, mScale.x);\n                yModified = !Mathf.Approximately(currentScale.y, mScale.y);\n                zModified = !Mathf.Approximately(currentScale.z, mScale.z);\n\n                if (xModified || yModified || zModified)\n                {\n                    foreach (var obj in targetObjects)\n                    {\n                        var tr = obj as Transform;\n                        if (tr == null)\n                            continue;\n\n                        Undo.RecordObject(tr, \"Scale changed\");\n                        goScale = tr.localScale;\n                        tr.localScale = new Vector3(\n                            xModified ? currentScale.x : goScale.x,\n                            yModified ? currentScale.y : goScale.y,\n                            zModified ? currentScale.z : goScale.z);\n                    }\n\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        internal static uint GetMixedValueFields(SerializedProperty property)\n        {\n            uint mask = 0;\n            mask = SetBit(mask, 0, property.FindPropertyRelative(\"x\").hasMultipleDifferentValues);\n            mask = SetBit(mask, 1, property.FindPropertyRelative(\"y\").hasMultipleDifferentValues);\n            mask = SetBit(mask, 2, property.FindPropertyRelative(\"z\").hasMultipleDifferentValues);\n\n            return mask;\n        }\n\n        internal static uint GetMultiSelectionLockedFields(UnityEngine.Object[] objects)\n        {\n            uint mask = 0;\n\n            // Verify multiselection\n            if (objects != null)\n            {\n                foreach (var obj in objects)\n                {\n                    var tr = obj as Transform;\n                    if (tr == null)\n                        continue;\n\n                    var localScale = tr.localScale;\n                    if (!IsBit(mask, 0) && localScale.x == 0)\n                        mask = SetBit(mask, 0, true);\n\n                    if (!IsBit(mask, 1) && localScale.y == 0)\n                        mask = SetBit(mask, 1, true);\n\n                    if (!IsBit(mask, 2) && localScale.z == 0)\n                        mask = SetBit(mask, 2, true);\n\n                    // If all axis are set(111), return immediately\n                    if (mask == 7)\n                    {\n                        return mask;\n                    }\n                }\n            }\n\n\n            return mask;\n        }\n\n        internal bool Initialize(UnityEngine.Object[] targetObjects)\n        {\n            bool isGameObjectSelected = targetObjects.Length > 0;\n            constrainProportionsScale = isGameObjectSelected && Selection.DoAllGOsHaveConstrainProportionsEnabled(targetObjects);\n            return isGameObjectSelected;\n        }\n\n        internal static bool IsBit(uint mask, int index)\n        {\n            return (mask & (1u << index)) != 0;\n        }\n\n        internal static uint SetBit(uint mask, int index, bool value)\n        {\n            uint bitmask = 1u << index;\n            if (value)\n                return mask | bitmask;\n            else\n                return mask & (~bitmask);\n        }\n\n        static bool IsValidRatio(float value)\n        {\n            return !float.IsNaN(value) && !float.IsInfinity(value);\n        }\n\n        internal static void NotifyPropertyPasted(string propertyPath)\n        {\n            // If user has pasted a scale property via a context menu, we might need to enforce proportions.\n            s_IsPropertyPaste = propertyPath.StartsWith(\"m_LocalScale\");\n        }\n\n        internal static bool ShouldForceEnablePropertyFields(float[] values)\n        {\n            if (!m_IsAnimationPreview)\n                return false;\n\n                foreach (var value in values)\n                {\n                    if (value != 0)\n                        return false;\n                }\n\n                return true;\n        }\n\n        internal static bool CanUseMathExpressions(SerializedProperty property)\n        {\n            // Constrain proportions multi-selection change relies on activeObject and precise numbers,\n            // so we cannot use math expressions that provides different results on different objects UUM-21958\n            var targetObjects = property.serializedObject.targetObjects;\n\n            return !(targetObjects.Length > 1 && property.propertyPath.StartsWith(\"m_LocalScale\") &&\n                     Selection.DoAllGOsHaveConstrainProportionsEnabled(targetObjects));\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ConstraintEditorBase.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Animations;\nusing Object = UnityEngine.Object;\nusing UnityEditorInternal;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal abstract class ConstraintStyleBase\n    {\n        GUIContent m_Activate = EditorGUIUtility.TrTextContent(\"Activate\", \"Activate the constraint at the current offset from the sources.\");\n        GUIContent m_Zero = EditorGUIUtility.TrTextContent(\"Zero\", \"Activate the constraint at zero offset from the sources.\");\n\n        GUIContent m_Sources = EditorGUIUtility.TrTextContent(\"Sources\");\n\n        GUIContent m_Weight = EditorGUIUtility.TrTextContent(\"Weight\");\n\n        GUIContent m_IsActive = EditorGUIUtility.TrTextContent(\"Is Active\", \"When set, the constraint is being evaluated.\");\n        GUIContent m_IsLocked = EditorGUIUtility.TrTextContent(\"Lock\", \"When set, evaluate with the current offset. When not set, update the offset based on the current transform.\");\n\n        GUIContent[] m_Axes =\n        {\n            EditorGUIUtility.TextContent(\"X\"),\n            EditorGUIUtility.TextContent(\"Y\"),\n            EditorGUIUtility.TextContent(\"Z\")\n        };\n\n        GUIContent m_ConstraintSettings = EditorGUIUtility.TrTextContent(\"Constraint Settings\");\n\n        public virtual GUIContent Activate { get { return m_Activate; } }\n        public virtual GUIContent Zero { get { return m_Zero; } }\n\n        public abstract GUIContent AtRest { get; }\n        public abstract GUIContent Offset { get; }\n\n        public virtual GUIContent Sources { get { return m_Sources; } }\n\n        public virtual GUIContent Weight { get { return m_Weight; } }\n\n        public virtual GUIContent IsActive { get { return m_IsActive; } }\n        public virtual GUIContent IsLocked { get { return m_IsLocked; } }\n\n        public virtual GUIContent[] Axes { get { return m_Axes; } }\n\n        public virtual GUIContent ConstraintSettings { get { return m_ConstraintSettings; } }\n    }\n\n    internal abstract class ConstraintEditorBase : Editor\n    {\n        private bool m_ShowConstraintSettings = false;\n\n        internal abstract SerializedProperty atRest { get; }\n        internal abstract SerializedProperty offset { get; }\n        internal abstract SerializedProperty weight { get; }\n        internal abstract SerializedProperty isContraintActive { get; }\n        internal abstract SerializedProperty isLocked { get; }\n        internal abstract SerializedProperty sources { get; }\n\n        private ReorderableList m_SourceList;\n\n        private int m_SelectedSourceIdx = -1;\n        protected int selectedSourceIndex { get { return m_SelectedSourceIdx; } set { m_SelectedSourceIdx = value; } }\n\n        protected const int kSourceWeightWidth = 60;\n\n        public void OnEnable(ConstraintStyleBase style)\n        {\n            Undo.undoRedoEvent += OnUndoRedoPerformed;\n\n            m_SourceList = new ReorderableList(serializedObject, sources, sources.editable, true, sources.editable, sources.editable);\n            m_SourceList.drawElementCallback += DrawElementCallback;\n            m_SourceList.onAddCallback += OnAddCallback;\n            m_SourceList.drawHeaderCallback += rect => EditorGUI.LabelField(rect, style.Sources);\n            m_SourceList.onRemoveCallback += OnRemoveCallback;\n            m_SourceList.onSelectCallback += OnSelectedCallback;\n            m_SourceList.onReorderCallbackWithDetails += OnReorderCallback;\n\n            if (sources.arraySize > 0 && m_SelectedSourceIdx == -1)\n            {\n                SelectSource(0);\n            }\n        }\n\n        public void OnDisable()\n        {\n            Undo.undoRedoEvent -= OnUndoRedoPerformed;\n        }\n\n        internal void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            // must call UserUpdateOffset to allow the offsets to be updated by the Undo system, otherwise the constraint can override them\n            foreach (var t in targets)\n                (t as IConstraintInternal).UserUpdateOffset();\n        }\n\n        protected void SelectSource(int index)\n        {\n            m_SelectedSourceIdx = index;\n\n            if (m_SourceList.index != index)\n            {\n                m_SourceList.index = index;\n            }\n        }\n\n        protected virtual void OnSelectedCallback(ReorderableList list)\n        {\n            SelectSource(list.index);\n        }\n\n        protected virtual void OnReorderCallback(ReorderableList list, int oldActiveElement, int newActiveElement) {}\n\n        protected virtual void OnRemoveCallback(ReorderableList list)\n        {\n            ReorderableList.defaultBehaviours.DoRemoveButton(list);\n            if (m_SelectedSourceIdx >= list.serializedProperty.arraySize)\n            {\n                SelectSource(list.serializedProperty.arraySize - 1);\n            }\n        }\n\n        protected virtual void OnAddCallback(ReorderableList list)\n        {\n            var index = list.serializedProperty.arraySize;\n            ReorderableList.defaultBehaviours.DoAddButton(list);\n\n            var source = list.serializedProperty.GetArrayElementAtIndex(index);\n            source.FindPropertyRelative(\"sourceTransform\").objectReferenceValue = null;\n            source.FindPropertyRelative(\"weight\").floatValue = 1.0f;\n\n            SelectSource(index);\n        }\n\n        private void DrawElementCallback(Rect rect, int index, bool isActive, bool isFocused)\n        {\n            rect.height = EditorGUIUtility.singleLineHeight;\n            rect.y += 1;\n\n            var element = sources.GetArrayElementAtIndex(index);\n            var source = element.FindPropertyRelative(\"sourceTransform\");\n            var weight = element.FindPropertyRelative(\"weight\");\n\n            EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width - kSourceWeightWidth, EditorGUIUtility.singleLineHeight), source, GUIContent.none);\n            EditorGUI.PropertyField(new Rect(rect.x + rect.width - kSourceWeightWidth, rect.y, kSourceWeightWidth, EditorGUIUtility.singleLineHeight), weight, GUIContent.none);\n        }\n\n        internal abstract void OnValueAtRestChanged();\n        internal abstract void ShowFreezeAxesControl();\n\n        /// Show the custom constraint properties that are not included in the foldout\n        internal virtual void ShowCustomProperties() {}\n\n        internal void ShowConstraintEditor<T>(ConstraintStyleBase style) where T : class, IConstraintInternal\n        {\n            if (m_SelectedSourceIdx == -1 || m_SelectedSourceIdx >= m_SourceList.serializedProperty.arraySize)\n            {\n                SelectSource(0);\n            }\n\n            using (new EditorGUI.DisabledScope(Application.isPlaying))\n            {\n                using (new EditorGUILayout.HorizontalScope())\n                {\n                    if (GUILayout.Button(style.Activate))\n                    {\n                        List<Object> recordObjects = new List<Object>();\n                        recordObjects.AddRange(targets);\n                        foreach (var t in targets)\n                            recordObjects.Add((t as T).transform);\n                        Undo.RegisterCompleteObjectUndo(recordObjects.ToArray(), \"Activate the Constraint\");\n\n                        foreach (var t in targets)\n                            (t as T).ActivateAndPreserveOffset();\n                    }\n\n                    if (GUILayout.Button(style.Zero))\n                    {\n                        List<Object> recordObjects = new List<Object>();\n                        recordObjects.AddRange(targets);\n                        foreach (var t in targets)\n                            recordObjects.Add((t as T).transform);\n                        Undo.RegisterCompleteObjectUndo(recordObjects.ToArray(), \"Zero the Constraint\");\n\n                        foreach (var t in targets)\n                            (t as T).ActivateWithZeroOffset();\n                    }\n                }\n            }\n\n            EditorGUILayout.PropertyField(isContraintActive, style.IsActive);\n            EditorGUILayout.Slider(weight, 0.0f, 1.0f, style.Weight);\n            ShowCustomProperties();\n\n            m_ShowConstraintSettings = EditorGUILayout.Foldout(m_ShowConstraintSettings, style.ConstraintSettings, true);\n            if (m_ShowConstraintSettings)\n            {\n                EditorGUI.indentLevel++;\n                using (new EditorGUI.DisabledScope(Application.isPlaying))\n                {\n                    EditorGUILayout.PropertyField(isLocked, style.IsLocked);\n                }\n                using (new EditorGUI.DisabledGroupScope(isLocked.boolValue))\n                {\n                    ShowValueAtRest(style);\n\n                    ShowOffset<T>(style);\n                }\n                ShowFreezeAxesControl();\n                EditorGUI.indentLevel--;\n            }\n            m_SourceList.DoLayoutList();\n        }\n\n        internal virtual void ShowValueAtRest(ConstraintStyleBase style)\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(atRest, style.AtRest);\n            if (EditorGUI.EndChangeCheck())\n            {\n                OnValueAtRestChanged();\n            }\n        }\n\n        internal virtual void ShowOffset<T>(ConstraintStyleBase style) where T : class, IConstraintInternal\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(offset, style.Offset);\n            if (EditorGUI.EndChangeCheck())\n            {\n                foreach (var t in targets)\n                    (t as T).UserUpdateOffset();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AddComponent/AddComponentDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.CodeDom;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\n\nnamespace UnityEditor.AddComponent\n{\n    internal class AddComponentDataSource : AdvancedDropdownDataSource\n    {\n        private static readonly string kSearchHeader = L10n.Tr(\"Search\");\n        AdvancedDropdownState m_State;\n        UnityEngine.GameObject[] m_Targets;\n\n        internal static readonly string kScriptHeader = \"Component/Scripts/\";\n\n        public AddComponentDataSource(AdvancedDropdownState state, UnityEngine.GameObject[] targets)\n        {\n            m_State = state;\n            m_Targets = targets;\n        }\n\n        protected override AdvancedDropdownItem FetchData()\n        {\n            return RebuildTree();\n        }\n\n        struct MenuItemData\n        {\n            public string path;\n            public string command;\n            public bool isLegacy;\n        }\n\n        protected AdvancedDropdownItem RebuildTree()\n        {\n            m_SearchableElements = new List<AdvancedDropdownItem>();\n            AdvancedDropdownItem root = new ComponentDropdownItem(\"ROOT\");\n            List<MenuItemData> menuItems = GetSortedMenuItems(m_Targets);\n\n            Dictionary<string, int> pathHashCodeMap = new Dictionary<string, int>();\n\n            for (var i = 0; i < menuItems.Count; i++)\n            {\n                var menu = menuItems[i];\n                if (menu.command == \"ADD\")\n                {\n                    continue;\n                }\n\n                var paths = menu.path.Split('/');\n\n                var parent = root;\n                for (var j = 0; j < paths.Length; j++)\n                {\n                    var path = paths[j];\n\n                    if (j == paths.Length - 1)\n                    {\n                        var element = new ComponentDropdownItem(path, L10n.Tr(path), menu.path, menu.command, menu.isLegacy);\n                        parent.AddChild(element);\n                        m_SearchableElements.Add(element);\n                        continue;\n                    }\n\n                    if (!pathHashCodeMap.TryGetValue(path, out int pathHashCode))\n                    {\n                        pathHashCode = path.GetHashCode();\n                        pathHashCodeMap[path] = pathHashCode;\n                    }\n\n                    var group = (ComponentDropdownItem)parent.children.SingleOrDefault(c => c.id == pathHashCode);\n                    if (group == null)\n                    {\n                        group = new ComponentDropdownItem(path, L10n.Tr(path));\n                        parent.AddChild(group);\n                    }\n                    parent = group;\n                }\n            }\n            root = root.children.Single();\n            var newScript = new ComponentDropdownItem(\"New script\", L10n.Tr(\"New script\"));\n            newScript.AddChild(new NewScriptDropdownItem());\n            root.AddChild(newScript);\n            return root;\n        }\n\n        static List<MenuItemData> GetSortedMenuItems(UnityEngine.GameObject[] targets)\n        {\n            var menus = Unsupported.GetSubmenus(\"Component\");\n            var commands = Unsupported.GetSubmenusCommands(\"Component\");\n\n            var menuItems = new List<MenuItemData>(menus.Length);\n            var legacyMenuItems = new List<MenuItemData>(menus.Length);\n            const string kLegacyString = \"legacy\";\n\n            var hasFilterOverride = ModeService.HasExecuteHandler(\"inspector_filter_component\");\n\n            for (var i = 0; i < menus.Length; i++)\n            {\n                var menuPath = menus[i];\n                bool isLegacy = menuPath.ToLower().Contains(kLegacyString);\n                var item = new MenuItemData\n                {\n                    path = menuPath,\n                    command = commands[i],\n                    isLegacy = isLegacy\n                };\n\n                if (!hasFilterOverride || ModeService.Execute(\"inspector_filter_component\", targets, menuPath))\n                {\n                    if (isLegacy)\n                    {\n                        legacyMenuItems.Add(item);\n                    }\n                    else\n                    {\n                        menuItems.Add(item);\n                    }\n                }\n            }\n\n            int comparison(MenuItemData x, MenuItemData y) => string.CompareOrdinal(x.path, y.path);\n\n            menuItems.Sort(comparison);\n            legacyMenuItems.Sort(comparison);\n\n            menuItems.AddRange(legacyMenuItems);\n\n            return menuItems;\n        }\n\n        protected override AdvancedDropdownItem Search(string searchString)\n        {\n            if (string.IsNullOrEmpty(searchString) || m_SearchableElements == null)\n                return null;\n\n            // Support multiple search words separated by spaces.\n            var searchWords = searchString.ToLower().Split(' ');\n\n            // We keep two lists. Matches that matches the start of an item always get first priority.\n            var matchesStart = new List<AdvancedDropdownItem>();\n            var matchesWithin = new List<AdvancedDropdownItem>();\n\n            bool found = false;\n            foreach (var e in m_SearchableElements)\n            {\n                var addComponentItem = (ComponentDropdownItem)e;\n                string name;\n                if (addComponentItem.menuPath.StartsWith(kScriptHeader))\n                    name = addComponentItem.menuPath.Remove(0, kScriptHeader.Length).ToLower().Replace(\" \", \"\");\n                else\n                    name = addComponentItem.searchableName.ToLower().Replace(\" \", \"\");\n\n                if (AddMatchItem(e, name, searchWords, matchesStart, matchesWithin))\n                    found = true;\n            }\n            if (!found)\n            {\n                foreach (var e in m_SearchableElements)\n                {\n                    var addComponentItem = (ComponentDropdownItem)e;\n                    var name = addComponentItem.searchableNameLocalized.Replace(\" \", \"\");\n                    AddMatchItem(e, name, searchWords, matchesStart, matchesWithin);\n                }\n            }\n\n            var searchTree = new AdvancedDropdownItem(kSearchHeader);\n            matchesStart.Sort();\n            foreach (var element in matchesStart)\n            {\n                searchTree.AddChild(element);\n            }\n            matchesWithin.Sort();\n            foreach (var element in matchesWithin)\n            {\n                searchTree.AddChild(element);\n            }\n            if (searchTree != null)\n            {\n                var addNewScriptGroup = new ComponentDropdownItem(\"New script\", L10n.Tr(\"New script\"));\n                m_State.SetSelectedIndex(addNewScriptGroup, 0);\n                var addNewScript = new NewScriptDropdownItem();\n                addNewScript.className = searchString;\n                addNewScriptGroup.AddChild(addNewScript);\n                searchTree.AddChild(addNewScriptGroup);\n            }\n            return searchTree;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AddComponent/AddComponentGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\n\nnamespace UnityEditor.AddComponent\n{\n    internal class AddComponentGUI : AdvancedDropdownGUI\n    {\n        private static class Styles\n        {\n            public static GUIStyle itemStyle = \"DD LargeItemStyle\";\n\n            const string k_includeNamespaceProSkin = \"{0} <color=#808080>({1})</color>\";\n            const string k_includeNamespace = \"{0} <color=#404040>({1})</color>\";\n\n            public static string includeNamespaceString => EditorGUIUtility.isProSkin ? k_includeNamespaceProSkin : k_includeNamespace;\n        }\n\n        private Vector2 m_IconSize = new Vector2(16, 16);\n        private Action<NewScriptDropdownItem> m_OnCreateNewScript;\n\n        internal override Vector2 iconSize => m_IconSize;\n        internal override GUIStyle lineStyle => Styles.itemStyle;\n\n        public AddComponentGUI(AdvancedDropdownDataSource dataSource, Action<NewScriptDropdownItem> onCreateNewScript) : base(dataSource)\n        {\n            m_OnCreateNewScript = onCreateNewScript;\n        }\n\n        private void DrawSearchItem(string name, string path, Texture2D icon, bool selected)\n        {\n            if (!string.IsNullOrEmpty(path))\n                name = string.Format(Styles.includeNamespaceString, name, path);\n\n            var contentWithIcon = new GUIContent(name, path);\n            contentWithIcon.image = icon;\n\n            var rect = GUILayoutUtility.GetRect(contentWithIcon, Styles.itemStyle, GUILayout.ExpandWidth(true));\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n            lineStyle.Draw(rect, contentWithIcon, selected, selected, selected, selected);\n        }\n\n        internal override void DrawItem(AdvancedDropdownItem item, string name, Texture2D icon, bool enabled, bool drawArrow, bool selected, bool hasSearch)\n        {\n            bool isScript = false;\n            var newScriptItem = item as NewScriptDropdownItem;\n            if (newScriptItem == null)\n            {\n                string namespaceName = \"\";\n                if (hasSearch && item is ComponentDropdownItem)\n                {\n                    var componentItem = item as ComponentDropdownItem;\n                    // null check doesn't work here so comparing against \"New script\"\n                    if (componentItem.menuPath != null && componentItem.displayName != null && !componentItem.displayName.Equals(\"New script\") && componentItem.menuPath.StartsWith(AddComponentDataSource.kScriptHeader))\n                    {\n                        namespaceName = componentItem.menuPath.Substring(AddComponentDataSource.kScriptHeader.Length);\n                        var last = namespaceName.LastIndexOf(\"/\");\n                        namespaceName = last != -1 ? namespaceName.Substring(0, last) : \"\";\n                        isScript = true;\n                    }\n                    else\n                        name = ((ComponentDropdownItem)item).searchableNameLocalized;\n                }\n\n                if (string.IsNullOrEmpty(namespaceName))\n                    base.DrawItem(item, name, icon, enabled, drawArrow, selected, hasSearch);\n                else\n                    DrawSearchItem(name, namespaceName, icon, selected);\n\n                // dummy label for easy tooltips\n                // this is to allow viewing full script names in cases where they are cut off\n                if (Event.current.type == EventType.Repaint && isScript)\n                {\n                    var text = string.IsNullOrEmpty(namespaceName) ? name : $\"{name} ({namespaceName})\";\n                    var tooltipRect = GUILayoutUtility.GetLastRect();\n                    GUI.Label(tooltipRect, new GUIContent(\"\", text));\n                }\n\n                return;\n            }\n\n            GUILayout.Label(L10n.Tr(\"Name\"), EditorStyles.label);\n\n            EditorGUI.FocusTextInControl(\"NewScriptName\");\n            GUI.SetNextControlName(\"NewScriptName\");\n\n            newScriptItem.m_ClassName = EditorGUILayout.TextField(newScriptItem.m_ClassName);\n\n            EditorGUILayout.Space();\n\n            var canCreate = newScriptItem.CanCreate();\n            if (!canCreate && newScriptItem.m_ClassName != \"\")\n                GUILayout.Label(newScriptItem.GetError(), EditorStyles.helpBox);\n\n            GUILayout.FlexibleSpace();\n\n            using (new EditorGUI.DisabledScope(!canCreate))\n            {\n                if (GUILayout.Button(L10n.Tr(\"Create and Add\")))\n                {\n                    m_OnCreateNewScript(newScriptItem);\n                }\n            }\n\n            EditorGUILayout.Space();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AddComponent/AddComponentWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.AddComponent\n{\n    [InitializeOnLoad]\n    internal class AddComponentWindow : AdvancedDropdownWindow\n    {\n        internal const string OpenAddComponentDropdown = \"OpenAddComponentDropdown\";\n        [Serializable]\n        internal class AnalyticsEventData\n        {\n            public string name;\n            public string filter;\n            public bool isNewScript;\n        }\n\n        private GameObject[] m_GameObjects;\n        private DateTime m_ComponentOpenTime;\n        private const string kComponentSearch = \"ComponentSearchString\";\n        private const int kMaxWindowHeight = 395 - 80;\n        private static AdvancedDropdownState s_State = new AdvancedDropdownState();\n\n        protected override bool setInitialSelectionPosition { get; } = false;\n\n        protected override bool isSearchFieldDisabled\n        {\n            get\n            {\n                var child = state.GetSelectedChild(renderedTreeItem);\n                if (child != null)\n                    return child is NewScriptDropdownItem;\n                return false;\n            }\n        }\n\n        internal static bool Show(Rect rect, GameObject[] gos)\n        {\n            CloseAllOpenWindows<AddComponentWindow>();\n            var window = CreateInstance<AddComponentWindow>();\n            window.dataSource = new AddComponentDataSource(s_State, gos);\n            window.gui = new AddComponentGUI(window.dataSource, window.OnCreateNewScript);\n            window.state = s_State;\n            window.m_GameObjects = gos;\n            window.m_ComponentOpenTime = DateTime.UtcNow;\n            window.Init(rect);\n            window.searchString = EditorPrefs.GetString(kComponentSearch, \"\");\n            return true;\n        }\n\n        protected override void OnEnable()\n        {\n            base.OnEnable();\n            showHeader = true;\n            selectionChanged += OnItemSelected;\n        }\n\n        private void OnItemSelected(AdvancedDropdownItem item)\n        {\n            if (item is ComponentDropdownItem cdi && !string.IsNullOrEmpty(cdi.menuPath))\n            {\n                SendUsabilityAnalyticsEvent(new AnalyticsEventData\n                {\n                    name = item.name,\n                    filter = searchString,\n                    isNewScript = false\n                });\n\n                var gos = m_GameObjects;\n                EditorApplication.ExecuteMenuItemOnGameObjects(cdi.menuPath, gos);\n            }\n        }\n\n        protected override void OnDisable()\n        {\n            EditorPrefs.SetString(kComponentSearch, searchString);\n        }\n\n        internal new void OnGUI()\n        {\n            if (m_GameObjects.Any(g => !g))\n            {\n                // Close the popup window if one of the object is now invalid (i.e. deleted from an undo operation)\n                Close();\n                GUIUtility.ExitGUI();\n                return;\n            }\n\n            base.OnGUI();\n        }\n\n        protected override Vector2 CalculateWindowSize(Rect buttonRect)\n        {\n            return new Vector2(buttonRect.width, kMaxWindowHeight);\n        }\n\n        protected override bool SpecialKeyboardHandling(Event evt)\n        {\n            var createScriptMenu = state.GetSelectedChild(renderedTreeItem);\n            if (createScriptMenu is NewScriptDropdownItem nsdi)\n            {\n                // When creating new script name we want to dedicate both left/right arrow and backspace\n                // to editing the script name so they can't be used for navigating the menus.\n                // The only way to get back using the keyboard is pressing Esc.\n                if (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter)\n                {\n                    OnCreateNewScript(nsdi);\n                    evt.Use();\n                    GUIUtility.ExitGUI();\n                }\n\n                if (evt.keyCode == KeyCode.Escape)\n                {\n                    GoToParent();\n                    evt.Use();\n                }\n\n                return true;\n            }\n            return false;\n        }\n\n        void OnCreateNewScript(NewScriptDropdownItem item)\n        {\n            item.Create(m_GameObjects, searchString);\n            SendUsabilityAnalyticsEvent(new AnalyticsEventData\n            {\n                name = item.className,\n                filter = searchString,\n                isNewScript = true\n            });\n            Close();\n        }\n\n        internal void SendUsabilityAnalyticsEvent(AnalyticsEventData eventData)\n        {\n            var openTime = m_ComponentOpenTime;\n            UsabilityAnalytics.SendEvent(\"executeAddComponentWindow\", openTime, DateTime.UtcNow - openTime, false, eventData);\n        }\n\n        [UsedByNativeCode]\n        internal static bool ValidateAddComponentMenuItem()\n        {\n            if (FirstInspectorWithGameObject() != null)\n                return true;\n            return false;\n        }\n\n        [UsedByNativeCode]\n        internal static void ExecuteAddComponentMenuItem()\n        {\n            var insp = FirstInspectorWithGameObject();\n            if (insp != null)\n            {\n                insp.ShowTab();\n                insp.m_OpenAddComponentMenu = true;\n            }\n        }\n\n        private static InspectorWindow FirstInspectorWithGameObject()\n        {\n            foreach (var insp in InspectorWindow.GetInspectors())\n                if (insp.GetInspectedObject() is GameObject)\n                    return insp;\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AddComponent/ComponentDropdownItem.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\n\nnamespace UnityEditor.AddComponent\n{\n    internal class ComponentDropdownItem : AdvancedDropdownItem\n    {\n        private string m_MenuPath;\n        private bool m_IsLegacy;\n        private string m_LocalizedName;\n        private string m_SearchableNameLocalized;\n        private string m_SearchableName;\n\n        internal override string displayName\n        {\n            get { return m_LocalizedName; }\n        }\n        public string searchableName\n        {\n            get\n            {\n                if (m_SearchableName == null)\n                    return name;\n                return m_SearchableName;\n            }\n            set { m_SearchableName = value; }\n        }\n\n        public string searchableNameLocalized\n        {\n            get\n            {\n                if (m_SearchableNameLocalized == null)\n                    return m_SearchableName;\n                return m_SearchableNameLocalized;\n            }\n            set { m_SearchableNameLocalized = value; }\n        }\n\n        public string localizedName\n        {\n            get { return m_LocalizedName ?? name; }\n        }\n\n        public string menuPath => m_MenuPath;\n\n        public ComponentDropdownItem(string name) : base(name)\n        {\n        }\n\n        public ComponentDropdownItem(string name, string localized) : base(name)\n        {\n            m_LocalizedName = localized;\n            m_SearchableName = name;\n            m_SearchableNameLocalized = localized;\n        }\n\n        public ComponentDropdownItem(string name, string localized, string menuPath, string command, bool isLegacy) : base(name)\n        {\n            m_LocalizedName = localized;\n            m_MenuPath = menuPath;\n            m_IsLegacy = isLegacy;\n\n            if (command.StartsWith(\"SCRIPT\"))\n            {\n                var scriptId = int.Parse(command.Substring(6));\n                var obj = EditorUtility.InstanceIDToObject(scriptId);\n                var icon = AssetPreview.GetMiniThumbnail(obj);\n                base.name = name;\n                base.icon = icon;\n            }\n            else\n            {\n                var classId = int.Parse(command);\n                base.name = name;\n                base.icon = AssetPreview.GetMiniTypeThumbnailFromClassID(classId);\n            }\n            m_SearchableName = name;\n            m_SearchableNameLocalized = localized;\n            if (m_IsLegacy)\n            {\n                m_SearchableName += \" (Legacy)\";\n            }\n        }\n\n        public override int CompareTo(object o)\n        {\n            if (o is ComponentDropdownItem)\n            {\n                // legacy elements should always come after non legacy elements\n                var componentElement = (ComponentDropdownItem)o;\n                if (m_IsLegacy && !componentElement.m_IsLegacy)\n                    return 1;\n                if (!m_IsLegacy && componentElement.m_IsLegacy)\n                    return -1;\n            }\n            return base.CompareTo(o);\n        }\n\n        public override string ToString()\n        {\n            return m_MenuPath;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AddComponent/NewScriptDropdownItem.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing Microsoft.CSharp;\n\nnamespace UnityEditor.AddComponent\n{\n    class NewScriptDropdownItem : ComponentDropdownItem\n    {\n        private const string NewScriptDirectoryPref = \"NewScriptDropdownItem.m_Directory\";\n\n        private readonly char[] kInvalidPathChars = new char[] {'<', '>', ':', '\"', '|', '?', '*', (char)0};\n        private readonly char[] kPathSepChars = new char[] {'/', '\\\\'};\n        private static System.CodeDom.Compiler.CodeDomProvider s_CSharpDOMProvider;\n\n        private string m_Directory = string.Empty;\n\n        internal string m_ClassName = \"NewBehaviourScript\";\n\n        public string className\n        {\n            set => m_ClassName = value;\n            get => m_ClassName;\n        }\n\n        public NewScriptDropdownItem() : base(\"New Script\", L10n.Tr(\"New Script\")) {}\n\n        internal bool CanCreate() =>\n            m_ClassName.Length > 0 &&\n            !ClassNameIsInvalidIdentifier() &&\n            !ClassNameIsInvalid() &&\n            !File.Exists(TargetPath()) &&\n            !ClassAlreadyExists() &&\n            !InvalidTargetPath();\n\n        public string GetError()\n        {\n            // Create string to tell the user what the problem is\n            var blockReason = string.Empty;\n            if (m_ClassName != string.Empty)\n            {\n                if (ClassNameIsInvalid() || m_ClassName.Contains('.'))\n                    blockReason = \"The script name may only consist of a-z, A-Z, 0-9, _ characters.\";\n                else if (ClassNameIsInvalidIdentifier())\n                    blockReason = $\"The script name is invalid in C#: {m_ClassName}.\";\n                else if (File.Exists(TargetPath()))\n                    blockReason = $\"A script called \\\"{m_ClassName}\\\" already exists at that path.\";\n                else if (ClassAlreadyExists())\n                    blockReason = $\"A class called \\\"{m_ClassName}\\\" already exists.\";\n                else if (InvalidTargetPath())\n                    blockReason = \"The folder path contains invalid characters.\";\n            }\n            return blockReason;\n        }\n\n        internal void Create(GameObject[] gameObjects, string searchString)\n        {\n            m_Directory = EditorPrefs.GetString(NewScriptDirectoryPref);\n\n            if (!CanCreate())\n                return;\n\n            if (!CreateScript())\n                return;\n\n            foreach (var go in gameObjects)\n            {\n                var script = AssetDatabase.LoadAssetAtPath(TargetPath(), typeof(MonoScript)) as MonoScript;\n                script.SetScriptTypeWasJustCreatedFromComponentMenu();\n                InternalEditorUtility.AddScriptComponentUncheckedUndoable(go, script);\n            }\n        }\n\n        private bool InvalidTargetPath()\n        {\n            if (m_Directory.IndexOfAny(kInvalidPathChars) >= 0)\n                return true;\n            if (TargetDir().Split(kPathSepChars, StringSplitOptions.None).Contains(string.Empty))\n                return true;\n            return false;\n        }\n\n        private string TargetPath() => Path.Combine(TargetDir(), m_ClassName + \".cs\");\n\n        private string TargetDir() => Path.Combine(\"Assets\", m_Directory.Trim(kPathSepChars));\n\n        private void SetDirectory(string newDir)\n        {\n            m_Directory = newDir;\n            EditorPrefs.SetString(NewScriptDirectoryPref, newDir);\n        }\n\n        private bool ClassNameIsInvalid() => !System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(m_ClassName);\n\n        private bool ClassNameIsInvalidIdentifier() => !IsValidIdentifier(m_ClassName);\n\n        internal static bool IsValidIdentifier(string className)\n        {\n            if (s_CSharpDOMProvider == null)\n                s_CSharpDOMProvider = new CSharpCodeProvider();\n\n            return s_CSharpDOMProvider.IsValidIdentifier(className);\n        }\n\n        private bool ClassExists(string className) => AppDomain.CurrentDomain.GetAssemblies().Any(a => a.GetType(className, false) != null);\n\n        private bool ClassAlreadyExists()\n        {\n            if (m_ClassName == string.Empty)\n                return false;\n            return ClassExists(m_ClassName);\n        }\n\n        private string GetTemplatePath()\n        {\n            var scriptTemplatePath = AssetsMenuUtility.GetScriptTemplatePath(ScriptTemplate.CSharp_NewBehaviourScript);\n            var scriptTemplateFilename = scriptTemplatePath.Substring(scriptTemplatePath.LastIndexOf('/'));\n\n            var localScriptTemplatePath = $\"Assets/ScriptTemplates/{scriptTemplateFilename}\";\n\n            if(File.Exists(localScriptTemplatePath))\n                return localScriptTemplatePath;\n\n            return scriptTemplatePath;\n        }\n        private bool CreateScript()\n        {\n            var userPath = EditorUtility.SaveFilePanel(\"Create MonoBehaviour Script\", TargetDir(), m_ClassName, \"cs\");\n            if (string.IsNullOrEmpty(userPath)) return false;\n\n            var indexToLocal = userPath.IndexOf(Application.dataPath);\n            if (indexToLocal == -1)\n            {\n                EditorUtility.DisplayDialog(\"Unable to Create MonoBehaviour Script\", \"You can't create a script outside of the project's Assets directory. Select a location in the Assets directory instead.\", \"Ok\");\n                return false;\n            }\n\n            var localPathAndFile = userPath.Remove(indexToLocal, Application.dataPath.Length);\n            var lastPathSeperator = localPathAndFile.LastIndexOf('/');\n            var localPath = localPathAndFile.Substring(0, lastPathSeperator);\n            SetDirectory(localPath);\n\n            // we dont want to include the last seperator so we need a +1 & -1 here\n            var returnedFileName = localPathAndFile.Substring(lastPathSeperator + 1, localPathAndFile.Length - lastPathSeperator - 1);\n\n            var extensionIndex = returnedFileName.LastIndexOf(\".cs\");\n            if (extensionIndex != -1) returnedFileName = returnedFileName.Substring(0, extensionIndex);\n\n            if (returnedFileName != m_ClassName) m_ClassName = returnedFileName;\n\n            ProjectWindowUtil.CreateScriptAssetFromTemplate(TargetPath(), GetTemplatePath());\n            AssetDatabase.Refresh();\n\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AdvancedDropdown/AdvancedDropdownDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    internal abstract class AdvancedDropdownDataSource\n    {\n        private static readonly string kSearchHeader = L10n.Tr(\"Search\");\n\n        private AdvancedDropdownItem m_MainTree;\n        private AdvancedDropdownItem m_SearchTree;\n        private AdvancedDropdownItem m_CurrentContextTree;\n        private List<int> m_SelectedIDs = new List<int>();\n\n        public AdvancedDropdownItem mainTree { get { return m_MainTree; }}\n        public AdvancedDropdownItem searchTree { get { return m_SearchTree; }}\n        public List<int> selectedIDs { get { return m_SelectedIDs; }}\n        public bool CurrentFolderContextualSearch { get; set; }\n\n        protected AdvancedDropdownItem root { get { return m_MainTree; }}\n        protected List<AdvancedDropdownItem> m_SearchableElements;\n\n        internal delegate bool SearchMatchItemHandler(in AdvancedDropdownItem item, in string[] words, out bool didMatchStart);\n\n        internal SearchMatchItemHandler searchMatchItem;\n        internal IComparer<AdvancedDropdownItem> searchMatchItemComparer;\n\n        public void ReloadData()\n        {\n            m_MainTree = FetchData();\n        }\n\n        protected abstract AdvancedDropdownItem FetchData();\n\n        public void RebuildSearch(string search, AdvancedDropdownItem currentTree)\n        {\n            if (CurrentFolderContextualSearch && m_CurrentContextTree != currentTree && currentTree != searchTree)\n            {\n                m_SearchableElements = null;\n            }\n            m_CurrentContextTree = currentTree;\n            m_SearchTree = Search(search);\n        }\n\n        protected bool AddMatchItem(AdvancedDropdownItem e, string name, string[] searchWords, List<AdvancedDropdownItem> matchesStart, List<AdvancedDropdownItem> matchesWithin)\n        {\n            var didMatchAll = true;\n            var didMatchStart = false;\n\n            if (searchMatchItem != null)\n            {\n                didMatchAll = searchMatchItem(e, searchWords, out didMatchStart);\n            }\n            else\n            {\n                // See if we match ALL the search words.\n                for (var w = 0; w < searchWords.Length; w++)\n                {\n                    var search = searchWords[w];\n                    if (name.Contains(search))\n                    {\n                        // If the start of the item matches the first search word, make a note of that.\n                        if (w == 0 && name.StartsWith(search))\n                            didMatchStart = true;\n                    }\n                    else\n                    {\n                        // As soon as any word is not matched, we disregard this item.\n                        didMatchAll = false;\n                        break;\n                    }\n                }\n            }\n\n            // We always need to match all search words.\n            // If we ALSO matched the start, this item gets priority.\n            if (didMatchAll)\n            {\n                if (didMatchStart)\n                    matchesStart.Add(e);\n                else\n                    matchesWithin.Add(e);\n            }\n            return didMatchAll;\n        }\n\n        protected virtual AdvancedDropdownItem Search(string searchString)\n        {\n            if (m_SearchableElements == null)\n            {\n                BuildSearchableElements();\n            }\n            if (string.IsNullOrEmpty(searchString))\n                return null;\n\n            // Support multiple search words separated by spaces.\n            var searchWords = searchString.ToLower().Split(' ');\n\n            // We keep two lists. Matches that matches the start of an item always get first priority.\n            var matchesStart = new List<AdvancedDropdownItem>();\n            var matchesWithin = new List<AdvancedDropdownItem>();\n\n            foreach (var e in m_SearchableElements)\n            {\n                var name = e.name.ToLower().Replace(\" \", \"\");\n                AddMatchItem(e, name, searchWords, matchesStart, matchesWithin);\n            }\n\n            var searchTree = new AdvancedDropdownItem(kSearchHeader);\n            if (searchMatchItemComparer == null)\n                matchesStart.Sort();\n            else\n                matchesStart.Sort(searchMatchItemComparer);\n            foreach (var element in matchesStart)\n            {\n                searchTree.AddChild(element);\n            }\n            if (searchMatchItemComparer == null)\n                matchesWithin.Sort();\n            else\n                matchesWithin.Sort(searchMatchItemComparer);\n            foreach (var element in matchesWithin)\n            {\n                searchTree.AddChild(element);\n            }\n            return searchTree;\n        }\n\n        void BuildSearchableElements()\n        {\n            m_SearchableElements = new List<AdvancedDropdownItem>();\n            BuildSearchableElements(CurrentFolderContextualSearch && m_CurrentContextTree != null ? m_CurrentContextTree : root);\n        }\n\n        void BuildSearchableElements(AdvancedDropdownItem item)\n        {\n            if (!item.children.Any())\n            {\n                m_SearchableElements.Add(item);\n                return;\n            }\n            foreach (var child in item.children)\n            {\n                BuildSearchableElements(child);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AdvancedDropdown/AdvancedDropdownGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEditor.StyleSheets;\nusing UnityEngine;\nusing Event = UnityEngine.Event;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    internal class AdvancedDropdownGUI\n    {\n        private static class Styles\n        {\n            public static GUIStyle itemStyle = \"DD ItemStyle\";\n            public static GUIStyle header = \"DD HeaderStyle\";\n            public static GUIStyle headerEllipsis = \"DD HeaderStyle\";\n            public static GUIStyle checkMark = \"DD ItemCheckmark\";\n            public static GUIStyle lineSeparator = \"DefaultLineSeparator\";\n            public static GUIStyle rightArrow = \"ArrowNavigationRight\";\n            public static GUIStyle leftArrow = \"ArrowNavigationLeft\";\n            public static GUIStyle searchFieldStyle = new GUIStyle(EditorStyles.toolbarSearchField)\n            {\n                margin = new RectOffset(5, 4, 4, 5)\n            };\n            public static SVC<Color> searchBackgroundColor = new SVC<Color>(\"--theme-toolbar-background-color\", Color.black);\n\n            public static GUIContent checkMarkContent = new GUIContent(\"✔\");\n\n            static Styles()\n            {\n                headerEllipsis.padding.left = 20;\n                headerEllipsis.clipping = TextClipping.Ellipsis;\n            }\n        }\n\n        internal static void LoadStyles()\n        {\n            Debug.Assert(Event.current.type == EventType.Repaint && Styles.itemStyle != null);\n        }\n\n        public static string k_SearchFieldName = \"ComponentSearch\";\n\n        //This should ideally match line height\n        private Vector2 s_IconSize = new Vector2(13, 13);\n        private AdvancedDropdownDataSource m_DataSource;\n\n        internal Rect m_SearchRect;\n        internal Rect m_HeaderRect;\n\n        internal Rect areaRect { get; set; }\n        internal virtual float searchHeight => m_SearchRect.height;\n        internal virtual float headerHeight => m_HeaderRect.height;\n        internal virtual GUIStyle lineStyle => Styles.itemStyle;\n        internal virtual Vector2 iconSize => s_IconSize;\n        internal AdvancedDropdownState state { get; set; }\n\n        public AdvancedDropdownGUI(AdvancedDropdownDataSource dataSource)\n        {\n            m_DataSource = dataSource;\n        }\n\n        internal virtual void DrawItem(AdvancedDropdownItem item, string name, Texture2D icon, bool enabled, bool drawArrow, bool selected, bool hasSearch)\n        {\n            var content = item.content;\n\n            // We need to pretend we have an icon to calculate proper width in case\n            var lastContentImage = content.image;\n            if (content.image == null)\n                content.image = Texture2D.whiteTexture;\n\n            // Clamp the rect width\n            var rect = GetItemRect(content);\n            var maxWidth = areaRect.width - GUI.skin.verticalScrollbar.fixedWidth; // todo: find a way to detect if we have a scrollbar\n            if (drawArrow)\n                maxWidth -= Styles.rightArrow.fixedWidth + Styles.rightArrow.margin.right;\n            if (maxWidth > 0)\n                rect.width = Math.Min(rect.width, maxWidth);\n\n            content.image = lastContentImage;\n\n            if (!string.IsNullOrEmpty(content.tooltip) && rect.Contains(Event.current.mousePosition) &&\n                !string.Equals(content.tooltip, content.text, StringComparison.Ordinal))\n                GUIStyle.SetMouseTooltip(content.tooltip, rect);\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            lastContentImage = content.image;\n            if (m_DataSource.selectedIDs.Any() && m_DataSource.selectedIDs.Contains(item.id))\n            {\n                var checkMarkRect = new Rect(rect);\n                checkMarkRect.width = iconSize.x + 1;\n                Styles.checkMark.Draw(checkMarkRect, Styles.checkMarkContent, false, false, selected, selected);\n                rect.x += iconSize.x + 1;\n                rect.width -= iconSize.x + 1;\n\n                // Don't draw the icon if the check mark is present\n                content.image = null;\n            }\n            else if (content.image == null)\n            {\n                lineStyle.Draw(rect, GUIContent.none, false, false, selected, selected);\n                rect.x += iconSize.x + 1;\n                rect.width -= iconSize.x + 1;\n            }\n\n            EditorGUI.BeginDisabled(!enabled);\n\n            var lastStyleClipping = lineStyle.clipping;\n            lineStyle.clipping = TextClipping.Ellipsis;\n\n            DrawItemContent(item, rect, content, false, false, selected, selected);\n\n            lineStyle.clipping = lastStyleClipping;\n            content.image = lastContentImage;\n\n            if (drawArrow)\n            {\n                var yOffset = (lineStyle.fixedHeight - Styles.rightArrow.fixedHeight) / 2;\n                Rect arrowRect = new Rect(\n                    rect.xMax,\n                    rect.y + yOffset,\n                    Styles.rightArrow.fixedWidth,\n                    Styles.rightArrow.fixedHeight);\n                Styles.rightArrow.Draw(arrowRect, false, false, false, false);\n            }\n\n            EditorGUI.EndDisabled();\n        }\n\n        internal virtual void DrawLineSeparator()\n        {\n            var rect = GUILayoutUtility.GetRect(GUIContent.none, Styles.lineSeparator, GUILayout.ExpandWidth(true));\n            if (Event.current.type != EventType.Repaint)\n                return;\n            Color orgColor = GUI.color;\n            Color tintColor = (EditorGUIUtility.isProSkin) ? new Color(0.12f, 0.12f, 0.12f, 1.333f) : new Color(0.6f, 0.6f, 0.6f, 1.333f);\n            GUI.color = GUI.color * tintColor;\n            GUI.DrawTexture(rect, EditorGUIUtility.whiteTexture);\n            GUI.color = orgColor;\n        }\n\n        internal void DrawHeader(AdvancedDropdownItem group, Action backButtonPressed, bool hasParent)\n        {\n            var content = group.content;\n            m_HeaderRect = GUILayoutUtility.GetRect(content, Styles.header, GUILayout.ExpandWidth(true), GUILayout.Height(22));\n            bool hovered = m_HeaderRect.Contains(Event.current.mousePosition);\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                var headerContentSize = Styles.header.CalcSize(content);\n                var textAreaWidth = m_HeaderRect.width - Styles.leftArrow.fixedWidth - Styles.header.padding.left - Styles.header.padding.right;\n                var headerStyle = textAreaWidth < headerContentSize.x ? Styles.headerEllipsis : Styles.header;\n                headerStyle.Draw(m_HeaderRect, content, hovered, false, false, false);\n            }\n\n            // Back button\n            if (hasParent)\n            {\n                var yOffset = (m_HeaderRect.height - Styles.leftArrow.fixedWidth) / 2;\n                var arrowRect = new Rect(\n                    m_HeaderRect.x + Styles.leftArrow.margin.left,\n                    m_HeaderRect.y + yOffset,\n                    Styles.leftArrow.fixedWidth,\n                    Styles.leftArrow.fixedHeight);\n                if (Event.current.type == EventType.Repaint)\n                    Styles.leftArrow.Draw(arrowRect, false, false, false, false);\n                if (Event.current.type == EventType.MouseDown && hovered)\n                {\n                    backButtonPressed();\n                    Event.current.Use();\n                }\n            }\n        }\n\n        internal void DrawSearchField(bool isSearchFieldDisabled, string searchString, Action<string> searchChanged)\n        {\n            if (!isSearchFieldDisabled && string.IsNullOrEmpty(GUI.GetNameOfFocusedControl()))\n            {\n                EditorGUI.FocusTextInControl(\"ComponentSearch\");\n            }\n\n            using (new EditorGUI.DisabledScope(isSearchFieldDisabled))\n            {\n                GUI.SetNextControlName(k_SearchFieldName);\n\n                var newSearch = DrawSearchFieldControl(searchString);\n\n                if (newSearch != searchString)\n                {\n                    searchChanged(newSearch);\n                }\n            }\n        }\n\n        internal virtual string DrawSearchFieldControl(string searchString)\n        {\n            var controlRect = GUILayoutUtility.GetRect(0, 0, Styles.searchFieldStyle);\n            m_SearchRect = CalculateSearchRect(ref controlRect);\n            EditorGUI.DrawRect(m_SearchRect, Styles.searchBackgroundColor);\n            var newSearch = EditorGUI.ToolbarSearchField(controlRect, searchString, false);\n\n            return newSearch;\n        }\n\n        Rect CalculateSearchRect(ref Rect controlRect)\n        {\n            const float kBorderWidth = 1f;\n            controlRect.height = Styles.searchFieldStyle.fixedHeight;\n            controlRect.xMin += kBorderWidth;\n            controlRect.xMax -= kBorderWidth;\n            controlRect.yMin += kBorderWidth;\n            return Styles.searchFieldStyle.margin.Add(controlRect);\n        }\n\n        internal Rect GetAnimRect(Rect position, float anim)\n        {\n            // Calculate rect for animated area\n            var rect = new Rect(position);\n            rect.x = position.x + position.width * anim;\n            rect.y += searchHeight;\n            rect.height -= searchHeight;\n            return rect;\n        }\n\n        internal Vector2 CalculateContentSize(AdvancedDropdownDataSource dataSource)\n        {\n            float maxWidth = 0;\n            float maxHeight = 0;\n            bool includeArrow = false;\n            float arrowWidth = Styles.rightArrow.fixedWidth;\n\n            foreach (var child in dataSource.mainTree.children)\n            {\n                var content = child.content;\n                var a = CalcItemSize(content);\n                a.x += iconSize.x + 1;\n\n                if (maxWidth < a.x)\n                {\n                    maxWidth = a.x + 1;\n                    includeArrow |= child.children.Any();\n                }\n                if (child.IsSeparator())\n                {\n                    maxHeight += Styles.lineSeparator.CalcHeight(content, maxWidth) + Styles.lineSeparator.margin.vertical;\n                }\n                else\n                {\n                    maxHeight += CalcItemHeight(content, maxWidth);\n                }\n            }\n            if (includeArrow)\n            {\n                maxWidth += arrowWidth;\n            }\n\n            // other size calculations may rely on m_HeaderRect and m_SearchRect, which wont be populated until the first time they are drawn\n            // so they need to be calculated here if needed.\n            if (m_HeaderRect == default(Rect))\n            {\n                var headerContent = GUIContent.Temp(dataSource.mainTree.name, dataSource.mainTree.icon);\n                var headerSize = Styles.header.CalcSize(headerContent);\n                if (maxWidth > headerSize.x)\n                    headerSize.x = maxWidth;\n                headerSize.y = Styles.header.CalcHeight(headerContent, maxWidth);\n                m_HeaderRect = new Rect(0, 0, headerSize.x, headerSize.y);\n            }\n            if (m_SearchRect == default(Rect))\n            {\n                var controlRectSize = Styles.searchFieldStyle.CalcSize(GUIContent.none);\n                controlRectSize.x = maxWidth;\n                var controlRect = new Rect(0, 0, controlRectSize.x, controlRectSize.y);\n                m_SearchRect = CalculateSearchRect(ref controlRect);\n            }\n\n            return new Vector2(maxWidth, maxHeight);\n        }\n\n        internal float GetSelectionHeight(AdvancedDropdownDataSource dataSource, Rect buttonRect)\n        {\n            if (state.GetSelectedIndex(dataSource.mainTree) == -1)\n                return 0;\n            float heigth = 0;\n            for (int i = 0; i < dataSource.mainTree.children.Count(); i++)\n            {\n                var child = dataSource.mainTree.children.ElementAt(i);\n                var content = child.content;\n                if (state.GetSelectedIndex(dataSource.mainTree) == i)\n                {\n                    var diff = (CalcItemHeight(content, 0) - buttonRect.height) / 2f;\n                    return heigth + diff;\n                }\n                if (child.IsSeparator())\n                {\n                    heigth += Styles.lineSeparator.CalcHeight(content, 0) + Styles.lineSeparator.margin.vertical;\n                }\n                else\n                {\n                    heigth += CalcItemHeight(content, 0);\n                }\n            }\n            return heigth;\n        }\n\n        internal virtual Rect GetItemRect(in GUIContent content)\n        {\n            return GUILayoutUtility.GetRect(content, lineStyle, GUILayout.ExpandWidth(true));\n        }\n\n        internal virtual float CalcItemHeight(GUIContent content, float width)\n        {\n            return lineStyle.CalcHeight(content, width);\n        }\n\n        internal virtual Vector2 CalcItemSize(GUIContent content)\n        {\n            return lineStyle.CalcSize(content);\n        }\n\n        internal virtual void DrawItemContent(AdvancedDropdownItem item, Rect rect, GUIContent content, bool isHover, bool isActive, bool on, bool hasKeyboardFocus)\n        {\n            lineStyle.Draw(rect, content, isHover, isActive, on, hasKeyboardFocus);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AdvancedDropdown/AdvancedDropdownItem.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public class AdvancedDropdownItem : IComparable\n    {\n        string m_Name;\n        int m_Id;\n        int m_ElementIndex = -1;\n        bool m_Enabled = true;\n        GUIContent m_Content;\n        List<AdvancedDropdownItem> m_Children = new List<AdvancedDropdownItem>();\n\n        public string name\n        {\n            get { return m_Name; }\n            set { m_Name = value; }\n        }\n\n        internal GUIContent content => m_Content;\n\n        internal string tooltip\n        {\n            get => m_Content.tooltip;\n            set { m_Content.tooltip = value; }\n        }\n\n        internal virtual string displayName\n        {\n            get => string.IsNullOrEmpty(m_Content.text) ? m_Name : m_Content.text;\n            set { m_Content.text = value; }\n        }\n\n        public Texture2D icon\n        {\n            get => m_Content?.image as Texture2D;\n            set { m_Content.image = value; }\n        }\n\n        public int id\n        {\n            get => m_Id;\n            set { m_Id = value; }\n        }\n\n        internal int elementIndex\n        {\n            get { return m_ElementIndex; }\n            set { m_ElementIndex = value; }\n        }\n\n        public bool enabled\n        {\n            get { return m_Enabled; }\n            set { m_Enabled = value; }\n        }\n\n        internal object userData { get; set; }\n\n        public IEnumerable<AdvancedDropdownItem> children => m_Children;\n\n        internal bool hasChildren => m_Children.Count > 0;\n\n        public void AddChild(AdvancedDropdownItem child)\n        {\n            m_Children.Add(child);\n        }\n\n        static readonly AdvancedDropdownItem k_SeparatorItem = new SeparatorDropdownItem();\n\n        public AdvancedDropdownItem(string name)\n        {\n            m_Name = name;\n            m_Id = name.GetHashCode();\n            m_Content = new GUIContent(m_Name);\n        }\n\n        public override int GetHashCode()\n        {\n            return name.GetHashCode();\n        }\n\n        public virtual int CompareTo(object o)\n        {\n            return string.CompareOrdinal(name, ((AdvancedDropdownItem)o).name);\n        }\n\n        public void AddSeparator()\n        {\n            AddChild(k_SeparatorItem);\n        }\n\n        internal bool IsSeparator()\n        {\n            return k_SeparatorItem == this;\n        }\n\n        public override string ToString()\n        {\n            return m_Name;\n        }\n\n        internal void SortChildren(Comparison<AdvancedDropdownItem> comparer, bool recursive = false)\n        {\n            if (recursive)\n            {\n                foreach (var child in m_Children)\n                    child.SortChildren(comparer, recursive);\n            }\n\n            m_Children.Sort(comparer);\n        }\n\n        class SeparatorDropdownItem : AdvancedDropdownItem\n        {\n            public SeparatorDropdownItem() : base(\"SEPARATOR\")\n            {\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AdvancedDropdown/AdvancedDropdownState.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    [Serializable]\n    public class AdvancedDropdownState\n    {\n        [Serializable]\n        private class AdvancedDropdownItemState\n        {\n            public AdvancedDropdownItemState(AdvancedDropdownItem item)\n            {\n                this.itemId = item.id;\n            }\n\n            public int itemId;\n            public int selectedIndex = -1;\n            public Vector2 scroll;\n        }\n\n        [SerializeField]\n        private AdvancedDropdownItemState[] states = new AdvancedDropdownItemState[0];\n        private AdvancedDropdownItemState m_LastSelectedState;\n\n        private AdvancedDropdownItemState GetStateForItem(AdvancedDropdownItem item)\n        {\n            if (m_LastSelectedState != null && m_LastSelectedState.itemId == item.id)\n                return m_LastSelectedState;\n            for (int i = 0; i < states.Length; i++)\n            {\n                if (states[i].itemId == item.id)\n                {\n                    m_LastSelectedState = states[i];\n                    return m_LastSelectedState;\n                }\n            }\n            Array.Resize(ref states, states.Length + 1);\n            states[states.Length - 1] = new AdvancedDropdownItemState(item);\n            m_LastSelectedState = states[states.Length - 1];\n            return states[states.Length - 1];\n        }\n\n        internal void MoveDownSelection(AdvancedDropdownItem item)\n        {\n            var state = GetStateForItem(item);\n            var selectedIndex = state.selectedIndex;\n            do\n            {\n                ++selectedIndex;\n            }\n            while (selectedIndex < item.children.Count() && item.children.ElementAt(selectedIndex).IsSeparator());\n\n            if (selectedIndex >= item.children.Count())\n                selectedIndex = 0;\n\n            if (selectedIndex < item.children.Count())\n                SetSelectionOnItem(item, selectedIndex);\n        }\n\n        internal void MoveUpSelection(AdvancedDropdownItem item)\n        {\n            var state = GetStateForItem(item);\n            var selectedIndex = state.selectedIndex;\n            do\n            {\n                --selectedIndex;\n            }\n            while (selectedIndex >= 0 && item.children.ElementAt(selectedIndex).IsSeparator());\n\n            if (selectedIndex < 0)\n                selectedIndex = item.children.Count() - 1;\n\n            if (selectedIndex >= 0)\n                SetSelectionOnItem(item, selectedIndex);\n        }\n\n        internal void SetSelectionOnItem(AdvancedDropdownItem item, int selectedIndex)\n        {\n            var state = GetStateForItem(item);\n\n            if (selectedIndex < 0)\n            {\n                state.selectedIndex = 0;\n            }\n            else if (selectedIndex >= item.children.Count())\n            {\n                state.selectedIndex = item.children.Count() - 1;\n            }\n            else\n            {\n                state.selectedIndex = selectedIndex;\n            }\n        }\n\n        internal int GetSelectedIndex(AdvancedDropdownItem item)\n        {\n            return GetStateForItem(item).selectedIndex;\n        }\n\n        internal void SetSelectedIndex(AdvancedDropdownItem item, int index)\n        {\n            GetStateForItem(item).selectedIndex = index;\n        }\n\n        internal AdvancedDropdownItem GetSelectedChild(AdvancedDropdownItem item)\n        {\n            var index = GetSelectedIndex(item);\n            if (!item.children.Any() || index < 0 || index >= item.children.Count())\n                return null;\n            return item.children.ElementAt(index);\n        }\n\n        internal Vector2 GetScrollState(AdvancedDropdownItem item)\n        {\n            return GetStateForItem(item).scroll;\n        }\n\n        internal void SetScrollState(AdvancedDropdownItem item, Vector2 scrollState)\n        {\n            GetStateForItem(item).scroll = scrollState;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AdvancedDropdown/AdvancedDropdownWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Callbacks;\nusing UnityEngine;\nusing Event = UnityEngine.Event;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    internal class AdvancedDropdownWindow : EditorWindow\n    {\n        private static class Styles\n        {\n            public static GUIStyle background = \"DD Background\";\n            public static GUIStyle previewHeader = new GUIStyle(EditorStyles.label);\n            public static GUIStyle previewText = new GUIStyle(EditorStyles.wordWrappedLabel);\n\n            static Styles()\n            {\n                previewText.padding.left += 3;\n                previewText.padding.right += 3;\n                previewHeader.padding.left += 3 - 2;\n                previewHeader.padding.right += 3;\n                previewHeader.padding.top += 3;\n                previewHeader.padding.bottom += 2;\n            }\n        }\n        private static readonly float kBorderThickness = 1f;\n        private static readonly float kRightMargin = 13f;\n\n        private AdvancedDropdownGUI m_Gui = null;\n        private AdvancedDropdownDataSource m_DataSource = null;\n        private AdvancedDropdownState m_State = null;\n\n        private AdvancedDropdownItem m_CurrentlyRenderedTree;\n        protected AdvancedDropdownItem renderedTreeItem => m_CurrentlyRenderedTree;\n\n        private AdvancedDropdownItem m_AnimationTree;\n        private float m_NewAnimTarget = 0;\n        private long m_LastTime = 0;\n        private bool m_ScrollToSelected = true;\n        private float m_InitialSelectionPosition = 0f;\n        private Rect m_ButtonRectScreenPos;\n        private Stack<AdvancedDropdownItem> m_ViewsStack = new Stack<AdvancedDropdownItem>();\n        private bool m_DirtyList = true;\n\n        private string m_Search = \"\";\n        private bool hasSearch { get { return !string.IsNullOrEmpty(m_Search); } }\n        protected internal string searchString\n        {\n            get { return m_Search; }\n            set\n            {\n                m_Search = value;\n                m_DataSource.RebuildSearch(m_Search, m_CurrentlyRenderedTree);\n                m_CurrentlyRenderedTree = m_DataSource.mainTree;\n                if (hasSearch)\n                {\n                    m_CurrentlyRenderedTree = m_DataSource.searchTree;\n                    if (state.GetSelectedIndex(m_CurrentlyRenderedTree) < 0)\n                    {\n                        state.SetSelectedIndex(m_CurrentlyRenderedTree, 0);\n                    }\n                }\n            }\n        }\n\n        internal bool showHeader { get; set; } = true;\n        internal bool searchable { get; set; } = true;\n        internal bool closeOnSelection { get; set; } = true;\n\n        protected virtual bool isSearchFieldDisabled { get; set; }\n        protected virtual bool setInitialSelectionPosition { get; } = true;\n\n        protected internal AdvancedDropdownState state\n        {\n            get { return m_State; }\n            set { m_State = value; }\n        }\n\n        protected internal AdvancedDropdownGUI gui\n        {\n            get { return m_Gui; }\n            set { m_Gui = value; }\n        }\n\n        protected internal AdvancedDropdownDataSource dataSource\n        {\n            get { return m_DataSource; }\n            set { m_DataSource = value; }\n        }\n\n        public event Action<AdvancedDropdownWindow> windowClosed;\n        public event Action<AdvancedDropdownItem> selectionChanged;\n        public event Action selectionCanceled;\n        internal Func<Event, bool> specialKeyboardHandling;\n\n        protected virtual void OnEnable()\n        {\n            m_DirtyList = true;\n        }\n\n        protected virtual void OnDisable()\n        {\n            selectionCanceled?.Invoke();\n        }\n\n        protected virtual void OnDestroy()\n        {\n            // This window sets 'editingTextField = true' continuously, through EditorGUI.FocusTextInControl(),\n            // for the search field in its AdvancedDropdownGUI so here we ensure to clean up. This fixes the issue that\n            // EditorGUI.IsEditingTextField() was returning true after e.g the Add Component Menu closes\n            EditorGUIUtility.editingTextField = false;\n        }\n\n        public static T CreateAndInit<T>(Rect rect, AdvancedDropdownState state) where T : AdvancedDropdownWindow\n        {\n            var instance = CreateInstance<T>();\n            instance.m_State = state;\n            instance.Init(rect);\n            return instance;\n        }\n\n        public void Init(Rect buttonRect)\n        {\n            m_ButtonRectScreenPos = EditorGUIUtility.GUIToScreenRect(buttonRect);\n            if (m_State == null)\n                m_State = new AdvancedDropdownState();\n            if (m_DataSource == null)\n                m_DataSource = new MultiLevelDataSource();\n            if (m_Gui == null)\n                m_Gui = new AdvancedDropdownGUI(m_DataSource);\n            m_Gui.state = m_State;\n\n            // Has to be done before calling Show / ShowWithMode\n            buttonRect = GUIUtility.GUIToScreenRect(buttonRect);\n            OnDirtyList();\n            m_CurrentlyRenderedTree = hasSearch ? m_DataSource.searchTree : m_DataSource.mainTree;\n            ShowAsDropDown(buttonRect, CalculateWindowSize(buttonRect), GetLocationPriority());\n            if (setInitialSelectionPosition)\n            {\n                m_InitialSelectionPosition = m_Gui.GetSelectionHeight(m_DataSource, buttonRect);\n            }\n            wantsMouseMove = true;\n            SetSelectionFromState();\n        }\n\n        void SetSelectionFromState()\n        {\n            var selectedIndex = m_State.GetSelectedIndex(m_CurrentlyRenderedTree);\n            while (selectedIndex >= 0)\n            {\n                var child = m_State.GetSelectedChild(m_CurrentlyRenderedTree);\n                if (child == null)\n                    break;\n                if (child.id == m_CurrentlyRenderedTree.id)\n                    Debug.LogWarning($\"Same id: {child.id} given to both {child.displayName} and {m_CurrentlyRenderedTree.displayName}. Selection may be wrong.\");\n                selectedIndex = m_State.GetSelectedIndex(child);\n                if (selectedIndex < 0)\n                    break;\n                m_ViewsStack.Push(m_CurrentlyRenderedTree);\n                m_CurrentlyRenderedTree = child;\n            }\n        }\n\n        PopupLocation[] GetLocationPriority()\n        {\n            return new[]\n            {\n                PopupLocation.Below,\n                PopupLocation.Overlay,\n            };\n        }\n\n        protected virtual Vector2 CalculateWindowSize(Rect buttonRect)\n        {\n            var size = m_Gui.CalculateContentSize(m_DataSource);\n            // Add 1 pixel for each border\n            size.x += kBorderThickness * 2;\n            size.y += kBorderThickness * 2;\n            size.x += kRightMargin;\n\n            size.y += m_Gui.searchHeight;\n\n            if (showHeader)\n            {\n                size.y += m_Gui.headerHeight;\n            }\n\n            size.y = Mathf.Clamp(size.y, minSize.y, maxSize.y);\n\n            var fitRect = ContainerWindow.FitRectToMouseScreen(new Rect(buttonRect.x, buttonRect.y, size.x, size.y), true, null);\n            // If the scrollbar is visible, we want to add extra space to compensate it\n            if (fitRect.height < size.y)\n                size.x += GUI.skin.verticalScrollbar.fixedWidth;\n\n            // Stretch to the width of the button\n            if (size.x < buttonRect.width)\n            {\n                size.x = buttonRect.width;\n            }\n            if (size.x < minSize.x)\n            {\n                size.x = minSize.x;\n            }\n            if (size.y < minSize.y)\n            {\n                size.y = minSize.y;\n            }\n\n            return new Vector2(size.x, size.y);\n        }\n\n        internal void OnGUI()\n        {\n            GUI.Label(new Rect(0, 0, position.width, position.height), GUIContent.none, Styles.background);\n\n            if (m_DirtyList)\n            {\n                OnDirtyList();\n            }\n\n            HandleKeyboard();\n            if (searchable)\n                OnGUISearch();\n\n            if (m_NewAnimTarget != 0 && Event.current.type == EventType.Layout)\n            {\n                long now = DateTime.Now.Ticks;\n                float deltaTime = (now - m_LastTime) / (float)TimeSpan.TicksPerSecond;\n                m_LastTime = now;\n\n                m_NewAnimTarget = Mathf.MoveTowards(m_NewAnimTarget, 0, deltaTime * 4);\n\n                if (m_NewAnimTarget == 0)\n                {\n                    m_AnimationTree = null;\n                }\n                Repaint();\n            }\n\n            var anim = m_NewAnimTarget;\n            // Smooth the animation\n            anim = Mathf.Floor(anim) + Mathf.SmoothStep(0, 1, Mathf.Repeat(anim, 1));\n\n            if (anim == 0)\n            {\n                DrawDropdown(0, m_CurrentlyRenderedTree);\n            }\n            else if (anim < 0)\n            {\n                // Go to parent\n                // m_NewAnimTarget goes -1 -> 0\n                DrawDropdown(anim, m_CurrentlyRenderedTree);\n                DrawDropdown(anim + 1, m_AnimationTree);\n            }\n            else // > 0\n            {\n                // Go to child\n                // m_NewAnimTarget 1 -> 0\n                DrawDropdown(anim - 1, m_AnimationTree);\n                DrawDropdown(anim, m_CurrentlyRenderedTree);\n            }\n        }\n\n        private void OnDirtyList()\n        {\n            m_DirtyList = false;\n            m_DataSource.ReloadData();\n            if (hasSearch)\n            {\n                m_DataSource.RebuildSearch(searchString, m_CurrentlyRenderedTree);\n                if (state.GetSelectedIndex(m_CurrentlyRenderedTree) < 0)\n                {\n                    state.SetSelectedIndex(m_CurrentlyRenderedTree, 0);\n                }\n            }\n        }\n\n        private void OnGUISearch()\n        {\n            m_Gui.DrawSearchField(isSearchFieldDisabled, m_Search, (newSearch) =>\n            {\n                searchString = newSearch;\n            });\n        }\n\n        private void HandleKeyboard()\n        {\n            var evt = Event.current;\n            if (evt.type == EventType.KeyDown)\n            {\n                // Special handling when in new script panel\n                if (SpecialKeyboardHandling(evt))\n                {\n                    return;\n                }\n\n                // Always do these\n                if (evt.keyCode == KeyCode.DownArrow)\n                {\n                    m_State.MoveDownSelection(m_CurrentlyRenderedTree);\n                    m_ScrollToSelected = true;\n                    evt.Use();\n                }\n                if (evt.keyCode == KeyCode.UpArrow)\n                {\n                    m_State.MoveUpSelection(m_CurrentlyRenderedTree);\n                    m_ScrollToSelected = true;\n                    evt.Use();\n                }\n                if (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter)\n                {\n                    var selected = m_State.GetSelectedChild(m_CurrentlyRenderedTree);\n                    if (selected != null)\n                    {\n                        if (selected.children.Any())\n                        {\n                            GoToChild();\n                        }\n                        else\n                        {\n                            if (selectionChanged != null)\n                            {\n                                selectionChanged(m_State.GetSelectedChild(m_CurrentlyRenderedTree));\n                            }\n                            if (closeOnSelection)\n                            {\n                                CloseWindow();\n                            }\n                        }\n                    }\n                    evt.Use();\n                }\n\n                // Do these if we're not in search mode\n                if (!hasSearch &&\n                    (string.IsNullOrEmpty(GUI.GetNameOfFocusedControl()) || GUI.GetNameOfFocusedControl() == AdvancedDropdownGUI.k_SearchFieldName))\n                {\n                    if (evt.keyCode == KeyCode.LeftArrow || evt.keyCode == KeyCode.Backspace)\n                    {\n                        GoToParent();\n                        evt.Use();\n                    }\n                    else if (evt.keyCode == KeyCode.RightArrow)\n                    {\n                        var idx = m_State.GetSelectedIndex(m_CurrentlyRenderedTree);\n                        if (idx > -1 && m_CurrentlyRenderedTree.children.ElementAt(idx).children.Any())\n                        {\n                            GoToChild();\n                        }\n                        evt.Use();\n                    }\n                    else if (evt.keyCode == KeyCode.Escape)\n                    {\n                        Close();\n                        evt.Use();\n                    }\n                }\n            }\n        }\n\n        private void CloseWindow()\n        {\n            if (GetSelectedItem() != null)\n                selectionCanceled = null;\n            if (windowClosed != null)\n                windowClosed(this);\n            Close();\n        }\n\n        internal AdvancedDropdownItem GetSelectedItem()\n        {\n            return m_State.GetSelectedChild(m_CurrentlyRenderedTree);\n        }\n\n        protected virtual bool SpecialKeyboardHandling(Event evt)\n        {\n            return specialKeyboardHandling?.Invoke(evt) ?? false;\n        }\n\n        private void DrawDropdown(float anim, AdvancedDropdownItem group)\n        {\n            // Start of animated area (the part that moves left and right)\n            var areaPosition = new Rect(0, 0, position.width, position.height);\n            // Adjust to the frame\n            areaPosition.x += kBorderThickness;\n            areaPosition.y += kBorderThickness;\n            areaPosition.height -= kBorderThickness * 2;\n            areaPosition.width -= kBorderThickness * 2;\n            m_Gui.areaRect = areaPosition;\n\n            GUILayout.BeginArea(m_Gui.GetAnimRect(areaPosition, anim));\n            // Header\n            if (showHeader)\n                m_Gui.DrawHeader(group, GoToParent, m_ViewsStack.Count > 0);\n\n            DrawList(group);\n            GUILayout.EndArea();\n        }\n\n        private void DrawList(AdvancedDropdownItem item)\n        {\n            // Start of scroll view list\n            m_State.SetScrollState(item, GUILayout.BeginScrollView(m_State.GetScrollState(item), GUIStyle.none, GUI.skin.verticalScrollbar));\n            EditorGUIUtility.SetIconSize(m_Gui.iconSize);\n            Rect selectedRect = new Rect();\n            for (var i = 0; i < item.children.Count(); i++)\n            {\n                var child = item.children.ElementAt(i);\n                bool selected = m_State.GetSelectedIndex(item) == i;\n\n                if (child.IsSeparator())\n                {\n                    m_Gui.DrawLineSeparator();\n                }\n                else\n                {\n                    m_Gui.DrawItem(child, child.displayName, child.icon, child.enabled, child.children.Any(), selected, hasSearch);\n                }\n\n                var r = GUILayoutUtility.GetLastRect();\n                if (selected)\n                    selectedRect = r;\n\n                // Skip input handling for the tree used for animation\n                if (item != m_CurrentlyRenderedTree)\n                    continue;\n\n                // Select the element the mouse cursor is over.\n                // Only do it on mouse move - keyboard controls are allowed to overwrite this until the next time the mouse moves.\n                if (Event.current.type == EventType.MouseMove || Event.current.type == EventType.MouseDrag)\n                {\n                    if (!selected && r.Contains(Event.current.mousePosition))\n                    {\n                        m_State.SetSelectedIndex(item, i);\n                        Event.current.Use();\n                    }\n                }\n                if (Event.current.type == EventType.MouseUp && r.Contains(Event.current.mousePosition))\n                {\n                    m_State.SetSelectedIndex(item, i);\n                    var selectedChild = m_State.GetSelectedChild(item);\n                    if (selectedChild.children.Any())\n                    {\n                        GoToChild();\n                    }\n                    else\n                    {\n                        if (!selectedChild.IsSeparator() && selectionChanged != null)\n                        {\n                            selectionChanged(selectedChild);\n                        }\n                        if (closeOnSelection)\n                        {\n                            CloseWindow();\n                            GUIUtility.ExitGUI();\n                        }\n                    }\n                    Event.current.Use();\n                }\n            }\n            EditorGUIUtility.SetIconSize(Vector2.zero);\n            GUILayout.EndScrollView();\n\n            // Scroll to selected on windows creation\n            if (m_ScrollToSelected && m_InitialSelectionPosition != 0)\n            {\n                float diffOfPopupAboveTheButton = m_ButtonRectScreenPos.y - position.y;\n                diffOfPopupAboveTheButton -= m_Gui.searchHeight + m_Gui.headerHeight;\n                m_State.SetScrollState(item, new Vector2(0, m_InitialSelectionPosition - diffOfPopupAboveTheButton));\n                m_ScrollToSelected = false;\n                m_InitialSelectionPosition = 0;\n            }\n            // Scroll to show selected\n            else if (m_ScrollToSelected && Event.current.type == EventType.Repaint)\n            {\n                m_ScrollToSelected = false;\n                Rect scrollRect = GUILayoutUtility.GetLastRect();\n                if (selectedRect.yMax - scrollRect.height > m_State.GetScrollState(item).y)\n                {\n                    m_State.SetScrollState(item, new Vector2(0, selectedRect.yMax - scrollRect.height));\n                    Repaint();\n                }\n                if (selectedRect.y < m_State.GetScrollState(item).y)\n                {\n                    m_State.SetScrollState(item, new Vector2(0, selectedRect.y));\n                    Repaint();\n                }\n            }\n        }\n\n        protected void GoToParent()\n        {\n            GUI.FocusControl(\"\");\n            if (m_ViewsStack.Count == 0)\n                return;\n            m_LastTime = DateTime.Now.Ticks;\n            if (m_NewAnimTarget > 0)\n                m_NewAnimTarget = -1 + m_NewAnimTarget;\n            else\n                m_NewAnimTarget = -1;\n            m_AnimationTree = m_CurrentlyRenderedTree;\n            m_CurrentlyRenderedTree = m_ViewsStack.Pop();\n        }\n\n        private void GoToChild()\n        {\n            GUI.FocusControl(\"\");\n            m_ViewsStack.Push(m_CurrentlyRenderedTree);\n            m_LastTime = DateTime.Now.Ticks;\n            if (m_NewAnimTarget < 0)\n                m_NewAnimTarget = 1 + m_NewAnimTarget;\n            else\n                m_NewAnimTarget = 1;\n            m_AnimationTree = m_CurrentlyRenderedTree;\n            m_CurrentlyRenderedTree = m_State.GetSelectedChild(m_CurrentlyRenderedTree);\n        }\n\n        [DidReloadScripts]\n        private static void OnScriptReload()\n        {\n            CloseAllOpenWindows<AdvancedDropdownWindow>();\n        }\n\n        protected static void CloseAllOpenWindows<T>()\n        {\n            var windows = Resources.FindObjectsOfTypeAll(typeof(T));\n            foreach (var window in windows)\n            {\n                try\n                {\n                    ((EditorWindow)window).Close();\n                }\n                catch\n                {\n                    DestroyImmediate(window);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AdvancedDropdown/DataSources/CallbackDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    internal class CallbackDataSource : AdvancedDropdownDataSource\n    {\n        Func<AdvancedDropdownItem> m_BuildCallback;\n\n        internal CallbackDataSource(Func<AdvancedDropdownItem> buildCallback)\n        {\n            m_BuildCallback = buildCallback;\n        }\n\n        protected override AdvancedDropdownItem FetchData()\n        {\n            return m_BuildCallback();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AdvancedDropdown/DataSources/MultiLevelDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    internal class MultiLevelDataSource : AdvancedDropdownDataSource\n    {\n        private string[] m_DisplayedOptions;\n        internal string[] displayedOptions\n        {\n            set { m_DisplayedOptions = value; }\n        }\n\n        private string m_Label = \"\";\n        internal string label\n        {\n            set { m_Label = value; }\n        }\n\n        private static int m_SelectedIndex;\n        internal int selectedIndex\n        {\n            set { m_SelectedIndex = value; }\n        }\n\n        internal MultiLevelDataSource()\n        {\n        }\n\n        public MultiLevelDataSource(string[] displayOptions)\n        {\n            m_DisplayedOptions = displayOptions;\n        }\n\n        protected override AdvancedDropdownItem FetchData()\n        {\n            var rootGroup = new AdvancedDropdownItem(m_Label);\n            m_SearchableElements = new List<AdvancedDropdownItem>();\n\n            for (int i = 0; i < m_DisplayedOptions.Length; i++)\n            {\n                var menuPath = m_DisplayedOptions[i];\n                var paths = menuPath.Split('/');\n\n                AdvancedDropdownItem parent = rootGroup;\n                for (var j = 0; j < paths.Length; j++)\n                {\n                    var path = paths[j];\n                    if (j == paths.Length - 1)\n                    {\n                        var element = new MultiLevelItem(path, menuPath);\n                        element.elementIndex = i;\n                        parent.AddChild(element);\n                        m_SearchableElements.Add(element);\n\n                        if (i == m_SelectedIndex)\n                        {\n                            selectedIDs.Add(element.id);\n//                            var tempParent = parent;\n//                            AdvancedDropdownItem searchedItem = element;\n                            //TODO fix selecting\n//                            while (tempParent != null)\n//                            {\n//                                state.SetSelectedIndex(tempParent, tempParent.children.IndexOf(searchedItem));\n//                                searchedItem = tempParent;\n//                                tempParent = tempParent.parent;\n//                            }\n                        }\n                        continue;\n                    }\n\n                    var groupPathId = paths[0];\n                    for (int k = 1; k <= j; k++)\n                        groupPathId += \"/\" + paths[k];\n\n                    var group = parent.children.SingleOrDefault(c => ((MultiLevelItem)c).stringId == groupPathId);\n                    if (group == null)\n                    {\n                        group = new MultiLevelItem(path, groupPathId);\n                        parent.AddChild(group);\n                    }\n                    parent = group;\n                }\n            }\n            return rootGroup;\n        }\n\n        class MultiLevelItem : AdvancedDropdownItem\n        {\n            internal string stringId;\n            public MultiLevelItem(string path, string menuPath) : base(path)\n            {\n                stringId = menuPath;\n                id = menuPath.GetHashCode();\n            }\n\n            public override string ToString()\n            {\n                return stringId;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AdvancedDropdown/DataSources/MultiselectDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    internal class MultiselectDataSource : AdvancedDropdownDataSource\n    {\n        private Enum m_EnumFlag;\n        private int m_Mask;\n        private int[] m_OptionMaskValues;\n        private string[] m_OptionNames;\n        private int[] m_SelectedOptions;\n\n        string[] m_DisplayNames;\n        int[] m_FlagValues;\n\n        public Enum enumFlags => m_EnumFlag;\n        public int mask => m_Mask;\n\n        public MultiselectDataSource(Enum enumValue)\n        {\n            m_EnumFlag = enumValue;\n            var enumType = enumFlags.GetType();\n\n            var enumData = EnumDataUtility.GetCachedEnumData(enumType);\n            if (!enumData.serializable)\n                // this is the same message used in SerializedPropertyEnumHelper.cpp\n                throw new NotSupportedException(string.Format(\"Unsupported enum base type for {0}\", enumType.Name));\n\n            m_Mask = EnumDataUtility.EnumFlagsToInt(enumData, enumFlags);\n            m_DisplayNames = enumData.displayNames;\n            m_FlagValues = enumData.flagValues;\n\n            MaskFieldGUI.GetMenuOptions(m_Mask, m_DisplayNames, m_FlagValues, out var buttonText, out var buttonTextMixed, out m_OptionNames, out m_OptionMaskValues, out m_SelectedOptions);\n        }\n\n        public MultiselectDataSource(int mask, string[] displayedOptions, int[] flagValues)\n        {\n            m_DisplayNames = displayedOptions;\n            m_FlagValues = flagValues;\n            MaskFieldGUI.GetMenuOptions(mask, displayedOptions, flagValues, out var buttonText, out var buttonTextMixed, out m_OptionNames, out m_OptionMaskValues, out m_SelectedOptions);\n        }\n\n        protected override AdvancedDropdownItem FetchData()\n        {\n            var rootGroup = new AdvancedDropdownItem(string.Empty);\n            for (var i = 0; i < m_OptionNames.Length; i++)\n            {\n                if (i == 2)\n                    rootGroup.AddSeparator();\n                var element = new AdvancedDropdownItem(m_OptionNames[i]);\n                element.elementIndex = i;\n                rootGroup.AddChild(element);\n            }\n\n            RebuildSelection(rootGroup);\n            return rootGroup;\n        }\n\n        void RebuildSelection(AdvancedDropdownItem rootItem)\n        {\n            selectedIDs.Clear();\n            foreach (var selectionOption in m_SelectedOptions)\n            {\n                var name = m_OptionNames[selectionOption];\n                foreach (var child in rootItem.children)\n                {\n                    if (child.name == name)\n                        selectedIDs.Add(child.id);\n                }\n            }\n        }\n\n        public void UpdateSelectedId(AdvancedDropdownItem item)\n        {\n            m_Mask = m_OptionMaskValues[item.elementIndex];\n            MaskFieldGUI.GetMenuOptions(m_Mask, m_DisplayNames, m_FlagValues, out var buttonText, out var buttonTextMixed, out m_OptionNames, out m_OptionMaskValues, out m_SelectedOptions);\n            if (enumFlags != null)\n                m_EnumFlag = EnumDataUtility.IntToEnumFlags(enumFlags.GetType(), m_Mask);\n            RebuildSelection(root);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AdvancedDropdown/DataSources/SimpleDataSource.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    internal class SimpleDataSource : AdvancedDropdownDataSource\n    {\n        private GUIContent[] m_DisplayedOptions;\n        internal GUIContent[] displayedOptions\n        {\n            set { m_DisplayedOptions = value; }\n        }\n\n        private static int m_SelectedIndex;\n#pragma warning disable 0649\n        private AdvancedDropdownState m_State;\n#pragma warning restore 0649\n\n        internal int selectedIndex\n        {\n            set { m_SelectedIndex = value; }\n        }\n\n        internal SimpleDataSource()\n        {\n        }\n\n        public SimpleDataSource(GUIContent[] displayOptions)\n        {\n            m_DisplayedOptions = displayOptions;\n        }\n\n        public SimpleDataSource(string[] displayOptions)\n        {\n            m_DisplayedOptions = displayOptions.Select(a => new GUIContent(a)).ToArray();\n        }\n\n        protected override AdvancedDropdownItem FetchData()\n        {\n            selectedIDs.Clear();\n            var rootGroup = new AdvancedDropdownItem(\"\");\n\n            for (int i = 0; i < m_DisplayedOptions.Length; i++)\n            {\n                var element = new AdvancedDropdownItem(m_DisplayedOptions[i].text)\n                {\n                    icon = (Texture2D)m_DisplayedOptions[i].image\n                };\n                element.elementIndex = i;\n                rootGroup.AddChild(element);\n                if (i == m_SelectedIndex)\n                {\n                    selectedIDs.Add(element.id);\n                    if (m_State != null)\n                        m_State.SetSelectedIndex(rootGroup, i);\n                }\n            }\n            return rootGroup;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AdvancedDropdown/EditorGUI/AdvancedDropdown.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    public abstract class AdvancedDropdown\n    {\n        protected Vector2 minimumSize { get; set; }\n        internal Vector2 maximumSize { get; set; }\n\n        internal AdvancedDropdownWindow m_WindowInstance;\n        internal AdvancedDropdownState m_State;\n        internal AdvancedDropdownDataSource m_DataSource;\n        internal AdvancedDropdownGUI m_Gui;\n\n        public AdvancedDropdown(AdvancedDropdownState state)\n        {\n            m_State = state;\n        }\n\n        public void Show(Rect rect)\n        {\n            if (m_WindowInstance != null)\n            {\n                m_WindowInstance.Close();\n                m_WindowInstance = null;\n            }\n\n            if (m_DataSource == null)\n            {\n                m_DataSource = new CallbackDataSource(BuildRoot);\n            }\n\n            if (m_Gui == null)\n            {\n                m_Gui = new AdvancedDropdownGUI(m_DataSource);\n            }\n\n            m_WindowInstance = ScriptableObject.CreateInstance<AdvancedDropdownWindow>();\n            if (minimumSize != Vector2.zero)\n                m_WindowInstance.minSize = minimumSize;\n            if (maximumSize!= Vector2.zero)\n                m_WindowInstance.maxSize = maximumSize;\n            m_WindowInstance.state = m_State;\n            m_WindowInstance.dataSource = m_DataSource;\n            m_WindowInstance.gui = m_Gui;\n            m_WindowInstance.windowClosed += (w) => ItemSelected(w.GetSelectedItem());\n            m_WindowInstance.Init(rect);\n        }\n\n        internal void SetFilter(string searchString)\n        {\n            m_WindowInstance.searchString = searchString;\n        }\n\n        protected abstract AdvancedDropdownItem BuildRoot();\n\n        protected virtual void ItemSelected(AdvancedDropdownItem item)\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AdvancedDropdown/EditorGUI/EditorGUIAdvancedDropdown.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal static partial class StatelessAdvancedDropdown\n    {\n        public static int SearchablePopup(Rect rect, int selectedIndex, string[] displayedOptions)\n        {\n            return DoSearchablePopup(rect, selectedIndex, displayedOptions, EditorStyles.popup);\n        }\n\n        public static Enum EnumFlagsField(Rect rect, Enum options)\n        {\n            return DoEnumMaskPopup(rect, options, EditorStyles.popup);\n        }\n\n        public static int MaskField(Rect rect, int mask, string[] displayedOptions)\n        {\n            return DoMaskField(rect, mask, displayedOptions, EditorStyles.popup);\n        }\n\n        public static Enum EnumPopup(Rect rect, Enum selected, params GUILayoutOption[] options)\n        {\n            return DoEnumPopup(rect, selected, EditorStyles.popup, options);\n        }\n\n        public static int Popup(Rect rect, int selectedIndex, string[] displayedOptions)\n        {\n            return Popup(rect, selectedIndex, EditorGUIUtility.TempContent(displayedOptions));\n        }\n\n        public static int Popup(Rect rect, int selectedIndex, GUIContent[] displayedOptions)\n        {\n            return DoPopup(rect, selectedIndex, displayedOptions);\n        }\n\n        public static int IntPopup(Rect rect, int selectedValue, string[] displayedOptions, int[] optionValues)\n        {\n            return DoIntPopup(rect, selectedValue, displayedOptions, optionValues);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/AdvancedDropdown/EditorGUI/StatelessAdvancedDropdown.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal static partial class StatelessAdvancedDropdown\n    {\n        private static AdvancedDropdownWindow s_Instance;\n        private static EditorWindow s_ParentWindow;\n        private static bool m_WindowClosed;\n        private static bool m_ShouldReturnValue;\n        private static int m_Result;\n        private static int s_CurrentControl;\n        private static MultiselectDataSource s_DataSource;\n\n        private static void ResetAndCreateWindow()\n        {\n            if (s_Instance != null)\n            {\n                s_Instance.Close();\n                s_Instance = null;\n            }\n            s_ParentWindow = EditorWindow.focusedWindow;\n            s_Instance = ScriptableObject.CreateInstance<AdvancedDropdownWindow>();\n            m_WindowClosed = false;\n        }\n\n        private static void InitSearchableWindow(Rect rect, string label, int selectedIndex, string[] displayedOptions)\n        {\n            var dataSource = new MultiLevelDataSource();\n\n            dataSource.displayedOptions = displayedOptions;\n            dataSource.selectedIndex = selectedIndex;\n            dataSource.label = label;\n\n            s_Instance.dataSource = dataSource;\n\n            s_Instance.windowClosed += (w) =>\n            {\n                if (s_ParentWindow != null)\n                    s_ParentWindow.Repaint();\n            };\n\n            s_Instance.Init(rect);\n        }\n\n        private static void InitPopupWindow(Rect rect, int selectedIndex, GUIContent[] displayedOptions)\n        {\n            var dataSource = new SimpleDataSource();\n\n            dataSource.displayedOptions = displayedOptions;\n            dataSource.selectedIndex = selectedIndex;\n\n            s_Instance.dataSource = dataSource;\n            s_Instance.searchable = false;\n            s_Instance.showHeader = false;\n\n            s_Instance.selectionChanged += (w) =>\n            {\n                if (s_ParentWindow != null)\n                    s_ParentWindow.Repaint();\n            };\n\n            s_Instance.Init(rect);\n        }\n\n        private static void InitMultiselectPopupWindow(Rect rect, MultiselectDataSource dataSource)\n        {\n            s_DataSource = dataSource;\n            s_Instance.dataSource = dataSource;\n            s_Instance.showHeader = false;\n            s_Instance.searchable = false;\n            s_Instance.closeOnSelection = false;\n            s_Instance.selectionChanged += (w) =>\n            {\n                if (s_ParentWindow != null)\n                    s_ParentWindow.Repaint();\n            };\n\n            s_Instance.Init(rect);\n        }\n\n        internal static int DoSearchablePopup(Rect rect, int selectedIndex, string[] displayedOptions, GUIStyle style)\n        {\n            string contentLabel = \"\";\n            if (selectedIndex >= 0)\n            {\n                contentLabel = displayedOptions[selectedIndex];\n            }\n\n            var content = new GUIContent(contentLabel);\n\n            int id =  EditorGUIUtility.GetControlID(\"AdvancedDropdown\".GetHashCode(), FocusType.Keyboard, rect);\n            if (EditorGUI.DropdownButton(id, rect, content, style))\n            {\n                s_CurrentControl = id;\n                ResetAndCreateWindow();\n                InitSearchableWindow(rect, content.text, selectedIndex, displayedOptions);\n\n                s_Instance.windowClosed += w =>\n                {\n                    m_Result =  w.GetSelectedItem().elementIndex;\n                    m_WindowClosed = true;\n                };\n            }\n            if (m_WindowClosed && s_CurrentControl == id)\n            {\n                s_CurrentControl = 0;\n                m_WindowClosed = false;\n                return m_Result;\n            }\n\n            return selectedIndex;\n        }\n\n        internal static int DoLazySearchablePopup(Rect rect, string selectedOption, int selectedIndex, Func<Tuple<int, string[]>> displayedOptionsFunc, GUIStyle style)\n        {\n            var content = new GUIContent(selectedOption);\n\n            int id = EditorGUIUtility.GetControlID(\"AdvancedDropdown\".GetHashCode(), FocusType.Keyboard, rect);\n            if (EditorGUI.DropdownButton(id, rect, content, style))\n            {\n                s_CurrentControl = id;\n                ResetAndCreateWindow();\n\n                var displayData = displayedOptionsFunc.Invoke();\n                InitSearchableWindow(rect, content.text, displayData.Item1, displayData.Item2);\n\n                s_Instance.windowClosed += w =>\n                {\n                    m_Result = w.GetSelectedItem().elementIndex;\n                    m_WindowClosed = true;\n                };\n            }\n            if (m_WindowClosed && s_CurrentControl == id)\n            {\n                s_CurrentControl = 0;\n                m_WindowClosed = false;\n                return m_Result;\n            }\n\n            return selectedIndex;\n        }\n\n        public static int DoPopup(Rect rect, int selectedIndex, GUIContent[] displayedOptions)\n        {\n            GUIContent content = GUIContent.none;\n            if (selectedIndex >= 0 && selectedIndex < displayedOptions.Length)\n                content = displayedOptions[selectedIndex];\n\n            int id = EditorGUIUtility.GetControlID(\"AdvancedDropdown\".GetHashCode(), FocusType.Keyboard, rect);\n            if (EditorGUI.DropdownButton(id, rect, content, EditorStyles.popup))\n            {\n                s_CurrentControl = id;\n                ResetAndCreateWindow();\n                InitPopupWindow(rect, selectedIndex, displayedOptions);\n\n                s_Instance.windowClosed += w =>\n                {\n                    m_Result = w.GetSelectedItem().elementIndex;\n                    m_WindowClosed = true;\n                };\n                GUIUtility.ExitGUI();\n            }\n            if (m_WindowClosed && s_CurrentControl == id)\n            {\n                s_CurrentControl = 0;\n                m_WindowClosed = false;\n                return m_Result;\n            }\n\n            return selectedIndex;\n        }\n\n        public static Enum DoEnumMaskPopup(Rect rect, Enum options, GUIStyle style)\n        {\n            var enumData = EnumDataUtility.GetCachedEnumData(options.GetType());\n            var optionValue = EnumDataUtility.EnumFlagsToInt(enumData, options);\n            MaskFieldGUI.GetMenuOptions(optionValue, enumData.displayNames, enumData.flagValues, out var buttonText, out var buttonTextMixed, out _, out _, out _);\n\n            var id = EditorGUIUtility.GetControlID(\"AdvancedDropdown\".GetHashCode(), FocusType.Keyboard, rect);\n\n            var buttonContent = MaskFieldGUI.DoMixedLabel(buttonText, buttonTextMixed, rect, EditorStyles.popup);\n            if (EditorGUI.DropdownButton(id, rect, buttonContent, EditorStyles.popup))\n            {\n                s_CurrentControl = id;\n                ResetAndCreateWindow();\n                var dataSource = new MultiselectDataSource(options);\n                InitMultiselectPopupWindow(rect, dataSource);\n                s_Instance.selectionChanged += dataSource.UpdateSelectedId;\n                s_Instance.selectionChanged += i =>\n                {\n                    m_ShouldReturnValue = true;\n                };\n                s_Instance.windowClosed += w =>\n                {\n                    m_WindowClosed = true;\n                };\n            }\n\n            if (m_ShouldReturnValue && s_CurrentControl == id)\n            {\n                m_ShouldReturnValue = false;\n                return s_DataSource.enumFlags;\n            }\n            if (m_WindowClosed && s_CurrentControl == id)\n            {\n                s_CurrentControl = 0;\n                m_WindowClosed = false;\n                var result = s_DataSource.enumFlags;\n                s_DataSource = null;\n                return result;\n            }\n            return options;\n        }\n\n        private static Enum DoEnumPopup(Rect rect, Enum selected, GUIStyle style, params GUILayoutOption[] options)\n        {\n            var enumType = selected.GetType();\n            var enumData = EnumDataUtility.GetCachedEnumData(enumType);\n            var i = Array.IndexOf(enumData.values, selected);\n            using (new LocalizationGroup(enumType))\n            {\n                i = DoPopup(rect, i, EditorGUIUtility.TrTempContent(enumData.displayNames, enumData.tooltip));\n            }\n            return (i < 0 || i >= enumData.flagValues.Length) ? selected : enumData.values[i];\n        }\n\n        private static int DoIntPopup(Rect rect, int selectedValue, string[] displayedOptions, int[] optionValues)\n        {\n            var idx = Array.IndexOf(optionValues, selectedValue);\n            var returnedValue = DoPopup(rect, idx, EditorGUIUtility.TempContent(displayedOptions));\n            return returnedValue >= 0 ? optionValues[returnedValue] : returnedValue;\n        }\n\n        static int DoMaskField(Rect rect, int mask, string[] displayedOptions, GUIStyle popup)\n        {\n            var flagValues = new int[displayedOptions.Length];\n            for (int i = 0; i < flagValues.Length; ++i)\n                flagValues[i] = (1 << i);\n\n            MaskFieldGUI.GetMenuOptions(mask, displayedOptions, flagValues, out var buttonText, out var buttonTextMixed, out _, out _, out _);\n\n            var id = EditorGUIUtility.GetControlID(\"AdvancedDropdown\".GetHashCode(), FocusType.Keyboard, rect);\n\n            var buttonContent = MaskFieldGUI.DoMixedLabel(buttonText, buttonTextMixed, rect, EditorStyles.popup);\n            if (EditorGUI.DropdownButton(id, rect, buttonContent, EditorStyles.popup))\n            {\n                s_CurrentControl = id;\n                ResetAndCreateWindow();\n                var dataSource = new MultiselectDataSource(mask, displayedOptions, flagValues);\n                InitMultiselectPopupWindow(rect, dataSource);\n                s_Instance.selectionChanged += dataSource.UpdateSelectedId;\n                s_Instance.selectionChanged += i =>\n                {\n                    m_ShouldReturnValue = true;\n                };\n                s_Instance.windowClosed += w =>\n                {\n                    m_WindowClosed = true;\n                };\n            }\n\n            if (m_ShouldReturnValue && s_CurrentControl == id)\n            {\n                m_ShouldReturnValue = false;\n                return s_DataSource.mask;\n            }\n            if (m_WindowClosed && s_CurrentControl == id)\n            {\n                s_CurrentControl = 0;\n                m_WindowClosed = false;\n                var result = s_DataSource.mask;\n                s_DataSource = null;\n                return result;\n            }\n            return mask;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/CustomEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing scm = System.ComponentModel;\nusing uei = UnityEngine.Internal;\nusing RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute;\nusing UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute;\n\nusing System;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Collections;\nusing System.Linq;\n\nnamespace UnityEditor\n{\n    public class CustomEditor : System.Attribute\n    {\n        public CustomEditor(System.Type inspectedType)\n        {\n            if (inspectedType == null)\n                Debug.LogError(\"Failed to load CustomEditor inspected type\");\n            m_InspectedType = inspectedType;\n            m_EditorForChildClasses = false;\n        }\n\n        public CustomEditor(System.Type inspectedType, bool editorForChildClasses)\n        {\n            if (inspectedType == null)\n                Debug.LogError(\"Failed to load CustomEditor inspected type\");\n            m_InspectedType = inspectedType;\n            m_EditorForChildClasses = editorForChildClasses;\n        }\n\n        internal Type m_InspectedType;\n        internal bool m_EditorForChildClasses;\n\n        public bool isFallback { get; set; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/GUI/TypeSelectionList.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing System.Collections.Generic;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    class TypeSelectionList\n    {\n        private List<TypeSelection> m_TypeSelections;\n        public List<TypeSelection> typeSelections { get { return m_TypeSelections; } }\n\n        public TypeSelectionList(Object[] objects)\n        {\n            // Create dictionary of lists of objects indexed by their type.\n            var types = new Dictionary<string, List<Object>>();\n            foreach (Object o in objects)\n            {\n                var typeName = ObjectNames.GetTypeName(o) + \"{0}\";\n\n                if (EditorUtility.IsPersistent(o))\n                {\n                    if (o is GameObject)\n                        typeName = \"Prefab{0}\";\n\n                    var importerType = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(o))?.GetType();\n                    if (importerType is not null && importerType != typeof(AssetImporter))\n                        typeName = $\"{typeName} ({importerType.Name})\";\n                }\n\n                if (!types.ContainsKey(typeName))\n                    types[typeName] = new List<Object>();\n                types[typeName].Add(o);\n            }\n\n            // Create and store a TypeSelection per type.\n            m_TypeSelections = new List<TypeSelection>();\n            foreach (var kvp in types)\n                m_TypeSelections.Add(new TypeSelection(kvp.Key, kvp.Value.ToArray()));\n\n            // Sort the TypeSelections\n            m_TypeSelections.Sort();\n        }\n    }\n\n    class TypeSelection : IComparable\n    {\n        public GUIContent label;\n        public Object[] objects;\n\n        public TypeSelection(string typeName, Object[] objects)\n        {\n            System.Diagnostics.Debug.Assert(objects != null && objects.Length >= 1);\n            this.objects = objects;\n\n            label = new GUIContent(\n                $\"{objects.Length} \" +\n                $\"{ObjectNames.NicifyVariableName(string.Format(typeName, objects.Length > 1 ? \"s\" : \"\"))}\");\n\n            if (objects[0] is GameObject)\n                label.image = EditorUtility.IsPersistent(objects[0]) ? PrefabUtility.GameObjectStyles.prefabIcon : PrefabUtility.GameObjectStyles.gameObjectIcon;\n            else\n                label.image = AssetPreview.GetMiniTypeThumbnail(objects[0]);\n        }\n\n        public int CompareTo(object o)\n        {\n            TypeSelection other = (TypeSelection)o;\n\n            // Sort by amount of objects\n            if (other.objects.Length != objects.Length)\n                return other.objects.Length.CompareTo(objects.Length);\n\n            // Sort alphabetically\n            return label.text.CompareTo(other.label.text);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/GenericInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.Audio.UIElements;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class GenericInspector : Editor\n    {\n        private enum OptimizedBlockState\n        {\n            CheckOptimizedBlock,\n            HasOptimizedBlock,\n            NoOptimizedBlock\n        }\n\n        private float m_LastHeight;\n        private Rect m_LastVisibleRect;\n        private OptimizedBlockState m_OptimizedBlockState = OptimizedBlockState.CheckOptimizedBlock;\n\n        static class Styles\n        {\n            public static string missingScriptMessage = L10n.Tr(\"The associated script can not be loaded: {}\\n\\nThis could be because the script has a compile error or because the script was deleted.\\nFix any compile errors if present or assign a valid script.\");\n            public static string missingScriptMessageForPrefabInstance = L10n.Tr(\"The associated script can not be loaded: {}\\n\\nYou must resolve missing scripts on prefabs on the prefab asset itself through the prefab view. Open the source prefab asset for this prefab instance to continue.\");\n            public static string missingSerializeReferenceInstanceMessage = L10n.Tr(\"This object contains SerializeReference types which are missing.\\nFor more information see SerializationUtility.HasManagedReferencesWithMissingTypes.\");\n        }\n\n        internal static string GetMissingSerializeRefererenceMessageContainer()\n        {\n            return Styles.missingSerializeReferenceInstanceMessage;\n        }\n\n        internal override bool GetOptimizedGUIBlock(bool isDirty, bool isVisible, out float height)\n        {\n            height = -1;\n\n            // Don't use optimizedGUI for audio filters\n            var behaviour = target as MonoBehaviour;\n            if (behaviour != null && AudioUtil.HasAudioCallback(behaviour) && AudioUtil.GetCustomFilterChannelCount(behaviour) > 0)\n                return false;\n\n            if (ObjectIsMonoBehaviourOrScriptableObjectWithoutScript(target))\n                return false;\n\n            var scriptableObject = target as ScriptableObject;\n            if ((behaviour != null || scriptableObject != null) && SerializationUtility.HasManagedReferencesWithMissingTypes(target))\n                return false;\n\n            if (isDirty)\n                ResetOptimizedBlock();\n\n            if (!isVisible)\n            {\n                height = 0;\n                return true;\n            }\n\n            // Return cached result if any.\n            if (m_OptimizedBlockState != OptimizedBlockState.CheckOptimizedBlock)\n            {\n                if (m_OptimizedBlockState == OptimizedBlockState.NoOptimizedBlock)\n                    return false;\n                height = m_LastHeight;\n                return true;\n            }\n\n            // Update serialized object representation\n            if (m_SerializedObject == null)\n            {\n                m_SerializedObject = new SerializedObject(targets, m_Context)\n                {\n                    inspectorMode = inspectorMode,\n                    inspectorDataMode = dataMode\n                };\n            }\n            else\n            {\n                m_SerializedObject.Update();\n                m_SerializedObject.inspectorMode = inspectorMode;\n                if (m_SerializedObject.inspectorDataMode != dataMode)\n                    m_SerializedObject.inspectorDataMode = dataMode;\n            }\n\n            height = 0;\n            SerializedProperty property = m_SerializedObject.GetIterator();\n            bool childrenAreExpanded = true;\n            while (property.NextVisible(childrenAreExpanded))\n            {\n                var handler = ScriptAttributeUtility.GetHandler(property);\n                var hasPropertyDrawer = handler.propertyDrawer != null;\n                var propertyHeight = handler.GetHeight(property, null, hasPropertyDrawer || PropertyHandler.UseReorderabelListControl(property));\n                if (propertyHeight > 0)\n                    height += propertyHeight + EditorGUI.kControlVerticalSpacing;\n                childrenAreExpanded = !hasPropertyDrawer && property.isExpanded && EditorGUI.HasVisibleChildFields(property);\n            }\n\n            m_LastHeight = height;\n            m_OptimizedBlockState = OptimizedBlockState.HasOptimizedBlock;\n\n            return true;\n        }\n\n        internal override bool OnOptimizedInspectorGUI(Rect contentRect)\n        {\n            m_SerializedObject.UpdateIfRequiredOrScript();\n\n            bool childrenAreExpanded = true;\n            bool wasEnabled = GUI.enabled;\n            var visibleRect = GUIClip.visibleRect;\n            var contentOffset = contentRect.y;\n\n            // In some specific cases (e.g. when the inspector field has a dropdown behavior - case 1335344) we need to\n            // apply the padding values so it behaves properly. By checking that xMin is zero when we do the assignments,\n            // we avoid applying the padding more than once (because this is called more than once in some cases and\n            // can lead to wrong indentation - case 1114055).\n            if (contentRect.xMin == 0)\n            {\n                contentRect.xMin = EditorStyles.kInspectorPaddingLeft;\n                contentRect.xMax -= EditorStyles.kInspectorPaddingRight;\n            }\n\n            if (Event.current.type != EventType.Repaint)\n                visibleRect = m_LastVisibleRect;\n\n            // Release keyboard focus before scrolling so that the virtual scrolling focus wrong control.\n            if (Event.current.type == EventType.ScrollWheel)\n                GUIUtility.keyboardControl = 0;\n\n            var behaviour = target as MonoBehaviour;\n            var property = m_SerializedObject.GetIterator();\n            bool isInspectorModeNormal = inspectorMode == InspectorMode.Normal;\n            bool isInPrefabInstance = PrefabUtility.GetPrefabInstanceHandle(behaviour) != null;\n            bool isMultiSelection = m_SerializedObject.targetObjectsCount > 1;\n\n            using (new LocalizationGroup(behaviour))\n            {\n                while (property.NextVisible(childrenAreExpanded))\n                {\n                    if (GUI.isInsideList && property.depth <= EditorGUI.GetInsideListDepth())\n                        EditorGUI.EndIsInsideList();\n\n                    if (property.isArray)\n                        EditorGUI.BeginIsInsideList(property.depth);\n\n                    var handler = ScriptAttributeUtility.GetHandler(property);\n                    var hasPropertyDrawer = handler.propertyDrawer != null;\n                    childrenAreExpanded = !hasPropertyDrawer && property.isExpanded && EditorGUI.HasVisibleChildFields(property);\n                    contentRect.height = handler.GetHeight(property, null, hasPropertyDrawer || PropertyHandler.UseReorderabelListControl(property));\n\n                    if (contentRect.Overlaps(visibleRect))\n                    {\n                        EditorGUI.indentLevel = property.depth;\n                        using (new EditorGUI.DisabledScope((isInspectorModeNormal || isInPrefabInstance || isMultiSelection) && string.Equals(\"m_Script\", property.propertyPath, System.StringComparison.Ordinal)))\n                            childrenAreExpanded &= handler.OnGUI(contentRect, property, GetPropertyLabel(property), PropertyHandler.UseReorderabelListControl(property), visibleRect);\n                    }\n\n                    if (contentRect.height > 0)\n                        contentRect.y += contentRect.height + EditorGUI.kControlVerticalSpacing;\n                }\n            }\n\n            // Fix new height\n            if (Event.current.type == EventType.Repaint)\n            {\n                m_LastVisibleRect = visibleRect;\n                var newHeight = contentRect.y - contentOffset;\n                if (newHeight != m_LastHeight)\n                {\n                    m_LastHeight = contentRect.y - contentOffset;\n                    Repaint();\n                }\n            }\n\n            GUI.enabled = wasEnabled;\n            return m_SerializedObject.ApplyModifiedProperties();\n        }\n\n        GUIContent GetPropertyLabel(SerializedProperty property)\n        {\n            var isInspectorModeNormal = inspectorMode == InspectorMode.Normal;\n            if (isInspectorModeNormal)\n                return null;\n\n            return GUIContent.Temp(property.displayName, $\"{property.tooltip}\\n{property.propertyPath} ({property.propertyType})\".Trim());\n        }\n\n        internal static bool IsAnyMonoBehaviourTargetPartOfPrefabInstance(Editor editor)\n        {\n            if ((editor.target is MonoBehaviour) == false)\n                return false;\n\n            foreach (var t in editor.targets)\n            {\n                var instanceID = t.GetInstanceID();\n                if (PrefabUtility.IsInstanceIDPartOfNonAssetPrefabInstance(instanceID))\n                    return true;\n            }\n\n            return false;\n        }\n\n        public bool MissingMonoBehaviourGUI()\n        {\n            serializedObject.Update();\n            var scriptProperty = serializedObject.FindProperty(\"m_Script\");\n            if (scriptProperty == null)\n                return false;\n\n            var originalEnabledState = GUI.enabled;\n            GUI.enabled = !IsAnyMonoBehaviourTargetPartOfPrefabInstance(this);\n\n            EditorGUILayout.PropertyField(scriptProperty); // We don't support changing script as an override on Prefab Instances (case 1255454)\n\n            if (!CheckIfScriptLoaded(scriptProperty))\n            {\n                GUI.enabled = true;\n                var originalClassIdentifier = serializedObject.FindProperty(\"m_EditorClassIdentifier\");\n                ShowScriptNotLoadedWarning(IsAnyMonoBehaviourTargetPartOfPrefabInstance(this), originalClassIdentifier);\n            }\n\n            GUI.enabled = originalEnabledState;\n\n            if (serializedObject.ApplyModifiedProperties())\n                EditorUtility.ForceRebuildInspectors();\n\n            return true;\n        }\n\n        internal static bool MissingSerializeReference(Object unityTarget)\n        {\n            var monoBehaviour = unityTarget as MonoBehaviour;\n            var scriptableObject = unityTarget as ScriptableObject;\n\n            return (monoBehaviour != null || scriptableObject != null) && SerializationUtility.HasManagedReferencesWithMissingTypes(unityTarget);\n        }\n\n        internal static bool ShowMissingSerializeReferenceWarningBoxIfRequired(Object unityTarget)\n        {\n            if (MissingSerializeReference(unityTarget))\n            {\n                EditorGUILayout.HelpBox(Styles.missingSerializeReferenceInstanceMessage, MessageType.Warning, true);\n                return true;\n            }\n            else\n            {\n                return false;\n            }\n        }\n\n        public bool ShowMissingSerializeReferenceWarningBoxIfRequired()\n        {\n            return ShowMissingSerializeReferenceWarningBoxIfRequired(target);\n        }\n\n        private static bool CheckIfScriptLoaded(SerializedProperty scriptProperty)\n        {\n            MonoScript targetScript = scriptProperty?.objectReferenceValue as MonoScript;\n            return targetScript != null && targetScript.GetScriptTypeWasJustCreatedFromComponentMenu();\n        }\n\n        private static void ShowScriptNotLoadedWarning(bool missingScriptIsOnPrefabInstance, SerializedProperty className)\n        {\n            var message = missingScriptIsOnPrefabInstance ? Styles.missingScriptMessageForPrefabInstance : Styles.missingScriptMessage;\n            var missingClassName = className == null || string.IsNullOrEmpty(className.stringValue);\n            message = message.Replace(\"{}\", missingClassName ? \"<unknown>\" : className.stringValue);\n            EditorGUILayout.HelpBox(message, MessageType.Warning, true);\n        }\n\n        internal static void ShowScriptNotLoadedWarning(SerializedProperty scriptProperty, bool isPartOfPrefabInstance, SerializedProperty className)\n        {\n            bool scriptLoaded = CheckIfScriptLoaded(scriptProperty);\n            if (!scriptLoaded)\n            {\n                ShowScriptNotLoadedWarning(isPartOfPrefabInstance, className);\n            }\n        }\n\n        private void ResetOptimizedBlock(OptimizedBlockState resetState = OptimizedBlockState.CheckOptimizedBlock)\n        {\n            m_LastHeight = -1;\n            m_OptimizedBlockState = resetState;\n        }\n\n        internal void OnDisableINTERNAL()\n        {\n            ResetOptimizedBlock();\n            CleanupPropertyEditor();\n            propertyHandlerCache.Dispose();\n\n            if (m_DummyPreview != null && m_DummyPreview is not Editor)\n                m_DummyPreview.Cleanup();\n        }\n\n        internal static bool ObjectIsMonoBehaviourOrScriptableObjectWithoutScript(Object obj)\n        {\n            if (obj)\n            {\n                // When script is present the type will be a derived class instead\n                return obj.GetType() == typeof(MonoBehaviour) || obj.GetType() == typeof(ScriptableObject);\n            }\n            return obj is MonoBehaviour || obj is ScriptableObject;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (ObjectIsMonoBehaviourOrScriptableObjectWithoutScript(target))\n            {\n                if (MissingMonoBehaviourGUI())\n                    return;\n            }\n            else\n            {\n                ShowMissingSerializeReferenceWarningBoxIfRequired();\n            }\n\n            base.OnInspectorGUI();\n        }\n\n        public override VisualElement CreateInspectorGUI()\n        {\n            if (serializedObject == null)\n                return null;\n\n            var root = new VisualElement();\n\n            if (MissingSerializeReference(target))\n            {\n                root.Add(new HelpBox(GetMissingSerializeRefererenceMessageContainer(), HelpBoxMessageType.Warning));\n            }\n\n            UIElements.InspectorElement.FillDefaultInspector(root, serializedObject, this);\n\n            if (target is MonoBehaviour behaviour && behaviour != null && AudioUtil.HasAudioCallback(behaviour))\n            {\n                root.Add(new OnAudioFilterReadLevelMeter(behaviour));\n            }\n\n            return root;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/InspectorPreviewWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.UIElements;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    internal class InspectorPreviewWindow : VisualElement\n    {\n        internal class Styles\n        {\n            public static readonly string ussClassName = \"unity-preview-pane\";\n            public static readonly string uxmlPath = \"UXML/InspectorWindow/InspectorPreview.uxml\";\n            public static readonly string ussPath = \"StyleSheets/InspectorWindow/InspectorPreview.uss\";\n            public static readonly string controlsUssPath = \"StyleSheets/InspectorWindow/InspectorPreviewControls.uss\";\n            public static readonly string titleName = \"title\";\n            public static readonly string previewName = \"inspector-preview\";\n            public static readonly string contentContainerName = \"content-container\";\n            public static readonly string toolbarName = \"toolbar\";\n            public static readonly string elipsisMenuName = \"ellipsis-menu\";\n            public static readonly string headerName = \"header\";\n            public static readonly string dropdownButton = \"unity-dropdown-button\";\n            public static readonly string basePopupFieldArrow = \"unity-base-popup-field__arrow\";\n            public static readonly string previewPopupFieldArrow = \"unity-dropdown-arrow\";\n        }\n\n        VisualElement m_Container;\n        VisualElement m_Toolbar;\n        ToolbarMenu m_EllipsisMenu;\n\n        public VisualElement GetButtonPane() { return m_Toolbar; }\n        public VisualElement GetPreviewPane() { return m_Container; }\n\n        public InspectorPreviewWindow()\n        {\n            AddToClassList(Styles.ussClassName);\n\n            var visualAsset = EditorGUIUtility.Load(Styles.uxmlPath) as VisualTreeAsset;\n            visualAsset.CloneTree(this);\n\n            AddStyleSheetPath(Styles.ussPath);\n            AddStyleSheetPath(Styles.controlsUssPath);\n\n            name = Styles.previewName;\n            m_Container = this.Q(Styles.contentContainerName);\n            m_Toolbar = this.Q(Styles.toolbarName);\n            focusable = true;\n\n            m_EllipsisMenu = this.Q<ToolbarMenu>(Styles.elipsisMenuName);\n            m_EllipsisMenu.style.display = DisplayStyle.Flex;\n        }\n\n        public void AppendActionToEllipsisMenu(string actionName,\n            Action<DropdownMenuAction> action,\n            Func<DropdownMenuAction, DropdownMenuAction.Status> actionStatusCallback,\n            object userData = null)\n        {\n            m_EllipsisMenu.menu.AppendAction(actionName, action, actionStatusCallback, userData);\n        }\n\n        public void ClearEllipsisMenu()\n        {\n            m_EllipsisMenu.menu.ClearItems();\n        }\n\n        public void AddButton(string propertyName, Texture2D image, Action clickEvent)\n        {\n            if (m_Toolbar.Q(propertyName) != null)\n                return;\n\n            var button = new Button(clickEvent);\n            button.name = propertyName;\n            button.style.backgroundImage = image;\n            m_Toolbar.Add(button);\n        }\n\n        public void UpdateButtonIcon(string propertyName, Texture2D image)\n        {\n            var button = m_Toolbar.Q(propertyName);\n\n            if (button == null)\n                return;\n\n            button.style.backgroundImage = image;\n        }\n\n        public void AddDropdownWithIcon(string propertyName, Texture2D image, Action clickEvent)\n        {\n            if (m_Toolbar.Q(propertyName) != null)\n                return;\n\n            var dropdown = new Button(clickEvent);\n            dropdown.name = propertyName;\n            dropdown.AddToClassList(Styles.dropdownButton);\n\n            var icon = new Image();\n            icon.image = image;\n\n            var arrow = new VisualElement();\n            arrow.AddToClassList(Styles.basePopupFieldArrow);\n            arrow.AddToClassList(Styles.previewPopupFieldArrow);\n\n            dropdown.style.flexDirection = FlexDirection.Row;\n            dropdown.Add(icon);\n            dropdown.Add(arrow);\n\n            m_Toolbar.Add(dropdown);\n        }\n\n        public override VisualElement contentContainer => m_Container == null ? this : m_Container;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/InspectorWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Profiling;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing UnityEngine.UIElements;\n\nusing Object = UnityEngine.Object;\n\nusing AssetImporterEditor = UnityEditor.AssetImporters.AssetImporterEditor;\n\nnamespace UnityEditor\n{\n    [EditorWindowTitle(title = \"Inspector\", useTypeNameAsIconName = true)]\n    internal class InspectorWindow : PropertyEditor, IPropertyView, IHasCustomMenu\n    {\n        static readonly List<InspectorWindow> m_AllInspectors = new List<InspectorWindow>();\n        static bool s_AllOptimizedGUIBlocksNeedsRebuild;\n\n        [SerializeField] EditorGUIUtility.EditorLockTrackerWithActiveEditorTracker m_LockTracker = new EditorGUIUtility.EditorLockTrackerWithActiveEditorTracker();\n        [SerializeField] PreviewWindow m_PreviewWindow;\n\n        readonly HashSet<DataMode> m_UserSupportedDataModes = new(4);\n        IMGUIContainer m_TrackerResetter;\n\n\n        public bool isLocked\n        {\n            get\n            {\n                //this makes sure the getter for InspectorWindow.tracker gets called and creates an ActiveEditorTracker if needed\n                m_LockTracker.tracker = tracker;\n                return m_LockTracker.isLocked;\n            }\n            set\n            {\n                //this makes sure the getter for InspectorWindow.tracker gets called and creates an ActiveEditorTracker if needed\n                m_LockTracker.tracker = tracker;\n                m_LockTracker.isLocked = value;\n            }\n        }\n\n        public bool isVisible => m_Parent.actualView == this;\n\n        internal class TestHelper\n        {\n            public static void PopupPreviewWindow(InspectorWindow inspector)\n            {\n                inspector.PopupPreviewWindow();\n            }\n\n            public static void DockPreviewWindow(InspectorWindow inspector)\n            {\n                inspector.DockPreviewWindow();\n            }\n\n            public static PreviewWindow GetPreviewWindow(InspectorWindow inspector)\n            {\n                return inspector.m_PreviewWindow;\n            }\n\n            public static InspectorPreviewWindow GetInspectorPreviewWindow(InspectorWindow inspector)\n            {\n                return inspector.previewWindow;\n            }\n        }\n\n\n        internal void Awake()\n        {\n            AddInspectorWindow(this);\n        }\n\n        protected override void OnDestroy()\n        {\n            if (m_PreviewWindow is { IsFloatingWindow: true })\n                m_PreviewWindow.Close();\n            if (m_Tracker != null && !m_Tracker.Equals(ActiveEditorTracker.sharedTracker))\n            {\n                // Ensure that m_Tracker is null before calling Destroy(), as a callback could be made to redraw the\n                // InspectorWindow, and the native representation of the tracker will already be gone\n                var trackerToDestroy = m_Tracker;\n                m_Tracker = null;\n                trackerToDestroy.Destroy();\n            }\n\n            if (m_TrackerResetter != null)\n            {\n                m_TrackerResetter.Dispose();\n                m_TrackerResetter = null;\n            }\n        }\n\n        protected override void OnEnable()\n        {\n            // Enable MSAA for UIElements inspectors, which is the only supported\n            // antialiasing solution for UIElements.\n            antiAliasing = 4;\n\n            RefreshTitle();\n            AddInspectorWindow(this);\n\n            base.OnEnable();\n\n            RestoreLockStateFromSerializedData();\n\n            if (m_LockTracker == null)\n            {\n                m_LockTracker = new EditorGUIUtility.EditorLockTrackerWithActiveEditorTracker();\n            }\n\n            m_LockTracker.tracker = tracker;\n            m_LockTracker.lockStateChanged.AddListener(LockStateChanged);\n            m_Tracker.dataMode = GetDataModeController_Internal().dataMode;\n\n            EditorApplication.projectWasLoaded += OnProjectWasLoaded;\n            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;\n            Selection.selectionChanged += OnSelectionChanged;\n            AssemblyReloadEvents.afterAssemblyReload += OnAfterAssemblyReload;\n        }\n\n        private void OnAfterAssemblyReload()\n        {\n            // Case 1348788: After reloading the assemblies after a script compilation,\n            // active editors are not rebuilt automatically. If a custom editor changed\n            // the way it handles multi object editing you won't see the effect in the inspector unless\n            // you change the selection. It is a minor issue. But this call makes sure to rebuild the active\n            // editors if necessary.\n            // Note: This is only a problem when adding the attribute CanEditMultipleObjects. When the attribute is not\n            // there, the editor used for multi editing is the generic inspector. If you add the CanEditMultipleObjects attribute,\n            // a refresh is triggered and we check if the editor instance is still valid, which is the case for the generic inspector\n            // so we don't rebuild it. When removing the CanEditMultipleObjects, the refresh sees that the editor was the custom inspector\n            // but its instance is no longer valid, so it rebuilds the inspector.\n            if (EditorsForMultiEditingChanged())\n                tracker.ForceRebuild();\n        }\n\n        void OnPlayModeStateChanged(PlayModeStateChange state)\n        {\n            // Case UUM-64580: unable to interact with the inspector after exiting play mode.\n            // Somehow the inspector is still showing the last selected object, but the tracker does not respond anymore.\n            // Forcing a rebuild of the tracker after exiting play mode ensures that it is put back in a valid state.\n            if (state == PlayModeStateChange.EnteredEditMode)\n                tracker.ForceRebuild();\n        }\n\n        void OnBecameVisible()\n        {\n            SceneView.SetActiveEditorsDirty(true);\n        }\n\n        void OnBecameInvisible()\n        {\n            SceneView.SetActiveEditorsDirty();\n        }\n\n        private void OnProjectWasLoaded()\n        {\n            // EditorApplication.projectWasLoaded, which calls this, fires after OnEnabled\n            // therefore the logic in OnEnabled already tried to de-serialize the locked objects, including those it only had InstanceIDs of\n            // This needs to get fixed here as the InstanceIDs have been reshuffled with the new session and could resolving to random Objects\n            if (m_InstanceIDsLockedBeforeSerialization.Count > 0)\n            {\n                // Game objects will have new instanceIDs in a new Unity session, so take out all objects that where reconstructed from InstanceIDs\n                for (int i = m_InstanceIDsLockedBeforeSerialization.Count - 1; i >= 0; i--)\n                {\n                    for (int j = m_ObjectsLockedBeforeSerialization.Count - 1; j >= 0; j--)\n                    {\n                        if (m_ObjectsLockedBeforeSerialization[j] == null || m_ObjectsLockedBeforeSerialization[j].GetInstanceID() == m_InstanceIDsLockedBeforeSerialization[i])\n                        {\n                            m_ObjectsLockedBeforeSerialization.RemoveAt(j);\n                            break;\n                        }\n                    }\n                }\n                m_InstanceIDsLockedBeforeSerialization.Clear();\n                RestoreLockStateFromSerializedData();\n            }\n        }\n\n        private void OnSelectionChanged()\n        {\n            if (isLocked)\n                return;\n        \n            RebuildContentsContainers();\n            if (Selection.objects.Length == 0 && m_MultiEditLabel != null)\n            {\n                m_MultiEditLabel.RemoveFromHierarchy();\n            }\n\n            UpdateSupportedDataModesList();\n        }\n\n        // Note: supportedModes is cleared before and sorted after this method is called\n        protected override void OnUpdateSupportedDataModes(List<DataMode> supportedModes)\n        {\n            // Not showing data modes in debug\n            if (m_InspectorMode != InspectorMode.Normal)\n                return;\n\n            m_UserSupportedDataModes.Clear();\n            DataModeSupportUtils.GetDataModeSupport(Selection.activeObject, Selection.activeContext, m_UserSupportedDataModes);\n            supportedModes.AddRange(m_UserSupportedDataModes);\n        }\n\n        protected override void OnDisable()\n        {\n            base.OnDisable();\n\n            RemoveInspectorWindow(this);\n            m_LockTracker?.lockStateChanged.RemoveListener(LockStateChanged);\n\n            EditorApplication.projectWasLoaded -= OnProjectWasLoaded;\n            EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;\n            Selection.selectionChanged -= OnSelectionChanged;\n            AssemblyReloadEvents.afterAssemblyReload -= OnAfterAssemblyReload;\n        }\n\n        static internal void RepaintAllInspectors()\n        {\n            foreach (var win in m_AllInspectors)\n                win.Repaint();\n        }\n\n        internal static List<InspectorWindow> GetInspectors()\n        {\n            return m_AllInspectors;\n        }\n\n        [UsedByNativeCode]\n        internal static void RedrawFromNative()\n        {\n            // This method could be called before `OnEnable` is being called on an editor window.\n            // Therefore it is important to make sure your editor window is enabled/active/alive first,\n            // which means it have to be contained in `activeEditorWindows` list.\n            foreach (var editorWindow in activeEditorWindows)\n            {\n                if (editorWindow is PropertyEditor propertyEditor)\n                    propertyEditor.RebuildContentsContainers();\n            }\n        }\n\n        internal static InspectorWindow[] GetAllInspectorWindows()\n        {\n            return m_AllInspectors.ToArray();\n        }\n\n        public override void AddItemsToMenu(GenericMenu menu)\n        {\n            m_LockTracker.AddItemsToMenu(menu);\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Properties...\"), false, () => OpenPropertyEditor(GetInspectedObjects()));\n            menu.AddSeparator(String.Empty);\n            base.AddItemsToMenu(menu);\n        }\n\n        protected override void RefreshTitle()\n        {\n            string iconName = \"UnityEditor.InspectorWindow\";\n            if (m_InspectorMode == InspectorMode.Normal)\n                titleContent = EditorGUIUtility.TrTextContentWithIcon(\"Inspector\", iconName);\n            else\n                titleContent = EditorGUIUtility.TrTextContentWithIcon(\"Debug\", iconName);\n        }\n\n        protected override void UpdateWindowObjectNameTitle()\n        {\n            // The inspector window doesn't not track the object name.\n        }\n\n        protected override void CreateTracker()\n        {\n            if (m_Tracker != null)\n            {\n                // Ensure that inspector mode\n                // This shouldn't be necessary but there are some non-reproducable bugs objects showing up as not able to multi-edit\n                // because this state goes out of sync.\n                m_Tracker.inspectorMode = m_InspectorMode;\n                return;\n            }\n\n            m_Tracker = sharedTrackerInUse ? new ActiveEditorTracker() : ActiveEditorTracker.sharedTracker;\n            m_Tracker.inspectorMode = m_InspectorMode;\n            m_Tracker.RebuildIfNecessary();\n        }\n\n        bool sharedTrackerInUse\n        {\n            get\n            {\n                return m_AllInspectors.Any(i => i.m_Tracker != null && i.m_Tracker.Equals(ActiveEditorTracker.sharedTracker));\n            }\n        }\n\n        protected virtual void ShowButton(Rect r)\n        {\n            m_LockTracker.ShowButton(r, Styles.lockButton);\n        }\n\n        private void LockStateChanged(bool lockState)\n        {\n            if (lockState)\n            {\n                PrepareLockedObjectsForSerialization();\n            }\n            else\n            {\n                ClearSerializedLockedObjects();\n            }\n\n            tracker.RebuildIfNecessary();\n        }\n\n        protected override bool CloseIfEmpty()\n        {\n            return false;\n        }\n\n        protected override void BeginRebuildContentContainers()\n        {\n            FlushAllOptimizedGUIBlocksIfNeeded();\n\n            if (m_TrackerResetter == null)\n            {\n                m_TrackerResetInserted = false;\n                m_TrackerResetter = CreateIMGUIContainer(() => {}, \"activeEditorTrackerResetter\");\n                rootVisualElement.Insert(0, m_TrackerResetter);\n            }\n        }\n\n        protected override bool BeginDrawPreviewAndLabels()\n        {\n            if (m_PreviewWindow && Event.current?.type == EventType.Repaint)\n                m_PreviewWindow.Repaint();\n            return m_PreviewWindow == null;\n        }\n\n        /// <summary>\n        /// Finalize IMGUI based inspectors.\n        /// </summary>\n        protected override void EndDrawPreviewAndLabels(Event evt, Rect rect, Rect dragRect)\n        {\n            if (m_HasPreview || m_PreviewWindow != null)\n            {\n                if (EditorGUILayout.DropdownButton(Styles.menuIcon, FocusType.Passive, Styles.preOptionsButton))\n                {\n                    GenericMenu menu = new GenericMenu();\n                    menu.AddItem(\n                        EditorGUIUtility.TrTextContent(m_PreviewWindow == null\n                            ? \"Convert to Floating Window\"\n                            : \"Dock Preview to Inspector\"), false,\n                        () =>\n                        {\n                            if (m_PreviewWindow == null)\n                            {\n                                PopupPreviewWindow(exitGUI: false);\n                            }\n                            else\n                            {\n                                DockPreviewWindow();\n                            }\n                        });\n                    menu.AddItem(\n                        EditorGUIUtility.TrTextContent(m_PreviewResizer.GetExpanded()\n                            ? \"Minimize in Inspector\"\n                            : \"Restore in Inspector\"), false,\n                        () =>\n                        {\n                            m_PreviewResizer.SetExpanded(position, k_InspectorPreviewMinTotalHeight,\n                                k_MinAreaAbovePreview, kBottomToolbarHeight, dragRect,\n                                !m_PreviewResizer.GetExpanded());\n                        });\n                    menu.ShowAsContext();\n                }\n            }\n\n            // Detach preview on right click in preview title bar\n            if (evt.type == EventType.MouseUp && evt.button == 1 && rect.Contains(evt.mousePosition) && m_PreviewWindow == null)\n                PopupPreviewWindow(exitGUI: true);\n        }\n\n        /// <summary>\n        /// Creates the ellipsis menu for UITK based inspectors.\n        /// </summary>\n        protected override void CreatePreviewEllipsisMenu()\n        {\n            if (previewWindow == null)\n                return;\n\n            var draglineAnchor = m_SplitView.Q(s_draglineAnchor);\n            var previewContainer = m_SplitView.Q(s_PreviewContainer);\n\n            previewWindow.ClearEllipsisMenu();\n            previewWindow.AppendActionToEllipsisMenu(\n                \"Convert to Floating Window\",\n                (e) =>\n                {\n                    if (m_PreviewWindow == null)\n                    {\n                        PopupPreviewWindow();\n\n                        previewContainer.style.display = DisplayStyle.None;\n                        draglineAnchor.style.display = DisplayStyle.None;\n                    }\n                    else\n                    {\n                        DockPreviewWindow();\n\n                        previewContainer.style.display = DisplayStyle.Flex;\n                        draglineAnchor.style.display = DisplayStyle.Flex;\n                    }\n                },\n                a => DropdownMenuAction.Status.Normal);\n\n            previewWindow.AppendActionToEllipsisMenu(\n                \"Minimize in Inspector\",\n                (e) =>\n                {\n                    ExpandCollapsePreview();\n                },\n                a => !showingPreview ? DropdownMenuAction.Status.Checked : DropdownMenuAction.Status.Normal\n            );\n\n            draglineAnchor.RegisterCallback<PointerUpEvent>(OnDraglineChange);\n        }\n\n        void OnDraglineChange(PointerUpEvent evt)\n        {\n            if (m_PreviewWindow != null || evt.button != (int)MouseButton.RightMouse)\n                return;\n\n            PopupPreviewWindow();\n        }\n\n        void PopupPreviewWindow(bool exitGUI = false)\n        {\n            DetachPreview(exitGUI);\n            previewWindow.parent?.Remove(previewWindow);\n        }\n\n        void DockPreviewWindow()\n        {\n            m_PreviewWindow?.Close();\n        }\n\n        private void DetachPreview(bool exitGUI = true)\n        {\n            if (Event.current != null)\n                Event.current.Use();\n            m_PreviewWindow = CreateInstance(typeof(PreviewWindow)) as PreviewWindow;\n            m_PreviewWindow.SetParentInspector(this);\n            m_PreviewWindow.RebuildContentsContainers();\n            m_PreviewWindow.Show();\n            Repaint();\n            UIEventRegistration.MakeCurrentIMGUIContainerDirty();\n            if (exitGUI)\n                GUIUtility.ExitGUI();\n        }\n\n        [UsedByNativeCode]\n        internal static void ShowWindow()\n        {\n            GetWindow(typeof(InspectorWindow));\n        }\n\n        private static void FlushAllOptimizedGUIBlocksIfNeeded()\n        {\n            if (!s_AllOptimizedGUIBlocksNeedsRebuild)\n                return;\n            s_AllOptimizedGUIBlocksNeedsRebuild = false;\n        }\n\n        private void PrepareLockedObjectsForSerialization()\n        {\n            ClearSerializedLockedObjects();\n\n            if (m_Tracker != null && m_Tracker.isLocked)\n            {\n                m_Tracker.GetObjectsLockedByThisTracker(m_ObjectsLockedBeforeSerialization);\n\n                // take out non persistent and track them in a list of instance IDs, because they wouldn't survive serialization as Objects\n                for (int i = m_ObjectsLockedBeforeSerialization.Count - 1; i >= 0; i--)\n                {\n                    if (!EditorUtility.IsPersistent(m_ObjectsLockedBeforeSerialization[i]))\n                    {\n                        if (m_ObjectsLockedBeforeSerialization[i] != null)\n                            m_InstanceIDsLockedBeforeSerialization.Add(m_ObjectsLockedBeforeSerialization[i].GetInstanceID());\n                        m_ObjectsLockedBeforeSerialization.RemoveAt(i);\n                    }\n                }\n            }\n        }\n\n        private void ClearSerializedLockedObjects()\n        {\n            m_ObjectsLockedBeforeSerialization.Clear();\n\n            m_InstanceIDsLockedBeforeSerialization.Clear();\n        }\n\n        internal void GetObjectsLocked(List<Object> objs)\n        {\n            m_Tracker.GetObjectsLockedByThisTracker(objs);\n        }\n\n        internal void SetObjectsLocked(List<Object> objs)\n        {\n            m_LockTracker.isLocked = true;\n            m_Tracker.SetObjectsLockedByThisTracker(objs);\n        }\n\n        private void RestoreLockStateFromSerializedData()\n        {\n            if (m_Tracker == null)\n            {\n                return;\n            }\n\n            // try to retrieve all Objects from their stored instance ids in the list.\n            // this is only used for non persistent objects (scene objects)\n\n            if (m_InstanceIDsLockedBeforeSerialization.Count > 0)\n            {\n                for (int i = 0; i < m_InstanceIDsLockedBeforeSerialization.Count; i++)\n                {\n                    Object instance = EditorUtility.InstanceIDToObject(m_InstanceIDsLockedBeforeSerialization[i]);\n                    //don't add null objects (i.e.\n                    if (instance)\n                    {\n                        m_ObjectsLockedBeforeSerialization.Add(instance);\n                    }\n                }\n            }\n\n            for (int i = m_ObjectsLockedBeforeSerialization.Count - 1; i >= 0; i--)\n            {\n                if (m_ObjectsLockedBeforeSerialization[i] == null)\n                {\n                    m_ObjectsLockedBeforeSerialization.RemoveAt(i);\n                }\n            }\n\n            // set the tracker to the serialized list. if it contains nulls or is empty, the tracker won't lock\n            // this fixes case 775007\n            m_Tracker.SetObjectsLockedByThisTracker(m_ObjectsLockedBeforeSerialization);\n            // since this method likely got called during OnEnable, and rebuilding the tracker could call OnDisable on all Editors,\n            // some of which might not have gotten their enable yet, the rebuilding needs to happen delayed in EditorApplication.update\n            EditorApplication.CallDelayed(tracker.RebuildIfNecessary, 0f);\n        }\n\n        internal static bool AddInspectorWindow(InspectorWindow window)\n        {\n            if (m_AllInspectors.Contains(window))\n            {\n                return false;\n            }\n\n            m_AllInspectors.Add(window);\n            return true;\n        }\n\n        internal static void RemoveInspectorWindow(InspectorWindow window)\n        {\n            m_AllInspectors.Remove(window);\n        }\n\n        internal static void ApplyChanges()\n        {\n            foreach (var inspector in m_AllInspectors)\n            {\n                foreach (var editor in inspector.tracker.activeEditors)\n                {\n                    if(editor.hasUnsavedChanges)\n                        editor.SaveChanges();\n                }\n            }\n        }\n\n        internal static void RefreshInspectors()\n        {\n            foreach (var inspector in m_AllInspectors)\n            {\n                inspector.tracker.ForceRebuild();\n            }\n        }\n\n        internal override Object GetInspectedObject()\n        {\n            if (tracker.hasComponentsWhichCannotBeMultiEdited && !tracker.isLocked)\n                return Selection.activeObject;\n\n            Editor editor = InspectorWindowUtils.GetFirstNonImportInspectorEditor(tracker.activeEditors);\n            if (editor == null)\n                return null;\n            return editor.target;\n        }\n\n        internal Object[] GetInspectedObjects()\n        {\n            if (tracker.hasComponentsWhichCannotBeMultiEdited && !tracker.isLocked)\n                return Selection.objects;\n\n            Editor editor = InspectorWindowUtils.GetFirstNonImportInspectorEditor(tracker.activeEditors);\n            if (editor == null)\n                return null;\n            return editor.targets;\n        }\n\n        private bool EditorsForMultiEditingChanged()\n        {\n            foreach (var editor in tracker.activeEditors)\n            {\n                if (EditorForMultiEditingChanged(editor, editor.target))\n                    return true;\n            }\n\n            return false;\n        }\n\n        private static bool EditorForMultiEditingChanged(Editor editor, Object target)\n        {\n            if (editor.targets.Length <= 1)\n                return false;\n\n            var currentEditorType = editor.GetType();\n            var expectedEditorType = CustomEditorAttributes.FindCustomEditorType(target, true);\n\n            // Going from generic to generic inspector for multi editing is correctly handled.\n            if (editor is GenericInspector && expectedEditorType == null)\n                return false;\n            return currentEditorType != expectedEditorType;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/PreviewWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    internal class PreviewWindow : InspectorWindow\n    {\n        [SerializeField]\n        private InspectorWindow m_ParentInspectorWindow;\n\n        VisualElement m_previewElement;\n\n        VisualElement previewElement => m_previewElement ?? (m_previewElement = rootVisualElement.Q(className: \"unity-inspector-preview\"));\n\n        internal bool IsFloatingWindow => parent is { window.rootView: not null, window.showMode: not ShowMode.MainWindow };\n\n        private readonly string k_PreviewName = \"preview-container\";\n        internal override BindingLogLevel defaultBindingLogLevel => BindingLogLevel.None;\n        public void SetParentInspector(InspectorWindow inspector)\n        {\n            m_ParentInspectorWindow = inspector;\n\n            // Create tracker after parent inspector window has been set (case 829182, 846156)\n            CreateTracker();\n        }\n\n        // It's important to NOT call the base.OnDestroy() here!\n        // The InspectorWindow.OnDestroy() deletes the tracker if we are not using the\n        // shared tracker. This makes sense when we are an InspectorWindow about to die,\n        // but it does not make sense when we are a PreviewWindow sharing this tracker with\n        // a perfectly not dead InspectorWindow. Killing the tracker used by a still-alive\n        // InspectorWindow cause many problems.\n        // case 1119612\n        protected override void OnDestroy() {}\n\n        protected override void OnEnable()\n        {\n            titleContent = EditorGUIUtility.TrTextContent(\"Preview\");\n            minSize = new Vector2(260, 220);\n\n            AddInspectorWindow(this);\n            var tpl = EditorGUIUtility.Load(\"UXML/InspectorWindow/PreviewWindow.uxml\") as VisualTreeAsset;\n            var container = tpl.Instantiate();\n            container.AddToClassList(s_MainContainerClassName);\n            rootVisualElement.hierarchy.Add(container);\n\n            rootVisualElement.AddStyleSheetPath(\"StyleSheets/InspectorWindow/PreviewWindow.uss\");\n            RebuildContentsContainers();\n        }\n\n        protected override void OnDisable()\n        {\n            base.OnDisable();\n            if (m_ParentInspectorWindow != null && GetInspectors().Contains(m_ParentInspectorWindow))\n            {\n                m_ParentInspectorWindow.RebuildContentsContainers();\n            }\n        }\n\n        protected override void CreateTracker()\n        {\n            if (m_ParentInspectorWindow != null)\n                m_Tracker = m_ParentInspectorWindow.tracker;\n            else if (m_Tracker == null)\n                base.CreateTracker();\n        }\n\n        internal override Editor GetLastInteractedEditor()\n        {\n            if (m_ParentInspectorWindow == null)\n                return null;\n\n            return m_ParentInspectorWindow.GetLastInteractedEditor();\n        }\n\n        internal override void RebuildContentsContainers()\n        {\n            Editor.m_AllowMultiObjectAccess = true;\n            var preview = previewElement;\n            preview.Clear();\n            CreatePreviewables();\n\n            previewWindow = new InspectorPreviewWindow();\n            IPreviewable editor = GetEditorThatControlsPreview(tracker.activeEditors);\n            previewWindow = editor?.CreatePreview(previewWindow) as InspectorPreviewWindow;\n\n            if (m_ParentInspectorWindow != null && previewWindow != null)\n            {\n                if (previewWindow.childCount == 0)\n                {\n                    PrepareToolbar(true);\n                    UpdateLabel(previewWindow);\n                    VisualElement previewPane = previewWindow.GetPreviewPane();\n\n                    // IMGUI fallback\n                    if (previewPane?.childCount == 0)\n                    {\n                        previewPane.Add(DrawPreview());\n                    }\n                }\n\n                SetPreviewStyle(previewWindow);\n\n                if (preview.Q(k_PreviewName) == null)\n                    preview.Add(previewWindow);\n            }\n            else\n            {\n                var container = DrawPreview(true);\n                SetPreviewStyle(container);\n\n                if (preview.Q(k_PreviewName) == null)\n                    preview.Add(container);\n            }\n        }\n\n        void SetPreviewStyle(VisualElement element)\n        {\n            element.style.flexGrow = 1f;\n            element.style.flexShrink = 0f;\n            element.style.flexBasis = 0f;\n            element.name = k_PreviewName;\n        }\n\n        IMGUIContainer DrawPreview(bool drawToolbar = false)\n        {\n            return new IMGUIContainer(() =>\n            {\n                IPreviewable editor = GetEditorThatControlsPreview(tracker.activeEditors);\n\n                if (drawToolbar)\n                {\n                    Rect toolbarRect = EditorGUILayout.BeginHorizontal(GUIContent.none, EditorStyles.toolbar,\n                        GUILayout.Height(kBottomToolbarHeight));\n                    {\n                        // Label\n                        string label = string.Empty;\n                        if ((editor != null))\n                        {\n                            label = editor.GetPreviewTitle().text;\n                        }\n\n                        GUILayout.Label(label, Styles.preToolbarLabel);\n\n                        GUILayout.FlexibleSpace();\n\n                        if (editor != null && editor.HasPreviewGUI())\n                            editor.OnPreviewSettings();\n                    }\n                    EditorGUILayout.EndHorizontal();\n                }\n\n                Rect previewPosition = GUILayoutUtility.GetRect(0, 10240, 64, 10240);\n\n                // Draw background\n                if (Event.current.type == EventType.Repaint)\n                    Styles.preBackground.Draw(previewPosition, false, false, false, false);\n\n                // Draw preview\n                if (editor != null && editor.HasPreviewGUI())\n                    editor.DrawPreview(previewPosition);\n            });\n        }\n\n        public override void AddItemsToMenu(GenericMenu menu)\n        {\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Dock Preview to Inspector\"), false, Close);\n        }\n\n        protected override void ShowButton(Rect r) {}\n\n        internal override bool CanMaximize()\n        {\n            /*Since preview window is tightly coupled with Ispector window, maximizing this would destroy inspector\n             * which internally closes all the windows tied with it which in this case would be this window so there\n             * is no point in maximizing a winodw that will be closed as a part of maximizing*/\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/PropertyEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing UnityEditor.AddComponent;\nusing UnityEditor.VersionControl;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing UnityEditorInternal;\nusing UnityEditorInternal.VersionControl;\nusing UnityEditor.StyleSheets;\nusing UnityEngine.Assertions.Comparers;\nusing UnityEngine.UIElements;\nusing UnityEditor.SceneManagement;\n\nusing Object = UnityEngine.Object;\nusing AssetImporterEditor = UnityEditor.AssetImporters.AssetImporterEditor;\nusing JetBrains.Annotations;\nusing Unity.Profiling;\nusing UnityEditor.UIElements;\nusing UnityEngine.Pool;\n\nnamespace UnityEditor\n{\n    interface IPropertyView\n    {\n        ActiveEditorTracker tracker { get; }\n        InspectorMode inspectorMode { get; }\n        HashSet<int> editorsWithImportedObjectLabel { get; }\n        Editor lastInteractedEditor { get; set; }\n        GUIView parent { get; }\n        EditorDragging editorDragging { get; }\n\n        IMGUIContainer CreateIMGUIContainer(Action headerOnGUI, string v);\n        bool WasEditorVisible(Editor[] editors, int editorIndex, Object target);\n        bool ShouldCullEditor(Editor[] editors, int editorIndex);\n        void Repaint();\n        void UnsavedChangesStateChanged(Editor editor, bool value);\n    }\n\n    interface IPropertySourceOpener\n    {\n        Object hoveredObject { get; }\n    }\n\n    class PropertyEditor : EditorWindow, IPropertyView, IHasCustomMenu\n    {\n        internal const string k_AssetPropertiesMenuItemName = \"Assets/Properties... _&P\";\n        protected const string s_MultiEditClassName = \"unity-inspector-no-multi-edit-warning\";\n        protected const string s_EditorListClassName = \"unity-inspector-editors-list\";\n        protected const string s_AddComponentClassName = \"unity-inspector-add-component-button\";\n        protected const string s_HeaderInfoClassName = \"unity-inspector-header-info\";\n        protected const string s_FooterInfoClassName = \"unity-inspector-footer-info\";\n        internal const string s_MainContainerClassName = \"unity-inspector-main-container\";\n        protected const string s_PreviewContainer = \"preview-container\";\n        protected const string s_Footer = \"footer\";\n        protected const string s_dragline = \"unity-dragline\";\n        protected const string s_draglineAnchor = \"unity-dragline-anchor\";\n\n        protected const float kBottomToolbarHeight = 21f;\n        protected const float kAddComponentButtonHeight = 45f;\n        internal const float kEditorElementPaddingBottom = 2f;\n        protected const float k_MinAreaAbovePreview = 130;\n        protected const float k_InspectorPreviewMinHeight = 130;\n        protected const float k_InspectorPreviewMinTotalHeight = k_InspectorPreviewMinHeight + kBottomToolbarHeight;\n        protected const int k_MinimumRootVisualHeight = 81;\n        protected const int k_MinimumWindowWidth = 275;\n        protected const int k_AutoScrollZoneHeight = 24;\n        const float m_PreviewDefaultHeight = 200;\n        const float m_PreviewMinHeight = 20;\n\n        float m_CachedPreviewHeight = m_PreviewDefaultHeight;\n\n        protected const long delayRepaintWhilePlayingAnimation = 150; // Delay between repaints in milliseconds while playing animation\n        protected long m_LastUpdateWhilePlayingAnimation = 0;\n\n        /// <summary>\n        /// The number of inspector elements to create on the initial draw.\n        /// </summary>\n        const int k_CreateInspectorElementMinCount = 2;\n\n        /// <summary>\n        /// The target number of milliseconds to spend on creating inspector elements per update.\n        /// </summary>\n        const int k_CreateInspectorElementTargetUpdateTime = 5;\n\n        [SerializeField] protected List<Object> m_ObjectsLockedBeforeSerialization = new List<Object>();\n        [SerializeField] protected List<int> m_InstanceIDsLockedBeforeSerialization = new List<int>();\n        [SerializeField] protected PreviewResizer m_PreviewResizer = new PreviewResizer();\n        [SerializeField] protected LabelGUI m_LabelGUI = new LabelGUI();\n        [SerializeField] protected int m_LastInspectedObjectInstanceID = -1;\n        [SerializeField] protected float m_LastVerticalScrollValue = 0;\n        [SerializeField] protected string m_GlobalObjectId = \"\";\n        [SerializeField] protected InspectorMode m_InspectorMode = InspectorMode.Normal;\n\n        private static readonly List<PropertyEditor> m_AllPropertyEditors = new List<PropertyEditor>();\n        private Object m_InspectedObject;\n        private static PropertyEditor s_LastPropertyEditor;\n        protected int m_LastInitialEditorInstanceID;\n        protected Component[] m_ComponentsInPrefabSource;\n        protected HashSet<Component> m_RemovedComponents;\n        protected HashSet<Component> m_SuppressedComponents;\n        // Map that maps from editorIndex to list of removed asset components\n        // This is later used to determine if removed components visual elements need to be added to some editor at some index\n        protected Dictionary<int, List<Component>> m_RemovedComponentDict;\n        // List of removed components at the end of the editor list that needs to have visual elements append to the editor list\n        protected List<Component> m_AdditionalRemovedComponents;\n        protected bool m_ResetKeyboardControl;\n        internal bool m_OpenAddComponentMenu = false;\n        protected ActiveEditorTracker m_Tracker;\n        protected AssetBundleNameGUI m_AssetBundleNameGUI = new AssetBundleNameGUI();\n        protected TypeSelectionList m_TypeSelectionList = null;\n        protected double m_lastRenderedTime;\n        protected List<IPreviewable> m_Previews;\n        protected Dictionary<Type, List<Type>> m_PreviewableTypes;\n        protected IPreviewable m_SelectedPreview;\n        protected VisualElement m_EditorsElement;\n        protected VisualElement editorsElement => m_EditorsElement ?? (m_EditorsElement = FindVisualElementInTreeByClassName(s_EditorListClassName));\n        protected VisualElement m_RemovedPrefabComponentsElement;\n        protected VisualElement m_PreviewAndLabelElement;\n        protected VisualElement previewAndLabelElement => m_PreviewAndLabelElement ?? (m_PreviewAndLabelElement = FindVisualElementInTreeByClassName(s_FooterInfoClassName));\n        protected VisualElement m_VersionControlElement;\n        protected VisualElement versionControlElement => m_VersionControlElement ?? (m_VersionControlElement = FindVisualElementInTreeByClassName(s_HeaderInfoClassName));\n        protected static Dictionary<Editor, VersionControlBarState> m_VersionControlBarState = new Dictionary<Editor, VersionControlBarState>();\n        protected VisualElement m_MultiEditLabel;\n        protected ScrollView m_ScrollView;\n        protected bool m_TrackerResetInserted;\n        internal bool m_FirstInitialize;\n        protected float m_PreviousFooterHeight = -1;\n        protected bool m_PreviousPreviewExpandedState;\n        protected bool m_HasPreview;\n        protected HashSet<int> m_DrawnSelection = new HashSet<int>();\n        readonly List<Type> m_EditorTargetTypes = new List<Type>();\n\n        List<DataMode> m_SupportedDataModes = new(4);\n        static readonly List<DataMode> k_DisabledDataModes = new() {DataMode.Disabled};\n\n        public GUIView parent => m_Parent;\n        public HashSet<int> editorsWithImportedObjectLabel { get; } = new HashSet<int>();\n        public EditorDragging editorDragging { get; }\n        public Editor lastInteractedEditor { get; set; }\n        internal static PropertyEditor HoveredPropertyEditor { get; private set; }\n        internal static PropertyEditor FocusedPropertyEditor { get; private set; }\n\n        EditorElementUpdater m_EditorElementUpdater;\n        IPreviewable m_cachedPreviewEditor;\n\n        /// <summary>\n        /// Delayer used to periodically check if the return value of <see cref=\"IPreviewable.HasPreviewGUI\"/> has changed.\n        /// </summary>\n        Delayer m_HasPreviewPeriodicCheckDelayer;\n\n        /// <summary>\n        /// Stores the last return value of <see cref=\"IPreviewable.HasPreviewGUI\"/> in <see cref=\"HasPreviewPeriodicCheck\"/>.\n        /// </summary>\n        bool m_LastHasPreviewPeriodicCheck;\n\n        public InspectorMode inspectorMode\n        {\n            get { return m_InspectorMode; }\n            set { SetMode(value); }\n        }\n\n        public ActiveEditorTracker tracker\n        {\n            get\n            {\n                CreateTracker();\n                return m_Tracker;\n            }\n        }\n\n        protected Rect bottomAreaDropRectangle\n        {\n            get\n            {\n                var worldEditorRect = editorsElement.LocalToWorld(editorsElement.rect);\n                var worldRootRect = rootVisualElement.LocalToWorld(rootVisualElement.rect);\n                return new Rect(\n                    worldEditorRect.x,\n                    worldEditorRect.y + worldEditorRect.height,\n                    worldEditorRect.width,\n                    worldRootRect.y + worldRootRect.height - worldEditorRect.height - worldEditorRect.y);\n            }\n        }\n\n        internal Rect scrollViewportRect => m_ScrollView.contentViewport.rect;\n\n        protected static class Styles\n        {\n            public static readonly GUIStyle preToolbar = \"preToolbar\";\n            public static readonly GUIStyle preToolbar2 = \"preToolbar2\";\n            public static readonly GUIStyle preToolbarLabel = \"ToolbarBoldLabel\";\n            public static readonly GUIStyle preDropDown = \"preDropDown\";\n            public static readonly GUIStyle dragHandle = \"RL DragHandle\";\n            public static readonly GUIStyle lockButton = \"IN LockButton\";\n            public static readonly GUIStyle insertionMarker = \"InsertionMarker\";\n            public static readonly GUIContent preTitle = EditorGUIUtility.TrTextContent(\"Preview\");\n            public static readonly GUIContent labelTitle = EditorGUIUtility.TrTextContent(\"Asset Labels\");\n            public static readonly GUIContent addComponentLabel = EditorGUIUtility.TrTextContent(\"Add Component\");\n            public static GUIStyle preBackground = \"preBackground\";\n            public static GUIStyle footer = \"IN Footer\";\n            public static GUIStyle preMargins = new GUIStyle() {margin = new RectOffset(0, 0, 0, 4)};\n            public static GUIStyle preOptionsButton = new GUIStyle(EditorStyles.toolbarButtonRight) { padding = new RectOffset(), contentOffset = new Vector2(1, 0) };\n            public static GUIStyle addComponentArea = EditorStyles.inspectorTitlebar;\n            public static GUIStyle addComponentButtonStyle = \"AC Button\";\n            public static readonly GUIContent menuIcon = EditorGUIUtility.TrIconContent(\"_Menu\");\n            public static GUIStyle previewMiniLabel = EditorStyles.whiteMiniLabel;\n            public static GUIStyle typeSelection = \"IN TypeSelection\";\n\n            public static readonly GUIContent vcsCheckoutHint = EditorGUIUtility.TrTextContent(\"Under Version Control\\nCheck out this asset in order to make changes.\", EditorGUIUtility.GetHelpIcon(MessageType.Info));\n            public static readonly GUIContent vcsNotConnected = EditorGUIUtility.TrTextContent(\"VCS ({0}) is not connected\");\n            public static readonly GUIContent vcsOffline = EditorGUIUtility.TrTextContent(\"Work Offline option is active\");\n            public static readonly GUIContent vcsSettings = EditorGUIUtility.TrTextContent(\"Settings\");\n            public static readonly GUIContent vcsCheckout = EditorGUIUtility.TrTextContent(\"Check Out\");\n            public static readonly GUIContent vcsCheckoutMeta = EditorGUIUtility.TrTextContent(\"Check Out Meta\");\n            public static readonly GUIContent vcsAdd = EditorGUIUtility.TrTextContent(\"Add\");\n            public static readonly GUIContent vcsLock = EditorGUIUtility.TrTextContent(\"Lock\");\n            public static readonly GUIContent vcsUnlock = EditorGUIUtility.TrTextContent(\"Unlock\");\n            public static readonly GUIContent vcsSubmit = EditorGUIUtility.TrTextContent(\"Submit\");\n            public static readonly GUIContent vcsRevert = EditorGUIUtility.TrTextContent(\"Revert\");\n            public static readonly GUIContent vcsRevertUnchanged = EditorGUIUtility.TrTextContent(\"Revert Unchanged\");\n            public static readonly GUIContent[] vcsRevertMenuNames = {vcsRevertUnchanged};\n            public static readonly GenericMenu.MenuFunction2[] vcsRevertMenuActions = {DoRevertUnchanged};\n            public static readonly GUIStyle vcsButtonStyle = EditorStyles.miniButton;\n            public static GUIStyle vcsRevertStyle = new GUIStyle(EditorStyles.dropDownList);\n            public static readonly GUIStyle vcsBarStyleOneRow = EditorStyles.toolbar;\n            public static GUIStyle vcsBarStyleTwoRows = new GUIStyle(EditorStyles.toolbar);\n            public static readonly string objectDisabledModuleWarningFormat = L10n.Tr(\n                \"The built-in package '{0}', which implements this component type, has been disabled in Package Manager. This object will be removed in play mode and from any builds you make.\"\n            );\n            public static readonly string objectDisabledModuleWithDependencyWarningFormat = L10n.Tr(\n                \"The built-in package '{0}', which is required by the package '{1}', which implements this component type, has been disabled in Package Manager. This object will be removed in play mode and from any builds you make.\"\n            );\n\n            public static SVC<float> lineSeparatorOffset = new SVC<float>(\"AC-Button\", \"--separator-line-top-offset\");\n            public static SVC<Color> lineSeparatorColor = new SVC<Color>(\"--theme-line-separator-color\", Color.red);\n\n            static Styles()\n            {\n                vcsRevertStyle.padding.right = 15;\n                vcsBarStyleTwoRows.fixedHeight *= 2;\n            }\n        }\n\n        protected class VersionControlBarState\n        {\n            public bool settings;\n            public bool revert;\n            public bool revertUnchanged;\n            public bool checkout;\n            public bool add;\n            public bool submit;\n            public bool @lock;\n            public bool unlock;\n\n            Editor m_Editor;\n            public Editor Editor\n            {\n                get\n                {\n                    if (m_Editor == null && editors != null) m_Editor = InspectorWindowUtils.GetFirstNonImportInspectorEditor(editors);\n                    return m_Editor;\n                }\n                private set\n                {\n                    m_Editor = value;\n                }\n            }\n            public Editor[] editors;\n            public AssetList assets = new AssetList();\n\n            public int GetButtonCount()\n            {\n                var c = 0;\n                if (settings) ++c;\n                if (revert) ++c; // revertUnchanged is same button in a drop-down\n                if (checkout) ++c;\n                if (add) ++c;\n                if (submit) ++c;\n                if (@lock) ++c;\n                if (unlock) ++c;\n                return c;\n            }\n\n            public static VersionControlBarState Calculate(Editor[] assetEditors, Asset asset, bool connected)\n            {\n                var res = new VersionControlBarState();\n                if (!connected)\n                {\n                    res.settings = true;\n                    return res;\n                }\n\n                var isFolder = asset.isFolder && !Provider.isVersioningFolders;\n\n                res.editors = assetEditors;\n                res.assets.AddRange(res.Editor.targets.Select(o => Provider.GetAssetByPath(AssetDatabase.GetAssetPath(o))));\n                res.assets = Provider.ConsolidateAssetList(res.assets, CheckoutMode.Both);\n\n                res.revert = Provider.RevertIsValid(res.assets, RevertMode.Normal);\n                res.revertUnchanged = Provider.RevertIsValid(res.assets, RevertMode.Unchanged);\n\n                bool checkoutBoth = res.Editor.target == null || AssetDatabase.CanOpenAssetInEditor(res.Editor.target.GetInstanceID());\n                res.checkout = isFolder || Provider.CheckoutIsValid(res.assets, checkoutBoth ? CheckoutMode.Both : CheckoutMode.Meta);\n                res.add = Provider.AddIsValid(res.assets);\n                res.submit = Provider.SubmitIsValid(null, res.assets);\n                res.@lock = Provider.hasLockingSupport && !isFolder && Provider.LockIsValid(res.assets);\n                res.unlock = Provider.hasLockingSupport && !isFolder && Provider.UnlockIsValid(res.assets);\n                return res;\n            }\n        }\n\n        internal PropertyEditor()\n        {\n            editorDragging = new EditorDragging(this);\n            minSize = new Vector2(k_MinimumWindowWidth, minSize.y);\n            m_EditorElementUpdater = new EditorElementUpdater(this);\n        }\n\n        [UsedImplicitly]\n        protected virtual void OnDestroy()\n        {\n            if (m_Tracker != null)\n                m_Tracker.Destroy();\n        }\n\n        [UsedImplicitly]\n        protected virtual void OnFocusChanged(bool focus)\n        {\n            // focusing away from the editor flushes VCS state cache and might get\n            // updated states from external clients; make sure to recalculate which VCS\n            // buttons should be visible\n            ClearVersionControlBarState();\n        }\n\n        [UsedImplicitly]\n        protected virtual void OnEnable()\n        {\n            LoadVisualTreeFromUxml();\n            m_PreviewResizer.localFrame = true;\n            m_PreviewResizer.Init(\"InspectorPreview\");\n            m_LabelGUI.OnEnable();\n            m_FirstInitialize = true;\n            var shouldUpdateSupportedDataModes = m_SerializedDataModeController == null;\n            CreateTracker();\n\n            EditorApplication.focusChanged += OnFocusChanged;\n            Undo.undoRedoEvent += OnUndoRedoPerformed;\n            PrefabUtility.prefabInstanceUnpacked += OnPrefabInstanceUnpacked;\n            ObjectChangeEvents.changesPublished += OnObjectChanged;\n\n            rootVisualElement.RegisterCallback<DragUpdatedEvent>(DragOverBottomArea);\n            rootVisualElement.RegisterCallback<DragPerformEvent>(DragPerformInBottomArea);\n            rootVisualElement.RegisterCallback<MouseEnterEvent>(OnMouseEnter);\n            rootVisualElement.RegisterCallback<MouseLeaveEvent>(OnMouseLeave);\n            rootVisualElement.RegisterCallback<FocusInEvent>(OnFocusIn);\n            rootVisualElement.RegisterCallback<FocusOutEvent>(OnFocusOut);\n\n            dataModeController.dataModeChanged += OnDataModeChanged;\n            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;\n\n            if (shouldUpdateSupportedDataModes)\n                EditorApplication.CallDelayed(UpdateSupportedDataModesList);\n\n            if (!m_AllPropertyEditors.Contains(this))\n                m_AllPropertyEditors.Add(this);\n\n            // Setup a periodic check to determine if we need to rebuild the contents containers\n            m_HasPreviewPeriodicCheckDelayer = Delayer.Throttle(HasPreviewPeriodicCheck, TimeSpan.FromMilliseconds(200));\n\n            // Restrict the minimum height of the content area so it can't be collapsed to nothing\n            m_ScrollView.style.minHeight = 150;\n        }\n\n        /// <summary>\n        /// Periodic check if the preview editor has changed its HasPreviewGUI return value.\n        /// This is not executed on every frame because getting the editor that controls the preview is expensive.\n        /// </summary>\n        void HasPreviewPeriodicCheck(object _)\n        {\n            var previewEditor = GetEditorThatControlsPreview(tracker.activeEditors);\n\n            // Check if the return value of HasPreviewGUI has changed, and rebuild the contents containers if it did\n            var hasPreview = previewEditor != null && previewEditor.HasPreviewGUI();\n            if (hasPreview != m_LastHasPreviewPeriodicCheck)\n            {\n                RebuildContentsContainers();\n                m_LastHasPreviewPeriodicCheck = hasPreview;\n            }\n        }\n\n        [UsedImplicitly]\n        protected virtual void OnDisable()\n        {\n            if (m_HasPreviewPeriodicCheckDelayer != null)\n            {\n                m_HasPreviewPeriodicCheckDelayer.Dispose();\n                m_HasPreviewPeriodicCheckDelayer = null;\n            }\n\n            ClearPreviewables();\n\n            // save vertical scroll position\n            m_LastInspectedObjectInstanceID = GetInspectedObject()?.GetInstanceID() ?? -1;\n            m_LastVerticalScrollValue = m_ScrollView?.verticalScroller.value ?? 0;\n\n            EditorApplication.focusChanged -= OnFocusChanged;\n            Undo.undoRedoEvent -= OnUndoRedoPerformed;\n            PrefabUtility.prefabInstanceUnpacked -= OnPrefabInstanceUnpacked;\n            ObjectChangeEvents.changesPublished -= OnObjectChanged;\n\n            rootVisualElement.UnregisterCallback<DragUpdatedEvent>(DragOverBottomArea);\n            rootVisualElement.UnregisterCallback<DragPerformEvent>(DragPerformInBottomArea);\n            rootVisualElement.UnregisterCallback<MouseEnterEvent>(OnMouseEnter);\n            rootVisualElement.UnregisterCallback<MouseLeaveEvent>(OnMouseLeave);\n            rootVisualElement.UnregisterCallback<FocusInEvent>(OnFocusIn);\n            rootVisualElement.UnregisterCallback<FocusOutEvent>(OnFocusOut);\n\n            dataModeController.dataModeChanged -= OnDataModeChanged;\n            EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;\n\n            m_AllPropertyEditors.Remove(this);\n        }\n\n        private void OnMouseEnter(MouseEnterEvent e) => HoveredPropertyEditor = this;\n\n        private void OnMouseLeave(MouseLeaveEvent e) => HoveredPropertyEditor = null;\n\n        private void OnFocusIn(FocusInEvent e) => FocusedPropertyEditor = this;\n\n        private void OnFocusOut(FocusOutEvent e) => FocusedPropertyEditor = null;\n\n        [UsedImplicitly]\n        protected virtual void OnLostFocus()\n        {\n            m_LabelGUI.OnLostFocus();\n        }\n\n        protected virtual bool CloseIfEmpty()\n        {\n            // We can rely on the tracker to always keep valid Objects\n            // even after an assemblyreload or assetdatabase refresh.\n            List<Object> locked = new List<Object>();\n            tracker.GetObjectsLockedByThisTracker(locked);\n            if (locked.Any(o => o != null))\n                return false;\n\n            EditorApplication.delayCall += Close;\n            return true;\n        }\n\n        [UsedImplicitly]\n        protected virtual void OnInspectorUpdate()\n        {\n            if (CloseIfEmpty())\n                return;\n\n            // Check if scripts have changed without calling set dirty\n            tracker.VerifyModifiedMonoBehaviours();\n            InspectorUtility.DirtyLivePropertyChanges(tracker);\n            if(previewWindow != null)\n                UpdateLabel(previewWindow);\n\n            if (!tracker.isDirty || !ReadyToRepaint())\n                return;\n\n            Repaint();\n        }\n\n        [UsedImplicitly]\n        protected virtual void OnGUI()\n        {\n            if (m_FirstInitialize)\n                RebuildContentsContainers();\n            else\n                m_HasPreviewPeriodicCheckDelayer?.Execute();\n        }\n\n        static Editor[] s_Editors = new Editor[10];\n\n        [UsedImplicitly]\n        protected virtual void Update()\n        {\n            ActiveEditorTracker.Internal_GetActiveEditorsNonAlloc(tracker, ref s_Editors);\n            if (s_Editors.Length == 0)\n                return;\n\n            bool wantsRepaint = false;\n            foreach (var myEditor in s_Editors)\n            {\n                if (myEditor != null && myEditor.RequiresConstantRepaint() && !EditorUtility.IsHiddenInInspector(myEditor))\n                    wantsRepaint = true;\n            }\n\n            m_EditorElementUpdater.CreateInspectorElementsForMilliseconds(k_CreateInspectorElementTargetUpdateTime);\n\n            if (wantsRepaint && m_lastRenderedTime + 0.033f < EditorApplication.timeSinceStartup)\n            {\n                m_lastRenderedTime = EditorApplication.timeSinceStartup;\n                Repaint();\n            }\n\n            if (m_InspectedObject && !string.Equals(m_InspectedObject.name, titleContent.text))\n                UpdateWindowObjectNameTitle();\n        }\n\n        internal static IEnumerable<PropertyEditor> GetPropertyEditors()\n        {\n            return m_AllPropertyEditors.AsEnumerable();\n        }\n\n        protected void SetMode(InspectorMode mode)\n        {\n            if (m_InspectorMode != mode)\n            {\n                m_InspectorMode = mode;\n                RefreshTitle();\n                // Clear the editors Element so that a real rebuild is done\n                editorsElement.Clear();\n                m_EditorElementUpdater.Clear();\n                tracker.inspectorMode = mode;\n                m_ResetKeyboardControl = true;\n                SceneView.SetActiveEditorsDirty(true);\n            }\n        }\n\n        protected void SetTitle(Object obj)\n        {\n            var objTitle = ObjectNames.GetInspectorTitle(obj);\n            var titleTooltip = objTitle;\n\n            if (obj is GameObject go)\n                titleTooltip = EditorUtility.GetHierarchyPath(go);\n            else if (obj is Component c)\n                titleTooltip = $\"{EditorUtility.GetHierarchyPath(c.gameObject)} ({objTitle})\";\n            else if (GlobalObjectId.TryParse(m_GlobalObjectId, out var gid))\n                titleTooltip = AssetDatabase.GUIDToAssetPath(gid.assetGUID);\n\n            titleContent = new GUIContent(obj.name, EditorGUIUtility.LoadIconRequired(\"UnityEditor.InspectorWindow\"), titleTooltip);\n            titleContent.image = AssetPreview.GetMiniThumbnail(obj);\n        }\n\n        protected virtual void RefreshTitle()\n        {\n            var obj = GetInspectedObject();\n            if (!obj)\n                return;\n            SetTitle(obj);\n        }\n\n        private VisualElement FindVisualElementInTreeByClassName(string elementClassName)\n        {\n            return rootVisualElement.Q(className: elementClassName);\n        }\n\n        internal static void ClearVersionControlBarState()\n        {\n            var vco = VersionControlManager.activeVersionControlObject;\n            if (vco != null)\n                vco.GetExtension<IInspectorWindowExtension>()?.InvalidateVersionControlBarState();\n            m_VersionControlBarState.Clear();\n        }\n\n        protected void LoadVisualTreeFromUxml()\n        {\n            var tpl = EditorGUIUtility.Load(\"UXML/InspectorWindow/InspectorWindow.uxml\") as VisualTreeAsset;\n            var fContainer = rootVisualElement.Query(null, s_MainContainerClassName).First();\n            VisualElement container = fContainer ?? tpl.Instantiate();\n            container.AddToClassList(s_MainContainerClassName);\n            rootVisualElement.hierarchy.Add(container);\n            m_ScrollView = container.Q<ScrollView>();\n\n            // We need to disable view-data persistence on the scrollbars of the ScrollView.\n            // There are a bunch of places that assume the Inspector will always refresh\n            // fully scrolled up. Users also had this behaviour since the beginning of time.\n            // While we need m_ScrollView to have a view data key so users inside of an Editor\n            // can use view data persistence, adding a key will enable persistence of the\n            // scrollbars.\n            m_ScrollView.verticalScroller.viewDataKey = null;\n            m_ScrollView.horizontalScroller.viewDataKey = null;\n            m_ScrollView.verticalScroller.slider.viewDataKey = null;\n            m_ScrollView.horizontalScroller.slider.viewDataKey = null;\n\n            var multiContainer = rootVisualElement.Q(className: s_MultiEditClassName);\n            multiContainer.Query<TextElement>().ForEach((label) => label.text = L10n.Tr(label.text));\n            multiContainer.RemoveFromHierarchy();\n\n            m_MultiEditLabel = multiContainer;\n\n            rootVisualElement.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);\n            rootVisualElement.AddStyleSheetPath(\"StyleSheets/InspectorWindow/InspectorWindow.uss\");\n        }\n\n        private void OnGeometryChanged(GeometryChangedEvent e)\n        {\n            if (m_PreviewResizer.GetExpanded())\n            {\n                if (previewAndLabelElement.layout.height > 0 &&\n                    rootVisualElement.layout.height <= k_MinimumRootVisualHeight + m_PreviewResizer.containerMinimumHeightExpanded)\n                {\n                    m_PreviewResizer.SetExpanded(false);\n                }\n            }\n            RestoreVerticalScrollIfNeeded();\n        }\n\n        internal static void ClearAndRebuildAll()\n        {\n            // Needs to be delayCall because it forces redrawing of UI which messes with the current IMGUI context of the Settings window.\n            EditorApplication.delayCall += ClearAndRebuildAllDelayed;\n        }\n\n        static void ClearAndRebuildAllDelayed()\n        {\n            // Cannot use something like EditorUtility.ForceRebuildInspectors() because this only refreshes\n            // the inspector's values and IMGUI state, but otherwise, if the target did not change we\n            // re-use the Editors. We need a special clear function to properly recreate the UI using\n            // the new setting.\n            var propertyEditors = Resources.FindObjectsOfTypeAll<PropertyEditor>();\n            foreach (var propertyEditor in propertyEditors)\n                propertyEditor.ClearEditorsAndRebuild();\n        }\n\n        internal void ClearEditorsAndRebuild()\n        {\n            // Clear the editors Element so that a real rebuild is done\n            editorsElement.Clear();\n            m_EditorElementUpdater.Clear();\n            RebuildContentsContainers();\n        }\n\n        private void SetDebug()\n        {\n            inspectorMode = InspectorMode.Debug;\n        }\n\n        private void SetNormal()\n        {\n            inspectorMode = InspectorMode.Normal;\n        }\n\n        private void SetDebugInternal()\n        {\n            inspectorMode = InspectorMode.DebugInternal;\n        }\n\n        public virtual void AddDebugItemsToMenu(GenericMenu menu)\n        {\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Normal\"), m_InspectorMode == InspectorMode.Normal, SetNormal);\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Debug\"), m_InspectorMode == InspectorMode.Debug, SetDebug);\n\n            if (Unsupported.IsDeveloperMode())\n            {\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Debug-Internal\"), m_InspectorMode == InspectorMode.DebugInternal, SetDebugInternal);\n            }\n        }\n\n        public virtual void AddItemsToMenu(GenericMenu menu)\n        {\n            AddDebugItemsToMenu(menu);\n            menu.AddSeparator(String.Empty);\n\n            if (IsAnyComponentCollapsed())\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Expand All Components\"), false, ExpandAllComponents);\n            else\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Expand All Components\"));\n\n            if (IsAnyComponentExpanded())\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Collapse All Components\"), false, CollapseAllComponents);\n            else\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Collapse All Components\"));\n\n            if (m_Tracker != null)\n            {\n                bool addedSeparator = false;\n                foreach (var editor in m_Tracker.activeEditors)\n                {\n                    var menuContainer = editor as IHasCustomMenu;\n                    if (menuContainer != null)\n                    {\n                        if (!addedSeparator)\n                        {\n                            menu.AddSeparator(String.Empty);\n                            addedSeparator = true;\n                        }\n                        menuContainer.AddItemsToMenu(menu);\n                    }\n                }\n            }\n\n            menu.AddSeparator(\"\");\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Ping\"), false, () => EditorGUIUtility.PingObject(GetInspectedObject()));\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Open in Import Activity Window\"), false, () => ImportActivityWindow.OpenFromPropertyEditor(GetInspectedObject()));\n        }\n\n        private void SetTrackerExpandedState(ActiveEditorTracker tracker, int editorIndex, bool expanded)\n        {\n            tracker.SetVisible(editorIndex, expanded ? 1 : 0);\n            InternalEditorUtility.SetIsInspectorExpanded(tracker.activeEditors[editorIndex].target, expanded);\n        }\n\n        protected void ExpandAllComponents()\n        {\n            var editors = tracker.activeEditors;\n            for (int i = 1; i < editors.Length; i++)\n                SetTrackerExpandedState(tracker, i, expanded: true);\n        }\n\n        protected bool IsAnyComponentCollapsed()\n        {\n            if (Selection.activeGameObject == null)\n                return false; // If the selection is not a game object then disable the option.\n\n            var editors = tracker.activeEditors;\n            for (int i = 1; i < editors.Length; i++)\n            {\n                if (tracker.GetVisible(i) == 0)\n                    return true;\n            }\n            return false;\n        }\n\n        protected void CollapseAllComponents()\n        {\n            var editors = tracker.activeEditors;\n            for (int i = 1; i < editors.Length; i++)\n                SetTrackerExpandedState(tracker, i, expanded: false);\n        }\n\n        protected bool IsAnyComponentExpanded()\n        {\n            if (Selection.activeGameObject == null)\n                return false;\n\n            var editors = this.tracker.activeEditors;\n            for (int i = 1; i < editors.Length; i++)\n            {\n                if (this.tracker.GetVisible(i) == 1)\n                    return true;\n            }\n            return false;\n        }\n\n        protected bool LoadPersistedObject()\n        {\n            if (String.IsNullOrEmpty(m_GlobalObjectId))\n                return false;\n\n            if (!GlobalObjectId.TryParse(m_GlobalObjectId, out var gid))\n                return false;\n\n            m_InspectedObject = GlobalObjectId.GlobalObjectIdentifierToObjectSlow(gid);\n            if (m_InspectedObject)\n            {\n                SetTitle(m_InspectedObject);\n                m_Tracker.SetObjectsLockedByThisTracker(new List<Object> { m_InspectedObject });\n            }\n            else\n            {\n                // Failed to load object, lets close this property editor.\n                EditorApplication.delayCall += Close;\n                return false;\n            }\n\n            return true;\n        }\n\n        protected virtual void CreateTracker()\n        {\n            if (m_Tracker != null)\n                return;\n\n            m_Tracker = new ActiveEditorTracker { inspectorMode = InspectorMode.Normal };\n            if (LoadPersistedObject())\n            {\n                m_Tracker.ForceRebuild();\n            }\n        }\n\n        private void OnTrackerRebuilt()\n        {\n            ExtractPrefabComponents();\n            // tracker gets rebuilt when selection or objects change; make sure to recalc which VCS\n            // buttons are shown\n            ClearVersionControlBarState();\n        }\n\n        private void OnObjectChanged(ref ObjectChangeEventStream stream)\n        {\n            var inspectedObject = GetInspectedObject();\n            if (inspectedObject == null)\n                return;\n            var inspectedInstanceId = inspectedObject.GetInstanceID();\n\n            for (int i = 0; i < stream.length; ++i)\n            {\n                var eventType = stream.GetEventType(i);\n                if (eventType == ObjectChangeKind.ChangeGameObjectOrComponentProperties)\n                {\n                    stream.GetChangeGameObjectOrComponentPropertiesEvent(i, out var e);\n                    if (e.instanceId == inspectedInstanceId)\n                    {\n                        UpdateWindowObjectNameTitle();\n                        return;\n                    }\n                }\n            }\n        }\n\n        protected virtual void UpdateWindowObjectNameTitle()\n        {\n            titleContent.text = GetInspectedObject()?.name ?? titleContent.text;\n            Repaint();\n        }\n\n        void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            // Fix for a swapping an `m_Script` field in debug mode followed by an undo/redo. This causes the serialized object\n            // to be reset back to it's previous type. The editor instance remains the same, the serialized object remains the same and property iterators return\n            // the previous type properties. This breaks most assumptions in the inspectors and property drawers and causes numerous errors. As a patch we do a nuclear\n            // rebuild of everything if this state is detected.\n            var editors = tracker.activeEditors;\n            for (var i = 0; i < m_EditorTargetTypes.Count && i < editors.Length; i++)\n            {\n                var targetType = editors[i].target ? editors[i].target.GetType() : null;\n\n                if (targetType == m_EditorTargetTypes[i])\n                    continue;\n\n                ActiveEditorTracker.sharedTracker.ForceRebuild();\n            }\n\n            // We need to detect and rebuild removed or suppressed component titlebars if the\n            // backend changes. Situations where this detection is needed is when:\n            // 1) Undo could cause a removed component to become a suppressed component and vice versa\n            // 2) Undo after replacing with a new prefab instance that has the same component count but the previous had a removed component.\n            // Other cases will cause the number of Editors to change which will result in the tracker being rebuilt already.\n            var prevRemovedComponents = new HashSet<Component>(m_RemovedComponents ?? new HashSet<Component>());\n            var prevSuppressedComponents = new HashSet<Component>(m_SuppressedComponents ?? new HashSet<Component>());\n            var prevComponentsInPrefabSource = new HashSet<Component>(m_ComponentsInPrefabSource ?? new Component[0]);\n            ExtractPrefabComponents();\n            if (!prevRemovedComponents.SetEquals(m_RemovedComponents ?? new HashSet<Component>())  ||\n                !prevSuppressedComponents.SetEquals(m_SuppressedComponents ?? new HashSet<Component>()) ||\n                !prevComponentsInPrefabSource.SetEquals(m_ComponentsInPrefabSource ?? new Component[0]))\n            {\n                RebuildContentsContainers();\n            }\n        }\n\n        private void DetermineInsertionPointOfVisualElementForRemovedComponent(int targetGameObjectIndex, Editor[] editors)\n        {\n            // Calculate which editor should have the removed component visual element added, if any.\n            // The visual element for removed components is added to the top of the chosen editor.\n            // It is assumed the asset components comes in the same order in the editors list, but there can be additional added\n            // components in the editors list, i.e. the editors for assets components can't be moved by the user\n            // Added components can appear anywhere in the editors list\n            if (m_RemovedComponentDict == null)\n                m_RemovedComponentDict = new Dictionary<int, List<Component>>();\n            if (m_AdditionalRemovedComponents == null)\n                m_AdditionalRemovedComponents = new List<Component>();\n\n            m_RemovedComponentDict.Clear();\n            m_AdditionalRemovedComponents.Clear();\n\n            int editorIndex = targetGameObjectIndex + 1;\n\n            foreach(var sourceComponent in m_ComponentsInPrefabSource)\n            {\n                // editorCounter is used to look forward in the list of editor, this is because added components might have be inserted between prefab components\n                // it starts at editorIndex because there is no need to look at the previous editors, based on the assumption that asset components and instance components\n                // always comes in the same order\n                int editorCounter = editorIndex;\n\n                // Move forwards through the list of editors to find one that matches the asset component\n                while (editorCounter < editors.Length)\n                {\n                    Object editorTarget = editors[editorCounter].target;\n\n                    // Skip added Components\n                    if (editorTarget is Component && PrefabUtility.GetPrefabInstanceHandle(editorTarget) == null)\n                    {\n                        // If editorIndex and editorCounter are identical we also increment the editor index because we don't\n                        // want to add the removed component visual element to added components editors\n                        // For consistency the visual element for removed components are never added to added components, so if the current\n                        // editor is an added component we skip the current editor\n                        if (editorIndex == editorCounter)\n                            ++editorIndex;\n                        ++editorCounter;\n                        continue;\n                    }\n\n                    Object correspondingSource = PrefabUtility.GetCorrespondingObjectFromSource(editorTarget);\n                    if (correspondingSource == sourceComponent)\n                    {\n                        // When we found an editor that matches the asset component, we move the start index because we don't have to test\n                        // this editor again\n                        editorIndex = editorCounter + 1;\n                        break;\n                    }\n\n                    ++editorCounter;\n                }\n\n                // If the forward looking counter has reached the end of the editors list, the component must have been removed from the instance\n                if (editorCounter >= editors.Length)\n                {\n                    // If the editorIndex has also reached the end we have removed components at the end of the list and those need to have their\n                    // visual element added separately\n                    if (editorIndex >= editors.Length)\n                    {\n                        m_AdditionalRemovedComponents.Add(sourceComponent);\n                    }\n                    else\n                    {\n                        if (!m_RemovedComponentDict.ContainsKey(editorIndex))\n                            m_RemovedComponentDict.Add(editorIndex, new List<Component>());\n\n                        m_RemovedComponentDict[editorIndex].Add(sourceComponent);\n                    }\n                }\n            }\n        }\n\n        private void ExtractPrefabComponents()\n        {\n            m_LastInitialEditorInstanceID = m_Tracker.activeEditors.Length == 0 ? 0 : m_Tracker.activeEditors[0].GetInstanceID();\n\n            m_ComponentsInPrefabSource = null;\n            m_RemovedComponentDict = null;\n            m_AdditionalRemovedComponents = null;\n            if (m_RemovedComponents == null)\n            {\n                m_RemovedComponents = new HashSet<Component>();\n                m_SuppressedComponents = new HashSet<Component>();\n            }\n            m_RemovedComponents.Clear();\n            m_SuppressedComponents.Clear();\n\n            if (m_Tracker.activeEditors.Length == 0)\n                return;\n            if (m_Tracker.activeEditors[0].targets.Length != 1)\n                return;\n\n            GameObject go = m_Tracker.activeEditors[0].target as GameObject;\n            if (go == null && m_Tracker.activeEditors[0] is PrefabImporterEditor)\n                go = m_Tracker.activeEditors[1].target as GameObject;\n            if (go == null)\n                return;\n\n            GameObject sourceGo = PrefabUtility.GetCorrespondingConnectedObjectFromSource(go);\n            if (sourceGo == null)\n                return;\n\n            m_ComponentsInPrefabSource = sourceGo.GetComponents<Component>();\n            Component[] actuallyRemovedComponents = PrefabUtility.GetRemovedComponents(PrefabUtility.GetPrefabInstanceHandle(go));\n            var removedComponentsList = PrefabOverridesUtility.GetRemovedComponentsForSingleGameObject(go);\n            for (int i = 0; i < removedComponentsList.Count; i++)\n            {\n                if (actuallyRemovedComponents.Contains(removedComponentsList[i].assetComponent))\n                    m_RemovedComponents.Add(removedComponentsList[i].assetComponent);\n                else\n                    m_SuppressedComponents.Add(removedComponentsList[i].assetComponent);\n            }\n        }\n\n        protected void CreatePreviewables()\n        {\n            if (m_Previews != null)\n                return;\n\n            m_Previews = new List<IPreviewable>();\n\n            var activeEditors = tracker?.activeEditors;\n            if (activeEditors == null || activeEditors.Length == 0)\n                return;\n\n            foreach (var editor in activeEditors)\n            {\n                IEnumerable<IPreviewable> previews = GetPreviewsForType(editor);\n                foreach (var preview in previews)\n                {\n                    m_Previews.Add(preview);\n                }\n            }\n        }\n\n        protected void ClearPreviewables()\n        {\n            if (m_Previews == null)\n                return;\n            for (int i = 0, c = m_Previews.Count; i < c; i++)\n                m_Previews[i]?.Cleanup();\n            m_Previews = null;\n        }\n\n        private Dictionary<Type, List<Type>> GetPreviewableTypes()\n        {\n            // We initialize this list once per PropertyEditor, instead of globally.\n            // This means that if the user is debugging an IPreviewable structure,\n            // the PropertyEditor can be closed and reopened to refresh this list.\n            //\n            if (m_PreviewableTypes == null)\n            {\n                InspectorWindowUtils.GetPreviewableTypes(out m_PreviewableTypes);\n            }\n\n            return m_PreviewableTypes;\n        }\n\n        private IEnumerable<IPreviewable> GetPreviewsForType(Editor editor)\n        {\n            // Retrieve the type we are looking for.\n            if (editor == null || editor.target == null)\n                return Enumerable.Empty<IPreviewable>();\n\n            Type targetType = editor.target.GetType();\n            var previewableTypes = GetPreviewableTypes();\n            if (previewableTypes == null || !previewableTypes.TryGetValue(targetType, out var previewerList) || previewerList == null)\n                return Enumerable.Empty<IPreviewable>();\n\n            List<IPreviewable> previews = new List<IPreviewable>();\n            foreach (var previewerType in previewerList)\n            {\n                var instance = Activator.CreateInstance(previewerType);\n\n                if (instance is IPreviewable preview)\n                {\n                    preview.Initialize(editor.targets);\n                    previews.Add(preview);\n                }\n            }\n\n            return previews;\n        }\n\n        private void ClearTrackerDirtyOnRepaint()\n        {\n            if (Event.current.type == EventType.Repaint)\n            {\n                tracker.ClearDirty();\n            }\n        }\n\n        public IMGUIContainer CreateIMGUIContainer(Action onGUIHandler, string name = null)\n        {\n            IMGUIContainer result = null;\n            if (m_TrackerResetInserted)\n            {\n                result = new IMGUIContainer(onGUIHandler);\n            }\n            else\n            {\n                m_TrackerResetInserted = true;\n                result = new IMGUIContainer(() =>\n                {\n                    ClearTrackerDirtyOnRepaint();\n                    onGUIHandler();\n                });\n            }\n\n            if (name != null)\n            {\n                result.name = name;\n            }\n\n            return result;\n        }\n\n        static readonly ProfilerMarker k_CreateInspectorElements = new ProfilerMarker(\"PropertyEditor.CreateInspectorElements\");\n\n        protected virtual void BeginRebuildContentContainers() {}\n        protected virtual void EndRebuildContentContainers() {}\n        internal virtual void RebuildContentsContainers()\n        {\n            ClearPreviewables();\n            m_SelectedPreview = null;\n            m_TypeSelectionList = null;\n            m_FirstInitialize = false;\n            editorsWithImportedObjectLabel.Clear();\n            m_LastInitialEditorInstanceID = 0;\n\n            if (m_RemovedPrefabComponentsElement != null)\n            {\n                m_RemovedPrefabComponentsElement.RemoveFromHierarchy();\n                m_RemovedPrefabComponentsElement = null;\n            }\n\n            if (m_RemovedComponentDict != null)\n            {\n                m_RemovedComponentDict = null;\n                m_AdditionalRemovedComponents = null;\n            }\n\n            BeginRebuildContentContainers();\n\n            ResetKeyboardControl();\n\n            var addComponentButton = rootVisualElement.Q(className: s_AddComponentClassName);\n            if (addComponentButton != null)\n                addComponentButton.Clear();\n            if (versionControlElement != null)\n                versionControlElement.Clear();\n            if (previewAndLabelElement != null)\n                previewAndLabelElement.Clear();\n\n            Editor[] editors = tracker.activeEditors;\n\n            // Fix for a swapping an `m_Script` field in debug mode followed by an undo/redo. This causes the serialized object to be reset back to it's previous type.\n            // The editor instance remains the same, the serialized object remains the same and property iterators return the previous type properties.\n            // Here we track the last built editor types which is compared during the next undo-redo operation.\n            m_EditorTargetTypes.Clear();\n            foreach (var editor in editors)\n                m_EditorTargetTypes.Add(editor.target ? editor.target.GetType() : null);\n\n            if (editors.Any() && versionControlElement != null)\n            {\n                versionControlElement.Add(CreateIMGUIContainer(\n                    () => VersionControlBar(editors)));\n            }\n\n            DrawEditors(editors);\n\n            var labelMustBeAdded = editorsElement != null && m_MultiEditLabel.parent != editorsElement;\n\n            // The PrefabImporterEditor can hide its imported objects if it detects missing scripts. In this case\n            // do not add the multi editing warning\n            var assetImporter = GetAssetImporter(editors);\n            if (assetImporter != null && !assetImporter.showImportedObject)\n                labelMustBeAdded = false;\n\n            if (tracker.hasComponentsWhichCannotBeMultiEdited)\n            {\n                if (editors.Length == 0 && !tracker.isLocked && Selection.objects.Length > 0 && editorsElement != null)\n                {\n                    editorsElement.Add(CreateIMGUIContainer(DrawSelectionPickerList));\n                }\n                else\n                {\n                    if (labelMustBeAdded && editorsElement != null)\n                    {\n                        editorsElement.Add(m_MultiEditLabel);\n                    }\n                }\n            }\n            else if (m_MultiEditLabel != null)\n            {\n                m_MultiEditLabel.RemoveFromHierarchy();\n            }\n\n            if (addComponentButton != null && editors.Any() && RootEditorUtils.SupportsAddComponent(editors))\n            {\n                addComponentButton.Add(CreateIMGUIContainer(() =>\n                {\n                    EditorGUI.indentLevel = 0;\n                    AddComponentButton(editors);\n                }));\n            }\n\n            if (m_SplitView == null)\n            {\n                m_SplitView = rootVisualElement.Q<TwoPaneSplitView>();\n\n                // Hide the dragline by default until we determine what kind of preview (UITK or IMGUI) we have\n                m_SplitView.Q(s_draglineAnchor).style.display = DisplayStyle.None;\n            }\n\n            ClearPreview();\n\n            if (m_PreviewResizer != null && editors.Any())\n            {\n                if (previewAndLabelElement != null)\n                {\n                    VisualElement previewItem = null;\n                    CreatePreviewables();\n                    m_cachedPreviewEditor = GetEditorThatControlsPreview(tracker.activeEditors);\n\n                    if (m_cachedPreviewEditor != null && m_cachedPreviewEditor.HasPreviewGUI())\n                    {\n                        previewWindow = new InspectorPreviewWindow();\n\n                        preview = m_SplitView.Q(s_PreviewContainer);\n                        preview.style.minHeight = m_PreviewMinHeight;\n\n                        previewItem = m_cachedPreviewEditor.CreatePreview(previewWindow);\n                        var draglineAnchor = m_SplitView.Q(s_draglineAnchor);\n\n                        if (previewItem != null)\n                        {\n                            // Temporary naming while in transition to UITK\n                            InitUITKPreview();\n                            preview.Add(previewWindow);\n\n                            preview.style.display = DisplayStyle.Flex;\n                            draglineAnchor.style.display = DisplayStyle.Flex;\n                        }\n                        else // IMGUI fallback if no UITK preview found\n                        {\n                            var previewAndLabelsContainer =\n                                CreateIMGUIContainer(DrawPreviewAndLabels, s_PreviewContainer);\n                            m_PreviewResizer.SetContainer(previewAndLabelsContainer, kBottomToolbarHeight);\n                            previewAndLabelElement.Add(previewAndLabelsContainer);\n\n                            preview.style.display = DisplayStyle.None;\n                            draglineAnchor.style.display = DisplayStyle.None;\n\n                            if (preview == null)\n                                m_SplitView.Add(previewAndLabelElement);\n                        }\n\n                    }\n                }\n\n                // Footer\n                if (previewAndLabelElement?.childCount == 0)\n                {\n                    var footerContainer = CreateIMGUIContainer(DrawFooter, s_Footer);\n                    previewAndLabelElement.Add(footerContainer);\n                }\n            }\n\n            k_CreateInspectorElements.Begin();\n            // Only trigger the fixed count and viewport creation if this is the first build. Otherwise let the update method handle it.\n            if (m_EditorElementUpdater.Position == 0 && editors.Any())\n            {\n                // Force create a certain number of inspector elements without invoking a layout pass.\n                // We always want a minimum number of elements to be added.\n                m_EditorElementUpdater.CreateInspectorElementsWithoutLayout(k_CreateInspectorElementMinCount);\n\n                // Continue creating elements until the viewport is full.\n                m_EditorElementUpdater.CreateInspectorElementsForViewport(m_ScrollView, editorsElement);\n            }\n            k_CreateInspectorElements.End();\n\n            rootVisualElement.MarkDirtyRepaint();\n\n            ScriptAttributeUtility.ClearGlobalCache();\n\n            EndRebuildContentContainers();\n            Repaint();\n            RefreshTitle();\n        }\n\n        void ClearPreview()\n        {\n            if (m_Previews == null)\n            {\n                if (m_SplitView?.fixedPane?.resolvedStyle != null)\n                {\n                    float height = m_SplitView.fixedPane.resolvedStyle.height;\n                    if(height != 0 && height != m_PreviewMinHeight)\n                        m_CachedPreviewHeight = height;\n                }\n\n                UpdatePreviewHeight(0);\n\n                m_cachedPreviewEditor = null;\n\n                if(preview?.childCount > 0 && previewWindow != null && preview.Q(previewWindow.name) != null)\n                    preview.Remove(previewWindow);\n\n                var footer = previewAndLabelElement?.Q(s_Footer);\n                if(previewAndLabelElement?.childCount > 0 && footer != null)\n                    previewAndLabelElement.Remove(footer);\n            }\n        }\n\n        void InitUITKPreview()\n        {\n            // Toolbar\n            PrepareToolbar();\n            UpdateLabel(previewWindow);\n\n            // Dragline\n            m_SplitView.AddToClassList(InspectorPreviewWindow.Styles.ussClassName);\n            var draglineAnchor = m_SplitView.Q(s_draglineAnchor);\n            var dragline = draglineAnchor.Q(s_dragline);\n            dragline.style.height = m_PreviewMinHeight;\n            dragline.RegisterCallback<GeometryChangedEvent>(e =>\n                OnDraglineGeometryChange(previewWindow, dragline));\n\n            draglineAnchor.RegisterCallback<PointerUpEvent>(OnDragLineChange);\n            UpdatePreviewHeight(m_CachedPreviewHeight);\n\n            // IMGUI Preview\n            VisualElement previewPane = previewWindow.GetPreviewPane();\n            if (previewPane.childCount == 0)\n            {\n                var previewAndLabelsContainer =\n                    CreateIMGUIContainer(() => DrawPreview(m_cachedPreviewEditor), \"preview\");\n                previewPane.Add(previewAndLabelsContainer);\n            }\n        }\n\n        private void OnDraglineGeometryChange(VisualElement window, VisualElement dragline)\n        {\n            if (window == null)\n                return;\n\n            var header = window.Q(InspectorPreviewWindow.Styles.headerName);\n            var toolbar = header?.Q(InspectorPreviewWindow.Styles.toolbarName);\n            var ellipsisMenu = header?.Q(InspectorPreviewWindow.Styles.elipsisMenuName);\n            float margin = dragline.resolvedStyle.marginRight;\n\n            if (header != null && toolbar != null && ellipsisMenu != null)\n            {\n                margin = toolbar.resolvedStyle.width + ellipsisMenu.resolvedStyle.width;\n            }\n\n            dragline.style.marginRight = margin;\n        }\n\n        internal void PrepareToolbar(bool isFloatingPreviewWindow = false)\n        {\n            if(!isFloatingPreviewWindow)\n                CreatePreviewEllipsisMenu();\n        }\n\n        internal void UpdateLabel(InspectorPreviewWindow toolbar)\n        {\n            IPreviewable previewEditor = GetEditorThatControlsPreview(tracker.activeEditors);\n\n            string label;\n            if (previewEditor != null && previewEditor.HasPreviewGUI())\n            {\n                string userDefinedTitle = previewEditor.GetPreviewTitle().text;\n                label = !String.IsNullOrEmpty(userDefinedTitle)? userDefinedTitle :  Styles.preTitle.text;\n            }\n            else\n            {\n                label = Styles.labelTitle.text;\n            }\n\n            var header = toolbar?.Q(InspectorPreviewWindow.Styles.headerName);\n            if (header?.Q(InspectorPreviewWindow.Styles.titleName) is Label labelElement)\n            {\n                labelElement.text = label;\n            }\n        }\n\n        public bool showingPreview => m_SplitView?.fixedPane?.resolvedStyle.height > m_PreviewMinHeight;\n\n        void UpdatePreviewHeight(float newHeight)\n        {\n            var draglineAnchor = m_SplitView?.Q(s_draglineAnchor);\n\n            if (draglineAnchor != null && m_SplitView.fixedPane != null)\n            {\n                m_SplitView.fixedPane.style.height = newHeight;\n                m_SplitView.fixedPaneDimension = newHeight;\n                draglineAnchor.style.top = m_SplitView.resolvedStyle.height - newHeight;\n            }\n        }\n\n        private void OnDragLineChange(PointerUpEvent evt)\n        {\n            var previewHeight = m_SplitView.fixedPane.resolvedStyle.height;\n            var isSingleClick = (previewHeight == m_CachedPreviewHeight || previewHeight == m_PreviewMinHeight)\n                                && Math.Abs(m_SplitView.m_Resizer.delta) <= 5;\n\n            if (isSingleClick && evt.button == (int) MouseButton.LeftMouse)\n            {\n                ExpandCollapsePreview();\n                return;\n            }\n\n            if (!showingPreview) return;\n            m_CachedPreviewHeight = previewHeight;\n        }\n\n        internal void ExpandCollapsePreview()\n        {\n            if (showingPreview)\n            {\n                m_CachedPreviewHeight = m_SplitView.fixedPane.resolvedStyle.height;\n                UpdatePreviewHeight(m_PreviewMinHeight);\n            }\n            else\n            {\n                UpdatePreviewHeight(m_CachedPreviewHeight);\n            }\n        }\n\n        internal void AutoScroll(Vector2 mousePosition)\n        {\n            if (m_ScrollView != null)\n            {\n                // implement auto-scroll for easier component drag'n'drop,\n                // we define a zone of height = k_AutoScrollZoneHeight\n                // at the top/bottom of the scrollView viewport,\n                // while dragging, when the mouse moves in these zones,\n                // we automatically scroll up/down\n                var localDragPosition = m_ScrollView.contentViewport.WorldToLocal(mousePosition);\n\n                if (localDragPosition.y < k_AutoScrollZoneHeight)\n                    m_ScrollView.verticalScroller.ScrollPageUp();\n                else if (localDragPosition.y > m_ScrollView.contentViewport.rect.height - k_AutoScrollZoneHeight)\n                    m_ScrollView.verticalScroller.ScrollPageDown();\n            }\n        }\n\n        internal void ScrollTo(Vector2 position)\n        {\n            if (m_ScrollView != null)\n            {\n                var localDragPosition = m_ScrollView.contentViewport.WorldToLocal(position);\n\n                if (localDragPosition.y < k_AutoScrollZoneHeight)\n                    m_ScrollView.verticalScroller.value += localDragPosition.y - k_AutoScrollZoneHeight;\n                else if (localDragPosition.y > m_ScrollView.contentViewport.rect.height - k_AutoScrollZoneHeight)\n                    m_ScrollView.verticalScroller.value += localDragPosition.y - (m_ScrollView.contentViewport.rect.height - k_AutoScrollZoneHeight);\n            }\n        }\n\n        private void DragOverBottomArea(DragUpdatedEvent dragUpdatedEvent)\n        {\n            if (DragAndDrop.objectReferences.Any())\n            {\n                if (editorsElement != null && editorsElement.ContainsPoint(editorsElement.WorldToLocal(dragUpdatedEvent.mousePosition)))\n                {\n                    AutoScroll(dragUpdatedEvent.mousePosition);\n                    return;\n                }\n\n                if (editorsElement != null)\n                {\n                    var lastChild = editorsElement.Children().LastOrDefault();\n                    if (lastChild == null)\n                        return;\n\n                    editorDragging.HandleDraggingInBottomArea(tracker.activeEditors, bottomAreaDropRectangle, lastChild.layout);\n                }\n            }\n        }\n\n        private void DragPerformInBottomArea(DragPerformEvent dragPerformedEvent)\n        {\n            if (editorsElement == null)\n                return;\n\n            if (editorsElement.ContainsPoint(editorsElement.WorldToLocal(dragPerformedEvent.mousePosition)))\n                return;\n\n            var lastChild = editorsElement.Children().LastOrDefault();\n            if (lastChild == null)\n                return;\n\n            editorDragging.HandleDragPerformInBottomArea(tracker.activeEditors, bottomAreaDropRectangle, lastChild.layout);\n        }\n\n        internal virtual Editor GetLastInteractedEditor()\n        {\n            return lastInteractedEditor;\n        }\n\n        protected IPreviewable GetEditorThatControlsPreview(Editor[] activeEditors)\n        {\n            using var _ = ListPool<IPreviewable>.Get(out var editorsWithPreviews);\n            GetEditorsWithPreviews(activeEditors, editorsWithPreviews);\n            return GetEditorThatControlsPreview(editorsWithPreviews);\n        }\n\n        protected IPreviewable GetEditorThatControlsPreview(List<IPreviewable> editors)\n        {\n            if (editors.Count == 0)\n                return null;\n\n            if (m_SelectedPreview != null)\n            {\n                return m_SelectedPreview;\n            }\n\n            // Find last interacted editor, if not found check if we had an editor of similar type,\n            // if not found use first editor that can show a preview otherwise return null.\n\n            IPreviewable lastInteractedEditor = GetLastInteractedEditor();\n            Type lastType = lastInteractedEditor?.GetType();\n\n            IPreviewable firstEditorThatHasPreview = null;\n            IPreviewable similarEditorAsLast = null;\n            foreach (IPreviewable e in editors)\n            {\n                if (e == null || e.target == null)\n                    continue;\n\n                // If target is an asset, but not the same asset as the asset\n                // of the first editor, then ignore it. This will prevent showing\n                // preview of materials attached to a GameObject but should cover\n                // future use cases as well.\n                if (EditorUtility.IsPersistent(e.target) &&\n                    AssetDatabase.GetAssetPath(e.target) != AssetDatabase.GetAssetPath(editors[0].target))\n                    continue;\n\n                // If main editor is an asset importer editor and this is an editor of the imported object, ignore.\n                if (editors[0] is AssetImporterEditor && !(e is AssetImporterEditor))\n                    continue;\n\n                if (e.HasPreviewGUI())\n                {\n                    if (e == lastInteractedEditor)\n                        return e;\n\n                    if (similarEditorAsLast == null && e.GetType() == lastType)\n                        similarEditorAsLast = e;\n\n                    if (firstEditorThatHasPreview == null)\n                        firstEditorThatHasPreview = e;\n                }\n            }\n\n            if (similarEditorAsLast != null)\n                return similarEditorAsLast;\n\n            if (firstEditorThatHasPreview != null)\n                return firstEditorThatHasPreview;\n\n            // Found no valid editor\n            return null;\n        }\n\n        protected void GetEditorsWithPreviews(Editor[] editors, List<IPreviewable> outEditorsWithPreview)\n        {\n            outEditorsWithPreview.Clear();\n            if (m_Previews == null) return;\n\n            int i = -1;\n            foreach (Editor e in editors)\n            {\n                ++i;\n                if (!e || e.target == null)\n                    continue;\n\n                // If target is an asset, but not the same asset as the asset\n                // of the first editor, then ignore it. This will prevent showing\n                // preview of materials attached to a GameObject but should cover\n                // future use cases as well.\n                if (EditorUtility.IsPersistent(e.target) &&\n                    AssetDatabase.GetAssetPath(e.target) != AssetDatabase.GetAssetPath(editors[0].target))\n                    continue;\n\n                if (!EditorUtility.IsPersistent(editors[0].target) && EditorUtility.IsPersistent(e.target))\n                    continue;\n\n                if (ShouldCullEditor(editors, i))\n                    continue;\n\n                // If main editor is an asset importer editor and this is an editor of the imported object, ignore.\n                if (editors[0] is AssetImporterEditor && !(e is AssetImporterEditor))\n                    continue;\n\n                if (e.HasPreviewGUI())\n                {\n                    outEditorsWithPreview.Add(e);\n                }\n            }\n\n            foreach (var previewable in m_Previews)\n            {\n                if (previewable.HasPreviewGUI())\n                    outEditorsWithPreview.Add(previewable);\n            }\n        }\n\n        internal virtual Object GetInspectedObject()\n        {\n            return m_InspectedObject;\n        }\n\n        private void ResetKeyboardControl()\n        {\n            if (m_ResetKeyboardControl)\n            {\n                GUIUtility.keyboardControl = 0;\n                m_ResetKeyboardControl = false;\n            }\n        }\n\n        private static bool IsOpenForEdit(Object target)\n        {\n            if (EditorUtility.IsPersistent(target))\n            {\n                var assetPath = AssetDatabase.GetAssetPath(target);\n                return Provider.PathHasMetaFile(assetPath) && AssetDatabase.IsMetaFileOpenForEdit(target);\n            }\n\n            return false;\n        }\n\n        private Object[] GetInspectedAssets()\n        {\n            // We use this technique to support locking of the inspector. An inspector locks via an editor, so we need to use an editor to get the selection\n            Editor assetEditor = InspectorWindowUtils.GetFirstNonImportInspectorEditor(tracker.activeEditors);\n            if (assetEditor != null && assetEditor.targets.Length == 1)\n            {\n                string assetPath = AssetDatabase.GetAssetPath(assetEditor.target);\n                if (IsOpenForEdit(assetEditor.target) && !Directory.Exists(assetPath))\n                    return assetEditor.targets;\n            }\n\n            // This is used if more than one asset is selected\n            // Ideally the tracker should be refactored to track not just editors but also the selection that caused them, so we wouldn't need this\n            return Selection.objects.Where(EditorUtility.IsPersistent).ToArray();\n        }\n\n        protected virtual bool BeginDrawPreviewAndLabels() { return true; }\n        protected virtual void EndDrawPreviewAndLabels(Event evt, Rect rect, Rect dragRect) {}\n        protected virtual void CreatePreviewEllipsisMenu() {}\n\n        protected TwoPaneSplitView m_SplitView = null;\n        VisualElement preview = null;\n        internal InspectorPreviewWindow previewWindow = null;\n        private void DrawPreviewAndLabels()\n        {\n            CreatePreviewables();\n            var hasPreview = BeginDrawPreviewAndLabels();\n\n            using var _ = ListPool<IPreviewable>.Get(out var editorsWithPreviews);\n            GetEditorsWithPreviews(tracker.activeEditors, editorsWithPreviews);\n            IPreviewable previewEditor = GetEditorThatControlsPreview(editorsWithPreviews);\n\n            // Do we have a preview?\n            m_HasPreview = previewEditor != null && previewEditor.HasPreviewGUI() && hasPreview;\n\n            m_PreviewResizer.containerMinimumHeightExpanded = m_HasPreview ? k_InspectorPreviewMinTotalHeight : 0;\n\n            Object[] assets = GetInspectedAssets();\n            bool hasLabels = assets.Length > 0;\n            bool hasBundleName = assets.Any(a => !(a is MonoScript) && AssetDatabase.IsMainAsset(a));\n\n            if (!m_HasPreview && !hasLabels)\n                return;\n\n            Event evt = Event.current;\n\n            // Preview / Asset Labels toolbar\n            Rect dragRect;\n            Rect dragIconRect = new Rect();\n            const float dragPadding = 3f;\n            const float minDragWidth = 20f;\n            Rect rect = EditorGUILayout.BeginHorizontal(GUIContent.none, Styles.preToolbar, GUILayout.Height(kBottomToolbarHeight));\n            {\n                GUILayout.FlexibleSpace();\n                dragRect = GUILayoutUtility.GetLastRect();\n\n            GUIContent title;\n            if (m_HasPreview)\n            {\n                GUIContent userDefinedTitle = previewEditor.GetPreviewTitle();\n                title = userDefinedTitle ?? Styles.preTitle;\n            }\n            else\n            {\n                title = Styles.labelTitle;\n            }\n\n                dragIconRect.x = dragRect.x + dragPadding;\n                dragIconRect.y = dragRect.y + (kBottomToolbarHeight - Styles.dragHandle.fixedHeight) / 2;\n                dragIconRect.width = dragRect.width - dragPadding * 2;\n                dragIconRect.height = Styles.dragHandle.fixedHeight;\n\n                //If we have more than one component with Previews, show a DropDown menu.\n                if (editorsWithPreviews.Count > 1)\n                {\n                    Vector2 foldoutSize = Styles.preDropDown.CalcSize(title);\n                    float maxFoldoutWidth = (dragIconRect.xMax - dragRect.xMin) - dragPadding - minDragWidth;\n                    float foldoutWidth = Mathf.Min(maxFoldoutWidth, foldoutSize.x);\n                    Rect foldoutRect = new Rect(dragRect.x, dragRect.y, foldoutWidth, foldoutSize.y);\n                    dragRect.xMin += foldoutWidth;\n                    dragIconRect.xMin += foldoutWidth;\n\n                    GUIContent[] panelOptions = new GUIContent[editorsWithPreviews.Count];\n                    int selectedPreview = -1;\n                    for (int index = 0; index < editorsWithPreviews.Count; index++)\n                    {\n                        IPreviewable currentEditor = editorsWithPreviews[index];\n                        GUIContent previewTitle = currentEditor.GetPreviewTitle() ?? Styles.preTitle;\n\n                        string fullTitle;\n                        if (previewTitle == Styles.preTitle)\n                        {\n                            string componentTitle = ObjectNames.GetTypeName(currentEditor.target);\n                            if (NativeClassExtensionUtilities.ExtendsANativeType(currentEditor.target))\n                            {\n                                componentTitle = MonoScript.FromScriptedObject(currentEditor.target).GetClass()\n                                    .Name;\n                            }\n\n                            fullTitle = previewTitle.text + \" - \" + componentTitle;\n                        }\n                        else\n                        {\n                            fullTitle = previewTitle.text;\n                        }\n\n                        panelOptions[index] = new GUIContent(fullTitle);\n                        if (editorsWithPreviews[index] == previewEditor)\n                        {\n                            selectedPreview = index;\n                        }\n                    }\n\n                    if (GUI.Button(foldoutRect, title, Styles.preDropDown))\n                    {\n                        EditorUtility.DisplayCustomMenu(foldoutRect, panelOptions, selectedPreview,\n                            OnPreviewSelected, editorsWithPreviews.ToArray());\n                    }\n                }\n                else\n                {\n                    float maxLabelWidth = (dragIconRect.xMax - dragRect.xMin) - dragPadding - minDragWidth;\n                    float labelWidth = Mathf.Min(maxLabelWidth, Styles.preToolbar2.CalcSize(title).x);\n                    Rect labelRect = new Rect(dragRect.x, dragRect.y, labelWidth, dragRect.height);\n\n                    dragIconRect.xMin = labelRect.xMax + dragPadding;\n\n                    GUI.Label(labelRect, title, Styles.preToolbarLabel);\n                }\n\n                if (m_HasPreview && Event.current.type == EventType.Repaint)\n                {\n                    // workaround: To properly center the image because it already has a 1px bottom padding\n                    dragIconRect.y += 1;\n                    Styles.dragHandle.Draw(dragIconRect, GUIContent.none, false, false, false, false);\n                }\n\n                if (m_HasPreview && m_PreviewResizer.GetExpandedBeforeDragging())\n                    previewEditor.OnPreviewSettings();\n\n                EndDrawPreviewAndLabels(evt, rect, dragRect);\n            }\n            EditorGUILayout.EndHorizontal();\n\n            // Logic for resizing and collapsing\n            float previewSize;\n            if (m_HasPreview)\n            {\n                // If we have a preview we'll use the ResizerControl which handles both resizing and collapsing\n                previewSize = m_PreviewResizer.ResizeHandle(position, k_InspectorPreviewMinTotalHeight, k_MinAreaAbovePreview, kBottomToolbarHeight, dragRect);\n            }\n            else\n            {\n                // If we don't have a preview, just toggle the collapsible state with a button\n                if (GUI.Button(rect, GUIContent.none, GUIStyle.none))\n                    m_PreviewResizer.ToggleExpanded();\n\n                previewSize = 0;\n            }\n\n            // If collapsed, early out\n            if (!m_PreviewResizer.GetExpanded())\n            {\n                if (m_PreviousPreviewExpandedState)\n                {\n                    UIEventRegistration.MakeCurrentIMGUIContainerDirty();\n                    m_PreviousPreviewExpandedState = false;\n                }\n                m_PreviousFooterHeight = previewSize;\n                return;\n            }\n\n            // The preview / label area (not including the toolbar)\n            GUILayout.BeginVertical(Styles.preBackground, GUILayout.Height(previewSize));\n            {\n                // Draw preview\n                if (m_HasPreview)\n                {\n                    DrawPreview(previewEditor);\n                }\n\n                DrawFooter();\n\n            }\n            GUILayout.EndVertical();\n\n            if (m_PreviousFooterHeight >= 0f && !FloatComparer.s_ComparerWithDefaultTolerance.Equals(previewSize, m_PreviousFooterHeight))\n            {\n                UIEventRegistration.MakeCurrentIMGUIContainerDirty();\n            }\n\n            m_PreviousFooterHeight = previewSize;\n            m_PreviousPreviewExpandedState = m_PreviewResizer.GetExpanded();\n        }\n\n        private void DrawPreview(IPreviewable editor)\n        {\n            var previewRect = GUILayoutUtility.GetRect(0, 10240, 64, 10240);\n            if (!float.IsNaN(previewRect.height) && !float.IsNaN(previewRect.width))\n            {\n                editor.DrawPreview(previewRect);\n            }\n        }\n\n        private void DrawFooter()\n        {\n            Object[] assets = GetInspectedAssets();\n            bool hasLabels = assets.Length > 0;\n            bool hasBundleName = assets.Any(a => !(a is MonoScript) && AssetDatabase.IsMainAsset(a));\n\n            IPreviewable previewEditor = GetEditorThatControlsPreview(tracker.activeEditors);\n\n            if (previewEditor == null || !previewEditor.HasPreviewGUI())\n            {\n                GUILayout.BeginVertical(Styles.footer);\n                GUILayout.Label(Styles.labelTitle, Styles.preToolbarLabel);\n                GUILayout.EndVertical();\n            }\n\n            GUILayout.BeginVertical(Styles.footer);\n            if (hasLabels)\n            {\n                using (new EditorGUI.DisabledScope(assets.Any(a => !IsOpenForEdit(a) || !Editor.IsAppropriateFileOpenForEdit(a))))\n                {\n                    m_LabelGUI.OnLabelGUI(assets);\n                }\n            }\n\n            if (hasBundleName)\n            {\n                using (new EditorGUI.DisabledScope(assets.Any(a => !IsOpenForEdit(a))))\n                {\n                    m_AssetBundleNameGUI.OnAssetBundleNameGUI(assets);\n                }\n            }\n            GUILayout.EndVertical();\n        }\n\n        private void OnPreviewSelected(object userData, string[] options, int selected)\n        {\n            var availablePreviews = (IPreviewable[])userData;\n            m_SelectedPreview = availablePreviews[selected];\n        }\n\n        internal static void VersionControlBar(Editor assetEditor) => VersionControlBar(new[] { assetEditor });\n\n        internal static void VersionControlBar(Editor[] assetEditors)\n        {\n            Editor assetEditor = InspectorWindowUtils.GetFirstNonImportInspectorEditor(assetEditors);\n\n            var vco = VersionControlManager.activeVersionControlObject;\n            if (vco != null)\n            {\n                vco.GetExtension<IInspectorWindowExtension>()?.OnVersionControlBar(assetEditor);\n                return;\n            }\n\n            if (!Provider.enabled)\n                return;\n            var vcsMode = VersionControlSettings.mode;\n            if (vcsMode == ExternalVersionControl.Generic || vcsMode == ExternalVersionControl.Disabled || vcsMode == ExternalVersionControl.AutoDetect)\n                return;\n\n            var assetPath = AssetDatabase.GetAssetPath(assetEditor.target);\n            Asset asset = Provider.GetAssetByPath(assetPath);\n            if (asset == null)\n                return;\n\n            if (!VersionControlUtils.IsPathVersioned(asset.path))\n                return;\n\n            var connected = Provider.isActive;\n\n            // Note: files under project settings do not have .meta files next to them,\n            // but Provider.GetAssetByPath API helpfully (or unhelpfully, in this case)\n            // checks if passed file ends with \"meta\" and says \"here, take this asset instead\"\n            // if it exists -- so for files under project settings, it ends up returning\n            // a valid entry for the non-existing meta file. So just don't do it.\n            Asset metaAsset = null;\n            if (Provider.PathHasMetaFile(asset.path))\n                metaAsset = Provider.GetAssetByPath(assetPath.Trim('/') + \".meta\");\n\n            string currentState = asset.StateToString();\n            string currentMetaState = metaAsset == null ? String.Empty : metaAsset.StateToString();\n\n            // If VCS is enabled but disconnected, the assets will have \"Updating\" state most of the time,\n            // but what we want to displays is a note that VCS is not connected.\n            if (!connected)\n            {\n                if (EditorUserSettings.WorkOffline)\n                    currentState = Styles.vcsOffline.text;\n                else\n                    currentState = string.Format(Styles.vcsNotConnected.text, Provider.GetActivePlugin().name);\n                currentMetaState = currentState;\n            }\n\n            var hasAssetState = !string.IsNullOrEmpty(currentState);\n            var hasMetaState = !string.IsNullOrEmpty(currentMetaState);\n\n            // Cache AssetList for current selection and\n            // figure out which buttons we'll need to show for them.\n            VersionControlBarState state;\n            if (!m_VersionControlBarState.TryGetValue(assetEditor, out state))\n            {\n                state = VersionControlBarState.Calculate(assetEditors, asset, connected);\n                m_VersionControlBarState.Add(assetEditor, state);\n            }\n            // Based on that and the current inspector width, we might want to layout the VCS\n            // bar in two rows to better fit status label & buttons.\n            var approxSpaceForButtons = state.GetButtonCount() * 50;\n            var useTwoRows = GUIView.current != null && GUIView.current.position.width * 0.5f < approxSpaceForButtons;\n\n            var lineHeight = Styles.vcsBarStyleOneRow.fixedHeight;\n            var barStyle = useTwoRows ? Styles.vcsBarStyleTwoRows : Styles.vcsBarStyleOneRow;\n            GUILayout.BeginHorizontal(GUIContent.none, barStyle);\n            var barRect = GUILayoutUtility.GetRect(GUIContent.none, barStyle, GUILayout.ExpandWidth(true));\n\n            var icon = AssetDatabase.GetCachedIcon(assetPath) as Texture2D;\n            var overlayRect = new Rect(barRect.x, barRect.y + 1, 28, 16);\n            var iconRect = overlayRect;\n            iconRect.x += 6;\n            iconRect.width = 16;\n            if (icon != null)\n                GUI.DrawTexture(iconRect, icon);\n            Overlay.DrawOtherOverlay(asset, metaAsset ?? asset, overlayRect);\n\n            if (currentMetaState != currentState)\n            {\n                if (hasAssetState && hasMetaState)\n                    currentState = currentState + \"; meta: \" + currentMetaState;\n                else if (hasAssetState && metaAsset != null) // project settings don't even have .meta files; no point in adding \"asset only\" for them\n                    currentState = currentState + \" (asset only)\";\n                else if (hasMetaState)\n                    currentState = currentMetaState + \" (meta only)\";\n            }\n\n            var buttonsRect = barRect;\n            buttonsRect.yMin = buttonsRect.yMax - lineHeight;\n            var buttonX = VersionControlBarButtons(state, buttonsRect, connected);\n            var textRect = barRect;\n            textRect.height = lineHeight;\n            textRect.xMin += 26;\n            if (!useTwoRows)\n                textRect.xMax = buttonX;\n\n            var content = GUIContent.Temp(currentState);\n            var fullState = Asset.AllStateToString(asset.state);\n            var fullMetaState = metaAsset != null ? Asset.AllStateToString(metaAsset.state) : string.Empty;\n            if (fullState != fullMetaState)\n                fullState = $\"Asset state: {fullState}\\nMeta state: {fullMetaState}\";\n            else\n                fullState = \"State: \" + fullState;\n            content.tooltip = fullState;\n            GUI.Label(textRect, content, EditorStyles.label);\n            GUILayout.EndHorizontal();\n\n            VersionControlCheckoutHint(assetEditor, connected);\n        }\n\n        private static void VersionControlCheckoutHint(Editor assetEditor, bool connected)\n        {\n            if (!connected)\n                return;\n\n            const string prefKeyName = \"vcs_CheckoutHintClosed\";\n            var removedHint = EditorPrefs.GetBool(prefKeyName);\n            if (removedHint)\n                return;\n            if (Editor.IsAppropriateFileOpenForEdit(assetEditor.target))\n                return;\n\n            // allow clicking the help note to make it go away via prefs\n            if (GUILayout.Button(Styles.vcsCheckoutHint, EditorStyles.helpBox))\n                EditorPrefs.SetBool(prefKeyName, true);\n\n            GUILayout.Space(4);\n        }\n\n        internal static void CheckoutForInspector(Object[] targets)\n        {\n            if (targets == null || targets.Length < 0) return;\n\n            AssetList inspectorAssets = new AssetList();\n\n            // Since we can't edit multiple asset types in one Inspector it is safe to say\n            // that we will have to checkout all assets in the same way as the first one.\n            bool needToCheckoutBoth = AssetDatabase.CanOpenAssetInEditor(targets[0].GetInstanceID());\n\n            foreach (var asset in targets)\n            {\n                string assetPath = AssetDatabase.GetAssetPath(asset);\n\n                if (needToCheckoutBoth)\n                {\n                    Asset actualAsset = Provider.CacheStatus(assetPath);\n                    if (actualAsset != null) inspectorAssets.Add(actualAsset);\n                }\n\n                Asset metaAsset = Provider.CacheStatus(AssetDatabase.GetTextMetaFilePathFromAssetPath(assetPath));\n                if (metaAsset != null) inspectorAssets.Add(metaAsset);\n            }\n\n            Provider.Checkout(inspectorAssets, CheckoutMode.Exact);\n        }\n\n        private static void DoRevertUnchanged(object o)\n        {\n            var al = (AssetList)o;\n            Provider.Revert(al, RevertMode.Unchanged);\n        }\n\n        private static float VersionControlBarButtons(VersionControlBarState presence, Rect rect, bool connected)\n        {\n            var buttonX = rect.xMax - 7;\n\n            var buttonRect = rect;\n            var buttonStyle = Styles.vcsButtonStyle;\n            buttonRect.y += 1;\n            buttonRect.height = buttonStyle.CalcSize(Styles.vcsAdd).y;\n\n            if (!connected)\n            {\n                if (presence.settings)\n                {\n                    if (VersionControlActionButton(buttonRect, ref buttonX, Styles.vcsSettings))\n                        SettingsService.OpenProjectSettings(\"Project/Version Control\");\n                }\n                return buttonX;\n            }\n\n            if (presence.revert && !presence.revertUnchanged)\n            {\n                // just a simple revert button\n                if (VersionControlActionButton(buttonRect, ref buttonX, Styles.vcsRevert))\n                {\n                    WindowRevert.Open(presence.assets);\n                    GUIUtility.ExitGUI();\n                }\n            }\n            else if (presence.revert || presence.revertUnchanged)\n            {\n                // revert + revert unchanged dropdown button\n                if (VersionControlActionDropdownButton(buttonRect, ref buttonX, Styles.vcsRevert,\n                    Styles.vcsRevertMenuNames, Styles.vcsRevertMenuActions, presence.assets))\n                {\n                    if (presence.revert)\n                    {\n                        WindowRevert.Open(presence.assets);\n                        GUIUtility.ExitGUI();\n                    }\n                }\n            }\n\n            if (presence.checkout)\n            {\n                if (VersionControlActionButton(buttonRect, ref buttonX, AssetDatabase.CanOpenAssetInEditor(presence.Editor.target.GetInstanceID()) ? Styles.vcsCheckout : Styles.vcsCheckoutMeta))\n                    CheckoutForInspector(presence.Editor.targets);\n            }\n            if (presence.add)\n            {\n                if (VersionControlActionButton(buttonRect, ref buttonX, Styles.vcsAdd))\n                    Provider.Add(presence.assets, true).Wait();\n            }\n            if (presence.submit)\n            {\n                if (VersionControlActionButton(buttonRect, ref buttonX, Styles.vcsSubmit))\n                    WindowChange.Open(presence.assets, true);\n            }\n            if (presence.@lock)\n            {\n                if (VersionControlActionButton(buttonRect, ref buttonX, Styles.vcsLock))\n                    Provider.Lock(presence.assets, true).Wait();\n            }\n            if (presence.unlock)\n            {\n                if (VersionControlActionButton(buttonRect, ref buttonX, Styles.vcsUnlock))\n                    Provider.Lock(presence.assets, false).Wait();\n            }\n\n            return buttonX;\n        }\n\n        private static bool VersionControlActionDropdownButton(Rect buttonRect, ref float buttonX, GUIContent content, GUIContent[] menuNames, GenericMenu.MenuFunction2[] menuActions, object context)\n        {\n            var dropdownStyle = Styles.vcsRevertStyle;\n            const float kDropDownButtonWidth = 20f;\n            buttonRect.width = dropdownStyle.CalcSize(content).x + 6;\n            buttonRect.x = buttonX - buttonRect.width;\n            buttonX -= buttonRect.width;\n\n            var dropDownRect = buttonRect;\n            dropDownRect.xMin = dropDownRect.xMax - kDropDownButtonWidth;\n\n            if (Event.current.type == EventType.MouseDown && dropDownRect.Contains(Event.current.mousePosition))\n            {\n                var menu = new GenericMenu();\n                for (var i = 0; i < menuNames.Length; ++i)\n                    menu.AddItem(menuNames[i], false, menuActions[i], context);\n                menu.DropDown(buttonRect);\n                Event.current.Use();\n            }\n            else\n            {\n                return GUI.Button(buttonRect, content, dropdownStyle);\n            }\n            return false;\n        }\n\n        private static bool VersionControlActionButton(Rect buttonRect, ref float buttonX, GUIContent content)\n        {\n            var buttonStyle = Styles.vcsButtonStyle;\n            buttonRect.width = buttonStyle.CalcSize(content).x;\n            buttonRect.x = buttonX - buttonRect.width;\n            buttonX -= buttonRect.width;\n            return GUI.Button(buttonRect, content, buttonStyle);\n        }\n\n        private void DrawEditors(Editor[] editors)\n        {\n            if (editorsElement == null)\n                return;\n\n            Dictionary<int, IEditorElement> mapping = null;\n\n            var selection = new HashSet<int>(Selection.instanceIDs);\n            if (m_DrawnSelection.SetEquals(selection))\n            {\n                if (editorsElement.childCount > 0 && m_DrawnSelection.Any()) // do we already have a hierarchy\n                {\n                    mapping = ProcessEditorElementsToRebuild(editors);\n                }\n            }\n            else\n            {\n                m_DrawnSelection.Clear();\n                m_DrawnSelection = selection;\n            }\n\n            if (mapping == null)\n            {\n                editorsElement.Clear();\n                m_EditorElementUpdater.Clear();\n            }\n\n            if (editors.Length == 0)\n            {\n                // Release references to prefabs so they can be removed by GC\n                m_ComponentsInPrefabSource = null;\n                return;\n            }\n\n            Editor.m_AllowMultiObjectAccess = true;\n\n            if (editors.Length > 0 && editors[0].GetInstanceID() != m_LastInitialEditorInstanceID)\n                OnTrackerRebuilt();\n            if (m_RemovedComponents == null)\n                ExtractPrefabComponents(); // needed after assembly reload (due to HashSet not being serializable)\n\n            int targetGameObjectIndex = -1;\n            GameObject targetGameObject = null;\n            if (m_ComponentsInPrefabSource != null)\n            {\n                targetGameObjectIndex = editors[0] is PrefabImporterEditor ? 1 : 0;\n                targetGameObject = (GameObject)editors[targetGameObjectIndex].target;\n            }\n\n            if (m_ComponentsInPrefabSource != null && m_RemovedComponents.Count > 0 && m_RemovedComponentDict == null)\n                DetermineInsertionPointOfVisualElementForRemovedComponent(targetGameObjectIndex, editors);\n\n            for (int editorIndex = 0; editorIndex < editors.Length; editorIndex++)\n            {\n                if (!editors[editorIndex])\n                    continue;\n                editors[editorIndex].propertyViewer = this;\n\n                VisualElement prefabsComponentElement = new VisualElement() { name = \"PrefabComponentElement\" };\n                Object target = editors[editorIndex].target;\n\n                if (m_RemovedComponentDict != null && m_RemovedComponentDict.ContainsKey(editorIndex))\n                {\n                    var objectList = m_RemovedComponentDict[editorIndex];\n                    foreach (var sourceComponent in objectList)\n                        AddRemovedPrefabComponentElement(targetGameObject, sourceComponent, prefabsComponentElement);\n                }\n\n                try\n                {\n                    var editor = editors[editorIndex];\n                    Object editorTarget = editor.targets[0];\n\n                    if (ShouldCullEditor(editors, editorIndex))\n                    {\n                        editor.isInspectorDirty = false;\n\n                        // Adds an empty IMGUIContainer to prevent infinite repainting (case 1264833).\n                        // EXCEPT for the ParticleSystemRenderer, because it prevents the ParticleSystem inspector\n                        // from working correctly when setting the Material for its renderer (case 1308966).\n                        if (!(editor.target is ParticleSystemRenderer) && (mapping == null || !mapping.TryGetValue(editor.target.GetInstanceID(),\n                            out var culledEditorContainer)))\n                        {\n                            culledEditorContainer =\n                                new UIElements.EditorElement(editorIndex, this, editors, true);\n                            editorsElement.Add(culledEditorContainer as VisualElement);\n\n                            if (!InspectorElement.disabledThrottling)\n                                m_EditorElementUpdater.Add(culledEditorContainer);\n                        }\n\n                        continue;\n                    }\n\n                    if (mapping == null || !mapping.TryGetValue(editors[editorIndex].target.GetInstanceID(), out var editorContainer))\n                    {\n                        editorContainer = new UIElements.EditorElement(editorIndex, this, editors);\n                        editorsElement.Add(editorContainer as VisualElement);\n                        if (!InspectorElement.disabledThrottling)\n                            m_EditorElementUpdater.Add(editorContainer);\n                    }\n\n                    if (prefabsComponentElement.childCount > 0)\n                    {\n                        editorContainer.AddPrefabComponent(prefabsComponentElement);\n                    }\n                    else\n                    {\n                        editorContainer.AddPrefabComponent(null);\n                    }\n                }\n                catch (Editor.SerializedObjectNotCreatableException)\n                {\n                    // This can happen after a domain reload when the\n                    // target is a pure c# object, like a MonoBehaviour\n                    // We'll just attempt to recreate the EditorElement on the next frame\n                    // see case 1147234\n                    // For some reasons the case 1302872 is also triggering that code but does not force an inspector rebuild.\n                    // Adding a delayed call to make sure a rebuild is done regardless of the magic happening behind it.\n                    EditorApplication.delayCall += InspectorWindow.RefreshInspectors;\n                }\n            }\n\n            // Make sure to display any remaining removed components that come after the last component on the GameObject.\n            if (m_AdditionalRemovedComponents != null && m_AdditionalRemovedComponents.Count() > 0)\n            {\n                VisualElement prefabsComponentElement = new VisualElement() { name = \"RemainingPrefabComponentElement\" };\n                foreach(var sourceComponent in m_AdditionalRemovedComponents)\n                    AddRemovedPrefabComponentElement(targetGameObject, sourceComponent, prefabsComponentElement);\n\n                if (prefabsComponentElement.childCount > 0)\n                {\n                    editorsElement.Add(prefabsComponentElement);\n                    m_RemovedPrefabComponentsElement = prefabsComponentElement;\n                }\n            }\n        }\n\n        private void RestoreVerticalScrollIfNeeded()\n        {\n            if (m_LastInspectedObjectInstanceID == -1)\n                return;\n            var inspectedObjectInstanceID = GetInspectedObject()?.GetInstanceID() ?? -1;\n            if (inspectedObjectInstanceID == m_LastInspectedObjectInstanceID && inspectedObjectInstanceID != -1)\n                m_ScrollView.verticalScroller.value = m_LastVerticalScrollValue;\n            m_LastInspectedObjectInstanceID = -1; // reset to make sure the restore occurs once\n        }\n\n        void OnPrefabInstanceUnpacked(GameObject unpackedPrefabInstance, PrefabUnpackMode unpackMode)\n        {\n            if (m_RemovedComponents == null)\n                return;\n\n            // We don't use the input 'unpackedPrefabInstance', instead we reuse the ExtractPrefabComponents logic to detect\n            // if RebuildContentsContainers if actually needed to clear any \"Component Name (Removed)\" title headers.\n            // This prevents performance issues when unpacking a large multiselection.\n            var prevRemovedComponents = new HashSet<Component>(m_RemovedComponents);\n            ExtractPrefabComponents();\n            if (!prevRemovedComponents.SetEquals(m_RemovedComponents))\n            {\n                RebuildContentsContainers();\n            }\n        }\n\n        private void AddRemovedPrefabComponentElement(GameObject targetGameObject, Component nextInSource, VisualElement element)\n        {\n            if (ShouldDisplayRemovedComponent(targetGameObject, nextInSource))\n            {\n                string missingComponentTitle = ObjectNames.GetInspectorTitle(nextInSource);\n                var removedComponentElement =\n                    CreateIMGUIContainer(() => DisplayRemovedComponent(targetGameObject, nextInSource), missingComponentTitle);\n                removedComponentElement.style.paddingBottom = kEditorElementPaddingBottom;\n\n                element.Add(removedComponentElement);\n            }\n        }\n\n        private bool ShouldDisplayRemovedComponent(GameObject go, Component comp)\n        {\n            if (m_ComponentsInPrefabSource == null || m_RemovedComponents == null)\n                return false;\n            if (go == null)\n                return false;\n            if (comp == null)\n                return false;\n            if ((comp.hideFlags & HideFlags.HideInInspector) != 0)\n                return false;\n            if (!m_RemovedComponents.Contains(comp))\n                return false;\n            if (comp.IsCoupledComponent())\n                return false;\n\n            return true;\n        }\n\n        private static void DisplayRemovedComponent(GameObject go, Component comp)\n        {\n            Rect rect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar);\n            EditorGUI.RemovedComponentTitlebar(rect, go, comp);\n        }\n\n        public bool WasEditorVisible(Editor[] editors, int editorIndex, Object target)\n        {\n            int wasVisibleState = tracker.GetVisible(editorIndex);\n            bool wasVisible;\n\n            if (wasVisibleState == -1)\n            {\n                // Some inspectors (MaterialEditor) needs to be told when they are the main visible asset.\n                if (editorIndex == 0 || (editorIndex == 1 && ShouldCullEditor(editors, 0)))\n                {\n                    editors[editorIndex].firstInspectedEditor = true;\n                }\n\n                // Init our state with last state\n                // Large headers should always be considered visible\n                // because they need to at least update their Icons when they have a static preview (Material for exemple)\n                wasVisible = InternalEditorUtility.GetIsInspectorExpanded(target) || EditorHasLargeHeader(editorIndex, editors);\n                tracker.SetVisible(editorIndex, wasVisible ? 1 : 0);\n            }\n            else\n            {\n                wasVisible = wasVisibleState == 1;\n            }\n\n            return wasVisible;\n        }\n\n        public static bool IsMultiEditingSupported(Editor editor, Object target, InspectorMode mode)\n        {\n            // Culling of editors that can't be properly shown.\n            // If the current editor is a GenericInspector even though a custom editor for it exists,\n            // then it's either a fallback for a custom editor that doesn't support multi-object editing,\n            // or we're in debug mode.\n            bool multiEditingSupported = true;\n            if (editor is GenericInspector && CustomEditorAttributes.FindCustomEditorType(target, false) != null)\n            {\n                if (mode == InspectorMode.DebugInternal)\n                {\n                    // Do nothing\n                }\n                else if (mode == InspectorMode.Normal)\n                {\n                    // If we're not in debug mode and it thus must be a fallback,\n                    // hide the editor and show a notification.\n                    multiEditingSupported = false;\n                }\n                else if (target is AssetImporter)\n                {\n                    // If we are in debug mode and it's an importer type,\n                    // hide the editor and show a notification.\n                    multiEditingSupported = false;\n                }\n\n                // If we are in debug mode and it's an NOT importer type,\n                // just show the debug inspector as usual.\n            }\n\n            return multiEditingSupported;\n        }\n\n        internal static bool EditorHasLargeHeader(int editorIndex, Editor[] trackerActiveEditors)\n        {\n            return trackerActiveEditors[editorIndex].firstInspectedEditor || trackerActiveEditors[editorIndex].HasLargeHeader();\n        }\n\n        public bool ShouldCullEditor(Editor[] editors, int editorIndex)\n        {\n            if (EditorUtility.IsHiddenInInspector(editors[editorIndex]))\n                return true;\n\n            Object currentTarget = editors[editorIndex].target;\n\n            // Editors that should always be hidden\n            if (currentTarget is ParticleSystemRenderer\n                || currentTarget is UnityEngine.VFX.VFXRenderer)\n                return true;\n\n            // Hide regular AssetImporters (but not inherited types)\n            if (currentTarget != null && currentTarget.GetType() == typeof(AssetImporter))\n                return true;\n\n            // Let asset importers decide if the imported object should be shown or not\n            if (m_InspectorMode == InspectorMode.Normal && editorIndex != 0)\n            {\n                AssetImporterEditor importerEditor = GetAssetImporter(editors);\n                if (importerEditor != null && !importerEditor.showImportedObject)\n                    return true;\n            }\n\n            return false;\n        }\n\n        public override void SaveChanges()\n        {\n            base.SaveChanges();\n            foreach (var editor in tracker.activeEditors)\n            {\n                editor.SaveChanges();\n            }\n        }\n\n        public override void DiscardChanges()\n        {\n            base.DiscardChanges();\n            foreach (var editor in tracker.activeEditors)\n            {\n                editor.DiscardChanges();\n            }\n        }\n\n        public void UnsavedChangesStateChanged(Editor editor, bool value)\n        {\n            tracker.UnsavedChangesStateChanged(editor, value);\n            hasUnsavedChanges = tracker.hasUnsavedChanges;\n            if (hasUnsavedChanges)\n            {\n                StringBuilder str = new StringBuilder();\n                foreach (var activeEditor in tracker.activeEditors)\n                {\n                    if (activeEditor.hasUnsavedChanges)\n                    {\n                        str.AppendLine(activeEditor.saveChangesMessage);\n                    }\n                }\n                saveChangesMessage = str.ToString();\n            }\n            else\n            {\n                saveChangesMessage = string.Empty;\n            }\n        }\n\n        [RequiredByNativeCode]\n        private static bool PrivateRequestRebuild(ActiveEditorTracker tracker)\n        {\n            foreach (var inspector in Resources.FindObjectsOfTypeAll<PropertyEditor>())\n            {\n                if (inspector.tracker.Equals(tracker))\n                {\n                    return ContainerWindow.CanClose(inspector);\n                }\n            }\n\n            return true;\n        }\n\n        private void DrawSelectionPickerList()\n        {\n            if (m_TypeSelectionList == null)\n                m_TypeSelectionList = new TypeSelectionList(Selection.objects);\n\n            // Force header to be flush with the top of the window\n            GUILayout.Space(0);\n\n            Editor.DrawHeaderGUI(null, Selection.objects.Length + \" Objects\");\n\n            GUILayout.Label(\"Narrow the Selection:\", EditorStyles.label);\n            GUILayout.Space(4);\n\n            Vector2 oldSize = EditorGUIUtility.GetIconSize();\n            EditorGUIUtility.SetIconSize(new Vector2(16, 16));\n\n            foreach (TypeSelection ts in m_TypeSelectionList.typeSelections)\n            {\n                Rect r = GUILayoutUtility.GetRect(16, 16, GUILayout.ExpandWidth(true));\n                if (GUI.Button(r, ts.label, Styles.typeSelection))\n                {\n                    Selection.objects = ts.objects;\n                    Event.current.Use();\n                }\n                if (GUIUtility.hotControl == 0)\n                    EditorGUIUtility.AddCursorRect(r, MouseCursor.Link);\n                GUILayout.Space(4);\n            }\n\n            EditorGUIUtility.SetIconSize(oldSize);\n        }\n\n        private AssetImporterEditor GetAssetImporter(Editor[] editors)\n        {\n            if (editors == null || editors.Length == 0)\n                return null;\n\n            return editors[0] as AssetImporterEditor;\n        }\n\n        private void AddComponentButton(Editor[] editors)\n        {\n            // Don't show the Add Component button if we are not showing imported objects for Asset Importers\n            var assetImporter = GetAssetImporter(editors);\n            if (assetImporter != null && !assetImporter.showImportedObject)\n                return;\n\n            Editor editor = InspectorWindowUtils.GetFirstNonImportInspectorEditor(editors);\n\n            if (editor != null && editor.target != null && editor.target is GameObject && editor.IsEnabled())\n            {\n                if (ModeService.HasExecuteHandler(\"inspector_read_only\") && ModeService.Execute(\"inspector_read_only\", editor.target))\n                    return;\n\n                EditorGUILayout.BeginHorizontal(GUIContent.none, GUIStyle.none, GUILayout.Height(kAddComponentButtonHeight));\n                {\n                    GUILayout.FlexibleSpace();\n                    var content = Styles.addComponentLabel;\n                    Rect rect = GUILayoutUtility.GetRect(content, Styles.addComponentButtonStyle);\n\n                    // Visually separates the Add Component button from the existing components\n                    if (Event.current.type == EventType.Repaint)\n                        DrawSplitLine(rect.y);\n                    rect.y += 9;\n\n                    if (EditorGUI.DropdownButton(rect, content, FocusType.Passive, Styles.addComponentButtonStyle) ||\n                        m_OpenAddComponentMenu && Event.current.type == EventType.Repaint)\n                    {\n                        m_OpenAddComponentMenu = false;\n                        if (AddComponentWindow.Show(rect, editor.targets.Cast<GameObject>().Where(o => o).ToArray()))\n                        {\n                            // Repaint the inspector window to ensure the AddComponentWindow.Show\n                            // does not clear the inspector window gl buffer, which blacks out the inspector window.\n                            this.RepaintImmediately();\n                            GUIUtility.ExitGUI();\n                        }\n                    }\n\n                    GUILayout.FlexibleSpace();\n                }\n                EditorGUILayout.EndHorizontal();\n            }\n        }\n\n        private bool ReadyToRepaint()\n        {\n            if (AnimationMode.InAnimationPlaybackMode())\n            {\n                long timeNow = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;\n                if (timeNow - m_LastUpdateWhilePlayingAnimation < delayRepaintWhilePlayingAnimation)\n                    return false;\n                m_LastUpdateWhilePlayingAnimation = timeNow;\n            }\n\n            return true;\n        }\n\n        private void DrawSplitLine(float y)\n        {\n            Rect position = new Rect(0, y - Styles.lineSeparatorOffset, m_Pos.width + 1, 1);\n            using (new GUI.ColorScope(Styles.lineSeparatorColor * GUI.color))\n                GUI.DrawTexture(position, EditorGUIUtility.whiteTexture);\n        }\n\n        private Dictionary<int, IEditorElement> ProcessEditorElementsToRebuild(Editor[] editors)\n        {\n            Dictionary<int, IEditorElement> editorToElementMap = new Dictionary<int, IEditorElement>();\n            var currentElements = editorsElement.Children().OfType<IEditorElement>().ToList();\n            if (editors.Length == 0)\n            {\n                return null;\n            }\n\n            if (rootVisualElement.panel == null)\n            {\n                return null;\n            }\n\n            var newEditorsIndex = 0;\n            var previousEditorsIndex = 0;\n            while (newEditorsIndex < editors.Length && previousEditorsIndex < currentElements.Count)\n            {\n                var ed = editors[newEditorsIndex];\n                var currentElement = currentElements[previousEditorsIndex];\n                var currentEditor = currentElement.editor;\n\n                if (currentEditor == null)\n                {\n                    ++previousEditorsIndex;\n                    continue;\n                }\n\n                // We won't have an EditorElement for editors that are normally culled so we should skip this\n\n                if (ShouldCullEditor(editors, newEditorsIndex))\n                {\n                    // Reinit culled when editor is culled to avoid NullPointerException (case 1281347)\n                    // EXCEPT for the ParticleSystemRenderer, because it prevents the ParticleSystem inspector\n                    // from working correctly when setting the Material for its renderer (case 1308966).\n                    if (!(ed.target is ParticleSystemRenderer))\n                    {\n                        currentElement.ReinitCulled(newEditorsIndex, editors);\n                        if (!InspectorElement.disabledThrottling)\n                            m_EditorElementUpdater.Add(currentElement);\n\n                        // We need to move forward as the current element is the culled one, so we're not really\n                        // interested in it.\n                        ++previousEditorsIndex;\n                    }\n                    ++newEditorsIndex;\n                    continue;\n                }\n\n                if (currentEditor && ed.target != currentEditor.target)\n                {\n                    return null;\n                }\n\n                editors[newEditorsIndex].propertyViewer = this;\n                currentElement.Reinit(newEditorsIndex, editors);\n                if (!InspectorElement.disabledThrottling)\n                    m_EditorElementUpdater.Add(currentElement);\n                editorToElementMap[ed.target.GetInstanceID()] = currentElement;\n                ++newEditorsIndex;\n                ++previousEditorsIndex;\n            }\n\n            // Remove any elements at the end of the PropertyEditor that don't have matching Editors\n            for (int j = previousEditorsIndex; j < currentElements.Count; ++j)\n            {\n                currentElements[j].RemoveFromHierarchy();\n                m_EditorElementUpdater.Remove(currentElements[j]);\n            }\n\n            return editorToElementMap;\n        }\n\n        [UsedImplicitly, MenuItem(k_AssetPropertiesMenuItemName, validate = true)]\n        internal static bool ValidatePropertyEditorOnSelection()\n        {\n            return Selection.activeObject;\n        }\n\n        [UsedImplicitly, MenuItem(k_AssetPropertiesMenuItemName, priority = 99999)]\n        internal static void OpenPropertyEditorOnSelection()\n        {\n            OpenPropertyEditor(Selection.objects);\n        }\n\n        internal static PropertyEditor OpenPropertyEditor(IList<Object> objs)\n        {\n            if (objs == null || objs.Count == 0)\n                return null;\n\n            var firstPropertyEditor = OpenPropertyEditor(objs.First());\n            EditorApplication.delayCall += () =>\n            {\n                var dock = firstPropertyEditor.m_Parent as DockArea;\n                for (int i = 1; i < objs.Count; ++i)\n                    dock.AddTab(OpenPropertyEditor(objs[i], false));\n            };\n\n            return firstPropertyEditor;\n        }\n\n        internal static PropertyEditor OpenPropertyEditor(Object obj, bool showWindow = true)\n        {\n            if (!obj)\n                return null;\n\n            var propertyEditor = CreateInstance<PropertyEditor>();\n            propertyEditor.tracker.SetObjectsLockedByThisTracker(new List<Object> { obj });\n\n            propertyEditor.m_GlobalObjectId = GlobalObjectId.GetGlobalObjectIdSlow(obj).ToString();\n            propertyEditor.m_InspectedObject = obj;\n\n            propertyEditor.SetTitle(obj);\n            if (showWindow)\n                ShowPropertyEditorWindow(propertyEditor);\n            return propertyEditor;\n        }\n\n        private static void ShowPropertyEditorWindow(PropertyEditor propertyEditor)\n        {\n            propertyEditor.Show();\n\n            // Offset new window instance.\n            if (s_LastPropertyEditor)\n            {\n                var pos = s_LastPropertyEditor.position;\n                propertyEditor.position = new Rect(pos.x + 30, pos.y + 30, propertyEditor.position.width, propertyEditor.position.height);\n            }\n            s_LastPropertyEditor = propertyEditor;\n        }\n\n        [ShortcutManagement.Shortcut(\"PropertyEditor/OpenMouseOver\")]\n        static void OpenHoveredItemPropertyEditor(ShortcutManagement.ShortcutArguments args)\n        {\n            var windows = Resources.FindObjectsOfTypeAll<EditorWindow>();\n            if (windows.Length == 0)\n                return;\n\n            foreach (var w in windows)\n            {\n                var pso = w as IPropertySourceOpener;\n                if (pso == null)\n                    continue;\n\n                if (!w.m_Parent || !w.m_Parent.window)\n                    continue;\n\n                if (pso.hoveredObject)\n                    OpenPropertyEditor(pso.hoveredObject);\n            }\n        }\n\n        internal static DataMode GetPreferredDataMode()\n            => EditorApplication.isPlaying\n                ? DataMode.Mixed\n                : DataMode.Authoring;\n\n        List<DataMode> GetSupportedDataModes() => m_SupportedDataModes;\n\n        bool m_IsEnteringPlaymode;\n\n        void OnPlayModeStateChanged(PlayModeStateChange stateChange)\n        {\n            if (stateChange is not (PlayModeStateChange.EnteredEditMode or PlayModeStateChange.EnteredPlayMode))\n                return;\n\n            m_IsEnteringPlaymode = true;\n            UpdateSupportedDataModesList();\n        }\n\n        void OnDataModeChanged(DataModeChangeEventArgs evt)\n        {\n            tracker.dataMode = evt.nextDataMode;\n            tracker.ForceRebuild();\n        }\n\n        protected void UpdateSupportedDataModesList()\n        {\n            m_SupportedDataModes.Clear();\n            OnUpdateSupportedDataModes(m_SupportedDataModes);\n            m_SupportedDataModes.Sort();\n\n            if (m_InspectorMode != InspectorMode.Normal || m_SupportedDataModes.Count == 0)\n                m_SupportedDataModes = k_DisabledDataModes;\n\n            var dataMode = Selection.dataModeHint == DataMode.Disabled ? GetPreferredDataMode() : Selection.dataModeHint;\n\n            // When entering playmode, Inspector relies on getting selection hint\n            // from Hierarchy window to switch to the proper data mode.\n            // However when inspector is locked, selection is locked too.\n            // Here we force the preferred data mode to inspector for this special case.\n            if (m_IsEnteringPlaymode && m_Tracker.isLocked)\n            {\n                dataMode = GetPreferredDataMode();\n                m_IsEnteringPlaymode = false;\n            }\n\n            dataModeController.UpdateSupportedDataModes(m_SupportedDataModes, dataMode);\n        }\n\n        protected virtual void OnUpdateSupportedDataModes(List<DataMode> supportedModes)\n        {\n            // Override me\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/RootEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing JetBrains.Annotations;\nusing UnityEngine.Internal;\nusing UnityEngine.Pool;\nusing UnityEngine.Scripting;\n\nusing RootEditorHandler = UnityEditor.RootEditorAttribute.RootEditorHandler;\nusing RootEditorWithMetaDataHandler = UnityEditor.RootEditorAttribute.RootEditorWithMetaDataHandler;\n\nnamespace UnityEditor\n{\n    [ExcludeFromDocs]\n    public class RootEditorAttribute : System.Attribute\n    {\n        public delegate System.Type RootEditorHandler(UnityEngine.Object[] objects);\n        internal delegate System.Type RootEditorWithMetaDataHandler(UnityEngine.Object[] objects, UnityEngine.Object context, DataMode dataMode);\n\n        public bool supportsAddComponent;\n        public RootEditorAttribute(bool supportsAddComponent = false)\n        {\n            this.supportsAddComponent = supportsAddComponent;\n        }\n\n        [RequiredSignature]\n        private static System.Type signature(UnityEngine.Object[] objects)\n        {\n            return null;\n        }\n\n        [RequiredSignature]\n        private static System.Type signature(UnityEngine.Object[] objects, UnityEngine.Object context, DataMode dataMode)\n        {\n            return null;\n        }\n    }\n\n    internal static class RootEditorUtils\n    {\n        class RootEditorDesc\n        {\n            public RootEditorHandler rootEditorHandler;\n            public RootEditorWithMetaDataHandler rootEditorWithMetaDataHandler;\n\n            public Type rootEditorType;\n            public bool supportsAddComponent;\n            public bool usesMetaData;\n        }\n\n        private static bool s_SuppressRootEditor = false;\n        private static readonly List<RootEditorDesc> kSRootEditor = new List<RootEditorDesc>();\n\n        static RootEditorUtils()\n        {\n            Rebuild();\n        }\n\n        internal static Editor CreateNonRootEditor(UnityEngine.Object[] objects)\n        {\n            try\n            {\n                s_SuppressRootEditor = true;\n                return Editor.CreateEditor(objects);\n            }\n            finally\n            {\n                s_SuppressRootEditor = false;\n            }\n        }\n\n        internal static bool SupportsAddComponent(Editor[] editors)\n        {\n            if (editors.Length != 1)\n                return true;\n\n            foreach (var e in editors)\n            {\n                var fittingRootEditor = kSRootEditor.FirstOrDefault(rootEditor => rootEditor.rootEditorType == e.GetType());\n                if (fittingRootEditor == null)\n                    continue;\n                return fittingRootEditor.supportsAddComponent;\n            }\n            return false;\n        }\n\n        [UsedByNativeCode, UsedImplicitly] // Currently, only called from native\n        internal static Type FindRootEditor(UnityEngine.Object[] objects, UnityEngine.Object context, DataMode dataMode)\n        {\n            if (s_SuppressRootEditor)\n                return null;\n\n            foreach (var desc in kSRootEditor)\n            {\n                var rootEditorType = desc.usesMetaData\n                    ? desc.rootEditorWithMetaDataHandler(objects, context, dataMode)\n                    : desc.rootEditorHandler(objects);\n\n                if (rootEditorType != null)\n                {\n                    desc.rootEditorType = rootEditorType;\n                    return rootEditorType;\n                }\n            }\n\n            return null;\n        }\n\n        internal static void Rebuild()\n        {\n            var rootEditors = ListPool<RootEditorDesc>.Get();\n            var rootEditorsWithMetaData = ListPool<RootEditorDesc>.Get();\n\n            var candidates = TypeCache.GetMethodsWithAttribute<RootEditorAttribute>();\n            var attributeType = typeof(RootEditorAttribute);\n            foreach (var candidate in candidates)\n            {\n                if (!AttributeHelper.MethodMatchesAnyRequiredSignatureOfAttribute(candidate, attributeType))\n                    continue;\n\n                var attribute = candidate.GetCustomAttribute<RootEditorAttribute>(false);\n                var desc = new RootEditorDesc { supportsAddComponent = attribute.supportsAddComponent };\n\n                if (Delegate.CreateDelegate(typeof(RootEditorHandler), candidate, false) is RootEditorHandler handler)\n                {\n                    desc.usesMetaData = false;\n                    desc.rootEditorHandler = handler;\n                    rootEditors.Add(desc);\n                }\n                else if (Delegate.CreateDelegate(typeof(RootEditorWithMetaDataHandler), candidate, false) is RootEditorWithMetaDataHandler handlerWithMetaData)\n                {\n                    desc.usesMetaData = true;\n                    desc.rootEditorWithMetaDataHandler = handlerWithMetaData;\n                    rootEditorsWithMetaData.Add(desc);\n                }\n                else\n                {\n                    var parameters = candidate.GetParameters();\n                    var signature = parameters is { Length: > 0 }\n                        ? string.Join(\", \", parameters.Select(p => p.ParameterType.FullName).ToArray())\n                        : string.Empty;\n                    throw new InvalidOperationException($\"Could not create a valid delegate from method marked: [{nameof(RootEditorAttribute)}] with signature: ({signature})\");\n                }\n            }\n\n            kSRootEditor.Clear();\n\n            // Adding the root editors with metadata first to take precedence over the general version\n            kSRootEditor.AddRange(rootEditorsWithMetaData);\n            kSRootEditor.AddRange(rootEditors);\n\n            ListPool<RootEditorDesc>.Release(rootEditors);\n            ListPool<RootEditorDesc>.Release(rootEditorsWithMetaData);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/ScriptAttributeGUI/CustomPropertyDrawerAttribute.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor\n{\n    // Tells a custom [[PropertyDrawer]] which run-time [[Serializable]] class or [[PropertyAttribute]] it's a drawer for.\n    [System.AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]\n    public sealed class CustomPropertyDrawer : Attribute\n    {\n        internal Type m_Type;\n        internal bool m_UseForChildren;\n\n        // Tells a PropertyDrawer class which run-time class or attribute it's a drawer for.\n        public CustomPropertyDrawer(Type type)\n        {\n            m_Type = type;\n        }\n\n        // Tells a PropertyDrawer class which run-time class or attribute it's a drawer for.\n        public CustomPropertyDrawer(Type type, bool useForChildren)\n        {\n            m_Type = type;\n            m_UseForChildren = useForChildren;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/ScriptAttributeGUI/DecoratorDrawer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    // Base class to derive custom decorator drawers from.\n    public abstract class DecoratorDrawer : GUIDrawer\n    {\n        internal PropertyAttribute m_Attribute;\n\n        // The [[PropertyAttribute]] for the property.\n        public PropertyAttribute attribute { get { return m_Attribute; } }\n\n        // Override this method to make your own GUI for the property.\n        public virtual void OnGUI(Rect position)\n        {\n        }\n\n        /// <summary>\n        /// Override this method to make your own GUI for the property based on UIElements.\n        /// </summary>\n        public virtual VisualElement CreatePropertyGUI()\n        {\n            return null;\n        }\n\n        // Override this method to specify how tall the GUI for this field is in pixels.\n        public virtual float GetHeight()\n        {\n            return EditorGUI.kSingleLineHeight;\n        }\n\n        [Obsolete(\"CanCacheInspectorGUI has been deprecated and is no longer used.\", false)]\n        public virtual bool CanCacheInspectorGUI()\n        {\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/ScriptAttributeGUI/GUIDrawer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor\n{\n    // Base class for both PropertyDrawer and DecoratorDrawer.\n    public abstract class GUIDrawer {}\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/ScriptAttributeGUI/Implementations/DecoratorDrawers.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    // Built-in DecoratorDrawers. See matching attributes in PropertyAttribute.cs\n\n    [CustomPropertyDrawer(typeof(SpaceAttribute))]\n    internal sealed class SpaceDrawer : DecoratorDrawer\n    {\n        public const string spaceDrawerClassName = \"unity-space-drawer\";\n\n        public override float GetHeight()\n        {\n            return (attribute as SpaceAttribute).height;\n        }\n\n        public override VisualElement CreatePropertyGUI()\n        {\n            var spaceElement = new VisualElement();\n            spaceElement.AddToClassList(spaceDrawerClassName);\n\n            spaceElement.style.height = GetHeight();\n\n            return spaceElement;\n        }\n    }\n\n    [CustomPropertyDrawer(typeof(HeaderAttribute))]\n    internal sealed class HeaderDrawer : DecoratorDrawer\n    {\n        public const string headerLabelClassName = \"unity-header-drawer__label\";\n\n        public override void OnGUI(Rect position)\n        {\n            position.yMin += EditorGUIUtility.singleLineHeight * 0.5f;\n            position = EditorGUI.IndentedRect(position);\n            GUI.Label(position, (attribute as HeaderAttribute).header, EditorStyles.boldLabel);\n        }\n\n        public override float GetHeight()\n        {\n            float fullTextHeight = EditorStyles.boldLabel.CalcHeight(GUIContent.Temp((attribute as HeaderAttribute).header), 1.0f);\n            int lines = 1;\n            if ((attribute as HeaderAttribute).header != null)\n                lines = (attribute as HeaderAttribute).header.Count(a => a == '\\n') + 1;\n            float eachLineHeight = fullTextHeight / lines;\n            return EditorGUIUtility.singleLineHeight * 1.5f + (eachLineHeight * (lines - 1));\n        }\n\n        public override VisualElement CreatePropertyGUI()\n        {\n            var text = (attribute as HeaderAttribute).header;\n            var label = new Label(text);\n\n            label.AddToClassList(headerLabelClassName);\n\n            return label;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/ScriptAttributeGUI/Implementations/ExposedReferenceDrawer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEditor.UIElements;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing ObjectField = UnityEditor.UIElements.ObjectField;\nusing Object = UnityEngine.Object;\n\nabstract class BaseExposedPropertyDrawer : UnityEditor.PropertyDrawer\n{\n    private static float kDriveWidgetWidth = 18.0f;\n    private static GUIStyle kDropDownStyle = null;\n    private static Color kMissingOverrideColor = new Color(1.0f, 0.11f, 0.11f, 1.0f);\n    protected static string kSetExposedPropertyMsg = \"Set Exposed Property\";\n    protected static string kClearExposedPropertyMsg = \"Clear Exposed Property\";\n    internal  const string kVisualElementName = \"ExposedReference\";\n\n    internal readonly GUIContent ExposePropertyContent = EditorGUIUtility.TrTextContent(\"Expose Property\");\n    internal readonly GUIContent UnexposePropertyContent = EditorGUIUtility.TrTextContent(\"Unexpose Property\");\n    protected readonly GUIContent NotFoundOn = EditorGUIUtility.TrTextContent(\"not found on\");\n    protected readonly GUIContent OverridenByContent = EditorGUIUtility.TrTextContent(\"Overridden by \");\n\n    private GUIContent m_ModifiedLabel = new GUIContent();\n\n    internal enum ExposedPropertyMode\n    {\n        DefaultValue,\n        Named,\n        NamedGUID\n    }\n\n    internal enum OverrideState\n    {\n        DefaultValue,\n        MissingOverride,\n        Overridden\n    }\n\n    ExposedReferenceObject m_Item;\n\n    public BaseExposedPropertyDrawer()\n    {\n        if (kDropDownStyle == null)\n            kDropDownStyle = \"ShurikenDropdown\";\n    }\n\n    static internal ExposedPropertyMode GetExposedPropertyMode(string propertyName)\n    {\n        if (string.IsNullOrEmpty(propertyName))\n            return ExposedPropertyMode.DefaultValue;\n        else\n        {\n            GUID guid;\n            if (GUID.TryParse(propertyName, out guid))\n                return ExposedPropertyMode.NamedGUID;\n            else\n                return ExposedPropertyMode.Named;\n        }\n    }\n\n    protected IExposedPropertyTable GetExposedPropertyTable(SerializedProperty property)\n    {\n        var t = property.serializedObject.context;\n        return t as IExposedPropertyTable;\n    }\n\n    protected abstract void OnRenderProperty(Rect position,\n        PropertyName exposedPropertyNameString,\n        Object currentReferenceValue,\n        UnityEditor.SerializedProperty exposedPropertyDefault,\n        UnityEditor.SerializedProperty exposedPropertyName,\n        ExposedPropertyMode mode,\n        IExposedPropertyTable exposedProperties);\n\n    public override void OnGUI(Rect position,\n        UnityEditor.SerializedProperty prop,\n        GUIContent label)\n    {\n        m_Item = new ExposedReferenceObject(prop);\n\n        Rect propertyFieldPosition = position;\n        propertyFieldPosition.xMax = propertyFieldPosition.xMax - ExposedReferencePropertyDrawer.kDriveWidgetWidth;\n\n        Rect driveFieldPosition = position;\n        driveFieldPosition.x = propertyFieldPosition.xMax;\n        driveFieldPosition.width = ExposedReferencePropertyDrawer.kDriveWidgetWidth;\n\n        bool showContextMenu = m_Item.exposedPropertyTable != null;\n        var propertyName = new PropertyName(m_Item.exposedPropertyNameString);\n\n        var previousColor = GUI.color;\n        var wasBoldDefaultFont = EditorGUIUtility.GetBoldDefaultFont();\n\n        var valuePosition = DrawLabel(showContextMenu, label, position, m_Item);\n        var indent = EditorGUI.indentLevel;\n        EditorGUI.indentLevel = 0;\n\n        if (m_Item.propertyMode == ExposedPropertyMode.DefaultValue || m_Item.propertyMode == ExposedPropertyMode.NamedGUID)\n        {\n            OnRenderProperty(valuePosition, propertyName, m_Item.currentReferenceValue, m_Item.exposedPropertyDefault,\n                m_Item.exposedPropertyName,\n                m_Item.propertyMode, m_Item.exposedPropertyTable);\n        }\n        else\n        {\n            valuePosition.width /= 2;\n            EditorGUI.BeginChangeCheck();\n            m_Item.exposedPropertyNameString = EditorGUI.TextField(valuePosition, m_Item.exposedPropertyNameString);\n            if (EditorGUI.EndChangeCheck())\n                m_Item.exposedPropertyName.stringValue = m_Item.exposedPropertyNameString;\n\n            valuePosition.x += valuePosition.width;\n            OnRenderProperty(valuePosition, new PropertyName(m_Item.exposedPropertyNameString),\n                m_Item.currentReferenceValue, m_Item.exposedPropertyDefault,\n                m_Item.exposedPropertyName, m_Item.propertyMode, m_Item.exposedPropertyTable);\n        }\n\n        GUI.color = previousColor;\n        EditorGUIUtility.SetBoldDefaultFont(wasBoldDefaultFont);\n\n        if (showContextMenu && GUI.Button(driveFieldPosition, GUIContent.none, kDropDownStyle))\n        {\n            GenericMenu menu = new GenericMenu();\n            PopulateContextMenu(menu, m_Item);\n            menu.ShowAsContext();\n            Event.current.Use();\n        }\n\n        EditorGUI.indentLevel = indent;\n    }\n\n    public override VisualElement CreatePropertyGUI(SerializedProperty prop)\n    {\n        m_Item = new ExposedReferenceObject(prop);\n\n        var propertyType = fieldInfo.FieldType;\n\n        if (propertyType.IsArrayOrList())\n        {\n            propertyType = propertyType.GetArrayOrListElementType();\n        }\n\n        var typeOfExposedReference = propertyType.GetGenericArguments()[0];\n\n        ObjectField obj = new ObjectField()\n        {\n            name = kVisualElementName,\n            label = preferredLabel,\n            objectType = typeOfExposedReference,\n            value = m_Item.currentReferenceValue,\n            allowSceneObjects = m_Item.exposedPropertyTable != null\n        };\n\n        obj.RegisterValueChangedCallback(SetReference);\n        obj.AddManipulator(new ContextualMenuManipulator(BuildContextualMenu));\n        obj.AddToClassList(ObjectField.alignedFieldUssClassName);\n\n        // Track for Undo/Redo changes which can come from exposedPropertyTable\n        Undo.UndoRedoCallback undoRedoCallback = () =>\n        {\n            m_Item.UpdateValue();\n            obj.SetValueWithoutNotify(m_Item.currentReferenceValue);\n        };\n\n        // Track the property for external changed including Undo/Redo\n        obj.TrackPropertyValue(prop, _ => undoRedoCallback());\n        obj.RegisterCallback<AttachToPanelEvent>(evt => Undo.undoRedoPerformed += undoRedoCallback);\n        obj.RegisterCallback<DetachFromPanelEvent>(evt => Undo.undoRedoPerformed -= undoRedoCallback);\n\n        // Set the serialized property so we can support drag and drop\n        obj.SetProperty(ObjectField.serializedPropertyKey, m_Item.exposedPropertyDefault);\n\n        return obj;\n    }\n\n    // Used for tests only\n\n    internal void InitForNamedGUIDTests(SerializedProperty prop)\n    {\n        m_Item = new ExposedReferenceObject(prop);\n        m_Item.propertyMode = ExposedPropertyMode.NamedGUID;\n    }\n    // Used for tests only\n\n    internal Object GetObjectReferenceValue()\n    {\n        return m_Item.exposedPropertyDefault.objectReferenceValue;\n    }\n\n    void SetReference(ChangeEvent<Object> evt)\n    {\n        SetReference(evt.newValue);\n        if (m_Item.currentReferenceValue != evt.newValue)\n        {\n            m_Item.currentReferenceValue = evt.newValue;\n\n            //save the modified SerializedObject since we are bypassing the binding system\n            m_Item.exposedPropertyName.serializedObject.ApplyModifiedProperties();\n        }\n    }\n\n    internal void SetReference(Object newValue)\n    {\n        bool isDefaultValueMode = m_Item.propertyMode == ExposedPropertyMode.DefaultValue;\n        if (isDefaultValueMode || m_Item.propertyMode == ExposedPropertyMode.NamedGUID)\n        {\n            // We can directly assign to the exposed property default value if\n            // * asset we are modifying is in the scene\n            // * object we are assigning to the property is also an asset\n            if (isDefaultValueMode && (!EditorUtility.IsPersistent(m_Item.exposedPropertyDefault.serializedObject.targetObject) ||\n                newValue == null || EditorUtility.IsPersistent(newValue)))\n            {\n                if (!EditorGUI.CheckForCrossSceneReferencing(\n                        m_Item.exposedPropertyDefault.serializedObject.targetObject, newValue))\n                {\n                    m_Item.exposedPropertyDefault.objectReferenceValue = newValue;\n                }\n            }\n            else\n            {\n                // If PropertyName already exists, re-use it UUM-25160\n                if (String.IsNullOrEmpty(m_Item.exposedPropertyNameString) || String.IsNullOrEmpty(m_Item.exposedPropertyName.stringValue))\n                {\n                    var str = UnityEditor.GUID.Generate().ToString();\n                    m_Item.exposedPropertyNameString = str;\n                    m_Item.exposedPropertyName.stringValue = str;\n                    m_Item.propertyMode = ExposedPropertyMode.NamedGUID;\n                }\n\n                // Timeline uses ExposedReference to hold both exposed and regular references, make sure we handle them differently\n                if (m_Item.isExposedReference)\n                    SetAsExposedReference(newValue);\n                else\n                    SetAsRegularReference(newValue);\n            }\n        }\n        else\n        {\n            if (m_Item.isExposedReference)\n                SetAsExposedReference(newValue);\n            else\n                SetAsRegularReference(newValue);\n        }\n    }\n\n    void SetAsExposedReference(Object value)\n    {\n        Undo.RecordObject(m_Item.exposedPropertyTable as UnityEngine.Object, kSetExposedPropertyMsg);\n        m_Item.exposedPropertyTable.SetReferenceValue(m_Item.exposedPropertyNameString, value);\n    }\n\n    void SetAsRegularReference(Object value)\n    {\n        if (m_Item.currentReferenceValue)\n            Undo.RecordObject(m_Item.exposedPropertyDefault.serializedObject.targetObject, kSetExposedPropertyMsg);\n\n        m_Item.exposedPropertyDefault.objectReferenceValue = value;\n    }\n\n\n    Rect DrawLabel(bool showContextMenu, GUIContent label, Rect position, ExposedReferenceObject item)\n    {\n        if (showContextMenu)\n        {\n            position.xMax = position.xMax - ExposedReferencePropertyDrawer.kDriveWidgetWidth;\n        }\n\n        EditorGUIUtility.SetBoldDefaultFont(item.currentOverrideState != OverrideState.DefaultValue);\n\n        m_ModifiedLabel.text = label.text;\n        m_ModifiedLabel.tooltip = label.tooltip;\n        m_ModifiedLabel.image = label.image;\n\n        if (!string.IsNullOrEmpty(m_ModifiedLabel.tooltip))\n        {\n            m_ModifiedLabel.tooltip += \"\\n\";\n        }\n\n        if (item.currentOverrideState == OverrideState.MissingOverride)\n        {\n            GUI.color = kMissingOverrideColor;\n            m_ModifiedLabel.tooltip += label.text + \" \" + NotFoundOn.text + \" \" + item.exposedPropertyTable + \".\";\n        }\n        else if (item.currentOverrideState == OverrideState.Overridden && item.exposedPropertyTable != null)\n        {\n            m_ModifiedLabel.tooltip += OverridenByContent.text + item.exposedPropertyTable + \".\";\n        }\n\n        var prefixRect = EditorGUI.PrefixLabel(position, m_ModifiedLabel);\n\n        // Show contextual menu\n        if (item.exposedPropertyTable != null && Event.current.type == EventType.ContextClick)\n        {\n            if (position.Contains(Event.current.mousePosition))\n            {\n                GenericMenu menu = new GenericMenu();\n                item.currentOverrideState = string.IsNullOrEmpty(item.exposedPropertyNameString) ? OverrideState.DefaultValue : OverrideState.Overridden;\n                PopulateContextMenu(menu, item);\n                menu.ShowAsContext();\n            }\n        }\n\n        return prefixRect;\n    }\n\n    protected abstract void PopulateContextMenu(GenericMenu menu, ExposedReferenceObject item);\n\n    // UITK context menu\n    void BuildContextualMenu(ContextualMenuPopulateEvent evt)\n    {\n        if (m_Item != null && m_Item.exposedPropertyTable != null)\n        {\n            OverrideState currentOverrideState;\n            var currentValue = m_Item.Resolve(out currentOverrideState);\n\n            if (m_Item.currentOverrideState == OverrideState.DefaultValue)\n            {\n                evt.menu.AppendAction(ExposePropertyContent.text,\n                    (userData) =>\n                    {\n                        ExposedReferencePropertyDrawer.SetReferenceValueMenuItem(m_Item.exposedPropertyTable,\n                            m_Item.exposedPropertyName, currentValue);\n                    });\n            }\n            else\n            {\n                evt.menu.AppendAction(UnexposePropertyContent.text, (userData) =>\n                {\n                    ExposedReferencePropertyDrawer.ClearReferenceValueMenuItem(m_Item.exposedPropertyTable,\n                        m_Item.exposedPropertyName, new PropertyName(m_Item.exposedPropertyName.stringValue));\n                });\n            }\n        }\n\n        evt.menu.AppendAction(\"Properties...\",\n            (userData) =>\n            {\n                UnityEditor.EditorUtility.OpenPropertyEditor(m_Item.currentReferenceValue);\n            });\n    }\n}\n\n[CustomPropertyDrawer(typeof(ExposedReference<>))]\nclass ExposedReferencePropertyDrawer : BaseExposedPropertyDrawer\n{\n    protected override void OnRenderProperty(Rect position,\n        PropertyName exposedPropertyNameString,\n        Object currentReferenceValue,\n        UnityEditor.SerializedProperty exposedPropertyDefault,\n        UnityEditor.SerializedProperty exposedPropertyName,\n        ExposedPropertyMode mode,\n        IExposedPropertyTable exposedPropertyTable)\n    {\n        var propertyType = fieldInfo.FieldType;\n\n        if (propertyType.IsArrayOrList())\n        {\n            propertyType = propertyType.GetArrayOrListElementType();\n        }\n\n        var typeOfExposedReference = propertyType.GetGenericArguments()[0];\n\n        EditorGUI.BeginChangeCheck();\n        var newValue = EditorGUI.ObjectField(position, currentReferenceValue, typeOfExposedReference,\n            exposedPropertyTable != null);\n\n        if (EditorGUI.EndChangeCheck())\n        {\n            SetReference(newValue);\n        }\n    }\n\n    protected override void PopulateContextMenu(GenericMenu menu, ExposedReferenceObject item)\n    {\n        var propertyName = new PropertyName(item.exposedPropertyName.stringValue);\n        OverrideState currentOverrideState;\n        UnityEngine.Object currentValue = item.Resolve(out currentOverrideState);\n\n        if (item.currentOverrideState == OverrideState.DefaultValue)\n        {\n            menu.AddItem(new GUIContent(ExposePropertyContent.text), false,\n                (userData) => { SetReferenceValueMenuItem(item.exposedPropertyTable, item.exposedPropertyName, currentValue); }, null);\n        }\n        else\n        {\n            menu.AddItem(UnexposePropertyContent, false,\n                (userData) => { ClearReferenceValueMenuItem(item.exposedPropertyTable, item.exposedPropertyName, propertyName); }, null);\n        }\n    }\n\n    internal static void SetReferenceValueMenuItem(IExposedPropertyTable exposedPropertyTable,\n        SerializedProperty exposedName, Object currentValue)\n    {\n        var guid = UnityEditor.GUID.Generate();\n        exposedName.stringValue = guid.ToString();\n        exposedName.serializedObject.ApplyModifiedProperties();\n        var newPropertyName = new PropertyName(exposedName.stringValue);\n\n        Undo.RecordObject(exposedPropertyTable as Object, kSetExposedPropertyMsg);\n        exposedPropertyTable.SetReferenceValue(newPropertyName, currentValue);\n    }\n\n    internal static void ClearReferenceValueMenuItem(IExposedPropertyTable exposedPropertyTable,\n        SerializedProperty exposedName, PropertyName propertyName)\n    {\n        exposedName.stringValue = \"\";\n        exposedName.serializedObject.ApplyModifiedProperties();\n\n        Undo.RecordObject(exposedPropertyTable as Object, kClearExposedPropertyMsg);\n        exposedPropertyTable.ClearReferenceValue(propertyName);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/ScriptAttributeGUI/Implementations/ExposedReferenceObject.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class ExposedReferenceObject\n    {\n        internal string exposedPropertyNameString { get; set; }\n        internal Object currentReferenceValue { get; set; }\n        internal SerializedProperty exposedPropertyDefault { get; set; }\n        internal SerializedProperty exposedPropertyName { get; set; }\n        internal BaseExposedPropertyDrawer.ExposedPropertyMode propertyMode { get; set; }\n        internal IExposedPropertyTable exposedPropertyTable { get; set; }\n        internal bool isExposedReference = false;\n\n        internal BaseExposedPropertyDrawer.OverrideState currentOverrideState\n        {\n            get => m_CurrentOverrideState;\n            set => m_CurrentOverrideState = value;\n        }\n\n        BaseExposedPropertyDrawer.OverrideState m_CurrentOverrideState;\n\n        internal ExposedReferenceObject(SerializedProperty property)\n        {\n            exposedPropertyDefault = property.FindPropertyRelative(\"defaultValue\");\n            exposedPropertyName = property.FindPropertyRelative(\"exposedName\");\n            exposedPropertyNameString = exposedPropertyName.stringValue;\n            propertyMode = BaseExposedPropertyDrawer.GetExposedPropertyMode(exposedPropertyNameString);\n            exposedPropertyTable = GetExposedPropertyTable(property);\n            currentOverrideState = BaseExposedPropertyDrawer.OverrideState.DefaultValue;\n            isExposedReference = exposedPropertyTable != null;\n            UpdateValue();\n        }\n\n        public void UpdateValue()\n        {\n            currentReferenceValue = Resolve(out m_CurrentOverrideState);\n        }\n\n        IExposedPropertyTable GetExposedPropertyTable(SerializedProperty property)\n        {\n            var t = property.serializedObject.context;\n            return t as IExposedPropertyTable;\n        }\n\n        internal Object Resolve(out BaseExposedPropertyDrawer.OverrideState currentOverrideState)\n        {\n            PropertyName exposedPropertyName = new PropertyName(exposedPropertyNameString);\n            Object defaultValue = exposedPropertyDefault.objectReferenceValue;\n            Object objReference = null;\n            var propertyIsNamed = !PropertyName.IsNullOrEmpty(exposedPropertyName);\n            currentOverrideState = BaseExposedPropertyDrawer.OverrideState.DefaultValue;\n\n            if (exposedPropertyTable != null)\n            {\n                objReference =\n                    exposedPropertyTable.GetReferenceValue(exposedPropertyName, out var propertyFoundInTable);\n\n                if (propertyFoundInTable)\n                    currentOverrideState = BaseExposedPropertyDrawer.OverrideState.Overridden;\n                else if (propertyIsNamed)\n                    currentOverrideState = BaseExposedPropertyDrawer.OverrideState.MissingOverride;\n            }\n\n            return currentOverrideState == BaseExposedPropertyDrawer.OverrideState.Overridden ? objReference : defaultValue;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/ScriptAttributeGUI/Implementations/PropertyDrawers.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Reflection;\nusing UnityEditor.UIElements;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing static UnityEngine.EnumDataUtility;\n\nnamespace UnityEditor\n{\n    // Built-in PropertyDrawers. See matching attributes in PropertyAttribute.cs\n\n    [CustomPropertyDrawer(typeof(RangeAttribute))]\n    internal sealed class RangeDrawer : PropertyDrawer\n    {\n        private static string s_InvalidTypeMessage = L10n.Tr(\"Use Range with float or int.\");\n\n        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n        {\n            RangeAttribute range = (RangeAttribute)attribute;\n            if (property.propertyType == SerializedPropertyType.Float)\n                EditorGUI.Slider(position, property, range.min, range.max, label);\n            else if (property.propertyType == SerializedPropertyType.Integer)\n                EditorGUI.IntSlider(position, property, (int)range.min, (int)range.max, label);\n            else\n                EditorGUI.LabelField(position, label.text, s_InvalidTypeMessage);\n        }\n\n        public override VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            RangeAttribute range = (RangeAttribute)attribute;\n\n            if (property.propertyType == SerializedPropertyType.Float)\n            {\n                var slider = new Slider(preferredLabel, range.min, range.max);\n                slider.AddToClassList(Slider.alignedFieldUssClassName);\n                slider.bindingPath = property.propertyPath;\n                slider.showInputField = true;\n                return slider;\n            }\n            else if (property.propertyType == SerializedPropertyType.Integer)\n            {\n                var intSlider = new SliderInt(preferredLabel, (int)range.min, (int)range.max);\n                intSlider.AddToClassList(SliderInt.alignedFieldUssClassName);\n                intSlider.bindingPath = property.propertyPath;\n                intSlider.showInputField = true;\n                return intSlider;\n            }\n\n            return new Label(s_InvalidTypeMessage);\n        }\n    }\n\n    [CustomPropertyDrawer(typeof(MinAttribute))]\n    internal sealed class MinDrawer : PropertyDrawer\n    {\n        private static string s_InvalidTypeMessage = L10n.Tr(\"Use Min with float, int or Vector.\");\n\n        private MinAttribute minAttribute\n        {\n            get\n            {\n                return attribute as MinAttribute;\n            }\n        }\n\n        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)\n        {\n            return EditorGUI.GetPropertyHeight(property, label);\n        }\n\n        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.DefaultPropertyField(position, property, label);\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (property.propertyType == SerializedPropertyType.Float)\n                {\n                    property.floatValue = Mathf.Max(minAttribute.min, property.floatValue);\n                }\n                else if (property.propertyType == SerializedPropertyType.Integer)\n                {\n                    property.intValue = Mathf.Max((int)minAttribute.min, property.intValue);\n                }\n                else if (property.propertyType == SerializedPropertyType.Vector2)\n                {\n                    var value = property.vector2Value;\n                    property.vector2Value = new Vector2(Mathf.Max(minAttribute.min, value.x), Mathf.Max(minAttribute.min, value.y));\n                }\n                else if (property.propertyType == SerializedPropertyType.Vector2Int)\n                {\n                    var value = property.vector2IntValue;\n                    property.vector2IntValue = new Vector2Int(Mathf.Max((int)minAttribute.min, value.x), Mathf.Max((int)minAttribute.min, value.y));\n                }\n                else if (property.propertyType == SerializedPropertyType.Vector3)\n                {\n                    var value = property.vector3Value;\n                    property.vector3Value = new Vector3(Mathf.Max(minAttribute.min, value.x), Mathf.Max(minAttribute.min, value.y), Mathf.Max(minAttribute.min, value.z));\n                }\n                else if (property.propertyType == SerializedPropertyType.Vector3Int)\n                {\n                    var value = property.vector3IntValue;\n                    property.vector3IntValue = new Vector3Int(Mathf.Max((int)minAttribute.min, value.x), Mathf.Max((int)minAttribute.min, value.y), Mathf.Max((int)minAttribute.min, value.z));\n                }\n                else if (property.propertyType == SerializedPropertyType.Vector4)\n                {\n                    var value = property.vector4Value;\n                    property.vector4Value = new Vector4(Mathf.Max(minAttribute.min, value.x), Mathf.Max(minAttribute.min, value.y), Mathf.Max(minAttribute.min, value.z), Mathf.Max(minAttribute.min, value.w));\n                }\n                else\n                {\n                    EditorGUI.LabelField(position, label.text, s_InvalidTypeMessage);\n                }\n            }\n        }\n\n        public override VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            BindableElement newField = null;\n\n            if (property.propertyType == SerializedPropertyType.Float)\n            {\n                if (property.type == \"float\")\n                {\n                    newField = new FloatField(preferredLabel);\n                    ((BaseField<float>)newField).onValidateValue += OnValidateValue;\n                }\n                else if (property.type == \"double\")\n                {\n                    newField = new DoubleField(preferredLabel);\n                    ((BaseField<double>)newField).onValidateValue += OnValidateValue;\n                }\n            }\n            else if (property.propertyType == SerializedPropertyType.Integer)\n            {\n                if (property.type == \"int\")\n                {\n                    newField = new IntegerField(preferredLabel);\n                    ((BaseField<int>)newField).onValidateValue += OnValidateValue;\n                }\n                else if (property.type == \"long\")\n                {\n                    newField = new LongField(preferredLabel);\n                    ((BaseField<long>)newField).onValidateValue += OnValidateValue;\n                }\n                else if (property.type == \"uint\")\n                {\n                    newField = new UnsignedIntegerField(preferredLabel);\n                    ((BaseField<uint>)newField).onValidateValue += OnValidateValue;\n                }\n                else if (property.type == \"ulong\")\n                {\n                    newField = new UnsignedLongField(preferredLabel);\n                    ((BaseField<ulong>)newField).onValidateValue += OnValidateValue;\n                }\n            }\n            else if (property.propertyType == SerializedPropertyType.Vector2)\n            {\n                newField = new Vector2Field(preferredLabel);\n                ((BaseField<Vector2>)newField).onValidateValue += OnValidateValue;\n            }\n            else if (property.propertyType == SerializedPropertyType.Vector2Int)\n            {\n                newField = new Vector2IntField(preferredLabel);\n                ((BaseField<Vector2Int>)newField).onValidateValue += OnValidateValue;\n            }\n            else if (property.propertyType == SerializedPropertyType.Vector3)\n            {\n                newField =  new Vector3Field(preferredLabel);\n                ((BaseField<Vector3>)newField).onValidateValue += OnValidateValue;\n            }\n            else if (property.propertyType == SerializedPropertyType.Vector3Int)\n            {\n                newField = new Vector3IntField(preferredLabel);\n                ((BaseField<Vector3Int>)newField).onValidateValue += OnValidateValue;\n            }\n            else if (property.propertyType == SerializedPropertyType.Vector4)\n            {\n                newField = new Vector4Field(preferredLabel);\n                ((BaseField<Vector4>)newField).onValidateValue += OnValidateValue;\n            }\n\n            if (newField != null)\n            {\n                var alignmentClass = TextField.alignedFieldUssClassName;\n                newField.AddToClassList(alignmentClass);\n                newField.bindingPath = property.propertyPath;\n                return newField;\n            }\n\n            return new Label(s_InvalidTypeMessage);\n        }\n\n        private float OnValidateValue(float value)\n        {\n            return Mathf.Max(minAttribute.min, value);\n        }\n\n        private double OnValidateValue(double value)\n        {\n            return Math.Max(minAttribute.min, value);\n        }\n\n        private int OnValidateValue(int value)\n        {\n            return Mathf.Max((int)minAttribute.min, value);\n        }\n\n        private long OnValidateValue(long value)\n        {\n            return Math.Max((long)minAttribute.min, value);\n        }\n\n        private uint OnValidateValue(uint value)\n        {\n            return Math.Max((uint)minAttribute.min, value);\n        }\n\n        private ulong OnValidateValue(ulong value)\n        {\n            return Math.Max((ulong)minAttribute.min, value);\n        }\n\n        private Vector2 OnValidateValue(Vector2 value)\n        {\n            return new Vector2(Mathf.Max(minAttribute.min, value.x), Mathf.Max(minAttribute.min, value.y));\n        }\n\n        private Vector2Int OnValidateValue(Vector2Int value)\n        {\n            return new Vector2Int(Mathf.Max((int)minAttribute.min, value.x), Mathf.Max((int)minAttribute.min, value.y));\n        }\n\n        private Vector3 OnValidateValue(Vector3 value)\n        {\n            return new Vector3(Mathf.Max(minAttribute.min, value.x), Mathf.Max(minAttribute.min, value.y), Mathf.Max(minAttribute.min, value.z));\n        }\n\n        private Vector3Int OnValidateValue(Vector3Int value)\n        {\n            return new Vector3Int(Mathf.Max((int)minAttribute.min, value.x), Mathf.Max((int)minAttribute.min, value.y), Mathf.Max((int)minAttribute.min, value.z));\n        }\n\n        private Vector4 OnValidateValue(Vector4 value)\n        {\n            return new Vector4(Mathf.Max(minAttribute.min, value.x), Mathf.Max(minAttribute.min, value.y), Mathf.Max(minAttribute.min, value.z), Mathf.Max(minAttribute.min, value.w));\n        }\n    }\n\n    [CustomPropertyDrawer(typeof(MultilineAttribute))]\n    internal sealed class MultilineDrawer : PropertyDrawer\n    {\n        private static string s_InvalidTypeMessage = L10n.Tr(\"Use Multiline with string.\");\n        private const int kLineHeight = 13;\n\n        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n        {\n            if (property.propertyType == SerializedPropertyType.String)\n            {\n                label = EditorGUI.BeginProperty(position, label, property);\n\n                position = EditorGUI.MultiFieldPrefixLabel(position, 0, label, 1);\n\n                EditorGUI.BeginChangeCheck();\n                int oldIndent = EditorGUI.indentLevel;\n                EditorGUI.indentLevel = 0; // The MultiFieldPrefixLabel already applied indent, so avoid indent of TextArea itself.\n                string newValue = EditorGUI.TextArea(position, property.stringValue);\n                EditorGUI.indentLevel = oldIndent;\n                if (EditorGUI.EndChangeCheck())\n                    property.stringValue = newValue;\n\n                EditorGUI.EndProperty();\n            }\n            else\n                EditorGUI.LabelField(position, label.text, s_InvalidTypeMessage);\n        }\n\n        public override VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            if (property.propertyType == SerializedPropertyType.String)\n            {\n                var lines = ((MultilineAttribute)attribute).lines;\n                var field = new TextField(preferredLabel);\n                field.multiline = true;\n                field.bindingPath = property.propertyPath;\n                field.style.height = EditorGUI.kSingleLineHeight + (lines - 1) * kLineHeight;\n                field.AddToClassList(TextField.alignedFieldUssClassName);\n                return field;\n            }\n\n            return new Label(s_InvalidTypeMessage);\n        }\n\n        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)\n        {\n            return (EditorGUIUtility.wideMode ? 0 : (int)EditorGUI.kSingleLineHeight) // header\n                + EditorGUI.kSingleLineHeight // first line\n                + (((MultilineAttribute)attribute).lines - 1) * kLineHeight; // remaining lines\n        }\n    }\n\n    [CustomPropertyDrawer(typeof(TextAreaAttribute))]\n    internal sealed class TextAreaDrawer : PropertyDrawer\n    {\n        private const int kLineHeight = 15;\n        private static string s_InvalidTypeMessage = L10n.Tr(\"Use TextAreaDrawer with string.\");\n        private Vector2 m_ScrollPosition = new Vector2();\n\n        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n        {\n            if (property.propertyType == SerializedPropertyType.String)\n            {\n                label = EditorGUI.BeginProperty(position, label, property);\n                Rect labelPosition = EditorGUI.IndentedRect(position);\n                labelPosition.height = EditorGUI.kSingleLineHeight;\n                position.yMin += labelPosition.height;\n                EditorGUI.HandlePrefixLabel(position, labelPosition, label);\n\n                EditorGUI.BeginChangeCheck();\n                string newValue = EditorGUI.ScrollableTextAreaInternal(position, property.stringValue, ref m_ScrollPosition, EditorStyles.textArea);\n                if (EditorGUI.EndChangeCheck())\n                    property.stringValue = newValue;\n\n                EditorGUI.EndProperty();\n            }\n            else\n                EditorGUI.LabelField(position, label.text, s_InvalidTypeMessage);\n        }\n\n        public override VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            if (property.propertyType != SerializedPropertyType.String)\n                return new Label(s_InvalidTypeMessage);\n\n            var textAreaAttribute = attribute as TextAreaAttribute;\n\n            // Label + first line\n            var initialHeight = EditorGUI.kSingleLineHeight + EditorGUI.kSingleLineHeight;\n\n            var minHeight = initialHeight + (textAreaAttribute!.minLines - 1) * kLineHeight;\n            var maxHeight = initialHeight + (textAreaAttribute!.maxLines - 1) * kLineHeight;\n\n            if (maxHeight < minHeight)\n                maxHeight = minHeight;\n\n            var textField = new TextField\n            {\n                label = preferredLabel,\n                multiline = true,\n                style =\n                {\n                    flexDirection = FlexDirection.Column,\n                    whiteSpace = WhiteSpace.Normal,\n                    minHeight = minHeight,\n                    maxHeight = maxHeight\n                }\n            };\n\n            textField.verticalScrollerVisibility = ScrollerVisibility.Auto;\n\n            textField.style.minHeight = minHeight;\n            textField.bindingPath = property.propertyPath;\n\n            return textField;\n        }\n\n        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)\n        {\n            TextAreaAttribute textAreaAttribute = attribute as TextAreaAttribute;\n            string text = property.stringValue;\n\n            float fullTextHeight = EditorStyles.textArea.CalcHeight(GUIContent.Temp(text), EditorGUIUtility.contextWidth);\n            int lines = Mathf.CeilToInt(fullTextHeight / kLineHeight);\n\n            lines = Mathf.Clamp(lines, textAreaAttribute.minLines, textAreaAttribute.maxLines);\n\n            return EditorGUI.kSingleLineHeight // header\n                + EditorGUI.kSingleLineHeight // first line\n                + (lines - 1) * kLineHeight; // remaining lines\n        }\n    }\n\n    [CustomPropertyDrawer(typeof(ColorUsageAttribute))]\n    internal sealed class ColorUsageDrawer : PropertyDrawer\n    {\n        private static string s_InvalidTypeMessage = L10n.Tr(\"Use ColorUsageDrawer with color.\");\n\n        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n        {\n            var colorUsage = (ColorUsageAttribute)attribute;\n            if (property.propertyType == SerializedPropertyType.Color)\n            {\n                label = EditorGUI.BeginProperty(position, label, property);\n                EditorGUI.BeginChangeCheck();\n                Color newColor = EditorGUI.ColorField(position, label, property.colorValue, true, colorUsage.showAlpha, colorUsage.hdr);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    property.colorValue = newColor;\n                }\n                EditorGUI.EndProperty();\n            }\n            else\n            {\n                EditorGUI.ColorField(position, label, property.colorValue, true, colorUsage.showAlpha, colorUsage.hdr);\n            }\n        }\n\n        public override VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            if (property.propertyType == SerializedPropertyType.Color)\n            {\n                var colorUsage = (ColorUsageAttribute)attribute;\n                var field = new ColorField(preferredLabel);\n                field.showAlpha = colorUsage.showAlpha;\n                field.hdr = colorUsage.hdr;\n                field.bindingPath = property.propertyPath;\n                field.AddToClassList(ColorField.alignedFieldUssClassName);\n                return field;\n            }\n\n            return new Label(s_InvalidTypeMessage);\n        }\n    }\n\n    [CustomPropertyDrawer(typeof(GradientUsageAttribute))]\n    internal sealed class GradientUsageDrawer : PropertyDrawer\n    {\n        private static string s_InvalidTypeMessage = L10n.Tr(\"Use GradientUsageDrawer with gradient.\");\n\n        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n        {\n            var colorUsage = (GradientUsageAttribute)attribute;\n\n            EditorGUI.BeginChangeCheck();\n            Gradient newGradient = EditorGUI.GradientField(position, label, property.gradientValue, colorUsage.hdr, colorUsage.colorSpace);\n            if (EditorGUI.EndChangeCheck())\n            {\n                property.gradientValue = newGradient;\n            }\n        }\n\n        public override VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            if (property.propertyType == SerializedPropertyType.Gradient)\n            {\n                var gradientUsage = (GradientUsageAttribute)attribute;\n                var field = new GradientField(preferredLabel);\n                field.hdr = gradientUsage.hdr;\n                field.colorSpace = gradientUsage.colorSpace;\n                field.bindingPath = property.propertyPath;\n                field.AddToClassList(GradientField.alignedFieldUssClassName);\n                return field;\n            }\n\n            return new Label(s_InvalidTypeMessage);\n        }\n    }\n\n    [CustomPropertyDrawer(typeof(DelayedAttribute))]\n    internal sealed class DelayedDrawer : PropertyDrawer\n    {\n        private static string s_InvalidTypeMessage = L10n.Tr(\"Use Delayed with float, int, or string.\");\n\n        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n        {\n            if (property.propertyType == SerializedPropertyType.Float)\n                EditorGUI.DelayedFloatField(position, property, label);\n            else if (property.propertyType == SerializedPropertyType.Integer)\n                EditorGUI.DelayedIntField(position, property, label);\n            else if (property.propertyType == SerializedPropertyType.String)\n                EditorGUI.DelayedTextField(position, property, label);\n            else\n                EditorGUI.LabelField(position, label.text, s_InvalidTypeMessage);\n        }\n\n        public override VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            BindableElement newField = null;\n            if (property.propertyType == SerializedPropertyType.Float)\n            {\n                if (property.type == \"float\")\n                {\n                    newField = new FloatField(preferredLabel);\n                    ((TextInputBaseField<float>)newField).isDelayed = true;\n                }\n                else if (property.type == \"double\")\n                {\n                    newField = new DoubleField(preferredLabel);\n                    ((TextInputBaseField<double>)newField).isDelayed = true;\n                }\n            }\n            else if (property.propertyType == SerializedPropertyType.Integer)\n            {\n                if (property.type == \"int\")\n                {\n                    newField = new IntegerField(preferredLabel);\n                    ((TextInputBaseField<int>)newField).isDelayed = true;\n                }\n                else if (property.type == \"long\")\n                {\n                    newField = new LongField(preferredLabel);\n                    ((TextInputBaseField<long>)newField).isDelayed = true;\n                }\n            }\n            else if (property.propertyType == SerializedPropertyType.String)\n            {\n                newField = new TextField(preferredLabel);\n                ((TextInputBaseField<string>)newField).isDelayed = true;\n            }\n\n            if (newField != null)\n            {\n                newField.bindingPath = property.propertyPath;\n                newField.AddToClassList(TextField.alignedFieldUssClassName);\n                return newField;\n            }\n\n            return new Label(s_InvalidTypeMessage);\n        }\n    }\n\n    [CustomPropertyDrawer(typeof(EnumButtonsAttribute))]\n    internal sealed class EnumButtonsDrawer : PropertyDrawer\n    {\n        public override VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            var toggleButtonGroup = new ToggleButtonGroup\n            {\n                label = property.localizedDisplayName,\n                tooltip = property.tooltip\n            };\n\n            var fieldInfo = ScriptAttributeUtility.GetFieldInfoFromProperty(property, out var enumType);\n            if (enumType == null)\n                return null;\n\n            var toggleButtonsAttribute = fieldInfo.GetCustomAttribute<EnumButtonsAttribute>(false);\n            var cachedType = toggleButtonsAttribute?.includeObsolete == true ? CachedType.IncludeAllObsolete : CachedType.ExcludeObsolete;\n            var enumData = EnumDataUtility.GetCachedEnumData(enumType, cachedType);\n\n            toggleButtonGroup.isMultipleSelection = enumData.flags;\n            toggleButtonGroup.allowEmptySelection = enumData.flags;\n            toggleButtonGroup.label = property.localizedDisplayName;\n            toggleButtonGroup.tooltip = property.tooltip;\n            toggleButtonGroup.AddToClassList(ToggleButtonGroup.alignedFieldUssClassName);\n\n            // Create buttons\n            for (int i = 0; i < enumData.values.Length; ++i)\n            {\n                var button = new Button { text = enumData.displayNames[i], name = enumData.names[i], tooltip = enumData.tooltip[i] };\n                toggleButtonGroup.Add(button);\n            }\n\n            toggleButtonGroup.RegisterValueChangedCallback(evt =>\n            {\n                SyncFieldChangeToProperty(evt, enumData, toggleButtonGroup, property);\n            });\n\n            toggleButtonGroup.TrackPropertyValue(property, p =>\n            {\n                SyncPropertyToField(p, enumData, toggleButtonGroup);\n            });\n\n            SyncPropertyToField(property, enumData, toggleButtonGroup);\n            return toggleButtonGroup;\n        }\n\n        static void SyncFieldChangeToProperty(ChangeEvent<ToggleButtonGroupState> evt, in EnumData enumData, ToggleButtonGroup toggleButtonGroup, SerializedProperty property)\n        {\n            // Calculate the new value by checking what buttons have changed.\n            // When the value has multiple different values, we calculate from 0.\n            var value = property.hasMultipleDifferentValues ? 0 : property.intValue;\n            if (enumData.flags)\n            {\n                for (int i = 0; i < enumData.values.Length; i++)\n                {\n                    // The button state didn't change, so skip it\n                    if (evt.previousValue[i] == evt.newValue[i])\n                        continue;\n\n                    // It was toggled on, enable the bits\n                    if (evt.newValue[i])\n                    {\n                        // Special handling for 0 which is usually a None flag.\n                        if (enumData.flagValues[i] == 0)\n                        {\n                            value = 0;\n                            break;\n                        }\n                        else\n                        {\n                            value |= enumData.flagValues[i];\n                        }\n                    }\n                    else // It was toggled off, disable the bits\n                    {\n                        value &= ~enumData.flagValues[i];\n                    }\n                }\n            }\n            else\n            {\n                for (int i = 0; i < enumData.values.Length; i++)\n                {\n                    if (evt.newValue[i])\n                    {\n                        value = enumData.flagValues[i];\n                        break;\n                    }\n                }\n            }\n\n            property.intValue = value;\n            property.serializedObject.ApplyModifiedProperties();\n            SyncPropertyToField(property, enumData, toggleButtonGroup);\n        }\n\n        static void SyncPropertyToField(SerializedProperty property, in EnumData enumData, ToggleButtonGroup toggleButtonGroup)\n        {\n            // EnumData limits us to ints.\n            var state = new ToggleButtonGroupState(0, 32);\n\n            // We leave the state at 0 when we have mixed values\n            if (!property.hasMultipleDifferentValues)\n            {\n                var value = property.intValue;\n\n                if (enumData.flags)\n                {\n                    for (int i = 0; i < enumData.values.Length; i++)\n                    {\n                        // Special handling for 0 which is usually a None flag.\n                        if (enumData.flagValues[i] == 0)\n                            state[i] = value == 0;\n                        else\n                            state[i] = (enumData.flagValues[i] & value) == enumData.flagValues[i];\n                    }\n                }\n                else\n                {\n                    for (int i = 0; i < enumData.values.Length; i++)\n                    {\n                        state[i] = value == enumData.flagValues[i];\n                    }\n                }\n            }\n\n            toggleButtonGroup.SetValueWithoutNotify(state);\n            toggleButtonGroup.showMixedValue = property.hasMultipleDifferentValues;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/ScriptAttributeGUI/PropertyDrawer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Reflection;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    // Base class to derive custom property drawers from. Use this to create custom drawers\n    // for your own [[Serializable]] classes or for script variables with custom [[PropertyAttribute]]s.\n    public abstract class PropertyDrawer : GUIDrawer\n    {\n        internal PropertyAttribute m_Attribute;\n        internal FieldInfo m_FieldInfo;\n        internal string m_PreferredLabel;\n\n        // The [[PropertyAttribute]] for the property. Not applicable for custom class drawers. (RO)\n        public PropertyAttribute attribute { get { return m_Attribute; } }\n\n        // The reflection FieldInfo for the member this property represents. (RO)\n        public FieldInfo fieldInfo { get { return m_FieldInfo; } }\n\n        // The preferred label for this property.\n        public string preferredLabel => m_PreferredLabel;\n\n        internal void OnGUISafe(Rect position, SerializedProperty property, GUIContent label)\n        {\n            ScriptAttributeUtility.s_DrawerStack.Push(this);\n            OnGUI(position, property, label);\n            ScriptAttributeUtility.s_DrawerStack.TryPop(out _);\n        }\n\n        // Override this method to make your own GUI for the property based on IMGUI.\n        public virtual void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n        {\n            var labelCopy = new GUIContent(label);\n            EditorGUI.LabelField(position, labelCopy, EditorGUIUtility.TempContent(\"No GUI Implemented\"));\n        }\n\n        // Override this method to make your own GUI for the property based on UIElements.\n        public virtual VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            return null;\n        }\n\n        internal float GetPropertyHeightSafe(SerializedProperty property, GUIContent label)\n        {\n            ScriptAttributeUtility.s_DrawerStack.Push(this);\n            float height = GetPropertyHeight(property, label);\n            ScriptAttributeUtility.s_DrawerStack.TryPop(out _);\n            return height;\n        }\n\n        // Override this method to specify how tall the GUI for this field is in pixels.\n        public virtual float GetPropertyHeight(SerializedProperty property, GUIContent label)\n        {\n            return EditorGUI.kSingleLineHeight;\n        }\n\n        [Obsolete(\"CanCacheInspectorGUI has been deprecated and is no longer used.\", false)]\n        public virtual bool CanCacheInspectorGUI(SerializedProperty property)\n        {\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/ScriptAttributeGUI/PropertyHandler.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing UnityEngine.Bindings;\nusing Object = UnityEngine.Object;\nusing UnityEngine.Pool;\n\nnamespace UnityEditor\n{\n    [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n    internal class PropertyHandler : IDisposable\n    {\n        readonly static Dictionary<Type, List<(FieldInfo fieldInfo, Object objectReference)>> s_DefaultObjectReferenceCache = new();\n\n        List<PropertyDrawer> m_PropertyDrawers;\n        List<DecoratorDrawer> m_DecoratorDrawers;\n        public string tooltip;\n\n        public bool hasPropertyDrawer => propertyDrawer != null;\n\n        internal PropertyDrawer propertyDrawer\n        {\n            get\n            {\n                if (m_PropertyDrawers == null || m_NestingLevel >= m_PropertyDrawers.Count)\n                    return null;\n                return m_PropertyDrawers[m_NestingLevel];\n            }\n        }\n\n        internal List<DecoratorDrawer> decoratorDrawers => m_DecoratorDrawers;\n        internal bool skipDecoratorDrawers { get; set; }\n\n        int m_NestingLevel;\n\n        bool isCurrentlyNested => m_NestingLevel > 0;\n\n        internal static Dictionary<string, ReorderableListWrapper> s_reorderableLists = new Dictionary<string, ReorderableListWrapper>();\n        static int s_LastInspectionTarget;\n        static int s_LastInspectorNumComponents;\n\n        static PropertyHandler()\n        {\n            Undo.undoRedoEvent += OnUndoRedo;\n        }\n\n        static void OnUndoRedo(in UndoRedoInfo info)\n        {\n            ReorderableList.InvalidateExistingListCaches();\n        }\n\n        public static void ClearCache()\n        {\n            s_reorderableLists.Clear();\n            s_LastInspectionTarget = 0;\n        }\n\n        public static void InvalidateListCacheIncludingChildren(SerializedProperty property)\n        {\n            foreach (var listEntry in s_reorderableLists)\n            {\n                if (listEntry.Key.Contains(property.propertyPath)\n                    && listEntry.Key.Contains(property.serializedObject.targetObject.GetInstanceID().ToString() + (GUIView.current?.nativeHandle.ToInt32() ?? -1)))\n                    listEntry.Value.InvalidateCache();\n            }\n        }\n\n        public List<ContextMenuItemAttribute> contextMenuItems;\n\n        public bool empty =>\n            m_DecoratorDrawers == null\n            && tooltip == null\n            && m_PropertyDrawers == null\n            && contextMenuItems == null;\n\n        public void HandleAttribute(SerializedProperty property, PropertyAttribute attribute, FieldInfo field, Type propertyType)\n        {\n            if (attribute is TooltipAttribute)\n            {\n                tooltip = (attribute as TooltipAttribute).tooltip;\n                return;\n            }\n\n            if (attribute is ContextMenuItemAttribute)\n            {\n                if (contextMenuItems == null)\n                    contextMenuItems = new List<ContextMenuItemAttribute>();\n                contextMenuItems.Add(attribute as ContextMenuItemAttribute);\n                return;\n            }\n\n            // Case 1: If property is a collection, applyToCollection == false, early return to avoid custom drawer;\n            // Case 2: If property is not a collection but within a collection, applyToCollection == true, early return\n            //         to avoid custom drawer;\n            // Case 3: If property is not a collection nor within a collection, applyToCollection value should\n            //         NOT have any effects on it. Custom drawer should be used.\n            // Case 4: Rest of the cases, custom drawer should be used.\n            var isArrayOrList = propertyType != null && propertyType.IsArrayOrList();\n            switch (attribute.applyToCollection)\n            {\n                // Case 1.\n                case false when isArrayOrList:\n                // Case 2.\n                case true when !isArrayOrList && property.propertyPath.Contains(\"[\"):\n                    return;\n                // Case 3 & 4.\n                default:\n                    // Look for its drawer type of this attribute\n                    HandleDrawnType(property, attribute.GetType(), propertyType, field, attribute);\n                    break;\n            }\n        }\n\n        public void HandleDrawnType(SerializedProperty property, Type drawnType, Type propertyType, FieldInfo field, PropertyAttribute attribute)\n        {\n            Type drawerType = ScriptAttributeUtility.GetDrawerTypeForPropertyAndType(property, drawnType);\n\n            // If we found a drawer type, instantiate the drawer, cache it, and return it.\n            if (drawerType != null)\n            {\n                if (typeof(PropertyDrawer).IsAssignableFrom(drawerType))\n                {\n                    // Use PropertyDrawer on array elements, not on array itself.\n                    // If there's a PropertyAttribute on an array, we want to apply it to the individual array elements instead.\n                    // This is the only convenient way we can let the user apply PropertyDrawer attributes to elements inside an array.\n                    if (propertyType != null && propertyType.IsArrayOrList() && (attribute == null || !attribute.applyToCollection))\n                        return;\n\n                    var propertyDrawerForType = CreatePropertyDrawerWithDefaultObjectReferences(drawerType);\n                    propertyDrawerForType.m_FieldInfo = field;\n\n                    // Will be null by design if default type drawer!\n                    propertyDrawerForType.m_Attribute = attribute;\n\n                    if (m_PropertyDrawers == null)\n                        m_PropertyDrawers = new List<PropertyDrawer>();\n                    m_PropertyDrawers.Add(propertyDrawerForType);\n                }\n                else if (typeof(DecoratorDrawer).IsAssignableFrom(drawerType))\n                {\n                    // Draw decorators on array itself, not on each array elements\n                    if (field != null && field.FieldType.IsArrayOrList() && !propertyType.IsArrayOrList())\n                        return;\n\n                    DecoratorDrawer decoratorDrawerForType = (DecoratorDrawer)System.Activator.CreateInstance(drawerType);\n                    decoratorDrawerForType.m_Attribute = attribute;\n\n                    if (m_DecoratorDrawers == null)\n                        m_DecoratorDrawers = new List<DecoratorDrawer>();\n                    m_DecoratorDrawers.Add(decoratorDrawerForType);\n                }\n            }\n        }\n\n        static PropertyDrawer CreatePropertyDrawerWithDefaultObjectReferences(Type drawerType)\n        {\n            var propertyDrawer = (PropertyDrawer)Activator.CreateInstance(drawerType);\n\n            // We cache the default values for the object references in the drawer as the lookup process can be slow.\n            if (!s_DefaultObjectReferenceCache.TryGetValue(drawerType, out var defaultObjectReferences))\n            {\n                var monoScript = MonoScript.FromType(drawerType);\n                if (monoScript != null)\n                {\n                    using var namePool = ListPool<string>.Get(out var names);\n                    using var targetsPool = ListPool<Object>.Get(out var targets);\n\n                    MonoImporter.GetDefaultReferencesInternal(monoScript, names, targets);\n                    Debug.Assert(names.Count == targets.Count);\n\n                    for (int i = 0; i < names.Count; i++)\n                    {\n                        defaultObjectReferences ??= new List<(FieldInfo, Object)>();\n                        var field = drawerType.GetField(names[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);\n                        if (field != null)\n                        {\n                            defaultObjectReferences.Add((field, targets[i]));\n                        }\n                    }\n                }\n\n                s_DefaultObjectReferenceCache[drawerType] = defaultObjectReferences;\n            }\n\n            if (defaultObjectReferences != null)\n            {\n                foreach (var (field, value) in defaultObjectReferences)\n                {\n                    field.SetValue(propertyDrawer, value);\n                }\n            }\n\n            return propertyDrawer;\n        }\n\n        // returns true if children needs to be drawn separately\n        public bool OnGUI(Rect position, SerializedProperty property, GUIContent label, bool includeChildren)\n        {\n            Rect visibleArea = new Rect(0, 0, float.MaxValue, float.MaxValue);\n            return OnGUI(position, property, label, includeChildren, visibleArea);\n        }\n\n        internal bool OnGUI(Rect position, SerializedProperty property, GUIContent label, bool includeChildren, Rect visibleArea)\n        {\n            TestInvalidateCache();\n\n            float oldLabelWidth, oldFieldWidth;\n\n            float propHeight = position.height;\n            position.height = 0;\n\n            if (!skipDecoratorDrawers && m_DecoratorDrawers != null && !isCurrentlyNested)\n            {\n                foreach (DecoratorDrawer decorator in m_DecoratorDrawers)\n                {\n                    position.height = decorator.GetHeight();\n\n                    oldLabelWidth = EditorGUIUtility.labelWidth;\n                    oldFieldWidth = EditorGUIUtility.fieldWidth;\n                    decorator.OnGUI(position);\n                    EditorGUIUtility.labelWidth = oldLabelWidth;\n                    EditorGUIUtility.fieldWidth = oldFieldWidth;\n\n                    position.y += position.height;\n                    propHeight -= position.height;\n                }\n            }\n\n            position.height = propHeight;\n            if (propertyDrawer != null)\n            {\n                // Remember widths\n                oldLabelWidth = EditorGUIUtility.labelWidth;\n                oldFieldWidth = EditorGUIUtility.fieldWidth;\n                // Draw with custom drawer - retrieve it BEFORE increasing nesting.\n                PropertyDrawer drawer = propertyDrawer;\n\n                using (var nestingContext = IncrementNestingContext())\n                {\n                    drawer.OnGUISafe(position, property.Copy(), label ?? EditorGUIUtility.TempContent(property.localizedDisplayName, tooltip));\n                }\n\n                // Restore widths\n                EditorGUIUtility.labelWidth = oldLabelWidth;\n                EditorGUIUtility.fieldWidth = oldFieldWidth;\n\n                return false;\n            }\n            else\n            {\n                if (!includeChildren)\n                    return EditorGUI.DefaultPropertyField(position, property, label);\n\n                if (UseReorderabelListControl(property))\n                {\n                    ReorderableListWrapper reorderableList;\n                    string key = ReorderableListWrapper.GetPropertyIdentifier(property);\n\n                    if (!s_reorderableLists.TryGetValue(key, out reorderableList))\n                    {\n                        // Manual layout controls don't call GetHeight() method so we need to have a way to initialized list as we prepare to render it here\n                        reorderableList = new ReorderableListWrapper(property, label, true);\n                        s_reorderableLists[key] = reorderableList;\n                    }\n\n                    // Calculate visibility rect specifically for reorderable list as when applied for the whole serialized object,\n                    // it causes collapsed out of sight array elements appear thus messing up scroll-bar experience\n                    var screenPos = GUIUtility.GUIToScreenPoint(position.position);\n\n                    screenPos.y = Mathf.Clamp(screenPos.y,\n                        GUIView.current?.screenPosition.yMin ?? 0,\n                        GUIView.current?.screenPosition.yMax ?? Screen.height);\n\n                    Rect listVisibility = new Rect(screenPos.x, screenPos.y,\n                        GUIView.current?.screenPosition.width ?? Screen.width,\n                        GUIView.current?.screenPosition.height ?? Screen.height);\n\n                    listVisibility = GUIUtility.ScreenToGUIRect(listVisibility);\n\n                    // Copy helps with recursive list rendering\n                    reorderableList.Property = property.Copy();\n                    reorderableList.Draw(label, position, listVisibility, tooltip, includeChildren);\n                    return !includeChildren && property.isExpanded;\n                }\n\n                // Remember state\n                Vector2 oldIconSize = EditorGUIUtility.GetIconSize();\n                bool wasEnabled = GUI.enabled;\n                int origIndent = EditorGUI.indentLevel;\n\n                int relIndent = origIndent - property.depth;\n\n                SerializedProperty prop = property.Copy();\n\n                position.height = EditorGUI.GetSinglePropertyHeight(prop, label);\n\n                // First property with custom label\n                EditorGUI.indentLevel = prop.depth + relIndent;\n                bool childrenAreExpanded = EditorGUI.DefaultPropertyField(position, prop, label) && EditorGUI.HasVisibleChildFields(prop);\n                position.y += position.height + EditorGUI.kControlVerticalSpacing;\n\n                if (property.isArray)\n                    EditorGUI.BeginIsInsideList(prop.depth);\n\n                // Loop through all child properties\n                if (childrenAreExpanded)\n                {\n                    SerializedProperty endProperty = prop.GetEndProperty();\n\n                    while (prop.NextVisible(childrenAreExpanded) && !SerializedProperty.EqualContents(prop, endProperty))\n                    {\n                        if (GUI.isInsideList && prop.depth <= EditorGUI.GetInsideListDepth())\n                            EditorGUI.EndIsInsideList();\n\n                        if (prop.isArray)\n                            EditorGUI.BeginIsInsideList(prop.depth);\n\n                        var handler = ScriptAttributeUtility.GetHandler(prop);\n                        EditorGUI.indentLevel = prop.depth + relIndent;\n                        position.height = handler.GetHeight(prop, null, UseReorderabelListControl(prop) && includeChildren);\n\n                        if (position.Overlaps(visibleArea))\n                        {\n                            EditorGUI.BeginChangeCheck();\n                            childrenAreExpanded = handler.OnGUI(position, prop, null, UseReorderabelListControl(prop)) && EditorGUI.HasVisibleChildFields(prop);\n                            // Changing child properties (like array size) may invalidate the iterator,\n                            // so stop now, or we may get errors.\n                            if (EditorGUI.EndChangeCheck())\n                                break;\n                        }\n\n                        position.y += position.height + EditorGUI.kControlVerticalSpacing;\n                    }\n                }\n\n                // Restore state\n                if (GUI.isInsideList && property.depth <= EditorGUI.GetInsideListDepth())\n                    EditorGUI.EndIsInsideList();\n                GUI.enabled = wasEnabled;\n                EditorGUIUtility.SetIconSize(oldIconSize);\n                EditorGUI.indentLevel = origIndent;\n\n                return false;\n            }\n        }\n\n        public bool OnGUILayout(SerializedProperty property, GUIContent label, bool includeChildren, params GUILayoutOption[] options)\n        {\n            Rect r;\n            if (property.propertyType == SerializedPropertyType.Boolean && propertyDrawer == null && (m_DecoratorDrawers == null || m_DecoratorDrawers.Count == 0))\n                r = EditorGUILayout.GetToggleRect(true, options);\n            else\n                r = EditorGUILayout.GetControlRect(EditorGUI.LabelHasContent(label), GetHeight(property, label, includeChildren), options);\n            EditorGUILayout.s_LastRect = r;\n            return OnGUI(r, property, label, includeChildren);\n        }\n\n        public float GetHeight(SerializedProperty property, GUIContent label, bool includeChildren)\n        {\n            float height = 0;\n\n            if (!skipDecoratorDrawers && m_DecoratorDrawers != null && !isCurrentlyNested)\n                foreach (DecoratorDrawer drawer in m_DecoratorDrawers)\n                    height += drawer.GetHeight();\n\n\n            if (propertyDrawer != null)\n            {\n                // Retrieve drawer BEFORE increasing nesting.\n                PropertyDrawer drawer = propertyDrawer;\n                using (var nestingContext = IncrementNestingContext())\n                {\n                    height += drawer.GetPropertyHeightSafe(property.Copy(), label ?? EditorGUIUtility.TempContent(property.localizedDisplayName, tooltip));\n                }\n            }\n            else if (!includeChildren)\n            {\n                height += EditorGUI.GetSinglePropertyHeight(property, label);\n            }\n            else if (UseReorderabelListControl(property))\n            {\n                ReorderableListWrapper reorderableList;\n                string key = ReorderableListWrapper.GetPropertyIdentifier(property);\n\n                // If collection doesn't have a ReorderableList assigned to it, create one and assign it\n                if (!s_reorderableLists.TryGetValue(key, out reorderableList))\n                {\n                    reorderableList = new ReorderableListWrapper(property, label, true);\n                    s_reorderableLists[key] = reorderableList;\n                }\n\n                // Copy helps with recursive list rendering\n                reorderableList.Property = property.Copy();\n                height += s_reorderableLists[key].GetHeight();\n                return height;\n            }\n            else\n            {\n                property = property.Copy();\n\n                // First property with custom label\n                height += EditorGUI.GetSinglePropertyHeight(property, label);\n                bool childrenAreExpanded = property.isExpanded && EditorGUI.HasVisibleChildFields(property);\n\n                // Loop through all child properties\n                if (childrenAreExpanded)\n                {\n                    var tc = EditorGUIUtility.TempContent(property.localizedDisplayName, tooltip);\n                    SerializedProperty endProperty = property.GetEndProperty();\n                    while (property.NextVisible(childrenAreExpanded) && !SerializedProperty.EqualContents(property, endProperty))\n                    {\n                        height += ScriptAttributeUtility.GetHandler(property).GetHeight(property, tc, true);\n                        childrenAreExpanded = false;\n                        height += EditorGUI.kControlVerticalSpacing;\n                    }\n                }\n            }\n\n            return height;\n        }\n\n        public void AddMenuItems(SerializedProperty property, GenericMenu menu)\n        {\n            if (contextMenuItems != null)\n            {\n                Type scriptType = property.serializedObject.targetObject.GetType();\n                foreach (ContextMenuItemAttribute attribute in contextMenuItems)\n                {\n                    MethodInfo method = scriptType.GetMethod(attribute.function, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);\n                    if (method == null)\n                        continue;\n                    menu.AddItem(new GUIContent(attribute.name), false, () => CallMenuCallback(property.serializedObject.targetObjects, method));\n                }\n            }\n\n            var propertyPath = property.propertyPath.Replace(\" \", \"\");\n            menu.AddItem(new GUIContent(\"Copy Property Path\"), false, () => EditorGUIUtility.systemCopyBuffer = propertyPath);\n\n            if (CanSearchProperty(property))\n            {\n                menu.AddItem(new GUIContent(\"Search Same Property Value\"), false, () => SearchProperty(property));\n                if (property.propertyType == SerializedPropertyType.ObjectReference && property.objectReferenceValue)\n                {\n                    menu.AddItem(new GUIContent($\"Find references to {property.objectReferenceValue.GetType().Name} {property.objectReferenceValue.name}\"), false, () => FindReferences(property.objectReferenceValue));\n                }\n            }\n        }\n\n        private void SearchProperty(SerializedProperty property)\n        {\n            CommandService.Execute(\"OpenToSearchByProperty\", CommandHint.Menu, property);\n        }\n\n        private void FindReferences(UnityEngine.Object obj)\n        {\n            CommandService.Execute(\"OpenToFindReferenceOnObject\", CommandHint.Menu, obj);\n        }\n\n        private bool CanSearchProperty(SerializedProperty property)\n        {\n            if (!CommandService.Exists(\"OpenToSearchByProperty\") || !CommandService.Exists(\"IsPropertyValidForQuery\"))\n                return false;\n\n            var result = CommandService.Execute(\"IsPropertyValidForQuery\", CommandHint.Menu, property);\n            return (bool)result;\n        }\n\n        public void CallMenuCallback(object[] targets, MethodInfo method)\n        {\n            foreach (object target in targets)\n                method.Invoke(target, new object[] {});\n        }\n\n        static List<Component> s_CachedComponents = new List<Component>();\n\n        internal void TestInvalidateCache()\n        {\n            GameObject activeObject = Selection.activeObject as GameObject;\n            if (activeObject != null)\n            {\n                activeObject.GetComponents(s_CachedComponents);\n                var componentCount = s_CachedComponents.Count;\n                s_CachedComponents.Clear();\n\n                if (s_LastInspectionTarget != activeObject.GetInstanceID() ||\n                    s_LastInspectorNumComponents != componentCount)\n                {\n                    ClearCache();\n                    s_LastInspectionTarget = activeObject.GetInstanceID();\n                    s_LastInspectorNumComponents = componentCount;\n                }\n            }\n        }\n\n        static bool IsNonStringArray(SerializedProperty property)\n        {\n            if (property == null) return false;\n            // Strings should not be represented with ReorderableList, they will use custom drawer therefore we don't treat them as other arrays\n            return property.isArray && property.propertyType != SerializedPropertyType.String;\n        }\n\n        internal static bool IsArrayReorderable(SerializedProperty property)\n        {\n            const BindingFlags fieldFilter = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;\n\n            if (property == null || property.serializedObject == null || !property.serializedObject.targetObject)\n                return false;\n\n            if (property.IsReorderable()) return true;\n\n            FieldInfo listInfo = null;\n            Queue<string> propertyName = new Queue<string>(property.propertyPath.Split(\".\".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));\n            Type type = property.serializedObject.targetObject.GetType();\n            var name = propertyName.Dequeue();\n            listInfo = type.GetField(name, fieldFilter);\n\n            if (listInfo == null)\n            {\n                // it may be private in any parent and still serializable\n                type = type.BaseType;\n                while (listInfo == null && type != null)\n                {\n                    listInfo = type.GetField(name, fieldFilter);\n                    type = type.BaseType;\n                }\n                if (listInfo == null) return false;\n            }\n\n            // If we have a nested property we need to find it via reflection in order to verify\n            // if it has a non-reorderable attribute\n            while (propertyName.Count > 0)\n            {\n                try\n                {\n                    // We should at least try to get the type from object instance\n                    // in order to handle interfaces and abstractions correctly\n                    type = listInfo.GetValue(property.serializedObject.targetObject).GetType();\n                }\n                catch\n                {\n                    type = listInfo.FieldType;\n                }\n\n                if (type.IsArray) type = type.GetElementType();\n                else if (type.IsArrayOrList()) type = type.GetGenericArguments().Single();\n\n                FieldInfo field = type.GetField(propertyName.Dequeue(), fieldFilter);\n                if (field != null) listInfo = field;\n            }\n\n            // Since we're using TypeCache to find NonReorderableAttribute, we will need to manually check base fields\n            List<FieldInfo> baseFields = new List<FieldInfo>();\n            baseFields.Add(listInfo);\n            while ((type = type.BaseType) != null)\n            {\n                var field = type.GetField(listInfo.Name, fieldFilter);\n                if (field != null) baseFields.Add(field);\n            }\n\n            return !TypeCache.GetFieldsWithAttribute(typeof(NonReorderableAttribute)).Any(f => baseFields.Any(b => f.Equals(b)));\n        }\n\n        internal static bool UseReorderabelListControl(SerializedProperty property) => IsNonStringArray(property) && IsArrayReorderable(property);\n\n        public NestingContext ApplyNestingContext(int nestingLevel)\n        {\n            return NestingContext.Get(this, nestingLevel);\n        }\n\n        public NestingContext IncrementNestingContext()\n        {\n            return NestingContext.Get(this, m_NestingLevel + 1);\n        }\n\n        public void Dispose()\n        {\n            if (m_PropertyDrawers?.Count > 0)\n            {\n                foreach (var propertyDrawer in m_PropertyDrawers)\n                {\n                    if (propertyDrawer is IDisposable disposable)\n                        disposable.Dispose();\n                }\n                m_PropertyDrawers.Clear();\n            }\n\n            if (m_DecoratorDrawers?.Count > 0)\n            {\n                foreach (var decoratorDrawer in m_DecoratorDrawers)\n                {\n                    if (decoratorDrawer is IDisposable disposable)\n                        disposable.Dispose();\n                }\n                m_DecoratorDrawers.Clear();\n            }\n        }\n\n        public struct NestingContext : IDisposable\n        {\n            PropertyHandler m_Handler;\n            int m_NestingLevel;\n            int m_OldNestingLevel;\n\n            public static NestingContext Get(PropertyHandler handler, int nestingLevel)\n            {\n                var result = new NestingContext {m_Handler = handler, m_NestingLevel = nestingLevel};\n                result.Open();\n                return result;\n            }\n\n            public void Dispose()\n            {\n                Close();\n            }\n\n            void Open()\n            {\n                m_OldNestingLevel = m_Handler.m_NestingLevel;\n                m_Handler.m_NestingLevel = m_NestingLevel;\n            }\n\n            void Close()\n            {\n                m_Handler.m_NestingLevel = m_OldNestingLevel;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/ScriptAttributeGUI/PropertyTrait.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    // Base class to derive property drawers from that represent traits and support stacking.\n    // Use this to create custom traits for script variables with custom [[PropertyAttribute]]s.\n    // This class itself just displays a property unmodified. The virtual methods can be overridden\n    // to modify various aspect of how the property is displayed. Usually the overridden methods\n    // should call this base class implementation in order to support stacking, but do additional work.\n    //\n    // Examples of things that can be done as property traits:\n    //  - Indent the property\n    //  - Disable the property depending on some criteria\n    //  - Display a helpbox below the property\n    //  - Display the property without the label so it gets the full Inspector width\n    internal class PropertyTrait : PropertyDrawer\n    {\n        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n        {\n            EditorGUI.PropertyField(position, property, label, true);\n        }\n\n        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)\n        {\n            return EditorGUI.GetPropertyHeight(property, true);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/ScriptAttributeGUI/ScriptAttributeUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing System.Text.RegularExpressions;\nusing Unity.Collections;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Rendering;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n    internal class ScriptAttributeUtility\n    {\n        readonly struct CustomPropertyDrawerContainer\n        {\n            public readonly Type drawerType;\n            public readonly Type[] supportedRenderPipelineTypes;\n            public readonly bool editorForChildClasses;\n\n            public CustomPropertyDrawerContainer(Type drawerType, Type[] supportedRenderPipelineTypes, bool editorForChildClasses)\n            {\n                this.drawerType = drawerType;\n                this.supportedRenderPipelineTypes = supportedRenderPipelineTypes;\n                this.editorForChildClasses = editorForChildClasses;\n            }\n        }\n\n        // Internal API members\n        internal static Stack<PropertyDrawer> s_DrawerStack = new Stack<PropertyDrawer>();\n        private static Dictionary<string, List<PropertyAttribute>> s_BuiltinAttributes = null;\n        static Dictionary<Type, List<FieldInfo>> s_AutoLoadProperties;\n        private static PropertyHandler s_SharedNullHandler = new PropertyHandler();\n        private static PropertyHandler s_NextHandler = new PropertyHandler();\n\n        private static PropertyHandlerCache s_GlobalCache = new PropertyHandlerCache();\n        private static PropertyHandlerCache s_CurrentCache = null;\n\n        static readonly Lazy<Dictionary<Type, CustomPropertyDrawerContainer[]>> k_DrawerTypeForType = new(BuildDrawerTypeForTypeDictionary);\n        static readonly Dictionary<Type, Type> k_DrawerStaticTypesCache = new();\n        static readonly Dictionary<Type, Type[]> k_SupportedRenderPipelinesForSerializedObject = new();\n\n        static readonly Comparer<CustomPropertyDrawerContainer> k_RenderPipelineTypeComparer\n            = Comparer<CustomPropertyDrawerContainer>.Create((c1, c2)\n                =>\n            {\n                var firstRenderPipelineByFullName1 = c1.supportedRenderPipelineTypes?.FirstOrDefaultSorted();\n                var firstRenderPipelineByFullName2 = c2.supportedRenderPipelineTypes?.FirstOrDefaultSorted();\n                return string.Compare(firstRenderPipelineByFullName1?.FullName, firstRenderPipelineByFullName2?.FullName, StringComparison.Ordinal);\n            });\n\n\n        static Type[] s_CurrentRenderPipelineAssetTypeArray;\n\n        static Type[] currentRenderPipelineAssetTypeArray\n        {\n            get\n            {\n                if (s_CurrentRenderPipelineAssetTypeArray != null && s_CurrentRenderPipelineAssetTypeArray[0] == GraphicsSettings.currentRenderPipelineAssetType)\n                    return s_CurrentRenderPipelineAssetTypeArray;\n\n                s_CurrentRenderPipelineAssetTypeArray = new[] { GraphicsSettings.currentRenderPipelineAssetType };\n                return s_CurrentRenderPipelineAssetTypeArray;\n            }\n        }\n\n\n        static void ResetCachedTypesAndAsset()\n        {\n            k_DrawerStaticTypesCache.Clear();\n            ClearGlobalCache();\n        }\n\n        internal static PropertyHandlerCache propertyHandlerCache\n        {\n            get => s_CurrentCache ?? s_GlobalCache;\n            set => s_CurrentCache = value;\n        }\n\n        internal static void ClearGlobalCache()\n        {\n            s_GlobalCache.Clear();\n        }\n\n        private static void PopulateBuiltinAttributes()\n        {\n            s_BuiltinAttributes = new Dictionary<string, List<PropertyAttribute>>();\n\n            AddBuiltinAttribute(\"TextMesh\", \"m_Text\", new MultilineAttribute());\n            // Example: Make Orthographic Size in Camera component be in range between 0 and 1000\n            //AddBuiltinAttribute (\"Camera\", \"m_OrthographicSize\", new RangeAttribute (0, 1000));\n        }\n\n        private static void AddBuiltinAttribute(string componentTypeName, string propertyPath, PropertyAttribute attr)\n        {\n            string key = componentTypeName + \"_\" + propertyPath;\n            if (!s_BuiltinAttributes.ContainsKey(key))\n                s_BuiltinAttributes.Add(key, new List<PropertyAttribute>());\n            s_BuiltinAttributes[key].Add(attr);\n        }\n\n        private static List<PropertyAttribute> GetBuiltinAttributes(SerializedProperty property)\n        {\n            if (property.serializedObject.targetObject == null)\n                return null;\n            Type t = property.serializedObject.targetObject.GetType();\n            string attrKey = t.Name + \"_\" + property.propertyPath;\n            List<PropertyAttribute> attr = null;\n            s_BuiltinAttributes.TryGetValue(attrKey, out attr);\n            return attr;\n        }\n\n        // Build a dictionary when k_DrawerTypeForType is first accessed\n        static Dictionary<Type, CustomPropertyDrawerContainer[]> BuildDrawerTypeForTypeDictionary()\n        {\n            RenderPipelineManager.activeRenderPipelineDisposed += ResetCachedTypesAndAsset;\n            RenderPipelineManager.activeRenderPipelineCreated += ResetCachedTypesAndAsset;\n\n            var tempDictionary = new Dictionary<Type, List<CustomPropertyDrawerContainer>>();\n            foreach (var drawerType in TypeCache.GetTypesDerivedFrom<GUIDrawer>())\n            {\n                //Debug.Log(\"Drawer: \" + type);\n                var customPropertyDrawers = drawerType.GetCustomAttributes<CustomPropertyDrawer>(true);\n                var supportedOnRenderPipelineAttribute = drawerType.GetCustomAttribute<SupportedOnRenderPipelineAttribute>();\n                foreach (CustomPropertyDrawer drawer in customPropertyDrawers)\n                {\n                    var propertyType = drawer.m_Type;\n                    if (!tempDictionary.ContainsKey(propertyType))\n                        tempDictionary.Add(propertyType, new List<CustomPropertyDrawerContainer>());\n\n                    tempDictionary[propertyType].AddSorted(new CustomPropertyDrawerContainer(drawerType, supportedOnRenderPipelineAttribute?.renderPipelineTypes, drawer.m_UseForChildren),\n                        k_RenderPipelineTypeComparer);\n                }\n            }\n\n            var dictionaryWithArrays = new Dictionary<Type, CustomPropertyDrawerContainer[]>();\n            foreach (var kvp in tempDictionary)\n                dictionaryWithArrays.Add(kvp.Key, kvp.Value.ToArray());\n            return dictionaryWithArrays;\n        }\n\n        /// <summary>\n        /// We build our CustomPropertyDrawerContainer cache the first time we access it.\n        /// It used solely to have a quick access to drawer types and their information.\n        /// We have a separate cache to map Type -> Drawer. It will work with managed references too as we map real type to the drawers.\n        /// This cache resets each type we create or dispose a Render Pipeline as SupportedOn can exist on some drawers.\n        /// </summary>\n        /// <param name=\"propertyType\">Find a drawer for provided Type</param>\n        /// <param name=\"renderPipelineAssetTypes\">This can be either GraphicsSettings.currentRenderPipelineAssetType or type from SupportedOnRenderPipeline attribute for serializedObject</param>\n        /// <param name=\"isPropertyTypeAManagedReference\">Specify if it's known that we deal with ManagedReference property</param>\n        /// <returns></returns>\n        internal static Type GetDrawerTypeForType(Type propertyType, Type[] renderPipelineAssetTypes, bool isPropertyTypeAManagedReference = false)\n        {\n            //We map specific types to drawers and it will work with managed references too.\n            if (k_DrawerStaticTypesCache.TryGetValue(propertyType, out var drawerTypeForType))\n                return drawerTypeForType;\n\n            var currentRenderPipelineAssetType = GraphicsSettings.currentRenderPipelineAssetType;\n            Type[] allInterfaces = null;\n            bool[] checkedInterfaces = null;\n            for (var inspectedType = propertyType; inspectedType != null; inspectedType = inspectedType.BaseType)\n            {\n                //In the first case we don't need to check for some properties as we know that we deal not with a Base class\n                //We check only if we have direct drawer and prepare to check interfaces in the next step if they exist\n                var requestedPropertyType = inspectedType == propertyType;\n\n                //Check for class drawers. For generics it would be 2 checks. One for generic type and one for generic definition.\n                //For example, for A <bool> we will check first for A<bool> and then for A<T>.\n                if (TryGetDrawerTypeForTypeFromCache(requestedPropertyType, renderPipelineAssetTypes, isPropertyTypeAManagedReference, inspectedType, currentRenderPipelineAssetType, out var drawerType))\n                {\n                    k_DrawerStaticTypesCache.Add(propertyType, drawerType);\n                    return drawerType;\n                }\n\n                if (requestedPropertyType)\n                {\n                    //Gather all interfaces for requested property type\n                    allInterfaces = inspectedType.GetInterfaces();\n                    checkedInterfaces = new bool[allInterfaces.Length];\n\n                    // Calculate inheritance level for each interface\n                    var interfaceLevels = new Dictionary<Type, int>();\n                    foreach (var interfaceType in allInterfaces)\n                        CalculateInheritanceLevel(interfaceType, 0, interfaceLevels);\n\n                    // Sort interfaces by inheritance level and then by name\n                    Array.Sort(allInterfaces, (x, y) =>\n                    {\n                        var levelComparison = interfaceLevels[x].CompareTo(interfaceLevels[y]);\n                        return levelComparison != 0 ? levelComparison : string.CompareOrdinal(x.Name, y.Name);\n                    });\n                }\n\n                if ((!requestedPropertyType || inspectedType.IsInterface) && allInterfaces != null && allInterfaces.Length != 0)\n                {\n                    // Get all interfaces for the current inspected type\n                    var baseTypeInterfaces = inspectedType.IsInterface ? null : inspectedType.GetInterfaces();\n                    for (int i = 0; i < allInterfaces.Length; i++)\n                    {\n                        // Skipped already checked interfaces\n                        if (checkedInterfaces[i])\n                            continue;\n\n                        // Exclude interfaces that are implemented by the base type\n                        var interfaceType = allInterfaces[i];\n                        if (baseTypeInterfaces != null && baseTypeInterfaces.ContainsByEquals(interfaceType))\n                            continue;\n\n                        // Check if there's an appropriate drawer for the interface\n                        checkedInterfaces[i] = true;\n                        if (TryGetDrawerTypeForTypeFromCache(requestedPropertyType, renderPipelineAssetTypes, isPropertyTypeAManagedReference, interfaceType, currentRenderPipelineAssetType, out drawerType))\n                        {\n                            k_DrawerStaticTypesCache.Add(propertyType, drawerType);\n                            return drawerType;\n                        }\n                    }\n                }\n            }\n\n            return null;\n        }\n\n        static int CalculateInheritanceLevel(Type interfaceType, int currentLevel, Dictionary<Type, int> processedInterfaces)\n        {\n            // Get parent interfaces\n            var parentInterfaces = interfaceType.GetInterfaces();\n\n            // Base case: if there are no parent interfaces, return current inheritance level\n            if (parentInterfaces.Length == 0)\n                return AddOrReplaceInterfaceLevel(currentLevel);\n\n            // Recursive case: return the minimum inheritance level minus 1 of the parent interfaces\n            var minParentLevel = int.MaxValue;\n            for (var i = 0; i < parentInterfaces.Length; i++)\n            {\n                var parentLevel = CalculateInheritanceLevel(parentInterfaces[i], currentLevel + 1, processedInterfaces);\n                if (parentLevel < minParentLevel)\n                    minParentLevel = parentLevel;\n            }\n\n            return AddOrReplaceInterfaceLevel(minParentLevel - 1);\n\n            //Local method just to simplify code\n            int AddOrReplaceInterfaceLevel(int newLevel)\n            {\n                // Check if the interface has already been processed and update its inheritance level if necessary\n                if (processedInterfaces.TryGetValue(interfaceType, out var level))\n                {\n                    // If the interface has already been processed and the new inheritance level is greater than the current one, update it\n                    if (level >= newLevel)\n                        return level;\n\n                    processedInterfaces[interfaceType] = newLevel;\n                    return newLevel;\n                }\n                processedInterfaces.Add(interfaceType, newLevel);\n                return newLevel;\n            }\n        }\n\n        static bool TryGetDrawerTypeForTypeFromCache(bool requestedPropertyType, Type[] renderPipelineAssetTypes, bool isPropertyTypeIsManagedReference, Type currentType, Type currentRenderPipelineAssetType,\n            out Type drawerType)\n        {\n            drawerType = null;\n            // check for exact type\n            if (TryExtractDrawerTypeForTypeFromCache(requestedPropertyType, renderPipelineAssetTypes, isPropertyTypeIsManagedReference, currentType, currentRenderPipelineAssetType, out drawerType))\n                return true;\n\n            // check for base generic versions of the drawers\n            if (!currentType.IsGenericType)\n                return false;\n\n            var genericDefinition = currentType.GetGenericTypeDefinition();\n            return TryExtractDrawerTypeForTypeFromCache(requestedPropertyType, renderPipelineAssetTypes, isPropertyTypeIsManagedReference, genericDefinition, currentRenderPipelineAssetType, out drawerType);\n        }\n\n        static bool TryExtractDrawerTypeForTypeFromCache(bool requestedPropertyType, Type[] renderPipelineAssetTypes, bool isPropertyTypeIsManagedReference, Type currentType, Type currentRenderPipelineAssetType,\n            out Type drawerType)\n        {\n            drawerType = null;\n            // Extract drawers for the current type from the cache\n            if (!k_DrawerTypeForType.Value.TryGetValue(currentType, out var drawerTypes))\n                return false;\n\n            // Check if there's an appropriate drawer for the current type and render pipeline. This is where we check for SupportedOnRenderPipelineAttribute\n            var result = TryFindDrawers(renderPipelineAssetTypes, drawerTypes, currentRenderPipelineAssetType, out var customPropertyDrawerContainer);\n            if (!IsAppropriateDrawerFound())\n                return false;\n\n            drawerType = customPropertyDrawerContainer.drawerType;\n            return true;\n\n            //Extracted just to simplify a condition\n            bool IsAppropriateDrawerFound()\n            {\n                if (!result)\n                    return false;\n\n                //When we check for requested property type we don't need to check for editorForChildClasses and managed reference type\n                if (requestedPropertyType)\n                    return true;\n\n                // Check for drawers with editorForChildClasses set to true and special case for managed references.\n                // The custom property drawers for those are defined with 'useForChildren=false'\n                // (otherwise the dynamic type is not taking into account in the custom property\n                // drawer resolution) so even if 's_DrawerTypeForType' is built (based on static types)\n                // we have to check base types for custom property drawers manually.\n                // Managed references with no drawers should properly try to fallback\n                return (customPropertyDrawerContainer.editorForChildClasses || isPropertyTypeIsManagedReference);\n            }\n        }\n\n        static bool TryFindDrawers(Type[] renderPipelineAssetTypes, CustomPropertyDrawerContainer[] drawerTypes, Type currentRenderPipelineAssetType,\n            out CustomPropertyDrawerContainer customPropertyDrawerContainer)\n        {\n            CustomPropertyDrawerContainer? supportedOnRenderPipelineDrawer = null;\n            CustomPropertyDrawerContainer? supportedByBaseRenderPipelineDrawer = null;\n            CustomPropertyDrawerContainer? regularDrawer = null;\n\n            for (var i = 0; i < drawerTypes.Length; i++)\n            {\n                var drawerContainer = drawerTypes[i];\n                if (drawerContainer.supportedRenderPipelineTypes == null)\n                {\n                    regularDrawer ??= drawerContainer;\n                    continue;\n                }\n\n                if (renderPipelineAssetTypes == null)\n                    continue;\n\n                for (int j = 0; j < renderPipelineAssetTypes.Length; j++)\n                {\n                    var renderPipelineAssetType = renderPipelineAssetTypes[j];\n                    var supportedMode = SupportedOnRenderPipelineAttribute.GetSupportedMode(drawerContainer.supportedRenderPipelineTypes, renderPipelineAssetType);\n                    switch (supportedMode)\n                    {\n                        case SupportedOnRenderPipelineAttribute.SupportedMode.Supported:\n                            if (supportedOnRenderPipelineDrawer == null || renderPipelineAssetType == currentRenderPipelineAssetType)\n                                supportedOnRenderPipelineDrawer = drawerContainer;\n                            break;\n                        case SupportedOnRenderPipelineAttribute.SupportedMode.SupportedByBaseClass:\n                            supportedByBaseRenderPipelineDrawer ??= drawerContainer;\n                            break;\n                    }\n                }\n            }\n\n            if (supportedOnRenderPipelineDrawer.HasValue)\n            {\n                customPropertyDrawerContainer = supportedOnRenderPipelineDrawer.Value;\n                return true;\n            }\n\n            if (supportedByBaseRenderPipelineDrawer.HasValue)\n            {\n                customPropertyDrawerContainer = supportedByBaseRenderPipelineDrawer.Value;\n                return true;\n            }\n\n            customPropertyDrawerContainer = regularDrawer ?? default;\n            return regularDrawer.HasValue;\n        }\n\n        /// <summary>\n        /// Does the same thing as 'GetDrawerTypeForType' (with the same side effect of building the cache)\n        /// but also plays well with Managed References. If the property that is used as a reference for the drawer\n        /// query is of a managed reference type, the class parents are also looked up as fallbacks.\n        /// </summary>\n        /// <param name=\"property\"></param>\n        /// <param name=\"type\"></param>\n        /// <returns>The custom property drawer type or 'null' if not found.</returns>\n        internal static Type GetDrawerTypeForPropertyAndType(SerializedProperty property, Type type)\n        {\n            //Try to gather SupportedOn from Serialized Object and rely on this instead of GraphicsSettings.currentRenderPipelineAssetType if exist\n            var serializedObject = property.serializedObject;\n            var serializedObjectType = serializedObject.targetObject.GetType();\n            if (!k_SupportedRenderPipelinesForSerializedObject.TryGetValue(serializedObjectType, out var supportedOnRenderPipelineTypes))\n            {\n                var supportedOn = serializedObjectType.GetCustomAttribute<SupportedOnRenderPipelineAttribute>();\n                supportedOnRenderPipelineTypes = supportedOn?.renderPipelineTypes;\n                k_SupportedRenderPipelinesForSerializedObject.Add(serializedObjectType, supportedOnRenderPipelineTypes);\n            }\n\n            //Choose to use SupportedOn from SO if exist or current RenderPipelineAsset.\n            //If our SO has SupportedOn it will indicate to our system that this SO used specifically with defined Render Pipeline Asset types\n            var renderPipelineAssetTypes = supportedOnRenderPipelineTypes ?? (GraphicsSettings.isScriptableRenderPipelineEnabled ? currentRenderPipelineAssetTypeArray : null);\n\n            return GetDrawerTypeForType(type, renderPipelineAssetTypes, property.propertyType == SerializedPropertyType.ManagedReference);\n        }\n\n        private static List<PropertyAttribute> GetFieldAttributes(FieldInfo field)\n        {\n            if (field == null)\n                return null;\n\n            var attrs = field.GetCustomAttributes<PropertyAttribute>(true);\n            Comparer<PropertyAttribute> comparer = null;\n            List<PropertyAttribute> propertyAttributeList = null;\n            foreach (PropertyAttribute attribute in attrs)\n            {\n                propertyAttributeList ??= new List<PropertyAttribute>();\n                comparer ??= Comparer<PropertyAttribute>.Create((p1, p2) => p1.order.CompareTo(p2.order));\n\n                propertyAttributeList.AddSorted(attribute, comparer);\n            }\n\n            return propertyAttributeList;\n        }\n\n        /// <summary>\n        /// Returns the field info and field type for the property. The types are based on the\n        /// static field definition.\n        /// </summary>\n        /// <param name=\"property\"></param>\n        /// <param name=\"type\"></param>\n        /// <returns></returns>\n        internal static FieldInfo GetFieldInfoAndStaticTypeFromProperty(SerializedProperty property, out Type type)\n        {\n            var classType = GetScriptTypeFromProperty(property);\n            if (classType == null)\n            {\n                type = null;\n                return null;\n            }\n\n            var fieldPath = property.propertyPath;\n            if (property.isReferencingAManagedReferenceField)\n            {\n                // When the field we are trying to access is a dynamic instance, things are a bit more tricky\n                // since we cannot \"statically\" (looking only at the parent class field types) know the actual\n                // \"classType\" of the parent class.\n\n                // The issue also is that at this point our only view on the object is the very limited SerializedProperty.\n\n                // So we have to:\n                // 1. try to get the FQN from for the current managed type from the serialized data,\n                // 2. get the path *in the current managed instance* of the field we are pointing to,\n                // 3. foward that to 'GetFieldInfoFromPropertyPath' as if it was a regular field,\n\n                var objectTypename = property.GetFullyQualifiedTypenameForCurrentTypeTreeInternal();\n                GetTypeFromManagedReferenceFullTypeName(objectTypename, out classType);\n\n                fieldPath = property.GetPropertyPathInCurrentManagedTypeTreeInternal();\n            }\n\n            if (classType == null)\n            {\n                type = null;\n                return null;\n            }\n\n            return GetFieldInfoFromPropertyPath(classType, fieldPath, out type);\n        }\n\n        /// <summary>\n        /// Returns the field info and type for the property. Contrary to GetFieldInfoAndStaticTypeFromProperty,\n        /// when confronted with a managed reference the dynamic instance type is returned.\n        /// </summary>\n        /// <param name=\"property\"></param>\n        /// <param name=\"type\"></param>\n        /// <returns></returns>\n        internal static FieldInfo GetFieldInfoFromProperty(SerializedProperty property, out Type type)\n        {\n            var fieldInfo = GetFieldInfoAndStaticTypeFromProperty(property, out type);\n            if (fieldInfo == null)\n                return null;\n\n            // Managed references are a special case, we need to override the static type\n            // returned by 'GetFieldInfoFromPropertyPath' for custom property handler matching\n            // by the dynamic type of the instance.\n            if (property.propertyType == SerializedPropertyType.ManagedReference)\n            {\n                // Try to get a Type instance for the managed reference\n                if (GetTypeFromManagedReferenceFullTypeName(property.managedReferenceFullTypename, out var managedReferenceInstanceType))\n                {\n                    type = managedReferenceInstanceType;\n                }\n\n                // We keep the fallback to the field type returned by 'GetFieldInfoFromPropertyPath'.\n            }\n\n            return fieldInfo;\n        }\n\n        /// <summary>\n        /// Create a Type instance from the managed reference full type name description.\n        /// The expected format for the typename string is the one returned by SerializedProperty.managedReferenceFullTypename.\n        /// </summary>\n        /// <param name=\"managedReferenceFullTypename\"></param>\n        /// <param name=\"managedReferenceInstanceType\"></param>\n        /// <returns></returns>\n        internal static bool GetTypeFromManagedReferenceFullTypeName(string managedReferenceFullTypename, out Type managedReferenceInstanceType)\n        {\n            managedReferenceInstanceType = null;\n\n            var splitIndex = managedReferenceFullTypename.IndexOf(' ');\n            if (splitIndex > 0)\n            {\n                var assemblyPart = managedReferenceFullTypename.Substring(0, splitIndex);\n                var nsClassnamePart = managedReferenceFullTypename.Substring(splitIndex);\n                managedReferenceInstanceType = Type.GetType($\"{nsClassnamePart}, {assemblyPart}\");\n            }\n\n            return managedReferenceInstanceType != null;\n        }\n\n        private static Type GetScriptTypeFromProperty(SerializedProperty property)\n        {\n            if (property.serializedObject.targetObject != null)\n                return property.serializedObject.targetObject.GetType();\n\n            // Fallback in case the targetObject has been destroyed but the property is still valid.\n            SerializedProperty scriptProp = property.serializedObject.FindProperty(\"m_Script\");\n\n            if (scriptProp == null)\n                return null;\n\n            MonoScript script = scriptProp.objectReferenceValue as MonoScript;\n\n            if (script == null)\n                return null;\n\n            return script.GetClass();\n        }\n\n        struct Cache : IEquatable<Cache>\n        {\n            Type host;\n            string path;\n\n            public Cache(Type host, string path)\n            {\n                this.host = host;\n                this.path = path;\n            }\n\n            public bool Equals(Cache other)\n            {\n                return Equals(host, other.host) && string.Equals(path, other.path);\n            }\n\n            public override bool Equals(object obj)\n            {\n                if (ReferenceEquals(null, obj)) return false;\n                return obj is Cache cache && Equals(cache);\n            }\n\n            public override int GetHashCode()\n            {\n                unchecked\n                {\n                    return ((host != null ? host.GetHashCode() : 0) * 397) ^ (path != null ? path.GetHashCode() : 0);\n                }\n            }\n        }\n\n        class FieldInfoCache\n        {\n            public FieldInfo fieldInfo;\n            public Type type;\n        }\n\n        static Dictionary<Cache, FieldInfoCache> s_FieldInfoFromPropertyPathCache = new Dictionary<Cache, FieldInfoCache>();\n\n        private static FieldInfo GetFieldInfoFromPropertyPath(Type host, string path, out Type type)\n        {\n            Cache cache = new Cache(host, path);\n\n            if (s_FieldInfoFromPropertyPathCache.TryGetValue(cache, out var fieldInfoCache))\n            {\n                type = fieldInfoCache?.type;\n                return fieldInfoCache?.fieldInfo;\n            }\n\n            const string arrayData = @\"\\.Array\\.data\\[[0-9]+\\]\";\n            // we are looking for array element only when the path ends with Array.data[x]\n            var lookingForArrayElement = Regex.IsMatch(path, arrayData + \"$\");\n            // remove any Array.data[x] from the path because it is prevents cache searching.\n            path = Regex.Replace(path, arrayData, \".___ArrayElement___\");\n\n            FieldInfo fieldInfo = null;\n            type = host;\n            string[] parts = path.Split('.');\n            for (int i = 0; i < parts.Length; i++)\n            {\n                string member = parts[i];\n                // GetField on class A will not find private fields in base classes to A,\n                // so we have to iterate through the base classes and look there too.\n                // Private fields are relevant because they can still be shown in the Inspector,\n                // and that applies to private fields in base classes too.\n                FieldInfo foundField = null;\n                for (Type currentType = type; foundField == null && currentType != null; currentType = currentType.BaseType)\n                    foundField = currentType.GetField(member, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);\n\n                if (foundField == null)\n                {\n                    type = null;\n                    s_FieldInfoFromPropertyPathCache.Add(cache, null);\n                    return null;\n                }\n\n                fieldInfo = foundField;\n                type = fieldInfo.FieldType;\n                // we want to get the element type if we are looking for Array.data[x]\n                if (i < parts.Length - 1 && parts[i + 1] == \"___ArrayElement___\" && type.IsArrayOrList())\n                {\n                    i++; // skip the \"___ArrayElement___\" part\n                    type = type.GetArrayOrListElementType();\n                }\n            }\n\n            // we want to get the element type if we are looking for Array.data[x]\n            if (lookingForArrayElement && type != null && type.IsArrayOrList())\n                type = type.GetArrayOrListElementType();\n\n            fieldInfoCache = new FieldInfoCache\n            {\n                type = type,\n                fieldInfo = fieldInfo\n            };\n            s_FieldInfoFromPropertyPathCache.Add(cache, fieldInfoCache);\n            return fieldInfo;\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal static PropertyHandler GetHandler(SerializedProperty property)\n        {\n            if (property == null)\n                return s_SharedNullHandler;\n\n            // Don't use custom drawers in debug mode\n            if (property.serializedObject.inspectorMode != InspectorMode.Normal)\n                return s_SharedNullHandler;\n\n            // If the drawer is cached, use the cached drawer\n            PropertyHandler handler = propertyHandlerCache.GetHandler(property);\n            if (handler != null)\n                return handler;\n\n            Type propertyType = null;\n            List<PropertyAttribute> attributes = null;\n            FieldInfo field = null;\n\n            // Determine if SerializedObject target is a script or a builtin type\n            Object target = property.serializedObject.targetObject;\n            if (NativeClassExtensionUtilities.ExtendsANativeType(target))\n            {\n                // For scripts, use reflection to get FieldInfo for the member the property represents\n                field = GetFieldInfoFromProperty(property, out propertyType);\n\n                // Use reflection to see if this member has an attribute\n                attributes = GetFieldAttributes(field);\n            }\n            else\n            {\n                // For builtin types, look if we hardcoded an attribute for this property\n                // First initialize the hardcoded properties if not already done\n                if (s_BuiltinAttributes == null)\n                    PopulateBuiltinAttributes();\n\n                attributes = GetBuiltinAttributes(property);\n            }\n\n            handler = s_NextHandler;\n\n            if (attributes != null)\n            {\n                for (int i = 0; i < attributes.Count; i++)\n                    handler.HandleAttribute(property, attributes[i], field, propertyType);\n            }\n\n            if (propertyType != null)\n                handler.HandleDrawnType(property, propertyType, propertyType, field, null);\n\n            if (handler.empty)\n            {\n                propertyHandlerCache.SetHandler(property, s_SharedNullHandler);\n                handler = s_SharedNullHandler;\n            }\n            else\n            {\n                propertyHandlerCache.SetHandler(property, handler);\n                s_NextHandler = new PropertyHandler();\n            }\n\n            return handler;\n        }\n\n        internal static bool CanUseSameHandler(SerializedProperty p1, SerializedProperty p2)\n        {\n            return PropertyHandlerCache.CanUseSameHandler(p1, p2);\n        }\n\n        internal static List<FieldInfo> GetAutoLoadProperties(Type type)\n        {\n            if (s_AutoLoadProperties == null)\n                s_AutoLoadProperties = new Dictionary<Type, List<FieldInfo>>();\n\n            if (!s_AutoLoadProperties.TryGetValue(type, out var list))\n            {\n                list = new List<FieldInfo>();\n                foreach (var field in type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))\n                {\n                    if (field.FieldType == typeof(SerializedProperty) && field.IsDefined(typeof(CachePropertyAttribute), false))\n                        list.Add(field);\n                }\n\n                s_AutoLoadProperties.Add(type, list);\n            }\n\n            return list;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/ScriptBindings/Editor.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing uei = UnityEngine.Internal;\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [StructLayout(LayoutKind.Sequential)]\n    [RequiredByNativeCode]\n    [NativeHeader(\"Editor/Mono/Inspector/Core/ScriptBindings/Editor.bindings.h\")]\n    [StaticAccessor(\"EditorBindings\", StaticAccessorType.DoubleColon)]\n    public partial class Editor\n    {\n        // Make a custom editor for /targetObject/ or /objects/.\n        extern static Editor CreateEditorWithContextInternal(Object[] targetObjects, Object context, Type editorType);\n        internal extern static Vector2 GetCurrentMousePosition();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/Utils/InspectorWindowUtils.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal static class InspectorWindowUtils\n    {\n        public struct LayoutGroupChecker : IDisposable\n        {\n            // cache the layout group we expect to have at the end of drawing this editor\n            GUILayoutGroup m_ExpectedGroup;\n            GUILayoutGroup expectedGroup => m_ExpectedGroup ?? (m_ExpectedGroup = GUILayoutUtility.current.topLevel);\n\n            public void Dispose()\n            {\n                if (GUIUtility.guiIsExiting)\n                {\n                    return; //Something has already requested an ExitGUI\n                }\n\n                // Check and try to cleanup layout groups.\n                if (GUILayoutUtility.current.topLevel != expectedGroup)\n                {\n                    if (!GUILayoutUtility.current.layoutGroups.Contains(expectedGroup))\n                    {\n                        // We can't recover from this, so we error.\n                        Debug.LogError(\"Expected top level layout group missing! Too many GUILayout.EndScrollView/EndVertical/EndHorizontal?\");\n                        GUIUtility.ExitGUI();\n                    }\n                    else\n                    {\n                        // We can recover from this, so we warning.\n                        Debug.LogWarning(\"Unexpected top level layout group! Missing GUILayout.EndScrollView/EndVertical/EndHorizontal?\");\n\n                        while (GUILayoutUtility.current.topLevel != expectedGroup)\n                            GUILayoutUtility.EndLayoutGroup();\n                    }\n                }\n            }\n        }\n\n        public static void GetPreviewableTypes(out Dictionary<Type, List<Type>> previewableTypes)\n        {\n            // We initialize this list once per InspectorWindow, instead of globally.\n            // This means that if the user is debugging an IPreviewable structure,\n            // the InspectorWindow can be closed and reopened to refresh this list.\n\n            previewableTypes = new Dictionary<Type, List<Type>>();\n            foreach (var type in TypeCache.GetTypesDerivedFrom<IPreviewable>())\n            {\n                // we don't want Editor classes with preview here.\n                if (type.IsSubclassOf(typeof(Editor)))\n                {\n                    continue;\n                }\n\n                if (type.GetConstructor(Type.EmptyTypes) == null)\n                {\n                    Debug.LogError($\"{type} does not contain a default constructor, it will not be registered as a \" +\n                        $\"preview handler. Use the Initialize function to set up your object instead.\");\n                    continue;\n                }\n\n                // Record only the types with a CustomPreviewAttribute.\n                var attrs = type.GetCustomAttributes(typeof(CustomPreviewAttribute), false) as CustomPreviewAttribute[];\n                foreach (CustomPreviewAttribute previewAttr in attrs)\n                {\n                    if (previewAttr.m_Type == null)\n                    {\n                        continue;\n                    }\n\n                    foreach (var customPreviewType in new[] { previewAttr.m_Type }.Concat(TypeCache.GetTypesDerivedFrom(previewAttr.m_Type)))\n                    {\n                        if (!previewableTypes.TryGetValue(customPreviewType, out var types))\n                        {\n                            types = new List<Type>();\n                            previewableTypes.Add(customPreviewType, types);\n                        }\n                        types.Add(type);\n                    }\n                }\n            }\n        }\n\n        public static Editor GetFirstNonImportInspectorEditor(Editor[] editors)\n        {\n            foreach (Editor e in editors)\n            {\n                // Check for target rather than the editor type itself,\n                // because some importers use default inspector\n                if (e.target is AssetImporter)\n                {\n                    continue;\n                }\n\n                return e;\n            }\n\n            return null;\n        }\n\n        internal static bool IsExcludedClass(Object target)\n        {\n            return ModuleMetadata.GetModuleIncludeSettingForObject(target) == ModuleIncludeSetting.ForceExclude;\n        }\n\n        private static Dictionary<Type, ObsoleteAttribute> s_ObsoleteTypes;\n\n        public static void DisplayDeprecationMessageIfNecessary(Editor editor)\n        {\n            if (!editor || !editor.target)\n            {\n                return;\n            }\n\n            if (s_ObsoleteTypes == null)\n            {\n                var obsoleteTypes = TypeCache.GetTypesWithAttribute<ObsoleteAttribute>();\n                s_ObsoleteTypes = new Dictionary<Type, ObsoleteAttribute>(obsoleteTypes.Count);\n                foreach (var type in obsoleteTypes)\n                {\n                    var attr = (ObsoleteAttribute)Attribute.GetCustomAttribute(type, typeof(ObsoleteAttribute));\n                    s_ObsoleteTypes[type] = attr;\n                }\n            }\n\n            if (!s_ObsoleteTypes.TryGetValue(editor.target.GetType(), out var obsoleteAttribute))\n            {\n                return;\n            }\n\n            var message = string.IsNullOrEmpty(obsoleteAttribute.Message) ? \"This component has been marked as obsolete.\" : obsoleteAttribute.Message;\n            EditorGUILayout.HelpBox(message, obsoleteAttribute.IsError ? MessageType.Error : MessageType.Warning);\n        }\n\n        public static void DrawAddedComponentBackground(Rect position, Object[] targets, float adjust = 0)\n        {\n            if (Event.current.type == EventType.Repaint && targets.Length == 1)\n            {\n                Component comp = targets[0] as Component;\n                if (comp != null &&\n                    EditorGUIUtility.comparisonViewMode == EditorGUIUtility.ComparisonViewMode.None &&\n                    PrefabUtility.GetCorrespondingConnectedObjectFromSource(comp.gameObject) != null &&\n                    PrefabUtility.GetCorrespondingObjectFromSource(comp) == null)\n                {\n                    // Ensure colored margin here for component body doesn't overlap colored margin from InspectorTitlebar,\n                    // and extends down to exactly touch the separator line between/after components.\n                    EditorGUI.DrawOverrideBackgroundApplicable(new Rect(position.x, position.y + 3 + adjust, position.width,\n                        position.height - 2));\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Core/Utils/PropertyDrawerCache.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class PropertyHandlerCache : IDisposable\n    {\n        internal readonly protected Dictionary<int, PropertyHandler> m_PropertyHandlers = new Dictionary<int, PropertyHandler>();\n\n        internal PropertyHandler GetHandler(SerializedProperty property)\n        {\n            PropertyHandler handler;\n            int key = GetPropertyHash(property);\n            if (m_PropertyHandlers.TryGetValue(key, out handler))\n                return handler;\n\n            return null;\n        }\n\n        internal void SetHandler(SerializedProperty property, PropertyHandler handler)\n        {\n            int key = GetPropertyHash(property);\n            m_PropertyHandlers[key] = handler;\n        }\n\n        internal static bool CanUseSameHandler(SerializedProperty p1, SerializedProperty p2)\n        {\n            return GetPropertyHash(p1) == GetPropertyHash(p2);\n        }\n\n        private static int GetPropertyHash(SerializedProperty property)\n        {\n            if (property.serializedObject.targetObject == null)\n                return 0;\n\n            // For efficiency, ignore indices inside brackets [] in order to make array elements share handlers.\n            int key = property.serializedObject.targetObject.GetInstanceID() ^ property.hashCodeForPropertyPathWithoutArrayIndex;\n            if (property.propertyType == SerializedPropertyType.ObjectReference)\n            {\n                key ^= property.objectReferenceInstanceIDValue;\n            }\n            return key;\n        }\n\n        public void Clear()\n        {\n            if (m_PropertyHandlers.Count > 0)\n            {\n                foreach (var handler in m_PropertyHandlers.Values)\n                {\n                    handler.Dispose();\n                }\n\n                m_PropertyHandlers.Clear();\n            }\n        }\n\n        public void Dispose() => Clear();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/CubemapArrayInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\n\nnamespace UnityEngine\n{\n    [ExcludeFromPreset]\n    [CustomEditor(typeof(CubemapArray))]\n    internal class CubemapArrayInspector : TextureInspector\n    {\n        private PreviewRenderUtility m_PreviewUtility;\n        private Material m_Material;\n        private int m_Slice;\n        private int m_Mip;\n        private int m_MipCount;\n\n        private Mesh m_Mesh;\n        public Vector2 m_PreviewDir = new Vector2(0, 0);\n\n        static class Styles\n        {\n            public static readonly GUIContent slice = EditorGUIUtility.TrTextContent(\"Slice\", \"Displayed array slice\");\n            public static readonly GUIStyle toolbarLabel = \"toolbarLabel\";\n        }\n\n        protected override void OnEnable()\n        {\n            base.OnEnable();\n            InitPreview();\n        }\n\n        protected override void OnDisable()\n        {\n            if (m_PreviewUtility != null)\n            {\n                m_PreviewUtility.Cleanup();\n                m_PreviewUtility = null;\n            }\n            base.OnDisable();\n        }\n\n        public override void OnPreviewSettings()\n        {\n            CubemapArray t = (CubemapArray)target;\n\n            EditorGUI.BeginDisabledGroup(t.cubemapCount <= 1);\n            EditorGUILayout.LabelField(Styles.slice, GUILayout.Width(40));\n            m_Slice = EditorGUILayout.IntSlider(m_Slice, 0, t.cubemapCount - 1, GUILayout.Width(120));\n            EditorGUI.EndDisabledGroup();\n            m_Material.SetFloat(\"_SliceIndex\", (float)m_Slice);\n\n            EditorGUI.BeginDisabledGroup(!TextureUtil.NeedsExposureControl(t));\n            m_ExposureSliderValue = EditorGUIInternal.ExposureSlider(m_ExposureSliderValue, ref m_ExposureSliderMax, EditorStyles.toolbarSlider);\n            EditorGUI.EndDisabledGroup();\n            m_Material.SetFloat(\"_Exposure\", GetExposureValueForTexture(t));\n\n            EditorGUI.BeginDisabledGroup(m_MipCount == 0);\n            GUILayout.Box(EditorGUIUtility.IconContent(\"PreTextureMipMapLow\"), Styles.toolbarLabel);\n            m_Mip = Mathf.RoundToInt(GUILayout.HorizontalSlider(m_Mip, m_MipCount - 1, 0, GUILayout.Width(64)));\n            GUILayout.Box(EditorGUIUtility.IconContent(\"PreTextureMipMapHigh\"), Styles.toolbarLabel);\n            EditorGUI.EndDisabledGroup();\n            m_Material.SetFloat(\"_Mip\", m_Mip);\n        }\n\n        public override void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            if (!SystemInfo.supportsCubemapArrayTextures || (m_Material != null && !m_Material.shader.isSupported))\n            {\n                if (Event.current.type == EventType.Repaint)\n                    EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), \"Cubemap array preview is not supported\");\n                return;\n            }\n\n            CubemapArray t = (CubemapArray)target;\n            m_Material.mainTexture = t;\n\n            m_PreviewUtility.BeginPreview(r, background);\n            const float previewDistance = 6.0f;\n            m_PreviewDir = PreviewGUI.Drag2D(m_PreviewDir, r);\n\n            m_PreviewUtility.camera.transform.position = -Vector3.forward * previewDistance;\n            m_PreviewUtility.camera.transform.rotation = Quaternion.identity;\n            Quaternion rot = Quaternion.Euler(m_PreviewDir.y, 0, 0) * Quaternion.Euler(0, m_PreviewDir.x, 0);\n\n            m_PreviewUtility.DrawMesh(m_Mesh, Vector3.zero, rot, m_Material, 0);\n            m_PreviewUtility.Render();\n            Texture renderedTexture = m_PreviewUtility.EndPreview();\n            GUI.DrawTexture(r, renderedTexture, ScaleMode.StretchToFill, false);\n\n            EditorGUI.DropShadowLabel(new Rect(r.x, r.y + 10, r.width, 30),\n                \"Slice \" + m_Slice + \"\\nMip \" + m_Mip);\n        }\n\n        void InitPreview()\n        {\n            OnDisable();\n            m_PreviewUtility = new PreviewRenderUtility();\n            m_PreviewUtility.camera.fieldOfView = 15f;\n            m_Mesh = PreviewRenderUtility.GetPreviewSphere();\n\n            var t = target as CubemapArray;\n            if (t == null)\n                return;\n\n            m_Material = (Material)EditorGUIUtility.LoadRequired(\"Previews/CubeArrayPreview.mat\");\n            m_Material.mainTexture = t;\n\n            m_Slice = 0;\n            m_Mip = Mathf.RoundToInt(GetMipLevelForRendering());\n            m_MipCount = TextureUtil.GetMipmapCount(t);\n\n            m_Material.SetFloat(\"_SliceIndex\", (float)m_Slice);\n            m_Material.SetFloat(\"_Mip\", m_Mip);\n            m_Material.SetFloat(\"_Exposure\", GetExposureValueForTexture(t));\n        }\n\n        public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height)\n        {\n            // It's not clear what a meaningful preview for a CubemapArray would be - the first slice? Multiple slices composed?\n            // Until we have a clear idea about the best way to do things, return null for now, to indicate no preview.\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/CubemapInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Globalization;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEngine.Experimental.Rendering;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(Cubemap))]\n    internal class CubemapInspector : TextureInspector\n    {\n        internal static class Styles\n        {\n            public const int faceThumbnailSize = 64;\n\n            public static readonly string nativeTextureInfo = L10n.Tr(\"External texture: Unity cannot make changes to this Cubemap.\");\n            public static readonly string compressedTextureInfo = L10n.Tr(\"Compressed texture: Unity can only make limited changes to this Cubemap.\");\n\n            public static readonly string[] faceSelectionLabels = { \"Right\\n(+X)\", \"Left\\n(-X)\", \"Top\\n(+Y)\", \"Bottom\\n(-Y)\", \"Front\\n(+Z)\", \"Back\\n(-Z)\" };\n\n            public static readonly string faceSizeLabel = L10n.Tr(\"Face size\");\n            public static readonly string faceSizeWarning = L10n.Tr(\"Lowering face size is a destructive operation, you might need to re-assign the textures later to fix resolution issues. It's preferable to use Cubemap texture import type instead of Legacy Cubemap assets.\");\n            public static readonly string[] faceSizeOptionLabels = { \"16\", \"32\", \"64\", \"128\", \"256\", \"512\", \"1024\", \"2048\" };\n            public static readonly int[] faceSizeOptionValues = { 16, 32, 64, 128, 256, 512, 1024, 2048 };\n\n            public static readonly string generateMipmapLabel = L10n.Tr(\"Generate Mipmap\");\n            public static readonly GUIContent streamingMipmapLevelsContent = EditorGUIUtility.TrTextContent(\"Stream Mipmap Levels\", \"Don't load image data immediately but wait till image data is requested from script.\");\n\n            public static readonly string linearLabel = L10n.Tr(\"Linear\");\n\n            public static readonly string readableLabel = L10n.Tr(\"Readable\");\n        }\n\n        private Texture2D[] m_Images;\n\n        protected override void OnDisable()\n        {\n            base.OnDisable();\n\n            if (m_Images != null)\n            {\n                for (int i = 0; i < m_Images.Length; ++i)\n                {\n                    if (m_Images[i] && !EditorUtility.IsPersistent(m_Images[i]))\n                        DestroyImmediate(m_Images[i]);\n                }\n            }\n            m_Images = null;\n        }\n\n        private void InitFaceThumbnailsFromCubemap()\n        {\n            var c = target as Cubemap;\n            if (c is null || c.isNativeTexture || GraphicsFormatUtility.IsCompressedFormat(c.format))\n            {\n                return;\n            }\n\n            if (m_Images == null)\n                m_Images = new Texture2D[6];\n            for (int i = 0; i < m_Images.Length; ++i)\n            {\n                if (m_Images[i] && !EditorUtility.IsPersistent(m_Images[i]))\n                    DestroyImmediate(m_Images[i]);\n\n                if (TextureUtil.GetSourceTexture(c, (CubemapFace)i))\n                {\n                    m_Images[i] = TextureUtil.GetSourceTexture(c, (CubemapFace)i);\n                }\n                else\n                {\n                    m_Images[i] = new Texture2D(Styles.faceThumbnailSize, Styles.faceThumbnailSize, TextureFormat.RGBA32, false);\n                    m_Images[i].hideFlags = HideFlags.HideAndDontSave;\n                    TextureUtil.CopyCubemapFaceIntoTexture(c, (CubemapFace)i, m_Images[i]);\n                }\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            var c = target as Cubemap;\n            if (c == null)\n                return;\n\n            if (c.isNativeTexture)\n            {\n                EditorGUILayout.HelpBox(Styles.nativeTextureInfo, MessageType.Info);\n                return;\n            }\n\n            // A number of option we present in the \"full\" inspector rely on reformatting or writing to the Cubemap to achieve the desired effect.\n            // These operations are not possible on compressed Cubemaps, so we display a limited version of the inspector for them.\n            bool isCompressedTex = GraphicsFormatUtility.IsCompressedFormat(c.format);\n            if (!isCompressedTex)\n            {\n                DisplayFullInspector(c);\n            }\n            else\n            {\n                DisplayInspectorForCompressedCubemap(c);\n            }\n        }\n\n        private void DisplayFullInspector(Cubemap c)\n        {\n            HandleFaceSelectionGUI();\n\n            EditorGUILayout.Space();\n\n            HandleFaceSizeGUI(c);\n            bool useMipMap = HandleGenerateMipmapGUI(c);\n\n            if (useMipMap)\n            {\n                using (new EditorGUI.IndentLevelScope())\n                {\n                    HandleStreamingMipmapGUI(c);\n                }\n            }\n\n            HandleLinearSamplingGUI(c);\n            HandleReadableGUI(c);\n        }\n\n        private void DisplayInspectorForCompressedCubemap(Cubemap c)\n        {\n            EditorGUILayout.HelpBox(Styles.compressedTextureInfo, MessageType.Info);\n\n            bool usesMipMap = TextureUtil.GetMipmapCount(c) > 1;\n            if (usesMipMap)\n            {\n                HandleStreamingMipmapGUI(c);\n            }\n            HandleReadableGUI(c);\n        }\n\n        private void HandleFaceSelectionGUI()\n        {\n            if (m_Images == null)\n                InitFaceThumbnailsFromCubemap();\n\n            EditorGUIUtility.labelWidth = 50;\n\n            using (new GUILayout.VerticalScope())\n            {\n                for (int face = 0; face < 6; face += 2)\n                {\n                    using (new GUILayout.HorizontalScope())\n                    {\n                        ShowFace(Styles.faceSelectionLabels[face], (CubemapFace)face);\n                        ShowFace(Styles.faceSelectionLabels[face + 1], (CubemapFace)face + 1);\n                    }\n                }\n            }\n\n            EditorGUIUtility.labelWidth = 0;\n        }\n\n        private int HandleFaceSizeGUI(Cubemap c)\n        {\n            using (var changed = new EditorGUI.ChangeCheckScope())\n            {\n                EditorGUILayout.HelpBox(Styles.faceSizeWarning, MessageType.Warning);\n                int faceSize = TextureUtil.GetGPUWidth(c);\n                faceSize = EditorGUILayout.IntPopup(Styles.faceSizeLabel, faceSize, Styles.faceSizeOptionLabels, Styles.faceSizeOptionValues);\n\n                if (changed.changed)\n                {\n                    HandleCubemapReformatting(c, faceSize: faceSize);\n                }\n\n                return faceSize;\n            }\n        }\n\n        private bool HandleGenerateMipmapGUI(Cubemap c)\n        {\n            using (var changed = new EditorGUI.ChangeCheckScope())\n            {\n                int mipMaps = TextureUtil.GetMipmapCount(c);\n                bool useMipMap = EditorGUILayout.Toggle(Styles.generateMipmapLabel, mipMaps > 1);\n\n                if (changed.changed)\n                {\n                    HandleCubemapReformatting(c, useMipMap: useMipMap);\n                }\n\n                return useMipMap;\n            }\n        }\n\n        private bool HandleStreamingMipmapGUI(Cubemap c)\n        {\n            using (var changed = new EditorGUI.ChangeCheckScope())\n            {\n                bool streamingMipmaps = TextureUtil.GetCubemapStreamingMipmaps(c);\n                streamingMipmaps = EditorGUILayout.Toggle(Styles.streamingMipmapLevelsContent, streamingMipmaps);\n\n                if (changed.changed)\n                {\n                    TextureUtil.SetCubemapStreamingMipmaps(c, streamingMipmaps);\n                }\n\n                return streamingMipmaps;\n            }\n        }\n\n        private bool HandleLinearSamplingGUI(Cubemap c)\n        {\n            using (var changed = new EditorGUI.ChangeCheckScope())\n            {\n                bool linear = TextureUtil.GetLinearSampled(c);\n                linear = EditorGUILayout.Toggle(Styles.linearLabel, linear);\n\n                if (changed.changed)\n                {\n                    HandleCubemapReformatting(c, linear: linear);\n                }\n\n                return linear;\n            }\n        }\n\n        private bool HandleReadableGUI(Cubemap c)\n        {\n            using (var changed = new EditorGUI.ChangeCheckScope())\n            {\n                bool readable = TextureUtil.IsCubemapReadable(c);\n                readable = EditorGUILayout.Toggle(Styles.readableLabel, readable);\n\n                if (changed.changed)\n                {\n                    TextureUtil.MarkCubemapReadable(c, readable);\n                }\n\n                return readable;\n            }\n        }\n\n        private void HandleCubemapReformatting(Cubemap c, int? faceSize = null, bool? useMipMap = null, bool? linear = null)\n        {\n            // If a value has not been provided, assume that it has not changed and needs to be fetched.\n            if (faceSize == null)\n            {\n                faceSize = TextureUtil.GetGPUWidth(c);\n            }\n            if (useMipMap == null)\n            {\n                useMipMap = TextureUtil.GetMipmapCount(c) > 1;\n            }\n            if (linear == null)\n            {\n                linear = TextureUtil.GetLinearSampled(c);\n            }\n\n            if (TextureUtil.ReformatCubemap(c, faceSize.Value, faceSize.Value, c.format, useMipMap.Value, linear.Value))\n            {\n                InitFaceThumbnailsFromCubemap();\n            }\n        }\n\n        // A minimal list of settings to be shown in the Asset Store preview inspector\n        internal override void OnAssetStoreInspectorGUI()\n        {\n            OnInspectorGUI();\n        }\n\n        private void ShowFace(string label, CubemapFace face)\n        {\n            var c = target as Cubemap;\n            var iface = (int)face;\n            GUI.changed = false;\n\n            var tex = (Texture2D)ObjectField(label, m_Images[iface], typeof(Texture2D), false);\n            if (GUI.changed)\n            {\n                if (tex != null)\n                {\n                    TextureUtil.CopyTextureIntoCubemapFace(tex, c, face);\n                }\n                // enable this line in order to retain connections from cube faces to their corresponding\n                // texture2D assets, this allows auto-update functionality when editing the source texture\n                // images\n                //TextureUtil.SetSourceTexture(c, face, tex);\n                m_Images[iface] = tex;\n            }\n        }\n\n        // Variation of ObjectField where label is not restricted to one line\n        public static Object ObjectField(string label, Object obj, System.Type objType, bool allowSceneObjects, params GUILayoutOption[] options)\n        {\n            using (new GUILayout.HorizontalScope())\n            {\n                Rect r = GUILayoutUtility.GetRect(EditorGUIUtility.labelWidth, EditorGUI.kSingleLineHeight * 2, EditorStyles.label, GUILayout.ExpandWidth(false));\n                GUI.Label(r, label, EditorStyles.label);\n                r = GUILayoutUtility.GetAspectRect(1, EditorStyles.objectField, GUILayout.Width(64));\n                Object retval = EditorGUI.ObjectField(r, obj, objType, allowSceneObjects);\n                return retval;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/CubemapPreview.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class CubemapPreview\n    {\n        static readonly int s_ShaderCubemapRotation = Shader.PropertyToID(\"_CubemapRotation\");\n        static readonly int s_ShaderMip = Shader.PropertyToID(\"_Mip\");\n        static readonly int s_ShaderAlpha = Shader.PropertyToID(\"_Alpha\");\n        static readonly int s_ShaderIntensity = Shader.PropertyToID(\"_Intensity\");\n        static readonly int s_ShaderIsNormalMap = Shader.PropertyToID(\"_IsNormalMap\");\n        static readonly int s_ShaderExposure = Shader.PropertyToID(\"_Exposure\");\n        static readonly int s_ColorspaceIsGamma = Shader.PropertyToID(\"_ColorspaceIsGamma\");\n\n        private enum PreviewType\n        {\n            RGB = 0,\n            Alpha = 1\n        }\n        // Preview settings\n        [SerializeField]\n        private PreviewType             m_PreviewType = PreviewType.RGB;\n        [SerializeField]\n        float                           m_MipLevel = 0.0F;\n        private float                   m_Intensity = 1.0f;\n\n        // Cached preview data\n        private PreviewRenderUtility    m_PreviewUtility;\n        private Mesh                    m_Mesh;\n        private Material                m_Material;\n        public Vector2                  m_PreviewDir = new Vector2(0, 0);\n\n        static class Styles\n        {\n            public static GUIStyle preButton = \"preButton\";\n            public static GUIStyle preSlider = \"preSlider\";\n            public static GUIStyle preSliderThumb = \"preSliderThumb\";\n            public static GUIStyle preLabel = \"preLabel\";\n            public static GUIContent smallZoom = EditorGUIUtility.IconContent(\"PreTextureMipMapLow\");\n            public static GUIContent largeZoom = EditorGUIUtility.IconContent(\"PreTextureMipMapHigh\");\n            public static GUIContent alphaIcon = EditorGUIUtility.IconContent(\"PreTextureAlpha\");\n            public static GUIContent RGBIcon = EditorGUIUtility.IconContent(\"PreTextureRGB\");\n        }\n\n        public void OnDisable()\n        {\n            if (m_PreviewUtility != null)\n            {\n                m_PreviewUtility.Cleanup();\n                m_PreviewUtility = null;\n            }\n        }\n\n        public float mipLevel { get { return m_MipLevel; } set { m_MipLevel = value; } }\n\n        // For mip maps we render by default with mipLevel 0 but allow for\n        public float GetMipLevelForRendering(Texture texture)\n        {\n            return Mathf.Min(m_MipLevel, TextureUtil.GetMipmapCount(texture));\n        }\n\n        public void SetIntensity(float intensity)\n        {\n            m_Intensity = intensity;\n        }\n\n        void InitPreview()\n        {\n            // Initialized?\n            if (m_PreviewUtility != null)\n                return;\n\n            m_PreviewUtility = new PreviewRenderUtility();\n            m_PreviewUtility.camera.fieldOfView = 15f;\n            m_Mesh = PreviewRenderUtility.GetPreviewSphere();\n            m_Material = EditorGUIUtility.LoadRequired(\"Previews/PreviewCubemapMaterial.mat\") as Material;\n        }\n\n        public void OnPreviewSettings(Object[] targets, int mipCount, bool alphaOnly, bool hasAlpha)\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture)\n                return;\n            GUI.enabled = true;\n            InitPreview();\n\n            bool showMode = true;\n\n            if (alphaOnly)\n            {\n                m_PreviewType = PreviewType.Alpha;\n                showMode = false;\n            }\n            else if (!hasAlpha)\n            {\n                m_PreviewType = PreviewType.RGB;\n                showMode = false;\n            }\n\n            if (showMode)\n            {\n                GUIContent[] kPreviewIcons = { Styles.RGBIcon, Styles.alphaIcon };\n                int index = (int)m_PreviewType;\n                if (GUILayout.Button(kPreviewIcons[index], Styles.preButton))\n                    m_PreviewType = (PreviewType)(++index % kPreviewIcons.Length);\n            }\n\n            GUI.enabled = (mipCount != 1);\n            GUILayout.Box(Styles.smallZoom, Styles.preLabel);\n            GUI.changed = false;\n            m_MipLevel = Mathf.Round(GUILayout.HorizontalSlider(m_MipLevel, mipCount - 1, 0, Styles.preSlider, Styles.preSliderThumb, GUILayout.MaxWidth(64)));\n            GUILayout.Box(Styles.largeZoom, Styles.preLabel);\n            GUI.enabled = true;\n        }\n\n        public void OnPreviewGUI(Texture t, Rect r, GUIStyle background, float exposure)\n        {\n            if (t == null)\n                return;\n\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture)\n            {\n                if (Event.current.type == EventType.Repaint)\n                    EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), \"Cubemap preview requires\\nrender texture support\");\n                return;\n            }\n\n            m_PreviewDir = PreviewGUI.Drag2D(m_PreviewDir, r);\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            InitPreview();\n            m_PreviewUtility.BeginPreview(r, background);\n            const float previewDistance = 6.0f;\n\n            RenderCubemap(t, m_PreviewDir, previewDistance, exposure);\n\n            Texture renderedTexture = m_PreviewUtility.EndPreview();\n            GUI.DrawTexture(r, renderedTexture, ScaleMode.StretchToFill, false);\n\n            if (mipLevel != 0)\n                EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 20), \"Mip \" + mipLevel);\n        }\n\n        public Texture2D RenderStaticPreview(Texture t, int width, int height, float exposure)\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture)\n                return null;\n\n            InitPreview();\n            m_PreviewUtility.BeginStaticPreview(new Rect(0, 0, width, height));\n            const float previewDistance = 5.3f;\n            Vector2 previewDirection = new Vector2(0, 0);\n\n            // When rendering the cubemap preview we don't need lighting so we provide a custom list with no lights.\n            // If we don't do this and we are generating the preview for a point light cookie, if a light uses this cookie it will try to bind it which result in internal assert in AssetDatabase due to using the texture while building it.\n            m_PreviewUtility.ambientColor = Color.black;\n\n            RenderCubemap(t, previewDirection, previewDistance, exposure);\n\n            return m_PreviewUtility.EndStaticPreview();\n        }\n\n        private void RenderCubemap(Texture t, Vector2 previewDir, float previewDistance, float exposure)\n        {\n            m_PreviewUtility.camera.transform.position = -Vector3.forward * previewDistance;\n            m_PreviewUtility.camera.transform.rotation = Quaternion.identity;\n            Quaternion rot = Quaternion.Euler(previewDir.y, 0, 0) * Quaternion.Euler(0, previewDir.x, 0);\n\n            m_Material.mainTexture = t;\n\n            m_Material.SetMatrix(s_ShaderCubemapRotation, Matrix4x4.TRS(Vector3.zero, rot, Vector3.one));\n\n            // -1 indicates \"use regular sampling\"; mips 0 and larger sample only that mip level for preview\n            float mipLevel = GetMipLevelForRendering(t);\n            m_Material.SetFloat(s_ShaderMip, mipLevel);\n            m_Material.SetFloat(s_ShaderAlpha, (m_PreviewType == PreviewType.Alpha) ? 1.0f : 0.0f);\n            m_Material.SetFloat(s_ShaderIntensity, m_Intensity);\n            m_Material.SetFloat(s_ShaderIsNormalMap, TextureInspector.IsNormalMap(t) ? 1.0f : 0.0f);\n            m_Material.SetFloat(s_ShaderExposure, exposure);\n            m_Material.SetInt(s_ColorspaceIsGamma, PlayerSettings.colorSpace == ColorSpace.Linear ? 0 : 1);\n\n            m_PreviewUtility.DrawMesh(m_Mesh, Vector3.zero, rot, m_Material, 0);\n            m_PreviewUtility.Render(Unsupported.useScriptableRenderPipeline);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/CurvePresetLibraryInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(CurvePresetLibrary))]\n    internal class CurvePresetLibraryEditor : Editor\n    {\n        private GenericPresetLibraryInspector<CurvePresetLibrary> m_GenericPresetLibraryInspector;\n        private CurveLibraryType m_CurveLibraryType;\n\n        public void OnEnable()\n        {\n            string filePath = AssetDatabase.GetAssetPath(target.GetInstanceID());\n            m_CurveLibraryType = GetCurveLibraryTypeFromExtension(Path.GetExtension(filePath).TrimStart('.'));\n            m_GenericPresetLibraryInspector = new GenericPresetLibraryInspector<CurvePresetLibrary>(target, GetHeader(), OnEditButtonClicked);\n            m_GenericPresetLibraryInspector.presetSize = new Vector2(72, 20);\n            m_GenericPresetLibraryInspector.lineSpacing = 5f;\n        }\n\n        public void OnDestroy()\n        {\n            if (m_GenericPresetLibraryInspector != null)\n                m_GenericPresetLibraryInspector.OnDestroy();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (m_GenericPresetLibraryInspector == null)\n                return;\n            string editorPrefPrefix = CurvePresetsContentsForPopupWindow.GetBasePrefText(m_CurveLibraryType);\n            m_GenericPresetLibraryInspector.itemViewMode = PresetLibraryEditorState.GetItemViewMode(editorPrefPrefix); // ensure in-sync\n            m_GenericPresetLibraryInspector.OnInspectorGUI();\n        }\n\n        private void OnEditButtonClicked(string libraryPath)\n        {\n            Rect ranges = GetCurveRanges();\n            CurveEditorSettings settings = new CurveEditorSettings();\n            if (ranges.width > 0 && ranges.height > 0 && ranges.width != Mathf.Infinity && ranges.height != Mathf.Infinity)\n            {\n                settings.hRangeMin = ranges.xMin;\n                settings.hRangeMax = ranges.xMax;\n                settings.vRangeMin = ranges.yMin;\n                settings.vRangeMax = ranges.yMax;\n            }\n\n            CurveEditorWindow.curve = new AnimationCurve();\n            CurveEditorWindow.color = new Color(0, 0.8f, 0f);\n            CurveEditorWindow.instance.Show(GUIView.current, settings);\n\n            CurveEditorWindow.instance.currentPresetLibrary = libraryPath;\n        }\n\n        private string GetHeader()\n        {\n            switch (m_CurveLibraryType)\n            {\n                case CurveLibraryType.NormalizedZeroToOne:\n                    return \"Curve Preset Library (Normalized 0 - 1)\";\n                case CurveLibraryType.Unbounded:\n                    return \"Curve Preset Library\";\n                default:\n                    return \"Curve Preset Library ?\";\n            }\n        }\n\n        private Rect GetCurveRanges()\n        {\n            switch (m_CurveLibraryType)\n            {\n                case CurveLibraryType.NormalizedZeroToOne:\n                    return new Rect(0, 0, 1, 1);\n                case CurveLibraryType.Unbounded:\n                    return new Rect();\n                default:\n                    return new Rect();\n            }\n        }\n\n        CurveLibraryType GetCurveLibraryTypeFromExtension(string extension)\n        {\n            string curveNormalized = PresetLibraryLocations.GetCurveLibraryExtension(true);\n            string curve = PresetLibraryLocations.GetCurveLibraryExtension(false);\n            if (extension.Equals(curveNormalized, StringComparison.OrdinalIgnoreCase))\n                return CurveLibraryType.NormalizedZeroToOne;\n\n            if (extension.Equals(curve, StringComparison.OrdinalIgnoreCase))\n                return CurveLibraryType.Unbounded;\n\n            Debug.LogError(\"Extension not recognized!\");\n            return CurveLibraryType.NormalizedZeroToOne;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Inspector/CustomPreviewAttribute.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor\n{\n    // Tells a custom [[IPreviewable]] which run-time [[Serializable]] class or [[PropertyAttribute]] it's a drawer for.\n    [System.AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]\n    public sealed class CustomPreviewAttribute : Attribute\n    {\n        internal Type m_Type;\n\n        // Tells a PropertyDrawer class which run-time class or attribute it's a drawer for.\n        public CustomPreviewAttribute(Type type)\n        {\n            m_Type = type;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/CustomRenderTextureEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditorInternal;\nusing System.Collections.Generic;\nusing System.IO;\nusing AnimatedBool = UnityEditor.AnimatedValues.AnimBool;\nusing UnityEngine.Experimental.Rendering;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(CustomRenderTexture))]\n    [CanEditMultipleObjects]\n    internal class CustomRenderTextureEditor : RenderTextureEditor\n    {\n        private class Styles\n        {\n            public readonly GUIContent  shaderPass          = EditorGUIUtility.TrTextContent(\"Shader Pass\", \"Shader Pass used to update the Custom Render Texture.\");\n            public readonly GUIContent  needSwap            = EditorGUIUtility.TrTextContent(\"Swap (Double Buffer)\", \"If ticked, and if the texture is double buffered, a request is made to swap the buffers before the next update. If this is not ticked, the buffers will not be swapped.\");\n            public readonly GUIContent  updateMode          = EditorGUIUtility.TrTextContent(\"Update Mode\", \"Specify how the texture should be updated.\");\n            public readonly GUIContent  updatePeriod        = EditorGUIUtility.TrTextContent(\"Period\", \"Period in seconds at which real-time textures are updated (0.0 will update every frame).\");\n            public readonly GUIContent  doubleBuffered      = EditorGUIUtility.TrTextContent(\"Double Buffered\", \"If ticked, the Custom Render Texture is double buffered so that you can access it during its own update. If unticked, the Custom Render Texture will be not be double buffered.\");\n            public readonly GUIContent  initializationMode  = EditorGUIUtility.TrTextContent(\"Initialization Mode\", \"Specify how the texture should be initialized.\");\n            public readonly GUIContent  initSource          = EditorGUIUtility.TrTextContent(\"Source\", \"Specify if the texture is initialized by a Material or by a Texture and a Color.\");\n            public readonly GUIContent  initColor           = EditorGUIUtility.TrTextContent(\"Color\", \"Color with which the Custom Render Texture is initialized.\");\n            public readonly GUIContent  initTexture         = EditorGUIUtility.TrTextContent(\"Texture\", \"Texture with which the Custom Render Texture is initialized (multiplied by the initialization color).\");\n            public readonly GUIContent  initMaterial        = EditorGUIUtility.TrTextContent(\"Material\", \"Material with which the Custom Render Texture is initialized.\");\n            public readonly GUIContent  updateZoneSpace     = EditorGUIUtility.TrTextContent(\"Update Zone Space\", \"Space in which the update zones are expressed (Normalized or Pixel space).\");\n            public readonly GUIContent  updateZoneList      = EditorGUIUtility.TrTextContent(\"Update Zones\", \"List of partial update zones.\");\n            public readonly GUIContent  cubemapFacesLabel   = EditorGUIUtility.TrTextContent(\"Cubemap Faces\", \"Enable or disable rendering on each face of the cubemap.\");\n            public readonly GUIContent  updateZoneCenter    = EditorGUIUtility.TrTextContent(\"Center\", \"Center of the partial update zone.\");\n            public readonly GUIContent  updateZoneSize      = EditorGUIUtility.TrTextContent(\"Size\", \"Size of the partial update zone.\");\n            public readonly GUIContent  updateZoneRotation  = EditorGUIUtility.TrTextContent(\"Rotation\", \"Rotation of the update zone.\");\n            public readonly GUIContent  wrapUpdateZones     = EditorGUIUtility.TrTextContent(\"Wrap Update Zones\", \"If ticked, Update zones will wrap around the border of the Custom Render Texture. If unticked, Update zones will be clamped at the border of the Custom Render Texture.\");\n\n            public readonly GUIContent[] updateModeStrings = { EditorGUIUtility.TextContent(\"OnLoad\"), EditorGUIUtility.TrTextContent(\"Realtime\"), EditorGUIUtility.TrTextContent(\"OnDemand\") };\n            public readonly int[] updateModeValues = { (int)CustomRenderTextureUpdateMode.OnLoad, (int)CustomRenderTextureUpdateMode.Realtime, (int)CustomRenderTextureUpdateMode.OnDemand };\n\n            public readonly GUIContent[] initSourceStrings = { EditorGUIUtility.TrTextContent(\"Texture and Color\"), EditorGUIUtility.TrTextContent(\"Material\") };\n            public readonly int[] initSourceValues = { (int)CustomRenderTextureInitializationSource.TextureAndColor, (int)CustomRenderTextureInitializationSource.Material };\n\n            public readonly GUIContent[] updateZoneSpaceStrings = { EditorGUIUtility.TrTextContent(\"Normalized\"), EditorGUIUtility.TrTextContent(\"Pixel\") };\n            public readonly int[] updateZoneSpaceValues = { (int)CustomRenderTextureUpdateZoneSpace.Normalized, (int)CustomRenderTextureUpdateZoneSpace.Pixel };\n\n            public readonly GUIContent[] cubemapFaces = { EditorGUIUtility.TextContent(\"+X\"), EditorGUIUtility.TextContent(\"-X\"), EditorGUIUtility.TextContent(\"+Y\"), EditorGUIUtility.TextContent(\"-Y\"), EditorGUIUtility.TrTextContent(\"+Z\"), EditorGUIUtility.TrTextContent(\"-Z\") };\n        }\n\n        static Styles s_Styles = null;\n        private static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } }\n\n        private SerializedProperty m_Material;\n        private SerializedProperty m_ShaderPass;\n        private SerializedProperty m_InitializationMode;\n        private SerializedProperty m_InitSource;\n        private SerializedProperty m_InitColor;\n        private SerializedProperty m_InitTexture;\n        private SerializedProperty m_InitMaterial;\n        private SerializedProperty m_UpdateMode;\n        private SerializedProperty m_UpdatePeriod;\n        private SerializedProperty m_UpdateZoneSpace;\n        private SerializedProperty m_UpdateZones;\n        private SerializedProperty m_WrapUpdateZones;\n        private SerializedProperty m_DoubleBuffered;\n        private SerializedProperty m_CubeFaceMask;\n\n        private UnityEditorInternal.ReorderableList m_RectList;\n\n        private const float kCubefaceToggleWidth = 70.0f;\n        private const float kRListAddButtonOffset = 16.0f;\n        private const float kIndentSize = 15.0f;\n        private const float kToggleWidth = 100.0f;\n\n        readonly AnimatedBool m_ShowInitSourceAsMaterial = new AnimatedBool();\n\n        private bool multipleEditing { get { return targets.Length > 1; } }\n\n        void UpdateZoneVec3PropertyField(Rect rect, SerializedProperty prop, GUIContent label, bool as2D, bool setWideMode)\n        {\n            EditorGUI.BeginProperty(rect, label, prop);\n            if (!as2D)\n            {\n                prop.vector3Value = EditorGUI.Vector3Field(rect, label, prop.vector3Value);\n            }\n            else\n            {\n                Vector2 newValue = EditorGUI.Vector2Field(rect, label, new Vector2(prop.vector3Value.x, prop.vector3Value.y), setWideMode);\n                prop.vector3Value = new Vector3(newValue.x, newValue.y, prop.vector3Value.z);\n            }\n            EditorGUI.EndProperty();\n        }\n\n        private void OnDrawElement(Rect rect, int index, bool isActive, bool isFocused)\n        {\n            CustomRenderTexture customRenderTexture = target as CustomRenderTexture;\n            bool is3DTexture = customRenderTexture.dimension == UnityEngine.Rendering.TextureDimension.Tex3D;\n            bool isDoubleBuffer = customRenderTexture.doubleBuffered;\n\n            var element = m_RectList.serializedProperty.GetArrayElementAtIndex(index);\n\n            float lineHeight = EditorGUIUtility.singleLineHeight;\n            rect.y += EditorGUIUtility.standardVerticalSpacing;\n            rect.height = lineHeight;\n            EditorGUI.LabelField(rect, string.Format(\"Update Zone {0}\", index));\n            rect.y += lineHeight;\n            SerializedProperty centerProp = element.FindPropertyRelative(\"updateZoneCenter\");\n            UpdateZoneVec3PropertyField(rect, centerProp, styles.updateZoneCenter, !is3DTexture, true);\n\n            rect.y += lineHeight + EditorGUIUtility.standardVerticalSpacing;\n            SerializedProperty sizeProp = element.FindPropertyRelative(\"updateZoneSize\");\n            UpdateZoneVec3PropertyField(rect, sizeProp, styles.updateZoneSize, !is3DTexture, true);\n\n            if (!is3DTexture)\n            {\n                rect.y += (EditorGUIUtility.standardVerticalSpacing + lineHeight);\n                EditorGUI.PropertyField(rect, element.FindPropertyRelative(\"rotation\"), styles.updateZoneRotation);\n            }\n\n            // Shader pass\n            List<GUIContent> shaderPassNames = new List<GUIContent>();\n            List<int> shaderPassValues = new List<int>();\n            Material material = m_Material.objectReferenceValue as Material;\n            if (material != null)\n            {\n                BuildShaderPassPopup(material, shaderPassNames, shaderPassValues, true);\n            }\n\n            using (new EditorGUI.DisabledScope(shaderPassNames.Count == 0))\n            {\n                SerializedProperty passIndexProperty = element.FindPropertyRelative(\"passIndex\");\n                rect.y += (EditorGUIUtility.standardVerticalSpacing + lineHeight);\n                EditorGUI.IntPopup(rect, passIndexProperty, shaderPassNames.ToArray(), shaderPassValues.ToArray(), styles.shaderPass);\n            }\n\n            if (isDoubleBuffer)\n            {\n                rect.y += (EditorGUIUtility.standardVerticalSpacing + lineHeight);\n                EditorGUI.PropertyField(rect, element.FindPropertyRelative(\"needSwap\"), styles.needSwap);\n            }\n        }\n\n        private void OnDrawHeader(Rect rect)\n        {\n            GUI.Label(rect, styles.updateZoneList);\n        }\n\n        private void OnAdd(ReorderableList l)\n        {\n            CustomRenderTexture customRenderTexture = target as CustomRenderTexture;\n            var index = l.serializedProperty.arraySize;\n            l.serializedProperty.arraySize++;\n            l.index = index;\n            var element = l.serializedProperty.GetArrayElementAtIndex(index);\n            Vector3 defaultCenter = new Vector3(0.5f, 0.5f, 0.5f);\n            Vector3 defaultSize = new Vector3(1.0f, 1.0f, 1.0f);\n            if (customRenderTexture.updateZoneSpace == CustomRenderTextureUpdateZoneSpace.Pixel)\n            {\n                Vector3 size = new Vector3((float)customRenderTexture.width, (float)customRenderTexture.height, (float)customRenderTexture.volumeDepth);\n                defaultCenter.Scale(size);\n                defaultSize.Scale(size);\n            }\n            element.FindPropertyRelative(\"updateZoneCenter\").vector3Value = defaultCenter;\n            element.FindPropertyRelative(\"updateZoneSize\").vector3Value = defaultSize;\n            element.FindPropertyRelative(\"rotation\").floatValue = 0.0f;\n            element.FindPropertyRelative(\"passIndex\").intValue = -1;\n            element.FindPropertyRelative(\"needSwap\").boolValue = false;\n        }\n\n        private void OnRemove(ReorderableList l)\n        {\n            l.serializedProperty.arraySize--;\n            if (l.index == l.serializedProperty.arraySize)\n            {\n                l.index--;\n            }\n        }\n\n        private float OnElementHeight(int index)\n        {\n            CustomRenderTexture customRenderTexture = target as CustomRenderTexture;\n            bool is3DTexture = customRenderTexture.dimension == UnityEngine.Rendering.TextureDimension.Tex3D;\n            bool isDoubleBuffer = customRenderTexture.doubleBuffered;\n            int lineCount = 4;  // 4 lines : Index, Zone Origin, Zone Size, Shader Pass\n            if (!is3DTexture) // We don't support rotation for 3D textures so we don't show it.\n                lineCount++;\n            if (isDoubleBuffer) // \"Swap\" only shown for double buffered custom textures\n                lineCount++;\n\n            return (EditorGUIUtility.singleLineHeight + 2.0f) * lineCount;\n        }\n\n        protected override void OnEnable()\n        {\n            base.OnEnable();\n            m_Material = serializedObject.FindProperty(\"m_Material\");\n            m_ShaderPass = serializedObject.FindProperty(\"m_ShaderPass\");\n            m_InitializationMode = serializedObject.FindProperty(\"m_InitializationMode\");\n            m_InitSource = serializedObject.FindProperty(\"m_InitSource\");\n            m_InitColor = serializedObject.FindProperty(\"m_InitColor\");\n            m_InitTexture = serializedObject.FindProperty(\"m_InitTexture\");\n            m_InitMaterial = serializedObject.FindProperty(\"m_InitMaterial\");\n            m_UpdateMode = serializedObject.FindProperty(\"m_UpdateMode\");\n            m_UpdatePeriod = serializedObject.FindProperty(\"m_UpdatePeriod\");\n            m_UpdateZoneSpace = serializedObject.FindProperty(\"m_UpdateZoneSpace\");\n            m_UpdateZones = serializedObject.FindProperty(\"m_UpdateZones\");\n            m_WrapUpdateZones = serializedObject.FindProperty(\"m_WrapUpdateZones\");\n            m_DoubleBuffered = serializedObject.FindProperty(\"m_DoubleBuffered\");\n            m_CubeFaceMask = serializedObject.FindProperty(\"m_CubemapFaceMask\");\n\n            m_RectList = new UnityEditorInternal.ReorderableList(serializedObject, m_UpdateZones);\n            m_RectList.drawElementCallback = OnDrawElement;\n            m_RectList.drawHeaderCallback = OnDrawHeader;\n            m_RectList.onAddCallback = OnAdd;\n            m_RectList.onRemoveCallback = OnRemove;\n            m_RectList.elementHeightCallback = OnElementHeight;\n            m_RectList.footerHeight = 0;\n\n            m_ShowInitSourceAsMaterial.value = !m_InitSource.hasMultipleDifferentValues && (m_InitSource.intValue == (int)CustomRenderTextureInitializationSource.Material);\n            m_ShowInitSourceAsMaterial.valueChanged.AddListener(Repaint);\n        }\n\n        protected override void OnDisable()\n        {\n            base.OnDisable();\n\n            m_ShowInitSourceAsMaterial.valueChanged.RemoveListener(Repaint);\n        }\n\n        void DisplayRenderTextureGUI()\n        {\n            OnRenderTextureGUI(GUIElements.RenderTargetDepthGUI | GUIElements.RenderTargetAAGUI);\n            GUILayout.Space(10.0f);\n        }\n\n        void BuildShaderPassPopup(Material material, List<GUIContent> names, List<int> values, bool addDefaultPass)\n        {\n            names.Clear();\n            values.Clear();\n\n            int shaderPassCount = material.passCount;\n            for (int i = 0; i < shaderPassCount; ++i)\n            {\n                string name = material.GetPassName(i);\n                if (name.Length == 0)\n                {\n                    name = string.Format(\"Unnamed Pass {0}\", i);\n                }\n                names.Add(EditorGUIUtility.TextContent(name));\n                values.Add(i);\n            }\n\n            if (addDefaultPass)\n            {\n                CustomRenderTexture customRenderTexture = target as CustomRenderTexture;\n\n                GUIContent defaultName = EditorGUIUtility.TextContent(string.Format(\"Default ({0})\", names[customRenderTexture.shaderPass].text));\n                names.Insert(0, defaultName);\n                values.Insert(0, -1);\n            }\n        }\n\n        void DisplayMaterialGUI()\n        {\n            EditorGUILayout.PropertyField(m_Material, true);\n            EditorGUI.indentLevel++;\n\n            List<GUIContent> shaderPassNames = new List<GUIContent>();\n            List<int> shaderPassValues = new List<int>();\n            Material material = m_Material.objectReferenceValue as Material;\n            if (material != null)\n            {\n                BuildShaderPassPopup(material, shaderPassNames, shaderPassValues, false);\n            }\n\n            using (new EditorGUI.DisabledScope(shaderPassNames.Count == 0 || m_Material.hasMultipleDifferentValues)) // Different materials can have widely different passes, so there's no point trying to edit that when multiple editing.\n            {\n                if (material != null)\n                    EditorGUILayout.IntPopup(m_ShaderPass, shaderPassNames.ToArray(), shaderPassValues.ToArray(), styles.shaderPass);\n            }\n\n            EditorGUI.indentLevel--;\n        }\n\n        void DisplayInitializationGUI()\n        {\n            m_ShowInitSourceAsMaterial.target = !m_InitSource.hasMultipleDifferentValues && (m_InitSource.intValue == (int)CustomRenderTextureInitializationSource.Material);\n\n            EditorGUILayout.IntPopup(m_InitializationMode, styles.updateModeStrings, styles.updateModeValues, styles.initializationMode);\n            EditorGUI.indentLevel++;\n\n            EditorGUILayout.IntPopup(m_InitSource, styles.initSourceStrings, styles.initSourceValues, styles.initSource);\n            if (!m_InitSource.hasMultipleDifferentValues)\n            {\n                EditorGUI.indentLevel++;\n                if (EditorGUILayout.BeginFadeGroup(m_ShowInitSourceAsMaterial.faded))\n                {\n                    EditorGUILayout.PropertyField(m_InitMaterial, styles.initMaterial);\n                }\n                EditorGUILayout.EndFadeGroup();\n\n                if (EditorGUILayout.BeginFadeGroup(1 - m_ShowInitSourceAsMaterial.faded))\n                {\n                    EditorGUILayout.PropertyField(m_InitColor, styles.initColor);\n                    EditorGUILayout.PropertyField(m_InitTexture, styles.initTexture);\n                }\n                EditorGUILayout.EndFadeGroup();\n                EditorGUI.indentLevel--;\n            }\n            EditorGUI.indentLevel--;\n        }\n\n        void DisplayUpdateGUI()\n        {\n            EditorGUILayout.IntPopup(m_UpdateMode, styles.updateModeStrings, styles.updateModeValues, styles.updateMode);\n\n            EditorGUI.indentLevel++;\n\n            if (m_UpdateMode.intValue == (int)CustomRenderTextureUpdateMode.Realtime)\n            {\n                EditorGUILayout.PropertyField(m_UpdatePeriod, styles.updatePeriod);\n            }\n\n            EditorGUILayout.PropertyField(m_DoubleBuffered, styles.doubleBuffered);\n            EditorGUILayout.PropertyField(m_WrapUpdateZones, styles.wrapUpdateZones);\n\n            bool isCubemap = true;\n            foreach (Object o in targets)\n            {\n                CustomRenderTexture customRenderTexture = o as CustomRenderTexture;\n                if (customRenderTexture != null && customRenderTexture.dimension != UnityEngine.Rendering.TextureDimension.Cube)\n                    isCubemap = false;\n            }\n\n            if (isCubemap)\n            {\n                int newFaceMask = 0;\n                int currentFaceMask = m_CubeFaceMask.intValue;\n\n                var AllRects = GUILayoutUtility.GetRect(0, EditorGUIUtility.singleLineHeight * 3 + EditorGUIUtility.standardVerticalSpacing * 2);\n                EditorGUI.BeginProperty(AllRects, GUIContent.none, m_CubeFaceMask);\n\n                Rect toggleRect = AllRects;\n                toggleRect.width = kToggleWidth;\n                toggleRect.height = EditorGUIUtility.singleLineHeight;\n                int faceIndex = 0;\n                {\n                    Rect labelRect = AllRects;\n                    EditorGUI.LabelField(labelRect, styles.cubemapFacesLabel);\n\n                    EditorGUI.BeginChangeCheck();\n                    for (int i = 0; i < 3; ++i)\n                    {\n                        toggleRect.x = AllRects.x + EditorGUIUtility.labelWidth - kIndentSize;\n\n                        {\n                            for (int j = 0; j < 2; ++j)\n                            {\n                                bool value = EditorGUI.ToggleLeft(toggleRect, styles.cubemapFaces[faceIndex], (currentFaceMask & (1 << faceIndex)) != 0);\n                                if (value)\n                                    newFaceMask |= (int)(1 << faceIndex);\n                                faceIndex++;\n\n                                toggleRect.x += kToggleWidth;\n                            }\n                        }\n\n                        toggleRect.y += EditorGUIUtility.singleLineHeight;\n                    }\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        m_CubeFaceMask.intValue = newFaceMask;\n                    }\n                }\n                EditorGUI.EndProperty();\n            }\n\n\n            EditorGUILayout.IntPopup(m_UpdateZoneSpace, styles.updateZoneSpaceStrings, styles.updateZoneSpaceValues, styles.updateZoneSpace);\n\n            if (!multipleEditing)\n            {\n                Rect listRect = GUILayoutUtility.GetRect(0.0f, m_RectList.GetHeight() + kRListAddButtonOffset, GUILayout.ExpandWidth(true)); // kRListAddButtonOffset because reorderable list does not take the  +/- button at the bottom when computing its Rects making it half occulted by other GUI elements.\n                // Reorderable list seems to not take indentLevel into account properly.\n                float indentSize = kIndentSize;\n                listRect.x += indentSize;\n                listRect.width -= indentSize;\n                m_RectList.DoList(listRect);\n            }\n            else\n            {\n                EditorGUILayout.HelpBox(\"Update Zones cannot be changed while editing multiple Custom Textures.\", MessageType.Info);\n            }\n\n            EditorGUI.indentLevel--;\n        }\n\n        void DisplayCustomRenderTextureGUI()\n        {\n            CustomRenderTexture customRenderTexture = target as CustomRenderTexture;\n\n            DisplayMaterialGUI();\n            EditorGUILayout.Space();\n            DisplayInitializationGUI();\n            EditorGUILayout.Space();\n            DisplayUpdateGUI();\n\n            EditorGUILayout.Space();\n\n            if (customRenderTexture.updateMode != CustomRenderTextureUpdateMode.Realtime && customRenderTexture.initializationMode == CustomRenderTextureUpdateMode.Realtime)\n                EditorGUILayout.HelpBox(\"Initialization Mode is set to Realtime but Update Mode is not. This will result in update never being visible.\", MessageType.Warning);\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            DisplayRenderTextureGUI();\n            DisplayCustomRenderTextureGUI();\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        [MenuItem(\"CONTEXT/CustomRenderTexture/Export\", secondaryPriority = 12)]\n        static void SaveToDisk(MenuCommand command)\n        {\n            CustomRenderTexture texture = command.context as CustomRenderTexture;\n            int width = texture.width;\n            int height = texture.height;\n            int depth = texture.volumeDepth;\n\n            // This has its TextureFormat helper equivalent in C++ but since we are going to try to refactor TextureFormat/RenderTextureFormat into a single type so let's not bloat Scripting APIs with stuff that will get useless soon(tm).\n            bool isFormatHDR = GraphicsFormatUtility.IsIEEE754Format(texture.graphicsFormat);\n            bool isFloatFormat = GraphicsFormatUtility.IsFloatFormat(texture.graphicsFormat);\n\n            TextureFormat format = isFormatHDR ? TextureFormat.RGBAFloat : TextureFormat.RGBA32;\n            int finalWidth = width;\n            if (texture.dimension == UnityEngine.Rendering.TextureDimension.Tex3D)\n                finalWidth = width * depth;\n            else if (texture.dimension == UnityEngine.Rendering.TextureDimension.Cube)\n                finalWidth = width * 6;\n\n            Texture2D tex = new Texture2D(finalWidth, height, format, false);\n\n            // Read screen contents into the texture\n            if (texture.dimension == UnityEngine.Rendering.TextureDimension.Tex2D)\n            {\n                Graphics.SetRenderTarget(texture);\n                tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);\n                tex.Apply();\n            }\n            else if (texture.dimension == UnityEngine.Rendering.TextureDimension.Tex3D)\n            {\n                int offset = 0;\n                for (int i = 0; i < depth; ++i)\n                {\n                    Graphics.SetRenderTarget(texture, 0, CubemapFace.Unknown, i);\n                    tex.ReadPixels(new Rect(0, 0, width, height), offset, 0);\n                    tex.Apply();\n                    offset += width;\n                }\n            }\n            else\n            {\n                int offset = 0;\n                for (int i = 0; i < 6; ++i)\n                {\n                    Graphics.SetRenderTarget(texture, 0, (CubemapFace)i);\n                    tex.ReadPixels(new Rect(0, 0, width, height), offset, 0);\n                    tex.Apply();\n                    offset += width;\n                }\n            }\n\n            // Encode texture into PNG\n            byte[] bytes = null;\n            if (isFormatHDR)\n                bytes = tex.EncodeToEXR(Texture2D.EXRFlags.CompressZIP | (isFloatFormat ? Texture2D.EXRFlags.OutputAsFloat : 0));\n            else\n                bytes = tex.EncodeToPNG();\n\n            Object.DestroyImmediate(tex);\n\n            var extension = isFormatHDR ? \"exr\" : \"png\";\n\n            string directory;\n            if (!IsPersistent(texture))\n            {\n                directory = Application.dataPath;\n            }\n            else\n            {\n                directory = Path.GetDirectoryName(AssetDatabase.GetAssetPath(texture.GetInstanceID()));\n            }\n\n            string assetPath = EditorUtility.SaveFilePanel(\"Save Custom Render Texture\", directory, texture.name, extension);\n            if (!string.IsNullOrEmpty(assetPath))\n            {\n                File.WriteAllBytes(assetPath, bytes);\n                AssetDatabase.Refresh();\n            }\n        }\n\n        override public string GetInfoString()\n        {\n            return base.GetInfoString();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/DirectorEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing UnityEngine.Playables;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(PlayableDirector))]\n    [CanEditMultipleObjects]\n    internal class DirectorEditor : Editor\n    {\n        private static class Styles\n        {\n            public static readonly GUIContent PlayableText = EditorGUIUtility.TrTextContent(\"Playable\");\n            public static readonly GUIContent InitialTimeContent = EditorGUIUtility.TrTextContent(\"Initial Time\", \"The time at which the Playable will begin playing\");\n            public static readonly GUIContent TimeContent = EditorGUIUtility.TrTextContent(\"Current Time\", \"The current Playable time\");\n            public static readonly GUIContent InitialStateContent = EditorGUIUtility.TrTextContent(\"Play On Awake\", \"Whether the Playable should be playing after it loads\");\n            public static readonly GUIContent UpdateMethod = EditorGUIUtility.TrTextContent(\"Update Method\", \"Controls how the Playable updates every frame\");\n            public static readonly GUIContent WrapModeContent = EditorGUIUtility.TrTextContent(\"Wrap Mode\", \"Controls the behaviour of evaluating the Playable outside its duration\");\n            public static readonly GUIContent NoBindingsContent = EditorGUIUtility.TrTextContent(\"This channel will not playback because it is not currently assigned\");\n            public static readonly GUIContent BindingsTitleContent = EditorGUIUtility.TrTextContent(\"Bindings\");\n            public static readonly GUIContent ClearUnused = EditorGUIUtility.TrTextContent(\"Show Unused\", \"A PlayableDirector may contain bindings to objects not referenced by the assigned Playable file.\\nToggle this field to show them.\\n It is recommended to remove unused bound objects if their Playable will be no longer used by this PlayableDirector.\");\n        }\n\n        private static readonly int ObjectFieldControlID = \"s_ObjectFieldHash\".GetHashCode();\n        private const int BindingHeaderPadding = 4;\n        private const float UnusedItemBackGroundScale = 0.92f;\n        private const float UnusedItemColorScale = 0.70f;\n\n\n        private SerializedProperty m_PlayableAsset;\n        private SerializedProperty m_InitialState;\n        private SerializedProperty m_WrapMode;\n        private SerializedProperty m_InitialTime;\n        private SerializedProperty m_UpdateMethod;\n        private SerializedProperty m_SceneBindings;\n\n        private bool m_DirtySceneBindings;\n\n        private Texture    m_DefaultScriptContentTexture;\n\n        private GUIContent m_BindingContent = new GUIContent();\n\n        private struct BindingItem\n        {\n            public PlayableBinding binding;\n            public SerializedProperty property;\n            public string AssetPath;\n            public bool IsMainAsset;\n            public PlayableAsset masterAsset;\n            public int propertyIndex;\n        }\n\n        private List<BindingItem> m_BindingItems = new List<BindingItem>();\n        private PlayableBinding[] m_SynchedPlayableBindings = null;\n\n        private ReorderableList m_BindingList;\n\n\n        bool showUnused\n        {\n            get { return EditorPrefs.GetBool(\"PlayableDirector.ShowUnused\", true); }\n            set { EditorPrefs.SetBool(\"PlayableDirector.ShowUnused\", value); }\n        }\n\n        bool hasUnused { get; set; }\n\n\n        public void OnEnable()\n        {\n            m_PlayableAsset = serializedObject.FindProperty(\"m_PlayableAsset\");\n            m_InitialState = serializedObject.FindProperty(\"m_InitialState\");\n            m_WrapMode = serializedObject.FindProperty(\"m_WrapMode\");\n            m_UpdateMethod = serializedObject.FindProperty(\"m_DirectorUpdateMode\");\n            m_InitialTime = serializedObject.FindProperty(\"m_InitialTime\");\n            m_SceneBindings = serializedObject.FindProperty(\"m_SceneBindings\");\n\n            m_DefaultScriptContentTexture = EditorGUIUtility.FindTexture(typeof(ScriptableObject));\n\n            m_BindingList = new ReorderableList(m_BindingItems, typeof(BindingItem), false, false, false, true);\n            m_BindingList.drawElementCallback = BindingDrawCallback;\n            m_BindingList.onCanRemoveCallback = BindingCanRemoveCallback;\n            m_BindingList.onRemoveCallback = BindingOnRemove;\n            m_BindingList.onSelectCallback = BindingOnSelect;\n            m_BindingList.elementHeightCallback = BindingElementHeight;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (PlayableAssetOutputsChanged() || m_BindingItems.Count != m_SceneBindings.arraySize)\n            {\n                m_DirtySceneBindings = true;\n            }\n\n            serializedObject.Update();\n\n            if (PropertyFieldAsObject(m_PlayableAsset, Styles.PlayableText, typeof(PlayableAsset)))\n            {\n                serializedObject.ApplyModifiedProperties();\n                m_DirtySceneBindings = true;\n\n                // some editors (like Timeline) needs to repaint when the playable asset changes\n                InternalEditorUtility.RepaintAllViews();\n            }\n\n            EditorGUILayout.PropertyField(m_UpdateMethod, Styles.UpdateMethod);\n\n            var rect = EditorGUILayout.GetControlRect(true);\n            var label = EditorGUI.BeginProperty(rect, Styles.InitialStateContent, m_InitialState);\n            bool playOnAwake = m_InitialState.enumValueIndex != (int)PlayState.Paused;\n            EditorGUI.BeginChangeCheck();\n            playOnAwake = EditorGUI.Toggle(rect, label, playOnAwake);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_InitialState.enumValueIndex = (int)(playOnAwake ? PlayState.Playing : PlayState.Paused);\n            }\n            EditorGUI.EndProperty();\n\n            EditorGUILayout.PropertyField(m_WrapMode, Styles.WrapModeContent);\n\n            PropertyFieldAsFloat(m_InitialTime, Styles.InitialTimeContent);\n\n            if (Application.isPlaying)\n            {\n                // time field isn't functional in Editor, unless the sequencer window is open,\n                // at which point it isn't required. In playmode it can provide valuable feedback,\n                // and allow the user to scrub and debug without the sequencer window\n                CurrentTimeField();\n            }\n\n            if (serializedObject.ApplyModifiedProperties())\n            {\n                m_DirtySceneBindings = true;\n            }\n\n            if (targets.Length == 1)\n                DoDirectorBindingInspector();\n        }\n\n        private bool PlayableAssetOutputsChanged()\n        {\n            var playableAsset = m_PlayableAsset.objectReferenceValue as PlayableAsset;\n\n            if (m_SynchedPlayableBindings == null)\n                return playableAsset != null;\n\n            if (playableAsset == null)\n                return true;\n\n            if (playableAsset.outputs.Count() != m_SynchedPlayableBindings.Length)\n                return true;\n\n            return playableAsset.outputs.Where((t, i) => t.sourceObject != m_SynchedPlayableBindings[i].sourceObject).Any();\n        }\n\n        GUIContent GetContentForOutput(PlayableBinding binding, UnityEngine.Object source)\n        {\n            m_BindingContent.text = binding.streamName;\n            m_BindingContent.tooltip = (source == null) ? Styles.NoBindingsContent.text : string.Empty;\n            m_BindingContent.image = AssetPreview.GetMiniTypeThumbnail(binding.outputTargetType) ?? m_DefaultScriptContentTexture;\n            return m_BindingContent;\n        }\n\n        private void DoDirectorBindingInspector()\n        {\n            if (m_SceneBindings.isExpanded)\n            {\n                SynchronizeSceneBindings();\n            }\n\n            serializedObject.Update();\n\n            EditorGUILayout.BeginHorizontal();\n\n            var rect = GUILayoutUtility.GetRect(EditorGUIUtility.fieldWidth, EditorGUIUtility.fieldWidth, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight,  EditorStyles.foldout);\n            EditorGUI.BeginProperty(rect, GUIContent.none, m_SceneBindings);\n            m_SceneBindings.isExpanded = EditorGUI.Foldout(rect, m_SceneBindings.isExpanded, Styles.BindingsTitleContent, true);\n            EditorGUI.EndProperty();\n\n            if (hasUnused)\n            {\n                const int rightEdgePad = 2;\n                GUILayout.FlexibleSpace();\n                EditorGUI.BeginChangeCheck();\n                var size = EditorStyles.toggle.CalcSize(Styles.ClearUnused).x + rightEdgePad;\n                showUnused = EditorGUILayout.ToggleLeft(Styles.ClearUnused, showUnused, GUILayout.Width(size));\n                if (EditorGUI.EndChangeCheck())\n                    SynchronizeSceneBindings();\n            }\n            EditorGUILayout.EndHorizontal();\n\n            if (m_SceneBindings.isExpanded)\n            {\n                EditorGUI.indentLevel++;\n                m_BindingList.displayRemove = showUnused;\n                m_BindingList.DoLayoutList();\n                EditorGUI.indentLevel--;\n            }\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        PlayableBinding FindBinding(PlayableAsset source, UnityEngine.Object key)\n        {\n            if (source == null || key == null)\n                return default(PlayableBinding);\n\n            return source.outputs.FirstOrDefault(a => a.sourceObject == key);\n        }\n\n        void SynchronizeSceneBindings()\n        {\n            if (targets.Length > 1 || !m_DirtySceneBindings)\n                return;\n\n            m_DirtySceneBindings = false;\n\n            var director = (PlayableDirector)target;\n            var playableAsset = m_PlayableAsset.objectReferenceValue as PlayableAsset;\n\n            hasUnused = false;\n            m_BindingItems.Clear();\n            UpdatePlayableBindingsIfRequired(playableAsset, director);\n\n            var mainAssetPath = AssetDatabase.GetAssetPath(director.playableAsset);\n            for (int i = 0; i < m_SceneBindings.arraySize; ++i)\n            {\n                var property = m_SceneBindings.GetArrayElementAtIndex(i);\n                var keyObject = property.FindPropertyRelative(\"key\").objectReferenceValue;\n\n                // Don't show completely null keys.\n                if (((object)keyObject) == null)\n                    continue;\n\n                var assetPath = AssetDatabase.GetAssetPath(keyObject);\n                var cacheValue = new BindingItem()\n                {\n                    property = property,\n                    AssetPath = assetPath,\n                    IsMainAsset = !string.IsNullOrEmpty(assetPath) && mainAssetPath == assetPath,\n                    masterAsset = !string.IsNullOrEmpty(assetPath) ? AssetDatabase.LoadMainAssetAtPath(assetPath) as PlayableAsset : null,\n                    propertyIndex = i,\n                };\n                cacheValue.binding = FindBinding(cacheValue.masterAsset, keyObject);\n\n                hasUnused |= !cacheValue.IsMainAsset;\n\n                if (showUnused || cacheValue.IsMainAsset)\n                    m_BindingItems.Add(cacheValue);\n            }\n\n            m_BindingItems.Sort((a, b) =>\n            {\n                if (a.IsMainAsset == b.IsMainAsset)\n                    return -string.CompareOrdinal(a.AssetPath, b.AssetPath);\n                if (a.IsMainAsset)\n                    return -1;\n                return 1;\n            }\n            );\n\n            if (showUnused)\n            {\n                bool addHeader = false;\n                for (int i = 0; i < m_BindingItems.Count - 1; i++)\n                {\n                    if (m_BindingItems[i].masterAsset != m_BindingItems[i + 1].masterAsset)\n                    {\n                        m_BindingItems.Insert(i + 1, new BindingItem()\n                            { masterAsset = m_BindingItems[i + 1].masterAsset, propertyIndex = -1}\n                        );\n                        addHeader = true;\n                    }\n                }\n\n                if (addHeader && m_BindingItems.Count > 0)\n                {\n                    m_BindingItems.Insert(0, new BindingItem()\n                    {\n                        masterAsset = m_BindingItems[0].masterAsset,\n                        propertyIndex = -1,\n                        IsMainAsset = m_BindingItems[0].masterAsset == director.playableAsset,\n                    }\n                    );\n                }\n            }\n        }\n\n        private void UpdatePlayableBindingsIfRequired(PlayableAsset playableAsset, PlayableDirector director)\n        {\n            m_SynchedPlayableBindings = new PlayableBinding[0];\n\n            if (playableAsset != null)\n            {\n                var bindings = playableAsset.outputs;\n                m_SynchedPlayableBindings = bindings.ToArray();\n            }\n\n            foreach (var binding in m_SynchedPlayableBindings)\n            {\n                // don't add bindings without a specific target type, clear previously bound objects\n                // This can happen with timeline tracks that do not have a specific binding.\n                if (binding.outputTargetType == null)\n                    director.ClearGenericBinding(binding.sourceObject);\n                else if (!director.HasGenericBinding(binding.sourceObject))\n                    director.SetGenericBinding(binding.sourceObject, null);\n            }\n        }\n\n        // To show the current time field in play mode\n        public override bool RequiresConstantRepaint()\n        {\n            return Application.isPlaying;\n        }\n\n        private static void PropertyFieldAsFloat(SerializedProperty property, GUIContent title)\n        {\n            Rect rect = EditorGUILayout.GetControlRect();\n            title = EditorGUI.BeginProperty(rect, title, property);\n            EditorGUI.BeginChangeCheck();\n            float newValue = EditorGUI.FloatField(rect, title, (float)property.doubleValue);\n            if (EditorGUI.EndChangeCheck())\n            {\n                property.doubleValue = newValue;\n            }\n            EditorGUI.EndProperty();\n        }\n\n        private static bool PropertyFieldAsObject(SerializedProperty property, GUIContent title, Type objType)\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.ObjectField(property, objType, title);\n            return EditorGUI.EndChangeCheck();\n        }\n\n        private static bool PropertyFieldAsObject(Rect rect, SerializedProperty property, GUIContent title, Type objType)\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.ObjectField(rect, property, objType, title);\n            return EditorGUI.EndChangeCheck();\n        }\n\n        // Does not use Properties because time is not a serialized property\n        private void CurrentTimeField()\n        {\n            if (targets.Length == 1)\n            {\n                var director = (PlayableDirector)target;\n                EditorGUI.BeginChangeCheck();\n                float t = EditorGUILayout.FloatField(Styles.TimeContent, (float)director.time);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    director.time = t;\n                }\n            }\n            else\n            {\n                EditorGUILayout.TextField(Styles.TimeContent, EditorGUI.mixedValueContent.text);\n            }\n        }\n\n        private void BindingDrawCallback(Rect rect, int index, bool isActive, bool isFocused)\n        {\n            // apply a subtle darkening to unused items\n            var guiColor = GUI.color;\n            var backGroundColor = GUI.backgroundColor;\n\n            if (!m_BindingItems[index].IsMainAsset)\n            {\n                if (EditorGUIUtility.isProSkin)\n                    GUI.color = GUI.color.RGBMultiplied(UnusedItemColorScale);\n                else\n                    GUI.backgroundColor = GUI.backgroundColor.RGBMultiplied(UnusedItemBackGroundScale);\n            }\n\n            // header item\n            if (m_BindingItems[index].property == null)\n            {\n                if (Event.current.type == EventType.Repaint)\n                {\n                    rect.yMin += BindingHeaderPadding * 0.5f;\n                    rect.height -= BindingHeaderPadding * 0.5f;\n\n                    var content = EditorGUIUtility.ObjectContent(m_BindingItems[index].masterAsset, typeof(PlayableAsset));\n                    EditorStyles.objectField.Draw(rect,\n                        content,\n                        ObjectFieldControlID,\n                        false,\n                        rect.Contains(Event.current.mousePosition)\n                    );\n                }\n            }\n            else\n            {\n                var binding = m_BindingItems[index].binding;\n                var key = m_BindingItems[index].property.FindPropertyRelative(\"key\");\n                var value = m_BindingItems[index].property.FindPropertyRelative(\"value\");\n                var type = m_BindingItems[index].binding.outputTargetType;\n\n                // don't permit assignment if we don't how to assign it\n                using (new EditorGUI.DisabledScope(type == null))\n                    PropertyFieldAsObject(ItemRect(rect), value, GetContentForOutput(binding, key.objectReferenceValue), type ?? typeof(Object));\n            }\n\n            GUI.backgroundColor = backGroundColor;\n            GUI.color = guiColor;\n        }\n\n        private Rect ItemRect(Rect rect)\n        {\n            if (hasUnused && showUnused)\n            {\n                EditorGUI.indentLevel++;\n                rect = EditorGUI.IndentedRect(rect);\n                EditorGUI.indentLevel--;\n            }\n\n            return rect;\n        }\n\n        private bool BindingCanRemoveCallback(ReorderableList list)\n        {\n            if (!showUnused)\n                return false;\n\n            if (list.index < 0 || list.index >= m_BindingItems.Count)\n                return false;\n\n            return !m_BindingItems[list.index].IsMainAsset;\n        }\n\n        private void BindingOnRemove(ReorderableList list)\n        {\n            if (list.index >= 0 && list.index < m_BindingItems.Count)\n            {\n                var bindingProperty = m_BindingItems[list.index].property;\n                // group header, remove all from this timeline\n                if (bindingProperty == null)\n                {\n                    var path = AssetDatabase.GetAssetPath(m_BindingItems[list.index].masterAsset);\n                    int size = m_SceneBindings.arraySize - 1;\n                    for (int i = size; i >= 0; i--)\n                    {\n                        var prop = m_SceneBindings.GetArrayElementAtIndex(i).FindPropertyRelative(\"key\").objectReferenceValue;\n                        if (AssetDatabase.GetAssetPath(prop) == path)\n                            m_SceneBindings.DeleteArrayElementAtIndex(i);\n                    }\n                }\n                else\n                {\n                    m_SceneBindings.DeleteArrayElementAtIndex(m_BindingItems[list.index].propertyIndex);\n                }\n            }\n        }\n\n        private void BindingOnSelect(ReorderableList list)\n        {\n            if (list.index < 0 || list.index >= m_BindingItems.Count)\n                return;\n\n            if (m_BindingItems[list.index].masterAsset)\n                EditorGUIUtility.PingObject(m_BindingItems[list.index].masterAsset);\n            else\n                EditorGUIUtility.PingObject(m_BindingItems[list.index].property.FindPropertyRelative(\"key\").objectReferenceValue);\n        }\n\n        private float BindingElementHeight(int index)\n        {\n            if (m_BindingItems[index].property == null)\n                return m_BindingList.elementHeight + DirectorEditor.BindingHeaderPadding;\n            return m_BindingList.elementHeight;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/DoubleCurvePresetLibraryInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(DoubleCurvePresetLibrary))]\n    internal class DoubleCurvePresetLibraryEditor : Editor\n    {\n        private GenericPresetLibraryInspector<DoubleCurvePresetLibrary> m_GenericPresetLibraryInspector;\n\n        public void OnEnable()\n        {\n            m_GenericPresetLibraryInspector = new GenericPresetLibraryInspector<DoubleCurvePresetLibrary>(target, GetHeader(),  null);\n            m_GenericPresetLibraryInspector.presetSize = new Vector2(72, 20);\n            m_GenericPresetLibraryInspector.lineSpacing = 5f;\n        }\n\n        private string GetHeader()\n        {\n            return \"Particle Curve Preset Library\";\n        }\n\n        public void OnDestroy()\n        {\n            if (m_GenericPresetLibraryInspector != null)\n                m_GenericPresetLibraryInspector.OnDestroy();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (m_GenericPresetLibraryInspector != null)\n                m_GenericPresetLibraryInspector.OnInspectorGUI();\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Inspector/EditMode.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.ComponentModel;\nusing UnityEditor;\nusing UnityEditor.EditorTools;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    // TODO: We need to make the editMode state e.g a string so users are able to extend with new edit mode states\n    // and so we still can serialize it (to survive assembly reloads)\n\n    [InitializeOnLoad]\n    public class EditMode\n    {\n        internal const int k_OwnerIdNone = 0;\n\n        private static class Styles\n        {\n            public static readonly GUIStyle multiButtonStyle = \"Button\";\n            public static readonly GUIStyle singleButtonStyle = \"EditModeSingleButton\";\n        }\n\n        const string kOwnerStringKey = \"EditModeOwner\";\n        const string kEditModeStringKey = \"EditModeState\";\n\n        static EditMode()\n        {\n            ownerID = SessionState.GetInt(kOwnerStringKey, ownerID);\n            s_EditMode = (SceneViewEditMode)SessionState.GetInt(kEditModeStringKey, (int)s_EditMode);\n            Selection.selectionChanged += OnSelectionChange;\n            ToolManager.activeToolChanging += OnActiveToolWillChange;\n        }\n\n        private const float k_EditColliderbuttonWidth = 33;\n        private const float k_EditColliderbuttonHeight = 23;\n        private const float k_SpaceBetweenLabelAndButton = 5;\n\n        // todo Obsolete, use editModeEnded\n        public static OnEditModeStopFunc onEditModeEndDelegate;\n        public delegate void OnEditModeStopFunc(Editor editor);\n\n        // todo Obsolete, use editModeStarted\n        public static OnEditModeStartFunc onEditModeStartDelegate;\n        public delegate void OnEditModeStartFunc(Editor editor, SceneViewEditMode mode);\n\n        internal static event Action<IToolModeOwner> editModeEnded;\n        internal static event Action<IToolModeOwner, SceneViewEditMode> editModeStarted;\n\n        private static int s_OwnerID;\n        private static SceneViewEditMode s_EditMode;\n\n        public enum SceneViewEditMode\n        {\n            None = 0,\n            Collider,\n            ClothConstraints,\n            ClothSelfAndInterCollisionParticles,\n            ReflectionProbeBox,\n            ReflectionProbeOrigin,\n            LightProbeProxyVolumeBox,\n            LightProbeProxyVolumeOrigin,\n            LightProbeGroup,\n            JointAngularLimits,\n            GridPainting,\n            GridPicking,\n            GridEraser,\n            GridFloodFill,\n            GridBox,\n            GridSelect,\n            GridMove,\n            LineRendererEdit,\n            LineRendererCreate,\n        }\n\n        public static bool IsOwner(Editor editor)\n        {\n            return IsOwner((IToolModeOwner)editor);\n        }\n\n        internal static bool IsOwner(IToolModeOwner owner)\n        {\n            return owner.GetInstanceID() == s_OwnerID;\n        }\n\n        internal static int ownerID\n        {\n            get { return s_OwnerID; }\n            set\n            {\n                s_OwnerID = value;\n                SessionState.SetInt(kOwnerStringKey, s_OwnerID);\n            }\n        }\n\n        public static SceneViewEditMode editMode\n        {\n            get { return s_EditMode; }\n            private set\n            {\n                s_EditMode = value;\n                SessionState.SetInt(kEditModeStringKey, (int)s_EditMode);\n            }\n        }\n\n        static void OnActiveToolWillChange()\n        {\n            if (ownerID != k_OwnerIdNone)\n                EditModeToolStateChanged(null, SceneViewEditMode.None);\n        }\n\n        public static void OnSelectionChange()\n        {\n            IToolModeOwner owner = InternalEditorUtility.GetObjectFromInstanceID(ownerID) as IToolModeOwner;\n            if (owner != null && owner.ModeSurvivesSelectionChange((int)s_EditMode))\n                return;\n            QuitEditMode();\n        }\n\n        public static void QuitEditMode()\n        {\n            if (ownerID != k_OwnerIdNone)\n                ChangeEditMode(SceneViewEditMode.None, new Bounds(Vector3.zero, Vector3.positiveInfinity), null);\n        }\n\n        [Obsolete(\"Obsolete msg (UnityUpgradable) -> UnityEditor.EditorTools.ToolManager.RestorePreviousTool()\")]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void ResetToolToPrevious()\n        {\n            ToolManager.RestorePreviousTool();\n        }\n\n        [Obsolete(\"Use signature passing Func<Bounds> rather than Bounds.\")]\n        public static void DoEditModeInspectorModeButton(SceneViewEditMode mode, string label, GUIContent icon, Bounds bounds, Editor caller)\n        {\n            DoEditModeInspectorModeButton(mode, label, icon, () => bounds, (IToolModeOwner)caller);\n        }\n\n        public static void DoEditModeInspectorModeButton(SceneViewEditMode mode, string label, GUIContent icon, Func<Bounds> getBoundsOfTargets, Editor caller)\n        {\n            DoEditModeInspectorModeButton(mode, label, icon, getBoundsOfTargets, (IToolModeOwner)caller);\n        }\n\n        internal static void DoEditModeInspectorModeButton(SceneViewEditMode mode, string label, GUIContent icon, IToolModeOwner owner)\n        {\n            DoEditModeInspectorModeButton(mode, label, icon, null, owner);\n        }\n\n        private static void DoEditModeInspectorModeButton(SceneViewEditMode mode, string label, GUIContent icon, Func<Bounds> getBoundsOfTargets, IToolModeOwner owner)\n        {\n            Rect rect = EditorGUILayout.GetControlRect(true, k_EditColliderbuttonHeight, Styles.singleButtonStyle);\n            Rect buttonRect = new Rect(rect.xMin + EditorGUIUtility.labelWidth, rect.yMin, k_EditColliderbuttonWidth, k_EditColliderbuttonHeight);\n\n            GUIContent labelContent = new GUIContent(label);\n            Vector2 labelSize = GUI.skin.label.CalcSize(labelContent);\n\n            Rect labelRect = new Rect(\n                buttonRect.xMax + k_SpaceBetweenLabelAndButton,\n                rect.yMin + (rect.height - labelSize.y) * .5f,\n                labelSize.x,\n                rect.height);\n\n            bool modeEnabled = IsOwner(owner);\n\n            EditorGUI.BeginChangeCheck();\n\n            bool toggleEnabled = false;\n            using (new EditorGUI.DisabledScope(!owner.areToolModesAvailable))\n            {\n                toggleEnabled = GUI.Toggle(buttonRect, modeEnabled, icon, Styles.singleButtonStyle);\n                GUI.Label(labelRect, label);\n            }\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                ChangeEditMode(toggleEnabled ? mode : SceneViewEditMode.None, getBoundsOfTargets == null ? owner.GetWorldBoundsOfTargets() : getBoundsOfTargets(), owner);\n            }\n        }\n\n        [Obsolete(\"Use signature passing Func<Bounds> rather than Bounds.\")]\n        public static void DoInspectorToolbar(SceneViewEditMode[] modes, GUIContent[] guiContents, Bounds bounds, Editor caller)\n        {\n            DoInspectorToolbar(modes, guiContents, () => bounds, (IToolModeOwner)caller);\n        }\n\n        public static void DoInspectorToolbar(SceneViewEditMode[] modes, GUIContent[] guiContents, Func<Bounds> getBoundsOfTargets, Editor caller)\n        {\n            DoInspectorToolbar(modes, guiContents, getBoundsOfTargets, (IToolModeOwner)caller);\n        }\n\n        internal static void DoInspectorToolbar(SceneViewEditMode[] modes, GUIContent[] guiContents, IToolModeOwner owner)\n        {\n            DoInspectorToolbar(modes, guiContents, null, owner);\n        }\n\n        private static void DoInspectorToolbar(SceneViewEditMode[] modes, GUIContent[] guiContents, Func<Bounds> getBoundsOfTargets, IToolModeOwner owner)\n        {\n            int callerID = owner.GetInstanceID();\n\n            int selectedIndex = ArrayUtility.IndexOf(modes, editMode);\n            if (ownerID != callerID)\n                selectedIndex = -1;\n            EditorGUI.BeginChangeCheck();\n            int newSelectedIndex = selectedIndex;\n            using (new EditorGUI.DisabledScope(!owner.areToolModesAvailable))\n                newSelectedIndex = GUILayout.Toolbar(selectedIndex, guiContents, Styles.multiButtonStyle);\n            if (EditorGUI.EndChangeCheck())\n            {\n                // Buttons can be toggled\n                SceneViewEditMode newEditMode = newSelectedIndex == selectedIndex ? SceneViewEditMode.None : modes[newSelectedIndex];\n                ChangeEditMode(newEditMode, getBoundsOfTargets == null ? owner.GetWorldBoundsOfTargets() : getBoundsOfTargets(), owner);\n            }\n        }\n\n        public static void ChangeEditMode(SceneViewEditMode mode, Bounds bounds, Editor caller)\n        {\n            ChangeEditMode(mode, bounds, (IToolModeOwner)caller);\n        }\n\n        internal static void ChangeEditMode(SceneViewEditMode mode, IToolModeOwner owner)\n        {\n            ChangeEditMode(mode, owner.GetWorldBoundsOfTargets(), owner);\n        }\n\n        internal static void ChangeEditMode(SceneViewEditMode mode, Bounds bounds, IToolModeOwner owner)\n        {\n            if (mode == SceneViewEditMode.None)\n            {\n                var activeToolIsEditModeTool = EditorToolManager.activeTool is NoneTool;\n\n                if (s_EditMode != SceneViewEditMode.None && activeToolIsEditModeTool)\n                    ToolManager.RestorePreviousTool();\n\n                EditModeToolStateChanged(owner, mode);\n                return;\n            }\n\n            ToolManager.SetActiveTool<NoneTool>();\n\n            EditModeToolStateChanged(owner, mode);\n        }\n\n        internal static void EditModeToolStateChanged(IToolModeOwner owner, SceneViewEditMode mode)\n        {\n            // In cases of domain reloads the EditorTool can be deserialized prior to the target Inspector being\n            // created. The EditMode tools do not expect an editModeStarted callback on reloads.\n            if (owner == null && mode != SceneViewEditMode.None)\n            {\n                editMode = mode;\n                return;\n            }\n\n            IToolModeOwner oldOwner = InternalEditorUtility.GetObjectFromInstanceID(ownerID) as IToolModeOwner;\n\n            editMode = mode;\n\n            if (oldOwner != null)\n            {\n                if (onEditModeEndDelegate != null && oldOwner is Editor)\n                    onEditModeEndDelegate(oldOwner as Editor);\n\n                if (editModeEnded != null)\n                    editModeEnded(oldOwner);\n            }\n\n            ownerID = mode != SceneViewEditMode.None ? owner.GetInstanceID() : k_OwnerIdNone;\n\n            if (editMode != SceneViewEditMode.None)\n            {\n                if (onEditModeStartDelegate != null && owner is Editor)\n                    onEditModeStartDelegate(owner as Editor, editMode);\n\n                if (editModeStarted != null)\n                    editModeStarted(owner, editMode);\n            }\n\n            FocusEditModeToolTarget((mode != SceneViewEditMode.None && owner != null)\n                ? owner.GetWorldBoundsOfTargets()\n                : new Bounds(Vector3.zero, Vector3.positiveInfinity));\n\n            InspectorWindow.RepaintAllInspectors();\n        }\n\n        // We make sure edited object is seen by the camera. We need object bounds to do that check.\n        static void FocusEditModeToolTarget(Bounds bounds)\n        {\n            // When entering the edit mode, check if the collider is seen by the scene view camera. If not, then we frame it.\n            if (editMode != SceneViewEditMode.None && SceneView.lastActiveSceneView != null && SceneView.lastActiveSceneView.camera != null)\n                if (!SeenByCamera(SceneView.lastActiveSceneView.camera, bounds))\n                    SceneView.lastActiveSceneView.Frame(bounds, EditorApplication.isPlaying);\n\n            SceneView.RepaintAll();\n        }\n\n        private static bool SeenByCamera(Camera camera, Bounds bounds)\n        {\n            return AnyPointSeenByCamera(camera, GetPoints(bounds));\n        }\n\n        private static Vector3[] GetPoints(Bounds bounds)\n        {\n            return BoundsToPoints(bounds);\n        }\n\n        private static Vector3[] BoundsToPoints(Bounds bounds)\n        {\n            Vector3[] result = new Vector3[8];\n            result[0] = new Vector3(bounds.min.x, bounds.min.y, bounds.min.z);\n            result[1] = new Vector3(bounds.min.x, bounds.min.y, bounds.max.z);\n            result[2] = new Vector3(bounds.min.x, bounds.max.y, bounds.min.z);\n            result[3] = new Vector3(bounds.min.x, bounds.max.y, bounds.max.z);\n            result[4] = new Vector3(bounds.max.x, bounds.min.y, bounds.min.z);\n            result[5] = new Vector3(bounds.max.x, bounds.min.y, bounds.max.z);\n            result[6] = new Vector3(bounds.max.x, bounds.max.y, bounds.min.z);\n            result[7] = new Vector3(bounds.max.x, bounds.max.y, bounds.max.z);\n            return result;\n        }\n\n        private static bool AnyPointSeenByCamera(Camera camera, Vector3[] points)\n        {\n            foreach (Vector3 point in points)\n                if (PointSeenByCamera(camera, point))\n                    return true;\n\n            return false;\n        }\n\n        private static bool PointSeenByCamera(Camera camera, Vector3 point)\n        {\n            Vector3 viewPoint = camera.WorldToViewportPoint(point);\n            return viewPoint.x > 0.0f && viewPoint.x < 1.0f && viewPoint.y > 0.0f && viewPoint.y < 1.0f;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Editor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEditor.AssetImporters;\nusing UnityEngine;\nusing UnityEngine.Internal;\nusing UnityEngine.Rendering;\nusing UnityEngine.Scripting;\nusing UnityEngine.UIElements;\nusing Component = UnityEngine.Component;\nusing UnityObject = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    interface IPreviewable\n    {\n        void Initialize(UnityObject[] targets);\n        void Cleanup();\n\n        UnityObject target { get; }\n        bool MoveNextTarget();\n        void ResetTarget();\n\n        bool HasPreviewGUI();\n        GUIContent GetPreviewTitle();\n        void DrawPreview(Rect previewArea);\n        VisualElement CreatePreview(VisualElement container);\n        void OnPreviewGUI(Rect r, GUIStyle background);\n        void OnInteractivePreviewGUI(Rect r, GUIStyle background);\n        void OnPreviewSettings();\n        string GetInfoString();\n\n        void ReloadPreviewInstances();\n    }\n\n    public class ObjectPreview : IPreviewable\n    {\n        static class Styles\n        {\n            public static readonly GUIStyle preBackground = \"PreBackground\";\n            public static readonly GUIStyle preBackgroundSolid = \"PreBackgroundSolid\";\n            public static readonly GUIStyle previewMiniLabel = \"PreMiniLabel\";\n            public static readonly GUIStyle dropShadowLabelStyle = \"PreOverlayLabel\";\n        }\n\n        const int kPreviewLabelHeight = 12;\n        const int kPreviewMinSize = 55;\n        const int kGridTargetCount = 25;\n        const int kGridSpacing = 10;\n        const int kPreviewLabelPadding = 5;\n\n        protected UnityObject[] m_Targets;\n        protected int m_ReferenceTargetIndex;\n\n        ~ObjectPreview()\n        {\n            // Watch out for Editor classes implementing OnDisableINTERNAL and not calling cleanup (GenericInspector).\n            Debug.LogError($\"{this} was not disposed properly. Make sure that base.Cleanup is called if overriding \" +\n                $\"the Cleanup method. If you are implementing this in an Editor or EditorWindow, don't \" +\n                $\"forget to call ObjectPreview.Cleanup in OnDisable.\");\n        }\n\n        public virtual void Cleanup()\n        {\n            GC.SuppressFinalize(this);\n        }\n\n        public virtual void Initialize(UnityObject[] targets)\n        {\n            m_ReferenceTargetIndex = 0;\n            m_Targets = targets;\n        }\n\n        public virtual bool MoveNextTarget()\n        {\n            m_ReferenceTargetIndex++;\n\n            return (m_ReferenceTargetIndex < m_Targets.Length - 1);\n        }\n\n        public virtual void ResetTarget()\n        {\n            m_ReferenceTargetIndex = 0;\n        }\n\n        public virtual UnityObject target\n        {\n            get\n            {\n                return m_Targets[m_ReferenceTargetIndex];\n            }\n        }\n\n        public virtual bool HasPreviewGUI()\n        {\n            return false;\n        }\n\n        public virtual VisualElement CreatePreview(VisualElement inspectorPreviewWindow)\n        {\n            return null;\n        }\n\n        public virtual GUIContent GetPreviewTitle()\n        {\n            GUIContent guiContent = new GUIContent();\n            guiContent.text = GetPreviewTitleString();\n            return guiContent;\n        }\n\n        string GetPreviewTitleString()\n        {\n            string title = String.Empty;\n            if (m_Targets.Length == 1)\n                title = target.name;\n            else\n            {\n                title = m_Targets.Length + \" \";\n                if (NativeClassExtensionUtilities.ExtendsANativeType(target))\n                    title += MonoScript.FromScriptedObject(target).GetClass().Name;\n                else\n                    title += ObjectNames.NicifyVariableName(ObjectNames.GetClassName(target));\n\n                title += \"s\";\n            }\n\n            return title;\n        }\n\n        public virtual void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            if (Event.current.type == EventType.Repaint)\n                background.Draw(r, false, false, false, false);\n        }\n\n        public virtual void OnInteractivePreviewGUI(Rect r, GUIStyle background)\n        {\n            OnPreviewGUI(r, background);\n        }\n\n        public virtual void OnPreviewSettings()\n        {\n        }\n\n        public virtual string GetInfoString()\n        {\n            return \"\";\n        }\n\n        public void DrawPreview(Rect previewArea)\n        {\n            DrawPreview(this, previewArea, m_Targets);\n        }\n\n        public virtual void ReloadPreviewInstances()\n        {\n        }\n\n        internal static void DrawPreview(IPreviewable defaultPreview, Rect previewArea, UnityObject[] targets)\n        {\n            string text = string.Empty;\n            Event evt = Event.current;\n\n            // If multiple targets, draw a grid of previews\n            if (targets.Length > 1)\n            {\n                // Draw the previews inside the region of the background that's solid colored\n                Rect previewPositionInner = new RectOffset(16, 16, 20, 25).Remove(previewArea);\n\n                // Number of previews to aim at\n                int maxRows = Mathf.Max(1, Mathf.FloorToInt((previewPositionInner.height + kGridSpacing) / (kPreviewMinSize + kGridSpacing + kPreviewLabelHeight)));\n                int maxCols = Mathf.Max(1, Mathf.FloorToInt((previewPositionInner.width + kGridSpacing) / (kPreviewMinSize + kGridSpacing)));\n                int countWithMinimumSize = maxRows * maxCols;\n                int neededCount = Mathf.Min(targets.Length, kGridTargetCount);\n\n                // Get number of columns and rows\n                bool fixedSize = true;\n                int[] division = new int[2] { maxCols, maxRows };\n                if (neededCount < countWithMinimumSize)\n                {\n                    division = GetGridDivision(previewPositionInner, neededCount, kPreviewLabelHeight);\n                    fixedSize = false;\n                }\n\n                // The available cells in the grid may be slightly higher than what was aimed at.\n                // If the number of targets is also higher, we might as well fill in the remaining cells.\n                int count = Mathf.Min(division[0] * division[1], targets.Length);\n\n                // Calculations become simpler if we add one spacing to the width and height,\n                // so there is the same number of spaces and previews.\n                previewPositionInner.width += kGridSpacing;\n                previewPositionInner.height += kGridSpacing;\n\n                Vector2 cellSize = new Vector2(\n                    Mathf.FloorToInt(previewPositionInner.width / division[0] - kGridSpacing),\n                    Mathf.FloorToInt(previewPositionInner.height / division[1] - kGridSpacing)\n                );\n                float previewSize = Mathf.Min(cellSize.x, cellSize.y - kPreviewLabelHeight);\n                if (fixedSize)\n                    previewSize = Mathf.Min(previewSize, kPreviewMinSize);\n\n                bool selectingOne = (evt.type == EventType.MouseDown && evt.button == 0 && evt.clickCount == 2 &&\n                    previewArea.Contains(evt.mousePosition));\n\n                defaultPreview.ResetTarget();\n                for (int i = 0; i < count; i++)\n                {\n                    Rect r = new Rect(\n                        previewPositionInner.x + (i % division[0]) * previewPositionInner.width / division[0],\n                        previewPositionInner.y + (i / division[0]) * previewPositionInner.height / division[1],\n                        cellSize.x,\n                        cellSize.y\n                    );\n\n                    if (selectingOne && r.Contains(Event.current.mousePosition))\n                    {\n                        if (defaultPreview.target is AssetImporter)\n                            // The new selection should be the asset itself, not the importer\n                            Selection.objects = new[] { AssetDatabase.LoadAssetAtPath<UnityObject>(((AssetImporter)defaultPreview.target).assetPath)};\n                        else\n                            Selection.objects = new UnityObject[] {defaultPreview.target};\n                    }\n\n                    // Make room for label underneath\n                    r.height -= kPreviewLabelHeight;\n                    // Make preview square\n                    Rect rSquare = new Rect(r.x + (r.width - previewSize) * 0.5f, r.y + (r.height - previewSize) * 0.5f, previewSize, previewSize);\n\n                    // Draw preview inside a group to prevent overdraw\n                    // @TODO: Make style with solid color that doesn't have overdraw\n                    GUI.BeginGroup(rSquare);\n                    Editor.m_AllowMultiObjectAccess = false;\n                    defaultPreview.OnInteractivePreviewGUI(new Rect(0, 0, previewSize, previewSize), Styles.preBackgroundSolid);\n                    Editor.m_AllowMultiObjectAccess = true;\n                    GUI.EndGroup();\n\n                    // Draw the name of the object\n                    r.y = rSquare.yMax;\n                    r.height = 16;\n                    GUI.Label(r, targets[i].name, Styles.previewMiniLabel);\n                    defaultPreview.MoveNextTarget();\n                }\n                defaultPreview.ResetTarget();  // Remember to reset referenceTargetIndex to prevent following calls to 'editor.target' will return a different target which breaks all sorts of places. Fix for case 600235\n\n                if (Event.current.type == EventType.Repaint)\n                    text = string.Format(\"Previewing {0} of {1} Objects\", count, targets.Length);\n            }\n            // If only a single target, just draw that one\n            else\n            {\n                defaultPreview.OnInteractivePreviewGUI(previewArea, Styles.preBackground);\n\n                if (Event.current.type == EventType.Repaint)\n                {\n                    // TODO: This should probably be calculated during import and stored together with the asset somehow. Or maybe not. Not sure, really...\n                    text = defaultPreview.GetInfoString();\n                    if (text != string.Empty)\n                    {\n                        text = text.Replace(\"\\n\", \"   \");\n                        text = string.Format(\"{0}\\n{1}\", defaultPreview.target.name, text);\n                    }\n                }\n            }\n\n            // Draw the asset info.\n            if (Event.current.type == EventType.Repaint && text != string.Empty)\n            {\n                var textHeight = Styles.dropShadowLabelStyle.CalcHeight(GUIContent.Temp(text), previewArea.width);\n                EditorGUI.DropShadowLabel(new Rect(previewArea.x, previewArea.yMax - textHeight - kPreviewLabelPadding, previewArea.width, textHeight), text);\n            }\n        }\n\n        // Get the number or columns and rows for a grid with a certain minimum number of cells\n        // such that the cells are as close to square as possible.\n        private static int[] GetGridDivision(Rect rect, int minimumNr, int labelHeight)\n        {\n            // The edge size of a square calculated based on area\n            float approxSize = Mathf.Sqrt(rect.width * rect.height / minimumNr);\n            int xCount = Mathf.FloorToInt(rect.width / approxSize);\n            int yCount = Mathf.FloorToInt(rect.height / (approxSize + labelHeight));\n            // This heuristic is not entirely optimal and could probably be improved\n            while (xCount * yCount < minimumNr)\n            {\n                float ratioIfXInc = AbsRatioDiff((xCount + 1) / rect.width, yCount / (rect.height - yCount * labelHeight));\n                float ratioIfYInc = AbsRatioDiff(xCount / rect.width, (yCount + 1) / (rect.height - (yCount + 1) * labelHeight));\n                if (ratioIfXInc < ratioIfYInc)\n                {\n                    xCount++;\n                    if (xCount * yCount > minimumNr)\n                        yCount = Mathf.CeilToInt((float)minimumNr / xCount);\n                }\n                else\n                {\n                    yCount++;\n                    if (xCount * yCount > minimumNr)\n                        xCount = Mathf.CeilToInt((float)minimumNr / yCount);\n                }\n            }\n            return new int[] { xCount, yCount };\n        }\n\n        private static float AbsRatioDiff(float x, float y)\n        {\n            return Mathf.Max(x / y, y / x);\n        }\n    }\n\n    internal interface IToolModeOwner\n    {\n        bool areToolModesAvailable { get; }\n        int GetInstanceID();\n        Bounds GetWorldBoundsOfTargets();\n        bool ModeSurvivesSelectionChange(int toolMode);\n    }\n\n    [Obsolete(@\"CustomEditorForRenderPipelineAttribute is deprecated. Use CustomEditor with SupportedOnCurrentPipeline instead. #from(2023.1)\", false)]\n    [AttributeUsage(AttributeTargets.Class)]\n    public class CustomEditorForRenderPipelineAttribute : CustomEditor\n    {\n        internal Type renderPipelineType;\n\n        public CustomEditorForRenderPipelineAttribute(Type inspectedType, Type renderPipeline) : base(inspectedType)\n        {\n            if (renderPipeline != null && !typeof(RenderPipelineAsset).IsAssignableFrom(renderPipeline))\n                Debug.LogError($\"The CustomEditorForRenderPipeline Attribute targets an invalid RenderPipelineAsset. {renderPipeline} cannot be assigned from RenderPipelineAsset.\");\n\n            renderPipelineType = renderPipeline;\n        }\n\n        public CustomEditorForRenderPipelineAttribute(Type inspectedType, Type renderPipeline, bool editorForChildClasses) : base(inspectedType, editorForChildClasses)\n        {\n            if (renderPipeline != null && !typeof(RenderPipelineAsset).IsAssignableFrom(renderPipeline))\n                Debug.LogError($\"The CustomEditorForRenderPipeline Attribute targets an invalid RenderPipelineAsset. {renderPipeline} cannot be assigned from RenderPipelineAsset.\");\n\n            renderPipelineType = renderPipeline;\n        }\n    }\n\n    public sealed partial class CanEditMultipleObjects : System.Attribute {}\n\n    [AttributeUsage(AttributeTargets.Field)]\n    internal sealed class CachePropertyAttribute : System.Attribute\n    {\n        public string propertyPath { get; }\n\n        public CachePropertyAttribute()\n        {\n            propertyPath = null;\n        }\n\n        public CachePropertyAttribute(string propertyPath)\n        {\n            this.propertyPath = propertyPath;\n        }\n    }\n\n    internal interface ICoupledEditor\n    {\n        SerializedObject coupledComponent { get; }\n    }\n\n    // Base class to derive custom Editors from. Use this to create your own custom inspectors and editors for your objects.\n    [ExcludeFromObjectFactory]\n    public partial class Editor : ScriptableObject, IPreviewable, IToolModeOwner\n    {\n        //If you modify the members of the Editor class, please keep in mind\n        //that you need to keep the c++ struct MonoInspectorData in sync.\n        //Last time this struct could be found at: Editor\\src\\Utility\\CreateEditor.cpp\n\n        // The object currently inspected by this editor.\n        UnityObject[] m_Targets;\n        // The context object with which this Editor was created\n        internal UnityObject m_Context;\n        // Note that m_Dirty is not only set through 'isInspectorDirty' but also from C++ in 'SetCustomEditorIsDirty (MonoBehaviour* inspector, bool dirty)'\n        int m_IsDirty;\n        int m_ReferenceTargetIndex = 0;\n        readonly PropertyHandlerCache m_PropertyHandlerCache = new PropertyHandlerCache();\n        internal IPreviewable m_DummyPreview;\n        AudioFilterGUI m_AudioFilterGUI;\n\n        internal SerializedObject m_SerializedObject = null;\n        internal SerializedProperty m_EnabledProperty = null;\n        private InspectorMode m_InspectorMode = InspectorMode.Normal;\n        internal InspectorMode inspectorMode\n        {\n            get\n            {\n                return propertyViewer?.inspectorMode ?? m_InspectorMode;\n            }\n            set\n            {\n                if (m_InspectorMode != value)\n                {\n                    m_InspectorMode = value;\n                    m_SerializedObject = null;\n                    m_EnabledProperty = null;\n                }\n            }\n        }\n\n        internal DataMode dataMode =>\n            propertyViewer is EditorWindow editorWindow\n                ? editorWindow.dataModeController.dataMode\n                : DataMode.Disabled;\n\n        internal static float kLineHeight = EditorGUI.kSingleLineHeight;\n\n        internal bool hideInspector = false;\n\n        const float kImageSectionWidth = 44;\n        internal const float k_WideModeMinWidth = 330f;\n        internal const float k_HeaderHeight = 21f;\n\n        internal delegate void OnEditorGUIDelegate(Editor editor, Rect drawRect);\n        internal static OnEditorGUIDelegate OnPostIconGUI = null;\n\n        internal static bool m_AllowMultiObjectAccess = true;\n\n        bool m_HasUnsavedChanges = false;\n\n        [UsedByNativeCode]\n        private bool GetHasUnsavedChanges()\n        {\n            return hasUnsavedChanges;\n        }\n\n        public bool hasUnsavedChanges\n        {\n            get\n            {\n                return m_HasUnsavedChanges;\n            }\n            protected set\n            {\n                if (m_HasUnsavedChanges != value)\n                {\n                    m_HasUnsavedChanges = value;\n                    if (propertyViewer != null)\n                    {\n                        propertyViewer.UnsavedChangesStateChanged(this, value);\n                    }\n                }\n            }\n        }\n\n        public string saveChangesMessage { get; protected set; }\n\n        public virtual void SaveChanges()\n        {\n            hasUnsavedChanges = false;\n        }\n\n        public virtual void DiscardChanges()\n        {\n            hasUnsavedChanges = false;\n        }\n\n        // used internally to know if this the first editor in the inspector window\n        internal bool firstInspectedEditor { get; set; }\n\n        IPropertyView m_PropertyViewer;\n\n        internal IPropertyView propertyViewer\n        {\n            get\n            {\n                return m_PropertyViewer;\n            }\n            set\n            {\n                if (m_PropertyViewer != value)\n                {\n                    m_PropertyViewer = value;\n\n                    // We are being assigned a new property view with different inspector mode to what our serialized object was built with.\n                    if (null != m_PropertyViewer && m_PropertyViewer.inspectorMode != m_InspectorMode)\n                    {\n                        // Keep the local inspector mode in sync.\n                        m_InspectorMode = m_PropertyViewer.inspectorMode;\n\n                        // Trash the local serialized object and property cache to force a rebuild.\n                        m_SerializedObject = null;\n                        m_EnabledProperty = null;\n                    }\n                }\n            }\n        }\n\n        internal virtual bool HasLargeHeader()\n        {\n            return AssetDatabase.IsMainAsset(target) || AssetDatabase.IsSubAsset(target);\n        }\n\n        internal bool canEditMultipleObjects\n        {\n            get\n            {\n                return Attribute.IsDefined(GetType(), typeof(CanEditMultipleObjects), false);\n            }\n        }\n\n        internal virtual IPreviewable preview\n        {\n            get\n            {\n                if (m_DummyPreview == null)\n                {\n                    m_DummyPreview = new ObjectPreview();\n                    m_DummyPreview.Initialize(targets);\n                }\n                return m_DummyPreview;\n            }\n        }\n\n        internal PropertyHandlerCache propertyHandlerCache\n        {\n            get { return m_PropertyHandlerCache; }\n        }\n\n        static class BaseStyles\n        {\n            public static readonly GUIContent open = EditorGUIUtility.TrTextContent(\"Open\");\n            public static readonly GUIStyle inspectorBig = new GUIStyle(EditorStyles.inspectorBig);\n            public static readonly GUIStyle centerStyle = new GUIStyle();\n            public static readonly GUIStyle postLargeHeaderBackground = \"IN BigTitle Post\";\n\n            static BaseStyles()\n            {\n                centerStyle.alignment = TextAnchor.MiddleCenter;\n            }\n        }\n\n        bool IToolModeOwner.areToolModesAvailable\n        {\n            get\n            {\n                // tool modes not available when the target is a prefab parent\n                return !EditorUtility.IsPersistent(target);\n            }\n        }\n\n        // The object being inspected.\n        public UnityObject target { get { return m_Targets[referenceTargetIndex]; } set { throw new InvalidOperationException(\"You can't set the target on an editor.\"); } }\n\n        // An array of all the object being inspected.\n        public UnityObject[] targets\n        {\n            get\n            {\n                if (!m_AllowMultiObjectAccess)\n                    Debug.LogError(\"The targets array should not be used inside OnSceneGUI or OnPreviewGUI. Use the single target property instead.\");\n                return m_Targets;\n            }\n        }\n\n        internal virtual int referenceTargetIndex\n        {\n            get { return Mathf.Clamp(m_ReferenceTargetIndex, 0, m_Targets.Length - 1); }\n            // Modulus that works for negative numbers as well\n            set { m_ReferenceTargetIndex = (Math.Abs(value * m_Targets.Length) + value) % m_Targets.Length; }\n        }\n\n        internal virtual string targetTitle\n        {\n            get\n            {\n                if (m_Targets.Length == 1 || !m_AllowMultiObjectAccess)\n                    return ObjectNames.GetInspectorTitle(target);\n                else\n                    return m_Targets.Length + \" \" + ObjectNames.NicifyVariableName(ObjectNames.GetTypeName(target)) + \"s\";\n            }\n        }\n\n        // A [[SerializedObject]] representing the object or objects being inspected.\n        public SerializedObject serializedObject\n        {\n            get\n            {\n                if (!m_AllowMultiObjectAccess)\n                    Debug.LogError(\"The serializedObject should not be used inside OnSceneGUI or OnPreviewGUI. Use the target property directly instead.\");\n                return GetSerializedObjectInternal();\n            }\n        }\n\n        internal SerializedProperty enabledProperty\n        {\n            get\n            {\n                GetSerializedObjectInternal();\n                return m_EnabledProperty;\n            }\n        }\n\n        internal virtual void PostSerializedObjectCreation() {}\n\n        internal bool isInspectorDirty\n        {\n            get { return m_IsDirty != 0; }\n            set { m_IsDirty = value ? 1 : 0; }\n        }\n\n        public static Editor CreateEditorWithContext(UnityObject[] targetObjects, UnityObject context, [UnityEngine.Internal.DefaultValue(\"null\")] Type editorType)\n        {\n            if (editorType != null && !editorType.IsSubclassOf(typeof(Editor)))\n                throw new ArgumentException($\"Editor type '{editorType}' does not derive from UnityEditor.Editor\", \"editorType\");\n\n            return CreateEditorWithContextInternal(targetObjects, context, editorType);\n        }\n\n        [ExcludeFromDocs]\n        public static Editor CreateEditorWithContext(UnityObject[] targetObjects, UnityObject context)\n        {\n            Type editorType = null;\n            return CreateEditorWithContext(targetObjects, context, editorType);\n        }\n\n        public static void CreateCachedEditorWithContext(UnityObject targetObject, UnityObject context, Type editorType, ref Editor previousEditor)\n        {\n            CreateCachedEditorWithContext(new[] {targetObject}, context, editorType, ref previousEditor);\n        }\n\n        public static void CreateCachedEditorWithContext(UnityObject[] targetObjects, UnityObject context, Type editorType, ref Editor previousEditor)\n        {\n            if (previousEditor != null && ArrayUtility.ArrayEquals(previousEditor.m_Targets, targetObjects) && previousEditor.m_Context == context)\n                return;\n\n            if (previousEditor != null)\n                DestroyImmediate(previousEditor);\n            previousEditor = CreateEditorWithContext(targetObjects, context, editorType);\n        }\n\n        public static void CreateCachedEditor(UnityObject targetObject, Type editorType, ref Editor previousEditor)\n        {\n            CreateCachedEditorWithContext(new[] {targetObject}, null, editorType, ref previousEditor);\n        }\n\n        public static void CreateCachedEditor(UnityObject[] targetObjects, Type editorType, ref Editor previousEditor)\n        {\n            CreateCachedEditorWithContext(targetObjects, null, editorType, ref previousEditor);\n        }\n\n        [ExcludeFromDocs]\n        public static Editor CreateEditor(UnityObject targetObject)\n        {\n            Type editorType = null;\n            return CreateEditor(targetObject, editorType);\n        }\n\n        public static Editor CreateEditor(UnityObject targetObject, [UnityEngine.Internal.DefaultValue(\"null\")]  Type editorType)\n        {\n            return CreateEditorWithContext(new[] {targetObject}, null, editorType);\n        }\n\n        [ExcludeFromDocs]\n        public static Editor CreateEditor(UnityObject[] targetObjects)\n        {\n            Type editorType = null;\n            return CreateEditor(targetObjects, editorType);\n        }\n\n        public static Editor CreateEditor(UnityObject[] targetObjects, [UnityEngine.Internal.DefaultValue(\"null\")]  Type editorType)\n        {\n            return CreateEditorWithContext(targetObjects, null, editorType);\n        }\n\n        internal void CleanupPropertyEditor()\n        {\n            if (m_SerializedObject != null)\n            {\n                m_SerializedObject.Dispose();\n                m_SerializedObject = null;\n            }\n        }\n\n        private void OnDisableINTERNAL()\n        {\n            CleanupPropertyEditor();\n            propertyHandlerCache.Dispose();\n            if (m_DummyPreview != null && m_DummyPreview is not Editor)\n                m_DummyPreview.Cleanup();\n        }\n\n        internal virtual SerializedObject GetSerializedObjectInternal()\n        {\n            if (m_SerializedObject == null)\n            {\n                CreateSerializedObject();\n            }\n\n            return m_SerializedObject;\n        }\n\n        internal class SerializedObjectNotCreatableException : Exception\n        {\n            public SerializedObjectNotCreatableException(string msg) : base(msg) {}\n        }\n\n        private void CreateSerializedObject()\n        {\n            try\n            {\n                m_SerializedObject = new SerializedObject(targets, m_Context);\n                m_SerializedObject.inspectorMode = inspectorMode;\n                if (m_SerializedObject.inspectorDataMode != dataMode)\n                    m_SerializedObject.inspectorDataMode = dataMode;\n\n                AssignCachedProperties(this, m_SerializedObject.GetIterator());\n                m_EnabledProperty = m_SerializedObject.FindProperty(\"m_Enabled\");\n                PostSerializedObjectCreation();\n            }\n            catch (ArgumentException e)\n            {\n                m_SerializedObject = null;\n                m_EnabledProperty = null;\n                throw new SerializedObjectNotCreatableException(e.Message);\n            }\n        }\n\n        internal static void AssignCachedProperties<T>(T self, SerializedProperty root) where T : class\n        {\n            var fields = ScriptAttributeUtility.GetAutoLoadProperties(typeof(T));\n            if (fields.Count == 0)\n                return;\n\n            var properties = new Dictionary<string, FieldInfo>(fields.Count);\n            var allParents = new HashSet<string>();\n            foreach (var fieldInfo in fields)\n            {\n                var attribute = (CachePropertyAttribute)fieldInfo.GetCustomAttributes(typeof(CachePropertyAttribute), false).First();\n                var propertyName = string.IsNullOrEmpty(attribute.propertyPath) ? fieldInfo.Name : attribute.propertyPath;\n                properties.Add(propertyName, fieldInfo);\n                int dot = propertyName.LastIndexOf('.');\n                while (dot != -1)\n                {\n                    propertyName = propertyName.Substring(0, dot);\n                    if (!allParents.Add(propertyName))\n                        break;\n                    dot = propertyName.LastIndexOf('.');\n                }\n            }\n\n            var parentPath = root.propertyPath;\n            var parentPathLength = parentPath.Length > 0 ? parentPath.Length + 1 : 0;\n            var exitCount = properties.Count;\n            var iterator = root.Copy();\n            bool enterChildren = true;\n            while (iterator.Next(enterChildren) && exitCount > 0)\n            {\n                FieldInfo fieldInfo;\n                var propertyPath = iterator.propertyPath.Substring(parentPathLength);\n                if (properties.TryGetValue(propertyPath, out fieldInfo))\n                {\n                    fieldInfo.SetValue(self, iterator.Copy());\n                    properties.Remove(propertyPath);\n                    exitCount--;\n                }\n\n                enterChildren = allParents.Contains(propertyPath);\n            }\n            iterator.Dispose();\n            if (exitCount > 0)\n            {\n                Debug.LogWarning(\"The following properties registered with CacheProperty where not found during the inspector creation: \" + string.Join(\", \", properties.Keys.ToArray()));\n            }\n        }\n\n        internal void InternalSetTargets(UnityObject[] t) { m_Targets = t; }\n        internal void InternalSetHidden(bool hidden) { hideInspector = hidden; }\n        internal void InternalSetContextObject(UnityObject context) { m_Context = context; }\n\n        Bounds IToolModeOwner.GetWorldBoundsOfTargets()\n        {\n            var result = new Bounds();\n            bool initialized = false;\n\n            foreach (var t in targets)\n            {\n                if (t == null)\n                    continue;\n\n                Bounds targetBounds = GetWorldBoundsOfTarget(t);\n\n                if (!initialized)\n                    result = targetBounds;\n                result.Encapsulate(targetBounds);\n\n                initialized = true;\n            }\n\n            return result;\n        }\n\n        internal virtual Bounds GetWorldBoundsOfTarget(UnityObject targetObject)\n        {\n            return targetObject is Component ? ((Component)targetObject).gameObject.CalculateBounds() : new Bounds();\n        }\n\n        bool IToolModeOwner.ModeSurvivesSelectionChange(int toolMode)\n        {\n            return false;\n        }\n\n        // Reload SerializedObject because flags etc might have changed.\n        internal virtual void OnForceReloadInspector()\n        {\n            if (m_SerializedObject != null)\n            {\n                m_SerializedObject.SetIsDifferentCacheDirty();\n                // Need to make sure internal target list PPtr have been updated from a native memory\n                // When assets are reloaded they are destroyed and recreated and the managed list does not get updated\n                // The m_SerializedObject is a native object thus its targetObjects is a native memory PPtr list which have the new PPtr ids.\n                InternalSetTargets(m_SerializedObject.targetObjects);\n            }\n        }\n\n        internal virtual bool GetOptimizedGUIBlock(bool isDirty, bool isVisible, out float height)\n        {\n            height = -1;\n            return false;\n        }\n\n        internal virtual bool OnOptimizedInspectorGUI(Rect contentRect)\n        {\n            Debug.LogError(\"Not supported\");\n            return false;\n        }\n\n        protected internal static void DrawPropertiesExcluding(SerializedObject obj, params string[] propertyToExclude)\n        {\n            // Loop through properties and create one field (including children) for each top level property.\n            SerializedProperty property = obj.GetIterator();\n            bool expanded = true;\n            while (property.NextVisible(expanded))\n            {\n                expanded = false;\n\n                if (propertyToExclude.Contains(property.name))\n                    continue;\n\n                EditorGUILayout.PropertyField(property, true);\n            }\n        }\n\n        // Draw the built-in inspector.\n        public bool DrawDefaultInspector()\n        {\n            return DoDrawDefaultInspector();\n        }\n\n        internal static bool DoDrawDefaultInspector(SerializedObject obj)\n        {\n            EditorGUI.BeginChangeCheck();\n            obj.UpdateIfRequiredOrScript();\n\n            // Loop through properties and create one field (including children) for each top level property.\n            SerializedProperty property = obj.GetIterator();\n            bool expanded = true;\n            while (property.NextVisible(expanded))\n            {\n                using (new EditorGUI.DisabledScope(\"m_Script\" == property.propertyPath))\n                {\n                    EditorGUILayout.PropertyField(property, true);\n                }\n                expanded = false;\n            }\n\n            obj.ApplyModifiedProperties();\n\n            return EditorGUI.EndChangeCheck();\n        }\n\n        internal bool DoDrawDefaultInspector()\n        {\n            bool res;\n            using (new LocalizationGroup(target))\n            {\n                res = DoDrawDefaultInspector(serializedObject);\n\n                var behaviour = target as MonoBehaviour;\n                if (behaviour == null || !AudioUtil.HasAudioCallback(behaviour) || AudioUtil.GetCustomFilterChannelCount(behaviour) <= 0)\n                    return res;\n\n                // If we have an OnAudioFilterRead callback, draw vu meter\n                if (m_AudioFilterGUI == null)\n                    m_AudioFilterGUI = new AudioFilterGUI();\n                m_AudioFilterGUI.DrawAudioFilterGUI(behaviour);\n            }\n            return res;\n        }\n\n        // Repaint any inspectors that shows this editor.\n        public void Repaint()\n        {\n            if (propertyViewer != null)\n                propertyViewer.Repaint();\n            else\n                InspectorWindow.RepaintAllInspectors();\n        }\n\n        // Implement this function to make a custom IMGUI inspector.\n        public virtual void OnInspectorGUI()\n        {\n            DrawDefaultInspector();\n        }\n\n        // Implement this function to make a custom UIElements inspector.\n        public virtual VisualElement CreateInspectorGUI()\n        {\n            return null;\n        }\n\n        // Implement this function if you want your editor constantly repaint (every 33ms)\n        public virtual bool RequiresConstantRepaint()\n        {\n            return false;\n        }\n\n        public static event Action<Editor> finishedDefaultHeaderGUI = null;\n\n        // This is the method that should be called from externally e.g. myEditor.DrawHeader ();\n        // Do not make this method virtual - override OnHeaderGUI instead.\n        public void DrawHeader()\n        {\n            // If we call DrawHeader from inside an an editor's OnInspectorGUI call, we have to do special handling.\n            // (See DrawHeaderFromInsideHierarchy for details.)\n            // We know we're inside the OnInspectorGUI block (or a similar vertical block) if hierarchyMode is set to true.\n            var hierarchyMode = EditorGUIUtility.hierarchyMode;\n            if (hierarchyMode)\n                DrawHeaderFromInsideHierarchy();\n            else\n                OnHeaderGUI();\n\n            if (finishedDefaultHeaderGUI != null)\n            {\n                // see DrawHeaderFromInsideHierarchy()\n                if (hierarchyMode)\n                {\n                    EditorGUILayout.EndVertical();\n                    EditorGUILayout.BeginVertical(GUILayoutUtility.topLevel.style);\n                }\n                // reset label and field widths to defaults\n                EditorGUIUtility.labelWidth = 0f;\n                EditorGUIUtility.fieldWidth = 0f;\n\n                GUILayout.Space(\n                    -1f                                          // move up to cover up bottom pixel of header box\n                    - BaseStyles.inspectorBig.margin.bottom\n                    - BaseStyles.inspectorBig.padding.bottom\n                    - BaseStyles.inspectorBig.overflow.bottom    // move up to bottom of content area in header\n                );\n\n                // align with controls in the Inspector\n                // see InspectorWindow.DrawEditor() before calls to OnOptimizedInspectorGUI()/OnInspectorGUI()\n                EditorGUIUtility.hierarchyMode = true;\n                EditorGUIUtility.wideMode = EditorGUIUtility.contextWidth > k_WideModeMinWidth;\n                EditorGUILayout.BeginVertical(BaseStyles.postLargeHeaderBackground, GUILayout.ExpandWidth(true));\n                finishedDefaultHeaderGUI(this);\n                EditorGUILayout.EndVertical();\n                if (hierarchyMode)\n                {\n                    EditorGUILayout.EndVertical();\n                    // see InspectorWindow.DoOnInspectorGUI()\n                    EditorGUILayout.BeginVertical(UseDefaultMargins() ? EditorStyles.inspectorDefaultMargins : GUIStyle.none);\n                }\n            }\n\n            // Restore previous hierarchy mode\n            EditorGUIUtility.hierarchyMode = hierarchyMode;\n        }\n\n        // This is the method to override to create custom header GUI.\n        // Do not make this method internal or public - call DrawHeader instead.\n        protected virtual void OnHeaderGUI()\n        {\n            DrawHeaderGUI(this, targetTitle);\n        }\n\n        internal virtual void OnHeaderControlsGUI()\n        {\n            // Ensure we take up the same amount of height as regular controls\n            GUILayoutUtility.GetRect(10, 10, 16, 16, EditorStyles.layerMaskField);\n\n            GUILayout.FlexibleSpace();\n\n            bool showOpenButton = true;\n            var importerEditor = this as AssetImporterEditor;\n            // only show open button for the main object of an asset and for AssetImportInProgressProxy (asset not yet imported)\n            if (importerEditor == null && !(targets[0] is AssetImportInProgressProxy))\n            {\n                var assetPath = AssetDatabase.GetAssetPath(targets[0]);\n                // Don't show open button if the target is not an asset\n                if (!AssetDatabase.IsMainAsset(targets[0]))\n                    showOpenButton = false;\n                // Don't show open button if the target has an importer\n                // (but ignore AssetImporters since they're not shown)\n                AssetImporter importer = AssetImporter.GetAtPath(assetPath);\n                if (importer && importer.GetType() != typeof(AssetImporter))\n                    showOpenButton = false;\n            }\n\n            if (showOpenButton && !ShouldHideOpenButton())\n            {\n                var assets = importerEditor != null ? importerEditor.assetTargets : targets;\n                var disabled = importerEditor != null && importerEditor.assetTarget == null;\n                ShowOpenButton(assets, !disabled);\n            }\n        }\n\n        internal void ShowOpenButton(UnityObject[] assets, bool enableCondition = true)\n        {\n            int assetCount = assets != null? assets.Length : 0;\n            enableCondition &= (CanOpenMultipleObjects() || assetCount == 1);\n            bool previousGUIState = GUI.enabled;\n            GUI.enabled = enableCondition;\n\n            if (GUILayout.Button(BaseStyles.open, EditorStyles.miniButton))\n            {\n                bool openAssets = false;\n\n                // 'Check Out and Open' dialog\n                openAssets = AssetDatabase.MakeEditable(assets.Select(AssetDatabase.GetAssetPath).ToArray(),\n                    \"Do you want to check out \" +\n                    (assetCount > 1 ? String.Format(\"these {0} files?\", assetCount) : \"this file?\"));\n\n                // 'Open multiple assets' dialog\n                if (openAssets && assetCount > 1)\n                {\n                    openAssets = (EditorUtility.DisplayDialog(\"Open Selected Assets?\",\n                        String.Format(\"Are you sure you want to open {0} selected assets?\", assetCount), \"Open\",\n                        \"Cancel\"));\n                }\n\n                if (openAssets)\n                {\n                    AssetDatabase.OpenAsset(assets);\n                    GUIUtility.ExitGUI();\n                }\n            }\n\n            GUI.enabled = previousGUIState;\n        }\n\n        protected virtual bool ShouldHideOpenButton()\n        {\n            return false;\n        }\n\n        internal virtual bool CanOpenMultipleObjects()\n        {\n            return true;\n        }\n\n        internal virtual bool ShouldTryToMakeEditableOnOpen()\n        {\n            return true;\n        }\n\n        internal virtual void OnHeaderIconGUI(Rect iconRect)\n        {\n            Texture2D icon = null;\n\n            //  Fetch isLoadingAssetPreview to ensure that there is no situation where a preview needs a repaint because it hasn't finished loading yet.\n            bool isLoadingAssetPreview = AssetPreview.IsLoadingAssetPreview(target.GetInstanceID());\n            icon = AssetPreview.GetAssetPreview(target);\n            if (!icon)\n            {\n                // We have a static preview it just hasn't been loaded yet. Repaint until we have it loaded.\n                if (isLoadingAssetPreview)\n                    Repaint();\n                icon = AssetPreview.GetMiniThumbnail(target);\n            }\n\n            GUI.Label(iconRect, icon, BaseStyles.centerStyle);\n        }\n\n        internal virtual void OnHeaderTitleGUI(Rect titleRect, string header)\n        {\n            titleRect.yMin -= 2;\n            titleRect.yMax += 2;\n            GUI.Label(titleRect, header, EditorStyles.largeLabel);\n        }\n\n        // Draws the help and settings part of the header.\n        // Returns a Rect to know where to draw the rest of the header.\n        internal virtual Rect DrawHeaderHelpAndSettingsGUI(Rect r)\n        {\n            // Help\n            var settingsSize = EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.titleSettingsIcon);\n\n            float currentOffset = settingsSize.x;\n\n            const int kTopMargin = 5;\n            // Settings; process event even for disabled UI\n            Rect settingsRect = new Rect(r.xMax - currentOffset, r.y + kTopMargin, settingsSize.x, settingsSize.y);\n            var wasEnabled = GUI.enabled;\n            GUI.enabled = true;\n            var showMenu = EditorGUI.DropdownButton(settingsRect, GUIContent.none, FocusType.Passive,\n                EditorStyles.optionsButtonStyle);\n            GUI.enabled = wasEnabled;\n            if (showMenu)\n            {\n                EditorUtility.DisplayObjectContextMenu(settingsRect, targets, 0);\n            }\n\n            currentOffset += settingsSize.x;\n\n            // Show Editor Header Items.\n            return EditorGUIUtility.DrawEditorHeaderItems(new Rect(r.xMax - currentOffset, r.y + kTopMargin, settingsSize.x, settingsSize.y), targets);\n        }\n\n        // If we call DrawHeaderGUI from inside an an editor's OnInspectorGUI call, we have to do special handling.\n        // Since OnInspectorGUI is wrapped inside a BeginVertical/EndVertical block that adds padding,\n        // and we don't want this padding for headers, we have to stop the vertical block,\n        // draw the header, and then start a new vertical block with the same style.\n        private void DrawHeaderFromInsideHierarchy()\n        {\n            var style = GUILayoutUtility.topLevel.style;\n            EditorGUILayout.EndVertical();\n            OnHeaderGUI();\n            EditorGUILayout.BeginVertical(style);\n        }\n\n        internal static Rect DrawHeaderGUI(Editor editor, string header)\n        {\n            return DrawHeaderGUI(editor, header, 0f);\n        }\n\n        internal static Rect DrawHeaderGUI(Editor editor, string header, float leftMargin)\n        {\n            GUILayout.BeginHorizontal(BaseStyles.inspectorBig);\n            GUILayout.Space(kImageSectionWidth - 6);\n            GUILayout.BeginVertical();\n            GUILayout.Space(k_HeaderHeight);\n            GUILayout.BeginHorizontal();\n            if (leftMargin > 0f)\n                GUILayout.Space(leftMargin);\n            if (editor)\n                editor.OnHeaderControlsGUI();\n            else\n                EditorGUILayout.GetControlRect();\n            GUILayout.EndHorizontal();\n            GUILayout.EndVertical();\n            GUILayout.EndHorizontal();\n            Rect fullRect = GUILayoutUtility.GetLastRect();\n\n            // Content rect\n            Rect r = new Rect(fullRect.x + leftMargin, fullRect.y, fullRect.width - leftMargin, fullRect.height);\n\n            // Icon\n            Rect iconRect = new Rect(r.x + 6, r.y + 6, 32, 32);\n\n            if (editor)\n                editor.OnHeaderIconGUI(iconRect);\n            else\n                GUI.Label(iconRect, AssetPreview.GetMiniTypeThumbnail(typeof(UnityObject)), BaseStyles.centerStyle);\n\n            if (editor)\n                editor.DrawPostIconContent(iconRect);\n\n            // Help and Settings\n            Rect titleRect;\n            var titleHeight = EditorGUI.lineHeight;\n            if (editor)\n            {\n                Rect helpAndSettingsRect = editor.DrawHeaderHelpAndSettingsGUI(r);\n                float rectX = r.x + kImageSectionWidth;\n                titleRect = new Rect(rectX, r.y + 6, (helpAndSettingsRect.x - rectX) - 4, titleHeight);\n            }\n            else\n                titleRect = new Rect(r.x + kImageSectionWidth, r.y + 6, r.width - kImageSectionWidth, titleHeight);\n\n            if (editor && editor.hasUnsavedChanges && !string.IsNullOrEmpty(header))\n            {\n                header += \" *\";\n            }\n\n            // Title\n            if (editor)\n                editor.OnHeaderTitleGUI(titleRect, header);\n            else\n                GUI.Label(titleRect, header, EditorStyles.largeLabel);\n\n            CheckForMainObjectNameMismatch(editor);\n\n            // Context Menu; process event even for disabled UI\n            var wasEnabled = GUI.enabled;\n            GUI.enabled = true;\n            Event evt = Event.current;\n            var showMenu = editor != null && evt.type == EventType.MouseDown && evt.button == 1 && r.Contains(evt.mousePosition);\n            GUI.enabled = wasEnabled;\n\n            if (showMenu)\n            {\n                EditorUtility.DisplayObjectContextMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), editor.targets, 0);\n                evt.Use();\n            }\n\n            return fullRect;\n        }\n\n        internal static void CheckForMainObjectNameMismatch(Editor editor)\n        {\n            if (editor && editor.target && AssetDatabase.IsNativeAsset(editor.target) && AssetDatabase.IsMainAsset(editor.target) && !Unsupported.GetSerializedAssetInterfaceSingleton(editor.target.name))\n            {\n                var mainObjectName = editor.target.name;\n                var fileName = FileUtil.GetLastPathNameComponent(AssetDatabase.GetAssetPath(editor.target));\n                var expectedMainObjectName = FileUtil.GetPathWithoutExtension(fileName);\n\n                if (mainObjectName != expectedMainObjectName)\n                {\n                    DrawMismatchedNameNotification(editor, expectedMainObjectName, mainObjectName);\n                }\n            }\n        }\n\n        static void DrawMismatchedNameNotification(Editor editor, string expectedMainObjectName, string mainObjectName)\n        {\n            var warningText = $\"The main object name '{mainObjectName}' should match the asset filename '{expectedMainObjectName}'.\\nPlease fix to avoid errors.\";\n            var image = EditorGUIUtility.GetHelpIcon(MessageType.Warning);\n            var btnText = \"Fix object name\";\n            Action onBtnClick = () =>\n            {\n                editor.target.name = expectedMainObjectName;\n                AssetDatabase.SaveAssetIfDirty(editor.target);\n\n                var message = String.Format(\"Main Object Name '{0}' does not match filename '{1}'\", mainObjectName, expectedMainObjectName);\n                var hash = Hash128.Compute(message);\n                UInt32 correspondingLogID = (UInt32)hash.GetHashCode();\n                Debug.RemoveLogEntriesByIdentifier((int)correspondingLogID);\n            };\n\n            DrawNotification(image, warningText, btnText, onBtnClick);\n        }\n\n        internal static void DrawNotification(Texture image, string text, string btnText, Action onBtnClick)\n        {\n            using (new GUILayout.VerticalScope(EditorStyles.helpBox))\n            {\n                using (new GUILayout.HorizontalScope())\n                {\n                    GUILayout.Label(image, GUILayout.ExpandWidth(false));\n                    using (new GUILayout.VerticalScope())\n                    {\n                        GUILayout.FlexibleSpace();\n                        GUILayout.Label(text, EditorStyles.wordWrappedLabel);\n                        GUILayout.FlexibleSpace();\n                    }\n\n                    GUILayout.FlexibleSpace();\n\n                    if (onBtnClick != null)\n                    {\n                        using (new GUILayout.VerticalScope())\n                        {\n                            GUILayout.FlexibleSpace();\n                            if (GUILayout.Button(btnText, EditorStyles.miniButtonRight, GUILayout.ExpandWidth(false)))\n                                onBtnClick.Invoke();\n                            GUILayout.FlexibleSpace();\n                        }\n                    }\n\n                }\n            }\n        }\n\n        internal void DrawPostIconContent(Rect iconRect)\n        {\n            if (OnPostIconGUI != null && Event.current.type == EventType.Repaint)\n            {\n                // Post icon draws 16 x 16 at bottom right corner\n                const float k_Size = 16;\n                Rect drawRect = iconRect;\n                drawRect.x = (drawRect.xMax - k_Size) + 4; // Move slightly outside bounds for overlap effect.\n                drawRect.y = (drawRect.yMax - k_Size) + 1;\n                drawRect.width = k_Size;\n                drawRect.height = k_Size;\n                OnPostIconGUI(this, drawRect);\n            }\n        }\n\n        public static void DrawFoldoutInspector(UnityObject target, ref Editor editor)\n        {\n            if (editor != null && (editor.target != target || target == null))\n            {\n                UnityObject.DestroyImmediate(editor);\n                editor = null;\n            }\n\n            if (editor == null && target != null)\n                editor = Editor.CreateEditor(target);\n\n            if (editor == null)\n                return;\n\n            const float kSpaceForFoldoutArrow = 10f;\n            Rect titleRect = Editor.DrawHeaderGUI(editor, editor.targetTitle, kSpaceForFoldoutArrow);\n            int id = GUIUtility.GetControlID(45678, FocusType.Passive);\n\n            Rect renderRect = EditorGUI.GetInspectorTitleBarObjectFoldoutRenderRect(titleRect);\n            renderRect.y = titleRect.yMax - 17f; // align with bottom\n            bool oldVisible = UnityEditorInternal.InternalEditorUtility.GetIsInspectorExpanded(target);\n            bool newVisible = EditorGUI.DoObjectFoldout(oldVisible, titleRect, renderRect, editor.targets, id);\n\n            if (newVisible != oldVisible)\n                UnityEditorInternal.InternalEditorUtility.SetIsInspectorExpanded(target, newVisible);\n\n            if (newVisible)\n                editor.OnInspectorGUI();\n        }\n\n        // Override this method in subclasses if you implement OnPreviewGUI.\n        public virtual bool HasPreviewGUI()\n        {\n            return preview.HasPreviewGUI();\n        }\n\n        public virtual VisualElement CreatePreview(VisualElement inspectorPreviewWindow)\n        {\n            return preview.CreatePreview(inspectorPreviewWindow);\n        }\n\n        // Override this method if you want to change the label of the Preview area.\n        public virtual GUIContent GetPreviewTitle()\n        {\n            return preview.GetPreviewTitle();\n        }\n\n        // Override this method if you want to render a static preview that shows.\n        public virtual Texture2D RenderStaticPreview(string assetPath, UnityObject[] subAssets, int width, int height)\n        {\n            return null;\n        }\n\n        // Implement to create your own custom preview. Custom previews are used in the preview area of the inspector, primary editor headers, and the object selector.\n        public virtual void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            preview.OnPreviewGUI(r, background);\n        }\n\n        // Implement to create your own interactive custom preview. Interactive custom previews are used in the preview area of the inspector and the object selector.\n        public virtual void OnInteractivePreviewGUI(Rect r, GUIStyle background)\n        {\n            OnPreviewGUI(r, background);\n        }\n\n        // Override this method if you want to show custom controls in the preview header.\n        public virtual void OnPreviewSettings()\n        {\n            preview.OnPreviewSettings();\n        }\n\n        // Implement this method to show asset information on top of the asset preview.\n        public virtual string GetInfoString()\n        {\n            return preview.GetInfoString();\n        }\n\n        public virtual void DrawPreview(Rect previewArea)\n        {\n            ObjectPreview.DrawPreview(this, previewArea, targets);\n        }\n\n        public virtual void ReloadPreviewInstances()\n        {\n            preview.ReloadPreviewInstances();\n        }\n\n        // Some custom editors manually display SerializedObjects with only private properties\n        // Setting this to true allows them to properly toggling the visibility via the standard header foldout\n        internal bool alwaysAllowExpansion {get; set;}\n\n        // Auxiliary method that determines whether this editor has a set of public properties and, as thus,\n        // can be expanded via a foldout. This is used in order to determine whether a foldout needs to be\n        // rendered on top of the inspector title bar or not. Some examples of editors that don't require\n        // a foldout are GUI Layer and Audio Listener.\n        internal bool CanBeExpandedViaAFoldout()\n        {\n            if (alwaysAllowExpansion)\n                return true;\n\n            if (m_SerializedObject == null)\n            {\n                CreateSerializedObject();\n            }\n            else\n                m_SerializedObject.Update();\n            m_SerializedObject.inspectorMode = inspectorMode;\n            if (m_SerializedObject.inspectorDataMode != dataMode)\n                m_SerializedObject.inspectorDataMode = dataMode;\n\n            return CanBeExpandedViaAFoldoutWithoutUpdate();\n        }\n\n        internal bool CanBeExpandedViaAFoldoutWithoutUpdate()\n        {\n            if (alwaysAllowExpansion)\n                return true;\n\n            if (m_SerializedObject == null)\n            {\n                CreateSerializedObject();\n            }\n            SerializedProperty property = m_SerializedObject.GetIterator();\n\n            bool analyzePropertyChildren = true;\n            while (property.NextVisible(analyzePropertyChildren))\n            {\n                if (EditorGUI.GetPropertyHeight(property, null, true) > 0)\n                {\n                    return true;\n                }\n                analyzePropertyChildren = false;\n            }\n\n            return false;\n        }\n\n        static internal bool IsAppropriateFileOpenForEdit(UnityObject assetObject)\n        {\n            // The native object for a ScriptableObject with an invalid script will be considered not alive.\n            // In order to allow editing of the m_Script property of a ScriptableObject with an invalid script\n            // we use the instance ID instead of the UnityEngine.Object reference to check if the asset is open for edit.\n\n            if ((object)assetObject == null)\n                return false;\n\n            var instanceID = assetObject.GetInstanceID();\n            if (instanceID == 0)\n                return false;\n\n            StatusQueryOptions opts = EditorUserSettings.allowAsyncStatusUpdate ? StatusQueryOptions.UseCachedAsync : StatusQueryOptions.UseCachedIfPossible;\n            if (AssetDatabase.IsNativeAsset(instanceID))\n            {\n                var assetPath = AssetDatabase.GetAssetPath(instanceID);\n                if (!AssetDatabase.IsOpenForEdit(assetPath, opts))\n                    return false;\n            }\n            else if (AssetDatabase.IsForeignAsset(instanceID))\n            {\n                if (!AssetDatabase.IsMetaFileOpenForEdit(assetObject, opts))\n                    return false;\n            }\n\n            return true;\n        }\n\n        internal virtual bool IsEnabled()\n        {\n            // disable editor if any objects in the editor are not editable\n            foreach (UnityObject target in targets)\n            {\n                if (target == null)\n                    return false;\n                if ((target.hideFlags & HideFlags.NotEditable) != 0)\n                    return false;\n\n                if (EditorUtility.IsPersistent(target) && !IsAppropriateFileOpenForEdit(target))\n                    return false;\n            }\n\n            return true;\n        }\n\n        internal bool IsOpenForEdit()\n        {\n            foreach (UnityObject target in targets)\n            {\n                if (EditorUtility.IsPersistent(target) && !IsAppropriateFileOpenForEdit(target))\n                    return false;\n            }\n\n            return true;\n        }\n\n        public virtual bool UseDefaultMargins()\n        {\n            return true;\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public void Initialize(UnityObject[] targets)\n        {\n            throw new InvalidOperationException(\"You shouldn't call Initialize for Editors\");\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public void Cleanup()\n        {\n            throw new InvalidOperationException(\"You shouldn't call Cleanup for Editors. Dispose resources in \" +\n                \"Editor.OnDisable\");\n        }\n\n        public bool MoveNextTarget()\n        {\n            referenceTargetIndex++;\n            return referenceTargetIndex < targets.Length;\n        }\n\n        public void ResetTarget()\n        {\n            referenceTargetIndex = 0;\n        }\n\n        // Implement this method to show a limited inspector for showing tweakable parameters in an Asset Store preview.\n        internal virtual void OnAssetStoreInspectorGUI()\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/EditorDragging.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class EditorDragging\n    {\n        const string k_DraggingModeKey = \"InspectorEditorDraggingMode\";\n\n        IPropertyView m_InspectorWindow;\n        bool m_TargetAbove;\n        int m_TargetIndex = -1;\n        int m_LastIndex = -1;\n\n        enum DraggingMode\n        {\n            NotApplicable,\n            Component,\n            Script,\n        }\n\n        static class Styles\n        {\n            public static readonly GUIStyle insertionMarker = \"InsertionMarker\";\n        }\n\n        public EditorDragging(IPropertyView inspectorWindow)\n        {\n            m_InspectorWindow = inspectorWindow;\n        }\n\n        public void HandleDraggingToEditor(Editor[] editors, int editorIndex, Rect dragRect, Rect contentRect)\n        {\n            if (dragRect.height == 0f)\n                return;\n\n            if (contentRect.height == 0f)\n                contentRect = dragRect;\n\n            var targetRect = GetTargetRect(contentRect);\n\n            var markerY = contentRect.yMax;\n\n            m_LastIndex = editorIndex;\n\n            HandleEditorDragging(editors, editorIndex, targetRect, markerY, false);\n        }\n\n        int m_BottomAreaDropIndex = -1;\n        Rect m_BottomArea;\n\n        public void HandleDraggingInBottomArea(Editor[] editors, Rect bottomRect, Rect contentRect)\n        {\n            HandleNativeDragDropInBottomArea(editors, bottomRect);\n\n            if (m_LastIndex >= 0 && m_LastIndex < editors.Length)\n            {\n                m_BottomArea = bottomRect;\n                m_BottomAreaDropIndex = m_LastIndex;\n                HandleEditorDragging(editors, m_LastIndex, bottomRect, contentRect.yMax, true);\n            }\n            else\n            {\n                m_BottomAreaDropIndex = -1;\n                m_BottomArea = Rect.zero;\n            }\n        }\n\n        internal void HandleDragPerformInBottomArea(Editor[] editors, Rect bottomRect, Rect targetRect)\n        {\n            HandleNativeDragDropInBottomArea(editors, bottomRect);\n\n            if (m_LastIndex >= 0 && m_LastIndex  < editors.Length)\n            {\n                HandleEditorDragging(editors, m_LastIndex, GetTargetRect(targetRect), targetRect.yMax, true);\n            }\n\n            m_BottomAreaDropIndex = -1;\n            m_BottomArea = Rect.zero;\n        }\n\n        void HandleNativeDragDropInBottomArea(Editor[] editors, Rect rect)\n        {\n            if (!DraggingOverRect(rect))\n            {\n                return;\n            }\n\n            Editor editor = InspectorWindowUtils.GetFirstNonImportInspectorEditor(editors);\n            if (editor == null)\n            {\n                return;\n            }\n\n            DragAndDrop.visualMode = DragAndDrop.DropOnInspectorWindow(editor.targets, Event.current.type == EventType.DragPerform);\n\n            if (Event.current.type == EventType.DragPerform)\n            {\n                // Determine if any object references are component, which would mean we are reordering components in the inspector\n                var anyComponent = DragAndDrop.objectReferences != null && DragAndDrop.objectReferences.Any(o => o is Component);\n\n                // None of the object references are component, cancel further processing to avoid adding component twice\n                if (!anyComponent)\n                {\n                    DragAndDrop.AcceptDrag();\n                    m_TargetIndex = -1;\n                    GUIUtility.ExitGUI();\n                }\n            }\n        }\n\n        void HandleEditorDragging(Editor[] editors, int editorIndex, Rect targetRect, float markerY, bool bottomTarget)\n        {\n            var evt = Event.current;\n\n            switch (evt.type)\n            {\n                case EventType.DragUpdated:\n                    if (targetRect.Contains(evt.mousePosition))\n                    {\n                        var draggingMode = DragAndDrop.GetGenericData(k_DraggingModeKey) as DraggingMode ? ;\n                        if (!draggingMode.HasValue)\n                        {\n                            var draggedObjects = DragAndDrop.objectReferences;\n\n                            if (draggedObjects.Length == 0)\n                                draggingMode = DraggingMode.NotApplicable;\n                            else if (draggedObjects.All(o => o is Component && !(o is Transform)))\n                                draggingMode = DraggingMode.Component;\n                            else if (draggedObjects.All(o => o is MonoScript))\n                                draggingMode = DraggingMode.Script;\n                            else\n                                draggingMode = DraggingMode.NotApplicable;\n\n                            DragAndDrop.SetGenericData(k_DraggingModeKey, draggingMode);\n                        }\n\n\n                        if (draggingMode.Value != DraggingMode.NotApplicable)\n                        {\n                            if (bottomTarget)\n                            {\n                                m_TargetAbove = false;\n                                m_TargetIndex = m_LastIndex;\n                            }\n                            else\n                            {\n                                m_TargetAbove = evt.mousePosition.y < targetRect.y + targetRect.height / 2f;\n                                m_TargetIndex = editorIndex;\n\n                                if (m_TargetAbove)\n                                {\n                                    m_TargetIndex++;\n                                    while (m_TargetIndex < editors.Length && m_InspectorWindow.ShouldCullEditor(editors, m_TargetIndex))\n                                        m_TargetIndex++;\n\n                                    if (m_TargetIndex == editors.Length)\n                                    {\n                                        m_TargetIndex = -1;\n                                        return;\n                                    }\n                                }\n                            }\n\n                            if (m_TargetAbove && InspectorWindow.EditorHasLargeHeader(m_TargetIndex, editors))\n                            {\n                                m_TargetIndex--;\n                                while (m_TargetIndex >= 0 && m_InspectorWindow.ShouldCullEditor(editors, m_TargetIndex))\n                                    m_TargetIndex--;\n\n                                if (m_TargetIndex == -1)\n                                    return;\n\n                                m_TargetAbove = false;\n                            }\n\n                            if (draggingMode.Value == DraggingMode.Script)\n                            {\n                                // Validate dragging scripts\n                                // Always allow script dragging, instead fail during DragPerform with a dialog box\n                                DragAndDrop.visualMode = DragAndDropVisualMode.Link;\n                            }\n                            else\n                            {\n                                // Validate dragging components\n                                var valid = false;\n                                if (editors[m_TargetIndex].targets.All(t => t is Component))\n                                {\n                                    var targetComponents = editors[m_TargetIndex].targets.Cast<Component>().ToArray();\n                                    var sourceComponents = DragAndDrop.objectReferences.Cast<Component>().ToArray();\n                                    valid = MoveOrCopyComponents(sourceComponents, targetComponents, EditorUtility.EventHasDragCopyModifierPressed(evt), true);\n                                }\n\n                                if (valid)\n                                    DragAndDrop.visualMode = EditorUtility.EventHasDragCopyModifierPressed(evt) ? DragAndDropVisualMode.Copy : DragAndDropVisualMode.Move;\n                                else\n                                {\n                                    DragAndDrop.visualMode = DragAndDropVisualMode.None;\n                                    m_TargetIndex = -1;\n                                    return;\n                                }\n                            }\n\n                            evt.Use();\n                        }\n                    }\n                    else\n                        m_TargetIndex = -1;\n\n                    break;\n\n                case EventType.DragPerform:\n                    // Linux does not make a DragExited call after a drag, and needs to have its visual mode move to None. All platforms reset their visualmode back to None after a drag.\n                    DragAndDrop.visualMode = DragAndDropVisualMode.None;\n                    if (m_TargetIndex != -1)\n                    {\n                        HandleDragPerformEvent(editors, evt, ref m_TargetIndex);\n                    }\n                    break;\n\n                case EventType.DragExited:\n                    m_TargetIndex = -1;\n                    break;\n\n                case EventType.Repaint:\n                    if (DragAndDrop.visualMode != DragAndDropVisualMode.None && DragAndDrop.visualMode != DragAndDropVisualMode.Rejected &&\n                        (targetRect.Contains(evt.mousePosition) ||\n                         editorIndex == m_BottomAreaDropIndex &&\n                         m_BottomArea.Contains(GUIClip.UnclipToWindow(evt.mousePosition)) &&\n                         m_BottomAreaDropIndex == editors.Length - 1))\n                    {\n                        Styles.insertionMarker.Draw(GetMarkerRect(targetRect), false, false, false, false);\n                    }\n                    break;\n            }\n        }\n\n        static bool DraggingOverRect(Rect rect)\n        {\n            return (Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform) && rect.Contains(Event.current.mousePosition);\n        }\n\n        void HandleDragPerformEvent(Editor[] editors, Event evt, ref int targetIndex)\n        {\n            if (targetIndex != -1)\n            {\n                var draggingMode = DragAndDrop.GetGenericData(k_DraggingModeKey) as DraggingMode ? ;\n                if (!draggingMode.HasValue || draggingMode.Value == DraggingMode.NotApplicable)\n                {\n                    targetIndex = -1;\n                    return;\n                }\n\n                if (!editors[targetIndex].targets.All(t => t is Component))\n                    return;\n\n                var targetComponents = editors[targetIndex].targets.Cast<Component>().ToArray();\n\n                if (draggingMode.Value == DraggingMode.Script)\n                {\n                    var scripts = DragAndDrop.objectReferences.Cast<MonoScript>();\n\n                    // Ensure all script components can be added\n                    var valid = true;\n                    foreach (var targetComponent in targetComponents)\n                    {\n                        var gameObject = targetComponent.gameObject;\n                        if (scripts.Any(s => !ComponentUtility.WarnCanAddScriptComponent(gameObject, s)))\n                        {\n                            valid = false;\n                            break;\n                        }\n                    }\n\n                    if (valid)\n                    {\n                        Undo.IncrementCurrentGroup();\n                        var undoGroup = Undo.GetCurrentGroup();\n\n                        // Add script components\n                        var index = 0;\n                        var addedComponents = new Component[targetComponents.Length * scripts.Count()];\n                        for (int i = 0; i < targetComponents.Length; i++)\n                        {\n                            var targetComponent = targetComponents[i];\n                            var gameObject = targetComponent.gameObject;\n                            bool targetIsTransform = targetComponent is Transform;\n                            foreach (var script in scripts)\n                                addedComponents[index++] = ObjectFactory.AddComponent(gameObject, script.GetClass());\n\n                            // If the target is a Transform, the AddComponent might have replaced it with a RectTransform.\n                            // Handle this possibility by updating the target component.\n                            if (targetIsTransform)\n                                targetComponents[i] = gameObject.transform;\n                        }\n\n                        // Move added components relative to target components\n                        if (!ComponentUtility.MoveComponentsRelativeToComponents(addedComponents, targetComponents, m_TargetAbove))\n                        {\n                            // Ensure we have the same selection after calling RevertAllDownToGroup below (MoveComponentsRelativeToComponents can have opened a Prefab in Prefab Mode and changed selection to that root)\n                            var wantedSelectedGameObject = Selection.activeGameObject;\n\n                            // Revert added components if move operation fails (e.g. user has been shown the dialog with 'prefab instance restructuring is not posssible' or object is not editable)\n                            Undo.RevertAllDownToGroup(undoGroup);\n\n                            if (wantedSelectedGameObject != Selection.activeGameObject)\n                                Selection.activeGameObject = wantedSelectedGameObject;\n                        }\n                    }\n                }\n                else\n                {\n                    // Handle dragging components\n                    var sourceComponents = DragAndDrop.objectReferences.Cast<Component>().ToArray();\n                    if (sourceComponents.Length == 0 || targetComponents.Length == 0)\n                        return;\n\n                    MoveOrCopyComponents(sourceComponents, targetComponents, EditorUtility.EventHasDragCopyModifierPressed(evt), false);\n                }\n\n                targetIndex = -1;\n                DragAndDrop.AcceptDrag();\n                evt.Use();\n                EditorGUIUtility.ExitGUI();\n            }\n        }\n\n        private Rect GetTargetRect(Rect contentRect)\n        {\n            var targetHeight = 9f;\n            var yPos = contentRect.yMax - targetHeight * .75f;\n            var uiDragTargetHeight = targetHeight * .75f;\n            return new Rect(contentRect.x, yPos + uiDragTargetHeight / (targetHeight * .25f), contentRect.width, uiDragTargetHeight);\n        }\n\n        private static Rect GetMarkerRect(Rect targetRect)\n        {\n            var markerRect = targetRect;\n            markerRect.y += 3;\n            return markerRect;\n        }\n\n        bool MoveOrCopyComponents(Component[] sourceComponents, Component[] targetComponents, bool copy, bool validateOnly)\n        {\n            // This version only allows reordering of components\n\n            if (copy)\n                return false;\n\n            if (sourceComponents.Length == 1 && targetComponents.Length == 1)\n            {\n                if (sourceComponents[0].gameObject != targetComponents[0].gameObject)\n                    return false;\n\n                return ComponentUtility.MoveComponentRelativeToComponent(sourceComponents[0], targetComponents[0], m_TargetAbove, validateOnly);\n            }\n            else\n                return ComponentUtility.MoveComponentsRelativeToComponents(sourceComponents, targetComponents, m_TargetAbove, validateOnly);\n        }\n\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/EditorElementUpdater.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing UnityEditorInternal;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    /// <summary>\n    /// The <see cref=\"EditorElementUpdater\"/> handles calling <see cref=\"IEditorElement.CreateInspectorElement\"/> in a time-sliced manner.\n    /// </summary>\n    class EditorElementUpdater\n    {\n        readonly PropertyEditor m_PropertyEditor;\n        readonly List<IEditorElement> m_EditorElements = new List<IEditorElement>();\n        readonly Stopwatch m_UpdateTickTimer = new Stopwatch();\n\n        Panel Panel => m_PropertyEditor.rootVisualElement.panel as Panel;\n\n        int m_Index;\n\n        public int Position => m_Index;\n        public int Count => m_EditorElements.Count;\n\n        public EditorElementUpdater(PropertyEditor propertyEditor)\n        {\n            m_PropertyEditor = propertyEditor;\n            m_Index = 0;\n        }\n\n        /// <summary>\n        /// Adds the specified <see cref=\"IEditorElement\"/> to the updater.\n        /// </summary>\n        /// <param name=\"element\">The editor element to add.</param>\n        public void Add(IEditorElement element)\n        {\n            m_EditorElements.Add(element);\n        }\n\n        /// <summary>\n        /// Removes the specified <see cref=\"IEditorElement\"/> from the updater.\n        /// </summary>\n        /// <param name=\"element\">The editor element to remove.</param>\n        public void Remove(IEditorElement element)\n        {\n            var index = m_EditorElements.IndexOf(element);\n\n            if (index == -1)\n                return;\n\n            if (m_Index > index)\n                m_Index--;\n        }\n\n        /// <summary>\n        /// Clears the internal state and resets the enumerator.\n        /// </summary>\n        public void Clear()\n        {\n            m_EditorElements.Clear();\n            m_Index = 0;\n        }\n\n        /// <summary>\n        /// Invokes <see cref=\"IEditorElement.CreateInspectorElement\"/> until the first <paramref name=\"count\"/> elements are created.\n        /// </summary>\n        /// <param name=\"count\">The number of elements to create.</param>\n        public void CreateMinimumInspectorElementsWithoutLayout(int count)\n        {\n            for (; m_Index < count && m_Index < m_EditorElements.Count; m_Index++)\n                m_EditorElements[m_Index].CreateInspectorElement();\n        }\n\n        /// <summary>\n        /// Invokes <see cref=\"IEditorElement.CreateInspectorElement\"/> for the specified number of elements.\n        /// </summary>\n        /// <param name=\"count\">The number of elements to create.</param>\n        public void CreateInspectorElementsWithoutLayout(int count)\n        {\n            for (var i = 0; m_Index < m_EditorElements.Count && i < count; i++)\n                m_EditorElements[m_Index++].CreateInspectorElement();\n        }\n\n        /// <summary>\n        /// Invokes <see cref=\"IEditorElement.CreateInspectorElement\"/> followed by a layout until the given <paramref name=\"viewport\"/> is filled.\n        /// </summary>\n        /// <param name=\"viewport\">The viewport to build elements for.</param>\n        /// <param name=\"contentContainer\"></param>\n        public void CreateInspectorElementsForViewport(ScrollView viewport, VisualElement contentContainer)\n        {\n            if (m_Index >= m_EditorElements.Count)\n                return;\n\n            var scroll = viewport.verticalScroller.value;\n\n            while (m_Index < m_EditorElements.Count)\n            {\n                var element = m_EditorElements[m_Index++];\n\n                element.CreateInspectorElement();\n\n                // If this element contributes to the layout, re-compute it immediately to determine how much of the viewport is occupied.\n                if (null != element.editor && InternalEditorUtility.GetIsInspectorExpanded(element.editor.target)&& contentContainer.childCount>0)\n                {\n                    Panel?.UpdateWithoutRepaint();\n\n                    if (contentContainer.ElementAt(contentContainer.childCount - 1).layout.yMax - scroll > viewport.layout.height)\n                        break;\n                }\n            }\n\n            viewport.verticalScroller.value = scroll;\n        }\n\n        /// <summary>\n        /// Invokes <see cref=\"IEditorElement.CreateInspectorElement\"/> followed by a layout until the target <see cref=\"targetMilliseconds\"/> has been reached.\n        /// </summary>\n        /// <remarks>\n        /// The time value includes creation of the GUI, styling and layout. This does NOT include render time.\n        /// </remarks>\n        /// <param name=\"targetMilliseconds\">The target number of milliseconds to spend on the update.</param>\n        public void CreateInspectorElementsForMilliseconds(long targetMilliseconds)\n        {\n            if (m_Index >= m_EditorElements.Count)\n                return;\n\n            m_UpdateTickTimer.Restart();\n\n            while (m_UpdateTickTimer.ElapsedMilliseconds < targetMilliseconds)\n            {\n                var element = m_EditorElements[m_Index++];\n\n                element.CreateInspectorElement();\n\n                // If this was the last element. We can early out and let the standard update loop tick the layout and repaint.\n                if (m_Index >= m_EditorElements.Count)\n                    break;\n\n                // If this element contributes to the layout, re-compute it immediately to determine how much of the viewport is occupied.\n                if (null != element.editor && InternalEditorUtility.GetIsInspectorExpanded(element.editor.target))\n                    Panel?.UpdateWithoutRepaint();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/EditorSettingsInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEditor.Hardware;\nusing UnityEngine.Rendering;\nusing UnityEngine.Assertions;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(EditorSettings))]\n    internal class EditorSettingsInspector : ProjectSettingsBaseEditor\n    {\n        class Content\n        {\n            public static GUIContent unityRemote = EditorGUIUtility.TrTextContent(\"Unity Remote\");\n            public static GUIContent device = EditorGUIUtility.TrTextContent(\"Device\");\n            public static GUIContent compression = EditorGUIUtility.TrTextContent(\"Compression\");\n            public static GUIContent resolution = EditorGUIUtility.TrTextContent(\"Resolution\");\n            public static GUIContent joystickSource = EditorGUIUtility.TrTextContent(\"Joystick Source\");\n\n            public static GUIContent mode = EditorGUIUtility.TrTextContent(\"Mode\");\n            public static GUIContent parallelImport = EditorGUIUtility.TrTextContent(\"Parallel Import\", \"During an asset database refresh some asset imports can be performed in parallel in sub processes.\");\n            public static GUIContent parallelImportLearnMore = EditorGUIUtility.TrTextContent(\"Learn more...\", \"During an asset database refresh some asset imports can be performed in parallel in sub processes.\");\n            public static GUIContent desiredImportWorkerCountOverride = EditorGUIUtility.TrTextContent(\"Override Desired Worker Count\", \"Override the desired worker count specified in the preferences.\");\n            public static GUIContent desiredImportWorkerCount = EditorGUIUtility.TrTextContent(\"Desired Import Worker Count\", \"The desired number of import worker processes to use for importing. The actual number of worker processes on the system can be both lower or higher that this, but the system will seek towards this number when importing.\");\n            public static GUIContent standbyImportWorkerCount = EditorGUIUtility.TrTextContent(\"Standby Import Worker Count\", \"The number of import worker processes to keep around in standby and ready for importing. The actual number of worker processes on the system can be both lower or higher that this, but the system will seek towards this number when worker processes are idle.\");\n            public static GUIContent idleWorkerShutdownDelay = EditorGUIUtility.TrTextContent(\"Idle Import Worker Shutdown Delay\", \"When an importer worker has been idle for this amount of seconds in will be shutdown unless it would take the worker count below the standby worker count setting.\");\n\n            public static GUIContent cacheServer = EditorGUIUtility.TrTextContent(\"Cache Server (project specific)\");\n            public static GUIContent assetPipeline = EditorGUIUtility.TrTextContent(\"Asset Pipeline\");\n            public static GUIContent artifactGarbageCollection = EditorGUIUtility.TrTextContent(\"Remove unused Artifacts on Restart\", \"By default, when you start the Editor, Unity removes unused artifact files in the Library folder, and removes their entries in the asset database. This is a form of \\\"garbage collection\\\". This setting allows you to turn off the asset database garbage collection, so that previous artifact revisions which are no longer used are still preserved after restarting the Editor. This is useful if you need to debug unexpected import results.\");\n            public static GUIContent cacheServerIPLabel = EditorGUIUtility.TrTextContent(\"IP address\");\n            public static GUIContent cacheServerNamespacePrefixLabel = EditorGUIUtility.TrTextContent(\"Namespace prefix\", \"The namespace used for looking up and storing values on the cache server\");\n            public static GUIContent cacheServerEnableDownloadLabel = EditorGUIUtility.TrTextContent(\"Download\", \"Enables downloads from the cache server.\");\n            public static GUIContent cacheServerEnableUploadLabel = EditorGUIUtility.TrTextContent(\"Upload\", \"Enables uploads to the cache server.\");\n            public static GUIContent cacheServerEnableTlsLabel = EditorGUIUtility.TrTextContent(\"TLS/SSL\", \"Enabled encryption on the cache server connection.\");\n            public static GUIContent cacheServerEnableAuthLabel = EditorGUIUtility.TrTextContent(\"Authentication (using Unity ID)\", \"Enable authentication for cache server using Unity ID. Also forces TLS/SSL encryption.\");\n            public static GUIContent cacheServerAuthUserLabel = EditorGUIUtility.TrTextContent(\"User\");\n            public static GUIContent cacheServerAuthPasswordLabel = EditorGUIUtility.TrTextContent(\"Password\");\n            public static GUIContent cacheServerValidationLabel = EditorGUIUtility.TrTextContent(\"Content Validation\");\n            public static GUIContent cacheServerDownloadBatchSizeLabel = EditorGUIUtility.TrTextContent(\"Download Batch Size\");\n            public static readonly GUIContent cacheServerLearnMore = new GUIContent(\"Learn more...\", \"Go to cacheserver documentation.\");\n\n            public static GUIContent assetSerialization = EditorGUIUtility.TrTextContent(\"Asset Serialization\");\n            public static GUIContent textSerializeMappingsOnOneLine = EditorGUIUtility.TrTextContent(\"Reduce version control noise\", \"Forces Unity to write references and similar YAML structures on one line, which reduces version control noise.\");\n            public static GUIContent defaultBehaviorMode = EditorGUIUtility.TrTextContent(\"Default Behaviour Mode\");\n\n            public static GUIContent buildPipelineHeader = EditorGUIUtility.TrTextContent(\"Build Pipeline\");\n            public static GUIContent ucbpEnableAssetBundles = EditorGUIUtility.TrTextContent(\"Multi-Process AssetBundle Building\", \"Enable experimental improvements to the AssetBundle Build Pipeline aimed at reducing build times with multi-process importing and providing more efficient incremental content building\");\n            public static readonly GUIContent ucbpLearnMore = new GUIContent(\"Learn more...\", \"Review official Unity documentation for important considerations around these experimental improvements.\");\n\n            public static GUIContent sceneHandlingHeader = EditorGUIUtility.TrTextContent(\"Scene Handling\");\n            public static GUIContent forceAssetUnloadAndGCOnSceneLoad = EditorGUIUtility.TrTextContent(\"Force Asset Unload & GC on Scene Load\", \"Force a managed heap garbage collection and unload unused assets after loading scenes in single mode in the Editor or exiting Prefab Mode. In complex projects, this can slow down performance. Disable this if you do not require class finalizers to run at the end of scene loading. Note that regular dynamic GC and unused asset unloading still occur when memory usage is high, but without this option, class finalizers might not run immediately after each scene load.\");\n\n            public static GUIContent graphics = EditorGUIUtility.TrTextContent(\"Graphics\");\n            public static GUIContent showLightmapResolutionOverlay = EditorGUIUtility.TrTextContent(\"Show Lightmap Resolution Overlay\");\n            public static GUIContent useLegacyProbeSampleCount = EditorGUIUtility.TrTextContent(\"Use legacy Light Probe sample counts\", \"Uses fixed Light Probe sample counts for baking with the Progressive Lightmapper. The sample counts are: 64 direct samples, 2048 indirect samples and 2048 environment samples.\");\n\n            public static GUIContent spritePacker = EditorGUIUtility.TrTextContent(\"Sprite Atlas\");\n            public static readonly GUIContent spriteMaxCacheSize = EditorGUIUtility.TrTextContent(\"Max SpriteAtlas Cache Size (GB)\", \"The size of the Sprite Atlas Cache folder will be kept below this maximum value when possible. Change requires Editor restart.\");\n\n            public static GUIContent cSharpProjectGeneration = EditorGUIUtility.TrTextContent(\"C# Project Generation\");\n            public static GUIContent additionalExtensionsToInclude = EditorGUIUtility.TrTextContent(\"Additional extensions to include\");\n            public static GUIContent rootNamespace = EditorGUIUtility.TrTextContent(\"Root namespace\");\n\n            public static GUIContent textureCompressors = EditorGUIUtility.TrTextContent(\"Texture Compressors\");\n            public static GUIContent bc7Compressor = EditorGUIUtility.TrTextContent(\"BC7 Compressor\", \"Compressor to use for BC7 format texture compression\");\n            public static GUIContent etcCompressor = EditorGUIUtility.TrTextContent(\"ETC Compressor\", \"Compressors to use for ETC/ETC2/EAC format texture compression\");\n            public static GUIContent fast = EditorGUIUtility.TrTextContent(\"Fast\");\n            public static GUIContent normal = EditorGUIUtility.TrTextContent(\"Normal\");\n            public static GUIContent best = EditorGUIUtility.TrTextContent(\"Best\");\n            public static GUIContent legacyDeprecationWarning = EditorGUIUtility.TrTextContent(\"ETC Legacy compression has been deprecated and will be removed in a future release.\\n\\n\" +\n                \"Legacy compression results are best matched by choosing \\\"Custom\\\", then choosing \\\"ETCPACK Fast\\\", \\\"ETCPACK Fast\\\" and \\\"ETCPACK Best\\\" for Fast, Normal, and Best, respectively. ETC Textures will be reimported and recompressed during the next AssetDatabase refresh.\");\n\n            public static GUIContent lineEndingForNewScripts = EditorGUIUtility.TrTextContent(\"Line Endings For New Scripts\");\n\n            public static GUIContent streamingSettings = EditorGUIUtility.TrTextContent(\"Texture Streaming Settings\");\n            public static GUIContent enablePlayModeTextureStreaming = EditorGUIUtility.TrTextContent(\"Enable Mipmap Streaming In Play Mode\", \"Texture Mipmap Streaming must be enabled in Quality Settings for mipmap streaming to function in Play Mode. This reduces GPU memory by streaming mips in and out as needed.\");\n            public static GUIContent enableEditModeTextureStreaming = EditorGUIUtility.TrTextContent(\"Enable Mipmap Streaming In Edit Mode\", \"Texture Mipmap Streaming must be enabled in Quality Settings for mipmap streaming to function in Edit Mode. This reduces GPU memory by streaming mips in and out as needed.\");\n            public static GUIContent enableEditorAsyncCPUTextureLoading = EditorGUIUtility.TrTextContent(\"Load texture data on demand\", \"While in Editor, load CPU side texture data for streaming textures from disk asynchronously on demand (will avoid some stalls and reduce CPU memory usage). Change requires Editor restart.\");\n\n            public static GUIContent shaderCompilation = EditorGUIUtility.TrTextContent(\"Shader Compilation\");\n            public static GUIContent asyncShaderCompilation = EditorGUIUtility.TrTextContent(\"Asynchronous Shader Compilation\", \"Enables async shader compilation in Game and Scene view. Async compilation for custom editor tools can be achieved via script API and is not affected by this option.\");\n\n            public static GUIContent prefabMode = EditorGUIUtility.TrTextContent(\"Prefab Mode\");\n            public static GUIContent prefabModeAllowAutoSave = EditorGUIUtility.TrTextContent(\"Allow Auto Save\", \"When enabled, an Auto Save toggle is displayed in Prefab Mode which you can turn on or off. This is the default. When disabled, there is no Auto Save in Prefab Mode in this project and the toggle is not displayed.\");\n            public static GUIContent prefabModeEditingEnvironments = EditorGUIUtility.TrTextContent(\"Editing Environments\");\n            public static GUIContent prefabModeRegularEnvironment = EditorGUIUtility.TrTextContent(\"Regular Environment\");\n            public static GUIContent prefabModeUIEnvironment = EditorGUIUtility.TrTextContent(\"UI Environment\");\n\n            public static readonly GUIContent enterPlayModeSettings = EditorGUIUtility.TrTextContent(\"Enter Play Mode Settings\");\n            public static readonly GUIContent enterPlayModeOptions = EditorGUIUtility.TrTextContent(\"When entering Play Mode\", \"Reload options when entering Play Mode.\");\n            public static readonly GUIContent[] enterPlayModeOptionNames =\n            {\n                EditorGUIUtility.TrTextContent(\"Reload Domain and Scene\"), // Default\n                EditorGUIUtility.TrTextContent(\"Reload Scene only\"),\n                EditorGUIUtility.TrTextContent(\"Reload Domain only\"),\n                EditorGUIUtility.TrTextContent(\"Do not reload Domain or Scene\")\n            };\n            public static readonly int[] enterPlayModeOptionValues =\n            {\n                (int)EnterPlayModeOptions.None, // Default\n                (int)EnterPlayModeOptions.DisableDomainReload,\n                (int)EnterPlayModeOptions.DisableSceneReload,\n                (int)(EnterPlayModeOptions.DisableDomainReload | EnterPlayModeOptions.DisableSceneReload)\n            };\n\n            public static readonly GUIContent numberingScheme = EditorGUIUtility.TrTextContent(\"Numbering Scheme\");\n\n            public static readonly GUIContent inspectorSettings = EditorGUIUtility.TrTextContent(\"Inspector\");\n            public static readonly GUIContent inspectorUseIMGUIDefaultInspector = EditorGUIUtility.TrTextContent(\"Use IMGUI Default Inspector\", \"Revert to using IMGUI to generate Default Inspectors where no custom Inspector/Editor was defined.\");\n\n            public static readonly GUIContent[] numberingSchemeNames =\n            {\n                EditorGUIUtility.TrTextContent(\"Prefab (1)\", \"Number in parentheses\"),\n                EditorGUIUtility.TrTextContent(\"Prefab.1\", \"Number after dot\"),\n                EditorGUIUtility.TrTextContent(\"Prefab_1\", \"Number after underscore\")\n            };\n            public static readonly int[] numberingSchemeValues =\n            {\n                (int)EditorSettings.NamingScheme.SpaceParenthesis,\n                (int)EditorSettings.NamingScheme.Dot,\n                (int)EditorSettings.NamingScheme.Underscore\n            };\n            public static readonly GUIContent numberingHierarchyScheme = EditorGUIUtility.TrTextContent(\"Game Object Naming\");\n            public static readonly GUIContent numberingHierarchyDigits = EditorGUIUtility.TrTextContent(\"Game Object Digits\");\n            public static readonly GUIContent numberingProjectSpace = EditorGUIUtility.TrTextContent(\"Space Before Number in Asset Names\");\n\n            public static GUIContent referencedClipsExactNaming = EditorGUIUtility.TrTextContent(\"Exactly Match Referenced Clip Names\", \"Controls how referenced clips are matched with models that are animated in Legacy mode. If turned on, the model name and the referenced clip names must exactly match. If turned off, only the start of the model name needs to match the referenced clip name. Also controls the behavior of the \\\"Update referenced clips\\\" button for models that are animated in Humanoid mode. See the documentation for EditorSettings.referencedClipsExactNaming for more details.\");\n        }\n\n        internal struct PopupElement\n        {\n            public readonly string id;\n            public readonly GUIContent content;\n\n            public PopupElement(string content)\n            {\n                this.id = content;\n                this.content = new GUIContent(content);\n            }\n\n            public PopupElement(string id, string content)\n            {\n                this.id = id;\n                this.content = new GUIContent(content);\n            }\n        }\n\n        private PopupElement[] serializationPopupList =\n        {\n            new PopupElement(\"Mixed\"),\n            new PopupElement(\"Force Binary\"),\n            new PopupElement(\"Force Text\"),\n        };\n\n        private PopupElement[] behaviorPopupList =\n        {\n            new PopupElement(\"3D\"),\n            new PopupElement(\"2D\"),\n        };\n\n        private PopupElement[] spritePackerPopupList =\n        {\n            new PopupElement(\"Disabled\"),\n            new PopupElement(\"Sprite Atlas V1 - Enabled For Builds\"),\n            new PopupElement(\"Sprite Atlas V1 - Always Enabled\"),\n            new PopupElement(\"Sprite Atlas V2 - Enabled\"),\n            new PopupElement(\"Sprite Atlas V2 - Enabled for Builds\"),\n        };\n        private static readonly int spritePackDeprecatedEnums = 2;\n\n        private PopupElement[] lineEndingsPopupList =\n        {\n            new PopupElement(\"OS Native\"),\n            new PopupElement(\"Unix\"),\n            new PopupElement(\"Windows\"),\n        };\n\n        private PopupElement[] remoteDevicePopupList;\n        private DevDevice[]    remoteDeviceList;\n        private PopupElement[] remoteCompressionList =\n        {\n            new PopupElement(\"JPEG\"),\n            new PopupElement(\"PNG\"),\n        };\n        private PopupElement[] remoteResolutionList =\n        {\n            new PopupElement(\"Downsize\"),\n            new PopupElement(\"Normal\"),\n        };\n        private PopupElement[] remoteJoystickSourceList =\n        {\n            new PopupElement(\"Remote\"),\n            new PopupElement(\"Local\"),\n        };\n\n        private PopupElement[] cacheServerModePopupList =\n        {\n            new PopupElement(\"Use global settings (stored in preferences)\"),\n            new PopupElement(\"Enabled\"),\n            new PopupElement(\"Disabled\"),\n        };\n\n        private PopupElement[] refreshImportModePopupList =\n        {\n            new PopupElement(\"In process\"),\n            new PopupElement(\"Out of process by queue\"),\n        };\n\n        private PopupElement[] cacheServerAuthMode =\n        {\n            new PopupElement(\"Basic\")\n        };\n\n        private GUIContent[] cacheServerValidationPopupList =\n        {\n            EditorGUIUtility.TrTextContent(\"Disabled\", \"Content hashes are not calculated for uploaded artifacts and are not validated for downloaded artifacts.\"),\n            EditorGUIUtility.TrTextContent(\"Upload Only\", \"Content hashes are calculated for uploaded artifacts and sent to the Accelerator. Content hashes are not validated for downloaded artifacts.\" ),\n            EditorGUIUtility.TrTextContent(\"Enabled\", \"Content hashes are calculated for uploaded artifacts and sent to the Accelerator. Content hashes, if provided by the Accelerator, are validated for downloaded artifacts.\"),\n            EditorGUIUtility.TrTextContent(\"Required\", \"Content hashes are calculated for uploaded artifacts and sent to the Accelerator. Content hashes are required and validated for downloaded artifacts.\"),\n        };\n\n        private GUIContent[] bc7TextureCompressorOptions =\n        {\n            EditorGUIUtility.TrTextContent(\"Default\", \"Use default BC7 compressor (currently bc7e)\"),\n            EditorGUIUtility.TrTextContent(\"ISPC (legacy)\", \"Use Intel ISPCTextureCompressor (legacy pre-2021.2 behavior)\"),\n            EditorGUIUtility.TrTextContent(\"bc7e\", \"Use Binomial bc7e compressor\"),\n        };\n\n        private PopupElement[] etcTextureCompressorPopupList =\n        {\n            new PopupElement(\"Legacy\"),\n            new PopupElement(\"Default\"),\n            new PopupElement(\"Custom\"),\n        };\n\n        private PopupElement[] etcTextureFastCompressorPopupList =\n        {\n            new PopupElement(\"etcpak\"),\n            new PopupElement(\"ETCPACK Fast\"),\n        };\n\n        private PopupElement[] etcTextureNormalCompressorPopupList =\n        {\n            new PopupElement(\"etcpak\"),\n            new PopupElement(\"ETCPACK Fast\"),\n            new PopupElement(\"Etc2Comp Fast\"),\n            new PopupElement(\"Etc2Comp Best\"),\n        };\n\n        private PopupElement[] etcTextureBestCompressorPopupList =\n        {\n            new PopupElement(\"Etc2Comp Fast\"),\n            new PopupElement(\"Etc2Comp Best\"),\n            new PopupElement(\"ETCPACK Best\"),\n        };\n\n        SerializedProperty m_EnableTextureStreamingInPlayMode;\n        SerializedProperty m_EnableTextureStreamingInEditMode;\n        SerializedProperty m_EnableEditorAsyncCPUTextureLoading;\n\n        SerializedProperty m_GameObjectNamingDigits;\n        SerializedProperty m_GameObjectNamingScheme;\n        SerializedProperty m_AssetNamingUsesSpace;\n\n        SerializedProperty m_AsyncShaderCompilation;\n        SerializedProperty m_DefaultBehaviorMode;\n        SerializedProperty m_SerializationMode;\n        SerializedProperty m_SerializeInlineMappingsOnOneLine;\n        SerializedProperty m_PrefabRegularEnvironment;\n        SerializedProperty m_PrefabUIEnvironment;\n        SerializedProperty m_PrefabModeAllowAutoSave;\n        SerializedProperty m_UseLegacyProbeSampleCount;\n        SerializedProperty m_DisableCookiesInLightmapper;\n        SerializedProperty m_SpritePackerMode;\n        SerializedProperty m_SpritePackerCacheSize;\n        SerializedProperty m_Bc7TextureCompressor;\n        SerializedProperty m_EtcTextureCompressorBehavior;\n        SerializedProperty m_EtcTextureFastCompressor;\n        SerializedProperty m_EtcTextureNormalCompressor;\n        SerializedProperty m_EtcTextureBestCompressor;\n        SerializedProperty m_LineEndingsForNewScripts;\n        SerializedProperty m_EnterPlayModeOptionsEnabled;\n        SerializedProperty m_EnterPlayModeOptions;\n        SerializedProperty m_ProjectGenerationIncludedExtensions;\n        SerializedProperty m_ProjectGenerationRootNamespace;\n        SerializedProperty m_CacheServerValidationMode;\n        SerializedProperty m_InspectorUseIMGUIDefaultInspector;\n\n        bool m_IsGlobalSettings;\n\n        const string kRefreshImportModeKeyArgs = \"-refreshImportMode\";\n        const string kStandbyWorkerCountKeyArgs = \"-standbyWorkerCount\";\n        const string kIdleWorkerShutdownDelayKeyArgs = \"-idleWorkerShutdownDelay\";\n        const string kDesiredImportWorkerCountKeyArgs = \"-desiredWorkerCount\";\n\n        private const string kCacheServerDownloadBatchSizeCmdArg = \"-cacheServerDownloadBatchSize\";\n\n        enum CacheServerConnectionState { Unknown, Success, Failure }\n        private CacheServerConnectionState m_CacheServerConnectionState;\n\n        public void OnEnable()\n        {\n            DevDeviceList.Changed += OnDeviceListChanged;\n            BuildRemoteDeviceList();\n\n            m_EnableTextureStreamingInPlayMode = serializedObject.FindProperty(\"m_EnableTextureStreamingInPlayMode\");\n            m_EnableTextureStreamingInEditMode = serializedObject.FindProperty(\"m_EnableTextureStreamingInEditMode\");\n            m_EnableEditorAsyncCPUTextureLoading = serializedObject.FindProperty(\"m_EnableEditorAsyncCPUTextureLoading\");\n\n            m_GameObjectNamingDigits = serializedObject.FindProperty(\"m_GameObjectNamingDigits\");\n            m_GameObjectNamingScheme = serializedObject.FindProperty(\"m_GameObjectNamingScheme\");\n            m_AssetNamingUsesSpace = serializedObject.FindProperty(\"m_AssetNamingUsesSpace\");\n\n            m_AsyncShaderCompilation = serializedObject.FindProperty(\"m_AsyncShaderCompilation\");\n\n            m_DefaultBehaviorMode = serializedObject.FindProperty(\"m_DefaultBehaviorMode\");\n            Assert.IsNotNull(m_DefaultBehaviorMode);\n\n            m_SerializationMode = serializedObject.FindProperty(\"m_SerializationMode\");\n            Assert.IsNotNull(m_SerializationMode);\n\n            m_SerializeInlineMappingsOnOneLine = serializedObject.FindProperty(\"m_SerializeInlineMappingsOnOneLine\");\n            Assert.IsNotNull(m_SerializeInlineMappingsOnOneLine);\n\n            m_PrefabRegularEnvironment = serializedObject.FindProperty(\"m_PrefabRegularEnvironment\");\n            Assert.IsNotNull(m_PrefabRegularEnvironment);\n\n            m_PrefabUIEnvironment = serializedObject.FindProperty(\"m_PrefabUIEnvironment\");\n            Assert.IsNotNull(m_PrefabUIEnvironment);\n\n            m_PrefabModeAllowAutoSave = serializedObject.FindProperty(\"m_PrefabModeAllowAutoSave\");\n            Assert.IsNotNull(m_PrefabModeAllowAutoSave);\n\n            m_UseLegacyProbeSampleCount = serializedObject.FindProperty(\"m_UseLegacyProbeSampleCount\");\n            Assert.IsNotNull(m_UseLegacyProbeSampleCount);\n\n            m_DisableCookiesInLightmapper = serializedObject.FindProperty(\"m_DisableCookiesInLightmapper\");\n            Assert.IsNotNull(m_DisableCookiesInLightmapper);\n\n            m_SpritePackerMode = serializedObject.FindProperty(\"m_SpritePackerMode\");\n            Assert.IsNotNull(m_SpritePackerMode);\n\n            m_SpritePackerCacheSize = serializedObject.FindProperty(\"m_SpritePackerCacheSize\");\n            Assert.IsNotNull(m_SpritePackerCacheSize);\n\n            m_Bc7TextureCompressor = serializedObject.FindProperty(\"m_Bc7TextureCompressor\");\n            Assert.IsNotNull(m_Bc7TextureCompressor);\n\n            m_EtcTextureCompressorBehavior = serializedObject.FindProperty(\"m_EtcTextureCompressorBehavior\");\n            Assert.IsNotNull(m_EtcTextureCompressorBehavior);\n\n            m_EtcTextureFastCompressor = serializedObject.FindProperty(\"m_EtcTextureFastCompressor\");\n            Assert.IsNotNull(m_EtcTextureFastCompressor);\n\n            m_EtcTextureNormalCompressor = serializedObject.FindProperty(\"m_EtcTextureNormalCompressor\");\n            Assert.IsNotNull(m_EtcTextureNormalCompressor);\n\n            m_EtcTextureBestCompressor = serializedObject.FindProperty(\"m_EtcTextureBestCompressor\");\n            Assert.IsNotNull(m_EtcTextureBestCompressor);\n\n            m_LineEndingsForNewScripts = serializedObject.FindProperty(\"m_LineEndingsForNewScripts\");\n            Assert.IsNotNull(m_LineEndingsForNewScripts);\n\n            m_EnterPlayModeOptionsEnabled = serializedObject.FindProperty(\"m_EnterPlayModeOptionsEnabled\");\n            Assert.IsNotNull(m_EnterPlayModeOptionsEnabled);\n\n            m_EnterPlayModeOptions = serializedObject.FindProperty(\"m_EnterPlayModeOptions\");\n            Assert.IsNotNull(m_EnterPlayModeOptions);\n\n            m_ProjectGenerationIncludedExtensions = serializedObject.FindProperty(\"m_ProjectGenerationIncludedExtensions\");\n            Assert.IsNotNull(m_ProjectGenerationIncludedExtensions);\n\n            m_ProjectGenerationRootNamespace = serializedObject.FindProperty(\"m_ProjectGenerationRootNamespace\");\n            Assert.IsNotNull(m_ProjectGenerationRootNamespace);\n\n            m_CacheServerValidationMode = serializedObject.FindProperty(\"m_CacheServerValidationMode\");\n            Assert.IsNotNull(m_ProjectGenerationRootNamespace);\n\n            m_CacheServerConnectionState = CacheServerConnectionState.Unknown;\n\n            m_InspectorUseIMGUIDefaultInspector = serializedObject.FindProperty(\"m_InspectorUseIMGUIDefaultInspector\");\n            Assert.IsNotNull(m_InspectorUseIMGUIDefaultInspector);\n\n            m_IsGlobalSettings = EditorSettings.GetEditorSettings() == target;\n        }\n\n        public void OnDisable()\n        {\n            DevDeviceList.Changed -= OnDeviceListChanged;\n            AssetDatabase.RefreshSettings();\n        }\n\n        void OnDeviceListChanged()\n        {\n            BuildRemoteDeviceList();\n        }\n\n        void BuildRemoteDeviceList()\n        {\n            var devices = new List<DevDevice>();\n            var popupList = new List<PopupElement>();\n\n            devices.Add(DevDevice.none);\n            popupList.Add(new PopupElement(\"None\"));\n\n            // TODO: move Android stuff to editor extension\n            devices.Add(new DevDevice(\"Any Android Device\", \"Any Android Device\",\n                \"virtual\", \"Android\", DevDeviceState.Connected,\n                DevDeviceFeatures.RemoteConnection));\n            popupList.Add(new PopupElement(\"Any Android Device\"));\n\n            foreach (var device in DevDeviceList.GetDevices())\n            {\n                bool supportsRemote = (device.features & DevDeviceFeatures.RemoteConnection) != 0;\n                if (!device.isConnected || !supportsRemote)\n                    continue;\n\n                devices.Add(device);\n                popupList.Add(new PopupElement(device.name));\n            }\n\n            remoteDeviceList = devices.ToArray();\n            remoteDevicePopupList = popupList.ToArray();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            // GUI.enabled hack because we don't want some controls to be disabled if the EditorSettings.asset is locked\n            // since some of the controls are not dependent on the Editor Settings asset. Unfortunately, this assumes\n            // that the editor will only be disabled because of version control locking which may change in the future.\n            var editorEnabled = GUI.enabled;\n\n            // Remove Settings are taken from preferences and NOT from the EditorSettings Asset.\n            // Only show them when editing the \"global\" settings\n            if (m_IsGlobalSettings)\n                ShowUnityRemoteGUI(editorEnabled);\n\n            GUILayout.Space(10);\n\n            GUI.enabled = true;\n            GUILayout.Label(Content.assetSerialization, EditorStyles.boldLabel);\n            GUI.enabled = editorEnabled;\n\n            int index = m_SerializationMode.intValue;\n            CreatePopupMenu(\"Mode\", serializationPopupList, index, SetAssetSerializationMode);\n\n            if (m_SerializationMode.intValue != (int)SerializationMode.ForceBinary)\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUILayout.PropertyField(m_SerializeInlineMappingsOnOneLine, Content.textSerializeMappingsOnOneLine);\n                if (EditorGUI.EndChangeCheck() && m_IsGlobalSettings)\n                {\n                    EditorSettings.serializeInlineMappingsOnOneLine = m_SerializeInlineMappingsOnOneLine.boolValue;\n                }\n            }\n\n            GUILayout.Space(10);\n\n            GUILayout.BeginHorizontal();\n            GUI.enabled = true;\n            GUILayout.Label(Content.buildPipelineHeader, EditorStyles.boldLabel);\n            GUI.enabled = editorEnabled;\n            if (GUILayout.Button(Content.ucbpLearnMore, EditorStyles.linkLabel))\n            {\n                var help = Help.FindHelpNamed(\"Build-MultiProcess\");\n                Application.OpenURL(help);\n            }\n            GUILayout.EndHorizontal();\n\n            EditorGUI.BeginChangeCheck();\n            bool parallelAssetBundleBuilding = EditorBuildSettings.UseParallelAssetBundleBuilding;\n            parallelAssetBundleBuilding = EditorGUILayout.Toggle(Content.ucbpEnableAssetBundles, parallelAssetBundleBuilding);\n            if (EditorGUI.EndChangeCheck())\n                EditorBuildSettings.UseParallelAssetBundleBuilding = parallelAssetBundleBuilding;\n            if(parallelAssetBundleBuilding)\n                EditorGUILayout.HelpBox(\"Please review official documentation before building any content with these experimental improvements enabled. These improvements apply only to AssetBundles built with BuildPipeline.BuildAssetBundles() and do not apply to AssetBundles built with Scriptable Build Pipeline or Addressables.\", MessageType.Info);\n\n            GUILayout.Label(Content.sceneHandlingHeader, EditorStyles.boldLabel);\n            EditorGUI.BeginChangeCheck();\n            bool forceAssetUnloadAndGCOnSceneLoad = EditorSettings.forceAssetUnloadAndGCOnSceneLoad;\n            forceAssetUnloadAndGCOnSceneLoad = EditorGUILayout.Toggle(Content.forceAssetUnloadAndGCOnSceneLoad, forceAssetUnloadAndGCOnSceneLoad);\n            if (EditorGUI.EndChangeCheck())\n                EditorSettings.forceAssetUnloadAndGCOnSceneLoad = forceAssetUnloadAndGCOnSceneLoad;\n\n            GUILayout.Space(10);\n\n            GUI.enabled = true;\n            GUILayout.Label(Content.defaultBehaviorMode, EditorStyles.boldLabel);\n            GUI.enabled = editorEnabled;\n\n            index = Mathf.Clamp(m_DefaultBehaviorMode.intValue, 0, behaviorPopupList.Length - 1);\n            CreatePopupMenu(Content.mode.text, behaviorPopupList, index, SetDefaultBehaviorMode);\n\n            DoAssetPipelineSettings();\n\n            // CacheServer is part asset and preferences. Only show UI in case of Global Settings editing.\n            if (m_IsGlobalSettings)\n            {\n                var wasEnabled = GUI.enabled;\n                GUI.enabled = true;\n\n                DoCacheServerSettings();\n\n                GUI.enabled = wasEnabled;\n            }\n\n            GUILayout.Space(10);\n\n            GUI.enabled = true;\n            GUILayout.Label(Content.prefabMode, EditorStyles.boldLabel);\n            GUI.enabled = editorEnabled;\n\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUILayout.PropertyField(m_PrefabModeAllowAutoSave, Content.prefabModeAllowAutoSave);\n                if (EditorGUI.EndChangeCheck() && m_IsGlobalSettings)\n                {\n                    EditorSettings.prefabModeAllowAutoSave = m_PrefabModeAllowAutoSave.boolValue;\n                }\n            }\n\n            GUILayout.Label(Content.prefabModeEditingEnvironments, EditorStyles.label);\n\n            EditorGUI.indentLevel++;\n            {\n                EditorGUI.BeginChangeCheck();\n                var scene = m_PrefabRegularEnvironment.objectReferenceValue as SceneAsset;\n                scene = (SceneAsset)EditorGUILayout.ObjectField(Content.prefabModeRegularEnvironment, scene, typeof(SceneAsset), false);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_PrefabRegularEnvironment.objectReferenceValue = scene;\n                    if (m_IsGlobalSettings)\n                    {\n                        EditorSettings.prefabRegularEnvironment = scene;\n                    }\n                }\n            }\n            {\n                EditorGUI.BeginChangeCheck();\n                var scene = m_PrefabUIEnvironment.objectReferenceValue as SceneAsset;\n                scene = (SceneAsset)EditorGUILayout.ObjectField(Content.prefabModeUIEnvironment, scene, typeof(SceneAsset), false);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_PrefabUIEnvironment.objectReferenceValue = scene;\n                    if (m_IsGlobalSettings)\n                    {\n                        EditorSettings.prefabUIEnvironment = scene;\n                    }\n                }\n            }\n            EditorGUI.indentLevel--;\n\n            GUILayout.Space(10);\n\n            GUI.enabled = true;\n            GUILayout.Label(Content.graphics, EditorStyles.boldLabel);\n            GUI.enabled = editorEnabled;\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_UseLegacyProbeSampleCount, Content.useLegacyProbeSampleCount);\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (m_IsGlobalSettings)\n                    EditorSettings.useLegacyProbeSampleCount = m_UseLegacyProbeSampleCount.boolValue;\n\n                EditorApplication.RequestRepaintAllViews();\n            }\n\n            GUILayout.Space(10);\n\n            GUI.enabled = true;\n            GUILayout.Label(Content.spritePacker, EditorStyles.boldLabel);\n            GUI.enabled = editorEnabled;\n\n            // Legacy Packer has been deprecated.\n            index = Mathf.Clamp(m_SpritePackerMode.intValue - spritePackDeprecatedEnums, 0, spritePackerPopupList.Length - 1);\n            CreatePopupMenu(Content.mode.text, spritePackerPopupList, index, SetSpritePackerMode);\n            if (EditorSettings.spritePackerMode != SpritePackerMode.SpriteAtlasV2 && EditorSettings.spritePackerMode != SpritePackerMode.SpriteAtlasV2Build && EditorSettings.spritePackerMode != SpritePackerMode.Disabled)\n                EditorGUILayout.IntSlider(m_SpritePackerCacheSize, 1, 200, Content.spriteMaxCacheSize);\n\n            DoProjectGenerationSettings();\n            var compressorsChanged = DoTextureCompressorSettings();\n            DoLineEndingsSettings();\n            DoStreamingSettings();\n            DoShaderCompilationSettings();\n            DoEnterPlayModeSettings();\n            DoNumberingSchemeSettings();\n            DoEnterInspectorSettings();\n\n            serializedObject.ApplyModifiedProperties();\n            if (compressorsChanged)\n                AssetDatabase.Refresh(); // note: needs to be done after ApplyModifiedProperties call\n        }\n\n        private void DoProjectGenerationSettings()\n        {\n            GUILayout.Space(10);\n            GUILayout.Label(Content.cSharpProjectGeneration, EditorStyles.boldLabel);\n\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_ProjectGenerationIncludedExtensions, Content.additionalExtensionsToInclude);\n            if (EditorGUI.EndChangeCheck() && m_IsGlobalSettings)\n            {\n                EditorSettings.Internal_ProjectGenerationUserExtensions = m_ProjectGenerationIncludedExtensions.stringValue;\n            }\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_ProjectGenerationRootNamespace, Content.rootNamespace);\n            if (EditorGUI.EndChangeCheck() && m_IsGlobalSettings)\n            {\n                EditorSettings.projectGenerationRootNamespace = m_ProjectGenerationRootNamespace.stringValue;\n            }\n        }\n\n        private bool DoTextureCompressorSettings()\n        {\n            GUILayout.Space(10);\n\n            GUILayout.Label(Content.textureCompressors, EditorStyles.boldLabel);\n\n            EditorGUI.BeginChangeCheck();\n\n            // BC7\n            EditorGUILayout.Popup(m_Bc7TextureCompressor, bc7TextureCompressorOptions, Content.bc7Compressor);\n\n            // ETC\n            int index = Mathf.Clamp(m_IsGlobalSettings ? EditorSettings.etcTextureCompressorBehaviorInternal : m_EtcTextureCompressorBehavior.intValue, 0, etcTextureCompressorPopupList.Length - 1);\n            CreatePopupMenu(Content.etcCompressor.text, etcTextureCompressorPopupList, index, SetEtcTextureCompressorBehavior);\n\n            EditorGUI.indentLevel++;\n            EditorGUI.BeginDisabledGroup(index < 2);\n\n            index = Mathf.Clamp(m_IsGlobalSettings ? EditorSettings.etcTextureFastCompressor : m_EtcTextureFastCompressor.intValue, 0, etcTextureFastCompressorPopupList.Length - 1);\n            CreatePopupMenu(Content.fast.text, etcTextureFastCompressorPopupList, index, SetEtcTextureFastCompressor);\n\n            index = Mathf.Clamp(m_IsGlobalSettings ? EditorSettings.etcTextureNormalCompressor : m_EtcTextureNormalCompressor.intValue, 0, etcTextureNormalCompressorPopupList.Length - 1);\n            CreatePopupMenu(Content.normal.text, etcTextureNormalCompressorPopupList, index, SetEtcTextureNormalCompressor);\n\n            index = Mathf.Clamp(m_IsGlobalSettings ? EditorSettings.etcTextureBestCompressor : m_EtcTextureBestCompressor.intValue, 0, etcTextureBestCompressorPopupList.Length - 1);\n            CreatePopupMenu(Content.best.text, etcTextureBestCompressorPopupList, index, SetEtcTextureBestCompressor);\n\n            EditorGUI.EndDisabledGroup();\n            EditorGUI.indentLevel--;\n\n            if ((m_IsGlobalSettings ? EditorSettings.etcTextureCompressorBehaviorInternal : m_EtcTextureCompressorBehavior.intValue) == 0)\n            {\n                EditorGUILayout.HelpBox(Content.legacyDeprecationWarning.text, MessageType.Warning, true);\n            }\n\n            return EditorGUI.EndChangeCheck();\n        }\n\n        private void DoAssetPipelineSettings()\n        {\n            GUILayout.Space(10);\n\n            GUILayout.Label(Content.assetPipeline, EditorStyles.boldLabel);\n\n            EditorGUI.BeginChangeCheck();\n            bool enableArtifactGarbageCollection = EditorUserSettings.artifactGarbageCollection;\n            enableArtifactGarbageCollection = EditorGUILayout.Toggle(Content.artifactGarbageCollection, enableArtifactGarbageCollection);\n            if (EditorGUI.EndChangeCheck())\n                EditorUserSettings.artifactGarbageCollection = enableArtifactGarbageCollection;\n\n            var overrideMode = GetCommandLineOverride(kRefreshImportModeKeyArgs);\n            if (overrideMode != null)\n            {\n                EditorGUILayout.HelpBox($\"Refresh Import mode forced to {overrideMode} via command line argument. To use the mode specified here please restart Unity without the -refreshImportMode command line argument.\", MessageType.Info, true);\n            }\n\n            using (new EditorGUI.DisabledScope(overrideMode != null))\n            {\n                GUILayout.BeginHorizontal();\n                    var refreshMode = EditorSettings.refreshImportMode;\n                    var parallelImportEnabledOld = refreshMode == AssetDatabase.RefreshImportMode.OutOfProcessPerQueue;\n                    var parallelImportEnabledNew = EditorGUILayout.Toggle(Content.parallelImport, parallelImportEnabledOld);\n\n                    if (parallelImportEnabledOld != parallelImportEnabledNew)\n                        EditorSettings.refreshImportMode = parallelImportEnabledNew ? AssetDatabase.RefreshImportMode.OutOfProcessPerQueue : AssetDatabase.RefreshImportMode.InProcess;\n                    if (GUILayout.Button(Content.parallelImportLearnMore, EditorStyles.linkLabel))\n                    {\n                        // Known issue with Docs redirect - versioned pages might not open offline docs\n                        var help = Help.FindHelpNamed(\"ParallelImport\");\n                        Help.BrowseURL(help);\n                    }\n                GUILayout.EndHorizontal();\n            }\n\n            var overrideDesiredCount = GetCommandLineOverride(kDesiredImportWorkerCountKeyArgs);\n            if (overrideDesiredCount != null)\n            {\n                EditorGUILayout.HelpBox($\"Desired import worker count forced to {overrideDesiredCount} via command line argument. To use the worker count specified here please restart Unity without the -desiredWorkerCount command line argument.\", MessageType.Info, true);\n            }\n\n            // This min/max worker count is enforced here and in EditorUserSettings.cpp\n            // Please keep them in sync.\n            const int minWorkerCount = 1;\n            const int maxWorkerCount = 128;\n\n            using (new EditorGUI.DisabledScope(overrideDesiredCount != null))\n            {\n                var oldCount = EditorUserSettings.desiredImportWorkerCount;\n                int newCount = EditorGUILayout.IntField(Content.desiredImportWorkerCount, oldCount);\n                newCount = Mathf.Clamp(newCount, minWorkerCount, maxWorkerCount);\n\n                if (oldCount != newCount)\n                    EditorUserSettings.desiredImportWorkerCount = newCount;\n            }\n\n            var overrideStandbyCount = GetCommandLineOverride(kStandbyWorkerCountKeyArgs);\n            if (overrideStandbyCount != null)\n            {\n                EditorGUILayout.HelpBox($\"Standby import worker count forced to {overrideStandbyCount} via command line argument. To use the standby worker count specified here please restart Unity without the -standbyWorkerCount command line argument.\", MessageType.Info, true);\n            }\n\n            using (new EditorGUI.DisabledScope(overrideStandbyCount != null))\n            {\n                var oldCount = EditorUserSettings.standbyImportWorkerCount;\n                var newCount = EditorGUILayout.IntField(Content.standbyImportWorkerCount, oldCount);\n                int desiredWorkerCount = EditorUserSettings.desiredImportWorkerCount;\n                newCount = Mathf.Clamp(newCount, 0, desiredWorkerCount);\n\n                if (oldCount != newCount)\n                {\n                    EditorUserSettings.standbyImportWorkerCount = newCount;\n                }\n            }\n\n            var overridekIdleWorkerShutdownDelay = GetCommandLineOverride(kIdleWorkerShutdownDelayKeyArgs);\n            if (overridekIdleWorkerShutdownDelay != null)\n            {\n                EditorGUILayout.HelpBox($\"Idle import worker shutdown delay forced to {overridekIdleWorkerShutdownDelay} ms. via command line argument. To use the settings specified here please restart Unity without the -idleWorkerShutdownDelay command line argument.\", MessageType.Info, true);\n            }\n\n            using (new EditorGUI.DisabledScope(overridekIdleWorkerShutdownDelay != null))\n            {\n                var oldSeconds = EditorUserSettings.idleImportWorkerShutdownDelayMilliseconds / 1000.0f;\n                var newSeconds = EditorGUILayout.FloatField(Content.idleWorkerShutdownDelay, oldSeconds);\n                newSeconds = Mathf.Max(0, newSeconds);\n\n                if (oldSeconds != newSeconds)\n                {\n                    EditorUserSettings.idleImportWorkerShutdownDelayMilliseconds = (int)(newSeconds * 1000.0f);\n                }\n            }\n\n            EditorGUI.BeginChangeCheck();\n            bool referencedClipsExactNaming = EditorSettings.referencedClipsExactNaming;\n            referencedClipsExactNaming = EditorGUILayout.Toggle(Content.referencedClipsExactNaming, referencedClipsExactNaming);\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (EditorUtility.DisplayDialog(\n                        \"Warning: Long Import Times\",\n                        \"Changing this setting might result in several models being re-imported\",\n                        $\"Proceed\",\n                        \"Cancel\"))\n                {\n                    EditorSettings.referencedClipsExactNaming = referencedClipsExactNaming;\n                    AssetDatabase.Refresh();\n                }\n            }\n        }\n\n        private void DoCacheServerSettings()\n        {\n            Assert.IsTrue(m_IsGlobalSettings);\n            GUILayout.Space(10);\n\n            GUILayout.BeginHorizontal();\n            GUILayout.Label(Content.cacheServer, EditorStyles.boldLabel);\n\n            if (GUILayout.Button(Content.cacheServerLearnMore, EditorStyles.linkLabel))\n            {\n                // Known issue with Docs redirect - versioned pages might not open offline docs\n                var help = Help.FindHelpNamed(\"UnityAccelerator\");\n                Help.BrowseURL(help);\n            }\n            GUILayout.EndHorizontal();\n\n            int index = Mathf.Clamp((int)EditorSettings.cacheServerMode, 0, cacheServerModePopupList.Length - 1);\n            CreatePopupMenu(Content.mode.text, cacheServerModePopupList, index, SetCacheServerMode);\n\n            if (index != (int)CacheServerMode.Disabled)\n            {\n                bool isCacheServerEnabled = true;\n\n                if (index == (int)CacheServerMode.AsPreferences)\n                {\n                    isCacheServerEnabled = false;\n                    if (AssetPipelinePreferences.IsCacheServerEnabled)\n                    {\n                        var cacheServerIP = AssetPipelinePreferences.CacheServerAddress;\n                        cacheServerIP = string.IsNullOrEmpty(cacheServerIP) ? \"Not set in preferences\" : cacheServerIP;\n                        EditorGUILayout.HelpBox(cacheServerIP, MessageType.None, false);\n                    }\n                    else\n                    {\n                        EditorGUILayout.HelpBox(\"Disabled\", MessageType.None, false);\n                    }\n                }\n\n                if (isCacheServerEnabled)\n                {\n                    var oldEndpoint = EditorSettings.cacheServerEndpoint;\n                    var newEndpoint = EditorGUILayout.TextField(Content.cacheServerIPLabel, oldEndpoint);\n                    if (newEndpoint != oldEndpoint)\n                    {\n                        EditorSettings.cacheServerEndpoint = newEndpoint;\n                    }\n\n                    EditorGUILayout.BeginHorizontal();\n\n                    if (GUILayout.Button(\"Check Connection\", GUILayout.Width(150)))\n                    {\n                        var address = EditorSettings.cacheServerEndpoint.Split(':');\n                        var ip = address[0];\n                        UInt16 port = 0; // If 0, will use the default set port\n                        if (address.Length == 2)\n                            port = Convert.ToUInt16(address[1]);\n\n                        bool canConnect = AssetDatabase.CanConnectToCacheServer(ip, port);\n                        bool isConnected = AssetDatabase.IsConnectedToCacheServer();\n                        if (canConnect)\n                            m_CacheServerConnectionState = CacheServerConnectionState.Success;\n                        else\n                            m_CacheServerConnectionState = CacheServerConnectionState.Failure;\n\n                        //We have to check if we're out of sync. here.\n                        //If we can connect, but we're not connected, we need to update some UI\n                        //If we CANNOT connect, but we are connected, we are out of sync. too and\n                        //need to update some UI.\n                        //Calling RefreshSettings here fixes that, and this check encapsulates the\n                        //above 2 conditions.\n                        if (canConnect != isConnected)\n                            AssetDatabase.RefreshSettings();\n                    }\n\n                    GUILayout.Space(25);\n\n                    switch (m_CacheServerConnectionState)\n                    {\n                        case CacheServerConnectionState.Success:\n                            EditorGUILayout.HelpBox(\"Connection successful.\", MessageType.Info, true);\n                            break;\n\n                        case CacheServerConnectionState.Failure:\n                            EditorGUILayout.HelpBox(\"Connection failed.\", MessageType.Warning, true);\n                            break;\n\n                        case CacheServerConnectionState.Unknown:\n                            GUILayout.Space(44);\n                            break;\n                    }\n\n                    EditorGUILayout.EndHorizontal();\n\n                    var oldPrefix = EditorSettings.cacheServerNamespacePrefix;\n                    var newPrefix = EditorGUILayout.TextField(Content.cacheServerNamespacePrefixLabel, oldPrefix);\n                    if (newPrefix != oldPrefix)\n                    {\n                        EditorSettings.cacheServerNamespacePrefix = newPrefix;\n                    }\n\n                    EditorGUI.BeginChangeCheck();\n                    bool enableDownload = EditorSettings.cacheServerEnableDownload;\n                    enableDownload = EditorGUILayout.Toggle(Content.cacheServerEnableDownloadLabel, enableDownload);\n                    if (EditorGUI.EndChangeCheck())\n                        EditorSettings.cacheServerEnableDownload = enableDownload;\n\n                    EditorGUI.BeginChangeCheck();\n                    bool enableUpload = EditorSettings.cacheServerEnableUpload;\n                    enableUpload = EditorGUILayout.Toggle(Content.cacheServerEnableUploadLabel, enableUpload);\n                    if (EditorGUI.EndChangeCheck())\n                        EditorSettings.cacheServerEnableUpload = enableUpload;\n\n                    bool enableAuth = EditorSettings.cacheServerEnableAuth;\n                    using (new EditorGUI.DisabledScope(enableAuth))\n                    {\n                        EditorGUI.BeginChangeCheck();\n                        bool enableTls = EditorSettings.cacheServerEnableTls;\n                        enableTls = EditorGUILayout.Toggle(Content.cacheServerEnableTlsLabel, enableTls);\n                        if (EditorGUI.EndChangeCheck())\n                            EditorSettings.cacheServerEnableTls = enableTls;\n                    }\n\n                    EditorGUI.BeginChangeCheck();\n                    enableAuth = EditorGUILayout.Toggle(Content.cacheServerEnableAuthLabel, enableAuth);\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        EditorSettings.cacheServerEnableAuth = enableAuth;\n                        if (enableAuth)\n                        {\n                            EditorSettings.cacheServerEnableTls = true;\n                        }\n                    }\n\n                    int validationIndex = Mathf.Clamp((int)EditorSettings.cacheServerValidationMode, 0, cacheServerValidationPopupList.Length - 1);\n                    EditorGUILayout.Popup(m_CacheServerValidationMode, cacheServerValidationPopupList, Content.cacheServerValidationLabel);\n\n                    var cacheServerDownloadBatchSizeOverride = GetCommandLineOverride(kCacheServerDownloadBatchSizeCmdArg);\n                    if (cacheServerDownloadBatchSizeOverride != null)\n                        EditorGUILayout.HelpBox($\"Forced via command line argument. To use the setting, please restart Unity without the {kCacheServerDownloadBatchSizeCmdArg} command line argument.\", MessageType.Info, true);\n\n                    using (new EditorGUI.DisabledScope(cacheServerDownloadBatchSizeOverride != null))\n                    {\n                        var oldDownloadBatchSize = cacheServerDownloadBatchSizeOverride != null ? Int32.Parse(cacheServerDownloadBatchSizeOverride) : EditorSettings.cacheServerDownloadBatchSize;\n                        var newDownloadBatchSize = EditorGUILayout.IntField(Content.cacheServerDownloadBatchSizeLabel, oldDownloadBatchSize);\n                        newDownloadBatchSize = Mathf.Max(0, newDownloadBatchSize);\n                        if (newDownloadBatchSize != oldDownloadBatchSize)\n                            EditorSettings.cacheServerDownloadBatchSize = newDownloadBatchSize;\n                    }\n                }\n            }\n        }\n\n        private static string GetCommandLineOverride(string key)\n        {\n            string address = null;\n            var argv = Environment.GetCommandLineArgs();\n            var index = Array.IndexOf(argv, key);\n            if (index >= 0 && argv.Length > index + 1)\n                address = argv[index + 1];\n\n            return address;\n        }\n\n        private void DoLineEndingsSettings()\n        {\n            GUILayout.Space(10);\n            GUILayout.Label(Content.lineEndingForNewScripts, EditorStyles.boldLabel);\n\n            int index = m_LineEndingsForNewScripts.intValue;\n            CreatePopupMenu(Content.mode.text, lineEndingsPopupList, index, SetLineEndingsForNewScripts);\n        }\n\n        private void DoStreamingSettings()\n        {\n            GUILayout.Space(10);\n            GUILayout.Label(Content.streamingSettings, EditorStyles.boldLabel);\n\n            EditorGUILayout.PropertyField(m_EnableTextureStreamingInPlayMode, Content.enablePlayModeTextureStreaming);\n            EditorGUILayout.PropertyField(m_EnableTextureStreamingInEditMode, Content.enableEditModeTextureStreaming);\n            EditorGUILayout.PropertyField(m_EnableEditorAsyncCPUTextureLoading, Content.enableEditorAsyncCPUTextureLoading);\n        }\n\n        EditorSettings.NamingScheme m_PrevGoNamingScheme;\n        int m_PrevGoNamingDigits = -1;\n        string m_GoNamingHelpText;\n        static string GetNewName(string name, List<string> names)\n        {\n            var newName = ObjectNames.GetUniqueName(names.ToArray(), name);\n            names.Add(newName);\n            return newName;\n        }\n\n        void DoNumberingSchemeSettings()\n        {\n            GUILayout.Space(10);\n            GUILayout.Label(Content.numberingScheme, EditorStyles.boldLabel);\n            EditorGUILayout.IntPopup(m_GameObjectNamingScheme, Content.numberingSchemeNames, Content.numberingSchemeValues, Content.numberingHierarchyScheme);\n            EditorGUILayout.IntSlider(m_GameObjectNamingDigits, 1, 5, Content.numberingHierarchyDigits);\n            if (m_PrevGoNamingDigits != EditorSettings.gameObjectNamingDigits ||\n                m_PrevGoNamingScheme != EditorSettings.gameObjectNamingScheme ||\n                m_GoNamingHelpText == null)\n            {\n                var names = new List<string>();\n                var n1 = \"Clap\";\n                var n2 = \"High5\";\n                m_GoNamingHelpText = $\"Instances of prefab '{n1}' will become '{GetNewName(n1, names)}', '{GetNewName(n1, names)}', '{GetNewName(n1, names)}'\\nInstances of prefab '{n2}' will become '{GetNewName(n2, names)}', '{GetNewName(n2, names)}', '{GetNewName(n2, names)}'\";\n                m_PrevGoNamingDigits = EditorSettings.gameObjectNamingDigits;\n                m_PrevGoNamingScheme = EditorSettings.gameObjectNamingScheme;\n            }\n            EditorGUILayout.HelpBox(m_GoNamingHelpText, MessageType.Info, true);\n\n            EditorGUILayout.PropertyField(m_AssetNamingUsesSpace, Content.numberingProjectSpace);\n        }\n\n        private void DoShaderCompilationSettings()\n        {\n            GUILayout.Space(10);\n            GUILayout.Label(Content.shaderCompilation, EditorStyles.boldLabel);\n\n            EditorGUILayout.PropertyField(m_AsyncShaderCompilation, Content.asyncShaderCompilation);\n        }\n\n        private void DoEnterPlayModeSettings()\n        {\n            GUILayout.Space(10);\n            GUILayout.Label(Content.enterPlayModeSettings, EditorStyles.boldLabel);\n\n            EditorGUI.BeginChangeCheck();\n\n            EditorGUILayout.IntPopup(m_EnterPlayModeOptions, Content.enterPlayModeOptionNames, Content.enterPlayModeOptionValues, Content.enterPlayModeOptions);\n\n            if (EditorGUI.EndChangeCheck() && m_IsGlobalSettings)\n            {\n                EditorSettings.enterPlayModeOptionsEnabled = m_EnterPlayModeOptionsEnabled.boolValue;\n                EditorSettings.enterPlayModeOptions = (EnterPlayModeOptions)m_EnterPlayModeOptions.intValue;\n            }\n        }\n\n        private void DoEnterInspectorSettings()\n        {\n            GUILayout.Space(10);\n            GUILayout.Label(Content.inspectorSettings, EditorStyles.boldLabel);\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_InspectorUseIMGUIDefaultInspector, Content.inspectorUseIMGUIDefaultInspector);\n            if (EditorGUI.EndChangeCheck() && m_IsGlobalSettings)\n            {\n                EditorSettings.inspectorUseIMGUIDefaultInspector = m_InspectorUseIMGUIDefaultInspector.boolValue;\n                PropertyEditor.ClearAndRebuildAll();\n            }\n        }\n\n        static int GetIndexById(DevDevice[] elements, string id, int defaultIndex)\n        {\n            for (int i = 0; i < elements.Length; i++)\n                if (elements[i].id == id)\n                    return i;\n\n            return defaultIndex;\n        }\n\n        static int GetIndexById(PopupElement[] elements, string id, int defaultIndex)\n        {\n            for (int i = 0; i < elements.Length; i++)\n                if (elements[i].id == id)\n                    return i;\n\n            return defaultIndex;\n        }\n\n        private void ShowUnityRemoteGUI(bool editorEnabled)\n        {\n            // This is a global Settings persisted in preferences\n            Assert.IsTrue(m_IsGlobalSettings);\n            GUI.enabled = true;\n            GUILayout.Label(Content.unityRemote, EditorStyles.boldLabel);\n            GUI.enabled = editorEnabled;\n\n            // Find selected device index\n            string id = EditorSettings.unityRemoteDevice;\n            // We assume first device to be \"None\", and default to it, hence 0\n            int index = GetIndexById(remoteDeviceList, id, 0);\n\n            var content = new GUIContent(remoteDevicePopupList[index].content);\n            var popupRect = GUILayoutUtility.GetRect(content, EditorStyles.popup);\n            popupRect = EditorGUI.PrefixLabel(popupRect, 0, Content.device);\n            if (EditorGUI.DropdownButton(popupRect, content, FocusType.Passive, EditorStyles.popup))\n                DoPopup(popupRect, remoteDevicePopupList, index, SetUnityRemoteDevice);\n\n            int compression = GetIndexById(remoteCompressionList, EditorSettings.unityRemoteCompression, 0);\n            content = new GUIContent(remoteCompressionList[compression].content);\n            popupRect = GUILayoutUtility.GetRect(content, EditorStyles.popup);\n            popupRect = EditorGUI.PrefixLabel(popupRect, 0, Content.compression);\n            if (EditorGUI.DropdownButton(popupRect, content, FocusType.Passive, EditorStyles.popup))\n                DoPopup(popupRect, remoteCompressionList, compression, SetUnityRemoteCompression);\n\n            int resolution = GetIndexById(remoteResolutionList, EditorSettings.unityRemoteResolution, 0);\n            content = new GUIContent(remoteResolutionList[resolution].content);\n            popupRect = GUILayoutUtility.GetRect(content, EditorStyles.popup);\n            popupRect = EditorGUI.PrefixLabel(popupRect, 0, Content.resolution);\n            if (EditorGUI.DropdownButton(popupRect, content, FocusType.Passive, EditorStyles.popup))\n                DoPopup(popupRect, remoteResolutionList, resolution, SetUnityRemoteResolution);\n\n            int joystickSource = GetIndexById(remoteJoystickSourceList, EditorSettings.unityRemoteJoystickSource, 0);\n            content = new GUIContent(remoteJoystickSourceList[joystickSource].content);\n            popupRect = GUILayoutUtility.GetRect(content, EditorStyles.popup);\n            popupRect = EditorGUI.PrefixLabel(popupRect, 0, Content.joystickSource);\n            if (EditorGUI.DropdownButton(popupRect, content, FocusType.Passive, EditorStyles.popup))\n                DoPopup(popupRect, remoteJoystickSourceList, joystickSource, SetUnityRemoteJoystickSource);\n        }\n\n        private void CreatePopupMenu(string title, PopupElement[] elements, int selectedIndex, GenericMenu.MenuFunction2 func)\n        {\n            CreatePopupMenu(serializedObject, new GUIContent(title), elements[selectedIndex].content, elements, selectedIndex, func);\n        }\n\n        internal static void CreatePopupMenu(SerializedObject obj, GUIContent titleContent, GUIContent content, PopupElement[] elements, int selectedIndex, GenericMenu.MenuFunction2 func)\n        {\n            var popupRect = GUILayoutUtility.GetRect(content, EditorStyles.popup);\n            popupRect = EditorGUI.PrefixLabel(popupRect, 0, titleContent);\n            if (EditorGUI.DropdownButton(popupRect, content, FocusType.Passive, EditorStyles.popup))\n            {\n                DoPopup(popupRect, elements, selectedIndex, data =>\n                {\n                    func(data);\n                    obj?.ApplyModifiedProperties();\n                });\n            }\n        }\n\n        internal static void DoPopup(Rect popupRect, PopupElement[] elements, int selectedIndex, GenericMenu.MenuFunction2 func)\n        {\n            GenericMenu menu = new GenericMenu();\n            for (int i = 0; i < elements.Length; i++)\n            {\n                var element = elements[i];\n                menu.AddItem(element.content, i == selectedIndex, func, i);\n            }\n            menu.DropDown(popupRect);\n        }\n\n        private void SetAssetSerializationMode(object data)\n        {\n            int popupIndex = (int)data;\n\n            if (m_SerializationMode.intValue == popupIndex) return;\n\n            if (!EditorUtility.DisplayDialog(\"Change Asset Serialization Mode?\",\n                    \"Changing the serialization method for assets may force a reimport of some or all assets immediately in the project.\\n\\nAre you sure you wish to change the asset serialization mode?\",\n                    \"Yes\", \"No\")) return;\n\n            m_SerializationMode.intValue = popupIndex;\n            if (m_IsGlobalSettings)\n                EditorSettings.serializationMode = (SerializationMode)popupIndex;\n        }\n\n        private void SetUnityRemoteDevice(object data)\n        {\n            EditorSettings.unityRemoteDevice = remoteDeviceList[(int)data].id;\n        }\n\n        private void SetUnityRemoteCompression(object data)\n        {\n            EditorSettings.unityRemoteCompression = remoteCompressionList[(int)data].id;\n        }\n\n        private void SetUnityRemoteResolution(object data)\n        {\n            EditorSettings.unityRemoteResolution = remoteResolutionList[(int)data].id;\n        }\n\n        private void SetUnityRemoteJoystickSource(object data)\n        {\n            EditorSettings.unityRemoteJoystickSource = remoteJoystickSourceList[(int)data].id;\n        }\n\n        private void SetDefaultBehaviorMode(object data)\n        {\n            int popupIndex = (int)data;\n            m_DefaultBehaviorMode.intValue = popupIndex;\n            if (m_IsGlobalSettings)\n            {\n                EditorSettings.defaultBehaviorMode = (EditorBehaviorMode)popupIndex;\n            }\n        }\n\n        private void SetSpritePackerMode(object data)\n        {\n            int popupIndex = (int)data;\n\n            // Legacy Packer has been obsoleted (1 & 2). Disabled (0) is still valid.\n            popupIndex = (popupIndex != 0) ? (popupIndex + spritePackDeprecatedEnums) : 0;\n            m_SpritePackerMode.intValue = popupIndex;\n\n            if (m_IsGlobalSettings)\n            {\n                EditorSettings.spritePackerMode = (SpritePackerMode)popupIndex;\n                if (popupIndex >= (int)SpritePackerMode.SpriteAtlasV2)\n                {\n                    UnityEditor.U2D.SpriteAtlasImporter.MigrateAllSpriteAtlases();\n                }\n            }\n        }\n\n        private void SetRefreshImportMode(object data)\n        {\n            EditorSettings.refreshImportMode = (AssetDatabase.RefreshImportMode)data;\n        }\n\n        private void SetCacheServerMode(object data)\n        {\n            EditorSettings.cacheServerMode = (CacheServerMode)data;\n        }\n\n        private void SetCacheServerAuthMode(object data)\n        {\n            EditorUserSettings.SetConfigValue(\"cacheServerAuthMode\", $\"{(int)data}\");\n        }\n\n        private void SetCacheServerValidationMode(object data)\n        {\n            EditorSettings.cacheServerValidationMode = (CacheServerValidationMode)data;\n        }\n\n        private void SetEtcTextureCompressorBehavior(object data)\n        {\n            int newValue = (int)data;\n            if (m_IsGlobalSettings)\n            {\n                if (EditorSettings.etcTextureCompressorBehaviorInternal == newValue)\n                    return;\n\n                EditorSettings.etcTextureCompressorBehaviorInternal = newValue;\n\n                if (newValue == 0)\n                    EditorSettings.SetEtcTextureCompressorLegacyBehavior();\n                else if (newValue == 1)\n                    EditorSettings.SetEtcTextureCompressorDefaultBehavior();\n            }\n            else\n            {\n                m_EtcTextureCompressorBehavior.intValue = newValue;\n            }\n        }\n\n        private void SetEtcTextureFastCompressor(object data)\n        {\n            if (m_IsGlobalSettings)\n                EditorSettings.etcTextureFastCompressor = (int)data;\n            else\n                m_EtcTextureFastCompressor.intValue = (int)data;\n        }\n\n        private void SetEtcTextureNormalCompressor(object data)\n        {\n            if (m_IsGlobalSettings)\n                EditorSettings.etcTextureNormalCompressor = (int)data;\n            else\n                m_EtcTextureNormalCompressor.intValue = (int)data;\n        }\n\n        private void SetEtcTextureBestCompressor(object data)\n        {\n            if (m_IsGlobalSettings)\n                EditorSettings.etcTextureBestCompressor = (int)data;\n            else\n                m_EtcTextureBestCompressor.intValue = (int)data;\n        }\n\n        private void SetLineEndingsForNewScripts(object data)\n        {\n            int popupIndex = (int)data;\n            m_LineEndingsForNewScripts.intValue = popupIndex;\n            if (m_IsGlobalSettings)\n                EditorSettings.lineEndingsForNewScripts = (LineEndingsMode)popupIndex;\n        }\n\n        [SettingsProvider]\n        internal static SettingsProvider CreateProjectSettingsProvider()\n        {\n            var provider = AssetSettingsProvider.CreateProviderFromAssetPath(\n                \"Project/Editor\", \"ProjectSettings/EditorSettings.asset\",\n                SettingsProvider.GetSearchKeywordsFromGUIContentProperties<Content>());\n            return provider;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Enlighten/LightmapParameters.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEngine.Rendering;\nusing System;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(LightmapParameters))]\n    [CanEditMultipleObjects]\n    class LightmapParametersEditor : Editor\n    {\n        SerializedProperty  m_Resolution;\n        SerializedProperty  m_ClusterResolution;\n        SerializedProperty  m_IrradianceBudget;\n        SerializedProperty  m_IrradianceQuality;\n        SerializedProperty  m_BackFaceTolerance;\n        SerializedProperty  m_ModellingTolerance;\n        SerializedProperty  m_EdgeStitching;\n        SerializedProperty  m_SystemTag;\n        SerializedProperty  m_IsTransparent;\n\n        SerializedProperty  m_Pushoff;\n        SerializedProperty  m_BakedLightmapTag;\n        SerializedProperty  m_LimitLightmapCount;\n        SerializedProperty  m_LightmapMaxCount;\n\n        SerializedProperty  m_AntiAliasingSamples;\n\n        SavedBool m_RealtimeGISettings;\n        SavedBool m_BakedGISettings;\n        SavedBool m_GeneralParametersSettings;\n\n        public void OnEnable()\n        {\n            m_Resolution                = serializedObject.FindProperty(\"resolution\");\n            m_ClusterResolution         = serializedObject.FindProperty(\"clusterResolution\");\n            m_IrradianceBudget          = serializedObject.FindProperty(\"irradianceBudget\");\n            m_IrradianceQuality         = serializedObject.FindProperty(\"irradianceQuality\");\n            m_BackFaceTolerance         = serializedObject.FindProperty(\"backFaceTolerance\");\n            m_ModellingTolerance        = serializedObject.FindProperty(\"modellingTolerance\");\n            m_EdgeStitching             = serializedObject.FindProperty(\"edgeStitching\");\n            m_IsTransparent             = serializedObject.FindProperty(\"isTransparent\");\n            m_SystemTag                 = serializedObject.FindProperty(\"systemTag\");\n            m_AntiAliasingSamples       = serializedObject.FindProperty(\"antiAliasingSamples\");\n            m_BakedLightmapTag          = serializedObject.FindProperty(\"bakedLightmapTag\");\n            m_Pushoff                   = serializedObject.FindProperty(\"pushoff\");\n            m_LimitLightmapCount        = serializedObject.FindProperty(\"limitLightmapCount\");\n            m_LightmapMaxCount          = serializedObject.FindProperty(\"maxLightmapCount\");\n\n            m_RealtimeGISettings        = new SavedBool(\"LightmapParameters.ShowRealtimeGISettings\", true);\n            m_BakedGISettings           = new SavedBool(\"LightmapParameters.ShowBakedGISettings\", true);\n            m_GeneralParametersSettings = new SavedBool(\"LightmapParameters.ShowGeneralParametersSettings\", true);\n        }\n\n        public override bool UseDefaultMargins()\n        {\n            return false;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            // realtime settings\n            if (SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime))\n            {\n                m_RealtimeGISettings.value = EditorGUILayout.FoldoutTitlebar(m_RealtimeGISettings.value, Styles.precomputedRealtimeGIContent, true);\n                if (m_RealtimeGISettings.value)\n                {\n                    ++EditorGUI.indentLevel;\n\n                    EditorGUILayout.PropertyField(m_Resolution, Styles.resolutionContent);\n                    EditorGUILayout.Slider(m_ClusterResolution, 0.1F, 1.0F, Styles.clusterResolutionContent);\n                    EditorGUILayout.IntSlider(m_IrradianceBudget, 32, 2048, Styles.irradianceBudgetContent);\n                    if (m_IrradianceQuality.hasMultipleDifferentValues)\n                    {\n                        EditorGUI.BeginChangeCheck();\n                        EditorGUI.showMixedValue = true;\n\n                        int newValue = (int) EditorGUILayout.LogarithmicIntSlider(Styles.irradianceQualityContent, value: m_IrradianceQuality.intValue, leftValue: 512, rightValue: 131072, logbase: 2, 512, 131072);\n                        if (EditorGUI.EndChangeCheck())\n                            m_IrradianceQuality.intValue = newValue;\n                        \n                        EditorGUI.showMixedValue = false;\n                    }\n                    else\n                        m_IrradianceQuality.intValue = EditorGUILayout.LogarithmicIntSlider(Styles.irradianceQualityContent, value: m_IrradianceQuality.intValue, leftValue: 512, rightValue: 131072, logbase: 2, 512, 131072);\n                    EditorGUILayout.Slider(m_ModellingTolerance, 0.0f, 1.0f, Styles.modellingToleranceContent);\n                    EditorGUILayout.PropertyField(m_EdgeStitching, Styles.edgeStitchingContent);\n                    EditorGUILayout.PropertyField(m_IsTransparent, Styles.isTransparent);\n                    EditorGUILayout.PropertyField(m_SystemTag, Styles.systemTagContent);\n                    EditorGUILayout.Space();\n\n                    --EditorGUI.indentLevel;\n                }\n            }\n\n            m_BakedGISettings.value = EditorGUILayout.FoldoutTitlebar(m_BakedGISettings.value, Styles.bakedGIContent, true);\n\n            if (m_BakedGISettings.value)\n            {\n                EditorGUI.indentLevel++;\n                if (m_AntiAliasingSamples.hasMultipleDifferentValues)\n                {\n                    EditorGUI.BeginChangeCheck();\n                    EditorGUI.showMixedValue = true;\n\n                    int fieldValue = EditorGUILayout.IntPopup(Styles.antiAliasingSamplesContent, m_AntiAliasingSamples.intValue, Styles.antiAliasingSamplesStrings, Styles.antiAliasingSampleValues);\n\n                    if (EditorGUI.EndChangeCheck())\n                        m_AntiAliasingSamples.intValue = fieldValue;\n                    \n                    EditorGUI.showMixedValue = false;\n                }\n\n                else\n                {\n                    int fieldValue = EditorGUILayout.IntPopup(Styles.antiAliasingSamplesContent, m_AntiAliasingSamples.intValue, Styles.antiAliasingSamplesStrings, Styles.antiAliasingSampleValues);\n                    m_AntiAliasingSamples.intValue = fieldValue;\n                }\n                \n                const float minPushOff = 0.0001f; // Keep in sync with PLM_MIN_PUSHOFF\n                EditorGUILayout.Slider(m_Pushoff, minPushOff, 1.0f, Styles.pushoffContent);\n                EditorGUILayout.PropertyField(m_BakedLightmapTag, Styles.bakedLightmapTagContent);\n                m_LimitLightmapCount.boolValue = EditorGUILayout.Toggle(Styles.limitLightmapCount, m_LimitLightmapCount.boolValue);\n                if (m_LimitLightmapCount.boolValue)\n                {\n                    EditorGUI.indentLevel++;\n                    EditorGUILayout.PropertyField(m_LightmapMaxCount, Styles.lightmapMaxCount);\n                    EditorGUI.indentLevel--;\n                }\n                EditorGUI.indentLevel--;\n            }\n            \n            m_GeneralParametersSettings.value = EditorGUILayout.FoldoutTitlebar(m_GeneralParametersSettings.value, Styles.generalGIContent, true);\n            if (m_GeneralParametersSettings.value)\n            {\n                ++EditorGUI.indentLevel;\n                EditorGUILayout.Slider(m_BackFaceTolerance, 0.0f, 1.0f, Styles.backFaceToleranceContent);\n                --EditorGUI.indentLevel;\n            }\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        internal override void OnHeaderControlsGUI()\n        {\n            GUILayoutUtility.GetRect(10, 10, 16, 16, EditorStyles.layerMaskField);\n            GUILayout.FlexibleSpace();\n        }\n\n        private class Styles\n        {\n            public static readonly int[] antiAliasingSampleValues = (int[]) Enum.GetValues(typeof(LightmapParameters.AntiAliasingSamples));\n            public static readonly GUIContent[] antiAliasingSamplesStrings =\n            {\n                EditorGUIUtility.TrTextContent(\"1\"),\n                EditorGUIUtility.TrTextContent(\"4\"),\n                EditorGUIUtility.TrTextContent(\"16\")\n            };\n\n            public static readonly GUIContent generalGIContent = EditorGUIUtility.TrTextContent(\"General Parameters\", \"Settings used in both Precomputed Realtime Global Illumination and Baked Global Illumination.\");\n            public static readonly GUIContent precomputedRealtimeGIContent = EditorGUIUtility.TrTextContent(\"Realtime Global Illumination\", \"Settings used in Precomputed Realtime Global Illumination where it is precomputed how indirect light can bounce between static objects, but the final lighting is done at runtime. Lights, ambient lighting in addition to the materials and emission of static objects can still be changed at runtime. Only static objects can affect GI by blocking and bouncing light, but non-static objects can receive bounced light via light probes.\");  // Reuse the label from the Lighting window\n            public static readonly GUIContent resolutionContent = EditorGUIUtility.TrTextContent(\"Resolution\", \"Realtime lightmap resolution in texels per world unit. This value is multiplied by the realtime resolution in the Lighting window to give the output lightmap resolution. This should generally be an order of magnitude less than what is common for baked lightmaps to keep the precompute time manageable and the performance at runtime acceptable. Note that if this is made more fine-grained, then the Irradiance Budget will often need to be increased too, to fully take advantage of this increased detail.\");\n            public static readonly GUIContent clusterResolutionContent = EditorGUIUtility.TrTextContent(\"Cluster Resolution\", \"The ratio between the resolution of the clusters with which light bounce is calculated and the resolution of the output lightmaps that sample from these.\");\n            public static readonly GUIContent irradianceBudgetContent = EditorGUIUtility.TrTextContent(\"Irradiance Budget\", \"The amount of data used by each texel in the output lightmap. Specifies how fine-grained a view of the scene an output texel has. Small values mean more averaged out lighting, since the light contributions from more clusters are treated as one. Affects runtime memory usage and to a lesser degree runtime CPU usage.\");\n            public static readonly GUIContent irradianceQualityContent = EditorGUIUtility.TrTextContent(\"Irradiance Quality\", \"The number of rays to cast to compute which clusters affect a given output lightmap texel - the granularity of how this is saved is defined by the Irradiance Budget. Affects the speed of the precomputation but has no influence on runtime performance.\");\n            public static readonly GUIContent backFaceToleranceContent = EditorGUIUtility.TrTextContent(\"Backface Tolerance\", \"Defines the percentage of rays which must hit front-facing geometry for the lightmapper to consider a texel valid. Increasing this number increases the likelihood that texels will be invalidated when backfaces can be seen. Invalid texels will then receive dilation.\");\n            public static readonly GUIContent modellingToleranceContent = EditorGUIUtility.TrTextContent(\"Modelling Tolerance\", \"Maximum size of gaps that can be ignored for GI.\");\n            public static readonly GUIContent edgeStitchingContent = EditorGUIUtility.TrTextContent(\"Edge Stitching\", \"If enabled, ensures that UV charts (aka UV islands) in the generated lightmaps blend together where they meet so there is no visible seam between them.\");\n            public static readonly GUIContent systemTagContent = EditorGUIUtility.TrTextContent(\"System Tag\", \"Systems are groups of objects whose lightmaps are in the same atlas. It is also the granularity at which dependencies are calculated. Multiple systems are created automatically if the scene is big enough, but it can be helpful to be able to split them up manually for e.g. streaming in sections of a level. The system tag lets you force an object into a different realtime system even though all the other parameters are the same.\");\n            public static readonly GUIContent bakedGIContent = EditorGUIUtility.TrTextContent(\"Baked Global Illumination\", \"Settings used in Baked Global Illumination where direct and indirect lighting for static objects is precalculated and saved (baked) into lightmaps for use at runtime. This is useful when lights are known to be static, for mobile, for low end devices and other situations where there is not enough processing power to use Precomputed Realtime GI. You can toggle on each light whether it should be included in the bake.\");  // Reuse the label from the Lighting window\n            public static readonly GUIContent antiAliasingSamplesContent = EditorGUIUtility.TrTextContent(\"Anti-aliasing Samples\", \"How many samples to use when antialiasing lightmap texels. Ray positions and normals buffers are also increased in size by this value. Higher values improve lightmap quality but also multiply memory usage when baking. A value of 1 disables supersampling.\");\n            public static readonly GUIContent isTransparent = EditorGUIUtility.TrTextContent(\"Is Transparent\", \"If enabled, the object appears transparent during GlobalIllumination lighting calculations. Backfaces are not contributing to and light travels through the surface. This is useful for emissive invisible surfaces.\");\n            public static readonly GUIContent pushoffContent = EditorGUIUtility.TrTextContent(\"Pushoff\", \"The amount to push off geometry for ray tracing, in modelling units. It is applied to all baked light maps, so it will affect direct light, indirect light and AO. Useful for getting rid of unwanted AO or shadowing.\");\n            public static readonly GUIContent bakedLightmapTagContent = EditorGUIUtility.TrTextContent(\"Baked Tag\", \"An integer that lets you force an object into a different baked lightmap even though all the other parameters are the same. This can be useful e.g. when streaming in sections of a level.\");\n            public static readonly GUIContent limitLightmapCount = EditorGUIUtility.TrTextContent(\"Limit Lightmap Count\", \"If enabled, objects with the same baked GI settings will be packed into a specified number of lightmaps. This may reduce the objects' lightmap resolution.\");\n            public static readonly GUIContent lightmapMaxCount = EditorGUIUtility.TrTextContent(\"Max Lightmaps\", \"The maximum number of lightmaps into which objects will be packed.\");\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/FontInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\n\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(Font))]\n    [CanEditMultipleObjects]\n    internal class FontInspector : Editor\n    {\n        public override void OnInspectorGUI()\n        {\n            foreach (Object o in targets)\n            {\n                // Dont draw the default inspector for imported font assets.\n                // It can be very slow when there is a lot of embedded font data,\n                // and the presented information is not useful to the user anyways.\n                // We still need it for editable, \"Custom Font\" assets, though.\n                if (o.hideFlags == HideFlags.NotEditable)\n                    return;\n            }\n\n            DrawDefaultInspector();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/GameObjectInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing UnityEditor.SceneManagement;\nusing UnityObject = UnityEngine.Object;\nusing UnityEditor.Experimental;\nusing System.IO;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(GameObject))]\n    [CanEditMultipleObjects]\n    internal class GameObjectInspector : Editor\n    {\n        SerializedProperty m_Name;\n        SerializedProperty m_IsActive;\n        SerializedProperty m_Layer;\n        SerializedProperty m_Tag;\n        SerializedProperty m_StaticEditorFlags;\n        SerializedProperty m_Icon;\n        string m_GOPreviousName;\n        bool m_SerializedObjectInitialized;\n\n        internal override void PostSerializedObjectCreation()\n        {\n            if (m_SerializedObjectInitialized)\n            {\n                m_Name = serializedObject.FindProperty(\"m_Name\");\n                m_IsActive = serializedObject.FindProperty(\"m_IsActive\");\n                m_Layer = serializedObject.FindProperty(\"m_Layer\");\n                m_Tag = serializedObject.FindProperty(\"m_TagString\");\n                m_StaticEditorFlags = serializedObject.FindProperty(\"m_StaticEditorFlags\");\n                m_Icon = serializedObject.FindProperty(\"m_Icon\");\n            }\n        }\n\n        static class Styles\n        {\n            public static GUIContent typelessIcon = EditorGUIUtility.IconContent(\"Prefab Icon\");\n            public static GUIContent overridesContent = EditorGUIUtility.TrTextContent(\"Overrides\");\n            public static GUIContent staticContent = EditorGUIUtility.TrTextContent(\"Static\", \"Enable the checkbox to mark this GameObject as static for all systems.\\n\\nDisable the checkbox to mark this GameObject as not static for all systems.\\n\\nUse the drop-down menu to mark as this GameObject as static or not static for individual systems.\");\n            public static GUIContent layerContent = EditorGUIUtility.TrTextContent(\"Layer\", \"The layer that this GameObject is in.\\n\\nChoose Add Layer... to edit the list of available layers.\");\n            public static GUIContent tagContent = EditorGUIUtility.TrTextContent(\"Tag\", \"The tag that this GameObject has.\\n\\nChoose Untagged to remove the current tag.\\n\\nChoose Add Tag... to edit the list of available tags.\");\n            public static GUIContent staticPreviewContent = EditorGUIUtility.TrTextContent(\"Static Preview\", \"This asset is greater than 8MB so, by default, the Asset Preview displays a static preview.\\nTo view the asset interactively, click the Asset Preview.\");\n\n            public static float tagFieldWidth = EditorGUI.CalcPrefixLabelWidth(Styles.tagContent, EditorStyles.boldLabel);\n            public static float layerFieldWidth = EditorGUI.CalcPrefixLabelWidth(Styles.layerContent, EditorStyles.boldLabel);\n\n            public static GUIStyle staticDropdown = \"StaticDropdown\";\n            public static GUIStyle tagPopup = new GUIStyle(EditorStyles.popup);\n            public static GUIStyle layerPopup = new GUIStyle(EditorStyles.popup);\n            public static GUIStyle overridesDropdown = new GUIStyle(\"MiniPullDown\");\n            public static GUIStyle prefabButtonsHorizontalLayout = new GUIStyle { fixedHeight = 17, margin = new RectOffset { top = 1, bottom = 1 } };\n\n            public static GUIContent goTypeLabelMultiple = EditorGUIUtility.TrTextContent(\"Multiple\");\n            private static GUIContent regularPrefab = EditorGUIUtility.TrTextContent(\"Prefab\");\n            private static GUIContent disconnectedPrefab = EditorGUIUtility.TrTextContent(\"Prefab\", \"You have broken the prefab connection. Changes to the prefab will not be applied to this object before you Apply or Revert.\");\n            private static GUIContent modelPrefab = EditorGUIUtility.TrTextContent(\"Prefab\");\n            private static GUIContent disconnectedModelPrefab =  EditorGUIUtility.TrTextContent(\"Prefab\", \"You have broken the prefab connection. Changes to the model will not be applied to this object before you Revert.\");\n            private static GUIContent variantPrefab = EditorGUIUtility.TrTextContent(\"Prefab\");\n            private static GUIContent disconnectedVariantPrefab = EditorGUIUtility.TrTextContent(\"Prefab\", \"You have broken the prefab connection. Changes to the prefab will not be applied to this object before you Apply or Revert.\");\n            private static GUIContent missingPrefabAsset = EditorGUIUtility.TrTextContent(\"Prefab\", \"The source Prefab or Model has been deleted.\");\n            public static GUIContent openModel = EditorGUIUtility.TrTextContent(\"Open\", \"Open Model in external tool.\");\n            public static GUIContent openPrefab = EditorGUIUtility.TrTextContent(\"Open\", \"Open Prefab Asset '{0}'\\nPress modifier key [Alt] to open in isolation.\");\n            public static GUIContent tooltipForObjectFieldForRootInPrefabContents = EditorGUIUtility.TrTextContent(\"\", \"Replacing the root Prefab instance in a Variant is not supported since it will break all overrides for existing instances of this Variant, including their positions and rotations.\");\n            public static GUIContent tooltipForObjectFieldForNestedPrefabs = EditorGUIUtility.TrTextContent(\"\", \"You can only replace outermost Prefab instances. Open Prefab Mode to replace a nested Prefab instance.\");\n            public static string selectString = L10n.Tr(\"Select\");\n\n            public static readonly float kIconSize = 24;\n            public static readonly float column1Width = kIconSize + Styles.tagFieldWidth + 10;\n\n            // Matrix based on two enums:\n            // Columns correspond to PrefabTypeUtility.PrefabAssetType (see comments above rows).\n            // Rows correspond to PrefabTypeUtility.PrefabInstanceStatus (None, Connected, Disconnected, Missing).\n            // If missing, both enums will be \"Missing\".\n            static public GUIContent[,] goTypeLabel =\n            {\n                // None\n                { null, null, null, null },\n                // Prefab\n                { regularPrefab, regularPrefab, disconnectedPrefab, null },\n                // Model\n                { modelPrefab , modelPrefab, disconnectedModelPrefab, null},\n                // Variant\n                { variantPrefab, variantPrefab, disconnectedVariantPrefab, null },\n                // Missing\n                { null, null, null, missingPrefabAsset }\n            };\n\n            static Styles()\n            {\n                // Seems to be a bug in the way controls with margin internal to layout groups with padding calculate position. We'll work around it here.\n                layerPopup.margin.right = 0;\n                overridesDropdown.margin.right = 0;\n            }\n        }\n\n        const long kMaxPreviewFileSizeInKB = 8000; // 8 MB\n\n        class PreviewData : IDisposable\n        {\n            bool m_Disposed;\n\n            public readonly PreviewRenderUtility renderUtility;\n            public GameObject gameObject { get; private set; }\n\n            public string prefabAssetPath { get; private set; }\n\n            public Bounds renderableBounds { get; private set; }\n\n            public bool useStaticAssetPreview { get; set; }\n\n            public PreviewData(UnityObject targetObject, bool creatingStaticPreview = false)\n            {\n                renderUtility = new PreviewRenderUtility();\n                renderUtility.camera.fieldOfView = 30.0f;\n                if (!creatingStaticPreview)\n                    useStaticAssetPreview = IsPrefabFileTooLargeForInteractivePreview(targetObject);\n                if (!useStaticAssetPreview)\n                    UpdateGameObject(targetObject);\n            }\n\n            public void UpdateGameObject(UnityObject targetObject)\n            {\n                UnityObject.DestroyImmediate(gameObject);\n                gameObject = EditorUtility.InstantiateForAnimatorPreview(targetObject);\n                renderUtility.AddManagedGO(gameObject);\n                renderableBounds = GetRenderableBounds(gameObject);\n            }\n\n            // Very large prefabs takes too long to instantiate for the interactive preview so we\n            // fall back to the static preview for such prefabs\n            bool IsPrefabFileTooLargeForInteractivePreview(UnityObject prefabObject)\n            {\n                string prefabAssetPath = AssetDatabase.GetAssetPath(prefabObject);\n                if (string.IsNullOrEmpty(prefabAssetPath))\n                    return false;\n\n                string guidString = AssetDatabase.AssetPathToGUID(prefabAssetPath);\n                if (string.IsNullOrEmpty(guidString))\n                    return false;\n\n                var artifactKey = new ArtifactKey(new GUID(guidString));\n                var artifactID = AssetDatabaseExperimental.LookupArtifact(artifactKey);\n                // The artifactID can be invalid if we are in the middle of an AssetDatabase.Refresh.\n                if (!artifactID.isValid)\n                    return false;\n                AssetDatabaseExperimental.GetArtifactPaths(artifactID, out var paths);\n                if (paths.Length != 1)\n                {\n                    Array.Sort(paths);\n                    int validatedPathCount = 1;\n                    for (int i = 1; i < paths.Length; i++)\n                    {\n                        if (paths[i].EndsWith(\".materialinfo\") || paths[i].EndsWith(\".importpathinfo\") || paths[i].EndsWith(\".alphapathinfo\"))\n                            validatedPathCount++;\n                    }\n\n                    if (validatedPathCount != paths.Length)\n                    {\n                        return false;\n                    }\n                }\n\n                string importedPrefabPath = Path.GetFullPath(paths[0]);\n                if (!System.IO.File.Exists(importedPrefabPath))\n                {\n                    Debug.LogError(\"Could not find prefab artifact on disk\");\n                    return false;\n                }\n\n                long length = new System.IO.FileInfo(importedPrefabPath).Length;\n                long fileSizeInKB = length / 1024;\n\n                // Keep for debugging\n                //Debug.Log(\"Imported prefab: \" + prefabAssetPath + \". File size: \" + fileSizeInKB + \" KB\" + \" (guid \" + importedPrefabPath + \")\");\n\n                return fileSizeInKB > kMaxPreviewFileSizeInKB;\n            }\n\n            public void Dispose()\n            {\n                if (m_Disposed)\n                    return;\n                renderUtility.Cleanup();\n                UnityObject.DestroyImmediate(gameObject);\n                gameObject = null;\n                m_Disposed = true;\n            }\n        }\n\n        Dictionary<int, PreviewData> m_PreviewInstances = new Dictionary<int, PreviewData>();\n        Dictionary<int, Texture> m_PreviewCache;\n        Vector2 m_PreviewDir;\n        Vector2 m_StaticPreviewLabelSize;\n        Rect m_PreviewRect;\n\n        [Flags]\n        enum ButtonStates\n        {\n            None = 0,\n            Openable = 1 << 0,\n            Selectable = 1 << 1,\n            CanShowOverrides = 1 << 2,\n        }\n\n        ButtonStates m_ButtonStates;\n        bool m_PlayModeObjects;\n        bool m_IsAsset;\n        bool m_ImmutableSelf;\n        bool m_IsMissingArtifact;\n        bool m_IsVariantParentMissingOrCorrupted;\n        bool m_IsPrefabInstanceAnyRoot;\n        bool m_IsPrefabInstanceOutermostRoot;\n        bool m_IsAssetRoot;\n        bool m_AllOfSamePrefabType = true;\n        GameObject m_AllPrefabInstanceRootsAreFromThisAsset;\n        bool m_IsInstanceRootInPrefabContents;\n        bool m_HasRenderableParts = true;\n        GUIContent m_OpenPrefabContent;\n        GUIContent m_SelectedObjectCountContent;\n        GameObject m_MissingGameObject;\n\n        public void OnEnable()\n        {\n            if (EditorSettings.defaultBehaviorMode == EditorBehaviorMode.Mode2D)\n                m_PreviewDir = new Vector2(0, 0);\n            else\n            {\n                m_PreviewDir = new Vector2(120, -20);\n\n                //Fix for FogBugz case : 1364821 Inspector Model Preview orientation is reversed when Bake Axis Conversion is enabled\n                UnityObject importedObject = PrefabUtility.IsPartOfVariantPrefab(target)\n                    ? PrefabUtility.GetCorrespondingObjectFromSource(target) as GameObject\n                    : target;\n\n                var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(importedObject)) as ModelImporter;\n                if (importer && importer.bakeAxisConversion)\n                {\n                    m_PreviewDir += new Vector2(180,0);\n                }\n            }\n\n\n            m_StaticPreviewLabelSize = new Vector2(0, 0);\n\n            m_Name = serializedObject.FindProperty(\"m_Name\");\n            m_IsActive = serializedObject.FindProperty(\"m_IsActive\");\n            m_Layer = serializedObject.FindProperty(\"m_Layer\");\n            m_Tag = serializedObject.FindProperty(\"m_TagString\");\n            m_StaticEditorFlags = serializedObject.FindProperty(\"m_StaticEditorFlags\");\n            m_Icon = serializedObject.FindProperty(\"m_Icon\");\n            m_SerializedObjectInitialized = true;\n\n            SetSelectedObjectCountLabelContent();\n            CalculatePrefabStatus();\n            CaculateHasRenderableParts();\n\n            m_MissingGameObject = EditorUtility.CreateGameObjectWithHideFlags(\"Missing GameObject for Object Field\", HideFlags.HideAndDontSave);\n            DestroyImmediate(m_MissingGameObject);\n\n            m_PreviewCache = new Dictionary<int, Texture>();\n\n            if (EditorUtility.IsPersistent(target))\n                AssetEvents.assetsChangedOnHDD += OnAssetsChangedOnHDD;\n        }\n\n        void CalculatePrefabStatus()\n        {\n            m_PlayModeObjects = false;\n            m_IsAsset = false;\n            m_ImmutableSelf = false;\n            m_IsMissingArtifact = false;\n            m_ButtonStates = ButtonStates.Openable | ButtonStates.Selectable | ButtonStates.CanShowOverrides;\n            m_IsVariantParentMissingOrCorrupted = false;\n            m_IsPrefabInstanceAnyRoot = true;\n            m_IsPrefabInstanceOutermostRoot = true;\n            m_AllOfSamePrefabType = true;\n            m_IsAssetRoot = false;\n            PrefabAssetType firstType = PrefabUtility.GetPrefabAssetType(targets[0]);\n            PrefabInstanceStatus firstStatus = PrefabUtility.GetPrefabInstanceStatus(targets[0]);\n            m_OpenPrefabContent = null;\n            m_AllPrefabInstanceRootsAreFromThisAsset = PrefabUtility.GetOriginalSourceOrVariantRoot(targets[0]);\n            m_IsInstanceRootInPrefabContents = false;\n\n            foreach (var o in targets)\n            {\n                var go = (GameObject)o;\n                if (m_AllOfSamePrefabType)\n                {\n                    PrefabAssetType type = PrefabUtility.GetPrefabAssetType(go);\n                    PrefabInstanceStatus status = PrefabUtility.GetPrefabInstanceStatus(go);\n                    if (type != firstType || status != firstStatus)\n                        m_AllOfSamePrefabType = false;\n                }\n\n                if (Application.IsPlaying(go))\n                    m_PlayModeObjects = true;\n                if (m_IsPrefabInstanceAnyRoot)\n                {\n                    if (!PrefabUtility.IsAnyPrefabInstanceRoot(go))\n                    {\n                        m_IsPrefabInstanceAnyRoot = false; // Conservative is false if any is false\n                    }\n                }\n                if (m_IsPrefabInstanceOutermostRoot)\n                {\n                    if (!m_IsPrefabInstanceAnyRoot || !PrefabUtility.IsOutermostPrefabInstanceRoot(go))\n                    {\n                        m_IsPrefabInstanceOutermostRoot = false; // Conservative is false if any is false\n                    }\n                }\n\n                if (m_AllPrefabInstanceRootsAreFromThisAsset != null && PrefabUtility.GetOriginalSourceOrVariantRoot(go) != m_AllPrefabInstanceRootsAreFromThisAsset)\n                    m_AllPrefabInstanceRootsAreFromThisAsset = null;\n\n                if (m_IsPrefabInstanceOutermostRoot && targets.Length == 1)\n                {\n                    if (PrefabStageUtility.IsGameObjectThePrefabRootInAnyPrefabStage(go))\n                        m_IsInstanceRootInPrefabContents = true; // Replacing base instance in a Variant will break all overrides of existing instances of the Variant\n                }\n\n                if (PrefabUtility.IsPartOfPrefabAsset(go))\n                {\n                    m_IsAsset = true; // Conservative is true if any is true\n                    if (go.transform.parent == null)\n                        m_IsAssetRoot = true;\n                }\n\n                if (m_IsAsset)\n                {\n                    if (PrefabUtility.IsPartOfImmutablePrefab(go))\n                    {\n                        m_ImmutableSelf = true; // Conservative is true if any is true\n                    }\n                }\n\n                if (PrefabUtility.IsPrefabAssetMissing(go))\n                {\n                    m_IsMissingArtifact = true;\n\n                    m_ButtonStates &= ~ButtonStates.CanShowOverrides;\n\n                    var brokenAsset = GetMainAssetFromBrokenPrefabInstanceRoot(go) as BrokenPrefabAsset;\n                    if(brokenAsset == null)\n                        m_ButtonStates = ButtonStates.None;\n                    else\n                    {\n                        if (brokenAsset.isVariant)\n                            m_IsVariantParentMissingOrCorrupted = true;\n                        else if (!brokenAsset.isPrefabFileValid)\n                            m_ButtonStates &= ~ButtonStates.Openable;\n                    }\n                }\n            }\n        }\n\n        internal void SetSelectedObjectCountLabelContent()\n        {\n            m_SelectedObjectCountContent = new GUIContent($\"({targets.Length})\", $\"{targets.Length} Objects Selected\");\n        }\n\n        internal void OnDisable()\n        {\n            foreach (var previewData in m_PreviewInstances.Values)\n                previewData.Dispose();\n            ClearPreviewCache();\n            m_PreviewCache = null;\n\n            if (string.IsNullOrEmpty(m_Name.stringValue) && !(string.IsNullOrEmpty(m_GOPreviousName)))\n            {\n                Debug.LogWarning(\"A GameObject name cannot be set to an empty string.\");\n                m_Name.stringValue = m_GOPreviousName;\n                serializedObject.ApplyModifiedProperties();\n            }\n\n            AssetEvents.assetsChangedOnHDD -= OnAssetsChangedOnHDD;\n        }\n\n        void OnAssetsChangedOnHDD(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)\n        {\n            foreach (var importedAssetPath in importedAssets)\n                ReloadPreviewInstance(importedAssetPath);\n        }\n\n        internal override void OnForceReloadInspector()\n        {\n            base.OnForceReloadInspector();\n            CalculatePrefabStatus();\n            CaculateHasRenderableParts();\n            ReloadPreviewInstances();\n            SetSelectedObjectCountLabelContent();\n        }\n\n        void ClearPreviewCache()\n        {\n            if (m_PreviewCache == null)\n            {\n                return;\n            }\n\n            foreach (var texture in m_PreviewCache.Values)\n            {\n                DestroyImmediate(texture);\n            }\n            m_PreviewCache.Clear();\n        }\n\n        private static StaticEditorFlags[] s_StaticEditorFlagValues;\n\n        private static bool ShowMixedStaticEditorFlags(StaticEditorFlags mask)\n        {\n            uint countedBits = 0;\n            uint numFlags = 0;\n\n            if (s_StaticEditorFlagValues == null)\n            {\n                var values = Enum.GetValues(typeof(StaticEditorFlags));\n                s_StaticEditorFlagValues = new StaticEditorFlags[values.Length];\n                for (var i = 0; i < values.Length; ++i)\n                    s_StaticEditorFlagValues[i] = (StaticEditorFlags)values.GetValue(i);\n            }\n\n            foreach (var i in s_StaticEditorFlagValues)\n            {\n                numFlags++;\n                if ((mask & i) > 0)\n                    countedBits++;\n            }\n\n            //If we have more then one selected... but it is not all the flags\n            //All indicates 'everything' which means it should be a tick!\n            return countedBits > 0 && countedBits != numFlags;\n        }\n\n        public override bool UseDefaultMargins()\n        {\n            return false;\n        }\n\n        protected override void OnHeaderGUI()\n        {\n            bool enabledTemp = GUI.enabled;\n            GUI.enabled = true;\n            EditorGUILayout.BeginVertical(EditorStyles.inspectorBig);\n            GUI.enabled = enabledTemp;\n            DrawInspector();\n            EditorGUILayout.EndVertical();\n        }\n\n        public override void OnInspectorGUI() {}\n\n        internal bool DrawInspector()\n        {\n            serializedObject.Update();\n\n            GameObject go = target as GameObject;\n\n            // Don't let icon be null as it will create null reference exceptions.\n            Texture2D icon = (Texture2D)(Styles.typelessIcon.image);\n\n            // Leave iconContent to be default if multiple objects not the same type.\n            if (m_AllOfSamePrefabType)\n            {\n                icon = PrefabUtility.GetIconForGameObject(go);\n            }\n\n            // Can't do this in OnEnable since it will cause Styles static initializer to be called and\n            // access properties on EditorStyles static class before that one has been initialized.\n            if (m_OpenPrefabContent == null)\n            {\n                if (targets.Length == 1)\n                {\n                    GameObject originalSourceOrVariant = PrefabUtility.GetOriginalSourceOrVariantRoot((GameObject)target);\n                    if (originalSourceOrVariant != null)\n                        m_OpenPrefabContent = new GUIContent(\n                            Styles.openPrefab.text,\n                            string.Format(Styles.openPrefab.tooltip, originalSourceOrVariant.name));\n                }\n                if (m_OpenPrefabContent == null)\n                    m_OpenPrefabContent = new GUIContent(Styles.openPrefab.text);\n            }\n\n            EditorGUILayout.BeginHorizontal();\n            Vector2 dropDownSize = EditorGUI.GetObjectIconDropDownSize(Styles.kIconSize, Styles.kIconSize);\n            var iconRect = GUILayoutUtility.GetRect(1, 1, GUILayout.ExpandWidth(false));\n            iconRect.width = dropDownSize.x;\n            iconRect.height = dropDownSize.y;\n            EditorGUI.ObjectIconDropDown(iconRect, targets, true, icon, m_Icon);\n            DrawPostIconContent(iconRect);\n\n            using (new EditorGUI.DisabledScope(m_ImmutableSelf))\n            {\n                EditorGUILayout.BeginVertical();\n                {\n                    EditorGUILayout.BeginHorizontal();\n                    {\n                        EditorGUILayout.BeginHorizontal(GUILayout.Width(Styles.column1Width));\n                        {\n                            GUILayout.FlexibleSpace();\n\n                            // IsActive\n                            EditorGUI.PropertyField(\n                                GUILayoutUtility.GetRect(EditorStyles.toggle.padding.left, EditorGUIUtility.singleLineHeight, EditorStyles.toggle,\n                                    GUILayout.ExpandWidth(false)), m_IsActive, GUIContent.none);\n                        }\n                        EditorGUILayout.EndHorizontal();\n\n                        // Disable the name field of root GO in prefab asset\n                        using (new EditorGUI.DisabledScope(m_IsAsset && m_IsAssetRoot))\n                        {\n                            // Name\n                            // Resets the game object name when attempted to set it to an empty string\n                            if (string.IsNullOrEmpty(m_Name.stringValue) && !(string.IsNullOrEmpty(m_GOPreviousName)))\n                            {\n                                Debug.LogWarning(\"A GameObject name cannot be set to an empty string.\");\n                                m_Name.stringValue = m_GOPreviousName;\n                            }\n                            else\n                                m_GOPreviousName = m_Name.stringValue;\n\n                            EditorGUILayout.DelayedTextField(m_Name, GUIContent.none, EditorStyles.boldTextField);\n                        }\n\n                        if (targets.Length > 1)\n                        {\n                            var maxW = GUI.skin.label.CalcSize(m_SelectedObjectCountContent).x;\n                            GUILayout.Label(m_SelectedObjectCountContent, GUILayout.MaxWidth(maxW));\n                        }\n\n                        // Static flags toggle\n                        DoStaticToggleField(go);\n\n                        // Static flags dropdown\n                        DoStaticFlagsDropDown(go);\n                    }\n                    EditorGUILayout.EndHorizontal();\n\n                    EditorGUILayout.Space(EditorGUI.kControlVerticalSpacing);\n\n                    EditorGUILayout.BeginHorizontal();\n                    {\n                        // Tag\n                        GUILayout.Space(Styles.column1Width - Styles.tagFieldWidth);\n                        DoTagsField(go);\n\n                        EditorGUILayout.Space(EditorGUI.kDefaultSpacing, false);\n\n                        // Layer\n                        DoLayerField(go);\n                    }\n                    EditorGUILayout.EndHorizontal();\n                }\n                EditorGUILayout.EndVertical();\n            }\n            EditorGUILayout.EndHorizontal();\n\n            // Prefab Toolbar\n            if (EditorGUIUtility.comparisonViewMode == EditorGUIUtility.ComparisonViewMode.None)\n            {\n                EditorGUILayout.Space(EditorGUI.kControlVerticalSpacing);\n\n                DoPrefabButtons();\n            }\n\n            serializedObject.ApplyModifiedProperties();\n\n            return true;\n        }\n\n        void DoPrefixLabel(GUIContent label, GUIStyle style)\n        {\n            var rect = GUILayoutUtility.GetRect(label, style, GUILayout.ExpandWidth(false));\n\n            rect.height = Math.Max(EditorGUI.kSingleLineHeight, rect.height);\n\n            GUI.Label(rect, label, style);\n        }\n\n        void IndentToColumn1()\n        {\n            EditorGUILayout.BeginHorizontal(GUILayout.Width(Styles.column1Width));\n            GUILayout.FlexibleSpace();\n            EditorGUILayout.EndHorizontal();\n        }\n\n        bool HandleDragPrefabAssetOverObjectFieldPopupMenu(Rect rect)\n        {\n            var evt = Event.current;\n            bool perform = evt.type == EventType.DragPerform;\n            if (rect.Contains(evt.mousePosition) && (perform ||evt.type == EventType.DragUpdated))\n            {\n                DragAndDropVisualMode visualMode;\n                if (PrefabReplaceUtility.GetDragVisualModeAndShowMenuWithReplaceMenuItemsWhenNeeded((GameObject)target, true, perform, false, false, out visualMode))\n                {\n                    DragAndDrop.visualMode = visualMode;\n                    return perform;\n                }\n            }\n            return false;\n        }\n\n        void PrefabObjectField()\n        {\n            // Change Prefab asset for instance\n            if (m_IsPrefabInstanceAnyRoot)\n            {\n                EditorGUILayout.BeginHorizontal();\n                EditorGUI.showMixedValue = m_AllPrefabInstanceRootsAreFromThisAsset == null && !m_IsMissingArtifact;\n                using (var scope = new EditorGUI.ChangeCheckScope())\n                {\n                    GameObject newAsset;\n                    bool disabled = !m_IsPrefabInstanceOutermostRoot || m_IsInstanceRootInPrefabContents;\n                    using (new EditorGUI.DisabledScope(disabled))\n                    {\n                        Rect r = EditorGUILayout.GetControlRect(false, EditorGUI.kSingleLineHeight);\n                        if (HandleDragPrefabAssetOverObjectFieldPopupMenu(r))\n                        {\n                            GUIUtility.ExitGUI(); // handled by popup menu\n                        }\n                        if (m_IsMissingArtifact)\n                            newAsset = EditorGUI.ObjectField(r, m_MissingGameObject, typeof(GameObject), false) as GameObject;\n                        else\n                            newAsset = EditorGUI.ObjectField(r, m_AllPrefabInstanceRootsAreFromThisAsset, typeof(GameObject), false) as GameObject;\n                    }\n\n                    if (disabled)\n                    {\n                        // Tooltips (should have tooltips that matches each of the conditions in the above DisabledScope)\n                        var rect = EditorGUILayout.s_LastRect;\n                        if (rect.Contains(Event.current.mousePosition))\n                        {\n                            if (m_IsInstanceRootInPrefabContents)\n                                GUI.Label(rect, Styles.tooltipForObjectFieldForRootInPrefabContents);\n                            else if (!m_IsPrefabInstanceOutermostRoot)\n                                GUI.Label(rect, Styles.tooltipForObjectFieldForNestedPrefabs);\n                        }\n                    }\n\n\n                    if (scope.changed)\n                    {\n                        if (newAsset != null)\n                        {\n                            string errorMsg = string.Empty;\n                            try\n                            {\n                                PrefabUtility.ThrowIfInvalidAssetForReplacePrefabInstance(newAsset, InteractionMode.UserAction);\n                                foreach (var t in targets)\n                                    PrefabUtility.ThrowIfInvalidArgumentsForReplacePrefabInstance((GameObject)t, newAsset, false, InteractionMode.UserAction);\n                            }\n                            catch (InvalidOperationException e)\n                            {\n                                errorMsg = e.Message;\n                            }\n\n                            if (string.IsNullOrEmpty(errorMsg))\n                            {\n                                // targets are in reverse order from the Hierarchy selection so we reverse it here so we get the same result as repalcing from the Hierarchy\n                                var replaceTargets = new List<UnityObject>(targets);\n                                replaceTargets.Reverse();\n                                if (targets.Length > 1)\n                                    PrefabUtility.ReplacePrefabAssetOfPrefabInstances(replaceTargets.Select(e => (GameObject)e).ToArray(), newAsset, InteractionMode.UserAction);\n                                else\n                                    PrefabUtility.ReplacePrefabAssetOfPrefabInstance((GameObject)target, newAsset, InteractionMode.UserAction);\n                                CalculatePrefabStatus(); // Updates the cached m_FirstPrefabInstanceOutermostRootAsset to the newly selected Prefab\n                                GUIUtility.ExitGUI();\n                            }\n                            else\n                            {\n                                var gameObjectsToPing = new List<GameObject>();\n                                var assetGameObjectsWithInvalidComponents = PrefabUtility.FindGameObjectsWithInvalidComponent(newAsset);\n                                var instanceGameObjectsWithInvalidComponents = PrefabUtility.FindGameObjectsWithInvalidComponent((GameObject)target);\n\n                                if (assetGameObjectsWithInvalidComponents.Count > 0)\n                                    gameObjectsToPing.Add(assetGameObjectsWithInvalidComponents[0]);\n                                if (instanceGameObjectsWithInvalidComponents.Count > 0)\n                                    gameObjectsToPing.Add(instanceGameObjectsWithInvalidComponents[0]);\n\n                                Debug.LogWarning(errorMsg, gameObjectsToPing.Count > 0 ? gameObjectsToPing[0] : null);\n                                foreach(var go in gameObjectsToPing)\n                                    EditorGUIUtility.PingObject(go);\n                            }\n                        }\n                        else\n                        {\n                            // 'newAsset' is null: Replacing with null Asset should just be ignored (no need to show a dialog)\n                        }\n                    }\n                }\n                EditorGUI.showMixedValue = false;\n                EditorGUILayout.EndHorizontal();\n            }\n        }\n\n        private void DoPrefabButtons()\n        {\n            if (!m_IsPrefabInstanceAnyRoot || m_IsAsset)\n                return;\n\n            // Vertical spacing to group Prefab related UI from the GameObject's UI\n            EditorGUILayout.Space(12);\n\n            using (new EditorGUI.DisabledScope(m_PlayModeObjects))\n            {\n                // Prefab label and asset field\n                EditorGUILayout.BeginHorizontal();\n                PrefabAssetType singlePrefabType = PrefabUtility.GetPrefabAssetType(target);\n                PrefabInstanceStatus singleInstanceStatus = PrefabUtility.GetPrefabInstanceStatus(target);\n                GUIContent prefixLabel;\n                if (targets.Length > 1)\n                {\n                    prefixLabel = Styles.goTypeLabelMultiple;\n                }\n                else\n                {\n                    prefixLabel = Styles.goTypeLabel[(int)singlePrefabType, (int)singleInstanceStatus];\n                }\n\n                if (prefixLabel != null)\n                {\n                    EditorGUILayout.BeginHorizontal(GUILayout.Width(Styles.column1Width));\n                    GUILayout.FlexibleSpace();\n                    DoPrefixLabel(prefixLabel, EditorStyles.label);\n                    EditorGUILayout.EndHorizontal();\n                }\n                PrefabObjectField();\n                EditorGUILayout.EndHorizontal();\n\n                if (m_ButtonStates != ButtonStates.None)\n                {\n                    EditorGUILayout.Space(EditorGUI.kControlVerticalSpacing);\n                    EditorGUILayout.BeginHorizontal(Styles.prefabButtonsHorizontalLayout);\n                    IndentToColumn1();\n\n                    // Overrides Popup. Reserve space regardless of whether the button is there or not to avoid jumps in button sizes.\n                    Rect rect = GUILayoutUtility.GetRect(Styles.overridesContent, Styles.overridesDropdown);\n                    if (m_ButtonStates.HasFlag(ButtonStates.CanShowOverrides) && m_IsPrefabInstanceOutermostRoot)\n                    {\n                        if (EditorGUI.DropdownButton(rect, Styles.overridesContent, FocusType.Passive))\n                        {\n                            if (targets.Length > 1)\n                                PopupWindow.Show(rect, new PrefabOverridesWindow(targets.Select(e => (GameObject)e).ToArray()));\n                            else\n                                PopupWindow.Show(rect, new PrefabOverridesWindow((GameObject)target));\n                            GUIUtility.ExitGUI();\n                        }\n                    }\n\n                    // Spacing between buttons\n                    GUILayoutUtility.GetRect(20, 6, GUILayout.MaxWidth(30), GUILayout.MinWidth(5));\n\n                    // Select prefab\n                    if (GUILayout.Button(Styles.selectString, EditorStyles.miniButton))\n                    {\n                        HashSet<UnityObject> selectedAssets = new HashSet<UnityObject>();\n                        for (int i = 0; i < targets.Length; i++)\n                        {\n                            GameObject targetGo = targets[i] as GameObject;\n                            GameObject prefabGo = PrefabUtility.GetOriginalSourceOrVariantRoot(targetGo);\n                            if (prefabGo != null)\n                            {\n                                // Because of legacy prefab references we have to have this extra step\n                                // to make sure we ping the prefab asset correctly.\n                                // Reason is that scene files created prior to making prefabs CopyAssets\n                                // will reference prefabs as if they are serialized assets. Those references\n                                // works fine but we are not able to ping objects loaded directly from the asset\n                                // file, so we have to make sure we ping the metadata version of the prefab.\n                                var assetPath = AssetDatabase.GetAssetPath(prefabGo);\n                                selectedAssets.Add((GameObject)AssetDatabase.LoadMainAssetAtPath(assetPath));\n                            }\n                            else\n                            {\n                                UnityObject mainAsset = GetMainAssetFromBrokenPrefabInstanceRoot(targetGo);\n                                if (mainAsset != null)\n                                    selectedAssets.Add(mainAsset);\n                            }\n                        }\n\n                        Selection.objects = selectedAssets.ToArray();\n                        if (Selection.objects.Length != 0)\n                            EditorGUIUtility.PingObject(Selection.activeObject);\n                    }\n\n                    // Open Prefab\n                    using (new EditorGUI.DisabledScope(targets.Length > 1 || !m_ButtonStates.HasFlag(ButtonStates.Openable)))\n                    {\n                        if (singlePrefabType == PrefabAssetType.Model)\n                        {\n                            // Open Model Prefab\n                            if (GUILayout.Button(Styles.openModel, EditorStyles.miniButton))\n                            {\n                                GameObject asset = PrefabUtility.GetOriginalSourceOrVariantRoot(target);\n                                AssetDatabase.OpenAsset(asset);\n                                GUIUtility.ExitGUI();\n                            }\n                        }\n                        else\n                        {\n                            // Open non-Model Prefab\n                            if (GUILayout.Button(m_OpenPrefabContent, EditorStyles.miniButton))\n                            {\n                                var prefabStageMode = PrefabStageUtility.GetPrefabStageModeFromModifierKeys();\n                                UnityObject asset = null;\n                                if (!m_IsVariantParentMissingOrCorrupted)\n                                    asset = PrefabUtility.GetOriginalSourceOrVariantRoot(target);\n                                else\n                                    asset = GetMainAssetFromBrokenPrefabInstanceRoot(target as GameObject);\n                                PrefabStageUtility.OpenPrefab(AssetDatabase.GetAssetPath(asset), (GameObject)target, prefabStageMode, StageNavigationManager.Analytics.ChangeType.EnterViaInstanceInspectorOpenButton);\n                                GUIUtility.ExitGUI();\n                            }\n                        }\n                    }\n\n                    EditorGUILayout.EndHorizontal();\n                }\n            }\n        }\n\n        private void DoLayerField(GameObject go)\n        {\n            EditorGUIUtility.labelWidth = Styles.layerFieldWidth;\n            Rect layerRect = GUILayoutUtility.GetRect(GUIContent.none, Styles.layerPopup);\n            EditorGUI.BeginProperty(layerRect, GUIContent.none, m_Layer);\n            EditorGUI.BeginChangeCheck();\n            int layer = EditorGUI.LayerField(layerRect, Styles.layerContent, go.layer, Styles.layerPopup);\n            if (EditorGUI.EndChangeCheck())\n            {\n                GameObjectUtility.ShouldIncludeChildren includeChildren = GameObjectUtility.DisplayUpdateChildrenDialogIfNeeded(targets.OfType<GameObject>(),\n                    L10n.Tr(\"Change Layer\"), string.Format(L10n.Tr(\"Do you want to set layer to {0} for all child objects as well?\"), InternalEditorUtility.GetLayerName(layer)));\n                if (includeChildren != GameObjectUtility.ShouldIncludeChildren.Cancel)\n                {\n                    m_Layer.intValue = layer;\n                    SetLayer(layer, includeChildren == GameObjectUtility.ShouldIncludeChildren.IncludeChildren);\n                }\n                // Displaying the dialog to ask the user whether to update children nukes the gui state\n                EditorGUIUtility.ExitGUI();\n            }\n            EditorGUI.EndProperty();\n        }\n\n        private void DoTagsField(GameObject go)\n        {\n            string tagName = go.tag;\n            EditorGUIUtility.labelWidth = Styles.tagFieldWidth;\n            Rect tagRect = GUILayoutUtility.GetRect(GUIContent.none, Styles.tagPopup);\n            EditorGUI.BeginProperty(tagRect, GUIContent.none, m_Tag);\n            EditorGUI.BeginChangeCheck();\n            string tag = EditorGUI.TagField(tagRect, Styles.tagContent, tagName);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_Tag.stringValue = tag;\n                Undo.RecordObjects(targets, \"Change Tag of \" + targetTitle);\n                foreach (UnityObject obj in targets)\n                    (obj as GameObject).tag = tag;\n            }\n            EditorGUI.EndProperty();\n        }\n\n        private void DoStaticFlagsDropDown(GameObject go)\n        {\n            var rect = GUILayoutUtility.GetRect(GUIContent.none, Styles.staticDropdown, GUILayout.ExpandWidth(false));\n\n            rect.height = Math.Max(EditorGUIUtility.singleLineHeight, rect.height);\n\n            bool toggled = EditorGUILayout.DropdownButton(GUIContent.none, FocusType.Keyboard, Styles.staticDropdown);\n            if (toggled)\n            {\n                rect = GUILayoutUtility.topLevel.GetLast();\n                // We do not pass the serializedProperty directly, as its parent serializedObject\n                // can get destroyed when references to parent windows are lost, thus we use\n                // the target object & the path to reconstruct the property inside the window itself\n                PopupWindow.Show(rect, new StaticFieldDropdown(m_StaticEditorFlags.serializedObject.targetObjects, m_StaticEditorFlags.propertyPath));\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        private void DoStaticToggleField(GameObject go)\n        {\n            var staticRect = GUILayoutUtility.GetRect(Styles.staticContent, EditorStyles.toggle, GUILayout.ExpandWidth(false));\n\n            staticRect.height = Math.Max(EditorGUIUtility.singleLineHeight, staticRect.height);\n            staticRect.width += 3; //offset for the bold text when displaying prefab instances.\n            EditorGUI.BeginProperty(staticRect, GUIContent.none, m_StaticEditorFlags);\n            EditorGUI.BeginChangeCheck();\n            var toggleRect = staticRect;\n            EditorGUI.showMixedValue |= ShowMixedStaticEditorFlags((StaticEditorFlags)m_StaticEditorFlags.intValue);\n            // Ignore mouse clicks that are not with the primary (left) mouse button so those can be grabbed by other things later.\n            Event evt = Event.current;\n            EventType origType = evt.type;\n            bool nonLeftClick = (evt.type == EventType.MouseDown && evt.button != 0);\n            if (nonLeftClick)\n                evt.type = EventType.Ignore;\n            var toggled = EditorGUI.ToggleLeft(toggleRect, Styles.staticContent, go.isStatic);\n            if (nonLeftClick)\n                evt.type = origType;\n            EditorGUI.showMixedValue = false;\n            if (EditorGUI.EndChangeCheck())\n            {\n                SceneModeUtility.SetStaticFlags(targets, int.MaxValue, toggled);\n                serializedObject.SetIsDifferentCacheDirty();\n\n                // Displaying the dialog to ask the user whether to update children nukes the gui state (case 962453)\n                EditorGUIUtility.ExitGUI();\n            }\n            EditorGUI.EndProperty();\n        }\n\n        UnityObject[] GetObjects(bool includeChildren)\n        {\n            return SceneModeUtility.GetObjects(targets, includeChildren);\n        }\n\n        void SetLayer(int layer, bool includeChildren)\n        {\n            UnityObject[] objects = GetObjects(includeChildren);\n            Undo.RecordObjects(objects, \"Change Layer of \" + targetTitle);\n            foreach (var o in objects)\n            {\n                var go = (GameObject)o;\n                go.layer = layer;\n            }\n        }\n\n        void ReloadPreviewInstance(string prefabAssetPath)\n        {\n            foreach (var pair in m_PreviewInstances)\n            {\n                var index = pair.Key;\n                if (index > targets.Length)\n                    continue;\n\n                var previewData = pair.Value;\n                if (previewData.prefabAssetPath == prefabAssetPath)\n                {\n                    previewData.UpdateGameObject(targets[index]);\n                    ClearPreviewCache();\n                    return;\n                }\n            }\n        }\n\n        public override void ReloadPreviewInstances()\n        {\n            foreach (var pair in m_PreviewInstances)\n            {\n                var index = pair.Key;\n                if (index > targets.Length)\n                    continue;\n\n                var previewData = pair.Value;\n                if (!previewData.useStaticAssetPreview)\n                    previewData.UpdateGameObject(targets[index]);\n            }\n            ClearPreviewCache();\n        }\n\n        PreviewData GetPreviewData(bool creatingStaticPreview = false)\n        {\n            PreviewData previewData;\n            if (!m_PreviewInstances.TryGetValue(referenceTargetIndex, out previewData))\n            {\n                previewData = new PreviewData(target, creatingStaticPreview);\n                m_PreviewInstances.Add(referenceTargetIndex, previewData);\n            }\n            if (!previewData.gameObject && !previewData.useStaticAssetPreview)\n                ReloadPreviewInstances();\n            return previewData;\n        }\n\n        static readonly List<Renderer> s_RendererComponentsList = new List<Renderer>();\n\n        static bool IsRendererUsableForPreview(Renderer r)\n        {\n            switch (r)\n            {\n                case MeshRenderer mr:\n                    mr.gameObject.TryGetComponent<MeshFilter>(out var mf);\n                    if (mf == null || mf.sharedMesh == null)\n                        return false;\n                    break;\n                case SkinnedMeshRenderer skin:\n                    if (skin.sharedMesh == null)\n                        return false;\n                    break;\n                case SpriteRenderer sprite:\n                    if (sprite.sprite == null)\n                        return false;\n                    break;\n                case BillboardRenderer billboard:\n                    if (billboard.billboard == null || billboard.sharedMaterial == null)\n                        return false;\n                    break;\n            }\n            return true;\n        }\n\n        void CaculateHasRenderableParts()\n        {\n            m_HasRenderableParts = HasRenderableParts(target as GameObject);\n        }\n\n        public static bool HasRenderableParts(GameObject go)\n        {\n            if (!go)\n                return false;\n            go.GetComponentsInChildren(s_RendererComponentsList);\n            return s_RendererComponentsList.Any(IsRendererUsableForPreview);\n        }\n\n        public static Bounds GetRenderableBounds(GameObject go)\n        {\n            var b = new Bounds();\n            if (!go)\n                return b;\n            go.GetComponentsInChildren(s_RendererComponentsList);\n            foreach (var r in s_RendererComponentsList)\n            {\n                if (!IsRendererUsableForPreview(r))\n                    continue;\n                if (b.extents == Vector3.zero)\n                    b = r.bounds;\n                else\n                    b.Encapsulate(r.bounds);\n            }\n\n            return b;\n        }\n\n        private static float GetRenderableCenterRecurse(ref Vector3 center, GameObject go, int depth, int minDepth, int maxDepth)\n        {\n            if (depth > maxDepth)\n                return 0;\n\n            float ret = 0;\n\n            if (depth > minDepth)\n            {\n                // Do we have a mesh?\n                var renderer = go.GetComponent<MeshRenderer>();\n                var filter = go.GetComponent<MeshFilter>();\n                var skin = go.GetComponent<SkinnedMeshRenderer>();\n                var sprite = go.GetComponent<SpriteRenderer>();\n                var billboard = go.GetComponent<BillboardRenderer>();\n\n                if (renderer == null && filter == null && skin == null && sprite == null && billboard == null)\n                {\n                    ret = 1;\n                    center = center + go.transform.position;\n                }\n                else if (renderer != null && filter != null)\n                {\n                    // case 542145, epsilon is too small. Accept up to 1 centimeter before discarding this model.\n                    if (Vector3.Distance(renderer.bounds.center, go.transform.position) < 0.01F)\n                    {\n                        ret = 1;\n                        center = center + go.transform.position;\n                    }\n                }\n                else if (skin != null)\n                {\n                    // case 542145, epsilon is too small. Accept up to 1 centimeter before discarding this model.\n                    if (Vector3.Distance(skin.bounds.center, go.transform.position) < 0.01F)\n                    {\n                        ret = 1;\n                        center = center + go.transform.position;\n                    }\n                }\n                else if (sprite != null)\n                {\n                    if (Vector3.Distance(sprite.bounds.center, go.transform.position) < 0.01F)\n                    {\n                        ret = 1;\n                        center = center + go.transform.position;\n                    }\n                }\n                else if (billboard != null)\n                {\n                    if (Vector3.Distance(billboard.bounds.center, go.transform.position) < 0.01F)\n                    {\n                        ret = 1;\n                        center = center + go.transform.position;\n                    }\n                }\n            }\n\n            depth++;\n            // Recurse into children\n            foreach (Transform t in go.transform)\n            {\n                ret += GetRenderableCenterRecurse(ref center, t.gameObject, depth, minDepth, maxDepth);\n            }\n\n            return ret;\n        }\n\n        public static Vector3 GetRenderableCenterRecurse(GameObject go, int minDepth, int maxDepth)\n        {\n            Vector3 center = Vector3.zero;\n\n            float sum = GetRenderableCenterRecurse(ref center, go, 0, minDepth, maxDepth);\n\n            if (sum > 0)\n            {\n                center = center / sum;\n            }\n            else\n            {\n                center = go.transform.position;\n            }\n\n            return center;\n        }\n\n        public override bool HasPreviewGUI()\n        {\n            if (!EditorUtility.IsPersistent(target))\n                return false;\n\n            return HasStaticPreview();\n        }\n\n        private bool HasStaticPreview()\n        {\n            if (targets.Length > 1)\n                return true;\n\n            if (target == null)\n                return false;\n\n            return m_HasRenderableParts;\n        }\n\n        public override void OnPreviewSettings()\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture)\n                return;\n            GUI.enabled = true;\n        }\n\n        private void DoRenderPreview(PreviewData previewData)\n        {\n            var bounds = previewData.renderableBounds;\n            float halfSize = Mathf.Max(bounds.extents.magnitude, 0.0001f);\n            float distance = halfSize * 3.8f;\n\n            Quaternion rot = Quaternion.Euler(-m_PreviewDir.y, -m_PreviewDir.x, 0);\n            Vector3 pos = bounds.center - rot * (Vector3.forward * distance);\n\n            previewData.renderUtility.camera.transform.position = pos;\n            previewData.renderUtility.camera.transform.rotation = rot;\n            previewData.renderUtility.camera.nearClipPlane = distance - halfSize * 1.1f;\n            previewData.renderUtility.camera.farClipPlane = distance + halfSize * 1.1f;\n\n            previewData.renderUtility.lights[0].intensity = .7f;\n            previewData.renderUtility.lights[0].transform.rotation = rot * Quaternion.Euler(40f, 40f, 0);\n            previewData.renderUtility.lights[1].intensity = .7f;\n            previewData.renderUtility.lights[1].transform.rotation = rot * Quaternion.Euler(340, 218, 177);\n\n            previewData.renderUtility.ambientColor = new Color(.1f, .1f, .1f, 0);\n\n            previewData.renderUtility.Render(true);\n        }\n\n        public override Texture2D RenderStaticPreview(string assetPath, UnityObject[] subAssets, int width, int height)\n        {\n            if (!HasStaticPreview() || !ShaderUtil.hardwareSupportsRectRenderTexture)\n            {\n                return null;\n            }\n\n            var previewData = GetPreviewData(true);\n\n            previewData.renderUtility.BeginStaticPreview(new Rect(0, 0, width, height));\n\n            DoRenderPreview(previewData);\n\n            return previewData.renderUtility.EndStaticPreview();\n        }\n\n        void DrawAssetPreviewTexture(Rect rect)\n        {\n            Texture2D icon = AssetPreview.GetAssetPreview(target);\n            if (!icon)\n            {\n                // We have a static preview it just hasn't been loaded yet. Repaint until we have it loaded.\n                if (AssetPreview.IsLoadingAssetPreview(target.GetInstanceID()))\n                    Repaint();\n            }\n            else\n            {\n                var scaleMode = ScaleMode.ScaleToFit;\n                GUI.DrawTexture(rect, icon, scaleMode);\n\n                if (m_StaticPreviewLabelSize.x == 0.0f && m_StaticPreviewLabelSize.y == 0.0f)\n                    m_StaticPreviewLabelSize = GUI.skin.label.CalcSize(Styles.staticPreviewContent);\n\n                // Only render overlay text if there is space enough\n                if (rect.width >= m_StaticPreviewLabelSize.x && rect.height >= m_StaticPreviewLabelSize.y + GUI.skin.label.padding.vertical)\n                {\n                    using (new EditorGUI.DisabledScope(true))\n                    {\n                        GUI.Label(new Rect(rect.x, rect.yMax - (m_StaticPreviewLabelSize.y + GUI.skin.label.padding.vertical), rect.width, m_StaticPreviewLabelSize.y), Styles.staticPreviewContent, EditorStyles.centeredGreyMiniLabel);\n                    }\n                }\n            }\n        }\n\n        public override void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            var previewData = GetPreviewData();\n\n            if (previewData.useStaticAssetPreview && GUI.Button(r, GUIContent.none))\n            {\n                previewData.useStaticAssetPreview = false;\n                previewData.UpdateGameObject(target);\n            }\n\n            if (previewData.useStaticAssetPreview || !ShaderUtil.hardwareSupportsRectRenderTexture)\n            {\n                if (Event.current.type == EventType.Repaint)\n                    DrawAssetPreviewTexture(r);\n                return;\n            }\n\n            var direction = PreviewGUI.Drag2D(m_PreviewDir, r);\n            if (direction != m_PreviewDir)\n            {\n                // None of the preview are valid since the camera position has changed.\n                ClearPreviewCache();\n                m_PreviewDir = direction;\n            }\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            if (m_PreviewRect != r)\n            {\n                ClearPreviewCache();\n                m_PreviewRect = r;\n            }\n\n            var previewUtility = GetPreviewData().renderUtility;\n            Texture previewTexture;\n            if (m_PreviewCache.TryGetValue(referenceTargetIndex, out previewTexture))\n            {\n                PreviewRenderUtility.DrawPreview(r, previewTexture);\n            }\n            else\n            {\n                previewUtility.BeginPreview(r, background);\n                DoRenderPreview(previewData);\n                previewUtility.EndAndDrawPreview(r);\n                var copy = new RenderTexture(previewUtility.renderTexture);\n                var previous = RenderTexture.active;\n                Graphics.Blit(previewUtility.renderTexture, copy);\n                RenderTexture.active = previous;\n                m_PreviewCache.Add(referenceTargetIndex, copy);\n            }\n        }\n\n        // Handle dragging in scene view\n        public GameObject m_DragObject;\n        static bool s_ShouldClearSelection;\n        internal static bool s_CyclicNestingDetected;\n        static bool s_PlaceObject;\n        static Vector3 s_PlaceObjectPoint;\n        static Vector3 s_PlaceObjectNormal;\n        public void OnSceneDrag(SceneView sceneView, int index)\n        {\n            Event evt = Event.current;\n            OnSceneDragInternal(sceneView, index, evt.type, evt.mousePosition, evt.alt);\n        }\n\n        static Scene GetDestinationSceneForNewGameObjectsForSceneView(SceneView sceneView)\n        {\n            if (sceneView.customParentForNewGameObjects != null)\n                return sceneView.customParentForNewGameObjects.gameObject.scene;\n\n            if (sceneView.customScene.IsValid())\n                return sceneView.customScene;\n\n            return SceneManager.GetActiveScene();\n        }\n\n        internal void OnSceneDragInternal(SceneView sceneView, int index, EventType type, Vector2 mousePosition, bool alt)\n        {\n            GameObject go = target as GameObject;\n            if (!PrefabUtility.IsPartOfPrefabAsset(go))\n                return;\n\n            var prefabAssetRoot = go.transform.root.gameObject;\n\n            switch (type)\n            {\n                case EventType.DragUpdated:\n\n                    if (m_DragObject == null)\n                    {\n                        // While dragging the instantiated prefab we do not want to record undo for this object\n                        // this will cause a remerge of the instance since changes are undone while dragging.\n                        // The DrivenRectTransformTracker by default records Undo when used when driving\n                        // UI components. This breaks our hideflag setup below due to a remerge of the dragged instance.\n                        // StartRecordingUndo() is called on DragExited. Fixes case 1223793.\n                        DrivenRectTransformTracker.StopRecordingUndo();\n\n                        Scene destinationScene = GetDestinationSceneForNewGameObjectsForSceneView(sceneView);\n                        if (!EditorApplication.isPlaying || EditorSceneManager.IsPreviewScene(destinationScene))\n                        {\n                            m_DragObject = (GameObject)PrefabUtility.InstantiatePrefab(prefabAssetRoot, destinationScene);\n                            m_DragObject.name = go.name;\n                        }\n                        else\n                        {\n                            // Instatiate as regular GameObject in Play Mode so runtime logic\n                            // won't run into restrictions on restructuring Prefab instances.\n                            m_DragObject = Instantiate(prefabAssetRoot);\n                            SceneManager.MoveGameObjectToScene(m_DragObject, destinationScene);\n                        }\n                        m_DragObject.hideFlags = HideFlags.HideInHierarchy;\n\n                        if (HandleUtility.ignoreRaySnapObjects == null)\n                            HandleUtility.ignoreRaySnapObjects = m_DragObject.GetComponentsInChildren<Transform>();\n                        else\n                            HandleUtility.ignoreRaySnapObjects = HandleUtility.ignoreRaySnapObjects.Union(m_DragObject.GetComponentsInChildren<Transform>()).ToArray();\n\n                        PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();\n                        if (prefabStage != null)\n                        {\n                            GameObject prefab = AssetDatabase.LoadMainAssetAtPath(prefabStage.assetPath) as GameObject;\n\n                            if (prefab != null)\n                            {\n                                if (PrefabUtility.CheckIfAddingPrefabWouldResultInCyclicNesting(prefab, target))\n                                {\n                                    s_CyclicNestingDetected = true;\n                                }\n                            }\n                        }\n                    }\n\n                    DragAndDrop.visualMode = DragAndDropVisualMode.Copy;\n                    Vector3 point, normal;\n                    float offset = 0;\n\n                    if (index == 0)\n                    {\n                        s_PlaceObject = HandleUtility.PlaceObject(mousePosition, out s_PlaceObjectPoint, out s_PlaceObjectNormal);\n                    }\n\n                    point = s_PlaceObjectPoint;\n                    normal = s_PlaceObjectNormal;\n\n                    if (s_PlaceObject)\n                    {\n                        if (Tools.pivotMode == PivotMode.Center)\n                        {\n                            float geomOffset = HandleUtility.CalcRayPlaceOffset(m_DragObject.GetComponentsInChildren<Transform>(), normal);\n                            if (geomOffset != Mathf.Infinity)\n                                offset = Vector3.Dot(m_DragObject.transform.position, normal) - geomOffset;\n                        }\n                        m_DragObject.transform.position = Matrix4x4.identity.MultiplyPoint(point + (normal * offset));\n                    }\n                    else\n                    {\n                        // UUM-95510 scale the distance based on FOV to avoid very close placement at low FOVs\n                        var clampedFov = Mathf.Clamp(sceneView.camera.fieldOfView, 4f, 60f);\n                        var fovFactor = Mathf.InverseLerp(60f, 4f, clampedFov);\n                        var distanceFactor = Mathf.Pow(fovFactor, 6);\n                        var distance = (distanceFactor * 110f) + 10f;\n                        m_DragObject.transform.position = HandleUtility.GUIPointToWorldRay(mousePosition).GetPoint(distance);\n                    }\n\n                    if (alt)\n                    {\n                        if (offset != 0)\n                        {\n                            m_DragObject.transform.position = point;\n                        }\n                        m_DragObject.transform.position += prefabAssetRoot.transform.localPosition;\n                    }\n\n                    // Use prefabs original z position when in 2D mode\n                    if (sceneView.in2DMode)\n                    {\n                        Vector3 dragPosition = m_DragObject.transform.position;\n                        dragPosition.z = prefabAssetRoot.transform.position.z;\n                        m_DragObject.transform.position = dragPosition;\n                    }\n\n                    // Schedule selection clearing for when we start performing the actual drag action\n                    s_ShouldClearSelection = true;\n                    break;\n                case EventType.DragPerform:\n                    DragPerform(sceneView, m_DragObject, go);\n                    m_DragObject = null;\n                    break;\n                case EventType.DragExited:\n                    // DragExited is always fired after DragPerform so we do no need to call StartRecordingUndo\n                    // in DragPerform\n                    DrivenRectTransformTracker.StartRecordingUndo();\n\n                    if (m_DragObject)\n                    {\n                        DestroyImmediate(m_DragObject, false);\n                        HandleUtility.ignoreRaySnapObjects = null;\n                        m_DragObject = null;\n                    }\n                    s_ShouldClearSelection = false;\n                    s_CyclicNestingDetected = false;\n                    break;\n            }\n        }\n\n        internal static void DragPerform(SceneView sceneView, GameObject draggedObject, GameObject go)\n        {\n            Transform defaultParentObject = SceneView.GetDefaultParentObjectIfSet();\n            var parent = defaultParentObject != null ? defaultParentObject : sceneView.customParentForDraggedObjects;\n            string uniqueName = GameObjectUtility.GetUniqueNameForSibling(parent, draggedObject.name);\n\n            if (parent != null)\n            {\n                draggedObject.transform.SetParent(parent, true);\n            }\n\n            if (defaultParentObject == null && sceneView.customParentForDraggedObjects == null)\n            {\n                draggedObject.transform.SetAsLastSibling();\n            }\n\n            draggedObject.hideFlags = 0;\n            Undo.RegisterCreatedObjectUndo(draggedObject, \"Place \" + draggedObject.name);\n            DragAndDrop.AcceptDrag();\n\n            if (s_ShouldClearSelection)\n            {\n                Selection.objects = new[] { draggedObject };\n                s_ShouldClearSelection = false;\n            }\n            else\n            {\n                // Since this inspector code executes for each dragged GameObject we should retain\n                // selection to all of them by joining them to the previous selection list\n                Selection.objects = Selection.gameObjects.Union(new[] { draggedObject }).ToArray();\n            }\n\n            HandleUtility.ignoreRaySnapObjects = null;\n\n            if (SceneView.mouseOverWindow != null)\n                SceneView.mouseOverWindow.Focus();\n\n            if (!Application.IsPlaying(draggedObject))\n                draggedObject.name = uniqueName;\n\n            s_CyclicNestingDetected = false;\n        }\n\n        internal UnityObject GetMainAssetFromBrokenPrefabInstanceRoot(GameObject targetGo)\n        {\n            //Handle cases where you have a variant with a parent that is missing\n            var path = PrefabUtility.GetAssetPathOfSourcePrefab(targetGo);\n            var asset = AssetDatabase.LoadMainAssetAtPath(path);\n            return asset;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/GenericPresetLibraryInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class GenericPresetLibraryInspector<T> where T : ScriptableObject\n    {\n        readonly ScriptableObjectSaveLoadHelper<T> m_SaveLoadHelper;\n        readonly UnityEngine.Object m_Target;\n        readonly string m_Header;\n        readonly VerticalGrid m_Grid;\n        readonly Action<string> m_EditButtonClickedCallback;\n        private static GUIStyle s_EditButtonStyle;\n        private float m_LastRepaintedWidth = -1f;\n\n        // Configure\n        public int maxShowNumPresets { get; set; }\n        public Vector2 presetSize { get; set; }\n        public float lineSpacing { get; set; }\n        public string extension { get { return m_SaveLoadHelper.fileExtensionWithoutDot; } }\n        public bool useOnePixelOverlappedGrid { get; set; }\n        public RectOffset marginsForList { get; set; }\n        public RectOffset marginsForGrid { get; set; }\n        public PresetLibraryEditorState.ItemViewMode itemViewMode { get; set; }\n\n        public GenericPresetLibraryInspector(UnityEngine.Object target, string header, Action<string> editButtonClicked)\n        {\n            m_Target = target;\n            m_Header = header;\n            m_EditButtonClickedCallback = editButtonClicked;\n\n            string assetPath = AssetDatabase.GetAssetPath(m_Target.GetInstanceID());\n            string extension = Path.GetExtension(assetPath);\n            if (!string.IsNullOrEmpty(extension))\n                extension = extension.TrimStart('.');\n            m_SaveLoadHelper = new ScriptableObjectSaveLoadHelper<T>(extension, SaveType.Text);\n            m_Grid = new VerticalGrid();\n\n            // Default configuration\n            maxShowNumPresets = 49; // We clear some preview caches when they reach 50 (See AnimationCurvePreviewCache and GradientPreviewCache)\n            presetSize = new Vector2(14, 14);\n            lineSpacing = 1f;\n            useOnePixelOverlappedGrid = false;\n            marginsForList = new RectOffset(10, 10, 5, 5);\n            marginsForGrid = new RectOffset(10, 10, 5, 5);\n            itemViewMode = PresetLibraryEditorState.ItemViewMode.List;\n        }\n\n        public void OnDestroy()\n        {\n            PresetLibraryManager.instance.UnloadAllLibrariesFor(m_SaveLoadHelper);\n        }\n\n        public void OnInspectorGUI()\n        {\n            if (s_EditButtonStyle == null)\n            {\n                s_EditButtonStyle = new GUIStyle(EditorStyles.miniButton);\n                s_EditButtonStyle.margin.top = 7;\n            }\n\n            string assetPath = AssetDatabase.GetAssetPath(m_Target.GetInstanceID());\n            string libraryPath = Path.ChangeExtension(assetPath, null);\n            bool isInAnEditorFolder = libraryPath.Contains(\"/Editor/\");\n\n            GUILayout.BeginHorizontal();\n            GUILayout.Label(m_Header, EditorStyles.boldLabel);\n            GUILayout.FlexibleSpace();\n            if (isInAnEditorFolder && m_EditButtonClickedCallback != null && GUILayout.Button(\"Edit...\", s_EditButtonStyle))\n            {\n                if (m_EditButtonClickedCallback != null)\n                    m_EditButtonClickedCallback(libraryPath);\n            }\n            GUILayout.EndHorizontal();\n\n            GUILayout.Space(6);\n\n            if (!isInAnEditorFolder)\n            {\n                GUIContent c = EditorGUIUtility.TrTextContent(\"Preset libraries should be placed in an 'Editor' folder.\", EditorGUIUtility.warningIcon);\n                GUILayout.Label(c, EditorStyles.helpBox);\n            }\n\n            DrawPresets(libraryPath);\n        }\n\n        private void DrawPresets(string libraryPath)\n        {\n            if (GUIClip.visibleRect.width > 0)\n                m_LastRepaintedWidth = GUIClip.visibleRect.width;\n\n            if (m_LastRepaintedWidth < 0)\n            {\n                GUILayoutUtility.GetRect(1, 1); // Ensure consistent call\n                HandleUtility.Repaint(); // Wait until we have a proper width\n                return;\n            }\n\n            PresetLibrary lib = PresetLibraryManager.instance.GetLibrary(m_SaveLoadHelper, libraryPath) as PresetLibrary;\n            if (lib == null)\n            {\n                Debug.Log(\"Could not load preset library '\" + libraryPath + \"'\");\n                return;\n            }\n\n            SetupGrid(m_LastRepaintedWidth, lib.Count(), itemViewMode);\n\n\n            int showNumPresets = Mathf.Min(lib.Count(), maxShowNumPresets);\n            int hiddenNumPresets = lib.Count() - showNumPresets;\n            float contentHeight = m_Grid.CalcRect(showNumPresets - 1, 0f).yMax + (hiddenNumPresets > 0 ? 20f : 0f);\n\n            Rect reservedRect = GUILayoutUtility.GetRect(1, contentHeight);\n\n            float spaceBetweenPresetAndText = presetSize.x + 6f;\n            for (int index = 0; index < showNumPresets; ++index)\n            {\n                Rect r = m_Grid.CalcRect(index, reservedRect.y);\n                Rect presetRect = new Rect(r.x, r.y, presetSize.x, presetSize.y);\n                lib.Draw(presetRect, index);\n                if (itemViewMode == PresetLibraryEditorState.ItemViewMode.List)\n                {\n                    Rect nameRect = new Rect(r.x + spaceBetweenPresetAndText, r.y, r.width - spaceBetweenPresetAndText, r.height);\n                    string name = lib.GetName(index);\n                    GUI.Label(nameRect, name);\n                }\n            }\n            if (hiddenNumPresets > 0)\n            {\n                Rect textRect = new Rect(m_Grid.CalcRect(0, 0).x, reservedRect.y + contentHeight - 20f, reservedRect.width, 20f);\n                GUI.Label(textRect, string.Format(\"+ {0} more...\", hiddenNumPresets));\n            }\n        }\n\n        void SetupGrid(float availableWidth, int itemCount, PresetLibraryEditorState.ItemViewMode presetsViewMode)\n        {\n            m_Grid.useFixedHorizontalSpacing = useOnePixelOverlappedGrid;\n            m_Grid.fixedHorizontalSpacing = useOnePixelOverlappedGrid ? -1 : 0;\n\n            switch (presetsViewMode)\n            {\n                case PresetLibraryEditorState.ItemViewMode.Grid:\n                    m_Grid.fixedWidth = availableWidth;\n                    m_Grid.topMargin = marginsForGrid.top;\n                    m_Grid.bottomMargin = marginsForGrid.bottom;\n                    m_Grid.leftMargin = marginsForGrid.left;\n                    m_Grid.rightMargin = marginsForGrid.right;\n                    m_Grid.verticalSpacing = useOnePixelOverlappedGrid ? -1 : lineSpacing;\n                    m_Grid.minHorizontalSpacing = 8f;\n                    m_Grid.itemSize = presetSize; // no text\n                    m_Grid.InitNumRowsAndColumns(itemCount, int.MaxValue);\n                    break;\n                case PresetLibraryEditorState.ItemViewMode.List:\n                    m_Grid.fixedWidth = availableWidth;\n                    m_Grid.topMargin = marginsForList.top;\n                    m_Grid.bottomMargin = marginsForList.bottom;\n                    m_Grid.leftMargin = marginsForList.left;\n                    m_Grid.rightMargin = marginsForList.right;\n                    m_Grid.verticalSpacing = lineSpacing;\n                    m_Grid.minHorizontalSpacing = 0f;\n                    m_Grid.itemSize = new Vector2(availableWidth - m_Grid.leftMargin, presetSize.y);\n                    m_Grid.InitNumRowsAndColumns(itemCount, int.MaxValue);\n                    break;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/GradientPresetLibraryInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(GradientPresetLibrary))]\n    internal class GradientPresetLibraryEditor : Editor\n    {\n        private GenericPresetLibraryInspector<GradientPresetLibrary> m_GenericPresetLibraryInspector;\n\n        public void OnEnable()\n        {\n            m_GenericPresetLibraryInspector = new GenericPresetLibraryInspector<GradientPresetLibrary>(target, \"Gradient Preset Library\", OnEditButtonClicked);\n            m_GenericPresetLibraryInspector.presetSize = new Vector2(72, 16);\n            m_GenericPresetLibraryInspector.lineSpacing = 4f;\n        }\n\n        public void OnDestroy()\n        {\n            if (m_GenericPresetLibraryInspector != null)\n                m_GenericPresetLibraryInspector.OnDestroy();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            m_GenericPresetLibraryInspector.itemViewMode = PresetLibraryEditorState.GetItemViewMode(\"Gradient\"); // ensure in-sync\n            if (m_GenericPresetLibraryInspector != null)\n                m_GenericPresetLibraryInspector.OnInspectorGUI();\n        }\n\n        private void OnEditButtonClicked(string libraryPath)\n        {\n            GradientPicker.Show(new Gradient(), true);\n            GradientPicker.instance.currentPresetLibrary = libraryPath;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/Inspector/GraphicsSettingsInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Rendering.Settings;\nusing UnityEditor.Inspector.GraphicsSettingsInspectors;\nusing UnityEditor.UIElements;\nusing UnityEditor.UIElements.ProjectSettings;\nusing UnityEditorInternal;\nusing UnityEditor.Rendering;\nusing UnityEditor.Build.Profile;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEngine.UIElements;\nusing Button = UnityEngine.UIElements.Button;\nusing HelpBox = UnityEngine.UIElements.HelpBox;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(GraphicsSettings))]\n    internal class GraphicsSettingsInspector : ProjectSettingsBaseEditor\n    {\n        internal static class GraphicsSettingsData\n        {\n            internal const string builtIn = \"Built-In\";\n            internal const string bodyTemplateBuiltInOnly = \"UXML/ProjectSettings/GraphicsSettingsEditor-Builtin.uxml\";\n            internal const string bodyTemplateSRP = \"UXML/ProjectSettings/GraphicsSettingsEditor-SRP.uxml\";\n            internal const string helpBoxesTemplateForSRP = \"UXML/ProjectSettings/GraphicsSettingsEditor-HelpBoxes.uxml\";\n            internal const string builtInTabContent = \"UXML/ProjectSettings/GraphicsSettingsEditor-BuiltInTab.uxml\";\n\n            internal static GUIContent builtInWarningText =\n                EditorGUIUtility.TrTextContent(\"A Scriptable Render Pipeline is in use. Settings in the Built-In Render Pipeline are not currently in use.\");\n            internal static readonly string k_BuildProfileGraphicsSettingsOverrideWarning =\n                L10n.Tr(\"The current active build profile has overridden certain Graphics settings. To ensure that the correct settings are included in your build, see the Build Profiles...\");\n        }\n        internal IEnumerable<GraphicsSettingsInspectorUtility.GlobalSettingsContainer> globalSettings => m_GlobalSettings;\n\n        readonly VisibilityControllerBasedOnRenderPipeline m_VisibilityController = new();\n        TabbedView m_TabbedView;\n        VisualElement m_CurrentRoot;\n        ScrollView m_ScrollView;\n        List<GraphicsSettingsInspectorUtility.GlobalSettingsContainer> m_GlobalSettings;\n        HelpBox m_BuildProfileGraphicsSettingsOverrideWarning;\n        internal static Action OnActiveProfileGraphicsSettingsChanged;\n\n        readonly Dictionary<VisualElement, List<Label>> m_Labels = new();\n        string m_CurrentText;\n\n        bool m_FinishedInitialization;\n        int m_LastListsHash;\n        int m_GeometryChangedEventCounter;\n\n        // As we use multiple IMGUI container while porting everything to UITK we will call serializedObject.Update in first separate IMGUI container.\n        // This way we don't need to do it in each following containers.\n        VisualElement ObjectUpdater()\n        {\n            return new IMGUIContainer(() => serializedObject.Update());\n        }\n\n        internal void Reload(bool globalSettingsExist, List<GraphicsSettingsInspectorUtility.GlobalSettingsContainer> globalSettingsContainers)\n        {\n            var newHash = GraphicsSettingsInspectorUtility.ComputeRenderPipelineGlobalSettingsListHash(globalSettingsContainers);\n            if (!m_FinishedInitialization || m_LastListsHash == newHash)\n                return;\n\n            Dispose();\n            Create(m_CurrentRoot, globalSettingsExist, globalSettingsContainers);\n\n            m_LastListsHash = newHash;\n        }\n\n        internal void Create(VisualElement root, bool globalSettingsExist, List<GraphicsSettingsInspectorUtility.GlobalSettingsContainer> globalSettingsContainers)\n        {\n            m_VisibilityController.Initialize();\n            Undo.undoRedoEvent += OnUndoRedoPerformed;\n\n            m_CurrentRoot = root;\n            m_CurrentRoot.Add(ObjectUpdater());\n            m_GlobalSettings = globalSettingsContainers;\n\n            var visualTreeAsset = EditorGUIUtility.Load(globalSettingsExist ? GraphicsSettingsData.bodyTemplateSRP : GraphicsSettingsData.bodyTemplateBuiltInOnly) as VisualTreeAsset;\n            var content = visualTreeAsset.Instantiate();\n            root.Add(content);\n\n            Setup(globalSettingsExist);\n\n            m_LastListsHash = GraphicsSettingsInspectorUtility.ComputeRenderPipelineGlobalSettingsListHash(globalSettingsContainers);\n        }\n\n        internal void Dispose()\n        {\n            UserSettings.ToConfig(m_CurrentRoot);\n\n            m_Labels.Clear();\n            m_CurrentRoot.Clear();\n\n            m_VisibilityController.Clear();\n            m_VisibilityController.Dispose();\n\n            Undo.undoRedoEvent -= OnUndoRedoPerformed;\n            OnActiveProfileGraphicsSettingsChanged -= UpdateBuildProfileGraphicsSettingsOverrideWarning;\n            m_FinishedInitialization = false;\n        }\n\n        void Setup(bool globalSettingsExist)\n        {\n            m_VisibilityController.Clear();\n\n            m_CurrentRoot\n                .Query<ProjectSettingsElementWithSO>()\n                .ForEach(d => d.Initialize(serializedObject));\n\n            m_BuildProfileGraphicsSettingsOverrideWarning = m_CurrentRoot.Query<HelpBox>(\"build-profile-override-warning-help-box\");\n            m_BuildProfileGraphicsSettingsOverrideWarning.text = GraphicsSettingsData.k_BuildProfileGraphicsSettingsOverrideWarning;\n            UpdateBuildProfileGraphicsSettingsOverrideWarning();\n            OnActiveProfileGraphicsSettingsChanged += UpdateBuildProfileGraphicsSettingsOverrideWarning;\n\n            BindEnumFieldWithFadeGroup(m_CurrentRoot, \"Lightmap\", ShaderUtil.CalculateLightmapStrippingFromCurrentScene);\n            BindEnumFieldWithFadeGroup(m_CurrentRoot, \"Fog\", ShaderUtil.CalculateFogStrippingFromCurrentScene);\n            BindEnumFieldToLightProbe(m_CurrentRoot);\n\n            BindShaderPreload(m_CurrentRoot);\n\n            if (globalSettingsExist)\n            {\n                m_TabbedView = m_CurrentRoot.MandatoryQ<TabbedView>(\"PipelineSpecificSettings\");\n                GenerateTabs();\n            }\n            else\n            {\n                m_CurrentRoot.Query<GraphicsSettingsElement>()\n                    .ForEach(e =>\n                    {\n                        if (e.BuiltinOnly)\n                            m_VisibilityController.RegisterVisualElement(e, null);\n                    });\n                m_CurrentRoot.Query<BuiltInShaderElement>().ForEach(e => m_VisibilityController.RegisterVisualElement(e, null));\n                SetupTransparencySortMode(m_CurrentRoot);\n            }\n\n            GraphicsSettingsInspectorUtility.LocalizeVisualTree(m_CurrentRoot);\n\n            // Register a callback on the Geometry Change event of the content container.It will be called when the size of all children will be known.\n            m_ScrollView = m_CurrentRoot.Q<ScrollView>(\"MainScrollView\");\n            m_ScrollView.contentContainer.RegisterCallback<GeometryChangedEvent>(OnMainScrollViewGeometryChanged);\n\n            m_CurrentRoot.Bind(serializedObject);\n        }\n\n        void BindShaderPreload(VisualElement root)\n        {\n            var shaderPreloadProperty = serializedObject.FindProperty(\"m_PreloadedShaders\");\n            shaderPreloadProperty.isExpanded = false;\n\n            var shaderPreloadPropertyField = root.MandatoryQ<IMGUIContainer>(\"PreloadedShaders\");\n            shaderPreloadPropertyField.onGUIHandler = () =>\n            {\n                //for some reason, converting the display of this native array to UITK make MacOS crash when domain reload after user add a new script\n                EditorGUILayout.PropertyField(shaderPreloadProperty, EditorGUIUtility.TrTextContent(\"Preload Shaders\"));\n            };\n            \n            var delayedShaderTimeLimitProperty = serializedObject.FindProperty(\"m_PreloadShadersBatchTimeLimit\");\n            var shaderPreloadToggle = root.MandatoryQ<Toggle>(\"ShaderPreloadToggle\");\n            var delayedShaderTimeLimitGroup = root.MandatoryQ<VisualElement>(\"DelayedShaderTimeLimitGroup\");\n            var delayedShaderTimeLimit = root.MandatoryQ<IntegerField>(\"DelayedShaderTimeLimit\");\n            shaderPreloadToggle.RegisterValueChangedCallback(evt => {\n                delayedShaderTimeLimitGroup.style.display = evt.newValue ? DisplayStyle.Flex : DisplayStyle.None;\n                var newVal = evt.newValue ? delayedShaderTimeLimit.value : -1;\n                if (delayedShaderTimeLimitProperty.intValue != newVal)\n                {\n                    delayedShaderTimeLimitProperty.intValue = newVal;\n                    delayedShaderTimeLimitProperty.serializedObject.ApplyModifiedProperties();\n                }\n            });\n            delayedShaderTimeLimit.RegisterValueChangedCallback(evt =>\n            {\n                if (delayedShaderTimeLimitProperty.intValue != evt.newValue)\n                {\n                    delayedShaderTimeLimitProperty.intValue = evt.newValue;\n                    delayedShaderTimeLimitProperty.serializedObject.ApplyModifiedProperties();\n                }\n            });\n            shaderPreloadToggle.SetValueWithoutNotify(delayedShaderTimeLimitProperty.intValue >= 0);\n            delayedShaderTimeLimit.SetValueWithoutNotify(Mathf.Max(0, delayedShaderTimeLimitProperty.intValue));\n            delayedShaderTimeLimitGroup.style.display = delayedShaderTimeLimitProperty.intValue >= 0 ? DisplayStyle.Flex : DisplayStyle.None;\n            \n            var shaderTracking = root.MandatoryQ<HelpBox>(\"ShaderTrackingInfoBox\");\n            shaderTracking.schedule.Execute(() =>\n                shaderTracking.text =\n                    $\"Currently tracked: {ShaderUtil.GetCurrentShaderVariantCollectionShaderCount()} shaders {ShaderUtil.GetCurrentShaderVariantCollectionVariantCount()} total variants\").Every(500);\n\n            var saveButton = root.MandatoryQ<Button>(\"SaveShaderVariants\");\n            saveButton.clickable = new Clickable(() =>\n            {\n                var assetPath = EditorUtility.SaveFilePanelInProject(\n                    L10n.Tr(\"Save Shader Variant Collection\"),\n                    \"NewShaderVariants\",\n                    \"shadervariants\",\n                    L10n.Tr(\"Save shader variant collection\"),\n                    ProjectWindowUtil.GetActiveFolderPath());\n                if (!string.IsNullOrEmpty(assetPath))\n                    ShaderUtil.SaveCurrentShaderVariantCollection(assetPath);\n            });\n            var clearButton = root.MandatoryQ<Button>(\"ClearCurrentShaderVariants\");\n            clearButton.clickable = new Clickable(ShaderUtil.ClearCurrentShaderVariantCollection);\n        }\n\n        void GenerateTabs()\n        {\n            //Add BuiltInTab\n            var builtInAsset = EditorGUIUtility.Load(GraphicsSettingsData.builtInTabContent) as VisualTreeAsset;\n            var builtInTemplate = builtInAsset.Instantiate();\n            builtInTemplate\n                .Query<ProjectSettingsElementWithSO>()\n                .ForEach(d => d.Initialize(serializedObject));\n\n            builtInTemplate.Query<PropertyField>().Where(p => !string.IsNullOrWhiteSpace(p.bindingPath)).ForEach(p =>\n            {\n                var serializedProperty = serializedObject.FindProperty(p.bindingPath);\n                if (serializedProperty != null)\n                    p.BindProperty(serializedProperty);\n            });\n\n            SetupTransparencySortMode(builtInTemplate);\n\n            var builtInSettingsContainer = builtInTemplate.MandatoryQ<VisualElement>($\"{GraphicsSettingsData.builtIn}SettingsContainer\");\n            var builtInHelpBoxes = GraphicsSettingsInspectorUtility.CreateRPHelpBox(m_VisibilityController, null);\n            builtInSettingsContainer.Insert(0, builtInHelpBoxes);\n            builtInHelpBoxes.MandatoryQ<HelpBox>(\"CurrentPipelineWarningHelpBox\").text = GraphicsSettingsData.builtInWarningText.text;\n\n            // If we open the settings page for the first time we check the current render pipeline.\n            var settingsPipelineFullTypeName = UserSettings.FromConfig().pipelineFullTypeName;\n            var selectedTab = string.IsNullOrEmpty(settingsPipelineFullTypeName) ? GraphicsSettings.currentRenderPipelineAssetType?.ToString() : settingsPipelineFullTypeName;\n\n            var builtinActive = string.IsNullOrEmpty(selectedTab) || selectedTab.Equals(GraphicsSettingsData.builtIn);\n            var tabButton = GraphicsSettingsInspectorUtility.CreateNewTab(m_TabbedView, GraphicsSettingsData.builtIn, builtInSettingsContainer, builtinActive);\n            tabButton.userData = GraphicsSettingsData.builtIn;\n\n            //Add SRP tabs\n            foreach (var globalSettingsContainer in m_GlobalSettings)\n            {\n                var globalSettingsElement = new VisualElement();\n                var rpHelpBoxes = GraphicsSettingsInspectorUtility.CreateRPHelpBox(m_VisibilityController, globalSettingsContainer.renderPipelineAssetType);\n                globalSettingsElement.Add(rpHelpBoxes);\n\n                globalSettingsElement.Bind(globalSettingsContainer.serializedObject);\n                var propertyEditor = new PropertyField(globalSettingsContainer.property);\n                propertyEditor.AddToClassList(InspectorElement.uIEInspectorVariantUssClassName);\n                globalSettingsElement.Add(propertyEditor);\n\n                var srpTabButton = GraphicsSettingsInspectorUtility.CreateNewTab(m_TabbedView, globalSettingsContainer.name, globalSettingsElement,\n                    !builtinActive && selectedTab.Equals(globalSettingsContainer.renderPipelineAssetType.ToString()));\n                srpTabButton.userData = globalSettingsContainer.renderPipelineAssetType;\n            }\n        }\n\n        void SearchChanged()\n        {\n            var settingsWindow = EditorWindow.GetWindow<ProjectSettingsWindow>(null, false);\n            if (settingsWindow.GetCurrentProvider() is not GraphicsSettingsProvider provider)\n                return;\n\n            var currentText = provider.settingsWindow.GetSearchText();\n            if (string.IsNullOrWhiteSpace(currentText))\n                return;\n\n            if (currentText.Equals(m_CurrentText, StringComparison.Ordinal))\n                return;\n\n            m_CurrentText = currentText;\n\n            if (m_Labels.Count == 0)\n            {\n                foreach (var tab in m_TabbedView.tabs)\n                {\n                    m_Labels.Add(tab.Target, tab.Target.Query<Label>().ToList());\n                }\n            }\n\n            var highlighted = AnyLabelMatchSearch(m_TabbedView.ActiveTab.Target);\n            if (highlighted)\n                return;\n\n            foreach (var tab in m_TabbedView.tabs)\n            {\n                if(tab == m_TabbedView.ActiveTab)\n                    continue;\n\n                var highlightedInDifferentTab = AnyLabelMatchSearch(tab.Target);\n                if (!highlightedInDifferentTab)\n                    continue;\n\n                m_TabbedView.Activate(tab);\n                return;\n            }\n\n            bool AnyLabelMatchSearch(VisualElement element)\n            {\n                var list = m_Labels[element];\n                foreach (var label in list)\n                {\n                    if (SettingsWindow.Styles.TagRegex.IsMatch(label.text))\n                        return true;\n                }\n                return false;\n            }\n        }\n\n        void OnMainScrollViewGeometryChanged(GeometryChangedEvent evt)\n        {\n            void Unregister()\n            {\n                m_ScrollView.contentContainer.UnregisterCallback<GeometryChangedEvent>(OnMainScrollViewGeometryChanged);\n                m_GeometryChangedEventCounter = 0;\n                m_FinishedInitialization = true;\n                m_TabbedView?.schedule.Execute(SearchChanged).Every(100);\n            }\n\n            void UnregisterAfterLastGeometryChange()\n            {\n                if (m_GeometryChangedEventCounter > 1)\n                {\n                    m_GeometryChangedEventCounter--;\n                    return;\n                }\n\n                Unregister();\n            }\n\n            var savedScrollOffset = UserSettings.FromConfig().scrollOffset;\n            if (m_ScrollView.scrollOffset != savedScrollOffset)\n            {\n                m_ScrollView.scrollOffset = savedScrollOffset;\n\n                m_GeometryChangedEventCounter++;\n                m_ScrollView.contentContainer.schedule.Execute(UnregisterAfterLastGeometryChange).ExecuteLater(500);\n            }\n            else\n                Unregister();\n        }\n\n        void BindEnumFieldWithFadeGroup(VisualElement content, string id, Action buttonCallback)\n        {\n            var enumMode = content.MandatoryQ<EnumField>($\"{id}Modes\");\n            var enumModeGroup = content.MandatoryQ<VisualElement>($\"{id}ModesGroup\");\n            var enumModeProperty = serializedObject.FindProperty($\"m_{id}Stripping\");\n            UIElementsEditorUtility.SetVisibility(enumModeGroup, (StrippingModes)enumModeProperty.enumValueFlag == StrippingModes.Custom);\n            UIElementsEditorUtility.BindSerializedProperty<StrippingModes>(enumMode, enumModeProperty,\n                mode => UIElementsEditorUtility.SetVisibility(enumModeGroup, mode == StrippingModes.Custom));\n            content.MandatoryQ<Button>($\"Import{id}FromCurrentScene\").clicked += buttonCallback;\n        }\n\n        void BindEnumFieldToLightProbe(VisualElement content)\n        {\n            var enumMode = content.MandatoryQ<EnumField>(\"LightProbe\");\n            var enumModeProperty = serializedObject.FindProperty(enumMode.bindingPath);\n            UIElementsEditorUtility.BindSerializedProperty<LightProbeOutsideHullStrategy>(enumMode, enumModeProperty);\n        }\n\n        void SetupTransparencySortMode(VisualElement root)\n        {\n            var transparencySortMode = root.MandatoryQ<PropertyField>(\"TransparencySortMode\");\n            var transparencySortAxis = root.MandatoryQ<PropertyField>(\"TransparencySortAxis\");\n            transparencySortMode.RegisterValueChangeCallback(evt =>\n                UIElementsEditorUtility.SetVisibility(transparencySortAxis, (TransparencySortMode)evt.changedProperty.enumValueIndex == TransparencySortMode.CustomAxis));\n        }\n\n        void UpdateBuildProfileGraphicsSettingsOverrideWarning()\n        {\n            if (BuildProfileContext.ActiveProfileHasGraphicsSettings())\n                m_BuildProfileGraphicsSettingsOverrideWarning.style.display = DisplayStyle.Flex;\n            else\n                m_BuildProfileGraphicsSettingsOverrideWarning.style.display = DisplayStyle.None;\n        }\n\n        [Serializable]\n        class UserSettings\n        {\n            internal const string s_Key = $\"{nameof(GraphicsSettingsInspector)}_{nameof(UserSettings)}\";\n\n            public Vector2 scrollOffset = Vector2.zero;\n            public string pipelineFullTypeName = \"\";\n\n            public static UserSettings FromConfig()\n            {\n                var serializedScrollValues = EditorUserSettings.GetConfigValue(s_Key);\n                return string.IsNullOrEmpty(serializedScrollValues) ? new UserSettings() : JsonUtility.FromJson<UserSettings>(serializedScrollValues);\n            }\n\n            public static void ToConfig(VisualElement root)\n            {\n                var userSettings = new UserSettings();\n\n                var mainScrollView = root.Q<ScrollView>(\"MainScrollView\");\n                var tabbedView = root.Q<TabbedView>(\"PipelineSpecificSettings\");\n                if (mainScrollView == null)\n                    return;\n\n                userSettings.scrollOffset = mainScrollView.scrollOffset;\n\n                if (tabbedView != null && tabbedView.ActiveTab != null)\n                {\n                    userSettings.pipelineFullTypeName = tabbedView.ActiveTab.userData.ToString();\n                }\n                else\n                {\n                    userSettings.pipelineFullTypeName = GraphicsSettingsData.builtIn;\n                }\n\n                EditorUserSettings.SetConfigValue(s_Key, JsonUtility.ToJson(userSettings));\n            }\n        }\n\n        //internal for tests\n        internal static void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            if (!info.undoName.StartsWith(RenderPipelineGraphicsSettingsManager.undoResetName))\n                return;\n\n            EditorGraphicsSettings.ForEachPipelineSettings(globalSettings =>\n            {\n                if (globalSettings == null)\n                    return;\n\n                var serializedGlobalSettings = new SerializedObject(globalSettings);\n                var settingsIterator = serializedGlobalSettings.FindProperty(RenderPipelineGraphicsSettingsManager.serializationPathToCollection);\n\n                using (new Notifier.Scope(settingsIterator, updateStateNow: false))\n                {\n                    /* Nothing to do: changes already done before this callback */\n                }\n            });\n        }\n    }\n\n    internal enum StrippingModes\n    {\n        Automatic = 0,\n        Custom = 1\n    }\n\n    /// <summary>\n    /// Control visibility of UI elements depends on active Render Pipeline.\n    /// For one it stays specific for GraphicsSettings as it requires a way to determine BuiltinOnly elements and there is no generic way to do it.\n    /// </summary>\n    internal class VisibilityControllerBasedOnRenderPipeline : IDisposable\n    {\n        readonly List<ValueTuple<VisualElement, Type[]>> m_TrackedElements = new();\n\n        public void Initialize()\n        {\n            RenderPipelineManager.activeRenderPipelineAssetChanged += RenderPipelineAssetChanged;\n        }\n\n        public bool RegisterVisualElement(VisualElement element, params Type[] renderPipelineAssetTypes)\n        {\n            if (element == null)\n                return false;\n\n            if (m_TrackedElements.Any(t => t.Item1 == element))\n                return false;\n\n            renderPipelineAssetTypes ??= new Type[] { null };\n            var newPair = new ValueTuple<VisualElement, Type[]>(element, renderPipelineAssetTypes);\n            m_TrackedElements.Add(newPair);\n            UpdateElementVisibility(GraphicsSettings.currentRenderPipelineAssetType, newPair);\n            return true;\n        }\n\n        public void RegisterVisualElementTree(VisualElement element, params Type[] renderPipelineAssetTypes)\n        {\n            element.Query<GraphicsSettingsElement>().ForEach(e => RegisterVisualElement(e, renderPipelineAssetTypes));\n        }\n\n        public bool UnregisterVisualElement(VisualElement element)\n        {\n            if (element == null || m_TrackedElements.Count == 0)\n                return false;\n\n            var index = m_TrackedElements.FindIndex(t => element == t.Item1);\n            if (index < 0)\n                return false;\n\n            m_TrackedElements.RemoveAt(index);\n            return true;\n        }\n\n        void RenderPipelineAssetChanged(RenderPipelineAsset previous, RenderPipelineAsset next)\n        {\n            var newAssetType = next != null ? next.GetType() : null;\n            for (var i = 0; i < m_TrackedElements.Count; i++)\n            {\n                UpdateElementVisibility(newAssetType, m_TrackedElements[i]);\n            }\n        }\n\n        bool ShouldDisplayElement(Type currentRenderPipelineAssetType, Type[] renderPipelineAssetTypes)\n        {\n            return renderPipelineAssetTypes.Contains(currentRenderPipelineAssetType)\n                   || renderPipelineAssetTypes.Any(t => t != null && t.IsAssignableFrom(currentRenderPipelineAssetType));\n        }\n\n        void UpdateElementVisibility(Type currentRenderPipelineAssetType, (VisualElement, Type[]) pair)\n        {\n            if (ShouldDisplayElement(currentRenderPipelineAssetType, pair.Item2))\n                Show(pair.Item1);\n            else\n                Hide(pair.Item1);\n        }\n\n        void Show(VisualElement element)\n        {\n            element.style.display = DisplayStyle.Flex;\n        }\n\n        void Hide(VisualElement element)\n        {\n            element.style.display = DisplayStyle.None;\n        }\n\n        public void ShowAll()\n        {\n            for (int i = 0; i < m_TrackedElements.Count; i++)\n            {\n                Show(m_TrackedElements[i].Item1);\n            }\n        }\n\n        public void HideAll()\n        {\n            for (int i = 0; i < m_TrackedElements.Count; i++)\n            {\n                Hide(m_TrackedElements[i].Item1);\n            }\n        }\n\n        public void Clear()\n        {\n            m_TrackedElements.Clear();\n        }\n\n        public void Dispose()\n        {\n            RenderPipelineManager.activeRenderPipelineAssetChanged -= RenderPipelineAssetChanged;\n        }\n    }\n\n    internal class GraphicsSettingsProvider : SettingsProvider\n    {\n        internal static readonly string s_GraphicsSettingsProviderPath = \"Project/Graphics\";\n        internal GraphicsSettingsInspector inspector;\n\n        [SettingsProvider]\n        public static SettingsProvider CreateUserSettingsProvider()\n        {\n            var graphicsSettingsProvider = new GraphicsSettingsProvider(s_GraphicsSettingsProviderPath, SettingsScope.Project)\n            {\n                icon = EditorGUIUtility.FindTexture(\"UnityEngine/UI/GraphicRaycaster Icon\")\n            };\n            return graphicsSettingsProvider;\n        }\n\n        internal GraphicsSettingsProvider(string path, SettingsScope scopes, IEnumerable<string> keywords = null) : base(path, scopes, keywords)\n        {\n            UpdateKeywords();\n            activateHandler = (_, root) =>\n            {\n                var (graphicsSettings, globalSettingsExist, globalSettingsContainers) = UpdateKeywords();\n                inspector = Editor.CreateEditor(graphicsSettings) as GraphicsSettingsInspector;\n                inspector.Create(root, globalSettingsExist, globalSettingsContainers);\n            };\n            deactivateHandler = (() =>\n            {\n                if (inspector != null)\n                {\n                    inspector.Dispose();\n                    inspector = null;\n                }\n            });\n        }\n\n        public (UnityEngine.Object, bool, List<GraphicsSettingsInspectorUtility.GlobalSettingsContainer>) UpdateKeywords()\n        {\n            var keywordsList = new List<string>();\n            keywordsList.AddRange(GetSearchKeywordsFromGUIContentProperties<GraphicsSettingsInspectorTierSettings.Styles>());\n\n            var graphicsSettings = GraphicsSettings.GetGraphicsSettings();\n            var graphicsSettingsSO = new SerializedObject(graphicsSettings);\n            keywordsList.AddRange(GetSearchKeywordsFromSerializedObject(graphicsSettingsSO, ResolveName));\n\n            var globalSettingsExist = GraphicsSettingsInspectorUtility.GatherGlobalSettingsFromSerializedObject(graphicsSettingsSO, out var globalSettingsContainers);\n            if (globalSettingsExist)\n            {\n                foreach (var globalSetting in globalSettingsContainers)\n                    keywordsList.AddRange(GetSearchKeywordsFromSerializedObject(globalSetting.serializedObject));\n            }\n\n            keywords = keywordsList;\n            return (graphicsSettings, globalSettingsExist, globalSettingsContainers);\n        }\n\n        // Important: GraphicsSettings only exists on C++ side.\n        // As there is no C# representation of the field, there is no way to decorate them with attribute.\n        // C++ variable name are used to build the path of the SerializedProperty, but do not match the displayed name.\n        // Introducing a C# bindings may be a good solution for long therm maintenance but for limited cost, let's just remap.\n        static readonly Dictionary<string, string> k_CPPToLabels = new()\n        {\n            //below are labels set in the UXML GraphicsSettingsEditor-Common.uxml\n            { \"m_LightmapStripping\" , \"Lightmap Modes\" },\n            { \"m_LightmapKeepPlain\" , \"Baked Non-Directional\" },\n            { \"m_LightmapKeepDirCombined\" , \"Baked Directional\" },\n            { \"m_LightmapKeepDynamicPlain\" , \"Realtime Non-Directional\" },\n            { \"m_LightmapKeepDynamicDirCombined\" , \"Realtime Directional\" },\n            { \"m_LightmapKeepShadowMask\" , \"Baked Shadowmask\" },\n            { \"m_LightmapKeepSubtractive\" , \"Baked Subtractive\" },\n            { \"m_FogStripping\" , \"Fog Modes\" },\n            { \"m_FogKeepLinear\" , \"Linear\" },\n            { \"m_FogKeepExp\" , \"Exponential\" },\n            { \"m_FogKeepExp2\" , \"Exponential Squared\" },\n            { \"m_InstancingStripping\" , \"Instancing Variants\" },\n            { \"m_BrgStripping\" , \"Batch Renderer Group Variants\" },\n            { \"m_LogWhenShaderIsCompiled\" , \"Log Shader Compilation\" },\n            { \"m_CameraRelativeLightCulling\" , \"Lights\" },\n            { \"m_CameraRelativeShadowCulling\" , \"Shadows\" },\n            { \"m_VideoShadersIncludeMode\" , \"Video\" },\n            { \"m_AlwaysIncludedShaders\" , \"Always Included Shaders\" },\n            { \"m_LightProbeOutsideHullStrategy\" , \"Renderer Light Probe Selection\" },\n            { \"m_PreloadedShaders\" , \"Preload Shaders\" },\n            // Below: 1 serialized property is for 2 field of the inspector. Adding all to the search keys\n            { \"m_PreloadShadersBatchTimeLimit\" , $\"Preload Shaders After Showing First Scene Preload Time Limit Per Frame (ms)\" },\n        };\n\n        string ResolveName(SerializedProperty property)\n        {\n            if (k_CPPToLabels.ContainsKey(property.name))\n                return k_CPPToLabels[property.name];\n            return property.displayName;\n        }\n\n        internal void Reload()\n        {\n            if (inspector == null)\n                return;\n\n            //Ensure of the Global Settings can update keywords as new settings may have been added\n            var (_, globalSettingsExist, globalSettingsContainers) = UpdateKeywords();\n            inspector.Reload(globalSettingsExist, globalSettingsContainers);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/GraphicsSettingsInspectors/GraphicsSettingsElement.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n﻿using UnityEditor.UIElements.ProjectSettings;\n\nnamespace UnityEditor.Inspector.GraphicsSettingsInspectors\n{\n    internal abstract class GraphicsSettingsElement : ProjectSettingsElementWithSO\n    {\n        //We rely on SupportedOn attribute for the cases when we need to show element for SRP.\n        //Here is a way to specify when we want to have element visible for BuiltinOnly.\n        //Important notice: we check first for SupportedOn first, then for this backup field.\n        public virtual bool BuiltinOnly => false;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/GraphicsSettingsInspectors/GraphicsSettingsInspectorTierSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n﻿using System;\nusing UnityEditor.AnimatedValues;\nusing UnityEditor.Build;\nusing UnityEditor.Inspector.VisualElements.ProjectSettings;\nusing UnityEditor.Rendering;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Inspector.GraphicsSettingsInspectors\n{\n    internal class TierSettingsWindow : EditorWindow\n    {\n        static TierSettingsWindow s_Instance;\n\n\n        public static void CreateWindow()\n        {\n            s_Instance = GetWindow<TierSettingsWindow>();\n            s_Instance.minSize = new Vector2(600, 300);\n            s_Instance.titleContent = GraphicsSettingsInspectorTierSettings.Styles.tierSettings;\n        }\n\n        internal static TierSettingsWindow GetInstance()\n        {\n            return s_Instance;\n        }\n\n        SerializedObject m_SerializedObject;\n\n        void OnEnable()\n        {\n            s_Instance = this;\n            m_SerializedObject = new SerializedObject(GraphicsSettings.GetGraphicsSettings());\n            var graphicsSettingsInspectorTierSettings = new GraphicsSettingsInspectorTierSettings()\n            {\n                style =\n                {\n                    marginTop = 5,\n                    marginBottom = 5,\n                    marginLeft = 5,\n                    marginRight = 5\n                },\n                UseAnimation = false,\n                VerticalLayout = false\n            };\n            var scrollView = new ScrollView(ScrollViewMode.Vertical);\n            rootVisualElement.Add(scrollView);\n            graphicsSettingsInspectorTierSettings.Initialize(m_SerializedObject);\n            scrollView.contentContainer.Add(graphicsSettingsInspectorTierSettings);\n            RenderPipelineManager.activeRenderPipelineAssetChanged += RenderPipelineAssetChanged;\n        }\n\n        void RenderPipelineAssetChanged(RenderPipelineAsset previous, RenderPipelineAsset next)\n        {\n            if (next != null)\n                Close();\n        }\n\n        void OnDisable()\n        {\n            RenderPipelineManager.activeRenderPipelineAssetChanged -= RenderPipelineAssetChanged;\n            rootVisualElement.Clear();\n\n            if (s_Instance == this)\n                s_Instance = null;\n        }\n    }\n\n    internal class GraphicsSettingsInspectorTierSettings : GraphicsSettingsElement\n    {\n        [Serializable]\n        public new class UxmlSerializedData : VisualElement.UxmlSerializedData\n        {\n            public override object CreateInstance() => new GraphicsSettingsInspectorTierSettings();\n        }\n\n        internal class Styles\n        {\n            public static readonly GUIContent[] shaderQualityName =\n                { EditorGUIUtility.TrTextContent(\"Low\"), EditorGUIUtility.TrTextContent(\"Medium\"), EditorGUIUtility.TrTextContent(\"High\") };\n\n            public static readonly int[] shaderQualityValue =\n                { (int)ShaderQuality.Low, (int)ShaderQuality.Medium, (int)ShaderQuality.High };\n\n            public static readonly GUIContent[] renderingPathName =\n                { EditorGUIUtility.TrTextContent(\"Forward\"), EditorGUIUtility.TrTextContent(\"Deferred\"), EditorGUIUtility.TrTextContent(\"Legacy Vertex Lit\") };\n\n            public static readonly int[] renderingPathValue =\n                { (int)RenderingPath.Forward, (int)RenderingPath.DeferredShading, (int)RenderingPath.VertexLit };\n\n            public static readonly GUIContent[] hdrModeName =\n                { EditorGUIUtility.TrTextContent(\"FP16\"), EditorGUIUtility.TrTextContent(\"R11G11B10\") };\n\n            public static readonly int[] hdrModeValue =\n                { (int)CameraHDRMode.FP16, (int)CameraHDRMode.R11G11B10 };\n\n            public static readonly GUIContent[] realtimeGICPUUsageName =\n                { EditorGUIUtility.TrTextContent(\"Low\"), EditorGUIUtility.TrTextContent(\"Medium\"), EditorGUIUtility.TrTextContent(\"High\"), EditorGUIUtility.TrTextContent(\"Unlimited\") };\n\n            public static readonly int[] realtimeGICPUUsageValue =\n                { (int)RealtimeGICPUUsage.Low, (int)RealtimeGICPUUsage.Medium, (int)RealtimeGICPUUsage.High, (int)RealtimeGICPUUsage.Unlimited };\n\n            public static readonly GUIContent showEditorWindow = EditorGUIUtility.TrTextContent(\"Open Editor...\");\n            public static readonly GUIContent closeEditorWindow = EditorGUIUtility.TrTextContent(\"Close Editor\");\n            public static readonly GUIContent tierSettings = EditorGUIUtility.TrTextContent(\"Tier Settings\");\n\n            public static readonly GUIContent[] tierName =\n            {\n                EditorGUIUtility.TrTextContent(\"Low (Tier 1)\"), EditorGUIUtility.TrTextContent(\"Medium (Tier 2)\"), EditorGUIUtility.TrTextContent(\"High (Tier 3)\")\n            };\n\n            public static readonly GUIContent empty = EditorGUIUtility.TextContent(\"\");\n            public static readonly GUIContent autoSettingsLabel = EditorGUIUtility.TrTextContent(\"Use Defaults\");\n\n            public static readonly GUIContent standardShaderSettings = EditorGUIUtility.TrTextContent(\"Standard Shader\");\n            public static readonly GUIContent renderingSettings = EditorGUIUtility.TrTextContent(\"Rendering\");\n\n            public static readonly GUIContent standardShaderQuality = EditorGUIUtility.TrTextContent(\"Standard Shader Quality\");\n\n            public static readonly GUIContent reflectionProbeBoxProjection =\n                EditorGUIUtility.TrTextContent(\"Reflection Probes Box Projection\", \"Enable projection for reflection UV mappings on Reflection Probes.\");\n\n            public static readonly GUIContent reflectionProbeBlending = EditorGUIUtility.TrTextContent(\"Reflection Probes Blending\",\n                \"Gradually fade out one probe's cubemap while fading in the other's as the reflective object passes from one zone to the other.\");\n\n            public static readonly GUIContent detailNormalMap =\n                EditorGUIUtility.TrTextContent(\"Detail Normal Map\", \"Enable Detail (secondary) Normal Map sampling for up-close viewing, if assigned.\");\n\n            public static readonly GUIContent cascadedShadowMaps = EditorGUIUtility.TrTextContent(\"Cascaded Shadows\");\n\n            public static readonly GUIContent prefer32BitShadowMaps =\n                EditorGUIUtility.TrTextContent(\"Prefer 32-bit shadow maps\", \"Enable 32-bit float shadow map when you are targeting PS4 or platforms using DX11 or DX12.\");\n\n            public static readonly GUIContent semitransparentShadows = EditorGUIUtility.TrTextContent(\"Enable Semitransparent Shadows\");\n\n            public static readonly GUIContent enableLPPV =\n                EditorGUIUtility.TrTextContent(\"Enable Light Probe Proxy Volume\", \"Enable rendering a 3D grid of interpolated Light Probes inside a Bounding Volume.\");\n\n            public static readonly GUIContent renderingPath = EditorGUIUtility.TrTextContent(\"Rendering Path\",\n                \"Choose how Unity should render graphics. Different rendering paths affect the performance of your game, and how lighting and shading are calculated.\");\n\n            public static readonly GUIContent useHDR = EditorGUIUtility.TrTextContent(\"Use HDR\", \"Enable High Dynamic Range rendering for this tier.\");\n            public static readonly GUIContent hdrMode = EditorGUIUtility.TrTextContent(\"HDR Mode\", \"Color render texture format for the HDR buffer to use when HDR is enabled.\");\n\n            public static readonly GUIContent realtimeGICPUUsage = EditorGUIUtility.TrTextContent(\"Realtime Global Illumination CPU Usage\",\n                \"How many CPU worker threads to create for Realtime Global Illumination lighting calculations in the Player. Increasing this makes the system react faster to changes in lighting at a cost of using more CPU time. The higher the CPU Usage value, the more worker threads are created for solving Realtime GI.\");\n        }\n\n        public override bool BuiltinOnly => true;\n        public bool UseAnimation { get; set; } = true;\n\n        public bool VerticalLayout { get; set; } = true;\n\n        // this is category animation is blatantly copied from PlayerSettingsEditor.cs\n        bool m_ShowTierSettingsUI = true; // show by default, as otherwise users are confused\n        AnimBool m_TierSettingsAnimator;\n\n        protected override void Initialize()\n        {\n            var container = new IMGUIContainer(Draw);\n            Add(container);\n\n            if (UseAnimation)\n            {\n                m_TierSettingsAnimator = new AnimBool(m_ShowTierSettingsUI, container.MarkDirtyRepaint);\n            }\n        }\n\n        void Draw()\n        {\n            using var settingsScope = new LabelWidthScope();\n            using var wideScreenScope = new WideScreenScope(this);\n            if (m_TierSettingsAnimator == null)\n                OnInspectorGUI();\n            else\n                TierSettingsGUI();\n        }\n\n        void HandleEditorWindowButton()\n        {\n            var window = TierSettingsWindow.GetInstance();\n            var text = window == null ? Styles.showEditorWindow : Styles.closeEditorWindow;\n            if (!GUILayout.Button(text, EditorStyles.miniButton, GUILayout.Width(110)))\n                return;\n\n            if (window)\n            {\n                window.Close();\n            }\n            else\n            {\n                TierSettingsWindow.CreateWindow();\n                TierSettingsWindow.GetInstance().Show();\n            }\n        }\n\n        void TierSettingsGUI()\n        {\n            var enabled = GUI.enabled;\n            GUI.enabled = true; // we don't want to disable the expand behavior\n            EditorGUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.Height(20));\n\n            EditorGUILayout.BeginHorizontal();\n            var r = GUILayoutUtility.GetRect(20, 21);\n            r.x += 3;\n            r.width += 6;\n            m_ShowTierSettingsUI = EditorGUI.FoldoutTitlebar(r, Styles.tierSettings, m_ShowTierSettingsUI, true, EditorStyles.inspectorTitlebarFlat, EditorStyles.inspectorTitlebarText);\n            HandleEditorWindowButton();\n            EditorGUILayout.EndHorizontal();\n\n            m_TierSettingsAnimator.target = m_ShowTierSettingsUI;\n            GUI.enabled = enabled;\n\n            if (EditorGUILayout.BeginFadeGroup(m_TierSettingsAnimator.faded) && TierSettingsWindow.GetInstance() == null)\n                OnInspectorGUI();\n            EditorGUILayout.EndFadeGroup();\n            EditorGUILayout.EndVertical();\n        }\n\n        void OnInspectorGUI()\n        {\n            using var highlightScope = new EditorGUI.LabelHighlightScope(m_SettingsWindow.GetSearchText(), HighlightSelectionColor, HighlightColor);\n            var validPlatforms = BuildPlatforms.instance.GetValidPlatforms().ToArray();\n            var platform = validPlatforms[EditorGUILayout.BeginPlatformGrouping(validPlatforms, null, EditorStyles.frameBox)];\n\n            if (VerticalLayout) OnGuiVertical(platform);\n            else OnGuiHorizontal(platform);\n\n            EditorGUILayout.EndPlatformGrouping();\n        }\n\n        void OnFieldLabelsGUI(bool vertical)\n        {\n            if (!vertical)\n                EditorGUILayout.LabelField(Styles.standardShaderSettings, EditorStyles.boldLabel);\n\n            EditorGUILayout.LabelField(Styles.standardShaderQuality);\n            EditorGUILayout.LabelField(Styles.reflectionProbeBoxProjection);\n            EditorGUILayout.LabelField(Styles.reflectionProbeBlending);\n            EditorGUILayout.LabelField(Styles.detailNormalMap);\n            EditorGUILayout.LabelField(Styles.semitransparentShadows);\n\n            if (SupportedRenderingFeatures.active.lightProbeProxyVolumes)\n                EditorGUILayout.LabelField(Styles.enableLPPV);\n\n            if (!vertical)\n            {\n                EditorGUILayout.LabelField(Styles.empty, EditorStyles.boldLabel);\n                EditorGUILayout.LabelField(Styles.renderingSettings, EditorStyles.boldLabel);\n            }\n\n            EditorGUILayout.LabelField(Styles.cascadedShadowMaps);\n            EditorGUILayout.LabelField(Styles.prefer32BitShadowMaps);\n            EditorGUILayout.LabelField(Styles.useHDR);\n            EditorGUILayout.LabelField(Styles.hdrMode);\n            EditorGUILayout.LabelField(Styles.renderingPath);\n\n            if (SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime))\n                EditorGUILayout.LabelField(Styles.realtimeGICPUUsage);\n        }\n\n\n        // custom enum handling\n        ShaderQuality ShaderQualityPopup(ShaderQuality sq) =>\n            (ShaderQuality)EditorGUILayout.IntPopup((int)sq, Styles.shaderQualityName, Styles.shaderQualityValue);\n\n        RenderingPath RenderingPathPopup(RenderingPath rp) =>\n            (RenderingPath)EditorGUILayout.IntPopup((int)rp, Styles.renderingPathName, Styles.renderingPathValue);\n\n        CameraHDRMode HDRModePopup(CameraHDRMode mode) =>\n            (CameraHDRMode)EditorGUILayout.IntPopup((int)mode, Styles.hdrModeName, Styles.hdrModeValue);\n\n        RealtimeGICPUUsage RealtimeGICPUUsagePopup(RealtimeGICPUUsage usage) =>\n            (RealtimeGICPUUsage)EditorGUILayout.IntPopup((int)usage, Styles.realtimeGICPUUsageName, Styles.realtimeGICPUUsageValue);\n\n\n        void OnTierGUI(BuildPlatform platform, GraphicsTier tier, bool vertical)\n        {\n            var ts = EditorGraphicsSettings.GetTierSettings(platform.namedBuildTarget, tier);\n\n            EditorGUI.BeginChangeCheck();\n\n\n            if (!vertical)\n                EditorGUILayout.LabelField(Styles.empty, EditorStyles.boldLabel);\n\n            ts.standardShaderQuality = ShaderQualityPopup(ts.standardShaderQuality);\n            ts.reflectionProbeBoxProjection = EditorGUILayout.Toggle(ts.reflectionProbeBoxProjection);\n            ts.reflectionProbeBlending = EditorGUILayout.Toggle(ts.reflectionProbeBlending);\n            ts.detailNormalMap = EditorGUILayout.Toggle(ts.detailNormalMap);\n            ts.semitransparentShadows = EditorGUILayout.Toggle(ts.semitransparentShadows);\n\n            if (SupportedRenderingFeatures.active.lightProbeProxyVolumes)\n                ts.enableLPPV = EditorGUILayout.Toggle(ts.enableLPPV);\n\n            if (!vertical)\n            {\n                EditorGUILayout.LabelField(Styles.empty, EditorStyles.boldLabel);\n                EditorGUILayout.LabelField(Styles.empty, EditorStyles.boldLabel);\n            }\n\n            ts.cascadedShadowMaps = EditorGUILayout.Toggle(ts.cascadedShadowMaps);\n            ts.prefer32BitShadowMaps = EditorGUILayout.Toggle(ts.prefer32BitShadowMaps);\n            ts.hdr = EditorGUILayout.Toggle(ts.hdr);\n            ts.hdrMode = HDRModePopup(ts.hdrMode);\n            ts.renderingPath = RenderingPathPopup(ts.renderingPath);\n\n            if (!GraphicsSettings.isScriptableRenderPipelineEnabled)\n                if (SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime))\n                    ts.realtimeGICPUUsage = RealtimeGICPUUsagePopup(ts.realtimeGICPUUsage);\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                // TODO: it should be doable in c# now as we \"expose\" GraphicsSettings anyway\n                EditorGraphicsSettings.RegisterUndo();\n                EditorGraphicsSettings.SetTierSettings(platform.namedBuildTarget, tier, ts);\n            }\n        }\n\n        void OnGuiHorizontal(BuildPlatform platform)\n        {\n            EditorGUILayout.BeginHorizontal();\n\n            EditorGUILayout.BeginVertical();\n            EditorGUIUtility.labelWidth = 140;\n            EditorGUILayout.LabelField(Styles.empty, EditorStyles.boldLabel);\n            OnFieldLabelsGUI(false);\n            EditorGUILayout.LabelField(Styles.empty, EditorStyles.boldLabel);\n            EditorGUILayout.LabelField(Styles.autoSettingsLabel, EditorStyles.boldLabel);\n            EditorGUILayout.EndVertical();\n\n            EditorGUIUtility.labelWidth = 50;\n            foreach (GraphicsTier tier in Enum.GetValues(typeof(GraphicsTier)))\n            {\n                bool autoSettings = EditorGraphicsSettings.AreTierSettingsAutomatic(platform.namedBuildTarget.ToBuildTargetGroup(), tier);\n\n                EditorGUILayout.BeginVertical();\n                EditorGUILayout.LabelField(Styles.tierName[(int)tier], EditorStyles.boldLabel);\n                using (new EditorGUI.DisabledScope(autoSettings))\n                    OnTierGUI(platform, tier, false);\n\n                EditorGUILayout.LabelField(Styles.empty, EditorStyles.boldLabel);\n                EditorGUI.BeginChangeCheck();\n                autoSettings = EditorGUILayout.Toggle(autoSettings);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    EditorGraphicsSettings.RegisterUndo();\n                    EditorGraphicsSettings.MakeTierSettingsAutomatic(platform.namedBuildTarget.ToBuildTargetGroup(), tier, autoSettings);\n                    EditorGraphicsSettings.OnUpdateTierSettings(platform.namedBuildTarget.ToBuildTargetGroup(), true);\n                }\n\n                EditorGUILayout.EndVertical();\n            }\n\n            EditorGUIUtility.labelWidth = 0;\n\n            EditorGUILayout.EndHorizontal();\n        }\n\n        void OnGuiVertical(BuildPlatform platform)\n        {\n            EditorGUILayout.BeginVertical();\n            foreach (GraphicsTier tier in Enum.GetValues(typeof(GraphicsTier)))\n            {\n                var autoSettings = EditorGraphicsSettings.AreTierSettingsAutomatic(platform.namedBuildTarget.ToBuildTargetGroup(), tier);\n                EditorGUI.BeginChangeCheck();\n                {\n                    GUILayout.BeginHorizontal();\n                    EditorGUIUtility.labelWidth = 80;\n                    EditorGUILayout.LabelField(Styles.tierName[(int)tier], EditorStyles.boldLabel);\n                    GUILayout.FlexibleSpace();\n                    EditorGUIUtility.labelWidth = 80;\n                    autoSettings = EditorGUILayout.Toggle(Styles.autoSettingsLabel, autoSettings);\n                    GUILayout.EndHorizontal();\n                }\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    EditorGraphicsSettings.RegisterUndo();\n                    EditorGraphicsSettings.MakeTierSettingsAutomatic(platform.namedBuildTarget.ToBuildTargetGroup(), tier, autoSettings);\n                    EditorGraphicsSettings.OnUpdateTierSettings(platform.namedBuildTarget.ToBuildTargetGroup(), true);\n                }\n\n                using (new EditorGUI.DisabledScope(autoSettings))\n                {\n                    EditorGUI.indentLevel++;\n                    EditorGUILayout.BeginHorizontal();\n\n                    EditorGUILayout.BeginVertical();\n                    EditorGUIUtility.labelWidth = 140;\n                    OnFieldLabelsGUI(true);\n                    EditorGUILayout.EndVertical();\n\n                    EditorGUILayout.BeginVertical();\n                    EditorGUIUtility.labelWidth = 50;\n                    OnTierGUI(platform, tier, true);\n                    EditorGUILayout.EndVertical();\n\n                    GUILayout.EndHorizontal();\n                    EditorGUI.indentLevel--;\n                }\n            }\n\n            GUILayout.EndVertical();\n            EditorGUIUtility.labelWidth = 0;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/GraphicsSettingsInspectors/GraphicsSettingsInspectorUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Reflection;\nusing System.Text;\nusing UnityEditor.Rendering;\nusing UnityEditor.Rendering.Settings;\nusing UnityEditor.UIElements;\nusing UnityEditor.UIElements.ProjectSettings;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Inspector.GraphicsSettingsInspectors\n{\n    public static class GraphicsSettingsInspectorUtility\n    {\n        #region Localization\n\n        internal static void Localize(VisualElement visualElement, Func<VisualElement, string> get, Action<VisualElement, string> set)\n        {\n            if (get == null)\n                throw new InvalidOperationException(\"get function cannot be null\");\n            if (set == null)\n                throw new InvalidOperationException(\"set function cannot be null\");\n\n            var extractedText = get.Invoke(visualElement);\n            if (string.IsNullOrWhiteSpace(extractedText))\n                return;\n\n            var localizedString = L10n.Tr(extractedText);\n            set.Invoke(visualElement, localizedString);\n        }\n\n        internal static void LocalizeTooltip(VisualElement visualElement)\n        {\n            Localize(visualElement, e => e.tooltip, (e, s) => e.tooltip = s);\n        }\n\n        internal static void LocalizeText(Label visualElement)\n        {\n            Localize(visualElement, e => ((Label)e).text, (e, s) => ((Label)e).text = s);\n        }\n\n        internal static void LocalizeVisualTree(VisualElement root)\n        {\n            root.Query<VisualElement>().ForEach(LocalizeTooltip);\n            root.Query<Label>().ForEach(label =>\n            {\n                //Ignore text inside ObjectField because it's an asset name\n                if (label.ClassListContains(\"unity-object-field-display__label\"))\n                    return;\n                LocalizeText(label);\n            });\n        }\n\n        #endregion\n\n        #region Render Pipeline Assets extraction\n\n        internal class GlobalSettingsContainer\n        {\n            public readonly string name;\n            public readonly string path;\n            public readonly Type renderPipelineAssetType;\n            public readonly SerializedProperty property;\n            public readonly SerializedObject serializedObject;\n\n            public GlobalSettingsContainer(string name, string path, Type renderPipelineAssetType, SerializedProperty property, SerializedObject serializedObject)\n            {\n                this.name = name;\n                this.path = path;\n                this.renderPipelineAssetType = renderPipelineAssetType;\n                this.property = property;\n                this.serializedObject = serializedObject;\n            }\n        }\n\n        internal static bool GatherGlobalSettingsFromSerializedObject(SerializedObject serializedObject, out List<GlobalSettingsContainer> globalSettings)\n        {\n            var renderPipelineGlobalSettingsMap = serializedObject.FindProperty(\"m_RenderPipelineGlobalSettingsMap\");\n            globalSettings = CollectRenderPipelineAssetsByGlobalSettings(renderPipelineGlobalSettingsMap);\n            return globalSettings.Count > 0;\n        }\n\n        internal static List<GlobalSettingsContainer> CollectRenderPipelineAssetsByGlobalSettings(SerializedProperty renderPipelineGlobalSettingsMap)\n        {\n            var existedGlobalSettings = new List<GlobalSettingsContainer>();\n            for (int i = 0; i < renderPipelineGlobalSettingsMap.arraySize; ++i)\n            {\n                var globalSettings = GetRenderPipelineGlobalSettingsByIndex(renderPipelineGlobalSettingsMap, i);\n                if (TryCreateNewGlobalSettingsContainer(globalSettings, out var globalSettingsContainer))\n                    existedGlobalSettings.Add(globalSettingsContainer);\n            }\n\n            return existedGlobalSettings;\n        }\n\n        internal static bool TryCreateNewGlobalSettingsContainer(RenderPipelineGlobalSettings globalSettings, out GlobalSettingsContainer globalSettingsContainer)\n        {\n            globalSettingsContainer = null;\n\n            if (globalSettings == null)\n                return false;\n\n            var result = TryGetSettingsListFromRenderPipelineGlobalSettings(globalSettings,\n                out var globalSettingsSO,\n                out var settingsContainer,\n                out var settingsListInContainer);\n            if (!result || settingsListInContainer.arraySize == 0)\n                return false;\n\n            if (!IsAnyRenderPipelineGraphicsSettingsValid(settingsListInContainer))\n                return false;\n\n            var globalSettingsType = globalSettings.GetType();\n            if (!TryExtractSupportedOnRenderPipelineAttribute(globalSettingsType, out var supportedOnRenderPipelineAttribute, out var message))\n            {\n                Debug.LogWarning(message);\n                return false;\n            }\n\n            var tabName = CreateNewTabName(globalSettingsType, supportedOnRenderPipelineAttribute);\n            var path = AssetDatabase.GetAssetPath(globalSettings);\n            globalSettingsContainer = new GlobalSettingsContainer(tabName, path, supportedOnRenderPipelineAttribute.renderPipelineTypes[0], settingsContainer, globalSettingsSO);\n            return true;\n        }\n\n        static bool TryGetSettingsListFromRenderPipelineGlobalSettings(RenderPipelineGlobalSettings globalSettings, out SerializedObject globalSettingsSO, out SerializedProperty settingsContainer,\n            out SerializedProperty settingsListInContainer)\n        {\n            globalSettingsSO = new SerializedObject(globalSettings);\n            settingsContainer = globalSettingsSO.FindProperty(RenderPipelineGraphicsSettingsManager.serializationPathToContainer);\n            if (settingsContainer == null)\n            {\n                settingsListInContainer = null;\n                return false;\n            }\n\n            settingsListInContainer = globalSettingsSO.FindProperty(RenderPipelineGraphicsSettingsManager.serializationPathToCollection);\n            return settingsListInContainer != null;\n        }\n\n        static bool IsAnyRenderPipelineGraphicsSettingsValid(SerializedProperty settingsListInContainer)\n        {\n            for (int i = 0; i < settingsListInContainer.arraySize; i++)\n            {\n                var serializedSettings = settingsListInContainer.GetArrayElementAtIndex(i);\n                if (serializedSettings.managedReferenceValue is not IRenderPipelineGraphicsSettings settings)\n                    continue;\n\n                if (Unsupported.IsDeveloperMode())\n                    return true; // TODO: Remove when all HDRP and URP settings have been fully migrated\n\n                if (settings.GetType().GetCustomAttribute<HideInInspector>() == null)\n                    return true;\n            }\n\n            return false;\n        }\n\n        internal static RenderPipelineGlobalSettings GetRenderPipelineGlobalSettingsByIndex(SerializedProperty srpDefaultSettings, int i)\n        {\n            var property = srpDefaultSettings.GetArrayElementAtIndex(i);\n            var second = property.FindPropertyRelative(\"second\");\n            var globalSettings = second.objectReferenceValue as RenderPipelineGlobalSettings;\n            return globalSettings;\n        }\n\n        internal static string CreateNewTabName(Type globalSettingsType, SupportedOnRenderPipelineAttribute supportedOnRenderPipelineAttribute)\n        {\n            string tabName;\n            var inspectorName = globalSettingsType.GetCustomAttribute<DisplayNameAttribute>();\n            if (inspectorName != null)\n                tabName = inspectorName.DisplayName;\n            else\n            {\n                var pipelineAssetName = supportedOnRenderPipelineAttribute.renderPipelineTypes[0].Name;\n                if (pipelineAssetName.EndsWith(\"Asset\", StringComparison.Ordinal))\n                    pipelineAssetName = pipelineAssetName[..^\"Asset\".Length];\n\n                tabName = GetAbbreviation(pipelineAssetName);\n            }\n\n            return tabName;\n        }\n\n        internal static bool TryExtractSupportedOnRenderPipelineAttribute(Type globalSettingsType, out SupportedOnRenderPipelineAttribute supportedOnRenderPipelineAttribute, out string message)\n        {\n            supportedOnRenderPipelineAttribute = globalSettingsType.GetCustomAttribute<SupportedOnRenderPipelineAttribute>();\n            if (supportedOnRenderPipelineAttribute == null)\n            {\n                message =\n                    $\"Cannot associate {globalSettingsType.FullName} settings with appropriate {nameof(RenderPipelineAsset)} without {nameof(SupportedOnRenderPipelineAttribute)}. Settings will be skipped and not displayed.\";\n                return false;\n            }\n\n            if (supportedOnRenderPipelineAttribute.renderPipelineTypes.Length != 1)\n            {\n                message =\n                    $\"{nameof(SupportedOnRenderPipelineAttribute)} for {globalSettingsType.FullName} settings must have exactly one parameter. {nameof(RenderPipelineGlobalSettings)} can only be for 1 {nameof(RenderPipeline)}. Settings will be skipped and not displayed.\";\n                return false;\n            }\n\n            if (supportedOnRenderPipelineAttribute.renderPipelineTypes.Length == 1 && supportedOnRenderPipelineAttribute.renderPipelineTypes[0] == typeof(RenderPipelineAsset))\n            {\n                message =\n                    $\"{nameof(SupportedOnRenderPipelineAttribute)} for {globalSettingsType.FullName} settings must have specific non-abstract {nameof(RenderPipelineAsset)} type\";\n                return false;\n            }\n\n            message = string.Empty;\n            return true;\n        }\n\n        internal static string GetAbbreviation(string text)\n        {\n            var nameArray = text.ToCharArray();\n            var builder = new StringBuilder();\n            for (int i = 0; i < nameArray.Length; i++)\n            {\n                if (char.IsUpper(nameArray[i]))\n                    builder.Append(nameArray[i]);\n            }\n\n            var abbreviation = builder.ToString();\n            return abbreviation.Length == 0 ? text : abbreviation;\n        }\n\n        #endregion\n\n        #region UI-relative methods\n\n        //Temp solution until we introduce custom editor support and title support for pipeline assets\n        internal static TabButton CreateNewTab(TabbedView tabView, string tabName, VisualElement tabTarget, bool active = false)\n        {\n            tabTarget.name = $\"{tabName}SettingsContainer\";\n            LocalizeVisualTree(tabTarget);\n\n            var tab = new TabButton(tabName, tabTarget)\n            {\n                name = $\"{tabName}TabButton\"\n            };\n            LocalizeVisualTree(tab);\n            tabView.AddTab(tab, active);\n            return tab;\n        }\n\n        internal static VisualElement CreateRPHelpBox(VisibilityControllerBasedOnRenderPipeline visibilityController, Type currentAssetType)\n        {\n            var helpBoxTemplate = EditorGUIUtility.Load(GraphicsSettingsInspector.GraphicsSettingsData.helpBoxesTemplateForSRP) as VisualTreeAsset;\n            var helpBoxContainer = helpBoxTemplate.Instantiate();\n            LocalizeVisualTree(helpBoxContainer);\n\n            var allRenderPipelineAssetTypes = TypeCache.GetTypesDerivedFrom<RenderPipelineAsset>();\n            var allAssetsExceptCurrent = new Type[allRenderPipelineAssetTypes.Count];\n            for (int j = 0, index = 0; j < allRenderPipelineAssetTypes.Count; j++, index++)\n            {\n                if (currentAssetType != null && allRenderPipelineAssetTypes[j] == currentAssetType)\n                {\n                    index--;\n                    continue;\n                }\n\n                allAssetsExceptCurrent[index] = allRenderPipelineAssetTypes[j] == null ? null : allRenderPipelineAssetTypes[j];\n            }\n\n            var infoHelpBox = helpBoxContainer.MandatoryQ<HelpBox>(\"CurrentPipelineInfoHelpBox\");\n            var warningHelpBox = helpBoxContainer.MandatoryQ<HelpBox>(\"CurrentPipelineWarningHelpBox\");\n            visibilityController.RegisterVisualElement(infoHelpBox, currentAssetType);\n            visibilityController.RegisterVisualElement(warningHelpBox, allAssetsExceptCurrent);\n\n            if (Unsupported.IsDeveloperMode())\n            {\n                helpBoxContainer.Add(new HelpBox($\"Developer Mode is enabled. HideInInspector attribute, for {nameof(IRenderPipelineGraphicsSettings)}, will be ignored.\", HelpBoxMessageType.Info));\n            }\n\n            return helpBoxContainer;\n        }\n\n        internal static TabButton GetTabButtonForRenderPipelineAssetType(VisualElement root, Type renderPipelineAssetType)\n        {\n            return root.Query<TabButton>().Where(t => t.userData as Type == renderPipelineAssetType).First();\n        }\n\n        internal static Type GetRenderPipelineAssetTypeForSelectedTab(VisualElement root)\n        {\n            var tabbedView = root.Q<TabbedView>();\n            var currentActiveTab = tabbedView?.ActiveTab;\n            return currentActiveTab?.userData as Type;\n        }\n\n        internal static void ReloadGraphicsSettingsEditorIfNeeded()\n        {\n            if (!EditorWindow.HasOpenInstances<ProjectSettingsWindow>())\n                return;\n\n            var settingsWindow = EditorWindow.GetWindow<ProjectSettingsWindow>(null, false);\n            if (settingsWindow.GetCurrentProvider() is not GraphicsSettingsProvider provider)\n                return;\n\n            if(provider.inspector == null)\n                return;\n\n            provider.Reload();\n        }\n\n        internal static int ComputeRenderPipelineGlobalSettingsListHash(List<GlobalSettingsContainer> settingsContainers)\n        {\n            bool haveSettings = settingsContainers is { Count: > 0 };\n            if (!haveSettings)\n                return 0;\n\n            var currentHash = new HashCode();\n            currentHash.Add(GraphicsSettings.currentRenderPipelineAssetType?.ToString() ?? \"\");\n            foreach (var globalSettings in settingsContainers)\n            {\n                TryGetSettingsListFromRenderPipelineGlobalSettings(\n                    globalSettings.serializedObject.targetObject as RenderPipelineGlobalSettings,\n                    out SerializedObject _,\n                    out SerializedProperty _,\n                    out SerializedProperty settingsListInContainer);\n                currentHash.Add(settingsListInContainer.contentHash);\n            }\n            return currentHash.ToHashCode();\n        }\n\n        #endregion\n\n        #region OpenAndScrollTo\n\n        const string highlightableClass = \"graphics-settings__highlightable\";\n        const string highlightableColorClass = \"graphics-settings__highlightable--background-color\";\n\n        static int s_EventCounter;\n        static VisualElement s_SearchedElement;\n        static readonly List<Foldout> k_Foldouts = new();\n\n        public static void OpenAndScrollTo(string propertyPath)\n        {\n            if (string.IsNullOrEmpty(propertyPath))\n                throw new ArgumentException(nameof(propertyPath), $\"The {nameof(propertyPath)} argument can't be null or empty.\");\n\n            OpenAndScrollTo<PropertyField, PropertyField>(\n                root => TryFindPropertyAndTabByBindingPath(propertyPath, root, out var tabbedView, out var tabButton, out var propertyField)\n                    ? (true, tabbedView, tabButton, propertyField)\n                    : (false, null, null, null),\n                () => $\"Couldn't find a property with bindingPath {propertyPath} in the settings container.\",\n                (scrollView, _, propertyField, _) => OpenFoldoutsThenScroll(propertyField, scrollView));\n        }\n\n        public static void OpenAndScrollTo(Type renderPipelineGraphicsSettingsType)\n        {\n            OpenAndScrollTo<PropertyField>(renderPipelineGraphicsSettingsType);\n        }\n\n        public static void OpenAndScrollTo<TGraphicsSettings>(string propertyPath = \"\")\n            where TGraphicsSettings : IRenderPipelineGraphicsSettings\n        {\n            OpenAndScrollTo<TGraphicsSettings, PropertyField>(p => p.bindingPath.Contains(propertyPath));\n        }\n\n        public static void OpenAndScrollTo<TGraphicsSettings, TVisualElement>(Func<TVisualElement, bool> subElementFunc = null)\n            where TGraphicsSettings : IRenderPipelineGraphicsSettings\n            where TVisualElement : VisualElement\n        {\n            OpenAndScrollTo(typeof(TGraphicsSettings), subElementFunc);\n        }\n\n        /// <summary>\n        /// Open the Graphics Settings window and scroll to the specified Render Pipeline Graphics Settings type.\n        /// </summary>\n        /// <param name=\"renderPipelineGraphicsSettingsType\">Type of the IRenderPipelineGraphicsSettings to search for.</param>\n        /// <param name=\"subElementFunc\">Provide a Func to search for sub element in the IRenderPipelineGraphicsSettings drawer.</param>\n        /// <typeparam name=\"TVisualElement\">Type of the VisualElement to searcg for.</typeparam>\n        /// <exception cref=\"ArgumentNullException\">Throw if a renderPipelineGraphicsSettingsType is null.</exception>\n        /// <exception cref=\"ArgumentException\">Throw if a renderPipelineGraphicsSettingsType type is not derived from IRenderPipelineGraphicsSettings.</exception>\n        internal static void OpenAndScrollTo<TVisualElement>(Type renderPipelineGraphicsSettingsType, Func<TVisualElement, bool> subElementFunc = null)\n            where TVisualElement : VisualElement\n        {\n            if (renderPipelineGraphicsSettingsType == null)\n                throw new ArgumentNullException(nameof(renderPipelineGraphicsSettingsType));\n            if (!typeof(IRenderPipelineGraphicsSettings).IsAssignableFrom(renderPipelineGraphicsSettingsType))\n                throw new ArgumentException($\"{nameof(IRenderPipelineGraphicsSettings)} is not assignable from {nameof(renderPipelineGraphicsSettingsType)}\");\n\n            OpenAndScrollTo(\n                root => TryFindTabByType(renderPipelineGraphicsSettingsType, root, out var tabbedView, out var tabButton, out var bindingPath)\n                    ? (true, tabbedView, tabButton, bindingPath)\n                    : (false, tabbedView, null, null),\n                () => $\"Couldn't find a tab for {renderPipelineGraphicsSettingsType.Name} type in the settings container.\",\n                SearchForVisualElementInTabsAndScroll,\n                subElementFunc);\n        }\n\n        /// <summary>\n        /// Open the Graphics Settings window and scroll to the field specified by the set of methods.\n        /// </summary>\n        /// <param name=\"searchForVisualElement\">Search for a visual element that corresponds to the propertyPath or IRenderPipelineGraphicsSettings type.</param>\n        /// <param name=\"message\">Message to log if the visual element wasn't found. It will also return tabbed view if exists and tab button if it contains a visual element.</param>\n        /// <param name=\"execute\">Execute the method to scroll to the visual element.</param>\n        /// <param name=\"subElementFunc\">Provide a Func to search for sub element in the IRenderPipelineGraphicsSettings drawer.</param>\n        /// <typeparam name=\"TVisualElement\">Type of the VisualElement to search for.</typeparam>\n        /// <typeparam name=\"TResult\">Type of the result data. Either binding path of the property field or property field itself.</typeparam>\n        static void OpenAndScrollTo<TVisualElement, TResult>(\n            Func<VisualElement, (bool, TabbedView, TabButton, TResult)> searchForVisualElement,\n            Func<string> message, Action<ScrollView, TabButton, TResult, Func<TVisualElement, bool>> execute,\n            Func<TVisualElement, bool> subElementFunc = null)\n            where TVisualElement : VisualElement\n        {\n            var settingsWindow = GetOrOpenGraphicsSettingsWindow(out var previousWindowState);\n            var root = settingsWindow.rootVisualElement;\n\n            //Wait for the window to layout if a window changed provider or open first time and then find the tabs.\n            RegisterCallbackOnceOrCallImmediately<GeometryChangedEvent>(previousWindowState is PreviousWindowState.Opened or PreviousWindowState.IncorrectProvider, settingsWindow.rootVisualElement, () =>\n            {\n                var (result, tabbedView, tabButton, resultedData) = searchForVisualElement.Invoke(root);\n                if (!result)\n                {\n                    Debug.LogWarning(message.Invoke());\n                    return;\n                }\n\n                var isTabbedViewNull = tabbedView == null;\n                var isCorrectTabOpen = isTabbedViewNull || tabButton == null || tabbedView.ActiveTab == tabButton;\n                var scrollView = root.Q<ScrollView>(\"MainScrollView\");\n\n                //Wait for the tab to layout if active tab was switched and then search for the VisualElement. Added a special check for the built-in settings because it will produce only one event when tab switch to it.\n                RegisterCallbackOnceOrCallImmediately<GeometryChangedEvent>(isTabbedViewNull || previousWindowState is PreviousWindowState.Opened, tabbedView,\n                    () => RegisterCallbackOnceOrCallImmediately<GeometryChangedEvent>(isTabbedViewNull || isCorrectTabOpen || tabbedView.ActiveTab.userData as string == GraphicsSettingsInspector.GraphicsSettingsData.builtIn, tabbedView,\n                        () => root.schedule.Execute(() => execute.Invoke(scrollView, tabButton, resultedData, subElementFunc)).StartingIn(500)));\n\n                if (!isTabbedViewNull && !isCorrectTabOpen)\n                    tabbedView.Activate(tabButton);\n            });\n        }\n\n        /// <summary>\n        /// Get or open the Graphics Settings window and focus on it.\n        /// </summary>\n        /// <param name=\"previousWindowState\"> The state of the window before the method was called.</param>\n        /// <returns>ProjectSettings window with selected Graphics Settings page.</returns>\n        internal static ProjectSettingsWindow GetOrOpenGraphicsSettingsWindow(out PreviousWindowState previousWindowState)\n        {\n            previousWindowState = PreviousWindowState.Opened;\n            if (!EditorWindow.HasOpenInstances<ProjectSettingsWindow>())\n            {\n                previousWindowState = PreviousWindowState.NotOpened;\n                return SettingsService.OpenProjectSettings(GraphicsSettingsProvider.s_GraphicsSettingsProviderPath) as ProjectSettingsWindow;\n            }\n\n            var settingsWindow = EditorWindow.GetWindow<ProjectSettingsWindow>(null, true);\n            if (settingsWindow.GetCurrentProvider() is GraphicsSettingsProvider && settingsWindow.rootVisualElement != null)\n                return settingsWindow;\n\n            previousWindowState = PreviousWindowState.IncorrectProvider;\n            settingsWindow = SettingsService.OpenProjectSettings(GraphicsSettingsProvider.s_GraphicsSettingsProviderPath) as ProjectSettingsWindow;\n            settingsWindow.Show();\n            return settingsWindow;\n        }\n\n        /// <summary>\n        /// Find the PropertyField and TabbedView by binding path.\n        /// </summary>\n        /// <param name=\"propertyPath\">Property Path of the element.</param>\n        /// <param name=\"root\">Root VisualElement to search for Tabs.</param>\n        /// <param name=\"tabbedView\">Visual Element that contains all tabs and bodies. Null if there's none.</param>\n        /// <param name=\"tabButton\">Tab that contains property field. Null if there's none.</param>\n        /// <param name=\"propertyField\">Property Field the contains provided property path.</param>\n        /// <returns>True if the search was successful.</returns>\n        static bool TryFindPropertyAndTabByBindingPath(string propertyPath, VisualElement root, out TabbedView tabbedView, out TabButton tabButton, out PropertyField propertyField)\n        {\n            tabbedView = root.Q<TabbedView>();\n            tabButton = null;\n\n            propertyField = root.Query<PropertyField>().Where(p => propertyPath.Contains(p.bindingPath)).First();\n            if (propertyField == null)\n                return false;\n\n            if (tabbedView != null)\n                tabButton = propertyField.GetFirstAncestorOfType<TabButton>();\n            return true;\n        }\n\n        /// <summary>\n        /// Find the tab and binding path for the Render Pipeline Graphics Settings type.\n        /// </summary>\n        /// <param name=\"renderPipelineGraphicsSettingsType\">Type of the IRenderPipelineGraphicsSettings</param>\n        /// <param name=\"root\">Root VisualElement to search for the TabbedView.</param>\n        /// <param name=\"tabbedView\">TabbedView that contains all tabs.</param>\n        /// <param name=\"tabButton\">Tab which contains IRenderPipelineGraphicsSettings.</param>\n        /// <param name=\"bindingPath\">Real bindingPath of the IRenderPipelineGraphicsSettings.</param>\n        /// <returns>True if the search was successful.</returns>\n        static bool TryFindTabByType(Type renderPipelineGraphicsSettingsType, VisualElement root, out TabbedView tabbedView, out TabButton tabButton, out string bindingPath)\n        {\n            tabButton = null;\n            bindingPath = \"\";\n\n            tabbedView = root.Q<TabbedView>();\n            if (tabbedView == null)\n                return false;\n\n            TabButton lambdaTabButton = null;\n            string lambdaBindingPath = \"\";\n            EditorGraphicsSettings.ForEachPipelineSettings(gs =>\n            {\n                if (gs == null)\n                    return;\n\n                if (!TryExtractSupportedOnRenderPipelineAttribute(gs.GetType(), out var globalSettingsSupportedOn, out var message))\n                    return;\n                var tabButton = root.Query<TabButton>().Where(tb =>\n                {\n                    if (tb.userData is not Type renderPipelineAssetType)\n                        return false;\n\n                    return globalSettingsSupportedOn.renderPipelineTypes[0] == renderPipelineAssetType;\n                }).First();\n\n                if (tabButton == null)\n                    return;\n\n                var index = gs.IndexOf(renderPipelineGraphicsSettingsType);\n                if (index < 0)\n                    return;\n\n                lambdaTabButton = tabButton;\n                lambdaBindingPath = $\"{RenderPipelineGraphicsSettingsManager.serializationPathToCollection}.Array.data[{index}]\";\n            });\n            if (!string.IsNullOrEmpty(lambdaBindingPath))\n                (tabButton, bindingPath) = (lambdaTabButton, lambdaBindingPath);\n            return tabButton != null;\n        }\n\n        /// <summary>\n        /// Search for the VisualElement in the tabs and scroll to it.\n        /// </summary>\n        /// <param name=\"subElementFunc\">Method to search for sub element of the IRenderPipelineGraphicsSettings.</param>\n        /// <param name=\"tabButton\">Tab to search for the VisualElement.</param>\n        /// <param name=\"bindingPath\">Binding path of the IRenderPipelineGraphicsSettings.</param>\n        /// <param name=\"root\">Root VisualElement to search for the Main ScrollView.</param>\n        /// <typeparam name=\"TVisualElement\">Type of the VisualElement to search for.</typeparam>\n        static void SearchForVisualElementInTabsAndScroll<TVisualElement>(ScrollView scrollView, TabButton tabButton, string bindingPath, Func<TVisualElement, bool> subElementFunc)\n            where TVisualElement : VisualElement\n        {\n            var target = tabButton.Target;\n            VisualElement field = target\n                .Query<PropertyField>()\n                .Where(p => string.CompareOrdinal(p.bindingPath, bindingPath) == 0)\n                .First();\n\n            if (field == null)\n                return;\n\n            // If the subElementFunc is null, we just want to scroll to the field.\n            if (subElementFunc == null)\n            {\n                OpenFoldoutsThenScroll(field, scrollView);\n                return;\n            }\n\n            var subElement = field.Query<TVisualElement>().Where(subElementFunc.Invoke).First();\n            // If the subElement is found, we just want to scroll to it.\n            if (subElement != null)\n            {\n                OpenFoldoutsThenScroll(subElement, scrollView);\n                return;\n            }\n\n            // This could mean that the field hidden in the Foldout.\n            // Let's try to find the Foldout and open it.\n            s_SearchedElement = null;\n            k_Foldouts.Clear();\n            field.Query<Foldout>().Where(f => !f.value).ForEach(\n                f => ExpandFoldoutAndChildren(f, subElementFunc, foundElement =>\n                {\n                    s_SearchedElement = null;\n                    k_Foldouts.Clear();\n                    OpenFoldoutsThenScroll(foundElement, scrollView);\n                }));\n        }\n\n        /// <summary>\n        /// Expand a foldout and all child's foldout until the searched element is found.\n        /// </summary>\n        /// <param name=\"foldout\">Foldout to expand.</param>\n        /// <param name=\"subElementFunc\">Condition to determine correct Visual Element.</param>\n        /// <param name=\"onFinished\">When correct VisualElement found then call this method with it.</param>\n        /// <typeparam name=\"TVisualElement\">VisualElement type to search for.</typeparam>\n        static void ExpandFoldoutAndChildren<TVisualElement>(Foldout foldout, Func<TVisualElement, bool> subElementFunc, Action<VisualElement> onFinished)\n            where TVisualElement : VisualElement\n        {\n            if(s_SearchedElement != null)\n                return;\n\n            k_Foldouts.Add(foldout);\n            foldout.value = true;\n\n            //We use Execute and Delay with starting 1 to be sure that foldouts loaded and layouted.\n            foldout.schedule.Execute(() =>\n            {\n                s_SearchedElement = foldout.Query<TVisualElement>().Where(subElementFunc.Invoke).First();\n                if (s_SearchedElement != null)\n                {\n                    foreach (var openedFoldout in k_Foldouts)\n                    {\n                        if (!openedFoldout.Contains(s_SearchedElement))\n                            openedFoldout.value = false;\n                    }\n\n                    onFinished.Invoke(s_SearchedElement);\n                    return;\n                }\n\n                var childFoldouts = foldout.Query<Foldout>().ToList();\n                foreach (var childFoldout in childFoldouts)\n                {\n                    ExpandFoldoutAndChildren(childFoldout, subElementFunc, onFinished);\n                }\n            }).StartingIn(1);\n        }\n\n        /// <summary>\n        /// Open all Foldouts and scroll to the provided field.\n        /// </summary>\n        /// <param name=\"field\">Field to check for open foldouts in parents.</param>\n        /// <param name=\"scrollView\">Main Scroll View of the Graphics Settings page.</param>\n        /// <typeparam name=\"T\">Type of the VisualElement.</typeparam>\n        static void OpenFoldoutsThenScroll<T>(T field, ScrollView scrollView)\n            where T : VisualElement\n        {\n            var current = field.parent;\n\n            s_EventCounter = 0;\n            while (current != null)\n            {\n                if (current is Foldout { value: false } foldout)\n                {\n                    s_EventCounter++;\n                    foldout.contentContainer.RegisterCallbackOnce<GeometryChangedEvent>(_ =>\n                    {\n                        s_EventCounter--;\n                        if (s_EventCounter != 0)\n                            return;\n\n                        scrollView.UpdateScrollers(scrollView.needsHorizontal, true);\n                        ScrollTo(field, scrollView);\n                    });\n                    foldout.value = true;\n                }\n\n                current = current.parent;\n            }\n\n            if (s_EventCounter == 0)\n                ScrollTo(field, scrollView);\n        }\n\n        /// <summary>\n        /// Scroll to the provided field and highlight it.\n        /// </summary>\n        /// <param name=\"field\">Provided VisualElement.</param>\n        /// <param name=\"scrollView\">Main Scroll View of the Graphics Settings page.</param>\n        /// <typeparam name=\"T\">Type of the VisualElement.</typeparam>\n        static void ScrollTo<T>(T field, ScrollView scrollView)\n            where T : VisualElement\n        {\n            scrollView.schedule.Execute(() =>\n            {\n                scrollView.ScrollTo(field);\n                field.AddToClassList(highlightableClass);\n                field.AddToClassList(highlightableColorClass);\n                field.RegisterCallbackOnce<TransitionEndEvent>(_ =>\n                {\n                    field.RemoveFromClassList(highlightableColorClass);\n                    field.RegisterCallbackOnce<TransitionEndEvent>(_ =>\n                        field.RemoveFromClassList(highlightableClass));\n                });\n            });\n        }\n\n        /// <summary>\n        /// Utility method to register a callback once or call it immediately if the condition is true.\n        /// </summary>\n        /// <param name=\"immediateCondition\">Condition to check.</param>\n        /// <param name=\"element\">Subscribe to the event on this VisualElement.</param>\n        /// <param name=\"callback\">Call this callback when finished.</param>\n        /// <typeparam name=\"T\">Type of the event to subscribe.</typeparam>\n        static void RegisterCallbackOnceOrCallImmediately<T>(bool immediateCondition, VisualElement element, Action callback)\n            where T : EventBase<T>, new()\n        {\n            if (immediateCondition)\n                callback?.Invoke();\n            else\n                element.RegisterCallbackOnce<T>(_ => callback?.Invoke());\n        }\n\n        /// <summary>\n        /// State of the window before GetOrOpenGraphicsSettingsWindow method was called. Used to determine how many layout events we expect.\n        /// </summary>\n        internal enum PreviousWindowState\n        {\n            /// <summary>\n            /// Window was not opened before.\n            /// </summary>\n            NotOpened,\n            /// <summary>\n            /// Window had different page open. We need to wait for the Graphics Settings page to open and layout.\n            /// </summary>\n            IncorrectProvider,\n            /// <summary>\n            /// Window was already opened with the Graphics Settings page.\n            /// </summary>\n            Opened\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/GraphicsSettingsInspectors/RenderPipelineGlobalSettingsAssetProcessor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n﻿using System;\nusing UnityEditor.Inspector.GraphicsSettingsInspectors;\nusing UnityEditor.Rendering;\n\nnamespace UnityEditor.Mono.Inspector.GraphicsSettingsInspectors\n{\n    internal class RenderPipelineGlobalSettingsAssetProcessor : AssetModificationProcessor\n    {\n        public static AssetDeleteResult OnWillDeleteAsset(string assetPath, RemoveAssetOptions option)\n        {\n            if (!EditorWindow.HasOpenInstances<ProjectSettingsWindow>())\n                return AssetDeleteResult.DidNotDelete;\n\n            var settingsWindow = EditorWindow.GetWindow<ProjectSettingsWindow>(null, false);\n            if (settingsWindow.GetCurrentProvider() is not GraphicsSettingsProvider currentProvider)\n                return AssetDeleteResult.DidNotDelete;\n\n            foreach (var globalSetting in currentProvider.inspector.globalSettings)\n            {\n                if (string.Compare(globalSetting.path, assetPath, StringComparison.InvariantCultureIgnoreCase) != 0)\n                    continue;\n\n                settingsWindow.m_Parent.Reload(settingsWindow);;\n                return AssetDeleteResult.DidNotDelete;\n            }\n\n            return AssetDeleteResult.DidNotDelete;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/GraphicsSettingsInspectors/RenderPipelineGraphicsSettingsPropertyDrawer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Rendering;\nusing UnityEditor.UIElements;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Inspector.GraphicsSettingsInspectors\n{\n    [CustomPropertyDrawer(typeof(IRenderPipelineGraphicsSettings), useForChildren: true)]\n    class RenderPipelineGraphicsSettingsPropertyDrawer : PropertyDrawer\n    {\n        public static bool IsEmpty(SerializedProperty property, out string warnings)\n        {\n            if (!property.hasVisibleChildren)\n            {\n                warnings = $\"This {nameof(IRenderPipelineGraphicsSettings)} has no visible children. Consider using {nameof(HideInInspector)} if you want to completely hide the setting.\";\n                return true;\n            }\n\n            warnings = string.Empty;\n            return false;\n        }\n\n        // Used in Unit tests\n        public static IEnumerable<SerializedProperty> VisibleChildrenEnumerator(SerializedProperty property)\n            => ChildrenEnumerator(property, includeInvisible: false, deepSearch: false, p => true);\n\n        internal static IEnumerable<SerializedProperty> ChildrenEnumerator(SerializedProperty property, bool includeInvisible, bool deepSearch, Func<SerializedProperty, bool> selector = null)\n        {\n            if (!property.hasVisibleChildren)\n                yield break;\n\n            selector ??= p => true;\n\n            var iterator = property.Copy();\n            var end = iterator.GetEndProperty(includeInvisible);\n\n            // Move to the first child property\n            if (includeInvisible)\n                iterator.Next(true);\n            else\n                iterator.NextVisible(true);\n\n            do\n            {\n                if (selector(iterator))\n                    yield return iterator;\n                if (includeInvisible)\n                    iterator.Next(deepSearch);\n                else\n                    iterator.NextVisible(deepSearch);\n            } while (!SerializedProperty.EqualContents(iterator, end)); // Move to the next sibling property\n        }\n\n        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n        {\n            if (IsEmpty(property, out var warnings))\n            {\n                EditorGUI.HelpBox(position, warnings, MessageType.Warning);\n                return;\n            }\n\n            int baseNameLength = property.propertyPath.Length + 1;\n            foreach (var child in VisibleChildrenEnumerator(property))\n            {\n                Rect childPosition = position;\n                childPosition.height = EditorGUI.GetPropertyHeight(child);\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.PropertyField(childPosition, child);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    child.serializedObject.ApplyModifiedProperties();\n                    var settings = property.boxedValue as IRenderPipelineGraphicsSettings;\n                    settings.NotifyValueChanged(child.propertyPath.Substring(baseNameLength));\n                }\n                position.y += childPosition.height + EditorGUIUtility.standardVerticalSpacing;\n            }\n        }\n\n        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)\n        {\n            float height = 0f;\n            foreach (var child in VisibleChildrenEnumerator(property))\n                height += EditorGUI.GetPropertyHeight(child) + EditorGUIUtility.standardVerticalSpacing;\n            if (height > 0)\n                height -= EditorGUIUtility.standardVerticalSpacing; //remove last one\n            return height;\n        }\n\n        public override VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            VisualElement root = new();\n\n            if (IsEmpty(property, out var warnings))\n            {\n                root.Add(new HelpBox(warnings, HelpBoxMessageType.Warning));\n                return root;\n            }\n\n            foreach (var child in VisibleChildrenEnumerator(property))\n            {\n                var propertyField = new PropertyField(child);\n                propertyField.RegisterCallback(PropagateOnChangeRecursivelyAtBinding(propertyField));\n                root.Add(propertyField);\n            }\n\n            return root;\n        }\n\n        EventCallback<SerializedPropertyBindEvent> PropagateOnChangeRecursivelyAtBinding(PropertyField propertyField)\n        {\n            EventCallback<SerializedPropertyBindEvent> callback = null;\n            callback = (SerializedPropertyBindEvent evt) => {\n                UQueryState<VisualElement> childs;\n                if(evt.bindProperty.isArray\n                    || (childs = propertyField.Query(name: \"unity-content\").Visible().Build())\n                        .AtIndex(0) == null) //no child\n                {\n                    // Fields that have no childs or array (handle all resizing and cell changes directly)\n                    bool isBindingTime = true;\n                    propertyField.RegisterCallback<SerializedPropertyChangeEvent>(evt =>\n                    {\n                        if (isBindingTime)\n                        {\n                            isBindingTime = false;\n                            return;\n                        }\n                        AddNotificationRequest(evt);\n                    });\n                }\n                else\n                {\n                    // Propagate to custom struct and class childs\n                    childs.ForEach(e => e.Query<PropertyField>().Visible().ForEach(p => p.RegisterCallback(PropagateOnChangeRecursivelyAtBinding(p))));\n                }\n                \n                propertyField.UnregisterCallback(callback);\n                callback = null;\n            };\n            return callback;\n        }\n\n        void AddNotificationRequest(SerializedPropertyChangeEvent evt)\n            => Notifier.AddNotificationRequest(evt.changedProperty);\n    }\n\n    // Aim is to batch notification for case where several are trigerred.\n    // Example:\n    //  - Modifying a color, several channel amongst r, g, b, a can be altered with same editor modification\n    //  - This result in several time the SerializedPropertyChangeEvent being raised.\n    // Also at binding we do not want to raise notification. As there is a previous SerializedObject state to\n    // compare, we can trim that, even for Arrays that have a lot of elements to bind/update.\n    static internal class Notifier\n    {\n        struct NotificationRequest\n        {\n            public IRenderPipelineGraphicsSettings rpgs;\n            public string path;\n\n            public NotificationRequest(SerializedProperty property)\n            {\n                ExtractFirstPropertyNameInPath(property, out path, out var baseLength);\n                rpgs = GetRenderPipelineGraphicsSettings(property, baseLength);\n            }\n\n            //This extraction start at IRenderPipelineGraphicsSettings as a root\n            //m_Settings.m_SettingsList.m_List.Array.data[x].embeddedobject.property -> embeddedobject\n            static void ExtractFirstPropertyNameInPath(SerializedProperty property, out string propertyName, out int baseLength)\n            {\n                propertyName = property.propertyPath;\n                baseLength = propertyName.IndexOf(']') + 2;\n                   \n                int length = propertyName.IndexOf('.', baseLength) - baseLength;\n                propertyName = length < 0\n                    ? propertyName.Substring(baseLength)\n                    : propertyName.Substring(baseLength, length);\n            }\n                \n            static IRenderPipelineGraphicsSettings GetRenderPipelineGraphicsSettings(SerializedProperty property, int baseLength)\n                => property.serializedObject.FindProperty(property.propertyPath.Substring(0, baseLength - 1)).boxedValue as IRenderPipelineGraphicsSettings;\n\n            static public bool operator ==(NotificationRequest a, NotificationRequest b)\n                => a.rpgs.GetType() == b.rpgs.GetType() && a.path == b.path;\n                \n            static public bool operator !=(NotificationRequest a, NotificationRequest b)\n                => !(a == b);\n\n            public override bool Equals(object obj)\n                => obj is NotificationRequest request && request == this;\n\n            public override int GetHashCode()\n                => HashCode.Combine(rpgs, path);\n        }\n\n        static HashSet<NotificationRequest> s_NotificationRequests = new();\n        static bool s_Scoped = false;\n        static Dictionary<Type, SerializedObject> s_SharedPreviousStates = null;\n\n        [InitializeOnLoadMethod]\n        static void OnDomainReload()\n            => RenderPipelineManager.activeRenderPipelineCreated += RecomputeDictionary;\n\n        internal static void RecomputeDictionary()\n        {\n            s_SharedPreviousStates = new();\n            EditorGraphicsSettings.ForEachPipelineSettings(gs => {\n                if (gs != null)\n                    s_SharedPreviousStates[gs.GetType()] = new SerializedObject(gs);\n            });\n        }\n\n        static void UpdatePreviousState(SerializedProperty property)\n            => GetPreviousState(property).Update();\n\n        static SerializedObject GetPreviousState(SerializedProperty property)\n        {\n            var type = property.serializedObject.targetObject.GetType();\n            return s_SharedPreviousStates[type];\n        }\n\n        static public void AddNotificationRequest(SerializedProperty property)\n        {\n            if (property == null)\n                throw new ArgumentException(\"Property cannot be null.\", $\"{nameof(property)}\");\n\n            //If GraphicsSettings window was open when project open, s_SharedPreviousStates can still be null when we call this.\n            if (s_SharedPreviousStates == null)\n                RecomputeDictionary();\n            \n            bool dataEquals = SerializedProperty.DataEquals(property, GetPreviousState(property).FindProperty(property.propertyPath));\n            if (dataEquals && !s_Scoped)\n                return;\n\n            NotificationRequest candidate = new(property);\n            if (dataEquals && s_NotificationRequests.Contains(candidate))\n                return;\n\n            UpdatePreviousState(property);\n            Register(candidate);\n        }\n\n        static void Register(NotificationRequest verifiedRequest)\n        {\n            if (!s_Scoped && s_NotificationRequests.Count == 0)\n                EditorApplication.CallDelayed(Notify);\n\n            s_NotificationRequests.Add(verifiedRequest);\n        }\n\n        static void Notify()\n        {\n            foreach (var request in s_NotificationRequests)\n                request.rpgs.NotifyValueChanged(request.path);\n            s_NotificationRequests.Clear();\n        }\n\n        static void BeginScope()\n        {\n            //If GraphicsSettings window was open when project open, s_SharedPreviousStates can still be null when we create Scope.\n            if (s_SharedPreviousStates == null)\n                RecomputeDictionary();\n\n            s_Scoped = true;\n        }\n\n        static void EndScope()\n        {\n            s_Scoped = false;\n            Notify();\n        }\n\n        //For bulk changes like in Reset, we actually need to notify different field even if the serialization change only once\n        //Note that this can also be used to iterate over collection of IRenderPipelineGRaphicsSettings.\n        internal struct Scope : IDisposable\n        {\n            SerializedProperty propertyToInspect;\n            SerializedProperty stateBeforeChange;\n\n            public Scope(SerializedProperty property, bool updateStateNow = true)\n            {\n                BeginScope();\n                propertyToInspect = property;\n                stateBeforeChange = updateStateNow\n                    ? CreateUnlinkedDataStateFromCurrentDataInMemory(property)\n                    : CreateUnlinkedDataStateFromPreviousState(property);\n            }\n\n            static SerializedProperty CreateUnlinkedDataStateFromCurrentDataInMemory(SerializedProperty property)\n                => new SerializedObject(GetPreviousState(property).targetObject).FindProperty(property.propertyPath);\n\n            static SerializedProperty CreateUnlinkedDataStateFromPreviousState(SerializedProperty property)\n            {\n                SerializedObject oldStateReconstructed = new SerializedObject(GetPreviousState(property).targetObject);\n\n                //Any array size difference will cause type tree to have different hash due to the varying size. \n                //To be able to copy the data we first need to fix any child array property\n                foreach (var dynamicSizeChild in RenderPipelineGraphicsSettingsPropertyDrawer.ChildrenEnumerator(property, includeInvisible: true, deepSearch: true, p => p.isArray))\n                {\n                    //AnimationCurv are detected 2 time as an array: ac.m_Curve and ac.m_Curve.Array Only the second one have a size\n                    var size = GetPreviousState(property).FindProperty($\"{dynamicSizeChild.propertyPath}.size\");\n                    if (size == null)\n                        continue;\n\n                    oldStateReconstructed.CopyFromSerializedProperty(size);\n                }\n\n                oldStateReconstructed.CopyFromSerializedProperty(GetPreviousState(property).FindProperty(property.propertyPath));\n                return oldStateReconstructed.FindProperty(property.propertyPath);\n            }\n\n            void IDisposable.Dispose()\n            {\n                // in case we iterate with next, go back to original path\n                if (propertyToInspect.propertyPath != stateBeforeChange.propertyPath)\n                    propertyToInspect = propertyToInspect.serializedObject.FindProperty(stateBeforeChange.propertyPath);\n\n                RecursivelyNotify();\n                EndScope();\n            }\n            \n            void RecursivelyNotify()\n            {\n                void Recurse(SerializedProperty newIt, SerializedProperty oldIt, SerializedProperty end)\n                {\n                    do\n                    {\n                        if (newIt.hasVisibleChildren)\n                        {\n                            if (newIt.isArray && newIt.arraySize != oldIt.arraySize)\n                            {\n                                AddNotificationRequest(newIt);\n                                newIt.NextVisible(false);\n                                oldIt.NextVisible(false);\n                                continue;\n                            }\n\n                            var childEnd = newIt.GetEndProperty();\n\n                            var childNewIt = newIt.Copy();\n                            var childOldIt = oldIt.Copy();\n                            childNewIt.NextVisible(true);\n                            childOldIt.NextVisible(true);\n\n                            Recurse(childNewIt, childOldIt, childEnd);\n                        }\n                        else\n                        {\n                            if (!SerializedProperty.DataEquals(newIt, oldIt))\n                                AddNotificationRequest(newIt);\n                        }\n\n                        newIt.NextVisible(false);\n                        oldIt.NextVisible(false);\n                    }\n                    while (!SerializedProperty.EqualContents(newIt, end));\n                }\n                var end = propertyToInspect.GetEndProperty();\n                Recurse(propertyToInspect, stateBeforeChange, end);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/IEditorElement.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    internal interface IEditorElement\n    {\n        Editor editor { get; }\n        IEnumerable<Editor> Editors { get; }\n\n        void Reinit(int editorIndex, Editor[] editors);\n        void ReinitCulled(int editorIndex, Editor[] editors);\n        void CreateInspectorElement();\n\n        void AddPrefabComponent(VisualElement comp);\n\n        // From VisualElement\n        void RemoveFromHierarchy();\n        string name { get; set; }\n    }\n\n    internal static class EditorElementHelper\n    {\n        internal static Func<int, IPropertyView, string, IEditorElement> CreateFunctor;\n\n        internal static IEditorElement CreateEditorElement(int editorIndex, IPropertyView iw, string title)\n        {\n            return CreateFunctor.Invoke(editorIndex, iw, title);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LODGroupEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor.AnimatedValues;\nusing UnityEditorInternal;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing UnityEditor.Presets;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(LODGroup))]\n    [CanEditMultipleObjects]\n    internal class LODGroupEditor : Editor\n    {\n        private int m_SelectedLODSlider = -1;\n        private int m_SelectedLOD = -1;\n        private int m_NumberOfLODs;\n\n        private LODGroup m_LODGroup;\n        private bool m_IsPrefab;\n        private bool m_IsPreset;\n\n        private int m_SelectedLODGroupCount;\n        private int m_MaxLODCountForMultiselection;\n\n        private SerializedProperty m_FadeMode;\n        private SerializedProperty m_AnimateCrossFading;\n        private SerializedProperty m_LastLODIsBillboard;\n        private SerializedProperty m_LODs;\n        private SerializedProperty m_LODSize;\n\n        private AnimBool m_ShowAnimateCrossFading = new AnimBool();\n        private AnimBool m_ShowFadeTransitionWidth = new AnimBool();\n\n        private Mesh m_BillboardPreviewMesh = null;\n        private MaterialPropertyBlock m_BillboardPreviewProperties = null;\n\n        private int[][] m_PrimitiveCounts;\n        private int[] m_SubmeshCounts;\n        private Texture2D[] m_Textures;\n\n        private GUIContent m_PrimitiveCountLabel;\n        private SavedBool[] m_LODGroupFoldoutHeaderValues = null;\n\n        private ReorderableList[] m_RendererMeshLists;\n        private int[] m_ReoderableMeshListCounts;\n        private int m_ReorderableListIndex = 0;\n\n        private Transform m_TargetTransform;\n\n        private bool m_HasMeshLod;\n        private bool[] m_EnabledMeshLods;\n\n        void InitAndSetFoldoutLabelTextures()\n        {\n            m_Textures = new Texture2D[m_LODs.arraySize];\n            for (int i = 0; i < m_Textures.Length; i++)\n            {\n                m_Textures[i] = new Texture2D(1, 1);\n                m_Textures[i].SetPixel(0, 0, LODGroupGUI.kLODColors[i]);\n            }\n        }\n\n        void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            if (target == null || serializedObject == null)\n                return;\n\n            serializedObject.Update();\n            m_LODs = serializedObject.FindProperty(\"m_LODs\");\n            m_LODSize = m_LODs.serializedObject.FindProperty(\"m_Size\");\n            m_LODGroup = (LODGroup)target;\n\n            ResetValuesAfterLODObjectIsModified();\n            InitAndSetFoldoutLabelTextures();\n            UpdateRendererMeshListCounts();\n        }\n\n        void OnEnable()\n        {\n            m_FadeMode = serializedObject.FindProperty(\"m_FadeMode\");\n            m_AnimateCrossFading = serializedObject.FindProperty(\"m_AnimateCrossFading\");\n            m_LastLODIsBillboard = serializedObject.FindProperty(\"m_LastLODIsBillboard\");\n            m_LODs = serializedObject.FindProperty(\"m_LODs\");\n            m_LODSize = m_LODs.serializedObject.FindProperty(\"m_Size\");\n\n            m_ShowAnimateCrossFading.value = m_FadeMode.intValue != (int)LODFadeMode.None;\n            m_ShowAnimateCrossFading.valueChanged.AddListener(Repaint);\n            m_ShowFadeTransitionWidth.value = false;\n            m_ShowFadeTransitionWidth.valueChanged.AddListener(Repaint);\n\n            EditorApplication.update += Update;\n\n            m_LODGroup = (LODGroup)target;\n            m_SelectedLODGroupCount = targets.Length;\n            m_MaxLODCountForMultiselection = GetMaxLODCountForMultiSelection();\n\n            // Calculate if the newly selected LOD group is a prefab... they require special handling\n            m_IsPrefab = PrefabUtility.IsPartOfPrefabAsset(m_LODGroup.gameObject);\n\n            // this is used to disable the Renderers section if we are viewing a Preset inspector\n            m_IsPreset = Preset.IsEditorTargetAPreset(serializedObject.targetObject);\n\n            CalculatePrimitiveCountForRenderers();\n            m_PrimitiveCountLabel = LODGroupGUI.GUIStyles.m_TriangleCountLabel;\n            ResetFoldoutLists();\n            UpdateRendererMeshListCounts();\n\n            m_TargetTransform = (target as LODGroup)?.gameObject?.transform;\n\n            Undo.undoRedoEvent += OnUndoRedoPerformed;\n            Repaint();\n        }\n\n        private void UpdateEnabledMeshLods()\n        {\n            if (m_EnabledMeshLods == null || m_EnabledMeshLods.Length != m_LODs.arraySize)\n            {\n                m_EnabledMeshLods = new bool[m_LODs.arraySize];\n            }\n            else\n            {\n                Array.Clear(m_EnabledMeshLods, 0, m_EnabledMeshLods.Length);\n            }\n\n            m_HasMeshLod = false;\n\n            for (int i = 0; i < m_LODs.arraySize; i++)\n            {\n                var property = m_RendererMeshLists[i].serializedProperty;\n                for (int r = 0; r < property.arraySize; r++)\n                {\n                    var entry = property.GetArrayElementAtIndex(r).FindPropertyRelative(\"renderer\");\n                    var renderer = entry.objectReferenceValue as Renderer;\n                    if (renderer != null)\n                    {\n                        var mesh = GetMeshFromRendererIfAvailable(renderer);\n                        if (mesh != null && mesh.isLodSelectionActive)\n                        {\n                            m_EnabledMeshLods[i] = true;\n                            m_HasMeshLod = true;\n                        }\n                    }\n                }\n            }\n        }\n\n\n        void UpdateRendererMeshListCounts()\n        {\n            m_ReoderableMeshListCounts = m_RendererMeshLists.Select(i => i.count).ToArray();\n            UpdateEnabledMeshLods();\n        }\n\n        protected virtual void DrawLODRendererMeshListItems(Rect rect, int index, bool isActive, bool isFocused)\n        {\n            Rect objectFieldRect = new Rect(rect.x, rect.y, rect.width * 0.6f, EditorGUI.kSingleLineHeight);\n            rect.height = EditorGUI.kSingleLineHeight;\n\n            if (m_RendererMeshLists.Length != m_ReoderableMeshListCounts.Length || m_RendererMeshLists[m_ReorderableListIndex].count != m_ReoderableMeshListCounts[m_ReorderableListIndex])\n            {\n                CalculatePrimitiveCountForRenderers();\n                UpdateRendererMeshListCounts();\n            }\n\n            var prop = m_RendererMeshLists[m_ReorderableListIndex].serializedProperty.GetArrayElementAtIndex(index).FindPropertyRelative(\"renderer\");\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.ObjectField(objectFieldRect, prop, typeof(Renderer), GUIContent.none);\n            if (EditorGUI.EndChangeCheck())\n            {\n                serializedObject.ApplyModifiedProperties();\n                UpdateRendererMeshListCounts();\n            }\n\n            string labelText = $\"{m_PrimitiveCounts[m_ReorderableListIndex][index]} Tris.\";\n            var size = EditorStyles.label.CalcSize(new GUIContent(labelText));\n            Rect triCountLabelRect = new Rect(rect.x + objectFieldRect.width + 10, rect.y, size.x, EditorGUI.kSingleLineHeight);\n            GUI.Label(triCountLabelRect, labelText);\n\n            var subMeshCount = \"0\";\n            var renderer = prop.objectReferenceValue as Renderer;\n            if (renderer != null)\n            {\n                MeshFilter meshFilter;\n                if (renderer.TryGetComponent(out meshFilter) && meshFilter.sharedMesh != null)\n                    subMeshCount = meshFilter.sharedMesh.subMeshCount.ToString();\n            }\n\n            labelText = $\"{subMeshCount} Sub Mesh(es).\";\n            size = EditorStyles.label.CalcSize(new GUIContent(labelText));\n            triCountLabelRect.x += triCountLabelRect.width;\n            triCountLabelRect.width = size.x;\n            GUI.Label(triCountLabelRect, labelText);\n        }\n\n        protected virtual void DrawLODRendererMeshListHeader(Rect rect)\n        {\n            rect.height = EditorGUI.kSingleLineHeight;\n            GUI.Label(rect, LODGroupGUI.Styles.m_RendersTitle);\n        }\n\n        protected virtual void RemoveLODRendererMeshFromList(ReorderableList list)\n        {\n            ReorderableList.defaultBehaviours.DoRemoveButton(list);\n            CalculatePrimitiveCountForRenderers();\n        }\n\n        protected virtual void AddLODRendererMeshToList(ReorderableList list)\n        {\n            ReorderableList.defaultBehaviours.DoAddButton(list);\n            CalculatePrimitiveCountForRenderers();\n        }\n\n        void OnDisable()\n        {\n            EditorApplication.update -= Update;\n            Undo.undoRedoEvent -= OnUndoRedoPerformed;\n\n            m_ShowAnimateCrossFading.valueChanged.RemoveListener(Repaint);\n            m_ShowFadeTransitionWidth.valueChanged.RemoveListener(Repaint);\n            if (m_PreviewUtility != null)\n                m_PreviewUtility.Cleanup();\n\n            DestroyImmediate(m_BillboardPreviewMesh, true);\n            m_BillboardPreviewProperties = null;\n        }\n\n        // Find the given sceen space rectangular bounds from a list of vector 3 points.\n        private static Rect CalculateScreenRect(IEnumerable<Vector3> points)\n        {\n            var points2 = points.Select(p => HandleUtility.WorldToGUIPoint(p)).ToList();\n\n            var min = new Vector2(float.MaxValue, float.MaxValue);\n            var max = new Vector2(float.MinValue, float.MinValue);\n\n            foreach (var point in points2)\n            {\n                min.x = (point.x < min.x) ? point.x : min.x;\n                max.x = (point.x > max.x) ? point.x : max.x;\n\n                min.y = (point.y < min.y) ? point.y : min.y;\n                max.y = (point.y > max.y) ? point.y : max.y;\n            }\n\n            return new Rect(min.x, min.y, max.x - min.x, max.y - min.y);\n        }\n\n        public static bool IsSceneGUIEnabled()\n        {\n            if (Event.current.type != EventType.Repaint\n                || Camera.current == null\n                || SceneView.lastActiveSceneView != SceneView.currentDrawingSceneView)\n            {\n                return false;\n            }\n\n            return true;\n        }\n\n        public void OnSceneGUI()\n        {\n            if (!target)\n                return;\n\n            if (m_SelectedLODGroupCount > 1)\n                return;\n\n            LODGroup lodGroup = (LODGroup)target;\n            Camera camera = SceneView.lastActiveSceneView.camera;\n            var worldReferencePoint = LODUtility.CalculateWorldReferencePoint(lodGroup);\n\n            if (Vector3.Dot(camera.transform.forward,\n                (camera.transform.position - worldReferencePoint).normalized) > 0)\n                return;\n\n            var info = LODUtility.CalculateVisualizationData(camera, lodGroup, -1);\n            float size = info.worldSpaceSize;\n\n            // Draw cap around LOD to visualize it's size\n            Handles.color = info.activeLODLevel != -1 ? LODGroupGUI.kLODColors[info.activeLODLevel] : LODGroupGUI.kCulledLODColor;\n\n            Handles.SelectionFrame(0, worldReferencePoint, camera.transform.rotation, size / 2);\n\n            // Calculate a screen rect for the on scene title\n            Vector3 sideways = camera.transform.right * size / 2.0f;\n            Vector3 up = camera.transform.up * size / 2.0f;\n            var rect = CalculateScreenRect(\n                new[]\n                {\n                    worldReferencePoint - sideways + up,\n                    worldReferencePoint - sideways - up,\n                    worldReferencePoint + sideways + up,\n                    worldReferencePoint + sideways - up\n                });\n\n            // Place the screen space lable directaly under the\n            var midPoint = rect.x + rect.width / 2.0f;\n            rect = new Rect(midPoint - LODGroupGUI.kSceneLabelHalfWidth, rect.yMax, LODGroupGUI.kSceneLabelHalfWidth * 2, LODGroupGUI.kSceneLabelHeight);\n\n            if (rect.yMax > Screen.height - LODGroupGUI.kSceneLabelHeight)\n                rect.y = Screen.height - LODGroupGUI.kSceneLabelHeight - LODGroupGUI.kSceneHeaderOffset;\n\n            Handles.BeginGUI();\n            GUI.Label(rect, GUIContent.none, EditorStyles.notificationBackground);\n            EditorGUI.DoDropShadowLabel(rect, GUIContent.Temp(info.activeLODLevel >= 0 ? \"LOD \" + info.activeLODLevel : \"Culled\"), LODGroupGUI.Styles.m_LODLevelNotifyText, 0.3f);\n            Handles.EndGUI();\n        }\n\n        private Vector3 m_LastCameraPos = Vector3.zero;\n        public void Update()\n        {\n            if (SceneView.lastActiveSceneView == null || SceneView.lastActiveSceneView.camera == null)\n            {\n                return;\n            }\n\n            // Update the last camera positon and repaint if the camera has moved\n            if (SceneView.lastActiveSceneView.camera.transform.position != m_LastCameraPos)\n            {\n                m_LastCameraPos = SceneView.lastActiveSceneView.camera.transform.position;\n                Repaint();\n            }\n        }\n\n        private const string kLODDataPath = \"m_LODs.Array.data[{0}]\";\n        private const string kPixelHeightDataPath = \"m_LODs.Array.data[{0}].screenRelativeHeight\";\n        private const string kRenderRootPath = \"m_LODs.Array.data[{0}].renderers\";\n        private const string kFadeTransitionWidthDataPath = \"m_LODs.Array.data[{0}].fadeTransitionWidth\";\n\n        private int activeLOD\n        {\n            get {return m_SelectedLOD; }\n        }\n\n        private ModelImporter GetImporter()\n        {\n            return AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(PrefabUtility.GetCorrespondingObjectFromSource(target))) as ModelImporter;\n        }\n\n        private bool IsLODUsingCrossFadeWidth(int lod)\n        {\n            if (m_FadeMode.intValue == (int)LODFadeMode.None || m_AnimateCrossFading.boolValue)\n                return false;\n            if (m_FadeMode.intValue == (int)LODFadeMode.CrossFade)\n                return true;\n            // SpeedTree: only last mesh LOD and billboard LOD do crossfade\n            if (m_NumberOfLODs > 0 && m_SelectedLOD == m_NumberOfLODs - 1)\n                return true;\n            if (m_NumberOfLODs > 1 && m_SelectedLOD == m_NumberOfLODs - 2)\n            {\n                // the second last LOD uses cross-fade if the last LOD is a billboard\n                var renderers = serializedObject.FindProperty(String.Format(kRenderRootPath, m_NumberOfLODs - 1));\n                if (renderers.arraySize != 1)\n                    return false;\n                var renderer = renderers.GetArrayElementAtIndex(0).FindPropertyRelative(\"renderer\").objectReferenceValue;\n                if (renderer is BillboardRenderer || (renderer is MeshRenderer && m_LastLODIsBillboard.boolValue))\n                    return true;\n            }\n            return false;\n        }\n\n        int GetMaxLODCountForMultiSelection()\n        {\n            var maxLODIndex = m_LODs.arraySize;\n\n            foreach (UnityEngine.Object targetObject in serializedObject.targetObjects)\n            {\n                SerializedObject targetObjectSerialized = new SerializedObject(targetObject);\n                SerializedProperty property = targetObjectSerialized.FindProperty(m_LODs.propertyPath);\n\n                maxLODIndex = Mathf.Min(property.arraySize, maxLODIndex);\n            }\n            return maxLODIndex;\n        }\n\n        void DrawLODGroupFoldouts()\n        {\n            EditorGUILayout.BeginHorizontal();\n            EditorGUILayout.PropertyField(m_LODSize, LODGroupGUI.Styles.m_LODObjectSizeLabel);\n\n            if (GUILayout.Button(LODGroupGUI.Styles.m_ResetObjectSizeLabel))\n            {\n                float originalSize = m_LODSize.floatValue;\n                m_LODSize.floatValue = 1f;\n                for (int i = 0; i < m_LODs.arraySize; i++)\n                {\n                    var heightPercentageProperty = serializedObject.FindProperty(string.Format(kPixelHeightDataPath, i));\n                    heightPercentageProperty.floatValue = heightPercentageProperty.floatValue / originalSize;\n                }\n            }\n            EditorGUILayout.EndHorizontal();\n\n            Camera camera = null;\n            if (SceneView.lastActiveSceneView && SceneView.lastActiveSceneView.camera)\n                camera = SceneView.lastActiveSceneView.camera;\n\n            if (camera == null)\n                return;\n\n            for (int i = 0; i < m_MaxLODCountForMultiselection; i++)\n            {\n                if (targets.Length == 1)\n                    DrawLODGroupFoldout(camera, i, ref m_LODGroupFoldoutHeaderValues[i]);\n                else\n                    DrawLODTransitionPropertyField(camera, i, m_MaxLODCountForMultiselection);\n            }\n        }\n\n        void DrawLODGroupFoldout(Camera camera, int lodGroupIndex, ref SavedBool foldoutState)\n        {\n            var totalTriCount = m_PrimitiveCounts.Length > 0 ? m_PrimitiveCounts[lodGroupIndex].Sum() : 0;\n            var lod0TriCount = m_PrimitiveCounts[0].Sum();\n            var triCountChange = lod0TriCount != 0 ? (float)totalTriCount / lod0TriCount * 100 : 0;\n            var triangleChangeLabel = lodGroupIndex > 0 && lod0TriCount != 0 ? $\"({triCountChange.ToString(\"f2\")}% LOD0)\" : \"\";\n\n            var wideInspector = Screen.width >= 350;\n            triangleChangeLabel = wideInspector ? triangleChangeLabel : \"\";\n            var submeshCountLabel = wideInspector ? $\"- {m_SubmeshCounts[lodGroupIndex]} Sub Mesh(es)\" : \"\";\n\n            if (activeLOD == lodGroupIndex)\n                LODGroupGUI.DrawRoundedBoxAroundLODDFoldout(lodGroupIndex, activeLOD);\n            else\n                EditorGUILayout.BeginVertical(EditorStyles.helpBox);\n\n            foldoutState.value = LODGroupGUI.FoldoutHeaderGroupInternal(GUILayoutUtility.GetRect(GUIContent.none, LODGroupGUI.GUIStyles.m_InspectorTitlebarFlat), foldoutState.value, $\"LOD {lodGroupIndex}\", m_Textures[lodGroupIndex],\n                LODGroupGUI.kLODColors[lodGroupIndex] * 0.6f, $\"{totalTriCount} {m_PrimitiveCountLabel.text} {triangleChangeLabel} {submeshCountLabel}\");\n\n            if (foldoutState.value)\n            {\n                DrawLODTransitionPropertyField(camera, lodGroupIndex, m_LODs.arraySize);\n\n                EditorGUILayout.BeginHorizontal();\n\n                m_ShowFadeTransitionWidth.target = IsLODUsingCrossFadeWidth(lodGroupIndex);\n                if (EditorGUILayout.BeginFadeGroup(m_ShowFadeTransitionWidth.faded))\n                {\n                    EditorGUILayout.Slider(serializedObject.FindProperty(string.Format(kFadeTransitionWidthDataPath, lodGroupIndex)), 0, 1);\n                }\n                EditorGUILayout.EndFadeGroup();\n                EditorGUILayout.EndHorizontal();\n\n                m_ReorderableListIndex = lodGroupIndex;\n\n                EditorGUI.BeginChangeCheck();\n\n                m_RendererMeshLists[lodGroupIndex].DoLayoutList();\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    serializedObject.ApplyModifiedProperties();\n                    ResetValuesAfterLODObjectIsModified();\n                }\n            }\n\n            if (activeLOD == lodGroupIndex)\n                GUILayoutUtility.EndLayoutGroup();\n            else\n                EditorGUILayout.EndVertical();\n        }\n\n        void DrawLODTransitionPropertyField(Camera camera, int lodGroupIndex, int maxLOD)\n        {\n            EditorGUILayout.BeginHorizontal();\n\n            var heightPercentageProperty = serializedObject.FindProperty(string.Format(kPixelHeightDataPath, lodGroupIndex));\n\n            EditorGUI.showMixedValue = heightPercentageProperty.hasMultipleDifferentValues;\n\n            EditorGUI.BeginChangeCheck();\n            float newVal = 0;\n            if (targets.Length == 1)\n                newVal = EditorGUILayout.FloatField(LODGroupGUI.Styles.m_LODTransitionPercentageLabel, heightPercentageProperty.floatValue * 100);\n            else\n            {\n                GUIContent label = new GUIContent($\"LOD {lodGroupIndex} Transition\", LODGroupGUI.Styles.m_LODTransitionPercentageLabel.tooltip);\n                newVal = EditorGUILayout.FloatField(label, heightPercentageProperty.floatValue * 100);\n            }\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                float minVal = 0, maxVal = 100f;\n                if (lodGroupIndex < maxLOD - 1)\n                {\n                    var nextTransitionProperty = serializedObject.FindProperty(string.Format(kPixelHeightDataPath, lodGroupIndex + 1));\n                    minVal = nextTransitionProperty.floatValue * 100;\n                }\n                if (lodGroupIndex > 0)\n                {\n                    var previousTransitionProperty = serializedObject.FindProperty(string.Format(kPixelHeightDataPath, lodGroupIndex - 1));\n                    maxVal = previousTransitionProperty.floatValue * 100;\n                }\n\n                float addToMinVal = lodGroupIndex == maxLOD - 1 && targets.Length == 1 ? 0f : 0.1f;\n\n                if (newVal > maxVal)\n                    newVal = maxVal - 0.1f;\n                else if (newVal < minVal)\n                    newVal = minVal + addToMinVal;\n\n                heightPercentageProperty.floatValue = newVal / 100;\n            }\n\n            EditorGUI.showMixedValue = false;\n\n            EditorGUI.BeginDisabledGroup(!IsObjectVisibleToCamera(camera));\n            if (GUILayout.Button(LODGroupGUI.Styles.m_LODSetToCameraLabel, GUILayout.Width(95)))\n            {\n                heightPercentageProperty.floatValue = m_LODGroup.GetRelativeHeight(camera);\n            }\n            EditorGUI.EndDisabledGroup();\n\n            if (Screen.width > 380)\n            {\n                var distanceLabel = Selection.count == 1 && newVal > 0 && camera != null ? LODGroupExtensions.RelativeHeightToDistance(camera, heightPercentageProperty.floatValue, m_LODSize.floatValue).ToString(\"F2\") + \" m\" : \"-\";\n                LODGroupGUI.GUIStyles.m_DistanceInMetersLabel.text = distanceLabel;\n                GUILayout.Label(LODGroupGUI.GUIStyles.m_DistanceInMetersLabel, GUILayout.Width(60));\n            }\n            EditorGUILayout.EndHorizontal();\n        }\n\n        bool IsObjectVisibleToCamera(Camera camera)\n        {\n            if (camera == null)\n                return false;\n\n            if (targets.Length == 1 && m_TargetTransform != null)\n            {\n                Vector3 pointOnScreen = camera.WorldToViewportPoint(m_TargetTransform.position);\n                bool isVisible = pointOnScreen.z > 0 && pointOnScreen.x > 0 && pointOnScreen.x < 1 && pointOnScreen.y > 0 && pointOnScreen.y < 1;\n                return isVisible;\n            }\n            return false;\n        }\n\n        public static Mesh GetMeshFromRendererIfAvailable(Renderer renderer)\n        {\n            if (renderer == null)\n                return null;\n\n            Mesh rendererMesh = null;\n            MeshFilter meshFilter = renderer.GetComponent<MeshFilter>();\n            if (meshFilter != null)\n                rendererMesh = meshFilter.sharedMesh;\n            else\n            {\n                var skinnedRenderer = renderer as SkinnedMeshRenderer;\n                if (skinnedRenderer != null)\n                    rendererMesh = skinnedRenderer.sharedMesh;\n            }\n\n            return rendererMesh;\n        }\n\n        void CalculatePrimitiveCountForRenderers()\n        {\n            var lods = m_LODGroup.GetLODs();\n\n            m_PrimitiveCountLabel = LODGroupGUI.GUIStyles.m_TriangleCountLabel;\n            m_PrimitiveCounts = new int[lods.Length][];\n            m_SubmeshCounts = new int[lods.Length];\n\n            for (int i = 0; i < lods.Length; i++)\n            {\n                var renderers = lods[i].renderers;\n                m_PrimitiveCounts[i] = new int[renderers.Length];\n\n                for (int j = 0; j < renderers.Length; j++)\n                {\n                    var hasMismatchingSubMeshTopologyTypes = CheckIfMeshesHaveMatchingTopologyTypes(renderers);\n\n                    var rendererMesh = GetMeshFromRendererIfAvailable(renderers[j]);\n                    if (rendererMesh == null)\n                        continue;\n\n                    m_SubmeshCounts[i] += rendererMesh.subMeshCount;\n\n                    if (hasMismatchingSubMeshTopologyTypes)\n                    {\n                        m_PrimitiveCounts[i][j] = rendererMesh.vertexCount;\n                        m_PrimitiveCountLabel = LODGroupGUI.GUIStyles.m_VertexCountLabel;\n                    }\n                    else\n                    {\n                        for (int subMeshIndex = 0; subMeshIndex < rendererMesh.subMeshCount; subMeshIndex++)\n                        {\n                            m_PrimitiveCounts[i][j] += (int)rendererMesh.GetIndexCount(subMeshIndex) / 3;\n                        }\n                    }\n                }\n            }\n        }\n\n        void ResetMembersForEachOpenInspector()\n        {\n            serializedObject.Update();\n            m_LODs = serializedObject.FindProperty(\"m_LODs\");\n            m_MaxLODCountForMultiselection = GetMaxLODCountForMultiSelection();\n\n            CalculatePrimitiveCountForRenderers();\n            ResetFoldoutLists();\n        }\n\n        void ResetValuesAfterLODObjectIsModified()\n        {\n            // A safeguard for when several inspectors of the same type are open for the same object\n            UnityEngine.Object[] openLODInspectors = Resources.FindObjectsOfTypeAll(typeof(LODGroupEditor));\n            Array.ForEach(openLODInspectors, el => (el as LODGroupEditor).ResetMembersForEachOpenInspector());\n        }\n\n        void ExpandSelectedHeaderAndCloseRemaining(int index)\n        {\n            // need this to safeguard against drag & drop on Culled section\n            // as that sets the LOD index to 8 which is outside of the total\n            // allowed LOD range\n            if (index >= m_LODs.arraySize)\n                return;\n\n            Array.ForEach(m_LODGroupFoldoutHeaderValues, el => el.value = false);\n            m_LODGroupFoldoutHeaderValues[index].value = true;\n        }\n\n        void ResetFoldoutLists()\n        {\n            m_RendererMeshLists = new ReorderableList[m_LODs.arraySize];\n            m_LODGroupFoldoutHeaderValues = new SavedBool[m_LODs.arraySize];\n\n            for (int i = 0; i < m_RendererMeshLists.Length; i++)\n            {\n                m_LODGroupFoldoutHeaderValues[i] = new SavedBool($\"{target.GetType()}.lodFoldout{i}\", false);\n\n                var renderersProperty = serializedObject.FindProperty(string.Format(kRenderRootPath, i));\n                m_RendererMeshLists[i] = new ReorderableList(serializedObject, renderersProperty);\n                m_RendererMeshLists[i].drawElementCallback = DrawLODRendererMeshListItems;\n                m_RendererMeshLists[i].drawHeaderCallback = DrawLODRendererMeshListHeader;\n                m_RendererMeshLists[i].onRemoveCallback = RemoveLODRendererMeshFromList;\n                m_RendererMeshLists[i].onAddCallback = AddLODRendererMeshToList;\n                m_RendererMeshLists[i].draggable = false;\n            }\n\n            InitAndSetFoldoutLabelTextures();\n        }\n\n        public static bool CheckIfSubmeshesHaveMatchingTopologyTypes(Mesh mesh)\n        {\n            var meshTopology = mesh.GetTopology(0);\n\n            for (int i = 0; i < mesh.subMeshCount; i++)\n            {\n                var newTopology = mesh.GetTopology(i);\n                if (meshTopology != newTopology)\n                    return true;\n            }\n\n            return false;\n        }\n\n        public static bool CheckIfMeshesHaveMatchingTopologyTypes(Renderer[] renderers)\n        {\n            for (int i = 0; i < renderers.Length; i++)\n            {\n                Mesh mesh = GetMeshFromRendererIfAvailable(renderers[i]);\n\n                if (mesh == null)\n                    return false;\n\n                if (CheckIfSubmeshesHaveMatchingTopologyTypes(mesh))\n                    return true;\n            }\n\n            return false;\n        }\n\n        private string MeshLodHelpboxText(bool[] isEnabled)\n        {\n            StringBuilder resultBuilder = new StringBuilder();\n            bool first = true; // Track if we're appending the first item\n\n            for (int i = 0; i < isEnabled.Length; i++)\n            {\n                if (isEnabled[i])\n                {\n                    if (!first)\n                    {\n                        resultBuilder.Append(\", \");\n                    }\n                    else\n                    {\n                        first = false;\n                    }\n                    resultBuilder.Append($\"LOD {i}\");\n                }\n            }\n\n            resultBuilder.Append('.');\n            return LODGroupGUI.GUIStyles.m_MeshLodInfo.text + resultBuilder.ToString();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            var initiallyEnabled = GUI.enabled;\n\n            // Grab the latest data from the object\n            serializedObject.Update();\n\n            if (m_HasMeshLod)\n            {\n                EditorGUILayout.HelpBox(MeshLodHelpboxText(m_EnabledMeshLods), MessageType.Info);\n            }\n\n            // Flush this editor's state when it's out of sync with serialized data.\n            if (m_LODs.arraySize != m_LODGroupFoldoutHeaderValues.Length || m_LODs.arraySize != m_RendererMeshLists.Length)\n            {\n                m_MaxLODCountForMultiselection = GetMaxLODCountForMultiSelection();\n                CalculatePrimitiveCountForRenderers();\n                ResetFoldoutLists();\n            }\n\n            EditorGUILayout.PropertyField(m_FadeMode);\n\n            m_ShowAnimateCrossFading.target = m_FadeMode.intValue != (int)LODFadeMode.None;\n            if (EditorGUILayout.BeginFadeGroup(m_ShowAnimateCrossFading.faded))\n                EditorGUILayout.PropertyField(m_AnimateCrossFading);\n            EditorGUILayout.EndFadeGroup();\n\n            m_NumberOfLODs = m_LODs.arraySize;\n\n            // This could happen when you select a newly inserted LOD level and then undo the insertion.\n            // It's valid for m_SelectedLOD to become -1, which means nothing is selected.\n            if (m_SelectedLOD >= m_NumberOfLODs)\n            {\n                m_SelectedLOD = m_NumberOfLODs - 1;\n            }\n\n            if (targets.Length > 1)\n            {\n                DrawLODGroupFoldouts();\n                serializedObject.ApplyModifiedProperties();\n                return;\n            }\n\n            // Add some space at the top..\n            GUILayout.Space(LODGroupGUI.kSliderBarTopMargin);\n\n            // Precalculate and cache the slider bar position for this update\n            var sliderBarPosition = GUILayoutUtility.GetRect(0, LODGroupGUI.kSliderBarHeight, GUILayout.ExpandWidth(true));\n\n            // Precalculate the lod info (button locations / ranges ect)\n            var lods = LODGroupGUI.CreateLODInfos(m_NumberOfLODs, sliderBarPosition,\n                i => String.Format(\"LOD {0}\", i),\n                i => serializedObject.FindProperty(string.Format(kPixelHeightDataPath, i)).floatValue);\n\n            DrawLODLevelSlider(sliderBarPosition, lods);\n            GUILayout.Space(LODGroupGUI.kSliderBarBottomMargin);\n\n            if (QualitySettings.lodBias != 1.0f)\n                EditorGUILayout.HelpBox(string.Format(\"Active LOD bias is {0:0.0#}. Distances are adjusted accordingly.\", QualitySettings.lodBias), MessageType.Warning);\n\n            // Draw the info for the selected LOD\n            if (m_NumberOfLODs > 0 && activeLOD >= 0 && activeLOD < m_NumberOfLODs && !m_IsPreset)\n            {\n                DrawRenderersInfo(EditorGUIUtility.contextWidth);\n            }\n\n            GUILayout.Space(8);\n\n            GUILayout.BeginHorizontal();\n            GUILayout.FlexibleSpace();\n\n            bool needUpdateBounds = LODUtility.NeedUpdateLODGroupBoundingBox(m_LODGroup);\n            using (new EditorGUI.DisabledScope(!needUpdateBounds))\n            {\n                if (GUILayout.Button(needUpdateBounds ? LODGroupGUI.Styles.m_RecalculateBounds : LODGroupGUI.Styles.m_RecalculateBoundsDisabled, GUILayout.ExpandWidth(false)))\n                {\n                    Undo.RecordObject(m_LODGroup, \"Recalculate LODGroup Bounds\");\n                    m_LODGroup.RecalculateBounds();\n                }\n            }\n\n            if (GUILayout.Button(LODGroupGUI.Styles.m_LightmapScale, GUILayout.ExpandWidth(false)))\n                SendPercentagesToLightmapScale();\n\n            GUILayout.EndHorizontal();\n\n            GUILayout.Space(5);\n\n            DrawLODGroupFoldouts();\n\n            var importer = PrefabUtility.IsPartOfModelPrefab(target) ? GetImporter() : null;\n            if (importer != null)\n            {\n                using (var importerRef = new SerializedObject(importer))\n                {\n                    var importerLODLevels = importerRef.FindProperty(\"m_LODScreenPercentages\");\n                    var lodNumberOnImporterMatches = importerLODLevels.isArray && importerLODLevels.arraySize == lods.Count;\n\n                    var guiState = GUI.enabled;\n                    if (!lodNumberOnImporterMatches)\n                        GUI.enabled = false;\n\n                    if (GUILayout.Button(lodNumberOnImporterMatches ? LODGroupGUI.Styles.m_UploadToImporter : LODGroupGUI.Styles.m_UploadToImporterDisabled))\n                    {\n                        // Number of imported LOD's is the same as in the imported model\n                        for (var i = 0; i < importerLODLevels.arraySize; i++)\n                            importerLODLevels.GetArrayElementAtIndex(i).floatValue = lods[i].RawScreenPercent;\n\n                        importerRef.ApplyModifiedProperties();\n\n                        AssetDatabase.ImportAsset(importer.assetPath);\n                    }\n                    GUI.enabled = guiState;\n                }\n            }\n\n            if (targets.Length == 1)\n                SpeedTreeMaterialFixer.DoFixerUI((target as LODGroup).gameObject);\n\n            // Apply the property, handle undo\n            serializedObject.ApplyModifiedProperties();\n\n            GUI.enabled = initiallyEnabled;\n        }\n\n        // Draw the renderers for the current LOD group\n        // Arrange in a grid\n        private void DrawRenderersInfo(float availableWidth)\n        {\n            var horizontalCount = Mathf.Max(Mathf.FloorToInt(availableWidth / LODGroupGUI.kRenderersButtonHeight), 1);\n            var titleArea = GUILayoutUtility.GetRect(LODGroupGUI.Styles.m_RendersTitle, LODGroupGUI.Styles.m_LODSliderTextSelected);\n            if (Event.current.type == EventType.Repaint)\n                EditorStyles.label.Draw(titleArea, LODGroupGUI.Styles.m_RendersTitle, false, false, false, false);\n\n            // Draw renderer info\n            var renderersProperty = serializedObject.FindProperty(string.Format(kRenderRootPath, activeLOD));\n\n            var numberOfButtons = renderersProperty.arraySize + 1;\n            var numberOfRows = Mathf.CeilToInt(numberOfButtons / (float)horizontalCount);\n\n            var drawArea = GUILayoutUtility.GetRect(0, numberOfRows * LODGroupGUI.kRenderersButtonHeight, GUILayout.ExpandWidth(true));\n            var rendererArea = drawArea;\n            GUI.Box(drawArea, GUIContent.none);\n            rendererArea.width -= 2 * LODGroupGUI.kRenderAreaForegroundPadding;\n            rendererArea.x += LODGroupGUI.kRenderAreaForegroundPadding;\n\n            var buttonWidth = rendererArea.width / horizontalCount;\n\n            var buttons = new List<Rect>();\n\n            for (int i = 0; i < numberOfRows; i++)\n            {\n                for (int k = 0; k < horizontalCount && (i * horizontalCount + k) < renderersProperty.arraySize; k++)\n                {\n                    var drawPos = new Rect(\n                        LODGroupGUI.kButtonPadding + rendererArea.x + k * buttonWidth,\n                        LODGroupGUI.kButtonPadding + rendererArea.y + i * LODGroupGUI.kRenderersButtonHeight,\n                        buttonWidth - LODGroupGUI.kButtonPadding * 2,\n                        LODGroupGUI.kRenderersButtonHeight - LODGroupGUI.kButtonPadding * 2);\n                    buttons.Add(drawPos);\n                    DrawRendererButton(drawPos, i * horizontalCount + k);\n                }\n            }\n\n            if (m_IsPrefab)\n                return;\n\n            //+ button\n            int horizontalPos = (numberOfButtons - 1) % horizontalCount;\n            int verticalPos = numberOfRows - 1;\n            HandleAddRenderer(new Rect(\n                LODGroupGUI.kButtonPadding + rendererArea.x + horizontalPos * buttonWidth,\n                LODGroupGUI.kButtonPadding + rendererArea.y + verticalPos * LODGroupGUI.kRenderersButtonHeight,\n                buttonWidth - LODGroupGUI.kButtonPadding * 2,\n                LODGroupGUI.kRenderersButtonHeight - LODGroupGUI.kButtonPadding * 2), buttons, drawArea);\n        }\n\n        private void HandleAddRenderer(Rect position, IEnumerable<Rect> alreadyDrawn, Rect drawArea)\n        {\n            Event evt = Event.current;\n            switch (evt.type)\n            {\n                case EventType.Repaint:\n                {\n                    bool isHovered = position.Contains(evt.mousePosition);\n                    LODGroupGUI.Styles.m_LODStandardButton.Draw(position, GUIContent.none, isHovered, false, false, false);\n                    LODGroupGUI.Styles.m_LODRendererAddButton.Draw(new Rect(position.x - LODGroupGUI.kButtonPadding, position.y, position.width, position.height), \"Add\", false, false, false, false);\n                    break;\n                }\n                case EventType.DragUpdated:\n                case EventType.DragPerform:\n                {\n                    bool dragArea = false;\n                    if (drawArea.Contains(evt.mousePosition))\n                    {\n                        if (alreadyDrawn.All(x => !x.Contains(evt.mousePosition)))\n                            dragArea = true;\n                    }\n\n                    if (!dragArea)\n                        break;\n\n                    // If we are over a valid range, make sure we have a game object...\n                    if (DragAndDrop.objectReferences.Length > 0)\n                    {\n                        DragAndDrop.visualMode = m_IsPrefab ? DragAndDropVisualMode.None : DragAndDropVisualMode.Copy;\n\n                        if (evt.type == EventType.DragPerform)\n                        {\n                            // First try gameobjects...\n                            var selectedGameObjects =\n                                from go in DragAndDrop.objectReferences\n                                where go as GameObject != null\n                                select go as GameObject;\n\n                            var renderers = GetRenderers(selectedGameObjects, true);\n                            AddGameObjectRenderers(renderers, true);\n                            ResetValuesAfterLODObjectIsModified();\n                            DragAndDrop.AcceptDrag();\n\n                            evt.Use();\n                            break;\n                        }\n                    }\n                    evt.Use();\n                    break;\n                }\n                case EventType.MouseDown:\n                {\n                    if (position.Contains(evt.mousePosition))\n                    {\n                        evt.Use();\n                        int id = \"LODGroupSelector\".GetHashCode();\n                        ObjectSelector.get.Show(null, typeof(Renderer), null, true);\n                        ObjectSelector.get.objectSelectorID = id;\n                        GUIUtility.ExitGUI();\n                    }\n                    break;\n                }\n                case EventType.ExecuteCommand:\n                {\n                    string commandName = evt.commandName;\n                    if (commandName == ObjectSelector.ObjectSelectorClosedCommand && ObjectSelector.get.objectSelectorID == \"LODGroupSelector\".GetHashCode())\n                    {\n                        var selectedObject = ObjectSelector.GetCurrentObject() as GameObject;\n                        if (selectedObject != null)\n                        {\n                            AddGameObjectRenderers(GetRenderers(new List<GameObject> { selectedObject }, true), true);\n                            CalculatePrimitiveCountForRenderers();\n                        }\n                        evt.Use();\n                        GUIUtility.ExitGUI();\n                    }\n                    break;\n                }\n            }\n        }\n\n        private void DrawRendererButton(Rect position, int rendererIndex)\n        {\n            var renderersProperty = serializedObject.FindProperty(string.Format(kRenderRootPath, activeLOD));\n            var rendererRef = renderersProperty.GetArrayElementAtIndex(rendererIndex).FindPropertyRelative(\"renderer\");\n            var renderer = rendererRef.objectReferenceValue as Renderer;\n\n            var deleteButton = new Rect(position.xMax - LODGroupGUI.kDeleteButtonSize, position.yMax - LODGroupGUI.kDeleteButtonSize, LODGroupGUI.kDeleteButtonSize, LODGroupGUI.kDeleteButtonSize);\n\n            Event evt = Event.current;\n            switch (evt.type)\n            {\n                case EventType.Repaint:\n                {\n                    if (renderer != null)\n                    {\n                        GUIContent content;\n\n                        var filter = renderer.GetComponent<MeshFilter>();\n                        if (filter != null && filter.sharedMesh != null)\n                            content = new GUIContent(AssetPreview.GetAssetPreview(filter.sharedMesh), renderer.gameObject.name);\n                        else if (renderer is SkinnedMeshRenderer)\n                            content = new GUIContent(AssetPreview.GetAssetPreview((renderer as SkinnedMeshRenderer).sharedMesh), renderer.gameObject.name);\n                        else if (renderer is BillboardRenderer)\n                            content = new GUIContent(AssetPreview.GetAssetPreview((renderer as BillboardRenderer).billboard), renderer.gameObject.name);\n                        else\n                            content = new GUIContent(ObjectNames.NicifyVariableName(renderer.GetType().Name), renderer.gameObject.name);\n\n                        LODGroupGUI.Styles.m_LODBlackBox.Draw(position, GUIContent.none, false, false, false, false);\n\n                        LODGroupGUI.Styles.m_LODRendererButton.Draw(\n                            new Rect(\n                                position.x + LODGroupGUI.kButtonPadding,\n                                position.y + LODGroupGUI.kButtonPadding,\n                                position.width - 2 * LODGroupGUI.kButtonPadding, position.height - 2 * LODGroupGUI.kButtonPadding),\n                            content, false, false, false, false);\n                    }\n                    else\n                    {\n                        LODGroupGUI.Styles.m_LODBlackBox.Draw(position, GUIContent.none, false, false, false, false);\n                        LODGroupGUI.Styles.m_LODRendererAddButton.Draw(position, \"Empty\", false, false, false, false);\n                    }\n\n                    if (!m_IsPrefab)\n                    {\n                        LODGroupGUI.Styles.m_LODBlackBox.Draw(deleteButton, GUIContent.none, false, false, false, false);\n                        LODGroupGUI.Styles.m_LODRendererRemove.Draw(deleteButton, LODGroupGUI.Styles.m_IconRendererMinus, false, false, false, false);\n                    }\n                    break;\n                }\n                case EventType.MouseDown:\n                {\n                    if (!m_IsPrefab && deleteButton.Contains(evt.mousePosition))\n                    {\n                        renderersProperty.DeleteArrayElementAtIndex(rendererIndex);\n                        evt.Use();\n                        serializedObject.ApplyModifiedProperties();\n                        CalculatePrimitiveCountForRenderers();\n                        m_LODGroup.RecalculateBounds();\n                    }\n                    else if (position.Contains(evt.mousePosition))\n                    {\n                        EditorGUIUtility.PingObject(renderer);\n                        evt.Use();\n                    }\n                    break;\n                }\n            }\n        }\n\n        // Get all the renderers that are attached to this game object\n        private IEnumerable<Renderer> GetRenderers(IEnumerable<GameObject> selectedGameObjects, bool searchChildren)\n        {\n            // Only allow renderers that are parented to this LODGroup\n            if (EditorUtility.IsPersistent(m_LODGroup))\n                return new List<Renderer>();\n\n            var validSearchObjects = from go in selectedGameObjects\n                where go.transform.IsChildOf(m_LODGroup.transform)\n                select go;\n\n            var nonChildObjects = from go in selectedGameObjects\n                where !go.transform.IsChildOf(m_LODGroup.transform)\n                select go;\n\n            // Handle reparenting\n            var validChildren = new List<GameObject>();\n            if (nonChildObjects.Count() > 0)\n            {\n                const string kReparent = \"Some objects are not children of the LODGroup GameObject. Do you want to reparent them and add them to the LODGroup?\";\n                if (EditorUtility.DisplayDialog(\n                    \"Reparent GameObjects\",\n                    kReparent,\n                    \"Yes, Reparent\",\n                    \"No, Use Only Existing Children\"))\n                {\n                    foreach (var go in nonChildObjects)\n                    {\n                        if (EditorUtility.IsPersistent(go))\n                        {\n                            var newGo = Instantiate(go);\n                            if (newGo != null)\n                            {\n                                newGo.transform.parent = m_LODGroup.transform;\n                                newGo.transform.localPosition = Vector3.zero;\n                                newGo.transform.localRotation = Quaternion.identity;\n                                validChildren.Add(newGo);\n                            }\n                        }\n                        else\n                        {\n                            go.transform.parent = m_LODGroup.transform;\n                            validChildren.Add(go);\n                        }\n                    }\n                    validSearchObjects = validSearchObjects.Union(validChildren);\n                }\n            }\n\n            //Get all the renderers\n            var renderers = new List<Renderer>();\n            foreach (var go in validSearchObjects)\n            {\n                if (searchChildren)\n                    renderers.AddRange(go.GetComponentsInChildren<Renderer>());\n                else\n                    renderers.Add(go.GetComponent<Renderer>());\n            }\n\n            // Then try renderers\n            var selectedRenderers = from go in DragAndDrop.objectReferences\n                where go as Renderer != null\n                select go as Renderer;\n\n            renderers.AddRange(selectedRenderers);\n            return renderers;\n        }\n\n        // Add the given renderers to the current LOD group\n        private void AddGameObjectRenderers(IEnumerable<Renderer> toAdd, bool add)\n        {\n            var renderersProperty = serializedObject.FindProperty(string.Format(kRenderRootPath, activeLOD));\n\n            if (!add)\n                renderersProperty.ClearArray();\n\n            // On add make a list of the old renderers (to check for dupes)\n            var oldRenderers = new List<Renderer>();\n            for (var i = 0; i < renderersProperty.arraySize; i++)\n            {\n                var lodRenderRef = renderersProperty.GetArrayElementAtIndex(i).FindPropertyRelative(\"renderer\");\n                var renderer = lodRenderRef.objectReferenceValue as Renderer;\n\n                if (renderer == null)\n                    continue;\n\n                oldRenderers.Add(renderer);\n            }\n\n            foreach (var renderer in toAdd)\n            {\n                // Ensure that we don't add the renderer if it already exists\n                if (oldRenderers.Contains(renderer))\n                    continue;\n\n                renderersProperty.arraySize += 1;\n                renderersProperty.\n                    GetArrayElementAtIndex(renderersProperty.arraySize - 1).\n                    FindPropertyRelative(\"renderer\").objectReferenceValue = renderer;\n\n                // Stop readd\n                oldRenderers.Add(renderer);\n            }\n            serializedObject.ApplyModifiedProperties();\n            m_LODGroup.RecalculateBounds();\n            ResetValuesAfterLODObjectIsModified();\n            ExpandSelectedHeaderAndCloseRemaining(activeLOD);\n        }\n\n        // Callback action for mouse context clicks on the LOD slider(right click ect)\n        private class LODAction\n        {\n            private readonly float m_Percentage;\n            private readonly List<LODGroupGUI.LODInfo> m_LODs;\n            private readonly Vector2 m_ClickedPosition;\n            private readonly SerializedObject m_ObjectRef;\n            private readonly SerializedProperty m_LODsProperty;\n\n            public delegate void Callback();\n            private readonly Callback m_Callback;\n\n            public LODAction(List<LODGroupGUI.LODInfo> lods, float percentage, Vector2 clickedPosition, SerializedProperty propLODs, Callback callback)\n            {\n                m_LODs = lods;\n                m_Percentage = percentage;\n                m_ClickedPosition = clickedPosition;\n                m_LODsProperty = propLODs;\n                m_ObjectRef = propLODs.serializedObject;\n                m_Callback = callback;\n            }\n\n            public void InsertLOD()\n            {\n                if (!m_LODsProperty.isArray)\n                    return;\n\n                // Find where to insert\n                int insertIndex = -1;\n                foreach (var lod in m_LODs)\n                {\n                    if (m_Percentage > lod.RawScreenPercent)\n                    {\n                        insertIndex = lod.LODLevel;\n                        break;\n                    }\n                }\n\n                // Clicked in the culled area... duplicate last\n                if (insertIndex < 0)\n                {\n                    m_LODsProperty.InsertArrayElementAtIndex(m_LODs.Count);\n                    insertIndex = m_LODs.Count;\n                }\n                else\n                {\n                    m_LODsProperty.InsertArrayElementAtIndex(insertIndex);\n                }\n\n                // Null out the copied renderers (we want the list to be empty)\n                var renderers = m_ObjectRef.FindProperty(string.Format(kRenderRootPath, insertIndex));\n                renderers.arraySize = 0;\n\n                var newLOD = m_LODsProperty.GetArrayElementAtIndex(insertIndex);\n                newLOD.FindPropertyRelative(\"screenRelativeHeight\").floatValue = m_Percentage;\n\n                m_ObjectRef.ApplyModifiedProperties();\n                if (m_Callback != null)\n                    m_Callback();\n            }\n\n            public void DeleteLOD()\n            {\n                if (m_LODs.Count <= 0)\n                    return;\n\n                // Check for range click\n                foreach (var lod in m_LODs)\n                {\n                    var numberOfRenderers = m_ObjectRef.FindProperty(string.Format(kRenderRootPath, lod.LODLevel)).arraySize;\n                    if (lod.m_RangePosition.Contains(m_ClickedPosition) && (numberOfRenderers == 0\n                                                                            || EditorUtility.DisplayDialog(\"Delete LOD\",\n                                                                                \"Are you sure you wish to delete this LOD?\",\n                                                                                \"Yes\",\n                                                                                \"No\")))\n                    {\n                        var lodData = m_ObjectRef.FindProperty(string.Format(kLODDataPath, lod.LODLevel));\n                        lodData.DeleteCommand();\n\n                        m_ObjectRef.ApplyModifiedProperties();\n                        if (m_Callback != null)\n                            m_Callback();\n                        break;\n                    }\n                }\n            }\n        }\n\n        private void DeletedLOD()\n        {\n            m_SelectedLOD--;\n\n            ResetValuesAfterLODObjectIsModified();\n        }\n\n        // Set the camera distance so that the current LOD group covers the desired percentage of the screen\n        private static void UpdateCamera(float desiredPercentage, LODGroup group)\n        {\n            var worldReferencePoint = LODUtility.CalculateWorldReferencePoint(group);\n            var percentage = Mathf.Max(desiredPercentage / QualitySettings.lodBias, 0.000001f);\n\n            var sceneView = SceneView.lastActiveSceneView;\n            var sceneCamera = sceneView.camera;\n\n            // Figure out a distance based on the percentage\n            var distance = LODUtility.CalculateDistance(sceneCamera, percentage, group);\n\n            // We need to do inverse of SceneView.cameraDistance:\n            // given the distance, need to figure out \"size\" to focus the scene view on.\n            float size;\n            if (sceneCamera.orthographic)\n            {\n                size = distance;\n                if (sceneCamera.aspect < 1.0)\n                    size *= sceneCamera.aspect;\n            }\n            else\n            {\n                var fov = sceneCamera.fieldOfView;\n                size = distance * Mathf.Sin(fov * 0.5f * Mathf.Deg2Rad);\n            }\n\n            SceneView.lastActiveSceneView.LookAtDirect(worldReferencePoint, sceneCamera.transform.rotation, size);\n        }\n\n        private void UpdateSelectedLODFromCamera(IEnumerable<LODGroupGUI.LODInfo> lods, float cameraPercent)\n        {\n            foreach (var lod in lods)\n            {\n                if (cameraPercent > lod.RawScreenPercent)\n                {\n                    m_SelectedLOD = lod.LODLevel;\n                    break;\n                }\n            }\n        }\n\n        private readonly int m_LODSliderId = \"LODSliderIDHash\".GetHashCode();\n        private readonly int m_CameraSliderId = \"LODCameraIDHash\".GetHashCode();\n        private void DrawLODLevelSlider(Rect sliderPosition, List<LODGroupGUI.LODInfo> lods)\n        {\n            int sliderId = GUIUtility.GetControlID(m_LODSliderId, FocusType.Passive);\n            int camerId = GUIUtility.GetControlID(m_CameraSliderId, FocusType.Passive);\n            Event evt = Event.current;\n\n            switch (evt.GetTypeForControl(sliderId))\n            {\n                case EventType.Repaint:\n                {\n                    LODGroupGUI.DrawLODSlider(sliderPosition, lods, activeLOD, m_EnabledMeshLods);\n                    break;\n                }\n                case EventType.MouseDown:\n                {\n                    // Handle right click first\n                    if (evt.button == 1 && sliderPosition.Contains(evt.mousePosition))\n                    {\n                        var cameraPercent = LODGroupGUI.GetCameraPercent(evt.mousePosition, sliderPosition);\n                        var pm = new GenericMenu();\n                        if (lods.Count >= 8)\n                        {\n                            pm.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Insert Before\"));\n                        }\n                        else\n                        {\n                            pm.AddItem(EditorGUIUtility.TrTextContent(\"Insert Before\"), false,\n                                new LODAction(lods, cameraPercent, evt.mousePosition, m_LODs, ResetValuesAfterLODObjectIsModified).\n                                InsertLOD);\n                        }\n\n                        // Figure out if we clicked in the culled region\n                        var disabledRegion = true;\n                        if (lods.Count > 0 && lods[lods.Count - 1].RawScreenPercent < cameraPercent)\n                            disabledRegion = false;\n\n                        if (disabledRegion)\n                            pm.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Delete\"));\n                        else\n                            pm.AddItem(EditorGUIUtility.TrTextContent(\"Delete\"), false,\n                                new LODAction(lods, cameraPercent, evt.mousePosition, m_LODs, DeletedLOD).\n                                DeleteLOD);\n                        pm.ShowAsContext();\n\n                        // Do selection\n                        bool selected = false;\n                        foreach (var lod in lods)\n                        {\n                            if (lod.m_RangePosition.Contains(evt.mousePosition))\n                            {\n                                m_SelectedLOD = lod.LODLevel;\n                                selected = true;\n                                break;\n                            }\n                        }\n\n                        if (!selected)\n                            m_SelectedLOD = -1;\n\n                        evt.Use();\n\n                        break;\n                    }\n\n                    // Slightly grow position on the x because edge buttons overflow by 5 pixels\n                    var barPosition = sliderPosition;\n                    barPosition.x -= 5;\n                    barPosition.width += 10;\n\n                    if (barPosition.Contains(evt.mousePosition))\n                    {\n                        evt.Use();\n                        GUIUtility.hotControl = sliderId;\n\n                        // Check for button click\n                        var clickedButton = false;\n\n                        // case:464019 have to re-sort the LOD array for these buttons to get the overlaps in the right order...\n                        var lodsLeft = lods.Where(lod => lod.ScreenPercent > 0.5f).OrderByDescending(x => x.LODLevel);\n                        var lodsRight = lods.Where(lod => lod.ScreenPercent <= 0.5f).OrderBy(x => x.LODLevel);\n\n                        var lodButtonOrder = new List<LODGroupGUI.LODInfo>();\n                        lodButtonOrder.AddRange(lodsLeft);\n                        lodButtonOrder.AddRange(lodsRight);\n\n                        foreach (var lod in lodButtonOrder)\n                        {\n                            if (lod.m_ButtonPosition.Contains(evt.mousePosition))\n                            {\n                                m_SelectedLODSlider = lod.LODLevel;\n                                clickedButton = true;\n                                // Bias by 0.1% so that there is no skipping when sliding\n                                BeginLODDrag(lod.RawScreenPercent + 0.001f, m_LODGroup);\n                                break;\n                            }\n                        }\n\n                        if (!clickedButton)\n                        {\n                            // Check for range click\n                            foreach (var lod in lodButtonOrder)\n                            {\n                                if (lod.m_RangePosition.Contains(evt.mousePosition))\n                                {\n                                    m_SelectedLODSlider = -1;\n                                    m_SelectedLOD = lod.LODLevel;\n                                    ExpandSelectedHeaderAndCloseRemaining(m_SelectedLOD);\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                    break;\n                }\n\n                case EventType.MouseDrag:\n                {\n                    if (GUIUtility.hotControl == sliderId && m_SelectedLODSlider >= 0 && lods[m_SelectedLODSlider] != null)\n                    {\n                        evt.Use();\n\n                        var cameraPercent = LODGroupGUI.GetCameraPercent(evt.mousePosition, sliderPosition);\n                        // Bias by 0.1% so that there is no skipping when sliding\n                        LODGroupGUI.SetSelectedLODLevelPercentage(cameraPercent - 0.001f, m_SelectedLODSlider, lods);\n                        var percentageProperty = serializedObject.FindProperty(string.Format(kPixelHeightDataPath, lods[m_SelectedLODSlider].LODLevel));\n                        percentageProperty.floatValue = lods[m_SelectedLODSlider].RawScreenPercent;\n\n                        UpdateLODDrag(cameraPercent, m_LODGroup);\n                    }\n                    break;\n                }\n\n                case EventType.MouseUp:\n                {\n                    if (GUIUtility.hotControl == sliderId)\n                    {\n                        GUIUtility.hotControl = 0;\n                        m_SelectedLODSlider = -1;\n                        EndLODDrag();\n                        evt.Use();\n                    }\n                    break;\n                }\n\n                case EventType.DragUpdated:\n                case EventType.DragPerform:\n                {\n                    // -2 = invalid region\n                    // -1 = culledregion\n                    // rest = LOD level\n                    var lodLevel = -2;\n                    // Is the mouse over a valid LOD level range?\n                    foreach (var lod in lods)\n                    {\n                        if (lod.m_RangePosition.Contains(evt.mousePosition))\n                        {\n                            lodLevel = lod.LODLevel;\n                            break;\n                        }\n                    }\n\n                    if (lodLevel == -2)\n                    {\n                        var culledRange = LODGroupGUI.GetCulledBox(sliderPosition, lods.Count > 0 ? lods[lods.Count - 1].ScreenPercent : 1.0f);\n                        if (culledRange.Contains(evt.mousePosition))\n                        {\n                            lodLevel = -1;\n                        }\n                    }\n\n                    if (lodLevel >= -1)\n                    {\n                        // Actually set LOD level now\n                        m_SelectedLOD = lodLevel;\n\n                        if (DragAndDrop.objectReferences.Length > 0)\n                        {\n                            DragAndDrop.visualMode = m_IsPrefab ? DragAndDropVisualMode.None : DragAndDropVisualMode.Copy;\n\n                            if (evt.type == EventType.DragPerform)\n                            {\n                                // First try gameobjects...\n                                var selectedGameObjects = from go in DragAndDrop.objectReferences\n                                    where go as GameObject != null\n                                    select go as GameObject;\n                                var renderers = GetRenderers(selectedGameObjects, true);\n\n                                if (lodLevel == -1)\n                                {\n                                    m_LODs.arraySize++;\n                                    var pixelHeightNew = serializedObject.FindProperty(string.Format(kPixelHeightDataPath, lods.Count));\n\n                                    if (lods.Count == 0)\n                                        pixelHeightNew.floatValue = 0.5f;\n                                    else\n                                    {\n                                        var pixelHeightPrevious = serializedObject.FindProperty(string.Format(kPixelHeightDataPath, lods.Count - 1));\n                                        pixelHeightNew.floatValue = pixelHeightPrevious.floatValue / 2.0f;\n                                    }\n\n                                    m_SelectedLOD = lods.Count;\n                                    AddGameObjectRenderers(renderers, false);\n                                }\n                                else\n                                {\n                                    AddGameObjectRenderers(renderers, true);\n                                }\n                                DragAndDrop.AcceptDrag();\n                            }\n                        }\n                        evt.Use();\n                    }\n\n                    break;\n                }\n                case EventType.DragExited:\n                {\n                    evt.Use();\n                    break;\n                }\n            }\n            if (SceneView.lastActiveSceneView != null && SceneView.lastActiveSceneView.camera != null && !m_IsPrefab)\n            {\n                var camera = SceneView.lastActiveSceneView.camera;\n\n                var info = LODUtility.CalculateVisualizationData(camera, m_LODGroup, -1);\n                var linearHeight = info.activeRelativeScreenSize;\n                var relativeHeight = LODGroupGUI.DelinearizeScreenPercentage(linearHeight);\n\n                var worldReferencePoint = LODUtility.CalculateWorldReferencePoint(m_LODGroup);\n                var vectorFromObjectToCamera = (SceneView.lastActiveSceneView.camera.transform.position - worldReferencePoint).normalized;\n                if (Vector3.Dot(camera.transform.forward, vectorFromObjectToCamera) > 0f)\n                    relativeHeight = 1.0f;\n\n                var cameraRect = LODGroupGUI.CalcLODButton(sliderPosition, Mathf.Clamp01(relativeHeight));\n                var cameraIconRect = new Rect(cameraRect.center.x - 15, cameraRect.y - 25, 32, 32);\n                var cameraLineRect = new Rect(cameraRect.center.x - 1, cameraRect.y, 2, cameraRect.height);\n                var cameraPercentRect = new Rect(cameraIconRect.center.x - 5, cameraLineRect.yMax, 35, 20);\n\n                switch (evt.GetTypeForControl(camerId))\n                {\n                    case EventType.Repaint:\n                    {\n                        // Draw a marker to indicate the current scene camera distance\n                        var colorCache = GUI.backgroundColor;\n                        GUI.backgroundColor = new Color(colorCache.r, colorCache.g, colorCache.b, 0.8f);\n                        LODGroupGUI.Styles.m_LODCameraLine.Draw(cameraLineRect, false, false, false, false);\n                        GUI.backgroundColor = colorCache;\n                        GUI.Label(cameraIconRect, LODGroupGUI.Styles.m_CameraIcon, GUIStyle.none);\n                        LODGroupGUI.Styles.m_LODSliderText.Draw(cameraPercentRect, String.Format(\"{0:0}%\", Mathf.Clamp01(linearHeight) * 100.0f), false, false, false, false);\n                        break;\n                    }\n                    case EventType.MouseDown:\n                    {\n                        if (cameraIconRect.Contains(evt.mousePosition))\n                        {\n                            evt.Use();\n                            var cameraPercent = LODGroupGUI.GetCameraPercent(evt.mousePosition, sliderPosition);\n\n                            // Update the selected LOD to be where the camera is if we click the camera\n                            UpdateSelectedLODFromCamera(lods, cameraPercent);\n                            GUIUtility.hotControl = camerId;\n\n                            BeginLODDrag(cameraPercent, m_LODGroup);\n                        }\n                        break;\n                    }\n                    case EventType.MouseDrag:\n                    {\n                        if (GUIUtility.hotControl == camerId)\n                        {\n                            evt.Use();\n                            var cameraPercent = LODGroupGUI.GetCameraPercent(evt.mousePosition, sliderPosition);\n\n                            // Change the active LOD level if the camera moves into a new LOD level\n                            UpdateSelectedLODFromCamera(lods, cameraPercent);\n                            UpdateLODDrag(cameraPercent, m_LODGroup);\n                        }\n                        break;\n                    }\n                    case EventType.MouseUp:\n                    {\n                        if (GUIUtility.hotControl == camerId)\n                        {\n                            EndLODDrag();\n                            GUIUtility.hotControl = 0;\n                            evt.Use();\n                        }\n                        break;\n                    }\n                }\n            }\n        }\n\n        private void BeginLODDrag(float desiredPercentage, LODGroup group)\n        {\n            if (SceneView.lastActiveSceneView == null || SceneView.lastActiveSceneView.camera == null || m_IsPrefab)\n                return;\n\n            UpdateCamera(desiredPercentage, group);\n            SceneView.lastActiveSceneView.ClearSearchFilter();\n            SceneView.lastActiveSceneView.SetSceneViewFilteringForLODGroups(true);\n            HierarchyProperty.FilterSingleSceneObject(group.gameObject.GetInstanceID(), false);\n            SceneView.RepaintAll();\n        }\n\n        private void UpdateLODDrag(float desiredPercentage, LODGroup group)\n        {\n            if (SceneView.lastActiveSceneView == null || SceneView.lastActiveSceneView.camera == null || m_IsPrefab)\n                return;\n\n            UpdateCamera(desiredPercentage, group);\n            SceneView.RepaintAll();\n        }\n\n        private void EndLODDrag()\n        {\n            if (SceneView.lastActiveSceneView == null || SceneView.lastActiveSceneView.camera == null || m_IsPrefab)\n                return;\n\n            SceneView.lastActiveSceneView.SetSceneViewFilteringForLODGroups(false);\n            SceneView.lastActiveSceneView.ClearSearchFilter();\n            // Clearing the search filter of a SceneView will not actually reset the visibility values\n            // of the GameObjects in the scene so we have to explicitly do that  (case 770915).\n            HierarchyProperty.ClearSceneObjectsFilter();\n        }\n\n        //Code to be able to send percentages to this gameobjects lightmap scale\n        private class LODLightmapScale\n        {\n            public readonly float m_Scale;\n            public readonly List<SerializedProperty> m_Renderers;\n\n            public LODLightmapScale(float scale, List<SerializedProperty> renderers)\n            {\n                m_Scale = scale;\n                m_Renderers = renderers;\n            }\n        }\n\n        private void SendPercentagesToLightmapScale()\n        {\n            //List of renderers per LOD\n            var lodRenderers = new List<LODLightmapScale>();\n\n            for (var i = 0; i < m_NumberOfLODs; i++)\n            {\n                var renderersProperty = serializedObject.FindProperty(string.Format(kRenderRootPath, i));\n                var renderersAtLOD = new List<SerializedProperty>();\n\n                for (var k = 0; k < renderersProperty.arraySize; k++)\n                {\n                    var rendererRef = renderersProperty.GetArrayElementAtIndex(k).FindPropertyRelative(\"renderer\");\n\n                    if (rendererRef != null)\n                        renderersAtLOD.Add(rendererRef);\n                }\n                var pixelHeight = i == 0 ? 1.0f : serializedObject.FindProperty(string.Format(kPixelHeightDataPath, i - 1)).floatValue;\n                lodRenderers.Add(new LODLightmapScale(pixelHeight, renderersAtLOD));\n            }\n\n            // set from least detailed to most detailed, as renderers can be in multiple layers\n            for (var i = m_NumberOfLODs - 1; i >= 0; i--)\n            {\n                SetLODLightmapScale(lodRenderers[i]);\n            }\n        }\n\n        private static void SetLODLightmapScale(LODLightmapScale lodRenderer)\n        {\n            foreach (var renderer in lodRenderer.m_Renderers)\n            {\n                if (renderer.objectReferenceValue == null)\n                    continue;\n\n                using (var so = new SerializedObject(renderer.objectReferenceValue))\n                {\n                    var lightmapScaleProp = so.FindProperty(\"m_ScaleInLightmap\");\n                    lightmapScaleProp.floatValue = Mathf.Max(0.0f, lodRenderer.m_Scale * (1.0f / LightmapVisualization.GetLightmapLODLevelScale((Renderer)renderer.objectReferenceValue)));\n                    so.ApplyModifiedProperties();\n                }\n            }\n        }\n\n        // / PREVIEW GUI CODE BELOW\n        public override bool HasPreviewGUI()\n        {\n            return (target != null);\n        }\n\n        private PreviewRenderUtility m_PreviewUtility;\n        static private readonly GUIContent[] kSLightIcons = {null, null};\n        private Vector2 m_PreviewDir = new Vector2(0, -20);\n\n        public override void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture)\n            {\n                if (Event.current.type == EventType.Repaint)\n                    EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), \"LOD preview \\nnot available\");\n                return;\n            }\n\n            InitPreview();\n            m_PreviewDir = PreviewGUI.Drag2D(m_PreviewDir, r);\n            m_PreviewDir.y = Mathf.Clamp(m_PreviewDir.y, -89.0f, 89.0f);\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            m_PreviewUtility.BeginPreview(r, background);\n\n            DoRenderPreview();\n\n            m_PreviewUtility.EndAndDrawPreview(r);\n        }\n\n        void InitPreview()\n        {\n            if (m_PreviewUtility == null)\n                m_PreviewUtility = new PreviewRenderUtility();\n\n            if (kSLightIcons[0] == null)\n            {\n                kSLightIcons[0] = EditorGUIUtility.IconContent(\"PreMatLight0\");\n                kSLightIcons[1] = EditorGUIUtility.IconContent(\"PreMatLight1\");\n            }\n        }\n\n        protected void DoRenderPreview()\n        {\n            bool LODSelected = activeLOD >= 0;\n            if (m_PreviewUtility.renderTexture.width <= 0\n                || m_PreviewUtility.renderTexture.height <= 0\n                || m_NumberOfLODs <= 0)\n                return;\n\n            var bounds = new Bounds(Vector3.zero, Vector3.zero);\n            bool boundsSet = false;\n\n            Renderer[] renderers = null;\n            if (target is LODGroup targetLODGroup)\n            {\n                LOD[] lodArray = targetLODGroup.GetLODs();\n                int lodIndex = LODSelected ? activeLOD : 0; // display LOD0 if no LOD is selected\n                if (lodIndex >= 0 && lodIndex < lodArray.Length)\n                {\n                    renderers = lodArray[lodIndex].renderers; \n                }\n            }\n            if (renderers == null)\n                return;\n\n            var meshsToRender = new List<MeshFilter>();\n            var billboards = new List<BillboardRenderer>();\n            for (int i = 0; i < renderers.Length; i++)\n            {\n                var renderer = renderers[i];\n                if (renderer == null)\n                    continue;\n\n                var meshFilter = renderer.GetComponent<MeshFilter>();\n                if (meshFilter != null && meshFilter.sharedMesh != null && meshFilter.sharedMesh.subMeshCount > 0)\n                {\n                    meshsToRender.Add(meshFilter);\n                }\n\n                var billboard = renderer.GetComponent<BillboardRenderer>();\n                if (billboard != null && billboard.billboard != null && billboard.sharedMaterial != null)\n                {\n                    billboards.Add(billboard);\n                }\n\n                if (!boundsSet)\n                {\n                    bounds = renderer.bounds;\n                    boundsSet = true;\n                }\n                else\n                    bounds.Encapsulate(renderer.bounds);\n            }\n\n            if (!boundsSet)\n                return;\n\n            var halfSize = bounds.extents.magnitude;\n            var distance = halfSize * 10.0f;\n\n            var viewDir = -(m_PreviewDir / 100.0f);\n\n            m_PreviewUtility.camera.transform.position = bounds.center + (new Vector3(Mathf.Sin(viewDir.x) * Mathf.Cos(viewDir.y), Mathf.Sin(viewDir.y), Mathf.Cos(viewDir.x) * Mathf.Cos(viewDir.y)) * distance);\n\n            m_PreviewUtility.camera.transform.LookAt(bounds.center);\n            m_PreviewUtility.camera.nearClipPlane = 0.05f;\n            m_PreviewUtility.camera.farClipPlane = 1000.0f;\n\n            m_PreviewUtility.lights[0].intensity = 1.0f;\n            m_PreviewUtility.lights[0].transform.rotation = Quaternion.Euler(50f, 50f, 0);\n            m_PreviewUtility.lights[1].intensity = 1.0f;\n            m_PreviewUtility.ambientColor = new Color(.2f, .2f, .2f, 0);\n\n            foreach (var meshFilter in meshsToRender)\n            {\n                for (int k = 0; k < meshFilter.sharedMesh.subMeshCount; k++)\n                {\n                    if (k < meshFilter.GetComponent<Renderer>().sharedMaterials.Length)\n                    {\n                        var matrix = Matrix4x4.TRS(meshFilter.transform.position, meshFilter.transform.rotation, meshFilter.transform.localScale);\n                        m_PreviewUtility.DrawMesh(\n                            meshFilter.sharedMesh,\n                            matrix,\n                            meshFilter.GetComponent<Renderer>().sharedMaterials[k],\n                            k);\n                    }\n                }\n            }\n\n            foreach (var billboard in billboards)\n            {\n                if (m_BillboardPreviewMesh == null)\n                {\n                    m_BillboardPreviewMesh = new Mesh();\n                    m_BillboardPreviewMesh.hideFlags = HideFlags.HideAndDontSave;\n                    m_BillboardPreviewMesh.MarkDynamic();\n                }\n                if (m_BillboardPreviewProperties == null)\n                    m_BillboardPreviewProperties = new MaterialPropertyBlock();\n                BillboardAssetInspector.MakeRenderMesh(m_BillboardPreviewMesh, billboard.billboard);\n                billboard.billboard.MakeMaterialProperties(m_BillboardPreviewProperties, m_PreviewUtility.camera);\n                var matrix = Matrix4x4.TRS(billboard.transform.position, billboard.transform.rotation, billboard.transform.localScale);\n                m_PreviewUtility.DrawMesh(\n                    m_BillboardPreviewMesh,\n                    matrix,\n                    billboard.sharedMaterial,\n                    0, m_BillboardPreviewProperties);\n            }\n\n            m_PreviewUtility.Render(Unsupported.useScriptableRenderPipeline);\n        }\n\n        override public string GetInfoString()\n        {\n            if (SceneView.lastActiveSceneView == null\n                || SceneView.lastActiveSceneView.camera == null\n                || m_NumberOfLODs <= 0\n                || activeLOD < 0)\n                return \"\";\n\n            var materials = new List<Material>();\n            var renderers = serializedObject.FindProperty(string.Format(kRenderRootPath, activeLOD));\n            for (int i = 0; i < renderers.arraySize; i++)\n            {\n                var renderRef = renderers.GetArrayElementAtIndex(i).FindPropertyRelative(\"renderer\");\n                var renderer = renderRef.objectReferenceValue as Renderer;\n\n                if (renderer != null)\n                    materials.AddRange(renderer.sharedMaterials);\n            }\n\n            var camera = SceneView.lastActiveSceneView.camera;\n\n            var info = LODUtility.CalculateVisualizationData(camera, m_LODGroup, activeLOD);\n            return activeLOD != -1 ? string.Format(\"{0} Renderer(s)\\n{1} Triangle(s)\\n{2} Material(s)\", renderers.arraySize, info.triangleCount, materials.Distinct().Count()) : \"LOD: culled\";\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LODGroupGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    internal static class LODGroupGUI\n    {\n        // Default colors for each LOD group....\n        public static readonly Color[] kLODColors =\n        {\n            new Color(0.4831376f, 0.6211768f, 0.0219608f, 1.0f),\n            new Color(0.2792160f, 0.4078432f, 0.5835296f, 1.0f),\n            new Color(0.2070592f, 0.5333336f, 0.6556864f, 1.0f),\n            new Color(0.5333336f, 0.1600000f, 0.0282352f, 1.0f),\n            new Color(0.3827448f, 0.2886272f, 0.5239216f, 1.0f),\n            new Color(0.8000000f, 0.4423528f, 0.0000000f, 1.0f),\n            new Color(0.4486272f, 0.4078432f, 0.0501960f, 1.0f),\n            new Color(0.7749016f, 0.6368624f, 0.0250984f, 1.0f)\n        };\n\n        public static readonly Color kCulledLODColor = new Color(.4f, 0f, 0f, 1f);\n\n        public const int kSceneLabelHalfWidth = 100;\n        public const int kSceneLabelHeight = 45;\n        public const int kSceneHeaderOffset = 40;\n\n        public const int kSliderBarTopMargin = 18;\n        public const int kSliderBarHeight = 30;\n        public const int kSliderBarBottomMargin = 16;\n\n        public const int kRenderersButtonHeight = 60;\n        public const int kButtonPadding = 2;\n        public const int kDeleteButtonSize = 20;\n\n        public const int kSelectedLODRangePadding = 3;\n\n        public const int kRenderAreaForegroundPadding = 3;\n\n        public class GUIStyles\n        {\n            public readonly GUIStyle m_LODSliderBG = \"LODSliderBG\";\n            public readonly GUIStyle m_LODSliderRange = \"LODSliderRange\";\n            public readonly GUIStyle m_LODSliderRangeSelected = \"LODSliderRangeSelected\";\n            public readonly GUIStyle m_LODSliderText = \"LODSliderText\";\n            public readonly GUIStyle m_LODSliderTextSelected = \"LODSliderTextSelected\";\n            public readonly GUIStyle m_LODStandardButton = \"Button\";\n            public readonly GUIStyle m_LODRendererButton = \"LODRendererButton\";\n            public readonly GUIStyle m_LODRendererAddButton = \"LODRendererAddButton\";\n            public readonly GUIStyle m_LODRendererRemove = \"LODRendererRemove\";\n            public readonly GUIStyle m_LODBlackBox = \"LODBlackBox\";\n            public readonly GUIStyle m_LODCameraLine = \"LODCameraLine\";\n\n            public readonly GUIStyle m_LODSceneText = \"LODSceneText\";\n            public readonly GUIStyle m_LODRenderersText = \"LODRenderersText\";\n            public readonly GUIStyle m_LODLevelNotifyText = \"LODLevelNotifyText\";\n\n            public readonly GUIContent m_IconRendererPlus                   = EditorGUIUtility.TrIconContent(\"Toolbar Plus\", \"Add New Renderers\");\n            public readonly GUIContent m_IconRendererMinus                  = EditorGUIUtility.TrIconContent(\"Toolbar Minus\", \"Remove Renderer\");\n            public readonly GUIContent m_CameraIcon                         = EditorGUIUtility.IconContent<Camera>();\n\n            public readonly GUIContent m_UploadToImporter                   = EditorGUIUtility.TrTextContent(\"Upload to Importer\", \"Upload the modified screen percentages to the model importer.\");\n            public readonly GUIContent m_UploadToImporterDisabled           = EditorGUIUtility.TrTextContent(\"Upload to Importer\", \"Number of LOD's in the scene instance differ from the number of LOD's in the imported model.\");\n            public readonly GUIContent m_RecalculateBounds                  = EditorGUIUtility.TrTextContent(\"Recalculate Bounds\", \"Recalculate bounds to encapsulate all child renderers.\");\n            public readonly GUIContent m_RecalculateBoundsDisabled          = EditorGUIUtility.TrTextContent(\"Recalculate Bounds\", \"Bounds are already up-to-date.\");\n            public readonly GUIContent m_LightmapScale                      = EditorGUIUtility.TrTextContent(\"Recalculate Lightmap Scale\", \"Set the lightmap scale to match the LOD percentages.\");\n            public readonly GUIContent m_RendersTitle                       = EditorGUIUtility.TrTextContent(\"Renderers\");\n\n            public readonly GUIContent m_AnimatedCrossFadeInvalidText       = EditorGUIUtility.TrTextContent(\"Animated cross-fading is currently disabled. Please enable \\\"Animate Between Next LOD\\\" on either the current or the previous LOD.\");\n            public readonly GUIContent m_AnimatedCrossFadeInconsistentText  = EditorGUIUtility.TrTextContent(\"Animated cross-fading is currently disabled. \\\"Animate Between Next LOD\\\" is enabled but the next LOD is not in Animated Cross Fade mode.\");\n            public readonly GUIContent m_AnimateBetweenPreviousLOD          = EditorGUIUtility.TrTextContent(\"Animate Between Previous LOD\", \"Cross-fade animation plays when transits between this LOD and the previous (lower) LOD.\");\n\n            public readonly GUIContent m_LODObjectSizeLabel = EditorGUIUtility.TrTextContent(\"Object Size\", \"The Object size in local space. This is used to calculate the relative screen height for the object.\");\n            public readonly GUIContent m_ResetObjectSizeLabel = EditorGUIUtility.TrTextContent(\"Reset Object Size\", \"Resets the Object Size in Local Space to 1 and preserves LOD distances.\");\n            public readonly GUIContent m_LODDistancesInRelativeSizeLabel = EditorGUIUtility.TrTextContent(\"LOD Distances in Screen Relative Size\");\n            public readonly GUIContent m_LODSetToCameraLabel = EditorGUIUtility.TrTextContent(\"Set to Camera\");\n\n            public readonly GUIContent m_LODTransitionPercentageLabel = EditorGUIUtility.TrTextContent(\"Transition (% Screen Size)\", \"This value marks where LOD level transitions into a lower LOD level.\");\n            public static GUIContent m_TriangleCountLabel = EditorGUIUtility.TrTextContent(\"Triangles\");\n            public static GUIContent m_VertexCountLabel = EditorGUIUtility.TrTextContent(\"Vertices\");\n\n            public static GUIContent m_DistanceInMetersLabel = EditorGUIUtility.TrTextContent(\"-\", \"The displayed distance depends on the current Scene View camera settings and might be different in Game View.\");\n\n            public static GUIStyle m_InspectorTitlebarFlat;\n\n            public static GUIContent m_BlueBorderTextureSelected = EditorGUIUtility.TrIconContent(\"AnimationRowOddSelected\");\n            public static GUIContent m_BlueBorderTextureNormal = EditorGUIUtility.TrIconContent(\"OL title act\");\n            public static GUIContent m_MeshLodInfo = EditorGUIUtility.TrTextContent(\"Mesh LOD is active and has been applied to \");\n\n            public GUIStyles()\n            {\n                m_InspectorTitlebarFlat = new GUIStyle(EditorStyles.inspectorTitlebarFlat);\n                m_InspectorTitlebarFlat.focused.textColor = m_InspectorTitlebarFlat.normal.textColor;\n            }\n        }\n\n        private static GUIStyles s_Styles;\n\n        public static GUIStyles Styles\n        {\n            get\n            {\n                if (s_Styles == null)\n                    s_Styles = new GUIStyles();\n                return s_Styles;\n            }\n        }\n\n        public static float DelinearizeScreenPercentage(float percentage)\n        {\n            if (Mathf.Approximately(0.0f, percentage))\n                return 0.0f;\n\n            return Mathf.Sqrt(percentage);\n        }\n\n        public static float LinearizeScreenPercentage(float percentage)\n        {\n            return percentage * percentage;\n        }\n\n        public static Rect CalcLODButton(Rect totalRect, float percentage)\n        {\n            return new Rect(totalRect.x + (Mathf.Round(totalRect.width * (1.0f - percentage))) - 5, totalRect.y, 10, totalRect.height);\n        }\n\n        public static Rect GetCulledBox(Rect totalRect, float previousLODPercentage)\n        {\n            var r = CalcLODRange(totalRect, previousLODPercentage, 0.0f);\n            r.height -= 2;\n            r.width -= 1;\n            r.center += new Vector2(0f, 1.0f);\n            return r;\n        }\n\n        public class LODInfo\n        {\n            public Rect m_ButtonPosition;\n            public Rect m_RangePosition;\n\n            public LODInfo(int lodLevel, string name, float screenPercentage)\n            {\n                LODLevel = lodLevel;\n                LODName = name;\n                RawScreenPercent = screenPercentage;\n            }\n\n            public int LODLevel { get; private set; }\n            public string LODName { get; private set; }\n            public float RawScreenPercent { get; set; }\n\n            public float ScreenPercent\n            {\n                get { return DelinearizeScreenPercentage(RawScreenPercent); }\n                set { RawScreenPercent = LinearizeScreenPercentage(value); }\n            }\n        }\n\n        public static List<LODInfo> CreateLODInfos(int numLODs, Rect area, Func<int, string> nameGen, Func<int, float> heightGen)\n        {\n            var lods = new List<LODInfo>();\n\n            for (int i = 0; i < numLODs; ++i)\n            {\n                var lodInfo = new LODInfo(i, nameGen(i), heightGen(i));\n                lodInfo.m_ButtonPosition = CalcLODButton(area, lodInfo.ScreenPercent);\n                var previousPercentage = i == 0 ? 1.0f : lods[i - 1].ScreenPercent;\n                lodInfo.m_RangePosition = CalcLODRange(area, previousPercentage, lodInfo.ScreenPercent);\n                lods.Add(lodInfo);\n            }\n\n            return lods;\n        }\n\n        public static float GetCameraPercent(Vector2 position, Rect sliderRect)\n        {\n            var percentage = Mathf.Clamp(1.0f - (position.x - sliderRect.x) / sliderRect.width, 0.01f, 1.0f);\n            percentage = LODGroupGUI.LinearizeScreenPercentage(percentage);\n            return percentage;\n        }\n\n        public static void SetSelectedLODLevelPercentage(float newScreenPercentage, int lod, List<LODInfo> lods)\n        {\n            // Find the lower detail lod... clamp value to stop overlapping slider\n            var minimum = 0.0f;\n            var lowerLOD = lods.FirstOrDefault(x => x.LODLevel == lods[lod].LODLevel + 1);\n            if (lowerLOD != null)\n                minimum = lowerLOD.RawScreenPercent;\n\n            // Find the higher detail lod... clamp value to stop overlapping slider\n            var maximum = 1.0f;\n            var higherLOD = lods.FirstOrDefault(x => x.LODLevel == lods[lod].LODLevel - 1);\n            if (higherLOD != null)\n                maximum = higherLOD.RawScreenPercent;\n\n            maximum = Mathf.Clamp01(maximum);\n            minimum = Mathf.Clamp01(minimum);\n\n            // Set that value\n            lods[lod].RawScreenPercent = Mathf.Clamp(newScreenPercentage, minimum, maximum);\n        }\n\n        public static void DrawLODSlider(Rect area, IList<LODInfo> lods, int selectedLevel, bool[] enabledMeshLods = null)\n        {\n            Styles.m_LODSliderBG.Draw(area, GUIContent.none, false, false, false, false);\n            for (int i = 0; i < lods.Count; i++)\n            {\n                var lod = lods[i];\n                if (enabledMeshLods != null)\n                {\n                    DrawLODRange(lod, i == 0 ? 1.0f : lods[i - 1].RawScreenPercent, i == selectedLevel, enabledMeshLods[i]);\n                }\n                else\n                {\n                    DrawLODRange(lod, i == 0 ? 1.0f : lods[i - 1].RawScreenPercent, i == selectedLevel);\n                }\n                DrawLODButton(lod);\n            }\n\n            DrawCulledRange(area, lods.Count > 0 ? lods[lods.Count - 1].RawScreenPercent : 1.0f);\n        }\n\n\n        public static void DrawMixedValueLODSlider(Rect area)\n        {\n            Styles.m_LODSliderBG.Draw(area, GUIContent.none, false, false, false, false);\n            var r = GetCulledBox(area, 1.0f);\n            // Draw the range of a lod level on the slider\n            var tempColor = GUI.color;\n            GUI.color = kLODColors[1] * 0.6f; // more greyish\n            Styles.m_LODSliderRange.Draw(r, GUIContent.none, false, false, false, false);\n            GUI.color = tempColor;\n            var centeredStyle = new GUIStyle(EditorStyles.whiteLargeLabel)\n            {\n                alignment = TextAnchor.MiddleCenter\n            };\n            GUI.Label(area, \"---\", centeredStyle);\n        }\n\n        private static Rect CalcLODRange(Rect totalRect, float startPercent, float endPercent)\n        {\n            var startX = Mathf.Round(totalRect.width * (1.0f - startPercent));\n            var endX = Mathf.Round(totalRect.width * (1.0f - endPercent));\n\n            return new Rect(totalRect.x + startX, totalRect.y, endX - startX, totalRect.height);\n        }\n\n        private static void DrawLODButton(LODInfo currentLOD)\n        {\n            // Make the lod button areas a horizonal resizer\n            EditorGUIUtility.AddCursorRect(currentLOD.m_ButtonPosition, MouseCursor.ResizeHorizontal);\n        }\n\n        private static void DrawLODRange(LODInfo currentLOD, float previousLODPercentage, bool isSelected, bool isMeshLodEnabled = false)\n        {\n            var tempColor = GUI.backgroundColor;\n            var startPercentageString = string.Format(\"{0}\\n{1:0}%\", currentLOD.LODName + (isMeshLodEnabled ? \" (Mesh LOD)\" : \"\"), previousLODPercentage * 100);\n            if (isSelected)\n            {\n                var foreground = currentLOD.m_RangePosition;\n                foreground.width -= kSelectedLODRangePadding * 2;\n                foreground.height -= kSelectedLODRangePadding * 2;\n                foreground.center += new Vector2(kSelectedLODRangePadding, kSelectedLODRangePadding);\n                Styles.m_LODSliderRangeSelected.Draw(currentLOD.m_RangePosition, GUIContent.none, false, false, false, false);\n                GUI.backgroundColor = kLODColors[currentLOD.LODLevel];\n                if (foreground.width > 0)\n                    Styles.m_LODSliderRange.Draw(foreground, GUIContent.none, false, false, false, false);\n                Styles.m_LODSliderText.Draw(currentLOD.m_RangePosition, startPercentageString, false, false, false, false);\n            }\n            else\n            {\n                GUI.backgroundColor = kLODColors[currentLOD.LODLevel];\n                GUI.backgroundColor *= 0.6f;\n                Styles.m_LODSliderRange.Draw(currentLOD.m_RangePosition, GUIContent.none, false, false, false, false);\n                Styles.m_LODSliderText.Draw(currentLOD.m_RangePosition, startPercentageString, false, false, false, false);\n            }\n            GUI.backgroundColor = tempColor;\n        }\n\n        private static void DrawCulledRange(Rect totalRect, float previousLODPercentage)\n        {\n            if (Mathf.Approximately(previousLODPercentage, 0.0f)) return;\n\n            var r = GetCulledBox(totalRect, DelinearizeScreenPercentage(previousLODPercentage));\n            // Draw the range of a lod level on the slider\n            var tempColor = GUI.color;\n            GUI.color = kCulledLODColor;\n            Styles.m_LODSliderRange.Draw(r, GUIContent.none, false, false, false, false);\n            GUI.color = tempColor;\n\n            // Draw some details for the current marker\n            var startPercentageString = string.Format(\"Culled\\n{0:0}%\", previousLODPercentage * 100);\n            Styles.m_LODSliderText.Draw(r, startPercentageString, false, false, false, false);\n        }\n\n        private static readonly int s_FoldoutHeaderHash = \"FoldoutHeader\".GetHashCode();\n\n        internal static void DrawRoundedBoxAroundLODDFoldout(int lodGroupIndex, int activeLOD)\n        {\n            Texture borderTexture = lodGroupIndex == activeLOD ? GUIStyles.m_BlueBorderTextureSelected.image : GUIStyles.m_BlueBorderTextureNormal.image;\n\n            GUILayoutGroup g = GUILayoutUtility.BeginLayoutGroup(EditorStyles.helpBox, null, typeof(GUILayoutGroup));\n            g.isVertical = true;\n\n            GUIUtility.CheckOnGUI();\n            if (Event.current.type == EventType.Repaint)\n            {\n                GUI.DrawTexture(g.rect, borderTexture, ScaleMode.StretchToFill, true, 1, Color.white, Vector4.one * 1, Vector4.one * 3, true);\n            }\n        }\n\n        internal static bool FoldoutHeaderGroupInternal(Rect position, bool foldout, string label, Texture2D background, Color backgroundColor, string additionalLabel = \"\")\n        {\n            GUIStyle foldoutStyle = EditorStyles.titlebarFoldout;\n\n            var offset = 18;\n            position.x += offset;\n\n            // add some spaces so that we could draw a colored texture before the label\n            label = $\"       {label}\";\n            GUIContent content = new GUIContent(label);\n            // Removing the default margin for inspectors\n            if (EditorGUIUtility.hierarchyMode)\n            {\n                position.xMin -= EditorStyles.inspectorDefaultMargins.padding.left - EditorStyles.inspectorDefaultMargins.padding.right;\n                position.xMax += EditorStyles.inspectorDefaultMargins.padding.right;\n            }\n\n            var labelSize = GUI.skin.label.CalcSize(new GUIContent(additionalLabel));\n            Rect menuRect = new Rect\n            {\n                x = position.xMax - foldoutStyle.padding.right - labelSize.x - offset,\n                y = position.y + 2,\n                size = labelSize\n            };\n\n            int id = GUIUtility.GetControlID(s_FoldoutHeaderHash, FocusType.Keyboard, position);\n\n            if (Event.current.type == EventType.KeyDown && GUIUtility.keyboardControl == id)\n            {\n                KeyCode kc = Event.current.keyCode;\n                if (kc == KeyCode.LeftArrow && foldout || (kc == KeyCode.RightArrow && foldout == false))\n                {\n                    foldout = !foldout;\n                    GUI.changed = true;\n                    Event.current.Use();\n                }\n            }\n            else\n            {\n                foldout = EditorGUIInternal.DoToggleForward(position, id, foldout, content, foldoutStyle);\n            }\n\n            if (additionalLabel != null && Event.current.type == EventType.Repaint && labelSize.x < Screen.width * 0.8f)\n            {\n                GUI.Label(menuRect, additionalLabel);\n                menuRect.x = 24 + offset;\n                menuRect.y += 1;\n                menuRect.width = menuRect.height = 16;\n                GUI.DrawTexture(menuRect, background, ScaleMode.ScaleToFit, true, 1, backgroundColor, Vector4.zero, Vector4.one * 2, true);\n            }\n\n            return foldout;\n        }\n    }\n}\n\ninternal static class LODGroupExtensions\n{\n    public static float GetWorldSpaceSize(this LODGroup lodGroup)\n    {\n        return GetWorldSpaceScale(lodGroup.transform) * lodGroup.size;\n    }\n\n    static float GetWorldSpaceScale(Transform t)\n    {\n        var scale = t.lossyScale;\n        float largestAxis = Mathf.Abs(scale.x);\n        largestAxis = Mathf.Max(largestAxis, Mathf.Abs(scale.y));\n        largestAxis = Mathf.Max(largestAxis, Mathf.Abs(scale.z));\n        return largestAxis;\n    }\n\n    public static float DistanceToRelativeHeight(Camera camera, float distance, float size)\n    {\n        if (camera.orthographic)\n            return size * 0.5F / camera.orthographicSize;\n\n        var halfAngle = Mathf.Tan(Mathf.Deg2Rad * camera.fieldOfView * 0.5F);\n        var relativeHeight = size * 0.5F / (distance * halfAngle);\n        return relativeHeight;\n    }\n\n    public static float RelativeHeightToDistance(Camera camera, float relativeHeight, float size)\n    {\n        if (camera.orthographic)\n            return -1;\n\n        var halfAngle = Mathf.Tan(Mathf.Deg2Rad * camera.fieldOfView * 0.5F);\n        var distance = size * 0.5F / (relativeHeight * halfAngle);\n        return distance;\n    }\n\n    public static float GetRelativeHeight(this LODGroup lodGroup, Camera camera)\n    {\n        var distance = (lodGroup.transform.TransformPoint(lodGroup.localReferencePoint) - camera.transform.position).magnitude;\n        return DistanceToRelativeHeight(camera, distance, lodGroup.GetWorldSpaceSize()) * QualitySettings.lodBias;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LabelGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing System.Text.RegularExpressions;\nusing System.Linq;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class LabelGUI\n    {\n        HashSet<Object> m_CurrentAssetsSet;\n        PopupList.InputData m_AssetLabels;\n        string m_ChangedLabel;\n        bool m_CurrentChanged = false;\n        bool m_ChangeWasAdd = false;\n        bool m_IgnoreNextAssetLabelsChangedCall = false;\n\n        static Action<Object>  s_AssetLabelsForObjectChangedDelegates;\n        private static int s_MaxShownLabels = 10;\n\n        public void OnEnable()\n        {\n            s_AssetLabelsForObjectChangedDelegates += AssetLabelsChangedForObject;\n            EditorApplication.projectChanged += InvalidateLabels;\n        }\n\n        public void OnDisable()\n        {\n            s_AssetLabelsForObjectChangedDelegates -= AssetLabelsChangedForObject;\n            EditorApplication.projectChanged -= InvalidateLabels;\n            SaveLabels();\n        }\n\n        public void OnLostFocus()\n        {\n            SaveLabels();\n        }\n\n        public void InvalidateLabels()\n        {\n            m_AssetLabels = null;\n            m_CurrentAssetsSet = null;\n        }\n\n        public void AssetLabelsChangedForObject(Object asset)\n        {\n            if (!m_IgnoreNextAssetLabelsChangedCall && m_CurrentAssetsSet != null && m_CurrentAssetsSet.Contains(asset))\n            {\n                InvalidateLabels(); // someone else changed the labels for one of our selected assets, so invalidate cache\n            }\n            m_IgnoreNextAssetLabelsChangedCall = false;\n        }\n\n        public void SaveLabels()\n        {\n            if (m_CurrentChanged && m_AssetLabels != null && m_CurrentAssetsSet != null)\n            {\n                bool anyLabelsWereChanged = false;\n                foreach (var currentAsset in m_CurrentAssetsSet)\n                {\n                    bool currentAssetWasChanged = false; // when multi-editing, some assets might e.g. already have the label that was added to all\n                    string[] currentLabels = AssetDatabase.GetLabels(currentAsset);\n                    List<string> currentLabelList = currentLabels.ToList<string>();\n                    if (m_ChangeWasAdd)\n                    {\n                        if (!currentLabelList.Contains(m_ChangedLabel))\n                        {\n                            currentLabelList.Add(m_ChangedLabel);\n                            currentAssetWasChanged = true;\n                        }\n                    }\n                    else\n                    {\n                        if (currentLabelList.Contains(m_ChangedLabel))\n                        {\n                            currentLabelList.Remove(m_ChangedLabel);\n                            currentAssetWasChanged = true;\n                        }\n                    }\n                    if (currentAssetWasChanged)\n                    {\n                        AssetDatabase.SetLabels(currentAsset, currentLabelList.ToArray());\n                        if (s_AssetLabelsForObjectChangedDelegates != null)\n                        {\n                            m_IgnoreNextAssetLabelsChangedCall = true;\n                            s_AssetLabelsForObjectChangedDelegates(currentAsset);\n                        }\n                        anyLabelsWereChanged = true;\n                    }\n                }\n                if (anyLabelsWereChanged)\n                    EditorApplication.Internal_CallAssetLabelsHaveChanged();\n                m_CurrentChanged = false;\n            }\n        }\n\n        public void AssetLabelListCallback(PopupList.ListElement element)\n        {\n            m_ChangedLabel = element.text;\n            element.selected = !element.selected;\n            m_ChangeWasAdd = element.selected;\n            element.partiallySelected = false;\n            m_CurrentChanged = true;\n            SaveLabels();\n            InspectorWindow.RepaintAllInspectors();\n        }\n\n        public void InitLabelCache(Object[] assets)\n        {\n            HashSet<Object> newAssetSet = new HashSet<Object>(assets);\n            // Init only if new asset\n            if (m_CurrentAssetsSet == null || !m_CurrentAssetsSet.SetEquals(newAssetSet))\n            {\n                List<string> all;\n                List<string> partial;\n                GetLabelsForAssets(assets, out all, out partial);\n\n                m_AssetLabels = new PopupList.InputData\n                {\n                    m_CloseOnSelection = false,\n                    m_AllowCustom = true,\n                    m_OnSelectCallback = AssetLabelListCallback,\n                    m_MaxCount = 15,\n                    m_SortAlphabetically = true\n                };\n\n                Dictionary<string, float> allLabels = AssetDatabase.GetAllLabels();\n                foreach (var pair in allLabels)\n                {\n                    PopupList.ListElement element = m_AssetLabels.NewOrMatchingElement(pair.Key);\n                    if (element.filterScore < pair.Value)\n                    {\n                        element.filterScore = pair.Value;\n                    }\n                    element.selected = all.Any(label => string.Equals(label, pair.Key, StringComparison.OrdinalIgnoreCase));\n                    element.partiallySelected = partial.Any(label => string.Equals(label, pair.Key, StringComparison.OrdinalIgnoreCase));\n                }\n            }\n\n            m_CurrentAssetsSet = newAssetSet;\n            m_CurrentChanged = false;\n        }\n\n        public void OnLabelGUI(Object[] assets)\n        {\n            InitLabelCache(assets);\n\n            // For the label list as a whole\n            // The previous layouting means we've already lost a pixel to the left and couple at the top, so it is an attempt at horizontal padding: 3, verical padding: 5\n            // (the rounded sides of labels makes this look like the horizontal and vertical padding is the same)\n            float leftPadding = 1.0f;\n            float rightPadding = 2.0f;\n            float topPadding = 3.0f;\n            float bottomPadding = 5.0f;\n\n            GUIStyle labelButton = EditorStyles.assetLabelIcon;\n\n            float buttonWidth = labelButton.margin.left + labelButton.fixedWidth + rightPadding;\n\n            // Assumes we are already in a vertical layout\n            GUILayout.Space(topPadding);\n\n            // Create a rect to test how wide the label list can be\n            Rect widthProbeRect = GUILayoutUtility.GetRect(0, 10240, 0, 0);\n            widthProbeRect.width -= buttonWidth; // reserve some width for the button\n\n            EditorGUILayout.BeginHorizontal();\n\n            // Left padding\n            GUILayoutUtility.GetRect(leftPadding, leftPadding, 0, 0);\n\n            // Draw labels (fully selected)\n            DrawLabelList(false, widthProbeRect.xMax);\n\n            // Draw labels (partially selected)\n            DrawLabelList(true, widthProbeRect.xMax);\n\n            GUILayout.FlexibleSpace();\n\n            Rect r = GUILayoutUtility.GetRect(labelButton.fixedWidth, labelButton.fixedWidth, labelButton.fixedHeight + bottomPadding, labelButton.fixedHeight + bottomPadding);\n            r.x = widthProbeRect.xMax + labelButton.margin.left;\n            if (EditorGUI.DropdownButton(r, GUIContent.none, FocusType.Passive, labelButton))\n            {\n                PopupWindow.Show(r, new PopupList(m_AssetLabels));\n            }\n\n            EditorGUILayout.EndHorizontal();\n        }\n\n        private void DrawLabelList(bool partiallySelected, float xMax)\n        {\n            GUIStyle labelStyle = partiallySelected ? EditorStyles.assetLabelPartial : EditorStyles.assetLabel;\n            Event evt = Event.current;\n            foreach (GUIContent content in (from i in m_AssetLabels.m_ListElements where (partiallySelected ? i.partiallySelected : i.selected) orderby i.text.ToLower() select i.m_Content).Take(s_MaxShownLabels))\n            {\n                Rect rt = GUILayoutUtility.GetRect(content, labelStyle);\n                if (Event.current.type == EventType.Repaint && rt.xMax >= xMax)\n                    break;\n                GUI.Label(rt, content, labelStyle);\n                if (rt.xMax <= xMax && evt.type == EventType.MouseDown && rt.Contains(evt.mousePosition) && evt.button == 0 && GUI.enabled)\n                {\n                    evt.Use();\n                    rt.x = xMax;\n                    PopupWindow.Show(rt, new PopupList(m_AssetLabels, content.text));\n                }\n            }\n        }\n\n        private void GetLabelsForAssets(Object[] assets, out List<string> all, out List<string> partial)\n        {\n            all = new List<string>();\n            partial = new List<string>();\n\n            Dictionary<string, int> labelAssetCount = new Dictionary<string, int>();\n            foreach (Object asset in assets)\n            {\n                string[] currentLabels = AssetDatabase.GetLabels(asset);\n                foreach (string label in currentLabels)\n                {\n                    labelAssetCount[label] = labelAssetCount.ContainsKey(label) ? labelAssetCount[label] + 1 : 1;\n                }\n            }\n\n            foreach (KeyValuePair<string, int> entry in labelAssetCount)\n            {\n                var list = (entry.Value == assets.Length) ? all : partial;\n                list.Add(entry.Key);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LayoutDropdownWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class LayoutDropdownWindow : PopupWindowContent\n    {\n        class Styles\n        {\n            public Color tableHeaderColor;\n            public Color tableLineColor;\n            public Color parentColor;\n            public Color selfColor;\n            public Color simpleAnchorColor;\n            public Color stretchAnchorColor;\n            public Color anchorCornerColor;\n            public Color pivotColor;\n\n            public GUIStyle frame;\n            public GUIStyle label = new GUIStyle(EditorStyles.miniLabel);\n\n            public Styles()\n            {\n                frame = new GUIStyle();\n                Texture2D tex = new Texture2D(4, 4);\n                tex.SetPixels(new Color[]\n                {\n                    Color.white, Color.white, Color.white, Color.white,\n                    Color.white, Color.clear, Color.clear, Color.white,\n                    Color.white, Color.clear, Color.clear, Color.white,\n                    Color.white, Color.white, Color.white, Color.white\n                });\n                tex.filterMode = FilterMode.Point;\n                tex.Apply();\n                tex.hideFlags = HideFlags.HideAndDontSave;\n                frame.normal.background = tex;\n                frame.border = new RectOffset(2, 2, 2, 2);\n\n                label.alignment = TextAnchor.LowerCenter;\n\n                if (EditorGUIUtility.isProSkin)\n                {\n                    tableHeaderColor = new Color(0.18f, 0.18f, 0.18f, 1);\n                    tableLineColor = new Color(1, 1, 1, 0.3f);\n                    parentColor = new Color(0.4f, 0.4f, 0.4f, 1);\n                    selfColor = new Color(0.6f, 0.6f, 0.6f, 1);\n                    simpleAnchorColor = new Color(0.7f, 0.3f, 0.3f, 1);\n                    stretchAnchorColor = new Color(0.0f, 0.6f, 0.8f, 1);\n                    anchorCornerColor = new Color(0.8f, 0.6f, 0.0f, 1);\n                    pivotColor = new Color(0.0f, 0.6f, 0.8f, 1);\n                }\n                else\n                {\n                    tableHeaderColor = new Color(0.8f, 0.8f, 0.8f, 1);\n                    tableLineColor = new Color(0, 0, 0, 0.5f);\n                    parentColor = new Color(0.55f, 0.55f, 0.55f, 1);\n                    selfColor = new Color(0.2f, 0.2f, 0.2f, 1);\n                    simpleAnchorColor = new Color(0.8f, 0.3f, 0.3f, 1);\n                    stretchAnchorColor = new Color(0.2f, 0.5f, 0.9f, 1);\n                    anchorCornerColor = new Color(0.6f, 0.4f, 0.0f, 1);\n                    pivotColor = new Color(0.2f, 0.5f, 0.9f, 1);\n                }\n            }\n        }\n        static Styles s_Styles;\n\n        SerializedProperty m_AnchorMin;\n        SerializedProperty m_AnchorMax;\n\n        Vector2[,] m_InitValues;\n\n        const int kTopPartHeight = 38;\n        static float[] kPivotsForModes = new float[] { 0, 0.5f, 1, 0.5f, 0.5f }; // Only for actual modes, not for Undefined.\n        static string[] kHLabels = new string[] { \"custom\", \"left\", \"center\", \"right\", \"stretch\", \"%\" };\n        static string[] kVLabels = new string[] { \"custom\", \"top\", \"middle\", \"bottom\", \"stretch\", \"%\" };\n\n        public enum LayoutMode { Undefined = -1, Min = 0, Middle = 1, Max = 2, Stretch = 3 }\n\n        public LayoutDropdownWindow(SerializedObject so)\n        {\n            m_AnchorMin = so.FindProperty(\"m_AnchorMin\");\n            m_AnchorMax = so.FindProperty(\"m_AnchorMax\");\n\n            var targetObjects = so.targetObjects;\n            m_InitValues = new Vector2[targetObjects.Length, 4];\n            for (int i = 0; i < targetObjects.Length; i++)\n            {\n                RectTransform gui = targetObjects[i] as RectTransform;\n                m_InitValues[i, 0] = gui.anchorMin;\n                m_InitValues[i, 1] = gui.anchorMax;\n                m_InitValues[i, 2] = gui.anchoredPosition;\n                m_InitValues[i, 3] = gui.sizeDelta;\n            }\n        }\n\n        public override void OnOpen()\n        {\n            EditorApplication.modifierKeysChanged += editorWindow.Repaint;\n        }\n\n        public override void OnClose()\n        {\n            EditorApplication.modifierKeysChanged -= editorWindow.Repaint;\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            return new Vector2(262, 262 + kTopPartHeight);\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Return)\n                editorWindow.Close();\n\n            if (Event.current.type == EventType.MouseDown && Event.current.clickCount == 2 && rect.Contains(Event.current.mousePosition))\n            {\n                Event.current.Use();\n                editorWindow.Close();\n            }\n\n            GUI.Label(new Rect(rect.x + 5, rect.y + 3, rect.width - 10, 16), EditorGUIUtility.TrTextContent(\"Anchor Presets\"), EditorStyles.boldLabel);\n            GUI.Label(new Rect(rect.x + 5, rect.y + 3 + 16, rect.width - 10, 16), EditorGUIUtility.TrTextContent(\"Shift: Also set pivot     Alt: Also set position\"), EditorStyles.label);\n\n            Color oldColor = GUI.color;\n            GUI.color = s_Styles.tableLineColor * oldColor;\n            GUI.DrawTexture(new Rect(0, kTopPartHeight - 1, 400, 1), EditorGUIUtility.whiteTexture);\n            GUI.color = oldColor;\n\n            GUI.BeginGroup(new Rect(rect.x, rect.y + kTopPartHeight, rect.width, rect.height - kTopPartHeight));\n            TableGUI(rect);\n            GUI.EndGroup();\n        }\n\n        static LayoutMode SwappedVMode(LayoutMode vMode)\n        {\n            if (vMode == LayoutMode.Min)\n                return LayoutMode.Max;\n            else if (vMode == LayoutMode.Max)\n                return LayoutMode.Min;\n            return vMode;\n        }\n\n        internal static void DrawLayoutModeHeadersOutsideRect(Rect rect,\n            SerializedProperty anchorMin,\n            SerializedProperty anchorMax,\n            SerializedProperty position,\n            SerializedProperty sizeDelta)\n        {\n            LayoutMode hMode = GetLayoutModeForAxis(anchorMin, anchorMax, 0);\n            LayoutMode vMode = GetLayoutModeForAxis(anchorMin, anchorMax, 1);\n            vMode = SwappedVMode(vMode);\n            DrawLayoutModeHeaderOutsideRect(rect, 0, hMode);\n            DrawLayoutModeHeaderOutsideRect(rect, 1, vMode);\n        }\n\n        internal static void DrawLayoutModeHeaderOutsideRect(Rect position, int axis, LayoutMode mode)\n        {\n            Rect headerRect = new Rect(position.x, position.y - 16, position.width, 16);\n\n            Matrix4x4 normalMatrix = GUI.matrix;\n            if (axis == 1)\n                GUIUtility.RotateAroundPivot(-90, position.center);\n\n            int index = (int)(mode) + 1;\n            GUI.Label(headerRect, axis == 0 ? kHLabels[index] : kVLabels[index], s_Styles.label);\n\n            GUI.matrix = normalMatrix;\n        }\n\n        void TableGUI(Rect rect)\n        {\n            int padding = 6;\n            int size = 31 + padding * 2;\n            int spacing = 0;\n            int[] groupings = new int[] { 15, 30, 30, 30, 45, 45 };\n\n            Color oldColor = GUI.color;\n\n            int headerW = 62;\n            GUI.color = s_Styles.tableHeaderColor * oldColor;\n            GUI.DrawTexture(new Rect(0, 0, 400, headerW), EditorGUIUtility.whiteTexture);\n            GUI.DrawTexture(new Rect(0, 0, headerW, 400), EditorGUIUtility.whiteTexture);\n            GUI.color = s_Styles.tableLineColor * oldColor;\n            GUI.DrawTexture(new Rect(0, headerW, 400, 1), EditorGUIUtility.whiteTexture);\n            GUI.DrawTexture(new Rect(headerW, 0, 1, 400), EditorGUIUtility.whiteTexture);\n            GUI.color = oldColor;\n\n            LayoutMode hMode = GetLayoutModeForAxis(m_AnchorMin, m_AnchorMax, 0);\n            LayoutMode vMode = GetLayoutModeForAxis(m_AnchorMin, m_AnchorMax, 1);\n            vMode = SwappedVMode(vMode);\n\n            bool doPivot = Event.current.shift;\n            bool doPosition = Event.current.alt;\n\n            int number = 5;\n\n            for (int i = 0; i < number; i++)\n            {\n                LayoutMode cellHMode = (LayoutMode)(i - 1);\n\n                for (int j = 0; j < number; j++)\n                {\n                    LayoutMode cellVMode = (LayoutMode)(j - 1);\n\n                    if (i == 0 && j == 0 && vMode >= 0 && hMode >= 0)\n                        continue;\n\n                    Rect position = new Rect(\n                        i * (size + spacing) + groupings[i],\n                        j * (size + spacing) + groupings[j],\n                        size,\n                        size);\n\n                    if (j == 0 && !(i == 0 && hMode != LayoutMode.Undefined))\n                        DrawLayoutModeHeaderOutsideRect(position, 0, cellHMode);\n                    if (i == 0 && !(j == 0 && vMode != LayoutMode.Undefined))\n                        DrawLayoutModeHeaderOutsideRect(position, 1, cellVMode);\n\n                    bool selected = (cellHMode == hMode) && (cellVMode == vMode);\n\n                    bool selectedHeader = (i == 0 && cellVMode == vMode) || (j == 0 && cellHMode == hMode);\n\n                    if (Event.current.type == EventType.Repaint)\n                    {\n                        if (selected)\n                        {\n                            GUI.color = Color.white * oldColor;\n                            s_Styles.frame.Draw(position, false, false, false, false);\n                        }\n                        else if (selectedHeader)\n                        {\n                            GUI.color = new Color(1, 1, 1, 0.7f) * oldColor;\n                            s_Styles.frame.Draw(position, false, false, false, false);\n                        }\n                    }\n\n                    DrawLayoutMode(\n                        new Rect(position.x + padding, position.y + padding, position.width - padding * 2, position.height - padding * 2),\n                        cellHMode, cellVMode,\n                        doPivot, doPosition);\n\n                    int clickCount = Event.current.clickCount;\n                    if (GUI.Button(position, GUIContent.none, GUIStyle.none))\n                    {\n                        SetLayoutModeForAxis(m_AnchorMin, 0, cellHMode, doPivot, doPosition, m_InitValues);\n                        SetLayoutModeForAxis(m_AnchorMin, 1, SwappedVMode(cellVMode), doPivot, doPosition, m_InitValues);\n                        if (clickCount == 2)\n                            editorWindow.Close();\n                        else\n                            editorWindow.Repaint();\n                    }\n                }\n            }\n            GUI.color = oldColor;\n        }\n\n        static LayoutMode GetLayoutModeForAxis(\n            SerializedProperty anchorMin,\n            SerializedProperty anchorMax,\n            int axis)\n        {\n            if (anchorMin.vector2Value[axis] == 0 && anchorMax.vector2Value[axis] == 0)\n                return LayoutMode.Min;\n            if (anchorMin.vector2Value[axis] == 0.5f && anchorMax.vector2Value[axis] == 0.5f)\n                return LayoutMode.Middle;\n            if (anchorMin.vector2Value[axis] == 1 && anchorMax.vector2Value[axis] == 1)\n                return LayoutMode.Max;\n            if (anchorMin.vector2Value[axis] == 0 && anchorMax.vector2Value[axis] == 1)\n                return LayoutMode.Stretch;\n            return LayoutMode.Undefined;\n        }\n\n        static void SetLayoutModeForAxis(\n            SerializedProperty anchorMin,\n            int axis, LayoutMode layoutMode,\n            bool doPivot, bool doPosition, Vector2[,] defaultValues)\n        {\n            anchorMin.serializedObject.ApplyModifiedProperties();\n\n            var targetObjects = anchorMin.serializedObject.targetObjects;\n            for (int i = 0; i < targetObjects.Length; i++)\n            {\n                RectTransform gui = targetObjects[i] as RectTransform;\n                Undo.RecordObject(gui, \"Change Rectangle Anchors\");\n\n                if (doPosition)\n                {\n                    if (defaultValues != null && defaultValues.Length > i)\n                    {\n                        Vector2 temp;\n\n                        temp = gui.anchorMin;\n                        temp[axis] = defaultValues[i, 0][axis];\n                        gui.anchorMin = temp;\n\n                        temp = gui.anchorMax;\n                        temp[axis] = defaultValues[i, 1][axis];\n                        gui.anchorMax = temp;\n\n                        temp = gui.anchoredPosition;\n                        temp[axis] = defaultValues[i, 2][axis];\n                        gui.anchoredPosition = temp;\n\n                        temp = gui.sizeDelta;\n                        temp[axis] = defaultValues[i, 3][axis];\n                        gui.sizeDelta = temp;\n                    }\n                }\n\n                if (doPivot && layoutMode != LayoutMode.Undefined)\n                {\n                    RectTransformEditor.SetPivotSmart(gui, kPivotsForModes[(int)layoutMode], axis, true, true);\n                }\n\n                Vector2 refPosition = Vector2.zero;\n                switch (layoutMode)\n                {\n                    case LayoutMode.Min:\n                        RectTransformEditor.SetAnchorSmart(gui, 0, axis, false, true, true);\n                        RectTransformEditor.SetAnchorSmart(gui, 0, axis, true, true, true);\n                        refPosition = gui.offsetMin;\n                        EditorUtility.SetDirty(gui);\n                        break;\n                    case LayoutMode.Middle:\n                        RectTransformEditor.SetAnchorSmart(gui, 0.5f, axis, false, true, true);\n                        RectTransformEditor.SetAnchorSmart(gui, 0.5f, axis, true, true, true);\n                        refPosition = (gui.offsetMin + gui.offsetMax) * 0.5f;\n                        EditorUtility.SetDirty(gui);\n                        break;\n                    case LayoutMode.Max:\n                        RectTransformEditor.SetAnchorSmart(gui, 1, axis, false, true, true);\n                        RectTransformEditor.SetAnchorSmart(gui, 1, axis, true, true, true);\n                        refPosition = gui.offsetMax;\n                        EditorUtility.SetDirty(gui);\n                        break;\n                    case LayoutMode.Stretch:\n                        RectTransformEditor.SetAnchorSmart(gui, 0, axis, false, true, true);\n                        RectTransformEditor.SetAnchorSmart(gui, 1, axis, true, true, true);\n                        refPosition = (gui.offsetMin + gui.offsetMax) * 0.5f;\n                        EditorUtility.SetDirty(gui);\n                        break;\n                }\n\n                if (doPosition)\n                {\n                    // Handle position\n                    Vector2 rectPosition = gui.anchoredPosition;\n                    rectPosition[axis] -= refPosition[axis];\n                    gui.anchoredPosition = rectPosition;\n\n                    // Handle sizeDelta\n                    if (layoutMode == LayoutMode.Stretch)\n                    {\n                        Vector2 rectSizeDelta = gui.sizeDelta;\n                        rectSizeDelta[axis] = 0;\n                        gui.sizeDelta = rectSizeDelta;\n                    }\n                }\n            }\n            anchorMin.serializedObject.Update();\n        }\n\n        internal static void DrawLayoutMode(Rect rect,\n            SerializedProperty anchorMin,\n            SerializedProperty anchorMax,\n            SerializedProperty position,\n            SerializedProperty sizeDelta)\n        {\n            LayoutMode hMode = GetLayoutModeForAxis(anchorMin, anchorMax, 0);\n            LayoutMode vMode = GetLayoutModeForAxis(anchorMin, anchorMax, 1);\n            vMode = SwappedVMode(vMode);\n            DrawLayoutMode(rect, hMode, vMode);\n        }\n\n        internal static void DrawLayoutMode(Rect position, LayoutMode hMode, LayoutMode vMode)\n        {\n            DrawLayoutMode(position, hMode, vMode, false, false);\n        }\n\n        internal static void DrawLayoutMode(Rect position, LayoutMode hMode, LayoutMode vMode, bool doPivot)\n        {\n            DrawLayoutMode(position, hMode, vMode, doPivot, false);\n        }\n\n        internal static void DrawLayoutMode(Rect position, LayoutMode hMode, LayoutMode vMode, bool doPivot, bool doPosition)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            Color oldColor = GUI.color;\n\n            // Make parent size the largest possible square, but enforce it's an uneven number.\n            int parentWidth = (int)Mathf.Min(position.width, position.height);\n            if (parentWidth % 2 == 0)\n                parentWidth--;\n\n            int selfWidth = parentWidth / 2;\n            if (selfWidth % 2 == 0)\n                selfWidth++;\n\n            Vector2 parentSize = parentWidth * Vector2.one;\n            Vector2 selfSize = selfWidth * Vector2.one;\n            Vector2 padding = (position.size - parentSize) / 2;\n            padding.x = Mathf.Floor(padding.x);\n            padding.y = Mathf.Floor(padding.y);\n            Vector2 padding2 = (position.size - selfSize) / 2;\n            padding2.x = Mathf.Floor(padding2.x);\n            padding2.y = Mathf.Floor(padding2.y);\n\n            Rect outer = new Rect(position.x + padding.x, position.y + padding.y, parentSize.x, parentSize.y);\n            Rect inner = new Rect(position.x + padding2.x, position.y + padding2.y, selfSize.x, selfSize.y);\n            if (doPosition)\n            {\n                for (int axis = 0; axis < 2; axis++)\n                {\n                    LayoutMode mode = (axis == 0 ? hMode : vMode);\n\n                    if (mode == LayoutMode.Min)\n                    {\n                        Vector2 center = inner.center;\n                        center[axis] += outer.min[axis] - inner.min[axis];\n                        inner.center = center;\n                    }\n                    if (mode == LayoutMode.Middle)\n                    {\n                        // TODO\n                    }\n                    if (mode == LayoutMode.Max)\n                    {\n                        Vector2 center = inner.center;\n                        center[axis] += outer.max[axis] - inner.max[axis];\n                        inner.center = center;\n                    }\n                    if (mode == LayoutMode.Stretch)\n                    {\n                        Vector2 innerMin = inner.min;\n                        Vector2 innerMax = inner.max;\n                        innerMin[axis] = outer.min[axis];\n                        innerMax[axis] = outer.max[axis];\n                        inner.min = innerMin;\n                        inner.max = innerMax;\n                    }\n                }\n            }\n\n            Rect anchor = new Rect();\n            Vector2 min = Vector2.zero;\n            Vector2 max = Vector2.zero;\n            for (int axis = 0; axis < 2; axis++)\n            {\n                LayoutMode mode = (axis == 0 ? hMode : vMode);\n\n                if (mode == LayoutMode.Min)\n                {\n                    min[axis] = outer.min[axis] + 0.5f;\n                    max[axis] = outer.min[axis] + 0.5f;\n                }\n                if (mode == LayoutMode.Middle)\n                {\n                    min[axis] = outer.center[axis];\n                    max[axis] = outer.center[axis];\n                }\n                if (mode == LayoutMode.Max)\n                {\n                    min[axis] = outer.max[axis] - 0.5f;\n                    max[axis] = outer.max[axis] - 0.5f;\n                }\n                if (mode == LayoutMode.Stretch)\n                {\n                    min[axis] = outer.min[axis] + 0.5f;\n                    max[axis] = outer.max[axis] - 0.5f;\n                }\n            }\n            anchor.min = min;\n            anchor.max = max;\n\n            // Draw parent rect\n            if (Event.current.type == EventType.Repaint)\n            {\n                GUI.color = s_Styles.parentColor * oldColor;\n                s_Styles.frame.Draw(outer, false, false, false, false);\n            }\n\n            // Draw anchor lines\n            if (hMode != LayoutMode.Undefined && hMode != LayoutMode.Stretch)\n            {\n                GUI.color = s_Styles.simpleAnchorColor * oldColor;\n                GUI.DrawTexture(new Rect(anchor.xMin - 0.5f, outer.y + 1, 1, outer.height - 2), EditorGUIUtility.whiteTexture);\n                GUI.DrawTexture(new Rect(anchor.xMax - 0.5f, outer.y + 1, 1, outer.height - 2), EditorGUIUtility.whiteTexture);\n            }\n            if (vMode != LayoutMode.Undefined && vMode != LayoutMode.Stretch)\n            {\n                GUI.color = s_Styles.simpleAnchorColor * oldColor;\n                GUI.DrawTexture(new Rect(outer.x + 1, anchor.yMin - 0.5f, outer.width - 2, 1), EditorGUIUtility.whiteTexture);\n                GUI.DrawTexture(new Rect(outer.x + 1, anchor.yMax - 0.5f, outer.width - 2, 1), EditorGUIUtility.whiteTexture);\n            }\n\n            // Draw stretch mode arrows\n            if (hMode == LayoutMode.Stretch)\n            {\n                GUI.color = s_Styles.stretchAnchorColor * oldColor;\n                DrawArrow(new Rect(inner.x + 1, inner.center.y - 0.5f, inner.width - 2, 1));\n            }\n            if (vMode == LayoutMode.Stretch)\n            {\n                GUI.color = s_Styles.stretchAnchorColor * oldColor;\n                DrawArrow(new Rect(inner.center.x - 0.5f, inner.y + 1, 1, inner.height - 2));\n            }\n\n            // Draw self rect\n            if (Event.current.type == EventType.Repaint)\n            {\n                GUI.color = s_Styles.selfColor * oldColor;\n                s_Styles.frame.Draw(inner, false, false, false, false);\n            }\n\n            // Draw pivot\n            if (doPivot && hMode != LayoutMode.Undefined && vMode != LayoutMode.Undefined)\n            {\n                Vector2 pivot = new Vector2(\n                    Mathf.Lerp(inner.xMin + 0.5f, inner.xMax - 0.5f, kPivotsForModes[(int)hMode]),\n                    Mathf.Lerp(inner.yMin + 0.5f, inner.yMax - 0.5f, kPivotsForModes[(int)vMode])\n                );\n\n                GUI.color = s_Styles.pivotColor * oldColor;\n                GUI.DrawTexture(new Rect(pivot.x - 2.5f, pivot.y - 1.5f, 5, 3), EditorGUIUtility.whiteTexture);\n                GUI.DrawTexture(new Rect(pivot.x - 1.5f, pivot.y - 2.5f, 3, 5), EditorGUIUtility.whiteTexture);\n            }\n\n            // Draw anchor corners\n            if (hMode != LayoutMode.Undefined && vMode != LayoutMode.Undefined)\n            {\n                GUI.color = s_Styles.anchorCornerColor * oldColor;\n                GUI.DrawTexture(new Rect(anchor.xMin - 1.5f, anchor.yMin - 1.5f, 2, 2), EditorGUIUtility.whiteTexture);\n                GUI.DrawTexture(new Rect(anchor.xMax - 0.5f, anchor.yMin - 1.5f, 2, 2), EditorGUIUtility.whiteTexture);\n                GUI.DrawTexture(new Rect(anchor.xMin - 1.5f, anchor.yMax - 0.5f, 2, 2), EditorGUIUtility.whiteTexture);\n                GUI.DrawTexture(new Rect(anchor.xMax - 0.5f, anchor.yMax - 0.5f, 2, 2), EditorGUIUtility.whiteTexture);\n            }\n\n            GUI.color = oldColor;\n        }\n\n        static void DrawArrow(Rect lineRect)\n        {\n            GUI.DrawTexture(lineRect, EditorGUIUtility.whiteTexture);\n            if (lineRect.width == 1)\n            {\n                GUI.DrawTexture(new Rect(lineRect.x - 1, lineRect.y + 1, 3, 1), EditorGUIUtility.whiteTexture);\n                GUI.DrawTexture(new Rect(lineRect.x - 2, lineRect.y + 2, 5, 1), EditorGUIUtility.whiteTexture);\n                GUI.DrawTexture(new Rect(lineRect.x - 1, lineRect.yMax - 2, 3, 1), EditorGUIUtility.whiteTexture);\n                GUI.DrawTexture(new Rect(lineRect.x - 2, lineRect.yMax - 3, 5, 1), EditorGUIUtility.whiteTexture);\n            }\n            else\n            {\n                GUI.DrawTexture(new Rect(lineRect.x + 1, lineRect.y - 1, 1, 3), EditorGUIUtility.whiteTexture);\n                GUI.DrawTexture(new Rect(lineRect.x + 2, lineRect.y - 2, 1, 5), EditorGUIUtility.whiteTexture);\n                GUI.DrawTexture(new Rect(lineRect.xMax - 2, lineRect.y - 1, 1, 3), EditorGUIUtility.whiteTexture);\n                GUI.DrawTexture(new Rect(lineRect.xMax - 3, lineRect.y - 2, 1, 5), EditorGUIUtility.whiteTexture);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LegacyIlluminShaderGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class LegacyIlluminShaderGUI : ShaderGUI\n    {\n        public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)\n        {\n            base.OnGUI(materialEditor, props);\n\n            materialEditor.LightmapEmissionProperty(0);\n\n            // We assume that illumin shader always has emission\n            foreach (Material material in materialEditor.targets)\n                material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;\n        }\n    }\n} // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/Inspector/LightEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing Object = UnityEngine.Object;\n\nusing UnityEditor.AnimatedValues;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing System;\nusing System.Linq;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(Light))]\n    [CanEditMultipleObjects]\n    public class LightEditor : Editor\n    {\n        public sealed class Settings\n        {\n            private SerializedObject m_SerializedObject;\n\n            public SerializedProperty lightType { get; private set; }\n            [Obsolete(\"The lightShape property has been deprecated in favor of the lightType property.\")]\n            public SerializedProperty lightShape { get; private set; }\n            public SerializedProperty range { get; private set; }\n            public SerializedProperty spotAngle { get; private set; }\n            public SerializedProperty innerSpotAngle { get; private set; }\n            public SerializedProperty enableSpotReflector { get; private set; }\n            public SerializedProperty cookieSize { get; private set; }\n            public SerializedProperty color { get; private set; }\n            public SerializedProperty intensity { get; private set; }\n            public SerializedProperty bounceIntensity { get; private set; }\n            public SerializedProperty lightUnit { get; private set; }\n            public SerializedProperty luxAtDistance { get; private set; }\n            public SerializedProperty colorTemperature { get; private set; }\n            public SerializedProperty useColorTemperature { get; private set; }\n            public SerializedProperty cookieProp { get; private set; }\n            public SerializedProperty shadowsType { get; private set; }\n            public SerializedProperty shadowsStrength { get; private set; }\n            public SerializedProperty shadowsResolution { get; private set; }\n            public SerializedProperty shadowsBias { get; private set; }\n            public SerializedProperty shadowsNormalBias { get; private set; }\n            public SerializedProperty shadowsNearPlane { get; private set; }\n            public SerializedProperty halo { get; private set; }\n            public SerializedProperty flare { get; private set; }\n            public SerializedProperty renderMode { get; private set; }\n            public SerializedProperty cullingMask { get; private set; }\n            public SerializedProperty renderingLayerMask { get; private set; }\n            public SerializedProperty lightmapping { get; private set; }\n            public SerializedProperty areaSizeX { get; private set; }\n            public SerializedProperty areaSizeY { get; private set; }\n            public SerializedProperty bakedShadowRadiusProp { get; private set; }\n            public SerializedProperty bakedShadowAngleProp { get; private set; }\n\n            Texture2D m_KelvinGradientTexture;\n            const float kMinKelvin = 1000f;\n            const float kMaxKelvin = 20000f;\n            const float kSliderPower = 2f;\n\n            // should have the same int values as corresponding shape in LightType\n            private enum AreaLightShape\n            {\n                None = 0,\n                Rectangle = 3,\n                Disc = 4\n            }\n\n            public Settings(SerializedObject so)\n            {\n                m_SerializedObject = so;\n            }\n\n            private static class Styles\n            {\n                public static readonly GUIContent Type = EditorGUIUtility.TrTextContent(\"Type\", \"Specifies the current type of light. Possible types are Directional, Spot, Point, and Area lights.\");\n                public static readonly GUIContent Shape = EditorGUIUtility.TrTextContent(\"Shape\", \"Specifies the shape of the Area light. Possible types are Rectangle and Disc.\");\n                public static readonly GUIContent Range = EditorGUIUtility.TrTextContent(\"Range\", \"Controls how far the light is emitted from the center of the object.\");\n                public static readonly GUIContent SpotAngle = EditorGUIUtility.TrTextContent(\"Spot Angle\", \"Controls the angle in degrees at the base of a Spot light's cone.\");\n                public static readonly GUIContent InnerOuterSpotAngle = EditorGUIUtility.TrTextContent(\"Inner / Outer Spot Angle\", \"Controls the inner and outer angles in degrees, at the base of a Spot light's cone.\");\n                public static readonly GUIContent Color = EditorGUIUtility.TrTextContent(\"Color\", \"Controls the color being emitted by the light.\");\n                public static readonly GUIContent UseColorTemperature = EditorGUIUtility.TrTextContent(\"Use color temperature mode\", \"Choose between RGB and temperature mode for light's color.\");\n                public static readonly GUIContent ColorFilter = EditorGUIUtility.TrTextContent(\"Filter\", \"A colored gel can be put in front of the light source to tint the light.\");\n                public static readonly GUIContent ColorTemperature = EditorGUIUtility.TrTextContent(\"Temperature\", \"Also known as CCT (Correlated color temperature). The color temperature of the electromagnetic radiation emitted from an ideal black body is defined as its surface temperature in Kelvin. White is 6500K\");\n                public static readonly GUIContent Intensity = EditorGUIUtility.TrTextContent(\"Intensity\", \"Controls the brightness of the light. Light color is multiplied by this value.\");\n                public static readonly GUIContent LightmappingMode = EditorGUIUtility.TrTextContent(\"Mode\", \"Specifies the light mode used to determine if and how a light will be baked. Possible modes are Baked, Mixed, and Realtime.\");\n                public static readonly GUIContent LightBounceIntensityRealtimeGISupport = EditorGUIUtility.TrTextContent(\"Indirect Multiplier\", \"Determines the intensity of indirect light being contributed to the scene. Has no effect when both Realtime and Baked Global Illumination are disabled. If this value is 0, Realtime lights to be removed from realtime global illumination and Baked and Mixed lights to no longer emit indirect lighting.\");\n                public static readonly GUIContent LightBounceIntensity = EditorGUIUtility.TrTextContent(\"Indirect Multiplier\", \"Determines the intensity of indirect light being contributed to to the scene. Has no effect when Baked Global Illumination is disabled. If this value is 0, Baked and Mixed lights no longer emit indirect lighting.\");\n                public static readonly GUIContent ShadowType = EditorGUIUtility.TrTextContent(\"Shadow Type\", \"Specifies whether Hard Shadows, Soft Shadows, or No Shadows will be cast by the light.\");\n                public static readonly GUIContent CastShadows = EditorGUIUtility.TrTextContent(\"Cast Shadows\", \"Specifies whether Soft Shadows or No Shadows will be cast by the light.\");\n                //realtime\n                public static readonly GUIContent ShadowRealtimeSettings = EditorGUIUtility.TrTextContent(\"Realtime Shadows\", \"Settings for realtime direct shadows.\");\n                public static readonly GUIContent ShadowStrength = EditorGUIUtility.TrTextContent(\"Strength\", \"Controls how dark the shadows cast by the light will be.\");\n                public static readonly GUIContent ShadowResolution = EditorGUIUtility.TrTextContent(\"Resolution\", \"Controls the rendered resolution of the shadow maps. A higher resolution will increase the fidelity of shadows at the cost of GPU performance and memory usage.\");\n                public static readonly GUIContent ShadowBias = EditorGUIUtility.TrTextContent(\"Bias\", \"Controls the distance at which the shadows will be pushed away from the light. Useful for avoiding false self-shadowing artifacts.\");\n                public static readonly GUIContent ShadowNormalBias = EditorGUIUtility.TrTextContent(\"Normal Bias\", \"Controls distance at which the shadow casting surfaces will be shrunk along the surface normal. Useful for avoiding false self-shadowing artifacts.\");\n                public static readonly GUIContent ShadowNearPlane = EditorGUIUtility.TrTextContent(\"Near Plane\", \"Controls the value for the near clip plane when rendering shadows. Currently clamped to 0.1 units or 1% of the lights range property, whichever is lower.\");\n                //baked\n                public static readonly GUIContent BakedShadowRadius = EditorGUIUtility.TrTextContent(\"Baked Shadow Radius\", \"Controls the amount of artificial softening applied to the edges of shadows cast by the Point or Spot light.\");\n                public static readonly GUIContent BakedShadowAngle = EditorGUIUtility.TrTextContent(\"Baked Shadow Angle\", \"Controls the amount of artificial softening applied to the edges of shadows cast by directional lights.\");\n\n                public static readonly GUIContent Cookie = EditorGUIUtility.TrTextContent(\"Cookie\", \"Specifies the Texture mask to cast shadows, create silhouettes, or patterned illumination for the light.\");\n                public static readonly GUIContent CookieSize = EditorGUIUtility.TrTextContent(\"Size\", \"Controls the size of the cookie mask currently assigned to the light.\");\n                public static readonly GUIContent CookieTexture = EditorGUIUtility.TrTextContent(\"Cookie\", \"Texture to use for the light cookie.\");\n\n                public static readonly GUIContent DrawHalo = EditorGUIUtility.TrTextContent(\"Draw Halo\", \"When enabled, draws a spherical halo of light with a radius equal to the lights range value.\");\n                public static readonly GUIContent Flare = EditorGUIUtility.TrTextContent(\"Flare\", \"Specifies the flare object to be used by the light to render lens flares in the scene.\");\n                public static readonly GUIContent RenderMode = EditorGUIUtility.TrTextContent(\"Render Mode\", \"Specifies the importance of the light which impacts lighting fidelity and performance. Options are Auto, Important, and Not Important. This only affects Forward Rendering.\");\n                public static readonly GUIContent CullingMask = EditorGUIUtility.TrTextContent(\"Culling Mask\", \"Specifies which layers will be affected or excluded from the light's effect on objects in the scene.\");\n                public static readonly GUIContent RenderingLayerMask = EditorGUIUtility.TrTextContent(\"Rendering Layer Mask\", \"Mask that can be used with SRP when drawing shadows to filter renderers outside of the normal layering system.\");\n\n                public static readonly GUIContent AreaWidth = EditorGUIUtility.TrTextContent(\"Width\", \"Controls the width in units of the area light.\");\n                public static readonly GUIContent AreaHeight = EditorGUIUtility.TrTextContent(\"Height\", \"Controls the height in units of the area light.\");\n                public static readonly GUIContent AreaRadius = EditorGUIUtility.TrTextContent(\"Radius\", \"Controls the radius in units of the disc area light.\");\n\n                public static readonly GUIContent BakingWarning = EditorGUIUtility.TrTextContent(\"Light mode is currently overridden to Realtime mode. Enable Baked Global Illumination to use Mixed or Baked light modes.\");\n                public static readonly GUIContent IndirectBounceShadowWarning = EditorGUIUtility.TrTextContent(\"Realtime indirect bounce shadowing is only supported for Directional lights.\");\n                public static readonly GUIContent CookieSpotRepeatWarning = EditorGUIUtility.TrTextContent(\"Cookie textures for spot lights should be set to clamp, not repeat, to avoid artifacts.\");\n                public static readonly GUIContent CookieNotEnabledWarning = EditorGUIUtility.TrTextContent(\"Cookie support for baked lights is not enabled. Please enable it in Project Settings > Editor > Enable baked cookies support\");\n                public static readonly GUIContent CookieNotEnabledInfo = EditorGUIUtility.TrTextContent(\"Cookie support for mixed lights is not enabled for indirect lighting. You can enable it in Project Settings > Editor > Enable baked cookies support\");\n                public static readonly GUIContent CookieSpotDirectionalTextureWarning = EditorGUIUtility.TrTextContent(\"Spot and directional light cookie textures must be 2D.\");\n                public static readonly GUIContent CookiePointCubemapTextureWarning = EditorGUIUtility.TrTextContent(\"Cookie support for baked lights is not enabled. Please enable it in Project Settings > Editor > Enable baked cookies support\");\n                public static readonly GUIContent MixedUnsupportedWarning = EditorGUIUtility.TrTextContent(\"Light mode is currently overridden to Realtime mode. The current render pipeline doesn't support Mixed mode and/or any of the lighting modes.\");\n                public static readonly GUIContent BakedUnsupportedWarning = EditorGUIUtility.TrTextContent(\"Light mode is currently overridden to Realtime mode. The current render pipeline doesn't support Baked mode.\");\n                public static readonly GUIContent ShadowMaskConvertedToBakedWarning = EditorGUIUtility.TrTextContent(\"Light mode is currently overridden to Baked mode because too many lights overlap in the scene. Shadowmask mode only supports a maximum of 4 overlapping lights.\");\n\n                public static readonly GUIContent[] LightmapBakeTypeTitles = { EditorGUIUtility.TrTextContent(\"Realtime\"), EditorGUIUtility.TrTextContent(\"Mixed\"), EditorGUIUtility.TrTextContent(\"Baked\") };\n                public static readonly int[] LightmapBakeTypeValues = { (int)LightmapBakeType.Realtime, (int)LightmapBakeType.Mixed, (int)LightmapBakeType.Baked };\n\n                public static readonly GUIContent[] LightTypeTitles = { EditorGUIUtility.TrTextContent(\"Spot\"), EditorGUIUtility.TrTextContent(\"Directional\"), EditorGUIUtility.TrTextContent(\"Point\"), EditorGUIUtility.TrTextContent(\"Area (baked only)\") };\n                public static readonly int[] LightTypeValues = { (int)LightType.Spot, (int)LightType.Directional, (int)LightType.Point, (int)LightType.Rectangle };\n\n                public static readonly GUIContent[] AreaLightShapeTitles = { EditorGUIUtility.TrTextContent(\"Rectangle\"), EditorGUIUtility.TrTextContent(\"Disc\") };\n                public static readonly int[] AreaLightShapeValues = { (int)AreaLightShape.Rectangle, (int)AreaLightShape.Disc };\n            }\n\n            public bool isRealtime { get { return lightmapping.intValue == (int)LightmapBakeType.Realtime; } }\n            public bool isMixed { get { return lightmapping.intValue == (int)LightmapBakeType.Mixed; } }\n            public bool isCompletelyBaked { get { return lightmapping.intValue == (int)LightmapBakeType.Baked; } }\n            public bool isBakedOrMixed { get { return !isRealtime; } }\n            public bool isAreaLightType { get { return lightType.intValue == (int)LightType.Rectangle || lightType.intValue == (int)LightType.Disc; } }\n\n            internal bool typeIsSame { get { return !lightType.hasMultipleDifferentValues; } }\n            internal bool shadowTypeIsSame { get { return !shadowsType.hasMultipleDifferentValues; } }\n            internal bool lightmappingTypeIsSame { get { return !lightmapping.hasMultipleDifferentValues; } }\n\n            internal bool isPrefabAsset\n            {\n                get\n                {\n                    if (m_SerializedObject == null || m_SerializedObject.targetObject == null)\n                        return false;\n\n                    return PrefabUtility.IsPartOfPrefabAsset(m_SerializedObject.targetObject);\n                }\n            }\n\n            public Light light { get { return m_SerializedObject.targetObject as Light; } }\n            public Texture cookie { get { return cookieProp.objectReferenceValue as Texture; } }\n\n            internal bool showMixedModeUnsupportedWarning { get { return !isPrefabAsset && isMixed && lightmappingTypeIsSame && !SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Mixed); } }\n            internal bool showBakedModeUnsupportedWarning { get { return !isPrefabAsset && isCompletelyBaked && lightmappingTypeIsSame && !SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Baked); } }\n\n            internal bool showBounceWarning\n            {\n                get\n                {\n                    return typeIsSame && (light.type == LightType.Point || light.type == LightType.Spot) &&\n                        lightmappingTypeIsSame && isRealtime && !bounceIntensity.hasMultipleDifferentValues && bounceIntensity.floatValue > 0.0F;\n                }\n            }\n            internal bool showBakingWarning { get { return !isPrefabAsset && !Lightmapping.GetLightingSettingsOrDefaultsFallback().bakedGI && lightmappingTypeIsSame && isBakedOrMixed; } }\n\n            internal bool showShadowMaskConvertedToBakedWarning { get { return isMixed && Lightmapping.GetLightingSettingsOrDefaultsFallback().mixedBakeMode == MixedLightingMode.Shadowmask && light.bakingOutput.lightmapBakeType == LightmapBakeType.Baked; } }\n\n            internal bool showCookieSpotRepeatWarning\n            {\n                get\n                {\n                    RenderPipelineAsset srpAsset = GraphicsSettings.currentRenderPipeline;\n                    bool usingSRP = srpAsset != null;\n\n                    return typeIsSame && light.type == LightType.Spot &&\n                        !cookieProp.hasMultipleDifferentValues && cookie && cookie.wrapMode != TextureWrapMode.Clamp\n                        && !usingSRP;\n                }\n            }\n\n            public void OnEnable()\n            {\n                lightType = m_SerializedObject.FindProperty(\"m_Type\");\n                range = m_SerializedObject.FindProperty(\"m_Range\");\n                spotAngle = m_SerializedObject.FindProperty(\"m_SpotAngle\");\n                innerSpotAngle = m_SerializedObject.FindProperty(\"m_InnerSpotAngle\");\n                enableSpotReflector = m_SerializedObject.FindProperty(\"m_EnableSpotReflector\");\n                cookieSize = m_SerializedObject.FindProperty(\"m_CookieSize\");\n                color = m_SerializedObject.FindProperty(\"m_Color\");\n                intensity = m_SerializedObject.FindProperty(\"m_Intensity\");\n                bounceIntensity = m_SerializedObject.FindProperty(\"m_BounceIntensity\");\n                lightUnit = m_SerializedObject.FindProperty(\"m_LightUnit\");\n                luxAtDistance = m_SerializedObject.FindProperty(\"m_LuxAtDistance\");\n                colorTemperature = m_SerializedObject.FindProperty(\"m_ColorTemperature\");\n                useColorTemperature = m_SerializedObject.FindProperty(\"m_UseColorTemperature\");\n                cookieProp = m_SerializedObject.FindProperty(\"m_Cookie\");\n                shadowsType = m_SerializedObject.FindProperty(\"m_Shadows.m_Type\");\n                shadowsStrength = m_SerializedObject.FindProperty(\"m_Shadows.m_Strength\");\n                shadowsResolution = m_SerializedObject.FindProperty(\"m_Shadows.m_Resolution\");\n                shadowsBias = m_SerializedObject.FindProperty(\"m_Shadows.m_Bias\");\n                shadowsNormalBias = m_SerializedObject.FindProperty(\"m_Shadows.m_NormalBias\");\n                shadowsNearPlane = m_SerializedObject.FindProperty(\"m_Shadows.m_NearPlane\");\n                halo = m_SerializedObject.FindProperty(\"m_DrawHalo\");\n                flare = m_SerializedObject.FindProperty(\"m_Flare\");\n                renderMode = m_SerializedObject.FindProperty(\"m_RenderMode\");\n                cullingMask = m_SerializedObject.FindProperty(\"m_CullingMask\");\n                renderingLayerMask = m_SerializedObject.FindProperty(\"m_RenderingLayerMask\");\n                lightmapping = m_SerializedObject.FindProperty(\"m_Lightmapping\");\n                areaSizeX = m_SerializedObject.FindProperty(\"m_AreaSize.x\");\n                areaSizeY = m_SerializedObject.FindProperty(\"m_AreaSize.y\");\n                bakedShadowRadiusProp = m_SerializedObject.FindProperty(\"m_ShadowRadius\");\n                bakedShadowAngleProp = m_SerializedObject.FindProperty(\"m_ShadowAngle\");\n\n                if (m_KelvinGradientTexture == null)\n                    m_KelvinGradientTexture = CreateKelvinGradientTexture(\"KelvinGradientTexture\", 300, 16, kMinKelvin, kMaxKelvin);\n            }\n\n            public void OnDestroy()\n            {\n                if (m_KelvinGradientTexture != null)\n                    DestroyImmediate(m_KelvinGradientTexture);\n            }\n\n            static Texture2D CreateKelvinGradientTexture(string name, int width, int height, float minKelvin, float maxKelvin)\n            {\n                // The texture is draw with a simple internal-GUITexture shader that don't perform any gamma correction\n                // so we need to provide value for color temperature texture in gamma space and use a linear format for the texture\n                var texture = new Texture2D(width, height, TextureFormat.ARGB32, false, true)\n                {\n                    name = name,\n                    hideFlags = HideFlags.HideAndDontSave\n                };\n                var pixels = new Color32[width * height];\n\n                float mappedMax = Mathf.Pow(maxKelvin, 1f / kSliderPower);\n                float mappedMin = Mathf.Pow(minKelvin, 1f / kSliderPower);\n\n                for (int i = 0; i < width; i++)\n                {\n                    float pixelfrac = i / (float)(width - 1);\n                    float mappedValue = (mappedMax - mappedMin) * pixelfrac + mappedMin;\n                    float kelvin = Mathf.Pow(mappedValue, kSliderPower);\n                    Color kelvinColor = Mathf.CorrelatedColorTemperatureToRGB(kelvin);\n                    for (int j = 0; j < height; j++)\n                        pixels[j * width + i] = kelvinColor.gamma;\n                }\n\n                texture.SetPixels32(pixels);\n                texture.wrapMode = TextureWrapMode.Clamp;\n                texture.Apply();\n                return texture;\n            }\n\n            public void Update()\n            {\n                m_SerializedObject.Update();\n            }\n\n            public void DrawLightType()\n            {\n                // To the user, we will only display it as a area light, but under the hood, we have Rectangle and Disc. This is not to confuse people\n                // who still use our legacy light inspector.\n\n                int selectedLightType = lightType.intValue;\n                int selectedShape = isAreaLightType ? lightType.intValue : (int)AreaLightShape.None;\n\n                var lightTypeRect = EditorGUILayout.GetControlRect();\n                EditorGUI.BeginProperty(lightTypeRect, Styles.Type, lightType);\n                EditorGUI.BeginChangeCheck();\n\n                int type;\n                if (Styles.LightTypeValues.Contains(lightType.intValue))\n                {\n                    // ^ The currently selected light type is supported in the\n                    // current pipeline.\n                    type = EditorGUI.IntPopup(lightTypeRect, Styles.Type, selectedLightType, Styles.LightTypeTitles, Styles.LightTypeValues);\n                }\n                else\n                {\n                    // ^ The currently selected light type is not supported in\n                    // the current pipeline. Add it to the dropdown, since it\n                    // would show up as a blank entry.\n                    string currentTitle = ((LightType)lightType.intValue).ToString();\n                    GUIContent[] titles = Styles.LightTypeTitles.Append(EditorGUIUtility.TrTextContent(currentTitle)).ToArray();\n                    int[] values = Styles.LightTypeValues.Append(lightType.intValue).ToArray();\n                    type = EditorGUI.IntPopup(lightTypeRect, Styles.Type, selectedLightType, titles, values);\n                }\n\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    AnnotationUtility.SetGizmosDirty();\n                    lightType.intValue = type;\n                }\n                EditorGUI.EndProperty();\n\n                if (!Styles.LightTypeValues.Contains(lightType.intValue))\n                {\n                    EditorGUILayout.HelpBox(\n                        \"This light type is not supported in the current active render pipeline. Change the light type or the active Render Pipeline to use this light.\",\n                        MessageType.Info\n                    );\n                }\n\n                if (isAreaLightType && selectedShape != (int)AreaLightShape.None)\n                {\n                    var lightShapeRect = EditorGUILayout.GetControlRect();\n                    EditorGUI.BeginProperty(lightShapeRect, Styles.Shape, lightType);\n                    EditorGUI.BeginChangeCheck();\n                    int shape = EditorGUI.IntPopup(lightShapeRect, Styles.Shape, selectedShape, Styles.AreaLightShapeTitles, Styles.AreaLightShapeValues);\n\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        Undo.RecordObject(light, \"Adjust Light Shape\");\n                        lightType.intValue = shape;\n                    }\n                    EditorGUI.EndProperty();\n                }\n            }\n\n            public void DrawRange()\n            {\n                EditorGUILayout.PropertyField(range, Styles.Range);\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"showAreaOptions argument for DrawRange(showAreaOptions) has been removed. Use DrawRange() instead (UnityUpgradable).\")]\n            public void DrawRange(bool showAreaOptions)\n            {\n                DrawRange();\n            }\n\n            public void DrawSpotAngle()\n            {\n                EditorGUILayout.Slider(spotAngle, 1f, 179f, Styles.SpotAngle);\n            }\n\n            public void DrawInnerAndOuterSpotAngle()\n            {\n                float textFieldWidth = 45f;\n\n                float min = innerSpotAngle.floatValue;\n                float max = spotAngle.floatValue;\n\n                var rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);\n                // This widget is a little bit of a special case.\n                // The right hand side of the min max slider will control the reset of the max value\n                // The left hand side of the min max slider will control the reset of the min value\n                // The label itself will not have a right click and reset value.\n\n                rect = EditorGUI.PrefixLabel(rect, Styles.InnerOuterSpotAngle);\n                EditorGUI.BeginProperty(new Rect(rect) { width = rect.width * 0.5f }, Styles.InnerOuterSpotAngle, innerSpotAngle);\n                EditorGUI.BeginProperty(new Rect(rect) { xMin = rect.x + rect.width * 0.5f }, GUIContent.none, spotAngle);\n\n                var minRect = new Rect(rect) { width = textFieldWidth };\n                var maxRect = new Rect(rect) { xMin = rect.xMax - textFieldWidth };\n                var sliderRect = new Rect(rect) { xMin = minRect.xMax + EditorGUI.kSpacing, xMax = maxRect.xMin - EditorGUI.kSpacing };\n                EditorGUI.DelayedFloatField(minRect,  innerSpotAngle, GUIContent.none);\n\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.MinMaxSlider(sliderRect, ref min, ref max, 0f, 179f);\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    innerSpotAngle.floatValue = min;\n                    spotAngle.floatValue = max;\n                }\n\n                EditorGUI.DelayedFloatField(maxRect,  spotAngle, GUIContent.none);\n\n                EditorGUI.EndProperty();\n                EditorGUI.EndProperty();\n            }\n\n            public void DrawArea()\n            {\n                if (lightType.intValue == (int)LightType.Rectangle)\n                {\n                    EditorGUILayout.PropertyField(areaSizeX, Styles.AreaWidth);\n                    EditorGUILayout.PropertyField(areaSizeY, Styles.AreaHeight);\n                }\n                else if (lightType.intValue == (int)LightType.Disc)\n                {\n                    EditorGUILayout.PropertyField(areaSizeX, Styles.AreaRadius);\n                }\n            }\n\n            public void DrawColor()\n            {\n                if (GraphicsSettings.lightsUseLinearIntensity && GraphicsSettings.lightsUseColorTemperature)\n                {\n                    EditorGUILayout.PropertyField(useColorTemperature, Styles.UseColorTemperature);\n                    if (useColorTemperature.boolValue)\n                    {\n                        EditorGUILayout.LabelField(Styles.Color);\n                        EditorGUI.indentLevel += 1;\n                        EditorGUILayout.PropertyField(color, Styles.ColorFilter);\n                        EditorGUILayout.SliderWithTexture(Styles.ColorTemperature, colorTemperature, kMinKelvin, kMaxKelvin, kSliderPower, m_KelvinGradientTexture);\n                        EditorGUI.indentLevel -= 1;\n                    }\n                    else\n                        EditorGUILayout.PropertyField(color, Styles.Color);\n                }\n                else\n                    EditorGUILayout.PropertyField(color, Styles.Color);\n            }\n\n            void OnLightmappingItemSelected(object userData)\n            {\n                lightmapping.intValue = (int)userData;\n                m_SerializedObject.ApplyModifiedProperties();\n            }\n\n            public void DrawLightmapping()\n            {\n                var rect = EditorGUILayout.GetControlRect();\n                EditorGUI.BeginProperty(rect, Styles.LightmappingMode, lightmapping);\n                rect = EditorGUI.PrefixLabel(rect, Styles.LightmappingMode);\n\n                int index = Math.Max(0, Array.IndexOf(Styles.LightmapBakeTypeValues, lightmapping.intValue));\n\n                if (EditorGUI.DropdownButton(rect, Styles.LightmapBakeTypeTitles[index], FocusType.Passive))\n                {\n                    var menu = new GenericMenu();\n\n                    for (int i = 0; i < Styles.LightmapBakeTypeValues.Length; i++)\n                    {\n                        int value = Styles.LightmapBakeTypeValues[i];\n                        bool selected = (lightmappingTypeIsSame && (value == lightmapping.intValue));\n\n                        if (((value == (int)LightmapBakeType.Mixed) || (value == (int)LightmapBakeType.Baked)) &&\n                            ((!SupportedRenderingFeatures.IsLightmapBakeTypeSupported((LightmapBakeType)value) || !Lightmapping.GetLightingSettingsOrDefaultsFallback().bakedGI) && !isPrefabAsset))\n                        {\n                            menu.AddDisabledItem(Styles.LightmapBakeTypeTitles[i], selected);\n                        }\n                        else\n                        {\n                            menu.AddItem(Styles.LightmapBakeTypeTitles[i], selected, OnLightmappingItemSelected, value);\n                        }\n                    }\n                    menu.DropDown(rect);\n                }\n                EditorGUI.EndProperty();\n\n                // first make sure that the modes arent unsupported, then unenabled\n                if (showMixedModeUnsupportedWarning)\n                    EditorGUILayout.HelpBox(Styles.MixedUnsupportedWarning.text, MessageType.Warning);\n                else if (showBakedModeUnsupportedWarning)\n                    EditorGUILayout.HelpBox(Styles.BakedUnsupportedWarning.text, MessageType.Warning);\n                else if (showBakingWarning)\n                    EditorGUILayout.HelpBox(Styles.BakingWarning.text, MessageType.Warning);\n                else if(showShadowMaskConvertedToBakedWarning)\n                    EditorGUILayout.HelpBox(Styles.ShadowMaskConvertedToBakedWarning.text, MessageType.Warning);\n            }\n\n            internal void CheckLightmappingConsistency()\n            {\n                //Built-in render-pipeline only support baked area light, enforce it as this inspector is the built-in one.\n                if (isAreaLightType && lightmapping.intValue != (int)LightmapBakeType.Baked)\n                {\n                    lightmapping.intValue = (int)LightmapBakeType.Baked;\n                    m_SerializedObject.ApplyModifiedProperties();\n                }\n            }\n\n            public void DrawIntensity()\n            {\n                EditorGUILayout.PropertyField(intensity, Styles.Intensity);\n            }\n\n            public void DrawBounceIntensity()\n            {\n                if (SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime))\n                {\n                    EditorGUILayout.PropertyField(bounceIntensity, Styles.LightBounceIntensityRealtimeGISupport);\n\n                    // No shadowing of indirect warning.\n                    if (showBounceWarning)\n                    {\n                        EditorGUILayout.HelpBox(Styles.IndirectBounceShadowWarning.text, MessageType.Warning);\n                    }\n                }\n                else\n                {\n                    // no realtime gi support, no need to show this property\n                    if (lightmapping.intValue != (int)LightmapBakeType.Realtime)\n                        EditorGUILayout.PropertyField(bounceIntensity, Styles.LightBounceIntensity);\n                }\n            }\n\n            static Object TextureValidator(Object[] references, System.Type objType, SerializedProperty property, EditorGUI.ObjectFieldValidatorOptions options)\n            {\n                // Accept RenderTextures of correct dimension\n                Texture validated = (RenderTexture)EditorGUI.ValidateObjectFieldAssignment(references, typeof(RenderTexture), property, options);\n                if (validated != null)\n                {\n                    if (objType == typeof(Texture2D) && validated.dimension != TextureDimension.Tex2D)\n                        validated = null;\n                    else if (objType == typeof(Texture3D) && validated.dimension != TextureDimension.Tex3D)\n                        validated = null;\n                    else if (objType == typeof(Cubemap) && validated.dimension != TextureDimension.Cube)\n                        validated = null;\n                }\n                // Accept regular textures\n                if (validated == null)\n                    validated = (Texture)EditorGUI.ValidateObjectFieldAssignment(references, objType, property, options);\n                return validated;\n            }\n\n            static void TexturePropertyBody(Rect position, SerializedProperty prop, LightType cookieLightType)\n            {\n                EditorGUI.BeginChangeCheck();\n                int controlID = GUIUtility.GetControlID(12354, FocusType.Keyboard, position);\n\n                Type type = null;\n                switch (cookieLightType)\n                {\n                    case LightType.Spot:\n                    case LightType.Directional:\n                    case LightType.Rectangle:\n                    case LightType.Disc:\n                        type = typeof(Texture2D);\n                        break;\n\n                    case LightType.Point:\n                        type = typeof(Cubemap);\n                        break;\n\n                    default:\n                        type = typeof(Texture);\n                        break;\n                }\n\n                var newValue = EditorGUI.DoObjectField(position, position, controlID, prop.objectReferenceValue, prop.objectReferenceValue, type, TextureValidator, false, typeof(RenderTexture)) as Texture;\n\n                if (EditorGUI.EndChangeCheck())\n                    prop.objectReferenceValue = newValue;\n            }\n\n            public void DrawCookieProperty(SerializedProperty cookieProperty, GUIContent content, LightType cookieLightType)\n            {\n                Rect controlRect = EditorGUILayout.GetControlRect();\n                Rect thumbRect, labelRect;\n                EditorGUI.GetRectsForMiniThumbnailField(controlRect, out thumbRect, out labelRect);\n                EditorGUI.HandlePrefixLabel(controlRect, labelRect, content, 0, EditorStyles.label);\n                TexturePropertyBody(thumbRect, cookieProperty, cookieLightType);\n            }\n\n            public void DrawCookie()\n            {\n                // Don't draw cookie texture UI for area lights as cookies are not supported by them (except by HDRP, but they handle their own UI drawing logic)\n                if (isAreaLightType)\n                    return;\n\n                DrawCookieProperty(cookieProp, Styles.CookieTexture, (LightType)lightType.intValue);\n            }\n\n            public void DrawCookieSize()\n            {\n                EditorGUI.indentLevel++;\n                EditorGUILayout.PropertyField(cookieSize, Styles.CookieSize);\n                EditorGUI.indentLevel--;\n            }\n\n            public void DrawHalo()\n            {\n                EditorGUILayout.PropertyField(halo, Styles.DrawHalo);\n            }\n\n            public void DrawFlare()\n            {\n                EditorGUILayout.PropertyField(flare, Styles.Flare);\n            }\n\n            public void DrawRenderMode()\n            {\n                EditorGUILayout.PropertyField(renderMode, Styles.RenderMode);\n            }\n\n            public void DrawCullingMask()\n            {\n                EditorGUILayout.PropertyField(cullingMask, Styles.CullingMask);\n            }\n\n            public void DrawRenderingLayerMask()\n            {\n                if (!GraphicsSettings.isScriptableRenderPipelineEnabled)\n                    return;\n\n                using var changeScope = new EditorGUI.ChangeCheckScope();\n                var mask = renderingLayerMask.uintValue;\n                mask = EditorGUILayout.RenderingLayerMaskField(Styles.RenderingLayerMask, mask);\n                if (changeScope.changed)\n                    renderingLayerMask.uintValue = mask;\n            }\n\n            public void ApplyModifiedProperties()\n            {\n                m_SerializedObject.ApplyModifiedProperties();\n            }\n\n            public void DrawShadowsType()\n            {\n                if (isAreaLightType)\n                {\n                    var rect = EditorGUILayout.GetControlRect();\n                    EditorGUI.BeginProperty(rect, Styles.CastShadows, shadowsType);\n                    EditorGUI.BeginChangeCheck();\n                    bool shadows = EditorGUI.Toggle(rect, Styles.CastShadows, shadowsType.intValue != (int)LightShadows.None);\n\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        shadowsType.intValue = shadows ? (int)LightShadows.Soft : (int)LightShadows.None;\n                    }\n                    EditorGUI.EndProperty();\n                }\n                else\n                {\n                    EditorGUILayout.PropertyField(shadowsType, Styles.ShadowType);\n                }\n            }\n\n            public void DrawBakedShadowRadius()\n            {\n                using (new EditorGUI.DisabledScope(shadowsType.intValue != (int)LightShadows.Soft))\n                {\n                    EditorGUILayout.PropertyField(bakedShadowRadiusProp, Styles.BakedShadowRadius);\n                }\n            }\n\n            public void DrawBakedShadowAngle()\n            {\n                using (new EditorGUI.DisabledScope(shadowsType.intValue != (int)LightShadows.Soft))\n                {\n                    EditorGUILayout.Slider(bakedShadowAngleProp, 0.0F, 90.0F, Styles.BakedShadowAngle);\n                }\n            }\n\n            public void DrawRuntimeShadow()\n            {\n                EditorGUILayout.LabelField(Styles.ShadowRealtimeSettings);\n                EditorGUI.indentLevel += 1;\n                EditorGUILayout.Slider(shadowsStrength, 0f, 1f, Styles.ShadowStrength);\n                EditorGUILayout.PropertyField(shadowsResolution, Styles.ShadowResolution);\n                EditorGUILayout.Slider(shadowsBias, 0.0f, 2.0f, Styles.ShadowBias);\n                EditorGUILayout.Slider(shadowsNormalBias, 0.0f, 3.0f, Styles.ShadowNormalBias);\n\n                // this min bound should match the calculation in SharedLightData::GetNearPlaneMinBound()\n                float nearPlaneMinBound = Mathf.Min(0.01f * range.floatValue, 0.1f);\n                EditorGUILayout.Slider(shadowsNearPlane, nearPlaneMinBound, 10.0f, Styles.ShadowNearPlane);\n                EditorGUI.indentLevel -= 1;\n            }\n        }\n\n        private static class StylesEx\n        {\n            public static readonly GUIContent iconRemove = EditorGUIUtility.TrIconContent(\"Toolbar Minus\", \"Remove command buffer\");\n            public static readonly GUIContent DisabledLightWarning = EditorGUIUtility.TrTextContent(\"Lighting has been disabled in at least one Scene view. Any changes applied to lights in the Scene will not be updated in these views until Lighting has been enabled again.\");\n            public static readonly GUIStyle invisibleButton = \"InvisibleButton\";\n        }\n\n        private Settings m_Settings;\n        protected Settings settings => m_Settings ?? (m_Settings = new Settings(serializedObject));\n\n        private IMGUI.Controls.SphereBoundsHandle m_BoundsHandle = new IMGUI.Controls.SphereBoundsHandle();\n\n        AnimBool m_AnimShowSpotOptions = new AnimBool();\n        AnimBool m_AnimShowPointOptions = new AnimBool();\n        AnimBool m_AnimShowDirOptions = new AnimBool();\n        AnimBool m_AnimShowAreaOptions = new AnimBool();\n        AnimBool m_AnimShowRuntimeOptions = new AnimBool();\n        AnimBool m_AnimShowShadowOptions = new AnimBool();\n        AnimBool m_AnimBakedShadowAngleOptions = new AnimBool();\n        AnimBool m_AnimBakedShadowRadiusOptions = new AnimBool();\n        AnimBool m_AnimShowLightBounceIntensity = new AnimBool();\n\n        private bool m_CommandBuffersShown = true;\n\n        protected static readonly Color kGizmoLight = new Color(254 / 255f, 253 / 255f, 136 / 255f, 128 / 255f);\n        protected static readonly Color kGizmoDisabledLight = new Color(135 / 255f, 116 / 255f, 50 / 255f, 128 / 255f);\n\n        static readonly Vector3[] directionalLightHandlesRayPositions = new Vector3[]\n        {\n            new Vector3(1, 0, 0),\n            new Vector3(-1, 0, 0),\n            new Vector3(0, 1, 0),\n            new Vector3(0, -1, 0),\n            new Vector3(1, 1, 0).normalized,\n            new Vector3(1, -1, 0).normalized,\n            new Vector3(-1, 1, 0).normalized,\n            new Vector3(-1, -1, 0).normalized\n        };\n\n        private void SetOptions(AnimBool animBool, bool initialize, bool targetValue)\n        {\n            if (initialize)\n            {\n                animBool.value = targetValue;\n                animBool.valueChanged.AddListener(Repaint);\n            }\n            else\n            {\n                animBool.target = targetValue;\n            }\n        }\n\n        bool spotOptionsValue { get { return settings.typeIsSame && settings.light.type == LightType.Spot; } }\n        bool pointOptionsValue { get { return settings.typeIsSame && settings.light.type == LightType.Point; } }\n        bool dirOptionsValue { get { return settings.typeIsSame && settings.light.type == LightType.Directional; } }\n        bool areaOptionsValue { get { return settings.typeIsSame && settings.isAreaLightType; } }\n        bool runtimeOptionsValue { get { return settings.typeIsSame && ((settings.light.type != LightType.Rectangle && settings.light.type != LightType.Disc) && !settings.isCompletelyBaked); } }\n        bool bakedShadowRadius { get { return settings.typeIsSame && (settings.light.type == LightType.Point || settings.light.type == LightType.Spot) && settings.isBakedOrMixed; } }\n        bool bakedShadowAngle { get { return settings.typeIsSame && settings.light.type == LightType.Directional && settings.isBakedOrMixed; } }\n        bool shadowOptionsValue { get { return settings.shadowTypeIsSame && settings.light.shadows != LightShadows.None; } }\n\n        private void UpdateShowOptions(bool initialize)\n        {\n            SetOptions(m_AnimShowSpotOptions, initialize, spotOptionsValue);\n            SetOptions(m_AnimShowPointOptions, initialize, pointOptionsValue);\n            SetOptions(m_AnimShowDirOptions, initialize, dirOptionsValue);\n            SetOptions(m_AnimShowShadowOptions, initialize, shadowOptionsValue);\n            SetOptions(m_AnimShowAreaOptions, initialize, areaOptionsValue);\n            SetOptions(m_AnimShowRuntimeOptions, initialize, runtimeOptionsValue);\n            SetOptions(m_AnimBakedShadowAngleOptions, initialize, bakedShadowAngle);\n            SetOptions(m_AnimBakedShadowRadiusOptions, initialize, bakedShadowRadius);\n            SetOptions(m_AnimShowLightBounceIntensity, initialize, true);\n        }\n\n        protected virtual void OnEnable()\n        {\n            settings.OnEnable();\n\n            UpdateShowOptions(true);\n        }\n\n        protected virtual void OnDestroy()\n        {\n            if (m_Settings != null)\n            {\n                m_Settings.OnDestroy();\n                m_Settings = null;\n            }\n        }\n\n        private void CommandBufferGUI()\n        {\n            // Command buffers are not serialized data, so can't get to them through\n            // serialized property (hence no multi-edit).\n            if (targets.Length != 1)\n                return;\n            var light = target as Light;\n            if (light == null)\n                return;\n            int count = light.commandBufferCount;\n            if (count == 0)\n                return;\n\n            m_CommandBuffersShown = GUILayout.Toggle(m_CommandBuffersShown, GUIContent.Temp(count + \" command buffers\"), EditorStyles.foldout);\n            if (!m_CommandBuffersShown)\n                return;\n            EditorGUI.indentLevel++;\n            foreach (LightEvent le in (LightEvent[])System.Enum.GetValues(typeof(LightEvent)))\n            {\n                CommandBuffer[] cbs = light.GetCommandBuffers(le);\n                foreach (CommandBuffer cb in cbs)\n                {\n                    using (new GUILayout.HorizontalScope())\n                    {\n                        // row with event & command buffer information label\n                        Rect rowRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.miniLabel);\n                        rowRect.xMin += EditorGUI.indent;\n                        Rect minusRect = GetRemoveButtonRect(rowRect);\n                        rowRect.xMax = minusRect.x;\n                        GUI.Label(rowRect, string.Format(\"{0}: {1} ({2})\", le, cb.name, EditorUtility.FormatBytes(cb.sizeInBytes)), EditorStyles.miniLabel);\n                        // and a button to remove it\n                        if (GUI.Button(minusRect, StylesEx.iconRemove, StylesEx.invisibleButton))\n                        {\n                            light.RemoveCommandBuffer(le, cb);\n                            SceneView.RepaintAll();\n                            PlayModeView.RepaintAll();\n                            GUIUtility.ExitGUI();\n                        }\n                    }\n                }\n            }\n            // \"remove all\" button\n            using (new GUILayout.HorizontalScope())\n            {\n                GUILayout.FlexibleSpace();\n                if (GUILayout.Button(\"Remove all\", EditorStyles.miniButton))\n                {\n                    light.RemoveAllCommandBuffers();\n                    SceneView.RepaintAll();\n                    PlayModeView.RepaintAll();\n                }\n            }\n            EditorGUI.indentLevel--;\n        }\n\n        static Rect GetRemoveButtonRect(Rect r)\n        {\n            var buttonSize = StylesEx.invisibleButton.CalcSize(StylesEx.iconRemove);\n            return new Rect(r.xMax - buttonSize.x, r.y + (int)(r.height / 2 - buttonSize.y / 2), buttonSize.x, buttonSize.y);\n        }\n\n        public override void OnInspectorGUI()\n        {\n            settings.Update();\n\n            UpdateShowOptions(false);\n\n            // Light type (shape and usage)\n            settings.DrawLightType();\n\n            // When we are switching between two light types that don't show the range (directional lights don't)\n            // we want the fade group to stay hidden.\n            if (EditorGUILayout.BeginFadeGroup(1.0f - m_AnimShowDirOptions.faded))\n                settings.DrawRange();\n            EditorGUILayout.EndFadeGroup();\n\n            if (EditorGUILayout.BeginFadeGroup(m_AnimShowSpotOptions.faded))\n                settings.DrawSpotAngle();\n            EditorGUILayout.EndFadeGroup();\n\n            // Area width & height\n            if (EditorGUILayout.BeginFadeGroup(m_AnimShowAreaOptions.faded))\n                settings.DrawArea();\n            EditorGUILayout.EndFadeGroup();\n\n            settings.DrawColor();\n\n            // Baking type\n            settings.CheckLightmappingConsistency();\n            if (EditorGUILayout.BeginFadeGroup(1.0F - m_AnimShowAreaOptions.faded))\n                settings.DrawLightmapping();\n            EditorGUILayout.EndFadeGroup();\n\n            settings.DrawIntensity();\n\n            if (EditorGUILayout.BeginFadeGroup(m_AnimShowLightBounceIntensity.faded))\n                settings.DrawBounceIntensity();\n            EditorGUILayout.EndFadeGroup();\n\n            ShadowsGUI();\n\n            settings.DrawCookie();\n\n            // Cookie size also requires directional light\n            if (EditorGUILayout.BeginFadeGroup(m_AnimShowDirOptions.faded))\n                settings.DrawCookieSize();\n            EditorGUILayout.EndFadeGroup();\n\n            settings.DrawHalo();\n            settings.DrawFlare();\n            settings.DrawRenderMode();\n            settings.DrawCullingMask();\n            settings.DrawRenderingLayerMask();\n\n            if (SceneView.lastActiveSceneView != null && SceneView.lastActiveSceneView.sceneLighting == false)\n                EditorGUILayout.HelpBox(StylesEx.DisabledLightWarning.text, MessageType.Warning);\n\n            CommandBufferGUI();\n\n            settings.ApplyModifiedProperties();\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        void ShadowsGUI()\n        {\n            //NOTE: FadeGroup's dont support nesting. Thus we just multiply the fade values here.\n            settings.DrawShadowsType();\n\n            EditorGUI.indentLevel += 1;\n\n            float show = m_AnimShowShadowOptions.faded;\n\n            // Baked Shadow radius\n            if (EditorGUILayout.BeginFadeGroup(show * m_AnimBakedShadowRadiusOptions.faded))\n                settings.DrawBakedShadowRadius();\n            EditorGUILayout.EndFadeGroup();\n\n            // Baked Shadow angle\n            if (EditorGUILayout.BeginFadeGroup(show * m_AnimBakedShadowAngleOptions.faded))\n                settings.DrawBakedShadowAngle();\n            EditorGUILayout.EndFadeGroup();\n\n            // Runtime shadows - shadow strength, resolution, bias\n            if (EditorGUILayout.BeginFadeGroup(show * m_AnimShowRuntimeOptions.faded))\n                settings.DrawRuntimeShadow();\n            EditorGUILayout.EndFadeGroup();\n\n            EditorGUI.indentLevel -= 1;\n        }\n\n        protected virtual void OnSceneGUI()\n        {\n            if (!target)\n                return;\n            Light t = target as Light;\n\n            Color temp = Handles.color;\n            if (t.enabled)\n                Handles.color = kGizmoLight;\n            else\n                Handles.color = kGizmoDisabledLight;\n\n            float thisRange = t.range;\n            switch (t.type)\n            {\n                case LightType.Directional:\n                    Vector3 lightPos = t.transform.position;\n                    float lightSize;\n                    using (new Handles.DrawingScope(Matrix4x4.identity))    //be sure no matrix affect the size computation\n                    {\n                        lightSize = HandleUtility.GetHandleSize(lightPos);\n                    }\n                    float radius = lightSize * 0.2f;\n                    using (new Handles.DrawingScope(Matrix4x4.TRS(lightPos, t.transform.rotation, Vector3.one)))\n                    {\n                        Handles.DrawWireDisc(Vector3.zero, Vector3.forward, radius);\n                        foreach (Vector3 normalizedPos in directionalLightHandlesRayPositions)\n                        {\n                            Vector3 pos = normalizedPos * radius;\n                            Handles.DrawLine(pos, pos + new Vector3(0, 0, lightSize));\n                        }\n                    }\n                    break;\n                case LightType.Point:\n                    thisRange = Handles.RadiusHandle(Quaternion.identity, t.transform.position, thisRange);\n                    if (GUI.changed)\n                    {\n                        Undo.RecordObject(t, \"Adjust Point Light\");\n                        t.range = thisRange;\n                    }\n                    break;\n                case LightType.Spot:\n                    Transform tr = t.transform;\n                    Vector3 circleCenter = tr.position;\n                    Vector3 arrivalCenter = circleCenter + tr.forward * t.range;\n                    float lightDisc = t.range * Mathf.Tan(Mathf.Deg2Rad * t.spotAngle / 2.0f);\n                    Handles.DrawLine(circleCenter, arrivalCenter + tr.up * lightDisc);\n                    Handles.DrawLine(circleCenter, arrivalCenter - tr.up * lightDisc);\n                    Handles.DrawLine(circleCenter, arrivalCenter + tr.right * lightDisc);\n                    Handles.DrawLine(circleCenter, arrivalCenter - tr.right * lightDisc);\n                    Handles.DrawWireDisc(arrivalCenter, tr.forward, lightDisc);\n                    Handles.color = GetLightHandleColor(Handles.color);\n                    Vector2 angleAndRange = new Vector2(t.spotAngle, t.range);\n                    angleAndRange = Handles.ConeHandle(t.transform.rotation, t.transform.position, angleAndRange, 1.0f, 1.0f, true);\n                    if (GUI.changed)\n                    {\n                        Undo.RecordObject(t, \"Adjust Spot Light\");\n                        t.spotAngle = angleAndRange.x;\n                        t.range = Mathf.Max(angleAndRange.y, 0.01F);\n                    }\n                    break;\n                case LightType.Rectangle:\n                    EditorGUI.BeginChangeCheck();\n                    Vector2 size = Handles.DoRectHandles(t.transform.rotation, t.transform.position, t.areaSize, false);\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        Undo.RecordObject(t, \"Adjust Rect Light\");\n                        t.areaSize = size;\n                    }\n                    // Draw the area light's normal only if it will not overlap with the current tool\n                    if (!((Tools.current == Tool.Move || Tools.current == Tool.Scale) && Tools.pivotRotation == PivotRotation.Local))\n                        Handles.DrawLine(t.transform.position, t.transform.position + t.transform.forward);\n                    break;\n                case LightType.Disc:\n                    m_BoundsHandle.radius = t.areaSize.x;\n                    m_BoundsHandle.axes = IMGUI.Controls.PrimitiveBoundsHandle.Axes.X | IMGUI.Controls.PrimitiveBoundsHandle.Axes.Y;\n                    m_BoundsHandle.center = Vector3.zero;\n                    m_BoundsHandle.wireframeColor = Handles.color;\n                    m_BoundsHandle.handleColor = GetLightHandleColor(Handles.color);\n                    Matrix4x4 mat = new Matrix4x4();\n                    mat.SetTRS(t.transform.position, t.transform.rotation, new Vector3(1, 1, 1));\n                    EditorGUI.BeginChangeCheck();\n                    using (new Handles.DrawingScope(Color.white, mat))\n                        m_BoundsHandle.DrawHandle();\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        Undo.RecordObject(t, \"Adjust Disc Light\");\n                        t.areaSize = new Vector2(m_BoundsHandle.radius, t.areaSize.y);\n                    }\n                    break;\n            }\n            Handles.color = temp;\n        }\n\n        private Color GetLightHandleColor(Color wireframeColor)\n        {\n            Color color = wireframeColor;\n            color.a = Mathf.Clamp01(color.a * 2);\n            return Handles.ToActiveColorSpace(color);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LightProbeGroupInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Xml.Serialization;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing System.Linq;\nusing UnityEditor.EditorTools;\nusing UnityEditor.Overlays;\nusing Object = UnityEngine.Object;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    internal class LightProbeGroupEditor : IEditablePoint\n    {\n        private bool m_Editing;\n\n        private List<Vector3> m_SourcePositions;\n        private List<int> m_Selection = new List<int>();\n\n        private LightProbeGroupSelection m_SerializedSelectedProbes;\n\n        private readonly LightProbeGroup m_Group;\n        private bool m_ShouldRecalculateTetrahedra;\n        private bool m_SourcePositionsDirty;\n        private Vector3 m_LastPosition = Vector3.zero;\n        private Quaternion m_LastRotation = Quaternion.identity;\n        private Vector3 m_LastScale = Vector3.one;\n\n        public SavedBool drawTetrahedra { get; set; }\n        public bool deringProbes { get { return m_Group.dering; } set { m_Group.dering = value; } }\n\n        public LightProbeGroupEditor(LightProbeGroup group)\n        {\n            m_Group = group;\n            m_ShouldRecalculateTetrahedra = true;\n            m_SourcePositionsDirty = true;\n            m_SerializedSelectedProbes = ScriptableObject.CreateInstance<LightProbeGroupSelection>();\n            m_SerializedSelectedProbes.hideFlags = HideFlags.HideAndDontSave;\n        }\n\n        public void SetEditing(bool editing)\n        {\n            m_Editing = editing;\n        }\n\n        public void AddProbe(Vector3 position)\n        {\n            Undo.RegisterCompleteObjectUndo(new Object[] { m_Group, m_SerializedSelectedProbes }, \"Add Probe\");\n            m_SourcePositions.Add(position);\n            SelectProbe(m_SourcePositions.Count - 1);\n\n            MarkSourcePositionsDirty();\n        }\n\n        private void SelectProbe(int i)\n        {\n            if (!m_Selection.Contains(i))\n                m_Selection.Add(i);\n        }\n\n        public void SelectAllProbes()\n        {\n            DeselectProbes();\n\n            var count = m_SourcePositions.Count;\n            for (var i = 0; i < count; i++)\n                m_Selection.Add(i);\n        }\n\n        public void DeselectProbes()\n        {\n            m_Selection.Clear();\n            m_SerializedSelectedProbes.m_Selection = m_Selection;\n        }\n\n        private IEnumerable<Vector3> SelectedProbePositions()\n        {\n            return m_Selection.Select(t => m_SourcePositions[t]).ToList();\n        }\n\n        public void DuplicateSelectedProbes()\n        {\n            var selectionCount = m_Selection.Count;\n            if (selectionCount == 0) return;\n\n            Undo.RegisterCompleteObjectUndo(new Object[] { m_Group, m_SerializedSelectedProbes }, \"Duplicate Probes\");\n\n            foreach (var position in SelectedProbePositions())\n            {\n                m_SourcePositions.Add(position);\n            }\n\n            MarkSourcePositionsDirty();\n        }\n\n        private void CopySelectedProbes()\n        {\n            //Convert probes to world position for serialization\n            var localPositions = SelectedProbePositions();\n\n            var serializer = new XmlSerializer(typeof(Vector3[]));\n            var writer = new StringWriter();\n\n            serializer.Serialize(writer, localPositions.Select(pos => m_Group.transform.TransformPoint(pos)).ToArray());\n            writer.Close();\n            GUIUtility.systemCopyBuffer = writer.ToString();\n        }\n\n        private static bool CanPasteProbes()\n        {\n            try\n            {\n                var deserializer = new XmlSerializer(typeof(Vector3[]));\n                var reader = new StringReader(GUIUtility.systemCopyBuffer);\n                deserializer.Deserialize(reader);\n                reader.Close();\n                return true;\n            }\n            catch\n            {\n                return false;\n            }\n        }\n\n        private bool PasteProbes()\n        {\n            //If we can't paste / paste buffer is bad do nothing\n            try\n            {\n                var deserializer = new XmlSerializer(typeof(Vector3[]));\n                var reader = new StringReader(GUIUtility.systemCopyBuffer);\n                var pastedProbes = (Vector3[])deserializer.Deserialize(reader);\n                reader.Close();\n\n                if (pastedProbes.Length == 0) return false;\n\n                Undo.RegisterCompleteObjectUndo(new Object[] { m_Group, m_SerializedSelectedProbes }, \"Paste Probes\");\n\n                var oldLength = m_SourcePositions.Count;\n\n                //Need to convert into local space...\n                foreach (var position in pastedProbes)\n                {\n                    m_SourcePositions.Add(m_Group.transform.InverseTransformPoint(position));\n                }\n\n                //Change selection to be the newly pasted probes\n                DeselectProbes();\n                for (int i = oldLength; i < oldLength + pastedProbes.Length; i++)\n                {\n                    SelectProbe(i);\n                }\n                MarkSourcePositionsDirty();\n\n                return true;\n            }\n            catch\n            {\n                return false;\n            }\n        }\n\n        public void RemoveSelectedProbes()\n        {\n            int selectionCount = m_Selection.Count;\n            if (selectionCount == 0)\n                return;\n\n            Undo.RegisterCompleteObjectUndo(new Object[] { m_Group, m_SerializedSelectedProbes }, \"Delete Probes\");\n\n            var reverseSortedIndicies = m_Selection.OrderByDescending(x => x);\n            foreach (var index in reverseSortedIndicies)\n            {\n                m_SourcePositions.RemoveAt(index);\n            }\n            DeselectProbes();\n            MarkSourcePositionsDirty();\n        }\n\n        public void PullProbePositions()\n        {\n            if (m_Group != null && m_SerializedSelectedProbes != null)\n            {\n                m_SourcePositions = new List<Vector3>(m_Group.probePositions);\n                m_Selection = new List<int>(m_SerializedSelectedProbes.m_Selection);\n            }\n        }\n\n        public void PushProbePositions()\n        {\n            if (m_SourcePositionsDirty)\n            {\n                m_Group.probePositions = m_SourcePositions.ToArray();\n                m_SourcePositionsDirty = false;\n            }\n\n            m_SerializedSelectedProbes.m_Selection = m_Selection;\n        }\n\n        private void DrawTetrahedra()\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            if (SceneView.lastActiveSceneView)\n            {\n                LightProbeVisualization.DrawTetrahedra(m_ShouldRecalculateTetrahedra,\n                    SceneView.lastActiveSceneView.camera.transform.position);\n                m_ShouldRecalculateTetrahedra = false;\n            }\n        }\n\n        public void HandleEditMenuHotKeyCommands()\n        {\n            //Handle other events!\n            if (Event.current.type == EventType.ValidateCommand\n                || Event.current.type == EventType.ExecuteCommand)\n            {\n                bool execute = Event.current.type == EventType.ExecuteCommand;\n                switch (Event.current.commandName)\n                {\n                    case EventCommandNames.SoftDelete:\n                    case EventCommandNames.Delete:\n                        if (execute) RemoveSelectedProbes();\n                        Event.current.Use();\n                        break;\n                    case EventCommandNames.Duplicate:\n                        if (execute) DuplicateSelectedProbes();\n                        Event.current.Use();\n                        break;\n                    case EventCommandNames.SelectAll:\n                        if (execute)\n                            SelectAllProbes();\n                        Event.current.Use();\n                        break;\n                    case EventCommandNames.Cut:\n                        if (execute)\n                        {\n                            CopySelectedProbes();\n                            RemoveSelectedProbes();\n                        }\n                        Event.current.Use();\n                        break;\n                    case EventCommandNames.Copy:\n                        if (execute) CopySelectedProbes();\n                        Event.current.Use();\n                        break;\n                }\n            }\n        }\n\n        public static void TetrahedralizeSceneProbes(out Vector3[] positions, out int[] indices)\n        {\n            var probeGroups = Object.FindObjectsByType<LightProbeGroup>(FindObjectsSortMode.None);\n\n            if (probeGroups == null)\n            {\n                positions = new Vector3[0];\n                indices = new int[0];\n                return;\n            }\n            var probePositions = new List<Vector3>();\n\n            foreach (var group in probeGroups)\n            {\n                var localPositions = group.probePositions;\n                foreach (var position in localPositions)\n                {\n                    var wPosition = group.transform.TransformPoint(position);\n                    probePositions.Add(wPosition);\n                }\n            }\n\n            if (probePositions.Count == 0)\n            {\n                positions = new Vector3[0];\n                indices = new int[0];\n                return;\n            }\n\n            Lightmapping.Tetrahedralize(probePositions.ToArray(), out indices, out positions);\n        }\n\n        public bool OnSceneGUI(Transform transform)\n        {\n            if (!m_Group.enabled || SupportedRenderingFeatures.active.overridesLightProbeSystem)\n                return m_Editing;\n\n            if (Event.current.type == EventType.Layout)\n            {\n                //If the group has moved / scaled since last frame need to retetra);)\n                if (m_LastPosition != m_Group.transform.position\n                    || m_LastRotation != m_Group.transform.rotation\n                    || m_LastScale != m_Group.transform.localScale)\n                {\n                    MarkSourcePositionsDirty();\n                }\n\n                m_LastPosition = m_Group.transform.position;\n                m_LastRotation = m_Group.transform.rotation;\n                m_LastScale = m_Group.transform.localScale;\n            }\n\n            //Need to cache this as select points will use it!\n            var mouseUpEvent = Event.current.type == EventType.MouseUp;\n\n            if (m_Editing)\n            {\n                if (PointEditor.SelectPoints(this, transform, ref m_Selection))\n                {\n                    Undo.RegisterCompleteObjectUndo(new Object[] { m_Group, m_SerializedSelectedProbes }, \"Select Probes\");\n                }\n            }\n\n            //Special handling for paste (want to be able to paste when not in edit mode!)\n\n            if ((Event.current.type == EventType.ValidateCommand || Event.current.type == EventType.ExecuteCommand)\n                && Event.current.commandName == EventCommandNames.Paste)\n            {\n                if (Event.current.type == EventType.ValidateCommand)\n                {\n                    if (CanPasteProbes())\n                        Event.current.Use();\n                }\n                if (Event.current.type == EventType.ExecuteCommand)\n                {\n                    if (PasteProbes())\n                    {\n                        Event.current.Use();\n                        m_Editing = true;\n                    }\n                }\n            }\n\n            if (drawTetrahedra)\n                DrawTetrahedra();\n\n            PointEditor.Draw(this, transform, m_Selection, true);\n\n            if (!m_Editing)\n                return m_Editing;\n\n            HandleEditMenuHotKeyCommands();\n\n            if (m_Editing && PointEditor.MovePoints(this, transform, m_Selection))\n            {\n                Undo.RegisterCompleteObjectUndo(new Object[] { m_Group, m_SerializedSelectedProbes }, \"Move Probes\");\n                if (LightProbeVisualization.dynamicUpdateLightProbes)\n                    MarkSourcePositionsDirty();\n            }\n\n            if (m_Editing && mouseUpEvent && !LightProbeVisualization.dynamicUpdateLightProbes)\n            {\n                MarkSourcePositionsDirty();\n            }\n\n            return m_Editing;\n        }\n\n        public void MarkSourcePositionsDirty()\n        {\n            m_ShouldRecalculateTetrahedra = true;\n            m_SourcePositionsDirty = true;\n        }\n\n        public Bounds selectedProbeBounds\n        {\n            get\n            {\n                List<Vector3> selectedPoints = new List<Vector3>();\n                foreach (var idx in m_Selection)\n                    selectedPoints.Add(m_SourcePositions[(int)idx]);\n                return GetBounds(selectedPoints);\n            }\n        }\n\n        public Bounds bounds\n        {\n            get { return GetBounds(m_SourcePositions); }\n        }\n\n        private Bounds GetBounds(List<Vector3> positions)\n        {\n            if (positions.Count == 0)\n                return new Bounds();\n\n            if (positions.Count == 1)\n                return new Bounds(m_Group.transform.TransformPoint(positions[0]), new Vector3(1f, 1f, 1f));\n\n            return GeometryUtility.CalculateBounds(positions.ToArray(), m_Group.transform.localToWorldMatrix);\n        }\n\n        /// Get the world-space position of a specific point\n        public Vector3 GetPosition(int idx)\n        {\n            return m_SourcePositions[idx];\n        }\n\n        public Vector3 GetWorldPosition(int idx)\n        {\n            return m_Group.transform.TransformPoint(m_SourcePositions[idx]);\n        }\n\n        public void SetPosition(int idx, Vector3 position)\n        {\n            if (m_SourcePositions[idx] == position)\n                return;\n\n            m_SourcePositions[idx] = position;\n            MarkSourcePositionsDirty();\n        }\n\n        private static readonly Color kCloudColor = new Color(200f / 255f, 200f / 255f, 20f / 255f, 0.85f);\n        private static readonly Color kSelectedCloudColor = new Color(.3f, .6f, 1, 1);\n\n        public Color GetDefaultColor()\n        {\n            return kCloudColor;\n        }\n\n        public Color GetSelectedColor()\n        {\n            return kSelectedCloudColor;\n        }\n\n        public float GetPointScale()\n        {\n            // Should match LightProbeVisualizationSettings::GetLightProbeSize()\n            return 10.0f * AnnotationUtility.iconSize;\n        }\n\n        public Vector3[] GetSelectedPositions()\n        {\n            var selectedCount = SelectedCount;\n            var result = new Vector3[selectedCount];\n            for (int i = 0; i < selectedCount; i++)\n            {\n                result[i] = m_SourcePositions[m_Selection[i]];\n            }\n            return result;\n        }\n\n        public void UpdateSelectedPosition(int idx, Vector3 position)\n        {\n            if (idx > (SelectedCount - 1))\n                return;\n\n            m_SourcePositions[m_Selection[idx]] = position;\n\n            MarkSourcePositionsDirty();\n        }\n\n        public IEnumerable<Vector3> GetPositions()\n        {\n            return m_SourcePositions;\n        }\n\n        public Vector3[] GetUnselectedPositions()\n        {\n            var totalProbeCount = Count;\n            var selectedProbeCount = SelectedCount;\n\n            if (selectedProbeCount == totalProbeCount)\n            {\n                return new Vector3[0];\n            }\n            else if (selectedProbeCount == 0)\n            {\n                return m_SourcePositions.ToArray();\n            }\n            else\n            {\n                var selectionList = new bool[totalProbeCount];\n\n                // Mark everything unselected\n                for (int i = 0; i < totalProbeCount; i++)\n                {\n                    selectionList[i] = false;\n                }\n\n                // Mark selected\n                for (int i = 0; i < selectedProbeCount; i++)\n                {\n                    selectionList[m_Selection[i]] = true;\n                }\n\n                // Get remaining unselected\n                var result = new Vector3[totalProbeCount - selectedProbeCount];\n                var unselectedCount = 0;\n                for (int i = 0; i < totalProbeCount; i++)\n                {\n                    if (selectionList[i] == false)\n                    {\n                        result[unselectedCount++] = m_SourcePositions[i];\n                    }\n                }\n\n                return result;\n            }\n        }\n\n        /// How many points are there in the array.\n        public int Count { get { return m_SourcePositions.Count; } }\n\n        /// How many points are selected in the array.\n        public int SelectedCount { get { return m_Selection.Count; } }\n    }\n\n    class LightProbeGroupOverlay : TransientSceneViewOverlay\n    {\n        LightProbeGroup m_Target;\n        LightProbeGroupEditor m_Editor;\n\n        internal static class Styles\n        {\n            public static readonly GUIContent showWireframe = EditorGUIUtility.TrTextContent(\"Show Wireframe\", \"Show the tetrahedron wireframe visualizing the blending between probes.\");\n            public static readonly GUIContent selectedProbePosition = EditorGUIUtility.TrTextContent(\"Selected Probe Position\", \"The local position of this probe relative to the parent group.\");\n            public static readonly GUIContent addProbe = EditorGUIUtility.TrTextContent(\"Add Probe\", \"Add a Light Probe to the Light Probe Group.\");\n            public static readonly GUIContent deleteSelected = EditorGUIUtility.TrTextContent(\"Delete Selected\", \"Delete the selected Light Probes from the Light Probe Group.\");\n            public static readonly GUIContent selectAll = EditorGUIUtility.TrTextContent(\"Select All\", \"Select all Light Probes in the Light Probe Group.\");\n            public static readonly GUIContent duplicateSelected = EditorGUIUtility.TrTextContent(\"Duplicate Selected\", \"Duplicate the selected Light Probes.\");\n            public static readonly GUIContent performDeringing = EditorGUIUtility.TrTextContent(\"Remove Ringing\", \"When enabled, removes visible overshooting often observed as ringing on objects affected by intense lighting at the expense of reduced contrast.\");\n            public static readonly GUIContent enterEditMode = EditorGUIUtility.TrTextContent(\"Edit Light Probe Positions\", \"Change positions for Light Probes.\");\n            public static readonly GUIContent exitEditMode = EditorGUIUtility.TrTextContent(\"Exit Light Probe Editing\", \"Exit Light Probe Positions Editing.\");\n            public static readonly GUIContent toolIcon = EditorGUIUtility.TrIconContent(\"EditCollider\", \"Edit Light Probe Group.\\n\\nUse the overlay to add Light Probes and modify probe positions.\");\n            public static readonly GUIContent editModeInfoBox = EditorGUIUtility.TrTextContentWithIcon(\"Use the <b>Edit Light Probe Group Tool</b> in the <b>Scene Tools Overlay</b> to edit Light Probe positions.\", MessageType.Info);\n            // This is a property due to [UUM-78837](https://jira.unity3d.com/browse/UUM-78837)\n            // Create GUIStyle lazily on request rather than on static class initialization where the EditorStyles.helpBox may not be initialized yet.\n            public static GUIStyle editModeInfoBoxStyle \n            {\n                get\n                {\n                    if (s_EditModeInfoBoxStyle == null)\n                        s_EditModeInfoBoxStyle = new GUIStyle(EditorStyles.helpBox) { richText = true };\n                    return s_EditModeInfoBoxStyle;\n                }\n            }\n\n            static GUIStyle s_EditModeInfoBoxStyle;\n        }\n\n        public LightProbeGroupOverlay(LightProbeGroup target, LightProbeGroupEditor editor)\n        {\n            m_Target = target;\n            m_Editor = editor;\n\n            displayName = \"Edit Light Probes\";\n            collapsedIcon = EditorGUIUtility.LoadIcon(\"EditCollider\");\n\n            displayedChanged += value => m_Visible = value;\n        }\n\n        public override void OnGUI()\n        {\n            EditorGUI.BeginChangeCheck();\n\n            m_Editor.PullProbePositions();\n            m_Editor.drawTetrahedra.value = GUILayout.Toggle(m_Editor.drawTetrahedra.value, Styles.showWireframe, EditorStyles.toggle);\n\n            EditorGUI.BeginChangeCheck();\n            Vector3 pos = m_Editor.SelectedCount > 0 ? m_Editor.GetSelectedPositions()[0] : Vector3.zero;\n            Vector3 newPosition = EditorGUILayout.Vector3Field(Styles.selectedProbePosition, pos);\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                Vector3[] selectedPositions = m_Editor.GetSelectedPositions();\n                Vector3 delta = CalculateDeltaAndClamp(newPosition, pos);\n                for (int i = 0; i < selectedPositions.Length; i++)\n                    m_Editor.UpdateSelectedPosition(i, selectedPositions[i] + delta);\n            }\n\n            GUILayout.Space(3);\n\n            GUILayoutOption minButtonWidth = GUILayout.MinWidth(130);\n            GUILayout.BeginHorizontal();\n            {\n                GUILayout.BeginVertical();\n                if (GUILayout.Button(Styles.addProbe, minButtonWidth))\n                {\n                    var position = Vector3.zero;\n                    if (SceneView.lastActiveSceneView)\n                        position = m_Target.transform.InverseTransformPoint(position);\n\n                    m_Editor.DeselectProbes();\n                    m_Editor.AddProbe(position);\n                }\n\n                if (GUILayout.Button(Styles.deleteSelected, minButtonWidth))\n                    m_Editor.RemoveSelectedProbes();\n\n                GUILayout.EndVertical();\n            }\n            GUILayout.BeginVertical();\n            {\n                if (GUILayout.Button(Styles.selectAll, minButtonWidth))\n                    m_Editor.SelectAllProbes();\n\n                if (GUILayout.Button(Styles.duplicateSelected, minButtonWidth))\n                    m_Editor.DuplicateSelectedProbes();\n\n                GUILayout.EndVertical();\n            }\n            GUILayout.EndHorizontal();\n\n            m_Editor.HandleEditMenuHotKeyCommands();\n            m_Editor.PushProbePositions();\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_Editor.MarkSourcePositionsDirty();\n                SceneView.RepaintAll();\n            }\n        }\n\n        Vector3 CalculateDeltaAndClamp(Vector3 vec1, Vector3 vec2)\n        {\n            if (float.IsInfinity(vec1.x) || float.IsNaN(vec1.x))\n                vec1.x = 0;\n\n            if (float.IsInfinity(vec1.y) || float.IsNaN(vec1.y))\n                vec1.y = 0;\n\n            if (float.IsInfinity(vec1.z) || float.IsNaN(vec1.z))\n                vec1.z = 0;\n\n            vec1.x = Mathf.Clamp(vec1.x, float.MinValue, float.MaxValue);\n            vec1.y = Mathf.Clamp(vec1.y, float.MinValue, float.MaxValue);\n            vec1.z = Mathf.Clamp(vec1.z, float.MinValue, float.MaxValue);\n\n            return vec1 - vec2;\n        }\n\n        public override bool visible => m_Visible;\n        private bool m_Visible = true;\n    }\n\n    [EditorTool(\"Light Probe Group\", typeof(LightProbeGroup))]\n    class LightProbeGroupTool : EditorTool, IDrawSelectedHandles\n    {\n        LightProbeGroup m_LightProbeGroup;\n        LightProbeGroupEditor m_Editor;\n        LightProbeGroupOverlay m_Overlay;\n\n        void OnEnable()\n        {\n            m_LightProbeGroup = (LightProbeGroup) target;\n            if (m_LightProbeGroup == null)\n                return;\n\n            m_Editor = new LightProbeGroupEditor(m_LightProbeGroup);\n            m_Editor.PullProbePositions();\n            m_Editor.DeselectProbes();\n            m_Editor.PushProbePositions();\n            m_Editor.drawTetrahedra = new SavedBool($\"{target.GetType()}.drawTetrahedra\", true);\n            Undo.undoRedoEvent += UndoRedoPerformed;\n        }\n\n        void OnDisable()\n        {\n            Undo.undoRedoEvent -= UndoRedoPerformed;\n        }\n\n        void UndoRedoPerformed(in UndoRedoInfo info)\n        {\n            // Update the cached probe positions from the ones just restored in the LightProbeGroup\n            m_Editor.PullProbePositions();\n            m_Editor.MarkSourcePositionsDirty();\n            SceneView.RepaintAll();\n        }\n\n        public override void OnActivated()\n        {\n            m_Editor.SetEditing(true);\n            SceneView.AddOverlayToActiveView(m_Overlay = new LightProbeGroupOverlay(m_LightProbeGroup, m_Editor));\n            SceneView.RepaintAll();\n        }\n\n        public override void OnWillBeDeactivated()\n        {\n            m_Editor.DeselectProbes();\n            m_Editor.SetEditing(false);\n            m_Editor.PushProbePositions();\n            SceneView.RemoveOverlayFromActiveView(m_Overlay);\n            SceneView.RepaintAll();\n        }\n\n        public void OnDrawHandles()\n        {\n            m_Editor.PullProbePositions();\n            if (m_Editor.OnSceneGUI(m_LightProbeGroup.transform))\n            {\n                m_Editor.PushProbePositions();\n\n                // OnSceneGUI can cause us to enter edit mode, for example when pasting probes.\n                // In these cases, we must set the active EditorTool to reflect that change.\n                if (!ToolManager.IsActiveTool(this))\n                    EditorToolManager.activeTool = this;\n            }\n        }\n\n        public override bool IsAvailable() => !SupportedRenderingFeatures.active.overridesLightProbeSystem;\n\n        public override GUIContent toolbarIcon => LightProbeGroupOverlay.Styles.toolIcon;\n    }\n\n    [CustomEditor(typeof(LightProbeGroup))]\n    class LightProbeGroupInspector : Editor\n    {\n        SerializedProperty dering;\n\n        public void OnEnable()\n        {\n            if (serializedObject == null)\n                return;\n            dering = serializedObject.FindProperty(\"m_Dering\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            bool srpHasAlternativeToLegacyProbes = SupportedRenderingFeatures.active.overridesLightProbeSystem;\n            using (new EditorGUI.DisabledScope(srpHasAlternativeToLegacyProbes))\n            {\n                serializedObject.Update();\n                EditorGUILayout.PropertyField(dering, LightProbeGroupOverlay.Styles.performDeringing);\n                serializedObject.ApplyModifiedProperties();\n            }\n\n            if (srpHasAlternativeToLegacyProbes)\n            {\n                EditorGUILayout.HelpBox(SupportedRenderingFeatures.active.overridesLightProbeSystemWarningMessage, MessageType.Warning, true);\n            }\n            else\n            {\n                EditorGUILayout.LabelField(GUIContent.none, LightProbeGroupOverlay.Styles.editModeInfoBox, LightProbeGroupOverlay.Styles.editModeInfoBoxStyle);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LightProbeProxyVolumeEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEditor.AnimatedValues;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(LightProbeProxyVolume))]\n    [CanEditMultipleObjects]\n    internal class LightProbeProxyVolumeEditor : Editor\n    {\n        static LightProbeProxyVolumeEditor s_LastInteractedEditor;\n\n        private SerializedProperty m_ResolutionX;\n        private SerializedProperty m_ResolutionY;\n        private SerializedProperty m_ResolutionZ;\n        private SerializedProperty m_BoundingBoxSize;\n        private SerializedProperty m_BoundingBoxOrigin;\n        private SerializedProperty m_BoundingBoxMode;\n        private SerializedProperty m_ResolutionMode;\n        private SerializedProperty m_ResolutionProbesPerUnit;\n        private SerializedProperty m_ProbePositionMode;\n        private SerializedProperty m_RefreshMode;\n        private SerializedProperty m_QualityMode;\n        private SerializedProperty m_DataFormat;\n\n        // Should match gizmo color in GizmoDrawers.cpp!\n        internal static Color kGizmoLightProbeProxyVolumeColor = new Color(0xFF / 255f, 0xE5 / 255f, 0x94 / 255f, 0x80 / 255f);\n        internal static Color kGizmoLightProbeProxyVolumeHandleColor = new Color(0xFF / 255f, 0xE5 / 255f, 0xAA / 255f, 0xFF / 255f);\n\n        private BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle();\n\n        private static class Styles\n        {\n            static Styles()\n            {\n                richTextMiniLabel.richText = true;\n            }\n\n            public static GUIStyle richTextMiniLabel = new GUIStyle(EditorStyles.miniLabel);\n            public static GUIContent volumeResolutionText = EditorGUIUtility.TrTextContent(\"Proxy Volume Resolution\", \"Specifies the resolution of the 3D grid of interpolated light probes. Higher resolution/density means better lighting, but the CPU cost will increase.\");\n            public static GUIContent resolutionXText = EditorGUIUtility.TrTextContent(\"X\", \"The 3D grid resolution on the X axis.\");\n            public static GUIContent resolutionYText = EditorGUIUtility.TrTextContent(\"Y\", \"The 3D grid resolution on the Y axis.\");\n            public static GUIContent resolutionZText = EditorGUIUtility.TrTextContent(\"Z\", \"The 3D grid resolution on the Z axis.\");\n            public static GUIContent sizeText = EditorGUIUtility.TrTextContent(\"Size\", \"The size of the Bounding Box relative to the Game Object.\");\n            public static GUIContent bbSettingsText = EditorGUIUtility.TrTextContent(\"Bounding Box Settings\");\n            public static GUIContent originText = EditorGUIUtility.TrTextContent(\"Origin\", \"The origin of the Bounding Box relative to the Game Object.\");\n            public static GUIContent bbModeText = EditorGUIUtility.TrTextContent(\"Bounding Box Mode\", \"The mode in which the bounding box is computed. A 3D grid of interpolated light probes will be generated inside this bounding box.\\n\\nAutomatic Local - the local-space bounding box of the Renderer is used.\\n\\nAutomatic Global - a bounding box is computed which encloses the current Renderer and all the Renderers down the hierarchy that have the Light Probes property set to Use Proxy Volume. The bounding box will be world-space aligned.\\n\\nCustom - a custom bounding box is used. The bounding box is specified in the local-space of the game object.\");\n            public static GUIContent resModeText = EditorGUIUtility.TrTextContent(\"Resolution Mode\", \"The mode in which the resolution of the 3D grid of interpolated light probes is specified:\\n\\nAutomatic - the resolution on each axis is computed using a user-specified number of interpolated light probes per unit area (Density).\\n\\nCustom - the user can specify a different resolution on each axis.\");\n            public static GUIContent probePositionText = EditorGUIUtility.TrTextContent(\"Probe Position Mode\", \"The mode in which the interpolated probe positions are generated.\\n\\nCellCorner - divide the volume in cells and generate interpolated probe positions in the corner/edge of the cells.\\n\\nCellCenter - divide the volume in cells and generate interpolated probe positions in the center of the cells.\");\n            public static GUIContent refreshModeText = EditorGUIUtility.TrTextContent(\"Refresh Mode\", \"An enum describing the way a Light Probe Proxy Volume refreshes in the Player.\");\n            public static GUIContent qualityText = EditorGUIUtility.TrTextContent(\"Quality\", \"Affects the total number of evaluated Spherical Harmonics(SH) bands for Renderers that use a Light Probe Proxy Volume:\\n\\nLow Quality - uses only 2 bands (L0 and L1) sampled from a LPPV texture. This option might improve the performance by not breaking batching.\\n\\nNormal Quality - uses all the bands to evaluate the SH. L0 and L1 are sampled from a LPPV texture and L2 is constant per Renderer.\");\n            public static GUIContent dataFormatText = EditorGUIUtility.TrTextContent(\"Data Format\", \"Affects the format of the LPPV texture.\");\n            public static GUIContent[] bbMode = (Enum.GetNames(typeof(LightProbeProxyVolume.BoundingBoxMode)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray()).Select(x => new GUIContent(x)).ToArray();\n            public static GUIContent[] resMode = (Enum.GetNames(typeof(LightProbeProxyVolume.ResolutionMode)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray()).Select(x => new GUIContent(x)).ToArray();\n            public static GUIContent[] probePositionMode = (Enum.GetNames(typeof(LightProbeProxyVolume.ProbePositionMode)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray()).Select(x => new GUIContent(x)).ToArray();\n            public static GUIContent[] refreshMode = (Enum.GetNames(typeof(LightProbeProxyVolume.RefreshMode)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray()).Select(x => new GUIContent(x)).ToArray();\n            public static GUIContent[] qualityMode = (Enum.GetNames(typeof(LightProbeProxyVolume.QualityMode)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray()).Select(x => new GUIContent(x)).ToArray();\n            public static GUIContent[] dataFormat = (Enum.GetNames(typeof(LightProbeProxyVolume.DataFormat)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray()).Select(x => new GUIContent(x)).ToArray();\n            public static GUIContent resProbesPerUnit = EditorGUIUtility.TrTextContent(\"Density\", \"Density in probes per world unit.\");\n            public static GUIContent componentUnusedNote = EditorGUIUtility.TrTextContent(\"In order to use the component on this game object, the Light Probes property should be set to 'Use Proxy Volume' in Renderer.\");\n            public static GUIContent noRendererNode = EditorGUIUtility.TrTextContent(\"The component is unused by this game object because there is no Renderer component attached.\");\n            public static GUIContent noLightProbes = EditorGUIUtility.TrTextContent(\"The scene doesn't contain any light probes. Add light probes using Light Probe Group components (menu: Component->Rendering->Light Probe Group).\");\n            public static GUIContent componentUnsuportedOnTreesNote = EditorGUIUtility.TrTextContent(\"Tree rendering doesn't support Light Probe Proxy Volume components.\");\n\n            public static int[] volTextureSizesValues = { 1, 2, 4, 8, 16, 32 };\n            public static GUIContent[] volTextureSizes = volTextureSizesValues.Select(n => new GUIContent(n.ToString())).ToArray();\n\n            public static GUIContent[] toolContents =\n            {\n                PrimitiveBoundsHandle.editModeButton,\n                EditorGUIUtility.TrIconContent(\"MoveTool\", \"Move the selected objects.\")\n            };\n            public static EditMode.SceneViewEditMode[] sceneViewEditModes = new[]\n            {\n                EditMode.SceneViewEditMode.LightProbeProxyVolumeBox,\n                EditMode.SceneViewEditMode.LightProbeProxyVolumeOrigin\n            };\n\n            public static string baseSceneEditingToolText = \"<color=grey>Light Probe Proxy Volume Scene Editing Mode:</color> \";\n            public static GUIContent[] toolNames =\n            {\n                new GUIContent(baseSceneEditingToolText + \"Box Bounds\", \"\"),\n                new GUIContent(baseSceneEditingToolText + \"Box Origin\", \"\")\n            };\n        }\n\n        private static bool IsLightProbeVolumeProxyEditMode(EditMode.SceneViewEditMode editMode)\n        {\n            return editMode == EditMode.SceneViewEditMode.LightProbeProxyVolumeBox ||\n                editMode == EditMode.SceneViewEditMode.LightProbeProxyVolumeOrigin;\n        }\n\n        private bool sceneViewEditing\n        {\n            get { return IsLightProbeVolumeProxyEditMode(EditMode.editMode) && EditMode.IsOwner(this); }\n        }\n\n        private AnimBool m_ShowBoundingBoxOptions = new AnimBool();\n        private AnimBool m_ShowComponentUnusedWarning = new AnimBool();\n        private AnimBool m_ShowResolutionXYZOptions = new AnimBool();\n        private AnimBool m_ShowResolutionProbesOption = new AnimBool();\n        private AnimBool m_ShowNoRendererWarning = new AnimBool();\n        private AnimBool m_ShowNoLightProbesWarning = new AnimBool();\n\n        private bool boundingBoxOptionsValue        { get { return (!m_BoundingBoxMode.hasMultipleDifferentValues) && (m_BoundingBoxMode.intValue == (int)LightProbeProxyVolume.BoundingBoxMode.Custom); } }\n        private bool resolutionXYZOptionValue       { get { return (!m_ResolutionMode.hasMultipleDifferentValues) && (m_ResolutionMode.intValue == (int)LightProbeProxyVolume.ResolutionMode.Custom); } }\n        private bool resolutionProbesOptionValue    { get { return (!m_ResolutionMode.hasMultipleDifferentValues) && (m_ResolutionMode.intValue == (int)LightProbeProxyVolume.ResolutionMode.Automatic); } }\n        private bool noLightProbesWarningValue      { get { return (LightmapSettings.lightProbes == null) || (LightmapSettings.lightProbes.count == 0); } }\n        private bool componentUnusedWarningValue\n        {\n            get\n            {\n                Renderer renderer = ((LightProbeProxyVolume)target).GetComponent(typeof(Renderer)) as Renderer;\n                bool useLightProbes = (renderer != null) && LightProbes.AreLightProbesAllowed(renderer);\n                return (renderer != null) && (targets.Length == 1) && ((renderer.lightProbeUsage != LightProbeUsage.UseProxyVolume) || !useLightProbes);\n            }\n        }\n\n        private bool noRendererWarningValue\n        {\n            get\n            {\n                var proxyVolume = (LightProbeProxyVolume)target;\n                Renderer renderer = proxyVolume.GetComponent(typeof(Renderer)) as Renderer;\n                return (renderer == null && proxyVolume.boundingBoxMode != LightProbeProxyVolume.BoundingBoxMode.Custom) && (targets.Length == 1);\n            }\n        }\n\n        private void SetOptions(AnimBool animBool, bool initialize, bool targetValue)\n        {\n            if (initialize)\n            {\n                animBool.value = targetValue;\n                animBool.valueChanged.AddListener(Repaint);\n            }\n            else\n            {\n                animBool.target = targetValue;\n            }\n        }\n\n        private void UpdateShowOptions(bool initialize)\n        {\n            SetOptions(m_ShowBoundingBoxOptions, initialize, boundingBoxOptionsValue);\n            SetOptions(m_ShowComponentUnusedWarning, initialize, componentUnusedWarningValue);\n            SetOptions(m_ShowResolutionXYZOptions, initialize, resolutionXYZOptionValue);\n            SetOptions(m_ShowResolutionProbesOption, initialize, resolutionProbesOptionValue);\n            SetOptions(m_ShowNoRendererWarning, initialize, noRendererWarningValue);\n            SetOptions(m_ShowNoLightProbesWarning, initialize, noLightProbesWarningValue);\n        }\n\n        public void OnEnable()\n        {\n            m_ResolutionX = serializedObject.FindProperty(\"m_ResolutionX\");\n            m_ResolutionY = serializedObject.FindProperty(\"m_ResolutionY\");\n            m_ResolutionZ = serializedObject.FindProperty(\"m_ResolutionZ\");\n            m_BoundingBoxSize = serializedObject.FindProperty(\"m_BoundingBoxSize\");\n            m_BoundingBoxOrigin = serializedObject.FindProperty(\"m_BoundingBoxOrigin\");\n            m_BoundingBoxMode = serializedObject.FindProperty(\"m_BoundingBoxMode\");\n            m_ResolutionMode = serializedObject.FindProperty(\"m_ResolutionMode\");\n            m_ResolutionProbesPerUnit = serializedObject.FindProperty(\"m_ResolutionProbesPerUnit\");\n            m_ProbePositionMode = serializedObject.FindProperty(\"m_ProbePositionMode\");\n            m_RefreshMode = serializedObject.FindProperty(\"m_RefreshMode\");\n            m_QualityMode = serializedObject.FindProperty(\"m_QualityMode\");\n            m_DataFormat = serializedObject.FindProperty(\"m_DataFormat\");\n            m_BoundsHandle.handleColor = kGizmoLightProbeProxyVolumeHandleColor;\n            m_BoundsHandle.wireframeColor = Color.clear;\n\n            UpdateShowOptions(true);\n        }\n\n        internal override Bounds GetWorldBoundsOfTarget(UnityEngine.Object targetObject)\n        {\n            return ((LightProbeProxyVolume)target).boundsGlobal;\n        }\n\n        void DoToolbar()\n        {\n            using (new EditorGUI.DisabledScope(m_BoundingBoxMode.intValue != (int)LightProbeProxyVolume.BoundingBoxMode.Custom))\n            {\n                GUILayout.BeginHorizontal();\n                GUILayout.FlexibleSpace();\n                var oldEditMode = EditMode.editMode;\n\n                EditorGUI.BeginChangeCheck();\n                EditMode.DoInspectorToolbar(Styles.sceneViewEditModes, Styles.toolContents, this);\n                if (EditorGUI.EndChangeCheck())\n                    s_LastInteractedEditor = this;\n\n                if (oldEditMode != EditMode.editMode)\n                {\n                    if (Toolbar.get != null)\n                        Toolbar.get.Repaint();\n                }\n\n                GUILayout.FlexibleSpace();\n                GUILayout.EndHorizontal();\n\n                // Info box for tools\n                GUILayout.BeginVertical(EditorStyles.helpBox);\n                string helpText = Styles.baseSceneEditingToolText;\n                if (sceneViewEditing)\n                {\n                    int index = ArrayUtility.IndexOf(Styles.sceneViewEditModes, EditMode.editMode);\n                    if (index >= 0)\n                        helpText = Styles.toolNames[index].text;\n                }\n                GUILayout.Label(helpText, Styles.richTextMiniLabel);\n                GUILayout.EndVertical();\n                EditorGUILayout.Space();\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            UpdateShowOptions(false);\n\n            var tree = ((LightProbeProxyVolume)target).GetComponent<Tree>();\n            if (tree != null)\n            {\n                EditorGUILayout.HelpBox(Styles.componentUnsuportedOnTreesNote.text, MessageType.Info);\n                return;\n            }\n\n            EditorGUILayout.Space();\n\n            EditorGUILayout.Popup(m_RefreshMode, Styles.refreshMode,  Styles.refreshModeText);\n\n            EditorGUILayout.Popup(m_QualityMode, Styles.qualityMode, Styles.qualityText);\n\n            EditorGUILayout.Popup(m_DataFormat, Styles.dataFormat, Styles.dataFormatText);\n\n            EditorGUILayout.Popup(m_BoundingBoxMode, Styles.bbMode, Styles.bbModeText);\n\n            if (EditorGUILayout.BeginFadeGroup(m_ShowBoundingBoxOptions.faded))\n            {\n                if (targets.Length == 1)\n                    DoToolbar();\n\n                GUILayout.Label(Styles.bbSettingsText);\n\n                EditorGUI.indentLevel++;\n\n                EditorGUILayout.PropertyField(m_BoundingBoxSize, Styles.sizeText);\n                EditorGUILayout.PropertyField(m_BoundingBoxOrigin, Styles.originText);\n\n                EditorGUI.indentLevel--;\n            }\n            EditorGUILayout.EndFadeGroup();\n\n            EditorGUILayout.Space();\n\n            GUILayout.Label(Styles.volumeResolutionText);\n\n            EditorGUI.indentLevel++;\n            {\n                EditorGUILayout.Popup(m_ResolutionMode, Styles.resMode, Styles.resModeText);\n\n                if (EditorGUILayout.BeginFadeGroup(m_ShowResolutionXYZOptions.faded))\n                {\n                    EditorGUILayout.IntPopup(m_ResolutionX, Styles.volTextureSizes, Styles.volTextureSizesValues, Styles.resolutionXText, GUILayout.MinWidth(40));\n                    EditorGUILayout.IntPopup(m_ResolutionY, Styles.volTextureSizes, Styles.volTextureSizesValues, Styles.resolutionYText, GUILayout.MinWidth(40));\n                    EditorGUILayout.IntPopup(m_ResolutionZ, Styles.volTextureSizes, Styles.volTextureSizesValues, Styles.resolutionZText, GUILayout.MinWidth(40));\n                }\n                EditorGUILayout.EndFadeGroup();\n\n                if (EditorGUILayout.BeginFadeGroup(m_ShowResolutionProbesOption.faded))\n                {\n                    GUILayout.BeginHorizontal();\n                    EditorGUILayout.PropertyField(m_ResolutionProbesPerUnit, Styles.resProbesPerUnit);\n                    GUILayout.Label(\" probes per unit\", EditorStyles.wordWrappedMiniLabel);\n                    GUILayout.EndHorizontal();\n                }\n                EditorGUILayout.EndFadeGroup();\n            }\n\n            EditorGUI.indentLevel--;\n\n            EditorGUILayout.Space();\n\n            EditorGUILayout.Popup(m_ProbePositionMode, Styles.probePositionMode, Styles.probePositionText);\n\n            if (EditorGUILayout.BeginFadeGroup(m_ShowComponentUnusedWarning.faded) && LightProbeProxyVolume.isFeatureSupported)\n            {\n                EditorGUILayout.HelpBox(Styles.componentUnusedNote.text, MessageType.Warning);\n            }\n            EditorGUILayout.EndFadeGroup();\n\n            if (EditorGUILayout.BeginFadeGroup(m_ShowNoRendererWarning.faded))\n            {\n                EditorGUILayout.HelpBox(Styles.noRendererNode.text, MessageType.Info);\n            }\n            EditorGUILayout.EndFadeGroup();\n\n            if (EditorGUILayout.BeginFadeGroup(m_ShowNoLightProbesWarning.faded))\n            {\n                EditorGUILayout.HelpBox(Styles.noLightProbes.text, MessageType.Info);\n            }\n            EditorGUILayout.EndFadeGroup();\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        [DrawGizmo(GizmoType.Active)]\n        static void RenderBoxGizmo(LightProbeProxyVolume probeProxyVolume, GizmoType gizmoType)\n        {\n            if (s_LastInteractedEditor == null)\n                return;\n\n            if (s_LastInteractedEditor.sceneViewEditing && EditMode.editMode == EditMode.SceneViewEditMode.LightProbeProxyVolumeBox)\n            {\n                Color oldColor = Gizmos.color;\n                Gizmos.color = kGizmoLightProbeProxyVolumeColor;\n                Vector3 position = probeProxyVolume.originCustom;\n                Matrix4x4 oldMatrix = Gizmos.matrix;\n\n                Gizmos.matrix = probeProxyVolume.transform.localToWorldMatrix;\n                Gizmos.DrawCube(position, -1f * probeProxyVolume.sizeCustom);\n\n                Gizmos.matrix = oldMatrix;\n                Gizmos.color = oldColor;\n            }\n        }\n\n        public static bool IsSceneGUIEnabled()\n        {\n            return IsLightProbeVolumeProxyEditMode(EditMode.editMode);\n        }\n\n        public void OnSceneGUI()\n        {\n            if (!sceneViewEditing)\n                return;\n\n            if (m_BoundingBoxMode.intValue != (int)LightProbeProxyVolume.BoundingBoxMode.Custom)\n                EditMode.QuitEditMode();\n\n            switch (EditMode.editMode)\n            {\n                case EditMode.SceneViewEditMode.LightProbeProxyVolumeBox:\n                    DoBoxEditing();\n                    break;\n                case EditMode.SceneViewEditMode.LightProbeProxyVolumeOrigin:\n                    DoOriginEditing();\n                    break;\n            }\n        }\n\n        void DoOriginEditing()\n        {\n            LightProbeProxyVolume proxyVolume = (LightProbeProxyVolume)target;\n\n            Vector3 handlePosition = proxyVolume.transform.TransformPoint(proxyVolume.originCustom);\n\n            EditorGUI.BeginChangeCheck();\n\n            Vector3 newPostion = Handles.PositionHandle(handlePosition, proxyVolume.transform.rotation);\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                Undo.RecordObject(proxyVolume, \"Modified Light Probe Proxy Volume Box Origin\");\n                proxyVolume.originCustom = proxyVolume.transform.InverseTransformPoint(newPostion);\n                EditorUtility.SetDirty(target);\n            }\n        }\n\n        void DoBoxEditing()\n        {\n            // Drawing of the probe box is done from GizmoDrawers.cpp,\n            // here we only want to show the box editing handles when needed.\n            LightProbeProxyVolume proxyVolume = (LightProbeProxyVolume)target;\n\n            using (new Handles.DrawingScope(proxyVolume.transform.localToWorldMatrix))\n            {\n                m_BoundsHandle.center = proxyVolume.originCustom;\n                m_BoundsHandle.size = proxyVolume.sizeCustom;\n\n                EditorGUI.BeginChangeCheck();\n                m_BoundsHandle.DrawHandle();\n                if (EditorGUI.EndChangeCheck())\n                {\n                    Undo.RecordObject(proxyVolume, \"Modified Light Probe Proxy Volume AABB\");\n                    proxyVolume.originCustom = m_BoundsHandle.center;\n                    proxyVolume.sizeCustom = m_BoundsHandle.size;\n                    EditorUtility.SetDirty(target);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LightProbesInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(LightProbes))]\n    class LightProbesInspector : Editor\n    {\n        public override void OnInspectorGUI()\n        {\n            GUILayout.BeginVertical(EditorStyles.helpBox);\n            var lp = target as LightProbes;\n            GUIStyle labelStyle = EditorStyles.wordWrappedMiniLabel;\n            GUILayout.Label(\"Light probe count: \" + lp.count, labelStyle);\n            GUILayout.Label(\"Cell count: \" + lp.cellCount, labelStyle);\n            GUILayout.EndVertical();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LightingSettingsEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEngine.Rendering;\nusing UnityEngine;\nusing UnityEngineInternal;\nusing Object = UnityEngine.Object;\nusing System.Runtime.InteropServices;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(LightingSettings))]\n    [CanEditMultipleObjects]\n    internal class LightingSettingsEditor : Editor\n    {\n        SharedLightingSettingsEditor m_Editor;\n\n        public void OnEnable()\n        {\n            m_Editor = new SharedLightingSettingsEditor();\n            m_Editor.OnEnable();\n            m_Editor.UpdateSettings(serializedObject);\n            m_Editor.ClampMaxRanges();\n        }\n\n        internal override void OnHeaderControlsGUI()\n        {\n            GUILayoutUtility.GetRect(10, 10, 16, 16, EditorStyles.layerMaskField);\n            GUILayout.FlexibleSpace();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            m_Editor.OnGUI(true, true);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        private void OnFocus()\n        {\n            m_Editor.ClampMaxRanges();\n        }\n    }\n\n    internal class SharedLightingSettingsEditor\n    {\n        SavedBool m_ShowRealtimeLightsSettings;\n        SavedBool m_ShowMixedLightsSettings;\n        SavedBool m_ShowGeneralLightingSettings;\n        SavedBool m_ShowInternalSettings;\n\n        //realtime GI\n        SerializedProperty m_EnableRealtimeGI;\n        SerializedProperty m_RealtimeResolution;\n        SerializedProperty m_RealtimeEnvironmentLighting;\n\n        //baked\n        SerializedProperty m_EnabledBakedGI;\n        SerializedProperty m_MixedBakeMode;\n        SerializedProperty m_AlbedoBoost;\n        SerializedProperty m_IndirectOutputScale;\n        SerializedProperty m_LightmapParameters;\n        SerializedProperty m_LightmapDirectionalMode;\n        SerializedProperty m_BakeResolution;\n        SerializedProperty m_Padding;\n        SerializedProperty m_AmbientOcclusion;\n        SerializedProperty m_AOMaxDistance;\n        SerializedProperty m_CompAOExponent;\n        SerializedProperty m_CompAOExponentDirect;\n        SerializedProperty m_LightmapCompression;\n        SerializedProperty m_LightmapMaxSize;\n        SerializedProperty m_LightmapSizeFixed;\n        SerializedProperty m_UseMipmapLimits;\n        SerializedProperty m_BakeBackend;\n        // pvr\n        SerializedProperty m_PVRSampleCount;\n        SerializedProperty m_PVRDirectSampleCount;\n        SerializedProperty m_PVRBounces;\n        SerializedProperty m_PVRCulling;\n        SerializedProperty m_PVRFilteringMode;\n        SerializedProperty m_PVRFilterTypeDirect;\n        SerializedProperty m_PVRFilterTypeIndirect;\n        SerializedProperty m_PVRFilterTypeAO;\n        SerializedProperty m_PVRDenoiserTypeDirect;\n        SerializedProperty m_PVRDenoiserTypeIndirect;\n        SerializedProperty m_PVRDenoiserTypeAO;\n        SerializedProperty m_PVRFilteringGaussRadiusDirect;\n        SerializedProperty m_PVRFilteringGaussRadiusIndirect;\n        SerializedProperty m_PVRFilteringGaussRadiusAO;\n        SerializedProperty m_PVRFilteringAtrousPositionSigmaDirect;\n        SerializedProperty m_PVRFilteringAtrousPositionSigmaIndirect;\n        SerializedProperty m_PVRFilteringAtrousPositionSigmaAO;\n        SerializedProperty m_PVREnvironmentIS;\n        SerializedProperty m_PVREnvironmentSampleCount;\n        SerializedProperty m_LightProbeSampleCountMultiplier;\n\n        // internal\n        SerializedProperty m_BounceScale;\n        SerializedProperty m_ExportTrainingData;\n        SerializedProperty m_EnableWorkerProcessBaking;\n        SerializedProperty m_TrainingDataDestination;\n        SerializedProperty m_ForceWhiteAlbedo;\n        SerializedProperty m_ForceUpdates;\n        SerializedProperty m_FilterMode;\n        SerializedProperty m_RespectSceneVisibilityWhenBakingGI;\n\n        enum DenoiserTarget\n        {\n            Direct = 0,\n            Indirect = 1,\n            AO = 2\n        }\n\n        static class Styles\n        {\n            public static readonly float buttonWidth = 200;\n\n            public static readonly int[] bakeBackendValues =\n            {\n                (int)LightingSettings.Lightmapper.ProgressiveCPU,\n                (int)LightingSettings.Lightmapper.ProgressiveGPU,\n                //(int)LightingSettings.Lightmapper.UnityComputeGPU\n            };\n            public static readonly GUIContent[] bakeBackendStrings =\n            {\n                EditorGUIUtility.TrTextContent(\"Progressive CPU\"),\n                EditorGUIUtility.TrTextContent(\"Progressive GPU\"),\n                //EditorGUIUtility.TrTextContent(\"Unity Compute (GPU)\"),\n            };\n\n            public static readonly int[] lightmapDirectionalModeValues = { (int)LightmapsMode.NonDirectional, (int)LightmapsMode.CombinedDirectional };\n            public static readonly GUIContent[] lightmapDirectionalModeStrings =\n            {\n                EditorGUIUtility.TrTextContent(\"Non-Directional\"),\n                EditorGUIUtility.TrTextContent(\"Directional\"),\n            };\n\n            public static readonly int[] lightmapMaxSizeValues = { 32, 64, 128, 256, 512, 1024, 2048, 4096 };\n            public static readonly GUIContent[] lightmapMaxSizeStrings = Array.ConvertAll(lightmapMaxSizeValues, (x) => new GUIContent(x.ToString()));\n\n            // must match LightmapMixedBakeMode\n            public static readonly int[] mixedModeValues = { 0, 1, 2 };\n            public static readonly GUIContent[] mixedModeStrings =\n            {\n                EditorGUIUtility.TrTextContent(\"Baked Indirect\"),\n                EditorGUIUtility.TrTextContent(\"Subtractive\"),\n                EditorGUIUtility.TrTextContent(\"Shadowmask\")\n            };\n\n            // must match PVRDenoiserType\n            public static readonly int[] denoiserTypeValues = { (int)LightingSettings.DenoiserType.Optix, (int)LightingSettings.DenoiserType.OpenImage, (int)LightingSettings.DenoiserType.None };\n            public static readonly GUIContent[] denoiserTypeStrings =\n            {\n                EditorGUIUtility.TrTextContent(\"Optix\"),\n                EditorGUIUtility.TrTextContent(\"OpenImageDenoise\"),\n                EditorGUIUtility.TrTextContent(\"None\")\n            };\n\n            public static readonly int[] lightmapCompressionValues =\n            {\n                (int)LightmapCompression.None,\n                (int)LightmapCompression.LowQuality,\n                (int)LightmapCompression.NormalQuality,\n                (int)LightmapCompression.HighQuality\n            };\n            public static readonly GUIContent[] lightmapCompressionStrings =\n            {\n                EditorGUIUtility.TrTextContent(\"None\"),\n                EditorGUIUtility.TrTextContent(\"Low Quality\"),\n                EditorGUIUtility.TrTextContent(\"Normal Quality\"),\n                EditorGUIUtility.TrTextContent(\"High Quality\")\n            };\n\n            public static readonly int[] concurrentJobsTypeValues = { (int)Lightmapping.ConcurrentJobsType.Min, (int)Lightmapping.ConcurrentJobsType.Low, (int)Lightmapping.ConcurrentJobsType.High };\n            public static readonly GUIContent[] concurrentJobsTypeStrings =\n            {\n                EditorGUIUtility.TrTextContent(\"Min\"),\n                EditorGUIUtility.TrTextContent(\"Low\"),\n                EditorGUIUtility.TrTextContent(\"High\")\n            };\n\n            public static readonly GUIContent lightmapperNotSupportedWarning = EditorGUIUtility.TrTextContent(\"This lightmapper is not supported by the current Render Pipeline. The Editor will use \");\n            public static readonly GUIContent appleSiliconCPULightmapperWarning = EditorGUIUtility.TrTextContent(\"Progressive CPU Lightmapper is not available on Apple Silicon. Use Progressive GPU Lightmapper instead.\");\n            public static readonly GUIContent mixedModeNotSupportedWarning = EditorGUIUtility.TrTextContent(\"The Mixed mode is not supported by the current Render Pipeline. Fallback mode is \");\n            public static readonly GUIContent directionalNotSupportedWarning = EditorGUIUtility.TrTextContent(\"Directional Mode is not supported. Fallback will be Non-Directional.\");\n            public static readonly GUIContent denoiserNotSupportedWarning = EditorGUIUtility.TrTextContent(\"The current hardware or system configuration does not support the selected denoiser. Select a different denoiser.\");\n\n            public static readonly GUIContent enableBaked = EditorGUIUtility.TrTextContent(\"Baked Global Illumination\", \"Controls whether Mixed and Baked lights will use baked Global Illumination. If enabled, Mixed lights are baked using the specified Lighting Mode and Baked lights will be completely baked and not adjustable at runtime.\");\n            public static readonly GUIContent bounceScale = EditorGUIUtility.TrTextContent(\"Bounce Scale\", \"Multiplier for indirect lighting. Use with care.\");\n            public static readonly GUIContent updateThreshold = EditorGUIUtility.TrTextContent(\"Update Threshold\", \"Threshold for updating realtime GI. A lower value causes more frequent updates (default 1.0).\");\n            public static readonly GUIContent albedoBoost = EditorGUIUtility.TrTextContent(\"Albedo Boost\", \"Controls the amount of light bounced between surfaces by intensifying the albedo of materials in the scene. Increasing this draws the albedo value towards white for indirect light computation. The default value is physically accurate.\");\n            public static readonly GUIContent indirectOutputScale = EditorGUIUtility.TrTextContent(\"Indirect Intensity\", \"Controls the brightness of indirect light stored in realtime and baked lightmaps. A value above 1.0 will increase the intensity of indirect light while a value less than 1.0 will reduce indirect light intensity.\");\n            public static readonly GUIContent lightmapDirectionalMode = EditorGUIUtility.TrTextContent(\"Directional Mode\", \"Controls whether baked and realtime lightmaps will store directional lighting information from the lighting environment. Options are Directional and Non-Directional.\");\n            public static readonly GUIContent lightmapParameters = EditorGUIUtility.TrTextContent(\"Lightmap Parameters\", \"Allows the adjustment of advanced parameters that affect the process of generating a lightmap for an object using global illumination.\");\n            public static readonly GUIContent newLightmapParameters = EditorGUIUtility.TrTextContent(\"New\", \"Create a new Lightmap Parameters Asset with default settings.\");\n            public static readonly GUIContent cloneLightmapParameters = EditorGUIUtility.TrTextContent(\"Clone\", \"Create a new Lightmap Parameters Asset based on the current settings.\");\n            public static readonly GUIContent realtimeLightsLabel = EditorGUIUtility.TrTextContent(\"Realtime Lighting\", \"Precompute Realtime indirect lighting for realtime lights and static objects. In this mode realtime lights, ambient lighting, materials of static objects (including emission) will generate indirect lighting at runtime. Only static objects are blocking and bouncing light, dynamic objects receive indirect lighting via light probes.\");\n            public static readonly GUIContent realtimeEnvironmentLighting = EditorGUIUtility.TrTextContent(\"Realtime Environment Lighting\", \"Specifies the Global Illumination mode that should be used for handling ambient light in the Scene. This property is not editable unless both Realtime Global Illumination and Baked Global Illumination are enabled for the scene.\");\n            public static readonly GUIContent mixedLightsLabel = EditorGUIUtility.TrTextContent(\"Mixed Lighting\", \"Bake Global Illumination for mixed lights and static objects. May bake both direct and/or indirect lighting based on settings. Only static objects are blocking and bouncing light, dynamic objects receive baked lighting via light probes.\");\n            public static readonly GUIContent generalLightmapLabel = EditorGUIUtility.TrTextContent(\"Lightmapping Settings\", \"Settings that apply to both Global Illumination modes (Precomputed Realtime and Baked).\");\n            public static readonly GUIContent internalLabel = EditorGUIUtility.TrTextContent(\"Internal Settings\", \"Internal only settings. \");\n            public static readonly GUIContent forceWhiteAlbedo = EditorGUIUtility.TrTextContent(\"Force White Albedo\", \"Force white albedo during lighting calculations.\");\n            public static readonly GUIContent forceUpdates = EditorGUIUtility.TrTextContent(\"Force Updates\", \"Force continuous updates of runtime indirect lighting calculations.\");\n            public static readonly GUIContent filterMode = EditorGUIUtility.TrTextContent(\"Filter Mode\");\n            public static readonly GUIContent exportTrainingData = EditorGUIUtility.TrTextContent(\"Export Training Data\", \"Exports unfiltered textures, normals, positions.\");\n            public static readonly GUIContent trainingDataDestination = EditorGUIUtility.TrTextContent(\"Destination\", \"Destination for the training data, for example 'mysetup/30samples'. Will still be located at the first level in the project folder. \");\n            public static readonly GUIContent concurrentJobs = EditorGUIUtility.TrTextContent(\"Concurrent Jobs\", \"The amount of simultaneously scheduled jobs.\");\n            public static readonly GUIContent indirectResolution = EditorGUIUtility.TrTextContent(\"Indirect Resolution\", \"Sets the resolution in texels that are used per unit for objects being lit by indirect lighting. The higher this value is, the more time the Editor needs to bake lighting.\");\n            public static readonly GUIContent lightmapResolution = EditorGUIUtility.TrTextContent(\"Lightmap Resolution\", \"Sets the number of texels per unit assigned to objects receiving GI from lightmaps. Also affects the resolution of albedo and emission textures used in lighting calculations for both lightmaps and Light Probes. Higher values increase bake times.\");\n            public static readonly GUIContent padding = EditorGUIUtility.TrTextContent(\"Lightmap Padding\", \"Sets the separation in texels between shapes in the baked lightmap.\");\n            public static readonly GUIContent lightmapMaxSize = EditorGUIUtility.TrTextContent(\"Max Lightmap Size\", \"Sets the max size of the full lightmap Texture in pixels. Values are squared, so a setting of 1024 can produce a 1024x1024 pixel sized lightmap.\");\n            public static readonly GUIContent lightmapSizeFixed = EditorGUIUtility.TrTextContent(\"Fixed Lightmap Size\", \"Forces all lightmap textures to use the same size. These can be no larger than Max Lightmap Size.\");\n            public static readonly GUIContent enableWorkerProcessBaking = EditorGUIUtility.TrTextContent(\"Enable worker process baking\", \"Leaving this unchecked will force bakes that would otherwise be run in a worker process to be run in-process and blocking.\");\n            public static readonly GUIContent useMipmapLimits = EditorGUIUtility.TrTextContent(\"Use Mipmap Limits\", \"Whether lightmap textures use the Global Mipmap limit defined in Quality Settings. Disable this to ensure lightmaps are available at the full mipmap resolution.\");\n            public static readonly GUIContent lightmapCompression = EditorGUIUtility.TrTextContent(\"Lightmap Compression\", \"Compresses baked lightmaps created using this Lighting Settings Asset. Lower quality compression reduces memory and storage requirements, at the cost of more visual artifacts. Higher quality compression requires more memory and storage, but provides better visual results.\");\n            public static readonly GUIContent ambientOcclusion = EditorGUIUtility.TrTextContent(\"Ambient Occlusion\", \"Specifies whether to include ambient occlusion or not in the baked lightmap result. Enabling this results in simulating the soft shadows that occur in cracks and crevices of objects when light is reflected onto them.\");\n            public static readonly GUIContent ambientOcclusionContribution = EditorGUIUtility.TrTextContent(\"Indirect Contribution\", \"Adjusts the contrast of ambient occlusion applied to indirect lighting. The larger the value, the more contrast is applied to the ambient occlusion for indirect lighting.\");\n            public static readonly GUIContent ambientOcclusionContributionDirect = EditorGUIUtility.TrTextContent(\"Direct Contribution\", \"Adjusts the contrast of ambient occlusion applied to the direct lighting. The larger the value is, the more contrast is applied to the ambient occlusion for direct lighting. This effect is not physically accurate.\");\n            public static readonly GUIContent AOMaxDistance = EditorGUIUtility.TrTextContent(\"Max Distance\", \"Controls how far rays are cast in order to determine if an object is occluded or not. A larger value produces longer rays and contributes more shadows to the lightmap, while a smaller value produces shorter rays that contribute shadows only when objects are very close to one another. A value of 0 casts an infinitely long ray that has no maximum distance.\");\n            public static readonly GUIContent mixedLightMode = EditorGUIUtility.TrTextContent(\"Lighting Mode\", \"Specifies the lighting mode of all Mixed lights in the Scene.\");\n            public static readonly GUIContent useRealtimeGI = EditorGUIUtility.TrTextContent(\"Realtime Global Illumination\", \"Precomputed Realtime Global Illumination using Enlighten. Provides diffuse Realtime Global Illumination for static geometry via low resolution lightmaps and via Light Probes for dynamic geometry.\");\n            public static readonly GUIContent bakedGIDisabledInfo = EditorGUIUtility.TrTextContent(\"All Baked and Mixed lights in the Scene are currently being overridden to Realtime light modes. Enable Baked Global Illumination to allow the use of Baked and Mixed light modes.\");\n            public static readonly GUIContent bakeBackend = EditorGUIUtility.TrTextContent(\"Lightmapper\", \"Specifies which baking system will be used to generate baked lightmaps.\");\n            public static readonly GUIContent directSampleCount = EditorGUIUtility.TrTextContent(\"Direct Samples\", \"Controls the number of samples the lightmapper will use for direct lighting calculations. Increasing this value may improve the quality of lightmaps but increases the time required for baking to complete.\");\n            public static readonly GUIContent indirectSampleCount = EditorGUIUtility.TrTextContent(\"Indirect Samples\", \"Controls the number of samples the lightmapper will use for indirect lighting calculations. Increasing this value may improve the quality of lightmaps but increases the time required for baking to complete.\");\n            public static readonly GUIContent bounces = EditorGUIUtility.TrTextContent(\"Max Bounces\", \"The maximum number of bounces the Lightmapper computes for indirect lighting.\");\n            public static readonly GUIContent denoisingWarningDirect = EditorGUIUtility.TrTextContent(\"Direct Denoiser\", \"Your hardware does not support denoising. For minimum requirements, please read the documentation.\");\n            public static readonly GUIContent denoisingWarningIndirect = EditorGUIUtility.TrTextContent(\"Indirect Denoiser\", \"Your hardware does not support denoising. For minimum requirements, please read the documentation.\");\n            public static readonly GUIContent denoisingWarningAO = EditorGUIUtility.TrTextContent(\"Ambient Occlusion Denoiser\", \"Your hardware Your hardware does not support denoising. For minimum requirements, please read the documentation.\");\n            public static readonly GUIContent denoiserTypeDirect = EditorGUIUtility.TrTextContent(\"Direct Denoiser\", \"Specifies the type of denoiser used to reduce noise for direct lights.\");\n            public static readonly GUIContent denoiserTypeIndirect = EditorGUIUtility.TrTextContent(\"Indirect Denoiser\", \"Specifies the type of denoiser used to reduce noise for indirect lights.\");\n            public static readonly GUIContent denoiserTypeAO = EditorGUIUtility.TrTextContent(\"Ambient Occlusion Denoiser\", \"Specifies the type of denoiser used to reduce noise for ambient occlusion.\");\n            public static readonly GUIContent filteringMode = EditorGUIUtility.TrTextContent(\"Filtering\", \"Specifies the method to reduce noise in baked lightmaps.\");\n            public static readonly GUIContent filterTypeDirect = EditorGUIUtility.TrTextContent(\"Direct Filter\", \"Specifies the filter kernel applied to the direct light stored in the lightmap. Gaussian blurs the lightmap with some loss of detail. A-Trous reduces noise based on a threshold while maintaining edge detail.\");\n            public static readonly GUIContent filterTypeIndirect = EditorGUIUtility.TrTextContent(\"Indirect Filter\", \"Specifies the filter kernel applied to the indirect light stored in the lightmap. Gaussian blurs the lightmap with some loss of detail. A-Trous reduces noise based on a threshold while maintaining edge detail.\");\n            public static readonly GUIContent filterTypeAO = EditorGUIUtility.TrTextContent(\"Ambient Occlusion Filter\", \"Specifies the filter kernel applied to the ambient occlusion stored in the lightmap. Gaussian blurs the lightmap with some loss of detail. A-Trous reduces noise based on a threshold while maintaining edge detail.\");\n            public static readonly GUIContent filteringGaussRadiusDirect = EditorGUIUtility.TrTextContent(\"Radius\", \"Controls the radius of the filter for direct light stored in the lightmap. A higher value gives a stronger blur and less noise.\");\n            public static readonly GUIContent filteringGaussRadiusIndirect = EditorGUIUtility.TrTextContent(\"Radius\", \"Controls the radius of the filter for indirect light stored in the lightmap. A higher value gives a stronger blur and less noise.\");\n            public static readonly GUIContent filteringGaussRadiusAO = EditorGUIUtility.TrTextContent(\"Radius\", \"Controls the radius of the filter for ambient occlusion stored in the lightmap. A higher value gives a stronger blur and less noise.\");\n            public static readonly GUIContent filteringAtrousPositionSigmaDirect = EditorGUIUtility.TrTextContent(\"Sigma\", \"Controls the threshold of the filter for direct light stored in the lightmap. A higher value increases the threshold, which reduces noise in the direct layer of the lightmap. Too high of a value can cause a loss of detail in the lightmap.\");\n            public static readonly GUIContent filteringAtrousPositionSigmaIndirect = EditorGUIUtility.TrTextContent(\"Sigma\", \"Controls the threshold of the filter for indirect light stored in the lightmap. A higher value increases the threshold, which reduces noise in the direct layer of the lightmap. Too high of a value can cause a loss of detail in the lightmap.\");\n            public static readonly GUIContent filteringAtrousPositionSigmaAO = EditorGUIUtility.TrTextContent(\"Sigma\", \"Controls the threshold of the filter for ambient occlusion stored in the lightmap. A higher value increases the threshold, which reduces noise in the direct layer of the lightmap. Too high of a value can cause a loss of detail in the lightmap.\");\n            public static readonly GUIContent culling = EditorGUIUtility.TrTextContent(\"Progressive Updates\", \"Specifies whether the lightmapper should prioritize baking what is visible in the scene view. When disabled, lightmaps are only composited once fully converged which can improve baking performance.\");\n            public static readonly GUIContent environmentImportanceSampling = EditorGUIUtility.TrTextContent(\"Importance Sampling\", \"Specifies whether to use importance sampling for sampling environment lighting. In most environments importance sampling facilitates faster convergence while generating lightmaps. In certain low frequency environments, importance sampling can produce noisy results.\");\n            public static readonly GUIContent environmentSampleCount = EditorGUIUtility.TrTextContent(\"Environment Samples\", \"Controls the number of samples the lightmapper will use for environment lighting calculations. Increasing this value may improve the quality of lightmaps but increases the time required for baking to complete.\");\n            public static readonly GUIContent probeSampleCountMultiplier = EditorGUIUtility.TrTextContent(\"Light Probe Sample Multiplier\", \"Controls how many samples are used for Light Probes as a multiplier of the general sample counts above. Higher values improve the quality of Light Probes, but also take longer to bake. Enable the Light Probe sample count multiplier by disabling Project Settings > Editor > Use legacy Light Probe sample counts\");\n            public static readonly GUIContent texelsPerUnit = EditorGUIUtility.TrTextContent(\" texels per unit\");\n            public static readonly GUIContent texels = EditorGUIUtility.TrTextContent(\" texels\");\n            public static readonly GUIContent sigma = EditorGUIUtility.TrTextContent(\" sigma\");\n\n            public static readonly GUIStyle labelStyle = EditorStyles.wordWrappedMiniLabel;\n        }\n\n        private int maxDirectSamples = 1024;\n        private int maxIndirectSamples = 8192;\n        private int maxEnvironmentSamples = 2048;\n        private SerializedObject currentLSO;\n\n        public void OnEnable()\n        {\n            m_ShowRealtimeLightsSettings = new SavedBool(\"LightingSettings.ShowRealtimeLightsSettings\", false);\n            m_ShowMixedLightsSettings = new SavedBool(\"LightingSettings.ShowMixedLightsSettings\", true);\n            m_ShowGeneralLightingSettings = new SavedBool(\"LightingSettings.ShowGeneralLightingSettings\", true);\n            m_ShowInternalSettings = new SavedBool(\"LightingSettings.ShowInternalSettings\", true);\n        }\n\n        public void OnGUI(bool compact, bool drawAutoGenerate)\n        {\n            if (currentLSO == null || currentLSO != m_EnabledBakedGI.serializedObject)\n            {\n                currentLSO = m_EnabledBakedGI.serializedObject;\n                ClampMaxRanges();\n            }\n\n            RealtimeLightingGUI(compact);\n            MixedLightingGUI(compact);\n            GeneralLightmapSettingsGUI(compact);\n            InternalSettingsGUI(compact);\n        }\n\n        public void UpdateSettings(SerializedObject lightingSettingsObject)\n        {\n            if (lightingSettingsObject == null)\n                return;\n\n            //realtime GI\n            m_RealtimeResolution = lightingSettingsObject.FindProperty(\"m_RealtimeResolution\");\n            m_EnableRealtimeGI = lightingSettingsObject.FindProperty(\"m_EnableRealtimeLightmaps\");\n            m_RealtimeEnvironmentLighting = lightingSettingsObject.FindProperty(\"m_RealtimeEnvironmentLighting\");\n\n            //baked\n            m_EnabledBakedGI = lightingSettingsObject.FindProperty(\"m_EnableBakedLightmaps\");\n            m_BakeBackend = lightingSettingsObject.FindProperty(\"m_BakeBackend\");\n            m_MixedBakeMode = lightingSettingsObject.FindProperty(\"m_MixedBakeMode\");\n            m_AlbedoBoost = lightingSettingsObject.FindProperty(\"m_AlbedoBoost\");\n            m_IndirectOutputScale = lightingSettingsObject.FindProperty(\"m_IndirectOutputScale\");\n            m_LightmapMaxSize = lightingSettingsObject.FindProperty(\"m_LightmapMaxSize\");\n            m_LightmapSizeFixed = lightingSettingsObject.FindProperty(\"m_LightmapSizeFixed\");\n            m_UseMipmapLimits = lightingSettingsObject.FindProperty(\"m_UseMipmapLimits\");\n            m_LightmapParameters = lightingSettingsObject.FindProperty(\"m_LightmapParameters\");\n            m_LightmapDirectionalMode = lightingSettingsObject.FindProperty(\"m_LightmapsBakeMode\");\n            m_BakeResolution = lightingSettingsObject.FindProperty(\"m_BakeResolution\");\n            m_Padding = lightingSettingsObject.FindProperty(\"m_Padding\");\n            m_AmbientOcclusion = lightingSettingsObject.FindProperty(\"m_AO\");\n            m_AOMaxDistance = lightingSettingsObject.FindProperty(\"m_AOMaxDistance\");\n            m_CompAOExponent = lightingSettingsObject.FindProperty(\"m_CompAOExponent\");\n            m_CompAOExponentDirect = lightingSettingsObject.FindProperty(\"m_CompAOExponentDirect\");\n            m_LightmapCompression = lightingSettingsObject.FindProperty(\"m_LightmapCompression\");\n\n            // pvr\n            m_PVRSampleCount = lightingSettingsObject.FindProperty(\"m_PVRSampleCount\");\n            m_PVRDirectSampleCount = lightingSettingsObject.FindProperty(\"m_PVRDirectSampleCount\");\n            m_PVRBounces = lightingSettingsObject.FindProperty(\"m_PVRBounces\");\n            m_PVRCulling = lightingSettingsObject.FindProperty(\"m_PVRCulling\");\n            m_PVRFilteringMode = lightingSettingsObject.FindProperty(\"m_PVRFilteringMode\");\n            m_PVRFilterTypeDirect = lightingSettingsObject.FindProperty(\"m_PVRFilterTypeDirect\");\n            m_PVRFilterTypeIndirect = lightingSettingsObject.FindProperty(\"m_PVRFilterTypeIndirect\");\n            m_PVRFilterTypeAO = lightingSettingsObject.FindProperty(\"m_PVRFilterTypeAO\");\n            m_PVRDenoiserTypeDirect = lightingSettingsObject.FindProperty(\"m_PVRDenoiserTypeDirect\");\n            m_PVRDenoiserTypeIndirect = lightingSettingsObject.FindProperty(\"m_PVRDenoiserTypeIndirect\");\n            m_PVRDenoiserTypeAO = lightingSettingsObject.FindProperty(\"m_PVRDenoiserTypeAO\");\n            m_PVRFilteringGaussRadiusDirect = lightingSettingsObject.FindProperty(\"m_PVRFilteringGaussRadiusDirect\");\n            m_PVRFilteringGaussRadiusIndirect = lightingSettingsObject.FindProperty(\"m_PVRFilteringGaussRadiusIndirect\");\n            m_PVRFilteringGaussRadiusAO = lightingSettingsObject.FindProperty(\"m_PVRFilteringGaussRadiusAO\");\n            m_PVRFilteringAtrousPositionSigmaDirect = lightingSettingsObject.FindProperty(\"m_PVRFilteringAtrousPositionSigmaDirect\");\n            m_PVRFilteringAtrousPositionSigmaIndirect = lightingSettingsObject.FindProperty(\"m_PVRFilteringAtrousPositionSigmaIndirect\");\n            m_PVRFilteringAtrousPositionSigmaAO = lightingSettingsObject.FindProperty(\"m_PVRFilteringAtrousPositionSigmaAO\");\n            m_PVREnvironmentIS = lightingSettingsObject.FindProperty(\"m_PVREnvironmentImportanceSampling\");\n            m_PVREnvironmentSampleCount = lightingSettingsObject.FindProperty(\"m_PVREnvironmentSampleCount\");\n            m_LightProbeSampleCountMultiplier = lightingSettingsObject.FindProperty(\"m_LightProbeSampleCountMultiplier\");\n\n            //dev debug properties\n            m_ExportTrainingData = lightingSettingsObject.FindProperty(\"m_ExportTrainingData\");\n            m_EnableWorkerProcessBaking = lightingSettingsObject.FindProperty(\"m_EnableWorkerProcessBaking\");\n            m_TrainingDataDestination = lightingSettingsObject.FindProperty(\"m_TrainingDataDestination\");\n            m_ForceWhiteAlbedo = lightingSettingsObject.FindProperty(\"m_ForceWhiteAlbedo\");\n            m_ForceUpdates = lightingSettingsObject.FindProperty(\"m_ForceUpdates\");\n            m_FilterMode = lightingSettingsObject.FindProperty(\"m_FilterMode\");\n            m_BounceScale = lightingSettingsObject.FindProperty(\"m_BounceScale\");\n            m_RespectSceneVisibilityWhenBakingGI = lightingSettingsObject.FindProperty(\"m_RespectSceneVisibilityWhenBakingGI\");\n        }\n\n        // Private methods\n\n        void RealtimeLightingGUI(bool compact)\n        {\n            // ambient GI - realtime / baked\n            bool realtimeGISupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime);\n\n            if (!realtimeGISupported)\n                return;\n\n            if (compact)\n                m_ShowRealtimeLightsSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_ShowRealtimeLightsSettings.value, Styles.realtimeLightsLabel);\n            else\n                m_ShowRealtimeLightsSettings.value = EditorGUILayout.FoldoutTitlebar(m_ShowRealtimeLightsSettings.value, Styles.realtimeLightsLabel, true);\n\n            if (m_ShowRealtimeLightsSettings.value)\n            {\n                EditorGUI.indentLevel++;\n\n                EditorGUILayout.PropertyField(m_EnableRealtimeGI, Styles.useRealtimeGI);\n\n                EditorGUI.indentLevel++;\n\n                bool bakedGISupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Baked);\n                bool enableRealtimeGI = (m_EnableRealtimeGI.boolValue && !m_EnableRealtimeGI.hasMultipleDifferentValues);\n                bool enableBakedGI = (m_EnabledBakedGI.boolValue && !m_EnabledBakedGI.hasMultipleDifferentValues);\n\n                if (enableBakedGI && enableRealtimeGI)\n                {\n                    // if the user has selected the only state that is supported, then gray it out\n                    using (new EditorGUI.DisabledScope(m_RealtimeEnvironmentLighting.boolValue && !bakedGISupported))\n                    {\n                        EditorGUILayout.PropertyField(m_RealtimeEnvironmentLighting, Styles.realtimeEnvironmentLighting);\n                    }\n\n                    // if they have selected a state that isnt supported, show dialog, and still make the box editable\n                    if (!m_RealtimeEnvironmentLighting.boolValue && !bakedGISupported)\n                    {\n                        EditorGUILayout.HelpBox(\"The following mode is not supported and will fallback on Realtime\", MessageType.Warning);\n                    }\n                }\n                // Show \"Realtime\" on if baked GI is disabled (but we don't wanna show the box if the whole mode is not supported.)\n                else\n                {\n                    using (new EditorGUI.DisabledScope(true))\n                    {\n                        EditorGUILayout.PropertyField(m_EnableRealtimeGI, Styles.realtimeEnvironmentLighting);\n                    }\n                }\n\n                using (new EditorGUI.DisabledScope(!enableRealtimeGI))\n                {\n                    DrawPropertyFieldWithPostfixLabel(m_RealtimeResolution, Styles.indirectResolution, Styles.texelsPerUnit);\n                }\n\n                EditorGUI.indentLevel -= 2;\n                EditorGUILayout.Space();\n            }\n\n            if (compact)\n                EditorGUILayout.EndFoldoutHeaderGroup();\n        }\n\n        void MixedLightingGUI(bool compact)\n        {\n            if (!SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Baked))\n                return;\n\n            if (compact)\n                m_ShowMixedLightsSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_ShowMixedLightsSettings.value, Styles.mixedLightsLabel);\n            else\n                m_ShowMixedLightsSettings.value = EditorGUILayout.FoldoutTitlebar(m_ShowMixedLightsSettings.value, Styles.mixedLightsLabel, true);\n\n            if (m_ShowMixedLightsSettings.value)\n            {\n                EditorGUI.indentLevel++;\n\n                EditorGUILayout.PropertyField(m_EnabledBakedGI, Styles.enableBaked);\n\n                if (!m_EnabledBakedGI.boolValue)\n                {\n                    EditorGUILayout.HelpBox(Styles.bakedGIDisabledInfo.text, MessageType.Info);\n                }\n\n                bool enableBakedGI = (m_EnabledBakedGI.boolValue && !m_EnabledBakedGI.hasMultipleDifferentValues);\n\n                using (new EditorGUI.DisabledScope(!enableBakedGI))\n                {\n                    bool mixedGISupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Mixed);\n\n                    using (new EditorGUI.DisabledScope(!mixedGISupported))\n                    {\n                        var rect = EditorGUILayout.GetControlRect();\n                        EditorGUI.BeginProperty(rect, Styles.mixedLightMode, m_MixedBakeMode);\n                        rect = EditorGUI.PrefixLabel(rect, Styles.mixedLightMode);\n\n                        int index = Math.Max(0, Array.IndexOf(Styles.mixedModeValues, m_MixedBakeMode.intValue));\n\n                        if (EditorGUI.DropdownButton(rect, Styles.mixedModeStrings[index], FocusType.Passive))\n                        {\n                            var menu = new GenericMenu();\n\n                            for (int i = 0; i < Styles.mixedModeValues.Length; i++)\n                            {\n                                int value = Styles.mixedModeValues[i];\n                                bool selected = (value == m_MixedBakeMode.intValue);\n\n                                if (!SupportedRenderingFeatures.IsMixedLightingModeSupported((MixedLightingMode)value))\n                                    menu.AddDisabledItem(Styles.mixedModeStrings[i], selected);\n                                else\n                                    menu.AddItem(Styles.mixedModeStrings[i], selected, OnMixedModeSelected, value);\n                            }\n                            menu.DropDown(rect);\n                        }\n                        EditorGUI.EndProperty();\n\n                        if (mixedGISupported && !SupportedRenderingFeatures.IsMixedLightingModeSupported((MixedLightingMode)m_MixedBakeMode.intValue))\n                        {\n                            string fallbackMode = Styles.mixedModeStrings[(int)SupportedRenderingFeatures.FallbackMixedLightingMode()].text;\n                            EditorGUILayout.HelpBox(Styles.mixedModeNotSupportedWarning.text + fallbackMode, MessageType.Warning);\n                        }\n                    }\n                }\n                EditorGUI.indentLevel--;\n                EditorGUILayout.Space();\n            }\n\n            if (compact)\n                EditorGUILayout.EndFoldoutHeaderGroup();\n        }\n\n        void GeneralLightmapSettingsGUI(bool compact)\n        {\n            bool bakedGISupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Baked);\n            bool realtimeGISupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime);\n            bool lightmapperSupported = SupportedRenderingFeatures.IsLightmapperSupported(m_BakeBackend.intValue);\n\n            if (!bakedGISupported && !realtimeGISupported)\n                return;\n\n            if (compact)\n                m_ShowGeneralLightingSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_ShowGeneralLightingSettings.value, Styles.generalLightmapLabel);\n            else\n                m_ShowGeneralLightingSettings.value = EditorGUILayout.FoldoutTitlebar(m_ShowGeneralLightingSettings.value, Styles.generalLightmapLabel, true);\n\n            bool enableRealtimeGI = (m_EnableRealtimeGI.boolValue && !m_EnableRealtimeGI.hasMultipleDifferentValues);\n            bool enableBakedGI = (m_EnabledBakedGI.boolValue && !m_EnabledBakedGI.hasMultipleDifferentValues);\n\n            if (m_ShowGeneralLightingSettings.value)\n            {\n                EditorGUI.indentLevel++;\n                using (new EditorGUI.DisabledScope(!enableRealtimeGI && !enableBakedGI))\n                {\n                    if (bakedGISupported)\n                    {\n                        using (new EditorGUI.DisabledScope(!enableBakedGI))\n                        {\n                            BakeBackendGUI();\n\n                            if (lightmapperSupported)\n                            {\n                                EditorGUI.indentLevel++;\n\n                                EditorGUILayout.PropertyField(m_PVREnvironmentIS, Styles.environmentImportanceSampling);\n\n                                MultiEditableLogarithmicIntSlider(m_PVRDirectSampleCount, Styles.directSampleCount, 1, maxDirectSamples, 1, 1 << 30);\n                                MultiEditableLogarithmicIntSlider(m_PVRSampleCount, Styles.indirectSampleCount, 1, maxIndirectSamples, 1, 1 << 30);\n                                MultiEditableLogarithmicIntSlider(m_PVREnvironmentSampleCount, Styles.environmentSampleCount, 1, maxEnvironmentSamples, 1, 1 << 30);\n\n                                maxDirectSamples = (int)Mathf.ClosestPowerOfTwo(Math.Max(maxDirectSamples, m_PVRDirectSampleCount.intValue));\n                                maxIndirectSamples = (int)Mathf.ClosestPowerOfTwo(Math.Max(maxIndirectSamples, m_PVRSampleCount.intValue));\n\n                                using (new EditorGUI.DisabledScope(EditorSettings.useLegacyProbeSampleCount))\n                                {\n                                    EditorGUILayout.PropertyField(m_LightProbeSampleCountMultiplier, Styles.probeSampleCountMultiplier);\n                                }\n\n                                EditorGUILayout.PropertyField(m_PVRBounces, Styles.bounces);\n\n                                // Filtering\n                                EditorGUILayout.PropertyField(m_PVRFilteringMode, Styles.filteringMode);\n\n                                if (m_PVRFilteringMode.intValue == (int)LightingSettings.FilterMode.Advanced && !m_PVRFilteringMode.hasMultipleDifferentValues)\n                                {\n                                    // Check if the platform doesn't support denoising.\n                                    bool anyDenoisingSupported = (Lightmapping.IsOptixDenoiserSupported() || Lightmapping.IsOpenImageDenoiserSupported());\n\n                                    EditorGUI.indentLevel++;\n                                    using (new EditorGUI.DisabledScope(!anyDenoisingSupported))\n                                    {\n                                        DrawDenoiserTypeDropdown(m_PVRDenoiserTypeDirect, anyDenoisingSupported ? Styles.denoiserTypeDirect : Styles.denoisingWarningDirect, DenoiserTarget.Direct);\n\n                                        if (anyDenoisingSupported && !DenoiserSupported((LightingSettings.DenoiserType)m_PVRDenoiserTypeDirect.intValue))\n                                        {\n                                            EditorGUILayout.HelpBox(Styles.denoiserNotSupportedWarning.text, MessageType.Info);\n                                        }\n                                    }\n\n                                    EditorGUILayout.PropertyField(m_PVRFilterTypeDirect, Styles.filterTypeDirect);\n\n                                    if (!m_PVRFilterTypeDirect.hasMultipleDifferentValues)\n                                    {\n                                        EditorGUI.indentLevel++;\n                                        DrawFilterSettingField(m_PVRFilteringGaussRadiusDirect,\n                                            m_PVRFilteringAtrousPositionSigmaDirect,\n                                            Styles.filteringGaussRadiusDirect,\n                                            Styles.filteringAtrousPositionSigmaDirect,\n                                            (LightingSettings.FilterType)m_PVRFilterTypeDirect.intValue);\n                                        EditorGUI.indentLevel--;\n                                    }\n\n                                    EditorGUILayout.Space();\n\n                                    using (new EditorGUI.DisabledScope(!anyDenoisingSupported))\n                                    {\n                                        DrawDenoiserTypeDropdown(m_PVRDenoiserTypeIndirect, anyDenoisingSupported ? Styles.denoiserTypeIndirect : Styles.denoisingWarningIndirect, DenoiserTarget.Indirect);\n\n                                        if (anyDenoisingSupported && !DenoiserSupported((LightingSettings.DenoiserType)m_PVRDenoiserTypeIndirect.intValue))\n                                        {\n                                            EditorGUILayout.HelpBox(Styles.denoiserNotSupportedWarning.text, MessageType.Info);\n                                        }\n                                    }\n                                    EditorGUILayout.PropertyField(m_PVRFilterTypeIndirect, Styles.filterTypeIndirect);\n\n                                    if (!m_PVRFilterTypeIndirect.hasMultipleDifferentValues)\n                                    {\n                                        EditorGUI.indentLevel++;\n                                        DrawFilterSettingField(m_PVRFilteringGaussRadiusIndirect,\n                                            m_PVRFilteringAtrousPositionSigmaIndirect,\n                                            Styles.filteringGaussRadiusIndirect,\n                                            Styles.filteringAtrousPositionSigmaIndirect,\n                                            (LightingSettings.FilterType)m_PVRFilterTypeIndirect.intValue);\n                                        EditorGUI.indentLevel--;\n                                    }\n\n                                    using (new EditorGUI.DisabledScope(!m_AmbientOcclusion.boolValue))\n                                    {\n                                        EditorGUILayout.Space();\n\n                                        using (new EditorGUI.DisabledScope(!anyDenoisingSupported))\n                                        {\n                                            DrawDenoiserTypeDropdown(m_PVRDenoiserTypeAO, anyDenoisingSupported ? Styles.denoiserTypeAO : Styles.denoisingWarningAO, DenoiserTarget.AO);\n\n                                            if (m_AmbientOcclusion.boolValue && anyDenoisingSupported && !DenoiserSupported((LightingSettings.DenoiserType)m_PVRDenoiserTypeAO.intValue))\n                                            {\n                                                EditorGUILayout.HelpBox(Styles.denoiserNotSupportedWarning.text, MessageType.Info);\n                                            }\n                                        }\n                                        EditorGUILayout.PropertyField(m_PVRFilterTypeAO, Styles.filterTypeAO);\n\n                                        if (!m_PVRFilterTypeAO.hasMultipleDifferentValues)\n                                        {\n                                            EditorGUI.indentLevel++;\n                                            DrawFilterSettingField(m_PVRFilteringGaussRadiusAO,\n                                                m_PVRFilteringAtrousPositionSigmaAO,\n                                                Styles.filteringGaussRadiusAO, Styles.filteringAtrousPositionSigmaAO,\n                                                (LightingSettings.FilterType)m_PVRFilterTypeAO.intValue);\n                                            EditorGUI.indentLevel--;\n                                        }\n                                    }\n\n                                    EditorGUI.indentLevel--;\n                                }\n\n                                EditorGUI.indentLevel--;\n                            }\n                        }\n                    }\n\n                    if (bakedGISupported)\n                    {\n                        using (new EditorGUI.DisabledScope(!enableBakedGI))\n                        {\n                            DrawPropertyFieldWithPostfixLabel(m_BakeResolution, Styles.lightmapResolution, Styles.texelsPerUnit);\n\n                            DrawPropertyFieldWithPostfixLabel(m_Padding, Styles.padding, Styles.texels);\n\n                            EditorGUILayout.IntPopup(m_LightmapMaxSize, Styles.lightmapMaxSizeStrings, Styles.lightmapMaxSizeValues, Styles.lightmapMaxSize);\n\n                            EditorGUILayout.PropertyField(m_LightmapSizeFixed, Styles.lightmapSizeFixed);\n\n                            EditorGUILayout.PropertyField(m_UseMipmapLimits, Styles.useMipmapLimits);\n\n                            EditorGUILayout.IntPopup(m_LightmapCompression, Styles.lightmapCompressionStrings, Styles.lightmapCompressionValues, Styles.lightmapCompression);\n\n                            EditorGUILayout.PropertyField(m_AmbientOcclusion, Styles.ambientOcclusion);\n                            if (m_AmbientOcclusion.boolValue)\n                            {\n                                EditorGUI.indentLevel++;\n                                EditorGUILayout.PropertyField(m_AOMaxDistance, Styles.AOMaxDistance);\n                                EditorGUILayout.Slider(m_CompAOExponent, 0.0f, 10.0f, Styles.ambientOcclusionContribution);\n                                EditorGUILayout.Slider(m_CompAOExponentDirect, 0.0f, 10.0f, Styles.ambientOcclusionContributionDirect);\n\n                                EditorGUI.indentLevel--;\n                            }\n                        }\n                    }\n\n                    bool directionalSupported = SupportedRenderingFeatures.IsLightmapsModeSupported(LightmapsMode.CombinedDirectional);\n\n                    if (directionalSupported || (m_LightmapDirectionalMode.intValue == (int)LightmapsMode.CombinedDirectional))\n                    {\n                        EditorGUILayout.IntPopup(m_LightmapDirectionalMode, Styles.lightmapDirectionalModeStrings, Styles.lightmapDirectionalModeValues, Styles.lightmapDirectionalMode);\n\n                        if (!directionalSupported)\n                        {\n                            EditorGUILayout.HelpBox(Styles.directionalNotSupportedWarning.text, MessageType.Warning);\n                        }\n                    }\n                    else\n                    {\n                        using (new EditorGUI.DisabledScope(true))\n                        {\n                            EditorGUILayout.IntPopup(Styles.lightmapDirectionalMode, 0, Styles.lightmapDirectionalModeStrings, Styles.lightmapDirectionalModeValues);\n                        }\n                    }\n\n                    // albedo boost, push the albedo value towards one in order to get more bounce\n                    EditorGUILayout.Slider(m_AlbedoBoost, 1.0f, 10.0f, Styles.albedoBoost);\n                    EditorGUILayout.Slider(m_IndirectOutputScale, 0.0f, 5.0f, Styles.indirectOutputScale);\n\n                    LightmapParametersGUI(m_LightmapParameters, Styles.lightmapParameters);\n                }\n\n                EditorGUI.indentLevel--;\n                EditorGUILayout.Space();\n            }\n\n            if (compact)\n                EditorGUILayout.EndFoldoutHeaderGroup();\n        }\n\n        void InternalSettingsGUI(bool compact)\n        {\n            if (!Unsupported.IsDeveloperMode())\n                return;\n\n            if (compact)\n                m_ShowInternalSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_ShowInternalSettings.value, Styles.internalLabel);\n            else\n                m_ShowInternalSettings.value = EditorGUILayout.FoldoutTitlebar(m_ShowInternalSettings.value, Styles.internalLabel, true);\n\n            if (m_ShowInternalSettings.value)\n            {\n                bool enableRealtimeGI = (m_EnableRealtimeGI.boolValue && !m_EnableRealtimeGI.hasMultipleDifferentValues);\n                EditorGUI.indentLevel++;\n                if (enableRealtimeGI)\n                {\n                    EditorGUILayout.PropertyField(m_ForceWhiteAlbedo, Styles.forceWhiteAlbedo);\n                    EditorGUILayout.PropertyField(m_ForceUpdates, Styles.forceUpdates);\n                }\n\n                EditorGUILayout.PropertyField(m_EnableWorkerProcessBaking, Styles.enableWorkerProcessBaking);\n\n                EditorGUILayout.PropertyField(m_ExportTrainingData, Styles.exportTrainingData);\n\n                if (m_ExportTrainingData.boolValue && !m_ExportTrainingData.hasMultipleDifferentValues)\n                {\n                    EditorGUI.indentLevel++;\n                    EditorGUILayout.PropertyField(m_TrainingDataDestination, Styles.trainingDataDestination);\n                    EditorGUI.indentLevel--;\n                }\n\n                EditorGUILayout.PropertyField(m_FilterMode, Styles.filterMode);\n                if (enableRealtimeGI)\n                {\n                    EditorGUILayout.Slider(m_BounceScale, 0.0f, 10.0f, Styles.bounceScale);\n                }\n\n                Lightmapping.concurrentJobsType = (Lightmapping.ConcurrentJobsType)EditorGUILayout.IntPopup(Styles.concurrentJobs, (int)Lightmapping.concurrentJobsType, Styles.concurrentJobsTypeStrings, Styles.concurrentJobsTypeValues);\n\n                EditorGUILayout.BeginHorizontal();\n                GUILayout.Space(EditorGUI.indent + 4);\n                EditorGUILayout.BeginVertical();\n\n                if (GUILayout.Button(\"Clear disk cache\", GUILayout.Width(Styles.buttonWidth)))\n                {\n                    Lightmapping.Clear();\n                    Lightmapping.ClearDiskCache();\n                }\n\n                if (GUILayout.Button(\"Print state to console\", GUILayout.Width(Styles.buttonWidth)))\n                {\n                    Lightmapping.PrintStateToConsole();\n                }\n\n                if (GUILayout.Button(\"Reset albedo/emissive\", GUILayout.Width(Styles.buttonWidth)))\n                    GIDebugVisualisation.ResetRuntimeInputTextures();\n\n                if (GUILayout.Button(\"Reset environment\", GUILayout.Width(Styles.buttonWidth)))\n                    DynamicGI.UpdateEnvironment();\n\n                EditorGUILayout.EndVertical();\n                EditorGUILayout.EndHorizontal();\n\n                EditorGUI.indentLevel--;\n                EditorGUILayout.Space();\n            }\n\n            if (compact)\n                EditorGUILayout.EndFoldoutHeaderGroup();\n        }\n\n        // Helper methods\n\n        static void DrawPropertyFieldWithPostfixLabel(SerializedProperty property, GUIContent label, GUIContent postfixLabel)\n        {\n            const float minimumWidth = 170.0f;\n            const float postfixLabelWidth = 80.0f;\n\n            DrawFieldWithPostfixLabel(\n                (Rect propertyRect) => { EditorGUI.PropertyField(propertyRect, property, label); },\n                postfixLabel,\n                EditorStyles.numberField,\n                minimumWidth,\n                postfixLabelWidth);\n        }\n\n        static void DrawFilterSettingField(SerializedProperty gaussSetting,\n            SerializedProperty atrousSetting,\n            GUIContent gaussLabel,\n            GUIContent atrousLabel,\n            LightingSettings.FilterType type)\n        {\n            const float minimumWidth = 230.0f;\n            const float postfixLabelWidth = 40.0f;\n\n            switch(type)\n            {\n                case LightingSettings.FilterType.Gaussian:\n                    DrawFieldWithPostfixLabel(\n                            (Rect propertyRect) => { EditorGUI.Slider(propertyRect, gaussSetting, 0.0f, 5.0f, gaussLabel); },\n                            Styles.texels,\n                            EditorStyles.toolbarSlider,\n                            minimumWidth,\n                            postfixLabelWidth);\n                    break;\n\n                case LightingSettings.FilterType.ATrous:\n                    DrawFieldWithPostfixLabel(\n                            (Rect propertyRect) => { EditorGUI.Slider(propertyRect, atrousSetting, 0.0f, 2.0f, atrousLabel); },\n                            Styles.sigma,\n                            EditorStyles.toolbarSlider,\n                            minimumWidth,\n                            postfixLabelWidth);\n                    break;\n            }\n        }\n\n        static void DrawFieldWithPostfixLabel(Action<Rect> drawFieldLambda, GUIContent postfixLabel, GUIStyle style, float minWidth, float postfixLabelWidth)\n        {\n            Rect propertyRect = GUILayoutUtility.GetRect(\n                EditorGUILayout.kLabelFloatMinW,\n                EditorGUILayout.kLabelFloatMaxW,\n                EditorGUI.kSingleLineHeight,\n                EditorGUI.kSingleLineHeight,\n                style);\n\n            propertyRect.width = Mathf.Max(propertyRect.width - postfixLabelWidth, minWidth);\n\n            drawFieldLambda(propertyRect);\n\n            int indent = EditorGUI.indentLevel;\n            EditorGUI.indentLevel = 0;\n\n            Rect labelRect = propertyRect;\n            labelRect.x += propertyRect.width;\n            EditorGUI.LabelField(labelRect, postfixLabel, Styles.labelStyle);\n\n            EditorGUI.indentLevel = indent;\n        }\n\n        static bool isBuiltIn(SerializedProperty prop)\n        {\n            if (prop.objectReferenceValue != null)\n            {\n                var parameters = prop.objectReferenceValue as LightmapParameters;\n                return (parameters.hideFlags == HideFlags.NotEditable);\n            }\n\n            return true;\n        }\n\n        private class DoCreateNewLightmapParameters : ProjectWindowCallback.DoCreateNewAsset\n        {\n            public override void Action(int instanceId, string pathName, string resourceFile)\n            {\n                base.Action(instanceId, pathName, resourceFile);\n\n                // Only assign the new parameters asset once it is fully imported.\n                if (EditorUtility.InstanceIDToObject(instanceId) is LightmapParameters lmp)\n                    lmp.AssignToLightingSettings(Lightmapping.lightingSettingsInternal);\n            }\n        }\n\n        void CreateLightmapParameters(LightmapParameters from = null)\n        {\n            string newName = L10n.Tr(\"New Lightmap Parameters\");\n\n            LightmapParameters lmp;\n            if (from == null)\n            {\n                lmp = new LightmapParameters();\n                lmp.name = newName;\n            }\n            else\n            {\n                lmp = Object.Instantiate(from);\n                lmp.name = from.name;\n            }\n            Undo.RecordObject(m_LightmapParameters.objectReferenceValue, newName);\n            ProjectWindowUtil.StartNameEditingIfProjectWindowExists(\n                lmp.GetInstanceID(),\n                ScriptableObject.CreateInstance<DoCreateNewLightmapParameters>(),\n                (lmp.name + \".giparams\"),\n                AssetPreview.GetMiniThumbnail(lmp),\n                null);\n        }\n\n        void LightmapParametersGUI(SerializedProperty prop, GUIContent content)\n        {\n            GUILayout.BeginHorizontal();\n\n            EditorGUILayout.PropertyField(prop);\n\n            if (GUILayout.Button(Styles.newLightmapParameters, EditorStyles.miniButtonLeft, GUILayout.Width(50)))\n                CreateLightmapParameters();\n            else if (GUILayout.Button(Styles.cloneLightmapParameters, EditorStyles.miniButtonRight, GUILayout.Width(50)))\n                CreateLightmapParameters(prop.objectReferenceValue as LightmapParameters);\n\n            GUILayout.EndHorizontal();\n        }\n\n        static bool DenoiserSupported(LightingSettings.DenoiserType denoiserType)\n        {\n            if (denoiserType == LightingSettings.DenoiserType.Optix && !Lightmapping.IsOptixDenoiserSupported())\n                return false;\n            if (denoiserType == LightingSettings.DenoiserType.OpenImage && !Lightmapping.IsOpenImageDenoiserSupported())\n                return false;\n\n            return true;\n        }\n\n        void OnMixedModeSelected(object userData)\n        {\n            m_MixedBakeMode.intValue = (int)userData;\n            m_MixedBakeMode.serializedObject.ApplyModifiedProperties();\n        }\n\n        void OnBakeBackedSelected(object userData)\n        {\n            m_BakeBackend.intValue = (int)userData;\n            m_BakeBackend.serializedObject.ApplyModifiedProperties();\n        }\n\n        void BakeBackendGUI()\n        {\n            bool isOpenRLFunctionalForArchitecture = RuntimeInformation.ProcessArchitecture == Architecture.X64;\n            var rect = EditorGUILayout.GetControlRect();\n            EditorGUI.BeginProperty(rect, Styles.bakeBackend, m_BakeBackend);\n            EditorGUI.BeginChangeCheck();\n            rect = EditorGUI.PrefixLabel(rect, Styles.bakeBackend);\n\n            int index = Math.Max(0, Array.IndexOf(Styles.bakeBackendValues, m_BakeBackend.intValue));\n\n            if (EditorGUI.DropdownButton(rect, Styles.bakeBackendStrings[index], FocusType.Passive))\n            {\n                var menu = new GenericMenu();\n\n                for (int i = Styles.bakeBackendValues.Length - 1; i >= 0; i--)\n                {\n                    int value = Styles.bakeBackendValues[i];\n                    bool selected = (value == m_BakeBackend.intValue);\n\n                    if (!SupportedRenderingFeatures.IsLightmapperSupported(value) || (!isOpenRLFunctionalForArchitecture && value == (int)LightingSettings.Lightmapper.ProgressiveCPU))\n                    {\n                        menu.AddDisabledItem(Styles.bakeBackendStrings[i], selected);\n                    }\n                    else\n                    {\n                        menu.AddItem(Styles.bakeBackendStrings[i], selected, OnBakeBackedSelected, value);\n                    }\n                }\n                menu.DropDown(rect);\n            }\n\n            if (EditorGUI.EndChangeCheck())\n                InspectorWindow.RepaintAllInspectors(); // We need to repaint other inspectors that might need to update based on the selected backend.\n\n            EditorGUI.EndProperty();\n\n            if (!isOpenRLFunctionalForArchitecture && m_BakeBackend.intValue == (int)LightingSettings.Lightmapper.ProgressiveCPU)\n            {\n                EditorGUILayout.HelpBox(Styles.appleSiliconCPULightmapperWarning.text, MessageType.Warning);\n            }\n            else if (!SupportedRenderingFeatures.IsLightmapperSupported(m_BakeBackend.intValue))\n            {\n                string fallbackLightmapper = Styles.bakeBackendStrings[SupportedRenderingFeatures.FallbackLightmapper()].text;\n                EditorGUILayout.HelpBox(Styles.lightmapperNotSupportedWarning.text + fallbackLightmapper + \" Lightmapper instead.\", MessageType.Warning);\n            }\n        }\n\n        void OnDirectDenoiserSelected(object userData)\n        {\n            m_PVRDenoiserTypeDirect.intValue = (int)userData;\n            m_PVRDenoiserTypeDirect.serializedObject.ApplyModifiedProperties();\n        }\n\n        void OnIndirectDenoiserSelected(object userData)\n        {\n            m_PVRDenoiserTypeIndirect.intValue = (int)userData;\n            m_PVRDenoiserTypeIndirect.serializedObject.ApplyModifiedProperties();\n        }\n\n        void OnAODenoiserSelected(object userData)\n        {\n            m_PVRDenoiserTypeAO.intValue = (int)userData;\n            m_PVRDenoiserTypeAO.serializedObject.ApplyModifiedProperties();\n        }\n\n        void DrawDenoiserTypeDropdown(SerializedProperty prop, GUIContent label, DenoiserTarget target)\n        {\n            var rect = EditorGUILayout.GetControlRect();\n            EditorGUI.BeginProperty(rect, label, prop);\n            rect = EditorGUI.PrefixLabel(rect, label);\n\n            int index = Math.Max(0, Array.IndexOf(Styles.denoiserTypeValues, prop.intValue));\n\n            if (EditorGUI.DropdownButton(rect, Styles.denoiserTypeStrings[index], FocusType.Passive))\n            {\n                var menu = new GenericMenu();\n\n                for (int i = 0; i < Styles.denoiserTypeValues.Length; i++)\n                {\n                    int value = Styles.denoiserTypeValues[i];\n                    bool denoiserSupported = DenoiserSupported((LightingSettings.DenoiserType)value);\n                    bool selected = (value == prop.intValue);\n\n                    if (!denoiserSupported)\n                        menu.AddDisabledItem(Styles.denoiserTypeStrings[i], selected);\n                    else\n                    {\n                        if (target == DenoiserTarget.Direct)\n                            menu.AddItem(Styles.denoiserTypeStrings[i], selected, OnDirectDenoiserSelected, value);\n                        else if (target == DenoiserTarget.Indirect)\n                            menu.AddItem(Styles.denoiserTypeStrings[i], selected, OnIndirectDenoiserSelected, value);\n                        else if (target == DenoiserTarget.AO)\n                            menu.AddItem(Styles.denoiserTypeStrings[i], selected, OnAODenoiserSelected, value);\n                    }\n                }\n                menu.DropDown(rect);\n            }\n            EditorGUI.EndProperty();\n        }\n\n        int MultiEditableLogarithmicIntSlider(SerializedProperty property, GUIContent style, int min, int max, int textFieldMin, int textFieldMax)\n        {\n            if (property.hasMultipleDifferentValues)\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = true;\n\n                int newValue = EditorGUILayout.LogarithmicIntSlider(style, property.intValue, min, max, 2, textFieldMin, textFieldMax);\n                if (EditorGUI.EndChangeCheck())\n                    property.intValue = newValue;\n\n                EditorGUI.showMixedValue = false;\n            }\n            else\n                property.intValue = EditorGUILayout.LogarithmicIntSlider(style, property.intValue, min, max, 2, textFieldMin, textFieldMax);\n\n            return property.intValue;\n        }\n\n        internal void ClampMaxRanges()\n        {\n            maxDirectSamples = Mathf.Max(m_PVRDirectSampleCount.intValue, 1024);\n            maxIndirectSamples = Mathf.Max(m_PVRSampleCount.intValue, 8192);\n            maxEnvironmentSamples = Mathf.Max(m_PVREnvironmentSampleCount.intValue, 2048);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LineRendererCurveEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class LineRendererCurveEditor\n    {\n        private class Styles\n        {\n            public static GUIContent widthMultiplier = EditorGUIUtility.TrTextContent(\"Width\", \"The multiplier applied to the curve, describing the width (in world space) along the line.\");\n        }\n\n        private bool m_Refresh = false;\n        private CurveEditor m_Editor = null;\n        private CurveEditorSettings m_Settings = new CurveEditorSettings();\n\n        private SerializedProperty m_WidthMultiplier;\n        private SerializedProperty m_WidthCurve;\n\n        public void OnEnable(SerializedObject serializedObject)\n        {\n            m_WidthMultiplier = serializedObject.FindProperty(\"m_Parameters.widthMultiplier\");\n            m_WidthCurve = serializedObject.FindProperty(\"m_Parameters.widthCurve\");\n\n            m_Settings.hRangeMin = 0.0f;\n            m_Settings.vRangeMin = 0.0f;\n            m_Settings.vRangeMax = 1.0f;\n            m_Settings.hRangeMax = 1.0f;\n            m_Settings.vSlider = false;\n            m_Settings.hSlider = false;\n            m_Settings.rectangleToolFlags = CurveEditorSettings.RectangleToolFlags.MiniRectangleTool;\n            m_Settings.allowDeleteLastKeyInCurve = false;\n\n            TickStyle hTS = new TickStyle();\n            hTS.tickColor.color = new Color(0.0f, 0.0f, 0.0f, 0.15f);\n            hTS.distLabel = 30;\n            hTS.stubs = false;\n            m_Settings.hTickStyle = hTS;\n            TickStyle vTS = new TickStyle();\n            vTS.tickColor.color = new Color(0.0f, 0.0f, 0.0f, 0.15f);\n            vTS.distLabel = 20;\n            vTS.stubs = false;\n            m_Settings.vTickStyle = vTS;\n\n            m_Settings.undoRedoSelection = true;\n\n            m_Editor = new CurveEditor(new Rect(0, 0, 1000, 100), new CurveWrapper[0], false);\n            m_Editor.settings = m_Settings;\n            m_Editor.margin = 25;\n            m_Editor.leftmargin = 35;\n            m_Editor.SetShownHRangeInsideMargins(0.0f, 1.0f);\n            m_Editor.SetShownVRangeInsideMargins(0.0f, 1.0f);\n            m_Editor.ignoreScrollWheelUntilClicked = true;\n\n            Undo.undoRedoEvent += UndoRedoPerformed;\n        }\n\n        public void OnDisable()\n        {\n            m_Editor.OnDisable();\n            Undo.undoRedoEvent -= UndoRedoPerformed;\n        }\n\n        private CurveWrapper GetCurveWrapper(AnimationCurve curve)\n        {\n            float colorMultiplier = !EditorGUIUtility.isProSkin ? 0.9f : 1.0f;\n            Color colorMult = new Color(colorMultiplier, colorMultiplier, colorMultiplier, 1);\n\n            CurveWrapper wrapper = new CurveWrapper();\n            wrapper.id = 0;\n            wrapper.groupId = -1;\n            wrapper.color = new Color(1.0f, 0.0f, 0.0f, 1.0f) * colorMult;\n            wrapper.hidden = false;\n            wrapper.readOnly = false;\n            wrapper.renderer = new NormalCurveRenderer(curve);\n            wrapper.renderer.SetCustomRange(0.0f, 1.0f);\n            wrapper.getAxisUiScalarsCallback = GetAxisScalars;\n            wrapper.setAxisUiScalarsCallback = SetAxisScalars;\n            return wrapper;\n        }\n\n        public Vector2 GetAxisScalars()\n        {\n            return new Vector2(1.0f, m_WidthMultiplier.floatValue);\n        }\n\n        public void SetAxisScalars(Vector2 scalars)\n        {\n            m_WidthMultiplier.floatValue = scalars.y;\n            m_Refresh = true;\n        }\n\n        private void UndoRedoPerformed(in UndoRedoInfo info)\n        {\n            m_Refresh = true;\n        }\n\n        public void CheckCurveChangedExternally()\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            CurveWrapper cw = m_Editor.GetCurveWrapperFromID(0);\n            if (m_WidthCurve != null)\n            {\n                AnimationCurve propCurve = m_WidthCurve.animationCurveValue;\n                if ((cw == null) != m_WidthCurve.hasMultipleDifferentValues)\n                {\n                    m_Refresh = true;\n                }\n                else if (cw != null)\n                {\n                    if (cw.curve.length == 0 || cw.curve.length != propCurve.length)\n                    {\n                        m_Refresh = true;\n                    }\n                    else\n                    {\n                        var curveKeys = cw.curve.keys;\n                        var propKeys = propCurve.keys;\n\n                        for (int i = 0; i < curveKeys.Length; i++)\n                        {\n                            if (!propKeys[i].Equals(curveKeys[i]))\n                            {\n                                m_Refresh = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n            else if (cw != null)\n            {\n                m_Refresh = true;\n            }\n        }\n\n        public void OnInspectorGUI()\n        {\n            Rect r = GUILayoutUtility.GetAspectRect(2, GUI.skin.textField);\n            r.xMin += EditorGUI.indent;\n            if (Event.current.type != EventType.Layout && Event.current.type != EventType.Used)\n            {\n                m_Editor.rect = new Rect(r.x, r.y, r.width, r.height);\n            }\n\n            // Draw Curve Editor\n            if (m_Refresh)\n            {\n                m_Editor.animationCurves = new CurveWrapper[] { GetCurveWrapper(m_WidthCurve.animationCurveValue) };\n                m_Refresh = false;\n            }\n\n            GUI.Label(m_Editor.drawRect, GUIContent.none, \"TextField\");\n\n            m_Editor.hRangeLocked = Event.current.shift;\n            m_Editor.vRangeLocked = EditorGUI.actionKey;\n\n            m_Editor.OnGUI();\n\n            var labelRect = new Rect(r.x + 4, r.y, r.width, EditorGUI.kSingleLineHeight);\n            EditorGUI.LabelField(labelRect, Styles.widthMultiplier);\n\n            // Apply curve changes\n            if ((m_Editor.GetCurveWrapperFromID(0) != null) && (m_Editor.GetCurveWrapperFromID(0).changed))\n            {\n                AnimationCurve changedCurve = m_Editor.GetCurveWrapperFromID(0).curve;\n\n                // Never save a curve with no keys\n                if (changedCurve.length > 0)\n                {\n                    m_WidthCurve.animationCurveValue = changedCurve;\n                    m_Editor.GetCurveWrapperFromID(0).changed = false;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LineRendererEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.AnimatedValues;\nusing UnityEditor.EditorTools;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(LineRenderer))]\n    [CanEditMultipleObjects]\n    internal class LineRendererInspector : RendererEditorBase\n    {\n        class Styles\n        {\n            public static readonly GUIContent alignment = EditorGUIUtility.TrTextContent(\"Alignment\", \"Lines can rotate to face their transform component or the camera. When using Local mode, lines face the XY plane of the Transform.\");\n            public static readonly GUIContent colorGradient = EditorGUIUtility.TrTextContent(\"Color\", \"The gradient describing the color along the line.\");\n            public static readonly string disabledEditMessage = L10n.Tr(\"Editing is only available when editing a single LineRenderer in a scene.\");\n            public static readonly GUIContent inputMode = EditorGUIUtility.TrTextContent(\"Input\", \"Use mouse position or physics raycast to determine where to create points.\");\n            public static readonly GUIContent layerMask = EditorGUIUtility.TrTextContent(\"Layer Mask\", \"The layer mask to use when performing raycasts.\");\n            public static readonly GUIContent normalOffset = EditorGUIUtility.TrTextContent(\"Offset\", \"The offset applied to created points either from the scene camera or raycast normal, when using physics.\");\n            public static readonly GUIContent numCapVertices = EditorGUIUtility.TrTextContent(\"End Cap Vertices\", \"How many vertices to add at each end.\");\n            public static readonly GUIContent numCornerVertices = EditorGUIUtility.TrTextContent(\"Corner Vertices\", \"How many vertices to add for each corner.\");\n            public static readonly GUIContent pointSeparation = EditorGUIUtility.TrTextContent(\"Min Vertex Distance\", \"When dragging the mouse, a new point will be created after the distance has been exceeded.\");\n            public static readonly GUIContent positions = EditorGUIUtility.TrTextContent(\"Positions\");\n            public static readonly GUIContent propertyMenuContent = EditorGUIUtility.TrTextContent(\"Delete Selected Array Elements\");\n            public static readonly GUIContent showWireframe = EditorGUIUtility.TrTextContent(\"Show Wireframe\", \"Show the wireframe visualizing the line.\");\n            public static readonly GUIContent simplify = EditorGUIUtility.TrTextContent(\"Simplify\", \"Generates a simplified version of the original line by removing points that fall within the specified tolerance.\");\n            public static readonly GUIContent simplifyPreview = EditorGUIUtility.TrTextContent(\"Simplify Preview\", \"Show a preview of the simplified version of the line.\");\n            public static readonly GUIContent subdivide = EditorGUIUtility.TrTextContent(\"Subdivide Selected\" , \"Inserts a new point in between selected adjacent points.\");\n            public static readonly GUIContent textureMode = EditorGUIUtility.TrTextContent(\"Texture Mode\", \"Should the U coordinate be stretched or tiled?\");\n            public static readonly GUIContent textureScale = EditorGUIUtility.TrTextContent(\"Texture Scale\", \"Scale the texture along the UV coordinates using this multiplier.\");\n            public static readonly GUIContent tolerance = EditorGUIUtility.TrTextContent(\"Tolerance\", \"Used to evaluate which points should be removed from the line. A higher value results in a simpler line (fewer points). A value of 0 results in the exact same line with little to no reduction.\");\n            public static readonly GUIContent shadowBias = EditorGUIUtility.TrTextContent(\"Shadow Bias\", \"Apply a shadow bias to prevent self-shadowing artifacts. The specified value is the proportion of the line width at each segment.\");\n            public static readonly GUIContent generateLightingData = EditorGUIUtility.TrTextContent(\"Generate Lighting Data\", \"Toggle generation of normal and tangent data, for use in lit shaders.\");\n            public static readonly GUIContent sceneTools = EditorGUIUtility.TrTextContent(\"Scene Tools\");\n            public static readonly GUIContent applyActiveColorSpace = EditorGUIUtility.TrTextContent(\"Apply Active Color Space\", \"When using Linear Rendering, colors will be converted appropriately before being passed to the GPU.\");\n        }\n\n        abstract class LineRendererTool : EditorTool\n        {\n            protected LineRendererEditor pointEditor\n            {\n                get\n                {\n                    if (m_PointEditor == null)\n                        m_PointEditor = new LineRendererEditor(target as LineRenderer);\n                    return m_PointEditor;\n                }\n            }\n\n            public override void OnActivated()\n            {\n                pointEditor.Deselect();\n            }\n\n            public override void OnWillBeDeactivated()\n            {\n                pointEditor.Deselect();\n            }\n\n            public void RemoveInvalidSelections()\n            {\n                pointEditor.RemoveInvalidSelections();\n            }\n\n            public List<int> pointSelection\n            {\n                set => pointEditor.m_Selection = value;\n                get => pointEditor.m_Selection;\n            }\n\n            public Bounds selectedPositionsBounds\n            {\n                get => pointEditor.selectedPositionsBounds;\n            }\n\n            public override bool IsAvailable()\n            {\n                return !targets.Skip(1).Any(); // TODO - multi-edit disabled for now. Need to make LineRendererEditor support multiple targets, and fix m_IsGameObjectEditable\n            }\n\n            public abstract void DrawToolbar(SerializedProperty positions);\n            public virtual void OnSceneGUIDelegate(SerializedProperty positions, LineRendererPositionsView positionsView) { }\n\n            private LineRendererEditor m_PointEditor;\n        }\n\n        [EditorTool(\"Edit Points\", typeof(LineRenderer))]\n        class LineRendererEditPointsTool : LineRendererTool\n        {\n            public override GUIContent toolbarIcon\n            {\n                get { return EditorGUIUtility.TrIconContent(\"EditCollider\", \"Edit LineRenderer Points in the Scene View.\"); }\n            }\n\n            public override void OnToolGUI(EditorWindow window)\n            {\n                pointEditor.EditSceneGUI(window);\n            }\n\n            public override void DrawToolbar(SerializedProperty positions)\n            {\n                EditorGUI.BeginChangeCheck();\n                LineRendererEditor.showWireframe = GUILayout.Toggle(LineRendererEditor.showWireframe, Styles.showWireframe);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    SceneView.RepaintAll();\n                }\n\n                bool adjacentPointsSelected = HasAdjacentPointsSelected();\n                using (new EditorGUI.DisabledGroupScope(!adjacentPointsSelected))\n                {\n                    GUILayout.BeginHorizontal();\n                    GUILayout.FlexibleSpace();\n                    if (GUILayout.Button(Styles.subdivide, GUILayout.Width(150)))\n                    {\n                        SubdivideSelected(positions);\n                    }\n                    GUILayout.EndHorizontal();\n                }\n            }\n\n            public override void OnSceneGUIDelegate(SerializedProperty positions, LineRendererPositionsView positionsView)\n            {\n                // We need to wait for m_Positions to be updated next frame or we risk calling SetSelection with invalid indexes.\n                if (pointEditor.Count == positions.arraySize)\n                {\n                    if (positions.arraySize != positionsView.GetRows().Count)\n                        positionsView.Reload();\n                    positionsView.SetSelection(pointSelection, TreeViewSelectionOptions.RevealAndFrame);\n                }\n            }\n\n            private bool HasAdjacentPointsSelected()\n            {\n                var selection = pointSelection;\n                selection.Sort();\n                if (selection.Count < 2)\n                    return false;\n\n                for (int i = 0; i < selection.Count - 1; ++i)\n                {\n                    if (selection[i + 1] == selection[i] + 1)\n                        return true;\n                }\n\n                return false;\n            }\n\n            private void SubdivideSelected(SerializedProperty positions)\n            {\n                var selection = pointSelection;\n                if (selection.Count < 2)\n                    return;\n                selection.Sort();\n                var insertedIndexes = new List<int>();\n                int numInserted = 0; // As we insert new nodes, the selected indexes will become offset so we need to keep track of this.\n                for (int i = 0; i < selection.Count - 1; ++i)\n                {\n                    if (selection[i + 1] == selection[i] + 1)\n                    {\n                        int fromIndex = selection[i] + numInserted;\n                        int toIndex = selection[i + 1] + numInserted;\n                        var from = positions.GetArrayElementAtIndex(fromIndex).vector3Value;\n                        var to = positions.GetArrayElementAtIndex(toIndex).vector3Value;\n                        var midPoint = Vector3.Lerp(from, to, 0.5f);\n                        positions.InsertArrayElementAtIndex(toIndex);\n                        positions.GetArrayElementAtIndex(toIndex).vector3Value = midPoint;\n                        insertedIndexes.Add(toIndex);\n                        numInserted++;\n                    }\n                }\n\n                pointSelection = insertedIndexes;\n            }\n        }\n\n        [EditorTool(\"Add Points\", typeof(LineRenderer))]\n        class LineRendererAddPointsTool : LineRendererTool\n        {\n            public override GUIContent toolbarIcon\n            {\n                get { return EditorGUIUtility.TrIconContent(\"Toolbar Plus\", \"Create LineRenderer Points in the Scene View.\"); }\n            }\n\n            public override void OnToolGUI(EditorWindow window)\n            {\n                pointEditor.CreateSceneGUI();\n            }\n\n            public override void DrawToolbar(SerializedProperty positions)\n            {\n                LineRendererEditor.inputMode = (LineRendererEditor.InputMode)EditorGUILayout.EnumPopup(Styles.inputMode, LineRendererEditor.inputMode);\n                if (LineRendererEditor.inputMode == LineRendererEditor.InputMode.PhysicsRaycast)\n                {\n                    LineRendererEditor.raycastMask = EditorGUILayout.LayerMaskField(LineRendererEditor.raycastMask, Styles.layerMask);\n                }\n\n                LineRendererEditor.createPointSeparation = EditorGUILayout.FloatField(Styles.pointSeparation, LineRendererEditor.createPointSeparation);\n                LineRendererEditor.creationOffset = EditorGUILayout.FloatField(Styles.normalOffset, LineRendererEditor.creationOffset);\n            }\n        }\n\n        public static float simplifyTolerance\n        {\n            get { return EditorPrefs.GetFloat(\"LineRendererInspectorSimplifyTolerance\", 1.0f); }\n            set { EditorPrefs.SetFloat(\"LineRendererInspectorSimplifyTolerance\", value < 0 ? 0 : value); }\n        }\n\n        public static bool showSimplifyPreview\n        {\n            get { return EditorPrefs.GetBool(\"LineRendererEditorShowSimplifyPreview\", false); }\n            set { EditorPrefs.SetBool(\"LineRendererEditorShowSimplifyPreview\", value); }\n        }\n\n        private Vector3[] m_PreviewPoints;\n\n        private LineRendererCurveEditor m_CurveEditor = new LineRendererCurveEditor();\n\n        private SerializedProperty m_Alignment;\n        private SerializedProperty m_ColorGradient;\n        private SerializedProperty m_ShadowBias;\n        private SerializedProperty m_GenerateLightingData;\n        private SerializedProperty m_Loop;\n        private SerializedProperty m_ApplyActiveColorSpace;\n        private SerializedProperty m_NumCapVertices;\n        private SerializedProperty m_NumCornerVertices;\n        private SerializedProperty m_Positions;\n        private SerializedProperty m_PositionsSize;\n        private SerializedProperty m_TextureMode;\n        private SerializedProperty m_TextureScale;\n        private SerializedProperty m_UseWorldSpace;\n        private SerializedProperty m_MaskInteraction;\n\n        private LineRendererPositionsView m_PositionsView;\n\n        AnimBool m_ShowPositionsAnimation;\n\n        bool m_IsMultiEditing;\n        bool m_IsGameObjectEditable;\n\n        public static readonly float kPositionsViewMinHeight = 30;\n\n        private LineRendererTool activeSceneViewTool\n        {\n            get { return EditorToolManager.activeTool as LineRendererTool; }\n        }\n\n        private bool canEditInScene\n        {\n            get { return !m_IsMultiEditing && m_IsGameObjectEditable; }\n        }\n\n        public override void OnEnable()\n        {\n            base.OnEnable();\n\n            var lineRenderer = target as LineRenderer;\n\n            SceneView.duringSceneGui += OnSceneGUIDelegate;\n            Undo.undoRedoEvent += UndoRedoPerformed;\n            m_CurveEditor.OnEnable(serializedObject);\n\n            m_Loop = serializedObject.FindProperty(\"m_Loop\");\n            m_ApplyActiveColorSpace = serializedObject.FindProperty(\"m_ApplyActiveColorSpace\");\n            m_Positions = serializedObject.FindProperty(\"m_Positions\");\n            m_PositionsSize = serializedObject.FindProperty(\"m_Positions.Array.size\");\n            m_ColorGradient = serializedObject.FindProperty(\"m_Parameters.colorGradient\");\n            m_NumCornerVertices = serializedObject.FindProperty(\"m_Parameters.numCornerVertices\");\n            m_NumCapVertices = serializedObject.FindProperty(\"m_Parameters.numCapVertices\");\n            m_Alignment = serializedObject.FindProperty(\"m_Parameters.alignment\");\n            m_TextureMode = serializedObject.FindProperty(\"m_Parameters.textureMode\");\n            m_TextureScale = serializedObject.FindProperty(\"m_Parameters.textureScale\");\n            m_GenerateLightingData = serializedObject.FindProperty(\"m_Parameters.generateLightingData\");\n            m_ShadowBias = serializedObject.FindProperty(\"m_Parameters.shadowBias\");\n            m_UseWorldSpace = serializedObject.FindProperty(\"m_UseWorldSpace\");\n            m_MaskInteraction = serializedObject.FindProperty(\"m_MaskInteraction\");\n\n            m_PositionsView = new LineRendererPositionsView(m_Positions);\n            m_PositionsView.selectionChangedCallback += PositionsViewSelectionChanged;\n            if (targets.Length == 1)\n                m_PositionsView.lineRenderer = lineRenderer;\n\n            m_ShowPositionsAnimation = new AnimBool(false, Repaint) { value = m_Positions.isExpanded };\n            EditorApplication.contextualPropertyMenu += OnPropertyContextMenu;\n\n            // We cannot access isEditingMultipleObjects when drawing the SceneView so we need to cache it here for later use.\n            m_IsMultiEditing = serializedObject.isEditingMultipleObjects;\n            m_IsGameObjectEditable = (lineRenderer.gameObject.hideFlags & HideFlags.NotEditable) == 0;\n        }\n\n        void OnPropertyContextMenu(GenericMenu menu, SerializedProperty property)\n        {\n            if (m_PositionsView == null)\n                return;\n\n            if (property.propertyPath.Contains(\"m_Positions\") && m_PositionsView.GetSelection().Count > 1)\n            {\n                menu.AddItem(Styles.propertyMenuContent, false, () =>\n                {\n                    var selection = m_PositionsView.GetSelection().ToList();\n                    var query = selection.OrderByDescending(c => c);\n\n                    foreach (var index in query)\n                    {\n                        m_Positions.DeleteArrayElementAtIndex(index);\n                    }\n                    m_Positions.serializedObject.ApplyModifiedProperties();\n                    m_PositionsView.SetSelection(new int[0]);\n                    m_PositionsView.Reload();\n                    ResetSimplifyPreview();\n                });\n            }\n        }\n\n        void PositionsViewSelectionChanged(List<int> selected)\n        {\n            var sceneTool = activeSceneViewTool;\n            if (sceneTool != null)\n                sceneTool.pointSelection = selected;\n\n            SceneView.RepaintAll();\n        }\n\n        public void OnDisable()\n        {\n            m_CurveEditor.OnDisable();\n            Undo.undoRedoEvent -= UndoRedoPerformed;\n            SceneView.duringSceneGui -= OnSceneGUIDelegate;\n            EditorApplication.contextualPropertyMenu -= OnPropertyContextMenu;\n        }\n\n        private void UndoRedoPerformed(in UndoRedoInfo info)\n        {\n            m_PositionsView.Reload();\n\n            var sceneTool = activeSceneViewTool;\n            if (sceneTool != null)\n            {\n                sceneTool.RemoveInvalidSelections();\n                m_PositionsView.SetSelection(sceneTool.pointSelection);\n            }\n\n            ResetSimplifyPreview();\n        }\n\n        private void DrawToolbar()\n        {\n            if (!canEditInScene)\n            {\n                EditorGUILayout.HelpBox(Styles.disabledEditMessage, MessageType.Info);\n            }\n\n            EditorGUILayout.BeginVertical(\"GroupBox\");\n\n            EditorGUI.BeginDisabled(!canEditInScene);\n            EditorGUILayout.EditorToolbarForTarget(Styles.sceneTools, this);\n\n            // Editing mode toolbar\n            var sceneTools = activeSceneViewTool;\n            if (sceneTools != null)\n            {\n                sceneTools.DrawToolbar(m_Positions);\n            }\n            else\n            {\n                EditorGUI.BeginChangeCheck();\n                showSimplifyPreview = EditorGUILayout.Toggle(Styles.simplifyPreview, showSimplifyPreview);\n                EditorGUILayout.BeginHorizontal();\n                EditorGUILayout.PrefixLabel(Styles.tolerance);\n                simplifyTolerance = Mathf.Max(0, EditorGUILayout.FloatField(simplifyTolerance, GUILayout.MaxWidth(35.0f)));\n                if (GUILayout.Button(Styles.simplify, EditorStyles.miniButton))\n                {\n                    SimplifyPoints();\n                }\n                if (EditorGUI.EndChangeCheck())\n                {\n                    ResetSimplifyPreview();\n                    SceneView.RepaintAll();\n                }\n\n                EditorGUILayout.EndHorizontal();\n            }\n            EditorGUI.EndDisabled();\n\n            EditorGUILayout.EndVertical();\n        }\n\n        private void SimplifyPoints()\n        {\n            var lineRenderer = target as LineRenderer;\n            Undo.RecordObject(lineRenderer, \"Simplify Line\");\n            lineRenderer.Simplify(simplifyTolerance);\n        }\n\n        private void ResetSimplifyPreview()\n        {\n            m_PreviewPoints = null;\n        }\n\n        private void DrawSimplifyPreview()\n        {\n            var lineRenderer = target as LineRenderer;\n\n            if (!showSimplifyPreview || !canEditInScene || !lineRenderer.enabled)\n                return;\n\n            if (m_PreviewPoints == null && lineRenderer.positionCount > 2)\n            {\n                m_PreviewPoints = new Vector3[lineRenderer.positionCount];\n                lineRenderer.GetPositions(m_PreviewPoints);\n                var simplePoints = new List<Vector3>();\n                LineUtility.Simplify(m_PreviewPoints.ToList(), simplifyTolerance, simplePoints);\n                if (lineRenderer.loop)\n                    simplePoints.Add(simplePoints[0]);\n                m_PreviewPoints = simplePoints.ToArray();\n            }\n\n            if (m_PreviewPoints != null)\n            {\n                Handles.color = Color.yellow;\n                var oldMatrix = Handles.matrix;\n                if (!lineRenderer.useWorldSpace)\n                    Handles.matrix = lineRenderer.transform.localToWorldMatrix;\n                Handles.DrawAAPolyLine(10, m_PreviewPoints.Length, m_PreviewPoints);\n                Handles.matrix = oldMatrix;\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            DrawToolbar();\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_Loop);\n            if (EditorGUI.EndChangeCheck())\n                ResetSimplifyPreview();\n\n            EditorGUILayout.PropertyField(m_ApplyActiveColorSpace, Styles.applyActiveColorSpace);\n\n            m_ShowPositionsAnimation.target = m_Positions.isExpanded = EditorGUILayout.Foldout(m_Positions.isExpanded, Styles.positions, true);\n            if (m_ShowPositionsAnimation.faded > 0)\n            {\n                EditorGUILayout.PropertyField(m_PositionsSize);\n                if (m_Positions.arraySize != m_PositionsView.GetRows().Count)\n                {\n                    m_PositionsView.Reload();\n                    ResetSimplifyPreview();\n                }\n\n                m_PositionsView.OnGUI(EditorGUILayout.GetControlRect(false, Mathf.Lerp(kPositionsViewMinHeight, m_PositionsView.totalHeight, m_ShowPositionsAnimation.faded)));\n                if (serializedObject.hasModifiedProperties)\n                    ResetSimplifyPreview();\n            }\n\n            EditorGUILayout.Space();\n            m_CurveEditor.CheckCurveChangedExternally();\n            m_CurveEditor.OnInspectorGUI();\n            EditorGUILayout.Space();\n\n            EditorGUILayout.PropertyField(m_ColorGradient, Styles.colorGradient);\n            EditorGUILayout.PropertyField(m_NumCornerVertices, Styles.numCornerVertices);\n            EditorGUILayout.PropertyField(m_NumCapVertices, Styles.numCapVertices);\n            EditorGUILayout.PropertyField(m_Alignment, Styles.alignment);\n            EditorGUILayout.PropertyField(m_TextureMode, Styles.textureMode);\n            EditorGUILayout.PropertyField(m_TextureScale, Styles.textureScale);\n            EditorGUILayout.PropertyField(m_ShadowBias, Styles.shadowBias);\n            EditorGUILayout.PropertyField(m_GenerateLightingData, Styles.generateLightingData);\n            EditorGUILayout.PropertyField(m_UseWorldSpace);\n            EditorGUILayout.PropertyField(m_MaskInteraction);\n\n            DrawMaterials();\n            LightingSettingsGUI(false);\n            OtherSettingsGUI(true, false, true);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        public void OnSceneGUIDelegate(SceneView sceneView)\n        {\n            var sceneTool = activeSceneViewTool;\n            if (sceneTool != null)\n            {\n                sceneTool.OnSceneGUIDelegate(m_Positions, m_PositionsView);\n                ResetSimplifyPreview();\n            }\n            else\n            {\n                DrawSimplifyPreview();\n            }\n        }\n\n        public bool HasFrameBounds()\n        {\n            var sceneTool = activeSceneViewTool;\n            return (sceneTool != null) && (sceneTool.pointSelection.Count > 0);\n        }\n\n        public Bounds OnGetFrameBounds()\n        {\n            var sceneTool = activeSceneViewTool;\n            return (sceneTool != null) ? sceneTool.selectedPositionsBounds : new Bounds();\n        }\n\n        internal override Bounds GetWorldBoundsOfTarget(Object targetObject)\n        {\n            var sceneTool = activeSceneViewTool;\n            if (sceneTool != null)\n                return sceneTool.selectedPositionsBounds;\n            return base.GetWorldBoundsOfTarget(targetObject);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LineRendererEditorSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [FilePathAttribute(\"Library/LineRendererEditorSettings\", FilePathAttribute.Location.ProjectFolder)]\n    internal class LineRendererEditorSettings : ScriptableSingleton<LineRendererEditorSettings>\n    {\n        [SerializeField] float m_SimplifyTolerance = 1;\n        [SerializeField] bool m_ShowSimplifyPreview = true;\n        [SerializeField] float m_CreatePointSeparation = 1;\n        [SerializeField] float m_CreationOffset = 5;\n        [SerializeField] InputMode m_InputMode = InputMode.MousePosition;\n        [SerializeField] LayerMask m_RaycastMask;\n        [SerializeField] bool m_ShowWireframe;\n\n        public enum InputMode\n        {\n            MousePosition,\n            PhysicsRaycast\n        }\n\n        static void SetValue<T>(ref T original, T value)\n        {\n            if (!original.Equals(value))\n            {\n                original = value;\n                instance.Save(false);\n            }\n        }\n\n        public static bool showSimplifyPreview\n        {\n            get { return instance.m_ShowSimplifyPreview; }\n            set { SetValue(ref instance.m_ShowSimplifyPreview, value); }\n        }\n\n        public static float createPointSeparation\n        {\n            get { return instance.m_CreatePointSeparation; }\n            set { SetValue(ref instance.m_CreatePointSeparation, value); }\n        }\n\n        public static float creationOffset\n        {\n            get { return instance.m_CreationOffset; }\n            set { SetValue(ref instance.m_CreationOffset, value); }\n        }\n\n        public static InputMode inputMode\n        {\n            get { return instance.m_InputMode; }\n            set { SetValue(ref instance.m_InputMode, value); }\n        }\n\n        public static LayerMask raycastMask\n        {\n            get { return instance.m_RaycastMask; }\n            set { SetValue(ref instance.m_RaycastMask, value); }\n        }\n\n        public static bool showWireframe\n        {\n            get { return instance.m_ShowWireframe; }\n            set { SetValue(ref instance.m_ShowWireframe, value); }\n        }\n\n        public static float simplifyTolerance\n        {\n            get { return instance.m_SimplifyTolerance; }\n            set { SetValue(ref instance.m_SimplifyTolerance, value); }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LineRendererPositionsView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing TreeView = UnityEditor.IMGUI.Controls.TreeView<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    class LineRendererPositionsView : TreeView\n    {\n        SerializedProperty m_Positions;\n\n        const string k_DragId = \"LineRendererPositionsViewDragging\";\n        const float k_DragRectWidth = 5;\n        readonly static string[] k_PropertyNames = { \"x\", \"y\", \"z\" };\n\n        public Action<List<int>> selectionChangedCallback { get; set; } // ids\n\n        public LineRenderer lineRenderer { get; set; }\n\n        public LineRendererPositionsView(SerializedProperty positions) :\n            base(new TreeViewState())\n        {\n            m_Positions = positions;\n            showBorder = true;\n            showAlternatingRowBackgrounds = true;\n            useScrollView = false;\n            rowHeight = 15.0f;\n\n            MultiColumnHeaderState.Column[] columns = new MultiColumnHeaderState.Column[4];\n            for (int i = 0; i < columns.Length; ++i)\n            {\n                columns[i] = new MultiColumnHeaderState.Column();\n                columns[i].minWidth = 50;\n                columns[i].width = 100;\n                columns[i].headerTextAlignment = TextAlignment.Center;\n                columns[i].canSort = false;\n            }\n            columns[0].headerContent = new GUIContent(\"Index\");\n            columns[0].width = 50;\n            columns[0].allowToggleVisibility = false; // Always show the Index column (case 1260526)\n            columns[1].headerContent = new GUIContent(\"X\");\n            columns[2].headerContent = new GUIContent(\"Y\");\n            columns[3].headerContent = new GUIContent(\"Z\");\n            var multiColState = new MultiColumnHeaderState(columns);\n            multiColumnHeader = new MultiColumnHeader(multiColState) { height = EditorGUI.kSingleLineHeight + EditorGUI.kSpacing };\n            multiColumnHeader.ResizeToFit();\n            Reload();\n        }\n\n        protected override void RowGUI(RowGUIArgs args)\n        {\n            var prop = m_Positions.GetArrayElementAtIndex(args.item.id);\n            EditorGUI.BeginProperty(args.rowRect, GUIContent.none, prop);\n            for (int i = 0; i < args.GetNumVisibleColumns(); ++i)\n            {\n                CellGUI(args.GetCellRect(i), args.item, args.GetColumn(i), prop);\n            }\n            EditorGUI.EndProperty();\n        }\n\n        protected void CellGUI(Rect cellRect, TreeViewItem item, int col, SerializedProperty property)\n        {\n            CenterRectUsingSingleLineHeight(ref cellRect);\n\n            if (col == 0)\n            {\n                EditorGUI.LabelField(cellRect, item.displayName);\n            }\n            else\n            {\n                var prop = property.FindPropertyRelative(k_PropertyNames[col - 1]);\n                EditorGUI.BeginProperty(cellRect, GUIContent.none, prop);\n                EditorGUI.BeginChangeCheck();\n                var dragRect = cellRect;\n                dragRect.width = k_DragRectWidth;\n                cellRect.xMin += k_DragRectWidth;\n                int id = GUIUtility.GetControlID(FocusType.Keyboard);\n                var newVal = EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor, cellRect, dragRect, id, prop.floatValue, \"g7\", EditorStyles.numberField, true);\n                if (EditorGUI.EndChangeCheck())\n                    prop.floatValue = newVal;\n                EditorGUI.EndProperty();\n            }\n        }\n\n        int GetArraySize()\n        {\n            int arraySize;\n            if (m_Positions.serializedObject.isEditingMultipleObjects)\n            {\n                arraySize = m_Positions.minArraySize;\n\n                // Make sure maxArraySizeForMultiEditing is set large enough to expose the array indexes that are present on all targets.\n                if (m_Positions.serializedObject.maxArraySizeForMultiEditing < arraySize)\n                    m_Positions.serializedObject.maxArraySizeForMultiEditing = arraySize;\n            }\n            else\n            {\n                arraySize = m_Positions.arraySize;\n            }\n            return arraySize;\n        }\n\n        protected override TreeViewItem BuildRoot()\n        {\n            int arraySize = GetArraySize();\n\n            var root = new TreeViewItem { id = -1, depth = -1, displayName = \"Root\" };\n            var allItems = new List<TreeViewItem>(arraySize);\n            for (int i = 0; i < arraySize; ++i)\n            {\n                var item = new TreeViewItem(i, 0, i.ToString());\n                allItems.Add(item);\n            }\n\n            SetupParentsAndChildrenFromDepths(root, allItems);\n            return root;\n        }\n\n        protected override void DoubleClickedItem(int id)\n        {\n            base.DoubleClickedItem(id);\n\n            // Focus on point\n            var prop = m_Positions.GetArrayElementAtIndex(id);\n\n            var sceneView = SceneView.lastActiveSceneView;\n            if (sceneView != null && lineRenderer != null)\n            {\n                var pos = prop.vector3Value;\n                if (!lineRenderer.useWorldSpace)\n                    pos = lineRenderer.transform.localToWorldMatrix.MultiplyPoint(pos);\n\n                sceneView.Frame(new Bounds(pos, Vector3.one), false);\n            }\n        }\n\n        protected override void SelectionChanged(IList<int> selectedIds)\n        {\n            if (selectionChangedCallback != null)\n                selectionChangedCallback(selectedIds.ToList());\n        }\n\n        protected override bool CanMultiSelect(TreeViewItem item)\n        {\n            return true;\n        }\n\n        protected override bool CanStartDrag(CanStartDragArgs args)\n        {\n            return true;\n        }\n\n        protected override void SetupDragAndDrop(SetupDragAndDropArgs args)\n        {\n            DragAndDrop.PrepareStartDrag();\n            var draggedRows = args.draggedItemIDs;\n            DragAndDrop.SetGenericData(k_DragId, draggedRows);\n            DragAndDrop.StartDrag(\"Move Positions\");\n        }\n\n        protected override DragAndDropVisualMode HandleDragAndDrop(DragAndDropArgs args)\n        {\n            // Check if we can handle the current drag data (could be dragged in from other areas/windows in the editor)\n            var draggedRows = DragAndDrop.GetGenericData(k_DragId) as List<int>;\n            if (draggedRows == null || args.dragAndDropPosition != DragAndDropPosition.BetweenItems)\n                return DragAndDropVisualMode.None;\n\n            if (args.performDrop)\n            {\n                if (m_Positions.hasMultipleDifferentValues)\n                {\n                    if (!EditorUtility.DisplayDialog(L10n.Tr(\"Moving an array element will copy the complete array to all other selected objects.\"),\n                        L10n.Tr(\"Unique values in the different selected objects will be lost\"),\n                        L10n.Tr(\"OK\"),\n                        L10n.Tr(\"Cancel\")))\n                    {\n                        return DragAndDropVisualMode.Rejected;\n                    }\n                }\n\n                int arraySize = GetArraySize();\n                var newList = new List<Vector3>(arraySize);\n                draggedRows.Sort();\n\n                int nextDragItem = 0;\n                for (int i = 0; i < arraySize; ++i)\n                {\n                    if (i == args.insertAtIndex)\n                    {\n                        // Insert the items here\n                        foreach (var viewItem in draggedRows)\n                        {\n                            newList.Add(m_Positions.GetArrayElementAtIndex(viewItem).vector3Value);\n                        }\n                    }\n\n                    if (i == draggedRows[nextDragItem])\n                    {\n                        // Ignore this item, it is being moved\n                        nextDragItem++;\n                        if (nextDragItem >= draggedRows.Count)\n                            nextDragItem = 0;\n                    }\n                    else\n                    {\n                        newList.Add(m_Positions.GetArrayElementAtIndex(i).vector3Value);\n                    }\n                }\n\n                // Add to the end?\n                if (args.insertAtIndex == arraySize)\n                {\n                    foreach (var viewItem in draggedRows)\n                    {\n                        newList.Add(m_Positions.GetArrayElementAtIndex(viewItem).vector3Value);\n                    }\n                }\n\n                // Copy the list back\n                for (int i = 0; i < arraySize; ++i)\n                {\n                    m_Positions.GetArrayElementAtIndex(i).vector3Value = newList[i];\n                }\n\n                SetSelection(Enumerable.Range(args.insertAtIndex - draggedRows.Count(o => o < args.insertAtIndex), draggedRows.Count).ToList());\n            }\n            return DragAndDropVisualMode.Move;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LineRendererToolModes.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\nusing System.Linq;\n\nnamespace UnityEditor\n{\n    internal class LineRendererEditor : IEditablePoint, ICreatablePoint\n    {\n        public enum InputMode\n        {\n            MousePosition,\n            PhysicsRaycast\n        }\n\n        private LineRenderer m_LineRenderer;\n        public List<int> m_Selection = new List<int>();\n\n        public static float createPointSeparation\n        {\n            get { return EditorPrefs.GetFloat(\"LineRendererEditorCreatePointSeparation\", 1.0f); }\n            set { EditorPrefs.SetFloat(\"LineRendererEditorCreatePointSeparation\", value < 0 ? 0 : value); }\n        }\n\n        public static float creationOffset\n        {\n            get { return EditorPrefs.GetFloat(\"LineRendererEditorCreationOffset\", 5.0f); }\n            set { EditorPrefs.SetFloat(\"LineRendererEditorCreationOffset\", value); }\n        }\n\n        public static InputMode inputMode\n        {\n            get { return (InputMode)EditorPrefs.GetInt(\"LineRendererEditorInputMode\", 0); }\n            set { EditorPrefs.SetInt(\"LineRendererEditorInputMode\", (int)value); }\n        }\n\n        public static LayerMask raycastMask\n        {\n            get { return EditorPrefs.GetInt(\"LineRendererEditorRaycastMask\", -1); }\n            set { EditorPrefs.SetInt(\"LineRendererEditorRaycastMask\", value); }\n        }\n\n        public static bool showWireframe\n        {\n            get { return EditorPrefs.GetBool(\"LineRendererEditorShowWireFrame\", false); }\n            set { EditorPrefs.SetBool(\"LineRendererEditorShowWireFrame\", value); }\n        }\n\n        private static readonly Color kCloudColor = new Color(200f / 255f, 200f / 255f, 20f / 255f, 0.85f);\n        private static readonly Color kSelectedCloudColor = new Color(.3f, .6f, 1, 1);\n\n        public LineRendererEditor(LineRenderer lineRenderer)\n        {\n            m_LineRenderer = lineRenderer;\n        }\n\n        public void Deselect()\n        {\n            m_Selection.Clear();\n        }\n\n        public void HandleEditMenuHotKeyCommands(EditorWindow window)\n        {\n            //Handle other events!\n            if (Event.current.type == EventType.ValidateCommand\n                || Event.current.type == EventType.ExecuteCommand)\n            {\n                bool execute = Event.current.type == EventType.ExecuteCommand;\n                switch (Event.current.commandName)\n                {\n                    case \"SoftDelete\":\n                    case \"Delete\":\n                        if (execute)\n                            DestroySelected();\n                        Event.current.Use();\n                        break;\n                    case \"Duplicate\":\n                        if (execute)\n                            DuplicateSelected();\n                        Event.current.Use();\n                        break;\n                    case \"SelectAll\":\n                        if (execute)\n                            SelectAllPoints(window);\n                        Event.current.Use();\n                        break;\n                    case \"Cut\":\n                    case \"Copy\":\n                    case \"Paste\":\n                        // We need to capture these events to prevent being taken out of Edit mode by accident.\n                        // The copy paste would trigger the Inspector and duplicate the GameObject instead.\n                        Event.current.Use();\n                        break;\n                }\n            }\n        }\n\n        public void RemoveInvalidSelections()\n        {\n            // Remove any selections that do not exist.\n            int points = m_LineRenderer.positionCount;\n            m_Selection = m_Selection.Where(o => o < points).ToList();\n        }\n\n        private void SelectAllPoints(EditorWindow window)\n        {\n            m_Selection.Clear();\n            for (int i = 0; i < m_LineRenderer.positionCount; ++i)\n                m_Selection.Add(i);\n            window.Repaint();\n        }\n\n        public void DestroySelected()\n        {\n            if (m_Selection.Count == 0)\n                return;\n\n            Undo.RecordObject(m_LineRenderer, \"Delete Selected\");\n            var positions = new Vector3[m_LineRenderer.positionCount];\n            var newPositions = new Vector3[m_LineRenderer.positionCount - m_Selection.Count];\n            m_LineRenderer.GetPositions(positions);\n\n            int selectionIndex = 0;\n            int insertIndex = 0;\n            for (int i = 0; i < positions.Length; ++i)\n            {\n                if (i == m_Selection[selectionIndex])\n                {\n                    if (selectionIndex < m_Selection.Count - 1)\n                        ++selectionIndex;\n                }\n                else\n                    newPositions[insertIndex++] = positions[i];\n            }\n\n            m_LineRenderer.positionCount = newPositions.Length;\n            m_LineRenderer.SetPositions(newPositions);\n            m_Selection.Clear();\n        }\n\n        public void DuplicateSelected()\n        {\n            if (m_Selection.Count == 0)\n                return;\n\n            Undo.RecordObject(m_LineRenderer, \"Duplicate Selected\");\n            var positions = new Vector3[m_LineRenderer.positionCount];\n            var newPositions = new Vector3[m_LineRenderer.positionCount + m_Selection.Count];\n            m_LineRenderer.GetPositions(positions);\n\n            int selectionIndex = 0;\n            int insertIndex = 0;\n            var insertedIndexes = new List<int>(m_Selection.Count);\n            for (int i = 0; i < positions.Length; ++i)\n            {\n                if (i == m_Selection[selectionIndex])\n                {\n                    if (selectionIndex < m_Selection.Count - 1)\n                        ++selectionIndex;\n\n                    newPositions[insertIndex++] = positions[i];\n                    insertedIndexes.Add(insertIndex); // Select the duplicate\n                    newPositions[insertIndex++] = positions[i];\n                }\n                else\n                    newPositions[insertIndex++] = positions[i];\n            }\n\n            m_LineRenderer.positionCount = newPositions.Length;\n            m_LineRenderer.SetPositions(newPositions);\n            m_Selection = insertedIndexes;\n        }\n\n        void DrawWireframe()\n        {\n            Handles.color = Color.white;\n\n            Vector3[] positions = new Vector3[m_LineRenderer.loop ? m_LineRenderer.positionCount + 1 : m_LineRenderer.positionCount];\n            m_LineRenderer.GetPositions(positions);\n            if (m_LineRenderer.loop)\n                positions[m_LineRenderer.positionCount] = positions[0];\n\n            var oldMatrix = Handles.matrix;\n            if (!m_LineRenderer.useWorldSpace)\n                Handles.matrix = m_LineRenderer.transform.localToWorldMatrix;\n\n            Handles.DrawAAPolyLine(3, positions.Length, positions);\n            Handles.matrix = oldMatrix;\n        }\n\n        public void CreateSceneGUI()\n        {\n            PointCreator.CreatePoints(this, true, inputMode == InputMode.PhysicsRaycast, raycastMask, creationOffset, createPointSeparation);\n            PointCreator.Draw();\n        }\n\n        public void EditSceneGUI(EditorWindow window)\n        {\n            Transform transform = m_LineRenderer.useWorldSpace ? null : m_LineRenderer.transform;\n\n            if (m_LineRenderer.positionCount == 0)\n                return;\n\n            PointEditor.SelectPoints(this, transform, ref m_Selection);\n            PointEditor.Draw(this, transform, m_Selection, true);\n            PointEditor.MovePoints(this, transform, m_Selection);\n            if (showWireframe)\n                DrawWireframe();\n\n            HandleEditMenuHotKeyCommands(window);\n        }\n\n        public int Count { get { return m_LineRenderer.positionCount; } }\n\n        public Color GetDefaultColor()\n        {\n            return kCloudColor;\n        }\n\n        public Color GetSelectedColor()\n        {\n            return kSelectedCloudColor;\n        }\n\n        public float GetPointScale()\n        {\n            return 5.0f * AnnotationUtility.iconSize;\n        }\n\n        public Vector3 GetPosition(int idx)\n        {\n            return m_LineRenderer.GetPosition(idx);\n        }\n\n        public IEnumerable<Vector3> GetPositions()\n        {\n            Vector3[] positions = new Vector3[m_LineRenderer.positionCount];\n            m_LineRenderer.GetPositions(positions);\n\n            return positions;\n        }\n\n        public Vector3[] GetSelectedPositions()\n        {\n            Vector3[] positions = new Vector3[m_LineRenderer.positionCount];\n            m_LineRenderer.GetPositions(positions);\n\n            var result = new Vector3[m_Selection.Count];\n            for (int i = 0; i < m_Selection.Count; i++)\n            {\n                result[i] = positions[m_Selection[i]];\n            }\n\n            return result;\n        }\n\n        public Vector3[] GetUnselectedPositions()\n        {\n            if (m_Selection.Count == m_LineRenderer.positionCount)\n            {\n                return new Vector3[0];\n            }\n\n            Vector3[] positions = new Vector3[m_LineRenderer.positionCount];\n            m_LineRenderer.GetPositions(positions);\n            if (m_Selection.Count == 0)\n            {\n                return positions;\n            }\n\n            var selectionList = new bool[positions.Length];\n\n            // Mark everything unselected\n            for (int i = 0; i < positions.Length; i++)\n            {\n                selectionList[i] = false;\n            }\n\n            // Mark selected\n            for (int i = 0; i < m_Selection.Count; i++)\n            {\n                selectionList[m_Selection[i]] = true;\n            }\n\n            // Get remaining unselected\n            var result = new Vector3[positions.Length - m_Selection.Count];\n            var unselectedCount = 0;\n            for (int i = 0; i < positions.Length; i++)\n            {\n                if (selectionList[i] == false)\n                {\n                    result[unselectedCount++] = positions[i];\n                }\n            }\n\n            return result;\n        }\n\n        public void SetPosition(int idx, Vector3 position)\n        {\n            Undo.RecordObject(m_LineRenderer, \"Move Position\");\n            m_LineRenderer.SetPosition(idx, position);\n        }\n\n        private Bounds GetBounds(List<Vector3> positions)\n        {\n            if (positions.Count == 0)\n                return new Bounds();\n\n            Transform transform = m_LineRenderer.useWorldSpace ? null : m_LineRenderer.transform;\n            if (positions.Count == 1)\n            {\n                return new Bounds(transform != null ? m_LineRenderer.transform.TransformPoint(positions[0]) : positions[0], new Vector3(1f, 1f, 1f));\n            }\n\n            return GeometryUtility.CalculateBounds(positions.ToArray(), transform != null ? transform.localToWorldMatrix : Matrix4x4.identity);\n        }\n\n        public void AddPositions(List<Vector3> newPositions)\n        {\n            Undo.RecordObject(m_LineRenderer, \"Add Positions\");\n            var positions = new Vector3[m_LineRenderer.positionCount + newPositions.Count];\n\n            m_LineRenderer.GetPositions(positions);\n            int readPos = 0;\n            int writePos = m_LineRenderer.positionCount;\n            Matrix4x4 worldToLocal = m_LineRenderer.transform.worldToLocalMatrix;\n            for (; writePos < positions.Length; ++writePos, ++readPos)\n            {\n                var transformedPos = m_LineRenderer.useWorldSpace ? newPositions[readPos] : worldToLocal.MultiplyPoint(newPositions[readPos]);\n                positions[writePos] = transformedPos;\n            }\n\n            m_LineRenderer.positionCount = positions.Length;\n            m_LineRenderer.SetPositions(positions);\n        }\n\n        public Bounds selectedPositionsBounds\n        {\n            get\n            {\n                List<Vector3> selectedPoints = new List<Vector3>();\n                foreach (var idx in m_Selection)\n                    selectedPoints.Add(GetPosition(idx));\n                return GetBounds(selectedPoints);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/LookAtConstraintEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Animations;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(LookAtConstraint))]\n    [CanEditMultipleObjects]\n    internal class LookAtConstraintEditor : ConstraintEditorBase\n    {\n        private SerializedProperty m_RotationAtRest;\n        private SerializedProperty m_RotationOffset;\n        private SerializedProperty m_WorldUpObject;\n        private SerializedProperty m_Roll;\n        private SerializedProperty m_UseUpObject;\n        private SerializedProperty m_Weight;\n        private SerializedProperty m_IsContraintActive;\n        private SerializedProperty m_IsLocked;\n        private SerializedProperty m_Sources;\n\n        internal override SerializedProperty atRest { get { return m_RotationAtRest; } }\n        internal override SerializedProperty offset { get { return m_RotationOffset; } }\n\n        internal override SerializedProperty weight { get { return m_Weight; } }\n        internal override SerializedProperty isContraintActive { get { return m_IsContraintActive; } }\n        internal override SerializedProperty isLocked { get { return m_IsLocked; } }\n        internal override SerializedProperty sources { get { return m_Sources; } }\n\n        private class Styles : ConstraintStyleBase\n        {\n            GUIContent m_RotationAtRest = EditorGUIUtility.TrTextContent(\"Rotation At Rest\", \"The orientation of the constrained object when the weights of the sources add up to zero or when all the rotation axes are disabled.\");\n            GUIContent m_RotationOffset = EditorGUIUtility.TrTextContent(\"Rotation Offset\", \"The offset from the constrained orientation.\");\n            GUIContent m_WorldUpObject = EditorGUIUtility.TrTextContent(\"World Up Object\", \"The reference object when the World Up Type is either Object Up or Object Rotation Up.\");\n            GUIContent m_Roll = EditorGUIUtility.TrTextContent(\"Roll\", \"Specifies the roll angle in degrees.\");\n            GUIContent m_UseUpObject = EditorGUIUtility.TrTextContent(\"Use Up Object\", \"Specifies how the world up vector should be computed. Either use the World Up Object or the Roll value\");\n\n            public override GUIContent AtRest { get { return m_RotationAtRest; } }\n            public override GUIContent Offset { get { return m_RotationOffset; } }\n            public GUIContent WorldUpObject { get { return m_WorldUpObject; } }\n            public GUIContent Roll { get { return m_Roll; } }\n            public GUIContent UseUpObject { get { return m_UseUpObject; } }\n        }\n\n        private static Styles s_Style = null;\n\n        public void OnEnable()\n        {\n            if (s_Style == null)\n                s_Style = new Styles();\n\n            m_RotationAtRest = serializedObject.FindProperty(\"m_RotationAtRest\");\n            m_RotationOffset = serializedObject.FindProperty(\"m_RotationOffset\");\n\n            m_UseUpObject = serializedObject.FindProperty(\"m_UseUpObject\");\n            m_WorldUpObject = serializedObject.FindProperty(\"m_WorldUpObject\");\n            m_Roll = serializedObject.FindProperty(\"m_Roll\");\n\n            m_Weight = serializedObject.FindProperty(\"m_Weight\");\n            m_IsContraintActive = serializedObject.FindProperty(\"m_Active\");\n            m_IsLocked = serializedObject.FindProperty(\"m_IsLocked\");\n            m_Sources = serializedObject.FindProperty(\"m_Sources\");\n\n            OnEnable(s_Style);\n        }\n\n        internal override void OnValueAtRestChanged()\n        {\n            foreach (var t in targets)\n            {\n                (t as LookAtConstraint).transform.SetLocalEulerAngles(atRest.vector3Value, RotationOrder.OrderZXY);\n                EditorUtility.SetDirty(target);\n            }\n        }\n\n        internal override void ShowCustomProperties()\n        {\n            EditorGUILayout.PropertyField(m_UseUpObject, s_Style.UseUpObject);\n\n            using (new EditorGUI.DisabledGroupScope(m_UseUpObject.boolValue))\n            {\n                EditorGUILayout.PropertyField(m_Roll, s_Style.Roll);\n            }\n\n            using (new EditorGUI.DisabledGroupScope(!m_UseUpObject.boolValue))\n            {\n                EditorGUILayout.PropertyField(m_WorldUpObject, s_Style.WorldUpObject);\n            }\n        }\n\n        internal override void ShowFreezeAxesControl()\n        {\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (s_Style == null)\n                s_Style = new Styles();\n\n            serializedObject.Update();\n\n            ShowConstraintEditor<LookAtConstraint>(s_Style);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/MaskFieldDropdown.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEngine;\nusing static UnityEditor.MaskDropDownUtils;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class MaskFieldDropDown : PopupWindowContent\n    {\n        internal const int m_LayerCount = 32;\n\n        SerializedProperty m_SerializedProperty;\n\n        // Keep a reference to the targets so we can recreate the serialized property if it becomes invalid. (UUM-72761)\n        Object[] m_Targets;\n        string m_PropertyName;\n\n        SelectionModes[] m_SelectionMatch;\n        string[] m_OptionNames;\n        int[] m_FlagValues;\n        int[] m_OptionMaskValues;\n        int[] m_SelectionMaskValues;\n\n        int m_AllLayersMask = 0;\n        bool m_AutoSelectEverything = true;\n\n        bool m_SingleSelection = false;\n        EditorUtility.SelectMenuItemFunction m_MaskChangeCallback;\n\n        float m_windowSize = 100.0f;\n        public MaskFieldDropDown(SerializedProperty property)\n        {\n            m_SerializedProperty = property;\n            m_Targets = property.serializedObject.targetObjects;\n            m_PropertyName = property.propertyPath;\n            m_SingleSelection = false;\n        }\n\n        public MaskFieldDropDown(string[] optionNames, int[] optionMaskValues, int mask, EditorUtility.SelectMenuItemFunction maskChangeCallback)\n            : this(optionNames, null, optionMaskValues, mask, maskChangeCallback)\n        {\n        }\n\n        public MaskFieldDropDown(string[] optionNames, int[] flagValues, int[] optionMaskValues, int mask, EditorUtility.SelectMenuItemFunction maskChangeCallback, bool autoSelectEverything = true)\n        {\n            // these are not flag values, i.e. 1, 2, 4...\n            // but the mask & flagValue[0..n] for each possible flag value\n            // this is to ensure backwards compatibility with everything that uses MaskFieldGUI.GetSelectedValueForControl\n            m_OptionMaskValues = (int[])optionMaskValues.Clone();\n            m_OptionNames = (string[])optionNames.Clone();\n\n            m_FlagValues = new int[optionNames.Length];\n            m_FlagValues[0] = 0;\n            m_FlagValues[1] = -1;\n\n            if (flagValues == null)\n            {\n                for (int i = 2; i < m_FlagValues.Length; ++i)\n                    m_FlagValues[i] = (1 << i);\n            }\n            else\n            {\n                int index = 0;\n                int length = flagValues.Length;\n\n                if (flagValues[0] == 0)\n                {\n                    index = 1;\n                    length--;\n                }\n\n                if (flagValues[flagValues.Length - 1] == ~0)\n                    length--;\n\n                Array.Copy(flagValues, index, m_FlagValues, 2, length);\n            }\n\n            m_SelectionMatch = new SelectionModes[] { SelectionModes.All };\n            m_SelectionMaskValues = new int[] { mask };\n\n            m_SingleSelection = true;\n            m_MaskChangeCallback = maskChangeCallback;\n\n            m_AllLayersMask = 0;\n            foreach (var val in optionMaskValues)\n                if (val != -1 && val != int.MaxValue)\n                    m_AllLayersMask |= val;\n            m_AutoSelectEverything = autoSelectEverything;\n        }\n\n        public void UpdateMaskValues(int mask, int[] optionMaskValues)\n        {\n            m_OptionMaskValues = (int[])optionMaskValues.Clone();\n            m_SelectionMaskValues = new int[] { mask };\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            var rowCount = m_FlagValues == null ? m_OptionNames.Length + 2 : m_OptionNames.Length;\n            return new Vector2(m_windowSize, (EditorGUI.kSingleLineHeight + 2) * rowCount);\n        }\n\n        void DrawEverythingOrNothingSelectedToggle(bool state, string label, GUIStyle style, int value)\n        {\n            var guiRect = EditorGUILayout.GetControlRect(false, EditorGUI.kSingleLineHeight);\n            guiRect.width = GetWindowSize().x;\n            guiRect.x = 0;\n            DrawListBackground(guiRect, value == 0);\n            EditorGUI.BeginChangeCheck();\n            GUI.Toggle(guiRect, state, label, style);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_SerializedProperty.intValue = value;\n                m_SerializedProperty.serializedObject.ApplyModifiedProperties();\n                m_SerializedProperty.serializedObject.SetIsDifferentCacheDirty();\n                m_SerializedProperty.serializedObject.Update();\n\n                var valueToPopulate = value == 0 ? SelectionModes.None : SelectionModes.All;\n                m_SelectionMatch = new SelectionModes[m_LayerCount];\n                m_SelectionMatch = m_SelectionMatch.Select(el => el = valueToPopulate).ToArray();\n            }\n        }\n\n        private void DrawListBackground(Rect rect, bool even)\n        {\n            GUIStyle backgroundStyle = even ? Styles.listEvenBg : Styles.listOddBg;\n            GUI.Label(rect, GUIContent.none, backgroundStyle);\n        }\n\n        void DrawGUIForArrays()\n        {\n            for (int i = 0; i < m_OptionNames.Length; i++)\n            {\n                bool toggleVal = (m_SelectionMaskValues[0] & m_OptionMaskValues[i]) == m_OptionMaskValues[i];\n                if ((m_SelectionMaskValues[0] != 0 && i == 0) || m_SelectionMaskValues[0] != -1 && i == 1)\n                    toggleVal = false;\n\n                // Check for m_AllLayerMask != 0 was added to cover a case when we have only the first defined Layer, Everything and Nothing.\n                // In this case optionMaskValues when Everything select it will contain [0, -1, 0] and m_AllLayerMask will be 0 when we populate it in the constructor.\n                // So when we click on Nothing we will get 0 but we will continue to show Everything as checked.\n                if((m_SelectionMaskValues[0] == m_AllLayersMask) && i == 1 && m_AllLayersMask != 0 && m_AutoSelectEverything)\n                    toggleVal = true;\n\n                var guiRect = EditorGUILayout.GetControlRect(false, EditorGUI.kSingleLineHeight);\n                guiRect.width = GetWindowSize().x;\n                guiRect.x = 0;\n                DrawListBackground(guiRect, i % 2 == 0);\n\n                EditorGUI.BeginChangeCheck();\n                bool value = GUI.Toggle(guiRect, toggleVal, m_OptionNames[i], Styles.menuItem);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_SelectionMaskValues[0] = m_OptionMaskValues[i];\n                    var oldMaskValues = (uint[])m_OptionMaskValues.Clone();\n                    MaskFieldGUI.CalculateMaskValues(m_SelectionMaskValues[0], m_FlagValues, ref m_OptionMaskValues);\n\n                    // If all flag options are selected the mask becomes everythingValue to be consistent with the \"Everything\" option\n                    // oldMaskValues[i] == (uint)m_AllLayersMask && i == 0 && m_OptionNames[0] != \"Nothing\" is for case when we clicked nothing and only have the first layer defined.\n                    // It will invert Nothing to Everything if we don't double-check it for Nothing separately.\n                    // Check comment above to see the math why we need it separately.\n                    if ((oldMaskValues[i] == (uint)m_AllLayersMask && i != 0\n                        || oldMaskValues[i] == (uint)m_AllLayersMask && i == 0 && m_OptionNames[0] != \"Nothing\") && m_AutoSelectEverything)\n                        oldMaskValues[i] = ~0u;\n\n                    m_MaskChangeCallback.Invoke(oldMaskValues, null, i);\n                }\n            }\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            if (Event.current.type == EventType.MouseMove)\n                Event.current.Use();\n\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)\n            {\n                editorWindow.Close();\n                GUIUtility.ExitGUI();\n            }\n\n            if (m_SingleSelection)\n            {\n                DrawGUIForArrays();\n                return;\n            }\n\n            if (!m_SerializedProperty.isValid)\n            {\n                var serializedObject = new SerializedObject(m_Targets);\n                m_SerializedProperty = serializedObject.FindProperty(m_PropertyName);\n            }\n\n            if (m_SerializedProperty.propertyType != SerializedPropertyType.LayerMask)\n                return;\n\n            var isNothing = m_SerializedProperty.intValue == 0;\n            var isEverything = m_SerializedProperty.intValue == -1;\n\n            GUILayout.Space(2);\n\n            var toggleStyle = m_SerializedProperty.hasMultipleDifferentValues && isNothing ? Styles.menuItemMixed : Styles.menuItem;\n            DrawEverythingOrNothingSelectedToggle(isNothing, \"Nothing\", toggleStyle, 0);\n            toggleStyle = m_SerializedProperty.hasMultipleDifferentValues && isEverything ? Styles.menuItemMixed : Styles.menuItem;\n            DrawEverythingOrNothingSelectedToggle(isEverything, \"Everything\", toggleStyle, -1);\n\n            for (int i = 0; i < m_OptionNames.Length; i++)\n            {\n                var index = (int)Math.Log((uint) m_OptionMaskValues[i], 2);\n                bool toggleVal = m_SelectionMatch[index] == SelectionModes.All || m_SelectionMatch[index] == SelectionModes.Mixed ? true : false;\n                toggleStyle = m_SelectionMatch[index] == SelectionModes.Mixed ? Styles.menuItemMixed : Styles.menuItem;\n\n                EditorGUI.BeginChangeCheck();\n                var guiRect = EditorGUILayout.GetControlRect(false, EditorGUI.kSingleLineHeight);\n                guiRect.width = GetWindowSize().x;\n                guiRect.x = 0;\n                DrawListBackground(guiRect, i % 2 == 0);\n                var value = GUI.Toggle(guiRect, toggleVal, m_OptionNames[i], toggleStyle);\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_SelectionMatch[index] = value ? SelectionModes.All : SelectionModes.None;\n                    ChangeMaskValues(index, value);\n                }\n            }\n        }\n\n        void ChangeMaskValues(int maskIndex, bool add)\n        {\n            var selectionCount = m_SerializedProperty.serializedObject.targetObjects.Length;\n\n            m_SelectionMaskValues = new int[selectionCount];\n            for (int i = 0; i < selectionCount; i++)\n            {\n                var serializedObject = new SerializedObject(m_SerializedProperty.serializedObject.targetObjects[i]);\n                var property = serializedObject.FindProperty(m_SerializedProperty.propertyPath);\n\n                // Second condition is for backward compatibility, currently we use int.MaxValue to represent all flags set, previously we used -1 and the same value is stored in YAML files\n                // So when we read the SerializedProperty we are getting -1, and the behaviour is not as expected.\n                if (property.intValue == int.MaxValue || property.intValue == -1)\n                {\n                    property.intValue = 0;\n                    for (int j = 0; j < m_OptionMaskValues.Length; j++)\n                    {\n                        var slotsToShift = (int)Math.Log((uint)m_OptionMaskValues[j], 2);\n                        property.intValue |= 1 << slotsToShift;\n                    }\n                }\n                if (add)\n                    property.intValue = property.intValue |= 1 << maskIndex;\n                else\n                {\n                    property.intValue = property.intValue |= 1 << maskIndex;\n                    property.intValue = property.intValue &= ~(1 << maskIndex);\n                }\n\n                if (property.intValue == m_AllLayersMask)\n                    property.intValue = -1;\n\n                m_SelectionMaskValues[i] = property.intValue;\n                serializedObject.ApplyModifiedProperties();\n            }\n\n            m_SerializedProperty.serializedObject.SetIsDifferentCacheDirty();\n            m_SerializedProperty.serializedObject.Update();\n        }\n\n        public override void OnOpen()\n        {\n            if (!m_SingleSelection)\n            {\n                m_SelectionMatch = new SelectionModes[m_LayerCount];\n                GetMultiSelectionValues(m_SerializedProperty, out m_SelectionMaskValues, out m_SelectionMatch, m_LayerCount);\n                m_OptionMaskValues = new int[m_SelectionMaskValues.Length];\n                TagManager.GetDefinedLayers(ref m_OptionNames, ref m_OptionMaskValues);\n                for (int i = 0; i < m_OptionMaskValues.Length; i++)\n                    m_AllLayersMask |= m_OptionMaskValues[i];\n            }\n\n            for (int i = 0; i < m_OptionNames.Length; i++)\n            {\n                var size = Styles.menuItem.CalcSize(new GUIContent(m_OptionNames[i]));\n                if (size.x > m_windowSize)\n                    m_windowSize = size.x;\n            }\n            m_windowSize = Mathf.Clamp(m_windowSize, 100, Screen.currentResolution.width * 0.95f);\n\n            Undo.undoRedoEvent += OnUndoRedoPerformed;\n        }\n\n        public override void OnClose()\n        {\n            Undo.undoRedoEvent -= OnUndoRedoPerformed;\n            Event.current?.Use();\n            MaskFieldGUI.DestroyMaskCallBackInfo();\n            base.OnClose();\n        }\n\n        void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            editorWindow.Close();\n        }\n    }\n\n    internal class StaticFieldDropdown : PopupWindowContent\n    {\n        SerializedProperty m_SerializedProperty;\n\n        SelectionModes[] m_SelectionMatch;\n        string[] m_OptionNames;\n        int[] m_SelectionMaskValues;\n        int m_OptionCount;\n        int m_AllLayersMask;\n        List<int> m_FunctioningOptions = new List<int>();\n\n        public StaticFieldDropdown(UnityEngine.Object[] targetObjects, string propertyPath)\n        {\n            var so = new SerializedObject(targetObjects);\n            m_SerializedProperty = so.FindProperty(propertyPath);\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            var size = Styles.menuItem.CalcSize(new GUIContent(\"Off Mesh Link Generation\"));\n            return new Vector2(size.x, size.y * (m_OptionCount + 2) + 2);\n        }\n\n        void DrawEverythingOrNothingSelectedToggle(bool state, string label, GUIStyle style, bool changedTo)\n        {\n            EditorGUI.BeginChangeCheck();\n            GUILayout.Toggle(state, label, style);\n            if (EditorGUI.EndChangeCheck())\n            {\n                ChangeMaskValues(int.MaxValue, changedTo);\n                var valueToPopulate = changedTo ? SelectionModes.All : SelectionModes.None;\n                m_SelectionMatch = new SelectionModes[m_OptionCount];\n                m_SelectionMatch = m_SelectionMatch.Select(el => el = valueToPopulate).ToArray();\n            }\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            if (Event.current.type == EventType.MouseMove)\n                Event.current.Use();\n\n            if (m_SerializedProperty.propertyType != SerializedPropertyType.Integer)\n                return;\n\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)\n            {\n                editorWindow.Close();\n                GUIUtility.ExitGUI();\n            }\n\n            var isNothing = m_SerializedProperty.intValue == 0;\n            var isEverything = ((uint)m_SerializedProperty.intValue & m_AllLayersMask) == m_AllLayersMask;\n\n            GUILayout.Space(Styles.menuItem.margin.bottom);\n\n            var toggleStyle = m_SerializedProperty.hasMultipleDifferentValues && isNothing ? Styles.menuItemMixed : Styles.menuItem;\n            DrawEverythingOrNothingSelectedToggle(isNothing, \"Nothing\", toggleStyle, false);\n            toggleStyle = m_SerializedProperty.hasMultipleDifferentValues && isEverything ? Styles.menuItemMixed : Styles.menuItem;\n            DrawEverythingOrNothingSelectedToggle(isEverything, \"Everything\", toggleStyle, true);\n\n            for (int i = 0; i < m_OptionCount; i++)\n            {\n                bool toggleVal = m_SelectionMatch[i] == SelectionModes.All || m_SelectionMatch[i] == SelectionModes.Mixed ? true : false;\n                toggleStyle = m_SelectionMatch[i] == SelectionModes.Mixed ? Styles.menuItemMixed : Styles.menuItem;\n\n                EditorGUI.BeginChangeCheck();\n                int flagIndex = (int)Math.Pow(2, i);\n                bool isDeprecated = !m_FunctioningOptions.Contains(flagIndex);\n\n                using (new EditorGUI.DisabledScope(isDeprecated))\n                {\n                    var value = GUILayout.Toggle(toggleVal, new GUIContent(m_OptionNames[i], (isDeprecated)?\"This static value has been deprecated.\":\"\"), toggleStyle);\n\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        m_SelectionMatch[i] = value ? SelectionModes.All : SelectionModes.None;\n                        ChangeMaskValues(flagIndex, value);\n                    }\n                }\n            }\n        }\n\n        void ChangeMaskValues(int maskIndex, bool add)\n        {\n            var selectionCount = m_SerializedProperty.serializedObject.targetObjects.Length;\n            m_SelectionMaskValues = new int[selectionCount];\n\n            SceneModeUtility.SetStaticFlags(m_SerializedProperty.serializedObject.targetObjects, maskIndex, add);\n\n            for (int i = 0; i < selectionCount; i++)\n                m_SelectionMaskValues[i] = m_SerializedProperty.intValue;\n\n            m_SerializedProperty.serializedObject.ApplyModifiedProperties();\n            m_SerializedProperty.serializedObject.SetIsDifferentCacheDirty();\n            m_SerializedProperty.serializedObject.Update();\n            editorWindow.Repaint();\n        }\n\n        public override void OnOpen()\n        {\n            m_FunctioningOptions.Clear();\n            m_OptionCount = 0;\n            List<FieldInfo> filteredFields = new List<FieldInfo>();\n            var fields = typeof(StaticEditorFlags).GetFields();\n            foreach (var field in fields)\n            {\n                if (!field.IsDefined(typeof(ObsoleteAttribute), true) && !field.IsSpecialName)\n                {\n                    filteredFields.Add(field);\n                    m_FunctioningOptions.Add((int)(field.GetValue(null)));\n                    m_OptionCount++;\n                }\n            }\n\n            // Add Obsolete values that were not replaced by a new value\n            foreach (var field in fields)\n            {\n                if (field.IsDefined(typeof(ObsoleteAttribute), true) && !field.IsSpecialName)\n                {\n                    if (!m_FunctioningOptions.Contains((int)(field.GetValue(null))))\n                    {\n                        filteredFields.Add(field);\n                        m_OptionCount++;\n                    }\n                }\n            }\n\n            m_OptionNames = new string[m_OptionCount];\n            for (int i = 0; i < m_OptionCount; i++)\n            {\n                var val = (int)(filteredFields[i].GetValue(null));\n                var index = (int)Math.Log(val, 2);\n\n                m_OptionNames[index] = ObjectNames.NicifyVariableName(filteredFields[i].Name);\n                m_AllLayersMask |= val;\n            }\n\n            GetMultiSelectionValues(m_SerializedProperty, out m_SelectionMaskValues, out m_SelectionMatch, m_OptionCount);\n            Undo.undoRedoEvent += OnUndoRedoPerformed;\n        }\n\n        public override void OnClose()\n        {\n            Undo.undoRedoEvent -= OnUndoRedoPerformed;\n            base.OnClose();\n        }\n\n        void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            editorWindow.Close();\n        }\n    }\n\n    internal class MaskDropDownUtils\n    {\n        internal static class Styles\n        {\n            internal static GUIStyle menuItem = new GUIStyle(\"MenuItem\");\n            internal static GUIStyle menuItemMixed = new GUIStyle(\"MenuItemMixed\");\n            internal static GUIStyle listEvenBg = \"ObjectPickerResultsOdd\";\n            internal static GUIStyle listOddBg = \"ObjectPickerResultsEven\";\n\n            static Styles()\n            {\n                menuItem.padding = new RectOffset(menuItem.padding.left, menuItem.padding.right, 0, 0);\n                menuItemMixed.padding = new RectOffset(menuItemMixed.padding.left, menuItemMixed.padding.right, 0, 0);\n            }\n        }\n\n        internal enum SelectionModes\n        {\n            None = 0,\n            All = 1,\n            Mixed = 2\n        };\n\n        internal static void GetSelected(int maskValue, out uint[] selected, int size)\n        {\n            if (maskValue == 0)\n                selected = new uint[0];\n            else if (maskValue == int.MaxValue)\n                selected = Enumerable.Range(1, size).Select(i => (uint)i).ToArray();\n            else\n            {\n                List<uint> selectedMaskToIndex = new List<uint>();\n                for (int i = 0; i < size; i++)\n                {\n                    if (((1 << i) & (uint)maskValue) > 0)\n                    {\n                        selectedMaskToIndex.Add((uint)(i + 1));\n                    }\n                }\n\n                selected = selectedMaskToIndex.ToArray();\n            }\n        }\n\n        internal static void GetSingleSelectionValues(int maskValue, out SelectionModes[] selectionMatch, int layerCount)\n        {\n            selectionMatch = new SelectionModes[layerCount];\n            uint[] selected;\n            GetSelected(maskValue, out selected, layerCount);\n\n            for (int i = 0; i < selectionMatch.Length; i++)\n            {\n                if (Array.Exists(selected, el => el == i + 1))\n                    selectionMatch[i] = SelectionModes.All;\n            }\n        }\n\n        internal static void GetMultiSelectionValues(SerializedProperty serializedProperty, out int[] selectionMaskValues, out SelectionModes[] selectionMatch, int layerCount)\n        {\n            var selectionCount = serializedProperty.serializedObject.targetObjects.Length;\n            selectionMaskValues = new int[selectionCount];\n            selectionMatch = new SelectionModes[layerCount];\n\n            for (int i = 0; i < selectionCount; i++)\n            {\n                var serializedObject = new SerializedObject(serializedProperty.serializedObject.targetObjects[i]);\n                var property = serializedObject.FindProperty(serializedProperty.propertyPath);\n                selectionMaskValues[i] = property.intValue;\n            }\n\n            if (selectionCount == 1)\n            {\n                GetSingleSelectionValues(selectionMaskValues[0], out selectionMatch, layerCount);\n                return;\n            }\n\n            uint[] firstSelected;\n            GetSelected(selectionMaskValues[0], out firstSelected, layerCount);\n\n            for (int i = 1; i < selectionCount; i++)\n            {\n                uint[] secondSelected;\n                GetSelected(selectionMaskValues[i], out secondSelected, layerCount);\n\n                for (int j = 0; j < layerCount; j++)\n                {\n                    var firstExists = Array.Exists(firstSelected, element => element == j + 1);\n                    var secondExists = Array.Exists(secondSelected, element => element == j + 1);\n\n                    if (firstExists && secondExists && selectionMatch[j] != SelectionModes.Mixed)\n                        selectionMatch[j] = SelectionModes.All;\n                    else if (!firstExists && !secondExists && selectionMatch[j] != SelectionModes.Mixed)\n                        selectionMatch[j] = SelectionModes.None;\n                    else\n                        selectionMatch[j] = SelectionModes.Mixed;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/MaterialEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing UnityEngine.UIElements;\nusing UnityEngine.Rendering;\nusing Object = UnityEngine.Object;\nusing UnityEngine.Scripting;\nusing VirtualTexturing = UnityEngine.Rendering.VirtualTexturing;\nusing StackValidationResult = UnityEngine.Rendering.VirtualTexturing.EditorHelpers.StackValidationResult;\nusing System.IO;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(Material))]\n    [CanEditMultipleObjects]\n    public partial class MaterialEditor : Editor\n    {\n        private static class Styles\n        {\n            public static readonly GUIContent reflectionProbePickerIcon = EditorGUIUtility.TrIconContent(\"ReflectionProbeSelector\");\n            public static readonly GUIContent lightmapEmissiveLabelRealtimeGISupport = EditorGUIUtility.TrTextContent(\"Global Illumination\", \"Controls if the emission is Baked or Realtime.\\n\\nBaked only has effect in scenes where Baked Global Illumination is enabled.\\n\\nRealtime uses Realtime Global Illumination if enabled in the scene. Otherwise the emission won't light up other objects.\");\n            public static readonly GUIContent lightmapEmissiveLabel = EditorGUIUtility.TrTextContent(\"Global Illumination\", \"Controls if the emission is Baked or Realtime.\\n\\nBaked only has effect in scenes where Baked Global Illumination is enabled.\\n\\nRealtime won't light up other objects since Realtime Global Illumination is not supported.\");\n            public static GUIContent[] lightmapEmissiveStrings = { EditorGUIUtility.TextContent(\"Realtime\"), EditorGUIUtility.TrTextContent(\"Baked\"), EditorGUIUtility.TrTextContent(\"None\") };\n            public static int[]  lightmapEmissiveValues = { (int)MaterialGlobalIlluminationFlags.RealtimeEmissive, (int)MaterialGlobalIlluminationFlags.BakedEmissive, (int)MaterialGlobalIlluminationFlags.None };\n            public static string propBlockInfo = EditorGUIUtility.TrTextContent(\"MaterialPropertyBlock is used to modify these values\").text;\n\n            public const int kNewShaderQueueValue = -1;\n            public const int kCustomQueueIndex = 4;\n            public static readonly GUIContent queueLabel = EditorGUIUtility.TrTextContent(\"Render Queue\");\n            public static readonly GUIContent[] queueNames =\n            {\n                EditorGUIUtility.TrTextContent(\"From Shader\"),\n                EditorGUIUtility.TrTextContent(\"Geometry\", \"Queue 2000\"),\n                EditorGUIUtility.TrTextContent(\"AlphaTest\", \"Queue 2450\"),\n                EditorGUIUtility.TrTextContent(\"Transparent\", \"Queue 3000\"),\n            };\n            public static readonly int[] queueValues =\n            {\n                kNewShaderQueueValue,\n                (int)UnityEngine.Rendering.RenderQueue.Geometry,\n                (int)UnityEngine.Rendering.RenderQueue.AlphaTest,\n                (int)UnityEngine.Rendering.RenderQueue.Transparent,\n            };\n            public static GUIContent[] customQueueNames =\n            {\n                queueNames[0],\n                queueNames[1],\n                queueNames[2],\n                queueNames[3],\n                EditorGUIUtility.TextContent(\"\"), // This name will be overriden during runtime\n            };\n            public static int[] customQueueValues =\n            {\n                queueValues[0],\n                queueValues[1],\n                queueValues[2],\n                queueValues[3],\n                0, // This value will be overriden during runtime\n            };\n\n            public static readonly GUIContent enableInstancingLabel = EditorGUIUtility.TrTextContent(\"Enable GPU Instancing\");\n            public static readonly GUIContent doubleSidedGILabel = EditorGUIUtility.TrTextContent(\"Double Sided Global Illumination\", \"When enabled, the lightmapper accounts for both sides of the geometry when calculating Global Illumination. Backfaces are not rendered or added to lightmaps, but get treated as valid when seen from other objects. When using the Progressive Lightmapper backfaces bounce light using the same emission and albedo as frontfaces.\");\n            public static readonly GUIContent emissionLabel = EditorGUIUtility.TrTextContent(\"Emission\");\n\n            public const string undoAssignMaterial = \"Assign Material\";\n            public const string undoAssignSkyboxMaterial = \"Assign Skybox Material\";\n\n            public static readonly GUIContent parentContent = EditorGUIUtility.TrTextContent(\"Parent\", \"Specify the parent of this material.\");\n            public static readonly GUIContent hierarchyIcon = EditorGUIUtility.IconContent(\"UnityEditor.SceneHierarchyWindow\", \"|Open Material Hierarchy Popup.\"); // right of | means tooltip\n            public static readonly GUIContent convertIcon = EditorGUIUtility.IconContent(\"d_RotateTool\", \"|This material is in a conversion process.\"); // right of | means tooltip\n\n            public const string timeUpdateButtonName = \"TimeUpdateButton\";\n            public const string selectedMeshButtonName = \"SelectedMeshButton\";\n            public const string lightModeButtonName = \"LightModeButton\";\n            public const string reflectionProbeDropdownName = \"ReflectionProbeDropdown\";\n\n            public const int kPadding = 3;\n            public const int kHierarchyIconWidth = 44;\n            public const float kSpaceForFoldoutArrow = 10f;\n        }\n\n        private static readonly List<MaterialEditor> s_MaterialEditors = new List<MaterialEditor>(4);\n        private int m_VariantCountCache = -1, m_HasMixedParentCache = -1;\n        private bool m_CheckSetup;\n\n        private static int s_ControlHash = \"EditorTextField\".GetHashCode();\n        const float kSpacingUnderTexture = 6f;\n        const float kMiniWarningMessageHeight = 27f;\n\n        private MaterialPropertyBlock m_PropertyBlock;\n\n        internal override string targetTitle\n        {\n            get\n            {\n                var typeName = AllTargetsAreVariants() ? \"Material Variant\" : \"Material\";\n                return (!m_AllowMultiObjectAccess || targets.Length == 1) ? target.name + \" (\" + typeName + \")\" : targets.Length + \" \" + typeName + \"s\";\n            }\n        }\n\n        private enum PreviewType\n        {\n            Mesh = 0,\n            Plane = 1,\n            Skybox = 2\n        }\n\n        private static PreviewType GetPreviewType(Material mat)\n        {\n            if (mat == null)\n                return PreviewType.Mesh;\n            var tag = mat.GetTag(\"PreviewType\", false, string.Empty).ToLower();\n            if (tag == \"plane\")\n                return PreviewType.Plane;\n            if (tag == \"skybox\")\n                return PreviewType.Skybox;\n            if (mat.shader != null && mat.shader.name.Contains(\"Skybox\"))\n                return PreviewType.Skybox;\n            return PreviewType.Mesh;\n        }\n\n        private static bool DoesPreviewAllowRotation(PreviewType type)\n        {\n            return type != PreviewType.Plane;\n        }\n\n        public bool isVisible { get { return firstInspectedEditor || InternalEditorUtility.GetIsInspectorExpanded(target); } }\n\n        private Shader m_Shader;\n\n        private string                      m_InfoMessage;\n        private Vector2                     m_PreviewDir = new Vector2(0, -20);\n        private int                  m_SelectedMesh;\n        private int                         m_TimeUpdate;\n        private int                         m_LightMode = 1;\n        private static readonly GUIContent  s_TilingText = EditorGUIUtility.TrTextContent(\"Tiling\");\n        private static readonly GUIContent  s_OffsetText = EditorGUIUtility.TrTextContent(\"Offset\");\n\n        const string kDefaultMaterialPreviewMesh = \"DefaultMaterialPreviewMesh\";\n\n        private ShaderGUI   m_CustomShaderGUI;\n        string              m_CustomEditorClassName;\n        public ShaderGUI customShaderGUI { get { return m_CustomShaderGUI; } }\n\n        bool                                m_InsidePropertiesGUI;\n        Renderer[]                          m_RenderersForAnimationMode;\n        Component                       m_MeshRendererComp;\n\n        internal enum ConvertAction { None, Flatten, Convert }\n        internal ConvertAction convertState;\n\n        private bool ShouldEditorBeHidden()\n        {\n            //When a MeshRenderer is hidden in the inspector, the MaterialEditor should also be hidden\n            //as showing a Material in the inspector without its supporting component feels wrong.\n            //This is more of a hack than a fix as we shouldnt be creating this editor in the first place when\n            //the supporting component is hidden, as the editor creation is a part of serialization and\n            //making changes at that level causes more issues this seems to be the best way to handle this case.\n            //This fix is for case 1289980\n\n            if (m_MeshRendererComp)\n            {\n                if (m_MeshRendererComp.hideFlags == HideFlags.HideInInspector)\n                    return true;\n                return false;\n            }\n\n            PropertyEditor property = propertyViewer as PropertyEditor;\n            if (!property)\n                return false;\n            GameObject gameObject = property.tracker.activeEditors[0].target as GameObject;\n            if (!gameObject)\n                return false;\n            foreach (Component comp in gameObject.GetComponents<MeshRenderer>())\n            {\n                m_MeshRendererComp = comp;\n                if (comp.hideFlags == HideFlags.HideInInspector)\n                    return true;\n            }\n            return false;\n        }\n\n        private Renderer rendererForAnimationMode\n        {\n            get\n            {\n                if (m_RenderersForAnimationMode == null)\n                    return null;\n\n                if (m_RenderersForAnimationMode.Length == 0)\n                    return null;\n\n                return m_RenderersForAnimationMode[0];\n            }\n        }\n\n        private struct AnimatedCheckData\n        {\n            public MaterialProperty property;\n            public Rect totalPosition;\n            public Color color;\n            public AnimatedCheckData(MaterialProperty property, Rect totalPosition, Color color)\n            {\n                this.property = property;\n                this.totalPosition = totalPosition;\n                this.color = color;\n            }\n        }\n\n        private static Stack<AnimatedCheckData> s_AnimatedCheckStack = new Stack<AnimatedCheckData>();\n\n        internal delegate void MaterialPropertyCallbackFunction(GenericMenu menu, MaterialProperty property, Renderer[] renderers);\n        internal static MaterialPropertyCallbackFunction contextualPropertyMenu;\n\n        internal class ReflectionProbePicker : PopupWindowContent\n        {\n            ReflectionProbe m_SelectedReflectionProbe;\n\n            public Transform Target\n            {\n                get { return m_SelectedReflectionProbe != null ? m_SelectedReflectionProbe.transform : null; }\n            }\n\n            public override Vector2 GetWindowSize()\n            {\n                return new Vector2(170, EditorGUI.kSingleLineHeight * 3f + 2f);\n            }\n\n            public void OnEnable()\n            {\n                m_SelectedReflectionProbe = EditorUtility.InstanceIDToObject(SessionState.GetInt(\"PreviewReflectionProbe\", 0)) as ReflectionProbe;\n            }\n\n            public void OnDisable()\n            {\n                SessionState.SetInt(\"PreviewReflectionProbe\", m_SelectedReflectionProbe ? m_SelectedReflectionProbe.GetInstanceID() : 0);\n            }\n\n            public override void OnGUI(Rect rc)\n            {\n                EditorGUILayout.LabelField(\"Select Reflection Probe\", EditorStyles.boldLabel);\n                EditorGUILayout.Space();\n                m_SelectedReflectionProbe = EditorGUILayout.ObjectField(\"\", m_SelectedReflectionProbe, typeof(ReflectionProbe), true) as ReflectionProbe;\n            }\n        }\n\n        ReflectionProbePicker               m_ReflectionProbePicker = new ReflectionProbePicker();\n\n\n        public void SetShader(Shader shader)\n        {\n            SetShader(shader, true);\n        }\n\n        public void SetShader(Shader newShader, bool registerUndo)\n        {\n            bool updateMaterialEditors = false;\n            ShaderGUI customEditor = m_CustomShaderGUI;\n            CreateCustomShaderEditorIfNeeded(newShader);\n            m_Shader = newShader;\n            if (customEditor != m_CustomShaderGUI)\n            {\n                if (customEditor != null)\n                {\n                    foreach (Material material in targets)\n                        customEditor.OnClosed(material);\n                }\n\n                updateMaterialEditors = true;\n            }\n\n            foreach (Material material in targets)\n            {\n                Shader oldShader = material.shader;\n                Undo.RecordObject(material, \"Assign shader\");\n\n                BeginNoApplyMaterialPropertyDrawers();\n                {\n                    if (m_CustomShaderGUI != null)\n                        m_CustomShaderGUI.AssignNewShaderToMaterial(material, oldShader, newShader);\n                    else\n                        material.shader = newShader;\n                }\n                EndNoApplyMaterialPropertyDrawers();\n\n                EditorMaterialUtility.ResetDefaultTextures(material, false);\n                ApplyMaterialPropertyDrawers(material);\n                if (m_CustomShaderGUI != null)\n                    m_CustomShaderGUI.ValidateMaterial(material);\n            }\n\n            if (updateMaterialEditors)\n            {\n                UpdateAllOpenMaterialEditors();\n            }\n            else\n            {\n                // ensure e.g., correctly rebuilt textures (case 879446)\n                OnShaderChanged();\n            }\n        }\n\n        private void UpdateAllOpenMaterialEditors()\n        {\n            // copy current list contents to array in case it changes during iteration\n            foreach (var materialEditor in s_MaterialEditors.ToArray())\n                materialEditor.DetectShaderEditorNeedsUpdate();\n        }\n\n        // Note: this is called from native code.\n        internal void OnSelectedShaderPopup(object shaderNameObj)\n        {\n            serializedObject.Update();\n            var shaderName = (string)shaderNameObj;\n            if (!string.IsNullOrEmpty(shaderName))\n            {\n                var shader = Shader.Find(shaderName);\n                if (shader != null)\n                    SetShader(shader);\n            }\n\n            PropertiesChanged();\n        }\n\n        private bool HasMultipleMixedShaderValues()\n        {\n            bool mixed = false;\n            Shader sh = (targets[0] as Material).shader;\n            for (int i = 1; i < targets.Length; ++i)\n            {\n                if (sh != (targets[i] as Material).shader)\n                {\n                    mixed = true;\n                    break;\n                }\n            }\n            return mixed;\n        }\n\n        private void ShaderPopup(GUIStyle style)\n        {\n            bool wasEnabled = GUI.enabled;\n\n            Rect position = EditorGUILayout.GetControlRect();\n            position = EditorGUI.PrefixLabel(position, 47385, EditorGUIUtility.TempContent(\"Shader\"));\n            EditorGUI.showMixedValue = HasMultipleMixedShaderValues();\n\n            var buttonContent = EditorGUIUtility.TempContent(m_Shader != null ? m_Shader.name : \"No Shader Selected\");\n            if (EditorGUI.DropdownButton(position, buttonContent, FocusType.Keyboard, style))\n            {\n                var dropdown = new ShaderSelectionDropdown(m_Shader, OnSelectedShaderPopup);\n                dropdown.Show(position);\n                GUIUtility.ExitGUI();\n            }\n\n            EditorGUI.showMixedValue = false;\n            GUI.enabled = wasEnabled;\n        }\n\n        bool HasMixedParent()\n        {\n            if (m_HasMixedParentCache != -1)\n                return m_HasMixedParentCache == 1;\n\n            m_HasMixedParentCache = 0;\n            if (targets.Length != 0)\n            {\n                var parent = ((Material)targets[0]).parent;\n                bool isVariant = ((Material)targets[0]).isVariant;\n                for (int i = 1; i < targets.Length; i++)\n                {\n                    if (((Material)targets[i]).parent != parent || ((Material)targets[i]).isVariant != isVariant)\n                    {\n                        m_HasMixedParentCache = 1;\n                        break;\n                    }\n                }\n            }\n            return m_HasMixedParentCache == 1;\n        }\n\n        int GetVariantCount()\n        {\n            if (m_VariantCountCache == -1)\n                m_VariantCountCache = GetVariantCount(targets);\n\n            return m_VariantCountCache;\n        }\n\n        bool AllTargetsAreVariants()\n        {\n            return GetVariantCount() == targets.Length;\n        }\n\n        // returns true if mat is a child of any element of the targets array\n        private static bool IsChildOfAnyTarget(Material mat, Object[] targets)\n        {\n            foreach (var target in targets)\n            {\n                if (mat == target || mat.IsChildOf(target as Material))\n                    return true;\n            }\n            return false;\n        }\n\n        private static Material HandleParentDragAndDrop(Rect rect, int controlID, EventType eventType, Object[] targets)\n        {\n            Material parent = (targets[0] as Material).parent;\n\n            // We handle drag and drop ourselves because we accept assets containing a material artifact\n            if (eventType == EventType.DragUpdated || eventType == EventType.DragPerform)\n            {\n                if (rect.Contains(Event.current.mousePosition) && GUI.enabled)\n                {\n                    Object[] references = DragAndDrop.objectReferences;\n                    Material validatedObject = EditorGUI.ValidateObjectFieldAssignment(references, typeof(Material), null, EditorGUI.ObjectFieldValidatorOptions.None) as Material;\n                    if (validatedObject == null)\n                    {\n                        foreach (var asset in AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(validatedObject)))\n                        {\n                            validatedObject = asset as Material;\n                            if (validatedObject)\n                                break;\n                        }\n                    }\n                    if (validatedObject != null && !IsChildOfAnyTarget(validatedObject, targets))\n                    {\n                        DragAndDrop.visualMode = DragAndDropVisualMode.Generic;\n                        if (eventType == EventType.DragPerform)\n                        {\n                            GUI.changed = true;\n                            DragAndDrop.AcceptDrag();\n                            DragAndDrop.activeControlID = 0;\n                            parent = validatedObject;\n                        }\n                        else\n                            DragAndDrop.activeControlID = controlID;\n                    }\n                    Event.current.Use();\n                }\n            }\n            return parent;\n        }\n\n        private static bool HasMissingParent(Material material)\n        {\n            return material.isVariant && material.parent == null;\n        }\n\n        private static Material DoParentObjectField(Rect rect, Object[] targets)\n        {\n            // This is an augmented object field, preventing cyclic dependencies in the material hierarchy, handling missing parent, and with custom drap and drop rejection\n\n            int controlID = GUIUtility.GetControlID(FocusType.Keyboard, rect);\n            var eventType = Event.current.type;\n\n            Material parent = HandleParentDragAndDrop(rect, controlID, eventType, targets);\n\n            if (eventType == EventType.Repaint && HasMissingParent(targets[0] as Material))\n            {\n                GUIContent content = EditorGUIUtility.TempContent(\"Missing (Material)\");\n\n                var mousePos = Event.current.mousePosition;\n                Rect buttonRect = EditorStyles.objectFieldButton.margin.Remove(new Rect(rect.xMax - 19, rect.y, 19, rect.height));\n\n                EditorGUI.BeginHandleMixedValueContentColor();\n                EditorStyles.objectField.Draw(rect, content, controlID, DragAndDrop.activeControlID == controlID, rect.Contains(mousePos));\n                EditorStyles.objectFieldButton.Draw(buttonRect, GUIContent.none, controlID, DragAndDrop.activeControlID == controlID, buttonRect.Contains(mousePos));\n                EditorGUI.EndHandleMixedValueContentColor();\n                return parent;\n            }\n\n            return EditorGUI.DoObjectField(rect, rect, controlID, parent, null, typeof(Material), null, true) as Material;\n        }\n\n        internal void ParentField(Rect rect, bool showMixedValue = false)\n        {\n            rect = EditorGUI.PrefixLabel(rect, Styles.parentContent);\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = showMixedValue;\n            var parent = DoParentObjectField(rect, targets);\n            EditorGUI.showMixedValue = false;\n            if (EditorGUI.EndChangeCheck())\n            {\n                convertState = ConvertAction.None;\n                Undo.RecordObjects(targets, \"Assign parent\");\n                foreach (Material target in targets)\n                    target.parent = parent;\n            }\n        }\n\n        private bool DoHierarchyButton()\n        {\n            bool clicked = EditorGUILayout.DropdownButton(GUIContent.none, FocusType.Passive, GUILayout.MaxWidth(Styles.kHierarchyIconWidth));\n\n            Rect rect = GUILayoutUtility.topLevel.GetLast();\n            rect.x += 6;\n            if (convertState == ConvertAction.Convert)\n            {\n                float height = rect.height;\n                rect.height *= 0.8f;\n                rect.y += (height - rect.height) * 0.5f;\n                EditorGUI.LabelField(rect, Styles.convertIcon);\n            }\n            else\n                EditorGUI.LabelField(rect, Styles.hierarchyIcon);\n\n            return clicked;\n        }\n\n        private class ShaderSelectionDropdown : AdvancedDropdown\n        {\n            Action<object> m_OnSelectedShaderPopup;\n            Shader m_CurrentShader;\n\n            public ShaderSelectionDropdown(Shader shader, Action<object> onSelectedShaderPopup)\n                : base(new AdvancedDropdownState())\n            {\n                minimumSize = new Vector2(270, 308);\n                m_CurrentShader = shader;\n                m_OnSelectedShaderPopup = onSelectedShaderPopup;\n                m_DataSource = new ShaderDropdownDataSource(m_CurrentShader);\n                m_Gui = new MaterialDropdownGUI(m_DataSource);\n            }\n\n            protected override AdvancedDropdownItem BuildRoot()\n            {\n                return m_DataSource.mainTree;\n            }\n\n            protected override void ItemSelected(AdvancedDropdownItem item)\n            {\n                m_OnSelectedShaderPopup(((ShaderDropdownItem)item).fullName);\n            }\n\n            internal class ShaderDropdownDataSource : AdvancedDropdownDataSource\n            {\n                Shader m_CurrentShader;\n                internal ShaderDropdownDataSource(Shader currentShader) { m_CurrentShader = currentShader; }\n\n                protected override AdvancedDropdownItem FetchData()\n                {\n                    m_SearchableElements = new List<AdvancedDropdownItem>();\n                    var root = new AdvancedDropdownItem(\"Shaders\");\n\n                    var shaders = ShaderUtil.GetAllShaderInfo();\n                    var shaderList = new List<string>();\n                    var legacyList = new List<string>();\n                    var notSupportedList = new List<string>();\n                    var failedCompilationList = new List<string>();\n\n                    foreach (var shader in shaders)\n                    {\n                        if (shader.name.StartsWith(\"Deprecated\") || shader.name.StartsWith(\"Hidden\"))\n                        {\n                            continue;\n                        }\n                        if (shader.hasErrors)\n                        {\n                            failedCompilationList.Add(shader.name);\n                            continue;\n                        }\n                        if (!shader.supported)\n                        {\n                            notSupportedList.Add(shader.name);\n                            continue;\n                        }\n                        if (shader.name.StartsWith(\"Legacy Shaders/\"))\n                        {\n                            legacyList.Add(shader.name);\n                            continue;\n                        }\n                        shaderList.Add(shader.name);\n                    }\n\n                    shaderList.Sort();\n                    var unnestedList =  shaderList.Where(s => s.Count(c => c == '/') == 0).ToList();\n                    shaderList = shaderList.Where(s => s.Count(c => c == '/') > 0).ToList();\n                    shaderList.AddRange(unnestedList);\n\n                    legacyList.Sort();\n                    notSupportedList.Sort();\n                    failedCompilationList.Sort();\n\n                    shaderList.ForEach(s => AddShaderToMenu(\"\", root, s, s));\n                    if (legacyList.Any() || notSupportedList.Any() || failedCompilationList.Any())\n                        root.AddSeparator();\n                    legacyList.ForEach(s => AddShaderToMenu(\"\", root, s, s));\n                    notSupportedList.ForEach(s => AddShaderToMenu(\"Not supported/\", root, s, \"Not supported/\" + s));\n                    failedCompilationList.ForEach(s => AddShaderToMenu(\"Failed to compile/\", root, s, \"Failed to compile/\" + s));\n\n                    return root;\n                }\n\n                private void AddShaderToMenu(string prefix, AdvancedDropdownItem parent, string fullShaderName, string shaderName)\n                {\n                    var shaderNameParts = shaderName.Split('/');\n                    if (shaderNameParts.Length > 1)\n                    {\n                        AddShaderToMenu(prefix, FindOrCreateChild(parent, shaderName), fullShaderName, shaderName.Substring(shaderNameParts[0].Length + 1));\n                    }\n                    else\n                    {\n                        var item = new ShaderDropdownItem(prefix, fullShaderName, shaderName);\n                        parent.AddChild(item);\n                        m_SearchableElements.Add(item);\n                        if (m_CurrentShader != null && m_CurrentShader.name == fullShaderName)\n                        {\n                            selectedIDs.Add(item.id);\n                        }\n                    }\n                }\n\n                private AdvancedDropdownItem FindOrCreateChild(AdvancedDropdownItem parent, string path)\n                {\n                    var shaderNameParts = path.Split('/');\n                    var group = shaderNameParts[0];\n                    foreach (var child in parent.children)\n                    {\n                        if (child.name == group)\n                            return child;\n                    }\n\n                    var item = new AdvancedDropdownItem(group);\n                    parent.AddChild(item);\n                    return item;\n                }\n\n                protected override AdvancedDropdownItem Search(string searchString)\n                {\n                    if (string.IsNullOrEmpty(searchString) || m_SearchableElements == null)\n                        return null;\n\n                    // Support multiple search words separated by spaces.\n                    var searchWords = searchString.ToLower().Split(' ');\n                    var matched = new List<List<AdvancedDropdownItem>>();\n                    matched.Add(new List<AdvancedDropdownItem>());\n\n                    bool found = false;\n                    foreach (var e in m_SearchableElements)\n                    {\n                        if (e.children.Any())\n                            continue;\n\n                        var menuItem = (ShaderDropdownItem)e;\n                        var name = menuItem.fullName.ToLower().Replace(\" \", \"\");\n                        if (AddMatchItem(e, name, searchWords, matched))\n                            found = true;\n                    }\n                    if (!found)\n                    {\n                        foreach (var e in m_SearchableElements)\n                        {\n                            var menuItem = (ShaderDropdownItem)e;\n                            var name = menuItem.fullName.Replace(\" \", \"\");\n                            AddMatchItem(e, name, searchWords, matched);\n                        }\n                    }\n\n                    var searchTree = new AdvancedDropdownItem(\"Shaders\");\n                    for (int i = 0; i < matched.Count; i++)\n                    {\n                        matched[i].Sort((s2, s1) =>\n                        {\n                            var order = (int)((s2 as ShaderDropdownItem)?.fullName.Count(c => c == '/') - (s1 as ShaderDropdownItem)?.fullName.Count(c => c == '/'));\n                            if (order == 0)\n                                order = s2.name.CompareTo(s1.name);\n                            return order;\n                        });\n\n\n                        foreach (var element in matched[i])\n                        {\n                            searchTree.AddChild(element);\n                        }\n                    }\n\n                    return searchTree;\n                }\n\n                protected bool AddMatchItem(AdvancedDropdownItem e, string fullName, string[] searchWords, List<List<AdvancedDropdownItem>> matched)\n                {\n                    int index = -1;\n                    var splitName = searchWords[0].Contains('/') && searchWords.Length == 1 ? new string[1] { fullName } : fullName.Split('/');\n\n                    // See if we match ALL the search words.\n                    for (var w = 0; w < searchWords.Length; w++)\n                    {\n                        index = -1;\n\n                        for (int i = 0; i < splitName.Length; i++)\n                        {\n                            if (splitName[i].Contains(searchWords[w]))\n                            {\n                                if(i >= index)\n                                    index = i;\n                            }\n                            else if(i == splitName.Length - 1 && index == -1)\n                                return false;\n                        }\n                    }\n\n                    // index 0 is reserved for Shader name matches thus the actual index is always higher by one\n                    index++;\n\n                    if (index == splitName.Length)\n                        index = 0;\n\n                    if (index >= matched.Count)\n                    {\n                        for (int i = matched.Count; i <= index; i++)\n                        {\n                            matched.Add(new List<AdvancedDropdownItem>());\n                        }\n                    }\n\n                    matched[index].Add(e);\n                    return true;\n                }\n            }\n\n            private class ShaderDropdownItem : AdvancedDropdownItem\n            {\n                string m_FullName;\n                string m_Prefix;\n                public string fullName => m_FullName;\n                public string prefix => m_Prefix;\n\n                public ShaderDropdownItem(string prefix, string fullName, string shaderName)\n                    : base(shaderName)\n                {\n                    m_FullName = fullName;\n                    m_Prefix = prefix;\n                    id = (prefix + fullName + shaderName).GetHashCode();\n                }\n            }\n\n            private class MaterialDropdownGUI : AdvancedDropdownGUI\n            {\n                public MaterialDropdownGUI(AdvancedDropdownDataSource dataSource)\n                    : base(dataSource) { m_DataSource = dataSource; }\n\n                AdvancedDropdownDataSource m_DataSource;\n\n                private static class Styles\n                {\n                    internal static GUIStyle lineStyleFaint = new GUIStyle(\"DD ItemStyle\");\n                    internal static GUIStyle checkMark = \"DD ItemCheckmark\";\n                    public static GUIContent checkMarkContent = new GUIContent(\"✔\");\n\n                    static Styles()\n                    {\n                        float val = EditorGUIUtility.isProSkin ? 0.5f : 0.25f;\n                        lineStyleFaint.active.textColor = new Color(val, val, val, 1f);\n                        lineStyleFaint.focused.textColor = new Color(val, val, val, 1f);\n                        lineStyleFaint.hover.textColor = new Color(val, val, val, 1f);\n                        lineStyleFaint.normal.textColor = new Color(val, val, val, 1f);\n                    }\n                }\n\n                internal override void DrawItem(AdvancedDropdownItem item, string name, Texture2D icon, bool enabled, bool drawArrow, bool selected, bool hasSearch)\n                {\n                    var newScriptItem = item as ShaderDropdownItem;\n                    string text;\n                    if (hasSearch && newScriptItem != null)\n                    {\n                        DrawSearchItem(item, newScriptItem.name, newScriptItem.prefix + newScriptItem.fullName, selected);\n                        text = newScriptItem.fullName.Contains('/') ? $\"{name} ({newScriptItem.fullName})\" : name;\n                    }\n                    else\n                    {\n                        text = name;\n                        base.DrawItem(item, name, icon, enabled, drawArrow, selected, hasSearch);\n                    }\n\n                    if (Event.current.type == EventType.Repaint && hasSearch)\n                    {\n                        var tooltipRect = GUILayoutUtility.GetLastRect();\n                        GUI.Label(tooltipRect, new GUIContent(\"\", text));\n                    }\n                }\n\n                private void DrawSearchItem(AdvancedDropdownItem item, string name, string path, bool selected)\n                {\n                    path = $\" ({path.Substring(0, path.Length - name.Length).Trim('/')})\";\n                    path = path.Equals(\" ()\") ? \"\" : path; // if the path we're left with is equal to \" ()\" - scrap it\n\n                    var contentWithIcon = new GUIContent(name, path);\n\n                    var rect = GUILayoutUtility.GetRect(contentWithIcon, Styles.lineStyleFaint, GUILayout.ExpandWidth(true));\n                    var fullRect = new Rect(rect);\n\n                    if (Event.current.type != EventType.Repaint)\n                        return;\n\n                    bool checkMark = false;\n                    if (m_DataSource.selectedIDs.Any() && m_DataSource.selectedIDs.Contains(item.id))\n                    {\n                        checkMark = true;\n                        var checkMarkRect = new Rect(fullRect);\n                        checkMarkRect.width = iconSize.x + 1;\n                        Styles.checkMark.Draw(checkMarkRect, Styles.checkMarkContent, selected, selected, selected, selected);\n                    }\n\n                    var emptySpace = Styles.lineStyleFaint.CalcSize(contentWithIcon);\n                    rect.x += emptySpace.x + iconSize.x + 1;\n\n                    if (!checkMark)\n                        lineStyle.Draw(fullRect, new GUIContent(), selected, selected, selected, selected);\n\n                    fullRect.x += iconSize.x + 1;\n                    lineStyle.Draw(fullRect, contentWithIcon, selected & checkMark, selected & checkMark, selected & checkMark, selected & checkMark);\n\n                    Styles.lineStyleFaint.Draw(rect, new GUIContent(path, path), selected, false, false, false);\n                }\n            }\n        }\n\n        public virtual void Awake()\n        {\n            if (GetPreviewType(target as Material) == PreviewType.Skybox)\n                m_PreviewDir = new Vector2(0, 50);\n\n            m_SelectedMesh = EditorPrefs.GetInt(kDefaultMaterialPreviewMesh);\n        }\n\n        private void DetectShaderEditorNeedsUpdate()\n        {\n            var material = target as Material;\n            bool shaderChanged = material && material.shader != m_Shader;\n            bool customEditorChanged = material && material.shader && m_CustomEditorClassName != ShaderUtil.GetCurrentCustomEditor(material.shader);\n            if (shaderChanged || customEditorChanged)\n            {\n                CreateCustomShaderEditorIfNeeded(material.shader);\n                if (shaderChanged)\n                {\n                    m_Shader = material.shader;\n                    OnShaderChanged();\n                }\n                InspectorWindow.RepaintAllInspectors();\n            }\n        }\n\n        private string ParseValidationResult(StackValidationResult validationResult)\n        {\n            string[] errorMessages = validationResult.errorMessage.Split('\\n');\n\n            string result = \"'\" + validationResult.stackName + \"' is invalid\";\n            if (errorMessages.Length == 1)\n                result += \" (1 issue)\\n\";\n            else\n                result += \" (\" + errorMessages.Length + \" issues)\\n\";\n\n            for (int i = 0; i < errorMessages.Length; ++i)\n            {\n                result += \" - \" + errorMessages[i] + '\\n';\n            }\n\n            return result;\n        }\n\n        private void DetectTextureStackValidationIssues()\n        {\n            if (PlayerSettings.GetVirtualTexturingSupportEnabled())\n            {\n                if (isVisible && m_Shader != null && !HasMultipleMixedShaderValues())\n                {\n                    // We want additional spacing, but only when the material properties are visible\n                    EditorGUILayout.Space(EditorGUIUtility.singleLineHeight / 2.0f);\n                }\n\n                // We don't want these message boxes to be indented\n                EditorGUI.indentLevel--;\n\n                var material = target as Material;\n                StackValidationResult[] stackValidationResults = VirtualTexturing.EditorHelpers.ValidateMaterialTextureStacks(material);\n                if (stackValidationResults.Length == 0)\n                    return;\n\n                foreach (StackValidationResult validationResult in stackValidationResults)\n                {\n                    string errorBoxText = ParseValidationResult(validationResult);\n                    EditorGUILayout.HelpBox(errorBoxText, MessageType.Error);\n                }\n\n                // Reset the original indentation level\n                EditorGUI.indentLevel++;\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (ShouldEditorBeHidden())\n                return;\n\n            serializedObject.Update();\n\n            CheckSetup();\n            DetectShaderEditorNeedsUpdate();\n\n            if (isVisible && m_Shader != null && !HasMultipleMixedShaderValues())\n            {\n                // Show Material properties\n                if (PropertiesGUI())\n                {\n                    foreach (Material material in targets)\n                    {\n                        if (m_CustomShaderGUI != null)\n                            m_CustomShaderGUI.ValidateMaterial(material);\n                    }\n                    PropertiesChanged();\n                }\n            }\n\n            DetectTextureStackValidationIssues();\n        }\n\n        void CheckSetup()\n        {\n            if (!m_CheckSetup || m_Shader == null)\n                return;\n\n            m_CheckSetup = false;\n            if (m_CustomShaderGUI == null && !IsMaterialEditor(ShaderUtil.GetCurrentCustomEditor(m_Shader)))\n            {\n                Debug.LogWarningFormat(\"Could not create a custom UI for the shader '{0}'. The shader has the following: 'CustomEditor = {1}'. Does the custom editor specified include its namespace? And does the class either derive from ShaderGUI or MaterialEditor?\", m_Shader.name, ShaderUtil.GetCurrentCustomEditor(m_Shader));\n            }\n        }\n\n        // A minimal list of settings to be shown in the Asset Store preview inspector\n        internal override void OnAssetStoreInspectorGUI()\n        {\n            OnInspectorGUI();\n        }\n\n        public void PropertiesChanged()\n        {\n            // @TODO: Show performance warnings for multi-selections too?\n            m_InfoMessage = null;\n            if (targets.Length == 1)\n                m_InfoMessage = Utils.PerformanceChecks.CheckMaterial(target as Material, EditorUserBuildSettings.activeBuildTarget);\n        }\n\n        protected virtual void OnShaderChanged()\n        {\n        }\n\n        protected override void OnHeaderGUI()\n        {\n            if (ShouldEditorBeHidden())\n                return;\n\n            Rect titleRect = DrawHeaderGUI(this, targetTitle, firstInspectedEditor ? 0 : Styles.kSpaceForFoldoutArrow);\n            int id = GUIUtility.GetControlID(45678, FocusType.Passive);\n\n            if (!firstInspectedEditor)\n            {\n                Rect renderRect = EditorGUI.GetInspectorTitleBarObjectFoldoutRenderRect(titleRect);\n                renderRect.y = titleRect.yMax - 17f; // align with bottom\n                bool oldVisible = InternalEditorUtility.GetIsInspectorExpanded(target);\n                bool newVisible = EditorGUI.DoObjectFoldout(oldVisible, titleRect, renderRect, targets, id);\n\n                // Toggle visibility\n                if (newVisible != oldVisible)\n                    InternalEditorUtility.SetIsInspectorExpanded(target, newVisible);\n            }\n        }\n\n        internal override void OnHeaderControlsGUI()\n        {\n            // Clear cache in case material is modified externally\n            m_VariantCountCache = -1;\n            m_HasMixedParentCache = -1;\n\n            if (ShouldEditorBeHidden())\n                return;\n\n            serializedObject.Update();\n\n            var oldLabelWidth = EditorGUIUtility.labelWidth;\n            EditorGUIUtility.labelWidth = 50;\n\n            // Shader selection dropdown\n            using (new EditorGUI.DisabledScope(!IsEnabled() || GetVariantCount() != 0))\n                ShaderPopup(\"MiniPulldown\");\n\n            // Edit button for custom shaders\n            if (m_Shader != null && !HasMultipleMixedShaderValues() && (m_Shader.hideFlags & HideFlags.DontSave) == 0)\n            {\n                if (GUILayout.Button(\"Edit...\", EditorStyles.miniButton, GUILayout.ExpandWidth(false)))\n                    AssetDatabase.OpenAsset(m_Shader);\n            }\n\n            using (new EditorGUI.DisabledScope(targets.Length != 1))\n            {\n                if (DoHierarchyButton())\n                {\n                    var rect = GUILayoutUtility.topLevel.GetLast();\n                    PopupWindow.Show(rect, new MaterialHierarchyPopup(target as Material, IsEnabled(), this, rect));\n                    GUIUtility.ExitGUI();\n                }\n            }\n\n            if (AllTargetsAreVariants() || convertState == ConvertAction.Convert)\n            {\n                // Start a new line for parent\n                EditorGUILayout.EndHorizontal();\n                EditorGUILayout.BeginHorizontal();\n                if (!firstInspectedEditor)\n                    GUILayout.Space(Styles.kSpaceForFoldoutArrow);\n                using (new EditorGUI.DisabledScope(!IsEnabled()))\n                    ParentField(EditorGUILayout.GetControlRect(), HasMixedParent());\n            }\n\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n        }\n\n        // -------- obsolete helper functions to get/set material values\n\n        [System.Obsolete(\"Use GetMaterialProperty instead.\")]\n        public float GetFloat(string propertyName, out bool hasMixedValue)\n        {\n            hasMixedValue = false;\n            float f = ((Material)targets[0]).GetFloat(propertyName);\n            for (int i = 1; i < targets.Length; i++)\n            {\n                if (((Material)targets[i]).GetFloat(propertyName) != f)\n                {\n                    hasMixedValue = true;\n                    break;\n                }\n            }\n            return f;\n        }\n\n        [System.Obsolete(\"Use MaterialProperty instead.\")]\n        public void SetFloat(string propertyName, float value)\n        {\n            foreach (Material material in targets)\n                material.SetFloat(propertyName, value);\n        }\n\n        [System.Obsolete(\"Use GetMaterialProperty instead.\")]\n        public Color GetColor(string propertyName, out bool hasMixedValue)\n        {\n            hasMixedValue = false;\n            Color f = ((Material)targets[0]).GetColor(propertyName);\n            for (int i = 1; i < targets.Length; i++)\n                if (((Material)targets[i]).GetColor(propertyName) != f) { hasMixedValue = true; break; }\n            return f;\n        }\n\n        [System.Obsolete(\"Use MaterialProperty instead.\")]\n        public void SetColor(string propertyName, Color value)\n        {\n            foreach (Material material in targets)\n                material.SetColor(propertyName, value);\n        }\n\n        [System.Obsolete(\"Use GetMaterialProperty instead.\")]\n        public Vector4 GetVector(string propertyName, out bool hasMixedValue)\n        {\n            hasMixedValue = false;\n            Vector4 f = ((Material)targets[0]).GetVector(propertyName);\n            for (int i = 1; i < targets.Length; i++)\n                if (((Material)targets[i]).GetVector(propertyName) != f) { hasMixedValue = true; break; }\n            return f;\n        }\n\n        [System.Obsolete(\"Use MaterialProperty instead.\")]\n        public void SetVector(string propertyName, Vector4 value)\n        {\n            foreach (Material material in targets)\n                material.SetVector(propertyName, value);\n        }\n\n        [System.Obsolete(\"Use GetMaterialProperty instead.\")]\n        public Texture GetTexture(string propertyName, out bool hasMixedValue)\n        {\n            hasMixedValue = false;\n            Texture f = ((Material)targets[0]).GetTexture(propertyName);\n            for (int i = 1; i < targets.Length; i++)\n                if (((Material)targets[i]).GetTexture(propertyName) != f) { hasMixedValue = true; break; }\n            return f;\n        }\n\n        [System.Obsolete(\"Use MaterialProperty instead.\")]\n        public void SetTexture(string propertyName, Texture value)\n        {\n            foreach (Material material in targets)\n                material.SetTexture(propertyName, value);\n        }\n\n        [System.Obsolete(\"Use MaterialProperty instead.\")]\n        public Vector2 GetTextureScale(string propertyName, out bool hasMixedValueX, out bool hasMixedValueY)\n        {\n            hasMixedValueX = false;\n            hasMixedValueY = false;\n            Vector2 f = ((Material)targets[0]).GetTextureScale(propertyName);\n            for (int i = 1; i < targets.Length; i++)\n            {\n                Vector2 f2 = ((Material)targets[i]).GetTextureScale(propertyName);\n                if (f2.x != f.x) { hasMixedValueX = true; }\n                if (f2.y != f.y) { hasMixedValueY = true; }\n                if (hasMixedValueX && hasMixedValueY)\n                    break;\n            }\n            return f;\n        }\n\n        [System.Obsolete(\"Use MaterialProperty instead.\")]\n        public Vector2 GetTextureOffset(string propertyName, out bool hasMixedValueX, out bool hasMixedValueY)\n        {\n            hasMixedValueX = false;\n            hasMixedValueY = false;\n            Vector2 f = ((Material)targets[0]).GetTextureOffset(propertyName);\n            for (int i = 1; i < targets.Length; i++)\n            {\n                Vector2 f2 = ((Material)targets[i]).GetTextureOffset(propertyName);\n                if (f2.x != f.x) { hasMixedValueX = true; }\n                if (f2.y != f.y) { hasMixedValueY = true; }\n                if (hasMixedValueX && hasMixedValueY)\n                    break;\n            }\n            return f;\n        }\n\n        [System.Obsolete(\"Use MaterialProperty instead.\")]\n        public void SetTextureScale(string propertyName, Vector2 value, int coord)\n        {\n            foreach (Material material in targets)\n            {\n                Vector2 f = material.GetTextureScale(propertyName);\n                f[coord] = value[coord];\n                material.SetTextureScale(propertyName, f);\n            }\n        }\n\n        [System.Obsolete(\"Use MaterialProperty instead.\")]\n        public void SetTextureOffset(string propertyName, Vector2 value, int coord)\n        {\n            foreach (Material material in targets)\n            {\n                Vector2 f = material.GetTextureOffset(propertyName);\n                f[coord] = value[coord];\n                material.SetTextureOffset(propertyName, f);\n            }\n        }\n\n        // -------- helper functions to handle material variant overrides\n\n        internal static int GetVariantCount(Object[] targets)\n        {\n            int count = 0;\n            foreach (Material target in targets)\n                count += target.isVariant ? 1 : 0;\n            return count;\n        }\n\n        static bool AllTargetsAreVariants(Object[] targets)\n        {\n            return GetVariantCount(targets) == targets.Length;\n        }\n\n        static MaterialSerializedProperty GetMaterialSerializedProperty(SerializedProperty property)\n        {\n            if (property.propertyPath == \"m_LightmapFlags\")\n                return MaterialSerializedProperty.LightmapFlags;\n            if (property.propertyPath == \"m_EnableInstancingVariants\")\n                return MaterialSerializedProperty.EnableInstancingVariants;\n            if (property.propertyPath == \"m_DoubleSidedGI\")\n                return MaterialSerializedProperty.DoubleSidedGI;\n            if (property.propertyPath == \"m_CustomRenderQueue\")\n                return MaterialSerializedProperty.CustomRenderQueue;\n            throw new ArgumentException(string.Format(\"The SerializedProperty '{0}' is not supported by BeginProperty.\", property.propertyPath));\n        }\n\n        internal static void BeginProperty(MaterialSerializedProperty property, Object[] targets)\n        {\n            MaterialProperty.BeginProperty(property, targets);\n        }\n\n        internal static void BeginProperty(Rect rect, MaterialSerializedProperty property, Object[] targets)\n        {\n            MaterialProperty.BeginProperty(rect, null, property, targets);\n        }\n\n        public static void BeginProperty(SerializedProperty property)\n        {\n            MaterialProperty.BeginProperty(GetMaterialSerializedProperty(property), property.serializedObject.targetObjects);\n        }\n\n        public static void BeginProperty(Rect rect, SerializedProperty property)\n        {\n            MaterialProperty.BeginProperty(rect, null, GetMaterialSerializedProperty(property), property.serializedObject.targetObjects);\n        }\n\n        public static void BeginProperty(MaterialProperty property)\n        {\n            MaterialProperty.BeginProperty(property, property.targets);\n        }\n\n        public static void BeginProperty(Rect rect, MaterialProperty property)\n        {\n            MaterialProperty.BeginProperty(rect, property, 0, property.targets);\n        }\n\n        public static void EndProperty()\n        {\n            MaterialProperty.EndProperty();\n        }\n\n        // -------- helper functions to display common material controls\n\n        // The 'Property' methods that accept GUIContent are internal with different name to avoid\n        // breaking backwards compatibility caused by adding overloads:\n        // 'RangeProperty(prop, null);' would cause a compile error because of ambigious overloads.\n\n        public float RangeProperty(MaterialProperty prop, string label)\n        {\n            return RangePropertyInternal(prop, new GUIContent(label));\n        }\n\n        internal float RangePropertyInternal(MaterialProperty prop, GUIContent label)\n        {\n            Rect r = GetPropertyRect(prop, label, true);\n            return RangePropertyInternal(r, prop, label);\n        }\n\n        public float RangeProperty(Rect position, MaterialProperty prop, string label)\n        {\n            return RangePropertyInternal(position, prop, new GUIContent(label));\n        }\n\n        internal static float RangePropertyInternal(Rect position, MaterialProperty prop, GUIContent label)\n        {\n            return DoPowerRangeProperty(position, prop, label, 1f);\n        }\n\n        internal static float DoPowerRangeProperty(Rect position, MaterialProperty prop, GUIContent label, float power)\n        {\n            BeginProperty(position, prop);\n\n            EditorGUI.BeginChangeCheck();\n\n            // For range properties we want to show the slider so we adjust label width to use default width (setting it to 0)\n            // See SetDefaultGUIWidths where we set: EditorGUIUtility.labelWidth = GUIClip.visibleRect.width - EditorGUIUtility.fieldWidth - 17;\n            float oldLabelWidth = EditorGUIUtility.labelWidth;\n            EditorGUIUtility.labelWidth = 0f;\n\n            // fix for case 1245429 where we sometimes get a rounding issue when converting between gamma and linear, which causes us to break the slider\n            // we need to check if the range is inverted before clamping (case 1351151)\n            bool invert = prop.rangeLimits.x > prop.rangeLimits.y;\n            float value = Mathf.Clamp(prop.floatValue, invert ? prop.rangeLimits.y : prop.rangeLimits.x, invert ? prop.rangeLimits.x : prop.rangeLimits.y);\n\n            float newValue = EditorGUI.PowerSlider(position, label, value, prop.rangeLimits.x, prop.rangeLimits.y, power);\n\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n\n            if (EditorGUI.EndChangeCheck())\n                prop.floatValue = newValue;\n\n            EndProperty();\n\n            return prop.floatValue;\n        }\n\n        internal static int DoIntRangeProperty(Rect position, MaterialProperty prop, GUIContent label)\n        {\n            BeginProperty(position, prop);\n\n            EditorGUI.BeginChangeCheck();\n\n            // For range properties we want to show the slider so we adjust label width to use default width (setting it to 0)\n            // See SetDefaultGUIWidths where we set: EditorGUIUtility.labelWidth = GUIClip.visibleRect.width - EditorGUIUtility.fieldWidth - 17;\n            float oldLabelWidth = EditorGUIUtility.labelWidth;\n            EditorGUIUtility.labelWidth = 0f;\n\n            int newValue = EditorGUI.IntSlider(position, label, (int)prop.floatValue, (int)prop.rangeLimits.x, (int)prop.rangeLimits.y);\n\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n\n            if (EditorGUI.EndChangeCheck())\n                prop.floatValue = (float)newValue;\n\n            EndProperty();\n\n            return (int)prop.floatValue;\n        }\n\n        public int IntegerProperty(MaterialProperty prop, string label)\n        {\n            return IntegerPropertyInternal(prop, new GUIContent(label));\n        }\n\n        internal int IntegerPropertyInternal(MaterialProperty prop, GUIContent label)\n        {\n            Rect r = GetPropertyRect(prop, label, true);\n            return IntegerPropertyInternal(r, prop, label);\n        }\n\n        public int IntegerProperty(Rect position, MaterialProperty prop, string label)\n        {\n            return IntegerPropertyInternal(position, prop, new GUIContent(label));\n        }\n\n        internal int IntegerPropertyInternal(Rect position, MaterialProperty prop, GUIContent label)\n        {\n            BeginProperty(position, prop);\n\n            EditorGUI.BeginChangeCheck();\n            int newValue = EditorGUI.IntField(position, label, prop.intValue);\n            if (EditorGUI.EndChangeCheck())\n                prop.intValue = newValue;\n\n            EndProperty();\n\n            return prop.intValue;\n        }\n\n        public float FloatProperty(MaterialProperty prop, string label)\n        {\n            return FloatPropertyInternal(prop, new GUIContent(label));\n        }\n\n        internal float FloatPropertyInternal(MaterialProperty prop, GUIContent label)\n        {\n            Rect r = GetPropertyRect(prop, label, true);\n            return FloatPropertyInternal(r, prop, label);\n        }\n\n        public float FloatProperty(Rect position, MaterialProperty prop, string label)\n        {\n            return FloatPropertyInternal(position, prop, new GUIContent(label));\n        }\n\n        internal static float FloatPropertyInternal(Rect position, MaterialProperty prop, GUIContent label)\n        {\n            BeginProperty(position, prop);\n\n            EditorGUI.BeginChangeCheck();\n            float newValue = EditorGUI.FloatField(position, label, prop.floatValue);\n            if (EditorGUI.EndChangeCheck())\n                prop.floatValue = newValue;\n\n            EndProperty();\n\n            return prop.floatValue;\n        }\n\n        public Color ColorProperty(MaterialProperty prop, string label)\n        {\n            return ColorPropertyInternal(prop, new GUIContent(label));\n        }\n\n        internal Color ColorPropertyInternal(MaterialProperty prop, GUIContent label)\n        {\n            Rect r = GetPropertyRect(prop, label, true);\n            return ColorPropertyInternal(r, prop, label);\n        }\n\n        public Color ColorProperty(Rect position, MaterialProperty prop, string label)\n        {\n            return ColorPropertyInternal(position, prop, new GUIContent(label));\n        }\n\n        internal static Color ColorPropertyInternal(Rect position, MaterialProperty prop, GUIContent label)\n        {\n            BeginProperty(position, prop);\n\n            EditorGUI.BeginChangeCheck();\n            bool isHDR = ((prop.propertyFlags & ShaderPropertyFlags.HDR) != 0);\n            bool showAlpha = true;\n            Color newValue = EditorGUI.ColorField(position, label, prop.colorValue, true, showAlpha, isHDR);\n            if (EditorGUI.EndChangeCheck())\n                prop.colorValue = newValue;\n\n            EndProperty();\n\n            return prop.colorValue;\n        }\n\n        public Vector4 VectorProperty(MaterialProperty prop, string label)\n        {\n            return VectorProperty(prop, new GUIContent(label));\n        }\n\n        public Vector4 VectorProperty(MaterialProperty prop, GUIContent label)\n        {\n            Rect r = GetPropertyRect(prop, label, true);\n            return VectorProperty(r, prop, label);\n        }\n\n        public Vector4 VectorProperty(Rect position, MaterialProperty prop, string label)\n        {\n            return VectorPropertyInternal(position, prop, new GUIContent(label));\n        }\n\n        public Vector4 VectorProperty(Rect position, MaterialProperty prop, GUIContent label)\n        {\n            return VectorPropertyInternal(position, prop, label);\n        }\n\n        internal static Vector4 VectorPropertyInternal(in Rect position, in MaterialProperty prop, in GUIContent label)\n        {\n            BeginProperty(position, prop);\n\n            EditorGUI.BeginChangeCheck();\n\n            // We want to make room for the field in case it's drawn on the same line as the label\n            // Set label width to default width (zero) temporarily\n            var oldLabelWidth = EditorGUIUtility.labelWidth;\n            EditorGUIUtility.labelWidth = 0f;\n\n            Vector4 newValue;\n            if ((prop.propertyFlags & ShaderPropertyFlags.Vector3) != 0)\n            {\n                var vec3value = EditorGUI.Vector3Field(position, label, new Vector3(prop.vectorValue.x, prop.vectorValue.y, prop.vectorValue.z));\n                newValue = new Vector4(vec3value.x, vec3value.y, vec3value.z, 0);\n            }\n            else if ((prop.propertyFlags & ShaderPropertyFlags.Vector2) != 0)\n            {\n                var vec2value = EditorGUI.Vector2Field(position, label, new Vector2(prop.vectorValue.x, prop.vectorValue.y));\n                newValue = new Vector4(vec2value.x, vec2value.y, 0, 0);\n            }\n            else\n            {\n                newValue = EditorGUI.Vector4Field(position, label, prop.vectorValue);\n            }\n\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n\n            if (EditorGUI.EndChangeCheck())\n                prop.vectorValue = newValue;\n\n            EndProperty();\n\n            return prop.vectorValue;\n        }\n\n        // Using GUILayout\n        public void TextureScaleOffsetProperty(MaterialProperty property)\n        {\n            Rect rect = EditorGUILayout.GetControlRect(true, 2 * (kLineHeight + EditorGUI.kVerticalSpacingMultiField), EditorStyles.layerMaskField);\n            TextureScaleOffsetProperty(rect, property, false);\n        }\n\n        // Returns height used\n        public float TextureScaleOffsetProperty(Rect position, MaterialProperty property)\n        {\n            return TextureScaleOffsetProperty(position, property, true);\n        }\n\n        // Returns height used\n        public float TextureScaleOffsetProperty(Rect position, MaterialProperty property, bool partOfTexturePropertyControl)\n        {\n            BeginAnimatedCheck(position, property);\n\n            BeginProperty(position, property);\n\n            EditorGUI.BeginChangeCheck();\n            // Mixed value mask is 4 bits for the uv offset & scale (First bit is for the texture itself)\n            int mixedValuemask = property.mixedValueMask >> 1;\n            Vector4 scaleAndOffset = TextureScaleOffsetProperty(position, property.textureScaleAndOffset, mixedValuemask, partOfTexturePropertyControl);\n\n            if (EditorGUI.EndChangeCheck())\n                property.textureScaleAndOffset = scaleAndOffset;\n\n            EndProperty();\n\n            EndAnimatedCheck();\n            return 2 * kLineHeight;\n        }\n\n        private Texture TexturePropertyBody(Rect position, MaterialProperty prop)\n        {\n            if (prop.propertyType != ShaderPropertyType.Texture)\n            {\n                throw new ArgumentException(string.Format(\"The MaterialProperty '{0}' should be of type 'Texture' (its type is '{1})'\", prop.name, prop.propertyType));\n            }\n\n            m_DesiredTexdim = prop.textureDimension;\n            System.Type t = MaterialEditor.GetTextureTypeFromDimension(m_DesiredTexdim);\n\n            // Why are we disabling the GUI in Animation Mode here?\n            // If it's because object references can't be changed, shouldn't it be done in ObjectField instead?\n            bool wasEnabled = GUI.enabled;\n\n            EditorGUI.BeginChangeCheck();\n            if ((prop.propertyFlags & ShaderPropertyFlags.NonModifiableTextureData) != 0)\n                GUI.enabled = false;\n\n            EditorGUI.showMixedValue = prop.hasMixedValue;\n            int controlID = GUIUtility.GetControlID(12354, FocusType.Keyboard, position);\n            var newValue = EditorGUI.DoObjectField(position, position, controlID, prop.textureValue, target, t, TextureValidator, false) as Texture;\n            EditorGUI.showMixedValue = false;\n            if (EditorGUI.EndChangeCheck())\n                prop.textureValue = newValue;\n\n            GUI.enabled = wasEnabled;\n\n            return prop.textureValue;\n        }\n\n        public Texture TextureProperty(MaterialProperty prop, string label)\n        {\n            bool scaleOffset = ((prop.propertyFlags & ShaderPropertyFlags.NoScaleOffset) == 0);\n            return TextureProperty(prop, label, scaleOffset);\n        }\n\n        public Texture TextureProperty(MaterialProperty prop, string label, bool scaleOffset)\n        {\n            Rect r = GetPropertyRect(prop, label, true);\n            return TextureProperty(r, prop, label, scaleOffset);\n        }\n\n        public bool HelpBoxWithButton(GUIContent messageContent, GUIContent buttonContent)\n        {\n            const float kButtonWidth = 60f;\n            const float kSpacing = 5f;\n            const float kButtonHeight = 20f;\n\n            // Reserve size of wrapped text\n            Rect contentRect = GUILayoutUtility.GetRect(messageContent, EditorStyles.helpBox);\n            // Reserve size of button\n            GUILayoutUtility.GetRect(1, kButtonHeight + kSpacing);\n\n            // Render background box with text at full height\n            contentRect.height += kButtonHeight + kSpacing;\n            GUI.Label(contentRect, messageContent, EditorStyles.helpBox);\n\n            // Button (align lower right)\n            Rect buttonRect = new Rect(contentRect.xMax - kButtonWidth - 4f, contentRect.yMax - kButtonHeight - 4f, kButtonWidth, kButtonHeight);\n            return GUI.Button(buttonRect, buttonContent);\n        }\n\n        public void TextureCompatibilityWarning(MaterialProperty prop)\n        {\n            if (InternalEditorUtility.BumpMapTextureNeedsFixing(prop))\n            {\n                if (HelpBoxWithButton(\n                    EditorGUIUtility.TrTextContent(\"This texture is not marked as a normal map\"),\n                    EditorGUIUtility.TrTextContent(\"Fix Now\")))\n                {\n                    InternalEditorUtility.FixNormalmapTexture(prop);\n                }\n            }\n        }\n\n        public Texture TexturePropertyMiniThumbnail(Rect position, MaterialProperty prop, string label, string tooltip)\n        {\n            BeginProperty(position, prop);\n\n            BeginAnimatedCheck(position, prop);\n            Rect thumbRect, labelRect;\n            EditorGUI.GetRectsForMiniThumbnailField(position, out thumbRect, out labelRect);\n            EditorGUI.HandlePrefixLabel(position, labelRect, new GUIContent(label, tooltip), 0, EditorStyles.label);\n            EndAnimatedCheck();\n\n            Texture retValue = TexturePropertyBody(thumbRect, prop);\n\n            Rect warningPosition = position;\n            warningPosition.y += position.height;\n            warningPosition.height = kMiniWarningMessageHeight;\n\n            TextureCompatibilityWarning(prop);\n\n            EndProperty();\n\n            return retValue;\n        }\n\n        public Rect GetTexturePropertyCustomArea(Rect position)\n        {\n            EditorGUI.indentLevel++;\n            position.height = GetTextureFieldHeight();\n            Rect scaleOffsetRect = position;\n            scaleOffsetRect.yMin += EditorGUI.kSingleLineHeight;\n            scaleOffsetRect.xMax -= EditorGUIUtility.fieldWidth + 2;\n            scaleOffsetRect = EditorGUI.IndentedRect(scaleOffsetRect);\n            EditorGUI.indentLevel--;\n            return scaleOffsetRect;\n        }\n\n        public Texture TextureProperty(Rect position, MaterialProperty prop, string label)\n        {\n            return TextureProperty(position, prop, new GUIContent(label, string.Empty));\n        }\n\n        public Texture TextureProperty(Rect position, MaterialProperty prop, GUIContent label)\n        {\n            bool scaleOffset = ((prop.propertyFlags & ShaderPropertyFlags.NoScaleOffset) == 0);\n            return TextureProperty(position, prop, label, scaleOffset);\n        }\n\n        public Texture TextureProperty(Rect position, MaterialProperty prop, string label, bool scaleOffset)\n        {\n            return TextureProperty(position, prop, label, string.Empty, scaleOffset);\n        }\n\n        public Texture TextureProperty(Rect position, MaterialProperty prop, string label, string tooltip, bool scaleOffset)\n        {\n            return TextureProperty(position, prop, new GUIContent(label, tooltip), scaleOffset);\n        }\n\n        public Texture TextureProperty(Rect position, MaterialProperty prop, GUIContent label, bool scaleOffset)\n        {\n            Rect scopeRect = new Rect(position.x, position.y, position.width, EditorGUI.lineHeight);\n            BeginProperty(scopeRect, prop);\n\n            // Label\n            EditorGUI.PrefixLabel(position, label);\n\n            // Texture slot\n            position.height = GetTextureFieldHeight();\n            Rect texPos = position;\n            texPos.xMin = texPos.xMax - EditorGUIUtility.fieldWidth;\n            Texture value = TexturePropertyBody(texPos, prop);\n\n            EndProperty();\n\n            // UV scale and offset\n            if (scaleOffset)\n            {\n                TextureScaleOffsetProperty(GetTexturePropertyCustomArea(position), prop);\n            }\n\n            // Potential warning help boxes\n            {\n                GUILayout.Space(-kSpacingUnderTexture);\n                TextureCompatibilityWarning(prop);\n                GUILayout.Space(kSpacingUnderTexture);\n            }\n            return value;\n        }\n\n        public static Vector4 TextureScaleOffsetProperty(Rect position, Vector4 scaleOffset)\n        {\n            return TextureScaleOffsetProperty(position, scaleOffset, 0, false);\n        }\n\n        public static Vector4 TextureScaleOffsetProperty(Rect position, Vector4 scaleOffset, bool partOfTexturePropertyControl)\n        {\n            return TextureScaleOffsetProperty(position, scaleOffset, 0, partOfTexturePropertyControl);\n        }\n\n        internal static Vector4 TextureScaleOffsetProperty(Rect position, Vector4 scaleOffset, int mixedValueMask, bool partOfTexturePropertyControl)\n        {\n            Vector2 tiling = new Vector2(scaleOffset.x, scaleOffset.y);\n            Vector2 offset = new Vector2(scaleOffset.z, scaleOffset.w);\n\n            float labelWidth = EditorGUIUtility.labelWidth;\n            float controlStartX = position.x + labelWidth;\n            float labelStartX = position.x + EditorGUI.indent;\n\n            // Temporarily reset the indent level as it was already used above to compute the positions of the label and control. See issue 946082.\n            int oldIndentLevel = EditorGUI.indentLevel;\n\n            EditorGUI.indentLevel = 0;\n\n            if (partOfTexturePropertyControl)\n            {\n                labelWidth = 65;\n                controlStartX = position.x + labelWidth;\n                labelStartX = position.x;\n                position.y = position.yMax - 2 * kLineHeight; // align with large texture thumb bottom\n            }\n\n            // Tiling\n            Rect labelRect = new Rect(labelStartX, position.y, labelWidth, kLineHeight);\n            Rect valueRect = new Rect(controlStartX, position.y, position.width - labelWidth, kLineHeight);\n            EditorGUI.PrefixLabel(labelRect, s_TilingText);\n            tiling = EditorGUI.Vector2Field(valueRect, GUIContent.none, tiling);\n\n            // Offset\n            labelRect.y += kLineHeight + EditorGUI.kVerticalSpacingMultiField;\n            valueRect.y += kLineHeight + EditorGUI.kVerticalSpacingMultiField;\n            EditorGUI.PrefixLabel(labelRect, s_OffsetText);\n            offset = EditorGUI.Vector2Field(valueRect, GUIContent.none, offset);\n\n            // Restore the indent level\n            EditorGUI.indentLevel = oldIndentLevel;\n\n            return new Vector4(tiling.x, tiling.y, offset.x, offset.y);\n        }\n\n        public float GetPropertyHeight(MaterialProperty prop)\n        {\n            return GetPropertyHeight(prop, prop.displayName);\n        }\n\n        public float GetPropertyHeight(MaterialProperty prop, string label)\n        {\n            // has custom drawers?\n            float handlerHeight = 0f;\n            MaterialPropertyHandler handler = MaterialPropertyHandler.GetHandler(((Material)target).shader, prop.name);\n            if (handler != null)\n            {\n                handlerHeight = handler.GetPropertyHeight(prop, label ?? prop.displayName, this);\n                // if we have a property drawer (and not just decorators), exit now and don't add default height\n                if (handler.propertyDrawer != null)\n                    return handlerHeight;\n            }\n\n            // otherwise, return default height\n            return handlerHeight + GetDefaultPropertyHeight(prop);\n        }\n\n        private static float GetTextureFieldHeight()\n        {\n            return EditorGUI.kObjectFieldThumbnailHeight;\n        }\n\n        public static float GetDefaultPropertyHeight(MaterialProperty prop)\n        {\n            if (prop.propertyType == ShaderPropertyType.Vector)\n                return EditorGUI.kStructHeaderLineHeight + EditorGUI.kSingleLineHeight;\n\n            if (prop.propertyType == ShaderPropertyType.Texture)\n                return GetTextureFieldHeight() + kSpacingUnderTexture;\n\n            return EditorGUI.kSingleLineHeight;\n        }\n\n        private Rect GetPropertyRect(MaterialProperty prop, GUIContent label, bool ignoreDrawer)\n        {\n            return GetPropertyRect(prop, label.text, ignoreDrawer);\n        }\n\n        private Rect GetPropertyRect(MaterialProperty prop, string label, bool ignoreDrawer)\n        {\n            float handlerHeight = 0f;\n            if (!ignoreDrawer)\n            {\n                MaterialPropertyHandler handler = MaterialPropertyHandler.GetHandler(((Material)target).shader, prop.name);\n                if (handler != null)\n                {\n                    handlerHeight = handler.GetPropertyHeight(prop, label ?? prop.displayName, this);\n                    // if we have a property drawer (and not just decorators), exit now and don't add default height\n                    if (handler.propertyDrawer != null)\n                        return EditorGUILayout.GetControlRect(true, handlerHeight, EditorStyles.layerMaskField);\n                }\n            }\n\n            return EditorGUILayout.GetControlRect(true, handlerHeight + GetDefaultPropertyHeight(prop), EditorStyles.layerMaskField);\n        }\n\n        public void BeginAnimatedCheck(Rect totalPosition, MaterialProperty prop)\n        {\n            if (rendererForAnimationMode == null)\n                return;\n\n            s_AnimatedCheckStack.Push(new AnimatedCheckData(prop, totalPosition, GUI.backgroundColor));\n\n            Color overrideColor;\n            if (MaterialAnimationUtility.OverridePropertyColor(prop, rendererForAnimationMode, out overrideColor))\n                GUI.backgroundColor = overrideColor;\n        }\n\n        public void BeginAnimatedCheck(MaterialProperty prop)\n        {\n            BeginAnimatedCheck(Rect.zero, prop);\n        }\n\n        public void EndAnimatedCheck()\n        {\n            if (rendererForAnimationMode == null)\n                return;\n\n            AnimatedCheckData data = s_AnimatedCheckStack.Pop();\n            if (Event.current.type == EventType.ContextClick && data.totalPosition.Contains(Event.current.mousePosition))\n            {\n                DoPropertyContextMenu(data.property);\n            }\n\n            GUI.backgroundColor = data.color;\n        }\n\n        private void DoPropertyContextMenu(MaterialProperty prop)\n        {\n            if (contextualPropertyMenu != null)\n            {\n                GenericMenu pm = new GenericMenu();\n                contextualPropertyMenu(pm, prop, m_RenderersForAnimationMode);\n\n                if (pm.GetItemCount() > 0)\n                    pm.ShowAsContext();\n            }\n        }\n\n        public void ShaderProperty(MaterialProperty prop, string label)\n        {\n            ShaderProperty(prop, new GUIContent(label));\n        }\n\n        public void ShaderProperty(MaterialProperty prop, GUIContent label)\n        {\n            ShaderProperty(prop, label, 0);\n        }\n\n        public void ShaderProperty(MaterialProperty prop, string label, int labelIndent)\n        {\n            ShaderProperty(prop, new GUIContent(label), labelIndent);\n        }\n\n        public void ShaderProperty(MaterialProperty prop, GUIContent label, int labelIndent)\n        {\n            Rect r = GetPropertyRect(prop, label, false);\n            ShaderProperty(r, prop, label, labelIndent);\n        }\n\n        public void ShaderProperty(Rect position, MaterialProperty prop, string label)\n        {\n            ShaderProperty(position, prop, new GUIContent(label));\n        }\n\n        public void ShaderProperty(Rect position, MaterialProperty prop, GUIContent label)\n        {\n            ShaderProperty(position, prop, label, 0);\n        }\n\n        public void ShaderProperty(Rect position, MaterialProperty prop, string label, int labelIndent)\n        {\n            ShaderProperty(position, prop, new GUIContent(label), labelIndent);\n        }\n\n        public void ShaderProperty(Rect position, MaterialProperty prop, GUIContent label, int labelIndent)\n        {\n            BeginAnimatedCheck(position, prop);\n            EditorGUI.indentLevel += labelIndent;\n\n            // [PerRendererData] material properties are read-only as they are meant to be set in code on a per-renderer basis.\n            using (new EditorGUI.DisabledScope((prop.propertyFlags & ShaderPropertyFlags.PerRendererData) != 0))\n            {\n                ShaderPropertyInternal(position, prop, label);\n            }\n\n            EditorGUI.indentLevel -= labelIndent;\n            EndAnimatedCheck();\n        }\n\n        public void LightmapEmissionProperty()\n        {\n            LightmapEmissionProperty(0);\n        }\n\n        public void LightmapEmissionProperty(int labelIndent)\n        {\n            Rect r = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.layerMaskField);\n            LightmapEmissionProperty(r, labelIndent);\n        }\n\n        static MaterialGlobalIlluminationFlags GetGlobalIlluminationFlags(MaterialGlobalIlluminationFlags flags)\n        {\n            MaterialGlobalIlluminationFlags newFlags = MaterialGlobalIlluminationFlags.None;\n            if ((flags & MaterialGlobalIlluminationFlags.RealtimeEmissive) != 0)\n                newFlags = MaterialGlobalIlluminationFlags.RealtimeEmissive;\n            else if ((flags & MaterialGlobalIlluminationFlags.BakedEmissive) != 0)\n                newFlags = MaterialGlobalIlluminationFlags.BakedEmissive;\n\n            return newFlags;\n        }\n\n        public void LightmapEmissionProperty(Rect position, int labelIndent)\n        {\n            EditorGUI.indentLevel += labelIndent;\n\n            Object[] materials = targets;\n            Material firstMaterial = (Material)target;\n\n            // Calculate isMixed\n            MaterialGlobalIlluminationFlags giFlags = GetGlobalIlluminationFlags(firstMaterial.globalIlluminationFlags);\n            bool isMixed = false;\n            for (int i = 1; i < materials.Length; i++)\n            {\n                Material material = (Material)materials[i];\n\n                if (GetGlobalIlluminationFlags(material.globalIlluminationFlags) != giFlags)\n                    isMixed = true;\n            }\n\n            BeginProperty(position, MaterialSerializedProperty.LightmapFlags, targets);\n            EditorGUI.BeginChangeCheck();\n\n            bool realtimeGISupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime);\n\n            // Show popup\n            EditorGUI.showMixedValue = isMixed;\n            giFlags = (MaterialGlobalIlluminationFlags)EditorGUI.IntPopup(position, realtimeGISupported ? Styles.lightmapEmissiveLabelRealtimeGISupport : Styles.lightmapEmissiveLabel, (int)giFlags, Styles.lightmapEmissiveStrings, Styles.lightmapEmissiveValues);\n            EditorGUI.showMixedValue = false;\n\n            // Apply flags. But only the part that this tool modifies (RealtimeEmissive, BakedEmissive, None)\n            if (EditorGUI.EndChangeCheck())\n            {\n                foreach (Material material in materials)\n                {\n                    MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;\n\n                    flags &= ~(MaterialGlobalIlluminationFlags.RealtimeEmissive | MaterialGlobalIlluminationFlags.BakedEmissive);\n                    flags |= giFlags;\n\n                    material.globalIlluminationFlags = flags;\n                }\n            }\n\n            EndProperty();\n            EditorGUI.indentLevel -= labelIndent;\n        }\n\n        public bool EmissionEnabledProperty()\n        {\n            Material[] materials = Array.ConvertAll(targets, (Object o) => { return (Material)o; });\n\n            var settings = Lightmapping.GetLightingSettingsOrDefaultsFallback();\n\n            MaterialGlobalIlluminationFlags defaultEnabled = settings.realtimeGI ? MaterialGlobalIlluminationFlags.RealtimeEmissive\n                : (settings.bakedGI ? MaterialGlobalIlluminationFlags.BakedEmissive : MaterialGlobalIlluminationFlags.None);\n\n            // Calculate isMixed\n            bool enabled = materials[0].globalIlluminationFlags != MaterialGlobalIlluminationFlags.EmissiveIsBlack;\n            bool isMixed = false;\n            for (int i = 1; i < materials.Length; i++)\n            {\n                if ((materials[i].globalIlluminationFlags != MaterialGlobalIlluminationFlags.EmissiveIsBlack) != enabled)\n                {\n                    isMixed = true;\n                    break;\n                }\n            }\n\n            BeginProperty(MaterialSerializedProperty.LightmapFlags, targets);\n\n            // initial checkbox for enabling/disabling emission\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = isMixed;\n            enabled = EditorGUILayout.Toggle(Styles.emissionLabel, enabled);\n            EditorGUI.showMixedValue = false;\n            if (EditorGUI.EndChangeCheck())\n            {\n                RegisterPropertyChangeUndo(\"Emission Flags\");\n                foreach (Material mat in materials)\n                {\n                    mat.globalIlluminationFlags = enabled ? defaultEnabled : MaterialGlobalIlluminationFlags.EmissiveIsBlack;\n                }\n                EndProperty();\n                return enabled;\n            }\n\n            EndProperty();\n            return !isMixed && enabled;\n        }\n\n        public static void FixupEmissiveFlag(Material mat)\n        {\n            if (mat == null)\n                throw new ArgumentNullException(\"mat\");\n\n            mat.globalIlluminationFlags = FixupEmissiveFlag(mat.GetColor(\"_EmissionColor\"), mat.globalIlluminationFlags);\n        }\n\n        public static MaterialGlobalIlluminationFlags FixupEmissiveFlag(Color col, MaterialGlobalIlluminationFlags flags)\n        {\n            if ((flags & MaterialGlobalIlluminationFlags.BakedEmissive) != 0 && col.maxColorComponent == 0.0f) // flag black baked\n                flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;\n            else if (flags != MaterialGlobalIlluminationFlags.EmissiveIsBlack) // clear baked flag on everything else, unless it's explicity disabled\n                flags &= MaterialGlobalIlluminationFlags.AnyEmissive;\n            return flags;\n        }\n\n        public void LightmapEmissionFlagsProperty(int indent, bool enabled)\n        {\n            LightmapEmissionFlagsProperty(indent, enabled, false);\n        }\n\n        public void LightmapEmissionFlagsProperty(int indent, bool enabled, bool ignoreEmissionColor)\n        {\n            Material[] materials = Array.ConvertAll(targets, (Object o) => { return (Material)o; });\n\n            // Calculate isMixed\n            MaterialGlobalIlluminationFlags any_em = MaterialGlobalIlluminationFlags.AnyEmissive;\n            MaterialGlobalIlluminationFlags giFlags = materials[0].globalIlluminationFlags & any_em;\n            bool isMixed = false;\n            for (int i = 1; i < materials.Length; i++)\n            {\n                isMixed = isMixed || (materials[i].globalIlluminationFlags & any_em) != giFlags;\n            }\n\n            BeginProperty(MaterialSerializedProperty.LightmapFlags, targets);\n            EditorGUI.BeginChangeCheck();\n\n            bool realtimeGISupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime);\n\n            // Show popup\n            EditorGUI.showMixedValue = isMixed;\n            EditorGUI.indentLevel += indent;\n            giFlags = (MaterialGlobalIlluminationFlags)EditorGUILayout.IntPopup(realtimeGISupported ? Styles.lightmapEmissiveLabelRealtimeGISupport : Styles.lightmapEmissiveLabel, (int)giFlags, Styles.lightmapEmissiveStrings, Styles.lightmapEmissiveValues);\n            EditorGUI.indentLevel -= indent;\n            EditorGUI.showMixedValue = false;\n\n            // Apply flags. But only the part that this tool modifies (RealtimeEmissive, BakedEmissive, None)\n            RegisterPropertyChangeUndo(\"Emission Flags\");\n            bool applyFlags = EditorGUI.EndChangeCheck();\n            foreach (Material mat in materials)\n            {\n                mat.globalIlluminationFlags = applyFlags ? giFlags : mat.globalIlluminationFlags;\n                if (!ignoreEmissionColor)\n                {\n                    FixupEmissiveFlag(mat);\n                }\n            }\n\n            EndProperty();\n        }\n\n        void ShaderPropertyInternal(Rect position, MaterialProperty prop, GUIContent label)\n        {\n            // Use custom property drawers if needed\n            MaterialPropertyHandler handler = MaterialPropertyHandler.GetHandler(((Material)target).shader, prop.name);\n            if (handler != null)\n            {\n                handler.OnGUI(ref position, prop, label.text != null ? label : new GUIContent(prop.displayName), this);\n                // If we had a property drawer (and not just decorators), exit now and don't draw default UI.\n                if (handler.propertyDrawer != null)\n                    return;\n            }\n\n            DefaultShaderPropertyInternal(position, prop, label);\n        }\n\n        public void DefaultShaderProperty(MaterialProperty prop, string label)\n        {\n            DefaultShaderPropertyInternal(prop, new GUIContent(label));\n        }\n\n        internal void DefaultShaderPropertyInternal(MaterialProperty prop, GUIContent label)\n        {\n            Rect r = GetPropertyRect(prop, label, true);\n            DefaultShaderPropertyInternal(r, prop, label);\n        }\n\n        public void DefaultShaderProperty(Rect position, MaterialProperty prop, string label)\n        {\n            DefaultShaderPropertyInternal(position, prop, new GUIContent(label));\n        }\n\n        internal void DefaultShaderPropertyInternal(Rect position, MaterialProperty prop, GUIContent label)\n        {\n            switch (prop.propertyType)\n            {\n                case ShaderPropertyType.Range: // float ranges\n                    RangePropertyInternal(position, prop, label);\n                    break;\n                case ShaderPropertyType.Float: // floats\n                    FloatPropertyInternal(position, prop, label);\n                    break;\n                case ShaderPropertyType.Int: // ints\n                    IntegerPropertyInternal(position, prop, label);\n                    break;\n                case ShaderPropertyType.Color: // colors\n                    ColorPropertyInternal(position, prop, label);\n                    break;\n                case ShaderPropertyType.Texture: // textures\n                    TextureProperty(position, prop, label);\n                    break;\n                case ShaderPropertyType.Vector: // vectors\n                    VectorProperty(position, prop, label);\n                    break;\n                default:\n                    GUI.Label(position, \"Unknown property type: \" + prop.name + \": \" + (int)prop.propertyType);\n                    break;\n            }\n        }\n\n        // -------- obsolete versions of common controls\n\n\n        [System.Obsolete(\"Use RangeProperty with MaterialProperty instead.\")]\n        public float RangeProperty(string propertyName, string label, float v2, float v3)\n        {\n            MaterialProperty prop = GetMaterialProperty(targets, propertyName);\n            return RangeProperty(prop, label);\n        }\n\n        [System.Obsolete(\"Use FloatProperty with MaterialProperty instead.\")]\n        public float FloatProperty(string propertyName, string label)\n        {\n            MaterialProperty prop = GetMaterialProperty(targets, propertyName);\n            return FloatProperty(prop, label);\n        }\n\n        [System.Obsolete(\"Use ColorProperty with MaterialProperty instead.\")]\n        public Color ColorProperty(string propertyName, string label)\n        {\n            MaterialProperty prop = GetMaterialProperty(targets, propertyName);\n            return ColorProperty(prop, label);\n        }\n\n        [System.Obsolete(\"Use VectorProperty with MaterialProperty instead.\")]\n        public Vector4 VectorProperty(string propertyName, string label)\n        {\n            MaterialProperty prop = GetMaterialProperty(targets, propertyName);\n            return VectorProperty(prop, label);\n        }\n\n        [System.Obsolete(\"Use TextureProperty with MaterialProperty instead.\", true)]\n        public Texture TextureProperty(string propertyName, string label, ShaderUtil.ShaderPropertyTexDim texDim)\n        {\n            MaterialProperty prop = GetMaterialProperty(targets, propertyName);\n            return TextureProperty(prop, label);\n        }\n\n        [System.Obsolete(\"Use TextureProperty with MaterialProperty instead.\", true)]\n        public Texture TextureProperty(string propertyName, string label, ShaderUtil.ShaderPropertyTexDim texDim, bool scaleOffset)\n        {\n            MaterialProperty prop = GetMaterialProperty(targets, propertyName);\n            return TextureProperty(prop, label, scaleOffset);\n        }\n\n        [System.Obsolete(\"Use ShaderProperty that takes MaterialProperty parameter instead.\")]\n        public void ShaderProperty(Shader shader, int propertyIndex)\n        {\n            MaterialProperty prop = GetMaterialProperty(targets, propertyIndex);\n            ShaderProperty(prop, prop.displayName);\n        }\n\n        // -------- other functionality\n\n        public static MaterialProperty[] GetMaterialProperties(Object[] mats)\n        {\n            if (mats == null)\n                throw new ArgumentNullException(\"mats\");\n            if (Array.IndexOf(mats, null) >= 0)\n                throw new ArgumentException(\"List of materials contains null\");\n            return ShaderUtil.GetMaterialProperties(mats);\n        }\n\n        public static string[] GetMaterialPropertyNames(Object[] mats)\n        {\n            if (mats == null)\n                throw new ArgumentNullException(\"mats\");\n            if (Array.IndexOf(mats, null) >= 0)\n                throw new ArgumentException(\"List of materials contains null\");\n            return ShaderUtil.GetMaterialPropertyNames(mats);\n        }\n\n        public static MaterialProperty GetMaterialProperty(Object[] mats, string name)\n        {\n            if (mats == null)\n                throw new ArgumentNullException(\"mats\");\n            if (Array.IndexOf(mats, null) >= 0)\n                throw new ArgumentException(\"List of materials contains null\");\n            return ShaderUtil.GetMaterialProperty(mats, name);\n        }\n\n        public static MaterialProperty GetMaterialProperty(Object[] mats, int propertyIndex)\n        {\n            if (mats == null)\n                throw new ArgumentNullException(\"mats\");\n            if (Array.IndexOf(mats, null) >= 0)\n                throw new ArgumentException(\"List of materials contains null\");\n            return ShaderUtil.GetMaterialProperty(mats, propertyIndex);\n        }\n\n        class ForwardApplyMaterialModification\n        {\n            readonly Renderer[] renderers;\n            bool        isMaterialEditable;\n\n            public ForwardApplyMaterialModification(Renderer[] r, bool inIsMaterialEditable)\n            {\n                renderers = r;\n                isMaterialEditable = inIsMaterialEditable;\n            }\n\n            public bool DidModifyAnimationModeMaterialProperty(MaterialProperty property, int changedMask, object previousValue)\n            {\n                bool didModify = false;\n                foreach (Renderer renderer in renderers)\n                {\n                    didModify = didModify | MaterialAnimationUtility.ApplyMaterialModificationToAnimationRecording(property, changedMask, renderer, previousValue);\n                }\n\n                if (didModify)\n                    return true;\n\n                // If the material is not editable,\n                // then we explicitly make sure that things that these properties arecan not be recorded are not going to be applied to the material\n                return !isMaterialEditable;\n            }\n        }\n\n        static Renderer[] GetAssociatedRenderersFromInspector()\n        {\n            var imguicontainer = UIElementsUtility.GetCurrentIMGUIContainer();\n            if (imguicontainer != null)\n            {\n                var editorElement = imguicontainer.GetFirstAncestorOfType<IEditorElement>();\n                if (editorElement != null)\n                {\n                    return GetAssociatedRenderersFromEditors(editorElement.Editors);\n                }\n            }\n\n            return new Renderer[0];\n        }\n\n        internal static Renderer[] GetAssociatedRenderersFromEditors(IEnumerable<Editor> editors)\n        {\n            List<Renderer> renderers = new List<Renderer>();\n            foreach (var editor in editors)\n            {\n                foreach (Object target in editor.targets)\n                {\n                    var renderer = target as Renderer;\n                    if (renderer)\n                        renderers.Add(renderer);\n                }\n            }\n            return renderers.ToArray();\n        }\n\n        public static Renderer PrepareMaterialPropertiesForAnimationMode(MaterialProperty[] properties, bool isMaterialEditable)\n        {\n            Renderer[] renderers = PrepareMaterialPropertiesForAnimationMode(properties, GetAssociatedRenderersFromInspector(), isMaterialEditable);\n            return (renderers != null && renderers.Length > 0) ? renderers[0] : null;\n        }\n\n        internal static Renderer PrepareMaterialPropertiesForAnimationMode(MaterialProperty[] properties, Renderer renderer, bool isMaterialEditable)\n        {\n            Renderer[] renderers = PrepareMaterialPropertiesForAnimationMode(properties, new Renderer[] {renderer}, isMaterialEditable);\n            return (renderers != null && renderers.Length > 0) ? renderers[0] : null;\n        }\n\n        internal static Renderer[] PrepareMaterialPropertiesForAnimationMode(MaterialProperty[] properties, Renderer[] renderers, bool isMaterialEditable)\n        {\n            bool isInAnimationMode = AnimationMode.InAnimationMode();\n\n            if (renderers != null && renderers.Length > 0)\n            {\n                var callback = new ForwardApplyMaterialModification(renderers, isMaterialEditable);\n                var block = new MaterialPropertyBlock();\n\n                renderers[0].GetPropertyBlock(block);\n                foreach (MaterialProperty prop in properties)\n                {\n                    prop.ReadFromMaterialPropertyBlock(block);\n                    if (isInAnimationMode)\n                        prop.applyPropertyCallback = callback.DidModifyAnimationModeMaterialProperty;\n                }\n            }\n\n            if (isInAnimationMode)\n                return renderers;\n            else\n                return null;\n        }\n\n        public void SetDefaultGUIWidths()\n        {\n            EditorGUIUtility.fieldWidth = EditorGUI.kObjectFieldThumbnailHeight;\n            EditorGUIUtility.labelWidth = GUIClip.visibleRect.width - EditorGUIUtility.fieldWidth - 25 - EditorGUI.kIndentPerLevel;\n        }\n\n        internal override bool GetOptimizedGUIBlock(bool isDirty, bool isVisible, out float height)\n        {\n            // Shift UI to the right to leave space for locks\n            // Done here because it's the only place between the creation of the vertical group and the call ot OnInspectorGUI\n            // And because OnInspectorGUI might be overriden by a user editor\n            var style = GUILayoutUtility.topLevel.style = new GUIStyle(GUILayoutUtility.topLevel.style);\n            style.padding.left += (int)EditorGUI.kIndentPerLevel;\n            return base.GetOptimizedGUIBlock(isDirty, isVisible, out height);\n        }\n\n        private bool IsMaterialEditor(string customEditorName)\n        {\n            string unityEditorFullName = \"UnityEditor.\" + customEditorName; // for convenience: adding UnityEditor namespace is not needed in the shader\n\n            foreach (var type in TypeCache.GetTypesDerivedFrom<MaterialEditor>())\n            {\n                if (type.FullName.Equals(customEditorName, StringComparison.Ordinal) ||\n                    type.FullName.Equals(unityEditorFullName, StringComparison.Ordinal))\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        void CreateCustomShaderEditorIfNeeded(Shader shader)\n        {\n            var customEditorName = ShaderUtil.GetCurrentCustomEditor(shader);\n            if (string.IsNullOrEmpty(customEditorName))\n            {\n                m_CustomEditorClassName = \"\";\n                m_CustomShaderGUI = null;\n                return;\n            }\n            if (m_CustomEditorClassName == customEditorName)\n                return;\n\n            m_CustomEditorClassName = customEditorName;\n            m_CustomShaderGUI = ShaderGUIUtility.CreateShaderGUI(m_CustomEditorClassName);\n            // We need to delay checking setup because we need all loaded editor assemblies which is not ready\n            // during package import. During package import we create an Editor to generate a asset preview. (case 707328)\n            m_CheckSetup = true;\n        }\n\n        public bool PropertiesGUI()\n        {\n            // Material Editor is the first inspected editor when accessed through the Project panel\n            // and this is the scenario where we do not want to redraw the VC status bar\n            // since InspectorWindow already takes care of that. Otherwise, the Material Editor\n            // is not the first inspected editor (e.g. when it's a part of a GO Inspector)\n            // thus we draw the VC status bar\n            if (!firstInspectedEditor)\n            {\n                // OnInspectorGUI is wrapped inside a BeginVertical/EndVertical block that adds padding,\n                // which we don't want here so we could have the VC bar span the entire Material Editor width\n                // we stop the vertical block, draw the VC bar, and then start a new vertical block with the same style.\n                var style = GUILayoutUtility.topLevel.style;\n                EditorGUILayout.EndVertical();\n\n                // setting the GUI to enabled where the VC status bar is drawn because it gets disabled by the parent inspector\n                // for non-checked out materials, and we need the version control status bar to be always active\n                bool wasGUIEnabled = GUI.enabled;\n                GUI.enabled = true;\n\n                PropertyEditor.VersionControlBar(this);\n\n                GUI.enabled = wasGUIEnabled;\n                EditorGUILayout.BeginVertical(style);\n            }\n\n            var eventType = Event.current.type;\n            bool isRunningCommand = eventType == EventType.ExecuteCommand || eventType == EventType.ValidateCommand;\n            if (m_InsidePropertiesGUI && !isRunningCommand)\n            {\n                Debug.LogWarning(\"PropertiesGUI() is being called recursively. If you want to render the default gui for shader properties then call PropertiesDefaultGUI() instead\");\n                return false;\n            }\n\n            EditorGUI.BeginChangeCheck();\n\n            MaterialProperty[] props = GetMaterialProperties(targets);\n\n            // In animation mode we are actually animating the Renderer instead of the material.\n            // Thus all properties are editable even if the material is not editable.\n            m_RenderersForAnimationMode = PrepareMaterialPropertiesForAnimationMode(props, GetAssociatedRenderersFromInspector(), GUI.enabled);\n            bool wasEnabled = GUI.enabled;\n            if (m_RenderersForAnimationMode != null)\n                GUI.enabled = true;\n\n            if (!isRunningCommand)\n                m_InsidePropertiesGUI = true;\n\n            // Since ExitGUI is called when showing the Object Picker we wrap\n            // properties gui in try/catch to catch the ExitGUIException thrown by ExitGUI()\n            // to ensure our m_InsidePropertiesGUI flag is reset\n            try\n            {\n                if (m_CustomShaderGUI != null)\n                    m_CustomShaderGUI.OnGUI(this, props);\n                else\n                    PropertiesDefaultGUI(props);\n\n                Renderer[] renderers = GetAssociatedRenderersFromInspector();\n                if (renderers != null && renderers.Length > 0)\n                {\n                    if (eventType == EventType.Layout)\n                    {\n                        renderers[0].GetPropertyBlock(m_PropertyBlock);\n                    }\n\n                    if (m_PropertyBlock != null && !m_PropertyBlock.isEmpty)\n                        EditorGUILayout.HelpBox(Styles.propBlockInfo, MessageType.Info);\n                }\n            }\n            catch (Exception)\n            {\n                throw;\n            }\n            finally\n            {\n                GUI.enabled = wasEnabled;\n                if (!isRunningCommand)\n                    m_InsidePropertiesGUI = false;\n                m_RenderersForAnimationMode = null;\n            }\n\n            return EditorGUI.EndChangeCheck();\n        }\n\n        public void PropertiesDefaultGUI(MaterialProperty[] props)\n        {\n            SetDefaultGUIWidths();\n\n            if (m_InfoMessage != null)\n                EditorGUILayout.HelpBox(m_InfoMessage, MessageType.Info);\n            else\n                // Hack to make sure that control IDs stay the same when the help box is there or is not there.\n                // Otherwise, open color picker windows will not keep synched to the same properties when the help box\n                // shows up or disappears (case 566958)\n                GUIUtility.GetControlID(s_ControlHash, FocusType.Passive, new Rect(0, 0, 0, 0));\n\n            for (var i = 0; i < props.Length; i++)\n            {\n                if ((props[i].propertyFlags & ShaderPropertyFlags.HideInInspector) != 0)\n                    continue;\n\n                float h = GetPropertyHeight(props[i], props[i].displayName);\n                Rect r = EditorGUILayout.GetControlRect(true, h, EditorStyles.layerMaskField);\n\n                ShaderProperty(r, props[i], props[i].displayName);\n            }\n\n            EditorGUILayout.Space();\n            EditorGUILayout.Space();\n\n            if (UnityEngine.Rendering.SupportedRenderingFeatures.active.editableMaterialRenderQueue)\n                RenderQueueField();\n            EnableInstancingField();\n            DoubleSidedGIField();\n        }\n\n        internal static void BeginNoApplyMaterialPropertyDrawers()\n        {\n            EditorMaterialUtility.disableApplyMaterialPropertyDrawers = true;\n        }\n\n        internal static void EndNoApplyMaterialPropertyDrawers()\n        {\n            EditorMaterialUtility.disableApplyMaterialPropertyDrawers = false;\n        }\n\n        public static void ApplyMaterialPropertyDrawers(Material material)\n        {\n            var objs = new Object[] { material };\n            ApplyMaterialPropertyDrawers(objs);\n        }\n\n        [RequiredByNativeCode]\n        internal static void ApplyMaterialPropertyDrawersFromNative(Material material)\n        {\n            var objs = new Object[] { material };\n            ApplyMaterialPropertyDrawers(objs);\n        }\n\n        public static void ApplyMaterialPropertyDrawers(Object[] targets)\n        {\n            if (!EditorMaterialUtility.disableApplyMaterialPropertyDrawers)\n            {\n                if (targets == null || targets.Length == 0)\n                    return;\n                var target = targets[0] as Material;\n                if (target == null)\n                    return;\n\n                var shader = target.shader;\n                var propNames = GetMaterialPropertyNames(targets);\n                for (var i = 0; i < propNames.Length; i++)\n                {\n                    MaterialPropertyHandler handler = MaterialPropertyHandler.GetHandler(shader, propNames[i]);\n                    if (handler != null && handler.propertyDrawer != null)\n                    {\n                        var prop = GetMaterialProperty(targets, i);\n                        handler.propertyDrawer.Apply(prop);\n                    }\n                }\n            }\n        }\n\n        public void RegisterPropertyChangeUndo(string label)\n        {\n            Undo.RecordObjects(targets, \"Modify \" + label + \" of \" + targetTitle);\n        }\n\n        private UnityEngine.Rendering.TextureDimension m_DesiredTexdim;\n\n        private Object TextureValidator(Object[] references, System.Type objType, SerializedProperty property, EditorGUI.ObjectFieldValidatorOptions options)\n        {\n            foreach (Object i in references)\n            {\n                var t = i as Texture;\n                if (t)\n                {\n                    if (t.dimension == m_DesiredTexdim || m_DesiredTexdim == UnityEngine.Rendering.TextureDimension.Any)\n                        return t;\n                }\n            }\n            return null;\n        }\n\n        private static readonly Mesh[] s_Meshes = {null, null, null, null, null };\n        private static Mesh s_PlaneMesh;\n        private static readonly GUIContent[] s_MeshIcons = { null, null, null, null, null };\n        private static readonly GUIContent[] s_LightIcons = { null, null };\n        private static readonly GUIContent[] s_TimeIcons = { null, null };\n\n        private void Init()\n        {\n            if (s_Meshes[0] == null)\n            {\n                var handleGo = (GameObject)EditorGUIUtility.LoadRequired(\"Previews/PreviewMaterials.fbx\");\n                // @TODO: temp workaround to make it not render in the scene\n                handleGo.SetActive(false);\n                foreach (Transform t in handleGo.transform)\n                {\n                    var meshFilter = t.GetComponent<MeshFilter>();\n                    switch (t.name)\n                    {\n                        case \"sphere\":\n                            s_Meshes[0] = meshFilter.sharedMesh;\n                            break;\n                        case \"cube\":\n                            s_Meshes[1] = meshFilter.sharedMesh;\n                            break;\n                        case \"cylinder\":\n                            s_Meshes[2] = meshFilter.sharedMesh;\n                            break;\n                        case \"torus\":\n                            s_Meshes[3] = meshFilter.sharedMesh;\n                            break;\n                        default:\n                            Debug.Log(\"Something is wrong, weird object found: \" + t.name);\n                            break;\n                    }\n                }\n\n                s_MeshIcons[0] = EditorGUIUtility.TrIconContent(\"PreMatSphere\");\n                s_MeshIcons[1] = EditorGUIUtility.TrIconContent(\"PreMatCube\");\n                s_MeshIcons[2] = EditorGUIUtility.TrIconContent(\"PreMatCylinder\");\n                s_MeshIcons[3] = EditorGUIUtility.TrIconContent(\"PreMatTorus\");\n                s_MeshIcons[4] = EditorGUIUtility.TrIconContent(\"PreMatQuad\");\n\n                s_LightIcons[0] = EditorGUIUtility.TrIconContent(\"PreMatLight0\");\n                s_LightIcons[1] = EditorGUIUtility.TrIconContent(\"PreMatLight1\");\n\n                s_TimeIcons[0] = EditorGUIUtility.TrIconContent(\"PlayButton\");\n                s_TimeIcons[1] = EditorGUIUtility.TrIconContent(\"PauseButton\");\n\n                Mesh quadMesh = Resources.GetBuiltinResource(typeof(Mesh), \"Quad.fbx\") as Mesh;\n                s_Meshes[4] = quadMesh;\n                s_PlaneMesh = quadMesh;\n            }\n        }\n\n        public override void OnPreviewSettings()\n        {\n            if (m_CustomShaderGUI != null)\n                m_CustomShaderGUI.OnMaterialPreviewSettingsGUI(this);\n            else\n                DefaultPreviewSettingsGUI();\n        }\n\n        private bool DoReflectionProbePicker(out Rect buttonRect)\n        {\n            buttonRect = GUILayoutUtility.GetRect(Styles.reflectionProbePickerIcon, EditorStyles.toolbarDropDownRight);\n\n            if (EditorGUI.DropdownButton(buttonRect, Styles.reflectionProbePickerIcon, FocusType.Passive, EditorStyles.toolbarDropDownRight))\n                return true;\n\n            return false;\n        }\n\n        public void DefaultPreviewSettingsGUI()\n        {\n            var mat = target as Material;\n            if (!SupportsRenderingPreview(mat))\n                return;\n\n            Init();\n\n            var viewType = GetPreviewType(mat);\n            if (targets.Length > 1 || viewType == PreviewType.Mesh)\n            {\n                var oldSelectedMeshVal = m_SelectedMesh;\n                m_TimeUpdate = PreviewGUI.CycleButton(m_TimeUpdate, s_TimeIcons);\n\n                m_SelectedMesh = PreviewGUI.CycleButton(m_SelectedMesh, s_MeshIcons);\n\n                if (oldSelectedMeshVal != m_SelectedMesh)\n                    EditorPrefs.SetInt(kDefaultMaterialPreviewMesh, m_SelectedMesh);\n\n                m_LightMode = PreviewGUI.CycleButton(m_LightMode, s_LightIcons);\n\n                Rect settingsButton;\n                if (DoReflectionProbePicker(out settingsButton))\n                    PopupWindow.Show(settingsButton, m_ReflectionProbePicker);\n            }\n        }\n\n        public sealed override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height)\n        {\n            var mat = target as Material;\n            if (!SupportsRenderingPreview(mat))\n                return null;\n\n            Init();\n\n            var previewRenderUtility = GetPreviewRendererUtility();\n            EditorUtility.SetCameraAnimateMaterials(previewRenderUtility.camera, true);\n\n            previewRenderUtility.BeginStaticPreview(new Rect(0, 0, width, height));\n            StreamRenderResources();\n            DoRenderPreview(previewRenderUtility, true);\n            return previewRenderUtility.EndStaticPreview();\n        }\n\n        private void StreamRenderResources()\n        {\n            //Streaming texture tiles if the material uses VT\n            if (PlayerSettings.GetVirtualTexturingSupportEnabled())\n            {\n                foreach (var t in targets)\n                {\n                    var mat = t as Material;\n                    var shader = mat.shader;\n\n                    //Find all texture stacks and the maximum texture dimension per stack\n                    var stackTextures = new Dictionary<int, int>();\n\n                    int count = shader.GetPropertyCount();\n                    for (int i = 0; i < count; i++)\n                    {\n                        if (shader.GetPropertyType(i) == UnityEngine.Rendering.ShaderPropertyType.Texture)\n                        {\n                            string stackName;\n                            int dummy;\n\n                            if (shader.FindTextureStack(i, out stackName, out dummy))\n                            {\n                                var stackId = Shader.PropertyToID(stackName);\n\n                                if (!stackTextures.ContainsKey(stackId))\n                                {\n                                    //Get the dimension of the texture stack. This can be different from the texture dimensions.\n                                    try\n                                    {\n                                        int width, height;\n                                        VirtualTexturing.Streaming.GetTextureStackSize(mat, stackId, out width, out height);\n                                        stackTextures[stackId] = Math.Max(width, height);\n                                    }\n                                    catch\n                                    {\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    if (stackTextures.Count != 0)\n                    {\n                        //@TODO Poor mans prefetching. Remove once we request the mips synchronously and are guaranteed that they are in the cache.\n                        //Now we need to update the VT system. We sleep to make sure any VT threads (transcoder?) can pick up the work.\n\n                        const int numberOfVTUpdates = 3; // We assume the texture data will be in the texture tile cache after this number of updates\n                        //Streaming texture mips for all the stacks so we have texture data to render with\n                        for (int i = 0; i < numberOfVTUpdates; i++)\n                        {\n                            foreach (var item in stackTextures)\n                            {\n                                var stackId = item.Key;\n                                var maxDimension = item.Value;\n\n                                //Requesting the 256x256 mip and 128x128 mip so that their is content in the cache to render with\n                                const int mipResolutionToRequest = 256;\n                                int mipToRequest = 0;\n\n                                if (maxDimension > mipResolutionToRequest)\n                                {\n                                    float factor = (float)maxDimension / (float)mipResolutionToRequest;\n                                    mipToRequest = (int)Math.Log(factor, 2);\n                                }\n\n                                //@TODO use synchronous requesting once it is available.\n                                VirtualTexturing.Streaming.RequestRegion(mat, stackId, new Rect(0, 0, 1, 1), mipToRequest, 2);\n                            }\n\n                            //2 system updates per sleep to make sure we flush the VT system while limiting sleeping.\n                            VirtualTexturing.System.Update();\n                            System.Threading.Thread.Sleep(1);\n                            VirtualTexturing.System.Update();\n                        }\n                    }\n                }\n            }\n        }\n\n        private void DoRenderPreview(PreviewRenderUtility previewRenderUtility, bool overridePreviewMesh = false)\n        {\n            if (previewRenderUtility.renderTexture.width <= 0 || previewRenderUtility.renderTexture.height <= 0)\n                return;\n\n            var mat = target as Material;\n            var viewType = GetPreviewType(mat);\n\n            previewRenderUtility.camera.transform.position = -Vector3.forward * 5;\n            previewRenderUtility.camera.transform.rotation = Quaternion.identity;\n            if (m_LightMode == 0)\n            {\n                previewRenderUtility.lights[0].intensity = 1.0f;\n                previewRenderUtility.lights[0].transform.rotation = Quaternion.Euler(30f, 30f, 0);\n                previewRenderUtility.lights[1].intensity = 0;\n            }\n            else\n            {\n                previewRenderUtility.lights[0].intensity = 1.0f;\n                previewRenderUtility.lights[0].transform.rotation = Quaternion.Euler(50f, 50f, 0);\n                previewRenderUtility.lights[1].intensity = 1.0f;\n            }\n\n            previewRenderUtility.ambientColor = new Color(0.2f, 0.2f, 0.2f, 0);\n\n            Quaternion rot = Quaternion.identity;\n            if (DoesPreviewAllowRotation(viewType))\n                rot = Quaternion.Euler(m_PreviewDir.y, 0, 0) * Quaternion.Euler(0, m_PreviewDir.x, 0);\n            Mesh mesh = overridePreviewMesh ? s_Meshes[0] : s_Meshes[m_SelectedMesh];\n\n            switch (viewType)\n            {\n                case PreviewType.Plane:\n                    mesh = s_PlaneMesh;\n                    break;\n                case PreviewType.Mesh:\n                    // We need to rotate camera, so we can see different reflections from different angles\n                    // If we would only rotate object, the reflections would stay the same\n                    previewRenderUtility.camera.transform.position = Quaternion.Inverse(rot) * previewRenderUtility.camera.transform.position;\n                    previewRenderUtility.camera.transform.LookAt(Vector3.zero);\n                    rot = Quaternion.identity;\n                    break;\n                case PreviewType.Skybox:\n                    mesh = null;\n                    previewRenderUtility.camera.transform.rotation = Quaternion.Inverse(rot);\n                    previewRenderUtility.camera.fieldOfView = 120.0f;\n                    break;\n            }\n\n            if (mesh != null)\n            {\n                previewRenderUtility.DrawMesh(mesh, Vector3.zero, rot, mat, 0, null, m_ReflectionProbePicker.Target, false);\n            }\n\n            previewRenderUtility.Render(true);\n            if (viewType == PreviewType.Skybox)\n            {\n                InternalEditorUtility.DrawSkyboxMaterial(mat, previewRenderUtility.camera);\n            }\n        }\n\n        public sealed override bool HasPreviewGUI()\n        {\n            return true;\n        }\n\n        public override bool RequiresConstantRepaint()\n        {\n            return m_TimeUpdate == 1;\n        }\n\n        public override void OnInteractivePreviewGUI(Rect r, GUIStyle background)\n        {\n            if (m_CustomShaderGUI != null)\n                m_CustomShaderGUI.OnMaterialInteractivePreviewGUI(this, r, background);\n            else\n                base.OnInteractivePreviewGUI(r, background);\n        }\n\n        public override void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            if (m_CustomShaderGUI != null)\n                m_CustomShaderGUI.OnMaterialPreviewGUI(this, r, background);\n            else\n                DefaultPreviewGUI(r, background);\n        }\n\n        // TO DO: remove IMGUI code after fully finished with UITK one\n        public override VisualElement CreatePreview(VisualElement inspectorPreviewWindow)\n        {\n            var window = inspectorPreviewWindow as InspectorPreviewWindow;\n            var toolbar = window?.GetButtonPane();\n\n            var mat = target as Material;\n            if (!SupportsRenderingPreview(mat))\n                return null;\n\n            Init();\n\n            var viewType = GetPreviewType(mat);\n            if (toolbar != null && (targets.Length > 1 || viewType == PreviewType.Mesh))\n            {\n                window.AddButton(Styles.timeUpdateButtonName, (Texture2D)s_TimeIcons[m_TimeUpdate].image, () => OnTimeUpdateClick(window));\n                window.AddButton(Styles.selectedMeshButtonName, (Texture2D)s_MeshIcons[m_SelectedMesh].image, () => OnSelectedMeshClick(window));\n                window.AddButton(Styles.lightModeButtonName, (Texture2D)s_LightIcons[m_LightMode].image, () => OnLightModeClick(window));\n                window.AddDropdownWithIcon(Styles.reflectionProbeDropdownName, (Texture2D)Styles.reflectionProbePickerIcon.image, () => OnReflectionProbeClick(toolbar));\n            }\n\n            return window;\n        }\n\n        void OnTimeUpdateClick(InspectorPreviewWindow window) { m_TimeUpdate = OnButtonClick(Styles.timeUpdateButtonName, m_TimeUpdate, s_TimeIcons, window); }\n\n        void OnLightModeClick(InspectorPreviewWindow window) { m_LightMode = OnButtonClick(Styles.lightModeButtonName, m_LightMode, s_LightIcons, window); }\n\n        void OnSelectedMeshClick(InspectorPreviewWindow window)\n        {\n            m_SelectedMesh = OnButtonClick(Styles.selectedMeshButtonName, m_SelectedMesh, s_MeshIcons, window);\n            EditorPrefs.SetInt(kDefaultMaterialPreviewMesh, m_SelectedMesh);\n        }\n\n        void OnReflectionProbeClick(VisualElement toolbar)\n        {\n            var button = toolbar.Q(Styles.reflectionProbeDropdownName);\n            if (button != null)\n            {\n                PopupWindow.Show(button.worldBound, m_ReflectionProbePicker);\n            }\n        }\n\n        int OnButtonClick(string name, int state, GUIContent[] icons, InspectorPreviewWindow window)\n        {\n            state++;\n            if (state == icons.Length)\n                state = 0;\n\n            window.UpdateButtonIcon(name, (Texture2D)icons[state].image);\n\n            return state;\n        }\n\n        private static bool SupportsRenderingPreview(Material material)\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture)\n                return false;\n\n            if (material == null)\n                return false;\n\n            var assetPath = AssetDatabase.GetAssetPath(material);\n            if (assetPath.EndsWith(\".vfx\", StringComparison.InvariantCultureIgnoreCase))\n                return false;\n\n            return true;\n        }\n\n        public void DefaultPreviewGUI(Rect r, GUIStyle background)\n        {\n            var mat = target as Material;\n            if (!SupportsRenderingPreview(mat))\n            {\n                if (Event.current.type == EventType.Repaint)\n                    EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), \"Material preview \\nnot available\");\n                return;\n            }\n\n            Init();\n\n            var viewType = GetPreviewType(mat);\n\n            if (DoesPreviewAllowRotation(viewType))\n                m_PreviewDir = PreviewGUI.Drag2D(m_PreviewDir, r);\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            var previewRenderUtility = GetPreviewRendererUtility();\n            previewRenderUtility.BeginPreview(r,  background);\n            DoRenderPreview(previewRenderUtility, !firstInspectedEditor);\n            previewRenderUtility.EndAndDrawPreview(r);\n        }\n\n        private static PreviewRenderUtility s_PreviewRenderUtility;\n        private static PreviewRenderUtility GetPreviewRendererUtility()\n        {\n            if (s_PreviewRenderUtility == null)\n            {\n                s_PreviewRenderUtility = new PreviewRenderUtility();\n                EditorUtility.SetCameraAnimateMaterials(s_PreviewRenderUtility.camera, true);\n            }\n            return s_PreviewRenderUtility;\n        }\n\n        private static void CleanUpPreviewRenderUtility()\n        {\n            if (s_PreviewRenderUtility == null)\n                return;\n\n            s_PreviewRenderUtility.Cleanup();\n            s_PreviewRenderUtility = null;\n        }\n\n        private static int s_NumberOfEditors = 0;\n\n        public virtual void OnEnable()\n        {\n            s_NumberOfEditors++;\n\n            if (!target)\n                return;\n            m_Shader = serializedObject.FindProperty(\"m_Shader\").objectReferenceValue as Shader;\n            m_CustomEditorClassName = \"\";\n            CreateCustomShaderEditorIfNeeded(m_Shader);\n\n            s_MaterialEditors.Add(this);\n            Undo.undoRedoEvent += UndoRedoPerformed;\n            PropertiesChanged();\n\n            m_PropertyBlock = new MaterialPropertyBlock();\n\n            m_ReflectionProbePicker.OnEnable();\n        }\n\n        [Obsolete(\"MaterialEditor.UndoRedoPerformed() has been deprecated. Use MaterialEditor.UndoRedoPerformed(in UndoRedoInfo) instead\", true)]\n        public virtual void UndoRedoPerformed() {}\n\n        public virtual void UndoRedoPerformed(in UndoRedoInfo info)\n        {\n            // Undo could've restored old shader which might lead to change in custom editor class\n            // therefore we need to rebuild inspector\n            UpdateAllOpenMaterialEditors();\n\n            PropertiesChanged();\n        }\n\n        public virtual void OnDisable()\n        {\n            s_NumberOfEditors--;\n            if (s_NumberOfEditors == 0)\n                CleanUpPreviewRenderUtility();\n\n            m_ReflectionProbePicker.OnDisable();\n            s_MaterialEditors.Remove(this);\n            Undo.undoRedoEvent -= UndoRedoPerformed;\n        }\n\n        // Handle dragging of material onto renderers\n        internal void OnSceneDrag(SceneView sceneView, int index)\n        {\n            Event evt = Event.current;\n\n            if (evt.type == EventType.Repaint)\n                return;\n\n            var materialIndex = -1;\n            var go = HandleUtility.PickGameObject(evt.mousePosition, out materialIndex);\n\n            if (EditorMaterialUtility.IsBackgroundMaterial((target as Material)))\n            {\n                HandleSkybox(go, evt);\n                ClearDragMaterialRendering();\n            }\n            else if (go && go.GetComponent<Renderer>())\n                HandleRenderer(go.GetComponent<Renderer>(), materialIndex, target as Material, evt.type, evt.alt);\n            else\n                ClearDragMaterialRendering();\n        }\n\n        private static void TryRevertDragChanges()\n        {\n            if (s_previousDraggedUponRenderer != null)\n            {\n                bool hasRevert = false;\n                if (!s_previousAlreadyHadPrefabModification &&\n                    PrefabUtility.GetPrefabInstanceStatus(s_previousDraggedUponRenderer) == PrefabInstanceStatus.Connected)\n                {\n                    var materialRendererSerializedObject = new SerializedObject(s_previousDraggedUponRenderer).FindProperty(\"m_Materials\");\n                    PrefabUtility.RevertPropertyOverride(materialRendererSerializedObject, InteractionMode.AutomatedAction, false);\n                    hasRevert = true;\n\n                    if (!hasRevert)\n                        s_previousDraggedUponRenderer.sharedMaterials = s_previousMaterialValue;\n                }\n            }\n        }\n\n        private static void ClearDragMaterialRendering()\n        {\n            TryRevertDragChanges();\n            s_previousDraggedUponRenderer = null;\n            s_previousMaterialValue = null;\n        }\n\n        Material s_OriginalMaterial;\n        internal void HandleSkybox(GameObject go, Event evt)\n        {\n            bool draggingOverBackground = !go;\n            var applyAndConsumeEvent = false;\n\n            if (!draggingOverBackground || evt.type == EventType.DragExited)\n            {\n                if (s_OriginalMaterial != null)\n                {\n                    RenderSettings.skybox = s_OriginalMaterial;\n                    s_OriginalMaterial = null;\n                }\n                evt.Use();\n            }\n            else\n            {\n                switch (evt.type)\n                {\n                    case EventType.DragUpdated:\n                        DragAndDrop.visualMode = DragAndDropVisualMode.Link;\n                        applyAndConsumeEvent = true;\n                        break;\n\n                    case EventType.DragPerform:\n                        DragAndDrop.AcceptDrag();\n                        applyAndConsumeEvent = true;\n                        break;\n                }\n            }\n\n            if (applyAndConsumeEvent)\n            {\n                Undo.RecordObject(RenderSettings.GetRenderSettings(), Styles.undoAssignSkyboxMaterial);\n                if (s_OriginalMaterial == null) s_OriginalMaterial = RenderSettings.skybox;\n\n                RenderSettings.skybox = target as Material;\n                if (evt.type == EventType.DragPerform) s_OriginalMaterial = null;\n\n                evt.Use();\n            }\n        }\n\n        static Renderer s_previousDraggedUponRenderer;\n        static Material[] s_previousMaterialValue;\n        static bool s_previousAlreadyHadPrefabModification;\n        internal static void HandleRenderer(Renderer r, int materialIndex, Material dragMaterial, EventType eventType, bool alt)\n        {\n            if (r.GetType().GetCustomAttributes(typeof(RejectDragAndDropMaterial), true).Length > 0)\n                return;\n\n            var applyMaterial = false;\n            switch (eventType)\n            {\n                case EventType.DragUpdated:\n                    DragAndDrop.visualMode = DragAndDropVisualMode.Copy;\n                    applyMaterial = true;\n                    break;\n\n                case EventType.DragPerform:\n                    DragAndDrop.AcceptDrag();\n                    applyMaterial = true;\n\n                    ClearDragMaterialRendering();\n                    break;\n            }\n            if (applyMaterial)\n            {\n                if (eventType != EventType.DragPerform)\n                {\n                    ClearDragMaterialRendering();\n                    s_previousDraggedUponRenderer = r;\n                    s_previousMaterialValue = r.sharedMaterials;\n\n                    // Update prefab modification status cache\n                    s_previousAlreadyHadPrefabModification = false;\n                    if (PrefabUtility.GetPrefabInstanceStatus(s_previousDraggedUponRenderer) == PrefabInstanceStatus.Connected)\n                    {\n                        var materialRendererSerializedObject = new SerializedObject(s_previousDraggedUponRenderer).FindProperty(\"m_Materials\");\n                        s_previousAlreadyHadPrefabModification = materialRendererSerializedObject.prefabOverride;\n                    }\n                }\n\n                Undo.RecordObject(r, Styles.undoAssignMaterial);\n                var materials = r.sharedMaterials;\n\n                bool isValidMaterialIndex = (materialIndex >= 0 && materialIndex < r.sharedMaterials.Length);\n                if (!alt && isValidMaterialIndex)\n                {\n                    materials[materialIndex] = dragMaterial;\n                }\n                else\n                {\n                    for (int q = 0; q < materials.Length; ++q)\n                        materials[q] = dragMaterial;\n                }\n\n                r.sharedMaterials = materials;\n                // Since we can handle multiple objects being dragged, we cannot use the event here.\n                // This will fall under respective view message processing responsibilities.\n            }\n        }\n\n        internal override bool HasLargeHeader()\n        {\n            return true;\n        }\n\n        internal override void OnHeaderIconGUI(Rect iconRect)\n        {\n            OnPreviewGUI(iconRect, \"IN BigTitle inner\");\n        }\n\n        [MenuItem(\"CONTEXT/Material/Flatten Material Variant\", true)]\n        static bool FlattenMaterialValidate(MenuCommand command)\n        {\n            Material mat = command.context as Material;\n            return mat.isVariant;\n        }\n\n        [MenuItem(\"CONTEXT/Material/Flatten Material Variant\", false, 502)]\n        static void FlattenMaterial(MenuCommand command)\n        {\n            Material mat = command.context as Material;\n\n            Undo.RecordObject(mat, \"Flatten Material Variant\");\n            mat.parent = null;\n        }\n\n        [MenuItem(\"CONTEXT/Material/Remove Unused Properties...\", false, 602)]\n        static void RemoveUnusedProperties(MenuCommand command)\n        {\n            Material mat = command.context as Material;\n\n            Undo.RegisterCompleteObjectUndo(mat, \"Remove unused properties\");\n            mat.RemoveUnusedProperties();\n        }\n\n        // We need to access renderer data in the GenericMenu callback, which is called from a static function\n        // So we backup these variables during header rendering in case context menu is openned\n        static Renderer[] renderersForContextMenu = null;\n        static Material materialForContextMenu = null;\n\n        internal override Rect DrawHeaderHelpAndSettingsGUI(Rect r)\n        {\n            if (!firstInspectedEditor && targets.Length == 1)\n            {\n                renderersForContextMenu = GetAssociatedRenderersFromInspector();\n                materialForContextMenu = target as Material;\n            }\n            return base.DrawHeaderHelpAndSettingsGUI(r);\n        }\n\n        internal static void AddAdditionalMaterialMenuItems(GenericMenu menu)\n        {\n            if (renderersForContextMenu == null || renderersForContextMenu.Length == 0)\n                return;\n\n            // Capture local copies for lambda, and clear static values\n            var renderers = renderersForContextMenu;\n            var material = materialForContextMenu;\n            renderersForContextMenu = null;\n            materialForContextMenu = null;\n\n            menu.AddItem(new GUIContent(\"Create Variant for Renderer\"), false, () => {\n\n                var directory = \"Assets/Materials\";\n                Directory.CreateDirectory(directory);\n                var assetPath = AssetDatabase.GetAssetPath(material);\n                var assetName = Path.GetFileNameWithoutExtension(assetPath) + \" Variant\";\n                var package = PackageManager.PackageInfo.FindForAssetPath(assetPath);\n                if (package == null || package.source == PackageManager.PackageSource.Local)\n                    directory = Path.GetDirectoryName(assetPath);\n\n                var path = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(directory, assetName + \".mat\"));\n                var variant = new Material(material) { name = assetName, parent = material };\n                AssetDatabase.CreateAsset(variant, path);\n\n                foreach (var renderer in renderers)\n                {\n                    Undo.RegisterCompleteObjectUndo(renderer, \"Assign Material\");\n                    var materials = renderer.sharedMaterials;\n                    for (int i = 0; i < materials.Length; i++)\n                    {\n                        if (materials[i] == material)\n                            materials[i] = variant;\n                    }\n                    renderer.sharedMaterials = materials;\n                }\n            });\n        }\n    }\n} // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing System;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    public partial class MaterialEditor\n    {\n        public const int kMiniTextureFieldLabelIndentLevel = 2;\n        const float kSpaceBetweenFlexibleAreaAndField = 5f;\n        const float kQueuePopupWidth = 100f;\n        const float kCustomQueuePopupWidth = kQueuePopupWidth + 15f;\n\n        private bool isPrefabAsset\n        {\n            get\n            {\n                if (m_SerializedObject == null || m_SerializedObject.targetObject == null)\n                    return false;\n\n                return PrefabUtility.IsPartOfPrefabAsset(m_SerializedObject.targetObject);\n            }\n        }\n\n        // Field for editing render queue value, with an automatically calculated rect\n        public void RenderQueueField()\n        {\n            Rect r = GetControlRectForSingleLine();\n            RenderQueueField(r);\n        }\n\n        // Field for editing render queue value, with an explicit rect\n        public void RenderQueueField(Rect r)\n        {\n            BeginProperty(r, MaterialSerializedProperty.CustomRenderQueue, targets);\n\n            var mat = targets[0] as Material;\n            int curRawQueue = mat.rawRenderQueue;\n            int curDisplayQueue = mat.renderQueue; // this gets final queue value used for rendering, taking shader's queue into account\n\n            // Figure out if we're using one of common queues, or a custom one\n            GUIContent[] queueNames = null;\n            int[] queueValues = null;\n            float labelWidth;\n            // If we use queue value that is not available, lets switch to the custom one\n            bool useCustomQueue = Array.IndexOf(Styles.queueValues, curRawQueue) < 0;\n            if (useCustomQueue)\n            {\n                // It is a big chance that we already have this custom queue value available\n                bool updateNewCustomQueueValue = Array.IndexOf(Styles.customQueueNames, curRawQueue) < 0;\n                if (updateNewCustomQueueValue)\n                {\n                    int targetQueueIndex = CalculateClosestQueueIndexToValue(curRawQueue);\n                    string targetQueueName = Styles.queueNames[targetQueueIndex].text;\n                    int targetQueueValueOverflow = curRawQueue - Styles.queueValues[targetQueueIndex];\n\n                    string newQueueName = string.Format(\n                        targetQueueValueOverflow > 0 ? \"{0}+{1}\" : \"{0}{1}\",\n                        targetQueueName,\n                        targetQueueValueOverflow);\n                    Styles.customQueueNames[Styles.kCustomQueueIndex].text = newQueueName;\n                    Styles.customQueueValues[Styles.kCustomQueueIndex] = curRawQueue;\n                }\n\n                queueNames = Styles.customQueueNames;\n                queueValues = Styles.customQueueValues;\n                labelWidth = kCustomQueuePopupWidth;\n            }\n            else\n            {\n                queueNames = Styles.queueNames;\n                queueValues = Styles.queueValues;\n                labelWidth = kQueuePopupWidth;\n            }\n\n            // We want the custom queue number field to line up with thumbnails & other value fields\n            // (on the right side), and common queues popup to be on the left of that.\n            float oldLabelWidth = EditorGUIUtility.labelWidth;\n            float oldFieldWidth = EditorGUIUtility.fieldWidth;\n            SetDefaultGUIWidths();\n            EditorGUIUtility.labelWidth -= labelWidth;\n            Rect popupRect = r;\n            popupRect.width -= EditorGUIUtility.fieldWidth + 2;\n            Rect numberRect = r;\n            numberRect.xMin = numberRect.xMax - EditorGUIUtility.fieldWidth;\n            numberRect.height = EditorGUI.kSingleLineHeight;\n\n            // Queues popup\n            int curPopupValue = curRawQueue;\n            int newPopupValue = EditorGUI.IntPopup(popupRect, Styles.queueLabel, curRawQueue, queueNames, queueValues);\n\n            // Custom queue field\n            int newDisplayQueue = EditorGUI.DelayedIntField(numberRect, curDisplayQueue);\n\n            // If popup or custom field changed, set the new queue\n            if (curPopupValue != newPopupValue || curDisplayQueue != newDisplayQueue)\n            {\n                RegisterPropertyChangeUndo(\"Render Queue\");\n                // Take the value from the number field,\n                int newQueue = newDisplayQueue;\n                // But if it's the popup that was changed\n                if (newPopupValue != curPopupValue)\n                    newQueue = newPopupValue;\n                newQueue = Mathf.Clamp(newQueue, -1, 5000); // clamp to valid queue ranges\n                // Change the material queues\n                foreach (var m in targets)\n                {\n                    ((Material)m).renderQueue = newQueue;\n                }\n            }\n\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n            EditorGUIUtility.fieldWidth = oldFieldWidth;\n\n            EndProperty();\n        }\n\n        public bool EnableInstancingField()\n        {\n            if (!ShaderUtil.HasInstancing(m_Shader))\n                return false;\n            Rect r = GetControlRectForSingleLine();\n            EnableInstancingField(r);\n            return true;\n        }\n\n        public void EnableInstancingField(Rect r)\n        {\n            BeginProperty(r, MaterialSerializedProperty.EnableInstancingVariants, targets);\n\n            using (var scope = new EditorGUI.ChangeCheckScope())\n            {\n                bool enableInstancing = EditorGUI.Toggle(r, Styles.enableInstancingLabel, (targets[0] as Material).enableInstancing);\n                if (scope.changed)\n                {\n                    foreach (Material material in targets)\n                        material.enableInstancing = enableInstancing;\n                }\n            }\n\n            EndProperty();\n        }\n\n        public bool IsInstancingEnabled()\n        {\n            return ShaderUtil.HasInstancing(m_Shader) && (targets[0] as Material).enableInstancing;\n        }\n\n        public bool DoubleSidedGIField()\n        {\n            Rect r = GetControlRectForSingleLine();\n\n            BeginProperty(r, MaterialSerializedProperty.DoubleSidedGI, targets);\n\n            EditorGUI.BeginChangeCheck();\n            bool doubleSidedGI = EditorGUI.Toggle(r, Styles.doubleSidedGILabel, (targets[0] as Material).doubleSidedGI);\n            if (EditorGUI.EndChangeCheck())\n            {\n                foreach (Material material in targets)\n                    material.doubleSidedGI = doubleSidedGI;\n            }\n\n            EndProperty();\n\n            return true;\n        }\n\n        private int CalculateClosestQueueIndexToValue(int requestedValue)\n        {\n            int bestCloseByDiff = int.MaxValue;\n            int result = 1;\n            for (int i = 1; i < Styles.queueValues.Length; i++)\n            {\n                int queueValue = Styles.queueValues[i];\n                int closeByDiff = Mathf.Abs(queueValue - requestedValue);\n                if (closeByDiff < bestCloseByDiff)\n                {\n                    result = i;\n                    bestCloseByDiff = closeByDiff;\n                }\n            }\n            return result;\n        }\n\n        public Rect TexturePropertySingleLine(GUIContent label, MaterialProperty textureProp)\n        {\n            return TexturePropertySingleLine(label, textureProp, null, null);\n        }\n\n        public Rect TexturePropertySingleLine(GUIContent label, MaterialProperty textureProp, MaterialProperty extraProperty1)\n        {\n            return TexturePropertySingleLine(label, textureProp, extraProperty1, null);\n        }\n\n        // Mini texture slot, with two extra controls on the same line (allocates rect in GUILayout)\n        // Have up to 3 controls on one line\n        public Rect TexturePropertySingleLine(GUIContent label, MaterialProperty textureProp, MaterialProperty extraProperty1, MaterialProperty extraProperty2)\n        {\n            Rect r = GetControlRectForSingleLine();\n\n            bool hasExtraProp = !(extraProperty1 == null && extraProperty2 == null);\n            if (hasExtraProp) BeginProperty(r, textureProp);\n            if (extraProperty1 != null) BeginProperty(r, extraProperty1);\n            if (extraProperty2 != null) BeginProperty(r, extraProperty2);\n\n            TexturePropertyMiniThumbnail(r, textureProp, label.text, label.tooltip);\n\n            // No extra properties: early out\n            if (!hasExtraProp)\n                return r;\n\n            // Temporarily reset the indent level as it was already used earlier to compute the positions of the layout items. See issue 946082.\n            int oldIndentLevel = EditorGUI.indentLevel;\n\n            EditorGUI.indentLevel = 0;\n\n            // One extra property\n            if (extraProperty1 == null || extraProperty2 == null)\n            {\n                var prop = extraProperty1 ?? extraProperty2;\n                ExtraPropertyAfterTexture(GetRectAfterLabelWidth(r), prop, false);\n            }\n            else // Two extra properties\n            {\n                if (extraProperty1.propertyType == ShaderPropertyType.Color)\n                {\n                    ExtraPropertyAfterTexture(GetFlexibleRectBetweenFieldAndRightEdge(r), extraProperty2);\n                    ExtraPropertyAfterTexture(GetLeftAlignedFieldRect(r), extraProperty1);\n                }\n                else\n                {\n                    ExtraPropertyAfterTexture(GetRightAlignedFieldRect(r), extraProperty2);\n                    ExtraPropertyAfterTexture(GetFlexibleRectBetweenLabelAndField(r), extraProperty1);\n                }\n            }\n            // Restore the indent level\n            EditorGUI.indentLevel = oldIndentLevel;\n\n            if (extraProperty2 != null) EndProperty();\n            if (extraProperty1 != null) EndProperty();\n            if (hasExtraProp) EndProperty();\n            return r;\n        }\n\n        [Obsolete(\"Use TexturePropertyWithHDRColor(GUIContent label, MaterialProperty textureProp, MaterialProperty colorProperty, bool showAlpha), true\")]\n        public Rect TexturePropertyWithHDRColor(\n            GUIContent label, MaterialProperty textureProp, MaterialProperty colorProperty, ColorPickerHDRConfig hdrConfig, bool showAlpha\n        )\n        {\n            return TexturePropertyWithHDRColor(label, textureProp, colorProperty, showAlpha);\n        }\n\n        public Rect TexturePropertyWithHDRColor(GUIContent label, MaterialProperty textureProp, MaterialProperty colorProperty, bool showAlpha)\n        {\n            Rect r = GetControlRectForSingleLine();\n\n            bool isColorProperty = colorProperty.propertyType == ShaderPropertyType.Color;\n            if (isColorProperty)\n            {\n                BeginProperty(r, textureProp);\n                BeginProperty(r, colorProperty);\n            }\n\n            TexturePropertyMiniThumbnail(r, textureProp, label.text, label.tooltip);\n\n            if (!isColorProperty)\n            {\n                Debug.LogError(\"Assuming ShaderPropertyType.Color (was \" + colorProperty.propertyType + \")\");\n                return r;\n            }\n\n            // Temporarily reset the indent level. See issue 946082.\n            int oldIndentLevel = EditorGUI.indentLevel;\n            EditorGUI.indentLevel = 0;\n\n            BeginAnimatedCheck(r, colorProperty);\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = colorProperty.hasMixedValue;\n            Color newValue = EditorGUI.ColorField(GetRectAfterLabelWidth(r), GUIContent.none, colorProperty.colorValue, true, showAlpha, true);\n            EditorGUI.showMixedValue = false;\n            if (EditorGUI.EndChangeCheck())\n                colorProperty.colorValue = newValue;\n\n            EndAnimatedCheck();\n\n            // Restore the indent level\n            EditorGUI.indentLevel = oldIndentLevel;\n\n            if (isColorProperty)\n            {\n                EndProperty();\n                EndProperty();\n            }\n\n            return r;\n        }\n\n        public Rect TexturePropertyTwoLines(GUIContent label, MaterialProperty textureProp, MaterialProperty extraProperty1, GUIContent label2, MaterialProperty extraProperty2)\n        {\n            // If not using the second extra property then use the single line version as\n            // the first extra property is always inlined with the the texture slot\n            if (extraProperty2 == null)\n            {\n                return TexturePropertySingleLine(label, textureProp, extraProperty1);\n            }\n\n            Rect r = GetControlRectForSingleLine();\n\n            BeginProperty(r, textureProp);\n            BeginProperty(r, extraProperty1);\n\n            TexturePropertyMiniThumbnail(r, textureProp, label.text, label.tooltip);\n\n            // Temporarily reset the indent level. See issue 946082.\n            int oldIndentLevel = EditorGUI.indentLevel;\n            EditorGUI.indentLevel = 0;\n\n            // First extra control on the same line as the texture\n            Rect r1 = GetRectAfterLabelWidth(r);\n            if (extraProperty1.propertyType == ShaderPropertyType.Color)\n                r1 = GetLeftAlignedFieldRect(r);\n            ExtraPropertyAfterTexture(r1, extraProperty1);\n\n            EndProperty();\n            EndProperty();\n\n            // New line for extraProperty2\n            Rect r2 = GetControlRectForSingleLine();\n            ShaderProperty(r2, extraProperty2, label2.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);\n\n            // Restore the indent level\n            EditorGUI.indentLevel = oldIndentLevel;\n\n            // Return total rect\n            r.height += r2.height;\n            return r;\n        }\n\n        Rect GetControlRectForSingleLine()\n        {\n            const float extraSpacing = 2f; // The shader properties needs a little more vertical spacing due to the mini texture field (looks cramped without)\n            return EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight + extraSpacing, EditorStyles.layerMaskField);\n        }\n\n        void ExtraPropertyAfterTexture(Rect r, MaterialProperty property, bool adjustLabelWidth = true)\n        {\n            if (adjustLabelWidth && (property.propertyType == ShaderPropertyType.Float || property.propertyType == ShaderPropertyType.Color) && r.width > EditorGUIUtility.fieldWidth)\n            {\n                // We want color fields and float fields to have same width as EditorGUIUtility.fieldWidth\n                // so controls aligns vertically.\n                // This also makes us able to have a draggable area in front of the float fields. We therefore ensures\n                // the property has a label (here we use a whitespace) and adjust label width.\n                float oldLabelWidth = EditorGUIUtility.labelWidth;\n                EditorGUIUtility.labelWidth = r.width - EditorGUIUtility.fieldWidth;\n                ShaderProperty(r, property, \" \");\n                EditorGUIUtility.labelWidth = oldLabelWidth;\n                return;\n            }\n\n            ShaderProperty(r, property, string.Empty);\n        }\n\n        static public Rect GetRightAlignedFieldRect(Rect r)\n        {\n            return new Rect(r.xMax - EditorGUIUtility.fieldWidth, r.y, EditorGUIUtility.fieldWidth, EditorGUIUtility.singleLineHeight);\n        }\n\n        static public Rect GetLeftAlignedFieldRect(Rect r)\n        {\n            return new Rect(r.x + EditorGUIUtility.labelWidth, r.y, EditorGUIUtility.fieldWidth, EditorGUIUtility.singleLineHeight);\n        }\n\n        static public Rect GetFlexibleRectBetweenLabelAndField(Rect r)\n        {\n            return new Rect(r.x + EditorGUIUtility.labelWidth, r.y, r.width - EditorGUIUtility.labelWidth - EditorGUIUtility.fieldWidth - kSpaceBetweenFlexibleAreaAndField, EditorGUIUtility.singleLineHeight);\n        }\n\n        static public Rect GetFlexibleRectBetweenFieldAndRightEdge(Rect r)\n        {\n            Rect r2 = GetRectAfterLabelWidth(r);\n            r2.xMin += EditorGUIUtility.fieldWidth + kSpaceBetweenFlexibleAreaAndField;\n            return r2;\n        }\n\n        static public Rect GetRectAfterLabelWidth(Rect r)\n        {\n            return new Rect(r.x + EditorGUIUtility.labelWidth, r.y, r.width - EditorGUIUtility.labelWidth, EditorGUIUtility.singleLineHeight);\n        }\n\n        static internal System.Type GetTextureTypeFromDimension(TextureDimension dim)\n        {\n            switch (dim)\n            {\n                case TextureDimension.Tex2D: return typeof(Texture); // common use case is RenderTextures too, so return base class\n                case TextureDimension.Cube: return typeof(Cubemap);\n                case TextureDimension.Tex3D: return typeof(Texture3D);\n                case TextureDimension.Tex2DArray: return typeof(Texture2DArray);\n                case TextureDimension.CubeArray: return typeof(CubemapArray);\n                case TextureDimension.Any: return typeof(Texture);\n                default: return null; // Unknown, None etc.\n            }\n        }\n    }\n} // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/Inspector/MaterialPropertyDrawer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing ShaderPropertyType = UnityEngine.Rendering.ShaderPropertyType;\n\nnamespace UnityEditor\n{\n    internal class MaterialPropertyHandler\n    {\n        private MaterialPropertyDrawer m_PropertyDrawer;\n        private List<MaterialPropertyDrawer> m_DecoratorDrawers;\n\n        public MaterialPropertyDrawer propertyDrawer { get { return m_PropertyDrawer; } }\n\n        public bool IsEmpty()\n        {\n            return m_PropertyDrawer == null && (m_DecoratorDrawers == null || m_DecoratorDrawers.Count == 0);\n        }\n\n        public void OnGUI(ref Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)\n        {\n            float oldLabelWidth, oldFieldWidth;\n            var propHeight = position.height;\n            position.height = 0;\n            if (m_DecoratorDrawers != null)\n            {\n                foreach (var decorator in m_DecoratorDrawers)\n                {\n                    position.height = decorator.GetPropertyHeight(prop, label.text, editor);\n\n                    oldLabelWidth = EditorGUIUtility.labelWidth;\n                    oldFieldWidth = EditorGUIUtility.fieldWidth;\n                    decorator.OnGUI(position, prop, label, editor);\n                    EditorGUIUtility.labelWidth = oldLabelWidth;\n                    EditorGUIUtility.fieldWidth = oldFieldWidth;\n\n                    position.y += position.height;\n                    propHeight -= position.height;\n                }\n            }\n\n            position.height = propHeight;\n            if (m_PropertyDrawer != null)\n            {\n                oldLabelWidth = EditorGUIUtility.labelWidth;\n                oldFieldWidth = EditorGUIUtility.fieldWidth;\n                m_PropertyDrawer.OnGUI(position, prop, label, editor);\n                EditorGUIUtility.labelWidth = oldLabelWidth;\n                EditorGUIUtility.fieldWidth = oldFieldWidth;\n            }\n        }\n\n        public float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor)\n        {\n            var height = 0f;\n            if (m_DecoratorDrawers != null)\n                foreach (var drawer in m_DecoratorDrawers)\n                    height += drawer.GetPropertyHeight(prop, label, editor);\n            if (m_PropertyDrawer != null)\n                height += m_PropertyDrawer.GetPropertyHeight(prop, label, editor);\n            return height;\n        }\n\n        private static Dictionary<string, MaterialPropertyHandler> s_PropertyHandlers = new Dictionary<string, MaterialPropertyHandler>();\n\n        private static string GetPropertyString(Shader shader, string name)\n        {\n            if (shader == null)\n                return string.Empty;\n            return shader.GetInstanceID() + \"_\" + name;\n        }\n\n        [RequiredByNativeCode]\n        internal static void InvalidatePropertyCache(Shader shader)\n        {\n            if (shader == null)\n                return;\n            string keyStart = shader.GetInstanceID() + \"_\";\n            var toDelete = new List<string>();\n            foreach (string key in s_PropertyHandlers.Keys)\n            {\n                if (key.StartsWith(keyStart, StringComparison.Ordinal))\n                    toDelete.Add(key);\n            }\n            foreach (string key in toDelete)\n            {\n                s_PropertyHandlers.Remove(key);\n            }\n        }\n\n        private static MaterialPropertyDrawer CreatePropertyDrawer(Type klass, string argsText)\n        {\n            // no args -> default constructor\n            if (string.IsNullOrEmpty(argsText))\n                return Activator.CreateInstance(klass) as MaterialPropertyDrawer;\n\n            // split the argument list by commas\n            string[] argStrings = argsText.Split(',');\n            var args = new object[argStrings.Length];\n            for (var i = 0; i < argStrings.Length; ++i)\n            {\n                float f;\n                string arg = argStrings[i].Trim();\n\n                // if can parse as a float, use the float; otherwise pass the string\n                if (float.TryParse(arg, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out f))\n                {\n                    args[i] = f;\n                }\n                else\n                {\n                    args[i] = arg;\n                }\n            }\n            return Activator.CreateInstance(klass, args) as MaterialPropertyDrawer;\n        }\n\n        private static MaterialPropertyDrawer GetShaderPropertyDrawer(string attrib, out bool isDecorator)\n        {\n            isDecorator = false;\n\n            string className = attrib;\n            string args = string.Empty;\n            Match match = Regex.Match(attrib, @\"(\\w+)\\s*\\((.*)\\)\");\n            if (match.Success)\n            {\n                className = match.Groups[1].Value;\n                args = match.Groups[2].Value.Trim();\n            }\n\n            //Debug.Log (\"looking for class \" + className + \" args '\" + args + \"'\");\n            foreach (var klass in TypeCache.GetTypesDerivedFrom<MaterialPropertyDrawer>())\n            {\n                // When you write [Foo] in shader, get Foo, FooDrawer, MaterialFooDrawer,\n                // FooDecorator or MaterialFooDecorator class;\n                // \"kind of\" similar to how C# does attributes.\n\n                //@TODO: namespaces?\n                if (klass.Name == className ||\n                    klass.Name == className + \"Drawer\" ||\n                    klass.Name == \"Material\" + className + \"Drawer\" ||\n                    klass.Name == className + \"Decorator\" ||\n                    klass.Name == \"Material\" + className + \"Decorator\")\n                {\n                    try\n                    {\n                        isDecorator = klass.Name.EndsWith(\"Decorator\");\n                        return CreatePropertyDrawer(klass, args);\n                    }\n                    catch (Exception)\n                    {\n                        Debug.LogWarningFormat(\"Failed to create material drawer {0} with arguments '{1}'\", className, args);\n                        return null;\n                    }\n                }\n            }\n\n            return null;\n        }\n\n        private static MaterialPropertyHandler GetShaderPropertyHandler(Shader shader, string name)\n        {\n            if (name == null)\n                return null;\n            int propertyIndex = shader.FindPropertyIndex(name);\n            if (propertyIndex < 0)\n                return null;\n            string[] attribs = shader.GetPropertyAttributes(propertyIndex);\n            if (attribs == null || attribs.Length == 0)\n                return null;\n\n            var handler = new MaterialPropertyHandler();\n            foreach (var attr in attribs)\n            {\n                bool isDecorator;\n                MaterialPropertyDrawer drawer = GetShaderPropertyDrawer(attr, out isDecorator);\n                if (drawer != null)\n                {\n                    if (isDecorator)\n                    {\n                        if (handler.m_DecoratorDrawers == null)\n                            handler.m_DecoratorDrawers = new List<MaterialPropertyDrawer>();\n                        handler.m_DecoratorDrawers.Add(drawer);\n                    }\n                    else\n                    {\n                        if (handler.m_PropertyDrawer != null)\n                        {\n                            Debug.LogWarning(string.Format(\"Shader property {0} already has a property drawer\", name), shader);\n                        }\n                        handler.m_PropertyDrawer = drawer;\n                    }\n                }\n            }\n\n            return handler;\n        }\n\n        internal static MaterialPropertyHandler GetHandler(Shader shader, string name)\n        {\n            if (shader == null || name == null)\n                return null;\n\n            // Use cached handler if available\n            MaterialPropertyHandler handler;\n            string key = GetPropertyString(shader, name);\n            if (s_PropertyHandlers.TryGetValue(key, out handler))\n                return handler;\n\n            // Get the handler for this shader property\n            handler = GetShaderPropertyHandler(shader, name);\n            if (handler != null && handler.IsEmpty())\n                handler = null;\n            //Debug.Log (\"drawer \" + drawer);\n\n            // Special exception for KeywordEnums, as the cache doesn't have a way to\n            // determine whether a KeywordEnum has been changed or not.\n            if (handler != null && handler.propertyDrawer is MaterialKeywordEnumDrawer)\n                return handler;\n\n            // Cache the handler and return. Cache even if it was null, so we can return\n            // later requests fast as well.\n            s_PropertyHandlers[key] = handler;\n            return handler;\n        }\n    }\n\n\n    public abstract class MaterialPropertyDrawer\n    {\n        public virtual void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)\n        {\n            OnGUI(position, prop, label.text, editor);\n        }\n\n        public virtual void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor)\n        {\n            EditorGUI.LabelField(position, new GUIContent(label), EditorGUIUtility.TempContent(\"No GUI Implemented\"));\n        }\n\n        public virtual float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor)\n        {\n            return EditorGUI.kSingleLineHeight;\n        }\n\n        public virtual void Apply(MaterialProperty prop)\n        {\n            // empty base implementation\n        }\n    }\n\n\n    // --------------------------------------------------------------------------\n    // Built-in drawers below.\n    // They aren't directly used by the code, but can be used by writing attribute-like\n    // syntax in shaders, e.g. [Toggle] in front of a shader property will\n    // end up using MaterialToggleDrawer to display it as a toggle.\n\n    // Variant of the ToggleDrawer that defines no keyword (just UI)\n    internal class MaterialToggleUIDrawer : MaterialPropertyDrawer\n    {\n        public MaterialToggleUIDrawer()\n        {\n        }\n\n        public MaterialToggleUIDrawer(string keyword)\n        {\n        }\n\n        protected virtual void SetKeyword(MaterialProperty prop, bool on)\n        {\n        }\n\n        static bool IsPropertyTypeSuitable(MaterialProperty prop)\n        {\n            return prop.propertyType == ShaderPropertyType.Float || prop.propertyType == ShaderPropertyType.Range || prop.propertyType == ShaderPropertyType.Int;\n        }\n\n        public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor)\n        {\n            if (!IsPropertyTypeSuitable(prop))\n            {\n                return EditorGUI.kSingleLineHeight * 2.5f;\n            }\n            return base.GetPropertyHeight(prop, label, editor);\n        }\n\n        public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)\n        {\n            if (!IsPropertyTypeSuitable(prop))\n            {\n                GUIContent c = EditorGUIUtility.TempContent(\"Toggle used on a non-float property: \" + prop.name,\n                    EditorGUIUtility.GetHelpIcon(MessageType.Warning));\n                EditorGUI.LabelField(position, c, EditorStyles.helpBox);\n                return;\n            }\n\n            MaterialEditor.BeginProperty(position, prop);\n\n            if (prop.propertyType != ShaderPropertyType.Int)\n            {\n                EditorGUI.BeginChangeCheck();\n\n                bool value = (Math.Abs(prop.floatValue) > 0.001f);\n                EditorGUI.showMixedValue = prop.hasMixedValue;\n                value = EditorGUI.Toggle(position, label, value);\n                EditorGUI.showMixedValue = false;\n                if (EditorGUI.EndChangeCheck())\n                {\n                    prop.floatValue = value ? 1.0f : 0.0f;\n                    SetKeyword(prop, value);\n                }\n            }\n            else\n            {\n                EditorGUI.BeginChangeCheck();\n\n                bool value = prop.intValue != 0;\n                EditorGUI.showMixedValue = prop.hasMixedValue;\n                value = EditorGUI.Toggle(position, label, value);\n                EditorGUI.showMixedValue = false;\n                if (EditorGUI.EndChangeCheck())\n                {\n                    prop.intValue = value ? 1 : 0;\n                    SetKeyword(prop, value);\n                }\n            }\n\n            MaterialEditor.EndProperty();\n        }\n\n        public override void Apply(MaterialProperty prop)\n        {\n            base.Apply(prop);\n            if (!IsPropertyTypeSuitable(prop))\n                return;\n\n            if (prop.hasMixedValue)\n                return;\n\n            if (prop.propertyType != ShaderPropertyType.Int)\n                SetKeyword(prop, (Math.Abs(prop.floatValue) > 0.001f));\n            else\n                SetKeyword(prop, prop.intValue != 0);\n        }\n    }\n\n\n    internal class MaterialToggleDrawer : MaterialToggleUIDrawer\n    {\n        protected readonly string keyword;\n        public MaterialToggleDrawer()\n        {\n        }\n\n        public MaterialToggleDrawer(string keyword)\n        {\n            this.keyword = keyword;\n        }\n\n        protected override void SetKeyword(MaterialProperty prop, bool on)\n        {\n            SetKeywordInternal(prop, on, \"_ON\");\n        }\n\n        protected void SetKeywordInternal(MaterialProperty prop, bool on, string defaultKeywordSuffix)\n        {\n            // if no keyword is provided, use <uppercase property name> + defaultKeywordSuffix\n            string kw = string.IsNullOrEmpty(keyword) ? prop.name.ToUpperInvariant() + defaultKeywordSuffix : keyword;\n            // set or clear the keyword\n            foreach (Material material in prop.targets)\n            {\n                if (on)\n                    material.EnableKeyword(kw);\n                else\n                    material.DisableKeyword(kw);\n            }\n        }\n    }\n\n    // Variant of the ToggleDrawer that defines a keyword when it's not on\n    // This is useful when adding Toggles to existing shaders while maintaining backwards compatibility\n    internal class MaterialToggleOffDrawer : MaterialToggleDrawer\n    {\n        public MaterialToggleOffDrawer()\n        {\n        }\n\n        public MaterialToggleOffDrawer(string keyword) : base(keyword)\n        {\n        }\n\n        protected override void SetKeyword(MaterialProperty prop, bool on)\n        {\n            SetKeywordInternal(prop, !on, \"_OFF\");\n        }\n    }\n\n    internal class MaterialPowerSliderDrawer : MaterialPropertyDrawer\n    {\n        private readonly float power;\n\n        public MaterialPowerSliderDrawer(float power)\n        {\n            this.power = power;\n        }\n\n        public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor)\n        {\n            if (prop.propertyType != ShaderPropertyType.Range)\n            {\n                return EditorGUI.kSingleLineHeight * 2.5f;\n            }\n            return base.GetPropertyHeight(prop, label, editor);\n        }\n\n        public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)\n        {\n            if (prop.propertyType != ShaderPropertyType.Range)\n            {\n                GUIContent c = EditorGUIUtility.TempContent(\"PowerSlider used on a non-range property: \" + prop.name,\n                    EditorGUIUtility.GetHelpIcon(MessageType.Warning));\n                EditorGUI.LabelField(position, c, EditorStyles.helpBox);\n                return;\n            }\n\n            MaterialEditor.DoPowerRangeProperty(position, prop, label, power);\n        }\n    }\n\n    internal class MaterialIntRangeDrawer : MaterialPropertyDrawer\n    {\n        public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)\n        {\n            if (prop.propertyType != ShaderPropertyType.Range)\n            {\n                GUIContent c = EditorGUIUtility.TempContent(\"IntRange used on a non-range property: \" + prop.name,\n                    EditorGUIUtility.GetHelpIcon(MessageType.Warning));\n                EditorGUI.LabelField(position, c, EditorStyles.helpBox);\n                return;\n            }\n\n            MaterialEditor.DoIntRangeProperty(position, prop, label);\n        }\n    }\n\n    internal class MaterialKeywordEnumDrawer : MaterialPropertyDrawer\n    {\n        private readonly GUIContent[] keywords;\n\n        public MaterialKeywordEnumDrawer(string kw1) : this(new[] { kw1 }) {}\n        public MaterialKeywordEnumDrawer(string kw1, string kw2) : this(new[] { kw1, kw2 }) {}\n        public MaterialKeywordEnumDrawer(string kw1, string kw2, string kw3) : this(new[] { kw1, kw2, kw3 }) {}\n        public MaterialKeywordEnumDrawer(string kw1, string kw2, string kw3, string kw4) : this(new[] { kw1, kw2, kw3, kw4 }) {}\n        public MaterialKeywordEnumDrawer(string kw1, string kw2, string kw3, string kw4, string kw5) : this(new[] { kw1, kw2, kw3, kw4, kw5 }) {}\n        public MaterialKeywordEnumDrawer(string kw1, string kw2, string kw3, string kw4, string kw5, string kw6) : this(new[] { kw1, kw2, kw3, kw4, kw5, kw6 }) {}\n        public MaterialKeywordEnumDrawer(string kw1, string kw2, string kw3, string kw4, string kw5, string kw6, string kw7) : this(new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7 }) {}\n        public MaterialKeywordEnumDrawer(string kw1, string kw2, string kw3, string kw4, string kw5, string kw6, string kw7, string kw8) : this(new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7, kw8 }) {}\n        public MaterialKeywordEnumDrawer(string kw1, string kw2, string kw3, string kw4, string kw5, string kw6, string kw7, string kw8, string kw9) : this(new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7, kw8, kw9 }) {}\n        public MaterialKeywordEnumDrawer(params string[] keywords)\n        {\n            this.keywords = new GUIContent[keywords.Length];\n            for (int i = 0; i < keywords.Length; ++i)\n                this.keywords[i] = new GUIContent(keywords[i]);\n        }\n\n        static bool IsPropertyTypeSuitable(MaterialProperty prop)\n        {\n            return prop.propertyType == ShaderPropertyType.Float || prop.propertyType == ShaderPropertyType.Range || prop.propertyType == ShaderPropertyType.Int;\n        }\n\n        void SetKeyword(MaterialProperty prop, int index)\n        {\n            for (int i = 0; i < keywords.Length; ++i)\n            {\n                string keyword = GetKeywordName(prop.name, keywords[i].text);\n                foreach (Material material in prop.targets)\n                {\n                    if (index == i)\n                        material.EnableKeyword(keyword);\n                    else\n                        material.DisableKeyword(keyword);\n                }\n            }\n        }\n\n        public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor)\n        {\n            if (!IsPropertyTypeSuitable(prop))\n            {\n                return EditorGUI.kSingleLineHeight * 2.5f;\n            }\n            return base.GetPropertyHeight(prop, label, editor);\n        }\n\n        public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)\n        {\n            if (!IsPropertyTypeSuitable(prop))\n            {\n                GUIContent c = EditorGUIUtility.TempContent(\"KeywordEnum used on a non-float property: \" + prop.name,\n                    EditorGUIUtility.GetHelpIcon(MessageType.Warning));\n                EditorGUI.LabelField(position, c, EditorStyles.helpBox);\n                return;\n            }\n\n            MaterialEditor.BeginProperty(position, prop);\n\n            if (prop.propertyType != ShaderPropertyType.Int)\n            {\n                EditorGUI.BeginChangeCheck();\n\n                EditorGUI.showMixedValue = prop.hasMixedValue;\n                var value = (int)prop.floatValue;\n                value = EditorGUI.Popup(position, label, value, keywords);\n                EditorGUI.showMixedValue = false;\n                if (EditorGUI.EndChangeCheck())\n                {\n                    prop.floatValue = value;\n                    SetKeyword(prop, value);\n                }\n            }\n            else\n            {\n                EditorGUI.BeginChangeCheck();\n\n                EditorGUI.showMixedValue = prop.hasMixedValue;\n                var value = prop.intValue;\n                value = EditorGUI.Popup(position, label, value, keywords);\n                EditorGUI.showMixedValue = false;\n                if (EditorGUI.EndChangeCheck())\n                {\n                    prop.intValue = value;\n                    SetKeyword(prop, value);\n                }\n            }\n\n            MaterialEditor.EndProperty();\n        }\n\n        public override void Apply(MaterialProperty prop)\n        {\n            base.Apply(prop);\n            if (!IsPropertyTypeSuitable(prop))\n                return;\n\n            if (prop.hasMixedValue)\n                return;\n\n            if (prop.propertyType != ShaderPropertyType.Int)\n                SetKeyword(prop, (int)prop.floatValue);\n            else\n                SetKeyword(prop, prop.intValue);\n        }\n\n        // Final keyword name: property name + \"_\" + display name. Uppercased,\n        // and spaces replaced with underscores.\n        private static string GetKeywordName(string propName, string name)\n        {\n            string n = propName + \"_\" + name;\n            return n.Replace(' ', '_').ToUpperInvariant();\n        }\n    }\n\n\n    internal class MaterialEnumDrawer : MaterialPropertyDrawer\n    {\n        private readonly GUIContent[] names;\n        private readonly int[] values;\n\n        // Single argument: enum type name; entry names & values fetched via reflection\n        public MaterialEnumDrawer(string enumName)\n        {\n            var loadedTypes = TypeCache.GetTypesDerivedFrom(typeof(Enum));\n            try\n            {\n                var enumType = loadedTypes.FirstOrDefault(x => x.Name == enumName || x.FullName == enumName);\n                var enumNames = Enum.GetNames(enumType);\n                this.names = new GUIContent[enumNames.Length];\n                for (int i = 0; i < enumNames.Length; ++i)\n                    this.names[i] = new GUIContent(enumNames[i]);\n\n                var enumVals = Enum.GetValues(enumType);\n                values = new int[enumVals.Length];\n                for (var i = 0; i < enumVals.Length; ++i)\n                    values[i] = (int)enumVals.GetValue(i);\n            }\n            catch (Exception)\n            {\n                Debug.LogWarningFormat(\"Failed to create MaterialEnum, enum {0} not found\", enumName);\n                throw;\n            }\n        }\n\n        // name,value,name,value,... pairs: explicit names & values\n        public MaterialEnumDrawer(string n1, float v1) : this(new[] {n1}, new[] {v1}) {}\n        public MaterialEnumDrawer(string n1, float v1, string n2, float v2) : this(new[] { n1, n2 }, new[] { v1, v2 }) {}\n        public MaterialEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3) : this(new[] { n1, n2, n3 }, new[] { v1, v2, v3 }) {}\n        public MaterialEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4) : this(new[] { n1, n2, n3, n4 }, new[] { v1, v2, v3, v4 }) {}\n        public MaterialEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5) : this(new[] { n1, n2, n3, n4, n5 }, new[] { v1, v2, v3, v4, v5 }) {}\n        public MaterialEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6) : this(new[] { n1, n2, n3, n4, n5, n6 }, new[] { v1, v2, v3, v4, v5, v6 }) {}\n        public MaterialEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7) : this(new[] { n1, n2, n3, n4, n5, n6, n7 }, new[] { v1, v2, v3, v4, v5, v6, v7 }) {}\n        public MaterialEnumDrawer(string[] enumNames, float[] vals)\n        {\n            this.names = new GUIContent[enumNames.Length];\n            for (int i = 0; i < enumNames.Length; ++i)\n                this.names[i] = new GUIContent(enumNames[i]);\n\n            values = new int[vals.Length];\n            for (int i = 0; i < vals.Length; ++i)\n                values[i] = (int)vals[i];\n        }\n\n        static bool IsPropertyTypeSuitable(MaterialProperty prop)\n        {\n            return prop.propertyType == ShaderPropertyType.Float || prop.propertyType == ShaderPropertyType.Range || prop.propertyType == ShaderPropertyType.Int;\n        }\n\n        public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor)\n        {\n            if (prop.propertyType != ShaderPropertyType.Float && prop.propertyType != ShaderPropertyType.Range && prop.propertyType != ShaderPropertyType.Int)\n            {\n                return EditorGUI.kSingleLineHeight * 2.5f;\n            }\n            return base.GetPropertyHeight(prop, label, editor);\n        }\n\n        public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)\n        {\n            if (!IsPropertyTypeSuitable(prop))\n            {\n                GUIContent c = EditorGUIUtility.TempContent(\"Enum used on a non-float property: \" + prop.name,\n                    EditorGUIUtility.GetHelpIcon(MessageType.Warning));\n                EditorGUI.LabelField(position, c, EditorStyles.helpBox);\n                return;\n            }\n\n            MaterialEditor.BeginProperty(position, prop);\n\n            if (prop.propertyType == ShaderPropertyType.Float || prop.propertyType == ShaderPropertyType.Range)\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = prop.hasMixedValue;\n\n                var value = (int)prop.floatValue;\n                int selectedIndex = -1;\n                for (var index = 0; index < values.Length; index++)\n                {\n                    var i = values[index];\n                    if (i == value)\n                    {\n                        selectedIndex = index;\n                        break;\n                    }\n                }\n\n                var selIndex = EditorGUI.Popup(position, label, selectedIndex, names);\n                EditorGUI.showMixedValue = false;\n                if (EditorGUI.EndChangeCheck())\n                {\n                    prop.floatValue = (float)values[selIndex];\n                }\n            }\n            else\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = prop.hasMixedValue;\n\n                var value = prop.intValue;\n                int selectedIndex = -1;\n                for (var index = 0; index < values.Length; index++)\n                {\n                    var i = values[index];\n                    if (i == value)\n                    {\n                        selectedIndex = index;\n                        break;\n                    }\n                }\n\n                var selIndex = EditorGUI.Popup(position, label, selectedIndex, names);\n                EditorGUI.showMixedValue = false;\n                if (EditorGUI.EndChangeCheck())\n                {\n                    prop.intValue = values[selIndex];\n                }\n            }\n\n            MaterialEditor.EndProperty();\n        }\n    }\n\n    // [Space] or [Space(height)] decorator creates a vertical space before shader property.\n    internal class MaterialSpaceDecorator : MaterialPropertyDrawer\n    {\n        private readonly float height;\n\n        public MaterialSpaceDecorator()\n        {\n            height = 6f;\n        }\n\n        public MaterialSpaceDecorator(float height)\n        {\n            this.height = height;\n        }\n\n        public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor)\n        {\n            return height;\n        }\n\n        public override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor)\n        {\n        }\n    }\n\n    // [Header(foobar)] decorator shows \"foobar\" header before shader property.\n    internal class MaterialHeaderDecorator : MaterialPropertyDrawer\n    {\n        private readonly string header;\n\n        public MaterialHeaderDecorator(string header)\n        {\n            this.header = header;\n        }\n\n        // so that we can accept Header(1) and display that as text\n        public MaterialHeaderDecorator(float headerAsNumber)\n        {\n            this.header = headerAsNumber.ToString(CultureInfo.InvariantCulture);\n        }\n\n        public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor)\n        {\n            return 24f;\n        }\n\n        public override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor)\n        {\n            position.y += 8;\n            position = EditorGUI.IndentedRect(position);\n            GUI.Label(position, header, EditorStyles.boldLabel);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/MemorySettingsEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.IO;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditor.Build;\nusing UnityEditorInternal;\nusing UnityEngine.Rendering;\nusing UnityEngine.UIElements;\nusing UnityEditor.Callbacks;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(MemorySettings))]\n    internal class MemorySettingsEditor : Editor\n    {\n        class Content\n        {\n            public static readonly GUIContent kGeneralSettingsWarning = EditorGUIUtility.TrTextContent(\"Changing Memory setup values can cause severe performance degradation.\");\n            public static readonly GUIContent kEditorSettingsWarning = EditorGUIUtility.TrTextContent(\"Changing the memory setup for editor will update the ProjectSettings/boot.config file. This file is loaded at Editor startup, so will take effect at next startup.\");\n\n            public static readonly GUIContent kMainAllocatorsTitle = EditorGUIUtility.TrTextContent(\"Main Allocators\");\n\n            public static readonly GUIContent kMainAllocatorTitle = EditorGUIUtility.TrTextContent(\"Main Allocator\");\n            public static readonly GUIContent kMainAllocatorBlockSize = EditorGUIUtility.TrTextContent(\"Main Thread Block Size\", \"Block size used by main thread allocator\");\n            public static readonly GUIContent kThreadAllocatorBlockSize = EditorGUIUtility.TrTextContent(\"Shared Thread Block Size\", \"Block size used by shared thread allocator\");\n\n            public static readonly GUIContent kGfxAllocatorTitle = EditorGUIUtility.TrTextContent(\"Gfx Allocator\");\n            public static readonly GUIContent kMainGfxBlockSize = EditorGUIUtility.TrTextContent(\"Main Thread Block Size\", \"Block size used by main thread for gfx allocations\");\n            public static readonly GUIContent kThreadGfxBlockSize = EditorGUIUtility.TrTextContent(\"Shared Thread Block Size\", \"Block size used by shared threads for gfx allocations\");\n\n            public static readonly GUIContent kExtraAllocatorTitle = EditorGUIUtility.TrTextContent(\"Other Allocators\");\n            public static readonly GUIContent kCacheBlockSize = EditorGUIUtility.TrTextContent(\"File Cache Block Size\", \"Block size used by file cache allocator. Setting this value to 0 will cause the file cache allocations to be passed to the main allocator\");\n            public static readonly GUIContent kTypetreeBlockSize = EditorGUIUtility.TrTextContent(\"Type Tree Block Size\", \"Block size used by the tree allocator. Setting this value to 0 will cause the type tree allocations to be passed to the main allocator\");\n\n            public static readonly GUIContent kTempAllocatorTitle_Player = EditorGUIUtility.TrTextContent(\"Fast Per Thread Temporary Allocators\", \"Block size can grow to twice the initial size\");\n            public static readonly GUIContent kTempAllocatorTitle_Editor = EditorGUIUtility.TrTextContent(\"Fast Per Thread Temporary Allocators\", \"Block size can grow to 8 times the initial size\");\n            public static readonly GUIContent kTempAllocatorSizeMain = EditorGUIUtility.TrTextContent(\"Main Thread Block Size\", \"Initial size for main thread temp allocator\");\n            public static readonly GUIContent kTempAllocatorSizeJobWorker = EditorGUIUtility.TrTextContent(\"Job Worker Block Size\", \"Block size for worker job temp allocators\");\n            public static readonly GUIContent kTempAllocatorSizeBackgroundWorker = EditorGUIUtility.TrTextContent(\"Background Job Worker Block Size\", \"Block size for worker job temp allocators\");\n            public static readonly GUIContent kTempAllocatorSizePreloadManager = EditorGUIUtility.TrTextContent(\"Preload Block Size\", \"Block size for worker job temp allocators\");\n            public static readonly GUIContent kTempAllocatorSizeAudioWorker = EditorGUIUtility.TrTextContent(\"Audio Worker Block Size\", \"Block size for worker job temp allocators\");\n            public static readonly GUIContent kTempAllocatorSizeCloudWorker = EditorGUIUtility.TrTextContent(\"Cloud Worker Block Size\", \"Block size for worker job temp allocators\");\n            public static readonly GUIContent kTempAllocatorSizeGfx = EditorGUIUtility.TrTextContent(\"Gfx Thread Block Size\", \"Block size for worker job temp allocators\");\n            public static readonly GUIContent kTempAllocatorSizeGIBakingWorker = EditorGUIUtility.TrTextContent(\"GI Baking Block Size\", \"Block size for GI baking workers temp allocators\");\n            public static readonly GUIContent kTempAllocatorSizeNavMeshWorker = EditorGUIUtility.TrTextContent(\"NavMesh Worker Block Size\", \"Block size for worker job temp allocators\");\n\n            // TODO: guard input parameters\n            public static readonly GUIContent kJobTempAllocatorTitle = EditorGUIUtility.TrTextContent(\"Fast Thread Shared Temporary Allocators\");\n            public static readonly GUIContent kJobTempAllocatorBlockSize = EditorGUIUtility.TrTextContent(\"Job Allocator Block Size\", \"Block size for worker job temp allocators. Can grow to 64 blocks\");\n            public static readonly GUIContent kBackgroundJobTempAllocatorBlockSize = EditorGUIUtility.TrTextContent(\"Background Job Allocator Block Size\", \"Block size for background worker job temp allocators. Can grow to 64 blocks\");\n            public static readonly GUIContent kJobTempAllocatorReducedBlockSize = EditorGUIUtility.TrTextContent(\"Job Allocator Block Sizes on low memory platform\", \"Block sizes for job and background if platform has less than 2GB memory\");\n\n            public static readonly GUIContent kBucketAllocatorTitle = EditorGUIUtility.TrTextContent(\"Shared Bucket Allocator\");\n            public static readonly GUIContent kBucketAllocatorGranularity = EditorGUIUtility.TrTextContent(\"Bucket Allocator Granularity\", \"Bucket allocator bucket granularity\");\n            public static readonly GUIContent kBucketAllocatorBucketsCount = EditorGUIUtility.TrTextContent(\"Bucket Allocator BucketCount\", \"Number of bucket size increments of bucket granularity\");\n            public static readonly GUIContent kBucketAllocatorBlockSize = EditorGUIUtility.TrTextContent(\"Bucket Allocator Block Size\", \"Bucket allocator block size\");\n            public static readonly GUIContent kBucketAllocatorBlockCount = EditorGUIUtility.TrTextContent(\"Bucket Allocator Block Count\", \"Bucket allocator block count\");\n\n            public static readonly GUIContent kProfilerAllocatorTitle = EditorGUIUtility.TrTextContent(\"Profiler Allocators\");\n            public static readonly GUIContent kProfilerBlockSize = EditorGUIUtility.TrTextContent(\"Profiler Block Size\", \"Block size used by main profiler allocations\");\n            public static readonly GUIContent kProfilerEditorBlockSize = EditorGUIUtility.TrTextContent(\"Editor Profiler Block Size\", \"Editor only: Block size used by editor specific profiler allocations\");\n\n            public static readonly GUIContent kProfilerBucketAllocatorTitle = EditorGUIUtility.TrTextContent(\"Shared Profiler Bucket Allocator\");\n            public static readonly GUIContent kProfilerBucketAllocatorGranularity = EditorGUIUtility.TrTextContent(\"Bucket Allocator Granularity\", \"Bucket allocator bucket granularity\");\n            public static readonly GUIContent kProfilerBucketAllocatorBucketsCount = EditorGUIUtility.TrTextContent(\"Bucket Allocator BucketCount\", \"Number of bucket size increments of bucket granularity\");\n            public static readonly GUIContent kProfilerBucketAllocatorBlockSize = EditorGUIUtility.TrTextContent(\"Bucket Allocator Block Size\", \"Bucket allocator block size\");\n            public static readonly GUIContent kProfilerBucketAllocatorBlockCount = EditorGUIUtility.TrTextContent(\"Bucket Allocator Block Count\", \"Bucket allocator block count\");\n\n            public static readonly GUIContent kEditorLabel = EditorGUIUtility.TrTextContent(\"Editor\", \"Editor settings\");\n            public static readonly GUIContent kPlayerLabel = EditorGUIUtility.TrTextContent(\"Players\", \"player settings\");\n        }\n\n        class Styles\n        {\n            public static readonly GUIStyle lockButton = \"IN LockButton\";\n            public static readonly GUIStyle titleGroupHeader = new GUIStyle(EditorStyles.toolbar) { margin = new RectOffset() };\n            public static readonly GUIStyle settingsFramebox = new GUIStyle(EditorStyles.frameBox) { padding = new RectOffset(1, 1, 1, 0) };\n\n            public static readonly string warningDialogTitle = L10n.Tr(\"Edit memory settings\");\n            public static readonly string warningDialogText = L10n.Tr(\"Changing default memory setting can have severe negative impact on performance. Are you sure you want to continue?\");\n            public static readonly string okDialogButton = L10n.Tr(\"OK\");\n            public static readonly string cancelDialogButton = L10n.Tr(\"Cancel\");\n        }\n\n        const string kWarningDialogSessionKey = \"MemorySettingsWarning\";\n\n        SerializedProperty m_PlatformMemorySettingsProperty;\n        SerializedProperty m_EditorMemorySettingsProperty;\n        SerializedProperty m_DefaultMemorySettingsProperty;\n\n        static Styles s_Styles;\n        static SettingsProvider s_SettingsProvider;\n\n        int m_SelectedPlatform = 0;\n        BuildPlatform[] m_ValidPlatforms;\n        const int kMaxGroupCount = 10;\n        bool[] m_ShowSettingsUI = new bool[kMaxGroupCount];\n        AnimatedValues.AnimBool[] m_SettingsAnimator = new AnimatedValues.AnimBool[kMaxGroupCount];\n\n        Dictionary<BuildTarget, SerializedProperty> m_MemorySettingsDictionary;\n\n        public void OnEnable()\n        {\n            m_ValidPlatforms = BuildPlatforms.instance.GetValidPlatforms(true).ToArray();\n\n            m_EditorMemorySettingsProperty = serializedObject.FindProperty(\"m_EditorMemorySettings\");\n            m_PlatformMemorySettingsProperty = serializedObject.FindProperty(\"m_PlatformMemorySettings\");\n            m_DefaultMemorySettingsProperty = serializedObject.FindProperty(\"m_DefaultMemorySettings\");\n\n            m_MemorySettingsDictionary = new Dictionary<BuildTarget, SerializedProperty>();\n\n            foreach (SerializedProperty prop in m_PlatformMemorySettingsProperty)\n            {\n                m_MemorySettingsDictionary.Add((BuildTarget)prop.FindPropertyRelative(\"first\").intValue, prop.FindPropertyRelative(\"second\"));\n            }\n\n            for (var i = 0; i < m_SettingsAnimator.Length; i++)\n                m_SettingsAnimator[i] = new AnimatedValues.AnimBool(m_ShowSettingsUI[i], RepaintSettingsEditorWindow);\n        }\n\n        bool m_EditorSelected = true;\n        static GUIStyle s_TabOnlyOne;\n        static GUIStyle s_TabFirst;\n        static GUIStyle s_TabMiddle;\n        static GUIStyle s_TabLast;\n\n        static Rect GetTabRect(Rect rect, int tabIndex, int tabCount, out GUIStyle tabStyle)\n        {\n            if (s_TabOnlyOne == null)\n            {\n                s_TabOnlyOne = \"Tab onlyOne\";\n                s_TabFirst = \"Tab first\";\n                s_TabMiddle = \"Tab middle\";\n                s_TabLast = \"Tab last\";\n            }\n\n            tabStyle = s_TabMiddle;\n\n            if (tabCount == 1)\n            {\n                tabStyle = s_TabOnlyOne;\n            }\n            else if (tabIndex == 0)\n            {\n                tabStyle = s_TabFirst;\n            }\n            else if (tabIndex == (tabCount - 1))\n            {\n                tabStyle = s_TabLast;\n            }\n\n            float tabWidth = rect.width / tabCount;\n            int left = Mathf.RoundToInt(tabIndex * tabWidth);\n            int right = Mathf.RoundToInt((tabIndex + 1) * tabWidth);\n            return new Rect(rect.x + left, rect.y, right - left, EditorGUI.kTabButtonHeight);\n        }\n\n        void RepaintSettingsEditorWindow()\n        {\n            // Invoking a Repaint on an Editor instantiated via AssetSettingsProvider does not currently work due to a bug. So instead we store a reference to the settings provider and repaint it directly.\n            s_SettingsProvider?.Repaint();\n        }\n\n        private bool BeginGroup(int index, GUIContent title)\n        {\n            Debug.Assert(kMaxGroupCount > index, \"Max group count in MemorySettings is too low\");\n\n            var indentLevel = EditorGUI.indentLevel;\n            EditorGUILayout.BeginVertical(GUILayout.Height(20));\n\n            EditorGUILayout.BeginHorizontal((indentLevel == 0) ? Styles.titleGroupHeader : GUIStyle.none);\n            Rect r = GUILayoutUtility.GetRect(title, EditorStyles.inspectorTitlebarText);\n            r = EditorGUI.IndentedRect(r);\n            EditorGUI.indentLevel = 0;\n            m_ShowSettingsUI[index] = EditorGUI.FoldoutTitlebar(r, title, m_ShowSettingsUI[index], true, EditorStyles.inspectorTitlebarFlat, EditorStyles.inspectorTitlebarText);\n            EditorGUI.indentLevel = indentLevel;\n            EditorGUILayout.EndHorizontal();\n\n            m_SettingsAnimator[index].target = m_ShowSettingsUI[index];\n\n            var visible = EditorGUILayout.BeginFadeGroup(m_SettingsAnimator[index].faded);\n            EditorGUI.indentLevel++;\n            EditorGUILayout.Space();\n            return visible;\n        }\n\n        private void EndGroup()\n        {\n            EditorGUI.indentLevel--;\n            EditorGUILayout.Space();\n            EditorGUILayout.EndFadeGroup();\n            EditorGUILayout.EndVertical();\n        }\n\n        enum SizeEnum\n        {\n            B,\n            KB,\n            MB,\n        }\n\n        private void OptionalVariableField(SerializedProperty settings, string variablename, GUIContent label, bool useBytes = true)\n        {\n            const int k_FieldSpacing = 2;\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            var prop = settings.FindPropertyRelative(variablename);\n            var defaultValueProp = m_DefaultMemorySettingsProperty.FindPropertyRelative(variablename);\n            var overrideText = new GUIContent(string.Empty, \"Override Default\");\n\n            var toggleSize = EditorStyles.toggle.CalcSize(overrideText);\n            var enumValue = SizeEnum.MB;\n            var sizeEnumWidth = EditorStyles.popup.CalcSize(GUIContent.Temp(enumValue.ToString())).x;\n            var minWidth = EditorGUI.indent + EditorGUIUtility.labelWidth + EditorGUI.kSpacing + toggleSize.x + EditorGUI.kSpacing + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing + sizeEnumWidth;\n            var rect = GUILayoutUtility.GetRect(minWidth, EditorGUIUtility.singleLineHeight + k_FieldSpacing);\n            rect.height -= k_FieldSpacing;\n            rect = EditorGUI.IndentedRect(rect);\n            var indent = EditorGUI.indentLevel;\n            EditorGUI.indentLevel = 0;\n\n            var labelRect = rect;\n            labelRect.width = EditorGUIUtility.labelWidth;\n            GUI.Label(labelRect, label);\n\n            var toggleRect = rect;\n            toggleRect.xMin = labelRect.xMax + EditorGUI.kSpacing;\n            toggleRect.size = toggleSize;\n            var useDefault = prop.intValue < 0;\n            var newuseDefault = GUI.Toggle(toggleRect, useDefault, overrideText, Styles.lockButton);\n\n            var fieldRect = rect;\n            fieldRect.xMin = toggleRect.xMax + EditorGUI.kSpacing;\n            fieldRect.xMax = Mathf.Max(fieldRect.xMax - sizeEnumWidth - EditorGUI.kSpacing, fieldRect.xMin + EditorGUIUtility.fieldWidth);\n            var defaultValue = defaultValueProp.intValue;\n\n            var sizeEnumRect = rect;\n            sizeEnumRect.xMin = fieldRect.xMax + EditorGUI.kSpacing;\n            sizeEnumRect.width = sizeEnumWidth;\n\n            if (newuseDefault != useDefault)\n            {\n                if (!newuseDefault)\n                {\n                    var result = EditorUtility.DisplayDialog(Styles.warningDialogTitle, Styles.warningDialogText, Styles.okDialogButton, Styles.cancelDialogButton, DialogOptOutDecisionType.ForThisSession, kWarningDialogSessionKey);\n                    if (!result)\n                        newuseDefault = true;\n                }\n\n                prop.intValue = newuseDefault ? -1 : defaultValue;\n            }\n\n            if (newuseDefault)\n            {\n                using (new EditorGUI.DisabledScope(true))\n                {\n                    int displayValue = defaultValue;\n                    if (useBytes)\n                    {\n                        enumValue = SizeEnum.B;\n                        if ((defaultValue % (1024 * 1024)) == 0)\n                        {\n                            enumValue = SizeEnum.MB;\n                            displayValue /= 1024 * 1024;\n                        }\n                        else if ((defaultValue % 1024) == 0)\n                        {\n                            enumValue = SizeEnum.KB;\n                            displayValue /= 1024;\n                        }\n                    }\n                    EditorGUI.IntField(fieldRect, displayValue);\n                    if (useBytes)\n                        EditorGUI.EnumPopup(sizeEnumRect, enumValue);\n                }\n            }\n            else\n            {\n                int factor = 1;\n                enumValue = SizeEnum.B;\n                int oldIntValue = prop.intValue;\n                if (useBytes)\n                {\n                    if ((oldIntValue % (1024 * 1024)) == 0)\n                    {\n                        factor = 1024 * 1024;\n                        enumValue = SizeEnum.MB;\n                    }\n                    else if ((oldIntValue % 1024) == 0)\n                    {\n                        factor = 1024;\n                        enumValue = SizeEnum.KB;\n                    }\n                }\n                var newIntValue = factor * EditorGUI.DelayedIntField(fieldRect, oldIntValue / factor);\n                if (useBytes)\n                {\n                    SizeEnum newEnumValue = (SizeEnum)EditorGUI.EnumPopup(sizeEnumRect, enumValue);\n\n                    if (newEnumValue != enumValue)\n                    {\n                        if (newEnumValue == SizeEnum.MB)\n                        {\n                            if (enumValue == SizeEnum.KB)\n                                newIntValue *= 1024;\n                            else\n                                newIntValue *= 1024 * 1024;\n                        }\n                        if (newEnumValue == SizeEnum.KB)\n                        {\n                            if (enumValue == SizeEnum.MB)\n                                newIntValue /= 1024;\n                            else\n                                newIntValue *= 1024;\n                        }\n                        if (newEnumValue == SizeEnum.B)\n                        {\n                            if (enumValue == SizeEnum.MB)\n                                newIntValue /= 1024 * 1024;\n                            else\n                                newIntValue /= 1024;\n                        }\n                    }\n                }\n                prop.intValue = newIntValue;\n            }\n\n            EditorGUI.indentLevel = indent;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.HelpBox(Content.kGeneralSettingsWarning.text, MessageType.Warning, true);\n\n            Rect r = EditorGUILayout.BeginVertical(Styles.settingsFramebox);\n            GUIStyle buttonStyle = null;\n\n            Rect buttonRect = GetTabRect(r, 0, 2, out buttonStyle);\n            if (GUI.Toggle(buttonRect, m_EditorSelected, Content.kEditorLabel, buttonStyle))\n                m_EditorSelected = true;\n\n            buttonRect = GetTabRect(r, 1, 2, out buttonStyle);\n            if (GUI.Toggle(buttonRect, !m_EditorSelected, Content.kPlayerLabel, buttonStyle))\n                m_EditorSelected = false;\n\n            GUILayoutUtility.GetRect(10, EditorGUI.kTabButtonHeight);\n\n            EditorGUI.EndChangeCheck();\n\n            SerializedProperty currentSettings;\n            if (m_EditorSelected)\n            {\n                EditorGUI.BeginChangeCheck();\n                GUILayout.Label(\"Settings for Editor\");\n                EditorGUILayout.HelpBox(Content.kEditorSettingsWarning.text, MessageType.Warning, true);\n                EditorGUILayout.Space();\n                currentSettings = m_EditorMemorySettingsProperty;\n                MemorySettingsUtils.InitializeDefaultsForPlatform(-1);\n            }\n            else\n            {\n                GUILayout.Label(\"Settings for Players\");\n                m_SelectedPlatform = EditorGUILayout.BeginPlatformGrouping(m_ValidPlatforms, null, Styles.settingsFramebox);\n                GUILayout.Label(string.Format(L10n.Tr(\"Settings for {0}\"), m_ValidPlatforms[m_SelectedPlatform].title.text));\n                if (!m_MemorySettingsDictionary.TryGetValue(m_ValidPlatforms[m_SelectedPlatform].defaultTarget, out currentSettings))\n                {\n                    MemorySettingsUtils.SetPlatformDefaultValues((int)m_ValidPlatforms[m_SelectedPlatform].defaultTarget);\n                    serializedObject.Update();\n                    OnEnable();\n                    m_MemorySettingsDictionary.TryGetValue(m_ValidPlatforms[m_SelectedPlatform].defaultTarget, out currentSettings);\n                }\n                MemorySettingsUtils.InitializeDefaultsForPlatform((int)m_ValidPlatforms[m_SelectedPlatform].defaultTarget);\n            }\n\n            if (BeginGroup(0, Content.kMainAllocatorsTitle))\n            {\n                if (BeginGroup(1, Content.kMainAllocatorTitle))\n                {\n                    OptionalVariableField(currentSettings, \"m_MainAllocatorBlockSize\", Content.kMainAllocatorBlockSize);\n                    OptionalVariableField(currentSettings, \"m_ThreadAllocatorBlockSize\", Content.kThreadAllocatorBlockSize);\n                }\n                EndGroup();\n                if (BeginGroup(2, Content.kGfxAllocatorTitle))\n                {\n                    OptionalVariableField(currentSettings, \"m_MainGfxBlockSize\", Content.kMainGfxBlockSize);\n                    OptionalVariableField(currentSettings, \"m_ThreadGfxBlockSize\", Content.kThreadGfxBlockSize);\n                }\n                EndGroup();\n                if (BeginGroup(3, Content.kExtraAllocatorTitle))\n                {\n                    OptionalVariableField(currentSettings, \"m_CacheBlockSize\", Content.kCacheBlockSize);\n                    OptionalVariableField(currentSettings, \"m_TypetreeBlockSize\", Content.kTypetreeBlockSize);\n                }\n                EndGroup();\n                if (BeginGroup(4, Content.kBucketAllocatorTitle))\n                {\n                    OptionalVariableField(currentSettings, \"m_BucketAllocatorGranularity\", Content.kBucketAllocatorGranularity);\n                    OptionalVariableField(currentSettings, \"m_BucketAllocatorBucketsCount\", Content.kBucketAllocatorBucketsCount, false);\n                    OptionalVariableField(currentSettings, \"m_BucketAllocatorBlockSize\", Content.kBucketAllocatorBlockSize);\n                    OptionalVariableField(currentSettings, \"m_BucketAllocatorBlockCount\", Content.kBucketAllocatorBlockCount, false);\n                }\n                EndGroup();\n            }\n            EndGroup();\n\n            if (BeginGroup(5, m_EditorSelected ? Content.kTempAllocatorTitle_Editor : Content.kTempAllocatorTitle_Player))\n            {\n                OptionalVariableField(currentSettings, \"m_TempAllocatorSizeMain\", Content.kTempAllocatorSizeMain);\n                OptionalVariableField(currentSettings, \"m_TempAllocatorSizeJobWorker\", Content.kTempAllocatorSizeJobWorker);\n                OptionalVariableField(currentSettings, \"m_TempAllocatorSizeBackgroundWorker\", Content.kTempAllocatorSizeBackgroundWorker);\n                OptionalVariableField(currentSettings, \"m_TempAllocatorSizePreloadManager\", Content.kTempAllocatorSizePreloadManager);\n                OptionalVariableField(currentSettings, \"m_TempAllocatorSizeAudioWorker\", Content.kTempAllocatorSizeAudioWorker);\n                OptionalVariableField(currentSettings, \"m_TempAllocatorSizeCloudWorker\", Content.kTempAllocatorSizeCloudWorker);\n                OptionalVariableField(currentSettings, \"m_TempAllocatorSizeGfx\", Content.kTempAllocatorSizeGfx);\n                OptionalVariableField(currentSettings, \"m_TempAllocatorSizeGIBakingWorker\", Content.kTempAllocatorSizeGIBakingWorker);\n                OptionalVariableField(currentSettings, \"m_TempAllocatorSizeNavMeshWorker\", Content.kTempAllocatorSizeNavMeshWorker);\n            }\n            EndGroup();\n            if (BeginGroup(6, Content.kJobTempAllocatorTitle))\n            {\n                OptionalVariableField(currentSettings, \"m_JobTempAllocatorBlockSize\", Content.kJobTempAllocatorBlockSize);\n                OptionalVariableField(currentSettings, \"m_BackgroundJobTempAllocatorBlockSize\", Content.kBackgroundJobTempAllocatorBlockSize);\n                OptionalVariableField(currentSettings, \"m_JobTempAllocatorReducedBlockSize\", Content.kJobTempAllocatorReducedBlockSize);\n            }\n            EndGroup();\n\n            if (BeginGroup(7, Content.kProfilerAllocatorTitle))\n            {\n                OptionalVariableField(currentSettings, \"m_ProfilerBlockSize\", Content.kProfilerBlockSize);\n                if (m_EditorSelected)\n                    OptionalVariableField(currentSettings, \"m_ProfilerEditorBlockSize\", Content.kProfilerEditorBlockSize);\n\n                if (BeginGroup(8, Content.kProfilerBucketAllocatorTitle))\n                {\n                    OptionalVariableField(currentSettings, \"m_ProfilerBucketAllocatorGranularity\", Content.kProfilerBucketAllocatorGranularity);\n                    OptionalVariableField(currentSettings, \"m_ProfilerBucketAllocatorBucketsCount\", Content.kProfilerBucketAllocatorBucketsCount, false);\n                    OptionalVariableField(currentSettings, \"m_ProfilerBucketAllocatorBlockSize\", Content.kProfilerBucketAllocatorBlockSize);\n                    OptionalVariableField(currentSettings, \"m_ProfilerBucketAllocatorBlockCount\", Content.kProfilerBucketAllocatorBlockCount, false);\n                }\n                EndGroup();\n            }\n            EndGroup();\n\n            if (m_EditorSelected)\n            {\n                if (EditorGUI.EndChangeCheck())\n                {\n                    serializedObject.ApplyModifiedProperties();\n                    MemorySettingsUtils.WriteEditorMemorySettings();\n                }\n            }\n            else\n            {\n                EditorGUILayout.EndPlatformGrouping();\n                serializedObject.ApplyModifiedProperties();\n            }\n\n            EditorGUILayout.EndVertical();\n        }\n\n        [SettingsProvider]\n        internal static SettingsProvider CreateProjectSettingsProvider()\n        {\n            var provider = AssetSettingsProvider.CreateProviderFromAssetPath(\n                \"Project/Memory Settings\", \"ProjectSettings/MemorySettings.asset\",\n                SettingsProvider.GetSearchKeywordsFromGUIContentProperties<Content>());\n            s_SettingsProvider = provider;\n            return provider;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/MeshPreview.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UObject = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    public class MeshPreview : IDisposable\n    {\n        internal static class Styles\n        {\n            const string k_DisplayModeTooltip = \"Change display mode\";\n\n            public static readonly GUIContent meshLodIcon = EditorGUIUtility.TrIconContent(\"MeshLOD\", \"Select a LOD to view.\");\n            public static readonly GUIContent wireframeToggle = EditorGUIUtility.TrIconContent(EditorGUIUtility.LoadIconRequired(\"Toolbars/wireframe\"), \"Show wireframe\");\n\n            public static GUIContent displayModeDropdown = EditorGUIUtility.TrTextContent(\"\", \"Change display mode\");\n            public static readonly GUIContent shadedIcon = EditorGUIUtility.TrIconContent(\"Toolbars/Shaded\", k_DisplayModeTooltip);\n            public static readonly GUIContent uvIcon = EditorGUIUtility.TrIconContent(\"PreTextureMipMapLow\", k_DisplayModeTooltip);\n\n            public static GUIContent uvChannelDropdown = EditorGUIUtility.TrTextContent(\"\", k_DisplayModeTooltip);\n\n            public static GUIStyle preSlider = \"preSlider\";\n            public static GUIStyle preSliderThumb = \"preSliderThumb\";\n        }\n\n        internal class Settings : IDisposable\n        {\n            public DisplayMode displayMode { get => m_DisplayMode; set => SetValue(ref m_DisplayMode, value); }\n            DisplayMode m_DisplayMode = DisplayMode.Shaded;\n\n            public int activeUVChannel { get => m_ActiveUVChannel; set => SetValue(ref m_ActiveUVChannel, value); }\n            int m_ActiveUVChannel = 0;\n\n            public int activeLod { get => m_SelectedLod; set => SetValue(ref m_SelectedLod, value); }\n            int m_SelectedLod;\n\n            public int activeBlendshape { get => m_ActiveBlendshape; set => SetValue(ref m_ActiveBlendshape, value); }\n            int m_ActiveBlendshape = 0;\n\n            public bool drawWire { get => m_DrawWire; set => SetValue(ref m_DrawWire, value); }\n            bool m_DrawWire = true;\n\n            public Vector3 orthoPosition { get => m_OrthoPosition; set => SetValue(ref m_OrthoPosition, value); }\n            Vector3 m_OrthoPosition = new Vector3(0.0f, 0.0f, 0.0f);\n\n            public Vector2 previewDir { get => m_PreviewDir; set => SetValue(ref m_PreviewDir, value); }\n            Vector2 m_PreviewDir = new Vector2(0, 0);\n\n            public Vector2 lightDir { get => m_LightDir; set => SetValue(ref m_LightDir, value); }\n            Vector2 m_LightDir = new Vector2(0, 0);\n\n            public Vector3 pivotPositionOffset { get => m_PivotPositionOffset; set => SetValue(ref m_PivotPositionOffset, value); }\n            Vector3 m_PivotPositionOffset = Vector3.zero;\n\n            public float zoomFactor { get => m_ZoomFactor; set => SetValue(ref m_ZoomFactor, value); }\n            float m_ZoomFactor = 1.0f;\n\n            public int checkerTextureMultiplier { get => m_CheckerTextureMultiplier; set => SetValue(ref m_CheckerTextureMultiplier, value); }\n            int m_CheckerTextureMultiplier = 10;\n\n            public Material shadedPreviewMaterial { get => m_ShadedPreviewMaterial; set => SetValue(ref m_ShadedPreviewMaterial, value); }\n            Material m_ShadedPreviewMaterial;\n            public Material activeMaterial { get => m_ActiveMaterial; set => SetValue(ref m_ActiveMaterial, value); }\n            Material m_ActiveMaterial;\n            public Material meshMultiPreviewMaterial { get => m_MeshMultiPreviewMaterial; set => SetValue(ref m_MeshMultiPreviewMaterial, value); }\n            Material m_MeshMultiPreviewMaterial;\n            public Material wireMaterial { get => m_WireMaterial; set => SetValue(ref m_WireMaterial, value); }\n            Material m_WireMaterial;\n            public Material lineMaterial { get => m_LineMaterial; set => SetValue(ref m_LineMaterial, value); }\n            Material m_LineMaterial;\n            public Texture2D checkeredTexture { get => m_CheckeredTexture; set => SetValue(ref m_CheckeredTexture, value); }\n            Texture2D m_CheckeredTexture;\n\n            public bool[] availableDisplayModes { get => m_AvailableDisplayModes; set => SetValue(ref m_AvailableDisplayModes, value); }\n            bool[] m_AvailableDisplayModes = Enumerable.Repeat(true, 7).ToArray();\n\n            public bool[] availableUVChannels { get => m_AvailableUVChannels; set => SetValue(ref m_AvailableUVChannels, value); }\n            bool[] m_AvailableUVChannels = Enumerable.Repeat(true, 8).ToArray();\n\n            public event Action changed;\n\n            public Settings()\n            {\n                shadedPreviewMaterial = new Material(Shader.Find(\"Standard\"));\n                wireMaterial = CreateWireframeMaterial();\n                meshMultiPreviewMaterial = CreateMeshMultiPreviewMaterial();\n                lineMaterial = CreateLineMaterial();\n                checkeredTexture = EditorGUIUtility.LoadRequired(\"Previews/Textures/textureChecker.png\") as Texture2D;\n                activeMaterial = shadedPreviewMaterial;\n\n                orthoPosition = new Vector3(0.5f, 0.5f, -1);\n                previewDir = new Vector2(130, 0);\n                lightDir = new Vector2(-40, -40);\n                zoomFactor = 1.0f;\n                activeLod = 0;\n            }\n\n            public void Dispose()\n            {\n                if (shadedPreviewMaterial != null)\n                    UObject.DestroyImmediate(shadedPreviewMaterial);\n                if (wireMaterial != null)\n                    UObject.DestroyImmediate(wireMaterial);\n                if (meshMultiPreviewMaterial != null)\n                    UObject.DestroyImmediate(meshMultiPreviewMaterial);\n                if (lineMaterial != null)\n                    UObject.DestroyImmediate(lineMaterial);\n            }\n\n            void SetValue<T>(ref T setting, T newValue)\n            {\n                if (setting == null || !setting.Equals(newValue))\n                {\n                    setting = newValue;\n                    changed?.Invoke();\n                }\n            }\n\n            public void Copy(Settings other)\n            {\n                displayMode = other.displayMode;\n                activeUVChannel = other.activeUVChannel;\n                activeBlendshape = other.activeBlendshape;\n                drawWire = other.drawWire;\n\n                orthoPosition = other.orthoPosition;\n                previewDir = other.previewDir;\n                lightDir = other.lightDir;\n                pivotPositionOffset = other.pivotPositionOffset;\n                zoomFactor = other.zoomFactor;\n                checkerTextureMultiplier = other.checkerTextureMultiplier;\n                activeLod = other.activeLod;\n\n                shadedPreviewMaterial = other.shadedPreviewMaterial;\n                activeMaterial = other.activeMaterial;\n                meshMultiPreviewMaterial = other.meshMultiPreviewMaterial;\n                wireMaterial = other.wireMaterial;\n                lineMaterial = other.lineMaterial;\n                checkeredTexture = other.checkeredTexture;\n\n                availableDisplayModes = new bool[other.availableDisplayModes.Length];\n                Array.Copy(other.availableDisplayModes, availableDisplayModes, other.availableDisplayModes.Length);\n\n                availableUVChannels = new bool[other.availableUVChannels.Length];\n                Array.Copy(other.availableUVChannels, availableUVChannels, other.availableUVChannels.Length);\n            }\n        }\n\n        static string[] m_DisplayModes =\n        {\n            \"Shaded\", \"UV Checker\", \"UV Layout\",\n            \"Vertex Color\", \"Normals\", \"Tangents\", \"Blendshapes\"\n        };\n\n        static string[] m_UVChannels =\n        {\n            \"Channel 0\", \"Channel 1\", \"Channel 2\", \"Channel 3\", \"Channel 4\", \"Channel 5\", \"Channel 6\", \"Channel 7\"\n        };\n\n        internal enum DisplayMode\n        {\n            Shaded = 0,\n            UVChecker = 1,\n            UVLayout = 2,\n            VertexColor = 3,\n            Normals = 4,\n            Tangent = 5,\n            Blendshapes = 6\n        }\n\n        Mesh m_Target;\n\n        public Mesh mesh\n        {\n            get => m_Target;\n            set => m_Target = value;\n        }\n\n        PreviewRenderUtility m_PreviewUtility;\n        Settings m_Settings;\n\n        internal event Action<MeshPreview> settingsChanged;\n\n        Mesh m_BakedSkinnedMesh;\n        List<string> m_BlendShapes;\n\n        public MeshPreview(Mesh target)\n        {\n            m_Target = target;\n\n            m_PreviewUtility = new PreviewRenderUtility();\n            m_PreviewUtility.camera.fieldOfView = 30.0f;\n            m_PreviewUtility.camera.transform.position = new Vector3(5, 5, 0);\n\n            m_Settings = new Settings();\n\n            //Fix for FogBugz case : 1364821 Inspector Model Preview orientation is reversed when Bake Axis Conversion is enabled\n            var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(target)) as ModelImporter;\n            if (importer && importer.bakeAxisConversion)\n            {\n                m_Settings.previewDir += new Vector2(180,0);\n            }\n\n            m_Settings.changed += OnSettingsChanged;\n            m_BlendShapes = new List<string>();\n            CheckAvailableAttributes();\n        }\n\n        public void Dispose()\n        {\n            DestroyBakedSkinnedMesh();\n            m_PreviewUtility.Cleanup();\n            m_Settings.changed -= OnSettingsChanged;\n            m_Settings.Dispose();\n        }\n\n\n        void OnSettingsChanged()\n        {\n            settingsChanged?.Invoke(this);\n        }\n\n        static Material CreateWireframeMaterial()\n        {\n            var shader = Shader.FindBuiltin(\"Internal-Colored.shader\");\n            if (!shader)\n            {\n                Debug.LogWarning(\"Could not find the built-in Colored shader\");\n                return null;\n            }\n            var mat = new Material(shader);\n            mat.hideFlags = HideFlags.HideAndDontSave;\n            mat.SetColor(\"_Color\", new Color(0, 0, 0, 0.3f));\n            mat.SetFloat(\"_ZWrite\", 0.0f);\n            mat.SetFloat(\"_ZBias\", -1.0f);\n            return mat;\n        }\n\n        static Material CreateMeshMultiPreviewMaterial()\n        {\n            var shader = EditorGUIUtility.LoadRequired(\"Previews/MeshPreviewShader.shader\") as Shader;\n            if (!shader)\n            {\n                Debug.LogWarning(\"Could not find the built in Mesh preview shader\");\n                return null;\n            }\n            var mat = new Material(shader);\n            mat.hideFlags = HideFlags.HideAndDontSave;\n            return mat;\n        }\n\n        static Material CreateLineMaterial()\n        {\n            Shader shader = Shader.FindBuiltin(\"Internal-Colored.shader\");\n            if (!shader)\n            {\n                Debug.LogWarning(\"Could not find the built-in Colored shader\");\n                return null;\n            }\n            var mat = new Material(shader);\n            mat.hideFlags = HideFlags.HideAndDontSave;\n            mat.SetFloat(\"_SrcBlend\", (float)BlendMode.SrcAlpha);\n            mat.SetFloat(\"_DstBlend\", (float)BlendMode.OneMinusSrcAlpha);\n            mat.SetFloat(\"_Cull\", (float)CullMode.Off);\n            mat.SetFloat(\"_ZWrite\", 0.0f);\n            return mat;\n        }\n\n        void ResetView()\n        {\n            m_Settings.zoomFactor = 1.0f;\n            m_Settings.orthoPosition = new Vector3(0.5f, 0.5f, -1);\n            m_Settings.pivotPositionOffset = Vector3.zero;\n\n            m_Settings.activeUVChannel = 0;\n\n            m_Settings.meshMultiPreviewMaterial.SetFloat(\"_UVChannel\", (float)m_Settings.activeUVChannel);\n            m_Settings.meshMultiPreviewMaterial.SetTexture(\"_MainTex\", null);\n\n            m_Settings.activeBlendshape = 0;\n            m_Settings.activeLod = 0;\n        }\n\n        void FrameObject()\n        {\n            m_Settings.zoomFactor = 1.0f;\n            m_Settings.orthoPosition = new Vector3(0.5f, 0.5f, -1);\n            m_Settings.pivotPositionOffset = Vector3.zero;\n        }\n\n        void CheckAvailableAttributes()\n        {\n            if (!mesh.HasVertexAttribute(VertexAttribute.Color))\n                m_Settings.availableDisplayModes[(int)DisplayMode.VertexColor] = false;\n            if (!mesh.HasVertexAttribute(VertexAttribute.Normal))\n                m_Settings.availableDisplayModes[(int)DisplayMode.Normals] = false;\n            if (!mesh.HasVertexAttribute(VertexAttribute.Tangent))\n                m_Settings.availableDisplayModes[(int)DisplayMode.Tangent] = false;\n\n            int index = 0;\n            for (int i = 4; i < 12; i++)\n            {\n                if (!mesh.HasVertexAttribute((VertexAttribute)i))\n                    m_Settings.availableUVChannels[index] = false;\n                index++;\n            }\n\n            var blendShapeCount = mesh.blendShapeCount;\n\n            if (blendShapeCount > 0)\n            {\n                for (int i = 0; i < blendShapeCount; i++)\n                {\n                    m_BlendShapes.Add(mesh.GetBlendShapeName(i));\n                }\n            }\n            else\n            {\n                m_Settings.availableDisplayModes[(int)DisplayMode.Blendshapes] = false;\n            }\n        }\n\n        void DoPopup(Rect popupRect, string[] elements, int selectedIndex, GenericMenu.MenuFunction2 func, bool[] disabledItems)\n        {\n            GenericMenu menu = new GenericMenu();\n            for (int i = 0; i < elements.Length; i++)\n            {\n                var element = elements[i];\n                if (element == m_DisplayModes[(int)DisplayMode.Blendshapes] && Selection.count > 1)\n                    continue;\n\n                if (disabledItems == null || disabledItems[i])\n                    menu.AddItem(new GUIContent(element), i == selectedIndex, func, i);\n                else\n                    menu.AddDisabledItem(new GUIContent(element));\n            }\n            menu.DropDown(popupRect);\n        }\n\n        void SetUVChannel(object data)\n        {\n            int popupIndex = (int)data;\n            if (popupIndex < 0 || popupIndex >= m_Settings.availableUVChannels.Length)\n                return;\n\n            m_Settings.activeUVChannel = popupIndex;\n\n            if (m_Settings.displayMode == DisplayMode.UVLayout || m_Settings.displayMode == DisplayMode.UVChecker)\n                m_Settings.activeMaterial.SetFloat(\"_UVChannel\", (float)popupIndex);\n        }\n\n        void DestroyBakedSkinnedMesh()\n        {\n            if (m_BakedSkinnedMesh)\n                UObject.DestroyImmediate(m_BakedSkinnedMesh);\n        }\n\n        void SetDisplayMode(object data)\n        {\n            int popupIndex = (int)data;\n            if (popupIndex < 0 || popupIndex >= m_DisplayModes.Length)\n                return;\n\n            m_Settings.displayMode = (DisplayMode)popupIndex;\n\n            DestroyBakedSkinnedMesh();\n\n            switch (m_Settings.displayMode)\n            {\n                case DisplayMode.Shaded:\n                    OnDropDownAction(m_Settings.shadedPreviewMaterial, 0, false);\n                    break;\n                case DisplayMode.UVChecker:\n                    OnDropDownAction(m_Settings.meshMultiPreviewMaterial, 4, false);\n                    m_Settings.meshMultiPreviewMaterial.SetTexture(\"_MainTex\", m_Settings.checkeredTexture);\n                    m_Settings.meshMultiPreviewMaterial.mainTextureScale = new Vector2(m_Settings.checkerTextureMultiplier, m_Settings.checkerTextureMultiplier);\n                    break;\n                case DisplayMode.UVLayout:\n                    OnDropDownAction(m_Settings.meshMultiPreviewMaterial, 0, true);\n                    break;\n                case DisplayMode.VertexColor:\n                    OnDropDownAction(m_Settings.meshMultiPreviewMaterial, 1, false);\n                    break;\n                case DisplayMode.Normals:\n                    OnDropDownAction(m_Settings.meshMultiPreviewMaterial, 2, false);\n                    break;\n                case DisplayMode.Tangent:\n                    OnDropDownAction(m_Settings.meshMultiPreviewMaterial, 3, false);\n                    break;\n                case DisplayMode.Blendshapes:\n                    OnDropDownAction(m_Settings.shadedPreviewMaterial, 0, false);\n                    BakeSkinnedMesh();\n                    break;\n            }\n        }\n\n        void SetBlendshape(object data)\n        {\n            int popupIndex = (int)data;\n            if (popupIndex < 0 || popupIndex >= m_BlendShapes.Count)\n                return;\n\n            m_Settings.activeBlendshape = popupIndex;\n\n            DestroyBakedSkinnedMesh();\n            BakeSkinnedMesh();\n        }\n\n        internal void CopySettings(MeshPreview other)\n        {\n            m_Settings.Copy(other.m_Settings);\n        }\n\n        internal static void RenderMeshPreview(\n            Mesh mesh,\n            PreviewRenderUtility previewUtility,\n            Settings settings,\n            int meshSubset)\n        {\n            if (mesh == null || previewUtility == null)\n                return;\n\n            Bounds bounds = mesh.bounds;\n\n            Transform renderCamTransform = previewUtility.camera.GetComponent<Transform>();\n            previewUtility.camera.nearClipPlane = 0.0001f;\n            previewUtility.camera.farClipPlane = 1000f;\n\n            if (settings.displayMode == DisplayMode.UVLayout)\n            {\n                previewUtility.camera.orthographic = true;\n                previewUtility.camera.orthographicSize = settings.zoomFactor;\n                renderCamTransform.position = settings.orthoPosition;\n                renderCamTransform.rotation = Quaternion.identity;\n                DrawUVLayout(mesh, previewUtility, settings);\n                return;\n            }\n\n            float halfSize = bounds.extents.magnitude;\n            float distance = 4.0f * halfSize;\n\n            previewUtility.camera.orthographic = false;\n            Quaternion camRotation = Quaternion.identity;\n            Vector3 camPosition = camRotation * Vector3.forward * (-distance * settings.zoomFactor) + settings.pivotPositionOffset;\n\n            renderCamTransform.position = camPosition;\n            renderCamTransform.rotation = camRotation;\n\n            previewUtility.lights[0].intensity = 1.1f;\n            previewUtility.lights[0].transform.rotation = Quaternion.Euler(-settings.lightDir.y, -settings.lightDir.x, 0);\n            previewUtility.lights[1].intensity = 1.1f;\n            previewUtility.lights[1].transform.rotation = Quaternion.Euler(settings.lightDir.y, settings.lightDir.x, 0);\n\n            previewUtility.ambientColor = new Color(.1f, .1f, .1f, 0);\n\n            RenderMeshPreviewSkipCameraAndLighting(mesh, bounds, previewUtility, settings, null, meshSubset);\n        }\n\n        static void DrawUVLayout(Mesh mesh, PreviewRenderUtility previewUtility, Settings settings)\n        {\n            GL.PushMatrix();\n\n            // draw UV grid\n            settings.lineMaterial.SetPass(0);\n\n            GL.LoadProjectionMatrix(previewUtility.camera.projectionMatrix);\n            GL.MultMatrix(previewUtility.camera.worldToCameraMatrix);\n\n            GL.Begin(GL.LINES);\n            const float step = 0.125f;\n            for (var g = -2.0f; g <= 3.0f; g += step)\n            {\n                var majorLine = Mathf.Abs(g - Mathf.Round(g)) < 0.01f;\n                if (majorLine)\n                {\n                    // major grid lines: larger area than [0..1] range, more opaque\n                    GL.Color(new Color(0.6f, 0.6f, 0.7f, 1.0f));\n                    GL.Vertex3(-2, g, 0);\n                    GL.Vertex3(+3, g, 0);\n                    GL.Vertex3(g, -2, 0);\n                    GL.Vertex3(g, +3, 0);\n                }\n                else if (g >= 0 && g <= 1)\n                {\n                    // minor grid lines: only within [0..1] area, more transparent\n                    GL.Color(new Color(0.6f, 0.6f, 0.7f, 0.5f));\n                    GL.Vertex3(0, g, 0);\n                    GL.Vertex3(1, g, 0);\n                    GL.Vertex3(g, 0, 0);\n                    GL.Vertex3(g, 1, 0);\n                }\n            }\n            GL.End();\n\n            // draw the mesh\n            GL.LoadIdentity();\n            settings.meshMultiPreviewMaterial.SetPass(0);\n            GL.wireframe = true;\n            Graphics.DrawMeshNow(mesh, previewUtility.camera.worldToCameraMatrix);\n            GL.wireframe = false;\n\n            GL.PopMatrix();\n        }\n\n        internal static Color GetSubMeshTint(int index)\n        {\n            // color palette generator based on \"golden ratio\" idea, like in\n            // https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/\n            var hue = Mathf.Repeat(index * 0.618f, 1);\n            var sat = index == 0 ? 0f : 0.3f;\n            var val = 1f;\n            return Color.HSVToRGB(hue, sat, val);\n        }\n\n        internal static void RenderMeshPreviewSkipCameraAndLighting(\n            Mesh mesh,\n            Bounds bounds,\n            PreviewRenderUtility previewUtility,\n            Settings settings,\n            MaterialPropertyBlock customProperties,\n            int meshSubset // -1 for whole mesh\n            ) \n        {\n            if (mesh == null || previewUtility == null)\n                return;\n\n            Quaternion rot = Quaternion.Euler(settings.previewDir.y, 0, 0) * Quaternion.Euler(0, settings.previewDir.x, 0);\n            Vector3 pos = rot * (-bounds.center);\n\n            bool oldFog = RenderSettings.fog;\n            Unsupported.SetRenderSettingsUseFogNoDirty(false);\n\n            int submeshes = mesh.subMeshCount;\n            var tintSubmeshes = false;\n            var colorPropID = 0;\n            if (submeshes > 1 && settings.displayMode == DisplayMode.Shaded && customProperties == null && meshSubset == -1)\n            {\n                tintSubmeshes = true;\n                customProperties = new MaterialPropertyBlock();\n                colorPropID = Shader.PropertyToID(\"_Color\");\n            }\n\n            var activeLod = Mathf.Clamp(settings.activeLod, 0, mesh.lodCount - 1);\n\n            if (settings.activeMaterial != null)\n            {\n                var transformation = Matrix4x4.TRS(pos, rot, Vector3.one);\n\n                previewUtility.camera.clearFlags = CameraClearFlags.Nothing;\n                if (meshSubset < 0 || meshSubset >= submeshes)\n                {\n                    for (int i = 0; i < submeshes; ++i)\n                    {\n                        if (tintSubmeshes)\n                            customProperties.SetColor(colorPropID, GetSubMeshTint(i));\n\n                        previewUtility.RenderMesh(mesh, transformation, settings.activeMaterial, i, customProperties, activeLod);\n                    }\n                }\n                else\n                {\n                    previewUtility.RenderMesh(mesh, transformation, settings.activeMaterial, meshSubset, customProperties, activeLod);\n                }\n\n                previewUtility.Render();\n            }\n\n            if (settings.wireMaterial != null && settings.drawWire)\n            {\n                previewUtility.camera.clearFlags = CameraClearFlags.Nothing;\n                GL.wireframe = true;\n\n                if (tintSubmeshes)\n                    customProperties.SetColor(colorPropID, settings.wireMaterial.color);\n\n                var transformation = Matrix4x4.TRS(pos, rot, Vector3.one);\n\n                if (meshSubset < 0 || meshSubset >= submeshes)\n                {\n                    for (int i = 0; i < submeshes; ++i)\n                    {\n                        // lines/points already are wire-like; it does not make sense to overdraw\n                        // them again with dark wireframe color\n                        var topology = mesh.GetTopology(i);\n                        if (topology == MeshTopology.Lines || topology == MeshTopology.LineStrip || topology == MeshTopology.Points)\n                            continue;\n\n                        previewUtility.RenderMesh(mesh, transformation, settings.wireMaterial, i, customProperties, activeLod);\n                    }\n                }\n                else\n                {\n                    previewUtility.RenderMesh(mesh, transformation, settings.wireMaterial, meshSubset, customProperties, activeLod);\n                }\n\n                previewUtility.Render();\n\n                GL.wireframe = false;\n            }\n\n            Unsupported.SetRenderSettingsUseFogNoDirty(oldFog);\n        }\n\n        static void SetTransformMatrix(Transform tr, Matrix4x4 mat)\n        {\n            // extract position\n            var pos = new Vector3(mat.m03, mat.m13, mat.m23);\n\n            // extract scale\n            var scale = mat.lossyScale;\n\n            // now remove scale from the matrix axes,\n            var invScale = new Vector3(1.0f / scale.x, 1.0f / scale.y, 1.0f / scale.z);\n            mat.m00 *= invScale.x; mat.m10 *= invScale.x; mat.m20 *= invScale.x;\n            mat.m01 *= invScale.y; mat.m11 *= invScale.y; mat.m21 *= invScale.y;\n            mat.m02 *= invScale.z; mat.m12 *= invScale.z; mat.m22 *= invScale.z;\n\n            // and extract rotation\n            var rot = mat.rotation;\n            tr.localPosition = pos;\n            tr.localRotation = rot;\n            tr.localScale = scale;\n        }\n\n        void BakeSkinnedMesh()\n        {\n            if (mesh == null)\n                return;\n\n            var baseGameObjectForSkinnedMeshRenderer = new GameObject { hideFlags = HideFlags.HideAndDontSave };\n            SkinnedMeshRenderer skinnedMeshRenderer = baseGameObjectForSkinnedMeshRenderer.AddComponent<SkinnedMeshRenderer>();\n            skinnedMeshRenderer.hideFlags = HideFlags.HideAndDontSave;\n\n            m_BakedSkinnedMesh = new Mesh() { hideFlags = HideFlags.HideAndDontSave };\n\n            var isRigid = mesh.blendShapeCount > 0 && mesh.bindposes.Length == 0;\n\n            Transform[] boneTransforms = new Transform[mesh.bindposes.Length];\n\n            if (!isRigid)\n            {\n                for (int i = 0; i < boneTransforms.Length; i++)\n                {\n                    var bindPoseInverse = mesh.bindposes[i].inverse;\n                    boneTransforms[i] = new GameObject().transform;\n                    boneTransforms[i].gameObject.hideFlags = HideFlags.HideAndDontSave;\n                    SetTransformMatrix(boneTransforms[i], bindPoseInverse);\n                }\n\n                skinnedMeshRenderer.bones = boneTransforms;\n            }\n\n            skinnedMeshRenderer.sharedMesh = mesh;\n            skinnedMeshRenderer.SetBlendShapeWeight(m_Settings.activeBlendshape, 100f);\n            skinnedMeshRenderer.BakeMesh(m_BakedSkinnedMesh);\n\n            if (isRigid)\n                m_BakedSkinnedMesh.RecalculateBounds();\n\n            skinnedMeshRenderer.sharedMesh = null;\n\n            UObject.DestroyImmediate(skinnedMeshRenderer);\n            UObject.DestroyImmediate(baseGameObjectForSkinnedMeshRenderer);\n\n            if (!isRigid)\n            {\n                for (int i = 0; i < boneTransforms.Length; i++)\n                    UObject.DestroyImmediate(boneTransforms[i].gameObject);\n            }\n        }\n\n        public Texture2D RenderStaticPreview(int width, int height)\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture)\n                return null;\n            m_PreviewUtility.BeginStaticPreview(new Rect(0, 0, width, height));\n            DoRenderPreview();\n            return m_PreviewUtility.EndStaticPreview();\n        }\n\n        void DoRenderPreview()\n        {\n            if (m_Settings.displayMode == DisplayMode.Blendshapes)\n                RenderMeshPreview(m_BakedSkinnedMesh, m_PreviewUtility, m_Settings, -1);\n            else\n                RenderMeshPreview(mesh, m_PreviewUtility, m_Settings, -1);\n        }\n\n        public void OnPreviewGUI(Rect rect, GUIStyle background)\n        {\n            var evt = Event.current;\n\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture)\n            {\n                if (evt.type == EventType.Repaint)\n                    EditorGUI.DropShadowLabel(new Rect(rect.x, rect.y, rect.width, 40),\n                        \"Mesh preview requires\\nrender texture support\");\n                return;\n            }\n\n            if ((evt.type == EventType.ValidateCommand || evt.type == EventType.ExecuteCommand) && evt.commandName == EventCommandNames.FrameSelected)\n            {\n                FrameObject();\n                evt.Use();\n            }\n\n            if (evt.button <= 0 && m_Settings.displayMode != DisplayMode.UVLayout)\n                m_Settings.previewDir = PreviewGUI.Drag2D(m_Settings.previewDir, rect);\n\n            if (evt.button == 1 && m_Settings.displayMode != DisplayMode.UVLayout)\n                m_Settings.lightDir = PreviewGUI.Drag2D(m_Settings.lightDir, rect);\n\n            if (evt.type == EventType.ScrollWheel)\n                MeshPreviewZoom(rect, evt);\n\n            if (evt.type == EventType.MouseDrag && (m_Settings.displayMode == DisplayMode.UVLayout || evt.button == 2))\n                MeshPreviewPan(rect, evt);\n\n            if (evt.type != EventType.Repaint)\n                return;\n\n            m_PreviewUtility.BeginPreview(rect, background);\n\n            DoRenderPreview();\n\n            m_PreviewUtility.EndAndDrawPreview(rect);\n        }\n\n        int DrawLodSelectionControls(int value, int min, int max)\n        {\n            var labelWidth = EditorStyles.label.CalcSize(Styles.meshLodIcon).x + 2;\n            var sliderWidth = 60f;\n            var fieldWidth = 30f;\n\n            var controlRect = EditorGUILayout.GetControlRect(GUILayout.Width(labelWidth + sliderWidth + fieldWidth));\n            var controlId = GUIUtility.GetControlID(FocusType.Keyboard);\n\n            var labelRect = new Rect(controlRect.position, new Vector2(labelWidth, controlRect.height));\n            controlRect.x += labelRect.width;\n            controlRect.width -= labelRect.width + 2;\n            GUI.Label(labelRect, Styles.meshLodIcon);\n\n            var sliderRect = new Rect(controlRect.position, new Vector2(sliderWidth, controlRect.height));\n            controlRect.x += sliderRect.width + 2;\n            controlRect.width -= sliderRect.width;\n            value = (int)GUI.Slider(sliderRect, value, 0, min, max, GUI.skin.horizontalSlider, GUI.skin.horizontalSliderThumb, true, 0);\n\n            value = EditorGUI.DoIntField(EditorGUI.s_RecycledEditor, controlRect, labelRect, controlId, value, EditorGUI.kIntFieldFormatString, EditorStyles.numberField, false, 0);\n\n            return Mathf.Clamp(value, min, max);\n        }\n\n        public void OnPreviewSettings()\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture)\n                return;\n\n            GUI.enabled = true;\n\n            if(mesh.isLodSelectionActive)\n            {\n                // Hide the LOD slider when in UVLayout mode\n                // As this mode uses Graphics.DrawMeshNow - this does not support LODs\n                if (m_Settings.displayMode != DisplayMode.UVLayout)\n                {\n                    m_Settings.activeLod = DrawLodSelectionControls(m_Settings.activeLod, 0, mesh.lodCount - 1);\n                }\n            }\n\n            if (m_Settings.displayMode == DisplayMode.UVChecker)\n            {\n                int oldVal = m_Settings.checkerTextureMultiplier;\n\n                float sliderWidth = EditorStyles.label.CalcSize(new GUIContent(\"--------\")).x;\n                Rect sliderRect = EditorGUILayout.GetControlRect(GUILayout.Width(sliderWidth));\n                sliderRect.x += 3;\n\n                m_Settings.checkerTextureMultiplier = (int)GUI.HorizontalSlider(sliderRect, m_Settings.checkerTextureMultiplier, 30, 1, Styles.preSlider, Styles.preSliderThumb);\n                if (oldVal != m_Settings.checkerTextureMultiplier)\n                    m_Settings.activeMaterial.mainTextureScale = new Vector2(m_Settings.checkerTextureMultiplier, m_Settings.checkerTextureMultiplier);\n            }\n\n            if (m_Settings.displayMode == DisplayMode.UVLayout || m_Settings.displayMode == DisplayMode.UVChecker)\n            {\n                float channelDropDownWidth = EditorStyles.toolbarDropDown.CalcSize(new GUIContent(\"Channel 6\")).x;\n                Rect channelDropdownRect = EditorGUILayout.GetControlRect(GUILayout.Width(channelDropDownWidth));\n                channelDropdownRect.y -= 1;\n                channelDropdownRect.x += 5;\n                GUIContent channel = new GUIContent(\"Channel \" + m_Settings.activeUVChannel, Styles.uvChannelDropdown.tooltip);\n\n                if (EditorGUI.DropdownButton(channelDropdownRect, channel, FocusType.Passive, EditorStyles.toolbarDropDown))\n                    DoPopup(channelDropdownRect, m_UVChannels,\n                        m_Settings.activeUVChannel, SetUVChannel, m_Settings.availableUVChannels);\n            }\n\n            if (m_Settings.displayMode == DisplayMode.Blendshapes)\n            {\n                float blendshapesDropDownWidth = EditorStyles.toolbarDropDown.CalcSize(new GUIContent(\"Blendshapes\")).x;\n                Rect blendshapesDropdownRect = EditorGUILayout.GetControlRect(GUILayout.Width(blendshapesDropDownWidth));\n                blendshapesDropdownRect.y -= 1;\n                blendshapesDropdownRect.x += 5;\n                GUIContent blendshape = new GUIContent(m_BlendShapes[m_Settings.activeBlendshape], Styles.uvChannelDropdown.tooltip);\n\n                if (EditorGUI.DropdownButton(blendshapesDropdownRect, blendshape, FocusType.Passive, EditorStyles.toolbarDropDown))\n                    DoPopup(blendshapesDropdownRect, m_BlendShapes.ToArray(),\n                        m_Settings.activeBlendshape, SetBlendshape, null);\n            }\n\n            GUIContent displayModeDropdownContent = m_Settings.displayMode switch\n            {\n                DisplayMode.Shaded => Styles.shadedIcon,\n                DisplayMode.UVChecker => Styles.uvIcon,\n                DisplayMode.UVLayout => Styles.uvIcon,\n                _ => new GUIContent(m_DisplayModes[(int)m_Settings.displayMode], Styles.displayModeDropdown.tooltip)\n            };\n\n            float displayModeDropDownWidth = EditorStyles.toolbarDropDown.CalcSize(displayModeDropdownContent).x;\n\n            Rect displayModeDropdownRect = EditorGUILayout.GetControlRect(GUILayout.Width(displayModeDropDownWidth));\n            displayModeDropdownRect.y -= 1;\n            displayModeDropdownRect.x += 2;\n\n            if (EditorGUI.DropdownButton(displayModeDropdownRect, displayModeDropdownContent, FocusType.Passive, EditorStyles.toolbarDropDown))\n                DoPopup(displayModeDropdownRect, m_DisplayModes, (int)m_Settings.displayMode, SetDisplayMode, m_Settings.availableDisplayModes);\n\n            using (new EditorGUI.DisabledScope(m_Settings.displayMode == DisplayMode.UVLayout))\n            {\n                m_Settings.drawWire = GUILayout.Toggle(m_Settings.drawWire, Styles.wireframeToggle, EditorStyles.toolbarButton);\n            }\n        }\n\n        void OnDropDownAction(Material mat, int mode, bool flatUVs)\n        {\n            ResetView();\n\n            m_Settings.activeMaterial = mat;\n\n            m_Settings.activeMaterial.SetFloat(\"_Mode\", (float)mode);\n            m_Settings.activeMaterial.SetFloat(\"_UVChannel\", 0.0f);\n            m_Settings.activeMaterial.SetFloat(\"_Cull\", flatUVs ? (float)CullMode.Off : (float)CullMode.Back);\n        }\n\n        void MeshPreviewZoom(Rect rect, Event evt)\n        {\n            float zoomDelta = -(HandleUtility.niceMouseDeltaZoom * 0.5f) * 0.05f;\n            var newZoom = m_Settings.zoomFactor + m_Settings.zoomFactor * zoomDelta;\n            newZoom = Mathf.Clamp(newZoom, 0.1f, 10.0f);\n\n            // we want to zoom around current mouse position\n            var mouseViewPos = new Vector2(\n                evt.mousePosition.x / rect.width,\n                1 - evt.mousePosition.y / rect.height);\n            var mouseWorldPos = m_PreviewUtility.camera.ViewportToWorldPoint(mouseViewPos);\n            var mouseToCamPos = m_Settings.orthoPosition - mouseWorldPos;\n            var newCamPos = mouseWorldPos + mouseToCamPos * (newZoom / m_Settings.zoomFactor);\n\n            if (m_Settings.displayMode != DisplayMode.UVLayout)\n            {\n                m_PreviewUtility.camera.transform.position = new Vector3(newCamPos.x, newCamPos.y, newCamPos.z);\n            }\n            else\n            {\n                m_Settings.orthoPosition = new Vector3(newCamPos.x,  newCamPos.y, m_Settings.orthoPosition.z);\n            }\n\n            m_Settings.zoomFactor = newZoom;\n            evt.Use();\n        }\n\n        void MeshPreviewPan(Rect rect, Event evt)\n        {\n            var cam = m_PreviewUtility.camera;\n\n            // event delta is in \"screen\" units of the preview rect, but the\n            // preview camera is rendering into a render target that could\n            // be different size; have to adjust drag position to match\n            var delta = new Vector3(\n                -evt.delta.x * cam.pixelWidth / rect.width,\n                evt.delta.y * cam.pixelHeight / rect.height,\n                0);\n\n            Vector3 screenPos;\n            Vector3 worldPos;\n            if (m_Settings.displayMode == DisplayMode.UVLayout)\n            {\n                screenPos = cam.WorldToScreenPoint(m_Settings.orthoPosition);\n                screenPos += delta;\n                worldPos = cam.ScreenToWorldPoint(screenPos);\n\n                m_Settings.orthoPosition = new Vector3(worldPos.x,  worldPos.y, m_Settings.orthoPosition.z);\n            }\n            else\n            {\n                screenPos = cam.WorldToScreenPoint(m_Settings.pivotPositionOffset);\n                screenPos += delta;\n                worldPos = cam.ScreenToWorldPoint(screenPos) - m_Settings.pivotPositionOffset;\n                m_Settings.pivotPositionOffset += worldPos;\n            }\n\n            evt.Use();\n        }\n\n        public static string GetInfoString(Mesh mesh)\n        {\n            if (mesh == null)\n                return \"\";\n\n            string info = $\"{mesh.vertexCount} Vertices, {InternalMeshUtil.GetPrimitiveCount(mesh)} Triangles\";\n\n            int submeshes = mesh.subMeshCount;\n            if (submeshes > 1)\n                info += $\", {submeshes} Sub Meshes\";\n\n            int blendShapeCount = mesh.blendShapeCount;\n            if (blendShapeCount > 0)\n                info += $\", {blendShapeCount} Blend Shapes\";\n\n            if (mesh.isLodSelectionActive)\n                info += $\", {mesh.lodCount} LODs\";\n\n            info += \" | \" + InternalMeshUtil.GetVertexFormat(mesh);\n            return info;\n        }\n\n        internal string GetInfoString()\n        {\n            if(mesh == null)\n                return \"\";\n\n            if (!mesh.isLodSelectionActive)\n            {\n                return GetInfoString(mesh);\n            }\n            else\n            {\n                var selectLod = Mathf.Clamp(m_Settings.activeLod, 0, mesh.lodCount);\n                var info = $\"Mesh LOD {selectLod} - {mesh.vertexCount} Vertices, {GetPrimitiveCount(selectLod)} Triangles\";\n\n                int submeshes = mesh.subMeshCount;\n                if (submeshes > 1)\n                    info += $\", {submeshes} Sub Meshes\";\n\n                int blendShapeCount = mesh.blendShapeCount;\n                if (blendShapeCount > 0)\n                    info += $\", {blendShapeCount} Blend Shapes\";\n\n                info += \" | \" + InternalMeshUtil.GetVertexFormat(mesh);\n                return info;\n            }\n\n            uint GetPrimitiveCount(int lod)\n            {\n                uint count = 0;\n\n                for (int i = 0; i < mesh.subMeshCount; i++)\n                {\n                    var range = mesh.GetLod(i, lod);\n\n                    // Assume triangle topology for now\n                    count += range.indexCount / 3;\n                }\n\n                return count;\n            }\n        }        \n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/MeshRendererEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Linq;\nusing UnityEngine.Rendering;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(MeshRenderer))]\n    [CanEditMultipleObjects]\n    internal class MeshRendererEditor : RendererEditorBase\n    {\n        class Styles\n        {\n            public static readonly GUIContent materialWarning = EditorGUIUtility.TrTextContent(\"This renderer has more materials than the Mesh has submeshes. Multiple materials will be applied to the same submesh, which costs performance. Consider using multiple shader passes.\");\n            public static readonly GUIContent staticBatchingWarning = EditorGUIUtility.TrTextContent(\"This Renderer uses static batching and instanced Shaders. When the Player is active, instancing is disabled. If you want instanced Shaders at run time, disable static batching.\");\n        }\n\n        private SerializedObject m_GameObjectsSerializedObject;\n        private SerializedProperty m_GameObjectStaticFlags;\n\n        public override void OnEnable()\n        {\n            // Since we are not doing anything if we are not displayed in the inspector, early out. This help keeps multi selection snappier.\n            if (hideInspector)\n                return;\n\n            base.OnEnable();\n\n            m_GameObjectsSerializedObject = new SerializedObject(targets.Select(t => ((MeshRenderer)t).gameObject).ToArray());\n            m_GameObjectStaticFlags = m_GameObjectsSerializedObject.FindProperty(\"m_StaticEditorFlags\");\n\n            Lightmapping.lightingDataUpdated += LightingDataUpdatedRepaint;\n        }\n\n        public void OnDisable()\n        {\n            Lightmapping.lightingDataUpdated -= LightingDataUpdatedRepaint;\n        }\n\n        private void LightingDataUpdatedRepaint()\n        {\n            if (m_Lighting.showLightmapSettings)\n            {\n                Repaint();\n            }\n        }\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            // Evaluate displayMaterialWarning before drawing properties to avoid mismatched layout group\n            bool displayMaterialWarning = false;\n\n            MeshFilter mf = ((MeshRenderer)serializedObject.targetObject).GetComponent<MeshFilter>();\n            if (!m_Materials.hasMultipleDifferentValues)\n            {\n                displayMaterialWarning = mf != null && mf.sharedMesh != null && m_Materials.arraySize > mf.sharedMesh.subMeshCount;\n            }\n\n            // Disable Materials menu for the legacy Tree objects, see Fogbugz case: 1283092\n            Tree treeComponent = ((MeshRenderer)serializedObject.targetObject).GetComponent<Tree>();\n            bool hasTreeComponent = treeComponent != null;\n            bool isSpeedTree = hasTreeComponent && treeComponent.data == null; // SpeedTrees always have the Tree component, but have null 'data' property\n            using (new EditorGUI.DisabledScope(hasTreeComponent && !isSpeedTree))\n            {\n                DrawMaterials();\n            }\n\n            if (!m_Materials.hasMultipleDifferentValues && displayMaterialWarning)\n            {\n                EditorGUILayout.HelpBox(Styles.materialWarning.text, MessageType.Warning, true);\n            }\n\n            if (ShaderUtil.MaterialsUseInstancingShader(m_Materials))\n            {\n                m_GameObjectsSerializedObject.Update();\n\n                int staticBatching, dynamicBatching;\n                PlayerSettings.GetBatchingForPlatform(EditorUserBuildSettings.activeBuildTarget, out staticBatching, out dynamicBatching);\n\n                if (!m_GameObjectStaticFlags.hasMultipleDifferentValues && ((StaticEditorFlags)m_GameObjectStaticFlags.intValue & StaticEditorFlags.BatchingStatic) != 0 && staticBatching != 0)\n                {\n                    EditorGUILayout.HelpBox(Styles.staticBatchingWarning.text, MessageType.Warning, true);\n                }\n            }\n\n            if (mf != null && mf.sharedMesh != null)\n                LightingSettingsGUI(true, mf.sharedMesh.isLodSelectionActive, mf.sharedMesh.lodCount);\n            else\n                LightingSettingsGUI(true);\n\n            RayTracingSettingsGUI();\n\n            if (mf != null && mf.sharedMesh != null)\n            {\n                if (mf.sharedMesh.isLodSelectionActive)\n                {\n                    MeshLodSettingsGUI(mf.sharedMesh.lodCount);\n                }\n            }\n\n            OtherSettingsGUI(true, false, false);\n\n            if (targets.Length == 1)\n                SpeedTreeMaterialFixer.DoFixerUI((target as MeshRenderer).gameObject);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/MinMaxCurvePropertyDrawer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEngine.UIElements;\nusing UnityEditor.UIElements;\n\nnamespace UnityEditorInternal\n{\n    [CustomPropertyDrawer(typeof(ParticleSystem.MinMaxCurve))]\n    public class MinMaxCurvePropertyDrawer : PropertyDrawer\n    {\n        class PropertyData\n        {\n            public SerializedProperty mode;\n            public SerializedProperty constantMin;\n            public SerializedProperty constantMax;\n            public SerializedProperty curveMultiplier;\n            public SerializedProperty curveMin;\n            public SerializedProperty curveMax;\n        }\n\n        internal bool isNativeProperty { get; set; }\n        internal string xAxisLabel { get; set; } = \"time\";\n\n        // Its possible that the PropertyDrawer may be used to draw more than one MinMaxCurve property(arrays, lists)\n        Dictionary<string, PropertyData> m_PropertyDataPerPropertyPath = new Dictionary<string, PropertyData>();\n        PropertyData m_Property;\n\n        class Styles\n        {\n            public readonly float floatFieldDragWidth = 20;\n            public readonly float stateButtonWidth = 18;\n            public readonly Color curveColor = Color.green;\n            public readonly Color curveBackgroundColor = new Color(0.337f, 0.337f, 0.337f, 1f);\n            public readonly AnimationCurve defaultCurve = new AnimationCurve(new Keyframe(0, 1), new Keyframe(1, 1)) { postWrapMode = WrapMode.ClampForever, preWrapMode = WrapMode.ClampForever };\n            public readonly GUIContent[] modes = new[]\n            {\n                EditorGUIUtility.TrTextContent(\"Constant\"),\n                EditorGUIUtility.TrTextContent(\"Curve\"),\n                EditorGUIUtility.TrTextContent(\"Random Between Two Curves\"),\n                EditorGUIUtility.TrTextContent(\"Random Between Two Constants\")\n            };\n        }\n        static Styles s_Styles;\n\n        static int s_CurveId;\n\n        void Init(SerializedProperty property)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            if (m_PropertyDataPerPropertyPath.TryGetValue(property.propertyPath, out m_Property))\n                return;\n\n            m_Property = new PropertyData()\n            {\n                mode = property.FindPropertyRelative(isNativeProperty ? \"minMaxState\" : \"m_Mode\"),\n                constantMax = property.FindPropertyRelative(isNativeProperty ? \"scalar\" : \"m_ConstantMax\"),\n                constantMin = property.FindPropertyRelative(isNativeProperty ? \"minScalar\" : \"m_ConstantMin\"),\n                curveMin = property.FindPropertyRelative(isNativeProperty ? \"minCurve\" : \"m_CurveMin\"),\n                curveMax = property.FindPropertyRelative(isNativeProperty ? \"maxCurve\" : \"m_CurveMax\"),\n\n                // In native we use the same value for multiplier and max scalar.\n                curveMultiplier = property.FindPropertyRelative(isNativeProperty ? \"scalar\" : \"m_CurveMultiplier\")\n            };\n\n            m_PropertyDataPerPropertyPath.Add(property.propertyPath, m_Property);\n            InitCurves();\n        }\n\n        // Ensure curves are not empty if they are in use.\n        void InitCurves()\n        {\n            var state = (MinMaxCurveState)m_Property.mode.intValue;\n            if ((state == MinMaxCurveState.k_Curve || state == MinMaxCurveState.k_TwoCurves) && m_Property.curveMax.animationCurveValue.keys.Length == 0)\n            {\n                if (Mathf.Approximately(m_Property.curveMultiplier.floatValue, 0))\n                    m_Property.curveMultiplier.floatValue = 1;\n                m_Property.curveMax.animationCurveValue = s_Styles.defaultCurve;\n            }\n            if (state == MinMaxCurveState.k_TwoCurves && m_Property.curveMin.animationCurveValue.keys.Length == 0)\n                m_Property.curveMin.animationCurveValue = s_Styles.defaultCurve;\n        }\n\n        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n        {\n            Init(property);\n\n            Rect fieldRect;\n            var mode = (MinMaxCurveState)m_Property.mode.intValue;\n\n            // Only curves require manually drawing a label, the controls for scalar handle the label drawing themselves.\n            if (!m_Property.mode.hasMultipleDifferentValues && (mode == MinMaxCurveState.k_Scalar || mode == MinMaxCurveState.k_TwoScalars))\n                fieldRect = position;\n            else\n                fieldRect = EditorGUI.PrefixLabel(position, label);\n\n            // Mode\n            fieldRect.width -= s_Styles.stateButtonWidth;\n            var modeRect = new Rect(fieldRect.xMax, fieldRect.y, s_Styles.stateButtonWidth, fieldRect.height);\n            EditorGUI.BeginProperty(modeRect, GUIContent.none, m_Property.mode);\n            EditorGUI.BeginChangeCheck();\n            int newSelection = EditorGUI.Popup(modeRect, null, m_Property.mode.intValue, s_Styles.modes, EditorStyles.minMaxStateDropdown);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_Property.mode.intValue = newSelection;\n                InitCurves();\n                AnimationCurvePreviewCache.ClearCache();\n            }\n            EditorGUI.EndProperty();\n\n            if (m_Property.mode.hasMultipleDifferentValues)\n            {\n                EditorGUI.LabelField(fieldRect, GUIContent.Temp(\"-\"));\n                return;\n            }\n\n            switch (mode)\n            {\n                case MinMaxCurveState.k_Scalar:\n                    EditorGUI.PropertyField(fieldRect, m_Property.constantMax, label);\n                    break;\n\n                case MinMaxCurveState.k_Curve:\n                    DoMinMaxCurvesField(fieldRect, m_Property.curveMax.GetHashCode(), m_Property.curveMax, null, m_Property.curveMultiplier, s_Styles.curveColor, s_Styles.curveBackgroundColor, xAxisLabel);\n                    break;\n\n                case MinMaxCurveState.k_TwoCurves:\n                    DoMinMaxCurvesField(fieldRect, m_Property.curveMin.GetHashCode(), m_Property.curveMax, m_Property.curveMin, m_Property.curveMultiplier, s_Styles.curveColor, s_Styles.curveBackgroundColor, xAxisLabel);\n                    break;\n\n                case MinMaxCurveState.k_TwoScalars:\n                    float fieldWidth = (fieldRect.width - EditorGUIUtility.labelWidth) * 0.5f;\n                    var rectMin = new Rect(fieldRect.x, fieldRect.y, fieldRect.width - fieldWidth - (s_Styles.floatFieldDragWidth * 0.5f), fieldRect.height);\n                    EditorGUI.PropertyField(rectMin, m_Property.constantMin, label);\n                    var rectMax = new Rect(rectMin.xMax + s_Styles.floatFieldDragWidth, fieldRect.y, fieldWidth - (s_Styles.floatFieldDragWidth * 0.5f), fieldRect.height);\n                    var rectMaxDragArea = new Rect(rectMax.xMin - s_Styles.floatFieldDragWidth, fieldRect.y, s_Styles.floatFieldDragWidth, fieldRect.height);\n                    EditorGUI.BeginProperty(rectMax, GUIContent.none, m_Property.constantMax);\n                    EditorGUI.BeginChangeCheck();\n                    float newConstantMax = EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor, rectMax, rectMaxDragArea, m_Property.constantMax.GetHashCode(), m_Property.constantMax.floatValue, \"g7\", EditorStyles.numberField, true);\n                    if (EditorGUI.EndChangeCheck())\n                        m_Property.constantMax.floatValue = newConstantMax;\n                    EditorGUI.EndProperty();\n                    break;\n            }\n        }\n\n        static void DoMinMaxCurvesField(Rect position, int id, SerializedProperty propertyMax, SerializedProperty propertyMin, SerializedProperty scalar, Color color, Color backgroundColor, string xLabel)\n        {\n            var evt = Event.current;\n\n            if (MinMaxCurveEditorWindow.visible && Event.current.type != EventType.Layout && GUIUtility.keyboardControl == id)\n            {\n                if (s_CurveId != id)\n                {\n                    s_CurveId = id;\n                    if (MinMaxCurveEditorWindow.visible)\n                    {\n                        MinMaxCurveEditorWindow.xAxisLabel = xLabel;\n                        MinMaxCurveEditorWindow.SetCurves(propertyMax, propertyMin, scalar, color);\n                        MinMaxCurveEditorWindow.ShowPopup(GUIView.current);\n                    }\n                }\n                else\n                {\n                    if (MinMaxCurveEditorWindow.visible && Event.current.type == EventType.Repaint)\n                    {\n                        MinMaxCurveEditorWindow.xAxisLabel = xLabel;\n                        MinMaxCurveEditorWindow.SetCurves(propertyMax, propertyMin, scalar, color);\n                        MinMaxCurveEditorWindow.instance.Repaint();\n                    }\n                }\n            }\n\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (position.Contains(evt.mousePosition))\n                    {\n                        s_CurveId = id;\n                        GUIUtility.keyboardControl = id;\n                        MinMaxCurveEditorWindow.xAxisLabel = xLabel;\n                        MinMaxCurveEditorWindow.SetCurves(propertyMax, propertyMin, scalar, color);\n                        MinMaxCurveEditorWindow.ShowPopup(GUIView.current);\n                        evt.Use();\n                        GUIUtility.ExitGUI();\n                    }\n                    break;\n\n                case EventType.Repaint:\n                    if (propertyMin != null)\n                        EditorGUIUtility.DrawRegionSwatch(position, propertyMax, propertyMin, color, backgroundColor);\n                    else\n                        EditorGUIUtility.DrawCurveSwatch(position, null, propertyMax, color, backgroundColor);\n                    EditorStyles.colorPickerBox.Draw(position, GUIContent.none, id, false);\n                    break;\n\n                case EventType.ExecuteCommand:\n\n                    if (s_CurveId == id && evt.commandName == \"CurveChanged\")\n                    {\n                        GUI.changed = true;\n                        AnimationCurvePreviewCache.ClearCache();\n                        HandleUtility.Repaint();\n                        if (propertyMax != null && MinMaxCurveEditorWindow.instance.maxCurve != null)\n                        {\n                            propertyMax.animationCurveValue = MinMaxCurveEditorWindow.instance.maxCurve;\n                        }\n                        if (propertyMin != null)\n                        {\n                            propertyMin.animationCurveValue = MinMaxCurveEditorWindow.instance.minCurve;\n                        }\n                    }\n                    break;\n\n                case EventType.KeyDown:\n                    if (evt.MainActionKeyForControl(id))\n                    {\n                        s_CurveId = id;\n                        MinMaxCurveEditorWindow.xAxisLabel = xLabel;\n                        MinMaxCurveEditorWindow.SetCurves(propertyMax, propertyMin, scalar, color);\n                        MinMaxCurveEditorWindow.ShowPopup(GUIView.current);\n                        evt.Use();\n                        GUIUtility.ExitGUI();\n                    }\n                    break;\n            }\n        }\n\n        public override VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            const string StylesheetPath = \"StyleSheets/ParticleSystem/ParticleSystem.uss\";\n            const string AlignClass = \"unity-base-field__aligned\";\n            const string InputClass = \"unity-base-popup-field__input\";\n            const string RowClass = \"unity-particle-system-min-max-curve__row\";\n            const string GrowClass = \"unity-particle-system-min-max-curve__grow\";\n\n            PropertyField PrepareProperty(SerializedProperty prop, string label, VisualElement parent)\n            {\n                var propField = new PropertyField(prop, label);\n                propField.AddToClassList(UIElementsUtility.hiddenClassName);\n                propField.AddToClassList(GrowClass);\n                parent.Add(propField);\n                return propField;\n            }\n\n            Init(property);\n\n            var container = new VisualElement();\n            container.AddStyleSheetPath(StylesheetPath);\n            container.AddToClassList(RowClass);\n\n            var constantMin = PrepareProperty(m_Property.constantMin, property.name, container);\n            var constantMax = PrepareProperty(m_Property.constantMax, property.name, container);\n\n            var region = new IMGUIContainer(() =>\n            {\n                var label = new GUIContent(preferredLabel);\n                var rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);\n                EditorGUI.LabelField(rect, label);\n                rect = EditorGUI.PrefixLabel(rect, label);\n\n                EditorGUI.BeginChangeCheck();\n                if ((MinMaxCurveState)m_Property.mode.intValue == MinMaxCurveState.k_Curve)\n                    DoMinMaxCurvesField(rect, m_Property.curveMax.GetHashCode(), m_Property.curveMax, null, m_Property.curveMultiplier, s_Styles.curveColor, s_Styles.curveBackgroundColor, xAxisLabel);\n                else DoMinMaxCurvesField(rect, m_Property.curveMin.GetHashCode(), m_Property.curveMax, m_Property.curveMin, m_Property.curveMultiplier, s_Styles.curveColor, s_Styles.curveBackgroundColor, xAxisLabel);\n                if (EditorGUI.EndChangeCheck()) m_Property.curveMax.serializedObject.ApplyModifiedProperties();\n            });\n            region.AddToClassList(UIElementsUtility.hiddenClassName);\n            region.AddToClassList(GrowClass);\n            container.Add(region);\n\n            var mode = new PopupField<string>(s_Styles.modes.Select(m => m.text).ToList(), m_Property.mode.intValue);\n            container.Add(mode);\n\n            EventCallback<ChangeEvent<string>> valueChangeAction = (e) =>\n            {\n                MinMaxCurveState state = (MinMaxCurveState)s_Styles.modes.Select(m => m.text).ToList().IndexOf(e.newValue);\n                m_Property.mode.intValue = (int)state;\n                m_Property.mode.serializedObject.ApplyModifiedProperties();\n\n                constantMax.EnableInClassList(UIElementsUtility.hiddenClassName, state != MinMaxCurveState.k_Scalar && state != MinMaxCurveState.k_TwoScalars);\n\n                if(constantMax.Children().Count() > 0)\n                {\n                    constantMax.Children().First().EnableInClassList(AlignClass, state != MinMaxCurveState.k_TwoScalars);\n\n                    var label = constantMax.Query<Label>().Build().First();\n                    if (state == MinMaxCurveState.k_Scalar)\n                    {\n                        label.ResetPositionProperties();\n                        label.text = preferredLabel;\n                    }\n                    else\n                    {\n                        label.text = string.Empty;\n                        label.style.width = label.style.minWidth = s_Styles.floatFieldDragWidth;\n                    }\n                }\n\n                constantMin.EnableInClassList(UIElementsUtility.hiddenClassName, state != MinMaxCurveState.k_TwoScalars);\n                region.EnableInClassList(UIElementsUtility.hiddenClassName, state != MinMaxCurveState.k_Curve && state != MinMaxCurveState.k_TwoCurves);\n                AnimationCurvePreviewCache.ClearCache();\n            };\n            mode.RegisterValueChangedCallback(valueChangeAction);\n\n            container.RegisterCallback<AttachToPanelEvent>((e) =>\n            {\n                var popup = mode.Children().First();\n                popup.Remove(popup.Children().First());\n                popup.RemoveFromClassList(InputClass);\n\n                valueChangeAction.Invoke(ChangeEvent<string>.GetPooled(\"\", s_Styles.modes[m_Property.mode.intValue].text));\n            });\n\n            return container;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/MinMaxGradientPropertyDrawer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEngine.UIElements;\nusing UnityEditor.UIElements;\n\nnamespace UnityEditorInternal\n{\n    [CustomPropertyDrawer(typeof(ParticleSystem.MinMaxGradient))]\n    public class MinMaxGradientPropertyDrawer : PropertyDrawer\n    {\n        internal class PropertyData\n        {\n            public SerializedProperty mode;\n            public SerializedProperty gradientMin;\n            public SerializedProperty gradientMax;\n            public SerializedProperty colorMin;\n            public SerializedProperty colorMax;\n        }\n\n        // Its possible that the PropertyDrawer may be used to draw more than one MinMaxCurve property(arrays, lists)\n        Dictionary<string, PropertyData> m_PropertyDataPerPropertyPath = new Dictionary<string, PropertyData>();\n        PropertyData m_Property;\n\n        class Styles\n        {\n            public readonly float stateButtonWidth = 18;\n            public readonly GUIContent[] modes = new[]\n            {\n                EditorGUIUtility.TrTextContent(\"Color\"),\n                EditorGUIUtility.TrTextContent(\"Gradient\"),\n                EditorGUIUtility.TrTextContent(\"Random Between Two Colors\"),\n                EditorGUIUtility.TrTextContent(\"Random Between Two Gradients\"),\n                EditorGUIUtility.TrTextContent(\"Random Color\")\n            };\n        }\n        static Styles s_Styles;\n\n        void Init(SerializedProperty property)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            if (m_PropertyDataPerPropertyPath.TryGetValue(property.propertyPath, out m_Property))\n                return;\n\n            m_Property = new PropertyData()\n            {\n                mode = property.FindPropertyRelative(\"m_Mode\"),\n                gradientMin = property.FindPropertyRelative(\"m_GradientMin\"),\n                gradientMax = property.FindPropertyRelative(\"m_GradientMax\"),\n                colorMin = property.FindPropertyRelative(\"m_ColorMin\"),\n                colorMax = property.FindPropertyRelative(\"m_ColorMax\")\n            };\n            m_PropertyDataPerPropertyPath.Add(property.propertyPath, m_Property);\n        }\n\n        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)\n        {\n            Init(property);\n            return m_Property.mode.intValue == (int)MinMaxGradientState.k_RandomBetweenTwoGradients ? EditorGUI.kSingleLineHeight * 2.0f : EditorGUI.kSingleLineHeight;\n        }\n\n        static void DrawTwoPropertyFields(Rect rect, GUIContent label, SerializedProperty prop1, SerializedProperty prop2, bool singleLine)\n        {\n            rect = EditorGUI.PrefixLabel(rect, label);\n\n            var property1Rect = rect;\n            var property2Rect = rect;\n            if (singleLine)\n            {\n                float wideModeWidth = rect.width * 0.5f;\n                property1Rect.width = wideModeWidth;\n                property2Rect.x += wideModeWidth;\n                property2Rect.width = wideModeWidth;\n            }\n            else\n            {\n                property2Rect.y += EditorGUI.kSingleLineHeight;\n            }\n            EditorGUI.PropertyField(property1Rect, prop1, GUIContent.none);\n            EditorGUI.PropertyField(property2Rect, prop2, GUIContent.none);\n        }\n\n        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n        {\n            Init(property);\n\n            Rect fieldRect = position;\n            fieldRect.height = EditorGUI.kSingleLineHeight;\n            var mode = (MinMaxGradientState)m_Property.mode.intValue;\n\n            // Mode\n            fieldRect.xMax -= s_Styles.stateButtonWidth;\n            var modeRect = new Rect(fieldRect.xMax, fieldRect.y, s_Styles.stateButtonWidth, fieldRect.height);\n            EditorGUI.BeginProperty(modeRect, GUIContent.none, m_Property.mode);\n            EditorGUI.BeginChangeCheck();\n            int prevIndentLevel = EditorGUI.indentLevel;\n            EditorGUI.indentLevel = 0;\n            int newSelection = EditorGUI.Popup(modeRect, GUIContent.none, m_Property.mode.intValue, s_Styles.modes, EditorStyles.minMaxStateDropdown);\n            EditorGUI.indentLevel = prevIndentLevel;\n            if (EditorGUI.EndChangeCheck())\n                m_Property.mode.intValue = newSelection;\n            EditorGUI.EndProperty();\n\n            if (m_Property.mode.hasMultipleDifferentValues)\n            {\n                EditorGUI.LabelField(fieldRect, GUIContent.Temp(\"-\"));\n                return;\n            }\n\n            switch (mode)\n            {\n                case MinMaxGradientState.k_Color:\n                    EditorGUI.PropertyField(fieldRect, m_Property.colorMax, label);\n                    break;\n                case MinMaxGradientState.k_Gradient:\n                case MinMaxGradientState.k_RandomColor:\n                    EditorGUI.PropertyField(fieldRect, m_Property.gradientMax, label);\n                    break;\n                case MinMaxGradientState.k_RandomBetweenTwoColors:\n                    DrawTwoPropertyFields(fieldRect, label, m_Property.colorMin, m_Property.colorMax, true);\n                    break;\n                case MinMaxGradientState.k_RandomBetweenTwoGradients:\n                    DrawTwoPropertyFields(fieldRect, label, m_Property.gradientMin, m_Property.gradientMax, false);\n                    break;\n            }\n        }\n\n        public override VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            Init(property);\n\n            var field = new MinMaxGradientField(m_Property, preferredLabel);\n            PropertyField.ConfigureFieldStyles<MinMaxGradientField, ParticleSystem.MinMaxGradient>(field);\n            return field;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ModelInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(Mesh))]\n    [CanEditMultipleObjects]\n    class ModelInspector : Editor\n    {\n        Dictionary<Object, MeshPreview> m_MeshPreviews = new Dictionary<Object, MeshPreview>();\n        MeshPreview m_DirtyMeshPreview = null;\n\n        static Vector2 m_ScrollPos;\n\n        static readonly GUIContent s_LevelOfDetailLabel = new GUIContent(\"Level of Detail\", \"The number of Mesh LODs within each sub-mesh.\");\n\n        void OnEnable()\n        {\n            foreach (var previewTarget in targets)\n            {\n                var meshPreview = new MeshPreview(previewTarget as Mesh);\n                meshPreview.settingsChanged += OnPreviewSettingsChanged;\n                m_MeshPreviews.Add(previewTarget, meshPreview);\n            }\n        }\n\n        void OnDisable()\n        {\n            foreach (var previewTarget in targets)\n            {\n                var meshPreview = m_MeshPreviews[previewTarget];\n                meshPreview.settingsChanged -= OnPreviewSettingsChanged;\n                meshPreview.Dispose();\n            }\n\n            m_MeshPreviews.Clear();\n        }\n\n        public override void OnPreviewSettings()\n        {\n            if (m_MeshPreviews.TryGetValue(target, out var targetMeshPreview))\n                targetMeshPreview.OnPreviewSettings();\n\n            if (m_DirtyMeshPreview != null)\n            {\n                foreach (var meshPreview in m_MeshPreviews.Values)\n                {\n                    if (meshPreview != m_DirtyMeshPreview)\n                        meshPreview.CopySettings(m_DirtyMeshPreview);\n                }\n\n                m_DirtyMeshPreview = null;\n            }\n        }\n\n        void OnPreviewSettingsChanged(MeshPreview preview)\n        {\n            m_DirtyMeshPreview = preview;\n        }\n\n        public override Texture2D RenderStaticPreview(\n            string assetPath,\n            Object[] subAssets,\n            int width,\n            int height)\n        {\n            if (m_MeshPreviews.TryGetValue(target, out var meshPreview))\n                return meshPreview.RenderStaticPreview(width, height);\n\n            return null;\n        }\n\n        public override bool HasPreviewGUI()\n        {\n            return (target != null);\n        }\n\n        public override void OnInspectorGUI()\n        {\n            GUI.enabled = true;\n\n            // Multi-selection, just display total # of verts/indices and bail out\n            if (targets?.Length > 1)\n            {\n                long totalVertices = 0;\n                long totalIndices = 0;\n\n                foreach (var obj in targets)\n                {\n                    if (obj is Mesh m)\n                    {\n                        totalVertices += m.vertexCount;\n                        totalIndices += CalcTotalIndices(m);\n                    }\n                }\n\n                EditorGUILayout.LabelField($\"{targets.Length} meshes selected, {totalVertices} total vertices, {totalIndices} total indices\");\n                return;\n            }\n\n            if (!(target is Mesh mesh))\n                return;\n\n            var attributes = mesh.GetVertexAttributes();\n\n            ShowVertexInfo(mesh, attributes);\n            ShowIndexInfo(mesh);\n            ShowSkinInfo(mesh, attributes);\n            ShowBlendShapeInfo(mesh);\n            ShowOtherInfo(mesh);\n\n            GUI.enabled = false;\n        }\n\n        static void ShowOtherInfo(Mesh mesh)\n        {\n            EditorGUILayout.Space();\n            EditorGUILayout.LabelField(\"Other\", EditorStyles.boldLabel);\n            EditorGUI.indentLevel++;\n            EditorGUILayout.LabelField(\"Bounds Center\", mesh.bounds.center.ToString(\"g4\"));\n            EditorGUILayout.LabelField(\"Bounds Size\", mesh.bounds.size.ToString(\"g4\"));\n            EditorGUILayout.LabelField(\"Read/Write Enabled\", mesh.isReadable.ToString());\n            EditorGUILayout.LabelField(s_LevelOfDetailLabel, GUIContent.Temp(mesh.isLodSelectionActive? $\"{mesh.lodCount} levels\" : $\"{mesh.lodCount} level\"));\n            EditorGUI.indentLevel--;\n        }\n\n        static void ShowBlendShapeInfo(Mesh mesh)\n        {\n            var blendShapeCount = mesh.blendShapeCount;\n            if (blendShapeCount <= 0)\n                return;\n\n            EditorGUILayout.Space();\n            EditorGUILayout.LabelField($\"Blend Shapes: {blendShapeCount}\", EditorStyles.boldLabel);\n\n            var showScroll = blendShapeCount > 10;\n            if (showScroll)\n                m_ScrollPos = EditorGUILayout.BeginScrollView(m_ScrollPos, GUILayout.Height(10 * EditorGUIUtility.singleLineHeight));\n            EditorGUI.indentLevel++;\n            for (int i = 0; i < blendShapeCount; ++i)\n            {\n                EditorGUILayout.LabelField($\"#{i}: {mesh.GetBlendShapeName(i)} ({mesh.GetBlendShapeFrameCount(i)} frames)\");\n            }\n            EditorGUI.indentLevel--;\n            if (showScroll)\n                EditorGUILayout.EndScrollView();\n        }\n\n        static void ShowSkinInfo(Mesh mesh, VertexAttributeDescriptor[] attributes)\n        {\n            var boneCount = mesh.bindposes.Length;\n            if (boneCount <= 0)\n                return;\n\n            EditorGUILayout.Space();\n            EditorGUILayout.LabelField($\"Skin: {boneCount} bones\", EditorStyles.boldLabel);\n            EditorGUI.indentLevel++;\n            foreach (var a in attributes)\n            {\n                // only list skin related attributes\n                if (a.attribute == VertexAttribute.BlendIndices || a.attribute == VertexAttribute.BlendWeight)\n                    EditorGUILayout.LabelField(a.attribute.ToString(), GetAttributeString(a));\n            }\n            EditorGUI.indentLevel--;\n        }\n\n        static void ShowIndexInfo(Mesh mesh)\n        {\n            var indexCount = CalcTotalIndices(mesh);\n            var indexSize = mesh.indexFormat == IndexFormat.UInt16 ? 2 : 4;\n            var bufferSizeStr = EditorUtility.FormatBytes(indexCount * indexSize);\n\n            EditorGUILayout.Space();\n            EditorGUILayout.LabelField($\"Indices: {indexCount}, {mesh.indexFormat} format ({bufferSizeStr})\", EditorStyles.boldLabel);\n            EditorGUI.indentLevel++;\n\n            var subMeshCount = mesh.subMeshCount;\n            string subMeshText = subMeshCount == 1 ? \"submesh\" : \"submeshes\";\n            EditorGUILayout.LabelField($\"{mesh.subMeshCount} {subMeshText}:\");\n\n            for (int i = 0; i < mesh.subMeshCount; i++)\n            {\n                var subMesh = mesh.GetSubMesh(i);\n                string topology = subMesh.topology.ToString().ToLowerInvariant();\n                string baseVertex = subMesh.baseVertex == 0 ? \"\" : \", base vertex \" + subMesh.baseVertex;\n\n                var divisor = 3;\n                switch (subMesh.topology)\n                {\n                    case MeshTopology.Points: divisor = 1; break;\n                    case MeshTopology.Lines: divisor = 2; break;\n                    case MeshTopology.Triangles: divisor = 3; break;\n                    case MeshTopology.Quads: divisor = 4; break;\n                    case MeshTopology.LineStrip: divisor = 2; break; // technically not correct, but eh\n                }\n\n                var primCount = subMesh.indexCount / divisor;\n                if (subMeshCount > 1)\n                {\n                    GUILayout.BeginHorizontal();\n                    var rect = GUILayoutUtility.GetRect(GUIContent.none, GUI.skin.label, GUILayout.Width(7));\n                    rect.x += EditorGUI.indent;\n                    var tint = MeshPreview.GetSubMeshTint(i);\n                    DrawColorRect(rect, tint);\n                }\n\n                EditorGUILayout.LabelField($\"#{i}: {primCount} {topology} ({subMesh.indexCount} indices starting from {subMesh.indexStart}){baseVertex}\");\n                if (subMeshCount > 1)\n                {\n                    GUILayout.EndHorizontal();\n                }\n            }\n            EditorGUI.indentLevel--;\n        }\n\n        static void ShowVertexInfo(Mesh mesh, VertexAttributeDescriptor[] attributes)\n        {\n            var vertexSize = attributes.Sum(attr => ConvertFormatToSize(attr.format) * attr.dimension);\n            var bufferSizeStr = EditorUtility.FormatBytes((long)mesh.vertexCount * vertexSize);\n            EditorGUILayout.LabelField($\"Vertices: {mesh.vertexCount} ({bufferSizeStr})\", EditorStyles.boldLabel);\n\n            EditorGUI.indentLevel++;\n            foreach (var a in attributes)\n            {\n                // skin related attributes listed separately\n                if (a.attribute == VertexAttribute.BlendIndices || a.attribute == VertexAttribute.BlendWeight)\n                    continue;\n                var title = a.attribute.ToString();\n                if (title.Contains(\"TexCoord\"))\n                    title = title.Replace(\"TexCoord\", \"UV\");\n                EditorGUILayout.LabelField(title, GetAttributeString(a));\n            }\n            EditorGUI.indentLevel--;\n        }\n\n        static int ConvertFormatToSize(VertexAttributeFormat format)\n        {\n            switch (format)\n            {\n                case VertexAttributeFormat.Float32:\n                case VertexAttributeFormat.UInt32:\n                case VertexAttributeFormat.SInt32:\n                    return 4;\n                case VertexAttributeFormat.Float16:\n                case VertexAttributeFormat.UNorm16:\n                case VertexAttributeFormat.SNorm16:\n                case VertexAttributeFormat.UInt16:\n                case VertexAttributeFormat.SInt16:\n                    return 2;\n                case VertexAttributeFormat.UNorm8:\n                case VertexAttributeFormat.SNorm8:\n                case VertexAttributeFormat.UInt8:\n                case VertexAttributeFormat.SInt8:\n                    return 1;\n                default:\n                    throw new ArgumentOutOfRangeException(nameof(format), format, $\"Unknown vertex format {format}\");\n            }\n        }\n\n        static string GetAttributeString(VertexAttributeDescriptor attr)\n        {\n            var format = attr.format;\n            var dimension = attr.dimension;\n            var str = $\"{format} x {dimension} ({ConvertFormatToSize(format) * dimension} bytes)\";\n            if (attr.stream != 0)\n                str += $\", stream {attr.stream}\";\n            return str;\n        }\n\n        static long CalcTotalIndices(Mesh mesh)\n        {\n            return mesh.GetTotalIndexCount();\n        }\n\n        static void DrawColorRect(Rect rect, Color color)\n        {\n            EditorGUI.DrawRect(rect, color);\n            var dimmed = color * new Color(0.2f, 0.2f, 0.2f, 0.5f);\n            EditorGUI.DrawRect(new Rect(rect.x, rect.y, 1, rect.height), dimmed);\n            EditorGUI.DrawRect(new Rect(rect.x + rect.width - 1, rect.y, 1, rect.height), dimmed);\n            EditorGUI.DrawRect(new Rect(rect.x, rect.y, rect.width, 1), dimmed);\n            EditorGUI.DrawRect(new Rect(rect.x, rect.y + rect.height - 1, rect.width, 1), dimmed);\n        }\n\n        public override void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            if (m_MeshPreviews.TryGetValue(target, out var meshPreview))\n                meshPreview.OnPreviewGUI(r, background);\n        }\n\n        public override string GetInfoString()\n        {\n            var mesh = target as Mesh;\n\n            if (mesh == null)\n                return \"\";\n\n            // When enough mesh lods are present attempt to show more detailed info\n            if(mesh.isLodSelectionActive && m_MeshPreviews.TryGetValue(target, out var meshPreview))\n            {\n                // Sanity check, fall back to default string if fail\n                if(meshPreview.mesh == mesh)\n                    return meshPreview.GetInfoString();\n            }\n\n            return MeshPreview.GetInfoString(mesh);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/MonoScriptInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Reflection;\nusing System.Collections.Generic;\nusing System;\nusing UnityEditor.AssetImporters;\nusing UnityEditorInternal;\nusing System.IO;\n\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(MonoImporter))]\n    internal class MonoScriptImporterInspector : AssetImporterEditor\n    {\n        const int m_RowHeight = 16;\n\n        private SerializedObject m_TargetObject;\n        private SerializedProperty m_Icon;\n\n        internal override void OnHeaderControlsGUI()\n        {\n            TextAsset textAsset = assetTarget as TextAsset;\n\n            GUILayout.FlexibleSpace();\n\n            ShowOpenButton(new[] { textAsset }, textAsset != null);\n\n            using (new EditorGUI.DisabledScope(textAsset == null))\n            {\n                if (textAsset as MonoScript)\n                {\n                    if (GUILayout.Button(\"Execution Order...\", EditorStyles.miniButton))//GUILayout.Width(150)))\n                    {\n                        SettingsService.OpenProjectSettings(\"Project/Script Execution Order\");\n                        GUIUtility.ExitGUI();\n                    }\n                }\n            }\n        }\n\n        internal override void OnHeaderIconGUI(Rect iconRect)\n        {\n            if (assetTargets != null)\n            {\n                if (m_Icon == null)\n                {\n                    m_TargetObject = new SerializedObject(assetTargets);\n                    m_Icon = m_TargetObject.FindProperty(\"m_Icon\");\n                }\n\n                if (m_Icon == null)\n                {\n                    base.OnHeaderIconGUI(iconRect);\n                    return;\n                }\n\n                Rect dropDownRect = iconRect;\n\n                dropDownRect.size = EditorGUI.GetObjectIconDropDownSize(iconRect.width, iconRect.height);\n                EditorGUI.ObjectIconDropDown(dropDownRect, assetTargets, true, null, m_Icon);\n\n                Event evt = Event.current;\n                if (EventType.ValidateCommand == evt.type && (evt.commandName == \"Undo Icon On GameObject\" || evt.commandName == \"Redo Icon On GameObject\"))\n                {\n                    MonoScript monoScript = assetTargets[0] as MonoScript;\n                    IconSelector.CopyIconToImporter(monoScript);\n                    GUI.changed = true;\n                    evt.Use();\n                }\n            }\n            else\n            {\n                base.OnHeaderIconGUI(iconRect);\n            }\n        }\n\n        protected override bool needsApplyRevert => false;\n\n        // Clear default references\n        // ReSharper disable once UnusedMember.Local - registers as menu handler\n        [MenuItem(\"CONTEXT/MonoImporter/Reset\", validate = true)]\n        static bool ResetDefaultReferencesValidate(MenuCommand command)\n        {\n            return AssetDatabase.IsOpenForEdit(command.context);\n        }\n\n        // ReSharper disable once UnusedMember.Local - registers as menu handler\n        [MenuItem(\"CONTEXT/MonoImporter/Reset\", secondaryPriority = 13)]\n        static void ResetDefaultReferences(MenuCommand command)\n        {\n            MonoImporter importer = command.context as MonoImporter;\n            importer.SetDefaultReferences(new string[0], new Object[0]);\n            AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(importer));\n        }\n\n        static bool IsTypeCompatible(Type type)\n        {\n            if (type == null ||\n                !(type.IsSubclassOf(typeof(MonoBehaviour)) ||\n                type.IsSubclassOf(typeof(ScriptableObject)) ||\n                type.IsSubclassOf(typeof(PropertyDrawer))))\n                return false;\n            return true;\n        }\n\n        void ShowFieldInfo(Type type, MonoImporter importer, List<string> names, List<Object> objects, ref bool didModify)\n        {\n            // Only show default properties for types that support it (so far only MonoBehaviour derived types)\n            if (!IsTypeCompatible(type))\n                return;\n\n            ShowFieldInfo(type.BaseType, importer, names, objects, ref didModify);\n\n            FieldInfo[] infos = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);\n            foreach (FieldInfo field in infos)\n            {\n                if (!field.IsPublic)\n                {\n                    object[] attr = field.GetCustomAttributes(typeof(SerializeField), true);\n                    if (attr == null || attr.Length == 0)\n                        continue;\n                }\n\n                if (field.FieldType.IsSubclassOf(typeof(Object)) || field.FieldType == typeof(Object))\n                {\n                    Object oldTarget = importer.GetDefaultReference(field.Name, out var instanceID);\n                    if(oldTarget == null && instanceID != 0)\n                    {\n                        oldTarget = Object.CreateMissingReferenceObject(instanceID);\n                    }\n                    Object newTarget = EditorGUILayout.ObjectField(ObjectNames.NicifyVariableName(field.Name), oldTarget, field.FieldType, false);\n\n                    names.Add(field.Name);\n                    objects.Add(newTarget);\n\n                    if (oldTarget != newTarget)\n                        didModify = true;\n                }\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            var importer = target as MonoImporter;\n            var script = importer.GetScript();\n\n            if (script)\n            {\n                Type type = script.GetClass();\n\n                // Ignore Editor scripts\n                if (!InternalEditorUtility.IsInEditorFolder(importer.assetPath))\n                {\n                    if (!IsTypeCompatible(type))\n                    {\n                        EditorGUILayout.HelpBox(\n                            \"No MonoBehaviour scripts in the file, or their names do not match the file name.\",\n                            MessageType.Info);\n                    }\n                }\n\n                var names = new List<string>();\n                var objects = new List<Object>();\n                var didModify = false;\n\n                // Make default reference fields show small icons\n                using (new EditorGUIUtility.IconSizeScope(new Vector2(m_RowHeight, m_RowHeight)))\n                {\n                    ShowFieldInfo(type, importer, names, objects, ref didModify);\n                }\n\n                if (0 != objects.Count)\n                    EditorGUILayout.HelpBox(\"Default references will only be applied in edit mode.\", MessageType.Info);\n\n                if (didModify)\n                {\n                    importer.SetDefaultReferences(names.ToArray(), objects.ToArray());\n                    AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(importer));\n                }\n            }\n        }\n    }\n\n    [CustomEditor(typeof(TextAsset))]\n    [CanEditMultipleObjects]\n    internal class TextAssetInspector : Editor\n    {\n        private const int kMaxChars = 7000;\n        [NonSerialized]\n        private GUIStyle m_TextStyle;\n        private TextAsset m_TextAsset;\n        private GUIContent m_CachedPreview;\n        private string m_AssetGUID;\n        private Hash128 m_LastDependencyHash;\n\n        public virtual void OnEnable()\n        {\n            alwaysAllowExpansion = true;\n            m_TextAsset = target as TextAsset;\n            m_AssetGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(m_TextAsset));\n            CachePreview();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (m_TextStyle == null)\n                m_TextStyle = \"ScriptText\";\n\n            Hash128 dependencyHash = AssetDatabase.GetSourceAssetFileHash(m_AssetGUID);\n            if (m_LastDependencyHash != dependencyHash)\n            {\n                CachePreview();\n                m_LastDependencyHash = dependencyHash;\n            }\n\n            bool enabledTemp = GUI.enabled;\n            GUI.enabled = true;\n            if (m_TextAsset != null)\n            {\n                Rect rect = GUILayoutUtility.GetRect(m_CachedPreview, m_TextStyle);\n                rect.x = 0;\n                rect.y -= 3;\n                rect.width = GUIClip.visibleRect.width + 1;\n                GUI.Box(rect, \"\");\n                EditorGUI.SelectableLabel(rect, m_CachedPreview.text, m_TextStyle);\n            }\n            GUI.enabled = enabledTemp;\n        }\n\n        void CachePreview()\n        {\n            string text = string.Empty;\n\n            if (m_TextAsset != null)\n            {\n                if (targets.Length > 1)\n                {\n                    text = targetTitle;\n                }\n                else if (Path.GetExtension(AssetDatabase.GetAssetPath(m_TextAsset)) != \".bytes\")\n                {\n                    text = m_TextAsset.GetPreview(kMaxChars);\n                    if (text.Length >= kMaxChars)\n                        text = text.Substring(0, kMaxChars) + \"...\\n\\n<...etc...>\";\n                }\n                else\n                {\n                    text = $\"{EditorUtility.FormatBytes(m_TextAsset.dataSize)} size .bytes file\";\n                }\n            }\n\n            m_CachedPreview = new GUIContent(text);\n        }\n    }\n\n\n    [CustomEditor(typeof(MonoScript))]\n    [CanEditMultipleObjects]\n    internal class MonoScriptInspector : TextAssetInspector\n    {\n        public override void OnInspectorGUI()\n        {\n            if (targets.Length == 1)\n            {\n                var assetPath = AssetDatabase.GetAssetPath(target);\n                var assemblyName = Compilation.CompilationPipeline.GetAssemblyNameFromScriptPath(assetPath);\n                // assemblyName is null for MonoScript's inside assemblies.\n                if (assemblyName != null)\n                {\n                    GUILayout.Label(\"Assembly Information\", EditorStyles.boldLabel);\n\n                    EditorGUILayout.LabelField(\"Filename\", assemblyName);\n\n                    var assemblyDefinitionFile = Compilation.CompilationPipeline.GetAssemblyDefinitionFilePathFromScriptPath(assetPath);\n\n                    if (assemblyDefinitionFile != null)\n                    {\n                        var assemblyDefinitionFileAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(assemblyDefinitionFile);\n\n                        using (new EditorGUI.DisabledScope(true))\n                        {\n                            EditorGUILayout.ObjectField(\"Definition File\", assemblyDefinitionFileAsset, typeof(TextAsset), false);\n                        }\n                    }\n\n                    EditorGUILayout.Space();\n                }\n            }\n\n            base.OnInspectorGUI();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/NavMeshAgentInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.AI;\n\n\nnamespace UnityEditor\n{\n    [CanEditMultipleObjects]\n    [CustomEditor(typeof(NavMeshAgent))]\n    internal class NavMeshAgentInspector : Editor\n    {\n        private SerializedProperty m_AgentTypeID;\n        private SerializedProperty m_Radius;\n        private SerializedProperty m_Height;\n        private SerializedProperty m_WalkableMask;\n        private SerializedProperty m_Speed;\n        private SerializedProperty m_Acceleration;\n        private SerializedProperty m_AngularSpeed;\n        private SerializedProperty m_StoppingDistance;\n        private SerializedProperty m_AutoTraverseOffMeshLink;\n        private SerializedProperty m_AutoBraking;\n        private SerializedProperty m_AutoRepath;\n        private SerializedProperty m_BaseOffset;\n        private SerializedProperty m_ObstacleAvoidanceType;\n        private SerializedProperty m_AvoidancePriority;\n\n        private static class Styles\n        {\n            public static readonly GUIContent AgentSteeringHeader = EditorGUIUtility.TrTextContent(\"Steering\");\n            public static readonly GUIContent AgentAvoidanceHeader = EditorGUIUtility.TrTextContent(\"Obstacle Avoidance\");\n            public static readonly GUIContent AgentPathFindingHeader = EditorGUIUtility.TrTextContent(\"Path Finding\");\n            public static readonly GUIContent AgentType = EditorGUIUtility.TrTextContent(\"Agent Type\", \"The agent characteristics for which a NavMesh has been built.\");\n            public static readonly GUIContent BaseOffset = EditorGUIUtility.TrTextContent(\"Base Offset\", \"The relative vertical displacement of the owning GameObject.\");\n            public static readonly GUIContent Speed = EditorGUIUtility.TrTextContent(\"Speed\", \"Maximum movement speed when following a path.\");\n            public static readonly GUIContent AngularSpeed = EditorGUIUtility.TrTextContent(\"Angular Speed\", \"Maximum turning speed in (deg/s) while following a path.\");\n            public static readonly GUIContent Acceleration = EditorGUIUtility.TrTextContent(\"Acceleration\", \"The maximum acceleration of an agent as it follows a path, given in units / sec^2.\");\n            public static readonly GUIContent StoppingDistance = EditorGUIUtility.TrTextContent(\"Stopping Distance\", \"Stop within this distance from the target position.\");\n            public static readonly GUIContent AutoBraking = EditorGUIUtility.TrTextContent(\"Auto Braking\", \"The agent will avoid overshooting the destination point by slowing down in time.\");\n            public static readonly GUIContent Radius = EditorGUIUtility.TrTextContent(\"Radius\", \"The minimum distance to keep clear between the center of this agent and any other agents or obstacles nearby.\");\n            public static readonly GUIContent Height = EditorGUIUtility.TrTextContent(\"Height\", \"The height of the agent for purposes of passing under obstacles.\");\n            public static readonly GUIContent Quality = EditorGUIUtility.TrTextContent(\"Quality\", \"Higher quality avoidance reduces more the chance of agents overlapping but it is slower to compute than lower quality avoidance.\");\n            public static readonly GUIContent Priority = EditorGUIUtility.TrTextContent(\"Priority\", \"This agent will ignore all other agents for which this number is higher. A lower value implies higher importance.\");\n            public static readonly GUIContent AutoTraverseOffMeshLink = EditorGUIUtility.TrTextContent(\"Auto Traverse Off Mesh Link\", \"The agent moves across Off Mesh Links automatically.\");\n            public static readonly GUIContent AutoRepath = EditorGUIUtility.TrTextContent(\"Auto Repath\", \"The agent will attempt to acquire a new path if the existing path becomes invalid.\");\n            public static readonly GUIContent AreaMask = EditorGUIUtility.TrTextContent(\"Area Mask\", \"The agent plans a path and moves only through the selected NavMesh area types.\");\n        }\n\n        void OnEnable()\n        {\n            m_AgentTypeID = serializedObject.FindProperty(\"m_AgentTypeID\");\n            m_Radius = serializedObject.FindProperty(\"m_Radius\");\n            m_Height = serializedObject.FindProperty(\"m_Height\");\n            m_WalkableMask = serializedObject.FindProperty(\"m_WalkableMask\");\n            m_Speed = serializedObject.FindProperty(\"m_Speed\");\n            m_Acceleration = serializedObject.FindProperty(\"m_Acceleration\");\n            m_AngularSpeed = serializedObject.FindProperty(\"m_AngularSpeed\");\n            m_StoppingDistance = serializedObject.FindProperty(\"m_StoppingDistance\");\n            m_AutoTraverseOffMeshLink = serializedObject.FindProperty(\"m_AutoTraverseOffMeshLink\");\n            m_AutoBraking = serializedObject.FindProperty(\"m_AutoBraking\");\n            m_AutoRepath = serializedObject.FindProperty(\"m_AutoRepath\");\n            m_BaseOffset = serializedObject.FindProperty(\"m_BaseOffset\");\n            m_ObstacleAvoidanceType = serializedObject.FindProperty(\"m_ObstacleAvoidanceType\");\n            m_AvoidancePriority = serializedObject.FindProperty(\"avoidancePriority\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            AI.NavMeshEditorHelpers.DisplayInstallPackageButtonIfNeeded();\n\n            serializedObject.Update();\n\n            AgentTypePopupInternal(m_AgentTypeID);\n            EditorGUILayout.PropertyField(m_BaseOffset, Styles.BaseOffset);\n            EditorGUILayout.Space();\n            EditorGUILayout.LabelField(Styles.AgentSteeringHeader, EditorStyles.boldLabel);\n            EditorGUILayout.PropertyField(m_Speed, Styles.Speed);\n            EditorGUILayout.PropertyField(m_AngularSpeed, Styles.AngularSpeed);\n            EditorGUILayout.PropertyField(m_Acceleration, Styles.Acceleration);\n            EditorGUILayout.PropertyField(m_StoppingDistance, Styles.StoppingDistance);\n            EditorGUILayout.PropertyField(m_AutoBraking, Styles.AutoBraking);\n\n            EditorGUILayout.Space();\n            EditorGUILayout.LabelField(Styles.AgentAvoidanceHeader, EditorStyles.boldLabel);\n            EditorGUILayout.PropertyField(m_Radius, Styles.Radius);\n            EditorGUILayout.PropertyField(m_Height, Styles.Height);\n            EditorGUILayout.PropertyField(m_ObstacleAvoidanceType, Styles.Quality);\n            EditorGUILayout.PropertyField(m_AvoidancePriority, Styles.Priority);\n\n            EditorGUILayout.Space();\n            EditorGUILayout.LabelField(Styles.AgentPathFindingHeader, EditorStyles.boldLabel);\n            EditorGUILayout.PropertyField(m_AutoTraverseOffMeshLink, Styles.AutoTraverseOffMeshLink);\n            EditorGUILayout.PropertyField(m_AutoRepath, Styles.AutoRepath);\n\n            //Initially needed data\n            var areaNames = NavMesh.GetAreaNames();\n            var currentMask = m_WalkableMask.longValue;\n            var compressedMask = 0;\n\n            if (currentMask == 0xffffffff)\n            {\n                compressedMask = ~0;\n            }\n            else\n            {\n                //Need to find the index as the list of names will compress out empty areas\n                for (var i = 0; i < areaNames.Length; i++)\n                {\n                    var areaIndex = NavMesh.GetAreaFromName(areaNames[i]);\n                    if (((1 << areaIndex) & currentMask) != 0)\n                        compressedMask = compressedMask | (1 << i);\n                }\n            }\n\n            var position = EditorGUILayout.GetControlRect();\n            EditorGUI.BeginProperty(position, GUIContent.none, m_WalkableMask);\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = m_WalkableMask.hasMultipleDifferentValues;\n            var areaMask = EditorGUI.MaskField(position, Styles.AreaMask, compressedMask, areaNames, EditorStyles.layerMaskField);\n            EditorGUI.showMixedValue = false;\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (areaMask == ~0)\n                {\n                    m_WalkableMask.longValue = 0xffffffff;\n                }\n                else\n                {\n                    uint newMask = 0;\n                    for (var i = 0; i < areaNames.Length; i++)\n                    {\n                        //If the bit has been set in the compacted mask\n                        if (((areaMask >> i) & 1) != 0)\n                        {\n                            //Find out the 'real' layer from the name, then set it in the new mask\n                            newMask = newMask | (uint)(1 << NavMesh.GetAreaFromName(areaNames[i]));\n                        }\n                    }\n                    m_WalkableMask.longValue = newMask;\n                }\n            }\n            EditorGUI.EndProperty();\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        private static void AgentTypePopupInternal(SerializedProperty agentTypeID)\n        {\n            var index = -1;\n            var count = NavMesh.GetSettingsCount();\n            var agentTypeNames = new string[count + 2];\n            for (var i = 0; i < count; i++)\n            {\n                var id = NavMesh.GetSettingsByIndex(i).agentTypeID;\n                var name = NavMesh.GetSettingsNameFromID(id);\n                agentTypeNames[i] = name;\n                if (id == agentTypeID.intValue)\n                    index = i;\n            }\n            agentTypeNames[count] = \"\";\n            agentTypeNames[count + 1] = \"Open Agent Settings...\";\n\n            bool validAgentType = index != -1;\n            if (!validAgentType)\n            {\n                EditorGUILayout.HelpBox(\"Agent Type invalid.\", MessageType.Warning);\n            }\n\n            var rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);\n            EditorGUI.BeginProperty(rect, GUIContent.none, agentTypeID);\n\n            EditorGUI.BeginChangeCheck();\n            index = EditorGUI.Popup(rect, Styles.AgentType, index, agentTypeNames);\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (index >= 0 && index < count)\n                {\n                    var id = NavMesh.GetSettingsByIndex(index).agentTypeID;\n                    agentTypeID.intValue = id;\n                }\n                else if (index == count + 1)\n                {\n                    UnityEditor.AI.NavMeshEditorHelpers.OpenAgentSettings(-1);\n                }\n            }\n\n            EditorGUI.EndProperty();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/NavMeshObstacleInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.AI;\n\nnamespace UnityEditor\n{\n    [CanEditMultipleObjects]\n    [CustomEditor(typeof(NavMeshObstacle))]\n    internal class NavMeshObstacleInspector : Editor\n    {\n        private SerializedProperty m_Shape;\n        private SerializedProperty m_Center;\n        private SerializedProperty m_Extents;\n        private SerializedProperty m_Carve;\n        private SerializedProperty m_MoveThreshold;\n        private SerializedProperty m_TimeToStationary;\n        private SerializedProperty m_CarveOnlyStationary;\n\n        static class Styles\n        {\n            public static readonly GUIContent Shape = EditorGUIUtility.TrTextContent(\"Shape\", \"The shape of the obstacle, applied to both carving and avoidance.\");\n            public static readonly GUIContent Center = EditorGUIUtility.TrTextContent(\"Center\", \"The center of the obstacle, specified in the object's local space.\");\n            public static readonly GUIContent Size = EditorGUIUtility.TrTextContent(\"Size\", \"The size of the obstacle, measured in the object's local space.\");\n            public static readonly GUIContent Carve = EditorGUIUtility.TrTextContent(\"Carve\", \"This obstacle cuts a hole in the NavMesh around it.\");\n            public static readonly GUIContent Radius = EditorGUIUtility.TrTextContent(\"Radius\", \"Radius of the obstacle's capsule shape.\");\n            public static readonly GUIContent Height = EditorGUIUtility.TrTextContent(\"Height\", \"Height of the obstacle's capsule shape.\");\n            public static readonly float RadiusAndHeightLabelsWidth = 45f;\n        }\n\n        void OnEnable()\n        {\n            m_Shape = serializedObject.FindProperty(\"m_Shape\");\n            m_Center = serializedObject.FindProperty(\"m_Center\");\n            m_Extents = serializedObject.FindProperty(\"m_Extents\");\n            m_Carve = serializedObject.FindProperty(\"m_Carve\");\n            m_MoveThreshold = serializedObject.FindProperty(\"m_MoveThreshold\");\n            m_TimeToStationary = serializedObject.FindProperty(\"m_TimeToStationary\");\n            m_CarveOnlyStationary = serializedObject.FindProperty(\"m_CarveOnlyStationary\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            AI.NavMeshEditorHelpers.DisplayInstallPackageButtonIfNeeded();\n\n            serializedObject.Update();\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_Shape, Styles.Shape);\n            if (EditorGUI.EndChangeCheck())\n            {\n                serializedObject.ApplyModifiedProperties();\n                (target as NavMeshObstacle).FitExtents();\n                serializedObject.Update();\n            }\n\n            EditorGUILayout.PropertyField(m_Center, Styles.Center);\n\n            if (m_Shape.enumValueIndex == 0)\n            {\n                // NavMeshObstacleShape : kObstacleShapeCapsule\n                var r = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight * 2 + EditorGUI.kControlVerticalSpacing);\n                EditorGUI.BeginProperty(r, GUIContent.none, m_Extents);\n\n                Rect valueRect = EditorGUI.PrefixLabel(r, Styles.Size);\n\n                float oldLabelWidth = EditorGUIUtility.labelWidth;\n                int oldIndentLevel = EditorGUI.indentLevel;\n                EditorGUIUtility.labelWidth = Styles.RadiusAndHeightLabelsWidth;\n                EditorGUI.indentLevel = 0;\n\n                EditorGUI.BeginChangeCheck();\n                valueRect.height = EditorGUI.kSingleLineHeight;\n                float radius = EditorGUI.FloatField(valueRect, Styles.Radius, m_Extents.vector3Value.x);\n                valueRect.y += EditorGUI.kSingleLineHeight + EditorGUI.kControlVerticalSpacing;\n                float height = EditorGUI.FloatField(valueRect, Styles.Height, m_Extents.vector3Value.y * 2.0f);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_Extents.vector3Value = new Vector3(radius, height / 2.0f, radius);\n                }\n\n                EditorGUI.indentLevel = oldIndentLevel;\n                EditorGUIUtility.labelWidth = oldLabelWidth;\n\n                EditorGUI.EndProperty();\n            }\n            else if (m_Shape.enumValueIndex == 1)\n            {\n                // NavMeshObstacleShape : kObstacleShapeBox\n                var r = EditorGUILayout.GetControlRect(true, (EditorGUIUtility.wideMode ? 1 : 2) * EditorGUI.kSingleLineHeight + EditorGUI.kControlVerticalSpacing);\n                EditorGUI.BeginProperty(r, GUIContent.none, m_Extents);\n\n                EditorGUI.BeginChangeCheck();\n                Vector3 size = m_Extents.vector3Value * 2.0f;\n                size = EditorGUI.Vector3Field(r, Styles.Size, size);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_Extents.vector3Value = size / 2.0f;\n                }\n                EditorGUI.EndProperty();\n            }\n\n            EditorGUILayout.PropertyField(m_Carve, Styles.Carve);\n\n            if (m_Carve.boolValue)\n            {\n                EditorGUI.indentLevel++;\n                EditorGUILayout.PropertyField(m_MoveThreshold);\n                EditorGUILayout.PropertyField(m_TimeToStationary);\n                EditorGUILayout.PropertyField(m_CarveOnlyStationary);\n                EditorGUI.indentLevel--;\n            }\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/NotSupportedOnRenderPipelineInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    internal class NotSupportedOnRenderPipelineInspector : Editor\n    {\n        public override VisualElement CreateInspectorGUI()\n        {\n            return new HelpBox(\"This component is not supported on the currently active render pipeline.\", HelpBoxMessageType.Warning);\n        }\n\n        public override void OnInspectorGUI()\n        {\n            EditorGUILayout.HelpBox(\"This component is not supported on the currently active render pipeline.\", MessageType.Warning);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/OcclusionAreaEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(OcclusionArea))]\n    class OcclusionAreaEditor : Editor\n    {\n        SerializedObject   m_Object;\n        SerializedProperty m_Size;\n        SerializedProperty m_Center;\n\n        void OnEnable()\n        {\n            m_Object = new SerializedObject(target);\n            m_Size = serializedObject.FindProperty(\"m_Size\");\n            m_Center = serializedObject.FindProperty(\"m_Center\");\n        }\n\n        void OnDisable()\n        {\n            m_Object.Dispose();\n            m_Object = null;\n        }\n\n        void OnSceneGUI()\n        {\n            if (!target)\n                return;\n            m_Object.Update();\n\n            OcclusionArea area = (OcclusionArea)target;\n\n\n            Color tempColor = Handles.color;\n            Handles.color = new Color(145f, 244f, 139f, 255f) / 255;\n\n            Vector3 offset = area.transform.TransformPoint(m_Center.vector3Value);\n\n            // Get min and max extends from center and size\n            Vector3 min = m_Size.vector3Value * 0.5f;\n            Vector3 max = m_Size.vector3Value * 0.5f;\n\n            // Yes, it's weird to use lossyScale here, but that's what the occlusion volumes do\n            Vector3 scale = area.transform.lossyScale;\n            Vector3 inverseScale = new Vector3(1 / scale.x, 1 / scale.y, 1 / scale.z);\n            min = Vector3.Scale(min, scale);\n            max = Vector3.Scale(max, scale);\n\n            // Handles\n            bool temp = GUI.changed;\n            min.x = SizeSlider(offset, -Vector3.right,   min.x);\n            min.y = SizeSlider(offset, -Vector3.up,      min.y);\n            min.z = SizeSlider(offset, -Vector3.forward, min.z);\n            max.x = SizeSlider(offset,  Vector3.right,   max.x);\n            max.y = SizeSlider(offset,  Vector3.up,      max.y);\n            max.z = SizeSlider(offset,  Vector3.forward, max.z);\n\n            // Apply cahnges if there were any\n            if (GUI.changed)\n            {\n                // Occlusion volumes can't be rotated but the center is still affected by rotation, so\n                // we need to rotate the offset (and apply the inverse lossyScale AFTER that)\n                m_Center.vector3Value = m_Center.vector3Value + Vector3.Scale(Quaternion.Inverse(area.transform.rotation) * (max - min) * 0.5f, inverseScale);\n                min = Vector3.Scale(min, inverseScale);\n                max = Vector3.Scale(max, inverseScale);\n                m_Size.vector3Value = (max + min);\n\n                serializedObject.ApplyModifiedProperties();\n            }\n            GUI.changed |= temp;\n\n            Handles.color = tempColor;\n        }\n\n        float SizeSlider(Vector3 p, Vector3 d, float r)\n        {\n            Vector3 position = p + d * r;\n            Color tempColor = Handles.color;\n\n            if (Vector3.Dot((position - Camera.current.transform.position), d) >= 0)\n                Handles.color = new Color(Handles.color.r, Handles.color.g, Handles.color.b, Handles.color.a * Handles.backfaceAlphaMultiplier);\n\n            float size = HandleUtility.GetHandleSize(position);\n            bool temp = GUI.changed;\n            GUI.changed = false;\n            position = Handles.Slider(position, d, size * 0.1f, Handles.CylinderHandleCap, 0f);\n            if (GUI.changed)\n                r = Vector3.Dot(position - p, d);\n            GUI.changed |= temp;\n\n            Handles.color = tempColor;\n            return r;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/OcclusionPortalEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(OcclusionPortal)), CanEditMultipleObjects]\n    internal class OcclusionPortalEditor : Editor\n    {\n        private const string k_CenterPath = \"m_Center\";\n        private const string k_SizePath = \"m_Size\";\n\n        private readonly BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle();\n\n        protected virtual void OnEnable()\n        {\n            m_BoundsHandle.SetColor(Handles.s_ColliderHandleColor);\n        }\n\n        public override void OnInspectorGUI()\n        {\n            EditMode.DoEditModeInspectorModeButton(\n                EditMode.SceneViewEditMode.Collider,\n                \"Edit Bounds\",\n                PrimitiveBoundsHandle.editModeButton,\n                this\n            );\n\n            base.OnInspectorGUI();\n        }\n\n        public static bool IsSceneGUIEnabled()\n        {\n            return (EditMode.editMode == EditMode.SceneViewEditMode.Collider);\n        }\n\n        protected virtual void OnSceneGUI()\n        {\n            if (!EditMode.IsOwner(this) || !target)\n                return;\n\n            OcclusionPortal portal = target as OcclusionPortal;\n\n            // this.serializedObject will not work within OnSceneGUI if multiple targets are selected\n            using (var so = new SerializedObject(portal))\n            {\n                so.Update();\n\n                using (new Handles.DrawingScope(portal.transform.localToWorldMatrix))\n                {\n                    SerializedProperty centerProperty = so.FindProperty(k_CenterPath);\n                    SerializedProperty sizeProperty = so.FindProperty(k_SizePath);\n                    m_BoundsHandle.center = centerProperty.vector3Value;\n                    m_BoundsHandle.size = sizeProperty.vector3Value;\n\n                    EditorGUI.BeginChangeCheck();\n                    m_BoundsHandle.DrawHandle();\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        centerProperty.vector3Value = m_BoundsHandle.center;\n                        sizeProperty.vector3Value = m_BoundsHandle.size;\n                        so.ApplyModifiedProperties();\n                    }\n                }\n            }\n        }\n\n        internal override Bounds GetWorldBoundsOfTarget(Object targetObject)\n        {\n            using (var so = new SerializedObject(targetObject))\n            {\n                Vector3 center = so.FindProperty(k_CenterPath).vector3Value;\n                Vector3 size = so.FindProperty(k_SizePath).vector3Value;\n\n                var localBounds = new Bounds(center, size);\n                Vector3 max = localBounds.max;\n                Vector3 min = localBounds.min;\n                Matrix4x4 portalTransformMatrix = ((OcclusionPortal)targetObject).transform.localToWorldMatrix;\n                var worldBounds = new Bounds(portalTransformMatrix.MultiplyPoint3x4(new Vector3(max.x, max.y, max.z)), Vector3.zero);\n                worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(max.x, max.y, max.z)));\n                worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(max.x, max.y, min.z)));\n                worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(max.x, min.y, max.z)));\n                worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(min.x, max.y, max.z)));\n                worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(max.x, min.y, min.z)));\n                worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(min.x, max.y, min.z)));\n                worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(min.x, min.y, max.z)));\n                worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(min.x, min.y, min.z)));\n\n                return worldBounds;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/OffMeshLinkInspector.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.AI;\n\nnamespace UnityEditor\n{\n    [CanEditMultipleObjects]\n    [CustomEditor(typeof(OffMeshLink))]\n    [Obsolete(\"OffMeshLink has been deprecated and replaced by NavMeshLink.\")]\n    internal class OffMeshLinkInspector : Editor\n    {\n        private SerializedProperty m_AreaIndex;\n        private SerializedProperty m_Start;\n        private SerializedProperty m_End;\n        private SerializedProperty m_CostOverride;\n        private SerializedProperty m_BiDirectional;\n        private SerializedProperty m_Activated;\n        private SerializedProperty m_AutoUpdatePositions;\n\n        static class Styles\n        {\n            public static readonly GUIContent Start = EditorGUIUtility.TrTextContent(\"Start\", \"The transform representing the start position of the link.\");\n            public static readonly GUIContent End = EditorGUIUtility.TrTextContent(\"End\", \"The transform representing the end position of the link.\");\n            public static readonly GUIContent CostOverride = EditorGUIUtility.TrTextContent(\"Cost Override\", \"A positive value here modifies the cost of the link that is normally given by Navigation Area.\");\n            public static readonly GUIContent BiDirectional = EditorGUIUtility.TrTextContent(\"Bidirectional\", \"When selected, agents can traverse the link also from End to Start, otherwise only from Start to End.\");\n            public static readonly GUIContent Activated = EditorGUIUtility.TrTextContent(\"Activated\", \"Makes the link available for pathfinding.\");\n            public static readonly GUIContent AutoUpdatePositions = EditorGUIUtility.TrTextContent(\"Auto Update Positions\", \"Automatically update the link's endpoints to match the positions of the Start and End transforms.\");\n            public static readonly GUIContent NavigationArea = EditorGUIUtility.TrTextContent(\"Navigation Area\", \"It assigns a specific cost to the link. Only NavMeshAgents with this area type in their Area Mask are allowed to pass through it.\");\n        }\n\n        void OnEnable()\n        {\n            m_AreaIndex = serializedObject.FindProperty(\"m_AreaIndex\");\n            m_Start = serializedObject.FindProperty(\"m_Start\");\n            m_End = serializedObject.FindProperty(\"m_End\");\n            m_CostOverride = serializedObject.FindProperty(\"m_CostOverride\");\n            m_BiDirectional = serializedObject.FindProperty(\"m_BiDirectional\");\n            m_Activated = serializedObject.FindProperty(\"m_Activated\");\n            m_AutoUpdatePositions = serializedObject.FindProperty(\"m_AutoUpdatePositions\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            AI.NavMeshEditorHelpers.DisplayInstallPackageButtonIfNeeded();\n\n            serializedObject.Update();\n\n            EditorGUILayout.PropertyField(m_Start, Styles.Start);\n            EditorGUILayout.PropertyField(m_End, Styles.End);\n            EditorGUILayout.PropertyField(m_CostOverride, Styles.CostOverride);\n            EditorGUILayout.PropertyField(m_BiDirectional, Styles.BiDirectional);\n            EditorGUILayout.PropertyField(m_Activated, Styles.Activated);\n            EditorGUILayout.PropertyField(m_AutoUpdatePositions, Styles.AutoUpdatePositions);\n\n            SelectNavMeshArea();\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        private void SelectNavMeshArea()\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = m_AreaIndex.hasMultipleDifferentValues;\n            var areaNames = NavMesh.GetAreaNames();\n            var currentAbsoluteIndex = m_AreaIndex.intValue;\n            var areaIndex = -1;\n\n            //Need to find the index as the list of names will compress out empty layers\n            for (var i = 0; i < areaNames.Length; i++)\n            {\n                if (NavMesh.GetAreaFromName(areaNames[i]) == currentAbsoluteIndex)\n                {\n                    areaIndex = i;\n                    break;\n                }\n            }\n\n            var area = EditorGUILayout.Popup(Styles.NavigationArea, areaIndex, areaNames);\n            EditorGUI.showMixedValue = false;\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                var newAreaIndex = NavMesh.GetAreaFromName(areaNames[area]);\n                m_AreaIndex.intValue = newAreaIndex;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ParentConstraintEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Animations;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(ParentConstraint))]\n    [CanEditMultipleObjects]\n    internal class ParentConstraintEditor : ConstraintEditorBase\n    {\n        private SerializedProperty m_TranslationAtRest;\n        private SerializedProperty m_TranslationOffsets;\n        private SerializedProperty m_RotationAtRest;\n        private SerializedProperty m_RotationOffsets;\n        private SerializedProperty m_Weight;\n        private SerializedProperty m_IsContraintActive;\n        private SerializedProperty m_IsLocked;\n        private SerializedProperty m_Sources;\n\n        private ReorderableList m_OffsetList;\n\n        internal override SerializedProperty atRest { get { throw new NotImplementedException(); } }\n        internal override SerializedProperty offset { get { throw new NotImplementedException(); } }\n        internal override SerializedProperty weight { get { return m_Weight; } }\n        internal override SerializedProperty isContraintActive { get { return m_IsContraintActive; } }\n        internal override SerializedProperty isLocked { get { return m_IsLocked; } }\n        internal override SerializedProperty sources { get { return m_Sources; } }\n\n        private class Styles : ConstraintStyleBase\n        {\n            GUIContent m_RestTranslation = EditorGUIUtility.TrTextContent(\"Position At Rest\");\n            GUIContent m_TranslationOffset = EditorGUIUtility.TrTextContent(\"Position Offset\");\n\n            GUIContent m_RestRotation = EditorGUIUtility.TrTextContent(\"Rotation At Rest\");\n            GUIContent m_RotationOffset = EditorGUIUtility.TrTextContent(\"Rotation Offset\");\n\n            GUIContent m_TranslationAxes = EditorGUIUtility.TrTextContent(\"Freeze Position Axes\");\n            GUIContent m_RotationAxes = EditorGUIUtility.TrTextContent(\"Freeze Rotation Axes\");\n\n            GUIContent m_DefaultSourceName = EditorGUIUtility.TrTextContent(\"None\");\n\n            GUIContent m_SourceOffsets = EditorGUIUtility.TrTextContent(\"Source Offsets\");\n\n            public override GUIContent AtRest { get { throw new NotImplementedException(); } }\n            public override GUIContent Offset { get { throw new NotImplementedException(); } }\n            public GUIContent TranslationAtRest { get { return m_RestTranslation; } }\n            public GUIContent RotationAtRest { get { return m_RestRotation; } }\n            public GUIContent TranslationOffset { get { return m_TranslationOffset; } }\n            public GUIContent RotationOffset { get { return m_RotationOffset; } }\n            public GUIContent FreezeTranslationAxes { get { return m_TranslationAxes; } }\n            public GUIContent FreezeRotationAxes { get { return m_RotationAxes; } }\n            public GUIContent SourceOffsets { get { return m_SourceOffsets; } }\n            public GUIContent DefaultSourceName { get { return m_DefaultSourceName; } }\n        }\n\n        private static Styles s_Style;\n\n        public void OnEnable()\n        {\n            if (s_Style == null)\n                s_Style = new Styles();\n\n            m_TranslationAtRest = serializedObject.FindProperty(\"m_TranslationAtRest\");\n            m_TranslationOffsets = serializedObject.FindProperty(\"m_TranslationOffsets\");\n            m_RotationAtRest = serializedObject.FindProperty(\"m_RotationAtRest\");\n            m_RotationOffsets = serializedObject.FindProperty(\"m_RotationOffsets\");\n            m_Weight = serializedObject.FindProperty(\"m_Weight\");\n            m_IsContraintActive = serializedObject.FindProperty(\"m_Active\");\n            m_IsLocked = serializedObject.FindProperty(\"m_IsLocked\");\n            m_Sources = serializedObject.FindProperty(\"m_Sources\");\n\n            m_OffsetList = new ReorderableList(serializedObject, sources, false, false, false, false);\n            m_OffsetList.drawHeaderCallback += rect => EditorGUI.LabelField(rect, s_Style.SourceOffsets);\n            m_OffsetList.drawElementCallback += DrawOffsetElementCallback;\n            m_OffsetList.elementHeightCallback += OnElementHeightCallback;\n\n            OnEnable(s_Style);\n\n            m_OffsetList.index = base.selectedSourceIndex;\n        }\n\n        private void DrawOffsetElementCallback(Rect rect, int index, bool isActive, bool isFocused)\n        {\n            var translationOffset = m_TranslationOffsets.GetArrayElementAtIndex(index);\n            var rotationOffset = m_RotationOffsets.GetArrayElementAtIndex(index);\n            var element = m_Sources.GetArrayElementAtIndex(index);\n            var sourceElement = element.FindPropertyRelative(\"sourceTransform\");\n            var sourceName = s_Style.DefaultSourceName;\n            if (sourceElement.objectReferenceValue != null)\n            {\n                sourceName = EditorGUIUtility.TextContent(sourceElement.objectReferenceValue.name);\n            }\n\n            Rect drawRect = rect;\n            drawRect.height = EditorGUIUtility.singleLineHeight;\n            drawRect.y += EditorGUIUtility.standardVerticalSpacing;\n\n            EditorGUI.LabelField(drawRect, sourceName);\n\n            drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;\n            EditorGUI.PropertyField(drawRect, translationOffset, s_Style.TranslationOffset);\n            drawRect.y += EditorGUIUtility.wideMode ? EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing : 2 * (EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing);\n            EditorGUI.PropertyField(drawRect, rotationOffset, s_Style.RotationOffset);\n        }\n\n        protected override void OnRemoveCallback(ReorderableList list)\n        {\n            int index = list.index;\n            ReorderableList.defaultBehaviours.DoRemoveButton(list);\n            m_TranslationOffsets.DeleteArrayElementAtIndex(index);\n            m_RotationOffsets.DeleteArrayElementAtIndex(index);\n            if (selectedSourceIndex >= list.serializedProperty.arraySize)\n            {\n                SelectSource(list.serializedProperty.arraySize - 1);\n            }\n        }\n\n        protected override void OnAddCallback(ReorderableList list)\n        {\n            var index = list.serializedProperty.arraySize;\n            ReorderableList.defaultBehaviours.DoAddButton(list);\n            m_TranslationOffsets.arraySize++;\n            m_RotationOffsets.arraySize++;\n\n            var source = list.serializedProperty.GetArrayElementAtIndex(index);\n            source.FindPropertyRelative(\"sourceTransform\").objectReferenceValue = null;\n            source.FindPropertyRelative(\"weight\").floatValue = 1.0f;\n\n            SelectSource(index);\n        }\n\n        protected override void OnReorderCallback(ReorderableList list, int oldActiveElement, int newActiveElement)\n        {\n            m_TranslationOffsets.MoveArrayElement(oldActiveElement, newActiveElement);\n            m_RotationOffsets.MoveArrayElement(oldActiveElement, newActiveElement);\n            m_SerializedObject.ApplyModifiedProperties();\n            m_SerializedObject.Update();\n        }\n\n        protected override void OnSelectedCallback(ReorderableList list)\n        {\n            base.OnSelectedCallback(list);\n            m_OffsetList.index = list.index;\n        }\n\n        static readonly float kListItemHeight = 3 * (EditorGUIUtility.singleLineHeight + 2 * EditorGUIUtility.standardVerticalSpacing);\n        static readonly float kListItemNarrowHeight = 5 * (EditorGUIUtility.singleLineHeight + 2 * EditorGUIUtility.standardVerticalSpacing);\n        private float OnElementHeightCallback(int index)\n        {\n            if (EditorGUIUtility.wideMode)\n            {\n                return kListItemHeight;\n            }\n\n            return kListItemNarrowHeight;\n        }\n\n        internal override void OnValueAtRestChanged()\n        {\n            foreach (var t in targets)\n            {\n                (t as IConstraintInternal).transform.localPosition = m_TranslationAtRest.vector3Value;\n                (t as IConstraintInternal).transform.SetLocalEulerAngles(m_RotationAtRest.vector3Value, RotationOrder.OrderZXY);\n            }\n        }\n\n        internal override void ShowFreezeAxesControl()\n        {\n            Rect drawRectT = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, s_Style.FreezeTranslationAxes), EditorStyles.toggle);\n            EditorGUI.MultiPropertyField(drawRectT, s_Style.Axes, serializedObject.FindProperty(\"m_AffectTranslationX\"), s_Style.FreezeTranslationAxes);\n\n            Rect drawRectR = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, s_Style.FreezeRotationAxes), EditorStyles.toggle);\n            EditorGUI.MultiPropertyField(drawRectR, s_Style.Axes, serializedObject.FindProperty(\"m_AffectRotationX\"), s_Style.FreezeRotationAxes);\n        }\n\n        internal override void ShowValueAtRest(ConstraintStyleBase style)\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_TranslationAtRest, (style as Styles).TranslationAtRest);\n            EditorGUILayout.PropertyField(m_RotationAtRest, (style as Styles).RotationAtRest);\n            if (EditorGUI.EndChangeCheck())\n            {\n                OnValueAtRestChanged();\n            }\n        }\n\n        internal override void ShowOffset<T>(ConstraintStyleBase style)\n        {\n            using (new EditorGUI.DisabledGroupScope(isLocked.boolValue))\n            {\n                EditorGUI.BeginChangeCheck();\n                m_OffsetList.DoLayoutList();\n                if (EditorGUI.EndChangeCheck())\n                {\n                    foreach (var t in targets)\n                        (t as IConstraintInternal).UserUpdateOffset();\n                }\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (s_Style == null)\n                s_Style = new Styles();\n\n            serializedObject.Update();\n\n            ShowConstraintEditor<ParentConstraint>(s_Style);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ParticleSystemForceFieldInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq.Expressions;\nusing System.Reflection;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class UniformBoxBoundsHandle : SphereBoundsHandle\n    {\n        internal UniformBoxBoundsHandle() : base() {}\n\n        protected override void DrawWireframe()\n        {\n            Handles.DrawWireCube(center, GetSize());\n        }\n    }\n\n    [CustomEditor(typeof(ParticleSystemForceField))]\n    [CanEditMultipleObjects]\n    internal class ParticleSystemForceFieldInspector : Editor\n    {\n        private static readonly SphereBoundsHandle s_SphereBoundsHandle = new SphereBoundsHandle();\n        private static readonly UniformBoxBoundsHandle s_BoxBoundsHandle = new UniformBoxBoundsHandle();\n\n        private static PrefColor s_GizmoColor = new PrefColor(\"Particle System/Force Field Gizmos\", 148f / 255f, 229f / 255f, 1f, 0.9f);\n        private static readonly Color s_GizmoFocusTint = new Color(0.7f, 0.7f, 0.7f, 1.0f);\n\n        private static PropertyInfo s_StartRangeProperty = typeof(ParticleSystemForceField).GetProperty(\"startRange\");\n        private static PropertyInfo s_EndRangeProperty = typeof(ParticleSystemForceField).GetProperty(\"endRange\");\n        private static PropertyInfo s_GravityFocusProperty = typeof(ParticleSystemForceField).GetProperty(\"gravityFocus\");\n        private static PropertyInfo s_LengthProperty = typeof(ParticleSystemForceField).GetProperty(\"length\");\n\n        private static readonly string s_UndoString = L10n.Tr(\"Modify {0}\");\n\n        private SerializedProperty m_Shape;\n        private SerializedProperty m_StartRange;\n        private SerializedProperty m_EndRange;\n        private SerializedProperty m_Length;\n        private SerializedProperty m_DirectionX;\n        private SerializedProperty m_DirectionY;\n        private SerializedProperty m_DirectionZ;\n        private SerializedProperty m_Gravity;\n        private SerializedProperty m_GravityFocus;\n        private SerializedProperty m_RotationSpeed;\n        private SerializedProperty m_RotationAttraction;\n        private SerializedProperty m_RotationRandomness;\n        private SerializedProperty m_Drag;\n        private SerializedProperty m_MultiplyDragByParticleSize;\n        private SerializedProperty m_MultiplyDragByParticleVelocity;\n        private SerializedProperty m_VectorField;\n        private SerializedProperty m_VectorFieldSpeed;\n        private SerializedProperty m_VectorFieldAttraction;\n\n        MinMaxCurvePropertyDrawer m_DirectionDrawerX;\n        MinMaxCurvePropertyDrawer m_DirectionDrawerY;\n        MinMaxCurvePropertyDrawer m_DirectionDrawerZ;\n        MinMaxCurvePropertyDrawer m_GravityDrawer;\n        MinMaxCurvePropertyDrawer m_RotationSpeedDrawer;\n        MinMaxCurvePropertyDrawer m_RotationAttractionDrawer;\n        MinMaxCurvePropertyDrawer m_DragDrawer;\n        MinMaxCurvePropertyDrawer m_VectorFieldSpeedDrawer;\n        MinMaxCurvePropertyDrawer m_VectorFieldAttractionDrawer;\n\n        private class Styles\n        {\n            public static GUIContent shape = EditorGUIUtility.TrTextContent(\"Shape\", \"The bounding shape that forces are applied inside.\");\n            public static GUIContent startRange = EditorGUIUtility.TrTextContent(\"Start Range\", \"The inner extent of the bounding shape.\");\n            public static GUIContent endRange = EditorGUIUtility.TrTextContent(\"End Range\", \"The outer extent of the bounding shape.\");\n            public static GUIContent length = EditorGUIUtility.TrTextContent(\"Length\", \"The length of the cylinder.\");\n            public static GUIContent directionX = EditorGUIUtility.TrTextContent(\"X\", \"The force to apply along the X axis.\");\n            public static GUIContent directionY = EditorGUIUtility.TrTextContent(\"Y\", \"The force to apply along the Y axis.\");\n            public static GUIContent directionZ = EditorGUIUtility.TrTextContent(\"Z\", \"The force to apply along the Z axis.\");\n            public static GUIContent gravity = EditorGUIUtility.TrTextContent(\"Strength\", \"The strength of the gravity effect.\");\n            public static GUIContent gravityFocus = EditorGUIUtility.TrTextContent(\"Focus\", \"Choose a band within the volume that particles will be attracted towards.\");\n            public static GUIContent rotationSpeed = EditorGUIUtility.TrTextContent(\"Speed\", \"The speed at which particles are propelled around the vortex.\");\n            public static GUIContent rotationAttraction = EditorGUIUtility.TrTextContent(\"Attraction\", \"Controls how strongly particles are dragged into the vortex motion.\");\n            public static GUIContent rotationRandomness = EditorGUIUtility.TrTextContent(\"Randomness\", \"Propel particles around random axes of the shape.\");\n            public static GUIContent drag = EditorGUIUtility.TrTextContent(\"Strength\", \"The strength of the drag effect.\");\n            public static GUIContent multiplyDragByParticleSize = EditorGUIUtility.TrTextContent(\"Multiply by Size\", \"Adjust the drag based on the size of the particles.\");\n            public static GUIContent multiplyDragByParticleVelocity = EditorGUIUtility.TrTextContent(\"Multiply by Velocity\", \"Adjust the drag based on the velocity of the particles.\");\n            public static GUIContent vectorField = EditorGUIUtility.TrTextContent(\"Volume Texture\", \"The texture used for the vector field.\");\n            public static GUIContent vectorFieldSpeed = EditorGUIUtility.TrTextContent(\"Speed\", \"The speed multiplier applied to particles traveling through the vector field.\");\n            public static GUIContent vectorFieldAttraction = EditorGUIUtility.TrTextContent(\"Attraction\", \"Controls how strongly particles are dragged into the vector field motion.\");\n\n            public static GUIContent[] shapeOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Sphere\"),\n                EditorGUIUtility.TrTextContent(\"Hemisphere\"),\n                EditorGUIUtility.TrTextContent(\"Cylinder\"),\n                EditorGUIUtility.TrTextContent(\"Box\")\n            };\n\n            public static GUIContent shapeHeading = EditorGUIUtility.TrTextContent(\"Shape\");\n            public static GUIContent directionHeading = EditorGUIUtility.TrTextContent(\"Direction\");\n            public static GUIContent gravityHeading = EditorGUIUtility.TrTextContent(\"Gravity\");\n            public static GUIContent rotationHeading = EditorGUIUtility.TrTextContent(\"Rotation\");\n            public static GUIContent dragHeading = EditorGUIUtility.TrTextContent(\"Drag\");\n            public static GUIContent vectorFieldHeading = EditorGUIUtility.TrTextContent(\"Vector Field\");\n        }\n\n        void OnEnable()\n        {\n            m_Shape = serializedObject.FindProperty(\"m_Parameters.m_Shape\");\n            m_StartRange = serializedObject.FindProperty(\"m_Parameters.m_StartRange\");\n            m_EndRange = serializedObject.FindProperty(\"m_Parameters.m_EndRange\");\n            m_Length = serializedObject.FindProperty(\"m_Parameters.m_Length\");\n            m_DirectionX = serializedObject.FindProperty(\"m_Parameters.m_DirectionCurveX\");\n            m_DirectionY = serializedObject.FindProperty(\"m_Parameters.m_DirectionCurveY\");\n            m_DirectionZ = serializedObject.FindProperty(\"m_Parameters.m_DirectionCurveZ\");\n            m_Gravity = serializedObject.FindProperty(\"m_Parameters.m_GravityCurve\");\n            m_GravityFocus = serializedObject.FindProperty(\"m_Parameters.m_GravityFocus\");\n            m_RotationSpeed = serializedObject.FindProperty(\"m_Parameters.m_RotationSpeedCurve\");\n            m_RotationAttraction = serializedObject.FindProperty(\"m_Parameters.m_RotationAttractionCurve\");\n            m_RotationRandomness = serializedObject.FindProperty(\"m_Parameters.m_RotationRandomness\");\n            m_Drag = serializedObject.FindProperty(\"m_Parameters.m_DragCurve\");\n            m_MultiplyDragByParticleSize = serializedObject.FindProperty(\"m_Parameters.m_MultiplyDragByParticleSize\");\n            m_MultiplyDragByParticleVelocity = serializedObject.FindProperty(\"m_Parameters.m_MultiplyDragByParticleVelocity\");\n            m_VectorField = serializedObject.FindProperty(\"m_Parameters.m_VectorField\");\n            m_VectorFieldSpeed = serializedObject.FindProperty(\"m_Parameters.m_VectorFieldSpeedCurve\");\n            m_VectorFieldAttraction = serializedObject.FindProperty(\"m_Parameters.m_VectorFieldAttractionCurve\");\n\n            m_DirectionDrawerX = new MinMaxCurvePropertyDrawer() { isNativeProperty = true, xAxisLabel = \"distance\" };\n            m_DirectionDrawerY = new MinMaxCurvePropertyDrawer() { isNativeProperty = true, xAxisLabel = \"distance\" };\n            m_DirectionDrawerZ = new MinMaxCurvePropertyDrawer() { isNativeProperty = true, xAxisLabel = \"distance\" };\n            m_GravityDrawer = new MinMaxCurvePropertyDrawer() { isNativeProperty = true, xAxisLabel = \"distance\" };\n            m_RotationSpeedDrawer = new MinMaxCurvePropertyDrawer() { isNativeProperty = true, xAxisLabel = \"distance\" };\n            m_RotationAttractionDrawer = new MinMaxCurvePropertyDrawer() { isNativeProperty = true, xAxisLabel = \"distance\" };\n            m_DragDrawer = new MinMaxCurvePropertyDrawer() { isNativeProperty = true, xAxisLabel = \"distance\" };\n            m_VectorFieldSpeedDrawer = new MinMaxCurvePropertyDrawer() { isNativeProperty = true, xAxisLabel = \"distance\" };\n            m_VectorFieldAttractionDrawer = new MinMaxCurvePropertyDrawer() { isNativeProperty = true, xAxisLabel = \"distance\" };\n        }\n\n        static void DrawMinMaxCurveField(SerializedProperty property, MinMaxCurvePropertyDrawer drawer, GUIContent label)\n        {\n            var rect = EditorGUILayout.GetControlRect(false, drawer.GetPropertyHeight(property, label));\n            EditorGUI.BeginProperty(rect, label, property);\n            drawer.OnGUI(rect, property, label);\n            EditorGUI.EndProperty();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            GUILayout.Label(Styles.shapeHeading, EditorStyles.boldLabel);\n\n            EditorGUI.showMixedValue = m_Shape.hasMultipleDifferentValues;\n            var shapeRect = EditorGUILayout.GetControlRect(true);\n            EditorGUI.Popup(shapeRect, m_Shape, Styles.shapeOptions, Styles.shape);\n\n            EditorGUILayout.PropertyField(m_StartRange, Styles.startRange);\n            EditorGUILayout.PropertyField(m_EndRange, Styles.endRange);\n            if (m_Shape.intValue == (int)ParticleSystemForceFieldShape.Cylinder)\n                EditorGUILayout.PropertyField(m_Length, Styles.length);\n\n            EditorGUILayout.Space();\n\n            GUILayout.Label(Styles.directionHeading, EditorStyles.boldLabel);\n            DrawMinMaxCurveField(m_DirectionX, m_DirectionDrawerX, Styles.directionX);\n            DrawMinMaxCurveField(m_DirectionY, m_DirectionDrawerY, Styles.directionY);\n            DrawMinMaxCurveField(m_DirectionZ, m_DirectionDrawerZ, Styles.directionZ);\n            EditorGUILayout.Space();\n\n            EditorGUILayout.Space();\n\n            GUILayout.Label(Styles.gravityHeading, EditorStyles.boldLabel);\n            DrawMinMaxCurveField(m_Gravity, m_GravityDrawer, Styles.gravity);\n            EditorGUILayout.PropertyField(m_GravityFocus, Styles.gravityFocus);\n            EditorGUILayout.Space();\n\n            GUILayout.Label(Styles.rotationHeading, EditorStyles.boldLabel);\n            DrawMinMaxCurveField(m_RotationSpeed, m_RotationSpeedDrawer, Styles.rotationSpeed);\n            DrawMinMaxCurveField(m_RotationAttraction, m_RotationAttractionDrawer, Styles.rotationAttraction);\n            EditorGUILayout.PropertyField(m_RotationRandomness, Styles.rotationRandomness);\n            EditorGUILayout.Space();\n\n            GUILayout.Label(Styles.dragHeading, EditorStyles.boldLabel);\n            DrawMinMaxCurveField(m_Drag, m_DragDrawer, Styles.drag);\n            EditorGUILayout.PropertyField(m_MultiplyDragByParticleSize, Styles.multiplyDragByParticleSize);\n            EditorGUILayout.PropertyField(m_MultiplyDragByParticleVelocity, Styles.multiplyDragByParticleVelocity);\n            EditorGUILayout.Space();\n\n            GUILayout.Label(Styles.vectorFieldHeading, EditorStyles.boldLabel);\n            EditorGUILayout.PropertyField(m_VectorField, Styles.vectorField);\n            DrawMinMaxCurveField(m_VectorFieldSpeed, m_VectorFieldSpeedDrawer, Styles.vectorFieldSpeed);\n            DrawMinMaxCurveField(m_VectorFieldAttraction, m_VectorFieldAttractionDrawer, Styles.vectorFieldAttraction);\n            EditorGUILayout.Space();\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        void OnSceneGUI()\n        {\n            if (!target)\n                return;\n            EditorGUI.BeginChangeCheck();\n\n            ParticleSystemForceField ff = (ParticleSystemForceField)target;\n            DrawHandle(ff);\n\n            if (EditorGUI.EndChangeCheck())\n                Repaint();\n        }\n\n        public static void DrawHandle(ParticleSystemForceField ff)\n        {\n            using (new Handles.DrawingScope(s_GizmoColor, ff.transform.localToWorldMatrix))\n            {\n                ParticleSystemForceFieldShape forceShape = ff.shape;\n                if (forceShape == ParticleSystemForceFieldShape.Sphere)\n                {\n                    DrawSphere(s_EndRangeProperty, ff);\n\n                    if (ff.startRange > 0.0f)\n                        DrawSphere(s_StartRangeProperty, ff);\n\n                    if (ff.gravityFocus > 0.0f)\n                    {\n                        using (new Handles.DrawingScope(s_GizmoColor * s_GizmoFocusTint))\n                            DrawSphere(s_GravityFocusProperty, ff, ff.endRange);\n                    }\n                }\n                else if (forceShape == ParticleSystemForceFieldShape.Hemisphere)\n                {\n                    DrawHemisphere(s_EndRangeProperty, ff);\n\n                    if (ff.startRange > 0.0f)\n                        DrawHemisphere(s_StartRangeProperty, ff);\n\n                    if (ff.gravityFocus > 0.0f)\n                    {\n                        using (new Handles.DrawingScope(s_GizmoColor * s_GizmoFocusTint))\n                            DrawHemisphere(s_GravityFocusProperty, ff, ff.endRange);\n                    }\n                }\n                else if (forceShape == ParticleSystemForceFieldShape.Cylinder)\n                {\n                    DrawCylinder(s_EndRangeProperty, s_LengthProperty, ff);\n\n                    if (ff.startRange > 0.0f)\n                        DrawCylinder(s_StartRangeProperty, s_LengthProperty, ff);\n\n                    if (ff.gravityFocus > 0.0f)\n                    {\n                        using (new Handles.DrawingScope(s_GizmoColor * s_GizmoFocusTint))\n                            DrawCylinder(s_GravityFocusProperty, s_LengthProperty, ff, ff.endRange);\n                    }\n                }\n                else if (forceShape == ParticleSystemForceFieldShape.Box)\n                {\n                    DrawBox(s_EndRangeProperty, ff);\n\n                    if (ff.startRange > 0.0f)\n                        DrawBox(s_StartRangeProperty, ff);\n\n                    if (ff.gravityFocus > 0.0f)\n                    {\n                        using (new Handles.DrawingScope(s_GizmoColor * s_GizmoFocusTint))\n                            DrawBox(s_GravityFocusProperty, ff, ff.endRange);\n                    }\n                }\n            }\n        }\n\n        private static void DrawSphere(PropertyInfo radiusProp, ParticleSystemForceField target, float multiplyByRadius = 1.0f)\n        {\n            s_SphereBoundsHandle.axes = PrimitiveBoundsHandle.Axes.All;\n            s_SphereBoundsHandle.center = Vector3.zero;\n            s_SphereBoundsHandle.radius = (float)radiusProp.GetValue(target, null) * multiplyByRadius;\n\n            EditorGUI.BeginChangeCheck();\n            s_SphereBoundsHandle.DrawHandle();\n            if (EditorGUI.EndChangeCheck())\n            {\n                Undo.RecordObject(target, string.Format(s_UndoString, ObjectNames.NicifyVariableName(target.GetType().Name)));\n                radiusProp.SetValue(target, s_SphereBoundsHandle.radius / multiplyByRadius, null);\n            }\n        }\n\n        private static void DrawHemisphere(PropertyInfo radiusProp, ParticleSystemForceField target, float multiplyByRadius = 1.0f)\n        {\n            EditorGUI.BeginChangeCheck();\n\n            float oldRadius = (float)radiusProp.GetValue(target, null) * multiplyByRadius;\n            float newRadius = Handles.DoSimpleRadiusHandle(Quaternion.Euler(-90, 0, 0), Vector3.zero, oldRadius, true);\n            if (EditorGUI.EndChangeCheck())\n            {\n                Undo.RecordObject(target, string.Format(s_UndoString, ObjectNames.NicifyVariableName(target.GetType().Name)));\n                radiusProp.SetValue(target, newRadius / multiplyByRadius, null);\n            }\n        }\n\n        private static void DrawCylinder(PropertyInfo radiusProp, PropertyInfo lengthProp, ParticleSystemForceField target, float multiplyByRadius = 1.0f)\n        {\n            float lengthHalf = (float)lengthProp.GetValue(target, null) * 0.5f;\n\n            // Circle at each end\n            for (int i = 0; i < 2; i++)\n            {\n                s_SphereBoundsHandle.axes = PrimitiveBoundsHandle.Axes.X | PrimitiveBoundsHandle.Axes.Z;\n                s_SphereBoundsHandle.center = new Vector3(0.0f, (i > 0) ? -lengthHalf : lengthHalf, 0.0f);\n                s_SphereBoundsHandle.radius = (float)radiusProp.GetValue(target, null) * multiplyByRadius;\n\n                EditorGUI.BeginChangeCheck();\n                s_SphereBoundsHandle.DrawHandle();\n                if (EditorGUI.EndChangeCheck())\n                {\n                    Undo.RecordObject(target, string.Format(s_UndoString, ObjectNames.NicifyVariableName(target.GetType().Name)));\n                    radiusProp.SetValue(target, s_SphereBoundsHandle.radius / multiplyByRadius,  null);\n                }\n            }\n\n            // Handle at each end for controlling the length\n            EditorGUI.BeginChangeCheck();\n            lengthHalf = Handles.SizeSlider(Vector3.zero, Vector3.up, lengthHalf);\n            lengthHalf = Handles.SizeSlider(Vector3.zero, -Vector3.up, lengthHalf);\n            if (EditorGUI.EndChangeCheck())\n            {\n                Undo.RecordObject(target, string.Format(s_UndoString, ObjectNames.NicifyVariableName(target.GetType().Name)));\n                lengthProp.SetValue(target, Mathf.Max(0.0f, lengthHalf * 2.0f), null);\n            }\n\n            // Connecting lines\n            float lineRadius = (float)radiusProp.GetValue(target, null) * multiplyByRadius;\n            Handles.DrawLine(new Vector3(lineRadius, lengthHalf, 0.0f), new Vector3(lineRadius, -lengthHalf, 0.0f));\n            Handles.DrawLine(new Vector3(-lineRadius, lengthHalf, 0.0f), new Vector3(-lineRadius, -lengthHalf, 0.0f));\n            Handles.DrawLine(new Vector3(0.0f, lengthHalf, lineRadius), new Vector3(0.0f, -lengthHalf, lineRadius));\n            Handles.DrawLine(new Vector3(0.0f, lengthHalf, -lineRadius), new Vector3(0.0f, -lengthHalf, -lineRadius));\n        }\n\n        private static void DrawBox(PropertyInfo extentProp, ParticleSystemForceField target, float multiplyByRadius = 1.0f)\n        {\n            s_BoxBoundsHandle.axes = PrimitiveBoundsHandle.Axes.All;\n            s_BoxBoundsHandle.center = Vector3.zero;\n            s_BoxBoundsHandle.radius = (float)extentProp.GetValue(target, null) * multiplyByRadius;\n\n            EditorGUI.BeginChangeCheck();\n            s_BoxBoundsHandle.DrawHandle();\n            if (EditorGUI.EndChangeCheck())\n            {\n                Undo.RecordObject(target, string.Format(s_UndoString, ObjectNames.NicifyVariableName(target.GetType().Name)));\n                extentProp.SetValue(target, s_BoxBoundsHandle.radius / multiplyByRadius, null);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.AnimatedValues;\nusing UnityEngine;\nusing UnityEditor.Build;\nusing UnityEditor.SceneManagement;\nusing UnityEditor.PlatformSupport;\nusing UnityEditor.Presets;\nusing UnityEditorInternal;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Reflection;\nusing UnityEditor.Modules;\nusing UnityEditorInternal.VR;\nusing UnityEngine.Events;\nusing UnityEngine.SceneManagement;\nusing GraphicsDeviceType = UnityEngine.Rendering.GraphicsDeviceType;\nusing TargetAttributes = UnityEditor.BuildTargetDiscovery.TargetAttributes;\nusing UnityEngine.Rendering;\nusing UnityEngine.Scripting;\nusing UnityEngine.Bindings;\nusing UnityEditor.Build.Profile;\nusing UnityEditor.UIElements;\n\n// ************************************* READ BEFORE EDITING **************************************\n//\n// DO NOT COPY/PASTE! Please do not have the same setting more than once in the code.\n// If a setting for one platform needs to be exposed to more platforms,\n// change the if statements so the same lines of code are executed for both platforms,\n// instead of copying the lines into multiple code blocks.\n// This ensures that if we change labels, or headers, or the order of settings, it will remain\n// consistent without having to remember to make the same change multiple places. THANK YOU!\n//\n// ADD_NEW_PLATFORM_HERE: review this file\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(PlayerSettings))]\n    [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n    internal partial class PlayerSettingsEditor : Editor\n    {\n        class Styles\n        {\n            public static readonly GUIStyle categoryBox = new GUIStyle(EditorStyles.helpBox);\n            static Styles()\n            {\n                categoryBox.padding.left = 4;\n            }\n        }\n\n        class SettingsContent\n        {\n            public static readonly GUIContent recordingInfo = EditorGUIUtility.TrTextContent(\"Reordering the list will switch editor to the first available platform\");\n            public static readonly GUIContent appleSiliconOpenGLWarning = EditorGUIUtility.TrTextContent(\"OpenGL is not supported on Apple Silicon chips. Metal will be used on devices with Apple Silicon chips instead.\");\n            public static readonly GUIContent sharedBetweenPlatformsInfo = EditorGUIUtility.TrTextContent(\"* Shared setting between multiple platforms.\");\n\n            public static readonly GUIContent cursorHotspot = EditorGUIUtility.TrTextContent(\"Cursor Hotspot\");\n            public static readonly GUIContent defaultCursor = EditorGUIUtility.TrTextContent(\"Default Cursor\");\n            public static readonly GUIContent vertexChannelCompressionMask = EditorGUIUtility.TrTextContent(\"Vertex Compression*\", \"Select which vertex channels should be compressed. Compression can save memory and bandwidth, but precision will be lower.\");\n\n            public static readonly GUIContent resolutionPresentationTitle = EditorGUIUtility.TrTextContent(\"Resolution and Presentation\");\n            public static readonly GUIContent resolutionTitle = EditorGUIUtility.TrTextContent(\"Resolution\");\n            public static readonly GUIContent orientationTitle = EditorGUIUtility.TrTextContent(\"Orientation\");\n            public static readonly GUIContent allowedOrientationTitle = EditorGUIUtility.TrTextContent(\"Allowed Orientations for Auto Rotation\");\n            public static readonly GUIContent multitaskingSupportTitle = EditorGUIUtility.TrTextContent(\"Multitasking Support\");\n            public static readonly GUIContent statusBarTitle = EditorGUIUtility.TrTextContent(\"Status Bar\");\n            public static readonly GUIContent standalonePlayerOptionsTitle = EditorGUIUtility.TrTextContent(\"Standalone Player Options\");\n            public static readonly GUIContent debuggingCrashReportingTitle = EditorGUIUtility.TrTextContent(\"Debugging and crash reporting\");\n            public static readonly GUIContent debuggingTitle = EditorGUIUtility.TrTextContent(\"Debugging\");\n            public static readonly GUIContent crashReportingTitle = EditorGUIUtility.TrTextContent(\"Crash Reporting\");\n            public static readonly GUIContent otherSettingsTitle = EditorGUIUtility.TrTextContent(\"Other Settings\");\n            public static readonly GUIContent renderingTitle = EditorGUIUtility.TrTextContent(\"Rendering\");\n            public static readonly GUIContent vulkanSettingsTitle = EditorGUIUtility.TrTextContent(\"Vulkan Settings\");\n            public static readonly GUIContent identificationTitle = EditorGUIUtility.TrTextContent(\"Identification\");\n            public static readonly GUIContent configurationTitle = EditorGUIUtility.TrTextContent(\"Configuration\");\n            public static readonly GUIContent optimizationTitle = EditorGUIUtility.TrTextContent(\"Optimization\");\n            public static readonly GUIContent loggingTitle = EditorGUIUtility.TrTextContent(\"Stack Trace*\");\n            public static readonly GUIContent legacyTitle = EditorGUIUtility.TrTextContent(\"Legacy\");\n            public static readonly GUIContent publishingSettingsTitle = EditorGUIUtility.TrTextContent(\"Publishing Settings\");\n            public static readonly GUIContent captureLogsTitle = EditorGUIUtility.TrTextContent(\"Capture Logs\");\n\n            public static readonly GUIContent usePlayerLog = EditorGUIUtility.TrTextContent(\"Use Player Log\");\n            public static readonly GUIContent resizableWindow = EditorGUIUtility.TrTextContent(\"Resizable Window\");\n            public static readonly GUIContent forceSingleInstance = EditorGUIUtility.TrTextContent(\"Force Single Instance\");\n\n            public static readonly GUIContent shaderSectionTitle = EditorGUIUtility.TrTextContent(\"Shader Settings\");\n            public static readonly GUIContent shaderVariantLoadingTitle = EditorGUIUtility.TrTextContent(\"Shader Variant Loading Settings\");\n            public static readonly GUIContent defaultShaderChunkSize = EditorGUIUtility.TrTextContent(\"Default chunk size (MB)*\", \"Use this setting to control how much memory is used when loading shader variants.\");\n            public static readonly GUIContent defaultShaderChunkCount = EditorGUIUtility.TrTextContent(\"Default chunk count*\", \"Use this setting to control how much memory is used when loading shader variants.\");\n            public static readonly GUIContent overrideDefaultChunkSettings = EditorGUIUtility.TrTextContent(\"Override\", \"Override the default settings for this build target.\");\n            public static readonly GUIContent platformShaderChunkSize = EditorGUIUtility.TrTextContent(\"Chunk size (MB)\", \"Use this setting to control how much memory is used when loading shader variants.\");\n            public static readonly GUIContent platformShaderChunkCount = EditorGUIUtility.TrTextContent(\"Chunk count\", \"Use this setting to control how much memory is used when loading shader variants.\");\n\n            public static readonly GUIContent bakeCollisionMeshes = EditorGUIUtility.TrTextContent(\"Prebake Collision Meshes*\", \"Bake collision data into the meshes on build time\");\n            public static readonly GUIContent dedicatedServerOptimizations = EditorGUIUtility.TrTextContent(\"Enable Dedicated Server optimizations\", \"Performs additional optimizations on Dedicated Server builds.\");\n            public static readonly GUIContent keepLoadedShadersAlive = EditorGUIUtility.TrTextContent(\"Keep Loaded Shaders Alive*\", \"Prevents shaders from being unloaded\");\n            public static readonly GUIContent preloadedAssets = EditorGUIUtility.TrTextContent(\"Preloaded Assets*\", \"Assets to load at start up in the player and kept alive until the player terminates\");\n            public static readonly GUIContent stripEngineCode = EditorGUIUtility.TrTextContent(\"Strip Engine Code*\", \"Strip Unused Engine Code - Note that byte code stripping of managed assemblies is always enabled for the IL2CPP scripting backend.\");\n            public static readonly GUIContent iPhoneScriptCallOptimization = EditorGUIUtility.TrTextContent(\"Script Call Optimization*\");\n            public static readonly GUIContent enableInternalProfiler = EditorGUIUtility.TrTextContent(\"Enable Internal Profiler* (Deprecated)\", \"Internal profiler counters should be accessed by scripts using UnityEngine.Profiling::Profiler API.\");\n            public static readonly GUIContent stripUnusedMeshComponents = EditorGUIUtility.TrTextContent(\"Optimize Mesh Data*\", \"Remove unused mesh components\");\n            public static readonly GUIContent strictShaderVariantMatching = EditorGUIUtility.TrTextContent(\"Strict shader variant matching*\", \"When enabled, if a shader variant is missing, Unity uses the error shader and displays an error in the Console.\");\n            public static readonly GUIContent mipStripping = EditorGUIUtility.TrTextContent(\"Texture Mipmap Stripping*\", \"Remove unused texture mipmap levels from package builds, reducing package size on disk. Limits the texture quality settings to the highest mipmap level that was included during the build.\");\n            public static readonly GUIContent enableFrameTimingStats = EditorGUIUtility.TrTextContent(\"Frame Timing Stats\", \"Enable gathering of CPU/GPU frame timing statistics.\");\n            public static readonly GUIContent enableOpenGLProfilerGPURecorders = EditorGUIUtility.TrTextContent(\"OpenGL: Profiler GPU Recorders\", \"Enable Profiler Recorders when rendering with OpenGL. Always enabled with other rendering APIs. Optional on OpenGL due to potential incompatibility with Frame Timing Stats and the GPU Profiler.\");\n            public static readonly GUIContent openGLFrameTimingStatsOnGPURecordersOnWarning = EditorGUIUtility.TrTextContent(\"On OpenGL, Frame Timing Stats may disable Profiler GPU Recorders and the GPU Profiler.\");\n            public static readonly GUIContent openGLFrameTimingStatsOnGPURecordersOffInfo = EditorGUIUtility.TrTextContent(\"On OpenGL, Frame Timing Stats may disable the GPU Profiler.\");\n            public static readonly GUIContent openGLFrameTimingStatsOffGPURecordersOnInfo = EditorGUIUtility.TrTextContent(\"On OpenGL, Profiler GPU Recorders may disable the GPU Profiler.\");\n            public static readonly GUIContent useOSAutoRotation = EditorGUIUtility.TrTextContent(\"Use Animated Autorotation (Deprecated)\", \"If set OS native animated autorotation method will be used. Otherwise orientation will be changed immediately. This has no effect on iOS 16 and later versions as autorotation is always animated. This option is deprecated and will be removed in a future release.\");\n            public static readonly GUIContent defaultScreenWidth = EditorGUIUtility.TrTextContent(\"Default Screen Width\");\n            public static readonly GUIContent defaultScreenHeight = EditorGUIUtility.TrTextContent(\"Default Screen Height\");\n            public static readonly GUIContent macRetinaSupport = EditorGUIUtility.TrTextContent(\"Mac Retina Support\");\n            public static readonly GUIContent runInBackground = EditorGUIUtility.TrTextContent(\"Run In Background*\");\n            public static readonly GUIContent defaultIsNativeResolution = EditorGUIUtility.TrTextContent(\"Default Is Native Resolution\");\n            public static readonly GUIContent defaultScreenOrientation = EditorGUIUtility.TrTextContent(\"Default Orientation*\");\n            public static readonly GUIContent allowedAutoRotateToPortrait = EditorGUIUtility.TrTextContent(\"Portrait\");\n            public static readonly GUIContent allowedAutoRotateToPortraitUpsideDown = EditorGUIUtility.TrTextContent(\"Portrait Upside Down\");\n            public static readonly GUIContent allowedAutoRotateToLandscapeRight = EditorGUIUtility.TrTextContent(\"Landscape Right\");\n            public static readonly GUIContent allowedAutoRotateToLandscapeLeft = EditorGUIUtility.TrTextContent(\"Landscape Left\");\n            public static readonly GUIContent UIRequiresFullScreen = EditorGUIUtility.TrTextContent(\"Requires Fullscreen\");\n            public static readonly GUIContent UIStatusBarHidden = EditorGUIUtility.TrTextContent(\"Status Bar Hidden\");\n            public static readonly GUIContent UIStatusBarStyle = EditorGUIUtility.TrTextContent(\"Status Bar Style\");\n            public static readonly GUIContent fullscreenMode = EditorGUIUtility.TrTextContent(\"Fullscreen Mode \", \" Not all platforms support all modes\");\n            public static readonly GUIContent exclusiveFullscreen = EditorGUIUtility.TrTextContent(\"Exclusive Fullscreen\");\n            public static readonly GUIContent fullscreenWindow = EditorGUIUtility.TrTextContent(\"Fullscreen Window\");\n            public static readonly GUIContent maximizedWindow = EditorGUIUtility.TrTextContent(\"Maximized Window\");\n            public static readonly GUIContent windowed = EditorGUIUtility.TrTextContent(\"Windowed\");\n            public static readonly GUIContent displayResolutionDialogEnabledLabel = EditorGUIUtility.TrTextContent(\"Enabled (Deprecated)\");\n            public static readonly GUIContent displayResolutionDialogHiddenLabel = EditorGUIUtility.TrTextContent(\"Hidden by Default (Deprecated)\");\n            public static readonly GUIContent displayResolutionDialogDeprecationWarning = EditorGUIUtility.TrTextContent(\"The Display Resolution Dialog has been deprecated and will be removed in a future version.\");\n            public static readonly GUIContent visibleInBackground = EditorGUIUtility.TrTextContent(\"Visible In Background\");\n            public static readonly GUIContent allowFullscreenSwitch = EditorGUIUtility.TrTextContent(\"Allow Fullscreen Switch*\");\n            public static readonly GUIContent useFlipModelSwapChain = EditorGUIUtility.TrTextContent(\"Use DXGI flip model swapchain for D3D11\", \"Disable this option to fallback to Windows 7-style BitBlt model. Using flip model (leaving this option enabled) ensures the best performance. This setting affects only D3D11 graphics API.\");\n            public static readonly GUIContent flipModelSwapChainWarning = EditorGUIUtility.TrTextContent(\"Disabling DXGI flip model swapchain will result in Unity falling back to the slower and less efficient BitBlt model. See documentation for more information.\");\n            public static readonly GUIContent use32BitDisplayBuffer = EditorGUIUtility.TrTextContent(\"Use 32-bit Display Buffer*\", \"If set Display Buffer will be created to hold 32-bit color values. Use it only if you see banding, as it has performance implications.\");\n            public static readonly GUIContent disableDepthAndStencilBuffers = EditorGUIUtility.TrTextContent(\"Disable Depth and Stencil*\");\n            public static readonly GUIContent preserveFramebufferAlpha = EditorGUIUtility.TrTextContent(\"Render Over Native UI*\", \"Enable this option ONLY if you want Unity to render on top of the native Android or iOS UI.\");\n            public static readonly GUIContent actionOnDotNetUnhandledException = EditorGUIUtility.TrTextContent(\"On .Net UnhandledException*\", \"This is non-functional. The option is deprecated and will be removed in a future release.\");\n            public static readonly GUIContent actionOnDotNetUnhandledExceptionDeprecation = EditorGUIUtility.TrTextContent(\"On .Net UnhandledException* is non-functional. This option is deprecated and will be removed in a future release.\");\n            public static readonly GUIContent logObjCUncaughtExceptions = EditorGUIUtility.TrTextContent(\"Log Obj-C Uncaught Exceptions*\");\n            public static readonly GUIContent enableCrashReportAPI = EditorGUIUtility.TrTextContent(\"Enable CrashReport API*\");\n            public static readonly GUIContent activeColorSpace = EditorGUIUtility.TrTextContent(\"Color Space*\");\n            public static readonly GUIContent unsupportedMSAAFallback = EditorGUIUtility.TrTextContent(\"MSAA Fallback\");\n            public static readonly GUIContent colorGamut = EditorGUIUtility.TrTextContent(\"Color Gamut*\");\n            public static readonly GUIContent colorGamutForMac = EditorGUIUtility.TrTextContent(\"Color Gamut For Mac*\");\n            public static readonly GUIContent metalForceHardShadows = EditorGUIUtility.TrTextContent(\"Force hard shadows on Metal*\");\n            public static readonly GUIContent metalAPIValidation = EditorGUIUtility.TrTextContent(\"Metal API Validation*\", \"When enabled, additional binding state validation is applied.\");\n            public static readonly GUIContent metalFramebufferOnly = EditorGUIUtility.TrTextContent(\"Metal Write-Only Backbuffer*\", \"Set framebufferOnly flag on backbuffer. This prevents readback from backbuffer but enables some driver optimizations.\");\n            public static readonly GUIContent framebufferDepthMemorylessMode = EditorGUIUtility.TrTextContent(\"Memoryless Depth*\", \"Memoryless mode of framebuffer depth\");\n            public static readonly GUIContent[] memorylessModeNames = { EditorGUIUtility.TrTextContent(\"Unused\"), EditorGUIUtility.TrTextContent(\"Forced\"), EditorGUIUtility.TrTextContent(\"Automatic\") };\n            public static readonly GUIContent vulkanEnableSetSRGBWrite = EditorGUIUtility.TrTextContent(\"SRGB Write Mode*\", \"If set, enables Graphics.SetSRGBWrite() for toggling sRGB write mode during the frame but may decrease performance especially on tiled GPUs.\");\n            public static readonly GUIContent vulkanNumSwapchainBuffers = EditorGUIUtility.TrTextContent(\"Number of swapchain buffers*\");\n            public static readonly GUIContent vulkanEnableLateAcquireNextImage = EditorGUIUtility.TrTextContent(\"Acquire swapchain image late as possible*\", \"If set, renders to a staging image to delay acquiring the swapchain buffer.\");\n            public static readonly GUIContent vulkanEnableCommandBufferRecycling = EditorGUIUtility.TrTextContent(\"Recycle command buffers*\", \"When enabled, command buffers are recycled after they have been executed as opposed to being freed.\");\n            public static readonly GUIContent mTRendering = EditorGUIUtility.TrTextContent(\"Multithreaded Rendering*\");\n            public static readonly GUIContent staticBatching = EditorGUIUtility.TrTextContent(\"Static Batching\");\n            public static readonly GUIContent dynamicBatching = EditorGUIUtility.TrTextContent(\"Dynamic Batching\", \"Toggle Dynamic Batching. Note: Sprites are always dynamically batched.\");\n            public static readonly GUIContent spriteBatchingVertexThreshold = EditorGUIUtility.TrTextContent(\"Sprite Batching Threshold\", \"Maximum vertex threshold of a sprite to be batched. Any sprite with vertex count above this value is not batched.\");\n            public static readonly GUIContent spriteBatchingMaxVertexCount = EditorGUIUtility.TrTextContent(\"Sprite Batching Max Vertex Count\", \"Maximum vertex count per batch.\");\n            public static readonly GUIContent graphicsJobsNonExperimental = EditorGUIUtility.TrTextContent(\"Graphics Jobs\");\n            public static readonly GUIContent graphicsJobsExperimental = EditorGUIUtility.TrTextContent(\"Graphics Jobs (Experimental)\");\n            public static readonly GUIContent graphicsJobsMode = EditorGUIUtility.TrTextContent(\"Graphics Jobs Mode\");\n            public static readonly GUIContent graphicsJobsSyncAfterKick = EditorGUIUtility.TrTextContent(\"Sync after kick (fallback)\", \"This prevents graphics jobs from running in parallel to the render thread. Enable this if you see artifacts with graphics jobs.\");\n            public static readonly GUIContent applicationIdentifierWarning = EditorGUIUtility.TrTextContent(\"Invalid characters have been removed from the Application Identifier.\");\n            public static readonly GUIContent applicationIdentifierError = EditorGUIUtility.TrTextContent(\"The Application Identifier must follow the convention 'com.YourCompanyName.YourProductName' and must contain only alphanumeric and hyphen characters.\");\n            public static readonly GUIContent packageNameError = EditorGUIUtility.TrTextContent(\"The Package Name must follow the convention 'com.YourCompanyName.YourProductName' and must contain only alphanumeric and underscore characters. Each segment must start with an alphabetical character.\");\n            public static readonly GUIContent applicationBuildNumber = EditorGUIUtility.TrTextContent(\"Build\");\n            public static readonly GUIContent appleDeveloperTeamID = EditorGUIUtility.TrTextContent(\"iOS Developer Team ID\", \"Developers can retrieve their Team ID by visiting the Apple Developer site under Account > Membership.\");\n            public static readonly GUIContent gcIncremental = EditorGUIUtility.TrTextContent(\"Use incremental GC*\", \"With incremental Garbage Collection, the Garbage Collector will try to time-slice the collection task into multiple steps, to avoid long GC times preventing content from running smoothly.\");\n            public static readonly GUIContent accelerometerFrequency = EditorGUIUtility.TrTextContent(\"Accelerometer Frequency*\");\n            public static readonly GUIContent cameraUsageDescription = EditorGUIUtility.TrTextContent(\"Camera Usage Description*\", \"String shown to the user when requesting permission to use the device camera. Written to the NSCameraUsageDescription field in Xcode project's info.plist file\");\n            public static readonly GUIContent locationUsageDescription = EditorGUIUtility.TrTextContent(\"Location Usage Description*\", \"String shown to the user when requesting permission to access the device location. Written to the NSLocationWhenInUseUsageDescription field in Xcode project's info.plist file.\");\n            public static readonly GUIContent microphoneUsageDescription = EditorGUIUtility.TrTextContent(\"Microphone Usage Description*\", \"String shown to the user when requesting to use the device microphone. Written to the NSMicrophoneUsageDescription field in Xcode project's info.plist file\");\n            public static readonly GUIContent muteOtherAudioSources = EditorGUIUtility.TrTextContent(\"Mute Other Audio Sources*\");\n            public static readonly GUIContent prepareIOSForRecording = EditorGUIUtility.TrTextContent(\"Prepare iOS for Recording\");\n            public static readonly GUIContent forceIOSSpeakersWhenRecording = EditorGUIUtility.TrTextContent(\"Force iOS Speakers when Recording\");\n            public static readonly GUIContent UIRequiresPersistentWiFi = EditorGUIUtility.TrTextContent(\"Requires Persistent WiFi*\");\n            public static readonly GUIContent insecureHttpOption = EditorGUIUtility.TrTextContent(\"Allow downloads over HTTP*\", \"\");\n            public static readonly GUIContent insecureHttpWarning = EditorGUIUtility.TrTextContent(\"Plain text HTTP connections are not secure and can make your application vulnerable to attacks.\");\n            public static readonly GUIContent[] insecureHttpOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Not allowed\"),\n                EditorGUIUtility.TrTextContent(\"Allowed in development builds\"),\n                EditorGUIUtility.TrTextContent(\"Always allowed\"),\n            };\n\n            public static readonly GUIContent autoGraphicsAPI = EditorGUIUtility.TrTextContent(\"Auto Graphics API\");\n            public static readonly GUIContent autoGraphicsAPIForWindows = EditorGUIUtility.TrTextContent(\"Auto Graphics API for Windows\");\n            public static readonly GUIContent autoGraphicsAPIForMac = EditorGUIUtility.TrTextContent(\"Auto Graphics API for Mac\");\n            public static readonly GUIContent autoGraphicsAPIForLinux = EditorGUIUtility.TrTextContent(\"Auto Graphics API for Linux\");\n\n            public static readonly GUIContent iOSURLSchemes = EditorGUIUtility.TrTextContent(\"Supported URL schemes*\");\n            public static readonly GUIContent iOSExternalAudioInputNotSupported = EditorGUIUtility.TrTextContent(\"Audio input from Bluetooth microphones is not supported when Mute Other Audio Sources is off.\");\n            public static readonly GUIContent require31 = EditorGUIUtility.TrTextContent(\"Require ES3.1\");\n            public static readonly GUIContent requireAEP = EditorGUIUtility.TrTextContent(\"Require ES3.1+AEP\");\n            public static readonly GUIContent require32 = EditorGUIUtility.TrTextContent(\"Require ES3.2\");\n            public static readonly GUIContent skinOnGPU = EditorGUIUtility.TrTextContent(\"GPU Skinning*\", \"Calculate mesh skinning and blend shapes on the GPU via shaders\");\n            public static readonly GUIContent[] meshDeformations = { EditorGUIUtility.TrTextContent(\"CPU\"), EditorGUIUtility.TrTextContent(\"GPU\"), EditorGUIUtility.TrTextContent(\"GPU (Batched)\") };\n            public static readonly GUIContent scriptingDefineSymbols = EditorGUIUtility.TrTextContent(\"Scripting Define Symbols\", \"Preprocessor defines passed to the C# script compiler.\");\n            public static readonly GUIContent additionalCompilerArguments = EditorGUIUtility.TrTextContent(\"Additional Compiler Arguments\", \"Additional arguments passed to the C# script compiler.\");\n            public static readonly GUIContent scriptingDefineSymbolsApply = EditorGUIUtility.TrTextContent(\"Apply\");\n            public static readonly GUIContent scriptingDefineSymbolsApplyRevert = EditorGUIUtility.TrTextContent(\"Revert\");\n            public static readonly GUIContent scriptingDefineSymbolsCopyDefines = EditorGUIUtility.TrTextContent(\"Copy Defines\", \"Copy applied defines\");\n            public static readonly GUIContent suppressCommonWarnings = EditorGUIUtility.TrTextContent(\"Suppress Common Warnings\", \"Suppresses C# warnings CS0169, CS0649, and CS0282.\");\n            public static readonly GUIContent scriptingBackend = EditorGUIUtility.TrTextContent(\"Scripting Backend\");\n            public static readonly GUIContent managedStrippingLevel = EditorGUIUtility.TrTextContent(\"Managed Stripping Level\", \"If scripting backend is IL2CPP, managed stripping can't be disabled.\");\n            public static readonly GUIContent il2cppCompilerConfiguration = EditorGUIUtility.TrTextContent(\"C++ Compiler Configuration\");\n            public static readonly GUIContent il2cppCodeGeneration = EditorGUIUtility.TrTextContent(\"IL2CPP Code Generation\", \"Determines whether IL2CPP should generate code optimized for runtime performance or build size/iteration.\");\n            public static readonly GUIContent[] il2cppCodeGenerationNames =  new GUIContent[] { EditorGUIUtility.TrTextContent(\"Optimize for runtime speed\"), EditorGUIUtility.TrTextContent(\"Optimize for code size and build time\") };\n            public static readonly GUIContent il2cppStacktraceInformation = EditorGUIUtility.TrTextContent(\"IL2CPP Stacktrace Information\", \"Which information to include in stack traces. Including the file name and line number may increase build size.\");\n            public static readonly GUIContent scriptingMono2x = EditorGUIUtility.TrTextContent(\"Mono\");\n            public static readonly GUIContent scriptingIL2CPP = EditorGUIUtility.TrTextContent(\"IL2CPP\");\n            public static readonly GUIContent scriptingCoreCLR = EditorGUIUtility.TrTextContent(\"CoreCLR\");\n            public static readonly GUIContent scriptingDefault = EditorGUIUtility.TrTextContent(\"Default\");\n            public static readonly GUIContent strippingDisabled = EditorGUIUtility.TrTextContent(\"Disabled\");\n            public static readonly GUIContent strippingMinimal = EditorGUIUtility.TrTextContent(\"Minimal\");\n            public static readonly GUIContent strippingLow = EditorGUIUtility.TrTextContent(\"Low\");\n            public static readonly GUIContent strippingMedium = EditorGUIUtility.TrTextContent(\"Medium\");\n            public static readonly GUIContent strippingHigh = EditorGUIUtility.TrTextContent(\"High\");\n            public static readonly GUIContent apiCompatibilityLevel = EditorGUIUtility.TrTextContent(\"Api Compatibility Level*\");\n            public static readonly GUIContent apiCompatibilityLevel_NET_2_0 = EditorGUIUtility.TrTextContent(\".NET 2.0\");\n            public static readonly GUIContent apiCompatibilityLevel_NET_2_0_Subset = EditorGUIUtility.TrTextContent(\".NET 2.0 Subset\");\n            public static readonly GUIContent apiCompatibilityLevel_NET_4_6 = EditorGUIUtility.TrTextContent(\".NET 4.x\");\n            public static readonly GUIContent apiCompatibilityLevel_NET_Standard_2_0 = EditorGUIUtility.TrTextContent(\".NET Standard 2.0\");\n            public static readonly GUIContent apiCompatibilityLevel_NET_FW_Unity = EditorGUIUtility.TrTextContent(\".NET Framework\");\n            public static readonly GUIContent apiCompatibilityLevel_NET_Standard = EditorGUIUtility.TrTextContent(\".NET Standard 2.1\");\n            public static readonly GUIContent editorAssembliesCompatibilityLevel = EditorGUIUtility.TrTextContent(\"Editor Assemblies Compatibility Level*\");\n            public static readonly GUIContent editorAssembliesCompatibilityLevel_Default = EditorGUIUtility.TrTextContent(\"Default (.NET Framework)\");\n            public static readonly GUIContent editorAssembliesCompatibilityLevel_NET_Framework = EditorGUIUtility.TrTextContent(\".NET Framework\");\n            public static readonly GUIContent editorAssembliesCompatibilityLevel_NET_Standard = EditorGUIUtility.TrTextContent(\".NET Standard\");\n            public static readonly GUIContent scriptCompilationTitle = EditorGUIUtility.TrTextContent(\"Script Compilation\");\n            public static readonly GUIContent allowUnsafeCode = EditorGUIUtility.TrTextContent(\"Allow 'unsafe' Code\", \"Allow compilation of unsafe code for predefined assemblies (Assembly-CSharp.dll, etc.)\");\n            public static readonly GUIContent useDeterministicCompilation = EditorGUIUtility.TrTextContent(\"Use Deterministic Compilation\", \"Compile with -deterministic compilation flag\");\n            public static readonly GUIContent activeInputHandling = EditorGUIUtility.TrTextContent(\"Active Input Handling*\");\n            public static readonly GUIContent[] activeInputHandlingOptions = new GUIContent[] { EditorGUIUtility.TrTextContent(\"Input Manager (Old)\"), EditorGUIUtility.TrTextContent(\"Input System Package (New)\"), EditorGUIUtility.TrTextContent(\"Both\") };\n            public static readonly GUIContent activeInputHandlingDeprecationError = EditorGUIUtility.TrTextContent(\"The Input Manager is a legacy feature and not recommended for new projects. For new projects you should use the Input System Package.\");\n            public static readonly GUIContent activeInputHandlingError = EditorGUIUtility.TrTextContent(\"The Active Input Handling is invalid. To use Input System Package (New) or Both, install the Input System package. Otherwise set the Active Input Handling to Input Manager (Old).\");\n            public static readonly GUIContent normalMapEncodingLabel = EditorGUIUtility.TrTextContent(\"Normal Map Encoding\");\n            public static readonly GUIContent[] normalMapEncodingNames = { EditorGUIUtility.TrTextContent(\"XYZ\"), EditorGUIUtility.TrTextContent(\"DXT5nm-style\") };\n            public static readonly GUIContent lightmapEncodingLabel = EditorGUIUtility.TrTextContent(\"Lightmap Encoding\", \"Affects the encoding scheme and compression format of the lightmaps.\");\n            public static readonly GUIContent[] lightmapEncodingNames = { EditorGUIUtility.TrTextContent(\"Low Quality\"), EditorGUIUtility.TrTextContent(\"Normal Quality\"), EditorGUIUtility.TrTextContent(\"High Quality\") };\n            public static readonly GUIContent hdrCubemapEncodingLabel = EditorGUIUtility.TrTextContent(\"HDR Cubemap Encoding\", \"Determines which encoding scheme Unity uses to encode HDR cubemaps.\");\n            public static readonly GUIContent[] hdrCubemapEncodingNames = { EditorGUIUtility.TrTextContent(\"Low Quality\"), EditorGUIUtility.TrTextContent(\"Normal Quality\"), EditorGUIUtility.TrTextContent(\"High Quality\") };\n            public static readonly GUIContent lightmapStreamingEnabled = EditorGUIUtility.TrTextContent(\"Lightmap Streaming\", \"Only load larger lightmap mipmap levels as needed to render the current game cameras. Requires texture mipmap streaming to be enabled in quality settings. This value is applied to the light map textures as they are generated.\");\n            public static readonly GUIContent lightmapStreamingPriority = EditorGUIUtility.TrTextContent(\"Streaming Priority\", \"Lightmap mipmap streaming priority when there's contention for resources. Positive numbers represent higher priority. Valid range is -128 to 127. This value is applied to the light map textures as they are generated.\");\n            public static readonly GUIContent legacyClampBlendShapeWeights = EditorGUIUtility.TrTextContent(\"Clamp BlendShapes (Deprecated)*\", \"If set, the range of BlendShape weights in SkinnedMeshRenderers will be clamped.\");\n            public static readonly GUIContent virtualTexturingSupportEnabled = EditorGUIUtility.TrTextContent(\"Virtual Texturing (Experimental)*\", \"Enable Virtual Texturing. This feature is experimental and not ready for production use. Changing this value requires an Editor restart.\");\n            public static readonly GUIContent virtualTexturingUnsupportedPlatformWarning = EditorGUIUtility.TrTextContent(\"The current target platform does not support Virtual Texturing. To build for this platform, uncheck Enable Virtual Texturing.\");\n            public static readonly GUIContent shaderPrecisionModel = EditorGUIUtility.TrTextContent(\"Shader Precision Model*\", \"Controls the default sampler precision and the definition of HLSL half.\");\n            public static readonly GUIContent[] shaderPrecisionModelOptions = { EditorGUIUtility.TrTextContent(\"Platform Default\"), EditorGUIUtility.TrTextContent(\"Unified\") };\n            public static readonly GUIContent stereo360CaptureCheckbox = EditorGUIUtility.TrTextContent(\"360 Stereo Capture*\");\n            public static readonly GUIContent forceSRGBBlit = EditorGUIUtility.TrTextContent(\"Force SRGB blit\", \"Force SRGB blit for Linear color space.\");\n            public static readonly GUIContent notApplicableInfo = EditorGUIUtility.TrTextContent(\"Not applicable for this platform.\");\n            public static readonly GUIContent loadStoreDebugModeCheckbox = EditorGUIUtility.TrTextContent(\"Load/Store Action Debug Mode\", \"Initializes Framebuffer such that errors in the load/store actions will be visually apparent. (Removed in Release Builds)\");\n            public static readonly GUIContent loadStoreDebugModeEditorOnlyCheckbox = EditorGUIUtility.TrTextContent(\"Editor Only\", \"Load/Store Action Debug Mode will only affect the Editor\");\n            public static readonly GUIContent allowHDRDisplay = EditorGUIUtility.TrTextContent(\"Allow HDR Display Output*\", \"Enable the use of HDR displays and include all the resources required for them to function correctly.\");\n            public static readonly GUIContent useHDRDisplay = EditorGUIUtility.TrTextContent(\"Use HDR Display Output*\", \"Checks if the main display supports HDR and if it does, switches to HDR output at the start of the application.\");\n            public static readonly GUIContent hdrOutputRequireHDRRenderingWarning = EditorGUIUtility.TrTextContent(\"The active Render Pipeline does not have HDR enabled. Enable HDR in the Render Pipeline Asset to see the changes.\");\n            public static readonly GUIContent graphicsAPIDeprecationMessage = EditorGUIUtility.TrTextContent(\"There are select Graphics API included that are deprecated and will be removed in a future version. For more information, refer to the Graphics API documentation.\");\n\n            public static readonly GUIContent captureStartupLogs = EditorGUIUtility.TrTextContent(\"Capture Startup Logs\", \"Capture startup logs for later processing (e.g., by com.unity.logging\");\n            public static readonly string undoChangedBatchingString                 = L10n.Tr(\"Changed Batching Settings\");\n            public static readonly string undoChangedGraphicsAPIString              = L10n.Tr(\"Changed Graphics API Settings\");\n            public static readonly string undoChangedScriptingDefineString          = L10n.Tr(\"Changed Scripting Define Settings\");\n            public static readonly string undoChangedGraphicsJobsString             = L10n.Tr(\"Changed Graphics Jobs Setting\");\n            public static readonly string undoChangedGraphicsJobModeString          = L10n.Tr(\"Changed Graphics Job Mode Setting\");\n            public static readonly string changeColorSpaceString                    = L10n.Tr(\"Changing the color space may take a significant amount of time.\");\n            public static readonly string undoChangedPlatformShaderChunkSizeString  = L10n.Tr(\"Changed Shader Chunk Size Platform Setting\");\n            public static readonly string undoChangedPlatformShaderChunkCountString = L10n.Tr(\"Changed Shader Chunk Count Platform Setting\");\n            public static readonly string undoChangedDefaultShaderChunkSizeString   = L10n.Tr(\"Changed Shader Chunk Size Default Setting\");\n            public static readonly string undoChangedDefaultShaderChunkCountString  = L10n.Tr(\"Changed Shader Chunk Count Default Setting\");\n\n            public static readonly string globalPlayerSettingsInfo =\n            L10n.Tr(\"Editing these global player settings will not affect the current state of the project, because the active build profile is using its own customized player settings. Edit the build profile to change them.\");\n            public static readonly string globalPlayerSettingsInfoButton = L10n.Tr(\"Edit Build Profile\");\n        }\n\n        internal class RecompileReason\n        {\n            public static readonly string scriptingDefineSymbolsModified             = L10n.Tr(\"Scripting define symbols setting modified\");\n            public static readonly string suppressCommonWarningsModified             = L10n.Tr(\"Suppress common warnings setting modified\");\n            public static readonly string allowUnsafeCodeModified                    = L10n.Tr(\"Allow 'unsafe' code setting modified\");\n            public static readonly string apiCompatibilityLevelModified              = L10n.Tr(\"API Compatibility level modified\");\n            public static readonly string editorAssembliesCompatibilityLevelModified = L10n.Tr(\"Editor Assemblies Compatibility level modified\");\n            public static readonly string useDeterministicCompilationModified        = L10n.Tr(\"Use deterministic compilation modified\");\n            public static readonly string additionalCompilerArgumentsModified        = L10n.Tr(\"Additional compiler arguments modified\");\n            public static readonly string activeBuildTargetGroupModified             = L10n.Tr(\"Active build target group modified\");\n\n            public static readonly string presetChanged = L10n.Tr(\"Preset changed\");\n        }\n\n        PlayerSettingsSplashScreenEditor m_SplashScreenEditor;\n        PlayerSettingsSplashScreenEditor splashScreenEditor\n        {\n            get\n            {\n                if (m_SplashScreenEditor == null)\n                    m_SplashScreenEditor = new PlayerSettingsSplashScreenEditor(this);\n                return m_SplashScreenEditor;\n            }\n        }\n\n        PlayerSettingsIconsEditor m_IconsEditor;\n        PlayerSettingsIconsEditor iconsEditor\n        {\n            get\n            {\n                if (m_IconsEditor == null)\n                    m_IconsEditor = new PlayerSettingsIconsEditor(this);\n                return m_IconsEditor;\n            }\n        }\n\n        private static MeshDeformation[] m_MeshDeformations = { MeshDeformation.CPU, MeshDeformation.GPU, MeshDeformation.GPUBatched };\n\n        internal static void SyncEditors(BuildTarget target)\n        {\n            foreach(var editor in s_activeEditors)\n                editor.OnSyncEditor(target);\n        }\n\n        // Section and tab selection state\n\n        SavedInt m_SelectedSection = new SavedInt(\"PlayerSettings.ShownSection\", -1);\n\n        BuildPlatform[] validPlatforms;\n        NamedBuildTarget lastNamedBuildTarget;\n\n        // il2cpp\n        SerializedProperty m_StripEngineCode;\n\n        // macOS\n        SerializedProperty m_ApplicationBundleVersion;\n\n        // vulkan\n        SerializedProperty m_VulkanNumSwapchainBuffers;\n        SerializedProperty m_VulkanEnableLateAcquireNextImage;\n        SerializedProperty m_VulkanEnableCommandBufferRecycling;\n        SerializedProperty m_VulkanEnableSetSRGBWrite;\n\n        // iOS, tvOS\n#pragma warning disable 169\n        SerializedProperty m_IPhoneApplicationDisplayName;\n\n        SerializedProperty m_CameraUsageDescription;\n        SerializedProperty m_LocationUsageDescription;\n        SerializedProperty m_MicrophoneUsageDescription;\n\n        SerializedProperty m_IPhoneScriptCallOptimization;\n\n        SerializedProperty m_DefaultScreenOrientation;\n        SerializedProperty m_AllowedAutoRotateToPortrait;\n        SerializedProperty m_AllowedAutoRotateToPortraitUpsideDown;\n        SerializedProperty m_AllowedAutoRotateToLandscapeRight;\n        SerializedProperty m_AllowedAutoRotateToLandscapeLeft;\n        SerializedProperty m_UseOSAutoRotation;\n        SerializedProperty m_Use32BitDisplayBuffer;\n        SerializedProperty m_PreserveFramebufferAlpha;\n        SerializedProperty m_DisableDepthAndStencilBuffers;\n\n        SerializedProperty m_AndroidProfiler;\n\n        SerializedProperty m_UIRequiresPersistentWiFi;\n        SerializedProperty m_UIStatusBarHidden;\n        SerializedProperty m_UIRequiresFullScreen;\n        SerializedProperty m_UIStatusBarStyle;\n\n        SerializedProperty m_InsecureHttpOption;\n        SerializedProperty m_SubmitAnalytics;\n\n        SerializedProperty m_IOSURLSchemes;\n\n        SerializedProperty m_AccelerometerFrequency;\n        SerializedProperty m_MuteOtherAudioSources;\n        SerializedProperty m_PrepareIOSForRecording;\n        SerializedProperty m_ForceIOSSpeakersWhenRecording;\n\n        SerializedProperty m_EnableInternalProfiler;\n        SerializedProperty m_ActionOnDotNetUnhandledException;\n        SerializedProperty m_LogObjCUncaughtExceptions;\n        SerializedProperty m_EnableCrashReportAPI;\n\n        SerializedProperty m_SuppressCommonWarnings;\n        SerializedProperty m_AllowUnsafeCode;\n        SerializedProperty m_GCIncremental;\n\n        SerializedProperty m_OverrideDefaultApplicationIdentifier;\n        SerializedProperty m_ApplicationIdentifier;\n\n        // General\n        SerializedProperty m_CompanyName;\n        SerializedProperty m_ProductName;\n\n        // Cursor\n        SerializedProperty m_DefaultCursor;\n        SerializedProperty m_CursorHotspot;\n\n        // Screen\n        SerializedProperty m_DefaultScreenWidth;\n        SerializedProperty m_DefaultScreenHeight;\n\n        SerializedProperty m_ActiveColorSpace;\n        SerializedProperty m_UnsupportedMSAAFallback;\n        SerializedProperty m_StripUnusedMeshComponents;\n        SerializedProperty m_StrictShaderVariantMatching;\n        SerializedProperty m_MipStripping;\n        SerializedProperty m_VertexChannelCompressionMask;\n        SerializedProperty m_MetalAPIValidation;\n        SerializedProperty m_MetalFramebufferOnly;\n        SerializedProperty m_MetalForceHardShadows;\n        SerializedProperty m_FramebufferDepthMemorylessMode;\n\n        SerializedProperty m_DefaultIsNativeResolution;\n        SerializedProperty m_MacRetinaSupport;\n\n        SerializedProperty m_UsePlayerLog;\n        SerializedProperty m_CaptureStartupLogs;\n        SerializedProperty m_KeepLoadedShadersAlive;\n        SerializedProperty m_PreloadedAssets;\n        SerializedProperty m_BakeCollisionMeshes;\n        SerializedProperty m_DedicatedServerOptimizations;\n        SerializedProperty m_ResizableWindow;\n        SerializedProperty m_FullscreenMode;\n        SerializedProperty m_VisibleInBackground;\n        SerializedProperty m_AllowFullscreenSwitch;\n        SerializedProperty m_ForceSingleInstance;\n        SerializedProperty m_UseFlipModelSwapchain;\n\n        SerializedProperty m_RunInBackground;\n\n        SerializedProperty m_SkinOnGPU;\n        SerializedProperty m_MeshDeformation;\n\n        SerializedProperty m_EnableLoadStoreDebugMode;\n\n        // OpenGL ES 3.1+\n        SerializedProperty m_RequireES31;\n        SerializedProperty m_RequireES31AEP;\n        SerializedProperty m_RequireES32;\n\n        SerializedProperty m_LightmapEncodingQuality;\n        SerializedProperty m_HDRCubemapEncodingQuality;\n        SerializedProperty m_LightmapStreamingEnabled;\n        SerializedProperty m_LightmapStreamingPriority;\n\n        SerializedProperty m_EnableOpenGLProfilerGPURecorders;\n\n        SerializedProperty m_EnableFrameTimingStats;\n\n        SerializedProperty m_AllowHDRDisplaySupport;\n        SerializedProperty m_UseHDRDisplay;\n        SerializedProperty m_HDRBitDepth;\n\n        // WebGPU\n        SerializedProperty m_WebGPUSupportEnabled;\n\n        // Legacy\n        SerializedProperty m_LegacyClampBlendShapeWeights;\n        SerializedProperty m_AndroidEnableTango;\n        SerializedProperty m_Enable360StereoCapture;\n\n        SerializedProperty m_VirtualTexturingSupportEnabled;\n        SerializedProperty m_ShaderPrecisionModel;\n\n        // Scripting\n        SerializedProperty m_UseDeterministicCompilation;\n        SerializedProperty m_ScriptingBackend;\n        SerializedProperty m_APICompatibilityLevel;\n        SerializedProperty m_DefaultAPICompatibilityLevel;\n        SerializedProperty m_EditorAssembliesCompatibilityLevel;\n        SerializedProperty m_Il2CppCompilerConfiguration;\n        SerializedProperty m_Il2CppCodeGeneration;\n        SerializedProperty m_Il2CppStacktraceInformation;\n        SerializedProperty m_ScriptingDefines;\n        SerializedProperty m_AdditionalCompilerArguments;\n        SerializedProperty m_StackTraceTypes;\n        SerializedProperty m_ManagedStrippingLevel;\n        SerializedProperty m_ActiveInputHandler;\n\n        SerializedProperty m_SpriteBatchVertexThreshold;\n        SerializedProperty m_SpriteBatchMaxVertexCount;\n\n\n        // Embedded Linux specific\n        SerializedProperty m_ForceSRGBBlit;\n\n        // Localization Cache\n        string m_LocalizedTargetName;\n\n        // reorderable lists of graphics devices, per platform\n        Dictionary<BuildTarget, ReorderableList> m_GraphicsDeviceLists = new Dictionary<BuildTarget, ReorderableList>();\n        ReorderableList m_ColorGamutList;\n\n        int scriptingDefinesControlID = 0;\n\n        int serializedActiveInputHandler = 0;\n        string[] serializedAdditionalCompilerArguments;\n        bool serializedSuppressCommonWarnings = true;\n        bool serializedAllowUnsafeCode = false;\n        string serializedScriptingDefines;\n        bool serializedUseDeterministicCompilation;\n\n        List<string> scriptingDefinesList;\n        bool hasScriptingDefinesBeenModified;\n        ReorderableList scriptingDefineSymbolsList;\n\n        List<string> additionalCompilerArgumentsList;\n        bool hasAdditionalCompilerArgumentsBeenModified;\n        ReorderableList additionalCompilerArgumentsReorderableList;\n\n        ISettingEditorExtension[] m_SettingsExtensions;\n        private HashSet<string> m_Reasons = new HashSet<string>();\n\n        // Section animation state\n        const int kNumberGUISections = 7;\n        List<AnimBool> m_SectionAnimators = new List<AnimBool>(kNumberGUISections);\n        readonly AnimBool m_ShowDefaultIsNativeResolution = new AnimBool();\n        readonly AnimBool m_ShowResolution = new AnimBool();\n        private static Texture2D s_WarningIcon;\n\n        // Preset check\n        bool isPresetWindowOpen = false;\n        bool hasPresetWindowClosed = false;\n\n        /// <summary>\n        /// Internal callback set by the build profile window when tracking\n        /// changes to settings not represented by a serialized property.\n        /// </summary>\n        Action<SerializedObject> m_OnTrackSerializedObjectValueChanged;\n\n        internal bool IsPreset() => playerSettingsType == PlayerSettingsType.Preset;\n\n        internal enum PlayerSettingsType\n        {\n            Global,\n            Preset,\n            ActiveBuildProfile,\n            NonActiveBuildProfile\n        }\n        internal PlayerSettingsType playerSettingsType = PlayerSettingsType.Global;\n        internal bool IsBuildProfileEditor() => playerSettingsType == PlayerSettingsType.ActiveBuildProfile || playerSettingsType == PlayerSettingsType.NonActiveBuildProfile;\n        internal bool IsActivePlayerSettingsEditor() => (playerSettingsType == PlayerSettingsType.Global && !BuildProfileContext.ProjectHasActiveProfileWithPlayerSettings()) || playerSettingsType == PlayerSettingsType.ActiveBuildProfile;\n\n        internal void OnTargetObjectChangedDirectly() => m_OnTrackSerializedObjectValueChanged?.Invoke(serializedObject);\n\n        internal void OnSyncEditor(BuildTarget target)\n        {\n            SyncColorGamuts();\n\n            if (target == BuildTarget.NoTarget)\n                return;\n\n            SyncPlatformAPIsList(target);\n        }\n\n        const string kSelectedPlatform = \"PlayerSettings.SelectedPlatform\";\n\n        /// <summary>\n        /// Current serialized object target as <see cref=\"PlayerSettings\"/>.\n        /// </summary>\n        PlayerSettings m_CurrentTarget;\n\n        public SerializedProperty FindPropertyAssert(string name)\n        {\n            SerializedProperty property = serializedObject.FindProperty(name);\n            if (property == null)\n                Debug.LogError(\"Failed to find:\" + name);\n            return property;\n        }\n\n        private static List<PlayerSettingsEditor> s_activeEditors = new List<PlayerSettingsEditor>();\n        void OnEnable()\n        {\n            s_activeEditors.Add(this);\n            if (Preset.IsEditorTargetAPreset(target))\n                playerSettingsType = PlayerSettingsType.Preset;\n            validPlatforms = BuildPlatforms.instance.GetValidPlatforms(true).ToArray();\n            m_CurrentTarget = target as PlayerSettings;\n\n            m_StripEngineCode               = FindPropertyAssert(\"stripEngineCode\");\n\n            m_IPhoneScriptCallOptimization  = FindPropertyAssert(\"iPhoneScriptCallOptimization\");\n            m_AndroidProfiler               = FindPropertyAssert(\"AndroidProfiler\");\n            m_CompanyName                   = FindPropertyAssert(\"companyName\");\n            m_ProductName                   = FindPropertyAssert(\"productName\");\n\n            m_DefaultCursor                 = FindPropertyAssert(\"defaultCursor\");\n            m_CursorHotspot                 = FindPropertyAssert(\"cursorHotspot\");\n\n\n            m_UIRequiresFullScreen          = FindPropertyAssert(\"uIRequiresFullScreen\");\n\n            m_UIStatusBarHidden             = FindPropertyAssert(\"uIStatusBarHidden\");\n            m_UIStatusBarStyle              = FindPropertyAssert(\"uIStatusBarStyle\");\n            m_ActiveColorSpace              = FindPropertyAssert(\"m_ActiveColorSpace\");\n            m_UnsupportedMSAAFallback       = FindPropertyAssert(\"unsupportedMSAAFallback\");\n            m_StripUnusedMeshComponents     = FindPropertyAssert(\"StripUnusedMeshComponents\");\n            m_StrictShaderVariantMatching   = FindPropertyAssert(\"strictShaderVariantMatching\");\n            m_MipStripping                  = FindPropertyAssert(\"mipStripping\");\n            m_VertexChannelCompressionMask  = FindPropertyAssert(\"VertexChannelCompressionMask\");\n            m_MetalAPIValidation            = FindPropertyAssert(\"metalAPIValidation\");\n            m_MetalFramebufferOnly          = FindPropertyAssert(\"metalFramebufferOnly\");\n            m_MetalForceHardShadows         = FindPropertyAssert(\"iOSMetalForceHardShadows\");\n            m_FramebufferDepthMemorylessMode = FindPropertyAssert(\"framebufferDepthMemorylessMode\");\n\n            m_OverrideDefaultApplicationIdentifier = FindPropertyAssert(\"overrideDefaultApplicationIdentifier\");\n            m_ApplicationIdentifier         = FindPropertyAssert(\"applicationIdentifier\");\n\n            m_ApplicationBundleVersion      = serializedObject.FindProperty(\"bundleVersion\");\n            if (m_ApplicationBundleVersion == null)\n                m_ApplicationBundleVersion  = FindPropertyAssert(\"iPhoneBundleVersion\");\n\n            m_AccelerometerFrequency        = FindPropertyAssert(\"accelerometerFrequency\");\n\n            m_MuteOtherAudioSources         = FindPropertyAssert(\"muteOtherAudioSources\");\n            m_PrepareIOSForRecording        = FindPropertyAssert(\"Prepare IOS For Recording\");\n            m_ForceIOSSpeakersWhenRecording = FindPropertyAssert(\"Force IOS Speakers When Recording\");\n            m_UIRequiresPersistentWiFi      = FindPropertyAssert(\"uIRequiresPersistentWiFi\");\n            m_InsecureHttpOption            = FindPropertyAssert(\"insecureHttpOption\");\n            m_SubmitAnalytics               = FindPropertyAssert(\"submitAnalytics\");\n\n            m_IOSURLSchemes                 = FindPropertyAssert(\"iOSURLSchemes\");\n\n            m_CameraUsageDescription        = FindPropertyAssert(\"cameraUsageDescription\");\n            m_LocationUsageDescription      = FindPropertyAssert(\"locationUsageDescription\");\n            m_MicrophoneUsageDescription    = FindPropertyAssert(\"microphoneUsageDescription\");\n\n            m_EnableInternalProfiler        = FindPropertyAssert(\"enableInternalProfiler\");\n            m_ActionOnDotNetUnhandledException  = FindPropertyAssert(\"actionOnDotNetUnhandledException\");\n            m_LogObjCUncaughtExceptions     = FindPropertyAssert(\"logObjCUncaughtExceptions\");\n            m_EnableCrashReportAPI          = FindPropertyAssert(\"enableCrashReportAPI\");\n\n            m_SuppressCommonWarnings        = FindPropertyAssert(\"suppressCommonWarnings\");\n            m_AllowUnsafeCode               = FindPropertyAssert(\"allowUnsafeCode\");\n            m_GCIncremental                 = FindPropertyAssert(\"gcIncremental\");\n            m_UseDeterministicCompilation   = FindPropertyAssert(\"useDeterministicCompilation\");\n            m_ScriptingBackend              = FindPropertyAssert(\"scriptingBackend\");\n            m_APICompatibilityLevel         = FindPropertyAssert(\"apiCompatibilityLevelPerPlatform\");\n            m_DefaultAPICompatibilityLevel  = FindPropertyAssert(\"apiCompatibilityLevel\");\n            m_EditorAssembliesCompatibilityLevel = FindPropertyAssert(\"editorAssembliesCompatibilityLevel\");\n            m_Il2CppCompilerConfiguration   = FindPropertyAssert(\"il2cppCompilerConfiguration\");\n            m_Il2CppCodeGeneration          = FindPropertyAssert(\"il2cppCodeGeneration\");\n            m_Il2CppStacktraceInformation   = FindPropertyAssert(\"il2cppStacktraceInformation\");\n            m_ScriptingDefines              = FindPropertyAssert(\"scriptingDefineSymbols\");\n            m_StackTraceTypes               = FindPropertyAssert(\"m_StackTraceTypes\");\n            m_ManagedStrippingLevel         = FindPropertyAssert(\"managedStrippingLevel\");\n            m_ActiveInputHandler            = FindPropertyAssert(\"activeInputHandler\");\n            m_AdditionalCompilerArguments   = FindPropertyAssert(\"additionalCompilerArguments\");\n\n            m_DefaultScreenWidth            = FindPropertyAssert(\"defaultScreenWidth\");\n            m_DefaultScreenHeight           = FindPropertyAssert(\"defaultScreenHeight\");\n            m_RunInBackground               = FindPropertyAssert(\"runInBackground\");\n\n            m_DefaultScreenOrientation              = FindPropertyAssert(\"defaultScreenOrientation\");\n            m_AllowedAutoRotateToPortrait           = FindPropertyAssert(\"allowedAutorotateToPortrait\");\n            m_AllowedAutoRotateToPortraitUpsideDown = FindPropertyAssert(\"allowedAutorotateToPortraitUpsideDown\");\n            m_AllowedAutoRotateToLandscapeRight     = FindPropertyAssert(\"allowedAutorotateToLandscapeRight\");\n            m_AllowedAutoRotateToLandscapeLeft      = FindPropertyAssert(\"allowedAutorotateToLandscapeLeft\");\n            m_UseOSAutoRotation                     = FindPropertyAssert(\"useOSAutorotation\");\n            m_Use32BitDisplayBuffer                 = FindPropertyAssert(\"use32BitDisplayBuffer\");\n            m_PreserveFramebufferAlpha              = FindPropertyAssert(\"preserveFramebufferAlpha\");\n            m_DisableDepthAndStencilBuffers         = FindPropertyAssert(\"disableDepthAndStencilBuffers\");\n\n            m_DefaultIsNativeResolution     = FindPropertyAssert(\"defaultIsNativeResolution\");\n            m_MacRetinaSupport              = FindPropertyAssert(\"macRetinaSupport\");\n            m_UsePlayerLog                  = FindPropertyAssert(\"usePlayerLog\");\n            m_CaptureStartupLogs            = FindPropertyAssert(\"captureStartupLogs\");\n\n            m_KeepLoadedShadersAlive           = FindPropertyAssert(\"keepLoadedShadersAlive\");\n            m_PreloadedAssets                  = FindPropertyAssert(\"preloadedAssets\");\n            m_BakeCollisionMeshes              = FindPropertyAssert(\"bakeCollisionMeshes\");\n            m_DedicatedServerOptimizations     = FindPropertyAssert(\"dedicatedServerOptimizations\");\n            m_ResizableWindow                  = FindPropertyAssert(\"resizableWindow\");\n            m_VulkanNumSwapchainBuffers        = FindPropertyAssert(\"vulkanNumSwapchainBuffers\");\n            m_VulkanEnableLateAcquireNextImage = FindPropertyAssert(\"vulkanEnableLateAcquireNextImage\");\n            m_VulkanEnableCommandBufferRecycling = FindPropertyAssert(\"vulkanEnableCommandBufferRecycling\");\n            m_VulkanEnableSetSRGBWrite         = FindPropertyAssert(\"vulkanEnableSetSRGBWrite\");\n            m_FullscreenMode                   = FindPropertyAssert(\"fullscreenMode\");\n            m_VisibleInBackground              = FindPropertyAssert(\"visibleInBackground\");\n            m_AllowFullscreenSwitch            = FindPropertyAssert(\"allowFullscreenSwitch\");\n            m_SkinOnGPU                        = FindPropertyAssert(\"gpuSkinning\");\n            m_MeshDeformation                  = FindPropertyAssert(\"meshDeformation\");\n            m_ForceSingleInstance              = FindPropertyAssert(\"forceSingleInstance\");\n            m_UseFlipModelSwapchain            = FindPropertyAssert(\"useFlipModelSwapchain\");\n\n            m_AllowHDRDisplaySupport = FindPropertyAssert(\"allowHDRDisplaySupport\");\n            m_UseHDRDisplay = FindPropertyAssert(\"useHDRDisplay\");\n            m_HDRBitDepth = FindPropertyAssert(\"hdrBitDepth\");\n            m_EnableFrameTimingStats = FindPropertyAssert(\"enableFrameTimingStats\");\n            m_EnableOpenGLProfilerGPURecorders = FindPropertyAssert(\"enableOpenGLProfilerGPURecorders\");\n\n            m_RequireES31                   = FindPropertyAssert(\"openGLRequireES31\");\n            m_RequireES31AEP                = FindPropertyAssert(\"openGLRequireES31AEP\");\n            m_RequireES32                   = FindPropertyAssert(\"openGLRequireES32\");\n\n            m_LegacyClampBlendShapeWeights = FindPropertyAssert(\"legacyClampBlendShapeWeights\");\n            m_AndroidEnableTango           = FindPropertyAssert(\"AndroidEnableTango\");\n\n            m_SpriteBatchVertexThreshold = FindPropertyAssert(\"m_SpriteBatchVertexThreshold\");\n            m_SpriteBatchMaxVertexCount = FindPropertyAssert(\"m_SpriteBatchMaxVertexCount\");\n\n            SerializedProperty property = FindPropertyAssert(\"vrSettings\");\n            if (property != null)\n                m_Enable360StereoCapture = property.FindPropertyRelative(\"enable360StereoCapture\");\n\n            m_VirtualTexturingSupportEnabled = FindPropertyAssert(\"virtualTexturingSupportEnabled\");\n            m_ShaderPrecisionModel = FindPropertyAssert(\"shaderPrecisionModel\");\n\n            m_ForceSRGBBlit                 = FindPropertyAssert(\"hmiForceSRGBBlit\");\n\n            var validPlatformsLength = validPlatforms.Length;\n            m_SettingsExtensions = new ISettingEditorExtension[validPlatformsLength];\n            var currentPlatform = 0;\n            var isStandaloneGroup = EditorUserBuildSettings.activeBuildTargetGroup == BuildTargetGroup.Standalone;\n            for (int i = 0; i < validPlatformsLength; i++)\n            {\n                // Show the settings of the active standalone platform for the standalone tab in global player settings\n                var buildTargetGroup = validPlatforms[i].namedBuildTarget.ToBuildTargetGroup();\n                var module = (isStandaloneGroup && buildTargetGroup == BuildTargetGroup.Standalone) ?\n                    ModuleManager.GetTargetStringFromBuildTarget(EditorUserBuildSettings.activeBuildTarget) :\n                    ModuleManager.GetTargetStringFromBuildTargetGroup(buildTargetGroup);\n\n                m_SettingsExtensions[i] = ModuleManager.GetEditorSettingsExtension(module);\n                if (m_SettingsExtensions[i] != null)\n                    m_SettingsExtensions[i].OnEnable(this);\n                if (validPlatforms[i].IsActive())\n                    currentPlatform = i;\n            }\n\n            for (int i = 0; i < kNumberGUISections; i++)\n                m_SectionAnimators.Add(new AnimBool(m_SelectedSection.value == i));\n            SetValueChangeListeners(Repaint);\n\n            splashScreenEditor.OnEnable();\n            iconsEditor.OnEnable();\n\n            // we clear it just to be on the safe side:\n            // we access this cache both from player settings editor and script side when changing api\n            m_GraphicsDeviceLists.Clear();\n\n            var selectedPlatform = SessionState.GetInt(kSelectedPlatform, currentPlatform);\n            if (selectedPlatform < 0)\n                selectedPlatform = 0;\n\n            if (selectedPlatform >= validPlatformsLength)\n                selectedPlatform = validPlatformsLength - 1;\n\n            // Setup initial values to prevent immediate script recompile (or editor restart)\n            NamedBuildTarget namedBuildTarget = validPlatforms[selectedPlatform].namedBuildTarget;\n            serializedActiveInputHandler = m_ActiveInputHandler.intValue;\n            serializedSuppressCommonWarnings = m_SuppressCommonWarnings.boolValue;\n            serializedAllowUnsafeCode = m_AllowUnsafeCode.boolValue;\n            serializedAdditionalCompilerArguments = GetAdditionalCompilerArgumentsForGroup(namedBuildTarget);\n            serializedScriptingDefines = GetScriptingDefineSymbolsForGroup(namedBuildTarget);\n            serializedUseDeterministicCompilation = m_UseDeterministicCompilation.boolValue;\n\n            InitReorderableScriptingDefineSymbolsList(namedBuildTarget);\n            InitReorderableAdditionalCompilerArgumentsList(namedBuildTarget);\n\n            FindPlayerSettingsAttributeSections();\n        }\n\n        void OnDisable()\n        {\n            s_activeEditors.Remove(this);\n            HandlePendingChangesRequiringRecompilation();\n\n            // Ensure script compilation handling is returned to to EditorOnlyPlayerSettings\n            if (!IsPreset())\n                PlayerSettings.isHandlingScriptRecompile = true;\n        }\n\n        /// <summary>\n        /// Configures the player settings editor for a build profile, ensuring only one platform\n        /// tab is displayed in the platform grouping.\n        /// </summary>\n        [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n        internal void ConfigurePlayerSettingsForBuildProfile(\n            SerializedObject serializedProfile,\n            GUID buildProfilePlatformGuid,\n            bool isActiveBuildProfile,\n            Action<SerializedObject> onTrackSerializedObjectChanged)\n        {\n            m_OnTrackSerializedObjectValueChanged = onTrackSerializedObjectChanged;\n            playerSettingsType = isActiveBuildProfile ? PlayerSettingsType.ActiveBuildProfile : PlayerSettingsType.NonActiveBuildProfile;\n\n            // We don't want to show other platform tabs that it's not the build profile one\n            var gotValidPlatform = false;\n            var buildProfileBasePlatformGuid = BuildTargetDiscovery.GetBasePlatformGUID(buildProfilePlatformGuid);\n            var buildProfileSubtarget = BuildTargetDiscovery.GetBuildTargetAndSubtargetFromGUID(buildProfileBasePlatformGuid).Item2;\n            var isBuildProfilePlatformStandalone = buildProfileSubtarget == StandaloneBuildSubtarget.Player;\n            var isBuildProfilePlatformServer = buildProfileSubtarget == StandaloneBuildSubtarget.Server;\n            for (int i = 0; i < validPlatforms.Length; i++)\n            {\n                var buildTarget = validPlatforms[i].defaultTarget;\n                var namedBuildTarget = validPlatforms[i].namedBuildTarget;\n                var basePlatformGuid = BuildTargetDiscovery.GetBasePlatformGUIDFromBuildTarget(namedBuildTarget, buildTarget);\n\n                // Player settings tabs are shown by BuildPlatform/NamedBuildTarget, so we need to compare the\n                // NamedBuildTarget in addition to the base platform guid for standalone and server platforms\n                var isStandalone = namedBuildTarget == NamedBuildTarget.Standalone && isBuildProfilePlatformStandalone;\n                var isServer = namedBuildTarget == NamedBuildTarget.Server && isBuildProfilePlatformServer;\n                if (basePlatformGuid != buildProfileBasePlatformGuid && !(isStandalone || isServer))\n                    continue;\n\n                var copy = (BuildPlatform)validPlatforms[i].Clone();\n                copy.tooltip = string.Empty;\n                validPlatforms[0] = copy;\n                gotValidPlatform = true;\n                break;\n            }\n\n            if (!gotValidPlatform)\n                return;\n\n            Array.Resize(ref validPlatforms, 1);\n            m_SettingsExtensions = new ISettingEditorExtension[1];\n            m_SettingsExtensions[0] = ModuleManager.GetEditorSettingsExtension(buildProfilePlatformGuid);\n            m_SettingsExtensions[0]?.OnEnable(this);\n            m_SettingsExtensions[0]?.ConfigurePlatformProfile(serializedProfile);\n        }\n\n        /// <summary>\n        /// Handles editor update when player setting changes outside the UI. If required,\n        /// schedules background work during the next editor update. After the global player settings\n        /// has changes.\n        /// </summary>\n        internal static void HandlePlayerSettingsChanged(\n            PlayerSettings current, PlayerSettings next,\n            BuildTarget currentBuildTarget, BuildTarget nextBuildTarget)\n        {\n            BuildTargetGroup currentBuildTargetGroup = BuildPipeline.GetBuildTargetGroup(currentBuildTarget);\n            BuildTargetGroup nextBuildTargetGroup = BuildPipeline.GetBuildTargetGroup(nextBuildTarget);\n            bool isLightmapEncodingChanged =\n                current.GetLightmapEncodingQualityForPlatform_Internal(currentBuildTarget)\n                != next.GetLightmapEncodingQualityForPlatform_Internal(nextBuildTarget);\n            bool isHDRCubemapEncodingChanged =\n                current.GetHDRCubemapEncodingQualityForPlatform_Internal(currentBuildTarget)\n                != next.GetHDRCubemapEncodingQualityForPlatform_Internal(nextBuildTarget);\n            bool isLightmapStreamingChanged =\n                (current.GetLightmapStreamingEnabledForPlatformGroup_Internal(currentBuildTargetGroup)\n                    != next.GetLightmapStreamingEnabledForPlatformGroup_Internal(nextBuildTargetGroup))\n                || (current.GetLightmapStreamingPriorityForPlatformGroup_Internal(currentBuildTargetGroup)\n                    != next.GetLightmapStreamingPriorityForPlatformGroup_Internal(nextBuildTargetGroup));\n            bool isShaderPrecisionChanged = PlayerSettings.ShouldSyncShaderPrecisionModel(current, next);\n\n            EditorApplication.delayCall += () =>\n            {\n                if (isHDRCubemapEncodingChanged)\n                {\n                    Lightmapping.OnUpdateHDRCubemapEncoding(nextBuildTargetGroup);\n                }\n\n                if (isLightmapEncodingChanged)\n                {\n                    Lightmapping.OnUpdateLightmapEncoding(nextBuildTargetGroup);\n                }\n\n                if (isLightmapStreamingChanged)\n                {\n                    Lightmapping.OnUpdateLightmapStreaming(nextBuildTargetGroup);\n                }\n\n                if (isShaderPrecisionChanged)\n                {\n                    PlayerSettings.SyncShaderPrecisionModel();\n                }\n            };\n        }\n\n        /// <summary>\n        /// Check if the platform-specific player settings in ISettingsExtensionData on the managed side\n        /// are equal to the corresponding data in the project settings\n        /// </summary>\n        [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n        internal bool IsPlayerSettingsExtensionDataEqualToProjectSettings()\n        {\n            if (m_SettingsExtensions == null || m_SettingsExtensions.Length == 0 || m_SettingsExtensions[0] == null)\n                return false;\n\n            return m_SettingsExtensions[0].IsPlayerSettingsDataEqualToProjectSettings();\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n        internal bool CopyProjectSettingsToPlayerSettingsExtension()\n        {\n            if (m_SettingsExtensions == null || m_SettingsExtensions.Length == 0 || m_SettingsExtensions[0] == null)\n                return false;\n\n            return m_SettingsExtensions[0].CopyProjectSettingsPlayerSettingsToBuildProfile();\n        }\n\n        [RequiredByNativeCode]\n        private static void HandlePendingChangesBeforeEnterPlaymode()\n        {\n            foreach (var editor in s_activeEditors)\n            {\n                editor.HandlePendingChangesRequiringRecompilation();\n            }\n\n            // Handle build profile pending recompilation.\n            BuildProfileContext.HandlePendingChangesBeforeEnterPlaymode();\n        }\n\n        private void HandlePendingChangesRequiringRecompilation()\n        {\n            if (hasScriptingDefinesBeenModified)\n            {\n                if (EditorUtility.DisplayDialog(\"Scripting Define Symbols Have Been Modified\", \"Do you want to apply changes?\", \"Apply\", \"Revert\"))\n                {\n                    SetScriptingDefineSymbolsForGroup(lastNamedBuildTarget, scriptingDefinesList.ToArray());\n                    SetReason(RecompileReason.scriptingDefineSymbolsModified);\n                }\n                else\n                {\n                    InitReorderableScriptingDefineSymbolsList(lastNamedBuildTarget);\n                }\n\n                hasScriptingDefinesBeenModified = false;\n            }\n\n            if (hasAdditionalCompilerArgumentsBeenModified)\n            {\n                if (EditorUtility.DisplayDialog(\"Additional Compiler Arguments Have Been Modified\", \"Do you want to apply changes?\", \"Apply\", \"Revert\"))\n                {\n                    SetAdditionalCompilerArgumentsForGroup(lastNamedBuildTarget, additionalCompilerArgumentsList.ToArray());\n                    SetReason(RecompileReason.additionalCompilerArgumentsModified);\n                }\n                else\n                {\n                    InitReorderableAdditionalCompilerArgumentsList(lastNamedBuildTarget);\n                }\n\n                hasAdditionalCompilerArgumentsBeenModified = false;\n            }\n\n            if (HasReasonToCompile())\n            {\n                serializedObject.ApplyModifiedProperties();\n                RecompileScripts();\n            }\n        }\n\n        public void SetValueChangeListeners(UnityAction action)\n        {\n            for (int i = 0; i < m_SectionAnimators.Count; i++)\n            {\n                m_SectionAnimators[i].valueChanged.RemoveAllListeners();\n                m_SectionAnimators[i].valueChanged.AddListener(action);\n            }\n\n            m_ShowDefaultIsNativeResolution.valueChanged.RemoveAllListeners();\n            m_ShowDefaultIsNativeResolution.valueChanged.AddListener(action);\n\n            m_ShowResolution.valueChanged.RemoveAllListeners();\n            m_ShowResolution.valueChanged.AddListener(action);\n        }\n\n        public override bool UseDefaultMargins()\n        {\n            return false;\n        }\n\n        internal override string targetTitle\n        {\n            get\n            {\n                if (m_LocalizedTargetName == null)\n                    m_LocalizedTargetName = L10n.Tr(target.name);\n                return m_LocalizedTargetName;\n            }\n        }\n\n        private void CheckUpdatePresetSelectorStatus()\n        {\n            if (playerSettingsType != PlayerSettingsType.Global)\n                return;\n\n            bool isOpen = PresetEditorHelper.presetEditorOpen;\n            hasPresetWindowClosed = (isPresetWindowOpen && !isOpen);\n            isPresetWindowOpen = isOpen;\n\n            if (isPresetWindowOpen)\n                PlayerSettings.isHandlingScriptRecompile = false;\n        }\n\n        private void SetReason(string reason)\n        {\n            if (!IsActivePlayerSettingsEditor())\n            {\n                return;\n            }\n\n            m_Reasons.Add(reason);\n        }\n\n        private string ConvertReasonsToString()\n        {\n            var sb = new StringBuilder();\n            foreach (var reason in m_Reasons)\n            {\n                sb.AppendLine(reason);\n            }\n\n            return sb.ToString();\n        }\n\n        private void RecompileScripts()\n        {\n            if (!IsActivePlayerSettingsEditor() || isPresetWindowOpen)\n            {\n                return;\n            }\n\n            var reasons = ConvertReasonsToString();\n            PlayerSettings.RecompileScripts(reasons);\n            m_Reasons.Clear();\n        }\n\n        private bool HasReasonToCompile()\n        {\n            return m_Reasons.Count > 0;\n        }\n\n        private bool SupportsRunInBackground(NamedBuildTarget buildTarget)\n        {\n            return buildTarget == NamedBuildTarget.Standalone || buildTarget == NamedBuildTarget.VisionOS;\n        }\n\n        private void OnPresetSelectorClosed()\n        {\n            hasPresetWindowClosed = false;\n\n            if (playerSettingsType != PlayerSettingsType.Global)\n                return;\n\n            if (HasReasonToCompile())\n            {\n                RecompileScripts();\n            }\n\n            PlayerSettings.isHandlingScriptRecompile = true;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            DisplayBuildProfileHelpBoxIfNeeded();\n\n            var serializedObjectUpdated = serializedObject.UpdateIfRequiredOrScript();\n            EditorGUILayout.BeginVertical();\n            {\n                CommonSettings();\n            }\n            EditorGUILayout.EndVertical();\n\n            EditorGUILayout.Space();\n\n            EditorGUI.BeginChangeCheck();\n            int oldPlatform = SessionState.GetInt(kSelectedPlatform, 0);\n            int selectedPlatformValue = EditorGUILayout.BeginPlatformGrouping(validPlatforms, null);\n            if (selectedPlatformValue != oldPlatform)\n            {\n                SessionState.SetInt(kSelectedPlatform, selectedPlatformValue);\n            }\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                // Awesome hackery to get string from delayed textfield when switching platforms\n                if (EditorGUI.s_DelayedTextEditor.IsEditingControl(scriptingDefinesControlID))\n                {\n                    EditorGUI.EndEditingActiveTextField();\n                    GUIUtility.keyboardControl = 0;\n                    string[] defines = ScriptingDefinesHelper.ConvertScriptingDefineStringToArray(EditorGUI.s_DelayedTextEditor.text);\n                    SetScriptingDefineSymbolsForGroup(validPlatforms[oldPlatform].namedBuildTarget, defines);\n                }\n                // Reset focus when changing between platforms.\n                // If we don't do this, the resolution width/height value will not update correctly when they have the focus\n                GUI.FocusControl(\"\");\n\n                m_SerializedObject.ApplyModifiedPropertiesWithoutUndo();\n            }\n\n            BuildPlatform platform = validPlatforms[selectedPlatformValue];\n\n            if (playerSettingsType == PlayerSettingsType.Global)\n                CheckUpdatePresetSelectorStatus();\n\n            if (!IsBuildProfileEditor())\n                GUILayout.Label(string.Format(L10n.Tr(\"Settings for {0}\"), validPlatforms[selectedPlatformValue].title.text));\n\n            // Increase the offset to accomodate large labels, though keep a minimum of 150.\n            EditorGUIUtility.labelWidth = Mathf.Max(150, EditorGUIUtility.labelWidth + 4);\n\n            int sectionIndex = 0;\n\n            if (serializedObjectUpdated)\n            {\n                m_IconsEditor.SerializedObjectUpdated();\n                foreach (var settingsExtension in m_SettingsExtensions)\n                {\n                    settingsExtension?.SerializedObjectUpdated();\n                }\n            }\n\n            m_IconsEditor.IconSectionGUI(platform, m_SettingsExtensions[selectedPlatformValue], selectedPlatformValue, sectionIndex++);\n\n            ResolutionSectionGUI(platform, m_SettingsExtensions[selectedPlatformValue], sectionIndex++);\n            m_SplashScreenEditor.SplashSectionGUI(platform, m_SettingsExtensions[selectedPlatformValue], sectionIndex++);\n            DebugAndCrashReportingGUI(platform, m_SettingsExtensions[selectedPlatformValue], sectionIndex++);\n            OtherSectionGUI(platform, m_SettingsExtensions[selectedPlatformValue], sectionIndex++);\n            PublishSectionGUI(platform, m_SettingsExtensions[selectedPlatformValue], sectionIndex++);\n\n            PlayerSettingsAttributeSectionsGUI(platform.namedBuildTarget, m_SettingsExtensions[selectedPlatformValue], ref sectionIndex);\n\n            EditorGUILayout.EndPlatformGrouping();\n\n            serializedObject.ApplyModifiedProperties();\n\n            if (hasPresetWindowClosed)\n            {\n                // We recompile after the window is closed just to make sure all the values are set/shown correctly.\n                // There might be a smarter idea where you detect the values that have changed and only do it if it's required,\n                // but the way the Preset window applies those changes as well as the way IMGUI works makes it difficult to track.\n                SetReason(RecompileReason.presetChanged);\n\n                OnPresetSelectorClosed();\n            }\n            else if (HasReasonToCompile())\n            {\n                RecompileScripts();\n            }\n        }\n\n        void DisplayBuildProfileHelpBoxIfNeeded()\n        {\n            if (playerSettingsType == PlayerSettingsType.Global && BuildProfileContext.activeProfile?.playerSettings != null)\n            {\n                GUILayout.BeginHorizontal(EditorStyles.helpBox);\n                GUILayout.BeginVertical();\n                GUILayout.Space(5);\n                GUILayout.Label(EditorGUIUtility.GetHelpIcon(MessageType.Warning), GUILayout.ExpandWidth(false));\n                GUILayout.EndVertical();\n                GUILayout.Label(SettingsContent.globalPlayerSettingsInfo, EditorStyles.wordWrappedMiniLabel);\n                GUILayout.BeginVertical();\n                GUILayout.Space(5);\n                if (GUILayout.Button(SettingsContent.globalPlayerSettingsInfoButton))\n                    BuildPipeline.ShowBuildProfileWindow();\n                GUILayout.Space(5);\n                GUILayout.EndVertical();\n                GUILayout.EndHorizontal();\n            }\n        }\n\n        private void CommonSettings()\n        {\n            EditorGUILayout.PropertyField(m_CompanyName);\n            EditorGUILayout.PropertyField(m_ProductName);\n            EditorGUILayout.PropertyField(m_ApplicationBundleVersion, EditorGUIUtility.TrTextContent(\"Version\"));\n            EditorGUILayout.Space();\n\n            m_IconsEditor.LegacyIconSectionGUI();\n\n            GUILayout.Space(3);\n\n            Rect cursorPropertyRect = EditorGUILayout.GetControlRect(true, EditorGUI.kObjectFieldThumbnailHeight);\n            EditorGUI.BeginProperty(cursorPropertyRect, SettingsContent.defaultCursor, m_DefaultCursor);\n            m_DefaultCursor.objectReferenceValue = EditorGUI.ObjectField(cursorPropertyRect, SettingsContent.defaultCursor, m_DefaultCursor.objectReferenceValue, typeof(Texture2D), false);\n            EditorGUI.EndProperty();\n\n            Rect rect = EditorGUILayout.GetControlRect();\n            rect = EditorGUI.PrefixLabel(rect, 0, SettingsContent.cursorHotspot);\n            EditorGUI.PropertyField(rect, m_CursorHotspot, GUIContent.none);\n        }\n\n        public bool BeginSettingsBox(int nr, GUIContent header)\n        {\n            if (nr >= m_SectionAnimators.Count)\n                m_SectionAnimators.Add(new AnimBool());\n            bool enabled = GUI.enabled;\n            GUI.enabled = true; // we don't want to disable the expand behavior\n            EditorGUILayout.BeginVertical(Styles.categoryBox);\n            Rect r = GUILayoutUtility.GetRect(20, 21);\n            EditorGUI.BeginChangeCheck();\n            bool expanded = EditorGUI.FoldoutTitlebar(r, header, m_SelectedSection.value == nr, true, EditorStyles.inspectorTitlebarFlat, EditorStyles.inspectorTitlebarText);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_SelectedSection.value = (expanded ? nr : -1);\n                GUIUtility.keyboardControl = 0;\n            }\n            m_SectionAnimators[nr].target = expanded;\n            GUI.enabled = enabled;\n            EditorGUI.indentLevel++;\n            return EditorGUILayout.BeginFadeGroup(m_SectionAnimators[nr].faded);\n        }\n\n        public void EndSettingsBox()\n        {\n            EditorGUILayout.EndFadeGroup();\n            EditorGUI.indentLevel--;\n            EditorGUILayout.EndVertical();\n        }\n\n        public void ShowSharedNote()\n        {\n            GUILayout.Label(SettingsContent.sharedBetweenPlatformsInfo, EditorStyles.miniLabel);\n        }\n\n        internal static void ShowNoSettings()\n        {\n            GUILayout.Label(SettingsContent.notApplicableInfo, EditorStyles.miniLabel);\n        }\n\n        private static bool TargetSupportsOptionalBuiltinSplashScreen(BuildTargetGroup targetGroup, ISettingEditorExtension settingsExtension)\n        {\n            if (settingsExtension != null)\n                return settingsExtension.CanShowUnitySplashScreen();\n\n            return targetGroup == BuildTargetGroup.Standalone;\n        }\n\n        public void ResolutionSectionGUI(BuildPlatform platform, ISettingEditorExtension settingsExtension, int sectionIndex = 0)\n        {\n            NamedBuildTarget namedBuildTarget = platform.namedBuildTarget;\n            if (BeginSettingsBox(sectionIndex, SettingsContent.resolutionPresentationTitle))\n            {\n                // PLEASE DO NOT COPY SETTINGS TO APPEAR MULTIPLE PLACES IN THE CODE! See top of file for more info.\n                if (namedBuildTarget == NamedBuildTarget.Server)\n                {\n                    ShowNoSettings();\n                    EditorGUILayout.Space();\n                }\n                else\n                {\n                    GUILayout.Label(SettingsContent.resolutionTitle, EditorStyles.boldLabel);\n                    if (SupportsRunInBackground(namedBuildTarget))\n                        EditorGUILayout.PropertyField(m_RunInBackground, SettingsContent.runInBackground);\n\n                    // Resolution itself\n                    if (settingsExtension != null)\n                    {\n                        float h = EditorGUI.kSingleLineHeight;\n                        float kLabelFloatMinW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing;\n                        float kLabelFloatMaxW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing;\n                        settingsExtension.ResolutionSectionGUI(h, kLabelFloatMinW, kLabelFloatMaxW);\n                    }\n\n                    if (namedBuildTarget == NamedBuildTarget.Standalone)\n                    {\n\n                        var fullscreenModes = new[] { FullScreenMode.FullScreenWindow, FullScreenMode.ExclusiveFullScreen, FullScreenMode.MaximizedWindow, FullScreenMode.Windowed };\n                        var fullscreenModeNames = new[] { SettingsContent.fullscreenWindow, SettingsContent.exclusiveFullscreen, SettingsContent.maximizedWindow, SettingsContent.windowed };\n                        var fullscreenModeNew = FullScreenMode.FullScreenWindow;\n                        using (var horizontal = new EditorGUILayout.HorizontalScope())\n                        {\n                            using (new EditorGUI.PropertyScope(horizontal.rect, GUIContent.none, m_FullscreenMode))\n                            {\n                                fullscreenModeNew = BuildEnumPopup(m_FullscreenMode, SettingsContent.fullscreenMode, fullscreenModes, fullscreenModeNames);\n                            }\n                        }\n\n                        bool defaultIsFullScreen = fullscreenModeNew != FullScreenMode.Windowed;\n                        m_ShowDefaultIsNativeResolution.target = defaultIsFullScreen;\n                        if (EditorGUILayout.BeginFadeGroup(m_ShowDefaultIsNativeResolution.faded))\n                            EditorGUILayout.PropertyField(m_DefaultIsNativeResolution, SettingsContent.defaultIsNativeResolution);\n                        EditorGUILayout.EndFadeGroup();\n\n                        m_ShowResolution.target = !(defaultIsFullScreen && m_DefaultIsNativeResolution.boolValue);\n                        if (EditorGUILayout.BeginFadeGroup(m_ShowResolution.faded))\n                        {\n                            EditorGUI.BeginChangeCheck();\n                            EditorGUILayout.PropertyField(m_DefaultScreenWidth, SettingsContent.defaultScreenWidth);\n                            if (EditorGUI.EndChangeCheck() && m_DefaultScreenWidth.intValue < 1)\n                                m_DefaultScreenWidth.intValue = 1;\n\n                            EditorGUI.BeginChangeCheck();\n                            EditorGUILayout.PropertyField(m_DefaultScreenHeight, SettingsContent.defaultScreenHeight);\n                            if (EditorGUI.EndChangeCheck() && m_DefaultScreenHeight.intValue < 1)\n                                m_DefaultScreenHeight.intValue = 1;\n                        }\n                        EditorGUILayout.EndFadeGroup();\n                    }\n\n                    if (namedBuildTarget == NamedBuildTarget.Standalone &&\n                        BuildTargetDiscovery.TryGetProperties(platform.defaultTarget, out IGraphicsPlatformProperties properties) &&\n                        (properties?.RetinaSupport ?? false))\n                        EditorGUILayout.PropertyField(m_MacRetinaSupport, SettingsContent.macRetinaSupport);\n\n                    if (settingsExtension != null && settingsExtension.SupportsOrientation())\n                    {\n                        GUILayout.Label(SettingsContent.orientationTitle, EditorStyles.boldLabel);\n\n                        EditorGUILayout.PropertyField(m_DefaultScreenOrientation, SettingsContent.defaultScreenOrientation);\n\n                        if (m_DefaultScreenOrientation.enumValueIndex == (int)UIOrientation.AutoRotation)\n                        {\n                            if (namedBuildTarget == NamedBuildTarget.iOS)\n                                EditorGUILayout.PropertyField(m_UseOSAutoRotation, SettingsContent.useOSAutoRotation);\n\n                            if (settingsExtension != null)\n                                settingsExtension.AutoRotationSectionGUI();\n\n                            EditorGUI.indentLevel++;\n\n                            GUILayout.Label(SettingsContent.allowedOrientationTitle, EditorStyles.boldLabel);\n\n                            bool somethingAllowed = m_AllowedAutoRotateToPortrait.boolValue\n                                || m_AllowedAutoRotateToPortraitUpsideDown.boolValue\n                                || m_AllowedAutoRotateToLandscapeRight.boolValue\n                                || m_AllowedAutoRotateToLandscapeLeft.boolValue;\n\n                            if (!somethingAllowed)\n                            {\n                                m_AllowedAutoRotateToPortrait.boolValue = true;\n                                Debug.LogError(\"All orientations are disabled. Allowing portrait\");\n                            }\n\n                            EditorGUILayout.PropertyField(m_AllowedAutoRotateToPortrait, SettingsContent.allowedAutoRotateToPortrait);\n                            EditorGUILayout.PropertyField(m_AllowedAutoRotateToPortraitUpsideDown, SettingsContent.allowedAutoRotateToPortraitUpsideDown);\n                            EditorGUILayout.PropertyField(m_AllowedAutoRotateToLandscapeRight, SettingsContent.allowedAutoRotateToLandscapeRight);\n                            EditorGUILayout.PropertyField(m_AllowedAutoRotateToLandscapeLeft, SettingsContent.allowedAutoRotateToLandscapeLeft);\n\n                            EditorGUI.indentLevel--;\n                        }\n                    }\n\n                    if (namedBuildTarget == NamedBuildTarget.iOS)\n                    {\n                        GUILayout.Label(SettingsContent.multitaskingSupportTitle, EditorStyles.boldLabel);\n                        EditorGUILayout.PropertyField(m_UIRequiresFullScreen, SettingsContent.UIRequiresFullScreen);\n                        EditorGUILayout.Space();\n\n                        GUILayout.Label(SettingsContent.statusBarTitle, EditorStyles.boldLabel);\n                        EditorGUILayout.PropertyField(m_UIStatusBarHidden, SettingsContent.UIStatusBarHidden);\n                        EditorGUILayout.PropertyField(m_UIStatusBarStyle, SettingsContent.UIStatusBarStyle);\n                        EditorGUILayout.Space();\n                    }\n\n                    EditorGUILayout.Space();\n\n                    // Standalone Player\n                    if (namedBuildTarget == NamedBuildTarget.Standalone)\n                    {\n                        GUILayout.Label(SettingsContent.standalonePlayerOptionsTitle, EditorStyles.boldLabel);\n\n                        EditorGUILayout.PropertyField(m_UsePlayerLog, SettingsContent.usePlayerLog);\n\n                        EditorGUILayout.PropertyField(m_ResizableWindow, SettingsContent.resizableWindow);\n\n                        EditorGUILayout.PropertyField(m_VisibleInBackground, SettingsContent.visibleInBackground);\n\n                        EditorGUILayout.PropertyField(m_AllowFullscreenSwitch, SettingsContent.allowFullscreenSwitch);\n\n                        EditorGUILayout.PropertyField(m_ForceSingleInstance, SettingsContent.forceSingleInstance);\n                        EditorGUILayout.PropertyField(m_UseFlipModelSwapchain, SettingsContent.useFlipModelSwapChain);\n\n                        if (!PlayerSettings.useFlipModelSwapchain)\n                        {\n                            EditorGUILayout.HelpBox(SettingsContent.flipModelSwapChainWarning.text, MessageType.Warning, true);\n                        }\n\n                        EditorGUILayout.Space();\n                    }\n\n                    // integrated gpu color/depth bits setup\n                    if (BuildTargetDiscovery.PlatformGroupHasFlag(namedBuildTarget.ToBuildTargetGroup(), TargetAttributes.HasIntegratedGPU))\n                    {\n                        // iOS, while supports 16bit FB through GL interface, use 32bit in hardware, so there is no need in 16bit\n                        if (namedBuildTarget != NamedBuildTarget.iOS &&\n                            namedBuildTarget != NamedBuildTarget.tvOS)\n                        {\n                            EditorGUILayout.PropertyField(m_Use32BitDisplayBuffer, SettingsContent.use32BitDisplayBuffer);\n                        }\n\n                        EditorGUILayout.PropertyField(m_DisableDepthAndStencilBuffers, SettingsContent.disableDepthAndStencilBuffers);\n                        EditorGUILayout.PropertyField(m_PreserveFramebufferAlpha, SettingsContent.preserveFramebufferAlpha);\n                    }\n\n                    ShowSharedNote();\n                }\n            }\n            EndSettingsBox();\n        }\n\n        // Checks if the GraphicsDeviceType is deprecated\n        static private bool IsGraphicsDeviceTypeDeprecated(BuildTarget target, GraphicsDeviceType graphicsDeviceType)\n        {\n            switch (graphicsDeviceType)\n            {\n                case GraphicsDeviceType.PlayStation5: return true;\n                case GraphicsDeviceType.OpenGLCore: return target == BuildTarget.StandaloneWindows || target == BuildTarget.StandaloneWindows64;\n                default: return false;\n            }\n        }\n\n        static private GraphicsDeviceType RecommendedGraphicsDeviceTypeFromDeprecated(BuildTarget target, GraphicsDeviceType graphicsDeviceType)\n        {\n            switch (graphicsDeviceType)\n            {\n                case GraphicsDeviceType.PlayStation5: return GraphicsDeviceType.PlayStation5NGGC;\n                case GraphicsDeviceType.OpenGLCore: return target == BuildTarget.StandaloneWindows || target == BuildTarget.StandaloneWindows64 ?\n                        GraphicsDeviceType.Vulkan : graphicsDeviceType;\n                default: return graphicsDeviceType;\n            }\n        }\n\n        // Checks if the GraphicsDeviceType is experimental\n        static private bool IsGraphicsDeviceTypeExperimental(BuildTarget target, GraphicsDeviceType graphicsDeviceType)\n        {\n            switch (graphicsDeviceType)\n            {\n                case GraphicsDeviceType.WebGPU: return true;\n                default: return false;\n            }\n        }\n\n        // Converts a GraphicsDeviceType to a string, along with visual modifiers for given target platform\n        static private string GraphicsDeviceTypeToString(BuildTarget target, GraphicsDeviceType graphicsDeviceType)\n        {\n            if (graphicsDeviceType != GraphicsDeviceType.WebGPU && target == BuildTarget.WebGL)\n            {\n                return \"WebGL 2\";\n            }\n\n            if (IsGraphicsDeviceTypeDeprecated(target, graphicsDeviceType))\n                return graphicsDeviceType.ToString() + \" (Deprecated)\";\n            else if (IsGraphicsDeviceTypeExperimental(target, graphicsDeviceType))\n            {\n                return graphicsDeviceType.ToString() + \" (Experimental)\";\n            }\n\n            return graphicsDeviceType.ToString();\n        }\n\n        // Parses a GraphicsDeviceType from a string.\n        static private GraphicsDeviceType GraphicsDeviceTypeFromString(string graphicsDeviceType)\n        {\n            graphicsDeviceType = graphicsDeviceType.Replace(\" (Deprecated)\", \"\");\n            graphicsDeviceType = graphicsDeviceType.Replace(\" (Experimental)\", \"\");\n            if (graphicsDeviceType == \"WebGL 2\") return GraphicsDeviceType.OpenGLES3;\n            return (GraphicsDeviceType)Enum.Parse(typeof(GraphicsDeviceType), graphicsDeviceType, true);\n        }\n\n        private void AddGraphicsDeviceMenuSelected(object userData, string[] options, int selected)\n        {\n            var target = (BuildTarget)userData;\n            var apis = m_CurrentTarget.GetGraphicsAPIs_Internal(target);\n            if (apis == null)\n                return;\n            var apiToAdd = GraphicsDeviceTypeFromString(options[selected]);\n            apis = apis.Append(apiToAdd).ToArray();\n            m_CurrentTarget.SetGraphicsAPIs_Internal(target, apis, true);\n            OnTargetObjectChangedDirectly();\n        }\n\n        private void AddGraphicsDeviceElement(BuildTarget target, Rect rect, ReorderableList list)\n        {\n            GraphicsDeviceType[] availableDevices = PlayerSettings.GetSupportedGraphicsAPIs(target);\n\n            if (availableDevices == null || availableDevices.Length == 0)\n                return;\n\n            //As part of OpenGL deprection from MacOS, hide the option of adding OpenGL\n            if (target == BuildTarget.StandaloneOSX)\n            {\n                var availableDeviceList = availableDevices.ToList();\n                availableDeviceList.Remove(GraphicsDeviceType.OpenGLCore);\n                availableDevices = availableDeviceList.ToArray();\n            }\n\n            var names = new string[availableDevices.Length];\n            var enabled = new bool[availableDevices.Length];\n            for (int i = 0; i < availableDevices.Length; ++i)\n            {\n                names[i] = L10n.Tr(GraphicsDeviceTypeToString(target, availableDevices[i]));\n                enabled[i] = !list.list.Contains(availableDevices[i]);\n            }\n\n            EditorUtility.DisplayCustomMenu(rect, names, enabled, null, AddGraphicsDeviceMenuSelected, target);\n        }\n\n        private bool CanRemoveGraphicsDeviceElement(ReorderableList list)\n        {\n            // don't allow removing the last API\n            return list.list.Count >= 2;\n        }\n\n        private void RemoveGraphicsDeviceElement(BuildTarget target, ReorderableList list)\n        {\n            var apis = m_CurrentTarget.GetGraphicsAPIs_Internal(target);\n            if (apis == null)\n                return;\n            // don't allow removing the last API\n            if (apis.Length < 2)\n            {\n                EditorApplication.Beep();\n                return;\n            }\n\n            var apiList = apis.ToList();\n            apiList.RemoveAt(list.index);\n            apis = apiList.ToArray();\n\n            ApplyChangedGraphicsAPIList(target, apis, list.index == 0);\n        }\n\n        private void ReorderGraphicsDeviceElement(BuildTarget target, ReorderableList list)\n        {\n            var previousAPIs = m_CurrentTarget.GetGraphicsAPIs_Internal(target);\n            var apiList = (List<GraphicsDeviceType>)list.list;\n            var apis = apiList.ToArray();\n\n            var firstAPIDifferent = (previousAPIs[0] != apis[0]);\n            ApplyChangedGraphicsAPIList(target, apis, firstAPIDifferent);\n        }\n\n        // these two methods are needed for cases when you want to take some action depending on user choice\n        // as changing graphics api will call GUIUtility.ExitGUI\n\n        private struct ChangeGraphicsApiAction\n        {\n            public readonly bool changeList, reloadGfx;\n            public ChangeGraphicsApiAction(bool doChange, bool doReload) { changeList = doChange; reloadGfx = doReload; }\n        }\n        private ChangeGraphicsApiAction CheckApplyGraphicsAPIList(BuildTarget target, bool firstEntryChanged)\n        {\n            bool doRestart = false;\n            // If we're changing the first API for relevant editor, this will cause editor to switch: ask for scene save & confirmation\n            if (firstEntryChanged && WillEditorUseFirstGraphicsAPI(target))\n            {\n                // If we have dirty scenes we need to save or discard changes before we restart editor.\n                // Otherwise user will get a dialog later on where they can click cancel and put editor in a bad device state.\n                var dirtyScenes = new List<Scene>();\n                for (int i = 0; i < EditorSceneManager.sceneCount; ++i)\n                {\n                    var scene = EditorSceneManager.GetSceneAt(i);\n                    if (scene.isDirty)\n                        dirtyScenes.Add(scene);\n                }\n                if (dirtyScenes.Count != 0)\n                {\n                    var result = EditorUtility.DisplayDialogComplex(\"Changing editor graphics API\",\n                        \"You've changed the active graphics API. This requires a restart of the Editor. Do you want to save the Scene when restarting?\",\n                        \"Save and Restart\", \"Cancel Changing API\", \"Discard Changes and Restart\");\n                    if (result == 1)\n                    {\n                        doRestart = false; // Cancel was selected\n                    }\n                    else\n                    {\n                        doRestart = true;\n                        if (result == 0) // Save and Restart was selected\n                        {\n                            for (int i = 0; i < dirtyScenes.Count; ++i)\n                            {\n                                var saved = EditorSceneManager.SaveScene(dirtyScenes[i]);\n                                if (saved == false)\n                                {\n                                    doRestart = false;\n                                }\n                            }\n                        }\n                        else // Discard Changes and Restart was selected\n                        {\n                            for (int i = 0; i < dirtyScenes.Count; ++i)\n                                EditorSceneManager.ClearSceneDirtiness(dirtyScenes[i]);\n                        }\n                    }\n                }\n                else\n                {\n                    doRestart = EditorUtility.DisplayDialog(\"Changing editor graphics API\",\n                        \"You've changed the active graphics API. This requires a restart of the Editor.\",\n                        \"Restart Editor\", \"Not now\");\n                }\n                return new ChangeGraphicsApiAction(doRestart, doRestart);\n            }\n            else\n            {\n                return new ChangeGraphicsApiAction(true, false);\n            }\n        }\n\n        private void ApplyChangeGraphicsApiAction(BuildTarget target, GraphicsDeviceType[] apis, ChangeGraphicsApiAction action)\n        {\n            if (action.changeList)\n            {\n                m_CurrentTarget.SetGraphicsAPIs_Internal(target, apis, true);\n                OnTargetObjectChangedDirectly();\n            }\n            else\n                m_GraphicsDeviceLists.Remove(target); // we cancelled the list change, so remove the cached one\n\n            if (action.reloadGfx)\n            {\n                EditorApplication.RequestCloseAndRelaunchWithCurrentArguments();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        private void ApplyChangedGraphicsAPIList(BuildTarget target, GraphicsDeviceType[] apis, bool firstEntryChanged)\n        {\n            ChangeGraphicsApiAction action = CheckApplyGraphicsAPIList(target, firstEntryChanged);\n            ApplyChangeGraphicsApiAction(target, apis, action);\n        }\n\n        private void DrawGraphicsDeviceElement(BuildTarget target, Rect rect, int index, bool selected, bool focused)\n        {\n            var name = GraphicsDeviceTypeToString(target, (GraphicsDeviceType)m_GraphicsDeviceLists[target].list[index]);\n\n            GUI.Label(rect, name, EditorStyles.label);\n        }\n\n        private static bool WillEditorUseFirstGraphicsAPI(BuildTarget targetPlatform)\n        {\n            return\n                Application.platform == RuntimePlatform.WindowsEditor && targetPlatform == BuildTarget.StandaloneWindows ||\n                Application.platform == RuntimePlatform.LinuxEditor && targetPlatform == BuildTarget.StandaloneLinux64 ||\n                Application.platform == RuntimePlatform.OSXEditor && targetPlatform == BuildTarget.StandaloneOSX;\n        }\n\n        private bool CheckApplyGraphicsJobsModeChange(BuildTarget target)\n        {\n            bool doRestart = false;\n\n            if (WillEditorUseFirstGraphicsAPI(target))\n            {\n                // If we have dirty scenes we need to save or discard changes before we restart editor.\n                // Otherwise user will get a dialog later on where they can click cancel and put editor in a bad device state.\n                var dirtyScenes = new List<Scene>();\n                for (int i = 0; i < EditorSceneManager.sceneCount; ++i)\n                {\n                    var scene = EditorSceneManager.GetSceneAt(i);\n                    if (scene.isDirty)\n                        dirtyScenes.Add(scene);\n                }\n                if (dirtyScenes.Count != 0)\n                {\n                    var result = EditorUtility.DisplayDialogComplex(\"Changing editor graphics jobs mode\",\n                        \"You've changed the active graphics jobs mode. This requires a restart of the Editor. Do you want to save the Scene when restarting?\",\n                        \"Save and Restart\", \"Cancel Changing API\", \"Discard Changes and Restart\");\n                    if (result == 1)\n                    {\n                        doRestart = false; // Cancel was selected\n                    }\n                    else\n                    {\n                        doRestart = true;\n                        if (result == 0) // Save and Restart was selected\n                        {\n                            for (int i = 0; i < dirtyScenes.Count; ++i)\n                            {\n                                var saved = EditorSceneManager.SaveScene(dirtyScenes[i]);\n                                if (saved == false)\n                                {\n                                    doRestart = false;\n                                }\n                            }\n                        }\n                        else // Discard Changes and Restart was selected\n                        {\n                            for (int i = 0; i < dirtyScenes.Count; ++i)\n                                EditorSceneManager.ClearSceneDirtiness(dirtyScenes[i]);\n                        }\n                    }\n                }\n                else\n                {\n                    doRestart = EditorUtility.DisplayDialog(\"Changing editor graphics jobs mode\",\n                        \"You've changed the active graphics jobs mode. This requires a restart of the Editor.\",\n                        \"Restart Editor\", \"Not now\");\n                }\n            }\n            return doRestart;\n        }\n\n        void OpenGLES31OptionsGUI(BuildTargetGroup targetGroup, BuildTarget targetPlatform)\n        {\n            // ES3.1 options only applicable on some platforms now\n            var hasES31Options = (targetGroup == BuildTargetGroup.Android);\n            if (!hasES31Options)\n                return;\n\n            var apis = m_CurrentTarget.GetGraphicsAPIs_Internal(targetPlatform);\n            // only available if we include ES3\n            var hasMinES3 = apis.Contains(GraphicsDeviceType.OpenGLES3);\n            if (!hasMinES3)\n                return;\n\n            EditorGUILayout.PropertyField(m_RequireES31, SettingsContent.require31);\n            EditorGUILayout.PropertyField(m_RequireES31AEP, SettingsContent.requireAEP);\n            EditorGUILayout.PropertyField(m_RequireES32, SettingsContent.require32);\n        }\n\n        void ExclusiveGraphicsAPIsGUI(BuildTarget targetPlatform, string displayTitle)\n        {\n            EditorGUI.BeginChangeCheck();\n            GraphicsDeviceType[] currentDevices = m_CurrentTarget.GetGraphicsAPIs_Internal(targetPlatform);\n            GraphicsDeviceType[] availableDevices = PlayerSettings.GetSupportedGraphicsAPIs(targetPlatform);\n\n            GUIContent[] names = new GUIContent[availableDevices.Length];\n            for (int i = 0; i < availableDevices.Length; ++i)\n            {\n                names[i] = EditorGUIUtility.TrTextContent(L10n.Tr(GraphicsDeviceTypeToString(targetPlatform, availableDevices[i])));\n            }\n\n            GraphicsDeviceType selected = BuildEnumPopup(EditorGUIUtility.TrTextContent(displayTitle), currentDevices[0], availableDevices, names);\n            if (EditorGUI.EndChangeCheck() && selected != currentDevices[0])\n            {\n                Undo.RecordObject(target, SettingsContent.undoChangedGraphicsAPIString);\n                m_CurrentTarget.SetGraphicsAPIs_Internal(targetPlatform, new GraphicsDeviceType[] { selected }, true);\n                OnTargetObjectChangedDirectly();\n            }\n\n            if (IsGraphicsDeviceTypeDeprecated(targetPlatform, selected))\n            {\n                GraphicsDeviceType recommendedAPI = RecommendedGraphicsDeviceTypeFromDeprecated(targetPlatform, selected);\n                string text = $\"The Graphics API has been deprecated and will be removed in a future version. Use {GraphicsDeviceTypeToString(targetPlatform, recommendedAPI)} instead.\";\n                EditorGUILayout.HelpBox(L10n.Tr(text), MessageType.Info, true);\n            }\n        }\n\n        void GraphicsAPIsGUIOnePlatform(BuildTargetGroup targetGroup, BuildTarget targetPlatform, GUIContent platformTitleContent)\n        {\n            if (IsPreset())\n                return;\n\n            GraphicsDeviceType[] availableDevices = PlayerSettings.GetSupportedGraphicsAPIs(targetPlatform);\n            // if no devices (e.g. no platform module), or we only have one possible choice, then no\n            // point in having any UI\n            if (availableDevices == null || availableDevices.Length < 2)\n                return;\n\n            // toggle for automatic API selection\n            EditorGUI.BeginChangeCheck();\n            var automatic = m_CurrentTarget.GetUseDefaultGraphicsAPIs_Internal(targetPlatform);\n            automatic = EditorGUILayout.Toggle(platformTitleContent ?? GUIContent.none, automatic);\n            if (EditorGUI.EndChangeCheck())\n            {\n                Undo.RecordObject(target, SettingsContent.undoChangedGraphicsAPIString);\n                m_CurrentTarget.SetUseDefaultGraphicsAPIs_Internal(targetPlatform, automatic);\n                OnTargetObjectChangedDirectly();\n            }\n\n            // graphics API list if not automatic\n            if (!automatic)\n            {\n                // note that editor will use first item, when we're in standalone settings\n                if (WillEditorUseFirstGraphicsAPI(targetPlatform))\n                {\n                    EditorGUILayout.HelpBox(SettingsContent.recordingInfo.text, MessageType.Info, true);\n                }\n\n                string displayTitle = String.Empty;\n                if (platformTitleContent != null)\n                {\n                    displayTitle = platformTitleContent.text;\n                    if (displayTitle.StartsWith(\"Auto \"))\n                        displayTitle = displayTitle.Substring(5);\n                }\n\n                if (targetPlatform == BuildTarget.PS5)\n                {\n                    ExclusiveGraphicsAPIsGUI(targetPlatform, displayTitle);\n                    return;\n                }\n\n                GraphicsDeviceType[] devices = m_CurrentTarget.GetGraphicsAPIs_Internal(targetPlatform);\n                var devicesList = (devices != null) ? devices.ToList() : new List<GraphicsDeviceType>();\n                // create reorderable list for this target if needed\n                if (!m_GraphicsDeviceLists.ContainsKey(targetPlatform))\n                {\n                    var rlist = new ReorderableList(devicesList, typeof(GraphicsDeviceType), true, true, true, true);\n                    rlist.onAddDropdownCallback = (rect, list) => AddGraphicsDeviceElement(targetPlatform, rect, list);\n                    rlist.onCanRemoveCallback = CanRemoveGraphicsDeviceElement;\n                    rlist.onRemoveCallback = (list) => RemoveGraphicsDeviceElement(targetPlatform, list);\n                    rlist.onReorderCallback = (list) => ReorderGraphicsDeviceElement(targetPlatform, list);\n                    rlist.drawElementCallback = (rect, index, isActive, isFocused) => DrawGraphicsDeviceElement(targetPlatform, rect, index, isActive, isFocused);\n                    rlist.drawHeaderCallback = (rect) => GUI.Label(rect, displayTitle, EditorStyles.label);\n                    rlist.elementHeight = 16;\n\n                    m_GraphicsDeviceLists.Add(targetPlatform, rlist);\n                }\n\n                if (targetPlatform == BuildTarget.StandaloneOSX && m_GraphicsDeviceLists[BuildTarget.StandaloneOSX].list.Contains(GraphicsDeviceType.OpenGLCore))\n                {\n                    EditorGUILayout.HelpBox(SettingsContent.appleSiliconOpenGLWarning.text, MessageType.Warning, true);\n                }\n\n                m_GraphicsDeviceLists[targetPlatform].DoLayoutList();\n\n                bool containsDeprecatedAPIs = devicesList.Exists(device => IsGraphicsDeviceTypeDeprecated(targetPlatform, device));\n                if (containsDeprecatedAPIs)\n                    EditorGUILayout.HelpBox(SettingsContent.graphicsAPIDeprecationMessage.text, MessageType.Info, true);\n\n                //@TODO: undo\n            }\n\n            // ES3.1 options\n            OpenGLES31OptionsGUI(targetGroup, targetPlatform);\n        }\n\n        void GraphicsAPIsGUI(BuildTargetGroup targetGroup, BuildTarget target)\n        {\n            // \"standalone\" is a generic group;\n            // split it into win/mac/linux manually\n            if (targetGroup == BuildTargetGroup.Standalone)\n            {\n                GraphicsAPIsGUIOnePlatform(targetGroup, BuildTarget.StandaloneWindows, SettingsContent.autoGraphicsAPIForWindows);\n                GraphicsAPIsGUIOnePlatform(targetGroup, BuildTarget.StandaloneOSX, SettingsContent.autoGraphicsAPIForMac);\n                GraphicsAPIsGUIOnePlatform(targetGroup, BuildTarget.StandaloneLinux64, SettingsContent.autoGraphicsAPIForLinux);\n            }\n            else\n            {\n                GraphicsAPIsGUIOnePlatform(targetGroup, target, SettingsContent.autoGraphicsAPI);\n            }\n        }\n\n        // Contains information about color gamuts supported by each platform.\n        // If platform group is not in the dictionary, then it's assumed it supports only sRGB.\n        // Color gamut player setting is not displayed for such platforms.\n        //\n        // This information might be useful for users that use the color gamut APIs,\n        // we could expose it somehow\n        private static Dictionary<BuildTargetGroup, List<ColorGamut>> s_SupportedColorGamuts =\n            new Dictionary<BuildTargetGroup, List<ColorGamut>>\n        {\n            { BuildTargetGroup.Standalone, new List<ColorGamut> { ColorGamut.sRGB, ColorGamut.DisplayP3 } },\n            { BuildTargetGroup.iOS, new List<ColorGamut> { ColorGamut.sRGB, ColorGamut.DisplayP3 } },\n            { BuildTargetGroup.tvOS, new List<ColorGamut> { ColorGamut.sRGB, ColorGamut.DisplayP3 } },\n            { BuildTargetGroup.VisionOS, new List<ColorGamut> { ColorGamut.sRGB, ColorGamut.DisplayP3 } },\n            { BuildTargetGroup.Android, new List<ColorGamut> {ColorGamut.sRGB, ColorGamut.DisplayP3 } }\n        };\n\n        private static bool IsColorGamutSupportedOnTargetGroup(BuildTargetGroup targetGroup, ColorGamut gamut)\n        {\n            if (gamut == ColorGamut.sRGB)\n                return true;\n            if (s_SupportedColorGamuts.ContainsKey(targetGroup) && s_SupportedColorGamuts[targetGroup].Contains(gamut))\n                return true;\n            return false;\n        }\n\n        private static string GetColorGamutDisplayString(BuildTargetGroup targetGroup, ColorGamut gamut)\n        {\n            string name = gamut.ToString();\n            if (!IsColorGamutSupportedOnTargetGroup(targetGroup, gamut))\n                name += L10n.Tr(\" (not supported on this platform)\");\n            return name;\n        }\n\n        private void AddColorGamutElement(BuildTargetGroup targetGroup, Rect rect, ReorderableList list)\n        {\n            var availableColorGamuts = new ColorGamut[]\n            {\n                // Enable the gamuts when at least one platform supports them\n                ColorGamut.sRGB,\n                //ColorGamut.Rec709,\n                //ColorGamut.Rec2020,\n                ColorGamut.DisplayP3,\n                //ColorGamut.HDR10,\n                //ColorGamut.DolbyHDR\n            };\n\n            var names = new string[availableColorGamuts.Length];\n            var enabled = new bool[availableColorGamuts.Length];\n            for (int i = 0; i < availableColorGamuts.Length; ++i)\n            {\n                names[i] = GetColorGamutDisplayString(targetGroup, availableColorGamuts[i]);\n                enabled[i] = !list.list.Contains(availableColorGamuts[i]);\n            }\n\n            EditorUtility.DisplayCustomMenu(rect, names, enabled, null, AddColorGamutMenuSelected, availableColorGamuts);\n        }\n\n        private void AddColorGamutMenuSelected(object userData, string[] options, int selected)\n        {\n            var colorGamuts = (ColorGamut[])userData;\n            var colorGamutList = m_CurrentTarget.GetColorGamuts_Internal().ToList();\n            colorGamutList.Add(colorGamuts[selected]);\n            m_CurrentTarget.SetColorGamuts_Internal(colorGamutList.ToArray());\n            OnTargetObjectChangedDirectly();\n            SyncColorGamuts();\n        }\n\n        private bool CanRemoveColorGamutElement(ReorderableList list)\n        {\n            // don't allow removing the sRGB\n            var colorGamutList = (List<ColorGamut>)list.list;\n            return colorGamutList[list.index] != ColorGamut.sRGB;\n        }\n\n        private void RemoveColorGamutElement(ReorderableList list)\n        {\n            var colorGamutList = m_CurrentTarget.GetColorGamuts_Internal().ToList();\n            // don't allow removing the last ColorGamut\n            if (colorGamutList.Count < 2)\n            {\n                EditorApplication.Beep();\n                return;\n            }\n            colorGamutList.RemoveAt(list.index);\n            m_CurrentTarget.SetColorGamuts_Internal(colorGamutList.ToArray());\n            OnTargetObjectChangedDirectly();\n            SyncColorGamuts();\n        }\n\n        private void ReorderColorGamutElement(ReorderableList list)\n        {\n            var colorGamutList = (List<ColorGamut>)list.list;\n            m_CurrentTarget.SetColorGamuts_Internal(colorGamutList.ToArray());\n            OnTargetObjectChangedDirectly();\n            SyncColorGamuts();\n        }\n\n        private void DrawColorGamutElement(BuildTargetGroup targetGroup, Rect rect, int index, bool selected, bool focused)\n        {\n            var colorGamut = m_ColorGamutList.list[index];\n            GUI.Label(rect, GetColorGamutDisplayString(targetGroup, (ColorGamut)colorGamut), EditorStyles.label);\n        }\n\n        void ColorGamutGUI(BuildPlatform platform)\n        {\n            BuildTargetGroup targetGroup = platform.namedBuildTarget.ToBuildTargetGroup();\n\n            if (IsPreset())\n                return;\n            if (!s_SupportedColorGamuts.ContainsKey(targetGroup))\n                return;\n\n            // Color gamut is not supported for other standalones besides Mac\n            if (!(BuildTargetDiscovery.TryGetProperties(platform.defaultTarget, out IGraphicsPlatformProperties properties) &&\n               (properties?.SupportsColorGamut ?? false)))\n                return;\n\n            if (m_ColorGamutList == null)\n            {\n                ColorGamut[] colorGamuts = m_CurrentTarget.GetColorGamuts_Internal();\n                var colorGamutsList = (colorGamuts != null) ? colorGamuts.ToList() : new List<ColorGamut>();\n                var rlist = new ReorderableList(colorGamutsList, typeof(ColorGamut), true, true, true, true);\n                rlist.onCanRemoveCallback = CanRemoveColorGamutElement;\n                rlist.onRemoveCallback = RemoveColorGamutElement;\n                rlist.onReorderCallback = ReorderColorGamutElement;\n                rlist.elementHeight = 16;\n\n                m_ColorGamutList = rlist;\n            }\n\n            // On standalone inspector mention that the setting applies only to Mac\n            // (Temporarily until other standalones support this setting)\n            GUIContent header = targetGroup == BuildTargetGroup.Standalone ? SettingsContent.colorGamutForMac : SettingsContent.colorGamut;\n            m_ColorGamutList.drawHeaderCallback = (rect) =>\n                GUI.Label(rect, header, EditorStyles.label);\n\n            // we want to change the displayed text per platform, to indicate unsupported gamuts\n            m_ColorGamutList.onAddDropdownCallback = (rect, list) =>\n                AddColorGamutElement(targetGroup, rect, list);\n\n            m_ColorGamutList.drawElementCallback = (rect, index, selected, focused) =>\n                DrawColorGamutElement(targetGroup, rect, index, selected, focused);\n\n            m_ColorGamutList.DoLayoutList();\n        }\n\n        public void DebugAndCrashReportingGUI(BuildPlatform platform,\n            ISettingEditorExtension settingsExtension, int sectionIndex = 3)\n        {\n            if (platform.namedBuildTarget != NamedBuildTarget.iOS && platform.namedBuildTarget != NamedBuildTarget.tvOS)\n                return;\n\n            if (BeginSettingsBox(sectionIndex, SettingsContent.debuggingCrashReportingTitle))\n            {\n                // PLEASE DO NOT COPY SETTINGS TO APPEAR MULTIPLE PLACES IN THE CODE! See top of file for more info.\n                {\n                    // Debugging\n                    GUILayout.Label(SettingsContent.debuggingTitle, EditorStyles.boldLabel);\n                    EditorGUILayout.PropertyField(m_EnableInternalProfiler, SettingsContent.enableInternalProfiler);\n                    EditorGUILayout.Space();\n                }\n\n                {\n                    // Crash reporting\n                    GUILayout.Label(SettingsContent.crashReportingTitle, EditorStyles.boldLabel);\n                    EditorGUILayout.PropertyField(m_ActionOnDotNetUnhandledException, SettingsContent.actionOnDotNetUnhandledException);\n                    EditorGUILayout.HelpBox(SettingsContent.actionOnDotNetUnhandledExceptionDeprecation.text, MessageType.Info, true);\n                    EditorGUILayout.PropertyField(m_LogObjCUncaughtExceptions, SettingsContent.logObjCUncaughtExceptions);\n\n                    GUIContent crashReportApiContent = SettingsContent.enableCrashReportAPI;\n\n                    bool apiFieldDisabled = false;\n\n                    if (UnityEditor.CrashReporting.CrashReportingSettings.canUploadReports)\n                    {\n                        // CrashReport API must be enabled if cloud crash reporting is enabled,\n                        // so don't let them change the value of the checkbox\n                        crashReportApiContent = new GUIContent(crashReportApiContent);  // Create a copy so we don't alter the style definition\n                        apiFieldDisabled = true;\n                        crashReportApiContent.tooltip = \"CrashReport API must be enabled for Performance Reporting service.\";\n                        m_EnableCrashReportAPI.boolValue = true;\n                    }\n\n                    EditorGUI.BeginDisabledGroup(apiFieldDisabled);\n                    EditorGUILayout.PropertyField(m_EnableCrashReportAPI, crashReportApiContent);\n                    EditorGUI.EndDisabledGroup();\n\n                    EditorGUILayout.Space();\n                }\n            }\n            EndSettingsBox();\n        }\n\n        public static void BuildDisabledEnumPopup(GUIContent selected, GUIContent uiString)\n        {\n            using (new EditorGUI.DisabledScope(true))\n            {\n                EditorGUI.Popup(EditorGUILayout.GetControlRect(true), uiString, 0, new GUIContent[] { selected });\n            }\n        }\n\n        public static T BuildEnumPopup<T>(SerializedProperty prop, GUIContent uiString, T[] options, GUIContent[] optionNames)\n        {\n            T val = (T)(object)prop.intValue;\n            T newVal = BuildEnumPopup(uiString, val, options, optionNames);\n\n            // Update property if the popup value has changed\n            if (!newVal.Equals(val))\n            {\n                prop.intValue = (int)(object)newVal;\n                prop.serializedObject.ApplyModifiedProperties();\n            }\n\n            return newVal;\n        }\n\n        public static T BuildEnumPopup<T>(GUIContent uiString, T selected, T[] options, GUIContent[] optionNames)\n        {\n            // Display dropdown\n            int idx = 0; // pick the first property when not found\n            for (int i = 1; i < options.Length; ++i)\n            {\n                if (selected.Equals(options[i]))\n                {\n                    idx = i;\n                    break;\n                }\n            }\n\n            int newIdx = EditorGUILayout.Popup(uiString, idx, optionNames);\n            return options[newIdx];\n        }\n\n        public static void EnumPropertyField<T>(SerializedProperty property, GUIContent name) where T : Enum\n        {\n            using (var horizontal = new EditorGUILayout.HorizontalScope())\n            {\n                using (new EditorGUI.PropertyScope(horizontal.rect, GUIContent.none, property))\n                {\n                    var values = (T[])Enum.GetValues(typeof(T));\n                    var valueNames = Enum.GetNames(typeof(T)).Select(e => new GUIContent(e)).ToArray();\n                    PlayerSettingsEditor.BuildEnumPopup(property, name, values, valueNames);\n                }\n            }\n        }\n\n        public void OtherSectionGUI(BuildPlatform platform, ISettingEditorExtension settingsExtension, int sectionIndex = 4)\n        {\n            if (BeginSettingsBox(sectionIndex, SettingsContent.otherSettingsTitle))\n            {\n                // PLEASE DO NOT COPY SETTINGS TO APPEAR MULTIPLE PLACES IN THE CODE! See top of file for more info.\n                if (platform.namedBuildTarget != NamedBuildTarget.Server)\n                {\n                    OtherSectionRenderingGUI(platform, settingsExtension);\n                    OtherSectionVulkanSettingsGUI(platform, settingsExtension);\n                    OtherSectionIdentificationGUI(platform, settingsExtension);\n                }\n                OtherSectionConfigurationGUI(platform, settingsExtension);\n                OtherSectionShaderSettingsGUI(platform);\n                OtherSectionScriptCompilationGUI(platform);\n                OtherSectionOptimizationGUI(platform);\n                OtherSectionLoggingGUI();\n                OtherSectionLegacyGUI(platform);\n                if (platform.namedBuildTarget == NamedBuildTarget.Standalone || platform.namedBuildTarget == NamedBuildTarget.Server)\n                {\n                    OtherSectionCaptureLogsGUI(platform.namedBuildTarget);\n                }\n                ShowSharedNote();\n            }\n            EndSettingsBox();\n        }\n\n        public void PlayerSettingsAttributeSectionsGUI(NamedBuildTarget namedBuildTarget, ISettingEditorExtension settingsExtension, ref int sectionIndex)\n        {\n            foreach (var box in m_boxes)\n            {\n                if (box.TargetName == namedBuildTarget.TargetName)\n                {\n                    if (BeginSettingsBox(sectionIndex, box.title))\n                    {\n                        box.mi.Invoke(null, null);\n                    }\n                    EndSettingsBox();\n                    sectionIndex++;\n                }\n            }\n        }\n\n        private void OtherSectionShaderSettingsGUI(BuildPlatform platform)\n        {\n            GUILayout.Label(SettingsContent.shaderSectionTitle, EditorStyles.boldLabel);\n\n            using (new EditorGUI.DisabledScope(EditorApplication.isPlaying || EditorApplication.isCompiling))\n            {\n                EditorGUI.BeginChangeCheck();\n                ShaderPrecisionModel currShaderPrecisionModel = (ShaderPrecisionModel) m_ShaderPrecisionModel.intValue;\n                ShaderPrecisionModel[] shaderPrecisionModelValues = { ShaderPrecisionModel.PlatformDefault, ShaderPrecisionModel.Unified };\n                ShaderPrecisionModel newShaderPrecisionModel = BuildEnumPopup(\n                    SettingsContent.shaderPrecisionModel, currShaderPrecisionModel, shaderPrecisionModelValues,\n                    SettingsContent.shaderPrecisionModelOptions);\n                if (EditorGUI.EndChangeCheck() && currShaderPrecisionModel != newShaderPrecisionModel)\n                {\n                    m_ShaderPrecisionModel.intValue = (int)newShaderPrecisionModel;\n                    serializedObject.ApplyModifiedProperties();\n                    if (IsActivePlayerSettingsEditor())\n                    {\n                        EditorApplication.delayCall += () => PlayerSettings.SyncShaderPrecisionModel();\n                    }\n                }\n            }\n\n            EditorGUILayout.PropertyField(m_StrictShaderVariantMatching, SettingsContent.strictShaderVariantMatching);\n\n            EditorGUILayout.PropertyField(m_KeepLoadedShadersAlive, SettingsContent.keepLoadedShadersAlive);\n\n            GUILayout.Label(SettingsContent.shaderVariantLoadingTitle, EditorStyles.boldLabel);\n\n            EditorGUI.BeginChangeCheck();\n            int defaultChunkSize = PlayerSettings.GetDefaultShaderChunkSizeInMB_Internal(m_CurrentTarget);\n            int newDefaultChunkSize = EditorGUILayout.IntField(SettingsContent.defaultShaderChunkSize, defaultChunkSize);\n            if (EditorGUI.EndChangeCheck() && newDefaultChunkSize > 0 && newDefaultChunkSize != defaultChunkSize)\n            {\n                Undo.RecordObject(target, SettingsContent.undoChangedDefaultShaderChunkSizeString);\n                PlayerSettings.SetDefaultShaderChunkSizeInMB_Internal(m_CurrentTarget, newDefaultChunkSize);\n                m_OnTrackSerializedObjectValueChanged?.Invoke(serializedObject);\n            }\n\n            EditorGUI.BeginChangeCheck();\n            int defaultChunkCount = PlayerSettings.GetDefaultShaderChunkCount_Internal(m_CurrentTarget);\n            int newDefaultChunkCount = EditorGUILayout.IntField(SettingsContent.defaultShaderChunkCount, defaultChunkCount);\n            if (EditorGUI.EndChangeCheck() && newDefaultChunkCount >= 0 && newDefaultChunkCount != defaultChunkCount)\n            {\n                Undo.RecordObject(target, SettingsContent.undoChangedDefaultShaderChunkCountString);\n                PlayerSettings.SetDefaultShaderChunkCount_Internal(m_CurrentTarget, newDefaultChunkCount);\n                m_OnTrackSerializedObjectValueChanged?.Invoke(serializedObject);\n            }\n\n            bool oldOverride = PlayerSettings.GetOverrideShaderChunkSettingsForPlatform_Internal(m_CurrentTarget, platform.defaultTarget);\n            bool newOverride = EditorGUILayout.Toggle(SettingsContent.overrideDefaultChunkSettings, oldOverride);\n            if (oldOverride != newOverride)\n            {\n                PlayerSettings.SetOverrideShaderChunkSettingsForPlatform_Internal(m_CurrentTarget, platform.defaultTarget, newOverride);\n                m_OnTrackSerializedObjectValueChanged?.Invoke(serializedObject);\n            }\n\n            if (newOverride)\n            {\n                int currentChunkSize = PlayerSettings.GetShaderChunkSizeInMBForPlatform_Internal(m_CurrentTarget, platform.defaultTarget);\n                int newChunkSize = EditorGUILayout.IntField(SettingsContent.platformShaderChunkSize, currentChunkSize);\n                if (EditorGUI.EndChangeCheck() && newChunkSize > 0 && newChunkSize != currentChunkSize)\n                {\n                    Undo.RecordObject(target, SettingsContent.undoChangedPlatformShaderChunkSizeString);\n                    PlayerSettings.SetShaderChunkSizeInMBForPlatform_Internal(m_CurrentTarget, platform.defaultTarget, newChunkSize);\n                    m_OnTrackSerializedObjectValueChanged?.Invoke(serializedObject);\n                }\n\n                EditorGUI.BeginChangeCheck();\n                int currentChunkCount = PlayerSettings.GetShaderChunkCountForPlatform_Internal(m_CurrentTarget, platform.defaultTarget);\n                int newChunkCount = EditorGUILayout.IntField(SettingsContent.platformShaderChunkCount, currentChunkCount);\n                if (EditorGUI.EndChangeCheck() && newChunkCount >= 0 && newChunkCount != currentChunkCount)\n                {\n                    Undo.RecordObject(target, SettingsContent.undoChangedPlatformShaderChunkCountString);\n                    PlayerSettings.SetShaderChunkCountForPlatform_Internal(m_CurrentTarget, platform.defaultTarget, newChunkCount);\n                    m_OnTrackSerializedObjectValueChanged?.Invoke(serializedObject);\n                }\n            }\n        }\n\n        private void OtherSectionRenderingGUI(BuildPlatform platform, ISettingEditorExtension settingsExtension)\n        {\n            // Rendering related settings\n            GUILayout.Label(SettingsContent.renderingTitle, EditorStyles.boldLabel);\n\n            // Color space (supported by all non deprecated platforms)\n            using (new EditorGUI.DisabledScope(EditorApplication.isPlaying)) // switching color spaces in play mode is not supported\n            {\n                EditorGUI.BeginChangeCheck();\n                int selectedValue = m_ActiveColorSpace.enumValueIndex;\n                EditorGUILayout.PropertyField(m_ActiveColorSpace, SettingsContent.activeColorSpace);\n\n                if (EditorGUI.EndChangeCheck() && IsActivePlayerSettingsEditor())\n                {\n                    if (m_ActiveColorSpace.enumValueIndex != selectedValue && EditorUtility.DisplayDialog(\"Changing Color Space\", SettingsContent.changeColorSpaceString, $\"Change to {(ColorSpace)m_ActiveColorSpace.enumValueIndex}\", \"Cancel\"))\n                    {\n                        serializedObject.ApplyModifiedProperties();\n                    }\n                    else m_ActiveColorSpace.enumValueIndex = selectedValue;\n                    GUIUtility.ExitGUI(); // Fixes case 690421\n                }\n            }\n\n            using (new EditorGUI.DisabledScope(EditorApplication.isPlaying))\n            {\n                if (BuildTargetDiscovery.TryGetBuildTarget(platform.defaultTarget, out IBuildTarget iBuildTarget) && (iBuildTarget.GraphicsPlatformProperties?.HasUnsupportedMSAAFallback ?? false))\n                    EditorGUILayout.PropertyField(m_UnsupportedMSAAFallback, SettingsContent.unsupportedMSAAFallback);\n            }\n\n            // Special cases for some platform with limitations regarding linear colorspace\n            if ((PlayerSettings.colorSpace == ColorSpace.Linear) &&\n                (null != settingsExtension) && settingsExtension.SupportsForcedSrgbBlit())\n            {\n                EditorGUILayout.PropertyField(m_ForceSRGBBlit, SettingsContent.forceSRGBBlit);\n            }\n\n            // Graphics APIs\n            using (new EditorGUI.DisabledScope(EditorApplication.isPlaying))\n            {\n                GraphicsAPIsGUI(platform.namedBuildTarget.ToBuildTargetGroup(), platform.defaultTarget);\n            }\n\n            // Output color spaces\n            ColorGamutGUI(platform);\n\n            // What we call \"Metal Validation\" is a random bunch of extra checks we do in editor in metal code\n            if (Application.platform == RuntimePlatform.OSXEditor && BuildTargetDiscovery.BuildTargetSupportsRenderer(platform, GraphicsDeviceType.Metal))\n                m_MetalAPIValidation.boolValue = EditorGUILayout.Toggle(SettingsContent.metalAPIValidation, m_MetalAPIValidation.boolValue);\n\n            // Metal\n            if (BuildTargetDiscovery.BuildTargetSupportsRenderer(platform, GraphicsDeviceType.Metal))\n            {\n                EditorGUILayout.PropertyField(m_MetalFramebufferOnly, SettingsContent.metalFramebufferOnly);\n                if (platform.namedBuildTarget == NamedBuildTarget.iOS || platform.namedBuildTarget == NamedBuildTarget.tvOS)\n                    EditorGUILayout.PropertyField(m_MetalForceHardShadows, SettingsContent.metalForceHardShadows);\n\n                int[] memorylessModeValues = { 0, 1, 2 };\n                BuildEnumPopup(m_FramebufferDepthMemorylessMode, SettingsContent.framebufferDepthMemorylessMode, memorylessModeValues, SettingsContent.memorylessModeNames);\n            }\n\n            if (!IsPreset())\n            {\n                // Multithreaded rendering\n                if (settingsExtension != null && settingsExtension.SupportsMultithreadedRendering())\n                    settingsExtension.MultithreadedRenderingGUI(platform.namedBuildTarget);\n\n                // Batching section\n                {\n                    int staticBatching, dynamicBatching;\n                    bool staticBatchingSupported = true;\n                    bool dynamicBatchingSupported = true;\n                    if (settingsExtension != null)\n                    {\n                        staticBatchingSupported = settingsExtension.SupportsStaticBatching();\n                        dynamicBatchingSupported = settingsExtension.SupportsDynamicBatching();\n                    }\n                    PlayerSettings.GetBatchingForPlatform_Internal(m_CurrentTarget, platform.defaultTarget, out staticBatching, out dynamicBatching);\n\n                    bool reset = false;\n                    if (staticBatchingSupported == false && staticBatching == 1)\n                    {\n                        staticBatching = 0;\n                        reset = true;\n                    }\n\n                    if (dynamicBatchingSupported == false && dynamicBatching == 1)\n                    {\n                        dynamicBatching = 0;\n                        reset = true;\n                    }\n\n                    if (reset)\n                    {\n                        PlayerSettings.SetBatchingForPlatform_Internal(m_CurrentTarget, platform.defaultTarget, staticBatching, dynamicBatching);\n                        m_OnTrackSerializedObjectValueChanged?.Invoke(serializedObject);\n                    }\n\n                    EditorGUI.BeginChangeCheck();\n                    using (new EditorGUI.DisabledScope(!staticBatchingSupported))\n                    {\n                        if (GUI.enabled)\n                            staticBatching = EditorGUILayout.Toggle(SettingsContent.staticBatching, staticBatching != 0) ? 1 : 0;\n                        else\n                            EditorGUILayout.Toggle(SettingsContent.staticBatching, false);\n                    }\n\n                    if (GraphicsSettings.currentRenderPipeline == null)\n                    {\n                        using (new EditorGUI.DisabledScope(!dynamicBatchingSupported))\n                        {\n                            dynamicBatching = EditorGUILayout.Toggle(SettingsContent.dynamicBatching, dynamicBatching != 0) ? 1 : 0;\n                        }\n                    }\n\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        Undo.RecordObject(target, SettingsContent.undoChangedBatchingString);\n                        PlayerSettings.SetBatchingForPlatform_Internal(m_CurrentTarget, platform.defaultTarget, staticBatching, dynamicBatching);\n                        m_OnTrackSerializedObjectValueChanged?.Invoke(serializedObject);\n                    }\n                }\n\n                EditorGUILayout.IntSlider(m_SpriteBatchVertexThreshold, 300, 8000, SettingsContent.spriteBatchingVertexThreshold);\n                EditorGUILayout.IntSlider(m_SpriteBatchMaxVertexCount, 1024, 65535, SettingsContent.spriteBatchingMaxVertexCount);\n            }\n\n            bool hdrDisplaySupported = false;\n            bool gfxJobModesSupported = false;\n            bool hdrEncodingSupportedByPlatform = (platform.namedBuildTarget.ToBuildTargetGroup() == BuildTargetGroup.Standalone || platform.namedBuildTarget == NamedBuildTarget.WebGL);\n            if (settingsExtension != null)\n            {\n                hdrDisplaySupported = settingsExtension.SupportsHighDynamicRangeDisplays();\n                gfxJobModesSupported = settingsExtension.SupportsGfxJobModes();\n                hdrEncodingSupportedByPlatform = hdrEncodingSupportedByPlatform || settingsExtension.SupportsCustomLightmapEncoding();\n            }\n            else\n            {\n                if (platform.namedBuildTarget.ToBuildTargetGroup() == BuildTargetGroup.Standalone)\n                {\n                    GraphicsDeviceType[] gfxAPIs = m_CurrentTarget.GetGraphicsAPIs_Internal(platform.defaultTarget);\n\n                    hdrDisplaySupported = gfxAPIs[0] == GraphicsDeviceType.Direct3D11 || gfxAPIs[0] == GraphicsDeviceType.Direct3D12 || gfxAPIs[0] == GraphicsDeviceType.Vulkan || gfxAPIs[0] == GraphicsDeviceType.Metal;\n                }\n            }\n\n            if (platform.namedBuildTarget.ToBuildTargetGroup() == BuildTargetGroup.Standalone)\n            {\n                GraphicsDeviceType[] gfxAPIs = m_CurrentTarget.GetGraphicsAPIs_Internal(platform.defaultTarget);\n                gfxJobModesSupported = (gfxAPIs[0] == GraphicsDeviceType.Direct3D12) || (gfxAPIs[0] == GraphicsDeviceType.Vulkan);\n            }\n            else if (platform.namedBuildTarget.ToBuildTargetGroup() == BuildTargetGroup.Android)\n            {\n                GraphicsDeviceType[] gfxAPIs = m_CurrentTarget.GetGraphicsAPIs_Internal(platform.defaultTarget);\n                gfxJobModesSupported = (gfxAPIs[0] == GraphicsDeviceType.Vulkan);\n            }\n\n            // GPU Skinning toggle (only show on relevant platforms)\n            if (!BuildTargetDiscovery.PlatformHasFlag(platform.defaultTarget, TargetAttributes.GPUSkinningNotSupported))\n            {\n                bool platformSupportsBatching = false;\n\n                GraphicsDeviceType[] gfxAPIs = m_CurrentTarget.GetGraphicsAPIs_Internal(platform.defaultTarget);\n                foreach (GraphicsDeviceType api in gfxAPIs)\n                {\n                    if (api == GraphicsDeviceType.Switch ||\n                        api == GraphicsDeviceType.PlayStation5 ||\n                        api == GraphicsDeviceType.PlayStation5NGGC ||\n                        api == GraphicsDeviceType.Direct3D11 ||\n                        api == GraphicsDeviceType.Metal ||\n                        api == GraphicsDeviceType.Vulkan ||\n                        api == GraphicsDeviceType.OpenGLES3 ||\n                        api == GraphicsDeviceType.Direct3D12)\n                    {\n                        platformSupportsBatching = true;\n                        break;\n                    }\n                    // TODO: GraphicsDeviceType.OpenGLCore does not have GPU skinning enabled yet\n                }\n\n\n                if (platformSupportsBatching)\n                {\n                    MeshDeformation currentDeformation = (MeshDeformation)m_MeshDeformation.intValue;\n\n                    EditorGUI.BeginChangeCheck();\n                    MeshDeformation newDeformation = BuildEnumPopup(SettingsContent.skinOnGPU, currentDeformation, m_MeshDeformations, SettingsContent.meshDeformations);\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        m_SkinOnGPU.boolValue = newDeformation != MeshDeformation.CPU;\n                        m_MeshDeformation.intValue = (int)newDeformation;\n                        serializedObject.ApplyModifiedProperties();\n                        ShaderUtil.RecreateSkinnedMeshResources();\n                    }\n                }\n                else\n                {\n                    // Use the original checkbox UI but preserve underlying batching mode whenever possible.\n                    // We need to do this because gpuSkinning/meshDeformation are properties which are shared between all platforms\n                    // and if the user sets gpuSkinning mode to \"enabled\", we actually want to preserve \"batchEnabled\" if it was set for other platforms.\n                    // Platforms that do not support batching but have meshDeformation == GPUBatched just silently use original non-batched code.\n\n                    {\n                        EditorGUI.BeginChangeCheck();\n                        EditorGUILayout.PropertyField(m_SkinOnGPU, SettingsContent.skinOnGPU);\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            // Preserve the value of m_MeshDeformation when possible.\n                            if (!m_SkinOnGPU.boolValue)\n                                m_MeshDeformation.intValue = (int)MeshDeformation.CPU;\n                            else\n                                m_MeshDeformation.intValue = m_MeshDeformation.intValue != (int)MeshDeformation.CPU ? m_MeshDeformation.intValue : (int)MeshDeformation.GPUBatched;\n                            serializedObject.ApplyModifiedProperties();\n                            ShaderUtil.RecreateSkinnedMeshResources();\n                        }\n                    }\n                }\n            }\n\n            bool graphicsJobsOptionEnabled = true;\n            bool graphicsJobs = PlayerSettings.GetGraphicsJobsForPlatform_Internal(m_CurrentTarget,\n                platform.namedBuildTarget.ToBuildTargetGroup() == BuildTargetGroup.Standalone ? EditorUserBuildSettings.selectedStandaloneTarget : platform.defaultTarget);\n            bool newGraphicsJobs = graphicsJobs;\n\n            bool graphicsJobsSyncAfterKick = PlayerSettings.GetSwitchGraphicsJobsSyncAfterKick();\n            bool newGraphicsJobsSyncAfterKick = graphicsJobsSyncAfterKick;\n\n            if (platform.namedBuildTarget == NamedBuildTarget.XboxOne)\n            {\n                // on XBoxOne, we only have kGfxJobModeNative active for DX12 API and kGfxJobModeLegacy for the DX11 API\n                // no need for a drop down popup for XBoxOne\n                // also if XboxOneD3D12 is selected as GraphicsAPI, then we want to set graphics jobs and disable the user option\n                GraphicsDeviceType[] gfxAPIs = m_CurrentTarget.GetGraphicsAPIs_Internal(platform.defaultTarget);\n                GraphicsJobMode newGfxJobMode = GraphicsJobMode.Legacy;\n                if (gfxAPIs[0] == GraphicsDeviceType.XboxOneD3D12)\n                {\n                    newGfxJobMode = GraphicsJobMode.Split;\n                    if (graphicsJobs == false)\n                    {\n                        PlayerSettings.SetGraphicsJobsForPlatform_Internal(m_CurrentTarget, platform.defaultTarget, true);\n                        graphicsJobs = true;\n                        newGraphicsJobs = true;\n                    }\n                }\n                PlayerSettings.SetGraphicsJobModeForPlatform_Internal(m_CurrentTarget, platform.defaultTarget, newGfxJobMode);\n                PlayerSettings.SetGraphicsThreadingModeForPlatform_Internal(m_CurrentTarget, platform.defaultTarget, GfxThreadingMode.SplitJobs);\n                OnTargetObjectChangedDirectly();\n            }\n            else if (platform.namedBuildTarget == NamedBuildTarget.PS5)\n            {\n                // On PS5NGGC, we always have graphics jobs enabled so we disable the option in that case\n                GraphicsDeviceType[] gfxAPIs = m_CurrentTarget.GetGraphicsAPIs_Internal(platform.defaultTarget);\n                if (gfxAPIs[0] == GraphicsDeviceType.PlayStation5NGGC)\n                {\n                    graphicsJobsOptionEnabled = false;\n                    if (graphicsJobs == false)\n                    {\n                        PlayerSettings.SetGraphicsJobsForPlatform_Internal(m_CurrentTarget, platform.defaultTarget, true);\n                        OnTargetObjectChangedDirectly();\n                        graphicsJobs = true;\n                        newGraphicsJobs = true;\n                    }\n                }\n            }\n\n            if (!IsPreset())\n            {\n                EditorGUI.BeginChangeCheck();\n                GUIContent graphicsJobsGUI = SettingsContent.graphicsJobsNonExperimental;\n\n                if (BuildTargetDiscovery.TryGetBuildTarget(platform.defaultTarget, out IBuildTarget iBuildTarget) && (iBuildTarget.GraphicsPlatformProperties?.AreGraphicsJobsExperimental ?? false))\n                    graphicsJobsGUI = SettingsContent.graphicsJobsExperimental;\n\n                using (new EditorGUI.DisabledScope(!graphicsJobsOptionEnabled))\n                {\n                    if (GUI.enabled)\n                    {\n                        newGraphicsJobs = EditorGUILayout.Toggle(graphicsJobsGUI, graphicsJobs);\n                    }\n                    else\n                    {\n                        EditorGUILayout.Toggle(graphicsJobsGUI, graphicsJobs);\n                    }\n                    // Optional fallback to previous graphics jobs implementation on Switch.\n                    if (platform.namedBuildTarget == NamedBuildTarget.NintendoSwitch && newGraphicsJobs)\n                    {\n                        using (new EditorGUI.IndentLevelScope())\n                        {\n                            /* (kaychang) Currently disabled.\n                            if (GUI.enabled)\n                            {\n                                newGraphicsJobsSyncAfterKick = EditorGUILayout.Toggle(SettingsContent.graphicsJobsSyncAfterKick, graphicsJobsSyncAfterKick);\n                            }\n                            else\n                            {\n                                EditorGUILayout.Toggle(SettingsContent.graphicsJobsSyncAfterKick, graphicsJobsSyncAfterKick);\n                            }\n                            */\n                        }\n                    }\n                }\n                if (EditorGUI.EndChangeCheck() && (newGraphicsJobs != graphicsJobs))\n                {\n                    Undo.RecordObject(target, SettingsContent.undoChangedGraphicsJobsString);\n                    PlayerSettings.SetGraphicsJobsForPlatform_Internal(m_CurrentTarget,\n                        platform.namedBuildTarget.ToBuildTargetGroup() == BuildTargetGroup.Standalone ? EditorUserBuildSettings.selectedStandaloneTarget : platform.defaultTarget, newGraphicsJobs);\n\n                    OnTargetObjectChangedDirectly();\n\n                    if (IsActivePlayerSettingsEditor() && CheckApplyGraphicsJobsModeChange(platform.defaultTarget))\n                    {\n                        EditorApplication.RequestCloseAndRelaunchWithCurrentArguments();\n                        GUIUtility.ExitGUI();\n                    }\n                }\n                if (EditorGUI.EndChangeCheck() && (newGraphicsJobsSyncAfterKick != graphicsJobsSyncAfterKick))\n                {\n                    Undo.RecordObject(target, SettingsContent.undoChangedGraphicsJobsString);\n                    PlayerSettings.SetSwitchGraphicsJobsSyncAfterKick(newGraphicsJobsSyncAfterKick);\n                }\n            }\n            if (gfxJobModesSupported && newGraphicsJobs)\n            {\n                // For a platform extension to support a gfx job mode, it means it wouldn't modify it. So we check if it's the same after adjustments.\n                var checkGfxJobModeSupport = (Enum value) => { return settingsExtension != null ? settingsExtension.AdjustGfxJobMode((GraphicsJobMode)value) == (GraphicsJobMode)value : true; };\n\n                EditorGUI.BeginChangeCheck();\n                GraphicsJobMode currGfxJobMode = PlayerSettings.GetGraphicsJobModeForPlatform_Internal(m_CurrentTarget, platform.defaultTarget);\n                GraphicsJobMode newGfxJobMode = (GraphicsJobMode)EditorGUILayout.EnumPopup(SettingsContent.graphicsJobsMode, currGfxJobMode, checkGfxJobModeSupport, false);\n\n                if (EditorGUI.EndChangeCheck() && (newGfxJobMode != currGfxJobMode))\n                {\n                    Undo.RecordObject(target, SettingsContent.undoChangedGraphicsJobModeString);\n                }\n\n                GraphicsJobMode fallbackGfxJobMode = settingsExtension != null ? settingsExtension.AdjustGfxJobMode(currGfxJobMode) : currGfxJobMode;\n                // If we changed other settings and the selected gfx job mode is suddently not supported, we fallback to what the platform settings extension wants\n                if (fallbackGfxJobMode != currGfxJobMode)\n                {\n                    newGfxJobMode = fallbackGfxJobMode;\n                }\n\n                // Finally we apply the change of gfx job mode\n                if (newGfxJobMode != currGfxJobMode)\n                {\n                    PlayerSettings.SetGraphicsJobModeForPlatform_Internal(m_CurrentTarget, platform.defaultTarget, newGfxJobMode);\n\n                    if(newGfxJobMode == GraphicsJobMode.Native)\n                        PlayerSettings.SetGraphicsThreadingModeForPlatform_Internal(m_CurrentTarget, platform.defaultTarget, GfxThreadingMode.ClientWorkerNativeJobs);\n                    else if (newGfxJobMode == GraphicsJobMode.Legacy)\n                        PlayerSettings.SetGraphicsThreadingModeForPlatform_Internal(m_CurrentTarget, platform.defaultTarget, GfxThreadingMode.ClientWorkerJobs);\n                    else if (newGfxJobMode == GraphicsJobMode.Split)\n                        PlayerSettings.SetGraphicsThreadingModeForPlatform_Internal(m_CurrentTarget, platform.defaultTarget, GfxThreadingMode.SplitJobs);\n\n                    OnTargetObjectChangedDirectly();\n                    if (IsActivePlayerSettingsEditor() && CheckApplyGraphicsJobsModeChange(platform.defaultTarget))\n                    {\n                        EditorApplication.RequestCloseAndRelaunchWithCurrentArguments();\n                        GUIUtility.ExitGUI();\n                    }\n                }\n            }\n\n            if (settingsExtension != null)\n            {\n                using (new EditorGUI.DisabledScope(EditorApplication.isPlaying))\n                {\n                    settingsExtension.RenderingSectionGUI();\n                }\n            }\n\n            if ((settingsExtension != null && settingsExtension.SupportsCustomNormalMapEncoding()) && !IsPreset())\n            {\n                using (new EditorGUI.DisabledScope(EditorApplication.isPlaying || Lightmapping.isRunning))\n                {\n                    EditorGUI.BeginChangeCheck();\n                    var oldEncoding = PlayerSettings.GetNormalMapEncoding_Internal(m_CurrentTarget, platform.name);\n                    NormalMapEncoding[] encodingValues = { NormalMapEncoding.XYZ, NormalMapEncoding.DXT5nm };\n                    var newEncoding = BuildEnumPopup(SettingsContent.normalMapEncodingLabel, oldEncoding, encodingValues, SettingsContent.normalMapEncodingNames);\n                    if (EditorGUI.EndChangeCheck() && newEncoding != oldEncoding)\n                    {\n                        PlayerSettings.SetNormalMapEncoding_Internal(m_CurrentTarget, platform.name, newEncoding);\n                        m_OnTrackSerializedObjectValueChanged?.Invoke(serializedObject);\n                        GUIUtility.ExitGUI();\n                    }\n                }\n            }\n\n            // Show Lightmap Encoding and HDR Cubemap Encoding quality options\n            if (hdrEncodingSupportedByPlatform && !IsPreset())\n            {\n                using (new EditorGUI.DisabledScope(EditorApplication.isPlaying || Lightmapping.isRunning))\n                {\n                    {\n                        EditorGUI.BeginChangeCheck();\n                        LightmapEncodingQuality encodingQuality = m_CurrentTarget.GetLightmapEncodingQualityForPlatform_Internal(platform.defaultTarget);\n                        LightmapEncodingQuality[] lightmapEncodingValues = { LightmapEncodingQuality.Low, LightmapEncodingQuality.Normal, LightmapEncodingQuality.High };\n                        LightmapEncodingQuality newEncodingQuality = BuildEnumPopup(SettingsContent.lightmapEncodingLabel, encodingQuality, lightmapEncodingValues, SettingsContent.lightmapEncodingNames);\n                        if (EditorGUI.EndChangeCheck() && encodingQuality != newEncodingQuality)\n                        {\n                            m_CurrentTarget.SetLightmapEncodingQualityForPlatform_Internal(platform.defaultTarget, newEncodingQuality);\n                            m_OnTrackSerializedObjectValueChanged?.Invoke(serializedObject);\n\n                            if(IsActivePlayerSettingsEditor())\n                                Lightmapping.OnUpdateLightmapEncoding(platform.namedBuildTarget.ToBuildTargetGroup());\n\n                            GUIUtility.ExitGUI();\n                        }\n                    }\n\n                    {\n                        EditorGUI.BeginChangeCheck();\n                        HDRCubemapEncodingQuality encodingQuality = m_CurrentTarget.GetHDRCubemapEncodingQualityForPlatform_Internal(platform.defaultTarget);\n                        HDRCubemapEncodingQuality[] hdrCubemapProbeEncodingValues = { HDRCubemapEncodingQuality.Low, HDRCubemapEncodingQuality.Normal, HDRCubemapEncodingQuality.High };\n                        HDRCubemapEncodingQuality newEncodingQuality = BuildEnumPopup(SettingsContent.hdrCubemapEncodingLabel, encodingQuality, hdrCubemapProbeEncodingValues, SettingsContent.hdrCubemapEncodingNames);\n                        if (EditorGUI.EndChangeCheck() && encodingQuality != newEncodingQuality)\n                        {\n                            m_CurrentTarget.SetHDRCubemapEncodingQualityForPlatform_Internal(platform.defaultTarget, newEncodingQuality);\n                            m_OnTrackSerializedObjectValueChanged?.Invoke(serializedObject);\n\n                            if (IsActivePlayerSettingsEditor())\n                                Lightmapping.OnUpdateHDRCubemapEncoding(platform.namedBuildTarget.ToBuildTargetGroup());\n\n                            GUIUtility.ExitGUI();\n                        }\n                    }\n                }\n            }\n\n            if (!IsPreset())\n            {\n                // Light map settings\n                using (new EditorGUI.DisabledScope(EditorApplication.isPlaying || Lightmapping.isRunning))\n                {\n                    bool streamingEnabled = m_CurrentTarget.GetLightmapStreamingEnabledForPlatformGroup_Internal(platform.namedBuildTarget.ToBuildTargetGroup());\n                    int streamingPriority = m_CurrentTarget.GetLightmapStreamingPriorityForPlatformGroup_Internal(platform.namedBuildTarget.ToBuildTargetGroup());\n\n                    EditorGUI.BeginChangeCheck();\n                    streamingEnabled = EditorGUILayout.Toggle(SettingsContent.lightmapStreamingEnabled, streamingEnabled);\n                    if (streamingEnabled)\n                    {\n                        EditorGUI.indentLevel++;\n                        streamingPriority = EditorGUILayout.DelayedIntField(SettingsContent.lightmapStreamingPriority, streamingPriority);\n                        streamingPriority = Math.Clamp(streamingPriority, Texture2D.streamingMipmapsPriorityMin, Texture2D.streamingMipmapsPriorityMax);\n                        EditorGUI.indentLevel--;\n                    }\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        m_CurrentTarget.SetLightmapStreamingEnabledForPlatformGroup_Internal(platform.namedBuildTarget.ToBuildTargetGroup(), streamingEnabled);\n                        m_CurrentTarget.SetLightmapStreamingPriorityForPlatformGroup_Internal(platform.namedBuildTarget.ToBuildTargetGroup(), streamingPriority);\n                        m_OnTrackSerializedObjectValueChanged?.Invoke(serializedObject);\n\n                        if (IsActivePlayerSettingsEditor())\n                            Lightmapping.OnUpdateLightmapStreaming(platform.namedBuildTarget.ToBuildTargetGroup());\n\n                        serializedObject.ApplyModifiedProperties();\n\n                        GUIUtility.ExitGUI();\n                    }\n                }\n\n                // Tickbox for Frame Timing Stats.\n                if (platform.namedBuildTarget.ToBuildTargetGroup() == BuildTargetGroup.Standalone || platform.namedBuildTarget == NamedBuildTarget.WindowsStoreApps || platform.namedBuildTarget == NamedBuildTarget.WebGL || (settingsExtension != null && settingsExtension.SupportsFrameTimingStatistics()))\n                {\n                    EditorGUILayout.PropertyField(m_EnableFrameTimingStats, SettingsContent.enableFrameTimingStats);\n                    if (m_EnableFrameTimingStats.boolValue)\n                    {\n                        EditorGUILayout.HelpBox(SettingsContent.openGLFrameTimingStatsOnGPURecordersOffInfo.text, MessageType.Info);\n                    }\n                }\n\n                // Tickbox for OpenGL-only option to toggle Profiler GPU Recorders.\n                if (platform.namedBuildTarget == NamedBuildTarget.Standalone || platform.namedBuildTarget == NamedBuildTarget.Android || platform.namedBuildTarget == NamedBuildTarget.EmbeddedLinux  || platform.namedBuildTarget == NamedBuildTarget.QNX)\n                {\n                    EditorGUILayout.PropertyField(m_EnableOpenGLProfilerGPURecorders, SettingsContent.enableOpenGLProfilerGPURecorders);\n\n                    // Add different notes/warnings depending on the tickbox combinations.\n                    // These concern Frame Timing Stats as well as Profiler GPU Recorders,\n                    // so are listed below both to (hopefully) highlight that they're linked.\n                    if (m_EnableOpenGLProfilerGPURecorders.boolValue)\n                    {\n                        EditorGUILayout.HelpBox(SettingsContent.openGLFrameTimingStatsOffGPURecordersOnInfo.text, MessageType.Info);\n                    }\n                }\n\n                if (hdrDisplaySupported)\n                {\n                    bool requestRepaint = false;\n                    bool oldAllowHDRDisplaySupport = m_AllowHDRDisplaySupport.boolValue;\n                    EditorGUILayout.PropertyField(m_AllowHDRDisplaySupport, SettingsContent.allowHDRDisplay);\n                    if (oldAllowHDRDisplaySupport != m_AllowHDRDisplaySupport.boolValue)\n                        requestRepaint = true;\n\n                    using (new EditorGUI.DisabledScope(!m_AllowHDRDisplaySupport.boolValue))\n                    {\n                        using (new EditorGUI.IndentLevelScope())\n                        {\n                            bool oldUseHDRDisplay = m_UseHDRDisplay.boolValue;\n                            EditorGUILayout.PropertyField(m_UseHDRDisplay, SettingsContent.useHDRDisplay);\n\n                            if (oldUseHDRDisplay != m_UseHDRDisplay.boolValue)\n                                requestRepaint = true;\n\n                            if (platform.namedBuildTarget.ToBuildTargetGroup() == BuildTargetGroup.Standalone || platform.namedBuildTarget == NamedBuildTarget.WindowsStoreApps || platform.namedBuildTarget == NamedBuildTarget.iOS)\n                            {\n                                using (new EditorGUI.DisabledScope(!m_UseHDRDisplay.boolValue))\n                                {\n                                    using (new EditorGUI.IndentLevelScope())\n                                    {\n                                        EditorGUI.BeginChangeCheck();\n                                        HDRDisplayBitDepth oldBitDepth = (HDRDisplayBitDepth)m_HDRBitDepth.intValue;\n                                        HDRDisplayBitDepth[] bitDepthValues = { HDRDisplayBitDepth.BitDepth10, HDRDisplayBitDepth.BitDepth16 };\n                                        GUIContent hdrBitDepthLabel = EditorGUIUtility.TrTextContent(\"Swap Chain Bit Depth\", \"Affects the bit depth of the final swap chain format and color space.\");\n                                        GUIContent[] hdrBitDepthNames = { EditorGUIUtility.TrTextContent(\"Bit Depth 10\"), EditorGUIUtility.TrTextContent(\"Bit Depth 16\") };\n\n                                        HDRDisplayBitDepth bitDepth = BuildEnumPopup(hdrBitDepthLabel, oldBitDepth, bitDepthValues, hdrBitDepthNames);\n                                        if (EditorGUI.EndChangeCheck())\n                                        {\n                                            m_HDRBitDepth.intValue = (int)bitDepth;\n                                            if (oldBitDepth != bitDepth)\n                                                requestRepaint = true;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    if (m_AllowHDRDisplaySupport.boolValue && GraphicsSettings.currentRenderPipeline != null && !SupportedRenderingFeatures.active.supportsHDR)\n                    {\n                        EditorGUILayout.HelpBox(SettingsContent.hdrOutputRequireHDRRenderingWarning.text, MessageType.Info);\n                    }\n\n                    if (requestRepaint)\n                        EditorApplication.RequestRepaintAllViews();\n                }\n\n                // Virtual Texturing settings\n                using (new EditorGUI.DisabledScope(EditorApplication.isPlaying || EditorApplication.isCompiling))\n                {\n                    EditorGUI.BeginChangeCheck();\n                    bool toggledValue =  EditorGUILayout.Toggle(SettingsContent.virtualTexturingSupportEnabled, m_VirtualTexturingSupportEnabled.boolValue);\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        if (IsActivePlayerSettingsEditor())\n                        {\n                            if (PlayerSettings.OnVirtualTexturingChanged())\n                            {\n                                // updating the property only after the user agrees to restart the editor for an active build profile\n                                // because on Windows, the dialog gives control back to the editor *before* the user interacts with it\n                                // so if the property is updated at that point, the editor will call ApplyModifiedProperties\n                                // which will call PlayerSettings::AwakeFromLoad and then PlayerSettings::SyncCurrentVirtualTexturingState\n                                // and incorrectly check against a value in its intermediate state\n                                m_VirtualTexturingSupportEnabled.boolValue = toggledValue;\n                                PlayerSettings.SetVirtualTexturingSupportEnabled(toggledValue);\n                                m_VirtualTexturingSupportEnabled.serializedObject.ApplyModifiedProperties();\n                                EditorApplication.delayCall += EditorApplication.RestartEditorAndRecompileScripts;\n                            }\n                        }\n                        else\n                        {\n                            // updating the serialized property for an inactive build profile is fine because it won't show a restart prompt\n                            // and SyncCurrentVirtualTexturingState will only work for active build profiles\n                            m_VirtualTexturingSupportEnabled.boolValue = toggledValue;\n                        }\n                        GUIUtility.ExitGUI();\n                    }\n                }\n\n                if (PlayerSettings.GetVirtualTexturingSupportEnabled())\n                {\n                    // Test Platform compatibility\n                    bool platformSupportsVT = UnityEngine.Rendering.VirtualTexturingEditor.Building.IsPlatformSupportedForPlayer(platform.defaultTarget);\n                    if (!platformSupportsVT)\n                    {\n                        EditorGUILayout.HelpBox(SettingsContent.virtualTexturingUnsupportedPlatformWarning.text, MessageType.Warning);\n                    }\n\n                    // Test for all three 'Automatic Graphics API for X' checkboxes and report API/Platform-specific error\n                    if (platform.namedBuildTarget.ToBuildTargetGroup() == BuildTargetGroup.Standalone)\n                    {\n                        var duplicatedBuildTargetCheck = new List<String>();\n                        foreach (var buildTarget in BuildTargetDiscovery.StandaloneBuildTargets)\n                        {\n                            if (BuildTargetDiscovery.TryGetBuildTarget(buildTarget, out IBuildTarget iBuildTarget))\n                            {\n                                if (duplicatedBuildTargetCheck.Contains(iBuildTarget.TargetName)) // Win64 and Win have the same target name and would duplicate the hint box\n                                    continue;\n\n                                duplicatedBuildTargetCheck.Add(iBuildTarget.TargetName);\n\n                                ShowWarningIfVirtualTexturingUnsupportedByAPI(iBuildTarget, true);\n                            }\n                        }\n                    }\n                    else\n                    {\n                        if (platformSupportsVT && BuildTargetDiscovery.TryGetBuildTarget(platform.defaultTarget, out IBuildTarget iBuildTarget))\n                            ShowWarningIfVirtualTexturingUnsupportedByAPI(iBuildTarget, false);\n                    }\n                }\n            }\n            if (!IsPreset())\n                EditorGUILayout.Space();\n\n            Stereo360CaptureGUI(platform.namedBuildTarget.ToBuildTargetGroup());\n\n            using (new EditorGUI.DisabledScope(EditorApplication.isPlaying || EditorApplication.isCompiling))\n            {\n                var target = platform.namedBuildTarget.ToBuildTargetGroup();\n                bool debugModeEnabled = m_CurrentTarget.GetLoadStoreDebugModeEnabledForPlatformGroup_Internal(target);\n                bool debugModeEditorOnly = m_CurrentTarget.GetLoadStoreDebugModeEditorOnlyForPlatformGroup_Internal(target);\n\n                EditorGUI.BeginChangeCheck();\n                debugModeEnabled = EditorGUILayout.Toggle(SettingsContent.loadStoreDebugModeCheckbox, debugModeEnabled);\n                if (debugModeEnabled)\n                {\n                    EditorGUI.indentLevel++;\n                    debugModeEditorOnly = EditorGUILayout.Toggle(SettingsContent.loadStoreDebugModeEditorOnlyCheckbox, debugModeEditorOnly);\n                    EditorGUI.indentLevel--;\n                }\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_CurrentTarget.SetLoadStoreDebugModeEnabledForPlatformGroup_Internal(target, debugModeEnabled);\n                    m_CurrentTarget.SetLoadStoreDebugModeEditorOnlyForPlatformGroup_Internal(target, debugModeEditorOnly);\n                    OnTargetObjectChangedDirectly();\n\n                    GUIUtility.ExitGUI();\n                }\n            }\n\n            EditorGUILayout.Space();\n        }\n\n        private bool VirtualTexturingInvalidGfxAPI(BuildTarget target, bool checkEditor)\n        {\n            GraphicsDeviceType[] gfxTypes = m_CurrentTarget.GetGraphicsAPIs_Internal(target);\n\n            bool supportedAPI = true;\n            foreach (GraphicsDeviceType api in gfxTypes)\n            {\n                supportedAPI &= UnityEngine.Rendering.VirtualTexturingEditor.Building.IsRenderAPISupported(api, target, checkEditor);\n            }\n\n            return !supportedAPI;\n        }\n\n        private static readonly Dictionary<IBuildTarget, GUIContent> virtualTexturingUnsupportedAPIContents = new();\n\n        void ShowWarningIfVirtualTexturingUnsupportedByAPI(IBuildTarget buildTarget, bool checkEditor)\n        {\n            GUIContent warningText = null;\n            if(!VirtualTexturingInvalidGfxAPI((BuildTarget)buildTarget.GetLegacyId, checkEditor))\n                return;\n\n            if (virtualTexturingUnsupportedAPIContents.TryGetValue(buildTarget, out var guiContent))\n                warningText = guiContent;\n            else\n                warningText = virtualTexturingUnsupportedAPIContents[buildTarget] = EditorGUIUtility.TrTextContent($\"The target {buildTarget.DisplayName} graphics API does not support Virtual Texturing. To target compatible graphics APIs, uncheck 'Auto Graphics API', and remove OpenGL ES 2/3 and OpenGLCoreOpenGLCore.\");\n\n            if (warningText != null)\n                EditorGUILayout.HelpBox(warningText.text, MessageType.Warning);\n        }\n\n        // WebGPU\n        private static IReadOnlyList<BuildTarget> k_WebGPUSupportedBuildTargets => new List<BuildTarget> {\n            BuildTarget.WebGL,\n            // The following is Google's Dawn native implementatation for WebGPU.\n            BuildTarget.StandaloneWindows,\n            BuildTarget.StandaloneWindows64,\n            // Dawn currently isn't supported on OSX or Linux.\n        };\n\n        private bool CheckIfWebGPUInGfxAPIList()\n        {\n            foreach (var target in k_WebGPUSupportedBuildTargets)\n            {\n                if (m_CurrentTarget.GetGraphicsAPIs_Internal(target).Contains(GraphicsDeviceType.WebGPU))\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        private void OtherSectionIdentificationGUI(BuildPlatform platform, ISettingEditorExtension settingsExtension)\n        {\n            // Identification\n            if (settingsExtension != null && settingsExtension.HasIdentificationGUI())\n            {\n                GUILayout.Label(SettingsContent.identificationTitle, EditorStyles.boldLabel);\n                settingsExtension.IdentificationSectionGUI();\n\n                EditorGUILayout.Space();\n            }\n        }\n\n        private void OtherSectionVulkanSettingsGUI(BuildPlatform platform, ISettingEditorExtension settingsExtension)\n        {\n            // Standalone targets don't have a settingsExtension but support vulkan\n            if (settingsExtension != null && !settingsExtension.ShouldShowVulkanSettings())\n                return;\n\n            GUILayout.Label(SettingsContent.vulkanSettingsTitle, EditorStyles.boldLabel);\n            if (!IsPreset())\n            {\n                EditorGUILayout.PropertyField(m_VulkanEnableSetSRGBWrite, SettingsContent.vulkanEnableSetSRGBWrite);\n                EditorGUILayout.PropertyField(m_VulkanNumSwapchainBuffers, SettingsContent.vulkanNumSwapchainBuffers);\n\n                // Not a No-OP, VulkanNumSwapchainBuffers has native work that should run when active setting changes.\n                if (IsActivePlayerSettingsEditor())\n                {\n                    PlayerSettings.vulkanNumSwapchainBuffers = m_VulkanNumSwapchainBuffers.uintValue;\n                }\n            }\n            EditorGUILayout.PropertyField(m_VulkanEnableLateAcquireNextImage, SettingsContent.vulkanEnableLateAcquireNextImage);\n            EditorGUILayout.PropertyField(m_VulkanEnableCommandBufferRecycling, SettingsContent.vulkanEnableCommandBufferRecycling);\n\n            if (settingsExtension != null && settingsExtension.ShouldShowVulkanSettings())\n                settingsExtension.VulkanSectionGUI();\n\n            EditorGUILayout.Space();\n        }\n\n        internal void ShowPlatformIconsByKind(PlatformIconFieldGroup iconFieldGroup, bool foldByKind = true, bool foldBySubkind = true)\n        {\n            m_IconsEditor.ShowPlatformIconsByKind(iconFieldGroup, foldByKind, foldBySubkind);\n        }\n\n        internal static GUIContent GetApplicationIdentifierError(BuildTargetGroup targetGroup)\n        {\n            if (targetGroup == BuildTargetGroup.Android)\n                return SettingsContent.packageNameError;\n\n            return SettingsContent.applicationIdentifierError;\n        }\n\n        internal void ShowApplicationIdentifierUI(BuildTargetGroup targetGroup, string label, string tooltip)\n        {\n            var overrideDefaultID = m_OverrideDefaultApplicationIdentifier.boolValue;\n            var defaultIdentifier = String.Format(\"com.{0}.{1}\", m_CompanyName.stringValue, m_ProductName.stringValue);\n            var oldIdentifier = \"\";\n            var currentIdentifier = PlayerSettings.SanitizeApplicationIdentifier(defaultIdentifier, targetGroup);\n            var buildTargetGroup = BuildPipeline.GetBuildTargetGroupName(targetGroup);\n            var warningMessage = SettingsContent.applicationIdentifierWarning.text;\n            var errorMessage = GetApplicationIdentifierError(targetGroup).text;\n\n            string GetSanitizedApplicationIdentifier()\n            {\n                var sanitizedIdentifier = PlayerSettings.SanitizeApplicationIdentifier(currentIdentifier, targetGroup);\n\n                if (currentIdentifier != oldIdentifier)\n                {\n                    if (!overrideDefaultID && !PlayerSettings.IsApplicationIdentifierValid(currentIdentifier, targetGroup))\n                        Debug.LogError(errorMessage);\n                    else if (overrideDefaultID && sanitizedIdentifier != currentIdentifier)\n                        Debug.LogWarning(warningMessage);\n                }\n\n                return sanitizedIdentifier;\n            }\n\n            if (!m_ApplicationIdentifier.serializedObject.isEditingMultipleObjects)\n            {\n                m_ApplicationIdentifier.TryGetMapEntry(buildTargetGroup, out var entry);\n\n                if (entry != null)\n                    oldIdentifier = entry.FindPropertyRelative(\"second\").stringValue;\n\n                if (currentIdentifier != oldIdentifier)\n                {\n                    if (overrideDefaultID)\n                        currentIdentifier = oldIdentifier;\n                    else\n                        m_ApplicationIdentifier.SetMapValue(buildTargetGroup, currentIdentifier);\n                }\n\n                EditorGUILayout.BeginVertical();\n                EditorGUI.BeginChangeCheck();\n\n                using (new EditorGUI.DisabledScope(!overrideDefaultID))\n                {\n                    currentIdentifier = GetSanitizedApplicationIdentifier();\n                    currentIdentifier = EditorGUILayout.TextField(EditorGUIUtility.TrTextContent(label, tooltip), currentIdentifier);\n                }\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    currentIdentifier = GetSanitizedApplicationIdentifier();\n                    m_ApplicationIdentifier.SetMapValue(buildTargetGroup, currentIdentifier);\n                }\n\n                if (currentIdentifier == \"com.Company.ProductName\" || currentIdentifier == \"com.unity3d.player\")\n                    EditorGUILayout.HelpBox(\"Don't forget to set the Application Identifier.\", MessageType.Warning);\n                else if (!PlayerSettings.IsApplicationIdentifierValid(currentIdentifier, targetGroup))\n                    EditorGUILayout.HelpBox(errorMessage, MessageType.Error);\n                else if (!overrideDefaultID && currentIdentifier != defaultIdentifier)\n                    EditorGUILayout.HelpBox(warningMessage, MessageType.Warning);\n\n                EditorGUILayout.EndVertical();\n            }\n        }\n\n        internal static void ShowBuildNumberUI(SerializedProperty prop, NamedBuildTarget buildTarget, string label, string tooltip)\n        {\n            if (!prop.serializedObject.isEditingMultipleObjects)\n            {\n                prop.TryGetMapEntry(buildTarget.TargetName, out var entry);\n\n                if (entry != null)\n                {\n                    var buildNumber = entry.FindPropertyRelative(\"second\");\n                    EditorGUILayout.PropertyField(buildNumber, EditorGUIUtility.TrTextContent(label, tooltip));\n                }\n            }\n        }\n\n        private bool ShouldRestartEditorToApplySetting()\n        {\n            return EditorUtility.DisplayDialog(\"Unity editor restart required\", \"The Unity editor must be restarted for this change to take effect.  Cancel to revert changes.\", \"Apply\", \"Cancel\");\n        }\n\n        private ScriptingImplementation GetCurrentBackendForTarget(NamedBuildTarget namedBuildTarget)\n        {\n            if (m_ScriptingBackend.TryGetMapEntry(namedBuildTarget.TargetName, out var entry))\n                return (ScriptingImplementation)entry.FindPropertyRelative(\"second\").intValue;\n            else\n                return PlayerSettings.GetDefaultScriptingBackend(namedBuildTarget);\n        }\n\n        private Il2CppCompilerConfiguration GetCurrentIl2CppCompilerConfigurationForTarget(NamedBuildTarget namedBuildTarget)\n        {\n            if (m_Il2CppCompilerConfiguration.TryGetMapEntry(namedBuildTarget.TargetName, out var entry))\n                return (Il2CppCompilerConfiguration)entry.FindPropertyRelative(\"second\").intValue;\n            else\n                return Il2CppCompilerConfiguration.Release;\n        }\n        private Il2CppCodeGeneration GetCurrentIl2CppCodeGenerationForTarget(NamedBuildTarget namedBuildTarget)\n        {\n            if (m_Il2CppCodeGeneration.TryGetMapEntry(namedBuildTarget.TargetName, out var entry))\n                return (Il2CppCodeGeneration)entry.FindPropertyRelative(\"second\").intValue;\n            else\n                return Il2CppCodeGeneration.OptimizeSpeed;\n        }\n\n        private Il2CppStacktraceInformation GetCurrentIl2CppStacktraceInformationOptionForTarget(NamedBuildTarget namedBuildTarget)\n        {\n            if (m_Il2CppStacktraceInformation.TryGetMapEntry(namedBuildTarget.TargetName, out var entry))\n                return (Il2CppStacktraceInformation)entry.FindPropertyRelative(\"second\").intValue;\n            else\n                return Il2CppStacktraceInformation.MethodOnly;\n        }\n\n        private ManagedStrippingLevel GetCurrentManagedStrippingLevelForTarget(NamedBuildTarget namedBuildTarget, ScriptingImplementation backend)\n        {\n            if (m_ManagedStrippingLevel.TryGetMapEntry(namedBuildTarget.TargetName, out var entry))\n                return (ManagedStrippingLevel)entry.FindPropertyRelative(\"second\").intValue;\n            else\n            {\n                if (backend == ScriptingImplementation.IL2CPP)\n                    return ManagedStrippingLevel.Minimal;\n                else\n                    return ManagedStrippingLevel.Disabled;\n            }\n        }\n\n        private ApiCompatibilityLevel GetApiCompatibilityLevelForTarget(NamedBuildTarget namedBuildTarget)\n        {\n            if (m_APICompatibilityLevel.TryGetMapEntry(namedBuildTarget.TargetName, out var entry))\n                return (ApiCompatibilityLevel)entry.FindPropertyRelative(\"second\").intValue;\n            else\n                // See comment in EditorOnlyPlayerSettings regarding defaultApiCompatibilityLevel\n                return (ApiCompatibilityLevel)m_DefaultAPICompatibilityLevel.intValue;\n        }\n\n        private void SetApiCompatibilityLevelForTarget(string targetGroup, ApiCompatibilityLevel apiCompatibilityLevel)\n        {\n            if (m_APICompatibilityLevel.TryGetMapEntry(targetGroup, out _))\n                m_APICompatibilityLevel.SetMapValue(targetGroup, (int)apiCompatibilityLevel);\n            else\n                // See comment in EditorOnlyPlayerSettings regarding defaultApiCompatibilityLevel\n                m_DefaultAPICompatibilityLevel.intValue = (int)apiCompatibilityLevel;\n        }\n\n        private EditorAssembliesCompatibilityLevel GetEditorAssembliesCompatibilityLevel()\n        {\n            return (EditorAssembliesCompatibilityLevel)m_EditorAssembliesCompatibilityLevel.intValue;\n        }\n\n        bool HasAnyNetFXCompatibilityLevel()\n        {\n            return m_CurrentTarget?.HasAnyNetFXCompatibilityLevel() ?? false;\n        }\n\n        private void SetEditorAssembliesCompatibilityLevel(EditorAssembliesCompatibilityLevel editorAssembliesCompatibilityLevel)\n        {\n            // We won't allow switching back to the \"Default\" value.\n            if (editorAssembliesCompatibilityLevel != EditorAssembliesCompatibilityLevel.Default)\n                m_EditorAssembliesCompatibilityLevel.intValue = (int)editorAssembliesCompatibilityLevel;\n        }\n\n        private const string kInputSystemPackageName = \"com.unity.inputsystem\";\n\n\n        private void OtherSectionConfigurationGUI(BuildPlatform platform, ISettingEditorExtension settingsExtension)\n        {\n            // Configuration\n            GUILayout.Label(SettingsContent.configurationTitle, EditorStyles.boldLabel);\n\n            // scripting runtime settings in play mode are not supported\n            using (new EditorGUI.DisabledScope(EditorApplication.isPlaying))\n            {\n                // Scripting back-end\n                bool allowCompilerConfigurationSelection = false;\n                ScriptingImplementation currentBackend = GetCurrentBackendForTarget(platform.namedBuildTarget);\n                using (new EditorGUI.DisabledScope(m_SerializedObject.isEditingMultipleObjects))\n                {\n                    using (var horizontal = new EditorGUILayout.HorizontalScope())\n                    {\n                        using (var propertyScope = new EditorGUI.PropertyScope(horizontal.rect, GUIContent.none, m_ScriptingBackend))\n                        {\n                            IScriptingImplementations scripting = ModuleManager.GetScriptingImplementations(platform.namedBuildTarget);\n\n                            if (scripting == null)\n                            {\n                                allowCompilerConfigurationSelection = true; // All platforms that support only one scripting backend are IL2CPP platforms\n                                BuildDisabledEnumPopup(SettingsContent.scriptingDefault, SettingsContent.scriptingBackend);\n                            }\n                            else\n                            {\n                                var backends = scripting.Enabled();\n\n                                allowCompilerConfigurationSelection = currentBackend == ScriptingImplementation.IL2CPP && scripting.AllowIL2CPPCompilerConfigurationSelection();\n                                ScriptingImplementation newBackend;\n\n                                if (backends.Length == 1)\n                                {\n                                    newBackend = backends[0];\n                                    BuildDisabledEnumPopup(GetNiceScriptingBackendName(backends[0]), SettingsContent.scriptingBackend);\n                                }\n                                else\n                                {\n                                    newBackend = BuildEnumPopup(SettingsContent.scriptingBackend, currentBackend, backends, GetNiceScriptingBackendNames(backends));\n                                }\n\n                                if (newBackend != currentBackend)\n                                {\n                                    m_ScriptingBackend.SetMapValue(platform.namedBuildTarget.TargetName, (int)newBackend);\n                                    currentBackend = newBackend;\n                                }\n                            }\n                        }\n                    }\n                }\n\n                // Api Compatibility Level\n                using (new EditorGUI.DisabledScope(m_SerializedObject.isEditingMultipleObjects))\n                {\n                    using (var horizontal = new EditorGUILayout.HorizontalScope())\n                    {\n                        using (var propertyScope = new EditorGUI.PropertyScope(horizontal.rect, GUIContent.none, m_APICompatibilityLevel))\n                        {\n                            var currentAPICompatibilityLevel = GetApiCompatibilityLevelForTarget(platform.namedBuildTarget);\n                            var availableCompatibilityLevels = new ApiCompatibilityLevel[] { ApiCompatibilityLevel.NET_Unity_4_8, ApiCompatibilityLevel.NET_Standard };\n\n                            var newAPICompatibilityLevel = BuildEnumPopup(\n                                SettingsContent.apiCompatibilityLevel,\n                                currentAPICompatibilityLevel,\n                                availableCompatibilityLevels,\n                                GetNiceApiCompatibilityLevelNames(availableCompatibilityLevels)\n                            );\n\n                            if (newAPICompatibilityLevel != currentAPICompatibilityLevel)\n                            {\n                                SetApiCompatibilityLevelForTarget(platform.namedBuildTarget.TargetName, newAPICompatibilityLevel);\n\n                                if (platform.IsActive())\n                                {\n                                    SetReason(RecompileReason.apiCompatibilityLevelModified);\n                                }\n                            }\n                        }\n                    }\n                }\n\n                // Editor Assemblies Compatibility level\n                using (new EditorGUI.DisabledScope(m_SerializedObject.isEditingMultipleObjects || HasAnyNetFXCompatibilityLevel()))\n                {\n                    using (var horizontal = new EditorGUILayout.HorizontalScope())\n                    {\n                        using (var propertyScope = new EditorGUI.PropertyScope(horizontal.rect, GUIContent.none, m_EditorAssembliesCompatibilityLevel))\n                        {\n                            var currentEditorAssembliesCompatibilityLevel = GetEditorAssembliesCompatibilityLevel();\n\n                            List<EditorAssembliesCompatibilityLevel> availableEditorAssemblyCompatibilityLevels = new List<EditorAssembliesCompatibilityLevel>(3);\n                            if (currentEditorAssembliesCompatibilityLevel == EditorAssembliesCompatibilityLevel.Default)\n                            {\n                                availableEditorAssemblyCompatibilityLevels.Add(EditorAssembliesCompatibilityLevel.Default);\n                            }\n\n                            availableEditorAssemblyCompatibilityLevels.Add(EditorAssembliesCompatibilityLevel.NET_Unity_4_8);\n                            availableEditorAssemblyCompatibilityLevels.Add(EditorAssembliesCompatibilityLevel.NET_Standard);\n\n                            var newEditorAssembliesCompatibilityLevel = BuildEnumPopup(\n                               SettingsContent.editorAssembliesCompatibilityLevel,\n                               currentEditorAssembliesCompatibilityLevel,\n                               availableEditorAssemblyCompatibilityLevels.ToArray(),\n                               GetNiceEditorAssembliesCompatibilityLevelNames(availableEditorAssemblyCompatibilityLevels.ToArray())\n                           );\n                            if (newEditorAssembliesCompatibilityLevel != currentEditorAssembliesCompatibilityLevel)\n                            {\n                                SetEditorAssembliesCompatibilityLevel(newEditorAssembliesCompatibilityLevel);\n\n                                if (platform.IsActive())\n                                {\n                                    SetReason(RecompileReason.editorAssembliesCompatibilityLevelModified);\n                                }\n                            }\n                        }\n                    }\n                }\n\n                // Il2cpp Code Generation\n                using (new EditorGUI.DisabledScope(m_SerializedObject.isEditingMultipleObjects))\n                {\n                    using (var horizontal = new EditorGUILayout.HorizontalScope())\n                    {\n                        using (var propertyScope = new EditorGUI.PropertyScope(horizontal.rect, GUIContent.none, m_Il2CppCodeGeneration))\n                        {\n                            using (new EditorGUI.DisabledScope(currentBackend != ScriptingImplementation.IL2CPP))\n                            {\n                                var currentCodeGeneration = GetCurrentIl2CppCodeGenerationForTarget(platform.namedBuildTarget);\n\n                                var codeGenerationValues = new[] { Il2CppCodeGeneration.OptimizeSpeed, Il2CppCodeGeneration.OptimizeSize };\n                                var newCodeGeneration = BuildEnumPopup(SettingsContent.il2cppCodeGeneration, currentCodeGeneration, codeGenerationValues, SettingsContent.il2cppCodeGenerationNames);\n\n                                if (currentCodeGeneration != newCodeGeneration)\n                                    m_Il2CppCodeGeneration.SetMapValue(platform.namedBuildTarget.TargetName, (int)newCodeGeneration);\n                            }\n                        }\n                    }\n                }\n\n                // Il2cpp Compiler Configuration\n                using (new EditorGUI.DisabledScope(m_SerializedObject.isEditingMultipleObjects))\n                {\n                    using (var horizontal = new EditorGUILayout.HorizontalScope())\n                    {\n                        using (var propertyScope = new EditorGUI.PropertyScope(horizontal.rect, GUIContent.none, m_Il2CppCompilerConfiguration))\n                        {\n                            using (new EditorGUI.DisabledScope(!allowCompilerConfigurationSelection))\n                            {\n                                Il2CppCompilerConfiguration currentConfiguration = GetCurrentIl2CppCompilerConfigurationForTarget(platform.namedBuildTarget);\n\n                                var configurations = GetIl2CppCompilerConfigurations();\n                                var configurationNames = GetIl2CppCompilerConfigurationNames();\n\n                                var newConfiguration = BuildEnumPopup(SettingsContent.il2cppCompilerConfiguration, currentConfiguration, configurations, configurationNames);\n\n                                if (currentConfiguration != newConfiguration)\n                                    m_Il2CppCompilerConfiguration.SetMapValue(platform.namedBuildTarget.TargetName, (int)newConfiguration);\n                            }\n                        }\n                    }\n                }\n\n                // Il2Cpp Stacktrace Configuration\n                using (new EditorGUI.DisabledScope(currentBackend != ScriptingImplementation.IL2CPP || platform.namedBuildTarget == NamedBuildTarget.WebGL))\n                {\n                    Il2CppStacktraceInformation config = GetCurrentIl2CppStacktraceInformationOptionForTarget(platform.namedBuildTarget);\n\n                    var newConfiguration = BuildEnumPopup(SettingsContent.il2cppStacktraceInformation, config,\n                        GetIl2CppStacktraceOptions(), GetIl2CppStacktraceOptionNames());\n\n                    if (config != newConfiguration)\n                        m_Il2CppStacktraceInformation.SetMapValue(platform.namedBuildTarget.TargetName, (int)newConfiguration);\n                }\n\n                bool gcIncrementalEnabled = BuildPipeline.IsFeatureSupported(\"ENABLE_SCRIPTING_GC_WBARRIERS\", platform.defaultTarget);\n\n                using (new EditorGUI.DisabledScope(!gcIncrementalEnabled))\n                {\n                    var oldValue = m_GCIncremental.boolValue;\n                    EditorGUILayout.PropertyField(m_GCIncremental, SettingsContent.gcIncremental);\n                    if (m_GCIncremental.boolValue != oldValue)\n                    {\n                        if (!IsActivePlayerSettingsEditor())\n                        {\n                            return;\n                        }\n                        // Give the user a chance to change mind and revert changes.\n                        if (ShouldRestartEditorToApplySetting())\n                        {\n                            m_GCIncremental.serializedObject.ApplyModifiedProperties();\n                            EditorApplication.delayCall += EditorApplication.RestartEditorAndRecompileScripts;\n                        }\n                        else\n                            m_GCIncremental.boolValue = oldValue;\n                    }\n                }\n            }\n\n            var insecureHttp = BuildEnumPopup(m_InsecureHttpOption, SettingsContent.insecureHttpOption, new[] { InsecureHttpOption.NotAllowed, InsecureHttpOption.DevelopmentOnly, InsecureHttpOption.AlwaysAllowed }, SettingsContent.insecureHttpOptions);\n            if (insecureHttp == InsecureHttpOption.AlwaysAllowed)\n                EditorGUILayout.HelpBox(SettingsContent.insecureHttpWarning.text, MessageType.Warning);\n\n            // Privacy permissions\n            bool showPrivacyPermissions =\n                platform.namedBuildTarget == NamedBuildTarget.iOS || platform.namedBuildTarget == NamedBuildTarget.tvOS || platform.namedBuildTarget == NamedBuildTarget.VisionOS;\n\n            if (showPrivacyPermissions)\n            {\n                EditorGUILayout.PropertyField(m_CameraUsageDescription, SettingsContent.cameraUsageDescription);\n                EditorGUILayout.PropertyField(m_MicrophoneUsageDescription, SettingsContent.microphoneUsageDescription);\n\n                if (platform.namedBuildTarget == NamedBuildTarget.iOS || platform.namedBuildTarget == NamedBuildTarget.tvOS)\n                    EditorGUILayout.PropertyField(m_LocationUsageDescription, SettingsContent.locationUsageDescription);\n            }\n\n            bool showMobileSection =\n                platform.namedBuildTarget == NamedBuildTarget.iOS ||\n                platform.namedBuildTarget == NamedBuildTarget.tvOS ||\n                platform.namedBuildTarget == NamedBuildTarget.Android ||\n                platform.namedBuildTarget == NamedBuildTarget.WindowsStoreApps;\n\n            // mobile-only settings\n            if (showMobileSection)\n            {\n                bool supportsAccelerometerFrequency =\n                    platform.namedBuildTarget == NamedBuildTarget.iOS ||\n                    platform.namedBuildTarget == NamedBuildTarget.tvOS ||\n                    platform.namedBuildTarget == NamedBuildTarget.WindowsStoreApps;\n                if (supportsAccelerometerFrequency)\n                    EditorGUILayout.PropertyField(m_AccelerometerFrequency, SettingsContent.accelerometerFrequency);\n\n                if (platform.namedBuildTarget == NamedBuildTarget.iOS || platform.namedBuildTarget == NamedBuildTarget.tvOS || platform.namedBuildTarget == NamedBuildTarget.Android)\n                {\n                    EditorGUILayout.PropertyField(m_MuteOtherAudioSources, SettingsContent.muteOtherAudioSources);\n\n                    if (m_MuteOtherAudioSources.boolValue == false && platform.namedBuildTarget == NamedBuildTarget.iOS)\n                        EditorGUILayout.HelpBox(SettingsContent.iOSExternalAudioInputNotSupported.text, MessageType.Warning);\n                }\n\n                // TVOS TODO: check what should stay or go\n                if (platform.namedBuildTarget == NamedBuildTarget.iOS || platform.namedBuildTarget == NamedBuildTarget.tvOS)\n                {\n                    if (platform.namedBuildTarget == NamedBuildTarget.iOS)\n                    {\n                        EditorGUILayout.PropertyField(m_PrepareIOSForRecording, SettingsContent.prepareIOSForRecording);\n                        EditorGUILayout.PropertyField(m_ForceIOSSpeakersWhenRecording, SettingsContent.forceIOSSpeakersWhenRecording);\n                    }\n                    EditorGUILayout.PropertyField(m_UIRequiresPersistentWiFi, SettingsContent.UIRequiresPersistentWiFi);\n                }\n            }\n\n            if (platform.namedBuildTarget == NamedBuildTarget.iOS || platform.namedBuildTarget == NamedBuildTarget.tvOS || platform.namedBuildTarget == NamedBuildTarget.VisionOS)\n                EditorGUILayout.PropertyField(m_IOSURLSchemes, SettingsContent.iOSURLSchemes, true);\n\n            // Active input handling\n            if (platform.namedBuildTarget != NamedBuildTarget.Server)\n            {\n                using (var vertical = new EditorGUILayout.VerticalScope())\n                {\n                    var currValue = m_ActiveInputHandler.intValue;\n\n                    using (var propertyScope = new EditorGUI.PropertyScope(vertical.rect, GUIContent.none, m_ActiveInputHandler))\n                    {\n                        m_ActiveInputHandler.intValue = EditorGUILayout.Popup(SettingsContent.activeInputHandling, m_ActiveInputHandler.intValue, SettingsContent.activeInputHandlingOptions);\n                    }\n\n                    if (m_ActiveInputHandler.intValue != currValue)\n                    {\n                        if (!IsActivePlayerSettingsEditor())\n                        {\n                            return;\n                        }\n                        // Give the user a chance to change mind and revert changes.\n                        if (ShouldRestartEditorToApplySetting())\n                        {\n                            m_ActiveInputHandler.serializedObject.ApplyModifiedProperties();\n                            EditorApplication.delayCall += EditorApplication.RestartEditorAndRecompileScripts;\n                        }\n                        else\n                            m_ActiveInputHandler.intValue = currValue;\n                    }\n                    var isInputSystemPackageInstalled = UnityEditor.PackageManager.PackageInfo.IsPackageRegistered(kInputSystemPackageName);\n                    if(m_ActiveInputHandler.intValue != 0 && !isInputSystemPackageInstalled)\n                    {\n                        EditorGUILayout.HelpBox(SettingsContent.activeInputHandlingError.text, MessageType.Error, true);\n                    }\n                    if(m_ActiveInputHandler.intValue != 1)\n                    {\n                        EditorGUILayout.HelpBox(SettingsContent.activeInputHandlingDeprecationError.text, MessageType.Warning, true);\n                    }\n                }\n            }\n\n            if (settingsExtension != null)\n                settingsExtension.ConfigurationSectionGUI();\n\n            EditorGUILayout.Space();\n        }\n\n        private string GetScriptingDefineSymbolsForGroup(NamedBuildTarget buildTarget)\n        {\n            string defines = string.Empty;\n            if (m_ScriptingDefines.TryGetMapEntry(buildTarget.TargetName, out var entry))\n            {\n                defines = entry.FindPropertyRelative(\"second\").stringValue;\n            }\n            return defines;\n        }\n\n        private void SetScriptingDefineSymbolsForGroup(NamedBuildTarget buildTarget, string[] defines)\n        {\n            m_ScriptingDefines.SetMapValue(buildTarget.TargetName, ScriptingDefinesHelper.ConvertScriptingDefineArrayToString(defines));\n        }\n\n        string[] GetAdditionalCompilerArgumentsForGroup(NamedBuildTarget buildTarget)\n        {\n            if (m_AdditionalCompilerArguments.TryGetMapEntry(buildTarget.TargetName, out var entry))\n            {\n                var serializedArguments = entry.FindPropertyRelative(\"second\");\n                var arguments = new string[serializedArguments.arraySize];\n\n                for (int i = 0; i < serializedArguments.arraySize; ++i)\n                {\n                    arguments[i] = serializedArguments.GetArrayElementAtIndex(i).stringValue;\n                }\n\n                return arguments;\n            }\n\n            return new string[0];\n        }\n\n        void SetAdditionalCompilerArgumentsForGroup(NamedBuildTarget buildTarget, string[] arguments)\n        {\n            m_AdditionalCompilerArguments.SetMapValue(buildTarget.TargetName, arguments);\n        }\n\n        bool GetCaptureStartupLogsForTarget(NamedBuildTarget buildTarget)\n        {\n            if (m_CaptureStartupLogs.TryGetMapEntry(buildTarget.TargetName, out var entry))\n            {\n                if (entry != null)\n                    return entry.FindPropertyRelative(\"second\").boolValue;\n            }\n            return buildTarget == NamedBuildTarget.Server ? true : false;\n        }\n\n        private void OtherSectionScriptCompilationGUI(BuildPlatform platform)\n        {\n            // Configuration\n            GUILayout.Label(SettingsContent.scriptCompilationTitle, EditorStyles.boldLabel);\n\n            // User script defines\n            using (new EditorGUI.DisabledScope(m_SerializedObject.isEditingMultipleObjects))\n            {\n                using (var vertical = new EditorGUILayout.VerticalScope())\n                {\n                    if (serializedScriptingDefines == null || scriptingDefineSymbolsList == null)\n                    {\n                        InitReorderableScriptingDefineSymbolsList(platform.namedBuildTarget);\n                    }\n\n                    if (lastNamedBuildTarget.TargetName == platform.namedBuildTarget.TargetName)\n                    {\n                        scriptingDefineSymbolsList.DoLayoutList();\n                    }\n                    else\n                    {\n                        // If platform changes, update define symbols\n                        serializedScriptingDefines = GetScriptingDefineSymbolsForGroup(platform.namedBuildTarget);\n                        UpdateScriptingDefineSymbolsLists();\n                    }\n\n                    using (new EditorGUILayout.HorizontalScope())\n                    {\n                        GUILayout.FlexibleSpace();\n\n                        var GUIState = GUI.enabled;\n\n\n                        GUI.enabled = serializedScriptingDefines.Count() > 0;\n\n                        if (GUILayout.Button(SettingsContent.scriptingDefineSymbolsCopyDefines, EditorStyles.miniButton))\n                        {\n                            EditorGUIUtility.systemCopyBuffer = PlayerSettings.GetScriptingDefineSymbols(platform.namedBuildTarget);\n                        }\n\n                        GUI.enabled = hasScriptingDefinesBeenModified;\n\n                        if (GUILayout.Button(SettingsContent.scriptingDefineSymbolsApplyRevert, EditorStyles.miniButton))\n                        {\n                            // Make sure to remove focus from reorderable list text field on revert\n                            GUI.FocusControl(null);\n\n                            UpdateScriptingDefineSymbolsLists();\n                        }\n\n                        if (GUILayout.Button(SettingsContent.scriptingDefineSymbolsApply, EditorStyles.miniButton))\n                        {\n                            // Make sure to remove focus from reorderable list text field on apply\n                            GUI.FocusControl(null);\n\n                            SetScriptingDefineSymbolsForGroup(platform.namedBuildTarget, scriptingDefinesList.ToArray());\n\n                            // Get Scripting Define Symbols without duplicates\n                            serializedScriptingDefines = GetScriptingDefineSymbolsForGroup(platform.namedBuildTarget);\n                            UpdateScriptingDefineSymbolsLists();\n\n                            if (platform.IsActive())\n                                SetReason(RecompileReason.scriptingDefineSymbolsModified);\n                        }\n\n                        // Set previous GUIState\n                        GUI.enabled = GUIState;\n                    }\n\n                    scriptingDefinesControlID = EditorGUIUtility.s_LastControlID;\n                }\n\n                EditorGUILayout.Space();\n\n                using (var vertical = new EditorGUILayout.VerticalScope())\n                {\n                    if (serializedAdditionalCompilerArguments == null || additionalCompilerArgumentsReorderableList == null)\n                    {\n                        InitReorderableAdditionalCompilerArgumentsList(platform.namedBuildTarget);\n                    }\n\n                    using (new EditorGUI.PropertyScope(vertical.rect, GUIContent.none, m_AdditionalCompilerArguments))\n                    {\n                        if (lastNamedBuildTarget.TargetName == platform.namedBuildTarget.TargetName)\n                        {\n                            additionalCompilerArgumentsReorderableList.DoLayoutList();\n                        }\n                        else\n                        {\n                            // If platform changes, update define symbols\n                            serializedAdditionalCompilerArguments = GetAdditionalCompilerArgumentsForGroup(platform.namedBuildTarget);\n                            UpdateAdditionalCompilerArgumentsLists();\n                        }\n\n                        using (new EditorGUILayout.HorizontalScope())\n                        {\n                            GUILayout.FlexibleSpace();\n\n                            using (new EditorGUI.DisabledScope(!hasAdditionalCompilerArgumentsBeenModified))\n                            {\n                                if (GUILayout.Button(SettingsContent.scriptingDefineSymbolsApplyRevert, EditorStyles.miniButton, GUILayout.ExpandWidth(false)))\n                                {\n                                    UpdateAdditionalCompilerArgumentsLists();\n                                }\n\n                                if (GUILayout.Button(SettingsContent.scriptingDefineSymbolsApply, EditorStyles.miniButton, GUILayout.ExpandWidth(false)))\n                                {\n                                    SetAdditionalCompilerArgumentsForGroup(platform.namedBuildTarget, additionalCompilerArgumentsList.ToArray());\n\n                                    // Get Additional Compiler Arguments without duplicates\n                                    serializedAdditionalCompilerArguments = GetAdditionalCompilerArgumentsForGroup(platform.namedBuildTarget);\n                                    UpdateAdditionalCompilerArgumentsLists();\n\n                                    if (platform.IsActive())\n                                    {\n                                        SetReason(RecompileReason.additionalCompilerArgumentsModified);\n                                    }\n                                }\n                            }\n                        }\n                    }\n                    //We want to cache latest build target only after rendering both Scripting Defines and Additional Args\n                    //Because both elements share the same logic\n                    lastNamedBuildTarget = platform.namedBuildTarget;\n                }\n            }\n\n            // Suppress common warnings\n            EditorGUILayout.PropertyField(m_SuppressCommonWarnings, SettingsContent.suppressCommonWarnings);\n            if (serializedSuppressCommonWarnings != m_SuppressCommonWarnings.boolValue)\n            {\n                serializedSuppressCommonWarnings = m_SuppressCommonWarnings.boolValue;\n                SetReason(RecompileReason.suppressCommonWarningsModified);\n            }\n\n            // Allow unsafe code\n            EditorGUILayout.PropertyField(m_AllowUnsafeCode, SettingsContent.allowUnsafeCode);\n            if (serializedAllowUnsafeCode != m_AllowUnsafeCode.boolValue)\n            {\n                serializedAllowUnsafeCode = m_AllowUnsafeCode.boolValue;\n                SetReason(RecompileReason.allowUnsafeCodeModified);\n            }\n\n            // Use deterministic compliation\n            EditorGUILayout.PropertyField(m_UseDeterministicCompilation, SettingsContent.useDeterministicCompilation);\n            if (serializedUseDeterministicCompilation != m_UseDeterministicCompilation.boolValue)\n            {\n                serializedUseDeterministicCompilation = m_UseDeterministicCompilation.boolValue;\n                SetReason(RecompileReason.useDeterministicCompilationModified);\n            }\n        }\n\n        void DrawTextField(Rect rect, int index)\n        {\n            // Handle list selection before the TextField grabs input\n            Event evt = Event.current;\n            if (evt.type == EventType.MouseDown && rect.Contains(evt.mousePosition))\n            {\n                if (scriptingDefineSymbolsList.index != index)\n                {\n                    scriptingDefineSymbolsList.index = index;\n                    scriptingDefineSymbolsList.onSelectCallback?.Invoke(scriptingDefineSymbolsList);\n                }\n            }\n\n            string define = scriptingDefinesList[index];\n            scriptingDefinesList[index] = EditorGUI.TextField(rect, scriptingDefinesList[index]);\n\n            if (!scriptingDefinesList[index].Equals(define))\n                SetScriptingDefinesListDirty();\n        }\n\n        void DrawTextFieldAdditionalCompilerArguments(Rect rect, int index)\n        {\n            // Handle list selection before the TextField grabs input\n            Event evt = Event.current;\n            if (evt.type == EventType.MouseDown && rect.Contains(evt.mousePosition))\n            {\n                if (additionalCompilerArgumentsReorderableList.index != index)\n                {\n                    additionalCompilerArgumentsReorderableList.index = index;\n                    additionalCompilerArgumentsReorderableList.onSelectCallback?.Invoke(additionalCompilerArgumentsReorderableList);\n                }\n            }\n\n            string additionalCompilerArgument = additionalCompilerArgumentsList[index];\n            additionalCompilerArgumentsList[index] = GUI.TextField(rect, additionalCompilerArgumentsList[index]);\n            if (!additionalCompilerArgumentsList[index].Equals(additionalCompilerArgument))\n                SetAdditionalCompilerArgumentListDirty();\n        }\n\n        void AddScriptingDefineCallback(ReorderableList list)\n        {\n            scriptingDefinesList.Add(\"\");\n            SetScriptingDefinesListDirty();\n        }\n\n        void RemoveScriptingDefineCallback(ReorderableList list)\n        {\n            scriptingDefinesList.RemoveAt(list.index);\n            SetScriptingDefinesListDirty();\n        }\n\n        void DrawScriptingDefinesHeaderCallback(Rect rect)\n        {\n            using (new EditorGUI.PropertyScope(rect, GUIContent.none, m_ScriptingDefines))\n            {\n                GUI.Label(rect, SettingsContent.scriptingDefineSymbols, EditorStyles.label);\n            }\n        }\n\n        void SetScriptingDefinesListDirty(ReorderableList list = null)\n        {\n            hasScriptingDefinesBeenModified = true;\n        }\n\n        void AddAdditionalCompilerArgumentCallback(ReorderableList list)\n        {\n            additionalCompilerArgumentsList.Add(\"\");\n            SetAdditionalCompilerArgumentListDirty();\n        }\n\n        void RemoveAdditionalCompilerArgumentCallback(ReorderableList list)\n        {\n            additionalCompilerArgumentsList.RemoveAt(list.index);\n            SetAdditionalCompilerArgumentListDirty();\n        }\n\n        void SetAdditionalCompilerArgumentListDirty(ReorderableList list = null)\n        {\n            hasAdditionalCompilerArgumentsBeenModified = true;\n        }\n\n        private void OtherSectionOptimizationGUI(BuildPlatform platform)\n        {\n            // Optimization\n            GUILayout.Label(SettingsContent.optimizationTitle, EditorStyles.boldLabel);\n\n            if (platform.namedBuildTarget == NamedBuildTarget.Server)\n                EditorGUILayout.PropertyField(m_DedicatedServerOptimizations, SettingsContent.dedicatedServerOptimizations);\n\n            EditorGUILayout.PropertyField(m_BakeCollisionMeshes, SettingsContent.bakeCollisionMeshes);\n\n            if (IsPreset())\n                EditorGUI.indentLevel++;\n\n            EditorGUILayout.PropertyField(m_PreloadedAssets, SettingsContent.preloadedAssets, true);\n\n            if (IsPreset())\n                EditorGUI.indentLevel--;\n\n            bool platformSupportsStripping = !BuildTargetDiscovery.PlatformGroupHasFlag(platform.namedBuildTarget.ToBuildTargetGroup(), TargetAttributes.StrippingNotSupported);\n\n            if (platformSupportsStripping)\n            {\n                ScriptingImplementation backend = GetCurrentBackendForTarget(platform.namedBuildTarget);\n                if (BuildPipeline.IsFeatureSupported(\"ENABLE_ENGINE_CODE_STRIPPING\", platform.defaultTarget) && backend == ScriptingImplementation.IL2CPP)\n                    EditorGUILayout.PropertyField(m_StripEngineCode, SettingsContent.stripEngineCode);\n\n                using (var vertical = new EditorGUILayout.VerticalScope())\n                {\n                    using (var propertyScope = new EditorGUI.PropertyScope(vertical.rect, GUIContent.none, m_ManagedStrippingLevel))\n                    {\n                        var availableStrippingLevels = GetAvailableManagedStrippingLevels(backend);\n                        ManagedStrippingLevel currentManagedStrippingLevel = GetCurrentManagedStrippingLevelForTarget(platform.namedBuildTarget, backend);\n                        ManagedStrippingLevel newManagedStrippingLevel;\n\n                        newManagedStrippingLevel = BuildEnumPopup(SettingsContent.managedStrippingLevel, currentManagedStrippingLevel, availableStrippingLevels, GetNiceManagedStrippingLevelNames(availableStrippingLevels));\n                        if (newManagedStrippingLevel != currentManagedStrippingLevel)\n                            m_ManagedStrippingLevel.SetMapValue(platform.namedBuildTarget.TargetName, (int)newManagedStrippingLevel);\n                    }\n                }\n            }\n\n            if (platform.namedBuildTarget == NamedBuildTarget.iOS || platform.namedBuildTarget == NamedBuildTarget.tvOS)\n            {\n                EditorGUILayout.PropertyField(m_IPhoneScriptCallOptimization, SettingsContent.iPhoneScriptCallOptimization);\n            }\n            if (platform.namedBuildTarget == NamedBuildTarget.Android)\n            {\n                EditorGUILayout.PropertyField(m_AndroidProfiler, SettingsContent.enableInternalProfiler);\n            }\n\n            EditorGUILayout.Space();\n\n            // Vertex compression flags dropdown\n            VertexChannelCompressionFlags vertexFlags = (VertexChannelCompressionFlags)m_VertexChannelCompressionMask.intValue;\n            vertexFlags = (VertexChannelCompressionFlags)EditorGUILayout.EnumFlagsField(SettingsContent.vertexChannelCompressionMask, vertexFlags);\n            m_VertexChannelCompressionMask.intValue = (int)vertexFlags;\n\n            EditorGUILayout.PropertyField(m_StripUnusedMeshComponents, SettingsContent.stripUnusedMeshComponents);\n            EditorGUILayout.PropertyField(m_MipStripping, SettingsContent.mipStripping);\n\n            EditorGUILayout.Space();\n        }\n\n        static ManagedStrippingLevel[] mono_levels = new ManagedStrippingLevel[] { ManagedStrippingLevel.Disabled, ManagedStrippingLevel.Minimal, ManagedStrippingLevel.Low, ManagedStrippingLevel.Medium, ManagedStrippingLevel.High };\n        static ManagedStrippingLevel[] il2cpp_levels = new ManagedStrippingLevel[] { ManagedStrippingLevel.Minimal, ManagedStrippingLevel.Low, ManagedStrippingLevel.Medium, ManagedStrippingLevel.High };\n        // stripping levels vary based on scripting backend\n        private ManagedStrippingLevel[] GetAvailableManagedStrippingLevels(ScriptingImplementation backend)\n        {\n            if (backend == ScriptingImplementation.IL2CPP)\n            {\n                return il2cpp_levels;\n            }\n            else\n            {\n                return mono_levels;\n            }\n        }\n\n        static Il2CppCompilerConfiguration[] m_Il2cppCompilerConfigurations;\n        static GUIContent[] m_Il2cppCompilerConfigurationNames;\n\n        private Il2CppCompilerConfiguration[] GetIl2CppCompilerConfigurations()\n        {\n            if (m_Il2cppCompilerConfigurations == null)\n            {\n                m_Il2cppCompilerConfigurations = new Il2CppCompilerConfiguration[]\n                {\n                    Il2CppCompilerConfiguration.Debug,\n                    Il2CppCompilerConfiguration.Release,\n                    Il2CppCompilerConfiguration.Master,\n                };\n            }\n\n            return m_Il2cppCompilerConfigurations;\n        }\n\n        private GUIContent[] GetIl2CppCompilerConfigurationNames()\n        {\n            if (m_Il2cppCompilerConfigurationNames == null)\n            {\n                var configurations = GetIl2CppCompilerConfigurations();\n                m_Il2cppCompilerConfigurationNames = new GUIContent[configurations.Length];\n\n                for (int i = 0; i < configurations.Length; i++)\n                    m_Il2cppCompilerConfigurationNames[i] = EditorGUIUtility.TextContent(configurations[i].ToString());\n            }\n\n            return m_Il2cppCompilerConfigurationNames;\n        }\n\n        static Il2CppStacktraceInformation[] m_Il2cppStacktraceOptions;\n        static GUIContent[] m_Il2cppStacktraceOptionNames;\n\n        private Il2CppStacktraceInformation[] GetIl2CppStacktraceOptions()\n        {\n            if (m_Il2cppStacktraceOptions == null)\n                m_Il2cppStacktraceOptions = (Il2CppStacktraceInformation[])Enum.GetValues(typeof(Il2CppStacktraceInformation));\n\n            return m_Il2cppStacktraceOptions;\n        }\n\n        private GUIContent[] GetIl2CppStacktraceOptionNames()\n        {\n            if (m_Il2cppStacktraceOptionNames == null)\n            {\n                m_Il2cppStacktraceOptionNames = new GUIContent[]\n                {\n                    EditorGUIUtility.TextContent(\"Method Name\"),\n                    EditorGUIUtility.TextContent(\"Method Name, File Name, and Line Number\"),\n                };\n            }\n\n            return m_Il2cppStacktraceOptionNames;\n        }\n\n        public static bool IsLatestApiCompatibility(ApiCompatibilityLevel level)\n        {\n            return (level == ApiCompatibilityLevel.NET_4_6 || level == ApiCompatibilityLevel.NET_Standard_2_0);\n        }\n\n        private void OtherSectionLoggingGUI()\n        {\n            GUILayout.Label(SettingsContent.loggingTitle, EditorStyles.boldLabel);\n\n            using (var vertical = new EditorGUILayout.VerticalScope())\n            {\n                using (var propertyScope = new EditorGUI.PropertyScope(vertical.rect, GUIContent.none, m_StackTraceTypes))\n                {\n                    using (new EditorGUILayout.HorizontalScope())\n                    {\n                        GUILayout.Label(\"Log Type\");\n                        foreach (StackTraceLogType stackTraceLogType in Enum.GetValues(typeof(StackTraceLogType)))\n                            GUILayout.Label(stackTraceLogType.ToString(), GUILayout.Width(70));\n                    }\n\n                    foreach (LogType logType in Enum.GetValues(typeof(LogType)))\n                    {\n                        var logProperty = m_StackTraceTypes.GetArrayElementAtIndex((int)logType);\n                        using (new EditorGUILayout.HorizontalScope())\n                        {\n                            GUILayout.Label(logType.ToString(), GUILayout.MinWidth(60));\n                            foreach (StackTraceLogType stackTraceLogType in Enum.GetValues(typeof(StackTraceLogType)))\n                            {\n                                StackTraceLogType inStackTraceLogType = (StackTraceLogType)logProperty.intValue;\n                                EditorGUI.BeginChangeCheck();\n                                bool val = EditorGUILayout.ToggleLeft(\" \", inStackTraceLogType == stackTraceLogType, GUILayout.Width(65));\n                                if (EditorGUI.EndChangeCheck() && val)\n                                {\n                                    logProperty.intValue = (int)stackTraceLogType;\n\n                                    if (IsActivePlayerSettingsEditor())\n                                        PlayerSettings.SetGlobalStackTraceLogType(logType, stackTraceLogType);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            EditorGUILayout.Space();\n        }\n\n        private void Stereo360CaptureGUI(BuildTargetGroup targetGroup)\n        {\n            EditorGUILayout.PropertyField(m_Enable360StereoCapture, SettingsContent.stereo360CaptureCheckbox);\n        }\n\n        private void OtherSectionLegacyGUI(BuildPlatform platform)\n        {\n            GUILayout.Label(SettingsContent.legacyTitle, EditorStyles.boldLabel);\n\n            EditorGUILayout.PropertyField(m_LegacyClampBlendShapeWeights, SettingsContent.legacyClampBlendShapeWeights);\n\n            EditorGUILayout.Space();\n        }\n\n        private void OtherSectionCaptureLogsGUI(NamedBuildTarget namedBuildTarget)\n        {\n            GUILayout.Label(SettingsContent.captureLogsTitle, EditorStyles.boldLabel);\n\n            bool val = GetCaptureStartupLogsForTarget(namedBuildTarget);\n            bool newVal = EditorGUILayout.Toggle(SettingsContent.captureStartupLogs, val);\n            if (val != newVal)\n                m_CaptureStartupLogs.SetMapValue(namedBuildTarget.TargetName, newVal);\n\n            EditorGUILayout.Space();\n        }\n\n        private static Dictionary<ApiCompatibilityLevel, GUIContent> m_NiceApiCompatibilityLevelNames;\n        private static Dictionary<EditorAssembliesCompatibilityLevel, GUIContent> m_NiceEditorAssembliesCompatibilityLevelNames;\n        private static Dictionary<ManagedStrippingLevel, GUIContent> m_NiceManagedStrippingLevelNames;\n\n        private static GUIContent[] GetGUIContentsForValues<T>(Dictionary<T, GUIContent> contents, T[] values)\n        {\n            var names = new GUIContent[values.Length];\n\n            for (int i = 0; i < values.Length; i++)\n            {\n                if (contents.ContainsKey(values[i]))\n                    names[i] = contents[values[i]];\n                else\n                    throw new NotImplementedException(string.Format(\"Missing name for {0}\", values[i]));\n            }\n            return names;\n        }\n\n        static GUIContent[] GetNiceScriptingBackendNames(ScriptingImplementation[] scriptingBackends)\n        {\n            return scriptingBackends.Select(s => GetNiceScriptingBackendName(s)).ToArray();\n        }\n\n        static GUIContent GetNiceScriptingBackendName(ScriptingImplementation scriptingBackend)\n        {\n            switch (scriptingBackend)\n            {\n                case ScriptingImplementation.Mono2x:\n                    return SettingsContent.scriptingMono2x;\n                case ScriptingImplementation.IL2CPP:\n                    return SettingsContent.scriptingIL2CPP;\n#pragma warning disable 618\n                case ScriptingImplementation.CoreCLR:\n                    return SettingsContent.scriptingCoreCLR;\n                default:\n                    throw new ArgumentException($\"Scripting backend value {scriptingBackend} is not supported.\", nameof(scriptingBackend));\n            }\n        }\n\n        private static GUIContent[] GetNiceApiCompatibilityLevelNames(ApiCompatibilityLevel[] apiCompatibilityLevels)\n        {\n            if (m_NiceApiCompatibilityLevelNames == null)\n            {\n                m_NiceApiCompatibilityLevelNames = new Dictionary<ApiCompatibilityLevel, GUIContent>\n                {\n                    { ApiCompatibilityLevel.NET_2_0, SettingsContent.apiCompatibilityLevel_NET_2_0 },\n                    { ApiCompatibilityLevel.NET_2_0_Subset, SettingsContent.apiCompatibilityLevel_NET_2_0_Subset },\n                    { ApiCompatibilityLevel.NET_Unity_4_8, SettingsContent.apiCompatibilityLevel_NET_FW_Unity },\n                    { ApiCompatibilityLevel.NET_Standard, SettingsContent.apiCompatibilityLevel_NET_Standard },\n                };\n            }\n\n            return GetGUIContentsForValues(m_NiceApiCompatibilityLevelNames, apiCompatibilityLevels);\n        }\n\n        private static GUIContent[] GetNiceEditorAssembliesCompatibilityLevelNames(EditorAssembliesCompatibilityLevel[] editorAssembliesCompatibilityLevels)\n        {\n            if (m_NiceEditorAssembliesCompatibilityLevelNames == null)\n            {\n                m_NiceEditorAssembliesCompatibilityLevelNames = new Dictionary<EditorAssembliesCompatibilityLevel, GUIContent>\n                {\n                    { EditorAssembliesCompatibilityLevel.Default, SettingsContent.editorAssembliesCompatibilityLevel_Default },\n                    { EditorAssembliesCompatibilityLevel.NET_Unity_4_8, SettingsContent.editorAssembliesCompatibilityLevel_NET_Framework },\n                    { EditorAssembliesCompatibilityLevel.NET_Standard, SettingsContent.editorAssembliesCompatibilityLevel_NET_Standard },\n                };\n            }\n\n            return GetGUIContentsForValues(m_NiceEditorAssembliesCompatibilityLevelNames, editorAssembliesCompatibilityLevels);\n        }\n\n        private static GUIContent[] GetNiceManagedStrippingLevelNames(ManagedStrippingLevel[] managedStrippingLevels)\n        {\n            if (m_NiceManagedStrippingLevelNames == null)\n            {\n                m_NiceManagedStrippingLevelNames = new Dictionary<ManagedStrippingLevel, GUIContent>\n                {\n                    { ManagedStrippingLevel.Disabled, SettingsContent.strippingDisabled },\n                    { ManagedStrippingLevel.Minimal, SettingsContent.strippingMinimal },\n                    { ManagedStrippingLevel.Low, SettingsContent.strippingLow },\n                    { ManagedStrippingLevel.Medium, SettingsContent.strippingMedium },\n                    { ManagedStrippingLevel.High, SettingsContent.strippingHigh },\n                };\n            }\n            return GetGUIContentsForValues(m_NiceManagedStrippingLevelNames, managedStrippingLevels);\n        }\n\n        internal static void BuildPathBoxButton(SerializedProperty prop, string uiString, string directory)\n        {\n            BuildPathBoxButton(prop, uiString, directory, null, null);\n        }\n\n        internal static void BuildPathBoxButton(SerializedProperty prop, string uiString, string directory, Action onSelect, Action onChanged)\n        {\n            float h = EditorGUI.kSingleLineHeight;\n            float kLabelFloatMinW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing;\n            float kLabelFloatMaxW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing;\n            Rect r = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, h, h, EditorStyles.layerMaskField, null);\n\n            float labelWidth = EditorGUIUtility.labelWidth;\n            Rect buttonRect = new Rect(r.x + EditorGUI.indent, r.y, labelWidth - EditorGUI.indent, r.height);\n            Rect fieldRect = new Rect(r.x + labelWidth, r.y, r.width - labelWidth, r.height);\n\n            string display = (prop.stringValue.Length == 0) ? \"Not selected\" : prop.stringValue;\n            EditorGUI.LabelField(fieldRect, display, EditorStyles.label);\n\n            bool changed = false;\n            if (GUI.Button(buttonRect, EditorGUIUtility.TextContent(uiString)))\n            {\n                string prevVal = prop.stringValue;\n                string path = EditorUtility.OpenFolderPanel(EditorGUIUtility.TextContent(uiString).text, directory, \"\");\n\n                string relPath = FileUtil.GetProjectRelativePath(path);\n                prop.stringValue = (relPath != string.Empty) ? relPath : path;\n                changed = (prop.stringValue != prevVal);\n\n                if (onSelect != null)\n                    onSelect();\n\n                prop.serializedObject.ApplyModifiedProperties();\n\n                if (changed && onChanged != null)\n                    onChanged();\n\n                // Necessary to avoid the error \"BeginLayoutGroup must be called first\".\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        internal static void BuildFileBoxButton(SerializedProperty prop, string uiString, string directory, string ext)\n        {\n            BuildFileBoxButton(prop, uiString, directory, ext, null, null);\n        }\n\n        internal static void BuildFileBoxButton(SerializedProperty prop, string uiString, string directory,\n            string ext, Action onSelect, Action onChanged)\n        {\n            bool changed = false;\n            using (var vertical = new EditorGUILayout.VerticalScope())\n            using (new EditorGUI.PropertyScope(vertical.rect, GUIContent.none, prop))\n            {\n                float h = EditorGUI.kSingleLineHeight;\n                float kLabelFloatMinW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing;\n                float kLabelFloatMaxW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing;\n                Rect r = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, h, h, EditorStyles.layerMaskField, null);\n\n                float labelWidth = EditorGUIUtility.labelWidth;\n                Rect buttonRect = new Rect(r.x + EditorGUI.indent, r.y, labelWidth - EditorGUI.indent, r.height);\n                Rect fieldRect = new Rect(r.x + labelWidth, r.y, r.width - labelWidth, r.height);\n\n                string display = (prop.stringValue.Length == 0) ? \"Not selected\" : prop.stringValue;\n                EditorGUI.LabelField(fieldRect, display, EditorStyles.label);\n\n                if (GUI.Button(buttonRect, EditorGUIUtility.TextContent(uiString)))\n                {\n                    string prevVal = prop.stringValue;\n                    string path = EditorUtility.OpenFilePanel(EditorGUIUtility.TextContent(uiString).text, directory, ext);\n\n                    string relPath = FileUtil.GetProjectRelativePath(path);\n                    prop.stringValue = (relPath != string.Empty) ? relPath : path;\n                    changed = (prop.stringValue != prevVal);\n\n                    if (onSelect != null)\n                        onSelect();\n\n                    prop.serializedObject.ApplyModifiedProperties();\n\n                    if (changed && onChanged != null)\n                        onChanged();\n\n                    // Necessary to avoid the error \"BeginLayoutGroup must be called first\".\n                    GUIUtility.ExitGUI();\n                }\n            }\n        }\n\n        public void PublishSectionGUI(BuildPlatform platform, ISettingEditorExtension settingsExtension, int sectionIndex = 5)\n        {\n            if (platform.namedBuildTarget != NamedBuildTarget.WindowsStoreApps &&\n                !(settingsExtension != null && settingsExtension.HasPublishSection()))\n                return;\n\n            if (BeginSettingsBox(sectionIndex, SettingsContent.publishingSettingsTitle))\n            {\n                float h = EditorGUI.kSingleLineHeight;\n                float kLabelFloatMinW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing;\n                float kLabelFloatMaxW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing;\n\n                if (settingsExtension != null)\n                {\n                    settingsExtension.PublishSectionGUI(h, kLabelFloatMinW, kLabelFloatMaxW);\n                }\n            }\n            EndSettingsBox();\n        }\n\n        protected override bool ShouldHideOpenButton()\n        {\n            return true;\n        }\n\n        [SettingsProvider]\n        internal static SettingsProvider CreateProjectSettingsProvider()\n        {\n            var keywordsList = new List<string>();\n\n            keywordsList.AddRange(SettingsProvider.GetSearchKeywordsFromGUIContentProperties<SettingsContent>());\n            keywordsList.AddRange(SettingsProvider.GetSearchKeywordsFromGUIContentProperties<PlayerSettingsSplashScreenEditor.Texts>());\n            keywordsList.AddRange(SettingsProvider.GetSearchKeywordsFromGUIContentProperties<PlayerSettingsIconsEditor.SettingsContent>());\n\n            var provider = AssetSettingsProvider.CreateProviderFromAssetPath(\n                \"Project/Player\", \"ProjectSettings/ProjectSettings.asset\",\n                keywordsList);\n            provider.activateHandler = (searchContext, rootElement) =>\n            {\n                var playerSettingsProvider = provider.settingsEditor as PlayerSettingsEditor;\n                if (playerSettingsProvider != null)\n                {\n                    playerSettingsProvider.SetValueChangeListeners(provider.Repaint);\n                    playerSettingsProvider.splashScreenEditor.SetValueChangeListeners(provider.Repaint);\n                }\n            };\n            return provider;\n        }\n\n        void InitReorderableScriptingDefineSymbolsList(NamedBuildTarget namedBuildTarget)\n        {\n            // Get Scripting Define Symbols data\n            string defines = GetScriptingDefineSymbolsForGroup(namedBuildTarget);\n            scriptingDefinesList = new List<string>(ScriptingDefinesHelper.ConvertScriptingDefineStringToArray(serializedScriptingDefines));\n\n            // Initialize Reorderable List\n            scriptingDefineSymbolsList = new ReorderableList(scriptingDefinesList, typeof(string), true, true, true, true);\n            scriptingDefineSymbolsList.drawElementCallback = (rect, index, isActive, isFocused) => DrawTextField(rect, index);\n            scriptingDefineSymbolsList.drawHeaderCallback = (rect) => DrawScriptingDefinesHeaderCallback(rect);\n            scriptingDefineSymbolsList.onAddCallback = AddScriptingDefineCallback;\n            scriptingDefineSymbolsList.onRemoveCallback = RemoveScriptingDefineCallback;\n            scriptingDefineSymbolsList.onChangedCallback = SetScriptingDefinesListDirty;\n        }\n\n        void UpdateScriptingDefineSymbolsLists()\n        {\n            scriptingDefinesList = new List<string>(ScriptingDefinesHelper.ConvertScriptingDefineStringToArray(serializedScriptingDefines));\n            scriptingDefineSymbolsList.list = scriptingDefinesList;\n            scriptingDefineSymbolsList.DoLayoutList();\n            hasScriptingDefinesBeenModified = false;\n        }\n\n        void InitReorderableAdditionalCompilerArgumentsList(NamedBuildTarget namedBuildTarget)\n        {\n            var additionalCompilerArgumentsArray = GetAdditionalCompilerArgumentsForGroup(namedBuildTarget);\n            additionalCompilerArgumentsList = additionalCompilerArgumentsArray.ToList();\n\n            additionalCompilerArgumentsReorderableList = new ReorderableList(additionalCompilerArgumentsList, typeof(string), true, true, true, true);\n            additionalCompilerArgumentsReorderableList.drawElementCallback = (rect, index, isActive, isFocused) => DrawTextFieldAdditionalCompilerArguments(rect, index);\n            additionalCompilerArgumentsReorderableList.drawHeaderCallback = (rect) => GUI.Label(rect, SettingsContent.additionalCompilerArguments, EditorStyles.label);\n            additionalCompilerArgumentsReorderableList.onAddCallback = AddAdditionalCompilerArgumentCallback;\n            additionalCompilerArgumentsReorderableList.onRemoveCallback = RemoveAdditionalCompilerArgumentCallback;\n            additionalCompilerArgumentsReorderableList.onChangedCallback = SetAdditionalCompilerArgumentListDirty;\n        }\n\n        void UpdateAdditionalCompilerArgumentsLists()\n        {\n            additionalCompilerArgumentsList = new List<string>(serializedAdditionalCompilerArguments);\n            additionalCompilerArgumentsReorderableList.list = additionalCompilerArgumentsList;\n            additionalCompilerArgumentsReorderableList.DoLayoutList();\n            hasAdditionalCompilerArgumentsBeenModified = false;\n        }\n\n        private struct PlayerSettingsBox\n        {\n            public MethodInfo mi;\n            public GUIContent title;\n            public int order;\n            public string TargetName;\n\n            public PlayerSettingsBox(MethodInfo mi, string targetName, string title, int order)\n            {\n                this.mi = mi;\n                this.title = EditorGUIUtility.TrTextContent(title);\n                this.order = order;\n                this.TargetName = targetName;\n            }\n        };\n\n        private List<PlayerSettingsBox> m_boxes;\n\n        private PlayerSettingsSectionAttribute GetSectionAttribute(MethodInfo mi)\n        {\n            foreach (var attr in mi.GetCustomAttributes())\n            {\n                if (attr is PlayerSettingsSectionAttribute)\n                    return (PlayerSettingsSectionAttribute)attr;\n            }\n            return null;\n        }\n\n        private bool IsValidSectionSetting(MethodInfo mi)\n        {\n            if (!mi.IsStatic)\n            {\n                Debug.LogError($\"Method {mi.Name} with attribute PlayerSettingsSection must be static.\");\n                return false;\n            }\n            if (mi.IsGenericMethod || mi.IsGenericMethodDefinition)\n            {\n                Debug.LogError($\"Method {mi.Name} with attribute PlayerSettingsSection cannot be generic.\");\n                return false;\n            }\n            if (mi.GetParameters().Length != 0)\n            {\n                Debug.LogError($\"Method {mi.Name} with attribute PlayerSettingsSection does not have the correct signature, expected: static void {mi.Name}()\");\n                return false;\n            }\n            return true;\n        }\n\n        private void FindPlayerSettingsAttributeSections()\n        {\n            m_boxes = new List<PlayerSettingsBox>();\n\n            foreach (var method in TypeCache.GetMethodsWithAttribute<PlayerSettingsSectionAttribute>())\n            {\n                if (IsValidSectionSetting(method))\n                {\n                    PlayerSettingsSectionAttribute attr = GetSectionAttribute(method);\n                    m_boxes.Add(new PlayerSettingsBox(method, attr.TargetName, attr.Title, attr.Order));\n                }\n            }\n\n            m_boxes.Sort((a, b) => a.order.CompareTo(b.order));\n        }\n\n        void SyncColorGamuts()\n        {\n            if (m_ColorGamutList == null)\n                return;\n\n            m_ColorGamutList.list = m_CurrentTarget.GetColorGamuts_Internal().ToList();\n        }\n\n        void SyncPlatformAPIsList(BuildTarget target)\n        {\n            if (!m_GraphicsDeviceLists.ContainsKey(target))\n                return;\n            m_GraphicsDeviceLists[target].list = m_CurrentTarget.GetGraphicsAPIs_Internal(target).ToList();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsIconsEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Build;\nusing UnityEditor.Modules;\nusing UnityEditor.PlatformSupport;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class PlayerSettingsIconsEditor\n    {\n        internal class SettingsContent\n        {\n            public static readonly GUIContent iconTitle = EditorGUIUtility.TrTextContent(\"Icon\");\n            public static readonly GUIContent defaultIcon = EditorGUIUtility.TrTextContent(\"Default Icon\");\n            public static readonly GUIContent UIPrerenderedIcon = EditorGUIUtility.TrTextContent(\"Prerendered Icon\");\n            public static string undoChangedIconString { get { return LocalizationDatabase.GetLocalizedString(\"Changed Icon\"); } }\n        }\n\n        // Icon layout constants\n        const int kSlotSize = 64;\n        const int kMaxPreviewSize = 96;\n        const int kIconSpacing = 6;\n\n        PlayerSettingsEditor m_Owner;\n\n        // Serialized icons\n        SerializedProperty m_PlatformIcons;\n        SerializedProperty m_LegacyPlatformIcons;\n        SerializedProperty m_UIPrerenderedIcon;\n\n\n        // Deserialized icons (all platforms)\n        BuildTargetIcons[] m_AllIcons;\n        // Deserialized legacy icons (all platforms)\n        LegacyBuildTargetIcons[] m_AllLegacyIcons;\n\n        // Required icons for platform. Provided by platform extension\n        Dictionary<PlatformIconKind, PlatformIcon[]> m_RequiredIcons;\n\n        public PlayerSettingsIconsEditor(PlayerSettingsEditor owner)\n        {\n            m_Owner = owner;\n        }\n\n        public void OnEnable()\n        {\n            m_PlatformIcons       = m_Owner.FindPropertyAssert(\"m_BuildTargetPlatformIcons\");\n            m_LegacyPlatformIcons = m_Owner.FindPropertyAssert(\"m_BuildTargetIcons\");\n            m_UIPrerenderedIcon   = m_Owner.FindPropertyAssert(\"uIPrerenderedIcon\");\n\n            DeserializeIcons();\n            DeserializeLegacyIcons();\n        }\n\n        private void DeserializeIcons()\n        {\n            var allIconsList = new List<BuildTargetIcons>();\n            for (int i = 0; i < m_PlatformIcons.arraySize; i++)\n            {\n                var platform = m_PlatformIcons.GetArrayElementAtIndex(i);\n                var icons = platform.FindPropertyRelative(\"m_Icons\");\n                var platformName = platform.FindPropertyRelative(\"m_BuildTarget\").stringValue;\n                if (platformName == null || icons.arraySize <= 0)\n                    continue;\n\n                var platformIcons = new BuildTargetIcons\n                {\n                    BuildTarget = platformName,\n                    Icons = new PlatformIconStruct[icons.arraySize]\n                };\n\n                for (int j = 0; j < icons.arraySize; j++)\n                {\n                    var platformIconsEntry = icons.GetArrayElementAtIndex(j);\n                    var icon = new PlatformIconStruct()\n                    {\n                        Width = platformIconsEntry.FindPropertyRelative(\"m_Width\").intValue,\n                        Height = platformIconsEntry.FindPropertyRelative(\"m_Height\").intValue,\n                        Kind = platformIconsEntry.FindPropertyRelative(\"m_Kind\").intValue,\n                        SubKind = platformIconsEntry.FindPropertyRelative(\"m_SubKind\").stringValue,\n                    };\n                    var texturesEntry = platformIconsEntry.FindPropertyRelative(\"m_Textures\");\n                    icon.Textures = new Texture2D[texturesEntry.arraySize];\n                    for (int k = 0; k < texturesEntry.arraySize; k++)\n                    {\n                        icon.Textures[k] = (Texture2D)texturesEntry.GetArrayElementAtIndex(k).objectReferenceValue;\n                    }\n\n                    platformIcons.Icons[j] = icon;\n                }\n                allIconsList.Add(platformIcons);\n            }\n\n            m_AllIcons = allIconsList.ToArray();\n        }\n\n        private void DeserializeLegacyIcons()\n        {\n            var allIconsList = new List<LegacyBuildTargetIcons>();\n            for (int i = 0; i < m_LegacyPlatformIcons.arraySize; i++)\n            {\n                var platform = m_LegacyPlatformIcons.GetArrayElementAtIndex(i);\n                var icons = platform.FindPropertyRelative(\"m_Icons\");\n                var platformName = platform.FindPropertyRelative(\"m_BuildTarget\").stringValue;\n                if (platformName == null || icons.arraySize <= 0)\n                    continue;\n\n                var platformIcons = new LegacyBuildTargetIcons\n                {\n                    BuildTarget = platformName,\n                    Icons = new LegacyPlatformIcon[icons.arraySize]\n                };\n\n                for (int j = 0; j < icons.arraySize; j++)\n                {\n                    var platformIconsEntry = icons.GetArrayElementAtIndex(j);\n                    var icon = new LegacyPlatformIcon()\n                    {\n                        Width = platformIconsEntry.FindPropertyRelative(\"m_Width\").intValue,\n                        Height = platformIconsEntry.FindPropertyRelative(\"m_Height\").intValue,\n                        Kind = (IconKind)platformIconsEntry.FindPropertyRelative(\"m_Kind\").intValue,\n                    };\n                    var texture = platformIconsEntry.FindPropertyRelative(\"m_Icon\");\n                    icon.Icon = (Texture2D)texture.objectReferenceValue;\n                    platformIcons.Icons[j] = icon;\n                }\n                allIconsList.Add(platformIcons);\n            }\n\n            m_AllLegacyIcons = allIconsList.ToArray();\n        }\n\n        private void SerializeIcons()\n        {\n            m_PlatformIcons.ClearArray();\n            for (int i = 0; i < m_AllIcons.Length; i++)\n            {\n                var platformIcons = m_AllIcons[i];\n                var platformName = platformIcons.BuildTarget;\n\n                m_PlatformIcons.InsertArrayElementAtIndex(i);\n                var serializedPlatform = m_PlatformIcons.GetArrayElementAtIndex(i);\n\n                if (platformName == null || platformIcons.Icons == null)\n                    return;\n\n                serializedPlatform.FindPropertyRelative(\"m_BuildTarget\").stringValue = platformName;\n                var iconsMember = serializedPlatform.FindPropertyRelative(\"m_Icons\");\n                iconsMember.ClearArray(); // Even after clearing parent array, this is not cleared\n                for (int k = 0; k < platformIcons.Icons.Length; k++)\n                {\n                    var icon = platformIcons.Icons[k];\n                    iconsMember.InsertArrayElementAtIndex(k);\n                    var platformIconsEntry = iconsMember.GetArrayElementAtIndex(k);\n                    platformIconsEntry.FindPropertyRelative(\"m_Width\").intValue = icon.Width;\n                    platformIconsEntry.FindPropertyRelative(\"m_Height\").intValue = icon.Height;\n                    platformIconsEntry.FindPropertyRelative(\"m_Kind\").intValue = icon.Kind;\n                    platformIconsEntry.FindPropertyRelative(\"m_SubKind\").stringValue = icon.SubKind;\n\n                    var texturesMember = platformIconsEntry.FindPropertyRelative(\"m_Textures\");\n                    texturesMember.ClearArray(); // Even after clearing parent array, this is not cleared\n                    for (int l = 0; l < icon.Textures.Length; l++)\n                    {\n                        texturesMember.InsertArrayElementAtIndex(l);\n                        texturesMember.GetArrayElementAtIndex(l).objectReferenceValue = icon.Textures[l];\n                    }\n                }\n            }\n        }\n\n        private void SerializeLegacyIcons()\n        {\n            m_LegacyPlatformIcons.ClearArray();\n            for (int i = 0; i < m_AllLegacyIcons.Length; i++)\n            {\n                var platformIcons = m_AllLegacyIcons[i];\n                var platformName = platformIcons.BuildTarget;\n\n                m_LegacyPlatformIcons.InsertArrayElementAtIndex(i);\n                var serializedPlatform = m_LegacyPlatformIcons.GetArrayElementAtIndex(i);\n\n                if (platformName == null || platformIcons.Icons == null)\n                    return;\n\n                serializedPlatform.FindPropertyRelative(\"m_BuildTarget\").stringValue = platformName;\n                var iconsMember = serializedPlatform.FindPropertyRelative(\"m_Icons\");\n                iconsMember.ClearArray(); // Even after clearing parent array, this is not cleared\n                for (int k = 0; k < platformIcons.Icons.Length; k++)\n                {\n                    var icon = platformIcons.Icons[k];\n                    iconsMember.InsertArrayElementAtIndex(k);\n                    var platformIconsEntry = iconsMember.GetArrayElementAtIndex(k);\n                    platformIconsEntry.FindPropertyRelative(\"m_Width\").intValue = icon.Width;\n                    platformIconsEntry.FindPropertyRelative(\"m_Height\").intValue = icon.Height;\n                    platformIconsEntry.FindPropertyRelative(\"m_Kind\").intValue = (int)icon.Kind;\n\n                    var iconTexture = platformIconsEntry.FindPropertyRelative(\"m_Icon\");\n                    iconTexture.objectReferenceValue = icon.Icon;\n                }\n            }\n        }\n\n        private void SetLegacyPlatformIcons(string platform, Texture2D[] icons, IconKind kind, ref LegacyBuildTargetIcons[] allIcons)\n        {\n            allIcons = PlayerSettings.SetPlatformIconsForTargetIcons(platform, icons, kind, allIcons);\n            SerializeLegacyIcons();\n        }\n\n        static void ImportLegacyIcons(string platform, PlatformIconKind kind, PlatformIcon[] platformIcons, LegacyBuildTargetIcons[] allLegacyIcons)\n        {\n            if (!Enum.IsDefined(typeof(IconKind), kind.kind))\n                return;\n\n            var iconKind = (IconKind)kind.kind;\n\n            var legacyIcons = PlayerSettings.GetPlatformIconsForTargetIcons(platform, iconKind, allLegacyIcons);\n            var legacyIconWidths = PlayerSettings.GetIconWidthsForPlatform(platform, iconKind);\n            var legacyIconHeights  = PlayerSettings.GetIconHeightsForPlatform(platform, iconKind);\n\n            for (var i = 0; i < legacyIcons.Length; i++)\n            {\n                var selectedIcons = new List<PlatformIcon>();\n                foreach (var icon in platformIcons)\n                {\n                    if (icon.width == legacyIconWidths[i] && icon.height == legacyIconHeights[i])\n                    {\n                        selectedIcons.Add(icon);\n                    }\n                }\n                foreach (var selectedIcon in selectedIcons)\n                    selectedIcon.SetTextures(legacyIcons[i]);\n            }\n        }\n\n        private void SetPreviewTextures(PlatformIcon platformIcon)\n        {\n            Texture2D[] previewTextures = new Texture2D[platformIcon.maxLayerCount];\n\n            for (int i = 0; i < platformIcon.maxLayerCount; i++)\n            {\n                previewTextures[i] = PlayerSettings.GetPlatformIconAtSizeForTargetIcons(platformIcon.kind.platform, platformIcon.width, platformIcon.height, m_AllIcons, platformIcon.kind.kind, platformIcon.iconSubKind, i);\n            }\n\n            platformIcon.SetPreviewTextures(previewTextures);\n        }\n\n        internal PlatformIcon[] GetPlatformIcons(BuildTargetGroup platform, PlatformIconKind kind, ref BuildTargetIcons[] allIcons)\n        {\n            var namedBuildTarget = NamedBuildTarget.FromBuildTargetGroup(platform);\n            if (!BuildTargetDiscovery.TryGetBuildTarget(BuildPipeline.GetBuildTargetByName(namedBuildTarget.TargetName), out var iBuildTarget))\n                return Array.Empty<PlatformIcon>();\n            var requiredIcons = iBuildTarget.IconPlatformProperties?.GetRequiredPlatformIcons();\n            if (requiredIcons == null)\n                return Array.Empty<PlatformIcon>();\n\n            var serializedIcons = PlayerSettings.GetPlatformIconsFromTargetIcons(namedBuildTarget.TargetName, kind.kind, allIcons);\n            if (m_RequiredIcons == null)\n                m_RequiredIcons = new Dictionary<PlatformIconKind, PlatformIcon[]>();\n            if (!m_RequiredIcons.ContainsKey(kind))\n            {\n                foreach (var requiredIcon in requiredIcons)\n                {\n                    if (!m_RequiredIcons.ContainsKey(requiredIcon.Key))\n                        m_RequiredIcons.Add(requiredIcon.Key, requiredIcon.Value);\n                }\n            }\n\n            var icons = PlatformIcon.GetRequiredPlatformIconsByType(kind, m_RequiredIcons);\n            if (serializedIcons.Length <= 0)\n            {\n                // Map legacy icons to required icons\n                ImportLegacyIcons(namedBuildTarget.TargetName, kind, icons, m_AllLegacyIcons);\n                // Serialize required icons\n                SetPlatformIcons(platform, kind, icons, ref allIcons);\n\n                foreach (var icon in icons)\n                    if (icon.IsEmpty())\n                        icon.SetTextures(null);\n            }\n            else\n            {\n                // Map serialized icons to required icons\n                icons = PlayerSettings.GetPlatformIconsFromStruct(icons, kind, serializedIcons.ToArray());\n            }\n\n            return icons;\n        }\n\n        void SetIconsForPlatform(BuildTargetGroup targetGroup, PlatformIcon[] icons, PlatformIconKind kind, ref BuildTargetIcons[] allIcons)\n        {\n            var namedBuildTarget = NamedBuildTarget.FromBuildTargetGroup(targetGroup);\n            if (!BuildTargetDiscovery.TryGetBuildTarget(BuildPipeline.GetBuildTargetByName(namedBuildTarget.TargetName), out var iBuildTarget))\n                return;\n\n            var requiredIcons = iBuildTarget.IconPlatformProperties?.GetRequiredPlatformIcons();\n            if (requiredIcons == null)\n                return;\n\n            if (m_RequiredIcons == null)\n                m_RequiredIcons = new Dictionary<PlatformIconKind, PlatformIcon[]>();\n            if (!m_RequiredIcons.ContainsKey(kind))\n            {\n                foreach (var requiredIcon in requiredIcons)\n                {\n                    if (!m_RequiredIcons.ContainsKey(requiredIcon.Key))\n                        m_RequiredIcons.Add(requiredIcon.Key, requiredIcon.Value);\n                }\n            }\n\n            var requiredIconCount = PlatformIcon.GetRequiredPlatformIconsByType(kind, m_RequiredIcons).Length;\n\n            PlatformIconStruct[] iconStructs;\n            if (icons == null)\n                iconStructs = new PlatformIconStruct[0];\n            else if (requiredIconCount != icons.Length)\n            {\n                throw new InvalidOperationException($\"Attempting to set an incorrect number of icons for {namedBuildTarget} {kind} kind, it requires {requiredIconCount} icons but trying to assign {icons.Length}.\");\n            }\n            else\n            {\n                iconStructs = icons.Select(\n                    i => i.GetPlatformIconStruct()\n                    ).ToArray<PlatformIconStruct>();\n            }\n\n            allIcons = PlayerSettings.SetIconsForPlatformForTargetIcons(namedBuildTarget.TargetName, iconStructs, kind.kind, allIcons);\n        }\n\n        void SetPlatformIcons(BuildTargetGroup targetGroup, PlatformIconKind kind, PlatformIcon[] icons, ref BuildTargetIcons[] allIcons)\n        {\n            SetIconsForPlatform(targetGroup, icons, kind, ref allIcons);\n            SerializeIcons();\n        }\n\n        public void LegacyIconSectionGUI()\n        {\n            // Both default icon and Legacy icons are serialized to the same map\n            // That's why m_LegacyPlatformIcons can be excluded in two places (other place in IconSectionGUI())\n            using (var vertical = new EditorGUILayout.VerticalScope())\n            using (new EditorGUI.PropertyScope(vertical.rect, GUIContent.none, m_LegacyPlatformIcons))\n            {\n                // Get icons and icon sizes for selected platform (or default)\n                EditorGUI.BeginChangeCheck();\n                string platformName = \"\";\n                Texture2D[] icons = PlayerSettings.GetPlatformIconsForTargetIcons(platformName, IconKind.Any, m_AllLegacyIcons);\n                int[] widths = PlayerSettings.GetIconWidthsForPlatform(platformName, IconKind.Any);\n\n                // Ensure the default icon list is always populated correctly\n                if (icons.Length != widths.Length)\n                {\n                    icons = new Texture2D[widths.Length];\n                }\n\n                icons[0] = (Texture2D)EditorGUILayout.ObjectField(SettingsContent.defaultIcon, icons[0], typeof(Texture2D), false);\n                // Save changes\n                if (EditorGUI.EndChangeCheck())\n                {\n                    Undo.RecordObjects(m_Owner.targets, SettingsContent.undoChangedIconString);\n                    SetLegacyPlatformIcons(platformName, icons, IconKind.Any, ref m_AllLegacyIcons);\n                }\n            }\n        }\n\n        public void SerializedObjectUpdated()\n        {\n            DeserializeIcons();\n            DeserializeLegacyIcons();\n        }\n\n        public void IconSectionGUI(BuildPlatform platform, ISettingEditorExtension settingsExtension, int platformID, int sectionIndex)\n        {\n            if (!m_Owner.BeginSettingsBox(sectionIndex, SettingsContent.iconTitle))\n            {\n                m_Owner.EndSettingsBox();\n                return;\n            }\n\n            var platformUsesStandardIcons = true;\n            if (settingsExtension != null)\n                platformUsesStandardIcons = settingsExtension.UsesStandardIcons();\n\n            if (platformUsesStandardIcons)\n            {\n                var selectedDefault = (platformID < 0);\n                // Set default platform variables\n                var platformName = \"\";\n\n                // Override if a platform is selected\n                if (!selectedDefault)\n                {\n                    platformName = platform.name;\n                }\n\n                var iconUISettings = IconSettings.StandardIcons;\n                if (BuildTargetDiscovery.TryGetBuildTarget(BuildPipeline.GetBuildTargetByName(platform.name), out IBuildTarget iBuildTarget))\n                    iconUISettings = iBuildTarget.IconPlatformProperties?.IconUISettings ?? IconSettings.StandardIcons;\n\n                if (iconUISettings == IconSettings.None)\n                {\n                    PlayerSettingsEditor.ShowNoSettings();\n                    EditorGUILayout.Space();\n                }\n                else if (iconUISettings == IconSettings.StandardIcons)\n                {\n                    // Both default icon and Legacy icons are serialized to the same map\n                    // That's why m_LegacyPlatformIcons can be excluded in two places (other place in CommonSettings())\n                    using (var vertical = new EditorGUILayout.VerticalScope())\n                    using (new EditorGUI.PropertyScope(vertical.rect, GUIContent.none, m_LegacyPlatformIcons))\n                    {\n                        // Get icons and icon sizes for selected platform (or default)\n                        var icons = PlayerSettings.GetPlatformIconsForTargetIcons(platformName, IconKind.Any, m_AllLegacyIcons);\n                        var widths = PlayerSettings.GetIconWidthsForPlatform(platformName, IconKind.Any);\n                        var heights = PlayerSettings.GetIconHeightsForPlatform(platformName, IconKind.Any);\n                        var kinds = PlayerSettings.GetIconKindsForPlatform(platformName);\n\n                        var overrideIcons = true;\n\n                        if (!selectedDefault)\n                        {\n                            // If the list of icons for this platform is not empty (and has the correct size),\n                            // consider the icon overridden for this platform\n                            EditorGUI.BeginChangeCheck();\n                            overrideIcons = (icons.Length == widths.Length);\n                            overrideIcons = GUILayout.Toggle(overrideIcons, IsInBuildProfileEditor() ? L10n.Tr(\"Override\") : string.Format(L10n.Tr(\"Override for {0}\"), platform.title.text));\n                            EditorGUI.BeginDisabled(!overrideIcons);\n                            var changed = EditorGUI.EndChangeCheck();\n                            if (changed || (!overrideIcons && icons.Length > 0))\n                            {\n                                // Set the list of icons to correct length if overridden, otherwise to an empty list\n                                if (overrideIcons)\n                                    icons = new Texture2D[widths.Length];\n                                else\n                                    icons = new Texture2D[0];\n\n                                if (changed)\n                                    SetLegacyPlatformIcons(platformName, icons, IconKind.Any, ref m_AllLegacyIcons);\n                            }\n                        }\n\n                        // Show the icons for this platform (or default)\n                        EditorGUI.BeginChangeCheck();\n                        for (int i = 0; i < widths.Length; i++)\n                        {\n                            var previewWidth = Mathf.Min(kMaxPreviewSize, widths[i]);\n                            var previewHeight = (int)((float)heights[i] * previewWidth / widths[i]);   // take into account the aspect ratio\n                            var rect = GUILayoutUtility.GetRect(kSlotSize, Mathf.Max(kSlotSize, previewHeight) + kIconSpacing);\n                            var width = Mathf.Min(rect.width, EditorGUIUtility.labelWidth + 4 + kSlotSize + kIconSpacing + kMaxPreviewSize);\n\n                            // Label\n                            var label = widths[i] + \"x\" + heights[i];\n                            GUI.Label(new Rect(rect.x, rect.y, width - kMaxPreviewSize - kSlotSize - 2 * kIconSpacing, 20), label);\n\n                            // Texture slot\n                            if (overrideIcons)\n                            {\n                                var slotWidth = kSlotSize;\n                                var slotHeight = (int)((float)heights[i] / widths[i] * kSlotSize);   // take into account the aspect ratio\n                                icons[i] = (Texture2D)EditorGUI.ObjectField(\n                                    new Rect(rect.x + width - kMaxPreviewSize - kSlotSize - kIconSpacing, rect.y, slotWidth, slotHeight),\n                                    icons[i],\n                                    typeof(Texture2D),\n                                    false);\n                            }\n\n                            // Preview\n                            var previewRect = new Rect(rect.x + width - kMaxPreviewSize, rect.y, previewWidth, previewHeight);\n                            var closestIcon = PlayerSettings.GetPlatformIconForSizeForTargetIcons(platformName, widths[i], heights[i], kinds[i], m_AllLegacyIcons);\n                            if (closestIcon != null)\n                                GUI.DrawTexture(previewRect, closestIcon);\n                            else\n                                GUI.Box(previewRect, \"\");\n                        }\n\n                        // Save changes\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            Undo.RecordObjects(m_Owner.targets, SettingsContent.undoChangedIconString);\n                            SetLegacyPlatformIcons(platformName, icons, IconKind.Any, ref m_AllLegacyIcons);\n                        }\n\n                        EditorGUI.EndDisabled();\n                    }\n                }\n            }\n\n            if (settingsExtension != null)\n                settingsExtension.IconSectionGUI();\n\n            m_Owner.EndSettingsBox();\n        }\n\n        internal void ShowPlatformIconsByKind(PlatformIconFieldGroup iconFieldGroup, bool foldByKind, bool foldBySubkind)\n        {\n            // All icons that are displayed here are serialized into a single map\n            // So in the preset we can only exclude/include all icons\n            using (var vertical = new EditorGUILayout.VerticalScope())\n            using (new EditorGUI.PropertyScope(vertical.rect, GUIContent.none, m_PlatformIcons))\n            {\n                int labelHeight = 20;\n\n                foreach (var kind in PlayerSettings.GetSupportedIconKinds(NamedBuildTarget.FromBuildTargetGroup(iconFieldGroup.targetGroup)))\n                {\n                    iconFieldGroup.SetPlatformIcons(GetPlatformIcons(iconFieldGroup.targetGroup, kind, ref m_AllIcons), kind);\n                }\n\n                foreach (var kindGroup in iconFieldGroup.m_IconsFields)\n                {\n                    EditorGUI.BeginChangeCheck();\n\n                    var key = kindGroup.Key;\n\n                    if (foldByKind)\n                    {\n                        GUIContent kindName = new GUIContent(\n                            string.Format(\"{0} icons ({1}/{2})\", key.m_Label, kindGroup.Key.m_SetIconSlots, kindGroup.Key.m_IconSlotCount),\n                            key.m_KindDescription\n                        );\n\n                        Rect rectKindLabel = GUILayoutUtility.GetRect(kSlotSize, labelHeight);\n                        rectKindLabel.x += 2;\n                        key.m_State = EditorGUI.Foldout(rectKindLabel, key.m_State, kindName, true, EditorStyles.foldout);\n                    }\n                    else\n                        key.m_State = true;\n\n                    if (key.m_State)\n                    {\n                        kindGroup.Key.m_SetIconSlots = 0;\n                        foreach (var subKindGroup in kindGroup.Value)\n                        {\n                            subKindGroup.Key.m_SetIconSlots =\n                                PlayerSettings.GetNonEmptyPlatformIconCount(subKindGroup.Value.Select(x => x.platformIcon)\n                                    .ToArray());\n                            kindGroup.Key.m_SetIconSlots += subKindGroup.Key.m_SetIconSlots;\n\n                            if (foldBySubkind)\n                            {\n                                string subKindName = string.Format(\"{0} icons ({1}/{2})\", subKindGroup.Key.m_Label, subKindGroup.Key.m_SetIconSlots, subKindGroup.Value.Length);\n                                Rect rectSubKindLabel = GUILayoutUtility.GetRect(kSlotSize, labelHeight);\n                                rectSubKindLabel.x += 8;\n\n                                subKindGroup.Key.m_State = EditorGUI.Foldout(rectSubKindLabel, subKindGroup.Key.m_State, subKindName, true, EditorStyles.foldout);\n                            }\n                            else\n                                subKindGroup.Key.m_State = true;\n\n                            if (subKindGroup.Key.m_State || !foldBySubkind)\n                            {\n                                foreach (var iconField in subKindGroup.Value)\n                                {\n                                    SetPreviewTextures(iconField.platformIcon);\n                                    iconField.DrawAt();\n                                }\n                            }\n                        }\n                    }\n\n                    if (EditorGUI.EndChangeCheck())\n                        SetPlatformIcons(iconFieldGroup.targetGroup, key.m_Kind, iconFieldGroup.m_PlatformIconsByKind[key.m_Kind], ref m_AllIcons);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Check if this class belongs to the build profile editor\n        /// </summary>\n        bool IsInBuildProfileEditor()\n        {\n            return m_Owner.IsBuildProfileEditor();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsSplashScreenEditor.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n    [NativeHeader(\"Runtime/Scripting/ScriptingExportUtility.h\")]\n    [NativeHeader(\"Runtime/Graphics/DrawSplashScreenAndWatermarks.h\")]\n    internal partial class PlayerSettingsSplashScreenEditor\n    {\n        [FreeFunction(\"GetSplashScreenBackgroundColor\")]\n        internal static extern Color GetSplashScreenActualBackgroundColor();\n\n        [FreeFunction(\"GetSplashScreenBackground\")]\n        internal static extern Texture2D GetSplashScreenActualBackgroundImage(Rect windowRect);\n\n        [FreeFunction(\"GetSplashScreenBackgroundUvs\")]\n        internal static extern Rect GetSplashScreenActualUVs(Rect windowRect);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsSplashScreenEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.AnimatedValues;\nusing UnityEditor.Modules;\nusing UnityEditorInternal;\nusing UnityEngine.Rendering;\nusing UnityEngine;\nusing UnityEditor.Build;\nusing UnityEngine.Events;\n\nnamespace UnityEditor\n{\n    internal partial class PlayerSettingsSplashScreenEditor\n    {\n        PlayerSettingsEditor m_Owner;\n\n        SerializedProperty m_ShowUnitySplashLogo;\n        SerializedProperty m_ShowUnitySplashScreen;\n        SerializedProperty m_SplashScreenAnimation;\n        SerializedProperty m_SplashScreenBackgroundAnimationZoom;\n        SerializedProperty m_SplashScreenBackgroundColor;\n        SerializedProperty m_SplashScreenBackgroundLandscape;\n        SerializedProperty m_SplashScreenBackgroundPortrait;\n        SerializedProperty m_SplashScreenBlurBackground;\n        SerializedProperty m_SplashScreenDrawMode;\n        SerializedProperty m_SplashScreenLogoAnimationZoom;\n        SerializedProperty m_SplashScreenLogos;\n        SerializedProperty m_SplashScreenLogoStyle;\n        SerializedProperty m_SplashScreenOverlayOpacity;\n        SerializedProperty m_VirtualRealitySplashScreen;\n\n        ReorderableList m_LogoList;\n\n        float m_TotalLogosDuration;\n\n        static readonly float k_MinLogoTime = 2;\n        static readonly float k_MaxLogoTime = 10.0f;\n        static readonly float k_DefaultLogoTime = 2.0f;\n\n        static readonly float k_LogoListElementHeight = 72;\n        static readonly float k_LogoListLogoFieldHeight = 64;\n        static readonly float k_LogoListFooterHeight = 20;\n        static readonly float k_LogoListUnityLogoMinWidth = 64;\n        static readonly float k_LogoListUnityLogoMaxWidth = 220;\n        static readonly float k_LogoListPropertyMinWidth = 230;\n        static readonly float k_LogoListPropertyLabelWidth = 100;\n        static readonly float k_MinOverlayOpacity = 0.0f;\n        static readonly Color32 k_DarkOnLightBgColor = new Color32(204, 204, 204, 255);// #CCCCCC\n        static readonly Color32 k_LightOnDarkBgColor = new Color32(35, 31, 32, 255);\n\n        static Sprite s_UnityLogoLight; // We use this version as a placeholder when the logo is in the list.\n        static Sprite s_UnityLogoDark;\n\n        readonly AnimBool m_ShowAnimationControlsAnimator = new AnimBool();\n        readonly AnimBool m_ShowBackgroundColorAnimator = new AnimBool();\n        readonly AnimBool m_ShowLogoControlsAnimator = new AnimBool();\n\n        Sprite UnityLogo => m_SplashScreenLogoStyle.intValue == (int)PlayerSettings.SplashScreen.UnityLogoStyle.DarkOnLight ? s_UnityLogoDark : s_UnityLogoLight;\n\n        // If the user changes an asset(delete, re-import etc) then we should cancel the splash screen to avoid using invalid data. (case 857060)\n        class CancelSplashScreenOnAssetChange : AssetPostprocessor\n        {\n            void OnPreprocessAsset()\n            {\n                SplashScreen.Stop(SplashScreen.StopBehavior.StopImmediate);\n            }\n        }\n\n        class CancelSplashScreenOnAssetDelete : AssetModificationProcessor\n        {\n            static AssetDeleteResult OnWillDeleteAsset(string asset, RemoveAssetOptions options)\n            {\n                SplashScreen.Stop(SplashScreen.StopBehavior.StopImmediate);\n                return AssetDeleteResult.DidNotDelete;\n            }\n        }\n\n        internal class Texts\n        {\n            public static readonly GUIContent animate = EditorGUIUtility.TrTextContent(\"Animation\");\n            public static readonly GUIContent backgroundColor = EditorGUIUtility.TrTextContent(\"Background Color\", \"Background color when no background image is used. On Android, use this property to set static splash image background color.\");\n            public static readonly GUIContent backgroundImage = EditorGUIUtility.TrTextContent(\"Background Image\", \"Image to be used in landscape and portrait (when portrait image is not set).\");\n            public static readonly GUIContent backgroundPortraitImage = EditorGUIUtility.TrTextContent(\"Alternate Portrait Image*\", \"Optional image to be used in portrait mode.\");\n            public static readonly GUIContent backgroundTitle = EditorGUIUtility.TrTextContent(\"Background*\");\n            public static readonly GUIContent backgroundZoom = EditorGUIUtility.TrTextContent(\"Background Zoom\");\n            public static readonly GUIContent blurBackground = EditorGUIUtility.TrTextContent(\"Blur Background Image\");\n            public static readonly GUIContent cancelPreviewSplash = EditorGUIUtility.TrTextContent(\"Cancel Preview\");\n            public static readonly GUIContent configDialogBanner = EditorGUIUtility.TrTextContent(\"Application Config Dialog Banner\");\n            public static readonly GUIContent configDialogBannerDeprecationWarning = EditorGUIUtility.TrTextContent(\"Application Config Dialog Banner is deprecated and will be removed in future versions.\");\n            public static readonly GUIContent drawMode = EditorGUIUtility.TrTextContent(\"Draw Mode\");\n            public static readonly GUIContent logoDuration = EditorGUIUtility.TrTextContent(\"Logo Duration\", \"The time the logo will be shown for.\");\n            public static readonly GUIContent logosTitle = EditorGUIUtility.TrTextContent(\"Logos*\");\n            public static readonly GUIContent logoZoom = EditorGUIUtility.TrTextContent(\"Logo Zoom\");\n            public static readonly GUIContent overlayOpacity = EditorGUIUtility.TrTextContent(\"Overlay Opacity\", \"Overlay strength applied to improve logo visibility.\");\n            public static readonly GUIContent previewSplash = EditorGUIUtility.TrTextContent(\"Preview\", \"Preview the splash screen in the game view.\");\n            public static readonly GUIContent showLogo = EditorGUIUtility.TrTextContent(\"Show Unity Logo\");\n            public static readonly GUIContent showSplash = EditorGUIUtility.TrTextContent(\"Show Splash Screen\");\n            public static readonly GUIContent splashStyle = EditorGUIUtility.TrTextContent(\"Splash Style\");\n            public static readonly GUIContent splashTitle = EditorGUIUtility.TrTextContent(\"Splash Screen\");\n            public static readonly GUIContent title = EditorGUIUtility.TrTextContent(\"Splash Image\");\n            public static readonly GUIContent vrSplashScreen = EditorGUIUtility.TrTextContent(\"Virtual Reality Splash Image\");\n        }\n\n        public PlayerSettingsSplashScreenEditor(PlayerSettingsEditor owner)\n        {\n            m_Owner = owner;\n        }\n\n        public void OnEnable()\n        {\n            m_ShowUnitySplashLogo = m_Owner.FindPropertyAssert(\"m_ShowUnitySplashLogo\");\n            m_ShowUnitySplashScreen = m_Owner.FindPropertyAssert(\"m_ShowUnitySplashScreen\");\n            m_SplashScreenAnimation = m_Owner.FindPropertyAssert(\"m_SplashScreenAnimation\");\n            m_SplashScreenBackgroundAnimationZoom = m_Owner.FindPropertyAssert(\"m_SplashScreenBackgroundAnimationZoom\");\n            m_SplashScreenBackgroundColor = m_Owner.FindPropertyAssert(\"m_SplashScreenBackgroundColor\");\n            m_SplashScreenBackgroundLandscape = m_Owner.FindPropertyAssert(\"splashScreenBackgroundSourceLandscape\");\n            m_SplashScreenBackgroundPortrait = m_Owner.FindPropertyAssert(\"splashScreenBackgroundSourcePortrait\");\n            m_SplashScreenBlurBackground = m_Owner.FindPropertyAssert(\"blurSplashScreenBackground\");\n            m_SplashScreenDrawMode = m_Owner.FindPropertyAssert(\"m_SplashScreenDrawMode\");\n            m_SplashScreenLogoAnimationZoom = m_Owner.FindPropertyAssert(\"m_SplashScreenLogoAnimationZoom\");\n            m_SplashScreenLogos = m_Owner.FindPropertyAssert(\"m_SplashScreenLogos\");\n            m_SplashScreenLogoStyle = m_Owner.FindPropertyAssert(\"m_SplashScreenLogoStyle\");\n            m_SplashScreenOverlayOpacity = m_Owner.FindPropertyAssert(\"m_SplashScreenOverlayOpacity\");\n            m_VirtualRealitySplashScreen = m_Owner.FindPropertyAssert(\"m_VirtualRealitySplashScreen\");\n\n            m_LogoList = new ReorderableList(m_Owner.serializedObject, m_SplashScreenLogos, true, true, true, true);\n            m_LogoList.elementHeight = k_LogoListElementHeight;\n            m_LogoList.footerHeight = k_LogoListFooterHeight;\n            m_LogoList.onAddCallback = OnLogoListAddCallback;\n            m_LogoList.drawHeaderCallback = DrawLogoListHeaderCallback;\n            m_LogoList.onCanRemoveCallback = OnLogoListCanRemoveCallback;\n            m_LogoList.drawElementCallback = DrawLogoListElementCallback;\n            m_LogoList.drawFooterCallback = DrawLogoListFooterCallback;\n\n            // Set up animations\n            m_ShowAnimationControlsAnimator.value = m_SplashScreenAnimation.intValue == (int)PlayerSettings.SplashScreen.AnimationMode.Custom;\n            m_ShowBackgroundColorAnimator.value = m_SplashScreenBackgroundLandscape.objectReferenceValue == null;\n            m_ShowLogoControlsAnimator.value = m_ShowUnitySplashLogo.boolValue;\n            SetValueChangeListeners(m_Owner.Repaint);\n\n            if (s_UnityLogoLight == null)\n                s_UnityLogoLight = AssetDatabase.GetBuiltinExtraResource<Sprite>(\"SplashScreen/UnitySplash-Light.png\");\n            if (s_UnityLogoDark == null)\n                s_UnityLogoDark = AssetDatabase.GetBuiltinExtraResource<Sprite>(\"SplashScreen/UnitySplash-Dark.png\");\n        }\n\n        internal void SetValueChangeListeners(UnityAction action)\n        {\n            m_ShowAnimationControlsAnimator.valueChanged.RemoveAllListeners();\n            m_ShowAnimationControlsAnimator.valueChanged.AddListener(action);\n\n            m_ShowBackgroundColorAnimator.valueChanged.RemoveAllListeners();\n            m_ShowBackgroundColorAnimator.valueChanged.AddListener(action);\n\n            m_ShowLogoControlsAnimator.valueChanged.RemoveAllListeners();\n            m_ShowLogoControlsAnimator.valueChanged.AddListener(action);\n        }\n\n        private void DrawLogoListHeaderCallback(Rect rect)\n        {\n            m_TotalLogosDuration = 0; // Calculated during logo list draw\n            EditorGUI.LabelField(rect, \"Logos\");\n        }\n\n        private void DrawElementUnityLogo(Rect rect, int index, bool isActive, bool isFocused)\n        {\n            var element = m_SplashScreenLogos.GetArrayElementAtIndex(index);\n            var duration = element.FindPropertyRelative(\"duration\");\n\n            // Unity logo\n            float logoWidth = Mathf.Clamp(rect.width - k_LogoListPropertyMinWidth, k_LogoListUnityLogoMinWidth, k_LogoListUnityLogoMaxWidth);\n            var logoRect = new Rect(rect.x, rect.y, logoWidth, rect.height);\n            GUI.DrawTexture(logoRect, UnityLogo.texture, ScaleMode.ScaleToFit);\n\n            // Properties\n            var oldLabelWidth = EditorGUIUtility.labelWidth;\n            EditorGUIUtility.labelWidth = k_LogoListPropertyLabelWidth;\n            var propertyRect = new Rect(rect.x + logoWidth, rect.y + EditorGUIUtility.standardVerticalSpacing + EditorGUIUtility.singleLineHeight, rect.width - logoWidth, EditorGUIUtility.singleLineHeight);\n            EditorGUI.BeginChangeCheck();\n            var durationLabel = EditorGUI.BeginProperty(propertyRect, Texts.logoDuration, duration);\n            var newDurationVal = EditorGUI.Slider(propertyRect, durationLabel, duration.floatValue, k_MinLogoTime, k_MaxLogoTime);\n            if (EditorGUI.EndChangeCheck())\n                duration.floatValue = newDurationVal;\n            EditorGUI.EndProperty();\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n\n            m_TotalLogosDuration += duration.floatValue;\n        }\n\n        private void DrawLogoListElementCallback(Rect rect, int index, bool isActive, bool isFocused)\n        {\n            rect.height -= EditorGUIUtility.standardVerticalSpacing;\n\n            var element = m_SplashScreenLogos.GetArrayElementAtIndex(index);\n            var logo = element.FindPropertyRelative(\"logo\");\n\n            if ((Sprite)logo.objectReferenceValue == s_UnityLogoLight)\n            {\n                DrawElementUnityLogo(rect, index, isActive, isFocused);\n                return;\n            }\n\n            // Logo field\n            float unityLogoWidth = Mathf.Clamp(rect.width - k_LogoListPropertyMinWidth, k_LogoListUnityLogoMinWidth, k_LogoListUnityLogoMaxWidth);\n            var logoRect = new Rect(rect.x, rect.y + (rect.height - k_LogoListLogoFieldHeight) / 2.0f, k_LogoListUnityLogoMinWidth, k_LogoListLogoFieldHeight);\n            EditorGUI.BeginChangeCheck();\n            var value = EditorGUI.ObjectField(logoRect, GUIContent.none, (Sprite)logo.objectReferenceValue, typeof(Sprite), false);\n            if (EditorGUI.EndChangeCheck())\n                logo.objectReferenceValue = value;\n\n            // Properties\n            var propertyRect = new Rect(rect.x + unityLogoWidth, rect.y + EditorGUIUtility.standardVerticalSpacing, rect.width - unityLogoWidth, EditorGUIUtility.singleLineHeight);\n            var duration = element.FindPropertyRelative(\"duration\");\n\n            EditorGUI.BeginChangeCheck();\n            var oldLabelWidth = EditorGUIUtility.labelWidth;\n            EditorGUIUtility.labelWidth = k_LogoListPropertyLabelWidth;\n            var newDurationVal = EditorGUI.Slider(propertyRect, Texts.logoDuration, duration.floatValue, k_MinLogoTime, k_MaxLogoTime);\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n            if (EditorGUI.EndChangeCheck())\n                duration.floatValue = newDurationVal;\n\n            m_TotalLogosDuration += duration.floatValue;\n        }\n\n        private void DrawLogoListFooterCallback(Rect rect)\n        {\n            float totalDuration = Mathf.Max(k_MinLogoTime, m_TotalLogosDuration);\n            EditorGUI.LabelField(rect, \"Splash Screen Duration: \" + totalDuration, EditorStyles.miniBoldLabel);\n            ReorderableList.defaultBehaviours.DrawFooter(rect, m_LogoList);\n        }\n\n        private void OnLogoListAddCallback(ReorderableList list)\n        {\n            int index = m_SplashScreenLogos.arraySize;\n            m_SplashScreenLogos.InsertArrayElementAtIndex(m_SplashScreenLogos.arraySize);\n            var element = m_SplashScreenLogos.GetArrayElementAtIndex(index);\n\n            // Set up default values.\n            var logo = element.FindPropertyRelative(\"logo\");\n            var duration = element.FindPropertyRelative(\"duration\");\n            logo.objectReferenceValue = null;\n            duration.floatValue = k_DefaultLogoTime;\n        }\n\n        // Prevent users removing the unity logo.\n        private bool OnLogoListCanRemoveCallback(ReorderableList list)\n        {\n            var element = list.serializedProperty.GetArrayElementAtIndex(list.index);\n            var logo = (Sprite)element.FindPropertyRelative(\"logo\").objectReferenceValue;\n            return logo != s_UnityLogoLight;\n        }\n\n        private void AddUnityLogoToLogosList()\n        {\n            // Only add a logo if one does not already exist.\n            for (int i = 0; i < m_SplashScreenLogos.arraySize; ++i)\n            {\n                var listElement = m_SplashScreenLogos.GetArrayElementAtIndex(i);\n                var listLogo = listElement.FindPropertyRelative(\"logo\");\n                if ((Sprite)listLogo.objectReferenceValue == s_UnityLogoLight)\n                    return;\n            }\n\n            m_SplashScreenLogos.InsertArrayElementAtIndex(0);\n            var element = m_SplashScreenLogos.GetArrayElementAtIndex(0);\n            var logo = element.FindPropertyRelative(\"logo\");\n            var duration = element.FindPropertyRelative(\"duration\");\n            logo.objectReferenceValue = s_UnityLogoLight;\n            duration.floatValue = k_DefaultLogoTime;\n        }\n\n        private void RemoveUnityLogoFromLogosList()\n        {\n            for (int i = 0; i < m_SplashScreenLogos.arraySize; ++i)\n            {\n                var element = m_SplashScreenLogos.GetArrayElementAtIndex(i);\n                var logo = element.FindPropertyRelative(\"logo\");\n                if ((Sprite)logo.objectReferenceValue == s_UnityLogoLight)\n                {\n                    m_SplashScreenLogos.DeleteArrayElementAtIndex(i);\n                    --i; // Continue checking in case we have duplicates.\n                }\n            }\n        }\n\n        private static bool TargetSupportsOptionalBuiltinSplashScreen(BuildTargetGroup targetGroup, ISettingEditorExtension settingsExtension)\n        {\n            if (settingsExtension != null)\n                return settingsExtension.CanShowUnitySplashScreen();\n            return targetGroup == BuildTargetGroup.Standalone;\n        }\n\n        private static void ObjectReferencePropertyField<T>(SerializedProperty property, GUIContent label) where T : UnityEngine.Object\n        {\n            EditorGUI.BeginChangeCheck();\n            Rect r = EditorGUILayout.GetControlRect(true, 64, EditorStyles.objectFieldThumb);\n            label = EditorGUI.BeginProperty(r, label, property);\n            var value = EditorGUI.ObjectField(r, label, (T)property.objectReferenceValue, typeof(T), false);\n            if (EditorGUI.EndChangeCheck())\n            {\n                property.objectReferenceValue = value;\n            }\n            EditorGUI.EndProperty();\n        }\n\n        public void SplashSectionGUI(BuildPlatform platform, ISettingEditorExtension settingsExtension, int sectionIndex = 2)\n        {\n            if (m_Owner.BeginSettingsBox(sectionIndex, Texts.title))\n            {\n                if (platform.namedBuildTarget == NamedBuildTarget.Server)\n                {\n                    PlayerSettingsEditor.ShowNoSettings();\n                    EditorGUILayout.Space();\n                }\n                else\n                {\n                    bool VREnabled = BuildPipeline.IsFeatureSupported(\"ENABLE_VR\", platform.defaultTarget);\n\n                    if (VREnabled)\n                        ObjectReferencePropertyField<Texture2D>(m_VirtualRealitySplashScreen, Texts.vrSplashScreen);\n\n                    if (TargetSupportsOptionalBuiltinSplashScreen(platform.namedBuildTarget.ToBuildTargetGroup(), settingsExtension))\n                        BuiltinCustomSplashScreenGUI(platform.namedBuildTarget.ToBuildTargetGroup(), settingsExtension);\n\n                    if (settingsExtension != null)\n                    {\n                        settingsExtension.SplashSectionGUI();\n                        if (!m_ShowUnitySplashScreen.boolValue && settingsExtension.SupportsStaticSplashScreenBackgroundColor())\n                            EditorGUILayout.PropertyField(m_SplashScreenBackgroundColor, Texts.backgroundColor);\n                    }\n\n                    if (m_ShowUnitySplashScreen.boolValue)\n                        m_Owner.ShowSharedNote();\n                }\n            }\n            m_Owner.EndSettingsBox();\n        }\n\n        private void BuiltinCustomSplashScreenGUI(BuildTargetGroup targetGroup, ISettingEditorExtension settingsExtension)\n        {\n            EditorGUILayout.LabelField(Texts.splashTitle, EditorStyles.boldLabel);\n\n            EditorGUILayout.PropertyField(m_ShowUnitySplashScreen, Texts.showSplash);\n            if (!m_ShowUnitySplashScreen.boolValue)\n                return;\n\n            GUIContent buttonLabel = SplashScreen.isFinished ? Texts.previewSplash : Texts.cancelPreviewSplash;\n            Rect previewButtonRect = GUILayoutUtility.GetRect(buttonLabel, \"button\");\n            previewButtonRect = EditorGUI.PrefixLabel(previewButtonRect, new GUIContent(\" \"));\n            if (GUI.Button(previewButtonRect, buttonLabel))\n            {\n                if (SplashScreen.isFinished)\n                {\n                    SplashScreen.Begin();\n                    PlayModeView.RepaintAll();\n                    var playModeView = PlayModeView.GetMainPlayModeView();\n                    if (playModeView)\n                    {\n                        playModeView.Focus();\n                    }\n                    EditorApplication.update += PollSplashState;\n                }\n                else\n                {\n                    SplashScreen.Stop(SplashScreen.StopBehavior.StopImmediate);\n                    EditorApplication.update -= PollSplashState;\n                }\n\n                GameView.RepaintAll();\n            }\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_SplashScreenLogoStyle, Texts.splashStyle);\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (m_SplashScreenLogoStyle.intValue == (int)PlayerSettings.SplashScreen.UnityLogoStyle.DarkOnLight)\n                    m_SplashScreenBackgroundColor.colorValue = k_DarkOnLightBgColor;\n                else\n                    m_SplashScreenBackgroundColor.colorValue = k_LightOnDarkBgColor;\n            }\n\n            // Animation\n            EditorGUILayout.PropertyField(m_SplashScreenAnimation, Texts.animate);\n            m_ShowAnimationControlsAnimator.target = m_SplashScreenAnimation.intValue == (int)PlayerSettings.SplashScreen.AnimationMode.Custom;\n\n            if (EditorGUILayout.BeginFadeGroup(m_ShowAnimationControlsAnimator.faded))\n            {\n                EditorGUI.indentLevel++;\n                EditorGUILayout.Slider(m_SplashScreenLogoAnimationZoom, 0.0f, 1.0f, Texts.logoZoom);\n                EditorGUILayout.Slider(m_SplashScreenBackgroundAnimationZoom, 0.0f, 1.0f, Texts.backgroundZoom);\n                EditorGUI.indentLevel--;\n            }\n            EditorGUILayout.EndFadeGroup();\n\n            EditorGUILayout.Space();\n\n            // Logos\n            EditorGUILayout.LabelField(Texts.logosTitle, EditorStyles.boldLabel);\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_ShowUnitySplashLogo, Texts.showLogo);\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (!m_ShowUnitySplashLogo.boolValue)\n                    RemoveUnityLogoFromLogosList();\n                else if (m_SplashScreenDrawMode.intValue == (int)PlayerSettings.SplashScreen.DrawMode.AllSequential)\n                    AddUnityLogoToLogosList();\n            }\n\n            m_ShowLogoControlsAnimator.target = m_ShowUnitySplashLogo.boolValue;\n\n            if (EditorGUILayout.BeginFadeGroup(m_ShowLogoControlsAnimator.faded))\n            {\n                EditorGUI.BeginChangeCheck();\n                var oldDrawmode = m_SplashScreenDrawMode.intValue;\n                EditorGUILayout.PropertyField(m_SplashScreenDrawMode, Texts.drawMode);\n                if (oldDrawmode != m_SplashScreenDrawMode.intValue)\n                {\n                    if (m_SplashScreenDrawMode.intValue == (int)PlayerSettings.SplashScreen.DrawMode.UnityLogoBelow)\n                        RemoveUnityLogoFromLogosList();\n                    else\n                        AddUnityLogoToLogosList();\n                }\n            }\n            EditorGUILayout.EndFadeGroup();\n\n            using (var vertical = new EditorGUILayout.VerticalScope())\n            using (new EditorGUI.PropertyScope(vertical.rect, GUIContent.none, m_SplashScreenLogos))\n            {\n                m_LogoList.DoLayoutList();\n            }\n\n\n            EditorGUILayout.Space();\n\n            // Background\n            EditorGUILayout.LabelField(Texts.backgroundTitle, EditorStyles.boldLabel);\n            EditorGUILayout.Slider(m_SplashScreenOverlayOpacity, k_MinOverlayOpacity, 1.0f, Texts.overlayOpacity);\n            m_ShowBackgroundColorAnimator.target = m_SplashScreenBackgroundLandscape.objectReferenceValue == null ||\n                (settingsExtension?.SupportsStaticSplashScreenBackgroundColor() ?? false);\n            if (EditorGUILayout.BeginFadeGroup(m_ShowBackgroundColorAnimator.faded))\n                EditorGUILayout.PropertyField(m_SplashScreenBackgroundColor, Texts.backgroundColor);\n            EditorGUILayout.EndFadeGroup();\n\n            EditorGUILayout.PropertyField(m_SplashScreenBlurBackground, Texts.blurBackground);\n            EditorGUI.BeginChangeCheck();\n            ObjectReferencePropertyField<Sprite>(m_SplashScreenBackgroundLandscape, Texts.backgroundImage);\n            if (EditorGUI.EndChangeCheck() && m_SplashScreenBackgroundLandscape.objectReferenceValue == null)\n                m_SplashScreenBackgroundPortrait.objectReferenceValue = null;\n\n            using (new EditorGUI.DisabledScope(m_SplashScreenBackgroundLandscape.objectReferenceValue == null))\n            {\n                ObjectReferencePropertyField<Sprite>(m_SplashScreenBackgroundPortrait, Texts.backgroundPortraitImage);\n            }\n        }\n\n        void PollSplashState()\n        {\n            // Force the GameViews to repaint whilst showing the splash(1166664)\n            PlayModeView.RepaintAll();\n\n            // When the splash screen is playing we need to keep track so that we can update the preview button when it has finished.\n            if (SplashScreen.isFinished)\n            {\n                var window = SettingsWindow.FindWindowByScope(SettingsScope.Project);\n                window?.Repaint();\n                EditorApplication.update -= PollSplashState;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/PlayerSettingsEditor/WebTemplate.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class WebTemplate\n    {\n        public string m_Path, m_Name;\n        public Texture2D m_Thumbnail;\n        public string[] m_CustomKeys;\n\n        public string[] CustomKeys\n        {\n            get\n            {\n                return m_CustomKeys;\n            }\n        }\n\n        public override bool Equals(System.Object other)\n        {\n            return other is WebTemplate && other.ToString().Equals(ToString());\n        }\n\n        public override int GetHashCode()\n        {\n            return base.GetHashCode() ^ m_Path.GetHashCode();\n        }\n\n        public override string ToString()\n        {\n            return m_Path;\n        }\n\n        public GUIContent ToGUIContent(Texture2D defaultIcon)\n        {\n            return new GUIContent(m_Name, m_Thumbnail == null ? defaultIcon : m_Thumbnail);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/PlayerSettingsEditor/WebTemplateManagerBase.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.IO;\n\nnamespace UnityEditor\n{\n    internal abstract class WebTemplateManagerBase\n    {\n        class Styles\n        {\n            public GUIStyle thumbnail = \"IN ThumbnailShadow\";\n            public GUIStyle thumbnailLabel = \"IN ThumbnailSelection\";\n        }\n\n        private static Styles s_Styles;\n\n        private WebTemplate[] m_Templates = null;\n        private GUIContent[] m_TemplateGUIThumbnails = null;\n\n        // Template layout constants\n        const float kWebTemplateGridPadding = 15.0f;\n        const float kThumbnailSize = 80.0f;\n        const float kThumbnailLabelHeight = 20.0f;\n        const float kThumbnailPadding = 5.0f;\n\n        public abstract string customTemplatesFolder\n        {\n            get;\n        }\n\n        public abstract string builtinTemplatesFolder\n        {\n            get;\n        }\n\n        public abstract Texture2D defaultIcon\n        {\n            get;\n        }\n\n        public WebTemplate[] Templates\n        {\n            get\n            {\n                if (m_Templates == null || m_TemplateGUIThumbnails == null)\n                {\n                    BuildTemplateList();\n                }\n\n                return m_Templates;\n            }\n        }\n\n        public GUIContent[] TemplateGUIThumbnails\n        {\n            get\n            {\n                if (m_Templates == null || m_TemplateGUIThumbnails == null)\n                {\n                    BuildTemplateList();\n                }\n\n                return m_TemplateGUIThumbnails;\n            }\n        }\n\n        public abstract string[] GetCustomKeys(string path);\n\n        public int GetTemplateIndex(string path)\n        {\n            for (int i = 0; i < Templates.Length; i++)\n            {\n                if (path.Equals(Templates[i].ToString()))\n                {\n                    return i;\n                }\n            }\n            return -1;\n        }\n\n        public void ClearTemplates()\n        {\n            m_Templates = null;\n            m_TemplateGUIThumbnails = null;\n        }\n\n        private void BuildTemplateList()\n        {\n            List<WebTemplate> templates = new List<WebTemplate>();\n\n            if (Directory.Exists(customTemplatesFolder))\n            {\n                templates.AddRange(ListTemplates(customTemplatesFolder));\n            }\n\n            if (Directory.Exists(builtinTemplatesFolder))\n            {\n                templates.AddRange(ListTemplates(builtinTemplatesFolder));\n            }\n            else\n            {\n                Debug.LogError(\"Did not find built-in templates.\");\n            }\n\n            m_Templates = templates.ToArray();\n\n            m_TemplateGUIThumbnails = new GUIContent[m_Templates.Length];\n            for (int i = 0; i < m_TemplateGUIThumbnails.Length; i++)\n            {\n                m_TemplateGUIThumbnails[i] = m_Templates[i].ToGUIContent(defaultIcon);\n            }\n        }\n\n        private WebTemplate Load(string path)\n        {\n            if (!Directory.Exists(path))\n            {\n                return null;\n            }\n\n            WebTemplate template = new WebTemplate();\n\n            string[] splitPath = path.Split(new char[] {'/', '\\\\'});\n            template.m_Name = splitPath[splitPath.Length - 1];\n            if (splitPath.Length > 3 && splitPath[splitPath.Length - 3].Equals(\"Assets\"))\n            {\n                template.m_Path = \"PROJECT:\" + template.m_Name;\n            }\n            else\n            {\n                template.m_Path = \"APPLICATION:\" + template.m_Name;\n            }\n\n            string thumbnailPath = Path.Combine(path, \"thumbnail.png\");\n            if (File.Exists(thumbnailPath))\n            {\n                template.m_Thumbnail = new Texture2D(2, 2);\n                template.m_Thumbnail.LoadImage(File.ReadAllBytes(thumbnailPath));\n            }\n\n            template.m_CustomKeys = GetCustomKeys(path);\n\n            return template;\n        }\n\n        private List<WebTemplate> ListTemplates(string path)\n        {\n            List<WebTemplate> templates = new List<WebTemplate>();\n            string[] directories = Directory.GetDirectories(path);\n            foreach (string directory in directories)\n            {\n                // skip WebGLIncludes\n                string[] separated_dirs = directory.Split(Path.DirectorySeparatorChar);\n                if (separated_dirs[separated_dirs.Length - 1].Equals(\"WebGLIncludes\")) {\n                    continue;\n                }\n                WebTemplate template = Load(directory);\n                if (template != null)\n                {\n                    templates.Add(template);\n                }\n            }\n            return templates;\n        }\n\n        public void SelectionUI(SerializedProperty templateProp, PlayerSettings playerSettings)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            bool templateChanged = false;\n            using (var vertical = new EditorGUILayout.VerticalScope())\n            {\n                using (new EditorGUI.PropertyScope(vertical.rect, GUIContent.none, templateProp))\n                {\n\n                    var selectedTemplateIndex = GetTemplateIndex(templateProp.stringValue);\n                    if (selectedTemplateIndex < 0)\n                        EditorGUILayout.HelpBox(\"No valid template is selected. Choose a template to proceed.\", MessageType.Error);\n\n                    using (var horizontal = new EditorGUILayout.HorizontalScope())\n                    {\n                        if (TemplateGUIThumbnails.Length < 1)\n                        {\n                            GUILayout.Label(EditorGUIUtility.TrTextContent(\"No templates found.\"));\n                        }\n                        else\n                        {\n                            int numCols = Mathf.Min((int)Mathf.Max((Screen.width - kWebTemplateGridPadding * 2.0f) / kThumbnailSize, 1.0f), TemplateGUIThumbnails.Length);\n                            int numRows = Mathf.Max((int)Mathf.Ceil((float)TemplateGUIThumbnails.Length / (float)numCols), 1);\n\n                            var updatedSelectedTemplateIndex =  ThumbnailList(\n                                GUILayoutUtility.GetRect(numCols * kThumbnailSize, numRows * (kThumbnailSize + kThumbnailLabelHeight), GUILayout.ExpandWidth(false)),\n                                selectedTemplateIndex,\n                                TemplateGUIThumbnails,\n                                numCols\n                            );\n                            templateChanged = selectedTemplateIndex != updatedSelectedTemplateIndex;\n\n                            // Only set/update templateProp and selectedTemplateIndex if there is a valid template selection.\n                            if (updatedSelectedTemplateIndex > -1)\n                            {\n                                templateProp.stringValue = Templates[updatedSelectedTemplateIndex].ToString();\n                                selectedTemplateIndex = updatedSelectedTemplateIndex;\n                            }\n                        }\n                    }\n\n                    bool orgChanged = GUI.changed;\n                    GUI.changed = false;\n\n                    var templateCustomKeys = new string[]{};\n                    if (selectedTemplateIndex > -1)\n                    {\n                        templateCustomKeys = Templates[GetTemplateIndex(templateProp.stringValue)].CustomKeys;\n                        foreach (string key in templateCustomKeys)\n                        {\n                            string value = playerSettings.GetTemplateCustomValue_Internal(key);\n                            value = EditorGUILayout.TextField(PrettyTemplateKeyName(key), value);\n                            playerSettings.SetTemplateCustomValue_Internal(key, value);\n                        }\n                    }\n\n                    if (GUI.changed)\n                        templateProp.serializedObject.Update();\n                    GUI.changed |= orgChanged;\n\n                    if (templateChanged)\n                    {\n                        GUIUtility.hotControl = 0;\n                        GUIUtility.keyboardControl = 0;\n                        templateProp.serializedObject.ApplyModifiedProperties();\n                        playerSettings.SetTemplateCustomKeys_Internal(templateCustomKeys);\n                        templateProp.serializedObject.Update();\n                    }\n                }\n            }\n        }\n\n        static int ThumbnailList(Rect rect, int selection, GUIContent[] thumbnails, int maxRowItems)\n        {\n            for (int y = 0, i = 0; i < thumbnails.Length; y++)\n            {\n                for (int x = 0; x < maxRowItems && i < thumbnails.Length; x++, i++)\n                {\n                    if (ThumbnailListItem(\n                        new Rect(rect.x + x * kThumbnailSize, rect.y + y * (kThumbnailSize + kThumbnailLabelHeight), kThumbnailSize, (kThumbnailSize + kThumbnailLabelHeight)),\n                        i == selection, thumbnails[i]))\n                    {\n                        selection = i;\n                    }\n                }\n            }\n            return selection;\n        }\n\n        static bool ThumbnailListItem(Rect rect, bool selected, GUIContent content)\n        {\n            switch (Event.current.type)\n            {\n                case EventType.MouseDown:\n                    if (rect.Contains(Event.current.mousePosition))\n                    {\n                        if (!selected)\n                        {\n                            GUI.changed = true;\n                        }\n                        selected = true;\n                        Event.current.Use();\n                    }\n                    break;\n                case EventType.Repaint:\n                    Rect thumbRect = new Rect(rect.x + kThumbnailPadding, rect.y + kThumbnailPadding, rect.width - kThumbnailPadding * 2.0f, rect.height - kThumbnailLabelHeight - kThumbnailPadding * 2.0f);\n                    s_Styles.thumbnail.Draw(thumbRect, content.image, false, false, selected, selected);\n                    s_Styles.thumbnailLabel.Draw(new Rect(rect.x, rect.y + rect.height - kThumbnailLabelHeight, rect.width, kThumbnailLabelHeight), content.text, false, false, selected, selected);\n                    break;\n            }\n            return selected;\n        }\n\n        static string PrettyTemplateKeyName(string name)\n        {\n            string[] elements = name.Split('_');\n\n            elements[0] = UppercaseFirst(elements[0].ToLower());\n            for (int i = 1; i < elements.Length; i++)\n            {\n                elements[i] = elements[i].ToLower();\n            }\n\n            return string.Join(\" \", elements);\n        }\n\n        static string UppercaseFirst(string target)\n        {\n            if (string.IsNullOrEmpty(target))\n            {\n                return string.Empty;\n            }\n            return char.ToUpper(target[0]) + target.Substring(1);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/PlayerSettingsSectionAttribute.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Reflection;\nusing UnityEditor.Build;\n\nnamespace UnityEditor\n{\n    [System.AttributeUsage(System.AttributeTargets.Method)]\n    internal class PlayerSettingsSectionAttribute: System.Attribute\n    {\n        private string targetName;\n        public string title;\n        public int order;\n\n        public string TargetName => targetName;\n        public string Title => title;\n        public int Order => order;\n\n        public PlayerSettingsSectionAttribute(string targetName)\n        {\n            this.targetName = targetName;\n            this.title = String.Empty;\n            this.order = 0;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/PositionConstraintEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Animations;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(PositionConstraint))]\n    [CanEditMultipleObjects]\n    internal class PositionConstraintEditor : ConstraintEditorBase\n    {\n        private SerializedProperty m_TranslationAtRest;\n        private SerializedProperty m_TranslationOffset;\n        private SerializedProperty m_Weight;\n        private SerializedProperty m_IsContraintActive;\n        private SerializedProperty m_IsLocked;\n        private SerializedProperty m_Sources;\n\n        internal override SerializedProperty atRest { get { return m_TranslationAtRest; } }\n        internal override SerializedProperty offset { get { return m_TranslationOffset; } }\n        internal override SerializedProperty weight { get { return m_Weight; } }\n        internal override SerializedProperty isContraintActive { get { return m_IsContraintActive; } }\n        internal override SerializedProperty isLocked { get { return m_IsLocked; } }\n        internal override SerializedProperty sources { get { return m_Sources; } }\n\n        private class Styles : ConstraintStyleBase\n        {\n            GUIContent m_RestTranslation = EditorGUIUtility.TrTextContent(\"Position At Rest\");\n            GUIContent m_TranslationOffset = EditorGUIUtility.TrTextContent(\"Position Offset\");\n\n            GUIContent m_TranslationAxes = EditorGUIUtility.TrTextContent(\"Freeze Position Axes\");\n\n            public override GUIContent AtRest { get { return m_RestTranslation; } }\n            public override GUIContent Offset { get { return m_TranslationOffset; }  }\n            public GUIContent FreezeAxes { get { return m_TranslationAxes; } }\n        }\n\n        private static Styles s_Style;\n\n        public void OnEnable()\n        {\n            if (s_Style == null)\n                s_Style = new Styles();\n\n            m_TranslationAtRest = serializedObject.FindProperty(\"m_TranslationAtRest\");\n            m_TranslationOffset = serializedObject.FindProperty(\"m_TranslationOffset\");\n            m_Weight = serializedObject.FindProperty(\"m_Weight\");\n            m_IsContraintActive = serializedObject.FindProperty(\"m_Active\");\n            m_IsLocked = serializedObject.FindProperty(\"m_IsLocked\");\n            m_Sources = serializedObject.FindProperty(\"m_Sources\");\n\n            OnEnable(s_Style);\n        }\n\n        internal override void OnValueAtRestChanged()\n        {\n            foreach (var t in targets)\n                (t as PositionConstraint).transform.localPosition = atRest.vector3Value;\n        }\n\n        internal override void ShowFreezeAxesControl()\n        {\n            Rect drawRect = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, s_Style.FreezeAxes), EditorStyles.toggle);\n            EditorGUI.MultiPropertyField(drawRect, s_Style.Axes, serializedObject.FindProperty(\"m_AffectTranslationX\"), s_Style.FreezeAxes);\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (s_Style == null)\n                s_Style = new Styles();\n\n            serializedObject.Update();\n\n            ShowConstraintEditor<PositionConstraint>(s_Style);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/PreviewRenderUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing UnityEditor.SceneManagement;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEngine.Experimental.Rendering;\nusing UnityEngine.SceneManagement;\nusing Debug = UnityEngine.Debug;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class PreviewScene : IDisposable\n    {\n        private readonly Scene m_Scene;\n        private readonly List<GameObject> m_GameObjects = new List<GameObject>();\n        private readonly Camera m_Camera;\n\n        public PreviewScene(string sceneName)\n        {\n            m_Scene = EditorSceneManager.NewPreviewScene();\n            if (!m_Scene.IsValid())\n                throw new InvalidOperationException(\"Preview scene could not be created\");\n\n            m_Scene.name = sceneName;\n\n            var camGO = EditorUtility.CreateGameObjectWithHideFlags(\"Preview Scene Camera\", HideFlags.HideAndDontSave, typeof(Camera));\n            AddGameObject(camGO);\n            m_Camera = camGO.GetComponent<Camera>();\n            camera.cameraType = CameraType.Preview;\n            camera.enabled = false;\n            camera.clearFlags = CameraClearFlags.Depth;\n            camera.fieldOfView = 15;\n            camera.farClipPlane = 10.0f;\n            camera.nearClipPlane = 2.0f;\n\n            // Explicitly use forward rendering for all previews\n            // (deferred fails when generating some static previews at editor launch; and we never want\n            // vertex lit previews if that is chosen in the player settings)\n            camera.renderingPath = RenderingPath.Forward;\n            camera.useOcclusionCulling = false;\n            camera.scene = m_Scene;\n        }\n\n        public Camera camera\n        {\n            get { return m_Camera; }\n        }\n\n        public Scene scene\n        {\n            get { return m_Scene; }\n        }\n\n        public void AddGameObject(GameObject go)\n        {\n            if (m_GameObjects.Contains(go))\n                return;\n\n            SceneManager.MoveGameObjectToScene(go, m_Scene);\n            m_GameObjects.Add(go);\n        }\n\n        public void AddManagedGO(GameObject go)\n        {\n            SceneManager.MoveGameObjectToScene(go, m_Scene);\n        }\n\n        public void Dispose()\n        {\n            EditorSceneManager.ClosePreviewScene(m_Scene);\n\n            foreach (var go in m_GameObjects)\n                Object.DestroyImmediate(go);\n\n            m_GameObjects.Clear();\n        }\n    }\n\n    public class PreviewRenderUtility\n    {\n        private readonly PreviewScene m_PreviewScene;\n\n        private RenderTexture m_RenderTexture;\n        private Rect m_TargetRect;\n        private SavedRenderTargetState m_SavedState;\n        private bool m_PixelPerfect;\n        private Material m_InvisibleMaterial;\n        private bool m_previewOpened;\n\n        private string m_Type;\n\n        // This is used to track colour space changes\n        // and try to keep colour values in sync\n        private ColorSpace colorSpace;\n        private Color defaultBackgroundColor;\n\n        public PreviewRenderUtility(bool renderFullScene) : this()\n        {}\n\n        public PreviewRenderUtility(bool renderFullScene, bool pixelPerfect) : this()\n        {\n            m_PixelPerfect = pixelPerfect;\n        }\n\n        public PreviewRenderUtility()\n        {\n            m_PreviewScene = new PreviewScene(\"Preview Scene\");\n\n            var l0 = CreateLight();\n            previewScene.AddGameObject(l0);\n            Light0 = l0.GetComponent<Light>();\n\n            var l1 = CreateLight();\n            previewScene.AddGameObject(l1);\n            Light1 = l1.GetComponent<Light>();\n\n            Light0.color = SceneView.kSceneViewFrontLight;\n            Light1.transform.rotation = Quaternion.Euler(340, 218, 177);\n            Light1.color = new Color(.4f, .4f, .45f, 0f) * .7f;\n\n            m_PixelPerfect = false;\n\n            // Set a default background color\n            defaultBackgroundColor = new Color(49.0f / 255.0f, 49.0f / 255.0f, 49.0f / 255.0f, 1.0f);\n            colorSpace = QualitySettings.activeColorSpace;\n            camera.backgroundColor = colorSpace == ColorSpace.Gamma ? defaultBackgroundColor : defaultBackgroundColor.linear;\n\n            if (Unsupported.IsDeveloperMode())\n            {\n                var stackTrace = new StackTrace();\n                for (int i = 0; i < stackTrace.FrameCount; i++)\n                {\n                    var frame = stackTrace.GetFrame(i);\n                    var type = frame.GetMethod().DeclaringType;\n                    if (type != null && (type.IsSubclassOf(typeof(Editor)) || type.IsSubclassOf(typeof(EditorWindow))))\n                    {\n                        m_Type = type.Name;\n                        break;\n                    }\n                }\n            }\n\n            m_previewOpened = false;\n        }\n\n        ~PreviewRenderUtility()\n        {\n            if (m_Type != null)\n            {\n                Debug.LogErrorFormat(\"{0} created a PreviewRenderUtility but didn't call its Cleanup() during OnDisable (or its execution was interrupted). This is leaking the Preview scene in the Editor and should be fixed.\", m_Type);\n            }\n            else\n            {\n                Debug.LogError(\"A PreviewRenderUtility was not clean up properly before assembly reloading which lead to leaking this scene in the Editor. \" +\n                    \"This can be caused by not calling Cleanup() (or its execution being interrupted) during the OnDisable of an Editor or an EditorWindow.\");\n            }\n        }\n\n        internal static void SetEnabledRecursive(GameObject go, bool enabled)\n        {\n            foreach (Renderer renderer in go.GetComponentsInChildren<Renderer>())\n                renderer.enabled = enabled;\n        }\n\n        [Obsolete(\"Use the property camera instead (UnityUpgradable) -> camera\", false)]\n        public Camera m_Camera;\n\n        public Camera camera\n        {\n            get { return previewScene.camera; }\n        }\n\n        [Obsolete(\"Use the property cameraFieldOfView (UnityUpgradable) -> cameraFieldOfView\", false)]\n        public float m_CameraFieldOfView;\n\n        public float cameraFieldOfView\n        {\n            get { return camera.fieldOfView; }\n            set { camera.fieldOfView = value; }\n        }\n\n        public Color ambientColor { get; set; }\n\n        [Obsolete(\"Use the property lights (UnityUpgradable) -> lights\", false)]\n        public Light[] m_Light;\n\n        public Light[] lights\n        {\n            get\n            {\n                return new[] { Light0, Light1 };\n            }\n        }\n\n        private Light Light0 { get; set; }\n\n        private Light Light1 { get; set; }\n\n        internal RenderTexture renderTexture\n        {\n            get { return m_RenderTexture; }\n        }\n\n        internal PreviewScene previewScene\n        {\n            get { return m_PreviewScene; }\n        }\n\n        public void Cleanup()\n        {\n            if (m_previewOpened)\n            {\n                Debug.LogError(\"Missing EndPreview() before cleanup of PreviewRenderUtility\");\n                EndPreview();\n            }\n\n            if (m_RenderTexture)\n            {\n                Object.DestroyImmediate(m_RenderTexture);\n                m_RenderTexture = null;\n            }\n\n            if (m_InvisibleMaterial != null)\n            {\n                Object.DestroyImmediate(m_InvisibleMaterial);\n                m_InvisibleMaterial = null;\n            }\n\n            previewScene.Dispose();\n            GC.SuppressFinalize(this);\n        }\n\n        public void BeginPreview(Rect r, GUIStyle previewBackground)\n        {\n            if(m_previewOpened)\n            {\n                Debug.LogError(\"Previous PreviewRenderUtility.BeginPreview() was not closed with PreviewRenderUtility.EndPreview()\");\n                return;\n            }\n\n            m_previewOpened = true;\n\n            Texture defaultEnvTexture = ReflectionProbe.defaultTexture;\n\n            if (Unsupported.SetOverrideLightingSettings(previewScene.scene))\n            {\n                RenderSettings.defaultReflectionMode = UnityEngine.Rendering.DefaultReflectionMode.Custom;\n                RenderSettings.customReflectionTexture = defaultEnvTexture;\n            }\n\n            InitPreview(r);\n\n            if (previewBackground == null || previewBackground == GUIStyle.none || previewBackground.normal.background == null)\n                return;\n\n            Graphics.DrawTexture(\n                previewBackground.overflow.Add(new Rect(0, 0, m_RenderTexture.width, m_RenderTexture.height)),\n                previewBackground.normal.background, new Rect(0, 0, 1, 1), previewBackground.border.left,\n                previewBackground.border.right, previewBackground.border.top, previewBackground.border.bottom,\n                new Color(.5f, .5f, .5f, 0.5f), null\n            );\n        }\n\n        public void BeginStaticPreview(Rect r)\n        {\n            InitPreview(r);\n            var color = new Color(82 / 255f, 82 / 255f, 82 / 255f, 1.0f);\n            var darkGreyBackground = new Texture2D(1, 1, TextureFormat.RGBA32, true);\n            darkGreyBackground.SetPixel(0, 0, color);\n            darkGreyBackground.Apply();\n            Graphics.DrawTexture(new Rect(0, 0, m_RenderTexture.width, m_RenderTexture.height), darkGreyBackground);\n            Object.DestroyImmediate(darkGreyBackground);\n\n            if (!EditorApplication.isUpdating && Unsupported.SetOverrideLightingSettings(previewScene.scene))\n            {\n                RenderSettings.defaultReflectionMode = UnityEngine.Rendering.DefaultReflectionMode.Custom;\n                RenderSettings.customReflectionTexture = GetDefaultReflection();\n            }\n        }\n\n        private static Cubemap s_DefaultReflection;\n        private static Cubemap GetDefaultReflection()\n        {\n            // Reflection texture set to default prefab mode cubemap so that there are at least some reflections\n            // (cannot use ReflectionProbe.defaultTexture as static previews are generated before it is set, case UUM-1820)\n            const string path = \"PrefabMode/DefaultReflectionForPrefabMode.exr\";\n            if (s_DefaultReflection == null)\n                s_DefaultReflection = EditorGUIUtility.Load(path) as Cubemap;\n            if (s_DefaultReflection == null)\n                Debug.LogError(\"Could not find: \" + path);\n\n            return s_DefaultReflection;\n        }\n\n        private void InitPreview(Rect r)\n        {\n            // If the background colour has changed then we can't make any assumptions\n            // about colour space, otherwise flip to the background colour to the correct one\n            if (colorSpace != QualitySettings.activeColorSpace\n                && (camera.backgroundColor == defaultBackgroundColor || camera.backgroundColor.linear == defaultBackgroundColor.linear))\n            {\n                camera.backgroundColor = QualitySettings.activeColorSpace == ColorSpace.Linear\n                    ? defaultBackgroundColor.linear\n                    : defaultBackgroundColor;\n            }\n\n            m_TargetRect = r;\n            float scaleFac = EditorGUIUtility.pixelsPerPoint;\n\n            int rtWidth = (int)(r.width * scaleFac);\n            int rtHeight = (int)(r.height * scaleFac);\n            if (!m_RenderTexture || m_RenderTexture.width != rtWidth || m_RenderTexture.height != rtHeight)\n            {\n                if (m_RenderTexture)\n                {\n                    Object.DestroyImmediate(m_RenderTexture);\n                    m_RenderTexture = null;\n                }\n\n                // Do not use GetTemporary to manage render textures. Temporary RTs are only\n                // garbage collected each N frames, and in the editor we might be wildly resizing\n                // the inspector, thus using up tons of memory.\n                GraphicsFormat format = camera.allowHDR ? GraphicsFormat.R16G16B16A16_SFloat : GraphicsFormat.R8G8B8A8_UNorm;\n                m_RenderTexture = new RenderTexture(rtWidth, rtHeight, format, SystemInfo.GetGraphicsFormat(DefaultFormat.DepthStencil));\n                m_RenderTexture.hideFlags = HideFlags.HideAndDontSave;\n\n                camera.targetTexture = m_RenderTexture;\n\n                foreach (var light in lights)\n                    light.enabled = true;\n            }\n\n            if (Event.current != null && Event.current.type == EventType.Repaint)\n                camera.pixelRect = new Rect(0, 0, rtWidth, rtHeight);\n            else if (Event.current != null && Event.current.type == EventType.Layout)\n                camera.pixelRect = EditorGUIUtility.PointsToPixels(r);\n\n            m_SavedState = new SavedRenderTargetState();\n            EditorGUIUtility.SetRenderTextureNoViewport(m_RenderTexture);\n            GL.LoadOrtho();\n            GL.LoadPixelMatrix(0, m_RenderTexture.width, m_RenderTexture.height, 0);\n            ShaderUtil.rawViewportRect = new Rect(0, 0, m_RenderTexture.width, m_RenderTexture.height);\n            ShaderUtil.rawScissorRect = new Rect(0, 0, m_RenderTexture.width, m_RenderTexture.height);\n            GL.Clear(true, true, camera.backgroundColor);\n\n            foreach (var light in lights)\n                light.enabled = true;\n        }\n\n        public float GetScaleFactor(float width, float height)\n        {\n            float scaleFacX = Mathf.Max(Mathf.Min(width * 2, 1024), width) / width;\n            float scaleFacY = Mathf.Max(Mathf.Min(height * 2, 1024), height) / height;\n            float result = Mathf.Min(scaleFacX, scaleFacY) * EditorGUIUtility.pixelsPerPoint;\n            if (m_PixelPerfect)\n                result = Mathf.Max(Mathf.Round(result), 1f);\n            return result;\n        }\n\n        [Obsolete(\"This method has been marked obsolete, use BeginStaticPreview() instead (UnityUpgradable) -> BeginStaticPreview(*)\", false)]\n        public void BeginStaticPreviewHDR(Rect r)\n        {\n            BeginStaticPreview(r);\n        }\n\n        [Obsolete(\"This method has been marked obsolete, use BeginPreview() instead (UnityUpgradable) -> BeginPreview(*)\", false)]\n        public void BeginPreviewHDR(Rect r, GUIStyle previewBackground)\n        {\n            BeginPreview(r, previewBackground);\n        }\n\n        public Texture EndPreview()\n        {\n            Unsupported.RestoreOverrideLightingSettings();\n\n            m_SavedState.Restore();\n            FinishFrame();\n            m_previewOpened = false;\n            return m_RenderTexture;\n        }\n\n        private void FinishFrame()\n        {\n            Unsupported.RestoreOverrideLightingSettings();\n            foreach (var light in lights)\n                light.enabled = false;\n        }\n\n        public void EndAndDrawPreview(Rect r)\n        {\n            var texture = EndPreview();\n            DrawPreview(r, texture);\n        }\n\n        internal static void DrawPreview(Rect r, Texture texture)\n        {\n            GUI.DrawTexture(r, texture, ScaleMode.StretchToFill, false);\n        }\n\n        public Texture2D EndStaticPreview()\n        {\n            if (!EditorApplication.isUpdating)\n                Unsupported.RestoreOverrideLightingSettings();\n\n            var tmp = RenderTexture.GetTemporary((int)m_TargetRect.width, (int)m_TargetRect.height, 0, GraphicsFormat.R8G8B8A8_UNorm);\n\n            Graphics.Blit(m_RenderTexture, tmp, EditorGUIUtility.GUITextureBlit2SRGBMaterial);\n\n            RenderTexture.active = tmp;\n            var copy = new Texture2D((int)m_TargetRect.width, (int)m_TargetRect.height, TextureFormat.RGB24, false, false);\n            copy.ReadPixels(new Rect(0, 0, m_TargetRect.width, m_TargetRect.height), 0, 0);\n            copy.Apply();\n            RenderTexture.ReleaseTemporary(tmp);\n            m_SavedState.Restore();\n            FinishFrame();\n            return copy;\n        }\n\n        [Obsolete(\"AddSingleGO(GameObject go, bool instantiateAtZero) has been deprecated, use AddSingleGo(GameObject go) instead. instantiateAtZero has no effect and is not supported.\")]\n        public void AddSingleGO(GameObject go, bool instantiateAtZero)\n        {\n            AddSingleGO(go);\n        }\n\n        public void AddSingleGO(GameObject go)\n        {\n            previewScene.AddGameObject(go);\n        }\n\n        public GameObject InstantiatePrefabInScene(GameObject prefab)\n        {\n            var instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab, m_PreviewScene.scene);\n            return instance;\n        }\n\n        internal void AddManagedGO(GameObject go)\n        {\n            m_PreviewScene.AddManagedGO(go);\n        }\n\n        public void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material mat, int subMeshIndex)\n        {\n            DrawMesh(mesh, matrix, mat, subMeshIndex, null, null, false);\n        }\n\n        public void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material mat, int subMeshIndex, MaterialPropertyBlock customProperties)\n        {\n            DrawMesh(mesh, matrix, mat, subMeshIndex, customProperties, null, false);\n        }\n\n        public void DrawMesh(Mesh mesh, Matrix4x4 m, Material mat, int subMeshIndex, MaterialPropertyBlock customProperties, Transform probeAnchor, bool useLightProbe)\n        {\n            var quat = Quaternion.LookRotation(m.GetColumn(2), m.GetColumn(1));\n            var pos = m.GetColumn(3);\n            var scale = new Vector3(\n                m.GetColumn(0).magnitude,\n                m.GetColumn(1).magnitude,\n                m.GetColumn(2).magnitude\n            );\n\n            DrawMesh(mesh, pos, scale, quat, mat, subMeshIndex, customProperties, probeAnchor, useLightProbe);\n        }\n\n        public void DrawMesh(Mesh mesh, Vector3 pos, Quaternion rot, Material mat, int subMeshIndex)\n        {\n            DrawMesh(mesh, pos, rot, mat, subMeshIndex, null, null, false);\n        }\n\n        public void DrawMesh(Mesh mesh, Vector3 pos, Quaternion rot, Material mat, int subMeshIndex, MaterialPropertyBlock customProperties)\n        {\n            DrawMesh(mesh, pos, rot, mat, subMeshIndex, customProperties, null, false);\n        }\n\n        public void DrawMesh(Mesh mesh, Vector3 pos, Quaternion rot, Material mat, int subMeshIndex, MaterialPropertyBlock customProperties, Transform probeAnchor)\n        {\n            DrawMesh(mesh, pos, rot, mat, subMeshIndex, customProperties, probeAnchor, false);\n        }\n\n        public void DrawMesh(Mesh mesh, Vector3 pos, Quaternion rot, Material mat, int subMeshIndex, MaterialPropertyBlock customProperties, Transform probeAnchor, bool useLightProbe)\n        {\n            DrawMesh(mesh, pos, Vector3.one, rot, mat, subMeshIndex, customProperties, probeAnchor, useLightProbe);\n        }\n\n        public void DrawMesh(Mesh mesh, Vector3 pos, Vector3 scale, Quaternion rot, Material mat, int subMeshIndex, MaterialPropertyBlock customProperties, Transform probeAnchor, bool useLightProbe)\n        {\n            Graphics.DrawMesh(mesh, Matrix4x4.TRS(pos, rot, scale), mat, 0, camera, subMeshIndex, customProperties, ShadowCastingMode.Off, false, probeAnchor, useLightProbe);\n        }\n\n        public void RenderMesh(Mesh mesh, Matrix4x4 matrix4X4, Material material, int submeshIndex, MaterialPropertyBlock materialProp = null, int meshLodIndex = -1)\n        {\n            RenderParams renderParams = new RenderParams(material);\n            renderParams.camera = camera;\n            renderParams.matProps = materialProp;\n            renderParams.layer = 0;\n            renderParams.shadowCastingMode = ShadowCastingMode.Off;\n            renderParams.receiveShadows = false;\n            renderParams.forceMeshLod = meshLodIndex;\n            renderParams.lightProbeUsage = LightProbeUsage.Off;\n            renderParams.reflectionProbeUsage = ReflectionProbeUsage.Off;\n\n            Graphics.RenderMesh(renderParams, mesh, submeshIndex, matrix4X4);\n        }\n\n        internal static Mesh GetPreviewSphere()\n        {\n            var handleGo = (GameObject)EditorGUIUtility.LoadRequired(\"Previews/PreviewMaterials.fbx\");\n            // Temp workaround to make it not render in the scene\n            handleGo.SetActive(false);\n            foreach (Transform t in handleGo.transform)\n            {\n                if (t.name == \"sphere\")\n                    return t.GetComponent<MeshFilter>().sharedMesh;\n            }\n            return null;\n        }\n\n        protected static GameObject CreateLight()\n        {\n            GameObject lightGO = EditorUtility.CreateGameObjectWithHideFlags(\"PreRenderLight\", HideFlags.HideAndDontSave, typeof(Light));\n            var light = lightGO.GetComponent<Light>();\n            light.type = LightType.Directional;\n            light.intensity = 1.0f;\n            light.enabled = false;\n            return lightGO;\n        }\n\n        public void Render(bool allowScriptableRenderPipeline = false, bool updatefov = true)\n        {\n            if (!EditorApplication.isUpdating && Unsupported.SetOverrideLightingSettings(previewScene.scene))\n            {\n                // User can set an ambientColor if they want to override the default black color\n                // Cannot grab the main scene light probe/color instead as this is sometimes run on a worker without access to the original probe/color.\n                RenderSettings.ambientMode = AmbientMode.Flat;\n                RenderSettings.ambientLight = ambientColor;\n            }\n\n            foreach (var light in lights)\n                light.enabled = true;\n            var oldAllowPipes = Unsupported.useScriptableRenderPipeline;\n            Unsupported.useScriptableRenderPipeline = allowScriptableRenderPipeline;\n\n            float saveFieldOfView = camera.fieldOfView;\n\n            if (updatefov)\n            {\n                // Calculate a view multiplier to avoid clipping when the preview width is smaller than the height.\n                float viewMultiplier = (m_RenderTexture.width <= 0 ? 1.0f : Mathf.Max(1.0f, (float)m_RenderTexture.height / m_RenderTexture.width));\n                // Multiply the viewing area by the viewMultiplier - it requires some conversions since the camera view is expressed as an angle.\n                camera.fieldOfView = Mathf.Atan(viewMultiplier * Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad)) * Mathf.Rad2Deg * 2.0f;\n            }\n\n            camera.Render();\n\n            camera.fieldOfView = saveFieldOfView;\n            Unsupported.useScriptableRenderPipeline = oldAllowPipes;\n        }\n    }\n\n    internal class SavedRenderTargetState\n    {\n        RenderTexture renderTexture;\n        Rect viewport;\n        Rect scissor;\n\n        internal SavedRenderTargetState()\n        {\n            GL.PushMatrix();\n            if (ShaderUtil.hardwareSupportsRectRenderTexture)\n                renderTexture = RenderTexture.active;\n            viewport = ShaderUtil.rawViewportRect;\n            scissor = ShaderUtil.rawScissorRect;\n        }\n\n        internal void Restore()\n        {\n            if (ShaderUtil.hardwareSupportsRectRenderTexture)\n                EditorGUIUtility.SetRenderTextureNoViewport(renderTexture);\n            ShaderUtil.rawViewportRect = viewport;\n            ShaderUtil.rawScissorRect = scissor;\n            GL.PopMatrix();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ProjectSettingsBaseEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    [CustomEditor(typeof(ProjectSettingsBase), true)]\n    internal class ProjectSettingsBaseEditor : Editor\n    {\n        protected override bool ShouldHideOpenButton()\n        {\n            return true;\n        }\n\n        private string m_LocalizedTargetName;\n\n        internal override string targetTitle\n        {\n            get\n            {\n                if (m_LocalizedTargetName == null)\n                    m_LocalizedTargetName = L10n.Tr(target.name);\n                return m_LocalizedTargetName;\n            }\n        }\n    }\n\n    [NativeClass(null)]\n    [ExcludeFromObjectFactory]\n    internal abstract class ProjectSettingsBase : Object\n    {}\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/QualitySettingsEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Build;\nusing UnityEditor.Build.Profile;\nusing UnityEditor.Modules;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(QualitySettings))]\n    internal class QualitySettingsEditor : ProjectSettingsBaseEditor\n    {\n        private class Content\n        {\n            public static readonly GUIContent kPlatformTooltip = EditorGUIUtility.TrTextContent(\"\", \"Allow quality setting on platform\");\n            public static readonly GUIContent kAddQualityLevel = EditorGUIUtility.TrTextContent(\"Add Quality Level\");\n\n            public static readonly GUIContent kGlobalTextureMipmapLimit = EditorGUIUtility.TrTextContent(\"Global Mipmap Limit\", \"The base texture quality level.\");\n\n            public static readonly GUIContent kTextureMipmapLimitGroupsHeader = EditorGUIUtility.TrTextContent(\"Mipmap Limit Groups\", \"Mipmap Limit Groups are used to control quality on a per-texture basis.\");\n            public static readonly GUIContent[] kTextureMipmapLimitGroupsOverrideModeItems =\n            {\n                EditorGUIUtility.TrTextContent(\"Override Global Mipmap Limit: Full Resolution\", \"Global Mipmap Limit is ignored, upload at full resolution.\"),\n                EditorGUIUtility.TrTextContent(\"Override Global Mipmap Limit: Half Resolution\", \"Global Mipmap Limit is ignored, upload at half resolution.\"),\n                EditorGUIUtility.TrTextContent(\"Override Global Mipmap Limit: Quarter Resolution\", \"Global Mipmap Limit is ignored, upload at quarter resolution.\"),\n                EditorGUIUtility.TrTextContent(\"Override Global Mipmap Limit: Eighth Resolution\", \"Global Mipmap Limit is ignored, upload at eighth resolution.\")\n            };\n            public static readonly GUIContent[] kTextureMipmapLimitGroupsOffsetModeItems =\n            {\n                EditorGUIUtility.TrTextContent(\"Offset Global Mipmap Limit: -3\", \"Upload 3 mipmap levels extra compared to the Global Mipmap Limit.\"),\n                EditorGUIUtility.TrTextContent(\"Offset Global Mipmap Limit: -2\", \"Upload 2 mipmap levels extra compared to the Global Mipmap Limit.\"),\n                EditorGUIUtility.TrTextContent(\"Offset Global Mipmap Limit: -1\", \"Upload 1 mipmap level extra compared to the Global Mipmap Limit.\"),\n                EditorGUIUtility.TrTextContent(\"Use Global Mipmap Limit\", \"No offset or override occurs, simply use the Global Mipmap Limit. (Default)\"),\n                EditorGUIUtility.TrTextContent(\"Offset Global Mipmap Limit: +1\", \"Upload 1 mipmap level less compared to the Global Mipmap Limit.\"),\n                EditorGUIUtility.TrTextContent(\"Offset Global Mipmap Limit: +2\", \"Upload 2 mipmap levels less compared to the Global Mipmap Limit.\"),\n                EditorGUIUtility.TrTextContent(\"Offset Global Mipmap Limit: +3\", \"Upload 3 mipmap levels less compared to the Global Mipmap Limit.\")\n            };\n            public static readonly GUIContent kTextureMipmapLimitGroupsOptions = EditorGUIUtility.TrIconContent(\"_Menu\", \"Show additional options\");\n            public static readonly GUIContent kTextureMipmapLimitGroupsOptionsIdentify = EditorGUIUtility.TrTextContent(\"Identify textures\");\n            public static readonly GUIContent kTextureMipmapLimitGroupsOptionsDuplicate = EditorGUIUtility.TrTextContent(\"Duplicate group\");\n            public static readonly GUIContent kTextureMipmapLimitGroupsOptionsRename = EditorGUIUtility.TrTextContent(\"Rename group\");\n            public static readonly GUIContent kTextureMipmapLimitGroupsAddButton = EditorGUIUtility.TrIconContent(\"Toolbar Plus\", \"Create a new mipmap limit group. Note that this adds a group to all quality levels, not only the active one!\");\n            public static readonly GUIContent kTextureMipmapLimitGroupsRemoveButton = EditorGUIUtility.TrIconContent(\"Toolbar Minus\", \"Remove mipmap limit group. Note that this removes the group from all quality levels, not only the active one!\");\n\n            public static readonly string kTextureMipmapLimitGroupsDialogTitleOnUpdate = L10n.Tr(\"Mipmap Limit Groups: Update textures?\");\n            public static readonly string kTextureMipmapLimitGroupsDialogMessageOnRemove = L10n.Tr(\"Textures in your project may still be using '{0}'.\\n\\nSelect 'No' to remove the group without modifying its associated textures. Relevant textures stay bound to the group and fall back automatically to the global mipmap limit.\\n\\nSelect 'Yes' to remove the group and reset the group property of associated textures to 'None'. This triggers a re-import and may take some time. An undo cannot revert the importer changes.\");\n            public static readonly string kTextureMipmapLimitGroupsDialogMessageOnRename = L10n.Tr(\"Textures in your project may still be using '{0}'.\\n\\nSelect 'No' to rename the group without modifying its associated textures. Relevant textures stay bound to the group and fall back automatically to the global mipmap limit.\\n\\nSelect 'Yes' to rename the group and update the group property of associated textures to '{1}'. This triggers a re-import and may take some time. An undo cannot revert the importer changes.\");\n            public static readonly string kTextureMipmapLimitGroupsDialogTitleOnFailure = L10n.Tr(\"Mipmap Limit Groups: Operation failed\");\n            public static readonly string kTextureMipmapLimitGroupsDialogMessageOnRenameFail = L10n.Tr(\"The mipmap limit group '{0}' already exists.\\n'{1}' was not renamed.\");\n            public static readonly string kTextureMipmapLimitGroupsDialogMessageOnUpdateAssetsError = L10n.Tr(\"An error occured while updating texture assets: {0}\");\n            public static readonly string kTextureMipmapLimitGroupsDialogMessageOnIdentifyFail = L10n.Tr(\"No textures are linked to the mipmap limit group '{0}'.\");\n\n            public static readonly GUIContent kStreamingMipmapsActive = EditorGUIUtility.TrTextContent(\"Mipmap Streaming\", \"When enabled, Unity only streams texture mipmap levels relevant to the current Camera's position in a Scene. This reduces the total amount of memory Unity needs for textures. Individual textures must also have 'Stream Mipmap Levels' enabled in their Import Settings.\");\n            public static readonly GUIContent kStreamingMipmapsMemoryBudget = EditorGUIUtility.TrTextContent(\"Memory Budget\", \"The amount of memory (in megabytes) to allocate for all loaded textures.\");\n            public static readonly GUIContent kStreamingMipmapsRenderersPerFrame = EditorGUIUtility.TrTextContent(\"Renderers Per Frame\", \"The number of renderers to process each frame. A lower number decreases the CPU load but delays mipmap loading.\");\n            public static readonly GUIContent kStreamingMipmapsAddAllCameras = EditorGUIUtility.TrTextContent(\"Add All Cameras\", \"When enabled, Unity uses mipmap streaming for every Camera in the Scene. Otherwise, Unity only uses mipmap streaming for Cameras that have an attached Streaming Controller component.\");\n            public static readonly GUIContent kStreamingMipmapsMaxLevelReduction = EditorGUIUtility.TrTextContent(\"Max Level Reduction\", \"The maximum number of mipmap levels a texture can drop.\");\n            public static readonly GUIContent kStreamingMipmapsMaxFileIORequests = EditorGUIUtility.TrTextContent(\"Max IO Requests\", \"The maximum number of texture file requests from the Mipmap Streaming system that can be active at the same time.\");\n\n            public static readonly GUIContent kIconTrash = EditorGUIUtility.TrIconContent(\"TreeEditor.Trash\", \"Delete Level\");\n            public static readonly GUIContent kSoftParticlesHint = EditorGUIUtility.TrTextContent(\"Soft Particles require either the Deferred Shading rendering path or Cameras that render depth textures.\");\n            public static readonly GUIContent kBillboardsFaceCameraPos = EditorGUIUtility.TrTextContent(\"Billboards Face Camera Position\", \"When enabled, terrain billboards face towards the camera position. Otherwise, they face towards the camera plane. This makes billboards look nicer when the camera rotates but it is more resource intensive to process.\");\n            public static readonly GUIContent kUseLegacyDistribution = EditorGUIUtility.TrTextContent(\"Use Legacy Details Distribution\", \"When enabled, terrain details will be scattered using the old scattering algorithm that often resulted in overlapping details. Included for backwards compatibility with terrain authored in Unity 2022.1 and earlier.\");\n            public static readonly GUIContent kVSyncCountLabel = EditorGUIUtility.TrTextContent(\"VSync Count\", \"Specifies how Unity synchronizes rendering with the refresh rate of the display device.\");\n            public static readonly GUIContent kRealtimeLGiCpuUsageLabel = EditorGUIUtility.TrTextContent(\"Realtime GI CPU Usage\", \"How many CPU worker threads to create for Realtime Global Illumination lighting calculations in the Player. Increasing this makes the system react faster to changes in lighting at a cost of using more CPU time. The higher the CPU Usage value, the more worker threads are created for solving Realtime GI.\");\n            public static readonly GUIContent kLODBiasLabel = EditorGUIUtility.TrTextContent(\"LOD Group Bias\", \"The bias Unity uses to determine which model to render when a GameObject’s on-screen size is between two LOD levels. Values between 0 and 1 favor the less detailed model. Values greater than 1 favor the more detailed model.\");\n            public static readonly GUIContent kMaximumLODLevelLabel = EditorGUIUtility.TrTextContent(\"Maximum LOD Group Level\", \"The highest LOD to use in the application.\");\n            public static readonly GUIContent kMeshLODThresholdLabel = EditorGUIUtility.TrTextContent(\"Mesh LOD Threshold\", \"Unity uses this parameter when selecting the Mesh LOD index to render. Increasing this setting makes Unity favor less detailed LODs in the evaluation process.\");\n            public static readonly GUIContent kEnableLODCrossFadeLabel = EditorGUIUtility.TrTextContent(\"LOD Cross Fade\", \"Enables or disables LOD Cross Fade.\");\n            public static readonly GUIContent kMipStrippingHint = EditorGUIUtility.TrTextContent(\"Detected platforms with textures that never use their highest resolution mipmap levels. Enable Texture Mipmap Stripping in the Player Settings to reduce the package size of those platforms.\");\n\n            public static readonly GUIContent kAsyncUploadTimeSlice = EditorGUIUtility.TrTextContent(\"Time Slice\", \"The amount of time (in milliseconds) Unity spends uploading Texture and Mesh data to the GPU per frame.\");\n            public static readonly GUIContent kAsyncUploadBufferSize = EditorGUIUtility.TrTextContent(\"Buffer Size\", \"The size (in megabytes) of the upload buffer Unity uses to stream Texture and Mesh data to GPU.\");\n            public static readonly GUIContent kAsyncUploadPersistentBuffer = EditorGUIUtility.TrTextContent(\"Persistent Buffer\", \"When enabled, the upload buffer persists even when there is nothing left to upload.\");\n            public static readonly GUIContent kAsyncUploadBufferSizeWarning = EditorGUIUtility.TrTextContent(\"Unity has detected that you are using an upload buffer size of {0} MB with the '{1}' setting enabled. If you have issues with excessive memory usage, you may need to reduce the upload buffer size or disable the '{1}' setting. Memory fragmentation can occur if you choose the latter option.\");\n\n            public static readonly GUIContent kOverrideTerrainPixelError = EditorGUIUtility.TrTextContent(\"\", \"Whether to override pixel error in active Terrains.\");\n            public static readonly GUIContent kOverrideTerrainBasemapDist = EditorGUIUtility.TrTextContent(\"\", \"Whether to override base map distance in active Terrains.\");\n            public static readonly GUIContent kOverrideTerrainDensityScale = EditorGUIUtility.TrTextContent(\"\", \"Whether to override detail density scale in active Terrains.\");\n            public static readonly GUIContent kOverrideTerrainDetailDistance = EditorGUIUtility.TrTextContent(\"\", \"Whether to override detail distance in active Terrains.\");\n            public static readonly GUIContent kOverrideTerrainTreeDistance = EditorGUIUtility.TrTextContent(\"\", \"Whether to override tree distance in active Terrains.\");\n            public static readonly GUIContent kOverrideTerrainBillboardStart = EditorGUIUtility.TrTextContent(\"\", \"Whether to override billboard start distance in active Terrains.\");\n            public static readonly GUIContent kOverrideTerrainFadeLength = EditorGUIUtility.TrTextContent(\"\", \"Whether to override billboard fade length in active Terrains.\");\n            public static readonly GUIContent kOverrideTerrainMaxTrees = EditorGUIUtility.TrTextContent(\"\", \"Whether to override max mesh trees in active Terrains.\");\n            public static readonly GUIContent kTerrainPixelError = EditorGUIUtility.TrTextContent(\"Pixel Error\", \"Value set to Terrain pixel error (See Terrain settings)\");\n            public static readonly GUIContent kTerrainBasemapDistance = EditorGUIUtility.TrTextContent(\"Base Map Dist.\", \"Value set to Terrain base map distance (See Terrain settings)\");\n            public static readonly GUIContent kTerrainDetailDensityScale = EditorGUIUtility.TrTextContent(\"Detail Density Scale\", \"Value set to Terrain detail density scale (See Terrain settings)\");\n            public static readonly GUIContent kTerrainDetailDistance = EditorGUIUtility.TrTextContent(\"Detail Distance\", \"Value set to Terrain detail object distance (See Terrain settings)\");\n            public static readonly GUIContent kTerrainTreeDistance = EditorGUIUtility.TrTextContent(\"Tree Distance\", \"Value set to Terrain tree distance (See Terrain settings)\");\n            public static readonly GUIContent kTerrainBillboardStart = EditorGUIUtility.TrTextContent(\"Billboard Start\", \"Value set to Terrain billboard start distance (See Terrain settings)\");\n            public static readonly GUIContent kTerrainFadeLength = EditorGUIUtility.TrTextContent(\"Fade Length\", \"Value set to Terrain billboard fade length (See Terrain settings)\");\n            public static readonly GUIContent kTerrainMaxTrees = EditorGUIUtility.TrTextContent(\"Max Mesh Trees\", \"Value set to Terrain max mesh trees (See Terrain settings)\");\n\n            public static readonly GUIContent kRenderPipelineObject = EditorGUIUtility.TrTextContent(\"Render Pipeline Asset\", \"Specifies the Render Pipeline Asset to use for this quality level. It overrides the value set in the Graphics Settings Window.\");\n\n            public static readonly string buildProfileQualitySettingsOverrideWarning = L10n.Tr(\"The current active build profile has overridden Quality levels inclusion. To ensure that the correct levels are included in your build, see the Build Profiles...\");\n            public static readonly string buildProfileQualitySettingsInformationSingular = L10n.Tr(\"Renaming and deleting Quality levels will impact one build profile. To edit Quality levels included in build profiles, go to Build Profiles...\");\n            public static readonly string buildProfileQualitySettingsInformationPlural = L10n.Tr(\"Renaming and deleting Quality levels will impact {0} build profiles. To edit Quality levels included in build profiles, go to Build Profiles...\");\n        }\n\n        private class Styles\n        {\n            public static readonly GUIStyle kToggle = \"OL Toggle\";\n            public static readonly GUIStyle kDefaultToggle = \"OL ToggleWhite\";\n\n            public static readonly GUIStyle kListEvenBg = \"ObjectPickerResultsOdd\";\n            public static readonly GUIStyle kListOddBg = \"ObjectPickerResultsEven\";\n            public static readonly GUIStyle kDefaultDropdown = \"QualitySettingsDefault\";\n\n            public static readonly GUIStyle kTextureMipmapLimitGroupsOptionsButton = new GUIStyle(EditorStyles.miniButton) { padding = new RectOffset() };\n\n            public const int kMinToggleWidth = 15;\n            public const int kMaxToggleWidth = 20;\n            public const int kHeaderRowHeight = 20;\n            public const int kLabelWidth = 80;\n\n            public const int kTextureMipmapLimitGroupsLabelWidthOffset = -6;\n            public const int kTextureMipmapLimitGroupsOptionsWidth = 16;\n            public const int kTextureMipmapLimitGroupsOffsetTop = 2;\n            public const int kTextureMipmapLimitGroupsPaddingRight = 4;\n\n            public static readonly Vector2 kTextureMipmapLimitGroupsOptionsMenuOffset = new Vector2(-134, 19);\n        }\n\n        public const int kMinAsyncRingBufferSize = 2;\n        public const int kMaxAsyncRingBufferSize = 2047;\n        public const int kAsyncRingBufferSizeWarningThreshold = 513;\n        public const int kMinAsyncUploadTimeSlice = 1;\n        public const int kMaxAsyncUploadTimeSlice = 33;\n\n        private SerializedObject m_QualitySettings;\n        private SerializedProperty m_QualitySettingsProperty;\n        private SerializedProperty m_PerPlatformDefaultQualityProperty;\n        private List<BuildPlatform> m_ValidPlatforms;\n\n        private SerializedProperty m_TextureMipmapLimitGroupNamesProperty;\n        private SerializedProperty m_TextureMipmapLimitGroupSettingsProperty; // Always refers to the active quality level\n        private ReorderableList m_TextureMipmapLimitGroupsList;\n        private bool m_TextureMipmapLimitGroupBeingRenamed = false;\n        private int m_TextureMipmapLimitGroupBeingRenamedIndex = -1;\n        private bool m_TextureMipmapLimitGroupsTextFieldNeedsFocus = false;\n        private bool m_TextureMipmapLimitGroupsRenameShowUpdatePrompt = true;\n\n        private Editor m_PresetEditor;\n        private Presets.Preset m_QualitySettingsPreset;\n\n        IAdaptiveVsyncSetting[] m_AdaptiveVsyncSettings;\n        bool m_AdaptiveVSyncVisible;\n\n        bool m_QualityLevelRenameJustStarted = true;\n        bool m_QualityLevelNeedsRenameInAllProfiles = false;\n        string m_OriginalQualityLevelName = string.Empty;\n        string m_NewQualityLevelName = string.Empty;\n\n        public void OnEnable()\n        {\n            m_QualitySettings = new SerializedObject(target);\n            m_QualitySettingsProperty = m_QualitySettings.FindProperty(\"m_QualitySettings\");\n            m_PerPlatformDefaultQualityProperty = m_QualitySettings.FindProperty(\"m_PerPlatformDefaultQuality\");\n            m_ValidPlatforms = BuildPlatforms.instance.GetValidPlatforms();\n\n            m_TextureMipmapLimitGroupNamesProperty = m_QualitySettings.FindProperty(\"m_TextureMipmapLimitGroupNames\");\n            m_TextureMipmapLimitGroupsList = new ReorderableList(m_QualitySettings, m_TextureMipmapLimitGroupNamesProperty, false, true, true, true);\n            // The ReorderableList uses the GroupNames property as an indicator for how many groups really do exist.\n            m_TextureMipmapLimitGroupsList.drawHeaderCallback = DrawTextureMipmapLimitGroupsHeader;\n            m_TextureMipmapLimitGroupsList.drawElementCallback = DrawTextureMipmapLimitGroupsElement;\n            m_TextureMipmapLimitGroupsList.drawFooterCallback = DrawTextureMipmapLimitGroupsFooter;\n            m_TextureMipmapLimitGroupsList.onAddCallback = AddTextureMipmapLimitGroup;\n            m_TextureMipmapLimitGroupsList.onRemoveCallback = RemoveTextureMipmapLimitGroup;\n\n            var validPlatforms = m_ValidPlatforms.ToArray();\n            var validPlatformsLength = validPlatforms.Length;\n            m_AdaptiveVsyncSettings = new IAdaptiveVsyncSetting[validPlatformsLength];\n            for (int i = 0; i < validPlatformsLength; i++)\n            {\n                string module = ModuleManager.GetTargetStringFromBuildTargetGroup(validPlatforms[i].namedBuildTarget.ToBuildTargetGroup());\n                m_AdaptiveVsyncSettings[i] = ModuleManager.GetAdaptiveSettingEditorExtension(module);\n            }\n\n            ResetQualityLevelRenameTracking();\n        }\n\n        public void OnDestroy()\n        {\n            ResolvePendingQualityLevelRename();\n        }\n\n        private struct QualitySetting\n        {\n            public string m_Name;\n            public string m_PropertyPath;\n            public List<string> m_ExcludedPlatforms;\n        }\n\n        private readonly int m_QualityElementHash = \"QualityElementHash\".GetHashCode();\n        private class Dragging\n        {\n            public int m_StartPosition;\n            public int m_Position;\n        }\n\n        private Dragging m_Dragging;\n        private bool m_ShouldAddNewLevel;\n        private int m_DeleteLevel = -1;\n        private int DoQualityLevelSelection(int currentQualitylevel, IList<QualitySetting> qualitySettings, Dictionary<string, int> platformDefaultQualitySettings)\n        {\n            GUILayout.BeginHorizontal();\n            GUILayout.BeginVertical();\n            var selectedLevel = currentQualitylevel;\n\n            //calculate maximum height\n            var max_height = 0.0f;\n            var min_height = float.MaxValue;\n            foreach (var platform in m_ValidPlatforms)\n            {\n                var icon = platform.compoundSmallIconForQualitySettings;\n                max_height = System.Math.Max(icon.height/icon.pixelsPerPoint + 2, max_height);\n                min_height = System.Math.Min(icon.height/icon.pixelsPerPoint + 2, min_height);\n            }\n\n            //Header row\n            GUILayout.BeginHorizontal();\n            {\n                var followingStyle = EditorStyles.label;\n                var labelStyle = EditorStyles.boldLabel;\n                float p = followingStyle.margin.left;\n                var label = EditorGUIUtility.TempContent(\"Levels\");\n                Rect r = GUILayoutUtility.GetRect(EditorGUIUtility.labelWidth - p, EditorGUI.kSingleLineHeight, followingStyle, GUILayout.ExpandWidth(false));\n                var delta = max_height - min_height;\n                r.yMax += delta;\n                r.yMin += delta;\n                r.xMin += EditorGUI.indent;\n                EditorGUI.HandlePrefixLabel(r, r, label, 0, labelStyle);\n            }\n\n            //Header row icons\n            foreach (var platform in m_ValidPlatforms)\n            {\n                var icon = platform.compoundSmallIconForQualitySettings;\n                var iconRect = GUILayoutUtility.GetRect(GUIContent.none, Styles.kToggle, GUILayout.MinWidth(Styles.kMinToggleWidth), GUILayout.MaxWidth(Styles.kMaxToggleWidth), GUILayout.Height(icon.height/icon.pixelsPerPoint + 2));\n                var delta = max_height - icon.height/icon.pixelsPerPoint-2;\n                iconRect.yMax += delta;\n                iconRect.yMin += delta;\n                var temp = EditorGUIUtility.TempContent(icon);\n                temp.tooltip = platform.title.text;\n                GUI.Label(iconRect, temp);\n                temp.tooltip = \"\";\n            }\n\n            //Extra column for deleting setting button\n            GUILayoutUtility.GetRect(GUIContent.none, Styles.kToggle, GUILayout.MinWidth(Styles.kMinToggleWidth), GUILayout.MaxWidth(Styles.kMaxToggleWidth), GUILayout.Height(Styles.kHeaderRowHeight));\n\n            GUILayout.EndHorizontal();\n\n            //Draw the row for each quality setting\n            var currentEvent = Event.current;\n            for (var i = 0; i < qualitySettings.Count; i++)\n            {\n                GUILayout.BeginHorizontal();\n                var bgStyle = i % 2 == 0 ? Styles.kListEvenBg : Styles.kListOddBg;\n                bool selected = (selectedLevel == i);\n\n                //Draw the selected icon if required\n                const int kExtraIndent = 4;\n                Rect r = GUILayoutUtility.GetRect(EditorGUIUtility.labelWidth - Styles.kToggle.margin.left, EditorGUI.kSingleLineHeight, Styles.kToggle, GUILayout.ExpandWidth(false));\n                r.x += EditorGUI.indent + kExtraIndent;\n\n                switch (currentEvent.type)\n                {\n                    case EventType.Repaint:\n                        bgStyle.Draw(r, GUIContent.none, false, false, selected, false);\n                        GUI.Label(r, EditorGUIUtility.TempContent(qualitySettings[i].m_Name));\n                        break;\n                    case EventType.MouseDown:\n                        if (r.Contains(currentEvent.mousePosition))\n                        {\n                            selectedLevel = i;\n                            GUIUtility.keyboardControl = 0;\n                            GUIUtility.hotControl = m_QualityElementHash;\n                            GUI.changed = true;\n                            m_Dragging = new Dragging {m_StartPosition = i, m_Position = i};\n                            currentEvent.Use();\n                        }\n                        break;\n                    case EventType.MouseDrag:\n                        if (GUIUtility.hotControl == m_QualityElementHash)\n                        {\n                            if (r.Contains(currentEvent.mousePosition))\n                            {\n                                m_Dragging.m_Position = i;\n                                currentEvent.Use();\n                            }\n                        }\n                        break;\n                    case EventType.MouseUp:\n                        if (GUIUtility.hotControl == m_QualityElementHash)\n                        {\n                            GUIUtility.hotControl = 0;\n                            currentEvent.Use();\n                        }\n                        break;\n                    case EventType.KeyDown:\n                        if (currentEvent.keyCode == KeyCode.UpArrow || currentEvent.keyCode == KeyCode.DownArrow)\n                        {\n                            selectedLevel += currentEvent.keyCode == KeyCode.UpArrow ? -1 : 1;\n                            selectedLevel = Mathf.Clamp(selectedLevel, 0, qualitySettings.Count - 1);\n                            GUIUtility.keyboardControl = 0;\n                            GUI.changed = true;\n                            currentEvent.Use();\n                        }\n                        break;\n                }\n\n                //Build a list of the current platform selection and draw it.\n                foreach (var platform in m_ValidPlatforms)\n                {\n                    bool isDefaultQuality = platformDefaultQualitySettings.ContainsKey(platform.name) &&  platformDefaultQualitySettings[platform.name] == i;\n\n                    var toggleRect = GUILayoutUtility.GetRect(Content.kPlatformTooltip, Styles.kToggle, GUILayout.MinWidth(Styles.kMinToggleWidth), GUILayout.MaxWidth(Styles.kMaxToggleWidth));\n                    toggleRect.x += EditorGUI.indent + kExtraIndent;\n\n                    if (Event.current.type == EventType.Repaint)\n                    {\n                        bgStyle.Draw(toggleRect, GUIContent.none, false, false, selected, false);\n                    }\n\n                    var color = GUI.backgroundColor;\n                    if (isDefaultQuality && !EditorApplication.isPlayingOrWillChangePlaymode)\n                        GUI.backgroundColor = Color.green;\n\n                    var supported = !qualitySettings[i].m_ExcludedPlatforms.Contains(platform.name);\n                    var newSupported = GUI.Toggle(toggleRect, supported, Content.kPlatformTooltip, isDefaultQuality ? Styles.kDefaultToggle : Styles.kToggle);\n                    if (supported != newSupported)\n                    {\n                        if (newSupported)\n                            qualitySettings[i].m_ExcludedPlatforms.Remove(platform.name);\n                        else\n                            qualitySettings[i].m_ExcludedPlatforms.Add(platform.name);\n                    }\n\n                    GUI.backgroundColor = color;\n                }\n\n                //Extra column for deleting quality button\n                var deleteButton = GUILayoutUtility.GetRect(GUIContent.none, Styles.kToggle, GUILayout.MinWidth(Styles.kMinToggleWidth), GUILayout.MaxWidth(Styles.kMaxToggleWidth));\n                if (Event.current.type == EventType.Repaint)\n                    bgStyle.Draw(deleteButton, GUIContent.none, false, false, selected, false);\n                if (GUI.Button(deleteButton, Content.kIconTrash, GUIStyle.none))\n                {\n                    m_DeleteLevel = i;\n                }\n\n                GUILayout.EndHorizontal();\n            }\n\n            //Add a spacer line to separate the levels from the defaults\n            GUILayout.BeginHorizontal();\n            DrawHorizontalDivider();\n            GUILayout.EndHorizontal();\n\n            //Default platform selection dropdowns\n            GUILayout.BeginHorizontal();\n\n            EditorGUILayout.PrefixLabel(\"Default\", EditorStyles.label, EditorStyles.boldLabel);\n\n            // Draw default dropdown arrows\n            foreach (var platform in m_ValidPlatforms)\n            {\n                var iconRect = GUILayoutUtility.GetRect(GUIContent.none, Styles.kToggle,\n                    GUILayout.MinWidth(Styles.kMinToggleWidth),\n                    GUILayout.MaxWidth(Styles.kMaxToggleWidth),\n                    GUILayout.Height(Styles.kHeaderRowHeight));\n\n                int position;\n                if (!platformDefaultQualitySettings.TryGetValue(platform.name, out position))\n                    platformDefaultQualitySettings.Add(platform.name, 0);\n\n                position = EditorGUI.Popup(iconRect, position, qualitySettings.Select(x => x.m_Name).ToArray(), Styles.kDefaultDropdown);\n                platformDefaultQualitySettings[platform.name] = position;\n            }\n\n            //Extra column for deleting setting button\n            GUILayoutUtility.GetRect(GUIContent.none, Styles.kToggle, GUILayout.MinWidth(Styles.kMinToggleWidth), GUILayout.MaxWidth(Styles.kMaxToggleWidth), GUILayout.Height(Styles.kHeaderRowHeight));\n\n            GUILayout.EndHorizontal();\n\n            GUILayout.Space(10);\n\n            //Add an extra row for 'Add' button\n            if (GUILayout.Button(Content.kAddQualityLevel))\n                m_ShouldAddNewLevel = true;\n\n            GUILayout.EndVertical();\n\n            GUILayout.FlexibleSpace();\n            GUILayout.EndHorizontal();\n            return selectedLevel;\n        }\n\n        private List<QualitySetting> GetQualitySettings()\n        {\n            // Pull the quality settings from the runtime.\n            var qualitySettings = new List<QualitySetting>();\n\n            foreach (SerializedProperty prop in m_QualitySettingsProperty)\n            {\n                var qs = new QualitySetting\n                {\n                    m_Name = prop.FindPropertyRelative(\"name\").stringValue,\n                    m_PropertyPath = prop.propertyPath\n                };\n\n                qs.m_PropertyPath = prop.propertyPath;\n\n                var platforms = new List<string>();\n                var platformsProp = prop.FindPropertyRelative(\"excludedTargetPlatforms\");\n                foreach (SerializedProperty platformProp in platformsProp)\n                    platforms.Add(platformProp.stringValue);\n\n                qs.m_ExcludedPlatforms = platforms;\n                qualitySettings.Add(qs);\n            }\n            return qualitySettings;\n        }\n\n        private void SetQualitySettings(IEnumerable<QualitySetting> settings)\n        {\n            foreach (var setting in settings)\n            {\n                var property = m_QualitySettings.FindProperty(setting.m_PropertyPath);\n                if (property == null)\n                    continue;\n\n                var platformsProp = property.FindPropertyRelative(\"excludedTargetPlatforms\");\n                if (platformsProp.arraySize != setting.m_ExcludedPlatforms.Count)\n                    platformsProp.arraySize = setting.m_ExcludedPlatforms.Count;\n\n                var count = 0;\n                foreach (SerializedProperty platform in platformsProp)\n                {\n                    if (platform.stringValue != setting.m_ExcludedPlatforms[count])\n                        platform.stringValue = setting.m_ExcludedPlatforms[count];\n                    count++;\n                }\n            }\n        }\n\n        private void HandleAddRemoveQualitySetting(ref int selectedLevel, Dictionary<string, int> platformDefaults)\n        {\n            if (m_DeleteLevel >= 0)\n            {\n                if (m_DeleteLevel < selectedLevel || m_DeleteLevel == m_QualitySettingsProperty.arraySize - 1)\n                {\n                    selectedLevel = Mathf.Max(0, selectedLevel - 1);\n                    QualitySettings.SetQualityLevel(selectedLevel);\n                }\n\n                //Always ensure there is one quality setting\n                if (m_QualitySettingsProperty.arraySize > 1 && m_DeleteLevel >= 0 && m_DeleteLevel < m_QualitySettingsProperty.arraySize)\n                {\n                    var deleteLevelName = m_QualitySettingsProperty.GetArrayElementAtIndex(m_DeleteLevel).FindPropertyRelative(\"name\")?.stringValue;\n                    m_QualitySettingsProperty.DeleteArrayElementAtIndex(m_DeleteLevel);\n                    BuildProfileModuleUtil.RemoveQualityLevelFromAllProfiles(deleteLevelName);\n\n                    // Fix defaults offset\n                    List<string> keys = new List<string>(platformDefaults.Keys);\n                    foreach (var key in keys)\n                    {\n                        int value = platformDefaults[key];\n                        if (value != 0 && value >= m_DeleteLevel)\n                            platformDefaults[key]--;\n                    }\n                }\n\n                m_DeleteLevel = -1;\n            }\n\n            if (m_ShouldAddNewLevel)\n            {\n                m_QualitySettingsProperty.arraySize++;\n                var addedSetting = m_QualitySettingsProperty.GetArrayElementAtIndex(m_QualitySettingsProperty.arraySize - 1);\n                var nameProperty = addedSetting.FindPropertyRelative(\"name\");\n                nameProperty.stringValue = \"Level \" + (m_QualitySettingsProperty.arraySize - 1);\n\n                m_ShouldAddNewLevel = false;\n            }\n        }\n\n        private Dictionary<string, int> GetDefaultQualityForPlatforms()\n        {\n            var defaultPlatformQualities = new Dictionary<string, int>();\n\n            foreach (SerializedProperty prop in m_PerPlatformDefaultQualityProperty)\n            {\n                defaultPlatformQualities.Add(prop.FindPropertyRelative(\"first\").stringValue, prop.FindPropertyRelative(\"second\").intValue);\n            }\n            return defaultPlatformQualities;\n        }\n\n        private void SetDefaultQualityForPlatforms(Dictionary<string, int> platformDefaults)\n        {\n            if (m_PerPlatformDefaultQualityProperty.arraySize != platformDefaults.Count)\n                m_PerPlatformDefaultQualityProperty.arraySize = platformDefaults.Count;\n\n            var count = 0;\n            foreach (var def in platformDefaults)\n            {\n                var element = m_PerPlatformDefaultQualityProperty.GetArrayElementAtIndex(count);\n                var firstProperty = element.FindPropertyRelative(\"first\");\n                var secondProperty = element.FindPropertyRelative(\"second\");\n\n                if (firstProperty.stringValue != def.Key || secondProperty.intValue != def.Value)\n                {\n                    firstProperty.stringValue = def.Key;\n                    secondProperty.intValue = def.Value;\n                }\n                count++;\n            }\n        }\n\n        private static void DrawHorizontalDivider()\n        {\n            var spacerLine = GUILayoutUtility.GetRect(GUIContent.none,\n                GUIStyle.none,\n                GUILayout.ExpandWidth(true),\n                GUILayout.Height(1));\n            var oldBgColor = GUI.backgroundColor;\n            if (EditorGUIUtility.isProSkin)\n                GUI.backgroundColor = oldBgColor * 0.7058f;\n            else\n                GUI.backgroundColor = Color.black;\n\n            if (Event.current.type == EventType.Repaint)\n                EditorGUIUtility.whiteTextureStyle.Draw(spacerLine, GUIContent.none, false, false, false, false);\n\n            GUI.backgroundColor = oldBgColor;\n        }\n\n        void SoftParticlesHintGUI()\n        {\n            var mainCamera = Camera.main;\n            if (mainCamera == null)\n                return;\n\n            RenderingPath renderPath = mainCamera.actualRenderingPath;\n            if (renderPath == RenderingPath.DeferredShading)\n                return; // using deferred, all is good\n\n            if ((mainCamera.depthTextureMode & DepthTextureMode.Depth) != 0)\n                return; // already produces depth texture, all is good\n\n            EditorGUILayout.HelpBox(Content.kSoftParticlesHint.text, MessageType.Warning, false);\n        }\n\n        void MipStrippingHintGUI()\n        {\n            if (PlayerSettings.mipStripping)\n                return;\n\n            EditorGUILayout.HelpBox(Content.kMipStrippingHint.text, MessageType.Info);\n        }\n\n        /**\n         * Internal function that takes the shadow cascade splits property field, and dispatches a call to render the GUI.\n         * It also transfers the result back\n         */\n\n        private void DrawCascadeSplitGUI<T>(ref SerializedProperty shadowCascadeSplit)\n        {\n            float[] cascadePartitionSizes = null;\n\n            System.Type type = typeof(T);\n            if (type == typeof(float))\n                cascadePartitionSizes = new float[] { shadowCascadeSplit.floatValue };\n            else if (type == typeof(Vector3))\n            {\n                Vector3 splits = shadowCascadeSplit.vector3Value;\n                cascadePartitionSizes = new float[]\n                {\n                    Mathf.Clamp(splits[0], 0.0f, 1.0f),\n                    Mathf.Clamp(splits[1] - splits[0], 0.0f, 1.0f),\n                    Mathf.Clamp(splits[2] - splits[1], 0.0f, 1.0f)\n                };\n            }\n\n            if (cascadePartitionSizes != null)\n            {\n                EditorGUI.BeginChangeCheck();\n                ShadowCascadeSplitGUI.HandleCascadeSliderGUI(ref cascadePartitionSizes);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    if (type == typeof(float))\n                        shadowCascadeSplit.floatValue = cascadePartitionSizes[0];\n                    else\n                    {\n                        Vector3 updatedValue = new Vector3();\n                        updatedValue[0] = cascadePartitionSizes[0];\n                        updatedValue[1] = updatedValue[0] + cascadePartitionSizes[1];\n                        updatedValue[2] = updatedValue[1] + cascadePartitionSizes[2];\n                        shadowCascadeSplit.vector3Value = updatedValue;\n                    }\n                }\n            }\n        }\n\n        private bool DrawOverrideToggle(ref SerializedProperty overrideProperty, TerrainQualityOverrides overrideFlag, GUIContent overrideStyle)\n        {\n            var overrideFlagsPropertyValue = (TerrainQualityOverrides)overrideProperty.enumValueFlag;\n            bool overrideActive = overrideFlagsPropertyValue.HasFlag(overrideFlag);\n\n            var overrideRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.toggle, GUILayout.Height(EditorGUIUtility.singleLineHeight), GUILayout.ExpandWidth(false));\n            overrideActive = GUI.Toggle(overrideRect, overrideActive, overrideStyle);\n            overrideProperty.enumValueFlag = overrideActive\n                ? (int)(overrideFlagsPropertyValue | overrideFlag)\n                : (int)(overrideFlagsPropertyValue & ~overrideFlag);\n\n            return overrideActive;\n        }\n\n        static List<string> s_PlatformsWithDifferentRPAssets = new();\n\n        void CheckSameRenderPipelineAssetForOverridenQualityLevels()\n        {\n            s_PlatformsWithDifferentRPAssets.Clear();\n\n            foreach (var platform in m_ValidPlatforms)\n            {\n                var buildTarget = BuildPipeline.GetBuildTargetByName(platform.namedBuildTarget.TargetName);\n                var buildTargetGroupName = BuildPipeline.GetBuildTargetGroup(buildTarget).ToString();\n\n                if (!QualitySettings.SamePipelineAssetsForPlatform(buildTargetGroupName))\n                    s_PlatformsWithDifferentRPAssets.Add(platform.title.ToString());\n            }\n\n            if (s_PlatformsWithDifferentRPAssets.Any())\n            {\n                EditorGUILayout.HelpBox($\"The following platforms have assets in its associated Quality levels that belong to different render pipelines: {string.Join(\", \", s_PlatformsWithDifferentRPAssets)}\", MessageType.Error);\n            }\n        }\n\n        private void ResetQualityLevelRenameTracking()\n        {\n            m_QualityLevelRenameJustStarted = true;\n            m_QualityLevelNeedsRenameInAllProfiles = false;\n            m_OriginalQualityLevelName = string.Empty;\n            m_NewQualityLevelName = string.Empty;\n        }\n\n        // We defer the actual renaming in all build profiles because renaming them with every keystroke is\n        // prohibitively slow. As a result, we perform the rename when the quality level selection changes,\n        // when the user selects a different control, and when the inspector window is closed or loses focus.\n        private void ResolvePendingQualityLevelRename()\n        {\n            if (m_QualityLevelNeedsRenameInAllProfiles)\n            {\n                if (m_OriginalQualityLevelName != m_NewQualityLevelName)\n                {\n                    BuildProfileModuleUtil.RenameQualityLevelInAllProfiles(m_OriginalQualityLevelName, m_NewQualityLevelName);\n                }\n            }\n            ResetQualityLevelRenameTracking();\n        }\n\n        private void ShowAffectedBuildProfileInformation()\n        {\n            var buildProfiles = BuildProfileModuleUtil.GetAllBuildProfiles();\n            var profilesWithQualityLevelOverrides = 0;\n            foreach (var profile in buildProfiles)\n            {\n                if (profile.qualitySettings != null)\n                {\n                    profilesWithQualityLevelOverrides++;\n                }\n            }\n            if (profilesWithQualityLevelOverrides > 0)\n            {\n                if (profilesWithQualityLevelOverrides == 1)\n                    EditorGUILayout.HelpBox(string.Format(Content.buildProfileQualitySettingsInformationSingular), MessageType.Info);\n                else\n                    EditorGUILayout.HelpBox(string.Format(Content.buildProfileQualitySettingsInformationPlural, profilesWithQualityLevelOverrides), MessageType.Info);\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (EditorApplication.isPlayingOrWillChangePlaymode)\n            {\n                EditorGUILayout.HelpBox(\"Changes made in play mode will not be saved.\", MessageType.Warning, true);\n            }\n\n            m_QualitySettings.Update();\n\n            var settings = GetQualitySettings();\n            var defaults = GetDefaultQualityForPlatforms();\n            var selectedLevel = QualitySettings.GetQualityLevel();\n            if (selectedLevel >= m_QualitySettingsProperty.arraySize)\n            {\n                selectedLevel = m_QualitySettingsProperty.arraySize - 1;\n            }\n\n            EditorGUI.BeginChangeCheck();\n            selectedLevel = DoQualityLevelSelection(selectedLevel, settings, defaults);\n            if (EditorGUI.EndChangeCheck())\n                QualitySettings.SetQualityLevel(selectedLevel);\n\n            SetQualitySettings(settings);\n            HandleAddRemoveQualitySetting(ref selectedLevel, defaults);\n            SetDefaultQualityForPlatforms(defaults);\n\n            GUILayout.Space(10.0f);\n            ShowAffectedBuildProfileInformation();\n\n            DrawHorizontalDivider();\n            GUILayout.Space(10.0f);\n\n            var currentSettings = m_QualitySettingsProperty.GetArrayElementAtIndex(selectedLevel);\n            var buildPlatform = currentSettings.FindPropertyRelative(\"buildPlatform\");\n            var nameProperty = currentSettings.FindPropertyRelative(\"name\");\n            var pixelLightCountProperty = currentSettings.FindPropertyRelative(\"pixelLightCount\");\n            var shadowsProperty = currentSettings.FindPropertyRelative(\"shadows\");\n            var shadowResolutionProperty = currentSettings.FindPropertyRelative(\"shadowResolution\");\n            var shadowProjectionProperty = currentSettings.FindPropertyRelative(\"shadowProjection\");\n            var shadowCascadesProperty = currentSettings.FindPropertyRelative(\"shadowCascades\");\n            var shadowDistanceProperty = currentSettings.FindPropertyRelative(\"shadowDistance\");\n            var shadowNearPlaneOffsetProperty = currentSettings.FindPropertyRelative(\"shadowNearPlaneOffset\");\n            var shadowCascade2SplitProperty = currentSettings.FindPropertyRelative(\"shadowCascade2Split\");\n            var shadowCascade4SplitProperty = currentSettings.FindPropertyRelative(\"shadowCascade4Split\");\n            var shadowMaskUsageProperty = currentSettings.FindPropertyRelative(\"shadowmaskMode\");\n            var skinWeightsProperty = currentSettings.FindPropertyRelative(\"skinWeights\");\n            var globalTextureMipmapLimitProperty = currentSettings.FindPropertyRelative(\"globalTextureMipmapLimit\");\n            m_TextureMipmapLimitGroupSettingsProperty = currentSettings.FindPropertyRelative(\"textureMipmapLimitSettings\");\n            var anisotropicTexturesProperty = currentSettings.FindPropertyRelative(\"anisotropicTextures\");\n            var antiAliasingProperty = currentSettings.FindPropertyRelative(\"antiAliasing\");\n            var softParticlesProperty = currentSettings.FindPropertyRelative(\"softParticles\");\n            var realtimeReflectionProbes = currentSettings.FindPropertyRelative(\"realtimeReflectionProbes\");\n            var billboardsFaceCameraPosition = currentSettings.FindPropertyRelative(\"billboardsFaceCameraPosition\");\n            var useLegacyDetailsDistribution = currentSettings.FindPropertyRelative(\"useLegacyDetailDistribution\");\n            var terrainQualityOverridesProperty = currentSettings.FindPropertyRelative(\"terrainQualityOverrides\");\n            var terrainPixelErrorProperty = currentSettings.FindPropertyRelative(\"terrainPixelError\");\n            var terrainDetailDensityScaleProperty = currentSettings.FindPropertyRelative(\"terrainDetailDensityScale\");\n            var terrainBasemapDistanceProperty = currentSettings.FindPropertyRelative(\"terrainBasemapDistance\");\n            var terrainDetailDistanceProperty = currentSettings.FindPropertyRelative(\"terrainDetailDistance\");\n            var terrainTreeDistanceProperty = currentSettings.FindPropertyRelative(\"terrainTreeDistance\");\n            var terrainBillboardStartProperty = currentSettings.FindPropertyRelative(\"terrainBillboardStart\");\n            var terrainFadeLengthProperty = currentSettings.FindPropertyRelative(\"terrainFadeLength\");\n            var terrainMaxTreesProperty = currentSettings.FindPropertyRelative(\"terrainMaxTrees\");\n            var vSyncCountProperty = currentSettings.FindPropertyRelative(\"vSyncCount\");\n            var realtimeGICPUUsageProperty = currentSettings.FindPropertyRelative(\"realtimeGICPUUsage\");\n            var adaptiveVsyncProperty = currentSettings.FindPropertyRelative(\"adaptiveVsync\");\n            var adaptiveVsyncExtraAProperty = currentSettings.FindPropertyRelative(\"adaptiveVsyncExtraA\");\n            var adaptiveVsyncExtraBProperty = currentSettings.FindPropertyRelative(\"adaptiveVsyncExtraB\");\n            var lodBiasProperty = currentSettings.FindPropertyRelative(\"lodBias\");\n            var meshLodThresholdProperty = currentSettings.FindPropertyRelative(\"meshLodThreshold\");\n            var maximumLODLevelProperty = currentSettings.FindPropertyRelative(\"maximumLODLevel\");\n            var enableLODCrossFadeProperty = currentSettings.FindPropertyRelative(\"enableLODCrossFade\");\n            var particleRaycastBudgetProperty = currentSettings.FindPropertyRelative(\"particleRaycastBudget\");\n            var asyncUploadTimeSliceProperty = currentSettings.FindPropertyRelative(\"asyncUploadTimeSlice\");\n            var asyncUploadBufferSizeProperty = currentSettings.FindPropertyRelative(\"asyncUploadBufferSize\");\n            var asyncUploadPersistentBufferProperty = currentSettings.FindPropertyRelative(\"asyncUploadPersistentBuffer\");\n            var resolutionScalingFixedDPIFactorProperty = currentSettings.FindPropertyRelative(\"resolutionScalingFixedDPIFactor\");\n\n            var customRenderPipeline = currentSettings.FindPropertyRelative(\"customRenderPipeline\");\n\n            CheckSameRenderPipelineAssetForOverridenQualityLevels();\n\n            bool usingSRP = GraphicsSettings.currentRenderPipeline != null;\n\n            if (string.IsNullOrEmpty(nameProperty.stringValue))\n                nameProperty.stringValue = \"Level \" + selectedLevel;\n\n            GUILayout.Label(EditorGUIUtility.TempContent(\"Current Build Target: \" + Modules.ModuleManager.GetTargetStringFromBuildTarget(EditorUserBuildSettings.activeBuildTarget)), EditorStyles.boldLabel);\n            if (BuildProfileContext.ActiveProfileHasQualitySettings())\n            {\n                EditorGUILayout.HelpBox(Content.buildProfileQualitySettingsOverrideWarning, MessageType.Warning, true);\n            }\n            if (m_AdaptiveVSyncVisible)\n                EditorGUILayout.HelpBox(\"There are settings below that are only applicable to the current Build Target such as Adaptive Vsync. To change the Build Target, go to the Build Settings\", MessageType.Info);\n            GUILayout.Label(EditorGUIUtility.TempContent(\"Current Active Quality Level\"), EditorStyles.boldLabel);\n\n            const string QualityLevelNamePropertyControlName = \"QualityLevelNamePropertyControl\";\n            var previousName = nameProperty.stringValue;\n            EditorGUI.BeginChangeCheck();\n            GUI.SetNextControlName(QualityLevelNamePropertyControlName);\n            EditorGUILayout.PropertyField(nameProperty);\n            var qualityLevelNameControlChanged = EditorGUI.EndChangeCheck();\n            var qualityLevelNameControlIsFocused = GUI.GetNameOfFocusedControl() == QualityLevelNamePropertyControlName;\n            var inspectorIsFocused = EditorWindow.focusedWindow is ProjectSettingsWindow;\n            if (qualityLevelNameControlChanged)\n            {\n                if (m_QualityLevelRenameJustStarted)\n                {\n                    m_OriginalQualityLevelName = previousName;\n                    m_QualityLevelRenameJustStarted = false;\n                }\n\n                m_QualityLevelNeedsRenameInAllProfiles = true;\n\n                if (string.IsNullOrEmpty(nameProperty.stringValue))\n                    nameProperty.stringValue = \"Level \" + selectedLevel;\n\n                m_NewQualityLevelName = nameProperty.stringValue;\n            }\n            if (m_QualityLevelNeedsRenameInAllProfiles && !(qualityLevelNameControlIsFocused && inspectorIsFocused))\n            {\n                ResolvePendingQualityLevelRename();\n            }\n\n            if (usingSRP)\n                EditorGUILayout.HelpBox(\"A Scriptable Render Pipeline is in use, some settings will not be used and are hidden\", MessageType.Info);\n            GUILayout.Space(10);\n\n            GUILayout.Label(EditorGUIUtility.TempContent(\"Rendering\"), EditorStyles.boldLabel);\n\n            EditorGUI.RenderPipelineAssetField(Content.kRenderPipelineObject, m_QualitySettings, customRenderPipeline);\n            if (!usingSRP && customRenderPipeline.objectReferenceValue != null)\n                EditorGUILayout.HelpBox(\"Missing a Scriptable Render Pipeline in Graphics: \\\"Scriptable Render Pipeline Settings\\\" to use Scriptable Render Pipeline from Quality: \\\"Custom Render Pipeline\\\".\", MessageType.Warning);\n\n            if (!usingSRP)\n                EditorGUILayout.PropertyField(pixelLightCountProperty);\n\n            // still valid with SRP\n            if (!usingSRP)\n            {\n                EditorGUILayout.PropertyField(antiAliasingProperty);\n            }\n\n            if (!SupportedRenderingFeatures.active.overridesRealtimeReflectionProbes)\n                EditorGUILayout.PropertyField(realtimeReflectionProbes);\n            EditorGUILayout.PropertyField(resolutionScalingFixedDPIFactorProperty);\n\n            if (usingSRP)\n                EditorGUILayout.PropertyField(realtimeGICPUUsageProperty, Content.kRealtimeLGiCpuUsageLabel);\n\n            EditorGUILayout.PropertyField(vSyncCountProperty, Content.kVSyncCountLabel);\n\n            if (BuildTargetDiscovery.TryGetBuildTarget(EditorUserBuildSettings.activeBuildTarget, out var iBuildTarget))\n            {\n                if (vSyncCountProperty.intValue > 0 && (iBuildTarget.GraphicsPlatformProperties?.IgnoresVSyncCount ?? false))\n                    EditorGUILayout.HelpBox(EditorGUIUtility.TrTextContent($\"VSync Count '{vSyncCountProperty.enumLocalizedDisplayNames[vSyncCountProperty.enumValueIndex]}' is ignored on {iBuildTarget.DisplayName}.\", EditorGUIUtility.GetHelpIcon(MessageType.Warning)));\n            }\n\n            m_AdaptiveVSyncVisible = false;\n            var externalUI = false;\n            switch (vSyncCountProperty.intValue)\n            {\n                case > 0:\n                {\n                    using var vertical = new EditorGUILayout.VerticalScope();\n                    using var scope = new EditorGUI.IndentLevelScope();\n                    using var disabledScope = new EditorGUI.DisabledScope(vSyncCountProperty.intValue == 0);\n\n                    var validPlatforms = m_ValidPlatforms.ToArray();\n                    for (int i = 0; i < validPlatforms.Length; i++)\n                    {\n                        if (validPlatforms[i].defaultTarget != EditorUserBuildSettings.activeBuildTarget || m_AdaptiveVsyncSettings[i] == null)\n                            continue;\n                        m_AdaptiveVsyncSettings[i].AdaptiveVsyncUI(currentSettings);\n                        m_AdaptiveVSyncVisible = true;\n                        externalUI = true;\n                        break;\n                    }\n                    if (!externalUI)\n                    {\n                        var gfxTypes = PlayerSettings.GetGraphicsAPIs(EditorUserBuildSettings.activeBuildTarget);\n                        for (int i = 0;i < gfxTypes.Length; i++)\n                        {\n                            if (adaptiveVsyncProperty == null || gfxTypes[i] != GraphicsDeviceType.Vulkan)\n                                continue;\n                            EditorGUILayout.PropertyField(adaptiveVsyncProperty);\n                            EditorGUILayout.HelpBox(\"If Adaptive Vsync extension is available at runtime with Vulkan it will use this, else fallback to vsync.\", MessageType.Info);\n                            m_AdaptiveVSyncVisible = true;\n                        }\n                    }\n                    break;\n                }\n                case 0:\n                    adaptiveVsyncProperty.boolValue = false;\n                    break;\n            }\n\n            bool shadowMaskSupported = SupportedRenderingFeatures.IsMixedLightingModeSupported(MixedLightingMode.Shadowmask);\n            bool showShadowMaskUsage = shadowMaskSupported && !SupportedRenderingFeatures.active.overridesShadowmask;\n\n            GUILayout.Space(10);\n            GUILayout.Label(EditorGUIUtility.TempContent(\"Textures\"), EditorStyles.boldLabel);\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(globalTextureMipmapLimitProperty, Content.kGlobalTextureMipmapLimit);\n            if (EditorGUI.EndChangeCheck() && usingSRP)\n            {\n                RenderPipelineManager.CleanupRenderPipeline();\n            }\n\n            EditorGUILayout.Space(3);\n            if (QualitySettings.IsTextureResReducedOnAnyPlatform())\n                MipStrippingHintGUI();\n            m_TextureMipmapLimitGroupsList.DoLayoutList();\n            EditorGUILayout.PropertyField(anisotropicTexturesProperty);\n\n            var streamingMipmapsActiveProperty = currentSettings.FindPropertyRelative(\"streamingMipmapsActive\");\n            EditorGUILayout.PropertyField(streamingMipmapsActiveProperty, Content.kStreamingMipmapsActive);\n            if (streamingMipmapsActiveProperty.boolValue)\n            {\n                EditorGUI.indentLevel++;\n                var streamingMipmapsAddAllCameras = currentSettings.FindPropertyRelative(\"streamingMipmapsAddAllCameras\");\n                EditorGUILayout.PropertyField(streamingMipmapsAddAllCameras, Content.kStreamingMipmapsAddAllCameras);\n                var streamingMipmapsBudgetProperty = currentSettings.FindPropertyRelative(\"streamingMipmapsMemoryBudget\");\n                EditorGUILayout.PropertyField(streamingMipmapsBudgetProperty, Content.kStreamingMipmapsMemoryBudget);\n                var streamingMipmapsRenderersPerFrameProperty = currentSettings.FindPropertyRelative(\"streamingMipmapsRenderersPerFrame\");\n                EditorGUILayout.PropertyField(streamingMipmapsRenderersPerFrameProperty, Content.kStreamingMipmapsRenderersPerFrame);\n                var streamingMipmapsMaxLevelReductionProperty = currentSettings.FindPropertyRelative(\"streamingMipmapsMaxLevelReduction\");\n                EditorGUILayout.PropertyField(streamingMipmapsMaxLevelReductionProperty, Content.kStreamingMipmapsMaxLevelReduction);\n                var streamingMipmapsMaxFileIORequestsProperty = currentSettings.FindPropertyRelative(\"streamingMipmapsMaxFileIORequests\");\n                EditorGUILayout.PropertyField(streamingMipmapsMaxFileIORequestsProperty, Content.kStreamingMipmapsMaxFileIORequests);\n                EditorGUI.indentLevel--;\n            }\n\n            GUILayout.Space(10);\n            GUILayout.Label(EditorGUIUtility.TempContent(\"Particles\"), EditorStyles.boldLabel);\n            if (!usingSRP)\n            {\n                EditorGUILayout.PropertyField(softParticlesProperty);\n                if (softParticlesProperty.boolValue)\n                    SoftParticlesHintGUI();\n            }\n            EditorGUILayout.PropertyField(particleRaycastBudgetProperty);\n\n            GUILayout.Space(10);\n            GUILayout.Label(EditorGUIUtility.TempContent(\"Terrain\"), EditorStyles.boldLabel);\n            EditorGUILayout.PropertyField(billboardsFaceCameraPosition, Content.kBillboardsFaceCameraPos);\n            EditorGUILayout.PropertyField(useLegacyDetailsDistribution, Content.kUseLegacyDistribution);\n\n            GUILayout.Space(5);\n            GUILayout.Label(EditorGUIUtility.TempContent(\"Terrain Setting Overrides\"), EditorStyles.boldLabel);\n\n            var originalLabelWidth = EditorGUIUtility.labelWidth;\n            EditorGUIUtility.labelWidth -= EditorStyles.toggle.CalcSize(GUIContent.none).x + EditorStyles.toggle.margin.left;\n\n            EditorGUILayout.BeginHorizontal();\n            bool pixelErrorActive = DrawOverrideToggle(ref terrainQualityOverridesProperty, TerrainQualityOverrides.PixelError, Content.kOverrideTerrainPixelError);\n            using (new EditorGUI.DisabledScope(!pixelErrorActive))\n                EditorGUILayout.Slider(terrainPixelErrorProperty, 1.0f, 200.0f, Content.kTerrainPixelError);\n            EditorGUILayout.EndHorizontal();\n\n            EditorGUILayout.BeginHorizontal();\n            bool basemapActive = DrawOverrideToggle(ref terrainQualityOverridesProperty, TerrainQualityOverrides.BasemapDistance, Content.kOverrideTerrainBasemapDist);\n            using (new EditorGUI.DisabledScope(!basemapActive))\n            {\n                EditorGUI.BeginChangeCheck();\n                var newValue = EditorGUILayout.PowerSlider(Content.kTerrainBasemapDistance, Mathf.Clamp(terrainBasemapDistanceProperty.floatValue, 0.0f, 20000.0f), 0.0f, 20000.0f, 2);\n                if (EditorGUI.EndChangeCheck())\n                    terrainBasemapDistanceProperty.floatValue = newValue;\n            }\n            EditorGUILayout.EndHorizontal();\n\n            EditorGUILayout.BeginHorizontal();\n            bool detailDensityActive = DrawOverrideToggle(ref terrainQualityOverridesProperty, TerrainQualityOverrides.DetailDensity, Content.kOverrideTerrainDensityScale);\n            using (new EditorGUI.DisabledScope(!detailDensityActive))\n                EditorGUILayout.Slider(terrainDetailDensityScaleProperty, 0.0f, 1.0f, Content.kTerrainDetailDensityScale);\n            EditorGUILayout.EndHorizontal();\n\n            EditorGUILayout.BeginHorizontal();\n            bool detailDistanceActive = DrawOverrideToggle(ref terrainQualityOverridesProperty, TerrainQualityOverrides.DetailDistance, Content.kOverrideTerrainDetailDistance);\n            using (new EditorGUI.DisabledScope(!detailDistanceActive))\n                EditorGUILayout.Slider(terrainDetailDistanceProperty, 0, 1000, Content.kTerrainDetailDistance);\n            EditorGUILayout.EndHorizontal();\n\n            EditorGUILayout.BeginHorizontal();\n            bool treeDistanceActive = DrawOverrideToggle(ref terrainQualityOverridesProperty, TerrainQualityOverrides.TreeDistance, Content.kOverrideTerrainTreeDistance);\n            using (new EditorGUI.DisabledScope(!treeDistanceActive))\n                EditorGUILayout.Slider(terrainTreeDistanceProperty, 0.0f, 5000.0f, Content.kTerrainTreeDistance);\n            EditorGUILayout.EndHorizontal();\n\n            EditorGUILayout.BeginHorizontal();\n            bool billboardStartActive = DrawOverrideToggle(ref terrainQualityOverridesProperty, TerrainQualityOverrides.BillboardStart, Content.kOverrideTerrainBillboardStart);\n            using (new EditorGUI.DisabledScope(!billboardStartActive))\n                EditorGUILayout.Slider(terrainBillboardStartProperty, 5, 2000, Content.kTerrainBillboardStart);\n            EditorGUILayout.EndHorizontal();\n\n            EditorGUILayout.BeginHorizontal();\n            bool fadeLengthActive = DrawOverrideToggle(ref terrainQualityOverridesProperty, TerrainQualityOverrides.FadeLength, Content.kOverrideTerrainFadeLength);\n            using (new EditorGUI.DisabledScope(!fadeLengthActive))\n                EditorGUILayout.Slider(terrainFadeLengthProperty, 0, 200, Content.kTerrainFadeLength);\n            EditorGUILayout.EndHorizontal();\n\n            EditorGUILayout.BeginHorizontal();\n            bool maxTreesActive = DrawOverrideToggle(ref terrainQualityOverridesProperty, TerrainQualityOverrides.MaxTrees, Content.kOverrideTerrainMaxTrees);\n            using (new EditorGUI.DisabledScope(!maxTreesActive))\n                EditorGUILayout.IntSlider(terrainMaxTreesProperty, 0, 10000, Content.kTerrainMaxTrees);\n            EditorGUILayout.EndHorizontal();\n\n            EditorGUIUtility.labelWidth = originalLabelWidth;\n\n            if (!usingSRP || showShadowMaskUsage)\n            {\n                GUILayout.Space(10);\n\n                GUILayout.Label(EditorGUIUtility.TempContent(\"Shadows\"), EditorStyles.boldLabel);\n\n                if (showShadowMaskUsage)\n                    EditorGUILayout.PropertyField(shadowMaskUsageProperty);\n\n                if (!usingSRP)\n                {\n                    EditorGUILayout.PropertyField(shadowsProperty);\n                    EditorGUILayout.PropertyField(shadowResolutionProperty);\n                    EditorGUILayout.PropertyField(shadowProjectionProperty);\n                    EditorGUILayout.PropertyField(shadowDistanceProperty);\n                    EditorGUILayout.PropertyField(shadowNearPlaneOffsetProperty);\n                    EditorGUILayout.PropertyField(shadowCascadesProperty);\n\n                    if (shadowCascadesProperty.intValue == 2)\n                        DrawCascadeSplitGUI<float>(ref shadowCascade2SplitProperty);\n                    else if (shadowCascadesProperty.intValue == 4)\n                        DrawCascadeSplitGUI<Vector3>(ref shadowCascade4SplitProperty);\n                }\n            }\n\n            GUILayout.Space(10);\n            GUILayout.Label(EditorGUIUtility.TempContent(\"Async Asset Upload\"), EditorStyles.boldLabel);\n\n            EditorGUILayout.PropertyField(asyncUploadTimeSliceProperty, Content.kAsyncUploadTimeSlice);\n            EditorGUILayout.PropertyField(asyncUploadBufferSizeProperty, Content.kAsyncUploadBufferSize);\n            EditorGUILayout.PropertyField(asyncUploadPersistentBufferProperty, Content.kAsyncUploadPersistentBuffer);\n\n            asyncUploadTimeSliceProperty.intValue = Mathf.Clamp(asyncUploadTimeSliceProperty.intValue, kMinAsyncUploadTimeSlice, kMaxAsyncUploadTimeSlice);\n            asyncUploadBufferSizeProperty.intValue = Mathf.Clamp(asyncUploadBufferSizeProperty.intValue, kMinAsyncRingBufferSize, kMaxAsyncRingBufferSize);\n\n            if (asyncUploadBufferSizeProperty.intValue >= kAsyncRingBufferSizeWarningThreshold && asyncUploadPersistentBufferProperty.boolValue)\n            {\n                string messageToDisplay = string.Format(Content.kAsyncUploadBufferSizeWarning.text, asyncUploadBufferSizeProperty.intValue, Content.kAsyncUploadPersistentBuffer.text);\n                EditorGUILayout.HelpBox(messageToDisplay, MessageType.Warning, false);\n            }\n\n            GUILayout.Space(10);\n            GUILayout.Label(EditorGUIUtility.TempContent(\"Level of Detail\"), EditorStyles.boldLabel);\n\n            if (!SupportedRenderingFeatures.active.overridesLODBias)\n                EditorGUILayout.PropertyField(lodBiasProperty, Content.kLODBiasLabel);\n            if (!SupportedRenderingFeatures.active.overridesMaximumLODLevel)\n                EditorGUILayout.PropertyField(maximumLODLevelProperty, Content.kMaximumLODLevelLabel);\n            EditorGUILayout.PropertyField(meshLodThresholdProperty, Content.kMeshLODThresholdLabel);\n            if (!SupportedRenderingFeatures.active.overridesEnableLODCrossFade)\n                EditorGUILayout.PropertyField(enableLODCrossFadeProperty, Content.kEnableLODCrossFadeLabel);\n\n            GUILayout.Space(10);\n            GUILayout.Label(EditorGUIUtility.TempContent(\"Meshes\"), EditorStyles.boldLabel);\n            EditorGUILayout.PropertyField(skinWeightsProperty);\n\n            if (m_Dragging != null && m_Dragging.m_Position != m_Dragging.m_StartPosition)\n            {\n                m_QualitySettingsProperty.MoveArrayElement(m_Dragging.m_StartPosition, m_Dragging.m_Position);\n                m_Dragging.m_StartPosition = m_Dragging.m_Position;\n                selectedLevel = m_Dragging.m_Position;\n\n                m_QualitySettings.ApplyModifiedProperties();\n                QualitySettings.SetQualityLevel(Mathf.Clamp(selectedLevel, 0, m_QualitySettingsProperty.arraySize - 1));\n            }\n\n            m_QualitySettings.ApplyModifiedProperties();\n        }\n\n        void DrawTextureMipmapLimitGroupsHeader(Rect rect)\n        {\n            EditorGUI.PrefixLabel(rect, Content.kTextureMipmapLimitGroupsHeader);\n\n            Event e = Event.current;\n            if (rect.Contains(e.mousePosition) && e.type == EventType.ContextClick)\n            {\n                GenericMenu menu = EditorGUI.FillPropertyContextMenu(m_TextureMipmapLimitGroupSettingsProperty);\n\n                if (Presets.Preset.IsEditorTargetAPreset(target))\n                {\n                    // If we are dealing with presets, we will be able to find the \"Include Property\" and/or \"Exclude Property\" menu items.\n                    // Our texture mipmap limit group names and group settings arrays are always separate properties entirely, which means\n                    // that those menu items will not always function as one would expect out-of-the-box, so we apply some custom logic here.\n                    GenericMenu.MenuItem includePropItem = menu.menuItems.Find(menu => menu.content.text == L10n.Tr(\"Include Property\"));\n                    GenericMenu.MenuItem excludePropItem = menu.menuItems.Find(menu => menu.content.text == L10n.Tr(\"Exclude Property\"));\n\n                    if (m_PresetEditor is null) // Can cache the PresetEditor/preset asset since they won't change.\n                    {\n                        m_PresetEditor = (includePropItem?.func2?.Target ?? excludePropItem.func2.Target) as Editor;\n                        m_QualitySettingsPreset = m_PresetEditor.target as Presets.Preset;\n                    }\n                    string groupSettingsArrayPropertyPath = (includePropItem?.userData ?? excludePropItem.userData) as string;\n                    const string groupNamesArrayPropertyPath = \"m_TextureMipmapLimitGroupNames\";\n\n                    // Whenever we include the group settings array of any quality level, it could be that the\n                    // group names array is not included. (if we used \"Exclude all properties\", for example)\n                    // In that case, forcefully include the group names array. (including only the settings will\n                    // not transfer group names over and can replace the settings of unrelated groups!)\n                    if (includePropItem is not null)\n                    {\n                        var includePropertyMethod = includePropItem.func2.Method;\n\n                        includePropItem.func2 = null;\n                        includePropItem.func = () =>\n                        {\n                            includePropertyMethod.Invoke(m_PresetEditor, new object[] { groupSettingsArrayPropertyPath });\n\n                            if (m_QualitySettingsPreset.excludedProperties.Contains(groupNamesArrayPropertyPath))\n                            {\n                                if (!m_QualitySettingsPreset.excludedProperties.Any(p => p == groupSettingsArrayPropertyPath || groupSettingsArrayPropertyPath.StartsWith(p + \".\", System.StringComparison.Ordinal)))\n                                {\n                                    // If and only if the group names array was excluded in the first place,\n                                    // and the group settings array was successfully included, then include\n                                    // the group names array too.\n                                    includePropertyMethod.Invoke(m_PresetEditor, new object[] { groupNamesArrayPropertyPath });\n                                }\n                            }\n                        };\n                    }\n\n                    // Depending on how many group settings arrays are still included after the\n                    // current one gets excluded, we take different paths.\n                    // 1 or more group settings arrays included -> group names stay included too.\n                    // 0 group settings arrays included -> exclude group names.\n                    if (excludePropItem is not null)\n                    {\n                        var excludePropertyMethod = excludePropItem.func2.Method;\n\n                        excludePropItem.func2 = null;\n                        excludePropItem.func = () =>\n                        {\n                            excludePropertyMethod.Invoke(m_PresetEditor, new object[] { groupSettingsArrayPropertyPath });\n\n                            // If the group names array was included (it can be manually excluded!),\n                            // then check if we've got all group settings arrays excluded. If that is\n                            // the case, exclude the group names array too as described earlier.\n                            if (!m_QualitySettingsPreset.excludedProperties.Contains(groupNamesArrayPropertyPath))\n                            {\n                                bool areAllGroupSettingsExcluded = true;\n                                int counter = 0;\n                                while (areAllGroupSettingsExcluded && counter < m_QualitySettingsProperty.arraySize)\n                                {\n                                    string propertyPathToCheck = $\"m_QualitySettings.Array.data[{counter}].textureMipmapLimitSettings\";\n                                    if (!m_QualitySettingsPreset.excludedProperties.Any(p => p == propertyPathToCheck || propertyPathToCheck.StartsWith(p + \".\", System.StringComparison.Ordinal)))\n                                    {\n                                        areAllGroupSettingsExcluded = false;\n                                    }\n                                    ++counter;\n                                }\n                                if (areAllGroupSettingsExcluded)\n                                {\n                                    excludePropertyMethod.Invoke(m_PresetEditor, new object[] { groupNamesArrayPropertyPath });\n                                }\n                            }\n                        };\n                    }\n                }\n\n                e.Use();\n                menu.ShowAsContext();\n            }\n        }\n\n        void DrawTextureMipmapLimitGroupsElement(Rect rect, int index, bool isActive, bool isFocused)\n        {\n            rect.y += Styles.kTextureMipmapLimitGroupsOffsetTop; // Elements need to be manually centered due to the usage of Rects\n            Rect labelPosition = new Rect(rect.x, rect.y, EditorGUIUtility.labelWidth + Styles.kTextureMipmapLimitGroupsLabelWidthOffset, EditorGUI.lineHeight);\n            Rect optionsPosition = new Rect(rect.xMax - Styles.kTextureMipmapLimitGroupsOptionsWidth, rect.y, Styles.kTextureMipmapLimitGroupsOptionsWidth, rect.height);\n            Rect dropdownPosition = new Rect(labelPosition.xMax + Styles.kTextureMipmapLimitGroupsPaddingRight, rect.y,\n                rect.width - labelPosition.width - Styles.kTextureMipmapLimitGroupsPaddingRight - (optionsPosition.width + Styles.kTextureMipmapLimitGroupsPaddingRight), rect.height);\n\n            string groupName = m_TextureMipmapLimitGroupNamesProperty.GetArrayElementAtIndex(index).stringValue;\n            SerializedProperty groupSettingsProp = m_TextureMipmapLimitGroupSettingsProperty.GetArrayElementAtIndex(index);\n            bool isOffset = groupSettingsProp.FindPropertyRelative(\"limitBiasMode\").intValue == 0;\n            int mipmapLimit = groupSettingsProp.FindPropertyRelative(\"limitBias\").intValue;\n\n            DoTextureMipmapLimitGroupNameLabel(labelPosition, EditorGUIUtility.TempContent(groupName, L10n.Tr(\"Mipmap Limit Group\") + $\" {index}\"), index, groupName);\n            DoTextureMipmapLimitGroupsSettingsDropdown(dropdownPosition, isOffset, mipmapLimit, index, groupName);\n            DoTextureMipmapLimitGroupsOptions(optionsPosition, index, groupName);\n        }\n\n        void DrawTextureMipmapLimitGroupsFooter(Rect rect)\n        {\n            GUIContent toolbarPlus = ReorderableList.defaultBehaviours.iconToolbarPlus;\n            GUIContent toolbarMinus = ReorderableList.defaultBehaviours.iconToolbarMinus;\n\n            // Temporarily replace tooltips\n            ReorderableList.defaultBehaviours.iconToolbarPlus = Content.kTextureMipmapLimitGroupsAddButton;\n            ReorderableList.defaultBehaviours.iconToolbarMinus = Content.kTextureMipmapLimitGroupsRemoveButton;\n            ReorderableList.defaultBehaviours.DrawFooter(rect, m_TextureMipmapLimitGroupsList);\n            ReorderableList.defaultBehaviours.iconToolbarPlus = toolbarPlus;\n            ReorderableList.defaultBehaviours.iconToolbarMinus = toolbarMinus;\n        }\n\n        void DoTextureMipmapLimitGroupNameLabel(Rect rect, GUIContent label, int index, string groupName)\n        {\n            if (m_TextureMipmapLimitGroupBeingRenamed && index == m_TextureMipmapLimitGroupBeingRenamedIndex)\n            {\n                DoTextureMipmapLimitGroupNameTextField(rect, label);\n            }\n            else\n            {\n                GUI.Label(rect, label, EditorStyles.label);\n                Event e = Event.current;\n                if (rect.Contains(e.mousePosition) && e.type == EventType.ContextClick)\n                {\n                    ShowTextureMipmapLimitGroupsContextMenu(new Rect(e.mousePosition, Vector2.zero), Vector2.zero, index, groupName);\n                }\n            }\n        }\n\n        void DoTextureMipmapLimitGroupNameTextField(Rect rect, GUIContent label)\n        {\n            const string controlName = \"TextFieldTextureMipmapLimitGroup\";\n\n            GUI.SetNextControlName(controlName);\n            EditorGUI.DelayedTextField(rect, label.text, EditorStyles.textField);\n\n            Event e = Event.current;\n            if (m_TextureMipmapLimitGroupsTextFieldNeedsFocus)\n            {\n                if (e.type == EventType.Repaint) // Wait until all other events are out of the way\n                {\n                    EditorGUI.s_DelayedTextEditor.text = label.text; // Should already be the case, but just to make sure.\n                    EditorGUI.s_DelayedTextEditor.SelectAll();\n                    EditorGUI.FocusTextInControl(controlName);\n                    m_TextureMipmapLimitGroupsTextFieldNeedsFocus = false;\n                }\n            }\n            else\n            {\n                // If clicking out, the rename is NOT cancelled.\n                if (e.isMouse && !rect.Contains(e.mousePosition))\n                {\n                    EndRenamingTextureMipmapLimitGroup(EditorGUI.s_DelayedTextEditor.text);\n                }\n                // If editing stops or focus is lost, submit the current content of the text editor.\n                // Pressing ESC effectively cancels the rename. Pressing Enter, Tab or clicking away\n                // submits the user's new group name. (renaming is cancelled if the name didn't change)\n                else if (!EditorGUIUtility.editingTextField || GUI.GetNameOfFocusedControl() != controlName)\n                {\n                    // Cannot open a dialog box until a Repaint event if the user clicked away from the QualitySettingsEditor.\n                    if (e.type == EventType.Repaint)\n                    {\n                        EndRenamingTextureMipmapLimitGroup(EditorGUI.s_DelayedTextEditor.text);\n                        GUIUtility.ExitGUI(); // Prevents layout errors when clicking on certain other windows. (Hierarchy)\n                    }\n                    else\n                        GUI.InternalRepaintEditorWindow(); // Prevents missing controls when window doesn't repaint on its own.\n                }\n            }\n        }\n\n        void DoTextureMipmapLimitGroupsSettingsDropdown(Rect rect, bool isOffset, int mipmapLimit, int index, string groupName)\n        {\n            const int limitValueToItemsArrayIndexOffset = 3;\n            GUIContent content = (isOffset ? (mipmapLimit > -4 && mipmapLimit < 4) : (mipmapLimit >= 0 && mipmapLimit < 4)) // Is limit within array bounds?\n                ? (isOffset ? Content.kTextureMipmapLimitGroupsOffsetModeItems[mipmapLimit + limitValueToItemsArrayIndexOffset] : Content.kTextureMipmapLimitGroupsOverrideModeItems[mipmapLimit])\n                : EditorGUIUtility.TrTextContent($\"{(isOffset ? \"Offset\" : \"Override\")} Global Mipmap Limit: {((mipmapLimit >= 0) ? $\"+{mipmapLimit}\" : $\"{mipmapLimit}\")}\", \"Custom User Setting\");\n\n            if (EditorGUI.Button(rect, content, EditorStyles.popup))\n            {\n                m_TextureMipmapLimitGroupsList.index = index;\n\n                GenericMenu menu = new GenericMenu();\n                for (int j = 0; j < Content.kTextureMipmapLimitGroupsOffsetModeItems.Length; ++j)\n                {\n                    int limitValueFromItemsArrayIndex = j - limitValueToItemsArrayIndexOffset;\n                    menu.AddItem(Content.kTextureMipmapLimitGroupsOffsetModeItems[j], isOffset ? mipmapLimit == limitValueFromItemsArrayIndex : false,\n                        () => SetTextureMipmapLimitGroupSettings(index, limitValueFromItemsArrayIndex, TextureMipmapLimitBiasMode.OffsetGlobalLimit));\n                }\n                menu.AddSeparator(string.Empty);\n                for (int j = 0; j < Content.kTextureMipmapLimitGroupsOverrideModeItems.Length; ++j)\n                {\n                    int limit = j;\n                    menu.AddItem(Content.kTextureMipmapLimitGroupsOverrideModeItems[j], !isOffset ? mipmapLimit == limit : false,\n                        () => SetTextureMipmapLimitGroupSettings(index, limit, TextureMipmapLimitBiasMode.OverrideGlobalLimit));\n                }\n\n                menu.DropDown(rect);\n            }\n        }\n\n        void DoTextureMipmapLimitGroupsOptions(Rect rect, int index, string groupName)\n        {\n            if (EditorGUI.Button(rect, Content.kTextureMipmapLimitGroupsOptions, Styles.kTextureMipmapLimitGroupsOptionsButton))\n            {\n                m_TextureMipmapLimitGroupsList.index = index;\n                EndRenamingTextureMipmapLimitGroup();\n\n                ShowTextureMipmapLimitGroupsContextMenu(rect, Styles.kTextureMipmapLimitGroupsOptionsMenuOffset, index, groupName);\n            }\n        }\n\n        void ShowTextureMipmapLimitGroupsContextMenu(Rect rect, Vector2 offset, int index, string groupName)\n        {\n            GenericMenu menu = new GenericMenu();\n            menu.AddItem(Content.kTextureMipmapLimitGroupsOptionsIdentify, false, () => IdentifyAssetsUsingTextureMipmapLimitGroup(groupName));\n            menu.AddSeparator(string.Empty);\n            menu.AddItem(Content.kTextureMipmapLimitGroupsOptionsDuplicate, false, () => DuplicateTextureMipmapLimitGroup(index));\n            menu.AddItem(Content.kTextureMipmapLimitGroupsOptionsRename, false, () => StartRenamingTextureMipmapLimitGroup(index));\n            menu.DropDown(new Rect(rect.position + offset, Vector2.zero));\n        }\n\n        void AddTextureMipmapLimitGroup(ReorderableList list)\n        {\n            int newGroupIndex = (++m_TextureMipmapLimitGroupNamesProperty.arraySize) - 1;\n            string newGroupName = GetNewTextureMipmapLimitGroupName();\n            m_TextureMipmapLimitGroupNamesProperty.GetArrayElementAtIndex(newGroupIndex).stringValue = newGroupName;\n\n            // For all quality levels, we need to add default settings for the new group.\n            for (int i = 0; i < m_QualitySettingsProperty.arraySize; ++i)\n            {\n                SerializedProperty settingsArrProp = m_QualitySettingsProperty.GetArrayElementAtIndex(i).FindPropertyRelative(\"textureMipmapLimitSettings\");\n                settingsArrProp.arraySize++;\n                SerializedProperty settingsProp = settingsArrProp.GetArrayElementAtIndex(newGroupIndex);\n                settingsProp.FindPropertyRelative(\"limitBias\").intValue = 0;\n                settingsProp.FindPropertyRelative(\"limitBiasMode\").intValue = 0;\n            }\n\n            m_QualitySettings.ApplyModifiedProperties();\n            StartRenamingTextureMipmapLimitGroup(newGroupIndex, true);\n        }\n\n        void RemoveTextureMipmapLimitGroup(ReorderableList list)\n        {\n            int indexOfGroupToRemove = list.index;\n            string nameOfGroupToRemove = m_TextureMipmapLimitGroupNamesProperty.GetArrayElementAtIndex(indexOfGroupToRemove).stringValue;\n\n            bool isRemoveOperationCancelled = false;\n\n            if (!Presets.Preset.IsEditorTargetAPreset(target))\n            {\n                int selection = EditorUtility.DisplayDialogComplex(Content.kTextureMipmapLimitGroupsDialogTitleOnUpdate,\n                string.Format(Content.kTextureMipmapLimitGroupsDialogMessageOnRemove, GetShortTextureMipmapLimitGroupName(nameOfGroupToRemove)),\n                L10n.Tr(\"No\"), L10n.Tr(\"Cancel\"), L10n.Tr(\"Yes\"));\n\n                switch (selection)\n                {\n                    case 2: // Yes\n                        UpdateTextureAssetsLinkedToOldTextureMipmapLimitGroup(nameOfGroupToRemove, string.Empty);\n                        break;\n\n                    case 0: // No\n                        break;\n\n                    case 1: // Cancel\n                        isRemoveOperationCancelled = true;\n                        break;\n                }\n            }\n\n            if (!isRemoveOperationCancelled)\n            {\n                m_TextureMipmapLimitGroupNamesProperty.DeleteArrayElementAtIndex(indexOfGroupToRemove);\n\n                // For all quality levels, we need to remove the settings of the deleted group.\n                for (int i = 0; i < m_QualitySettingsProperty.arraySize; ++i)\n                {\n                    SerializedProperty settingsArrProp = m_QualitySettingsProperty.GetArrayElementAtIndex(i).FindPropertyRelative(\"textureMipmapLimitSettings\");\n                    settingsArrProp.DeleteArrayElementAtIndex(indexOfGroupToRemove);\n                }\n\n                m_QualitySettings.ApplyModifiedProperties();\n                m_TextureMipmapLimitGroupsList.m_Selection = new List<int>();\n                InspectorWindow.RepaintAllInspectors();\n            }\n\n            EndRenamingTextureMipmapLimitGroup();\n        }\n\n        void DuplicateTextureMipmapLimitGroup(int indexOfGroupToDuplicate)\n        {\n            int newGroupIndex = (++m_TextureMipmapLimitGroupNamesProperty.arraySize) - 1;\n            string newGroupName = GetNewTextureMipmapLimitGroupName();\n            m_TextureMipmapLimitGroupNamesProperty.GetArrayElementAtIndex(newGroupIndex).stringValue = newGroupName;\n\n            // For all quality levels, we need to duplicate the settings of the other group.\n            for (int i = 0; i < m_QualitySettingsProperty.arraySize; ++i)\n            {\n                SerializedProperty settingsArrProp = m_QualitySettingsProperty.GetArrayElementAtIndex(i).FindPropertyRelative(\"textureMipmapLimitSettings\");\n                settingsArrProp.arraySize++;\n\n                SerializedProperty newSettingsProp = settingsArrProp.GetArrayElementAtIndex(newGroupIndex);\n                SerializedProperty settingsPropToDuplicate = settingsArrProp.GetArrayElementAtIndex(indexOfGroupToDuplicate);\n                newSettingsProp.FindPropertyRelative(\"limitBias\").intValue = settingsPropToDuplicate.FindPropertyRelative(\"limitBias\").intValue;\n                newSettingsProp.FindPropertyRelative(\"limitBiasMode\").intValue = settingsPropToDuplicate.FindPropertyRelative(\"limitBiasMode\").intValue;\n            }\n\n            m_QualitySettings.ApplyModifiedProperties();\n            StartRenamingTextureMipmapLimitGroup(newGroupIndex, true);\n        }\n\n        void UpdateTextureAssetsLinkedToOldTextureMipmapLimitGroup(string oldName, string newName)\n        {\n            // If we operate on importers while they are selected, the user will still be prompted to confirm changes\n            // that they already agreed to. To avoid this: reset the selection, and restore it after we're done.\n            Object[] originalSelection = Selection.objects;\n\n            try\n            {\n                Selection.objects = null;\n\n                string[] guids = AssetDatabase.FindAssets(\"t:texture t:preset\");\n                AssetDatabase.StartAssetEditing();\n\n                for (int i = 0; i < guids.Length; ++i)\n                {\n                    string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]);\n                    Presets.Preset preset = AssetDatabase.LoadMainAssetAtPath(assetPath) as Presets.Preset;\n                    bool isPreset = preset is not null;\n                    AssetImporter importer = isPreset ? preset.GetReferenceObject() as AssetImporter : AssetImporter.GetAtPath(assetPath);\n\n                    if (importer is TextureImporter)\n                    {\n                        TextureImporter texImporter = importer as TextureImporter;\n                        bool supportsMipmapLimits = texImporter.textureShape == TextureImporterShape.Texture2D || texImporter.textureShape == TextureImporterShape.Texture2DArray;\n                        if (supportsMipmapLimits && texImporter.mipmapLimitGroupName == oldName)\n                        {\n                            texImporter.mipmapLimitGroupName = newName;\n                            if (!isPreset)\n                                importer.SaveAndReimport();\n                            else\n                            {\n                                preset.UpdateProperties(importer);\n                                AssetDatabase.ImportAsset(assetPath);\n                            }\n                        }\n                    }\n                    else if (importer is IHVImageFormatImporter)\n                    {\n                        IHVImageFormatImporter ihvImporter = importer as IHVImageFormatImporter;\n                        if (ihvImporter.mipmapLimitGroupName == oldName)\n                        {\n                            ihvImporter.mipmapLimitGroupName = newName;\n                            if (!isPreset)\n                                importer.SaveAndReimport();\n                            else\n                            {\n                                preset.UpdateProperties(importer);\n                                AssetDatabase.ImportAsset(assetPath);\n                            }\n                        }\n                    }\n                }\n            }\n            catch (System.Exception e)\n            {\n                EditorUtility.DisplayDialog(Content.kTextureMipmapLimitGroupsDialogTitleOnFailure,\n                    string.Format(Content.kTextureMipmapLimitGroupsDialogMessageOnUpdateAssetsError, e.Message),\n                    L10n.Tr(\"OK\"));\n            }\n            finally\n            {\n                AssetDatabase.StopAssetEditing();\n                Selection.objects = originalSelection;\n            }\n        }\n\n        // Acts on the current quality level\n        void SetTextureMipmapLimitGroupSettings(int groupIndex, int mipmapLimit, TextureMipmapLimitBiasMode mode)\n        {\n            SerializedProperty settingsToModify = m_TextureMipmapLimitGroupSettingsProperty.GetArrayElementAtIndex(groupIndex);\n\n            settingsToModify.FindPropertyRelative(\"limitBias\").intValue = mipmapLimit;\n            settingsToModify.FindPropertyRelative(\"limitBiasMode\").intValue = (int)mode;\n\n            m_QualitySettings.ApplyModifiedProperties();\n        }\n\n        void IdentifyAssetsUsingTextureMipmapLimitGroup(string groupNameToIdentify)\n        {\n            List<Object> newSelection = new List<Object>();\n            string[] guids = AssetDatabase.FindAssets(\"t:texture\");\n\n            for (int i = 0; i < guids.Length; ++i)\n            {\n                TextureImporter importer = AssetImporter.GetAtPath(AssetDatabase.GUIDToAssetPath(guids[i])) as TextureImporter;\n                if (importer is not null && (importer.textureShape == TextureImporterShape.Texture2D || importer.textureShape == TextureImporterShape.Texture2DArray) && importer.mipmapLimitGroupName == groupNameToIdentify)\n                {\n                    newSelection.Add(AssetDatabase.LoadAssetAtPath<Object>(importer.assetPath));\n                }\n            }\n\n            if (newSelection.Count > 0)\n            {\n                Selection.objects = newSelection.ToArray();\n            }\n            else\n            {\n                EditorUtility.DisplayDialog(Content.kTextureMipmapLimitGroupsDialogTitleOnFailure,\n                    string.Format(Content.kTextureMipmapLimitGroupsDialogMessageOnIdentifyFail, GetShortTextureMipmapLimitGroupName(groupNameToIdentify)),\n                    L10n.Tr(\"OK\"));\n            }\n        }\n\n        void StartRenamingTextureMipmapLimitGroup(int index, bool isNewGroup = false)\n        {\n            m_TextureMipmapLimitGroupsList.index = index;\n            m_TextureMipmapLimitGroupsTextFieldNeedsFocus = true;\n            m_TextureMipmapLimitGroupBeingRenamed = true;\n            m_TextureMipmapLimitGroupBeingRenamedIndex = index;\n            m_TextureMipmapLimitGroupsRenameShowUpdatePrompt = !Presets.Preset.IsEditorTargetAPreset(target) && !isNewGroup;\n\n            if (isNewGroup)\n            {\n                InspectorWindow.RepaintAllInspectors();\n            }\n        }\n\n        void EndRenamingTextureMipmapLimitGroup(string newName = \"\")\n        {\n            if (!m_TextureMipmapLimitGroupBeingRenamed)\n            {\n                return;\n            }\n            m_TextureMipmapLimitGroupBeingRenamed = false;\n\n            if (newName != string.Empty)\n            {\n                string toRename = m_TextureMipmapLimitGroupNamesProperty.GetArrayElementAtIndex(m_TextureMipmapLimitGroupBeingRenamedIndex).stringValue;\n                if (toRename == newName)\n                {\n                    return;\n                }\n\n                string shortNewName = GetShortTextureMipmapLimitGroupName(newName);\n                string shortToRename = GetShortTextureMipmapLimitGroupName(toRename);\n\n                for (int i = 0; i < m_TextureMipmapLimitGroupNamesProperty.arraySize; ++i)\n                {\n                    if (m_TextureMipmapLimitGroupNamesProperty.GetArrayElementAtIndex(i).stringValue == newName)\n                    {\n                        EditorUtility.DisplayDialog(Content.kTextureMipmapLimitGroupsDialogTitleOnFailure,\n                            string.Format(Content.kTextureMipmapLimitGroupsDialogMessageOnRenameFail, shortNewName, shortToRename),\n                            L10n.Tr(\"OK\"));\n                        return;\n                    }\n                }\n\n                bool applyModifiedProperties = true;\n                if (m_TextureMipmapLimitGroupsRenameShowUpdatePrompt)\n                {\n                    int selection = EditorUtility.DisplayDialogComplex(Content.kTextureMipmapLimitGroupsDialogTitleOnUpdate,\n                        string.Format(Content.kTextureMipmapLimitGroupsDialogMessageOnRename, shortToRename, shortNewName),\n                        L10n.Tr(\"No\"), L10n.Tr(\"Cancel\"), L10n.Tr(\"Yes\"));\n\n                    switch (selection)\n                    {\n                        case 2: // Yes\n                            UpdateTextureAssetsLinkedToOldTextureMipmapLimitGroup(toRename, newName);\n                            break;\n\n                        case 0: // No\n                            break;\n\n                        case 1: // Cancel\n                            applyModifiedProperties = false;\n                            break;\n                    }\n                }\n\n                if (applyModifiedProperties)\n                {\n                    m_TextureMipmapLimitGroupNamesProperty.GetArrayElementAtIndex(m_TextureMipmapLimitGroupBeingRenamedIndex).stringValue = newName;\n                    m_QualitySettings.ApplyModifiedProperties();\n                    InspectorWindow.RepaintAllInspectors();\n                }\n            }\n\n            m_TextureMipmapLimitGroupBeingRenamedIndex = -1;\n            GUI.FocusControl(string.Empty);\n        }\n\n        string GetNewTextureMipmapLimitGroupName()\n        {\n            string newName = L10n.Tr(\"New Group\");\n            string[] existingNames = GetAllKnownTextureMipmapLimitGroupNames();\n\n            int counter = 0;\n            while (existingNames.Any(existingName => existingName == newName))\n            {\n                newName = L10n.Tr(\"New Group\") + string.Format(\" ({0})\", ++counter);\n            }\n\n            return newName;\n        }\n\n        string[] GetAllKnownTextureMipmapLimitGroupNames()\n        {\n            string[] existingNames = new string[m_TextureMipmapLimitGroupNamesProperty.arraySize];\n            for (int i = 0; i < m_TextureMipmapLimitGroupNamesProperty.arraySize; ++i)\n            {\n                existingNames[i] = m_TextureMipmapLimitGroupNamesProperty.GetArrayElementAtIndex(i).stringValue;\n            }\n            return existingNames;\n        }\n\n        // Only meant to limit the length of various messages addressed to the user that concern mipmap limit groups.\n        // Don't use elsewhere.\n        string GetShortTextureMipmapLimitGroupName(string groupName)\n        {\n            const int maxGroupNameLength = 41;\n            // ^ Cannot fit more than this many characters on 1 line.\n            if (groupName.Length > maxGroupNameLength)\n            {\n                const string suffix = \" (...)\";\n                groupName = groupName.Substring(0, maxGroupNameLength - suffix.Length) + suffix;\n            }\n            return groupName;\n        }\n\n        [SettingsProvider]\n        internal static SettingsProvider CreateProjectSettingsProvider()\n        {\n            var provider = AssetSettingsProvider.CreateProviderFromAssetPath(\n                \"Project/Quality\", \"ProjectSettings/QualitySettings.asset\",\n                SettingsProvider.GetSearchKeywordsFromGUIContentProperties<Styles>()\n                    .Concat(SettingsProvider.GetSearchKeywordsFromGUIContentProperties<Content>())\n                    .Concat(SettingsProvider.GetSearchKeywordsFromPath(\"ProjectSettings/QualitySettings.asset\")));\n            return provider;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/RayTracingShaderInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(RayTracingShader))]\n    internal class RayTracingShaderInspector : Editor\n    {\n        SerializedProperty m_MaxRecursionDepth;\n\n        Vector2 m_ScrollPosition = Vector2.zero;\n\n        private class Styles\n        {\n            public GUIContent s_MaxRecursionDepthText = EditorGUIUtility.TrTextContent(\"Max. Recursion Depth\", \"Limit on ray recursion for the Ray Tracing pipeline. This is defined in the shader by using max_recursion_depth pragma(e.g. \\\"#pragma max_recursion_depth 5\\\"). Applications should pick a limit that is as low as absolutely necessary. A value of 1 means that only primary rays can be cast.\");\n            public GUIContent s_PlatformList = EditorGUIUtility.TrTextContent(\"Platforms:\");\n            public GUIContent s_NotSupported = EditorGUIUtility.TrTextContent(\"Ray Tracing Shader not supported! No graphics APIs with Ray Tracing support found in the graphics APIs list or the importing process failed.\");\n            public GUIContent s_Index = EditorGUIUtility.TrTextContent(\"Index\");\n            public GUIContent s_Name = EditorGUIUtility.TrTextContent(\"Name\");\n            public GUIContent s_PayloadSize = EditorGUIUtility.TrTextContent(\"Payload Size (Bytes)\");\n            public GUIContent s_ParamSize = EditorGUIUtility.TrTextContent(\"Param. Size (Bytes)\");\n            public GUIContent s_RayGenShaderNames = EditorGUIUtility.TrTextContent(\"Ray Generation Shaders\", \"The list of all ray generation shaders in the shader file. Only one ray generation shader can be executed at a time.\");\n            public GUIContent s_MissShaderNames = EditorGUIUtility.TrTextContent(\"Miss Shaders\", \"The list of all miss shaders in the shader file. The index of the miss shader to execute is specified when calling TraceRay HLSL function.\");\n            public GUIContent s_CallableShaderNames = EditorGUIUtility.TrTextContent(\"Callable Shaders\", \"The list of all callable shaders in the shader file. The index of the callable shader to execute is specified when calling CallShader HLSL function.\");\n            public GUIStyle s_LabelStyle = new GUIStyle(EditorStyles.boldLabel);\n            public Styles()\n            {\n                s_LabelStyle.richText = true;\n            }\n        }\n\n        static Styles styles;\n\n        static List<string> GetPlatformList(RayTracingShader rs)\n        {\n            var platformList = new List<string>();\n            var platformCount = ShaderUtil.GetRayTracingShaderPlatformCount(rs);\n            for (var i = 0; i < platformCount; ++i)\n            {\n                var platform = ShaderUtil.GetRayTracingShaderPlatformType(rs, i);\n                if (ShaderUtil.IsRayTracingShaderValidForPlatform(rs, platform))\n                    platformList.Add(platform.ToString());\n            }\n            return platformList;\n        }\n\n        private bool ShowPlatformListSection(RayTracingShader rs)\n        {\n            var platformList = GetPlatformList(rs);\n            if (platformList.Count != 0)\n            {\n                EditorGUI.indentLevel++;\n                GUILayout.Label(styles.s_PlatformList);\n                foreach (var p in platformList)\n                {\n                    EditorGUILayout.LabelField(p);\n                }\n                EditorGUI.indentLevel--;\n                return true;\n            }\n            return false;\n        }\n\n        public void OnEnable()\n        {\n            m_MaxRecursionDepth = serializedObject.FindProperty(\"m_MaxRecursionDepth\");\n        }\n\n        void ShowRayGenerationShaderList(string[] shaderNames)\n        {\n            GUILayout.BeginVertical(GUI.skin.box);\n\n            for (int i = 0; i < shaderNames.Length; ++i)\n            {\n                GUILayout.Label(shaderNames[i], EditorStyles.textArea);\n            }\n\n            GUILayout.EndVertical();\n        }\n\n        void ShowMissShaderList(string[] missShaderNames, int[] rayPayloadSize)\n        {\n            GUIStyle messageStyle = \"CN StatusInfo\";\n\n            float lineHeight = messageStyle.CalcHeight(EditorGUIUtility.TempContent(\"ShaderName\"), 100);\n\n            Rect rHeader = EditorGUILayout.GetControlRect(false, lineHeight);\n\n            Vector2 indexColumnSize = EditorStyles.boldLabel.CalcSize(styles.s_Index);\n            indexColumnSize.x += 15;\n            GUI.Label(rHeader, styles.s_Index, new GUIStyle(EditorStyles.boldLabel));\n\n            rHeader.xMin += indexColumnSize.x;\n            GUI.Label(rHeader, styles.s_Name, EditorStyles.boldLabel);\n\n            Vector2 payloadColumnSize = EditorStyles.boldLabel.CalcSize(styles.s_PayloadSize);\n\n            rHeader.xMin = rHeader.xMax - payloadColumnSize.x - 15;\n            GUI.Label(rHeader, styles.s_PayloadSize, EditorStyles.boldLabel);\n\n            GUILayout.BeginVertical(GUI.skin.box);\n\n            for (int i = 0; i < missShaderNames.Length; ++i)\n            {\n                Rect r = EditorGUILayout.GetControlRect(false, lineHeight);\n\n                GUI.Label(r, i.ToString(), EditorStyles.textArea);\n\n                r.xMin += indexColumnSize.x;\n                GUI.Label(r, missShaderNames[i], EditorStyles.textArea);\n\n                r.xMin = r.xMax - payloadColumnSize.x - 10;\n                GUI.Label(r, rayPayloadSize[i].ToString(), EditorStyles.textArea);\n            }\n\n            GUILayout.EndVertical();\n        }\n\n        void ShowCallableShaderList(string[] callableShaderNames, int[] paramSize)\n        {\n            GUIStyle messageStyle = \"CN StatusInfo\";\n\n            float lineHeight = messageStyle.CalcHeight(EditorGUIUtility.TempContent(\"ShaderName\"), 100);\n\n            Rect rHeader = EditorGUILayout.GetControlRect(false, lineHeight);\n\n            Vector2 indexColumnSize = EditorStyles.boldLabel.CalcSize(styles.s_Index);\n            indexColumnSize.x += 15;\n            GUI.Label(rHeader, styles.s_Index, EditorStyles.boldLabel);\n\n            rHeader.xMin += indexColumnSize.x;\n            GUI.Label(rHeader, styles.s_Name, EditorStyles.boldLabel);\n\n            Vector2 paramColumnSize = EditorStyles.boldLabel.CalcSize(styles.s_ParamSize);\n\n            rHeader.xMin = rHeader.xMax - paramColumnSize.x - 15;\n            GUI.Label(rHeader, styles.s_ParamSize, EditorStyles.boldLabel);\n\n            GUILayout.BeginVertical(GUI.skin.box);\n\n            for (int i = 0; i < callableShaderNames.Length; ++i)\n            {\n                Rect r = EditorGUILayout.GetControlRect(false, lineHeight);\n\n                GUI.Label(r, i.ToString(), EditorStyles.textArea);\n\n                r.xMin += indexColumnSize.x;\n                GUI.Label(r, callableShaderNames[i], EditorStyles.textArea);\n\n                r.xMin = r.xMax - paramColumnSize.x - 10;\n                GUI.Label(r, paramSize[i].ToString(), EditorStyles.textArea);\n            }\n\n            GUILayout.EndVertical();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (styles == null)\n                styles = new Styles();\n\n            var rts = target as RayTracingShader;\n            if (rts == null)\n                return;\n\n            serializedObject.Update();\n\n            GUI.enabled = true;\n\n            EditorGUI.indentLevel = 0;\n\n            if (ShowPlatformListSection(rts))\n            {\n                EditorGUILayout.Space();\n\n                EditorGUILayout.PropertyField(m_MaxRecursionDepth, styles.s_MaxRecursionDepthText);\n\n                int rayGenShaderCount = ShaderUtil.GetRayGenerationShaderCount(rts);\n                if (rayGenShaderCount > 0)\n                {\n                    GUILayout.Space(15.0f);\n                    GUILayout.Label(styles.s_RayGenShaderNames, styles.s_LabelStyle);\n\n                    string[] rayGenShaderNames = new string[rayGenShaderCount];\n                    for (int i = 0; i < rayGenShaderCount; i++)\n                        rayGenShaderNames[i] = ShaderUtil.GetRayGenerationShaderName(rts, i);\n\n                    ShowRayGenerationShaderList(rayGenShaderNames);\n                }\n\n                int missShaderCount = ShaderUtil.GetMissShaderCount(rts);\n                if (missShaderCount > 0)\n                {\n                    GUILayout.Space(15.0f);\n\n                    GUILayout.Label(styles.s_MissShaderNames, styles.s_LabelStyle);\n\n                    string[] missShaderNames = new string[missShaderCount];\n                    int[] missShaderPayloadSize = new int[missShaderCount];\n                    for (int i = 0; i < missShaderCount; i++)\n                    {\n                        missShaderNames[i] = ShaderUtil.GetMissShaderName(rts, i);\n                        missShaderPayloadSize[i] = ShaderUtil.GetMissShaderRayPayloadSize(rts, i);\n                    }\n\n                    ShowMissShaderList(missShaderNames, missShaderPayloadSize);\n                }\n\n                int callableShaderCount = ShaderUtil.GetCallableShaderCount(rts);\n                if (callableShaderCount > 0)\n                {\n                    GUILayout.Space(15.0f);\n\n                    GUILayout.Label(styles.s_CallableShaderNames, styles.s_LabelStyle);\n\n                    string[] callableShaderNames = new string[callableShaderCount];\n                    int[] callableShaderParamsSize = new int[callableShaderCount];\n                    for (int i = 0; i < callableShaderCount; i++)\n                    {\n                        callableShaderNames[i] = ShaderUtil.GetCallableShaderName(rts, i);\n                        callableShaderParamsSize[i] = ShaderUtil.GetCallableShaderParamSize(rts, i);\n                    }\n\n                    ShowCallableShaderList(callableShaderNames, callableShaderParamsSize);\n                }\n            }\n            else\n            {\n                EditorGUILayout.HelpBox(styles.s_NotSupported.text, MessageType.Error);\n            }\n\n            ShowShaderErrors(rts);\n        }\n\n        ShaderMessage[] m_ShaderMessages;\n        private void ShowShaderErrors(RayTracingShader s)\n        {\n            if (Event.current.type == EventType.Layout)\n            {\n                int n = ShaderUtil.GetRayTracingShaderMessageCount(s);\n                m_ShaderMessages = null;\n                if (n >= 1)\n                {\n                    m_ShaderMessages = ShaderUtil.GetRayTracingShaderMessages(s);\n                }\n            }\n\n            if (m_ShaderMessages == null)\n                return;\n            ShaderInspector.ShaderErrorListUI(s, m_ShaderMessages, ref m_ScrollPosition);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/RectHandles.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class RectHandles\n    {\n        static Styles s_Styles;\n        class Styles\n        {\n            public readonly GUIStyle dragdot = \"U2D.dragDot\";\n            public readonly GUIStyle pivotdot = \"U2D.pivotDot\";\n            public readonly GUIStyle dragdotactive = \"U2D.dragDotActive\";\n            public readonly GUIStyle pivotdotactive = \"U2D.pivotDotActive\";\n        }\n\n        private static int s_LastCursorId;\n\n        internal static bool RaycastGUIPointToWorldHit(Vector2 guiPoint, Plane plane, out Vector3 hit)\n        {\n            Ray ray = HandleUtility.GUIPointToWorldRay(guiPoint);\n            float dist = 0f;\n            bool isHit = plane.Raycast(ray, out dist);\n            hit = isHit ? ray.GetPoint(dist) : Vector3.zero;\n            return isHit;\n        }\n\n        internal static void DetectCursorChange(int id)\n        {\n            if (HandleUtility.nearestControl == id)\n            {\n                // Don't optimize this to only use event if s_LastCursorId wasn't already id.\n                // Cursor can sometimes change for the same handle.\n                s_LastCursorId = id;\n                Event.current.Use();\n            }\n            else if (s_LastCursorId == id)\n            {\n                s_LastCursorId = 0;\n                Event.current.Use();\n            }\n        }\n\n        internal static Vector3 SideSlider(int id, Vector3 position, Vector3 sideVector, Vector3 direction, float size, Handles.CapFunction capFunction, Vector2 snap)\n        {\n            return SideSlider(id, position, sideVector, direction, size, capFunction, snap, 0);\n        }\n\n        internal static Vector3 SideSlider(int id, Vector3 position, Vector3 sideVector, Vector3 direction, float size, Handles.CapFunction capFunction, Vector2 snap, float bias)\n        {\n            Event evt = Event.current;\n            Vector3 handleDir = Vector3.Cross(sideVector, direction).normalized;\n            Vector3 pos = Handles.Slider2D(id, position, handleDir, direction, sideVector, 0, capFunction, snap);\n            pos = position + Vector3.Project(pos - position, direction);\n\n            switch (evt.type)\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    Vector3 sideDir = sideVector.normalized;\n                    HandleUtility.AddControl(id, HandleUtility.DistanceToLine(position + sideVector * 0.5f - sideDir * size * 2, position - sideVector * 0.5f + sideDir * size * 2) - bias);\n\n                    if (evt.type == EventType.MouseMove)\n                        DetectCursorChange(id);\n                    break;\n\n                case EventType.Repaint:\n                    if ((HandleUtility.nearestControl == id && GUIUtility.hotControl == 0) || GUIUtility.hotControl == id)\n                        HandleDirectionalCursor(position, handleDir, direction);\n                    break;\n            }\n\n            return pos;\n        }\n\n        internal static Vector3 CornerSlider(int id, Vector3 cornerPos, Vector3 handleDir, Vector3 outwardsDir1, Vector3 outwardsDir2, float handleSize, Handles.CapFunction drawFunc, Vector2 snap)\n        {\n            Event evt = Event.current;\n            Vector3 pos = Handles.Slider2D(id, cornerPos, handleDir, outwardsDir1, outwardsDir2, handleSize, drawFunc, snap);\n\n            switch (evt.type)\n            {\n                case EventType.MouseMove:\n                    DetectCursorChange(id);\n                    break;\n\n                case EventType.Repaint:\n                    if ((HandleUtility.nearestControl == id && GUIUtility.hotControl == 0) || GUIUtility.hotControl == id)\n                        HandleDirectionalCursor(cornerPos, handleDir, outwardsDir1 + outwardsDir2);\n                    break;\n            }\n            return pos;\n        }\n\n        private static void HandleDirectionalCursor(Vector3 handlePosition, Vector3 handlePlaneNormal, Vector3 direction)\n        {\n            Vector2 mousePosition = Event.current.mousePosition;\n\n            // Find cursor direction (supports perspective camera)\n            Plane guiPlane = new Plane(handlePlaneNormal, handlePosition);\n            Vector3 mousePosWorld;\n            if (RaycastGUIPointToWorldHit(mousePosition, guiPlane, out mousePosWorld))\n            {\n                Vector2 cursorDir = WorldToScreenSpaceDir(mousePosWorld, direction);\n                // 200px x 200px rect around mousepos to switch cursor via fake cursorRect.\n                Rect mouseScreenRect = new Rect(mousePosition.x - 100f, mousePosition.y - 100f, 200f, 200f);\n                EditorGUIUtility.AddCursorRect(mouseScreenRect, GetScaleCursor(cursorDir));\n            }\n        }\n\n        public static float AngleAroundAxis(Vector3 dirA, Vector3 dirB, Vector3 axis)\n        {\n            // Project A and B onto the plane orthogonal target axis\n            dirA = Vector3.ProjectOnPlane(dirA, axis);\n            dirB = Vector3.ProjectOnPlane(dirB, axis);\n\n            // Find (positive) angle between A and B\n            float angle = Vector3.Angle(dirA, dirB);\n\n            // Return angle multiplied with 1 or -1\n            return angle * (Vector3.Dot(axis, Vector3.Cross(dirA, dirB)) < 0 ? -1 : 1);\n        }\n\n        public static float RotationSlider(int id, Vector3 cornerPos, float rotation, Vector3 pivot, Vector3 handleDir, Vector3 outwardsDir1, Vector3 outwardsDir2, float handleSize, Handles.CapFunction drawFunc, Vector2 snap)\n        {\n            Vector3 diagonal = (outwardsDir1 + outwardsDir2);\n            Vector2 screenCorner = HandleUtility.WorldToGUIPoint(cornerPos);\n            Vector2 screenOffset = HandleUtility.WorldToGUIPoint(cornerPos + diagonal) - screenCorner;\n            screenOffset = screenOffset.normalized * 15;\n            RaycastGUIPointToWorldHit(screenCorner + screenOffset, new Plane(handleDir, cornerPos), out cornerPos);\n\n            Event evt = Event.current;\n            Vector3 pos = Handles.Slider2D(id, cornerPos, handleDir, outwardsDir1, outwardsDir2, handleSize, drawFunc, Vector2.zero);\n\n            if (evt.type == EventType.MouseMove)\n                DetectCursorChange(id);\n\n            if (evt.type == EventType.Repaint)\n            {\n                if ((HandleUtility.nearestControl == id && GUIUtility.hotControl == 0) || GUIUtility.hotControl == id)\n                {\n                    Rect mouseScreenRect = new Rect(evt.mousePosition.x - 100f, evt.mousePosition.y - 100f, 200f, 200f);\n                    EditorGUIUtility.AddCursorRect(mouseScreenRect, MouseCursor.RotateArrow);\n                }\n            }\n\n            return rotation - AngleAroundAxis(pos - pivot, cornerPos - pivot, handleDir);\n        }\n\n        static Vector2 WorldToScreenSpaceDir(Vector3 worldPos, Vector3 worldDir)\n        {\n            Vector3 screenPos = HandleUtility.WorldToGUIPoint(worldPos);\n            Vector3 screenPosPlusDirection = HandleUtility.WorldToGUIPoint(worldPos + worldDir);\n            Vector2 screenSpaceDir = screenPosPlusDirection - screenPos;\n            screenSpaceDir.y *= -1;\n            return screenSpaceDir;\n        }\n\n        private static MouseCursor GetScaleCursor(Vector2 direction)\n        {\n            float angle = Mathf.Atan2(direction.x, direction.y) * Mathf.Rad2Deg;\n\n            if (angle < 0f)\n                angle = 360f + angle;\n\n            if (angle < 0f + 27.5f)\n                return MouseCursor.ResizeVertical;\n            if (angle < 45f + 27.5f)\n                return MouseCursor.ResizeUpRight;\n            if (angle < 90f + 27.5f)\n                return MouseCursor.ResizeHorizontal;\n            if (angle < 135f + 27.5f)\n                return MouseCursor.ResizeUpLeft;\n            if (angle < 180f + 27.5f)\n                return MouseCursor.ResizeVertical;\n            if (angle < 225f + 27.5f)\n                return MouseCursor.ResizeUpRight;\n            if (angle < 270f + 27.5f)\n                return MouseCursor.ResizeHorizontal;\n            if (angle < 315f + 27.5f)\n                return MouseCursor.ResizeUpLeft;\n            else\n                return MouseCursor.ResizeVertical;\n        }\n\n        public static void RectScalingHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            switch (eventType)\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    HandleUtility.AddControl(controlID, HandleUtility.DistanceToCircle(position, size * .5f));\n                    break;\n                case EventType.Repaint:\n                    DrawImageBasedCap(controlID, position, rotation, size, s_Styles.dragdot, s_Styles.dragdotactive);\n                    break;\n            }\n        }\n\n        public static void PivotHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            switch (eventType)\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    HandleUtility.AddControl(controlID, HandleUtility.DistanceToCircle(position, size * .5f));\n                    break;\n                case EventType.Repaint:\n                    DrawImageBasedCap(controlID, position, rotation, size, s_Styles.pivotdot, s_Styles.pivotdotactive);\n                    break;\n            }\n        }\n\n        static void DrawImageBasedCap(int controlID, Vector3 position, Quaternion rotation, float size, GUIStyle normal, GUIStyle active)\n        {\n            // Don't draw positions behind the camera\n            if (Camera.current && Vector3.Dot(position - Camera.current.transform.position, Camera.current.transform.forward) < 0)\n                return;\n\n            Vector3 screenPos = HandleUtility.WorldToGUIPoint(position);\n\n            Handles.BeginGUI();\n            float w = normal.fixedWidth;\n            float h = normal.fixedHeight;\n            Rect r = new Rect(screenPos.x - w / 2f, screenPos.y - h / 2f, w, h);\n            if (GUIUtility.hotControl == controlID)\n                active.Draw(r, GUIContent.none, controlID);\n            else\n                normal.Draw(r, GUIContent.none, controlID);\n\n            Handles.EndGUI();\n        }\n\n        public static void RenderRectWithShadow(bool active, params Vector3[] corners)\n        {\n            Vector3[] verts = new Vector3[] { corners[0], corners[1], corners[2], corners[3], corners[0] };\n\n            Color oldColor = Handles.color;\n            Handles.color = new Color(1f, 1f, 1f, active ? 1f : 0.5f);\n            DrawPolyLineWithShadow(new Color(0f, 0f, 0f, active ? 1f : 0.5f), new Vector2(1f, -1f), verts);\n            Handles.color = oldColor;\n        }\n\n        static Vector3[] s_TempVectors = new Vector3[0];\n        public static void DrawPolyLineWithShadow(Color shadowColor, Vector2 screenOffset, params Vector3[] points)\n        {\n            Camera cam = Camera.current;\n            if (!cam || Event.current.type != EventType.Repaint)\n                return;\n\n            if (s_TempVectors.Length != points.Length)\n                s_TempVectors = new Vector3[points.Length];\n\n            for (int i = 0; i < points.Length; i++)\n                s_TempVectors[i] = cam.ScreenToWorldPoint(cam.WorldToScreenPoint(points[i]) + (Vector3)screenOffset);\n\n            Color oldColor = Handles.color;\n\n            // shadow\n            shadowColor.a = shadowColor.a * oldColor.a;\n            Handles.color = shadowColor;\n            Handles.DrawPolyLine(s_TempVectors);\n\n            // line itself\n            Handles.color = oldColor;\n            Handles.DrawPolyLine(points);\n        }\n\n        public static void DrawDottedLineWithShadow(Color shadowColor, Vector2 screenOffset, Vector3 p1, Vector3 p2, float screenSpaceSize)\n        {\n            Camera cam = Camera.current;\n            if (!cam || Event.current.type != EventType.Repaint)\n                return;\n\n            Color oldColor = Handles.color;\n\n            // shadow\n            shadowColor.a = shadowColor.a * oldColor.a;\n            Handles.color = shadowColor;\n            Handles.DrawDottedLine(\n                cam.ScreenToWorldPoint(cam.WorldToScreenPoint(p1) + (Vector3)screenOffset),\n                cam.ScreenToWorldPoint(cam.WorldToScreenPoint(p2) + (Vector3)screenOffset), screenSpaceSize);\n\n            // line itself\n            Handles.color = oldColor;\n            Handles.DrawDottedLine(p1, p2, screenSpaceSize);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/RectTransformEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\nusing System.Linq;\nusing UnityEditor.AnimatedValues;\nusing System.Globalization;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(RectTransform))]\n    [CanEditMultipleObjects]\n    internal class RectTransformEditor : Editor\n    {\n        // Consts\n        // (Some are technically statics, but still have k prefix because they're not meant to be changed.)\n\n        private const string kShowAnchorPropsPrefName = \"RectTransformEditor.showAnchorProperties\";\n        private const string kLockRectPrefName = \"RectTransformEditor.lockRect\";\n\n        private static Vector2 kShadowOffset = new Vector2(1, -1);\n        private static Color kShadowColor = new Color(0, 0, 0, 0.5f);\n        private const float kDottedLineSize = 5f;\n        private static float kDropdownSize = 49;\n        private static Color kRectInParentSpaceColor = new Color(1, 1, 1, 0.4f);\n        private static Color kParentColor = new Color(1, 1, 1, 0.6f);\n        private static Color kSiblingColor = new Color(1, 1, 1, 0.2f);\n        private static Color kAnchorColor = new Color(1, 1, 1, 1);\n        private static Color kAnchorLineColor = new Color(1, 1, 1, 0.6f);\n        private static Vector3[] s_Corners = new Vector3[4];\n\n        // Statics\n\n        class Styles\n        {\n            public GUIStyle measuringLabelStyle = \"PreOverlayLabel\";\n\n            public GUIContent anchorsContent = EditorGUIUtility.TrTextContent(\"Anchors\");\n            public GUIContent anchorMinContent = EditorGUIUtility.TrTextContent(\"Min\", \"The normalized position in the parent rectangle that the lower left corner is anchored to.\");\n            public GUIContent anchorMaxContent = EditorGUIUtility.TrTextContent(\"Max\", \"The normalized position in the parent rectangle that the upper right corner is anchored to.\");\n            public GUIContent pivotContent = EditorGUIUtility.TrTextContent(\"Pivot\", \"The pivot point specified in normalized values between 0 and 1. The pivot point is the origin of this rectangle. Rotation and scaling are around this point.\");\n            public GUIContent transformScaleContent = EditorGUIUtility.TrTextContent(\"Scale\", \"The local scaling of this Game Object relative to the parent. This scales everything including image borders and text.\");\n            public GUIContent rawEditContent;\n            public GUIContent blueprintContent;\n\n            public Styles()\n            {\n                rawEditContent = EditorGUIUtility.IconContent(@\"RectTransformRaw\", \"|Raw edit mode. When enabled, editing pivot and anchor values will not counter-adjust the position and size of the rectangle in order to make it stay in place.\");\n                blueprintContent = EditorGUIUtility.IconContent(@\"RectTransformBlueprint\", \"|Blueprint mode. Edit RectTransforms as if they were not rotated and scaled. This enables snapping too.\");\n            }\n        }\n        static Styles s_Styles;\n        static Styles styles { get { if (s_Styles == null) { s_Styles = new Styles(); } return s_Styles; } }\n\n        private static int s_FoldoutHash = \"Foldout\".GetHashCode();\n        private static int s_FloatFieldHash = \"EditorTextField\".GetHashCode();\n        private static int s_ParentRectPreviewHandlesHash = \"ParentRectPreviewDragHandles\".GetHashCode();\n        private static GUIContent[] s_XYLabels = {new GUIContent(\"X\"), new GUIContent(\"Y\")};\n        private static GUIContent[] s_XYZLabels = {new GUIContent(\"X\"), new GUIContent(\"Y\"), new GUIContent(\"Z\")};\n        private static bool[] s_ScaleDisabledMask = new bool[3];\n\n        private static bool s_DragAnchorsTogether;\n        private static Vector2 s_StartDragAnchorMin;\n        private static Vector2 s_StartDragAnchorMax;\n\n        enum AnchorFusedState { None, All, Horizontal, Vertical }\n        private static AnchorFusedState s_AnchorFusedState = AnchorFusedState.None;\n\n        // Instance members\n\n        private SerializedProperty m_AnchorMin;\n        private SerializedProperty m_AnchorMax;\n        private SerializedProperty m_AnchoredPosition;\n        private SerializedProperty m_SizeDelta;\n        private SerializedProperty m_Pivot;\n\n        private SerializedProperty m_LocalPositionZ;\n        private SerializedProperty m_LocalScale;\n        private TransformRotationGUI m_RotationGUI;\n\n        private bool m_ShowLayoutOptions = false;\n        private bool m_RawEditMode = false;\n        private int m_TargetCount = 0;\n        ConstrainProportionsTransformScale m_ConstrainProportionsScale;\n        private bool isScaleDirty;\n\n        private Dictionary<int, AnimBool> m_KeyboardControlIDs = new Dictionary<int, AnimBool>();\n        private AnimatedValues.AnimBool m_ChangingAnchors = new AnimatedValues.AnimBool();\n        private AnimatedValues.AnimBool m_ChangingPivot = new AnimatedValues.AnimBool();\n        private AnimatedValues.AnimBool m_ChangingWidth = new AnimatedValues.AnimBool();\n        private AnimatedValues.AnimBool m_ChangingHeight = new AnimatedValues.AnimBool();\n        private AnimatedValues.AnimBool m_ChangingPosX = new AnimatedValues.AnimBool();\n        private AnimatedValues.AnimBool m_ChangingPosY = new AnimatedValues.AnimBool();\n        private AnimatedValues.AnimBool m_ChangingLeft = new AnimatedValues.AnimBool();\n        private AnimatedValues.AnimBool m_ChangingRight = new AnimatedValues.AnimBool();\n        private AnimatedValues.AnimBool m_ChangingTop = new AnimatedValues.AnimBool();\n        private AnimatedValues.AnimBool m_ChangingBottom = new AnimatedValues.AnimBool();\n\n        private delegate float FloatGetter(RectTransform rect);\n        private delegate void FloatSetter(RectTransform rect, float f);\n\n        void OnEnable()\n        {\n            m_AnchorMin = serializedObject.FindProperty(\"m_AnchorMin\");\n            m_AnchorMax = serializedObject.FindProperty(\"m_AnchorMax\");\n            m_AnchoredPosition = serializedObject.FindProperty(\"m_AnchoredPosition\");\n            m_SizeDelta = serializedObject.FindProperty(\"m_SizeDelta\");\n            m_Pivot = serializedObject.FindProperty(\"m_Pivot\");\n\n            m_TargetCount = targets.Length;\n            m_LocalPositionZ = serializedObject.FindProperty(\"m_LocalPosition.z\");\n            m_LocalScale = serializedObject.FindProperty(\"m_LocalScale\");\n            if (m_RotationGUI == null)\n                m_RotationGUI = new TransformRotationGUI();\n            m_RotationGUI.OnEnable(serializedObject.FindProperty(\"m_LocalRotation\"), EditorGUIUtility.TrTextContent(\"Rotation\"));\n\n            m_ConstrainProportionsScale = new ConstrainProportionsTransformScale(m_LocalScale.vector3Value);\n\n            m_ShowLayoutOptions = EditorPrefs.GetBool(kShowAnchorPropsPrefName, false);\n            m_RawEditMode = EditorPrefs.GetBool(kLockRectPrefName, false);\n\n            m_ChangingAnchors.valueChanged.AddListener(RepaintScene);\n            m_ChangingPivot.valueChanged.AddListener(RepaintScene);\n            m_ChangingWidth.valueChanged.AddListener(RepaintScene);\n            m_ChangingHeight.valueChanged.AddListener(RepaintScene);\n            m_ChangingPosX.valueChanged.AddListener(RepaintScene);\n            m_ChangingPosY.valueChanged.AddListener(RepaintScene);\n            m_ChangingLeft.valueChanged.AddListener(RepaintScene);\n            m_ChangingRight.valueChanged.AddListener(RepaintScene);\n            m_ChangingTop.valueChanged.AddListener(RepaintScene);\n            m_ChangingBottom.valueChanged.AddListener(RepaintScene);\n\n            ManipulationToolUtility.handleDragChange += HandleDragChange;\n            SceneView.duringSceneGui += DrawAnchorsOnSceneView;\n        }\n\n        void OnDisable()\n        {\n            m_ChangingAnchors.valueChanged.RemoveListener(RepaintScene);\n            m_ChangingPivot.valueChanged.RemoveListener(RepaintScene);\n            m_ChangingWidth.valueChanged.RemoveListener(RepaintScene);\n            m_ChangingHeight.valueChanged.RemoveListener(RepaintScene);\n            m_ChangingPosX.valueChanged.RemoveListener(RepaintScene);\n            m_ChangingPosY.valueChanged.RemoveListener(RepaintScene);\n            m_ChangingLeft.valueChanged.RemoveListener(RepaintScene);\n            m_ChangingRight.valueChanged.RemoveListener(RepaintScene);\n            m_ChangingTop.valueChanged.RemoveListener(RepaintScene);\n            m_ChangingBottom.valueChanged.RemoveListener(RepaintScene);\n\n            ManipulationToolUtility.handleDragChange -= HandleDragChange;\n            SceneView.duringSceneGui -= DrawAnchorsOnSceneView;\n\n            if (m_DropdownWindow != null && m_DropdownWindow.editorWindow != null)\n                m_DropdownWindow.editorWindow.Close();\n        }\n\n        void HandleDragChange(string handleName, bool dragging)\n        {\n            AnimatedValues.AnimBool animBool;\n            switch (handleName)\n            {\n                case RectTool.kChangingLeft: animBool = m_ChangingLeft; break;\n                case RectTool.kChangingRight: animBool = m_ChangingRight; break;\n                case RectTool.kChangingPosY: animBool = m_ChangingPosY; break;\n                case RectTool.kChangingWidth: animBool = m_ChangingWidth; break;\n                case RectTool.kChangingBottom: animBool = m_ChangingBottom; break;\n                case RectTool.kChangingTop: animBool = m_ChangingTop; break;\n                case RectTool.kChangingPosX: animBool = m_ChangingPosX; break;\n                case RectTool.kChangingHeight: animBool = m_ChangingHeight; break;\n                case RectTool.kChangingPivot: animBool = m_ChangingPivot; break;\n                default: animBool = null; break;\n            }\n            if (animBool != null)\n                animBool.target = dragging;\n        }\n\n        void DrawAnchorsOnSceneView(SceneView sceneView)\n        {\n            if (!target)\n                return;\n\n            if (!sceneView.drawGizmos || !EditorGUIUtility.IsGizmosAllowedForObject(target))\n                return;\n\n            if (SceneView.activeEditors.Contains(this) || SceneView.activeEditors.Contains(target))\n                return;\n\n            RectTransform gui = target as RectTransform;\n            Transform ownSpace = gui.transform;\n            Transform parentSpace = ownSpace;\n            RectTransform guiParent = null;\n\n            if (ownSpace.parent != null)\n            {\n                parentSpace = ownSpace.parent;\n                guiParent = parentSpace.GetComponent<RectTransform>();\n            }\n\n            if (m_TargetCount == 1)\n                if (guiParent != null)\n                    AllAnchorsSceneGUI(gui, guiParent, parentSpace, ownSpace);\n        }\n\n        void SetFadingBasedOnMouseDownUp(ref AnimatedValues.AnimBool animBool, Event eventBefore)\n        {\n            if (eventBefore.type == EventType.MouseDrag && Event.current.type != EventType.MouseDrag)\n                animBool.value = true;\n            else if (eventBefore.type == EventType.MouseUp && Event.current.type != EventType.MouseUp)\n                animBool.target = false;\n        }\n\n        void SetFadingBasedOnControlID(ref AnimatedValues.AnimBool animBool, int id)\n        {\n            GUIView focusedView = (EditorWindow.focusedWindow == null ? null : EditorWindow.focusedWindow.m_Parent);\n            if (GUIUtility.keyboardControl == id && GUIView.current == focusedView)\n            {\n                animBool.value = true;\n                m_KeyboardControlIDs[id] = animBool;\n            }\n            else if ((GUIUtility.keyboardControl != id || GUIView.current != focusedView) && m_KeyboardControlIDs.ContainsKey(id))\n            {\n                m_KeyboardControlIDs.Remove(id);\n                if (!m_KeyboardControlIDs.ContainsValue(animBool))\n                    animBool.target = false;\n            }\n        }\n\n        void RepaintScene()\n        {\n            SceneView.RepaintAll();\n        }\n\n        private static bool ShouldDoIntSnapping(RectTransform rect)\n        {\n            Canvas canvas = rect.gameObject.GetComponentInParent<Canvas>();\n            return (canvas != null && canvas.renderMode != RenderMode.WorldSpace);\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (!EditorGUIUtility.wideMode)\n            {\n                EditorGUIUtility.wideMode = true;\n                EditorGUIUtility.labelWidth = EditorGUIUtility.currentViewWidth - 212;\n            }\n\n            serializedObject.Update();\n\n            bool anyDriven = false;\n            bool anyDrivenXPositionOrSize = false;\n            bool anyDrivenYPositionOrSize = false;\n            bool anyWithoutParent = false;\n            foreach (RectTransform gui in targets)\n            {\n                if (gui.drivenByObject != null)\n                {\n                    anyDriven = true;\n                    if ((gui.drivenProperties & (DrivenTransformProperties.AnchoredPositionX | DrivenTransformProperties.SizeDeltaX)) != 0)\n                        anyDrivenXPositionOrSize = true;\n                    if ((gui.drivenProperties & (DrivenTransformProperties.AnchoredPositionY | DrivenTransformProperties.SizeDeltaY)) != 0)\n                        anyDrivenYPositionOrSize = true;\n                }\n\n                if ((gui.transform.parent == null || gui.transform.parent.GetComponent<RectTransform>() == null)\n                    && (!PrefabUtility.IsPartOfPrefabAsset(gui.gameObject)))\n                    anyWithoutParent = true;\n            }\n\n            if (anyDriven)\n            {\n                if (targets.Length == 1)\n                    EditorGUILayout.HelpBox(\"Some values driven by \" + (target as RectTransform).drivenByObject.GetType().Name + \".\", MessageType.None);\n                else\n                    EditorGUILayout.HelpBox(\"Some values in some or all objects are driven.\", MessageType.None);\n            }\n\n            LayoutDropdownButton(anyWithoutParent);\n\n            // Position and Size Delta\n            SmartPositionAndSizeFields(anyWithoutParent, anyDrivenXPositionOrSize, anyDrivenYPositionOrSize);\n\n            // Anchor and pivot fields\n            SmartAnchorFields();\n            SmartPivotField();\n\n            EditorGUILayout.Space();\n\n            // Rotation\n            m_RotationGUI.RotationField(targets.Any(x => ((x as RectTransform).drivenProperties & DrivenTransformProperties.Rotation) != 0));\n\n            // Scale\n            s_ScaleDisabledMask[0] = targets.Any(x => ((x as RectTransform).drivenProperties & DrivenTransformProperties.ScaleX) != 0);\n            s_ScaleDisabledMask[1] = targets.Any(x => ((x as RectTransform).drivenProperties & DrivenTransformProperties.ScaleY) != 0);\n            s_ScaleDisabledMask[2] = targets.Any(x => ((x as RectTransform).drivenProperties & DrivenTransformProperties.ScaleZ) != 0);\n\n            Transform t = target as Transform;\n            if (t != null)\n            {\n                if (m_ConstrainProportionsScale.Initialize(serializedObject.targetObjects) && !s_ScaleDisabledMask.All(x => x))\n                {\n                    //AxisModified values [-1;2] : [none, x, y, z]\n                    int axisModified = -1;\n                    var mixedFields = ConstrainProportionsTransformScale.GetMixedValueFields(m_LocalScale);\n                    Vector3 scale = m_ConstrainProportionsScale.DoGUI(EditorGUILayout.GetControlRect(), styles.transformScaleContent, m_LocalScale.vector3Value, serializedObject.targetObjects, ref axisModified, m_LocalScale);\n                    var mixedFieldsAfterGUI = ConstrainProportionsTransformScale.GetMixedValueFields(m_LocalScale);\n\n                    if (scale != m_LocalScale.vector3Value || mixedFields != mixedFieldsAfterGUI)\n                    {\n                        if (serializedObject.targetObjectsCount > 1)\n                        {\n                            if (mixedFields != mixedFieldsAfterGUI)\n                            {\n                                axisModified = -1;\n                                for (int i = 0; i < 3; i++)\n                                {\n                                    if (ConstrainProportionsTransformScale.IsBit(mixedFields, i) && !ConstrainProportionsTransformScale.IsBit(mixedFieldsAfterGUI, i))\n                                    {\n                                        axisModified = i;\n                                        break;\n                                    }\n                                }\n                            }\n\n                            if (axisModified != -1)\n                            {\n                                isScaleDirty = ConstrainProportionsTransformScale.HandleMultiSelectionScaleChanges(\n                                    m_LocalScale.vector3Value, scale,\n                                    m_ConstrainProportionsScale.constrainProportionsScale,\n                                    serializedObject.targetObjects, ref axisModified);\n                            }\n                        }\n\n                        if (scale != m_LocalScale.vector3Value)\n                            m_LocalScale.vector3Value = scale;\n                    }\n                }\n                else\n                {\n                    Vector3FieldWithDisabledMash(EditorGUILayout.GetControlRect(), m_LocalScale, styles.transformScaleContent, s_ScaleDisabledMask);\n                }\n            }\n\n            if (isScaleDirty)\n                serializedObject.Update();\n\n            serializedObject.ApplyModifiedProperties();\n\n            if (isScaleDirty)\n            {\n                isScaleDirty = false;\n                OnForceReloadInspector();\n            }\n        }\n\n        // A Vector3 field where each of the x, y and z elements can be disabled.\n        static void Vector3FieldWithDisabledMash(Rect position, SerializedProperty property, GUIContent label, bool[] disabledMask)\n        {\n            EditorGUI.BeginProperty(position, label, property);\n\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position);\n            position = EditorGUI.MultiFieldPrefixLabel(position, id, label, 3);\n            position.height = EditorGUIUtility.singleLineHeight;\n            SerializedProperty cur = property.Copy();\n            cur.NextVisible(true);\n            EditorGUI.MultiPropertyFieldInternal(position, s_XYZLabels, cur, EditorGUI.PropertyVisibility.OnlyVisible, disabledMask);\n\n            EditorGUI.EndProperty();\n        }\n\n        private LayoutDropdownWindow m_DropdownWindow;\n        void LayoutDropdownButton(bool anyWithoutParent)\n        {\n            Rect dropdownPosition = GUILayoutUtility.GetRect(0, 0);\n            dropdownPosition.x += 2;\n            dropdownPosition.y += 17;\n            dropdownPosition.height = kDropdownSize;\n            dropdownPosition.width = kDropdownSize;\n\n            using (new EditorGUI.DisabledScope(anyWithoutParent))\n            {\n                if (EditorGUI.DropdownButton(dropdownPosition, GUIContent.none, FocusType.Passive, \"label\"))\n                {\n                    GUIUtility.keyboardControl = 0;\n                    m_DropdownWindow = new LayoutDropdownWindow(serializedObject);\n                    PopupWindow.Show(dropdownPosition, m_DropdownWindow);\n                }\n            }\n\n            if (!anyWithoutParent)\n            {\n                LayoutDropdownWindow.DrawLayoutMode(new RectOffset(7, 7, 7, 7).Remove(dropdownPosition), m_AnchorMin, m_AnchorMax, m_AnchoredPosition, m_SizeDelta);\n                LayoutDropdownWindow.DrawLayoutModeHeadersOutsideRect(dropdownPosition, m_AnchorMin, m_AnchorMax, m_AnchoredPosition, m_SizeDelta);\n            }\n        }\n\n        void SmartPositionAndSizeFields(bool anyWithoutParent, bool anyDrivenX, bool anyDrivenY)\n        {\n            Rect rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 4);\n\n            rect.height = EditorGUIUtility.singleLineHeight * 2;\n            Rect rect2;\n\n            bool anyStretchX = targets.Any(x => (x as RectTransform).anchorMin.x != (x as RectTransform).anchorMax.x);\n            bool anyStretchY = targets.Any(x => (x as RectTransform).anchorMin.y != (x as RectTransform).anchorMax.y);\n            bool anyNonStretchX = targets.Any(x => (x as RectTransform).anchorMin.x == (x as RectTransform).anchorMax.x);\n            bool anyNonStretchY = targets.Any(x => (x as RectTransform).anchorMin.y == (x as RectTransform).anchorMax.y);\n\n            rect2 = GetColumnRect(rect, 0);\n            if (anyNonStretchX || anyWithoutParent || anyDrivenX)\n            {\n                EditorGUI.BeginProperty(rect2, null, m_AnchoredPosition.FindPropertyRelative(\"x\"));\n                FloatFieldLabelAbove(rect2,\n                    rectTransform => rectTransform.anchoredPosition.x,\n                    (rectTransform, val) => rectTransform.anchoredPosition = new Vector2(val, rectTransform.anchoredPosition.y),\n                    DrivenTransformProperties.AnchoredPositionX,\n                    EditorGUIUtility.TrTextContent(\"Pos X\"));\n                SetFadingBasedOnControlID(ref m_ChangingPosX, EditorGUIUtility.s_LastControlID);\n                EditorGUI.EndProperty();\n            }\n            else\n            {\n                // Affected by both anchored position and size delta so do property handling for both. (E.g. showing animated value, prefab override etc.)\n                EditorGUI.BeginProperty(rect2, null, m_AnchoredPosition.FindPropertyRelative(\"x\"));\n                EditorGUI.BeginProperty(rect2, null, m_SizeDelta.FindPropertyRelative(\"x\"));\n                FloatFieldLabelAbove(rect2,\n                    rectTransform => rectTransform.offsetMin.x,\n                    (rectTransform, val) => rectTransform.offsetMin = new Vector2(val, rectTransform.offsetMin.y),\n                    DrivenTransformProperties.None,\n                    EditorGUIUtility.TrTextContent(\"Left\"));\n                SetFadingBasedOnControlID(ref m_ChangingLeft, EditorGUIUtility.s_LastControlID);\n                EditorGUI.EndProperty();\n                EditorGUI.EndProperty();\n            }\n\n            rect2 = GetColumnRect(rect, 1);\n            if (anyNonStretchY || anyWithoutParent || anyDrivenY)\n            {\n                EditorGUI.BeginProperty(rect2, null, m_AnchoredPosition.FindPropertyRelative(\"y\"));\n                FloatFieldLabelAbove(rect2,\n                    rectTransform => rectTransform.anchoredPosition.y,\n                    (rectTransform, val) => rectTransform.anchoredPosition = new Vector2(rectTransform.anchoredPosition.x, val),\n                    DrivenTransformProperties.AnchoredPositionY,\n                    EditorGUIUtility.TrTextContent(\"Pos Y\"));\n                SetFadingBasedOnControlID(ref m_ChangingPosY, EditorGUIUtility.s_LastControlID);\n                EditorGUI.EndProperty();\n            }\n            else\n            {\n                // Affected by both anchored position and size delta so do property handling for both. (E.g. showing animated value, prefab override etc.)\n                EditorGUI.BeginProperty(rect2, null, m_AnchoredPosition.FindPropertyRelative(\"y\"));\n                EditorGUI.BeginProperty(rect2, null, m_SizeDelta.FindPropertyRelative(\"y\"));\n                FloatFieldLabelAbove(rect2,\n                    rectTransform => - rectTransform.offsetMax.y,\n                    (rectTransform, val) => rectTransform.offsetMax = new Vector2(rectTransform.offsetMax.x, -val),\n                    DrivenTransformProperties.None,\n                    EditorGUIUtility.TrTextContent(\"Top\"));\n                SetFadingBasedOnControlID(ref m_ChangingTop, EditorGUIUtility.s_LastControlID);\n                EditorGUI.EndProperty();\n                EditorGUI.EndProperty();\n            }\n\n            rect2 = GetColumnRect(rect, 2);\n            EditorGUI.BeginProperty(rect2, null, m_LocalPositionZ);\n            FloatFieldLabelAbove(rect2,\n                rectTransform => rectTransform.transform.localPosition.z,\n                (rectTransform, val) => rectTransform.transform.localPosition = new Vector3(rectTransform.transform.localPosition.x, rectTransform.transform.localPosition.y, val),\n                DrivenTransformProperties.AnchoredPositionZ,\n                EditorGUIUtility.TrTextContent(\"Pos Z\"));\n            EditorGUI.EndProperty();\n\n            rect.y += EditorGUIUtility.singleLineHeight * 2;\n\n            rect2 = GetColumnRect(rect, 0);\n            if (anyNonStretchX || anyWithoutParent || anyDrivenX)\n            {\n                EditorGUI.BeginProperty(rect2, null, m_SizeDelta.FindPropertyRelative(\"x\"));\n                FloatFieldLabelAbove(rect2,\n                    rectTransform => rectTransform.sizeDelta.x,\n                    (rectTransform, val) => rectTransform.sizeDelta = new Vector2(val, rectTransform.sizeDelta.y),\n                    DrivenTransformProperties.SizeDeltaX,\n                    anyStretchX ? EditorGUIUtility.TrTextContent(\"W Delta\") : EditorGUIUtility.TrTextContent(\"Width\"));\n                SetFadingBasedOnControlID(ref m_ChangingWidth, EditorGUIUtility.s_LastControlID);\n                EditorGUI.EndProperty();\n            }\n            else\n            {\n                // Affected by both anchored position and size delta so do property handling for both. (E.g. showing animated value, prefab override etc.)\n                EditorGUI.BeginProperty(rect2, null, m_AnchoredPosition.FindPropertyRelative(\"x\"));\n                EditorGUI.BeginProperty(rect2, null, m_SizeDelta.FindPropertyRelative(\"x\"));\n                FloatFieldLabelAbove(rect2,\n                    rectTransform => - rectTransform.offsetMax.x,\n                    (rectTransform, val) => rectTransform.offsetMax = new Vector2(-val, rectTransform.offsetMax.y),\n                    DrivenTransformProperties.None,\n                    EditorGUIUtility.TrTextContent(\"Right\"));\n                SetFadingBasedOnControlID(ref m_ChangingRight, EditorGUIUtility.s_LastControlID);\n                EditorGUI.EndProperty();\n                EditorGUI.EndProperty();\n            }\n\n            rect2 = GetColumnRect(rect, 1);\n            if (anyNonStretchY || anyWithoutParent || anyDrivenY)\n            {\n                EditorGUI.BeginProperty(rect2, null, m_SizeDelta.FindPropertyRelative(\"y\"));\n                FloatFieldLabelAbove(rect2,\n                    rectTransform => rectTransform.sizeDelta.y,\n                    (rectTransform, val) => rectTransform.sizeDelta = new Vector2(rectTransform.sizeDelta.x, val),\n                    DrivenTransformProperties.SizeDeltaY,\n                    anyStretchY ? EditorGUIUtility.TrTextContent(\"H Delta\") : EditorGUIUtility.TrTextContent(\"Height\"));\n                SetFadingBasedOnControlID(ref m_ChangingHeight, EditorGUIUtility.s_LastControlID);\n                EditorGUI.EndProperty();\n            }\n            else\n            {\n                // Affected by both anchored position and size delta so do property handling for both. (E.g. showing animated value, prefab override etc.)\n                EditorGUI.BeginProperty(rect2, null, m_AnchoredPosition.FindPropertyRelative(\"y\"));\n                EditorGUI.BeginProperty(rect2, null, m_SizeDelta.FindPropertyRelative(\"y\"));\n                FloatFieldLabelAbove(rect2,\n                    rectTransform => rectTransform.offsetMin.y,\n                    (rectTransform, val) => rectTransform.offsetMin = new Vector2(rectTransform.offsetMin.x, val),\n                    DrivenTransformProperties.None,\n                    EditorGUIUtility.TrTextContent(\"Bottom\"));\n                SetFadingBasedOnControlID(ref m_ChangingBottom, EditorGUIUtility.s_LastControlID);\n                EditorGUI.EndProperty();\n                EditorGUI.EndProperty();\n            }\n\n            rect2 = rect;\n            rect2.height = EditorGUIUtility.singleLineHeight;\n            rect2.y += EditorGUIUtility.singleLineHeight;\n            rect2.yMin -= 2;\n            rect2.xMin = rect2.xMax - 26;\n            rect2.x -= rect2.width;\n            BlueprintButton(rect2);\n\n            rect2.x += rect2.width;\n            RawButton(rect2);\n        }\n\n        void SmartAnchorFields()\n        {\n            Rect anchorRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * (m_ShowLayoutOptions ? 3 : 1));\n            anchorRect.height = EditorGUIUtility.singleLineHeight;\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.BeginProperty(anchorRect, null, m_AnchorMin);\n            EditorGUI.BeginProperty(anchorRect, null, m_AnchorMax);\n            m_ShowLayoutOptions = EditorGUI.Foldout(anchorRect, m_ShowLayoutOptions, styles.anchorsContent, true);\n            EditorGUI.EndProperty();\n            EditorGUI.EndProperty();\n            if (EditorGUI.EndChangeCheck())\n                EditorPrefs.SetBool(kShowAnchorPropsPrefName, m_ShowLayoutOptions);\n\n            if (!m_ShowLayoutOptions)\n                return;\n\n            EditorGUI.indentLevel++;\n\n            anchorRect.y += EditorGUIUtility.singleLineHeight;\n            Vector2Field(anchorRect,\n                rectTransform => rectTransform.anchorMin.x,\n                (rectTransform, val) => SetAnchorSmart(rectTransform, val, 0, false, !m_RawEditMode, true),\n                rectTransform => rectTransform.anchorMin.y,\n                (rectTransform, val) => SetAnchorSmart(rectTransform, val, 1, false, !m_RawEditMode, true),\n                DrivenTransformProperties.AnchorMinX,\n                DrivenTransformProperties.AnchorMinY,\n                m_AnchorMin,\n                styles.anchorMinContent);\n\n            EditorGUILayout.Space(EditorGUI.kVerticalSpacingMultiField);\n\n            anchorRect.y += EditorGUIUtility.singleLineHeight + EditorGUI.kVerticalSpacingMultiField;\n            Vector2Field(anchorRect,\n                rectTransform => rectTransform.anchorMax.x,\n                (rectTransform, val) => SetAnchorSmart(rectTransform, val, 0, true, !m_RawEditMode, true),\n                rectTransform => rectTransform.anchorMax.y,\n                (rectTransform, val) => SetAnchorSmart(rectTransform, val, 1, true, !m_RawEditMode, true),\n                DrivenTransformProperties.AnchorMaxX,\n                DrivenTransformProperties.AnchorMaxY,\n                m_AnchorMax,\n                styles.anchorMaxContent);\n\n            EditorGUI.indentLevel--;\n        }\n\n        void SmartPivotField()\n        {\n            Vector2Field(EditorGUILayout.GetControlRect(),\n                rectTransform => rectTransform.pivot.x,\n                (rectTransform, val) => SetPivotSmart(rectTransform, val, 0, !m_RawEditMode, false),\n                rectTransform => rectTransform.pivot.y,\n                (rectTransform, val) => SetPivotSmart(rectTransform, val, 1, !m_RawEditMode, false),\n                DrivenTransformProperties.PivotX,\n                DrivenTransformProperties.PivotY,\n                m_Pivot,\n                styles.pivotContent);\n        }\n\n        void RawButton(Rect position)\n        {\n            EditorGUI.BeginChangeCheck();\n            m_RawEditMode = GUI.Toggle(position, m_RawEditMode, styles.rawEditContent, \"ButtonRight\");\n            if (EditorGUI.EndChangeCheck())\n                EditorPrefs.SetBool(kLockRectPrefName, m_RawEditMode);\n        }\n\n        void BlueprintButton(Rect position)\n        {\n            EditorGUI.BeginChangeCheck();\n            bool newValue = GUI.Toggle(position, Tools.rectBlueprintMode, styles.blueprintContent, \"ButtonLeft\");\n            if (EditorGUI.EndChangeCheck())\n            {\n                Tools.rectBlueprintMode = newValue;\n                Tools.RepaintAllToolViews();\n            }\n        }\n\n        void FloatFieldLabelAbove(Rect position, FloatGetter getter, FloatSetter setter, DrivenTransformProperties driven, GUIContent label)\n        {\n            using (new EditorGUI.DisabledScope(targets.Any(x => ((x as RectTransform).drivenProperties & driven) != 0)))\n            {\n                float value = getter(target as RectTransform);\n                EditorGUI.showMixedValue = targets.Select(x => getter(x as RectTransform)).Distinct().Count() >= 2;\n\n                EditorGUI.BeginChangeCheck();\n\n                int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position);\n                Rect positionLabel = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);\n                Rect positionField = new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight, position.width, EditorGUIUtility.singleLineHeight);\n                EditorGUI.HandlePrefixLabel(position, positionLabel, label, id);\n                float newValue = EditorGUI.DoFloatField(EditorGUI.s_DelayedTextEditor, positionField, positionLabel, id, value, EditorGUI.kFloatFieldFormatString, EditorStyles.textField, true);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    Undo.RecordObjects(targets, \"Modified RectTransform Values\");\n                    foreach (RectTransform tr in targets)\n                        setter(tr, newValue);\n                }\n            }\n        }\n\n        void Vector2Field(Rect position,\n            FloatGetter xGetter, FloatSetter xSetter,\n            FloatGetter yGetter, FloatSetter ySetter,\n            DrivenTransformProperties xDriven, DrivenTransformProperties yDriven,\n            SerializedProperty vec2Property, GUIContent label)\n        {\n            EditorGUI.BeginProperty(position, label, vec2Property);\n\n            SerializedProperty xProperty = vec2Property.FindPropertyRelative(\"x\");\n            SerializedProperty yProperty = vec2Property.FindPropertyRelative(\"y\");\n\n            int id = GUIUtility.GetControlID(label.GetHashCode(), FocusType.Keyboard, position);\n            EditorGUI.PrefixLabel(position, id, label);\n            float t = EditorGUIUtility.labelWidth;\n            int l = EditorGUI.indentLevel;\n            Rect r0 = GetColumnRect(position, 0);\n            Rect r1 = GetColumnRect(position, 1);\n            EditorGUIUtility.labelWidth = EditorGUI.CalcPrefixLabelWidth(s_XYLabels[0]);\n            EditorGUI.indentLevel = 0;\n\n            EditorGUI.BeginProperty(r0, s_XYLabels[0], xProperty);\n            FloatField(r0, xGetter, xSetter, xDriven, s_XYLabels[0]);\n            EditorGUI.EndProperty();\n\n            EditorGUI.BeginProperty(r0, s_XYLabels[1], yProperty);\n            FloatField(r1, yGetter, ySetter, yDriven, s_XYLabels[1]);\n            EditorGUI.EndProperty();\n\n            EditorGUIUtility.labelWidth = t;\n            EditorGUI.indentLevel = l;\n\n            EditorGUI.EndProperty();\n        }\n\n        void FloatField(Rect position, FloatGetter getter, FloatSetter setter, DrivenTransformProperties driven, GUIContent label)\n        {\n            using (new EditorGUI.DisabledScope(targets.Any(x => ((x as RectTransform).drivenProperties & driven) != 0)))\n            {\n                float value = getter(target as RectTransform);\n                EditorGUI.showMixedValue = targets.Select(x => getter(x as RectTransform)).Distinct().Count() >= 2;\n\n                EditorGUI.BeginChangeCheck();\n                float newValue = EditorGUI.FloatField(position, label, value);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    Undo.RecordObjects(targets, \"Modified RectTransform Values\");\n                    foreach (RectTransform tr in targets)\n                        setter(tr, newValue);\n                }\n            }\n        }\n\n        Rect GetColumnRect(Rect totalRect, int column)\n        {\n            totalRect.xMin += EditorGUIUtility.labelWidth - 1;\n            Rect rect = totalRect;\n            rect.xMin += (totalRect.width - 4) * (column / 3f) + column * 2;\n            rect.width = (totalRect.width - 4) / 3f;\n            return rect;\n        }\n\n        void DrawRect(Rect rect, Transform space, bool dotted)\n        {\n            Vector3 p0 = space.TransformPoint(new Vector2(rect.x, rect.y));\n            Vector3 p1 = space.TransformPoint(new Vector2(rect.x, rect.yMax));\n            Vector3 p2 = space.TransformPoint(new Vector2(rect.xMax, rect.yMax));\n            Vector3 p3 = space.TransformPoint(new Vector2(rect.xMax, rect.y));\n            if (!dotted)\n            {\n                Handles.DrawLine(p0, p1);\n                Handles.DrawLine(p1, p2);\n                Handles.DrawLine(p2, p3);\n                Handles.DrawLine(p3, p0);\n            }\n            else\n            {\n                RectHandles.DrawDottedLineWithShadow(kShadowColor, kShadowOffset, p0, p1, kDottedLineSize);\n                RectHandles.DrawDottedLineWithShadow(kShadowColor, kShadowOffset, p1, p2, kDottedLineSize);\n                RectHandles.DrawDottedLineWithShadow(kShadowColor, kShadowOffset, p2, p3, kDottedLineSize);\n                RectHandles.DrawDottedLineWithShadow(kShadowColor, kShadowOffset, p3, p0, kDottedLineSize);\n            }\n        }\n\n        void OnSceneGUI()\n        {\n            if (!target)\n                return;\n            RectTransform gui = target as RectTransform;\n\n            Rect rectInOwnSpace = gui.rect;\n            Rect rectInUserSpace = rectInOwnSpace;\n            Rect rectInParentSpace = rectInOwnSpace;\n            Transform ownSpace = gui.transform;\n            Transform userSpace = ownSpace;\n            Transform parentSpace = ownSpace;\n            RectTransform guiParent = null;\n            if (ownSpace.parent != null)\n            {\n                parentSpace = ownSpace.parent;\n                rectInParentSpace.x += ownSpace.localPosition.x;\n                rectInParentSpace.y += ownSpace.localPosition.y;\n\n                guiParent = parentSpace.GetComponent<RectTransform>();\n            }\n\n            if (Tools.rectBlueprintMode)\n            {\n                userSpace = parentSpace;\n                rectInUserSpace = rectInParentSpace;\n            }\n\n            // Show unrotated/unscaled rect if moving anchor/pivot\n            float alpha = Mathf.Max(m_ChangingAnchors.faded, m_ChangingPivot.faded);\n            // Also show when moving or resizing rect if anchors are scaling on either axis\n            if (gui.anchorMin != gui.anchorMax)\n            {\n                alpha = Mathf.Max(alpha,\n                    m_ChangingPosX.faded,\n                    m_ChangingPosY.faded,\n                    m_ChangingLeft.faded,\n                    m_ChangingRight.faded,\n                    m_ChangingTop.faded,\n                    m_ChangingBottom.faded);\n            }\n\n            Color rectInParentSpaceColor = kRectInParentSpaceColor;\n            rectInParentSpaceColor.a *= alpha;\n            Handles.color = rectInParentSpaceColor;\n            DrawRect(rectInParentSpace, parentSpace, true);\n\n            if (m_TargetCount == 1)\n            {\n                RectTransformSnapping.OnGUI();\n\n                if (guiParent != null)\n                    AllAnchorsSceneGUI(gui, guiParent, parentSpace, ownSpace);\n\n                DrawSizes(rectInUserSpace, userSpace, rectInParentSpace, parentSpace, gui, guiParent);\n\n                RectTransformSnapping.DrawGuides();\n\n                if (Tools.current == Tool.Rect)\n                    ParentRectPreviewDragHandles(guiParent, parentSpace);\n            }\n        }\n\n        void ParentRectPreviewDragHandles(RectTransform gui, Transform space)\n        {\n            if (gui == null)\n                return;\n\n            float size = 0.05f * HandleUtility.GetHandleSize(space.position);\n            Rect rect = gui.rect;\n            for (int xHandle = 0; xHandle <= 2; xHandle++)\n            {\n                for (int yHandle = 0; yHandle <= 2; yHandle++)\n                {\n                    // Exactly one of the axes should be 1\n                    if ((xHandle == 1) == (yHandle == 1))\n                        continue;\n\n                    Vector3 curPos = Vector2.zero;\n                    for (int axis = 0; axis < 2; axis++)\n                        curPos[axis] = Mathf.Lerp(rect.min[axis], rect.max[axis], (axis == 0 ? xHandle : yHandle) * 0.5f);\n                    curPos = space.TransformPoint(curPos);\n\n                    int id = GUIUtility.GetControlID(s_ParentRectPreviewHandlesHash, FocusType.Passive);\n\n                    Vector3 sideDir = (xHandle == 1 ? space.right * rect.width : space.up * rect.height);\n                    Vector3 slideDir = (xHandle == 1 ? space.up : space.right);\n\n                    // could happen if gui.rect.{width,height} == 0\n                    if (sideDir == Vector3.zero)\n                        continue;\n\n                    EditorGUI.BeginChangeCheck();\n                    Vector3 newPos = RectHandles.SideSlider(id, curPos, sideDir, slideDir, size, null, Vector2.zero, -3);\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        Vector2 curPosInSpace = space.InverseTransformPoint(curPos);\n                        Vector2 newPosInSpace = space.InverseTransformPoint(newPos);\n                        Rect newRect = rect;\n                        Vector2 offset = newPosInSpace - curPosInSpace;\n                        if (xHandle == 0)\n                            newRect.min = new Vector2(newRect.min.x + offset.x, newRect.min.y);\n                        if (xHandle == 2)\n                            newRect.max = new Vector2(newRect.max.x + offset.x, newRect.max.y);\n                        if (yHandle == 0)\n                            newRect.min = new Vector2(newRect.min.x, newRect.min.y + offset.y);\n                        if (yHandle == 2)\n                            newRect.max = new Vector2(newRect.max.x, newRect.max.y + offset.y);\n                        SetTemporaryRect(gui, newRect, id);\n                    }\n\n                    if (EditorGUIUtility.hotControl == id)\n                    {\n                        Handles.BeginGUI();\n                        EditorGUI.DropShadowLabel(new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 60, 16), \"Preview\");\n                        Handles.EndGUI();\n                    }\n                }\n            }\n        }\n\n        private static float s_ParentDragTime = 0;\n        private static float s_ParentDragId = 0;\n        private static Rect s_ParentDragOrigRect = new Rect();\n        private static Rect s_ParentDragPreviewRect = new Rect();\n        private static RectTransform s_ParentDragRectTransform = null;\n        void SetTemporaryRect(RectTransform gui, Rect rect, int id)\n        {\n            if (s_ParentDragRectTransform == null)\n            {\n                s_ParentDragRectTransform = gui;\n                s_ParentDragOrigRect = gui.rect;\n                s_ParentDragId = id;\n            }\n            else if (s_ParentDragRectTransform != gui)\n            {\n                return;\n            }\n\n            s_ParentDragPreviewRect = rect;\n            s_ParentDragTime = Time.realtimeSinceStartup;\n\n            InternalEditorUtility.SetRectTransformTemporaryRect(gui, rect);\n\n            // Remove if it was already added so it's not added more than once.\n            EditorApplication.update -= UpdateTemporaryRect;\n            EditorApplication.update += UpdateTemporaryRect;\n        }\n\n        void UpdateTemporaryRect()\n        {\n            if (s_ParentDragRectTransform == null)\n                return;\n\n            if (EditorGUIUtility.hotControl == s_ParentDragId)\n            {\n                s_ParentDragTime = Time.realtimeSinceStartup;\n                Canvas.ForceUpdateCanvases();\n                PlayModeView.RepaintAll();\n                return;\n            }\n\n            float elapsed = Time.realtimeSinceStartup - s_ParentDragTime;\n            float lerp = Mathf.Clamp01(1 - elapsed * 8);\n            if (lerp > 0)\n            {\n                Rect r = new Rect();\n                r.position = Vector2.Lerp(s_ParentDragOrigRect.position, s_ParentDragPreviewRect.position, lerp);\n                r.size = Vector2.Lerp(s_ParentDragOrigRect.size, s_ParentDragPreviewRect.size, lerp);\n                InternalEditorUtility.SetRectTransformTemporaryRect(s_ParentDragRectTransform, r);\n            }\n            else\n            {\n                InternalEditorUtility.SetRectTransformTemporaryRect(s_ParentDragRectTransform, new Rect());\n                EditorApplication.update -= UpdateTemporaryRect;\n                s_ParentDragRectTransform = null;\n            }\n            Canvas.ForceUpdateCanvases();\n            SceneView.RepaintAll();\n            PlayModeView.RepaintAll();\n        }\n\n        void AllAnchorsSceneGUI(RectTransform gui, RectTransform guiParent, Transform parentSpace, Transform transform)\n        {\n            Handles.color = kParentColor;\n            // Draw parent rect\n            DrawRect(guiParent.rect, parentSpace, false);\n\n            // Draw sibling rects and anchors\n            Handles.color = kSiblingColor;\n            foreach (Transform tr in parentSpace)\n            {\n                if (!tr.gameObject.activeInHierarchy)\n                    continue;\n                RectTransform sibling = tr.GetComponent<RectTransform>();\n                if (sibling)\n                {\n                    Rect siblingRect = sibling.rect;\n                    siblingRect.x += sibling.transform.localPosition.x;\n                    siblingRect.y += sibling.transform.localPosition.y;\n                    DrawRect(sibling.rect, sibling, false);\n                    if (sibling != transform)\n                        AnchorsSceneGUI(sibling, guiParent, parentSpace, false);\n                }\n            }\n\n            // Draw anchors for RectTransform itself\n            Handles.color = kAnchorColor;\n            AnchorsSceneGUI(gui, guiParent, parentSpace, true);\n        }\n\n        Vector3 GetAnchorLocal(RectTransform guiParent, Vector2 anchor)\n        {\n            return NormalizedToPointUnclamped(guiParent.rect, anchor);\n        }\n\n        static Vector2 NormalizedToPointUnclamped(Rect rectangle, Vector2 normalizedRectCoordinates)\n        {\n            return new Vector2(\n                Mathf.LerpUnclamped(rectangle.x, rectangle.xMax, normalizedRectCoordinates.x),\n                Mathf.LerpUnclamped(rectangle.y, rectangle.yMax, normalizedRectCoordinates.y)\n            );\n        }\n\n        static bool AnchorAllowedOutsideParent(int axis, int minmax)\n        {\n            // Allow dragging outside if action key is held down (same key that disables snapping).\n            // Also allow when not dragging at all - for e.g. typing values into the Inspector.\n            if (EditorGUI.actionKey || EditorGUIUtility.hotControl == 0)\n                return true;\n            // Also allow if drag started outside of range to begin with.\n            float value = (minmax == 0 ? s_StartDragAnchorMin[axis] : s_StartDragAnchorMax[axis]);\n            return (value < -0.001f || value > 1.001f);\n        }\n\n        void AnchorsSceneGUI(RectTransform gui, RectTransform guiParent, Transform parentSpace, bool interactive)\n        {\n            if (Event.current.type == EventType.MouseDown)\n            {\n                s_AnchorFusedState = AnchorFusedState.None;\n                if (gui.anchorMin == gui.anchorMax)\n                    s_AnchorFusedState = AnchorFusedState.All;\n                else if (gui.anchorMin.x == gui.anchorMax.x)\n                    s_AnchorFusedState = AnchorFusedState.Horizontal;\n                else if (gui.anchorMin.y == gui.anchorMax.y)\n                    s_AnchorFusedState = AnchorFusedState.Vertical;\n            }\n\n            // Handles for the four corners\n            AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 0, 0, GUIUtility.GetControlID(FocusType.Passive));\n            AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 0, 1, GUIUtility.GetControlID(FocusType.Passive));\n            AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 1, 0, GUIUtility.GetControlID(FocusType.Passive));\n            AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 1, 1, GUIUtility.GetControlID(FocusType.Passive));\n\n            if (!interactive)\n                return;\n\n            // Aditional handles for dragging multiple of the corners simultaneously.\n            // These are not drawn, so don't need to be done for non-interactive handles.\n\n            // Get all ids always, regardless of whether the handles are done or not,\n            // to prevent id mismatch issues.\n            int idAll = GUIUtility.GetControlID(FocusType.Passive);\n            int idH1 = GUIUtility.GetControlID(FocusType.Passive);\n            int idH2 = GUIUtility.GetControlID(FocusType.Passive);\n            int idV1 = GUIUtility.GetControlID(FocusType.Passive);\n            int idV2 = GUIUtility.GetControlID(FocusType.Passive);\n\n            if (s_AnchorFusedState == AnchorFusedState.All)\n            {\n                AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 2, 2, idAll);\n            }\n            if (s_AnchorFusedState == AnchorFusedState.Horizontal)\n            {\n                AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 2, 0, idH1);\n                AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 2, 1, idH2);\n            }\n            if (s_AnchorFusedState == AnchorFusedState.Vertical)\n            {\n                AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 0, 2, idV1);\n                AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 1, 2, idV2);\n            }\n        }\n\n        // Minmax here means: 0 = min, 1 = max, 2 = both at once\n        void AnchorSceneGUI(RectTransform gui, RectTransform guiParent, Transform parentSpace, bool interactive, int minmaxX, int minmaxY, int id)\n        {\n            Vector3 curPos = new Vector2();\n            curPos.x = (minmaxX == 0 ? gui.anchorMin.x : gui.anchorMax.x);\n            curPos.y = (minmaxY == 0 ? gui.anchorMin.y : gui.anchorMax.y);\n            curPos = GetAnchorLocal(guiParent, curPos);\n            curPos = parentSpace.TransformPoint(curPos);\n\n            float size = 0.05f * HandleUtility.GetHandleSize(curPos);\n\n            if (minmaxX < 2)\n                curPos += parentSpace.right * size * (minmaxX * 2 - 1);\n            if (minmaxY < 2)\n                curPos += parentSpace.up * size * (minmaxY * 2 - 1);\n\n            if (minmaxX < 2 && minmaxY < 2)\n                DrawAnchor(curPos, parentSpace.right * size * 2 * (minmaxX * 2 - 1), parentSpace.up * size * 2 * (minmaxY * 2 - 1));\n\n            if (!interactive)\n                return;\n\n            Event evtCopy = new Event(Event.current);\n\n            EditorGUI.BeginChangeCheck();\n            Vector3 newPos = Handles.Slider2D(id, curPos, parentSpace.forward, parentSpace.right, parentSpace.up, size, (Handles.CapFunction)null, Vector2.zero);\n\n            if (evtCopy.type == EventType.MouseDown && GUIUtility.hotControl == id)\n            {\n                s_DragAnchorsTogether = EditorGUI.actionKey;\n                s_StartDragAnchorMin = gui.anchorMin;\n                s_StartDragAnchorMax = gui.anchorMax;\n                RectTransformSnapping.CalculateAnchorSnapValues(parentSpace, gui.transform, gui, minmaxX, minmaxY);\n            }\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                Undo.RecordObject(gui, \"Move Rectangle Anchors\");\n                Vector2 offset = parentSpace.InverseTransformVector(newPos - curPos);\n                for (int axis = 0; axis <= 1; axis++)\n                {\n                    offset[axis] /= guiParent.rect.size[axis];\n\n                    int minmaxForAxis = (axis == 0 ? minmaxX : minmaxY);\n                    bool isMax = (minmaxForAxis == 1);\n                    float old = isMax ? gui.anchorMax[axis] : gui.anchorMin[axis];\n                    float newValue = old + offset[axis];\n\n                    // Constraint to valid values\n                    float snappedValue = newValue;\n                    if (!AnchorAllowedOutsideParent(axis, minmaxForAxis))\n                        snappedValue = Mathf.Clamp01(snappedValue);\n                    if (minmaxForAxis == 0)\n                        snappedValue = Mathf.Min(snappedValue, gui.anchorMax[axis]);\n                    if (minmaxForAxis == 1)\n                        snappedValue = Mathf.Max(snappedValue, gui.anchorMin[axis]);\n\n                    // Snap to sibling anchors\n                    float snapSize = HandleUtility.GetHandleSize(newPos) * RectTransformSnapping.kSnapThreshold / guiParent.rect.size[axis];\n                    snapSize *= parentSpace.InverseTransformVector(axis == 0 ? Vector3.right : Vector3.up)[axis];\n                    snappedValue = RectTransformSnapping.SnapToGuides(snappedValue, snapSize, axis);\n\n                    bool snap = snappedValue != newValue;\n                    newValue = snappedValue;\n\n                    if (minmaxForAxis == 2)\n                    {\n                        SetAnchorSmart(gui, newValue, axis, false, !evtCopy.shift, snap, false, s_DragAnchorsTogether);\n                        SetAnchorSmart(gui, newValue, axis, true, !evtCopy.shift, snap, false, s_DragAnchorsTogether);\n                    }\n                    else\n                    {\n                        SetAnchorSmart(gui, newValue, axis, isMax, !evtCopy.shift, snap, true, s_DragAnchorsTogether);\n                    }\n                    EditorUtility.SetDirty(gui);\n                    if (gui.drivenByObject != null)\n                        RectTransform.SendReapplyDrivenProperties(gui);\n                }\n            }\n\n            SetFadingBasedOnMouseDownUp(ref m_ChangingAnchors, evtCopy);\n        }\n\n        static float Round(float value) { return Mathf.Floor(0.5f + value); }\n        static int RoundToInt(float value) { return Mathf.FloorToInt(0.5f + value); }\n\n        void DrawSizes(Rect rectInUserSpace, Transform userSpace, Rect rectInParentSpace, Transform parentSpace, RectTransform gui, RectTransform guiParent)\n        {\n            float size = 0.05f * HandleUtility.GetHandleSize(parentSpace.position);\n            float alpha;\n\n            bool stretchW = (gui.anchorMin.x != gui.anchorMax.x);\n            bool stretchH = (gui.anchorMin.y != gui.anchorMax.y);\n\n            alpha = Mathf.Max(\n                m_ChangingPosX.faded,\n                m_ChangingLeft.faded,\n                m_ChangingRight.faded,\n                m_ChangingAnchors.faded);\n            DrawAnchorRect(parentSpace, gui, guiParent, 0, alpha);\n\n            alpha = Mathf.Max(\n                m_ChangingPosY.faded,\n                m_ChangingTop.faded,\n                m_ChangingBottom.faded,\n                m_ChangingAnchors.faded);\n            DrawAnchorRect(parentSpace, gui, guiParent, 1, alpha);\n\n            DrawAnchorDistances(parentSpace, gui, guiParent, size, m_ChangingAnchors.faded);\n\n            if (stretchW)\n            {\n                DrawPositionDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 0, 1, m_ChangingLeft.faded);\n                DrawPositionDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 0, 2, m_ChangingRight.faded);\n            }\n            else\n            {\n                DrawPositionDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 0, 0, m_ChangingPosX.faded);\n                DrawSizeDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 0, m_ChangingWidth.faded);\n            }\n\n            if (stretchH)\n            {\n                DrawPositionDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 1, 1, m_ChangingBottom.faded);\n                DrawPositionDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 1, 2, m_ChangingTop.faded);\n            }\n            else\n            {\n                DrawPositionDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 1, 0, m_ChangingPosY.faded);\n                DrawSizeDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 1, m_ChangingHeight.faded);\n            }\n        }\n\n        void DrawSizeDistances(Transform userSpace, Rect rectInParentSpace, Transform parentSpace, RectTransform gui, RectTransform guiParent, float size, int axis, float alpha)\n        {\n            if (alpha <= 0)\n                return;\n\n            Color col = kAnchorColor;\n            col.a *= alpha;\n            GUI.color = col;\n\n            if (userSpace == gui.transform)\n            {\n                gui.GetWorldCorners(s_Corners);\n            }\n            else\n            {\n                gui.GetLocalCorners(s_Corners);\n                for (int i = 0; i < 4; i++)\n                {\n                    s_Corners[i] += gui.transform.localPosition;\n                    s_Corners[i] = userSpace.TransformPoint(s_Corners[i]);\n                }\n            }\n\n            string str = gui.sizeDelta[axis].ToString(CultureInfo.InvariantCulture.NumberFormat);\n            GUIContent label = new GUIContent(str);\n            Vector3 dir = (axis == 0 ? userSpace.up : userSpace.right) * size * 2;\n            DrawLabelBetweenPoints(s_Corners[0] + dir, s_Corners[axis == 0 ? 3 : 1] + dir, label);\n        }\n\n        void DrawPositionDistances(Transform userSpace, Rect rectInParentSpace, Transform parentSpace, RectTransform gui, RectTransform guiParent, float size, int axis, int side, float alpha)\n        {\n            if (guiParent == null || alpha <= 0)\n                return;\n\n            Color col = kAnchorLineColor;\n            col.a *= alpha;\n            Handles.color = col;\n            col = kAnchorColor;\n            col.a *= alpha;\n            GUI.color = col;\n\n            Vector3 posA;\n            Vector3 posB;\n            float value;\n            if (side == 0)\n            {\n                Vector2 pivot = Rect.NormalizedToPoint(rectInParentSpace, gui.pivot);\n                posA = pivot;\n                posB = pivot;\n                posA[axis] = Mathf.LerpUnclamped(guiParent.rect.min[axis], guiParent.rect.max[axis], gui.anchorMin[axis]);\n                value = gui.anchoredPosition[axis];\n            }\n            else\n            {\n                Vector2 center = rectInParentSpace.center;\n                posA = center;\n                posB = center;\n                if (side == 1)\n                {\n                    posA[axis] = Mathf.LerpUnclamped(guiParent.rect.min[axis], guiParent.rect.max[axis], gui.anchorMin[axis]);\n                    posB[axis] = rectInParentSpace.min[axis];\n                    value = gui.offsetMin[axis];\n                }\n                else\n                {\n                    posA[axis] = Mathf.LerpUnclamped(guiParent.rect.min[axis], guiParent.rect.max[axis], gui.anchorMax[axis]);\n                    posB[axis] = rectInParentSpace.max[axis];\n                    value = -gui.offsetMax[axis];\n                }\n            }\n\n            posA = parentSpace.TransformPoint(posA);\n            posB = parentSpace.TransformPoint(posB);\n\n            RectHandles.DrawDottedLineWithShadow(kShadowColor, kShadowOffset, posA, posB, kDottedLineSize);\n            GUIContent label = new GUIContent(value.ToString(CultureInfo.InvariantCulture.NumberFormat));\n            DrawLabelBetweenPoints(posA, posB, label);\n        }\n\n        void DrawAnchorDistances(Transform parentSpace, RectTransform gui, RectTransform guiParent, float size, float alpha)\n        {\n            if (guiParent == null || alpha <= 0)\n                return;\n\n            Color col = kAnchorColor;\n            col.a *= alpha;\n            GUI.color = col;\n\n            // Show percentages in Scene View while dragging anchors.\n            Vector3[,] points = new Vector3[2, 4];\n            for (int axis = 0; axis < 2; axis++)\n            {\n                for (int i = 0; i < 4; i++)\n                {\n                    Vector3 p = Vector3.zero;\n                    switch (i)\n                    {\n                        case 0: p = Vector3.zero; break;\n                        case 1: p = gui.anchorMin; break;\n                        case 2: p = gui.anchorMax; break;\n                        case 3: p = Vector3.one; break;\n                    }\n                    p[axis] = gui.anchorMin[axis];\n                    p = parentSpace.TransformPoint(GetAnchorLocal(guiParent, p));\n                    points[axis, i] = p;\n                }\n            }\n\n            for (int axis = 0; axis < 2; axis++)\n            {\n                Vector3 dir = (axis == 0 ? parentSpace.right : parentSpace.up) * size * 2;\n                int startValue = RoundToInt((gui.anchorMin[1 - axis]) * 100);\n                int midValue   = RoundToInt((gui.anchorMax[1 - axis] - gui.anchorMin[1 - axis]) * 100);\n                int endValue   = RoundToInt((1 - gui.anchorMax[1 - axis]) * 100);\n                if (startValue > 0)\n                    DrawLabelBetweenPoints(points[axis, 0] - dir, points[axis, 1] - dir, GUIContent.Temp(startValue + \"%\"));\n                if (midValue > 0)\n                    DrawLabelBetweenPoints(points[axis, 1] - dir, points[axis, 2] - dir, GUIContent.Temp(midValue + \"%\"));\n                if (endValue > 0)\n                    DrawLabelBetweenPoints(points[axis, 2] - dir, points[axis, 3] - dir, GUIContent.Temp(endValue + \"%\"));\n            }\n        }\n\n        void DrawAnchorRect(Transform parentSpace, RectTransform gui, RectTransform guiParent, int axis, float alpha)\n        {\n            if (guiParent == null || alpha <= 0)\n                return;\n\n            Color col = kAnchorLineColor;\n            col.a *= alpha;\n            Handles.color = col;\n\n            Vector3[,] points = new Vector3[2, 2];\n            for (int side = 0; side < 2; side++)\n            {\n                if (side == 1 && gui.anchorMin[axis] == gui.anchorMax[axis])\n                    continue;\n\n                points[side, 0][1 - axis] = Mathf.Min(0, gui.anchorMin[1 - axis]);\n                points[side, 1][1 - axis] = Mathf.Max(1, gui.anchorMax[1 - axis]);\n                for (int endpoint = 0; endpoint < 2; endpoint++)\n                {\n                    points[side, endpoint][axis] = (side == 0 ? gui.anchorMin[axis] : gui.anchorMax[axis]);\n                    points[side, endpoint] = parentSpace.TransformPoint(GetAnchorLocal(guiParent, points[side, endpoint]));\n                }\n                RectHandles.DrawDottedLineWithShadow(kShadowColor, kShadowOffset, points[side, 0], points[side, 1], kDottedLineSize);\n            }\n        }\n\n        void DrawLabelBetweenPoints(Vector3 pA, Vector3 pB, GUIContent label)\n        {\n            if (pA == pB)\n                return;\n\n            Vector2 vA = HandleUtility.WorldToGUIPoint(pA);\n            Vector2 vB = HandleUtility.WorldToGUIPoint(pB);\n            Vector2 center = (vA + vB) * 0.5f;\n            center.x = Round(center.x);\n            center.y = Round(center.y);\n            float angle = Mathf.Atan2(vB.y - vA.y, vB.x - vA.x) * Mathf.Rad2Deg;\n            angle = Mathf.Repeat(angle + 89f, 180f) - 89f;\n\n            Handles.BeginGUI();\n            Matrix4x4 oldMatrix = GUI.matrix;\n\n            GUIStyle style = styles.measuringLabelStyle;\n            style.alignment = TextAnchor.MiddleCenter;\n\n            GUIUtility.RotateAroundPivot(angle, center);\n            EditorGUI.DropShadowLabel(new Rect(center.x - 50, center.y - 9, 100, 16), label, style);\n\n            GUI.matrix = oldMatrix;\n            Handles.EndGUI();\n        }\n\n        static Vector3 GetRectReferenceCorner(RectTransform gui, bool worldSpace)\n        {\n            if (worldSpace)\n            {\n                Transform t = gui.transform;\n                gui.GetWorldCorners(s_Corners);\n                if (t.parent)\n                    return t.parent.InverseTransformPoint(s_Corners[0]);\n                else\n                    return s_Corners[0];\n            }\n            return (Vector3)gui.rect.min + gui.transform.localPosition;\n        }\n\n        void DrawAnchor(Vector3 pos, Vector3 right, Vector3 up)\n        {\n            pos -= up * 0.5f;\n            pos -= right * 0.5f;\n            up *= 1.4f;\n            right *= 1.4f;\n            RectHandles.DrawPolyLineWithShadow(kShadowColor, kShadowOffset,\n                pos,\n                pos + up + right * 0.5f,\n                pos + right + up * 0.5f,\n                pos);\n        }\n\n        public static void SetPivotSmart(RectTransform rect, float value, int axis, bool smart, bool parentSpace)\n        {\n            Vector3 cornerBefore = GetRectReferenceCorner(rect, !parentSpace);\n\n            Vector2 rectPivot = rect.pivot;\n            rectPivot[axis] = value;\n            rect.pivot = rectPivot;\n\n            if (smart)\n            {\n                Vector3 cornerAfter = GetRectReferenceCorner(rect, !parentSpace);\n                Vector3 cornerOffset = cornerAfter - cornerBefore;\n                rect.anchoredPosition -= (Vector2)cornerOffset;\n\n                Vector3 pos = rect.transform.position;\n                pos.z -= cornerOffset.z;\n                rect.transform.position = pos;\n            }\n        }\n\n        public static void SetAnchorSmart(RectTransform rect, float value, int axis, bool isMax, bool smart)\n        {\n            SetAnchorSmart(rect, value, axis, isMax, smart, false, false, false);\n        }\n\n        public static void SetAnchorSmart(RectTransform rect, float value, int axis, bool isMax, bool smart, bool enforceExactValue)\n        {\n            SetAnchorSmart(rect, value, axis, isMax, smart, enforceExactValue, false, false);\n        }\n\n        public static void SetAnchorSmart(RectTransform rect, float value, int axis, bool isMax, bool smart, bool enforceExactValue, bool enforceMinNoLargerThanMax, bool moveTogether)\n        {\n            RectTransform parent = null;\n            if (rect.transform.parent == null)\n            {\n                smart = false;\n            }\n            else\n            {\n                parent = rect.transform.parent.GetComponent<RectTransform>();\n                if (parent == null)\n                    smart = false;\n            }\n\n            bool clampToParent = !AnchorAllowedOutsideParent(axis, isMax ? 1 : 0);\n            if (clampToParent)\n                value = Mathf.Clamp01(value);\n            if (enforceMinNoLargerThanMax)\n            {\n                if (isMax)\n                    value = Mathf.Max(value, rect.anchorMin[axis]);\n                else\n                    value = Mathf.Min(value, rect.anchorMax[axis]);\n            }\n\n            float offsetSizePixels = 0;\n            float offsetPositionPixels = 0;\n            if (smart)\n            {\n                float oldValue = isMax ? rect.anchorMax[axis] : rect.anchorMin[axis];\n\n                offsetSizePixels = (value - oldValue) * parent.rect.size[axis];\n\n                // Ensure offset is in whole pixels.\n                // Note: In this particular instance we want to use Mathf.Round (which rounds towards nearest even number)\n                // instead of Round from this class which always rounds down.\n                // This makes the position of rect more stable when their anchors are changed.\n                float roundingDelta = 0;\n                if (ShouldDoIntSnapping(rect))\n                    roundingDelta = Mathf.Round(offsetSizePixels) - offsetSizePixels;\n                offsetSizePixels += roundingDelta;\n\n                if (!enforceExactValue)\n                {\n                    value += roundingDelta / parent.rect.size[axis];\n\n                    // Snap value to whole percent if close\n                    if (Mathf.Abs(Round(value * 1000) - value * 1000) < 0.1f)\n                        value = Round(value * 1000) * 0.001f;\n\n                    if (clampToParent)\n                        value = Mathf.Clamp01(value);\n                    if (enforceMinNoLargerThanMax)\n                    {\n                        if (isMax)\n                            value = Mathf.Max(value, rect.anchorMin[axis]);\n                        else\n                            value = Mathf.Min(value, rect.anchorMax[axis]);\n                    }\n                }\n\n                if (moveTogether)\n                    offsetPositionPixels = offsetSizePixels;\n                else\n                    offsetPositionPixels = (isMax ? offsetSizePixels * rect.pivot[axis] : (offsetSizePixels * (1 - rect.pivot[axis])));\n            }\n\n            if (isMax)\n            {\n                Vector2 rectAnchorMax = rect.anchorMax;\n                rectAnchorMax[axis] = value;\n                rect.anchorMax = rectAnchorMax;\n\n                Vector2 other = rect.anchorMin;\n                if (moveTogether)\n                    other[axis] = s_StartDragAnchorMin[axis] + rectAnchorMax[axis] - s_StartDragAnchorMax[axis];\n                rect.anchorMin = other;\n            }\n            else\n            {\n                Vector2 rectAnchorMin = rect.anchorMin;\n                rectAnchorMin[axis] = value;\n                rect.anchorMin = rectAnchorMin;\n\n                Vector2 other = rect.anchorMax;\n                if (moveTogether)\n                    other[axis] = s_StartDragAnchorMax[axis] + rectAnchorMin[axis] - s_StartDragAnchorMin[axis];\n                rect.anchorMax = other;\n            }\n\n            if (smart)\n            {\n                Vector2 rectPosition = rect.anchoredPosition;\n                rectPosition[axis] -= offsetPositionPixels;\n                rect.anchoredPosition = rectPosition;\n\n                if (!moveTogether)\n                {\n                    Vector2 rectSizeDelta = rect.sizeDelta;\n                    rectSizeDelta[axis] += offsetSizePixels * (isMax ? -1 : 1);\n                    rect.sizeDelta = rectSizeDelta;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/RectTransformSnapping.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class SnapGuideCollection\n    {\n        private List<SnapGuide> currentGuides = null;\n\n        private Dictionary<float, List<SnapGuide>> guides = new Dictionary<float, List<SnapGuide>>();\n\n        public void Clear()\n        {\n            guides.Clear();\n        }\n\n        public void AddGuide(SnapGuide guide)\n        {\n            List<SnapGuide> guideList;\n            if (!guides.TryGetValue(guide.value, out guideList))\n            {\n                guideList = new List<SnapGuide>();\n                guides.Add(guide.value, guideList);\n            }\n            guideList.Add(guide);\n        }\n\n        public float SnapToGuides(float value, float snapDistance)\n        {\n            if (guides.Count == 0)\n                return value;\n\n            KeyValuePair<float, List<SnapGuide>> snapPair = new KeyValuePair<float, List<SnapGuide>>();\n            float closestDistance = Mathf.Infinity;\n            foreach (var kvp in guides)\n            {\n                float distance = Mathf.Abs(value - kvp.Key);\n                if (distance < closestDistance)\n                {\n                    snapPair = kvp;\n                    closestDistance = distance;\n                }\n            }\n            if (closestDistance <= snapDistance)\n            {\n                value = snapPair.Key;\n                currentGuides = snapPair.Value;\n            }\n            else\n            {\n                currentGuides = null;\n            }\n            return value;\n        }\n\n        public void OnGUI()\n        {\n            if (Event.current.type == EventType.MouseUp)\n                currentGuides = null;\n        }\n\n        public void DrawGuides()\n        {\n            if (currentGuides != null)\n                foreach (SnapGuide guide in currentGuides)\n                    guide.Draw();\n        }\n    }\n\n    internal class SnapGuide\n    {\n        public float value;\n        public List<Vector3> lineVertices = new List<Vector3>();\n        public bool safe = true;\n\n        public SnapGuide(float value, params Vector3[] vertices) : this(value, true, vertices) {}\n\n        public SnapGuide(float value, bool safe, params Vector3[] vertices)\n        {\n            this.value = value;\n            this.lineVertices.AddRange(vertices);\n            this.safe = safe;\n        }\n\n        public void Draw()\n        {\n            Handles.color = safe ? new Color(0.0f, 0.5f, 1.0f, 1.0f) : new Color(1.0f, 0.5f, 0.0f, 1.0f);\n            for (int i = 0; i < lineVertices.Count; i += 2)\n            {\n                Vector3 v1 = lineVertices[i];\n                Vector3 v2 = lineVertices[i + 1];\n                if (v1 == v2)\n                    continue;\n                Vector3 dir = (v2 - v1).normalized * 0.05f;\n                v1 -= dir * HandleUtility.GetHandleSize(v1);\n                v2 += dir * HandleUtility.GetHandleSize(v2);\n                Handles.DrawLine(v1, v2);\n            }\n        }\n    }\n\n    internal class RectTransformSnapping\n    {\n        internal const float kSnapThreshold = 0.05f;\n        private static SnapGuideCollection[] s_SnapGuides = new SnapGuideCollection[] { new SnapGuideCollection(), new SnapGuideCollection() };\n        private static float[] kSidesAndMiddle = new float[] { 0, 0.5f, 1 };\n        private static Vector3[] s_Corners = new Vector3[4];\n\n        internal static void OnGUI()\n        {\n            s_SnapGuides[0].OnGUI();\n            s_SnapGuides[1].OnGUI();\n        }\n\n        internal static void DrawGuides()\n        {\n            if (EditorGUI.actionKey)\n                return;\n\n            s_SnapGuides[0].DrawGuides();\n            s_SnapGuides[1].DrawGuides();\n        }\n\n        static Vector3 GetInterpolatedCorner(Vector3[] corners, int mainAxis, float alongMainAxis, float alongOtherAxis)\n        {\n            if (mainAxis != 0)\n            {\n                float temp = alongMainAxis;\n                alongMainAxis = alongOtherAxis;\n                alongOtherAxis = temp;\n            }\n            return corners[0] * (1 - alongMainAxis) * (1 - alongOtherAxis)\n                +  corners[1] * (1 - alongMainAxis) * (alongOtherAxis)\n                +  corners[3] * (alongMainAxis) * (1 - alongOtherAxis)\n                +  corners[2] * (alongMainAxis) * (alongOtherAxis);\n        }\n\n        internal static void CalculatePivotSnapValues(Rect rect, Vector3 pivot, Quaternion rotation)\n        {\n            for (int axis = 0; axis < 2; axis++)\n            {\n                s_SnapGuides[axis].Clear();\n\n                // Snap to min, center, and max\n                for (int i = 0; i < kSidesAndMiddle.Length; i++)\n                    s_SnapGuides[axis].AddGuide(new SnapGuide(kSidesAndMiddle[i], GetGuideLineForRect(rect, pivot, rotation, axis, kSidesAndMiddle[i])));\n            }\n        }\n\n        internal static void CalculateAnchorSnapValues(Transform parentSpace, Transform self, RectTransform gui, int minmaxX, int minmaxY)\n        {\n            for (int axis = 0; axis < 2; axis++)\n            {\n                s_SnapGuides[axis].Clear();\n\n                // Snap to edges of parent\n                RectTransform parentRect = parentSpace.GetComponent<RectTransform>();\n                parentRect.GetWorldCorners(s_Corners);\n                for (int i = 0; i < kSidesAndMiddle.Length; i++)\n                {\n                    float val = kSidesAndMiddle[i];\n                    s_SnapGuides[axis].AddGuide(new SnapGuide(val,\n                        GetInterpolatedCorner(s_Corners, axis, val, 0),\n                        GetInterpolatedCorner(s_Corners, axis, val, 1)));\n                }\n\n                // Snap to sibling anchor values\n                foreach (Transform tr in parentSpace)\n                {\n                    if (tr == self)\n                        continue;\n                    RectTransform sibling = tr.GetComponent<RectTransform>();\n                    if (sibling)\n                    {\n                        s_SnapGuides[axis].AddGuide(new SnapGuide(sibling.anchorMin[axis]));\n                        s_SnapGuides[axis].AddGuide(new SnapGuide(sibling.anchorMax[axis]));\n                    }\n                }\n\n                // Snap to own opposite anchor values\n                int minmax = (axis == 0 ? minmaxX : minmaxY);\n                if (minmax == 0)\n                    s_SnapGuides[axis].AddGuide(new SnapGuide(gui.anchorMax[axis]));\n                if (minmax == 1)\n                    s_SnapGuides[axis].AddGuide(new SnapGuide(gui.anchorMin[axis]));\n            }\n        }\n\n        // handle values are: 0 = min, 1 = middle, 2 = max\n        internal static void CalculateOffsetSnapValues(Transform parentSpace, Transform self, RectTransform parentRect, RectTransform rect, int xHandle, int yHandle)\n        {\n            for (int axis = 0; axis < 2; axis++)\n                s_SnapGuides[axis].Clear();\n\n            if (parentSpace == null)\n                return;\n\n            List<SnapGuide> guides;\n            for (int axis = 0; axis < 2; axis++)\n            {\n                int handle = (axis == 0 ? xHandle : yHandle);\n                if (handle == 1)\n                    continue;\n\n                guides = GetSnapGuides(parentSpace, self, parentRect, rect, axis, handle);\n                foreach (SnapGuide guide in guides)\n                {\n                    s_SnapGuides[axis].AddGuide(guide);\n                }\n            }\n        }\n\n        internal static void CalculatePositionSnapValues(Transform parentSpace, Transform self, RectTransform parentRect, RectTransform rect)\n        {\n            for (int axis = 0; axis < 2; axis++)\n                s_SnapGuides[axis].Clear();\n\n            if (parentSpace == null)\n                return;\n\n            List<SnapGuide> guides;\n            for (int axis = 0; axis < 2; axis++)\n            {\n                for (int side = 0; side < kSidesAndMiddle.Length; side++)\n                {\n                    guides = GetSnapGuides(parentSpace, self, parentRect, rect, axis, side);\n                    foreach (SnapGuide guide in guides)\n                    {\n                        guide.value = GetGuideValueForRect(rect, guide.value, axis, kSidesAndMiddle[side]);\n                        s_SnapGuides[axis].AddGuide(guide);\n                    }\n                }\n            }\n        }\n\n        // side is: 0 = min, 1 = middle, 2 = max\n        private static List<SnapGuide> GetSnapGuides(Transform parentSpace, Transform self, RectTransform parentRect, RectTransform rect, int axis, int side)\n        {\n            List<SnapGuide> guides = new List<SnapGuide>();\n\n            // For snapping we have a concept of safe and unsafe snapping.\n            //  - Safe snapping means the objects will remain aligned when the parent rect changes size.\n            //  - Unsafe snapping means that the objects are aligned right now, but will no longer be aligned\n            //    if the parent rect changes size because of different anchoring.\n\n            if (parentRect != null)\n            {\n                float val = kSidesAndMiddle[side];\n\n                // Snap min side to min anchor, center to center point, max side to max anchor - this is always safe\n                float normalized = Mathf.Lerp(rect.anchorMin[axis], rect.anchorMax[axis], val);\n                guides.Add(new SnapGuide(normalized * parentRect.rect.size[axis],\n                    GetGuideLineForRect(parentRect, axis, normalized)));\n\n                // Snap to sides and center of the parent rect (if not the same as the anchor).\n                // This snapping is not safe.\n                float anchorVal = Mathf.Lerp(rect.anchorMin[axis], rect.anchorMax[axis], val);\n                if (val != anchorVal)\n                {\n                    guides.Add(new SnapGuide(val * parentRect.rect.size[axis], false,\n                        GetGuideLineForRect(parentRect, axis, val)));\n                }\n            }\n\n            // Snap to siblings\n            foreach (Transform tr in parentSpace)\n            {\n                if (tr == self)\n                    continue;\n                RectTransform sibling = tr.GetComponent<RectTransform>();\n                bool safe = true;\n                if (sibling)\n                {\n                    if (side == 0)\n                    {\n                        // Snap min to min side\n                        // This is safe if both objects have the same min anchor.\n                        safe = (sibling.anchorMin[axis] == rect.anchorMin[axis]);\n                        guides.Add(new SnapGuide(sibling.GetRectInParentSpace().min[axis], safe,\n                            GetGuideLineForRect(sibling, axis, 0)));\n\n                        // Snap min to max side\n                        // This is safe if min anchor of this object is equal to max anchor of the sibling.\n                        safe = (sibling.anchorMax[axis] == rect.anchorMin[axis]);\n                        guides.Add(new SnapGuide(sibling.GetRectInParentSpace().max[axis], safe,\n                            GetGuideLineForRect(sibling, axis, 1)));\n                    }\n\n                    if (side == 2)\n                    {\n                        // Snap max to max side\n                        // This is safe if both objects have the same max anchor.\n                        safe = (sibling.anchorMax[axis] == rect.anchorMax[axis]);\n                        guides.Add(new SnapGuide(sibling.GetRectInParentSpace().max[axis], safe,\n                            GetGuideLineForRect(sibling, axis, 1)));\n\n                        // Snap max to min side\n                        // This is safe if max anchor of this object is equal to min anchor of the sibling.\n                        safe = (sibling.anchorMin[axis] == rect.anchorMax[axis]);\n                        guides.Add(new SnapGuide(sibling.GetRectInParentSpace().min[axis], safe,\n                            GetGuideLineForRect(sibling, axis, 0)));\n                    }\n\n                    if (side == 1)\n                    {\n                        // Snap middle to middle\n                        // This is safe if the difference between the min anchors is the opposite of the difference between the max anchors.\n                        // This also includes the case where both objects have the same min and max anchors.\n                        safe = (sibling.anchorMin[axis] - rect.anchorMin[axis] == -(sibling.anchorMax[axis] - rect.anchorMax[axis]));\n                        guides.Add(new SnapGuide(sibling.GetRectInParentSpace().center[axis], safe,\n                            GetGuideLineForRect(sibling, axis, 0.5f)));\n                    }\n                }\n            }\n\n            return guides;\n        }\n\n        private static Vector3[] GetGuideLineForRect(RectTransform rect, int axis, float side)\n        {\n            Vector3[] points = new Vector3[2];\n\n            // Set end points of line on other axis\n            points[0][1 - axis] = rect.rect.min[1 - axis];\n            points[1][1 - axis] = rect.rect.max[1 - axis];\n\n            // Set position of line on axis\n            points[0][axis] = Mathf.Lerp(rect.rect.min[axis], rect.rect.max[axis], side);\n            points[1][axis] = points[0][axis];\n\n            // Transform to world space\n            points[0] = rect.transform.TransformPoint(points[0]);\n            points[1] = rect.transform.TransformPoint(points[1]);\n\n            return points;\n        }\n\n        private static Vector3[] GetGuideLineForRect(Rect rect, Vector3 pivot, Quaternion rotation, int axis, float side)\n        {\n            Vector3[] points = new Vector3[2];\n\n            // Set end points of line on other axis\n            points[0][1 - axis] = rect.min[1 - axis];\n            points[1][1 - axis] = rect.max[1 - axis];\n\n            // Set position of line on axis\n            points[0][axis] = Mathf.Lerp(rect.min[axis], rect.max[axis], side);\n            points[1][axis] = points[0][axis];\n\n            // Transform to world space\n            points[0] = rotation * points[0] + pivot;\n            points[1] = rotation * points[1] + pivot;\n\n            return points;\n        }\n\n        private static float GetGuideValueForRect(RectTransform rect, float value, int axis, float side)\n        {\n            RectTransform parentRect = rect.transform.parent.GetComponent<RectTransform>();\n            float parentSize = parentRect ? parentRect.rect.size[axis] : 0;\n            float anchorReference = Mathf.Lerp(rect.anchorMin[axis], rect.anchorMax[axis], rect.pivot[axis]) * parentSize;\n            float positionRelativeToSide = rect.rect.size[axis] * (rect.pivot[axis] - side);\n            return value - anchorReference + positionRelativeToSide;\n        }\n\n        internal static Vector2 SnapToGuides(Vector2 value, Vector2 snapDistance)\n        {\n            return new Vector2(\n                SnapToGuides(value.x, snapDistance.x, 0),\n                SnapToGuides(value.y, snapDistance.y, 1)\n            );\n        }\n\n        internal static float SnapToGuides(float value, float snapDistance, int axis)\n        {\n            if (EditorGUI.actionKey)\n                return value;\n\n            SnapGuideCollection guides = (axis == 0 ? s_SnapGuides[0] : s_SnapGuides[1]);\n            return guides.SnapToGuides(value, snapDistance);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ReflectionProbeEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor.AnimatedValues;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEngine.SceneManagement;\nusing UnityEditor.SceneManagement;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(ReflectionProbe))]\n    [CanEditMultipleObjects]\n    internal class ReflectionProbeEditor : Editor\n    {\n        static ReflectionProbeEditor s_LastInteractedEditor;\n        static HashSet<ReflectionProbe> s_CurrentlyEditedProbes = new HashSet<ReflectionProbe>();\n\n        SerializedProperty m_Mode;\n        SerializedProperty m_RefreshMode;\n        SerializedProperty m_TimeSlicingMode;\n        SerializedProperty m_Resolution;\n        SerializedProperty m_ShadowDistance;\n        SerializedProperty m_Importance;\n        SerializedProperty m_BoxSize;\n        SerializedProperty m_BoxOffset;\n        SerializedProperty m_CullingMask;\n        SerializedProperty m_ClearFlags;\n        SerializedProperty m_BackgroundColor;\n        SerializedProperty m_HDR;\n        SerializedProperty m_BoxProjection;\n        SerializedProperty m_IntensityMultiplier;\n        SerializedProperty m_BlendDistance;\n        SerializedProperty m_CustomBakedTexture;\n        SerializedProperty m_RenderDynamicObjects;\n        SerializedProperty m_UseOcclusionCulling;\n\n        SerializedProperty[] m_NearAndFarProperties;\n\n        private static Mesh s_SphereMesh;\n        private Material m_ReflectiveMaterial;\n        private Matrix4x4 m_OldLocalSpace = Matrix4x4.identity;\n        private float m_MipLevelPreview = 0.0F;\n\n        private BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle();\n\n        private Hashtable m_CachedGizmoMaterials = new Hashtable();\n\n        public static void GetResolutionArray(ref int[] resolutionList, ref GUIContent[] resolutionStringList)\n        {\n            if (Styles.reflectionResolutionValuesArray == null && Styles.reflectionResolutionTextArray == null)\n            {\n                int cubemapResolution = Mathf.Max(1, ReflectionProbe.minBakedCubemapResolution);\n\n                List<int> envReflectionResolutionValues = new List<int>();\n                List<GUIContent> envReflectionResolutionText = new List<GUIContent>();\n\n                do\n                {\n                    envReflectionResolutionValues.Add(cubemapResolution);\n                    envReflectionResolutionText.Add(new GUIContent(cubemapResolution.ToString()));\n                    cubemapResolution *= 2;\n                }\n                while (cubemapResolution <= ReflectionProbe.maxBakedCubemapResolution);\n\n                Styles.reflectionResolutionValuesArray = envReflectionResolutionValues.ToArray();\n                Styles.reflectionResolutionTextArray = envReflectionResolutionText.ToArray();\n            }\n\n            resolutionList = Styles.reflectionResolutionValuesArray;\n            resolutionStringList = Styles.reflectionResolutionTextArray;\n        }\n\n        static internal class Styles\n        {\n            static Styles()\n            {\n                richTextMiniLabel.richText = true;\n            }\n\n            public static GUIStyle richTextMiniLabel = new GUIStyle(EditorStyles.miniLabel);\n\n            public static GUIContent bakeButtonText = EditorGUIUtility.TrTextContent(\"Bake\");\n            public static string[] bakeCustomOptionText = { \"Bake as new Cubemap...\" };\n            public static string[] bakeButtonsText = { \"Bake All Reflection Probes\" };\n\n            public static GUIContent bakeCustomButtonText = EditorGUIUtility.TrTextContent(\"Bake\", \"Bakes Reflection Probe's cubemap, overwriting the existing cubemap texture asset (if any).\");\n            public static GUIContent runtimeSettingsHeader = EditorGUIUtility.TrTextContent(\"Runtime Settings\", \"These settings determine this Probe's priority, blending, intensity, and zone of effect and works in conjunction with the cubemap of this probe when it is rendered.\");\n            public static GUIContent backgroundColorText = EditorGUIUtility.TrTextContent(\"Background Color\", \"Camera clears the screen to this color before rendering.\");\n            public static GUIContent clearFlagsText = EditorGUIUtility.TrTextContent(\"Clear Flags\", \"Specify how to fill empty areas of the cubemap.\");\n            public static GUIContent intensityText = EditorGUIUtility.TrTextContent(\"Intensity\", \"The intensity modifier the Editor applies to this probe's texture in its shader.\");\n            public static GUIContent resolutionText = EditorGUIUtility.TrTextContent(\"Resolution\", \"The resolution of the cubemap.\");\n            public static GUIContent captureCubemapHeader = EditorGUIUtility.TrTextContent(\"Cubemap Capture Settings\", \"Settings that determine how to render this probe's cubemap.\");\n            public static GUIContent boxProjectionText = EditorGUIUtility.TrTextContent(\"Box Projection\", \"When enabled, Unity assumes that the reflected light is originating from the inside of the probe's box, rather than from infinitely far away. This is useful for box-shaped indoor environments.\");\n            public static GUIContent blendDistanceText = EditorGUIUtility.TrTextContent(\"Blend Distance\", \"Area around the probe where it is blended with other probes. Only used in deferred probes.\");\n            public static GUIContent sizeText = EditorGUIUtility.TrTextContent(\"Box Size\", \"The size of the box in which the reflections will be applied to objects. The value is not affected by the Transform of the Game Object.\");\n            public static GUIContent centerText = EditorGUIUtility.TrTextContent(\"Box Offset\", \"The center of the box in which the reflections will be applied to objects. The value is relative to the position of the Game Object.\");\n            public static GUIContent customCubemapText = EditorGUIUtility.TrTextContent(\"Cubemap\", \"Sets a custom cubemap for this probe.\");\n            public static GUIContent importanceText = EditorGUIUtility.TrTextContent(\"Importance\", \"When reflection probes overlap, Unity uses Importance to determine which probe should take priority.\");\n            public static GUIContent renderDynamicObjects = EditorGUIUtility.TrTextContent(\"Dynamic Objects\", \"If enabled dynamic objects are also rendered into the cubemap\");\n            public static GUIContent timeSlicing = EditorGUIUtility.TrTextContent(\"Time Slicing\", \"If enabled this probe will update over several frames, to help reduce the impact on the frame rate\");\n            public static GUIContent refreshMode = EditorGUIUtility.TrTextContent(\"Refresh Mode\", \"Controls how this probe refreshes in the Player\");\n            public static GUIContent useOcclusionCulling = EditorGUIUtility.TrTextContent(\"Occlusion Culling\", \"If this property is enabled, geometries which are blocked from the probe's line of sight are skipped during rendering.\");\n            public static GUIContent hdrText = EditorGUIUtility.TrTextContent(\"HDR\", \"Enable High Dynamic Range rendering.\");\n            public static GUIContent shadowDistanceText = EditorGUIUtility.TrTextContent(\"Shadow Distance\", \"Maximum distance at which Unity renders shadows associated with this probe.\");\n            public static GUIContent cullingMaskText = EditorGUIUtility.TrTextContent(\"Culling Mask\", \"Allows objects on specified layers to be included or excluded in the reflection.\");\n\n            public static GUIContent typeText = EditorGUIUtility.TrTextContent(\"Type\", \"Specify the lighting setup for this probe: Baked, Custom, or Realtime.\");\n            public static GUIContent[] reflectionProbeMode = { EditorGUIUtility.TrTextContent(\"Baked\"), EditorGUIUtility.TrTextContent(\"Custom\"), EditorGUIUtility.TrTextContent(\"Realtime\") };\n            public static int[] reflectionProbeModeValues = { (int)ReflectionProbeMode.Baked, (int)ReflectionProbeMode.Custom, (int)ReflectionProbeMode.Realtime };\n\n            public static int[] reflectionResolutionValuesArray = null;\n            public static GUIContent[] reflectionResolutionTextArray = null;\n\n            public static GUIContent[] clearFlags =\n            {\n                EditorGUIUtility.TrTextContent(\"Skybox\"),\n                EditorGUIUtility.TrTextContent(\"Solid Color\")\n            };\n            public static int[] clearFlagsValues = { 1, 2 }; // taken from Camera.h\n\n            private static GUIContent customPrivitiveBoundsHandleEditModeButton = new GUIContent(\n                EditorGUIUtility.IconContent(\"EditShape\").image,\n                EditorGUIUtility.TrTextContent(\"Adjust the probe's zone of effect. Holding Alt or Shift and click the control handle to pin the center or scale the volume uniformly.\").text\n            );\n            public static GUIContent[] toolContents =\n            {\n                customPrivitiveBoundsHandleEditModeButton,\n                EditorGUIUtility.TrIconContent(\"CapturePosition\", \"Modify capture position.\")\n            };\n            public static EditMode.SceneViewEditMode[] sceneViewEditModes = new[]\n            {\n                EditMode.SceneViewEditMode.ReflectionProbeBox,\n                EditMode.SceneViewEditMode.ReflectionProbeOrigin\n            };\n\n            public static string baseSceneEditingToolText = \"<color=grey>Probe Scene Editing Mode:</color> \";\n            public static GUIContent[] toolNames =\n            {\n                new GUIContent(baseSceneEditingToolText + \"Box Projection Bounds\", \"\"),\n                new GUIContent(baseSceneEditingToolText + \"Probe Origin\", \"\")\n            };\n        } // end of class Styles\n\n        // Should match reflection probe gizmo color in GizmoDrawers.cpp!\n        internal static Color kGizmoReflectionProbe = new Color(0xFF / 255f, 0xE5 / 255f, 0x94 / 255f, 0x80 / 255f);\n        internal static Color kGizmoReflectionProbeDisabled = new Color(0x99 / 255f, 0x89 / 255f, 0x59 / 255f, 0x60 / 255f);\n        internal static Color kGizmoHandleReflectionProbe = new Color(0xFF / 255f, 0xE5 / 255f, 0xAA / 255f, 0xFF / 255f);\n\n        private SavedBool m_ShowRuntimeSettings;\n        private SavedBool m_ShowCubemapCaptureSettings;\n\n        readonly AnimBool m_ShowProbeModeRealtimeOptions = new AnimBool(); // p.mode == ReflectionProbeMode.Realtime; Will be brought back in 5.1\n        readonly AnimBool m_ShowProbeModeCustomOptions = new AnimBool();\n        readonly AnimBool m_ShowBoxOptions = new AnimBool();\n\n        private TextureInspector m_CubemapEditor = null;\n\n        static bool IsReflectionProbeEditMode(EditMode.SceneViewEditMode editMode)\n        {\n            return editMode == EditMode.SceneViewEditMode.ReflectionProbeBox ||\n                editMode == EditMode.SceneViewEditMode.ReflectionProbeOrigin;\n        }\n\n        bool sceneViewEditing\n        {\n            get { return IsReflectionProbeEditMode(EditMode.editMode) && EditMode.IsOwner(this); }\n        }\n\n        public void OnEnable()\n        {\n            m_Mode = serializedObject.FindProperty(\"m_Mode\");\n            m_RefreshMode = serializedObject.FindProperty(\"m_RefreshMode\");\n            m_TimeSlicingMode = serializedObject.FindProperty(\"m_TimeSlicingMode\");\n\n            m_Resolution = serializedObject.FindProperty(\"m_Resolution\");\n            m_NearAndFarProperties = new[] { serializedObject.FindProperty(\"m_NearClip\"), serializedObject.FindProperty(\"m_FarClip\") };\n            m_ShadowDistance = serializedObject.FindProperty(\"m_ShadowDistance\");\n            m_Importance = serializedObject.FindProperty(\"m_Importance\");\n            m_BoxSize = serializedObject.FindProperty(\"m_BoxSize\");\n            m_BoxOffset = serializedObject.FindProperty(\"m_BoxOffset\");\n            m_CullingMask = serializedObject.FindProperty(\"m_CullingMask\");\n            m_ClearFlags = serializedObject.FindProperty(\"m_ClearFlags\");\n            m_BackgroundColor = serializedObject.FindProperty(\"m_BackGroundColor\");\n            m_HDR = serializedObject.FindProperty(\"m_HDR\");\n            m_BoxProjection = serializedObject.FindProperty(\"m_BoxProjection\");\n            m_IntensityMultiplier = serializedObject.FindProperty(\"m_IntensityMultiplier\");\n            m_BlendDistance = serializedObject.FindProperty(\"m_BlendDistance\");\n            m_CustomBakedTexture = serializedObject.FindProperty(\"m_CustomBakedTexture\");\n            m_RenderDynamicObjects = serializedObject.FindProperty(\"m_RenderDynamicObjects\");\n            m_UseOcclusionCulling = serializedObject.FindProperty(\"m_UseOcclusionCulling\");\n\n            ReflectionProbe p = target as ReflectionProbe;\n            m_ShowProbeModeRealtimeOptions.valueChanged.AddListener(Repaint);\n            m_ShowProbeModeCustomOptions.valueChanged.AddListener(Repaint);\n            m_ShowBoxOptions.valueChanged.AddListener(Repaint);\n            m_ShowProbeModeRealtimeOptions.value = p.mode == ReflectionProbeMode.Realtime;\n            m_ShowProbeModeCustomOptions.value = p.mode == ReflectionProbeMode.Custom;\n            m_ShowBoxOptions.value = true;\n\n            m_BoundsHandle.handleColor = kGizmoHandleReflectionProbe;\n            m_BoundsHandle.wireframeColor = Color.clear;\n\n            m_ShowRuntimeSettings = new SavedBool(\"ReflectionProbeEditor.ShowRuntimeSettings\", true);\n            m_ShowCubemapCaptureSettings = new SavedBool(\"ReflectionProbeEditor.ShowCubemapCaptureSettings\", true);\n\n            UpdateOldLocalSpace();\n            SceneView.beforeSceneGui += OnPreSceneGUICallback;\n\n            for (int i = 0; i < targets.Length; ++i)\n            {\n                s_CurrentlyEditedProbes.Add((ReflectionProbe)targets[i]);\n            }\n        }\n\n        public void OnDisable()\n        {\n            SceneView.beforeSceneGui -= OnPreSceneGUICallback;\n\n            DestroyImmediate(m_ReflectiveMaterial);\n            DestroyImmediate(m_CubemapEditor);\n\n            foreach (Material mat in m_CachedGizmoMaterials.Values)\n                DestroyImmediate(mat);\n            m_CachedGizmoMaterials.Clear();\n\n            for (int i = 0; i < targets.Length; ++i)\n            {\n                s_CurrentlyEditedProbes.Remove((ReflectionProbe)targets[i]);\n            }\n        }\n\n        private bool IsCollidingWithOtherProbes(string targetPath, ReflectionProbe targetProbe, out ReflectionProbe collidingProbe)\n        {\n            ReflectionProbe[] probes = FindObjectsByType<ReflectionProbe>(FindObjectsSortMode.InstanceID).ToArray();\n            collidingProbe = null;\n            foreach (var probe in probes)\n            {\n                if (probe == targetProbe || probe.customBakedTexture == null)\n                    continue;\n                string path = AssetDatabase.GetAssetPath(probe.customBakedTexture);\n                if (path == targetPath)\n                {\n                    collidingProbe = probe;\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        private void BakeCustomReflectionProbe(ReflectionProbe probe, bool usePreviousAssetPath)\n        {\n            string path = \"\";\n            if (usePreviousAssetPath)\n                path = AssetDatabase.GetAssetPath(probe.customBakedTexture);\n\n            string targetExtension = probe.hdr ? \"exr\" : \"png\";\n            if (string.IsNullOrEmpty(path) || Path.GetExtension(path) != \".\" + targetExtension)\n            {\n                // We use the path of the active scene as the target path\n                string targetPath = FileUtil.GetPathWithoutExtension(SceneManager.GetActiveScene().path);\n                if (string.IsNullOrEmpty(targetPath))\n                    targetPath = \"Assets\";\n                else if (Directory.Exists(targetPath) == false)\n                    Directory.CreateDirectory(targetPath);\n\n                string fileName = probe.name + (probe.hdr ? \"-reflectionHDR\" : \"-reflection\") + \".\" + targetExtension;\n                fileName = Path.GetFileNameWithoutExtension(AssetDatabase.GenerateUniqueAssetPath(Path.Combine(targetPath, fileName)));\n\n                path = EditorUtility.SaveFilePanelInProject(\"Save reflection probe's cubemap.\", fileName, targetExtension, \"\", targetPath);\n                if (string.IsNullOrEmpty(path))\n                    return;\n\n                ReflectionProbe collidingProbe;\n                if (IsCollidingWithOtherProbes(path, probe, out collidingProbe))\n                {\n                    if (!EditorUtility.DisplayDialog(\"Cubemap is used by other reflection probe\",\n                        string.Format(\"'{0}' path is used by the game object '{1}', do you really want to overwrite it?\",\n                            path, collidingProbe.name), \"Yes\", \"No\"))\n                    {\n                        return;\n                    }\n                }\n            }\n\n            EditorUtility.DisplayProgressBar(\"Reflection Probes\", \"Baking \" + path, 0.5f);\n            if (!Lightmapping.BakeReflectionProbe(probe, path))\n                Debug.LogError(\"Failed to bake reflection probe to \" + path);\n            EditorUtility.ClearProgressBar();\n        }\n\n        private void OnBakeCustomButton(object data)\n        {\n            int mode = (int)data;\n\n            ReflectionProbe p = target as ReflectionProbe;\n            if (mode == 0)\n                BakeCustomReflectionProbe(p, false);\n        }\n\n        private void OnBakeButton(object data)\n        {\n            int mode = (int)data;\n            if (mode == 0)\n                Lightmapping.BakeAllReflectionProbesSnapshots();\n        }\n\n        ReflectionProbe reflectionProbeTarget\n        {\n            get { return (ReflectionProbe)target; }\n        }\n\n        void DoBakeButton()\n        {\n            if (reflectionProbeTarget.mode == ReflectionProbeMode.Realtime)\n            {\n                EditorGUILayout.HelpBox(\"Baking of this reflection probe should be initiated from the scripting API because the type is 'Realtime'\", MessageType.Info);\n\n                if (!QualitySettings.realtimeReflectionProbes)\n                    EditorGUILayout.HelpBox(\"Realtime reflection probes are disabled in Quality Settings\", MessageType.Warning);\n                return;\n            }\n\n            GUILayout.BeginHorizontal();\n\n            switch (reflectionProbeMode)\n            {\n                case ReflectionProbeMode.Custom:\n                    if (EditorGUI.LargeSplitButtonWithDropdownList(Styles.bakeCustomButtonText, Styles.bakeCustomOptionText, OnBakeCustomButton))\n                    {\n                        BakeCustomReflectionProbe(reflectionProbeTarget, true);\n                        GUIUtility.ExitGUI();\n                    }\n                    break;\n\n                case ReflectionProbeMode.Baked:\n                    using (new EditorGUI.DisabledScope(!reflectionProbeTarget.enabled))\n                    {\n                        // Bake button in non-continous mode\n                        if (EditorGUI.LargeSplitButtonWithDropdownList(Styles.bakeButtonText, Styles.bakeButtonsText, OnBakeButton))\n                        {\n                            Lightmapping.BakeReflectionProbeSnapshot(reflectionProbeTarget);\n                            GUIUtility.ExitGUI();\n                        }\n                    }\n\n                    break;\n\n                case ReflectionProbeMode.Realtime:\n                    // Not showing bake button in realtime\n                    break;\n            }\n\n            GUILayout.EndHorizontal();\n        }\n\n        void DoToolbar()\n        {\n            // Show the master tool selector\n            GUILayout.BeginHorizontal();\n            GUILayout.FlexibleSpace();\n            GUI.changed = false;\n            var oldEditMode = EditMode.editMode;\n\n            EditorGUI.BeginChangeCheck();\n            EditMode.DoInspectorToolbar(Styles.sceneViewEditModes, Styles.toolContents, this);\n            if (EditorGUI.EndChangeCheck())\n                s_LastInteractedEditor = this;\n\n            if (oldEditMode != EditMode.editMode)\n            {\n                switch (EditMode.editMode)\n                {\n                    case EditMode.SceneViewEditMode.ReflectionProbeOrigin:\n                        UpdateOldLocalSpace();\n                        break;\n                }\n                if (Toolbar.get != null)\n                    Toolbar.get.Repaint();\n            }\n\n            GUILayout.FlexibleSpace();\n            GUILayout.EndHorizontal();\n\n            // Info box for tools\n            GUILayout.BeginVertical(EditorStyles.helpBox);\n            string helpText = Styles.baseSceneEditingToolText;\n            if (sceneViewEditing)\n            {\n                int index = ArrayUtility.IndexOf(Styles.sceneViewEditModes, EditMode.editMode);\n                if (index >= 0)\n                    helpText = Styles.toolNames[index].text;\n            }\n            GUILayout.Label(helpText, Styles.richTextMiniLabel);\n            GUILayout.EndVertical();\n            EditorGUILayout.Space();\n        }\n\n        ReflectionProbeMode reflectionProbeMode\n        {\n            get { return reflectionProbeTarget.mode; }\n        }\n\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            if (targets.Length == 1)\n                DoToolbar();\n\n            m_ShowProbeModeRealtimeOptions.target = reflectionProbeMode == ReflectionProbeMode.Realtime;\n            m_ShowProbeModeCustomOptions.target = reflectionProbeMode == ReflectionProbeMode.Custom;\n\n            // Bake/custom/realtime type\n            EditorGUILayout.IntPopup(m_Mode, Styles.reflectionProbeMode, Styles.reflectionProbeModeValues, Styles.typeText);\n\n            // We cannot show multiple different type controls\n            if (!m_Mode.hasMultipleDifferentValues)\n            {\n                EditorGUI.indentLevel++;\n                {\n                    // Custom cubemap UI (Bake button and manual cubemap assignment)\n                    if (EditorGUILayout.BeginFadeGroup(m_ShowProbeModeCustomOptions.faded))\n                    {\n                        EditorGUILayout.PropertyField(m_RenderDynamicObjects, Styles.renderDynamicObjects);\n\n                        EditorGUI.BeginChangeCheck();\n                        EditorGUI.showMixedValue = m_CustomBakedTexture.hasMultipleDifferentValues;\n                        var newCubemap = EditorGUILayout.ObjectField(Styles.customCubemapText, m_CustomBakedTexture.objectReferenceValue, typeof(Texture), false);\n                        EditorGUI.showMixedValue = false;\n                        if (EditorGUI.EndChangeCheck())\n                            m_CustomBakedTexture.objectReferenceValue = newCubemap;\n                    }\n                    EditorGUILayout.EndFadeGroup();\n\n                    // Realtime UI\n                    if (EditorGUILayout.BeginFadeGroup(m_ShowProbeModeRealtimeOptions.faded))\n                    {\n                        EditorGUILayout.PropertyField(m_RefreshMode, Styles.refreshMode);\n                        EditorGUILayout.PropertyField(m_TimeSlicingMode, Styles.timeSlicing);\n\n                        EditorGUILayout.Space();\n                    }\n                    EditorGUILayout.EndFadeGroup();\n                }\n                EditorGUI.indentLevel--;\n            }\n\n            EditorGUILayout.Space();\n\n            m_ShowRuntimeSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_ShowRuntimeSettings.value, Styles.runtimeSettingsHeader);\n\n            if (m_ShowRuntimeSettings.value)\n            {\n                EditorGUI.indentLevel++;\n\n                EditorGUILayout.PropertyField(m_Importance, Styles.importanceText);\n                EditorGUILayout.PropertyField(m_IntensityMultiplier, Styles.intensityText);\n\n                // Only take graphic Tier settings into account when built-in render pipeline is active.\n                if (GraphicsSettings.currentRenderPipeline == null && Rendering.EditorGraphicsSettings.GetCurrentTierSettings().reflectionProbeBoxProjection == false)\n                {\n                    using (new EditorGUI.DisabledScope(true))\n                    {\n                        EditorGUILayout.Toggle(Styles.boxProjectionText, false);\n                    }\n                }\n                else\n                {\n                    EditorGUILayout.PropertyField(m_BoxProjection, Styles.boxProjectionText);\n                }\n\n                bool isDeferredRenderingPath = SceneView.IsUsingDeferredRenderingPath();\n                bool isDeferredReflections = isDeferredRenderingPath && (UnityEngine.Rendering.GraphicsSettings.GetShaderMode(BuiltinShaderType.DeferredReflections) != BuiltinShaderMode.Disabled);\n                using (new EditorGUI.DisabledScope(!isDeferredReflections && !SupportedRenderingFeatures.active.reflectionProbesBlendDistance))\n                {\n                    EditorGUILayout.PropertyField(m_BlendDistance, Styles.blendDistanceText);\n                }\n\n                // Bounds editing (box projection bounds + the bounds that objects use to check if they should be affected by this reflection probe)\n                if (EditorGUILayout.BeginFadeGroup(m_ShowBoxOptions.faded))\n                {\n                    EditorGUI.BeginChangeCheck();\n                    EditorGUILayout.PropertyField(m_BoxSize, Styles.sizeText);\n                    EditorGUILayout.PropertyField(m_BoxOffset, Styles.centerText);\n\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        Vector3 center = m_BoxOffset.vector3Value;\n                        Vector3 size = m_BoxSize.vector3Value;\n                        if (ValidateAABB(ref center, ref size))\n                        {\n                            m_BoxOffset.vector3Value = center;\n                            m_BoxSize.vector3Value = size;\n                        }\n                    }\n                }\n                EditorGUILayout.EndFadeGroup();\n\n                EditorGUI.indentLevel--;\n            }\n            EditorGUILayout.EndFoldoutHeaderGroup();\n\n            m_ShowCubemapCaptureSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_ShowCubemapCaptureSettings.value, Styles.captureCubemapHeader);\n\n            if (m_ShowCubemapCaptureSettings.value)\n            {\n                EditorGUI.indentLevel++;\n\n                int[] reflectionResolutionValuesArray = null;\n                GUIContent[] reflectionResolutionTextArray = null;\n                GetResolutionArray(ref reflectionResolutionValuesArray, ref reflectionResolutionTextArray);\n\n                EditorGUILayout.IntPopup(m_Resolution, reflectionResolutionTextArray, reflectionResolutionValuesArray, Styles.resolutionText, GUILayout.MinWidth(40));\n                EditorGUILayout.PropertyField(m_HDR, Styles.hdrText);\n                EditorGUILayout.PropertyField(m_ShadowDistance, Styles.shadowDistanceText);\n                EditorGUILayout.IntPopup(m_ClearFlags, Styles.clearFlags, Styles.clearFlagsValues, Styles.clearFlagsText);\n                EditorGUILayout.PropertyField(m_BackgroundColor, Styles.backgroundColorText);\n                EditorGUILayout.PropertyField(m_CullingMask, Styles.cullingMaskText);\n                EditorGUILayout.PropertyField(m_UseOcclusionCulling, Styles.useOcclusionCulling);\n                EditorGUILayout.PropertiesField(EditorGUI.s_ClipingPlanesLabel, m_NearAndFarProperties, EditorGUI.s_NearAndFarLabels, EditorGUI.kNearFarLabelsWidth);\n\n                EditorGUI.indentLevel--;\n            }\n            EditorGUILayout.EndFoldoutHeaderGroup();\n\n            EditorGUILayout.Space();\n\n            if (targets.Length == 1)\n            {\n                ReflectionProbe probe = (ReflectionProbe)target;\n                if (probe.mode == ReflectionProbeMode.Custom && probe.customBakedTexture != null)\n                {\n                    Cubemap cubemap = probe.customBakedTexture as Cubemap;\n                    if (cubemap && cubemap.mipmapCount == 1)\n                        EditorGUILayout.HelpBox(\"No mipmaps in the cubemap, Smoothness value in Standard shader will be ignored.\", MessageType.Warning);\n                }\n            }\n\n            DoBakeButton();\n            EditorGUILayout.Space();\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        internal override Bounds GetWorldBoundsOfTarget(Object targetObject)\n        {\n            return ((ReflectionProbe)targetObject).bounds;\n        }\n\n        bool ValidPreviewSetup()\n        {\n            ReflectionProbe p = (ReflectionProbe)target;\n            return (p != null && p.texture != null);\n        }\n\n        void CreateTextureInspector(Texture texture, ref Editor previousEditor)\n        {\n            switch (texture)\n            {\n                case Cubemap _:\n                    Editor.CreateCachedEditor(texture, typeof(CubemapInspector), ref previousEditor);\n                    break;\n                case CustomRenderTexture _:\n                    Editor.CreateCachedEditor(texture, typeof(CustomRenderTextureEditor), ref previousEditor);\n                    break;\n                case RenderTexture _:\n                    Editor.CreateCachedEditor(texture, typeof(RenderTextureEditor), ref previousEditor);\n                    break;\n                default:\n                    Editor.CreateCachedEditor(texture, typeof(TextureInspector), ref previousEditor);\n                    break;\n            }\n        }\n\n        public override bool HasPreviewGUI()\n        {\n            if (targets.Length > 1)\n                return false;  // We only handle one preview for reflection probes\n\n            // Ensure valid cube map editor (if possible)\n            if (ValidPreviewSetup())\n            {\n                Editor editor = m_CubemapEditor;\n                CreateTextureInspector(((ReflectionProbe)target).texture, ref editor);\n                m_CubemapEditor = editor as TextureInspector;\n            }\n\n            // If having one probe selected we always want preview (to prevent preview window from popping)\n            return true;\n        }\n\n        public override void OnPreviewSettings()\n        {\n            if (!ValidPreviewSetup())\n                return;\n\n            m_CubemapEditor.mipLevel = m_MipLevelPreview;\n\n            EditorGUI.BeginChangeCheck();\n            m_CubemapEditor.OnPreviewSettings();\n            // Need to repaint, because mipmap value changes affect reflection probe preview in the scene\n            if (EditorGUI.EndChangeCheck())\n            {\n                EditorApplication.SetSceneRepaintDirty();\n                m_MipLevelPreview = m_CubemapEditor.mipLevel;\n            }\n        }\n\n        public override void OnPreviewGUI(Rect position, GUIStyle style)\n        {\n            // Fix for case 939947 where we didn't get the Layout event if the texture was null when changing color\n            if (!ValidPreviewSetup() && Event.current.type != EventType.ExecuteCommand)\n            {\n                GUILayout.BeginHorizontal();\n                GUILayout.FlexibleSpace();\n                Color prevColor = GUI.color;\n                GUI.color = new Color(1, 1, 1, 0.5f);\n                GUILayout.Label(\"Reflection Probe not baked/ready yet\");\n                GUI.color = prevColor;\n                GUILayout.FlexibleSpace();\n                GUILayout.EndHorizontal();\n                return;\n            }\n\n            ReflectionProbe p = target as ReflectionProbe;\n            if (p != null && p.texture != null && targets.Length == 1)\n            {\n                Editor editor = m_CubemapEditor;\n                CreateTextureInspector(p.texture, ref editor);\n                m_CubemapEditor = editor as TextureInspector;\n            }\n\n            if (m_CubemapEditor != null)\n            {\n                m_CubemapEditor.SetCubemapIntensity(GetProbeIntensity((ReflectionProbe)target));\n                m_CubemapEditor.OnPreviewGUI(position, style);\n            }\n        }\n\n        private static Mesh sphereMesh\n        {\n            get { return s_SphereMesh ?? (s_SphereMesh = Resources.GetBuiltinResource(typeof(Mesh), \"New-Sphere.fbx\") as Mesh); }\n        }\n\n        private Material reflectiveMaterial\n        {\n            get\n            {\n                if (m_ReflectiveMaterial == null)\n                {\n                    m_ReflectiveMaterial = (Material)Instantiate(EditorGUIUtility.Load(\"Previews/PreviewCubemapMaterial.mat\"));\n                    m_ReflectiveMaterial.hideFlags = HideFlags.HideAndDontSave;\n                }\n                return m_ReflectiveMaterial;\n            }\n        }\n\n        private float GetProbeIntensity(ReflectionProbe p)\n        {\n            if (p == null || p.texture == null)\n                return 1.0f;\n\n            float intensity = p.intensity;\n            if (TextureUtil.GetTextureColorSpaceString(p.texture) == \"Linear\")\n                intensity = Mathf.LinearToGammaSpace(intensity);\n            return intensity;\n        }\n\n        // Draw Reflection probe preview sphere\n        private void OnPreSceneGUICallback(SceneView sceneView)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            foreach (var t in targets)\n            {\n                ReflectionProbe p = (ReflectionProbe)t;\n                if (!reflectiveMaterial)\n                    return;\n\n                if (StageUtility.IsGizmoCulledBySceneCullingMasksOrFocusedScene(p.gameObject, Camera.current))\n                    return;\n\n                Matrix4x4 m = new Matrix4x4();\n\n                // @TODO: use MaterialPropertyBlock instead - once it actually works!\n                // Tried to use MaterialPropertyBlock in 5.4.0b2, but would get incorrectly set parameters when using with Graphics.DrawMesh\n                if (!m_CachedGizmoMaterials.ContainsKey(p))\n                    m_CachedGizmoMaterials.Add(p, Instantiate(reflectiveMaterial));\n\n                Material mat = m_CachedGizmoMaterials[p] as Material;\n                if (!mat)\n                    return;\n                {\n                    // Get mip level\n                    float mipLevel = 0.0F;\n                    TextureInspector cubemapEditor = m_CubemapEditor;\n                    if (cubemapEditor)\n                        mipLevel = cubemapEditor.GetMipLevelForRendering();\n\n                    mat.SetTexture(\"_MainTex\", p.texture);\n                    mat.SetMatrix(\"_CubemapRotation\", Matrix4x4.identity);\n                    mat.SetFloat(\"_Mip\", mipLevel);\n                    mat.SetFloat(\"_Alpha\", 0.0f);\n                    mat.SetFloat(\"_Intensity\", GetProbeIntensity(p));\n                    mat.SetVector(\"_MainTex_HDR\", p.textureHDRDecodeValues);\n\n                    if (PlayerSettings.colorSpace == ColorSpace.Linear)\n                    {\n                        mat.SetInt(\"_ColorspaceIsGamma\", 0);\n                    }\n                    else\n                    {\n                        mat.SetInt(\"_ColorspaceIsGamma\", 1);\n                    }\n\n                    // draw a preview sphere that scales with overall GO scale, but always uniformly\n                    var scale = p.transform.lossyScale.magnitude * 0.5f;\n                    m.SetTRS(p.transform.position, Quaternion.identity, new Vector3(scale, scale, scale));\n                    Graphics.DrawMesh(sphereMesh, m, mat, 0, SceneView.currentDrawingSceneView.camera, 0);\n                }\n            }\n        }\n\n        // Ensures that probe's AABB encapsulates probe's position\n        // Returns true, if center or size was modified\n        private bool ValidateAABB(ref Vector3 center, ref Vector3 size)\n        {\n            ReflectionProbe p = (ReflectionProbe)target;\n\n            Matrix4x4 localSpace = GetLocalSpace(p);\n            Vector3 localTransformPosition = localSpace.inverse.MultiplyPoint3x4(p.transform.position);\n\n            Bounds b = new Bounds(center, size);\n\n            if (b.Contains(localTransformPosition)) return false;\n\n            b.Encapsulate(localTransformPosition);\n\n            center = b.center;\n            size = b.size;\n            return true;\n        }\n\n        [DrawGizmo(GizmoType.Active)]\n        static void RenderBoxGizmo(ReflectionProbe reflectionProbe, GizmoType gizmoType)\n        {\n            if (s_LastInteractedEditor == null)\n                return;\n\n            if (s_LastInteractedEditor.sceneViewEditing && EditMode.editMode == EditMode.SceneViewEditMode.ReflectionProbeBox)\n            {\n                Color oldColor = Gizmos.color;\n                Gizmos.color = kGizmoReflectionProbe;\n\n                Gizmos.matrix = GetLocalSpace(reflectionProbe);\n                Gizmos.DrawCube(reflectionProbe.center, -1f * reflectionProbe.size);\n                Gizmos.matrix = Matrix4x4.identity;\n                Gizmos.color = oldColor;\n            }\n        }\n\n        [DrawGizmo(GizmoType.Selected)]\n        static void RenderBoxOutline(ReflectionProbe reflectionProbe, GizmoType gizmoType)\n        {\n            if (!s_CurrentlyEditedProbes.Contains(reflectionProbe))\n                return;\n\n            Color oldColor = Gizmos.color;\n            Gizmos.color = reflectionProbe.isActiveAndEnabled ? kGizmoReflectionProbe : kGizmoReflectionProbeDisabled;\n\n            Gizmos.matrix = GetLocalSpace(reflectionProbe);\n            Gizmos.DrawWireCube(reflectionProbe.center, reflectionProbe.size);\n            Gizmos.matrix = Matrix4x4.identity;\n            Gizmos.color = oldColor;\n        }\n\n        public static bool IsSceneGUIEnabled()\n        {\n            return IsReflectionProbeEditMode(EditMode.editMode);\n        }\n\n        public void OnSceneGUI()\n        {\n            if (!sceneViewEditing)\n                return;\n\n            switch (EditMode.editMode)\n            {\n                case EditMode.SceneViewEditMode.ReflectionProbeBox:\n                    DoBoxEditing();\n                    break;\n                case EditMode.SceneViewEditMode.ReflectionProbeOrigin:\n                    DoOriginEditing();\n                    break;\n            }\n        }\n\n        void UpdateOldLocalSpace()\n        {\n            m_OldLocalSpace = GetLocalSpace((ReflectionProbe)target);\n        }\n\n        void DoOriginEditing()\n        {\n            ReflectionProbe p = (ReflectionProbe)target;\n            Vector3 transformPosition = p.transform.position;\n            Vector3 size = p.size;\n\n            EditorGUI.BeginChangeCheck();\n            Vector3 newPostion = Handles.PositionHandle(transformPosition, GetLocalSpaceRotation(p));\n\n            bool changed = EditorGUI.EndChangeCheck();\n\n            if (changed || m_OldLocalSpace != GetLocalSpace((ReflectionProbe)target))\n            {\n                Vector3 localNewPosition = m_OldLocalSpace.inverse.MultiplyPoint3x4(newPostion);\n\n                Bounds b = new Bounds(p.center, size);\n                localNewPosition = b.ClosestPoint(localNewPosition);\n\n                Undo.RecordObject(p.transform, \"Modified Reflection Probe Origin\");\n                p.transform.position = m_OldLocalSpace.MultiplyPoint3x4(localNewPosition);\n\n                Undo.RecordObject(p, \"Modified Reflection Probe Origin\");\n                p.center = GetLocalSpace(p).inverse.MultiplyPoint3x4(m_OldLocalSpace.MultiplyPoint3x4(p.center));\n\n                EditorUtility.SetDirty(target);\n\n                UpdateOldLocalSpace();\n            }\n        }\n\n        static Matrix4x4 GetLocalSpace(ReflectionProbe probe)\n        {\n            Vector3 t = probe.transform.position;\n            return Matrix4x4.TRS(t, GetLocalSpaceRotation(probe), Vector3.one);\n        }\n\n        static Quaternion GetLocalSpaceRotation(ReflectionProbe probe)\n        {\n            bool supportsRotation = (SupportedRenderingFeatures.active.reflectionProbeModes & SupportedRenderingFeatures.ReflectionProbeModes.Rotation) != 0;\n            if (supportsRotation)\n                return probe.transform.rotation;\n            else\n                return Quaternion.identity;\n        }\n\n        void DoBoxEditing()\n        {\n            // Drawing of the probe box is done from GizmoDrawers.cpp,\n            // here we only want to show the box editing handles when needed.\n            ReflectionProbe p = (ReflectionProbe)target;\n\n            using (new Handles.DrawingScope(GetLocalSpace(p)))\n            {\n                m_BoundsHandle.center = p.center;\n                m_BoundsHandle.size = p.size;\n\n                EditorGUI.BeginChangeCheck();\n                m_BoundsHandle.DrawHandle();\n                if (EditorGUI.EndChangeCheck())\n                {\n                    Undo.RecordObject(p, \"Modified Reflection Probe AABB\");\n                    Vector3 center = m_BoundsHandle.center;\n                    Vector3 size = m_BoundsHandle.size;\n                    ValidateAABB(ref center, ref size);\n                    p.center = center;\n                    p.size = size;\n                    EditorUtility.SetDirty(target);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/RenderPipelineAssetSelector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    /// <summary>\n    /// Provides a display for a <see cref=\"EditorGUI.ObjectField\"/> and prompts the user to confirm the change.\n    /// </summary>\n    public sealed partial class EditorGUI\n    {\n        static class RenderPipelineAssetSelectorStyles\n        {\n            public static readonly GUIContent renderPipeLabel = EditorGUIUtility.TrTextContent(\"Scriptable Render Pipeline\");\n\n            public static string renderPipeChangedWarning => LocalizationDatabase.GetLocalizedString(\"Changing this render pipeline asset may take a significant amount of time.\");\n            public static string renderPipeChangedTitleBox => LocalizationDatabase.GetLocalizedString(\"Changing Render Pipeline\");\n            public static string renderPipeChangedConfirmation => LocalizationDatabase.GetLocalizedString(\"Continue\");\n            public static string cancelLabel => LocalizationDatabase.GetLocalizedString(\"Cancel\");\n        }\n\n        static void PromptConfirmation(SerializedObject serializedObject, SerializedProperty serializedProperty, Object selectedRenderPipelineAsset)\n        {\n            if (selectedRenderPipelineAsset == serializedProperty.objectReferenceValue)\n                return;\n\n            if (EditorUtility.DisplayDialog(RenderPipelineAssetSelectorStyles.renderPipeChangedTitleBox, RenderPipelineAssetSelectorStyles.renderPipeChangedWarning, RenderPipelineAssetSelectorStyles.renderPipeChangedConfirmation, RenderPipelineAssetSelectorStyles.cancelLabel))\n            {\n                serializedProperty.objectReferenceValue = selectedRenderPipelineAsset;\n                serializedObject.ApplyModifiedProperties();\n            }\n        }\n\n        /// <summary>\n        /// Draws the object field and, if the user attempts to change the value, asks the user for confirmation.\n        /// </summary>\n        /// <param name=\"content\">The label.</param>\n        /// <param name=\"serializedObject\">The <see cref=\"SerializedObject\"/> that holds the <see cref=\"SerializedProperty\"/> with the new render pipeline asset.</param>\n        /// <param name=\"serializedProperty\">The <see cref=\"SerializedProperty\"/> to modify with the new render pipeline asset.</param>\n        internal static void RenderPipelineAssetField(GUIContent content, SerializedObject serializedObject, SerializedProperty serializedProperty)\n        {\n            using (new EditorGUILayout.HorizontalScope())\n            {\n                EditorGUILayout.PrefixLabel(content);\n                RenderPipelineAssetField(serializedObject, serializedProperty);\n            }\n        }\n\n        private static bool s_ObjectSelectorClosed = false;\n        private static Object s_LastPickedObject = null;\n\n        /// <summary>\n        /// Draws the object field and, if the user attempts to change the value, asks the user for confirmation.\n        /// </summary>\n        /// <param name=\"serializedObject\">The <see cref=\"SerializedObject\"/> that holds the <see cref=\"SerializedProperty\"/> with the new render pipeline asset.</param>\n        /// <param name=\"serializedProperty\">The <see cref=\"SerializedProperty\"/> to modify with the new render pipeline asset.</param>\n        internal static void RenderPipelineAssetField(SerializedObject serializedObject, SerializedProperty serializedProperty)\n        {\n            Rect renderLoopRect = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(serializedProperty));\n\n            EditorGUI.BeginProperty(renderLoopRect, RenderPipelineAssetSelectorStyles.renderPipeLabel, serializedProperty);\n\n            int id = GUIUtility.GetControlID(s_ObjectFieldHash, FocusType.Keyboard, renderLoopRect);\n\n            var selectedRenderPipelineAsset = DoObjectField(\n                position: IndentedRect(renderLoopRect),\n                dropRect: IndentedRect(renderLoopRect),\n                id: id,\n                obj: serializedProperty.objectReferenceValue,\n                objBeingEdited: null,\n                objType: typeof(RenderPipelineAsset),\n                additionalType: null,\n                property: null,\n                validator: null,\n                allowSceneObjects: false,\n                style: EditorStyles.objectField,\n                onObjectSelectorClosed: obj =>\n                {\n                    if (ObjectSelector.SelectionCanceled()) return;\n                    s_ObjectSelectorClosed = true;\n                    s_LastPickedObject = obj;\n                });\n\n            if (s_ObjectSelectorClosed)\n            {\n                s_ObjectSelectorClosed = false;\n                PromptConfirmation(serializedObject, serializedProperty, s_LastPickedObject);\n            }\n            else if (!ObjectSelector.isVisible) // Drag and drop\n            {\n                PromptConfirmation(serializedObject, serializedProperty, selectedRenderPipelineAsset);\n            }\n\n            EditorGUI.EndProperty();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/RenderPipelineEditorUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEngine;\nusing UnityEngine.Pool;\nusing UnityEngine.Rendering;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor.Rendering\n{\n    public static class RenderPipelineEditorUtility\n    {\n        public static Type[] GetDerivedTypesSupportedOnCurrentPipeline<T>()\n        {\n            return TypeCache.GetTypesDerivedFrom<T>()\n                .Where(t => t.GetCustomAttribute<SupportedOnRenderPipelineAttribute>() is { isSupportedOnCurrentPipeline: true })\n                .ToArray();\n        }\n\n        [Obsolete($\"{nameof(FetchFirstCompatibleTypeUsingScriptableRenderPipelineExtension)} is deprecated. Use {nameof(GetDerivedTypesSupportedOnCurrentPipeline)} instead. #from(2023.1)\", false)]\n        public static Type FetchFirstCompatibleTypeUsingScriptableRenderPipelineExtension<TBaseClass>()\n        {\n            var extensionTypes = TypeCache.GetTypesDerivedFrom<TBaseClass>();\n\n            foreach (Type extensionType in extensionTypes)\n            {\n#pragma warning disable CS0618\n                if (Attribute.GetCustomAttribute(extensionType, typeof(ScriptableRenderPipelineExtensionAttribute)) is ScriptableRenderPipelineExtensionAttribute { inUse: true })\n                    return extensionType;\n#pragma warning restore CS0618\n            }\n\n            return null;\n        }\n\n        private static Dictionary<Type, Type> s_RenderPipelineAssetToRenderPipelineType = new();\n\n        public static Type GetPipelineTypeFromPipelineAssetType(Type pipelineAssetType)\n        {\n            if (!typeof(RenderPipelineAsset).IsAssignableFrom(pipelineAssetType))\n                return null;\n\n            if (s_RenderPipelineAssetToRenderPipelineType.TryGetValue(pipelineAssetType, out var pipelineType))\n                return pipelineType;\n\n            Type baseGenericType = pipelineAssetType;\n            while (baseGenericType != null)\n            {\n                if (!baseGenericType.IsGenericType || baseGenericType.GetGenericTypeDefinition() != typeof(RenderPipelineAsset<>))\n                {\n                    baseGenericType = baseGenericType.BaseType;\n                    continue;\n                }\n\n                pipelineType = baseGenericType.GetGenericArguments()[0];\n                s_RenderPipelineAssetToRenderPipelineType[pipelineAssetType] = pipelineType;\n                return pipelineType;\n            }\n\n            var pipelineAsset = ScriptableObject.CreateInstance(pipelineAssetType) as RenderPipelineAsset;\n            pipelineType = pipelineAsset.pipelineType;\n            Object.DestroyImmediate(pipelineAsset);\n            s_RenderPipelineAssetToRenderPipelineType[pipelineAssetType] = pipelineType;\n            return pipelineType;\n        }\n\n        public static bool TrySetRenderingLayerName(int index, string name)\n            => TagManager.Internal_TrySetRenderingLayerName(index, name);\n\n        public static bool TryAddRenderingLayerName(string name)\n            => TagManager.Internal_TryAddRenderingLayerName(name);\n\n        public static bool TryRemoveLastRenderingLayerName()\n            => TagManager.Internal_TryRemoveLastRenderingLayerName();\n\n        public static Action onRenderingLayerCountChanged;\n\n        /// <summary>\n        /// Retrieves the maximum number of rendering layers supported by the currently active render pipeline.\n        /// </summary>\n        /// <returns>The maximum number of supported rendering layers, or the default maximum if no specific setting is found.</returns>\n        internal static int GetActiveMaxRenderingLayers()\n        {\n            if (EditorGraphicsSettings.TryGetRenderPipelineSettingsFromInterface<RenderingLayersLimitSettings>(out var settings)\n                && settings.Length != 0)\n                return settings[0].maxSupportedRenderingLayers;\n            return RenderingLayerMask.maxRenderingLayerSize;\n        }\n\n        /// <summary>\n        /// Gathers the maximum number of rendering layers supported by all configured render pipelines in the graphics settings.\n        /// </summary>\n        /// <returns>A list of tuples, each containing the maximum number of rendering layers and the name of the corresponding render pipeline type.</returns>\n        internal static List<(int, string)> GetMaxRenderingLayersFromSettings()\n        {\n            using var hashset = HashSetPool<Type>.Get(out var types);\n\n            var result = new List<(int, string)>();\n            var renderPipelineAssets = GraphicsSettings.allConfiguredRenderPipelines;\n            foreach (var renderPipelineAsset in renderPipelineAssets)\n            {\n                var pipelineType = GetPipelineTypeFromPipelineAssetType(renderPipelineAsset.GetType());\n                if (pipelineType == null || types.Contains(pipelineType))\n                    continue;\n\n                if (!EditorGraphicsSettings.TryGetRenderPipelineSettingsFromInterfaceForPipeline<RenderingLayersLimitSettings>(pipelineType, out var settings))\n                    continue;\n\n                if (settings.Length == 0)\n                    continue;\n\n                types.Add(pipelineType);\n                result.Add((settings[0].maxSupportedRenderingLayers, renderPipelineAsset.pipelineType.Name));\n            }\n\n            return result;\n        }\n\n        /// <summary>\n        /// Get names and values for the Rendering Layer Mask dropdown.\n        /// </summary>\n        /// <param name=\"currentMask\">Current mask value.</param>\n        /// <returns>Names and values lists corresponding to the requirements from active Render Pipeline and selected Mask</returns>\n        internal static (string[], int[]) GetRenderingLayerNamesAndValuesForMask(uint currentMask)\n        {\n            var names = RenderingLayerMask.GetDefinedRenderingLayerNames();\n            var values = RenderingLayerMask.GetDefinedRenderingLayerValues();\n\n            var currentMax = GetActiveMaxRenderingLayers();\n            var isMaskEverything = currentMask == uint.MaxValue;\n            var remainingMaskForUnnamedLayers = CalculateMaskOutsideOfDefinedLayers(currentMask, isMaskEverything, values);\n\n            if (currentMax < RenderingLayerMask.maxRenderingLayerSize || remainingMaskForUnnamedLayers != 0)\n                (names, values) = ApplyRPLimitAndUnnamedLayers(currentMask, remainingMaskForUnnamedLayers, names, values, currentMax, isMaskEverything);\n\n            return (names, values);\n        }\n\n        /// <summary>\n        /// Apply Rendering Pipeline limit and add used unnamed layers to the dropdown options.\n        /// </summary>\n        /// <param name=\"currentMask\">Current selected mask.</param>\n        /// <param name=\"remainingMaskForUnnamedLayers\">Mask value for unnamed layers extracted from the current selected mask.</param>\n        /// <param name=\"names\">List of defined names in Tags&Layers.</param>\n        /// <param name=\"values\">List of values that correspond to the names in Tags&Layers.</param>\n        /// <param name=\"currentMax\">Limit of Layers used by active Render Pipeline</param>\n        /// <param name=\"isMaskEverything\">True if current mask is everything.</param>\n        /// <returns>Modified names and values that includes selected unnamed layers cropped by limit of the active Render Pipeline.</returns>\n        static (string[], int[]) ApplyRPLimitAndUnnamedLayers(uint currentMask, uint remainingMaskForUnnamedLayers,\n            string[] names, int[] values, int currentMax, bool isMaskEverything)\n        {\n            {\n                using var namesPooledObject = ListPool<string>.Get(out var namesList);\n                using var valuesPooledObject = ListPool<int>.Get(out var valuesList);\n\n                // Add defined Layers to the dropdown options if they are selected or if there's no RP limit\n                var maxIndex = BitOperationUtils.BitCountToIndex(currentMax);\n                for (int i = 0; i < values.Length; i++)\n                {\n                    var valueUint = unchecked((uint)values[i]);\n                    if (BitOperationUtils.IsValueSmallerOrEqualThanIndex(valueUint, maxIndex) ||\n                        IsLayerSelected(valueUint))\n                    {\n                        namesList.Add(names[i]);\n                        valuesList.Add(values[i]);\n                    }\n                }\n\n                // Add used unnamed Layers to the dropdown options\n                if (remainingMaskForUnnamedLayers == 0)\n                    return (namesList.ToArray(), valuesList.ToArray());\n\n                using var listOfUnnamedBitsPooledObject = ListPool<int>.Get(out var listOfUnnamedBits);\n\n                ConvertUsedUnnamedLayersValuesToLayerIndexes(remainingMaskForUnnamedLayers, listOfUnnamedBits);\n                for (int i = 0; i < listOfUnnamedBits.Count; i++)\n                {\n                    //find an index of the next value that is greater than the current unnamed bit\n                    var index = listOfUnnamedBits[i];\n                    var indexOfTheNextValue = NextIndexInTheArray(index, valuesList);\n\n                    //insert\n                    namesList.Insert(indexOfTheNextValue, $\"Unnamed Layer {index}\");\n                    valuesList.Insert(indexOfTheNextValue, unchecked((int)BitOperationUtils.IndexToValue(index)));\n                }\n\n                return (namesList.ToArray(), valuesList.ToArray());\n            }\n\n            bool IsLayerSelected(uint valueUint)\n            {\n                return !isMaskEverything && BitOperationUtils.AnyBitMatch(valueUint, currentMask);\n            }\n        }\n\n        /// <summary>\n        /// Find an index of the next value that is greater than the bit.\n        /// </summary>\n        /// <param name=\"layerIndex\">Index of the current bit.</param>\n        /// <param name=\"valuesList\">Current list of values.</param>\n        /// <returns></returns>\n        static int NextIndexInTheArray(int layerIndex, List<int> valuesList)\n        {\n            var indexOfTheNextValue = valuesList.FindIndex(currentValue =>\n                BitOperationUtils.IsValueBiggerThanIndex(unchecked((uint)currentValue), layerIndex));\n            if (indexOfTheNextValue == -1)\n                indexOfTheNextValue = valuesList.Count;\n            return indexOfTheNextValue;\n        }\n\n        /// <summary>\n        /// Convert used unnamed layers from mask value to layer indexes.\n        /// </summary>\n        /// <param name=\"remainingMaskForUnnamedLayers\">Mask value for unnamed layers.</param>\n        /// <param name=\"listOfUnnamedBits\">List of indexes of used unnamed layers.</param>\n        static void ConvertUsedUnnamedLayersValuesToLayerIndexes(uint remainingMaskForUnnamedLayers, List<int> listOfUnnamedBits)\n        {\n            for (int i = 0; i < RenderingLayerMask.maxRenderingLayerSize; i++)\n            {\n                if (BitOperationUtils.AnyBitMatch(remainingMaskForUnnamedLayers, BitOperationUtils.IndexToValue(i)))\n                    listOfUnnamedBits.Add(i);\n            }\n        }\n\n        /// <summary>\n        /// Calculate mask value for unnamed layers if the mask is not full.\n        /// </summary>\n        /// <param name=\"currentMask\">Specify current mask.</param>\n        /// <param name=\"isMaskEverything\">Specify if current mask is Everything.</param>\n        /// <param name=\"values\">All named values for Layers in the Tags&Layers.</param>\n        /// <returns>Returns 0u if Mask is full or remaining mask after excluding all named values from current Mask.</returns>\n        static uint CalculateMaskOutsideOfDefinedLayers(uint currentMask, bool isMaskEverything, int[] values)\n        {\n            var remainingMask = 0u;\n            if (isMaskEverything)\n                return remainingMask;\n\n            remainingMask = currentMask;\n            for (int i = 0; i < values.Length; i++)\n            {\n                uint valueUint = unchecked((uint)values[i]);\n                if (BitOperationUtils.AnyBitMatch(currentMask, valueUint))\n                    remainingMask &= ~valueUint;\n            }\n\n            return remainingMask;\n        }\n\n        /// <summary>\n        /// Checks if a rendering layer mask contains layer bits set outside the maximum allowed bit count.\n        /// </summary>\n        /// <param name=\"mask\">The rendering layer mask to check.</param>\n        /// <param name=\"bitCount\">The maximum bit count allowed for rendering layers.</param>\n        /// <returns>A boolean indicating whether the mask includes layer bits beyond the specified maximum.</returns>\n        internal static bool DoesMaskContainRenderingLayersOutsideOfMaxBitCount(uint mask, int bitCount) =>\n            bitCount != RenderingLayerMask.maxRenderingLayerSize && mask != uint.MaxValue && BitOperationUtils.IsValueBiggerOrEqualThanIndex(mask, bitCount);\n\n        /// <summary>\n        /// Constructs a warning message indicating that a rendering layer mask contains layers exceeding the supported range of the active Render Pipeline.\n        /// </summary>\n        /// <param name=\"bitCount\">The maximum number of layer bits supported by the active Render Pipeline.</param>\n        /// <returns>A string with the warning message about layers beyond the supported bit count being ignored.</returns>\n        internal static string GetOutsideOfMaxBitCountWarningMessage(int bitCount) =>\n            $\"Current mask contains layers outside of a supported range by active Render Pipeline. The active Render Pipeline only supports up to {bitCount} layers. Rendering Layers above {bitCount} are ignored.\";\n\n        internal static bool SupportPreview(Camera camera, out string reason)\n        {\n            if (!RenderPipelineManager.isCurrentPipelineValid)\n            {\n                //Thus we are in Built-in Render Pipeline. Preview are supported here.\n                if (camera == null || camera.Equals(null))\n                {\n                    reason = \"Camera is null\";\n                    return false;\n                }\n                reason = null;\n                return true;\n            }\n\n            return RenderPipelineManager.currentPipeline.IsPreviewSupported(camera, out reason);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/RenderSettingsInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.AnimatedValues;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(RenderSettings))]\n    internal class RenderSettingsInspector : Editor\n    {\n        Editor m_LightingEditor;\n        Editor lightingEditor\n        {\n            get { return m_LightingEditor ?? (m_LightingEditor = Editor.CreateEditor(target, typeof(LightingEditor))); }\n        }\n\n\n        Editor m_FogEditor;\n        Editor fogEditor\n        {\n            get { return m_FogEditor ?? (m_FogEditor = Editor.CreateEditor(target, typeof(FogEditor))); }\n        }\n\n        Editor m_OtherRenderingEditor;\n        Editor otherRenderingEditor\n        {\n            get { return m_OtherRenderingEditor ?? (m_OtherRenderingEditor = Editor.CreateEditor(target, typeof(OtherRenderingEditor))); }\n        }\n\n        public virtual void OnEnable()\n        {\n            m_LightingEditor = null;\n            m_FogEditor = null;\n            m_OtherRenderingEditor = null;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            lightingEditor.OnInspectorGUI();\n            fogEditor.OnInspectorGUI();\n            otherRenderingEditor.OnInspectorGUI();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/RenderTextureEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing UnityEngine.Experimental.Rendering;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(RenderTexture))]\n    [CanEditMultipleObjects]\n    internal class RenderTextureEditor : TextureInspector\n    {\n        private int m_RepaintDelay = 0;\n\n        private class Styles\n        {\n            public readonly GUIContent size = EditorGUIUtility.TrTextContent(\"Size\", \"Size of the render texture in pixels.\");\n            public readonly GUIContent cross = EditorGUIUtility.TextContent(\"x\");\n            public readonly GUIContent antiAliasing = EditorGUIUtility.TrTextContent(\"Anti-aliasing\", \"Number of anti-aliasing samples.\");\n            public readonly GUIContent colorFormat = EditorGUIUtility.TrTextContent(\"Color Format\", \"Format of the color buffer.\");\n            public readonly GUIContent depthStencilFormat = EditorGUIUtility.TrTextContent(\"Depth Stencil Format\", \"Format of the depth stencil buffer.\");\n            public readonly GUIContent enableCompatibleFormat = EditorGUIUtility.TrTextContent(\"Enable Compatible Format\", \"Lets the color and depth stencil formats be changed to compatible and supported formats for the target platform automatically, if the target platform doesn't support the input format.\");\n            public readonly GUIContent dimension = EditorGUIUtility.TrTextContent(\"Dimension\", \"Is the texture 2D, Cube or 3D?\");\n            public readonly GUIContent enableMipmaps = EditorGUIUtility.TrTextContent(\"Mipmap\", \"This render texture will have a mipmap.\");\n            public readonly GUIContent autoGeneratesMipmaps = EditorGUIUtility.TrTextContent(\"Auto-generate\", \"This render texture automatically generate its mipmap.\");\n            public readonly GUIContent useDynamicScale = EditorGUIUtility.TrTextContent(\"Dynamic Scaling\", \"Allow the texture to be automatically resized by ScalableBufferManager, to support dynamic resolution.\");\n            public readonly GUIContent enableRandomWrite = EditorGUIUtility.TrTextContent(\"Random Write\", \"Enable/disable random access write into the color buffer of this render texture.\");\n            public readonly GUIContent shadowSamplingMode = EditorGUIUtility.TrTextContent(\"Shadow Sampling Mode\", \"Enable/disable shadow depth-compare sampling and percentage closer filtering.\");\n\n            public readonly GUIContent[] renderTextureAntiAliasing =\n            {\n                EditorGUIUtility.TrTextContent(\"None\"),\n                EditorGUIUtility.TrTextContent(\"2 samples\"),\n                EditorGUIUtility.TrTextContent(\"4 samples\"),\n                EditorGUIUtility.TrTextContent(\"8 samples\")\n            };\n            public readonly int[] renderTextureAntiAliasingValues = { 1, 2, 4, 8 };\n\n            public readonly GUIContent[] dimensionStrings = { EditorGUIUtility.TextContent(\"2D\"), EditorGUIUtility.TextContent(\"2D Array\"), EditorGUIUtility.TrTextContent(\"Cube\"), EditorGUIUtility.TrTextContent(\"3D\") };\n            public readonly int[] dimensionValues = { (int)UnityEngine.Rendering.TextureDimension.Tex2D, (int)UnityEngine.Rendering.TextureDimension.Tex2DArray, (int)UnityEngine.Rendering.TextureDimension.Cube, (int)UnityEngine.Rendering.TextureDimension.Tex3D };\n        }\n\n        static Styles s_Styles = null;\n        private static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } }\n\n\n        [Flags]\n        protected enum GUIElements\n        {\n            RenderTargetNoneGUI = 0,\n            RenderTargetDepthGUI = 1 << 1,\n            RenderTargetAAGUI = 1 << 2\n        }\n\n        const GUIElements s_AllGUIElements = GUIElements.RenderTargetDepthGUI | GUIElements.RenderTargetAAGUI;\n\n        SerializedProperty m_Width;\n        SerializedProperty m_Height;\n        SerializedProperty m_Depth;\n        SerializedProperty m_ColorFormat;\n        SerializedProperty m_DepthStencilFormat;\n        SerializedProperty m_EnableCompatibleFormat;\n        SerializedProperty m_AntiAliasing;\n        SerializedProperty m_EnableMipmaps;\n        SerializedProperty m_AutoGeneratesMipmaps;\n        SerializedProperty m_Dimension;\n        SerializedProperty m_sRGB;\n        SerializedProperty m_UseDynamicScale;\n        SerializedProperty m_EnableRandomWrite;\n        SerializedProperty m_ShadowSamplingMode;\n\n        protected override void OnEnable()\n        {\n            base.OnEnable();\n            m_Width = serializedObject.FindProperty(\"m_Width\");\n            m_Height = serializedObject.FindProperty(\"m_Height\");\n            m_Depth = serializedObject.FindProperty(\"m_VolumeDepth\");\n            m_AntiAliasing = serializedObject.FindProperty(\"m_AntiAliasing\");\n            m_ColorFormat = serializedObject.FindProperty(\"m_ColorFormat\");\n            m_DepthStencilFormat = serializedObject.FindProperty(\"m_DepthStencilFormat\");\n            m_EnableCompatibleFormat = serializedObject.FindProperty(\"m_EnableCompatibleFormat\");\n            m_EnableMipmaps = serializedObject.FindProperty(\"m_MipMap\");\n            m_AutoGeneratesMipmaps = serializedObject.FindProperty(\"m_GenerateMips\");\n            m_Dimension = serializedObject.FindProperty(\"m_Dimension\");\n            m_sRGB = serializedObject.FindProperty(\"m_SRGB\");\n            m_UseDynamicScale = serializedObject.FindProperty(\"m_UseDynamicScale\");\n            m_EnableRandomWrite = serializedObject.FindProperty(\"m_EnableRandomWrite\");\n            m_ShadowSamplingMode = serializedObject.FindProperty(\"m_ShadowSamplingMode\");\n\n            Undo.undoRedoEvent += OnUndoRedoPerformed;\n        }\n\n        protected override void OnDisable()\n        {\n            base.OnDisable();\n\n            Undo.undoRedoEvent -= OnUndoRedoPerformed;\n        }\n\n        private void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            var rt = target as RenderTexture;\n            if (rt != null)\n            {\n                rt.Release();\n            }\n        }\n\n        protected void OnRenderTextureGUI(GUIElements guiElements)\n        {\n            GUI.changed = false;\n\n            EditorGUILayout.IntPopup(m_Dimension, styles.dimensionStrings, styles.dimensionValues, styles.dimension);\n\n            // Note that TextureInspector.IsTexture3D/Cube/2DArray/etc. exist. Those functions will use the actual target object to determine the dimension.\n            // This because they are drawing preview settings based on the selected target objects.\n            // Here we are drawing the one and only Render Texture GUI so we have the dimension field as most correct value.\n            bool isTexture3D = (m_Dimension.intValue == (int)UnityEngine.Rendering.TextureDimension.Tex3D);\n            bool isTexture2DArray = (m_Dimension.intValue == (int)UnityEngine.Rendering.TextureDimension.Tex2DArray);\n\n            GUILayout.BeginHorizontal();\n            EditorGUILayout.PrefixLabel(styles.size, EditorStyles.popup);\n            EditorGUILayout.DelayedIntField(m_Width, GUIContent.none, GUILayout.MinWidth(40));\n            GUILayout.Label(styles.cross);\n            EditorGUILayout.DelayedIntField(m_Height, GUIContent.none, GUILayout.MinWidth(40));\n            if (isTexture3D || isTexture2DArray)\n            {\n                GUILayout.Label(styles.cross);\n                EditorGUILayout.DelayedIntField(m_Depth, GUIContent.none, GUILayout.MinWidth(40));\n            }\n            GUILayout.FlexibleSpace();\n            GUILayout.EndHorizontal();\n\n            if ((guiElements & GUIElements.RenderTargetAAGUI) != 0)\n                EditorGUILayout.IntPopup(m_AntiAliasing, styles.renderTextureAntiAliasing, styles.renderTextureAntiAliasingValues, styles.antiAliasing);\n\n            GraphicsFormat colorFormat = (GraphicsFormat)m_ColorFormat.intValue;\n            GraphicsFormat compatibleColorFormat = SystemInfo.GetCompatibleFormat(colorFormat, GraphicsFormatUsage.Render);\n\n            GraphicsFormat depthStencilFormat = (GraphicsFormat)m_DepthStencilFormat.intValue;\n            bool isDepthStencilUnused = depthStencilFormat == GraphicsFormat.None;\n            bool isDepthStencilFormatIncompatible = !isDepthStencilUnused && SystemInfo.GetCompatibleFormat(depthStencilFormat, GraphicsFormatUsage.Render) == GraphicsFormat.None;\n            GraphicsFormat compatibleDepthStencilFormat = (isDepthStencilUnused) ? GraphicsFormat.None :\n                GraphicsFormatUtility.GetDepthStencilFormat(GraphicsFormatUtility.GetDepthBits(depthStencilFormat), (GraphicsFormatUtility.IsStencilFormat(depthStencilFormat)) ? 8 : 0);\n\n            // If no fallbacks are found for the color AND depth stencil buffer, disable the EnableCompatibleFormat field\n            // If only one of the two fails, checkbox can still be interacted with\n            if (!(compatibleColorFormat == GraphicsFormat.None && compatibleDepthStencilFormat == GraphicsFormat.None))\n            {\n                EditorGUILayout.PropertyField(m_EnableCompatibleFormat, styles.enableCompatibleFormat);\n            }\n\n            EditorGUILayout.PropertyField(m_ColorFormat, styles.colorFormat);\n            m_sRGB.boolValue = GraphicsFormatUtility.IsSRGBFormat((GraphicsFormat)m_ColorFormat.intValue);\n\n            if (compatibleColorFormat != colorFormat)\n            {\n                string text = string.Format(\"Format {0} is not supported on this platform. \", colorFormat.ToString());\n                if (compatibleColorFormat != GraphicsFormat.None)\n                {\n                    if (m_EnableCompatibleFormat.boolValue)\n                        text += string.Format(\"Using {0} as a compatible format.\", compatibleColorFormat.ToString());\n                    else\n                        text += string.Format(\"You may enable Compatible Format to fallback automatically to a platform specific compatible format, {0} on this device.\", compatibleColorFormat.ToString());\n                }\n                EditorGUILayout.HelpBox(text, m_EnableCompatibleFormat.boolValue && compatibleColorFormat != GraphicsFormat.None ? MessageType.Warning : MessageType.Error);\n            }\n\n            // 3D Textures with a depth buffer aren't supported.\n            if (!isTexture3D)\n            {\n                if ((guiElements & GUIElements.RenderTargetDepthGUI) != 0)\n                {\n                    EditorGUILayout.PropertyField(m_DepthStencilFormat, styles.depthStencilFormat);\n                }\n\n                if (depthStencilFormat != compatibleDepthStencilFormat)\n                {\n                    string text = string.Format(\"Format {0} is not supported on this platform. \", depthStencilFormat.ToString());\n                    if (compatibleDepthStencilFormat != GraphicsFormat.None)\n                    {\n                        if (m_EnableCompatibleFormat.boolValue)\n                            text += string.Format(\"Using {0} as a compatible format.\", compatibleDepthStencilFormat.ToString());\n                        else\n                            text += string.Format(\"You may enable Compatible Format to fallback automatically to a platform specific compatible format, {0} on this device.\", compatibleDepthStencilFormat.ToString());\n                    }\n                    EditorGUILayout.HelpBox(text, m_EnableCompatibleFormat.boolValue && compatibleDepthStencilFormat != GraphicsFormat.None ? MessageType.Warning : MessageType.Error);\n                }\n\n                if ((GraphicsFormat)m_DepthStencilFormat.intValue == GraphicsFormat.None && (GraphicsFormat)m_ColorFormat.intValue == GraphicsFormat.None)\n                {\n                    EditorGUILayout.HelpBox(\"You cannot set both color format and depth format to None\", MessageType.Error);\n                }\n            }\n\n            // Mip map generation is not supported yet for 3D textures (and for depth only textures).\n            if (!(isTexture3D || RenderTextureIsDepthOnly()))\n            {\n                EditorGUILayout.PropertyField(m_EnableMipmaps, styles.enableMipmaps);\n                if (m_EnableMipmaps.boolValue)\n                {\n                    ++EditorGUI.indentLevel;\n                    EditorGUILayout.PropertyField(m_AutoGeneratesMipmaps, styles.autoGeneratesMipmaps);\n                    --EditorGUI.indentLevel;\n                }\n            }\n            else\n            {\n                if (isTexture3D)\n                {\n                    // Mip map generation is not supported yet for 3D textures.\n                    EditorGUILayout.HelpBox(\"3D RenderTextures do not support Mip Maps.\", MessageType.Info);\n                }\n\n                if (RenderTextureIsDepthOnly())\n                {\n                    // Mip map generation is not supported yet for depth-only textures.\n                    EditorGUILayout.HelpBox(\"Depth-only RenderTextures do not support Mip Maps.\", MessageType.Info);\n                }\n            }\n\n            EditorGUILayout.PropertyField(m_UseDynamicScale, styles.useDynamicScale);\n            EditorGUILayout.PropertyField(m_EnableRandomWrite, styles.enableRandomWrite);\n\n            var rt = target as RenderTexture;\n            if (GUI.changed && rt != null)\n            {\n                rt.Release();\n                m_RepaintDelay = 5;\n            }\n\n            // Trigger delayed repaint to allow camera's to be rendered before thumbnail is generated.\n            if (m_RepaintDelay > 0)\n            {\n                --m_RepaintDelay;\n                if (m_RepaintDelay == 0)\n                    EditorUtility.SetDirty(target);\n            }\n\n            EditorGUILayout.Space();\n\n            EditorGUI.BeginChangeCheck();\n            DoWrapModePopup();\n            DoFilterModePopup();\n\n            if (!RenderTextureHasDepth()) // Render Textures with depth are forced to 0 Aniso Level\n            {\n                DoAnisoLevelSlider();\n            }\n            else\n            {\n                EditorGUILayout.HelpBox(\"RenderTextures with depth are forced to have an Aniso Level of 0.\", MessageType.Info);\n            }\n\n            if (RenderTextureHasDepth()) // Depth-only textures have shadow mode\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUILayout.PropertyField(m_ShadowSamplingMode, styles.shadowSamplingMode);\n                // Shadow mode unlike the other filter settings requires re-creating the rt if it changed\n                // as it's an actual creation flag on the texture.\n                if (EditorGUI.EndChangeCheck() && rt != null)\n                {\n                    rt.Release();\n                }\n            }\n            else\n            {\n                EditorGUILayout.HelpBox(\"Only render textures with depth can have shadow filtering.\", MessageType.Info);\n            }\n\n            serializedObject.ApplyModifiedProperties();\n\n            if (EditorGUI.EndChangeCheck())\n                ApplySettingsToTextures();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            OnRenderTextureGUI(s_AllGUIElements);\n        }\n\n        private bool RenderTextureHasDepth()\n        {\n            return RenderTextureIsDepthOnly() || m_DepthStencilFormat.enumValueIndex != 0;\n        }\n\n        private bool RenderTextureIsDepthOnly()\n        {\n            GraphicsFormat colorFormat = (GraphicsFormat)m_ColorFormat.enumValueIndex;\n            return colorFormat == GraphicsFormat.None;\n        }\n\n        override public string GetInfoString()\n        {\n            RenderTexture t = target as RenderTexture;\n\n            string info = t.width + \"x\" + t.height;\n            if (t.dimension == UnityEngine.Rendering.TextureDimension.Tex3D)\n                info += \"x\" + t.volumeDepth;\n\n            if (!t.isPowerOfTwo)\n                info += \"(NPOT)\";\n\n            if (QualitySettings.desiredColorSpace == ColorSpace.Linear)\n            {\n                bool formatIsHDR = GraphicsFormatUtility.IsIEEE754Format(t.graphicsFormat);\n                bool sRGB = t.sRGB && !formatIsHDR;\n                info += \" \" + (sRGB ? \"sRGB\" : \"Linear\");\n            }\n\n            info += \"  \" + t.graphicsFormat;\n            info += \"  \" + EditorUtility.FormatBytes(TextureUtil.GetRuntimeMemorySizeLong(t));\n\n            return info;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/RendererEditorBase.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing System.Linq;\nusing Object = UnityEngine.Object;\nusing System.Globalization;\n\n// RayTracingMode enum will be moved into UnityEngine.Rendering in the future.\nusing RayTracingMode = UnityEngine.Experimental.Rendering.RayTracingMode;\n\nnamespace UnityEditor\n{\n    internal class RendererEditorBase : Editor\n    {\n        internal class Probes\n        {\n            private SerializedProperty m_LightProbeUsage;\n            private SerializedProperty m_LightProbeVolumeOverride;\n            private SerializedProperty m_ReflectionProbeUsage;\n            private SerializedProperty m_ProbeAnchor;\n            private SerializedProperty m_ReceiveShadows;\n\n            private GUIContent m_LightProbeUsageStyle = EditorGUIUtility.TrTextContent(\"Light Probes\", \"Specifies how Light Probes will handle the interpolation of lighting and occlusion. Disabled if the object is set to receive Global Illumination from lightmaps.\");\n            private GUIContent m_LightProbeVolumeOverrideStyle = EditorGUIUtility.TrTextContent(\"Proxy Volume Override\", \"If set, the Renderer will use the Light Probe Proxy Volume component from another GameObject.\");\n            private GUIContent m_ReflectionProbeUsageStyle = EditorGUIUtility.TrTextContent(\"Reflection Probes\", \"Specifies if or how the object is affected by reflections in the Scene.  This property cannot be disabled in deferred rendering modes.\");\n            private GUIContent m_ProbeAnchorStyle = EditorGUIUtility.TrTextContent(\"Anchor Override\", \"Specifies the Transform position that will be used for sampling the light probes and reflection probes.\");\n            private GUIContent m_ProbeAnchorNoReflectionProbesStyle = EditorGUIUtility.TrTextContent(\"Anchor Override\", \"Specifies the Transform position that will be used for sampling the light probes.\");\n            private GUIContent m_DeferredNote = EditorGUIUtility.TrTextContent(\"In Deferred Shading, all objects receive shadows and get per-pixel reflection probes.\");\n            private GUIContent m_LightProbeVolumeNote = EditorGUIUtility.TrTextContent(\"A valid Light Probe Proxy Volume component could not be found.\");\n            private GUIContent m_LightProbeVolumeUnsupportedNote = EditorGUIUtility.TrTextContent(\"The Light Probe Proxy Volume feature is unsupported by the current graphics hardware or API configuration. Simple 'Blend Probes' mode will be used instead.\");\n            private GUIContent m_LightProbeVolumeUnsupportedOnTreesNote = EditorGUIUtility.TrTextContent(\"The Light Probe Proxy Volume feature is not supported on tree rendering. Simple 'Blend Probes' mode will be used instead.\");\n            private GUIContent m_LightProbeCustomNote = EditorGUIUtility.TrTextContent(\"The Custom Provided mode requires SH properties to be sent via MaterialPropertyBlock.\");\n            private GUIContent[] m_ReflectionProbeUsageOptions = (Enum.GetNames(typeof(ReflectionProbeUsage)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray()).Select(x => new GUIContent(x)).ToArray();\n\n            private GUIContent probeAnchorStyle\n            {\n                get\n                {\n                    if (!SupportedRenderingFeatures.active.reflectionProbes)\n                        return m_ProbeAnchorNoReflectionProbesStyle;\n                    return m_ProbeAnchorStyle;\n                }\n            }\n\n            private List<ReflectionProbeBlendInfo> m_BlendInfo = new List<ReflectionProbeBlendInfo>();\n\n            internal void Initialize(SerializedObject serializedObject)\n            {\n                m_LightProbeUsage = serializedObject.FindProperty(\"m_LightProbeUsage\");\n                m_LightProbeVolumeOverride = serializedObject.FindProperty(\"m_LightProbeVolumeOverride\");\n                m_ReflectionProbeUsage = serializedObject.FindProperty(\"m_ReflectionProbeUsage\");\n                m_ProbeAnchor = serializedObject.FindProperty(\"m_ProbeAnchor\");\n                m_ReceiveShadows = serializedObject.FindProperty(\"m_ReceiveShadows\");\n            }\n\n            internal bool IsUsingLightProbeProxyVolume(int selectionCount)\n            {\n                bool isUsingLightProbeVolumes =\n                    ((selectionCount == 1) && (m_LightProbeUsage.intValue == (int)LightProbeUsage.UseProxyVolume)) ||\n                    ((selectionCount > 1) && !m_LightProbeUsage.hasMultipleDifferentValues && (m_LightProbeUsage.intValue == (int)LightProbeUsage.UseProxyVolume));\n\n                return isUsingLightProbeVolumes;\n            }\n\n            internal void RenderLightProbeProxyVolumeWarningNote(Renderer renderer, int selectionCount)\n            {\n                if (IsUsingLightProbeProxyVolume(selectionCount))\n                {\n                    if (LightProbeProxyVolume.isFeatureSupported && SupportedRenderingFeatures.active.lightProbeProxyVolumes)\n                    {\n                        LightProbeProxyVolume lightProbeProxyVol = renderer.GetComponent<LightProbeProxyVolume>();\n                        bool invalidProxyVolumeOverride = (renderer.lightProbeProxyVolumeOverride == null) ||\n                            (renderer.lightProbeProxyVolumeOverride.GetComponent<LightProbeProxyVolume>() == null);\n                        if (lightProbeProxyVol == null && invalidProxyVolumeOverride && LightProbes.AreLightProbesAllowed(renderer))\n                        {\n                            EditorGUILayout.HelpBox(m_LightProbeVolumeNote.text, MessageType.Warning);\n                        }\n                    }\n                    else\n                    {\n                        EditorGUILayout.HelpBox(m_LightProbeVolumeUnsupportedNote.text, MessageType.Warning);\n                    }\n                }\n            }\n\n            internal void RenderReflectionProbeUsage(bool useMiniStyle, bool isDeferredRenderingPath, bool isDeferredReflections)\n            {\n                if (!SupportedRenderingFeatures.active.reflectionProbes)\n                    return;\n\n                using (new EditorGUI.DisabledScope(isDeferredRenderingPath))\n                {\n                    // reflection probe usage field; UI disabled when using deferred reflections\n                    if (!useMiniStyle)\n                    {\n                        if (isDeferredReflections)\n                        {\n                            EditorGUILayout.EnumPopup(m_ReflectionProbeUsageStyle, (m_ReflectionProbeUsage.intValue != (int)ReflectionProbeUsage.Off) ? ReflectionProbeUsage.Simple : ReflectionProbeUsage.Off);\n                        }\n                        else\n                        {\n                            EditorGUILayout.Popup(m_ReflectionProbeUsage, m_ReflectionProbeUsageOptions, m_ReflectionProbeUsageStyle);\n                        }\n                    }\n                    else\n                    {\n                        if (isDeferredReflections)\n                        {\n                            ModuleUI.GUIPopup(m_ReflectionProbeUsageStyle, (int)ReflectionProbeUsage.Simple, m_ReflectionProbeUsageOptions);\n                        }\n                        else\n                        {\n                            ModuleUI.GUIPopup(m_ReflectionProbeUsageStyle, m_ReflectionProbeUsage, m_ReflectionProbeUsageOptions);\n                        }\n                    }\n                }\n            }\n\n            internal void RenderLightProbeUsage(int selectionCount, Renderer renderer, bool useMiniStyle, bool lightProbeAllowed)\n            {\n                using (new EditorGUI.DisabledScope(!lightProbeAllowed))\n                {\n                    if (lightProbeAllowed)\n                    {\n                        // LightProbeUsage has non-sequential enum values. Extra care is to be taken.\n                        if (useMiniStyle)\n                        {\n                            EditorGUI.BeginChangeCheck();\n                            var newValue = ModuleUI.GUIEnumPopup(m_LightProbeUsageStyle, (LightProbeUsage)m_LightProbeUsage.intValue, m_LightProbeUsage);\n                            if (EditorGUI.EndChangeCheck())\n                                m_LightProbeUsage.intValue = (int)(LightProbeUsage)newValue;\n                        }\n                        else\n                        {\n                            Rect r = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup);\n                            EditorGUI.BeginProperty(r, m_LightProbeUsageStyle, m_LightProbeUsage);\n                            EditorGUI.BeginChangeCheck();\n                            var newValue = EditorGUI.EnumPopup(r, m_LightProbeUsageStyle, (LightProbeUsage)m_LightProbeUsage.intValue);\n                            if (EditorGUI.EndChangeCheck())\n                                m_LightProbeUsage.intValue = (int)(LightProbeUsage)newValue;\n                            EditorGUI.EndProperty();\n                        }\n\n                        if (!m_LightProbeUsage.hasMultipleDifferentValues)\n                        {\n                            if (m_LightProbeUsage.intValue == (int)LightProbeUsage.UseProxyVolume\n                                && SupportedRenderingFeatures.active.lightProbeProxyVolumes)\n                            {\n                                EditorGUI.indentLevel++;\n                                if (useMiniStyle)\n                                    ModuleUI.GUIObject(m_LightProbeVolumeOverrideStyle, m_LightProbeVolumeOverride);\n                                else\n                                    EditorGUILayout.PropertyField(m_LightProbeVolumeOverride, m_LightProbeVolumeOverrideStyle);\n                                EditorGUI.indentLevel--;\n                            }\n                            else if (m_LightProbeUsage.intValue == (int)LightProbeUsage.CustomProvided)\n                            {\n                                EditorGUI.indentLevel++;\n                                if (!Application.isPlaying)\n                                    EditorGUILayout.HelpBox(m_LightProbeCustomNote.text, MessageType.Info);\n                                else if (!renderer.HasPropertyBlock())\n                                    EditorGUILayout.HelpBox(m_LightProbeCustomNote.text, MessageType.Error);\n                                EditorGUI.indentLevel--;\n                            }\n                        }\n                    }\n                    else\n                    {\n                        if (useMiniStyle)\n                            ModuleUI.GUIEnumPopup(m_LightProbeUsageStyle, LightProbeUsage.Off, m_LightProbeUsage);\n                        else\n                            EditorGUILayout.EnumPopup(m_LightProbeUsageStyle, LightProbeUsage.Off);\n                    }\n                }\n\n                Tree tree;\n                renderer.TryGetComponent(out tree);\n                if ((tree != null) && (m_LightProbeUsage.intValue == (int)LightProbeUsage.UseProxyVolume))\n                {\n                    EditorGUI.indentLevel++;\n                    EditorGUILayout.HelpBox(m_LightProbeVolumeUnsupportedOnTreesNote.text, MessageType.Warning);\n                    EditorGUI.indentLevel--;\n                }\n            }\n\n            internal bool RenderProbeAnchor(bool useMiniStyle)\n            {\n                bool useReflectionProbes = !m_ReflectionProbeUsage.hasMultipleDifferentValues && (ReflectionProbeUsage)m_ReflectionProbeUsage.intValue != ReflectionProbeUsage.Off && SupportedRenderingFeatures.active.reflectionProbes;\n                bool lightProbesEnabled = !m_LightProbeUsage.hasMultipleDifferentValues && (LightProbeUsage)m_LightProbeUsage.intValue != LightProbeUsage.Off;\n                bool needsRendering = useReflectionProbes || lightProbesEnabled;\n\n                if (needsRendering)\n                {\n                    // anchor field\n                    if (!useMiniStyle)\n                        EditorGUILayout.PropertyField(m_ProbeAnchor, probeAnchorStyle);\n                    else\n                        ModuleUI.GUIObject(probeAnchorStyle, m_ProbeAnchor);\n                }\n\n                return needsRendering;\n            }\n\n            // Set useMiniStyle to true to use smaller UI styles,\n            // like in particle system modules UI.\n            //\n            // The code does branches right now on that instead of just\n            // picking one or another style, since there are no UI\n            // functions, like EditorGUILayout.ObjectField that would take\n            // a style parameter :(\n            internal void OnGUI(UnityEngine.Object[] selection, Renderer renderer, bool useMiniStyle)\n            {\n                int selectionCount = 1;\n                bool isDeferredRenderingPath = SceneView.IsUsingDeferredRenderingPath();\n                bool isDeferredReflections = isDeferredRenderingPath && (UnityEngine.Rendering.GraphicsSettings.GetShaderMode(BuiltinShaderType.DeferredReflections) != BuiltinShaderMode.Disabled);\n                bool areLightProbesAllowed = true;\n\n                if (selection != null)\n                {\n                    foreach (UnityEngine.Object obj in selection)\n                    {\n                        if (LightProbes.AreLightProbesAllowed((Renderer)obj) == false)\n                        {\n                            areLightProbesAllowed = false;\n                            break;\n                        }\n                    }\n\n                    selectionCount = selection.Length;\n                }\n\n                RenderLightProbeUsage(selectionCount, renderer, useMiniStyle, areLightProbesAllowed);\n\n                RenderLightProbeProxyVolumeWarningNote(renderer, selectionCount);\n\n                RenderReflectionProbeUsage(useMiniStyle, isDeferredRenderingPath, isDeferredReflections);\n\n                // anchor field - light probes and reflection probes share the same anchor\n                bool needsProbeAnchorField = RenderProbeAnchor(useMiniStyle);\n\n                if (needsProbeAnchorField)\n                {\n                    bool useReflectionProbes = !m_ReflectionProbeUsage.hasMultipleDifferentValues && (ReflectionProbeUsage)m_ReflectionProbeUsage.intValue != ReflectionProbeUsage.Off && SupportedRenderingFeatures.active.reflectionProbes;\n\n                    if (useReflectionProbes)\n                    {\n                        if (!isDeferredReflections)\n                        {\n                            renderer.GetClosestReflectionProbes(m_BlendInfo);\n                            ShowClosestReflectionProbes(m_BlendInfo);\n                        }\n                    }\n                }\n\n                bool receivesShadow = !m_ReceiveShadows.hasMultipleDifferentValues && m_ReceiveShadows.boolValue;\n\n                if ((isDeferredRenderingPath && receivesShadow) || (isDeferredReflections && needsProbeAnchorField))\n                {\n                    EditorGUILayout.HelpBox(m_DeferredNote.text, MessageType.Info);\n                }\n            }\n\n            // Show an info list of probes affecting this object, and their weights.\n            internal static void ShowClosestReflectionProbes(List<ReflectionProbeBlendInfo> blendInfos)\n            {\n                float kProbeLabelWidth = 20;\n                float kWeightWidth = 70;\n\n                // No UI interaction, so disable all controls.\n                using (new EditorGUI.DisabledScope(true))\n                {\n                    for (int i = 0; i < blendInfos.Count; i++)\n                    {\n                        var rowRect = GUILayoutUtility.GetRect(0, EditorGUI.kSingleLineHeight);\n                        rowRect = EditorGUI.IndentedRect(rowRect);\n                        float probeFieldWidth = rowRect.width - kProbeLabelWidth - kWeightWidth;\n                        var rect = rowRect;\n\n                        rect.width = kProbeLabelWidth;\n                        GUI.Label(rect, \"#\" + i, EditorStyles.miniLabel);\n\n                        rect.x += rect.width;\n                        rect.width = probeFieldWidth;\n                        EditorGUI.ObjectField(rect, blendInfos[i].probe, typeof(ReflectionProbe), true);\n\n                        rect.x += rect.width;\n                        rect.width = kWeightWidth;\n                        GUI.Label(rect, \"Weight \" + blendInfos[i].weight.ToString(\"f2\", CultureInfo.InvariantCulture.NumberFormat), EditorStyles.miniLabel);\n                    }\n                }\n            }\n\n            internal static string[] GetFieldsStringArray()\n            {\n                return new[]\n                {\n                    \"m_LightProbeUsage\",\n                    \"m_LightProbeVolumeOverride\",\n                    \"m_ReflectionProbeUsage\",\n                    \"m_ProbeAnchor\",\n                };\n            }\n        }\n\n        private SerializedProperty m_SortingOrder;\n        private SerializedProperty m_SortingLayerID;\n        private SerializedProperty m_DynamicOccludee;\n        private SerializedProperty m_RenderingLayerMask;\n        private SerializedProperty m_RendererPriority;\n        private SerializedProperty m_SkinnedMotionVectors;\n        private SerializedProperty m_MotionVectors;\n        private SerializedProperty m_RayTracingMode;\n        private SerializedProperty m_RayTraceProcedural;\n        private SerializedProperty m_RayTracingAccelStructBuildFlags;\n        private SerializedProperty m_RayTracingAccelStructBuildFlagsOverride;\n        protected SerializedProperty m_Materials;\n        private SerializedProperty m_ForceMeshLod;\n        private SerializedProperty m_MeshLodSelectionBias;\n\n        class Styles\n        {\n            public static readonly GUIContent materials = EditorGUIUtility.TrTextContent(\"Materials\");\n            public static readonly GUIContent probeSettings = EditorGUIUtility.TrTextContent(\"Probes\");\n            public static readonly GUIContent otherSettings = EditorGUIUtility.TrTextContent(\"Additional Settings\");\n            public static readonly GUIContent meshLodSettings = EditorGUIUtility.TrTextContent(\"Mesh LOD\");\n\n            public static readonly GUIContent dynamicOcclusion = EditorGUIUtility.TrTextContent(\"Dynamic Occlusion\", \"Controls if dynamic occlusion culling should be performed for this renderer.\");\n            public static readonly GUIContent motionVectors = EditorGUIUtility.TrTextContent(\"Motion Vectors\", \"Specifies whether the Mesh Renders 'Per Object Motion', 'Camera Motion', or 'No Motion' vectors to the Camera Motion Vector Texture.\");\n            public static readonly GUIContent skinnedMotionVectors = EditorGUIUtility.TrTextContent(\"Skinned Motion Vectors\", \"Enabling Skinned Motion Vectors will allow generation of high precision motion vectors for the Skinned Mesh. This is achieved by keeping the skinning results of the previous frame in memory thus increasing the memory usage.\");\n            public static readonly GUIContent renderingLayerMask = EditorGUIUtility.TrTextContent(\"Rendering Layer Mask\", \"Mask that can be used with SRP DrawRenderers command to filter renderers outside of the normal layering system.\");\n            public static readonly GUIContent rendererPriority = EditorGUIUtility.TrTextContent(\"Priority\", \"Sets the priority value that the render pipeline uses to calculate the rendering order.\");\n            public static readonly GUIContent rayTracingModeStyle = EditorGUIUtility.TrTextContent(\"Ray Tracing Mode\", \"Describes how the acceleration structure associated with a renderer will update for ray tracing.\");\n            public static readonly GUIContent[] rayTracingModeOptions = (Enum.GetNames(typeof(RayTracingMode)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray()).Select(x => new GUIContent(x)).ToArray();\n            public static readonly GUIContent rayTracingGeomStyle = EditorGUIUtility.TrTextContent(\"Procedural Geometry\", \"Specifies whether to treat geometry as procedurally defined by an intersection shader or as a Mesh.\");\n            public static readonly GUIContent rayTracingAccelStructBuildFlagsStyle = EditorGUIUtility.TrTextContent(\"Acceleration Structure Build Flags\", \"Specifies whether this renderer overrides the default build flags that you specified when you created a RayTracingAccelerationStructure.\");\n            public static readonly GUIContent forceMeshLodStyle = EditorGUIUtility.TrTextContent(\"LOD Override\", \"Disable automatic LOD selection and set the LOD index to the value in the Override Level property.\");\n            public static readonly GUIContent forcedMeshLodLevelStyle = EditorGUIUtility.TrTextContent(\"Override Level\", \"Set the LOD index to this value.\");\n            public static readonly GUIContent meshLodSelectionBiasStyle = EditorGUIUtility.TrTextContent(\"LOD Selection Bias\", \"The value that Unity adds to the calculated LOD index. Increasing this value results in Unity selecting less detailed LODs, reducing the value - in more detailed LODs.\");\n        }\n\n        protected Probes m_Probes;\n        protected RendererLightingSettings m_Lighting;\n\n        protected SavedBool m_ShowMaterials;\n        protected SavedBool m_ShowProbeSettings;\n        protected SavedBool m_ShowOtherSettings;\n        protected SavedBool m_ShowMeshLodSettings;\n        protected SavedBool m_ShowRayTracingSettings;\n\n        public virtual void OnEnable()\n        {\n            m_SortingOrder = serializedObject.FindProperty(\"m_SortingOrder\");\n            m_SortingLayerID = serializedObject.FindProperty(\"m_SortingLayerID\");\n            m_DynamicOccludee = serializedObject.FindProperty(\"m_DynamicOccludee\");\n            m_RenderingLayerMask = serializedObject.FindProperty(\"m_RenderingLayerMask\");\n            m_RendererPriority = serializedObject.FindProperty(\"m_RendererPriority\");\n            m_RayTracingMode = serializedObject.FindProperty(\"m_RayTracingMode\");\n            m_RayTraceProcedural = serializedObject.FindProperty(\"m_RayTraceProcedural\");\n            m_RayTracingAccelStructBuildFlags = serializedObject.FindProperty(\"m_RayTracingAccelStructBuildFlags\");\n            m_RayTracingAccelStructBuildFlagsOverride = serializedObject.FindProperty(\"m_RayTracingAccelStructBuildFlagsOverride\");\n            m_MotionVectors = serializedObject.FindProperty(\"m_MotionVectors\");\n            m_SkinnedMotionVectors = serializedObject.FindProperty(\"m_SkinnedMotionVectors\");\n            m_Materials = serializedObject.FindProperty(\"m_Materials\");\n            m_ForceMeshLod = serializedObject.FindProperty(\"m_ForceMeshLod\");\n            m_MeshLodSelectionBias = serializedObject.FindProperty(\"m_MeshLodSelectionBias\");\n\n            m_ShowMaterials = new SavedBool($\"{target.GetType()}.ShowMaterials\", true);\n            m_ShowProbeSettings = new SavedBool($\"{target.GetType()}.ShowProbeSettings\", true);\n            m_ShowOtherSettings = new SavedBool($\"{target.GetType()}.ShowOtherSettings\", true);\n            m_ShowMeshLodSettings = new SavedBool($\"{target.GetType()}.ShowLodSettings\", true);\n            m_ShowRayTracingSettings = new SavedBool($\"{target.GetType()}.ShowRayTracingSettings\", true);\n\n            m_Lighting = new RendererLightingSettings(serializedObject);\n            m_Lighting.showLightingSettings = new SavedBool($\"{target.GetType()}.ShowLightingSettings\", true);\n            m_Lighting.showLightmapSettings = new SavedBool($\"{target.GetType()}.ShowLightmapSettings\", true);\n            m_Lighting.showBakedLightmap = new SavedBool($\"{target.GetType()}.ShowBakedLightmapSettings\", false);\n            m_Lighting.showPreviewLightmap = new SavedBool($\"{target.GetType()}.ShowPreviewLightmapSettings\", false);\n            m_Lighting.showRealtimeLightmap = new SavedBool($\"{target.GetType()}.ShowRealtimeLightmapSettings\", false);\n\n            m_Probes = new Probes();\n            m_Probes.Initialize(serializedObject);\n        }\n\n        protected void LightingSettingsGUI(bool showLightmappSettings)\n        {\n            LightingSettingsGUI(showLightmappSettings, false, 1);\n        }\n\n        protected void LightingSettingsGUI(bool showLightmappSettings, bool showMeshLODSettings, int lodCount)\n        {\n            m_Lighting.RenderSettings(showLightmappSettings, showMeshLODSettings, lodCount);\n\n            if (SupportedRenderingFeatures.active.rendererProbes)\n            {\n                m_ShowProbeSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_ShowProbeSettings.value, Styles.probeSettings);\n\n                if (m_ShowProbeSettings.value)\n                {\n                    EditorGUI.indentLevel += 1;\n                    m_Probes.OnGUI(targets, (Renderer)target, false);\n                    EditorGUI.indentLevel -= 1;\n                }\n\n                EditorGUILayout.EndFoldoutHeaderGroup();\n            }\n        }\n\n        protected void Other2DSettingsGUI()\n        {\n            m_ShowOtherSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_ShowOtherSettings.value, Styles.otherSettings);\n\n            if (m_ShowOtherSettings.value)\n            {\n                EditorGUI.indentLevel++;\n\n                SortingLayerEditorUtility.RenderSortingLayerFields(m_SortingOrder, m_SortingLayerID);\n\n                DrawRenderingLayer();\n\n                EditorGUI.indentLevel--;\n            }\n\n            EditorGUILayout.EndFoldoutHeaderGroup();\n        }\n\n        protected void MeshLodSettingsGUI(int lodCount)\n        {\n            m_ShowMeshLodSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_ShowMeshLodSettings.value, Styles.meshLodSettings);\n\n            if (m_ShowMeshLodSettings.value)\n            {\n                using (new EditorGUI.IndentLevelScope())\n                {\n                    EditorGUI.BeginChangeCheck();\n\n                    var forceMeshLODEnabled = EditorGUILayout.Toggle(Styles.forceMeshLodStyle, m_ForceMeshLod.intValue != -1);\n\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        if (forceMeshLODEnabled)\n                            m_ForceMeshLod.intValue = 0;\n                        else\n                            m_ForceMeshLod.intValue = -1;\n                    }\n\n                    if (forceMeshLODEnabled)\n                    {\n                        using (new EditorGUI.IndentLevelScope())\n                        {\n                            EditorGUILayout.IntSlider(m_ForceMeshLod, 0, lodCount - 1, Styles.forcedMeshLodLevelStyle);\n                        }\n                    }\n\n                    using (new EditorGUI.DisabledScope(forceMeshLODEnabled))\n                    {\n                        int maxLevel = lodCount - 1;\n                        EditorGUILayout.Slider(m_MeshLodSelectionBias, -maxLevel, maxLevel, Styles.meshLodSelectionBiasStyle);\n                    }\n                }\n            }\n\n            EditorGUILayout.EndFoldoutHeaderGroup();\n        }\n\n        protected void OtherSettingsGUI(bool showMotionVectors, bool showSkinnedMotionVectors = false, bool showSortingLayerFields = false)\n        {\n            m_ShowOtherSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_ShowOtherSettings.value, Styles.otherSettings);\n\n            if (m_ShowOtherSettings.value)\n            {\n                EditorGUI.indentLevel++;\n\n                if (SupportedRenderingFeatures.active.motionVectors)\n                {\n                    if (showMotionVectors)\n                        EditorGUILayout.PropertyField(m_MotionVectors, Styles.motionVectors, true);\n                    else if (showSkinnedMotionVectors)\n                        EditorGUILayout.PropertyField(m_SkinnedMotionVectors, Styles.skinnedMotionVectors, true);\n                }\n\n                EditorGUILayout.PropertyField(m_DynamicOccludee, Styles.dynamicOcclusion);\n\n\n                if (showSortingLayerFields)\n                    SortingLayerEditorUtility.RenderSortingLayerFields(m_SortingOrder, m_SortingLayerID);\n\n                DrawRenderingLayer();\n                DrawRendererPriority(m_RendererPriority);\n\n                EditorGUI.indentLevel--;\n            }\n\n            EditorGUILayout.EndFoldoutHeaderGroup();\n        }\n\n        protected void DrawMaterials()\n        {\n            EditorGUILayout.PropertyField(m_Materials);\n        }\n\n        protected void DrawRenderingLayer()\n        {\n            DrawRenderingLayer(m_RenderingLayerMask, target as Renderer, targets.ToArray());\n        }\n\n        internal static void DrawRenderingLayer(SerializedProperty layerMask, Renderer target, Object[] targets, bool useMiniStyle = false)\n        {\n            if (!GraphicsSettings.isScriptableRenderPipelineEnabled || target == null)\n                return;\n\n            using var changeScope = new EditorGUI.ChangeCheckScope();\n\n            var mask = target.renderingLayerMask;\n            var rect = EditorGUILayout.GetControlRect();\n            if (useMiniStyle)\n            {\n                rect = ModuleUI.PrefixLabel(rect, Styles.renderingLayerMask);\n                mask = EditorGUI.RenderingLayerMaskField(rect, GUIContent.none, mask, ParticleSystemStyles.Get().popup);\n            }\n            else\n                mask = EditorGUI.RenderingLayerMaskField(rect,Styles.renderingLayerMask, mask);\n\n            if (changeScope.changed)\n            {\n                Undo.RecordObjects(targets, \"Set rendering layer mask\");\n                for (var i = 0; i < targets.Length; i++)\n                {\n                    var t = targets[i];\n                    var r = t as Renderer;\n                    if (r == null)\n                        continue;\n                    r.renderingLayerMask = mask;\n                    EditorUtility.SetDirty(t);\n                }\n            }\n        }\n\n        internal static void DrawRendererPriority(SerializedProperty rendererPrority, bool useMiniStyle = false)\n        {\n            if (!SupportedRenderingFeatures.active.rendererPriority)\n                return;\n\n            if (!useMiniStyle)\n            {\n                EditorGUILayout.PropertyField(rendererPrority, Styles.rendererPriority);\n            }\n            else\n            {\n                ModuleUI.GUIInt(Styles.rendererPriority, rendererPrority);\n            }\n        }\n\n        protected void RayTracingSettingsGUI()\n        {\n            if (SystemInfo.supportsRayTracingShaders || SystemInfo.supportsInlineRayTracing)\n            {\n                m_ShowRayTracingSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_ShowRayTracingSettings.value, \"Ray Tracing\");\n                if (m_ShowRayTracingSettings.value)\n                {\n                    EditorGUI.indentLevel++;\n\n                    EditorGUILayout.Popup(m_RayTracingMode, Styles.rayTracingModeOptions, Styles.rayTracingModeStyle);\n\n                    EditorGUILayout.PropertyField(m_RayTraceProcedural, Styles.rayTracingGeomStyle);\n\n                    // Ray Tracing Acceleration Structure Build Flags\n                    {\n                        Rect rect = EditorGUILayout.GetControlRect();\n                        EditorGUI.BeginProperty(rect, Styles.rayTracingAccelStructBuildFlagsStyle, m_RayTracingAccelStructBuildFlagsOverride);\n\n                        rect = EditorGUI.PrefixLabel(rect, Styles.rayTracingAccelStructBuildFlagsStyle);\n\n                        EditorGUI.BeginChangeCheck();\n\n                        Rect toggleRect = rect;\n\n                        toggleRect.x -= EditorGUI.indent;\n                        toggleRect.width = 30;\n\n                        bool overrideFlags = EditorGUI.Toggle(toggleRect, m_RayTracingAccelStructBuildFlagsOverride.boolValue);\n                        int buildFlags = m_RayTracingAccelStructBuildFlags.intValue;\n\n                        EditorGUI.EndProperty();\n\n                        bool disableFlagsField = m_RayTracingAccelStructBuildFlags.hasMultipleDifferentValues;\n\n                        using (new EditorGUI.DisabledScope(!m_RayTracingAccelStructBuildFlagsOverride.boolValue || m_RayTracingAccelStructBuildFlagsOverride.hasMultipleDifferentValues || disableFlagsField))\n                        {\n                            rect.xMin += EditorGUI.kDefaultSpacing;\n\n                            if (m_RayTracingAccelStructBuildFlags.hasMultipleDifferentValues)\n                                EditorGUI.showMixedValue = true;\n\n                            buildFlags = (int)(RayTracingAccelerationStructureBuildFlags)EditorGUI.EnumFlagsField(rect, (RayTracingAccelerationStructureBuildFlags)m_RayTracingAccelStructBuildFlags.intValue);\n\n                            EditorGUI.showMixedValue = false;\n\n                            if (buildFlags == -1 && !disableFlagsField)\n                            {\n                                buildFlags = 0;\n\n                                foreach (RayTracingAccelerationStructureBuildFlags type in Enum.GetValues(typeof(RayTracingAccelerationStructureBuildFlags)))\n                                {\n                                    buildFlags = buildFlags | (int)type;\n                                }\n                            }\n\n                        }\n\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            m_RayTracingAccelStructBuildFlagsOverride.boolValue = overrideFlags;\n\n                            if (!disableFlagsField)\n                                m_RayTracingAccelStructBuildFlags.intValue = buildFlags;\n                        }\n                    }\n\n                    EditorGUI.indentLevel--;\n                }\n                EditorGUILayout.EndFoldoutHeaderGroup();\n            }\n        }\n\n        protected void RenderCommonProbeFields(bool useMiniStyle)\n        {\n            bool isDeferredRenderingPath = SceneView.IsUsingDeferredRenderingPath();\n            bool isDeferredReflections = isDeferredRenderingPath && (GraphicsSettings.GetShaderMode(BuiltinShaderType.DeferredReflections) != BuiltinShaderMode.Disabled);\n            m_Probes.RenderReflectionProbeUsage(useMiniStyle, isDeferredRenderingPath, isDeferredReflections);\n            m_Probes.RenderProbeAnchor(useMiniStyle);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/RendererLightingSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Linq;\nusing UnityEditor.AnimatedValues;\nusing UnityEngine.Rendering;\nusing UnityEngineInternal;\nusing System.Globalization;\nusing UnityEditor.Presets;\n\nnamespace UnityEditor\n{\n    internal class RendererLightingSettings\n    {\n        static class Styles\n        {\n            public static readonly GUIContent optimizeRealtimeUVs = EditorGUIUtility.TrTextContent(\"Optimize Realtime UVs\", \"Specifies whether the authored mesh UVs get optimized for Realtime Global Illumination or not. When enabled, the authored UVs can get merged, and are scaled and packed for optimization purposes. When disabled, the authored UVs are scaled and packed, but not merged.\");\n            public static readonly GUIContent ignoreNormalsForChartDetection = EditorGUIUtility.TrTextContent(\"Ignore Normals\", \"When enabled, prevents the UV charts from being split during the precompute process for Realtime Global Illumination lighting.\");\n            public static readonly int[] minimumChartSizeValues = { 2, 4 };\n            public static readonly GUIContent[] minimumChartSizeStrings =\n            {\n                EditorGUIUtility.TrTextContent(\"2 (Minimum)\"),\n                EditorGUIUtility.TrTextContent(\"4 (Stitchable)\"),\n            };\n\n            public static readonly int[] receiveGILightmapValues = { (int)ReceiveGI.Lightmaps, (int)ReceiveGI.LightProbes };\n            public static readonly GUIContent[] receiveGILightmapStrings =\n            {\n                EditorGUIUtility.TrTextContent(\"Lightmaps\"),\n                EditorGUIUtility.TrTextContent(\"Light Probes\")\n            };\n\n            public static readonly GUIContent lightingSettings = EditorGUIUtility.TrTextContent(\"Lighting\");\n            public static readonly GUIContent lighting = new GUIContent(EditorGUIUtility.TrTextContent(\"Lighting\").text); // prevent the Lighting window icon from being added\n            public static readonly GUIContent minimumChartSize = EditorGUIUtility.TrTextContent(\"Min Chart Size\", \"Specifies the minimum texel size used for a UV chart. If stitching is required, a value of 4 will create a chart of 4x4 texels to store lighting and directionality. If stitching is not required, a value of 2 will reduce the texel density and provide better lighting build times and run time performance.\");\n            public static readonly GUIContent importantGI = EditorGUIUtility.TrTextContent(\"Prioritize Illumination\", \"When enabled, the object will be marked as a priority object and always included in lighting calculations. Useful for objects that will be strongly emissive to make sure that other objects will be illuminated by this object.\");\n            public static readonly GUIContent stitchLightmapSeams = EditorGUIUtility.TrTextContent(\"Stitch Seams\", \"When enabled, seams in baked lightmaps will get smoothed.\");\n            public static readonly GUIContent autoUVMaxDistance = EditorGUIUtility.TrTextContent(\"Max Distance\", \"Specifies the maximum worldspace distance to be used for UV chart simplification. If charts are within this distance, they will be simplified for optimization purposes.\");\n            public static readonly GUIContent autoUVMaxAngle = EditorGUIUtility.TrTextContent(\"Max Angle\", \"Specifies the maximum angle in degrees between faces sharing a UV edge. If the angle between the faces is below this value, the UV charts will be simplified.\");\n            public static readonly GUIContent lightmapParameters = EditorGUIUtility.TrTextContent(\"Lightmap Parameters\", \"Allows the adjustment of advanced parameters that affect the process of generating a lightmap for an object using global illumination.\");\n            public static readonly GUIContent atlasTilingX = EditorGUIUtility.TrTextContent(\"Tiling X\");\n            public static readonly GUIContent atlasTilingY = EditorGUIUtility.TrTextContent(\"Tiling Y\");\n            public static readonly GUIContent atlasOffsetX = EditorGUIUtility.TrTextContent(\"Offset X\");\n            public static readonly GUIContent atlasOffsetY = EditorGUIUtility.TrTextContent(\"Offset Y\");\n            public static readonly GUIContent clampedSize = EditorGUIUtility.TrTextContent(\"Object's size in lightmap has reached the max atlas size.\", \"If you need higher resolution for this object, divide it into smaller meshes or set higher max atlas size via the LightingSettings class.\");\n            public static readonly GUIContent clampedPackingResolution = EditorGUIUtility.TrTextContent(\"Object's size in the realtime lightmap has reached the maximum size. If you need higher resolution for this object, divide it into smaller meshes.\");\n            public static readonly GUIContent zeroAreaPackingMesh = EditorGUIUtility.TrTextContent(\"Mesh used by the renderer has zero UV or surface area. Non zero area is required for lightmapping.\");\n            public static readonly GUIContent noNormalsNoLightmapping = EditorGUIUtility.TrTextContent(\"Mesh used by the renderer doesn't have normals. Normals are needed for lightmapping.\");\n            public static readonly GUIContent noVerticesNoLightmapping = EditorGUIUtility.TrTextContent(\"Mesh used by the renderer doesn't have vertices. Vertices are needed for lightmapping.\");\n            public static readonly GUIContent unsupportedTopology = EditorGUIUtility.TrTextContent(\"Mesh with point, strip or line topology is not supported by lightmapping.\");\n            public static readonly GUIContent uvOverlap = EditorGUIUtility.TrTextContent(\"This GameObject has overlapping UVs. Please adjust Mesh Importer settings or increase chart padding in your modeling package.\");\n            public static readonly GUIContent atlas = EditorGUIUtility.TrTextContent(\"Baked Lightmap\");\n            public static readonly GUIContent interactiveAtlas = EditorGUIUtility.TrTextContent(\"Preview Lightmap\");\n            public static readonly GUIContent realtimeLM = EditorGUIUtility.TrTextContent(\"Realtime Lightmap\");\n            public static readonly GUIContent scaleInLightmap = EditorGUIUtility.TrTextContent(\"Scale In Lightmap\", \"Specifies the relative size of object's UVs within a lightmap. A value of 0 will result in the object not being lightmapped, but still contribute lighting to other objects in the Scene.\");\n            public static readonly GUIContent albedoScale = EditorGUIUtility.TrTextContent(\"Albedo Scale\", \"Specifies the relative size of object's UVs within its albedo texture that is used when calculating the influence on surrounding objects.\");\n            public static readonly GUIContent atlasIndex = EditorGUIUtility.TrTextContent(\"Lightmap Index\");\n            public static readonly GUIContent lightmapResolution = EditorGUIUtility.TrTextContent(\"Lightmap Resolution\");\n            public static readonly GUIContent lightmapObjectScale = EditorGUIUtility.TrTextContent(\"Lightmap Object Scale\");\n            public static readonly GUIContent pvrInstanceHash = EditorGUIUtility.TrTextContent(\"Instance Hash\", \"The hash of the baked GI instance.\");\n            public static readonly GUIContent pvrAtlasHash = EditorGUIUtility.TrTextContent(\"Atlas Hash\", \"The hash of the atlas this baked GI instance is a part of.\");\n            public static readonly GUIContent pvrAtlasInstanceOffset = EditorGUIUtility.TrTextContent(\"Atlas Instance Offset\", \"The offset into the transform array instances of this atlas start at.\");\n            public static readonly GUIContent realtimeLMResolution = EditorGUIUtility.TrTextContent(\"System Resolution\", \"The resolution in texels of the realtime lightmap that this renderer belongs to.\");\n            public static readonly GUIContent realtimeLMInstanceResolution = EditorGUIUtility.TrTextContent(\"Instance Resolution\", \"The resolution in texels of the realtime lightmap packed instance.\");\n            public static readonly GUIContent realtimeLMInputSystemHash = EditorGUIUtility.TrTextContent(\"System Hash\", \"The hash of the realtime system that the renderer belongs to.\");\n            public static readonly GUIContent realtimeLMInstanceHash = EditorGUIUtility.TrTextContent(\"Instance Hash\", \"The hash of the realtime GI instance.\");\n            public static readonly GUIContent realtimeLMGeometryHash = EditorGUIUtility.TrTextContent(\"Geometry Hash\", \"The hash of the realtime GI geometry that the renderer is using.\");\n            public static readonly GUIContent uvCharting = EditorGUIUtility.TrTextContent(\"Realtime UVs\");\n            public static readonly GUIContent lightmapSettings = EditorGUIUtility.TrTextContent(\"Lightmapping\");\n            public static readonly GUIContent castShadows = EditorGUIUtility.TrTextContent(\"Cast Shadows\", \"Specifies whether a geometry creates shadows or not when a shadow-casting Light shines on it.\");\n            public static readonly GUIContent receiveShadows = EditorGUIUtility.TrTextContent(\"Receive Shadows\", \"When enabled, any shadows cast from other objects are drawn on the geometry.\");\n            public static readonly GUIContent staticShadowCaster = EditorGUIUtility.TrTextContent(\"Static Shadow Caster\", \"When enabled, Unity considers this renderer as being static for the sake of shadow rendering. If the SRP implements cached shadow maps, this field indicates to the render pipeline what renderers are considered static and what renderers are considered dynamic.\");\n            public static readonly GUIContent shadowBias = EditorGUIUtility.TrTextContent(\"Shadow Bias\", \"Apply a shadow bias to prevent self-shadowing artifacts. The specified value is the proportion of the trail width at each segment.\");\n            public static readonly GUIContent contributeGI = EditorGUIUtility.TrTextContent(\"Contribute Global Illumination\", \"When enabled, this GameObject influences lightmaps and Light Probes. If you want this object itself to be lightmapped, you must enable this property.\");\n            public static readonly GUIContent receiveGITitle = EditorGUIUtility.TrTextContent(\"Receive Global Illumination\", \"If enabled, this GameObject receives global illumination from lightmaps or Light Probes. To use lightmaps, Contribute Global Illumination must be enabled.\");\n            public static readonly GUIContent lightmapParametersDefault = EditorGUIUtility.TrTextContent(\"Scene Default Parameters\");\n            public static readonly GUIContent globalIlluminationMeshLod = EditorGUIUtility.TrTextContent(\"Mesh LOD for Global Illumination\", \"The Mesh LOD index to use for Global Illumination.\");\n            public static readonly GUIContent resolutionTooHighWarning = EditorGUIUtility.TrTextContent(\"Precompute/indirect resolution for this terrain is probably too high. Use a lower realtime/indirect resolution setting in the Lighting window or assign LightmapParameters that use a lower resolution setting. Otherwise it may take a very long time to bake and memory consumption during and after the bake may be very high.\");\n            public static readonly GUIContent resolutionTooLowWarning = EditorGUIUtility.TrTextContent(\"Precompute/indirect resolution for this terrain is probably too low. If the Clustering stage takes a long time, try using a higher realtime/indirect resolution setting in the Lighting window or assign LightmapParameters that use a higher resolution setting.\");\n            public static readonly GUIContent giNotEnabledInfo = EditorGUIUtility.TrTextContent(\"Lightmapping settings are currently disabled. Enable Baked Global Illumination or Realtime Global Illumination to display these settings.\");\n            public static readonly GUIContent terrainProbeNotSupported = EditorGUIUtility.TrTextContent(\"Legacy Light Probes are enabled in the Project's Render Pipeline. These are not supported by Terrain, therefore the Scene's Ambient Probe will be used instead.\");\n            public static readonly GUIContent isPresetInfo = EditorGUIUtility.TrTextContent(\"The Contribute Global Illumination property cannot be stored in a preset.\");\n            public static readonly GUIContent giMeshNotValid = EditorGUIUtility.TrTextContent(\"It is not possible to generate lighting for this Mesh because it is missing the required attribute(s). Ensure that this Mesh has normals, vertices, and texture coordinates.\");\n            public static readonly GUIContent giMeshNotValidMultiple = EditorGUIUtility.TrTextContent(\"It is not possible to generate lighting for these Meshes because one or more of them are missing the required attribute(s). Ensure that all the Meshes you've selected have normals, vertices, and texture coordinates.\");\n\n            public static readonly GUIContent openPreview = EditorGUIUtility.TrTextContent(\"View\");\n            public static readonly GUIStyle openPreviewStyle = EditorStyles.objectFieldThumb.name + \"LightmapPreviewOverlay\";\n            public static readonly int previewPadding = 30;\n            public static readonly int previewWidth = 104;\n        }\n\n        SerializedObject m_SerializedObject;\n        SerializedObject m_GameObjectsSerializedObject;\n\n        SerializedProperty m_StaticEditorFlags;\n        SerializedProperty m_ImportantGI;\n        SerializedProperty m_StitchLightmapSeams;\n        SerializedProperty m_LightmapParameters;\n        SerializedProperty m_LightmapIndex;\n        SerializedProperty m_LightmapTilingOffsetX;\n        SerializedProperty m_LightmapTilingOffsetY;\n        SerializedProperty m_LightmapTilingOffsetZ;\n        SerializedProperty m_LightmapTilingOffsetW;\n        SerializedProperty m_PreserveUVs;\n        SerializedProperty m_AutoUVMaxDistance;\n        SerializedProperty m_IgnoreNormalsForChartDetection;\n        SerializedProperty m_AutoUVMaxAngle;\n        SerializedProperty m_MinimumChartSize;\n        SerializedProperty m_LightmapScale;\n        SerializedProperty m_ReceiveGI;\n        SerializedProperty m_CastShadows;\n        SerializedProperty m_ReceiveShadows;\n        SerializedProperty m_StaticShadowCaster;\n        SerializedProperty m_GlobalIlluminationMeshLod;\n\n        Renderer[] m_Renderers;\n        Terrain[] m_Terrains;\n\n        internal SavedBool showLightingSettings { get; set; }\n        internal SavedBool showLightmapSettings { get; set; }\n        internal SavedBool showPreviewLightmap { get; set; }\n        internal SavedBool showBakedLightmap { get; set; }\n        internal SavedBool showRealtimeLightmap { get; set; }\n\n        VisualisationGITexture m_CachedRealtimeTexture;\n        VisualisationGITexture m_CachedBakedTexture;\n\n        private bool isPrefabAsset\n        {\n            get\n            {\n                if (m_SerializedObject == null || m_SerializedObject.targetObject == null)\n                    return false;\n\n                return PrefabUtility.IsPartOfPrefabAsset(m_SerializedObject.targetObject);\n            }\n        }\n\n        private bool isPreset { get; }\n\n        private float CalcLODScale(bool isMeshRenderer)\n        {\n            float lodScale = 1.0f;\n            if (isMeshRenderer && (m_Renderers != null) && (m_Renderers.Length > 0))\n            {\n                lodScale = LightmapVisualization.GetLightmapLODLevelScale(m_Renderers[0]);\n                for (int i = 1; i < m_Renderers.Length; i++)\n                {\n                    if (!Mathf.Approximately(lodScale, LightmapVisualization.GetLightmapLODLevelScale(m_Renderers[i])))\n                        lodScale = 1.0F;\n                }\n            }\n            return lodScale;\n        }\n\n        public RendererLightingSettings(SerializedObject serializedObject)\n        {\n            m_SerializedObject = serializedObject;\n\n            m_GameObjectsSerializedObject = new SerializedObject(serializedObject.targetObjects.Select(t => ((Component)t).gameObject).ToArray());\n\n            m_ImportantGI = m_SerializedObject.FindProperty(\"m_ImportantGI\");\n            m_StitchLightmapSeams = m_SerializedObject.FindProperty(\"m_StitchLightmapSeams\");\n            m_LightmapParameters = m_SerializedObject.FindProperty(\"m_LightmapParameters\");\n            m_LightmapIndex = m_SerializedObject.FindProperty(\"m_LightmapIndex\");\n            m_LightmapTilingOffsetX = m_SerializedObject.FindProperty(\"m_LightmapTilingOffset.x\");\n            m_LightmapTilingOffsetY = m_SerializedObject.FindProperty(\"m_LightmapTilingOffset.y\");\n            m_LightmapTilingOffsetZ = m_SerializedObject.FindProperty(\"m_LightmapTilingOffset.z\");\n            m_LightmapTilingOffsetW = m_SerializedObject.FindProperty(\"m_LightmapTilingOffset.w\");\n            m_PreserveUVs = m_SerializedObject.FindProperty(\"m_PreserveUVs\");\n            m_AutoUVMaxDistance = m_SerializedObject.FindProperty(\"m_AutoUVMaxDistance\");\n            m_IgnoreNormalsForChartDetection = m_SerializedObject.FindProperty(\"m_IgnoreNormalsForChartDetection\");\n            m_AutoUVMaxAngle = m_SerializedObject.FindProperty(\"m_AutoUVMaxAngle\");\n            m_MinimumChartSize = m_SerializedObject.FindProperty(\"m_MinimumChartSize\");\n            m_LightmapScale = m_SerializedObject.FindProperty(\"m_ScaleInLightmap\");\n            m_CastShadows = m_SerializedObject.FindProperty(\"m_CastShadows\");\n            m_ReceiveShadows = m_SerializedObject.FindProperty(\"m_ReceiveShadows\");\n            m_StaticShadowCaster = m_SerializedObject.FindProperty(\"m_StaticShadowCaster\");\n            m_ReceiveGI = m_SerializedObject.FindProperty(\"m_ReceiveGI\");\n            m_GlobalIlluminationMeshLod = m_SerializedObject.FindProperty(\"m_GlobalIlluminationMeshLod\");\n\n            m_Renderers = m_SerializedObject.targetObjects.OfType<Renderer>().ToArray();\n            m_Terrains = m_SerializedObject.targetObjects.OfType<Terrain>().ToArray();\n\n            m_StaticEditorFlags = m_GameObjectsSerializedObject.FindProperty(\"m_StaticEditorFlags\");\n\n            if (m_SerializedObject == null || m_SerializedObject.targetObject == null)\n                isPreset = false;\n            else\n                isPreset = Preset.IsEditorTargetAPreset(m_SerializedObject.targetObject);\n        }\n\n        public void RenderSettings(bool showLightmapSettings, bool showMeshLODSettings, int meshLodCount)\n        {\n            if (m_SerializedObject == null || m_GameObjectsSerializedObject == null || m_GameObjectsSerializedObject.targetObjectsCount == 0)\n                return;\n\n            var settings = Lightmapping.GetLightingSettingsOrDefaultsFallback();\n            var lightmapper = settings.lightmapper;\n            bool bakedGI = settings.bakedGI;\n            bool realtimeGI = settings.realtimeGI;\n\n            m_GameObjectsSerializedObject.Update();\n\n            ReceiveGI receiveGI = (ReceiveGI)m_ReceiveGI.intValue;\n            bool contributeGI = isPreset ? true : (m_StaticEditorFlags.intValue & (int)StaticEditorFlags.ContributeGI) != 0;\n            bool showEnlightenSettings = (isPreset || isPrefabAsset || realtimeGI) && SupportedRenderingFeatures.active.enlighten;\n\n            // m_ReceiveGI might still be set to Lightmaps, but LightProbes is shown in the inspector since the contributeGI if off.\n            // In this case we still have to mark it as \"multiple values\" even though both have \"Lightmaps\" as the value, but one is showing a grayed out \"Light Probes\" in the UI\n            bool showMixedGIValue = m_ReceiveGI.hasMultipleDifferentValues || (isPreset ? false : ((m_StaticEditorFlags.hasMultipleDifferentValuesBitwise & (int)StaticEditorFlags.ContributeGI) != 0));\n\n            showLightingSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(showLightingSettings.value, Styles.lightingSettings);\n\n            if (showLightingSettings.value)\n            {\n                EditorGUI.indentLevel += 1;\n\n                EditorGUILayout.PropertyField(m_CastShadows, Styles.castShadows, true);\n\n                bool isDeferredRenderingPath = SceneView.IsUsingDeferredRenderingPath();\n\n                if (SupportedRenderingFeatures.active.receiveShadows)\n                {\n                    using (new EditorGUI.DisabledScope(isDeferredRenderingPath))\n                        EditorGUILayout.PropertyField(m_ReceiveShadows, Styles.receiveShadows, true);\n                }\n\n                if (m_CastShadows.hasMultipleDifferentValues || m_CastShadows.intValue != 0)\n                {\n                    RenderPipelineAsset srpAsset = GraphicsSettings.currentRenderPipeline;\n                    if (srpAsset != null)\n                        EditorGUILayout.PropertyField(m_StaticShadowCaster, Styles.staticShadowCaster);\n                }\n\n                if (!showLightmapSettings)\n                {\n                    EditorGUI.indentLevel -= 1;\n\n                    EditorGUILayout.EndFoldoutHeaderGroup();\n\n                    return;\n                }\n\n                using (new EditorGUI.DisabledScope(isPreset))\n                    contributeGI = ContributeGISettings();\n\n                if (isPreset)\n                    EditorGUILayout.HelpBox(Styles.isPresetInfo.text, MessageType.Info);\n\n                if (!(bakedGI || realtimeGI) && contributeGI && !isPrefabAsset && !isPreset)\n                {\n                    EditorGUILayout.HelpBox(Styles.giNotEnabledInfo.text, MessageType.Info);\n                    EditorGUI.indentLevel -= 1;\n\n                    EditorGUILayout.EndFoldoutHeaderGroup();\n\n                    return;\n                }\n\n                using (new EditorGUI.IndentLevelScope())\n                {\n                    if (contributeGI)\n                    {\n                        var rect = EditorGUILayout.GetControlRect();\n                        EditorGUI.BeginProperty(rect, Styles.receiveGITitle, m_ReceiveGI);\n                        EditorGUI.BeginChangeCheck();\n\n                        receiveGI = (ReceiveGI)EditorGUI.IntPopup(rect, Styles.receiveGITitle, (int)receiveGI, Styles.receiveGILightmapStrings, Styles.receiveGILightmapValues);\n\n                        if (EditorGUI.EndChangeCheck())\n                            m_ReceiveGI.intValue = (int)receiveGI;\n\n                        EditorGUI.EndProperty();\n\n                        if (showEnlightenSettings)\n                            EditorGUILayout.PropertyField(m_ImportantGI, Styles.importantGI);\n\n                        if (receiveGI == ReceiveGI.LightProbes && !showMixedGIValue)\n                        {\n                            LightmapScaleGUI(true, Styles.albedoScale, true);\n                        }\n                    }\n                    else\n                    {\n                        using (new EditorGUI.DisabledScope(true))\n                        {\n                            EditorGUI.showMixedValue = showMixedGIValue;\n                            receiveGI = (ReceiveGI)EditorGUILayout.IntPopup(Styles.receiveGITitle, (int)ReceiveGI.LightProbes, Styles.receiveGILightmapStrings, Styles.receiveGILightmapValues);\n                            EditorGUI.showMixedValue = false;\n                        }\n                    }\n\n                    if (contributeGI && showMeshLODSettings)\n                    {\n                        using (new EditorGUI.DisabledScope(meshLodCount == 1))\n                        {\n                            EditorGUILayout.IntSlider(m_GlobalIlluminationMeshLod, 0, meshLodCount - 1, Styles.globalIlluminationMeshLod);\n                        }\n                    }\n                }\n\n                EditorGUI.indentLevel -= 1;\n            }\n\n            EditorGUILayout.EndFoldoutHeaderGroup();\n\n            if (showLightmapSettings && contributeGI && receiveGI == ReceiveGI.Lightmaps && !showMixedGIValue)\n            {\n                this.showLightmapSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(this.showLightmapSettings.value, Styles.lightmapSettings);\n\n                if (this.showLightmapSettings.value)\n                {\n                    EditorGUI.indentLevel += 1;\n\n                    bool showProgressiveSettings = isPreset || isPrefabAsset || bakedGI;\n\n                    LightmapScaleGUI(true, Styles.scaleInLightmap, false);\n\n                    if (showProgressiveSettings)\n                        EditorGUILayout.PropertyField(m_StitchLightmapSeams, Styles.stitchLightmapSeams);\n\n                    LightmapParametersGUI(m_LightmapParameters, Styles.lightmapParameters);\n\n                    if (showEnlightenSettings)\n                    {\n                        RendererUVSettings();\n                    }\n\n                    if ((m_Renderers != null) && (m_Renderers.Length > 0))\n                    {\n                        ShowAtlasGUI(m_Renderers[0].GetInstanceID(), true, true);\n                        ShowAtlasGUI(m_Renderers[0].GetInstanceID(), true, false);\n                        ShowRealtimeLMGUI(m_Renderers[0]);\n\n                        DisplayMeshWarning();\n\n                        if (showEnlightenSettings)\n                        {\n                            if (Lightmapping.HasClampedResolution(m_Renderers[0]))\n                                EditorGUILayout.HelpBox(Styles.clampedPackingResolution.text, MessageType.Warning);\n                        }\n\n                        if (showProgressiveSettings)\n                        {\n                            if (Lightmapping.HasUVOverlaps(m_Renderers[0]))\n                                EditorGUILayout.HelpBox(Styles.uvOverlap.text, MessageType.Warning);\n                        }\n                    }\n\n                    EditorGUI.indentLevel -= 1;\n                }\n\n                EditorGUILayout.EndFoldoutHeaderGroup();\n            }\n        }\n\n        public void RenderTerrainSettings()\n        {\n            if (m_SerializedObject == null || m_GameObjectsSerializedObject == null || m_GameObjectsSerializedObject.targetObjectsCount == 0)\n                return;\n\n            m_GameObjectsSerializedObject.Update();\n\n            var settings = Lightmapping.GetLightingSettingsOrDefaultsFallback();\n            bool bakedGI = settings.bakedGI;\n            bool realtimeGI = settings.realtimeGI;\n\n            ReceiveGI receiveGI = (ReceiveGI)m_ReceiveGI.intValue;\n\n            bool contributeGI = isPreset ? true : (m_StaticEditorFlags.intValue & (int)StaticEditorFlags.ContributeGI) != 0;\n\n            showLightingSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(showLightingSettings.value, Styles.lightingSettings);\n\n            if (showLightingSettings.value)\n            {\n                EditorGUI.indentLevel += 1;\n\n                using (new EditorGUI.DisabledScope(isPreset))\n                    contributeGI = ContributeGISettings();\n\n                if (isPreset)\n                    EditorGUILayout.HelpBox(Styles.isPresetInfo.text, MessageType.Info);\n\n                if (!(bakedGI || realtimeGI) && contributeGI && !isPrefabAsset && !isPreset)\n                {\n                    EditorGUILayout.HelpBox(Styles.giNotEnabledInfo.text, MessageType.Info);\n                    EditorGUI.indentLevel -= 1;\n                    EditorGUILayout.EndFoldoutHeaderGroup();\n                    return;\n                }\n\n                bool srpHasAlternativeToLegacyProbes = UnityEngine.Rendering.SupportedRenderingFeatures.active.overridesLightProbeSystem;\n                EditorGUI.BeginChangeCheck();\n\n                receiveGI = (ReceiveGI)EditorGUILayout.IntPopup(Styles.receiveGITitle, (int)receiveGI, Styles.receiveGILightmapStrings, Styles.receiveGILightmapValues);\n\n                if (EditorGUI.EndChangeCheck())\n                    m_ReceiveGI.intValue = (int)receiveGI;\n\n                if (!srpHasAlternativeToLegacyProbes)\n                    EditorGUILayout.HelpBox(Styles.terrainProbeNotSupported.text, MessageType.Warning);\n\n                EditorGUI.indentLevel -= 1;\n            }\n\n            EditorGUILayout.EndFoldoutHeaderGroup();\n            EditorGUILayout.Space();\n\n            if (contributeGI && receiveGI == ReceiveGI.Lightmaps)\n            {\n                showLightmapSettings.value = EditorGUILayout.BeginFoldoutHeaderGroup(showLightmapSettings.value, Styles.lightmapSettings);\n\n                if (showLightmapSettings.value)\n                {\n                    EditorGUI.indentLevel += 1;\n\n                    if (GUI.enabled)\n                        ShowTerrainChunks(m_Terrains);\n\n                    LightmapScaleGUI(false, Styles.scaleInLightmap, false);\n\n                    LightmapParametersGUI(m_LightmapParameters, Styles.lightmapParameters);\n\n                    if ((m_Terrains != null) && (m_Terrains.Length > 0))\n                    {\n                        if (GUI.enabled && m_Terrains.Length == 1 && m_Terrains[0].terrainData != null)\n                            ShowBakePerformanceWarning(m_Terrains[0]);\n\n                        ShowAtlasGUI(m_Terrains[0].GetInstanceID(), false, true);\n                        ShowAtlasGUI(m_Terrains[0].GetInstanceID(), false, false);\n                        ShowRealtimeLMGUI(m_Terrains[0]);\n                    }\n\n                    EditorGUI.indentLevel -= 1;\n                }\n\n                EditorGUILayout.EndFoldoutHeaderGroup();\n\n                GUILayout.Space(10);\n            }\n        }\n\n        bool ContributeGISettings()\n        {\n            if (isPreset)\n            {\n                EditorGUILayout.Toggle(Styles.contributeGI, true);\n                return true;\n            }\n\n            bool contributeGI = (m_StaticEditorFlags.intValue & (int)StaticEditorFlags.ContributeGI) != 0;\n            bool mixedValue = (m_StaticEditorFlags.hasMultipleDifferentValuesBitwise & (int)StaticEditorFlags.ContributeGI) != 0;\n            EditorGUI.showMixedValue = mixedValue;\n\n            EditorGUI.BeginChangeCheck();\n            contributeGI = EditorGUILayout.Toggle(Styles.contributeGI, contributeGI);\n\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                SceneModeUtility.SetStaticFlags(m_GameObjectsSerializedObject.targetObjects, (int)StaticEditorFlags.ContributeGI, contributeGI);\n                m_GameObjectsSerializedObject.SetIsDifferentCacheDirty();\n                m_GameObjectsSerializedObject.Update();\n            }\n\n            // show a warning if not all renderers are valid, even when not active or enabled\n            if (contributeGI || mixedValue)\n                if (m_Renderers != null && !m_Renderers.All(Lightmapping.IsRendererValid))\n                    EditorGUILayout.HelpBox(m_Renderers.Length > 1 ? Styles.giMeshNotValidMultiple.text : Styles.giMeshNotValid.text, MessageType.Warning);\n\n            EditorGUI.showMixedValue = false;\n\n            return contributeGI && !mixedValue;\n        }\n\n        void RendererUVSettings()\n        {\n            // TODO: This is very temporary and the flag needs to be changed.\n            bool optimizeRealtimeUVs = !m_PreserveUVs.boolValue;\n\n            var rect = EditorGUILayout.GetControlRect();\n            EditorGUI.BeginProperty(rect, Styles.optimizeRealtimeUVs, m_PreserveUVs);\n            EditorGUI.BeginChangeCheck();\n\n            optimizeRealtimeUVs = EditorGUI.Toggle(rect, Styles.optimizeRealtimeUVs, optimizeRealtimeUVs);\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_PreserveUVs.boolValue = !optimizeRealtimeUVs;\n            }\n            EditorGUI.EndProperty();\n\n            if (optimizeRealtimeUVs)\n            {\n                EditorGUI.indentLevel++;\n                EditorGUILayout.PropertyField(m_AutoUVMaxDistance, Styles.autoUVMaxDistance);\n                if (m_AutoUVMaxDistance.floatValue < 0.0f)\n                    m_AutoUVMaxDistance.floatValue = 0.0f;\n                EditorGUILayout.Slider(m_AutoUVMaxAngle, 0, 180, Styles.autoUVMaxAngle);\n                EditorGUI.indentLevel--;\n            }\n\n            EditorGUILayout.PropertyField(m_IgnoreNormalsForChartDetection, Styles.ignoreNormalsForChartDetection);\n\n            EditorGUILayout.IntPopup(m_MinimumChartSize, Styles.minimumChartSizeStrings, Styles.minimumChartSizeValues, Styles.minimumChartSize);\n        }\n\n        void ShowClampedSizeInLightmapGUI(float lightmapScale, float cachedSurfaceArea, bool isSSD)\n        {\n            float sizeInLightmap = Mathf.Sqrt(cachedSurfaceArea) * Lightmapping.GetLightingSettingsOrDefaultsFallback().lightmapResolution * lightmapScale;\n\n            if (sizeInLightmap > Lightmapping.GetLightingSettingsOrDefaultsFallback().lightmapMaxSize)\n                EditorGUILayout.HelpBox(Styles.clampedSize.text, MessageType.Info);\n        }\n\n        void LightmapScaleGUI(bool isMeshRenderer, GUIContent title, bool isSSD)\n        {\n            // SSDs (with the exception of those being computed with Enlighten) do not end up in a lightmap,\n            // therefore we do not show clamping information.\n            if (isSSD)\n                return;\n\n            float lodScale = CalcLODScale(isMeshRenderer);\n            float lightmapScale = lodScale * m_LightmapScale.floatValue;\n\n            Rect rect = EditorGUILayout.GetControlRect();\n            EditorGUI.BeginProperty(rect, Styles.scaleInLightmap, m_LightmapScale);\n            EditorGUI.BeginChangeCheck();\n            lightmapScale = EditorGUI.FloatField(rect, title, lightmapScale);\n            if (EditorGUI.EndChangeCheck())\n                m_LightmapScale.floatValue = Mathf.Max(lightmapScale / Mathf.Max(lodScale, float.Epsilon), 0.0f);\n            EditorGUI.EndProperty();\n\n            float cachedSurfaceArea = 0.0f;\n\n            if (isMeshRenderer)\n            {\n                if ((m_Renderers != null) && (m_Renderers.Length > 0))\n                {\n                    lightmapScale = lightmapScale * LightmapVisualization.GetLightmapLODLevelScale(m_Renderers[0]);\n\n                    // tell the user if the object's size in lightmap has reached the max atlas size\n                    cachedSurfaceArea = InternalMeshUtil.GetCachedMeshSurfaceArea((MeshRenderer)m_Renderers[0]);\n                }\n            }\n            else //terrain\n            {\n                // tell the user if the object's size in lightmap has reached the max atlas size\n                if ((m_Terrains != null) && (m_Terrains.Length > 0))\n                {\n                    var terrainData = m_Terrains[0].terrainData;\n                    cachedSurfaceArea = terrainData != null ? terrainData.size.x * terrainData.size.z : 0.0f;\n                }\n            }\n\n            ShowClampedSizeInLightmapGUI(lightmapScale, cachedSurfaceArea, isSSD);\n        }\n\n        void ShowAtlasGUI(int instanceID, bool isMeshRenderer, bool useInteractiveLightBakingData)\n        {\n            const int InfluenceOnlyIndex = 0xFFFE; // kLightmapIndexInfluenceOnly\n            const int NotLightmappedIndex = 0xFFFF; // kLightmapIndexNotLightmapped\n\n            int lightmapIndex = useInteractiveLightBakingData ?\n                InteractiveLightBaking.GetLightmapIndexFromRenderer(instanceID) :\n                (m_LightmapIndex?.intValue ?? NotLightmappedIndex);\n\n            Vector4 lightmapST = useInteractiveLightBakingData ?\n                InteractiveLightBaking.GetLightmapSTFromRenderer(instanceID) :\n                new Vector4(m_LightmapTilingOffsetX.floatValue, m_LightmapTilingOffsetY.floatValue, m_LightmapTilingOffsetZ.floatValue, m_LightmapTilingOffsetW.floatValue);\n\n            // If lightmap index is missing, or renderer is not lightmapped, hide this gui\n            if (lightmapIndex >= InfluenceOnlyIndex)\n                return;\n\n            // Hide preview lightmaps if we aren't in preview mode\n            if (useInteractiveLightBakingData && !Lightmapping.shouldBakeInteractively)\n                return;\n\n            Hash128 contentHash = LightmapVisualizationUtility.GetBakedGITextureHash(lightmapIndex, 0, GITextureType.Baked, useInteractiveLightBakingData);\n\n            // if we need to fetch a new texture\n            if (m_CachedBakedTexture.texture == null || m_CachedBakedTexture.contentHash != contentHash)\n                m_CachedBakedTexture = LightmapVisualizationUtility.GetBakedGITexture(lightmapIndex, 0, GITextureType.Baked, useInteractiveLightBakingData);\n\n            if (m_CachedBakedTexture.texture == null)\n                return;\n\n            SavedBool showLightmap = useInteractiveLightBakingData ? showPreviewLightmap : showBakedLightmap;\n            GUIContent foldoutContent = useInteractiveLightBakingData ? Styles.interactiveAtlas : Styles.atlas;\n            showLightmap.value = EditorGUILayout.Foldout(showLightmap.value, foldoutContent, true);\n\n            if (!showLightmap.value)\n                return;\n\n            EditorGUI.indentLevel += 1;\n\n            GUILayout.BeginHorizontal();\n\n            DrawLightmapPreview(m_CachedBakedTexture.texture, false, instanceID, useInteractiveLightBakingData);\n\n            GUILayout.BeginVertical();\n\n            GUILayout.Label(Styles.atlasIndex.text + \": \" + lightmapIndex);\n            GUILayout.Label(Styles.atlasTilingX.text + \": \" + lightmapST.x.ToString(CultureInfo.InvariantCulture.NumberFormat));\n            GUILayout.Label(Styles.atlasTilingY.text + \": \" + lightmapST.y.ToString(CultureInfo.InvariantCulture.NumberFormat));\n            GUILayout.Label(Styles.atlasOffsetX.text + \": \" + lightmapST.z.ToString(CultureInfo.InvariantCulture.NumberFormat));\n            GUILayout.Label(Styles.atlasOffsetY.text + \": \" + lightmapST.w.ToString(CultureInfo.InvariantCulture.NumberFormat));\n\n            var settings = Lightmapping.GetLightingSettingsOrDefaultsFallback();\n\n            float lightmapResolution = settings.lightmapResolution * CalcLODScale(isMeshRenderer) * m_LightmapScale.floatValue;\n\n            if (isMeshRenderer && (m_Renderers != null) && (m_Renderers.Length > 0))\n            {\n                Transform transform = m_Renderers[0].GetComponent<Transform>();\n                float lightmapObjectScale = System.Math.Min(System.Math.Min(transform.localScale.x, transform.localScale.y), transform.localScale.z);\n                GUILayout.Label(Styles.lightmapResolution.text + \": \" + lightmapResolution.ToString(CultureInfo.InvariantCulture.NumberFormat));\n                GUILayout.Label(Styles.lightmapObjectScale.text + \": \" + lightmapObjectScale.ToString(CultureInfo.InvariantCulture.NumberFormat));\n            }\n\n            GUILayout.EndVertical();\n            GUILayout.FlexibleSpace();\n            GUILayout.EndHorizontal();\n\n            GUILayout.Space(5);\n        }\n\n        void ShowRealtimeLMGUI(Terrain terrain)\n        {\n            Hash128 inputSystemHash;\n            if (terrain == null || !Lightmapping.GetInputSystemHash(terrain.GetInstanceID(), out inputSystemHash) || inputSystemHash == new Hash128())\n                return; // early return since we don't have any lightmaps for it\n\n            if (!UpdateRealtimeTexture(inputSystemHash, terrain.GetInstanceID()))\n                return;\n\n            showRealtimeLightmap.value = EditorGUILayout.Foldout(showRealtimeLightmap.value, Styles.realtimeLM, true);\n\n            if (!showRealtimeLightmap.value)\n                return;\n\n            EditorGUI.indentLevel += 1;\n\n            GUILayout.BeginHorizontal();\n\n            DrawLightmapPreview(m_CachedRealtimeTexture.texture, true, terrain.GetInstanceID(), false);\n\n            GUILayout.BeginVertical();\n\n            // Resolution of the system.\n            int width, height;\n            int numChunksInX, numChunksInY;\n            if (Lightmapping.GetTerrainSystemResolution(terrain, out width, out height, out numChunksInX, out numChunksInY))\n            {\n                var str = width + \"x\" + height;\n                if (numChunksInX > 1 || numChunksInY > 1)\n                    str += string.Format(\" ({0}x{1} chunks)\", numChunksInX, numChunksInY);\n                GUILayout.Label(Styles.realtimeLMResolution.text + \": \" + str);\n            }\n\n            GUILayout.EndVertical();\n            GUILayout.FlexibleSpace();\n            GUILayout.EndHorizontal();\n\n            EditorGUI.indentLevel -= 1;\n\n            GUILayout.Space(5);\n        }\n\n        void ShowRealtimeLMGUI(Renderer renderer)\n        {\n            Hash128 inputSystemHash;\n            if (renderer == null || !Lightmapping.GetInputSystemHash(renderer.GetInstanceID(), out inputSystemHash) || inputSystemHash == new Hash128())\n                return; // early return since we don't have any lightmaps for it\n\n            if (!UpdateRealtimeTexture(inputSystemHash, renderer.GetInstanceID()))\n                return;\n\n            showRealtimeLightmap.value = EditorGUILayout.Foldout(showRealtimeLightmap.value, Styles.realtimeLM, true);\n\n            if (!showRealtimeLightmap.value)\n                return;\n\n            EditorGUI.indentLevel += 1;\n\n            GUILayout.BeginHorizontal();\n\n            DrawLightmapPreview(m_CachedRealtimeTexture.texture, true, renderer.GetInstanceID(), false);\n\n            GUILayout.BeginVertical();\n\n            int instWidth, instHeight;\n            if (Lightmapping.GetInstanceResolution(renderer, out instWidth, out instHeight))\n            {\n                GUILayout.Label(Styles.realtimeLMInstanceResolution.text + \": \" + instWidth + \"x\" + instHeight);\n            }\n\n            int width, height;\n            if (Lightmapping.GetSystemResolution(renderer, out width, out height))\n            {\n                GUILayout.Label(Styles.realtimeLMResolution.text + \": \" + width + \"x\" + height);\n            }\n\n            GUILayout.EndVertical();\n            GUILayout.FlexibleSpace();\n            GUILayout.EndHorizontal();\n\n            if (Unsupported.IsDeveloperMode())\n            {\n                Hash128 instanceHash;\n                if (Lightmapping.GetInstanceHash(renderer, out instanceHash))\n                {\n                    EditorGUILayout.LabelField(Styles.realtimeLMInstanceHash, GUIContent.Temp(instanceHash.ToString()));\n                }\n\n                Hash128 geometryHash;\n                if (Lightmapping.GetGeometryHash(renderer, out geometryHash))\n                {\n                    EditorGUILayout.LabelField(Styles.realtimeLMGeometryHash, GUIContent.Temp(geometryHash.ToString()));\n                }\n\n                EditorGUILayout.LabelField(Styles.realtimeLMInputSystemHash, GUIContent.Temp(inputSystemHash.ToString()));\n            }\n\n            EditorGUI.indentLevel -= 1;\n\n            GUILayout.Space(5);\n        }\n\n        bool UpdateRealtimeTexture(Hash128 inputSystemHash, int instanceId)\n        {\n            if (inputSystemHash == new Hash128())\n                return false;\n\n            Hash128 contentHash = LightmapVisualizationUtility.GetRealtimeGITextureHash(inputSystemHash, GITextureType.Irradiance);\n\n            // if we need to fetch a new texture\n            if (m_CachedRealtimeTexture.texture == null || m_CachedRealtimeTexture.contentHash != contentHash)\n                m_CachedRealtimeTexture = LightmapVisualizationUtility.GetRealtimeGITexture(inputSystemHash, GITextureType.Irradiance);\n\n            if (m_CachedRealtimeTexture.texture == null)\n                return false;\n\n            return true;\n        }\n\n        private void DrawLightmapPreview(Texture2D texture, bool realtimeLightmap, int instanceId, bool useInteractiveLightBakingData)\n        {\n            GUILayout.Space(Styles.previewPadding);\n\n            int previewWidth = Styles.previewWidth - 4; // padding\n\n            Rect rect = GUILayoutUtility.GetRect(previewWidth, previewWidth, EditorStyles.objectField);\n            Rect buttonRect = new Rect(rect.xMax - 35, rect.yMax - 14, 35, 14);\n\n            if (Event.current.type == EventType.MouseDown)\n            {\n                if ((buttonRect.Contains(Event.current.mousePosition) && Event.current.clickCount == 1) ||\n                    (rect.Contains(Event.current.mousePosition) && Event.current.clickCount == 2))\n                {\n                    LightmapPreviewWindow.CreateLightmapPreviewWindow(instanceId, realtimeLightmap, false, useInteractiveLightBakingData);\n                }\n                else if (rect.Contains(Event.current.mousePosition) && Event.current.clickCount == 1)\n                {\n                    Object actualTargetObject = texture;\n                    Component com = actualTargetObject as Component;\n\n                    if (com)\n                        actualTargetObject = com.gameObject;\n\n                    EditorGUI.PingObjectOrShowPreviewOnClick(actualTargetObject, rect);\n                }\n            }\n\n            EditorGUI.Toggle(rect, false, EditorStyles.objectFieldThumb);\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                rect = EditorStyles.objectFieldThumb.padding.Remove(rect);\n                EditorGUI.DrawPreviewTexture(rect, texture);\n\n                Styles.openPreviewStyle.Draw(rect, Styles.openPreview, false, false, false, false);\n            }\n\n            float spacing = Mathf.Max(5.0f, EditorGUIUtility.labelWidth - Styles.previewPadding - Styles.previewWidth);\n            GUILayout.Space(spacing);\n        }\n\n        private void DisplayMeshWarning()\n        {\n            if (isPreset)\n                return;\n\n            Mesh mesh = GetSharedMesh(m_Renderers[0]);\n\n            var settings = Lightmapping.GetLightingSettingsOrDefaultsFallback();\n\n            bool showEnlightenSettings = isPrefabAsset || settings.realtimeGI;\n\n            if (!HasSupportedTopologyForGI(mesh))\n            {\n                EditorGUILayout.HelpBox(Styles.unsupportedTopology.text, MessageType.Warning);\n                return;\n            }\n\n            if (!HasVertices(mesh))\n            {\n                EditorGUILayout.HelpBox(Styles.noVerticesNoLightmapping.text, MessageType.Warning);\n                return;\n            }\n\n            if (!HasNormals(mesh))\n            {\n                EditorGUILayout.HelpBox(Styles.noNormalsNoLightmapping.text, MessageType.Warning);\n                return;\n            }\n        }\n\n        static Mesh GetSharedMesh(Renderer renderer)\n        {\n            Mesh mesh = null;\n\n            if (renderer is MeshRenderer)\n            {\n                MeshFilter mf = renderer.GetComponent<MeshFilter>();\n                if (mf != null)\n                    mesh = mf.sharedMesh;\n            }\n\n            return mesh;\n        }\n\n        static bool HasNormals(Mesh mesh)\n        {\n            return mesh != null && InternalMeshUtil.HasNormals(mesh);\n        }\n\n        static bool HasVertices(Mesh mesh)\n        {\n            return mesh != null && InternalMeshUtil.HasVertices(mesh);\n        }\n\n        static bool HasSupportedTopologyForGI(Mesh mesh)\n        {\n            return mesh != null && InternalMeshUtil.HasSupportedTopologyForGI(mesh);\n        }\n\n        static private bool isBuiltIn(SerializedProperty prop)\n        {\n            if (prop.objectReferenceValue != null)\n            {\n                var parameters = prop.objectReferenceValue as LightmapParameters;\n                return (parameters.hideFlags == HideFlags.NotEditable);\n            }\n\n            return false;\n        }\n\n        static public void LightmapParametersGUI(SerializedProperty prop, GUIContent content)\n        {\n            EditorGUILayout.BeginHorizontal();\n\n            var rect = EditorGUILayout.GetControlRect();\n            EditorGUI.BeginProperty(rect, content, prop);\n\n            rect = EditorGUI.PrefixLabel(rect, content);\n\n            GUIContent buttonContent = prop.hasMultipleDifferentValues ? EditorGUI.mixedValueContent : (prop.objectReferenceValue != null ? GUIContent.Temp(prop.objectReferenceStringValue) : Styles.lightmapParametersDefault);\n\n            if (EditorGUI.DropdownButton(rect, buttonContent, FocusType.Passive, EditorStyles.popup))\n                AssetPopupBackend.ShowAssetsPopupMenu<LightmapParameters>(rect, prop.objectReferenceTypeString, prop, \"giparams\", Styles.lightmapParametersDefault.text);\n\n            string label = isBuiltIn(prop) ? \"View\" : \"Edit...\";\n\n            // If object is null, then get the scene parameter setting and view this instead.\n            using (new EditorGUI.DisabledScope(prop.hasMultipleDifferentValues))\n            {\n                if (prop.objectReferenceValue == null)\n                {\n                    SerializedObject so = new SerializedObject(Lightmapping.GetLightingSettingsOrDefaultsFallback());\n                    SerializedProperty lightmapParameters = so.FindProperty(\"m_LightmapParameters\");\n\n                    if (lightmapParameters.objectReferenceValue != null)\n                    {\n                        label = isBuiltIn(lightmapParameters) ? \"View\" : \"Edit...\";\n\n                        if (GUILayout.Button(label, EditorStyles.miniButton, GUILayout.ExpandWidth(false)))\n                        {\n                            Selection.activeObject = lightmapParameters.objectReferenceValue;\n                        }\n                    }\n                }\n                else\n                {\n                    if (GUILayout.Button(label, EditorStyles.miniButton, GUILayout.ExpandWidth(false)))\n                    {\n                        Selection.activeObject = prop.objectReferenceValue;\n                    }\n                }\n            }\n\n            EditorGUILayout.EndHorizontal();\n            EditorGUI.EndProperty();\n        }\n\n        void ShowTerrainChunks(Terrain[] terrains)\n        {\n            if (terrains == null)\n                return;\n\n            int terrainChunksX = 0, terrainChunksY = 0;\n            foreach (var terrain in terrains)\n            {\n                int tmpChunksX = 0, tmpChunksY = 0;\n                Lightmapping.GetTerrainGIChunks(terrain, ref tmpChunksX, ref tmpChunksY);\n                if (terrainChunksX == 0 && terrainChunksY == 0)\n                {\n                    terrainChunksX = tmpChunksX;\n                    terrainChunksY = tmpChunksY;\n                }\n                else if (terrainChunksX != tmpChunksX || terrainChunksY != tmpChunksY)\n                {\n                    terrainChunksX = terrainChunksY = 0;\n                    break;\n                }\n            }\n            if (terrainChunksX * terrainChunksY > 1)\n                EditorGUILayout.HelpBox(string.Format(L10n.Tr(\"Terrain is chunked up into {0} instances for baking.\"), terrainChunksX * terrainChunksY), MessageType.None);\n        }\n\n        void ShowBakePerformanceWarning(Terrain terrain)\n        {\n            var terrainWidth = terrain.terrainData.size.x;\n            var terrainHeight = terrain.terrainData.size.z;\n            var lightmapParameters = (LightmapParameters)m_LightmapParameters.objectReferenceValue ?? new LightmapParameters();\n            var indirectResolution = Lightmapping.GetLightingSettingsOrDefaultsFallback().indirectResolution;\n\n            var terrainSystemTexelsInWidth = terrainWidth * lightmapParameters.resolution * indirectResolution;\n            var terrainSystemTexelsInHeight = terrainHeight * lightmapParameters.resolution * indirectResolution;\n            const int kTerrainTexelsThreshold = 64 * 8;\n            if (terrainSystemTexelsInWidth > kTerrainTexelsThreshold || terrainSystemTexelsInHeight > kTerrainTexelsThreshold)\n            {\n                EditorGUILayout.HelpBox(Styles.resolutionTooHighWarning.text, MessageType.Warning);\n            }\n\n            var terrainClustersInWidth = terrainSystemTexelsInWidth * lightmapParameters.clusterResolution;\n            var terrainClustersInHeight = terrainSystemTexelsInHeight * lightmapParameters.clusterResolution;\n            var terrainTrisPerClusterInWidth = terrain.terrainData.heightmapResolution / terrainClustersInWidth;\n            var terrainTrisPerClusterInHeight = terrain.terrainData.heightmapResolution / terrainClustersInHeight;\n            const float kTerrainClusterTriDensityThreshold = 256.0f / 5.0f;\n            if (terrainTrisPerClusterInWidth > kTerrainClusterTriDensityThreshold || terrainTrisPerClusterInHeight > kTerrainClusterTriDensityThreshold)\n            {\n                EditorGUILayout.HelpBox(Styles.resolutionTooLowWarning.text, MessageType.Warning);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ReorderableListWrapper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEditor;\nusing UnityEditor.SceneManagement;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditorInternal\n{\n    // Provides a default appearance for a generic reorderable list that is typically used in inspector to draw arrays\n    internal class ReorderableListWrapper\n    {\n        public static class Constants\n        {\n            public const float kHeaderPadding = 3f;\n            public const float kArraySizeWidth = 48f;\n            public const float kDefaultFoldoutHeaderHeight = 18;\n        }\n\n        internal ReorderableList m_ReorderableList;\n        float m_HeaderHeight;\n        bool m_Reorderable = false;\n        bool m_ListIsPatchedInPrefabModeInContext = false;\n        bool m_DisableListElements = false;\n\n        SerializedProperty m_OriginalProperty;\n        SerializedProperty m_ArraySize;\n        string m_PropertyPath = string.Empty;\n        string m_PropertyPathArraySize = string.Empty;\n\n        internal static Rect s_ToolTipRect;\n\n        int m_LastArraySize = -1;\n        internal SerializedProperty Property\n        {\n            get\n            {\n                return m_OriginalProperty;\n            }\n            set\n            {\n                m_OriginalProperty = value;\n                if (!m_OriginalProperty.isValid)\n                {\n                    m_ArraySize = null;\n                    m_PropertyPath = string.Empty;\n                    m_PropertyPathArraySize = string.Empty;\n                    return;\n                }\n                m_ArraySize = m_OriginalProperty.FindPropertyRelative(\"Array.size\");\n                m_PropertyPath = m_OriginalProperty.propertyPath;\n                m_PropertyPathArraySize = m_OriginalProperty + \".Array.size\";\n\n                if (m_ReorderableList != null)\n                {\n                    bool versionChanged = !SerializedProperty.VersionEquals(m_ReorderableList.serializedProperty, m_OriginalProperty);\n                    bool serializedObjectChanged = m_ReorderableList.serializedProperty.serializedObject.m_NativeObjectPtr != m_OriginalProperty.serializedObject.m_NativeObjectPtr;\n\n                    m_ReorderableList.serializedProperty = m_OriginalProperty;\n                    UpdatePrefabPatchState(m_OriginalProperty.serializedObject.targetObject);\n\n                    if (versionChanged || serializedObjectChanged || m_ArraySize != null && m_LastArraySize != m_ArraySize.intValue)\n                    {\n                        m_ReorderableList.InvalidateCacheRecursive();\n                        ReorderableList.InvalidateParentCaches(m_ReorderableList.serializedProperty.propertyPath);\n\n                        if (m_ArraySize != null) m_LastArraySize = m_ArraySize.intValue;\n                    }\n                }\n            }\n        }\n\n        public static string GetPropertyIdentifier(SerializedProperty serializedProperty)\n        {\n            // Property may be disposed\n            try\n            {\n                return serializedProperty?.propertyPath + serializedProperty.serializedObject.targetObject.GetInstanceID() + (GUIView.current?.nativeHandle.ToInt32() ?? -1);\n            }\n            catch (NullReferenceException)\n            {\n                return string.Empty;\n            }\n        }\n\n        ReorderableListWrapper() {}\n\n        public ReorderableListWrapper(SerializedProperty property, GUIContent label, bool reorderable = true)\n        {\n            Init(reorderable, property);\n        }\n\n        void Init(bool reorderable, SerializedProperty property)\n        {\n            m_Reorderable = reorderable;\n            SerializedProperty childProperty = property.Copy();\n            childProperty.Next(true);\n\n            m_ReorderableList = new ReorderableList(property.serializedObject, property.Copy(), m_Reorderable, false, true, true);\n            m_ReorderableList.headerHeight = ReorderableList.Defaults.minHeaderHeight;\n            m_ReorderableList.m_IsEditable = true;\n            m_ReorderableList.multiSelect = true;\n            // Check to see if the list has any elements, and use one to find out if serialized property type has children\n            m_ReorderableList.m_HasPropertyDrawer = (childProperty != null) ? childProperty.hasChildren : false;\n\n            m_ReorderableList.onCanAddCallback += (list) =>\n            {\n                return !m_ListIsPatchedInPrefabModeInContext;\n            };\n\n            m_ReorderableList.onCanRemoveCallback += (list) =>\n            {\n                return !m_ListIsPatchedInPrefabModeInContext;\n            };\n\n            Property = property;\n            m_HeaderHeight = Constants.kDefaultFoldoutHeaderHeight;\n        }\n\n        internal void InvalidateCache() => m_ReorderableList.InvalidateCache();\n\n        public float GetHeight()\n        {\n            return m_HeaderHeight + (Property.isExpanded && m_ReorderableList != null ? Constants.kHeaderPadding + m_ReorderableList.GetHeight() : 0.0f);\n        }\n\n        void UpdatePrefabPatchState(Object serializedObjectTarget)\n        {\n            m_DisableListElements = false;\n            m_ListIsPatchedInPrefabModeInContext = false;\n\n            var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();\n            if (prefabStage != null)\n            {\n                m_ListIsPatchedInPrefabModeInContext = prefabStage.HasPatchedPropertyModificationsFor(serializedObjectTarget, m_PropertyPath);\n                if (m_ListIsPatchedInPrefabModeInContext)\n                {\n                    m_DisableListElements = prefabStage.HasPatchedPropertyModificationsFor(serializedObjectTarget, m_PropertyPathArraySize);\n                }\n            }\n\n            if (m_ReorderableList != null)\n                m_ReorderableList.draggable = m_Reorderable && !m_ListIsPatchedInPrefabModeInContext;\n        }\n\n        public void Draw(GUIContent label, Rect r, Rect visibleArea, string tooltip, bool includeChildren)\n        {\n            r.xMin += EditorGUI.indent;\n\n            Rect headerRect = new Rect(r.x, r.y, r.width, m_HeaderHeight);\n            Rect sizeRect = new Rect(headerRect.xMax - Constants.kArraySizeWidth - EditorGUI.indent * EditorGUI.indentLevel, headerRect.y,\n                Constants.kArraySizeWidth + EditorGUI.indent * EditorGUI.indentLevel, m_HeaderHeight);\n\n            Event evt = Event.current;\n            EventType prevType = evt.type;\n            if (!string.IsNullOrEmpty(tooltip) && prevType == EventType.Repaint)\n            {\n                bool hovered = headerRect.Contains(evt.mousePosition);\n\n                if (hovered && GUIClip.visibleRect.Contains(evt.mousePosition))\n                {\n                    if (!GUIStyle.IsTooltipActive(tooltip))\n                        s_ToolTipRect = new Rect(evt.mousePosition, Vector2.zero);\n                    GUIStyle.SetMouseTooltip(tooltip, s_ToolTipRect);\n                }\n            }\n            if (Event.current.type == EventType.MouseUp && sizeRect.Contains(Event.current.mousePosition))\n            {\n                Event.current.type = EventType.Used;\n            }\n\n            EditorGUI.BeginChangeCheck();\n            if (!m_OriginalProperty.hasMultipleDifferentValues) EditorGUI.BeginProperty(headerRect, GUIContent.none, m_OriginalProperty);\n\n            bool prevEnabled = GUI.enabled;\n            GUI.enabled = true;\n            Property.isExpanded = EditorGUI.BeginFoldoutHeaderGroup(headerRect, Property.isExpanded, label ?? GUIContent.Temp(Property.displayName));\n            EditorGUI.EndFoldoutHeaderGroup();\n            GUI.enabled = prevEnabled;\n\n            if (!m_OriginalProperty.hasMultipleDifferentValues) EditorGUI.EndProperty();\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (Event.current.alt)\n                {\n                    EditorGUI.SetExpandedRecurse(Property, Property.isExpanded);\n                }\n\n                m_ReorderableList.InvalidateCacheRecursive();\n            }\n\n            if (m_DisableListElements)\n                GUI.enabled = false;\n\n            DrawChildren(r, headerRect, sizeRect, visibleArea, prevType);\n            GUI.enabled = prevEnabled;\n        }\n\n        void DrawChildren(Rect listRect, Rect headerRect, Rect sizeRect, Rect visibleRect, EventType previousEvent)\n        {\n            if (Event.current.type == EventType.Used && sizeRect.Contains(Event.current.mousePosition)) Event.current.type = previousEvent;\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.DefaultPropertyField(sizeRect, m_ArraySize, GUIContent.none);\n            EditorGUI.LabelField(sizeRect, new GUIContent(\"\", \"Array Size\"));\n            if (EditorGUI.EndChangeCheck())\n                m_ReorderableList.InvalidateForGUI();\n\n            if (headerRect.Contains(Event.current.mousePosition))\n            {\n                if (Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform)\n                {\n                    Object[] objReferences = DragAndDrop.objectReferences;\n                    foreach (var o in objReferences)\n                    {\n                        Object validatedObject = EditorGUI.ValidateObjectFieldAssignment(new[] { o }, typeof(Object), m_ReorderableList.serializedProperty, EditorGUI.ObjectFieldValidatorOptions.None);\n                        if (validatedObject != null)\n                        {\n                            DragAndDrop.visualMode = DragAndDropVisualMode.Generic;\n                        }\n                        else continue;\n\n                        if (Event.current.type == EventType.DragPerform) ReorderableList.defaultBehaviours.DoAddButton(m_ReorderableList, validatedObject);\n                    }\n                    DragAndDrop.AcceptDrag();\n                    Event.current.Use();\n                }\n            }\n\n            if (Event.current.type == EventType.DragExited)\n            {\n                DragAndDrop.visualMode = DragAndDropVisualMode.None;\n                Event.current.Use();\n            }\n\n            if (Property.isExpanded)\n            {\n                listRect.y += m_HeaderHeight + Constants.kHeaderPadding;\n                listRect.height -= m_HeaderHeight + Constants.kHeaderPadding;\n\n                visibleRect.y -= listRect.y;\n                m_ReorderableList.DoList(listRect, visibleRect);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/RotationConstraintEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Animations;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(RotationConstraint))]\n    [CanEditMultipleObjects]\n    internal class RotationConstraintEditor : ConstraintEditorBase\n    {\n        private SerializedProperty m_RotationAtRest;\n        private SerializedProperty m_RotationOffset;\n        private SerializedProperty m_Weight;\n        private SerializedProperty m_IsContraintActive;\n        private SerializedProperty m_IsLocked;\n        private SerializedProperty m_Sources;\n\n        internal override SerializedProperty atRest { get { return m_RotationAtRest; } }\n        internal override SerializedProperty offset { get { return m_RotationOffset; } }\n        internal override SerializedProperty weight { get { return m_Weight; } }\n        internal override SerializedProperty isContraintActive { get { return m_IsContraintActive; } }\n        internal override SerializedProperty isLocked { get { return m_IsLocked; } }\n        internal override SerializedProperty sources { get { return m_Sources; } }\n\n        private class Styles : ConstraintStyleBase\n        {\n            GUIContent m_RotationAtRest = EditorGUIUtility.TrTextContent(\"Rotation At Rest\");\n            GUIContent m_RotationOffset = EditorGUIUtility.TrTextContent(\"Rotation Offset\");\n\n            GUIContent m_RotationAxes = EditorGUIUtility.TrTextContent(\"Freeze Rotation Axes\");\n\n            public override GUIContent AtRest { get { return m_RotationAtRest; } }\n            public override GUIContent Offset { get { return m_RotationOffset; } }\n            public GUIContent FreezeAxes { get { return m_RotationAxes; } }\n        }\n\n        private static Styles s_Style = null;\n\n        public void OnEnable()\n        {\n            if (s_Style == null)\n                s_Style = new Styles();\n\n            m_RotationAtRest = serializedObject.FindProperty(\"m_RotationAtRest\");\n            m_RotationOffset = serializedObject.FindProperty(\"m_RotationOffset\");\n            m_Weight = serializedObject.FindProperty(\"m_Weight\");\n            m_IsContraintActive = serializedObject.FindProperty(\"m_Active\");\n            m_IsLocked = serializedObject.FindProperty(\"m_IsLocked\");\n            m_Sources = serializedObject.FindProperty(\"m_Sources\");\n\n            OnEnable(s_Style);\n        }\n\n        internal override void OnValueAtRestChanged()\n        {\n            foreach (var t in targets)\n                (t as RotationConstraint).transform.SetLocalEulerAngles(atRest.vector3Value, RotationOrder.OrderZXY);\n        }\n\n        internal override void ShowFreezeAxesControl()\n        {\n            Rect drawRect = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, s_Style.FreezeAxes), EditorStyles.toggle);\n            EditorGUI.MultiPropertyField(drawRect, s_Style.Axes, serializedObject.FindProperty(\"m_AffectRotationX\"), s_Style.FreezeAxes);\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (s_Style == null)\n                s_Style = new Styles();\n\n            serializedObject.Update();\n\n            ShowConstraintEditor<RotationConstraint>(s_Style);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ScaleConstraintEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Animations;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(ScaleConstraint))]\n    [CanEditMultipleObjects]\n    internal class ScaleConstraintEditor : ConstraintEditorBase\n    {\n        private SerializedProperty m_ScaleAtRest;\n        private SerializedProperty m_ScaleOffset;\n        private SerializedProperty m_Weight;\n        private SerializedProperty m_IsContraintActive;\n        private SerializedProperty m_IsLocked;\n        private SerializedProperty m_Sources;\n\n        internal override SerializedProperty atRest { get { return m_ScaleAtRest; } }\n        internal override SerializedProperty offset { get { return m_ScaleOffset; } }\n        internal override SerializedProperty weight { get { return m_Weight; } }\n        internal override SerializedProperty isContraintActive { get { return m_IsContraintActive; } }\n        internal override SerializedProperty isLocked { get { return m_IsLocked; } }\n        internal override SerializedProperty sources { get { return m_Sources; } }\n\n        private class Styles : ConstraintStyleBase\n        {\n            GUIContent m_ScaleAtRest = EditorGUIUtility.TrTextContent(\"Scale At Rest\");\n            GUIContent m_ScaleOffset = EditorGUIUtility.TrTextContent(\"Scale Offset\");\n\n            GUIContent m_ScalingAxes = EditorGUIUtility.TrTextContent(\"Freeze Scaling Axes\");\n\n            public override GUIContent AtRest { get { return m_ScaleAtRest; } }\n            public override GUIContent Offset { get { return m_ScaleOffset; } }\n            public GUIContent FreezeAxes { get { return m_ScalingAxes; } }\n        }\n\n        private static Styles s_Style;\n\n        public void OnEnable()\n        {\n            if (s_Style == null)\n                s_Style = new Styles();\n\n            m_ScaleAtRest = serializedObject.FindProperty(\"m_ScaleAtRest\");\n            m_ScaleOffset = serializedObject.FindProperty(\"m_ScaleOffset\");\n            m_Weight = serializedObject.FindProperty(\"m_Weight\");\n            m_IsContraintActive = serializedObject.FindProperty(\"m_Active\");\n            m_IsLocked = serializedObject.FindProperty(\"m_IsLocked\");\n            m_Sources = serializedObject.FindProperty(\"m_Sources\");\n\n            OnEnable(s_Style);\n        }\n\n        internal override void OnValueAtRestChanged()\n        {\n            foreach (var t in targets)\n                (t as ScaleConstraint).transform.localScale = atRest.vector3Value;\n        }\n\n        internal override void ShowFreezeAxesControl()\n        {\n            Rect drawRect = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, s_Style.FreezeAxes), EditorStyles.toggle);\n            EditorGUI.MultiPropertyField(drawRect, s_Style.Axes, serializedObject.FindProperty(\"m_AffectScalingX\"), s_Style.FreezeAxes);\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (s_Style == null)\n                s_Style = new Styles();\n\n            serializedObject.Update();\n\n            ShowConstraintEditor<ScaleConstraint>(s_Style);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ScriptExecutionOrderInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.VersionControl;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(MonoManager))]\n    internal class ScriptExecutionOrderInspector : Editor\n    {\n        /*\n         * @TODO\n        - Make it work with imported dll's + meta file serialization\n        */\n\n        internal override string targetTitle\n        {\n            get { return L10n.Tr(\"Script Execution Order\"); }\n        }\n\n        public class SortMonoScriptNameOrder : IComparer<MonoScript>\n        {\n            public virtual int Compare(MonoScript x, MonoScript y)\n            {\n                if (x != null && y != null)\n                {\n                    var xClass = x.GetClass();\n                    var yClass = y.GetClass();\n                    if (xClass != null && yClass != null)\n                        return xClass.FullName.CompareTo(yClass.FullName);\n\n                    return x.name.CompareTo(y.name);\n                }\n                return -1;\n            }\n        }\n\n        public class SortMonoScriptExecutionOrder : SortMonoScriptNameOrder\n        {\n            ScriptExecutionOrderInspector inspector;\n\n            public SortMonoScriptExecutionOrder(ScriptExecutionOrderInspector inspector)\n            {\n                this.inspector = inspector;\n            }\n\n            public override int Compare(MonoScript x, MonoScript y)\n            {\n                if (x != null && y != null)\n                {\n                    int orderX = inspector.GetExecutionOrder(x);\n                    int orderY = inspector.GetExecutionOrder(y);\n                    if (orderX == orderY)\n                        return base.Compare(x, y);\n\n                    return orderX.CompareTo(orderY);\n                }\n                return -1;\n            }\n        }\n\n        private const int kOrderRangeMin = -32000;\n        private const int kOrderRangeMax =  32000;\n        private const int kListElementHeight = 21;\n        private const int kIntFieldWidth = 50;\n        private const int kPreferredSpacing = 100;\n        private int[] kRoundingAmounts = new int[] { 1000, 500, 100, 50, 10, 5, 1 };\n\n        private MonoScript m_Edited = null;\n        private List<MonoScript> m_CustomTimeScripts;\n        private List<MonoScript> m_DefaultTimeScripts;\n        private static MonoScript sDummyScript;\n        private Vector2 m_Scroll = Vector2.zero;\n        private static readonly List<ScriptExecutionOrderInspector> m_Instances = new List<ScriptExecutionOrderInspector>();\n\n        // Important that these 3 use data types that are serializable.\n        // That way we don't loose the unapplied reordering upon a script compile.\n        private MonoScript[] m_AllScripts;\n        private int[] m_AllOrders;\n        private bool m_DirtyOrders = false;\n\n        private static int s_DropFieldHash = \"DropField\".GetHashCode();\n\n        public class Content\n        {\n            public static GUIContent helpText = EditorGUIUtility.TrTextContent(\"Add scripts to the custom order and drag them to reorder.\\n\\nScripts in the custom order can execute before or after the default time and are executed from top to bottom. All other scripts execute at the default time in the order they are loaded.\\n\\n(Changing the order of a script may modify the meta data for more than one script.)\");\n            public static GUIContent iconToolbarPlus = EditorGUIUtility.TrIconContent(\"Toolbar Plus\", \"Add script to custom order\");\n            public static GUIContent iconToolbarMinus = EditorGUIUtility.TrIconContent(\"Toolbar Minus\", \"Remove script from custom order\");\n            public static GUIContent defaultTimeContent = EditorGUIUtility.TrTextContent(\"Default Time\", \"All scripts not in the custom order are executed at the default time.\");\n            public static GUIContent[] emptyMenuOptions = { EditorGUIUtility.TrTextContent(\"Empty\") };\n        }\n\n        public static class Styles\n        {\n            public static readonly GUIStyle toolbarDropDown = \"TE ToolbarDropDown\";\n            public static readonly GUIStyle toolbar = \"TE Toolbar\";\n            public static readonly GUIStyle boxBackground = \"TE NodeBackground\";\n            public static readonly GUIStyle removeButton = \"InvisibleButton\";\n            public static readonly GUIStyle elementBackground = \"TE ElementBackground\";\n            public static readonly GUIStyle defaultTime = \"TE DefaultTime\";\n            public static readonly GUIStyle draggingHandle = \"WindowBottomResize\";\n            // Drop field style that has extra overflow and is only visible when \"on\".\n            // Used to draw a blue glow when dragging scripts into the ordering to\n            // indicate that drag-and-drop is supported.\n            public static readonly GUIStyle dropField = \"TE DropField\";\n\n            public static readonly GUIStyle textfield = new GUIStyle(EditorStyles.textField)\n            {\n                padding = new RectOffset(2, 2, 1, 0),\n                contentOffset = new Vector2(0, -0.5f),\n                alignment = TextAnchor.UpperLeft\n            };\n\n            public static readonly GUIStyle label = new GUIStyle(EditorStyles.label)\n            {\n                padding = new RectOffset(1, 1, 2, 1),\n                alignment = TextAnchor.UpperLeft\n            };\n        }\n\n        [MenuItem(\"CONTEXT/MonoManager/Reset\", secondaryPriority = 14)]\n        private static void Reset(MenuCommand cmd)\n        {\n            var instances = ScriptExecutionOrderInspector.GetInstances();\n\n            foreach (var instance in instances)\n            {\n                for (var i = 0; i < instance.m_AllOrders.Length; i++)\n                    instance.m_AllOrders[i] = 0;\n\n                instance.Apply();\n            }\n        }\n\n        public void OnEnable()\n        {\n            if (sDummyScript == null)\n                sDummyScript = new MonoScript();\n\n            // Don't reload the order if an unapplied reordering exists\n            if (m_AllScripts == null || !m_DirtyOrders)\n                PopulateScriptArray();\n\n            if (!m_Instances.Contains(this))\n                m_Instances.Add(this);\n\n            EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;\n            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;\n        }\n\n        public void OnDisable()\n        {\n            EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;\n        }\n\n        private void AskApplyRevertIfNecessary()\n        {\n            if (!m_DirtyOrders)\n                return;\n\n            if (EditorUtility.DisplayDialog(\"Unapplied execution order\", \"Unapplied script execution order\", \"Apply\", \"Revert\"))\n                Apply();\n        }\n\n        private void OnPlayModeStateChanged(PlayModeStateChange state)\n        {\n            if (state != PlayModeStateChange.ExitingEditMode)\n                return;\n\n            AskApplyRevertIfNecessary();\n        }\n\n        static Object MonoScriptValidatorCallback(Object[] references, System.Type objType, SerializedProperty property, EditorGUI.ObjectFieldValidatorOptions options)\n        {\n            foreach (Object i in references)\n            {\n                var monoScript = i as MonoScript;\n                if (monoScript != null && IsValidScript(monoScript))\n                {\n                    return monoScript;\n                }\n            }\n            return null;\n        }\n\n        static bool IsValidScript(MonoScript script)\n        {\n            if (script == null)\n                return false;\n\n            // The user can only define the order of scripts that contains valid classes (see case 579536)\n            if (script.GetClass() == null)\n                return false;\n\n            // Only allow MonoBehaviours and ScriptableObjects\n            bool isMonoBehaviour = typeof(MonoBehaviour).IsAssignableFrom(script.GetClass());\n            bool isScriptableObject = typeof(ScriptableObject).IsAssignableFrom(script.GetClass());\n            if (!isMonoBehaviour && !isScriptableObject)\n            {\n                return false;\n            }\n\n            // The user can only define the order of scripts in the assets folder.\n            bool isRootFolder, isReadOnly;\n            if (!AssetDatabase.TryGetAssetFolderInfo(AssetDatabase.GetAssetPath(script), out isRootFolder, out isReadOnly))\n            {\n                return false;\n            }\n\n            return true;\n        }\n\n        internal static List<ScriptExecutionOrderInspector> GetInstances()\n        {\n            return m_Instances;\n        }\n\n        void PopulateScriptArray()\n        {\n            m_AllScripts = MonoImporter.GetAllRuntimeMonoScripts();\n            m_AllOrders = new int[m_AllScripts.Length];\n\n            // Create cleaned up list of scripts\n            m_CustomTimeScripts = new List<MonoScript>();\n            m_DefaultTimeScripts = new List<MonoScript>();\n            for (int i = 0; i < m_AllScripts.Length; i++)\n            {\n                MonoScript script = m_AllScripts[i];\n                m_AllOrders[i] = MonoImporter.GetExecutionOrder(script);\n\n                if (!IsValidScript(script))\n                    continue;\n\n                if (GetExecutionOrder(script) == 0)\n                    m_DefaultTimeScripts.Add(script);\n                else\n                    m_CustomTimeScripts.Add(script);\n            }\n\n            // Add two dummy items used for the default time area\n            m_CustomTimeScripts.Add(sDummyScript);\n            m_CustomTimeScripts.Add(sDummyScript);\n\n            // Assign and sort\n            m_CustomTimeScripts.Sort(new SortMonoScriptExecutionOrder(this));\n            m_DefaultTimeScripts.Sort(new SortMonoScriptNameOrder());\n            m_Edited = null;\n\n            m_DirtyOrders = false;\n        }\n\n        private int GetExecutionOrder(MonoScript script)\n        {\n            int index = System.Array.IndexOf<MonoScript>(m_AllScripts, script);\n            if (index >= 0)\n                return m_AllOrders[index];\n            return 0;\n        }\n\n        private void SetExecutionOrder(MonoScript script, int order)\n        {\n            int index = System.Array.IndexOf<MonoScript>(m_AllScripts, script);\n            if (index >= 0)\n            {\n                m_AllOrders[index] = Mathf.Clamp(order, kOrderRangeMin, kOrderRangeMax);\n                m_DirtyOrders = true;\n            }\n        }\n\n        private void Apply()\n        {\n            var changedIndices = new List<int>();\n            var changedPaths = new List<string>();\n\n            for (var i = 0; i < m_AllScripts.Length; i++)\n            {\n                var script = m_AllScripts[i];\n                if (MonoImporter.GetExecutionOrder(script) == m_AllOrders[i])\n                    continue;\n\n                var assetPath = AssetDatabase.GetAssetPath(script);\n                if (string.IsNullOrEmpty(assetPath)) // Script might be outside of the project (e.g. in a package).\n                    continue;\n\n                var metaPath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetPath);\n                if (!AssetDatabase.CanOpenForEdit(metaPath))\n                    continue;\n\n                changedIndices.Add(i);\n                if (!AssetDatabase.IsOpenForEdit(metaPath)) // No VCS enabled, not connected, already checked out, etc.\n                    changedPaths.Add(metaPath);\n            }\n\n            if (!AssetDatabase.MakeEditable(changedPaths.ToArray()))\n            {\n                Debug.LogError(\"Could not make scrips editable for changing script execution order.\");\n                return;\n            }\n\n            foreach (var index in changedIndices)\n                MonoImporter.SetExecutionOrder(m_AllScripts[index], m_AllOrders[index]);\n\n            PopulateScriptArray();\n        }\n\n        private void Revert()\n        {\n            PopulateScriptArray();\n        }\n\n        private void OnDestroy()\n        {\n            if (m_Instances.Contains(this))\n                m_Instances.Remove(this);\n\n            if (!Application.isPlaying)\n                AskApplyRevertIfNecessary();\n        }\n\n        private void ApplyRevertGUI()\n        {\n            EditorGUILayout.Space();\n            bool wasEnabled = GUI.enabled;\n            GUI.enabled = m_DirtyOrders;\n\n            GUILayout.BeginHorizontal();\n            {\n                GUILayout.FlexibleSpace();\n\n                if (GUILayout.Button(\"Revert\"))\n                    Revert();\n\n                if (GUILayout.Button(\"Apply\"))\n                    Apply();\n            } GUILayout.EndHorizontal();\n\n            GUI.enabled = wasEnabled;\n        }\n\n        private void MenuSelection(object userData, string[] options, int selected)\n        {\n            var selectableScripts = userData as IList<MonoScript>;\n            if (selectableScripts == null)\n            {\n                return;\n            }\n            AddScriptToCustomOrder(selectableScripts[selected]);\n        }\n\n        private void AddScriptToCustomOrder(MonoScript script)\n        {\n            if (!IsValidScript(script))\n                return;\n\n            if (m_CustomTimeScripts.Contains(script))\n                return;\n\n            int orderOfAddedScript = RoundByAmount(GetExecutionOrderAtIndex(m_CustomTimeScripts.Count - 1) + kPreferredSpacing, kPreferredSpacing);\n            SetExecutionOrder(script, orderOfAddedScript);\n            m_CustomTimeScripts.Add(script);\n            m_DefaultTimeScripts.Remove(script);\n        }\n\n        private void ShowScriptPopup(Rect r)\n        {\n            var length = m_DefaultTimeScripts.Count;\n            var names = new List<string>(length);\n            var selectableScripts = new List<MonoScript>(length);\n\n            for (var i = 0; i < length; ++i)\n            {\n                var assetPath = AssetDatabase.GetAssetPath(m_DefaultTimeScripts[i]);\n                if (string.IsNullOrEmpty(assetPath))\n                    continue;\n\n                var metaPath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetPath);\n                if (!AssetDatabase.CanOpenForEdit(metaPath))\n                    continue;\n\n                names.Add(m_DefaultTimeScripts[i].GetClass().FullName); // todo: Localization with a proper database.\n                selectableScripts.Add(m_DefaultTimeScripts[i]);\n            }\n\n            if (names.Count == 0)\n            {\n                EditorUtility.DisplayCustomMenu(r, Content.emptyMenuOptions, i => false, -1, null, null);\n                return;\n            }\n\n            var options = names.ToArray();\n            var enabled = Enumerable.Repeat(true, options.Length).ToArray();\n            EditorUtility.DisplayCustomMenu(r, options, enabled, null, MenuSelection, selectableScripts);\n        }\n\n        private int RoundBasedOnContext(int val, int lowerBound, int upperBound)\n        {\n            // Make the bounds a bit closer to avoid the value ending up right next to one of the bounds\n            int fraction = Mathf.Max(0, (upperBound - lowerBound) / 6);\n            lowerBound += fraction;\n            upperBound -= fraction;\n\n            // Round by smaller amounts until we find a value that fit within the bounds\n            for (int i = 0; i < kRoundingAmounts.Length; i++)\n            {\n                int roundedVal = RoundByAmount(val, kRoundingAmounts[i]);\n                if (roundedVal > lowerBound && roundedVal < upperBound)\n                    return roundedVal;\n            }\n\n            return val;\n        }\n\n        private int RoundByAmount(int val, int rounding)\n        {\n            return Mathf.RoundToInt(val / (float)rounding) * rounding;\n        }\n\n        private int GetAverageRoundedAwayFromZero(int a, int b)\n        {\n            if ((a + b) % 2 == 0)\n                return (a + b) / 2;\n            else\n                return (a + b + System.Math.Sign(a + b)) / 2;\n        }\n\n        private void SetExecutionOrderAtIndexAccordingToNeighbors(int indexOfChangedItem, int pushDirection)\n        {\n            // Ignore invalid index\n            if (indexOfChangedItem < 0 || indexOfChangedItem >= m_CustomTimeScripts.Count)\n                return;\n\n            // Set order if changed is first in list\n            if (indexOfChangedItem == 0)\n            {\n                SetExecutionOrderAtIndex(\n                    indexOfChangedItem,\n                    RoundByAmount(GetExecutionOrderAtIndex(indexOfChangedItem + 1) - kPreferredSpacing, kPreferredSpacing));\n                return;\n            }\n\n            // Set order if changed is last in list\n            if (indexOfChangedItem == m_CustomTimeScripts.Count - 1)\n            {\n                SetExecutionOrderAtIndex(\n                    indexOfChangedItem,\n                    RoundByAmount(GetExecutionOrderAtIndex(indexOfChangedItem - 1) + kPreferredSpacing, kPreferredSpacing));\n                return;\n            }\n\n            // Make nr average of prev and next script nr, but rounded to a nice round number\n            int prevOrder = GetExecutionOrderAtIndex(indexOfChangedItem - 1);\n            int nextOrder = GetExecutionOrderAtIndex(indexOfChangedItem + 1);\n            int newAverageExecutionOrder = RoundBasedOnContext(GetAverageRoundedAwayFromZero(prevOrder, nextOrder), prevOrder, nextOrder);\n\n            if (newAverageExecutionOrder != 0)\n            {\n                if (pushDirection == 0)\n                    pushDirection = GetBestPushDirectionForOrderValue(newAverageExecutionOrder);\n\n                // Ensure new value is at least one higher/lower than the neighbor\n                if (pushDirection > 0)\n                    newAverageExecutionOrder = Mathf.Max(newAverageExecutionOrder, prevOrder + 1);\n                else\n                    newAverageExecutionOrder = Mathf.Min(newAverageExecutionOrder, nextOrder - 1);\n            }\n\n            SetExecutionOrderAtIndex(indexOfChangedItem, newAverageExecutionOrder);\n        }\n\n        private void UpdateOrder(MonoScript changedScript)\n        {\n            // Remove the script prior to reordering\n            // Remember to add later, either to custom or default time list\n            m_CustomTimeScripts.Remove(changedScript);\n\n            int changedScriptOrder = GetExecutionOrder(changedScript);\n\n            // If script order was set to zero, script gets removed from list, so no reordering needed\n            if (changedScriptOrder == 0)\n            {\n                m_DefaultTimeScripts.Add(changedScript);\n                m_DefaultTimeScripts.Sort(new SortMonoScriptNameOrder());\n                return;\n            }\n\n            // See if any other scripts have an order that conflicts with the one just moved\n            int conflictedIndex = -1;\n            for (int i = 0; i < m_CustomTimeScripts.Count; i++)\n            {\n                if (GetExecutionOrderAtIndex(i) == changedScriptOrder)\n                {\n                    conflictedIndex = i;\n                    break;\n                }\n            }\n\n            // If not, add the changed script back and sort orders.\n            // This will also happen if there' only one script in the custom order,\n            // so we don't need to worry about that case further down.\n            if (conflictedIndex == -1)\n            {\n                m_CustomTimeScripts.Add(changedScript);\n                m_CustomTimeScripts.Sort(new SortMonoScriptExecutionOrder(this));\n                return;\n            }\n\n            int pushDirection = GetBestPushDirectionForOrderValue(changedScriptOrder);\n            if (pushDirection == 1)\n            {\n                m_CustomTimeScripts.Insert(conflictedIndex, changedScript);\n                conflictedIndex++;\n            }\n            else\n            {\n                m_CustomTimeScripts.Insert(conflictedIndex + 1, changedScript);\n            }\n\n            PushAwayToAvoidConflicts(conflictedIndex, pushDirection);\n        }\n\n        private void PushAwayToAvoidConflicts(int startIndex, int pushDirection)\n        {\n            int curIndex = startIndex;\n            while (curIndex >= 0 && curIndex < m_CustomTimeScripts.Count)\n            {\n                // Check if there's any conflict between the order at this index and the previous one. If not, stop here.\n                if ((GetExecutionOrderAtIndex(curIndex) - GetExecutionOrderAtIndex(curIndex - pushDirection)) * pushDirection >= 1)\n                    break;\n\n                SetExecutionOrderAtIndexAccordingToNeighbors(curIndex, pushDirection);\n                curIndex += pushDirection;\n            }\n        }\n\n        private int GetBestPushDirectionForOrderValue(int order)\n        {\n            // If there's any conflicts we want to push neighboring scripts until the conflict has been resolved.\n            // However, we can't push the order of any script past 0 (from either direction)\n            // or past the minimum or maximum allowed order values.\n            // So we push away from zero if the new order is close to zero and towards zero if it's closer to the min or max.\n            // This should only be able to fail if the user has more than 16000 scripts (a quarter of the total range).\n            int pushDirection = (int)Mathf.Sign(order);\n            if (order < kOrderRangeMin / 2 || order > kOrderRangeMax / 2)\n                pushDirection = -pushDirection;\n            return pushDirection;\n        }\n\n        public override bool UseDefaultMargins() { return false; }\n\n        public override void OnInspectorGUI()\n        {\n            bool GUIEnabledValue = GUI.enabled;\n\n            var vcDisconnected = false;\n            if (!EditorUserSettings.WorkOffline)\n            {\n                var vco = VersionControlManager.activeVersionControlObject;\n                if (vco != null)\n                    vcDisconnected = !vco.isConnected;\n                else if (Provider.enabled)\n                    vcDisconnected = !Provider.isActive;\n            }\n\n            if (vcDisconnected)\n            {\n                GUI.enabled = false;\n            }\n\n            if (m_Edited)\n            {\n                UpdateOrder(m_Edited);\n                m_Edited = null;\n            }\n\n            EditorGUILayout.BeginVertical(EditorStyles.inspectorFullWidthMargins);\n            {\n                GUILayout.Label(Content.helpText, EditorStyles.helpBox);\n\n                EditorGUILayout.Space();\n\n                // Vertical that contains box and the toolbar below it\n                Rect listRect = EditorGUILayout.BeginVertical();\n                {\n                    int dropFieldId = EditorGUIUtility.GetControlID(s_DropFieldHash, FocusType.Passive, listRect);\n                    MonoScript dropped = EditorGUI.DoDropField(listRect, dropFieldId, typeof(MonoScript), MonoScriptValidatorCallback, false, Styles.dropField) as MonoScript;\n                    if (dropped)\n                        AddScriptToCustomOrder(dropped);\n\n                    // Vertical that is used as a border around the scrollview\n                    EditorGUILayout.BeginVertical(Styles.boxBackground);\n                    {\n                        // The scrollview itself\n                        m_Scroll = EditorGUILayout.BeginVerticalScrollView(m_Scroll);\n                        {\n                            // List\n                            Rect r = GUILayoutUtility.GetRect(10, kListElementHeight * m_CustomTimeScripts.Count, GUILayout.ExpandWidth(true));\n                            int changed = DragReorderGUI.DragReorder(r, kListElementHeight, m_CustomTimeScripts, DrawElement);\n                            if (changed >= 0)\n                            {\n                                // Give dragged item value in between neighbors\n                                SetExecutionOrderAtIndexAccordingToNeighbors(changed, 0);\n                                // Update neighbors if needed\n                                UpdateOrder(m_CustomTimeScripts[changed]);\n                                // Neighbors may have been moved so there's more space around dragged item,\n                                // so set order again to get possible rounding benefits\n                                SetExecutionOrderAtIndexAccordingToNeighbors(changed, 0);\n                            }\n                        } EditorGUILayout.EndScrollView();\n                    } EditorGUILayout.EndVertical();\n\n                    // The toolbar below the box\n                    GUILayout.BeginHorizontal(Styles.toolbar);\n                    {\n                        GUILayout.FlexibleSpace();\n                        Rect r2;\n                        GUIContent content = Content.iconToolbarPlus;\n                        r2 = GUILayoutUtility.GetRect(content, Styles.toolbarDropDown);\n                        if (EditorGUI.DropdownButton(r2, content, FocusType.Passive, Styles.toolbarDropDown))\n                            ShowScriptPopup(r2);\n                    } GUILayout.EndHorizontal();\n                } GUILayout.EndVertical();\n\n                ApplyRevertGUI();\n            } GUILayout.EndVertical();\n\n            GUI.enabled = GUIEnabledValue;\n            if (vcDisconnected)\n            {\n                EditorGUILayout.HelpBox(\"Version control is disconnected\", MessageType.Warning);\n            }\n\n            GUILayout.FlexibleSpace();\n        }\n\n        int GetExecutionOrderAtIndex(int idx)\n        {\n            return GetExecutionOrder(m_CustomTimeScripts[idx]);\n        }\n\n        void SetExecutionOrderAtIndex(int idx, int order)\n        {\n            SetExecutionOrder(m_CustomTimeScripts[idx], order);\n        }\n\n        private Rect GetButtonLabelRect(Rect r)\n        {\n            return new Rect(r.x + 20, r.y, r.width - GetMinusButtonSize().x - 10 - 20 - (kIntFieldWidth + 5), r.height);\n        }\n\n        private Rect GetAddRemoveButtonRect(Rect r)\n        {\n            var buttonSize = GetMinusButtonSize();\n\n            return new Rect(r.xMax - buttonSize.x - 5, r.y + 1, buttonSize.x, buttonSize.y);\n        }\n\n        private Rect GetFieldRect(Rect r)\n        {\n            return new Rect(r.xMax - kIntFieldWidth - GetMinusButtonSize().x - 10, r.y + 2, kIntFieldWidth, r.height - 5);\n        }\n\n        private Vector2 GetMinusButtonSize()\n        {\n            return Styles.removeButton.CalcSize(Content.iconToolbarMinus);\n        }\n\n        private Rect GetDraggingHandleRect(Rect r)\n        {\n            return new Rect(r.x + 5, r.y + 7, 10, r.height - 14);\n        }\n\n        public void DrawElement(Rect r, object obj, bool dragging)\n        {\n            MonoScript script = obj as MonoScript;\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                Styles.elementBackground.Draw(r, false, false, false, false);\n                Styles.draggingHandle.Draw(GetDraggingHandleRect(r), false, false, false, false);\n            }\n\n            GUI.Label(GetButtonLabelRect(r), script.GetClass().FullName, Styles.label);\n\n            int oldNr = GetExecutionOrder(script);\n            Rect position = GetFieldRect(r);\n            // associate control id with script so that removing an element when its text field is active will not potentially cause subsequent element to inherit value when list is reordered\n            int id = GUIUtility.GetControlID(script.GetHashCode(), FocusType.Keyboard, position);\n            string intStr = EditorGUI.DelayedTextFieldInternal(position, id, GUIContent.none, oldNr.ToString(), \"0123456789-\", Styles.textfield);\n            int newNr = oldNr;\n            if (System.Int32.TryParse(intStr, out newNr) && newNr != oldNr)\n            {\n                SetExecutionOrder(script, newNr);\n                m_Edited = script;\n            }\n\n            if (GUI.Button(GetAddRemoveButtonRect(r), Content.iconToolbarMinus, Styles.removeButton))\n            {\n                SetExecutionOrder(script, 0);\n                m_Edited = script;\n            }\n        }\n\n        class DragReorderGUI\n        {\n            public delegate void DrawElementDelegate(Rect r, object obj, bool dragging);\n\n            private static int s_ReorderingDraggedElement;\n            private static float[] s_ReorderingPositions;\n            private static int[] s_ReorderingGoals;\n            private static int s_DragReorderGUIHash = \"DragReorderGUI\".GetHashCode();\n\n            private static bool IsDefaultTimeElement(MonoScript element)\n            {\n                if (element == null)\n                    return true;\n                return (element.name == string.Empty);\n            }\n\n            public static int DragReorder(Rect position, int elementHeight, List<MonoScript> elements, DrawElementDelegate drawElementDelegate)\n            {\n                int id = GUIUtility.GetControlID(s_DragReorderGUIHash, FocusType.Passive);\n\n                Rect elementRect = position;\n                elementRect.height = elementHeight;\n\n                int defPos = 0;\n                Rect defRect;\n\n                // If we're dragging, draw elements based on their animated reordering positions,\n                // but only for repainting. Control event handling does't like to suddenly change order,\n                // so things will screw up if we HANDLE the controls in a different order when dragging.\n                if (GUIUtility.hotControl == id && Event.current.type == EventType.Repaint)\n                {\n                    for (int i = 0; i < elements.Count; i++)\n                    {\n                        // Don't draw the dragged element as part of loop\n                        if (i == s_ReorderingDraggedElement)\n                            continue;\n                        if (IsDefaultTimeElement(elements[i]))\n                        {\n                            defPos = i;\n                            i++;\n                            continue;\n                        }\n                        elementRect.y = position.y + s_ReorderingPositions[i] * elementHeight;\n                        drawElementDelegate(elementRect, elements[i], false);\n                    }\n                    defRect = new Rect(elementRect.x, position.y + s_ReorderingPositions[defPos] * elementHeight, elementRect.width, (s_ReorderingPositions[defPos + 1] - s_ReorderingPositions[defPos] + 1) * elementHeight);\n                }\n                // For everything else than repainting while dragging,\n                // draw controls based on their positions in the array.\n                else\n                {\n                    for (int i = 0; i < elements.Count; i++)\n                    {\n                        elementRect.y = position.y + i * elementHeight;\n                        if (IsDefaultTimeElement(elements[i]))\n                        {\n                            defPos = i;\n                            i++;\n                            continue;\n                        }\n                        drawElementDelegate(elementRect, elements[i], false);\n                    }\n                    defRect = new Rect(elementRect.x, position.y + defPos * elementHeight, elementRect.width, elementHeight * 2);\n                }\n\n                GUI.Label(defRect, Content.defaultTimeContent, Styles.defaultTime);\n\n                bool isAddingToDefault = defRect.height > elementHeight * 2.5f;\n\n                if (GUIUtility.hotControl == id)\n                {\n                    if (isAddingToDefault)\n                        GUI.color = new Color(1, 1, 1, 0.5f);\n                    // Draw the dragged element after all the other ones\n                    elementRect.y = position.y + s_ReorderingPositions[s_ReorderingDraggedElement] * elementHeight;\n                    drawElementDelegate(elementRect, elements[s_ReorderingDraggedElement], true);\n\n                    GUI.color = Color.white;\n                }\n\n                int changed = -1;\n                EventType type = Event.current.GetTypeForControl(id);\n                switch (type)\n                {\n                    case EventType.MouseDown:\n                        if (position.Contains(Event.current.mousePosition))\n                        {\n                            GUIUtility.keyboardControl = 0;\n                            EditorGUI.EndEditingActiveTextField();\n\n                            s_ReorderingDraggedElement = Mathf.FloorToInt((Event.current.mousePosition.y - position.y) / elementHeight);\n                            if (!IsDefaultTimeElement(elements[s_ReorderingDraggedElement]))\n                            {\n                                s_ReorderingPositions = new float[elements.Count];\n                                s_ReorderingGoals = new int[elements.Count];\n                                for (int i = 0; i < elements.Count; i++)\n                                {\n                                    s_ReorderingGoals[i] = i;\n                                    s_ReorderingPositions[i] = i;\n                                }\n                                GUIUtility.hotControl = id;\n                                Event.current.Use();\n                            }\n                        }\n                        break;\n                    case EventType.MouseDrag:\n                        if (GUIUtility.hotControl != id)\n                            break;\n\n                        // Set reordering position of dragged element based on mouse cursor\n                        s_ReorderingPositions[s_ReorderingDraggedElement] = (Event.current.mousePosition.y - position.y) / elementHeight - 0.5f;\n                        // Clamp to range of list\n                        s_ReorderingPositions[s_ReorderingDraggedElement] = Mathf.Clamp(s_ReorderingPositions[s_ReorderingDraggedElement], 0, elements.Count - 1);\n                        // Set draggedToPosition based on dragged position\n                        int draggedToPosition = Mathf.RoundToInt(s_ReorderingPositions[s_ReorderingDraggedElement]);\n\n                        // if dragged to a new position, re-assign goals\n                        if (draggedToPosition != s_ReorderingGoals[s_ReorderingDraggedElement])\n                        {\n                            // Reset\n                            for (int i = 0; i < elements.Count; i++)\n                                s_ReorderingGoals[i] = i;\n                            // Find direction that other elements must be moved in\n                            int direction = (draggedToPosition > s_ReorderingDraggedElement ? -1 : 1);\n\n                            // Move goals of elements to make room for the dragged one\n                            for (int i = s_ReorderingDraggedElement; i != draggedToPosition; i -= direction)\n                                s_ReorderingGoals[i - direction] = i;\n\n                            // At last, move the goal of the dragged element\n                            s_ReorderingGoals[s_ReorderingDraggedElement] = draggedToPosition;\n                        }\n                        Event.current.Use();\n                        break;\n                    case EventType.MouseUp:\n                        if (GUIUtility.hotControl != id)\n                            break;\n\n                        if (s_ReorderingGoals[s_ReorderingDraggedElement] != s_ReorderingDraggedElement)\n                        {\n                            // Reorder array according to the reordering goals\n                            List<MonoScript> reorderedArray = new List<MonoScript>(elements);\n                            for (int i = 0; i < elements.Count; i++)\n                                elements[s_ReorderingGoals[i]] = reorderedArray[i];\n\n                            // Return which elements was just moved\n                            changed = s_ReorderingGoals[s_ReorderingDraggedElement];\n                        }\n\n                        // Reset\n                        s_ReorderingGoals = null;\n                        s_ReorderingPositions = null;\n                        s_ReorderingDraggedElement = -1;\n                        GUIUtility.hotControl = 0;\n                        Event.current.Use();\n                        break;\n                    case EventType.Repaint:\n                        // Animate elements to move towards their goals\n                        if (GUIUtility.hotControl == id)\n                        {\n                            for (int i = 0; i < elements.Count; i++)\n                                if (i != s_ReorderingDraggedElement)\n                                    s_ReorderingPositions[i] = Mathf.MoveTowards(s_ReorderingPositions[i], s_ReorderingGoals[i], 0.075f);\n                            GUIView.current.Repaint();\n                        }\n                        break;\n                }\n\n                return changed;\n            }\n        }\n\n        [SettingsProvider]\n        internal static SettingsProvider CreateProjectSettingsProvider()\n        {\n            var provider = new AssetSettingsProvider(\n                \"Project/Script Execution Order\",\n                () => Editor.CreateEditor(Resources.FindObjectsOfTypeAll(typeof(MonoManager)).First()),\n                SettingsProvider.GetSearchKeywordsFromGUIContentProperties<Content>());\n            return provider;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ScriptableObjectAssetEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    // This base class can be used when the type of an imported object derives from ScriptableObject\n    // Since SOs have the special need of being reloaded after a re-import\n    // we need to check for validity of the target in a few places\n    abstract internal class ScriptableObjectAssetEditor : Editor\n    {\n        // hack to avoid null references when a scriptedImporter runs and replaces the current selection\n        internal override string targetTitle\n        {\n            get\n            {\n                if (!target)\n                {\n                    serializedObject.Update();\n                    InternalSetTargets(serializedObject.targetObjects);\n                }\n                return base.targetTitle;\n            }\n        }\n\n        public override GUIContent GetPreviewTitle()\n        {\n            return GUIContent.Temp(targetTitle);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ScriptableRenderPipelineExtensionAttribute.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n﻿using System;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor.Rendering;\n\n[Obsolete($\"{nameof(ScriptableRenderPipelineExtensionAttribute)} is deprecated. Use {nameof(SupportedOnRenderPipelineAttribute)} instead. #from(23.1) (UnityUpgradable) -> UnityEngine.Rendering.SupportedOnRenderPipelineAttribute\", false)]\n[AttributeUsage(AttributeTargets.Class)]\npublic class ScriptableRenderPipelineExtensionAttribute : Attribute\n{\n    internal Type renderPipelineType;\n\n    public ScriptableRenderPipelineExtensionAttribute(Type rpAssetType)\n    {\n        if (!(rpAssetType?.IsSubclassOf(typeof(RenderPipelineAsset)) ?? false))\n            throw new ArgumentException($\"Given {nameof(rpAssetType)} must derive from {nameof(RenderPipelineAsset)}\");\n        renderPipelineType = rpAssetType;\n    }\n\n    [Obsolete($\"ScriptableRenderPipelineExtensionAttribute.inUse is deprecated. Use SupportedOnRenderPipelineAttribute.isSupportedOnCurrentPipeline instead. #from(23.1) (UnityUpgradable) -> UnityEngine.Rendering.SupportedOnRenderPipelineAttribute.isSupportedOnCurrentPipeline\", false)]\n    public bool inUse\n        => GraphicsSettings.currentRenderPipelineAssetType == renderPipelineType;\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ShaderGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    public abstract class ShaderGUI\n    {\n        virtual public void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)\n        {\n            materialEditor.PropertiesDefaultGUI(properties);\n        }\n\n        virtual public void OnMaterialPreviewGUI(MaterialEditor materialEditor, Rect r, GUIStyle background)\n        {\n            materialEditor.DefaultPreviewGUI(r, background);\n        }\n\n        virtual public void OnMaterialInteractivePreviewGUI(MaterialEditor materialEditor, Rect r, GUIStyle background)\n        {\n            materialEditor.DefaultPreviewGUI(r, background);\n        }\n\n        virtual public void OnMaterialPreviewSettingsGUI(MaterialEditor materialEditor)\n        {\n            materialEditor.DefaultPreviewSettingsGUI();\n        }\n\n        virtual public void OnClosed(Material material)\n        {\n        }\n\n        virtual public void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)\n        {\n            material.shader = newShader;\n        }\n\n        virtual public void ValidateMaterial(Material material)\n        {\n        }\n\n        // Utility methods\n        protected static MaterialProperty FindProperty(string propertyName, MaterialProperty[] properties)\n        {\n            return FindProperty(propertyName, properties, true);\n        }\n\n        protected static MaterialProperty FindProperty(string propertyName, MaterialProperty[] properties, bool propertyIsMandatory)\n        {\n            for (var i = 0; i < properties.Length; i++)\n                if (properties[i] != null && properties[i].name == propertyName)\n                    return properties[i];\n\n            // We assume all required properties can be found, otherwise something is broken\n            if (propertyIsMandatory)\n                throw new ArgumentException(\"Could not find MaterialProperty: '\" + propertyName + \"', Num properties: \" + properties.Length);\n            return null;\n        }\n    }\n\n    internal static class ShaderGUIUtility\n    {\n        private static Type ExtractCustomEditorType(string customEditorName)\n        {\n            if (string.IsNullOrEmpty(customEditorName))\n                return null;\n\n            // To allow users to implement their own ShaderGUI for the Standard shader we iterate in reverse order\n            // because the UnityEditor assembly is assumed first in the assembly list.\n            // Users can now place a copy of the StandardShaderGUI script in the project and start modifying that copy to make their own version.\n            var unityEditorFullName = $\"UnityEditor.{customEditorName}\"; // for convenience: adding UnityEditor namespace is not needed in the shader\n            foreach (var type in TypeCache.GetTypesDerivedFrom<ShaderGUI>())\n            {\n                if (type.FullName.Equals(customEditorName, StringComparison.Ordinal) ||\n                    type.FullName.Equals(unityEditorFullName, StringComparison.Ordinal))\n                    return typeof(ShaderGUI).IsAssignableFrom(type) ? type : null;\n            }\n            return null;\n        }\n\n        internal static ShaderGUI CreateShaderGUI(string customEditorName)\n        {\n            Type customEditorType = ExtractCustomEditorType(customEditorName);\n            return customEditorType != null ? (Activator.CreateInstance(customEditorType) as ShaderGUI) : null;\n        }\n\n        [RequiredByNativeCode]\n        internal static void ValidateMaterial(Material material)\n        {\n            string customEditor = ShaderUtil.GetCurrentCustomEditor(material.shader);\n            CreateShaderGUI(customEditor)?.ValidateMaterial(material);\n        }\n    }\n} // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/Inspector/ShaderImporterInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditor.AssetImporters;\nusing System.Linq;\nusing UnityEditor.VersionControl;\nusing UnityEngine.Rendering;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(ShaderImporter))]\n    internal class ShaderImporterInspector : AssetImporterEditor\n    {\n        internal class Styles\n        {\n            public static GUIContent overridePreprocessor = EditorGUIUtility.TrTextContent(\"Override preprocessor\", \"Select preprocessor to use for this shader.\");\n        }\n\n        [Serializable]\n        private class TextureProp\n        {\n            public string propertyName;\n            public string displayName;\n            public Texture texture;\n            public TextureDimension dimension;\n            public bool modifiable;\n        }\n\n        private class ShaderProperties : ScriptableObject\n        {\n            public List<TextureProp> m_Properties = new List<TextureProp>();\n\n            public void CleanUp()\n            {\n                m_Properties.Clear();\n            }\n        }\n\n        SerializedProperty m_Properties;\n\n        internal override void OnHeaderControlsGUI()\n        {\n            GUILayout.FlexibleSpace();\n            ShowOpenButton(new[] { assetTarget });\n        }\n\n        protected override bool needsApplyRevert\n        {\n            // The shader include files are handled by shader importer & inspector but there are no\n            // properties for them to tweak atm. So we can ignore the apply/revert mechanism for them.\n            get\n            {\n                var importer = target as ShaderImporter;\n                if (importer == null)\n                    return false;\n\n                if (importer.GetShader() == null)\n                    return false;\n\n                return base.needsApplyRevert;\n            }\n        }\n\n        protected override Type extraDataType => typeof(ShaderProperties);\n\n        protected override void InitializeExtraDataInstance(Object extraTarget, int targetIndex)\n        {\n            var data = (ShaderProperties)extraTarget;\n            data.CleanUp();\n\n            var importer = targets[targetIndex] as ShaderImporter;\n            if (importer == null)\n                return;\n\n            var shader = importer.GetShader();\n            if (shader == null)\n                return;\n\n            var propertyCount = shader.GetPropertyCount();\n\n            for (var i = 0; i < propertyCount; i++)\n            {\n                if (shader.GetPropertyType(i) != ShaderPropertyType.Texture)\n                    continue;\n\n                var propertyName = shader.GetPropertyName(i);\n                var displayName = shader.GetPropertyDescription(i);  // might be empty\n                var modifiable = (shader.GetPropertyFlags(i) & ShaderPropertyFlags.NonModifiableTextureData) == 0;\n\n                Texture tex;\n                if (!modifiable)\n                    tex = importer.GetNonModifiableTexture(propertyName);\n                else\n                    tex = importer.GetDefaultTexture(propertyName);\n\n                var temp = new TextureProp\n                {\n                    propertyName = propertyName,\n                    texture = tex,\n                    dimension = shader.GetPropertyTextureDimension(i),\n                    displayName = displayName,\n                    modifiable = modifiable\n                };\n                data.m_Properties.Add(temp);\n            }\n        }\n\n        public override void OnEnable()\n        {\n            base.OnEnable();\n\n            m_Properties = extraDataSerializedObject.FindProperty(\"m_Properties\");\n        }\n\n        private void ShowTextures()\n        {\n            if (m_Properties.arraySize == 0)\n                return;\n\n            EditorGUILayout.LabelField(\"Default Maps\", EditorStyles.boldLabel);\n            for (var i = 0; i < m_Properties.arraySize; i++)\n            {\n                var prop = m_Properties.GetArrayElementAtIndex(i);\n                if (!prop.FindPropertyRelative(\"modifiable\").boolValue)\n                    continue;\n\n                DrawTextureField(prop);\n            }\n\n            EditorGUILayout.LabelField(\"NonModifiable Maps\", EditorStyles.boldLabel);\n            for (var i = 0; i < m_Properties.arraySize; i++)\n            {\n                var prop = m_Properties.GetArrayElementAtIndex(i);\n                if (prop.FindPropertyRelative(\"modifiable\").boolValue)\n                    continue;\n\n                DrawTextureField(prop);\n            }\n        }\n\n        private void DrawTextureField(SerializedProperty prop)\n        {\n            var oldTexture = prop.FindPropertyRelative(\"texture\").objectReferenceValue;\n            Texture newTexture = null;\n\n            EditorGUI.BeginChangeCheck();\n\n            Type textureType = MaterialEditor.GetTextureTypeFromDimension((TextureDimension)prop.FindPropertyRelative(\"dimension\").intValue);\n\n            if (textureType != null)\n            {\n                // Require at least two character in display name to prevent names like \"-\"\n                var displayName = prop.FindPropertyRelative(\"displayName\").stringValue;\n                var text = string.IsNullOrEmpty(displayName) ? ObjectNames.NicifyVariableName(prop.FindPropertyRelative(\"propertyName\").stringValue) : displayName;\n                newTexture = EditorGUILayout.MiniThumbnailObjectField(GUIContent.Temp(text), oldTexture, textureType) as Texture;\n            }\n\n            if (EditorGUI.EndChangeCheck())\n                prop.FindPropertyRelative(\"texture\").objectReferenceValue = newTexture;\n        }\n\n        protected override void Apply()\n        {\n            base.Apply();\n\n            var importer = target as ShaderImporter;\n            if (importer == null)\n                return;\n\n            var properties = (ShaderProperties)extraDataTarget;\n            var defaultNames = properties.m_Properties.Where(x => x.modifiable).Select(x => x.propertyName).ToArray();\n            var defaultTextures = properties.m_Properties.Where(x => x.modifiable).Select(x => x.texture).ToArray();\n            importer.SetDefaultTextures(defaultNames, defaultTextures);\n\n            var nonModNames = properties.m_Properties.Where(x => !x.modifiable).Select(x => x.propertyName).ToArray();\n            var nonModTextures = properties.m_Properties.Where(x => !x.modifiable).Select(x => x.texture).ToArray();\n            importer.SetNonModifiableTextures(nonModNames, nonModTextures);\n\n            AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(importer));\n        }\n\n        private static int GetNumberOfTextures(Shader shader)\n        {\n            int numberOfTextures = 0;\n            var propertyCount = shader.GetPropertyCount();\n\n            for (var i = 0; i < propertyCount; i++)\n            {\n                if (shader.GetPropertyType(i) == ShaderPropertyType.Texture)\n                    numberOfTextures++;\n            }\n            return numberOfTextures;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            var importer = target as ShaderImporter;\n            if (importer == null)\n                return;\n\n            var shader = importer.GetShader();\n            if (shader == null)\n                return;\n\n            if (GetNumberOfTextures(shader) != m_Properties.arraySize)\n            {\n                for (int i = 0; i < targets.Length; i++)\n                {\n                    InitializeExtraDataInstance(extraDataTargets[i], i);\n                }\n            }\n\n            serializedObject.Update();\n            extraDataSerializedObject.Update();\n\n            ShowTextures();\n\n            extraDataSerializedObject.ApplyModifiedProperties();\n            serializedObject.ApplyModifiedProperties();\n\n            ApplyRevertGUI();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ShaderIncludePathAttribute.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor\n{\n    [Obsolete(\"[ShaderIncludePath] attribute is no longer supported. Your shader library must be under the Assets folder or in a package. To include shader headers directly from a package, use #include \\\"Packages/<package name>/<path to your header file>\\\"\", true)]\n    [AttributeUsage(AttributeTargets.Method)]\n    public class ShaderIncludePathAttribute : Attribute\n    {\n        [RequiredSignature]\n        static string[] GetIncludePaths() { throw new InvalidOperationException(); }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ShaderInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing UnityEditor.Rendering;\nusing Object = UnityEngine.Object;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(Shader))]\n    internal class ShaderInspector : Editor\n    {\n        private static readonly string[] kPropertyTypes =\n        {\n            \"Color: \",\n            \"Vector: \",\n            \"Float: \",\n            \"Range: \",\n            \"Texture: \"\n        };\n        private static readonly string[] kTextureTypes =\n        {\n            \"No Texture?: \",\n            \"Any texture: \",\n            \"2D: \",\n            \"3D: \",\n            \"Cube: \",\n            \"2DArray: \",\n            \"CubeArray: \"\n        };\n\n        private const float kSpace = 5f;\n\n        const float kValueFieldWidth = 200.0f;\n        const float kArrayValuePopupBtnWidth = 25.0f;\n\n        private static bool s_KeywordsUnfolded = false;\n        private static bool s_PropertiesUnfolded = true;\n\n        internal class Styles\n        {\n            public static Texture2D errorIcon = EditorGUIUtility.LoadIcon(\"console.erroricon.sml\");\n            public static Texture2D warningIcon = EditorGUIUtility.LoadIcon(\"console.warnicon.sml\");\n\n            public static GUIContent togglePreprocess = EditorGUIUtility.TrTextContent(\"Preprocess only\", \"Show preprocessor output instead of compiled shader code\");\n            public static GUIContent toggleStripLineDirective = EditorGUIUtility.TrTextContent(\"Strip #line directives\", \"Strip #line directives from preprocessor output\");\n            public static GUIContent showSurface = EditorGUIUtility.TrTextContent(\"Show generated code\", \"Show generated code of a surface shader\");\n            public static GUIContent showFF = EditorGUIUtility.TrTextContent(\"Show generated code\", \"Show generated code of a fixed function shader\");\n            public static GUIContent showCurrent = EditorGUIUtility.TrTextContent(\"Compile and show code \\u007C \\u25BE\");  // vertical bar & dropdow arrow - due to lacking editor style of \"mini button with a dropdown\"\n            public static GUIContent overridableKeywords = EditorGUIUtility.TrTextContent(\"Overridable\", \"Shader keywords overridable by global shader keyword state\");\n            public static GUIContent notOverridableKeywords = EditorGUIUtility.TrTextContent(\"Not overridable\", \"Shader keywords not overridable by global shader keyword state\");\n\n            public static GUIStyle messageStyle = \"CN StatusInfo\";\n            public static GUIStyle evenBackground = \"CN EntryBackEven\";\n\n            public static GUIContent no = EditorGUIUtility.TrTextContent(\"no\");\n            public static GUIContent builtinShader = EditorGUIUtility.TrTextContent(\"Built-in shader\");\n\n            public static readonly GUIContent arrayValuePopupButton = EditorGUIUtility.TrTextContent(\"...\");\n        }\n        static readonly int kErrorViewHash = \"ShaderErrorView\".GetHashCode();\n\n        private static bool s_PreprocessOnly = false;\n        private static bool s_StripLineDirectives = true;\n\n        Vector2 m_ScrollPosition = Vector2.zero;\n        private Material m_SrpCompatibilityCheckMaterial = null;\n\n        public Material srpCompatibilityCheckMaterial\n        {\n            get\n            {\n                if (m_SrpCompatibilityCheckMaterial == null)\n                {\n                    m_SrpCompatibilityCheckMaterial = new Material(target as Shader);\n                }\n                return m_SrpCompatibilityCheckMaterial;\n            }\n        }\n\n        public virtual void OnEnable()\n        {\n            var s = target as Shader;\n            if (s != null)\n                ShaderUtil.FetchCachedMessages(s);\n        }\n\n        public virtual void OnDisable()\n        {\n            if (m_SrpCompatibilityCheckMaterial != null)\n            {\n                GameObject.DestroyImmediate(m_SrpCompatibilityCheckMaterial);\n            }\n        }\n\n        private static string GetPropertyType(Shader s, int index)\n        {\n            var type = s.GetPropertyType(index);\n            if (type == ShaderPropertyType.Texture)\n            {\n                return kTextureTypes[(int)s.GetPropertyTextureDimension(index)];\n            }\n            return kPropertyTypes[(int)type];\n        }\n\n        public override void OnInspectorGUI()\n        {\n            var s = target as Shader;\n            if (s == null)\n                return;\n\n            GUI.enabled = true;\n\n            EditorGUI.indentLevel = 0;\n\n            ShowShaderCodeArea(s);\n\n            if (s.isSupported)\n            {\n                EditorGUILayout.LabelField(\"Cast shadows\", (ShaderUtil.HasShadowCasterPass(s)) ? \"yes\" : \"no\");\n                EditorGUILayout.LabelField(\"Render queue\", ShaderUtil.GetRenderQueue(s).ToString(CultureInfo.InvariantCulture));\n                EditorGUILayout.LabelField(\"LOD\", ShaderUtil.GetLOD(s).ToString(CultureInfo.InvariantCulture));\n                EditorGUILayout.LabelField(\"Ignore projector\", ShaderUtil.DoesIgnoreProjector(s) ? \"yes\" : \"no\");\n                string disableBatchingString;\n                switch (s.disableBatching)\n                {\n                    case DisableBatchingType.False:\n                        disableBatchingString = \"no\";\n                        break;\n                    case DisableBatchingType.True:\n                        disableBatchingString = \"yes\";\n                        break;\n                    case DisableBatchingType.WhenLODFading:\n                        disableBatchingString = \"when LOD fading is on\";\n                        break;\n                    default:\n                        disableBatchingString = \"unknown\";\n                        break;\n                }\n                EditorGUILayout.LabelField(\"Disable batching\", disableBatchingString);\n                ShowKeywords(s);\n\n                // If any SRP is active, then display the SRP Batcher compatibility status\n                if (GraphicsSettings.currentRenderPipeline != null)\n                {\n                    // NOTE: Force the shader compilation to ensure GetSRPBatcherCompatibilityCode will be up to date\n                    srpCompatibilityCheckMaterial.SetPass(0);\n                    int subShader = ShaderUtil.GetShaderActiveSubshaderIndex(s);\n                    int SRPErrCode = ShaderUtil.GetSRPBatcherCompatibilityCode(s, subShader);\n                    string result = (0 == SRPErrCode) ? \"compatible\" : \"not compatible\";\n                    EditorGUILayout.LabelField(\"SRP Batcher\", result);\n                    if (SRPErrCode != 0)\n                    {\n                        EditorGUILayout.HelpBox(ShaderUtil.GetSRPBatcherCompatibilityIssueReason(s, subShader, SRPErrCode), MessageType.Info);\n                    }\n                }\n\n                ShowShaderProperties(s);\n            }\n        }\n\n        private void ShowKeywords(Shader s)\n        {\n            EditorGUILayout.BeginVertical();\n            s_KeywordsUnfolded = EditorGUILayout.Foldout(s_KeywordsUnfolded, \"Keywords\");\n            if (s_KeywordsUnfolded)\n            {\n                var keywords = s.keywordSpace.keywords;\n                var overridable = new List<LocalKeyword>();\n                var nonOverridable = new List<LocalKeyword>();\n\n                foreach (var k in keywords)\n                {\n                    if (k.isOverridable)\n                        overridable.Add(k);\n                    else\n                        nonOverridable.Add(k);\n                }\n\n                overridable.Sort((x, y) => string.CompareOrdinal(x.name, y.name));\n                nonOverridable.Sort((x, y) => string.CompareOrdinal(x.name, y.name));\n\n                EditorGUILayout.LabelField(Styles.overridableKeywords, EditorStyles.boldLabel);\n                foreach (var k in overridable)\n                    EditorGUILayout.LabelField(k.name);\n\n                EditorGUILayout.LabelField(Styles.notOverridableKeywords, EditorStyles.boldLabel);\n                foreach (var k in nonOverridable)\n                    EditorGUILayout.LabelField(k.name);\n            }\n\n            EditorGUILayout.EndVertical();\n        }\n\n        private void ShowShaderCodeArea(Shader s)\n        {\n            ShowSurfaceShaderButton(s);\n            ShowFixedFunctionShaderButton(s);\n            ShowCompiledCodeButton(s);\n            ShowShaderErrors(s);\n        }\n\n        private static void ShowShaderProperties(Shader s)\n        {\n            GUILayout.Space(kSpace);\n            s_PropertiesUnfolded = EditorGUILayout.Foldout(s_PropertiesUnfolded, \"Properties\");\n            if (s_PropertiesUnfolded)\n            {\n                int n = s.GetPropertyCount();\n                for (int i = 0; i < n; ++i)\n                {\n                    string pname = s.GetPropertyName(i);\n                    string pdesc = s.GetPropertyDescription(i) + \" (\" + s.GetPropertyType(i) + \")\";\n                    EditorGUILayout.LabelField(pname, pdesc);\n                }\n            }\n        }\n\n        // shared by compute shader inspector too\n        internal static void ShaderErrorListUI(Object shader, ShaderMessage[] messages, ref Vector2 scrollPosition)\n        {\n            int n = messages.Length;\n\n            int errorCount = 0;\n            int warningCount = 0;\n\n            for (int i = 0; i < n; ++i)\n            {\n                ShaderCompilerMessageSeverity severity = messages[i].severity;\n\n                if (severity == ShaderCompilerMessageSeverity.Warning)\n                    warningCount++;\n                else if (severity == ShaderCompilerMessageSeverity.Error)\n                    errorCount++;\n            }\n\n            GUILayout.Space(kSpace);\n            GUILayout.Label(string.Format(\"({0}) Error{1} and ({2}) Warning{3}:\", errorCount, (errorCount != 1) ? \"s\" : \"\", warningCount, (warningCount != 1) ? \"s\" : \"\"), EditorStyles.boldLabel);\n\n            int errorListID = GUIUtility.GetControlID(kErrorViewHash, FocusType.Passive);\n            float height = Mathf.Min(n * 20f + 40f, 150f);\n            scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUISkin.current.box, GUILayout.MinHeight(height));\n\n            EditorGUIUtility.SetIconSize(new Vector2(16.0f, 16.0f));\n            float lineHeight = Styles.messageStyle.CalcHeight(EditorGUIUtility.TempContent(Styles.errorIcon), 100);\n\n            Event e = Event.current;\n\n            for (int i = 0; i < n; ++i)\n            {\n                Rect r = EditorGUILayout.GetControlRect(false, lineHeight);\n\n                string err = messages[i].message;\n                string plat = messages[i].platform.ToString();\n                bool warn = messages[i].severity != ShaderCompilerMessageSeverity.Error;\n                string fileName = FileUtil.GetLastPathNameComponent(messages[i].file);\n                int line = messages[i].line;\n\n                // Double click opens shader file at error line\n                if (e.type == EventType.MouseDown && e.button == 0 && r.Contains(e.mousePosition))\n                {\n                    GUIUtility.keyboardControl = errorListID;\n                    if (e.clickCount == 2)\n                    {\n                        string filePath = messages[i].file;\n                        Object asset = string.IsNullOrEmpty(filePath) ? null : AssetDatabase.LoadMainAssetAtPath(filePath);\n\n                        // if we don't have an asset and the filePath is an absolute path, it's an error in a system\n                        // cginc - open that instead\n                        if (asset == null && System.IO.Path.IsPathRooted(filePath))\n                            ShaderUtil.OpenSystemShaderIncludeError(filePath, line);\n                        else\n                            AssetDatabase.OpenAsset(asset ?? shader, line);\n                        GUIUtility.ExitGUI();\n                    }\n                    e.Use();\n                }\n\n                // Context menu, \"Copy\"\n                if (e.type == EventType.ContextClick && r.Contains(e.mousePosition))\n                {\n                    e.Use();\n                    var menu = new GenericMenu();\n                    // need to copy current value to be used in delegate\n                    // (C# closures close over variables, not their values)\n                    var errorIndex = i;\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Copy error text\"), false, delegate {\n                        string errMsg = messages[errorIndex].message;\n                        if (!string.IsNullOrEmpty(messages[errorIndex].messageDetails))\n                        {\n                            errMsg += '\\n';\n                            errMsg += messages[errorIndex].messageDetails;\n                        }\n                        EditorGUIUtility.systemCopyBuffer = errMsg;\n                    });\n                    menu.ShowAsContext();\n                }\n\n                // background\n                if (e.type == EventType.Repaint)\n                {\n                    if ((i & 1) == 0)\n                    {\n                        GUIStyle st = Styles.evenBackground;\n                        st.Draw(r, false, false, false, false);\n                    }\n                }\n\n                // error location on the right side\n                Rect locRect = r;\n                locRect.xMin = locRect.xMax;\n                if (line > 0)\n                {\n                    GUIContent gc;\n                    if (string.IsNullOrEmpty(fileName))\n                        gc = EditorGUIUtility.TempContent(line.ToString(CultureInfo.InvariantCulture));\n                    else\n                        gc = EditorGUIUtility.TempContent(fileName + \":\" + line.ToString(CultureInfo.InvariantCulture));\n\n                    // calculate size so we can right-align it\n                    Vector2 size = EditorStyles.miniLabel.CalcSize(gc);\n                    locRect.xMin -= size.x;\n                    GUI.Label(locRect, gc, EditorStyles.miniLabel);\n                    locRect.xMin -= 2;\n                    // ensure some minimum width so that platform field next will line up\n                    if (locRect.width < 30)\n                        locRect.xMin = locRect.xMax - 30;\n                }\n\n                // platform to the left of it\n                Rect platRect = locRect;\n                platRect.width = 0;\n                if (plat.Length > 0)\n                {\n                    GUIContent gc = EditorGUIUtility.TempContent(plat);\n                    // calculate size so we can right-align it\n                    Vector2 size = EditorStyles.miniLabel.CalcSize(gc);\n                    platRect.xMin -= size.x;\n\n                    // draw platform in dimmer color; it's often not very important information\n                    Color oldColor = GUI.contentColor;\n                    GUI.contentColor = new Color(1, 1, 1, 0.5f);\n                    GUI.Label(platRect, gc, EditorStyles.miniLabel);\n                    GUI.contentColor = oldColor;\n                    platRect.xMin -= 2;\n                }\n\n                // error message\n                Rect msgRect = r;\n                msgRect.xMax = platRect.xMin;\n                GUI.Label(msgRect, EditorGUIUtility.TempContent(err, warn ? Styles.warningIcon : Styles.errorIcon), Styles.messageStyle);\n            }\n            EditorGUIUtility.SetIconSize(Vector2.zero);\n            GUILayout.EndScrollView();\n        }\n\n        ShaderMessage[] m_ShaderMessages;\n        private void ShowShaderErrors(Shader s)\n        {\n            if (Event.current.type == EventType.Layout)\n            {\n                int n = ShaderUtil.GetShaderMessageCount(s);\n                m_ShaderMessages = null;\n                if (n >= 1)\n                {\n                    m_ShaderMessages = ShaderUtil.GetShaderMessages(s);\n                }\n            }\n\n            if (m_ShaderMessages == null)\n                return;\n            ShaderErrorListUI(s, m_ShaderMessages, ref m_ScrollPosition);\n        }\n\n        // Compiled shader code button+dropdown\n        private void ShowCompiledCodeButton(Shader s)\n        {\n            EditorGUILayout.BeginVertical();\n            ShaderImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(s.GetInstanceID())) as ShaderImporter;\n\n            s_PreprocessOnly = EditorGUILayout.Toggle(Styles.togglePreprocess, s_PreprocessOnly);\n            if (s_PreprocessOnly)\n                s_StripLineDirectives = EditorGUILayout.Toggle(Styles.toggleStripLineDirective, s_StripLineDirectives);\n\n            EditorGUILayout.BeginHorizontal();\n            EditorGUILayout.PrefixLabel(\"Compiled code\", EditorStyles.miniButton);\n\n            var hasCode = ShaderUtil.HasShaderSnippets(s) || ShaderUtil.HasSurfaceShaders(s) || ShaderUtil.HasFixedFunctionShaders(s);\n            if (hasCode)\n            {\n                // button with a drop-down part on the right\n                var modeContent = Styles.showCurrent;\n                var modeRect = GUILayoutUtility.GetRect(modeContent, EditorStyles.miniButton, GUILayout.ExpandWidth(false));\n                var modeDropRect = new Rect(modeRect.xMax - 16, modeRect.y, 16, modeRect.height);\n                if (EditorGUI.DropdownButton(modeDropRect, GUIContent.none, FocusType.Passive, GUIStyle.none))\n                {\n                    Rect rect = GUILayoutUtility.topLevel.GetLast();\n                    PopupWindow.Show(rect, new ShaderInspectorPlatformsPopup(s));\n                    GUIUtility.ExitGUI();\n                }\n                if (GUI.Button(modeRect, modeContent, EditorStyles.miniButton))\n                {\n                    ShaderUtil.OpenCompiledShader(s, ShaderInspectorPlatformsPopup.currentMode, ShaderInspectorPlatformsPopup.currentPlatformMask, ShaderInspectorPlatformsPopup.currentVariantStripping == 0, s_PreprocessOnly, s_StripLineDirectives);\n                    GUIUtility.ExitGUI();\n                }\n            }\n            else\n            {\n                // Note: PrefixLabel is sometimes buggy if followed by a non-control (like Label).\n                // We just want to show a label here, but have to pretend it's a button so it is treated like\n                // a control.\n                GUILayout.Button(\"none (precompiled shader)\", GUI.skin.label);\n            }\n\n            EditorGUILayout.EndHorizontal();\n            EditorGUILayout.EndVertical();\n        }\n\n        // \"show surface shader\" button\n        private static void ShowSurfaceShaderButton(Shader s)\n        {\n            var hasSurface = ShaderUtil.HasSurfaceShaders(s);\n            EditorGUILayout.BeginHorizontal();\n            EditorGUILayout.PrefixLabel(\"Surface shader\", EditorStyles.miniButton);\n            if (hasSurface)\n            {\n                // check if this is a built-in shader (has no importer);\n                // we can't show generated code in that case\n                var builtinShader = (AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(s)) == null);\n                if (!builtinShader)\n                {\n                    if (GUILayout.Button(Styles.showSurface, EditorStyles.miniButton, GUILayout.ExpandWidth(false)))\n                    {\n                        ShaderUtil.OpenParsedSurfaceShader(s);\n                        GUIUtility.ExitGUI();\n                    }\n                }\n                else\n                {\n                    // See comment below why this is a button.\n                    GUILayout.Button(Styles.builtinShader, GUI.skin.label);\n                }\n            }\n            else\n            {\n                // Note: PrefixLabel is sometimes buggy if followed by a non-control (like Label).\n                // We just want to show a label here, but have to pretend it's a button so it is treated like\n                // a control.\n                GUILayout.Button(Styles.no, GUI.skin.label);\n            }\n            EditorGUILayout.EndHorizontal();\n        }\n\n        // \"show fixed function shader\" button\n        private static void ShowFixedFunctionShaderButton(Shader s)\n        {\n            var hasFF = ShaderUtil.HasFixedFunctionShaders(s);\n            EditorGUILayout.BeginHorizontal();\n            EditorGUILayout.PrefixLabel(\"Fixed function\", EditorStyles.miniButton);\n            if (hasFF)\n            {\n                // check if this is a built-in shader (has no importer);\n                // we can't show generated code in that case\n                var builtinShader = (AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(s)) == null);\n                if (!builtinShader)\n                {\n                    if (GUILayout.Button(Styles.showFF, EditorStyles.miniButton, GUILayout.ExpandWidth(false)))\n                    {\n                        ShaderUtil.OpenGeneratedFixedFunctionShader(s);\n                        GUIUtility.ExitGUI();\n                    }\n                }\n                else\n                {\n                    // See comment below why this is a button.\n                    GUILayout.Button(Styles.builtinShader, GUI.skin.label);\n                }\n            }\n            else\n            {\n                // Note: PrefixLabel is sometimes buggy if followed by a non-control (like Label).\n                // We just want to show a label here, but have to pretend it's a button so it is treated like\n                // a control.\n                GUILayout.Button(Styles.no, GUI.skin.label);\n            }\n            EditorGUILayout.EndHorizontal();\n        }\n    }\n\n    // Popup window to select which platforms to compile a shader for.\n    internal class ShaderInspectorPlatformsPopup : PopupWindowContent\n    {\n        private class Styles\n        {\n            static public readonly GUIStyle menuItem = \"MenuItem\";\n            static public readonly GUIStyle separator = \"sv_iconselector_sep\";\n        }\n\n        static internal readonly string[] s_PlatformModes =\n        {\n            \"Current graphics device\",\n            \"Current build platform\",\n            \"All platforms\",\n            \"Custom:\"\n        };\n\n        private static string[] s_ShaderPlatformNames;\n        private static int[] s_ShaderPlatformIndices;\n\n        const float kFrameWidth = 1f;\n        const float kSeparatorHeight = 6;\n\n        private readonly Shader m_Shader;\n\n        private ulong totalVariants;\n        private ulong variantsWithUsage;\n\n\n        public static int currentMode\n        {\n            get\n            {\n                if (s_CurrentMode < 0)\n                    s_CurrentMode = EditorPrefs.GetInt(\"ShaderInspectorPlatformMode\", 1);\n                return s_CurrentMode;\n            }\n            set\n            {\n                s_CurrentMode = value;\n                EditorPrefs.SetInt(\"ShaderInspectorPlatformMode\", value);\n            }\n        }\n        static int s_CurrentMode = -1;\n\n        public static int currentPlatformMask\n        {\n            get\n            {\n                if (s_CurrentPlatformMask < 0)\n                {\n                    int defaultMask = (1 << Enum.GetNames(typeof(Rendering.ShaderCompilerPlatform)).Length - 1);\n                    s_CurrentPlatformMask = EditorPrefs.GetInt(\"ShaderInspectorPlatformMask\", defaultMask);\n                }\n                return s_CurrentPlatformMask;\n            }\n            set\n            {\n                s_CurrentPlatformMask = value;\n                EditorPrefs.SetInt(\"ShaderInspectorPlatformMask\", value);\n            }\n        }\n        static int s_CurrentPlatformMask = -1;\n\n        public static int currentVariantStripping\n        {\n            get\n            {\n                if (s_CurrentVariantStripping < 0)\n                    s_CurrentVariantStripping = EditorPrefs.GetInt(\"ShaderInspectorVariantStripping\", 1);\n                return s_CurrentVariantStripping;\n            }\n            set\n            {\n                s_CurrentVariantStripping = value;\n                EditorPrefs.SetInt(\"ShaderInspectorVariantStripping\", value);\n            }\n        }\n        static int s_CurrentVariantStripping = -1;\n\n\n        public ShaderInspectorPlatformsPopup(Shader shader)\n        {\n            m_Shader = shader;\n            InitializeShaderPlatforms();\n            totalVariants = 0;\n            variantsWithUsage = 0;\n        }\n\n        static void InitializeShaderPlatforms()\n        {\n            if (s_ShaderPlatformNames != null)\n                return;\n            int platformMask = ShaderUtil.GetAvailableShaderCompilerPlatforms();\n            var names = new List<string>();\n            var indices = new List<int>();\n            for (int i = 0; i < 32; ++i)\n            {\n                if ((platformMask & (1 << i)) == 0)\n                    continue;\n                names.Add(((Rendering.ShaderCompilerPlatform)i).ToString());\n                indices.Add(i);\n            }\n            s_ShaderPlatformNames = names.ToArray();\n            s_ShaderPlatformIndices = indices.ToArray();\n            currentPlatformMask &= platformMask;\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            var rowCount = s_PlatformModes.Length + s_ShaderPlatformNames.Length + 2;\n            var windowHeight = rowCount * EditorGUI.kSingleLineHeight + kSeparatorHeight * 3;\n            windowHeight += 2 * kFrameWidth;\n\n            var windowSize = new Vector2(210, windowHeight);\n            return windowSize;\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            if (m_Shader == null)\n                return;\n\n            // We do not use the layout event\n            if (Event.current.type == EventType.Layout)\n                return;\n\n            Draw(editorWindow, rect.width);\n\n            // Use mouse move so we get hover state correctly in the menu item rows\n            if (Event.current.type == EventType.MouseMove)\n                Event.current.Use();\n\n            // Escape closes the window\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)\n            {\n                editorWindow.Close();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        private void DrawSeparator(ref Rect rect)\n        {\n            GUI.Label(new Rect(rect.x + 5, rect.y + 3, rect.width - 10, 3), GUIContent.none, Styles.separator);\n            rect.y += kSeparatorHeight;\n        }\n\n        private void Draw(EditorWindow caller, float listElementWidth)\n        {\n            var drawPos = new Rect(0, 0, listElementWidth, EditorGUI.kSingleLineHeight);\n\n            // Generic platform modes\n            for (var i = 0; i < s_PlatformModes.Length; ++i)\n            {\n                DoOneMode(drawPos, i);\n                drawPos.y += EditorGUI.kSingleLineHeight;\n            }\n\n            // Custom platform settings\n            Color oldColor = GUI.color;\n            if (currentMode != 3) // darker color when \"Custom\" is not selected\n                GUI.color *= new Color(1, 1, 1, 0.7f);\n            drawPos.xMin += 16.0f;\n            for (var i = 0; i < s_ShaderPlatformNames.Length; ++i)\n            {\n                DoCustomPlatformBit(drawPos, i);\n                drawPos.y += EditorGUI.kSingleLineHeight;\n            }\n            GUI.color = oldColor;\n            drawPos.xMin -= 16.0f;\n            DrawSeparator(ref drawPos);\n\n            DoShaderVariants(caller, ref drawPos);\n        }\n\n        void DoOneMode(Rect rect, int index)\n        {\n            EditorGUI.BeginChangeCheck();\n            GUI.Toggle(rect, currentMode == index, EditorGUIUtility.TempContent(s_PlatformModes[index]), Styles.menuItem);\n            if (EditorGUI.EndChangeCheck())\n                currentMode = index;\n        }\n\n        void DoCustomPlatformBit(Rect rect, int index)\n        {\n            EditorGUI.BeginChangeCheck();\n            int maskBit = 1 << s_ShaderPlatformIndices[index];\n            bool on = (currentPlatformMask & maskBit) != 0;\n            on = GUI.Toggle(rect, on, EditorGUIUtility.TempContent(s_ShaderPlatformNames[index]), Styles.menuItem);\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (on)\n                    currentPlatformMask |= maskBit;\n                else\n                    currentPlatformMask &= ~maskBit;\n                currentMode = 3; // custom\n            }\n        }\n\n        static string FormatCount(ulong count)\n        {\n            if (count > 1000 * 1000 * 1000)\n                return ((double)count / 1000000000.0).ToString(\"f2\", CultureInfo.InvariantCulture.NumberFormat) + \"B\";\n            if (count > 1000 * 1000)\n                return ((double)count / 1000000.0).ToString(\"f2\", CultureInfo.InvariantCulture.NumberFormat) + \"M\";\n            if (count > 1000)\n                return ((double)count / 1000.0).ToString(\"f2\", CultureInfo.InvariantCulture.NumberFormat) + \"K\";\n            return count.ToString();\n        }\n\n        void DoShaderVariants(EditorWindow caller, ref Rect drawPos)\n        {\n            // setting for whether shader variants should be stripped\n            EditorGUI.BeginChangeCheck();\n            bool strip = GUI.Toggle(drawPos, currentVariantStripping == 1, EditorGUIUtility.TempContent(\"Skip unused shader_features\"), Styles.menuItem);\n            drawPos.y += EditorGUI.kSingleLineHeight;\n            if (EditorGUI.EndChangeCheck())\n                currentVariantStripping = strip ? 1 : 0;\n\n            // display included variant count, and a button to show list of them\n            drawPos.y += kSeparatorHeight;\n            ulong variantCount = 0;\n            if (strip)\n            {\n                if (variantsWithUsage == 0)\n                    variantsWithUsage = ShaderUtil.GetVariantCount(m_Shader, true);\n                variantCount = variantsWithUsage;\n            }\n            else\n            {\n                if (totalVariants == 0)\n                    totalVariants = ShaderUtil.GetVariantCount(m_Shader, false);\n                variantCount = totalVariants;\n            }\n            var variantText = FormatCount(variantCount) +\n                (strip ?\n                    \" variants included\" :\n                    \" variants total\");\n            Rect buttonRect = drawPos;\n            buttonRect.x += Styles.menuItem.padding.left;\n            buttonRect.width -= Styles.menuItem.padding.left + 4;\n            GUI.Label(buttonRect, variantText);\n            buttonRect.xMin = buttonRect.xMax - 40;\n            if (GUI.Button(buttonRect, \"Show\", EditorStyles.miniButtonMid))\n            {\n                ShaderUtil.OpenShaderCombinations(m_Shader, strip);\n                caller.Close();\n                GUIUtility.ExitGUI();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ShaderVariantCollectionInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(ShaderVariantCollection))]\n    internal class ShaderVariantCollectionInspector : Editor\n    {\n        private class Styles\n        {\n            public static readonly GUIContent iconAdd    = EditorGUIUtility.TrIconContent(\"Toolbar Plus\", \"Add variant\");\n            public static readonly GUIContent iconRemove = EditorGUIUtility.TrIconContent(\"Toolbar Minus\", \"Remove entry\");\n            public static readonly GUIStyle invisibleButton = \"InvisibleButton\";\n        }\n\n        SerializedProperty m_Shaders;\n\n\n        public virtual void OnEnable()\n        {\n            m_Shaders = serializedObject.FindProperty(\"m_Shaders\");\n        }\n\n        static Rect GetAddRemoveButtonRect(Rect r)\n        {\n            var buttonSize = Styles.invisibleButton.CalcSize(Styles.iconRemove);\n            return new Rect(r.xMax - buttonSize.x, r.y + (int)(r.height / 2 - buttonSize.y / 2), buttonSize.x, buttonSize.y);\n        }\n\n        // Show window to select shader variants\n        void DisplayAddVariantsWindow(Shader shader, ShaderVariantCollection collection)\n        {\n            var data = new AddShaderVariantWindow.PopupData();\n            data.shader = shader;\n            data.collection = collection;\n            AddShaderVariantWindow.ShowAddVariantWindow(data);\n            GUIUtility.ExitGUI();\n        }\n\n        void DrawShaderEntry(int shaderIndex)\n        {\n            var entryProp = m_Shaders.GetArrayElementAtIndex(shaderIndex);\n            Shader shader = (Shader)entryProp.FindPropertyRelative(\"first\").objectReferenceValue;\n\n            // Shader name and button to remove it\n            var variantsProp = entryProp.FindPropertyRelative(\"second.variants\");\n            using (new GUILayout.HorizontalScope())\n            {\n                Rect rowRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.boldLabel);\n                Rect minusRect = GetAddRemoveButtonRect(rowRect);\n                rowRect.xMax = minusRect.x;\n\n                GUI.Label(rowRect, shader == null ? \"<MISSING SHADER>\" : shader.name, EditorStyles.boldLabel);\n\n                if (GUI.Button(minusRect, Styles.iconRemove, Styles.invisibleButton))\n                {\n                    m_Shaders.DeleteArrayElementAtIndex(shaderIndex);\n                    return;\n                }\n            }\n\n            // Variants for this shader\n            for (var i = 0; i < variantsProp.arraySize; ++i)\n            {\n                var prop = variantsProp.GetArrayElementAtIndex(i);\n                var keywords = prop.FindPropertyRelative(\"keywords\").stringValue;\n                if (string.IsNullOrEmpty(keywords))\n                    keywords = \"<no keywords>\";\n                var passType = (UnityEngine.Rendering.PassType)prop.FindPropertyRelative(\"passType\").intValue;\n                Rect rowRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.miniLabel);\n                Rect minusRect = GetAddRemoveButtonRect(rowRect);\n\n\n                // Variant entry with button to remove it\n                rowRect.xMax = minusRect.x;\n                GUI.Label(rowRect, passType + \" \" + keywords, EditorStyles.miniLabel);\n                if (GUI.Button(minusRect, Styles.iconRemove, Styles.invisibleButton))\n                {\n                    variantsProp.DeleteArrayElementAtIndex(i);\n                }\n            }\n\n            // Add variant button\n            Rect addRowRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.miniLabel);\n            Rect plusRect = GetAddRemoveButtonRect(addRowRect);\n\n            if (shader != null && GUI.Button(plusRect, Styles.iconAdd, Styles.invisibleButton))\n            {\n                DisplayAddVariantsWindow(shader, target as ShaderVariantCollection);\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            for (var i = 0; i < m_Shaders.arraySize; ++i)\n            {\n                DrawShaderEntry(i);\n            }\n\n            // Button to add a new shader to collection\n            if (GUILayout.Button(\"Add shader\"))\n            {\n                // Show object selector\n                ObjectSelector.get.Show(null, typeof(Shader), null, false);\n                ObjectSelector.get.objectSelectorID = \"ShaderVariantSelector\".GetHashCode();\n                GUIUtility.ExitGUI();\n            }\n            if (Event.current.type == EventType.ExecuteCommand)\n            {\n                // New shader picked in object selector; add it to the collection\n                if (Event.current.commandName == ObjectSelector.ObjectSelectorClosedCommand && ObjectSelector.get.objectSelectorID == \"ShaderVariantSelector\".GetHashCode())\n                {\n                    var newShader = ObjectSelector.GetCurrentObject() as Shader;\n                    if (newShader != null)\n                    {\n                        ShaderUtil.AddNewShaderToCollection(newShader, target as ShaderVariantCollection);\n                    }\n                    Event.current.Use();\n                    GUIUtility.ExitGUI();\n                }\n            }\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n\n\n    // Utility window for selecting shader variants to add.\n    // Some shaders (Standard, SpeedTree etc.) have massive amounts of variants\n    // (e.g. about 30000), and approaches like \"display a popup menu with all of them\"\n    // don't work.\n    internal class AddShaderVariantWindow : EditorWindow\n    {\n        internal class PopupData\n        {\n            public Shader shader;\n            public ShaderVariantCollection collection;\n        }\n\n        class Styles\n        {\n            public static readonly GUIStyle sMenuItem = \"MenuItem\";\n            public static readonly GUIStyle sSeparator = \"sv_iconselector_sep\";\n        }\n\n        const float kMargin = 2;\n        const float kSpaceHeight = 6;\n        const float kSeparatorHeight = 3;\n\n        private const float kMinWindowWidth = 400;\n        static readonly float kMiscUIHeight =\n            5 * EditorGUI.kSingleLineHeight +\n            kSeparatorHeight * 2 +\n            kSpaceHeight * 5 +\n            kMargin * 2;\n\n        private static readonly float kMinWindowHeight = 9 * EditorGUI.kSingleLineHeight + kMiscUIHeight;\n\n        PopupData m_Data;\n        List<string> m_SelectedKeywords;\n        List<string> m_AvailableKeywords;\n        List<int> m_SelectedVariants; // Indices of variants currently selected for adding\n\n        int[] m_FilteredVariantTypes;\n        string[][] m_FilteredVariantKeywords;\n\n        int m_MaxVisibleVariants;\n        int m_NumFilteredVariants;\n\n        public AddShaderVariantWindow()\n        {\n            position = new Rect(100, 100, kMinWindowWidth * 1.5f, kMinWindowHeight * 1.5f);\n            minSize = new Vector2(kMinWindowWidth, kMinWindowHeight);\n            wantsMouseMove = true;\n        }\n\n        private void Initialize(PopupData data)\n        {\n            m_Data = data;\n            m_SelectedKeywords = new List<string>();\n            m_AvailableKeywords = new List<string>();\n            m_SelectedVariants = new List<int>();\n            ApplyKeywordFilter();\n        }\n\n        public static void ShowAddVariantWindow(PopupData data)\n        {\n            var w = EditorWindow.GetWindow<AddShaderVariantWindow>(true, \"Add shader \" + data.shader.name + \" variants to collection\");\n            w.Initialize(data);\n            w.m_Parent.window.m_DontSaveToLayout = true;\n        }\n\n        void ApplyKeywordFilter()\n        {\n            m_MaxVisibleVariants = (int)(CalcVerticalSpaceForVariants() / EditorGUI.kSingleLineHeight);\n            string[] keywordLists, remainingKeywords;\n            m_FilteredVariantTypes = new int[m_MaxVisibleVariants];\n\n            ShaderUtil.GetShaderVariantEntriesFiltered(m_Data.shader,\n                m_MaxVisibleVariants + 1,                                         // query one more to know if we're truncating\n                m_SelectedKeywords.ToArray(),\n                m_Data.collection,\n                out m_FilteredVariantTypes,\n                out keywordLists,\n                out remainingKeywords);\n\n            m_NumFilteredVariants = m_FilteredVariantTypes.Length;\n            m_FilteredVariantKeywords = new string[m_NumFilteredVariants][];\n            for (var i = 0; i < m_NumFilteredVariants; ++i)\n            {\n                m_FilteredVariantKeywords[i] = keywordLists[i].Split(' ');\n            }\n\n            m_AvailableKeywords.Clear();\n            m_AvailableKeywords.InsertRange(0, remainingKeywords);\n            m_AvailableKeywords.Sort();\n        }\n\n        public void OnGUI()\n        {\n            // Objects became deleted while our window was showing? Close.\n            if (m_Data == null || m_Data.shader == null || m_Data.collection == null)\n            {\n                Close();\n                return;\n            }\n\n            // We do not use the layout event\n            if (Event.current.type == EventType.Layout)\n                return;\n\n            Rect rect = new Rect(0, 0, position.width, position.height);\n            Draw(rect);\n\n            // Repaint on mouse move so we get hover highlights in menu item rows\n            if (Event.current.type == EventType.MouseMove)\n                Repaint();\n        }\n\n        private bool KeywordButton(Rect buttonRect, string k, Vector2 areaSize)\n        {\n            // If we can't fit all buttons (shader has *a lot* of keywords) and would start clipping,\n            // do display the partially clipped ones with some transparency.\n            var oldColor = GUI.color;\n            if (buttonRect.yMax > areaSize.y)\n                GUI.color = new Color(1, 1, 1, 0.4f);\n\n            var result = GUI.Button(buttonRect, EditorGUIUtility.TempContent(k), EditorStyles.miniButton);\n            GUI.color = oldColor;\n            return result;\n        }\n\n        float CalcVerticalSpaceForKeywords()\n        {\n            return Mathf.Floor((position.height - kMiscUIHeight) / 4);\n        }\n\n        float CalcVerticalSpaceForVariants()\n        {\n            return (position.height - kMiscUIHeight) / 2;\n        }\n\n        void DrawKeywordsList(ref Rect rect, List<string> keywords, bool clickingAddsToSelected)\n        {\n            rect.height = CalcVerticalSpaceForKeywords();\n            var displayKeywords = keywords.Select(k => k.ToLowerInvariant()).ToList();\n\n            GUI.BeginGroup(rect);\n            Rect indentRect = new Rect(4, 0, rect.width, rect.height);\n            var layoutRects = EditorGUIUtility.GetFlowLayoutedRects(indentRect, EditorStyles.miniButton, 2, 2, displayKeywords);\n            for (var i = 0; i < displayKeywords.Count; ++i)\n            {\n                if (KeywordButton(layoutRects[i], displayKeywords[i], rect.size))\n                {\n                    if (clickingAddsToSelected)\n                    {\n                        if (!m_SelectedKeywords.Contains(keywords[i]))\n                        {\n                            m_SelectedKeywords.Add(keywords[i]);\n                            m_SelectedKeywords.Sort();\n                            m_AvailableKeywords.Remove(keywords[i]);\n                        }\n                    }\n                    else\n                    {\n                        m_AvailableKeywords.Add(keywords[i]);\n                        m_SelectedKeywords.Remove(keywords[i]);\n                    }\n                    ApplyKeywordFilter();\n                    GUIUtility.ExitGUI();\n                }\n            }\n            GUI.EndGroup();\n            rect.y += rect.height;\n        }\n\n        void DrawSectionHeader(ref Rect rect, string titleString, bool separator)\n        {\n            // space\n            rect.y += kSpaceHeight;\n            // separator\n            if (separator)\n            {\n                rect.height = kSeparatorHeight;\n                GUI.Label(rect, GUIContent.none, Styles.sSeparator);\n                rect.y += rect.height;\n            }\n            // label\n            rect.height = EditorGUI.kSingleLineHeight;\n            GUI.Label(rect, titleString);\n            rect.y += rect.height;\n        }\n\n        private void Draw(Rect windowRect)\n        {\n            var rect = new Rect(kMargin, kMargin, windowRect.width - kMargin * 2, EditorGUI.kSingleLineHeight);\n\n            DrawSectionHeader(ref rect, \"Pick shader keywords to narrow down variant list:\", false);\n            DrawKeywordsList(ref rect, m_AvailableKeywords, true);\n\n            DrawSectionHeader(ref rect, \"Selected keywords:\", true);\n            DrawKeywordsList(ref rect, m_SelectedKeywords, false);\n\n            DrawSectionHeader(ref rect, \"Shader variants with these keywords (click to select):\", true);\n\n            if (m_NumFilteredVariants > 0)\n            {\n                int maxFilteredLength = (int)(CalcVerticalSpaceForVariants() / EditorGUI.kSingleLineHeight);\n\n                if (maxFilteredLength > m_MaxVisibleVariants) // Query data again if we have bigger window than at last query\n                    ApplyKeywordFilter();\n\n                // Display first N variants (don't want to display thousands of them if filter is not narrow)\n                for (var i = 0; i < Mathf.Min(m_NumFilteredVariants, maxFilteredLength); ++i)\n                {\n                    var passType = (UnityEngine.Rendering.PassType)m_FilteredVariantTypes[i];\n                    var wasSelected = m_SelectedVariants.Contains(i);\n                    var keywordString = string.IsNullOrEmpty(m_FilteredVariantKeywords[i][0]) ? \"<no keywords>\" : string.Join(\" \", m_FilteredVariantKeywords[i]);\n                    var displayString = passType + \" \" + keywordString.ToLowerInvariant();\n                    var isSelected = GUI.Toggle(rect, wasSelected, displayString, Styles.sMenuItem);\n                    rect.y += rect.height;\n\n                    if (isSelected && !wasSelected)\n                        m_SelectedVariants.Add(i);\n                    else if (!isSelected && wasSelected)\n                        m_SelectedVariants.Remove(i);\n                }\n\n                // show how many variants we skipped due to filter not being narrow enough\n                if (m_NumFilteredVariants > maxFilteredLength)\n                {\n                    GUI.Label(rect, \"List of variants was cropped. Pick further keywords to narrow the selection.\", EditorStyles.miniLabel);\n                    rect.y += rect.height;\n                }\n            }\n            else\n            {\n                GUI.Label(rect, \"No variants with these keywords\");\n                rect.y += rect.height;\n            }\n\n            // Button to add them at the bottom of popup\n            rect.y = windowRect.height - kMargin - kSpaceHeight - EditorGUI.kSingleLineHeight;\n            rect.height = EditorGUI.kSingleLineHeight;\n            // Disable button if no variants selected\n            using (new EditorGUI.DisabledScope(m_SelectedVariants.Count == 0))\n            {\n                if (GUI.Button(rect, string.Format(\"Add {0} selected variants\", m_SelectedVariants.Count)))\n                {\n                    // Add the selected variants\n                    Undo.RecordObject(m_Data.collection, \"Add variant\");\n                    for (var i = 0; i < m_SelectedVariants.Count; ++i)\n                    {\n                        var index = m_SelectedVariants[i];\n                        var variant = new ShaderVariantCollection.ShaderVariant(m_Data.shader, (UnityEngine.Rendering.PassType)m_FilteredVariantTypes[index], m_FilteredVariantKeywords[index]);\n                        m_Data.collection.Add(variant);\n                    }\n                    // Close our popup\n                    Close();\n                    GUIUtility.ExitGUI();\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/ShadowCascadeSplitGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.Linq;\n\nnamespace UnityEditor\n{\n    /**\n     * Internal class for handling the drawing of ShadowCascade splits GUI and user interaction.\n     */\n    internal static class ShadowCascadeSplitGUI\n    {\n        private const int kSliderbarTopMargin = 2;\n        private const int kSliderbarHeight = 28;\n        private const int kSliderbarBottomMargin = 2;\n        private const int kPartitionHandleWidth = 2;\n        private const int kPartitionHandleExtraHitAreaWidth = 2;\n\n        private static readonly Color[] kCascadeColors =\n        {\n            new Color(0.5f, 0.5f, 0.6f, 1.0f),\n            new Color(0.5f, 0.6f, 0.5f, 1.0f),\n            new Color(0.6f, 0.6f, 0.5f, 1.0f),\n            new Color(0.6f, 0.5f, 0.5f, 1.0f),\n        };\n\n        // using a LODGroup skin\n        private static readonly GUIStyle s_CascadeSliderBG = \"LODSliderRange\";\n        private static readonly GUIStyle s_TextCenteredStyle =  new GUIStyle(EditorStyles.whiteMiniLabel)\n        {\n            alignment = TextAnchor.MiddleCenter\n        };\n\n        // Internal struct to bundle drag information\n        private class DragCache\n        {\n            public int      m_ActivePartition;          // the cascade partition that we are currently dragging/resizing\n            public float    m_NormalizedPartitionSize;  // the normalized size of the partition (0.0f < size < 1.0f)\n            public Vector2  m_LastCachedMousePosition;  // mouse position the last time we registered a drag or mouse down.\n\n            public DragCache(int activePartition, float normalizedPartitionSize, Vector2 currentMousePos)\n            {\n                m_ActivePartition = activePartition;\n                m_NormalizedPartitionSize = normalizedPartitionSize;\n                m_LastCachedMousePosition = currentMousePos;\n            }\n        }\n        private static DragCache  s_DragCache;\n\n        private static readonly int s_CascadeSliderId = \"s_CascadeSliderId\".GetHashCode();\n\n        private static SceneView s_RestoreSceneView;\n        private static SceneView.CameraMode s_OldSceneDrawMode;\n        private static bool s_OldSceneLightingMode;\n\n\n        /**\n         *  Static function to handle the GUI and User input related to the cascade slider.\n         *\n         *  @param  normalizedCascadePartition      The array of partition sizes in the range 0.0f - 1.0f; expects ONE entry if cascades = 2, and THREE if cascades=4\n         *                                          The last entry will be automatically determined by summing up the array, and doing 1.0f - sum\n         */\n        public static void HandleCascadeSliderGUI(ref float[] normalizedCascadePartitions)\n        {\n            GUILayout.Label(\"Cascade splits\");\n\n            // get the inspector width since we need it while drawing the partition rects.\n            // Only way currently is to reserve the block in the layout using GetRect(), and then immediately drawing the empty box\n            // to match the call to GetRect.\n            // From this point on, we move to non-layout based code.\n            var sliderRect = GUILayoutUtility.GetRect(GUIContent.none\n                , s_CascadeSliderBG\n                , GUILayout.Height(kSliderbarTopMargin + kSliderbarHeight + kSliderbarBottomMargin)\n                , GUILayout.ExpandWidth(true));\n            GUI.Box(sliderRect, GUIContent.none);\n\n            float currentX = sliderRect.x;\n            float cascadeBoxStartY = sliderRect.y + kSliderbarTopMargin;\n            float cascadeSliderWidth = sliderRect.width - (normalizedCascadePartitions.Length * kPartitionHandleWidth);\n            Color origTextColor = GUI.color;\n            Color origBackgroundColor = GUI.backgroundColor;\n            int colorIndex = -1;\n\n            // setup the array locally with the last partition\n            float[] adjustedCascadePartitions = new float[normalizedCascadePartitions.Length + 1];\n            Array.Copy(normalizedCascadePartitions, adjustedCascadePartitions, normalizedCascadePartitions.Length);\n            adjustedCascadePartitions[adjustedCascadePartitions.Length - 1] = 1.0f - normalizedCascadePartitions.Sum();\n\n\n            // check for user input on any of the partition handles\n            // this mechanism gets the current event in the queue... make sure that the mouse is over our control before consuming the event\n            int sliderControlId = GUIUtility.GetControlID(s_CascadeSliderId, FocusType.Passive);\n            Event currentEvent = Event.current;\n            int hotPartitionHandleIndex = -1; // the index of any partition handle that we are hovering over or dragging\n\n            // draw each cascade partition\n            for (int i = 0; i < adjustedCascadePartitions.Length; ++i)\n            {\n                float currentPartition = adjustedCascadePartitions[i];\n\n                colorIndex = (colorIndex + 1) % kCascadeColors.Length;\n                GUI.backgroundColor = kCascadeColors[colorIndex];\n                float boxLength = (cascadeSliderWidth * currentPartition);\n\n                // main cascade box\n                Rect partitionRect = new Rect(currentX, cascadeBoxStartY, boxLength, kSliderbarHeight);\n                GUI.Box(partitionRect, GUIContent.none, s_CascadeSliderBG);\n                currentX += boxLength;\n\n                // cascade box percentage text\n                GUI.color = Color.white;\n                Rect textRect = partitionRect;\n                var cascadeText = string.Format(\"{0}\\n{1:F1}%\", i, currentPartition * 100.0f);\n\n                GUI.Label(textRect, GUIContent.Temp(cascadeText, cascadeText), s_TextCenteredStyle);\n\n                // no need to draw the partition handle for last box\n                if (i == adjustedCascadePartitions.Length - 1)\n                    break;\n\n                // partition handle\n                GUI.backgroundColor = Color.black;\n                Rect handleRect = partitionRect;\n                handleRect.x = currentX;\n                handleRect.width = kPartitionHandleWidth;\n                GUI.Box(handleRect, GUIContent.none, s_CascadeSliderBG);\n                // we want a thin handle visually (since wide black bar looks bad), but a slightly larger\n                // hit area for easier manipulation\n                Rect handleHitRect = handleRect;\n                handleHitRect.xMin -= kPartitionHandleExtraHitAreaWidth;\n                handleHitRect.xMax += kPartitionHandleExtraHitAreaWidth;\n                if (handleHitRect.Contains(currentEvent.mousePosition))\n                    hotPartitionHandleIndex = i;\n\n                // add regions to slider where the cursor changes to Resize-Horizontal\n                if (s_DragCache == null)\n                {\n                    EditorGUIUtility.AddCursorRect(handleHitRect, MouseCursor.ResizeHorizontal, sliderControlId);\n                }\n\n                currentX += kPartitionHandleWidth;\n            }\n\n            GUI.color = origTextColor;\n            GUI.backgroundColor = origBackgroundColor;\n\n            EventType eventType = currentEvent.GetTypeForControl(sliderControlId);\n            switch (eventType)\n            {\n                case EventType.MouseDown:\n                    if (hotPartitionHandleIndex >= 0)\n                    {\n                        s_DragCache = new DragCache(hotPartitionHandleIndex, normalizedCascadePartitions[hotPartitionHandleIndex], currentEvent.mousePosition);\n                        if (GUIUtility.hotControl == 0)\n                            GUIUtility.hotControl = sliderControlId;\n                        currentEvent.Use();\n\n                        // Switch active scene view into shadow cascades visualization mode, once we start\n                        // tweaking cascade splits.\n                        if (s_RestoreSceneView == null)\n                        {\n                            s_RestoreSceneView = SceneView.lastActiveSceneView;\n                            if (s_RestoreSceneView != null)\n                            {\n                                s_OldSceneDrawMode = s_RestoreSceneView.cameraMode;\n                                s_OldSceneLightingMode = s_RestoreSceneView.sceneLighting;\n                                s_RestoreSceneView.cameraMode = SceneView.GetBuiltinCameraMode(DrawCameraMode.ShadowCascades);\n                            }\n                        }\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    // mouseUp event anywhere should release the hotcontrol (if it belongs to us), drags (if any)\n                    if (GUIUtility.hotControl == sliderControlId)\n                    {\n                        GUIUtility.hotControl = 0;\n                        currentEvent.Use();\n                    }\n                    s_DragCache = null;\n\n                    // Restore previous scene view drawing mode once we stop tweaking cascade splits.\n                    if (s_RestoreSceneView != null)\n                    {\n                        s_RestoreSceneView.cameraMode = s_OldSceneDrawMode;\n                        s_RestoreSceneView.sceneLighting = s_OldSceneLightingMode;\n                        s_RestoreSceneView = null;\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl != sliderControlId)\n                        break;\n\n                    // convert the mouse movement to normalized cascade width. Make sure that we are safe to apply the delta before using it.\n                    float delta = (currentEvent.mousePosition - s_DragCache.m_LastCachedMousePosition).x / cascadeSliderWidth;\n                    bool isLeftPartitionHappy = ((adjustedCascadePartitions[s_DragCache.m_ActivePartition] + delta) > 0.0f);\n                    bool isRightPartitionHappy = ((adjustedCascadePartitions[s_DragCache.m_ActivePartition + 1] - delta) > 0.0f);\n                    if (isLeftPartitionHappy && isRightPartitionHappy)\n                    {\n                        s_DragCache.m_NormalizedPartitionSize += delta;\n                        normalizedCascadePartitions[s_DragCache.m_ActivePartition] = s_DragCache.m_NormalizedPartitionSize;\n                        if (s_DragCache.m_ActivePartition < normalizedCascadePartitions.Length - 1)\n                            normalizedCascadePartitions[s_DragCache.m_ActivePartition + 1] -= delta;\n                        GUI.changed = true;\n                    }\n                    s_DragCache.m_LastCachedMousePosition = currentEvent.mousePosition;\n                    currentEvent.Use();\n                    break;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/SkinnedMeshRendererEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(SkinnedMeshRenderer))]\n    [CanEditMultipleObjects]\n    internal class SkinnedMeshRendererEditor : RendererEditorBase\n    {\n        class Styles\n        {\n            public static readonly GUIContent legacyClampBlendShapeWeightsInfo = EditorGUIUtility.TrTextContent(\"Note that BlendShape weight range is clamped. This can be disabled in Player Settings.\");\n            public static readonly GUIContent meshNotSupportingSkinningInfo = EditorGUIUtility.TrTextContent(\"The assigned mesh is missing either bone weights with bind pose, or blend shapes. This might cause the mesh not to render in the Player. If your mesh does not have either bone weights with bind pose, or blend shapes, use a Mesh Renderer instead of Skinned Mesh Renderer.\");\n            public static readonly GUIContent bounds = EditorGUIUtility.TrTextContent(\"Bounds\", \"The bounding box that encapsulates the mesh.\");\n            public static readonly GUIContent quality = EditorGUIUtility.TrTextContent(\"Quality\", \"Number of bones to use per vertex during skinning.\");\n            public static readonly GUIContent updateWhenOffscreen = EditorGUIUtility.TrTextContent(\"Update When Offscreen\", \"If an accurate bounding volume representation should be calculated every frame. \");\n            public static readonly GUIContent mesh = EditorGUIUtility.TrTextContent(\"Mesh\", \"The mesh used by this renderer.\");\n            public static readonly GUIContent rootBone = EditorGUIUtility.TrTextContent(\"Root Bone\", \"Transform with which the bounds move, and the space in which skinning is computed.\");\n        }\n\n        private SerializedProperty m_AABB;\n        private SerializedProperty m_DirtyAABB;\n        private SerializedProperty m_BlendShapeWeights;\n        private SerializedProperty m_Quality;\n        private SerializedProperty m_UpdateWhenOffscreen;\n        private SerializedProperty m_Mesh;\n        private SerializedProperty m_RootBone;\n\n        private BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle();\n\n        public override void OnEnable()\n        {\n            base.OnEnable();\n\n            m_AABB = serializedObject.FindProperty(\"m_AABB\");\n            m_DirtyAABB = serializedObject.FindProperty(\"m_DirtyAABB\");\n            m_BlendShapeWeights = serializedObject.FindProperty(\"m_BlendShapeWeights\");\n            m_Quality = serializedObject.FindProperty(\"m_Quality\");\n            m_UpdateWhenOffscreen = serializedObject.FindProperty(\"m_UpdateWhenOffscreen\");\n            m_Mesh = serializedObject.FindProperty(\"m_Mesh\");\n            m_RootBone = serializedObject.FindProperty(\"m_RootBone\");\n\n            m_BoundsHandle.SetColor(Handles.s_BoundingBoxHandleColor);\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            EditMode.DoEditModeInspectorModeButton(\n                EditMode.SceneViewEditMode.Collider,\n                \"Edit Bounds\",\n                PrimitiveBoundsHandle.editModeButton,\n                this\n            );\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_AABB, Styles.bounds);\n            // If we set m_AABB then we need to set m_DirtyAABB to false\n            if (EditorGUI.EndChangeCheck())\n                m_DirtyAABB.boolValue = false;\n\n            OnMeshUI();\n\n            OnBlendShapeUI();\n\n            EditorGUILayout.PropertyField(m_Quality, Styles.quality);\n            EditorGUILayout.PropertyField(m_UpdateWhenOffscreen, Styles.updateWhenOffscreen);\n\n            EditorGUILayout.PropertyField(m_RootBone, Styles.rootBone);\n\n            DrawMaterials();\n            LightingSettingsGUI(false);\n            RayTracingSettingsGUI();\n\n            SkinnedMeshRenderer renderer = (SkinnedMeshRenderer)target;\n            if (renderer != null && renderer.sharedMesh != null)\n            {               \n                if (renderer.sharedMesh.isLodSelectionActive)\n                {\n                    MeshLodSettingsGUI(renderer.sharedMesh.lodCount);\n                }\n            }\n\n            OtherSettingsGUI(false, true);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        internal override Bounds GetWorldBoundsOfTarget(Object targetObject)\n        {\n            return ((SkinnedMeshRenderer)targetObject).bounds;\n        }\n\n        public void OnMeshUI()\n        {\n            SkinnedMeshRenderer renderer = (SkinnedMeshRenderer)target;\n\n            EditorGUILayout.PropertyField(m_Mesh, Styles.mesh);\n\n            if (renderer.sharedMesh != null)\n            {\n                bool haveClothComponent = renderer.gameObject.GetComponent<Cloth>() != null;\n\n                if (!haveClothComponent && renderer.sharedMesh.blendShapeCount == 0 && (renderer.sharedMesh.boneWeights.Length == 0 || renderer.sharedMesh.bindposes.Length == 0))\n                {\n                    EditorGUILayout.HelpBox(Styles.meshNotSupportingSkinningInfo.text, MessageType.Error);\n                }\n            }\n        }\n\n        public void OnBlendShapeUI()\n        {\n            SkinnedMeshRenderer renderer = (SkinnedMeshRenderer)target;\n            int blendShapeCount = renderer.sharedMesh == null ? 0 : renderer.sharedMesh.blendShapeCount;\n            if (blendShapeCount == 0)\n                return;\n\n            GUIContent content = new GUIContent();\n            content.text = \"BlendShapes\";\n\n            EditorGUILayout.PropertyField(m_BlendShapeWeights, content, false);\n            if (!m_BlendShapeWeights.isExpanded)\n                return;\n\n            EditorGUI.indentLevel++;\n\n            if (PlayerSettings.legacyClampBlendShapeWeights)\n                EditorGUILayout.HelpBox(Styles.legacyClampBlendShapeWeightsInfo.text, MessageType.Info);\n\n            Mesh m = renderer.sharedMesh;\n\n            int arraySize = m_BlendShapeWeights.arraySize;\n            for (int i = 0; i < blendShapeCount; i++)\n            {\n                content.text = m.GetBlendShapeName(i);\n\n                // Calculate the min and max values for the slider from the frame blendshape weights\n                float sliderMin = 0f, sliderMax = 0f;\n\n                int frameCount = m.GetBlendShapeFrameCount(i);\n                for (int j = 0; j < frameCount; j++)\n                {\n                    float frameWeight = m.GetBlendShapeFrameWeight(i, j);\n                    sliderMin = Mathf.Min(frameWeight, sliderMin);\n                    sliderMax = Mathf.Max(frameWeight, sliderMax);\n                }\n\n                // The SkinnedMeshRenderer blendshape weights array size can be out of sync with the size defined in the mesh\n                // (default values in that case are 0)\n                // The desired behaviour is to resize the blendshape array on edit.\n\n                // Default path when the blend shape array size is big enough.\n                if (i < arraySize)\n                    EditorGUILayout.Slider(m_BlendShapeWeights.GetArrayElementAtIndex(i), sliderMin, sliderMax, float.MinValue, float.MaxValue, content);\n                // Fall back to 0 based editing &\n                else\n                {\n                    EditorGUI.BeginChangeCheck();\n\n                    float value = EditorGUILayout.Slider(content, 0f, sliderMin, sliderMax, float.MinValue, float.MaxValue);\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        m_BlendShapeWeights.arraySize = blendShapeCount;\n                        arraySize = blendShapeCount;\n                        m_BlendShapeWeights.GetArrayElementAtIndex(i).floatValue = value;\n                    }\n                }\n            }\n\n            EditorGUI.indentLevel--;\n        }\n\n        public void OnSceneGUI()\n        {\n            if (!target)\n                return;\n            SkinnedMeshRenderer renderer = (SkinnedMeshRenderer)target;\n\n            if (renderer.updateWhenOffscreen)\n            {\n                Bounds bounds = renderer.bounds;\n                Vector3 center = bounds.center;\n                Vector3 size = bounds.size;\n\n                Handles.DrawWireCube(center, size);\n            }\n            else\n            {\n                using (new Handles.DrawingScope(renderer.actualRootBone.localToWorldMatrix))\n                {\n                    Bounds bounds = renderer.localBounds;\n                    m_BoundsHandle.center = bounds.center;\n                    m_BoundsHandle.size = bounds.size;\n\n                    // only display interactive handles if edit mode is active\n                    m_BoundsHandle.handleColor = EditMode.editMode == EditMode.SceneViewEditMode.Collider && EditMode.IsOwner(this) ?\n                        m_BoundsHandle.wireframeColor : Color.clear;\n\n                    EditorGUI.BeginChangeCheck();\n                    m_BoundsHandle.DrawHandle();\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        Undo.RecordObject(renderer, \"Resize Bounds\");\n                        renderer.localBounds = new Bounds(m_BoundsHandle.center, m_BoundsHandle.size);\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/SkyboxPanoramicShaderGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditor.AnimatedValues;\nusing UnityEditorInternal;\nusing UnityEditor.Build;\n\nnamespace UnityEditor\n{\n    internal class SkyboxPanoramicShaderGUI : ShaderGUI\n    {\n        class Styles\n        {\n            public static GUIContent Get3DLayoutContent(MaterialProperty property)\n            {\n                if (s_Stereo3DLayoutContent == null)\n                    s_Stereo3DLayoutContent = EditorGUIUtility.TrTextContent(\n                        property.displayName,\n                        \"Layout of 3D content in the source. Only meaningful when stereoscopic render is used.\");\n\n                return s_Stereo3DLayoutContent;\n            }\n\n            private static GUIContent s_Stereo3DLayoutContent;\n        }\n\n        readonly AnimBool m_ShowLatLongLayout = new AnimBool();\n        readonly AnimBool m_ShowMirrorOnBack = new AnimBool();\n\n        bool m_Initialized = false;\n\n        public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)\n        {\n            if (!m_Initialized)\n            {\n                m_ShowLatLongLayout.valueChanged.AddListener(materialEditor.Repaint);\n                m_ShowMirrorOnBack.valueChanged.AddListener(materialEditor.Repaint);\n                m_Initialized = true;\n            }\n\n            // Allow the default implementation to set widths for consistency for common properties.\n            float lw = EditorGUIUtility.labelWidth;\n            materialEditor.SetDefaultGUIWidths();\n            ShowProp(materialEditor, FindProperty(\"_Tint\", props));\n            ShowProp(materialEditor, FindProperty(\"_Exposure\", props));\n            ShowProp(materialEditor, FindProperty(\"_Rotation\", props));\n            ShowProp(materialEditor, FindProperty(\"_MainTex\", props));\n            EditorGUIUtility.labelWidth = lw;\n\n            m_ShowLatLongLayout.target = ShowProp(materialEditor, FindProperty(\"_Mapping\", props)) == 1;\n            if (EditorGUILayout.BeginFadeGroup(m_ShowLatLongLayout.faded))\n            {\n                m_ShowMirrorOnBack.target = ShowProp(materialEditor, FindProperty(\"_ImageType\", props)) == 1;\n                if (EditorGUILayout.BeginFadeGroup(m_ShowMirrorOnBack.faded))\n                {\n                    EditorGUI.indentLevel++;\n                    ShowProp(materialEditor, FindProperty(\"_MirrorOnBack\", props));\n                    EditorGUI.indentLevel--;\n                }\n                EditorGUILayout.EndFadeGroup();\n                ShowProp(materialEditor, FindProperty(\"_Layout\", props), Styles.Get3DLayoutContent);\n            }\n            EditorGUILayout.EndFadeGroup();\n\n            // Let the default implementation add the extra shader properties at the bottom.\n            materialEditor.PropertiesDefaultGUI(new MaterialProperty[0]);\n        }\n\n        private delegate GUIContent ContentGenerator(MaterialProperty property);\n        private float ShowProp(\n            MaterialEditor materialEditor, MaterialProperty prop,\n            ContentGenerator contentGenerator = null)\n        {\n            if (contentGenerator != null)\n                materialEditor.ShaderProperty(prop, contentGenerator(prop));\n            else\n                materialEditor.ShaderProperty(prop, prop.displayName);\n            return prop.floatValue;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/SkyboxProceduralShaderGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing ShaderPropertyType = UnityEngine.Rendering.ShaderPropertyType;\nusing ShaderPropertyFlags = UnityEngine.Rendering.ShaderPropertyFlags;\n\nnamespace UnityEditor\n{\n    internal class SkyboxProceduralShaderGUI : ShaderGUI\n    {\n        private enum SunDiskMode\n        {\n            None,\n            Simple,\n            HighQuality\n        }\n\n        public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)\n        {\n            MaterialProperty sunDiskModeProp = FindProperty(\"_SunDisk\", props);\n            SunDiskMode sunDiskMode = (SunDiskMode)sunDiskModeProp.floatValue;\n\n            float labelWidth = EditorGUIUtility.labelWidth;\n\n            for (var i = 0; i < props.Length; i++)\n            {\n                // dropdowns should have full width\n                if (props[i].propertyType == ShaderPropertyType.Float)\n                    EditorGUIUtility.labelWidth = labelWidth;\n                else\n                    materialEditor.SetDefaultGUIWidths();\n\n                if ((props[i].propertyFlags & ShaderPropertyFlags.HideInInspector) != 0)\n                    continue;\n\n                //_SunSizeConvergence is only used with the HighQuality sun disk.\n                if ((props[i].name == \"_SunSizeConvergence\") && (sunDiskMode != SunDiskMode.HighQuality))\n                    continue;\n\n                float h = materialEditor.GetPropertyHeight(props[i], props[i].displayName);\n                Rect r = EditorGUILayout.GetControlRect(true, h, EditorStyles.layerMaskField);\n\n                materialEditor.ShaderProperty(r, props[i], props[i].displayName);\n            }\n        }\n    }\n} // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/Inspector/SortingGroupEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(UnityEngine.Rendering.SortingGroup))]\n    [CanEditMultipleObjects]\n    internal class SortingGroupEditor : Editor\n    {\n        private static class Styles\n        {\n            public static GUIContent m_SortAtRootStyle = EditorGUIUtility.TrTextContent(\"Sort At Root\"\n                , \"Ignores all parent Sorting Groups and sorts at the root level against other Sorting Groups and Renderers\");\n        }\n\n\n        private SerializedProperty m_SortingOrder;\n        private SerializedProperty m_SortingLayerID;\n        private SerializedProperty m_SortAtRoot;\n\n        public virtual void OnEnable()\n        {\n            alwaysAllowExpansion = true;\n            m_SortingOrder = serializedObject.FindProperty(\"m_SortingOrder\");\n            m_SortingLayerID = serializedObject.FindProperty(\"m_SortingLayerID\");\n            m_SortAtRoot = serializedObject.FindProperty(\"m_SortAtRoot\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n            SortingLayerEditorUtility.RenderSortingLayerFields(m_SortingOrder, m_SortingLayerID);\n            EditorGUILayout.PropertyField(m_SortAtRoot, Styles.m_SortAtRootStyle);\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/SortingLayerEditorUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditorInternal;\nusing UnityEngine;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class SortingLayerEditorUtility\n    {\n        private static class Styles\n        {\n            private static GUIStyle m_BoldPopupStyle;\n\n            public static GUIContent m_SortingLayerStyle = EditorGUIUtility.TrTextContent(\"Sorting Layer\", \"Name of the Renderer's sorting layer\");\n            public static GUIContent m_SortingOrderStyle = EditorGUIUtility.TrTextContent(\"Order in Layer\", \"Renderer's order within a sorting layer\");\n\n            public static GUIStyle boldPopupStyle\n            {\n                get\n                {\n                    if (m_BoldPopupStyle == null)\n                    {\n                        m_BoldPopupStyle = new GUIStyle(EditorStyles.popup);\n                        m_BoldPopupStyle.fontStyle = FontStyle.Bold;\n                    }\n                    return m_BoldPopupStyle;\n                }\n            }\n        }\n\n        internal static bool HasPrefabOverride(SerializedProperty property)\n        {\n            return property != null && property.serializedObject.targetObjectsCount == 1 && property.isInstantiatedPrefab && property.prefabOverride;\n        }\n\n        public static void RenderSortingLayerFields(SerializedProperty sortingOrder, SerializedProperty sortingLayer)\n        {\n            var hasPrefabOverride = HasPrefabOverride(sortingLayer);\n            EditorGUILayout.SortingLayerField(Styles.m_SortingLayerStyle, sortingLayer, hasPrefabOverride ? Styles.boldPopupStyle : EditorStyles.popup, hasPrefabOverride ? EditorStyles.boldLabel : EditorStyles.label);\n            EditorGUILayout.PropertyField(sortingOrder, Styles.m_SortingOrderStyle);\n        }\n\n        public static void RenderSortingLayerFields(Rect r, SerializedProperty sortingOrder, SerializedProperty sortingLayer)\n        {\n            var hasPrefabOverride = HasPrefabOverride(sortingLayer);\n            EditorGUI.SortingLayerField(r, Styles.m_SortingLayerStyle, sortingLayer, hasPrefabOverride ? Styles.boldPopupStyle : EditorStyles.popup, hasPrefabOverride ? EditorStyles.boldLabel : EditorStyles.label);\n            r.y += EditorGUIUtility.singleLineHeight;\n            EditorGUI.PropertyField(r, sortingOrder, Styles.m_SortingOrderStyle);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/SpeedTree8ShaderGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.Linq;\n\nnamespace UnityEditor\n{\n    internal class SpeedTree8ShaderGUI : ShaderGUI\n    {\n        private static class Styles\n        {\n            public static GUIContent colorText = EditorGUIUtility.TrTextContent(\"Color\", \"Color (RGB) and Opacity (A)\");\n            public static GUIContent normalMapText = EditorGUIUtility.TrTextContent(\"Normal\", \"Normal (RGB)\");\n            public static GUIContent extraMapText = EditorGUIUtility.TrTextContent(\"Extra\", \"Smoothness (R), Metallic (G), AO (B)\");\n            public static GUIContent subsurfaceMapText = EditorGUIUtility.TrTextContent(\"Subsurface\", \"Subsurface (RGB)\");\n\n            public static GUIContent smoothnessText = EditorGUIUtility.TrTextContent(\"Smoothness\", \"Smoothness value\");\n            public static GUIContent metallicText = EditorGUIUtility.TrTextContent(\"Metallic\", \"Metallic value\");\n\n            public static GUIContent twoSidedText = EditorGUIUtility.TrTextContent(\"Two-Sided\", \"Set this material to render as two-sided\");\n            public static GUIContent windQualityText = EditorGUIUtility.TrTextContent(\"Wind Quality\", \"Wind quality setting\");\n            public static GUIContent hueVariationText = EditorGUIUtility.TrTextContent(\"Hue Variation\", \"Hue variation Color (RGB) and Amount (A)\");\n            public static GUIContent normalMappingText = EditorGUIUtility.TrTextContent(\"Normal Map\", \"Enable normal mapping\");\n            public static GUIContent subsurfaceText = EditorGUIUtility.TrTextContent(\"Subsurface\", \"Enable subsurface scattering\");\n            public static GUIContent subsurfaceIndirectText = EditorGUIUtility.TrTextContent(\"Indirect Subsurface\", \"Scalar on subsurface from indirect light\");\n\n            public static GUIContent billboardText = EditorGUIUtility.TrTextContent(\"Billboard\", \"Enable billboard features (crossfading, etc.)\");\n            public static GUIContent billboardShadowFadeText = EditorGUIUtility.TrTextContent(\"Shadow Fade\", \"Fade shadow effect on billboards\");\n\n            public static GUIContent primaryMapsText = EditorGUIUtility.TrTextContent(\"Maps\");\n            public static GUIContent optionsText = EditorGUIUtility.TrTextContent(\"Options\");\n            public static GUIContent advancedText = EditorGUIUtility.TrTextContent(\"Advanced Options\");\n        }\n\n        public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)\n        {\n            // Use default labelWidth\n            EditorGUIUtility.labelWidth = 0.0f;\n\n            {\n                GUILayout.Label(Styles.primaryMapsText, EditorStyles.boldLabel);\n\n                // color\n                var colorTexProp = ShaderGUI.FindProperty(\"_MainTex\", properties);\n                var colorProp = ShaderGUI.FindProperty(\"_Color\", properties);\n                materialEditor.TexturePropertySingleLine(Styles.colorText, colorTexProp, null, colorProp);\n\n                // normal\n                var normalTexProp = ShaderGUI.FindProperty(\"_BumpMap\", properties);\n                materialEditor.TexturePropertySingleLine(Styles.normalMapText, normalTexProp);\n\n                // extra\n                var extraTexProp = ShaderGUI.FindProperty(\"_ExtraTex\", properties);\n                materialEditor.TexturePropertySingleLine(Styles.extraMapText, extraTexProp, null);\n                if (extraTexProp.textureValue == null)\n                {\n                    var glossProp = ShaderGUI.FindProperty(\"_Glossiness\", properties);\n                    materialEditor.ShaderProperty(glossProp, Styles.smoothnessText, 2);\n                    var metallicProp = ShaderGUI.FindProperty(\"_Metallic\", properties);\n                    materialEditor.ShaderProperty(metallicProp, Styles.metallicText, 2);\n                }\n\n                // subsurface\n                var ssTexProp = ShaderGUI.FindProperty(\"_SubsurfaceTex\", properties);\n                var ssProp = ShaderGUI.FindProperty(\"_SubsurfaceColor\", properties);\n                materialEditor.TexturePropertySingleLine(Styles.subsurfaceMapText, ssTexProp, null, ssProp);\n\n                // other options\n                EditorGUILayout.Space();\n                GUILayout.Label(Styles.optionsText, EditorStyles.boldLabel);\n\n                MakeAlignedProperty(FindProperty(\"_TwoSided\", properties), Styles.twoSidedText, materialEditor, true);\n                MakeAlignedProperty(FindProperty(\"_WindQuality\", properties), Styles.windQualityText, materialEditor, true);\n                MakeCheckedProperty(FindProperty(\"_HueVariationKwToggle\", properties), FindProperty(\"_HueVariationColor\", properties), Styles.hueVariationText, materialEditor);\n                MakeAlignedProperty(FindProperty(\"_NormalMapKwToggle\", properties), Styles.normalMappingText, materialEditor, true);\n\n                // subsurface\n                var subsurfaceToggle = FindProperty(\"_SubsurfaceKwToggle\", properties);\n                MakeAlignedProperty(subsurfaceToggle, Styles.subsurfaceText, materialEditor, true);\n                if (subsurfaceToggle.floatValue > 0.0f)\n                {\n                    var sssIndirectProp = ShaderGUI.FindProperty(\"_SubsurfaceIndirect\", properties);\n                    materialEditor.ShaderProperty(sssIndirectProp, Styles.subsurfaceIndirectText, 2);\n                }\n\n                // billboard\n                var billboardToggle = FindProperty(\"_BillboardKwToggle\", properties);\n                MakeAlignedProperty(billboardToggle, Styles.billboardText, materialEditor, true);\n                if (billboardToggle.floatValue > 0.0f)\n                {\n                    var prop = ShaderGUI.FindProperty(\"_BillboardShadowFade\", properties);\n                    materialEditor.ShaderProperty(prop, Styles.billboardShadowFadeText, 2);\n                }\n            }\n\n            EditorGUILayout.Space();\n            GUILayout.Label(Styles.advancedText, EditorStyles.boldLabel);\n            materialEditor.EnableInstancingField();\n            materialEditor.DoubleSidedGIField();\n        }\n\n        static void MakeAlignedProperty(MaterialProperty prop, GUIContent text, MaterialEditor materialEditor, bool doubleWide = false)\n        {\n            Rect r = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight + 2.0f);\n            r.width = EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth * (doubleWide ? 2.0f : 1.0f);\n\n            materialEditor.ShaderProperty(r, prop, text);\n        }\n\n        static void MakeCheckedProperty(MaterialProperty keywordToggleProp, MaterialProperty prop, GUIContent text, MaterialEditor materialEditor, bool doubleWide = false)\n        {\n            Rect r = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight + 2.0f);\n            r.width = EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth / 2;\n\n            materialEditor.ShaderProperty(r, keywordToggleProp, text);\n\n            using (new EditorGUI.DisabledScope(keywordToggleProp.floatValue == 0.0f))\n            {\n                r.width = EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth * (doubleWide ? 2.0f : 1.0f);\n                r.x += EditorGUIUtility.fieldWidth / 2;\n\n                materialEditor.ShaderProperty(r, prop, \" \");\n            }\n        }\n\n        public override void ValidateMaterial(Material material)\n        {\n            SetKeyword(material, \"EFFECT_EXTRA_TEX\", material.GetTexture(\"_ExtraTex\"));\n        }\n\n        static void SetKeyword(Material m, string keyword, bool state)\n        {\n            if (state)\n                m.EnableKeyword(keyword);\n            else\n                m.DisableKeyword(keyword);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/SpeedTree9ShaderGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class SpeedTree9ShaderGUI : ShaderGUI\n    {\n        private static class Styles\n        {\n            public static GUIContent colorText = EditorGUIUtility.TrTextContent(\"Color\", \"Color (RGB) and Opacity (A)\");\n            public static GUIContent normalMapText = EditorGUIUtility.TrTextContent(\"Normal\", \"Normal (RGB)\");\n            public static GUIContent extraMapText = EditorGUIUtility.TrTextContent(\"Extra\", \"Smoothness (R), Metallic (G), AO (B)\");\n            public static GUIContent subsurfaceMapText = EditorGUIUtility.TrTextContent(\"Subsurface\", \"Subsurface (RGB)\");\n\n            public static GUIContent smoothnessText = EditorGUIUtility.TrTextContent(\"Smoothness\", \"Smoothness value\");\n            public static GUIContent metallicText = EditorGUIUtility.TrTextContent(\"Metallic\", \"Metallic value\");\n\n            public static GUIContent twoSidedText = EditorGUIUtility.TrTextContent(\"Two-Sided\", \"Set this material to render as two-sided\");\n            public static GUIContent hueVariationText = EditorGUIUtility.TrTextContent(\"Hue Variation\", \"Hue variation Color (RGB) and Amount (A)\");\n            public static GUIContent normalMappingText = EditorGUIUtility.TrTextContent(\"Normal Map\", \"Enable normal mapping\");\n            public static GUIContent subsurfaceText = EditorGUIUtility.TrTextContent(\"Subsurface\", \"Enable subsurface scattering\");\n            public static GUIContent subsurfaceIndirectText = EditorGUIUtility.TrTextContent(\"Indirect Subsurface\", \"Scalar on subsurface from indirect light\");\n\n            public static GUIContent windSharedText = EditorGUIUtility.TrTextContent(\"Shared Motion\", \"Wind quality setting\");\n            public static GUIContent windBranch1Text = EditorGUIUtility.TrTextContent(\"Branch1 Motion\", \"Wind quality setting\");\n            public static GUIContent windBranch2Text = EditorGUIUtility.TrTextContent(\"Branch2 Motion\", \"Wind quality setting\");\n            public static GUIContent windRippleText = EditorGUIUtility.TrTextContent(\"Ripple Motion\", \"Wind quality setting\");\n            public static GUIContent windShimmerText = EditorGUIUtility.TrTextContent(\"Shimmer Motion\", \"Wind quality setting\");\n\n            public static GUIContent billboardText = EditorGUIUtility.TrTextContent(\"Billboard\", \"Enable billboard features (crossfading, etc.)\");\n            public static GUIContent billboardShadowFadeText = EditorGUIUtility.TrTextContent(\"Shadow Fade\", \"Fade shadow effect on billboards\");\n\n            public static GUIContent primaryMapsText = EditorGUIUtility.TrTextContent(\"Maps\");\n            public static GUIContent optionsText = EditorGUIUtility.TrTextContent(\"Options\");\n            public static GUIContent advancedText = EditorGUIUtility.TrTextContent(\"Advanced Options\");\n        }\n\n        public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)\n        {\n            // Use default labelWidth\n            EditorGUIUtility.labelWidth = 0.0f;\n\n            {\n                GUILayout.Label(Styles.primaryMapsText, EditorStyles.boldLabel);\n\n                // color\n                var colorTexProp = ShaderGUI.FindProperty(\"_MainTex\", properties);\n                var colorProp = ShaderGUI.FindProperty(\"_ColorTint\", properties);\n                materialEditor.TexturePropertySingleLine(Styles.colorText, colorTexProp, null, colorProp);\n\n                // normal\n                var normalTexProp = ShaderGUI.FindProperty(\"_NormalMap\", properties);\n                materialEditor.TexturePropertySingleLine(Styles.normalMapText, normalTexProp);\n\n                // extra\n                var extraTexProp = ShaderGUI.FindProperty(\"_ExtraTex\", properties);\n                materialEditor.TexturePropertySingleLine(Styles.extraMapText, extraTexProp, null);\n                if (extraTexProp.textureValue == null)\n                {\n                    var glossProp = ShaderGUI.FindProperty(\"_Glossiness\", properties);\n                    materialEditor.ShaderProperty(glossProp, Styles.smoothnessText, 2);\n                    var metallicProp = ShaderGUI.FindProperty(\"_Metallic\", properties);\n                    materialEditor.ShaderProperty(metallicProp, Styles.metallicText, 2);\n                }\n\n                // subsurface\n                var ssTexProp = ShaderGUI.FindProperty(\"_SubsurfaceTex\", properties);\n                var ssProp = ShaderGUI.FindProperty(\"_SubsurfaceColor\", properties);\n                materialEditor.TexturePropertySingleLine(Styles.subsurfaceMapText, ssTexProp, null, ssProp);\n\n                // other options\n                EditorGUILayout.Space();\n                GUILayout.Label(Styles.optionsText, EditorStyles.boldLabel);\n\n                MakeAlignedProperty(FindProperty(\"_TwoSided\", properties), Styles.twoSidedText, materialEditor, true);\n                MakeCheckedProperty(FindProperty(\"_HueVariationKwToggle\", properties), FindProperty(\"_HueVariationColor\", properties), Styles.hueVariationText, materialEditor);\n                MakeAlignedProperty(FindProperty(\"_NormalMapKwToggle\", properties), Styles.normalMappingText, materialEditor, true);\n\n                // subsurface\n                var subsurfaceToggle = FindProperty(\"_SubsurfaceKwToggle\", properties);\n                MakeAlignedProperty(subsurfaceToggle, Styles.subsurfaceText, materialEditor, true);\n                if (subsurfaceToggle.floatValue > 0.0f)\n                {\n                    var sssIndirectProp = ShaderGUI.FindProperty(\"_SubsurfaceIndirect\", properties);\n                    materialEditor.ShaderProperty(sssIndirectProp, Styles.subsurfaceIndirectText, 2);\n                }\n\n                // billboard\n                var billboardToggle = FindProperty(\"_BillboardKwToggle\", properties);\n                bool hasBillboard = billboardToggle.floatValue > 0.0f;\n                MakeAlignedProperty(billboardToggle, Styles.billboardText, materialEditor, true);\n                if (hasBillboard)\n                {\n                    var prop = ShaderGUI.FindProperty(\"_BillboardShadowFade\", properties);\n                    materialEditor.ShaderProperty(prop, Styles.billboardShadowFadeText, 2);\n                }\n\n                // leaf facing\n                MaterialProperty propLeafFacing = FindProperty(\"_LeafFacingKwToggle\", properties);\n                MakeAlignedProperty(propLeafFacing, EditorGUIUtility.TrTextContent(\"Leaf Facing\", \"Toggles the effect that renders the leaves facing the camera.\"), materialEditor, true);\n\n                // wind\n                MaterialProperty propWindShared  = FindProperty(\"_WIND_SHARED\", properties);\n                MaterialProperty propWindBranch1 = !hasBillboard ? FindProperty(\"_WIND_BRANCH1\", properties) : null;\n                MaterialProperty propWindBranch2 = !hasBillboard ? FindProperty(\"_WIND_BRANCH2\", properties) : null;\n                MaterialProperty propWindRipple  = !hasBillboard ? FindProperty(\"_WIND_RIPPLE\" , properties) : null;\n                MaterialProperty propWindShimmer = !hasBillboard ? FindProperty(\"_WIND_SHIMMER\", properties) : null;\n                const bool DOUBLE_WIDE = true;\n\n                EditorGUILayout.Space();\n                EditorGUILayout.Space();\n                EditorGUILayout.LabelField(\"Wind\", EditorStyles.boldLabel);\n                MakeAlignedProperty(propWindShared, Styles.windSharedText, materialEditor, DOUBLE_WIDE);\n                if (!hasBillboard) // 3D-only wind props\n                {\n                    MakeAlignedProperty(propWindBranch1, Styles.windBranch1Text, materialEditor, DOUBLE_WIDE);\n                    MakeAlignedProperty(propWindBranch2, Styles.windBranch2Text, materialEditor, DOUBLE_WIDE);\n                    MakeAlignedProperty(propWindRipple, Styles.windRippleText, materialEditor, DOUBLE_WIDE);\n                    if (propWindRipple.floatValue > 0.0f)\n                    {\n                        MakeAlignedProperty(propWindShimmer, Styles.windShimmerText, materialEditor, DOUBLE_WIDE);\n                    }\n                }\n            }\n\n            EditorGUILayout.Space();\n            GUILayout.Label(Styles.advancedText, EditorStyles.boldLabel);\n            materialEditor.EnableInstancingField();\n            materialEditor.DoubleSidedGIField();\n        }\n\n        static void MakeAlignedProperty(MaterialProperty prop, GUIContent text, MaterialEditor materialEditor, bool doubleWide = false)\n        {\n            Rect r = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight + 2.0f);\n            r.width = EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth * (doubleWide ? 2.0f : 1.0f);\n\n            materialEditor.ShaderProperty(r, prop, text);\n        }\n\n        static void MakeCheckedProperty(MaterialProperty keywordToggleProp, MaterialProperty prop, GUIContent text, MaterialEditor materialEditor, bool doubleWide = false)\n        {\n            Rect r = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight + 2.0f);\n            r.width = EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth / 2;\n\n            materialEditor.ShaderProperty(r, keywordToggleProp, text);\n\n            using (new EditorGUI.DisabledScope(keywordToggleProp.floatValue == 0.0f))\n            {\n                r.width = EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth * (doubleWide ? 2.0f : 1.0f);\n                r.x += EditorGUIUtility.fieldWidth / 2;\n\n                materialEditor.ShaderProperty(r, prop, \" \");\n            }\n        }\n\n        public override void ValidateMaterial(Material material)\n        {\n            SetKeyword(material, \"EFFECT_EXTRA_TEX\", material.GetTexture(\"_ExtraTex\"));\n        }\n\n        static void SetKeyword(Material m, string keyword, bool state)\n        {\n            if (state)\n                m.EnableKeyword(keyword);\n            else\n                m.DisableKeyword(keyword);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/SpeedTreeMaterialInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing ShaderPropertyFlags = UnityEngine.Rendering.ShaderPropertyFlags;\n\nnamespace UnityEditor\n{\n    [CanEditMultipleObjects]\n    internal class SpeedTreeMaterialInspector : MaterialEditor\n    {\n        private enum SpeedTreeGeometryType\n        {\n            Branch = 0,\n            BranchDetail,\n            Frond,\n            Leaf,\n            Mesh // mapped with GEOM_TYPE_MESH in SpeedTreeImporter\n        }\n\n        private string[] speedTreeGeometryTypeString =\n        {\n            \"GEOM_TYPE_BRANCH\",\n            \"GEOM_TYPE_BRANCH_DETAIL\",\n            \"GEOM_TYPE_FROND\",\n            \"GEOM_TYPE_LEAF\",\n            \"GEOM_TYPE_MESH\"\n        };\n\n        private bool ShouldEnableAlphaTest(SpeedTreeGeometryType geomType)\n        {\n            return geomType == SpeedTreeGeometryType.Frond\n                || geomType == SpeedTreeGeometryType.Leaf;\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n            var theShader = serializedObject.FindProperty(\"m_Shader\");\n\n            // if we are not visible... return\n            if (!isVisible || theShader.hasMultipleDifferentValues || theShader.objectReferenceValue == null)\n                return;\n\n            List<MaterialProperty> props = new List<MaterialProperty>(GetMaterialProperties(targets));\n\n            SetDefaultGUIWidths();\n\n            // Geometry type choice\n            //---------------------------------------------------------------\n            var geomTypes = new SpeedTreeGeometryType[targets.Length];\n            for (int i = 0; i < targets.Length; ++i)\n            {\n                geomTypes[i] = SpeedTreeGeometryType.Branch;\n                for (int j = 0; j < speedTreeGeometryTypeString.Length; ++j)\n                {\n                    if (((Material)targets[i]).shaderKeywords.Contains(speedTreeGeometryTypeString[j]))\n                    {\n                        geomTypes[i] = (SpeedTreeGeometryType)j;\n                        break;\n                    }\n                }\n            }\n            EditorGUI.showMixedValue = geomTypes.Distinct().Count() > 1;\n            EditorGUI.BeginChangeCheck();\n            var setGeomType = (SpeedTreeGeometryType)EditorGUILayout.EnumPopup(\"Geometry Type\", geomTypes[0]);\n            if (EditorGUI.EndChangeCheck())\n            {\n                bool shouldEnableAlphaTest = ShouldEnableAlphaTest(setGeomType);\n                UnityEngine.Rendering.CullMode cullMode = shouldEnableAlphaTest ? UnityEngine.Rendering.CullMode.Off : UnityEngine.Rendering.CullMode.Back;\n\n                foreach (var m in targets.Cast<Material>())\n                {\n                    if (shouldEnableAlphaTest)\n                        m.SetOverrideTag(\"RenderType\", \"treeTransparentCutout\");\n                    for (int i = 0; i < speedTreeGeometryTypeString.Length; ++i)\n                        m.DisableKeyword(speedTreeGeometryTypeString[i]);\n                    m.EnableKeyword(speedTreeGeometryTypeString[(int)setGeomType]);\n                    m.renderQueue = shouldEnableAlphaTest ? (int)UnityEngine.Rendering.RenderQueue.AlphaTest : (int)UnityEngine.Rendering.RenderQueue.Geometry;\n                    m.SetFloat(\"_Cull\", (float)cullMode);\n                }\n            }\n            EditorGUI.showMixedValue = false;\n\n            //---------------------------------------------------------------\n            var mainTex = props.Find(prop => prop.name == \"_MainTex\");\n            if (mainTex != null)\n            {\n                props.Remove(mainTex);\n                ShaderProperty(mainTex, mainTex.displayName);\n            }\n\n            //---------------------------------------------------------------\n            var bumpMap = props.Find(prop => prop.name == \"_BumpMap\");\n            if (bumpMap != null)\n            {\n                props.Remove(bumpMap);\n\n                var enableBump = targets.Select(t => ((Material)t).shaderKeywords.Contains(\"EFFECT_BUMP\"));\n                bool? enable = ToggleShaderProperty(bumpMap, enableBump.First(), enableBump.Distinct().Count() > 1);\n                if (enable != null)\n                {\n                    foreach (var m in targets.Cast<Material>())\n                    {\n                        if (enable.Value)\n                            m.EnableKeyword(\"EFFECT_BUMP\");\n                        else\n                            m.DisableKeyword(\"EFFECT_BUMP\");\n                    }\n                }\n            }\n\n            //---------------------------------------------------------------\n            var detailTex = props.Find(prop => prop.name == \"_DetailTex\");\n            if (detailTex != null)\n            {\n                props.Remove(detailTex);\n                if (geomTypes.Contains(SpeedTreeGeometryType.BranchDetail))\n                    ShaderProperty(detailTex, detailTex.displayName);\n            }\n\n            //---------------------------------------------------------------\n            var enableHueVariation = targets.Select(t => ((Material)t).shaderKeywords.Contains(\"EFFECT_HUE_VARIATION\"));\n            var hueVariation = props.Find(prop => prop.name == \"_HueVariation\");\n            if (enableHueVariation != null && hueVariation != null)\n            {\n                props.Remove(hueVariation);\n                bool? enable = ToggleShaderProperty(hueVariation, enableHueVariation.First(), enableHueVariation.Distinct().Count() > 1);\n                if (enable != null)\n                {\n                    foreach (var m in targets.Cast<Material>())\n                    {\n                        if (enable.Value)\n                            m.EnableKeyword(\"EFFECT_HUE_VARIATION\");\n                        else\n                            m.DisableKeyword(\"EFFECT_HUE_VARIATION\");\n                    }\n                }\n            }\n\n            //---------------------------------------------------------------\n            var alphaCutoff = props.Find(prop => prop.name == \"_Cutoff\");\n            if (alphaCutoff != null)\n            {\n                props.Remove(alphaCutoff);\n                if (geomTypes.Any(t => ShouldEnableAlphaTest(t)))\n                    ShaderProperty(alphaCutoff, alphaCutoff.displayName);\n            }\n\n            //---------------------------------------------------------------\n            foreach (var prop in props)\n            {\n                if ((prop.propertyFlags & ShaderPropertyFlags.HideInInspector) != 0)\n                    continue;\n                ShaderProperty(prop, prop.displayName);\n            }\n\n            EditorGUILayout.Space();\n            EditorGUILayout.Space();\n\n            RenderQueueField();\n            EnableInstancingField();\n            DoubleSidedGIField();\n        }\n\n        private bool? ToggleShaderProperty(MaterialProperty prop, bool enable, bool hasMixedEnable)\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = hasMixedEnable;\n            Rect controlRect = EditorGUILayout.GetControlRect(false, GUILayout.ExpandWidth(false));\n            controlRect.width = controlRect.width > EditorGUIUtility.fieldWidth ? controlRect.width - EditorGUIUtility.fieldWidth : controlRect.width;\n            enable = EditorGUI.ToggleLeft(controlRect, prop.displayName, enable);\n            EditorGUI.showMixedValue = false;\n            bool? retValue = EditorGUI.EndChangeCheck() ? (bool?)enable : null;\n\n            GUILayout.Space(-EditorGUIUtility.singleLineHeight);\n            using (new EditorGUI.DisabledScope(!enable && !hasMixedEnable))\n            {\n                EditorGUI.showMixedValue = prop.hasMixedValue;\n                ShaderProperty(prop, \" \");\n                EditorGUI.showMixedValue = false;\n            }\n            return retValue;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/SpriteFrameInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Text;\nusing Unity.Collections;\nusing UnityEditor.UIElements;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.U2D;\nusing UnityEngine.Rendering;\nusing UnityEngine.Experimental.Rendering;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(Sprite))]\n    [CanEditMultipleObjects]\n    internal class SpriteInspector : Editor\n    {\n        private static class Styles\n        {\n            public static readonly GUIContent nameLabel = EditorGUIUtility.TrTextContent(\"Name\", \"The name for the Sprite.\");\n            public static readonly GUIContent spriteAlignmentLabel = EditorGUIUtility.TrTextContent(\"Pivot\", \"The value is normalized to the Sprite's size where (0, 0) is the lower left and (1, 1) is the upper right. May be used for syncing animation frames of different sizes.\");\n            public static readonly GUIContent spriteAlignmentText = EditorGUIUtility.TrTextContent(\"X:{0:0.##}, Y:{1:0.##}\");\n            public static readonly GUIContent borderLabel = EditorGUIUtility.TrTextContent(\"Border\", \"Border values for the Sprite set in Sprite Editor window. May be useful for 9-Slicing Sprites. The values are in pixels units.\");\n            public static readonly GUIContent borderText = EditorGUIUtility.TrTextContent(\"L:{0:0.##} B:{1:0.##} R:{2:0.##} T:{3:0.##}\");\n            public static readonly GUIContent multiValueText = EditorGUIUtility.TrTextContent(\"-\");\n            public static readonly GUIContent elemenText = EditorGUIUtility.TrTextContent(\"Element {0}\");\n        }\n\n        SerializedProperty m_Name;\n        SerializedProperty m_Pivot;\n        SerializedProperty m_ScriptableObjects;\n        Vector4 m_BorderValue;\n        bool m_BorderHasSameValue = true;\n        GUIContent m_SpriteNameContent;\n        GUIContent m_SpriteAlignmentContent;\n        GUIContent m_SpriteBorderContent;\n        StringBuilder m_ElementStringBuilder;\n        void OnEnable()\n        {\n            m_Name = serializedObject.FindProperty(\"m_Name\");\n            m_Pivot = serializedObject.FindProperty(\"m_Pivot\");\n            m_ScriptableObjects = serializedObject.FindProperty(\"m_ScriptableObjects\");\n            m_BorderValue = sprite.border;\n\n            CheckBorderHasSameValue();\n            m_SpriteNameContent = new GUIContent(sprite.name);\n            m_SpriteAlignmentContent = new GUIContent(string.Format(Styles.spriteAlignmentText.text, m_Pivot.vector2Value.x, m_Pivot.vector2Value.y));\n            m_SpriteBorderContent = new GUIContent(string.Format(Styles.borderText.text, m_BorderValue.x, m_BorderValue.y, m_BorderValue.z, m_BorderValue.w));\n            m_ElementStringBuilder = new StringBuilder();\n        }\n\n        void CheckBorderHasSameValue()\n        {\n            foreach (var obj in serializedObject.targetObjects)\n            {\n                if (obj == target)\n                    continue;\n                if (obj is Sprite)\n                {\n                    var spr = (Sprite)obj;\n                    var borderValue = spr.border;\n                    if (borderValue != m_BorderValue)\n                    {\n                        m_BorderHasSameValue = false;\n                        break;\n                    }\n                }\n                else\n                {\n                    m_BorderHasSameValue = false;\n                    break;\n                }\n            }\n        }\n\n        private Sprite sprite\n        {\n            get { return target as Sprite; }\n        }\n\n        public override VisualElement CreateInspectorGUI()\n        {\n            var rootVisualElement = new VisualElement();\n            rootVisualElement.Add(new IMGUIContainer(OnSpriteFramePropertiesGUI));\n            var listElement = new ListView()\n            {\n                name = \"SpriteScriptableObjectListView\",\n                style = { height = 300}\n            };\n            listElement.headerTitle = \"ScriptableObjects\";\n            listElement.showBorder = true;\n            listElement.showAddRemoveFooter = false;\n            listElement.showBoundCollectionSize = false;\n            listElement.showFoldoutHeader = true;\n            listElement.virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight;\n            listElement.userData = (object) m_ScriptableObjects;\n            listElement.showAlternatingRowBackgrounds = AlternatingRowBackground.ContentOnly;\n            listElement.bindingPath = m_ScriptableObjects.propertyPath;\n            listElement.viewDataKey = m_ScriptableObjects.propertyPath;\n            listElement.name = \"unity-list-\" + m_ScriptableObjects.propertyPath;\n            listElement.BindProperty(m_ScriptableObjects.serializedObject);\n            listElement.makeItem = () =>\n            {\n                var propertyField = new ObjectField();\n                propertyField.SetEnabled(false);\n                var image = new Image()\n                {\n                    image = EditorGUIUtility.GetHelpIcon(MessageType.Warning),\n                    tooltip = EditorGUIUtility.TrTextContent(\"ScriptableObject that was previously assigned is no longer available.\").text,\n                    style =\n                    {\n                        maxHeight = EditorGUI.kSingleLineHeight,\n                        flexShrink = 0,\n                        alignSelf = Align.FlexEnd,\n                    },\n                    name = \"WarningIcon\"\n                };\n                propertyField.Add(image);\n\n                return propertyField;\n            };\n            listElement.bindItem = (element, i) =>\n            {\n                var pf = (ObjectField)element;\n                m_ElementStringBuilder.Clear();\n                m_ElementStringBuilder.AppendFormat(Styles.elemenText.text, i);\n                pf.label = m_ElementStringBuilder.ToString();\n                var objReference = m_ScriptableObjects.GetArrayElementAtIndex(i).objectReferenceValue;\n                pf.SetValueWithoutNotify(objReference);\n                var image = pf.Q<Image>(\"WarningIcon\");\n                image.style.visibility = objReference != null ? Visibility.Hidden : Visibility.Visible;\n                image.style.position = objReference != null ? Position.Absolute : Position.Relative;\n                element.MarkDirtyRepaint();\n            };\n            listElement.unbindItem = (element, i) =>\n            {\n                element.Unbind();\n            };\n            listElement.destroyItem = element => element.Unbind();\n            rootVisualElement.Add(listElement);\n            return rootVisualElement;\n        }\n\n        void OnSpriteFramePropertiesGUI()\n        {\n            if (!m_Name.hasMultipleDifferentValues)\n                EditorGUILayout.LabelField(Styles.nameLabel, m_SpriteNameContent);\n            else\n                EditorGUILayout.LabelField(Styles.nameLabel, Styles.multiValueText);\n\n            if (!m_Pivot.hasMultipleDifferentValues)\n                EditorGUILayout.LabelField(Styles.spriteAlignmentLabel, m_SpriteAlignmentContent);\n            else\n                EditorGUILayout.LabelField(Styles.spriteAlignmentLabel, Styles.multiValueText);\n\n            if (m_BorderHasSameValue)\n                EditorGUILayout.LabelField(Styles.borderLabel, m_SpriteBorderContent);\n            else\n                EditorGUILayout.LabelField(Styles.borderLabel, Styles.multiValueText);\n        }\n\n\n        public static Texture2D BuildPreviewTexture(Sprite sprite, Material spriteRendererMaterial, bool isPolygon, int width, int height)\n        {\n            return BuildPreviewTexture(sprite, spriteRendererMaterial, isPolygon, width, height, Color.white, Matrix4x4.identity);\n        }\n\n        public static Texture2D BuildPreviewTexture(Sprite sprite, Material spriteRendererMaterial, bool isPolygon, int width, int height, Color color, Matrix4x4 transform)\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture || sprite == null)\n            {\n                return null;\n            }\n\n            var spriteWidth = sprite.rect.width;\n            var spriteHeight = sprite.rect.height;\n\n            Texture2D texture = UnityEditor.Sprites.SpriteUtility.GetSpriteTexture(sprite, false);\n\n            // only adjust the preview texture size if the sprite is not in polygon mode.\n            // In polygon mode, we are looking at a 4x4 texture will detailed mesh. It's better to maximize the display of it.\n            if (!isPolygon)\n            {\n                // Try to have a minimum of 64 pixels for width and height, unless requested width and height is smaller\n                var minWidth = Mathf.Min(64f, width);\n                var minHeight = Mathf.Min(64f, height);\n\n                PreviewHelpers.AdjustWidthAndHeightForStaticPreview((int) spriteWidth, (int) spriteHeight, ref width, ref height);\n\n                // Set minimum size for width/height to prevent small previews for small sprites\n                if (width < minWidth && height < minHeight)\n                {\n                    var ratio = Mathf.Min( minWidth / width, minHeight / height);\n                    ratio = Mathf.CeilToInt(ratio);\n                    width = Mathf.FloorToInt(width * ratio);\n                    height = Mathf.FloorToInt(height * ratio);\n                }\n            }\n\n            SavedRenderTargetState savedRTState = new SavedRenderTargetState();\n\n            RenderTexture tmp = RenderTexture.GetTemporary(\n                width,\n                height,\n                0,\n                SystemInfo.GetGraphicsFormat(DefaultFormat.LDR));\n\n            RenderTexture.active = tmp;\n\n            GL.Clear(true, true, new Color(0f, 0f, 0f, 0f));\n\n            Texture _oldTexture = null;\n            Vector4 _oldTexelSize = new Vector4(0, 0, 0, 0);\n            bool _matHasTexture = false;\n            bool _matHasTexelSize = false;\n            if (spriteRendererMaterial != null)\n            {\n                _matHasTexture = spriteRendererMaterial.HasProperty(\"_MainTex\");\n                _matHasTexelSize = spriteRendererMaterial.HasProperty(\"_MainTex_TexelSize\");\n            }\n\n            bool hasColors = sprite.HasVertexAttribute(VertexAttribute.Color);\n\n            Material copyMaterial = null;\n            if (spriteRendererMaterial != null)\n            {\n                if (_matHasTexture)\n                {\n                    _oldTexture = spriteRendererMaterial.GetTexture(\"_MainTex\");\n                    spriteRendererMaterial.SetTexture(\"_MainTex\", texture);\n                }\n\n                if (_matHasTexelSize)\n                {\n                    _oldTexelSize = spriteRendererMaterial.GetVector(\"_MainTex_TexelSize\");\n                    spriteRendererMaterial.SetVector(\"_MainTex_TexelSize\", TextureUtil.GetTexelSizeVector(texture));\n                }\n\n                spriteRendererMaterial.SetPass(0);\n            }\n            else\n            {\n                if (hasColors || texture == null)\n                {\n                    SpriteUtility.previewSpriteDefaultMaterial.SetPass(0);\n                }\n                else if (texture != null)\n                {\n                    copyMaterial = new Material(Shader.Find(\"Hidden/BlitCopy\"));\n                    copyMaterial.mainTexture = texture;\n                    copyMaterial.mainTextureScale = Vector2.one;\n                    copyMaterial.mainTextureOffset = Vector2.zero;\n                    copyMaterial.SetPass(0);\n                }\n            }\n\n            float pixelsToUnits = sprite.rect.width / sprite.bounds.size.x;\n            Vector2[] vertices = sprite.vertices;\n            Vector2[] uvs = Sprites.SpriteUtility.GetSpriteUVs(sprite, false);\n            ushort[] triangles = sprite.triangles;\n            Vector2 pivot = sprite.pivot;\n\n            NativeSlice<Color32>? colors = null;\n            if (hasColors)\n                colors = sprite.GetVertexAttribute<Color32>(VertexAttribute.Color);\n\n            GL.PushMatrix();\n            GL.LoadOrtho();\n            GL.Begin(GL.TRIANGLES);\n            for (int i = 0; i < triangles.Length; ++i)\n            {\n                ushort index = triangles[i];\n                Vector3 vertex = vertices[index];\n                vertex = transform.MultiplyPoint(vertex);\n                Vector2 uv = uvs[index];\n                GL.Color(colors != null ? colors.Value[index] * color : color);\n                GL.TexCoord(new Vector3(uv.x, uv.y, 0));\n                GL.Vertex3((vertex.x * pixelsToUnits + pivot.x) / spriteWidth, (vertex.y * pixelsToUnits + pivot.y) / spriteHeight, 0);\n            }\n            GL.End();\n            GL.PopMatrix();\n\n            if (spriteRendererMaterial != null)\n            {\n                if (_matHasTexture)\n                    spriteRendererMaterial.SetTexture(\"_MainTex\", _oldTexture);\n                if (_matHasTexelSize)\n                    spriteRendererMaterial.SetVector(\"_MainTex_TexelSize\", _oldTexelSize);\n            }\n\n            var tmp2 = RenderTexture.GetTemporary(width, height, 0, GraphicsFormat.R8G8B8A8_UNorm);\n            Graphics.Blit(tmp, tmp2, EditorGUIUtility.GUITextureBlit2SRGBMaterial);\n\n            RenderTexture.active = tmp2;\n\n            Texture2D copy = new Texture2D(width, height, TextureFormat.RGBA32, false);\n            copy.hideFlags = HideFlags.HideAndDontSave;\n            copy.filterMode = texture != null ? texture.filterMode : FilterMode.Point;\n            copy.anisoLevel = texture != null ? texture.anisoLevel : 0;\n            copy.wrapMode = texture != null ? texture.wrapMode : TextureWrapMode.Clamp;\n            copy.ReadPixels(new Rect(0, 0, width, height), 0, 0);\n            copy.Apply();\n            RenderTexture.ReleaseTemporary(tmp);\n            RenderTexture.ReleaseTemporary(tmp2);\n\n            savedRTState.Restore();\n\n            if (copyMaterial != null)\n                DestroyImmediate(copyMaterial);\n\n            return copy;\n        }\n\n        public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height)\n        {\n            // Determine is sprite in assetpath a polygon sprite\n            bool isPolygonSpriteAsset = false;\n            TextureImporter textureImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;\n            if (textureImporter != null)\n            {\n                isPolygonSpriteAsset = textureImporter.spriteImportMode == SpriteImportMode.Polygon;\n            }\n\n            return BuildPreviewTexture(sprite, null, isPolygonSpriteAsset, width, height);\n        }\n\n        public override bool HasPreviewGUI()\n        {\n            var sprite = target as Sprite;\n            return (sprite != null) && UnityEditor.Sprites.SpriteUtility.GetSpriteTexture(sprite, false) != null;\n        }\n\n        public override void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            if (target == null)\n                return;\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            bool isPolygon = false;\n            string path = AssetDatabase.GetAssetPath(sprite);\n            TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;\n            if (textureImporter != null)\n            {\n                isPolygon = textureImporter.spriteImportMode == SpriteImportMode.Polygon;\n            }\n\n            DrawPreview(r, sprite, null, isPolygon);\n        }\n\n        public static void DrawPreview(Rect r, Sprite frame, Material spriteRendererMaterial, bool isPolygon)\n        {\n            if (frame == null)\n                return;\n\n            float zoomLevel = Mathf.Min(r.width / frame.rect.width, r.height / frame.rect.height);\n            Rect wantedRect = new Rect(r.x, r.y, frame.rect.width * zoomLevel, frame.rect.height * zoomLevel);\n            wantedRect.center = r.center;\n\n            Texture2D previewTexture = BuildPreviewTexture(frame, spriteRendererMaterial, isPolygon, (int) wantedRect.width, (int) wantedRect.height);\n            EditorGUI.DrawTextureTransparent(wantedRect, previewTexture, ScaleMode.ScaleToFit);\n\n            var border = frame.border;\n            border *= zoomLevel;\n            if (!Mathf.Approximately(border.sqrMagnitude, 0))\n            {\n                SpriteEditorUtility.BeginLines(new Color(0f, 1f, 0f, 0.7f));\n                //TODO: this\n                //SpriteEditorUtility.DrawBorder (wantedRect, border);\n                SpriteEditorUtility.EndLines();\n            }\n\n            DestroyImmediate(previewTexture);\n        }\n\n        public override string GetInfoString()\n        {\n            if (target == null)\n                return \"\";\n\n            Sprite sprite = target as Sprite;\n\n            return string.Format(\"({0}x{1})\",\n                (int)sprite.rect.width,\n                (int)sprite.rect.height\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/SpriteRendererEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditorInternal;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditor.AnimatedValues;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(SpriteRenderer))]\n    [CanEditMultipleObjects]\n    internal class SpriteRendererEditor : RendererEditorBase\n    {\n        private SerializedProperty m_Sprite;\n        private SerializedProperty m_Color;\n        private SerializedProperty m_Material;\n\n        class Styles\n        {\n            public static readonly GUIContent flipLabel = EditorGUIUtility.TrTextContent(\"Flip\", \"Sprite flipping\");\n            public static readonly GUIContent flipXLabel = EditorGUIUtility.TrTextContent(\"X\", \"Sprite horizontal flipping\");\n            public static readonly GUIContent flipYLabel = EditorGUIUtility.TrTextContent(\"Y\", \"Sprite vertical flipping\");\n            public static readonly int flipToggleHash = \"FlipToggleHash\".GetHashCode();\n\n            public static readonly GUIContent fullTileLabel = EditorGUIUtility.TrTextContent(\"Tile Mode\", \"Specify the 9-slice tiling behaviour\");\n            public static readonly GUIContent fullTileThresholdLabel = EditorGUIUtility.TrTextContent(\"Stretch Value\", \"This value defines how much the center portion will stretch before it tiles.\");\n            public static readonly GUIContent drawModeLabel = EditorGUIUtility.TrTextContent(\"Draw Mode\", \"Specify the draw mode for the sprite\");\n            public static readonly GUIContent widthLabel = EditorGUIUtility.TrTextContent(\"Width\", \"The width dimension value for the sprite\");\n            public static readonly GUIContent heightLabel = EditorGUIUtility.TrTextContent(\"Height\", \"The height dimension value for the sprite\");\n            public static readonly GUIContent sizeLabel = EditorGUIUtility.TrTextContent(\"Size\", \"The rendering dimension for the sprite\");\n            public static readonly GUIContent notFullRectWarningLabel = EditorGUIUtility.TrTextContent(\"Sprite Tiling might not appear correctly because the Sprite used is not generated with Full Rect or Sprite Mode is set to Polygon mode. To fix this, change the Mesh Type in the Sprite's import setting to Full Rect and Sprite Mode is either Single or Multiple\");\n            public static readonly GUIContent notFullRectMultiEditWarningLabel = EditorGUIUtility.TrTextContent(\"Sprite Tiling might not appear correctly because some of the Sprites used are not generated with Full Rect. To fix this, change the Mesh Type in the Sprite's import setting to Full Rect\");\n            public static readonly int sizeFieldHash = \"SpriteRendererSizeField\".GetHashCode();\n            public static readonly GUIContent materialLabel = EditorGUIUtility.TrTextContent(\"Material\", \"Material to be used by SpriteRenderer\");\n            public static readonly GUIContent spriteLabel = EditorGUIUtility.TrTextContent(\"Sprite\", \"The Sprite to render\");\n            public static readonly GUIContent colorLabel = EditorGUIUtility.TrTextContent(\"Color\", \"Rendering color for the Sprite graphic\");\n            public static readonly GUIContent maskInteractionLabel = EditorGUIUtility.TrTextContent(\"Mask Interaction\", \"SpriteRenderer's interaction with a Sprite Mask\");\n            public static readonly GUIContent spriteSortPointLabel = EditorGUIUtility.TrTextContent(\"Sprite Sort Point\", \"Determines which position of the Sprite which is used for sorting\");\n            public static readonly Texture2D warningIcon = EditorGUIUtility.LoadIcon(\"console.warnicon\");\n            public static readonly GUIContent drawModeChange = EditorGUIUtility.TrTextContent(\"Draw mode Change\");\n        }\n\n        private SerializedProperty m_FlipX;\n        private SerializedProperty m_FlipY;\n\n        private SerializedProperty m_DrawMode;\n        private SerializedProperty m_SpriteTileMode;\n        private SerializedProperty m_AdaptiveModeThreshold;\n        private SerializedProperty m_Size;\n        private AnimBool m_ShowDrawMode;\n        private AnimBool m_ShowTileMode;\n        private AnimBool m_ShowAdaptiveThreshold;\n        private SerializedProperty m_MaskInteraction;\n        private SerializedProperty m_SpriteSortPoint;\n\n        public override void OnEnable()\n        {\n            base.OnEnable();\n\n            m_Sprite = serializedObject.FindProperty(\"m_Sprite\");\n            m_Color = serializedObject.FindProperty(\"m_Color\");\n            m_FlipX = serializedObject.FindProperty(\"m_FlipX\");\n            m_FlipY = serializedObject.FindProperty(\"m_FlipY\");\n            m_Material = serializedObject.FindProperty(\"m_Materials.Array\"); // Only allow to edit one material\n            m_DrawMode = serializedObject.FindProperty(\"m_DrawMode\");\n            m_Size = serializedObject.FindProperty(\"m_Size\");\n            m_SpriteTileMode = serializedObject.FindProperty(\"m_SpriteTileMode\");\n            m_AdaptiveModeThreshold = serializedObject.FindProperty(\"m_AdaptiveModeThreshold\");\n            m_ShowDrawMode = new AnimBool(ShouldShowDrawMode());\n            m_ShowTileMode = new AnimBool(ShouldShowTileMode());\n            m_ShowAdaptiveThreshold = new AnimBool(ShouldShowAdaptiveThreshold());\n\n            m_ShowDrawMode.valueChanged.AddListener(Repaint);\n            m_ShowTileMode.valueChanged.AddListener(Repaint);\n            m_ShowAdaptiveThreshold.valueChanged.AddListener(Repaint);\n            m_MaskInteraction = serializedObject.FindProperty(\"m_MaskInteraction\");\n            m_SpriteSortPoint = serializedObject.FindProperty(\"m_SpriteSortPoint\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUILayout.PropertyField(m_Sprite, Styles.spriteLabel);\n            using (new EditorGUI.DisabledScope(m_Sprite.objectReferenceValue == null))\n            {\n                if(SpriteUtilityWindow.DoOpenSpriteEditorWindowUI())\n                    SpriteUtilityWindow.ShowSpriteEditorWindow(m_Sprite.objectReferenceValue);\n            }\n            GUILayout.Space(5);\n            EditorGUILayout.PropertyField(m_Color, Styles.colorLabel, true);\n\n            FlipToggles();\n\n            using (new EditorGUI.DisabledGroupScope(IsTextureless()))\n            {\n                var showMixedValue = EditorGUI.showMixedValue;\n                if (m_DrawMode.hasMultipleDifferentValues)\n                    EditorGUI.showMixedValue = true;\n                SpriteDrawMode drawMode = (SpriteDrawMode)m_DrawMode.intValue;\n                drawMode = (SpriteDrawMode)EditorGUILayout.EnumPopup(Styles.drawModeLabel, drawMode);\n                SetDrawMode(drawMode);\n                EditorGUI.showMixedValue = showMixedValue;\n\n                m_ShowDrawMode.target = ShouldShowDrawMode();\n                if (EditorGUILayout.BeginFadeGroup(m_ShowDrawMode.faded))\n                {\n                    string notFullRectWarning = GetSpriteNotFullRectWarning();\n                    if (notFullRectWarning != null)\n                        EditorGUILayout.HelpBox(notFullRectWarning, MessageType.Warning);\n\n                    EditorGUI.indentLevel++;\n                    EditorGUILayout.BeginHorizontal();\n                    EditorGUILayout.PrefixLabel(Styles.sizeLabel);\n                    EditorGUI.showMixedValue = m_Size.hasMultipleDifferentValues;\n                    FloatFieldLabelAbove(Styles.widthLabel, m_Size.FindPropertyRelative(\"x\"));\n                    FloatFieldLabelAbove(Styles.heightLabel, m_Size.FindPropertyRelative(\"y\"));\n                    EditorGUI.showMixedValue = false;\n                    EditorGUILayout.EndHorizontal();\n\n\n                    m_ShowTileMode.target = ShouldShowTileMode();\n                    if (EditorGUILayout.BeginFadeGroup(m_ShowTileMode.faded))\n                    {\n                        EditorGUILayout.PropertyField(m_SpriteTileMode, Styles.fullTileLabel);\n\n                        m_ShowAdaptiveThreshold.target = ShouldShowAdaptiveThreshold();\n                        if (EditorGUILayout.BeginFadeGroup(m_ShowAdaptiveThreshold.faded))\n                        {\n                            EditorGUI.indentLevel++;\n                            EditorGUILayout.Slider(m_AdaptiveModeThreshold, 0.0f, 1.0f, Styles.fullTileThresholdLabel);\n                            EditorGUI.indentLevel--;\n                        }\n                        EditorGUILayout.EndFadeGroup();\n                    }\n                    EditorGUILayout.EndFadeGroup();\n\n                    EditorGUI.indentLevel--;\n                }\n                EditorGUILayout.EndFadeGroup();\n            }\n\n            EditorGUILayout.PropertyField(m_MaskInteraction, Styles.maskInteractionLabel);\n            EditorGUILayout.PropertyField(m_SpriteSortPoint, Styles.spriteSortPointLabel);\n            EditorGUILayout.PropertyField(m_Material.GetArrayElementAtIndex(0), Styles.materialLabel, true);\n\n            ShowMaterialError();\n\n            Other2DSettingsGUI();\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        internal void SetDrawMode(SpriteDrawMode drawMode)\n        {\n            if (drawMode != (SpriteDrawMode)m_DrawMode.intValue)\n            {\n                foreach (var target in serializedObject.targetObjects)\n                {\n                    var sr = (SpriteRenderer)target;\n                    var t = sr.transform;\n                    Undo.RecordObjects(new UnityEngine.Object[] {sr, t}, Styles.drawModeChange.text);\n                    sr.drawMode = drawMode;\n                    foreach (var editor in ActiveEditorTracker.sharedTracker.activeEditors)\n                    {\n                        if(editor.target == t)\n                            editor.serializedObject.SetIsDifferentCacheDirty();\n                    }\n                }\n                serializedObject.SetIsDifferentCacheDirty();\n            }\n        }\n\n        void FloatFieldLabelAbove(GUIContent contentLabel, SerializedProperty sp)\n        {\n            EditorGUILayout.BeginVertical();\n            Rect rtLabel = GUILayoutUtility.GetRect(contentLabel, EditorStyles.label);\n            GUIContent label = EditorGUI.BeginProperty(rtLabel, contentLabel, sp);\n            int id = GUIUtility.GetControlID(Styles.sizeFieldHash, FocusType.Keyboard, rtLabel);\n            EditorGUI.HandlePrefixLabel(rtLabel, rtLabel, label, id);\n            Rect rt = GUILayoutUtility.GetRect(contentLabel, EditorStyles.textField);\n            EditorGUI.BeginChangeCheck();\n            float value = EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor, rt, rtLabel, id, sp.floatValue, EditorGUI.kFloatFieldFormatString, EditorStyles.textField, true);\n            if (EditorGUI.EndChangeCheck())\n                sp.floatValue = value;\n            EditorGUI.EndProperty();\n            EditorGUILayout.EndVertical();\n        }\n\n        string GetSpriteNotFullRectWarning()\n        {\n            foreach (var t in targets)\n            {\n                if (!(t as SpriteRenderer).shouldSupportTiling)\n                    return targets.Length == 1 ? Styles.notFullRectWarningLabel.text : Styles.notFullRectMultiEditWarningLabel.text;\n            }\n            return null;\n        }\n\n        bool IsTextureless()\n        {\n            foreach (var t in targets)\n            {\n                var sr = (t as SpriteRenderer);\n                if (sr.sprite != null && sr.sprite.texture == null)\n                    return true;\n            }\n            return false;\n        }\n\n        bool ShouldShowDrawMode()\n        {\n            return m_DrawMode.intValue != (int)SpriteDrawMode.Simple && !m_DrawMode.hasMultipleDifferentValues;\n        }\n\n        bool ShouldShowAdaptiveThreshold()\n        {\n            return m_SpriteTileMode.intValue == (int)SpriteTileMode.Adaptive && !m_SpriteTileMode.hasMultipleDifferentValues;\n        }\n\n        bool ShouldShowTileMode()\n        {\n            return m_DrawMode.intValue == (int)SpriteDrawMode.Tiled && !m_DrawMode.hasMultipleDifferentValues;\n        }\n\n        void FlipToggles()\n        {\n            const int toggleOffset = 30;\n            GUILayout.BeginHorizontal();\n            Rect r = GUILayoutUtility.GetRect(EditorGUIUtility.fieldWidth, EditorGUILayout.kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.numberField);\n            int id = GUIUtility.GetControlID(Styles.flipToggleHash, FocusType.Keyboard, r);\n            r = EditorGUI.PrefixLabel(r, id, Styles.flipLabel);\n            r.width = toggleOffset;\n            FlipToggle(r, Styles.flipXLabel, m_FlipX);\n            r.x += toggleOffset;\n            FlipToggle(r, Styles.flipYLabel, m_FlipY);\n            GUILayout.EndHorizontal();\n        }\n\n        void FlipToggle(Rect r, GUIContent label, SerializedProperty property)\n        {\n            EditorGUI.BeginProperty(r, label, property);\n\n            bool toggle = property.boolValue;\n            EditorGUI.BeginChangeCheck();\n            int oldIndent = EditorGUI.indentLevel;\n            EditorGUI.indentLevel = 0;\n            toggle = EditorGUI.ToggleLeft(r, label, toggle);\n            EditorGUI.indentLevel = oldIndent;\n            if (EditorGUI.EndChangeCheck())\n            {\n                property.boolValue = toggle;\n            }\n\n            EditorGUI.EndProperty();\n        }\n\n        private void ShowMaterialError()\n        {\n            bool materialHasMainTex = DoesMaterialHaveSpriteTexture(\"_MainTex\");\n            bool materialHasBaseMap = DoesMaterialHaveSpriteTexture(\"_BaseMap\");\n\n            if (!materialHasMainTex && !materialHasBaseMap)\n            {\n                ShowWarning(\"Material does not have a _MainTex or _BaseMap texture property. Having one of them is required for SpriteRenderer.\");\n            }\n            else\n            {\n                if(materialHasMainTex)\n                    CheckPropertyForScaleAndOffset(\"_MainTex\");\n                else if(materialHasBaseMap)\n                    CheckPropertyForScaleAndOffset(\"_BaseMap\");\n            }\n        }\n\n        private void CheckPropertyForScaleAndOffset(string propertyName)\n        {\n            Material material = (target as SpriteRenderer).sharedMaterial;\n            if (material != null)\n            {\n                Vector2 offset = material.GetTextureOffset(propertyName);\n                Vector2 scale = material.GetTextureScale(propertyName);\n                if (offset.x != 0 || offset.y != 0 || scale.x != 1 || scale.y != 1)\n                {\n                    ShowWarning(\"Material texture property \" + propertyName + \" has offset/scale set. It is incompatible with SpriteRenderer.\");\n                }\n            }\n        }\n\n        private bool DoesMaterialHaveSpriteTexture(string propertyName)\n        {\n            Material material = (target as SpriteRenderer).sharedMaterial;\n            if (material == null)\n                return true;\n\n            return material.HasProperty(propertyName);\n        }\n\n        private static void ShowWarning(string message)\n        {\n            var c = new GUIContent(message) {image = Styles.warningIcon};\n\n            GUILayout.Space(5);\n            GUILayout.BeginVertical(EditorStyles.helpBox);\n            GUILayout.Label(c, EditorStyles.wordWrappedMiniLabel);\n            GUILayout.EndVertical();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/StandardParticlesShaderGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class StandardParticlesShaderGUI : ShaderGUI\n    {\n        public enum BlendMode\n        {\n            Opaque,\n            Cutout,\n            Fade,   // Old school alpha-blending mode, fresnel does not affect amount of transparency\n            Transparent, // Physically plausible transparency mode, implemented as alpha pre-multiply\n            Additive,\n            Subtractive,\n            Modulate\n        }\n\n        public enum FlipbookMode\n        {\n            Simple,\n            Blended\n        }\n\n        public enum ColorMode\n        {\n            Multiply,\n            Additive,\n            Subtractive,\n            Overlay,\n            Color,\n            Difference\n        }\n\n        private static class Styles\n        {\n            public static GUIContent albedoText = EditorGUIUtility.TrTextContent(\"Albedo\", \"Albedo (RGB) and Transparency (A).\");\n            public static GUIContent alphaCutoffText = EditorGUIUtility.TrTextContent(\"Alpha Cutoff\", \"Threshold for alpha cutoff.\");\n            public static GUIContent metallicMapText = EditorGUIUtility.TrTextContent(\"Metallic\", \"Metallic (R) and Smoothness (A).\");\n            public static GUIContent smoothnessText = EditorGUIUtility.TrTextContent(\"Smoothness\", \"Smoothness value.\");\n            public static GUIContent smoothnessScaleText = EditorGUIUtility.TrTextContent(\"Smoothness\", \"Smoothness scale factor.\");\n            public static GUIContent normalMapText = EditorGUIUtility.TrTextContent(\"Normal Map\", \"Normal Map.\");\n            public static GUIContent emissionText = EditorGUIUtility.TrTextContent(\"Color\", \"Emission (RGB).\");\n\n            public static GUIContent renderingMode = EditorGUIUtility.TrTextContent(\"Rendering Mode\", \"Determines the transparency and blending method for drawing the object to the screen.\");\n            public static GUIContent[] blendNames = Array.ConvertAll(Enum.GetNames(typeof(BlendMode)), item => new GUIContent(item));\n\n            public static GUIContent colorMode = EditorGUIUtility.TrTextContent(\"Color Mode\", \"Determines the blending mode between the particle color and the texture albedo.\");\n            public static GUIContent[] colorNames = Array.ConvertAll(Enum.GetNames(typeof(ColorMode)), item => new GUIContent(item));\n\n            public static GUIContent flipbookBlending = EditorGUIUtility.TrTextContent(\"Flip-Book Frame Blending\", \"Enables blending between the frames of animated texture sheets.\");\n            public static GUIContent twoSidedEnabled = EditorGUIUtility.TrTextContent(\"Two Sided\", \"Render both front and back faces of the particle geometry.\");\n\n            public static GUIContent distortionEnabled = EditorGUIUtility.TrTextContent(\"Distortion\", \"Use a grab pass and normal map to simulate refraction.\");\n            public static GUIContent distortionStrengthText = EditorGUIUtility.TrTextContent(\"Strength\", \"Distortion Strength.\");\n            public static GUIContent distortionBlendText = EditorGUIUtility.TrTextContent(\"Blend\", \"Weighting between albedo and grab pass.\");\n\n            public static GUIContent softParticlesEnabled = EditorGUIUtility.TrTextContent(\"Soft Particles\", \"Fade out particle geometry when it gets close to the surface of objects written into the depth buffer.\");\n            public static GUIContent softParticlesNearFadeDistanceText = EditorGUIUtility.TrTextContent(\"Near fade\", \"Soft Particles near fade distance.\");\n            public static GUIContent softParticlesFarFadeDistanceText = EditorGUIUtility.TrTextContent(\"Far fade\", \"Soft Particles far fade distance.\");\n\n            public static GUIContent cameraFadingEnabled = EditorGUIUtility.TrTextContent(\"Camera Fading\", \"Fade out particle geometry when it gets close to the camera.\");\n            public static GUIContent cameraNearFadeDistanceText = EditorGUIUtility.TrTextContent(\"Near fade\", \"Camera near fade distance.\");\n            public static GUIContent cameraFarFadeDistanceText = EditorGUIUtility.TrTextContent(\"Far fade\", \"Camera far fade distance.\");\n\n            public static GUIContent emissionEnabled = EditorGUIUtility.TrTextContent(\"Emission\");\n\n            public static GUIContent blendingOptionsText = EditorGUIUtility.TrTextContent(\"Blending Options\");\n            public static GUIContent mainOptionsText = EditorGUIUtility.TrTextContent(\"Main Options\");\n            public static GUIContent mapsOptionsText = EditorGUIUtility.TrTextContent(\"Maps\");\n            public static GUIContent advancedText = EditorGUIUtility.TrTextContent(\"Advanced Options\");\n            public static GUIContent requiredVertexStreamsText = EditorGUIUtility.TrTextContent(\"Required Vertex Streams\");\n\n            public static GUIContent streamPositionText = EditorGUIUtility.TrTextContent(\"Position (POSITION.xyz)\");\n            public static GUIContent streamNormalText = EditorGUIUtility.TrTextContent(\"Normal (NORMAL.xyz)\");\n            public static GUIContent streamColorText = EditorGUIUtility.TrTextContent(\"Color (COLOR.xyzw)\");\n            public static GUIContent streamColorInstancedText = EditorGUIUtility.TrTextContent(\"Color (INSTANCED0.xyzw)\");\n            public static GUIContent streamUVText = EditorGUIUtility.TrTextContent(\"UV (TEXCOORD0.xy)\");\n            public static GUIContent streamUV2Text = EditorGUIUtility.TrTextContent(\"UV2 (TEXCOORD0.zw)\");\n            public static GUIContent streamAnimBlendText = EditorGUIUtility.TrTextContent(\"AnimBlend (TEXCOORD1.x)\");\n            public static GUIContent streamAnimFrameText = EditorGUIUtility.TrTextContent(\"AnimFrame (INSTANCED1.x)\");\n            public static GUIContent streamTangentText = EditorGUIUtility.TrTextContent(\"Tangent (TANGENT.xyzw)\");\n\n            public static GUIContent streamApplyToAllSystemsText = EditorGUIUtility.TrTextContent(\"Apply to Systems\", \"Apply the vertex stream layout to all Particle Systems using this material\");\n\n            public static string undoApplyCustomVertexStreams = L10n.Tr(\"Apply custom vertex streams from material\");\n        }\n\n        MaterialProperty blendMode = null;\n        MaterialProperty colorMode = null;\n        MaterialProperty flipbookMode = null;\n        MaterialProperty cullMode = null;\n        MaterialProperty distortionEnabled = null;\n        MaterialProperty distortionStrength = null;\n        MaterialProperty distortionBlend = null;\n        MaterialProperty albedoMap = null;\n        MaterialProperty albedoColor = null;\n        MaterialProperty alphaCutoff = null;\n        MaterialProperty metallicMap = null;\n        MaterialProperty metallic = null;\n        MaterialProperty smoothness = null;\n        MaterialProperty bumpScale = null;\n        MaterialProperty bumpMap = null;\n        MaterialProperty emissionEnabled = null;\n        MaterialProperty emissionColorForRendering = null;\n        MaterialProperty emissionMap = null;\n        MaterialProperty softParticlesEnabled = null;\n        MaterialProperty cameraFadingEnabled = null;\n        MaterialProperty softParticlesNearFadeDistance = null;\n        MaterialProperty softParticlesFarFadeDistance = null;\n        MaterialProperty cameraNearFadeDistance = null;\n        MaterialProperty cameraFarFadeDistance = null;\n\n        MaterialEditor m_MaterialEditor;\n\n        List<ParticleSystemRenderer> m_RenderersUsingThisMaterial = new List<ParticleSystemRenderer>();\n\n        bool m_FirstTimeApply = true;\n\n        public void FindProperties(MaterialProperty[] props)\n        {\n            blendMode = FindProperty(\"_Mode\", props);\n            colorMode = FindProperty(\"_ColorMode\", props, false);\n            flipbookMode = FindProperty(\"_FlipbookMode\", props);\n            cullMode = FindProperty(\"_Cull\", props);\n            distortionEnabled = FindProperty(\"_DistortionEnabled\", props);\n            distortionStrength = FindProperty(\"_DistortionStrength\", props);\n            distortionBlend = FindProperty(\"_DistortionBlend\", props);\n            albedoMap = FindProperty(\"_MainTex\", props);\n            albedoColor = FindProperty(\"_Color\", props);\n            alphaCutoff = FindProperty(\"_Cutoff\", props);\n            metallicMap = FindProperty(\"_MetallicGlossMap\", props, false);\n            metallic = FindProperty(\"_Metallic\", props, false);\n            smoothness = FindProperty(\"_Glossiness\", props, false);\n            bumpScale = FindProperty(\"_BumpScale\", props);\n            bumpMap = FindProperty(\"_BumpMap\", props);\n            emissionEnabled = FindProperty(\"_EmissionEnabled\", props);\n            emissionColorForRendering = FindProperty(\"_EmissionColor\", props);\n            emissionMap = FindProperty(\"_EmissionMap\", props);\n            softParticlesEnabled = FindProperty(\"_SoftParticlesEnabled\", props);\n            cameraFadingEnabled = FindProperty(\"_CameraFadingEnabled\", props);\n            softParticlesNearFadeDistance = FindProperty(\"_SoftParticlesNearFadeDistance\", props);\n            softParticlesFarFadeDistance = FindProperty(\"_SoftParticlesFarFadeDistance\", props);\n            cameraNearFadeDistance = FindProperty(\"_CameraNearFadeDistance\", props);\n            cameraFarFadeDistance = FindProperty(\"_CameraFarFadeDistance\", props);\n        }\n\n        public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)\n        {\n            FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly\n            m_MaterialEditor = materialEditor;\n            Material material = materialEditor.target as Material;\n\n            if (m_FirstTimeApply)\n            {\n                CacheRenderersUsingThisMaterial(material);\n                m_FirstTimeApply = false;\n            }\n\n            ShaderPropertiesGUI(material);\n        }\n\n        public void ShaderPropertiesGUI(Material material)\n        {\n            // Use default labelWidth\n            EditorGUIUtility.labelWidth = 0f;\n\n            {\n                GUILayout.Label(Styles.blendingOptionsText, EditorStyles.boldLabel);\n\n                bool blendModeChanged = BlendModePopup();\n                ColorModePopup();\n\n                EditorGUILayout.Space();\n                GUILayout.Label(Styles.mainOptionsText, EditorStyles.boldLabel);\n\n                FlipbookBlendingPopup();\n                TwoSidedPopup(material);\n                FadingPopup(material);\n                DistortionPopup(material);\n\n                EditorGUILayout.Space();\n                GUILayout.Label(Styles.mapsOptionsText, EditorStyles.boldLabel);\n\n                DoAlbedoArea(material);\n                DoSpecularMetallicArea(material);\n                DoNormalMapArea(material);\n                DoEmissionArea(material);\n\n                if (!flipbookMode.hasMixedValue && (FlipbookMode)flipbookMode.floatValue != FlipbookMode.Blended)\n                {\n                    EditorGUI.BeginChangeCheck();\n                    m_MaterialEditor.TextureScaleOffsetProperty(albedoMap);\n                    if (EditorGUI.EndChangeCheck())\n                        emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake\n                }\n\n                EditorGUILayout.Space();\n                GUILayout.Label(Styles.advancedText, EditorStyles.boldLabel);\n\n                m_MaterialEditor.RenderQueueField();\n\n                if (blendModeChanged)\n                {\n                    foreach (var obj in blendMode.targets)\n                        SetupMaterialWithBlendMode((Material)obj, (BlendMode)((Material)obj).GetFloat(\"_Mode\"), true);\n                }\n            }\n\n            EditorGUILayout.Space();\n\n            GUILayout.Label(Styles.requiredVertexStreamsText, EditorStyles.boldLabel);\n            DoVertexStreamsArea(material);\n        }\n\n        public override void OnClosed(Material material)\n        {\n            material.SetShaderPassEnabled(\"Always\", true); // because grabpass used to use the always pass, we need to force it on, to correct old materials (case 1402353)\n            material.SetShaderPassEnabled(\"GrabPass\", true);\n        }\n\n        public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)\n        {\n            // Sync the lighting flag for the unlit shader\n            if (newShader.name.Contains(\"Unlit\"))\n                material.SetFloat(\"_LightingEnabled\", 0.0f);\n            else\n                material.SetFloat(\"_LightingEnabled\", 1.0f);\n\n            // _Emission property is lost after assigning Standard shader to the material\n            // thus transfer it before assigning the new shader\n            if (material.HasProperty(\"_Emission\"))\n            {\n                material.SetColor(\"_EmissionColor\", material.GetColor(\"_Emission\"));\n            }\n\n            base.AssignNewShaderToMaterial(material, oldShader, newShader);\n\n            if (oldShader == null || !oldShader.name.Contains(\"Legacy Shaders/\"))\n            {\n                SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat(\"_Mode\"), true);\n                return;\n            }\n\n            BlendMode blendMode = BlendMode.Opaque;\n            if (oldShader.name.Contains(\"/Transparent/Cutout/\"))\n            {\n                blendMode = BlendMode.Cutout;\n            }\n            else if (oldShader.name.Contains(\"/Transparent/\"))\n            {\n                // NOTE: legacy shaders did not provide physically based transparency\n                // therefore Fade mode\n                blendMode = BlendMode.Fade;\n            }\n            material.SetFloat(\"_Mode\", (float)blendMode);\n\n            SetupMaterialWithBlendMode(material, blendMode, true);\n        }\n\n        bool BlendModePopup()\n        {\n            EditorGUI.showMixedValue = blendMode.hasMixedValue;\n            var mode = (BlendMode)blendMode.floatValue;\n\n            EditorGUI.BeginChangeCheck();\n            mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);\n            bool result = EditorGUI.EndChangeCheck();\n            if (result)\n            {\n                m_MaterialEditor.RegisterPropertyChangeUndo(\"Rendering Mode\");\n                blendMode.floatValue = (float)mode;\n            }\n\n            EditorGUI.showMixedValue = false;\n            return result;\n        }\n\n        void ColorModePopup()\n        {\n            if (colorMode != null)\n            {\n                EditorGUI.showMixedValue = colorMode.hasMixedValue;\n                var mode = (ColorMode)colorMode.floatValue;\n\n                EditorGUI.BeginChangeCheck();\n                mode = (ColorMode)EditorGUILayout.Popup(Styles.colorMode, (int)mode, Styles.colorNames);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_MaterialEditor.RegisterPropertyChangeUndo(\"Color Mode\");\n                    colorMode.floatValue = (float)mode;\n                }\n\n                EditorGUI.showMixedValue = false;\n            }\n        }\n\n        void FlipbookBlendingPopup()\n        {\n            EditorGUI.showMixedValue = flipbookMode.hasMixedValue;\n            var enabled = (flipbookMode.floatValue == (float)FlipbookMode.Blended);\n\n            EditorGUI.BeginChangeCheck();\n            enabled = EditorGUILayout.Toggle(Styles.flipbookBlending, enabled);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_MaterialEditor.RegisterPropertyChangeUndo(\"Flip-Book Mode\");\n                flipbookMode.floatValue = enabled ? (float)FlipbookMode.Blended : (float)FlipbookMode.Simple;\n            }\n\n            EditorGUI.showMixedValue = false;\n        }\n\n        void TwoSidedPopup(Material material)\n        {\n            EditorGUI.showMixedValue = cullMode.hasMixedValue;\n            var enabled = (cullMode.floatValue == (float)UnityEngine.Rendering.CullMode.Off);\n\n            EditorGUI.BeginChangeCheck();\n            enabled = EditorGUILayout.Toggle(Styles.twoSidedEnabled, enabled);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_MaterialEditor.RegisterPropertyChangeUndo(\"Two Sided Enabled\");\n                cullMode.floatValue = enabled ? (float)UnityEngine.Rendering.CullMode.Off : (float)UnityEngine.Rendering.CullMode.Back;\n            }\n\n            EditorGUI.showMixedValue = false;\n        }\n\n        void FadingPopup(Material material)\n        {\n            // Z write doesn't work with fading\n            bool hasZWrite = (material.GetFloat(\"_ZWrite\") > 0.0f);\n            if (!hasZWrite)\n            {\n                // Soft Particles\n                {\n                    EditorGUI.showMixedValue = softParticlesEnabled.hasMixedValue;\n                    var enabled = softParticlesEnabled.floatValue;\n\n                    EditorGUI.BeginChangeCheck();\n                    enabled = EditorGUILayout.Toggle(Styles.softParticlesEnabled, enabled != 0.0f) ? 1.0f : 0.0f;\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        m_MaterialEditor.RegisterPropertyChangeUndo(\"Soft Particles Enabled\");\n                        softParticlesEnabled.floatValue = enabled;\n                    }\n\n                    if (enabled != 0.0f)\n                    {\n                        int indentation = 2;\n                        m_MaterialEditor.ShaderProperty(softParticlesNearFadeDistance, Styles.softParticlesNearFadeDistanceText, indentation);\n                        m_MaterialEditor.ShaderProperty(softParticlesFarFadeDistance, Styles.softParticlesFarFadeDistanceText, indentation);\n                    }\n                }\n\n                // Camera Fading\n                {\n                    EditorGUI.showMixedValue = cameraFadingEnabled.hasMixedValue;\n                    var enabled = cameraFadingEnabled.floatValue;\n\n                    EditorGUI.BeginChangeCheck();\n                    enabled = EditorGUILayout.Toggle(Styles.cameraFadingEnabled, enabled != 0.0f) ? 1.0f : 0.0f;\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        m_MaterialEditor.RegisterPropertyChangeUndo(\"Camera Fading Enabled\");\n                        cameraFadingEnabled.floatValue = enabled;\n                    }\n\n                    if (enabled != 0.0f)\n                    {\n                        int indentation = 2;\n                        m_MaterialEditor.ShaderProperty(cameraNearFadeDistance, Styles.cameraNearFadeDistanceText, indentation);\n                        m_MaterialEditor.ShaderProperty(cameraFarFadeDistance, Styles.cameraFarFadeDistanceText, indentation);\n                    }\n                }\n\n                EditorGUI.showMixedValue = false;\n            }\n        }\n\n        void DistortionPopup(Material material)\n        {\n            // Z write doesn't work with distortion\n            bool hasZWrite = (material.GetFloat(\"_ZWrite\") > 0.0f);\n            if (!hasZWrite)\n            {\n                EditorGUI.showMixedValue = distortionEnabled.hasMixedValue;\n                var enabled = (distortionEnabled.floatValue != 0.0f);\n\n                EditorGUI.BeginChangeCheck();\n                enabled = EditorGUILayout.Toggle(Styles.distortionEnabled, enabled);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_MaterialEditor.RegisterPropertyChangeUndo(\"Distortion Enabled\");\n                    distortionEnabled.floatValue = enabled ? 1.0f : 0.0f;\n                }\n\n                if (enabled)\n                {\n                    int indentation = 2;\n                    m_MaterialEditor.ShaderProperty(distortionStrength, Styles.distortionStrengthText, indentation);\n                    m_MaterialEditor.ShaderProperty(distortionBlend, Styles.distortionBlendText, indentation);\n                }\n\n                EditorGUI.showMixedValue = false;\n            }\n        }\n\n        void DoAlbedoArea(Material material)\n        {\n            m_MaterialEditor.TexturePropertyWithHDRColor(Styles.albedoText, albedoMap, albedoColor, true);\n            if (((BlendMode)material.GetFloat(\"_Mode\") == BlendMode.Cutout))\n            {\n                m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText, MaterialEditor.kMiniTextureFieldLabelIndentLevel);\n            }\n        }\n\n        void DoEmissionArea(Material material)\n        {\n            // Emission\n            EditorGUI.showMixedValue = emissionEnabled.hasMixedValue;\n            var enabled = (emissionEnabled.floatValue != 0.0f);\n\n            EditorGUI.BeginChangeCheck();\n            enabled = EditorGUILayout.Toggle(Styles.emissionEnabled, enabled);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_MaterialEditor.RegisterPropertyChangeUndo(\"Emission Enabled\");\n                emissionEnabled.floatValue = enabled ? 1.0f : 0.0f;\n            }\n\n            if (enabled)\n            {\n                bool hadEmissionTexture = emissionMap.textureValue != null;\n\n                // Texture and HDR color controls\n                m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, false);\n\n                // If texture was assigned and color was black set color to white\n                float brightness = emissionColorForRendering.colorValue.maxColorComponent;\n                if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f)\n                    emissionColorForRendering.colorValue = Color.white;\n            }\n        }\n\n        void DoSpecularMetallicArea(Material material)\n        {\n            if (metallicMap == null)\n                return;\n\n            bool useLighting = (material.GetFloat(\"_LightingEnabled\") > 0.0f);\n            if (useLighting)\n            {\n                bool hasGlossMap = metallicMap.textureValue != null;\n                m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap, hasGlossMap ? null : metallic);\n\n                int indentation = 2; // align with labels of texture properties\n                bool showSmoothnessScale = hasGlossMap;\n                m_MaterialEditor.ShaderProperty(smoothness, showSmoothnessScale ? Styles.smoothnessScaleText : Styles.smoothnessText, indentation);\n            }\n        }\n\n        void DoNormalMapArea(Material material)\n        {\n            bool hasZWrite = (material.GetFloat(\"_ZWrite\") > 0.0f);\n            bool useLighting = (material.GetFloat(\"_LightingEnabled\") > 0.0f);\n            bool useDistortion = (material.GetFloat(\"_DistortionEnabled\") > 0.0f) && !hasZWrite;\n            if (useLighting || useDistortion)\n            {\n                m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null);\n            }\n        }\n\n        void DoVertexStreamsArea(Material material)\n        {\n            // Display list of streams required to make this shader work\n            bool useLighting = (material.GetFloat(\"_LightingEnabled\") > 0.0f);\n            bool useFlipbookBlending = (material.GetFloat(\"_FlipbookMode\") > 0.0f);\n            bool useTangents = useLighting && material.GetTexture(\"_BumpMap\");\n\n            bool useGPUInstancing = ShaderUtil.HasProceduralInstancing(material.shader);\n            if (useGPUInstancing && m_RenderersUsingThisMaterial.Count > 0)\n            {\n                if (!m_RenderersUsingThisMaterial[0].enableGPUInstancing || m_RenderersUsingThisMaterial[0].renderMode != ParticleSystemRenderMode.Mesh)\n                    useGPUInstancing = false;\n            }\n\n            GUILayout.Label(Styles.streamPositionText, EditorStyles.label);\n\n            if (useLighting)\n                GUILayout.Label(Styles.streamNormalText, EditorStyles.label);\n\n            GUILayout.Label(useGPUInstancing ? Styles.streamColorInstancedText : Styles.streamColorText, EditorStyles.label);\n            GUILayout.Label(Styles.streamUVText, EditorStyles.label);\n\n            if (useTangents)\n                GUILayout.Label(Styles.streamTangentText, EditorStyles.label);\n\n            if (useGPUInstancing)\n            {\n                GUILayout.Label(Styles.streamAnimFrameText, EditorStyles.label);\n            }\n            else if (useFlipbookBlending && !useGPUInstancing)\n            {\n                GUILayout.Label(Styles.streamUV2Text, EditorStyles.label);\n                GUILayout.Label(Styles.streamAnimBlendText, EditorStyles.label);\n            }\n\n            // Build the list of expected vertex streams\n            List<ParticleSystemVertexStream> streams = new List<ParticleSystemVertexStream>();\n            streams.Add(ParticleSystemVertexStream.Position);\n\n            if (useLighting)\n                streams.Add(ParticleSystemVertexStream.Normal);\n\n            streams.Add(ParticleSystemVertexStream.Color);\n            streams.Add(ParticleSystemVertexStream.UV);\n\n            if (useTangents)\n                streams.Add(ParticleSystemVertexStream.Tangent);\n\n            List<ParticleSystemVertexStream> instancedStreams = new List<ParticleSystemVertexStream>(streams);\n\n            if (useGPUInstancing)\n            {\n                instancedStreams.Add(ParticleSystemVertexStream.AnimFrame);\n            }\n            if (useFlipbookBlending)\n            {\n                streams.Add(ParticleSystemVertexStream.UV2);\n                streams.Add(ParticleSystemVertexStream.AnimBlend);\n            }\n\n            // Set the streams on all systems using this material\n            if (GUILayout.Button(Styles.streamApplyToAllSystemsText, EditorStyles.miniButton, GUILayout.ExpandWidth(false)))\n            {\n                Undo.RecordObjects(m_RenderersUsingThisMaterial.Where(r => r != null).ToArray(), Styles.undoApplyCustomVertexStreams);\n\n                foreach (ParticleSystemRenderer renderer in m_RenderersUsingThisMaterial)\n                {\n                    if (renderer != null)\n                    {\n                        if (useGPUInstancing && renderer.renderMode == ParticleSystemRenderMode.Mesh && renderer.supportsMeshInstancing)\n                            renderer.SetActiveVertexStreams(instancedStreams);\n                        else\n                            renderer.SetActiveVertexStreams(streams);\n                    }\n                }\n            }\n\n            // Display a warning if any renderers have incorrect vertex streams\n            string Warnings = \"\";\n            List<ParticleSystemVertexStream> rendererStreams = new List<ParticleSystemVertexStream>();\n            foreach (ParticleSystemRenderer renderer in m_RenderersUsingThisMaterial)\n            {\n                if (renderer != null)\n                {\n                    renderer.GetActiveVertexStreams(rendererStreams);\n\n                    bool streamsValid;\n                    if (useGPUInstancing && renderer.renderMode == ParticleSystemRenderMode.Mesh && renderer.supportsMeshInstancing)\n                        streamsValid = CompareVertexStreams(rendererStreams, instancedStreams);\n                    else\n                        streamsValid = CompareVertexStreams(rendererStreams, streams);\n\n                    if (!streamsValid)\n                        Warnings += \"  \" + renderer.name + \"\\n\";\n                }\n            }\n            if (Warnings != \"\")\n            {\n                EditorGUILayout.HelpBox(\"The following Particle System Renderers are using this material with incorrect Vertex Streams:\\n\" + Warnings + \"Use the Apply to Systems button to fix this\", MessageType.Warning, true);\n            }\n\n            EditorGUILayout.Space();\n        }\n\n        private static bool CompareVertexStreams(IEnumerable<ParticleSystemVertexStream> a, IEnumerable<ParticleSystemVertexStream> b)\n        {\n            var differenceA = a.Except(b);\n            var differenceB = b.Except(a);\n            var difference = differenceA.Union(differenceB).Distinct();\n\n            if (!difference.Any())\n                return true;\n\n            // If normals are the only difference, ignore them, because the default particle streams include normals, to make it easy for users to switch between lit and unlit\n            if (difference.Count() == 1)\n            {\n                if (difference.First() == ParticleSystemVertexStream.Normal)\n                    return true;\n            }\n\n            return false;\n        }\n\n        public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode, bool overrideRenderQueue)\n        {\n            int minRenderQueue = -1;\n            int maxRenderQueue = 5000;\n            int defaultRenderQueue = -1;\n\n            switch (blendMode)\n            {\n                case BlendMode.Opaque:\n                    material.SetOverrideTag(\"RenderType\", \"\");\n                    material.SetFloat(\"_BlendOp\", (float)UnityEngine.Rendering.BlendOp.Add);\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.One);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.Zero);\n                    material.SetFloat(\"_ZWrite\", 1.0f);\n                    material.DisableKeyword(\"_ALPHATEST_ON\");\n                    material.DisableKeyword(\"_ALPHABLEND_ON\");\n                    material.DisableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    material.DisableKeyword(\"_ALPHAMODULATE_ON\");\n                    minRenderQueue = -1;\n                    maxRenderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest - 1;\n                    defaultRenderQueue = -1;\n                    break;\n                case BlendMode.Cutout:\n                    material.SetOverrideTag(\"RenderType\", \"TransparentCutout\");\n                    material.SetFloat(\"_BlendOp\", (float)UnityEngine.Rendering.BlendOp.Add);\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.One);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.Zero);\n                    material.SetFloat(\"_ZWrite\", 1.0f);\n                    material.EnableKeyword(\"_ALPHATEST_ON\");\n                    material.DisableKeyword(\"_ALPHABLEND_ON\");\n                    material.DisableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    material.DisableKeyword(\"_ALPHAMODULATE_ON\");\n                    minRenderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;\n                    maxRenderQueue = (int)UnityEngine.Rendering.RenderQueue.GeometryLast;\n                    defaultRenderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;\n                    break;\n                case BlendMode.Fade:\n                    material.SetOverrideTag(\"RenderType\", \"Transparent\");\n                    material.SetFloat(\"_BlendOp\", (float)UnityEngine.Rendering.BlendOp.Add);\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);\n                    material.SetFloat(\"_ZWrite\", 0.0f);\n                    material.DisableKeyword(\"_ALPHATEST_ON\");\n                    material.EnableKeyword(\"_ALPHABLEND_ON\");\n                    material.DisableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    material.DisableKeyword(\"_ALPHAMODULATE_ON\");\n                    minRenderQueue = (int)UnityEngine.Rendering.RenderQueue.GeometryLast + 1;\n                    maxRenderQueue = (int)UnityEngine.Rendering.RenderQueue.Overlay - 1;\n                    defaultRenderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;\n                    break;\n                case BlendMode.Transparent:\n                    material.SetOverrideTag(\"RenderType\", \"Transparent\");\n                    material.SetFloat(\"_BlendOp\", (float)UnityEngine.Rendering.BlendOp.Add);\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.One);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);\n                    material.SetFloat(\"_ZWrite\", 0.0f);\n                    material.DisableKeyword(\"_ALPHATEST_ON\");\n                    material.DisableKeyword(\"_ALPHABLEND_ON\");\n                    material.EnableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    material.DisableKeyword(\"_ALPHAMODULATE_ON\");\n                    minRenderQueue = (int)UnityEngine.Rendering.RenderQueue.GeometryLast + 1;\n                    maxRenderQueue = (int)UnityEngine.Rendering.RenderQueue.Overlay - 1;\n                    defaultRenderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;\n                    break;\n                case BlendMode.Additive:\n                    material.SetOverrideTag(\"RenderType\", \"Transparent\");\n                    material.SetFloat(\"_BlendOp\", (float)UnityEngine.Rendering.BlendOp.Add);\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.One);\n                    material.SetFloat(\"_ZWrite\", 0.0f);\n                    material.DisableKeyword(\"_ALPHATEST_ON\");\n                    material.EnableKeyword(\"_ALPHABLEND_ON\");\n                    material.DisableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    material.DisableKeyword(\"_ALPHAMODULATE_ON\");\n                    minRenderQueue = (int)UnityEngine.Rendering.RenderQueue.GeometryLast + 1;\n                    maxRenderQueue = (int)UnityEngine.Rendering.RenderQueue.Overlay - 1;\n                    defaultRenderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;\n                    break;\n                case BlendMode.Subtractive:\n                    material.SetOverrideTag(\"RenderType\", \"Transparent\");\n                    material.SetFloat(\"_BlendOp\", (float)UnityEngine.Rendering.BlendOp.ReverseSubtract);\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.One);\n                    material.SetFloat(\"_ZWrite\", 0.0f);\n                    material.DisableKeyword(\"_ALPHATEST_ON\");\n                    material.EnableKeyword(\"_ALPHABLEND_ON\");\n                    material.DisableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    material.DisableKeyword(\"_ALPHAMODULATE_ON\");\n                    minRenderQueue = (int)UnityEngine.Rendering.RenderQueue.GeometryLast + 1;\n                    maxRenderQueue = (int)UnityEngine.Rendering.RenderQueue.Overlay - 1;\n                    defaultRenderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;\n                    break;\n                case BlendMode.Modulate:\n                    material.SetOverrideTag(\"RenderType\", \"Transparent\");\n                    material.SetFloat(\"_BlendOp\", (float)UnityEngine.Rendering.BlendOp.Add);\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.DstColor);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);\n                    material.SetFloat(\"_ZWrite\", 0.0f);\n                    material.DisableKeyword(\"_ALPHATEST_ON\");\n                    material.DisableKeyword(\"_ALPHABLEND_ON\");\n                    material.DisableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    material.EnableKeyword(\"_ALPHAMODULATE_ON\");\n                    minRenderQueue = (int)UnityEngine.Rendering.RenderQueue.GeometryLast + 1;\n                    maxRenderQueue = (int)UnityEngine.Rendering.RenderQueue.Overlay - 1;\n                    defaultRenderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;\n                    break;\n            }\n\n            if (overrideRenderQueue || material.renderQueue < minRenderQueue || material.renderQueue > maxRenderQueue)\n            {\n                if (!overrideRenderQueue)\n                    Debug.LogFormat(LogType.Log, LogOption.NoStacktrace, null, \"Render queue value outside of the allowed range ({0} - {1}) for selected Blend mode, resetting render queue to default\", minRenderQueue, maxRenderQueue);\n                material.renderQueue = defaultRenderQueue;\n            }\n        }\n\n        public static void SetupMaterialWithColorMode(Material material, ColorMode colorMode)\n        {\n            switch (colorMode)\n            {\n                case ColorMode.Multiply:\n                    material.DisableKeyword(\"_COLOROVERLAY_ON\");\n                    material.DisableKeyword(\"_COLORCOLOR_ON\");\n                    material.DisableKeyword(\"_COLORADDSUBDIFF_ON\");\n                    break;\n                case ColorMode.Overlay:\n                    material.DisableKeyword(\"_COLORCOLOR_ON\");\n                    material.DisableKeyword(\"_COLORADDSUBDIFF_ON\");\n                    material.EnableKeyword(\"_COLOROVERLAY_ON\");\n                    break;\n                case ColorMode.Color:\n                    material.DisableKeyword(\"_COLOROVERLAY_ON\");\n                    material.DisableKeyword(\"_COLORADDSUBDIFF_ON\");\n                    material.EnableKeyword(\"_COLORCOLOR_ON\");\n                    break;\n                case ColorMode.Difference:\n                    material.DisableKeyword(\"_COLOROVERLAY_ON\");\n                    material.DisableKeyword(\"_COLORCOLOR_ON\");\n                    material.EnableKeyword(\"_COLORADDSUBDIFF_ON\");\n                    material.SetVector(\"_ColorAddSubDiff\", new Vector4(-1.0f, 1.0f, 0.0f, 0.0f));\n                    break;\n                case ColorMode.Additive:\n                    material.DisableKeyword(\"_COLOROVERLAY_ON\");\n                    material.DisableKeyword(\"_COLORCOLOR_ON\");\n                    material.EnableKeyword(\"_COLORADDSUBDIFF_ON\");\n                    material.SetVector(\"_ColorAddSubDiff\", new Vector4(1.0f, 0.0f, 0.0f, 0.0f));\n                    break;\n                case ColorMode.Subtractive:\n                    material.DisableKeyword(\"_COLOROVERLAY_ON\");\n                    material.DisableKeyword(\"_COLORCOLOR_ON\");\n                    material.EnableKeyword(\"_COLORADDSUBDIFF_ON\");\n                    material.SetVector(\"_ColorAddSubDiff\", new Vector4(-1.0f, 0.0f, 0.0f, 0.0f));\n                    break;\n            }\n        }\n\n        void SetMaterialKeywords(Material material)\n        {\n            // Z write doesn't work with distortion/fading\n            bool hasZWrite = (material.GetFloat(\"_ZWrite\") > 0.0f);\n\n            // Lit shader?\n            bool useLighting = (material.GetFloat(\"_LightingEnabled\") > 0.0f);\n\n            // Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation\n            // (MaterialProperty value might come from renderer material property block)\n            bool useDistortion = !hasZWrite && (material.GetFloat(\"_DistortionEnabled\") > 0.0f);\n            SetKeyword(material, \"_NORMALMAP\", (useLighting || useDistortion) && material.GetTexture(\"_BumpMap\"));\n            SetKeyword(material, \"_METALLICGLOSSMAP\", useLighting && material.GetTexture(\"_MetallicGlossMap\"));\n\n            material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.None;\n            SetKeyword(material, \"_EMISSION\", material.GetFloat(\"_EmissionEnabled\") > 0.0f);\n\n            // Set the define for flipbook blending\n            bool useFlipbookBlending = (material.GetFloat(\"_FlipbookMode\") > 0.0f);\n            SetKeyword(material, \"_REQUIRE_UV2\", useFlipbookBlending);\n\n            // Clamp fade distances\n            bool useSoftParticles = (material.GetFloat(\"_SoftParticlesEnabled\") > 0.0f);\n            bool useCameraFading = (material.GetFloat(\"_CameraFadingEnabled\") > 0.0f);\n            float softParticlesNearFadeDistance = material.GetFloat(\"_SoftParticlesNearFadeDistance\");\n            float softParticlesFarFadeDistance = material.GetFloat(\"_SoftParticlesFarFadeDistance\");\n            float cameraNearFadeDistance = material.GetFloat(\"_CameraNearFadeDistance\");\n            float cameraFarFadeDistance = material.GetFloat(\"_CameraFarFadeDistance\");\n\n            if (softParticlesNearFadeDistance < 0.0f)\n            {\n                softParticlesNearFadeDistance = 0.0f;\n                material.SetFloat(\"_SoftParticlesNearFadeDistance\", 0.0f);\n            }\n            if (softParticlesFarFadeDistance < 0.0f)\n            {\n                softParticlesFarFadeDistance = 0.0f;\n                material.SetFloat(\"_SoftParticlesFarFadeDistance\", 0.0f);\n            }\n            if (cameraNearFadeDistance < 0.0f)\n            {\n                cameraNearFadeDistance = 0.0f;\n                material.SetFloat(\"_CameraNearFadeDistance\", 0.0f);\n            }\n            if (cameraFarFadeDistance < 0.0f)\n            {\n                cameraFarFadeDistance = 0.0f;\n                material.SetFloat(\"_CameraFarFadeDistance\", 0.0f);\n            }\n\n            // Set the define for fading\n            bool useFading = (useSoftParticles || useCameraFading) && !hasZWrite;\n            SetKeyword(material, \"_FADING_ON\", useFading);\n            if (useSoftParticles)\n                material.SetVector(\"_SoftParticleFadeParams\", new Vector4(softParticlesNearFadeDistance, 1.0f / (softParticlesFarFadeDistance - softParticlesNearFadeDistance), 0.0f, 0.0f));\n            else\n                material.SetVector(\"_SoftParticleFadeParams\", new Vector4(0.0f, 0.0f, 0.0f, 0.0f));\n            if (useCameraFading)\n                material.SetVector(\"_CameraFadeParams\", new Vector4(cameraNearFadeDistance, 1.0f / (cameraFarFadeDistance - cameraNearFadeDistance), 0.0f, 0.0f));\n            else\n                material.SetVector(\"_CameraFadeParams\", new Vector4(0.0f, Mathf.Infinity, 0.0f, 0.0f));\n\n            // Set the define for distortion + grabpass\n            SetKeyword(material, \"EFFECT_BUMP\", useDistortion);\n            material.SetShaderPassEnabled(\"Always\", true); // because grabpass used to use the always pass, we need to force it on, to correct old materials (case 1402353)\n            material.SetShaderPassEnabled(\"GrabPass\", useDistortion);\n            if (useDistortion)\n                material.SetFloat(\"_DistortionStrengthScaled\", material.GetFloat(\"_DistortionStrength\") * 0.1f);   // more friendly number scale than 1 unit per size of the screen\n        }\n\n        override public void ValidateMaterial(Material material)\n        {\n            SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat(\"_Mode\"), false);\n            if (material.HasProperty(\"_ColorMode\"))\n                SetupMaterialWithColorMode(material, (ColorMode)material.GetFloat(\"_ColorMode\"));\n            SetMaterialKeywords(material);\n        }\n\n        void CacheRenderersUsingThisMaterial(Material material)\n        {\n            m_RenderersUsingThisMaterial.Clear();\n\n            ParticleSystemRenderer[] renderers = Resources.FindObjectsOfTypeAll(typeof(ParticleSystemRenderer)) as ParticleSystemRenderer[];\n            foreach (ParticleSystemRenderer renderer in renderers)\n            {\n                var go = renderer.gameObject;\n                if (go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave)\n                    continue;\n\n                if (renderer.sharedMaterial == material)\n                    m_RenderersUsingThisMaterial.Add(renderer);\n            }\n        }\n\n        static void SetKeyword(Material m, string keyword, bool state)\n        {\n            if (state)\n                m.EnableKeyword(keyword);\n            else\n                m.DisableKeyword(keyword);\n        }\n    }\n} // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/Inspector/StandardShaderGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class StandardShaderGUI : ShaderGUI\n    {\n        private enum WorkflowMode\n        {\n            Specular,\n            Metallic,\n            Dielectric\n        }\n\n        public enum BlendMode\n        {\n            Opaque,\n            Cutout,\n            Fade,   // Old school alpha-blending mode, fresnel does not affect amount of transparency\n            Transparent // Physically plausible transparency mode, implemented as alpha pre-multiply\n        }\n\n        public enum SmoothnessMapChannel\n        {\n            SpecularMetallicAlpha,\n            AlbedoAlpha,\n        }\n\n        private static class Styles\n        {\n            public static GUIContent uvSetLabel = EditorGUIUtility.TrTextContent(\"UV Set\");\n\n            public static GUIContent albedoText = EditorGUIUtility.TrTextContent(\"Albedo\", \"Albedo (RGB) and Transparency (A)\");\n            public static GUIContent alphaCutoffText = EditorGUIUtility.TrTextContent(\"Alpha Cutoff\", \"Threshold for alpha cutoff\");\n            public static GUIContent specularMapText = EditorGUIUtility.TrTextContent(\"Specular\", \"Specular (RGB) and Smoothness (A)\");\n            public static GUIContent metallicMapText = EditorGUIUtility.TrTextContent(\"Metallic\", \"Metallic (R) and Smoothness (A)\");\n            public static GUIContent smoothnessText = EditorGUIUtility.TrTextContent(\"Smoothness\", \"Smoothness value\");\n            public static GUIContent smoothnessScaleText = EditorGUIUtility.TrTextContent(\"Smoothness\", \"Smoothness scale factor\");\n            public static GUIContent smoothnessMapChannelText = EditorGUIUtility.TrTextContent(\"Source\", \"Smoothness texture and channel\");\n            public static GUIContent highlightsText = EditorGUIUtility.TrTextContent(\"Specular Highlights\", \"Specular Highlights\");\n            public static GUIContent reflectionsText = EditorGUIUtility.TrTextContent(\"Reflections\", \"Glossy Reflections\");\n            public static GUIContent normalMapText = EditorGUIUtility.TrTextContent(\"Normal Map\", \"Normal Map\");\n            public static GUIContent heightMapText = EditorGUIUtility.TrTextContent(\"Height Map\", \"Height Map (G)\");\n            public static GUIContent occlusionText = EditorGUIUtility.TrTextContent(\"Occlusion\", \"Occlusion (G)\");\n            public static GUIContent emissionText = EditorGUIUtility.TrTextContent(\"Color\", \"Emission (RGB)\");\n            public static GUIContent detailMaskText = EditorGUIUtility.TrTextContent(\"Detail Mask\", \"Mask for Secondary Maps (A)\");\n            public static GUIContent detailAlbedoText = EditorGUIUtility.TrTextContent(\"Detail Albedo x2\", \"Albedo (RGB) multiplied by 2\");\n            public static GUIContent detailNormalMapText = EditorGUIUtility.TrTextContent(\"Normal Map\", \"Normal Map\");\n\n            public static string primaryMapsText = \"Main Maps\";\n            public static string secondaryMapsText = \"Secondary Maps\";\n            public static string forwardText = \"Forward Rendering Options\";\n            public static string renderingMode = \"Rendering Mode\";\n            public static string advancedText = \"Advanced Options\";\n            public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode));\n        }\n\n        MaterialProperty blendMode = null;\n        MaterialProperty albedoMap = null;\n        MaterialProperty albedoColor = null;\n        MaterialProperty alphaCutoff = null;\n        MaterialProperty specularMap = null;\n        MaterialProperty specularColor = null;\n        MaterialProperty metallicMap = null;\n        MaterialProperty metallic = null;\n        MaterialProperty smoothness = null;\n        MaterialProperty smoothnessScale = null;\n        MaterialProperty smoothnessMapChannel = null;\n        MaterialProperty highlights = null;\n        MaterialProperty reflections = null;\n        MaterialProperty bumpScale = null;\n        MaterialProperty bumpMap = null;\n        MaterialProperty occlusionStrength = null;\n        MaterialProperty occlusionMap = null;\n        MaterialProperty heigtMapScale = null;\n        MaterialProperty heightMap = null;\n        MaterialProperty emissionColorForRendering = null;\n        MaterialProperty emissionMap = null;\n        MaterialProperty detailMask = null;\n        MaterialProperty detailAlbedoMap = null;\n        MaterialProperty detailNormalMapScale = null;\n        MaterialProperty detailNormalMap = null;\n        MaterialProperty uvSetSecondary = null;\n\n        MaterialEditor m_MaterialEditor;\n        WorkflowMode m_WorkflowMode = WorkflowMode.Specular;\n\n        static int _SpecGlossMap = Shader.PropertyToID(\"_SpecGlossMap\");\n        static int _SpecColor = Shader.PropertyToID(\"_SpecColor\");\n        static int _MetallicGlossMap = Shader.PropertyToID(\"_MetallicGlossMap\");\n        static int _Metallic = Shader.PropertyToID(\"_Metallic\");\n\n        public void FindProperties(MaterialProperty[] props)\n        {\n            blendMode = FindProperty(\"_Mode\", props);\n            albedoMap = FindProperty(\"_MainTex\", props);\n            albedoColor = FindProperty(\"_Color\", props);\n            alphaCutoff = FindProperty(\"_Cutoff\", props);\n            specularMap = FindProperty(\"_SpecGlossMap\", props, false);\n            specularColor = FindProperty(\"_SpecColor\", props, false);\n            metallicMap = FindProperty(\"_MetallicGlossMap\", props, false);\n            metallic = FindProperty(\"_Metallic\", props, false);\n            if (specularMap != null && specularColor != null)\n                m_WorkflowMode = WorkflowMode.Specular;\n            else if (metallicMap != null && metallic != null)\n                m_WorkflowMode = WorkflowMode.Metallic;\n            else\n                m_WorkflowMode = WorkflowMode.Dielectric;\n            smoothness = FindProperty(\"_Glossiness\", props);\n            smoothnessScale = FindProperty(\"_GlossMapScale\", props, false);\n            smoothnessMapChannel = FindProperty(\"_SmoothnessTextureChannel\", props, false);\n            highlights = FindProperty(\"_SpecularHighlights\", props, false);\n            reflections = FindProperty(\"_GlossyReflections\", props, false);\n            bumpScale = FindProperty(\"_BumpScale\", props);\n            bumpMap = FindProperty(\"_BumpMap\", props);\n            heigtMapScale = FindProperty(\"_Parallax\", props);\n            heightMap = FindProperty(\"_ParallaxMap\", props);\n            occlusionStrength = FindProperty(\"_OcclusionStrength\", props);\n            occlusionMap = FindProperty(\"_OcclusionMap\", props);\n            emissionColorForRendering = FindProperty(\"_EmissionColor\", props);\n            emissionMap = FindProperty(\"_EmissionMap\", props);\n            detailMask = FindProperty(\"_DetailMask\", props);\n            detailAlbedoMap = FindProperty(\"_DetailAlbedoMap\", props);\n            detailNormalMapScale = FindProperty(\"_DetailNormalMapScale\", props);\n            detailNormalMap = FindProperty(\"_DetailNormalMap\", props);\n            uvSetSecondary = FindProperty(\"_UVSec\", props);\n        }\n\n        public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)\n        {\n            FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly\n            m_MaterialEditor = materialEditor;\n            Material material = materialEditor.target as Material;\n\n            ShaderPropertiesGUI(material);\n        }\n\n        public void ShaderPropertiesGUI(Material material)\n        {\n            // Use default labelWidth\n            EditorGUIUtility.labelWidth = 0f;\n\n            bool blendModeChanged = false;\n\n            {\n                blendModeChanged = BlendModePopup();\n\n                // Primary properties\n                GUILayout.Label(Styles.primaryMapsText, EditorStyles.boldLabel);\n                DoAlbedoArea(material);\n                DoSpecularMetallicArea();\n                DoNormalArea();\n                m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightMap.textureValue != null ? heigtMapScale : null);\n                m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null);\n                m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask);\n                DoEmissionArea(material);\n                EditorGUI.BeginChangeCheck();\n                m_MaterialEditor.TextureScaleOffsetProperty(albedoMap);\n                if (EditorGUI.EndChangeCheck())\n                    emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake\n\n                EditorGUILayout.Space();\n\n                // Secondary properties\n                GUILayout.Label(Styles.secondaryMapsText, EditorStyles.boldLabel);\n                m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlbedoText, detailAlbedoMap);\n                m_MaterialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale);\n                m_MaterialEditor.TextureScaleOffsetProperty(detailAlbedoMap);\n                m_MaterialEditor.ShaderProperty(uvSetSecondary, Styles.uvSetLabel.text);\n\n                // Third properties\n                GUILayout.Label(Styles.forwardText, EditorStyles.boldLabel);\n                if (highlights != null)\n                    m_MaterialEditor.ShaderProperty(highlights, Styles.highlightsText);\n                if (reflections != null)\n                    m_MaterialEditor.ShaderProperty(reflections, Styles.reflectionsText);\n\n                EditorGUILayout.Space();\n\n                GUILayout.Label(Styles.advancedText, EditorStyles.boldLabel);\n\n                m_MaterialEditor.RenderQueueField();\n            }\n            if (blendModeChanged)\n            {\n                foreach (var obj in blendMode.targets)\n                    SetupMaterialWithBlendMode((Material)obj, (BlendMode)((Material)obj).GetFloat(\"_Mode\"), true);\n            }\n\n            m_MaterialEditor.EnableInstancingField();\n            m_MaterialEditor.DoubleSidedGIField();\n        }\n\n        bool ShaderHasProperty(Shader shader, int nameId)\n        {\n            for (int i = 0, count = shader.GetPropertyCount(); i < count; i++)\n            {\n                if (shader.GetPropertyNameId(i) == nameId)\n                    return true;\n            }\n            return false;\n        }\n\n        internal void DetermineWorkflow(Material material)\n        {\n            var shader = material.shader;\n            if (ShaderHasProperty(shader, _SpecGlossMap) && ShaderHasProperty(shader, _SpecColor))\n                m_WorkflowMode = WorkflowMode.Specular;\n            else if (ShaderHasProperty(shader, _MetallicGlossMap) && ShaderHasProperty(shader, _Metallic))\n                m_WorkflowMode = WorkflowMode.Metallic;\n            else\n                m_WorkflowMode = WorkflowMode.Dielectric;\n        }\n\n        public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)\n        {\n            // _Emission property is lost after assigning Standard shader to the material\n            // thus transfer it before assigning the new shader\n            if (material.HasProperty(\"_Emission\"))\n            {\n                material.SetColor(\"_EmissionColor\", material.GetColor(\"_Emission\"));\n            }\n\n            base.AssignNewShaderToMaterial(material, oldShader, newShader);\n\n            if (oldShader == null || !oldShader.name.Contains(\"Legacy Shaders/\"))\n            {\n                SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat(\"_Mode\"), true);\n                return;\n            }\n\n            BlendMode blendMode = BlendMode.Opaque;\n            if (oldShader.name.Contains(\"/Transparent/Cutout/\"))\n            {\n                blendMode = BlendMode.Cutout;\n            }\n            else if (oldShader.name.Contains(\"/Transparent/\"))\n            {\n                // NOTE: legacy shaders did not provide physically based transparency\n                // therefore Fade mode\n                blendMode = BlendMode.Fade;\n            }\n            material.SetFloat(\"_Mode\", (float)blendMode);\n\n            SetupMaterialWithBlendMode(material, blendMode, true);\n        }\n\n        bool BlendModePopup()\n        {\n            MaterialEditor.BeginProperty(blendMode);\n            var mode = (BlendMode)blendMode.floatValue;\n\n            EditorGUI.BeginChangeCheck();\n            mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);\n            bool result = EditorGUI.EndChangeCheck();\n            if (result)\n            {\n                m_MaterialEditor.RegisterPropertyChangeUndo(\"Rendering Mode\");\n                blendMode.floatValue = (float)mode;\n            }\n\n            MaterialEditor.EndProperty();\n\n            return result;\n        }\n\n        void DoNormalArea()\n        {\n            m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null);\n            if (bumpScale.floatValue != 1\n                && UnityEditorInternal.InternalEditorUtility.IsMobilePlatform(EditorUserBuildSettings.activeBuildTarget))\n                if (m_MaterialEditor.HelpBoxWithButton(\n                    EditorGUIUtility.TrTextContent(\"Bump scale is not supported on mobile platforms\"),\n                    EditorGUIUtility.TrTextContent(\"Fix Now\")))\n                {\n                    bumpScale.floatValue = 1;\n                }\n        }\n\n        void DoAlbedoArea(Material material)\n        {\n            m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor);\n            if (((BlendMode)material.GetFloat(\"_Mode\") == BlendMode.Cutout))\n            {\n                m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);\n            }\n        }\n\n        void DoEmissionArea(Material material)\n        {\n            // Emission for GI?\n            if (m_MaterialEditor.EmissionEnabledProperty())\n            {\n                bool hadEmissionTexture = emissionMap.textureValue != null;\n\n                // Texture and HDR color controls\n                m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, false);\n\n                if (material.globalIlluminationFlags.HasFlag(MaterialGlobalIlluminationFlags.EmissiveIsBlack))\n                {\n                    material.GetPropertyState(MaterialSerializedProperty.LightmapFlags, out _, out _, out bool lockedByAncestor);\n                    if (lockedByAncestor)\n                        EditorGUILayout.HelpBox(\"Emissive lighting is locked to black by a parent Material. Changing the emissive color will have no effect.\", MessageType.Warning);\n                }\n\n                // If texture was assigned and color was black set color to white\n                float brightness = emissionColorForRendering.colorValue.maxColorComponent;\n                if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f)\n                    emissionColorForRendering.colorValue = Color.white;\n\n                // change the GI flag and fix it up with emissive as black if necessary\n                m_MaterialEditor.LightmapEmissionFlagsProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel, true);\n            }\n        }\n\n        void DoSpecularMetallicArea()\n        {\n            bool hasGlossMap = false;\n            if (m_WorkflowMode == WorkflowMode.Specular)\n            {\n                hasGlossMap = specularMap.textureValue != null;\n                m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specularMap, hasGlossMap ? null : specularColor);\n            }\n            else if (m_WorkflowMode == WorkflowMode.Metallic)\n            {\n                hasGlossMap = metallicMap.textureValue != null;\n                m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap, hasGlossMap ? null : metallic);\n            }\n\n            bool showSmoothnessScale = hasGlossMap;\n            if (smoothnessMapChannel != null)\n            {\n                int smoothnessChannel = (int)smoothnessMapChannel.floatValue;\n                if (smoothnessChannel == (int)SmoothnessMapChannel.AlbedoAlpha)\n                    showSmoothnessScale = true;\n            }\n\n            int indentation = 2; // align with labels of texture properties\n            m_MaterialEditor.ShaderProperty(showSmoothnessScale ? smoothnessScale : smoothness, showSmoothnessScale ? Styles.smoothnessScaleText : Styles.smoothnessText, indentation);\n\n            ++indentation;\n            if (smoothnessMapChannel != null)\n                m_MaterialEditor.ShaderProperty(smoothnessMapChannel, Styles.smoothnessMapChannelText, indentation);\n        }\n\n        public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode, bool overrideRenderQueue)\n        {\n            int minRenderQueue = -1;\n            int maxRenderQueue = 5000;\n            int defaultRenderQueue = -1;\n            switch (blendMode)\n            {\n                case BlendMode.Opaque:\n                    material.SetOverrideTag(\"RenderType\", \"\");\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.One);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.Zero);\n                    material.SetFloat(\"_ZWrite\", 1.0f);\n                    material.DisableKeyword(\"_ALPHATEST_ON\");\n                    material.DisableKeyword(\"_ALPHABLEND_ON\");\n                    material.DisableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    minRenderQueue = -1;\n                    maxRenderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest - 1;\n                    defaultRenderQueue = -1;\n                    break;\n                case BlendMode.Cutout:\n                    material.SetOverrideTag(\"RenderType\", \"TransparentCutout\");\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.One);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.Zero);\n                    material.SetFloat(\"_ZWrite\", 1.0f);\n                    material.EnableKeyword(\"_ALPHATEST_ON\");\n                    material.DisableKeyword(\"_ALPHABLEND_ON\");\n                    material.DisableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    minRenderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;\n                    maxRenderQueue = (int)UnityEngine.Rendering.RenderQueue.GeometryLast;\n                    defaultRenderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;\n                    break;\n                case BlendMode.Fade:\n                    material.SetOverrideTag(\"RenderType\", \"Transparent\");\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);\n                    material.SetFloat(\"_ZWrite\", 0.0f);\n                    material.DisableKeyword(\"_ALPHATEST_ON\");\n                    material.EnableKeyword(\"_ALPHABLEND_ON\");\n                    material.DisableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    minRenderQueue = (int)UnityEngine.Rendering.RenderQueue.GeometryLast + 1;\n                    maxRenderQueue = (int)UnityEngine.Rendering.RenderQueue.Overlay - 1;\n                    defaultRenderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;\n                    break;\n                case BlendMode.Transparent:\n                    material.SetOverrideTag(\"RenderType\", \"Transparent\");\n                    material.SetFloat(\"_SrcBlend\", (float)UnityEngine.Rendering.BlendMode.One);\n                    material.SetFloat(\"_DstBlend\", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);\n                    material.SetFloat(\"_ZWrite\", 0.0f);\n                    material.DisableKeyword(\"_ALPHATEST_ON\");\n                    material.DisableKeyword(\"_ALPHABLEND_ON\");\n                    material.EnableKeyword(\"_ALPHAPREMULTIPLY_ON\");\n                    minRenderQueue = (int)UnityEngine.Rendering.RenderQueue.GeometryLast + 1;\n                    maxRenderQueue = (int)UnityEngine.Rendering.RenderQueue.Overlay - 1;\n                    defaultRenderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;\n                    break;\n            }\n\n            if (overrideRenderQueue || material.renderQueue < minRenderQueue || material.renderQueue > maxRenderQueue)\n            {\n                if (!overrideRenderQueue)\n                    Debug.LogFormat(LogType.Log, LogOption.NoStacktrace, null, \"Render queue value outside of the allowed range ({0} - {1}) for selected Blend mode, resetting render queue to default\", minRenderQueue, maxRenderQueue);\n                material.renderQueue = defaultRenderQueue;\n            }\n        }\n\n        static SmoothnessMapChannel GetSmoothnessMapChannel(Material material)\n        {\n            int ch = (int)material.GetFloat(\"_SmoothnessTextureChannel\");\n            if (ch == (int)SmoothnessMapChannel.AlbedoAlpha)\n                return SmoothnessMapChannel.AlbedoAlpha;\n            else\n                return SmoothnessMapChannel.SpecularMetallicAlpha;\n        }\n\n        static void SetMaterialKeywords(Material material, WorkflowMode workflowMode)\n        {\n            // Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation\n            // (MaterialProperty value might come from renderer material property block)\n            SetKeyword(material, \"_NORMALMAP\", material.GetTexture(\"_BumpMap\") || material.GetTexture(\"_DetailNormalMap\"));\n            if (workflowMode == WorkflowMode.Specular)\n                SetKeyword(material, \"_SPECGLOSSMAP\", material.GetTexture(\"_SpecGlossMap\"));\n            else if (workflowMode == WorkflowMode.Metallic)\n                SetKeyword(material, \"_METALLICGLOSSMAP\", material.GetTexture(\"_MetallicGlossMap\"));\n            SetKeyword(material, \"_PARALLAXMAP\", material.GetTexture(\"_ParallaxMap\"));\n            SetKeyword(material, \"_DETAIL_MULX2\", material.GetTexture(\"_DetailAlbedoMap\") || material.GetTexture(\"_DetailNormalMap\"));\n\n            // A material's GI flag internally keeps track of whether emission is enabled at all, it's enabled but has no effect\n            // or is enabled and may be modified at runtime. This state depends on the values of the current flag and emissive color.\n            // The fixup routine makes sure that the material is in the correct state if/when changes are made to the mode or color.\n            MaterialEditor.FixupEmissiveFlag(material);\n            bool shouldEmissionBeEnabled = (material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0;\n            SetKeyword(material, \"_EMISSION\", shouldEmissionBeEnabled);\n\n            if (material.HasProperty(\"_SmoothnessTextureChannel\"))\n            {\n                SetKeyword(material, \"_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A\", GetSmoothnessMapChannel(material) == SmoothnessMapChannel.AlbedoAlpha);\n            }\n        }\n\n        override public void ValidateMaterial(Material material)\n        {\n            DetermineWorkflow(material);\n            SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat(\"_Mode\"), false);\n            SetMaterialKeywords(material, m_WorkflowMode);\n        }\n\n        static void SetKeyword(Material m, string keyword, bool state)\n        {\n            if (state)\n                m.EnableKeyword(keyword);\n            else\n                m.DisableKeyword(keyword);\n        }\n    }\n} // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/Inspector/StreamingControllerInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(StreamingController))]\n    [CanEditMultipleObjects]\n    internal class StreamingControllerEditor : Editor\n    {\n        public SerializedProperty streamingMipmapBias { get; private set; }\n\n        internal static class Styles\n        {\n            public static GUIContent streamingMipmapBias = EditorGUIUtility.TrTextContent(\"Mipmap Bias\", \"When mipmap streaming is active, Unity loads mipmap levels for textures based on their distance from all active cameras. This bias is added to all textures visible from this camera and allows you to force smaller or larger mipmap levels to be loaded for textures visible from this camera.\");\n        }\n\n        public void OnEnable()\n        {\n            streamingMipmapBias = serializedObject.FindProperty(\"m_StreamingMipmapBias\");\n        }\n\n        override public void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            //DrawDefaultInspector();\n            EditorGUILayout.PropertyField(streamingMipmapBias, Styles.streamingMipmapBias);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/TabbedEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    // Version for editors not derived from AssetImporterEditor\n    internal abstract class TabbedEditor : Editor\n    {\n        protected System.Type[] m_SubEditorTypes = null;\n        protected string[] m_SubEditorNames = null;\n        private int m_ActiveEditorIndex = 0;\n        private Editor m_ActiveEditor;\n        public Editor activeEditor { get { return m_ActiveEditor; } }\n\n        internal virtual void OnEnable()\n        {\n            m_ActiveEditorIndex = EditorPrefs.GetInt(GetType().Name + \"ActiveEditorIndex\", 0);\n            if (m_ActiveEditor == null)\n                m_ActiveEditor = CreateEditor(targets, m_SubEditorTypes[m_ActiveEditorIndex]);\n        }\n\n        void OnDestroy()\n        {\n            DestroyImmediate(activeEditor);\n        }\n\n        public override void OnInspectorGUI()\n        {\n            using (new GUILayout.HorizontalScope())\n            {\n                GUILayout.FlexibleSpace();\n                using (var check = new EditorGUI.ChangeCheckScope())\n                {\n                    m_ActiveEditorIndex = GUILayout.Toolbar(m_ActiveEditorIndex, m_SubEditorNames, \"LargeButton\", GUI.ToolbarButtonSize.FitToContents);\n                    if (check.changed)\n                    {\n                        EditorPrefs.SetInt(GetType().Name + \"ActiveEditorIndex\", m_ActiveEditorIndex);\n                        var oldEditor = activeEditor;\n                        m_ActiveEditor = null;\n                        DestroyImmediate(oldEditor);\n                        m_ActiveEditor = CreateEditor(targets, m_SubEditorTypes[m_ActiveEditorIndex]);\n                    }\n                }\n                GUILayout.FlexibleSpace();\n            }\n\n            activeEditor.OnInspectorGUI();\n        }\n\n        public override void OnPreviewSettings()\n        {\n            activeEditor.OnPreviewSettings();\n        }\n\n        public override void OnInteractivePreviewGUI(Rect r, GUIStyle background)\n        {\n            activeEditor.OnInteractivePreviewGUI(r, background);\n        }\n\n        public override bool HasPreviewGUI()\n        {\n            return activeEditor.HasPreviewGUI();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/TagManagerInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor.Presets;\nusing UnityEditor.Rendering;\nusing UnityEditor.UIElements;\nusing UnityEditor.UIElements.ProjectSettings;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing Button = UnityEngine.UIElements.Button;\nusing Debug = System.Diagnostics.Debug;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(TagManager))]\n    internal class TagManagerInspector : ProjectSettingsBaseEditor\n    {\n        const string k_ProjectPath = \"Project/Tags and Layers\";\n        const string k_AssetPath = \"ProjectSettings/TagManager.asset\";\n\n        const string k_BodyTemplate = \"UXML/ProjectSettings/TagManagerInspector-Body.uxml\";\n        const string k_ProjectSettingsStyleSheet = \"StyleSheets/ProjectSettings/ProjectSettingsCommon.uss\";\n        internal override string targetTitle => \"Tags & Layers\";\n\n        bool isEditable => AssetDatabase.IsOpenForEdit(k_AssetPath, StatusQueryOptions.UseCachedIfPossible);\n\n        static InitialExpansionState s_InitialExpansionState = InitialExpansionState.None;\n\n        internal enum InitialExpansionState\n        {\n            None = 0,\n            Tags = 1,\n            Layers = 2,\n            SortingLayers = 3,\n            RenderingLayers = 4\n        }\n\n        internal class Styles\n        {\n            public static GUIContent tags = EditorGUIUtility.TrTextContent(\"Tags\");\n            public static GUIContent sortingLayers = EditorGUIUtility.TrTextContent(\"Sorting Layers\");\n            public static GUIContent layers = EditorGUIUtility.TrTextContent(\"Layers\");\n            public static GUIContent renderingLayers = EditorGUIUtility.TrTextContent(\"Rendering Layers\");\n\n            public static float elementHeight = EditorGUIUtility.singleLineHeight + 2;\n            public const float headerListHeight = 3;\n\n            public const string tagListElement = \"tags-and-layer-list__element\";\n            public const string helperBox = \"tags-and-layer-list__helper-box\";\n        }\n\n        public TagManager tagManager => target as TagManager;\n\n        internal static void ShowWithInitialExpansion(InitialExpansionState initialExpansionState)\n        {\n            s_InitialExpansionState = initialExpansionState;\n            Selection.activeObject = EditorApplication.tagManager;\n        }\n\n        #region Sorting Layers\n\n        bool CanEditSortLayerEntry(int index)\n        {\n            if (index < 0 || index >= tagManager.GetSortingLayerCount())\n                return false;\n            return !tagManager.IsSortingLayerDefault(index);\n        }\n\n        #endregion\n\n        public override VisualElement CreateInspectorGUI()\n        {\n            var visualTreeAsset = EditorGUIUtility.Load(k_BodyTemplate) as VisualTreeAsset;\n            var content = visualTreeAsset.Instantiate();\n\n            var tagsProperty = serializedObject.FindProperty(\"tags\");\n            var sortingLayersProperty = serializedObject.FindProperty(\"m_SortingLayers\");\n            var layersProperty = serializedObject.FindProperty(\"layers\");\n            var renderingLayersProperty = serializedObject.FindProperty(\"m_RenderingLayers\");\n\n            Debug.Assert(layersProperty.arraySize == 32);\n\n            var tagsList = SetupTags(content, tagsProperty);\n            var sortingLayers = SetupSortingLayers(content, sortingLayersProperty);\n            var layers = SetupLayers(content, layersProperty);\n            var renderingLayers = SetupRenderingLayers(content, renderingLayersProperty);\n\n            if (s_InitialExpansionState != InitialExpansionState.None)\n            {\n                tagsProperty.isExpanded = false;\n                sortingLayersProperty.isExpanded = false;\n                layersProperty.isExpanded = false;\n                renderingLayersProperty.isExpanded = false;\n                switch (s_InitialExpansionState)\n                {\n                    case InitialExpansionState.Tags:\n                        tagsProperty.isExpanded = true;\n                        tagsList.Q<Foldout>().value = true;\n                        break;\n                    case InitialExpansionState.SortingLayers:\n                        sortingLayersProperty.isExpanded = true;\n                        sortingLayers.Q<Foldout>().value = true;\n                        break;\n                    case InitialExpansionState.Layers:\n                        layersProperty.isExpanded = true;\n                        layers.Q<Foldout>().value = true;\n                        break;\n                    case InitialExpansionState.RenderingLayers:\n                        renderingLayersProperty.isExpanded = true;\n                        renderingLayers.Q<Foldout>().value = true;\n                        break;\n                }\n\n                s_InitialExpansionState = InitialExpansionState.None;\n            }\n\n            content.Bind(serializedObject);\n            return content;\n        }\n\n        VisualElement SetupTags(VisualElement content, SerializedProperty tagsProperty)\n        {\n            var tagsList = content.Q<ListView>(\"Tags\");\n            tagsList.fixedItemHeight = Styles.elementHeight;\n            tagsList.headerTitle = Styles.tags.text;\n            tagsList.makeItem = () =>\n            {\n                var tagListElement = new VisualElement { classList = { Styles.tagListElement } };\n                tagListElement.Add(new Label()\n                {\n                    name = \"Title\",\n                    classList = { \"tag-list__element__title\" }\n                });\n                tagListElement.Add(new Label\n                {\n                    name = \"Value\"\n                });\n                return tagListElement;\n            };\n            tagsList.bindItem = (ve, index) =>\n            {\n                ve.Q<Label>(\"Title\").text = $\"Tag {index}\";\n                ve.Q<Label>(\"Value\").text = index < tagsProperty.arraySize\n                    ? tagsProperty.GetArrayElementAtIndex(index).stringValue\n                    : \"Unknown\";\n            };\n            tagsList.onAdd += (listView) =>\n            {\n                var addButton = listView.Q<Button>(\"unity-list-view__add-button\");\n                PopupWindow.Show(addButton.worldBound, new EnterTagNamePopup(tagsProperty, s =>\n                {\n                    tagManager.AddTag(s);\n                    serializedObject.ApplyModifiedProperties();\n                }));\n            };\n            tagsList.onRemove += (listView) =>\n            {\n                if (tagsProperty.arraySize == 0)\n                    return;\n\n                var indexForRemoval = listView.selectedIndex;\n                if (indexForRemoval == -1)\n                    indexForRemoval = tagsProperty.arraySize - 1;\n\n                var tag = tagsProperty.GetArrayElementAtIndex(indexForRemoval).stringValue;\n                if (string.IsNullOrEmpty(tag))\n                    return;\n\n                var isPreset = Preset.IsEditorTargetAPreset(target);\n                if (!isPreset)\n                {\n                    var go = GameObject.FindWithTag(tag);\n                    if (go != null)\n                    {\n                        EditorUtility.DisplayDialog(\"Error\", \"Can't remove this tag because it is being used by \" + go.name, \"OK\");\n                        return;\n                    }\n                }\n\n                tagManager.RemoveTag(tag);\n                serializedObject.ApplyModifiedProperties();\n            };\n            //TextFields in Array are not bind correctly so we need to refresh them manually\n            content.TrackPropertyValue(tagsProperty, sp => tagsList.RefreshItems());\n            return tagsList;\n        }\n\n        VisualElement SetupSortingLayers(VisualElement content, SerializedProperty sortingLayersProperty)\n        {\n            var sortingLayers = content.Q<ListView>(\"SortingLayers\");\n            sortingLayers.fixedItemHeight = Styles.elementHeight;\n            sortingLayers.headerTitle = Styles.sortingLayers.text;\n            sortingLayers.makeItem = () => new TextField\n            {\n                classList = { Styles.tagListElement }\n            };\n\n            void SortingLayersChanged(ChangeEvent<string> evt)\n            {\n                if (evt.target is not TextField textField)\n                    return;\n                evt.StopPropagation();\n                var index = (int)textField.userData;\n                tagManager.SetSortingLayerName(index, evt.newValue);\n                serializedObject.ApplyModifiedProperties();\n            }\n\n            sortingLayers.bindItem = (ve, index) =>\n            {\n                var textField = ve as TextField;\n                textField.label = $\"Layer {index}\";\n                textField.SetValueWithoutNotify(tagManager.GetSortingLayerName(index));\n\n                var isEnable = isEditable && CanEditSortLayerEntry(index);\n                textField.SetEnabled(isEnable);\n                textField.userData = index;\n\n                textField.RegisterValueChangedCallback(SortingLayersChanged);\n            };\n            sortingLayers.unbindItem = (ve, index) =>\n            {\n                var textField = ve as TextField;\n                textField.UnregisterValueChangedCallback(SortingLayersChanged);\n            };\n            sortingLayers.itemIndexChanged += (prev, next) =>\n            {\n                serializedObject.ApplyModifiedProperties();\n                tagManager.UpdateSortingLayersOrder();\n\n                if (SortingLayer.onLayerChanged != null)\n                    SortingLayer.onLayerChanged();\n            };\n            sortingLayers.onAdd += (listView) =>\n            {\n                serializedObject.ApplyModifiedProperties();\n                tagManager.AddSortingLayer();\n                serializedObject.Update();\n\n                listView.selectedIndex = tagManager.GetSortingLayerCount() - 1; // select just added one\n\n                if (SortingLayer.onLayerAdded != null)\n                    SortingLayer.onLayerAdded(SortingLayer.layers[listView.selectedIndex]);\n\n                if (SortingLayer.onLayerChanged != null)\n                    SortingLayer.onLayerChanged();\n            };\n            sortingLayers.onRemove += (listView) =>\n            {\n                if (tagManager.GetSortingLayerCount() == 0 || !CanEditSortLayerEntry(listView.selectedIndex))\n                    return;\n\n                if (SortingLayer.onLayerRemoved != null)\n                    SortingLayer.onLayerRemoved(SortingLayer.layers[listView.selectedIndex]);\n\n                listView.viewController.RemoveItem(listView.selectedIndex);\n                serializedObject.ApplyModifiedProperties();\n                serializedObject.Update();\n                tagManager.UpdateSortingLayersOrder();\n\n                if (SortingLayer.onLayerChanged != null)\n                    SortingLayer.onLayerChanged();\n            };\n            //TextFields in Array are not bind correctly so we need to refresh them manually\n            content.TrackPropertyValue(sortingLayersProperty, sp => sortingLayers.RefreshItems());\n            return sortingLayers;\n        }\n\n        VisualElement SetupLayers(VisualElement content, SerializedProperty layersProperty)\n        {\n            var layers = content.Q<ListView>(\"Layers\");\n            layers.fixedItemHeight = Styles.elementHeight;\n            layers.headerTitle = Styles.layers.text;\n            layers.makeItem = () => new TextField\n            {\n                classList = { Styles.tagListElement }\n            };\n\n            void LayersChanged(ChangeEvent<string> evt)\n            {\n                if (evt.target is not TextField textField)\n                    return;\n                evt.StopPropagation();\n                var index = (int)textField.userData;\n                layersProperty.GetArrayElementAtIndex(index).stringValue = evt.newValue;\n                serializedObject.ApplyModifiedProperties();\n            }\n\n            layers.bindItem = (ve, index) =>\n            {\n                // Layers up to 8 used to be reserved for Builtin Layers\n                // As layers with indices 3, 6 and 7 were empty,\n                // it was decided to change them to User Layers\n                // However, we cannot shift layers around so we need to explicitly handle\n                // the gap where layer index == 3 in the layer stack\n                var isUserLayer = index is > 5 or 3;\n                var editable = isEditable && isUserLayer;\n\n                var textField = ve as TextField;\n                var layerName = layersProperty.GetArrayElementAtIndex(index).stringValue;\n\n                textField.label = isUserLayer ? $\" User Layer {index}\" : $\" Builtin Layer {index}\";\n                textField.SetValueWithoutNotify(layerName);\n                textField.SetEnabled(editable);\n                textField.userData = index;\n\n                textField.RegisterValueChangedCallback(LayersChanged);\n            };\n            layers.unbindItem = (ve, index) =>\n            {\n                var textField = ve as TextField;\n                textField.UnregisterValueChangedCallback(LayersChanged);\n            };\n            //TextFields in Array are not bind correctly so we need to refresh them manually\n            content.TrackPropertyValue(layersProperty, sp => layers.RefreshItems());\n            return layers;\n        }\n\n        void UpdateAllowanceAndMessages(BaseListView listView)\n        {\n            var renderingLayerCount = tagManager.GetRenderingLayerCount();\n            var currentMaxRenderingLayerIndex = RenderPipelineEditorUtility.GetActiveMaxRenderingLayers();\n            listView.allowAdd = renderingLayerCount < currentMaxRenderingLayerIndex;\n            listView.allowRemove = !tagManager.IsIndexReservedForDefaultRenderingLayer(renderingLayerCount - 1);\n\n            var viewport = listView.Q<VisualElement>(\"unity-content-viewport\");\n            ClearHelpBoxes(viewport);\n\n            var maxRenderingLayers = RenderPipelineEditorUtility.GetMaxRenderingLayersFromSettings();\n            AddInfoBoxesForMaximumValueRestriction(viewport, maxRenderingLayers);\n            AddWarningMessageForUnsupportedLayers(viewport, maxRenderingLayers);\n        }\n\n        void ClearHelpBoxes(VisualElement viewport)\n        {\n            viewport\n                .Query<HelpBox>()\n                .Where(h => h.name == \"MaximumSupportedRenderingLayers\")\n                .ForEach(viewport.Remove);\n        }\n\n        void AddInfoBoxesForMaximumValueRestriction(VisualElement viewport, List<(int, string)> maxRenderingLayers)\n        {\n            for (var i = 0; i < maxRenderingLayers.Count; i++)\n            {\n                if (maxRenderingLayers[i].Item1 >= 32)\n                    continue;\n\n                var message = $\"Maximum supported rendering layers on {maxRenderingLayers[i].Item2} is {maxRenderingLayers[i].Item1}.\";\n                AddHelperBoxToViewport(viewport, maxRenderingLayers, message, HelpBoxMessageType.Info);\n            }\n        }\n\n        void AddWarningMessageForUnsupportedLayers(VisualElement viewport, List<(int, string)> maxRenderingLayers)\n        {\n            for (var i = 0; i < maxRenderingLayers.Count; i++)\n            {\n                if (tagManager.GetRenderingLayerCount() <= maxRenderingLayers[i].Item1)\n                    continue;\n\n                var message = $\"One of the used Render Pipelines doesn't supports all defined Rendering Layers. Additional layers added due to other Render Pipelines will be ignored.\";\n                AddHelperBoxToViewport(viewport, maxRenderingLayers, message, HelpBoxMessageType.Warning);\n                break;\n            }\n        }\n\n        static void AddHelperBoxToViewport(VisualElement viewport, List<(int, string)> maxRenderingLayers, string message, HelpBoxMessageType type)\n        {\n            var supportedLabel = new HelpBox(message, type)\n            {\n                name = \"MaximumSupportedRenderingLayers\",\n                classList = { Styles.helperBox }\n            };\n            viewport.Insert(0, supportedLabel);\n        }\n\n        VisualElement SetupRenderingLayers(VisualElement content, SerializedProperty renderingLayersProperty)\n        {\n            var renderingLayers = content.Q<ListView>(\"RenderingLayers\");\n            renderingLayers.fixedItemHeight = Styles.elementHeight;\n            renderingLayers.headerTitle = Styles.renderingLayers.text;\n            renderingLayers.makeItem = () => new TextField\n            {\n                classList = { Styles.tagListElement }\n            };\n\n            void RenderingLayersChanged(ChangeEvent<string> evt)\n            {\n                if (evt.target is not TextField textField)\n                    return;\n                evt.StopPropagation();\n                var index = (int)textField.userData;\n                renderingLayersProperty.GetArrayElementAtIndex(index).stringValue = evt.newValue;\n                serializedObject.ApplyModifiedProperties();\n            }\n\n            renderingLayers.bindItem = (ve, index) =>\n            {\n                var renderingLayerCount = tagManager.GetRenderingLayerCount();\n                if (index >= renderingLayerCount)\n                    return;\n\n                var textField = ve as TextField;\n                textField.label = $\"Layer {index}\";\n                textField.SetValueWithoutNotify(tagManager.RenderingLayerToString(index));\n\n                var isEnabled = isEditable && !tagManager.IsIndexReservedForDefaultRenderingLayer(index);\n                textField.SetEnabled(isEnabled);\n                textField.userData = index;\n\n                textField.RegisterValueChangedCallback(RenderingLayersChanged);\n            };\n            renderingLayers.unbindItem = (ve, index) =>\n            {\n                var textField = ve as TextField;\n                textField.UnregisterValueChangedCallback(RenderingLayersChanged);\n            };\n            renderingLayers.onAdd += (listView) =>\n            {\n                var newIndex = tagManager.GetRenderingLayerCount();\n\n                tagManager.TryAddRenderingLayerName($\"Layer {newIndex}\");\n                serializedObject.ApplyModifiedProperties();\n\n                listView.selectedIndex = newIndex; // select just added one\n\n                UpdateAllowanceAndMessages(listView);\n            };\n\n            renderingLayers.selectionChanged += (item) =>\n            {\n                var index = renderingLayers.selectedIndex;\n                var lastIndex = tagManager.GetRenderingLayerCount() - 1;\n                renderingLayers.allowRemove = !tagManager.IsIndexReservedForDefaultRenderingLayer(index) && lastIndex == index;\n            };\n\n            renderingLayers.onRemove += (listView) =>\n            {\n                var lastIndex = tagManager.GetRenderingLayerCount() - 1;\n                if (tagManager.IsIndexReservedForDefaultRenderingLayer(lastIndex))\n                    return;\n\n                tagManager.TryRemoveLastRenderingLayerName();\n                serializedObject.ApplyModifiedProperties();\n\n                listView.selectedIndex = lastIndex - 1; // select just added one\n\n                UpdateAllowanceAndMessages(listView);\n            };\n\n            UpdateAllowanceAndMessages(renderingLayers);\n\n            //TextFields in Array are not bind correctly so we need to refresh them manually\n            content.TrackPropertyValue(renderingLayersProperty, sp => renderingLayers.RefreshItems());\n            return renderingLayers;\n        }\n\n        [SettingsProvider]\n        static SettingsProvider CreateProjectSettingsProvider()\n        {\n            var provider = AssetSettingsProvider.CreateProviderFromAssetPath(k_ProjectPath, k_AssetPath, SettingsProvider.GetSearchKeywordsFromGUIContentProperties<Styles>());\n            provider.activateHandler = (text, root) =>\n            {\n                var serializedObject = provider.settingsEditor.serializedObject;\n                var titleBar = new ProjectSettingsTitleBar(\"Tags and Layers\");\n                titleBar.Initialize(serializedObject);\n\n                var styleSheet = EditorGUIUtility.Load(k_ProjectSettingsStyleSheet) as StyleSheet;\n                root.styleSheets.Add(styleSheet);\n\n                root.Add(titleBar);\n                root.Add(provider.settingsEditor.CreateInspectorGUI());\n            };\n            return provider;\n        }\n\n        class EnterTagNamePopup : PopupWindowContent\n        {\n            public delegate void EnterDelegate(string str);\n\n            readonly EnterDelegate m_EnterCallback;\n            string m_NewTagName = \"New tag\";\n            bool m_NeedsFocus = true;\n\n            public EnterTagNamePopup(SerializedProperty tags, EnterDelegate callback)\n            {\n                m_EnterCallback = callback;\n\n                var existingTagNames = new List<string>();\n                for (var i = 0; i < tags.arraySize; i++)\n                {\n                    var tagName = tags.GetArrayElementAtIndex(i).stringValue;\n                    if (!string.IsNullOrEmpty(tagName))\n                        existingTagNames.Add(tagName);\n                }\n\n                m_NewTagName = ObjectNames.GetUniqueName(existingTagNames.ToArray(), m_NewTagName);\n            }\n\n            public override Vector2 GetWindowSize() =>\n                new(400, EditorGUI.kSingleLineHeight * 2 + EditorGUI.kControlVerticalSpacing + 14);\n\n            public override void OnGUI(Rect windowRect)\n            {\n                GUILayout.Space(5);\n                var evt = Event.current;\n                var hitEnter = evt.type == EventType.KeyDown && evt.keyCode is KeyCode.Return or KeyCode.KeypadEnter;\n                GUI.SetNextControlName(\"TagName\");\n                m_NewTagName = EditorGUILayout.TextField(\"New Tag Name\", m_NewTagName);\n\n                if (m_NeedsFocus)\n                {\n                    m_NeedsFocus = false;\n                    EditorGUI.FocusTextInControl(\"TagName\");\n                }\n\n                GUI.enabled = m_NewTagName.Length != 0;\n                var savePressed = GUILayout.Button(\"Save\");\n                if (string.IsNullOrWhiteSpace(m_NewTagName) || (!savePressed && !hitEnter))\n                    return;\n                m_EnterCallback(m_NewTagName);\n                editorWindow.Close();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/TextMeshInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\n\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(TextMesh))]\n    [CanEditMultipleObjects]\n    internal class TextMeshInspector : Editor\n    {\n        SerializedProperty m_Font;\n\n        void OnEnable()\n        {\n            m_Font = serializedObject.FindProperty(\"m_Font\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            Font oldFont = m_Font.hasMultipleDifferentValues ? null : (m_Font.objectReferenceValue as Font);\n            DrawDefaultInspector();\n            Font newFont = m_Font.hasMultipleDifferentValues ? null : (m_Font.objectReferenceValue as Font);\n            if (newFont != null && newFont != oldFont)\n            {\n                foreach (TextMesh textMesh in targets)\n                {\n                    var renderer = textMesh.GetComponent<MeshRenderer>();\n                    if (renderer)\n                        renderer.sharedMaterial = newFont.material;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Texture2DArrayInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Experimental.Rendering;\n\nnamespace UnityEditor\n{\n    // This derived class looks barren because TextureInspector already handles Texture2DArray (Texture or RenderTexture) for most functions.\n    [CustomEditor(typeof(Texture2DArray))]\n    [CanEditMultipleObjects]\n    class Texture2DArrayInspector : TextureInspector\n    {\n        public override string GetInfoString()\n        {\n            var tex = (Texture2DArray)target;\n            var info = $\"{tex.width}x{tex.height} {tex.depth} slice{(tex.depth != 1 ? \"s\" : \"\")} {GraphicsFormatUtility.GetFormatString(tex.format)} {EditorUtility.FormatBytes(TextureUtil.GetStorageMemorySizeLong(tex))}\";\n            return info;\n        }\n\n        public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height)\n        {\n            return m_Texture2DArrayPreview.RenderStaticPreview(target as Texture, assetPath, subAssets, width, height);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Texture2DArrayPreview.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class Texture2DArrayPreview\n    {\n        static readonly int s_ShaderColorMask = Shader.PropertyToID(\"_ColorMaskBits\");\n        static readonly int s_ShaderSliceIndex = Shader.PropertyToID(\"_SliceIndex\");\n        static readonly int s_ShaderMip = Shader.PropertyToID(\"_Mip\");\n        static readonly int s_ShaderToSrgb = Shader.PropertyToID(\"_ToSRGB\");\n        static readonly int s_ShaderIsNormalMap = Shader.PropertyToID(\"_IsNormalMap\");\n\n        // Preview settings\n        Material m_Material;\n        int m_Slice = 0;\n\n        private Vector2 m_Pos;\n\n        static class Styles\n        {\n            public static GUIContent smallZoom = EditorGUIUtility.IconContent(\"PreTextureMipMapLow\");\n            public static GUIContent largeZoom = EditorGUIUtility.IconContent(\"PreTextureMipMapHigh\");\n            public static GUIContent alphaIcon = EditorGUIUtility.IconContent(\"PreTextureAlpha\");\n            public static GUIContent RGBIcon = EditorGUIUtility.IconContent(\"PreTextureRGB\");\n            public static GUIContent arrayIcon = EditorGUIUtility.IconContent(\"Texture2DArray\");\n        }\n\n        public float GetMipLevelForRendering(Texture texture, float mipLevel)\n        {\n            return Mathf.Min(mipLevel, TextureUtil.GetMipmapCount(texture));\n        }\n\n        public void SetShaderColorMask(TextureInspector.PreviewMode mode)\n        {\n            var mask = 15;\n            switch (mode)\n            {\n                case TextureInspector.PreviewMode.RGB: mask = 7; break;\n                case TextureInspector.PreviewMode.R: mask = 1; break;\n                case TextureInspector.PreviewMode.G: mask = 2; break;\n                case TextureInspector.PreviewMode.B: mask = 4; break;\n                case TextureInspector.PreviewMode.A: mask = 8; break;\n            }\n            m_Material.SetFloat(s_ShaderColorMask, (float)mask);\n        }\n\n        public void OnPreviewSettings(Texture target)\n        {\n            Texture2DArray texture2DArray = target as Texture2DArray;\n            RenderTexture renderTexture = target as RenderTexture;\n\n            if (texture2DArray == null && renderTexture == null)\n                return;\n\n            if (texture2DArray != null)\n            {\n                m_Slice = (int)TextureInspector.PreviewSettingsSlider(Styles.arrayIcon, m_Slice, 0, texture2DArray.depth - 1, 60, 30, isInteger: true);\n            }\n            else\n            {\n                m_Slice = (int)TextureInspector.PreviewSettingsSlider(Styles.arrayIcon, m_Slice, 0, renderTexture.volumeDepth - 1, 60, 30, isInteger: true);\n            }\n        }\n\n        public void OnPreviewGUI(Texture t, Rect r, GUIStyle background, float exposure, TextureInspector.PreviewMode previewMode, float mipLevel)\n        {\n            if (t == null)\n                return;\n\n            if (!SystemInfo.supports2DArrayTextures)\n            {\n                EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), \"2D texture array preview not supported\");\n                return;\n            }\n\n            InitPreviewMaterialIfNeeded();\n            m_Material.mainTexture = t;\n\n            int effectiveSlice = GetEffectiveSlice(t);\n\n            m_Material.SetFloat(s_ShaderSliceIndex, (float)effectiveSlice);\n            m_Material.SetFloat(s_ShaderToSrgb, QualitySettings.activeColorSpace == ColorSpace.Linear ? 1.0f : 0.0f);\n            m_Material.SetFloat(s_ShaderIsNormalMap, TextureInspector.IsNormalMap(t) ? 1.0f : 0.0f);\n\n            SetShaderColorMask(previewMode);\n\n            int texWidth = Mathf.Max(t.width, 1);\n            int texHeight = Mathf.Max(t.height, 1);\n\n            float effectiveMipLevel = GetMipLevelForRendering(t, mipLevel);\n            float zoomLevel = Mathf.Min(Mathf.Min(r.width / texWidth, r.height / texHeight), 1);\n            Rect wantedRect = new Rect(r.x, r.y, texWidth * zoomLevel, texHeight * zoomLevel);\n            PreviewGUI.BeginScrollView(r, m_Pos, wantedRect, \"PreHorizontalScrollbar\",\n                \"PreHorizontalScrollbarThumb\");\n            FilterMode oldFilter = t.filterMode;\n            TextureUtil.SetFilterModeNoDirty(t, FilterMode.Point);\n\n            EditorGUI.DrawPreviewTexture(wantedRect, t, m_Material, ScaleMode.StretchToFill, 0, effectiveMipLevel, UnityEngine.Rendering.ColorWriteMask.All, exposure);\n\n            TextureUtil.SetFilterModeNoDirty(t, oldFilter);\n\n            int mipmapLimit = GetMipmapLimit(t);\n            int cpuMipLevel = Mathf.Min(TextureUtil.GetMipmapCount(t) - 1, (int)mipLevel + mipmapLimit);\n            m_Pos = PreviewGUI.EndScrollView();\n\n            GUIContent sliceAndMipLevelTextContent = new GUIContent($\"Slice {effectiveSlice}\");\n            if (cpuMipLevel != 0)\n                sliceAndMipLevelTextContent.text += cpuMipLevel != (int)effectiveMipLevel\n                    ? $\" | Mip {cpuMipLevel}\\nMip {mipLevel} on GPU (Texture Limit)\"\n                    : $\" | Mip {mipLevel}\";\n\n            EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), sliceAndMipLevelTextContent);\n        }\n\n        int GetEffectiveSlice(Texture t)\n        {\n            var texture2DArray = t as Texture2DArray;\n\n            if (texture2DArray != null)\n            {\n                // If multiple objects are selected, we might be using a slice level before the maximum\n                return Mathf.Clamp(m_Slice, 0, texture2DArray.depth - 1);\n            }\n            else\n            {\n                var renderTexture = t as RenderTexture;\n                // If multiple objects are selected, we might be using a slice level before the maximum\n                return Mathf.Clamp(m_Slice, 0, renderTexture.volumeDepth - 1);\n            }\n        }\n\n        int GetMipmapLimit(Texture t)\n        {\n            var texture2DArray = t as Texture2DArray;\n            if (texture2DArray != null)\n                return texture2DArray.activeMipmapLimit;\n\n            return 0;\n        }\n\n        void InitPreviewMaterialIfNeeded()\n        {\n            if (m_Material == null)\n                m_Material = (Material)EditorGUIUtility.LoadRequired(\"Previews/Preview2DTextureArrayMaterial.mat\");\n        }\n\n        public Texture2D RenderStaticPreview(Texture target, string assetPath, Object[] subAssets, int width, int height)\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture || !SystemInfo.supports2DArrayTextures)\n                return null;\n\n            var texture = target as Texture2DArray;\n            if (texture == null)\n                return null;\n\n            var previewUtility = new PreviewRenderUtility();\n            previewUtility.BeginStaticPreview(new Rect(0, 0, width, height));\n\n            InitPreviewMaterialIfNeeded();\n            m_Material.mainTexture = texture;\n            m_Material.SetFloat(s_ShaderColorMask, 15.0f);\n            m_Material.SetFloat(s_ShaderMip, 0);\n            m_Material.SetFloat(s_ShaderToSrgb, 0.0f);\n            m_Material.SetFloat(s_ShaderIsNormalMap, TextureInspector.IsNormalMap(texture) ? 1.0f : 0.0f);\n\n            int sliceDistance = previewUtility.renderTexture.width / 12;\n            var elementCount = Mathf.Min(texture.depth, 6);\n            Rect screenRect = new Rect(), sourceRect = new Rect();\n            var subRect = new Rect(0, 0, previewUtility.renderTexture.width - sliceDistance * (elementCount - 1), previewUtility.renderTexture.height - sliceDistance * (elementCount - 1));\n            for (var el = elementCount - 1; el >= 0; --el)\n            {\n                m_Material.SetFloat(s_ShaderSliceIndex, (float)el);\n\n                subRect.x = sliceDistance * el;\n                subRect.y = previewUtility.renderTexture.height - subRect.height - sliceDistance * el;\n\n                var aspect = texture.width / (float)texture.height;\n                GUI.CalculateScaledTextureRects(subRect, ScaleMode.ScaleToFit, aspect, ref screenRect, ref sourceRect);\n                Graphics.DrawTexture(screenRect, texture, sourceRect, 0, 0, 0, 0, Color.white, m_Material);\n            }\n\n            var res = previewUtility.EndStaticPreview();\n            previewUtility.Cleanup();\n            return res;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Texture3DInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Runtime;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(Texture3D))]\n    [CanEditMultipleObjects]\n    internal class Texture3DInspector : TextureInspector\n    {\n        new Texture3DPreview preview;\n\n        protected override void OnEnable()\n        {\n            if (preview == null) preview = CreateInstance<Texture3DPreview>();\n\n            base.OnEnable();\n            preview.OnEnable();\n        }\n\n        protected override void OnDisable()\n        {\n            base.OnDisable();\n            preview.OnDisable();\n        }\n\n        public override string GetInfoString() => preview.GetInfoString();\n        public override void OnPreviewSettings()\n        {\n            preview.OnPreviewSettings(targets);\n        }\n\n        public override void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            preview.Texture = target as Texture;\n            preview.OnPreviewGUI(r, background);\n        }\n\n        public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height)\n            => preview.RenderStaticPreview(target as Texture, width, height);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/Texture3DPreview.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Experimental.Rendering;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class Texture3DPreview : ScriptableObject\n    {\n        enum Preview3DMode\n        {\n            Volume,\n            Slice,\n            SDF,\n        }\n\n        internal static class Materials\n        {\n            static Material s_SDF;\n            public static Material SDF\n            {\n                get\n                {\n                    if (s_SDF == null)\n                        s_SDF = Instantiate(EditorGUIUtility.LoadRequired(\"Previews/Preview3DSDF.mat\")) as Material;\n                    return s_SDF;\n                }\n            }\n\n            static Material s_Slice;\n            public static Material Slice\n            {\n                get\n                {\n                    if (s_Slice == null)\n                        s_Slice = Instantiate(EditorGUIUtility.LoadRequired(\"Previews/Preview3DSliced.mat\")) as Material;\n                    return s_Slice;\n                }\n            }\n\n            static Material s_Volume;\n            public static Material Volume\n            {\n                get\n                {\n                    if (s_Volume == null)\n                        s_Volume = Instantiate(EditorGUIUtility.LoadRequired(\"Previews/Preview3DVolume.mat\")) as Material;\n                    return s_Volume;\n                }\n            }\n        }\n\n        static class MaterialProps\n        {\n            public static readonly int colorRamp = Shader.PropertyToID(\"_ColorRamp\");\n            public static readonly int voxelSize = Shader.PropertyToID(\"_VoxelSize\");\n            public static readonly int invChannels = Shader.PropertyToID(\"_InvChannels\");\n            public static readonly int invScale = Shader.PropertyToID(\"_InvScale\");\n            public static readonly int globalScale = Shader.PropertyToID(\"_GlobalScale\");\n            public static readonly int invResolution = Shader.PropertyToID(\"_InvResolution\");\n            public static readonly int quality = Shader.PropertyToID(\"_Quality\");\n            public static readonly int alpha = Shader.PropertyToID(\"_Alpha\");\n            public static readonly int positions = Shader.PropertyToID(\"_Positions\");\n            public static readonly int scale = Shader.PropertyToID(\"_Scale\");\n            public static readonly int offset = Shader.PropertyToID(\"_Offset\");\n            public static readonly int filterMode = Shader.PropertyToID(\"_FilterMode\");\n            public static readonly int ramp = Shader.PropertyToID(\"_Ramp\");\n            public static readonly int CamToW = Shader.PropertyToID(\"_CamToW\");\n            public static readonly int WToCam = Shader.PropertyToID(\"_WToCam\");\n            public static readonly int ObjToW = Shader.PropertyToID(\"_ObjToW\");\n            public static readonly int WToObj = Shader.PropertyToID(\"_WToObj\");\n            public static readonly int isNormalMap = Shader.PropertyToID(\"_IsNormalMap\");\n            public static readonly int isSignedFormat = Shader.PropertyToID(\"_IsSignedFormat\");\n        }\n\n        static class Styles\n        {\n            public static readonly GUIContent ramp = EditorGUIUtility.TrTextContent(\"Ramp\", \"Use gradient color ramp visualization\");\n            public static readonly GUIContent quality = EditorGUIUtility.TrTextContent(\"Quality\", \"Sample per texture pixel modifier\");\n            public static readonly GUIContent alpha = EditorGUIUtility.TrTextContent(\"Alpha\", \"Opacity of the texture visualization\");\n            public static readonly GUIContent x = EditorGUIUtility.TrTextContent(\"X\");\n            public static readonly GUIContent y = EditorGUIUtility.TrTextContent(\"Y\");\n            public static readonly GUIContent z = EditorGUIUtility.TrTextContent(\"Z\");\n            public static readonly GUIContent scale = EditorGUIUtility.TrTextContent(\"Scale\", \"SDF value scale (how many texels SDF value of 1 represents)\");\n            public static readonly GUIContent offset = EditorGUIUtility.TrTextContent(\"Offset\", \"SDF surface is at this value\");\n            public static readonly GUIContent volume = EditorGUIUtility.TrTextContent(\"Volume\", \"Volumetric rendering display\");\n            public static readonly GUIContent slice = EditorGUIUtility.TrTextContent(\"Slice\", \"Display three planar slices of the texture\");\n            public static readonly GUIContent sdf = EditorGUIUtility.TrTextContent(\"SDF\", \"Display texture as a Signed Distance Field surface\");\n        }\n\n        const float s_SliderWidth = 40;\n        const float s_FloatWidth = 40;\n        const float s_MinViewDistance = 0f;\n        const float s_MaxViewDistance = 5.0f;\n        static readonly Vector2 s_InitialRotation = new Vector2(15, 30);\n        const float s_MaxPreviewPixelCount = 512 * 512 * 512;\n\n        PreviewRenderUtility m_PreviewUtility;\n        Preview3DMode m_Preview3DMode;\n        Texture m_Texture;\n        Vector2 m_PreviewDir;\n        float m_ViewDistance;\n\n        public Texture Texture\n        {\n            get => m_Texture;\n            set\n            {\n                bool init = m_Texture == null;\n\n                m_Texture = value;\n\n                if (init)\n                {\n                    float inverseResolution;\n                    Vector3 resolution = GetTextureResolution(Texture);\n                    Vector3 scale = VoxelSize(resolution, out inverseResolution);\n                    m_ViewDistance = Mathf.Lerp(1, 3, Mathf.Clamp01(scale.magnitude - 0.414f));\n                    m_PreviewUtility.camera.farClipPlane = s_MaxViewDistance * 2 + 1;\n                    m_PreviewUtility.camera.nearClipPlane = 0.1f;\n\n                    m_QualityModifier = Mathf.Clamp(8 - Mathf.Log(1.0f / inverseResolution, 2), 1, 8);\n                    m_Slice = Vector3.Scale(Vector3.one / 2, new Vector3(resolution.x, resolution.y, resolution.z));\n                }\n            }\n        }\n\n        static Color TurboColorEvaluation(float t)\n        {\n            Vector4 kRedVec4 = new Vector4(0.13572138f, 4.61539260f, -42.66032258f, 132.13108234f);\n            Vector4 kGreenVec4 = new Vector4(0.09140261f, 2.19418839f, 4.84296658f, -14.18503333f);\n            Vector4 kBlueVec4 = new Vector4(0.10667330f, 12.64194608f, -60.58204836f, 110.36276771f);\n            Vector2 kRedVec2 = new Vector2(-152.94239396f, 59.28637943f);\n            Vector2 kGreenVec2 = new Vector2(4.27729857f, 2.82956604f);\n            Vector2 kBlueVec2 = new Vector2(-89.90310912f, 27.34824973f);\n\n            t = Mathf.Clamp01(t);\n            Vector4 v4 = new Vector4(1.0f, t, t * t, t * t * t);\n            Vector2 v2 = new Vector2(v4.z, v4.w) * v4.z;\n\n            return new Color(Vector4.Dot(v4, kRedVec4) + Vector2.Dot(v2, kRedVec2),\n                Vector4.Dot(v4, kGreenVec4) + Vector2.Dot(v2, kGreenVec2),\n                Vector4.Dot(v4, kBlueVec4) + Vector2.Dot(v2, kBlueVec2));\n        }\n\n        static Texture2D s_TurboColorRamp;\n        static Texture2D TurboColorRamp\n        {\n            get\n            {\n                if (s_TurboColorRamp == null)\n                {\n                    s_TurboColorRamp = new Texture2D(256, 1);\n                    s_TurboColorRamp.filterMode = FilterMode.Bilinear;\n                    s_TurboColorRamp.wrapMode = TextureWrapMode.Clamp;\n                    Color[] pixels = new Color[256];\n\n                    float inversePixelCount = 1.0f / (pixels.Length - 1);\n                    for (int i = 0; i < pixels.Length; i++)\n                    {\n                        pixels[i] = TurboColorEvaluation(i * inversePixelCount);\n                    }\n\n                    s_TurboColorRamp.SetPixels(pixels);\n                    s_TurboColorRamp.Apply();\n                }\n\n                return s_TurboColorRamp;\n            }\n        }\n\n        bool m_Ramp;\n        float m_QualityModifier = 1;\n        float m_MaxAlpha = 1;\n\n        Vector3 m_Slice;\n\n        float m_StepScale = 1;\n        float m_SurfaceOffset = 0;\n\n        public string GetInfoString()\n        {\n            if (Texture == null) return \"\";\n\n            Vector3 resolution = GetTextureResolution(Texture);\n            var format = GraphicsFormatUtility.GetFormatString(Texture.graphicsFormat);\n            var size = EditorUtility.FormatBytes(TextureUtil.GetStorageMemorySizeLong(Texture));\n            string info = $\"{resolution.x}x{resolution.y}x{resolution.z} {format} {size}\";\n            return info;\n        }\n\n        public void OnEnable()\n        {\n            InitPreviewUtility();\n        }\n\n        public void OnDisable()\n        {\n            if (m_PreviewUtility != null)\n            {\n                m_PreviewUtility.Cleanup();\n                m_PreviewUtility = null;\n            }\n        }\n\n        void InitPreviewUtility()\n        {\n            if (m_PreviewUtility == null)\n            {\n                m_PreviewUtility = new PreviewRenderUtility();\n                m_PreviewUtility.camera.fieldOfView = 30.0f;\n                m_Preview3DMode = Preview3DMode.Volume;\n                m_PreviewDir = new Vector2(0, 0);\n            }\n        }\n\n        float PreviewFloatField(GUIContent content, float value, float width)\n        {\n            float labelWidth = EditorStyles.label.CalcSize(content).x + 2;\n            Rect controlRect = EditorGUILayout.GetControlRect(GUILayout.Width(labelWidth + width));\n            int controlId = GUIUtility.GetControlID(FocusType.Keyboard);\n            Rect labelRect = new Rect(controlRect.position, new Vector2(labelWidth, controlRect.height));\n            controlRect.x += labelRect.width;\n            controlRect.width -= labelRect.width + 2;\n            EditorGUI.PrefixLabel(labelRect, controlId, content);\n            return EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor, controlRect, labelRect, controlId, value, EditorGUI.kFloatFieldFormatString, EditorStyles.numberField, true);\n        }\n\n        public void OnPreviewSettings(Object[] targets)\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture || !SystemInfo.supports3DTextures)\n                return;\n            GUI.enabled = true;\n\n            switch (m_Preview3DMode)\n            {\n                case Preview3DMode.Volume:\n                    m_Ramp = GUILayout.Toggle(m_Ramp, Styles.ramp, EditorStyles.toolbarButton);\n                    m_QualityModifier = TextureInspector.PreviewSettingsSlider(Styles.quality, m_QualityModifier, 0.5f, 8, s_SliderWidth, s_FloatWidth, isInteger: false);\n                    m_MaxAlpha = TextureInspector.PreviewSettingsSlider(Styles.alpha, m_MaxAlpha, 0.01f, 1, s_SliderWidth, s_FloatWidth, isInteger: false);\n                    break;\n\n                case Preview3DMode.Slice:\n                    Vector3 resolution = GetTextureResolution(targets);\n                    m_Ramp = GUILayout.Toggle(m_Ramp, Styles.ramp, EditorStyles.toolbarButton);\n                    m_Slice.x = Mathf.Clamp(PreviewFloatField(Styles.x, m_Slice.x, s_FloatWidth), 0, resolution.x);\n                    m_Slice.y = Mathf.Clamp(PreviewFloatField(Styles.y, m_Slice.y, s_FloatWidth), 0, resolution.y);\n                    m_Slice.z = Mathf.Clamp(PreviewFloatField(Styles.z, m_Slice.z, s_FloatWidth), 0, resolution.z);\n                    break;\n\n                case Preview3DMode.SDF:\n                    m_StepScale = PreviewFloatField(Styles.scale, m_StepScale, s_FloatWidth);\n                    m_SurfaceOffset = PreviewFloatField(Styles.offset, m_SurfaceOffset, s_FloatWidth);\n                    break;\n\n                default:\n                    throw new ArgumentException($\"Unexpected \\\"Preview3DMode\\\" value: \\\"{m_Preview3DMode}\\\"\");\n            }\n\n            if (GUILayout.Toggle(m_Preview3DMode == Preview3DMode.Volume, Styles.volume, EditorStyles.toolbarButton))\n                m_Preview3DMode = Preview3DMode.Volume;\n            if (GUILayout.Toggle(m_Preview3DMode == Preview3DMode.Slice, Styles.slice, EditorStyles.toolbarButton))\n                m_Preview3DMode = Preview3DMode.Slice;\n            if (GUILayout.Toggle(m_Preview3DMode == Preview3DMode.SDF, Styles.sdf, EditorStyles.toolbarButton))\n                m_Preview3DMode = Preview3DMode.SDF;\n        }\n\n        static Vector3 GetTextureResolution(Object[] textures)\n        {\n            if (textures == null || textures.Length < 1) return Vector3.one;\n\n            Vector3 textureResolution = Vector3.one;\n\n            foreach (var texture in textures)\n            {\n                Texture t = texture as Texture;\n                if (t == null || t.dimension != UnityEngine.Rendering.TextureDimension.Tex3D)\n                {\n                    continue;\n                }\n\n                Texture3D texture3D = texture as Texture3D;\n                RenderTexture renderTexture = texture as RenderTexture;\n\n                if (texture3D != null)\n                {\n                    textureResolution.x = Mathf.Max(textureResolution.x, texture3D.width);\n                    textureResolution.y = Mathf.Max(textureResolution.y, texture3D.height);\n                    textureResolution.z = Mathf.Max(textureResolution.z, texture3D.depth);\n                }\n                else if (renderTexture != null)\n                {\n                    textureResolution.x = Mathf.Max(textureResolution.x, renderTexture.width);\n                    textureResolution.y = Mathf.Max(textureResolution.y, renderTexture.height);\n                    textureResolution.z = Mathf.Max(textureResolution.z, renderTexture.volumeDepth);\n                }\n                else\n                {\n                    throw new ArgumentException($\"Could not cast texture to {typeof(Texture3D)} or {typeof(RenderTexture)}\");\n                }\n            }\n\n            return textureResolution;\n        }\n\n        static Vector3 GetTextureResolution(Texture texture) => GetTextureResolution(new[] { texture });\n\n        static Vector3 VoxelSize(Vector3 textureResolution, out float inverseResolution)\n        {\n            inverseResolution = 1.0f / Mathf.Max(textureResolution.x, textureResolution.y, textureResolution.z);\n            return new Vector3(textureResolution.x * inverseResolution, textureResolution.y * inverseResolution, textureResolution.z * inverseResolution);\n        }\n\n        static Vector3 PrepareGeneralPreview(Material material, Texture texture, out Vector3 inverseScale,\n            out float inverseResolution, Gradient customColorRamp = null)\n        {\n            Vector3 voxelSize = VoxelSize(GetTextureResolution(texture), out inverseResolution);\n            inverseScale = new Vector3(1.0f / voxelSize.x, 1.0f / voxelSize.y, 1.0f / voxelSize.z);\n\n            material.mainTexture = texture;\n            material.SetVector(MaterialProps.voxelSize, voxelSize);\n            material.SetVector(MaterialProps.invScale, inverseScale);\n            material.SetFloat(MaterialProps.isNormalMap, TextureInspector.IsNormalMap(texture) ? 1.0f : 0.0f);\n            material.SetFloat(MaterialProps.isSignedFormat, GraphicsFormatUtility.IsSignedFormat(texture.graphicsFormat) ? 1.0f : 0.0f);\n\n            if (customColorRamp != null)\n            {\n                material.SetTexture(MaterialProps.colorRamp, GradientPreviewCache.GetGradientPreview(customColorRamp, false));\n            }\n            else\n            {\n                material.SetTexture(MaterialProps.colorRamp, TurboColorRamp);\n            }\n\n            return voxelSize;\n        }\n\n        internal static void PrepareSDFPreview(Material material, Texture texture, Vector3 scale, float stepScale = 1,\n            float surfaceOffset = 0, Gradient customColorRamp = null)\n        {\n            float inverseResolution;\n            Vector3 inverseScale;\n            PrepareGeneralPreview(material, texture, out inverseScale, out inverseResolution, customColorRamp);\n\n            float boundSize = Mathf.Max(scale.x, scale.y, scale.z) / 2;\n\n            material.SetVector(MaterialProps.globalScale, scale);\n            material.SetFloat(MaterialProps.invResolution, inverseResolution);\n            material.SetFloat(MaterialProps.scale, stepScale * boundSize);\n            material.SetFloat(MaterialProps.offset, surfaceOffset);\n        }\n\n        internal static void PrepareSlicePreview(Material material, Texture texture, Vector3 slice,\n            FilterMode filterMode, bool colorRamp = false, Gradient customColorRamp = null)\n        {\n            float inverseResolution;\n            Vector3 inverseScale;\n            PrepareGeneralPreview(material, texture, out inverseScale, out inverseResolution, customColorRamp);\n            uint colorChannelCount = GraphicsFormatUtility.GetColorComponentCount(texture.graphicsFormat);\n\n            Vector3 voxelSize = material.GetVector(MaterialProps.voxelSize);\n            Vector3 textureResolution = GetTextureResolution(texture);\n            Vector3 positions = new Vector3(slice.x / textureResolution.x, slice.y / textureResolution.y, slice.z / textureResolution.z);\n            positions.x = Mathf.Clamp01(positions.x);\n            positions.y = Mathf.Clamp01(positions.y);\n            positions.z = Mathf.Clamp01(positions.z);\n            positions -= new Vector3(0.5f, 0.5f, 0.5f);\n            positions.Scale(voxelSize);\n            material.SetVector(MaterialProps.positions, positions);\n            material.SetVector(MaterialProps.invChannels, new Vector3(1.0f / colorChannelCount, 1.0f / colorChannelCount, 1.0f / colorChannelCount));\n            material.SetFloat(MaterialProps.filterMode, Convert.ToSingle(filterMode));\n            material.SetFloat(MaterialProps.ramp, Convert.ToSingle(colorRamp));\n        }\n\n        internal static int PrepareVolumePreview(Material material, Texture texture, Vector3 scale, float opacity,\n            FilterMode filterMode, bool colorRamp, Gradient customColorRamp, Camera camera, Matrix4x4 trs, float qualityModifier = 2)\n        {\n            float inverseResolution;\n            Vector3 inverseScale;\n            PrepareGeneralPreview(material, texture, out inverseScale, out inverseResolution, customColorRamp);\n            uint colorChannelCount = GraphicsFormatUtility.GetColorComponentCount(texture.graphicsFormat);\n\n            material.SetVector(MaterialProps.globalScale, scale);\n            material.SetFloat(MaterialProps.ramp, Convert.ToSingle(colorRamp));\n            material.SetFloat(MaterialProps.invResolution, inverseResolution);\n            material.SetVector(MaterialProps.invChannels, new Vector3(1.0f / colorChannelCount, 1.0f / colorChannelCount, 1.0f / colorChannelCount));\n            material.SetFloat(MaterialProps.alpha, Mathf.Pow(Mathf.Clamp01(opacity), 3));\n            material.SetFloat(MaterialProps.filterMode, Convert.ToSingle(filterMode));\n\n            float quality = inverseResolution / qualityModifier / 2;\n            material.SetFloat(MaterialProps.quality, quality);\n\n            material.SetMatrix(MaterialProps.CamToW, camera.cameraToWorldMatrix);\n            material.SetMatrix(MaterialProps.WToCam, camera.worldToCameraMatrix);\n            material.SetMatrix(MaterialProps.ObjToW, trs);\n            material.SetMatrix(MaterialProps.WToObj, trs.inverse);\n\n            return Convert.ToInt32(1 / inverseResolution * qualityModifier * 2);\n        }\n\n        void DrawPreview()\n        {\n            if (!SystemInfo.supports3DTextures)\n                return;\n            if (Texture == null) return;\n            if (!SystemInfo.supportsCompressed3DTextures && GraphicsFormatUtility.IsCompressedFormat(Texture.graphicsFormat))\n                return;\n\n            Quaternion rotation = Quaternion.Euler(-m_PreviewDir.y + s_InitialRotation.x, -m_PreviewDir.x + s_InitialRotation.y, 0);\n\n            m_PreviewUtility.camera.transform.position = rotation * Vector3.back * m_ViewDistance;\n            m_PreviewUtility.camera.transform.rotation = rotation;\n\n            Vector3 scale = Vector3.one;\n            switch (m_Preview3DMode)\n            {\n                case Preview3DMode.Volume:\n                    int sampleCount = PrepareVolumePreview(Materials.Volume, Texture, scale, m_MaxAlpha, Texture.filterMode,\n                        m_Ramp, null, m_PreviewUtility.camera, Matrix4x4.identity, m_QualityModifier);\n                    GL.PushMatrix();\n                    GL.LoadProjectionMatrix(m_PreviewUtility.camera.projectionMatrix);\n                    Materials.Volume.SetPass(0);\n                    Graphics.DrawProceduralNow(MeshTopology.Quads, 4, sampleCount);\n                    GL.PopMatrix();\n                    return;\n                case Preview3DMode.Slice:\n                    PrepareSlicePreview(Materials.Slice, Texture, m_Slice, Texture.filterMode, m_Ramp);\n                    m_PreviewUtility.DrawMesh(Handles.cubeMesh, Matrix4x4.Scale(scale + new Vector3(0.0001f, 0.0001f, 0.0001f)), Materials.Slice, 0);\n                    break;\n                case Preview3DMode.SDF:\n                    PrepareSDFPreview(Materials.SDF, Texture, scale, m_StepScale, m_SurfaceOffset);\n                    m_PreviewUtility.DrawMesh(Handles.cubeMesh, Matrix4x4.Scale(scale), Materials.SDF, 0);\n                    break;\n            }\n\n            m_PreviewUtility.Render();\n        }\n\n        bool IsPreviewExpensiveToDisplay()\n        {\n            if (m_Preview3DMode == Preview3DMode.Volume || m_Preview3DMode == Preview3DMode.SDF)\n            {\n                Vector3 res = GetTextureResolution(Texture);\n                return res.x * res.y * res.z > s_MaxPreviewPixelCount;\n            }\n            return false;\n        }\n\n        public void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture || !SystemInfo.supports3DTextures)\n            {\n                if (Event.current.type == EventType.Repaint)\n                    EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), \"3D texture preview not supported\");\n                return;\n            }\n            if (Texture == null) return;\n            if (!SystemInfo.supportsCompressed3DTextures && GraphicsFormatUtility.IsCompressedFormat(Texture.graphicsFormat))\n            {\n                if (Event.current.type == EventType.Repaint)\n                    EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), \"Compressed 3D texture preview is not supported\");\n                return;\n            }\n            if (IsPreviewExpensiveToDisplay())\n            {\n                if (Event.current.type == EventType.Repaint)\n                    EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), \"Preview disabled (3D texture too large to display)\");\n                return;\n            }\n\n            InitPreviewUtility();\n            Event e = Event.current;\n            m_PreviewDir = PreviewGUI.Drag2D(m_PreviewDir, r);\n\n            if (e.type == EventType.ScrollWheel)\n            {\n                m_ViewDistance = Mathf.Clamp(m_ViewDistance + e.delta.y * (0.01f + Mathf.Sqrt(m_ViewDistance) / 20), s_MinViewDistance, s_MaxViewDistance);\n                e.Use();\n                EditorWindow.focusedWindow.Repaint();\n            }\n\n            if (e.type != EventType.Repaint)\n                return;\n\n            m_PreviewUtility.BeginPreview(r, background);\n            DrawPreview();\n            m_PreviewUtility.EndAndDrawPreview(r);\n        }\n\n        public Texture2D RenderStaticPreview(Texture texture, int width, int height)\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture || !SystemInfo.supports3DTextures)\n                return null;\n            if (texture == null)\n                return null;\n\n            Texture = texture as Texture3D;\n\n            OnEnable();\n            m_QualityModifier *= 2;\n\n            if (IsPreviewExpensiveToDisplay())\n                return null;\n\n            Rect r = new Rect(0, 0, width, height);\n            m_PreviewUtility.BeginStaticPreview(r);\n            DrawPreview();\n            return m_PreviewUtility.EndStaticPreview();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/TextureInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEngine.Rendering;\nusing UnityEngine.Experimental.Rendering;\nusing VirtualTexturing = UnityEngine.Rendering.VirtualTexturing;\n\nnamespace UnityEditor\n{\n    internal class PreviewHelpers\n    {\n        //This assumes NPOT RenderTextures since Unity 4.3 has this as a requirment already.\n        internal static void AdjustWidthAndHeightForStaticPreview(int textureWidth, int textureHeight, ref int width, ref int height)\n        {\n            int orgWidth = width;\n            int orgHeight = height;\n\n            if (textureWidth <= width && textureHeight <= height)\n            {\n                // For textures smaller than our wanted width and height we use the textures size\n                // to prevent excessive magnification artifacts (as seen in the Asset Store).\n                width = textureWidth;\n                height = textureHeight;\n            }\n            else\n            {\n                // For textures larger than our wanted width and height we ensure to\n                // keep aspect ratio of the texture and fit it to best match our wanted width and height.\n                float relWidth = width / (float)textureWidth;\n                float relHeight = height / (float)textureHeight;\n\n                float scale = Mathf.Min(relHeight, relWidth);\n\n                width = Mathf.RoundToInt(textureWidth * scale);\n                height = Mathf.RoundToInt(textureHeight * scale);\n            }\n\n            // Ensure we have not scaled size below 2 pixels\n            width = Mathf.Clamp(width, 2, orgWidth);\n            height = Mathf.Clamp(height, 2, orgHeight);\n        }\n    }\n\n    internal class TextureMipLevels\n    {\n        public Texture2D texture { get; }\n        public int lastMipmapLevel;\n        public bool loadAllMips;\n\n        public TextureMipLevels(Texture2D _texture)\n        {\n            texture = _texture;\n            if (texture)\n            {\n                lastMipmapLevel = texture.loadedMipmapLevel;\n                loadAllMips = texture.loadAllMips;\n            }\n        }\n    }\n\n    [CustomEditor(typeof(Texture2D))]\n    [CanEditMultipleObjects]\n    internal class TextureInspector : Editor\n    {\n        class Styles\n        {\n            public GUIContent smallZoom, largeZoom;\n            public GUIStyle toolbarButton, previewSlider, previewSliderThumb, previewLabel, mipLevelLabel;\n\n            public readonly GUIContent[] previewButtonContents =\n            {\n                EditorGUIUtility.TrIconContent(\"PreTexRGB\"),\n                EditorGUIUtility.TrIconContent(\"PreTexR\"),\n                EditorGUIUtility.TrIconContent(\"PreTexG\"),\n                EditorGUIUtility.TrIconContent(\"PreTexB\"),\n                EditorGUIUtility.TrIconContent(\"PreTexA\")\n            };\n\n            public readonly GUIContent wrapModeLabel = EditorGUIUtility.TrTextContent(\"Wrap Mode\");\n            public readonly GUIContent wrapU = EditorGUIUtility.TrTextContent(\"U axis\");\n            public readonly GUIContent wrapV = EditorGUIUtility.TrTextContent(\"V axis\");\n            public readonly GUIContent wrapW = EditorGUIUtility.TrTextContent(\"W axis\");\n\n            public readonly GUIContent[] wrapModeContents =\n            {\n                EditorGUIUtility.TrTextContent(\"Repeat\"),\n                EditorGUIUtility.TrTextContent(\"Clamp\"),\n                EditorGUIUtility.TrTextContent(\"Mirror\"),\n                EditorGUIUtility.TrTextContent(\"Mirror Once\"),\n                EditorGUIUtility.TrTextContent(\"Per-axis\")\n            };\n            public readonly int[] wrapModeValues =\n            {\n                (int)TextureWrapMode.Repeat,\n                (int)TextureWrapMode.Clamp,\n                (int)TextureWrapMode.Mirror,\n                (int)TextureWrapMode.MirrorOnce,\n                -1\n            };\n\n            public Styles()\n            {\n                smallZoom = EditorGUIUtility.IconContent(\"PreTextureMipMapLow\");\n                largeZoom = EditorGUIUtility.IconContent(\"PreTextureMipMapHigh\");\n\n                toolbarButton = \"toolbarbutton\";\n                previewSlider = \"preSlider\";\n                previewSliderThumb = \"preSliderThumb\";\n                previewLabel = \"toolbarLabel\";\n\n                mipLevelLabel = \"PreOverlayLabel\";\n                mipLevelLabel.alignment = TextAnchor.UpperCenter;\n                mipLevelLabel.padding.top = 5;\n            }\n        }\n        static Styles s_Styles;\n\n        internal enum PreviewMode\n        {\n            RGB,\n            R,\n            G,\n            B,\n            A,\n        }\n\n        internal PreviewMode m_PreviewMode = PreviewMode.RGB;\n        public bool showAlpha\n        {\n            get { return m_PreviewMode == PreviewMode.A; }\n        }\n\n        // Plain Texture\n        protected SerializedProperty m_WrapU;\n        protected SerializedProperty m_WrapV;\n        protected SerializedProperty m_WrapW;\n        protected SerializedProperty m_FilterMode;\n        protected SerializedProperty m_Aniso;\n\n        [SerializeField]\n        protected Vector2 m_Pos;\n\n        [SerializeField]\n        float m_MipLevel = 0;\n\n        [SerializeField]\n        protected float m_ExposureSliderValue = 0.0f;\n\n        protected float m_ExposureSliderMax = 16f; // this value can be altered by the user\n\n        CubemapPreview m_CubemapPreview = new CubemapPreview();\n        Texture3DPreview m_Texture3DPreview;\n        protected Texture2DArrayPreview m_Texture2DArrayPreview = new Texture2DArrayPreview();\n\n        List<TextureMipLevels> m_TextureMipLevels = new List<TextureMipLevels>();\n\n        public static bool IsNormalMap(Texture t)\n        {\n            TextureUsageMode mode = TextureUtil.GetUsageMode(t);\n            return TextureUtil.IsNormalMapUsageMode(mode);\n        }\n\n        protected virtual void OnEnable()\n        {\n            Initialize();\n        }\n\n        void CacheSerializedProperties()\n        {\n            m_WrapU = serializedObject.FindProperty(\"m_TextureSettings.m_WrapU\");\n            m_WrapV = serializedObject.FindProperty(\"m_TextureSettings.m_WrapV\");\n            m_WrapW = serializedObject.FindProperty(\"m_TextureSettings.m_WrapW\");\n            m_FilterMode = serializedObject.FindProperty(\"m_TextureSettings.m_FilterMode\");\n            m_Aniso = serializedObject.FindProperty(\"m_TextureSettings.m_Aniso\");\n        }\n\n        void Initialize()\n        {\n            CacheSerializedProperties();\n            RecordTextureMipLevels();\n            SetMipLevelDefaultForVT();\n\n            if(m_Texture3DPreview == null)\n                m_Texture3DPreview = CreateInstance<Texture3DPreview>();\n\n            if (IsTexture3D())\n            {\n                m_Texture3DPreview.Texture = target as Texture;\n            }\n            m_Texture3DPreview.OnEnable();\n        }\n\n        //VT textures can be very large and aren't in GPU memory yet. To avoid unnecessary streaming and cache use, we limit the default shown mip resolution.\n        private void SetMipLevelDefaultForVT()\n        {\n            foreach (var t in targets)\n            {\n                var tex = t as Texture;\n                if (EditorGUI.UseVTMaterial(tex))\n                {\n                    int mips = TextureUtil.GetMipmapCount(tex);\n                    const int numMipsFor1K = 11;\n\n                    if (mips > numMipsFor1K)\n                    {\n                        mipLevel = Mathf.Max(mipLevel, mips - numMipsFor1K); //set to 1024x1024 or less\n                    }\n                }\n            }\n        }\n\n        public override void ReloadPreviewInstances()\n        {\n            SetMipLevelDefaultForVT();\n        }\n\n        private void RecordTextureMipLevels()\n        {\n            m_TextureMipLevels.Clear();\n            foreach (var item in targets)\n            {\n                Texture2D texture = item as Texture2D;\n                if (texture)\n                {\n                    m_TextureMipLevels.Add(new TextureMipLevels(texture));\n                    texture.loadAllMips = true;\n                }\n            }\n        }\n\n        private void RestoreLastTextureMipLevels()\n        {\n            foreach (TextureMipLevels textureInfo in m_TextureMipLevels)\n            {\n                if (textureInfo.texture == null)\n                    continue;\n\n                textureInfo.texture.loadAllMips = textureInfo.loadAllMips;\n            }\n        }\n\n        protected virtual void OnDisable()\n        {\n            RestoreLastTextureMipLevels();\n\n            m_TextureMipLevels.Clear();\n\n            m_CubemapPreview.OnDisable();\n            m_Texture3DPreview.OnDisable();\n            DestroyImmediate(m_Texture3DPreview);\n        }\n\n        public override bool RequiresConstantRepaint()\n        {\n            //Keep repainting if the texture is rendered with a virtual texturing material because we don't know when all texture tiles will be streamed in\n            if (hasTargetUsingVTMaterial)\n                return true;\n\n            bool mipsHaveChanged = false;\n\n            foreach (TextureMipLevels textureInfo in m_TextureMipLevels)\n            {\n                if (textureInfo.texture == null)\n                    continue;\n\n                // See if texture has new mips loaded\n                if (textureInfo.texture.loadedMipmapLevel != textureInfo.lastMipmapLevel)\n                {\n                    textureInfo.lastMipmapLevel = textureInfo.texture.loadedMipmapLevel;\n\n                    if (textureInfo.lastMipmapLevel == mipLevel)\n                    {\n                        // Don't early out- We need to finish the loop to update them all this frame\n                        mipsHaveChanged = true;\n                    }\n                }\n            }\n\n            return mipsHaveChanged;\n        }\n\n        internal void SetCubemapIntensity(float intensity)\n        {\n            if (m_CubemapPreview != null)\n                m_CubemapPreview.SetIntensity(intensity);\n        }\n\n        public float GetMipLevelForRendering()\n        {\n            if (target == null)\n                return 0.0f;\n\n            if (IsCubemap())\n                return m_CubemapPreview.GetMipLevelForRendering(target as Texture);\n            else\n                return Mathf.Min(m_MipLevel, TextureUtil.GetMipmapCount(target as Texture) - 1);\n        }\n\n        public int GetMipmapLimit(Texture t)\n        {\n            switch (t)\n            {\n                case Texture2D tex:\n                    return tex.activeMipmapLimit;\n                case Texture2DArray tex:\n                    return tex.activeMipmapLimit;\n                default:\n                    return 0;\n            }\n        }\n\n        public float mipLevel\n        {\n            get\n            {\n                if (IsCubemap())\n                    return m_CubemapPreview.mipLevel;\n                else\n                    return m_MipLevel;\n            }\n            set\n            {\n                m_CubemapPreview.mipLevel = value;\n                m_MipLevel = value;\n            }\n        }\n\n        // Note: Even though this is a custom editor for Texture2D, the target may not be a Texture2D,\n        // since other editors inherit from this one, such as ProceduralTextureInspector.\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n            EditorGUI.BeginChangeCheck();\n\n            if (IsCubemapArray())\n            {\n                DoFilterModePopup();\n            }\n            else\n            {\n                DoWrapModePopup();\n                DoFilterModePopup();\n                DoAnisoLevelSlider();\n            }\n\n            serializedObject.ApplyModifiedProperties();\n\n            if (EditorGUI.EndChangeCheck())\n                ApplySettingsToTextures();\n        }\n\n        internal override void PostSerializedObjectCreation()\n        {\n            base.PostSerializedObjectCreation();\n\n            Initialize();\n        }\n\n        // wrap/filter/aniso editors will change serialized object\n        // but in case of textures we need an extra step to ApplySettings (so rendering uses new values)\n        // alas we cant have good things: it will be PITA to make sure we always call that after applying changes to serialized object\n        // meaning that we need to work without relying on it, hence we do similar to TextureImporter:\n        //   use TextureUtil methods to update texture settings from current values of serialized property\n        // another possibility would be to do it separately for wrap/filter/aniso\n        //   alas for wrapmode i dont see how it can be done clearly and leaving it out seems a bit weird\n\n        protected void ApplySettingsToTextures()\n        {\n            bool anisoDiffer = m_Aniso.hasMultipleDifferentValues, filterDiffer = m_FilterMode.hasMultipleDifferentValues;\n            bool wrapDiffer = m_WrapU.hasMultipleDifferentValues || m_WrapV.hasMultipleDifferentValues || m_WrapW.hasMultipleDifferentValues;\n\n            foreach (Texture tex in targets)\n            {\n                if (!anisoDiffer)\n                    TextureUtil.SetAnisoLevelNoDirty(tex, m_Aniso.intValue);\n\n                if (!filterDiffer)\n                    TextureUtil.SetFilterModeNoDirty(tex, (FilterMode)m_FilterMode.intValue);\n\n                if (!wrapDiffer)\n                    TextureUtil.SetWrapModeNoDirty(tex, (TextureWrapMode)m_WrapU.intValue, (TextureWrapMode)m_WrapV.intValue, (TextureWrapMode)m_WrapW.intValue);\n            }\n        }\n\n        static void WrapModeAxisPopup(GUIContent label, SerializedProperty wrapProperty)\n        {\n            // In texture importer settings, serialized properties for wrap modes can contain -1, which means \"use default\".\n            var wrap = (TextureWrapMode)Mathf.Max(wrapProperty.intValue, 0);\n            Rect rect = EditorGUILayout.GetControlRect();\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.BeginProperty(rect, label, wrapProperty);\n            wrap = (TextureWrapMode)EditorGUI.EnumPopup(rect, label, wrap);\n            EditorGUI.EndProperty();\n            if (EditorGUI.EndChangeCheck())\n            {\n                wrapProperty.intValue = (int)wrap;\n            }\n        }\n\n        private static bool IsAnyTextureObjectUsingPerAxisWrapMode(Object[] objects, bool isVolumeTexture)\n        {\n            foreach (var o in objects)\n            {\n                int u = 0, v = 0, w = 0;\n                // the objects can be Textures themselves, or texture-related importers\n                if (o is Texture)\n                {\n                    var ti = (Texture)o;\n                    u = (int)ti.wrapModeU;\n                    v = (int)ti.wrapModeV;\n                    w = (int)ti.wrapModeW;\n                }\n                if (o is TextureImporter)\n                {\n                    var ti = (TextureImporter)o;\n                    u = (int)ti.wrapModeU;\n                    v = (int)ti.wrapModeV;\n                    w = (int)ti.wrapModeW;\n                }\n                if (o is IHVImageFormatImporter)\n                {\n                    var ti = (IHVImageFormatImporter)o;\n                    u = (int)ti.wrapModeU;\n                    v = (int)ti.wrapModeV;\n                    w = (int)ti.wrapModeW;\n                }\n                u = Mathf.Max(0, u);\n                v = Mathf.Max(0, v);\n                w = Mathf.Max(0, w);\n                if (u != v)\n                {\n                    return true;\n                }\n                if (isVolumeTexture)\n                {\n                    if (u != w || v != w)\n                    {\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        // showPerAxisWrapModes is state of whether \"Per-Axis\" mode should be active in the main dropdown.\n        // It is set automatically if wrap modes in UVW are different, or if user explicitly picks \"Per-Axis\" option -- when that one is picked,\n        // then it should stay true even if UVW wrap modes will initially be the same.\n        // enforcePerAxis is used to always show all axis option. In some cases (Preset), we want to show each property separately to make sure users can act on one or another with the context menu.\n        // Note: W wrapping mode is only shown when isVolumeTexture is true.\n        internal static void WrapModePopup(SerializedProperty wrapU, SerializedProperty wrapV, SerializedProperty wrapW, bool isVolumeTexture, ref bool showPerAxisWrapModes, bool enforcePerAxis)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            // In texture importer settings, serialized properties for things like wrap modes can contain -1;\n            // that seems to indicate \"use defaults, user has not changed them to anything\" but not totally sure.\n            // Show them as Repeat wrap modes in the popups.\n            var wu = (TextureWrapMode)Mathf.Max(wrapU.intValue, 0);\n            var wv = (TextureWrapMode)Mathf.Max(wrapV.intValue, 0);\n            var ww = (TextureWrapMode)Mathf.Max(wrapW.intValue, 0);\n\n            // automatically go into per-axis mode if values are already different\n            if (wu != wv) showPerAxisWrapModes = true;\n            if (isVolumeTexture)\n            {\n                if (wu != ww || wv != ww) showPerAxisWrapModes = true;\n            }\n\n            // It's not possible to determine whether any single texture in the whole selection is using per-axis wrap modes\n            // just from SerializedProperty values. They can only tell if \"some values in whole selection are different\" (e.g.\n            // wrap value on U axis is not the same among all textures), and can return value of \"some\" object in the selection\n            // (typically based on object loading order). So in order for more intuitive behavior with multi-selection,\n            // we go over the actual objects when there's >1 object selected and some wrap modes are different.\n            if (!showPerAxisWrapModes)\n            {\n                if (wrapU.hasMultipleDifferentValues || wrapV.hasMultipleDifferentValues || (isVolumeTexture && wrapW.hasMultipleDifferentValues))\n                {\n                    if (IsAnyTextureObjectUsingPerAxisWrapMode(wrapU.serializedObject.targetObjects, isVolumeTexture))\n                    {\n                        showPerAxisWrapModes = true;\n                    }\n                }\n            }\n\n            int value = showPerAxisWrapModes || enforcePerAxis ? -1 : (int)wu;\n\n            // main wrap mode popup\n            if (enforcePerAxis)\n            {\n                EditorGUILayout.LabelField(s_Styles.wrapModeLabel);\n            }\n            else\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = !showPerAxisWrapModes && (wrapU.hasMultipleDifferentValues || wrapV.hasMultipleDifferentValues || (isVolumeTexture && wrapW.hasMultipleDifferentValues));\n                value = EditorGUILayout.IntPopup(s_Styles.wrapModeLabel, value, s_Styles.wrapModeContents, s_Styles.wrapModeValues);\n                if (EditorGUI.EndChangeCheck() && value != -1)\n                {\n                    // assign the same wrap mode to all axes, and hide per-axis popups\n                    wrapU.intValue = value;\n                    wrapV.intValue = value;\n                    wrapW.intValue = value;\n                    showPerAxisWrapModes = false;\n                }\n                EditorGUI.showMixedValue = false;\n            }\n\n            // show per-axis popups if needed\n            if (value == -1)\n            {\n                showPerAxisWrapModes = true;\n                EditorGUI.indentLevel++;\n                WrapModeAxisPopup(s_Styles.wrapU, wrapU);\n                WrapModeAxisPopup(s_Styles.wrapV, wrapV);\n                if (isVolumeTexture)\n                {\n                    WrapModeAxisPopup(s_Styles.wrapW, wrapW);\n                }\n                EditorGUI.indentLevel--;\n            }\n        }\n\n        bool m_ShowPerAxisWrapModes = false;\n        protected void DoWrapModePopup()\n        {\n            WrapModePopup(m_WrapU, m_WrapV, m_WrapW, IsTexture3D(), ref m_ShowPerAxisWrapModes, false);\n        }\n\n        protected void DoFilterModePopup()\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = m_FilterMode.hasMultipleDifferentValues;\n            FilterMode filter = (FilterMode)m_FilterMode.intValue;\n            filter = (FilterMode)EditorGUILayout.EnumPopup(EditorGUIUtility.TempContent(\"Filter Mode\"), filter);\n            EditorGUI.showMixedValue = false;\n            if (EditorGUI.EndChangeCheck())\n                m_FilterMode.intValue = (int)filter;\n        }\n\n        protected void DoAnisoLevelSlider()\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = m_Aniso.hasMultipleDifferentValues;\n            int aniso = m_Aniso.intValue;\n            aniso = EditorGUILayout.IntSlider(\"Aniso Level\", aniso, 0, 16);\n            EditorGUI.showMixedValue = false;\n            if (EditorGUI.EndChangeCheck())\n                m_Aniso.intValue = aniso;\n            DoAnisoGlobalSettingNote(aniso);\n        }\n\n        internal static void DoAnisoGlobalSettingNote(int anisoLevel)\n        {\n            if (anisoLevel > 1)\n            {\n                if (QualitySettings.anisotropicFiltering == AnisotropicFiltering.Disable)\n                    EditorGUILayout.HelpBox(\"Anisotropic filtering is disabled for all textures in Quality Settings.\", MessageType.Info);\n                else if (QualitySettings.anisotropicFiltering == AnisotropicFiltering.ForceEnable)\n                    EditorGUILayout.HelpBox(\"Anisotropic filtering is enabled for all textures in Quality Settings.\", MessageType.Info);\n            }\n        }\n\n        protected bool IsCubemap()\n        {\n            var t = target as Texture;\n            return t != null && t.dimension == UnityEngine.Rendering.TextureDimension.Cube;\n        }\n\n        bool IsCubemapArray()\n        {\n            var t = target as Texture;\n            return t != null && t.dimension == UnityEngine.Rendering.TextureDimension.CubeArray;\n        }\n\n        bool IsTexture3D()\n        {\n            var t = target as Texture;\n            return t != null && t.dimension == UnityEngine.Rendering.TextureDimension.Tex3D;\n        }\n\n        bool IsTexture2DArray()\n        {\n            var t = target as Texture;\n            return t != null && t.dimension == UnityEngine.Rendering.TextureDimension.Tex2DArray;\n        }\n\n        protected float GetExposureValueForTexture(Texture t)\n        {\n            if (NeedsExposureControl(t))\n            {\n                return m_ExposureSliderValue;\n            }\n            return 0.0f;\n        }\n\n        // Native NeedsExposureControl doesn't work for RenderTextures (they are hardcoded to return kTexFormatUnknown).\n        protected bool NeedsExposureControl(Texture t)\n        {\n            TextureUsageMode usageMode = TextureUtil.GetUsageMode(t);\n            return GraphicsFormatUtility.IsHDRFormat(t.graphicsFormat) || TextureUtil.IsRGBMUsageMode(usageMode) || TextureUtil.IsDoubleLDRUsageMode(usageMode);\n        }\n\n        public override void OnPreviewSettings()\n        {\n            // TextureInspector code is reused for RenderTexture and Cubemap inspectors.\n            // Make sure we can handle the situation where target is just a Texture and\n            // not a Texture2D. It's also used for large popups for mini texture fields,\n            // and while it's being shown the actual texture object might disappear --\n            // make sure to handle null targets.\n            Texture tex = target as Texture;\n\n            bool alphaOnly = true;\n            bool hasAlpha = false;\n            bool needsExposureControl = false;\n            int mipCount = 1;\n\n            foreach (Texture t in targets)\n            {\n                if (t == null) // texture might have disappeared while we're showing this in a preview popup\n                    continue;\n\n                mipCount = Mathf.Max(mipCount, TextureUtil.GetMipmapCount(t));\n\n                TextureUsageMode mode = TextureUtil.GetUsageMode(t);\n\n                if (!GraphicsFormatUtility.IsAlphaOnlyFormat(t.graphicsFormat))\n                    alphaOnly = false;\n\n                if (GraphicsFormatUtility.HasAlphaChannel(t.graphicsFormat))\n                {\n                    if (mode == TextureUsageMode.Default) // all other texture usage modes don't displayable alpha\n                        hasAlpha = true;\n                }\n\n                // 3D texture previewer doesn't support an exposure value.\n                if (t.dimension != TextureDimension.Tex3D && NeedsExposureControl(t))\n                    needsExposureControl = true;\n            }\n\n            if (needsExposureControl)\n            {\n                OnExposureSlider();\n            }\n\n            if (IsCubemap())\n            {\n                m_CubemapPreview.OnPreviewSettings(targets, mipCount, alphaOnly, hasAlpha);\n                return;\n            }\n\n            if (IsTexture3D())\n            {\n                m_Texture3DPreview.OnPreviewSettings(targets);\n                return;\n            }\n\n            if (IsTexture2DArray() && !SystemInfo.supports2DArrayTextures)\n                return;\n\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            List<PreviewMode> previewCandidates = new List<PreviewMode>(5);\n            previewCandidates.Add(PreviewMode.RGB);\n            previewCandidates.Add(PreviewMode.R);\n            previewCandidates.Add(PreviewMode.G);\n            previewCandidates.Add(PreviewMode.B);\n            previewCandidates.Add(PreviewMode.A);\n\n            if (alphaOnly)\n            {\n                previewCandidates.Clear();\n                previewCandidates.Add(PreviewMode.A);\n                m_PreviewMode = PreviewMode.A;\n            }\n            else if (!hasAlpha)\n            {\n                previewCandidates.Remove(PreviewMode.A);\n            }\n\n            if (previewCandidates.Count > 1 && tex != null && !IsNormalMap(tex))\n            {\n                int selectedIndex = previewCandidates.IndexOf(m_PreviewMode);\n                if (selectedIndex == -1)\n                    selectedIndex = 0;\n\n                if (previewCandidates.Contains(PreviewMode.RGB))\n                    m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.RGB, s_Styles.previewButtonContents[0], s_Styles.toolbarButton)\n                        ? PreviewMode.RGB\n                        : m_PreviewMode;\n                if (previewCandidates.Contains(PreviewMode.R))\n                    m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.R, s_Styles.previewButtonContents[1], s_Styles.toolbarButton)\n                        ? PreviewMode.R\n                        : m_PreviewMode;\n                if (previewCandidates.Contains(PreviewMode.G))\n                    m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.G, s_Styles.previewButtonContents[2], s_Styles.toolbarButton)\n                        ? PreviewMode.G\n                        : m_PreviewMode;\n                if (previewCandidates.Contains(PreviewMode.B))\n                    m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.B, s_Styles.previewButtonContents[3], s_Styles.toolbarButton)\n                        ? PreviewMode.B\n                        : m_PreviewMode;\n                if (previewCandidates.Contains(PreviewMode.A))\n                    m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.A, s_Styles.previewButtonContents[4], s_Styles.toolbarButton)\n                        ? PreviewMode.A\n                        : m_PreviewMode;\n            }\n\n            if (IsTexture2DArray())\n            {\n                m_Texture2DArrayPreview.OnPreviewSettings(tex);\n            }\n\n            if (mipCount > 1)\n            {\n                int mipmapLimit = GetMipmapLimit(target as Texture);\n                GUILayout.Box(s_Styles.smallZoom, s_Styles.previewLabel);\n                GUI.changed = false;\n\n                int leftValue = mipCount - mipmapLimit - 1;\n                if (m_MipLevel > leftValue)\n                {\n                    // Left value can change depending on the mipmap limit. Cap slider value appropriately.\n                    m_MipLevel = leftValue;\n                }\n                m_MipLevel = Mathf.Round(GUILayout.HorizontalSlider(m_MipLevel, leftValue, 0, s_Styles.previewSlider, s_Styles.previewSliderThumb, GUILayout.MaxWidth(64)));\n\n                //For now, we don't have mipmaps smaller than the tile size when using VT.\n                if (EditorGUI.UseVTMaterial(tex))\n                {\n                    int numMipsOfTile = (int)Mathf.Log(VirtualTexturing.EditorHelpers.tileSize, 2) + 1;\n                    m_MipLevel = Mathf.Min(m_MipLevel, Mathf.Max(mipCount - numMipsOfTile, 0));\n                }\n\n                GUILayout.Box(s_Styles.largeZoom, s_Styles.previewLabel);\n            }\n        }\n\n        public void OnExposureSlider()\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n            m_ExposureSliderValue = EditorGUIInternal.ExposureSlider(m_ExposureSliderValue, ref m_ExposureSliderMax, s_Styles.previewSlider);\n        }\n\n        public override bool HasPreviewGUI()\n        {\n            return (target != null);\n        }\n\n        internal bool hasTargetUsingVTMaterial\n        {\n            get\n            {\n                foreach (var t in targets)\n                    if (EditorGUI.UseVTMaterial(t as Texture))\n                        return true;\n\n                return false;\n            }\n        }\n\n\n        public override void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            if (Event.current.type == EventType.Repaint)\n                background.Draw(r, false, false, false, false);\n\n            // show texture\n            Texture t = target as Texture;\n            if (t == null) // texture might be gone by now, in case this code is used for floating texture preview\n                return;\n\n            GraphicsFormat format = t.graphicsFormat;\n            if (!(GraphicsFormatUtility.IsIEEE754Format(format) || GraphicsFormatUtility.IsNormFormat(format)))\n            {\n                EditorGUI.HelpBox(r, \"This preview only supports floating point or normalized formats.\", MessageType.Warning);\n                return;\n            }\n\n            // Render target must be created before we can display it (case 491797)\n            RenderTexture rt = t as RenderTexture;\n            if (rt != null)\n            {\n                if (rt.Create() == false)\n                {\n                    return;\n                }\n            }\n\n            if (IsCubemap())\n            {\n                m_CubemapPreview.OnPreviewGUI(t, r, background, GetExposureValueForTexture(t));\n                return;\n            }\n\n            if (IsTexture3D())\n            {\n                m_Texture3DPreview.Texture = t;\n                m_Texture3DPreview.OnPreviewGUI(r, background);\n                return;\n            }\n\n            if (IsTexture2DArray())\n            {\n                m_Texture2DArrayPreview.OnPreviewGUI(t, r, background, GetExposureValueForTexture(t), m_PreviewMode, m_MipLevel);\n                return;\n            }\n\n            // target can report zero sizes in some cases just after a parameter change;\n            // guard against that.\n            int texWidth = Mathf.Max(t.width, 1);\n            int texHeight = Mathf.Max(t.height, 1);\n\n            float mipLevel = GetMipLevelForRendering();\n            float zoomLevel = Mathf.Min(Mathf.Min(r.width / texWidth, r.height / texHeight), 1);\n            Rect wantedRect = new Rect(r.x, r.y, texWidth * zoomLevel, texHeight * zoomLevel);\n            PreviewGUI.BeginScrollView(r, m_Pos, wantedRect, \"PreHorizontalScrollbar\", \"PreHorizontalScrollbarThumb\");\n            FilterMode oldFilter = t.filterMode;\n            TextureUtil.SetFilterModeNoDirty(t, FilterMode.Point);\n            Texture2D t2d = t as Texture2D;\n            ColorWriteMask colorWriteMask = ColorWriteMask.All;\n\n            switch (m_PreviewMode)\n            {\n                case PreviewMode.R:\n                    colorWriteMask = ColorWriteMask.Red | ColorWriteMask.Alpha;\n                    break;\n                case PreviewMode.G:\n                    colorWriteMask = ColorWriteMask.Green | ColorWriteMask.Alpha;\n                    break;\n                case PreviewMode.B:\n                    colorWriteMask = ColorWriteMask.Blue | ColorWriteMask.Alpha;\n                    break;\n            }\n\n            if (m_PreviewMode == PreviewMode.A)\n            {\n                EditorGUI.DrawTextureAlpha(wantedRect, t, ScaleMode.StretchToFill, 0, mipLevel);\n            }\n            else\n            {\n                if (t2d != null && t2d.alphaIsTransparency)\n                    EditorGUI.DrawTextureTransparent(wantedRect, t, ScaleMode.StretchToFill, 0, mipLevel,\n                        colorWriteMask, GetExposureValueForTexture(t));\n                else\n                    EditorGUI.DrawPreviewTexture(wantedRect, t, null, ScaleMode.StretchToFill, 0, mipLevel,\n                        colorWriteMask, GetExposureValueForTexture(t));\n            }\n\n            // TODO: Less hacky way to prevent sprite rects to not appear in smaller previews like icons.\n            if ((wantedRect.width > 32 && wantedRect.height > 32) && Event.current.type == EventType.Repaint)\n            {\n                string path = AssetDatabase.GetAssetPath(t);\n                TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;\n                SpriteMetaData[] spritesheet = textureImporter != null ? textureImporter.GetSpriteMetaDatas() : null;\n\n                if (spritesheet != null && textureImporter.spriteImportMode == SpriteImportMode.Multiple)\n                {\n                    Rect screenRect = new Rect();\n                    Rect sourceRect = new Rect();\n                    GUI.CalculateScaledTextureRects(wantedRect, ScaleMode.StretchToFill, (float)t.width / (float)t.height, ref screenRect, ref sourceRect);\n\n                    int origWidth = t.width;\n                    int origHeight = t.height;\n                    textureImporter.GetWidthAndHeight(ref origWidth, ref origHeight);\n                    float definitionScale = (float)t.width / (float)origWidth;\n\n                    HandleUtility.ApplyWireMaterial();\n                    GL.PushMatrix();\n                    GL.MultMatrix(Handles.matrix);\n                    GL.Begin(GL.LINES);\n                    GL.Color(new Color(1f, 1f, 1f, 0.5f));\n                    foreach (SpriteMetaData sprite in spritesheet)\n                    {\n                        Rect spriteRect = sprite.rect;\n                        Rect spriteScreenRect = new Rect();\n                        spriteScreenRect.xMin = screenRect.xMin + screenRect.width * (spriteRect.xMin / t.width * definitionScale);\n                        spriteScreenRect.xMax = screenRect.xMin + screenRect.width * (spriteRect.xMax / t.width * definitionScale);\n                        spriteScreenRect.yMin = screenRect.yMin + screenRect.height * (1f - spriteRect.yMin / t.height * definitionScale);\n                        spriteScreenRect.yMax = screenRect.yMin + screenRect.height * (1f - spriteRect.yMax / t.height * definitionScale);\n                        DrawRect(spriteScreenRect);\n                    }\n                    GL.End();\n                    GL.PopMatrix();\n                }\n            }\n\n            TextureUtil.SetFilterModeNoDirty(t, oldFilter);\n\n            int mipmapLimit = GetMipmapLimit(target as Texture);\n            int cpuMipLevel = Mathf.Min(TextureUtil.GetMipmapCount(target as Texture) - 1, (int)mipLevel + mipmapLimit);\n            m_Pos = PreviewGUI.EndScrollView();\n            if (cpuMipLevel != 0)\n            {\n                GUIContent mipLevelTextContent = new GUIContent((cpuMipLevel != mipLevel)\n                        ? string.Format(\"Mip {0}\\nMip {1} on GPU (Texture Limit)\", cpuMipLevel, mipLevel)\n                        : string.Format(\"Mip {0}\", mipLevel));\n                Vector2 size = s_Styles.mipLevelLabel.CalcSize(mipLevelTextContent);\n                if (size.x <= r.width)\n                {\n                    EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, size.y), mipLevelTextContent, s_Styles.mipLevelLabel);\n                }\n            }\n        }\n\n        private void DrawRect(Rect rect)\n        {\n            GL.Vertex(new Vector3(rect.xMin, rect.yMin, 0f));\n            GL.Vertex(new Vector3(rect.xMax, rect.yMin, 0f));\n            GL.Vertex(new Vector3(rect.xMax, rect.yMin, 0f));\n            GL.Vertex(new Vector3(rect.xMax, rect.yMax, 0f));\n            GL.Vertex(new Vector3(rect.xMax, rect.yMax, 0f));\n            GL.Vertex(new Vector3(rect.xMin, rect.yMax, 0f));\n            GL.Vertex(new Vector3(rect.xMin, rect.yMax, 0f));\n            GL.Vertex(new Vector3(rect.xMin, rect.yMin, 0f));\n        }\n\n        public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height)\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture)\n            {\n                return null;\n            }\n\n            Texture texture = target as Texture;\n\n            GraphicsFormat format = texture.graphicsFormat;\n            if (!(GraphicsFormatUtility.IsIEEE754Format(format) || GraphicsFormatUtility.IsNormFormat(format)))\n            {\n                // Can't generate correct previews for non-float/norm formats. On Metal and Vulkan this even causes validation errors.\n                return null;\n            }\n\n            if (IsCubemap())\n            {\n                return m_CubemapPreview.RenderStaticPreview(texture, width, height, GetExposureValueForTexture(texture));\n            }\n\n            if (IsTexture3D())\n            {\n                return m_Texture3DPreview.RenderStaticPreview(texture, width, height);\n            }\n\n            TextureImporter textureImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;\n            if (textureImporter != null && textureImporter.textureType == TextureImporterType.Sprite && textureImporter.spriteImportMode == SpriteImportMode.Polygon)\n            {\n                // If the texture importer is a Sprite of primitive, use the sprite inspector for generating preview/icon.\n                if (subAssets.Length > 0)\n                {\n                    Sprite sprite = subAssets[0] as Sprite;\n                    if (sprite)\n                        return SpriteInspector.BuildPreviewTexture(sprite, null, true, width, height);\n                }\n                else\n                    return null;\n            }\n\n            PreviewHelpers.AdjustWidthAndHeightForStaticPreview(texture.width, texture.height, ref width, ref height);\n\n            RenderTexture savedRT = RenderTexture.active;\n            Rect savedViewport = ShaderUtil.rawViewportRect;\n\n            var rt = texture as RenderTexture;\n            if (rt != null)\n            {\n                rt.Create(); // Ensure RT is created. Otherwise the first attempted Blit will end up binding a dummy 2D Texture where it expects a 2D Texture Array. (validation errors observed on Vulkan/Metal)\n            }\n\n            RenderTexture tmp = RenderTexture.GetTemporary(\n                width, height,\n                0,\n                SystemInfo.GetGraphicsFormat(DefaultFormat.LDR));\n            Material mat = EditorGUI.GetMaterialForSpecialTexture(texture, null, QualitySettings.activeColorSpace == ColorSpace.Linear, false);\n            if (mat != null)\n                Graphics.Blit(texture, tmp, mat);\n            else Graphics.Blit(texture, tmp);\n\n            RenderTexture.active = tmp;\n            Texture2D copy;\n            Texture2D tex2d = target as Texture2D;\n            if (tex2d != null && tex2d.alphaIsTransparency)\n            {\n                copy = new Texture2D(width, height, TextureFormat.RGBA32, false);\n            }\n            else\n            {\n                copy = new Texture2D(width, height, TextureFormat.RGB24, false);\n            }\n            copy.ReadPixels(new Rect(0, 0, width, height), 0, 0);\n            copy.Apply();\n            RenderTexture.ReleaseTemporary(tmp);\n\n            EditorGUIUtility.SetRenderTextureNoViewport(savedRT);\n            ShaderUtil.rawViewportRect = savedViewport;\n\n            return copy;\n        }\n\n        public override string GetInfoString()\n        {\n            // TextureInspector code is reused for RenderTexture and Cubemap inspectors.\n            // Make sure we can handle the situation where target is just a Texture and\n            // not a Texture2D.\n            Texture t = target as Texture;\n            Texture2D t2 = target as Texture2D;\n            TextureImporter textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(t)) as TextureImporter;\n            string info = t.width + \"x\" + t.height;\n\n            bool showSize = true;\n            bool isPackedSprite = textureImporter && textureImporter.qualifiesForSpritePacking;\n            bool isNormalmap = IsNormalMap(t);\n            bool stillNeedsCompression = textureImporter && textureImporter.textureStillNeedsToBeCompressed;\n            bool isNPOT = t2 != null && TextureUtil.IsNonPowerOfTwo(t2);\n            GraphicsFormat format = t.graphicsFormat;\n\n            showSize = !stillNeedsCompression;\n            if (isNPOT)\n                info += \" (NPOT)\";\n            if (stillNeedsCompression)\n                info += \" (Not yet compressed)\";\n            else\n            {\n                if (isNormalmap)\n                {\n                    switch (format)\n                    {\n                        case GraphicsFormat.RGBA_DXT5_SRGB:\n                        case GraphicsFormat.RGBA_DXT5_UNorm:\n                            info += \"  DXTnm\";\n                            break;\n                        case GraphicsFormat.R8G8B8A8_SRGB:\n                        case GraphicsFormat.R8G8B8A8_UNorm:\n                        case GraphicsFormat.B8G8R8A8_SRGB:\n                        case GraphicsFormat.B8G8R8A8_UNorm:\n                            info += \"  Nm 32 bit\";\n                            break;\n                        case GraphicsFormat.R4G4B4A4_UNormPack16:\n                        case GraphicsFormat.B4G4R4A4_UNormPack16:\n                            info += \"  Nm 16 bit\";\n                            break;\n                        default:\n                            info += \"  \" + GraphicsFormatUtility.GetFormatString(format);\n                            break;\n                    }\n                }\n                else if (isPackedSprite)\n                {\n                    TextureFormat desiredFormat;\n                    ColorSpace dummyColorSpace;\n                    int dummyComressionQuality;\n                    textureImporter.ReadTextureImportInstructions(EditorUserBuildSettings.activeBuildTarget, out desiredFormat, out dummyColorSpace, out dummyComressionQuality);\n\n                    info += \"\\n \" + GraphicsFormatUtility.GetFormatString(format) + \"(Original) \" + GraphicsFormatUtility.GetFormatString(desiredFormat) + \"(Atlas)\";\n                }\n                else\n                    info += \"  \" + GraphicsFormatUtility.GetFormatString(format);\n            }\n\n            if (showSize)\n                info += \"\\n\" + EditorUtility.FormatBytes(TextureUtil.GetStorageMemorySizeLong(t));\n\n            TextureUsageMode mode = TextureUtil.GetUsageMode(t);\n\n            if (mode == TextureUsageMode.AlwaysPadded)\n            {\n                var glWidth = TextureUtil.GetGPUWidth(t);\n                var glHeight = TextureUtil.GetGPUHeight(t);\n                if (t.width != glWidth || t.height != glHeight)\n                    info += string.Format(\"\\nPadded to {0}x{1}\", glWidth, glHeight);\n            }\n            else if (TextureUtil.IsRGBMUsageMode(mode))\n            {\n                info += \"\\nRGBM encoded\";\n            }\n            else if (TextureUtil.IsDoubleLDRUsageMode(mode))\n            {\n                info += \"\\ndLDR encoded\";\n            }\n\n            return info;\n        }\n\n        internal static float PreviewSettingsSlider(GUIContent content, float value, float min, float max, float sliderWidth, float floatFieldWidth, bool isInteger)\n        {\n            var labelWidth = EditorStyles.label.CalcSize(content).x + 2;\n            var controlRect = EditorGUILayout.GetControlRect(GUILayout.Width(labelWidth + sliderWidth + floatFieldWidth));\n            var controlId = GUIUtility.GetControlID(FocusType.Keyboard);\n\n            var labelRect = new Rect(controlRect.position, new Vector2(labelWidth, controlRect.height));\n            controlRect.x += labelRect.width;\n            controlRect.width -= labelRect.width + 2;\n            GUI.Label(labelRect, content);\n\n            var sliderRect = new Rect(controlRect.position, new Vector2(sliderWidth, controlRect.height));\n            controlRect.x += sliderRect.width + 2;\n            controlRect.width -= sliderRect.width;\n            value = GUI.Slider(sliderRect, value, 0, min, max, GUI.skin.horizontalSlider, GUI.skin.horizontalSliderThumb, true, 0);\n            if (isInteger)\n                value = Mathf.Round(EditorGUI.DoIntField(EditorGUI.s_RecycledEditor, controlRect, labelRect, controlId, Mathf.RoundToInt(value), EditorGUI.kIntFieldFormatString, EditorStyles.numberField, false, 0));\n            else\n                value = EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor, controlRect, labelRect, controlId, value, EditorGUI.kFloatFieldFormatString, EditorStyles.numberField, true);\n            return Mathf.Clamp(value, min, max);\n        }\n    }\n}\n\n\nclass PreviewGUI\n{\n    static int sliderHash = \"Slider\".GetHashCode();\n    static Rect s_ViewRect, s_Position;\n    static Vector2 s_ScrollPos;\n\n    internal static void BeginScrollView(Rect position, Vector2 scrollPosition, Rect viewRect, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar)\n    {\n        s_ScrollPos = scrollPosition;\n        s_ViewRect = viewRect;\n        s_Position = position;\n        GUIClip.Push(position, new Vector2(Mathf.Round(-scrollPosition.x - viewRect.x - (viewRect.width - position.width) * .5f), Mathf.Round(-scrollPosition.y - viewRect.y - (viewRect.height - position.height) * .5f)), Vector2.zero, false);\n    }\n\n    internal class Styles\n    {\n        public static GUIStyle preButton;\n        public static void Init()\n        {\n            preButton = \"toolbarbutton\";\n        }\n    }\n\n    public static int CycleButton(int selected, GUIContent[] options)\n    {\n        Styles.Init();\n        return EditorGUILayout.CycleButton(selected, options, Styles.preButton);\n    }\n\n    public static Vector2 EndScrollView()\n    {\n        GUIClip.Pop();\n\n        Rect clipRect = s_Position, position = s_Position, viewRect = s_ViewRect;\n\n        Vector2 scrollPosition = s_ScrollPos;\n        switch (Event.current.type)\n        {\n            case EventType.Layout:\n                GUIUtility.GetControlID(sliderHash, FocusType.Passive);\n                GUIUtility.GetControlID(sliderHash, FocusType.Passive);\n                break;\n            case EventType.Used:\n                break;\n            default:\n                bool needsVerticalScrollbar = ((int)viewRect.width > (int)clipRect.width);\n                bool needsHorizontalScrollbar = ((int)viewRect.height > (int)clipRect.height);\n                int id = GUIUtility.GetControlID(sliderHash, FocusType.Passive);\n\n                if (needsHorizontalScrollbar)\n                {\n                    GUIStyle horizontalScrollbar = \"PreHorizontalScrollbar\";\n                    GUIStyle horizontalScrollbarThumb = \"PreHorizontalScrollbarThumb\";\n                    float offset = (viewRect.width - clipRect.width) * .5f;\n                    scrollPosition.x = GUI.Slider(new Rect(position.x, position.yMax - horizontalScrollbar.fixedHeight, clipRect.width - (needsVerticalScrollbar ? horizontalScrollbar.fixedHeight : 0) , horizontalScrollbar.fixedHeight),\n                        scrollPosition.x, clipRect.width + offset, -offset, viewRect.width,\n                        horizontalScrollbar, horizontalScrollbarThumb, true, id);\n                }\n                else\n                {\n                    // Get the same number of Control IDs so the ID generation for children don't depend on number of things above\n                    scrollPosition.x = 0;\n                }\n\n                id = GUIUtility.GetControlID(sliderHash, FocusType.Passive);\n\n                if (needsVerticalScrollbar)\n                {\n                    GUIStyle verticalScrollbar = \"PreVerticalScrollbar\";\n                    GUIStyle verticalScrollbarThumb = \"PreVerticalScrollbarThumb\";\n                    float offset = (viewRect.height - clipRect.height) * .5f;\n                    scrollPosition.y = GUI.Slider(new Rect(clipRect.xMax - verticalScrollbar.fixedWidth, clipRect.y, verticalScrollbar.fixedWidth, clipRect.height),\n                        scrollPosition.y, clipRect.height + offset, -offset, viewRect.height,\n                        verticalScrollbar, verticalScrollbarThumb, false, id);\n                }\n                else\n                {\n                    scrollPosition.y = 0;\n                }\n                break;\n        }\n\n        return scrollPosition;\n    }\n\n    public static Vector2 Drag2D(Vector2 scrollPosition, Rect position)\n    {\n        int id = GUIUtility.GetControlID(sliderHash, FocusType.Passive);\n        Event evt = Event.current;\n        switch (evt.GetTypeForControl(id))\n        {\n            case EventType.MouseDown:\n                if (position.Contains(evt.mousePosition) && position.width > 50)\n                {\n                    GUIUtility.hotControl = id;\n                    evt.Use();\n                    EditorGUIUtility.SetWantsMouseJumping(1);\n                }\n                break;\n            case EventType.MouseDrag:\n                if (GUIUtility.hotControl == id)\n                {\n                    scrollPosition -= evt.delta * (evt.shift ? 3 : 1) / Mathf.Min(position.width, position.height) * 140.0f;\n                    evt.Use();\n                    GUI.changed = true;\n                }\n                break;\n            case EventType.MouseUp:\n                if (GUIUtility.hotControl == id)\n                    GUIUtility.hotControl = 0;\n                EditorGUIUtility.SetWantsMouseJumping(0);\n                break;\n        }\n        return scrollPosition;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/TimeControl.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    internal class TimeControl\n    {\n        // currentTime will be clamped to preview range.\n        // Make sure it's initially at the beginning, even if the clip start is negative.\n        public float currentTime = Mathf.NegativeInfinity;\n        public float nextCurrentTime\n        {\n            set { deltaTime = value - currentTime; m_NextCurrentTimeSet = true; }\n        }\n        private bool m_NextCurrentTimeSet = false;\n        public float startTime = 0.0f;\n        public float stopTime = 1.0f;\n        public bool playSelection = false;\n        public bool loop = true;\n        public float playbackSpeed = 1.0f;\n        private float m_DeltaTime = 0.0f;\n        private bool m_DeltaTimeSet = false;\n        public float deltaTime\n        {\n            get { return m_DeltaTime; }\n            set { m_DeltaTime = value; m_DeltaTimeSet = true; }\n        }\n        public float normalizedTime\n        {\n            // Don't use InverseLerp and Lerp since they clamp between 0 and 1\n            get { return (stopTime == startTime) ? 0 : ((currentTime - startTime) / (stopTime - startTime)); }\n            set { currentTime = startTime * (1 - value) + stopTime * value; }\n        }\n        public bool playing\n        {\n            get { return m_Playing; }\n            set\n            {\n                if (m_Playing != value)\n                {\n                    // Start Playing\n                    if (value)\n                    {\n                        EditorApplication.update += InspectorWindow.RepaintAllInspectors;\n                        m_LastFrameEditorTime = EditorApplication.timeSinceStartup;\n\n                        if (m_ResetOnPlay)\n                        {\n                            nextCurrentTime = startTime;\n                            m_ResetOnPlay = false;\n                        }\n                    }\n                    // Stop Playing\n                    else\n                    {\n                        EditorApplication.update -= InspectorWindow.RepaintAllInspectors;\n                    }\n                }\n\n                m_Playing = value;\n            }\n        }\n\n        private double m_LastFrameEditorTime = 0.0f;\n        private bool m_Playing = false;\n        private bool m_ResetOnPlay = false;\n        private float m_MouseDrag = 0.0f;\n        private bool m_WrapForwardDrag = false;\n\n        private const float kStepTime = 0.01f;\n        private const float kScrubberHeight = 21;\n        private const float kPlayButtonWidth = 33;\n\n        private class Styles\n        {\n            public GUIContent playIcon = EditorGUIUtility.IconContent(\"PlayButton\");\n            public GUIContent pauseIcon = EditorGUIUtility.IconContent(\"PauseButton\");\n\n            public GUIStyle playButton = \"TimeScrubberButton\";\n            public GUIStyle timeScrubber = \"TimeScrubber\";\n        }\n        private static Styles s_Styles;\n\n        private static readonly int kScrubberIDHash = \"ScrubberIDHash\".GetHashCode();\n        public void DoTimeControl(Rect rect)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            var evt = Event.current;\n            int id = EditorGUIUtility.GetControlID(kScrubberIDHash, FocusType.Keyboard);\n\n            // Play/Pause Button + Scrubber\n            Rect timelineRect = rect;\n            timelineRect.height = kScrubberHeight;\n            // Only Scrubber\n            Rect scrubberRect = timelineRect;\n            scrubberRect.xMin += kPlayButtonWidth;\n\n            // Handle Input\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.MouseDown:\n                    if (rect.Contains(evt.mousePosition))\n                    {\n                        EditorGUIUtility.keyboardControl = id;\n                    }\n                    if (scrubberRect.Contains(evt.mousePosition))\n                    {\n                        EditorGUIUtility.SetWantsMouseJumping(1);\n                        EditorGUIUtility.hotControl = id;\n                        m_MouseDrag = evt.mousePosition.x - scrubberRect.xMin;\n                        nextCurrentTime = (m_MouseDrag * (stopTime - startTime) / scrubberRect.width + startTime);\n                        m_WrapForwardDrag = false;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (EditorGUIUtility.hotControl == id)\n                    {\n                        m_MouseDrag += evt.delta.x * playbackSpeed;\n                        // We want to not wrap if we immediately drag to the beginning, but we do want to wrap if we drag past the end.\n                        if (loop && ((m_MouseDrag < 0.0f && m_WrapForwardDrag) || (m_MouseDrag > scrubberRect.width)))\n                        {\n                            // scrubing out of range was generating a big deltaTime in wrong time direction\n                            // this new code prevent this and it is compliant with new and more robust v5.0 root motion looping of animation clip\n                            if (m_MouseDrag > scrubberRect.width)\n                            {\n                                currentTime -= (stopTime - startTime);\n                            }\n                            else if (m_MouseDrag < 0)\n                            {\n                                currentTime += (stopTime - startTime);\n                            }\n\n                            m_WrapForwardDrag = true;\n                            m_MouseDrag = Mathf.Repeat(m_MouseDrag, scrubberRect.width);\n                        }\n                        nextCurrentTime = (Mathf.Clamp(m_MouseDrag, 0.0f, scrubberRect.width) * (stopTime - startTime) / scrubberRect.width + startTime);\n                        evt.Use();\n                    }\n                    break;\n                case EventType.MouseUp:\n                    if (EditorGUIUtility.hotControl == id)\n                    {\n                        EditorGUIUtility.SetWantsMouseJumping(0);\n                        EditorGUIUtility.hotControl = 0;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.KeyDown:\n                    if (EditorGUIUtility.keyboardControl == id)\n                    {\n                        // TODO: loop?\n                        if (evt.keyCode == KeyCode.LeftArrow)\n                        {\n                            if (currentTime - startTime > kStepTime)\n                                deltaTime = -kStepTime;\n                            evt.Use();\n                        }\n                        if (evt.keyCode == KeyCode.RightArrow)\n                        {\n                            if (stopTime - currentTime > kStepTime)\n                                deltaTime = kStepTime;\n                            evt.Use();\n                        }\n                    }\n                    break;\n            }\n\n            // background\n            GUI.Box(timelineRect, GUIContent.none, s_Styles.timeScrubber);\n\n            // Play/Pause Button\n            playing = GUI.Toggle(timelineRect, playing, playing ? s_Styles.pauseIcon : s_Styles.playIcon, s_Styles.playButton);\n\n            // Current time indicator\n            float normalizedPosition = Mathf.Lerp(scrubberRect.x, scrubberRect.xMax, normalizedTime);\n            TimeArea.DrawPlayhead(normalizedPosition, scrubberRect.yMin, scrubberRect.yMax, 2f, (EditorGUIUtility.keyboardControl == id) ? 1f : 0.5f);\n        }\n\n        public void OnDisable()\n        {\n            playing = false;\n        }\n\n        public void Update()\n        {\n            // If the deltaTime was not set, update it when playing\n            if (!m_DeltaTimeSet)\n            {\n                if (playing)\n                {\n                    double timeSinceStartup = EditorApplication.timeSinceStartup;\n                    deltaTime = (float)(timeSinceStartup - m_LastFrameEditorTime) * playbackSpeed;\n                    m_LastFrameEditorTime = timeSinceStartup;\n                }\n                else\n                    deltaTime = 0;\n            }\n\n\n            currentTime += deltaTime;\n\n            // If the nextCurrentTime was set explicitly, we don't want to loop\n            bool wrap = loop && playing && !m_NextCurrentTimeSet;\n            if (wrap)\n            {\n                normalizedTime = Mathf.Repeat(normalizedTime, 1.0f);\n            }\n            else\n            {\n                if (normalizedTime > 1)\n                {\n                    playing = false;\n                    m_ResetOnPlay = true;\n                }\n                normalizedTime = Mathf.Clamp01(normalizedTime);\n            }\n\n            m_DeltaTimeSet = false;\n            m_NextCurrentTimeSet = false;\n        }\n    }//class TimeControl\n}//namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/Inspector/TimeManagerInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing Unity.IntegerTime;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(TimeManager))]\n    internal class TimeManagerEditor : Editor\n    {\n        class Content\n        {\n            public static readonly GUIContent fixedTimestepLabel =  EditorGUIUtility.TrTextContent(\"Fixed Timestep\", \"A framerate-independent interval that dictates when physics calculations and FixedUpdate() events are performed.\");\n            public static readonly GUIContent maxAllowedTimestepLabel =  EditorGUIUtility.TrTextContent(\"Maximum Allowed Timestep\", \"A framerate-independent interval that caps the worst-case scenario when framerate is low. Physics calculations and FixedUpdate() events will not be performed for longer time than specified.\");\n            public static readonly GUIContent timeScaleLabel = EditorGUIUtility.TrTextContent(\"Time Scale\", \"The speed at which time progresses. Change this value to simulate bullet-time effects. A value of 1 means real-time. A value of .5 means half speed; a value of 2 is double speed.\");\n            public static readonly GUIContent maxParticleTimestepLabel = EditorGUIUtility.TrTextContent(\"Maximum Particle Timestep\", \"The maximum frame delta time Unity permits for a single iteration of the Particle System update. If the delta time is larger than this value, Unity will run the Particle System update multiple times during the frame with smaller timesteps. This preserves the quality of the simulation.\");\n        }\n\n        SerializedProperty m_FixedTimestepCountProperty;\n        SerializedProperty m_MaxAllowedTimestepProperty;\n        SerializedProperty m_TimeScaleProperty;\n        SerializedProperty m_MaxParticleTimestepProperty;\n\n        static RationalTime.TicksPerSecond m_FixedTimeTicksPerSecond;\n        const float MinFixedTimeStep = 0.0001f;\n\n        public void OnEnable()\n        {\n            var fixedTimestepProperty = serializedObject.FindProperty(\"Fixed Timestep\");\n            m_FixedTimestepCountProperty = fixedTimestepProperty.FindPropertyRelative(\"m_Count\");\n            m_MaxAllowedTimestepProperty = serializedObject.FindProperty(\"Maximum Allowed Timestep\");\n            m_TimeScaleProperty = serializedObject.FindProperty(\"m_TimeScale\");\n            m_MaxParticleTimestepProperty = serializedObject.FindProperty(\"Maximum Particle Timestep\");\n\n            if (!m_FixedTimeTicksPerSecond.Valid) // FixedTime has a constant ticks per second value\n            {\n                var numerator = fixedTimestepProperty.FindPropertyRelative(\"m_Rate.m_Numerator\");\n                var denominator = fixedTimestepProperty.FindPropertyRelative(\"m_Rate.m_Denominator\");\n                m_FixedTimeTicksPerSecond =\n                    new RationalTime.TicksPerSecond(numerator.uintValue, denominator.uintValue);\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            DrawFixedTimeAsFloat(m_FixedTimestepCountProperty);\n            EditorGUILayout.PropertyField(m_MaxAllowedTimestepProperty, Content.maxAllowedTimestepLabel);\n            EditorGUILayout.PropertyField(m_TimeScaleProperty, Content.timeScaleLabel);\n            EditorGUILayout.PropertyField(m_MaxParticleTimestepProperty, Content.maxParticleTimestepLabel);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        static void DrawFixedTimeAsFloat(SerializedProperty prop)\n        {\n            var fixedTime = (float)new RationalTime(prop.longValue, m_FixedTimeTicksPerSecond).ToDouble(); // Convert a tick count to a float\n            using (var c = new EditorGUI.ChangeCheckScope())\n            {\n                var maxFixedTime = MathF.Max(fixedTime, MinFixedTimeStep);\n                var roundedTime = Math.Round(maxFixedTime, 4, MidpointRounding.AwayFromZero);\n                fixedTime = EditorGUILayout.FloatField(Content.fixedTimestepLabel, (float)roundedTime);\n\n                if (c.changed)\n                {\n                    var newCount = RationalTime\n                        .FromDouble(fixedTime, m_FixedTimeTicksPerSecond)\n                        .Count; // convert it back to a count to store in the property\n                    prop.longValue = newCount;\n                }\n            }\n        }\n\n\n        [SettingsProvider]\n        internal static SettingsProvider CreateProjectSettingsProvider()\n        {\n            var provider = AssetSettingsProvider.CreateProviderFromAssetPath(\n                \"Project/Time\", \"ProjectSettings/TimeManager.asset\",\n                SettingsProvider.GetSearchKeywordsFromGUIContentProperties<Content>());\n            return provider;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/TimelineControl.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System;\n\nnamespace UnityEditor\n{\n    internal class TimelineControl\n    {\n        private TimeArea m_TimeArea;\n\n        private float m_Time = Mathf.Infinity;\n\n        private float m_StartTime = 0;\n        private float m_StopTime = 1;\n\n        private string m_SrcName = \"Left\";\n        private string m_DstName = \"Right\";\n\n        private bool m_SrcLoop = false;\n        private bool m_DstLoop = false;\n\n        private float m_SrcStartTime = 0;\n        private float m_SrcStopTime = 0.75f;\n\n        private float m_DstStartTime = 0.25f;\n        private float m_DstStopTime = 1;\n\n        private bool m_HasExitTime = false;\n        private float m_TransitionStartTime = Mathf.Infinity;\n        private float m_TransitionStopTime = Mathf.Infinity;\n\n        private float m_SampleStopTime = Mathf.Infinity;\n\n\n        private float m_DstDragOffset = 0f;\n        private float m_LeftThumbOffset = 0f;\n        private float m_RightThumbOffset = 0f;\n\n        private float m_TimeStartDrag = 0f;\n        private float m_TimeOffset = 0f;\n\n        private enum DragStates { None, LeftSelection, RightSelection, FullSelection, Destination, Source, Playhead, TimeArea }\n        private DragStates m_DragState = DragStates.None;\n\n        private int id = -1;\n        private Rect m_Rect = new Rect(0, 0, 0, 0);\n\n        private Vector3[] m_SrcPivotVectors;\n        private Vector3[] m_DstPivotVectors;\n\n        private List<TimelineControl.PivotSample> m_SrcPivotList = new List<TimelineControl.PivotSample>();\n        private List<TimelineControl.PivotSample> m_DstPivotList = new List<TimelineControl.PivotSample>();\n\n        public List<TimelineControl.PivotSample> SrcPivotList\n        {\n            get { return m_SrcPivotList; }\n            set { m_SrcPivotList = value; m_SrcPivotVectors = null; }\n        }\n\n        public List<TimelineControl.PivotSample> DstPivotList\n        {\n            get { return m_DstPivotList; }\n            set { m_DstPivotList = value; m_DstPivotVectors = null; }\n        }\n\n\n        class Styles\n        {\n            public readonly GUIStyle block = \"MeTransitionBlock\";\n            public readonly GUIStyle leftBlock = \"MeTransitionBlock\";\n            public readonly GUIStyle rightBlock = \"MeTransitionBlock\";\n            public readonly GUIStyle timeBlockRight = \"MeTimeBlockRight\";\n            public readonly GUIStyle timeBlockLeft = \"MeTimeBlockLeft\";\n\n            public readonly GUIStyle offLeft = \"MeTransOffLeft\";\n            public readonly GUIStyle offRight = \"MeTransOffRight\";\n            public readonly GUIStyle onLeft = \"MeTransOnLeft\";\n            public readonly GUIStyle onRight = \"MeTransOnRight\";\n            public readonly GUIStyle offOn = \"MeTransOff2On\";\n            public readonly GUIStyle onOff = \"MeTransOn2Off\";\n            public readonly GUIStyle background = \"MeTransitionBack\";\n            public readonly GUIStyle header = \"MeTransitionHead\";\n\n            public readonly GUIStyle handLeft = \"MeTransitionHandleLeft\";\n            public readonly GUIStyle handRight = \"MeTransitionHandleRight\";\n            public readonly GUIStyle handLeftPrev = \"MeTransitionHandleLeftPrev\";\n\n            public readonly GUIStyle playhead = \"MeTransPlayhead\";\n\n            public readonly GUIStyle selectHead = \"MeTransitionSelectHead\";\n            public readonly GUIStyle select = \"MeTransitionSelect\";\n        }\n        private Styles styles;\n\n        internal class PivotSample\n        {\n            public float m_Time;\n            public float m_Weight;\n        }\n\n\n        public bool srcLoop\n        {\n            get { return m_SrcLoop; }\n            set { m_SrcLoop = value; }\n        }\n\n        public bool dstLoop\n        {\n            get { return m_DstLoop; }\n            set { m_DstLoop = value; }\n        }\n\n\n        public float Time\n        {\n            get { return m_Time; }\n            set { m_Time = value; }\n        }\n\n        public float StartTime\n        {\n            get { return m_StartTime; }\n            set { m_StartTime = value; }\n        }\n\n        public float StopTime\n        {\n            get { return m_StopTime; }\n            set { m_StopTime = value; }\n        }\n\n        public string SrcName\n        {\n            get { return m_SrcName; }\n            set { m_SrcName = value; }\n        }\n\n        public string DstName\n        {\n            get { return m_DstName; }\n            set { m_DstName = value; }\n        }\n\n        public float SrcStartTime\n        {\n            get { return m_SrcStartTime; }\n            set { m_SrcStartTime = value; }\n        }\n\n        public float SrcStopTime\n        {\n            get { return m_SrcStopTime; }\n            set { m_SrcStopTime = value; }\n        }\n\n        public float SrcDuration\n        {\n            get { return SrcStopTime - SrcStartTime; }\n        }\n\n        public float DstStartTime\n        {\n            get { return m_DstStartTime; }\n            set { m_DstStartTime = value; }\n        }\n\n        public float DstStopTime\n        {\n            get { return m_DstStopTime; }\n            set { m_DstStopTime = value; }\n        }\n\n        public float DstDuration\n        {\n            get { return DstStopTime - DstStartTime; }\n        }\n\n        public float TransitionStartTime\n        {\n            get { return m_TransitionStartTime; }\n            set { m_TransitionStartTime = value; }\n        }\n\n        public float TransitionStopTime\n        {\n            get { return m_TransitionStopTime; }\n            set { m_TransitionStopTime = value; }\n        }\n\n        public bool HasExitTime\n        {\n            get { return m_HasExitTime; }\n            set { m_HasExitTime = value; }\n        }\n\n        public float TransitionDuration\n        {\n            get { return TransitionStopTime - TransitionStartTime; }\n        }\n\n        public float SampleStopTime\n        {\n            get { return m_SampleStopTime; }\n            set { m_SampleStopTime = value; }\n        }\n\n\n        public void ResetRange()\n        {\n            m_TimeArea.SetShownHRangeInsideMargins(0, StopTime);\n        }\n\n        private void Init()\n        {\n            if (id == -1)\n                id = GUIUtility.GetPermanentControlID();\n\n            if (m_TimeArea == null)\n            {\n                m_TimeArea = new TimeArea(false);\n                m_TimeArea.hRangeLocked = false;\n                m_TimeArea.vRangeLocked = true;\n                m_TimeArea.hSlider = false;\n                m_TimeArea.vSlider = false;\n                m_TimeArea.margin = 10;\n                m_TimeArea.scaleWithWindow = true;\n                m_TimeArea.hTicks.SetTickModulosForFrameRate(30);\n            }\n\n            if (styles == null)\n                styles = new Styles();\n        }\n\n        public TimelineControl()\n        {\n            Init();\n        }\n\n        private List<Vector3> GetControls(List<Vector3> segmentPoints, float scale)\n        {\n            List<Vector3> controlPoints = new List<Vector3>();\n            if (segmentPoints.Count < 2)\n                return controlPoints;\n            for (int i = 0; i < segmentPoints.Count; i++)\n            {\n                if (i == 0)\n                {\n                    Vector3 p1 = segmentPoints[i];\n                    Vector3 p2 = segmentPoints[i + 1];\n                    Vector3 tangent = (p2 - p1);\n                    Vector3 q1 = p1 + scale * tangent;\n                    controlPoints.Add(p1);\n                    controlPoints.Add(q1);\n                }\n                else if (i == segmentPoints.Count - 1)\n                {\n                    Vector3 p0 = segmentPoints[i - 1];\n                    Vector3 p1 = segmentPoints[i];\n                    Vector3 tangent = (p1 - p0);\n                    Vector3 q0 = p1 - scale * tangent;\n                    controlPoints.Add(q0);\n                    controlPoints.Add(p1);\n                }\n                else\n                {\n                    Vector3 p0 = segmentPoints[i - 1];\n                    Vector3 p1 = segmentPoints[i];\n                    Vector3 p2 = segmentPoints[i + 1];\n                    Vector3 tangent = (p2 - p0).normalized;\n                    Vector3 q0 = p1 - scale * tangent * (p1 - p0).magnitude;\n                    Vector3 q1 = p1 + scale * tangent * (p2 - p1).magnitude;\n                    controlPoints.Add(q0);\n                    controlPoints.Add(p1);\n                    controlPoints.Add(q1);\n                }\n            }\n            return controlPoints;\n        }\n\n        private Vector3 CalculatePoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)\n        {\n            float u = 1 - t;\n            float tt = t * t;\n            float uu = u * u;\n            float uuu = uu * u;\n            float ttt = tt * t;\n            Vector3 p = uuu * p0;\n            p += 3 * uu * t * p1;\n            p += 3 * u * tt * p2;\n            p += ttt * p3;\n            return p;\n        }\n\n        private Color[] GetPivotColors(Vector3[] vectors, float motionStart, float motionStop, Color fromColor, Color toColor, Color loopColor, float offset)\n        {\n            Color[] colors = new Color[vectors.Length];\n\n            float transStart = m_TimeArea.TimeToPixel(m_TransitionStartTime, m_Rect) + m_LeftThumbOffset;\n            float transStop = m_TimeArea.TimeToPixel(m_TransitionStopTime, m_Rect) + m_RightThumbOffset;\n            float transWidth = transStop - transStart;\n\n            for (int i = 0; i < colors.Length; i++)\n            {\n                if (vectors[i].x >= transStart && vectors[i].x <= transStop)\n                    colors[i] = Color.Lerp(fromColor, toColor, (vectors[i].x - transStart) / transWidth);\n                else if (vectors[i].x < transStart && vectors[i].x >= motionStart + offset)\n                    colors[i] = fromColor;\n                else if (vectors[i].x > transStop && vectors[i].x <= motionStop + offset)\n                    colors[i] = toColor;\n                else\n                    colors[i] = loopColor;\n            }\n            return colors;\n        }\n\n        private Vector3[] GetPivotVectors(PivotSample[] samples, float width, Rect rect, float height, bool loop)\n        {\n            if (samples.Length == 0 || width < 0.33f) // not pivots for super small anims\n                return new Vector3[0];\n\n            List<Vector3> vectorList = new List<Vector3>();\n            for (int i = 0; i < samples.Length; i++)\n            {\n                PivotSample s = samples[i];\n                Vector3 point = Vector3.zero;\n                point.x = m_TimeArea.TimeToPixel(s.m_Time, rect);\n                point.y = height / 16 + s.m_Weight * 12 * height / 16;\n                vectorList.Add(point);\n            }\n            if (loop && vectorList[vectorList.Count - 1].x <= rect.width)\n            {\n                float pos = vectorList[vectorList.Count - 1].x;\n                int iterator = 0;\n                int multiplier = 1;\n                List<Vector3> loopVectors = new List<Vector3>();\n                while (pos < rect.width)\n                {\n                    if (iterator > vectorList.Count - 1)\n                    {\n                        iterator = 0;\n                        multiplier++;\n                    }\n                    Vector3 point = vectorList[iterator];\n                    point.x += (multiplier * width);\n                    pos = point.x;\n                    loopVectors.Add(point);\n                    iterator++;\n                }\n                vectorList.AddRange(loopVectors);\n            }\n            List<Vector3> controls = GetControls(vectorList, .5f);\n            vectorList.Clear();\n            for (int i = 0; i < controls.Count - 3; i += 3)\n            {\n                Vector3 p0 = controls[i];\n                Vector3 p1 = controls[i + 1];\n                Vector3 p2 = controls[i + 2];\n                Vector3 p3 = controls[i + 3];\n                if (i == 0)\n                    vectorList.Add(CalculatePoint(0, p0, p1, p2, p3));\n                for (int j = 1; j <= 10; j++)\n                    vectorList.Add(CalculatePoint(j / 10f, p0, p1, p2, p3));\n            }\n            return vectorList.ToArray();\n        }\n\n        private Vector3[] OffsetPivotVectors(Vector3[] vectors, float offset)\n        {\n            for (int i = 0; i < vectors.Length; i++)\n                vectors[i].x += offset;\n            return vectors;\n        }\n\n        private void DoPivotCurves()\n        {\n            Color srcFull = Color.white;\n            Color dstFull = Color.white;\n            Color srcNone = new Color(1f, 1f, 1f, 0.1f);\n            Color dstNone = new Color(1f, 1f, 1f, 0.1f);\n            Color srcLoopColor = new Color(0.75f, 0.75f, 0.75f, 0.2f);\n            Color dstLoopColor = new Color(0.75f, 0.75f, 0.75f, 0.2f);\n\n            Rect rect = new Rect(0, 18, m_Rect.width, 66);\n            GUI.BeginGroup(rect);\n            // build vectors lists if needed\n            float srcStart = m_TimeArea.TimeToPixel(SrcStartTime, rect);\n            float srcStop = m_TimeArea.TimeToPixel(SrcStopTime, rect);\n            float dstStart = m_TimeArea.TimeToPixel(DstStartTime, rect);\n            float dstStop = m_TimeArea.TimeToPixel(DstStopTime, rect);\n            if (m_SrcPivotVectors == null)\n                m_SrcPivotVectors = GetPivotVectors(m_SrcPivotList.ToArray(), srcStop - srcStart, rect, rect.height, srcLoop);\n            if (m_DstPivotVectors == null)\n                m_DstPivotVectors = GetPivotVectors(m_DstPivotList.ToArray(), dstStop - dstStart, rect, rect.height, dstLoop);\n\n            m_DstPivotVectors = OffsetPivotVectors(m_DstPivotVectors, m_DstDragOffset + dstStart - srcStart);\n\n            Color[] srcColors = GetPivotColors(m_SrcPivotVectors, srcStart, srcStop, srcFull, srcNone, srcLoopColor, 0f);\n            Color[] dstColors = GetPivotColors(m_DstPivotVectors, dstStart, dstStop, dstNone, dstFull, dstLoopColor, m_DstDragOffset);\n\n            Handles.DrawAAPolyLine(srcColors, m_SrcPivotVectors);\n            Handles.DrawAAPolyLine(dstColors, m_DstPivotVectors);\n            GUI.EndGroup();\n        }\n\n        private void EnforceConstraints()\n        {\n            Rect r = new Rect(0, 0, m_Rect.width, 150);\n            if (m_DragState == DragStates.LeftSelection)\n            {\n                float minLimit = m_TimeArea.TimeToPixel(SrcStartTime, r) - m_TimeArea.TimeToPixel(TransitionStartTime, r);\n                float maxLimit = m_TimeArea.TimeToPixel(TransitionStopTime, r) - m_TimeArea.TimeToPixel(TransitionStartTime, r);\n\n                m_LeftThumbOffset = Mathf.Clamp(m_LeftThumbOffset, minLimit, maxLimit);\n            }\n\n            if (m_DragState == DragStates.RightSelection)\n            {\n                float minLimit = m_TimeArea.TimeToPixel(TransitionStartTime, r) - m_TimeArea.TimeToPixel(TransitionStopTime, r);\n                if (m_RightThumbOffset < minLimit)\n                    m_RightThumbOffset = minLimit;\n            }\n        }\n\n        private bool WasDraggingData()\n        {\n            return m_DstDragOffset != 0 ||\n                m_LeftThumbOffset != 0 ||\n                m_RightThumbOffset != 0;\n        }\n\n        public bool DoTimeline(Rect timeRect)\n        {\n            bool hasModifiedData = false;\n\n            Init();\n\n            // Case 1233111: timeRect is not valid during the layout phase and setting GUI.changed during that phase\n            // invalidates the layout.\n            if (Event.current.type == EventType.Repaint)\n            {\n                m_Rect = timeRect;\n\n\n                float timeAreaStart = m_TimeArea.PixelToTime(timeRect.xMin, timeRect);\n                float timeAreaStop = m_TimeArea.PixelToTime(timeRect.xMax, timeRect);\n\n                if (!Mathf.Approximately(timeAreaStart, StartTime))\n                {\n                    StartTime = timeAreaStart;\n                    GUI.changed = true;\n                }\n                if (!Mathf.Approximately(timeAreaStop, StopTime))\n                {\n                    StopTime = timeAreaStop;\n                    GUI.changed = true;\n                }\n\n                Time = Mathf.Max(Time, 0f);\n\n                m_TimeArea.rect = timeRect;\n            }\n            else\n                timeRect = m_Rect;\n\n            m_TimeArea.BeginViewGUI();\n            m_TimeArea.EndViewGUI();\n\n            GUI.BeginGroup(timeRect);\n            {\n                Event evt = Event.current;\n                Rect r = new Rect(0, 0, timeRect.width, timeRect.height);\n                Rect headerRect = new Rect(0, 0, timeRect.width, 18);\n                Rect bodyRect = new Rect(0, 18, timeRect.width, 132);\n\n                // get the relevant positions in pixels\n                float srcStart = m_TimeArea.TimeToPixel(SrcStartTime, r);\n                float srcStop = m_TimeArea.TimeToPixel(SrcStopTime, r);\n                float dstStart = m_TimeArea.TimeToPixel(DstStartTime, r) + m_DstDragOffset;\n                float dstStop = m_TimeArea.TimeToPixel(DstStopTime, r) + m_DstDragOffset;\n                float transStart = m_TimeArea.TimeToPixel(TransitionStartTime, r) + m_LeftThumbOffset;\n                float transStop = m_TimeArea.TimeToPixel(TransitionStopTime, r) + m_RightThumbOffset;\n                float playPoint = m_TimeArea.TimeToPixel(Time, r);\n\n                // get the relevant Rects\n\n                Rect srcRect = new Rect(srcStart, 85, srcStop - srcStart, 32);\n                Rect dstRect = new Rect(dstStart, 117, dstStop - dstStart, 32);\n                Rect transHeaderRect = new Rect(transStart, 0, transStop - transStart, 18);\n                Rect transRect = new Rect(transStart, 18, transStop - transStart, r.height - 18);\n                Rect leftThumbRect = new Rect(transStart - 9, 5, 9, 15);\n                Rect rightThumbRect = new Rect(transStop, 5, 9, 15);\n                Rect playHeadRect = new Rect(playPoint - 7, 4, 15, 15);\n\n\n                // handle keyboard\n                if (evt.type == EventType.KeyDown)\n                {\n                    if (EditorGUIUtility.keyboardControl == id)\n                        if (m_DragState == DragStates.Destination)\n                            m_DstDragOffset = 0f;\n                    if (m_DragState == DragStates.LeftSelection)\n                        m_LeftThumbOffset = 0f;\n                    if (m_DragState == DragStates.RightSelection)\n                        m_RightThumbOffset = 0f;\n                    if (m_DragState == DragStates.Playhead)\n                        m_TimeOffset = 0f;\n                    if (m_DragState == DragStates.FullSelection)\n                    {\n                        m_LeftThumbOffset = 0f;\n                        m_RightThumbOffset = 0f;\n                    }\n                }\n\n                // handle mouse down\n                if (evt.type == EventType.MouseDown)\n                {\n                    if (r.Contains(evt.mousePosition))\n                    {\n                        EditorGUIUtility.hotControl = id;\n                        EditorGUIUtility.keyboardControl = id;\n                        if (playHeadRect.Contains(evt.mousePosition))\n                        {\n                            m_DragState = DragStates.Playhead;\n                            m_TimeStartDrag = m_TimeArea.TimeToPixel(Time, r);\n                        }\n                        else if (srcRect.Contains(evt.mousePosition))\n                            m_DragState = DragStates.Source;\n                        else if (dstRect.Contains(evt.mousePosition))\n                            m_DragState = DragStates.Destination;\n                        else if (leftThumbRect.Contains(evt.mousePosition))\n                            m_DragState = DragStates.LeftSelection;\n                        else if (rightThumbRect.Contains(evt.mousePosition))\n                            m_DragState = DragStates.RightSelection;\n                        else if (transHeaderRect.Contains(evt.mousePosition))\n                            m_DragState = DragStates.FullSelection;\n                        else if (headerRect.Contains(evt.mousePosition))\n                            m_DragState = DragStates.TimeArea;\n                        else if (bodyRect.Contains(evt.mousePosition))\n                            m_DragState = DragStates.TimeArea;\n                        else\n                            m_DragState = DragStates.None;\n                        evt.Use();\n                    }\n                }\n\n                // handle mouse drag\n                if (evt.type == EventType.MouseDrag)\n                {\n                    if (EditorGUIUtility.hotControl == id)\n                    {\n                        switch (m_DragState)\n                        {\n                            case DragStates.Source:\n                            case DragStates.TimeArea:\n                                m_TimeArea.m_Translation.x += evt.delta.x;\n                                break;\n                            case DragStates.Destination:\n                                m_DstDragOffset += evt.delta.x;\n                                EnforceConstraints();\n                                break;\n                            case DragStates.LeftSelection:\n                                // clamp the delta when off range\n                                if ((evt.delta.x > 0 && evt.mousePosition.x > srcStart) ||\n                                    (evt.delta.x < 0 && evt.mousePosition.x < transStop))\n                                    m_LeftThumbOffset += evt.delta.x;\n                                EnforceConstraints();\n                                break;\n                            case DragStates.RightSelection:\n                                // clamp the delta when off range\n                                if (evt.delta.x > 0 && evt.mousePosition.x > transStart || evt.delta.x < 0)\n                                    m_RightThumbOffset += evt.delta.x;\n                                EnforceConstraints();\n                                break;\n                            case DragStates.FullSelection:\n                                m_RightThumbOffset += evt.delta.x;\n                                m_LeftThumbOffset += evt.delta.x;\n                                EnforceConstraints();\n                                break;\n                            case DragStates.Playhead:\n                                if ((evt.delta.x > 0 && evt.mousePosition.x > srcStart) ||\n                                    (evt.delta.x < 0 && evt.mousePosition.x <= m_TimeArea.TimeToPixel(SampleStopTime, r)))\n                                    m_TimeOffset += evt.delta.x;\n                                Time = m_TimeArea.PixelToTime(m_TimeStartDrag + m_TimeOffset, r);\n\n                                break;\n                            case DragStates.None:\n                                break;\n                        }\n                        evt.Use();\n                        GUI.changed = true;\n                    }\n                }\n\n\n                // handle mouse up both when it happens over the control area and outside control area (case 834214)\n                if (Event.current.GetTypeForControl(id) == EventType.MouseUp)\n                {\n                    SrcStartTime = m_TimeArea.PixelToTime(srcStart, r);\n                    SrcStopTime = m_TimeArea.PixelToTime(srcStop, r);\n                    DstStartTime = m_TimeArea.PixelToTime(dstStart, r);\n                    DstStopTime = m_TimeArea.PixelToTime(dstStop, r);\n                    TransitionStartTime = m_TimeArea.PixelToTime(transStart, r);\n                    TransitionStopTime = m_TimeArea.PixelToTime(transStop, r);\n                    GUI.changed = true;\n                    m_DragState = DragStates.None;\n\n                    hasModifiedData = WasDraggingData();\n                    m_LeftThumbOffset = 0f;\n                    m_RightThumbOffset = 0f;\n                    m_TimeOffset = 0f;\n                    m_DstDragOffset = 0f;\n                    EditorGUIUtility.hotControl = 0;\n                    evt.Use();\n                }\n\n\n                // draw the background boxes\n                GUI.Box(headerRect, GUIContent.none, styles.header);\n                GUI.Box(bodyRect, GUIContent.none, styles.background);\n\n                // draw ticks and curves on top of background boxes\n                m_TimeArea.DrawMajorTicks(bodyRect, 30);\n\n\n                GUIContent srcContent = EditorGUIUtility.TempContent(SrcName);\n\n                // draw src Loop\n                int srcLoopCount = srcLoop ? (1 + (int)((transStop - srcRect.xMin) / (srcRect.xMax - srcRect.xMin))) : 1;\n                Rect loopRect = srcRect;\n                if (srcRect.width < 10) // if smaller than 10 pixel, group\n                {\n                    loopRect = new Rect(srcRect.x, srcRect.y, (srcRect.xMax - srcRect.xMin) * srcLoopCount, srcRect.height);\n                    srcLoopCount = 1;\n                }\n\n                for (int loopSrcIt = 0; loopSrcIt < srcLoopCount; loopSrcIt++)\n                {\n                    GUI.BeginGroup(loopRect, GUIContent.none, styles.leftBlock);\n                    float widthBefore = transStart - loopRect.xMin;\n                    float widthDuring = transStop - transStart;\n                    float widthAfter = (loopRect.xMax - loopRect.xMin) - (widthBefore + widthDuring);\n                    if (widthBefore > 0)\n                        GUI.Box(new Rect(0, 0, widthBefore, srcRect.height), GUIContent.none, styles.onLeft);\n                    if (widthDuring > 0)\n                        GUI.Box(new Rect(widthBefore, 0, widthDuring, srcRect.height), GUIContent.none, styles.onOff);\n                    if (widthAfter > 0)\n                        GUI.Box(new Rect(widthBefore + widthDuring, 0, widthAfter, srcRect.height), GUIContent.none, styles.offRight);\n                    float srcAlphaTarget = 1f;\n                    float srcLabelRight = styles.block.CalcSize(srcContent).x;\n                    float srcPercentLeft = Mathf.Max(0, widthBefore) - 20;\n                    float srcPercentRight = srcPercentLeft + 15;\n                    if (srcPercentLeft < srcLabelRight && srcPercentRight > 0f && m_DragState == DragStates.LeftSelection)\n                        srcAlphaTarget = 0f;\n                    GUI.EndGroup();\n\n                    float srcAlpha = styles.leftBlock.normal.textColor.a;\n                    if (!Mathf.Approximately(srcAlpha, srcAlphaTarget) && Event.current.type == EventType.Repaint)\n                    {\n                        srcAlpha = Mathf.Lerp(srcAlpha, srcAlphaTarget, 0.1f);\n                        styles.leftBlock.normal.textColor = new Color(styles.leftBlock.normal.textColor.r, styles.leftBlock.normal.textColor.g, styles.leftBlock.normal.textColor.b, srcAlpha);\n                        HandleUtility.Repaint();\n                    }\n                    GUI.Box(loopRect, srcContent, styles.leftBlock);\n                    loopRect = new Rect(loopRect.xMax, 85, loopRect.xMax - loopRect.xMin, 32);\n                }\n\n\n                GUIContent dstContent = EditorGUIUtility.TempContent(DstName);\n                int dstLoopCount = dstLoop  ? (1 + (int)((transStop - dstRect.xMin) / (dstRect.xMax - dstRect.xMin))) : 1;\n                loopRect = dstRect;\n                if (dstRect.width < 10) // if smaller than 10 pixel, group\n                {\n                    loopRect = new Rect(dstRect.x, dstRect.y, (dstRect.xMax - dstRect.xMin) * dstLoopCount, dstRect.height);\n                    dstLoopCount = 1;\n                }\n\n                for (int loopDstIt = 0; loopDstIt < dstLoopCount; loopDstIt++)\n                {\n                    // draw the DST box\n                    GUI.BeginGroup(loopRect, GUIContent.none, styles.rightBlock);\n                    float widthBefore = transStart - loopRect.xMin;\n                    float widthDuring = transStop - transStart;\n                    float widthAfter = (loopRect.xMax - loopRect.xMin) - (widthBefore + widthDuring);\n                    if (widthBefore > 0)\n                        GUI.Box(new Rect(0, 0, widthBefore, dstRect.height), GUIContent.none, styles.offLeft);\n                    if (widthDuring > 0)\n                        GUI.Box(new Rect(widthBefore, 0, widthDuring, dstRect.height), GUIContent.none, styles.offOn);\n                    if (widthAfter > 0)\n                        GUI.Box(new Rect(widthBefore + widthDuring, 0, widthAfter, dstRect.height), GUIContent.none, styles.onRight);\n                    float dstAlphaTarget = 1f;\n                    float dstLabelRight = styles.block.CalcSize(dstContent).x;\n                    float dstPercentLeft = Mathf.Max(0, widthBefore) - 20;\n                    float dstPercentRight = dstPercentLeft + 15;\n                    if (dstPercentLeft < dstLabelRight && dstPercentRight > 0f && (m_DragState == DragStates.LeftSelection || m_DragState == DragStates.Destination))\n                        dstAlphaTarget = 0f;\n                    GUI.EndGroup();\n                    float dstAlpha = styles.rightBlock.normal.textColor.a;\n                    if (!Mathf.Approximately(dstAlpha, dstAlphaTarget) && Event.current.type == EventType.Repaint)\n                    {\n                        dstAlpha = Mathf.Lerp(dstAlpha, dstAlphaTarget, 0.1f);\n                        styles.rightBlock.normal.textColor = new Color(styles.rightBlock.normal.textColor.r, styles.rightBlock.normal.textColor.g, styles.rightBlock.normal.textColor.b, dstAlpha);\n                        HandleUtility.Repaint();\n                    }\n                    GUI.Box(loopRect, dstContent, styles.rightBlock);\n\n                    loopRect = new Rect(loopRect.xMax, loopRect.yMin, loopRect.xMax - loopRect.xMin, 32);\n                }\n\n                // draw the transition selection box in the body\n                GUI.Box(transRect, GUIContent.none, styles.select);\n\n                // draw the transition selection box in the header\n                GUI.Box(transHeaderRect, GUIContent.none, styles.selectHead);\n\n                m_TimeArea.TimeRuler(headerRect, 30);\n\n                // draw the thumbs\n                GUI.Box(leftThumbRect, GUIContent.none, (m_HasExitTime) ? styles.handLeft : styles.handLeftPrev);\n                GUI.Box(rightThumbRect, GUIContent.none, styles.handRight);\n\n                // playhead and bar\n                GUI.Box(playHeadRect, GUIContent.none, styles.playhead);\n                Color oldColor = Handles.color;\n                Handles.color = Color.white;\n                Handles.DrawLine(new Vector3(playPoint, 19, 0), new Vector3(playPoint, r.height, 0));\n                Handles.color = oldColor;\n\n\n                bool oneFrameSrc = (SrcStopTime - SrcStartTime) < 1.0f / 30.0f;\n                bool oneFrameDst = (DstStopTime - DstStartTime) < 1.0f / 30.0f;\n                // show normalized time label when moving destination state\n                if (m_DragState == DragStates.Destination && !oneFrameDst)\n                {\n                    Rect transLabelRect = new Rect(transStart - 50, dstRect.y, 45, dstRect.height);\n                    string transLabel = string.Format(\"{0:0%}\", (transStart - dstStart) / (dstStop - dstStart));\n                    GUI.Box(transLabelRect, EditorGUIUtility.TempContent(transLabel), styles.timeBlockRight);\n                }\n\n                // show normalized time label on left side when moving left edge of transition\n                if (m_DragState == DragStates.LeftSelection)\n                {\n                    if (!oneFrameSrc)\n                    {\n                        Rect srcLabelRect = new Rect(transStart - 50, srcRect.y, 45, srcRect.height);\n                        string srcLabel = string.Format(\"{0:0%}\", (transStart - srcStart) / (srcStop - srcStart));\n                        GUI.Box(srcLabelRect, EditorGUIUtility.TempContent(srcLabel), styles.timeBlockRight);\n                    }\n\n                    if (!oneFrameDst)\n                    {\n                        Rect dstLabelRect = new Rect(transStart - 50, dstRect.y, 45, dstRect.height);\n                        string dstLabel = string.Format(\"{0:0%}\", (transStart - dstStart) / (dstStop - dstStart));\n                        GUI.Box(dstLabelRect, EditorGUIUtility.TempContent(dstLabel), styles.timeBlockRight);\n                    }\n                }\n\n                // show normalized time label on right side when moving right edge of transition\n                if (m_DragState == DragStates.RightSelection)\n                {\n                    if (!oneFrameSrc)\n                    {\n                        Rect srcLabelRect = new Rect(transStop + 5, srcRect.y, 45, srcRect.height);\n                        string srcLabel = string.Format(\"{0:0%}\", (transStop - srcStart) / (srcStop - srcStart));\n                        GUI.Box(srcLabelRect, EditorGUIUtility.TempContent(srcLabel), styles.timeBlockLeft);\n                    }\n\n                    if (!oneFrameDst)\n                    {\n                        Rect dstLabelRect = new Rect(transStop + 5, dstRect.y, 45, dstRect.height);\n                        string dstLabel = string.Format(\"{0:0%}\", (transStop - dstStart) / (dstStop - dstStart));\n                        GUI.Box(dstLabelRect, EditorGUIUtility.TempContent(dstLabel), styles.timeBlockLeft);\n                    }\n                }\n\n                DoPivotCurves();\n            }\n            GUI.EndGroup();\n\n            return hasModifiedData;\n        }\n    }//class Timeline\n}//namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/Inspector/TrailRendererEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.EditorTools;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.Overlays;\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(TrailRenderer))]\n    [CanEditMultipleObjects]\n    internal class TrailRendererInspector : RendererEditorBase\n    {\n        private class Styles\n        {\n            public static readonly GUIContent colorGradient = EditorGUIUtility.TrTextContent(\"Color\", \"The gradient describing the color along the trail.\");\n            public static readonly GUIContent numCornerVertices = EditorGUIUtility.TrTextContent(\"Corner Vertices\", \"How many vertices to add for each corner.\");\n            public static readonly GUIContent numCapVertices = EditorGUIUtility.TrTextContent(\"End Cap Vertices\", \"How many vertices to add at each end.\");\n            public static readonly GUIContent alignment = EditorGUIUtility.TrTextContent(\"Alignment\", \"Trails can rotate to face their transform component or the camera. When using TransformZ mode, lines extrude along the XY plane of the Transform.\");\n            public static readonly GUIContent textureMode = EditorGUIUtility.TrTextContent(\"Texture Mode\", \"Should the U coordinate be stretched or tiled?\");\n            public static readonly GUIContent textureScale = EditorGUIUtility.TrTextContent(\"Texture Scale\", \"Scale the texture along the UV coordinates using this multiplier.\");\n            public static readonly GUIContent shadowBias = EditorGUIUtility.TrTextContent(\"Shadow Bias\", \"Apply a shadow bias to prevent self-shadowing artifacts. The specified value is the proportion of the trail width at each segment.\");\n            public static readonly GUIContent generateLightingData = EditorGUIUtility.TrTextContent(\"Generate Lighting Data\", \"Toggle generation of normal and tangent data, for use in lit shaders.\");\n            public static readonly GUIContent applyActiveColorSpace = EditorGUIUtility.TrTextContent(\"Apply Active Color Space\", \"When using Linear Rendering, colors will be converted appropriately before being passed to the GPU.\");\n\n            public static readonly GUIContent play = EditorGUIUtility.TrTextContent(\"Play\");\n            public static readonly GUIContent playDisabled = EditorGUIUtility.TrTextContent(\"Play\", \"Play is disabled, because the Time Scale in the Time Manager is set to 0.0.\");\n            public static readonly GUIContent stop = EditorGUIUtility.TrTextContent(\"Stop\");\n            public static readonly GUIContent pause = EditorGUIUtility.TrTextContent(\"Pause\");\n            public static readonly GUIContent restart = EditorGUIUtility.TrTextContent(\"Restart\");\n            public static readonly GUIContent movementSpeed = EditorGUIUtility.TrTextContent(\"Movement Speed\", \"Speed is also affected by the Time Scale setting in the Time Manager.\");\n            public static readonly GUIContent movementSpeedDisabled = EditorGUIUtility.TrTextContent(\"Movement Speed\", \"Speed is locked to 0.0, because the Time Scale in the Time Manager is set to 0.0.\");\n            public static readonly GUIContent timeScale = EditorGUIUtility.TrTextContent(\"Time Scale\", \"Speed up or slow down the preview of the trail.\");\n            public static readonly GUIContent timeScaleDisabled = EditorGUIUtility.TrTextContent(\"Time Scale\", \"Time Scale is locked to 0.0, because the Time Scale in the Time Manager is set to 0.0.\");\n            public static readonly GUIContent showBounds = EditorGUIUtility.TrTextContent(\"Show Bounds\", \"Show world space bounding boxes.\");\n            public static readonly GUIContent previewShape = EditorGUIUtility.TrTextContent(\"Shape\", \"The trail preview will follow the selected shape.\");\n            public static readonly GUIContent previewShapeSize = EditorGUIUtility.TrTextContent(\"Shape Size\", \"The size of the shape.\");\n\n            public static readonly GUIContent toolIcon = EditorGUIUtility.IconContent(\"ParticleShapeTool\", \"Shape gizmo editing mode.\");\n\n            public static readonly string secondsFloatFieldFormatString = \"f2\";\n        }\n\n        private enum PreviewShape\n        {\n            Circle,\n            Square,\n            Line,\n            SineWave,\n            Spring\n        }\n\n        private const string k_PreviewMovementSpeed = \"TrailPreviewMovementSpeed\";\n        private const string k_PreviewTimeScale = \"TrailPreviewTimeScale\";\n        private const string k_PreviewShape = \"TrailPreviewShape\";\n        private const string k_PreviewShapeSize = \"TrailPreviewShapeSize\";\n\n        private static LinkedList<TrailRendererInspector> s_Inspectors = new LinkedList<TrailRendererInspector>();\n        private static bool s_PreviewIsPlaying;\n        private static bool s_PreviewIsPaused;\n        private static float s_PreviewMovementSpeed;\n        private static float s_PreviewTimeScale;\n        private static bool s_PreviewShowBounds;\n        private static PreviewShape s_PreviewShape;\n        private static float s_PreviewShapeSize;\n        private Vector3? m_PreviewBackupPosition;\n        private bool m_PreviewIsFirstMove;\n        private float m_PreviewTimePercentage;\n\n        private static readonly Matrix4x4 s_ArcHandleOffsetMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(90f, Vector3.right) * Quaternion.AngleAxis(90f, Vector3.up), Vector3.one);\n        private const float k_SineWaveRepeat = 2.0f;\n        private const float k_SineWaveHeightMultiplier = 0.5f;\n        private const float k_SpringRotations = 5.0f;\n        private const float k_PreviewMinSize = 0.1f;\n        private const float k_SceneViewOverlayLabelWidth = 110.0f;\n        private ArcHandle m_PreviewArcHandle = new ArcHandle();\n\n        private LineRendererCurveEditor m_CurveEditor = new LineRendererCurveEditor();\n        private SerializedProperty m_Time;\n        private SerializedProperty m_MinVertexDistance;\n        private SerializedProperty m_Autodestruct;\n        private SerializedProperty m_Emitting;\n        private SerializedProperty m_ApplyActiveColorSpace;\n        private SerializedProperty m_ColorGradient;\n        private SerializedProperty m_NumCornerVertices;\n        private SerializedProperty m_NumCapVertices;\n        private SerializedProperty m_Alignment;\n        private SerializedProperty m_TextureMode;\n        private SerializedProperty m_TextureScale;\n        private SerializedProperty m_ShadowBias;\n        private SerializedProperty m_GenerateLightingData;\n        private SerializedProperty m_MaskInteraction;\n\n        public class ShortcutContext : IShortcutContext\n        {\n            public bool active { get; set; }\n        }\n\n        private ShortcutContext m_ShortcutContext = new ShortcutContext { active = true };\n\n        private static Event CreateCommandEvent(string commandName)\n        {\n            return new Event { type = EventType.ExecuteCommand, commandName = \"TrailRenderer/\" + commandName };\n        }\n\n        private static Event s_PlayEvent;\n        private static Event s_StopEvent;\n        private static Event s_RestartEvent;\n        private static Event s_ShowBoundsEvent;\n\n        private static PrefColor s_BoundsColor = new PrefColor(\"Trail Renderer/Bounds\", 1.0f, 235.0f / 255.0f, 4.0f / 255.0f, 1.0f);\n        private static PrefColor s_GizmoColor = new PrefColor(\"Trail Renderer/Shape Gizmos\", 148f / 255f, 229f / 255f, 1f, 0.9f);\n\n        private static void DispatchShortcutEvent(Event evt)\n        {\n            var sceneView = SceneView.lastActiveSceneView;\n            if (sceneView != null)\n            {\n                if (sceneView.SendEvent(evt))\n                    return;\n            }\n\n            var inspectors = Resources.FindObjectsOfTypeAll<TrailRendererInspector>();\n            foreach (var inspector in inspectors)\n            {\n                if (inspector != null)\n                {\n                    if (inspector.HandleShortcutEvent(evt))\n                        return;\n                }\n            }\n        }\n\n        [Shortcut(\"TrailRenderer/Play\", typeof(ShortcutContext), KeyCode.Comma)]\n        private static void PlayPauseShortcut(ShortcutArguments args)\n        {\n            DispatchShortcutEvent(s_PlayEvent);\n        }\n\n        [Shortcut(\"TrailRenderer/Stop\", typeof(ShortcutContext), KeyCode.Period)]\n        private static void StopShortcut(ShortcutArguments args)\n        {\n            DispatchShortcutEvent(s_StopEvent);\n        }\n\n        [Shortcut(\"TrailRenderer/Restart\", typeof(ShortcutContext), KeyCode.Slash)]\n        private static void RestartShortcut(ShortcutArguments args)\n        {\n            DispatchShortcutEvent(s_RestartEvent);\n        }\n\n        [Shortcut(\"TrailRenderer/ShowBounds\", typeof(ShortcutContext))]\n        private static void ShowBoundsShortcut(ShortcutArguments args)\n        {\n            DispatchShortcutEvent(s_ShowBoundsEvent);\n        }\n\n        public override void OnEnable()\n        {\n            base.OnEnable();\n\n            s_PreviewMovementSpeed = SessionState.GetFloat(k_PreviewMovementSpeed, 0.2f);\n            s_PreviewTimeScale = SessionState.GetFloat(k_PreviewTimeScale, 1.0f);\n            s_PreviewShape = (PreviewShape)SessionState.GetInt(k_PreviewShape, 0);\n            s_PreviewShapeSize = SessionState.GetFloat(k_PreviewShapeSize, 5.0f);\n\n            m_CurveEditor.OnEnable(serializedObject);\n            s_Inspectors.AddLast(this);\n            SceneView.duringSceneGui += OnSceneViewGUI;\n            EditorApplication.update += RepaintSceneView;\n            ShortcutIntegration.instance.contextManager.RegisterToolContext(m_ShortcutContext);\n\n            s_PlayEvent = CreateCommandEvent(\"Play\");\n            s_StopEvent = CreateCommandEvent(\"Stop\");\n            s_RestartEvent = CreateCommandEvent(\"Restart\");\n            s_ShowBoundsEvent = CreateCommandEvent(\"ShowBounds\");\n\n            m_Time = serializedObject.FindProperty(\"m_Time\");\n            m_MinVertexDistance = serializedObject.FindProperty(\"m_MinVertexDistance\");\n            m_Autodestruct = serializedObject.FindProperty(\"m_Autodestruct\");\n            m_Emitting = serializedObject.FindProperty(\"m_Emitting\");\n            m_ApplyActiveColorSpace = serializedObject.FindProperty(\"m_ApplyActiveColorSpace\");\n            m_ColorGradient = serializedObject.FindProperty(\"m_Parameters.colorGradient\");\n            m_NumCornerVertices = serializedObject.FindProperty(\"m_Parameters.numCornerVertices\");\n            m_NumCapVertices = serializedObject.FindProperty(\"m_Parameters.numCapVertices\");\n            m_Alignment = serializedObject.FindProperty(\"m_Parameters.alignment\");\n            m_TextureMode = serializedObject.FindProperty(\"m_Parameters.textureMode\");\n            m_TextureScale = serializedObject.FindProperty(\"m_Parameters.textureScale\");\n            m_ShadowBias = serializedObject.FindProperty(\"m_Parameters.shadowBias\");\n            m_GenerateLightingData = serializedObject.FindProperty(\"m_Parameters.generateLightingData\");\n            m_MaskInteraction = serializedObject.FindProperty(\"m_MaskInteraction\");\n        }\n\n        public void OnDisable()\n        {\n            Stop();\n\n            m_CurveEditor.OnDisable();\n            s_Inspectors.Remove(this);\n            SceneView.duringSceneGui -= OnSceneViewGUI;\n            EditorApplication.update -= RepaintSceneView;\n            ShortcutIntegration.instance.contextManager.DeregisterToolContext(m_ShortcutContext);\n\n            SessionState.SetFloat(k_PreviewMovementSpeed, s_PreviewMovementSpeed);\n            SessionState.SetFloat(k_PreviewTimeScale, s_PreviewTimeScale);\n            SessionState.SetInt(k_PreviewShape, (int)s_PreviewShape);\n            SessionState.SetFloat(k_PreviewShapeSize, s_PreviewShapeSize);\n        }\n\n        private static float ClampPreviewSize(TrailRenderer tr, float size)\n        {\n            float minSize = Mathf.Max(k_PreviewMinSize, tr.widthMultiplier * 0.5f);\n            return Mathf.Max(size, minSize);\n        }\n\n        private void SavePositionForPreview()\n        {\n            if (!m_PreviewBackupPosition.HasValue)\n            {\n                if (target is TrailRenderer tr)\n                {\n                    m_PreviewBackupPosition = tr.transform.localPosition;\n                    m_PreviewIsFirstMove = true;\n\n                    s_PreviewShapeSize = ClampPreviewSize(tr, s_PreviewShapeSize);\n\n                    DrivenPropertyManager.TryRegisterProperty(this, tr.transform, \"m_LocalPosition\");\n                    DrivenPropertyManager.TryRegisterProperty(this, tr, \"s_PreviewTimeScale\");\n                    EditorGUIUtility.beginProperty += BeginDrivenPropertyCheck;\n                }\n\n                m_PreviewTimePercentage = 0.0f;\n                Tools.hidden = true;\n            }\n        }\n\n        private void RestorePositionAfterPreview()\n        {\n            DrivenPropertyManager.UnregisterProperties(this);\n            EditorGUIUtility.beginProperty -= BeginDrivenPropertyCheck;\n\n            if (m_PreviewBackupPosition.HasValue)\n            {\n                if (target is TrailRenderer tr)\n                    tr.Clear();\n                m_PreviewBackupPosition = null;\n            }\n\n            Tools.hidden = false;\n        }\n\n        private void BeginDrivenPropertyCheck(Rect rect, SerializedProperty property)\n        {\n            if (EditorApplication.isPlayingOrWillChangePlaymode)\n                return;\n\n            if (DrivenPropertyManagerInternal.IsDriving(this, property.serializedObject.targetObject, property.propertyPath))\n            {\n                // Properties driven by a UnityEvent are disabled as changes to them would be ignored.\n                GUI.enabled = false;\n\n                Color animatedColor = AnimationMode.animatedPropertyColor;\n                animatedColor.a *= GUI.backgroundColor.a;\n                GUI.backgroundColor = AnimationMode.animatedPropertyColor;\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            m_CurveEditor.CheckCurveChangedExternally();\n            m_CurveEditor.OnInspectorGUI();\n\n            EditorGUILayout.PropertyField(m_Time);\n            EditorGUILayout.PropertyField(m_MinVertexDistance);\n            EditorGUILayout.PropertyField(m_Autodestruct);\n            EditorGUILayout.PropertyField(m_Emitting);\n            EditorGUILayout.PropertyField(m_ApplyActiveColorSpace, Styles.applyActiveColorSpace);\n            EditorGUILayout.PropertyField(m_ColorGradient, Styles.colorGradient);\n            EditorGUILayout.PropertyField(m_NumCornerVertices, Styles.numCornerVertices);\n            EditorGUILayout.PropertyField(m_NumCapVertices, Styles.numCapVertices);\n            EditorGUILayout.PropertyField(m_Alignment, Styles.alignment);\n            EditorGUILayout.PropertyField(m_TextureMode, Styles.textureMode);\n            EditorGUILayout.PropertyField(m_TextureScale, Styles.textureScale);\n            EditorGUILayout.PropertyField(m_GenerateLightingData, Styles.generateLightingData);\n            EditorGUILayout.PropertyField(m_ShadowBias, Styles.shadowBias);\n            EditorGUILayout.PropertyField(m_MaskInteraction);\n\n            DrawMaterials();\n            LightingSettingsGUI(false);\n            OtherSettingsGUI(true, false, true);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        private void OnSceneViewGUI(SceneView sceneView)\n        {\n            // Bounds\n            if (s_PreviewShowBounds)\n            {\n                var oldCol = Handles.color;\n                Handles.color = s_BoundsColor;\n\n                foreach (var obj in targets)\n                {\n                    if (obj is TrailRenderer trail)\n                    {\n                        var worldBounds = trail.bounds;\n                        Handles.DrawWireCube(worldBounds.center, worldBounds.size);\n                    }\n                }\n\n                Handles.color = oldCol;\n            }\n\n            // Move trail using shape\n            if (target is TrailRenderer tr)\n            {\n                if (m_PreviewBackupPosition.HasValue)\n                {\n                    if (s_PreviewIsPlaying && !s_PreviewIsPaused)\n                    {\n                        Tools.hidden = !(EditorToolManager.activeTool is ShapeGizmoTool);\n\n                        float previousPreviewTimePercentage = m_PreviewTimePercentage;\n                        float timeStep = Mathf.Min(Time.deltaTime, 0.1f);\n\n                        float moveSpeed = s_PreviewMovementSpeed;\n                        if (s_PreviewShape == PreviewShape.Spring)\n                            moveSpeed *= 0.5f;\n\n                        m_PreviewTimePercentage += (timeStep * moveSpeed * s_PreviewTimeScale);\n                        m_PreviewTimePercentage %= 1.0f;\n\n                        tr.previewTimeScale = s_PreviewTimeScale;\n\n                        var transform = tr.transform;\n                        Matrix4x4 localTransform = Matrix4x4.TRS(Vector3.zero, transform.localRotation, transform.localScale);\n\n                        switch (s_PreviewShape)\n                        {\n                            case PreviewShape.Circle:\n                                transform.localPosition = m_PreviewBackupPosition.Value + localTransform.MultiplyPoint(new Vector3(Mathf.Sin(m_PreviewTimePercentage * Mathf.PI * 2.0f), Mathf.Cos(m_PreviewTimePercentage * Mathf.PI * 2.0f), 0.0f) * s_PreviewShapeSize);\n                                break;\n                            case PreviewShape.Square:\n                                if (m_PreviewTimePercentage < 0.25f)\n                                    transform.localPosition = m_PreviewBackupPosition.Value + localTransform.MultiplyPoint(new Vector3(Mathf.Lerp(-1.0f, 1.0f, m_PreviewTimePercentage * 4.0f), -1.0f, 0.0f) * s_PreviewShapeSize);\n                                else if (m_PreviewTimePercentage < 0.5f)\n                                    transform.localPosition = m_PreviewBackupPosition.Value + localTransform.MultiplyPoint(new Vector3(1.0f, Mathf.Lerp(-1.0f, 1.0f, (m_PreviewTimePercentage - 0.25f) * 4.0f), 0.0f) * s_PreviewShapeSize);\n                                else if (m_PreviewTimePercentage < 0.75f)\n                                    transform.localPosition = m_PreviewBackupPosition.Value + localTransform.MultiplyPoint(new Vector3(Mathf.Lerp(1.0f, -1.0f, (m_PreviewTimePercentage - 0.5f) * 4.0f), 1.0f, 0.0f) * s_PreviewShapeSize);\n                                else\n                                    transform.localPosition = m_PreviewBackupPosition.Value + localTransform.MultiplyPoint(new Vector3(-1.0f, Mathf.Lerp(1.0f, -1.0f, (m_PreviewTimePercentage - 0.75f) * 4.0f), 0.0f) * s_PreviewShapeSize);\n                                break;\n                            case PreviewShape.Line:\n                                transform.localPosition = m_PreviewBackupPosition.Value + localTransform.MultiplyPoint(new Vector3(Mathf.Lerp(-1.0f, 1.0f, m_PreviewTimePercentage), 0.0f, 0.0f) * s_PreviewShapeSize);\n                                break;\n                            case PreviewShape.SineWave:\n                                transform.localPosition = m_PreviewBackupPosition.Value + localTransform.MultiplyPoint(new Vector3(Mathf.Lerp(-1.0f, 1.0f, m_PreviewTimePercentage), Mathf.Sin(m_PreviewTimePercentage * Mathf.PI * 2.0f * k_SineWaveRepeat) * k_SineWaveHeightMultiplier, 0.0f) * s_PreviewShapeSize);\n                                break;\n                            case PreviewShape.Spring:\n                                transform.localPosition = m_PreviewBackupPosition.Value + localTransform.MultiplyPoint(new Vector3(Mathf.Sin(m_PreviewTimePercentage * Mathf.PI * 2.0f * k_SpringRotations), Mathf.Cos(m_PreviewTimePercentage * Mathf.PI * 2.0f * k_SpringRotations), Mathf.Lerp(-0.5f, 0.5f, m_PreviewTimePercentage) * k_SpringRotations) * s_PreviewShapeSize);\n                                break;\n                        }\n\n                        // Clear non-looping shapes when they repeat\n                        if (previousPreviewTimePercentage > m_PreviewTimePercentage)\n                        {\n                            if (s_PreviewShape == PreviewShape.Line || s_PreviewShape == PreviewShape.SineWave || s_PreviewShape == PreviewShape.Spring)\n                                tr.Clear();\n                        }\n\n                        // Clear the trail when a preview starts\n                        if (m_PreviewIsFirstMove)\n                        {\n                            tr.Clear();\n                            m_PreviewIsFirstMove = false;\n                        }\n                    }\n                    else if (s_PreviewIsPaused)\n                    {\n                        tr.previewTimeScale = 0.0f;\n                    }\n                }\n                else\n                {\n                    tr.previewTimeScale = s_PreviewTimeScale; // Not playing or paused, but might be dragging the Trail around the scene view using the Transform gizmo\n                }\n            }\n        }\n\n        private void RepaintSceneView()\n        {\n            if (s_PreviewIsPlaying && !s_PreviewIsPaused)\n                SceneView.RepaintAll();\n        }\n\n        private void Play()\n        {\n            if (!s_PreviewIsPlaying && !s_PreviewIsPaused)\n                SavePositionForPreview();\n\n            s_PreviewIsPlaying = true;\n            s_PreviewIsPaused = false;\n        }\n\n        private void Pause()\n        {\n            s_PreviewIsPlaying = false;\n            s_PreviewIsPaused = true;\n            Tools.hidden = false;\n        }\n\n        private void Stop()\n        {\n            s_PreviewIsPlaying = false;\n            s_PreviewIsPaused = false;\n            RestorePositionAfterPreview();\n        }\n\n        private void PlayStopGUI()\n        {\n            bool disablePlayButton = (Time.timeScale == 0.0f);\n            GUIContent playText = disablePlayButton ? Styles.playDisabled : Styles.play;\n\n            // Play/Stop buttons\n            GUILayout.BeginHorizontal(GUILayout.Width(220.0f));\n            {\n                using (new EditorGUI.DisabledScope(disablePlayButton))\n                {\n                    bool isPlaying = s_PreviewIsPlaying && !s_PreviewIsPaused && !disablePlayButton;\n                    if (GUILayout.Button(isPlaying ? Styles.pause : playText, \"ButtonLeft\"))\n                    {\n                        if (isPlaying)\n                            Pause();\n                        else\n                            Play();\n                    }\n                }\n\n                if (GUILayout.Button(Styles.restart, \"ButtonMid\"))\n                {\n                    Stop();\n                    Play();\n                }\n\n                if (GUILayout.Button(Styles.stop, \"ButtonRight\"))\n                {\n                    Stop();\n                }\n            }\n            GUILayout.EndHorizontal();\n\n            // Playback info\n            PlayBackInfoGUI();\n\n            // Handle shortcut keys last so we do not activate them if inputfield has used the event\n            HandleKeyboardShortcuts();\n        }\n\n        private void PlayBackInfoGUI()\n        {\n            EventType oldEventType = Event.current.type;\n            int oldHotControl = GUIUtility.hotControl;\n            string oldFormat = EditorGUI.kFloatFieldFormatString;\n\n            EditorGUIUtility.labelWidth = k_SceneViewOverlayLabelWidth;\n\n            EditorGUI.kFloatFieldFormatString = Styles.secondsFloatFieldFormatString;\n            if (Time.timeScale == 0.0f)\n            {\n                using (new EditorGUI.DisabledScope(true))\n                {\n                    EditorGUILayout.FloatField(Styles.movementSpeedDisabled, 0.0f);\n                    EditorGUILayout.FloatField(Styles.timeScaleDisabled, 0.0f);\n                }\n            }\n            else\n            {\n                EditorGUI.BeginChangeCheck();\n                s_PreviewMovementSpeed = Mathf.Clamp(EditorGUILayout.FloatField(Styles.movementSpeed, s_PreviewMovementSpeed), 0.0f, 2.0f);\n                s_PreviewTimeScale = Mathf.Clamp(EditorGUILayout.FloatField(Styles.timeScale, s_PreviewTimeScale), 0.1f, 1.0f);\n                if (EditorGUI.EndChangeCheck())\n                    m_PreviewIsFirstMove = true;\n            }\n\n            EditorGUI.BeginChangeCheck();\n            s_PreviewShape = (PreviewShape)EditorGUILayout.EnumPopup(Styles.previewShape, s_PreviewShape);\n            if (EditorGUI.EndChangeCheck())\n                m_PreviewIsFirstMove = true;\n\n            EditorGUI.BeginChangeCheck();\n            s_PreviewShapeSize = EditorGUILayout.FloatField(Styles.previewShapeSize, s_PreviewShapeSize);\n            if (EditorGUI.EndChangeCheck())\n            {\n                s_PreviewShapeSize = ClampPreviewSize(target as TrailRenderer, s_PreviewShapeSize);\n                m_PreviewIsFirstMove = true;\n            }\n\n            EditorGUI.kFloatFieldFormatString = oldFormat;\n\n            s_PreviewShowBounds = GUILayout.Toggle(s_PreviewShowBounds, Styles.showBounds, EditorStyles.toggle);\n\n            EditorGUIUtility.labelWidth = 0.0f;\n        }\n\n        private void HandleKeyboardShortcuts()\n        {\n            var evt = Event.current;\n\n            if (evt.type == EventType.ExecuteCommand)\n            {\n                if (HandleShortcutEvent(evt))\n                    evt.Use();\n            }\n        }\n\n        private bool HandleShortcutEvent(Event evt)\n        {\n            if (EditorApplication.isPlaying)\n                return false;\n\n            if (evt.commandName == s_PlayEvent.commandName)\n            {\n                if (!s_PreviewIsPlaying)\n                    Play();\n                else\n                    Pause();\n\n                return true;\n            }\n            else if (evt.commandName == s_StopEvent.commandName)\n            {\n                Stop();\n                return true;\n            }\n            else if (evt.commandName == s_RestartEvent.commandName)\n            {\n                Stop();\n                Play();\n                return true;\n            }\n            else if (evt.commandName == s_ShowBoundsEvent.commandName)\n            {\n                s_PreviewShowBounds = !s_PreviewShowBounds;\n                return true;\n            }\n\n            return false;\n        }\n\n        private static Matrix4x4 GetPreviewMatrix(Vector3? backupPosition, Transform transform)\n        {\n            Matrix4x4 parentMatrix = Matrix4x4.identity;\n            if (transform.parent)\n                parentMatrix = transform.parent.localToWorldMatrix;\n\n            Vector3 localPosition = backupPosition.HasValue ? backupPosition.Value : transform.localPosition;\n            Matrix4x4 localMatrix = Matrix4x4.TRS(localPosition, transform.localRotation, transform.localScale);\n            return parentMatrix * localMatrix;\n        }\n\n        [Overlay(typeof(SceneView), k_OverlayId, k_DisplayName)]\n        class SceneViewTrailRendererOverlay : TransientSceneViewOverlay\n        {\n            const string k_OverlayId = \"Scene View/TrailRenderer\";\n            const string k_DisplayName = \"Trail Renderer\";\n\n            public override bool visible\n            {\n                get { return s_Inspectors != null && s_Inspectors.Count > 0 && !EditorApplication.isPlaying && (s_Inspectors.Last().targets.Length == 1); }\n            }\n\n            public override void OnGUI()\n            {\n                if (!visible)\n                    return;\n                s_Inspectors.Last().PlayStopGUI();\n            }\n        }\n\n        [EditorTool(\"Shape\", typeof(TrailRenderer))]\n        class ShapeGizmoTool : EditorTool, IDrawSelectedHandles\n        {\n            public override GUIContent toolbarIcon\n            {\n                get { return Styles.toolIcon; }\n            }\n\n            public override bool IsAvailable()\n            {\n                // Check for count != 1\n                if (targets.Skip(1).Any())\n                    return false;\n                if (s_Inspectors == null || s_Inspectors.Count == 0)\n                    return false;\n\n                return !EditorApplication.isPlaying;\n            }\n\n            public override void OnToolGUI(EditorWindow window)\n            {\n                if (s_Inspectors == null || !s_Inspectors.Any())\n                    return;\n\n                DrawHandles(s_Inspectors.Last(), true);\n            }\n\n            public void OnDrawHandles()\n            {\n                if (!s_PreviewIsPlaying)\n                    DrawHandles(s_Inspectors.Last(), false);\n            }\n\n            private void DrawHandles(TrailRendererInspector inspector, bool allowGizmoEditing)\n            {\n                Color gizmoEditingColor = new Color(1.0f, 1.0f, 1.0f, allowGizmoEditing && !Event.current.alt ? 1.0f : 0.0f);\n\n                Color origCol = Handles.color;\n                Handles.color = s_GizmoColor;\n\n                Matrix4x4 orgMatrix = Handles.matrix;\n\n                foreach (var tr in targets.OfType<TrailRenderer>())\n                {\n                    Handles.matrix = GetPreviewMatrix(inspector.m_PreviewBackupPosition, tr.transform);\n\n                    switch (s_PreviewShape)\n                    {\n                        case PreviewShape.Circle:\n                            {\n                                EditorGUI.BeginChangeCheck();\n\n                                inspector.m_PreviewArcHandle.angle = 360.0f;\n                                inspector.m_PreviewArcHandle.radius = s_PreviewShapeSize;\n                                inspector.m_PreviewArcHandle.SetColorWithRadiusHandle(Color.white, 0f);\n                                inspector.m_PreviewArcHandle.radiusHandleColor *= gizmoEditingColor;\n                                inspector.m_PreviewArcHandle.angleHandleColor = Color.clear;\n\n                                using (new Handles.DrawingScope(Handles.matrix * s_ArcHandleOffsetMatrix))\n                                    inspector.m_PreviewArcHandle.DrawHandle();\n\n                                if (EditorGUI.EndChangeCheck())\n                                    s_PreviewShapeSize = ClampPreviewSize(tr, inspector.m_PreviewArcHandle.radius);\n                            }\n                            break;\n                        case PreviewShape.Square:\n                            {\n                                EditorGUI.BeginChangeCheck();\n                                float size = DoSimpleSquareHandle(s_PreviewShapeSize, allowGizmoEditing);\n                                if (EditorGUI.EndChangeCheck())\n                                    s_PreviewShapeSize = ClampPreviewSize(tr, size);\n                            }\n                            break;\n                        case PreviewShape.Line:\n                            {\n                                EditorGUI.BeginChangeCheck();\n                                float radius = Handles.DoSimpleEdgeHandle(Quaternion.identity, Vector3.zero, s_PreviewShapeSize, allowGizmoEditing);\n                                if (EditorGUI.EndChangeCheck())\n                                    s_PreviewShapeSize = ClampPreviewSize(tr, radius);\n                            }\n                            break;\n                        case PreviewShape.SineWave:\n                            {\n                                EditorGUI.BeginChangeCheck();\n                                float radius = DoSimpleSineWaveHandle(s_PreviewShapeSize, allowGizmoEditing, k_SineWaveHeightMultiplier, k_SineWaveRepeat);\n                                if (EditorGUI.EndChangeCheck())\n                                    s_PreviewShapeSize = ClampPreviewSize(tr, radius);\n                            }\n                            break;\n                        case PreviewShape.Spring:\n                            {\n                                EditorGUI.BeginChangeCheck();\n                                float radius = DoSimpleSpringHandle(s_PreviewShapeSize, allowGizmoEditing, k_SpringRotations);\n                                if (EditorGUI.EndChangeCheck())\n                                    s_PreviewShapeSize = ClampPreviewSize(tr, radius);\n                            }\n                            break;\n                    }\n                }\n\n                Handles.color = origCol;\n                Handles.matrix = orgMatrix;\n            }\n\n            private static float DoSimpleSquareHandle(float size, bool editable)\n            {\n                if (Event.current.alt)\n                    editable = false;\n\n                Vector3 right = Vector3.right;\n                Vector3 up = Vector3.up;\n\n                if (editable)\n                {\n                    // Size handles at edges\n                    EditorGUI.BeginChangeCheck();\n                    size = Handles.SizeSlider(Vector3.zero, up, size);\n                    size = Handles.SizeSlider(Vector3.zero, -up, size);\n                    size = Handles.SizeSlider(Vector3.zero, right, size);\n                    size = Handles.SizeSlider(Vector3.zero, -right, size);\n                    if (EditorGUI.EndChangeCheck())\n                        size = Mathf.Max(0.0f, size);\n                }\n\n                // Draw gizmo\n                if (size > 0)\n                {\n                    Vector3[] points = new Vector3[5];\n\n                    points[0] = up * size + right * size;\n                    points[1] = -up * size + right * size;\n                    points[2] = -up * size - right * size;\n                    points[3] = up * size - right * size;\n                    points[4] = points[0];\n\n                    Handles.DrawPolyLine(points);\n                }\n\n                return size;\n            }\n\n            private static float DoSimpleSineWaveHandle(float radius, bool editable, float heightMultiplier, float repeatCount)\n            {\n                if (Event.current.alt)\n                    editable = false;\n\n                Vector3 right = Vector3.right;\n                Vector3 up = Vector3.up;\n\n                if (editable)\n                {\n                    // Radius handles at ends\n                    EditorGUI.BeginChangeCheck();\n                    radius = Handles.SizeSlider(Vector3.zero, right, radius);\n                    radius = Handles.SizeSlider(Vector3.zero, -right, radius);\n                    if (EditorGUI.EndChangeCheck())\n                        radius = Mathf.Max(0.0f, radius);\n                }\n\n                // Draw gizmo\n                if (radius > 0)\n                {\n                    Vector3 start = -right * radius;\n\n                    Vector3[] points = new Vector3[128];\n                    for (int i = 0; i < points.Length; i++)\n                    {\n                        float percent = ((float)i / (points.Length - 1));\n                        Vector3 sine = start + right * (radius * percent) * 2.0f;\n                        sine += up * Mathf.Sin(percent * Mathf.PI * 2.0f * repeatCount) * radius * heightMultiplier;\n                        points[i] = sine;\n                    }\n\n                    Handles.DrawPolyLine(points);\n                }\n\n                return radius;\n            }\n\n            private static float DoSimpleSpringHandle(float radius, bool editable, float rotationCount)\n            {\n                if (Event.current.alt)\n                    editable = false;\n\n                Vector3 right = Vector3.right;\n                Vector3 up = Vector3.up;\n\n                if (editable)\n                {\n                    // Radius handles at ends\n                    EditorGUI.BeginChangeCheck();\n\n                    Vector3 start = new Vector3(0.0f, 0.0f, -0.5f * rotationCount) * radius;\n                    radius = Handles.SizeSlider(start, up, radius);\n\n                    Vector3 end = new Vector3(0.0f, 0.0f, 0.5f * rotationCount) * radius;\n                    radius = Handles.SizeSlider(end, up, radius);\n\n                    if (EditorGUI.EndChangeCheck())\n                        radius = Mathf.Max(0.0f, radius);\n                }\n\n                // Draw gizmo\n                if (radius > 0)\n                {\n                    Vector3[] points = new Vector3[128];\n                    for (int i = 0; i < points.Length; i++)\n                    {\n                        float percent = ((float)i / (points.Length - 1));\n                        float theta = percent * Mathf.PI * 2.0f * rotationCount;\n                        Vector3 sine = new Vector3(Mathf.Sin(theta), Mathf.Cos(theta), Mathf.Lerp(-0.5f, 0.5f, percent) * rotationCount);\n                        points[i] = sine * radius;\n                    }\n\n                    Handles.DrawPolyLine(points);\n                }\n\n                return radius;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/TransformInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(Transform))]\n    [CanEditMultipleObjects]\n    internal class TransformInspector : Editor\n    {\n        SerializedProperty m_Position;\n        SerializedProperty m_Scale;\n        TransformRotationGUI m_RotationGUI;\n        ConstrainProportionsTransformScale m_ConstrainProportionsScale;\n        SerializedProperty m_ConstrainProportionsScaleProperty;\n        bool m_IsScaleDirty;\n\n        class Contents\n        {\n            public GUIContent positionContent = EditorGUIUtility.TrTextContent(\"Position\", \"The local position of this GameObject relative to the parent.\");\n            public GUIContent scaleContent = EditorGUIUtility.TrTextContent(\"Scale\", \"The local scaling of this GameObject relative to the parent.\");\n            public string floatingPointWarning = LocalizationDatabase.GetLocalizedString(\"Due to floating-point precision limitations, it is recommended to bring the world coordinates of the GameObject within a smaller range.\");\n        }\n        static Contents s_Contents;\n\n        public void OnEnable()\n        {\n            m_Position = serializedObject.FindProperty(\"m_LocalPosition\");\n            m_Scale = serializedObject.FindProperty(\"m_LocalScale\");\n            m_ConstrainProportionsScaleProperty = serializedObject.FindProperty(\"m_ConstrainProportionsScale\");\n\n            if (m_RotationGUI == null)\n                m_RotationGUI = new TransformRotationGUI();\n            m_RotationGUI.OnEnable(serializedObject.FindProperty(\"m_LocalRotation\"), EditorGUIUtility.TrTextContent(\"Rotation\", \"The local rotation of this GameObject relative to the parent.\"));\n            m_ConstrainProportionsScale = new ConstrainProportionsTransformScale(m_Scale.vector3Value);\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (s_Contents == null)\n                s_Contents = new Contents();\n\n            if (!EditorGUIUtility.wideMode)\n            {\n                EditorGUIUtility.wideMode = true;\n                EditorGUIUtility.labelWidth = EditorGUIUtility.currentViewWidth - 212;\n            }\n\n            serializedObject.Update();\n\n            Inspector3D();\n\n            // If scale is dirty, update serializedObject to avoid overwriting new value with previous one when applying modifications\n            if (m_IsScaleDirty)\n                serializedObject.Update();\n\n            // Warning if global position is too large for floating point errors.\n            // SanitizeBounds function doesn't even support values beyond 100000\n            Transform t = target as Transform;\n            Vector3 pos = t.position;\n            if (Mathf.Abs(pos.x) > 100000 || Mathf.Abs(pos.y) > 100000 || Mathf.Abs(pos.z) > 100000)\n                EditorGUILayout.HelpBox(s_Contents.floatingPointWarning, MessageType.Warning);\n\n            bool saveUndoName = serializedObject.hasModifiedProperties;\n            serializedObject.ApplyModifiedProperties();\n\n            if (saveUndoName)\n            {\n                int selection = Selection.count;\n                if (t.position != pos)\n                    Undo.SetCurrentGroupName(string.Format(\"Set Position to {0} in {1}\", t.localPosition, selection == 1 ? target.name : \"Selected Objects\"));\n                else\n                    Undo.SetCurrentGroupName(string.Format(\"Set Scale to {0} in {1}\", t.localScale, selection == 1 ? target.name : \"Selected Objects\"));\n            }\n\n            if (m_IsScaleDirty)\n            {\n                m_IsScaleDirty = false;\n                OnForceReloadInspector();\n            }\n            //resetting label width as it is carried over to other windows\n            EditorGUIUtility.labelWidth = 0;\n        }\n\n        void Inspector3D()\n        {\n            EditorGUILayout.PropertyField(m_Position, s_Contents.positionContent);\n            m_RotationGUI.RotationField();\n            Transform t = target as Transform;\n\n            if (t != null && m_ConstrainProportionsScale.Initialize(serializedObject.targetObjects) && m_ConstrainProportionsScaleProperty != null)\n            {\n                //AxisModified values [-1;2] : [none, x, y, z]\n                int axisModified = -1;\n                var mixedFields = ConstrainProportionsTransformScale.GetMixedValueFields(m_Scale);\n                Vector3 currentScale = m_ConstrainProportionsScale.DoGUI(EditorGUILayout.GetControlRect(true),\n                    s_Contents.scaleContent, m_Scale.vector3Value, serializedObject.targetObjects, ref axisModified, m_Scale, m_ConstrainProportionsScaleProperty);\n                var mixedFieldsAfterGUI = ConstrainProportionsTransformScale.GetMixedValueFields(m_Scale);\n\n                if (currentScale != m_Scale.vector3Value || mixedFields != mixedFieldsAfterGUI)\n                {\n                    if (serializedObject.targetObjectsCount > 1)\n                    {\n                        if (mixedFields != mixedFieldsAfterGUI)\n                        {\n                            axisModified = -1;\n                            for (int i = 0; i < 3; i++)\n                            {\n                                if (ConstrainProportionsTransformScale.IsBit(mixedFields, i) && !ConstrainProportionsTransformScale.IsBit(mixedFieldsAfterGUI, i))\n                                {\n                                    axisModified = i;\n                                    break;\n                                }\n                            }\n                        }\n\n                        if (axisModified != -1)\n                            m_IsScaleDirty = ConstrainProportionsTransformScale.HandleMultiSelectionScaleChanges(\n                                m_Scale.vector3Value,\n                                currentScale, m_ConstrainProportionsScale.constrainProportionsScale,\n                                serializedObject.targetObjects, ref axisModified);\n                    }\n\n                    if (currentScale != m_Scale.vector3Value)\n                        m_Scale.vector3Value = currentScale;\n                }\n            }\n            else\n            {\n                EditorGUILayout.PropertyField(m_Scale, s_Contents.scaleContent);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/TransformRotationGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    internal class TransformRotationGUI\n    {\n        private GUIContent rotationContent = EditorGUIUtility.TrTextContent(\"Rotation\", \"The local rotation of this Game Object relative to the parent.\");\n        private const float kQuaternionFloatPrecision = 1e-6f;\n\n        EditorGUI.NumberFieldValue[] m_EulerFloats =\n        {\n            new EditorGUI.NumberFieldValue(0.0f),\n            new EditorGUI.NumberFieldValue(0.0f),\n            new EditorGUI.NumberFieldValue(0.0f)\n        };\n\n        SerializedProperty m_Rotation;\n        Object[] targets;\n\n        private static int s_FoldoutHash = \"Foldout\".GetHashCode();\n        private static readonly GUIContent[] s_XYZLabels = {EditorGUIUtility.TextContent(\"X\"), EditorGUIUtility.TextContent(\"Y\"), EditorGUIUtility.TextContent(\"Z\")};\n\n        public void OnEnable(SerializedProperty m_Rotation, GUIContent label)\n        {\n            this.m_Rotation = m_Rotation;\n            this.targets = m_Rotation.serializedObject.targetObjects;\n            rotationContent = label;\n        }\n\n        public void RotationField()\n        {\n            RotationField(false);\n        }\n\n        public void RotationField(bool disabled)\n        {\n            Transform transform0 = targets[0] as Transform;\n            Vector3 eulerAngles0 = transform0.GetLocalEulerAngles(transform0.rotationOrder);\n\n            int differentRotationMask = 0b000;\n            bool differentRotationOrder = false;\n            for (int i = 1; i < targets.Length; i++)\n            {\n                Transform otherTransform = (targets[i] as Transform);\n                if (differentRotationMask != 0b111)\n                {\n                    Vector3 otherLocalEuler = otherTransform.GetLocalEulerAngles(otherTransform.rotationOrder);\n                    for (int j = 0; j < 3; j++)\n                    {\n                        if (otherLocalEuler[j] != eulerAngles0[j])\n                            differentRotationMask |= 1 << j;\n                    }\n                }\n\n                differentRotationOrder |= otherTransform.rotationOrder != transform0.rotationOrder;\n            }\n\n            Rect r = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 1 : 2));\n            GUIContent label = EditorGUI.BeginProperty(r, rotationContent, m_Rotation);\n\n            if (m_Rotation.isLiveModified)\n            {\n                Vector3 eulerValue = m_Rotation.quaternionValue.eulerAngles;\n                m_EulerFloats[0].doubleVal = Mathf.Floor(eulerValue.x / kQuaternionFloatPrecision) * kQuaternionFloatPrecision;\n                m_EulerFloats[1].doubleVal = Mathf.Floor(eulerValue.y / kQuaternionFloatPrecision) * kQuaternionFloatPrecision;\n                m_EulerFloats[2].doubleVal = Mathf.Floor(eulerValue.z / kQuaternionFloatPrecision) * kQuaternionFloatPrecision;\n            }\n            else\n            {\n                m_EulerFloats[0].doubleVal = eulerAngles0.x;\n                m_EulerFloats[1].doubleVal = eulerAngles0.y;\n                m_EulerFloats[2].doubleVal = eulerAngles0.z;\n            }\n\n            int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, r);\n            if (AnimationMode.InAnimationMode() && transform0.rotationOrder != RotationOrder.OrderZXY)\n            {\n                string rotationLabel = differentRotationOrder ? \"Mixed\" : transform0.rotationOrder.ToString().Substring(RotationOrder.OrderXYZ.ToString().Length - 3);\n                label.text = label.text + \" (\" + rotationLabel + \")\";\n            }\n\n            // Using manual 3 float fields here instead of MultiFloatField or Vector3Field\n            // since we want to query expression validity of each individually, and\n            // so that the label and the fields can be disabled separately, similar to\n            // regular property fields. Also want to avoid superfluous label, which\n            // creates a focus target even when there's no content (Case 953241).\n            r = EditorGUI.MultiFieldPrefixLabel(r, id, label, 3);\n            r.height = EditorGUIUtility.singleLineHeight;\n            int eulerChangedMask = 0;\n            using (new EditorGUI.DisabledScope(disabled))\n            {\n                var eCount = m_EulerFloats.Length;\n                float w = (r.width - (eCount - 1) * EditorGUI.kSpacingSubLabel) / eCount;\n                Rect nr = new Rect(r) {width = w};\n                var prevWidth = EditorGUIUtility.labelWidth;\n                var prevIndent = EditorGUI.indentLevel;\n                EditorGUI.indentLevel = 0;\n                SerializedProperty rotation = m_Rotation.Copy();\n\n                for (int i = 0; i < m_EulerFloats.Length; i++)\n                {\n                    rotation.Next(true);\n                    EditorGUI.BeginProperty(nr, s_XYZLabels[i], rotation);\n\n                    EditorGUIUtility.labelWidth = EditorGUI.GetLabelWidth(s_XYZLabels[i]);\n                    EditorGUI.BeginChangeCheck();\n                    EditorGUI.showMixedValue = (differentRotationMask & (1 << i)) != 0;\n                    EditorGUI.FloatField(nr, s_XYZLabels[i], ref m_EulerFloats[i]);\n                    if (EditorGUI.EndChangeCheck() && m_EulerFloats[i].hasResult)\n                        eulerChangedMask |= 1 << i;\n\n                    if (Event.current.type == EventType.ContextClick && nr.Contains(Event.current.mousePosition))\n                    {\n                        var childProperty = m_Rotation.Copy();\n                        childProperty.Next(true);\n                        int childPropertyIndex = i;\n                        while (childPropertyIndex > 0)\n                        {\n                            childProperty.Next(false);\n                            childPropertyIndex--;\n                        }\n\n                        EditorGUI.DoPropertyContextMenu(childProperty);\n                        Event.current.Use();\n                    }\n\n                    nr.x += w + EditorGUI.kSpacingSubLabel;\n\n                    EditorGUI.EndProperty();\n                }\n                EditorGUIUtility.labelWidth = prevWidth;\n                EditorGUI.indentLevel = prevIndent;\n            }\n\n            if (eulerChangedMask != 0)\n            {\n                eulerAngles0 = new Vector3(\n                    MathUtils.ClampToFloat(m_EulerFloats[0].doubleVal),\n                    MathUtils.ClampToFloat(m_EulerFloats[1].doubleVal),\n                    MathUtils.ClampToFloat(m_EulerFloats[2].doubleVal));\n                Undo.RecordObjects(targets, \"Inspector\");  // Generic undo title as remove duplicates will discard the name.\n                Undo.SetCurrentGroupName(string.Format(\"Set Rotation\"));\n                for (var idx = 0; idx < targets.Length; ++idx)\n                {\n                    var tr = targets[idx] as Transform;\n                    if (tr == null)\n                        continue;\n                    var trEuler = tr.GetLocalEulerAngles(tr.rotationOrder);\n                    // if we have any per-object expressions just entered, we need to evaluate\n                    // it for each object with their own individual input value\n                    for (int c = 0; c < 3; ++c)\n                    {\n                        if ((eulerChangedMask & (1 << c)) != 0)\n                        {\n                            if (m_EulerFloats[c].expression != null)\n                            {\n                                double trEulerComp = eulerAngles0[c];\n                                if (m_EulerFloats[c].expression.Evaluate(ref trEulerComp, idx, targets.Length))\n                                    trEuler[c] = MathUtils.ClampToFloat(trEulerComp);\n                            }\n                            else\n                            {\n                                trEuler[c] = MathUtils.ClampToFloat(eulerAngles0[c]);\n                            }\n                        }\n                    }\n\n                    if (m_Rotation.isLiveModified)\n                    {\n                        m_Rotation.quaternionValue = Quaternion.Euler(trEuler.x, trEuler.y, trEuler.z);\n                    }\n                    else\n                    {\n                        tr.SetLocalEulerAngles(trEuler, tr.rotationOrder);\n                        if (tr.parent != null)\n                            tr.SendTransformChangedScale(); // force scale update, needed if tr has non-uniformly scaled parent.\n                    }\n                }\n                m_Rotation.serializedObject.SetIsDifferentCacheDirty();\n            }\n\n            EditorGUI.showMixedValue = false;\n\n            if (differentRotationOrder)\n            {\n                EditorGUILayout.HelpBox(\"Transforms have different rotation orders, keyframes saved will have the same value but not the same local rotation\", MessageType.Warning);\n            }\n\n            EditorGUI.EndProperty();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/TransformUtils.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditor\n{\n    public static class TransformUtils\n    {\n        public static Vector3 GetInspectorRotation(Transform t)\n        {\n            return t.GetLocalEulerAngles(t.rotationOrder);\n        }\n\n        public static void SetInspectorRotation(Transform t, Vector3 r)\n        {\n            t.SetLocalEulerAngles(r, t.rotationOrder);\n        }\n\n        public static bool GetConstrainProportions(Transform transform)\n        {\n            return GetConstrainProportions(new []{transform});\n        }\n\n        public static bool GetConstrainProportions(Transform[] transforms)\n        {\n            return Selection.DoAllGOsHaveConstrainProportionsEnabled(transforms);\n        }\n\n        public static void SetConstrainProportions(Transform transform, bool enabled)\n        {\n            SetConstrainProportions(new[] { transform }, enabled);\n        }\n\n        public static void SetConstrainProportions(Transform[] transforms, bool enabled)\n        {\n            foreach (var t in transforms)\n            {\n                if (t == null)\n                    throw new ArgumentNullException(\"transform\", \"One or more transforms are null\");\n            }\n\n            ConstrainProportionsTransformScale.SetConstrainProportions(transforms, enabled);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/UNetBehaviourInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n// gone\n"
  },
  {
    "path": "Editor/Mono/Inspector/UnityEventDrawer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing System.Text;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditor.UIElements;\nusing UnityEngine.Events;\nusing Object = UnityEngine.Object;\nusing UnityEngine.Pool;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditorInternal\n{\n    [CustomPropertyDrawer(typeof(UnityEventBase), true)]\n    public class UnityEventDrawer : PropertyDrawer\n    {\n        protected class State\n        {\n            internal ReorderableList m_ReorderableList;\n            public int lastSelectedIndex;\n        }\n\n        private const string kNoFunctionString = \"No Function\";\n\n        //Persistent Listener Paths\n        internal const string kInstancePath   = \"m_Target\";\n        internal const string kInstanceTypePath = \"m_TargetAssemblyTypeName\";\n        internal const string kCallStatePath  = \"m_CallState\";\n        internal const string kArgumentsPath  = \"m_Arguments\";\n        internal const string kModePath       = \"m_Mode\";\n        internal const string kMethodNamePath = \"m_MethodName\";\n        internal const string kCallsPath      = \"m_PersistentCalls.m_Calls\";\n\n        //ArgumentCache paths\n        internal const string kFloatArgument  = \"m_FloatArgument\";\n        internal const string kIntArgument    = \"m_IntArgument\";\n        internal const string kObjectArgument = \"m_ObjectArgument\";\n        internal const string kStringArgument = \"m_StringArgument\";\n        internal const string kBoolArgument = \"m_BoolArgument\";\n        internal const string kObjectArgumentAssemblyTypeName = \"m_ObjectArgumentAssemblyTypeName\";\n\n        // uss names\n        internal const string kUssClassName = \"unity-event\";\n        internal const string kLeftColumnClassName = kUssClassName + \"__left-column\";\n        internal const string kRightColumnClassName = kUssClassName + \"__right-column\";\n        internal const string kContainerClassName = kUssClassName + \"__container\";\n        internal const string kHeaderClassName = \"unity-list-view__header\";\n        internal const string kListViewScrollViewClassName = kUssClassName + \"__list-view-scroll-view\";\n        internal const string kListViewItemClassName = kUssClassName + \"__list-view-item\";\n\n        string m_Text;\n        UnityEventBase m_DummyEvent;\n        SerializedProperty m_Prop;\n        SerializedProperty m_ListenersArray;\n\n        const int kExtraSpacing = 9;\n\n        //State:\n        ReorderableList m_ReorderableList;\n        int m_LastSelectedIndex;\n        Dictionary<string, State> m_States = new Dictionary<string, State>();\n\n        static string GetEventParams(UnityEventBase evt)\n        {\n            var methodInfo = evt.FindMethod(\"Invoke\", evt.GetType(), PersistentListenerMode.EventDefined, null);\n\n            var sb = new StringBuilder();\n            sb.Append(\" (\");\n\n            var types = methodInfo.GetParameters().Select(x => x.ParameterType).ToArray();\n            for (int i = 0; i < types.Length; i++)\n            {\n                sb.Append(types[i].Name);\n                if (i < types.Length - 1)\n                {\n                    sb.Append(\", \");\n                }\n            }\n            sb.Append(\")\");\n            return sb.ToString();\n        }\n\n        private State GetState(SerializedProperty prop)\n        {\n            State state;\n            string key = prop.propertyPath;\n            m_States.TryGetValue(key, out state);\n            // ensure the cached SerializedProperty is synchronized (case 974069)\n            if (state == null || state.m_ReorderableList.serializedProperty.serializedObject != prop.serializedObject)\n            {\n                if (state == null)\n                    state = new State();\n\n                SerializedProperty listenersArray = prop.FindPropertyRelative(kCallsPath);\n                state.m_ReorderableList =\n                    new ReorderableList(prop.serializedObject, listenersArray, true, true, true, true)\n                {\n                    drawHeaderCallback = DrawEventHeader,\n                    drawElementCallback = DrawEvent,\n                    onSelectCallback = OnSelectEvent,\n                    onReorderCallback = OnReorderEvent,\n                    onAddCallback = OnAddEvent,\n                    onRemoveCallback = OnRemoveEvent\n                };\n                SetupReorderableList(state.m_ReorderableList);\n\n                m_States[key] = state;\n            }\n            return state;\n        }\n\n        private State RestoreState(SerializedProperty property)\n        {\n            State state = GetState(property);\n\n            m_ListenersArray = state.m_ReorderableList.serializedProperty;\n            m_ReorderableList = state.m_ReorderableList;\n            m_LastSelectedIndex = state.lastSelectedIndex;\n            m_ReorderableList.index = m_LastSelectedIndex;\n\n            return state;\n        }\n\n        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n        {\n            m_Prop = property;\n            m_Text = label.text;\n\n            State state = RestoreState(property);\n\n            OnGUI(position);\n            state.lastSelectedIndex = m_LastSelectedIndex;\n        }\n\n        private ListView CreateListView(SerializedProperty property)\n        {\n            var listView = new ListView\n            {\n                showAddRemoveFooter = true,\n                reorderMode = ListViewReorderMode.Animated,\n                reorderable = true,\n                showBorder = true,\n                showFoldoutHeader = false,\n                showBoundCollectionSize = false,\n                showAlternatingRowBackgrounds = AlternatingRowBackground.None,\n                fixedItemHeight = GetElementHeight()\n            };\n\n            var propertyRelative = property.FindPropertyRelative(kCallsPath);\n            listView.bindingPath = propertyRelative.propertyPath;\n\n            listView.makeItem += () => new UnityEventItem\n            {\n                createMenuCallback = data => BuildPopupList(data.listenerTarget.objectReferenceValue, m_DummyEvent, data.listener),\n                formatSelectedValueCallback = data => GetFunctionDropdownText(data.listener),\n                getArgumentCallback = data => GetArgument(data.listener)\n            };\n            listView.bindItem += (VisualElement element, int i) =>\n            {\n                if (i >= propertyRelative.arraySize)\n                {\n                    return;\n                }\n\n                var pListener = propertyRelative.GetArrayElementAtIndex(i);\n                var arguments = pListener.FindPropertyRelative(kArgumentsPath);\n                var listenerTarget = pListener.FindPropertyRelative(kInstancePath);\n\n                var propertyData = new UnityEventItem.PropertyData\n                {\n                    listener = pListener,\n                    mode = pListener.FindPropertyRelative(kModePath),\n                    arguments = arguments,\n                    callState = pListener.FindPropertyRelative(kCallStatePath),\n                    listenerTarget = listenerTarget,\n                    methodName = pListener.FindPropertyRelative(kMethodNamePath),\n                    objectArgument = arguments.FindPropertyRelative(kObjectArgument)\n                };\n\n                var eventItem = element as UnityEventItem;\n                eventItem.BindFields(propertyData);\n            };\n\n            listView.itemsAdded += indices =>\n            {\n                foreach (var i in indices)\n                {\n                    var pListener = propertyRelative.GetArrayElementAtIndex(i);\n                    var callState = pListener.FindPropertyRelative(kCallStatePath);\n                    // SERIAL-124\n                    // Objects added to an array via SerializedObject do not have their default values set.\n                    // Therefore we need to set the initial values here to fix UUM-27561\n                    callState.enumValueIndex = (int)UnityEventCallState.RuntimeOnly;\n                    callState.serializedObject.ApplyModifiedPropertiesWithoutUndo();\n                }\n            };\n\n            return listView;\n        }\n\n        private SerializedProperty GetArgument(SerializedProperty pListener)\n        {\n            var listenerTarget = pListener.FindPropertyRelative(kInstancePath);\n            var methodName = pListener.FindPropertyRelative(kMethodNamePath);\n            var mode = pListener.FindPropertyRelative(kModePath);\n            var arguments = pListener.FindPropertyRelative(kArgumentsPath);\n\n            SerializedProperty argument;\n            var modeEnum = GetMode(mode);\n            //only allow argument if we have a valid target / method\n            if (listenerTarget.objectReferenceValue == null || string.IsNullOrEmpty(methodName.stringValue))\n                modeEnum = PersistentListenerMode.Void;\n\n            switch (modeEnum)\n            {\n                case PersistentListenerMode.Float:\n                    argument = arguments.FindPropertyRelative(kFloatArgument);\n                    break;\n                case PersistentListenerMode.Int:\n                    argument = arguments.FindPropertyRelative(kIntArgument);\n                    break;\n                case PersistentListenerMode.Object:\n                    argument = arguments.FindPropertyRelative(kObjectArgument);\n                    break;\n                case PersistentListenerMode.String:\n                    argument = arguments.FindPropertyRelative(kStringArgument);\n                    break;\n                case PersistentListenerMode.Bool:\n                    argument = arguments.FindPropertyRelative(kBoolArgument);\n                    break;\n                default:\n                    argument = arguments.FindPropertyRelative(kIntArgument);\n                    break;\n            }\n\n            return argument;\n        }\n\n        public override VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            m_Prop = property;\n            m_Text = preferredLabel;\n            m_DummyEvent = GetDummyEvent(m_Prop);\n\n            var listViewContainer = new VisualElement();\n            listViewContainer.AddToClassList(kContainerClassName);\n\n            var header = new Label();\n            header.text = GetHeaderText();\n            header.tooltip = property.tooltip;\n            BindingsStyleHelpers.RegisterRightClickMenu(header, property);\n            header.AddToClassList(kHeaderClassName);\n\n            var listView = CreateListView(property);\n            listView.scrollView.AddToClassList(kListViewScrollViewClassName);\n\n            listViewContainer.Add(header);\n            listViewContainer.Add(listView);\n\n            return listViewContainer;\n        }\n\n        private float GetElementHeight()\n        {\n            return EditorGUI.kSingleLineHeight * 2 + EditorGUI.kControlVerticalSpacing + kExtraSpacing;\n        }\n\n        private string GetHeaderText()\n        {\n            return (string.IsNullOrEmpty(m_Text) ? \"Event\" : m_Text) + GetEventParams(m_DummyEvent);\n        }\n\n        private string GetFunctionDropdownText(SerializedProperty pListener)\n        {\n            var listenerTarget = pListener.FindPropertyRelative(kInstancePath);\n            var methodName = pListener.FindPropertyRelative(kMethodNamePath);\n            var mode = pListener.FindPropertyRelative(kModePath);\n            var arguments = pListener.FindPropertyRelative(kArgumentsPath);\n            var desiredArgTypeName = arguments.FindPropertyRelative(kObjectArgumentAssemblyTypeName).stringValue;\n            var desiredType = typeof(Object);\n            if (!string.IsNullOrEmpty(desiredArgTypeName))\n                desiredType = Type.GetType(desiredArgTypeName, false) ?? typeof(Object);\n\n            var buttonLabel = new StringBuilder();\n            if (listenerTarget.objectReferenceValue == null || string.IsNullOrEmpty(methodName.stringValue))\n            {\n                buttonLabel.Append(kNoFunctionString);\n            }\n            else if (!IsPersistantListenerValid(m_DummyEvent, methodName.stringValue, listenerTarget.objectReferenceValue, GetMode(mode), desiredType))\n            {\n                var instanceString = \"UnknownComponent\";\n                var instance = listenerTarget.objectReferenceValue;\n                if (instance != null)\n                    instanceString = instance.GetType().Name;\n\n                buttonLabel.Append(string.Format(\"<Missing {0}.{1}>\", instanceString, methodName.stringValue));\n            }\n            else\n            {\n                buttonLabel.Append(listenerTarget.objectReferenceValue.GetType().Name);\n\n                if (!string.IsNullOrEmpty(methodName.stringValue))\n                {\n                    buttonLabel.Append(\".\");\n                    if (methodName.stringValue.StartsWith(\"set_\"))\n                        buttonLabel.Append(methodName.stringValue.Substring(4));\n                    else\n                        buttonLabel.Append(methodName.stringValue);\n                }\n            }\n\n            return buttonLabel.ToString();\n        }\n\n        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)\n        {\n            //TODO: Also we need to have a constructor or initializer called for this property Drawer, before OnGUI or GetPropertyHeight\n            //otherwise, we get Restore the State twice, once here and again in OnGUI. Maybe we should only do it here?\n            RestoreState(property);\n\n            float height = 0f;\n            if (m_ReorderableList != null)\n            {\n                height = m_ReorderableList.GetHeight();\n            }\n            return height;\n        }\n\n        public void OnGUI(Rect position)\n        {\n            if (m_ListenersArray == null || !m_ListenersArray.isArray)\n                return;\n\n            m_DummyEvent = GetDummyEvent(m_Prop);\n            if (m_DummyEvent == null)\n                return;\n\n            if (m_ReorderableList != null)\n            {\n                var oldIdentLevel = EditorGUI.indentLevel;\n                position = EditorGUI.IndentedRect(position);\n                EditorGUI.indentLevel = 0;\n                m_ReorderableList.DoList(position);\n                EditorGUI.indentLevel = oldIdentLevel;\n            }\n        }\n\n        protected virtual void SetupReorderableList(ReorderableList list)\n        {\n            // Two standard lines with standard spacing between and extra spacing below to better separate items visually.\n            list.elementHeight = GetElementHeight();\n        }\n\n        protected virtual void DrawEventHeader(Rect headerRect)\n        {\n            headerRect.height = EditorGUI.kSingleLineHeight;\n            string text = GetHeaderText();\n            GUI.Label(headerRect, text);\n        }\n\n        static PersistentListenerMode GetMode(SerializedProperty mode)\n        {\n            return (PersistentListenerMode)mode.enumValueIndex;\n        }\n\n        internal static bool ShouldClearMethodAfterTargetChanged(SerializedProperty listener, Object newValue)\n        {\n            // If the type is the same we dont need to clear the method\n            var typeProperty = listener.FindPropertyRelative(kInstanceTypePath);\n            var typeString = typeProperty.stringValue;\n            if (!string.IsNullOrEmpty(typeString))\n            {\n                var objType = Type.GetType(typeString, false);\n\n                if (objType == null || newValue == null || newValue.GetType() != objType)\n                    return true;\n            }\n\n            // Clear if the value is null\n            return newValue == null;\n        }\n\n        protected virtual void DrawEvent(Rect rect, int index, bool isActive, bool isFocused)\n        {\n            var pListener = m_ListenersArray.GetArrayElementAtIndex(index);\n\n            rect.y++;\n            Rect[] subRects = GetRowRects(rect);\n            Rect enabledRect = subRects[0];\n            Rect goRect = subRects[1];\n            Rect functionRect = subRects[2];\n            Rect argRect = subRects[3];\n\n            // find the current event target...\n            var callState = pListener.FindPropertyRelative(kCallStatePath);\n            var mode = pListener.FindPropertyRelative(kModePath);\n            var arguments = pListener.FindPropertyRelative(kArgumentsPath);\n            var listenerTarget = pListener.FindPropertyRelative(kInstancePath);\n            var methodName = pListener.FindPropertyRelative(kMethodNamePath);\n\n            Color c = GUI.backgroundColor;\n            GUI.backgroundColor = Color.white;\n\n            EditorGUI.PropertyField(enabledRect, callState, GUIContent.none);\n\n            EditorGUI.BeginChangeCheck();\n            {\n                GUI.Box(goRect, GUIContent.none);\n                EditorGUI.PropertyField(goRect, listenerTarget, GUIContent.none);\n                if (EditorGUI.EndChangeCheck() && ShouldClearMethodAfterTargetChanged(pListener, listenerTarget.objectReferenceValue))\n                {\n                    methodName.stringValue = null;\n                }\n            }\n\n            SerializedProperty argument = GetArgument(pListener);\n            var modeEnum = GetMode(mode);\n            //only allow argument if we have a valid target / method\n            if (listenerTarget.objectReferenceValue == null || string.IsNullOrEmpty(methodName.stringValue))\n                modeEnum = PersistentListenerMode.Void;\n\n            var desiredArgTypeName = arguments.FindPropertyRelative(kObjectArgumentAssemblyTypeName).stringValue;\n            var desiredType = typeof(Object);\n            if (!string.IsNullOrEmpty(desiredArgTypeName))\n                desiredType = Type.GetType(desiredArgTypeName, false) ?? typeof(Object);\n\n            if (modeEnum == PersistentListenerMode.Object)\n            {\n                EditorGUI.BeginChangeCheck();\n                var result = EditorGUI.ObjectField(argRect, GUIContent.none, argument.objectReferenceValue, desiredType, true);\n                if (EditorGUI.EndChangeCheck())\n                    argument.objectReferenceValue = result;\n            }\n            else if (modeEnum != PersistentListenerMode.Void && modeEnum != PersistentListenerMode.EventDefined)\n                EditorGUI.PropertyField(argRect, argument, GUIContent.none);\n\n            using (new EditorGUI.DisabledScope(listenerTarget.objectReferenceValue == null))\n            {\n                EditorGUI.BeginProperty(functionRect, GUIContent.none, methodName);\n                {\n                    GUIContent buttonContent;\n                    if (EditorGUI.showMixedValue)\n                    {\n                        buttonContent = EditorGUI.mixedValueContent;\n                    }\n                    else\n                    {\n                        var buttonLabel = GetFunctionDropdownText(pListener);\n                        buttonContent = GUIContent.Temp(buttonLabel.ToString());\n                    }\n\n                    if (EditorGUI.DropdownButton(functionRect, buttonContent, FocusType.Passive, EditorStyles.popup))\n                        BuildPopupList(listenerTarget.objectReferenceValue, m_DummyEvent, pListener).DropDown(functionRect);\n                }\n                EditorGUI.EndProperty();\n            }\n            GUI.backgroundColor = c;\n        }\n\n        Rect[] GetRowRects(Rect rect)\n        {\n            Rect[] rects = new Rect[4];\n\n            rect.height = EditorGUI.kSingleLineHeight;\n            rect.y += 2;\n\n            Rect enabledRect = rect;\n            enabledRect.width *= 0.3f;\n\n            Rect goRect = enabledRect;\n            goRect.y += EditorGUIUtility.singleLineHeight + EditorGUI.kControlVerticalSpacing;\n\n            Rect functionRect = rect;\n            functionRect.xMin = goRect.xMax + EditorGUI.kSpacing;\n\n            Rect argRect = functionRect;\n            argRect.y += EditorGUIUtility.singleLineHeight + EditorGUI.kControlVerticalSpacing;\n\n            rects[0] = enabledRect;\n            rects[1] = goRect;\n            rects[2] = functionRect;\n            rects[3] = argRect;\n            return rects;\n        }\n\n        protected virtual void OnRemoveEvent(ReorderableList list)\n        {\n            ReorderableList.defaultBehaviours.DoRemoveButton(list);\n            m_LastSelectedIndex = list.index;\n        }\n\n        protected virtual void OnAddEvent(ReorderableList list)\n        {\n            if (m_ListenersArray.hasMultipleDifferentValues)\n            {\n                //When increasing a multi-selection array using Serialized Property\n                //Data can be overwritten if there is mixed values.\n                //The Serialization system applies the Serialized data of one object, to all other objects in the selection.\n                //We handle this case here, by creating a SerializedObject for each object.\n                //Case 639025.\n                foreach (var targetObject in m_ListenersArray.serializedObject.targetObjects)\n                {\n                    using (var temSerialziedObject = new SerializedObject(targetObject))\n                    {\n                        var listenerArrayProperty = temSerialziedObject.FindProperty(m_ListenersArray.propertyPath);\n                        listenerArrayProperty.arraySize += 1;\n                        temSerialziedObject.ApplyModifiedProperties();\n                    }\n                }\n                m_ListenersArray.serializedObject.SetIsDifferentCacheDirty();\n                m_ListenersArray.serializedObject.Update();\n                list.index = list.serializedProperty.arraySize - 1;\n            }\n            else\n            {\n                ReorderableList.defaultBehaviours.DoAddButton(list);\n            }\n\n            m_LastSelectedIndex = list.index;\n            var pListener = m_ListenersArray.GetArrayElementAtIndex(list.index);\n\n            var callState      = pListener.FindPropertyRelative(kCallStatePath);\n            var listenerTarget = pListener.FindPropertyRelative(kInstancePath);\n            var methodName     = pListener.FindPropertyRelative(kMethodNamePath);\n            var mode           = pListener.FindPropertyRelative(kModePath);\n            var arguments      = pListener.FindPropertyRelative(kArgumentsPath);\n\n            callState.enumValueIndex = (int)UnityEventCallState.RuntimeOnly;\n            listenerTarget.objectReferenceValue = null;\n            methodName.stringValue = null;\n            mode.enumValueIndex = (int)PersistentListenerMode.Void;\n            arguments.FindPropertyRelative(kFloatArgument).floatValue = 0;\n            arguments.FindPropertyRelative(kIntArgument).intValue = 0;\n            arguments.FindPropertyRelative(kObjectArgument).objectReferenceValue = null;\n            arguments.FindPropertyRelative(kStringArgument).stringValue = null;\n            arguments.FindPropertyRelative(kObjectArgumentAssemblyTypeName).stringValue = null;\n        }\n\n        protected virtual void OnSelectEvent(ReorderableList list)\n        {\n            m_LastSelectedIndex = list.index;\n        }\n\n        protected virtual void OnReorderEvent(ReorderableList list)\n        {\n            m_LastSelectedIndex = list.index;\n        }\n\n        internal static UnityEventBase GetDummyEvent(SerializedProperty prop)\n        {\n            //Use the SerializedProperty path to iterate through the fields of the inspected targetObject\n            Object tgtobj = prop.serializedObject.targetObject;\n            if (tgtobj == null)\n                return new UnityEvent();\n\n            ScriptAttributeUtility.GetFieldInfoAndStaticTypeFromProperty(prop, out var propType);\n            if (propType.IsSubclassOf(typeof(UnityEventBase)))\n                return Activator.CreateInstance(propType) as UnityEventBase;\n            return new UnityEvent();\n        }\n\n        struct ValidMethodMap\n        {\n            public Object target;\n            public MethodInfo methodInfo;\n            public PersistentListenerMode mode;\n        }\n\n        static IEnumerable<ValidMethodMap> CalculateMethodMap(Object target, Type[] t, bool allowSubclasses)\n        {\n            var validMethods = new List<ValidMethodMap>();\n            if (target == null || t == null)\n                return validMethods;\n\n            // find the methods on the behaviour that match the signature\n            Type componentType = target.GetType();\n            var componentMethods = componentType.GetMethods().Where(x => !x.IsSpecialName).ToList();\n\n            var wantedProperties = componentType.GetProperties().AsEnumerable();\n            wantedProperties = wantedProperties.Where(x => x.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length == 0 && x.GetSetMethod() != null);\n            componentMethods.AddRange(wantedProperties.Select(x => x.GetSetMethod()));\n\n            foreach (var componentMethod in componentMethods)\n            {\n                //Debug.Log (\"Method: \" + componentMethod);\n                // if the argument length is not the same, no match\n                var componentParamaters = componentMethod.GetParameters();\n                if (componentParamaters.Length != t.Length)\n                    continue;\n\n                // Don't show obsolete methods.\n                if (componentMethod.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0)\n                    continue;\n\n                if (componentMethod.ReturnType != typeof(void))\n                    continue;\n\n                // if the argument types do not match, no match\n                bool paramatersMatch = true;\n                for (int i = 0; i < t.Length; i++)\n                {\n                    if (!componentParamaters[i].ParameterType.IsAssignableFrom(t[i]))\n                        paramatersMatch = false;\n\n                    if (allowSubclasses && t[i].IsAssignableFrom(componentParamaters[i].ParameterType))\n                        paramatersMatch = true;\n                }\n\n                // valid method\n                if (paramatersMatch)\n                {\n                    var vmm = new ValidMethodMap\n                    {\n                        target = target,\n                        methodInfo = componentMethod\n                    };\n                    validMethods.Add(vmm);\n                }\n            }\n            return validMethods;\n        }\n\n        public static bool IsPersistantListenerValid(UnityEventBase dummyEvent, string methodName, Object uObject, PersistentListenerMode modeEnum, Type argumentType)\n        {\n            if (uObject == null || string.IsNullOrEmpty(methodName))\n                return false;\n\n            return dummyEvent.FindMethod(methodName, uObject.GetType(), modeEnum, argumentType) != null;\n        }\n\n        internal static GenericMenu BuildPopupList(Object target, UnityEventBase dummyEvent, SerializedProperty listener)\n        {\n            //special case for components... we want all the game objects targets there!\n            var targetToUse = target;\n            if (targetToUse is Component)\n                targetToUse = (target as Component).gameObject;\n\n            // find the current event target...\n            var methodName = listener.FindPropertyRelative(kMethodNamePath);\n\n            var menu = new GenericMenu();\n            menu.AddItem(new GUIContent(kNoFunctionString),\n                string.IsNullOrEmpty(methodName.stringValue),\n                ClearEventFunction,\n                new UnityEventFunction(listener, null, null, PersistentListenerMode.EventDefined));\n\n            if (targetToUse == null)\n                return menu;\n\n            menu.AddSeparator(\"\");\n\n            // figure out the signature of this delegate...\n            // The property at this stage points to the 'container' and has the field name\n            Type delegateType = dummyEvent.GetType();\n\n            // check out the signature of invoke as this is the callback!\n            MethodInfo delegateMethod = delegateType.GetMethod(\"Invoke\");\n            var delegateArgumentsTypes = delegateMethod.GetParameters().Select(x => x.ParameterType).ToArray();\n\n            var duplicateNames = DictionaryPool<string, int>.Get();\n            var duplicateFullNames = DictionaryPool<string, int>.Get();\n\n            GeneratePopUpForType(menu, targetToUse, targetToUse.GetType().Name, listener, delegateArgumentsTypes);\n            duplicateNames[targetToUse.GetType().Name] = 0;\n            if (targetToUse is GameObject)\n            {\n                Component[] comps = (targetToUse as GameObject).GetComponents<Component>();\n\n                // Collect all the names and record how many times the same name is used.\n                foreach (Component comp in comps)\n                {\n                    if (comp == null)\n                        continue;\n\n                    var duplicateIndex = 0;\n                    if (duplicateNames.TryGetValue(comp.GetType().Name, out duplicateIndex))\n                        duplicateIndex++;\n                    duplicateNames[comp.GetType().Name] = duplicateIndex;\n                }\n\n                foreach (Component comp in comps)\n                {\n                    if (comp == null)\n                        continue;\n\n                    var compType = comp.GetType();\n                    string targetName = compType.Name;\n                    int duplicateIndex = 0;\n\n                    // Is this name used multiple times? If so then use the full name plus an index if there are also duplicates of this. (case 1309997)\n                    if (duplicateNames[compType.Name] > 0)\n                    {\n                        if (duplicateFullNames.TryGetValue(compType.FullName, out duplicateIndex))\n                            targetName = $\"{compType.FullName} ({duplicateIndex})\";\n                        else\n                            targetName = compType.FullName;\n                    }\n                    GeneratePopUpForType(menu, comp, targetName, listener, delegateArgumentsTypes);\n                    duplicateFullNames[compType.FullName] = duplicateIndex + 1;\n                }\n\n                DictionaryPool<string, int>.Release(duplicateNames);\n                DictionaryPool<string, int>.Release(duplicateFullNames);\n            }\n            return menu;\n        }\n\n        private static void GeneratePopUpForType(GenericMenu menu, Object target, string targetName, SerializedProperty listener, Type[] delegateArgumentsTypes)\n        {\n            var methods = new List<ValidMethodMap>();\n            bool didAddDynamic = false;\n\n            // skip 'void' event defined on the GUI as we have a void prebuilt type!\n            if (delegateArgumentsTypes.Length != 0)\n            {\n                GetMethodsForTargetAndMode(target, delegateArgumentsTypes, methods, PersistentListenerMode.EventDefined);\n                if (methods.Count > 0)\n                {\n                    menu.AddDisabledItem(new GUIContent(targetName + \"/Dynamic \" + string.Join(\", \", delegateArgumentsTypes.Select(e => GetTypeName(e)).ToArray())));\n                    AddMethodsToMenu(menu, listener, methods, targetName);\n                    didAddDynamic = true;\n                }\n            }\n\n            methods.Clear();\n            GetMethodsForTargetAndMode(target, new[] {typeof(float)}, methods, PersistentListenerMode.Float);\n            GetMethodsForTargetAndMode(target, new[] {typeof(int)}, methods, PersistentListenerMode.Int);\n            GetMethodsForTargetAndMode(target, new[] {typeof(string)}, methods, PersistentListenerMode.String);\n            GetMethodsForTargetAndMode(target, new[] {typeof(bool)}, methods, PersistentListenerMode.Bool);\n            GetMethodsForTargetAndMode(target, new[] {typeof(Object)}, methods, PersistentListenerMode.Object);\n            GetMethodsForTargetAndMode(target, new Type[] {}, methods, PersistentListenerMode.Void);\n            if (methods.Count > 0)\n            {\n                if (didAddDynamic)\n                    // AddSeperator doesn't seem to work for sub-menus, so we have to use this workaround instead of a proper separator for now.\n                    menu.AddItem(new GUIContent(targetName + \"/ \"), false, null);\n                if (delegateArgumentsTypes.Length != 0)\n                    menu.AddDisabledItem(new GUIContent(targetName + \"/Static Parameters\"));\n                AddMethodsToMenu(menu, listener, methods, targetName);\n            }\n        }\n\n        private static void AddMethodsToMenu(GenericMenu menu, SerializedProperty listener, List<ValidMethodMap> methods, string targetName)\n        {\n            // Note: sorting by a bool in OrderBy doesn't seem to work for some reason, so using numbers explicitly.\n            IEnumerable<ValidMethodMap> orderedMethods = methods.OrderBy(e => e.methodInfo.Name.StartsWith(\"set_\") ? 0 : 1).ThenBy(e => e.methodInfo.Name);\n            foreach (var validMethod in orderedMethods)\n                AddFunctionsForScript(menu, listener, validMethod, targetName);\n        }\n\n        private static void GetMethodsForTargetAndMode(Object target, Type[] delegateArgumentsTypes, List<ValidMethodMap> methods, PersistentListenerMode mode)\n        {\n            IEnumerable<ValidMethodMap> newMethods = CalculateMethodMap(target, delegateArgumentsTypes, mode == PersistentListenerMode.Object);\n            foreach (var m in newMethods)\n            {\n                var method = m;\n                method.mode = mode;\n                methods.Add(method);\n            }\n        }\n\n        static void AddFunctionsForScript(GenericMenu menu, SerializedProperty listener, ValidMethodMap method, string targetName)\n        {\n            PersistentListenerMode mode = method.mode;\n\n            // find the current event target...\n            var listenerTarget = listener.FindPropertyRelative(kInstancePath).objectReferenceValue;\n            var methodName = listener.FindPropertyRelative(kMethodNamePath).stringValue;\n            var setMode = GetMode(listener.FindPropertyRelative(kModePath));\n            var typeName = listener.FindPropertyRelative(kArgumentsPath).FindPropertyRelative(kObjectArgumentAssemblyTypeName);\n\n            var args = new StringBuilder();\n            var count = method.methodInfo.GetParameters().Length;\n            for (int index = 0; index < count; index++)\n            {\n                var methodArg = method.methodInfo.GetParameters()[index];\n                args.Append(string.Format(\"{0}\", GetTypeName(methodArg.ParameterType)));\n\n                if (index < count - 1)\n                    args.Append(\", \");\n            }\n\n            var isCurrentlySet = listenerTarget == method.target\n                && methodName == method.methodInfo.Name\n                && mode == setMode;\n\n            if (isCurrentlySet && mode == PersistentListenerMode.Object && method.methodInfo.GetParameters().Length == 1)\n            {\n                isCurrentlySet &= (method.methodInfo.GetParameters()[0].ParameterType.AssemblyQualifiedName == typeName.stringValue);\n            }\n\n            string path = GetFormattedMethodName(targetName, method.methodInfo.Name, args.ToString(), mode == PersistentListenerMode.EventDefined);\n            menu.AddItem(new GUIContent(path),\n                isCurrentlySet,\n                SetEventFunction,\n                new UnityEventFunction(listener, method.target, method.methodInfo, mode));\n        }\n\n        private static string GetTypeName(Type t)\n        {\n            if (t == typeof(int))\n                return \"int\";\n            if (t == typeof(float))\n                return \"float\";\n            if (t == typeof(string))\n                return \"string\";\n            if (t == typeof(bool))\n                return \"bool\";\n            return t.Name;\n        }\n\n        static string GetFormattedMethodName(string targetName, string methodName, string args, bool dynamic)\n        {\n            if (dynamic)\n            {\n                if (methodName.StartsWith(\"set_\"))\n                    return string.Format(\"{0}/{1}\", targetName, methodName.Substring(4));\n                else\n                    return string.Format(\"{0}/{1}\", targetName, methodName);\n            }\n            else\n            {\n                if (methodName.StartsWith(\"set_\"))\n                    return string.Format(\"{0}/{2} {1}\", targetName, methodName.Substring(4), args);\n                else\n                    return string.Format(\"{0}/{1} ({2})\", targetName, methodName, args);\n            }\n        }\n\n        static void SetEventFunction(object source)\n        {\n            ((UnityEventFunction)source).Assign();\n        }\n\n        static void ClearEventFunction(object source)\n        {\n            ((UnityEventFunction)source).Clear();\n        }\n\n        struct UnityEventFunction\n        {\n            readonly SerializedProperty m_Listener;\n            readonly Object m_Target;\n            readonly MethodInfo m_Method;\n            readonly PersistentListenerMode m_Mode;\n\n            public UnityEventFunction(SerializedProperty listener, Object target, MethodInfo method, PersistentListenerMode mode)\n            {\n                m_Listener = listener;\n                m_Target = target;\n                m_Method = method;\n                m_Mode = mode;\n            }\n\n            public void Assign()\n            {\n                // find the current event target...\n                var listenerTarget = m_Listener.FindPropertyRelative(kInstancePath);\n                var listenerTargetType = m_Listener.FindPropertyRelative(kInstanceTypePath);\n                var methodName = m_Listener.FindPropertyRelative(kMethodNamePath);\n                var mode = m_Listener.FindPropertyRelative(kModePath);\n                var arguments = m_Listener.FindPropertyRelative(kArgumentsPath);\n\n                listenerTarget.objectReferenceValue = m_Target;\n                listenerTargetType.stringValue = m_Method.DeclaringType.AssemblyQualifiedName;\n                methodName.stringValue = m_Method.Name;\n                mode.enumValueIndex = (int)m_Mode;\n\n                if (m_Mode == PersistentListenerMode.Object)\n                {\n                    var fullArgumentType = arguments.FindPropertyRelative(kObjectArgumentAssemblyTypeName);\n                    var argParams = m_Method.GetParameters();\n                    if (argParams.Length == 1 && typeof(Object).IsAssignableFrom(argParams[0].ParameterType))\n                        fullArgumentType.stringValue = argParams[0].ParameterType.AssemblyQualifiedName;\n                    else\n                        fullArgumentType.stringValue = typeof(Object).AssemblyQualifiedName;\n                }\n\n                ValidateObjectParamater(arguments, m_Mode);\n\n                m_Listener.m_SerializedObject.ApplyModifiedProperties();\n            }\n\n            private void ValidateObjectParamater(SerializedProperty arguments, PersistentListenerMode mode)\n            {\n                var fullArgumentType = arguments.FindPropertyRelative(kObjectArgumentAssemblyTypeName);\n                var argument = arguments.FindPropertyRelative(kObjectArgument);\n                var argumentObj = argument.objectReferenceValue;\n\n                if (mode != PersistentListenerMode.Object)\n                {\n                    fullArgumentType.stringValue = typeof(Object).AssemblyQualifiedName;\n                    argument.objectReferenceValue = null;\n                    return;\n                }\n\n                if (argumentObj == null)\n                    return;\n\n                Type t = Type.GetType(fullArgumentType.stringValue, false);\n                if (!typeof(Object).IsAssignableFrom(t) || !t.IsInstanceOfType(argumentObj))\n                    argument.objectReferenceValue = null;\n            }\n\n            public void Clear()\n            {\n                // find the current event target...\n                var methodName = m_Listener.FindPropertyRelative(kMethodNamePath);\n                methodName.stringValue = null;\n\n                var mode = m_Listener.FindPropertyRelative(kModePath);\n                mode.enumValueIndex = (int)PersistentListenerMode.Void;\n\n                m_Listener.m_SerializedObject.ApplyModifiedProperties();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/VersionControlSettingsInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing UnityEditor.VersionControl;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(VersionControlSettings))]\n    internal class VersionControlSettingsProvider : ProjectSettingsBaseEditor\n    {\n        class Styles\n        {\n            public static GUIContent mode = new GUIContent(\"Mode\");\n            public static GUIContent logLevel = new GUIContent(\"Log Level\");\n            public static GUIContent automaticAdd = new GUIContent(\"Automatic Add\",\n                \"Automatically add newly created assets to version control.\");\n            public static GUIContent scanLocalPackagesOnConnect = new GUIContent(\"Scan Local Packages on Connect\",\n                \"Scan local packages during the version control initialization to automatically add newly created assets to source control.\");\n            public static GUIContent smartMerge = new GUIContent(\"Smart merge\");\n            public static GUIContent trackPackagesOutsideProject = new GUIContent(\"Version Packages Outside Project\", \"Tracks changes to packages that reside on disk outside of the project's root folder.\");\n            public static GUIContent vcsConnect = new GUIContent(\"Connect\");\n            public static GUIContent vcsReconnect = new GUIContent(\"Reconnect\");\n            public static GUIContent workOffline = new GUIContent(\"Work Offline\",\n                \"Enable asset modifications even when not connected to a version control server. Requires manual integration into VCS system afterwards.\");\n            public static GUIContent allowAsyncUpdate = new GUIContent(\"Async Status\",\n                \"Enable asynchronous file status queries (useful with slow server connections).\");\n            public static GUIContent showFailedCheckouts = new GUIContent(\"Show Failed Checkouts\",\n                \"Show dialogs for failed 'Check Out' operations.\");\n            public static GUIContent overwriteFailedCheckoutAssets =\n                new GUIContent(\"Overwrite Failed Checkout Assets\",\n                    \"When on, assets that can not be checked out will get saved anyway.\");\n            public static GUIContent overlayIcons = new GUIContent(\"Overlay Icons\",\n                \"Should version control status icons be shown.\");\n            public static GUIContent projectOverlayIcons = new GUIContent(\"Project Window\",\n                \"Should version control status icons be shown in the Project window.\");\n            public static GUIContent hierarchyOverlayIcons = new GUIContent(\"Hierarchy Window\",\n                \"Should version control status icons be shown in the Hierarchy window.\");\n            public static GUIContent otherOverlayIcons = new GUIContent(\"Other Windows\",\n                \"Should version control status icons be shown in other windows.\");\n\n            // these are required to have correct search keywords\n            public static GUIContent password = new GUIContent(\"Password\");\n            public static GUIContent username = new GUIContent(\"Username\");\n            public static GUIContent server = new GUIContent(\"Server\");\n        }\n\n        const int kVCFieldRecentCount = 10;\n        const string kVCFieldRecentPrefix = \"vcs_ConfigField\";\n        Dictionary<string, string[]> m_VCConfigFieldsRecentValues = new Dictionary<string, string[]>();\n\n        bool m_NeedToSaveValuesOnConnect;\n\n        private string[] logLevelPopupList =\n        {\n            \"Verbose\", \"Info\", \"Notice\", \"Fatal\"\n        };\n\n        private string[] semanticMergePopupList =\n        {\n            \"Off\", \"Premerge\", \"Ask\"\n        };\n\n        private EditorSettingsInspector.PopupElement[] vcDefaultPopupList =\n        {\n            new EditorSettingsInspector.PopupElement(ExternalVersionControl.Disabled),\n            new EditorSettingsInspector.PopupElement(ExternalVersionControl.Generic),\n        };\n\n        private EditorSettingsInspector.PopupElement[] vcPopupList = null;\n\n        void DrawOverlayDescriptions()\n        {\n            Texture2D atlas = Provider.overlayAtlas;\n            if (atlas == null)\n                return;\n\n            GUILayout.BeginHorizontal();\n            GUILayout.BeginVertical();\n            DrawOverlayDescription(Asset.States.Local);\n            DrawOverlayDescription(Asset.States.OutOfSync);\n            DrawOverlayDescription(Asset.States.CheckedOutLocal);\n            DrawOverlayDescription(Asset.States.CheckedOutRemote);\n            GUILayout.EndVertical();\n            GUILayout.BeginVertical();\n            DrawOverlayDescription(Asset.States.DeletedLocal);\n            DrawOverlayDescription(Asset.States.DeletedRemote);\n            DrawOverlayDescription(Asset.States.AddedLocal);\n            DrawOverlayDescription(Asset.States.AddedRemote);\n            GUILayout.EndVertical();\n            GUILayout.BeginVertical();\n            DrawOverlayDescription(Asset.States.Conflicted);\n            DrawOverlayDescription(Asset.States.LockedLocal);\n            DrawOverlayDescription(Asset.States.LockedRemote);\n            DrawOverlayDescription(Asset.States.Updating);\n            GUILayout.EndVertical();\n            GUILayout.EndHorizontal();\n        }\n\n        void DrawOverlayDescription(Asset.States state)\n        {\n            Rect atlasUV = Provider.GetAtlasRectForState((int)state);\n            if (atlasUV.width == 0f)\n                return; // no overlay\n\n            Texture2D atlas = Provider.overlayAtlas;\n            if (atlas == null)\n                return;\n\n            GUILayout.Label(\"    \" + Asset.StateToString(state), EditorStyles.miniLabel);\n            Rect r = GUILayoutUtility.GetLastRect();\n            r.width = r.height;\n            GUI.DrawTextureWithTexCoords(r, atlas, atlasUV);\n        }\n\n        private void CreatePopupMenuVersionControl(string title, EditorSettingsInspector.PopupElement[] elements, string selectedValue,\n            GenericMenu.MenuFunction2 func)\n        {\n            var selectedIndex = Array.FindIndex(elements, e => e.id == selectedValue);\n            if (selectedIndex == -1)\n                selectedIndex = Array.FindIndex(elements, e => e.id == ExternalVersionControl.Generic);\n            var content = new GUIContent(elements[selectedIndex].content);\n            EditorSettingsInspector.CreatePopupMenu(null, new GUIContent(title), content, elements, selectedIndex, func);\n        }\n\n        private void SetVersionControlSystem(object data)\n        {\n            int popupIndex = (int)data;\n            if (popupIndex < 0 || popupIndex >= vcPopupList.Length)\n                return;\n\n            EditorSettingsInspector.PopupElement el = vcPopupList[popupIndex];\n            string oldVC = VersionControlSettings.mode;\n\n            VersionControlSettings.mode = el.id;\n            Provider.UpdateSettings();\n            AssetDatabase.Refresh();\n\n            if (oldVC != el.id)\n            {\n                if (el.content.text == ExternalVersionControl.Disabled ||\n                    el.content.text == ExternalVersionControl.Generic\n                )\n                {\n                    // Close the normal version control window\n                    WindowPending.CloseAllWindows();\n                }\n            }\n        }\n\n        private bool VersionControlSystemHasGUI()\n        {\n            ExternalVersionControl system = VersionControlSettings.mode;\n            return\n                system != ExternalVersionControl.Disabled &&\n                system != ExternalVersionControl.AutoDetect &&\n                system != ExternalVersionControl.Generic;\n        }\n\n        string[] GetVCConfigFieldRecentValues(string fieldName)\n        {\n            if (m_VCConfigFieldsRecentValues.ContainsKey(fieldName))\n                return m_VCConfigFieldsRecentValues[fieldName];\n\n            var res = new List<string>();\n            for (var i = 0; i < kVCFieldRecentCount; ++i)\n            {\n                var prefName = $\"{kVCFieldRecentPrefix}{fieldName}{i}\";\n                var prefValue = EditorPrefs.GetString(prefName);\n                if (!string.IsNullOrEmpty(prefValue))\n                    res.Add(prefValue);\n            }\n\n            var arr = res.ToArray();\n            m_VCConfigFieldsRecentValues[fieldName] = arr;\n            return arr;\n        }\n\n        void UpdateVCConfigFieldRecentValues(ConfigField[] fields)\n        {\n            if (fields == null)\n                return;\n            foreach (var field in fields)\n            {\n                if (field.isPassword)\n                    continue;\n                var val = EditorUserSettings.GetConfigValue(field.name);\n                if (string.IsNullOrEmpty(val))\n                    continue;\n                UpdateVCConfigFieldRecentValue(field.name, val);\n            }\n        }\n\n        void UpdateVCConfigFieldRecentValue(string fieldName, string value)\n        {\n            if (string.IsNullOrEmpty(value))\n                return;\n            var arr = GetVCConfigFieldRecentValues(fieldName);\n            var newVal = new[] {value};\n            // put newly used value in front\n            arr = newVal.Concat(arr.Except(newVal)).Take(kVCFieldRecentCount).ToArray();\n            m_VCConfigFieldsRecentValues[fieldName] = arr;\n\n            for (var i = 0; i < arr.Length; ++i)\n            {\n                var prefName = $\"{kVCFieldRecentPrefix}{fieldName}{i}\";\n                EditorPrefs.SetString(prefName, arr[i]);\n            }\n        }\n\n        public void OnEnable()\n        {\n            IEnumerable<Plugin> availvc = Plugin.availablePlugins;\n\n            var popupArray = new List<EditorSettingsInspector.PopupElement>(vcDefaultPopupList);\n            var descriptors = VersionControlManager.versionControlDescriptors;\n            popupArray.AddRange(descriptors.OrderBy(d => d.displayName).Select(d => new EditorSettingsInspector.PopupElement(d.name, d.displayName)));\n            availvc = availvc.Where(p => !descriptors.Any(d => string.Equals(d.name, p.name, StringComparison.Ordinal)));\n            foreach (var plugin in availvc)\n            {\n                popupArray.Add(new EditorSettingsInspector.PopupElement(plugin.name));\n            }\n\n            vcPopupList = popupArray.ToArray();\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            GUILayout.Space(10);\n            GUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);\n\n            using (new EditorGUI.DisabledScope(true))\n            {\n                GUI.enabled = true;\n\n                ExternalVersionControl selvc = VersionControlSettings.mode;\n                CreatePopupMenuVersionControl(Styles.mode.text, vcPopupList, selvc, SetVersionControlSystem);\n                GUI.enabled = true;\n            }\n\n            GUI.enabled = true;\n            ConfigField[] configFields = null;\n\n            var versionControlSystemHasGUI = VersionControlSystemHasGUI();\n            var vco = versionControlSystemHasGUI ? VersionControlManager.activeVersionControlObject : null;\n            if (vco != null)\n            {\n                vco.GetExtension<ISettingsInspectorExtension>()?.OnInspectorGUI();\n            }\n            else if (versionControlSystemHasGUI)\n            {\n                bool hasRequiredFields = false;\n\n                if (VersionControlSettings.mode == ExternalVersionControl.Generic ||\n                    VersionControlSettings.mode == ExternalVersionControl.Disabled)\n                {\n                    // no specific UI for these VCS types\n                }\n                else\n                {\n                    configFields = Provider.GetActiveConfigFields();\n\n                    hasRequiredFields = true;\n\n                    foreach (ConfigField field in configFields)\n                    {\n                        string newVal;\n                        string oldVal = EditorUserSettings.GetConfigValue(field.name);\n                        if (field.isPassword)\n                        {\n                            newVal = EditorGUILayout.PasswordField(GUIContent.Temp(field.label, field.description),\n                                oldVal);\n                            if (newVal != oldVal)\n                                EditorUserSettings.SetPrivateConfigValue(field.name, newVal);\n                        }\n                        else\n                        {\n                            var recentValues = GetVCConfigFieldRecentValues(field.name);\n                            newVal = EditorGUILayout.TextFieldDropDown(GUIContent.Temp(field.label, field.description),\n                                oldVal, recentValues);\n                            if (newVal != oldVal)\n                                EditorUserSettings.SetConfigValue(field.name, newVal);\n                        }\n\n                        if (field.isRequired && string.IsNullOrEmpty(newVal))\n                            hasRequiredFields = false;\n                    }\n                }\n\n                // Log level popup\n                string logLevel = EditorUserSettings.GetConfigValue(\"vcSharedLogLevel\");\n                int idx = System.Array.FindIndex(logLevelPopupList, (item) => item.ToLower() == logLevel);\n                if (idx == -1)\n                {\n                    logLevel = \"notice\";\n                    idx = System.Array.FindIndex(logLevelPopupList, (item) => item.ToLower() == logLevel);\n                    if (idx == -1)\n                    {\n                        idx = 0;\n                    }\n\n                    logLevel = logLevelPopupList[idx];\n                    EditorUserSettings.SetConfigValue(\"vcSharedLogLevel\", logLevel);\n                }\n\n                int newIdx = EditorGUILayout.Popup(Styles.logLevel, idx, logLevelPopupList);\n                if (newIdx != idx)\n                {\n                    EditorUserSettings.SetConfigValue(\"vcSharedLogLevel\", logLevelPopupList[newIdx].ToLower());\n                }\n\n                if (Provider.onlineState == OnlineState.Offline)\n                {\n                    var text = \"Not Connected. \" + (Provider.offlineReason ?? \"\");\n                    EditorGUILayout.HelpBox(text, MessageType.Error);\n                }\n                else if (Provider.onlineState == OnlineState.Updating)\n                {\n                    var text = \"Connecting...\";\n                    EditorGUILayout.HelpBox(text, MessageType.Info);\n                }\n                else if (EditorUserSettings.WorkOffline)\n                {\n                    var text =\n                        \"Working Offline. Manually integrate your changes using a version control client, and uncheck 'Work Offline' setting below to get back to regular state.\";\n                    EditorGUILayout.HelpBox(text, MessageType.Warning);\n                }\n                else if (Provider.onlineState == OnlineState.Online)\n                {\n                    var text = \"Connected\";\n                    EditorGUILayout.HelpBox(text, MessageType.Info);\n                }\n\n                GUILayout.BeginHorizontal();\n                GUILayout.FlexibleSpace();\n                GUI.enabled = hasRequiredFields && Provider.onlineState != OnlineState.Updating;\n                if (GUILayout.Button(\n                    Provider.onlineState != OnlineState.Offline ? Styles.vcsReconnect : Styles.vcsConnect,\n                    EditorStyles.miniButton))\n                {\n                    m_NeedToSaveValuesOnConnect = true;\n                    Provider.UpdateSettings();\n                }\n\n                GUILayout.EndHorizontal();\n\n                if (m_NeedToSaveValuesOnConnect && Provider.onlineState == OnlineState.Online)\n                {\n                    // save connection field settings if we got online with them successfully\n                    m_NeedToSaveValuesOnConnect = false;\n                    UpdateVCConfigFieldRecentValues(configFields);\n                }\n\n                if (Provider.requiresNetwork)\n                {\n                    bool workOfflineNew =\n                        EditorGUILayout.Toggle(Styles.workOffline,\n                            EditorUserSettings.WorkOffline); // Enabled has a slightly different behaviour\n                    if (workOfflineNew != EditorUserSettings.WorkOffline)\n                    {\n                        // On toggling on show a warning\n                        if (workOfflineNew && !EditorUtility.DisplayDialog(\"Confirm working offline\",\n                            \"Working offline and making changes to your assets means that you will have to manually integrate changes back into version control using your standard version control client before you stop working offline in Unity. Make sure you know what you are doing.\",\n                            \"Work offline\", \"Cancel\"))\n                        {\n                            workOfflineNew = false; // User cancelled working offline\n                        }\n\n                        EditorUserSettings.WorkOffline = workOfflineNew;\n                        EditorApplication.RequestRepaintAllViews();\n                    }\n                }\n\n                EditorUserSettings.AutomaticAdd =\n                    EditorGUILayout.Toggle(Styles.automaticAdd, EditorUserSettings.AutomaticAdd);\n\n                EditorUserSettings.scanLocalPackagesOnConnect =\n                    EditorGUILayout.Toggle(Styles.scanLocalPackagesOnConnect, EditorUserSettings.scanLocalPackagesOnConnect);\n\n                if (Provider.requiresNetwork)\n                    EditorUserSettings.allowAsyncStatusUpdate = EditorGUILayout.Toggle(Styles.allowAsyncUpdate,\n                        EditorUserSettings.allowAsyncStatusUpdate);\n\n                if (Provider.hasCheckoutSupport)\n                {\n                    EditorUserSettings.showFailedCheckout = EditorGUILayout.Toggle(Styles.showFailedCheckouts,\n                        EditorUserSettings.showFailedCheckout);\n                    EditorUserSettings.overwriteFailedCheckoutAssets = EditorGUILayout.Toggle(\n                        Styles.overwriteFailedCheckoutAssets, EditorUserSettings.overwriteFailedCheckoutAssets);\n                }\n\n                EditorUserSettings.semanticMergeMode = (SemanticMergeMode)EditorGUILayout.Popup(Styles.smartMerge,\n                    (int)EditorUserSettings.semanticMergeMode, semanticMergePopupList);\n\n                VersionControlSettings.trackPackagesOutsideProject =\n                EditorGUILayout.Toggle(Styles.trackPackagesOutsideProject, VersionControlSettings.trackPackagesOutsideProject);\n\n                GUILayout.Space(10);\n                GUILayout.Label(Styles.overlayIcons);\n\n                EditorGUI.indentLevel++;\n                var newProjectOverlayIcons = EditorGUILayout.Toggle(Styles.projectOverlayIcons, EditorUserSettings.overlayIcons);\n                if (newProjectOverlayIcons != EditorUserSettings.overlayIcons)\n                {\n                    EditorUserSettings.overlayIcons = newProjectOverlayIcons;\n                    EditorApplication.RequestRepaintAllViews();\n                }\n\n                var newHierarchyOverlayIcons = EditorGUILayout.Toggle(Styles.hierarchyOverlayIcons, EditorUserSettings.hierarchyOverlayIcons);\n                if (newHierarchyOverlayIcons != EditorUserSettings.hierarchyOverlayIcons)\n                {\n                    EditorUserSettings.hierarchyOverlayIcons = newHierarchyOverlayIcons;\n                    EditorApplication.RequestRepaintAllViews();\n                }\n\n                var newOtherOverlayIcons = EditorGUILayout.Toggle(Styles.otherOverlayIcons, EditorUserSettings.otherOverlayIcons);\n                if (newOtherOverlayIcons != EditorUserSettings.otherOverlayIcons)\n                {\n                    EditorUserSettings.otherOverlayIcons = newOtherOverlayIcons;\n                    EditorApplication.RequestRepaintAllViews();\n                }\n                EditorGUI.indentLevel--;\n                GUILayout.Space(10);\n\n                GUI.enabled = true;\n                if (newProjectOverlayIcons || newHierarchyOverlayIcons || newOtherOverlayIcons)\n                    DrawOverlayDescriptions();\n            }\n            GUILayout.EndVertical();\n        }\n\n        [SettingsProvider]\n        internal static SettingsProvider CreateProjectSettingsProvider()\n        {\n            var provider = AssetSettingsProvider.CreateProviderFromAssetPath(\n                \"Project/Version Control\", \"ProjectSettings/VersionControlSettings.asset\",\n                SettingsProvider.GetSearchKeywordsFromGUIContentProperties<Styles>());\n            return provider;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/VisualElements/ClippingPlanes.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.UIElements;\nusing UnityEngine.UIElements;\nusing System;\nusing System.Diagnostics;\n\nnamespace UnityEditor.Inspector\n{\n    internal class ClippingPlanes : BaseCompositeField<Vector2, FloatField, float>\n    {\n        [Serializable]\n        public new class UxmlSerializedData : BaseCompositeField<Vector2, FloatField, float>.UxmlSerializedData\n        {\n            [RegisterUxmlCache]\n            [Conditional(\"UNITY_EDITOR\")]\n            public new static void Register()\n            {\n                BaseCompositeField<Vector2, FloatField, float>.UxmlSerializedData.Register();\n            }\n\n            public override object CreateInstance() => new ClippingPlanes();\n        }\n\n        const string k_CompositeInputStyle = \"unity-composite-field__input\";\n        const string k_CompositeFieldStyle = \"unity-composite-field__field\";\n        const string k_NearClipStyle = \"unity-near-clip-input\";\n        const string k_FarClipStyle = \"unity-far-clip-input\";\n        const float k_NearFarLabelsWidth = EditorGUI.kNearFarLabelsWidth;\n\n        bool m_DirtyX;\n        bool m_DirtyY;\n\n        readonly SerializedProperty[] m_Properties = new SerializedProperty[2];\n\n        public SerializedProperty nearClip\n        {\n            get => m_Properties[0];\n            set\n            {\n                m_Properties[0] = value;\n                MockPropertyField(fields[0], EditorGUI.s_NearAndFarLabels[0], m_Properties[0]);\n                Update();\n            }\n        }\n        public SerializedProperty farClip\n        {\n            get => m_Properties[1];\n            set\n            {\n                m_Properties[1] = value;\n                MockPropertyField(fields[1], EditorGUI.s_NearAndFarLabels[1], m_Properties[1]);\n                Update();\n            }\n        }\n\n        internal override FieldDescription[] DescribeFields() => new[]\n        {\n                new FieldDescription(\"Near\", k_NearClipStyle, r => r.x, (ref Vector2 r, float v) =>\n                {\n                    r.x = v;\n                    m_DirtyX = true;\n                }),\n                new FieldDescription(\"Far\", k_FarClipStyle, r => r.y, (ref Vector2 r, float v) =>\n                {\n                    r.y = v;\n                    m_DirtyY = true;\n                }),\n            };\n\n        public ClippingPlanes() : base(labelProperty, 2)\n        {\n            AddToClassList(BaseField<bool>.alignedFieldUssClassName);\n\n            RegisterCallback<AttachToPanelEvent>(e =>\n            {\n                e.elementTarget.Q(className: k_CompositeInputStyle)?.RemoveFromClassList(k_CompositeInputStyle);\n\n                foreach (var field in fields)\n                {\n                    field.RemoveFromClassList(k_CompositeFieldStyle);\n                    field.RemoveFromClassList(BaseField<bool>.alignedFieldUssClassName);\n                    field.style.marginLeft = field.style.marginRight = 0;\n                    field.isDelayed = true;\n\n                    var label = field.Q<Label>();\n                    label.style.flexBasis = label.style.minWidth = new StyleLength(k_NearFarLabelsWidth);\n                    label.style.marginLeft = label.style.marginRight = 0;\n                }\n            });\n            RegisterCallback<ChangeEvent<Vector2>>(e =>\n            {\n                if (m_DirtyX)\n                {\n                    m_Properties[0].floatValue = e.newValue.x;\n                    m_Properties[0].serializedObject.ApplyModifiedProperties();\n                }\n\n                if (m_DirtyY)\n                {\n                    m_Properties[1].floatValue = e.newValue.y;\n                    m_Properties[1].serializedObject.ApplyModifiedProperties();\n                }\n\n                m_DirtyX = m_DirtyY = false;\n            });\n        }\n\n        public void Update()\n        {\n            value = new Vector2(m_Properties[0]?.floatValue ?? default, m_Properties[1]?.floatValue ?? default);\n\n            if (m_Properties[0] != null)\n                fields[0]?.schedule.Execute(() => BindingsStyleHelpers.UpdateElementStyle(fields[0], m_Properties[0]));\n\n            if (m_Properties[1] != null)\n                fields[1]?.schedule.Execute(() => BindingsStyleHelpers.UpdateElementStyle(fields[1], m_Properties[1]));\n        }\n\n        static BaseField<TValue> MockPropertyField<TValue>(BaseField<TValue> field, GUIContent content, SerializedProperty property)\n        {\n            field.label = content.text;\n            field.tooltip = content.tooltip;\n            field.AddToClassList(BaseField<bool>.alignedFieldUssClassName);\n            BindingsStyleHelpers.RegisterRightClickMenu(field, property);\n            return field;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/VisualElements/MinMaxGradientField.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.UIElements\n{\n    internal class MinMaxGradientField : BaseField<ParticleSystem.MinMaxGradient>\n    {\n        [Obsolete(\"UxmlFactory is deprecated and will be removed. Use UxmlElementAttribute instead.\", false)]\n        protected new class UxmlFactory : UxmlFactory<MinMaxGradientField, UxmlTraits> { }\n\n        public new static readonly string ussClassName = \"unity-min-max-gradient-field\";\n        public static readonly string visualInputUssClass = ussClassName + \"__visual-input\";\n        public static readonly string dropdownFieldUssClass = ussClassName + \"__dropdown-field\";\n        public static readonly string dropdownInputUssClass = ussClassName + \"__dropdown-input\";\n        public static readonly string gradientContainerUssClass = ussClassName + \"__gradient-container\";\n        public static readonly string colorFieldUssClass = ussClassName + \"__color-field\";\n        public static readonly string multipleValuesLabelUssClass = ussClassName + \"__multiple-values-label\";\n\n        /// <summary>\n        /// Defines <see cref=\"UxmlTraits\"/> for the <see cref=\"MinMaxGradientField\"/>.\n        /// </summary>\n        /// <remarks>\n        /// This class defines the properties of a MinMaxGradientField element that you can\n        /// use in a UXML asset.\n        /// </remarks>\n        [Obsolete(\"UxmlTraits is deprecated and will be removed. Use UxmlElementAttribute instead.\", false)]\n        protected new class UxmlTraits : BaseField<ParticleSystem.MinMaxGradient>.UxmlTraits {}\n\n        public readonly string[] stringModes = new[]\n        {\n            L10n.Tr(\"Color\"),\n            L10n.Tr(\"Gradient\"),\n            L10n.Tr(\"Random Between Two Colors\"),\n            L10n.Tr(\"Random Between Two Gradients\"),\n            L10n.Tr(\"Random Color\")\n        };\n\n        PropertyField m_ColorMin;\n        PropertyField m_ColorMax;\n        PropertyField m_GradientMin;\n        PropertyField m_GradientMax;\n        DropdownField m_ModeDropdown;\n        VisualElement m_GradientsContainer;\n        Label m_MixedValueTypeLabel;\n\n        public MinMaxGradientField()\n            : this(null, null) { }\n\n        public MinMaxGradientField(MinMaxGradientPropertyDrawer.PropertyData propertyData, string label) : base(label, null)\n        {\n            if (propertyData != null)\n            {\n                m_ColorMin = new PropertyField(propertyData.colorMin, \"\");\n                m_ColorMin.AddToClassList(colorFieldUssClass);\n                m_ColorMax = new PropertyField(propertyData.colorMax, \"\");\n                m_ColorMax.AddToClassList(colorFieldUssClass);\n                m_GradientMin = new PropertyField(propertyData.gradientMin, \"\");\n                m_GradientMax = new PropertyField(propertyData.gradientMax, \"\");\n                m_ModeDropdown = new DropdownField\n                {\n                    choices = stringModes.ToList()\n                };\n                m_ModeDropdown.createMenuCallback = () =>\n                {\n                    var osMenu = new GenericOSMenu();\n\n                    for (int i = 0; i < stringModes.Length; i++)\n                    {\n                        var option = stringModes[i];\n                        var isValueSelected = propertyData.mode.intValue == i;\n\n                        osMenu.AddItem(option, isValueSelected, () =>\n                        {\n                            m_ModeDropdown.value = option;\n                        });\n                    }\n\n                    return osMenu;\n                };\n                m_ModeDropdown.formatSelectedValueCallback = (value) =>\n                {\n                    // Don't show label for this dropdown\n                    return \"\";\n                };\n\n                m_ModeDropdown.index = propertyData.mode.intValue;\n                m_ModeDropdown.AddToClassList(dropdownFieldUssClass);\n                m_MixedValueTypeLabel = new Label(\"\\u2014\");\n                m_MixedValueTypeLabel.AddToClassList(multipleValuesLabelUssClass);\n\n                var dropdownInput = m_ModeDropdown.Q<VisualElement>(null, \"unity-popup-field__input\");\n                dropdownInput.AddToClassList(dropdownInputUssClass);\n\n                m_GradientsContainer = new VisualElement();\n                m_GradientsContainer.AddToClassList(gradientContainerUssClass);\n                m_GradientsContainer.Add(m_GradientMin);\n                m_GradientsContainer.Add(m_GradientMax);\n\n                visualInput.AddToClassList(visualInputUssClass);\n                visualInput.Add(m_ColorMin);\n                visualInput.Add(m_ColorMax);\n                visualInput.Add(m_GradientsContainer);\n                visualInput.Add(m_MixedValueTypeLabel);\n                visualInput.Add(m_ModeDropdown);\n\n                m_ModeDropdown.RegisterCallback<ChangeEvent<string>>(e =>\n                {\n                    var index = Array.IndexOf(stringModes, e.newValue);\n                    var mode = (MinMaxGradientState)index;\n\n                    propertyData.mode.intValue = index;\n                    propertyData.mode.serializedObject.ApplyModifiedProperties();\n                    UpdateFieldsDisplay(propertyData.mode);\n                });\n\n                UpdateFieldsDisplay(propertyData.mode);\n            }\n        }\n\n        private void UpdateFieldsDisplay(SerializedProperty mode)\n        {\n            var hasMixedValues = mode.hasMultipleDifferentValues;\n\n            m_ColorMin.style.display = DisplayStyle.None;\n            m_ColorMax.style.display = DisplayStyle.None;\n            m_GradientMin.style.display = DisplayStyle.None;\n            m_GradientMax.style.display = DisplayStyle.None;\n            m_GradientsContainer.style.display = DisplayStyle.None;\n            m_MixedValueTypeLabel.style.display = hasMixedValues ? DisplayStyle.Flex : DisplayStyle.None;\n\n            if (hasMixedValues)\n            {\n                return;\n            }\n\n            var modeValue = (MinMaxGradientState)mode.intValue;\n\n            switch (modeValue)\n            {\n                case MinMaxGradientState.k_Color:\n                    m_ColorMax.style.display = DisplayStyle.Flex;\n                    break;\n                case MinMaxGradientState.k_Gradient:\n                case MinMaxGradientState.k_RandomColor:\n                    m_GradientsContainer.style.display = DisplayStyle.Flex;\n                    m_GradientMax.style.display = DisplayStyle.Flex;\n                    break;\n                case MinMaxGradientState.k_RandomBetweenTwoColors:\n                    m_ColorMin.style.display = DisplayStyle.Flex;\n                    m_ColorMax.style.display = DisplayStyle.Flex;\n                    break;\n                case MinMaxGradientState.k_RandomBetweenTwoGradients:\n                    m_GradientsContainer.style.display = DisplayStyle.Flex;\n                    m_GradientMin.style.display = DisplayStyle.Flex;\n                    m_GradientMax.style.display = DisplayStyle.Flex;\n                    break;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/VisualElements/ObjectFieldWithPrompt.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Diagnostics;\nusing System.Text;\nusing Unity.Properties;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor.UIElements\n{\n    internal class ObjectFieldWithPrompt : BaseField<Object>\n    {\n        static readonly BindingId titleProperty = nameof(title);\n        static readonly BindingId messageProperty = nameof(message);\n        static readonly BindingId objectTypeProperty = nameof(objectType);\n        static readonly BindingId allowSceneObjectsProperty = nameof(allowSceneObjects);\n\n        [UnityEngine.Internal.ExcludeFromDocs, Serializable]\n        public new class UxmlSerializedData : BaseField<Object>.UxmlSerializedData\n        {\n            [RegisterUxmlCache]\n            [Conditional(\"UNITY_EDITOR\")]\n            public new static void Register()\n            {\n                BaseField<Object>.UxmlSerializedData.Register();\n                UxmlDescriptionCache.RegisterType(typeof(UxmlSerializedData), new UxmlAttributeNames[]\n                {\n                    new (nameof(allowSceneObjects), \"allow-scene-objects\"),\n                    new (nameof(objectType), \"type\", typeof(Object)),\n                    new (nameof(title), \"title\"),\n                    new (nameof(message), \"message\"),\n                });\n            }\n\n            #pragma warning disable 649\n            [SerializeField] bool allowSceneObjects;\n            [SerializeField, UxmlIgnore, HideInInspector] UxmlAttributeFlags allowSceneObjects_UxmlAttributeFlags;\n            [UxmlAttribute(\"type\"), UxmlTypeReference(typeof(Object))]\n            [SerializeField] string objectType;\n            [SerializeField, UxmlIgnore, HideInInspector] UxmlAttributeFlags objectType_UxmlAttributeFlags;\n            [SerializeField] string title;\n            [SerializeField, UxmlIgnore, HideInInspector] UxmlAttributeFlags title_UxmlAttributeFlags;\n            [SerializeField] string message;\n            [SerializeField, UxmlIgnore, HideInInspector] UxmlAttributeFlags message_UxmlAttributeFlags;\n            #pragma warning restore 649\n            public override object CreateInstance() => new ObjectFieldWithPrompt();\n\n            public override void Deserialize(object obj)\n            {\n                base.Deserialize(obj);\n\n                var e = (ObjectFieldWithPrompt)obj;\n                if (ShouldWriteAttributeValue(allowSceneObjects_UxmlAttributeFlags))\n                    e.allowSceneObjects = allowSceneObjects;\n                if (ShouldWriteAttributeValue(objectType_UxmlAttributeFlags))\n                    e.objectType = UxmlUtility.ParseType(objectType, typeof(Object));\n                if (ShouldWriteAttributeValue(title_UxmlAttributeFlags))\n                    e.title = title;\n                if (ShouldWriteAttributeValue(message_UxmlAttributeFlags))\n                    e.message = message;\n            }\n        }\n\n        string m_Title;\n\n        [CreateProperty]\n        public string title\n        {\n            get => m_Title;\n            set\n            {\n                if (string.Equals(m_Title, value, StringComparison.Ordinal))\n                    return;\n                m_Title = value;\n                NotifyPropertyChanged(titleProperty);\n            }\n        }\n\n        string m_Message;\n\n        [CreateProperty]\n        public string message\n        {\n            get => m_Message;\n            set\n            {\n                if (m_Message == value) return;\n                m_Message = value;\n                NotifyPropertyChanged(messageProperty);\n            }\n        }\n\n        Type m_objectType;\n\n        [CreateProperty]\n        public Type objectType\n        {\n            get { return m_objectType; }\n            set\n            {\n                if (m_objectType == value) return;\n                m_objectType = value;\n                m_ObjectField.objectType = value;\n                NotifyPropertyChanged(objectTypeProperty);\n            }\n        }\n\n        bool m_AllowSceneObjects;\n\n        [CreateProperty]\n        public bool allowSceneObjects\n        {\n            get => m_AllowSceneObjects;\n            set\n            {\n                if (m_AllowSceneObjects == value) return;\n                m_AllowSceneObjects = value;\n                m_ObjectField.allowSceneObjects = value;\n                NotifyPropertyChanged(allowSceneObjectsProperty);\n            }\n        }\n\n        readonly ObjectField m_ObjectField;\n\n        public ObjectFieldWithPrompt() : this(null)\n        {\n        }\n\n        public ObjectFieldWithPrompt(string label) : base(label, null)\n        {\n            visualInput.style.display = DisplayStyle.None;\n\n            m_ObjectField = new ObjectField\n            {\n                allowSceneObjects = false,\n                style =\n                {\n                    flexGrow = 1,\n                    flexShrink = 1,\n                    marginLeft = 0,\n                    marginRight = 0\n                }\n            };\n            m_ObjectField.SelectorClosed += (obj, canceled) =>\n            {\n                if (canceled)\n                    return; // User pressed the Escape Key\n\n                // Delay the change call to avoid calling DestroyImmediate from the ObjectSelector.\n                EditorApplication.delayCall += () => ChangeObject(obj);\n            };\n            m_ObjectField.RegisterValueChangedCallback(evt =>\n            {\n                if (!ObjectSelector.isVisible)\n                {\n                   // If the Object Selector is NOT visible that means that the user performed a Drag&Drop into the field with a valid asset.\n                    if (ChangeObject(evt.newValue))\n                        return;\n                }\n\n                // The UI with the actual backend value might be out of sync as the ObjectSelector or the Drag&Drop might\n                // have changed the display value. Keep them in sync.\n                m_ObjectField.SetValueWithoutNotify(value);\n            });\n            Add(m_ObjectField);\n        }\n\n        private static StringBuilder s_MessageBuilder = new StringBuilder();\n\n        private bool ChangeObject(Object newValue)\n        {\n            if (value != newValue)\n            {\n                s_MessageBuilder.Clear();\n                s_MessageBuilder.AppendLine(message);\n                s_MessageBuilder.AppendLine();\n                s_MessageBuilder.AppendLine($\"Current Value: {(value ? value.name : \"None\")}.\");\n                s_MessageBuilder.AppendLine($\"New Value: {(newValue ? newValue.name : \"None\")}.\");\n                if (EditorUtility.DisplayDialog(title, s_MessageBuilder.ToString(), \"Confirm\", \"Cancel\"))\n                {\n                    value = newValue;\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        public override void SetValueWithoutNotify(Object newValue)\n        {\n            base.SetValueWithoutNotify(newValue);\n            m_ObjectField.SetValueWithoutNotify(newValue);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/VisualElements/ProjectSettings/BuiltInShaderElement.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Diagnostics;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.UIElements.ProjectSettings\n{\n    internal class BuiltInShaderElement : VisualElement\n    {\n        internal enum BuiltinShaderMode\n        {\n            None,\n            Builtin,\n            Custom\n        }\n\n        [UnityEngine.Internal.ExcludeFromDocs, Serializable]\n        public new class UxmlSerializedData : VisualElement.UxmlSerializedData\n        {\n            [RegisterUxmlCache]\n            [Conditional(\"UNITY_EDITOR\")]\n            public new static void Register()\n            {\n                UxmlDescriptionCache.RegisterType(typeof(UxmlSerializedData), new UxmlAttributeNames[]\n                {\n                    new (nameof(shaderMode), \"shader-mode\"),\n                    new (nameof(customShader), \"custom-shader\"),\n                    new (nameof(shaderModeLabel), \"shader-mode-label\"),\n                    new (nameof(customShaderLabel), \"custom-shader-label\"),\n                });\n            }\n\n            #pragma warning disable 649\n            [SerializeField, UxmlAttribute(\"shader-mode\")] string shaderMode;\n            [SerializeField, UxmlIgnore, HideInInspector] UxmlAttributeFlags shaderMode_UxmlAttributeFlags;\n            [SerializeField, UxmlAttribute(\"custom-shader\")] string customShader;\n            [SerializeField, UxmlIgnore, HideInInspector] UxmlAttributeFlags customShader_UxmlAttributeFlags;\n            [SerializeField, UxmlAttribute(\"shader-mode-label\")] string shaderModeLabel;\n            [SerializeField, UxmlIgnore, HideInInspector] UxmlAttributeFlags shaderModeLabel_UxmlAttributeFlags;\n            [SerializeField, UxmlAttribute(\"custom-shader-label\")] string customShaderLabel;\n            [SerializeField, UxmlIgnore, HideInInspector] UxmlAttributeFlags customShaderLabel_UxmlAttributeFlags;\n            #pragma warning restore 649\n\n            public override object CreateInstance() => new BuiltInShaderElement();\n\n            public override void Deserialize(object obj)\n            {\n                base.Deserialize(obj);\n\n                var e = (BuiltInShaderElement)obj;\n                if (ShouldWriteAttributeValue(shaderMode_UxmlAttributeFlags))\n                    e.shaderMode = shaderMode;\n                if (ShouldWriteAttributeValue(customShader_UxmlAttributeFlags))\n                    e.customShader = customShader;\n                if (ShouldWriteAttributeValue(shaderModeLabel_UxmlAttributeFlags))\n                    e.shaderModeLabel = shaderModeLabel;\n                if (ShouldWriteAttributeValue(customShaderLabel_UxmlAttributeFlags))\n                    e.customShaderLabel = customShaderLabel;\n            }\n        }\n\n        PropertyField m_ShaderModeField;\n        ObjectField m_CustomShaderObjectField;\n\n        string m_ShaderMode;\n\n        public string shaderMode\n        {\n            get => m_ShaderMode;\n            set\n            {\n                if (string.Equals(value, m_ShaderMode, StringComparison.Ordinal))\n                    return;\n                m_ShaderMode = value;\n                m_ShaderModeField.bindingPath = value;\n            }\n        }\n\n        string m_CustomShader;\n\n        public string customShader\n        {\n            get => m_CustomShader;\n            set\n            {\n                if (string.Equals(value, m_CustomShader, StringComparison.Ordinal))\n                    return;\n                m_CustomShader = value;\n                m_CustomShaderObjectField.bindingPath = value;\n            }\n        }\n\n        string m_ShaderModeLabel;\n\n        public string shaderModeLabel\n        {\n            get => m_ShaderModeLabel;\n            set\n            {\n                if (string.Equals(value, m_ShaderModeLabel, StringComparison.Ordinal))\n                    return;\n                m_ShaderModeLabel = value;\n                m_ShaderModeField.label = value;\n            }\n        }\n\n        string m_CustomShaderLabel;\n\n        public string customShaderLabel\n        {\n            get => m_CustomShaderLabel;\n            set\n            {\n                if (string.Equals(value, m_CustomShaderLabel, StringComparison.Ordinal))\n                    return;\n                m_CustomShaderLabel = value;\n                m_CustomShaderObjectField.label = value;\n            }\n        }\n\n        public BuiltInShaderElement()\n        {\n            m_ShaderModeField = new PropertyField();\n            m_CustomShaderObjectField = new ObjectField();\n            m_CustomShaderObjectField.SetObjectTypeWithoutDisplayUpdate(typeof(Shader));\n\n            m_ShaderModeField.RegisterValueChangeCallback(evt =>\n            {\n                m_CustomShaderObjectField.style.display = evt.changedProperty.intValue == (int)BuiltinShaderMode.Custom ? DisplayStyle.Flex : DisplayStyle.None;\n            });\n\n            Add(m_ShaderModeField);\n            Add(m_CustomShaderObjectField);\n            RegisterCallback<TooltipEvent>(evt => ApplyTooltips());\n            m_ShaderModeField.RegisterValueChangeCallback(evt => ApplyTooltips());\n        }\n\n        public void ApplyTooltips()\n        {\n            m_ShaderModeField.tooltip = tooltip;\n            m_CustomShaderObjectField.tooltip = tooltip;\n            m_ShaderModeField.Query<VisualElement>().ForEach(ve => ve.tooltip = tooltip);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/VisualElements/ProjectSettings/ProjectSettingsElementWithSO.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n﻿using UnityEditor.Experimental;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.UIElements.ProjectSettings\n{\n    internal abstract class ProjectSettingsElementWithSO : VisualElement\n    {\n        protected SerializedObject m_SerializedObject;\n        protected SettingsWindow m_SettingsWindow;\n\n        protected Color HighlightSelectionColor = EditorResources.GetStyle(\"sb-settings-panel-client-area\").GetColor(\"-unity-search-highlight-selection-color\");\n        protected Color HighlightColor = EditorResources.GetStyle(\"sb-settings-panel-client-area\").GetColor(\"-unity-search-highlight-color\");\n\n        internal void Initialize(SerializedObject serializedObject)\n        {\n            m_SerializedObject = serializedObject;\n            m_SettingsWindow = EditorWindow.GetWindow<ProjectSettingsWindow>(\"\", false);\n\n            Initialize();\n        }\n\n        internal void InitializeWithoutWindow(SerializedObject serializedObject)\n        {\n            m_SerializedObject = serializedObject;\n\n            Initialize();\n        }\n\n        protected abstract void Initialize();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/VisualElements/ProjectSettings/ProjectSettingsScopes.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n﻿using UnityEditor.Experimental;\nusing UnityEditor.StyleSheets;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Inspector.VisualElements.ProjectSettings\n{\n    internal class LabelWidthScope : GUI.Scope\n    {\n        static StyleBlock window => EditorResources.GetStyle(\"sb-settings-window\");\n        static float s_DefaultLabelWidth => window.GetFloat(\"-unity-label-width\");\n\n        readonly float m_LabelWidth;\n        public LabelWidthScope(float layoutMaxWidth)\n        {\n            m_LabelWidth = EditorGUIUtility.labelWidth;\n            EditorGUIUtility.labelWidth = s_DefaultLabelWidth;\n        }\n\n        public LabelWidthScope() : this(s_DefaultLabelWidth)\n        {\n        }\n\n        protected override void CloseScope()\n        {\n            EditorGUIUtility.labelWidth = m_LabelWidth;\n        }\n    }\n\n    internal class WideScreenScope : GUI.Scope\n    {\n        readonly bool m_CurrentWideMode;\n\n        public WideScreenScope(VisualElement currentElement)\n        {\n            m_CurrentWideMode = EditorGUIUtility.wideMode;\n\n            // the inspector's width can be NaN if this is our first layout check.\n            // If that's the case we'll set wideMode to true to avoid computing too tall an inspector on the first layout calculation\n            var inspectorWidth = currentElement.layout.width;\n            EditorGUIUtility.wideMode = float.IsNaN(inspectorWidth) || inspectorWidth > Editor.k_WideModeMinWidth;\n        }\n\n        protected override void CloseScope()\n        {\n            EditorGUIUtility.wideMode = m_CurrentWideMode;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/VisualElements/ProjectSettings/ProjectSettingsSection.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Diagnostics;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.UIElements.ProjectSettings\n{\n    internal class ProjectSettingsSection : VisualElement\n    {\n        [UnityEngine.Internal.ExcludeFromDocs, Serializable]\n        public new class UxmlSerializedData : VisualElement.UxmlSerializedData\n        {\n            [RegisterUxmlCache]\n            [Conditional(\"UNITY_EDITOR\")]\n            public new static void Register()\n            {\n                UxmlDescriptionCache.RegisterType(typeof(UxmlSerializedData), new UxmlAttributeNames[]\n                {\n                    new (nameof(label), \"label\")\n                });\n            }\n\n            #pragma warning disable 649\n            [SerializeField] string label;\n            [SerializeField, UxmlIgnore, HideInInspector] UxmlAttributeFlags label_UxmlAttributeFlags;\n            #pragma warning restore 649\n            public override object CreateInstance() => new ProjectSettingsSection();\n\n            public override void Deserialize(object obj)\n            {\n                base.Deserialize(obj);\n\n                if (ShouldWriteAttributeValue(label_UxmlAttributeFlags))\n                {\n                    var e = (ProjectSettingsSection)obj;\n                    e.label = label;\n                }\n            }\n        }\n\n        internal static class Styles\n        {\n            public static readonly string section = \"project-settings-section\";\n            public static readonly string header = \"project-settings-section__header\";\n            public static readonly string subheader = \"project-settings-section__subheader\";\n            public static readonly string content = \"project-settings-section__content\";\n        }\n\n        public Label labelElement { get; private set; }\n\n        public string label\n        {\n            get => labelElement?.text;\n            set\n            {\n                if (labelElement == null && !string.IsNullOrEmpty(value))\n                    CreateLabelElement(value);\n\n                if (labelElement == null || labelElement.text == value)\n                    return;\n\n                labelElement.text = value;\n            }\n        }\n\n        VisualElement m_ContentContainer;\n\n        /// <summary>\n        /// Contains full content, potentially partially visible.\n        /// </summary>\n        public override VisualElement contentContainer // Contains full content, potentially partially visible\n        {\n            get { return m_ContentContainer; }\n        }\n\n        // Custom controls need a default constructor. This default constructor calls the other constructor in this\n        // class.\n        public ProjectSettingsSection() : this(null)\n        {\n        }\n\n        // This constructor allows users to set the contents of the label.\n        public ProjectSettingsSection(string label)\n        {\n            AddToClassList(Styles.section);\n            AddToClassList(InspectorElement.ussClassName);\n\n            if (!string.IsNullOrEmpty(label))\n                CreateLabelElement(label);\n\n            m_ContentContainer = new VisualElement() { name = \"unity-content-container\" };\n            m_ContentContainer.AddToClassList(Styles.content);\n            hierarchy.Add(m_ContentContainer);\n\n            m_ContentContainer.RegisterCallback<AttachToPanelEvent>(OnAttachToPanel);\n            m_ContentContainer.RegisterCallback<DetachFromPanelEvent>(OnDetachFromPanel);\n        }\n\n        void CreateLabelElement(string newLabel)\n        {\n            labelElement = new Label(newLabel);\n            labelElement.AddToClassList(Styles.header);\n            hierarchy.Insert(0, labelElement);\n        }\n\n        static bool IsSubclassOfGeneric(Type genericType, Type typeToCheck) {\n            while (typeToCheck != null && typeToCheck != typeof(object))\n            {\n                var currentType = typeToCheck.IsGenericType ? typeToCheck.GetGenericTypeDefinition() : typeToCheck;\n                if (genericType == currentType)\n                    return true;\n                typeToCheck = typeToCheck.BaseType;\n            }\n            return false;\n        }\n\n        void OnAttachToPanel(AttachToPanelEvent evt)\n        {\n            if (evt.destinationPanel == null)\n                return;\n\n            var type = typeof(BaseField<>);\n            evt.elementTarget.Query<BindableElement>()\n                .Where(e =>\n                    IsSubclassOfGeneric(type, e.GetType()))\n                .ForEach(e =>\n                    e.EnableInClassList(BaseField<bool>.alignedFieldUssClassName, true));\n        }\n\n        void OnDetachFromPanel(DetachFromPanelEvent evt)\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/VisualElements/ProjectSettings/ProjectSettingsTitleBar.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Diagnostics;\nusing UnityEditor.Experimental;\nusing UnityEditor.StyleSheets;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor.UIElements.ProjectSettings\n{\n    internal class ProjectSettingsTitleBar : ProjectSettingsElementWithSO\n    {\n        [UnityEngine.Internal.ExcludeFromDocs, Serializable]\n        public new class UxmlSerializedData : VisualElement.UxmlSerializedData\n        {\n            [RegisterUxmlCache]\n            [Conditional(\"UNITY_EDITOR\")]\n            public new static void Register()\n            {\n                UxmlDescriptionCache.RegisterType(typeof(UxmlSerializedData), new UxmlAttributeNames[]\n                {\n                    new (nameof(label), \"label\")\n                });\n            }\n\n            #pragma warning disable 649\n            [SerializeField] string label;\n            [SerializeField, UxmlIgnore, HideInInspector] UxmlAttributeFlags label_UxmlAttributeFlags;\n            #pragma warning restore 649\n\n            public override object CreateInstance() => new ProjectSettingsTitleBar();\n\n            public override void Deserialize(object obj)\n            {\n                base.Deserialize(obj);\n\n                if (ShouldWriteAttributeValue(label_UxmlAttributeFlags))\n                {\n                    var e = (ProjectSettingsTitleBar)obj;\n                    e.label = label;\n                }\n            }\n        }\n\n\n        internal class Styles\n        {\n            public static StyleBlock settingsBtn { get; } = EditorResources.GetStyle(\"sb-settings-icon-btn\");\n\n            public const string k_TitleBarClassName = \"project-settings-title-bar\";\n            public const string k_TitleLabelClassName = \"project-settings-title-bar__label\";\n        }\n\n        string m_Label;\n\n        public string label\n        {\n            get => m_Label;\n            set\n            {\n                m_Label = value;\n                m_LabelElement.text = m_Label;\n            }\n        }\n\n        readonly Label m_LabelElement;\n        Object[] m_TargetObjects;\n\n        public ProjectSettingsTitleBar()\n        : this (null)\n        {\n        }\n\n        public ProjectSettingsTitleBar(string label)\n        {\n            AddToClassList(Styles.k_TitleBarClassName);\n\n            m_LabelElement = new Label();\n            m_LabelElement.AddToClassList(Styles.k_TitleLabelClassName);\n            Add(m_LabelElement);\n            Add(new IMGUIContainer(DrawEditorHeaderItems));\n\n            if (!string.IsNullOrEmpty(label))\n                this.label = label;\n        }\n\n        protected override void Initialize()\n        {\n            m_TargetObjects = m_SerializedObject.targetObjects;\n        }\n\n        void DrawEditorHeaderItems()\n        {\n            GUILayout.BeginHorizontal();\n            var btnWidth = Styles.settingsBtn.GetFloat(StyleCatalogKeyword.width);\n            var btnHeight = Styles.settingsBtn.GetFloat(StyleCatalogKeyword.height);\n            var btnMargin = Styles.settingsBtn.GetFloat(StyleCatalogKeyword.marginTop);\n\n            var currentRect = GUILayoutUtility.GetRect(btnWidth, btnHeight);\n            currentRect.y = btnMargin;\n            currentRect.x += btnWidth;\n            EditorGUIUtility.DrawEditorHeaderItems(currentRect, m_TargetObjects);\n\n            //This needs to be here to not draw HeaderItems and Dropdown for Presets on the same place\n            var settingsRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.optionsButtonStyle);\n            settingsRect.y = currentRect.y;\n\n            // Settings; process event even for disabled UI\n            var wasEnabled = GUI.enabled;\n            GUI.enabled = true;\n            var dropdownRect = GUILayoutUtility.GetRect(GUIContent.none,  EditorStyles.optionsButtonStyle);\n            dropdownRect.y = currentRect.y;\n            var showMenu =  EditorGUI.DropdownButton(dropdownRect, GUIContent.none, FocusType.Passive,  EditorStyles.optionsButtonStyle);\n            GUI.enabled = wasEnabled;\n            if (showMenu)\n                EditorUtility.DisplayObjectContextMenu(dropdownRect, m_TargetObjects, 0);\n            GUILayout.EndHorizontal();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/VisualElements/ProjectSettings/TabButton.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Diagnostics;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.UIElements.ProjectSettings\n{\n    internal class TabButton : VisualElement\n    {\n        [Serializable]\n        internal new class UxmlSerializedData : VisualElement.UxmlSerializedData\n        {\n            [RegisterUxmlCache]\n            [Conditional(\"UNITY_EDITOR\")]\n            public new static void Register()\n            {\n                UxmlDescriptionCache.RegisterType(typeof(UxmlSerializedData), new UxmlAttributeNames[]\n                {\n                    new (nameof(text), \"text\"),\n                    new (nameof(target), \"target\"),\n                });\n            }\n\n            #pragma warning disable 649\n            [SerializeField] string text;\n            [SerializeField, UxmlIgnore, HideInInspector] UxmlAttributeFlags text_UxmlAttributeFlags;\n            [SerializeField] string target;\n            [SerializeField, UxmlIgnore, HideInInspector] UxmlAttributeFlags target_UxmlAttributeFlags;\n            #pragma warning restore 649\n\n            public override object CreateInstance() => new TabButton();\n\n            public override void Deserialize(object obj)\n            {\n                base.Deserialize(obj);\n\n                var e = (TabButton)obj;\n                if (ShouldWriteAttributeValue(text_UxmlAttributeFlags))\n                    e.m_Label.text = text;\n                if (ShouldWriteAttributeValue(target_UxmlAttributeFlags))\n                    e.TargetId = target;\n            }\n        }\n\n        static readonly string UxmlName = \"TabButton\";\n        static readonly string s_UssClassName = \"unity-tab-button\";\n        static readonly string s_UssActiveClassName = s_UssClassName + \"--active\";\n\n        public bool IsCloseable { get; set; }\n        public string TargetId { get; private set; }\n        public VisualElement Target { get; set; }\n\n        public event Action<TabButton> OnSelect;\n        public event Action<TabButton> OnClose;\n\n        Label m_Label;\n        VisualElement m_BottomBar;\n\n        public TabButton()\n        {\n            Init();\n        }\n\n        public TabButton(string text, VisualElement target)\n        {\n            Init();\n            m_Label.text = text;\n            Target = target;\n        }\n\n        void PopulateContextMenu(ContextualMenuPopulateEvent populateEvent)\n        {\n            var dropdownMenu = populateEvent.menu;\n\n            if (IsCloseable)\n                dropdownMenu.AppendAction(\"Close Tab\", e => { OnClose?.Invoke(this); });\n        }\n\n        void CreateContextMenu(VisualElement visualElement)\n        {\n            var menuManipulator = new ContextualMenuManipulator(PopulateContextMenu);\n\n            visualElement.focusable = true;\n            visualElement.pickingMode = PickingMode.Position;\n            visualElement.AddManipulator(menuManipulator);\n        }\n\n        void Init()\n        {\n            AddToClassList(s_UssClassName);\n\n            var visualTree = EditorGUIUtility.Load($\"UXML/InspectorWindow/{UxmlName}.uxml\") as VisualTreeAsset;\n            visualTree.CloneTree(this);\n\n            m_Label = this.Q<Label>(\"Label\");\n            m_BottomBar = this.Q<VisualElement>(\"BottomBar\");\n\n            CreateContextMenu(this);\n            RegisterCallback<MouseDownEvent>(OnMouseDownEvent);\n            RegisterCallback<GeometryChangedEvent>(OnGeometryChangedEvent);\n        }\n\n        void OnGeometryChangedEvent(GeometryChangedEvent evt)\n        {\n            if(m_BottomBar.style.display == DisplayStyle.Flex)\n                RecalculateBottomBarPosition();\n        }\n\n        public void Select()\n        {\n            AddToClassList(s_UssActiveClassName);\n\n            if (Target == null)\n                return;\n\n            Target.style.display = DisplayStyle.Flex;\n            Target.style.flexGrow = 1;\n            m_BottomBar.style.display = DisplayStyle.Flex;\n            GetFirstAncestorOfType<TabbedView>().hierarchy.Add(m_BottomBar);\n            RecalculateBottomBarPosition();\n        }\n\n        void RecalculateBottomBarPosition()\n        {\n            //we need to calculate the width of the bottom bar based on the tab width and remove border width from left and right\n            m_BottomBar.style.width = layout.width - resolvedStyle.borderRightWidth - resolvedStyle.borderLeftWidth;\n            //we extract additional padding from the parent to get the correct position + tab height\n            m_BottomBar.style.top = (parent.worldBound.y - parent.parent.worldBound.y) + parent.layout.height;\n            //we extract additional padding from the parent to get the correct position + tab position x + border width\n            m_BottomBar.style.left = (parent.worldBound.x - parent.parent.worldBound.x) + layout.x + resolvedStyle.borderLeftWidth;\n        }\n\n        public void Deselect()\n        {\n            RemoveFromClassList(s_UssActiveClassName);\n            MarkDirtyRepaint();\n\n            if (Target == null)\n                return;\n            Target.style.display = DisplayStyle.None;\n            Target.style.flexGrow = 0;\n            m_BottomBar.style.display = DisplayStyle.None;\n            parent.Add(m_BottomBar);\n        }\n\n        void OnMouseDownEvent(MouseDownEvent e)\n        {\n            switch (e.button)\n            {\n                case 0:\n                {\n                    OnSelect?.Invoke(this);\n                    break;\n                }\n\n                case 2 when IsCloseable:\n                {\n                    OnClose?.Invoke(this);\n                    break;\n                }\n            }\n\n            e.StopImmediatePropagation();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/VisualElements/ProjectSettings/TabbedView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.UIElements.ProjectSettings\n{\n    internal class TabbedView : VisualElement\n    {\n        [Serializable]\n        public new class UxmlSerializedData : VisualElement.UxmlSerializedData\n        {\n            public override object CreateInstance() => new TabbedView();\n        }\n\n        const string s_UssClassName = \"unity-tabbed-view\";\n        const string s_ContentContainerClassName = \"unity-tabbed-view__content-container\";\n        const string s_TabsContainerClassName = \"unity-tabbed-view__tabs-container\";\n\n        readonly VisualElement m_TabContent;\n        readonly VisualElement m_Content;\n\n        readonly List<TabButton> m_Tabs = new();\n        internal IEnumerable<TabButton> tabs => m_Tabs;\n\n        TabButton m_ActiveTab;\n        internal TabButton ActiveTab => m_ActiveTab;\n        internal int ActiveTabIndex => m_ActiveTab != null ? m_Tabs.IndexOf(m_ActiveTab) : -1;\n\n        public override VisualElement contentContainer => m_Content;\n\n        public TabbedView()\n        {\n            AddToClassList(s_UssClassName);\n\n            styleSheets.Add(EditorGUIUtility.Load(\"StyleSheets/InspectorWindow/TabbedView.uss\") as StyleSheet);\n\n            m_TabContent = new VisualElement { name = \"unity-tabs-container\" };\n            m_TabContent.AddToClassList(s_TabsContainerClassName);\n            hierarchy.Add(m_TabContent);\n\n            m_Content = new VisualElement { name = \"unity-content-container\" };\n            m_Content.AddToClassList(s_ContentContainerClassName);\n            hierarchy.Add(m_Content);\n\n            RegisterCallback<AttachToPanelEvent>(OnAttachPanelEvent);\n        }\n\n        public void AddTab(TabButton tabButton, bool activate)\n        {\n            switch (m_Tabs.Count)\n            {\n                case 0:\n                    SetStyleForLeftmost(tabButton);\n                    break;\n                case > 0:\n                    SetStyleForRightmost(tabButton);\n                    break;\n            }\n\n            m_Tabs.Add(tabButton);\n            m_TabContent.Add(tabButton);\n\n            UpdateBorderStyles();\n\n            tabButton.OnClose += RemoveTab;\n            tabButton.OnSelect += Activate;\n\n            Add(tabButton.Target);\n            tabButton.Target.style.display = DisplayStyle.None;\n\n            if (activate)\n                Activate(tabButton);\n        }\n\n        public void RemoveTab(TabButton tabButton)\n        {\n            var index = m_Tabs.IndexOf(tabButton);\n\n            // If this tab is the active one make sure we deselect it first...\n            if (m_ActiveTab == tabButton)\n            {\n                DeselectTab(tabButton);\n                m_ActiveTab = null;\n            }\n\n            m_Tabs.RemoveAt(index);\n            m_TabContent.Remove(tabButton);\n\n            UpdateBorderStyles();\n\n            tabButton.OnClose -= RemoveTab;\n            tabButton.OnSelect -= Activate;\n\n            // If we closed the active tab AND we have any tabs left - active the next valid one...\n            if (m_ActiveTab != null || m_Tabs.Count == 0)\n                return;\n            var clampedIndex = Mathf.Clamp(index, 0, m_Tabs.Count - 1);\n            var tabToActivate = m_Tabs[clampedIndex];\n\n            Activate(tabToActivate);\n        }\n\n        void UpdateBorderStyles()\n        {\n            var tabAmount = m_Tabs.Count;\n            if (tabAmount == 0)\n                return;\n\n            for (int i = 0; i < tabAmount; i++)\n            {\n                ResetBorderStyles(m_Tabs[i]);\n                if (i == 0)\n                    SetStyleForLeftmost(m_Tabs[i]);\n                if (i + 1 == tabAmount)\n                    SetStyleForRightmost(m_Tabs[i]);\n            }\n        }\n\n        void OnAttachPanelEvent(AttachToPanelEvent e)\n        {\n            // This code takes any existing tab buttons and hooks them into the system...\n            for (int i = 0; i < m_Content.childCount; ++i)\n            {\n                VisualElement element = m_Content[i];\n\n                if (element is TabButton button)\n                {\n                    m_Content.Remove(element);\n                    if (button.Target == null)\n                    {\n                        string targetId = button.TargetId;\n\n                        button.Target = this.Q(targetId);\n                    }\n\n                    AddTab(button, false);\n                    --i;\n                }\n                else\n                {\n                    element.style.display = DisplayStyle.None;\n                }\n            }\n\n            // Finally, if we need to, activate this tab...\n            if (m_ActiveTab != null)\n            {\n                SelectTab(m_ActiveTab);\n            }\n            else if (m_TabContent.childCount > 0)\n            {\n                m_ActiveTab = (TabButton)m_TabContent[0];\n\n                SelectTab(m_ActiveTab);\n            }\n        }\n\n        static void SetStyleForLeftmost(VisualElement element)\n        {\n            element.style.borderTopLeftRadius = 3;\n            foreach (var child in element.Children())\n            {\n                child.style.borderTopLeftRadius = 3;\n                break;\n            }\n        }\n\n        static void SetStyleForRightmost(VisualElement element)\n        {\n            element.style.borderRightWidth = 1;\n            element.style.borderTopRightRadius = 3;\n            foreach (var child in element.Children())\n            {\n                child.style.borderTopRightRadius = 3;\n                break;\n            }\n        }\n\n        static void ResetBorderStyles(VisualElement element)\n        {\n            element.style.borderTopLeftRadius = 0;\n            foreach (var child in element.Children())\n            {\n                child.style.borderTopLeftRadius = 0;\n                break;\n            }\n            element.style.borderRightWidth = 0;\n            element.style.borderTopRightRadius = 0;\n            foreach (var child in element.Children())\n            {\n                child.style.borderTopRightRadius = 0;\n                break;\n            }\n        }\n\n        public void SelectTab(int index)\n        {\n            if(index >= m_Tabs.Count || index < 0)\n                return;\n\n            Activate(m_Tabs[index]);\n        }\n\n        public void Activate(TabButton button)\n        {\n            if (m_ActiveTab == button)\n                return;\n\n            if (m_ActiveTab != null)\n            {\n                DeselectTab(m_ActiveTab);\n            }\n\n            m_ActiveTab = button;\n            SelectTab(m_ActiveTab);\n        }\n\n        void SelectTab(TabButton tabButton)\n        {\n            tabButton.Select();\n        }\n\n        void DeselectTab(TabButton tabButton)\n        {\n            tabButton.Deselect();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/VisualElements/RenderingLayerMaskField.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n﻿using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing UnityEditor.Rendering;\nusing UnityEngine;\nusing UnityEngine.Internal;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.UIElements\n{\n    /// <summary>\n    /// A RenderingLayerMaskField editor.\n    /// </summary>\n    public class RenderingLayerMaskField : BaseMaskField<uint>\n    {\n        [ExcludeFromDocs, Serializable]\n        public new class UxmlSerializedData : BaseField<uint>.UxmlSerializedData\n        {\n            [RegisterUxmlCache]\n            [Conditional(\"UNITY_EDITOR\")]\n            public new static void Register()\n            {\n                BaseField<uint>.UxmlSerializedData.Register();\n                UxmlDescriptionCache.RegisterType(typeof(UxmlSerializedData), new UxmlAttributeNames[]\n                {\n                    new(nameof(layerMask), \"value\")\n                });\n            }\n\n#pragma warning disable 649\n            [UxmlAttribute(\"value\")] [SerializeField]\n            RenderingLayerMask layerMask;\n\n            [SerializeField, UxmlIgnore, HideInInspector]\n            UxmlAttributeFlags layerMask_UxmlAttributeFlags;\n#pragma warning restore 649\n\n            public override object CreateInstance() => new RenderingLayerMaskField();\n\n            public override void Deserialize(object obj)\n            {\n                base.Deserialize(obj);\n\n                if (ShouldWriteAttributeValue(layerMask_UxmlAttributeFlags))\n                {\n                    var e = (RenderingLayerMaskField)obj;\n                    e.layerMask = layerMask;\n                }\n            }\n        }\n\n        /// <summary>\n        /// USS class name of elements of this type.\n        /// </summary>\n        public new static readonly string ussClassName = \"unity-rendering-layer-mask-field\";\n\n        /// <summary>\n        /// USS class name of labels in elements of this type.\n        /// </summary>\n        public new static readonly string labelUssClassName = ussClassName + \"__label\";\n\n        /// <summary>\n        /// USS class name of input elements in elements of this type.\n        /// </summary>\n        public new static readonly string inputUssClassName = ussClassName + \"__input\";\n\n        internal RenderingLayerMask layerMask\n        {\n            get => value;\n            set => this.value = value;\n        }\n\n        readonly HelpBox m_HelpBox;\n\n        readonly List<string> m_RenderingLayersChoices = new();\n        readonly List<int> m_RenderingLayersChoicesMasks = new();\n\n        /// <summary>\n        /// Constructor of the field.\n        /// </summary>\n        /// <param name=\"defaultMask\">The default mask to use for the initial selection.</param>\n        public RenderingLayerMaskField(uint defaultMask)\n            : this(null, defaultMask)\n        {\n        }\n\n        /// <summary>\n        /// Constructor of the field.\n        /// </summary>\n        /// <param name=\"label\">The label to prefix the <see cref=\"RenderingLayerMaskField\"/>.</param>\n        public RenderingLayerMaskField(string label)\n            : this(label, RenderingLayerMask.defaultRenderingLayerMask)\n        {\n        }\n\n        /// <summary>\n        /// Constructor of the field.\n        /// </summary>\n        public RenderingLayerMaskField()\n            : this(null)\n        {\n        }\n\n        /// <summary>\n        /// Constructor of the field.\n        /// </summary>\n        /// <param name=\"label\">The label to prefix the <see cref=\"RenderingLayerMaskField\"/>.</param>\n        /// <param name=\"defaultMask\">The default mask to use for the initial selection.</param>\n        public RenderingLayerMaskField(string label, uint defaultMask)\n            : base(label)\n        {\n            style.flexWrap = Wrap.Wrap;\n            AddToClassList(ussClassName);\n            labelElement.AddToClassList(labelUssClassName);\n            visualInput.AddToClassList(inputUssClassName);\n\n            m_HelpBox = new HelpBox(string.Empty, HelpBoxMessageType.Warning);\n            Add(m_HelpBox);\n\n            UpdateChoices(defaultMask);\n            SetValueWithoutNotify(defaultMask);\n\n            RegisterCallback<AttachToPanelEvent>(_ => RenderPipelineEditorUtility.onRenderingLayerCountChanged += OnRenderingLayersChanged);\n            RegisterCallback<DetachFromPanelEvent>(_ => RenderPipelineEditorUtility.onRenderingLayerCountChanged -= OnRenderingLayersChanged);\n            RegisterCallback<GeometryChangedEvent>(RecalculateHelpBoxSize);\n        }\n\n        internal override uint MaskToValue(int newMask) => unchecked((uint)newMask);\n\n        internal override int ValueToMask(uint value) => unchecked((int)value);\n\n        private protected override int UpdateMaskIfEverything(int currentMask)\n        {\n            var limit = RenderPipelineEditorUtility.GetActiveMaxRenderingLayers();\n            return RenderPipelineEditorUtility.DoesMaskContainRenderingLayersOutsideOfMaxBitCount(unchecked((uint)currentMask), limit) ? currentMask : base.UpdateMaskIfEverything(currentMask);\n        }\n\n        public override uint value\n        {\n            get => rawValue;\n            set\n            {\n                if (CheckIfOnlyOneLayerWasDeselectedFromEverything(value))\n                {\n                    var diffValue = ~value;\n                    var counter = BitOperationUtils.CountBits(diffValue);\n                    if (counter == 1)\n                    {\n                        var currentMax = RenderPipelineEditorUtility.GetActiveMaxRenderingLayers();\n                        var definedRenderingLayerValues = RenderingLayerMask.GetDefinedRenderingLayerValues();\n                        value = BitOperationUtils.ModifyMaskByValuesArrayAndBitCount(value, definedRenderingLayerValues, currentMax);\n                    }\n                }\n\n                UpdateChoices(value);\n                base.value = value;\n            }\n        }\n\n        protected void UpdateLayersInfo()\n        {\n            UpdateChoices(value);\n        }\n\n        bool CheckIfOnlyOneLayerWasDeselectedFromEverything(uint nextValue)\n        {\n            return rawValue == uint.MaxValue && nextValue != uint.MaxValue;\n        }\n\n        void UpdateChoices(uint mask)\n        {\n            // Create the appropriate choices for the mask\n            var (names, values) = RenderPipelineEditorUtility.GetRenderingLayerNamesAndValuesForMask(mask);\n\n            m_RenderingLayersChoices.Clear();\n            m_RenderingLayersChoices.AddRange(names);\n            choices = m_RenderingLayersChoices;\n\n            m_RenderingLayersChoicesMasks.Clear();\n            m_RenderingLayersChoicesMasks.AddRange(values);\n            choicesMasks = m_RenderingLayersChoicesMasks;\n\n            UpdateHelpBoxVisibility(mask);\n        }\n\n        void OnRenderingLayersChanged()\n        {\n            value = rawValue;\n        }\n\n        //We manually recalculate the HelpBox width to imitate the behavior of flex column for our mask control and HelpBox\n        void RecalculateHelpBoxSize(GeometryChangedEvent evt)\n        {\n            m_HelpBox.style.width = evt.newRect.width;\n        }\n\n        void UpdateHelpBoxVisibility(uint mask)\n        {\n            var maxBitCount = RenderPipelineEditorUtility.GetActiveMaxRenderingLayers();\n            if (RenderPipelineEditorUtility.DoesMaskContainRenderingLayersOutsideOfMaxBitCount(mask, maxBitCount))\n            {\n                m_HelpBox.style.display = DisplayStyle.Flex;\n                m_HelpBox.text = RenderPipelineEditorUtility.GetOutsideOfMaxBitCountWarningMessage(maxBitCount);\n            }\n            else\n            {\n                m_HelpBox.style.display = DisplayStyle.None;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/WebCamTextureInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Experimental.Rendering;\nusing UnityEditor;\nusing System.Globalization;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(WebCamTexture))]\n    internal class WebCamTextureInspector : Editor\n    {\n        static GUIContent[] s_PlayIcons = {null, null};\n        Vector2 m_Pos;\n\n        public override void OnInspectorGUI()\n        {\n            WebCamTexture t = target as WebCamTexture;\n            EditorGUILayout.LabelField(\"Requested FPS\", t.requestedFPS.ToString(CultureInfo.InvariantCulture.NumberFormat));\n            EditorGUILayout.LabelField(\"Requested Width\", t.requestedWidth.ToString(CultureInfo.InvariantCulture.NumberFormat));\n            EditorGUILayout.LabelField(\"Requested Height\", t.requestedHeight.ToString(CultureInfo.InvariantCulture.NumberFormat));\n            EditorGUILayout.LabelField(\"Device Name\", t.deviceName);\n        }\n\n        static void Init()\n        {\n            s_PlayIcons[0] = EditorGUIUtility.IconContent(\"preAudioPlayOff\");\n            s_PlayIcons[1] = EditorGUIUtility.IconContent(\"preAudioPlayOn\");\n        }\n\n        public override bool HasPreviewGUI()\n        {\n            return (target != null);\n        }\n\n        public override void OnPreviewSettings()\n        {\n            Init();\n\n            // Disallow playing movie previews in play mode. Better not to interfere\n            // with any playback the game does.\n            GUI.enabled = !Application.isPlaying;\n            WebCamTexture t = target as WebCamTexture;\n            bool isPlaying = PreviewGUI.CycleButton(t.isPlaying ? 1 : 0, s_PlayIcons) != 0;\n            if (isPlaying != t.isPlaying)\n            {\n                if (isPlaying)\n                {\n                    t.Stop();\n                    t.Play();\n                }\n                else\n                {\n                    t.Pause();\n                }\n            }\n            GUI.enabled = true;\n        }\n\n        public override void OnPreviewGUI(Rect r, GUIStyle background)\n        {\n            if (Event.current.type == EventType.Repaint)\n                background.Draw(r, false, false, false, false);\n\n            // show texture\n            WebCamTexture t = target as WebCamTexture;\n\n            float zoomLevel = Mathf.Min(Mathf.Min(r.width / t.width, r.height / t.height), 1);\n            Rect wantedRect = new Rect(r.x, r.y, t.width * zoomLevel, t.height * zoomLevel);\n            PreviewGUI.BeginScrollView(r, m_Pos, wantedRect, \"PreHorizontalScrollbar\", \"PreHorizontalScrollbarThumb\");\n            GUI.DrawTexture(wantedRect, t, ScaleMode.StretchToFill, false);\n            m_Pos = PreviewGUI.EndScrollView();\n\n            // force update GUI\n            if (t.isPlaying)\n                GUIView.current.Repaint();\n\n            if (Application.isPlaying)\n            {\n                if (t.isPlaying)\n                    EditorGUI.DropShadowLabel(new Rect(r.x, r.y + 10, r.width, 20), \"Can't pause preview when in play mode\");\n                else\n                    EditorGUI.DropShadowLabel(new Rect(r.x, r.y + 10, r.width, 20), \"Can't start preview when in play mode\");\n            }\n        }\n\n        public void OnDisable()\n        {\n            WebCamTexture t = target as WebCamTexture;\n\n            //stop the camera if we started it\n            if (!Application.isPlaying && t != null)\n            {\n                t.Stop();\n            }\n        }\n\n        public override string GetInfoString()\n        {\n            Texture t = target as Texture;\n            string info = t.width + \"x\" + t.height;\n            GraphicsFormat format = GraphicsFormatUtility.GetFormat(t);\n            info += \"  \" + GraphicsFormatUtility.GetFormatString(format);\n            return info;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Inspector/WindInspector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditor.AnimatedValues;\n\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(WindZone))]\n    [CanEditMultipleObjects]\n    internal class WindInspector : Editor\n    {\n        private class Styles\n        {\n            public static GUIContent Mode               = EditorGUIUtility.TrTextContent(\"Mode\", \"The wind blows towards a direction or outwards within a sphere\");\n            public static GUIContent Radius             = EditorGUIUtility.TrTextContent(\"Radius\", \"The radius of the spherical area\");\n            public static GUIContent WindMain           = EditorGUIUtility.TrTextContent(\"Main\", \"Overall strength of the wind\");\n            public static GUIContent WindTurbulence     = EditorGUIUtility.TrTextContent(\"Turbulence\", \"Randomness in strength\");\n            public static GUIContent WindPulseMagnitude = EditorGUIUtility.TrTextContent(\"Pulse Magnitude\", \"Strength of the wind pulses\");\n            public static GUIContent WindPulseFrequency = EditorGUIUtility.TrTextContent(\"Pulse Frequency\", \"Frequency of the wind pulses\");\n        }\n\n        private SerializedProperty m_Mode;\n        private SerializedProperty m_Radius;\n        private SerializedProperty m_WindMain;\n        private SerializedProperty m_WindTurbulence;\n        private SerializedProperty m_WindPulseMagnitude;\n        private SerializedProperty m_WindPulseFrequency;\n\n        private readonly AnimBool m_ShowRadius = new AnimBool();\n\n        private void OnEnable()\n        {\n            m_Mode = serializedObject.FindProperty(\"m_Mode\");\n            m_Radius = serializedObject.FindProperty(\"m_Radius\");\n            m_WindMain = serializedObject.FindProperty(\"m_WindMain\");\n            m_WindTurbulence = serializedObject.FindProperty(\"m_WindTurbulence\");\n            m_WindPulseMagnitude = serializedObject.FindProperty(\"m_WindPulseMagnitude\");\n            m_WindPulseFrequency = serializedObject.FindProperty(\"m_WindPulseFrequency\");\n\n            m_ShowRadius.value = !m_Mode.hasMultipleDifferentValues && m_Mode.intValue == (int)WindZoneMode.Spherical;\n            m_ShowRadius.valueChanged.AddListener(Repaint);\n        }\n\n        private void OnDisable()\n        {\n            m_ShowRadius.valueChanged.RemoveListener(Repaint);\n        }\n\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n\n            EditorGUILayout.PropertyField(m_Mode, Styles.Mode);\n\n            m_ShowRadius.target = !m_Mode.hasMultipleDifferentValues && m_Mode.intValue == (int)WindZoneMode.Spherical;\n            if (EditorGUILayout.BeginFadeGroup(m_ShowRadius.faded))\n                EditorGUILayout.PropertyField(m_Radius, Styles.Radius);\n            EditorGUILayout.EndFadeGroup();\n\n            EditorGUILayout.PropertyField(m_WindMain, Styles.WindMain);\n            EditorGUILayout.PropertyField(m_WindTurbulence, Styles.WindTurbulence);\n            EditorGUILayout.PropertyField(m_WindPulseMagnitude, Styles.WindPulseMagnitude);\n            EditorGUILayout.PropertyField(m_WindPulseFrequency, Styles.WindPulseFrequency);\n\n            serializedObject.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/InspectorUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\nusing System;\nusing Object = UnityEngine.Object;\nusing System.Collections.Generic;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    internal class InspectorUtility\n    {\n        internal delegate void LivePropertyOverrideCallback(SerializedObject serializedObject, bool isLiveUpdate);\n        internal delegate bool LivePropertyChangedCallback(Object[] unityObject);\n\n        internal static Dictionary<Type, LivePropertyOverrideCallback> s_LivePropertyOverrideCallbacks = new Dictionary<Type, LivePropertyOverrideCallback>();\n        internal static Dictionary<Type, LivePropertyChangedCallback> s_LivePropertyChangedCallbacks = new Dictionary<Type, LivePropertyChangedCallback>();\n\n        static SerializedObject s_CachedSerializedObject = new SerializedObject(IntPtr.Zero);\n\n        internal static void SetLivePropertyOverride(Type type, LivePropertyOverrideCallback callback)\n        {\n            if (s_LivePropertyOverrideCallbacks.TryGetValue(type, out var del))\n            {\n                del += callback;\n            }\n            else\n            {\n                s_LivePropertyOverrideCallbacks[type] = callback;\n            }\n        }\n\n        internal static void RemoveLivePropertyOverride(Type type, LivePropertyOverrideCallback callback)\n        {\n            s_LivePropertyOverrideCallbacks[type] -= callback;\n            if (s_LivePropertyOverrideCallbacks[type] == null)\n                s_LivePropertyOverrideCallbacks.Remove(type);\n        }\n\n        internal static void SetLivePropertyChanged(Type type, LivePropertyChangedCallback callback)\n        {\n            if (s_LivePropertyChangedCallbacks.TryGetValue(type, out var del))\n            {\n                del += callback;\n            }\n            else\n            {\n                s_LivePropertyChangedCallbacks[type] = callback;\n            }\n        }\n\n        internal static void RemoveLivePropertyChanged(Type type, LivePropertyChangedCallback callback)\n        {\n            s_LivePropertyChangedCallbacks[type] -= callback;\n            if (s_LivePropertyChangedCallbacks[type] == null)\n                s_LivePropertyChangedCallbacks.Remove(type);\n        }\n\n        static bool IsLivePropertyChanged(Editor editor)\n        {\n            var target = editor.target;\n            if (target == null)\n                return false;\n\n            var targetType = target.GetType();\n\n            if (s_LivePropertyChangedCallbacks.TryGetValue(targetType, out var cb))\n            {\n                if (cb.Invoke(editor.targets))\n                    return true;\n            }\n\n            return false;\n        }\n\n        internal static void DirtyLivePropertyChanges(ActiveEditorTracker tracker)\n        {\n            if (!EditorApplication.isPlaying || s_LivePropertyOverrideCallbacks.Count <= 0)\n                return;\n\n            var editors = tracker.activeEditors;\n            for (var i = 0; i != editors.Length;i++)\n            {\n                if (tracker.GetVisible(i) == 0)\n                    continue;\n\n                // Callback\n                var editor = editors[i];\n                if (IsLivePropertyChanged(editor))\n                    editor.isInspectorDirty = true;\n            }\n        }\n\n        // Check if current serialized object contains any live properties.\n        // If so, enable live property feature.\n        [RequiredByNativeCode]\n        internal static bool Internal_HasLiveProperties(IntPtr nativeObjectPtr)\n        {\n            if (!EditorApplication.isPlaying || s_LivePropertyOverrideCallbacks.Count <= 0)\n                return false;\n\n            if (s_CachedSerializedObject.m_NativeObjectPtr != IntPtr.Zero)\n                throw new ArgumentException(\"Recursive EnableLivePropertyFeature are not allowed.\");\n\n            var livePropertyFeatureEnabled = false;\n\n            try\n            {\n                s_CachedSerializedObject.m_NativeObjectPtr = nativeObjectPtr;\n                var target = s_CachedSerializedObject.targetObject;\n                if (target == null)\n                    return false;\n\n                var targetType = target.GetType();\n\n                if (s_LivePropertyOverrideCallbacks.ContainsKey(targetType))\n                {\n                    livePropertyFeatureEnabled = true;\n                }\n            }\n            finally\n            {\n                // This serialized object is just a temp reference to pass around, it doesn't own the pointer\n                s_CachedSerializedObject.m_NativeObjectPtr = IntPtr.Zero;\n            }\n\n            return livePropertyFeatureEnabled;\n        }\n\n        // Invoke override callback for live property.\n        [RequiredByNativeCode]\n        internal static void Internal_CallPropertyOverrideCallback(IntPtr nativeObjectPtr, bool isLiveUpdate)\n        {\n            if (s_CachedSerializedObject.m_NativeObjectPtr != IntPtr.Zero && s_CachedSerializedObject.m_NativeObjectPtr != nativeObjectPtr)\n                throw new ArgumentException(\"Recursive SetLivePropertyOverrides are not allowed.\");\n\n            try\n            {\n                if (s_CachedSerializedObject.m_NativeObjectPtr == IntPtr.Zero)\n                {\n                    s_CachedSerializedObject.m_NativeObjectPtr = nativeObjectPtr;\n                    if (s_CachedSerializedObject.targetObject == null)\n                        return;\n                }\n\n                var targetType = s_CachedSerializedObject.targetObject.GetType();\n                if (s_LivePropertyOverrideCallbacks.TryGetValue(targetType, out var cb))\n                {\n                    cb.Invoke(s_CachedSerializedObject, isLiveUpdate);\n                }\n            }\n            finally\n            {\n                // This serialized object is just a temp reference to pass around, it doesn't own the pointer\n                s_CachedSerializedObject.m_NativeObjectPtr = IntPtr.Zero;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/InteractionContext.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Assertions;\n\nnamespace UnityEditor\n{\n    [NativeType(Header = \"Editor/Src/InteractionContext.h\")]\n    internal partial class InteractionContext: IDisposable\n    {\n        [Flags]\n        public enum Flags\n        {\n            DisableNone = 0,\n            DisableUndo = 1,\n            DisableDialogs = 2,\n\n            DisableUndoAndDialogs = DisableUndo | DisableDialogs,\n        }\n\n        internal IntPtr m_NativePtr;\n\n        public InteractionContext(Flags flags) : this (Internal_Create((int)flags))\n        {\n        }\n\n        private InteractionContext(IntPtr nativePtr)\n        {\n            m_NativePtr = nativePtr;\n        }\n\n        ~InteractionContext()\n        {\n            if (m_NativePtr != IntPtr.Zero)\n            {\n                Dispose();\n            }\n        }\n\n        public virtual void Dispose()\n        {\n            if (m_NativePtr != IntPtr.Zero)\n            {\n                Internal_Destroy(m_NativePtr);\n                m_NativePtr = IntPtr.Zero;\n            }\n        }\n\n        public extern bool IsUndoEnabled();\n        public extern bool WasAnyUndoOperationRegisteredSinceCreation();\n\n        public extern bool AreDialogsEnabled();\n        public extern bool HasUnusedDialogResponses();\n        public extern bool IsCurrentDialogResponse(string dialogTitle);\n        public extern string GetCurrentDialogResponse();\n        public extern string GetCurrentDialogResponseAndAvance();\n        public extern void AppendDialogResponse(string dialogTitle, string dialogResponse);\n\n        public extern string GetErrors();\n\n        [FreeFunction(\"CreateInteractionContext\", IsThreadSafe = false)]\n        private static extern IntPtr Internal_Create(int flags);\n        [FreeFunction(\"DestroyInteractionContext\")]\n        private static extern void Internal_Destroy(IntPtr m_NativePtr);\n\n        public static InteractionContext UserAction = new InteractionContext(Flags.DisableNone);\n\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(InteractionContext context) => context.m_NativePtr;\n            public static InteractionContext ConvertToManaged(IntPtr ptr) => new InteractionContext(ptr);\n        }\n    }\n\n    internal class GlobalInteractionContext : InteractionContext, IDisposable\n    {\n        public GlobalInteractionContext(InteractionContext.Flags flags)\n            : base(flags)\n        {\n            Assert.IsNull(GetGlobalInteractionContext());\n            SetGlobalInteractionContext(this);\n        }\n\n        public override void Dispose()\n        {\n            try\n            {\n                Assert.IsFalse(HasUnusedDialogResponses());\n                if (!IsUndoEnabled())\n                {\n                    Assert.IsFalse(WasAnyUndoOperationRegisteredSinceCreation(), \"InteractionContext has unused dialog responses\");\n                }\n            }\n            finally\n            {\n                ClearGlobalInteractionContext();\n            }\n            base.Dispose();\n        }\n\n        [FreeFunction(\"SetGlobalInteractionContext\")]\n        private static extern void SetGlobalInteractionContext(InteractionContext interactionContext);\n\n        [FreeFunction(\"GetGlobalInteractionContext\")]\n        private static extern InteractionContext GetGlobalInteractionContext();\n\n        [FreeFunction(\"ClearGlobalInteractionContext\")]\n        private static extern void ClearGlobalInteractionContext();\n\n        new internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(GlobalInteractionContext context) => context.m_NativePtr;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Internal/MonoScripts.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEngine;\n\nnamespace UnityEditorInternal\n{\n    /// <summary>\n    /// Helper factory for <see cref=\"UnityEditor.MonoScript\"/> instances.\n    /// </summary>\n    public static class MonoScripts\n    {\n        public static MonoScript CreateMonoScript(string scriptContents, string className, string nameSpace, string assemblyName, bool isEditorScript)\n        {\n            var script = new MonoScript();\n            if (!string.IsNullOrEmpty(scriptContents))\n            {\n                Debug.LogWarning($\"MonoScript {className} was initialized with a non-empty script. This has never worked and should not be attempted. The script contents will be ignored\");\n            }\n            script.Init(className, nameSpace, assemblyName, isEditorScript);\n            return script;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/InternalEditorUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\nusing UnityEditor;\nusing System.Reflection;\nusing UnityEngine.Bindings;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing System.Globalization;\nusing Unity.CodeEditor;\nusing TargetAttributes = UnityEditor.BuildTargetDiscovery.TargetAttributes;\nusing UnityEngine.Scripting;\nusing System.Runtime.InteropServices;\nusing UnityEngine.SceneManagement;\nusing ShaderPropertyType = UnityEngine.Rendering.ShaderPropertyType;\nusing ShaderPropertyFlags = UnityEngine.Rendering.ShaderPropertyFlags;\n\nnamespace UnityEditorInternal\n{\n    [System.Obsolete(\"CanAppendBuild has been deprecated. Use UnityEditor.CanAppendBuild instead (UnityUpgradable) -> [UnityEditor] UnityEditor.CanAppendBuild\", true)]\n    public enum CanAppendBuild\n    {\n        Unsupported = 0,\n        Yes = 1,\n        No = 2,\n    }\n\n    // Keep in sync with DllType in MonoEditorUtility.h\n    public enum DllType\n    {\n        Unknown = 0,\n        Native = 1,\n        UnknownManaged = 2,\n        ManagedNET35 = 3,\n        ManagedNET40 = 4,\n        WinMDNative = 5,\n        WinMDNET40 = 6\n    }\n\n    [RequiredByNativeCode]\n    internal class LoadFileAndForgetOperationHelper\n    {\n        // When the load operation completes this is invoked to hold the result so that it doesn't\n        // get garbage collected\n        [RequiredByNativeCode]\n        public static void SetObjectResult(LoadFileAndForgetOperation op, UnityEngine.Object result)\n        {\n            op.m_ObjectReference = result;\n        }\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    [RequiredByNativeCode]\n    public class LoadFileAndForgetOperation : AsyncOperation\n    {\n        internal UnityEngine.Object m_ObjectReference;\n\n        public extern UnityEngine.Object Result\n        {\n            [NativeMethod(\"GetRequestedObject\")]\n            get;\n        }\n\n        public LoadFileAndForgetOperation() { }\n\n        private LoadFileAndForgetOperation(IntPtr ptr) : base(ptr) { }\n\n        new internal static class BindingsMarshaller\n        {\n            public static LoadFileAndForgetOperation ConvertToManaged(IntPtr ptr) => new LoadFileAndForgetOperation(ptr);\n            public static IntPtr ConvertToNative(LoadFileAndForgetOperation asyncOperation) => asyncOperation.m_Ptr;\n        }\n    }\n\n    [NativeHeader(\"Editor/Src/InternalEditorUtility.bindings.h\")]\n\n    [NativeHeader(\"Editor/Mono/MonoEditorUtility.h\")]\n    [NativeHeader(\"Editor/Platform/Interface/ColorPicker.h\")]\n    [NativeHeader(\"Editor/Platform/Interface/EditorUtility.h\")]\n    [NativeHeader(\"Editor/Src/Application/Application.h\")]\n    [NativeHeader(\"Modules/AssetDatabase/Editor/Public/AssetDatabase.h\")]\n    [NativeHeader(\"Modules/AssetDatabase/Editor/Public/AssetDatabaseDeprecated.h\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/TextureImporting/BumpMapSettings.h\")]\n    [NativeHeader(\"Editor/Src/ScriptCompilation/PrecompiledAssemblies.h\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/ObjectHashGenerator.h\")]\n    [NativeHeader(\"Editor/Src/AssetPipeline/UnityExtensions.h\")]\n    [NativeHeader(\"Editor/Src/Windowing/AuxWindowManager.h\")]\n    [NativeHeader(\"Editor/Src/DisplayDialog.h\")]\n    [NativeHeader(\"Editor/Src/DragAndDropForwarding.h\")]\n    [NativeHeader(\"Editor/Src/EditorHelper.h\")]\n    [NativeHeader(\"Editor/Src/EditorUserBuildSettings.h\")]\n    [NativeHeader(\"Editor/Src/EditorWindowController.h\")]\n    [NativeHeader(\"Editor/Src/EditorModules.h\")]\n    [NativeHeader(\"Editor/Src/Gizmos/GizmoUtil.h\")]\n    [NativeHeader(\"Editor/Src/HierarchyState.h\")]\n    [NativeHeader(\"Editor/Src/InspectorExpandedState.h\")]\n    [NativeHeader(\"Editor/Src/LoadFileAndForgetOperation.h\")]\n    [NativeHeader(\"Runtime/Interfaces/ILicensing.h\")]\n    [NativeHeader(\"Editor/Src/RemoteInput/RemoteInput.h\")]\n    [NativeHeader(\"Editor/Src/ShaderMenu.h\")]\n    [NativeHeader(\"Editor/Src/Undo/ObjectUndo.h\")]\n    [NativeHeader(\"Modules/AssetDatabase/Editor/Public/AssetDatabaseProperty.h\")]\n    [NativeHeader(\"Editor/Src/Utility/CustomLighting.h\")]\n    [NativeHeader(\"Editor/Src/Utility/DiffTool.h\")]\n    [NativeHeader(\"Editor/Src/Utility/GameObjectHierarchyProperty.h\")]\n    [NativeHeader(\"Runtime/BaseClasses/TagManager.h\")]\n    [NativeHeader(\"Runtime/Camera/Camera.h\")]\n    [NativeHeader(\"Runtime/Camera/RenderManager.h\")]\n    [NativeHeader(\"Runtime/Camera/RenderSettings.h\")]\n    [NativeHeader(\"Runtime/Camera/Skybox.h\")]\n    [NativeHeader(\"Runtime/Transform/RectTransform.h\")]\n    [NativeHeader(\"Runtime/Graphics/Renderer.h\")]\n    [NativeHeader(\"Runtime/Graphics/ScreenManager.h\")]\n    [NativeHeader(\"Runtime/Graphics/SpriteFrame.h\")]\n    [NativeHeader(\"Runtime/2D/Common/SpriteTypes.h\")]\n    [NativeHeader(\"Runtime/Graphics/GraphicsHelper.h\")]\n    [NativeHeader(\"Runtime/Graphics/GpuDeviceManager.h\")]\n    [NativeHeader(\"Runtime/Input/Cursor.h\")]\n    [NativeHeader(\"Runtime/Misc/GameObjectUtility.h\")]\n    [NativeHeader(\"Runtime/Misc/Player.h\")]\n    [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n    [NativeHeader(\"Runtime/Serialize/PersistentManager.h\")]\n    [NativeHeader(\"Runtime/Shaders/ShaderImpl/FastPropertyName.h\")]\n    [NativeHeader(\"Runtime/Serialize/PersistentManager.h\")]\n    [NativeHeader(\"Runtime/Threads/ThreadChecks.h\")]\n    [NativeHeader(\"Runtime/Utilities/Word.h\")]\n    [NativeHeader(\"Editor/Src/BuildPipeline/BuildPlayer.h\")]\n    [NativeHeader(\"Editor/Src/BuildPipeline/BuildTargetPlatformSpecific.h\")]\n    [NativeHeader(\"Runtime/Utilities/Argv.h\")]\n    [NativeHeader(\"Runtime/Utilities/FileUtilities.h\")]\n    [NativeHeader(\"Runtime/Utilities/LaunchUtilities.h\")]\n    [NativeHeader(\"Runtime/Utilities/UnityConfiguration.h\")]\n    [NativeHeader(\"Runtime/Utilities/UnityGitConfiguration.h\")]\n    public partial class InternalEditorUtility\n    {\n        public extern static bool isHumanControllingUs\n        {\n            [FreeFunction(\"IsHumanControllingUs\")]\n            get;\n        }\n\n        public extern static bool isApplicationActive\n        {\n            [FreeFunction(\"IsApplicationActive\")]\n            get;\n        }\n\n        public extern static bool inBatchMode\n        {\n            [FreeFunction(\"IsBatchmode\")]\n            get;\n        }\n\n        [StaticAccessor(\"BumpMapSettings::Get()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"PerformUnmarkedBumpMapTexturesFixingAfterDialog\")]\n        public extern static void BumpMapSettingsFixingWindowReportResult(int result);\n\n        [StaticAccessor(\"BumpMapSettings::Get()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"PerformUnmarkedBumpMapTexturesFixing\")]\n        public extern static bool PerformUnmarkedBumpMapTexturesFixing();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::BumpMapTextureNeedsFixingInternal\")]\n        public extern static bool BumpMapTextureNeedsFixingInternal([NotNull] Material material, string propName, bool flaggedAsNormal);\n\n        internal static bool BumpMapTextureNeedsFixing(MaterialProperty prop)\n        {\n            if (prop.propertyType != ShaderPropertyType.Texture)\n                return false;\n\n            bool hintIfNormal = ((prop.propertyFlags & ShaderPropertyFlags.Normal) != 0);\n\n            foreach (Material material in prop.targets)\n                if (BumpMapTextureNeedsFixingInternal(material, prop.name, hintIfNormal))\n                    return true;\n\n            return false;\n        }\n\n        [FreeFunction(\"InternalEditorUtilityBindings::FixNormalmapTextureInternal\")]\n        public extern static void FixNormalmapTextureInternal([NotNull] Material material, string propName);\n\n        internal static void FixNormalmapTexture(MaterialProperty prop)\n        {\n            foreach (Material material in prop.targets)\n                FixNormalmapTextureInternal(material, prop.name);\n        }\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetEditorAssemblyPath\")]\n        public extern static string GetEditorAssemblyPath();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetEngineAssemblyPath\")]\n        public extern static string GetEngineAssemblyPath();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetEngineCoreModuleAssemblyPath\")]\n        public extern static string GetEngineCoreModuleAssemblyPath();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetBuildSystemVariationArgs\")]\n        internal extern static string GetBuildSystemVariationArgs();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::CalculateHashForObjectsAndDependencies\")]\n        public extern static string CalculateHashForObjectsAndDependencies(Object[] objects);\n\n        [FreeFunction]\n        public extern static void ExecuteCommandOnKeyWindow(string commandName);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::InstantiateMaterialsInEditMode\")]\n        public extern static Material[] InstantiateMaterialsInEditMode([NotNull] Renderer renderer);\n\n        [System.Obsolete(\"BuildCanBeAppended has been deprecated. Use UnityEditor.BuildPipeline.BuildCanBeAppended instead (UnityUpgradable) -> [UnityEditor] UnityEditor.BuildPipeline.BuildCanBeAppended(*)\", true)]\n        public static CanAppendBuild BuildCanBeAppended(BuildTarget target, string location)\n        {\n            return (CanAppendBuild)BuildPipeline.BuildCanBeAppended(target, location);\n        }\n\n        [FreeFunction]\n        extern internal static void RegisterPlatformModuleAssembly(string dllName, string dllLocation);\n\n        [FreeFunction]\n        extern internal static void RegisterPrecompiledAssembly(string dllName, string dllLocation);\n\n        // This lets you add a MonoScript to a game object directly without any type checks or requiring the .NET representation to be loaded already.\n        [FreeFunction(\"InternalEditorUtilityBindings::AddScriptComponentUncheckedUndoable\")]\n        extern internal static int AddScriptComponentUncheckedUndoable([NotNull] GameObject gameObject, [NotNull] MonoScript script);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::CreateScriptableObjectUnchecked\")]\n        extern internal static int CreateScriptableObjectUnchecked(MonoScript script);\n\n        [Obsolete(\"RequestScriptReload has been deprecated. Use UnityEditor.EditorUtility.RequestScriptReload instead (UnityUpgradable) -> [UnityEditor] UnityEditor.EditorUtility.RequestScriptReload(*)\")]\n        public static void RequestScriptReload()\n        {\n            EditorUtility.RequestScriptReload();\n        }\n\n        // Repaint all views on next tick. Used when the user changes skins in the prefs.\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"SwitchSkinAndRepaintAllViews\")]\n        extern public static void SwitchSkinAndRepaintAllViews();\n\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        extern internal static bool IsSwitchSkinRequested();\n\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"RequestRepaintAllViews\")]\n        extern public static void RepaintAllViews();\n\n        [StaticAccessor(\"GetInspectorExpandedState()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"IsInspectorExpanded\")]\n        extern public static bool GetIsInspectorExpanded(Object obj);\n\n        [StaticAccessor(\"GetInspectorExpandedState()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"SetInspectorExpanded\")]\n        extern public static void SetIsInspectorExpanded(Object obj, bool isExpanded);\n\n        extern public static int[] expandedProjectWindowItems\n        {\n            [StaticAccessor(\"AssetDatabase::GetProjectWindowHierarchyState()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"GetExpandedArray\")]\n            get;\n            [FreeFunction(\"InternalEditorUtilityBindings::SetExpandedProjectWindowItems\")]\n            set;\n        }\n\n        public static Assembly LoadAssemblyWrapper(string dllName, string dllLocation)\n        {\n            return (Assembly)LoadAssemblyWrapperInternal(dllName, dllLocation);\n        }\n\n        [StaticAccessor(\"GetMonoManager()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"LoadAssembly\")]\n        extern internal static object LoadAssemblyWrapperInternal(string dllName, string dllLocation);\n\n        public static void SaveToSerializedFileAndForget(Object[] obj, string path, bool allowTextSerialization)\n        {\n            SaveToSerializedFileAndForgetInternal(path, obj, allowTextSerialization);\n        }\n\n        [FreeFunction(\"SaveToSerializedFileAndForget\")]\n        extern private static void SaveToSerializedFileAndForgetInternal(string path, Object[] obj, bool allowTextSerialization);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::LoadSerializedFileAndForget\")]\n        extern public static Object[] LoadSerializedFileAndForget(string path);\n\n        [FreeFunction(\"LoadFileAndForgetOperation::LoadSerializedFileAndForgetAsync\")]\n        extern public static LoadFileAndForgetOperation LoadSerializedFileAndForgetAsync(string path, long localIdentifierInFile, ulong offsetInFile=0, long fileSize=-1, Scene destScene = default);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::ProjectWindowDrag\")]\n        extern public static DragAndDropVisualMode ProjectWindowDrag([Unmarshalled] HierarchyProperty property, bool perform);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::HierarchyWindowDrag\")]\n        extern public static DragAndDropVisualMode HierarchyWindowDrag([Unmarshalled] HierarchyProperty property, HierarchyDropFlags dropMode, Transform parentForDraggedObjects, bool perform);\n\n        public static DragAndDropVisualMode HierarchyWindowDragByID(int dropTargetInstanceID, HierarchyDropFlags dropMode, Transform parentForDraggedObjects, bool perform)\n            => HierarchyWindowDragByID(dropTargetInstanceID, GOCreationCommands.GetNewObjectPosition(), dropMode, parentForDraggedObjects, perform);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::HierarchyWindowDragByID\")]\n        extern internal static DragAndDropVisualMode HierarchyWindowDragByID(int dropTargetInstanceID, Vector3 worldPosition, HierarchyDropFlags dropMode, Transform parentForDraggedObjects, bool perform);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::InspectorWindowDrag\")]\n        extern internal static DragAndDropVisualMode InspectorWindowDrag(Object[] targets, bool perform);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::SceneViewDrag\")]\n        extern public static DragAndDropVisualMode SceneViewDrag(Object dropUpon, Vector3 worldPosition, Vector2 viewportPosition, Transform parentForDraggedObjects, bool perform);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::SetRectTransformTemporaryRect\")]\n        extern public static void SetRectTransformTemporaryRect([NotNull] RectTransform rectTransform, Rect rect);\n\n        [Obsolete(\"HasTeamLicense always returns true, no need to call it\")]\n        public static bool HasTeamLicense() { return true; }\n\n        [FreeFunction(\"InternalEditorUtilityBindings::HasPro\", IsThreadSafe = true)]\n        extern public static bool HasPro();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::HasFreeLicense\", IsThreadSafe = true)]\n        extern public static bool HasFreeLicense();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::HasEduLicense\", IsThreadSafe = true)]\n        extern public static bool HasEduLicense();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::HasUFSTLicense\", IsThreadSafe = true)]\n        extern internal static bool HasUFSTLicense();\n\n        [FreeFunction]\n        extern public static bool HasAdvancedLicenseOnBuildTarget(BuildTarget target);\n\n        public static bool IsMobilePlatform(BuildTarget target)\n        {\n            return BuildTargetDiscovery.PlatformHasFlag(target, TargetAttributes.HasIntegratedGPU);\n        }\n\n        [NativeThrows]\n        [FreeFunction(\"InternalEditorUtilityBindings::GetBoundsOfDesktopAtPoint\")]\n        extern public static Rect GetBoundsOfDesktopAtPoint(Vector2 pos);\n\n        [StaticAccessor(\"GetTagManager()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"RemoveTag\")]\n        extern public static void RemoveTag(string tag);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::AddTag\")]\n        extern public static void AddTag(string tag);\n\n        extern public static string[] tags\n        {\n            [FreeFunction(\"InternalEditorUtilityBindings::GetTags\")]\n            get;\n        }\n\n        extern public static string[] layers\n        {\n            [FreeFunction(\"InternalEditorUtilityBindings::GetLayers\")]\n            get;\n        }\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetLayersWithId\")]\n        extern static internal string[] GetLayersWithId();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::CanRenameAssetInternal\")]\n        extern internal static bool CanRenameAsset(int instanceID);\n\n        public static LayerMask ConcatenatedLayersMaskToLayerMask(int concatenatedLayersMask)\n        {\n            return ConcatenatedLayersMaskToLayerMaskInternal(concatenatedLayersMask);\n        }\n\n        [FreeFunction(\"InternalEditorUtilityBindings::ConcatenatedLayersMaskToLayerMaskInternal\")]\n        extern private static int ConcatenatedLayersMaskToLayerMaskInternal(int concatenatedLayersMask);\n\n        [FreeFunction(\"TryOpenErrorFileFromConsole\")]\n        public extern static bool TryOpenErrorFileFromConsole(string path, int line, int column);\n\n        [FreeFunction(\"TryOpenErrorFileFromConsoleInternal\")]\n        internal extern static bool TryOpenErrorFileFromConsoleInternal(string path, int line, int column, bool isDryRun);\n\n        public static bool TryOpenErrorFileFromConsole(string path, int line)\n        {\n            return TryOpenErrorFileFromConsole(path, line, 0);\n        }\n\n        public static int LayerMaskToConcatenatedLayersMask(LayerMask mask)\n        {\n            return LayerMaskToConcatenatedLayersMaskInternal(mask);\n        }\n\n        [StaticAccessor(\"GetTagManager()\", StaticAccessorType.Dot)]\n        extern internal static string GetSortingLayerName(int index);\n\n        [StaticAccessor(\"GetTagManager()\", StaticAccessorType.Dot)]\n        extern internal static int GetSortingLayerUniqueID(int index);\n\n        [StaticAccessor(\"GetTagManager()\", StaticAccessorType.Dot)]\n        extern internal static string GetSortingLayerNameFromUniqueID(int id);\n\n        [StaticAccessor(\"GetTagManager()\", StaticAccessorType.Dot)]\n        extern internal static int GetSortingLayerCount();\n\n        [StaticAccessor(\"GetTagManager()\", StaticAccessorType.Dot)]\n        extern internal static void SetSortingLayerName(int index, string name);\n\n        [StaticAccessor(\"GetTagManager()\", StaticAccessorType.Dot)]\n        extern internal static void SetSortingLayerLocked(int index, bool locked);\n\n        [StaticAccessor(\"GetTagManager()\", StaticAccessorType.Dot)]\n        extern internal static bool GetSortingLayerLocked(int index);\n\n        [StaticAccessor(\"GetTagManager()\", StaticAccessorType.Dot)]\n        extern internal static bool IsSortingLayerDefault(int index);\n\n        [StaticAccessor(\"GetTagManager()\", StaticAccessorType.Dot)]\n        extern internal static void AddSortingLayer();\n\n        [StaticAccessor(\"GetTagManager()\", StaticAccessorType.Dot)]\n        extern internal static void UpdateSortingLayersOrder();\n\n        extern internal static string[] sortingLayerNames\n        {\n            [FreeFunction(\"InternalEditorUtilityBindings::GetSortingLayerNames\")]\n            get;\n        }\n\n        extern internal static int[] sortingLayerUniqueIDs\n        {\n            [FreeFunction(\"InternalEditorUtilityBindings::GetSortingLayerUniqueIDs\")]\n            get;\n        }\n\n        // UV coordinates for the outer part of a sliced Sprite (the whole Sprite)\n        [FreeFunction(\"InternalEditorUtilityBindings::GetSpriteOuterUV\")]\n        extern public static Vector4 GetSpriteOuterUV([NotNull] Sprite sprite, bool getAtlasData);\n\n        [FreeFunction(\"PPtr<Object>::FromInstanceID\")]\n        extern public static Object GetObjectFromInstanceID(int instanceID);\n\n        [FreeFunction(\"GetTypeWithoutLoadingObject\")]\n        extern public static Type GetTypeWithoutLoadingObject(int instanceID);\n\n        [FreeFunction(\"Object::IDToPointer\")]\n        extern public static Object GetLoadedObjectFromInstanceID(int instanceID);\n\n        [StaticAccessor(\"GetTagManager()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"LayerToString\")]\n        extern public static string GetLayerName(int layer);\n\n        extern public static string unityPreferencesFolder\n        {\n            [FreeFunction]\n            get;\n        }\n\n        internal static extern string userAppDataFolder\n        {\n            [FreeFunction(\"GetUserAppDataFolder\")]\n            get;\n        }\n\n        [FreeFunction]\n        extern public static string GetAssetsFolder();\n\n        [FreeFunction]\n        extern public static string GetEditorFolder();\n\n        [FreeFunction]\n        extern public static bool IsInEditorFolder(string path);\n\n        public static void ReloadWindowLayoutMenu()\n        {\n            WindowLayout.UpdateWindowLayoutMenu();\n        }\n\n        public static void RevertFactoryLayoutSettings(bool quitOnCancel)\n        {\n            WindowLayout.ResetAllLayouts(quitOnCancel);\n        }\n\n        public static void LoadDefaultLayout()\n        {\n            WindowLayout.LoadDefaultLayout();\n        }\n\n        [StaticAccessor(\"GetRenderSettings()\", StaticAccessorType.Dot)]\n        extern internal static void CalculateAmbientProbeFromSkybox();\n\n        [Obsolete(\"SetupShaderMenu is obsolete. You can get list of available shaders with ShaderUtil.GetAllShaderInfos\", true)]\n        public static void SetupShaderMenu(Material material) {}\n\n        [FreeFunction(\"UnityConfig::GetUnityBuildFullVersion\")]\n        extern public static string GetFullUnityVersion();\n\n        public static Version GetUnityVersion()\n        {\n            Version version = new Version(GetUnityVersionDigits());\n            return new Version(version.Major, version.Minor, version.Build, GetUnityRevision());\n        }\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetUnityVersionDigits\")]\n        extern public static string GetUnityVersionDigits();\n\n        [FreeFunction(\"UnityConfig::GetUnityBuildBranchName\")]\n        extern public static string GetUnityBuildBranch();\n\n        [FreeFunction(\"UnityConfig::GetUnityBuildHash\")]\n        extern public static string GetUnityBuildHash();\n\n        [FreeFunction(\"UnityConfig::GetUnityDisplayVersion\")]\n        extern public static string GetUnityDisplayVersion();\n\n        [FreeFunction(\"UnityConfig::GetUnityDisplayVersionVerbose\")]\n        extern public static string GetUnityDisplayVersionVerbose();\n\n        [FreeFunction(\"UnityConfig::GetUnityBuildTimeSinceEpoch\")]\n        extern public static int GetUnityVersionDate();\n\n        [FreeFunction(\"UnityConfig::GetUnityBuildNumericRevision\")]\n        extern public static int GetUnityRevision();\n\n        [FreeFunction(\"UnityConfig::GetUnityProductName\")]\n        extern public static string GetUnityProductName();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::IsUnityBeta\")]\n        extern public static bool IsUnityBeta();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetUnityCopyright\")]\n        extern public static string GetUnityCopyright();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetLicenseInfoText\")]\n        extern public static string GetLicenseInfo();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetLicenseInfoTypeText\")]\n        extern internal static string GetLicenseInfoType();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetLicenseInfoSerialText\")]\n        extern internal static string GetLicenseInfoSerial();\n\n        [Obsolete(\"GetLicenseFlags is no longer supported\", error: true)]\n        [FreeFunction(\"InternalEditorUtilityBindings::GetLicenseFlags\")]\n        extern public static int[] GetLicenseFlags();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetAuthToken\")]\n        extern public static string GetAuthToken();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::OpenEditorConsole\")]\n        extern public static void OpenEditorConsole();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetGameObjectInstanceIDFromComponent\")]\n        extern public static int GetGameObjectInstanceIDFromComponent(int instanceID);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::ReadScreenPixel\")]\n        extern public static Color[] ReadScreenPixel(Vector2 pixelPos, int sizex, int sizey);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::ReadScreenPixelUnderCursor\")]\n        extern public static Color[] ReadScreenPixelUnderCursor(Vector2 cursorPosHint, int sizex, int sizey);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::IsAllowedToReadPixelOutsideUnity\")]\n        extern internal static bool IsAllowedToReadPixelOutsideUnity(out string errorMessage);\n\n        [StaticAccessor(\"GetGpuDeviceManager()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"SetDevice\")]\n        extern public static void SetGpuDeviceAndRecreateGraphics(int index, string name);\n\n        [StaticAccessor(\"GetGpuDeviceManager()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"IsSupported\")]\n        extern public static bool IsGpuDeviceSelectionSupported();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetGpuDevices\")]\n        extern public static string[] GetGpuDevices();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::OpenPlayerConsole\")]\n        extern public static void OpenPlayerConsole();\n\n        public static string TextifyEvent(Event evt)\n        {\n            if (evt == null)\n                return \"none\";\n\n            string text = null;\n\n            switch (evt.keyCode)\n            {\n                case KeyCode.Keypad0: text = \"[0]\"; break;\n                case KeyCode.Keypad1: text = \"[1]\"; break;\n                case KeyCode.Keypad2: text = \"[2]\"; break;\n                case KeyCode.Keypad3: text = \"[3]\"; break;\n                case KeyCode.Keypad4: text = \"[4]\"; break;\n                case KeyCode.Keypad5: text = \"[5]\"; break;\n                case KeyCode.Keypad6: text = \"[6]\"; break;\n                case KeyCode.Keypad7: text = \"[7]\"; break;\n                case KeyCode.Keypad8: text = \"[8]\"; break;\n                case KeyCode.Keypad9: text = \"[9]\"; break;\n                case KeyCode.KeypadPeriod: text = \"[.]\"; break;\n                case KeyCode.KeypadDivide: text = \"[/]\"; break;\n                case KeyCode.KeypadMinus: text = \"[-]\"; break;\n                case KeyCode.KeypadPlus: text = \"[+]\"; break;\n                case KeyCode.KeypadEquals: text = \"[=]\"; break;\n\n                case KeyCode.KeypadEnter: text = \"enter\"; break;\n                case KeyCode.UpArrow: text = \"up\"; break;\n                case KeyCode.DownArrow: text = \"down\"; break;\n                case KeyCode.LeftArrow: text = \"left\"; break;\n                case KeyCode.RightArrow: text = \"right\"; break;\n\n                case KeyCode.Insert: text = \"insert\"; break;\n                case KeyCode.Home: text = \"home\"; break;\n                case KeyCode.End: text = \"end\"; break;\n                case KeyCode.PageUp: text = \"page up\"; break;\n                case KeyCode.PageDown: text = \"page down\"; break;\n\n                case KeyCode.Backspace: text = \"backspace\"; break;\n                case KeyCode.Delete: text = \"delete\"; break;\n\n                case KeyCode.F1: text = \"F1\"; break;\n                case KeyCode.F2: text = \"F2\"; break;\n                case KeyCode.F3: text = \"F3\"; break;\n                case KeyCode.F4: text = \"F4\"; break;\n                case KeyCode.F5: text = \"F5\"; break;\n                case KeyCode.F6: text = \"F6\"; break;\n                case KeyCode.F7: text = \"F7\"; break;\n                case KeyCode.F8: text = \"F8\"; break;\n                case KeyCode.F9: text = \"F9\"; break;\n                case KeyCode.F10: text = \"F10\"; break;\n                case KeyCode.F11: text = \"F11\"; break;\n                case KeyCode.F12: text = \"F12\"; break;\n                case KeyCode.F13: text = \"F13\"; break;\n                case KeyCode.F14: text = \"F14\"; break;\n                case KeyCode.F15: text = \"F15\"; break;\n                case KeyCode.F16: text = \"F16\"; break;\n                case KeyCode.F17: text = \"F17\"; break;\n                case KeyCode.F18: text = \"F18\"; break;\n                case KeyCode.F19: text = \"F19\"; break;\n                case KeyCode.F20: text = \"F20\"; break;\n                case KeyCode.F21: text = \"F21\"; break;\n                case KeyCode.F22: text = \"F22\"; break;\n                case KeyCode.F23: text = \"F23\"; break;\n                case KeyCode.F24: text = \"F24\"; break;\n\n\n                case KeyCode.Escape: text = \"[esc]\"; break;\n                case KeyCode.Return: text = \"return\"; break;\n\n                default: text = \"\" + evt.keyCode; break;\n            }\n\n            string modifiers = string.Empty;\n            if (evt.alt)        modifiers += \"Alt+\";\n            if (evt.command)    modifiers += Application.platform == RuntimePlatform.OSXEditor ? \"Cmd+\" : \"Ctrl+\";\n            if (evt.control)    modifiers += \"Ctrl+\";\n            if (evt.shift)      modifiers += \"Shift+\";\n\n            return modifiers + text;\n        }\n\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        [NativeProperty(\"defaultScreenWidth\", TargetType.Field)]\n        extern public static float defaultScreenWidth\n        {\n            get;\n        }\n\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        [NativeProperty(\"defaultScreenHeight\", TargetType.Field)]\n        extern public static float defaultScreenHeight\n        {\n            get;\n        }\n\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        [NativeProperty(\"defaultWebScreenWidth\", TargetType.Field)]\n        extern public static float defaultWebScreenWidth\n        {\n            get;\n        }\n\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        [NativeProperty(\"defaultWebScreenHeight\", TargetType.Field)]\n        extern public static float defaultWebScreenHeight\n        {\n            get;\n        }\n\n        extern public static float remoteScreenWidth\n        {\n            [FreeFunction(\"RemoteScreenWidth\")]\n            get;\n        }\n\n        extern public static float remoteScreenHeight\n        {\n            [FreeFunction(\"RemoteScreenHeight\")]\n            get;\n        }\n\n        [FreeFunction]\n        extern public static string[] GetAvailableDiffTools();\n\n        [FreeFunction]\n        extern public static string GetNoDiffToolsDetectedMessage();\n\n        [FreeFunction(\"SetCustomDiffToolData\")]\n        extern internal static void SetCustomDiffToolData(string  path, string diff2Command, string diff3Command, string mergeCommand);\n\n        [FreeFunction(\"SetCustomDiffToolPrefs\")]\n        extern internal static void SetCustomDiffToolPrefs(string  path, string diff2Command, string diff3Command, string mergeCommand);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::TransformBounds\")]\n        extern public static Bounds TransformBounds(Bounds b, Transform t);\n\n        [StaticAccessor(\"CustomLighting::Get()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"SetCustomLighting\")]\n        extern public static void SetCustomLightingInternal([Unmarshalled] Light[] lights, Color ambient);\n\n        public static void SetCustomLighting(Light[] lights, Color ambient)\n        {\n            if (lights == null)\n                throw new System.ArgumentNullException(\"lights\");\n\n            SetCustomLightingInternal(lights, ambient);\n        }\n\n        [StaticAccessor(\"CustomLighting::Get()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"RestoreSceneLighting\")]\n        extern public static void RemoveCustomLighting();\n\n        [StaticAccessor(\"GetRenderManager()\", StaticAccessorType.Dot)]\n        extern public static bool HasFullscreenCamera();\n\n        public static Bounds CalculateSelectionBounds(bool usePivotOnlyForParticles)\n        {\n            return CalculateSelectionBounds(usePivotOnlyForParticles, false, false);\n        }\n\n        public static Bounds CalculateSelectionBounds(bool usePivotOnlyForParticles, bool onlyUseActiveSelection)\n        {\n            return CalculateSelectionBounds(usePivotOnlyForParticles, onlyUseActiveSelection, false);\n        }\n\n        [FreeFunction]\n        extern public static Bounds CalculateSelectionBounds(bool usePivotOnlyForParticles, bool onlyUseActiveSelection, bool ignoreEditableField);\n\n        internal static Bounds CalculateSelectionBoundsInSpace(Vector3 position, Quaternion rotation, bool rectBlueprintMode)\n        {\n            Quaternion inverseRotation = Quaternion.Inverse(rotation);\n            Vector3 min = new Vector3(float.MaxValue - 1f, float.MaxValue - 1f, float.MaxValue - 1f);\n            Vector3 max = new Vector3(float.MinValue + 1f, float.MinValue + 1f, float.MinValue + 1f);\n\n            Vector3[] minmax = new Vector3[2];\n            foreach (GameObject gameObject in Selection.gameObjects)\n            {\n                Bounds localBounds = GetLocalBounds(gameObject);\n                minmax[0] = localBounds.min;\n                minmax[1] = localBounds.max;\n                for (int x = 0; x < 2; x++)\n                {\n                    for (int y = 0; y < 2; y++)\n                    {\n                        for (int z = 0; z < 2; z++)\n                        {\n                            Vector3 point = new Vector3(minmax[x].x, minmax[y].y, minmax[z].z);\n                            if (rectBlueprintMode && SupportsRectLayout(gameObject.transform))\n                            {\n                                Vector3 localPosXY = gameObject.transform.localPosition;\n                                localPosXY.z = 0;\n                                point = gameObject.transform.parent.TransformPoint(point + localPosXY);\n                            }\n                            else\n                            {\n                                point = gameObject.transform.TransformPoint(point);\n                            }\n\n                            point = inverseRotation * (point - position);\n\n                            for (int axis = 0; axis < 3; axis++)\n                            {\n                                min[axis] = Mathf.Min(min[axis], point[axis]);\n                                max[axis] = Mathf.Max(max[axis], point[axis]);\n                            }\n                        }\n                    }\n                }\n            }\n\n            return new Bounds((min + max) * 0.5f, max - min);\n        }\n\n        internal static bool SupportsRectLayout(Transform tr)\n        {\n            if (tr == null || tr.parent == null)\n                return false;\n            if (tr.GetComponent<RectTransform>() == null || tr.parent.GetComponent<RectTransform>() == null)\n                return false;\n            return true;\n        }\n\n        private static Bounds GetLocalBounds(GameObject gameObject)\n        {\n            if (gameObject.TryGetComponent(out RectTransform rectTransform))\n                return new Bounds(rectTransform.rect.center, rectTransform.rect.size);\n\n            // Account for case where there is a mesh filter but no renderer\n            if (gameObject.TryGetComponent(out MeshFilter filter) && filter.sharedMesh != null)\n                return filter.sharedMesh.bounds;\n\n            if (gameObject.TryGetComponent(out Renderer renderer))\n            {\n                if (renderer is SpriteRenderer)\n                    return ((SpriteRenderer)renderer).GetSpriteBounds();\n\n                if (renderer is SpriteMask)\n                    return ((SpriteMask)renderer).GetSpriteBounds();\n\n                if (renderer is UnityEngine.U2D.SpriteShapeRenderer)\n                    return ((UnityEngine.U2D.SpriteShapeRenderer)renderer).GetLocalAABB();\n\n                if (renderer is UnityEngine.Tilemaps.TilemapRenderer && renderer.TryGetComponent(out UnityEngine.Tilemaps.Tilemap tilemap))\n                    return tilemap.localBounds;\n            }\n\n            return new Bounds(Vector3.zero, Vector3.zero);\n        }\n\n        [FreeFunction(\"SetPlayerFocus\")]\n        extern public static void OnGameViewFocus(bool focus);\n\n        [FreeFunction(\"OpenScriptFile\")]\n        extern public static bool OpenFileAtLineExternal(string filename, int line, int column);\n\n        public static bool OpenFileAtLineExternal(string filename, int line)\n        {\n            if (!CodeEditor.Editor.CurrentCodeEditor.OpenProject(filename, line))\n            {\n                return OpenFileAtLineExternal(filename, line, 0);\n            }\n            return true;\n        }\n\n        [FreeFunction(\"AssetDatabaseDeprecated::CanConnectToCacheServer\")]\n        extern public static bool CanConnectToCacheServer();\n\n        [FreeFunction]\n        extern public static DllType DetectDotNetDll(string path);\n\n        [FreeFunction]\n        internal static extern bool IsDotNetDll(string path);\n\n        public static bool IsDotNet4Dll(string path)\n        {\n            var dllType = DetectDotNetDll(path);\n            switch (dllType)\n            {\n                case UnityEditorInternal.DllType.Unknown:\n                case UnityEditorInternal.DllType.Native:\n                case UnityEditorInternal.DllType.UnknownManaged:\n                case UnityEditorInternal.DllType.ManagedNET35:\n                    return false;\n                case UnityEditorInternal.DllType.ManagedNET40:\n                case UnityEditorInternal.DllType.WinMDNative:\n                case UnityEditorInternal.DllType.WinMDNET40:\n                    return true;\n                default:\n                    throw new Exception(string.Format(\"Unknown dll type: {0}\", dllType));\n            }\n        }\n\n        internal static bool RunningUnderWindows8(bool orHigher = true)\n        {\n            if (Application.platform == RuntimePlatform.WindowsEditor)\n            {\n                OperatingSystem sys = System.Environment.OSVersion;\n                int major = sys.Version.Major;\n                int minor = sys.Version.Minor;\n                // Window 8 is technically version 6.2\n                if (orHigher)\n                    return major > 6 || (major == 6 && minor >= 2);\n                else\n                    return major == 6 && minor == 2;\n            }\n            return false;\n        }\n\n        [FreeFunction(\"UnityExtensions::IsValidExtensionPath\")]\n        extern internal static bool IsValidUnityExtensionPath(string path);\n\n        [StaticAccessor(\"UnityExtensions::Get()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"IsRegistered\")]\n        extern internal static bool IsUnityExtensionRegistered(string filename);\n\n        [StaticAccessor(\"UnityExtensions::Get()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"IsCompatibleWithEditor\")]\n        extern internal static bool IsUnityExtensionCompatibleWithEditor(BuildTarget target, string path);\n\n        [FreeFunction(IsThreadSafe = true)]\n        extern public static bool CurrentThreadIsMainThread();\n\n        // Internal property to check if the currently selected Assets can be renamed, used to unify rename logic between native and c#\n        extern internal static bool canRenameSelectedAssets\n        {\n            [FreeFunction(\"CanRenameSelectedAssets\")]\n            get;\n        }\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetCrashReportFolder\")]\n        extern public static string GetCrashReportFolder();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::GetCrashHandlerProcessID\")]\n        extern public static UInt32 GetCrashHandlerProcessID();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::DrawSkyboxMaterial\")]\n        extern internal static void DrawSkyboxMaterial([NotNull] Material mat, [NotNull] Camera cam);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::ResetCursor\")]\n        extern public static void ResetCursor();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::VerifyCacheServerIntegrity\")]\n        extern public static UInt64 VerifyCacheServerIntegrity();\n\n        [FreeFunction(\"InternalEditorUtilityBindings::FixCacheServerIntegrityErrors\")]\n        extern public static UInt64 FixCacheServerIntegrityErrors();\n\n        [FreeFunction]\n        extern public static int DetermineDepthOrder(Transform lhs, Transform rhs);\n\n\n        internal static PrecompiledAssembly[] GetUnityAssemblies(bool buildingForEditor, BuildTarget target)\n        {\n            return GetUnityAssembliesInternal(buildingForEditor, target);\n        }\n\n        [FreeFunction(\"GetUnityAssembliesManaged\")]\n        extern private static PrecompiledAssembly[] GetUnityAssembliesInternal(bool buildingForEditor, BuildTarget target);\n\n        [FreeFunction(\"GetPrecompiledAssemblyPathsManaged\")]\n        extern internal static string[] GetPrecompiledAssemblyPaths();\n\n        [FreeFunction(\"GetEditorAssembliesPath\")]\n        extern internal static string GetEditorScriptAssembliesPath();\n\n        [Obsolete(\"The Module Manager is deprecated\", error: true)]\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public static void ShowPackageManagerWindow() { throw new NotSupportedException(\"The Module Manager is deprecated\"); }\n\n        // For testing Vector2 marshalling\n        [FreeFunction(\"InternalEditorUtilityBindings::PassAndReturnVector2\")]\n        extern public static Vector2 PassAndReturnVector2(Vector2 v);\n\n        // For testing Color32 marshalling\n        [FreeFunction(\"InternalEditorUtilityBindings::PassAndReturnColor32\")]\n        extern public static Color32 PassAndReturnColor32(Color32 c);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::SaveCursorToFile\")]\n        extern public static bool SaveCursorToFile(string path, Texture2D image, Vector2 hotSpot);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::SaveCursorToInMemoryResource\")]\n        extern internal static bool SaveCursorToInMemoryResource(Texture2D image, Vector2 hotSpot, ushort cursorDataResourceId, IntPtr cursorDirectoryBuffer, uint cursorDirectoryBufferSize, IntPtr cursorDataBuffer, uint cursorDataBufferSize);\n\n        [FreeFunction(\"GetScriptCompilationDefines\")]\n        extern internal static string[] GetCompilationDefines(EditorScriptCompilationOptions options, BuildTarget target, int subtarget, ApiCompatibilityLevel apiCompatibilityLevel, string[] extraDefines = null);\n\n        //Launches an application that is kept alive, even during a domain reload\n        [FreeFunction(\"LaunchApplication\")]\n        extern internal static bool LaunchApplication(string path, string[] arguments);\n\n        public static string CountToString(ulong count)\n        {\n            string[] names = {\"G\", \"M\", \"k\", \"\"};\n            float[] magnitudes = {1000000000.0f, 1000000.0f, 1000.0f, 1.0f};\n\n            int index = 0;\n            while (index < 3 && count < (magnitudes[index] / 2.0f))\n            {\n                index++;\n            }\n            float result = count / magnitudes[index];\n            return result.ToString(\"0.0\", CultureInfo.InvariantCulture.NumberFormat) + names[index];\n        }\n\n        [StaticAccessor(\"GetSceneManager()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"EnsureUntitledSceneHasBeenSaved\")]\n        [Obsolete(\"use EditorSceneManager.EnsureUntitledSceneHasBeenSaved\")]\n        extern public static bool EnsureSceneHasBeenSaved(string operation);\n\n        internal static void PrepareDragAndDropTesting(EditorWindow editorWindow)\n        {\n            if (editorWindow.m_Parent != null)\n                PrepareDragAndDropTestingInternal(editorWindow.m_Parent);\n        }\n\n        [FreeFunction(\"InternalEditorUtilityBindings::PrepareDragAndDropTestingInternal\")]\n        extern internal static void PrepareDragAndDropTestingInternal(GUIView guiView);\n\n        [FreeFunction(\"InternalEditorUtilityBindings::LayerMaskToConcatenatedLayersMaskInternal\")]\n        extern private static int LayerMaskToConcatenatedLayersMaskInternal(int mask);\n\n        [StaticAccessor(\"GetApplication()\", StaticAccessorType.Dot)]\n        internal static extern bool IsScriptReloadRequested();\n\n        [FreeFunction(\"HandleProjectWindowFileDrag\")]\n        internal static extern DragAndDropVisualMode HandleProjectWindowFileDrag(string newParentPath, string[] paths, bool perform, int defaultPromptAction);\n\n        //Drag and drop current selection to project window\n        //Set prefabVariantCreationModeDialogChoice to -1 to allow dialogs to be shown.\n        //If set to 0 or 1 no dialogs will be shown. Using a value of 0 is similar to choosing PrefabVariantCreationMode::kOriginal and a value of 1 is similar to choosing PrefabVariantCreationMode::kVariant from the \"Create Prefab or Variant\" dialog if dropping a Prefab instance to the Project Browser.\n        //Non-zero values also blocks the \"Cyclic References\" error dialog, and it defaults the \"Possibly unwanted Prefab replacement\" menu to return \"Replace Anyway\".\n        [FreeFunction(\"InternalEditorUtilityBindings::DragAndDropPrefabsFromHierarchyToProjectWindow\")]\n        internal static extern DragAndDropVisualMode DragAndDropPrefabsFromHierarchyToProjectWindow(string destAssetGuid, bool perform, int prefabVariantCreationModeDialogChoice);\n\n        [FreeFunction]\n        [NativeHeader(\"Editor/Src/Undo/DefaultParentObjectUndo.h\")]\n        internal static extern void RegisterSetDefaultParentObjectUndo(string sceneGUID, int instanceID, string undoName);\n\n        // Aux window functionality is quite brittle. It is strongly advised to avoid\n        // using this method but if you really need it, consult Desktop team first.\n        [StaticAccessor(\"GetAuxWindowManager()\", StaticAccessorType.Dot)]\n        internal static extern void RetainAuxWindows();\n\n        [FreeFunction]\n        internal static extern bool IsPlaybackEngineDisabled(string engineName);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/InternalEditorUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\n\nusing System.IO;\nusing System.Linq;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Text.RegularExpressions;\nusing UnityEditor.Experimental;\nusing UnityEngine.Scripting;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEngine.UIElements;\nusing UnityEngine.Video;\nusing UnityEditor.Build;\n\nnamespace UnityEditorInternal\n{\n    partial class InternalEditorUtility\n    {\n        public static Texture2D FindIconForFile(string fileName)\n        {\n            int i = fileName.LastIndexOf('.');\n            string extension = i == -1 ? \"\" : fileName.Substring(i + 1).ToLower();\n\n            switch (extension)\n            {\n                // Most .asset files use their scriptable object defined icon instead of a default one.\n                case \"asset\": return AssetDatabase.GetCachedIcon(fileName) as Texture2D ?? EditorGUIUtility.FindTexture(\"GameManager Icon\");\n\n                case \"cginc\": return EditorGUIUtility.FindTexture(\"CGProgram Icon\");\n                case \"cs\": return EditorGUIUtility.FindTexture(\"cs Script Icon\");\n                case \"guiskin\": return EditorGUIUtility.FindTexture(typeof(GUISkin));\n                case \"dll\": return EditorGUIUtility.FindTexture(\"Assembly Icon\");\n                case \"asmdef\": return EditorGUIUtility.FindTexture(typeof(AssemblyDefinitionAsset));\n                case \"asmref\": return EditorGUIUtility.FindTexture(typeof(AssemblyDefinitionAsset));\n                case \"mat\": return EditorGUIUtility.FindTexture(typeof(Material));\n                case \"physicmaterial\": return EditorGUIUtility.FindTexture(typeof(PhysicsMaterial));\n                case \"prefab\": return EditorGUIUtility.FindTexture(\"Prefab Icon\");\n                case \"shader\": return EditorGUIUtility.FindTexture(typeof(Shader));\n                case \"txt\": return EditorGUIUtility.FindTexture(typeof(TextAsset));\n                case \"unity\": return EditorGUIUtility.FindTexture(typeof(SceneAsset));\n                case \"prefs\": return EditorGUIUtility.FindTexture(typeof(EditorSettings));\n                case \"anim\": return EditorGUIUtility.FindTexture(typeof(Animation));\n                case \"meta\": return EditorGUIUtility.FindTexture(\"MetaFile Icon\");\n                case \"mixer\": return EditorGUIUtility.FindTexture(typeof(UnityEditor.Audio.AudioMixerController));\n                case \"uxml\": return EditorGUIUtility.FindTexture(typeof(UnityEngine.UIElements.VisualTreeAsset));\n                case \"uss\": return EditorGUIUtility.FindTexture(typeof(StyleSheet));\n                case \"lighting\": return EditorGUIUtility.FindTexture(typeof(UnityEngine.LightingSettings));\n                case \"scenetemplate\": return EditorGUIUtility.FindTexture(\"UnityEditor/SceneTemplate/SceneTemplateAsset Icon\");\n                case \"ttf\": case \"otf\": case \"fon\": case \"fnt\":\n                    return EditorGUIUtility.FindTexture(typeof(Font));\n\n                case \"aac\": case \"aif\": case \"aiff\": case \"au\": case \"mid\": case \"midi\": case \"mp3\": case \"mpa\":\n                case \"ra\": case \"ram\": case \"wma\": case \"wav\": case \"wave\": case \"ogg\": case \"flac\":\n                    return EditorGUIUtility.FindTexture(typeof(AudioClip));\n\n                case \"ai\": case \"apng\": case \"png\": case \"bmp\": case \"cdr\": case \"dib\": case \"eps\": case \"exif\":\n                case \"gif\": case \"ico\": case \"icon\": case \"j\": case \"j2c\": case \"j2k\": case \"jas\":\n                case \"jiff\": case \"jng\": case \"jp2\": case \"jpc\": case \"jpe\": case \"jpeg\": case \"jpf\": case \"jpg\":\n                case \"jpw\": case \"jpx\": case \"jtf\": case \"mac\": case \"omf\": case \"qif\": case \"qti\": case \"qtif\":\n                case \"tex\": case \"tfw\": case \"tga\": case \"tif\": case \"tiff\": case \"wmf\": case \"psd\": case \"exr\":\n                case \"hdr\":\n                    return EditorGUIUtility.FindTexture(typeof(Texture));\n\n                case \"3df\": case \"3dm\": case \"3dmf\": case \"3ds\": case \"3dv\": case \"3dx\": case \"blend\": case \"c4d\":\n                case \"lwo\": case \"lws\": case \"ma\": case \"max\": case \"mb\": case \"mesh\": case \"obj\": case \"vrl\":\n                case \"wrl\": case \"wrz\": case \"fbx\":\n                    return EditorGUIUtility.FindTexture(typeof(Mesh));\n\n                case \"dv\": case \"mp4\": case \"mpg\": case \"mpeg\": case \"m4v\": case \"ogv\": case \"vp8\": case \"webm\":\n                case \"asf\": case \"asx\": case \"avi\": case \"dat\": case \"divx\": case \"dvx\": case \"mlv\": case \"m2l\":\n                case \"m2t\": case \"m2ts\": case \"m2v\": case \"m4e\": case \"mjp\": case \"mov\": case \"movie\":\n                case \"mp21\": case \"mpe\": case \"mpv2\": case \"ogm\": case \"qt\": case \"rm\": case \"rmvb\": case \"wmw\": case \"xvid\":\n                    return AssetDatabase.GetCachedIcon(fileName) as Texture2D ?? EditorGUIUtility.FindTexture(typeof(VideoClip));\n\n                case \"colors\": case \"gradients\":\n                case \"curves\": case \"curvesnormalized\": case \"particlecurves\": case \"particlecurvessigned\": case \"particledoublecurves\": case \"particledoublecurvessigned\":\n                    return EditorGUIUtility.FindTexture(typeof(ScriptableObject));\n\n                case \"vulkandevicefilter\":\n                    return EditorGUIUtility.FindTexture(typeof(EditorSettings));\n\n                default: return null;\n            }\n        }\n\n        [RequiredByNativeCode]\n        public static Texture2D GetIconForFile(string fileName)\n        {\n            return FindIconForFile(fileName) ?? EditorGUIUtility.FindTexture(typeof(DefaultAsset));\n        }\n\n        static GUIContent[] sStatusWheel;\n\n        internal static GUIContent animatedProgressImage\n        {\n            get\n            {\n                if (sStatusWheel == null)\n                {\n                    sStatusWheel = new GUIContent[12];\n                    for (int i = 0; i < 12; i++)\n                    {\n                        GUIContent gc = new GUIContent();\n                        gc.image = EditorGUIUtility.LoadIcon(\"WaitSpin\" + i.ToString(\"00\"));\n                        gc.image.hideFlags = HideFlags.HideAndDontSave;\n                        gc.image.name = \"Spinner\";\n                        sStatusWheel[i] = gc;\n                    }\n                }\n                int frame = (int)Mathf.Repeat(Time.realtimeSinceStartup * 10, 11.99f);\n                return sStatusWheel[frame];\n            }\n        }\n\n        public static string[] GetEditorSettingsList(string prefix, int count)\n        {\n            ArrayList aList = new ArrayList();\n\n            for (int i = 1; i <= count; i++)\n            {\n                string str = EditorPrefs.GetString(prefix + i, \"defaultValue\");\n\n                if (str == \"defaultValue\")\n                    break;\n\n                aList.Add(str);\n            }\n\n            return aList.ToArray(typeof(string)) as string[];\n        }\n\n        public static void SaveEditorSettingsList(string prefix, string[] aList, int count)\n        {\n            int i;\n\n            for (i = 0; i < aList.Length; i++)\n                EditorPrefs.SetString(prefix + (i + 1), (string)aList[i]);\n\n            for (i = aList.Length + 1; i <= count; i++)\n                EditorPrefs.DeleteKey(prefix + i);\n        }\n\n        public static string TextAreaForDocBrowser(Rect position, string text, GUIStyle style)\n        {\n            int id = EditorGUIUtility.GetControlID(\"TextAreaWithTabHandling\".GetHashCode(), FocusType.Keyboard, position);\n            var editor = EditorGUI.s_RecycledEditor;\n            var evt = Event.current;\n            if (editor.IsEditingControl(id) && evt.type == EventType.KeyDown)\n            {\n                if (evt.character == '\\t')\n                {\n                    editor.Insert('\\t');\n                    evt.Use();\n                    GUI.changed = true;\n                    text = editor.text;\n                }\n                if (evt.character == '\\n')\n                {\n                    editor.Insert('\\n');\n                    evt.Use();\n                    GUI.changed = true;\n                    text = editor.text;\n                }\n            }\n            bool dummy;\n            text = EditorGUI.DoTextField(editor, id, EditorGUI.IndentedRect(position), text, style, null, out dummy, false, true, false);\n            return text;\n        }\n\n        public static Camera[] GetSceneViewCameras()\n        {\n            return SceneView.GetAllSceneCameras();\n        }\n\n        public static void ShowGameView()\n        {\n            WindowLayout.ShowAppropriateViewOnEnterExitPlaymode(true);\n        }\n\n        internal struct AssetReference\n        {\n            // The guid is always valid. Assets not yet present will not have an instanceID yet.\n            // Could be because it is on-demand imported.\n            public string guid;\n            public int instanceID; // instanceID of an object in an asset if the asset is available in imported form. Else 0.\n\n            public sealed class GuidThenInstanceIDEqualityComparer : IEqualityComparer<AssetReference>\n            {\n                public bool Equals(AssetReference x, AssetReference y)\n                {\n                    if (!string.IsNullOrEmpty(x.guid) || !string.IsNullOrEmpty(y.guid))\n                        return string.Equals(x.guid, y.guid);\n\n                    // Both guids are nullOrEmpty now\n                    return x.instanceID == y.instanceID;\n                }\n\n                public int GetHashCode(AssetReference assetReference)\n                {\n                    return (assetReference.instanceID * 397)\n                        ^ (assetReference.guid != null ? assetReference.guid.GetHashCode() : 0);\n                }\n            }\n\n            public static bool IsAssetImported(int instanceID)\n            {\n                return instanceID != 0;\n            }\n        }\n\n        public static List<int> GetNewSelection(int clickedInstanceID, List<int> allInstanceIDs, List<int> selectedInstanceIDs, int lastClickedInstanceID, bool keepMultiSelection, bool useShiftAsActionKey, bool allowMultiSelection)\n        {\n            return GetNewSelection(clickedInstanceID, allInstanceIDs, selectedInstanceIDs, lastClickedInstanceID, keepMultiSelection, useShiftAsActionKey, allowMultiSelection, Event.current?.shift ?? false, EditorGUI.actionKey);\n        }\n\n        internal static List<int> GetNewSelection(int clickedInstanceID, List<int> allInstanceIDs, List<int> selectedInstanceIDs, int lastClickedInstanceID, bool keepMultiSelection, bool useShiftAsActionKey, bool allowMultiSelection, bool shiftKeyIsDown, bool actionKeyIsDown)\n        {\n            List<string> allGuids = null;\n            var clicked = new AssetReference() { guid = null, instanceID = clickedInstanceID };\n\n            return GetNewSelection(ref clicked, allInstanceIDs, allGuids, selectedInstanceIDs, lastClickedInstanceID, keepMultiSelection, useShiftAsActionKey, allowMultiSelection, shiftKeyIsDown, actionKeyIsDown);\n        }\n\n        internal static bool TrySetInstanceId(ref AssetReference entry)\n        {\n            if (entry.instanceID != 0 || string.IsNullOrEmpty(entry.guid))\n                return true;\n\n            if (entry.instanceID == 0 && EditorUtility.isInSafeMode)\n                return false; // Íf instance id is 0 in safe mode, then don't try to produce it. InstanceIDs are 0 for non script assets in safe mode.\n\n            GUID lookupGUID = new GUID(entry.guid);\n            var hash = UnityEditor.Experimental.AssetDatabaseExperimental.ProduceArtifactAsync(new ArtifactKey(lookupGUID));\n            if (!hash.isValid)\n                return false;\n\n            string path = AssetDatabase.GUIDToAssetPath(entry.guid);\n            entry.instanceID = AssetDatabase.GetMainAssetInstanceID(path);\n            return true;\n        }\n\n        internal static List<int> TryGetInstanceIds(List<int> entryInstanceIds, List<string> entryInstanceGuids, int from, int to)\n        {\n            List<GUID> guids = new List<GUID>();\n\n            for (int i = from; i <= to; ++i)\n            {\n                if (entryInstanceIds[i] == 0)\n                {\n                    GUID parsedGuid = new GUID(entryInstanceGuids[i]);\n                    guids.Add(parsedGuid);\n                }\n            }\n\n            // Force import if needed so that we can get an instance ID for the entry\n\n            if (guids.Count == 0)\n            {\n                return entryInstanceIds.GetRange(from, to - from + 1);\n            }\n            else\n            {\n                var hashes = UnityEditor.Experimental.AssetDatabaseExperimental.ProduceArtifactsAsync(guids.ToArray());\n                if (System.Array.FindIndex(hashes, a => !a.isValid) != -1)\n                    return null;\n\n                var newSelection = new List<int>(to - from + 1);\n\n                for (int i = from; i <= to; ++i)\n                {\n                    int instanceID = entryInstanceIds[i];\n                    if (instanceID == 0)\n                    {\n                        if (EditorUtility.isInSafeMode)\n                            continue; // Íf instance id is 0 in safe mode, then don't try to produce it. InstanceIDs are 0 for non script assets in safe mode.\n\n                        string path = AssetDatabase.GUIDToAssetPath(entryInstanceGuids[i]);\n                        instanceID = AssetDatabase.GetMainAssetInstanceID(path);\n                        entryInstanceIds[i] = instanceID;\n                    }\n                    newSelection.Add(instanceID);\n                }\n                return newSelection;\n            }\n        }\n\n        internal static List<int> GetNewSelection(ref AssetReference clickedEntry, List<int> allEntryInstanceIDs, List<string> allEntryGuids, List<int> selectedInstanceIDs, int lastClickedInstanceID, bool keepMultiSelection, bool useShiftAsActionKey, bool allowMultiSelection)\n        {\n            return GetNewSelection(ref clickedEntry, allEntryInstanceIDs, allEntryGuids, selectedInstanceIDs, lastClickedInstanceID, keepMultiSelection, useShiftAsActionKey, allowMultiSelection, Event.current.shift, EditorGUI.actionKey);\n        }\n\n        // Multi selection handling. Returns new list of selected instanceIDs\n        internal static List<int> GetNewSelection(ref AssetReference clickedEntry, List<int> allEntryInstanceIDs, List<string> allEntryGuids, List<int> selectedInstanceIDs, int lastClickedInstanceID, bool keepMultiSelection, bool useShiftAsActionKey, bool allowMultiSelection, bool shiftKeyIsDown, bool actionKeyIsDown)\n        {\n            bool useShift = shiftKeyIsDown || (actionKeyIsDown && useShiftAsActionKey);\n            bool useActionKey = actionKeyIsDown && !useShiftAsActionKey;\n            if (!allowMultiSelection)\n                useShift = useActionKey = false;\n\n            int firstIndex;\n            int lastIndex;\n            // Toggle selected node from selection\n            if (useActionKey && !useShift)\n            {\n                var newSelection = new List<int>(selectedInstanceIDs);\n                if (newSelection.Contains(clickedEntry.instanceID))\n                {\n                    if (!keepMultiSelection)\n                        newSelection.Remove(clickedEntry.instanceID);\n                }\n                else\n                {\n                    if (TrySetInstanceId(ref clickedEntry))\n                        newSelection.Add(clickedEntry.instanceID);\n                }\n                return newSelection;\n            }\n            // Select everything between the first selected object and the selected\n            else if (useShift)\n            {\n                if (clickedEntry.instanceID == lastClickedInstanceID)\n                {\n                    return new List<int>(selectedInstanceIDs);\n                }\n\n                if (!GetFirstAndLastSelected(allEntryInstanceIDs, selectedInstanceIDs, out firstIndex, out lastIndex))\n                {\n                    // We had no selection\n                    var newSelection = new List<int>(1);\n                    if (TrySetInstanceId(ref clickedEntry))\n                        newSelection.Add(clickedEntry.instanceID);\n\n                    return newSelection;\n                }\n\n                int newIndex = -1;\n                int prevIndex = -1;\n\n                // Only valid in case the selection concerns assets\n\n                if (!TrySetInstanceId(ref clickedEntry))\n                    return new List<int>(selectedInstanceIDs);\n\n                int clickedInstanceID = clickedEntry.instanceID;\n\n                if (lastClickedInstanceID != 0)\n                {\n                    for (int i = 0; i < allEntryInstanceIDs.Count; ++i)\n                    {\n                        if (allEntryInstanceIDs[i] == clickedInstanceID)\n                            newIndex = i;\n\n                        if (allEntryInstanceIDs[i] == lastClickedInstanceID)\n                            prevIndex = i;\n                    }\n                }\n                else\n                {\n                    for (int i = 0; i < allEntryInstanceIDs.Count; ++i)\n                    {\n                        if (allEntryInstanceIDs[i] == clickedInstanceID)\n                            newIndex = i;\n                    }\n                }\n\n                System.Diagnostics.Debug.Assert(newIndex != -1); // new item should be part of visible folder set\n                int dir = 0;\n                if (prevIndex != -1)\n                    dir = (newIndex > prevIndex) ? 1 : -1;\n\n                int from = 0, to = 0;\n                var addExisting = false;\n\n                bool usingArrowKeys = Event.current != null ? Event.current.keyCode == KeyCode.DownArrow || Event.current.keyCode == KeyCode.UpArrow : false;\n                var clickedInTheMiddle = lastIndex > newIndex && firstIndex < newIndex;\n\n                if (selectedInstanceIDs.Count > 1)\n                {\n                    var clickedID = allEntryInstanceIDs[newIndex];\n                    var noGapsInSelection = (allEntryInstanceIDs.Count - firstIndex + selectedInstanceIDs.Count) == allEntryInstanceIDs.Count - lastIndex;\n                    var isInSelection = selectedInstanceIDs.Contains(clickedID);\n                    // if the newly clicked item is already selected,\n                    // we treat this as a combination of selecting items from the highest selected item to the clicked item\n                    // or from the lowest selected item to the clicked item depending on the direction of the selection,\n                    // e.g. if we select item 1 and shift-select item 5, then shift-select item 3, we'll have items 1 to 3 selected\n                    if (isInSelection || noGapsInSelection || clickedInTheMiddle)\n                    {\n                        from = dir > 0 ? firstIndex : newIndex;\n                        to = dir > 0 ? newIndex : lastIndex;\n\n                        // if we clicked in-between the lowest and highest selected indices of a selection containing gaps\n                        // and the item was not already in the selection\n                        // make sure that the new selection is added to the currently existing one\n                        if (clickedInTheMiddle && !noGapsInSelection && !isInSelection)\n                            addExisting = true;\n                    }\n                    else if (dir > 0)\n                    {\n                        if (newIndex > lastIndex)\n                        {\n                            from = lastIndex + 1;\n                            to = newIndex;\n\n                            addExisting = true;\n                        }\n                        else\n                        {\n                            from = newIndex;\n                            to = lastIndex;\n                        }\n                    }\n                    else if (dir < 0)\n                    {\n                        if (newIndex < firstIndex)\n                        {\n                            from = newIndex;\n                            to = firstIndex - 1;\n\n                            addExisting = true;\n                        }\n                        else\n                        {\n                            from = firstIndex;\n                            to = newIndex;\n                        }\n                    }\n                }\n\n                if (!addExisting || usingArrowKeys)\n                {\n                    if (newIndex > lastIndex)\n                    {\n                        from = firstIndex;\n                        to = newIndex;\n                    }\n                    else if (newIndex >= firstIndex && newIndex < lastIndex)\n                    {\n                        if (dir > 0)\n                        {\n                            from = newIndex;\n                            to = lastIndex;\n                        }\n                        else\n                        {\n                            from = firstIndex;\n                            to = newIndex;\n                        }\n                    }\n                    else\n                    {\n                        from = newIndex;\n                        to = lastIndex;\n                    }\n                }\n\n                if (allEntryGuids == null)\n                {\n                    List<int> allSelectedInstanceIDs = new List<int>();\n\n                    if (addExisting && !usingArrowKeys)\n                    {\n                        allSelectedInstanceIDs.AddRange(selectedInstanceIDs.GetRange(0, selectedInstanceIDs.Count));\n                        allSelectedInstanceIDs.AddRange(allEntryInstanceIDs.GetRange(from, to - from + 1));\n\n                        if (clickedInTheMiddle)\n                            allSelectedInstanceIDs = allSelectedInstanceIDs.Distinct().ToList();\n                    }\n                    else\n                    {\n                        allSelectedInstanceIDs.AddRange(allEntryInstanceIDs.GetRange(from, to - from + 1));\n                    }\n\n                    return allSelectedInstanceIDs;\n                }\n\n                var foundInstanceIDs = TryGetInstanceIds(allEntryInstanceIDs, allEntryGuids, from, to);\n                if (foundInstanceIDs != null)\n                {\n                    // adding the entire selectedInstanceIDs would result\n                    // in the last entry being duplicated later on\n                    // thus when selecting upwards we add the existing selection - 1;\n                    // when selecting downwards don't add the last index from the new selection\n                    if (addExisting && !usingArrowKeys)\n                    {\n                        List<int> allSelectedInstanceIDs = new List<int>();\n                        allSelectedInstanceIDs.AddRange(selectedInstanceIDs.GetRange(0, selectedInstanceIDs.Count));\n                        allSelectedInstanceIDs.AddRange(allEntryInstanceIDs.GetRange(from, to - from + 1));\n                        if (clickedInTheMiddle)\n                            allSelectedInstanceIDs = allSelectedInstanceIDs.Distinct().ToList();\n\n                        return allSelectedInstanceIDs;\n                    }\n\n                    return foundInstanceIDs;\n                }\n\n                return new List<int>(selectedInstanceIDs);\n            }\n            // Just set the selection to the clicked object\n            else\n            {\n                if (keepMultiSelection)\n                {\n                    // Don't change selection on mouse down when clicking on selected item.\n                    // This is for dragging in case with multiple items selected or right click (mouse down should not unselect the rest).\n                    if (selectedInstanceIDs.Contains(clickedEntry.instanceID))\n                    {\n                        return new List<int>(selectedInstanceIDs);\n                    }\n                }\n\n                if (TrySetInstanceId(ref clickedEntry))\n                {\n                    var newSelection = new List<int>(1);\n                    newSelection.Add(clickedEntry.instanceID);\n                    return newSelection;\n                }\n                else\n                {\n                    return new List<int>(selectedInstanceIDs);\n                }\n            }\n        }\n\n        static bool GetFirstAndLastSelected(List<int> allEntries, List<int> selectedInstanceIDs, out int firstIndex, out int lastIndex)\n        {\n            firstIndex = -1;\n            lastIndex = -1;\n            for (int i = 0; i < allEntries.Count; ++i)\n            {\n                if (selectedInstanceIDs.Contains(allEntries[i]))\n                {\n                    if (firstIndex == -1)\n                        firstIndex = i;\n                    lastIndex = i; // just overwrite and we will have the last in the end...\n                }\n            }\n            return firstIndex != -1 && lastIndex != -1;\n        }\n\n        internal static string GetApplicationExtensionForRuntimePlatform(RuntimePlatform platform)\n        {\n            switch (platform)\n            {\n                case RuntimePlatform.OSXEditor:\n                    return \"app\";\n                case RuntimePlatform.WindowsEditor:\n                    return \"exe\";\n                default:\n                    break;\n            }\n            return string.Empty;\n        }\n\n        public static bool IsValidFileName(string filename)\n        {\n            string validFileName = RemoveInvalidCharsFromFileName(filename, false);\n            if (validFileName != filename || string.IsNullOrEmpty(validFileName))\n                return false;\n            return true;\n        }\n\n        public static string RemoveInvalidCharsFromFileName(string filename, bool logIfInvalidChars)\n        {\n            if (string.IsNullOrEmpty(filename))\n                return filename;\n\n            filename = filename.Trim(); // remove leading and trailing white spaces\n            if (string.IsNullOrEmpty(filename))\n                return filename;\n\n            string invalidChars = new string(System.IO.Path.GetInvalidFileNameChars());\n            string legal = \"\";\n            bool hasInvalidChar = false;\n            foreach (char c in filename)\n            {\n                if (invalidChars.IndexOf(c) == -1)\n                    legal += c;\n                else\n                    hasInvalidChar = true;\n            }\n            if (hasInvalidChar && logIfInvalidChars)\n            {\n                string invalid = GetDisplayStringOfInvalidCharsOfFileName(filename);\n                if (invalid.Length > 0)\n                    Debug.LogWarningFormat(\"A filename cannot contain the following character{0}:  {1}\", invalid.Length > 1 ? \"s\" : \"\", invalid);\n            }\n\n            return legal;\n        }\n\n        public static string GetDisplayStringOfInvalidCharsOfFileName(string filename)\n        {\n            if (string.IsNullOrEmpty(filename))\n                return \"\";\n\n            string invalid = new string(System.IO.Path.GetInvalidFileNameChars());\n\n            string illegal = \"\";\n            foreach (char c in filename)\n            {\n                if (invalid.IndexOf(c) >= 0)\n                {\n                    if (illegal.IndexOf(c) == -1)\n                    {\n                        if (illegal.Length > 0)\n                            illegal += \" \";\n                        illegal += c;\n                    }\n                }\n            }\n            return illegal;\n        }\n\n        internal static bool IsScriptOrAssembly(string filename)\n        {\n            if (string.IsNullOrEmpty(filename))\n                return false;\n\n            switch (System.IO.Path.GetExtension(filename).ToLower())\n            {\n                case \".cs\":\n                    return true;\n                case \".dll\":\n                case \".exe\":\n                    return AssemblyHelper.IsManagedAssembly(filename);\n                default:\n                    return false;\n            }\n        }\n\n        internal static IEnumerable<string> GetAllScriptGUIDs()\n        {\n            return AssetDatabase.GetAllAssetPaths()\n                .Where(asset => (IsScriptOrAssembly(asset) && !UnityEditor.PackageManager.Folders.IsPackagedAssetPath(asset)))\n                .Select(asset => AssetDatabase.AssetPathToGUID(asset));\n        }\n\n        internal static string GetMonolithicEngineAssemblyPath()\n        {\n            // We still build a monolithic UnityEngine.dll as a compilation target for user projects.\n            // It lives next to the editor dll.\n            var dir = Path.GetDirectoryName(GetEditorAssemblyPath());\n            return Path.Combine(dir, \"UnityEngine.dll\");\n        }\n\n        internal static string[] GetCompilationDefines(EditorScriptCompilationOptions options, BuildTarget target, int subtarget)\n        {\n            return GetCompilationDefines(options, target, subtarget, PlayerSettings.GetApiCompatibilityLevel(NamedBuildTarget.FromActiveSettings(target)));\n        }\n\n        public static void SetShowGizmos(bool value)\n        {\n            var view = PlayModeView.GetMainPlayModeView();\n\n            if (view == null)\n                view = PlayModeView.GetRenderingView();\n\n            if (view == null)\n                return;\n\n            view.SetShowGizmos(value);\n        }\n\n        private static Material blitSceneViewCaptureMat;\n\n        [Obsolete(\"Use CaptureEditorWindow instead\", false)]\n        public static bool CaptureSceneView(SceneView sv, RenderTexture rt)\n        {\n            if (!sv.hasFocus)\n                return false;\n\n            if (blitSceneViewCaptureMat == null)\n                blitSceneViewCaptureMat = (Material)EditorGUIUtility.LoadRequired(\"SceneView/BlitSceneViewCapture.mat\");\n\n            // Grab SceneView framebuffer into a temporary RT.\n            RenderTexture tmp = RenderTexture.GetTemporary(rt.descriptor);\n            Rect rect = new Rect(0, 0, sv.position.width, sv.position.height);\n            sv.m_Parent.GrabPixels(tmp, rect);\n\n            // Blit it into the target RT, it will be flipped by the shader if necessary.\n            Graphics.Blit(tmp, rt, blitSceneViewCaptureMat);\n            RenderTexture.ReleaseTemporary(tmp);\n\n            return true;\n        }\n\n        public static bool CaptureEditorWindow(EditorWindow window, RenderTexture rt)\n        {\n            if (!window.hasFocus)\n            {\n                Debug.LogError(\"CaptureEditorWindow: window must have focus\");\n                return false;\n            }\n\n            blitSceneViewCaptureMat = blitSceneViewCaptureMat ?? (Material)EditorGUIUtility.LoadRequired(\"SceneView/BlitSceneViewCapture.mat\");\n\n            // Grab SceneView framebuffer into a temporary RT.\n            RenderTexture tmp = RenderTexture.GetTemporary(rt.descriptor);\n            Rect rect = new Rect(0, 0, window.position.width, window.position.height);\n            window.m_Parent.GrabPixels(tmp, rect);\n\n            // Blit it into the target RT, it will be flipped by the shader if necessary.\n            Graphics.Blit(tmp, rt, blitSceneViewCaptureMat);\n            RenderTexture.ReleaseTemporary(tmp);\n\n            return true;\n        }\n\n        static readonly Regex k_UnityAssemblyRegex = new(\"^(Unity|UnityEditor|UnityEngine).\", RegexOptions.Compiled);\n        internal static bool IsUnityAssembly(Type type)\n        {\n            var assemblyName = type.Assembly.GetName().ToString();\n            return k_UnityAssemblyRegex.IsMatch(assemblyName);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/InternalMeshUtil.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Mono/InternalMeshUtil.bindings.h\")]\n    internal static class InternalMeshUtil\n    {\n        public static extern int GetPrimitiveCount(Mesh mesh);\n\n        public static extern int CalcTriangleCount(Mesh mesh);\n\n        public static extern bool HasSupportedTopologyForGI(Mesh mesh);\n\n        public static extern bool HasVertices(Mesh mesh);\n\n        public static extern bool HasNormals(Mesh mesh);\n\n        public static extern string GetVertexFormat(Mesh mesh);\n\n        public static extern float GetCachedMeshSurfaceArea(MeshRenderer meshRenderer);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/LODUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    internal struct LODVisualizationInformation\n    {\n        public int triangleCount;\n        public int vertexCount;\n        public int rendererCount;\n        public int submeshCount;\n\n        public int activeLODLevel;\n        public float activeLODFade;\n        public float activeDistance;\n        public float activeRelativeScreenSize;\n        public float activePixelSize;\n        public float worldSpaceSize;\n    }\n\n    [NativeHeader(\"Editor/Mono/LODUtility.bindings.h\")]\n    public sealed class LODUtility\n    {\n        [FreeFunction(\"LODUtilityBindings::CalculateVisualizationData\")]\n        extern internal static LODVisualizationInformation CalculateVisualizationData(Camera camera, LODGroup group, int lodLevel);\n\n        [FreeFunction(\"LODUtilityBindings::IsLODAnimatingOnDisplay\")]\n        extern internal static bool IsLODAnimatingOnDisplay(int displayId);\n\n        [FreeFunction(\"LODUtilityBindings::IsLODAnimating\")]\n        extern internal static bool IsLODAnimating(Camera camera);\n\n        [FreeFunction(\"LODUtilityBindings::CalculateDistance\")]\n        extern internal static float CalculateDistance(Camera camera, float relativeScreenHeight, LODGroup group);\n\n        internal static Vector3 CalculateWorldReferencePoint(LODGroup group)\n        {\n            return group.worldReferencePoint;\n        }\n\n        [FreeFunction]\n        extern internal static bool NeedUpdateLODGroupBoundingBox([NotNull] LODGroup group);\n\n        public static void CalculateLODGroupBoundingBox(LODGroup group)\n        {\n            if (group == null)\n                throw new ArgumentNullException(\"group\");\n            group.RecalculateBounds();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/LogEntries.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Collections;\nusing UnityEngine.Bindings;\nusing System.Reflection;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    // To keep in sync with the enum in LogAssert.h\n    [Flags]\n    internal enum LogMessageFlags : int\n    {\n        kNoLogMessageFlags = 0,\n        kError = 1 << 0, // Message describes an error.\n        kAssert = 1 << 1, // Message describes an assertion failure.\n        kLog = 1 << 2, // Message is a general log message.\n        kFatal = 1 << 4, // Message describes a fatal error, and that the program should now exit.\n        kAssetImportError = 1 << 6, // Message describes an error generated during asset importing.\n        kAssetImportWarning = 1 << 7, // Message describes a warning generated during asset importing.\n        kScriptingError = 1 << 8, // Message describes an error produced by script code.\n        kScriptingWarning = 1 << 9, // Message describes a warning produced by script code.\n        kScriptingLog = 1 << 10, // Message describes a general log message produced by script code.\n        kScriptCompileError = 1 << 11, // Message describes an error produced by the script compiler.\n        kScriptCompileWarning = 1 << 12, // Message describes a warning produced by the script compiler.\n        kStickyLog = 1 << 13, // Message is 'sticky' and should not be removed when the user manually clears the console window.\n        kMayIgnoreLineNumber = 1 << 14, // The scripting runtime should skip annotating the log callstack with file and line information.\n        kReportBug = 1 << 15, // When used with kFatal, indicates that the log system should launch the bug reporter.\n        kDisplayPreviousErrorInStatusBar = 1 << 16, // The message before this one should be displayed at the bottom of Unity's main window, unless there are no messages before this one.\n        kScriptingException = 1 << 17, // Message describes an exception produced by script code.\n        kDontExtractStacktrace = 1 << 18, // Stacktrace extraction should be skipped for this message.\n        kScriptingAssertion = 1 << 21, // The message describes an assertion failure in script code.\n        kStacktraceIsPostprocessed = 1 << 22, // The stacktrace has already been postprocessed and does not need further processing.\n        kIsCalledFromManaged = 1 << 23, // The message is being called from managed code.\n\n        FromEditor = kDontExtractStacktrace | kMayIgnoreLineNumber | kIsCalledFromManaged,\n\n        DebugLog = kScriptingLog | FromEditor,\n        DebugWarning = kScriptingWarning | FromEditor,\n        DebugError = kScriptingError | FromEditor,\n        DebugException = kScriptingException | FromEditor,\n        DebugAssert = kScriptingAssertion | FromEditor\n    }\n\n    internal static class LogMessageFlagsExtensions\n    {\n        public static bool IsInfo(this LogMessageFlags flags)\n        {\n            return (flags & (LogMessageFlags.kLog | LogMessageFlags.kScriptingLog)) != 0;\n        }\n        public static bool IsWarning(this LogMessageFlags flags)\n        {\n            return (flags & (LogMessageFlags.kScriptCompileWarning | LogMessageFlags.kScriptingWarning | LogMessageFlags.kAssetImportWarning)) != 0;\n        }\n        public static bool IsError(this LogMessageFlags flags)\n        {\n            return (flags & (LogMessageFlags.kFatal | LogMessageFlags.kAssert | LogMessageFlags.kError | LogMessageFlags.kScriptCompileError |\n                            LogMessageFlags.kScriptingError | LogMessageFlags.kAssetImportError | LogMessageFlags.kScriptingAssertion | LogMessageFlags.kScriptingException)) != 0;\n        }\n    }\n\n    [NativeHeader(\"Editor/Src/EditorMonoConsole.h\")]\n    [NativeAsStruct]\n    [StructLayout(LayoutKind.Sequential)]\n    internal partial class LogEntry\n    {\n        public string message;\n        public string file;\n        public int line;\n        public int column;\n        public int mode;\n        public int instanceID;\n        public int identifier;\n        public int globalLineIndex;\n        public int callstackTextStartUTF8;\n        public int callstackTextStartUTF16;\n        internal static extern void RemoveLogEntriesByMode(int mode);\n    }\n\n    [NativeHeader(\"Editor/Src/EditorMonoConsole.h\")]\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct LogEntryStruct\n    {\n        public UTF8StringView messagePrefix;\n        public UTF8StringView message;\n        public UTF8StringView callstack;\n        public UTF8StringView timestamp;\n\n        public UTF8StringView file;\n        public int line;\n        public int column;\n\n        public LogMessageFlags mode;\n        public int instanceID;\n        public int identifier;\n    }\n\n    // used to pull log messages from Cpp side to mono window\n    // All functions marked internal may not be called unless you call StartGettingEntries and EndGettingEntries\n    [StaticAccessor(\"GetEditorMonoConsole()\", StaticAccessorType.Dot)]\n    [NativeHeader(\"Editor/Mono/LogEntries.bindings.h\")]\n    internal sealed class LogEntries\n    {\n        public static extern void RowGotDoubleClicked(int index);\n        public static extern void OpenFileOnSpecificLineAndColumn(string filePath, int line, int column);\n\n        [FreeFunction]\n        public static extern string GetStatusText();\n\n        public static extern int GetStatusMask();\n\n        // returns total line count\n        public static extern int StartGettingEntries();\n        public static extern void EndGettingEntries();\n\n        public static extern int consoleFlags { get; set; }\n        public static extern void SetConsoleFlag(int bit, bool value);\n        public static extern void SetFilteringText(string filteringText);\n        public static extern string GetFilteringText();\n\n        public static extern int GetCount();\n\n        public static extern void GetCountsByType(ref int errorCount, ref int warningCount, ref int logCount);\n\n        public static extern void GetLinesAndModeFromEntryInternal(int row, int numberOfLines, ref int mask, [In, Out] ref string outString);\n\n        [FreeFunction]\n        public static extern bool GetEntryInternal(int row, [Out] LogEntry outputEntry);\n\n        [FreeFunction]\n        internal static extern string GetCallstackFormattedSignatureInternal(MethodBase methodInfo);\n\n        [FreeFunction(ThrowsException = true)]\n        public static extern int GetEntryCount(int row);\n\n        public static extern void Clear();\n\n        public static extern int GetStatusViewErrorIndex();\n\n        public static extern void ClickStatusBar(int count);\n\n        public static extern void AddMessageWithDoubleClickCallback(LogEntry outputEntry);\n\n        [ThreadSafe]\n        public extern static unsafe void AddMessagesImpl(void* messagesBuffer, int messagesBufferLength);\n\n        internal static extern int GetEntryRowIndex(int globalIndex, int indexHint = -1);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Macros/MacroEvaluator.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Macros\n{\n    public static class MacroEvaluator\n    {\n        [RequiredByNativeCode]\n        public static string Eval(string macro)\n        {\n            var ret = MethodEvaluator.ExecuteExternalCode(macro);\n            return ret == null ? \"Null\" : ret.ToString();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Macros/MethodEvaluator.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Runtime.Serialization.Formatters;\nusing System.Runtime.Serialization.Formatters.Binary;\n\nnamespace UnityEditor.Macros\n{\n    public static class MethodEvaluator\n    {\n        private static readonly BinaryFormatter s_Formatter =\n            new BinaryFormatter { AssemblyFormat = FormatterAssemblyStyle.Simple };\n\n        private class AssemblyResolver\n        {\n            private readonly string m_AssemblyDirectory;\n\n            public AssemblyResolver(string assemblyDirectory)\n            {\n                m_AssemblyDirectory = assemblyDirectory;\n            }\n\n            public Assembly AssemblyResolve(object sender, ResolveEventArgs args)\n            {\n                var simpleName = args.Name.Split(',')[0];\n                var assemblyFile = Path.Combine(m_AssemblyDirectory, simpleName + \".dll\");\n                if (File.Exists(assemblyFile))\n                    return Assembly.LoadFrom(assemblyFile);\n\n                return null;\n            }\n\n            public Assembly TypeResolve(object sender, ResolveEventArgs args)\n            {\n                //This removes (or at least aleviates) the requirement to qualify the type with the assembly name in tests.\n                var dlls = Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), \"Library/ScriptAssemblies/\"), \"*.dll\");\n                foreach (var dllPath in dlls)\n                {\n                    try\n                    {\n                        var assembly = Assembly.LoadFrom(dllPath);\n                        if (assembly != null && assembly.GetTypes().Any(t => t.Name == args.Name))\n                            return assembly;\n                    }\n                    catch (Exception)\n                    {\n                    }\n                }\n                return null;\n            }\n        }\n\n        public static object Eval(string assemblyFile, string typeName,\n            string methodName, Type[] paramTypes, object[] args)\n        {\n            var assemblyDirectory = Path.GetDirectoryName(assemblyFile);\n            var resolver = new AssemblyResolver(assemblyDirectory);\n            AppDomain.CurrentDomain.AssemblyResolve += resolver.AssemblyResolve;\n            try\n            {\n                var assembly = Assembly.LoadFrom(assemblyFile);\n                var method = assembly.GetType(typeName, true).GetMethod(methodName,\n                    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static,\n                    null, paramTypes, null);\n                if (method == null)\n                    throw new ArgumentException(string.Format(\n                        \"Method {0}.{1}({2}) not found in assembly {3}!\", typeName,\n                        methodName, ToCommaSeparatedString(paramTypes),\n                        assembly.FullName));\n                return method.Invoke(null, args);\n            }\n            finally\n            {\n                AppDomain.CurrentDomain.AssemblyResolve -= resolver.AssemblyResolve;\n            }\n        }\n\n        private static Type TypeOrTypeName(object o)\n        {\n            switch (o)\n            {\n                case Type t:\n                    return t;\n                case string s:\n                    return Type.GetType(s);\n                default:\n                    throw new FormatException($\"Expected {o} to be a string or a Type. It is a {o.GetType()}\");\n            }\n        }\n\n        private static Type[] TypesOrTypeNames(object o)\n        {\n\n            switch (o)\n            {\n                case Type[] t:\n                    return t;\n                case string[] s:\n                    return s.Select(Type.GetType).ToArray();\n                default:\n                    throw new FormatException($\"Expected {o} to be a string[] or a Type[]. It is a {o.GetType()}\");\n            }\n        }\n\n        public static object ExecuteExternalCode(string parcel)\n        {\n            using (var stream = new MemoryStream(Convert.FromBase64String(parcel)))\n            {\n                var header = (string)s_Formatter.Deserialize(stream);\n                if (header != \"com.unity3d.automation\")\n                    throw new Exception(\"Invalid parcel for external code execution.\");\n                var assemblyPath = (string)s_Formatter.Deserialize(stream);\n                AssemblyResolver resolver = null;\n                Assembly assembly = null;\n                if (assemblyPath != \"netstandard\") {\n                    resolver = new AssemblyResolver(Path.GetDirectoryName(assemblyPath));\n\n                    AppDomain.CurrentDomain.AssemblyResolve += resolver.AssemblyResolve;\n                    AppDomain.CurrentDomain.TypeResolve += resolver.TypeResolve;\n                    assembly = Assembly.LoadFrom(assemblyPath);\n                }\n                try\n                {\n                    var type = TypeOrTypeName(s_Formatter.Deserialize(stream));\n\n                    var methodName = (string)s_Formatter.Deserialize(stream);\n\n                    const BindingFlags methodVisibility = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;\n                    var methodParametersTypes = TypesOrTypeNames(s_Formatter.Deserialize(stream));\n\n                    var method = type.GetMethod(methodName, methodVisibility, null, methodParametersTypes, null);\n                    if (method == null)\n                        throw new Exception(string.Format(\n                            \"Could not find method {0}.{1} in assembly {2} located in {3}.\",\n                            type.FullName, methodName, type.Assembly.GetName().Name, assemblyPath));\n\n                    var arguments = (object[])s_Formatter.Deserialize(stream);\n                    TransformArgumentsBack(methodParametersTypes, arguments);\n                    var returnValue = ExecuteCode(type, method, arguments);\n                    return returnValue;\n                }\n                finally\n                {\n                    if (resolver != null)\n                    {\n                        AppDomain.CurrentDomain.AssemblyResolve -= resolver.AssemblyResolve;\n                    }\n                }\n            }\n        }\n\n        private static void  TransformArgumentsBack(Type[] argTypes, object[] args)\n        {\n            for(int i = 0; i<argTypes.Length; i++)\n            {\n                if (argTypes[i] == typeof(Type) && args[i] is string)\n                {\n                    args[i] = TypeOrTypeName(args[i]);\n                }\n                if (argTypes[i].IsSubclassOf(typeof(Delegate)) && args[i] is string str)\n                {\n                    args[i] = DeserializeDelegate(argTypes[i], str);\n                }\n            }\n        }\n\n        private static Delegate DeserializeDelegate(Type t, string serialized)\n        {\n            var parts = serialized.Split('\\n', StringSplitOptions.RemoveEmptyEntries);\n            var declaringType = TypeOrTypeName(parts[0]);\n            var methodName = parts[1];\n            var parameterTypes = TypesOrTypeNames(parts.Skip(2).ToArray());\n            const BindingFlags methodVisibility = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;\n            var method = declaringType.GetMethod(methodName, methodVisibility, null, parameterTypes, null);\n            if (method == null)\n                throw new Exception(string.Format(\n                    \"Could not find method {0}.{1} in assembly {2}.\",\n                    declaringType.FullName, methodName, declaringType.Assembly.GetName().Name));\n            return method.CreateDelegate(t);\n        }\n\n        private static object ExecuteCode(Type target, MethodInfo method, object[] args)\n        {\n            return method.Invoke(method.IsStatic ? null : GetActor(target), args);\n        }\n\n        private static object GetActor(Type type)\n        {\n            var ctorInfo = type.GetConstructor(new Type[] {});\n            return ctorInfo != null ? ctorInfo.Invoke(new object[] {}) : null;\n        }\n\n        private static string ToCommaSeparatedString<T>(IEnumerable<T> items)\n        {\n            return string.Join(\", \", items.Select(o => o.ToString()).ToArray());\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/MaterialProperty.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\nusing ShaderPropertyType = UnityEngine.Rendering.ShaderPropertyType;\nusing ShaderPropertyFlags = UnityEngine.Rendering.ShaderPropertyFlags;\n\nnamespace UnityEditor\n{\n    // match MonoMaterialProperty layout!\n    [StructLayout(LayoutKind.Sequential)]\n    public sealed partial class MaterialProperty\n    {\n        public delegate bool ApplyPropertyCallback(MaterialProperty prop, int changeMask, object previousValue);\n\n        private Object[] m_Targets;\n        private ApplyPropertyCallback m_ApplyPropertyCallback;\n        private string m_Name;\n        private string m_DisplayName;\n        private System.Object m_Value;\n        private Vector4 m_TextureScaleAndOffset;\n        private Vector2 m_RangeLimits;\n        private ShaderPropertyType m_Type;\n        private ShaderPropertyFlags m_Flags;\n        private UnityEngine.Rendering.TextureDimension m_TextureDimension;\n        private int m_MixedValueMask;\n\n        public Object[] targets { get { return m_Targets; } }\n        [Obsolete(\"The 'type' property is deprated. Please use 'propertyType' instead. (UnityUpgradable) -> propertyType\", false)]\n        public PropType type { get { return (PropType)m_Type; } }\n        public ShaderPropertyType propertyType { get { return m_Type; } }\n        public string name { get { return m_Name; } }\n        public string displayName { get { return m_DisplayName; } }\n        [Obsolete(\"The 'flags' property is deprated. Please use 'propertyFlags' instead. (UnityUpgradable) -> propertyFlags\", false)]\n        public PropFlags flags { get { return (PropFlags)m_Flags; } }\n        public ShaderPropertyFlags propertyFlags { get { return m_Flags; } }\n        public UnityEngine.Rendering.TextureDimension textureDimension { get { return m_TextureDimension; } }\n        public Vector2 rangeLimits { get { return m_RangeLimits; } }\n        public bool hasMixedValue { get { return (m_MixedValueMask & 1) != 0; } }\n        public ApplyPropertyCallback applyPropertyCallback { get { return m_ApplyPropertyCallback; }  set { m_ApplyPropertyCallback = value; } }\n\n        // Textures have 5 different mixed values for texture + UV scale/offset\n        internal int mixedValueMask { get { return m_MixedValueMask; } }\n\n        public void ReadFromMaterialPropertyBlock(MaterialPropertyBlock block)\n        {\n            ShaderUtil.ApplyMaterialPropertyBlockToMaterialProperty(block, this);\n        }\n\n        public void WriteToMaterialPropertyBlock(MaterialPropertyBlock materialblock, int changedPropertyMask)\n        {\n            ShaderUtil.ApplyMaterialPropertyToMaterialPropertyBlock(this, changedPropertyMask, materialblock);\n        }\n\n        public Color colorValue\n        {\n            get\n            {\n                if (m_Type == ShaderPropertyType.Color)\n                    return (Color)m_Value;\n                return Color.black;\n            }\n            set\n            {\n                if (m_Type != ShaderPropertyType.Color)\n                    return;\n                if (!hasMixedValue && value == (Color)m_Value)\n                    return;\n\n                ApplyProperty(value);\n            }\n        }\n\n        public Vector4 vectorValue\n        {\n            get\n            {\n                if (m_Type == ShaderPropertyType.Vector)\n                    return (Vector4)m_Value;\n                return Vector4.zero;\n            }\n            set\n            {\n                if (m_Type != ShaderPropertyType.Vector)\n                    return;\n                if (!hasMixedValue && value == (Vector4)m_Value)\n                    return;\n\n                ApplyProperty(value);\n            }\n        }\n\n        internal static bool IsTextureOffsetAndScaleChangedMask(int changedMask)\n        {\n            changedMask >>= 1;\n            return changedMask != 0;\n        }\n\n        public float floatValue\n        {\n            get\n            {\n                if (m_Type == ShaderPropertyType.Float || m_Type == ShaderPropertyType.Range)\n                    return (float)m_Value;\n                return 0.0f;\n            }\n            set\n            {\n                if (m_Type != ShaderPropertyType.Float && m_Type != ShaderPropertyType.Range)\n                    return;\n                if (!hasMixedValue && value == (float)m_Value)\n                    return;\n\n                ApplyProperty(value);\n            }\n        }\n\n        public int intValue\n        {\n            get\n            {\n                if (m_Type == ShaderPropertyType.Int)\n                    return (int)m_Value;\n                return 0;\n            }\n            set\n            {\n                if (m_Type != ShaderPropertyType.Int)\n                    return;\n                if (!hasMixedValue && value == (int)m_Value)\n                    return;\n\n                ApplyProperty(value);\n            }\n        }\n\n        public Texture textureValue\n        {\n            get\n            {\n                if (m_Type == ShaderPropertyType.Texture)\n                    return (Texture)m_Value;\n                return null;\n            }\n            set\n            {\n                if (m_Type != ShaderPropertyType.Texture)\n                    return;\n                if (!hasMixedValue && value == (Texture)m_Value)\n                    return;\n\n                m_MixedValueMask &= ~1;\n                object previousValue = m_Value;\n                m_Value = value;\n\n                ApplyProperty(previousValue, 1);\n            }\n        }\n\n        public Vector4 textureScaleAndOffset\n        {\n            get\n            {\n                if (m_Type == ShaderPropertyType.Texture)\n                    return m_TextureScaleAndOffset;\n                return Vector4.zero;\n            }\n            set\n            {\n                if (m_Type != ShaderPropertyType.Texture)\n                    return;\n                if (!hasMixedValue && value == m_TextureScaleAndOffset)\n                    return;\n\n                m_MixedValueMask &= 1;\n                int changedMask = 0;\n                for (int c = 1; c < 5; c++)\n                    changedMask |= 1 << c;\n\n                object previousValue = m_TextureScaleAndOffset;\n                m_TextureScaleAndOffset = value;\n                ApplyProperty(previousValue, changedMask);\n            }\n        }\n\n        private void ApplyProperty(object newValue)\n        {\n            m_MixedValueMask = 0;\n            object previousValue = m_Value;\n            m_Value = newValue;\n            ApplyProperty(previousValue, 1);\n        }\n\n        private void ApplyProperty(object previousValue, int changedPropertyMask)\n        {\n            if (targets == null || targets.Length == 0)\n                throw new ArgumentException(\"No material targets provided\");\n\n            Object[] mats = targets;\n            string targetTitle;\n            if (mats.Length == 1)\n                targetTitle = mats[0].name;\n            else\n                targetTitle = mats.Length + \" \" + ObjectNames.NicifyVariableName(ObjectNames.GetClassName(mats[0])) + \"s\";\n\n            //@TODO: Maybe all this logic should be moved to C++\n            // reduces api surface...\n            bool didApply = false;\n            if (m_ApplyPropertyCallback != null)\n                didApply = m_ApplyPropertyCallback(this, changedPropertyMask, previousValue);\n\n            if (!didApply)\n                ShaderUtil.ApplyProperty(this, changedPropertyMask, \"Modify \" + displayName + \" of \" + targetTitle);\n\n            foreach (Material material in targets)\n            {\n                if (material != null)\n                {\n                    ShaderGUIUtility.ValidateMaterial(material);\n                    // If the edited material is the base for any material variants, we may need to mark these variants\n                    // for re-validation.\n                    material.MarkChildrenNeedValidation(this.name);\n                }\n            }\n        }\n\n        // -------- helper functions to handle material variant overrides\n        // It displays the override bar on the left, the lock icon, and the bold font\n        // It also creates the context menu when left clicking a property\n\n        private static class Styles\n        {\n            public static string revertMultiText = L10n.Tr(\"Revert on {0} Material(s)\");\n            public static string applyToMaterialText = L10n.Tr(\"Apply to Material '{0}'\");\n            public static string applyToVariantText = L10n.Tr(\"Apply as Override in Variant '{0}'\");\n\n            static Color overrideLineColor_l = new Color32(0x09, 0x09, 0x09, 0xFF);\n            static Color overrideLineColor_d = new Color32(0xC4, 0xC4, 0xC4, 0xFF);\n            public static Color overrideLineColor { get { return EditorGUIUtility.isProSkin ? overrideLineColor_d : overrideLineColor_l; } }\n\n            public static readonly GUIContent revertContent = EditorGUIUtility.TrTextContent(\"Revert\");\n            public static readonly GUIContent revertAllContent = EditorGUIUtility.TrTextContent(\"Revert all Overrides\");\n            public static readonly GUIContent lockContent = EditorGUIUtility.TrTextContent(\"Lock in children\");\n            public static readonly GUIContent lockOriginContent = EditorGUIUtility.TrTextContent(\"See lock origin\");\n\n            public static readonly GUIContent resetContent = EditorGUIUtility.TrTextContent(\"Reset\");\n            public static readonly GUIContent copyContent = EditorGUIUtility.TrTextContent(\"Copy\");\n            public static readonly GUIContent pasteContent = EditorGUIUtility.TrTextContent(\"Paste\");\n\n            static readonly Texture lockInChildrenIcon = EditorGUIUtility.IconContent(\"HierarchyLock\").image;\n            public static readonly GUIContent lockInChildrenContent = EditorGUIUtility.TrTextContent(string.Empty, \"Locked properties cannot be overriden by a child.\", lockInChildrenIcon);\n\n            static readonly Texture lockedByAncestorIcon = EditorGUIUtility.IconContent(\"IN LockButton on\").image;\n            public static readonly GUIContent lockedByAncestorContent = EditorGUIUtility.TrTextContent(string.Empty, \"This property is set and locked by an ancestor.\", lockedByAncestorIcon);\n\n            public static readonly GUIStyle centered = new GUIStyle(EditorStyles.label) { alignment = TextAnchor.MiddleLeft };\n        }\n\n        struct PropertyData\n        {\n            public MaterialProperty property;\n            public MaterialSerializedProperty serializedProperty;\n            public Object[] targets;\n\n            public bool wasBoldDefaultFont;\n            public bool allowLocking;\n            public bool isLockedInChildren, isLockedByAncestor, isOverriden;\n\n            public float startY;\n            public Rect position;\n\n            private static List<MaterialProperty> capturedProperties = new List<MaterialProperty>();\n            private static List<MaterialSerializedProperty> capturedSerializedProperties = new List<MaterialSerializedProperty>();\n\n            private bool HasMixedValues<T>(Func<Material, T> getter)\n            {\n                T value = getter(targets[0] as Material);\n                for (int i = 1; i < targets.Length; ++i)\n                {\n                    if (!EqualityComparer<T>.Default.Equals(value, getter(targets[i] as Material)))\n                        return true;\n                }\n                return false;\n            }\n\n            public bool hasMixedValue\n            {\n                get\n                {\n                    if (property != null)\n                        return property.hasMixedValue;\n\n                    if (serializedProperty == MaterialSerializedProperty.EnableInstancingVariants)\n                        return HasMixedValues((mat) => mat.enableInstancing);\n                    else if (serializedProperty == MaterialSerializedProperty.LightmapFlags)\n                        return HasMixedValues((mat) => mat.globalIlluminationFlags);\n                    else if (serializedProperty == MaterialSerializedProperty.DoubleSidedGI)\n                        return HasMixedValues((mat) => mat.doubleSidedGI);\n                    else if (serializedProperty == MaterialSerializedProperty.CustomRenderQueue)\n                        return HasMixedValues((mat) => mat.rawRenderQueue);\n                    return false;\n                }\n            }\n\n            public void Init()\n            {\n                isLockedInChildren = false;\n                isLockedByAncestor = false;\n                allowLocking = true;\n                isOverriden = true;\n                int nameId = property != null ? Shader.PropertyToID(property.name) : -1;\n                foreach (Material target in targets)\n                {\n                    bool l, b, o;\n                    if (property != null)\n                        target.GetPropertyState(nameId, out o, out l, out b);\n                    else\n                        target.GetPropertyState(serializedProperty, out o, out l, out b);\n                    // When multi editing:\n                    // 1. Show property as locked if any target is locked, to prevent bypassing the lock\n                    // 2. Show property as overriden if all targets override it, to not show overrides on materials\n                    isLockedInChildren |= l;\n                    isLockedByAncestor |= b;\n                    isOverriden &= o;\n                    allowLocking &= target.allowLocking;\n                }\n            }\n\n            static void MergeStack(out bool lockedInChildren, out bool lockedByAncestor, out bool overriden)\n            {\n                // We have to copy the property stack, because access from the Menu callbacks is delayed\n                capturedProperties.Clear();\n                capturedSerializedProperties.Clear();\n\n                lockedInChildren = false;\n                lockedByAncestor = false;\n                overriden = false;\n                for (int i = 0; i < s_PropertyStack.Count; i++)\n                {\n                    // When multiple properties are displayed on the same line, we *or* everything otherwise it gets confusing.\n                    if (s_PropertyStack[i].targets == null) continue;\n                    lockedInChildren |= s_PropertyStack[i].isLockedInChildren;\n                    lockedByAncestor |= s_PropertyStack[i].isLockedByAncestor;\n                    overriden        |= s_PropertyStack[i].isOverriden;\n\n                    if (s_PropertyStack[i].property != null)\n                        capturedProperties.Add(s_PropertyStack[i].property);\n                    else\n                        capturedSerializedProperties.Add(s_PropertyStack[i].serializedProperty);\n                }\n            }\n\n            static string GetMultiEditingDisplayName(string multiEditSuffix)\n            {\n                int nonEmptyCount = capturedProperties.Count + capturedSerializedProperties.Count;\n                if (nonEmptyCount != 1)\n                    return nonEmptyCount + \" \" + multiEditSuffix;\n                else if (capturedProperties.Count != 0)\n                    return capturedProperties[0].displayName;\n                else\n                    return capturedSerializedProperties[0].ToString();\n            }\n\n            public static void DoPropertyContextMenu(bool lockMenusOnly, Object[] targets, bool allowLocking)\n            {\n                MergeStack(out bool lockedInChildren, out bool lockedByAncestor, out bool overriden);\n\n                GenericMenu menu = new GenericMenu();\n\n                if (lockedByAncestor)\n                {\n                    if (targets.Length != 1)\n                        return;\n\n                    menu.AddItem(Styles.lockOriginContent, false, () => GotoLockOriginAction(targets));\n                }\n                else if (GUI.enabled)\n                {\n                    if (!lockMenusOnly)\n                        DoRegularMenu(menu, overriden, targets);\n                    DoLockPropertiesMenu(menu, !lockedInChildren, targets, allowLocking);\n                }\n\n                if (Event.current.shift && capturedProperties.Count == 1)\n                {\n                    if (menu.GetItemCount() != 0)\n                        menu.AddSeparator(\"\");\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Copy Property Name\"), false, () => EditorGUIUtility.systemCopyBuffer = capturedProperties[0].name);\n                }\n\n                if (menu.GetItemCount() == 0)\n                    return;\n\n                Event.current.Use();\n                menu.ShowAsContext();\n            }\n\n            enum DisplayMode { Material, Variant, Mixed };\n            static DisplayMode GetDisplayMode(Object[] targets)\n            {\n                int variantCount = MaterialEditor.GetVariantCount(targets);\n                if (variantCount == 0)\n                    return DisplayMode.Material;\n                if (variantCount == targets.Length)\n                    return DisplayMode.Variant;\n                return DisplayMode.Mixed;\n            }\n\n            static void ResetMaterialProperties()\n            {\n                foreach (var property in capturedProperties)\n                {\n                    // fetch default value from shader\n                    var shader = (property.targets[0] as Material).shader;\n                    int nameId = shader.FindPropertyIndex(property.name);\n                    switch (property.propertyType)\n                    {\n                        case ShaderPropertyType.Float:\n                        case ShaderPropertyType.Range:\n                            property.floatValue = shader.GetPropertyDefaultFloatValue(nameId);\n                            break;\n                        case ShaderPropertyType.Vector:\n                            property.vectorValue = shader.GetPropertyDefaultVectorValue(nameId);\n                            break;\n                        case ShaderPropertyType.Color:\n                            property.colorValue = shader.GetPropertyDefaultVectorValue(nameId);\n                            break;\n                        case ShaderPropertyType.Int:\n                            property.intValue = shader.GetPropertyDefaultIntValue(nameId);\n                            break;\n                        case ShaderPropertyType.Texture:\n                            Texture texture = null;\n                            var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(shader)) as ShaderImporter;\n                            if (importer != null)\n                                texture = importer.GetDefaultTexture(property.name);\n                            if (texture == null)\n                                texture = EditorMaterialUtility.GetShaderDefaultTexture(shader, property.name);\n                            property.textureValue = texture;\n                            property.textureScaleAndOffset = new Vector4(1, 1, 0, 0);\n                            break;\n                    }\n                }\n            }\n\n            static void HandleApplyRevert(GenericMenu menu, bool singleEditing, Object[] targets)\n            {\n                // Apply\n                if (singleEditing)\n                {\n                    Material source = (Material)targets[0];\n                    Material destination = (Material)targets[0];\n                    while (destination = destination.parent as Material)\n                    {\n                        if (AssetDatabase.IsForeignAsset(destination))\n                            continue;\n\n                        var text = destination.isVariant ? Styles.applyToVariantText : Styles.applyToMaterialText;\n                        var applyContent = new GUIContent(string.Format(text, destination.name));\n\n                        menu.AddItem(applyContent, false, (object dest) => {\n                            foreach (var prop in capturedProperties)\n                                source.ApplyPropertyOverride((Material)dest, prop.name);\n                            foreach (var prop in capturedSerializedProperties)\n                                source.ApplyPropertyOverride((Material)dest, prop);\n                        }, destination);\n                    }\n                }\n\n                // Revert\n                var content = singleEditing ? Styles.revertContent :\n                    EditorGUIUtility.TempContent(string.Format(Styles.revertMultiText, targets.Length));\n                menu.AddItem(content, false, () => {\n                    string displayName = GetMultiEditingDisplayName(\"overrides\");\n                    string targetName = singleEditing ? targets[0].name : targets.Length + \" Materials\";\n                    Undo.RecordObjects(targets, \"Revert \" + displayName + \" of \" + targetName);\n\n                    foreach (Material target in targets)\n                    {\n                        foreach (var prop in capturedProperties)\n                            target.RevertPropertyOverride(prop.name);\n                        foreach (var prop in capturedSerializedProperties)\n                            target.RevertPropertyOverride(prop);\n                    }\n                });\n            }\n\n            static void HandleCopyPaste(GenericMenu menu)\n            {\n                GetCopyPasteAction(s_CopyPasteCache, out var copyAction, out var pasteAction);\n\n                if (menu.GetItemCount() != 0)\n                    menu.AddSeparator(\"\");\n\n                if (copyAction != null)\n                    menu.AddItem(Styles.copyContent, false, copyAction);\n                else\n                    menu.AddDisabledItem(Styles.copyContent);\n                if (pasteAction != null)\n                    menu.AddItem(Styles.pasteContent, false, pasteAction);\n                else\n                    menu.AddDisabledItem(Styles.pasteContent);\n            }\n\n            static void HandleRevertAll(GenericMenu menu, bool singleEditing, Object[] targets)\n            {\n                foreach (Material target in targets)\n                {\n                    if (target.overrideCount != 0)\n                    {\n                        if (menu.GetItemCount() != 0)\n                            menu.AddSeparator(\"\");\n\n                        menu.AddItem(Styles.revertAllContent, false, () => {\n                                string targetName = singleEditing ? targets[0].name : targets.Length + \" Materials\";\n                                Undo.RecordObjects(targets, \"Revert all overrides of \" + targetName);\n\n                                foreach (Material target in targets)\n                                target.RevertAllPropertyOverrides();\n                                });\n                        break;\n                    }\n                }\n            }\n\n            static void DoRegularMenu(GenericMenu menu, bool isOverriden, Object[] targets)\n            {\n                var singleEditing = targets.Length == 1;\n\n                if (isOverriden)\n                    HandleApplyRevert(menu, singleEditing, targets);\n\n                if (singleEditing && s_CopyPasteCache != null)\n                {\n                    HandleCopyPaste(menu);\n                    s_CopyPasteCache = null;\n                }\n                DisplayMode displayMode = GetDisplayMode(targets);\n                if (displayMode == DisplayMode.Material)\n                {\n                    if (menu.GetItemCount() != 0)\n                        menu.AddSeparator(\"\");\n\n                    menu.AddItem(Styles.resetContent, false, ResetMaterialProperties);\n                }\n                else if (displayMode == DisplayMode.Variant)\n                    HandleRevertAll(menu, singleEditing, targets);\n            }\n\n            static void GetCopyPasteAction(MaterialProperty prop, out GenericMenu.MenuFunction copyAction, out GenericMenu.MenuFunction pasteAction)\n            {\n                bool canCopy = !s_CopyPasteCache.hasMixedValue;\n                bool canPaste = GUI.enabled;\n\n                copyAction = null;\n                pasteAction = null;\n                switch (prop.propertyType)\n                {\n                    case ShaderPropertyType.Float:\n                    case ShaderPropertyType.Range:\n                        if (canCopy) copyAction = () => Clipboard.floatValue = prop.floatValue;\n                        if (canPaste && Clipboard.hasFloat) pasteAction = () => prop.floatValue = Clipboard.floatValue;\n                        break;\n                    case ShaderPropertyType.Int:\n                        if (canCopy) copyAction = () => Clipboard.integerValue = prop.intValue;\n                        if (canPaste && Clipboard.hasInteger) pasteAction = () => prop.intValue = Clipboard.integerValue;\n                        break;\n                    case ShaderPropertyType.Color:\n                        if (canCopy) copyAction = () => Clipboard.colorValue = prop.colorValue;\n                        if (canPaste && Clipboard.hasColor) pasteAction = () => prop.colorValue = Clipboard.colorValue;\n                        break;\n                    case ShaderPropertyType.Vector:\n                        if (canCopy) copyAction = () => Clipboard.vector4Value = prop.vectorValue;\n                        if (canPaste && Clipboard.hasVector4) pasteAction = () => prop.vectorValue = Clipboard.vector4Value;\n                        break;\n                    case ShaderPropertyType.Texture:\n                        if (canCopy) copyAction = () => Clipboard.guidValue = AssetDatabase.GUIDFromAssetPath(AssetDatabase.GetAssetPath(prop.textureValue));\n                        if (canPaste && Clipboard.hasGuid) pasteAction = () => prop.textureValue = AssetDatabase.LoadMainAssetAtPath(AssetDatabase.GUIDToAssetPath(Clipboard.guidValue)) as Texture;\n                        break;\n                }\n            }\n\n            static void DoLockPropertiesMenu(GenericMenu menu, bool lockValue, Object[] targets, bool allowLocking)\n            {\n                if (menu.GetItemCount() != 0)\n                    menu.AddSeparator(\"\");\n\n                if (allowLocking)\n                {\n                    menu.AddItem(Styles.lockContent, !lockValue, () => { LockProperties(lockValue, targets); });\n                }\n                else\n                {\n                    menu.AddDisabledItem(Styles.lockContent);\n                }\n            }\n\n            static void LockProperties(bool lockValue, Object[] targets)\n            {\n                string actionName = lockValue ? \"locking\" : \"unlocking\";\n                string displayName = GetMultiEditingDisplayName(\"properties\");\n                string targetName = targets.Length == 1 ? targets[0].name : targets.Length + \" Materials\";\n                Undo.RecordObjects(targets, string.Format(\"{0} {1} of {2}\", actionName, displayName, targetName));\n\n                foreach (Material target in targets)\n                {\n                    foreach (var prop in capturedProperties)\n                        target.SetPropertyLock(prop.name, lockValue);\n                    foreach (var prop in capturedSerializedProperties)\n                        target.SetPropertyLock(prop, lockValue);\n                }\n            }\n\n            static public void DoLockAction(Object[] targets)\n            {\n                MergeStack(out bool lockedInChildren, out bool lockedByAncestor, out bool _);\n\n                if (lockedByAncestor)\n                    GotoLockOriginAction(targets);\n                else\n                    LockProperties(!lockedInChildren, targets);\n\n                Event.current.Use();\n            }\n\n            static void GotoLockOriginAction(Object[] targets)\n            {\n                // Find lock origin\n                Material origin = targets[0] as Material;\n                while ((origin = origin.parent))\n                {\n                    bool isLocked = false;\n                    foreach (var prop in capturedProperties)\n                    {\n                        origin.GetPropertyState(Shader.PropertyToID(prop.name), out _, out isLocked, out _);\n                        if (isLocked) break;\n                    }\n                    if (isLocked) break;\n\n                    foreach (var prop in capturedSerializedProperties)\n                    {\n                        origin.GetPropertyState(prop, out _, out isLocked, out _);\n                        if (isLocked) break;\n                    }\n                    if (isLocked) break;\n                }\n\n                if (origin)\n                {\n                    int clickCount = 1;\n                    if (Event.current != null)\n                    {\n                        clickCount = Event.current.clickCount;\n                        Event.current.Use();\n                    }\n                    if (clickCount == 1)\n                        EditorGUIUtility.PingObject(origin);\n                    else\n                    {\n                        Selection.SetActiveObjectWithContext(origin, null);\n                        GUIUtility.ExitGUI();\n                    }\n                }\n            }\n        }\n        static List<PropertyData> s_PropertyStack = new List<PropertyData>();\n        static MaterialProperty s_CopyPasteCache = null;\n        internal static void ClearStack() => s_PropertyStack.Clear();\n\n        internal static void BeginProperty(MaterialProperty prop, Object[] targets)\n        {\n            // Get the current Y coordinate before drawing the property\n            // We define a new empty rect in order to grab the current height even if there was nothing drawn in the block\n            // (GetLastRect cause issue if it was first element of block)\n            MaterialProperty.BeginProperty(Rect.zero, prop, 0, targets, GUILayoutUtility.GetRect(0, 0).yMax);\n        }\n\n        internal static void BeginProperty(MaterialSerializedProperty prop, Object[] targets)\n        {\n            // Get the current Y coordinate before drawing the property\n            // We define a new empty rect in order to grab the current height even if there was nothing drawn in the block\n            // (GetLastRect cause issue if it was first element of block)\n            MaterialProperty.BeginProperty(Rect.zero, null, prop, targets, GUILayoutUtility.GetRect(0, 0).yMax);\n        }\n\n        internal static void BeginProperty(Rect totalRect, MaterialProperty prop, MaterialSerializedProperty serializedProp, Object[] targets, float startY = -1)\n        {\n            if (Event.current.rawType == EventType.ContextClick && (totalRect.Contains(Event.current.mousePosition)))\n                s_CopyPasteCache = prop;\n\n            if (targets == null || IsRegistered(prop, serializedProp))\n            {\n                s_PropertyStack.Add(new PropertyData() { targets = null });\n                return;\n            }\n\n            PropertyData data = new PropertyData()\n            {\n                property = prop,\n                serializedProperty = serializedProp,\n                targets = targets,\n\n                startY = startY,\n                position = totalRect,\n                wasBoldDefaultFont = EditorGUIUtility.GetBoldDefaultFont()\n            };\n            data.Init();\n            s_PropertyStack.Add(data);\n\n            if (data.isOverriden)\n                EditorGUIUtility.SetBoldDefaultFont(true);\n\n            if (data.isLockedByAncestor)\n                EditorGUI.BeginDisabledGroup(true);\n\n            EditorGUI.showMixedValue = data.hasMixedValue;\n        }\n\n        internal static void EndProperty()\n        {\n            if (s_PropertyStack.Count == 0)\n            {\n                Debug.LogError(\"MaterialProperty stack is empty\");\n                return;\n            }\n            var data = s_PropertyStack[s_PropertyStack.Count - 1];\n            if (data.targets == null)\n            {\n                s_PropertyStack.RemoveAt(s_PropertyStack.Count - 1);\n                return;\n            }\n\n            Rect position = data.position;\n            if (data.startY != -1)\n            {\n                position = GUILayoutUtility.GetLastRect();\n                position.yMin = data.startY;\n                position.x = 1;\n                position.width = EditorGUIUtility.labelWidth;\n            }\n\n            bool mouseOnLock = false;\n            if (position != Rect.zero)\n            {\n                // Display override rect\n                if (data.isOverriden)\n                    EditorGUI.DrawMarginLineForRect(position, Styles.overrideLineColor);\n\n                Rect lockRegion = position;\n                lockRegion.width = 14;\n                lockRegion.height = 14;\n                lockRegion.x = 11;\n                lockRegion.y += (position.height - lockRegion.height) * 0.5f;\n                mouseOnLock = lockRegion.Contains(Event.current.mousePosition);\n\n                // Display lock icon\n                Rect lockRect = position;\n                lockRect.width = 32;\n                lockRect.height = Mathf.Max(lockRect.height, 20.0f);\n                lockRect.x = 8;\n                lockRect.y += (position.height - lockRect.height) * 0.5f;\n\n                if (data.isLockedByAncestor)\n                {\n                    // Make sure we draw the lock only once\n                    bool isLastLockInStack = true;\n                    for (int i = 0; i < s_PropertyStack.Count - 1; i++)\n                    {\n                        if (s_PropertyStack[i].isLockedByAncestor)\n                        {\n                            isLastLockInStack = false;\n                            break;\n                        }\n                    }\n\n                    if (isLastLockInStack)\n                        GUI.Label(lockRect, Styles.lockedByAncestorContent, Styles.centered);\n                }\n                else if (data.isLockedInChildren)\n                    GUI.Label(lockRect, Styles.lockInChildrenContent, Styles.centered);\n                else if (GUI.enabled && data.allowLocking)\n                {\n                    GUIView.current?.MarkHotRegion(GUIClip.UnclipToWindow(lockRegion));\n                    if (mouseOnLock)\n                    {\n                        EditorGUI.BeginDisabledGroup(true);\n                        GUI.Label(lockRect, Styles.lockInChildrenContent, Styles.centered);\n                        EditorGUI.EndDisabledGroup();\n                    }\n                }\n            }\n\n            // Restore state\n            EditorGUI.showMixedValue = false;\n\n            EditorGUIUtility.SetBoldDefaultFont(data.wasBoldDefaultFont);\n\n            if (data.isLockedByAncestor)\n                EditorGUI.EndDisabledGroup();\n\n            // Context menu\n            if (Event.current.rawType == EventType.ContextClick && (position.Contains(Event.current.mousePosition) || mouseOnLock))\n                PropertyData.DoPropertyContextMenu(mouseOnLock, data.targets, data.allowLocking);\n            else if (Event.current.type == EventType.MouseUp && Event.current.button == 0 && mouseOnLock && data.allowLocking)\n                PropertyData.DoLockAction(data.targets);\n\n            s_PropertyStack.RemoveAt(s_PropertyStack.Count - 1);\n        }\n\n        static bool IsRegistered(MaterialProperty prop, MaterialSerializedProperty serializedProp)\n        {\n            // [PerRendererData] material properties are read-only as they are meant to be set in code on a per-renderer basis.\n            // Don't show override UI for them\n            if (prop != null && (prop.propertyFlags & ShaderPropertyFlags.PerRendererData) != 0)\n                return true;\n            for (int i = 0; i < s_PropertyStack.Count; i++)\n            {\n                if (s_PropertyStack[i].property == prop && s_PropertyStack[i].serializedProperty == serializedProp)\n                    return true;\n            }\n            return false;\n        }\n    }\n} // namespace UnityEngine.Rendering\n"
  },
  {
    "path": "Editor/Mono/MaterialProperty.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor\n{\n    partial class MaterialProperty\n    {\n        [Obsolete(\"Use UnityEngine.Rendering.ShaderPropertyType instead. (UnityUpgradable) -> UnityEngine.Rendering.ShaderPropertyType\", false)]\n        public enum PropType\n        {\n            Color,\n            Vector,\n            Float,\n            Range,\n            Texture,\n            Int,\n        }\n\n        [Obsolete(\"Use UnityEngine.Rendering.ShaderPropertyFlags instead. (UnityUpgradable) -> UnityEngine.Rendering.ShaderPropertyFlags\", false)]\n        [Flags]\n        public enum PropFlags\n        {\n            None = 0,\n            HideInInspector = (1 << 0),\n            PerRendererData = (1 << 1),\n            NoScaleOffset = (1 << 2),\n            Normal = (1 << 3),\n            HDR = (1 << 4),\n            Gamma = (1 << 5),\n            NonModifiableTextureData = (1 << 6),\n        }\n\n        [Obsolete(\"Use UnityEngine.Rendering.TextureDimension instead. (UnityUpgradable) -> UnityEngine.Rendering.TextureDimension\", true)]\n        public enum TexDim\n        {\n            Unknown = -1,\n            None = 0,\n            Tex2D = 2,\n            Tex3D = 3,\n            Cube = 4,\n            Any = 6,\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Media/Bindings/MediaDecoder.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing Unity.Collections;\nusing Unity.Collections.LowLevel.Unsafe;\nusing UnityEditor.Media;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEngine.Video;\nusing System.Runtime.CompilerServices;\n\n[assembly: InternalsVisibleTo(\"VideoTesting\")]\nnamespace UnityEditorInternal.Media\n{\n    internal class MediaDecoder : IDisposable\n    {\n        IntPtr m_Ptr;\n\n        public MediaDecoder(string filePath)\n        {\n            m_Ptr = Create(filePath);\n        }\n\n        public MediaDecoder(VideoClip clip)\n        {\n            m_Ptr = Create(clip);\n        }\n\n        ~MediaDecoder()\n        {\n            Dispose();\n        }\n\n        public bool GetNextFrame(Texture2D tex, out MediaTime time)\n        {\n            ThrowIfDisposed();\n            return Internal_MediaDecoder_GetNextFrame(m_Ptr, tex, out time);\n        }\n\n        public int GetNextSamples(ushort trackIndex, NativeArray<float> interleavedSamples)\n        {\n            ThrowIfDisposed();\n            unsafe\n            {\n                return Internal_MediaDecoder_GetNextSamples(\n                    m_Ptr, trackIndex, interleavedSamples.GetUnsafePtr(), interleavedSamples.Length);\n            }\n        }\n\n        public bool SetPosition(MediaTime time)\n        {\n            ThrowIfDisposed();\n            return Internal_MediaDecoder_SetPosition(m_Ptr, time);\n        }\n\n        public string[] GetCustomDependencies()\n        {\n            ThrowIfDisposed();\n            return Internal_MediaDecoder_GetCustomDependencies(m_Ptr);\n        }\n\n        public void Dispose()\n        {\n            if (m_Ptr != IntPtr.Zero)\n            {\n                Internal_Release(m_Ptr);\n                m_Ptr = IntPtr.Zero;\n            }\n            GC.SuppressFinalize(this);\n        }\n\n        private IntPtr Create(string filePath)\n        {\n            IntPtr ptr = Internal_MediaDecoder_Create(filePath);\n            if (ptr == IntPtr.Zero)\n                throw new InvalidOperationException(\n                    \"MediaDecoder: Could not open \" + filePath);\n            return ptr;\n        }\n\n        private IntPtr Create(VideoClip clip)\n        {\n            IntPtr ptr = Internal_MediaDecoder_CreateFromClip(clip);\n            if (ptr == IntPtr.Zero)\n                throw new InvalidOperationException(\n                    \"MediaDecoder: Could not open clip \" + clip.name);\n            return ptr;\n        }\n\n        private void ThrowIfDisposed()\n        {\n            if (m_Ptr == IntPtr.Zero)\n                throw new ObjectDisposedException(\"MediaDecoder\");\n        }\n\n        [NativeHeader(\"Editor/Mono/Media/Bindings/MediaDecoder.bindings.h\")]\n        [FreeFunction]\n        extern private static IntPtr Internal_MediaDecoder_Create(string filePath);\n\n        [NativeHeader(\"Editor/Mono/Media/Bindings/MediaDecoder.bindings.h\")]\n        [FreeFunction]\n        extern private static IntPtr Internal_MediaDecoder_CreateFromClip([NotNull] VideoClip clip);\n\n        [NativeHeader(\"Modules/Video/Public/Base/VideoClipMedia.h\")]\n        [FreeFunction(\"VideoClipMedia::Release\")]\n        extern private static void Internal_Release(IntPtr decoder);\n\n        [FreeFunction]\n        extern private static bool Internal_MediaDecoder_GetNextFrame(IntPtr decoder, [NotNull] Texture2D texture, out MediaTime time);\n\n        [FreeFunction]\n        unsafe extern private static int Internal_MediaDecoder_GetNextSamples(IntPtr decoder, ushort trackIndex, void* buffer, int sampleCount);\n\n        [FreeFunction]\n        extern private static bool Internal_MediaDecoder_SetPosition(IntPtr decoder, MediaTime time);\n\n        [NativeHeader(\"Editor/Mono/Media/Bindings/MediaDecoder.bindings.h\")]\n        [FreeFunction]\n        extern private static string[] Internal_MediaDecoder_GetCustomDependencies(IntPtr decoder);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Media/Bindings/MediaEncoder.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngineInternal.Video;\nusing Unity.Collections;\nusing Unity.Collections.LowLevel.Unsafe;\nusing Object = UnityEngine.Object;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n[assembly: InternalsVisibleTo(\"VideoTesting\")]\nnamespace UnityEditor.Media\n{\n    [NativeHeader(\"Editor/Mono/Media/Bindings/MediaEncoder.bindings.h\")]\n\n    public struct MediaRational\n    {\n        public static readonly MediaRational Invalid = new MediaRational { numerator = 0, denominator = 0 };\n\n        public MediaRational(int numerator)\n        {\n            this.numerator = numerator;\n            this.denominator = 1;\n        }\n\n        public MediaRational(int numerator, int denominator)\n        {\n            this.numerator = numerator;\n            this.denominator = denominator;\n            Reduce();\n        }\n\n        public void Set(int numerator, int denominator = 1)\n        {\n            this.numerator = numerator;\n            this.denominator = denominator;\n            Reduce();\n        }\n\n        public static explicit operator double(MediaRational r)\n        {\n            return (r.denominator == 0) ? 0.0 : ((double)r.numerator / r.denominator);\n        }\n\n        public MediaRational inverse\n        {\n            get { return new MediaRational(denominator, numerator); }\n        }\n\n        public bool isValid { get { return denominator != 0; } }\n        public bool isZero { get { return isValid && numerator == 0; } }\n        public bool isNegative\n        { get { return isValid && ((numerator < 0) != (denominator < 0)); } }\n\n        public int numerator;\n        public int denominator;\n\n        private void Reduce()\n        {\n            Internal_MediaRational_Reduce(ref numerator, ref denominator);\n        }\n\n        [FreeFunction]\n        extern private static void Internal_MediaRational_Reduce(ref int numerator, ref int denominator);\n    }\n\n    public struct MediaTime\n    {\n        public static readonly MediaTime Invalid = new MediaTime { count = 0, rate = MediaRational.Invalid };\n\n        public MediaTime(long seconds) : this(seconds, 1)\n        {}\n\n        public MediaTime(long count, uint rateNumerator, uint rateDenominator = 1)\n        {\n            this.count = count;\n            m_Rate = new MediaRational(Convert.ToInt32(rateNumerator), Convert.ToInt32(rateDenominator));\n        }\n\n        public static explicit operator double(MediaTime t)\n        {\n            return t.count * (double)t.rate.inverse;\n        }\n\n        public long count { set; get; }\n        public MediaRational rate\n        {\n            set\n            {\n                if (value.isNegative)\n                    throw new ArgumentException(\"MediaTime expects a positive rate.\");\n                m_Rate.Set(value.numerator, value.denominator);\n            }\n\n            get { return m_Rate; }\n        }\n\n        private MediaRational m_Rate;\n    }\n\n    public struct H264EncoderAttributes\n    {\n        public uint gopSize;\n        public uint numConsecutiveBFrames;\n        public VideoEncodingProfile profile;\n    }\n\n    public struct VP8EncoderAttributes\n    {\n        public uint keyframeDistance;\n        internal VideoAlphaLayout alphaLayout;\n    }\n\n    [StructLayout(LayoutKind.Explicit)]\n    public struct VideoTrackEncoderAttributes\n    {\n        [FieldOffset(0)] public MediaRational           frameRate;\n        [FieldOffset(8)] public uint                    width;\n        [FieldOffset(12)] public uint                   height;\n        [FieldOffset(16)] public uint                   targetBitRate;\n        [FieldOffset(20)] public VideoBitrateMode       bitRateMode;\n        [FieldOffset(24)] public bool                   includeAlpha;\n\n        [FieldOffset(28)] private VideoCodec            codecType;\n        [FieldOffset(32)] private H264EncoderAttributes h264;\n        [FieldOffset(32)] private VP8EncoderAttributes  vp8;\n\n        public VideoTrackEncoderAttributes(H264EncoderAttributes h264Attrs) : this()\n        {\n            if (h264Attrs.profile == VideoEncodingProfile.H264Baseline && h264Attrs.numConsecutiveBFrames != 0)\n            {\n                h264Attrs.numConsecutiveBFrames = 0;\n                Debug.Log(\"VideoTrackEncoderAttributes: B-frames are not used when encoding profile is set to baseline inside the encoder. NumConsecutiveBFrames will be set to 0.\");\n            }\n            else if (h264Attrs.numConsecutiveBFrames > 2)\n            {\n                h264Attrs.numConsecutiveBFrames = 2;\n                Debug.Log(\"VideoTrackEncoderAttributes: Maximum number of consecutive B-frames is 2. NumConsecutiveBFrames will be set to 2.\");\n            }\n\n\n            h264 = h264Attrs;\n            codecType = VideoCodec.H264;\n        }\n\n        public VideoTrackEncoderAttributes(VP8EncoderAttributes vp8Attrs) : this()\n        {\n            vp8 = vp8Attrs;\n            codecType = VideoCodec.VP8;\n        }\n\n        internal VideoTrackEncoderAttributes(VideoTrackAttributes videoAttrs) : this()\n        {\n            frameRate = videoAttrs.frameRate;\n            width = videoAttrs.width;\n            height = videoAttrs.height;\n            includeAlpha = videoAttrs.includeAlpha;\n            bitRateMode = videoAttrs.bitRateMode;\n            codecType = videoAttrs.codec;\n            vp8.alphaLayout = videoAttrs.alphaLayout;\n        }\n    }\n\n    public struct VideoTrackAttributes\n    {\n        public MediaRational      frameRate;\n        public uint               width;\n        public uint               height;\n        public bool               includeAlpha; // For webm only; not applicable to mp4.\n        public VideoBitrateMode   bitRateMode;\n        internal VideoCodec       codec;\n        internal VideoAlphaLayout alphaLayout;\n    }\n\n    public struct AudioTrackAttributes\n    {\n        public MediaRational sampleRate;\n        public ushort        channelCount;\n        public string        language;\n        //Future work:\n        //public string      format;   // E.g.: \"Stereo\", \"5.1\", \"Ambisonic 1st order\", ...\n        //public string      layout[]; // E.g.: [\"Left\", \"Right\", \"Center\"]\n    }\n\n    public class MediaEncoder : IDisposable\n    {\n        IntPtr m_ThisPtr;\n\n        [Obsolete(\"Was made public by mistake. Not meant to be used by user code.\", true)]\n        public IntPtr m_Ptr;\n\n        public MediaEncoder(\n            string filePath, VideoTrackAttributes videoAttrs, AudioTrackAttributes[] audioAttrs)\n        {\n            m_ThisPtr = Create(filePath, videoAttrs, audioAttrs);\n        }\n\n        public MediaEncoder(\n            string filePath, VideoTrackEncoderAttributes videoAttrs, AudioTrackAttributes[] audioAttrs)\n        {\n            m_ThisPtr = Create(filePath, videoAttrs, audioAttrs);\n        }\n\n        public MediaEncoder(\n            string filePath, VideoTrackEncoderAttributes videoAttrs, AudioTrackAttributes audioAttrs)\n            : this(filePath, videoAttrs, new[] { audioAttrs })\n        {\n        }\n\n        public MediaEncoder(\n            string filePath, VideoTrackEncoderAttributes videoAttrs)\n            : this(filePath, videoAttrs, new AudioTrackAttributes[0])\n        {\n        }\n\n        public MediaEncoder(\n            string filePath, VideoTrackAttributes videoAttrs, AudioTrackAttributes audioAttrs)\n            : this(filePath, videoAttrs, new[] {audioAttrs})\n        {}\n\n        public MediaEncoder(string filePath, VideoTrackAttributes videoAttrs)\n            : this(filePath, videoAttrs, new AudioTrackAttributes[0])\n        {}\n\n        public MediaEncoder(string filePath, AudioTrackAttributes[] audioAttrs)\n        {\n            m_ThisPtr = Create(filePath, audioAttrs);\n        }\n\n        public MediaEncoder(string filePath, AudioTrackAttributes audioAttrs)\n            : this(filePath, new[] {audioAttrs})\n        {}\n\n        ~MediaEncoder()\n        {\n            Dispose();\n        }\n\n        unsafe public bool AddFrame(\n            int width, int height, int rowBytes, TextureFormat format, NativeArray<byte> data)\n        {\n            ThrowIfDisposed();\n            return Internal_AddFrameRaw(\n                m_ThisPtr, width, height, rowBytes, format, data.GetUnsafeReadOnlyPtr(), data.Length, MediaTime.Invalid);\n        }\n\n        unsafe public bool AddFrame(\n            int width, int height, int rowBytes, TextureFormat format, NativeArray<byte> data, MediaTime time)\n        {\n            ThrowIfDisposed();\n            return Internal_AddFrameRaw(\n                m_ThisPtr, width, height, rowBytes, format, data.GetUnsafeReadOnlyPtr(), data.Length, time);\n        }\n\n        public bool AddFrame(Texture2D texture)\n        {\n            ThrowIfDisposed();\n            return Internal_AddFrame(m_ThisPtr, texture, MediaTime.Invalid);\n        }\n\n        public bool AddFrame(Texture2D texture, MediaTime time)\n        {\n            ThrowIfDisposed();\n            return Internal_AddFrame(m_ThisPtr, texture, time);\n        }\n\n        unsafe public bool AddSamples(ushort trackIndex, NativeArray<float> interleavedSamples)\n        {\n            ThrowIfDisposed();\n            return Internal_AddSamples(\n                m_ThisPtr, trackIndex, interleavedSamples.GetUnsafeReadOnlyPtr(),\n                interleavedSamples.Length);\n        }\n\n        public bool AddSamples(NativeArray<float> interleavedSamples)\n        {\n            return AddSamples(0, interleavedSamples);\n        }\n\n        public void Dispose()\n        {\n            if (m_ThisPtr != IntPtr.Zero)\n            {\n                Internal_Release(m_ThisPtr);\n                m_ThisPtr = IntPtr.Zero;\n            }\n            GC.SuppressFinalize(this);\n        }\n\n        private void ValidateVideoAttributes(VideoTrackEncoderAttributes videoAttrs)\n        {\n            var rate = videoAttrs.frameRate;\n            if (rate.isNegative)\n                throw new ArgumentException($\"Negative frame rate not supported: {rate.numerator}/{rate.denominator}\");\n        }\n\n        private void ValidateAudioAttributes(AudioTrackAttributes[] audioAttrs)\n        {\n            foreach (var a in audioAttrs)\n            {\n                var r = a.sampleRate;\n                if (!r.isValid)\n                    throw new ArgumentException($\"Invalid sample rate: {r.numerator}/{r.denominator}\");\n                if (r.isZero)\n                    throw new ArgumentException($\"Zero sample rate not supported: {r.numerator}/{r.denominator}\");\n                if (r.isNegative)\n                    throw new ArgumentException($\"Negative sample rate not supported: {r.numerator}/{r.denominator}\");\n            }\n        }\n\n        private IntPtr Create(\n            string filePath, VideoTrackAttributes videoAttrs, AudioTrackAttributes[] audioAttrs)\n        {\n            VideoTrackEncoderAttributes videoEncoderAttrs = new VideoTrackEncoderAttributes(videoAttrs);\n\n            return Create(filePath, videoEncoderAttrs, audioAttrs);\n        }\n\n        private IntPtr Create(\n            string filePath, VideoTrackEncoderAttributes videoAttrs, AudioTrackAttributes[] audioAttrs)\n        {\n            ValidateVideoAttributes(videoAttrs);\n            ValidateAudioAttributes(audioAttrs);\n\n            unsafe\n            {\n                IntPtr ptr = IntPtr.Zero;\n                void* videoAttrsPtr = &videoAttrs;\n                ptr = Internal_Create(filePath, videoAttrsPtr, audioAttrs);\n                if (ptr == IntPtr.Zero)\n                    throw new InvalidOperationException(\n                        \"MediaEncoder: Output file creation failed for \" + filePath);\n                return ptr;\n            }\n        }\n\n        private IntPtr Create(\n            string filePath, AudioTrackAttributes[] audioAttrs)\n        {\n            ValidateAudioAttributes(audioAttrs);\n\n            unsafe\n            {\n                IntPtr ptr = IntPtr.Zero;\n                ptr = Internal_Create(filePath, null, audioAttrs);\n                if (ptr == IntPtr.Zero)\n                    throw new InvalidOperationException(\n                        \"MediaEncoder: Output file creation failed for \" + filePath);\n                return ptr;\n            }\n        }\n\n        private void ThrowIfDisposed()\n        {\n            if (m_ThisPtr == IntPtr.Zero)\n                throw new ObjectDisposedException(\"MediaEncoder\");\n        }\n\n        [FreeFunction]\n        extern private unsafe static IntPtr Internal_Create(\n            string filePath, void* videoAttrs, AudioTrackAttributes[] audioAttrs);\n\n        [FreeFunction]\n        extern private static void Internal_Release(IntPtr encoder);\n\n        [FreeFunction]\n        extern private static bool Internal_AddFrame(IntPtr encoder, [NotNull] Texture2D texture, MediaTime time);\n\n        [FreeFunction]\n        unsafe extern private static bool Internal_AddFrameRaw(\n            IntPtr encoder, int width, int height, int rowBytes, TextureFormat format, void* buffer,\n            int byteCount, MediaTime time);\n\n        [FreeFunction]\n        unsafe extern private static bool Internal_AddSamples(\n            IntPtr encoder, ushort trackIndex, void* buffer, int sampleCount);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/MemorySettings.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing Object = UnityEngine.Object;\nusing UnityEngine.Bindings;\nusing UnityEditor;\n\nnamespace UnityEditorInternal\n{\n    [NativeHeader(\"Editor/Mono/MemorySettings.bindings.h\")]\n    [StaticAccessor(\"MemorySettingsBindings\", StaticAccessorType.DoubleColon)]\n    internal sealed partial class MemorySettingsUtils\n    {\n        extern internal static void SetPlatformDefaultValues(int platform);\n        extern internal static void WriteEditorMemorySettings();\n        extern internal static void InitializeDefaultsForPlatform(int platform);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Menu.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    [UsedByNativeCode]\n    struct ScriptingMenuItem\n    {\n        string m_Path;\n        bool m_IsSeparator;\n        int m_Priority;\n\n        public string path => m_Path;\n        public bool isSeparator => m_IsSeparator;\n        public int priority => m_Priority;\n\n        public ScriptingMenuItem(string path, int priority = -1, bool isSeparator = false)\n        {\n            m_Path = path;\n            m_Priority = priority;\n            m_IsSeparator = isSeparator;\n        }\n    }\n\n    [NativeHeader(\"Editor/Src/MenuController.h\")]\n    public sealed class Menu\n    {\n        internal static event Action menuChanged;\n\n        [NativeMethod(\"MenuController::SetChecked\", true)]\n        public static extern void SetChecked(string menuPath, bool isChecked);\n\n        [NativeMethod(\"MenuController::GetChecked\", true)]\n        public static extern bool GetChecked(string menuPath);\n\n        [NativeMethod(\"MenuController::GetEnabled\", true)]\n        public static extern bool GetEnabled(string menuPath);\n\n        [NativeMethod(\"MenuController::UpdateContextMenu\", true)]\n        internal static extern void UpdateContextMenu(UnityEngine.Object[] context, int userData);\n\n        [NativeMethod(\"MenuController::CreateActionMenuBegin\", true)]\n        internal static extern void CreateActionMenuBegin();\n\n        [NativeMethod(\"MenuController::CreateActionMenuEnd\", true)]\n        internal static extern void CreateActionMenuEnd();\n\n        [NativeMethod(\"MenuController::GetEnabledWithContext\", true)]\n        internal static extern bool GetEnabledWithContext(string menuPath, UnityEngine.Object[] context);\n\n        [FreeFunction(\"MenuController::GetMenuItemDefaultShortcuts\")]\n        internal static extern void GetMenuItemDefaultShortcuts(List<string> outItemNames, List<string> outItemDefaultShortcuts);\n\n        [FreeFunction(\"MenuController::SetMenuItemHotkey\")]\n        internal static extern void SetHotkey(string menuPath, string hotkey);\n\n        [FreeFunction(\"MenuController::GetMenuItemHotkey\")]\n        internal static extern string GetHotkey(string menuPath);\n\n        [FreeFunction(\"MenuController::ExtractSubmenus\")]\n        internal static extern string[] ExtractSubmenus(string menuPath);\n\n        // \"separators\" in this context means submenu roots, ex \"GameObject/\" in \"GameObject/Cube\".\n        [FreeFunction(\"MenuController::ExtractMenuItems\")]\n        internal static extern ScriptingMenuItem[] GetMenuItems(string menuPath, bool includeSeparators, bool localized);\n\n        [FreeFunction(\"MenuController::AddMenuItem\")]\n        internal static extern void AddMenuItem(string name, string shortcut, bool @checked, int priority, System.Action execute, System.Func<bool> validate);\n\n        [FreeFunction(\"MenuController::RemoveMenuItem\")]\n        internal static extern void RemoveMenuItem(string name);\n\n        [FreeFunction(\"MenuController::AddSeparator\")]\n        internal static extern void AddSeparator(string name, int priority);\n\n        [FreeFunction(\"MenuController::RebuildAllMenus\")]\n        internal static extern void RebuildAllMenus();\n\n        [NativeMethod(\"MenuController::FindHotkeyStartIndex\", true)]\n        internal static extern int FindHotkeyStartIndex(string menuPath);\n\n        [NativeMethod(\"MenuController::MenuItemExists\", true)]\n        internal static extern bool MenuItemExists(string menuPath);\n\n        [RequiredByNativeCode]\n        private static void OnMenuChanged()\n        {\n            menuChanged?.Invoke();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/MenuCommand.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    // Used to extract the context for a [[MenuItem]]. MenuCommand objects are passed to custom menu item functions defined using the [[MenuItem]] attribute.\n    // Keep in sync with MenuCommandBinding in Runtime\\Scripting\\ManagedAttributeManager.h\n    [StructLayout(LayoutKind.Sequential)]\n    [RequiredByNativeCode]\n    public sealed class MenuCommand\n    {\n        // Context is the object that is the target of a menu command.\n        public Object context;\n        // An integer for passing custom information to a menu item.\n        public int    userData;\n\n        // Creates a new MenuCommand object.\n        public MenuCommand(Object inContext, int inUserData) { context = inContext; userData = inUserData;  }\n        // Creates a new MenuCommand object.\n        public MenuCommand(Object inContext) { context = inContext; userData = 0;  }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/MenuItem.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing System.Reflection;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    // The MenuItem attribute allows you to add menu items to the main menu and inspector context menus.\n    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]\n    [RequiredByNativeCode]\n    public sealed class MenuItem : Attribute\n    {\n        private static readonly string[] kMenuItemSeparators = {\"/\"};\n\n        // Creates a menu item and invokes the static function following it, when the menu item is selected.\n        public MenuItem(string itemName) : this(itemName, false) {}\n\n        // Creates a menu item and invokes the static function following it, when the menu item is selected.\n        public MenuItem(string itemName, bool isValidateFunction) : this(itemName, isValidateFunction, itemName.StartsWith(\"GameObject/Create Other\") ? 10 : 1000) {}\n        // The special treatment of \"GameObject/Other\" is to ensure that legacy scripts that don't set a priority don't create a\n        // \"Create Other\" menu at the very bottom of the GameObject menu (thus preventing the items from being propagated to the\n        // scene hierarchy dropdown and context menu).\n\n        // Creates a menu item and invokes the static function following it, when the menu item is selected.\n        public MenuItem(string itemName, bool isValidateFunction, int priority) : this(itemName, isValidateFunction, priority, false) {}\n\n        // Creates a menu item and invokes the static function following it, when the menu item is selected.\n        internal MenuItem(string itemName, bool isValidateFunction, int priority, bool internalMenu) : this(itemName, isValidateFunction, priority, internalMenu, new string[] { \"default\" }) {}\n\n        // Creates a menu item and invokes the static function following it, when the menu item is selected.\n        internal MenuItem(string itemName, bool isValidateFunction, int priority, bool internalMenu, string[] editorModes)\n        {\n            itemName = NormalizeMenuItemName(itemName);\n            if (internalMenu)\n                menuItem = \"internal:\" + itemName;\n            else\n                menuItem = itemName;\n            validate = isValidateFunction;\n            this.priority = priority;\n            this.editorModes = editorModes;\n            secondaryPriority = float.MaxValue;\n        }\n\n        private static string NormalizeMenuItemName(string rawName)\n        {\n            return string.Join(kMenuItemSeparators[0], rawName.Split(kMenuItemSeparators, StringSplitOptions.None).Select(token => token.Trim()).ToArray());\n        }\n\n        public string menuItem;\n        public bool validate;\n        public int priority;\n        public float secondaryPriority; // transition period until UW-65 lands.\n        public string[] editorModes;\n    }\n\n    [RequiredByNativeCode(GenerateProxy = true)]\n    [StructLayout(LayoutKind.Sequential)]\n    class MenuItemScriptCommand : IMenuItem\n    {\n        public string name;\n        public int priority;\n        public float secondaryPriority;\n        public MethodInfo execute;\n        public MethodInfo validate;\n        public Delegate commandExecute;\n        public Delegate commandValidate;\n        public bool @checked;\n        public string shortcut;\n\n        public string Name => name;\n\n        public int Priority => priority;\n\n        public float SecondaryPriority => secondaryPriority;\n        internal bool IsNotValid => validate != null && execute == null;\n\n        public static MenuItemScriptCommand Initialize(string menuName, MenuItem menuItemAttribute, MethodInfo methodInfo)\n        {\n            if (!menuItemAttribute.validate)\n                return InitializeFromExecute(menuName, menuItemAttribute.priority, menuItemAttribute.secondaryPriority, methodInfo);\n            else\n                return InitializeFromValidate(menuName, methodInfo);\n        }\n\n        private static MenuItemScriptCommand InitializeFromValidate(string menuName, MethodInfo validate)\n        {\n            return new MenuItemScriptCommand()\n            {\n                name = menuName,\n                validate = validate\n            };\n        }\n\n        private static MenuItemScriptCommand InitializeFromExecute(string menuName, int priority, float secondaryPriority, MethodInfo execute)\n        {\n            return new MenuItemScriptCommand()\n            {\n                name = menuName,\n                priority = priority,\n                secondaryPriority = secondaryPriority,\n                execute = execute\n            };\n        }\n\n        internal static MenuItemScriptCommand InitializeFromCommand(string fullMenuName, int priority, string commandId, string validateCommandId)\n        {\n            var menuItem = new MenuItemScriptCommand()\n            {\n                name = fullMenuName,\n                priority = priority,\n                commandExecute = new Action(() => CommandService.Execute(commandId, CommandHint.Menu))\n            };\n            if (!string.IsNullOrEmpty(validateCommandId))\n                menuItem.commandValidate = new Func<bool>(() => (bool)CommandService.Execute(commandId, CommandHint.Menu | CommandHint.Validate));\n\n            return menuItem;\n        }\n\n        internal void Update(MenuItem menuItemAttribute, MethodInfo methodInfo)\n        {\n            if (!menuItemAttribute.validate)\n            {\n                if (execute != null)\n                {\n                    if (!(name == \"GameObject/3D Object/Mirror\" || name == \"GameObject/Light/Planar Reflection Probe\")) //TODO: remove when HDRP removes the duplicate menus\n                        Debug.LogWarning($\"Cannot add menu item '{name}' for method '{methodInfo.DeclaringType}.{methodInfo.Name}' because a menu item with the same name already exists.\");\n                    return;\n                }\n                priority = menuItemAttribute.priority;\n                secondaryPriority = menuItemAttribute.secondaryPriority;\n                execute = methodInfo;\n            }\n            else\n            {\n                if (validate != null)\n                {\n                    Debug.LogWarning($\"Cannot add validate method '{methodInfo.DeclaringType}.{methodInfo.Name}' for menu item '{name}' because a menu item with the same name already has a validate method.\");\n                    return;\n                }\n                validate  = methodInfo;\n            }\n        }\n    }\n\n    [RequiredByNativeCode(GenerateProxy = true)]\n    [StructLayout(LayoutKind.Sequential)]\n    class MenuItemOrderingNative : IMenuItem\n    {\n        public int position = -1;\n        public int parentPosition = -1;\n        public float secondaryPriority;\n        public string currentModeFullMenuName; // name of the menu to show\n        public string defaultModeFullMenuName; // name to find the default menu\n        public bool addChildren; // if true then native should add all children menu\n        public string[] childrenToExclude; // exclude those menu (path) when adding children\n        public string[] childrenToNotExclude; // if excluding, those menu (path) will not be excluded\n\n        public MenuItemOrderingNative()\n        {\n            defaultModeFullMenuName = string.Empty;\n        }\n\n        public MenuItemOrderingNative(string currentModeFullMenuName, string defaultModeFullMenuName, int position, int parentPosition, float secondaryPriority, bool addChildren = false)\n        {\n            this.position = position;\n            this.parentPosition = parentPosition;\n            this.secondaryPriority = secondaryPriority;\n            this.currentModeFullMenuName = currentModeFullMenuName;\n            this.defaultModeFullMenuName = defaultModeFullMenuName;\n            this.addChildren = addChildren;\n        }\n\n        public string Name => defaultModeFullMenuName;\n\n        public int Priority => position;\n\n        public float SecondaryPriority => secondaryPriority;\n    }\n\n    interface IMenuItem\n    {\n        string Name { get; }\n        int Priority { get; }\n\n        float SecondaryPriority { get; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/MeshUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Mono/MeshUtility.bindings.h\")]\n    [NativeHeader(\"Runtime/Graphics/Mesh/MeshOptimizer.h\")]\n    [NativeHeader(\"Runtime/Graphics/Texture.h\")]\n    [StaticAccessor(\"MeshUtility\", StaticAccessorType.DoubleColon)]\n    public class MeshUtility\n    {\n        [FreeFunction] extern private static void OptimizeIndexBuffers([NotNull] Mesh mesh);\n        [FreeFunction] extern private static void OptimizeReorderVertexBuffer([NotNull] Mesh mesh);\n\n        public static void Optimize(Mesh mesh)\n        {\n            OptimizeIndexBuffers(mesh);\n            OptimizeReorderVertexBuffer(mesh);\n        }\n\n        extern public static void SetMeshCompression([NotNull] Mesh mesh, ModelImporterMeshCompression compression);\n        extern public static ModelImporterMeshCompression GetMeshCompression([NotNull] Mesh mesh);\n\n        [NativeName(\"SetPerTriangleUV2\")]\n        static extern bool SetPerTriangleUV2NoCheck(Mesh src, Vector2[] triUV);\n        public static bool SetPerTriangleUV2(Mesh src, Vector2[] triUV)\n        {\n            if (src == null)\n                throw new ArgumentNullException(\"src\");\n\n            if (triUV == null)\n                throw new ArgumentNullException(\"triUV\");\n\n            int triCount = InternalMeshUtil.CalcTriangleCount(src), uvCount  = triUV.Length;\n            if (uvCount != 3 * triCount)\n            {\n                Debug.LogError(\"mesh contains \" + triCount + \" triangles but \" + uvCount + \" uvs are provided\");\n                return false;\n            }\n            return SetPerTriangleUV2NoCheck(src, triUV);\n        }\n\n        extern internal static Vector2[] ComputeTextureBoundingHull(Texture texture, int vertexCount);\n\n        public static Mesh.MeshDataArray AcquireReadOnlyMeshData(Mesh mesh)\n        {\n            return new Mesh.MeshDataArray(mesh, false);\n        }\n\n        public static Mesh.MeshDataArray AcquireReadOnlyMeshData(Mesh[] meshes)\n        {\n            if (meshes == null)\n                throw new ArgumentNullException(nameof(meshes), \"Mesh array is null\");\n            return new Mesh.MeshDataArray(meshes, meshes.Length, false);\n        }\n\n        public static Mesh.MeshDataArray AcquireReadOnlyMeshData(List<Mesh> meshes)\n        {\n            if (meshes == null)\n                throw new ArgumentNullException(nameof(meshes), \"Mesh list is null\");\n            return new Mesh.MeshDataArray(NoAllocHelpers.ExtractArrayFromList(meshes), meshes.Count, false);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ModuleMetadata.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/BuildPipeline/ModuleMetadata.h\")]\n    internal enum ModuleIncludeSetting\n    {\n        Auto = 0,\n        ForceExclude = 1,\n        ForceInclude = 2\n    }\n\n    [StaticAccessor(\"ModuleMetadata::Get()\", StaticAccessorType.Dot)]\n    [NativeHeader(\"Editor/Src/BuildPipeline/ModuleMetadata.h\")]\n    [NativeHeader(\"Editor/Mono/ModuleMetadata.bindings.h\")]\n    internal sealed class ModuleMetadata\n    {\n        [FreeFunction(\"ModuleMetadataBindings::GetModuleNames\")]\n        public extern static string[] GetModuleNames();\n\n        [FreeFunction(\"ModuleMetadataBindings::GetModuleDependencies\")]\n        public extern static string[] GetModuleDependencies(string moduleName);\n\n        [FreeFunction(\"ModuleMetadataBindings::IsStrippableModule\")]\n        extern public static bool IsStrippableModule(string moduleName);\n\n        public static UnityType[] GetModuleTypes(string moduleName)\n        {\n            var runtimeTypeIndices = GetModuleTypeIndices(moduleName);\n            return runtimeTypeIndices.Select(index => UnityType.GetTypeByRuntimeTypeIndex(index)).ToArray();\n        }\n\n        [NativeName(\"GetModuleIncludeSetting\")]\n        extern public static ModuleIncludeSetting GetModuleIncludeSettingForModule(string module);\n\n        [FreeFunction(\"ModuleMetadataBindings::SetModuleIncludeSettingForModule\")]\n        extern public static void SetModuleIncludeSettingForModule(string module, ModuleIncludeSetting setting);\n\n        [FreeFunction(\"ModuleMetadataBindings::GetModuleIncludeSettingForObject\")]\n        extern internal static ModuleIncludeSetting GetModuleIncludeSettingForObject(Object o);\n\n        [FreeFunction(\"ModuleMetadataBindings::GetModuleForObject\")]\n        extern internal static string GetModuleForObject(Object o);\n\n        [FreeFunction(\"ModuleMetadataBindings::GetModuleTypeIndices\")]\n        extern internal static uint[] GetModuleTypeIndices(string moduleName);\n\n        extern public static string GetICallModule(string icall);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/BeeBuildPostprocessor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Threading;\nusing Bee.BeeDriver;\nusing Bee.BinLog;\nusing NiceIO;\nusing PlayerBuildProgramLibrary.Data;\nusing UnityEditor.Build;\nusing UnityEditor.Build.Player;\nusing UnityEditor.Build.Reporting;\nusing UnityEditor.CrashReporting;\nusing UnityEditor.Scripting;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEditor.Utils;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Modules\n{\n    internal abstract class BeeBuildPostprocessor : IBuildPostprocessor\n    {\n        protected BeeDriverResult BeeDriverResult { get; set; }\n        protected static bool isBuildingPlayer { get; set; }\n\n        public static readonly string kBackupFolderPostfix = \"_BackUpThisFolder_ButDontShipItWithYourGame\";\n\n        static readonly string kXrBootSettingsKey = \"xr-boot-settings\";\n        public virtual ILaunchReport LaunchPlayer(BuildLaunchPlayerArgs args) => throw new NotSupportedException();\n\n        public static event Action<IPostStrippingModuleAdder> onAddModulesPostUnityLinker;\n\n        public virtual void PostProcess(BuildPostProcessArgs args, out BuildProperties outProperties)\n        {\n            PostProcess(args);\n\n            // NOTE: For some reason, calling PostProcess seems like it can trigger this object to be GC'd\n            //  so create is just before returning\n            outProperties = ScriptableObject.CreateInstance<DefaultBuildProperties>();\n        }\n\n        public virtual bool SupportsInstallInBuildFolder() => false;\n\n        public virtual bool SupportsLz4Compression() => false;\n\n        public virtual Compression GetDefaultCompression() => Compression.None;\n\n        public virtual void UpdateBootConfig(BuildTarget target, BootConfigData config, BuildOptions options)\n        {\n            config.Set(\"wait-for-native-debugger\", \"0\");\n            if (config.Get(\"player-connection-debug\") == \"1\")\n            {\n                config.Set(\"wait-for-managed-debugger\", EditorUserBuildSettings.waitForManagedDebugger ? \"1\" : \"0\");\n                config.Set(\"managed-debugger-fixed-port\", EditorUserBuildSettings.managedDebuggerFixedPort.ToString());\n            }\n\n            config.Set(\"hdr-display-enabled\", PlayerSettings.useHDRDisplay ? \"1\" : \"0\");\n            if (BuildPipeline.IsFeatureSupported(\"ENABLE_SCRIPTING_GC_WBARRIERS\", target))\n            {\n                if (PlayerSettings.gcWBarrierValidation)\n                    config.AddKey(\"validate-write-barriers\");\n                if (PlayerSettings.gcIncremental)\n                    config.Set(\"gc-max-time-slice\", \"3\");\n            }\n\n            string xrBootSettings = UnityEditor.EditorUserBuildSettings.GetPlatformSettings(BuildPipeline.GetBuildTargetName(target), kXrBootSettingsKey);\n            if (!String.IsNullOrEmpty(xrBootSettings))\n            {\n                var bootSettings = xrBootSettings.Split(';');\n                foreach (var bootSetting in bootSettings)\n                {\n                    var setting = bootSetting.Split(':');\n                    if (setting.Length == 2 && !String.IsNullOrEmpty(setting[0]) && !String.IsNullOrEmpty(setting[1]))\n                    {\n                        config.Set(setting[0], setting[1]);\n                    }\n                }\n            }\n\n\n            if ((options & BuildOptions.Development) != 0)\n            {\n                if ((options & BuildOptions.EnableDeepProfilingSupport) != 0)\n                {\n                    config.Set(\"profiler-enable-deep-profiling-support\", \"1\");\n                }\n            }\n        }\n\n        protected virtual string GetIl2CppDataBackupFolderName(BuildPostProcessArgs args) => $\"{args.installPath.ToNPath().FileNameWithoutExtension}{kBackupFolderPostfix}\";\n\n        public virtual string GetExtension(BuildTarget target, int subtarget, BuildOptions options) => string.Empty;\n\n        [RequiredByNativeCode]\n        static bool IsBuildingPlayer() => isBuildingPlayer;\n\n        [RequiredByNativeCode]\n        static void BeginProfile() => UnityBeeDriverProfilerSession.Start($\"{DagDirectory}/buildreport.json\");\n\n        [RequiredByNativeCode]\n        static void EndProfile() => UnityBeeDriverProfilerSession.Finish();\n\n        [RequiredByNativeCode]\n        static void BeginBuildSection(string name) => UnityBeeDriverProfilerSession.BeginSection(name);\n\n        [RequiredByNativeCode]\n        static void EndBuildSection() => UnityBeeDriverProfilerSession.EndSection();\n\n        protected virtual IPluginImporterExtension GetPluginImpExtension() => new EditorPluginImporterExtension();\n\n\n\n        protected virtual PluginsData PluginsDataFor(BuildPostProcessArgs args)\n        {\n            return new PluginsData\n            {\n                Plugins = GetPluginBuildTargetsFor(args).SelectMany(GetPluginsFor).ToArray()\n            };\n        }\n\n        protected virtual IEnumerable<BuildTarget> GetPluginBuildTargetsFor(BuildPostProcessArgs args)\n        {\n            yield return args.target;\n        }\n\n        protected virtual Plugin GetPluginFor(PluginImporter imp, BuildTarget target, string destinationPath)\n        {\n            // Skip .cpp files. They get copied to il2cpp output folder just before code compilation\n            if (DesktopPluginImporterExtension.IsCppPluginFile(imp.assetPath))\n                return null;\n\n            return new Plugin\n            {\n                AssetPath = imp.assetPath,\n                DestinationPath = destinationPath,\n            };\n        }\n\n        IEnumerable<Plugin> GetPluginsFor(BuildTarget target)\n        {\n            var buildTargetName = BuildPipeline.GetBuildTargetName(target);\n            var pluginImpExtension = GetPluginImpExtension();\n            foreach (PluginImporter imp in PluginImporter.GetImporters(target))\n            {\n                if (!IsPluginCompatibleWithCurrentBuild(target, imp))\n                    continue;\n\n                // Skip managed DLLs.\n                if (!imp.isNativePlugin)\n                    continue;\n\n                // HACK: This should never happen.\n                if (string.IsNullOrEmpty(imp.assetPath))\n                {\n                    UnityEngine.Debug.LogWarning(\"Got empty plugin importer path for \" + target);\n                    continue;\n                }\n\n                var destinationPath = pluginImpExtension.CalculateFinalPluginPath(buildTargetName, imp);\n                if (string.IsNullOrEmpty(destinationPath))\n                    continue;\n\n                var plugin = GetPluginFor(imp, target, destinationPath);\n                if (plugin != null)\n                    yield return plugin;\n            }\n        }\n\n        static IEnumerable<NPath> GetFilesWithRoleFromBuildReport(BuildReport report, params string[] roles) =>\n            report.GetFiles()\n                .Where(file => roles.Contains(file.role))\n                .Select(file => file.path.ToNPath())\n                .GroupBy(file => file.FileName)\n                .Select(group => group.First());\n\n        LinkerConfig LinkerConfigFor(BuildPostProcessArgs args)\n        {\n            var namedBuildTarget = GetNamedBuildTarget(args);\n            var strippingLevel = PlayerSettings.GetManagedStrippingLevel(namedBuildTarget);\n\n            // IL2CPP does not support a managed stripping level of disabled. If the player settings\n            // do try this (which should not be possible from the editor), use Low instead.\n            if (GetScriptingBackend(args) == ScriptingBackend.IL2CPP && strippingLevel == ManagedStrippingLevel.Disabled)\n                strippingLevel = ManagedStrippingLevel.Minimal;\n\n            var additionalArgs = new List<string>();\n\n            var diagArgs = Debug.GetDiagnosticSwitch(\"VMUnityLinkerAdditionalArgs\").value as string;\n            if (!string.IsNullOrEmpty(diagArgs))\n                additionalArgs.Add(diagArgs.Trim('\\''));\n\n            var linkerInputDirectory = DagDirectory.Combine($\"artifacts/UnityLinkerInputs\").CreateDirectory();\n\n            // In Disabled mode, we pass all generated and engine assemblies to the linker as roots, as the linker\n            // will only perform a simple assembly reference traversal, ignoring link.xml files and attributes which\n            // would otherwise find dependent assemblies to preserve.\n            // In other modes (when stripping is desired), we pass only a smaller set of user assemblies (assemblies from\n            // packages if used in any scenes, as well as any assembly from the Assets folder) as roots.\n            var assembliesToProcess = strippingLevel == ManagedStrippingLevel.Disabled\n                ? GetFilesWithRoleFromBuildReport(args.report, \"ManagedLibrary\", \"ManagedEngineAPI\").Select(f => f.FileName)\n                : args.usedClassRegistry.GetUsedUserAssemblies();\n\n            return new LinkerConfig\n            {\n                LinkXmlFiles = AssemblyStripper.GetLinkXmlFiles(args, linkerInputDirectory),\n                EditorToLinkerData = AssemblyStripper.WriteEditorData(args, linkerInputDirectory),\n                AssembliesToProcess = assembliesToProcess.ToArray(),\n                Runtime = GetScriptingBackend(args).ToString().ToLowerInvariant(),\n                Profile = IL2CPPUtils.ApiCompatibilityLevelToDotNetProfileArgument(\n                    PlayerSettings.GetApiCompatibilityLevel(namedBuildTarget), args.target),\n                Ruleset = strippingLevel switch\n                {\n                    ManagedStrippingLevel.Disabled => \"Copy\",\n                    ManagedStrippingLevel.Minimal => \"Minimal\",\n                    ManagedStrippingLevel.Low => \"Conservative\",\n                    ManagedStrippingLevel.Medium => \"Aggressive\",\n                    ManagedStrippingLevel.High => \"Experimental\",\n                    _ => throw new ArgumentException($\"Unhandled {nameof(ManagedStrippingLevel)} value\")\n                },\n                AdditionalArgs = additionalArgs.ToArray(),\n                ModulesAssetPath = $\"{BuildPipeline.GetPlaybackEngineDirectory(args.target, 0)}/modules.asset\",\n                AllowDebugging = GetAllowDebugging(args),\n                PerformEngineStripping = PlayerSettings.stripEngineCode,\n            };\n        }\n\n        static bool IsBuildOptionSet(BuildOptions options, BuildOptions flag) => (options & flag) != 0;\n\n        static string GetConfigurationName(Il2CppCompilerConfiguration compilerConfiguration)\n        {\n            // In IL2CPP, Master config is called \"ReleasePlus\"\n            return compilerConfiguration != Il2CppCompilerConfiguration.Master ? compilerConfiguration.ToString() : \"ReleasePlus\";\n        }\n\n        protected virtual string Il2CppBuildConfigurationNameFor(BuildPostProcessArgs args)\n        {\n            return GetConfigurationName(PlayerSettings.GetIl2CppCompilerConfiguration(GetNamedBuildTarget(args)));\n        }\n\n        protected virtual IEnumerable<string> AdditionalIl2CppArgsFor(BuildPostProcessArgs args)\n        {\n            yield break;\n        }\n\n        IEnumerable<string> SplitArgs(string args)\n        {\n            int startIndex = 0;\n            bool inQuotes = false;\n            int i = 0;\n            for (; i < args.Length; i++)\n            {\n                if (args[i] == '\"')\n                    inQuotes = !inQuotes;\n                if (args[i] == ' ' && !inQuotes)\n                {\n                    if (i - startIndex > 0)\n                        yield return args.Substring(startIndex, i - startIndex);\n                    startIndex = i + 1;\n                }\n            }\n            if (i - startIndex > 0)\n                yield return args.Substring(startIndex, i - startIndex);\n        }\n\n\n        protected virtual string Il2CppSysrootPathFor(BuildPostProcessArgs args) => null;\n\n        protected virtual string Il2CppToolchainPathFor(BuildPostProcessArgs args) => null;\n\n        protected virtual string Il2CppCompilerFlagsFor(BuildPostProcessArgs args) => null;\n\n        protected virtual string[] Il2CppAdditionalLibrariesFor(BuildPostProcessArgs args) => Array.Empty<string>();\n        protected virtual string[] Il2CppAdditionalDefinesFor(BuildPostProcessArgs args) => Array.Empty<string>();\n        protected virtual string[] Il2CppAdditionalIncludeDirectoriesFor(BuildPostProcessArgs args) => Array.Empty<string>();\n        protected virtual string[] Il2CppAdditionalLinkDirectoriesFor(BuildPostProcessArgs args) => Array.Empty<string>();\n\n        protected virtual string Il2CppLinkerFlagsFor(BuildPostProcessArgs args) => null;\n\n        protected virtual string Il2CppLinkerFlagsFileFor(BuildPostProcessArgs args) => null;\n\n        protected virtual string Il2CppDataRelativePath(BuildPostProcessArgs args) => \"Data\";\n\n        Il2CppConfig Il2CppConfigFor(BuildPostProcessArgs args)\n        {\n            if (GetScriptingBackend(args) != ScriptingBackend.IL2CPP)\n                return null;\n\n            var additionalArgs = new List<string>(AdditionalIl2CppArgsFor(args));\n\n            var diagArgs = Debug.GetDiagnosticSwitch(\"VMIl2CppAdditionalArgs\").value as string;\n            if (!string.IsNullOrEmpty(diagArgs))\n                additionalArgs.AddRange(SplitArgs(diagArgs.Trim('\\'')));\n\n            var playerSettingsArgs = PlayerSettings.GetAdditionalIl2CppArgs();\n            if (!string.IsNullOrEmpty(playerSettingsArgs))\n                additionalArgs.AddRange(SplitArgs(playerSettingsArgs));\n            var sysrootPath = Il2CppSysrootPathFor(args);\n            var toolchainPath = Il2CppToolchainPathFor(args);\n            var compilerFlags = Il2CppCompilerFlagsFor(args);\n            var additionalLibraries = Il2CppAdditionalLibrariesFor(args);\n            var additionalDefines = Il2CppAdditionalDefinesFor(args);\n            var additionalIncludeDirectories = Il2CppAdditionalIncludeDirectoriesFor(args);\n            var additionalLinkDirectories = Il2CppAdditionalLinkDirectoriesFor(args);\n            var linkerFlags = Il2CppLinkerFlagsFor(args);\n            var linkerFlagsFile = Il2CppLinkerFlagsFileFor(args);\n            var relativeDataPath = Il2CppDataRelativePath(args);\n\n            if (CrashReportingSettings.canUploadReports)\n                additionalArgs.Add(\"--emit-source-mapping\");\n\n            var namedBuildTarget = GetNamedBuildTarget(args);\n            var apiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(namedBuildTarget);\n            var il2cppCodeGeneration = PlayerSettings.GetIl2CppCodeGeneration(namedBuildTarget);\n            var platformHasIncrementalGC = BuildPipeline.IsFeatureSupported(\"ENABLE_SCRIPTING_GC_WBARRIERS\", args.target);\n            var allowDebugging = GetAllowDebugging(args);\n\n            NPath extraTypesFile = null;\n            if (PlayerBuildInterface.ExtraTypesProvider != null)\n            {\n                var extraTypes = new HashSet<string>();\n                foreach (var extraType in PlayerBuildInterface.ExtraTypesProvider())\n                {\n                    extraTypes.Add(extraType);\n                }\n\n                extraTypesFile = \"Temp/extra-types.txt\";\n                extraTypesFile.WriteAllLines(extraTypes.ToArray());\n            }\n\n            return new Il2CppConfig\n            {\n                EnableDeepProfilingSupport = GetDevelopment(args) &&\n                    IsBuildOptionSet(args.report.summary.options,\n                    BuildOptions.EnableDeepProfilingSupport),\n                EnableFullGenericSharing = il2cppCodeGeneration == Il2CppCodeGeneration.OptimizeSize,\n                Profile = IL2CPPUtils.ApiCompatibilityLevelToDotNetProfileArgument(PlayerSettings.GetApiCompatibilityLevel(namedBuildTarget), args.target),\n                IDEProjectDefines = IL2CPPUtils.GetBuilderDefinedDefines(args.target, apiCompatibilityLevel, allowDebugging),\n                ConfigurationName = Il2CppBuildConfigurationNameFor(args),\n                GcWBarrierValidation = platformHasIncrementalGC && PlayerSettings.gcWBarrierValidation,\n                GcIncremental = platformHasIncrementalGC && PlayerSettings.gcIncremental &&\n                    (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6 ||\n                        apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0 ||\n                        apiCompatibilityLevel == ApiCompatibilityLevel.NET_Unity_4_8 ||\n                        apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard),\n                CreateSymbolFiles = !GetDevelopment(args) || CrashReportingSettings.canUploadReports,\n                AdditionalCppFiles = PluginImporter.GetImporters(args.target)\n                    .Where(imp => DesktopPluginImporterExtension.IsCppPluginFile(imp.assetPath))\n                    .Select(imp => imp.assetPath)\n                    .ToArray(),\n                AdditionalArgs = additionalArgs.ToArray(),\n                AllowDebugging = allowDebugging,\n                CompilerFlags = compilerFlags,\n                AdditionalLibraries = additionalLibraries,\n                AdditionalDefines = additionalDefines,\n                AdditionalIncludeDirectories = additionalIncludeDirectories,\n                AdditionalLinkDirectories = additionalLinkDirectories,\n                LinkerFlags = linkerFlags,\n                LinkerFlagsFile = linkerFlagsFile,\n                SysRootPath = sysrootPath,\n                ToolChainPath = toolchainPath,\n                RelativeDataPath = relativeDataPath,\n                ExtraTypes = extraTypesFile?.ToString(),\n                GenerateUsymFile = PlayerSettings.GetIl2CppStacktraceInformation(namedBuildTarget) == Il2CppStacktraceInformation.MethodFileLineNumber,\n                UsymtoolPath = GetUsymtoolPath(),\n            };\n        }\n\n        static string GetUsymtoolPath()\n        {\n            if (Application.platform == RuntimePlatform.OSXEditor)\n                return Paths.Combine(EditorApplication.applicationContentsPath, \"Tools\", \"macosx\", \"usymtool\");\n            if (Application.platform == RuntimePlatform.LinuxEditor)\n                return Paths.Combine(EditorApplication.applicationContentsPath, \"Tools\", \"usymtool\");\n\n            return Paths.Combine(EditorApplication.applicationContentsPath, \"Tools\", \"usymtool.exe\");\n        }\n\n        static bool IsNewInputSystemEnabled()\n        {\n            var propName = \"activeInputHandler\";\n            var ps = PlayerSettings.GetSerializedObject();\n            var newInputEnabledProp = ps.FindProperty(propName);\n            if (newInputEnabledProp == null)\n                throw new Exception($\"Failed to find {propName}\");\n            return newInputEnabledProp.intValue != 0;\n        }\n\n        static GenerateNativePluginsForAssembliesSettings GetGenerateNativePluginsForAssembliesSettings(BuildPostProcessArgs args)\n        {\n            var settings = new GenerateNativePluginsForAssembliesSettings();\n            settings.DisplayName = \"Generating Native Plugins\";\n            if (BuildPipelineInterfaces.processors.generateNativePluginsForAssembliesProcessors != null)\n            {\n                foreach (var processor in BuildPipelineInterfaces.processors.generateNativePluginsForAssembliesProcessors)\n                {\n                    var setupResult = processor.PrepareOnMainThread(new () { report = args.report });\n                    if (setupResult.additionalInputFiles != null)\n                        settings.AdditionalInputFiles = settings.AdditionalInputFiles.Concat(setupResult.additionalInputFiles).ToArray();\n                    if (setupResult.displayName != null)\n                        settings.DisplayName = setupResult.displayName;\n                    settings.HasCallback = true;\n                }\n            }\n\n            return settings;\n        }\n\n        PlayerBuildConfig PlayerBuildConfigFor(BuildPostProcessArgs args) => new PlayerBuildConfig\n        {\n            DestinationPath = GetInstallPathFor(args),\n            StagingArea = args.stagingArea,\n            CompanyName = args.companyName,\n            ProductName = Paths.MakeValidFileName(args.productName),\n            PlayerPackage = args.playerPackage,\n            ApplicationIdentifier = PlayerSettings.GetApplicationIdentifier(GetNamedBuildTarget(args)),\n            InstallIntoBuildsFolder = GetInstallingIntoBuildsFolder(args),\n            GenerateIdeProject = GetCreateSolution(args),\n            Development = (args.options & BuildOptions.Development) == BuildOptions.Development,\n            NoGUID = (args.options & BuildOptions.NoUniqueIdentifier) == BuildOptions.NoUniqueIdentifier,\n            ScriptingBackend = GetScriptingBackend(args),\n            Architecture = GetArchitecture(args),\n            DataFolder = GetDataFolderFor(args),\n            GenerateNativePluginsForAssembliesSettings = GetGenerateNativePluginsForAssembliesSettings(args),\n            Services = new ()\n            {\n                EnableAnalytics = UnityEngine.Analytics.Analytics.enabled,\n                EnableCrashReporting = UnityEditor.CrashReporting.CrashReportingSettings.canUploadReports,\n                EnablePerformanceReporting = UnityEngine.Analytics.PerformanceReporting.enabled,\n                EnableUnityConnect = UnityEngine.Connect.UnityConnectSettings.enabled,\n            },\n            StreamingAssetsFiles = BuildPlayerContext.ActiveInstance.StreamingAssets\n                .Select(e => new StreamingAssetsFile { File = e.src.ToString(), RelativePath = e.dst.ToString() })\n                .ToArray(),\n            UseNewInputSystem = IsNewInputSystemEnabled(),\n            ManagedAssemblies = GetFilesWithRoleFromBuildReport(args.report, \"ManagedLibrary\", \"DependentManagedLibrary\", \"ManagedEngineAPI\")\n                .Select(p => p.ToString())\n                .ToArray()\n        };\n\n        protected virtual string GetInstallPathFor(BuildPostProcessArgs args)\n        {\n            // Try to minimize path lengths for windows\n            NPath absoluteInstallationPath = args.installPath;\n            return absoluteInstallationPath.IsChildOf(NPath.CurrentDirectory)\n                ? absoluteInstallationPath.RelativeTo(NPath.CurrentDirectory).ToString()\n                : absoluteInstallationPath.ToString();\n        }\n\n        protected string GetDataFolderFor(BuildPostProcessArgs args) => $\"Library/PlayerDataCache/{BuildPipeline.GetSessionIdForBuildTarget(args.target, args.subtarget)}/Data\";\n\n        protected ScriptingBackend GetScriptingBackend(BuildPostProcessArgs args)\n        {\n            var scriptingBackend = PlayerSettings.GetScriptingBackend(GetNamedBuildTarget(args));\n            switch (scriptingBackend)\n            {\n                case ScriptingImplementation.Mono2x:\n                    return ScriptingBackend.Mono;\n\n                case ScriptingImplementation.IL2CPP:\n                    return ScriptingBackend.IL2CPP;\n\n#pragma warning disable 618\n                case ScriptingImplementation.CoreCLR:\n                    return ScriptingBackend.CoreCLR;\n#pragma warning restore 618\n\n                default:\n                    throw new NotSupportedException(\"Unknown scripting backend:\" + scriptingBackend);\n            }\n        }\n\n        protected virtual string GetPlatformNameForBuildProgram(BuildPostProcessArgs args) => args.target.ToString();\n        protected virtual string GetArchitecture(BuildPostProcessArgs args) => EditorUserBuildSettings.GetPlatformSettings(BuildPipeline.GetBuildTargetName(args.target), \"Architecture\");\n        protected Dictionary<string, Action<NodeFinishedMessage>> ResultProcessors { get; } = new ();\n\n        RunnableProgram MakePlayerBuildProgram(BuildPostProcessArgs args)\n        {\n            var buildProgramAssembly = new NPath($\"{args.playerPackage}/{GetPlatformNameForBuildProgram(args)}PlayerBuildProgram.exe\");\n            NPath buildPipelineFolder = $\"{EditorApplication.applicationContentsPath}/Tools/BuildPipeline\";\n            NPath beePlatformFolder = $\"{args.playerPackage}/Bee\";\n            var searchPaths = $\"{beePlatformFolder}{Path.PathSeparator}\";\n            if (IL2CPPUtils.UsingDevelopmentBuild())\n            {\n                searchPaths = $\"{IL2CPPUtils.ConstructBeeLibrarySearchPath()}{Path.PathSeparator}\";\n            }\n\n            return new SystemProcessRunnableProgram(NetCoreRunProgram.NetCoreRunPath,\n                new[]\n                {\n                    buildProgramAssembly.InQuotes(SlashMode.Native),\n                    $\"\\\"{searchPaths}{buildPipelineFolder}\\\"\"\n                },\n                new () {{ \"DOTNET_SYSTEM_GLOBALIZATION_INVARIANT\", \"1\" }});\n        }\n\n        static NPath DagDirectory => \"Library/Bee\";\n\n        string DagName(BuildPostProcessArgs args) => $\"Player{GetInstallPathFor(args).GetHashCode():x8}\";\n\n        protected virtual IEnumerable<object> GetDataForBuildProgramFor(BuildPostProcessArgs args)\n        {\n            yield return PlayerBuildConfigFor(args);\n            yield return PluginsDataFor(args);\n            yield return LinkerConfigFor(args);\n            yield return Il2CppConfigFor(args);\n        }\n        protected virtual RunnableProgram BeeBackendProgram(BuildPostProcessArgs args) => null;\n\n        protected virtual BuildRequest SetupBuildRequest(BuildPostProcessArgs args, ILPostProcessingProgram ilpp)\n        {\n            RunnableProgram buildProgram = MakePlayerBuildProgram(args);\n            var cacheMode = ((args.options & BuildOptions.CleanBuildCache) == BuildOptions.CleanBuildCache)\n                ? UnityBeeDriver.CacheMode.WriteOnly\n                : UnityBeeDriver.CacheMode.ReadWrite;\n\n            var buildRequest = UnityBeeDriver.BuildRequestFor(buildProgram, DagName(args), DagDirectory.ToString(), false, \"\",ilpp, cacheMode, UnityBeeDriver.StdOutModeForPlayerBuilds, BeeBackendProgram(args));\n            buildRequest.DataForBuildProgram.Add(() => GetDataForBuildProgramFor(args).Where(o=> o is not null));\n\n            return buildRequest;\n        }\n\n        // Some node types produce meaningful, human readable error messages,\n        // but the output files names are Unity internals, not helpful to users.\n        // For such nodes, directly print the output if the action fails.\n        void PrintStdoutOnErrorProcessor(NodeFinishedMessage node)\n        {\n            if (node.ExitCode != 0)\n                Debug.LogError(node.Output);\n            else\n                DefaultResultProcessor(node);\n        }\n\n        void UnityLinkerResultProcessor(NodeFinishedMessage node)\n        {\n            if (node.ExitCode != 0 && node.Output.Contains(\"UnityEditor\"))\n                Debug.LogError($\"UnityEditor.dll assembly is referenced by user code, but this is not allowed.\");\n            else\n                DefaultResultProcessor(node);\n        }\n\n        void UsymtoolResultProcessor(NodeFinishedMessage node)\n        {\n            // Usymtool might print a message like \"error: <something>\" to stdout, even when\n            // it succeeds. So only process error messages when it fails.\n            if (node.ExitCode != 0)\n                DefaultResultProcessor(node);\n        }\n\n        public BeeBuildPostprocessor()\n        {\n            ResultProcessors[\"IL2CPP_CodeGen\"] = PrintStdoutOnErrorProcessor;\n            ResultProcessors[\"UnityLinker\"] = UnityLinkerResultProcessor;\n            ResultProcessors[\"ExtractUsedFeatures\"] = PrintStdoutOnErrorProcessor;\n            ResultProcessors[\"Usym\"] = UsymtoolResultProcessor;\n        }\n\n        protected void DefaultResultProcessor(NodeFinishedMessage node, bool printErrors = true, bool printWarnings = true)\n        {\n            var output = node.Node.OutputDirectory;\n            if (string.IsNullOrEmpty(output))\n                output = node.Node.OutputFile;\n\n            var lines = (node.Output ?? string.Empty).Split(new[] {'\\r', '\\n'},\n                StringSplitOptions.RemoveEmptyEntries);\n\n            if (printErrors)\n            {\n                var errorKey = \"error:\";\n                foreach (var error in lines.Where(l =>\n                    l.StartsWith(errorKey, StringComparison.InvariantCultureIgnoreCase)))\n                    Debug.LogError($\"{output}: {error.Substring(errorKey.Length).TrimStart()}\");\n            }\n\n            if (printWarnings)\n            {\n                var warningKey = \"warning:\";\n                foreach (var warning in lines.Where(l =>\n                    l.StartsWith(warningKey, StringComparison.InvariantCultureIgnoreCase)))\n                    Debug.LogWarning($\"{output}: {warning.Substring(warningKey.Length).TrimStart()}\");\n            }\n\n            if (node.ExitCode != 0)\n                Debug.LogError($\"Building {output} failed with output:\\n{node.Output}\");\n        }\n\n        void ReportBuildResults()\n        {\n            foreach (var node in BeeDriverResult.NodeFinishedMessages)\n            {\n                var annotationAction = node.Node.Annotation.Split(' ')[0];\n                if (ResultProcessors.TryGetValue(annotationAction, out var processor))\n                    processor(node);\n                else\n                    DefaultResultProcessor(node);\n            }\n\n            foreach (var resultBeeDriverMessage in BeeDriverResult.BeeDriverMessages)\n            {\n                if (resultBeeDriverMessage.Kind == BeeDriverResult.MessageKind.Warning)\n                    Debug.LogWarning(resultBeeDriverMessage.Text);\n                else\n                    Debug.LogError(resultBeeDriverMessage.Text);\n            }\n        }\n\n        void ReportBuildOutputFiles(BuildPostProcessArgs args)\n        {\n            // Remove any previous file entries in the build report.\n            // We can track any file written by the backend ourselves.\n            // Once all platforms use the Bee backend, we can remove a lot\n            // of code to add file entries in the native build pipeline.\n            args.report.DeleteAllFileEntries();\n\n            var filesOutput = BeeDriverResult.DataFromBuildProgram.Get<BuiltFilesOutput>();\n            foreach (var outputfile in filesOutput.Files.ToNPaths().Where(f => f.FileExists() && !f.IsSymbolicLink))\n                args.report.RecordFileAdded(outputfile.ToString(), outputfile.Extension);\n\n            var config = filesOutput.BootConfigArtifact.ToNPath().ReadAllLines();\n            var guidKey = \"build-guid=\";\n            var guidLine = config.FirstOrDefault(l => l.StartsWith(guidKey));\n            if (guidLine != null)\n            {\n                var guid = guidLine.Substring(guidKey.Length);\n                args.report.SetBuildGUID(new GUID(guid));\n            }\n            else\n            {\n                args.report.SetBuildGUID(new GUID(\"00000000000000000000000000000000\"));\n            }\n        }\n\n        public virtual string PrepareForBuild(BuildPlayerOptions buildOptions)\n        {\n            // Clean the Bee folder in PrepareForBuild, so that it is also clean for script compilation.\n            if ((buildOptions.options & BuildOptions.CleanBuildCache) == BuildOptions.CleanBuildCache)\n                EditorCompilation.ClearBeeBuildArtifacts();\n\n            return null;\n        }\n\n        protected virtual void CleanBuildOutput(BuildPostProcessArgs args)\n        {\n            if (!GetInstallingIntoBuildsFolder(args))\n            {\n                new NPath(GetInstallPathFor(args)).DeleteIfExists(DeleteMode.Soft);\n                new NPath(GetInstallPathFor(args)).Parent.Combine(GetIl2CppDataBackupFolderName(args)).DeleteIfExists(DeleteMode.Soft);\n            }\n        }\n\n        static void GenerateNativePluginsForAssemblies(GenerateNativePluginsForAssembliesArgs args)\n        {\n            using var section = UnityBeeDriverProfilerSession.ProfilerInstance.Section(nameof(GenerateNativePluginsForAssembliesArgs));\n            var generateArgs = new IGenerateNativePluginsForAssemblies.GenerateArgs { assemblyFiles = args.Assemblies };\n            bool wrotePlugins = false;\n            bool wroteSymbols = false;\n            foreach (var processor in BuildPipelineInterfaces.processors.generateNativePluginsForAssembliesProcessors)\n            {\n                using var _ = UnityBeeDriverProfilerSession.ProfilerInstance.Section(processor.GetType().ToString());\n                var result = processor.GenerateNativePluginsForAssemblies(generateArgs);\n                if (result.generatedPlugins?.Length > 0)\n                {\n                    wrotePlugins = true;\n                    foreach (var file in result.generatedPlugins.ToNPaths())\n                        file.Copy($\"{args.PluginOutputFolder}/{file.FileName}\");\n                }\n                if (result.generatedSymbols?.Length > 0)\n                {\n                    wroteSymbols = true;\n                    foreach (var file in result.generatedSymbols.ToNPaths())\n                        file.Copy($\"{args.SymbolOutputFolder}/{file.FileName}\");\n                }\n            }\n\n            if (!wrotePlugins)\n            {\n                // We need to produce a file, so Bee will not be upset when we use the `FilesOrDummy` mechanism.\n                new NPath(args.PluginOutputFolder)\n                    .Combine(\"no_plugins_were_generated.txt\")\n                    .WriteAllText(\"GenerateNativePluginsForAssemblies did not produce any output\");\n            }\n\n            if (!wroteSymbols)\n            {\n                // We need to produce a file, so Bee will not be upset when we use the `FilesOrDummy` mechanism.\n                new NPath(args.SymbolOutputFolder)\n                    .Combine(\"no_symbols_were_generated.txt\")\n                    .WriteAllText(\"GenerateNativePluginsForAssemblies did not produce any output\");\n            }\n        }\n\n        public virtual void PostProcess(BuildPostProcessArgs args)\n        {\n            try\n            {\n                if ((args.options & BuildOptions.CleanBuildCache) == BuildOptions.CleanBuildCache)\n                    CleanBuildOutput(args);\n\n                var buildStep = args.report.BeginBuildStep(\"Setup incremental player build\");\n\n                var buildRequest = SetupBuildRequest(args,new ILPostProcessingProgram());\n                args.report.EndBuildStep(buildStep);\n\n                buildStep = args.report.BeginBuildStep(\"Incremental player build\");\n\n                using var cancellationTokenSource = new CancellationTokenSource();\n\n                buildRequest.Target = \"Player\";\n                buildRequest.RegisterRPCCallback<GenerateNativePluginsForAssembliesArgs>(nameof(GenerateNativePluginsForAssemblies), GenerateNativePluginsForAssemblies);\n                var activeBuild = BeeDriver.BuildAsync(buildRequest, cancellationToken: cancellationTokenSource.Token);\n\n                {\n                    while (!activeBuild.TaskObject.IsCompleted)\n                    {\n                        activeBuild.TaskObject.Wait(100);\n\n                        //important to keep on pumping the execution context here, as there might be async tasks being kicked off by the bee driver build that have to run on the main thread.\n                        ((UnitySynchronizationContext) SynchronizationContext.Current).Exec();\n\n                        var activeBuildStatus = activeBuild.Status;\n                        float progress = activeBuildStatus.Progress.HasValue\n                            ? activeBuildStatus.Progress.Value.nodesFinishedOrUpToDate / (float) activeBuildStatus.Progress.Value.totalNodesQeueued\n                            : 0f;\n                        if (EditorUtility.DisplayCancelableProgressBar(\"Incremental Player Build\", activeBuildStatus.Description, progress))\n                        {\n                            EditorUtility.DisplayCancelableProgressBar(\"Incremental Player Build\", \"Canceling build\", 1.0f);\n                            cancellationTokenSource.Cancel();\n                        }\n                    }\n                    args.report.EndBuildStep(buildStep);\n\n                    BeeDriverResult = activeBuild.TaskObject.Result;\n\n                    UnityBeeDriverProfilerSession.AddTaskToWaitForBeforeFinishing(BeeDriverResult.ProfileOutputWritingTask);\n\n                    if (BeeDriverResult.Success)\n                    {\n                        PostProcessCompletedBuild(args);\n                    }\n                    ReportBuildResults();\n\n                    UnityBeeDriver.RunCleanBeeCache();\n\n                    if (BeeDriverResult.Success)\n                    {\n                        buildStep = args.report.BeginBuildStep(\"Report output files\");\n                        ReportBuildOutputFiles(args);\n                        args.report.EndBuildStep(buildStep);\n                    } else\n                        throw new BuildFailedException($\"Player build failed: {args.report.SummarizeErrors()}\", silent: true);\n                }\n            }\n            catch (OperationCanceledException)\n            {\n                throw;\n            }\n            catch (BuildFailedException)\n            {\n                throw;\n            }\n            catch (AggregateException e)\n            {\n                if (e.InnerException is OperationCanceledException or BuildFailedException)\n                    throw e.InnerException;\n\n                throw new BuildFailedException(e);\n            }\n            catch (Exception e)\n            {\n                throw new BuildFailedException(e);\n            }\n        }\n\n        public virtual void PostProcessCompletedBuild(BuildPostProcessArgs args)\n        {\n            if (PlayerSettings.GetManagedStrippingLevel(GetNamedBuildTarget(args)) == ManagedStrippingLevel.Disabled)\n                return;\n\n            var strippingInfo = GetStrippingInfoFromBuild(args);\n            if (strippingInfo != null && EditorBuildOutputPathFor(args) != null)\n            {\n                args.report.AddAppendix(strippingInfo);\n                var linkerToEditorData = AssemblyStripper.ReadLinkerToEditorData(EditorBuildOutputPathFor(args).ToString());\n\n                onAddModulesPostUnityLinker?.Invoke(new PostStrippingModuleAdder(linkerToEditorData));\n\n                AssemblyStripper.UpdateBuildReport(linkerToEditorData, strippingInfo);\n            }\n        }\n\n        public virtual bool AddIconsToBuild(AddIconsArgs args) => true;\n\n        protected virtual bool GetCreateSolution(BuildPostProcessArgs args) => false;\n\n        protected virtual NPath EditorBuildOutputPathFor(BuildPostProcessArgs buildPostProcessArgs) => null;\n\n        protected virtual StrippingInfo GetStrippingInfoFromBuild(BuildPostProcessArgs args) => null;\n\n        protected virtual bool IsPluginCompatibleWithCurrentBuild(BuildTarget buildTarget, PluginImporter imp)\n        {\n            var cpu = imp.GetPlatformData(buildTarget, \"CPU\");\n            return !string.Equals(cpu, \"None\", StringComparison.OrdinalIgnoreCase);\n        }\n\n        protected NamedBuildTarget GetNamedBuildTarget(BuildPostProcessArgs args)\n        {\n            var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(args.target);\n\n            if (buildTargetGroup == BuildTargetGroup.Standalone)\n            {\n                return (StandaloneBuildSubtarget)args.subtarget == StandaloneBuildSubtarget.Server\n                    ? NamedBuildTarget.Server : NamedBuildTarget.Standalone;\n            }\n\n            return NamedBuildTarget.FromBuildTargetGroup(buildTargetGroup);\n        }\n\n        protected bool GetDevelopment(BuildPostProcessArgs args) =>\n            IsBuildOptionSet(args.options, BuildOptions.Development);\n\n        protected bool GetInstallingIntoBuildsFolder(BuildPostProcessArgs args) =>\n            IsBuildOptionSet(args.options, BuildOptions.InstallInBuildFolder);\n\n        protected bool ShouldAppendBuild(BuildPostProcessArgs args) =>\n            IsBuildOptionSet(args.options, BuildOptions.AcceptExternalModificationsToPlayer);\n\n        protected virtual bool GetAllowDebugging(BuildPostProcessArgs args) => (args.report.summary.options & BuildOptions.AllowDebugging) == BuildOptions.AllowDebugging;\n\n    }\n\n    internal class DefaultBuildProperties : BuildProperties\n    {\n        public override DeploymentTargetRequirements GetTargetRequirements() { return null; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/DefaultBuildProfileExtension.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing UnityEditor.Build;\nusing UnityEditor.Build.Profile;\nusing UnityEditor.UIElements;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Modules\n{\n    internal abstract class DefaultBuildProfileExtension : IBuildProfileExtension\n    {\n        static readonly GUIContent k_DevelopmentBuild = EditorGUIUtility.TrTextContent(\"Development Build\");\n        static readonly GUIContent k_AutoconnectProfiler = EditorGUIUtility.TrTextContent(\"Autoconnect Profiler\", \"When the build is started, an open Profiler Window will automatically connect to the Player and start profiling. The \\\"Build And Run\\\" option will also automatically open the Profiler Window.\");\n        static readonly GUIContent k_AutoconnectProfilerDisabled = EditorGUIUtility.TrTextContent(\"Autoconnect Profiler\", \"Profiling is only enabled in a Development Player.\");\n        static readonly GUIContent k_BuildWithDeepProfiler = EditorGUIUtility.TrTextContent(\"Deep Profiling Support\", \"Build Player with Deep Profiling Support. This might affect Player performance.\");\n        static readonly GUIContent k_BuildWithDeepProfilerDisabled = EditorGUIUtility.TrTextContent(\"Deep Profiling Support\", \"Profiling is only enabled in a Development Player.\");\n        static readonly GUIContent k_AllowDebugging = EditorGUIUtility.TrTextContent(\"Script Debugging\", \"Enable this setting to allow your script code to be debugged.\");\n        static readonly GUIContent k_WaitForManagedDebugger = EditorGUIUtility.TrTextContent(\"Wait For Managed Debugger\", \"Show a dialog where you can attach a managed debugger before any script execution. Can also use volume Up or Down button to confirm on Android.\");\n        static readonly GUIContent k_ManagedDebuggerFixedPort = EditorGUIUtility.TrTextContent(\"Managed Debugger Fixed Port\", \"Use the specified port to attach to the managed debugger. If 0, the port will be automatically selected.\");\n        static readonly GUIContent k_CompressionMethod = EditorGUIUtility.TrTextContent(\"Compression Method\", \"Compression applied to Player data (scenes and resources).\\nDefault - none or default platform compression.\\nLZ4 - fast compression suitable for Development Builds.\\nLZ4HC - higher compression rate variance of LZ4, causes longer build times. Works best for Release Builds.\");\n        static readonly GUIContent k_ExplicitNullChecks = EditorGUIUtility.TrTextContent(\"Explicit Null Checks\");\n        static readonly GUIContent k_ExplicitDivideByZeroChecks = EditorGUIUtility.TrTextContent(\"Divide By Zero Checks\");\n        static readonly GUIContent k_ExplicitArrayBoundsChecks = EditorGUIUtility.TrTextContent(\"Array Bounds Checks\");\n        static readonly Compression[] k_CompressionTypes =\n        {\n            Compression.None,\n            Compression.Lz4,\n            Compression.Lz4HC\n        };\n        static readonly GUIContent[] k_CompressionStrings =\n        {\n            EditorGUIUtility.TrTextContent(\"Default\"),\n            EditorGUIUtility.TrTextContent(\"LZ4\"),\n            EditorGUIUtility.TrTextContent(\"LZ4HC\"),\n        };\n        static readonly GUIContent k_InstallInBuildFolder = EditorGUIUtility.TrTextContent(\"Install into source code 'build' folder\", \"Install into source checkout 'build' folder, for debugging with source code\");\n        static readonly GUIContent k_InstallInBuildFolderHelp = EditorGUIUtility.TrIconContent(\"_Help\", \"Open documentation about source code building and debugging\");\n\n        SerializedProperty m_Development;\n        SerializedProperty m_ConnectProfiler;\n        SerializedProperty m_BuildWithDeepProfilingSupport;\n        SerializedProperty m_AllowDebugging;\n        SerializedProperty m_WaitForManagedDebugger;\n        SerializedProperty m_ManagedDebuggerFixedPort;\n        SerializedProperty m_ExplicitNullChecks;\n        SerializedProperty m_ExplicitDivideByZeroChecks;\n        SerializedProperty m_ExplicitArrayBoundsChecks;\n        SerializedProperty m_CompressionType;\n        SerializedProperty m_InstallInBuildFolder;\n\n        BuildTarget m_BuildTarget;\n        BuildTargetGroup m_BuildTargetGroup;\n        NamedBuildTarget m_NamedBuildTarget;\n        protected bool m_IsClassicProfile = false;\n        protected SharedPlatformSettings m_SharedSettings;\n        BuildProfile m_BuildProfile;\n\n        // The properties can be unresponsive on multiple clicks due to the\n        // complex layout calculations which can slow down GUI rendering.\n        // So we set the GUI label elements' width to make it more responsive.\n        protected virtual float labelWidth => 230;\n\n        public abstract BuildProfilePlatformSettingsBase CreateBuildProfilePlatformSettings();\n\n        public virtual void CopyPlatformSettingsToBuildProfile(BuildProfilePlatformSettingsBase platformSettingsBase)\n        {\n        }\n\n        public virtual void CopyPlatformSettingsFromBuildProfile(BuildProfilePlatformSettingsBase platformSettings)\n        {\n        }\n\n        public virtual PreconfiguredSettingsVariant[] GetPreconfiguredSettingsVariants()\n        {\n            return Array.Empty<PreconfiguredSettingsVariant>();\n        }\n\n        public virtual void OnBuildProfileCreated(BuildProfile buildProfile, int preconfiguredSettingsVariant)\n        {\n        }\n\n        public virtual void OnDisable()\n        {\n        }\n\n        public virtual bool ShouldDrawDevelopmentPlayerCheckbox() => true;\n\n        public virtual bool ShouldDrawLinkTimeOptimization()\n        {\n            return BuildTargetDiscovery.TryGetBuildTarget(m_BuildTarget, out var buildTarget) && buildTarget.BuildPlatformProperties?.SupportLinkTimeOptimization == true;\n        }\n        public virtual bool ShouldDrawProfilerCheckbox() => true;\n        public virtual bool ShouldDrawScriptDebuggingCheckbox() => true;\n        // Enables a dialog \"Wait For Managed debugger\", which halts program execution until managed debugger is connected\n        public virtual bool ShouldDrawWaitForManagedDebugger() => false;\n        public virtual bool ShouldDrawManagedDebuggerFixedPort() => false;\n        public virtual bool ShouldDrawExplicitNullCheckbox() => false;\n        public virtual bool ShouldDrawExplicitDivideByZeroCheckbox() => false;\n        public virtual bool ShouldDrawExplicitArrayBoundsCheckbox() => false;\n        public virtual bool ShouldDrawInstallInBuildFolderCheckbox()\n        {\n            return Unsupported.IsSourceBuild() && PostprocessBuildPlayer.SupportsInstallInBuildFolder(m_BuildTarget);\n        }\n\n        protected virtual string GetPlatformProfileInfoMessage()\n        {\n            return null;\n        }\n\n        public string GetProfileInfoMessage()\n        {\n            return GetPlatformProfileInfoMessage();\n        }\n\n        public VisualElement CreateSettingsGUI(\n            SerializedObject serializedObject, SerializedProperty rootProperty, BuildProfileWorkflowState workflowState)\n        {\n            var commonSettingsGUI = CreateCommonSettingsGUI(serializedObject, rootProperty, workflowState);\n            var platformSettingsGUI = CreatePlatformSettingsGUI(serializedObject, rootProperty, workflowState);\n\n            var settingsGUI = new VisualElement();\n            settingsGUI.Add(platformSettingsGUI);\n            if (BuildPlayerWindow.WillDrawMultiplayerBuildOptions())\n                settingsGUI.Add(CreateMultiplayerSettingsGUI(serializedObject.targetObject as BuildProfile));\n            settingsGUI.Add(commonSettingsGUI);\n            return settingsGUI;\n        }\n\n        public virtual VisualElement CreatePlatformSettingsGUI(\n            SerializedObject serializedObject, SerializedProperty rootProperty, BuildProfileWorkflowState workflowState)\n        {\n            // Default implementation will render all platform settings defined in\n            // BuildProfilePlatformSettingsBase as a PropertyField. Enumerators are\n            // shown as-is.\n            var field = new PropertyField(rootProperty);\n            field.BindProperty(rootProperty);\n            return field;\n        }\n\n        public virtual VisualElement CreatePlatformBuildWarningsGUI(SerializedObject serializedObject, SerializedProperty rootProperty)\n        {\n            return null;\n        }\n\n        public SerializedProperty FindPlatformSettingsPropertyAssert(SerializedProperty rootProperty, string name)\n        {\n            SerializedProperty property = rootProperty.FindPropertyRelative(name);\n            Debug.Assert(property != null);\n            return property;\n        }\n\n        public SerializedProperty FindSerializedObjectPropertyAssert(SerializedObject serializedObject, string name)\n        {\n            SerializedProperty property = serializedObject.FindProperty(name);\n            Debug.Assert(property != null);\n            return property;\n        }\n\n        public VisualElement CreateCommonSettingsGUI(SerializedObject serializedObject, SerializedProperty rootProperty, BuildProfileWorkflowState workflowState)\n        {\n            m_Development = FindPlatformSettingsPropertyAssert(rootProperty, \"m_Development\");\n            m_ConnectProfiler = FindPlatformSettingsPropertyAssert(rootProperty, \"m_ConnectProfiler\");\n            m_BuildWithDeepProfilingSupport = FindPlatformSettingsPropertyAssert(rootProperty, \"m_BuildWithDeepProfilingSupport\");\n            m_AllowDebugging = FindPlatformSettingsPropertyAssert(rootProperty, \"m_AllowDebugging\");\n            m_WaitForManagedDebugger = FindPlatformSettingsPropertyAssert(rootProperty, \"m_WaitForManagedDebugger\");\n            m_ManagedDebuggerFixedPort = FindPlatformSettingsPropertyAssert(rootProperty, \"m_ManagedDebuggerFixedPort\");\n            m_ExplicitNullChecks = FindPlatformSettingsPropertyAssert(rootProperty, \"m_ExplicitNullChecks\");\n            m_ExplicitDivideByZeroChecks = FindPlatformSettingsPropertyAssert(rootProperty, \"m_ExplicitDivideByZeroChecks\");\n            m_ExplicitArrayBoundsChecks = FindPlatformSettingsPropertyAssert(rootProperty, \"m_ExplicitArrayBoundsChecks\");\n            m_CompressionType = FindPlatformSettingsPropertyAssert(rootProperty, \"m_CompressionType\");\n            m_InstallInBuildFolder = FindPlatformSettingsPropertyAssert(rootProperty, \"m_InstallInBuildFolder\");\n\n            m_BuildProfile = serializedObject.targetObject as BuildProfile;\n            Debug.Assert(m_BuildProfile != null, \"Build profile cannot be null\");\n            m_BuildTarget = m_BuildProfile.buildTarget;\n            var subtarget = m_BuildProfile.subtarget;\n            m_BuildTargetGroup = BuildPipeline.GetBuildTargetGroup(m_BuildTarget);\n            m_NamedBuildTarget = (subtarget == StandaloneBuildSubtarget.Server) ? NamedBuildTarget.Server : NamedBuildTarget.FromBuildTargetGroup(m_BuildTargetGroup);\n            m_IsClassicProfile = BuildProfileContext.IsClassicPlatformProfile(m_BuildProfile);\n            m_SharedSettings = BuildProfileContext.instance.sharedProfile.platformBuildProfile as SharedPlatformSettings;\n\n            return new IMGUIContainer(\n                () =>\n                {\n                    if (serializedObject == null || !serializedObject.isValid)\n                    {\n                        return;\n                    }\n\n                    var oldLabelWidth = EditorGUIUtility.labelWidth;\n                    EditorGUIUtility.labelWidth = labelWidth;\n                    serializedObject.UpdateIfRequiredOrScript();\n                    ShowCommonBuildOptions(workflowState);\n                    serializedObject.ApplyModifiedProperties();\n                    EditorGUIUtility.labelWidth = oldLabelWidth;\n                });\n        }\n\n        VisualElement CreateMultiplayerSettingsGUI(BuildProfile profile)\n        {\n            return new IMGUIContainer(\n                () =>\n                {\n                    var oldLabelWidth = EditorGUIUtility.labelWidth;\n                    EditorGUIUtility.labelWidth = labelWidth;\n                    BuildPlayerWindow.DrawMultiplayerBuildOption(profile);\n                    EditorGUIUtility.labelWidth = oldLabelWidth;\n                });\n        }\n\n        public void ShowCommonBuildOptions(BuildProfileWorkflowState workflowState)\n        {\n            if (ShouldDrawDevelopmentPlayerCheckbox())\n            {\n                ShowDevelopmentPlayerCheckbox();\n            }\n\n            if (ShouldDrawLinkTimeOptimization())\n            {\n                ShowLinkTimeOptimization();\n            }\n\n            using (new EditorGUI.DisabledScope(!m_Development.boolValue))\n            {\n                if (ShouldDrawProfilerCheckbox())\n                {\n                    ShowProfilerCheckbox();\n                }\n\n                if (ShouldDrawScriptDebuggingCheckbox())\n                {\n                    ShowScriptDebuggingCheckbox();\n                }\n            }\n\n            if (ShouldDrawExplicitNullCheckbox())\n            {\n                ShowExplicitNullChecksToggle();\n            }\n\n            if (ShouldDrawExplicitDivideByZeroCheckbox())\n            {\n                ShowDivideByZeroChecksToggle();\n            }\n\n            if (ShouldDrawExplicitArrayBoundsCheckbox())\n            {\n                ShowArrayBoundsChecksToggle();\n            }\n\n            var postprocessor = ModuleManager.GetBuildPostProcessor(m_BuildTarget);\n\n            if (postprocessor != null && postprocessor.SupportsLz4Compression())\n            {\n                using (var vertical = new EditorGUILayout.VerticalScope())\n                using (var propertyScope = new EditorGUI.PropertyScope(vertical.rect, GUIContent.none, m_CompressionType))\n                {\n                    var cmpIdx = Array.IndexOf(k_CompressionTypes, (Compression)m_CompressionType.intValue);\n                    if (cmpIdx == BuildProfilePlatformSettingsBase.k_InvalidCompressionIdx)\n                        cmpIdx = Array.IndexOf(k_CompressionTypes, postprocessor.GetDefaultCompression());\n                    if (cmpIdx == BuildProfilePlatformSettingsBase.k_InvalidCompressionIdx)\n                        cmpIdx = (int)CompressionType.Lz4;  // Lz4 by default.\n                    cmpIdx = EditorGUILayout.Popup(k_CompressionMethod, cmpIdx, k_CompressionStrings);\n                    m_CompressionType.intValue = (int)k_CompressionTypes[cmpIdx];\n\n                    if (m_BuildTargetGroup == BuildTargetGroup.Standalone && m_IsClassicProfile)\n                    {\n                        m_SharedSettings.compressionType = (Compression)m_CompressionType.intValue;\n                    }\n                }\n            }\n\n            if (ShouldDrawInstallInBuildFolderCheckbox())\n            {\n                using (new EditorGUILayout.HorizontalScope())\n                {\n                    EditorGUILayout.PropertyField(m_InstallInBuildFolder, k_InstallInBuildFolder, GUILayout.ExpandWidth(false));\n                    EditorGUILayout.BeginVertical();\n                    GUILayout.Space(3);\n                    if (GUILayout.Button(k_InstallInBuildFolderHelp, EditorStyles.iconButton))\n                    {\n                        const string k_ViewScriptPath = \"Documentation/InternalDocs/view\";\n                        const string k_WindowsEditorScriptExtension = \".cmd\";\n                        const string k_MacAndLinuxEditorScriptExtension = \".sh\";\n\n                        var path = Path.Combine(Unsupported.GetBaseUnityDeveloperFolder(), k_ViewScriptPath);\n                        if (Application.platform == RuntimePlatform.WindowsEditor)\n                            System.Diagnostics.Process.Start(path + k_WindowsEditorScriptExtension);\n                        else\n                            System.Diagnostics.Process.Start(path + k_MacAndLinuxEditorScriptExtension);\n                    }\n\n                    EditorGUILayout.EndVertical();\n                }\n            }\n            else\n                m_InstallInBuildFolder.boolValue = false;\n\n            if (m_IsClassicProfile)\n            {\n                m_SharedSettings.installInBuildFolder = m_InstallInBuildFolder.boolValue;\n            }\n\n            ActionState buildAndRunState = (m_InstallInBuildFolder != null && m_InstallInBuildFolder.boolValue) ? ActionState.Disabled : workflowState.buildAndRunAction;\n            workflowState.UpdateBuildActionStates(workflowState.buildAction, buildAndRunState);\n\n            if (Unsupported.IsSourceBuild())\n                ShowInternalPlatformBuildOptions();\n        }\n\n        /// <summary>\n        /// Show the Development checkbox. Platforms can override this method to hide/customize the UI.\n        /// </summary>\n        public virtual void ShowDevelopmentPlayerCheckbox()\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_Development, k_DevelopmentBuild);\n            if (EditorGUI.EndChangeCheck() && m_IsClassicProfile)\n            {\n                m_SharedSettings.development = m_Development.boolValue;\n            }\n        }\n\n        /// <summary>\n        /// Show Link Time Optimization. Platforms can override this method to show/customize the UI.\n        /// </summary>\n        public virtual void ShowLinkTimeOptimization()\n        {\n        }\n\n        /// <summary>\n        /// Show profiler checkboxes, including Autoconnect Profiler and Deep Profiling Support checkboxes.\n        /// Platforms can override this method to hide/customize the UI.\n        /// </summary>\n        public virtual void ShowProfilerCheckbox()\n        {\n            var autoConnectLabel = m_Development.boolValue ? k_AutoconnectProfiler : k_AutoconnectProfilerDisabled;\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_ConnectProfiler, autoConnectLabel);\n            if (EditorGUI.EndChangeCheck() && m_IsClassicProfile)\n            {\n                m_SharedSettings.connectProfiler = m_ConnectProfiler.boolValue;\n            }\n\n            var buildWithDeepProfilerLabel = m_Development.boolValue ? k_BuildWithDeepProfiler : k_BuildWithDeepProfilerDisabled;\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_BuildWithDeepProfilingSupport, buildWithDeepProfilerLabel);\n            if (EditorGUI.EndChangeCheck() && m_IsClassicProfile)\n            {\n                m_SharedSettings.buildWithDeepProfilingSupport = m_BuildWithDeepProfilingSupport.boolValue;\n            }\n        }\n\n        /// <summary>\n        /// Show script debugging options. Platforms can override this method to hide/customize the UI.\n        /// </summary>\n        public virtual void ShowScriptDebuggingCheckbox()\n        {\n            ShowManagedDebuggerCheckboxes();\n            var currentPlayerSettings = BuildProfileModuleUtil.GetBuildProfileOrGlobalPlayerSettings(m_BuildProfile);\n            if (m_AllowDebugging.boolValue && PlayerSettings.GetScriptingBackend_Internal(currentPlayerSettings, m_NamedBuildTarget.TargetName) == ScriptingImplementation.IL2CPP)\n            {\n                var apiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(m_NamedBuildTarget);\n                bool isDebuggerUsable = apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6 || apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0 ||\n                    apiCompatibilityLevel == ApiCompatibilityLevel.NET_Unity_4_8 || apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard;\n\n                if (!isDebuggerUsable)\n                    EditorGUILayout.HelpBox(\"Script debugging is only supported with IL2CPP on .NET 4.x and .NET Standard 2.0 API Compatibility Levels.\", MessageType.Warning);\n            }\n        }\n\n        /// <summary>\n        /// Show managed debugger options. Platforms can override this method to\n        /// hide/customize the UI.\n        /// </summary>\n        public virtual void ShowManagedDebuggerCheckboxes()\n        {\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.PropertyField(m_AllowDebugging, k_AllowDebugging);\n            if (EditorGUI.EndChangeCheck() && m_IsClassicProfile)\n            {\n                m_SharedSettings.allowDebugging = m_AllowDebugging.boolValue;\n            }\n\n            // Not all platforms have native dialog implemented in Runtime\\Misc\\GiveDebuggerChanceToAttachIfRequired.cpp\n            // Display this option only for developer builds\n            if (ShouldDrawWaitForManagedDebugger())\n            {\n                ShowWaitForManagedDebuggerCheckbox();\n            }\n\n            if (ShouldDrawManagedDebuggerFixedPort())\n            {\n                ShowManagedDebuggerFixedPort();\n            }\n        }\n\n        public void ShowWaitForManagedDebuggerCheckbox()\n        {\n            if (m_AllowDebugging.boolValue)\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUILayout.PropertyField(m_WaitForManagedDebugger, k_WaitForManagedDebugger);\n                if (EditorGUI.EndChangeCheck() && m_IsClassicProfile)\n                {\n                    m_SharedSettings.waitForManagedDebugger = m_WaitForManagedDebugger.boolValue;\n                }\n            }\n        }\n\n        public void ShowManagedDebuggerFixedPort()\n        {\n            if (m_AllowDebugging.boolValue)\n            {\n                EditorGUI.BeginChangeCheck();\n                EditorGUILayout.PropertyField(m_ManagedDebuggerFixedPort, k_ManagedDebuggerFixedPort);\n                if (m_ManagedDebuggerFixedPort.intValue < 0 || m_ManagedDebuggerFixedPort.intValue > BuildProfilePlatformSettingsBase.k_MaxPortNumber)\n                {\n                    m_ManagedDebuggerFixedPort.intValue = 0;\n                }\n\n                if (EditorGUI.EndChangeCheck() && m_IsClassicProfile)\n                {\n                    m_SharedSettings.managedDebuggerFixedPort = m_ManagedDebuggerFixedPort.intValue;\n                }\n            }\n        }\n\n        public void ShowExplicitNullChecksToggle()\n        {\n            using (new EditorGUI.DisabledScope(m_Development.boolValue))\n            {\n                EditorGUILayout.PropertyField(m_ExplicitNullChecks, k_ExplicitNullChecks);\n            }\n\n            // Force 'ExplicitNullChecks' to true if it's a development build.\n            if (m_Development.boolValue)\n                m_ExplicitNullChecks.boolValue = true;\n\n            if (m_IsClassicProfile)\n            {\n                m_SharedSettings.explicitNullChecks = m_ExplicitNullChecks.boolValue;\n            }\n        }\n\n        public void ShowDivideByZeroChecksToggle()\n        {\n            using (new EditorGUI.DisabledScope(m_Development.boolValue))\n            {\n                EditorGUILayout.PropertyField(m_ExplicitDivideByZeroChecks, k_ExplicitDivideByZeroChecks);\n            }\n\n            // Force 'explicitDivideByZeroChecks' to true if it's a development build.\n            if (m_Development.boolValue)\n                m_ExplicitDivideByZeroChecks.boolValue = true;\n\n            if (m_IsClassicProfile)\n            {\n                m_SharedSettings.explicitDivideByZeroChecks = m_ExplicitDivideByZeroChecks.boolValue;\n            }\n        }\n\n        public void ShowArrayBoundsChecksToggle()\n        {\n            using (new EditorGUI.DisabledScope(m_Development.boolValue))\n            {\n                EditorGUILayout.PropertyField(m_ExplicitArrayBoundsChecks, k_ExplicitArrayBoundsChecks);\n            }\n\n            // Force 'explicitArrayBoundsChecks' to true if it's a development build.\n            if (m_Development.boolValue)\n                m_ExplicitArrayBoundsChecks.boolValue = true;\n\n            if (m_IsClassicProfile)\n            {\n                m_SharedSettings.explicitArrayBoundsChecks = m_ExplicitArrayBoundsChecks.boolValue;\n            }\n        }\n\n        /// <summary>\n        /// Show internal platform build options for source-built editor.\n        /// </summary>\n        public virtual void ShowInternalPlatformBuildOptions()\n        {\n        }\n\n        /// Helper method for rendering an IMGUI popup over an enum\n        /// serialized property.\n        /// </summary>\n        protected void ShowIMGUIPopupOption<T>\n        (\n            GUIContent label,\n            (T SettingValue, GUIContent GUIString)[] options,\n            SerializedProperty currentSetting\n        ) where T : Enum\n        {\n            using var vertical = new EditorGUILayout.VerticalScope();\n            using var prop = new EditorGUI.PropertyScope(vertical.rect, GUIContent.none, currentSetting);\n\n            // Find the index of the currently set value relative to the GUI layout\n            var selectedIndex = Array.FindIndex(options,\n                match => match.SettingValue.Equals((T)(object)currentSetting.intValue));\n            selectedIndex = selectedIndex < 0 ? 0 : selectedIndex;\n\n            var GUIStrings = new GUIContent[options.Length];\n            for (var i = 0; i < options.Length; i++)\n                GUIStrings[i] = options[i].GUIString;\n\n            EditorGUI.BeginChangeCheck();\n            var newIndex = EditorGUILayout.Popup(label, selectedIndex, GUIStrings);\n            if (EditorGUI.EndChangeCheck())\n                currentSetting.intValue = (int)(object)options[newIndex].SettingValue;\n        }\n\n        /// <summary>\n        /// Helper method for rendering an IMGUI popup over an enum\n        /// serialized property.\n        /// </summary>\n        protected bool ShowIMGUIPopupOption<T>\n        (\n            GUIContent label,\n            T[] options,\n            GUIContent[] optionString,\n            SerializedProperty currentSetting\n        ) where T : Enum\n        {\n            using var vertical = new EditorGUILayout.VerticalScope();\n            using var prop = new EditorGUI.PropertyScope(vertical.rect, GUIContent.none, currentSetting);\n\n            // Find the index of the currently set value relative to the GUI layout\n            var selectedIndex = Array.FindIndex(options,\n                match => match.Equals((T)(object)currentSetting.intValue));\n            selectedIndex = selectedIndex < 0 ? 0 : selectedIndex;\n\n            EditorGUI.BeginChangeCheck();\n            var newIndex = EditorGUILayout.Popup(label, selectedIndex, optionString);\n            if (EditorGUI.EndChangeCheck())\n            {\n                currentSetting.intValue = (int)(object)options[newIndex];\n                return true;\n            }\n\n            return false;\n        }\n\n        /// <summary>\n        /// Helper method for rendering an IMGUI popup over an enum.\n        /// </summary>\n        protected bool ShowIMGUIPopupOption<T>\n        (\n            GUIContent label,\n            T[] options,\n            GUIContent[] optionString,\n            T currentSetting,\n            out T returnSettings\n        ) where T : Enum\n        {\n            using var vertical = new EditorGUILayout.VerticalScope();\n            returnSettings = currentSetting;\n\n            // Find the index of the currently set value relative to the GUI layout\n            var selectedIndex = Array.FindIndex(options,\n                match => match.Equals(currentSetting));\n            selectedIndex = selectedIndex < 0 ? 0 : selectedIndex;\n\n            EditorGUI.BeginChangeCheck();\n            var newIndex = EditorGUILayout.Popup(label, selectedIndex, optionString);\n            if (EditorGUI.EndChangeCheck())\n            {\n                returnSettings = options[newIndex];\n                return true;\n            }\n\n            return false;\n        }\n\n        /// <summary>\n        /// Helper method for rendering an IMGUI popup for GUIContent\n        /// option values\n        /// </summary>\n        protected int ShowIMGUIPopupOptionForGUIContents\n        (\n            GUIContent label,\n            GUIContent[] optionValues,\n            GUIContent[] displayNames,\n            SerializedProperty property\n        )\n        {\n            EditorGUI.BeginChangeCheck();\n            using var verticalScope = new EditorGUILayout.VerticalScope();\n            using var propertyScope = new EditorGUI.PropertyScope(verticalScope.rect, GUIContent.none, property);\n            int selectedIndex = Math.Max(0, Array.FindIndex(optionValues, item => item.text == property.stringValue));\n            selectedIndex = EditorGUILayout.Popup(label, selectedIndex, displayNames);\n            if (EditorGUI.EndChangeCheck())\n            {\n                property.stringValue = optionValues[selectedIndex].text;\n            }\n            return selectedIndex;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/DefaultBuildWindowExtension.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor.Modules\n{\n    internal class DefaultBuildWindowExtension : IBuildWindowExtension\n    {\n        internal class Styles\n        {\n            public GUIContent runLastBuild = EditorGUIUtility.TrTextContent(\"Run Last Build\", \"Run the most recent build\");\n            public static readonly GUIContent patch = EditorGUIUtility.TrTextContent(\"Patch\", \"Compiles only the scripts and patches the previous build with the updated code.\");\n            public static readonly GUIContent patchAndRun = EditorGUIUtility.TrTextContent(\"Patch And Run\", \"Compiles only the scripts, patches the previous build with the updated code, then runs the build.\");\n        }\n\n        static private Styles m_Styles = null;\n\n        internal Styles styles\n        {\n            get\n            {\n                if (m_Styles == null)\n                    m_Styles = new Styles();\n                return m_Styles;\n            }\n        }\n\n        public virtual void ShowPlatformBuildOptions() {}\n        public virtual void ShowPlatformBuildWarnings() {}\n        public virtual void ShowInternalPlatformBuildOptions() {}\n        public virtual bool EnabledBuildButton() { return true; }\n        public virtual bool EnabledBuildAndRunButton() { return true; }\n        public virtual void GetBuildButtonTitles(out GUIContent buildButtonTitle, out GUIContent buildAndRunButtonTitle)\n        {\n            buildButtonTitle = null;\n            buildAndRunButtonTitle = null;\n        }\n\n        public virtual bool AskForBuildLocation()\n        {\n            return true;\n        }\n\n        public virtual bool ShouldDrawScriptDebuggingCheckbox() { return true; }\n        public virtual bool ShouldDrawProfilerCheckbox() { return true; }\n        public virtual bool ShouldDrawDevelopmentPlayerCheckbox() { return true; }\n        public virtual bool ShouldDrawExplicitNullCheckbox() { return false; }\n        public virtual bool ShouldDrawExplicitDivideByZeroCheckbox() { return false; }\n        public virtual bool ShouldDrawExplicitArrayBoundsCheckbox() { return false; }\n        public virtual bool ShouldDrawForceOptimizeScriptsCheckbox() { return false; }\n        public virtual bool ShouldDrawWaitForManagedDebugger() { return false; }\n        public virtual bool ShouldDrawManagedDebuggerFixedPort() { return false; }\n        public virtual bool ShouldDisableManagedDebuggerCheckboxes() { return false; }\n        public virtual bool ShouldDrawRunLastBuildButton() { return false; }\n        public virtual void DoRunLastBuildButtonGui()\n        {\n            GUI.enabled = EnabledRunLastBuildButton();\n            if (GUILayout.Button(styles.runLastBuild, GUILayout.Width(110)))\n            {\n                DoRunLastBuild();\n                GUIUtility.ExitGUI();\n            }\n            GUI.enabled = true;\n        }\n\n        protected virtual bool EnabledRunLastBuildButton() { return false; }\n        protected virtual void DoRunLastBuild() {}\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/DefaultCompilationExtension.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing Mono.Cecil;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEngine;\n\nnamespace UnityEditor.Modules\n{\n    internal class DefaultCompilationExtension\n        : ICompilationExtension\n    {\n        public virtual string[] GetCompilerExtraAssemblyPaths(bool isEditor, string assemblyPathName)\n        {\n            return new string[] {};\n        }\n\n        public virtual IEnumerable<string> GetWindowsMetadataReferences()\n        {\n            return new string[0];\n        }\n\n        public virtual IEnumerable<string> GetAdditionalAssemblyReferences()\n        {\n            return new string[0];\n        }\n\n        public virtual IEnumerable<string> GetAdditionalDefines()\n        {\n            return new string[0];\n        }\n\n        public virtual IEnumerable<string> GetAdditionalEditorDefines()\n        {\n            return new string[0];\n        }\n\n        public virtual IEnumerable<string> GetAdditionalSourceFiles()\n        {\n            return new string[0];\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/DefaultPlatformSupportModule.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditor.DeploymentTargets;\n\nnamespace UnityEditor.Modules\n{\n    internal abstract class DefaultPlatformSupportModule : IPlatformSupportModule\n    {\n        protected ICompilationExtension compilationExtension;\n\n        protected ITextureImportSettingsExtension textureSettingsExtension;\n\n        public abstract string TargetName { get; }\n\n        public abstract string JamTarget { get; }\n\n        public abstract IBuildTarget PlatformBuildTarget { get; }\n\n        public virtual string ExtensionVersion { get { return null; } }\n\n        public virtual GUIContent[] GetDisplayNames() { return null; }\n\n        public virtual string[] NativeLibraries { get { return new string[0]; } }\n\n        public virtual string[] AssemblyReferencesForUserScripts { get { return new string[0]; } }\n\n        public virtual string[] AssemblyReferencesForEditorCsharpProject { get { return new string[0]; } }\n\n        public abstract IBuildPostprocessor CreateBuildPostprocessor();\n\n        public virtual IScriptingImplementations CreateScriptingImplementations() { return null; }\n\n        public virtual ISettingEditorExtension CreateSettingsEditorExtension() { return null; }\n\n        public virtual IAdaptiveVsyncSetting CreateAdaptiveSettingEditorExtension() { return null; }\n\n        public virtual IPreferenceWindowExtension CreatePreferenceWindowExtension() { return null; }\n\n        public virtual ITextureImportSettingsExtension CreateTextureImportSettingsExtension() { return textureSettingsExtension != null ? textureSettingsExtension : textureSettingsExtension = new DefaultTextureImportSettingsExtension(); }\n\n        public virtual IBuildWindowExtension CreateBuildWindowExtension() { return null; }\n\n        public virtual ICompilationExtension CreateCompilationExtension() { return compilationExtension != null ? compilationExtension : compilationExtension = new DefaultCompilationExtension(); }\n\n        public virtual IPluginImporterExtension CreatePluginImporterExtension() { return null; }\n\n        public virtual IBuildProfileExtension CreateBuildProfileExtension() { return null; }\n\n        public virtual IDeploymentTargetsExtension CreateDeploymentTargetsExtension() { return null; }\n\n        public virtual void RegisterAdditionalUnityExtensions() {}\n\n        public virtual IDevice CreateDevice(string id) { throw new NotSupportedException(); }\n\n        public virtual void OnActivate() {}\n\n        public virtual void OnDeactivate() {}\n\n        public virtual void OnLoad() {}\n\n        public virtual void OnUnload() {}\n\n        public virtual IEnumerable<ScriptAssemblyPlatform> GetExtraScriptAssemblyPlatforms(BuildTarget target = BuildTarget.NoTarget)\n        {\n            return Enumerable.Empty<ScriptAssemblyPlatform>();\n        }\n\n        public virtual IEditorAnalyticsExtension GetEditorAnalyticsExtension() { return null; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/DefaultPlayerSettingsEditorExtension.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.Build;\nusing UnityEditor.Build.Profile;\nusing UnityEngine;\nusing TargetAttributes = UnityEditor.BuildTargetDiscovery.TargetAttributes;\n\nnamespace UnityEditor.Modules\n{\n    internal abstract class DefaultPlayerSettingsEditorExtension : ISettingEditorExtension\n    {\n        protected PlayerSettingsEditor m_playerSettingsEditor;\n\n        protected PlayerSettingsEditor playerSettingsEditor\n        {\n            get { return m_playerSettingsEditor; }\n        }\n\n        public virtual void OnEnable(PlayerSettingsEditor settingsEditor)\n        {\n            m_playerSettingsEditor = settingsEditor;\n\n            m_MTRendering = playerSettingsEditor.FindPropertyAssert(\"m_MTRendering\");\n        }\n\n        public virtual void ConfigurePlatformProfile(SerializedObject serializedProfile)\n        {\n        }\n\n        public virtual bool CopyProjectSettingsPlayerSettingsToBuildProfile()\n        {\n            return false;\n        }\n\n        public virtual bool IsPlayerSettingsDataEqualToProjectSettings()\n        {\n            return true;\n        }\n\n        public virtual void OnActiveProfileChanged(BuildProfile previous, BuildProfile newProfile)\n        {\n        }\n\n        public virtual bool HasPublishSection()\n        {\n            return true;\n        }\n\n        public virtual void PublishSectionGUI(float h, float midWidth, float maxWidth) {}\n\n        public virtual bool HasIdentificationGUI()\n        {\n            return false;\n        }\n\n        public virtual void IdentificationSectionGUI() {}\n\n        public virtual void ConfigurationSectionGUI() {}\n\n        public virtual void RenderingSectionGUI() {}\n\n        public virtual bool SupportsOrientation()\n        {\n            return false;\n        }\n\n        public virtual bool CanShowUnitySplashScreen()\n        {\n            return false;\n        }\n\n        public virtual void SplashSectionGUI() {}\n\n        public virtual bool UsesStandardIcons()\n        {\n            return true;\n        }\n\n        public virtual void IconSectionGUI() {}\n\n        public virtual bool HasResolutionSection()\n        {\n            return false;\n        }\n\n        public virtual bool SupportsStaticBatching()\n        {\n            return true;\n        }\n\n        public virtual bool SupportsDynamicBatching()\n        {\n            return true;\n        }\n\n        public virtual void ResolutionSectionGUI(float h, float midWidth, float maxWidth) {}\n\n        public virtual bool HasBundleIdentifier()\n        {\n            return true;\n        }\n\n        public virtual bool SupportsHighDynamicRangeDisplays()\n        {\n            return false;\n        }\n\n        public virtual bool SupportsGfxJobModes()\n        {\n            return false;\n        }\n\n        public virtual GraphicsJobMode AdjustGfxJobMode(GraphicsJobMode graphicsJobMode)\n        {\n            return graphicsJobMode;\n        }\n\n        public virtual bool SupportsMultithreadedRendering()\n        {\n            return false;\n        }\n\n        public virtual bool SupportsFrameTimingStatistics()\n        {\n            return false;\n        }\n\n        public virtual void SerializedObjectUpdated() {}\n\n        protected SerializedProperty m_MTRendering;\n        private static readonly GUIContent m_MTRenderingTooltip = EditorGUIUtility.TrTextContent(\"Multithreaded Rendering*\");\n\n        protected virtual GUIContent MultithreadedRenderingGUITooltip()\n        {\n            return m_MTRenderingTooltip;\n        }\n\n        public virtual void MultithreadedRenderingGUI(NamedBuildTarget namedBuildTarget)\n        {\n            // For platforms defined as IsMTRenderingDisabledByDefault in BuildTargetDiscovery::PreloadKnownBuildTargets (iPhone, tvOS, Android) the \"Multithreaded Rendering\" feature is controlled by PlayerSettings::m_MobileMTRenderingBaked (whose default is false)\n            // For other platforms the \"Multithreaded Rendering\" feature is controlled by PlayerSettings::m_MTRendering. Default value is true (set during PlayerSettings::Reset)\n            if (BuildTargetDiscovery.PlatformGroupHasFlag(namedBuildTarget.ToBuildTargetGroup(), TargetAttributes.IsMTRenderingDisabledByDefault))\n            {\n                var playerSettings = playerSettingsEditor.m_SerializedObject.targetObject as PlayerSettings;\n                Debug.Assert(playerSettings != null);\n\n                bool oldValue = playerSettings.GetMobileMTRenderingInternal_Instance(namedBuildTarget.TargetName);\n                bool newValue = EditorGUILayout.Toggle(MultithreadedRenderingGUITooltip(), oldValue);\n                if (oldValue != newValue)\n                {\n                    playerSettings.SetMobileMTRenderingInternal_Instance(namedBuildTarget.TargetName, newValue);\n                    playerSettingsEditor.OnTargetObjectChangedDirectly();\n                }\n            }\n            else EditorGUILayout.PropertyField(m_MTRendering, m_MTRenderingTooltip);\n        }\n\n        public virtual bool SupportsCustomLightmapEncoding()\n        {\n            return false;\n        }\n\n        public virtual bool SupportsCustomNormalMapEncoding()\n        {\n            return false;\n        }\n\n        public virtual bool ShouldShowVulkanSettings()\n        {\n            return false;\n        }\n\n        public virtual void VulkanSectionGUI() {}\n\n        public virtual bool SupportsForcedSrgbBlit()\n        {\n            return false;\n        }\n\n        public virtual bool SupportsStaticSplashScreenBackgroundColor()\n        {\n            return false;\n        }\n\n        public virtual void AutoRotationSectionGUI() {}\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/DefaultPluginImporterExtension.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEngine;\n\nnamespace UnityEditor.Modules\n{\n    internal class DefaultPluginImporterExtension : IPluginImporterExtension\n    {\n        protected bool hasModified = false;\n        protected Property[] properties = null;\n        protected const string cpuKey = \"CPU\";\n\n        internal class Property\n        {\n            internal GUIContent name { get; set; }\n            internal string key { get; set; }\n            internal object defaultValue { get; set; }\n            internal Type type { get; set; }\n            internal string platformName { get; set; }\n            internal object value { get; set; }\n\n            internal Property(string name, string key, object defaultValue, string platformName)\n                : this(new GUIContent(name), key, defaultValue, platformName)\n            {\n            }\n\n            internal Property(GUIContent name, string key, object defaultValue, string platformName)\n            {\n                this.name = name;\n                this.key = key;\n                this.defaultValue = defaultValue;\n                this.type = defaultValue.GetType();\n                this.platformName = platformName;\n            }\n\n            internal virtual void Reset(PluginImporterInspector inspector)\n            {\n                string valueString = inspector.importer.GetPlatformData(platformName, key);\n                ParseStringValue(inspector, valueString);\n            }\n\n            protected void ParseStringValue(PluginImporterInspector inspector, string valueString, bool muteWarnings = false)\n            {\n                try\n                {\n                    value = TypeDescriptor.GetConverter(type).ConvertFromString(valueString);\n                }\n                catch\n                {\n                    value = defaultValue;\n\n                    if (!muteWarnings && !string.IsNullOrEmpty(valueString))\n                    {\n                        // We mute warnings for properties that are on disabled platforms to avoid unnecessary spam for deprecated values, case 909247\n                        if (inspector.importer.GetCompatibleWithPlatform(platformName))\n                            Debug.LogWarning(\"Failed to parse value ('\" + valueString + \"') for \" + key + \", platform: \" + platformName + \", type: \" + type + \". Default value will be set '\" + defaultValue + \"'\");\n                    }\n                }\n            }\n\n            internal virtual void Apply(PluginImporterInspector inspector)\n            {\n                string valueString = type == typeof(bool) ? value.ToString().ToLower() : value.ToString();\n                inspector.importer.SetPlatformData(platformName, key, valueString);\n            }\n\n            internal virtual void OnGUI(PluginImporterInspector inspector)\n            {\n                if (type == typeof(bool)) value = EditorGUILayout.Toggle(name, (bool)value);\n                else if (type.IsEnum)\n                {\n                    if (type.GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0)\n                        value = EditorGUILayout.EnumFlagsField(name, (Enum)value);\n                    else\n                        value = EditorGUILayout.EnumPopup(name, (Enum)value);\n                }\n                else if (type == typeof(string)) value = EditorGUILayout.TextField(name, (string)value);\n                else throw new NotImplementedException(\"Don't know how to display value.\");\n            }\n        }\n\n        internal bool propertiesRefreshed = false;\n\n        public DefaultPluginImporterExtension(Property[] properties)\n        {\n            this.properties = properties;\n        }\n\n        protected virtual Property[] GetPropertiesForInspector(PluginImporterInspector inspector)\n        {\n            return properties;\n        }\n\n        public virtual void ResetValues(PluginImporterInspector inspector)\n        {\n            hasModified = false;\n            RefreshProperties(inspector);\n        }\n\n        public virtual bool HasModified(PluginImporterInspector inspector)\n        {\n            return hasModified;\n        }\n\n        public virtual void Apply(PluginImporterInspector inspector)\n        {\n            if (!propertiesRefreshed) return;\n\n            foreach (var p in GetPropertiesForInspector(inspector))\n            {\n                p.Apply(inspector);\n            }\n\n            hasModified = false;\n        }\n\n        public virtual void OnEnable(PluginImporterInspector inspector)\n        {\n            RefreshProperties(inspector);\n        }\n\n        public virtual void OnDisable(PluginImporterInspector inspector)\n        {\n        }\n\n        public virtual void OnPlatformSettingsGUI(PluginImporterInspector inspector)\n        {\n            if (!propertiesRefreshed) RefreshProperties(inspector);\n\n            EditorGUI.BeginChangeCheck();\n            foreach (var p in GetPropertiesForInspector(inspector))\n            {\n                // skip CPU property for things that aren't native libs\n                if (p.key == cpuKey && !inspector.importer.isNativePlugin)\n                    continue;\n                p.OnGUI(inspector);\n            }\n            if (EditorGUI.EndChangeCheck()) hasModified = true;\n        }\n\n        protected virtual void RefreshProperties(PluginImporterInspector inspector)\n        {\n            foreach (var p in GetPropertiesForInspector(inspector))\n            {\n                p.Reset(inspector);\n            }\n            propertiesRefreshed = true;\n        }\n\n        public virtual string CalculateFinalPluginPath(string platformName, PluginImporter imp)\n        {\n            string cpu = imp.GetPlatformData(platformName, cpuKey);\n\n            if (!string.IsNullOrEmpty(cpu) && (string.Compare(cpu, \"AnyCPU\", true) != 0) && (string.Compare(cpu, \"None\", true) != 0))\n                return Path.Combine(cpu, Path.GetFileName(imp.assetPath));\n\n            return Path.GetFileName(imp.assetPath);\n        }\n\n        private static bool IsPluginDefinesCompatible(PluginImporter pluginImporter, string buildTargetName, string[] defines)\n        {\n            var defineConstraints = pluginImporter.DefineConstraints;\n            return DefineConstraintsHelper.IsDefineConstraintsCompatible(defines, defineConstraints);\n        }\n\n        protected Dictionary<string, List<PluginImporter>> GetCompatiblePlugins(string buildTargetName, string[] defines)\n        {\n            var pluginImporters = PluginImporter.GetImporters(buildTargetName);\n            var plugins = pluginImporters\n                .Where(pluginImporter => IsPluginDefinesCompatible(pluginImporter, buildTargetName, defines));\n\n            plugins = PluginImporter.FilterAssembliesByAssemblyVersion(plugins);\n\n            var matchingPlugins = new Dictionary<string, List<PluginImporter>>();\n            foreach (var plugin in plugins)\n            {\n                string finalPluginPath = CalculateFinalPluginPath(buildTargetName, plugin);\n                if (string.IsNullOrEmpty(finalPluginPath))\n                    continue;\n\n                if (!matchingPlugins.TryGetValue(finalPluginPath, out var pluginsList))\n                {\n                    pluginsList = new List<PluginImporter>();\n                    matchingPlugins[finalPluginPath] = pluginsList;\n                }\n                pluginsList.Add(plugin);\n            }\n\n            return matchingPlugins;\n        }\n\n        public virtual bool CheckFileCollisions(string buildTargetName, string[] defineConstraints)\n        {\n            Dictionary<string, List<PluginImporter>> matchingPlugins = GetCompatiblePlugins(buildTargetName, defineConstraints);\n\n            bool foundCollisions = false;\n\n            StringBuilder errorMessage = new StringBuilder();\n            foreach (KeyValuePair<string, List<PluginImporter>> pair in matchingPlugins)\n            {\n                List<PluginImporter> plugins = pair.Value;\n                // If we have only one plugin with specified final path, that means everything is ok, and no overwrite will occur\n                if (plugins.Count == 1) continue;\n\n                // Project plugins are those found inside of the User's project folder.\n                int projectPluginCount = 0;\n                foreach (PluginImporter importer in plugins)\n                {\n                    if (!importer.GetIsOverridable())\n                    {\n                        projectPluginCount++;\n                    }\n                }\n\n                // If we have a single user project plugin, it will take precedence and overwrite the others.\n                // Anything else should throw errors if there are multiple.\n                if (projectPluginCount == 1)\n                    continue;\n\n                foundCollisions = true;\n                // Two or more plugins are being copied to the same path, create an error message\n                errorMessage.AppendLine(string.Format(\"Plugin '{0}' is used from several locations:\", Path.GetFileName(pair.Key)));\n                foreach (PluginImporter importer in plugins)\n                {\n                    errorMessage.AppendLine(\" \" + importer.assetPath + \" would be copied to <PluginPath>/\" + pair.Key.Replace(\"\\\\\", \"/\"));\n                }\n            }\n            if (foundCollisions)\n            {\n                errorMessage.AppendLine(\"Please fix plugin settings and try again.\");\n                Debug.LogError(errorMessage.ToString());\n            }\n\n            return foundCollisions;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/DefaultTextureImportSettingsExtension.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.AnimatedValues;\nusing UnityEditor.Modules;\nusing UnityEngine;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System;\nusing UnityEngine.Experimental.Rendering;\nusing TargetAttributes = UnityEditor.BuildTargetDiscovery.TargetAttributes;\n\nnamespace UnityEditor.Modules\n{\n    //everything happening here in this default extension used to happen in TextureImporterInspector.\n    //now, platforms that want to have their own texture import settings can subclass this class,\n    //and put the platform-specific stuff (either new, or down below) into the new subclass.\n    internal class DefaultTextureImportSettingsExtension : ITextureImportSettingsExtension\n    {\n        static readonly string[] kMaxTextureSizeStrings = { \"32\", \"64\", \"128\", \"256\", \"512\", \"1024\", \"2048\", \"4096\", \"8192\", \"16384\" };\n        static readonly int[] kMaxTextureSizeValues = { 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384 };\n        static readonly GUIContent maxSize = EditorGUIUtility.TrTextContent(\"Max Size\", \"Textures larger than this will be scaled down.\");\n        static readonly string kMaxSizeOverrideString = L10n.Tr(\"Max texture size is overriden to {0} in Build Settings window.\");\n\n        static readonly string[] kResizeAlgorithmStrings = { \"Mitchell\", \"Bilinear\" };\n        static readonly int[] kResizeAlgorithmValues = { (int)TextureResizeAlgorithm.Mitchell, (int)TextureResizeAlgorithm.Bilinear };\n        static readonly GUIContent kResizeAlgorithm = EditorGUIUtility.TrTextContent(\"Resize Algorithm\", \"Select algorithm to apply for textures when scaled down.\");\n        static readonly GUIContent kTextureFormat = EditorGUIUtility.TrTextContent(\"Format\");\n        static readonly GUIContent kTextureCompression = EditorGUIUtility.TrTextContent(\"Compression\", \"How will this texture be compressed?\");\n        static readonly GUIContent kUseAlphaSplitLabel = EditorGUIUtility.TrTextContent(\"Split Alpha Channel\", \"Alpha for this texture will be preserved by splitting the alpha channel to another texture, and both resulting textures will be compressed using ETC1.\");\n        static readonly GUIContent kCrunchedCompression = EditorGUIUtility.TrTextContent(\"Use Crunch Compression\", \"Texture is crunch-compressed to save space on disk when applicable.\");\n        static readonly GUIContent kCompressionQuality = EditorGUIUtility.TrTextContent(\"Compressor Quality\");\n        static readonly GUIContent kCompressionQualitySlider = EditorGUIUtility.TrTextContent(\"Compressor Quality\", \"Use the slider to adjust compression quality from 0 (Fastest) to 100 (Best)\");\n        static readonly GUIContent[] kMobileCompressionQualityOptions =\n        {\n            EditorGUIUtility.TrTextContent(\"Fast\"),\n            EditorGUIUtility.TrTextContent(\"Normal\"),\n            EditorGUIUtility.TrTextContent(\"Best\")\n        };\n\n        static readonly GUIContent[] kTextureCompressionOptions =\n        {\n            EditorGUIUtility.TrTextContent(\"None\", \"Texture is not compressed.\"),\n            EditorGUIUtility.TrTextContent(\"Low Quality\", \"Texture compressed with low quality but high performance, high compression format.\"),\n            EditorGUIUtility.TrTextContent(\"Normal Quality\", \"Texture is compressed with a standard format.\"),\n            EditorGUIUtility.TrTextContent(\"High Quality\", \"Texture compressed with a high quality format.\"),\n        };\n        static readonly int[] kTextureCompressionValues =\n        {\n            (int)TextureImporterCompression.Uncompressed,\n            (int)TextureImporterCompression.CompressedLQ,\n            (int)TextureImporterCompression.Compressed,\n            (int)TextureImporterCompression.CompressedHQ\n        };\n\n        public virtual void ShowImportSettings(BaseTextureImportPlatformSettings editor)\n        {\n            // Max texture size\n            Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup);\n            GUIContent label = maxSize;\n            if (editor.model.maxTextureSizeProperty != null)\n            {\n                label = EditorGUI.BeginProperty(controlRect, label, editor.model.maxTextureSizeProperty);\n            }\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = editor.model.maxTextureSizeIsDifferent;\n            int maxTextureSize = EditorGUI.IntPopup(controlRect, label, editor.model.platformTextureSettings.maxTextureSize, GUIContent.Temp(kMaxTextureSizeStrings), kMaxTextureSizeValues);\n            if (EditorGUI.EndChangeCheck())\n            {\n                editor.model.SetMaxTextureSizeForAll(maxTextureSize);\n            }\n            if (editor.model.maxTextureSizeProperty != null)\n            {\n                EditorGUI.EndProperty();\n            }\n\n            // Show a note if max size is overriden globally by the user\n            var userMaxSizeOverride = EditorUserBuildSettings.overrideMaxTextureSize;\n            if (userMaxSizeOverride > 0 && userMaxSizeOverride < maxTextureSize)\n                EditorGUILayout.HelpBox(string.Format(kMaxSizeOverrideString, userMaxSizeOverride), MessageType.Info);\n\n            // Resize Algorithm\n            controlRect = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup);\n            label = kResizeAlgorithm;\n            if (editor.model.resizeAlgorithmProperty != null)\n            {\n                label = EditorGUI.BeginProperty(controlRect, label, editor.model.resizeAlgorithmProperty);\n            }\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = editor.model.resizeAlgorithmIsDifferent;\n            int resizeAlgorithmVal = EditorGUI.IntPopup(controlRect, label, (int)editor.model.platformTextureSettings.resizeAlgorithm, GUIContent.Temp(kResizeAlgorithmStrings), kResizeAlgorithmValues);\n            if (EditorGUI.EndChangeCheck())\n            {\n                editor.model.SetResizeAlgorithmForAll((TextureResizeAlgorithm)resizeAlgorithmVal);\n            }\n            if (editor.model.resizeAlgorithmProperty != null)\n            {\n                EditorGUI.EndProperty();\n            }\n\n            // Texture format\n            int[] formatValuesForAll = {};\n            string[] formatStringsForAll = {};\n            bool formatOptionsAreDifferent = false;\n\n            int formatForAll = 0;\n            var textureShape = TextureImporterShape.Texture2D;\n\n            // TODO : This should not be calculated every refresh and be kept in a cache somewhere instead...\n            for (int i = 0; i < editor.GetTargetCount(); i++)\n            {\n                TextureImporterSettings settings = editor.GetImporterSettings(i);\n                TextureImporterType textureTypeForThis = editor.textureTypeHasMultipleDifferentValues ? settings.textureType : editor.textureType;\n                int format = (int)editor.model.platformTextureSettings.format;\n\n                int[] formatValues = null;\n                string[] formatStrings = null;\n\n                if (!editor.model.isDefault && !editor.model.platformTextureSettings.overridden)\n                {\n                    // If not overriden, show what the auto format is going to be\n                    // don't care about alpha in normal maps. If editor.assetTarget is null\n                    // then we are dealing with texture preset and we show all options.\n                    var showSettingsForPreset = editor.ShowPresetSettings();\n                    var sourceHasAlpha = showSettingsForPreset || (editor.DoesSourceTextureHaveAlpha(i) &&\n                        textureTypeForThis != TextureImporterType.NormalMap);\n\n                    format = (int)TextureImporter.DefaultFormatFromTextureParameters(settings,\n                        editor.model.platformTextureSettings,\n                        !showSettingsForPreset && sourceHasAlpha,\n                        !showSettingsForPreset && editor.IsSourceTextureHDR(i),\n                        editor.model.buildTarget);\n\n                    formatValues = new int[] { format };\n                    formatStrings = new string[] { GraphicsFormatUtility.GetFormatString((TextureFormat)format) };\n                }\n                else\n                {\n                    // otherwise show valid formats\n                    editor.model.GetValidTextureFormatsAndStrings(textureTypeForThis, out formatValues, out formatStrings);\n                }\n\n                // Check if values are the same\n                if (i == 0)\n                {\n                    formatValuesForAll = formatValues;\n                    formatStringsForAll = formatStrings;\n                    formatForAll = format;\n                    textureShape = settings.textureShape;\n                }\n                else\n                {\n                    if (!formatValues.SequenceEqual(formatValuesForAll) || !formatStrings.SequenceEqual(formatStringsForAll))\n                    {\n                        formatOptionsAreDifferent = true;\n                        break;\n                    }\n                }\n            }\n\n            using (new EditorGUI.DisabledScope(formatOptionsAreDifferent || formatStringsForAll.Length == 1))\n            {\n                controlRect = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup);\n                label = kTextureFormat;\n                if (editor.model.textureFormatProperty != null)\n                {\n                    label = EditorGUI.BeginProperty(controlRect, label, editor.model.textureFormatProperty);\n                }\n                EditorGUI.BeginChangeCheck();\n                bool mixedValues = formatOptionsAreDifferent || editor.model.textureFormatIsDifferent;\n                EditorGUI.showMixedValue = mixedValues;\n                var selectionResult = EditorGUI.IntPopup(controlRect, label, formatForAll, GUIContent.Temp(formatStringsForAll), formatValuesForAll);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    editor.model.SetTextureFormatForAll((TextureImporterFormat)selectionResult);\n                    formatForAll = selectionResult;\n                }\n                if (editor.model.textureFormatProperty != null)\n                {\n                    EditorGUI.EndProperty();\n                }\n\n                if (!mixedValues && !Array.Exists(formatValuesForAll, i => i == formatForAll))\n                {\n                    EditorGUILayout.HelpBox(string.Format(L10n.Tr(\"The selected format value {0} is not compatible on this platform for the selected texture type, please change it to a valid one from the dropdown.\"), (TextureImporterFormat)formatForAll), MessageType.Error);\n                }\n            }\n\n            // Texture Compression\n            if (editor.model.isDefault && editor.model.platformTextureSettings.format == TextureImporterFormat.Automatic)\n            {\n                controlRect = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup);\n                label = kTextureCompression;\n                if (editor.model.textureCompressionProperty != null)\n                {\n                    label = EditorGUI.BeginProperty(controlRect, label, editor.model.textureCompressionProperty);\n                }\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = editor.model.overriddenIsDifferent ||\n                    editor.model.textureCompressionIsDifferent;\n                TextureImporterCompression textureCompression =\n                    (TextureImporterCompression)EditorGUI.IntPopup(controlRect,\n                        label, (int)editor.model.platformTextureSettings.textureCompression, kTextureCompressionOptions,\n                        kTextureCompressionValues);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    editor.model.SetTextureCompressionForAll(textureCompression);\n                }\n                if (editor.model.textureCompressionProperty != null)\n                {\n                    EditorGUI.EndProperty();\n                }\n            }\n\n            // Use Crunch Compression\n            if (editor.model.isDefault &&\n                (TextureImporterFormat)formatForAll == TextureImporterFormat.Automatic &&\n                editor.model.platformTextureSettings.textureCompression != TextureImporterCompression.Uncompressed &&\n                (textureShape == TextureImporterShape.Texture2D || textureShape == TextureImporterShape.TextureCube)) // 2DArray & 3D don't support Crunch\n            {\n                controlRect = EditorGUILayout.GetToggleRect(true);\n                label = kCrunchedCompression;\n                if (editor.model.crunchedCompressionProperty != null)\n                {\n                    label = EditorGUI.BeginProperty(controlRect, label, editor.model.crunchedCompressionProperty);\n                }\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = editor.model.overriddenIsDifferent ||\n                    editor.model.crunchedCompressionIsDifferent;\n                bool crunchedCompression = EditorGUI.Toggle(\n                    controlRect, label, editor.model.platformTextureSettings.crunchedCompression);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    editor.model.SetCrunchedCompressionForAll(crunchedCompression);\n                }\n                if (editor.model.crunchedCompressionProperty != null)\n                {\n                    EditorGUI.EndProperty();\n                }\n            }\n\n            // compression quality\n            bool isCrunchedFormat = false\n                || GraphicsFormatUtility.IsCrunchFormat((TextureFormat)formatForAll)\n            ;\n\n            if (\n                (editor.model.isDefault &&\n                 (TextureImporterFormat)formatForAll == TextureImporterFormat.Automatic &&\n                 editor.model.platformTextureSettings.textureCompression != TextureImporterCompression.Uncompressed &&\n                 editor.model.platformTextureSettings.crunchedCompression) ||\n                (editor.model.isDefault && editor.model.platformTextureSettings.crunchedCompression && isCrunchedFormat) ||\n                (!editor.model.isDefault && isCrunchedFormat) ||\n                (!editor.model.textureFormatIsDifferent && ArrayUtility.Contains<TextureImporterFormat>(\n                    TextureImporterInspector.kFormatsWithCompressionSettings,\n                    (TextureImporterFormat)formatForAll)))\n            {\n                EditCompressionQuality(editor, isCrunchedFormat, (TextureImporterFormat)formatForAll);\n            }\n\n            // show the ETC1 split option only for sprites on platforms supporting ETC and only when there is an alpha channel\n            bool isETCPlatform = TextureImporter.IsETC1SupportedByBuildTarget(BuildPipeline.GetBuildTargetByName(editor.model.platformTextureSettings.name));\n            bool isDealingWithSprite = (editor.spriteImportMode != SpriteImportMode.None);\n            bool isETCFormatSelected = TextureImporter.IsTextureFormatETC1Compression((TextureFormat)formatForAll);\n\n            if (isETCPlatform && isDealingWithSprite && isETCFormatSelected)\n            {\n                controlRect = EditorGUILayout.GetToggleRect(true);\n                label = kUseAlphaSplitLabel;\n                if (editor.model.alphaSplitProperty != null)\n                {\n                    label = EditorGUI.BeginProperty(controlRect, label, editor.model.alphaSplitProperty);\n                }\n                EditorGUI.BeginChangeCheck();\n                EditorGUI.showMixedValue = editor.model.overriddenIsDifferent || editor.model.allowsAlphaSplitIsDifferent;\n                bool allowsAlphaSplit = EditorGUI.Toggle(controlRect, label, editor.model.platformTextureSettings.allowsAlphaSplitting);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    editor.model.SetAllowsAlphaSplitForAll(allowsAlphaSplit);\n                }\n                if (editor.model.alphaSplitProperty != null)\n                {\n                    EditorGUI.EndProperty();\n                }\n            }\n        }\n\n        private void EditCompressionQuality(BaseTextureImportPlatformSettings editor, bool isCrunchedFormat, TextureImporterFormat textureFormat)\n        {\n            bool showAsEnum = !isCrunchedFormat && (BuildTargetDiscovery.PlatformHasFlag(editor.model.buildTarget, TargetAttributes.HasIntegratedGPU) || (textureFormat == TextureImporterFormat.BC6H) || (textureFormat == TextureImporterFormat.BC7));\n\n            Rect controlRect = showAsEnum ? EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup) : EditorGUILayout.GetSliderRect(true);\n            GUIContent label = showAsEnum ? kCompressionQuality : kCompressionQualitySlider;\n            if (editor.model.compressionQualityProperty != null)\n            {\n                label = EditorGUI.BeginProperty(controlRect, label, editor.model.compressionQualityProperty);\n            }\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.showMixedValue = editor.model.overriddenIsDifferent ||\n                editor.model.compressionQualityIsDifferent;\n\n            // Prior to exposing compression quality for BC6H/BC7 formats they were always compressed at maximum quality even though the setting was\n            // defaulted to 'Normal'.  Now BC6H/BC7 quality is exposed to the user as Fast/Normal/Best 'Normal' maps to one setting down from maximum in the\n            // ISPC compressor but to maintain the behaviour of existing projects we need to force their quality up to 'Best'.  The 'forceMaximumCompressionQuality_BC6H_BC7'\n            // flag is set when loading existing texture platform settings to do this and cleared when the compression quality level is manually set (by UI or API)\n            bool forceBestQuality = editor.model.forceMaximumCompressionQuality_BC6H_BC7 && ((textureFormat == TextureImporterFormat.BC6H) || (textureFormat == TextureImporterFormat.BC7));\n            int compression = forceBestQuality ? (int)TextureCompressionQuality.Best : editor.model.platformTextureSettings.compressionQuality;\n\n            if (showAsEnum)\n            {\n                int compressionMode = 1;\n                if (compression == (int)TextureCompressionQuality.Fast)\n                    compressionMode = 0;\n                else if (compression == (int)TextureCompressionQuality.Best)\n                    compressionMode = 2;\n\n                int ret = EditorGUI.Popup(controlRect, label, compressionMode, kMobileCompressionQualityOptions);\n\n                switch (ret)\n                {\n                    case 0:\n                        compression = (int)TextureCompressionQuality.Fast;\n                        break;\n                    case 1:\n                        compression = (int)TextureCompressionQuality.Normal;\n                        break;\n                    case 2:\n                        compression = (int)TextureCompressionQuality.Best;\n                        break;\n\n                    default:\n                        compression = (int)TextureCompressionQuality.Normal;\n                        break;\n                }\n            }\n            else\n                compression = EditorGUI.IntSlider(controlRect, label, compression, 0, 100);\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                editor.model.SetCompressionQualityForAll(compression);\n                //SyncPlatformSettings ();\n            }\n            if (editor.model.compressionQualityProperty != null)\n            {\n                EditorGUI.EndProperty();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/DerivedBuildTargetExtensionsProvider.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace UnityEditor.Modules\n{\n    using DiscoveredTargetInfo = BuildTargetDiscovery.DiscoveredTargetInfo;\n\n    internal class DerivedBuildTargetExtensionsProvider\n    {\n        Dictionary<GUID, IDerivedBuildTargetExtensions> m_DerivedBuildTargetExtensions = new();\n        DiscoveredTargetInfo m_DiscoveredTargetInfo;\n        BuildTarget m_BuildTarget;\n\n        internal DerivedBuildTargetExtensionsProvider(BuildTarget buildTarget)\n        {\n            m_BuildTarget = buildTarget;\n            LoadDiscoveredTargetInfo();\n        }\n\n        internal IBuildTarget GetIBuildTarget(IBuildTarget baseBuildTarget)\n        {\n            var activePlatformGuid = EditorUserBuildSettings.activePlatformGuid;\n            if (m_DerivedBuildTargetExtensions.TryGetValue(activePlatformGuid, out var derivedBuildTargetExtensions))\n            {\n                return derivedBuildTargetExtensions.DerivedBuildTarget;\n            }\n            return baseBuildTarget;\n        }\n\n        internal ICompilationExtension CreateCompilationExtension(ICompilationExtension baseCompilationExtension)\n        {\n            var activePlatformGuid = EditorUserBuildSettings.activePlatformGuid;\n            if (m_DerivedBuildTargetExtensions.TryGetValue(activePlatformGuid, out var derivedBuildTargetExtensions))\n            {\n                return derivedBuildTargetExtensions.CompilationExtension ?? baseCompilationExtension;\n            }\n            return baseCompilationExtension;\n        }\n\n        internal IBuildPostprocessor CreateBuildPostprocessor(IBuildPostprocessor baseBuildPostprocessor)\n        {\n            var activePlatformGuid = EditorUserBuildSettings.activePlatformGuid;\n            if (m_DerivedBuildTargetExtensions.TryGetValue(activePlatformGuid, out var derivedBuildTargetExtensions))\n            {\n                return derivedBuildTargetExtensions.BuildPostprocessor ?? baseBuildPostprocessor;\n            }\n            return baseBuildPostprocessor;\n        }\n\n        internal ISettingEditorExtension CreateSettingsEditorExtension(GUID buildTarget, ISettingEditorExtension baseSettingEditorExtension)\n        {\n            if (m_DerivedBuildTargetExtensions.TryGetValue(buildTarget, out var derivedBuildTargetExtensions))\n            {\n                return derivedBuildTargetExtensions.CreateSettingEditorExtension() ?? baseSettingEditorExtension;\n            }\n            return baseSettingEditorExtension;\n        }\n\n        internal IBuildProfileExtension CreateBuildProfileExtension(GUID buildTarget, IBuildProfileExtension baseBuildProfileExtension)\n        {\n            if (m_DerivedBuildTargetExtensions.TryGetValue(buildTarget, out var derivedBuildTargetExtensions))\n            {\n                return derivedBuildTargetExtensions.CreateBuildProfileExtension() ?? baseBuildProfileExtension;\n            }\n            return baseBuildProfileExtension;\n        }\n\n        internal IEnumerable<IDerivedBuildTarget> GetDerivedBuildTargets()\n        {\n            List<IDerivedBuildTarget> derivedBuildTargets = new();\n            foreach (var extension in m_DerivedBuildTargetExtensions.Values)\n                derivedBuildTargets.Add(extension.DerivedBuildTarget);\n            return derivedBuildTargets;\n        }\n\n        internal bool TryGetDiscoveredTargetInfo(GUID buildTarget, out DiscoveredTargetInfo discoveredTargetInfo)\n        {\n            if (m_DerivedBuildTargetExtensions.TryGetValue(buildTarget, out var derivedBuildTargetExtensions))\n            {\n                discoveredTargetInfo = derivedBuildTargetExtensions.DerivedBuildTarget.GetDerivedBuildTargetInfo(m_DiscoveredTargetInfo);\n                return true;\n            }\n\n            discoveredTargetInfo = default;\n            return false;\n        }\n\n        internal void LoadDerivedPlatformPlugin<T>() where T : IDerivedBuildTargetExtensions, new()\n        {\n            var derivedBuildTargetExtensions = new T();\n            var guid = derivedBuildTargetExtensions.DerivedBuildTarget.Guid;\n            var guidStr = guid.ToString();\n            var platformEnabled = EditorPrefs.HasKey(guidStr) && (EditorPrefs.GetInt(guidStr) == 1);\n            if (platformEnabled || ForceEnablePlatform())\n            {\n                m_DerivedBuildTargetExtensions.Add(guid, derivedBuildTargetExtensions);\n            }\n        }\n        internal void LoadAndEnableDerivedPlatformPlugin<T>() where T : IDerivedBuildTargetExtensions, new()\n        {\n            var derivedBuildTargetExtensions = new T();\n            var guid = derivedBuildTargetExtensions.DerivedBuildTarget.Guid;\n            if ((!EditorPrefs.HasKey(guid.ToString())) || (EditorPrefs.GetInt(guid.ToString()) != 1))\n            {\n                EditorPrefs.SetInt(guid.ToString(), 1);\n            }\n            LoadDerivedPlatformPlugin<T>();\n        }\n\n        bool ForceEnablePlatform()\n        {\n            foreach (var arg in Environment.GetCommandLineArgs())\n            {\n                if (arg == \"-enableAllDerivedPlatforms\")\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        void LoadDiscoveredTargetInfo()\n        {\n            var list = BuildTargetDiscovery.GetBuildTargetInfoList();\n            foreach (var info in list)\n            {\n                if (info.buildTargetPlatformVal == m_BuildTarget)\n                {\n                    m_DiscoveredTargetInfo = info;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/IDerivedBuildTargetExtensions.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor.Modules\n{\n    internal interface IDerivedBuildTargetExtensions\n    {\n        ICompilationExtension CompilationExtension { get; }\n        IBuildPostprocessor BuildPostprocessor { get; }\n        IDerivedBuildTarget DerivedBuildTarget { get; }\n        IBuildProfileExtension CreateBuildProfileExtension();\n        ISettingEditorExtension CreateSettingEditorExtension();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/IPostStrippingModuleAdder.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\nnamespace UnityEditor.Modules;\n\n[VisibleToOtherModules]\ninternal interface IPostStrippingModuleAdder\n{\n    /// <summary>\n    /// Add a module to the list of modules to include in the build.\n    /// </summary>\n    /// <remarks>\n    /// After UnityLinker has run, only limited modules are allowed to be added to the build:\n    /// * The module must be purely native.\n    /// * The module's dependencies must also not be stripped.\n    ///\n    /// It is still useful to add modules at this point in the build process because it allows us\n    /// to conditionally add them depending on whether other modules were included - for example,\n    /// only add a pure-native 'backend' module if the corresponding 'frontend' module is included\n    /// (due to being used by user code / in user scenes / etc).\n    /// </remarks>\n    /// <param name=\"moduleName\">The name of the module to not strip from the build.</param>\n    public void AddModule(string moduleName);\n\n    /// <summary>\n    /// Check whether a given module is already on the list of modules that should not be stripped.\n    /// </summary>\n    /// <param name=\"moduleName\">The name of the module to check for.</param>\n    /// <returns>True if the module is on the list of modules to not strip; false otherwise.</returns>\n    public bool IsModuleIncluded(string moduleName);\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/IPreStrippingModuleAdder.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor.Modules;\n\n[VisibleToOtherModules]\ninternal interface IPreStrippingModuleAdder\n{\n    /// <summary>\n    /// Add a module to the list of modules to include in the build.\n    /// </summary>\n    /// <remarks>\n    /// This happens right after the force includes and excludes are calculated,\n    /// and allows a module to add itself to the force includes list.  Due to where this\n    /// happens in the build pipeline, this will also cause the dependencies of\n    /// that module to be force included.\n    /// </remarks>\n    /// <param name=\"moduleName\">The name of the module to force add to the build.</param>\n    public void AddModule(string moduleName);\n\n    /// <summary>\n    /// Check whether a given module is already on the list of modules that should be added.\n    /// </summary>\n    /// <param name=\"moduleName\">The name of the module to check for.</param>\n    /// <returns>True if the module is on the list of modules to add; false otherwise.</returns>\n    public bool IsModuleIncluded(string moduleName);\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/ModuleManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Collections.Generic;\nusing System.Text.RegularExpressions;\nusing Unity.Profiling;\nusing UnityEditor.Hardware;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEditor.DeploymentTargets;\nusing RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute;\nusing UnityEditor.Build;\n\nnamespace UnityEditor.Modules\n{\n    internal static class ModuleManager\n    {\n        private static readonly ProfilerMarkerWithStringData s_InitializePlatformSupportModule = ProfilerMarkerWithStringData.Create(\"InitializePlatformSupportModule\", \"Name\");\n\n        [NonSerialized]\n        static Dictionary<string, IPlatformSupportModule> s_PlatformModules;\n\n        [NonSerialized]\n        static Dictionary<GUID, IPlatformSupportModule> s_PlatformModulesByGuid;\n\n        [NonSerialized]\n        static bool s_PlatformModulesInitialized;\n\n        [NonSerialized]\n        static IPlatformSupportModule s_ActivePlatformModule;\n\n        internal static Dictionary<string, IPlatformSupportModule> platformSupportModules\n        {\n            get\n            {\n                if (s_PlatformModules == null)\n                    RegisterPlatformSupportModules();\n                return s_PlatformModules;\n            }\n        }\n\n        internal static Dictionary<GUID, IPlatformSupportModule> platformSupportModulesByGuid\n        {\n            get\n            {\n                if (s_PlatformModulesByGuid == null)\n                    RegisterPlatformSupportModules();\n                return s_PlatformModulesByGuid;\n            }\n        }\n\n        class BuildTargetChangedHandler : Build.IActiveBuildTargetChanged\n        {\n            public int callbackOrder { get { return 0; } }\n\n            public void OnActiveBuildTargetChanged(BuildTarget oldTarget, BuildTarget newTarget)\n            {\n                ModuleManager.OnActiveBuildTargetChanged(oldTarget, newTarget);\n            }\n        }\n\n        static void OnActiveBuildTargetChanged(BuildTarget oldTarget, BuildTarget newTarget)\n        {\n            string target = GetTargetStringFromBuildTarget(newTarget);\n            ChangeActivePlatformModuleTo(target);\n        }\n\n        static void DeactivateActivePlatformModule()\n        {\n            if (s_ActivePlatformModule != null)\n            {\n                s_ActivePlatformModule.OnDeactivate();\n                s_ActivePlatformModule = null;\n            }\n        }\n\n        static void ChangeActivePlatformModuleTo(string target)\n        {\n            DeactivateActivePlatformModule();\n\n            IPlatformSupportModule selected;\n            if (platformSupportModules.TryGetValue(target, out selected))\n            {\n                s_ActivePlatformModule = selected;\n                s_ActivePlatformModule.OnActivate();\n            }\n        }\n\n        // entry point from native\n        [RequiredByNativeCode]\n        internal static bool IsPlatformSupportLoaded(string target)\n        {\n            return platformSupportModules.ContainsKey(target);\n        }\n\n        internal static bool IsPlatformSupportLoadedByGuid(GUID platformId)\n        {\n            return platformSupportModulesByGuid.ContainsKey(platformId);\n        }\n\n        // Native binding doesn't support overloaded functions\n        internal static bool IsPlatformSupportLoadedByBuildTarget(BuildTarget target)\n        {\n            return IsPlatformSupportLoaded(GetTargetStringFromBuildTarget(target));\n        }\n\n        // entry point from native\n        [RequiredByNativeCode]\n        internal static void RegisterAdditionalUnityExtensions()\n        {\n            foreach (var module in platformSupportModules)\n            {\n                module.Value.RegisterAdditionalUnityExtensions();\n            }\n        }\n\n        // entry point from native\n        // Note that in order for this function to work properly, it must be called between two domain\n        // reloads. The first domain reload is needed because RegisterPlatformSupportModules()\n        // investigates the currently loaded set of assemblies. The second reload is needed so that\n        // assemblies returned by module.AssemblyReferencesForUserScripts are actually loaded in the\n        // current domain and user code may use it.\n        [RequiredByNativeCode]\n        internal static void InitializePlatformSupportModules()\n        {\n            if (s_PlatformModulesInitialized)\n            {\n                Console.WriteLine(\"Platform modules already initialized, skipping\");\n                return;\n            }\n\n            foreach (var module in platformSupportModules.Values)\n            {\n                using (s_InitializePlatformSupportModule.Auto(module.TargetName))\n                {\n                    foreach (var library in module.NativeLibraries)\n                        EditorUtility.LoadPlatformSupportNativeLibrary(library);\n                    foreach (var fullPath in module.AssemblyReferencesForUserScripts)\n                        InternalEditorUtility.RegisterPlatformModuleAssembly(Path.GetFileName(fullPath), fullPath);\n\n                    EditorUtility.LoadPlatformSupportModuleNativeDllInternal(module.TargetName);\n\n                    try\n                    {\n                        module.OnLoad();\n                    }\n                    catch (Exception e)\n                    {\n                        Debug.LogException(e);\n                    }\n                }\n            }\n\n            // Setup active build target and call OnActivate() for current platform module\n            OnActiveBuildTargetChanged(BuildTarget.NoTarget, EditorUserBuildSettings.activeBuildTarget);\n\n            s_PlatformModulesInitialized = true;\n        }\n\n        // entry point from native\n        [RequiredByNativeCode]\n        internal static void ShutdownPlatformSupportModules()\n        {\n            DeactivateActivePlatformModule();\n\n            if (s_PlatformModules != null)\n            {\n                foreach (var module in s_PlatformModules.Values)\n                    module.OnUnload();\n            }\n        }\n\n        // entry point from native\n        [RequiredByNativeCode(true)]\n        internal static void ShutdownModuleManager()\n        {\n            s_PlatformModules = null;\n        }\n\n        private static void RegisterPlatformSupportModules()\n        {\n            var allTypesWithInterface = TypeCache.GetTypesDerivedFrom<IPlatformSupportModule>();\n            s_PlatformModules = new Dictionary<string, IPlatformSupportModule>(allTypesWithInterface.Count);\n            s_PlatformModulesByGuid = new Dictionary<GUID, IPlatformSupportModule>(allTypesWithInterface.Count);\n\n            foreach (var type in allTypesWithInterface)\n            {\n                if (type.IsAbstract)\n                {\n                    continue;\n                }\n\n                try\n                {\n                    var platformSupportModule = Activator.CreateInstance(type) as IPlatformSupportModule;\n                    s_PlatformModules.Add(platformSupportModule.TargetName, platformSupportModule);\n                    if (platformSupportModule is IDerivedBuildTargetProvider derivedBuildTargetProvider)\n                    {\n                        s_PlatformModulesByGuid.Add(derivedBuildTargetProvider.GetBasePlatformGuid(), platformSupportModule);\n                        var derivedBuildTargets = derivedBuildTargetProvider.GetDerivedBuildTargets();\n                        foreach (var target in derivedBuildTargets)\n                        {\n                            s_PlatformModulesByGuid.Add(target.Guid, platformSupportModule);\n                        }\n                    }\n                    else\n                    {\n                        s_PlatformModulesByGuid.Add(platformSupportModule.PlatformBuildTarget.Guid, platformSupportModule);\n                    }\n                    var (buildTarget, _) = BuildTargetDiscovery.GetBuildTargetAndSubtargetFromGUID(platformSupportModule.PlatformBuildTarget.Guid);\n                    if (BuildTargetDiscovery.IsStandalonePlatform(buildTarget))\n                    {\n                        if (BuildTargetDiscovery.TryGetServerGUIDFromBuildTarget(NamedBuildTarget.Server, buildTarget, out var serverGuid))\n                        {\n                            if (BuildTargetDiscovery.BuildPlatformIsInstalled(serverGuid))\n                                s_PlatformModulesByGuid.Add(serverGuid, platformSupportModule);\n                        }\n                    }\n                }\n                catch (Exception ex)\n                {\n                    Debug.LogError($\"Could not add platformSupportModule {type.FullName}, try rebuilding the module: {ex.Message}\");\n                }\n            }\n        }\n\n        internal static List<string> GetJamTargets()\n        {\n            List<string> jamTargets = new List<string>();\n\n            foreach (var module in platformSupportModules.Values)\n            {\n                jamTargets.Add(module.JamTarget);\n            }\n\n            return jamTargets;\n        }\n\n        internal static IPlatformSupportModule FindPlatformSupportModule(string moduleName)\n        {\n            if (platformSupportModules.TryGetValue(moduleName, out var module))\n                return module;\n\n            return null;\n        }\n\n        internal static IPlatformSupportModule FindPlatformSupportModule(GUID platformGuid)\n        {\n            if (platformSupportModulesByGuid.TryGetValue(platformGuid, out var module))\n                return module;\n\n            return null;\n        }\n\n        internal static IDevice GetDevice(string deviceId)\n        {\n            DevDevice device;\n            if (DevDeviceList.FindDevice(deviceId, out device))\n            {\n                IPlatformSupportModule module = FindPlatformSupportModule(device.module);\n                if (module != null)\n                    return module.CreateDevice(deviceId);\n                else\n                    throw new ApplicationException(\"Couldn't find module for target: \" + device.module);\n            }\n\n            throw new ApplicationException(\"Couldn't create device API for device: \" + deviceId);\n        }\n\n        internal static IBuildTarget GetIBuildTarget(BuildTarget target)\n        {\n            var targetModuleName = BuildTargetDiscovery.GetModuleNameForBuildTarget(target);\n            if (platformSupportModules.TryGetValue(targetModuleName, out var module))\n            {\n                return module.PlatformBuildTarget;\n            }\n\n            return null;\n        }\n\n        internal static IBuildTarget GetIBuildTarget(GUID platformGuid)\n        {\n            if (platformSupportModulesByGuid.TryGetValue(platformGuid, out var module))\n            {\n                if (module.PlatformBuildTarget.Guid == platformGuid)\n                {\n                    return module.PlatformBuildTarget;\n                }\n                else\n                {\n                    if (module is IDerivedBuildTargetProvider derivedBuildTargetProvider)\n                    {\n                        var derivedBuildTargets = derivedBuildTargetProvider.GetDerivedBuildTargets();\n                        foreach (var target in derivedBuildTargets)\n                        {\n                            if (target.Guid == platformGuid)\n                            {\n                                return target;\n                            }\n                        }\n                    }\n                }\n            }\n\n            return null;\n        }\n\n        internal static IBuildPostprocessor GetBuildPostProcessor(string target)\n        {\n            if (target == null)\n                return null;\n\n            IPlatformSupportModule module;\n            if (platformSupportModules.TryGetValue(target, out module))\n            {\n                return platformSupportModules[target].CreateBuildPostprocessor();\n            }\n\n            return null;\n        }\n\n        internal static IBuildPostprocessor GetBuildPostProcessor(BuildTarget target)\n        {\n            return GetBuildPostProcessor(GetTargetStringFrom(target));\n        }\n\n        internal static IDeploymentTargetsExtension GetDeploymentTargetsExtension(string target)\n        {\n            if (target == null)\n                return null;\n\n            IPlatformSupportModule module;\n            if (platformSupportModules.TryGetValue(target, out module))\n            {\n                return platformSupportModules[target].CreateDeploymentTargetsExtension();\n            }\n\n            return null;\n        }\n\n        internal static IDeploymentTargetsExtension GetDeploymentTargetsExtension(BuildTarget target)\n        {\n            return GetDeploymentTargetsExtension(GetTargetStringFrom(target));\n        }\n\n        [Obsolete(\"ModuleManager.GetDeploymentTargetsExtension(BuildTargetGroup targetGroup, BuildTarget target) has been deprecated. Use ModuleManager.GetDeploymentTargetsExtension(BuildTarget target) instead.\")]\n        internal static IDeploymentTargetsExtension GetDeploymentTargetsExtension(BuildTargetGroup targetGroup, BuildTarget target)\n        {\n            return GetDeploymentTargetsExtension(target);\n        }\n\n        internal static ISettingEditorExtension GetEditorSettingsExtension(string target)\n        {\n            if (string.IsNullOrEmpty(target))\n                return null;\n\n            IPlatformSupportModule module;\n            if (platformSupportModules.TryGetValue(target, out module))\n            {\n                return platformSupportModules[target].CreateSettingsEditorExtension();\n            }\n\n            return null;\n        }\n\n        internal static ISettingEditorExtension GetEditorSettingsExtension(GUID target)\n        {\n            if (platformSupportModulesByGuid.TryGetValue(target, out var module))\n            {\n                if (module is IDerivedBuildTargetProvider derivedBuildTargetProvider)\n                {\n                    return derivedBuildTargetProvider.CreateSettingsEditorExtension(target);\n                }\n                \n                return module.CreateSettingsEditorExtension();\n            }\n\n            return null;\n        }\n\n        internal static IAdaptiveVsyncSetting GetAdaptiveSettingEditorExtension(string target)\n        {\n            if (string.IsNullOrEmpty(target))\n                return null;\n\n            IPlatformSupportModule module;\n            if (platformSupportModules.TryGetValue(target, out module))\n            {\n                return platformSupportModules[target].CreateAdaptiveSettingEditorExtension();\n            }\n\n            return null;\n        }\n\n        internal static ITextureImportSettingsExtension GetTextureImportSettingsExtension(BuildTarget target)\n        {\n            return GetTextureImportSettingsExtension(GetTargetStringFromBuildTarget(target));\n        }\n\n        internal static ITextureImportSettingsExtension GetTextureImportSettingsExtension(string targetName)\n        {\n            IPlatformSupportModule module;\n            if (platformSupportModules.TryGetValue(targetName, out module))\n            {\n                return platformSupportModules[targetName].CreateTextureImportSettingsExtension();\n            }\n\n            return new DefaultTextureImportSettingsExtension();\n        }\n\n        internal static List<IPreferenceWindowExtension> GetPreferenceWindowExtensions()\n        {\n            List<IPreferenceWindowExtension> prefWindExtensions = new List<IPreferenceWindowExtension>();\n\n            foreach (var module in platformSupportModules.Values)\n            {\n                IPreferenceWindowExtension prefWindowExtension = module.CreatePreferenceWindowExtension();\n\n                if (prefWindowExtension != null)\n                    prefWindExtensions.Add(prefWindowExtension);\n            }\n            return prefWindExtensions;\n        }\n\n        internal static IBuildWindowExtension GetBuildWindowExtension(string target)\n        {\n            if (string.IsNullOrEmpty(target))\n                return null;\n\n            IPlatformSupportModule module;\n            if (platformSupportModules.TryGetValue(target, out module))\n            {\n                return platformSupportModules[target].CreateBuildWindowExtension();\n            }\n\n            return null;\n        }\n\n        internal static ICompilationExtension GetCompilationExtension(string target)\n        {\n            IPlatformSupportModule module;\n            if (platformSupportModules.TryGetValue(target, out module))\n            {\n                return platformSupportModules[target].CreateCompilationExtension();\n            }\n\n            return new DefaultCompilationExtension();\n        }\n\n        private static IScriptingImplementations GetScriptingImplementations(string target)\n        {\n            if (string.IsNullOrEmpty(target))\n                return null;\n\n            IPlatformSupportModule module;\n            if (platformSupportModules.TryGetValue(target, out module))\n            {\n                return platformSupportModules[target].CreateScriptingImplementations();\n            }\n\n            return null;\n        }\n\n        internal static IScriptingImplementations GetScriptingImplementations(NamedBuildTarget namedBuildTarget)\n        {\n            // Standalone Windows, Linux and OS X share player settings between each other, so they share scripting implementations too\n            // However, since we can't pin BuildTargetGroup to any single platform support module, we have to explicitly check for this case\n            if (namedBuildTarget == NamedBuildTarget.Standalone)\n                return new DesktopStandalonePostProcessor.ScriptingImplementations();\n\n            return GetScriptingImplementations(GetTargetStringFromBuildTargetGroup(namedBuildTarget.ToBuildTargetGroup()));\n        }\n\n        internal static IPluginImporterExtension GetPluginImporterExtension(string target)\n        {\n            if (target == null)\n                return null;\n\n\n            IPlatformSupportModule module;\n            if (platformSupportModules.TryGetValue(target, out module))\n            {\n                try\n                {\n                    return platformSupportModules[target].CreatePluginImporterExtension();\n                }\n                // Handle exception since otherwise creating extension from other platforms will also stop\n                catch (Exception ex)\n                {\n                    Debug.LogError(ex);\n                    return null;\n                }\n            }\n\n            return null;\n        }\n\n        internal static IPluginImporterExtension GetPluginImporterExtension(BuildTarget target)\n        {\n            return GetPluginImporterExtension(GetTargetStringFromBuildTarget(target));\n        }\n\n        internal static IPluginImporterExtension GetPluginImporterExtension(BuildTargetGroup target)\n        {\n            return GetPluginImporterExtension(GetTargetStringFromBuildTargetGroup(target));\n        }\n\n        internal static IBuildProfileExtension GetBuildProfileExtension(GUID platformId)\n        {\n            if (platformSupportModulesByGuid.TryGetValue(platformId, out var module))\n            {\n                if (module is IDerivedBuildTargetProvider derivedBuildTargetProvider)\n                {\n                    return derivedBuildTargetProvider.CreateBuildProfileExtension(platformId);\n                }\n                else\n                {\n                    return module.CreateBuildProfileExtension();\n                }\n            }\n\n            return null;\n        }\n\n        internal static string GetTargetStringFromBuildTarget(BuildTarget target)\n        {\n            return BuildTargetDiscovery.GetModuleNameForBuildTarget(target);\n        }\n\n        internal static string GetTargetStringFromBuildTargetGroup(BuildTargetGroup target)\n        {\n            return BuildTargetDiscovery.GetModuleNameForBuildTargetGroup(target);\n        }\n\n        // This function returns module name depending on the combination of targetGroup x target\n        internal static string GetTargetStringFrom(BuildTarget target)\n        {\n            if (target == BuildTarget.NoTarget)\n                throw new ArgumentException(\"target must be valid\");\n\n            return GetTargetStringFromBuildTarget(target);\n        }\n\n        [Obsolete(\"ModuleManager.GetTargetStringFrom(BuildTargetGroup targetGroup, BuildTarget target) is deprecated, please use ModuleManager.GetTargetStringFrom(BuildTarget target)\")]\n        internal static string GetTargetStringFrom(BuildTargetGroup targetGroup, BuildTarget target)\n        {\n            return GetTargetStringFrom(target);\n        }\n\n        internal static bool IsPlatformSupported(BuildTarget target)\n        {\n            return GetTargetStringFromBuildTarget(target) != null;\n        }\n\n        internal static string GetExtensionVersion(string target)\n        {\n            if (string.IsNullOrEmpty(target))\n                return null;\n\n            IPlatformSupportModule module;\n            if (platformSupportModules.TryGetValue(target, out module))\n            {\n                return platformSupportModules[target].ExtensionVersion;\n            }\n\n            return null;\n        }\n\n        internal static bool ShouldShowMultiDisplayOption()\n        {\n            GUIContent[] platformDisplayNames = Modules.ModuleManager.GetDisplayNames(EditorUserBuildSettings.activeBuildTarget.ToString());\n\n            if (platformDisplayNames != null)\n                return true;\n\n            BuildTargetGroup curPlatform = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);\n            // In Editortests no platforms are installed and below would result in false, but we support.\n            if (curPlatform == BuildTargetGroup.Standalone)\n                return true;\n\n            if (BuildTargetDiscovery.TryGetProperties(EditorUserBuildSettings.activeBuildTarget, out IGraphicsPlatformProperties properties))\n                return properties.HasMultiDisplayOption;\n\n            return false;\n        }\n\n        internal static GUIContent[] GetDisplayNames(string target)\n        {\n            if (string.IsNullOrEmpty(target))\n                return null;\n\n            IPlatformSupportModule module;\n            if (platformSupportModules.TryGetValue(target, out module))\n            {\n                return platformSupportModules[target].GetDisplayNames();\n            }\n\n            return null;\n        }\n\n        internal static IEditorAnalyticsExtension GetEditorAnalyticsExtension(string target)\n        {\n            IPlatformSupportModule module;\n            if (platformSupportModules.TryGetValue(target, out module))\n            {\n                return module.GetEditorAnalyticsExtension();\n            }\n\n            return null;\n        }\n    }\n\n    internal static class ModuleUtils\n    {\n        // entry point from native\n        internal static string[] GetAdditionalReferencesForUserScripts()\n        {\n            var references = new List<string>();\n\n            foreach (var module in ModuleManager.platformSupportModules.Values)\n                references.AddRange(module.AssemblyReferencesForUserScripts);\n\n            return references.ToArray();\n        }\n\n        internal static string[] GetAdditionalReferencesForEditorCsharpProject()\n        {\n            var references = new List<string>();\n\n            foreach (var module in ModuleManager.platformSupportModules.Values)\n                references.AddRange(module.AssemblyReferencesForEditorCsharpProject);\n\n            return references.ToArray();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/PlatformSupportModule.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.DeploymentTargets;\nusing UnityEditor.Build;\nusing UnityEditor.Build.Reporting;\nusing UnityEditor.Build.Profile;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Modules\n{\n    internal interface IPlatformSupportModule\n    {\n        /// Returns name identifying a target, for ex., Metro, note this name should match prefix\n        /// for extension module UnityEditor.Metro.Extensions.dll, UnityEditor.Metro.Extensions.Native.dll\n        string TargetName { get; }\n\n        /// Returns the filename of jam which should be executed when you're recompiling extensions\n        /// from Editor using CTRL + L shortcut, for ex., WP8EditorExtensions, MetroEditorExtensions, etc\n        string JamTarget { get; }\n\n        IBuildTarget PlatformBuildTarget { get; }\n\n        /// Returns an array of native libraries that are required by the extension and must be loaded\n        /// by the editor.\n        ///\n        /// NOTE: If two different platform extensions return a native library with a same file name\n        /// (regardless of the path), then only first one will be loaded. This is due to the fact that\n        /// some platforms may require same native library, but we must ship a copy with both platforms,\n        /// since our modularization and platform installers don't support shared stuff.\n        string[] NativeLibraries { get; }\n\n        /// Returns an array of assemblies that should be referenced by user's scripts. These will be\n        /// referenced by editor scripts, and game scripts running in editor. Used to export additional\n        /// platform specific editor API.\n        string[] AssemblyReferencesForUserScripts { get; }\n\n        // Returns an array of assemblies that should be included into C# project as references.\n        // This is different from AssemblyReferencesForUserScripts by that most assembly references\n        // are internal and not added to the C# project. On the other hand, certain assemblies\n        // contain public API, and thus should be added to C# project.\n        string[] AssemblyReferencesForEditorCsharpProject { get; }\n\n        /// A human friendly version (eg. an incrementing number on each release) of the platform extension. Null/Empty if none available\n        string ExtensionVersion { get; }\n\n        // Names of displays to show in GameView and Camera inspector if the platform supports multiple displays. Return null if default names should be used.\n        GUIContent[] GetDisplayNames();\n\n        IBuildPostprocessor CreateBuildPostprocessor();\n\n        // Returns an instance of IDeploymentTargetsExtension or null if not supported\n        IDeploymentTargetsExtension CreateDeploymentTargetsExtension();\n\n        // Returns an instance of IScriptingImplementations or null if only one scripting backend is supported\n        IScriptingImplementations CreateScriptingImplementations();\n\n        // Return an instance of ISettingEditorExtension or null if not used\n        // See DefaultPlayerSettingsEditorExtension.cs for abstract implementation\n        ISettingEditorExtension CreateSettingsEditorExtension();\n\n        IAdaptiveVsyncSetting CreateAdaptiveSettingEditorExtension();\n\n        // Return an instance of IPreferenceWindowExtension or null if not used\n        IPreferenceWindowExtension CreatePreferenceWindowExtension();\n\n        // Return an instance of IBuildWindowExtension or null if not used\n        IBuildWindowExtension CreateBuildWindowExtension();\n\n        ICompilationExtension CreateCompilationExtension();\n\n        // Rather than null above, this returns a default extension if not used\n        ITextureImportSettingsExtension CreateTextureImportSettingsExtension();\n\n        IPluginImporterExtension CreatePluginImporterExtension();\n\n        // Returns an instance of IBuildProfileExtension or null if not supported.\n        IBuildProfileExtension CreateBuildProfileExtension();\n\n        // Register platform specific Unity extensions\n        // For ex., Metro specifc UnityEngine.Networking.dll which is different from the generic UnityEngine.Networking.dll\n        void RegisterAdditionalUnityExtensions();\n\n        // return valid object for this device. This ensures that API for certain operations is\n        // still available even if device was removed, for example stopping remote support.\n        IDevice CreateDevice(string id);\n\n        // Called when build target supplied by this module is activated in the editor.\n        //\n        // NOTE: Keep in mind that due domain reloads and the way unity builds, calls on OnActive\n        //     and OnDeactivate will be forced even if current build target isn't being changed.\n        //\n        // PERFORMANCE: This method will be called each time user starts the game, so use this\n        //     only for lightweight code, like registering to events, etc.\n        //\n        // Currently (de)activation happens when:\n        //     * User switches build target.\n        //     * User runs build for current target.\n        //     * Build is run through scripting API.\n        //     * Scripts are recompiled and reloaded (due user's change, forced reimport, etc).\n        //     * User clicks play in editor.\n        //     * ... and possibly more I'm not aware of.\n        void OnActivate();\n\n        // Called when build target supplied by this module is deactivated in the editor.\n        //\n        // NOTE: Keep in mind that due domain reloads and the way unity builds, calls on OnActive\n        //     and OnDeactivate will be forced even if current build target isn't being changed.\n        //\n        // PERFORMANCE: This method will be called each time user starts the game, so use this\n        //     only for lightweight code, like unregistering from events, etc.\n        //\n        // For more info see OnActivate().\n        void OnDeactivate();\n\n        // Called when extension is loaded, on editor start or domain reload.\n        //\n        // PERFORMANCE: This will be called for all available platform extensions during each\n        //     domain reload, including each time user starts the game, so use this only for\n        //     lightweight code.\n        void OnLoad();\n\n        // Called when extension is unloaded, when editor is exited or before domain reload.\n        //\n        // PERFORMANCE: This will be called for all available platform extensions during each\n        //     domain reload, including each time user starts the game, so use this only for\n        //     lightweight code.\n        void OnUnload();\n\n        IEnumerable<ScriptAssemblyPlatform> GetExtraScriptAssemblyPlatforms(BuildTarget buildTarget);\n\n        IEditorAnalyticsExtension GetEditorAnalyticsExtension();\n    }\n\n    internal interface IAdaptiveVsyncSetting\n    {\n        void AdaptiveVsyncUI(SerializedProperty currentSettings);\n    }\n\n    struct ScriptAssemblyPlatform\n    {\n        public string AssemblyNamePostfix;\n        public string TargetNiceName;\n        public int Subtarget;\n    }\n\n    internal interface IBuildPostprocessor\n    {\n        ILaunchReport LaunchPlayer(BuildLaunchPlayerArgs args);\n\n        void PostProcess(BuildPostProcessArgs args, out BuildProperties outProperties);\n\n        bool SupportsInstallInBuildFolder();\n\n        bool SupportsLz4Compression();\n\n        Compression GetDefaultCompression();\n\n        // This is the place to make sure platform has everything it needs for the build.\n        // Use EditorUtility.Display(Cancelable)ProgressBar when running long tasks (e.g. downloading SDK from internet).\n        // Return non-empty string indicating error message to stop the build.\n        /// <param name=\"buildOptions\">Build details. Useful to get the location of the player to build, for instance.</param>\n        string PrepareForBuild(BuildPlayerOptions buildOptions);\n\n        void PostProcessCompletedBuild(BuildPostProcessArgs args);\n\n        void UpdateBootConfig(BuildTarget target, BootConfigData config, BuildOptions options);\n\n        // Return string.Empty if targeting a folder.\n        string GetExtension(BuildTarget target, int subtarget, BuildOptions options);\n\n        bool AddIconsToBuild(AddIconsArgs args);\n    }\n\n    internal interface IScriptingImplementations\n    {\n        // All supported scripting implementations. First is the default one.\n        ScriptingImplementation[] Supported();\n\n        // Scripting implementations exposed to the user.\n        ScriptingImplementation[] Enabled();\n        bool AllowIL2CPPCompilerConfigurationSelection();\n    }\n\n    internal class DefaultScriptingImplementations : IScriptingImplementations\n    {\n        public virtual ScriptingImplementation[] Supported()\n        {\n            return new[]\n            {\n                ScriptingImplementation.Mono2x,\n                ScriptingImplementation.IL2CPP,\n            };\n        }\n\n        public virtual ScriptingImplementation[] Enabled()\n        {\n            return Supported();\n        }\n\n        public virtual bool AllowIL2CPPCompilerConfigurationSelection()\n        {\n            return true;\n        }\n    }\n\n    // Extension point to add/alter the SettingsEditorWindow class\n    // If you are creating a new extension you should probably inherit from DefaultPlayerSettingsEditorExtension\n    internal interface ISettingEditorExtension\n    {\n        void OnEnable(PlayerSettingsEditor settingsEditor);\n\n        void ConfigurePlatformProfile(SerializedObject serializedProfile);\n\n        bool CopyProjectSettingsPlayerSettingsToBuildProfile();\n\n        bool IsPlayerSettingsDataEqualToProjectSettings();\n\n        void OnActiveProfileChanged(BuildProfile previous, BuildProfile newProfile);\n\n        bool HasPublishSection();\n\n        // Leave blank if no contribution\n        void PublishSectionGUI(float h, float midWidth, float maxWidth);\n\n        bool HasIdentificationGUI();\n\n        // Leave blank if no contribution\n        void IdentificationSectionGUI();\n\n        // Leave blank if no contribution\n        void ConfigurationSectionGUI();\n\n        // Leave blank if no contribution\n        void RenderingSectionGUI();\n\n        bool SupportsOrientation();\n\n        bool SupportsStaticBatching();\n        bool SupportsDynamicBatching();\n        bool SupportsHighDynamicRangeDisplays();\n        bool SupportsGfxJobModes();\n        GraphicsJobMode AdjustGfxJobMode(GraphicsJobMode graphicsJobMode);\n\n        bool CanShowUnitySplashScreen();\n\n        void SplashSectionGUI();\n\n        bool UsesStandardIcons();\n\n        void IconSectionGUI();\n\n        bool HasResolutionSection();\n\n        void ResolutionSectionGUI(float h, float midWidth, float maxWidth);\n\n        bool HasBundleIdentifier();\n\n        bool SupportsMultithreadedRendering();\n\n        void MultithreadedRenderingGUI(NamedBuildTarget targetGroup);\n\n        bool SupportsCustomLightmapEncoding();\n\n        bool SupportsCustomNormalMapEncoding();\n\n        bool ShouldShowVulkanSettings();\n\n        void VulkanSectionGUI();\n\n        bool SupportsFrameTimingStatistics();\n\n        void SerializedObjectUpdated();\n\n        bool SupportsForcedSrgbBlit();\n\n        bool SupportsStaticSplashScreenBackgroundColor();\n\n        void AutoRotationSectionGUI();\n    }\n\n\n    // Extension point to add preferences to the PreferenceWindow class\n    internal interface IPreferenceWindowExtension\n    {\n        // Called from PreferenceWindow whenever preferences should be read\n        void ReadPreferences();\n\n        // Called from PreferenceWindow whenever preferences should be written\n        void WritePreferences();\n\n        // True is this extension contributes an external application/tool preference(s)\n        bool HasExternalApplications();\n\n        // Called from OnGui - this function should draw any contributing UI components\n        void ShowExternalApplications();\n    }\n\n    // NOTE: You probably want to inherit from DefaultBuildWindowExtension class\n    internal interface IBuildWindowExtension\n    {\n        void ShowPlatformBuildOptions();\n\n        void ShowPlatformBuildWarnings();\n\n        // Use this for \"developer\" Unity builds\n        void ShowInternalPlatformBuildOptions();\n\n        bool EnabledBuildButton();\n\n        bool EnabledBuildAndRunButton();\n\n        void GetBuildButtonTitles(out GUIContent buildButtonTitle, out GUIContent buildAndRunButtonTitle);\n\n        // Show path location dialog during Build or Build & Run click\n        bool AskForBuildLocation();\n\n        bool ShouldDrawRunLastBuildButton();\n        void DoRunLastBuildButtonGui();\n\n        bool ShouldDrawScriptDebuggingCheckbox();\n\n        bool ShouldDrawProfilerCheckbox();\n\n        bool ShouldDrawDevelopmentPlayerCheckbox();\n\n        bool ShouldDrawExplicitNullCheckbox();\n\n        bool ShouldDrawExplicitDivideByZeroCheckbox();\n\n        bool ShouldDrawExplicitArrayBoundsCheckbox();\n\n        // Force full optimisations for script complilation in Development builds.\n        // Useful for forcing optimized compiler for IL2CPP when profiling.\n        bool ShouldDrawForceOptimizeScriptsCheckbox();\n\n        // Enables a dialog \"Wait For Managed debugger\", which halts program execution until managed debugger is connected\n        bool ShouldDrawWaitForManagedDebugger();\n\n        bool ShouldDrawManagedDebuggerFixedPort();\n\n        // Grays out managed debugger options\n        bool ShouldDisableManagedDebuggerCheckboxes();\n    }\n\n    // Extension point to add platform-specific texture import settings.\n    // You probably want to inherit from DefaultTextureImportSettingsExtension\n    internal interface ITextureImportSettingsExtension\n    {\n        void ShowImportSettings(BaseTextureImportPlatformSettings editor);\n    }\n\n    /// <summary>\n    /// Describes a setting variant and if it should be selected in the UI initially.\n    /// </summary>\n    [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n    internal class PreconfiguredSettingsVariant\n    {\n        public string Name { get; }\n        public bool SelectedInitially { get; }\n        public bool Selected { get; set; }\n        public string Tooltip;\n        public PreconfiguredSettingsVariant(string name, bool selectedInitially, string tooltip = \"\")\n        {\n            Name = name;\n            SelectedInitially = selectedInitially;\n            Selected = selectedInitially;\n            Tooltip = tooltip;\n        }\n    }\n\n    // Interface for implementing platform specific setting in Build Profiles window.\n    [VisibleToOtherModules(\"UnityEditor.BuildProfileModule\")]\n    internal interface IBuildProfileExtension\n    {\n        BuildProfilePlatformSettingsBase CreateBuildProfilePlatformSettings();\n\n        /// <summary>\n        /// When editing a build profile asset, this method is invoked to render the UI for\n        /// viewing and/or editing the platform specific settings. <see cref=\"BuildProfilePlatformSettingsBase\"/>.\n        /// </summary>\n        /// <param name=\"serializedObject\">\n        /// Target Build Profile serialized object .\n        /// </param>\n        /// <param name=\"rootProperty\">\n        /// Property instance for <see cref=\"BuildProfile.platformBuildProfile\"/>.\n        /// </param>\n        /// <param name=\"state\">\n        /// Workflow state for the Build Profile window.\n        /// </param>\n        /// <returns>\n        /// Root visual element for the platform specific settings UI.\n        /// </returns>\n        VisualElement CreateSettingsGUI(\n            SerializedObject serializedObject,\n            SerializedProperty rootProperty,\n            BuildProfileWorkflowState state);\n\n        /// <summary>\n        /// When editing a build profile asset, this method is invoked to render the\n        /// warning help boxes for build related issues.\n        /// </summary>\n        /// <param name=\"serializedObject\">\n        /// Target Build Profile serialized object .\n        /// </param>\n        /// <param name=\"rootProperty\">\n        /// Property instance for <see cref=\"BuildProfile.platformBuildProfile\"/>.\n        /// </param>\n        /// <returns>\n        /// Root visual element for the platform specific warnings.\n        /// </returns>\n        VisualElement CreatePlatformBuildWarningsGUI(\n            SerializedObject serializedObject,\n            SerializedProperty rootProperty);\n\n        /// <summary>\n        /// Copy settings to the platform settings base we are passing. This is used, for example, when creating\n        /// a new classic profile and we need to copy settings - that live in the managed side only - to it\n        /// </summary>\n        void CopyPlatformSettingsToBuildProfile(BuildProfilePlatformSettingsBase platformSettingsBase);\n\n        /// <summary>\n        /// Copy platform settings from build profile to platform specific setting asset.\n        /// </summary>\n        void CopyPlatformSettingsFromBuildProfile(BuildProfilePlatformSettingsBase platformSettings);\n\n        /// <summary>\n        /// The info message paired with the create build profile button.\n        /// If platform does not override this message, TrText.sharedSettingsInfo will be used.\n        /// </summary>\n        /// <returns>\n        /// Message to be displayed.\n        /// </returns>\n        string GetProfileInfoMessage();\n\n        /// <summary>\n        /// Provides the list of preconfigured settings variants to display in the platform browser window\n        /// when creating a new build profile.\n        /// </summary>\n        PreconfiguredSettingsVariant[] GetPreconfiguredSettingsVariants();\n\n        /// <summary>\n        /// Gets called when a build profile is created from defaults or by duplication from a classic profile.\n        /// </summary>\n        void OnBuildProfileCreated(BuildProfile buildProfile, int preconfiguredSettingsVariant);\n\n        void OnDisable();\n    }\n\n    // Interface for target device related operations\n    internal interface IDevice\n    {\n        // Start remote support for this device\n        RemoteAddress StartRemoteSupport();\n\n        // Stop remote support for this device\n        void StopRemoteSupport();\n\n        // Start player connection support for this device. This only sets up ability to connect,\n        // like setting up TCP tunneling over USB, getting remote device's IP, but it doesn't\n        // actually make the connection. Only available if SupportsPlayerConnection is true.\n        // Otherwise throws NotSupportedException.\n        RemoteAddress StartPlayerConnectionSupport();\n\n        // Stop player connection support for this device. Only available if SupportsPlayerConnection\n        // is true. Otherwise throws NotSupportedException.\n        void StopPlayerConnectionSupport();\n    }\n\n    internal struct RemoteAddress\n    {\n        public string ip;\n        public int port;\n\n        public RemoteAddress(string ip, int port)\n        {\n            this.ip = ip;\n            this.port = port;\n        }\n    }\n\n    internal interface IPluginImporterExtension\n    {\n        // Functions use by PluginImporterInspector\n        void ResetValues(PluginImporterInspector inspector);\n        bool HasModified(PluginImporterInspector inspector);\n        void Apply(PluginImporterInspector inspector);\n        void OnEnable(PluginImporterInspector inspector);\n        void OnDisable(PluginImporterInspector inspector);\n        void OnPlatformSettingsGUI(PluginImporterInspector inspector);\n\n        // Called before building the player, checks if plugins don't overwrite each other\n        string CalculateFinalPluginPath(string buildTargetName, PluginImporter imp);\n        bool CheckFileCollisions(string buildTargetName, string[] buildDefineConstraints);\n    }\n\n    internal struct BuildLaunchPlayerArgs\n    {\n        public BuildTarget target;\n        public string playerPackage;\n        public string installPath;\n        public string productName;\n        public BuildOptions options;\n        public Build.Reporting.BuildReport report;\n    }\n\n    internal struct BuildPostProcessArgs\n    {\n        public BuildTarget target;\n        public int subtarget;\n        public string stagingArea;\n        public string stagingAreaData;\n        public string stagingAreaDataManaged;\n        public string playerPackage;\n        public string installPath;\n        public string companyName;\n        public string productName;\n        public Guid productGUID;\n        public BuildOptions options;\n        public Build.Reporting.BuildReport report;\n        internal RuntimeClassRegistry usedClassRegistry;\n    }\n\n    internal struct AddIconsArgs\n    {\n        public string stagingArea;\n    }\n\n    internal interface ICompilationExtension\n    {\n        string[] GetCompilerExtraAssemblyPaths(bool isEditor, string assemblyPathName);\n\n        // Returns an array of windows metadata files (.winmd) that should be referenced when compiling scripts.\n        // Only WinRT based platforms need these references.\n        IEnumerable<string> GetWindowsMetadataReferences();\n\n        // Returns an array of managed assemblies that should be referenced when compiling scripts\n        // Currently, only .NET scripting backend uses it to include WinRTLegacy.dll into compilation\n        IEnumerable<string> GetAdditionalAssemblyReferences();\n\n        // Returns an array of defines that should be used when compiling scripts\n        IEnumerable<string> GetAdditionalDefines();\n\n        // Returns an array of defines that should be used when compiling scripts for the editor\n        IEnumerable<string> GetAdditionalEditorDefines();\n\n        // Returns an array of C# source files that should be included into the assembly when compiling scripts\n        IEnumerable<string> GetAdditionalSourceFiles();\n    }\n\n    internal interface IEditorAnalyticsExtension\n    {\n        void AddExtraBuildAnalyticsFields(IntPtr eventData, BuildOptions buildOptions);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Modules/PostStrippingModuleAdder.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing UnityEditorInternal;\nnamespace UnityEditor.Modules;\n\ninternal class PostStrippingModuleAdder : IPostStrippingModuleAdder\n{\n    readonly LinkerToEditorData m_targetData;\n\n    public PostStrippingModuleAdder(LinkerToEditorData targetData)\n    {\n        m_targetData = targetData;\n    }\n\n    public void AddModule(string moduleName)\n    {\n        if (IsModuleIncluded(moduleName))\n            return;\n\n        // Check that the module has no managed component\n        var coreModulePath = InternalEditorUtility.GetEngineCoreModuleAssemblyPath();\n        var moduleAssemblyPath = Path.Combine(Path.GetDirectoryName(coreModulePath), $\"UnityEngine.{moduleName}Module.dll\");\n\n        //a managed assembly is still getting generated for this module, check if the assembly contains no types\n        if (File.Exists(moduleAssemblyPath))\n        {\n            var assembly = System.Reflection.Assembly.LoadFrom(moduleAssemblyPath);\n            var types = assembly.GetTypes();\n            if (types.Length > 0)\n                throw new ArgumentException($\"Cannot add {moduleName} after UnityLinker has run because it has a non-empty managed assembly. Types found: {string.Join<Type>(\", \", types)}.\");\n        }\n\n        // Check that all the module's dependencies are already on the list\n        var moduleDependencyNames = ModuleMetadata.GetModuleDependencies(moduleName);\n        var moduleDependencies = new List<LinkerToEditorData.ReportData.Dependency>();\n\n        var missingDependencyNames = new List<string>();\n        foreach (var dependency in moduleDependencyNames)\n        {\n            if (!IsModuleIncluded(dependency))\n            {\n                missingDependencyNames.Add(dependency);\n\n                //no need to process this entry further as it is missing from the included module list\n                continue;\n            }\n\n            moduleDependencies.Add(new LinkerToEditorData.ReportData.Dependency\n            {\n                name = dependency,\n                dependencyType = LinkerToEditorData.ReportData.DependencyType.Custom,\n                scenes = Array.Empty<string>(),\n            });\n        }\n\n        if (missingDependencyNames.Count > 0)\n            throw new ArgumentException(\n                $\"Cannot add module {moduleName} because it has dependencies on other modules that are not present: {string.Join(\", \", missingDependencyNames)}\");\n\n        m_targetData.report.modules.Add(new LinkerToEditorData.ReportData.Module\n        {\n            name = moduleName,\n            dependencies = moduleDependencies\n        });\n    }\n\n    public bool IsModuleIncluded(string moduleName) => m_targetData.report.modules.Find(m => m.name == moduleName) != null;\n}\n"
  },
  {
    "path": "Editor/Mono/MonoCecil/FileOpenInfo.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor\n{\n    internal class FileOpenInfo : IFileOpenInfo\n    {\n        public string FilePath { get; set; }\n        public int LineNumber { get; set; }\n\n        public FileOpenInfo()\n        {\n            LineNumber = 1;\n            FilePath = string.Empty;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/MonoCecil/IFileOpenInfo.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor\n{\n    internal interface IFileOpenInfo\n    {\n        string FilePath { get; set; }\n        int LineNumber { get; set; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/MonoCecil/IMonoCecilHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Reflection;\n\nnamespace UnityEditor\n{\n    internal interface IMonoCecilHelper\n    {\n        IFileOpenInfo TryGetCecilFileOpenInfo(Type type, MethodInfo methodInfo);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/MonoCecil/MonoCecilHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing Mono.Cecil;\nusing Mono.Cecil.Cil;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class MonoCecilHelper : IMonoCecilHelper\n    {\n        private static SequencePoint GetMethodFirstSequencePoint(MethodDefinition methodDefinition)\n        {\n            if (methodDefinition == null)\n            {\n                Debug.Log(\"MethodDefinition cannot be null. Check if any method was found by name in its declaring type TypeDefinition.\");\n                return null;\n            }\n\n            if (!methodDefinition.HasBody || !methodDefinition.Body.Instructions.Any() || methodDefinition.DebugInformation == null)\n            {\n                Debug.Log(string.Concat(\"To get SequencePoints MethodDefinition for \", methodDefinition.Name, \" must have MethodBody, DebugInformation and Instructions.\"));\n                return null;\n            }\n\n            if (!methodDefinition.DebugInformation.HasSequencePoints)\n            {\n                // If we don't have any sequence points for this method, it could be that\n                // the method is delegating its implementation to a state machine method (e.g using yield).\n                // The state machine method will contain the debug info, not this method.\n                // In that case, the debug information of the state machine method (e.g MoveNext)\n                // will contain a StateMachineKickOffMethod that will link backward to the\n                // this original method that was containing the yield.\n                // That's the method we are looking for to extract correct sequence points after.\n                foreach (var nestedType in methodDefinition.DeclaringType.NestedTypes)\n                {\n                    foreach (var method in nestedType.Methods)\n                    {\n                        if (method.DebugInformation != null && method.DebugInformation.StateMachineKickOffMethod == methodDefinition && method.HasBody && method.Body.Instructions.Count > 0)\n                        {\n                            methodDefinition = method;\n                            goto foundKickOffMethod;\n                        }\n                    }\n                }\n\n                Debug.Log(string.Concat(\"No SequencePoints for MethodDefinition for \", methodDefinition.Name));\n                return null;\n            }\n\n        foundKickOffMethod:\n\n            foreach (var instruction in methodDefinition.Body.Instructions)\n            {\n                // An instruction might be attached to a hidden sequence point (or no seq point at all)\n                // so we need to skip them as they don't have any debug line info.\n                var sequencePoint = methodDefinition.DebugInformation.GetSequencePoint(instruction);\n                if (sequencePoint != null && !sequencePoint.IsHidden)\n                {\n                    return sequencePoint;\n                }\n            }\n\n            return null;\n        }\n\n        private static AssemblyDefinition ReadAssembly(string assemblyPath)\n        {\n            using var assemblyResolver = new DefaultAssemblyResolver();\n            assemblyResolver.AddSearchDirectory(Path.GetDirectoryName(assemblyPath));\n            var readerParameters = new ReaderParameters\n            {\n                ReadSymbols = true,\n                SymbolReaderProvider = new DefaultSymbolReaderProvider(false),\n                AssemblyResolver = assemblyResolver,\n                ReadingMode = ReadingMode.Deferred\n            };\n\n            try\n            {\n                return AssemblyDefinition.ReadAssembly(assemblyPath, readerParameters);\n            }\n            catch (Exception exception)\n            {\n                Debug.Log(exception.Message);\n                return null;\n            }\n        }\n\n        public IFileOpenInfo TryGetCecilFileOpenInfo(Type type, MethodInfo methodInfo)\n        {\n            var assemblyPath = type.Assembly.Location;\n\n            // Get the sequence point directly from the method token (to avoid scanning all types/methods)\n            using var assemblyDefinition = ReadAssembly(assemblyPath);\n            var methodDefinition = assemblyDefinition.MainModule.LookupToken(methodInfo.MetadataToken) as MethodDefinition;\n            var sequencePoint = GetMethodFirstSequencePoint(methodDefinition);\n\n            var fileOpenInfo = new FileOpenInfo();\n            if (sequencePoint != null) // Can be null in case of yield return in target method\n            {\n                fileOpenInfo.LineNumber = sequencePoint.StartLine;\n                fileOpenInfo.FilePath = sequencePoint.Document.Url;\n            }\n\n            return fileOpenInfo;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/MonoScript.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEditor.Animations;\n\nnamespace UnityEditor\n{\n    // Representation of Script assets.\n    [NativeClass(null)]\n    [NativeType(\"Editor/Mono/MonoScript.bindings.h\")]\n    [ExcludeFromPreset]\n    public class MonoScript : TextAsset\n    {\n        // Returns the System.Type object of the class implemented by this script\n        public extern System.Type GetClass();\n\n        // Returns the MonoScript object containing specified MonoBehaviour\n        public static MonoScript FromMonoBehaviour(MonoBehaviour behaviour)\n        {\n            return FromScriptedObject(behaviour);\n        }\n\n        // Returns the MonoScript object containing specified ScriptableObject\n        public static MonoScript FromScriptableObject(ScriptableObject scriptableObject)\n        {\n            return FromScriptedObject(scriptableObject);\n        }\n\n        // Returns the MonoScript object containing the specified Type.\n        // Note we only store one type per MonoScript. Therefore, if the file contains multiple types, we will return null for the other types.\n        internal static MonoScript FromType(Type type)\n        {\n            if (type == null)\n                return null;\n            return FromTypeInternal(type.Name, type.Namespace, type.Assembly.GetName().Name);\n        }\n\n        // Returns the MonoScript object used by the given scripted object\n        [FreeFunction]\n        internal static extern MonoScript FromScriptedObject(UnityEngine.Object obj);\n\n        [FreeFunction]\n        internal static extern MonoScript FromTypeInternal(string className, string nameSpace, string assemblyName);\n\n        internal extern bool GetScriptTypeWasJustCreatedFromComponentMenu();\n\n        internal extern void SetScriptTypeWasJustCreatedFromComponentMenu();\n\n        // *undocumented*\n        // Pass CreateOptions.None to TextAsset constructor so it does not create a native TextAsset object.\n        // We create MonoScript native object instead.\n        public MonoScript() : base(TextAsset.CreateOptions.None, (string)null)\n        {\n            Init_Internal(this);\n        }\n\n        [FreeFunction(\"MonoScript_Init_Internal\")]\n        private static extern void Init_Internal([Writable] MonoScript script);\n\n        [FreeFunction(\"MonoScript_Init\", HasExplicitThis = true)]\n        internal extern void Init(string className, string nameSpace, string assemblyName, bool isEditorScript);\n\n        // *undocumented*\n        [NativeName(\"GetAssemblyName\")]\n        internal extern string GetAssemblyName();\n\n        // *undocumented*\n        [NativeName(\"GetNameSpace\")]\n        internal extern string GetNamespace();\n\n        [NativeName(\"GetPropertiesHashString\")]\n        internal extern string GetPropertiesHashString(bool developmentBuild);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/MuscleClipUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing System.Runtime.InteropServices;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/Animation/MuscleClipQualityInfo.h\")]\n    [RequiredByNativeCode]\n    [NativeAsStruct]\n    [StructLayout(LayoutKind.Sequential)]\n    internal class MuscleClipQualityInfo\n    {\n        [NativeName(\"m_Loop\")]\n        public float loop = 0;\n        [NativeName(\"m_LoopOrientation\")]\n        public float loopOrientation = 0;\n        [NativeName(\"m_LoopPositionY\")]\n        public float loopPositionY = 0;\n        [NativeName(\"m_LoopPositionXZ\")]\n        public float loopPositionXZ = 0;\n    }\n\n    internal struct QualityCurvesTime\n    {\n        public float fixedTime;\n        public float variableEndStart;\n        public float variableEndEnd;\n        public int q;\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/MuscleClipQualityInfo.h\")]\n    internal class MuscleClipUtility\n    {\n        [FreeFunction]\n        extern internal static MuscleClipQualityInfo GetMuscleClipQualityInfo([NotNull] AnimationClip clip, float startTime, float stopTime);\n\n        internal static void CalculateQualityCurves(AnimationClip clip, QualityCurvesTime time, Vector2[] poseCurve, Vector2[] rotationCurve, Vector2[] heightCurve, Vector2[] positionCurve)\n        {\n            if (poseCurve.Length != rotationCurve.Length || rotationCurve.Length != heightCurve.Length || heightCurve.Length != positionCurve.Length)\n            {\n                throw new ArgumentException(string.Format(\n                    \"poseCurve '{0}', rotationCurve '{1}', heightCurve '{2}' and positionCurve '{3}' Length must be equals.\",\n                    poseCurve.Length, rotationCurve.Length, heightCurve.Length, positionCurve.Length));\n            }\n\n            CalculateQualityCurves(clip, time.fixedTime, time.variableEndStart, time.variableEndEnd, time.q, poseCurve, rotationCurve, heightCurve, positionCurve);\n        }\n\n        [FreeFunction]\n        extern protected static void CalculateQualityCurves([NotNull] AnimationClip clip, float fixedTime, float variableEndStart, float variableEndEnd, int q, [Out] Vector2[] poseCurve, [Out] Vector2[] rotationCurve, [Out] Vector2[] heightCurve, [Out] Vector2[] positionCurve);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Networking/PlayerConnection/AttachToPlayerGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Hardware;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Networking.PlayerConnection;\n\nnamespace UnityEditor.Networking.PlayerConnection\n{\n    internal interface IConnectionStateInternal : IConnectionState\n    {\n        EditorWindow parentWindow { get; }\n        GUIContent notificationMessage { get; }\n        bool deepProfilingSupported { get; }\n        void AddItemsToTree(ConnectionTreeViewWindow connectionTreeViewWindow, Rect position);\n        string connectionDisplayName { get; set; }\n    }\n\n    internal enum EditorConnectionTarget\n    {\n        None,\n        MainEditorProcessPlaymode,\n        MainEditorProcessEditmode,\n        // add out-off-process player/profiler here\n    }\n\n    public static class PlayerConnectionGUIUtility\n    {\n        public static IConnectionState GetConnectionState(EditorWindow parentWindow, Action<string> connectedCallback = null)\n        {\n            return new GeneralConnectionState(parentWindow, (player, editorConnectionTarget) => connectedCallback?.Invoke(player));\n        }\n\n        internal static IConnectionState GetConnectionState(EditorWindow parentWindow, Action<EditorConnectionTarget> editorModeTargetSwitchedCallback, Func<EditorConnectionTarget, bool> editorModeTargetConnectionStatus, Action<string, EditorConnectionTarget?> connectedCallback = null)\n        {\n            return new GeneralConnectionState(parentWindow, connectedCallback, editorModeTargetSwitchedCallback, editorModeTargetConnectionStatus);\n        }\n    }\n\n    static class Styles\n    {\n        public static readonly GUIStyle defaultDropdown = \"MiniPullDown\";\n        public static readonly GUIContent dropdownButton = UnityEditor.EditorGUIUtility.TrTextContent(\"\", \"Target Selection: Choose the target to connect to.\");\n    }\n\n    public static class PlayerConnectionGUI\n    {\n        public static void ConnectionTargetSelectionDropdown(Rect rect, IConnectionState state, GUIStyle style = null)\n        {\n            var internalState = state as IConnectionStateInternal;\n            if (internalState?.parentWindow)\n            {\n                if (internalState.notificationMessage != null)\n                    internalState.parentWindow.ShowNotification(internalState.notificationMessage);\n                else\n                    internalState.parentWindow.RemoveNotification();\n            }\n            style ??= Styles.defaultDropdown;\n            if (!UnityEditor.EditorGUI.DropdownButton(rect, Styles.dropdownButton, FocusType.Keyboard, style))\n                return;\n\n            if (internalState != null)\n            {\n                ConnectionTreeViewWindow ctvw = new ConnectionTreeViewWindow(internalState, rect);\n                PopupWindow.Show(rect, ctvw);\n            }\n        }\n    }\n\n    public static class PlayerConnectionGUILayout\n    {\n        public static void ConnectionTargetSelectionDropdown(IConnectionState state, GUIStyle style = null, int maxWidth = 100)\n        {\n            if (style == null)\n                style = Styles.defaultDropdown;\n            Styles.dropdownButton.text = ConnectionUIHelper.GetToolbarContent(state.connectionName, style, maxWidth );\n            var size = style.CalcSize(Styles.dropdownButton);\n            Rect connectRect = GUILayoutUtility.GetRect(size.x, size.y);\n\n            if(connectRect.width > size.x)\n                Styles.dropdownButton.text = ConnectionUIHelper.GetToolbarContent(state.connectionName, style, (int)connectRect.width);\n\n            PlayerConnectionGUI.ConnectionTargetSelectionDropdown(connectRect, state, style);\n        }\n    }\n\n    internal class GeneralConnectionState : IConnectionStateInternal\n    {\n        static class Content\n        {\n            public static readonly GUIContent Playmode = UnityEditor.EditorGUIUtility.TrTextContent(\"Play Mode\");\n            public static readonly GUIContent Editmode = UnityEditor.EditorGUIUtility.TrTextContent(\"Edit Mode\");\n            public static readonly GUIContent EnterIPText = UnityEditor.EditorGUIUtility.TrTextContent(\"<Enter IP>\");\n            public static readonly GUIContent AutoconnectedPlayer = UnityEditor.EditorGUIUtility.TrTextContent(\"(Autoconnected Player)\");\n            public static readonly GUIContent ConnectingToPlayerMessage = UnityEditor.EditorGUIUtility.TrTextContent(\"Connecting to player... (this can take a while)\");\n\n            public static readonly string LocalHostProhibited = L10n.Tr(\" (Localhost prohibited)\");\n            public static readonly string VersionMismatch = L10n.Tr(\" (Version mismatch)\");\n\n            public static readonly string Editor = \"Editor\";\n            public static readonly string DirectConnection = \"Direct Connection\";\n        }\n        static GUIContent s_NotificationMessage;\n\n        public GUIContent notificationMessage => s_NotificationMessage;\n\n        // keep this constant in sync with PLAYER_DIRECT_IP_CONNECT_GUID in GeneralConnection.h\n        const int PLAYER_DIRECT_IP_CONNECT_GUID = 0xFEED;\n        // keep this constant in sync with PLAYER_DIRECT_URL_CONNECT_GUID in GeneralConnection.h\n        const int PLAYER_DIRECT_URL_CONNECT_GUID = 0xFEEE;\n        const string k_EditorConnectionName = \"Editor\";\n\n        public EditorWindow parentWindow { get; private set; }\n\n        public ConnectionTarget connectedToTarget => ProfilerDriver.IsConnectionEditor() ? ConnectionTarget.Editor : ConnectionTarget.Player;\n\n        public string connectionName\n        {\n            get\n            {\n                string name = ProfilerDriver.GetConnectionIdentifier(ProfilerDriver.connectedProfiler);\n                if (m_EditorModeTargetState.HasValue && name.Contains(k_EditorConnectionName))\n                {\n                    if (m_EditorModeTargetConnectionStatus(EditorConnectionTarget.MainEditorProcessEditmode))\n                        name = Content.Editmode.text;\n                    else\n                        name = Content.Playmode.text;\n                }\n                return name;\n            }\n        }\n\n        public string connectionDisplayName { get; set; }\n\n        public bool deepProfilingSupported => ProfilerDriver.IsDeepProfilingSupported(ProfilerDriver.connectedProfiler);\n\n        event Action<string, EditorConnectionTarget?> connected;\n\n\n        event Action<EditorConnectionTarget> switchedEditorModeTarget;\n        Func<EditorConnectionTarget, bool> m_EditorModeTargetConnectionStatus;\n        EditorConnectionTarget? m_EditorModeTargetState = null;\n\n\n        static List<WeakReference> s_AllGeneralAttachToPlayerStates = new List<WeakReference>();\n\n        public GeneralConnectionState(EditorWindow parentWindow, Action<string, EditorConnectionTarget?> connectedCallback = null, Action<EditorConnectionTarget> editorModeTargetSwitchedCallback = null, Func<EditorConnectionTarget, bool> editorModeTargetConnectionStatus = null)\n        {\n            this.parentWindow = parentWindow;\n            if (parentWindow != null)\n                connected += (player, editorConnectionTarget) => this.parentWindow.Repaint();\n\n            if (connectedCallback != null)\n                connected += connectedCallback;\n\n            if (editorModeTargetSwitchedCallback != null)\n            {\n                Debug.Assert(editorModeTargetConnectionStatus != null, $\"{nameof(editorModeTargetConnectionStatus)} can't be null when a {nameof(editorModeTargetSwitchedCallback)} is provided.\");\n                switchedEditorModeTarget += editorModeTargetSwitchedCallback;\n                m_EditorModeTargetConnectionStatus = editorModeTargetConnectionStatus;\n                m_EditorModeTargetState = EditorConnectionTarget.None;\n            }\n\n            s_AllGeneralAttachToPlayerStates.Add(new WeakReference(this));\n        }\n\n        private static void SuccessfullyConnectedToPlayer(string player, EditorConnectionTarget? editorConnectionTarget = null)\n        {\n            for (int i = s_AllGeneralAttachToPlayerStates.Count - 1; i >= 0; i--)\n            {\n                if (s_AllGeneralAttachToPlayerStates[i] == null || !s_AllGeneralAttachToPlayerStates[i].IsAlive)\n                {\n                    s_AllGeneralAttachToPlayerStates.RemoveAt(i);\n                }\n                var generalConnectionState = (s_AllGeneralAttachToPlayerStates[i].Target as GeneralConnectionState);\n                generalConnectionState.connected?.Invoke(player, editorConnectionTarget);\n                if (editorConnectionTarget.HasValue)\n                {\n                    generalConnectionState.switchedEditorModeTarget?.Invoke(editorConnectionTarget.Value);\n                }\n                else\n                {\n                    if (player.Contains(k_EditorConnectionName))\n                    {\n                        // if e.g. the console or the memory profiler connects to the Editor, the profiler should switch to PlayMode profiling, not to Editmode profiling\n                        // especially since falling back onto the Editor is the default.\n                        generalConnectionState.switchedEditorModeTarget?.Invoke(EditorConnectionTarget.MainEditorProcessPlaymode);\n                    }\n                    else\n                    {\n                        generalConnectionState.switchedEditorModeTarget?.Invoke(EditorConnectionTarget.None);\n                    }\n                }\n            }\n        }\n\n        public virtual void AddItemsToTree(ConnectionTreeViewWindow menu, Rect position)\n        {\n            bool hasAnyConnectionOpen = false;\n            AddAvailablePlayerConnections(menu, ref hasAnyConnectionOpen);\n            AddAvailableDeviceConnections(menu, ref hasAnyConnectionOpen);\n            AddLastConnectedIP(menu, ref hasAnyConnectionOpen);\n\n            // Case 810030: Check if player is connected using AutoConnect Profiler feature via 'connect <ip> string in PlayerConnectionConfigFile\n            // In that case ProfilerDriver.GetAvailableProfilers() won't return the connected player\n            // But we still want to show that it's connected, because the data is incoming\n            if (!ProfilerDriver.IsConnectionEditor() && !hasAnyConnectionOpen)\n            {\n                menu.AddDisabledItem(new ConnectionDropDownItem(Content.AutoconnectedPlayer.text, ProfilerDriver.connectedProfiler, Content.DirectConnection, ConnectionDropDownItem.ConnectionMajorGroup.Direct, () => true, null));\n            }\n\n            AddConnectionViaEnterIPWindow(menu, GUIUtility.GUIToScreenRect(position));\n        }\n\n        internal static void DirectIPConnect(string ip)\n        {\n            // Profiler.DirectIPConnect is a blocking call, so a notification message is used to show the progress\n            if (ProfilerDriver.connectedProfiler == PLAYER_DIRECT_IP_CONNECT_GUID)\n                return;\n            s_NotificationMessage = Content.ConnectingToPlayerMessage;\n            ProfilerDriver.DirectIPConnect(ip);\n            s_NotificationMessage = null;\n            SuccessfullyConnectedToPlayer(ip);\n        }\n\n        internal static void DirectURLConnect(string url)\n        {\n            // Profiler.DirectURLConnect is a blocking call, so a notification message is used to show the progress\n            s_NotificationMessage = Content.ConnectingToPlayerMessage;\n            ProfilerDriver.DirectURLConnect(url);\n            s_NotificationMessage = null;\n            SuccessfullyConnectedToPlayer(url);\n        }\n\n        void AddLastConnectedIP(ConnectionTreeViewWindow menuOptions, ref bool hasOpenConnection)\n        {\n            string lastIP = AttachToPlayerPlayerIPWindow.GetLastIPString();\n            if (string.IsNullOrEmpty(lastIP))\n                return;\n\n            bool isConnected = ProfilerDriver.connectedProfiler == PLAYER_DIRECT_IP_CONNECT_GUID;\n            hasOpenConnection |= isConnected;\n            menuOptions.AddItem(new ConnectionDropDownItem(lastIP, PLAYER_DIRECT_IP_CONNECT_GUID,\n                Content.DirectConnection, ConnectionDropDownItem.ConnectionMajorGroup.Direct, () => ProfilerDriver.connectedProfiler == PLAYER_DIRECT_IP_CONNECT_GUID,\n                () => DirectIPConnect(lastIP)));\n        }\n\n        internal static string GetConnectionName(int guid)\n        {\n            // Connection identifier is constructed in the PlayerConnection::ConstructWhoamiString()\n            // in a form \"{platform name}(host name or ip)[:port]\n            var name = ProfilerDriver.GetConnectionIdentifier(guid);\n\n            // Ignore Editor connections which named explicitly after project name.\n            var portSpacerIndex = name.LastIndexOf(')');\n            if (portSpacerIndex == -1)\n                return name;\n\n            // Port already specified\n            if (name.Length > (portSpacerIndex + 1) && name[portSpacerIndex + 1] == ':')\n                return name;\n\n            // If port hasn't been specified in the connection identifier, we place it with \"host name or ip\" segment.\n            var port = ProfilerDriver.GetConnectionPort(guid);\n            return string.Format(\"{0}:{1})\", name.Substring(0, portSpacerIndex), port);\n        }\n\n        void AddAvailablePlayerConnections(ConnectionTreeViewWindow menuOptions, ref bool hasOpenConnection,\n            Func<bool> disabler = null)\n        {\n            int[] connectionGuids = ProfilerDriver.GetAvailableProfilers();\n            for (int index = 0; index < connectionGuids.Length; index++)\n            {\n                int guid = connectionGuids[index];\n                string name = GetConnectionName(guid);\n                bool isProhibited = ProfilerDriver.IsIdentifierOnLocalhost(guid) && (name.Contains(\"MetroPlayerX\") || name.Contains(\"UWPPlayerX\"));\n                bool enabled = !isProhibited && ProfilerDriver.IsIdentifierConnectable(guid);\n\n                bool isConnected = ProfilerDriver.connectedProfiler == guid;\n                hasOpenConnection |= isConnected;\n                if (!enabled)\n                {\n                    if (isProhibited)\n                        name += Content.LocalHostProhibited;\n                    else\n                        name += Content.VersionMismatch;\n                }\n                if (enabled)\n                {\n                    if (m_EditorModeTargetState.HasValue && name.Contains(k_EditorConnectionName))\n                    {\n                        if (!menuOptions.HasItem(Content.Playmode.text) && !name.StartsWith(\"Profiler-\"))\n                        {\n                            menuOptions.AddItem(new ConnectionDropDownItem(Content.Playmode.text, guid, Content.Editor,\n                                ConnectionDropDownItem.ConnectionMajorGroup.Editor,\n                                () => ProfilerDriver.connectedProfiler == guid &&\n                                !m_EditorModeTargetConnectionStatus(EditorConnectionTarget\n                                    .MainEditorProcessPlaymode),\n                                () =>\n                                {\n                                    ProfilerDriver.connectedProfiler = guid;\n                                    SuccessfullyConnectedToPlayer(connectionName,\n                                        EditorConnectionTarget.MainEditorProcessPlaymode);\n                                }));\n\n                            menuOptions.AddItem(new ConnectionDropDownItem(Content.Editmode.text, guid, Content.Editor,\n                                ConnectionDropDownItem.ConnectionMajorGroup.Editor,\n                                () => ProfilerDriver.connectedProfiler == guid &&\n                                m_EditorModeTargetConnectionStatus(EditorConnectionTarget\n                                    .MainEditorProcessEditmode),\n                                () =>\n                                {\n                                    ProfilerDriver.connectedProfiler = guid;\n                                    SuccessfullyConnectedToPlayer(connectionName,\n                                        EditorConnectionTarget.MainEditorProcessEditmode);\n                                }));\n                        }\n                    }\n                    else\n                    {\n                        menuOptions.AddItem(new ConnectionDropDownItem(\n                            name, guid, null, ConnectionDropDownItem.ConnectionMajorGroup.Unknown,\n                            () => ProfilerDriver.connectedProfiler == guid,\n                            () =>\n                            {\n                                ProfilerDriver.connectedProfiler = guid;\n                                if (ProfilerDriver.connectedProfiler == guid)\n                                {\n                                    SuccessfullyConnectedToPlayer(connectionName);\n                                }\n                            }));\n                    }\n                }\n                else\n                    menuOptions.AddDisabledItem(new ConnectionDropDownItem(name, guid, null, ConnectionDropDownItem.ConnectionMajorGroup.Unknown, () => ProfilerDriver.connectedProfiler == guid, null));\n            }\n        }\n\n        void AddAvailableDeviceConnections(ConnectionTreeViewWindow menuOptions, ref bool hasOpenConnection)\n        {\n            foreach (var device in DevDeviceList.GetDevices())\n            {\n                bool supportsPlayerConnection = (device.features & DevDeviceFeatures.PlayerConnection) != 0;\n                if (!device.isConnected || !supportsPlayerConnection)\n                    continue;\n\n                var url = \"device://\" + device.id;\n                bool isConnected = ProfilerDriver.connectedProfiler == PLAYER_DIRECT_URL_CONNECT_GUID && ProfilerDriver.directConnectionUrl == url;\n                hasOpenConnection |= isConnected;\n                //iphone handles the naming differently to android\n                menuOptions.AddItem(new ConnectionDropDownItem(\n                    device.type == \"Android\"\n                    ? device.name.Substring(device.name.IndexOf('(') + 1).TrimEnd(')')\n                    : device.name, PLAYER_DIRECT_URL_CONNECT_GUID, \"Devices\" ,\n                    ConnectionDropDownItem.ConnectionMajorGroup.Local,\n                    () => ProfilerDriver.connectedProfiler == PLAYER_DIRECT_URL_CONNECT_GUID &&\n                    ProfilerDriver.directConnectionUrl == url, () => DirectURLConnect(url), true, device.type == \"iOS\" ? \"IPhonePlayer\" : device.type));\n            }\n        }\n\n        void AddConnectionViaEnterIPWindow(ConnectionTreeViewWindow menuOptions, Rect buttonScreenRect,\n            Func<bool> disabler = null)\n        {\n            menuOptions.AddItem(new ConnectionDropDownItem(Content.EnterIPText.text, -2, Content.DirectConnection, ConnectionDropDownItem.ConnectionMajorGroup.Direct, () => false, () =>\n            {\n                AttachToPlayerPlayerIPWindow.Show(buttonScreenRect);\n                GUIUtility.ExitGUI(); // clear the gui state to prevent hot control issues\n            }));\n        }\n\n        private bool disposed = false; // To detect redundant calls\n\n        ~GeneralConnectionState()\n        {\n            if (!disposed)\n                // Referring to the interface here, because the user only knows about the public IConnectionState interfaces and nothing about the internal GeneralConnectionState (except for the fact that it's about to show up in this error's callstack)\n                Debug.LogError(\"IConnectionState was not Disposed! Please make sure to call Dispose in OnDisable of the EditorWindow in which it was used.\");\n        }\n\n        public void Dispose()\n        {\n            if (!disposed)\n            {\n                if (s_AllGeneralAttachToPlayerStates != null)\n                {\n                    for (int i = s_AllGeneralAttachToPlayerStates.Count - 1; i >= 0; i--)\n                    {\n                        if (!s_AllGeneralAttachToPlayerStates[i].IsAlive || s_AllGeneralAttachToPlayerStates[i].Target == this)\n                        {\n                            s_AllGeneralAttachToPlayerStates.RemoveAt(i);\n                        }\n                    }\n                }\n                parentWindow = null;\n                disposed = true;\n            }\n        }\n    }\n\n    internal class AttachToPlayerPlayerIPWindow : EditorWindow\n    {\n        static class Content\n        {\n            public static readonly GUIContent ConnectButtonContent = UnityEditor.EditorGUIUtility.TrTextContent(\"Connect\");\n            public static readonly string EnterPlayerIPWindowName = L10n.Tr(\"Enter Player IP\");\n        }\n        private const string k_TextFieldControlId = \"IPWindow\";\n        private const string k_LastIPEditorPrefKey = \"ProfilerLastIP\";\n\n        private string m_IPString;\n        private bool m_DidFocus = false;\n\n\n        public static void Show(Rect buttonScreenRect)\n        {\n            Rect rect = new Rect(buttonScreenRect.x, buttonScreenRect.yMax, 300, 50);\n            AttachToPlayerPlayerIPWindow w = EditorWindow.GetWindowWithRect<AttachToPlayerPlayerIPWindow>(rect, true, Content.EnterPlayerIPWindowName);\n            w.position = rect;\n            w.m_Parent.window.m_DontSaveToLayout = true;\n        }\n\n        void OnEnable()\n        {\n            m_IPString = GetLastIPString();\n        }\n\n        public static string GetLastIPString()\n        {\n            return EditorPrefs.GetString(k_LastIPEditorPrefKey, \"\");\n        }\n\n        void OnGUI()\n        {\n            Event evt = Event.current;\n            bool hitEnter = evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter);\n\n            UnityEditor.EditorGUILayout.BeginVertical();\n            {\n                GUILayout.Space(5);\n                GUI.SetNextControlName(k_TextFieldControlId);\n                m_IPString = UnityEditor.EditorGUILayout.TextField(m_IPString);\n\n\n                if (!m_DidFocus)\n                {\n                    m_DidFocus = true;\n                    UnityEditor.EditorGUI.FocusTextInControl(k_TextFieldControlId);\n                }\n\n                GUI.enabled = m_IPString.Length != 0;\n                if (GUILayout.Button(Content.ConnectButtonContent) || hitEnter)\n                {\n                    Close();\n                    // Save ip\n                    EditorPrefs.SetString(k_LastIPEditorPrefKey, m_IPString);\n                    GeneralConnectionState.DirectIPConnect(m_IPString);\n                    GUIUtility.ExitGUI();\n                }\n            }\n            UnityEditor.EditorGUILayout.EndVertical();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Networking/PlayerConnection/ConnectionDropDown.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing TreeView = UnityEditor.IMGUI.Controls.TreeView<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor.Networking.PlayerConnection\n{\n    internal static class ConnectionUIHelper\n    {\n        private static string portPattern = @\":\\d{4,}\";\n        private static string ipPattern = @\"@\\d{1,3}.\\d{1,3}.\\d{1,3}.\\d{1,3}\";\n        private static string localHostPattern = @\" (Localhost prohibited)\";\n        public static readonly string kDevices = L10n.Tr(\"Devices\");\n\n        internal static class Content\n        {\n            public static string PlayerLogging = L10n.Tr(\"Player Logging\");\n            public static string FullLog = L10n.Tr(\"Full Log [Developer Mode Only]\");\n            public static string Logging = L10n.Tr(\"Logging\");\n        }\n\n        public static string GetToolbarContent(string connectionName, GUIStyle style, int maxWidth)\n        {\n            var projectNameFromConnectionIdentifier = GetProjectNameFromConnectionIdentifier(ProfilerDriver.connectedProfiler);\n            var s =  $\"{GetPlayerNameFromIDString(GetIdString(connectionName))}{(string.IsNullOrEmpty(projectNameFromConnectionIdentifier) ? \"\" : $\" - {projectNameFromConnectionIdentifier}\")}\";\n            return TruncateString(s, style, maxWidth);\n        }\n\n        public static string TruncateString(string s, GUIStyle style, float maxwidth)\n        {\n            if (style.CalcSize(GUIContent.Temp(s)).x < maxwidth)\n                return s;\n\n            maxwidth -= style.CalcSize(GUIContent.Temp(\"...\")).x;\n            while (s.Length > 0 && style.CalcSize(GUIContent.Temp(s)).x > maxwidth)\n            {\n                s = s.Remove(s.Length - 1, 1);\n            }\n\n            return s + \"...\";\n        }\n\n        public static string GetPlayerNameFromId(int id)\n        {\n            return GetPlayerNameFromIDString(GetIdString(GeneralConnectionState.GetConnectionName(id)));\n        }\n\n        public static string GetIdString(string id)\n        {\n            //strip port info\n            var portMatch = Regex.Match(id, portPattern);\n            if (portMatch.Success)\n            {\n                id = id.Replace(portMatch.Value, \"\");\n            }\n\n            //strip ip info\n            var ipMatch = Regex.Match(id, ipPattern);\n            if (ipMatch.Success)\n            {\n                id = id.Replace(ipMatch.Value, \"\");\n            }\n\n            var removedWarning = false;\n            if (id.Contains(localHostPattern))\n            {\n                id = id.Replace(localHostPattern, \"\");\n                removedWarning = true;\n            }\n\n            id = id.Contains('(') ? id.Substring(id.IndexOf('(') + 1) : id;// trim the brackets\n            id = id.EndsWith(\")\") ? id.Substring(0, id.Length - 1) : id; // trimend cant be used as the player id might end with )\n\n            if (removedWarning)\n                id += localHostPattern;\n            return id;\n        }\n\n        public static string GetRuntimePlatformFromIDString(string id)\n        {\n            var commaIndx = id.IndexOf(',');\n            if (commaIndx == -1)\n                return \"\";\n\n            var s = id.Substring(0, commaIndx);\n            return RuntimePlatform.TryParse(s, out RuntimePlatform result) ? result.ToString() : \"\";\n        }\n\n        public static string GetPlayerNameFromIDString(string id)\n        {\n            var commaIndx = id.IndexOf(',');\n            return commaIndx != -1 ? id.Substring(commaIndx + 1) : id;\n        }\n\n        public static string GetPlayerType(string connectionName)\n        {\n            var parenthesisIndx = connectionName.IndexOf('(');\n            return parenthesisIndx != -1 ? connectionName.Substring(0, parenthesisIndx) : connectionName;\n        }\n\n        public static string GetProjectNameFromConnectionIdentifier(int connectionId)\n        {\n            return ProfilerDriver.GetProjectName(connectionId);\n        }\n\n        public static string GetIP(int connectionId)\n        {\n            return ProfilerDriver.GetConnectionIP(connectionId);\n        }\n\n        public static string GetPort(int connectionId)\n        {\n            var port = ProfilerDriver.GetConnectionPort(connectionId);\n            return port == 0 ? \"-\" : port.ToString();\n        }\n\n        public static GUIContent GetIcon(string name)\n        {\n            var content = GetBuildTargetIcon(name);\n            if (content == null)\n            {\n                content = name switch\n                {\n                    \"Editor\" => EditorGUIUtility.IconContent(\"d_SceneAsset Icon\"),\n                    \"WindowsEditor\" => EditorGUIUtility.IconContent(\"d_SceneAsset Icon\"),\n                    \"WindowsPlayer\" => EditorGUIUtility.IconContent(\"BuildSettings.Metro.Small\"),\n                    \"Android\" => EditorGUIUtility.IconContent(\"BuildSettings.Android.Small\"),\n                    \"OSXPlayer\" => EditorGUIUtility.IconContent(\"BuildSettings.Standalone.Small\"),\n                    \"IPhonePlayer\" => EditorGUIUtility.IconContent(\"BuildSettings.iPhone.Small\"),\n                    \"WebGLPlayer\" => EditorGUIUtility.IconContent(\"BuildSettings.WebGL.Small\"),\n                    \"tvOS\" => EditorGUIUtility.IconContent(\"BuildSettings.tvOS.Small\"),\n                    \"Lumin\" => EditorGUIUtility.IconContent(\"BuildSettings.Lumin.small\"),\n                    \"LinuxPlayer\" => EditorGUIUtility.IconContent(\"BuildSettings.EmbeddedLinux.Small\"),\n                    \"WSAPlayerX86\" => EditorGUIUtility.IconContent(\"BuildSettings.Metro.Small\"),\n                    \"WSAPlayerX64\" => EditorGUIUtility.IconContent(\"BuildSettings.Metro.Small\"),\n                    \"WSAPlayerARM\" => EditorGUIUtility.IconContent(\"BuildSettings.Metro.Small\"),\n                    \"Switch\" => EditorGUIUtility.IconContent(\"BuildSettings.Switch.Small\"),\n                    \"EmbeddedLinuxArm64\" => EditorGUIUtility.IconContent(\"BuildSettings.EmbeddedLinux.Small\"),\n                    \"EmbeddedLinuxArm32\" => EditorGUIUtility.IconContent(\"BuildSettings.EmbeddedLinux.Small\"),\n                    \"EmbeddedLinuxX64\" => EditorGUIUtility.IconContent(\"BuildSettings.EmbeddedLinux.Small\"),\n                    \"EmbeddedLinuxX86\" => EditorGUIUtility.IconContent(\"BuildSettings.EmbeddedLinux.Small\"),\n                    \"QNXArm64\" => EditorGUIUtility.IconContent(\"BuildSettings.QNX.Small\"),\n                    \"QNXArm32\" => EditorGUIUtility.IconContent(\"BuildSettings.QNX.Small\"),\n                    \"QNXX64\" => EditorGUIUtility.IconContent(\"BuildSettings.QNX.Small\"),\n                    \"QNXX86\" => EditorGUIUtility.IconContent(\"BuildSettings.QNX.Small\"),\n                    \"PS4\" => EditorGUIUtility.IconContent(\"BuildSettings.PS4.Small\"),\n                    \"PS5\" => EditorGUIUtility.IconContent(\"BuildSettings.PS5.Small\"),\n                    \"Devices\" => EditorGUIUtility.IconContent(\"BuildSettings.Standalone.Small\"),\n                    \"<unknown>\" => EditorGUIUtility.IconContent(\"BuildSettings.Broadcom\"),\n                    _ => EditorGUIUtility.IconContent(\"BuildSettings.Broadcom\")\n                };\n            }\n\n            return content;\n        }\n\n        private static GUIContent GetBuildTargetIcon(string name)\n        {\n            var target = BuildPipeline.GetBuildTargetByName(name);\n            if (target == BuildTarget.NoTarget)\n            {\n                return null;\n            }\n\n            var namedBuildTarget = Build.NamedBuildTarget.FromActiveSettings(target);\n            if (namedBuildTarget == null)\n            {\n                return null;\n            }\n\n            var buildPlatform = Build.BuildPlatforms.instance.BuildPlatformFromNamedBuildTarget(namedBuildTarget);\n            if (buildPlatform == null || buildPlatform.smallIcon == null)\n            {\n                return null;\n            }\n\n            return new GUIContent(buildPlatform.smallIcon);\n        }\n    }\n\n    internal class ConnectionDropDownItem : TreeViewItem\n    {\n        public Func<bool> m_Connected;\n        public Action m_OnSelected;\n        public string m_SubGroup;\n        public bool m_Disabled;\n        public string ProjectName;\n        public float ProjectNameSize;\n        public ConnectionMajorGroup m_TopLevelGroup;\n        public int m_ConnectionId;\n        internal string DisplayName;\n        public float DisplayNameSize;\n        internal string IP;\n        internal float IPSize;\n        internal string Port;\n        internal float PortSize;\n        internal bool OldConnectionFormat;\n        public bool IsDevice;\n        public GUIContent IconContent;\n\n        static class Content\n        {\n            public static readonly string DirectConnection = L10n.Tr(\"Direct Connection\");\n        }\n\n        internal enum ConnectionMajorGroup\n        {\n            Editor,\n            Logging,\n            Local,\n            Remote,\n            ConnectionsWithoutID,\n            Direct,\n            Unknown\n        }\n\n        internal static string[] ConnectionMajorGroupLabels =\n        {\n            \"Editor\",\n            \"Logging\",\n            \"Local\",\n            \"Remote\",\n            \"Connections Without ID\",\n            \"Direct Connection\",\n            \"Unknown\"\n        };\n\n        public ConnectionDropDownItem(string content, int connectionId, string subGroup, ConnectionMajorGroup topLevelGroup, Func<bool> connected, Action onSelected,\n                                       bool isDevice = false, string iconString = null)\n        {\n            var idString = ConnectionUIHelper.GetIdString(content);\n            DisplayName = subGroup == ConnectionUIHelper.kDevices ? content : ConnectionUIHelper.GetPlayerNameFromIDString(idString);\n            DisplayNameSize = ConnectionDropDownStyles.sTVLine.CalcSize(GUIContent.Temp(DisplayName)).x;\n\n            ProjectName = subGroup == ConnectionUIHelper.kDevices ? \"\" : ConnectionUIHelper.GetProjectNameFromConnectionIdentifier(connectionId);\n            ProjectNameSize = ConnectionDropDownStyles.sTVLine.CalcSize(GUIContent.Temp(ProjectName)).x;\n\n            IP = ConnectionUIHelper.GetIP(connectionId);\n            IPSize = ConnectionDropDownStyles.sTVLine.CalcSize(GUIContent.Temp(IP)).x;\n\n            Port = ConnectionUIHelper.GetPort(connectionId);\n            PortSize = ConnectionDropDownStyles.sTVLine.CalcSize(GUIContent.Temp(Port)).x;\n\n            m_ConnectionId = connectionId;\n            m_Connected = connected;\n            m_OnSelected = onSelected;\n            m_SubGroup = string.IsNullOrEmpty(subGroup) ? ConnectionUIHelper.GetRuntimePlatformFromIDString(idString) : subGroup;\n            m_TopLevelGroup = topLevelGroup == ConnectionMajorGroup.Unknown ? (m_SubGroup == Content.DirectConnection ? ConnectionMajorGroup.Direct : (ProfilerDriver.IsIdentifierOnLocalhost(connectionId) ? ConnectionMajorGroup.Local : ConnectionMajorGroup.Remote)) : topLevelGroup;\n\n            if (m_TopLevelGroup == ConnectionMajorGroup.Direct)\n            {\n                DisplayName = content;\n            }\n\n            if (string.IsNullOrEmpty(m_SubGroup))\n            {\n                if (idString == \"Editor\" || idString == \"Main Editor Process\")\n                {\n                    m_TopLevelGroup = ConnectionMajorGroup.Editor;\n                    m_SubGroup = \"Editor\";\n                }\n                else\n                {\n                    DisplayName = content;\n                    m_TopLevelGroup = ConnectionMajorGroup.ConnectionsWithoutID;\n                    OldConnectionFormat = true;\n                }\n            }\n\n            displayName = DisplayName + ProjectName;\n            id = GenerateID();\n            IsDevice = isDevice;\n            if (isDevice)\n            {\n                IconContent = ConnectionUIHelper.GetIcon(iconString);\n            }\n        }\n\n        public int GenerateID()\n        {\n            return (DisplayName + ProjectName + IP + Port).GetHashCode();\n        }\n\n        public bool DisplayProjectName()\n        {\n            return !IsDevice && !OldConnectionFormat &&\n                ConnectionMajorGroup.Direct != m_TopLevelGroup && ConnectionMajorGroup.Logging != m_TopLevelGroup;\n        }\n\n        public bool DisplayPort()\n        {\n            return !IsDevice && !OldConnectionFormat &&\n                ConnectionMajorGroup.Direct != m_TopLevelGroup && ConnectionMajorGroup.Logging != m_TopLevelGroup;\n        }\n\n        public bool DisplayIP()\n        {\n            return !IsDevice && !OldConnectionFormat &&\n                ConnectionMajorGroup.Direct != m_TopLevelGroup && ConnectionMajorGroup.Logging != m_TopLevelGroup;\n        }\n    }\n\n    enum ConnectionDropDownColumns\n    {\n        DisplayName,\n        ProjectName,\n        IP,\n        Port\n    }\n\n    internal class ConnectionDropDownMultiColumnHeader : MultiColumnHeader\n    {\n        public ConnectionDropDownMultiColumnHeader(MultiColumnHeaderState state) : base(state)\n        {\n        }\n\n        protected override void AddColumnHeaderContextMenuItems(GenericMenu menu)\n        {\n            base.AddColumnHeaderContextMenuItems(menu);\n            menu.menuItems.RemoveAt(0);\n        }\n    }\n\n    internal class ConnectionTreeView : TreeView\n    {\n        public List<ConnectionDropDownItem> dropDownItems = new List<ConnectionDropDownItem>(0);\n\n        public string search = \"\";\n        public float DisplayNameIndent => 2 * depthIndentWidth + ConnectionDropDownStyles.ToggleRectWidth + (2 * ConnectionDropDownStyles.SeparatorVerticalPadding) + ConnectionDropDownStyles.SeparatorLineWidth;\n        Action m_CloseWindow;\n\n        public ConnectionTreeView(TreeViewState state, ConnectionDropDownMultiColumnHeader multiColumnHeader, Action closeWindow) : base(state, multiColumnHeader)\n        {\n            showAlternatingRowBackgrounds = false;\n            baseIndent = 0;\n            depthIndentWidth = foldoutWidth;\n            rowHeight = 20f;\n            m_CloseWindow = closeWindow;\n        }\n\n        protected override TreeViewItem BuildRoot()\n        {\n            var root = new TreeViewItem { id = -1, depth = -1, displayName = \"Root\" };\n            foreach (var connectionType in dropDownItems.OrderBy(x => x.m_TopLevelGroup).GroupBy(x => x.m_TopLevelGroup))\n            {\n                if (connectionType.Key == ConnectionDropDownItem.ConnectionMajorGroup.Editor)\n                {\n                    foreach (var connectionDropDownItem in connectionType)\n                    {\n                        root.AddChild(connectionDropDownItem);\n                    }\n                    continue;\n                }\n                // connection major group\n                var i = new TreeViewItem { displayName = ConnectionDropDownItem.ConnectionMajorGroupLabels[(int)connectionType.Key]};\n                i.id = (i.displayName + root.displayName).GetHashCode();\n                root.AddChild(i);\n                foreach (var playerType in connectionType.Where(x => x.m_SubGroup != null).GroupBy(x => x.m_SubGroup).OrderBy(x => x.Key))\n                {\n                    // direct and preeasy id connections dont have any subgrouping\n                    if (i.displayName == ConnectionDropDownItem.ConnectionMajorGroupLabels[(int)ConnectionDropDownItem.ConnectionMajorGroup.Direct] ||\n                        i.displayName == ConnectionDropDownItem.ConnectionMajorGroupLabels[(int)ConnectionDropDownItem.ConnectionMajorGroup.ConnectionsWithoutID])\n                    {\n                        foreach (var player in playerType.OrderBy(x => x.DisplayName).Where(x => x.DisplayName.ToLower().Contains(search.ToLower())))\n                            i.AddChild(player);\n                        continue;\n                    }\n\n                    // if we match a top level group add all of its children and return\n                    if (string.Equals(i.displayName.ToLower(), search.ToLower(), StringComparison.Ordinal))\n                    {\n                        AddChildren(playerType, i);\n                        SetupDepthsFromParentsAndChildren(root);\n                        return root;\n                    }\n                    // if we match a player type add all of its children and continue\n                    if (string.Equals(playerType.Key.ToLower(), search.ToLower(), StringComparison.Ordinal))\n                    {\n                        AddChildren(playerType, i);\n                        continue;\n                    }\n\n                    AddChildren(playerType, i, search);\n                }\n\n                if (!i.hasChildren)\n                    root.children.Remove(i);\n            }\n            SetupDepthsFromParentsAndChildren(root);\n            return root;\n        }\n\n        TreeViewItem AddHeaderItem(string name, TreeViewItem item)\n        {\n            if (name == item.displayName) return item;\n\n            var newItem = new TreeViewItem { displayName = name, id = (name + item.parent.displayName).GetHashCode() };\n            item.AddChild(newItem);\n            return newItem;\n        }\n\n        void AddChildren(IGrouping<string, ConnectionDropDownItem> group, TreeViewItem treeViewItem, string filter = null)\n        {\n            if (filter == null)\n            {\n                var header = AddHeaderItem(group.Key, treeViewItem);\n                foreach (var player in group.OrderBy(x => x.DisplayName))\n                    header.AddChild(player);\n            }\n            else\n            {\n                var header = AddHeaderItem(group.Key, treeViewItem);\n                bool addedChild = false;\n                foreach (var player in group.Where(x => x.DisplayName.ToLower().Contains(filter.ToLower()))\n                         .OrderBy(x => x.DisplayName))\n                {\n                    addedChild = true;\n                    header.AddChild(player);\n                }\n\n                if (!addedChild && treeViewItem.hasChildren)\n                    treeViewItem.children.Remove(treeViewItem.children.Last());\n            }\n        }\n\n        protected override void SingleClickedItem(int id)\n        {\n            var t = dropDownItems.Find(x => x.id == id);\n            if (t is ConnectionDropDownItem && !t.m_Disabled)\n            {\n                t.m_OnSelected?.Invoke();\n                m_CloseWindow.Invoke();\n                EditorGUIUtility.ExitGUI();\n                return;\n            }\n\n            var item = FindItem(id, rootItem);\n            controller.UserInputChangedExpandedState(item, FindRowOfItem(item), !IsExpanded(id));\n        }\n\n        protected override void RowGUI(RowGUIArgs args)\n        {\n            var item = args.item;\n\n            if (item is ConnectionDropDownItem cddi)\n            {\n                GUI.enabled = !cddi.m_Disabled;\n                if (GUI.enabled && args.selected && Event.current.keyCode == KeyCode.Return)\n                {\n                    cddi.m_OnSelected?.Invoke();\n                    Repaint();\n                }\n            }\n\n            for (int i = 0; i < args.GetNumVisibleColumns(); ++i)\n            {\n                CellGUI(args.GetCellRect(i), item, (ConnectionDropDownColumns)args.GetColumn(i), ref args);\n            }\n            GUI.enabled = true;\n        }\n\n        void CellGUI(Rect cellRect, TreeViewItem item, ConnectionDropDownColumns column, ref RowGUIArgs args)\n        {\n            // Center cell rect vertically (makes it easier to place controls, icons etc in the cells)\n            CenterRectUsingSingleLineHeight(ref cellRect);\n            ConnectionDropDownItem cddi = null;\n            if (item is ConnectionDropDownItem downItem)\n                cddi = downItem;\n\n            switch (column)\n            {\n                case ConnectionDropDownColumns.DisplayName:\n                    if (cddi != null)\n                    {//actual connections\n                        var rect = cellRect;\n                        rect.x += GetContentIndent(item) - foldoutWidth;\n\n                        EditorGUI.BeginChangeCheck();\n                        rect.width = ConnectionDropDownStyles.ToggleRectWidth;\n                        var isConnected = cddi.m_Connected?.Invoke() ?? false;\n                        GUI.Label(rect, (isConnected ? EditorGUIUtility.IconContent(\"Valid\") : GUIContent.none));\n                        rect.x += ConnectionDropDownStyles.ToggleRectWidth;\n                        if (cddi.IsDevice)\n                        {\n                            EditorGUI.LabelField(new Rect(rect.x, rect.y, rowHeight, rowHeight), cddi.IconContent);\n                            rect.x += rowHeight;\n                        }\n                        var textRect = cellRect;\n                        textRect.x = rect.x;\n                        textRect.width = cellRect.width - (textRect.x - cellRect.x);\n\n                        GUI.Label(textRect, ConnectionUIHelper.TruncateString(cddi.DisplayName, ConnectionDropDownStyles.sTVLine, textRect.width));\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            cddi.m_OnSelected.Invoke();\n                        }\n                    }\n                    else\n                    {\n                        var r = cellRect;\n                        if (item.depth <= 0)\n                        {// major group headers\n                            if (args.row != 0)\n                                EditorGUI.DrawRect(new Rect(r.x, r.y, args.rowRect.width, 1f), ConnectionDropDownStyles.SeparatorColor);\n                            r.x += GetContentIndent(item);\n                            r.width = args.rowRect.width - GetContentIndent(item);\n                            GUI.Label(r, item.displayName, EditorStyles.boldLabel);\n                        }\n                        else\n                        {// sub group headers\n                            r.x += GetContentIndent(item);\n                            EditorGUI.LabelField(new Rect(r.x, r.y, rowHeight, rowHeight), ConnectionUIHelper.GetIcon(item.displayName));\n                            GUI.Label(new Rect(r.x + rowHeight, r.y, r.width - rowHeight, r.height), item.displayName, EditorStyles.miniBoldLabel);\n                        }\n                    }\n                    break;\n\n                case ConnectionDropDownColumns.ProjectName:\n                    if(item.depth > 1)\n                    {\n                        DrawVerticalSeparatorLine(cellRect);\n                        GUI.Label(cellRect, ConnectionUIHelper.TruncateString(cddi.ProjectName, ConnectionDropDownStyles.sTVLine, cellRect.width));\n\n                    }\n                    break;\n                case ConnectionDropDownColumns.IP:\n                    if(item.depth > 1)\n                    {\n                        DrawVerticalSeparatorLine(cellRect);\n                        GUI.Label(cellRect, ConnectionUIHelper.TruncateString(cddi.IP, ConnectionDropDownStyles.sTVLine, cellRect.width));\n                    }\n                    break;\n                case ConnectionDropDownColumns.Port:\n                    if(item.depth > 1)\n                    {\n                        DrawVerticalSeparatorLine(cellRect);\n                        GUI.Label(cellRect, ConnectionUIHelper.TruncateString(cddi.Port, ConnectionDropDownStyles.sTVLine, cellRect.width));\n                    }\n                    break;\n                default:\n                    throw new ArgumentOutOfRangeException(nameof(column), column, null);\n            }\n        }\n\n\n        private void DrawVerticalSeparatorLine(Rect cellRect)\n        {\n            EditorGUI.DrawRect(\n                new Rect(cellRect.x - 4, cellRect.y + ConnectionDropDownStyles.SeparatorVerticalPadding, ConnectionDropDownStyles.SeparatorLineWidth,\n                    cellRect.height - 2 * ConnectionDropDownStyles.SeparatorVerticalPadding), ConnectionDropDownStyles.SeparatorColor);\n        }\n\n        public float GetHeight()\n        {\n            if (dropDownItems.Count > 0)\n                return totalHeight;\n\n            return 0;\n        }\n    }\n\n    internal class ConnectionDropDownStyles\n    {\n        internal static float searchFieldPadding = 12f;\n        internal static float searchFieldVerticalSpacing = 12f;\n\n        internal static GUIStyle sConnectionTrouble = \"MenuItem\";\n        internal static GUIStyle sTVLine = \"TV Line\";\n\n        internal static readonly Color SeparatorColor = new Color(0.5f, 0.5f, 0.5f, 0.5f);\n        internal static int ToggleRectWidth = 16;\n        internal static float SeparatorLineWidth = 1f;\n        internal static float SeparatorVerticalPadding = 2f;\n        public static float troubleShootBtnPadding = 10f;\n    }\n\n    internal class ConnectionTreeViewWindow : PopupWindowContent\n    {\n        private ConnectionTreeView m_connectionTreeView;\n        private SearchField m_SearchField;\n\n        private ConnectionDropDownMultiColumnHeader multiColumnHeader;\n        private IConnectionStateInternal state;\n        private static MultiColumnHeaderState multiColumnHeaderState;\n        private static TreeViewState treeViewState;\n        private List<ConnectionDropDownItem> connectionItems;\n        private static bool firstOpen = true;\n        float loggingVerticalPadding = 3f;\n        float searchToLoggingPadding = 8f;\n        ConsoleWindow.ConsoleAttachToPlayerState consoleAttachToPlayerState;\n        bool didFocus;\n        Dictionary<int, bool> m_expandedState = new Dictionary<int, bool>();\n        bool searching;\n\n        public ConnectionTreeViewWindow(IConnectionStateInternal internalState, Rect rect)\n        {\n            state = internalState;\n            state.AddItemsToTree(this, rect);\n            if (multiColumnHeaderState == null)\n            {\n                treeViewState = new TreeViewState();\n                multiColumnHeaderState = CreateDefaultMultiColumnHeaderState(100);\n                multiColumnHeader = new ConnectionDropDownMultiColumnHeader(multiColumnHeaderState);\n                m_connectionTreeView = new ConnectionTreeView(treeViewState, multiColumnHeader, ClosePopUp) { dropDownItems = connectionItems };\n                SetMinColumnWidths();\n                return;\n            }\n\n            multiColumnHeader = new ConnectionDropDownMultiColumnHeader(multiColumnHeaderState);\n            m_connectionTreeView = new ConnectionTreeView(treeViewState, multiColumnHeader, ClosePopUp) { dropDownItems = connectionItems };\n        }\n\n        static class Content\n        {\n            private static GUIStyle style = MultiColumnHeader.DefaultStyles.columnHeader;\n            public static GUIContent PlayerName = new GUIContent(\"Player Name\");\n            public static float PlayerNameMinWidth = 150;\n            public static GUIContent ProjectName = new GUIContent(\"Product Name\");\n            public static float ProjectNameMinWidth = style.CalcSize(ProjectName).x;\n            public static GUIContent IP = new GUIContent(\"IP\");\n            public static float IPMinWidth = style.CalcSize(GUIContent.Temp(\"00000\")).x;\n            public static GUIContent Port = new GUIContent(\"Port\");\n            public static float PortMinWidth = style.CalcSize(GUIContent.Temp(\"00000\")).x;\n            public static GUIContent TroubleShoot = new GUIContent(\"Troubleshoot Connection Issues\");\n        }\n\n        void ClosePopUp()\n        {\n            this.editorWindow.Close();\n        }\n\n        public override void OnClose()\n        {\n            state = null;\n        }\n\n        internal void Reload()\n        {\n            if (m_connectionTreeView.dropDownItems.Count > 0)\n            {\n                m_connectionTreeView.Reload();\n            }\n        }\n\n        public override void OnOpen()\n        {\n            Reload();\n\n            if (firstOpen)\n                m_connectionTreeView.ExpandAll();\n\n            firstOpen = false;\n            m_SearchField = new SearchField();\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            EditorGUI.BeginChangeCheck();\n            m_connectionTreeView.search = m_SearchField.OnGUI(new Rect(rect.x + ConnectionDropDownStyles.searchFieldPadding, rect.y + ConnectionDropDownStyles.searchFieldPadding, rect.width - (2 * ConnectionDropDownStyles.searchFieldPadding), EditorGUI.kSingleLineHeight), m_connectionTreeView.search);\n\n            if (!didFocus && !m_SearchField.HasFocus())\n            {\n                m_SearchField.SetFocus();\n                didFocus = true;\n            }\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (!string.IsNullOrEmpty(m_connectionTreeView.search))\n                {\n                    if (!searching)\n                    {\n                        var rows = m_connectionTreeView.GetRows();\n                        m_expandedState.Clear();\n                        foreach (var row in rows)\n                        {\n                            m_expandedState.Add(row.id, m_connectionTreeView.IsExpanded(row.id));\n                        }\n                    }\n                    m_connectionTreeView.ExpandAll();\n                    searching = true;\n                }\n                else\n                {\n                    if (searching)\n                    {\n                        foreach (var b in m_expandedState)\n                        {\n                            m_connectionTreeView.SetExpanded(b.Key, b.Value);\n                        }\n                        searching = false;\n                    }\n\n                }\n\n                Reload();\n            }\n            rect.y += EditorGUI.kSingleLineHeight + ConnectionDropDownStyles.searchFieldVerticalSpacing;\n\n            if (consoleAttachToPlayerState != null)\n            {\n                rect.y += searchToLoggingPadding;\n                EditorGUI.BeginChangeCheck();\n                GUI.Toggle(new Rect(rect.x + ConnectionDropDownStyles.searchFieldPadding, rect.y, rect.width, EditorGUI.kSingleLineHeight), consoleAttachToPlayerState.IsConnected(), ConnectionUIHelper.Content.PlayerLogging);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    consoleAttachToPlayerState.PlayerLoggingOptionSelected();\n                }\n                rect.y += EditorGUI.kSingleLineHeight + loggingVerticalPadding;\n                GUI.enabled = consoleAttachToPlayerState.IsConnected();\n                m_connectionTreeView.dropDownItems.ForEach(x => x.m_Disabled = !GUI.enabled);\n\n                EditorGUI.BeginChangeCheck();\n                GUI.Toggle(new Rect(rect.x + ConnectionDropDownStyles.searchFieldPadding, rect.y, rect.width, EditorGUI.kSingleLineHeight), consoleAttachToPlayerState.IsLoggingFullLog(), ConnectionUIHelper.Content.FullLog);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    consoleAttachToPlayerState.FullLogOptionSelected();\n                }\n                rect.y += EditorGUI.kSingleLineHeight + loggingVerticalPadding;\n            }\n\n            m_connectionTreeView?.OnGUI(new Rect(rect.x, rect.y, rect.width, (float)m_connectionTreeView?.totalHeight));\n            rect.y += (float)m_connectionTreeView?.totalHeight;\n            GUI.enabled = true;\n\n            EditorGUI.DrawDelimiterLine(new Rect(rect.x,rect.y,rect.width,1f));\n            rect.y += 1f;\n            rect.y += ConnectionDropDownStyles.troubleShootBtnPadding / 2f;\n            if (EditorGUI.Button(rect, Content.TroubleShoot, ConnectionDropDownStyles.sConnectionTrouble))\n            {\n                var help = Help.FindHelpNamed(\"profiler-profiling-applications\");\n                Help.BrowseURL(help);\n            }\n\n            if(Event.current.type == EventType.MouseMove)\n                Event.current.Use();\n\n        }\n\n        private void SetMinColumnWidths()\n        {\n            foreach (var stateVisibleColumn in m_connectionTreeView.multiColumnHeader.state.visibleColumns)\n            {\n                m_connectionTreeView.multiColumnHeader.state.columns[stateVisibleColumn].width = GetLargestWidth(stateVisibleColumn);\n            }\n        }\n\n        public static MultiColumnHeaderState CreateDefaultMultiColumnHeaderState(float treeViewWidth)\n        {\n            var columns = new[]\n            {\n                new MultiColumnHeaderState.Column\n                {\n                    headerContent = Content.PlayerName,\n                    headerTextAlignment = TextAlignment.Left,\n                    autoResize = false,\n                    allowToggleVisibility = false,\n                    minWidth = Content.PlayerNameMinWidth,\n                    canSort = false\n                },\n                new MultiColumnHeaderState.Column\n                {\n                    headerContent = Content.ProjectName,\n                    headerTextAlignment = TextAlignment.Left,\n                    autoResize = false,\n                    allowToggleVisibility = true,\n                    minWidth = Content.ProjectNameMinWidth,\n                    canSort = false\n                },\n                new MultiColumnHeaderState.Column\n                {\n                    headerContent = Content.IP,\n                    headerTextAlignment = TextAlignment.Left,\n                    autoResize = false,\n                    allowToggleVisibility = true,\n                    minWidth = Content.IPMinWidth,\n                    canSort = false,\n                },\n                new MultiColumnHeaderState.Column\n                {\n                    headerContent = Content.Port,\n                    headerTextAlignment = TextAlignment.Left,\n                    autoResize = false,\n                    allowToggleVisibility = true,\n                    minWidth = Content.PortMinWidth,\n                    canSort = false\n                }\n            };\n\n            var state = new MultiColumnHeaderState(columns);\n            return state;\n        }\n\n        public void AddDisabledItem(ConnectionDropDownItem connectionDropDownItem)\n        {\n            connectionDropDownItem.m_Disabled = true;\n            AddItem(connectionDropDownItem);\n        }\n\n        public void AddItem(ConnectionDropDownItem connectionDropDownItem)\n        {\n            // *begin-nonstandard-formatting*\n            connectionItems ??= new List<ConnectionDropDownItem>();\n            // *end-nonstandard-formatting*\n\n            var dupes = connectionItems.FirstOrDefault(x => x.DisplayName == connectionDropDownItem.DisplayName && x.IP == connectionDropDownItem.IP && x.Port == connectionDropDownItem.Port);\n            if (dupes != null)\n                connectionItems.Remove(dupes);\n\n            connectionItems.Add(connectionDropDownItem);\n        }\n\n        public bool HasItem(string name)\n        {\n            return connectionItems != null && connectionItems.Any(x => x.DisplayName == name);\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            Vector2 v = Vector2.zero;\n            v.y +=  EditorGUI.kSingleLineHeight + ConnectionDropDownStyles.searchFieldVerticalSpacing; // search field\n            v.x = Mathf.Max(200, GetTotalVisibleWidth());\n            if (consoleAttachToPlayerState != null)\n            {\n                v.y += searchToLoggingPadding + 2 * (EditorGUI.kSingleLineHeight + loggingVerticalPadding);\n            }\n            v.y += GetTotalTreeViewHeight();\n            v.y += EditorGUI.kSingleLineHeight;\n            v.y += ConnectionDropDownStyles.troubleShootBtnPadding;\n            return v;\n        }\n\n        private float GetTotalTreeViewHeight()\n        {\n            return m_connectionTreeView.GetHeight();\n        }\n\n        float GetLargestWidth(int idx)\n        {\n            return idx switch\n            {\n                0 => GetRequiredDisplayNameColumnWidth(),\n                1 => GetRequiredProjectNameColumnWidth(),\n                2 => GetRequiredIPColumnWidth(),\n                3 => GetRequiredPortColumnWidth(),\n                _ => 0\n            };\n        }\n\n        private float GetRequiredProjectNameColumnWidth()\n        {\n            return Mathf.Max(Content.ProjectNameMinWidth,\n                connectionItems.Max(x => x.ProjectNameSize));\n        }\n\n        private float GetRequiredDisplayNameColumnWidth()\n        {\n            return Mathf.Max(Content.PlayerNameMinWidth,\n                connectionItems.Max(x => x.DisplayNameSize) + m_connectionTreeView.DisplayNameIndent );\n        }\n\n        private float GetRequiredIPColumnWidth()\n        {\n            return Mathf.Max(Content.IPMinWidth, connectionItems.Max(x => x.IPSize));\n        }\n\n        private float GetRequiredPortColumnWidth()\n        {\n            return Mathf.Max(Content.PortMinWidth, connectionItems.Max(x => x.PortSize));\n        }\n\n        float GetTotalVisibleWidth()\n        {\n            return m_connectionTreeView.multiColumnHeader.state.widthOfAllVisibleColumns;\n        }\n\n        //needed for tests\n        public int GetItemCount()\n        {\n            return m_connectionTreeView?.dropDownItems.Count ?? 0;\n        }\n\n        public void Clear()\n        {\n            m_connectionTreeView?.dropDownItems.Clear();\n        }\n\n        public void SetLoggingOptions(ConsoleWindow.ConsoleAttachToPlayerState state)\n        {\n            consoleAttachToPlayerState = state;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Networking/PlayerConnection/EditorConnection.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Events;\nusing UnityEngine.Networking.PlayerConnection;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Networking.PlayerConnection\n{\n    [Serializable]\n    public class ConnectedPlayer\n    {\n        public ConnectedPlayer()\n        {\n        }\n\n        public ConnectedPlayer(int playerId)\n        {\n            m_PlayerId = playerId;\n        }\n\n        public ConnectedPlayer(int playerId, string name)\n        {\n            m_PlayerId = playerId;\n            m_PlayerName = name;\n        }\n\n        [SerializeField]\n        private int m_PlayerId;\n\n        [SerializeField]\n        private string m_PlayerName;\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"Use playerId instead (UnityUpgradable) -> playerId\", true)]\n        public int PlayerId\n        {\n            get { return m_PlayerId; }\n        }\n\n        public int playerId\n        {\n            get { return m_PlayerId; }\n        }\n\n        public string name\n        {\n            get { return m_PlayerName; }\n        }\n    }\n\n    [Serializable]\n    public class EditorConnection : ScriptableSingleton<EditorConnection>, IEditorPlayerConnection\n    {\n        internal static IPlayerEditorConnectionNative connectionNative;\n\n        [SerializeField]\n        private PlayerEditorConnectionEvents m_PlayerEditorConnectionEvents = new PlayerEditorConnectionEvents();\n\n        [SerializeField]\n        private List<ConnectedPlayer> m_connectedPlayers = new List<ConnectedPlayer>();\n\n        public List<ConnectedPlayer> ConnectedPlayers\n        {\n            get { return m_connectedPlayers; }\n        }\n\n        public void Initialize()\n        {\n            GetEditorConnectionNativeApi().Initialize();\n        }\n\n        private void Cleanup()\n        {\n            UnregisterAllPersistedListeners(m_PlayerEditorConnectionEvents.connectionEvent);\n            UnregisterAllPersistedListeners(m_PlayerEditorConnectionEvents.disconnectionEvent);\n            m_PlayerEditorConnectionEvents.Clear();\n        }\n\n        private void UnregisterAllPersistedListeners(UnityEventBase connectionEvent)\n        {\n            var persistentEventCount = connectionEvent.GetPersistentEventCount();\n            for (int i = 0; i < persistentEventCount; i++)\n            {\n                connectionEvent.UnregisterPersistentListener(i);\n            }\n        }\n\n        private IPlayerEditorConnectionNative GetEditorConnectionNativeApi()\n        {\n            return connectionNative ?? new EditorConnectionInternal();\n        }\n\n        public void Register(Guid messageId, UnityAction<MessageEventArgs> callback)\n        {\n            if (messageId == Guid.Empty)\n            {\n                throw new ArgumentException(\"Cant be Guid.Empty\", \"messageId\");\n            }\n\n            if (!m_PlayerEditorConnectionEvents.messageTypeSubscribers.Any(x => x.MessageTypeId == messageId))\n            {\n                GetEditorConnectionNativeApi().RegisterInternal(messageId);\n            }\n\n            m_PlayerEditorConnectionEvents.AddAndCreate(messageId)\n                .AddPersistentListener(callback, UnityEventCallState.EditorAndRuntime);\n        }\n\n        public void Unregister(Guid messageId, UnityAction<MessageEventArgs> callback)\n        {\n            m_PlayerEditorConnectionEvents.UnregisterManagedCallback(messageId, callback);\n            if (!m_PlayerEditorConnectionEvents.messageTypeSubscribers.Any(x => x.MessageTypeId == messageId))\n            {\n                GetEditorConnectionNativeApi().UnregisterInternal(messageId);\n            }\n        }\n\n        public void RegisterConnection(UnityAction<int> callback)\n        {\n            foreach (var players in m_connectedPlayers)\n            {\n                callback.Invoke(players.playerId);\n            }\n            m_PlayerEditorConnectionEvents.connectionEvent.AddPersistentListener(callback, UnityEventCallState.EditorAndRuntime);\n        }\n\n        public void RegisterDisconnection(UnityAction<int> callback)\n        {\n            m_PlayerEditorConnectionEvents.disconnectionEvent.AddPersistentListener(callback, UnityEventCallState.EditorAndRuntime);\n        }\n\n        public void UnregisterConnection(UnityAction<int> callback)\n        {\n            m_PlayerEditorConnectionEvents.connectionEvent.RemovePersistentListener((UnityEngine.Object)callback.Target, callback.Method);\n        }\n\n        public void UnregisterDisconnection(UnityAction<int> callback)\n        {\n            m_PlayerEditorConnectionEvents.disconnectionEvent.RemovePersistentListener((UnityEngine.Object)callback.Target, callback.Method);\n        }\n\n        public void Send(Guid messageId, byte[] data, int playerId)\n        {\n            if (messageId == Guid.Empty)\n            {\n                throw new ArgumentException(\"Can not be Guid.Empty\", \"messageId\");\n            }\n\n            GetEditorConnectionNativeApi().SendMessage(messageId, data, playerId);\n        }\n\n        public void Send(Guid messageId, byte[] data)\n        {\n            Send(messageId, data, 0);\n        }\n\n        public bool TrySend(Guid messageId, byte[] data, int playerId)\n        {\n            if (messageId == Guid.Empty)\n            {\n                throw new ArgumentException(\"Can not be Guid.Empty\", \"messageId\");\n            }\n\n            return GetEditorConnectionNativeApi().TrySendMessage(messageId, data, playerId);\n        }\n\n        public bool TrySend(Guid messageId, byte[] data)\n        {\n            return TrySend(messageId, data, 0);\n        }\n\n        public void DisconnectAll()\n        {\n            GetEditorConnectionNativeApi().DisconnectAll();\n        }\n\n        [RequiredByNativeCode]\n        private static void MessageCallbackInternal(IntPtr data, UInt64 size, UInt64 guid, string messageId)\n        {\n            byte[] bytes = null;\n            if (size > 0)\n            {\n                bytes = new byte[size];\n                Marshal.Copy(data, bytes, 0, unchecked((int)size));\n            }\n\n            instance.m_PlayerEditorConnectionEvents.InvokeMessageIdSubscribers(new Guid(messageId), bytes, (int)guid);\n        }\n\n        [RequiredByNativeCode]\n        private static void ConnectedCallbackInternal(int playerId, string playerName)\n        {\n            instance.m_connectedPlayers.Add(new ConnectedPlayer(playerId, playerName));\n            instance.m_PlayerEditorConnectionEvents.connectionEvent.Invoke(playerId);\n        }\n\n        [RequiredByNativeCode]\n        private static void DisconnectedCallback(int playerId)\n        {\n            instance.m_connectedPlayers.RemoveAll(c => c.playerId == playerId);\n            instance.m_PlayerEditorConnectionEvents.disconnectionEvent.Invoke(playerId);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/OSUtil.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Platform/Interface/AppInfo.h\")]\n    [NativeHeader(\"Runtime/Utilities/FileUtilities.h\")]\n    internal static class OSUtil\n    {\n        [StaticAccessor(\"AppInfo\", StaticAccessorType.DoubleColon)]\n        public static extern string[] GetDefaultApps(string fileType);\n\n        [StaticAccessor(\"AppInfo\", StaticAccessorType.DoubleColon)]\n        public static extern string GetAppFriendlyName(string app);\n\n        [StaticAccessor(\"AppInfo\", StaticAccessorType.DoubleColon)]\n        public static extern string GetDefaultAppPath(string fileType);\n\n        [FreeFunction(\"GetUserAppCacheFolder\")]\n        public static extern string GetDefaultCachePath();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ObjectFactory.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Reflection;\nusing UnityEditor.SceneManagement;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.SceneManagement;\nusing UnityEngine.Scripting;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/ObjectFactory.h\")]\n    public static class ObjectFactory\n    {\n        const int kInvalidSceneHandle = 0;\n\n        [FreeFunction]\n        internal static extern void SmartResetObjectToDefault([NotNull] Object target);\n\n        [FreeFunction]\n        internal static extern void FinalizeObjectAndAwake([NotNull] Object target);\n\n        [FreeFunction(ThrowsException = true)]\n        static extern Object CreateDefaultInstance([NotNull] Type type);\n\n        [FreeFunction(ThrowsException = true)]\n        static extern Component AddDefaultComponent([NotNull] GameObject gameObject, [NotNull] Type type);\n\n        [FreeFunction]\n        static extern GameObject CreateDefaultGameObject(string name);\n\n        public static event Action<Component> componentWasAdded;\n\n        [RequiredByNativeCode]\n        static void InvokeComponentWasAdded(Component component)\n        {\n            if (componentWasAdded != null)\n                componentWasAdded(component);\n        }\n\n        static void CheckTypeValidity(Type type)\n        {\n            if (type.IsAbstract)\n            {\n                throw new ArgumentException(\"Abstract types can't be used in the ObjectFactory : \" + type.FullName);\n            }\n            if (Attribute.GetCustomAttribute(type, typeof(ExcludeFromObjectFactoryAttribute)) != null)\n            {\n                throw new ArgumentException(\"The type \" + type.FullName + \" is not supported by the ObjectFactory.\");\n            }\n        }\n\n        public static T CreateInstance<T>() where T : Object\n        {\n            return (T)CreateInstance(typeof(T));\n        }\n\n        public static Object CreateInstance(Type type)\n        {\n            CheckTypeValidity(type);\n            if (type == typeof(GameObject))\n            {\n                throw new ArgumentException(\"GameObject type must be created using ObjectFactory.CreateGameObject instead : \" + type.FullName);\n            }\n            if (type.IsSubclassOf(typeof(Component)))\n            {\n                throw new ArgumentException(\"Component type must be created using ObjectFactory.AddComponent instead : \" + type.FullName);\n            }\n            if (type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null) != null)\n            {\n                throw new ArgumentException(type.FullName + \" constructor is not accessible which prevent this type from being used in ObjectFactory.\");\n            }\n            var obj = CreateDefaultInstance(type);\n            return obj;\n        }\n\n        public static T AddComponent<T>(GameObject gameObject) where T : Component\n        {\n            return (T)AddComponent(gameObject, typeof(T));\n        }\n\n        public static Component AddComponent(GameObject gameObject, Type type)\n        {\n            CheckTypeValidity(type);\n            if (!type.IsSubclassOf(typeof(Component)))\n            {\n                throw new ArgumentException(\"Non-Component type must use ObjectFactory.CreateInstance instead : \" + type.FullName);\n            }\n            return AddDefaultComponent(gameObject, type);\n        }\n\n        public static GameObject CreateGameObject(Scene scene, HideFlags hideFlags, string name, params Type[] types)\n        {\n            if (!scene.IsValid())\n            {\n                throw new ArgumentException(\"Cannot create a GameObject to a null Scene.\");\n            }\n\n            //Internally, this sets the target scene that the scene points to.\n            EditorSceneManager.SetTargetSceneForNewGameObjects(scene);\n            var go = CreateGameObject(name, types);\n            go.hideFlags = hideFlags;\n            EditorSceneManager.ClearTargetSceneForNewGameObjects();\n            return go;\n        }\n\n        public static GameObject CreateGameObject(string name, params Type[] types)\n        {\n            var go = CreateDefaultGameObject(name);\n            go.SetActive(false);\n            foreach (var type in types)\n            {\n                AddComponent(go, type);\n            }\n            go.SetActive(true);\n            GameObjectUtility.SetDefaultParentForNewObject(go);\n            return go;\n        }\n\n        public static GameObject CreatePrimitive(PrimitiveType type)\n        {\n            var go = CreateGameObject(type.ToString(), typeof(MeshFilter), typeof(MeshRenderer));\n            go.SetActive(false);\n            switch (type)\n            {\n                case PrimitiveType.Sphere:\n                    go.GetComponent<MeshFilter>().sharedMesh = Resources.GetBuiltinResource<Mesh>(\"New-Sphere.fbx\");\n                    AddComponent<SphereCollider>(go);\n                    break;\n                case PrimitiveType.Capsule:\n                    go.GetComponent<MeshFilter>().sharedMesh = Resources.GetBuiltinResource<Mesh>(\"New-Capsule.fbx\");\n                    AddComponent<CapsuleCollider>(go);\n                    break;\n                case PrimitiveType.Cylinder:\n                    go.GetComponent<MeshFilter>().sharedMesh = Resources.GetBuiltinResource<Mesh>(\"New-Cylinder.fbx\");\n                    AddComponent<CapsuleCollider>(go);\n                    break;\n                case PrimitiveType.Cube:\n                    go.GetComponent<MeshFilter>().sharedMesh = Resources.GetBuiltinResource<Mesh>(\"Cube.fbx\");\n                    AddComponent<BoxCollider>(go);\n                    break;\n                case PrimitiveType.Plane:\n                    go.GetComponent<MeshFilter>().sharedMesh = Resources.GetBuiltinResource<Mesh>(\"New-Plane.fbx\");\n                    AddComponent<MeshCollider>(go);\n                    break;\n                case PrimitiveType.Quad:\n                    go.GetComponent<MeshFilter>().sharedMesh = Resources.GetBuiltinResource<Mesh>(\"Quad.fbx\");\n                    AddComponent<MeshCollider>(go);\n                    break;\n            }\n\n            var renderer = go.GetComponent<Renderer>();\n            renderer.material = Material.GetDefaultMaterial();\n            go.SetActive(true);\n            return go;\n        }\n\n        public static void PlaceGameObject(GameObject go, GameObject parent = null)\n        {\n            GOCreationCommands.Place(go, parent);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ObjectListArea.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor.VersionControl;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditorInternal;\nusing AssetReference = UnityEditorInternal.InternalEditorUtility.AssetReference;\nusing Object = UnityEngine.Object;\nusing RenameOverlay = UnityEditor.RenameOverlay<int>;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    internal class ObjectListAreaState\n    {\n        // Selection state\n        public List<int> m_SelectedInstanceIDs = new List<int>();\n        public int m_LastClickedInstanceID;     // Used for navigation\n        public bool m_HadKeyboardFocusLastEvent; // Needs to survive domain reloads to prevent setting selection on got keyboard focus\n\n        // Expanded instanceIDs\n        public List<int> m_ExpandedInstanceIDs = new List<int>();\n\n        // Rename state\n        public RenameOverlay m_RenameOverlay = new RenameOverlay();\n\n        // Create new asset state\n        public CreateAssetUtility m_CreateAssetUtility = new CreateAssetUtility();\n        public int m_NewAssetIndexInList = -1;\n\n        // Misc state\n        public Vector2 m_ScrollPosition;\n        public int m_GridSize = 64;\n\n        public void OnAwake()\n        {\n            // Clear state that should not survive closing/starting Unity\n            m_NewAssetIndexInList = -1;\n            m_RenameOverlay.Clear();\n            m_CreateAssetUtility = new CreateAssetUtility();\n        }\n    }\n\n\n    internal partial class ObjectListArea\n    {\n        static class Styles\n        {\n            public static readonly GUIStyle resultsLabel = new GUIStyle(\"OL ResultLabel\");\n            public static readonly GUIStyle resultsGridLabel = new GUIStyle(\"ProjectBrowserGridLabel\");\n            public static readonly GUIStyle resultsGrid = new GUIStyle(\"ObjectPickerResultsGrid\");\n            public static readonly GUIStyle groupHeaderMiddle = new GUIStyle(\"ProjectBrowserHeaderBgMiddle\");\n            public static readonly GUIStyle groupHeaderTop = new GUIStyle(\"ProjectBrowserHeaderBgTop\");\n            public static readonly GUIStyle groupHeaderLabel = new GUIStyle(\"Label\");\n            public static readonly GUIStyle groupHeaderLabelCount = new GUIStyle(\"MiniLabel\");\n            public static readonly GUIStyle groupFoldout = new GUIStyle(\"IN Foldout\");\n            public static readonly GUIStyle miniRenameField = new GUIStyle(\"OL MiniRenameField\");\n            public static readonly GUIStyle ping = new GUIStyle(\"OL Ping\");\n            public static readonly GUIStyle miniPing = new GUIStyle(\"OL MiniPing\");\n            public static readonly GUIStyle iconDropShadow = new GUIStyle(\"ProjectBrowserIconDropShadow\");\n            public static readonly GUIStyle textureIconDropShadow = new GUIStyle(\"ProjectBrowserTextureIconDropShadow\");\n            public static readonly GUIStyle iconAreaBg = new GUIStyle(\"ProjectBrowserIconAreaBg\");\n            public static readonly GUIStyle previewBg = new GUIStyle(\"ProjectBrowserPreviewBg\");\n            public static readonly GUIStyle subAssetBg = new GUIStyle(\"ProjectBrowserSubAssetBg\");\n            public static readonly GUIStyle subAssetBgOpenEnded = new GUIStyle(\"ProjectBrowserSubAssetBgOpenEnded\");\n            public static readonly GUIStyle subAssetBgCloseEnded = new GUIStyle(\"ProjectBrowserSubAssetBgCloseEnded\");\n            public static readonly GUIStyle subAssetBgMiddle = new GUIStyle(\"ProjectBrowserSubAssetBgMiddle\");\n            public static readonly GUIStyle subAssetExpandButton = new GUIStyle(\"ProjectBrowserSubAssetExpandBtn\");\n            public static readonly GUIStyle subAssetExpandButtonMedium = new GUIStyle(\"ProjectBrowserSubAssetExpandBtnMedium\");\n            public static readonly GUIStyle subAssetExpandButtonSmall = new GUIStyle(\"ProjectBrowserSubAssetExpandBtnSmall\");\n\n            public static readonly GUIContent maxmumItemCountInfo = EditorGUIUtility.TrTextContent(\"NOTE: Maximum item count is reached, not all items are shown. Narrow your search.\");\n        }\n\n        // State persisted across assembly reloads\n        ObjectListAreaState m_State;\n\n        // Key navigation\n        const int kHome = int.MinValue;\n        const int kEnd = int.MaxValue;\n        const int kPageDown = int.MaxValue - 1;\n        const int kPageUp = int.MinValue + 1;\n        int m_SelectionOffset = 0;\n\n        const float k_ListModeVersionControlOverlayPadding = 14f;\n        static bool s_VCEnabled = false;\n\n        PingData m_Ping = new PingData();\n\n        EditorWindow m_Owner;\n\n        public bool allowDragging { get; set; }\n        public bool allowRenaming { get; set; }\n        public bool allowMultiSelect { get; set; }\n        public bool allowDeselection { get; set; }\n        public bool allowFocusRendering { get; set; }\n        public bool allowBuiltinResources { get; set; }\n        public bool allowUserRenderingHook { get; set; }\n        public bool allowFindNextShortcut { get; set; }\n        public bool foldersFirst { get; set; }\n        int m_KeyboardControlID;\n\n        bool m_AllowRenameOnMouseUp = true;\n\n\n        Vector2 m_LastScrollPosition = new Vector2(0, 0);\n        double LastScrollTime = 0;\n\n        internal Texture m_SelectedObjectIcon = null;\n\n        protected LocalGroup m_LocalAssets;\n\n        // List of all available groups\n        List<Group> m_Groups;\n\n        // Layout\n        Rect m_TotalRect;\n        Rect m_VisibleRect;\n        const int kListLineHeight = 16;\n        private int m_pingIndex;\n\n        int m_MinIconSize = 32;\n        int m_MinGridSize = 16;\n        int m_MaxGridSize = 96;\n        bool m_AllowThumbnails = true;\n        const int kSpaceForScrollBar = 13;\n        int m_LeftPaddingForPinging = 0;\n        bool m_FrameLastClickedItem = false;\n\n        bool m_ShowLocalAssetsOnly = true;\n\n        double m_NextDirtyCheck = 0;\n\n        readonly SearchService.ProjectSearchSessionHandler m_SearchSessionHandler = new SearchService.ProjectSearchSessionHandler();\n\n        // Callbacks\n        System.Action m_RepaintWantedCallback;\n        System.Action<bool> m_ItemSelectedCallback;\n        System.Action m_KeyboardInputCallback;\n        System.Action m_GotKeyboardFocus;\n        System.Func<Rect, float> m_DrawLocalAssetHeader;\n\n        public System.Action repaintCallback                { get {return m_RepaintWantedCallback; } set {m_RepaintWantedCallback = value; }}\n        public System.Action<bool> itemSelectedCallback     { get {return m_ItemSelectedCallback; }  set {m_ItemSelectedCallback = value; }}\n        public System.Action keyboardCallback               { get {return m_KeyboardInputCallback; } set {m_KeyboardInputCallback = value; }}\n        public System.Action gotKeyboardFocus               { get {return m_GotKeyboardFocus; }      set {m_GotKeyboardFocus = value; }}\n        public System.Func<Rect, float> drawLocalAssetHeader { get {return m_DrawLocalAssetHeader; }  set {m_DrawLocalAssetHeader = value; }}\n\n        // Debug\n        static internal bool s_Debug = false;\n\n        public ObjectListArea(ObjectListAreaState state, EditorWindow owner, bool showNoneItem)\n        {\n            m_State = state;\n            m_Owner = owner;\n\n            m_LocalAssets = new LocalGroup(this, \"\", showNoneItem);\n\n            m_Groups = new List<Group>();\n            m_Groups.Add(m_LocalAssets);\n        }\n\n        public void ShowObjectsInList(int[] instanceIDs)\n        {\n            // Clear search, etc.\n            Init(m_TotalRect, HierarchyType.Assets, new SearchFilter(), false);\n\n            // Set list manually\n            m_LocalAssets.ShowObjectsInList(instanceIDs);\n        }\n\n        internal void ShowObjectsInList(int[] instanceIDs, string[] rootPaths)\n        {\n            // Clear search, etc.\n            Init(m_TotalRect, HierarchyType.Assets, new SearchFilter(), false);\n\n            // Set list manually\n            m_LocalAssets.ShowObjectsInList(instanceIDs, rootPaths);\n        }\n\n        // This method is being used by the EditorTests/Searching tests\n        public string[] GetCurrentVisibleNames()\n        {\n            var list = m_LocalAssets.GetVisibleNameAndInstanceIDs();\n            return list.Select(x => x.Key).ToArray();\n        }\n\n        public void Init(Rect rect, HierarchyType hierarchyType, SearchFilter searchFilter, bool checkThumbnails)\n        {\n            Init(rect, hierarchyType, searchFilter, checkThumbnails, SearchService.SearchSessionOptions.Default);\n        }\n\n        public void Init(Rect rect, HierarchyType hierarchyType, SearchFilter searchFilter, bool checkThumbnails, SearchService.SearchSessionOptions searchSessionOptions)\n        {\n            // Keep for debugging\n            //Debug.Log (\"Init ObjectListArea: \" + searchFilter);\n\n            m_TotalRect = m_VisibleRect = rect;\n\n            m_LocalAssets.UpdateFilter(hierarchyType, searchFilter, foldersFirst, searchSessionOptions);\n            m_LocalAssets.UpdateAssets();\n\n            if (checkThumbnails)\n                m_AllowThumbnails = ObjectsHaveThumbnails(hierarchyType, searchFilter, searchSessionOptions);\n            else\n                m_AllowThumbnails = true;\n\n            Repaint();\n\n            // Prepare data\n            SetupData(true);\n        }\n\n        internal void InitForSearch(Rect rect, HierarchyType hierarchyType, SearchFilter searchFilter, bool checkThumbnails, Func<string, int> assetToInstanceId)\n        {\n            InitForSearch(rect, hierarchyType, searchFilter, checkThumbnails, assetToInstanceId, SearchService.SearchSessionOptions.Default);\n        }\n\n        internal void InitForSearch(Rect rect, HierarchyType hierarchyType, SearchFilter searchFilter, bool checkThumbnails, Func<string, int> assetToInstanceId, SearchService.SearchSessionOptions searchSessionOptions)\n        {\n            var searchQuery = searchFilter.originalText;\n            if (string.IsNullOrEmpty(searchQuery))\n                searchQuery = searchFilter.FilterToSearchFieldString();\n\n            // Override Asset search here. For GameObjects, it is done in CachedFilteredHierarchy.cs\n            if (hierarchyType == HierarchyType.GameObjects)\n            {\n                Init(rect, hierarchyType, searchFilter, checkThumbnails, searchSessionOptions);\n                return;\n            }\n\n            var allResults = new List<string>();\n            if (searchFilter.IsSearching())\n            {\n                m_SearchSessionHandler.BeginSession(() =>\n                {\n                    return new SearchService.ProjectSearchContext\n                    {\n                        requiredTypeNames = searchFilter.classNames,\n                        requiredTypes = searchFilter.classNames.Select(name =>\n                            TypeCache.GetTypesDerivedFrom<Object>()\n                                .FirstOrDefault(t => name == t.FullName || name == t.Name)),\n                        searchFilter = searchFilter\n                    };\n                }, searchSessionOptions);\n                m_SearchSessionHandler.BeginSearch(searchQuery);\n                // Asynchronous searches return new results. Accumulate those results when using ShowObjectsInList.\n                var results = m_SearchSessionHandler.Search(searchQuery, newResults =>\n                {\n                    if (newResults == null || !searchFilter.IsSearching())\n                        return;\n                    allResults.AddRange(newResults);\n                    InitListAreaWithItems(rect, hierarchyType, searchFilter, checkThumbnails, allResults, assetToInstanceId, searchSessionOptions);\n                });\n                InitListAreaWithItems(rect, hierarchyType, searchFilter, checkThumbnails, results, assetToInstanceId, searchSessionOptions);\n                if (results != null)\n                    allResults.AddRange(results);\n                m_SearchSessionHandler.EndSearch();\n            }\n            else\n            {\n                m_SearchSessionHandler.EndSession();\n                // Call default implementation when not searching\n                Init(rect, hierarchyType, searchFilter, checkThumbnails, searchSessionOptions);\n            }\n        }\n\n        void InitListAreaWithItems(Rect rect, HierarchyType hierarchyType, SearchFilter searchFilter, bool checkThumbnails, IEnumerable<string> items, Func<string, int> assetToInstanceId, SearchService.SearchSessionOptions searchSessionOptions)\n        {\n            // When items is null, we fallback to default implementation. Current default search engine returns null.\n            Init(rect, hierarchyType, items == null ? searchFilter : new SearchFilter(), checkThumbnails, searchSessionOptions);\n            if (items != null && hierarchyType == HierarchyType.Assets)\n            {\n                // We only support assets under \"Assets\" and \"Packages\"\n                var instanceIdSet = new HashSet<int>();\n                var uniqueInstanceIds = new List<int>();\n                var rootPaths = new List<string>();\n                var itemsTaken = 0;\n                foreach (var path in items)\n                {\n                    if (string.IsNullOrEmpty(path))\n                        continue;\n\n                    var reformattedPath = path.Replace('\\\\', '/');\n\n                    var rootPath = \"\";\n                    if (reformattedPath.StartsWith(\"Assets\"))\n                        rootPath = \"Assets\";\n                    else if (reformattedPath.StartsWith(\"Packages\"))\n                    {\n                        var secondSlashIndex = reformattedPath.IndexOf('/', \"Packages\".Length + 1);\n                        rootPath = secondSlashIndex == -1 ? reformattedPath : reformattedPath.Substring(0, secondSlashIndex);\n                    }\n                    else\n                        continue;\n\n                    // We don't support showing root folders\n                    if (reformattedPath == rootPath)\n                        continue;\n\n                    var instanceId = assetToInstanceId(reformattedPath);\n                    if (instanceId == 0)\n                        continue;\n\n                    if (instanceIdSet.Add(instanceId))\n                    {\n                        uniqueInstanceIds.Add(instanceId);\n                        rootPaths.Add(rootPath);\n                        ++itemsTaken;\n                    }\n\n                    if (itemsTaken >= FilteredHierarchy.maxSearchAddCount)\n                        break;\n                }\n                ShowObjectsInList(uniqueInstanceIds.ToArray(), rootPaths.ToArray());\n            }\n        }\n\n        bool HasFocus()\n        {\n            if (!allowFocusRendering)\n                return true;\n            return m_KeyboardControlID == GUIUtility.keyboardControl && m_Owner.m_Parent.hasFocus;\n        }\n\n        internal float GetVisibleWidth()\n        {\n            return m_VisibleRect.width;\n        }\n\n        public float m_SpaceBetween = 6f;\n        public float m_TopMargin = 10f;\n        public float m_BottomMargin = 10f;\n        public float m_RightMargin = 10f;\n        public float m_LeftMargin = 10f;\n\n        public void OnGUI(Rect position, int keyboardControlID)\n        {\n            s_VCEnabled = VersionControlUtils.isVersionControlConnected;\n\n            Event evt = Event.current;\n\n            m_TotalRect = position;\n\n            FrameLastClickedItemIfWanted();\n\n            // Background\n            GUI.Label(m_TotalRect, GUIContent.none, Styles.iconAreaBg);\n\n            // For keyboard focus handling (for Tab support and rendering of keyboard focus state)\n            m_KeyboardControlID = keyboardControlID;\n\n            // Grab keyboard focus on mousedown in entire rect\n            if (evt.type == EventType.MouseDown && position.Contains(Event.current.mousePosition))\n            {\n                GUIUtility.keyboardControl = m_KeyboardControlID;\n                m_AllowRenameOnMouseUp = true; // Reset on mouse down\n\n                Repaint(); // Ensure repaint so we can show we have keyboard focus\n            }\n\n            bool hasKeyboardFocus = m_KeyboardControlID == GUIUtility.keyboardControl;\n            if (hasKeyboardFocus != m_State.m_HadKeyboardFocusLastEvent)\n            {\n                m_State.m_HadKeyboardFocusLastEvent = hasKeyboardFocus;\n\n                // We got focus\n                if (hasKeyboardFocus)\n                {\n                    if (evt.type == EventType.MouseDown)\n                        m_AllowRenameOnMouseUp = false; // If we got focus by mouse down then we do not want to begin renaming if clicking on an already selected item\n\n                    if (m_GotKeyboardFocus != null)\n                        m_GotKeyboardFocus();\n                }\n            }\n\n            // For key navigation: Auto set selection to first element if selection is not shown currently when tabbing\n            if (evt.keyCode == KeyCode.Tab && evt.type == EventType.KeyDown && !hasKeyboardFocus && !IsShowingAny(GetSelection()))\n            {\n                AssetReference firstAssetReference;\n                if (m_LocalAssets.AssetReferenceAtIndex(0, out firstAssetReference))\n                {\n                    m_LocalAssets.GetNewSelection(ref firstAssetReference, false, false);\n                    Selection.activeInstanceID = firstAssetReference.instanceID;\n                }\n            }\n\n\n            HandleKeyboard(true);\n            HandleZoomScrolling();\n            HandleListArea();\n            DoOffsetSelection();\n            HandleUnusedEvents();\n        }\n\n        void FrameLastClickedItemIfWanted()\n        {\n            if (m_FrameLastClickedItem && Event.current.type == EventType.Repaint)\n            {\n                m_FrameLastClickedItem = false;\n                double timeSinceLastDraw = EditorApplication.timeSinceStartup - m_LocalAssets.m_LastClickedDrawTime;\n                if (m_State.m_SelectedInstanceIDs.Count > 0 && timeSinceLastDraw < 0.2)\n                    Frame(m_State.m_LastClickedInstanceID, true, false);\n            }\n        }\n\n        void HandleUnusedEvents()\n        {\n            if (allowDeselection && Event.current.type == EventType.MouseDown && Event.current.button == 0 && m_TotalRect.Contains(Event.current.mousePosition))\n                SetSelection(new int[0], false);\n        }\n\n        internal Vector2 sizeUsedForCroppingName;\n\n        public bool CanShowThumbnails()\n        {\n            //\n            //      return m_AllowThumbnails;\n            // #else\n            return m_AllowThumbnails;\n            //\n        }\n\n        public int gridSize\n        {\n            get { return m_State.m_GridSize; }\n            set\n            {\n                if (m_State.m_GridSize != value)\n                {\n                    m_State.m_GridSize = value;\n                    m_FrameLastClickedItem = true;\n                }\n            }\n        }\n\n        public int minGridSize\n        {\n            get { return m_MinGridSize; }\n        }\n        public int maxGridSize\n        {\n            get { return m_MaxGridSize; }\n        }\n\n\n        public int numItemsDisplayed\n        {\n            get { return m_LocalAssets.ItemCount; }\n        }\n\n        bool ObjectsHaveThumbnails(HierarchyType type, SearchFilter searchFilter, SearchService.SearchSessionOptions searchSessionOptions)\n        {\n            // Check if we have any built-ins, if so we have thumbs since all builtins have thumbs\n            if (m_LocalAssets.HasBuiltinResources)\n                return true;\n\n            // Check if current hierarchy have thumbs\n            FilteredHierarchy hierarchy = new FilteredHierarchy(type, searchSessionOptions);\n            hierarchy.searchFilter = searchFilter;\n            IHierarchyProperty assetProperty = FilteredHierarchyProperty.CreateHierarchyPropertyForFilter(hierarchy);\n            int[] empty = new int[0];\n            if (assetProperty.CountRemaining(empty) == 0)\n                return true;\n\n            assetProperty.Reset();\n            while (assetProperty.Next(empty))\n            {\n                if (assetProperty.hasFullPreviewImage)\n                    return true;\n            }\n\n            return false;\n        }\n\n        internal void OnDestroy()\n        {\n            AssetPreview.DeletePreviewTextureManagerByID(GetAssetPreviewManagerID());\n        }\n\n        public void Repaint()\n        {\n            if (m_RepaintWantedCallback != null)\n                m_RepaintWantedCallback();\n        }\n\n        public void OnEvent()\n        {\n            GetRenameOverlay().OnEvent();\n        }\n\n        CreateAssetUtility GetCreateAssetUtility()\n        {\n            return m_State.m_CreateAssetUtility;\n        }\n\n        internal RenameOverlay GetRenameOverlay()\n        {\n            return m_State.m_RenameOverlay;\n        }\n\n        internal void BeginNamingNewAsset(string newAssetName, int instanceID, bool isCreatingNewFolder)\n        {\n            m_State.m_NewAssetIndexInList = m_LocalAssets.IndexOfNewText(newAssetName, isCreatingNewFolder, foldersFirst);\n            if (m_State.m_NewAssetIndexInList != -1)\n            {\n                Frame(instanceID, true, false);\n                GetRenameOverlay().BeginRename(newAssetName, instanceID, 0f);\n            }\n            else\n            {\n                Debug.LogError(\"Failed to insert new asset into list\");\n            }\n\n            Repaint();\n        }\n\n        public bool BeginRename(float delay)\n        {\n            if (!allowRenaming)\n                return false;\n\n            // Only allow renaming when one item is selected\n            if (m_State.m_SelectedInstanceIDs.Count != 1)\n                return false;\n            int instanceID = m_State.m_SelectedInstanceIDs[0];\n            if (!InternalEditorUtility.CanRenameAsset(instanceID))\n                return false;\n\n            string name = m_LocalAssets.GetNameOfLocalAsset(instanceID);\n\n            return GetRenameOverlay().BeginRename(name, instanceID, delay);\n        }\n\n        public void EndRename(bool acceptChanges)\n        {\n            if (GetRenameOverlay().IsRenaming())\n            {\n                GetRenameOverlay().EndRename(acceptChanges);\n                RenameEnded();\n            }\n        }\n\n        void RenameEnded()\n        {\n            // We are done renaming (user accepted/rejected, we lost focus etc, other grabbed renameOverlay etc.)\n            string name = string.IsNullOrEmpty(GetRenameOverlay().name) ? GetRenameOverlay().originalName : GetRenameOverlay().name;\n            int instanceID = GetRenameOverlay().userData; // we passed in an instanceID as userData\n\n            try\n            {\n                // Are we creating new asset?\n                if (GetCreateAssetUtility().IsCreatingNewAsset())\n                {\n                    if (GetRenameOverlay().userAcceptedRename)\n                        GetCreateAssetUtility().EndNewAssetCreation(name);\n                    else\n                        GetCreateAssetUtility().EndNewAssetCreationCanceled(name);\n                }\n                else // renaming existing asset\n                {\n                    if (GetRenameOverlay().userAcceptedRename)\n                    {\n                        ObjectNames.SetNameSmartWithInstanceID(instanceID, name);\n                    }\n                }\n\n                if (GetRenameOverlay().HasKeyboardFocus())\n                    GUIUtility.keyboardControl = m_KeyboardControlID;\n\n                if (GetRenameOverlay().userAcceptedRename)\n                {\n                    Frame(instanceID, true, false); // frames existing assets (new ones could have instanceID 0)\n                }\n            }\n            catch (UnityException)\n            {\n                // Any UnityException reported by the asset database is already printed in the console.\n                GUIUtility.keyboardControl = m_KeyboardControlID;\n            }\n            finally\n            {\n                ClearRenameState();\n            }\n        }\n\n        void ClearRenameState()\n        {\n            // Cleanup\n            GetRenameOverlay().Clear();\n            GetCreateAssetUtility().Clear();\n            m_State.m_NewAssetIndexInList = -1;\n        }\n\n        internal void HandleRenameOverlay()\n        {\n            if (GetRenameOverlay().IsRenaming())\n            {\n                GUIStyle renameStyle = (IsListMode() ? null : Styles.miniRenameField);\n                if (!GetRenameOverlay().OnGUI(renameStyle))\n                {\n                    RenameEnded();\n                    GUIUtility.ExitGUI(); // We exit gui because we are iterating items and when we end naming a new asset this will change the order of items we are iterating.\n                }\n            }\n        }\n\n        public bool IsSelected(int instanceID)\n        {\n            return m_State.m_SelectedInstanceIDs.Contains(instanceID);\n        }\n\n        public int[] GetSelection()\n        {\n            return m_State.m_SelectedInstanceIDs.ToArray();\n        }\n\n        public bool IsLastClickedItemVisible()\n        {\n            return GetSelectedAssetIdx() >= 0;\n        }\n\n        public void SelectAll()\n        {\n            List<int> instanceIDs;\n            List<string> guids;\n            m_LocalAssets.GetAssetReferences(out instanceIDs, out guids);\n            if (instanceIDs.Count != 0)\n            {\n                var selectedInstanceIDs = InternalEditorUtility.TryGetInstanceIds(instanceIDs, guids, 0, instanceIDs.Count - 1);\n                if (selectedInstanceIDs == null)\n                {\n                    Debug.Log(\"Cannot select all because some assets being selected are in progress of being imported\");\n                    return;\n                }\n            }\n            SetSelection(instanceIDs.ToArray(), false);\n        }\n\n        public void SetSelection(int[] selectedInstanceIDs, bool doubleClicked)\n        {\n            InitSelection(selectedInstanceIDs);\n\n            if (m_ItemSelectedCallback != null)\n            {\n                Repaint();\n                m_ItemSelectedCallback(doubleClicked);\n            }\n        }\n\n        public void InitSelection(int[] selectedInstanceIDs)\n        {\n            // Note that selectedInstanceIDs can be gameObjects\n            m_State.m_SelectedInstanceIDs = new List<int>(selectedInstanceIDs);\n\n            // Keep for debugging\n            //Debug.Log (\"InitSelection (ObjectListArea): new selection \" + DebugUtils.ListToString(m_State.m_SelectedInstanceIDs));\n\n            if (m_State.m_SelectedInstanceIDs.Count > 0)\n            {\n                // Only init last clicked instance if it is NOT part of our selection (we need it for navigation)\n                if (!m_State.m_SelectedInstanceIDs.Contains(m_State.m_LastClickedInstanceID))\n                    m_State.m_LastClickedInstanceID = m_State.m_SelectedInstanceIDs[m_State.m_SelectedInstanceIDs.Count - 1];\n            }\n            else\n            {\n                m_State.m_LastClickedInstanceID = 0;\n            }\n        }\n\n        void HandleZoomScrolling()\n        {\n            if (EditorGUI.actionKey && Event.current.type == EventType.ScrollWheel && m_TotalRect.Contains(Event.current.mousePosition))\n            {\n                int sign = Event.current.delta.y > 0 ? -1 : 1;\n                gridSize = Mathf.Clamp(gridSize + sign * 7, minGridSize, maxGridSize);\n\n                if (sign < 0 && gridSize < m_MinIconSize)\n                    gridSize = m_MinGridSize;\n                if (sign > 0 && gridSize < m_MinIconSize)\n                    gridSize = m_MinIconSize;\n\n                Event.current.Use();\n                GUI.changed = true;\n            }\n        }\n\n        bool IsPreviewIconExpansionModifierPressed()\n        {\n            return Event.current.alt;\n        }\n\n        bool AllowLeftRightArrowNavigation()\n        {\n            bool gridMode = !m_LocalAssets.ListMode && !IsPreviewIconExpansionModifierPressed();\n            bool validItemCount = !m_ShowLocalAssetsOnly || (m_LocalAssets.ItemCount > 1);\n            return gridMode && validItemCount;\n        }\n\n        public void HandleKeyboard(bool checkKeyboardControl)\n        {\n            // Are we allowed to handle keyboard events?\n            if (checkKeyboardControl && GUIUtility.keyboardControl != m_KeyboardControlID || !GUI.enabled)\n                return;\n\n            // Let client handle keyboard first\n            if (m_KeyboardInputCallback != null)\n                m_KeyboardInputCallback();\n\n            // Now default list area handling\n            if (Event.current.type == EventType.KeyDown)\n            {\n                int offset = 0;\n\n                if (IsLastClickedItemVisible())\n                {\n                    switch (Event.current.keyCode)\n                    {\n                        case KeyCode.UpArrow:\n                            offset = -m_LocalAssets.m_Grid.columns; // we assume that all groups have same number of columns\n                            break;\n                        case KeyCode.DownArrow:\n                            offset = m_LocalAssets.m_Grid.columns;\n                            break;\n                        case KeyCode.LeftArrow:\n                            if (AllowLeftRightArrowNavigation())\n                                offset = -1;\n                            break;\n                        case KeyCode.RightArrow:\n                            if (AllowLeftRightArrowNavigation())\n                                offset = 1;\n                            break;\n                        case KeyCode.Home:\n                            offset = kHome;\n                            break;\n                        case KeyCode.End:\n                            offset = kEnd;\n                            break;\n                        case KeyCode.PageUp:\n                            offset = kPageUp;\n                            break;\n                        case KeyCode.PageDown:\n                            offset = kPageDown;\n                            break;\n                    }\n                }\n                else\n                {\n                    // Select first on any key navigation events if not selection is present\n                    bool validNavigationKey = false;\n                    switch (Event.current.keyCode)\n                    {\n                        case KeyCode.LeftArrow:\n                        case KeyCode.RightArrow:\n                            validNavigationKey = AllowLeftRightArrowNavigation();\n                            break;\n\n                        case KeyCode.UpArrow:\n                        case KeyCode.DownArrow:\n                        case KeyCode.Home:\n                        case KeyCode.End:\n                        case KeyCode.PageUp:\n                        case KeyCode.PageDown:\n                            validNavigationKey = true;\n                            break;\n                    }\n\n                    if (validNavigationKey)\n                    {\n                        SelectFirst();\n                        Event.current.Use();\n                    }\n                }\n\n                if (offset != 0)\n                {\n                    // If nothing is selected then select first object and ignore the offset (when showing none GetSelectedAssetIdx return -1)\n                    if (GetSelectedAssetIdx() < 0 && !m_LocalAssets.ShowNone)\n                        SetSelectedAssetByIdx(0);\n                    else\n                        m_SelectionOffset = offset;\n\n                    Event.current.Use();\n                    GUI.changed = true;\n                }\n                else\n                {\n                    if (allowFindNextShortcut && m_LocalAssets.DoCharacterOffsetSelection())\n                        Event.current.Use();\n                }\n            }\n        }\n\n        void DoOffsetSelectionSpecialKeys(int idx, int maxIndex)\n        {\n            float itemHeight = m_LocalAssets.m_Grid.itemSize.y + m_LocalAssets.m_Grid.verticalSpacing;\n            int columns = m_LocalAssets.m_Grid.columns;\n\n            switch (m_SelectionOffset)\n            {\n                case kPageUp:\n                    // on OSX paging only scrolls the scrollbar\n                    if (Application.platform == RuntimePlatform.OSXEditor)\n                    {\n                        m_State.m_ScrollPosition.y -= m_TotalRect.height;\n                        m_SelectionOffset = 0;\n                    }\n                    else\n                    {\n                        m_SelectionOffset = -Mathf.RoundToInt(m_TotalRect.height / itemHeight) * columns;\n                        // we want it to go to the very top row, but stay on same column\n                        m_SelectionOffset = Mathf.Max(-Mathf.FloorToInt(idx / (float)columns) * columns, m_SelectionOffset);\n                    }\n                    break;\n                case kPageDown:\n                    // on OSX paging only scrolls the scrollbar\n                    if (Application.platform == RuntimePlatform.OSXEditor)\n                    {\n                        m_State.m_ScrollPosition.y += m_TotalRect.height;\n                        m_SelectionOffset = 0;\n                    }\n                    else\n                    {\n                        m_SelectionOffset = Mathf.RoundToInt(m_TotalRect.height / itemHeight) * columns;\n                        // we want it to go to the very bottom row, but stay on same column\n                        int remainingItems = maxIndex - idx;\n                        m_SelectionOffset = Mathf.Min(Mathf.FloorToInt(remainingItems / (float)columns) * columns, m_SelectionOffset);\n                    }\n                    break;\n                case kHome:\n                    m_SelectionOffset = 0;\n                    SetSelectedAssetByIdx(0); // assumes that 'none' is the first item\n                    return;\n                case kEnd:\n                    m_SelectionOffset = maxIndex - idx;\n                    break;\n            }\n        }\n\n        void DoOffsetSelection()\n        {\n            if (m_SelectionOffset == 0)\n                return;\n\n            int maxGridIndex = GetMaxIdx();\n            if (maxGridSize == -1)\n                return; // no items\n\n            int selectedAssetIdx = GetSelectedAssetIdx();\n            selectedAssetIdx = selectedAssetIdx < 0 ? 0 : selectedAssetIdx; // default to first item\n\n            DoOffsetSelectionSpecialKeys(selectedAssetIdx, maxGridIndex);\n\n            // Special keys on some OSs will simply scroll and not change selection\n            if (m_SelectionOffset == 0)\n                return;\n\n            int newGridIdx = selectedAssetIdx + m_SelectionOffset;\n            m_SelectionOffset = 0;\n\n            // We ignore the offset if newIdx is less than 0 or clamp to item list length.\n            // This ensures that we stay on the same column at top or jump to the last item when navigating with keys.\n            if (newGridIdx < 0)\n                newGridIdx = selectedAssetIdx;\n            else\n                newGridIdx = Mathf.Min(newGridIdx, maxGridIndex);\n\n            // If newIdx is on one of the two bottom rows we scroll to the bottom row because we might jump to another row\n            // when navigating (because the last row is half empty). This is a usability decision and can be removed.\n            int scrollGridIdx = newGridIdx;\n            //if (newGridIdx >= m_Columns * m_Rows - m_Columns * 2)\n            //  scrollGridIdx = maxGridIndex + 2 * m_Columns;\n\n            SetSelectedAssetByIdx(scrollGridIdx);\n        }\n\n        public void OffsetSelection(int selectionOffset)\n        {\n            m_SelectionOffset = selectionOffset;\n        }\n\n        public void SelectFirst()\n        {\n            int startIndex = 0;\n            if (m_ShowLocalAssetsOnly && m_LocalAssets.ShowNone && m_LocalAssets.ItemCount > 1)\n                startIndex = 1;\n            SetSelectedAssetByIdx(startIndex);\n        }\n\n        void SetSelectedAssetByIdx(int selectedIdx)\n        {\n            // instanceID can be 0 if 'None' item is at index\n            AssetReference assetReference;\n            if (m_LocalAssets.AssetReferenceAtIndex(selectedIdx, out assetReference))\n            {\n                Rect r = m_LocalAssets.m_Grid.CalcRect(selectedIdx, 0f);\n                ScrollToPosition(AdjustRectForFraming(r));\n                Repaint();\n\n                int[] newSelection;\n                if (IsLocalAssetsCurrentlySelected())\n                    newSelection = m_LocalAssets.GetNewSelection(ref assetReference, false, true).ToArray(); // Handle multi selection\n                else\n                    newSelection = m_LocalAssets.GetNewSelection(ref assetReference, false, false).ToArray();\n\n                SetSelection(newSelection, false);\n                m_State.m_LastClickedInstanceID = assetReference.instanceID;\n            }\n        }\n\n        void Reveal(int instanceID)\n        {\n            if (!AssetDatabase.Contains(instanceID))\n                return;\n\n            // We only show one level of subassets so just expand parent asset\n            int mainAssetInstanceID = AssetDatabase.GetMainAssetInstanceID(AssetDatabase.GetAssetPath(instanceID));\n            bool isSubAsset = mainAssetInstanceID != instanceID;\n            if (isSubAsset)\n                m_LocalAssets.ChangeExpandedState(mainAssetInstanceID, true);\n        }\n\n        // Frames only local assets\n        public bool Frame(int instanceID, bool frame, bool ping)\n        {\n            int index = -1;\n\n            // Check if it is an asset we are creating\n            if (GetCreateAssetUtility().IsCreatingNewAsset() && m_State.m_NewAssetIndexInList != -1)\n                if (GetCreateAssetUtility().instanceID == instanceID)\n                    index = m_State.m_NewAssetIndexInList;\n\n            // Ensure instanceID is visible\n            if (frame)\n                Reveal(instanceID);\n\n            // Check local assets\n            if (index == -1)\n                index = m_LocalAssets.IndexOf(instanceID);\n\n            if (index != -1)\n            {\n                if (frame)\n                {\n                    float yOffset = 0f;\n                    Rect r = m_LocalAssets.m_Grid.CalcRect(index, yOffset);\n                    CenterRect(AdjustRectForFraming(r));\n                    Repaint();\n                }\n\n                if (ping)\n                    BeginPing(instanceID);\n                return true;\n            }\n\n            return false;\n        }\n\n        int GetSelectedAssetIdx()\n        {\n            // Find index of selection\n            int offsetIdx = m_LocalAssets.IndexOf(m_State.m_LastClickedInstanceID);\n            if (offsetIdx != -1)\n                return offsetIdx;\n            return -1;\n        }\n\n        bool SkipGroup(Group group)\n        {\n            // We show local assets here\n            if (!m_ShowLocalAssetsOnly)\n            {\n                if (group is LocalGroup)\n                    return true;\n            }\n\n            return false;\n        }\n\n        int GetMaxIdx()\n        {\n            int groupLastIdx = 0;\n            int groupSizesAccumulated = 0;\n            int lastGroupSize = 0;\n\n            foreach (Group g in m_Groups)\n            {\n                if (SkipGroup(g))\n                    continue;\n\n                if (!g.Visible)\n                    continue;\n\n                groupSizesAccumulated += lastGroupSize;\n                lastGroupSize = g.m_Grid.rows * g.m_Grid.columns;\n                groupLastIdx = g.ItemCount - 1;\n            }\n            int max = groupSizesAccumulated + groupLastIdx;\n            return (lastGroupSize + max) == 0 ? -1 : max;\n        }\n\n        bool IsLocalAssetsCurrentlySelected()\n        {\n            int currentSelectedInstanceID = m_State.m_SelectedInstanceIDs.FirstOrDefault();\n            if (currentSelectedInstanceID != 0)\n            {\n                int index = m_LocalAssets.IndexOf(currentSelectedInstanceID);\n                return index != -1;\n            }\n\n            return false;\n        }\n\n        private void SetupData(bool forceReflow)\n        {\n            // Make sure the groups contains the correct assets to show\n            foreach (Group g in m_Groups)\n            {\n                if (SkipGroup(g))\n                    continue;\n                g.UpdateAssets();\n            }\n\n            if (forceReflow || Event.current.type == EventType.Repaint)\n            {\n                // Reflow according to number of items, scrollbar presence, item dims etc.\n                Reflow();\n            }\n        }\n\n        bool IsObjectSelector()\n        {\n            // ShowNone is only used in object select window\n            return m_LocalAssets.ShowNone;\n        }\n\n        void HandleListArea()\n        {\n            SetupData(false);\n\n            // Figure out height needed to contain all assets\n            float totalContentsHeight = 0f;\n            foreach (Group g in m_Groups)\n            {\n                if (SkipGroup(g))\n                    continue;\n\n                totalContentsHeight += g.Height;\n\n                // ShowNone is only used in object select window\n                if (m_LocalAssets.ShowNone)\n                    break;\n            }\n\n            bool maxItemsReached = m_LocalAssets.projectItemCount >= FilteredHierarchy.maxSearchAddCount;\n            if (maxItemsReached)\n                totalContentsHeight += 45;\n\n            Rect scrollRect = m_TotalRect;\n            Rect contentRect = new Rect(0, 0, 1, totalContentsHeight);\n            bool scrollBarVisible = totalContentsHeight > m_TotalRect.height;\n\n            m_VisibleRect = m_TotalRect;\n            if (scrollBarVisible)\n                m_VisibleRect.width -= kSpaceForScrollBar;\n\n\n            double timeNow = EditorApplication.timeSinceStartup;\n            m_LastScrollPosition = m_State.m_ScrollPosition;\n\n            bool needRepaint = false;\n            m_State.m_ScrollPosition = GUI.BeginScrollView(scrollRect, m_State.m_ScrollPosition, contentRect);\n            {\n                Vector2 scrollPos = m_State.m_ScrollPosition; // Copy scroll pos since the draw calls may change it\n\n                if (m_LastScrollPosition != m_State.m_ScrollPosition)\n                    LastScrollTime = timeNow;\n\n                float yOffset = 0f;\n                int rowsBeingUsed = 0;\n                foreach (Group g in m_Groups)\n                {\n                    if (SkipGroup(g))\n                        continue;\n\n                    // rect contains the offset rect where the group should draw\n                    g.Draw(yOffset, scrollPos, ref rowsBeingUsed);\n                    needRepaint = needRepaint || g.NeedsRepaint;\n                    yOffset += g.Height;\n\n                    // ShowNone is only used in object select window\n                    if (m_LocalAssets.ShowNone)\n                        break;\n                }\n\n                if (maxItemsReached)\n                {\n                    GUI.Label(new Rect(0, yOffset + 20, scrollRect.width, 16), Styles.maxmumItemCountInfo, EditorStyles.centeredGreyMiniLabel);\n                }\n\n                HandlePing();\n                if (needRepaint)\n                    Repaint();\n            } GUI.EndScrollView();\n        }\n\n        bool IsListMode()\n        {\n            if (allowMultiSelect)\n                return (gridSize == kListLineHeight); // ProjectBrowser (should auto change layout on content but entirely user controlled)\n            else\n                return (gridSize == kListLineHeight) || !CanShowThumbnails(); // ObjectSelector\n        }\n\n        void Reflow()\n        {\n            if (gridSize < 20)\n                gridSize = m_MinGridSize;\n            else if (gridSize < m_MinIconSize)\n                gridSize = m_MinIconSize;\n\n            // We're in list mode.\n            if (IsListMode())\n            {\n                foreach (Group g in m_Groups)\n                {\n                    if (SkipGroup(g))\n                        continue;\n\n                    g.ListMode = true;\n                    UpdateGroupSizes(g);\n\n                    // ShowNone is only used in object select window\n                    if (m_LocalAssets.ShowNone)\n                        break;\n                }\n            }\n            // we're in thumbnail mode\n            else\n            {\n                // Grid without scrollbar\n                float totalHeight = 0;\n                foreach (Group g in m_Groups)\n                {\n                    if (SkipGroup(g))\n                        continue;\n\n                    g.ListMode = false;\n                    UpdateGroupSizes(g);\n\n                    totalHeight += g.Height;\n\n                    // ShowNone is only used in object select window\n                    if (m_LocalAssets.ShowNone)\n                        break;\n                }\n\n                // Grid with scrollbar\n                bool scrollbarVisible = m_TotalRect.height < totalHeight;\n                if (scrollbarVisible)\n                {\n                    // Make room for the scrollbar\n                    foreach (Group g in m_Groups)\n                    {\n                        if (SkipGroup(g))\n                            continue;\n\n                        g.m_Grid.fixedWidth = m_TotalRect.width - kSpaceForScrollBar;\n                        g.m_Grid.InitNumRowsAndColumns(g.ItemCount, g.m_Grid.CalcRows(g.ItemsWantedShown));\n                        g.UpdateHeight();\n\n                        // ShowNone is only used in object select window\n                        if (m_LocalAssets.ShowNone)\n                            break;\n                    }\n                }\n\n                int maxVisibleItems = GetMaxNumVisibleItems();\n\n                AssetPreview.SetPreviewTextureCacheSize(maxVisibleItems * 2 + 30, GetAssetPreviewManagerID());\n            }\n        }\n\n        void UpdateGroupSizes(Group g)\n        {\n            if (g.ListMode)\n            {\n                g.m_Grid.fixedWidth = m_VisibleRect.width;\n                g.m_Grid.itemSize = new Vector2(m_VisibleRect.width, kListLineHeight);\n                g.m_Grid.topMargin = 0f;\n                g.m_Grid.bottomMargin = 0f;\n                g.m_Grid.leftMargin = 0f;\n                g.m_Grid.rightMargin = 0f;\n                g.m_Grid.verticalSpacing = 0f;\n                g.m_Grid.minHorizontalSpacing = 0f;\n                g.m_Grid.InitNumRowsAndColumns(g.ItemCount, g.ItemsWantedShown);\n\n                g.UpdateHeight();\n            }\n            else\n            {\n                g.m_Grid.fixedWidth = m_TotalRect.width;\n                g.m_Grid.itemSize = new Vector2(gridSize, gridSize + 14);\n                g.m_Grid.topMargin = 10f;\n                g.m_Grid.bottomMargin = 10f;\n                g.m_Grid.leftMargin = 10f;\n                g.m_Grid.rightMargin = 10f;\n                g.m_Grid.verticalSpacing = 15f;\n                g.m_Grid.minHorizontalSpacing = 12f;\n                g.m_Grid.InitNumRowsAndColumns(g.ItemCount, g.m_Grid.CalcRows(g.ItemsWantedShown));\n\n                g.UpdateHeight();\n            }\n        }\n\n        int GetMaxNumVisibleItems()\n        {\n            foreach (Group g in m_Groups)\n            {\n                if (SkipGroup(g))\n                    continue;\n\n                return g.m_Grid.GetMaxVisibleItems(m_TotalRect.height);\n            }\n\n            return 0;\n        }\n\n        static Rect AdjustRectForFraming(Rect r)\n        {\n            r.height += (Styles.resultsGridLabel.fixedHeight * 2);\n            r.y -= Styles.resultsGridLabel.fixedHeight;\n            return r;\n        }\n\n        void CenterRect(Rect r)\n        {\n            float middle = (r.yMax + r.yMin) / 2;\n            float middleVisibleRect = m_TotalRect.height / 2;\n\n            m_State.m_ScrollPosition.y = middle - middleVisibleRect;\n\n            // Ensure clamped\n            ScrollToPosition(r);\n        }\n\n        void ScrollToPosition(Rect r)\n        {\n            float top = r.y;\n            float bottom = r.yMax;\n            float viewHeight = m_TotalRect.height;\n\n            if (bottom > viewHeight + m_State.m_ScrollPosition.y)\n            {\n                m_State.m_ScrollPosition.y = bottom - viewHeight;\n            }\n            if (top < m_State.m_ScrollPosition.y)\n            {\n                m_State.m_ScrollPosition.y = top;\n            }\n\n            m_State.m_ScrollPosition.y = Mathf.Max(m_State.m_ScrollPosition.y, 0f);\n        }\n\n        public void OnInspectorUpdate()\n        {\n            if (EditorApplication.timeSinceStartup > m_NextDirtyCheck && m_LocalAssets.IsAnyLastRenderedAssetsDirty())\n            {\n                // If an asset is dirty we ensure to get a updated preview by clearing cache of temporary previews\n                AssetPreview.ClearTemporaryAssetPreviews();\n                Repaint();\n                m_NextDirtyCheck = EditorApplication.timeSinceStartup + 0.77;\n            }\n        }\n\n        public bool IsShowing(int instanceID)\n        {\n            return m_LocalAssets.IndexOf(instanceID) >= 0;\n        }\n\n        public bool IsShowingAny(int[] instanceIDs)\n        {\n            if (instanceIDs.Length == 0)\n                return false;\n\n            foreach (int instanceID in instanceIDs)\n                if (IsShowing(instanceID))\n                    return true;\n\n            return false;\n        }\n\n        protected Texture GetIconByInstanceID(int instanceID)\n        {\n            Texture icon = null;\n            if (instanceID != 0)\n            {\n                string path = AssetDatabase.GetAssetPath(instanceID);\n                icon = AssetDatabase.GetCachedIcon(path);\n            }\n            return icon;\n        }\n\n        internal int GetAssetPreviewManagerID()\n        {\n            return m_Owner.GetInstanceID();\n        }\n\n        // Pings only local assets\n        public void BeginPing(int instanceID)\n        {\n            // Check local assets\n            int index =  m_LocalAssets.IndexOf(instanceID);\n\n            if (index != -1)\n            {\n                string name = null;\n                HierarchyProperty hierarchyProperty = new HierarchyProperty(HierarchyType.Assets);\n                if (hierarchyProperty.Find(instanceID, null))\n                {\n                    name = hierarchyProperty.name;\n                }\n                var path = AssetDatabase.GetAssetPath(instanceID);\n                if (string.IsNullOrEmpty(path))\n                    return;\n\n                var packageInfo = PackageManager.PackageInfo.FindForAssetPath(path);\n                if (packageInfo != null)\n                {\n                    hierarchyProperty = new HierarchyProperty(packageInfo.assetPath);\n                    if (hierarchyProperty.Find(instanceID, null))\n                    {\n                        name = hierarchyProperty.name;\n                    }\n                }\n                if (name == null)\n                    return;\n\n                m_Ping.isPinging = true;\n                m_Ping.m_AvailableWidth = m_VisibleRect.width;\n                m_pingIndex = index;\n\n                float vcPadding = s_VCEnabled ? k_ListModeVersionControlOverlayPadding : 0f;\n                var assetReference = new AssetReference() { instanceID = instanceID };\n                var textClipping = m_LocalAssets.ListMode ? TextClipping.Overflow : TextClipping.Ellipsis;\n                GUIContent cont = new GUIContent(name);\n                string label = cont.text;\n\n                if (m_LocalAssets.ListMode)\n                {\n                    const float iconWidth = 16;\n                    m_Ping.m_PingStyle = Styles.ping;\n                    Vector2 pingLabelSize = m_Ping.m_PingStyle.CalcSize(cont);\n                    m_Ping.m_ContentRect.width = pingLabelSize.x + vcPadding + iconWidth;\n                    m_Ping.m_ContentRect.height = pingLabelSize.y;\n                    m_LeftPaddingForPinging = hierarchyProperty.isMainRepresentation ? LocalGroup.k_ListModeLeftPadding : LocalGroup.k_ListModeLeftPaddingForSubAssets;\n                    FilteredHierarchy.FilterResult res = m_LocalAssets.LookupByInstanceID(instanceID);\n                    var icon = hierarchyProperty.icon;\n                    m_Ping.m_ContentDraw = (Rect r) =>\n                    {\n                        if (icon)\n                        {\n                            m_LocalAssets.DrawIconAndLabel(r, res, label, icon, false, false);\n                        }\n                    };\n                }\n                else\n                {\n                    m_Ping.m_PingStyle = Styles.miniPing;\n                    var oldClipping = m_Ping.m_PingStyle.clipping;\n                    m_Ping.m_PingStyle.clipping = textClipping;\n                    Vector2 pingLabelSize = Styles.resultsGridLabel.CalcSizeWithConstraints(cont, sizeUsedForCroppingName);\n                    m_Ping.m_ContentRect.width = pingLabelSize.x + Styles.resultsGridLabel.padding.horizontal;\n                    m_Ping.m_ContentRect.height = pingLabelSize.y;\n                    m_Ping.m_ContentDraw = (Rect r) =>\n                    {\n                        // We need to temporary adjust style to render into content rect (org anchor is middle-centered)\n                        var orgAnchor = Styles.resultsGridLabel.alignment;\n                        var orgClipping = Styles.resultsGridLabel.clipping;\n                        // Shift the rect to match the original text position\n                        r.position -= new Vector2(5, 1);\n                        Styles.resultsGridLabel.alignment = TextAnchor.MiddleCenter;\n                        Styles.resultsGridLabel.clipping = TextClipping.Ellipsis;\n                        Styles.resultsGridLabel.Draw(r, label, false, false, false, false);\n                        Styles.resultsGridLabel.alignment = orgAnchor;\n                        Styles.resultsGridLabel.clipping = orgClipping;\n                    };\n                    m_Ping.m_PingStyle.clipping = oldClipping;\n                }\n                Vector2 pos = CalculatePingPosition();\n                m_Ping.m_ContentRect.x = pos.x;\n                m_Ping.m_ContentRect.y = pos.y;\n\n                Repaint();\n            }\n        }\n\n        public void EndPing()\n        {\n            m_Ping.isPinging = false;\n        }\n\n        void HandlePing()\n        {\n            // We need to update m_Ping.m_ContentTopLeft in icon mode. The position might change if user resizes the window while pinging\n            if (m_Ping.isPinging && !m_LocalAssets.ListMode)\n            {\n                Vector2 pos = CalculatePingPosition();\n                m_Ping.m_ContentRect.x = pos.x;\n                m_Ping.m_ContentRect.y = pos.y;\n            }\n            m_Ping.HandlePing();\n\n            if (m_Ping.isPinging)\n                Repaint();\n        }\n\n        Vector2 CalculatePingPosition()\n        {\n            Rect gridRect = m_LocalAssets.m_Grid.CalcRect(m_pingIndex, 0f);\n\n            if (m_LocalAssets.ListMode)\n            {\n                return new Vector2(m_LeftPaddingForPinging, gridRect.y);\n            }\n            else\n            {\n                Vector2 adjustLabel = new Vector2(-3, 2); // adjust so ping label matches grid label exactly\n                float width = m_Ping.m_ContentRect.width;\n                return new Vector2(gridRect.center.x - width / 2f + m_Ping.m_PingStyle.padding.left + adjustLabel.x, gridRect.yMax - Styles.resultsGridLabel.fixedHeight + adjustLabel.y);\n            }\n        }\n    }\n}  // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/ObjectListGroup.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing Math = System.Math;\n\nnamespace UnityEditor\n{\n    internal partial class ObjectListArea\n    {\n        /* Abstract base class for each group of assets (e.g. Local, AssetStore) used in the ObjectListArea\n         */\n        protected abstract class Group\n        {\n            readonly protected float kGroupSeparatorHeight = EditorStyles.toolbar.fixedHeight;\n            protected string m_GroupSeparatorTitle;\n\n            protected static int[] s_Empty;\n            public ObjectListArea m_Owner;\n            public VerticalGrid m_Grid = new VerticalGrid();\n            public float m_Height;\n\n            public float Height { get { return m_Height; } }\n            abstract public int ItemCount { get; }\n            abstract public bool ListMode { get; set; }\n            abstract public bool NeedsRepaint { get; protected set; }\n\n            public bool Visible = true; // Visibility toggled in GUI\n            public int ItemsAvailable = 0; // Calculated from total asset count\n            public int ItemsWantedShown = 0; // Rows requested to be displayed\n            protected bool m_Collapsable = true;\n            public double m_LastClickedDrawTime = 0;\n\n            public Group(ObjectListArea owner, string groupTitle)\n            {\n                m_GroupSeparatorTitle = groupTitle;\n                if (s_Empty == null)\n                    s_Empty = new int[0];\n                m_Owner = owner;\n                Visible = visiblePreference;\n            }\n\n            public bool visiblePreference\n            {\n                get\n                {\n                    if (string.IsNullOrEmpty(m_GroupSeparatorTitle))\n                        return true;\n                    return EditorPrefs.GetBool(m_GroupSeparatorTitle, true);\n                }\n                set\n                {\n                    if (string.IsNullOrEmpty(m_GroupSeparatorTitle))\n                        return;\n                    EditorPrefs.SetBool(m_GroupSeparatorTitle, value);\n                }\n            }\n\n\n            // Called before repaints in order to prepare internal assets for rendering\n            abstract public void UpdateAssets();\n\n            // Called when height of this group should be recalculated\n            abstract public void UpdateHeight();\n\n            abstract protected void DrawInternal(int itemIdx, int endItem, float yOffset);\n\n            // Called when the filter has changed\n            abstract public void UpdateFilter(HierarchyType hierarchyType, SearchFilter searchFilter, bool showFoldersFirst, SearchService.SearchSessionOptions searchSessionOptions);\n\n            public void UpdateFilter(HierarchyType hierarchyType, SearchFilter searchFilter, bool showFoldersFirst)\n            {\n                UpdateFilter(hierarchyType, searchFilter, showFoldersFirst, SearchService.SearchSessionOptions.Default);\n            }\n\n            protected virtual float GetHeaderHeight()\n            {\n                return kGroupSeparatorHeight;\n            }\n\n            protected virtual void HandleUnusedDragEvents(float yOffset) {}\n\n            int FirstVisibleRow(float yOffset, Vector2 scrollPos)\n            {\n                if (!Visible)\n                    return -1;\n\n                // Skip rows that is outside the offset rect\n                float yRelOffset = scrollPos.y - (yOffset + GetHeaderHeight());\n\n                int invisibleRows = 0;\n                if (yRelOffset > 0f)\n                {\n                    // Initial rows hidden\n                    float itemHeight = m_Grid.itemSize.y + m_Grid.verticalSpacing;\n                    invisibleRows = (int)Mathf.Max(0, Mathf.Floor(yRelOffset / itemHeight));\n                }\n                return invisibleRows;\n            }\n\n            bool IsInView(float yOffset, Vector2 scrollPos, float scrollViewHeight)\n            {\n                if ((scrollPos.y + scrollViewHeight) < yOffset)\n                    return false; // after visible area\n\n                if ((yOffset + Height) < scrollPos.y)\n                    return false; // before visible area\n\n                return true;\n            }\n\n            // Main draw method of a group that is called from outside\n            public void Draw(float yOffset, Vector2 scrollPos, ref int rowsInUse)\n            {\n                NeedsRepaint = false;\n\n                // We need to always draw the header as it uses controlIDs (and we cannot cull gui elements using controlID)\n                bool isRepaint = Event.current.type == EventType.Repaint || Event.current.type == EventType.Layout;\n\n                if (!isRepaint)\n                    DrawHeader(yOffset, m_Collapsable); // logic here, draw on top below\n\n                if (!IsInView(yOffset, scrollPos, m_Owner.m_VisibleRect.height))\n                    return;\n\n                int invisibleRows = FirstVisibleRow(yOffset, scrollPos);\n                int beginItem = invisibleRows * m_Grid.columns;\n                int totalItemCount = ItemCount;\n                if (beginItem >= 0 && beginItem < totalItemCount)\n                {\n                    int itemIdx = beginItem;\n                    // Limit by items avail and max items to show\n                    // (plus an extra row to allow half a row in top and bottom at the same time)\n                    int endItem = Math.Min(totalItemCount, m_Grid.rows * m_Grid.columns);\n\n                    // Also limit to what can possible be in view in order to limit draws\n                    float itemHeight = m_Grid.itemSize.y + m_Grid.verticalSpacing;\n                    int rowsInVisibleRect = (int)Math.Ceiling(m_Owner.m_VisibleRect.height / itemHeight);\n\n                    //When a row is hidden behind the header, it is still counted as visible, therefore to avoid\n                    //weird popping in and out for the icons, we make sure that a new row will be rendered even if one\n                    //is considered visible, even though it cannot be seen in the window\n                    rowsInVisibleRect += 1;\n\n                    int rowsNotInUse = rowsInVisibleRect - rowsInUse;\n                    if (rowsNotInUse < 0)\n                        rowsNotInUse = 0;\n\n                    rowsInUse = Math.Min(rowsInVisibleRect, Mathf.CeilToInt((endItem - beginItem) / (float)m_Grid.columns));\n\n                    endItem = rowsNotInUse * m_Grid.columns + beginItem;\n                    if (endItem > totalItemCount)\n                        endItem = totalItemCount;\n\n                    DrawInternal(itemIdx, endItem, yOffset);\n                }\n\n                if (isRepaint)\n                    DrawHeader(yOffset, m_Collapsable);\n\n                // Always handle drag events in the case where we have no items we still want to be able to drag into the group.\n                HandleUnusedDragEvents(yOffset);\n            }\n\n            protected void DrawObjectIcon(Rect position, Texture icon)\n            {\n                if (icon == null)\n                    return;\n\n                int size = icon.width;\n\n                FilterMode temp = icon.filterMode;\n                icon.filterMode = FilterMode.Point;\n                GUI.DrawTexture(new Rect(position.x + ((int)position.width - size) / 2, position.y + ((int)position.height - size) / 2, size, size), icon, ScaleMode.ScaleToFit);\n                icon.filterMode = temp;\n            }\n\n            protected void DrawDropShadowOverlay(Rect position, bool selected, bool isDropTarget, bool isRenaming)\n            {\n                // Draw dropshadow overlay\n                float fraction = position.width / 128f;\n                Rect dropShadowRect = new Rect(position.x - 4 * fraction, position.y - 2 * fraction, position.width + 8 * fraction, position.height + 12 * fraction - 0.5f);\n                Styles.iconDropShadow.Draw(dropShadowRect, GUIContent.none, false, false, selected || isDropTarget, m_Owner.HasFocus() || isRenaming || isDropTarget);\n            }\n\n            protected void DrawHeaderBackground(Rect rect, bool firstHeader, bool expanded)\n            {\n                if (Event.current.type != EventType.Repaint)\n                    return;\n\n                // Draw the group bar background\n                (firstHeader ? Styles.groupHeaderTop : Styles.groupHeaderMiddle)?.Draw(rect, GUIContent.none,\n                    rect.Contains(Event.current.mousePosition), false, expanded, false);\n            }\n\n            protected float GetHeaderYPosInScrollArea(float yOffset)\n            {\n                float y = yOffset;\n                float yScrollPos = m_Owner.m_State.m_ScrollPosition.y;\n                if (yScrollPos > yOffset)\n                {\n                    y = Mathf.Min(yScrollPos, yOffset + Height - kGroupSeparatorHeight);\n                }\n                return y;\n            }\n\n            virtual protected void DrawHeader(float yOffset, bool collapsable)\n            {\n                const int foldoutSpacing = 3;\n                Rect rect = new Rect(0, GetHeaderYPosInScrollArea(yOffset), m_Owner.GetVisibleWidth(), kGroupSeparatorHeight - 1);\n\n                DrawHeaderBackground(rect, yOffset == 0, Visible);\n\n                // Draw the group toggle\n                rect.x += 7;\n                if (collapsable)\n                {\n                    bool oldVisible = Visible;\n                    Visible = GUI.Toggle(rect, Visible, GUIContent.none, Styles.groupFoldout);\n                    if (oldVisible ^ Visible)\n                        visiblePreference = Visible;\n                }\n\n                // Draw title\n                GUIStyle textStyle = Styles.groupHeaderLabel;\n                if (collapsable)\n                    rect.x += Styles.groupFoldout.fixedWidth + foldoutSpacing;\n                rect.y += 1;\n                if (!string.IsNullOrEmpty(m_GroupSeparatorTitle))\n                    GUI.Label(rect, m_GroupSeparatorTitle, textStyle);\n\n                rect.y -= 1;\n\n                // Only draw counts if we have room for it\n                if (m_Owner.GetVisibleWidth() > 150)\n                    DrawItemCount(rect);\n            }\n\n            protected void DrawItemCount(Rect rect)\n            {\n                // Draw item count in group\n                const float rightMargin = 4f;\n\n                string label = ItemsAvailable + \" Total\";\n                Vector2 labelDims = Styles.groupHeaderLabelCount.CalcSize(new GUIContent(label));\n                if (labelDims.x < rect.width)\n                    rect.x = m_Owner.GetVisibleWidth() - labelDims.x - rightMargin; // right align if room\n                rect.width = labelDims.x;\n                rect.y += 2; // better y pos for minilabel\n                GUI.Label(rect, label, Styles.groupHeaderLabelCount);\n            }\n        }\n    }\n}  // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/ObjectListLocalGroup.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor.VersionControl;\nusing UnityEditorInternal;\nusing UnityEditorInternal.VersionControl;\nusing System.Collections.Generic;\nusing Math = System.Math;\nusing AssetReference = UnityEditorInternal.InternalEditorUtility.AssetReference;\nusing RenameOverlay = UnityEditor.RenameOverlay<int>;\n\nnamespace UnityEditor\n{\n    internal partial class ObjectListArea\n    {\n        // Enable external source(s) to draw in the project browser.\n        // 'iconRect' frame for the asset icon.\n        // 'guid' asset being drawn.\n        internal delegate void OnAssetIconDrawDelegate(Rect iconRect, string guid, bool isListMode);\n        internal static event OnAssetIconDrawDelegate postAssetIconDrawCallback = null;\n\n        // 'drawRect' prescribed draw area after the asset label.\n        // 'guid' asset being drawn.\n        // return whether drawing occured (space will be redistributed if false)\n        internal delegate bool OnAssetLabelDrawDelegate(Rect drawRect, string guid, bool isListMode);\n        internal static event OnAssetLabelDrawDelegate postAssetLabelDrawCallback = null;\n\n        // Asset on local disk in project\n        protected class LocalGroup : Group\n        {\n            public class ExtraItem : BuiltinResource\n            {\n                public Texture2D m_Icon = null;\n            }\n            ExtraItem[] m_NoneList;\n            public ExtraItem[] NoneList => m_NoneList;\n\n            GUIContent m_Content = new GUIContent();\n\n            List<int> m_DragSelection = new List<int>();                // Temp instanceID state while dragging (not serialized)\n            int m_DropTargetControlID = 0;\n\n            private List<Type> m_AssetPreviewIgnoreList = new List<Type>();\n            private List<string> m_AssetExtensionsPreviewIgnoreList = new List<string>();\n\n            // Type name if resource is the key\n            Dictionary<string, BuiltinResource[]> m_BuiltinResourceMap;\n            BuiltinResource[] m_CurrentBuiltinResources;\n            bool m_ShowNoneItem;\n            public bool ShowNone { get { return m_ShowNoneItem; } }\n            public override bool NeedsRepaint { get { return false; } protected set {} }\n            List<int> m_LastRenderedAssetInstanceIDs = new List<int>();\n            List<int> m_LastRenderedAssetDirtyCounts = new List<int>();\n\n            public bool m_ListMode = false;\n            FilteredHierarchy m_FilteredHierarchy;\n            BuiltinResource[] m_ActiveBuiltinList;\n\n            public const int k_ListModeLeftPadding = 13;\n            public const int k_ListModeLeftPaddingForSubAssets = 28;\n            public const int k_ListModeVersionControlOverlayPadding = 14;\n            const int k_ListModeExternalIconPadding = 6;\n            const float k_IconWidth = 16f;\n            const float k_SpaceBetweenIconAndText = 2f;\n\n\n            public SearchFilter searchFilter { get {return m_FilteredHierarchy.searchFilter; }}\n            public override bool ListMode { get { return m_ListMode; } set { m_ListMode = value; } }\n            public bool HasBuiltinResources { get {  return m_CurrentBuiltinResources.Length > 0; } }\n\n            ItemFader m_ItemFader = new ItemFader();\n            private readonly Action m_OwnerRepaintAction;\n\n            public int projectItemCount { get { return m_FilteredHierarchy.results.Length; } }\n\n            public override int ItemCount\n            {\n                get\n                {\n                    int totalItemCount = projectItemCount + m_ActiveBuiltinList.Length;\n                    int noneItem = m_ShowNoneItem ? 1 : 0;\n                    int newItem = m_Owner.m_State.m_NewAssetIndexInList != -1 ? 1 : 0;\n                    return totalItemCount + noneItem + newItem;\n                }\n            }\n\n            public LocalGroup(ObjectListArea owner, string groupTitle, bool showNone) : base(owner, groupTitle)\n            {\n                m_ShowNoneItem = showNone;\n                m_ListMode = false;\n                InitBuiltinResources();\n                ItemsWantedShown = int.MaxValue;\n                m_Collapsable = false;\n                m_OwnerRepaintAction = () => m_Owner.Repaint();\n                InitAssetPreviewIgnoreList();\n            }\n\n            //Initialize the list with known asset types that has no Preview Image and should use icons instead like Text, Folder, Scene etc.\n            //This will prevent the AssetPreview generation for asset types that has no asset previews.\n            //This has been added to handle projects with a large number of assets that has no preview,\n            //as preview generation for all those assets is consuming significant amount of CPU,\n            //it feels like Unity is frozen for repaint event in ProjectBrowse/ObjectSelector.\n            private void InitAssetPreviewIgnoreList()\n            {\n                m_AssetPreviewIgnoreList.Add(typeof(DefaultAsset));                                                 //DLLs, corrupted files, pdf, Folder etc.\n                m_AssetPreviewIgnoreList.Add(typeof(MonoScript));                                                   //Monobehaviour scripts\n                m_AssetPreviewIgnoreList.Add(typeof(SceneAsset));\n                m_AssetPreviewIgnoreList.Add(typeof(AnimationClip));\n                m_AssetPreviewIgnoreList.Add(typeof(Animations.AnimatorController));\n                m_AssetPreviewIgnoreList.Add(typeof(TextAsset));\n                m_AssetPreviewIgnoreList.Add(typeof(Shader));\n                m_AssetPreviewIgnoreList.Add(typeof(LightingSettings));\n                m_AssetPreviewIgnoreList.Add(typeof(LightmapParameters));\n\n                m_AssetExtensionsPreviewIgnoreList.Add(\".index\");\n                m_AssetExtensionsPreviewIgnoreList.Add(\".vfx\");\n            }\n\n            //Use this to add the specific types that needs to ignored for AssetPreview image generation.\n            //External packages can use these to add support for their specific asset types.\n            public void AddTypetoAssetPreviewIgnoreList(Type assetType)\n            {\n                if (m_AssetPreviewIgnoreList.Contains(assetType))\n                    return;\n\n                m_AssetPreviewIgnoreList.Add(assetType);\n            }\n\n            public override void UpdateAssets()\n            {\n                // Set up our builtin list\n                if (m_FilteredHierarchy?.hierarchyType == HierarchyType.Assets)\n                    m_ActiveBuiltinList = m_CurrentBuiltinResources;\n                else\n                    m_ActiveBuiltinList = new BuiltinResource[0];   // The Scene tab does not display builtin resources\n\n                ItemsAvailable = m_FilteredHierarchy.results.Length + m_ActiveBuiltinList.Length;\n            }\n\n            protected override float GetHeaderHeight()\n            {\n                return 0f;\n            }\n\n            override protected void DrawHeader(float yOffset, bool collapsable)\n            {\n                if (GetHeaderHeight() > 0f)\n                {\n                    Rect rect = new Rect(0, GetHeaderYPosInScrollArea(yOffset), m_Owner.GetVisibleWidth(), kGroupSeparatorHeight);\n\n                    base.DrawHeaderBackground(rect, true, Visible);\n\n                    // Draw the group toggle\n                    if (collapsable)\n                    {\n                        rect.x += 7;\n                        bool oldVisible = Visible;\n                        Visible = GUI.Toggle(new Rect(rect.x, rect.y, 14, rect.height), Visible, GUIContent.none, Styles.groupFoldout);\n                        if (oldVisible ^ Visible)\n                            EditorPrefs.SetBool(m_GroupSeparatorTitle, Visible);\n\n                        rect.x += 7;\n                    }\n\n                    float usedWidth = 0f;\n                    if (m_Owner.drawLocalAssetHeader != null)\n                        usedWidth = m_Owner.drawLocalAssetHeader(rect) + 10f; // add space between arrow and count\n\n                    rect.x += usedWidth;\n                    rect.width -= usedWidth;\n                    if (rect.width > 0)\n                        base.DrawItemCount(rect);\n                }\n            }\n\n            public override void UpdateHeight()\n            {\n                // Ensure that m_Grid is setup before calling UpdateHeight\n                m_Height = GetHeaderHeight();\n\n                if (!Visible)\n                    return;\n\n                m_Height += m_Grid.height;\n            }\n\n            bool IsCreatingAtThisIndex(int itemIdx)\n            {\n                return m_Owner.m_State.m_NewAssetIndexInList == itemIdx;\n            }\n\n            protected override void DrawInternal(int beginIndex, int endIndex, float yOffset)\n            {\n                int itemIndex = beginIndex;\n                int itemCount = 0;\n\n                FilteredHierarchy.FilterResult[] results = m_FilteredHierarchy.results;\n\n                bool isFolderBrowsing = m_FilteredHierarchy.searchFilter.GetState() == SearchFilter.State.FolderBrowsing;\n\n                // The seperator bar is drawn before all items\n                yOffset += GetHeaderHeight();\n\n                // 1. None item\n                Rect itemRect;\n                if (m_NoneList.Length > 0)\n                {\n                    if (beginIndex < 1)\n                    {\n                        itemRect = m_Grid.CalcRect(itemIndex, yOffset);\n                        DrawItem(itemRect, null, m_NoneList[0], isFolderBrowsing);\n                        itemIndex++;\n                    }\n                    itemCount++;\n                }\n\n                // 2. Project Assets\n                if (!ListMode && isFolderBrowsing)\n                    DrawSubAssetBackground(beginIndex, endIndex, yOffset); // only show sub asset bg when not searching i.e. folder browsing\n\n                if (Event.current.type == EventType.Repaint)\n                    ClearDirtyStateTracking();\n                int resultsIdx = itemIndex - itemCount;\n                while (true)\n                {\n                    // Insert new asset item here\n                    if (IsCreatingAtThisIndex(itemIndex))\n                    {\n                        BuiltinResource newAsset = new BuiltinResource();\n                        newAsset.m_Name = m_Owner.GetCreateAssetUtility().originalName;\n                        newAsset.m_InstanceID = m_Owner.GetCreateAssetUtility().instanceID;\n\n                        DrawItem(m_Grid.CalcRect(itemIndex, yOffset), null, newAsset, isFolderBrowsing);\n                        itemIndex++; // Push following items forward\n                        itemCount++;\n                    }\n\n                    // Stop conditions\n                    if (itemIndex > endIndex)\n                        break;\n                    if (resultsIdx >= results.Length)\n                        break;\n\n                    // Draw item\n                    FilteredHierarchy.FilterResult result = results[resultsIdx];\n                    itemRect = m_Grid.CalcRect(itemIndex, yOffset);\n                    DrawItem(itemRect, result, null, isFolderBrowsing);\n                    itemIndex++;\n                    resultsIdx++;\n                }\n                itemCount += results.Length;\n\n                // 3. Builtin\n                if (m_ActiveBuiltinList.Length > 0)\n                {\n                    int builtinStartIdx = beginIndex - itemCount;\n                    builtinStartIdx = Math.Max(builtinStartIdx, 0);\n                    for (int builtinIdx = builtinStartIdx; builtinIdx < m_ActiveBuiltinList.Length && itemIndex <= endIndex; itemIndex++, builtinIdx++)\n                    {\n                        DrawItem(m_Grid.CalcRect(itemIndex, yOffset), null, m_ActiveBuiltinList[builtinIdx], isFolderBrowsing);\n                    }\n                }\n\n                // Repaint again if we are in preview icon mode and previews are being loaded\n                if (!ListMode && AssetPreview.IsLoadingAssetPreviews(m_Owner.GetAssetPreviewManagerID()))\n                    m_Owner.Repaint();\n            }\n\n            void ClearDirtyStateTracking()\n            {\n                m_LastRenderedAssetInstanceIDs.Clear();\n                m_LastRenderedAssetDirtyCounts.Clear();\n            }\n\n            void AddDirtyStateFor(int instanceID)\n            {\n                m_LastRenderedAssetInstanceIDs.Add(instanceID);\n                m_LastRenderedAssetDirtyCounts.Add(EditorUtility.GetDirtyCount(instanceID));\n            }\n\n            public bool IsAnyLastRenderedAssetsDirty()\n            {\n                for (int i = 0; i < m_LastRenderedAssetInstanceIDs.Count; ++i)\n                {\n                    int dirtyCount = EditorUtility.GetDirtyCount(m_LastRenderedAssetInstanceIDs[i]);\n                    if (dirtyCount != m_LastRenderedAssetDirtyCounts[i])\n                    {\n                        m_LastRenderedAssetDirtyCounts[i] = dirtyCount;\n                        return true;\n                    }\n                }\n                return false;\n            }\n\n            protected override void HandleUnusedDragEvents(float yOffset)\n            {\n                if (!m_Owner.allowDragging)\n                    return;\n                Event evt = Event.current;\n                switch (evt.type)\n                {\n                    case EventType.DragUpdated:\n                    case EventType.DragPerform:\n                        Rect localGroupRect = new Rect(0, yOffset, m_Owner.m_TotalRect.width, m_Owner.m_TotalRect.height > Height ? m_Owner.m_TotalRect.height : Height);\n                        if (localGroupRect.Contains(evt.mousePosition))\n                        {\n                            DragAndDropVisualMode mode;\n                            bool isFolderBrowsing = (m_FilteredHierarchy.searchFilter.GetState() == SearchFilter.State.FolderBrowsing);\n                            if (isFolderBrowsing && m_FilteredHierarchy.searchFilter.folders.Length == 1)\n                            {\n                                string folder = m_FilteredHierarchy.searchFilter.folders[0];\n                                int instanceID = AssetDatabase.GetMainAssetInstanceID(folder);\n                                bool perform = evt.type == EventType.DragPerform;\n                                mode = DoDrag(instanceID, perform);\n                                if (perform && mode != DragAndDropVisualMode.None)\n                                    DragAndDrop.AcceptDrag();\n                            }\n                            else\n                            {\n                                // Disallow drop: more than one folder or search is active, since dropping would be ambiguous.\n                                mode = DragAndDropVisualMode.None;\n                            }\n                            DragAndDrop.visualMode = mode;\n                            evt.Use();\n                        }\n                        break;\n                    case EventType.DragExited:\n                        m_DragSelection.Clear();\n                        break;\n                }\n            }\n\n            void HandleMouseWithDragging(ref AssetReference assetReference, int controlID, Rect rect)\n            {\n                // Handle mouse down on entire line\n                Event evt = Event.current;\n\n                switch (evt.GetTypeForControl(controlID))\n                {\n                    case EventType.MouseDown:\n                        if (Event.current.button == 0 && rect.Contains(Event.current.mousePosition))\n                        {\n                            if (evt.clickCount == 2)\n                            {\n                                // Double clicked\n                                var newSelection = GetNewSelection(ref assetReference, false, false);\n                                m_Owner.SetSelection(newSelection.ToArray(), true);\n                                m_DragSelection.Clear();\n                            }\n                            else\n                            {\n                                // Begin drag\n                                var newSelection = GetNewSelection(ref assetReference, false, false);\n                                var oldItemControlID = controlID;\n                                controlID = GetControlIDFromInstanceID(assetReference.instanceID);\n                                if (controlID == oldItemControlID)\n                                {\n                                    newSelection = GetNewSelection(ref assetReference, true, false);\n                                    m_DragSelection = newSelection;\n                                    DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), controlID);\n                                    delay.mouseDownPosition = Event.current.mousePosition;\n                                    m_Owner.ScrollToPosition(ObjectListArea.AdjustRectForFraming(rect));\n                                }\n                                else\n                                {\n                                    m_Owner.SetSelection(newSelection.ToArray(), false);\n                                    m_DragSelection.Clear();\n                                }\n                                GUIUtility.hotControl = controlID;\n                            }\n\n                            evt.Use();\n                        }\n                        else if (Event.current.button == 1 && rect.Contains(Event.current.mousePosition))\n                        {\n                            if (assetReference.instanceID == 0)\n                            {\n                                // For non selectable assets, don't show context menu. Selection is deselected\n                                m_Owner.SetSelection(new int[0], false);\n                                Event.current.Use();\n                            }\n                            else\n                            {\n                                // Right mouse down selection (do NOT use event since we need ContextClick event, which is not fired if right click is used)\n                                m_Owner.SetSelection(GetNewSelection(ref assetReference, true, false).ToArray(), false);\n                            }\n                        }\n                        break;\n                    case EventType.MouseDrag:\n                        if (GUIUtility.hotControl == controlID)\n                        {\n                            DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), controlID);\n                            if (delay.CanStartDrag())\n                            {\n                                StartDrag(assetReference.instanceID, m_DragSelection);\n                                GUIUtility.hotControl = 0;\n                            }\n\n                            evt.Use();\n                        }\n                        break;\n                    case EventType.DragUpdated:\n                    case EventType.DragPerform:\n                    {\n                        bool perform = evt.type == EventType.DragPerform;\n                        if (rect.Contains(evt.mousePosition))\n                        {\n                            DragAndDropVisualMode mode = DoDrag(assetReference.instanceID, perform);\n\n                            if (mode == DragAndDropVisualMode.Rejected && perform)\n                                evt.Use();\n                            else if (mode != DragAndDropVisualMode.None)\n                            {\n                                if (perform)\n                                    DragAndDrop.AcceptDrag();\n\n                                m_DropTargetControlID = controlID;\n                                DragAndDrop.visualMode = mode;\n                                evt.Use();\n                            }\n\n                            if (perform)\n                                m_DropTargetControlID = 0;\n                        }\n\n                        if (perform)\n                            m_DragSelection.Clear();\n                    }\n                    break;\n                    case EventType.MouseUp:\n                        if (GUIUtility.hotControl == controlID)\n                        {\n                            if (rect.Contains(evt.mousePosition))\n                            {\n                                bool clickedOnText;\n                                if (ListMode)\n                                {\n                                    rect.x += 28;\n                                    rect.width += 28;\n                                    clickedOnText = rect.Contains(evt.mousePosition);\n                                }\n                                else\n                                {\n                                    rect.y = rect.y + rect.height - Styles.resultsGridLabel.fixedHeight;\n                                    rect.height = Styles.resultsGridLabel.fixedHeight;\n                                    clickedOnText = rect.Contains(evt.mousePosition);\n                                }\n\n                                List<int> selected = m_Owner.m_State.m_SelectedInstanceIDs;\n                                if (clickedOnText && m_Owner.allowRenaming && m_Owner.m_AllowRenameOnMouseUp && selected.Count == 1 && selected[0] == assetReference.instanceID && !EditorGUIUtility.HasHolddownKeyModifiers(evt))\n                                {\n                                    m_Owner.BeginRename(0.5f);\n                                }\n                                else\n                                {\n                                    List<int> newSelection = GetNewSelection(ref assetReference, false, false);\n                                    m_Owner.SetSelection(newSelection.ToArray(), false);\n                                }\n\n                                GUIUtility.hotControl = 0;\n                                evt.Use();\n                            }\n\n                            m_DragSelection.Clear();\n                        }\n                        break;\n\n                    case EventType.ContextClick:\n                        HandleContextClick(evt, rect);\n                        break;\n                }\n            }\n\n            void HandleMouseWithoutDragging(ref AssetReference assetReference, int controlID, Rect position)\n            {\n                Event evt = Event.current;\n\n                switch (evt.GetTypeForControl(controlID))\n                {\n                    case EventType.MouseDown:\n                        if (evt.button == 0 && position.Contains(evt.mousePosition))\n                        {\n                            m_Owner.Repaint();\n\n                            if (evt.clickCount == 1)\n                            {\n                                m_Owner.ScrollToPosition(ObjectListArea.AdjustRectForFraming(position));\n                            }\n\n                            evt.Use();\n                            List<int> newSelection = GetNewSelection(ref assetReference, false, false);\n                            m_Owner.SetSelection(newSelection.ToArray(), evt.clickCount == 2);\n                        }\n                        break;\n\n                    case EventType.ContextClick:\n                        if (position.Contains(evt.mousePosition))\n                        {\n                            // Select it\n                            List<int> newSelection = GetNewSelection(ref assetReference, false, false);\n                            m_Owner.SetSelection(newSelection.ToArray(), false);\n\n                            HandleContextClick(evt, position);\n                        }\n                        break;\n                }\n            }\n\n            static void HandleContextClick(Event evt, Rect rect)\n            {\n                var overlayRect = rect;\n                overlayRect.x += 2;\n                overlayRect = ProjectHooks.GetOverlayRect(overlayRect);\n\n                var vco = VersionControlManager.activeVersionControlObject;\n                if (vco != null && !vco.isConnected)\n                    vco = null;\n                var vcConnected = vco != null || Provider.isActive;\n                if (vcConnected && overlayRect.width != rect.width && overlayRect.Contains(evt.mousePosition))\n                {\n                    if (vco != null)\n                        vco.GetExtension<IPopupMenuExtension>()?.DisplayPopupMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0));\n                    else\n                        EditorUtility.DisplayPopupMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), \"Assets/Version Control\", new MenuCommand(null, 0));\n                    evt.Use();\n                }\n            }\n\n            public void ChangeExpandedState(int instanceID, bool expanded)\n            {\n                m_Owner.m_State.m_ExpandedInstanceIDs.Remove(instanceID);\n                if (expanded)\n                    m_Owner.m_State.m_ExpandedInstanceIDs.Add(instanceID);\n                m_FilteredHierarchy.RefreshVisibleItems(m_Owner.m_State.m_ExpandedInstanceIDs);\n            }\n\n            bool IsExpanded(int instanceID)\n            {\n                return (m_Owner.m_State.m_ExpandedInstanceIDs.IndexOf(instanceID) >= 0);\n            }\n\n            void SelectAndFrameParentOf(int instanceID)\n            {\n                int parentInstanceID = 0;\n                FilteredHierarchy.FilterResult[] results = m_FilteredHierarchy.results;\n                for (int i = 0; i < results.Length; ++i)\n                {\n                    if (results[i].instanceID == instanceID)\n                    {\n                        if (results[i].isMainRepresentation)\n                            parentInstanceID = 0;\n                        break;\n                    }\n\n                    if (results[i].isMainRepresentation)\n                        parentInstanceID = results[i].instanceID;\n                }\n\n                if (parentInstanceID != 0)\n                {\n                    m_Owner.SetSelection(new int[] {parentInstanceID}, false);\n                    m_Owner.Frame(parentInstanceID, true, false);\n                }\n            }\n\n            bool IsRenaming(int instanceID)\n            {\n                RenameOverlay renameOverlay = m_Owner.GetRenameOverlay();\n                return renameOverlay.IsRenaming() && renameOverlay.userData == instanceID && !renameOverlay.isWaitingForDelay;\n            }\n\n            protected void DrawSubAssetRowBg(int startSubAssetIndex, int endSubAssetIndex, bool continued, float yOffset)\n            {\n                Rect startRect = m_Grid.CalcRect(startSubAssetIndex, yOffset);\n                Rect endRect = m_Grid.CalcRect(endSubAssetIndex, yOffset);\n\n                float texWidth = 30f;\n                float texHeight = 128f;\n                float fraction = startRect.width / texHeight;\n                float overflowHeight = 9f * fraction;\n                float shrinkHeight = 4f;\n\n                // Start\n                bool startIsOnFirstColumn = (startSubAssetIndex % m_Grid.columns) == 0;\n                float adjustStart = startIsOnFirstColumn ? 18f * fraction : m_Grid.horizontalSpacing + fraction * 10f;\n                Rect rect = new Rect(startRect.x - adjustStart, startRect.y + shrinkHeight, texWidth * fraction, startRect.width - shrinkHeight * 2 + overflowHeight - 1);\n                rect.y = Mathf.Round(rect.y);\n                rect.height = Mathf.Ceil(rect.height);\n                Styles.subAssetBg.Draw(rect, GUIContent.none, false, false, false, false);\n\n                // End\n                float scaledWidth = texWidth * fraction;\n                bool endIsOnLastColumn = (endSubAssetIndex % m_Grid.columns) == (m_Grid.columns - 1);\n                float extendEnd = (continued || endIsOnLastColumn) ? 16 * fraction : 8 * fraction;\n                Rect rect2 = new Rect(endRect.xMax - scaledWidth + extendEnd, endRect.y + shrinkHeight, scaledWidth, rect.height);\n                rect2.y = Mathf.Round(rect2.y);\n                rect2.height = Mathf.Ceil(rect2.height);\n                GUIStyle endStyle = continued ? Styles.subAssetBgOpenEnded : Styles.subAssetBgCloseEnded;\n                endStyle.Draw(rect2, GUIContent.none, false, false, false, false);\n\n                // Middle\n                rect = new Rect(rect.xMax, rect.y, rect2.xMin - rect.xMax, rect.height);\n                rect.y = Mathf.Round(rect.y);\n                rect.height = Mathf.Ceil(rect.height);\n                Styles.subAssetBgMiddle.Draw(rect, GUIContent.none, false, false, false, false);\n            }\n\n            void DrawSubAssetBackground(int beginIndex, int endIndex, float yOffset)\n            {\n                if (Event.current.type != EventType.Repaint)\n                    return;\n\n                FilteredHierarchy.FilterResult[] results = m_FilteredHierarchy.results;\n\n                int columns = m_Grid.columns;\n                int rows = (endIndex - beginIndex) / columns + 1;\n\n                for (int y = 0; y < rows; ++y)\n                {\n                    int startSubAssetIndex = -1;\n                    int endSubAssetIndex = -1;\n                    for (int x = 0; x < columns; ++x)\n                    {\n                        int index = beginIndex + (x + y * columns);\n                        if (index >= results.Length)\n                            break;\n\n                        FilteredHierarchy.FilterResult result = results[index];\n                        if (!result.isMainRepresentation)\n                        {\n                            if (startSubAssetIndex == -1)\n                                startSubAssetIndex = index;\n                            endSubAssetIndex = index;\n                        }\n                        else\n                        {\n                            // Check if a section was ended\n                            if (startSubAssetIndex != -1)\n                            {\n                                DrawSubAssetRowBg(startSubAssetIndex, endSubAssetIndex, false, yOffset);\n                                startSubAssetIndex = -1;\n                                endSubAssetIndex = -1;\n                            }\n                        }\n                    }\n\n                    if (startSubAssetIndex != -1)\n                    {\n                        bool continued = false;\n                        if (y < rows - 1)\n                        {\n                            int indexFirstColumnNextRow = beginIndex + (y + 1) * columns;\n                            if (indexFirstColumnNextRow < results.Length)\n                                continued = !results[indexFirstColumnNextRow].isMainRepresentation;\n                        }\n\n                        DrawSubAssetRowBg(startSubAssetIndex, endSubAssetIndex, continued, yOffset);\n                    }\n                }\n            }\n\n            void DrawItem(Rect position, FilteredHierarchy.FilterResult filterItem, BuiltinResource builtinResource, bool isFolderBrowsing)\n            {\n                System.Diagnostics.Debug.Assert((filterItem != null && builtinResource == null) ||\n                    (builtinResource != null && filterItem == null));          // only one should be valid\n\n                Event evt = Event.current;\n                Rect itemRect = position;\n                Rect orgPosition = position;\n\n                var assetReference = new AssetReference() { instanceID = 0 };\n                bool showFoldout = false;\n                if (filterItem != null)\n                {\n                    assetReference.instanceID = filterItem.instanceID;\n                    assetReference.guid = filterItem.guid;\n                    showFoldout = filterItem.hasChildren && !filterItem.isFolder && isFolderBrowsing; // we do not want to be able to expand folders\n                }\n                else if (builtinResource != null)\n                {\n                    assetReference.instanceID = builtinResource.m_InstanceID;\n                }\n\n                int controlID = GetControlIDFromInstanceID(assetReference.instanceID);\n\n                bool selected;\n                if (m_Owner.allowDragging)\n                    selected = m_DragSelection.Count > 0 ? m_DragSelection.Contains(assetReference.instanceID) : m_Owner.IsSelected(assetReference.instanceID);\n                else\n                    selected = m_Owner.IsSelected(assetReference.instanceID);\n\n                if (selected && assetReference.instanceID == m_Owner.m_State.m_LastClickedInstanceID)\n                    m_LastClickedDrawTime = EditorApplication.timeSinceStartup;\n\n                Rect foldoutRect = new Rect(position.x + Styles.groupFoldout.margin.left, position.y, Styles.groupFoldout.padding.left, position.height); // ListMode foldout\n                if (showFoldout && !ListMode)\n                {\n                    float fraction = position.height / 128f;\n                    float buttonWidth = 28f;\n                    float buttonHeight = 32f;\n\n                    if (fraction < 0.5f)\n                    {\n                        buttonWidth = 14f;\n                        buttonHeight = 16;\n                    }\n                    else if (fraction < 0.75f)\n                    {\n                        buttonWidth = 21f;\n                        buttonHeight = 24f;\n                    }\n\n                    foldoutRect = new Rect(position.xMax - buttonWidth * 0.5f, position.y + (position.height - Styles.resultsGridLabel.fixedHeight) * 0.5f - buttonWidth * 0.5f, buttonWidth, buttonHeight);\n                }\n\n                bool toggleState = false;\n                if (selected && evt.type == EventType.KeyDown && m_Owner.HasFocus()) // We need to ensure we have keyboard focus because rename overlay might have it - and need the key events)\n                {\n                    switch (evt.keyCode)\n                    {\n                        // Fold in\n                        case KeyCode.LeftArrow:\n                            if (ListMode || m_Owner.IsPreviewIconExpansionModifierPressed())\n                            {\n                                if (IsExpanded(assetReference.instanceID))\n                                    toggleState = true;\n                                else\n                                    SelectAndFrameParentOf(assetReference.instanceID);\n                                evt.Use();\n                            }\n                            break;\n\n                        // Fold out\n                        case KeyCode.RightArrow:\n                            if (ListMode || m_Owner.IsPreviewIconExpansionModifierPressed())\n                            {\n                                if (!IsExpanded(assetReference.instanceID))\n                                    toggleState = true;\n                                evt.Use();\n                            }\n                            break;\n                    }\n                }\n\n                // Foldout mouse button logic (rendering the item itself can be found below)\n                if (showFoldout && evt.type == EventType.MouseDown && evt.button == 0 && foldoutRect.Contains(evt.mousePosition))\n                    toggleState = true;\n\n                if (toggleState)\n                {\n                    bool expanded = !IsExpanded(assetReference.instanceID);\n                    if (expanded)\n                        m_ItemFader.Start(m_FilteredHierarchy.GetSubAssetInstanceIDs(assetReference.instanceID));\n                    ChangeExpandedState(assetReference.instanceID, expanded);\n                    evt.Use();\n                    GUIUtility.ExitGUI();\n                }\n\n                bool isRenaming = IsRenaming(assetReference.instanceID);\n\n                Rect labelRect = position;\n                if (!ListMode)\n                    labelRect = new Rect(position.x, position.yMax + 1 - Styles.resultsGridLabel.fixedHeight, position.width - 1, Styles.resultsGridLabel.fixedHeight);\n\n                var vcPadding = VersionControlUtils.isVersionControlConnected && ListMode ? k_ListModeVersionControlOverlayPadding : 0;\n\n                float contentStartX = foldoutRect.xMax;\n                if (ListMode)\n                {\n                    itemRect.x = contentStartX;\n                    if (filterItem != null && !filterItem.isMainRepresentation && isFolderBrowsing)\n                    {\n                        contentStartX = k_ListModeLeftPaddingForSubAssets;\n                        itemRect.x = k_ListModeLeftPaddingForSubAssets + vcPadding * 0.5f;\n                    }\n                    itemRect.width -= itemRect.x;\n                }\n\n                // Draw section\n                if (Event.current.type == EventType.Repaint)\n                {\n                    if (m_DropTargetControlID == controlID && !position.Contains(evt.mousePosition))\n                        m_DropTargetControlID = 0;\n                    bool isDropTarget = controlID == m_DropTargetControlID && m_DragSelection.IndexOf(m_DropTargetControlID) == -1;\n\n                    string labeltext = filterItem != null ? filterItem.name : builtinResource.m_Name;\n                    if (ListMode)\n                    {\n                        if (isRenaming)\n                        {\n                            selected = false;\n                            labeltext = \"\";\n                        }\n\n                        m_Content.text = labeltext;\n                        m_Content.image = null;\n                        Texture2D icon;\n\n                        if (string.IsNullOrEmpty(assetReference.guid) && m_Owner.GetCreateAssetUtility().instanceID == assetReference.instanceID && m_Owner.GetCreateAssetUtility().icon != null)\n                        {\n                            // If we are creating a new asset we might have an icon to use\n                            icon = m_Owner.GetCreateAssetUtility().icon;\n                        }\n                        else if (builtinResource is ExtraItem extraItem)\n                        {\n                            icon = extraItem.m_Icon;\n                        }\n                        else\n                        {\n                            icon = filterItem != null ? filterItem.icon : null;\n                            if (icon == null)\n                            {\n                                if (ShouldGetAssetPreview(assetReference))\n                                {\n                                    if (assetReference.instanceID != 0)\n                                        icon = AssetPreview.GetAssetPreview(assetReference.instanceID, m_Owner.GetAssetPreviewManagerID());\n                                    else if (!string.IsNullOrEmpty(assetReference.guid))\n                                        icon = AssetPreview.GetAssetPreviewFromGUID(assetReference.guid, m_Owner.GetAssetPreviewManagerID());\n                                }\n                                else if (assetReference.instanceID != 0)\n                                {\n                                    icon = AssetPreview.GetMiniTypeThumbnail(EditorUtility.InstanceIDToObject(assetReference.instanceID));\n                                }\n                            }\n                        }\n\n                        if (selected)\n                            Styles.resultsLabel.Draw(position, GUIContent.none, false, false, selected, m_Owner.HasFocus());\n\n                        if (isDropTarget)\n                            Styles.resultsLabel.Draw(position, GUIContent.none, true, true, false, false);\n\n                        DrawIconAndLabel(new Rect(contentStartX, position.y, position.width - contentStartX, position.height),\n                            filterItem, labeltext, icon, selected, m_Owner.HasFocus());\n\n                        // Foldout!\n                        if (showFoldout)\n                            Styles.groupFoldout.Draw(foldoutRect, !ListMode, !ListMode, IsExpanded(assetReference.instanceID), false);\n                    }\n                    else // Icon grid\n                    {\n                        Texture previewImage = null;\n\n                        // Get icon\n                        bool drawDropShadow = false;\n                        if (string.IsNullOrEmpty(assetReference.guid) && m_Owner.GetCreateAssetUtility().instanceID == assetReference.instanceID && m_Owner.GetCreateAssetUtility().icon != null)\n                        {\n                            // If we are creating a new asset we might have an icon to use\n                            m_Content.image = m_Owner.GetCreateAssetUtility().icon;\n                        }\n                        else if (builtinResource is ExtraItem extraItem)\n                        {\n                            m_Content.image = extraItem.m_Icon;\n                        }\n                        else\n                        {\n                            // Check for asset preview\n                            bool shouldGetAssetPreview = ShouldGetAssetPreview(assetReference);\n                            if (shouldGetAssetPreview)\n                            {\n                                if (assetReference.instanceID != 0)\n                                    previewImage = AssetPreview.GetAssetPreview(assetReference.instanceID, m_Owner.GetAssetPreviewManagerID());\n                                else if (!string.IsNullOrEmpty(assetReference.guid))\n                                    previewImage = AssetPreview.GetAssetPreviewFromGUID(assetReference.guid, m_Owner.GetAssetPreviewManagerID());\n                            }\n\n                            m_Content.image = previewImage;\n                            if (m_Content.image != null)\n                                drawDropShadow = true;\n\n                            if (filterItem != null)\n                            {\n                                // Otherwise use cached icon\n                                if (m_Content.image == null)\n                                    m_Content.image = filterItem.icon;\n\n                                // When folder browsing sub assets are shown on a background slate and do not need rounded corner overlay\n                                if (isFolderBrowsing && !filterItem.isMainRepresentation)\n                                    drawDropShadow = false;\n                            }\n\n                            // If the icon is still hasn't been found, fall back to the default one\n                            if (m_Content.image == null && assetReference.instanceID != 0)\n                            {\n                                m_Content.image = AssetPreview.GetMiniTypeThumbnail(EditorUtility.InstanceIDToObject(assetReference.instanceID));\n                            }\n                        }\n\n                        float padding = (drawDropShadow) ? 2.0f : 0.0f; // the padding compensates for the drop shadow (so it doesn't get too close to the label text)\n                        position.height -= Styles.resultsGridLabel.fixedHeight + 2 * padding; // get icon rect (remove label height which is included in the position rect)\n                        position.y += padding;\n\n                        Rect actualImageDrawPosition = (m_Content.image == null) ? new Rect() : ActualImageDrawPosition(position, m_Content.image.width, m_Content.image.height);\n                        m_Content.text = null;\n                        float alpha = 1f;\n\n                        if (filterItem != null)\n                        {\n                            AddDirtyStateFor(filterItem.instanceID);\n\n                            if (!filterItem.isMainRepresentation && isFolderBrowsing)\n                            {\n                                position.x += 4f;\n                                position.y += 4f;\n                                position.width -= 8f;\n                                position.height -= 8f;\n\n                                actualImageDrawPosition = (m_Content.image == null) ? new Rect() : ActualImageDrawPosition(position, m_Content.image.width, m_Content.image.height);\n\n                                alpha = m_ItemFader.GetAlpha(filterItem.instanceID);\n                                if (alpha < 1f)\n                                    m_Owner.Repaint();\n                            }\n\n                            // Draw static preview bg color as bg for small textures and non-square textures\n                            if (drawDropShadow && filterItem.iconDrawStyle == IconDrawStyle.NonTexture)\n                                Styles.previewBg.Draw(actualImageDrawPosition, GUIContent.none, false, false, false, false);\n                        }\n\n                        var color = ProjectBrowser.GetAssetItemColor(assetReference.instanceID);\n\n                        using (new GUI.ColorScope(color))\n                        {\n                            Color orgColor = GUI.color;\n                            if (selected)\n                                GUI.color = GUI.color * new Color(0.85f, 0.9f, 1f);\n\n                            if (m_Content.image != null)\n                            {\n                                Color orgColor2 = GUI.color;\n                                if (alpha < 1f)\n                                    GUI.color = new Color(GUI.color.r, GUI.color.g, GUI.color.b, alpha);\n\n                                Styles.resultsGrid.Draw(actualImageDrawPosition, m_Content, false, false, selected, m_Owner.HasFocus());\n                                DynamicHintUtility.DrawHint(position, evt.mousePosition, assetReference);\n\n                                if (alpha < 1f)\n                                    GUI.color = orgColor2;\n                            }\n\n                            if (selected)\n                                GUI.color = orgColor;\n\n                            if (drawDropShadow)\n                            {\n                                Rect borderPosition = new RectOffset(1, 1, 1, 1).Remove(Styles.textureIconDropShadow.border.Add(actualImageDrawPosition));\n                                Styles.textureIconDropShadow.Draw(borderPosition, GUIContent.none, false, false, selected || isDropTarget, m_Owner.HasFocus() || isRenaming || isDropTarget);\n                            }\n\n                            // Draw label\n                            if (!isRenaming)\n                            {\n                                if (isDropTarget)\n                                    Styles.resultsLabel.Draw(new Rect(labelRect.x - 10, labelRect.y, labelRect.width + 20, labelRect.height), GUIContent.none, true, true, false, false);\n\n\n                                Texture2D typeIcon = null;\n                                if (filterItem != null && previewImage != null)\n                                {\n                                    Type type = InternalEditorUtility.GetTypeWithoutLoadingObject(filterItem.instanceID);\n                                    \n                                    if (type != typeof(Texture2D))\n                                    {\n                                        typeIcon = filterItem.icon;\n                                    }\n                                }\n\n                                if (builtinResource != null)\n                                {\n                                    Type type = InternalEditorUtility.GetTypeWithoutLoadingObject(builtinResource.m_InstanceID);\n\n                                    if (type != typeof(Texture2D))\n                                    {\n                                        typeIcon = AssetPreview.GetMiniTypeThumbnail(type);\n                                    }\n                                }\n\n                                var orgClipping = Styles.resultsGridLabel.clipping;\n                                var orgAlignment = Styles.resultsLabel.alignment;\n                                var size  = Styles.resultsGridLabel.CalcSizeWithConstraints(GUIContent.Temp(labeltext, typeIcon), orgPosition.size);\n                                size.x += Styles.resultsGridLabel.padding.horizontal;\n                                labelRect.x = orgPosition.x + (orgPosition.width - size.x) / 2.0f;\n                                labelRect.width = size.x;\n                                labelRect.height = size.y;\n                                m_Owner.sizeUsedForCroppingName = orgPosition.size;\n\n                                Styles.resultsGridLabel.clipping = TextClipping.Ellipsis;\n                                Styles.resultsGridLabel.alignment = TextAnchor.MiddleCenter;\n                                Styles.resultsGridLabel.Draw(labelRect, GUIContent.Temp(labeltext, typeIcon), false, false, selected, m_Owner.HasFocus());\n                                Styles.resultsGridLabel.clipping = orgClipping;\n                                Styles.resultsLabel.alignment = orgAlignment;\n\n                                // We only need to set the tooltip once, and not for every item.\n                                if (labelRect.Contains(Event.current.mousePosition))\n                                {\n                                    string tooltip = null;\n\n                                    if (filterItem != null)\n                                    {\n                                        //We use GetAssetPath to have the file extension as well\n                                        string path = AssetDatabase.GetAssetPath(filterItem.instanceID);\n                                        tooltip = path.Substring(path.LastIndexOf('/') + 1);\n                                    }\n                                    else if (builtinResource != null)\n                                    {\n                                        //We have a \"None\" item in the ObjectSelector that has a 0 instanceID\n                                        if (builtinResource.m_InstanceID != 0)     \n                                            tooltip = builtinResource.m_Name + \"\\n\" + \"(Built-in Resource)\";\n                                    }\n\n                                    if (tooltip != null)\n                                    {\n                                        GUI.Label(labelRect, GUIContent.Temp(\"\", tooltip));\n                                    }\n                                }\n                            }\n                        }\n\n                        if (showFoldout)\n                        {\n                            var style = Styles.subAssetExpandButton;\n\n                            if (foldoutRect.height <= 16)\n                            {\n                                style = Styles.subAssetExpandButtonSmall;\n                            }\n                            else if (foldoutRect.height <= 24)\n                            {\n                                style = Styles.subAssetExpandButtonMedium;\n                            }\n                            style.Draw(foldoutRect, !ListMode, !ListMode, IsExpanded(assetReference.instanceID), false);\n                        }\n\n                        if (filterItem != null && filterItem.isMainRepresentation)\n                        {\n                            if (null != postAssetIconDrawCallback)\n                            {\n                                postAssetIconDrawCallback(position, filterItem.guid, false);\n                            }\n\n                            ProjectHooks.OnProjectWindowItem(filterItem.guid, position, m_OwnerRepaintAction);\n                        }\n                    }\n                }\n                // Adjust edit field if needed\n                if (isRenaming)\n                {\n                    if (ListMode)\n                    {\n                        float iconOffset = vcPadding + k_IconWidth + k_SpaceBetweenIconAndText + Styles.resultsLabel.margin.left;\n                        labelRect.x = itemRect.x + iconOffset;\n                        labelRect.width -= labelRect.x;\n                    }\n                    else\n                    {\n                        labelRect.x -= 4;\n                        labelRect.width += 8f;\n                    }\n                    m_Owner.GetRenameOverlay().editFieldRect = labelRect;\n                    m_Owner.HandleRenameOverlay();\n                }\n\n                // User hook for rendering stuff on top of items (notice it being called after rendering but before mouse handling to make user able to react on mouse events)\n                if (filterItem != null && m_Owner.allowUserRenderingHook)\n                {\n                    if (EditorApplication.projectWindowItemOnGUI != null)\n                        EditorApplication.projectWindowItemOnGUI(filterItem.guid, itemRect);\n\n                    if (EditorApplication.projectWindowItemInstanceOnGUI != null)\n                        EditorApplication.projectWindowItemInstanceOnGUI(filterItem.instanceID, itemRect);\n                }\n\n                // Mouse handling (must be after rename overlay to ensure overlay get mouseevents)\n                if (m_Owner.allowDragging)\n                    HandleMouseWithDragging(ref assetReference, controlID, position);\n                else\n                    HandleMouseWithoutDragging(ref assetReference, controlID, position);\n\n                if (filterItem != null && filterItem.instanceID == 0)\n                    filterItem.instanceID = assetReference.instanceID;\n            }\n\n            private static Rect ActualImageDrawPosition(Rect position, float imageWidth, float imageHeight)\n            {\n                if (imageWidth > position.width || imageHeight > position.height)\n                {\n                    Rect screenRect = new Rect();\n                    Rect sourceRect = new Rect();\n                    float imageAspect = imageWidth / imageHeight;\n                    GUI.CalculateScaledTextureRects(position, ScaleMode.ScaleToFit, imageAspect, ref screenRect, ref sourceRect);\n                    return screenRect;\n                }\n                else\n                {\n                    float x = position.x + Mathf.Round((position.width - imageWidth) / 2.0f);\n                    float y = position.y + Mathf.Round((position.height - imageHeight) / 2.0f);\n                    return new Rect(x, y, imageWidth, imageHeight);\n                }\n            }\n\n            public List<KeyValuePair<string, int>> GetVisibleNameAndInstanceIDs()\n            {\n                List<KeyValuePair<string, int>> result = new List<KeyValuePair<string, int>>();\n\n                // 1. None item\n                if (m_NoneList.Length > 0)\n                    result.Add(new KeyValuePair<string, int>(m_NoneList[0].m_Name, m_NoneList[0].m_InstanceID)); // 0\n\n                // 2. Project Assets\n                foreach (FilteredHierarchy.FilterResult r in m_FilteredHierarchy.results)\n                    result.Add(new KeyValuePair<string, int>(r.name, r.instanceID));\n\n                // 3. Builtin\n                for (int i = 0; i < m_ActiveBuiltinList.Length; ++i)\n                    result.Add(new KeyValuePair<string, int>(m_ActiveBuiltinList[i].m_Name, m_ActiveBuiltinList[i].m_InstanceID));\n\n                return result;\n            }\n\n            private void BeginPing(int instanceID)\n            {\n            }\n\n            public void GetAssetReferences(out List<int> instanceIDs, out List<string> guids)\n            {\n                instanceIDs = new List<int>();\n                guids = new List<string>();\n\n                // 1. None item\n                if (m_NoneList.Length > 0)\n                {\n                    instanceIDs.Add(m_NoneList[0].m_InstanceID); // 0\n                    guids.Add(null);\n                }\n\n                // 2. Project Assets\n                foreach (FilteredHierarchy.FilterResult r in m_FilteredHierarchy.results)\n                {\n                    instanceIDs.Add(r.instanceID);\n                    guids.Add(r.guid);\n                }\n\n                if (m_Owner.m_State.m_NewAssetIndexInList >= 0)\n                {\n                    instanceIDs.Add(m_Owner.GetCreateAssetUtility().instanceID);\n                    guids.Add(null);\n                }\n\n                // 3. Builtin\n                for (int i = 0; i < m_ActiveBuiltinList.Length; ++i)\n                {\n                    instanceIDs.Add(m_ActiveBuiltinList[i].m_InstanceID);\n                    guids.Add(null);\n                }\n            }\n\n            // Returns list of selected instanceIDs\n            public List<int> GetNewSelection(ref AssetReference clickedAssetReference, bool beginOfDrag, bool useShiftAsActionKey)\n            {\n                // Flatten grid\n                List<int> instanceIDs;\n                List<string> guids;\n                GetAssetReferences(out instanceIDs, out guids);\n                List<int> selectedInstanceIDs = m_Owner.m_State.m_SelectedInstanceIDs;\n                int lastClickedInstanceID = m_Owner.m_State.m_LastClickedInstanceID;\n                bool allowMultiselection = m_Owner.allowMultiSelect;\n\n                return InternalEditorUtility.GetNewSelection(ref clickedAssetReference, instanceIDs, guids, selectedInstanceIDs, lastClickedInstanceID, beginOfDrag, useShiftAsActionKey, allowMultiselection);\n            }\n\n            public override void UpdateFilter(HierarchyType hierarchyType, SearchFilter searchFilter, bool foldersFirst, SearchService.SearchSessionOptions searchSessionOptions)\n            {\n                // Filtered hierarchy list\n                RefreshHierarchy(hierarchyType, searchFilter, foldersFirst, searchSessionOptions);\n\n                // Filtered builtin list\n                RefreshBuiltinResourceList(searchFilter);\n            }\n\n            private void RefreshHierarchy(HierarchyType hierarchyType, SearchFilter searchFilter, bool foldersFirst, SearchService.SearchSessionOptions searchSessionOptions)\n            {\n                m_FilteredHierarchy = new FilteredHierarchy(hierarchyType, searchSessionOptions);\n                m_FilteredHierarchy.foldersFirst = foldersFirst;\n                m_FilteredHierarchy.searchFilter = searchFilter;\n                m_FilteredHierarchy.RefreshVisibleItems(m_Owner.m_State.m_ExpandedInstanceIDs);\n            }\n\n            void RefreshBuiltinResourceList(SearchFilter searchFilter)\n            {\n                // Early out if we do not want to show builtin resources\n                if (!m_Owner.allowBuiltinResources || (searchFilter.GetState() == SearchFilter.State.FolderBrowsing) || (searchFilter.GetState() == SearchFilter.State.EmptySearchFilter))\n                {\n                    m_CurrentBuiltinResources = new BuiltinResource[0];\n                    return;\n                }\n\n                List<BuiltinResource> currentBuiltinResources = new List<BuiltinResource>();\n\n                // Filter by assets labels (Builtins have no asset labels currently)\n                if (searchFilter.assetLabels != null && searchFilter.assetLabels.Length > 0)\n                {\n                    m_CurrentBuiltinResources = currentBuiltinResources.ToArray();\n                    return;\n                }\n\n                // Filter by class/type\n                List<int> requiredClassIDs = new List<int>();\n                foreach (string className in searchFilter.classNames)\n                {\n                    var unityType = UnityType.FindTypeByNameCaseInsensitive(className);\n                    if (unityType != null)\n                        requiredClassIDs.Add(unityType.persistentTypeID);\n                }\n                if (requiredClassIDs.Count > 0)\n                {\n                    foreach (KeyValuePair<string, BuiltinResource[]> kvp in m_BuiltinResourceMap)\n                    {\n                        UnityType classType = UnityType.FindTypeByName(kvp.Key);\n                        if (classType == null)\n                            continue;\n\n                        foreach (int requiredClassID in requiredClassIDs)\n                        {\n                            if (classType.IsDerivedFrom(UnityType.FindTypeByPersistentTypeID(requiredClassID)))\n                                currentBuiltinResources.AddRange(kvp.Value);\n                        }\n                    }\n                }\n\n                // Filter by name\n                BuiltinResource[] builtinList = currentBuiltinResources.ToArray();\n                if (builtinList.Length > 0 && !string.IsNullOrEmpty(searchFilter.nameFilter))\n                {\n                    List<BuiltinResource> filtered = new List<BuiltinResource>(); // allocated here to prevent from allocating on every event.\n                    string nameFilter = searchFilter.nameFilter.ToLower();\n                    foreach (BuiltinResource br in builtinList)\n                        if (br.m_Name.ToLower().Contains(nameFilter))\n                            filtered.Add(br);\n\n                    builtinList = filtered.ToArray();\n                }\n\n                m_CurrentBuiltinResources = builtinList;\n            }\n\n            public string GetNameOfLocalAsset(int instanceID)\n            {\n                foreach (var r in m_FilteredHierarchy.results)\n                {\n                    if (r.instanceID == instanceID)\n                        return r.name;\n                }\n                return null;\n            }\n\n            public bool IsBuiltinAsset(int instanceID)\n            {\n                foreach (KeyValuePair<string, BuiltinResource[]> kvp in m_BuiltinResourceMap)\n                {\n                    BuiltinResource[] list = kvp.Value;\n                    for (int i = 0; i < list.Length; ++i)\n                        if (list[i].m_InstanceID == instanceID)\n                            return true;\n                }\n                return false;\n            }\n\n            private void InitBuiltinAssetType(System.Type type)\n            {\n                if (type == null)\n                {\n                    Debug.LogWarning(\"ObjectSelector::InitBuiltinAssetType: type is null!\");\n                    return;\n                }\n                string typeName = type.ToString().Substring(type.Namespace.Length + 1);\n\n                var unityType = UnityType.FindTypeByName(typeName);\n                if (unityType == null)\n                {\n                    Debug.LogWarning(\"ObjectSelector::InitBuiltinAssetType: class '\" + typeName + \"' not found\");\n                    return;\n                }\n\n                BuiltinResource[] resourceList = EditorGUIUtility.GetBuiltinResourceList(unityType.persistentTypeID);\n                if (resourceList != null)\n                    m_BuiltinResourceMap.Add(typeName, resourceList);\n            }\n\n            private bool ShouldGetAssetPreview(AssetReference assetReference)\n            {\n                string path = AssetDatabase.GUIDToAssetPath(assetReference.guid);\n                if (m_AssetExtensionsPreviewIgnoreList.Contains(System.IO.Path.GetExtension(path).ToLowerInvariant()))\n                    return false;\n                Type assetDataType = InternalEditorUtility.GetTypeWithoutLoadingObject(assetReference.instanceID);\n                if (m_AssetPreviewIgnoreList.Contains(assetDataType))\n                    return false;\n                return true;\n            }\n\n            public void InitBuiltinResources()\n            {\n                if (m_BuiltinResourceMap != null)\n                    return;\n\n                m_BuiltinResourceMap = new Dictionary<string, BuiltinResource[]>();\n\n                if (m_ShowNoneItem)\n                {\n                    m_NoneList = new ExtraItem[1];\n                    m_NoneList[0] = new ExtraItem();\n                    m_NoneList[0].m_InstanceID = 0;\n                    m_NoneList[0].m_Name = \"None\";\n                }\n                else\n                {\n                    m_NoneList = new ExtraItem[0];\n                }\n\n                // We don't show all built-in resources; just the ones where their type\n                // makes sense. The actual lists are in ResourceManager.cpp,\n                // GetBuiltinResourcesOfClass\n                InitBuiltinAssetType(typeof(Mesh));\n                InitBuiltinAssetType(typeof(Material));\n                InitBuiltinAssetType(typeof(Texture2D));\n                InitBuiltinAssetType(typeof(Font));\n                InitBuiltinAssetType(typeof(Shader));\n                InitBuiltinAssetType(typeof(Sprite));\n                InitBuiltinAssetType(typeof(LightmapParameters));\n\n                // PrintBuiltinResourcesAvailable();\n            }\n\n            public void PrintBuiltinResourcesAvailable()\n            {\n                string text = \"\";\n                text += \"ObjectSelector -Builtin Assets Available:\\n\";\n                foreach (KeyValuePair<string, BuiltinResource[]> kvp in m_BuiltinResourceMap)\n                {\n                    BuiltinResource[] list = kvp.Value;\n                    text += \"    \" + kvp.Key + \": \";\n                    for (int i = 0; i < list.Length; ++i)\n                    {\n                        if (i != 0)\n                            text += \", \";\n                        text += list[i].m_Name;\n                    }\n                    text += \"\\n\";\n                }\n                Debug.Log(text);\n            }\n\n            // Can return an index 1 past end of existing items (if newText is last in sort)\n            public int IndexOfNewText(string newText, bool isCreatingNewFolder, bool foldersFirst)\n            {\n                int idx = 0;\n                if (m_ShowNoneItem)\n                    idx++;\n\n                for (; idx < m_FilteredHierarchy.results.Length; ++idx)\n                {\n                    FilteredHierarchy.FilterResult r = m_FilteredHierarchy.results[idx];\n\n                    // Skip folders when inserting a normal asset if folders is sorted first\n                    if (foldersFirst && r.isFolder && !isCreatingNewFolder)\n                        continue;\n\n                    // When inserting a folder in folders first list break when we reach normal assets\n                    if (foldersFirst && !r.isFolder && isCreatingNewFolder)\n                        break;\n\n                    // Use same name compare as when we sort in the backend: See AssetDatabase.cpp: SortChildren\n                    string propertyPath = AssetDatabase.GetAssetPath(r.instanceID);\n                    if (EditorUtility.NaturalCompare(System.IO.Path.GetFileNameWithoutExtension(propertyPath), newText) > 0)\n                    {\n                        return idx;\n                    }\n                }\n                return idx;\n            }\n\n            public int IndexOf(int instanceID)\n            {\n                int idx = 0;\n\n                // 1. 'none' first (has instanceID 0)\n                if (m_ShowNoneItem)\n                {\n                    if (instanceID == 0)\n                        return 0;\n                    else\n                        idx++;\n                }\n                else if (instanceID == 0)\n                    return -1;\n\n                // 2. Project assets\n                foreach (FilteredHierarchy.FilterResult r in m_FilteredHierarchy.results)\n                {\n                    // When creating new asset we jump over that item (assuming we do not search for that new asset)\n                    if (m_Owner.m_State.m_NewAssetIndexInList == idx)\n                        idx++;\n\n                    if (r.instanceID == instanceID)\n                        return idx;\n                    idx++;\n                }\n\n                // 3. Builtin resources\n                foreach (BuiltinResource b in m_ActiveBuiltinList)\n                {\n                    if (instanceID == b.m_InstanceID)\n                        return idx;\n                    idx++;\n                }\n                return -1;\n            }\n\n            public FilteredHierarchy.FilterResult LookupByInstanceID(int instanceID)\n            {\n                if (instanceID == 0)\n                    return null;\n\n                int idx = 0;\n                foreach (FilteredHierarchy.FilterResult r in m_FilteredHierarchy.results)\n                {\n                    // When creating new asset we jump over that item (assuming we do not search for that new asset)\n                    if (m_Owner.m_State.m_NewAssetIndexInList == idx)\n                        idx++;\n\n                    if (r.instanceID == instanceID)\n                        return r;\n                    idx++;\n                }\n                return null;\n            }\n\n            // Returns true if index was valid. Note that instance can be 0 if 'None' item was found at index\n            public bool AssetReferenceAtIndex(int index, out AssetReference assetReference)\n            {\n                assetReference = new AssetReference() { instanceID = 0 };\n                if (index >= m_Grid.rows * m_Grid.columns)\n                    return false;\n\n                int idx = 0;\n\n                // 1. 'none' first (has instanceID 0)\n                if (m_ShowNoneItem)\n                {\n                    if (index == 0)\n                        return true;\n                    else\n                        idx++;\n                }\n\n                // 2. Project assets\n                foreach (FilteredHierarchy.FilterResult r in m_FilteredHierarchy.results)\n                {\n                    assetReference.instanceID = r.instanceID;\n                    assetReference.guid = r.guid;\n                    if (idx == index)\n                        return true;\n                    idx++;\n                }\n\n                // 3. Builtin resources\n                foreach (BuiltinResource b in m_ActiveBuiltinList)\n                {\n                    assetReference.instanceID = b.m_InstanceID;\n                    if (idx == index)\n                        return true;\n                    idx++;\n                }\n\n                // If last row and the row is not entirely filled\n                // we just use the last item on that row\n                if (index < m_Grid.rows * m_Grid.columns)\n                    return true;\n\n                return false;\n            }\n\n            public virtual void StartDrag(int draggedInstanceID, List<int> selectedInstanceIDs)\n            {\n                ProjectWindowUtil.StartDrag(draggedInstanceID, selectedInstanceIDs);\n            }\n\n            public DragAndDropVisualMode DoDrag(int dragToInstanceID, bool perform)\n            {\n                return DragAndDrop.DropOnProjectBrowserWindow(dragToInstanceID, AssetDatabase.GetAssetPath(dragToInstanceID), perform);\n            }\n\n            static internal int GetControlIDFromInstanceID(int instanceID)\n            {\n                return instanceID + 100000000;\n            }\n\n            public bool DoCharacterOffsetSelection()\n            {\n                if (Event.current.type == EventType.KeyDown && Event.current.shift && Event.current.character != 0)\n                {\n                    System.StringComparison ignoreCase = System.StringComparison.CurrentCultureIgnoreCase;\n                    string startName = \"\";\n                    if (Selection.activeObject != null)\n                        startName = Selection.activeObject.name;\n\n                    string c = new string(new[] {Event.current.character});\n                    List<KeyValuePair<string, int>> list = GetVisibleNameAndInstanceIDs();\n                    if (list.Count == 0)\n                        return false;\n\n\n                    // If same c is same start char as current selected then find current selected index\n                    int startIndex = 0;\n                    if (startName.StartsWith(c, ignoreCase))\n                    {\n                        // Iterate from there until next char is found\n                        for (int i = 0; i < list.Count; ++i)\n                        {\n                            if (list[i].Key == startName)\n                            {\n                                startIndex = i + 1;\n                            }\n                        }\n                    }\n\n                    // Check all items starting with startIndex\n                    for (int i = 0; i < list.Count; i++)\n                    {\n                        int index = (i + startIndex) % list.Count;\n\n                        if (list[index].Key.StartsWith(c, ignoreCase))\n                        {\n                            Selection.activeInstanceID = list[index].Value;\n                            m_Owner.Repaint();\n                            return true;\n                        }\n                    }\n                }\n\n                return false;\n            }\n\n            public void ShowObjectsInList(int[] instanceIDs)\n            {\n                m_FilteredHierarchy = new FilteredHierarchy(HierarchyType.Assets);\n                m_FilteredHierarchy.SetResults(instanceIDs);\n            }\n\n            internal void ShowObjectsInList(int[] instanceIDs, string[] rootPaths)\n            {\n                m_FilteredHierarchy = new FilteredHierarchy(HierarchyType.Assets);\n                m_FilteredHierarchy.SetResults(instanceIDs, rootPaths);\n            }\n\n            public void DrawIconAndLabel(Rect rect, FilteredHierarchy.FilterResult filterItem, string label, Texture2D icon, bool selected, bool focus)\n            {\n                var color = filterItem == null ? GUI.color : ProjectBrowser.GetAssetItemColor(filterItem.instanceID);\n\n                float vcPadding = s_VCEnabled ? k_ListModeVersionControlOverlayPadding : 0f;\n                using (new GUI.ColorScope(color))\n                {\n                    rect.xMin += Styles.resultsLabel.margin.left;\n\n                    if (filterItem != null)\n                    {\n                        var assetReference = new AssetReference() { instanceID = filterItem.instanceID };\n                        assetReference.guid = filterItem.guid;\n                        DynamicHintUtility.DrawHint(rect, Event.current.mousePosition, assetReference);\n                    }\n\n                    // Reduce the label width to allow delegate drawing on the right.\n                    float delegateDrawWidth = (k_ListModeExternalIconPadding * 2) + k_IconWidth;\n                    Rect delegateDrawRect = new Rect(rect.xMax - delegateDrawWidth, rect.y, delegateDrawWidth, rect.height);\n                    Rect labelRect = new Rect(rect);\n                    if (DrawExternalPostLabelInList(delegateDrawRect, filterItem))\n                    {\n                        labelRect.width = (rect.width - delegateDrawWidth);\n                    }\n\n                    Styles.resultsLabel.padding.left = (int)(vcPadding + k_IconWidth + k_SpaceBetweenIconAndText);\n                    Styles.resultsLabel.Draw(labelRect, label, false, false, selected, focus);\n\n                    Rect iconRect = rect;\n                    iconRect.width = k_IconWidth;\n                    iconRect.x += vcPadding * 0.5f;\n\n                    if (selected && focus)\n                    {\n                        var activeIcon = EditorUtility.GetIconInActiveState(icon) as Texture2D;\n\n                        if (activeIcon)\n                            icon = activeIcon;\n                    }\n\n                    if (icon != null)\n                        GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleToFit);\n                }\n\n                if (filterItem != null && filterItem.guid != null && filterItem.isMainRepresentation)\n                {\n                    Rect overlayRect = rect;\n                    overlayRect.width = vcPadding + k_IconWidth;\n\n                    if (null != postAssetIconDrawCallback)\n                    {\n                        postAssetIconDrawCallback(overlayRect, filterItem.guid, true);\n                    }\n                    ProjectHooks.OnProjectWindowItem(filterItem.guid, overlayRect, m_OwnerRepaintAction);\n                }\n            }\n\n            private static bool DrawExternalPostLabelInList(Rect drawRect, FilteredHierarchy.FilterResult filterItem)\n            {\n                bool didDraw = false;\n                if (filterItem != null && filterItem.guid != null && filterItem.isMainRepresentation)\n                {\n                    if (null != postAssetLabelDrawCallback)\n                    {\n                        didDraw = postAssetLabelDrawCallback(drawRect, filterItem.guid, true);\n                    }\n                }\n                return didDraw;\n            }\n\n            class ItemFader\n            {\n                double m_FadeDuration = 0.3;\n                double m_FirstToLastDuration = 0.3;\n                double m_FadeStartTime;\n                double m_TimeBetweenEachItem;\n                List<int> m_InstanceIDs;\n\n                public void Start(List<int> instanceIDs)\n                {\n                    m_InstanceIDs = instanceIDs;\n                    m_FadeStartTime = EditorApplication.timeSinceStartup;\n                    m_FirstToLastDuration = Math.Min(0.5, instanceIDs.Count * 0.03);\n                    m_TimeBetweenEachItem = 0;\n                    if (m_InstanceIDs.Count > 1)\n                        m_TimeBetweenEachItem = m_FirstToLastDuration / (m_InstanceIDs.Count - 1);\n                }\n\n                public float GetAlpha(int instanceID)\n                {\n                    if (m_InstanceIDs == null)\n                        return 1f;\n\n                    if (EditorApplication.timeSinceStartup > m_FadeStartTime + m_FadeDuration + m_FirstToLastDuration)\n                    {\n                        m_InstanceIDs = null; // reset\n                        return 1f;\n                    }\n\n                    int index = m_InstanceIDs.IndexOf(instanceID);\n                    if (index >= 0)\n                    {\n                        double elapsed = EditorApplication.timeSinceStartup - m_FadeStartTime;\n                        double itemStartTime = m_TimeBetweenEachItem * index;\n\n                        float alpha = 0f;\n                        if (itemStartTime < elapsed)\n                        {\n                            alpha = Mathf.Clamp((float)((elapsed - itemStartTime) / m_FadeDuration), 0f, 1f);\n                        }\n                        return alpha;\n                    }\n                    return 1f;\n                }\n            }\n        }\n    }\n}  // namespace UnityEditor\n"
  },
  {
    "path": "Editor/Mono/ObjectNames.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nusing UnityObject = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    // Helper class for constructing displayable names for objects.\n    [NativeHeader(\"Editor/Src/Utility/ObjectNames.bindings.h\")]\n    public sealed partial class ObjectNames\n    {\n        // Class name of an object.\n        [FreeFunction(\"GetClassName_Internal\")]\n        public static extern string GetClassName([NotNull] UnityObject obj);\n\n        // Drag and drop title for an object.\n        [FreeFunction]\n        public static extern string GetDragAndDropTitle(UnityObject obj);\n\n        // Sets the name of an Object.\n        [FreeFunction(\"SetObjectNameSmart\")]\n        public static extern void SetNameSmart(UnityObject obj, string name);\n\n        [FreeFunction(\"SetNameSmartWithInstanceID_Internal\")]\n        internal static extern void SetNameSmartWithInstanceID(int instanceID, string name);\n\n        [FreeFunction(\"GetUniqueName_Internal\")]\n        public static extern string GetUniqueName(string[] existingNames, string name);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ObjectNames.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing JetBrains.Annotations;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    public sealed partial class ObjectNames\n    {\n        static class InspectorTitles\n        {\n            static readonly Dictionary<Type, string> s_InspectorTitles;\n\n            static InspectorTitles()\n            {\n                var addComponentMenuTypes = TypeCache.GetTypesWithAttribute<AddComponentMenu>();\n\n                s_InspectorTitles = new Dictionary<Type, string>(addComponentMenuTypes.Count);\n\n                foreach (var type in addComponentMenuTypes)\n                {\n                    var attr = type.GetCustomAttributes(typeof(AddComponentMenu), false).FirstOrDefault()\n                        as AddComponentMenu;\n                    if (attr == null)\n                        continue;\n                    var title = attr.componentMenu?.Trim();\n                    if (string.IsNullOrEmpty(title))\n                        continue;\n                    var lastPathCharIndex = title.LastIndexOf('/');\n                    if (lastPathCharIndex >= 0)\n                        if (lastPathCharIndex < title.Length - 1)\n                            title = title.Substring(lastPathCharIndex + 1);\n                        else\n                            continue;\n\n                    s_InspectorTitles[type] = title;\n                }\n            }\n\n            public static bool TryGet(Type objectType, out string title)\n            {\n                return s_InspectorTitles.TryGetValue(objectType, out title);\n            }\n        }\n\n        // Make a displayable name for a variable.\n        public static string NicifyVariableName(string name) => NameFormatter.FormatVariableName(name);\n\n        private static string GetObjectTypeName([NotNull] Object o, bool multiObjectEditing = false)\n        {\n            if (o is GameObject)\n                return o.name;\n\n            // Show \"Tags & Layers\" instead of \"TagManager\"\n            if (o is TagManager)\n                return \"Tags & Layers\";\n\n            if (o is Component)\n            {\n                var behaviour = o as MonoBehaviour;\n                if (behaviour)\n                {\n                    var scriptClassName = behaviour.GetScriptClassName();\n                    if (scriptClassName == \"InvalidStateMachineBehaviour\")\n                        return behaviour.name + L10n.Tr(\" (Script)\");\n                    return scriptClassName + L10n.Tr(\" (Script)\");\n                }\n\n                var meshfilter = o as MeshFilter;\n                if (meshfilter)\n                {\n                    if (multiObjectEditing)\n                        return \"MeshFilter\";\n\n                    var mesh = meshfilter.sharedMesh;\n                    return (mesh ? mesh.name : L10n.Tr(\"[none]\")) + \" (MeshFilter)\";\n                }\n\n                return o.GetType().Name;\n            }\n\n            // Importers don't have names. Just show the type without parenthesis (like we do for components).\n            if (o is AssetImporter)\n            {\n                var monoImporter = o as MonoImporter;\n                if (monoImporter)\n                {\n                    var script = monoImporter.GetScript();\n                    return \"Default References (\" + (script ? script.name : string.Empty) + \")\";\n                }\n\n                if (NativeClassExtensionUtilities.ExtendsANativeType(o))\n                {\n                    var script = MonoScript.FromScriptedObject(o);\n                    if (script != null)\n                        return script.GetClass().Name + L10n.Tr(\" (Script)\");\n                }\n\n                return o.GetType().Name;\n            }\n\n            return o.name + \" (\" + o.GetType().Name + \")\";\n        }\n\n        public static string GetInspectorTitle(Object obj, bool multiObjectEditing)\n        {\n            // Note: The following condition is true when the native MonoBehaviour/ScriptableObject is destroyed but not its managed counterpart\n            if (obj == null && (object)obj != null && (obj is MonoBehaviour || obj is ScriptableObject))\n                return L10n.Tr(\" (Script)\");\n\n            if (obj == null)\n                return L10n.Tr(\"Nothing Selected\");\n\n            string title;\n            if (!InspectorTitles.TryGet(obj.GetType(), out title))\n                title = NicifyVariableName(GetObjectTypeName(obj, multiObjectEditing));\n\n            if (Attribute.IsDefined(obj.GetType(), typeof(ObsoleteAttribute)))\n                title += L10n.Tr(\" (Deprecated)\");\n\n            return title;\n        }\n\n        // Inspector title for an object.\n        public static string GetInspectorTitle(Object obj)\n        {\n            return GetInspectorTitle(obj, false);\n        }\n\n        // Like GetClassName but handles folders, scenes, GUISkins, and other default assets as separate types.\n        internal static string GetTypeName(Object obj)\n        {\n            // Return \"Object\" when null so we have a icon in the inspector(null does not have an icon). case 707513.\n            if (obj == null)\n                return \"Object\";\n\n            string pathLower = AssetDatabase.GetAssetPath(obj).ToLower();\n            if (pathLower.EndsWith(\".unity\"))\n                return \"Scene\";\n            else if (pathLower.EndsWith(\".guiskin\"))\n                return \"GUI Skin\";\n            else if (System.IO.Directory.Exists(AssetDatabase.GetAssetPath(obj)))\n                return \"Folder\";\n            else if (obj.GetType() == typeof(Object))\n                return System.IO.Path.GetExtension(pathLower) + \" File\";\n            return obj.GetType().Name;\n        }\n\n        [Obsolete(\"Please use NicifyVariableName instead\")]\n        public static string MangleVariableName(string name)\n        {\n            return NicifyVariableName(name);\n        }\n\n        [Obsolete(\"Please use GetInspectorTitle instead\")]\n        public static string GetPropertyEditorTitle(Object obj)\n        {\n            return GetInspectorTitle(obj);\n        }\n\n        internal static string CapitaliseFirstLetter(string srt) => $\"{char.ToUpper(srt[0], CultureInfo.InvariantCulture).ToString()}{srt.Substring(1)}\";\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ObjectPool/PoolManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor.ObjectPool\n{\n    [InitializeOnLoad]\n    static class PoolManager\n    {\n        static PoolManager() => EditorApplication.playModeStateChanged += OnEditorStateChange;\n\n        static void OnEditorStateChange(PlayModeStateChange stateChange)\n        {\n            if(!EditorSettings.enterPlayModeOptionsEnabled\n                || !EditorSettings.enterPlayModeOptions.HasFlag(EnterPlayModeOptions.DisableDomainReload))\n            {\n                return;\n            }\n\n            switch (stateChange)\n            {\n                case PlayModeStateChange.EnteredEditMode:\n                case PlayModeStateChange.EnteredPlayMode:\n                    UnityEngine.Pool.PoolManager.Reset();\n                    break;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ObjectSelector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing JetBrains.Annotations;\nusing UnityEditor.AnimatedValues;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.SceneManagement;\nusing UnityEditor.SearchService;\nusing UnityEditor.ShortcutManagement;\nusing UnityEditor.UIElements;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Audio;\nusing UnityEngine.UIElements;\nusing UnityObject = UnityEngine.Object;\nusing Scene = UnityEngine.SceneManagement.Scene;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\n\nnamespace UnityEditor\n{\n    internal abstract class ObjectSelectorReceiver : ScriptableObject\n    {\n        public abstract void OnSelectionChanged(UnityObject selection);\n        public abstract void OnSelectionClosed(UnityObject selection);\n    }\n\n    internal class ObjectSelector : EditorWindow\n    {\n        // Styles used in the object selector\n        static class Styles\n        {\n            public static GUIStyle smallStatus = \"ObjectPickerSmallStatus\";\n            public static GUIStyle largeStatus = \"ObjectPickerLargeStatus\";\n            public static GUIStyle tab = \"ObjectPickerTab\";\n            public static GUIStyle bottomResize = \"WindowBottomResize\";\n            public static GUIStyle previewBackground = \"PopupCurveSwatchBackground\"; // TODO: Make dedicated style\n            public static GUIStyle previewTextureBackground = \"ObjectPickerPreviewBackground\"; // TODO: Make dedicated style\n\n            public static GUIContent assetsTabLabel = EditorGUIUtility.TrTextContent(\"Assets\");\n            public static GUIContent sceneTabLabel = EditorGUIUtility.TrTextContent(\"Scene\");\n\n            public static readonly GUIContent packagesVisibilityContent = EditorGUIUtility.TrIconContent(\"SceneViewVisibility\", \"Number of hidden packages, click to toggle packages visibility\");\n\n            public const string rootName = \"unity-object-selector\";\n            public const string headerName = rootName + \"__header\";\n            public const string searchBarName = rootName + \"__search-bar\";\n            public const string searchFieldName = rootName + \"__search-field\";\n            public const string toolbarName = rootName + \"__toolbar\";\n            public const string tabViewName = rootName + \"__tab-view\";\n            public const string assetsTabName = rootName + \"__assets-tab\";\n            public const string sceneTabName = rootName + \"__scene-tab\";\n            public const string gridSizeSliderName = rootName + \"__grid-size-slider\";\n            public const string skipHiddenPackagesToggleName = rootName + \"__skip-hidden-packages-toggle\";\n            public const string imguiContainerName = rootName + \"__imgui-container\";\n\n            public const string mainStyleSheetPath = \"StyleSheets/ObjectSelector/ObjectSelector.uss\";\n            public const string darkThemeStyleSheetPath = \"StyleSheets/ObjectSelector/ObjectSelectorDark.uss\";\n            public const string lightThemeStyleSheetPath = \"StyleSheets/ObjectSelector/ObjectSelectorLight.uss\";\n\n            public const string treeViewVariantClassName = rootName + \"--treeview\";\n        }\n\n        public const string ObjectSelectorClosedCommand = \"ObjectSelectorClosed\";\n        public const string ObjectSelectorUpdatedCommand = \"ObjectSelectorUpdated\";\n        public const string ObjectSelectorCanceledCommand = \"ObjectSelectorCanceled\";\n        public const string ObjectSelectorSelectionDoneCommand = \"ObjectSelectorSelectionDone\";\n\n        // Filters\n        string[]        m_RequiredTypes;\n        Type[]          m_RequiredRawTypes;\n        string          m_SearchFilter;\n\n        // Display state\n        bool            m_AllowSceneObjects;\n        bool            m_IsShowingAssets;\n        bool            m_SkipHiddenPackages;\n        SavedInt        m_StartGridSize = new SavedInt(\"ObjectSelector.GridSize\", 64);\n\n        // UI Elememts\n        UnityEditor.UIElements.Toolbar  m_Toolbar;\n        ToolbarSearchField              m_SearchField;\n        ToolbarToggle                   m_SkipHiddenPackagesToggle;\n        IMGUIContainer                  m_ImGUIContainer;\n        Rect                            m_Position;\n\n        // Misc\n        internal int    objectSelectorID = 0;\n        ObjectSelectorReceiver m_ObjectSelectorReceiver;\n        int             m_ModalUndoGroup = -1;\n        UnityObject     m_OriginalSelection;\n        EditorCache     m_EditorCache;\n        GUIView         m_DelegateView;\n        PreviewResizer  m_PreviewResizer = new PreviewResizer();\n        List<int> m_AllowedIDs;\n\n        // Callbacks\n        Action<UnityObject> m_OnObjectSelectorClosed;\n        Action<UnityObject> m_OnObjectSelectorUpdated;\n\n        ObjectListAreaState m_ListAreaState;\n        ObjectListArea  m_ListArea;\n        ObjectTreeForSelector m_ObjectTreeWithSearch = new ObjectTreeForSelector();\n        UnityObject m_ObjectBeingEdited;\n        SerializedProperty m_EditedProperty;\n        bool m_ShowNoneItem;\n\n        bool m_SelectionCancelled;\n        bool m_PreventSetSelectionOnClose;\n        int m_LastSelectedInstanceId = 0;\n        readonly SearchService.ObjectSelectorSearchSessionHandler m_SearchSessionHandler = new SearchService.ObjectSelectorSearchSessionHandler();\n        readonly SearchSessionOptions m_LegacySearchSessionOptions = new SearchSessionOptions { legacyOnly = true };\n\n        // Layout\n        const float kMinTopSize = 250;\n        const float kMinWidth = 200;\n        const float kPreviewMargin = 5;\n        const float kPreviewExpandedAreaHeight = 75;\n        static float kToolbarHeight => EditorGUI.kWindowToolbarHeight;\n        static float kTopAreaHeight => 0; // top area is rendered with UI-Toolkit\n        const float kResizerHeight = 20f;\n\n        float           m_PreviewSize = 0;\n        float           m_TopSize = 0;\n        AnimBool m_ShowWidePreview = new AnimBool();\n        AnimBool m_ShowOverlapPreview = new AnimBool();\n\n        static HashSet<Event> s_GridAreaPriorityKeyboardEvents;\n\n        // Delayer for debouncing search inputs\n        private Delayer m_Debounce;\n\n        Rect listPosition\n        {\n            get\n            {\n                return new Rect(0, kTopAreaHeight, m_Position.width, Mathf.Max(0f, m_TopSize - kTopAreaHeight));\n            }\n        }\n\n        public List<int> allowedInstanceIDs\n        {\n            get { return m_AllowedIDs; }\n        }\n\n        public UnityObject objectBeingEdited\n        {\n            get { return m_ObjectBeingEdited; }\n        }\n\n        internal static void DestroySharedSelector()\n        {\n            if (s_SharedObjectSelector != null)\n            {\n                EditorWindow.DestroyImmediate(s_SharedObjectSelector);\n                s_SharedObjectSelector = null;\n            }\n        }\n\n        // get an existing ObjectSelector or create one\n        static ObjectSelector s_SharedObjectSelector = null;\n        public static ObjectSelector get\n        {\n            get\n            {\n                if (s_SharedObjectSelector == null)\n                {\n                    UnityObject[] objs = Resources.FindObjectsOfTypeAll(typeof(ObjectSelector));\n                    if (objs != null && objs.Length > 0)\n                        s_SharedObjectSelector = (ObjectSelector)objs[0];\n                    if (s_SharedObjectSelector == null)\n                        s_SharedObjectSelector = ScriptableObject.CreateInstance<ObjectSelector>();\n                }\n                return s_SharedObjectSelector;\n            }\n        }\n\n        public static bool isVisible\n        {\n            get\n            {\n                return s_SharedObjectSelector != null;\n            }\n        }\n\n        // used by AI-toolkit to inject UI elements when the window is shown.\n        [UsedImplicitly]\n        public static event Action<EditorWindow> shown;\n\n        // used by AI-toolkit to set the allowed types for the current object selector (if any).\n        [UsedImplicitly]\n        public static Type[] allowedTypes => s_SharedObjectSelector ? s_SharedObjectSelector.m_RequiredRawTypes : null;\n\n        // used by AI-toolkit to set the selection without user interaction.\n        [UsedImplicitly]\n        public static void SetSelection(int instanceID)\n        {\n            if (s_SharedObjectSelector)\n                s_SharedObjectSelector.SetSelectionInternal(instanceID);\n        }\n\n        // This will notify for a selection change but without repainting the window\n        void SetSelectionInternal(int instanceID)\n        {\n            SetSelectedInstanceID(instanceID);\n            NotifySelectionChanged(false);\n            m_PreventSetSelectionOnClose = true;\n        }\n\n        bool IsUsingTreeView()\n        {\n            return m_ObjectTreeWithSearch.IsInitialized();\n        }\n\n        // Internal for test purposes only\n        internal int GetInternalSelectedInstanceID()\n        {\n            if (m_ListArea == null)\n                InitIfNeeded();\n            int[] selection = IsUsingTreeView() ? m_ObjectTreeWithSearch.GetSelection() : m_ListArea.GetSelection();\n            if (selection.Length >= 1)\n                return selection[0];\n            return 0;\n        }\n\n        int GetSelectedInstanceID()\n        {\n            return m_LastSelectedInstanceId;\n        }\n\n        void SetSelectedInstanceID(int instanceID)\n        {\n            m_LastSelectedInstanceId = instanceID;\n            if (m_ListArea == null)\n                return;\n\n            if (instanceID != 0)\n                m_ListArea.m_SelectedObjectIcon = AssetDatabase.GetCachedIcon(AssetDatabase.GetAssetPath(instanceID));\n            else\n                m_ListArea.m_SelectedObjectIcon = null;\n        }\n\n        [UsedImplicitly]\n        void OnEnable()\n        {\n            hideFlags = HideFlags.DontSave;\n            m_ShowOverlapPreview.valueChanged.AddListener(Repaint);\n            m_ShowOverlapPreview.speed = 1.5f;\n            m_ShowWidePreview.valueChanged.AddListener(Repaint);\n            m_ShowWidePreview.speed = 1.5f;\n\n            m_PreviewResizer.Init(\"ObjectPickerPreview\");\n            m_PreviewSize = m_PreviewResizer.GetPreviewSize(); // Init size\n\n            if (s_GridAreaPriorityKeyboardEvents == null)\n            {\n                s_GridAreaPriorityKeyboardEvents = new HashSet<Event>\n                {\n                    Event.KeyboardEvent(\"up\"),\n                    Event.KeyboardEvent(\"down\"),\n                };\n            }\n\n            AssetPreview.ClearTemporaryAssetPreviews();\n\n            SetupPreview();\n\n            m_Debounce = Delayer.Debounce(_ =>\n            {\n                FilterSettingsChanged();\n                Repaint();\n            });\n        }\n\n        [UsedImplicitly]\n        void OnDisable()\n        {\n            NotifySelectorClosed(false);\n            if (m_ListArea != null)\n                m_StartGridSize.value = m_ListArea.gridSize;\n\n            if (s_SharedObjectSelector == this)\n                s_SharedObjectSelector = null;\n            if (m_EditorCache != null)\n                m_EditorCache.Dispose();\n\n            AssetPreview.ClearTemporaryAssetPreviews();\n            HierarchyProperty.ClearSceneObjectsFilter();\n            m_Debounce?.Dispose();\n            m_Debounce = null;\n        }\n\n        public void SetupPreview()\n        {\n            bool open = PreviewIsOpen();\n            bool wide = PreviewIsWide();\n            m_ShowOverlapPreview.target = m_ShowOverlapPreview.value = (open && !wide);\n            m_ShowWidePreview.target = m_ShowWidePreview.value = (open && wide);\n        }\n\n        void ListAreaItemSelectedCallback(bool doubleClicked)\n        {\n            SetSelectedInstanceID(GetInternalSelectedInstanceID());\n\n            if (doubleClicked)\n            {\n                ItemWasDoubleClicked();\n            }\n            else\n            {\n                NotifySelectionChanged(true);\n            }\n        }\n\n        internal string searchFilter\n        {\n            get { return m_SearchFilter; }\n            set\n            {\n                if (ObjectSelectorSearch.HasEngineOverride())\n                {\n                    m_SearchSessionHandler.SetSearchFilter(value);\n                    return;\n                }\n                m_SearchFilter = value;\n                if (m_ObjectTreeWithSearch.IsInitialized())\n                    m_ObjectTreeWithSearch.SetSearchFilter(m_SearchFilter);\n                else\n                    m_Debounce?.Execute();\n            }\n        }\n\n        public ObjectSelectorReceiver objectSelectorReceiver\n        {\n            get { return m_ObjectSelectorReceiver; }\n            set { m_ObjectSelectorReceiver = value; }\n        }\n\n        Scene GetSceneFromObject(UnityObject obj)\n        {\n            var go = obj as GameObject;\n            if (go != null)\n                return go.scene;\n\n            var component = obj as Component;\n            if (component != null)\n                return component.gameObject.scene;\n\n            return new Scene();\n        }\n\n        // Used by tests\n        internal void Internal_TriggerFilterSettingsChanged()\n        {\n            FilterSettingsChanged();\n        }\n\n        void FilterSettingsChanged()\n        {\n            var filter = GetSearchFilter();\n            var hierarchyType = m_IsShowingAssets ? HierarchyType.Assets : HierarchyType.GameObjects;\n\n            bool hasObject = false;\n            var requiredTypes = new List<Type>();\n            var objectTypes = TypeCache.GetTypesDerivedFrom<UnityEngine.Object>();\n            foreach (var type in m_RequiredTypes)\n            {\n                foreach (var objectType in objectTypes)\n                {\n                    if (objectType.Name == type)\n                        requiredTypes.Add(objectType);\n                    else if (!hasObject)\n                    {\n                        requiredTypes.Add(typeof(UnityObject));\n                        hasObject = true;\n                    }\n                }\n            }\n            m_ListArea.InitForSearch(listPosition, hierarchyType, filter, true, s =>\n            {\n                foreach (var type in requiredTypes)\n                {\n                    var asset = AssetDatabase.LoadAssetAtPath(s, type);\n                    if (asset != null && asset.GetInstanceID() != 0)\n                        return asset.GetInstanceID();\n                }\n                return 0;\n            }, m_LegacySearchSessionOptions);\n        }\n\n        void Frame()\n        {\n            if (m_ListArea.GetSelection() is { Length: > 0 } selection)\n                m_ListArea.Frame(selection[0], true, false);\n        }\n\n        SearchFilter GetSearchFilter()\n        {\n            var filter = new SearchFilter();\n            if (m_IsShowingAssets)\n                filter.searchArea = SearchFilter.SearchArea.AllAssets;\n\n            filter.SearchFieldStringToFilter(m_SearchFilter);\n            if (filter.classNames.Length == 0 && m_RequiredTypes.All(type => !string.IsNullOrEmpty(type)))\n                filter.classNames = m_RequiredTypes;\n\n            var hierarchyType = m_IsShowingAssets ? HierarchyType.Assets : HierarchyType.GameObjects;\n\n            if (hierarchyType == HierarchyType.GameObjects)\n            {\n                if (m_ObjectBeingEdited != null)\n                {\n                    var scene = GetSceneFromObject(m_ObjectBeingEdited);\n                    if (scene.IsValid())\n                    {\n                        // We do not support cross scene references so ensure we only show game objects\n                        // from the same scene as the object being edited is part of.\n                        // Also don't allow references to other scenes if object being edited\n                        // is in a preview scene.\n                        if (EditorSceneManager.IsPreviewScene(scene) || EditorSceneManager.preventCrossSceneReferences)\n                            filter.sceneHandles = new[] { scene.handle };\n                    }\n                }\n                else\n                {\n                    // If we don't know which object is being edited, assume it's one in current stage.\n                    PreviewSceneStage previewSceneStage = StageUtility.GetCurrentStage() as PreviewSceneStage;\n                    if (previewSceneStage != null)\n                    {\n                        filter.sceneHandles = new[] { previewSceneStage.scene.handle };\n                    }\n                }\n            }\n\n            if (hierarchyType == HierarchyType.Assets)\n            {\n                // When AssemblyDefinitionAsset is the required type, don't skip hidden packages\n                foreach (var type in m_RequiredTypes)\n                {\n                    if (!string.IsNullOrEmpty(type) && type == typeof(AssemblyDefinitionAsset).Name)\n                    {\n                        m_SkipHiddenPackages = false;\n                        break;\n                    }\n                }\n                filter.skipHidden = m_SkipHiddenPackages;\n            }\n\n            return filter;\n        }\n\n        static bool ShouldTreeViewBeUsed(String typeStr)\n        {\n            return (String.Equals(typeof(AudioMixerGroup).Name, typeStr));\n        }\n\n        static Type GetUnityObjectType(string typeName)\n        {\n            var objectTypes = TypeCache.GetTypesDerivedFrom<UnityEngine.Object>();\n            foreach (var objectType in objectTypes)\n            {\n                if (objectType.FullName == typeName || objectType.Name == typeName)\n                    return objectType;\n            }\n            return null;\n        }\n\n        private readonly Regex s_MatchPPtrTypeName = new Regex(@\"PPtr\\<(\\w+)\\>\");\n\n        internal void Show(Type requiredType, SerializedProperty property, bool allowSceneObjects, List<int> allowedInstanceIDs = null, Action<UnityObject> onObjectSelectorClosed = null, Action<UnityObject> onObjectSelectedUpdated = null)\n        {\n            if (property == null)\n                throw new ArgumentNullException(nameof(property));\n\n            if (requiredType == null)\n            {\n                ScriptAttributeUtility.GetFieldInfoFromProperty(property, out requiredType);\n                // case 951876: built-in types do not actually have reflectable fields, so their object types must be extracted from the type string\n                // this works because built-in types will only ever have serialized references to other built-in types, which this window's filter expects as unqualified names\n                if (requiredType == null)\n                    m_RequiredTypes = new string[] { s_MatchPPtrTypeName.Match(property.type).Groups[1].Value };\n            }\n\n            // Don't select anything on multi selection\n            UnityObject obj = property.hasMultipleDifferentValues ? null : property.objectReferenceValue;\n\n            UnityObject objectBeingEdited = property.serializedObject.targetObject;\n            m_EditedProperty = property;\n\n            Show(obj, new Type[] { requiredType }, objectBeingEdited, allowSceneObjects, allowedInstanceIDs, onObjectSelectorClosed, onObjectSelectedUpdated);\n        }\n\n        internal void Show(Type[] requiredTypes, SerializedProperty property, bool allowSceneObjects, List<int> allowedInstanceIDs = null, Action<UnityObject> onObjectSelectorClosed = null, Action<UnityObject> onObjectSelectedUpdated = null)\n        {\n            if (requiredTypes == null)\n            {\n                Show((Type)null, property, allowSceneObjects, allowedInstanceIDs, onObjectSelectorClosed, onObjectSelectedUpdated);\n                return;\n            }\n\n            if (property == null)\n                throw new ArgumentNullException(nameof(property));\n\n            m_RequiredTypes = new string[requiredTypes.Length];\n            for (int i = 0; i < requiredTypes.Length; i++)\n            {\n                var requiredType = requiredTypes[i];\n                if (requiredType == null)\n                {\n                    ScriptAttributeUtility.GetFieldInfoFromProperty(property, out requiredType);\n                    // case 951876: built-in types do not actually have reflectable fields, so their object types must be extracted from the type string\n                    // this works because built-in types will only ever have serialized references to other built-in types, which this window's filter expects as unqualified names\n                    if (requiredType == null)\n                        m_RequiredTypes[i] = s_MatchPPtrTypeName.Match(property.type).Groups[1].Value;\n                    else\n                        requiredTypes[i] = requiredType;\n                }\n            }\n\n            // Don't select anything on multi selection\n            UnityObject obj = property.hasMultipleDifferentValues ? null : property.objectReferenceValue;\n\n            UnityObject objectBeingEdited = property.serializedObject.targetObject;\n            m_EditedProperty = property;\n\n            Show(obj, requiredTypes, objectBeingEdited, allowSceneObjects, allowedInstanceIDs, onObjectSelectorClosed, onObjectSelectedUpdated);\n        }\n\n        internal void Show(UnityObject obj, Type requiredType, UnityObject objectBeingEdited, bool allowSceneObjects, List<int> allowedInstanceIDs = null, Action<UnityObject> onObjectSelectorClosed = null, Action<UnityObject> onObjectSelectedUpdated = null, bool showNoneItem = true)\n        {\n            Show(obj, new Type[] { requiredType }, objectBeingEdited, allowSceneObjects, allowedInstanceIDs, onObjectSelectorClosed, onObjectSelectedUpdated, showNoneItem);\n        }\n\n        internal void Show(UnityObject obj, Type[] requiredTypes, UnityObject objectBeingEdited, bool allowSceneObjects, List<int> allowedInstanceIDs = null, Action<UnityObject> onObjectSelectorClosed = null, Action<UnityObject> onObjectSelectedUpdated = null, bool showNoneItem = true)\n        {\n            // We can't rely on the fact that the window will always be closed when we call Show. For example,\n            // if a user clicks on multiple object fields without closing the window first, there is no guarantee\n            // that the auxiliary window will close before the click event is processed. And since closing the window\n            // cleans up the undo state, we have to force close the window if it wasn't already closed.\n            CloseOpenedWindow();\n            m_ObjectSelectorReceiver = null;\n            m_AllowSceneObjects = allowSceneObjects;\n            m_IsShowingAssets = true;\n            m_SkipHiddenPackages = true;\n            m_AllowedIDs = allowedInstanceIDs;\n            m_ObjectBeingEdited = objectBeingEdited;\n            SetSelectedInstanceID(obj?.GetInstanceID() ?? 0);\n            m_SelectionCancelled = false;\n            m_PreventSetSelectionOnClose = false;\n            m_ShowNoneItem = showNoneItem;\n\n            m_OnObjectSelectorClosed = onObjectSelectorClosed;\n            m_OnObjectSelectorUpdated = onObjectSelectedUpdated;\n\n            // Do not allow to show scene objects if the object being edited is persistent\n            if (m_ObjectBeingEdited != null && EditorUtility.IsPersistent(m_ObjectBeingEdited))\n                m_AllowSceneObjects = false;\n\n            // Set which tab should be visible at startup\n            if (m_AllowSceneObjects)\n            {\n                if (obj != null)\n                {\n                    if (typeof(Component).IsAssignableFrom(obj.GetType()))\n                    {\n                        obj = ((Component)obj).gameObject;\n                    }\n                    // Set the right tab visible (so we can see our selection)\n                    m_IsShowingAssets = EditorUtility.IsPersistent(obj);\n                }\n                else\n                {\n                    foreach (var requiredType in requiredTypes)\n                        m_IsShowingAssets &= (requiredType != typeof(GameObject) && !typeof(Component).IsAssignableFrom(requiredType));\n                }\n            }\n            else\n            {\n                m_IsShowingAssets = true;\n            }\n\n            // Set member variables\n            m_DelegateView = GUIView.current;\n            m_RequiredRawTypes = new Type[requiredTypes.Length];\n            // type filter requires unqualified names for built-in types, but will prioritize them over user types, so ensure user types are namespace-qualified\n            if (m_RequiredTypes == null || m_RequiredTypes.Length != requiredTypes.Length)\n                m_RequiredTypes = new string[requiredTypes.Length];\n            for (var i = 0; i < requiredTypes.Length; i++)\n            {\n                if (requiredTypes[i] != null)\n                {\n                    m_RequiredTypes[i] = typeof(ScriptableObject).IsAssignableFrom(requiredTypes[i]) || typeof(MonoBehaviour).IsAssignableFrom(requiredTypes[i]) ? requiredTypes[i].FullName : requiredTypes[i].Name;\n                    m_RequiredRawTypes[i] = requiredTypes[i];\n                }\n                else\n                {\n                    m_RequiredRawTypes[i] = GetUnityObjectType(m_RequiredTypes[i]);\n                }\n            }\n            m_SearchFilter = \"\";\n            m_OriginalSelection = obj;\n            m_ModalUndoGroup = Undo.GetCurrentGroup();\n\n            // Show custom selector if available\n            if (ObjectSelectorSearch.HasEngineOverride())\n            {\n                m_SearchSessionHandler.BeginSession(() =>\n                {\n                    return new SearchService.ObjectSelectorSearchContext\n                    {\n                        currentObject = obj,\n                        editedObjects = m_EditedProperty != null ? m_EditedProperty.serializedObject.targetObjects : new[] { objectBeingEdited },\n                        requiredTypes = requiredTypes,\n                        requiredTypeNames = m_RequiredTypes,\n                        allowedInstanceIds = allowedInstanceIDs,\n                        visibleObjects = allowSceneObjects ? SearchService.VisibleObjects.All : SearchService.VisibleObjects.Assets,\n                        searchFilter = GetSearchFilter()\n                    };\n                });\n\n                Action<UnityObject> onSelectionChanged = selectedObj =>\n                {\n                    SetSelectedInstanceID(selectedObj == null ? 0 : selectedObj.GetInstanceID());\n                    NotifySelectionChanged(false);\n                };\n                Action<UnityObject, bool> onSelectorClosed = (selectedObj, canceled) =>\n                {\n                    bool notifySelectorClosedOnly = false;\n                    if (m_SearchSessionHandler.context is ObjectSelectorSearchContext c)\n                    {\n                        notifySelectorClosedOnly = (c.endSessionModes & ObjectSelectorSearchEndSessionModes.CloseSelector) == ObjectSelectorSearchEndSessionModes.CloseSelector;\n                    }\n\n                    m_SearchSessionHandler.EndSession();\n                    if (canceled)\n                    {\n                        // Undo changes we have done in the ObjectSelector\n                        Undo.RevertAllDownToGroup(m_ModalUndoGroup);\n                        SetSelectedInstanceID(0);\n                        m_SelectionCancelled = true;\n                    }\n                    else if (!m_PreventSetSelectionOnClose) // prevent re-set selection if it has been set programmatically before closing\n                    {\n                        SetSelectedInstanceID(selectedObj == null ? 0 : selectedObj.GetInstanceID());\n                        NotifySelectionChanged(false);\n                    }\n\n                    m_EditedProperty = null;\n\n                    // When force closing the selector because we are opening a new ObjectSelector, we must not destroy the shared selector.\n                    if (notifySelectorClosedOnly)\n                    {\n                        NotifySelectorClosed(false);\n                    }\n                    else\n                    {\n                        // This will call OnDisable, which will call NotifySelectorClosed(false)\n                        DestroySharedSelector();\n                    }\n                };\n\n                if (m_SearchSessionHandler.SelectObject(onSelectorClosed, onSelectionChanged))\n                    return;\n                else\n                    m_SearchSessionHandler.EndSession();\n            }\n\n            // Freeze to prevent flicker on OSX.\n            // Screen will be updated again when calling\n            // SetFreezeDisplay(false) further down.\n            ContainerWindow.SetFreezeDisplay(true);\n\n            var shouldRepositionWindow = m_Parent != null;\n            ShowWithMode(ShowMode.AuxWindow);\n\n            titleContent = EditorGUIUtility.TrTextContent(GenerateTitleContent(requiredTypes, m_RequiredTypes));\n\n            // Deal with window size\n            if (shouldRepositionWindow)\n            {\n                m_Parent.window.LoadInCurrentMousePosition();\n                m_Parent.window.FitWindowToScreen(true);\n            }\n            Rect p = m_Parent == null ? new Rect(0, 0, 1, 1) : m_Parent.window.position;\n            p.width = EditorPrefs.GetFloat(\"ObjectSelectorWidth\", 200);\n            p.height = EditorPrefs.GetFloat(\"ObjectSelectorHeight\", 390);\n            position = p;\n            minSize = new Vector2(kMinWidth, kMinTopSize + kPreviewExpandedAreaHeight + 2 * kPreviewMargin);\n            maxSize = new Vector2(10000, 10000);\n            SetupPreview();\n\n            // Focus\n            Focus();\n            ContainerWindow.SetFreezeDisplay(false);\n\n            // Add after unfreezing display because AuxWindowManager.cpp assumes that aux windows are added after we get 'got/lost'- focus calls.\n            if (m_Parent != null)\n                m_Parent.AddToAuxWindowList();\n\n            // Initial selection\n            int initialSelection = obj != null ? obj.GetInstanceID() : 0;\n\n            if (initialSelection != 0)\n            {\n                var assetPath = AssetDatabase.GetAssetPath(initialSelection);\n                if (m_SkipHiddenPackages && !PackageManagerUtilityInternal.IsPathInVisiblePackage(assetPath))\n                    m_SkipHiddenPackagesToggle.value = false;\n            }\n\n            if (m_RequiredTypes.All(t => ShouldTreeViewBeUsed(t)))\n            {\n                m_ObjectTreeWithSearch.Init(position, this, CreateAndSetTreeView, TreeViewSelection, ItemWasDoubleClicked, initialSelection, 0);\n            }\n            else\n            {\n                // To frame the selected item we need to wait to initialize the search until our window has been setup\n                InitIfNeeded();\n                m_ListArea.InitSelection(new[] { initialSelection });\n                if (initialSelection != 0)\n                    m_ListArea.Frame(initialSelection, true, false);\n            }\n\n            InvokeWindowShown(this);\n        }\n\n        internal static void InvokeWindowShown(EditorWindow editorWindow)\n        {\n            shown?.Invoke(editorWindow);\n        }\n\n        void CloseOpenedWindow()\n        {\n            // We check m_ModalUndoGroup as it is the only value that will be reliably set when the window is open\n            // and unset when the window is closed. Checking m_OnObjectSelectorClosed or m_ObjectSelectorReceiver is not enough\n            // as they are not always set.\n            if (m_ModalUndoGroup >= 0)\n            {\n                if (ObjectSelectorSearch.HasEngineOverride())\n                {\n                    m_SearchSessionHandler.CloseSelector();\n                }\n                else\n                {\n                    NotifySelectorClosed(false);\n                }\n            }\n        }\n\n        internal static string GenerateTitleContent(Type[] requiredTypes, string[] requiredTypeStrings)\n        {\n            var typeName = requiredTypes[0] == null ? requiredTypeStrings[0] : requiredTypes[0].Name;\n            var text = \"Select \" + ObjectNames.NicifyVariableName(typeName);\n\n            for (int i = 1; i < requiredTypes.Length; i++)\n            {\n                typeName = requiredTypes[i] == null ? requiredTypeStrings[i] : requiredTypes[i].Name;\n                text += (i == requiredTypes.Length - 1 ? \" or \" : \", \") + ObjectNames.NicifyVariableName(typeName);\n            }\n\n            return text;\n        }\n\n        void ItemWasDoubleClicked()\n        {\n            SendEvent(ObjectSelectorSelectionDoneCommand, false);\n\n            Close();\n            GUIUtility.ExitGUI();\n        }\n\n        // TreeView Section\n\n        void CreateAndSetTreeView(ObjectTreeForSelector.TreeSelectorData data)\n        {\n            TreeViewForAudioMixerGroup.CreateAndSetTreeView(data);\n        }\n\n        void TreeViewSelection(TreeViewItem item)\n        {\n            SetSelectedInstanceID(GetInternalSelectedInstanceID());\n            NotifySelectionChanged(true);\n        }\n\n        // Grid Section\n\n        void InitIfNeeded()\n        {\n            if (m_ListAreaState == null)\n                m_ListAreaState = new ObjectListAreaState(); // is serialized\n\n            if (m_ListArea == null)\n            {\n                m_ListArea = new ObjectListArea(m_ListAreaState, this, m_ShowNoneItem);\n                m_ListArea.allowDeselection = false;\n                m_ListArea.allowDragging = false;\n                m_ListArea.allowFocusRendering = false;\n                m_ListArea.allowMultiSelect = false;\n                m_ListArea.allowRenaming = false;\n                m_ListArea.allowBuiltinResources = true;\n                m_ListArea.repaintCallback += Repaint;\n                m_ListArea.itemSelectedCallback += ListAreaItemSelectedCallback;\n                m_ListArea.gridSize = m_StartGridSize.value;\n\n                SetSelectedInstanceID(m_LastSelectedInstanceId);\n\n                FilterSettingsChanged();\n            }\n        }\n\n        public static bool SelectionCanceled()\n        {\n            return ObjectSelector.get.m_SelectionCancelled;\n        }\n\n        public static UnityObject GetCurrentObject()\n        {\n            return EditorUtility.InstanceIDToObject(ObjectSelector.get.GetSelectedInstanceID());\n        }\n\n        // This is the public Object that the inspector might revert to\n        public static UnityObject GetInitialObject()\n        {\n            return ObjectSelector.get.m_OriginalSelection;\n        }\n\n        [UsedImplicitly]\n        void OnInspectorUpdate()\n        {\n            if (m_ListArea != null && AssetPreview.HasAnyNewPreviewTexturesAvailable(m_ListArea.GetAssetPreviewManagerID()))\n                Repaint();\n        }\n\n        // This is the preview area at the bottom of the screen\n        void PreviewArea()\n        {\n            GUI.Box(new Rect(0, m_TopSize, m_Position.width, m_PreviewSize), \"\", Styles.previewBackground);\n\n            if (m_ListArea.GetSelection().Length == 0)\n                return;\n\n            EditorWrapper p = null;\n            UnityObject selectedObject = GetCurrentObject();\n            if (m_PreviewSize < kPreviewExpandedAreaHeight)\n            {\n                // Get info string\n                string s;\n                if (selectedObject != null)\n                {\n                    p = m_EditorCache[selectedObject];\n                    string typeName = ObjectNames.NicifyVariableName(selectedObject.GetType().Name);\n                    if (p != null)\n                        s = p.name + \" (\" + typeName + \")\";\n                    else\n                        s = selectedObject.name + \" (\" + typeName + \")\";\n\n                    s += \"      \" + AssetDatabase.GetAssetPath(selectedObject);\n                }\n                else\n                    s = \"None\";\n\n                LinePreview(s, selectedObject, p);\n            }\n            else\n            {\n                if (m_EditorCache == null)\n                    m_EditorCache = new EditorCache(EditorFeatures.PreviewGUI);\n\n                // Get info string\n                string s;\n                if (selectedObject != null)\n                {\n                    p = m_EditorCache[selectedObject];\n                    string typeName = ObjectNames.NicifyVariableName(selectedObject.GetType().Name);\n                    if (p != null)\n                    {\n                        s = p.GetInfoString();\n                        if (s != \"\")\n                            s = p.name + \"\\n\" + typeName + \"\\n\" + s;\n                        else\n                            s = p.name + \"\\n\" + typeName;\n                    }\n                    else\n                    {\n                        s = selectedObject.name + \"\\n\" + typeName;\n                    }\n\n                    s += \"\\n\" + AssetDatabase.GetAssetPath(selectedObject);\n                }\n                else\n                    s = \"None\";\n\n                // Make previews\n                if (m_ShowWidePreview.faded != 0.0f)\n                {\n                    GUI.color = new Color(1, 1, 1, m_ShowWidePreview.faded);\n                    WidePreview(m_PreviewSize, s, selectedObject, p);\n                }\n                if (m_ShowOverlapPreview.faded != 0.0f)\n                {\n                    GUI.color = new Color(1, 1, 1, m_ShowOverlapPreview.faded);\n                    OverlapPreview(m_PreviewSize, s, selectedObject, p);\n                }\n                GUI.color = Color.white;\n                m_EditorCache.CleanupUntouchedEditors();\n            }\n        }\n\n        void WidePreview(float actualSize, string s, UnityObject o, EditorWrapper p)\n        {\n            float margin = kPreviewMargin;\n            Rect previewRect = new Rect(margin, m_TopSize + margin, actualSize - margin * 2, actualSize - margin * 2);\n\n            Rect labelRect = new Rect(m_PreviewSize + 3, m_TopSize + (m_PreviewSize - kPreviewExpandedAreaHeight) * 0.5f, m_Parent.window.position.width - m_PreviewSize - 3 - margin, kPreviewExpandedAreaHeight);\n\n            if (p != null && p.HasPreviewGUI())\n                p.OnPreviewGUI(previewRect, Styles.previewTextureBackground);\n            else if (o != null)\n                DrawObjectIcon(previewRect, m_ListArea.m_SelectedObjectIcon);\n\n            var prevClipping = Styles.smallStatus.clipping;\n            Styles.smallStatus.clipping = TextClipping.Overflow;\n            if (EditorGUIUtility.isProSkin)\n                EditorGUI.DropShadowLabel(labelRect, s, Styles.smallStatus);\n            else\n                GUI.Label(labelRect, s, Styles.smallStatus);\n            Styles.smallStatus.clipping = prevClipping;\n        }\n\n        void OverlapPreview(float actualSize, string s, UnityObject o, EditorWrapper p)\n        {\n            float margin = kPreviewMargin;\n            Rect previewRect = new Rect(margin, m_TopSize + margin, m_Position.width - margin * 2, actualSize - margin * 2);\n\n            if (p != null && p.HasPreviewGUI())\n                p.OnPreviewGUI(previewRect, Styles.previewTextureBackground);\n            else if (o != null)\n                DrawObjectIcon(previewRect, m_ListArea.m_SelectedObjectIcon);\n\n            if (EditorGUIUtility.isProSkin)\n                EditorGUI.DropShadowLabel(previewRect, s, Styles.largeStatus);\n            else\n                EditorGUI.DoDropShadowLabel(previewRect, EditorGUIUtility.TempContent(s), Styles.largeStatus, .3f);\n        }\n\n        void LinePreview(string s, UnityObject o, EditorWrapper p)\n        {\n            if (m_ListArea.m_SelectedObjectIcon != null)\n                GUI.DrawTexture(new Rect(2, (int)(m_TopSize + 2), 16, 16), m_ListArea.m_SelectedObjectIcon, ScaleMode.StretchToFill);\n            Rect labelRect = new Rect(20, m_TopSize + 1, m_Position.width - 22, 18);\n            if (EditorGUIUtility.isProSkin)\n                EditorGUI.DropShadowLabel(labelRect, s, Styles.smallStatus);\n            else\n                GUI.Label(labelRect, s, Styles.smallStatus);\n        }\n\n        void DrawObjectIcon(Rect position, Texture icon)\n        {\n            if (icon == null)\n                return;\n            int size = Mathf.Min((int)position.width, (int)position.height);\n            if (size >= icon.width * 2)\n                size = icon.width * 2;\n\n            FilterMode temp = icon.filterMode;\n            icon.filterMode = FilterMode.Bilinear;\n            GUI.DrawTexture(new Rect(position.x + ((int)position.width - size) / 2, position.y + ((int)position.height - size) / 2, size, size), icon, ScaleMode.ScaleToFit);\n            icon.filterMode = temp;\n        }\n\n        // Resize the preview area\n        void ResizeBottomPartOfWindow()\n        {\n            GUI.changed = false;\n\n            // Handle preview size\n            m_PreviewSize = m_PreviewResizer.ResizeHandle(m_Position, kPreviewExpandedAreaHeight + kPreviewMargin * 2 - kResizerHeight, kMinTopSize + kResizerHeight, kResizerHeight) + kResizerHeight;\n            m_TopSize = m_Position.height - m_PreviewSize;\n\n            bool open = PreviewIsOpen();\n            bool wide = PreviewIsWide();\n            m_ShowOverlapPreview.target = open && !wide;\n            m_ShowWidePreview.target = open && wide;\n        }\n\n        bool PreviewIsOpen()\n        {\n            return m_PreviewSize >= 32 + kPreviewMargin;\n        }\n\n        bool PreviewIsWide()\n        {\n            return position.width - m_PreviewSize - kPreviewMargin > Mathf.Min(m_PreviewSize * 2 - 20, 256);\n        }\n\n        // send an event to the delegate view (the view that called us)\n        void SendEvent(string eventName, bool exitGUI)\n        {\n            if (m_DelegateView)\n            {\n                Event e = EditorGUIUtility.CommandEvent(eventName);\n\n                try\n                {\n                    m_DelegateView.SendEvent(e);\n                }\n                finally\n                {\n                }\n                if (exitGUI)\n                    GUIUtility.ExitGUI();\n            }\n        }\n\n        void HandleKeyboard()\n        {\n            // Handle events on the object selector window\n            if (Event.current.type != EventType.KeyDown)\n                return;\n\n            switch (Event.current.keyCode)\n            {\n                case KeyCode.Return:\n                case KeyCode.KeypadEnter:\n                    Close();\n                    GUI.changed = true;\n                    GUIUtility.ExitGUI();\n                    break;\n                default:\n                    //Debug.Log (\"Unhandled \" + Event.current.keyCode);\n                    return;\n            }\n            Event.current.Use();\n            GUI.changed = true;\n        }\n\n        internal void Cancel()\n        {\n            // Undo changes we have done in the ObjectSelector\n            Undo.RevertAllDownToGroup(m_ModalUndoGroup);\n\n            // Clear selection so that object field doesn't grab it\n            m_ListArea?.InitSelection(new int[0]);\n            m_ObjectTreeWithSearch.Clear();\n            SetSelectedInstanceID(0);\n            m_SelectionCancelled = true;\n            m_EditedProperty = null;\n\n            SendEvent(ObjectSelectorCanceledCommand, false);\n\n            Close();\n            GUI.changed = true;\n            GUIUtility.ExitGUI();\n        }\n\n        [UsedImplicitly]\n        void OnDestroy()\n        {\n            if (m_ListArea != null)\n                m_ListArea.OnDestroy();\n\n            m_ObjectTreeWithSearch.Clear();\n        }\n\n        void OnGUIHandler()\n        {\n            HandleKeyboard();\n\n            m_Position = m_ImGUIContainer.worldBound;\n\n            if (m_ObjectTreeWithSearch.IsInitialized())\n                OnObjectTreeGUI();\n            else\n                OnObjectGridGUI();\n\n            // Must be after gui so search field can use the Escape event if it has focus\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)\n                Cancel();\n            else if (Event.current.commandName == EventCommandNames.UndoRedoPerformed && Selection.activeObject == null)\n            {\n                Close();\n                GUI.changed = true;\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        [UsedImplicitly]\n        void CreateGUI()\n        {\n            InitIfNeeded();\n\n            // root\n            rootVisualElement.name = Styles.rootName;\n            rootVisualElement.AddToClassList(Styles.rootName);\n\n            // header\n            var header = new VisualElement\n            {\n                name = Styles.headerName\n            };\n\n            // header - search bar\n            var searchBar = new UnityEditor.UIElements.Toolbar\n            {\n                name = Styles.searchBarName\n            };\n            m_SearchField = new ToolbarSearchField\n            {\n                name = Styles.searchFieldName\n            };\n            m_SearchField.SetValueWithoutNotify(m_SearchFilter);\n            m_SearchField.RegisterCallback<KeyDownEvent>(OnSearchFieldKeyDown, TrickleDown.TrickleDown);\n            m_SearchField.RegisterValueChangedCallback(OnSearchFieldChanged);\n            m_SearchField.RegisterCallback<AttachToPanelEvent>(evt => ((VisualElement)evt.target).Focus());\n            searchBar.Add(m_SearchField);\n            header.Add(searchBar);\n\n            // header - toolbar\n            m_Toolbar = new UnityEditor.UIElements.Toolbar\n            {\n                name = Styles.toolbarName\n            };\n\n            // header - toolbar - left side\n            var tabView = new TabView\n            {\n                name = Styles.tabViewName\n            };\n            var assetsButton = new Tab(Styles.assetsTabLabel.text)\n            {\n                name = Styles.assetsTabName\n            };\n            tabView.Add(assetsButton);\n            if (m_AllowSceneObjects)\n            {\n                var sceneButton = new Tab(Styles.sceneTabLabel.text)\n                {\n                    name = Styles.sceneTabName\n                };\n                tabView.Add(sceneButton);\n                tabView.activeTab = m_IsShowingAssets ? assetsButton : sceneButton;\n            }\n            else\n            {\n                tabView.activeTab = assetsButton;\n            }\n            tabView.activeTabChanged += OnActiveTabChanged;\n            m_Toolbar.Add(tabView);\n            var spacer = new ToolbarSpacer();\n            m_Toolbar.Add(spacer);\n\n            // header - toolbar - right side\n            var gridSizeSlider = new SliderInt(null, m_ListArea.minGridSize, m_ListArea.maxGridSize)\n            {\n                name = Styles.gridSizeSliderName\n            };\n            gridSizeSlider.EnableInClassList(UIElementsUtility.hiddenClassName, !m_ListArea.CanShowThumbnails());\n            gridSizeSlider.SetValueWithoutNotify(m_ListArea.gridSize);\n            gridSizeSlider.RegisterValueChangedCallback(evt => m_ListArea.gridSize = evt.newValue);\n            m_Toolbar.Add(gridSizeSlider);\n\n            m_SkipHiddenPackagesToggle = new ToolbarToggle\n            {\n                name = Styles.skipHiddenPackagesToggleName,\n                tooltip = Styles.packagesVisibilityContent.tooltip\n            };\n            var skipLabel = new Label(PackageManagerUtilityInternal.HiddenPackagesCount.ToString());\n            var skipIcon = new Image();\n            m_SkipHiddenPackagesToggle.Add(skipIcon);\n            m_SkipHiddenPackagesToggle.Add(skipLabel);\n            m_SkipHiddenPackagesToggle.EnableInClassList(UIElementsUtility.hiddenClassName, !m_IsShowingAssets);\n            m_SkipHiddenPackagesToggle.SetValueWithoutNotify(m_SkipHiddenPackages);\n            m_SkipHiddenPackagesToggle.RegisterValueChangedCallback(OnSkipHiddenPackagesToggleChanged);\n            m_Toolbar.Add(m_SkipHiddenPackagesToggle);\n            header.Add(m_Toolbar);\n\n            // imgui view\n            m_ImGUIContainer = new IMGUIContainer(OnGUIHandler)\n            {\n                name = Styles.imguiContainerName\n            };\n\n            rootVisualElement.Add(header);\n            rootVisualElement.Add(m_ImGUIContainer);\n            rootVisualElement.AddStyleSheetPath(Styles.mainStyleSheetPath);\n            var theme = EditorGUIUtility.isProSkin ? Styles.darkThemeStyleSheetPath : Styles.lightThemeStyleSheetPath;\n            rootVisualElement.AddStyleSheetPath(theme);\n        }\n\n        void OnSkipHiddenPackagesToggleChanged(ChangeEvent<bool> evt)\n        {\n            m_SkipHiddenPackages = evt.newValue;\n            FilterSettingsChanged();\n            Frame();\n        }\n\n        void OnActiveTabChanged(Tab previous, Tab current)\n        {\n            m_IsShowingAssets = current.parent.IndexOf(current) == 0;\n            m_SkipHiddenPackagesToggle.EnableInClassList(UIElementsUtility.hiddenClassName, !m_IsShowingAssets);\n            FilterSettingsChanged();\n            Frame();\n        }\n\n        void OnSearchFieldKeyDown(KeyDownEvent evt)\n        {\n            if (evt.keyCode == KeyCode.Escape)\n            {\n                // If we hit esc and the string WAS empty, it's an actual cancel event.\n                if (string.IsNullOrEmpty(m_SearchFilter))\n                    Cancel();\n            }\n        }\n\n        void OnSearchFieldChanged(ChangeEvent<string> evt)\n        {\n            searchFilter = evt.newValue;\n        }\n\n        void OnObjectTreeGUI()\n        {\n            // the toolbar should not be visible when the tree is visible\n            rootVisualElement.AddToClassList(Styles.treeViewVariantClassName);\n\n            m_ObjectTreeWithSearch.OnGUI(new Rect(0, 0, m_Position.width, m_Position.height));\n        }\n\n        void OnObjectGridGUI()\n        {\n            InitIfNeeded();\n\n            if (m_EditorCache == null)\n                m_EditorCache = new EditorCache(EditorFeatures.PreviewGUI);\n\n            // Handle window/preview stuff\n            ResizeBottomPartOfWindow();\n\n            EditorPrefs.SetFloat(\"ObjectSelectorWidth\", position.width);\n            EditorPrefs.SetFloat(\"ObjectSelectorHeight\", position.height);\n\n            GUI.BeginGroup(new Rect(0, 0, m_Position.width, m_Position.height), GUIContent.none);\n\n            // Let grid/list area take priority over search area on up/down arrow keys\n            if (s_GridAreaPriorityKeyboardEvents.Contains(Event.current))\n                m_ListArea.HandleKeyboard(false);\n\n            // Let grid/list area handle any keyboard events not used by search area\n            m_ListArea.HandleKeyboard(false);\n\n            GridListArea();\n            PreviewArea();\n\n            GUI.EndGroup();\n\n            // overlay preview resize widget\n            GUI.Label(new Rect(m_Position.width * .5f - 16, m_Position.height - m_PreviewSize + 2, 32, Styles.bottomResize.fixedHeight), GUIContent.none, Styles.bottomResize);\n        }\n\n        void GridListArea()\n        {\n            int listKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard);\n            m_ListArea.OnGUI(listPosition, listKeyboardControlID);\n        }\n\n        void NotifySelectionChanged(bool exitGUI)\n        {\n            var currentObject = GetCurrentObject();\n            Internal_NotifySelectionChanged(currentObject, exitGUI);\n        }\n\n        // Used by tests\n        internal void Internal_NotifySelectionChanged(UnityObject selectedObject, bool exitGUI)\n        {\n            if (m_ObjectSelectorReceiver != null)\n            {\n                m_ObjectSelectorReceiver.OnSelectionChanged(selectedObject);\n            }\n\n            m_OnObjectSelectorUpdated?.Invoke(selectedObject);\n\n            SendEvent(ObjectSelectorUpdatedCommand, exitGUI);\n        }\n\n        void NotifySelectorClosed(bool exitGUI)\n        {\n            var currentObject = GetCurrentObject();\n            Internal_NotifySelectorClosed(currentObject, exitGUI);\n        }\n\n        // Used by tests\n        internal void Internal_NotifySelectorClosed(UnityObject selectedObject, bool exitGUI)\n        {\n            if (m_ObjectSelectorReceiver != null)\n            {\n                m_ObjectSelectorReceiver.OnSelectionClosed(selectedObject);\n                m_ObjectSelectorReceiver = null;\n            }\n\n            m_OnObjectSelectorClosed?.Invoke(selectedObject);\n            m_OnObjectSelectorClosed = null;\n            m_OnObjectSelectorUpdated = null;\n\n            SendEvent(ObjectSelectorClosedCommand, exitGUI);\n            Undo.CollapseUndoOperations(m_ModalUndoGroup);\n            m_ModalUndoGroup = -1;\n        }\n\n        [Shortcut(EventCommandNames.Find, typeof(ObjectSelector), KeyCode.F, ShortcutModifiers.Action)]\n        static void FindShortcut(ShortcutArguments args)\n        {\n            if (args.context is ObjectSelector selector)\n                selector.m_SearchField?.Focus();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ObjectTreeForSelector.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing System.Text;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEngine.Events;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\n\nnamespace UnityEditor\n{\n    // Description: Since TreeView is not serialized the client should set the tree view when requested\n    // by ObjectTreeSelector.  Requested by calling treeViewNeededCallback provided by the client,\n    // use SetTreeView() to set tree view.\n\n    [Serializable]\n    internal class ObjectTreeForSelector\n    {\n        internal class TreeSelectorData\n        {\n            public ObjectTreeForSelector objectTreeForSelector;\n            public EditorWindow editorWindow;\n            public TreeViewState state;\n            public Rect treeViewRect;\n            public int userData;\n        }\n\n        EditorWindow m_Owner;\n        TreeViewController m_TreeView;\n        TreeViewState m_TreeViewState;\n        int m_ErrorCounter;\n        int m_OriginalSelectedID;\n        int m_UserData;\n        int m_LastSelectedID = -1;\n        string m_SelectedPath = \"\";\n        const string kSearchFieldTag = \"TreeSearchField\";\n        const float kBottomBarHeight = 17f;\n        const float kTopBarHeight = 0; // top bar rendered with UI-Toolkit\n        SelectionEvent m_SelectionEvent;\n        TreeViewNeededEvent m_TreeViewNeededEvent;\n        DoubleClickedEvent m_DoubleClickedEvent;\n        Delayer m_Debounce;\n        string m_SearchString;\n\n        [Serializable] public class SelectionEvent : UnityEvent<TreeViewItem> {}\n        [Serializable] public class TreeViewNeededEvent : UnityEvent<TreeSelectorData> {}\n        [Serializable] public class DoubleClickedEvent : UnityEvent {}\n\n        class Styles\n        {\n            public GUIStyle searchBg = \"OT TopBar\";\n            public GUIStyle bottomBarBg = \"OT BottomBar\";\n        }\n        static Styles s_Styles;\n\n        public bool IsInitialized()\n        {\n            return m_Owner != null;\n        }\n\n        public void Init(\n            Rect position,\n            EditorWindow owner,\n            UnityAction<TreeSelectorData> treeViewNeededCallback,\n            UnityAction<TreeViewItem> selectionCallback,\n            UnityAction doubleClickedCallback,\n            int initialSelectedTreeViewItemID,\n            int userData)\n        {\n            Clear();\n\n            m_Owner = owner;\n\n            m_TreeViewNeededEvent = new TreeViewNeededEvent();\n            m_TreeViewNeededEvent.AddPersistentListener(treeViewNeededCallback, UnityEventCallState.EditorAndRuntime);\n\n            m_SelectionEvent = new SelectionEvent();\n            m_SelectionEvent.AddPersistentListener(selectionCallback, UnityEventCallState.EditorAndRuntime);\n\n            m_DoubleClickedEvent = new DoubleClickedEvent();\n            m_DoubleClickedEvent.AddPersistentListener(doubleClickedCallback, UnityEventCallState.EditorAndRuntime);\n\n            m_OriginalSelectedID = initialSelectedTreeViewItemID;\n            m_UserData = userData;\n\n            // Initial setup\n            EnsureTreeViewIsValid(GetTreeViewRect(position));\n            if (m_TreeView != null)\n            {\n                m_TreeView.SetSelection(new[] { m_OriginalSelectedID }, true);\n                // If nothing is selected we expand all to better start overview. If we have a selection it has been revealed in SetSelection above\n                if (m_OriginalSelectedID == 0)\n                    m_TreeView.data.SetExpandedWithChildren(m_TreeView.data.root, true);\n            }\n\n            m_Debounce = Delayer.Debounce(context =>\n            {\n                DoSearchFilter();\n                m_Owner.Repaint();\n            });\n        }\n\n        public void Clear()\n        {\n            m_Owner = null;\n            m_TreeViewNeededEvent = null;\n            m_SelectionEvent = null;\n\n            m_DoubleClickedEvent = null;\n            m_OriginalSelectedID = 0;\n            m_UserData = 0;\n\n            m_TreeView = null;\n            m_TreeViewState = null;\n            m_ErrorCounter = 0;\n\n            m_Debounce?.Dispose();\n            m_Debounce = null;\n        }\n\n        public int[] GetSelection()\n        {\n            if (m_TreeView != null)\n                return m_TreeView.GetSelection();\n\n            return new int[0];\n        }\n\n        public void SetSearchFilter(string searchString)\n        {\n            m_SearchString = searchString;\n            m_Debounce.Execute();\n        }\n\n        public void SetSelection(int[] selectedIDs)\n        {\n            m_TreeView.SetSelection(selectedIDs, false);\n        }\n\n        // Call this when requested by ObjectTreeSelector (it calls treeViewNeededCallback)\n        public void SetTreeView(TreeViewController treeView)\n        {\n            m_TreeView = treeView;\n\n            // Hook up to tree view events\n            m_TreeView.selectionChangedCallback -= OnItemSelectionChanged;\n            m_TreeView.selectionChangedCallback += OnItemSelectionChanged;\n            m_TreeView.itemDoubleClickedCallback -= OnItemDoubleClicked;\n            m_TreeView.itemDoubleClickedCallback += OnItemDoubleClicked;\n        }\n\n        bool EnsureTreeViewIsValid(Rect treeViewRect)\n        {\n            if (m_TreeViewState == null)\n                m_TreeViewState = new TreeViewState();\n\n            if (m_TreeView == null)\n            {\n                var input = new TreeSelectorData()\n                {\n                    state = m_TreeViewState,\n                    treeViewRect = treeViewRect,\n                    userData = m_UserData,\n                    objectTreeForSelector = this,\n                    editorWindow = m_Owner\n                };\n\n                m_TreeViewNeededEvent.Invoke(input);\n                if (m_TreeView != null)\n                {\n                    if (m_TreeView.data.root == null)\n                    {\n                        m_TreeView.ReloadData();\n                    }\n                }\n\n                if (m_TreeView == null)\n                {\n                    if (m_ErrorCounter == 0)\n                    {\n                        Debug.LogError(\"ObjectTreeSelector is missing its tree view. Ensure to call 'SetTreeView()' when the treeViewNeededCallback is invoked!\");\n                        m_ErrorCounter++;\n                    }\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        Rect GetTreeViewRect(Rect position)\n        {\n            return new Rect(0, kTopBarHeight, position.width, position.height - kBottomBarHeight - kTopBarHeight);\n        }\n\n        public void OnGUI(Rect position)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            Rect rect = new Rect(0, 0, position.width, position.height);\n            Rect toolbarRect = new Rect(rect.x, rect.y, rect.width, kTopBarHeight);\n            Rect bottomRect = new Rect(rect.x, rect.yMax - kBottomBarHeight, rect.width, kBottomBarHeight);\n            Rect treeViewRect = GetTreeViewRect(position);\n\n            if (!EnsureTreeViewIsValid(treeViewRect))\n                return;\n\n            int treeViewControlID = GUIUtility.GetControlID(\"Tree\".GetHashCode(), FocusType.Keyboard);\n\n            HandleCommandEvents();\n            HandleKeyboard(treeViewControlID);\n            TreeViewArea(treeViewRect, treeViewControlID);\n            BottomBar(bottomRect);\n        }\n\n        void BottomBar(Rect bottomRect)\n        {\n            int currentID = m_TreeView.GetSelection().FirstOrDefault();   // 0 is none selected\n\n            // Refresh cached string\n            if (currentID != m_LastSelectedID)\n            {\n                m_LastSelectedID = currentID;\n                m_SelectedPath = \"\";\n                var selected = m_TreeView.FindItem(currentID);\n                if (selected != null)\n                {\n                    StringBuilder sb = new StringBuilder();\n                    var item = selected;\n                    while (item != null && item != m_TreeView.data.root)\n                    {\n                        if (item != selected)\n                            sb.Insert(0, \"/\");\n                        sb.Insert(0, item.displayName);\n                        item = item.parent;\n                    }\n                    m_SelectedPath = sb.ToString();\n                }\n            }\n\n            GUI.Label(bottomRect, GUIContent.none, s_Styles.bottomBarBg);\n            if (!string.IsNullOrEmpty(m_SelectedPath))\n                GUI.Label(bottomRect, GUIContent.Temp(m_SelectedPath), EditorStyles.miniLabel);\n        }\n\n        private void OnItemDoubleClicked(int id)\n        {\n            if (m_DoubleClickedEvent != null)\n                m_DoubleClickedEvent.Invoke();\n        }\n\n        private void OnItemSelectionChanged(int[] selection)\n        {\n            if (m_SelectionEvent != null)\n            {\n                TreeViewItem item = null;\n                if (selection.Length > 0)\n                {\n                    item = m_TreeView.FindItem(selection[0]);\n                }\n                FireSelectionEvent(item);\n            }\n        }\n\n        void HandleKeyboard(int treeViewControlID)\n        {\n            if (Event.current.type != EventType.KeyDown)\n                return;\n\n            switch (Event.current.keyCode)\n            {\n                case KeyCode.DownArrow:\n                case KeyCode.UpArrow:\n                {\n                    // When searchfield has focus give keyboard focus to the tree view on Down/UpArrow\n                    bool hasSearchFilterFocus = GUI.GetNameOfFocusedControl() == kSearchFieldTag;\n                    if (hasSearchFilterFocus)\n                    {\n                        GUIUtility.keyboardControl = treeViewControlID;\n\n                        // If nothing is selected ensure first item is selected, otherwise ensure current\n                        // selection is visible (we just gave focus to the tree)\n                        if (m_TreeView.IsLastClickedPartOfRows())\n                            FrameSelectedTreeViewItem();\n                        else\n                            m_TreeView.OffsetSelection(1);      // Selects first item\n\n                        Event.current.Use();\n                    }\n                }\n                break;\n                default:\n                    return;\n            }\n        }\n\n        void FrameSelectedTreeViewItem()\n        {\n            m_TreeView.Frame(m_TreeView.state.lastClickedID, true, false);\n        }\n\n        void HandleCommandEvents()\n        {\n            Event evt = Event.current;\n\n            if (evt.type != EventType.ExecuteCommand && evt.type != EventType.ValidateCommand)\n                return;\n\n            if (evt.commandName == EventCommandNames.FrameSelected)\n            {\n                if (evt.type == EventType.ExecuteCommand && m_TreeView.HasSelection())\n                {\n                    m_SearchString = string.Empty;\n                    DoSearchFilter();\n                    FrameSelectedTreeViewItem();\n                }\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        void FireSelectionEvent(TreeViewItem item)\n        {\n            if (m_SelectionEvent != null)\n                m_SelectionEvent.Invoke(item);\n        }\n\n        void TreeViewArea(Rect treeViewRect, int treeViewControlID)\n        {\n            bool hasRows = m_TreeView.data.rowCount > 0;\n            if (hasRows)\n            {\n                m_TreeView.OnGUI(treeViewRect, treeViewControlID);\n            }\n        }\n\n        private void DoSearchFilter()\n        {\n            m_TreeView.searchString = m_SearchString;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/OrderedCallbackCollection.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Text;\nusing UnityEngine;\nusing UnityEngine.Pool;\n\nnamespace UnityEditor.Callbacks\n{\n    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]\n    public class RunAfterClassAttribute : Attribute\n    {\n        public Type classType { get; }\n\n        public RunAfterClassAttribute(Type type) => classType = type;\n\n        public RunAfterClassAttribute(string assemblyQualifiedName) => classType = Type.GetType(assemblyQualifiedName, false);\n    }\n\n    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]\n    public class RunBeforeClassAttribute : Attribute\n    {\n        public Type classType { get; }\n\n        public RunBeforeClassAttribute(Type type) => classType = type;\n\n        public RunBeforeClassAttribute(string assemblyQualifiedName) => classType = Type.GetType(assemblyQualifiedName, false);\n    }\n\n    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]\n    public class RunAfterAssemblyAttribute : Attribute\n    {\n        public string assemblyName { get; }\n\n        public RunAfterAssemblyAttribute(string assemblyName) => this.assemblyName = assemblyName;\n    }\n\n    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]\n    public class RunBeforeAssemblyAttribute : Attribute\n    {\n        public string assemblyName { get; }\n\n        public RunBeforeAssemblyAttribute(string assemblyName) => this.assemblyName = assemblyName;\n    }\n\n    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]\n    public class RunAfterPackageAttribute : Attribute\n    {\n        public string packageName { get; }\n\n        public RunAfterPackageAttribute(string packageName) => this.packageName = packageName;\n    }\n\n    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]\n    public class RunBeforePackageAttribute : Attribute\n    {\n        public string packageName { get; }\n\n        public RunBeforePackageAttribute(string packageName) => this.packageName = packageName;\n    }\n\n    abstract class OrderedCallbackCollection\n    {\n        public abstract class Callback : IComparable\n        {\n            string m_PackageName;\n\n            public abstract Type classType { get; }\n\n            public abstract string name { get; }\n\n            public string packageName\n            {\n                get\n                {\n                    if (m_PackageName == null)\n                    {\n                        var pkg = PackageManager.PackageInfo.FindForAssembly(classType.Assembly);\n                        m_PackageName = pkg != null ? pkg.name : string.Empty;\n                    }\n                    return m_PackageName;\n                }\n            }\n\n            public HashSet<Callback> outgoing { get; } = new HashSet<Callback>();\n            public HashSet<Callback> incoming { get; } = new HashSet<Callback>();\n\n            public abstract IEnumerable<T> GetCustomAttributes<T>() where T : Attribute;\n\n            public void AddIncomingConnection(Callback method)\n            {\n                incoming.Add(method);\n                method.outgoing.Add(this);\n            }\n\n            public void AddIncomingConnections(IList<Callback> methods)\n            {\n                foreach(var m in methods)\n                {\n                    AddIncomingConnection(m);\n                }\n            }\n\n            public void AddOutgoingConnection(Callback method)\n            {\n                outgoing.Add(method);\n                method.incoming.Add(this);\n            }\n\n            public void AddOutgoingConnections(IList<Callback> methods)\n            {\n                foreach (var m in methods)\n                {\n                    AddOutgoingConnection(m);\n                }\n            }\n\n            public int CompareTo(object obj)\n            {\n                if (obj is Callback other)\n                    return classType.FullName.CompareTo(other.classType.FullName);\n                return 0;\n            }\n        }\n\n        List<Callback> m_SortedCallbacks;\n\n        public abstract string name { get; }\n\n        public List<Callback> sortedCallbacks\n        {\n            get\n            {\n                if (m_SortedCallbacks == null)\n                    m_SortedCallbacks = GenerateSortedCallbacks();\n                return m_SortedCallbacks;\n            }\n        }\n\n        public abstract List<Callback> GetCallbacks();\n\n        public List<Callback> GenerateDependencyGraph()\n        {\n            var callbacks = GetCallbacks();\n            var packageLookup = DictionaryPool<string, List<Callback>>.Get();\n            var assemblyLookup = DictionaryPool<string, List<Callback>>.Get();\n            var classLookup = DictionaryPool<Type, Callback>.Get();\n\n            // First generate our lookups for class, assembly and package.\n            foreach (var cb in callbacks)\n            {\n                classLookup[cb.classType] = cb;\n\n                var assemblyName = cb.classType.Assembly.GetName().Name;\n                if (!assemblyLookup.TryGetValue(assemblyName, out var assemblies))\n                {\n                    assemblies = new List<Callback>();\n                    assemblyLookup[assemblyName] = assemblies;\n                }\n                assemblies.Add(cb);\n\n                var package = cb.packageName;\n                if(package != null)\n                {\n                    if (!packageLookup.TryGetValue(package, out var packages))\n                    {\n                        packages = new List<Callback>();\n                        packageLookup[package] = packages;\n                    }\n                    packages.Add(cb);\n                }\n            }\n\n            // Sort the methods so that the output order is deterministic.\n            callbacks.Sort();\n\n            // Now connect the dependency graph nodes\n            foreach (var dependency in callbacks)\n            {\n                // Dependency by class\n                foreach (var runAfter in dependency.GetCustomAttributes<RunAfterClassAttribute>())\n                {\n                    // Ignore classes that may not exist in the project\n                    if (runAfter.classType == null)\n                        continue;\n\n                    if (classLookup.TryGetValue(runAfter.classType, out var runAfterMethodInfo))\n                    {\n                        dependency.AddIncomingConnection(runAfterMethodInfo);\n                    }\n                }\n                foreach (var runBefore in dependency.GetCustomAttributes<RunBeforeClassAttribute>())\n                {\n                    // Ignore classes that may not exist in the project\n                    if (runBefore.classType == null)\n                        continue;\n\n                    if (classLookup.TryGetValue(runBefore.classType, out var runBeforeMethodInfo))\n                    {\n                        dependency.AddOutgoingConnection(runBeforeMethodInfo);\n                    }\n                }\n\n                // Dependency by package\n                foreach (var runAfter in dependency.GetCustomAttributes<RunAfterPackageAttribute>())\n                {\n                    if (packageLookup.TryGetValue(runAfter.packageName, out var runAfterMethodInfos))\n                    {\n                        dependency.AddIncomingConnections(runAfterMethodInfos);\n                    }\n                }\n                foreach (var runBefore in dependency.GetCustomAttributes<RunBeforePackageAttribute>())\n                {\n                    if (packageLookup.TryGetValue(runBefore.packageName, out var runBeforeMethodInfos))\n                    {\n                        dependency.AddOutgoingConnections(runBeforeMethodInfos);\n                    }\n                }\n\n                // Dependency by Assembly\n                foreach (var runAfter in dependency.GetCustomAttributes<RunAfterAssemblyAttribute>())\n                {\n                    if (assemblyLookup.TryGetValue(runAfter.assemblyName, out var runAfterMethodInfos))\n                    {\n                        dependency.AddIncomingConnections(runAfterMethodInfos);\n                    }\n                }\n                foreach (var runBefore in dependency.GetCustomAttributes<RunBeforeAssemblyAttribute>())\n                {\n                    if (assemblyLookup.TryGetValue(runBefore.assemblyName, out var runBeforeMethodInfos))\n                    {\n                        dependency.AddOutgoingConnections(runBeforeMethodInfos);\n                    }\n                }\n            }\n\n            DictionaryPool<string, List<Callback>>.Release(packageLookup);\n            DictionaryPool<string, List<Callback>>.Release(assemblyLookup);\n            DictionaryPool<Type, Callback>.Release(classLookup);\n\n            return callbacks;\n        }\n\n        public List<Callback> GenerateSortedCallbacks() => PerformTopologicalSortingKahnAlgorithm(GenerateDependencyGraph());\n\n        List<Callback> PerformTopologicalSortingKahnAlgorithm(List<Callback> dependencyGraph, HashSet<string> cyclicNodes = null)\n        {\n            int n = dependencyGraph.Count;\n            var ordered = new List<Callback>(n);\n            var q = new Queue<Callback>();\n\n            // Find nodes which do not need to run after anything(no incoming)\n            foreach (var node in dependencyGraph)\n            {\n                if (node.incoming.Count == 0)\n                    q.Enqueue(node);\n            }\n\n            while (q.Count != 0)\n            {\n                var at = q.Dequeue();\n                ordered.Add(at);\n\n                foreach (var o in at.outgoing)\n                {\n                    o.incoming.Remove(at);\n                    if (o.incoming.Count == 0)\n                        q.Enqueue(o);\n                }\n                at.outgoing.Clear();\n            }\n\n            // Graph contains a cycle\n            if (ordered.Count != dependencyGraph.Count)\n            {\n                var sb = new StringBuilder();\n                sb.Append($\"Found cycles in callback dependency graph for {name}.\\nThe following nodes could not be added:\\n\");\n\n                var visited = cyclicNodes ?? new HashSet<string>();\n                foreach (var node in dependencyGraph)\n                {\n                    if (node.incoming.Count == 0)\n                        continue;\n\n                    PrintChildren(node, sb, visited, 0);\n                }\n                Debug.LogError(sb.ToString());\n            }\n\n            return ordered;\n        }\n\n        static void PrintChildren(Callback callback, StringBuilder stringBuilder, HashSet<string> visited, int depth)\n        {\n            if (visited.Contains(callback.name))\n            {\n                if (depth != 0)\n                {\n                    // We have a cycle. Abort here\n                    stringBuilder.Append(new string('-', depth));\n                    stringBuilder.AppendLine($\"<color=red>{callback.name}</color>\");\n                }\n\n                return;\n            }\n\n            visited.Add(callback.name);\n\n            if (depth != 0)\n            {\n                stringBuilder.Append(new string('-', depth));\n            }\n\n            stringBuilder.AppendLine(callback.name);\n\n            foreach (var node in callback.outgoing)\n            {\n                PrintChildren(node, stringBuilder, visited, depth + 1);\n            }\n        }\n\n        /// <summary>\n        /// This can aid with debugging and understanding the dependencies.\n        /// It will generate a Graphviz dot diagram to show the dependencies, cyclic issues and generated callback order.\n        /// </summary>\n        /// <param name=\"path\">Where to save the generated dot diagram.</param>\n        public void GenerateDependencyDiagram(string path = \"DependenciesDiagram.dot\")\n        {\n            var dependencyGraph = GenerateDependencyGraph();\n            var cyclicNodes = new HashSet<string>();\n            var sortedCallbacks = PerformTopologicalSortingKahnAlgorithm(GenerateDependencyGraph(), cyclicNodes);\n\n            var graphvizDiagram = new StringBuilder();\n            graphvizDiagram.AppendLine(\"digraph DependenciesDiagram {\");\n            graphvizDiagram.AppendLine(\"\\tnode [style=\\\"filled, rounded\\\", shape=box, fillcolor=\\\"#FCE5EC\\\" color=\\\"#EB417A\\\"]\");\n            foreach(var node in cyclicNodes)\n            {\n                graphvizDiagram.AppendLine($\"\\t<{node}>\");\n            }\n\n            graphvizDiagram.AppendLine();\n            graphvizDiagram.AppendLine(\"\\tnode [style=\\\"filled, rounded\\\", shape=box, fillcolor=\\\"#DAEDFD\\\" color=\\\"#2196F3\\\"]\");\n            graphvizDiagram.AppendLine(\"\\tedge [penwidth=1.5, color=\\\"#2196F3\\\"]\");\n            foreach (var node in dependencyGraph)\n            {\n                if (node.outgoing.Count > 0)\n                {\n                    graphvizDiagram.Append($\"\\t<{node.name}> -> \");\n\n                    var enumerator = node.outgoing.GetEnumerator();\n                    enumerator.MoveNext();\n                    graphvizDiagram.Append($\"<{enumerator.Current.name}>\");\n                    while (enumerator.MoveNext())\n                    {\n                        graphvizDiagram.Append($\", <{enumerator.Current.name}>\");\n                    }\n                    graphvizDiagram.AppendLine();\n                }\n            }\n            graphvizDiagram.AppendLine();\n\n            // Sorted results\n            graphvizDiagram.AppendLine(\"\\tedge [penwidth=1.5, color=\\\"#67BC6B\\\"]\");\n            for (var i = 0; i < sortedCallbacks.Count - 1; ++i)\n            {\n                graphvizDiagram.AppendLine($\"\\t<{sortedCallbacks[i].name}> -> <{sortedCallbacks[i + 1].name}>\");\n            }\n            graphvizDiagram.AppendLine(\"}\");\n\n            File.WriteAllText(path, graphvizDiagram.ToString());\n            EditorUtility.OpenWithDefaultApp(path);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/ICreateToolbar.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\n\nnamespace UnityEditor.Overlays\n{\n    public interface ICreateHorizontalToolbar\n    {\n        OverlayToolbar CreateHorizontalToolbarContent();\n    }\n\n    public interface ICreateVerticalToolbar\n    {\n        OverlayToolbar CreateVerticalToolbarContent();\n    }\n\n    public interface ICreateToolbar\n    {\n        public IEnumerable<string> toolbarElements { get; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/IMGUIOverlay.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    // No interference from OverlayCanvas. This overlay completely controls when it is visible or hidden.\n    interface IControlVisibility\n    {\n    }\n\n    // Overlay is only displayed in the active scene view, when visible is true.\n    public interface ITransientOverlay\n    {\n        bool visible { get; }\n    }\n\n    // Used by SRP https://github.com/Unity-Technologies/Graphics/commit/9e7999d30a1a5189ab9d30e5341a2e48962db453\n    // Remove once VFX overlays are using ITransientOverlay\n    abstract class TransientSceneViewOverlay : IMGUIOverlay, ITransientOverlay\n    {\n        public abstract bool visible { get; }\n        internal virtual bool ShouldDisplay() => visible;\n    }\n\n    public abstract class IMGUIOverlay : Overlay\n    {\n        internal IMGUIContainer imguiContainer { get; private set; }\n\n        public sealed override VisualElement CreatePanelContent()\n        {\n            rootVisualElement.pickingMode = PickingMode.Position;\n            imguiContainer = new IMGUIContainer();\n            imguiContainer.onGUIHandler = OnPanelGUIHandler;\n            OnContentRebuild();\n            return imguiContainer;\n        }\n\n        internal virtual void OnContentRebuild() { }\n\n        void OnPanelGUIHandler()\n        {\n            if (!displayed)\n                return;\n\n            m_DisableContentModification = Event.current.type == EventType.Layout;\n\n            OnGUI();\n\n            m_DisableContentModification = false;\n\n            if (Event.current.isMouse)\n                Event.current.Use();\n        }\n\n        public abstract void OnGUI();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/Overlay.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.ComponentModel;\nusing UnityEditor.Toolbars;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    [Flags]\n    public enum Layout\n    {\n        HorizontalToolbar = 1 << 0,\n        VerticalToolbar = 1 << 1,\n        Panel = 1 << 2,\n\n        All = Panel | HorizontalToolbar | VerticalToolbar,\n    }\n\n    // See also OverlayPlacement.cs\n    public abstract partial class Overlay\n    {\n        const string k_UxmlPath = \"UXML/Overlays/overlay.uxml\";\n        public static readonly string ussClassName = \"unity-overlay\";\n        const string k_Highlight = \"overlay-box-highlight\";\n        const string k_Floating = \"overlay--floating\";\n        internal const string k_HeaderTitle = \"overlay-header__title\";\n        internal const string k_HeaderIcon = \"overlay-header__icon\";\n        const string k_Collapsed = \"unity-overlay--collapsed\";\n        internal const string k_Header = \"overlay-header\";\n        const string k_Expanded = \"unity-overlay--expanded\";\n        internal const string k_CollapsedContent = \"overlay-collapsed-content\";\n        internal const string k_UnfoldedContent = \"overlay-panel-foldout-content-expanded\";\n        internal const string k_FoldedContent = \"overlay-panel-foldout-content-collapsed\";\n        const string k_CollapsedIconButton = \"unity-overlay-collapsed-dropdown__icon\";\n        internal const string k_ToolbarHorizontalLayout = \"overlay-layout--toolbar-horizontal\";\n        internal const string k_ToolbarVerticalLayout = \"overlay-layout--toolbar-vertical\";\n        const string k_PanelLayout = \"overlay-layout--freesize\";\n        internal const string draggerName = \"unity-overlay-collapse__dragger\";\n\n        string m_Id, m_RootVisualElementName, m_DisplayName;\n        Layout m_ActiveLayout = Layout.Panel;\n\n        internal bool dontSaveInLayout {get; set;}\n        internal bool m_HasMenuEntry = true;\n\n        [SerializeField]\n        Layout m_Layout = Layout.Panel;\n        [SerializeField]\n        bool m_Collapsed;\n        [SerializeField]\n        bool m_Folded;\n        [SerializeField]\n        bool m_Floating;\n        [SerializeField]\n        Vector2 m_FloatingSnapOffset;\n        [SerializeField]\n        internal Vector2 m_SnapOffsetDelta = Vector2.zero;\n        [SerializeField]\n        SnapCorner m_FloatingSnapCorner = SnapCorner.TopLeft;\n\n        //Min and Max being 0 means the resizing is disabled for that axis without enforcing an actual size\n        //Resizing is disabled by default\n        [SerializeField]\n        Vector2 m_Size;\n        [SerializeField]\n        bool m_SizeOverridden;\n        Vector2 m_MinSize = Vector2.zero;\n        Vector2 m_MaxSize = Vector2.zero;\n        Vector2 m_DefaultSize = Vector2.zero;\n\n        // Temporary Variables\n        bool m_LockAnchor = false;\n        bool m_ContentsChanged = true;\n        internal bool m_DisableContentModification = false;\n\n        // Connections\n        public EditorWindow containerWindow => canvas.containerWindow;\n        internal OverlayCanvas canvas { get; set; }\n        internal bool isPopup { get; set; }\n        OverlayContainer m_Container;\n        internal OverlayContainer tempTargetContainer { get; set; }\n\n        // Instantiated VisualElement contents\n        VisualElement m_CurrentContent;\n        VisualElement m_CollapsedContent;\n        OverlayPopup m_ModalPopup; // collapsed popup root\n        VisualElement m_RootVisualElement;\n        Toggle m_ToggleElement;\n        VisualElement m_ResizeTarget;\n\n        internal VisualElement resizeTarget => m_ResizeTarget;\n\n        OverlayDropZone m_BeforeDropZone;\n        OverlayDropZone m_AfterDropZone;\n\n        internal OverlayDropZone insertBeforeDropZone => m_BeforeDropZone;\n        internal OverlayDropZone insertAfterDropZone => m_AfterDropZone;\n\n        // Callbacks\n        public event Action<Layout> layoutChanged;\n        public event Action<bool> collapsedChanged;\n        public event Action<bool> displayedChanged;\n        internal event Action<OverlayContainer> containerChanged;\n        internal event Action minSizeChanged;\n        internal event Action maxSizeChanged;\n        internal event Action defaultSizeChanged;\n        internal event Action sizeOverridenChanged;\n\n        // Invoked in partial class OverlayPlacement.cs\n#pragma warning disable 67\n        public event Action<bool> floatingChanged;\n        public event Action<Vector3> floatingPositionChanged;\n#pragma warning restore 67\n\n        public string id\n        {\n            get => m_Id;\n            internal set { m_Id = value; }\n        }\n\n        static VisualTreeAsset s_TreeAsset;\n        event Action displayNameChanged;\n        VisualElement m_ContentRoot;\n\n        // Properties\n        internal bool hasMenuEntry => m_HasMenuEntry;\n        internal Rect collapsedButtonRect => collapsedContent.worldBound;\n\n        Texture2D m_CollapsedIcon = null;\n        public Texture2D collapsedIcon\n        {\n            set\n            {\n                if(m_CollapsedIcon != null && m_CollapsedIcon.Equals(value))\n                    return;\n\n                m_CollapsedIcon = value;\n\n                if (m_CollapsedContent == null)\n                    return;\n                UpdateOverlayIcons();\n            }\n        }\n\n        VisualElement collapsedContent\n        {\n            get\n            {\n                if (m_CollapsedContent != null)\n                    return m_CollapsedContent;\n\n                m_CollapsedContent = rootVisualElement.Q(k_CollapsedContent);\n                m_CollapsedContent.Q<Button>().clicked += ToggleCollapsedPopup;\n\n                var iconElement = rootVisualElement.Q<Label>(classes: k_CollapsedIconButton);\n\n                var collapsedIcon = GetCollapsedIconContent();\n                if (collapsedIcon.image != null)\n                    iconElement.style.backgroundImage = collapsedIcon.image as Texture2D;\n                else\n                    iconElement.text = collapsedIcon.text;\n\n                return m_CollapsedContent;\n            }\n        }\n\n        public Layout layout\n        {\n            get => m_Layout;\n\n            internal set\n            {\n                if(m_DisableContentModification)\n                {\n                    Debug.LogError(GetEventTypeErrorMessage(\"Overlay.layout\"));\n                    return;\n                }\n\n                if (m_Layout == value)\n                    return;\n\n                m_Layout = value;\n                RebuildContent();\n            }\n        }\n\n        // layout is the preferred layout, active layout is what this overlay is actually using\n        protected internal Layout activeLayout => m_ActiveLayout;\n\n        public bool collapsed\n        {\n            get => m_CollapsedContent != null && m_CollapsedContent.parent == contentRoot;\n\n            set\n            {\n                if(m_DisableContentModification)\n                {\n                    Debug.LogError(GetEventTypeErrorMessage(\"Overlay.collapsed\"));\n                    return;\n                }\n\n                m_Collapsed = value;\n                if (m_Collapsed != (m_CollapsedContent != null && m_CollapsedContent.parent == contentRoot))\n                    RebuildContent();\n            }\n        }\n\n        internal bool folded\n        {\n            get => m_Folded;\n\n            set\n            {\n                m_Folded = value;\n                UpdateHeaderFoldout();\n            }\n        }\n\n        public string displayName\n        {\n            get\n            {\n                if (String.IsNullOrEmpty(m_DisplayName))\n                    return rootVisualElement.name;\n                return m_DisplayName;\n            }\n            set\n            {\n                if (m_DisplayName != value)\n                {\n                    m_DisplayName = value;\n                    displayNameChanged?.Invoke();\n                }\n            }\n        }\n\n        internal bool userControlledVisibility => !(this is IControlVisibility || this is ITransientOverlay);\n\n        internal OverlayContainer container\n        {\n            get => m_Container;\n            set\n            {\n                if (m_Container == value)\n                    return;\n\n                m_Container = value;\n                containerChanged?.Invoke(m_Container);\n            }\n        }\n\n        internal DockZone dockZone => floating ? DockZone.Floating : OverlayCanvas.GetDockZone(container);\n\n        internal DockPosition dockPosition => container.GetSection(OverlayContainerSection.BeforeSpacer).Contains(this) ? DockPosition.Top : DockPosition.Bottom;\n\n        internal static VisualTreeAsset treeAsset\n        {\n            get\n            {\n                if (s_TreeAsset != null)\n                    return s_TreeAsset;\n                return s_TreeAsset = (VisualTreeAsset)EditorGUIUtility.Load(k_UxmlPath);\n            }\n        }\n\n        public bool displayed\n        {\n            get => rootVisualElement.style.display == DisplayStyle.Flex;\n            set\n            {\n                if (rootVisualElement.style.display != (value ? DisplayStyle.Flex : DisplayStyle.None))\n                {\n                    if(m_DisableContentModification)\n                    {\n                        Debug.LogError(GetEventTypeErrorMessage(\"Overlay.displayed\"));\n                        return;\n                    }\n\n                    rootVisualElement.style.display = value ? DisplayStyle.Flex : DisplayStyle.None;\n\n                    RebuildContent();\n                    displayedChanged?.Invoke(value);\n                }\n            }\n        }\n\n        // Externally supported layouts are enforced by implementing ICreate interfaces. Internally we need a dynamic\n        // solution to handle CustomEditors. This isn't exposed because it would require much more validation to ensure\n        // that `supportedLayouts` is correct when coming from external code, whereas internally we can trust that this\n        // value is correct.\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        protected internal virtual Layout supportedLayouts\n        {\n            get\n            {\n                var supported = Layout.Panel;\n                if (this is ICreateToolbar)\n                    supported |= Layout.HorizontalToolbar | Layout.VerticalToolbar;\n                if (this is ICreateHorizontalToolbar)\n                    supported |= Layout.HorizontalToolbar;\n                if (this is ICreateVerticalToolbar)\n                    supported |= Layout.VerticalToolbar;\n                return supported;\n            }\n        }\n\n        sealed class GlobalMouseBehaviourForOverlays : MouseManipulator\n        {\n            Overlay m_Overlay;\n\n            public GlobalMouseBehaviourForOverlays(Overlay overlay)\n            {\n                m_Overlay = overlay;\n            }\n\n            protected override void RegisterCallbacksOnTarget()\n            {\n                target.RegisterCallback<MouseDownEvent>(OnMouseDownTrickleDown, TrickleDown.TrickleDown);\n                target.RegisterCallback<MouseDownEvent>(OnMouseDownBubbleUp, TrickleDown.NoTrickleDown);\n                target.RegisterCallback<MouseUpEvent>(OnMouseUp);\n                target.RegisterCallback<MouseMoveEvent>(OnMouseMove);\n            }\n\n            protected override void UnregisterCallbacksFromTarget()\n            {\n                target.UnregisterCallback<MouseDownEvent>(OnMouseDownTrickleDown, TrickleDown.TrickleDown);\n                target.UnregisterCallback<MouseDownEvent>(OnMouseDownBubbleUp, TrickleDown.NoTrickleDown);\n                target.UnregisterCallback<MouseUpEvent>(OnMouseUp);\n                target.UnregisterCallback<MouseMoveEvent>(OnMouseMove);\n            }\n\n            void OnMouseDownTrickleDown(MouseDownEvent e)\n            {\n                m_Overlay.BringToFront();\n            }\n\n            void OnMouseDownBubbleUp(MouseDownEvent e)\n            {\n                e.StopPropagation();\n            }\n\n            void OnMouseUp(MouseUpEvent e)\n            {\n                e.StopPropagation();\n            }\n\n            void OnMouseMove(MouseMoveEvent e)\n            {\n                e.StopPropagation();\n            }\n        }\n\n        public VisualElement rootVisualElement\n        {\n            get\n            {\n                if (m_RootVisualElement != null)\n                    return m_RootVisualElement;\n\n                m_RootVisualElement = new VisualElement();\n                treeAsset.CloneTree(m_RootVisualElement);\n\n                m_RootVisualElement.name = m_RootVisualElementName;\n                m_RootVisualElement.usageHints = UsageHints.DynamicTransform;\n                m_RootVisualElement.AddToClassList(ussClassName);\n                m_RootVisualElement.AddManipulator(new GlobalMouseBehaviourForOverlays(this));\n\n                var dragger = new OverlayDragger(this);\n                var contextClick = new ContextualMenuManipulator(BuildContextMenu);\n\n                var header = m_RootVisualElement.Q(null, k_Header);\n                m_ToggleElement = m_RootVisualElement.Q<Toggle>(\"overlay-header__toggle\");\n                m_ToggleElement.RegisterValueChangedCallback(evt => folded = !evt.newValue);\n                header.AddManipulator(contextClick);\n                header.AddManipulator(dragger);\n\n                var title = m_RootVisualElement.Q<Label>(k_HeaderTitle);\n                title.text = displayName;\n\n                UpdateOverlayIcons();\n\n                displayNameChanged += () => title.text = displayName;\n\n                var dockArea = new VisualElement() { name = \"OverlayDockArea\" };\n                dockArea.pickingMode = PickingMode.Ignore;\n                dockArea.StretchToParentSize();\n                m_RootVisualElement.Add(dockArea);\n\n                dockArea.Add(m_BeforeDropZone = new OverlayDropZone(this, OverlayDropZone.Placement.Before));\n                dockArea.Add(m_AfterDropZone = new OverlayDropZone(this, OverlayDropZone.Placement.After));\n\n                m_RootVisualElement.tooltip = L10n.Tr(displayName);\n\n                m_ResizeTarget = m_RootVisualElement.Q(\"unity-overlay\");\n                m_ResizeTarget.style.overflow = Overflow.Hidden;\n                m_ResizeTarget.Add(new OverlayResizerGroup(this));\n\n                return m_RootVisualElement;\n            }\n        }\n\n        // used by tests\n        internal VisualElement contentRoot\n        {\n            get\n            {\n                if(m_ContentRoot != null)\n                    return m_ContentRoot;\n                m_ContentRoot = rootVisualElement.Q(\"overlay-content\");\n                m_ContentRoot.renderHints = RenderHints.ClipWithScissors;\n                return m_ContentRoot;\n            }\n        }\n\n        public bool isInToolbar => container is ToolbarOverlayContainer;\n\n        internal bool sizeOverridden\n        {\n            get => m_SizeOverridden;\n\n            set\n            {\n                if (m_SizeOverridden == value)\n                    return;\n\n                m_SizeOverridden = value;\n                sizeOverridenChanged?.Invoke();\n            }\n        }\n\n        internal Vector2 sizeToSave => m_Size;\n\n        public Vector2 size\n        {\n            get\n            {\n                return m_ResizeTarget.layout.size;\n            }\n            set\n            {\n                if (m_Size == value && sizeOverridden)\n                    return;\n\n                m_Size = value;\n                sizeOverridden = true;\n                UpdateSize();\n            }\n        }\n\n        public Vector2 minSize\n        {\n            get => m_MinSize;\n            set\n            {\n                if (m_MinSize == value)\n                    return;\n\n                m_MinSize = value;\n                minSizeChanged?.Invoke();\n                UpdateSize();\n            }\n        }\n\n        public Vector2 maxSize\n        {\n            get => m_MaxSize;\n            set\n            {\n                if (m_MaxSize == value)\n                    return;\n\n                m_MaxSize = value;\n                maxSizeChanged?.Invoke();\n                UpdateSize();\n            }\n        }\n\n        public Vector2 defaultSize\n        {\n            get => m_DefaultSize;\n            set\n            {\n                if (m_DefaultSize == value)\n                    return;\n\n                m_DefaultSize = value;\n                defaultSizeChanged?.Invoke();\n                UpdateSize();\n            }\n        }\n\n        internal static string GetEventTypeErrorMessage(string errorEvent)\n        {\n            return L10n.Tr($\"Cannot modify {errorEvent} during event of type EventType.Layout\");\n        }\n\n        internal void ResetSize()\n        {\n            if (!sizeOverridden)\n                return;\n\n            sizeOverridden = false;\n            UpdateSize();\n        }\n\n        bool CanCreateRequestedLayout(Layout requested)\n        {\n            // Is layout requesting a toolbar while Overlay is not implementing ICreateToolbar?\n            if ((int)(requested & supportedLayouts) < 1)\n                return false;\n\n            if (tempTargetContainer != null)\n                return tempTargetContainer.IsOverlayLayoutSupported(requested);\n\n            return floating || container == null || container.IsOverlayLayoutSupported(requested);\n        }\n\n        Layout GetBestLayoutForState()\n        {\n            // Always prefer the user-set layout\n            if (CanCreateRequestedLayout(layout))\n                return layout;\n\n            for (int i = 0; i < 3; i++)\n            {\n                if (CanCreateRequestedLayout((Layout)(1 << i)))\n                    return (Layout)(1 << i);\n            }\n\n            return 0;\n        }\n\n        internal VisualElement GetSimpleHeader()\n        {\n            var header = new VisualElement();\n            var title = new Label(displayName);\n            title.name = k_HeaderTitle;\n            header.Add(title);\n\n            return header;\n        }\n\n        // Rebuild the Overlay contents, taking into account the container and layout. If the container does not support\n        // the requested layout, the overlay will be collapsed (the collapsed property will not be modified, and the\n        // next time RebuildContent is invoked this method will try again to build the requested layout and un-collapse\n        // the Overlay).\n        internal void RebuildContent()\n        {\n            if (m_Container == null)\n                return;\n\n            // We need to invoke a callback if the collapsed state changes (either from user request or invalid layout)\n            bool wasCollapsed = collapsedContent.parent == contentRoot;\n\n            var prevLayout = m_ActiveLayout;\n            m_ActiveLayout = GetBestLayoutForState();\n\n            // Clear any existing contents.\n            m_CurrentContent?.RemoveFromHierarchy();\n            collapsedContent.RemoveFromHierarchy();\n            m_CurrentContent = null;\n\n            if (!displayed)\n                return;\n\n            // An Overlay can collapsed by request, or by necessity. If collapsed due to invalid layout/container match,\n            // the collapsed property is not modified. The next time a content rebuild is requested we'll try again to\n            // create the contents with the stored state.\n            bool isCollapsed = m_Collapsed || activeLayout == 0;\n            var targetContainer = tempTargetContainer ?? container;\n\n            m_ContentsChanged = true;\n\n            m_ActiveLayout = m_ActiveLayout == 0 ? targetContainer.preferredLayout : m_ActiveLayout;\n\n            // Update styling\n            if (floating)\n            {\n                rootVisualElement.style.position = Position.Absolute;\n                rootVisualElement.AddToClassList(k_Floating);\n            }\n            else\n            {\n                rootVisualElement.style.position = Position.Relative;\n#pragma warning disable CS0618 // Type or member is obsolete\n                rootVisualElement.transform.position = Vector3.zero;\n#pragma warning restore CS0618 // Type or member is obsolete\n                rootVisualElement.RemoveFromClassList(k_Floating);\n            }\n\n            rootVisualElement.EnableInClassList(k_ToolbarVerticalLayout, m_ActiveLayout == Layout.VerticalToolbar);\n            rootVisualElement.EnableInClassList(k_ToolbarHorizontalLayout, m_ActiveLayout == Layout.HorizontalToolbar);\n            rootVisualElement.EnableInClassList(k_PanelLayout, m_ActiveLayout == Layout.Panel);\n            rootVisualElement.EnableInClassList(k_Collapsed, isCollapsed);\n            rootVisualElement.EnableInClassList(k_Expanded, !isCollapsed);\n\n            if (isCollapsed)\n            {\n                if (collapsedContent.parent != contentRoot)\n                    contentRoot.Add(collapsedContent);\n            }\n            else\n            {\n                m_CurrentContent = CreateContent(m_ActiveLayout);\n                contentRoot.Add(m_CurrentContent);\n            }\n\n            // Disable drop zone previews when floating\n            var dropZonesDisplay = !floating ? DisplayStyle.Flex : DisplayStyle.None;\n            m_BeforeDropZone.style.display = dropZonesDisplay;\n            m_AfterDropZone.style.display = dropZonesDisplay;\n\n            UpdateSize();\n            UpdateHeaderFoldout();\n\n            // Invoke callbacks after content is created and styling has been applied\n            if(wasCollapsed != isCollapsed)\n                collapsedChanged?.Invoke(isCollapsed);\n\n            if (prevLayout != m_ActiveLayout)\n                layoutChanged?.Invoke(m_ActiveLayout);\n        }\n\n        void UpdateHeaderFoldout()\n        {\n            // Folded styling should only be applied if the overlay is not collapsed.\n            bool isFolded = folded && !collapsed;\n            m_ToggleElement.SetValueWithoutNotify(!folded);\n            var foldoutContent = m_RootVisualElement.Q(\"overlay-content\");\n            if (foldoutContent == null)\n                return;\n            foldoutContent.EnableInClassList(k_UnfoldedContent, !isFolded);\n            foldoutContent.EnableInClassList(k_FoldedContent, isFolded);\n            UpdateSize();\n        }\n\n        internal GUIContent GetCollapsedIconContent()\n        {\n            var icon = m_CollapsedIcon == null\n                ? EditorGUIUtility.LoadIcon(EditorGUIUtility.GetIconPathFromAttribute(GetType()))\n                : m_CollapsedIcon;\n\n            if (icon != null)\n                return new GUIContent(icon);\n\n            return new GUIContent(OverlayUtilities.GetSignificantLettersForIcon(displayName));\n        }\n\n        private void UpdateOverlayIcons()\n        {\n            var collapsedIconElement = collapsedContent.Q<Label>(classes: k_CollapsedIconButton);\n            var headerIconElement = m_RootVisualElement.Q<VisualElement>(k_HeaderIcon);\n            var content = GetCollapsedIconContent();\n            var image = content.image as Texture2D;\n\n            if(collapsedIconElement != null)\n            {\n                collapsedIconElement.style.backgroundImage = image;\n                collapsedIconElement.text = image != null ? null : OverlayUtilities.GetSignificantLettersForIcon(displayName);\n            }\n\n            if (headerIconElement != null)\n            {\n                if (image == null)\n                    headerIconElement.style.display = DisplayStyle.None;\n                else\n                {\n                    headerIconElement.style.backgroundImage = image;\n                    headerIconElement.style.display = StyleKeyword.Null;\n                }\n            }\n        }\n\n        internal bool IsResizable()\n        {\n            return activeLayout == Layout.Panel && !collapsed && !folded;\n        }\n\n        bool IsSizeAuto(float size)\n        {\n            return size <= 0 || float.IsNegativeInfinity(size);\n        }\n\n        void UpdateSize()\n        {\n            if (m_ResizeTarget == null)\n                return;\n\n            ApplySize(m_ResizeTarget, IsResizable(), sizeOverridden);\n\n            var position = canvas.EnsureOverlapsWindow(new Rect(floatingPosition, m_Size)).position;\n            UpdateSnapping(position);\n        }\n\n        void ApplySize(VisualElement element, bool resizableLayout, bool sizeOverridden)\n        {\n            element.style.minWidth = resizableLayout && !IsSizeAuto(m_MinSize.x) ? m_MinSize.x : new StyleLength(StyleKeyword.Auto);\n            element.style.minHeight = resizableLayout && !IsSizeAuto(m_MinSize.y) ? m_MinSize.y : new StyleLength(StyleKeyword.Auto);\n            element.style.maxWidth = resizableLayout && !IsSizeAuto(m_MaxSize.x) ? m_MaxSize.x : new StyleLength(StyleKeyword.Auto);\n            element.style.maxHeight = resizableLayout && !IsSizeAuto(m_MaxSize.y) ? m_MaxSize.y : new StyleLength(StyleKeyword.Auto);\n\n            if (resizableLayout && sizeOverridden)\n            {\n                element.style.width = m_Size.x;\n                element.style.height = m_Size.y;\n            }\n            else\n            {\n                element.style.width = defaultSize.x > 0 && resizableLayout ? defaultSize.x : new StyleLength(StyleKeyword.Auto);\n                element.style.height = defaultSize.y > 0 && resizableLayout ? defaultSize.y : new StyleLength(StyleKeyword.Auto);\n            }\n        }\n\n        // CreateContent always returns a new VisualElement tree with the Overlay contents. It does not modify the\n        // m_CurrentContent or m_ContentRoot properties. Use RebuildContent() to update an Overlay contents.\n        // CreateContent will try to return content in the requested layout, regardless of whether the container\n        // supports it. The only reason that content would not be created with the requested layout is if the Overlay\n        // does not implement the correct ICreate{Horizontal, Vertical}Toolbar interface.\n        // To rebuild content taking into account the parent container, use RebuildContent().\n        public VisualElement CreateContent(Layout requestedLayout)\n        {\n            var previousContent = m_ContentRoot;\n\n            try\n            {\n                VisualElement content = null;\n\n                switch (requestedLayout)\n                {\n                    case Layout.HorizontalToolbar:\n                        if (!(this is ICreateHorizontalToolbar horizontal)\n                            || (content = horizontal.CreateHorizontalToolbarContent()) == null)\n                            goto default;\n                        break;\n\n                    case Layout.VerticalToolbar:\n                        if (!(this is ICreateVerticalToolbar vertical)\n                            || (content = vertical.CreateVerticalToolbarContent()) == null)\n                            goto default;\n                        break;\n\n                    case Layout.Panel:\n                        content = CreatePanelContent();\n                        break;\n\n                    default:\n                        if (!(this is ICreateToolbar toolbar))\n                        {\n                            Debug.LogError($\"Overlay {GetType()} attempting to set unsupported layout: {requestedLayout}\");\n                            goto case Layout.Panel;\n                        }\n                        content = new EditorToolbar(toolbar.toolbarElements, canvas.containerWindow).rootVisualElement;\n                        break;\n                }\n\n                if (content != null)\n                {\n                    // When this happens styling isn't applied correctly when transitioning between popup window and\n                    // floating/docked.\n                    if (content == previousContent)\n                        Debug.LogError($\"Overlay named \\\"{displayName}\\\" returned a reference to the previous \" +\n                            $\" content. This is not allowed; CreateContent() must return a new instance.\");\n                    return content;\n                }\n            }\n            catch (Exception e)\n            {\n                Debug.LogError($\"Failed loading overlay \\\"{displayName}\\\"!\\n{e}\");\n                return new Label($\"{displayName} failed to load\");\n            }\n\n            Debug.LogError($\"Overlay \\\"{displayName}\\\" returned a null VisualElement.\");\n            return new Label($\"{displayName} failed to load\");\n        }\n\n        public abstract VisualElement CreatePanelContent();\n\n        // Invoked when an Overlay is added to an OverlayCanvas\n        public virtual void OnCreated() {}\n\n        public virtual void OnWillBeDestroyed() {}\n\n        public void Close() => canvas?.Remove(this);\n\n        // Used by tests\n        internal VisualElement popup => m_ModalPopup;\n\n        // Used by tests\n        internal void ToggleCollapsedPopup()\n        {\n            if (m_ModalPopup != null)\n            {\n                ClosePopup();\n                return;\n            }\n\n            m_ModalPopup = OverlayPopup.CreateUnderOverlay(this);\n            ApplySize(m_ModalPopup.Q(className: \"overlay-box-background\"), true, sizeOverridden);\n\n            m_ModalPopup.RegisterCallback<FocusOutEvent>(evt =>\n            {\n                if (evt.relatedTarget is VisualElement target && (m_ModalPopup == target || m_ModalPopup.Contains(target)))\n                    return;\n\n                // When the new focus is an embedded IMGUIContainer or popup window, give focus back to the modal\n                // popup so that the next focus out event has the opportunity to close the element.\n                if (evt.relatedTarget == null && m_ModalPopup.containsCursor)\n                    EditorApplication.delayCall += m_ModalPopup.Focus;\n                else\n                    ClosePopup();\n            });\n\n            canvas.rootVisualElement.Add(m_ModalPopup);\n            m_ModalPopup.Focus();\n        }\n\n        public void RefreshPopup()\n        {\n            m_ModalPopup?.Refresh();\n        }\n\n        void ClosePopup()\n        {\n            m_ModalPopup?.RemoveFromHierarchy();\n            m_ModalPopup = null;\n        }\n\n        static DropdownMenuAction.Status GetMenuItemState(bool isChecked)\n        {\n            return isChecked ? DropdownMenuAction.Status.Checked : DropdownMenuAction.Status.Normal;\n        }\n\n        void BuildContextMenu(ContextualMenuPopulateEvent evt)\n        {\n            var menu = evt.menu;\n\n            menu.AppendAction(L10n.Tr(\"Hide\"),\n                (action) => displayed = false,\n                userControlledVisibility ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);\n\n            if (collapsed)\n            {\n                if (container == null || container.IsOverlayLayoutSupported(supportedLayouts))\n                    menu.AppendAction(L10n.Tr(\"Expand\"), (action) => collapsed = false);\n            }\n            else\n                menu.AppendAction(L10n.Tr(\"Collapse\"), (action) => collapsed = true);\n\n            if (!isInToolbar)\n            {\n                menu.AppendAction(L10n.Tr(\"Reset Size\"), action => ResetSize());\n\n                menu.AppendSeparator();\n                var layouts = supportedLayouts;\n\n                // Panel layout is always supported by default, we only add this option in the menu if other options are available\n                if ((layouts & Layout.HorizontalToolbar) != 0 || (layouts & Layout.VerticalToolbar) != 0)\n                    menu.AppendAction(L10n.Tr(\"Panel\"), action => { layout = Layout.Panel; collapsed = false; }, GetMenuItemState(layout == Layout.Panel));\n                if ((layouts & Layout.HorizontalToolbar) != 0)\n                    menu.AppendAction(L10n.Tr(\"Horizontal\"), action => { layout = Layout.HorizontalToolbar; collapsed = false; }, GetMenuItemState(layout == Layout.HorizontalToolbar));\n                if ((layouts & Layout.VerticalToolbar) != 0)\n                    menu.AppendAction(L10n.Tr(\"Vertical\"), action => { layout = Layout.VerticalToolbar; collapsed = false; }, GetMenuItemState(layout == Layout.VerticalToolbar));\n            }\n        }\n\n        internal void SetHighlightEnabled(bool highlight)\n        {\n            rootVisualElement.EnableInClassList(k_Highlight, highlight);\n        }\n\n        internal void Initialize(OverlayAttribute attrib) => Initialize(attrib.id, attrib.ussName, attrib.displayName, attrib.defaultSize, attrib.minSize, attrib.maxSize);\n\n        internal void Initialize(string _id, string _uss, string _display, Vector2 defaultSize, Vector2 minSize, Vector2 maxSize)\n        {\n            m_RootVisualElementName = _uss;\n            string name = string.IsNullOrEmpty(_display) ? m_RootVisualElementName : _display;\n            m_Id = string.IsNullOrEmpty(_id) ? name : _id;\n            displayName = L10n.Tr(name);\n            rootVisualElement.style.display = DisplayStyle.None;\n\n            // Taking into account the case where the user modifies the sizes in their overlay constructor.\n            if (!float.IsNegativeInfinity(defaultSize.x) && !float.IsNegativeInfinity(defaultSize.y))\n                m_DefaultSize = defaultSize;\n\n            if (!float.IsNegativeInfinity(minSize.x) && !float.IsNegativeInfinity(minSize.y))\n                m_MinSize = minSize;\n\n            if (!float.IsNegativeInfinity(maxSize.x) && !float.IsNegativeInfinity(maxSize.y))\n                m_MaxSize = maxSize;\n        }\n\n        // marked obsolete by @karlh 2023/03/13\n        [Obsolete(\"No longer necessary, Overlay data is serialized by the OverlayCanvas.\", false)]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        internal void ApplySaveData(SaveData data)\n        {\n            floatingSnapCorner = data.snapCorner;\n            m_Floating = data.floating;\n            m_Collapsed = data.collapsed;\n            m_Layout = data.layout;\n            m_FloatingSnapOffset = data.snapOffset;\n            m_SnapOffsetDelta = data.snapOffsetDelta;\n            m_SizeOverridden = data.sizeOverridden;\n            m_Size = data.size;\n        }\n\n        internal void Reset(OverlayAttribute attrib)\n        {\n            if (attrib != null)\n            {\n                if (!float.IsNegativeInfinity(attrib.defaultSize.x) && !float.IsNegativeInfinity(attrib.defaultSize.y))\n                    m_DefaultSize = attrib.defaultSize;\n\n                if (!float.IsNegativeInfinity(attrib.minSize.x) && !float.IsNegativeInfinity(attrib.minSize.y))\n                    m_MinSize = attrib.minSize;\n\n                if (!float.IsNegativeInfinity(attrib.maxSize.x) && !float.IsNegativeInfinity(attrib.maxSize.y))\n                    m_MaxSize = attrib.maxSize;\n\n                m_Floating = attrib.defaultDockZone == DockZone.Floating;\n                m_Collapsed = false;\n                m_Folded = false;\n                m_Layout = attrib.defaultLayout;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayAttribute.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor.Overlays\n{\n    enum OverlayPriority\n    {\n        //Default overlays\n        Tools = 0,\n        ToolSettings = 1,\n        GridAndSnap = 2,\n        DrawModes = 5,\n        ViewOptions = 6,\n        Search = 11,\n        Orientation = 12,\n        Cameras = 13,\n        //Additional overlays\n        AINavigation = 20,\n        LightingVisualization = 31,\n        PBRValidation = 32,\n        LightingVisualizationColor = 33,\n        ClothConstraints = 41,\n        ClothCollisions = 42,\n        Default = 100\n    }\n\n    [AttributeUsage(AttributeTargets.Class)]\n    public sealed class OverlayAttribute : Attribute\n    {\n        Type m_EditorWindowType;\n        string m_Id;\n        string m_UssName;\n        bool m_DefaultDisplay;\n        string m_DisplayName;\n        DockZone m_DefaultDockZone;\n        DockPosition m_DefaultDockPosition;\n        int m_DefaultDockIndex;\n        Layout m_DefaultLayout;\n        float m_DefaultWidth;\n        float m_DefaultHeight;\n        float m_MinWidth;\n        float m_MinHeight;\n        float m_MaxWidth;\n        float m_MaxHeight;\n        int m_Priority = (int)OverlayPriority.Default;\n\n        public Type editorWindowType\n        {\n            get => m_EditorWindowType;\n            set => m_EditorWindowType = value;\n        }\n\n        public string id\n        {\n            get => m_Id;\n            set => m_Id = value;\n        }\n\n        public string displayName\n        {\n            get => m_DisplayName;\n            set => m_DisplayName = value;\n        }\n\n        public string ussName\n        {\n            get => m_UssName;\n            set => m_UssName = value;\n        }\n\n        public bool defaultDisplay\n        {\n            get => m_DefaultDisplay;\n            set => m_DefaultDisplay = value;\n        }\n\n        public DockZone defaultDockZone\n        {\n            get => m_DefaultDockZone;\n            set => m_DefaultDockZone = value;\n        }\n\n        public DockPosition defaultDockPosition\n        {\n            get => m_DefaultDockPosition;\n            set => m_DefaultDockPosition = value;\n        }\n\n        public int defaultDockIndex\n        {\n            get => m_DefaultDockIndex;\n            set => m_DefaultDockIndex = value;\n        }\n\n        public Layout defaultLayout\n        {\n            get => m_DefaultLayout;\n            set => m_DefaultLayout = value;\n        }\n\n        public float defaultWidth\n        {\n            get => m_DefaultWidth;\n            set => m_DefaultWidth = value;\n        }\n\n        public float defaultHeight\n        {\n            get => m_DefaultHeight;\n            set => m_DefaultHeight = value;\n        }\n\n        public float minWidth\n        {\n            get => m_MinWidth;\n            set => m_MinWidth = value;\n        }\n\n        public float minHeight\n        {\n            get => m_MinHeight;\n            set => m_MinHeight = value;\n        }\n\n        public float maxWidth\n        {\n            get => m_MaxWidth;\n            set => m_MaxWidth = value;\n        }\n\n        public float maxHeight\n        {\n            get => m_MaxHeight;\n            set => m_MaxHeight = value;\n        }\n\n        internal Vector2 defaultSize => new Vector2(defaultWidth, defaultHeight);\n        internal Vector2 minSize => new Vector2(minWidth, minHeight);\n        internal Vector2 maxSize => new Vector2(maxWidth, maxHeight);\n\n        public int priority\n        {\n            get => m_Priority;\n            set => m_Priority = value;\n        }\n\n        public OverlayAttribute()\n        {\n            m_EditorWindowType = null;\n            m_DefaultDisplay = true;\n            m_Id = null;\n            m_DisplayName = null;\n            m_UssName = null;\n            m_DefaultDockZone = DockZone.RightColumn;\n            m_DefaultDockPosition = DockPosition.Bottom;\n            m_DefaultDockIndex = int.MaxValue;\n            m_DefaultLayout = Layout.Panel;\n            m_DefaultWidth = float.NegativeInfinity;\n            m_DefaultHeight = float.NegativeInfinity;\n            m_MinWidth = float.NegativeInfinity;\n            m_MinHeight = float.NegativeInfinity;\n            m_MaxWidth = float.NegativeInfinity;\n            m_MaxHeight = float.NegativeInfinity;\n            if (string.IsNullOrEmpty(m_UssName)) m_UssName = m_Id;\n        }\n\n        public OverlayAttribute(Type editorWindowType, string id, string displayName, string ussName, bool defaultDisplay = false):this()\n        {\n            this.editorWindowType = editorWindowType;\n            this.displayName = displayName;\n            this.id = id;\n            this.defaultDisplay = defaultDisplay;\n            this.ussName = ussName;\n        }\n\n        public OverlayAttribute(Type editorWindowType, string id, string displayName, bool defaultDisplay = false)\n            : this(editorWindowType, id, displayName, displayName, defaultDisplay)\n        {\n        }\n\n        public OverlayAttribute(Type editorWindowType, string displayName, bool defaultDisplay = false)\n            : this(editorWindowType, displayName, displayName, displayName, defaultDisplay)\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayCanvas.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEngine;\nusing UnityEngine.Profiling;\nusing UnityEngine.Serialization;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    [Serializable]\n    public class SaveData : IEquatable<SaveData>\n    {\n        // Note on the obsolete fields in this class:\n        // Previously, overlays were not serialized in any form. In 2023.2, overlays are serialized via json to the\n        // SaveData.contents field. This removes the need for many state variables previously required to restore an\n        // overlay to it's last position, visibility, dock, etc. SaveData as a class is still necessary, however, as\n        // the non-obsolete fields are conditions that are not known the Overlay itself.\n        // In the interest of backwards compatibility, the obsolete fields are left here for 2023.2. In 2024.1 (or\n        // whatever the next version happens to be), consider removing these. Overlay save data is implicitly updated\n        // when closing an editor or window for all overlays known to the window.\n\n        const int k_InvalidIndex = -1;\n\n        [SerializeField]\n        internal DockPosition dockPosition = DockPosition.Bottom;\n        [SerializeField]\n        internal string containerId = string.Empty;\n        [SerializeField]\n        internal bool displayed;\n        [SerializeField]\n        internal string id;\n        [SerializeField]\n        internal int index = k_InvalidIndex;\n        [SerializeField]\n        internal string contents;\n\n        [SerializeField, Obsolete]\n        internal bool floating;\n        [SerializeField, Obsolete]\n        internal bool collapsed;\n        [SerializeField, Obsolete]\n        internal Vector2 snapOffset;\n        [SerializeField, Obsolete]\n        internal Vector2 snapOffsetDelta;\n        [SerializeField, Obsolete]\n        internal SnapCorner snapCorner;\n        [SerializeField, Obsolete]\n        internal Layout layout = Layout.Panel;\n        [SerializeField, Obsolete]\n        internal Vector2 size;\n        [SerializeField, Obsolete]\n        [FormerlySerializedAs(\"sizeOverriden\")]\n        internal bool sizeOverridden;\n\n        public SaveData() { }\n\n#pragma warning disable 612\n\n        internal SaveData(SaveData other)\n        {\n            dockPosition = other.dockPosition;\n            containerId = other.containerId;\n            id = other.id;\n            index = other.index;\n            contents = other.contents;\n\n            // obsolete\n            floating = other.floating;\n            collapsed = other.collapsed;\n            displayed = other.displayed;\n            snapOffset = other.snapOffset;\n            snapOffsetDelta = other.snapOffsetDelta;\n            snapCorner = other.snapCorner;\n            layout = other.layout;\n            size = other.size;\n            sizeOverridden = other.sizeOverridden;\n        }\n\n        public SaveData(Overlay overlay)\n            : this(overlay, k_InvalidIndex) { }\n\n        internal SaveData(Overlay overlay, int indexInContainer)\n        {\n            if (indexInContainer < 0)\n                if (overlay.container == null || !overlay.container.GetOverlayIndex(overlay, out _, out indexInContainer))\n                    indexInContainer = k_InvalidIndex;\n\n            string container = overlay.container != null ? overlay.container.name : \"\";\n            DockPosition dock = overlay.container != null\n                                && overlay.container.ContainsOverlay(overlay, OverlayContainerSection.BeforeSpacer)\n                ? DockPosition.Top\n                : DockPosition.Bottom;\n\n            containerId = container;\n            index = indexInContainer;\n            dockPosition = dock;\n            id = overlay.id;\n            displayed = overlay.displayed;\n            contents = EditorJsonUtility.ToJson(overlay);\n\n            // obsolete\n            floating = overlay.floating;\n            collapsed = overlay.collapsed;\n            layout = overlay.layout;\n            snapCorner = overlay.floatingSnapCorner;\n            snapOffset = overlay.floatingSnapOffset - overlay.m_SnapOffsetDelta;\n            snapOffsetDelta = overlay.m_SnapOffsetDelta;\n            size = overlay.sizeToSave;\n            sizeOverridden = overlay.sizeOverridden;\n        }\n\n        public bool Equals(SaveData other)\n        {\n            if (ReferenceEquals(null, other)) return false;\n            if (ReferenceEquals(this, other)) return true;\n\n            return dockPosition == other.dockPosition\n                && containerId == other.containerId\n                && id == other.id\n                && index == other.index\n                && displayed == other.displayed\n                && floating == other.floating\n                && collapsed == other.collapsed\n                && snapOffset.Equals(other.snapOffset)\n                && snapOffsetDelta.Equals(other.snapOffsetDelta)\n                && snapCorner == other.snapCorner\n                && layout == other.layout\n                && size == other.size\n                && sizeOverridden == other.sizeOverridden;\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj)) return false;\n            if (ReferenceEquals(this, obj)) return true;\n            if (obj.GetType() != this.GetType()) return false;\n            return Equals((SaveData)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                var hashCode = (int)dockPosition;\n                hashCode = (hashCode * 397) ^ (containerId != null ? containerId.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ floating.GetHashCode();\n                hashCode = (hashCode * 397) ^ (id != null ? id.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ collapsed.GetHashCode();\n                hashCode = (hashCode * 397) ^ displayed.GetHashCode();\n                hashCode = (hashCode * 397) ^ snapOffset.GetHashCode();\n                hashCode = (hashCode * 397) ^ snapOffsetDelta.GetHashCode();\n                hashCode = (hashCode * 397) ^ (int)snapCorner;\n                hashCode = (hashCode * 397) ^ index;\n                hashCode = (hashCode * 397) ^ (int)layout;\n                hashCode = (hashCode * 397) ^ size.GetHashCode();\n                hashCode = (hashCode * 397) ^ sizeOverridden.GetHashCode();\n                return hashCode;\n            }\n        }\n\n        public override string ToString()\n        {\n            return $\"dockPosition: {dockPosition}\" +\n                   $\"\\ncontainerId: {containerId}\" +\n                   $\"\\nfloating: {floating}\" +\n                   $\"\\ncollapsed: {collapsed}\" +\n                   $\"\\ndisplayed: {displayed}\" +\n                   $\"\\nsnapOffset: {snapOffset}\" +\n                   $\"\\nsnapOffsetDelta: {snapOffsetDelta}\" +\n                   $\"\\nsnapCorner: {snapCorner}\" +\n                   $\"\\nid: {id}\" +\n                   $\"\\nindex: {index}\" +\n                   $\"\\nlayout: {layout}\" +\n                   $\"\\nsize: {size}\" +\n                   $\"\\nsizeOverridden: {sizeOverridden}\";\n        }\n#pragma warning restore 612\n    }\n\n    [Serializable]\n    sealed class ContainerData\n    {\n        public string containerId;\n        public float scrollOffset;\n    }\n\n    //Dock position within container\n    //for a horizontal container, Top is left, Bottom is right\n    public enum DockPosition\n    {\n        Top,\n        Bottom\n    }\n\n    enum SnapCorner\n    {\n        TopLeft,\n        TopRight,\n        BottomLeft,\n        BottomRight,\n    }\n\n    // public API to set a default docking zone. default is RightColumnBottom\n    public enum DockZone\n    {\n        LeftToolbar = 0,\n        RightToolbar = 1,\n        TopToolbar = 2,\n        BottomToolbar = 3,\n        LeftColumn = 4,\n        RightColumn = 5,\n        Floating = 6\n    }\n\n    [Serializable]\n    public sealed class OverlayCanvas : ISerializationCallbackReceiver\n    {\n        internal static readonly string ussClassName = \"unity-overlay-canvas\";\n        const string k_UxmlPath = \"UXML/Overlays/overlay-canvas.uxml\";\n        const string k_UxmlPathDropZone = \"UXML/Overlays/overlay-toolbar-dropzone.uxml\";\n        internal const string k_StyleCommon = \"StyleSheets/Overlays/OverlayCommon.uss\";\n        internal const string k_StyleLight = \"StyleSheets/Overlays/OverlayLight.uss\";\n        internal const string k_StyleDark = \"StyleSheets/Overlays/OverlayDark.uss\";\n        internal const int k_OverlayMinVisibleArea = 24;\n\n        const string k_FloatingContainer = \"overlay-container--floating\";\n        const string k_ToolbarArea = \"overlay-toolbar-area\";\n        const string k_DropTargetClassName = \"overlay-droptarget\";\n        const string k_DefaultContainer = \"overlay-container-default\";\n        static VisualTreeAsset s_TreeAsset;\n        static VisualTreeAsset s_DropZoneTreeAsset;\n\n        static SaveData defaultSaveData => new SaveData()\n        {\n            containerId = null,\n            displayed = false,\n            dockPosition = DockPosition.Bottom,\n            index = int.MaxValue\n        };\n\n        // order must match OverlayDockArea\n        static readonly string[] k_DockZoneContainerIDs = new string[7]\n        {\n            \"overlay-toolbar__left\",\n            \"overlay-toolbar__right\",\n            \"overlay-toolbar__top\",\n            \"overlay-toolbar__bottom\",\n            \"overlay-container--left\",\n            \"overlay-container--right\",\n            \"Floating\"\n        };\n\n        internal static DockZone GetDockZone(OverlayContainer container)\n        {\n            for(int i = 0, c = k_DockZoneContainerIDs.Length; i < c; i++)\n                if (k_DockZoneContainerIDs[i] == container.name)\n                    return (DockZone)i;\n            return DockZone.Floating;\n        }\n        \n        // used by tests\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        internal OverlayContainer GetDockZoneContainer(DockZone zone)\n        {\n            foreach(var container in m_Containers)\n                if (container.name == k_DockZoneContainerIDs[(int)zone])\n                    return container;\n            return null;\n        }\n\n        //Used by tests\n        internal bool m_MouseInCurrentCanvas = false;\n\n        internal string lastAppliedPresetName => m_LastAppliedPresetName;\n        List<Overlay> m_Overlays = new List<Overlay>();\n        List<Overlay> m_TransientOverlays = new();\n\n        internal static string k_DefaultPresetName = \"Default\";\n        [SerializeField]\n        string m_LastAppliedPresetName = k_DefaultPresetName;\n\n        [SerializeField]\n        List<SaveData> m_SaveData = new List<SaveData>();\n\n        [SerializeField]\n        List<ContainerData> m_ContainerData = new List<ContainerData>();\n\n        [SerializeField]\n        bool m_OverlaysVisible = true;\n        \n        bool m_OverlaysSupportEnabled = true;\n\n        VisualElement m_RootVisualElement;\n        internal EditorWindow containerWindow { get; set; }\n\n        internal FloatingOverlayContainer floatingContainer => m_FloatingOverlayContainer ??= new FloatingOverlayContainer {canvas = this};\n\n        FloatingOverlayContainer m_FloatingOverlayContainer;\n        Overlay m_HoveredOverlay;\n\n        internal VisualElement rootVisualElement => m_RootVisualElement ??= CreateRoot();\n\n        internal Overlay hoveredOverlay => m_HoveredOverlay;\n        OverlayContainer hoveredOverlayContainer { get; set; }\n        OverlayContainer defaultContainer { get; set; }\n        OverlayContainer defaultToolbarContainer { get; set; }\n\n        internal OverlayDockArea dockArea { get; private set; }\n\n        List<OverlayContainer> m_Containers;\n\n        internal IEnumerable<OverlayContainer> containers => m_Containers;\n\n        readonly Dictionary<VisualElement, Overlay> m_OverlaysByVE = new Dictionary<VisualElement, Overlay>();\n\n        public IEnumerable<Overlay> overlays => m_Overlays.AsReadOnly();\n\n        internal IEnumerable<Overlay> transientOverlays => m_TransientOverlays;\n\n        OverlayPopup m_PopupOverlay;\n\n        VisualElement m_WindowRoot;\n        internal VisualElement windowRoot => m_WindowRoot;\n\n        internal Action afterOverlaysInitialized;\n        internal event Action<bool> overlaysEnabledChanged;\n        internal event Action<bool> overlaysSupportEnabledChanged;\n        internal event Action presetChanged;\n\n\n        internal event Action overlayListChanged;\n\n        public bool overlaysEnabled\n        {\n            get => m_Containers != null && m_OverlaysVisible;\n\n            set\n            {\n                var changed = m_OverlaysVisible != value;\n                if (changed)\n                    m_OverlaysVisible = value;\n\n                // Ensure the containers' state refreshes in case m_OverlaysVisible value is somehow desynced from container state\n                var allContainersMatchEnabledState = true;\n                foreach (var container in m_Containers)\n                {\n                    if (container.style.display != (value ? DisplayStyle.Flex : DisplayStyle.None))\n                    {\n                        allContainersMatchEnabledState = false;\n                        break;\n                    }\n                }\n                if (!allContainersMatchEnabledState)\n                {\n                    foreach (var container in m_Containers)\n                        container.style.display = value ? DisplayStyle.Flex : DisplayStyle.None;\n                }\n\n                if (changed)\n                    overlaysEnabledChanged?.Invoke(m_OverlaysVisible);\n            }\n        }\n\n        internal bool overlaysSupportEnabled\n        {\n            get => m_OverlaysSupportEnabled;\n\n            set\n            {\n                if (value != m_OverlaysSupportEnabled)\n                {\n                    m_OverlaysSupportEnabled = value;\n\n                    if (!m_OverlaysSupportEnabled)\n                    {\n                        // Ensure no lingering popup is left open\n                        ClosePopupOverlay();\n                        // Hide all overlay containers\n                        foreach (var container in m_Containers)\n                            container.style.display = DisplayStyle.None;\n                    }\n                    // Unhide overlay containers if they're enabled when reactivating support\n                    else if (overlaysEnabled)\n                    {\n                        foreach (var container in m_Containers)\n                            container.style.display = DisplayStyle.Flex;\n                    }\n\n                    overlaysSupportEnabledChanged?.Invoke(value);\n                }\n            }\n        }\n\n        internal OverlayCanvas() { }\n\n        VisualElement CreateRoot()\n        {\n            var ve = new VisualElement();\n\n            ve.AddToClassList(ussClassName);\n\n            StyleSheet sheet;\n            sheet = EditorGUIUtility.Load(k_StyleCommon) as StyleSheet;\n            ve.styleSheets.Add(sheet);\n\n            if (EditorGUIUtility.isProSkin)\n                sheet = EditorGUIUtility.Load(k_StyleDark) as StyleSheet;\n            else\n                sheet = EditorGUIUtility.Load(k_StyleLight) as StyleSheet;\n\n            ve.styleSheets.Add(sheet);\n\n            if (s_TreeAsset == null)\n                s_TreeAsset = EditorGUIUtility.Load(k_UxmlPath) as VisualTreeAsset;\n\n            if (s_TreeAsset != null)\n                s_TreeAsset.CloneTree(ve);\n\n            if (s_DropZoneTreeAsset == null)\n                s_DropZoneTreeAsset = EditorGUIUtility.Load(k_UxmlPathDropZone) as VisualTreeAsset;\n\n            ve.name = ussClassName;\n            ve.style.flexGrow = 1;\n\n            ve.Add(floatingContainer);\n            floatingContainer.AddToClassList(k_FloatingContainer);\n            floatingContainer.name = \"Floating\";\n\n            m_Containers = ve.Query<OverlayContainer>().ToList();\n\n            foreach (var container in m_Containers)\n            {\n                container.RegisterCallback<MouseEnterEvent>(OnMouseEnterOverlayContainer);\n                if (container.ClassListContains(k_DefaultContainer))\n                {\n                    if (container.ClassListContains(k_ToolbarArea))\n                        defaultToolbarContainer = container;\n                    else\n                        defaultContainer = container;\n                }\n\n                var data = GetContainerData(container.name);\n                if (container is ToolbarOverlayContainer toolbar)\n                    toolbar.scrollOffset = data.scrollOffset;\n            }\n\n            SetPickingMode(ve, PickingMode.Ignore);\n\n            ve.RegisterCallback<AttachToPanelEvent>(OnAttachedToPanel);\n            ve.RegisterCallback<DetachFromPanelEvent>(OnDetachedFromPanel);\n\n            m_WindowRoot = ve.Q(\"overlay-window-root\");\n\n            ve.Add(dockArea = new OverlayDockArea(this));\n            m_WindowRoot.RegisterCallback<GeometryChangedEvent>((evt) =>\n            {\n                var worldPos = m_WindowRoot.LocalToWorld(evt.newRect.position);\n#pragma warning disable CS0618 // Type or member is obsolete\n                dockArea.transform.position = ve.WorldToLocal(worldPos);\n#pragma warning restore CS0618 // Type or member is obsolete\n                dockArea.style.width = evt.newRect.width;\n                dockArea.style.height = evt.newRect.height;\n            });\n\n            overlaysEnabled = m_OverlaysVisible;\n\n            return ve;\n        }\n\n        void SetPickingMode(VisualElement element, PickingMode mode)\n        {\n            element.pickingMode = mode;\n            foreach (var child in element.Children())\n                SetPickingMode(child, mode);\n        }\n\n        void OnMouseEnterOverlayContainer(MouseEnterEvent evt)\n        {\n            var overlayContainer = evt.target as OverlayContainer;\n            hoveredOverlayContainer = overlayContainer;\n        }\n\n        void OnAttachedToPanel(AttachToPanelEvent evt)\n        {\n            //this is used to clamp overlays to floating container bounds.\n            floatingContainer.RegisterCallback<GeometryChangedEvent>(GeometryChanged);\n            rootVisualElement.RegisterCallback<MouseEnterEvent>(OnMouseEnter);\n            rootVisualElement.RegisterCallback<MouseLeaveEvent>(OnMouseLeave);\n            EditorWindow.windowFocusChanged += OnFocusedWindowChanged;\n\n        }\n\n        void OnDetachedFromPanel(DetachFromPanelEvent evt)\n        {\n            floatingContainer.UnregisterCallback<GeometryChangedEvent>(GeometryChanged);\n            rootVisualElement.UnregisterCallback<MouseEnterEvent>(OnMouseEnter);\n            rootVisualElement.UnregisterCallback<MouseLeaveEvent>(OnMouseLeave);\n            EditorWindow.windowFocusChanged -= OnFocusedWindowChanged;\n        }\n\n        internal void OnContainerWindowDisabled()\n        {\n            if (containerWindow != null)\n            {\n                var overlayCanvasesData = OverlayCanvasesData.instance;\n                var containerTypeWindows = Resources.FindObjectsOfTypeAll(containerWindow.GetType());\n                // This closing container is last instance of its type\n                if (containerTypeWindows.Length <= 1)\n                {\n                    // Ensures m_SaveData is refreshed.\n                    OnBeforeSerialize();\n                    overlayCanvasesData.AddAndSaveCanvasData(containerWindow, m_SaveData);\n                }\n            }\n            \n            foreach (var overlay in m_Overlays)\n                overlay.OnWillBeDestroyed();\n        }\n\n        void OnFocusedWindowChanged()\n        {\n            if (EditorWindow.focusedWindow == containerWindow)\n                OverlayCanvasesData.instance.SetLastActiveCanvasForWindowType(this);\n        }\n\n        void OnMouseEnter(MouseEnterEvent evt)\n        {\n            m_MouseInCurrentCanvas = true;\n        }\n\n        void OnMouseLeave(MouseLeaveEvent evt)\n        {\n            m_MouseInCurrentCanvas = false;\n        }\n\n        Rect GetBoundaryRect()\n        {\n            var rect = rootVisualElement.localBound;\n            rect.xMin += k_OverlayMinVisibleArea;\n            rect.yMin += k_OverlayMinVisibleArea;\n            rect.xMax -= k_OverlayMinVisibleArea;\n            rect.yMax -= k_OverlayMinVisibleArea;\n            return rect;\n        }\n\n        // This ensures that the rect is at least partly contained within the boundary. Use ClampRectToRect if the rect needs to be fully within.\n        internal Rect EnsureOverlapsWindow(Rect rect)\n        {\n            return OverlayUtilities.EnsureRectOverlapsRect(rect, GetBoundaryRect());\n        }\n\n        // This ensure the given rect is fully within the window (unless the window is smaller then the rect)\n        internal Rect ClampToWindow(Rect rect)\n        {\n            return OverlayUtilities.ClampRectToRect(rect, GetBoundaryRect());\n        }\n\n        // clamp all overlays to  root visual element's new bounds\n        void GeometryChanged(GeometryChangedEvent evt)\n        {\n            if (!overlaysEnabled || !overlaysSupportEnabled)\n                return;\n\n            foreach (var overlay in m_Overlays)\n            {\n                if (overlay == null)\n                    continue;\n\n                using (new Overlay.LockedAnchor(overlay))\n                    overlay.floatingPosition = overlay.floatingPosition; //force an update of the floating position\n\n                overlay.UpdateAbsolutePosition();\n\n                //Register the geometrychanged callback to the overlay if it was not registered before,\n                //this is not doing anything if it has already been registered\n                overlay.rootVisualElement.RegisterCallback<GeometryChangedEvent>(overlay.OnGeometryChanged);\n            }\n        }\n\n        void OnMouseLeaveOverlay(MouseLeaveEvent evt)\n        {\n            m_HoveredOverlay = null;\n        }\n\n        void OnMouseEnterOverlay(MouseEnterEvent evt)\n        {\n            var overlay = evt.target as VisualElement;\n            if (overlay != null && overlay.ClassListContains(Overlay.ussClassName))\n                m_HoveredOverlay = m_OverlaysByVE[overlay];\n        }\n\n        internal void HideHoveredOverlay()\n        {\n            if (hoveredOverlay != null && hoveredOverlay.userControlledVisibility)\n                hoveredOverlay.displayed = false;\n        }\n\n        internal bool HasTransientOverlays()\n        {\n            return m_TransientOverlays.Count > 0;\n        }\n\n        internal bool IsTransient(Overlay overlay) => m_TransientOverlays.Contains(overlay);\n\n        internal Func<OverlayUtilities.OverlayEditorWindowAssociation, bool> filterOverlays;\n\n        internal void Initialize(EditorWindow window)\n        {\n            Profiler.BeginSample(\"OverlayCanvas.Initialize\");\n            containerWindow = window;\n\n            AssemblyReloadEvents.beforeAssemblyReload += OnBeforeAssemblyReload;\n\n            List<Type> overlayTypes = OverlayUtilities.GetOverlaysForType(window.GetType(), filterOverlays);\n\n            // init all overlays\n            foreach (var overlayType in overlayTypes)\n                AddOverlay(OverlayUtilities.CreateOverlay(overlayType));\n            \n            // No save data deserialized from layout or this is a new instance\n            if (m_SaveData == null || m_SaveData.Count < 1)\n            {\n                var containerTypeWindows = Resources.FindObjectsOfTypeAll(containerWindow.GetType());\n                var overlayCanvasesData = OverlayCanvasesData.instance;\n                \n                // If our container is not the first instance of its type (i.e. container window is duplicate),\n                // we want to \"inherit\" overlay save data from the last focused overlay canvas.\n                if (containerTypeWindows.Length > 1 && overlayCanvasesData.TryGetLastActiveCanvasForWindowType(containerWindow, out var lastActiveCanvas))\n                {\n                    lastActiveCanvas.CopySaveData(out var lastActiveCanvasData);\n                    m_SaveData = new List<SaveData>(lastActiveCanvasData);\n                }\n                // Otherwise check if SaveData's been serialized in OverlayCanvasesData asset during last window close of container type.\n                else if (!overlayCanvasesData.GetCanvasSaveData(containerWindow, out m_SaveData))\n                {\n                    var preset = OverlayPresetManager.GetDefaultPreset(window.GetType());\n                    if (preset != null && preset.saveData != null)\n                        m_SaveData = new List<SaveData>(preset.saveData);\n                }\n            }\n\n            // If save data is still null at this point, initialize it to empty list as code down the line is not expecting it to be null\n            if (m_SaveData == null)\n                m_SaveData = new List<SaveData>();\n\n            RestoreOverlays();\n            Profiler.EndSample();\n        }\n\n        void OnBeforeAssemblyReload()\n        {\n            AssemblyReloadEvents.beforeAssemblyReload -= OnBeforeAssemblyReload;\n            foreach (var overlay in m_Overlays)\n                overlay.rootVisualElement.UnregisterCallback<GeometryChangedEvent>(overlay.OnGeometryChanged);\n        }\n\n        void WriteOrReplaceSaveData(Overlay overlay, int containerIndex = -1)\n        {\n            var saveData = new SaveData(overlay, containerIndex);\n            int existing = m_SaveData.FindIndex(x => x.id == overlay.id);\n\n            if (existing < 0)\n                m_SaveData.Add(saveData);\n            else\n                m_SaveData[existing] = saveData;\n        }\n\n        public void OnBeforeSerialize()\n        {\n            if (m_Containers == null)\n                return;\n\n            foreach (var container in m_Containers)\n            {\n                if (container != null)\n                {\n                    var before = container.GetSection(OverlayContainerSection.BeforeSpacer);\n                    var after = container.GetSection(OverlayContainerSection.AfterSpacer);\n\n                    for (int i = 0, c = before.Count; i < c; ++i)\n                    {\n                        if (!before[i].dontSaveInLayout)\n                            WriteOrReplaceSaveData(before[i], i);\n                    }\n\n                    for (int i = 0, c = after.Count; i < c; ++i)\n                    {\n                        if (!after[i].dontSaveInLayout)\n                            WriteOrReplaceSaveData(after[i], i);\n                    }\n\n                    var data = GetContainerData(container.name);\n                    if (container is ToolbarOverlayContainer toolbar)\n                        data.scrollOffset = toolbar.scrollOffset;\n                }\n            }\n        }\n\n        public void OnAfterDeserialize() {}\n\n        // used by tests\n        internal void CopySaveData(out SaveData[] saveData)\n        {\n            // Force a save of the current data\n            OnBeforeSerialize();\n            saveData = m_SaveData.ToArray();\n            for (int i = 0; i < saveData.Length; ++i)\n                saveData[i] = new SaveData(saveData[i]);\n        }\n\n        internal void SetLastAppliedPresetName(string name)\n        {\n            m_LastAppliedPresetName = name;\n        }\n\n        internal void ApplyPreset(IOverlayPreset preset)\n        {\n            if (!preset.CanApplyToWindow(containerWindow.GetType()))\n            {\n                Debug.LogError($\"Cannot apply preset for type {preset.targetWindowType} to canvas of type \" +\n                    $\"{containerWindow.GetType()}\");\n                return;\n            }\n\n            SetLastAppliedPresetName(preset.name);\n            ApplySaveData(preset.saveData);\n            preset.ApplyCustomData(this);\n            presetChanged?.Invoke();\n        }\n\n        internal void ApplySaveData(SaveData[] saveData)\n        {\n            m_SaveData = new List<SaveData>(saveData);\n            RestoreOverlays();\n        }\n\n        internal void Move(Overlay overlay, DockZone zone, DockPosition position = DockPosition.Bottom)\n        {\n            var container = GetDockZoneContainer(zone);\n            if (position == DockPosition.Bottom)\n                overlay.DockAt(container, OverlayContainerSection.AfterSpacer);\n            else\n                overlay.DockAt(container, OverlayContainerSection.BeforeSpacer);\n        }\n\n        internal void Rebuild()\n        {\n            OnBeforeSerialize();\n            RestoreOverlays();\n        }\n\n        // Overlays added to the canvas through this method are considered \"temporary\" and will be shown in separate\n        // category in the menu. Persistent overlays (i.e., overlays registered through OverlayAttribute) are not\n        // created using this method.\n        public void Add(Overlay overlay)\n        {\n            if(m_Overlays.Contains(overlay))\n                return;\n            overlay.canvas?.Remove(overlay);\n            AddOverlay(overlay, true);\n            RestoreOverlay(overlay);\n        }\n\n        public bool Remove(Overlay overlay)\n        {\n            if (!m_Overlays.Remove(overlay))\n                return false;\n            m_TransientOverlays.Remove(overlay);\n            overlay.OnWillBeDestroyed();\n            WriteOrReplaceSaveData(overlay);\n            overlay.container?.RemoveOverlay(overlay);\n            overlay.canvas = null;\n            var root = overlay.rootVisualElement;\n            m_OverlaysByVE.Remove(root);\n            root.UnregisterCallback<MouseEnterEvent>(OnMouseEnterOverlay);\n            root.UnregisterCallback<MouseLeaveEvent>(OnMouseLeaveOverlay);\n            root.RemoveFromHierarchy();\n            overlayListChanged?.Invoke();\n            return true;\n        }\n\n        public void ShowPopup<T>() where T : Overlay, new()\n        {\n            if (ClosePopupOverlay() || !overlaysSupportEnabled)\n                return;\n\n            var popup = OverlayPopup.CreateAtCanvasCenter(this, CreateOverlayForPopup<T>());\n            SetActiveOverlayPopup(popup);\n        }\n\n        public void ShowPopupAtMouse<T>() where T : Overlay, new()\n        {\n            if (!m_MouseInCurrentCanvas)\n            {\n                ClosePopupOverlay();\n                return;\n            }\n\n            if (!overlaysSupportEnabled)\n                return;\n\n            ShowPopup<T>(PointerDeviceState.GetPointerPosition(PointerId.mousePointerId, ContextType.Editor));\n        }\n\n        public void ShowPopup<T>(Vector2 position) where T : Overlay, new()\n        {\n            if (ClosePopupOverlay() || !overlaysSupportEnabled)\n                return;\n\n            var popup = OverlayPopup.CreateAtPosition(this, CreateOverlayForPopup<T>(), position);\n            SetActiveOverlayPopup(popup);\n        }\n\n        T CreateOverlayForPopup<T>() where T : Overlay, new()\n        {\n            var overlay = new T();\n            var overlayName = OverlayUtilities.GetDisplayNameFromAttribute(typeof(T));\n            if (overlayName == string.Empty)\n                overlayName = ObjectNames.NicifyVariableName(typeof(T).Name);\n\n            // OnCreated must be invoked before contents are requested for the first time\n            overlay.canvas = this;\n            overlay.isPopup = true;\n            overlay.OnCreated();\n            overlay.displayed = false;\n            overlay.displayName = overlayName;\n\n            return overlay;\n        }\n\n        void SetActiveOverlayPopup(OverlayPopup popup)\n        {\n            m_PopupOverlay = popup;\n            m_PopupOverlay.RegisterCallback<FocusOutEvent>(evt =>\n            {\n                if (evt.relatedTarget is VisualElement target && (m_PopupOverlay == target || m_PopupOverlay.Contains(target)))\n                    return;\n\n                // When the new focus is an embedded IMGUIContainer or popup window, give focus back to the modal\n                // popup so that the next focus out event has the opportunity to close the element.\n                if (evt.relatedTarget == null && m_PopupOverlay.containsCursor)\n                    EditorApplication.delayCall += m_PopupOverlay.Focus;\n                else\n                    ClosePopupOverlay();\n            });\n\n            rootVisualElement.Add(m_PopupOverlay);\n            m_PopupOverlay.Focus();\n        }\n\n        internal bool ClosePopupOverlay()\n        {\n            if (m_PopupOverlay == null)\n                return false;\n\n            m_PopupOverlay.overlay.OnWillBeDestroyed();\n            m_PopupOverlay.RemoveFromHierarchy();\n            m_PopupOverlay = null;\n            return true;\n        }\n\n        // AddOverlay just registers the Overlay with Canvas. It does not init save data or add to a valid container.\n        void AddOverlay(Overlay overlay, bool transient = false)\n        {\n            // Don't show an error when attempting to add a null overlay. This means that a persistent Overlay type was\n            // removed from a project, or moved to a transient overlay. In either case, the user can't do anything\n            // meaningful with this information.\n            if (overlay == null)\n                return;\n\n            if(!OverlayUtilities.EnsureValidId(m_Overlays, overlay))\n            {\n                Debug.LogError($\"An overlay with id \\\"{overlay.id}\\\" was already registered to window \" +\n                    $\"({containerWindow.titleContent.text}).\");\n                return;\n            }\n\n            overlay.canvas = this;\n            m_Overlays.Add(overlay);\n            if (transient)\n                m_TransientOverlays.Add(overlay);\n            m_OverlaysByVE[overlay.rootVisualElement] = overlay;\n            overlay.rootVisualElement.RegisterCallback<MouseEnterEvent>(OnMouseEnterOverlay);\n            overlay.rootVisualElement.RegisterCallback<MouseLeaveEvent>(OnMouseLeaveOverlay);\n\n\n            // OnCreated must be invoked before contents are requested for the first time\n            overlay.OnCreated();\n\n            overlayListChanged?.Invoke();\n        }\n\n        internal bool TryGetOverlay(string id, out Overlay overlay)\n        {\n            overlay = m_Overlays.FirstOrDefault(x => x.id == id);\n            return overlay != null;\n        }\n\n        internal bool TryGetOverlay<T>(string id, out T overlay) where T : Overlay\n        {\n            overlay = m_Overlays.FirstOrDefault(x => x is T && x.id == id) as T;\n            return overlay != null;\n        }\n\n        // GetOrCreateOverlay is used to instantiate Overlays. Do not use this method when deserializing and batch\n        // constructing Overlays, instead use AddOverlay/RestoreOverlays.\n        internal T GetOrCreateOverlay<T>(string id = null) where T : Overlay, new()\n        {\n            var attrib = OverlayUtilities.GetAttribute(containerWindow.GetType(), typeof(T));\n\n            if (string.IsNullOrEmpty(id))\n                id = attrib.id;\n\n            if(TryGetOverlay(id, out T overlay))\n                return overlay;\n\n            overlay = new T();\n            overlay.Initialize(id, attrib.ussName, attrib.displayName, attrib.defaultSize, attrib.minSize, attrib.maxSize);\n\n            if (overlay is LegacyOverlay legacy)\n                legacy.dontSaveInLayout = true;\n\n            AddOverlay(overlay);\n            RestoreOverlay(overlay);\n\n            return overlay;\n        }\n\n        // used by tests\n        internal SaveData FindSaveData(Overlay overlay)\n        {\n            var data = m_SaveData.FirstOrDefault(x => x.id == overlay.id);\n\n            if (data == null)\n            {\n                data = defaultSaveData;\n\n                var attrib = overlay.GetType().GetCustomAttribute<OverlayAttribute>();\n\n                if (attrib != null)\n                {\n                    data.containerId = k_DockZoneContainerIDs[(int)attrib.defaultDockZone];\n                    data.index = attrib.defaultDockIndex;\n                    data.dockPosition = attrib.defaultDockPosition;\n                    data.displayed = attrib.defaultDisplay;\n                    overlay.layout = attrib.defaultLayout;\n\n                    // also apply to obsolete SaveData fields for backwards compatibility (ie, there is no\n                    // SaveData.contents but we still want layout and size attribute values to be forwarded)\n#pragma warning disable 612\n                    data.layout = attrib.defaultLayout;\n                    data.floating = attrib.defaultDockZone == DockZone.Floating;\n#pragma warning restore 612\n                }\n            }\n\n            return data;\n        }\n\n        public void ResetOverlay(Overlay overlay)\n        {\n            overlay.sizeOverridden = false;\n\n            var attrib = overlay.GetType().GetCustomAttribute<OverlayAttribute>();\n            overlay.Reset(attrib);\n\n            var container = GetDockZoneContainer(attrib.defaultDockZone);\n\n            if (attrib.defaultDockPosition == DockPosition.Top)\n            {\n                var index = Mathf.Min(attrib.defaultDockIndex, container.GetSectionCount(OverlayContainerSection.BeforeSpacer) - (container.ContainsOverlay(overlay, OverlayContainerSection.BeforeSpacer) ? 1 : 0));\n\n                overlay.DockAt(container, OverlayContainerSection.BeforeSpacer, index);\n            }\n            else if (attrib.defaultDockPosition == DockPosition.Bottom)\n            {\n                var index = Mathf.Min(attrib.defaultDockIndex, container.GetSectionCount(OverlayContainerSection.AfterSpacer) - (container.ContainsOverlay(overlay, OverlayContainerSection.AfterSpacer) ? 1 : 0));\n                overlay.DockAt(container, OverlayContainerSection.AfterSpacer, index);\n            }\n            else\n                throw new Exception(\"data.dockPosition is not Top or Bottom, did someone add a new one?\");\n\n            if(overlay.floating)\n                overlay.Undock();\n\n            if (overlay.displayed != attrib.defaultDisplay)\n            {\n                // start from \"not shown\" state so that Overlay.displayedChanged is called\n                overlay.rootVisualElement.style.display = DisplayStyle.None;\n                overlay.displayed = attrib.defaultDisplay;\n            }\n            else\n                overlay.RebuildContent();\n\n            overlay.UpdateAbsolutePosition();\n        }\n\n        public void RestoreOverlay(Overlay overlay, SaveData data = null)\n        {\n            if(data == null)\n                data = FindSaveData(overlay);\n\n            try\n            {\n                EditorJsonUtility.FromJsonOverwrite(data.contents, overlay);\n            }\n            catch (ArgumentException)\n            {\n                data.contents = string.Empty;\n            }\n\n            #pragma warning disable 618\n            if(string.IsNullOrEmpty(data.contents))\n                overlay.ApplySaveData(data);\n            #pragma warning restore 618\n\n            var container = m_Containers.FirstOrDefault(x => data.containerId == x.name);\n\n            // Overlays were implemented with the idea that they are always associated with an OverlayContainer. While\n            // this doesn't really need to be true (floating Overlays don't need a Container), the code isn't capable\n            // of handling that case. So if a valid container can't be found from the serialized data, we just add it\n            // to a default container.\n            if(container == null)\n                container = overlay is ToolbarOverlay ? defaultToolbarContainer : defaultContainer;\n\n\n\n            // Overlays are sorted by their index in containers so we can directly add them to top or bottom without\n            // thinking of order\n            if (data.dockPosition == DockPosition.Top || container is FloatingOverlayContainer)\n                overlay.DockAt(container, OverlayContainerSection.BeforeSpacer);\n            else if (data.dockPosition == DockPosition.Bottom)\n                overlay.DockAt(container, OverlayContainerSection.AfterSpacer);\n            else\n                throw new Exception(\"data.dockPosition is not Top or Bottom, did someone add a new one?\");\n\n            if(overlay.floating)\n                overlay.Undock();\n\n            // when restoring an overlay from serialized state, always start from \"not shown\" state so that\n            // Overlay.displayedChanged is called\n            overlay.rootVisualElement.style.display = DisplayStyle.None;\n\n            if(overlay.displayed != data.displayed)\n                overlay.displayed = data.displayed;\n            else\n                overlay.RebuildContent();\n\n            overlay.UpdateAbsolutePosition();\n        }\n\n        void RestoreOverlays()\n        {\n            if (m_Containers == null)\n                return;\n\n            // Clear OverlayContainer instances and set Overlay.displayed to false. RestoreOverlay expects that Overlay\n            // is not present in VisualElement hierarchy.\n            foreach (var overlay in this.overlays)\n            {\n                overlay.displayed = false;\n                overlay.container?.RemoveOverlay(overlay);\n            }\n\n            // Three steps to reinitialize a canvas:\n            // 1. Find and associate all Overlays with SaveData (using default SaveData if necessary)\n            // 2. Sort in ascending order by SaveData.index\n            // 3. Apply SaveData, insert Overlay in Container\n            var overlays = new List<Tuple<SaveData, Overlay>>();\n\n            foreach(var o in this.overlays)\n                overlays.Add(new Tuple<SaveData, Overlay>(FindSaveData(o), o));\n\n            var ordered = overlays.OrderBy(x => x.Item1.index);\n            foreach (var o in ordered)\n                RestoreOverlay(o.Item2, o.Item1);\n\n            afterOverlaysInitialized?.Invoke();\n        }\n\n        ContainerData GetContainerData(string containerId)\n        {\n            foreach (var data in m_ContainerData)\n                if (data.containerId == containerId)\n                    return data;\n\n            var newData = new ContainerData\n            {\n                containerId = containerId,\n                scrollOffset = 0\n            };\n\n            m_ContainerData.Add(newData);\n            return newData;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayCanvasesData.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor.Overlays\n{\n    [FilePath(\"Overlays/CanvasesSaveData.asset\", FilePathAttribute.Location.PreferencesFolder)]\n    class OverlayCanvasesData : ScriptableSingleton<OverlayCanvasesData>, ISerializationCallbackReceiver\n    {\n        [Serializable]\n        struct WindowToCanvasDataPair\n        {\n            public WindowToCanvasDataPair(string windowType, List<SaveData> canvasSaveData)\n            {\n                m_WindowType = windowType;\n                m_CanvasSaveData = canvasSaveData;\n            }\n\n            public string m_WindowType;\n            public List<SaveData> m_CanvasSaveData = new();\n        }\n        \n        [SerializeField]\n        List<WindowToCanvasDataPair> m_CanvasesSaveData = new();\n        Dictionary<string, List<SaveData>> m_WindowToCanvasSaveData = new();\n        \n        [Serializable]\n        struct WindowToCanvasPair\n        {\n            public WindowToCanvasPair(string windowType, OverlayCanvas canvas)\n            {\n                m_WindowType = windowType;\n                m_Canvas = canvas;\n            }\n\n            public string m_WindowType;\n            public OverlayCanvas m_Canvas;\n        }\n        \n        // [SerializeField] for the list below is intentionally omitted.\n        // Since List is serializable, it will survive domain reload as a ScriptableSingleton field but not serialize to asset.\n        // This allows to track last active canvas throughout a session and NOT have this data restored on next session.\n        List<WindowToCanvasPair> m_WindowToLastActiveCanvasList = new();\n        \n        Dictionary<string, OverlayCanvas> m_WindowToLastActiveCanvasMap = new();\n\n        public void OnBeforeSerialize()\n        {\n            // Output window to canvas SaveData map to a list\n            if (m_CanvasesSaveData == null)\n                m_CanvasesSaveData = new();\n            else \n                m_CanvasesSaveData.Clear();\n\n            foreach (var dataPair in m_WindowToCanvasSaveData)\n                m_CanvasesSaveData.Add(new WindowToCanvasDataPair(dataPair.Key, dataPair.Value));\n            \n            // Output window to last active canvas map to a list\n            if (m_WindowToLastActiveCanvasList == null)\n                m_WindowToLastActiveCanvasList = new();\n            else \n                m_WindowToLastActiveCanvasList.Clear();\n            \n            foreach (var dataPair in m_WindowToLastActiveCanvasMap)\n                m_WindowToLastActiveCanvasList.Add(new WindowToCanvasPair(dataPair.Key, dataPair.Value));\n        }\n        \n        public void OnAfterDeserialize()\n        {\n            // Restore window to canvas save datas map\n            if (m_WindowToCanvasSaveData == null)\n                m_WindowToCanvasSaveData = new();\n            else \n                m_WindowToCanvasSaveData.Clear();\n\n            if (m_CanvasesSaveData == null)\n            {\n                m_CanvasesSaveData = new();\n                return;\n            }\n\n            for (int i = 0; i < m_CanvasesSaveData.Count; ++i)\n            {\n                var dataPair = m_CanvasesSaveData[i];\n                m_WindowToCanvasSaveData.Add(dataPair.m_WindowType, dataPair.m_CanvasSaveData);\n            }\n            \n            // Restore window to last active canvas map\n            if (m_WindowToLastActiveCanvasMap == null)\n                m_WindowToLastActiveCanvasMap = new();\n            else \n                m_WindowToLastActiveCanvasMap.Clear();\n\n            if (m_WindowToLastActiveCanvasList == null)\n            {\n                m_WindowToLastActiveCanvasList = new();\n                return;\n            }\n            \n            for (int i = 0; i < m_WindowToLastActiveCanvasList.Count; ++i)\n            {\n                var dataPair = m_WindowToLastActiveCanvasList[i];\n                m_WindowToLastActiveCanvasMap.Add(dataPair.m_WindowType, dataPair.m_Canvas);\n            }\n        }\n        \n        void OnDisable()\n        {\n            Save();\n        }\n\n        public void AddAndSaveCanvasData(EditorWindow containerWindow, List<SaveData> canvasSaveData)\n        {\n            var windowType = containerWindow.GetType().AssemblyQualifiedName;\n            if (!m_WindowToCanvasSaveData.TryAdd(windowType, canvasSaveData))\n                m_WindowToCanvasSaveData[windowType] = canvasSaveData;\n\n            Save();\n        }\n\n        public bool GetCanvasSaveData(EditorWindow containerWindow, out List<SaveData> canvasSaveData)\n        {\n            if (m_WindowToCanvasSaveData.TryGetValue(containerWindow.GetType().AssemblyQualifiedName, out canvasSaveData) &&\n                canvasSaveData != null)\n                return true;\n\n            return false;\n        }\n        \n        void Save()\n        {\n            Save(true);\n        }\n\n        public bool TryGetLastActiveCanvasForWindowType(EditorWindow window, out OverlayCanvas lastActiveCanvas)\n        {\n            return m_WindowToLastActiveCanvasMap.TryGetValue(window.GetType().AssemblyQualifiedName, out lastActiveCanvas);\n        }\n\n        public void SetLastActiveCanvasForWindowType(OverlayCanvas canvas)\n        {\n            var windowType = canvas.containerWindow.GetType().AssemblyQualifiedName;\n            if (!m_WindowToLastActiveCanvasMap.TryAdd(windowType, canvas))\n                m_WindowToLastActiveCanvasMap[windowType] = canvas;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayContainer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Collections.ObjectModel;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    enum OverlayContainerSection\n    {\n        BeforeSpacer,\n        AfterSpacer\n    }\n\n    class OverlayContainer : VisualElement\n    {\n        [Serializable]\n        public new class UxmlSerializedData : VisualElement.UxmlSerializedData\n        {\n            [RegisterUxmlCache]\n            [Conditional(\"UNITY_EDITOR\")]\n            public new static void Register()\n            {\n                UxmlDescriptionCache.RegisterType(typeof(UxmlSerializedData), new UxmlAttributeNames[]\n                {\n                    new(nameof(horizontal), \"horizontal\"),\n                    new(nameof(supportedOverlayLayout), \"supported-overlay-layout\"),\n                });\n            }\n\n            #pragma warning disable 649\n            [SerializeField] bool horizontal;\n            [SerializeField, UxmlIgnore, HideInInspector] UxmlAttributeFlags horizontal_UxmlAttributeFlags;\n            [SerializeField] string supportedOverlayLayout;\n            [SerializeField, UxmlIgnore, HideInInspector] UxmlAttributeFlags supportedOverlayLayout_UxmlAttributeFlags;\n            #pragma warning restore 649\n\n            public override object CreateInstance() => new OverlayContainer();\n\n            public override void Deserialize(object obj)\n            {\n                base.Deserialize(obj);\n\n                var e = (OverlayContainer)obj;\n                if (ShouldWriteAttributeValue(horizontal_UxmlAttributeFlags))\n                    e.isHorizontal = horizontal;\n\n                e.m_SupportedOverlayLayouts = Layout.Panel;\n                if (ShouldWriteAttributeValue(supportedOverlayLayout_UxmlAttributeFlags))\n                {\n                    var split = supportedOverlayLayout?.Split(' ');\n                    if (split?.Length > 0)\n                    {\n                        foreach (var layout in split)\n                        {\n                            switch (layout.ToLower())\n                            {\n                                case \"horizontal\":\n                                    e.m_SupportedOverlayLayouts |= Layout.HorizontalToolbar;\n                                    break;\n\n                                case \"vertical\":\n                                    e.m_SupportedOverlayLayouts |= Layout.VerticalToolbar;\n                                    break;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        public const string className = \"unity-overlay-container\";\n        const string k_HorizontalClassName = className + \"-horizontal\";\n        const string k_VerticalClassName = className + \"-vertical\";\n        const string k_ContentClassName = className + \"__content\";\n        const string k_BeforeClassName = className + \"__before-spacer-container\";\n        const string k_AfterClassName = className + \"__after-spacer-container\";\n        const string k_SpacingContainerClassName = className + \"__spacing-container\";\n        public static readonly Overlay spacerMarker = null;\n\n        readonly List<Overlay> m_BeforeOverlays = new List<Overlay>();\n        readonly List<Overlay> m_AfterOverlays = new List<Overlay>();\n        readonly VisualElement m_BeforeSectionContent;\n        readonly VisualElement m_AfterSectionContent;\n\n        // This is set by querying the stylesheet for 'vertical' and 'horizontal'\n        Layout m_SupportedOverlayLayouts = 0; //Used as a flag in this case\n        bool m_IsHorizontal;\n\n        public OverlayCanvas canvas { get; internal set; }\n\n        protected readonly VisualElement beforeSectionContainer;\n        protected readonly VisualElement afterSectionContainer;\n\n        public int overlayCount => m_BeforeOverlays.Count + m_AfterOverlays.Count;\n        public virtual Layout preferredLayout => Layout.Panel;\n\n        public bool isHorizontal\n        {\n            get => m_IsHorizontal;\n            set\n            {\n                if (m_IsHorizontal == value)\n                    return;\n\n                m_IsHorizontal = value;\n                if (m_IsHorizontal)\n                    SetHorizontal();\n                else\n                    SetVertical();\n            }\n        }\n\n        public float spacerSize => isHorizontal\n                ? layout.width - (beforeSectionContainer.layout.width + afterSectionContainer.layout.width)\n                : layout.height - (beforeSectionContainer.layout.height + afterSectionContainer.layout.height);\n\n        public bool isSpacerVisible => !Mathf.Approximately(spacerSize, 0);\n\n        public OverlayContainer()\n        {\n            AddToClassList(className);\n            name = className;\n\n            beforeSectionContainer = new VisualElement();\n            Add(beforeSectionContainer);\n            beforeSectionContainer.Add(m_BeforeSectionContent = new VisualElement());\n            beforeSectionContainer.AddToClassList(k_BeforeClassName);\n            beforeSectionContainer.AddToClassList(k_SpacingContainerClassName);\n            m_BeforeSectionContent.AddToClassList(k_ContentClassName);\n\n            afterSectionContainer = new VisualElement();\n            Add(afterSectionContainer);\n            afterSectionContainer.Add(m_AfterSectionContent = new VisualElement());\n            afterSectionContainer.AddToClassList(k_AfterClassName);\n            afterSectionContainer.AddToClassList(k_SpacingContainerClassName);\n            m_AfterSectionContent.AddToClassList(k_ContentClassName);\n\n            SetVertical();\n        }\n\n        protected virtual void SetHorizontal()\n        {\n            EnableInClassList(k_HorizontalClassName, true);\n            EnableInClassList(k_VerticalClassName, false);\n        }\n\n        protected virtual void SetVertical()\n        {\n            EnableInClassList(k_HorizontalClassName, false);\n            EnableInClassList(k_VerticalClassName, true);\n        }\n\n        public bool ContainsOverlay(Overlay overlay, OverlayContainerSection section)\n        {\n            return GetSectionInternal(section).Contains(overlay);\n        }\n\n        public bool ContainsOverlay(Overlay overlay)\n        {\n            return ContainsOverlay(overlay, OverlayContainerSection.BeforeSpacer)\n                   || ContainsOverlay(overlay, OverlayContainerSection.AfterSpacer);\n        }\n\n        public void InsertOverlay(Overlay overlay, OverlayContainerSection section, int index)\n        {\n            if (overlay == null)\n                return;\n\n            var list = GetSectionInternal(section);\n            var element = GetSectionElement(section);\n            int realIndex = -1;\n\n            //Insert relative to another element in case other visual elements are added to hierarchy\n            if (index < list.Count)\n            {\n                realIndex = element.IndexOf(list[index].rootVisualElement);\n            }\n            else if (index == list.Count)\n            {\n                realIndex = element.childCount;\n            }\n\n            realIndex = Mathf.Max(realIndex, 0);\n\n            element.Insert(realIndex, overlay.rootVisualElement);\n            list.Insert(index, overlay);\n        }\n\n        public bool RemoveOverlay(Overlay overlay)\n        {\n            if (overlay == spacerMarker)\n                return false;\n\n            bool found = m_BeforeOverlays.Remove(overlay);\n            found |= m_AfterOverlays.Remove(overlay);\n            if (found)\n               overlay.rootVisualElement.RemoveFromHierarchy();\n\n            return found;\n        }\n\n        public bool GetOverlayIndex(Overlay overlay, out OverlayContainerSection section, out int index)\n        {\n            index = m_BeforeOverlays.IndexOf(overlay);\n            if (index >= 0)\n            {\n                section = OverlayContainerSection.BeforeSpacer;\n                return true;\n            }\n\n            index = m_AfterOverlays.IndexOf(overlay);\n            if (index >= 0)\n            {\n                section = OverlayContainerSection.AfterSpacer;\n                return true;\n            }\n\n            section = (OverlayContainerSection)(-1);\n            index = -1;\n            return false;\n        }\n\n        public bool HasVisibleOverlays(OverlayContainerSection section)\n        {\n            return GetFirstVisible(section) != null;\n        }\n\n        public bool HasVisibleOverlays()\n        {\n            return HasVisibleOverlays(OverlayContainerSection.BeforeSpacer) || HasVisibleOverlays(OverlayContainerSection.AfterSpacer);\n        }\n\n        public int GetSectionCount(OverlayContainerSection section)\n        {\n            return GetSectionInternal(section).Count;\n        }\n\n        public ReadOnlyCollection<Overlay> GetSection(OverlayContainerSection section)\n        {\n            return GetSectionInternal(section).AsReadOnly();\n        }\n\n        public VisualElement GetSectionElement(OverlayContainerSection section)\n        {\n            switch (section)\n            {\n                case OverlayContainerSection.BeforeSpacer: return m_BeforeSectionContent;\n                case OverlayContainerSection.AfterSpacer: return m_AfterSectionContent;\n                default:\n                    throw new InvalidEnumArgumentException();\n            }\n        }\n\n        List<Overlay> GetSectionInternal(OverlayContainerSection section)\n        {\n            switch (section)\n            {\n                case OverlayContainerSection.BeforeSpacer: return m_BeforeOverlays;\n                case OverlayContainerSection.AfterSpacer: return m_AfterOverlays;\n                default:\n                    throw new InvalidEnumArgumentException();\n            }\n        }\n\n        public Overlay GetFirstVisible(OverlayContainerSection section)\n        {\n            List<Overlay> overlays = GetSectionInternal(section);\n            foreach (var overlay in overlays)\n            {\n                if (overlay != null && overlay.displayed)\n                    return overlay;\n            }\n\n            return null;\n        }\n\n        public Overlay GetLastVisible(OverlayContainerSection section)\n        {\n            List<Overlay> overlays = GetSectionInternal(section);\n            for (int i = overlays.Count - 1; i >= 0; --i)\n            {\n                var overlay = overlays[i];\n                if (overlay != null && overlay.displayed)\n                    return overlay;\n            }\n\n            return null;\n        }\n\n        public Overlay GetOverlay(OverlayContainerSection section, int index)\n        {\n            return GetSectionInternal(section)[index];\n        }\n\n        public virtual bool IsOverlayLayoutSupported(Layout requested)\n        {\n            return (m_SupportedOverlayLayouts & requested) > 0;\n        }\n\n        internal virtual IEnumerable<OverlayDropZoneBase> GetDropZones()\n        {\n            return new OverlayDropZoneBase[0];\n        }\n    }\n\n    class FloatingOverlayContainer : OverlayContainer\n    {\n        public FloatingOverlayContainer()\n        {\n            this.StretchToParentSize();\n        }\n\n        public override bool IsOverlayLayoutSupported(Layout requested)\n        {\n            return true;\n        }\n    }\n\n    class ToolbarOverlayContainer : OverlayContainer\n    {\n        [Serializable]\n        public new class UxmlSerializedData : OverlayContainer.UxmlSerializedData\n        {\n            public override object CreateInstance() => new ToolbarOverlayContainer();\n        }\n\n        const string k_ToolbarClassName = \"overlay-toolbar-area\";\n\n        readonly VisualElement m_ContentContainer;\n        readonly ScrollView m_ScrollView;\n        readonly VisualElement m_DockArea;\n        readonly OverlayContainerInsertDropZone m_BeforeDropZone;\n        readonly OverlayContainerInsertDropZone m_AfterDropZone;\n\n        float m_ScrollOffsetRequestedValue;\n\n        public override VisualElement contentContainer => m_ContentContainer ?? base.contentContainer;\n\n        public override Layout preferredLayout => isHorizontal ? Layout.HorizontalToolbar : Layout.VerticalToolbar;\n\n        internal bool canAssignScrollOffset => isHorizontal ? HasValidScrollerValues(m_ScrollView.horizontalScroller) : HasValidScrollerValues(m_ScrollView.verticalScroller);\n\n        public float scrollOffset\n        {\n            get => isHorizontal ? m_ScrollView.scrollOffset.x : m_ScrollView.scrollOffset.y;\n            set\n            {\n                if (canAssignScrollOffset)\n                    m_ScrollView.scrollOffset = isHorizontal ? new Vector2(value, 0) : new Vector2(0, value);\n                else\n                    m_ScrollOffsetRequestedValue = value;\n            }\n        }\n\n        public ToolbarOverlayContainer()\n        {\n            m_ScrollView = new ScrollView(ScrollViewMode.Horizontal);\n            m_ScrollView.style.width = new StyleLength(new Length(100, LengthUnit.Percent));\n            hierarchy.Add(m_ScrollView);\n            m_ScrollView.RegisterCallback<GeometryChangedEvent>(DelayScrollViewInit);\n\n            AddToClassList(k_ToolbarClassName);\n\n            m_ContentContainer = m_ScrollView.contentContainer;\n            Add(beforeSectionContainer);\n            Add(afterSectionContainer);\n\n            //Force the current direction because scroll view was just created\n            if (isHorizontal)\n                SetHorizontal();\n            else\n                SetVertical();\n\n            m_DockArea = new VisualElement { name = \"DockArea\", pickingMode = PickingMode.Ignore };\n            m_DockArea.StretchToParentSize();\n            Add(m_DockArea);\n\n            m_DockArea.Add(m_BeforeDropZone = new OverlayContainerInsertDropZone(this, OverlayContainerDropZone.Placement.Start));\n            m_DockArea.Add(m_AfterDropZone = new OverlayContainerInsertDropZone(this, OverlayContainerDropZone.Placement.End));\n            beforeSectionContainer.RegisterCallback<GeometryChangedEvent>((evt) => UpdateDockArea());\n            afterSectionContainer.RegisterCallback<GeometryChangedEvent>((evt) => UpdateDockArea());\n        }\n\n        // Flex containers have some weird interactions with scroll views so we manually updated the \"empty space\" between before and after sections\n        void UpdateDockArea()\n        {\n            var containerRect = layout;\n            var beforeSectionRect = beforeSectionContainer.layout;\n            var afterSectionRect = afterSectionContainer.layout;\n\n            m_DockArea.style.left = isHorizontal ? beforeSectionRect.width : 0;\n            m_DockArea.style.top = !isHorizontal ? beforeSectionRect.height : 0;\n            m_DockArea.style.width = isHorizontal ? Mathf.Max(containerRect.width - beforeSectionRect.width - afterSectionRect.width, 0) : new StyleLength(StyleKeyword.Auto);\n            m_DockArea.style.height = !isHorizontal ? Mathf.Max(containerRect.height - beforeSectionRect.height - afterSectionRect.height, 0) : new StyleLength(StyleKeyword.Auto);\n        }\n\n        internal override IEnumerable<OverlayDropZoneBase> GetDropZones()\n        {\n            yield return m_BeforeDropZone;\n            yield return m_AfterDropZone;\n        }\n\n        void DelayScrollViewInit(GeometryChangedEvent evt)\n        {\n            m_ScrollView.UnregisterCallback<GeometryChangedEvent>(DelayScrollViewInit);\n            m_ScrollView.horizontalScrollerVisibility = m_ScrollView.verticalScrollerVisibility = ScrollerVisibility.Hidden;\n            if (!Mathf.Approximately(m_ScrollOffsetRequestedValue, 0))\n                scrollOffset = m_ScrollOffsetRequestedValue;\n        }\n\n        protected override void SetHorizontal()\n        {\n            base.SetHorizontal();\n\n            if (m_ScrollView != null)\n            {\n                m_ScrollView.mode = ScrollViewMode.Horizontal;\n                m_ScrollView.style.width = new StyleLength(new Length(100, LengthUnit.Percent));\n                m_ScrollView.style.height = new StyleLength(StyleKeyword.Auto);\n            }\n        }\n\n        protected override void SetVertical()\n        {\n            base.SetVertical();\n\n            if (m_ScrollView != null)\n            {\n                m_ScrollView.mode = ScrollViewMode.Vertical;\n                m_ScrollView.style.height = new StyleLength(new Length(100, LengthUnit.Percent));\n                m_ScrollView.style.width = new StyleLength(StyleKeyword.Auto);\n            }\n        }\n\n        public override bool IsOverlayLayoutSupported(Layout requested)\n        {\n            if (isHorizontal)\n                return (requested & Layout.HorizontalToolbar) > 0;\n            return (requested & Layout.VerticalToolbar) > 0;\n        }\n\n        bool HasValidScrollerValues(Scroller scroller)\n        {\n            return !float.IsNaN(scroller.lowValue) && !float.IsNaN(scroller.highValue);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayContainerDropZone.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.ComponentModel;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    class OverlayContainerDropZone : OverlayDropZoneBase\n    {\n        public enum Placement\n        {\n            Start,\n            End\n        }\n\n        readonly Placement m_Placement;\n        readonly OverlayContainer m_Container;\n        readonly OverlayDropZoneBase[] m_HideIfHovered;\n\n        public override OverlayContainer targetContainer => m_Container;\n        public override OverlayContainerSection targetSection => GetSection();\n        protected Placement placement => m_Placement;\n\n        public OverlayContainerDropZone(OverlayContainer container, Placement placement, params OverlayDropZoneBase[] hideIfHovered)\n        {\n            m_Placement = placement;\n            m_Container = container;\n            m_HideIfHovered = hideIfHovered;\n        }\n\n        public override void Activate(Overlay draggedOverlay)\n        {\n            base.Activate(draggedOverlay);\n\n            SetHidden(false);\n        }\n\n        protected override bool ShouldEnable(Overlay draggedOverlay)\n        {\n            return !m_Container.HasVisibleOverlays(GetSection())\n                && !m_Container.ContainsOverlay(draggedOverlay, GetSection());\n        }\n\n        public override void UpdateHover(OverlayDropZoneBase hovered)\n        {\n            base.UpdateHover(hovered);\n\n            // Hide this dropzone if the hovered dropzone should hide this one\n            var shouldHide = Array.IndexOf(m_HideIfHovered, hovered) >= 0 || hovered is OverlayDropZone && HasSameTargetContainer(hovered);\n            pickingMode = shouldHide ? PickingMode.Ignore : PickingMode.Position;\n            SetHidden(shouldHide);\n        }\n\n        protected OverlayContainerSection GetSection()\n        {\n            switch (placement)\n            {\n                case Placement.Start: return OverlayContainerSection.BeforeSpacer;\n                case Placement.End: return OverlayContainerSection.AfterSpacer;\n                default:\n                    throw new InvalidEnumArgumentException();\n            }\n        }\n\n        public override void DropOverlay(Overlay overlay)\n        {\n            overlay.DockAt(m_Container, GetSection(), 0);\n            overlay.floating = false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayContainerInsertDropZone.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor.Overlays\n{\n    sealed class OverlayContainerInsertDropZone : OverlayContainerDropZone\n    {\n        public OverlayContainerInsertDropZone(OverlayContainer container, Placement placement) : base(container, placement)\n        {\n            style.flexGrow = 1;\n        }\n\n        public override void Activate(Overlay draggedOverlay)\n        {\n            base.Activate(draggedOverlay);\n\n            SetHidden(true);\n        }\n\n        protected override bool ShouldEnable(Overlay draggedOverlay)\n        {\n            return targetContainer.GetLastVisible(GetSection()) != draggedOverlay;\n        }\n\n        public override void UpdateHover(OverlayDropZoneBase hovered) {}\n\n        public override void BeginHover()\n        {\n            base.BeginHover();\n\n            targetContainer.GetSectionElement(GetSection()).Add(insertIndicator);\n            insertIndicator.Setup(targetContainer.isHorizontal, targetContainer is ToolbarOverlayContainer, true); //Horizontal container has vertical insert indicators\n        }\n\n        public override void EndHover()\n        {\n            base.EndHover();\n\n            insertIndicator.RemoveFromHierarchy();\n        }\n\n        public override void DropOverlay(Overlay overlay)\n        {\n            overlay.DockAt(targetContainer, GetSection());\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayDockArea.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    sealed class OverlayDockArea : VisualElement\n    {\n        // Used in tests.\n        internal const string topToolbarDropZone = \"DropZone-TopToolbar\";\n        internal const string bottomToolbarDropZone = \"DropZone-BottomToolbar\";\n        internal const string leftToolbarDropZone = \"DropZone-LeftToolbar\";\n        internal const string rightToolbarDropZone = \"DropZone-RightToolbar\";\n\n        // Used in tests.\n        internal const string topLeftColumnDropZone = \"DropZone-TopLeftColumn\";\n        internal const string bottomLeftColumnDropZone = \"DropZone-BottomLeftColumn\";\n        internal const string topRightColumnDropZone = \"DropZone-TopRightColumn\";\n        internal const string bottomRightColumnDropZone = \"DropZone-BottomRightColumn\";\n\n        readonly ToolbarDropZone m_TopToolbar;\n        readonly ToolbarDropZone m_BottomToolbar;\n        readonly ToolbarDropZone m_LeftToolbar;\n        readonly ToolbarDropZone m_RightToolbar;\n        readonly OverlayContainerDropZone m_TopLeftColumn;\n        readonly OverlayContainerDropZone m_BottomLeftColumn;\n        readonly OverlayContainerDropZone m_TopRightColumn;\n        readonly OverlayContainerDropZone m_BottomRightColumn;\n\n        public OverlayDockArea(OverlayCanvas canvas)\n        {\n            this.StretchToParentSize();\n            style.position = Position.Absolute;\n            pickingMode = PickingMode.Ignore;\n\n            Add(m_TopToolbar = new ToolbarDropZone(canvas.GetDockZoneContainer(DockZone.TopToolbar)) { name = topToolbarDropZone });\n            Add(m_BottomToolbar = new ToolbarDropZone(canvas.GetDockZoneContainer(DockZone.BottomToolbar)) { name = bottomToolbarDropZone });\n            Add(m_LeftToolbar = new ToolbarDropZone(canvas.GetDockZoneContainer(DockZone.LeftToolbar)) { name = leftToolbarDropZone });\n            Add(m_RightToolbar = new ToolbarDropZone(canvas.GetDockZoneContainer(DockZone.RightToolbar)) { name = rightToolbarDropZone });\n            Add(m_TopLeftColumn = new OverlayContainerDropZone(canvas.GetDockZoneContainer(DockZone.LeftColumn), OverlayContainerDropZone.Placement.Start, m_TopToolbar, m_LeftToolbar) { name = topLeftColumnDropZone });\n            Add(m_BottomLeftColumn = new OverlayContainerDropZone(canvas.GetDockZoneContainer(DockZone.LeftColumn), OverlayContainerDropZone.Placement.End, m_BottomToolbar, m_LeftToolbar) { name = bottomLeftColumnDropZone });\n            Add(m_TopRightColumn = new OverlayContainerDropZone(canvas.GetDockZoneContainer(DockZone.RightColumn), OverlayContainerDropZone.Placement.Start, m_TopToolbar, m_RightToolbar) { name = topRightColumnDropZone });\n            Add(m_BottomRightColumn = new OverlayContainerDropZone(canvas.GetDockZoneContainer(DockZone.RightColumn), OverlayContainerDropZone.Placement.End, m_BottomToolbar, m_RightToolbar) { name = bottomRightColumnDropZone });\n        }\n\n        public IEnumerable<OverlayDropZoneBase> GetDropZones()\n        {\n            yield return m_TopToolbar;\n            yield return m_BottomToolbar;\n            yield return m_LeftToolbar;\n            yield return m_RightToolbar;\n            yield return m_TopLeftColumn;\n            yield return m_BottomLeftColumn;\n            yield return m_TopRightColumn;\n            yield return m_BottomRightColumn;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayDragger.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    sealed class OverlayDragger : MouseManipulator\n    {\n        sealed class DockingOperation : IDisposable\n        {\n            static readonly Type[] s_PickingPriority =\n            {\n                typeof(ToolbarDropZone),\n                typeof(OverlayGhostDropZone),\n                typeof(OverlayDropZone),\n                typeof(OverlayContainerInsertDropZone),\n                typeof(OverlayContainerDropZone),\n            };\n\n            const string k_OverlayDraggedState = \"unity-overlay--dragged\";\n\n            readonly OverlayInsertIndicator m_InsertIndicator;\n            readonly List<OverlayDropZoneBase> m_DropZones = new(32);\n            readonly List<VisualElement> m_PickingBuffer = new();\n            readonly List<OverlayDropZoneBase> m_DropZoneBuffer = new();\n            readonly Overlay m_TargetOverlay;\n            readonly OverlayContainer m_OriginContainer;\n            readonly OverlayGhostDropZone m_OriginGhostDropZone;\n            readonly VisualElement m_CanvasRoot;\n            OverlayDropZoneBase m_Hovered;\n\n            public DockingOperation(OverlayCanvas canvas, Overlay targetOverlay)\n            {\n                m_InsertIndicator = new OverlayInsertIndicator(canvas.rootVisualElement);\n                m_OriginContainer = targetOverlay.container;\n                m_OriginContainer.GetOverlayIndex(targetOverlay, out var section, out var index);\n                m_TargetOverlay = targetOverlay;\n                m_CanvasRoot = canvas.rootVisualElement;\n                targetOverlay.rootVisualElement.AddToClassList(k_OverlayDraggedState);\n\n                if (!targetOverlay.floating)\n                {\n                    m_OriginGhostDropZone = OverlayGhostDropZone.Create(targetOverlay);\n                    m_DropZones.Add(m_OriginGhostDropZone);\n                }\n\n                //Collect dropzones\n                m_DropZones.AddRange(canvas.dockArea.GetDropZones());\n\n                foreach (var overlay in canvas.overlays)\n                {\n                    m_DropZones.Add(overlay.insertBeforeDropZone);\n                    m_DropZones.Add(overlay.insertAfterDropZone);\n                }\n\n                foreach (var container in canvas.containers)\n                    m_DropZones.AddRange(container.GetDropZones());\n\n                foreach (var dropZone in m_DropZones)\n                {\n                    dropZone.Setup(m_InsertIndicator, m_OriginContainer, section);\n                    dropZone.Activate(m_TargetOverlay);\n                }\n            }\n\n            public void UpdateHover(OverlayDropZoneBase hovered)\n            {\n                if (m_Hovered == hovered)\n                    return;\n\n                if (m_Hovered != null)\n                    m_Hovered.EndHover();\n\n                m_Hovered = hovered;\n\n                // Remove dropzone if we have a different container\n                if ((m_Hovered == null || m_Hovered.targetContainer != m_OriginContainer)\n                    && m_OriginGhostDropZone != null && !(m_OriginGhostDropZone.targetContainer is ToolbarOverlayContainer))\n                {\n                    m_OriginGhostDropZone.RemoveFromHierarchy();\n                    foreach (var dropZone in m_DropZones)\n                    {\n                        if (dropZone.targetContainer == m_OriginContainer)\n                            dropZone.Activate(m_TargetOverlay);\n                    }\n                }\n\n                if (m_Hovered != null)\n                    m_Hovered.BeginHover();\n\n                foreach (var dropZone in m_DropZones)\n                    dropZone.UpdateHover(hovered);\n            }\n\n            public OverlayDropZoneBase GetOverlayDropZoneAtPosition(Vector2 mousePosition)\n            {\n                //get list of items under mouse\n                m_PickingBuffer.Clear();\n                m_DropZoneBuffer.Clear();\n                m_CanvasRoot.panel.PickAll(mousePosition, m_PickingBuffer);\n\n                foreach (var element in m_PickingBuffer)\n                    if (element is OverlayDropZoneBase dropZone && dropZone.CanAcceptTarget(m_TargetOverlay))\n                        m_DropZoneBuffer.Add(dropZone);\n\n                if (m_DropZoneBuffer.Count == 0)\n                    return null;\n\n                //Sort by priority\n                m_DropZoneBuffer.Sort((a, b) => Array.IndexOf(s_PickingPriority, a.GetType()).CompareTo(Array.IndexOf(s_PickingPriority, b.GetType())));\n\n                return m_DropZoneBuffer[0];\n            }\n\n            public void Dispose()\n            {\n                m_TargetOverlay.rootVisualElement.RemoveFromClassList(k_OverlayDraggedState);\n\n                m_Hovered?.EndHover();\n\n                foreach (var dropZone in m_DropZones)\n                {\n                    dropZone.Deactivate(m_TargetOverlay);\n                    dropZone.Cleanup();\n                }\n\n                m_OriginGhostDropZone?.RemoveFromHierarchy();\n                m_InsertIndicator.RemoveFromHierarchy();\n            }\n        }\n\n\n        bool m_Active;\n        bool m_WasFloating;\n        bool m_WasCollapsed;\n        OverlayContainer m_StartContainer;\n        Vector2 m_InitialLayoutPosition;\n        Vector2 m_StartLeftCornerPosition;\n        Vector2 m_StartMousePosition;\n        readonly Overlay m_Overlay;\n        int m_InitialIndex;\n        OverlayContainerSection m_InitialSection;\n        DockingOperation m_DockOperation;\n\n        OverlayCanvas canvas => m_Overlay.canvas;\n        FloatingOverlayContainer floatingContainer => canvas.floatingContainer;\n\n        public OverlayDragger(Overlay overlay)\n        {\n            m_Overlay = overlay;\n            activators.Add(new ManipulatorActivationFilter {button = MouseButton.LeftMouse});\n            activators.Add(new ManipulatorActivationFilter {button = MouseButton.LeftMouse, modifiers = EventModifiers.Control});\n            m_Active = false;\n        }\n\n        protected override void RegisterCallbacksOnTarget()\n        {\n            target.RegisterCallback<MouseDownEvent>(OnMouseDown);\n            target.RegisterCallback<MouseUpEvent>(OnMouseUp);\n            target.RegisterCallback<KeyDownEvent>(OnKeyDown);\n            target.RegisterCallback<PointerCaptureOutEvent>(OnPointerCaptureOut);\n        }\n\n        protected override void UnregisterCallbacksFromTarget()\n        {\n            target.UnregisterCallback<MouseDownEvent>(OnMouseDown);\n            target.UnregisterCallback<MouseMoveEvent>(OnMouseMove);\n            target.UnregisterCallback<MouseUpEvent>(OnMouseUp);\n            target.UnregisterCallback<KeyDownEvent>(OnKeyDown);\n            target.UnregisterCallback<PointerCaptureOutEvent>(OnPointerCaptureOut);\n        }\n\n        bool IsInDraggableArea(Vector2 mousePosition)\n        {\n            return target.worldBound.Contains(mousePosition);\n        }\n\n        void OnMouseDown(MouseDownEvent e)\n        {\n            if (m_Active)\n            {\n                e.StopImmediatePropagation();\n                return;\n            }\n\n            if (!IsInDraggableArea(e.mousePosition) || !CanStartManipulation(e))\n                return;\n\n            m_WasFloating = m_Overlay.floating;\n            m_WasCollapsed = m_Overlay.collapsed;\n            m_StartContainer = m_Overlay.container;\n            m_DockOperation = new DockingOperation(canvas, m_Overlay);\n\n            m_StartMousePosition = OverlayUtilities.ClampPositionToRect(e.mousePosition, canvas.rootVisualElement.worldBound);\n            m_StartLeftCornerPosition = m_Overlay.rootVisualElement.Q(Overlay.draggerName).worldBound.position;\n\n            m_InitialLayoutPosition = floatingContainer.WorldToLocal(m_Overlay.rootVisualElement.worldBound.position);\n\n            //if docked, convert to floating\n            if (!m_Overlay.floating)\n            {\n                m_Overlay.container.GetOverlayIndex(m_Overlay, out m_InitialSection, out m_InitialIndex);\n                m_Overlay.Undock();\n                m_Overlay.floatingPosition = m_InitialLayoutPosition;\n                m_Overlay.UpdateAbsolutePosition();\n            }\n\n            m_Overlay.BringToFront();\n\n            m_Active = true;\n            target.RegisterCallback<MouseMoveEvent>(OnMouseMove, TrickleDown.TrickleDown);\n            target.CaptureMouse();\n            e.StopPropagation();\n        }\n\n        void OnMouseMove(MouseMoveEvent e)\n        {\n            if (!m_Active)\n                return;\n\n            var constrainedMousePosition = OverlayUtilities.ClampPositionToRect(e.mousePosition, canvas.rootVisualElement.worldBound);\n\n            var dropZone = m_DockOperation.GetOverlayDropZoneAtPosition(constrainedMousePosition);\n            var targetContainer = dropZone != null ? dropZone.targetContainer : null;\n\n            bool delayPositionUpdate = false;\n            if (m_Overlay.tempTargetContainer != targetContainer)\n            {\n                var prevLayout = m_Overlay.activeLayout;\n                m_Overlay.tempTargetContainer = targetContainer;\n                m_Overlay.RebuildContent();\n                if (m_Overlay.activeLayout != prevLayout)\n                    delayPositionUpdate = true;\n            }\n\n            var diff = (constrainedMousePosition - (!m_WasCollapsed && m_Overlay.collapsed ? m_StartLeftCornerPosition : m_StartMousePosition));\n            var targetPosition = m_InitialLayoutPosition + diff;\n            var targetRect = new Rect(targetPosition, m_Overlay.rootVisualElement.layout.size);\n\n            if (delayPositionUpdate)\n                m_Overlay.rootVisualElement.RegisterCallback<GeometryChangedEvent, Rect>(DelayedPositionUpdate, targetRect);\n            else\n#pragma warning disable CS0618 // Type or member is obsolete\n                m_Overlay.rootVisualElement.transform.position = OverlayUtilities.ClampRectToRect(targetRect, floatingContainer.rect).position;\n#pragma warning restore CS0618 // Type or member is obsolete\n\n            m_DockOperation.UpdateHover(dropZone);\n\n            e.StopPropagation();\n        }\n\n        void DelayedPositionUpdate(GeometryChangedEvent evt, Rect targetRect)\n        {\n#pragma warning disable CS0618 // Type or member is obsolete\n            m_Overlay.rootVisualElement.transform.position = OverlayUtilities.ClampRectToRect(targetRect, floatingContainer.rect).position;\n#pragma warning restore CS0618 // Type or member is obsolete\n            m_Overlay.rootVisualElement.UnregisterCallback<GeometryChangedEvent, Rect>(DelayedPositionUpdate);\n        }\n\n        void OnMouseUp(MouseUpEvent e)\n        {\n            if (!m_Active)\n                return;\n\n            if (e.button != (int)MouseButton.RightMouse && !CanStopManipulation(e))\n                return;\n\n            e.StopPropagation();\n\n            var dropZone = m_DockOperation.GetOverlayDropZoneAtPosition(OverlayUtilities.ClampPositionToRect(e.mousePosition, canvas.rootVisualElement.worldBound));\n            if (dropZone != null)\n            {\n                if (dropZone is OverlayGhostDropZone)\n                {\n                    CancelDrag();\n                    return;\n                }\n\n                m_Overlay.container?.RemoveOverlay(m_Overlay);\n#pragma warning disable CS0618 // Type or member is obsolete\n                m_Overlay.rootVisualElement.transform.position = Vector2.zero;\n#pragma warning restore CS0618 // Type or member is obsolete\n                dropZone.DropOverlay(m_Overlay);\n            }\n\n            if (m_Overlay.floating)\n            {\n#pragma warning disable CS0618 // Type or member is obsolete\n                var pos = m_Overlay.rootVisualElement.transform.position;\n#pragma warning restore CS0618 // Type or member is obsolete\n                m_Overlay.floatingPosition = new Vector2(pos.x, pos.y);\n            }\n\n            OnDragEnd();\n        }\n\n        void OnPointerCaptureOut(PointerCaptureOutEvent evt)\n        {\n            if (!m_Active)\n                return;\n            CancelDrag();\n        }\n\n        void OnKeyDown(KeyDownEvent evt)\n        {\n            if (m_Active && evt.keyCode == KeyCode.Escape)\n            {\n                CancelDrag();\n                evt.StopPropagation();\n            }\n        }\n\n        void CancelDrag()\n        {\n            if (m_WasFloating)\n            {\n#pragma warning disable CS0618 // Type or member is obsolete\n                m_Overlay.rootVisualElement.transform.position = m_InitialLayoutPosition;\n#pragma warning restore CS0618 // Type or member is obsolete\n            }\n            else\n            {\n                m_Overlay.DockAt(m_StartContainer, m_InitialSection, m_InitialIndex);\n            }\n\n            OnDragEnd();\n            m_Overlay.RebuildContent();\n        }\n\n        void OnDragEnd()\n        {\n            m_Active = false;\n            target.ReleaseMouse();\n\n            target.UnregisterCallback<MouseMoveEvent>(OnMouseMove);\n            m_Overlay.rootVisualElement.UnregisterCallback<GeometryChangedEvent, Rect>(DelayedPositionUpdate); //Ensure we kill any delayed position update that was still in process\n\n            m_Overlay.tempTargetContainer = null;\n            m_DockOperation.Dispose();\n            m_DockOperation = null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayDropZone.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    class OverlayDropZone : OverlayDropZoneBase\n    {\n        public enum Placement\n        {\n            Before,\n            After\n        }\n\n        readonly Overlay m_TargetOverlay;\n        readonly Placement m_Placement;\n        OverlayContainer m_TargetContainer;\n        OverlayContainerSection m_TargetSection;\n        Overlay m_DraggedOverlay;\n\n        public override OverlayContainer targetContainer => m_TargetOverlay.container;\n        public override OverlayContainerSection targetSection => m_TargetSection;\n\n        public OverlayDropZone(Overlay target, Placement placement)\n        {\n            m_TargetOverlay = target;\n            m_Placement = placement;\n            style.flexGrow = 1;\n        }\n\n        protected override bool ShouldEnable(Overlay draggedOverlay)\n        {\n            return !m_TargetOverlay.floating && m_TargetOverlay != draggedOverlay;\n        }\n\n        public override bool CanAcceptTarget(Overlay overlay)\n        {\n            return m_TargetOverlay != overlay;\n        }\n\n        public override void Activate(Overlay draggedOverlay)\n        {\n            base.Activate(draggedOverlay);\n\n            m_DraggedOverlay = draggedOverlay;\n            m_TargetContainer = m_TargetOverlay.container;\n            m_TargetContainer.GetOverlayIndex(m_TargetOverlay, out m_TargetSection, out var _);\n            SetHidden(true);\n        }\n\n        public override void BeginHover()\n        {\n            base.BeginHover();\n           \n            if (m_TargetContainer is not ToolbarOverlayContainer)\n                m_DraggedOverlay.rootVisualElement.RegisterCallback<GeometryChangedEvent>(OnDraggedOverlayGeometryChanged);\n\n            var parent = m_TargetOverlay.rootVisualElement.parent;\n            var index = parent.IndexOf(m_TargetOverlay.rootVisualElement);\n\n            bool dockAfter = ShouldDockAfter(m_TargetSection);\n            if (dockAfter)\n                ++index;\n\n            parent.Insert(index, insertIndicator);\n\n            //Horizontal container has vertical insert indicators\n            insertIndicator.Setup(m_TargetOverlay.container.isHorizontal, targetContainer is ToolbarOverlayContainer,\n                (dockAfter && m_TargetOverlay.container.GetLastVisible(m_TargetSection) == m_TargetOverlay)\n                || (!dockAfter && m_TargetOverlay.container.GetFirstVisible(m_TargetSection) == m_TargetOverlay));\n\n            MatchIndicatorToDraggedOverlay();\n        }\n\n        public override void EndHover()\n        {\n            base.EndHover();\n            insertIndicator.RemoveFromHierarchy();\n            \n            if (m_TargetContainer is not ToolbarOverlayContainer)\n                m_DraggedOverlay.rootVisualElement.UnregisterCallback<GeometryChangedEvent>(OnDraggedOverlayGeometryChanged);\n        }\n        \n        void OnDraggedOverlayGeometryChanged(GeometryChangedEvent evt)\n        {\n            MatchIndicatorToDraggedOverlay();\n        }\n\n        void MatchIndicatorToDraggedOverlay()\n        {\n            // When adding an overlay in one of the 2 columns we use the current width of the overlay as preview\n            if (m_TargetContainer is not ToolbarOverlayContainer)\n                insertIndicator.style.width = m_DraggedOverlay.rootVisualElement.layout.width;\n        }\n\n        public override void DropOverlay(Overlay overlay)\n        {\n\n            m_TargetOverlay.container.GetOverlayIndex(m_TargetOverlay, out var section, out _);\n            if (ShouldDockAfter(section))\n            {\n                overlay.DockAfter(m_TargetOverlay);\n            }\n            else\n            {\n                overlay.DockBefore(m_TargetOverlay);\n            }\n\n            overlay.floating = false;\n        }\n\n        bool ShouldDockAfter(OverlayContainerSection targetSection)\n        {\n            // The drop zone before the element should place after the next overlay when after the spacer.\n            // Overlay after the spacer are listed from bottom to spacer instead of spacer to bottom.\n            return targetSection == OverlayContainerSection.BeforeSpacer && m_Placement == Placement.After\n                || targetSection == OverlayContainerSection.AfterSpacer && m_Placement == Placement.Before;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayDropZoneBase.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    abstract class OverlayDropZoneBase : VisualElement\n    {\n        public const string className = \"unity-overlay-drop-zone\";\n        const string k_HoveredState = \"unity-overlay-drop-zone--hovered\";\n        internal const string hiddenState = \"unity-overlay-drop-zone--hidden\"; // Used in tests.\n\n        protected OverlayInsertIndicator insertIndicator { get; private set; }\n        protected OverlayContainer originContainer { get; private set; }\n        protected OverlayContainerSection originSection { get; private set; }\n\n        public abstract OverlayContainer targetContainer { get; }\n        public abstract OverlayContainerSection targetSection { get; }\n\n        public virtual bool CanAcceptTarget(Overlay overlay) { return true; }\n        public abstract void DropOverlay(Overlay overlay);\n\n        protected OverlayDropZoneBase()\n        {\n            AddToClassList(className);\n\n            pickingMode = PickingMode.Ignore;\n            visible = false;\n        }\n\n        public void Setup(OverlayInsertIndicator insertIndicator, OverlayContainer originContainer, OverlayContainerSection originSection)\n        {\n            this.insertIndicator = insertIndicator;\n            this.originContainer = originContainer;\n            this.originSection = originSection;\n        }\n\n        public void Cleanup()\n        {\n            insertIndicator = null;\n            originContainer = null;\n        }\n\n        public virtual void Activate(Overlay draggedOverlay)\n        {\n            var shouldEnable = ShouldEnable(draggedOverlay);\n            pickingMode = shouldEnable ? PickingMode.Position : PickingMode.Ignore;\n            visible = shouldEnable;\n        }\n\n        protected virtual bool ShouldEnable(Overlay draggedOverlay) { return true; }\n\n        public virtual void BeginHover()\n        {\n            EnableInClassList(k_HoveredState, true);\n        }\n\n        public virtual void EndHover()\n        {\n            EnableInClassList(k_HoveredState, false);\n        }\n\n        public virtual void UpdateHover(OverlayDropZoneBase hovered)\n        {\n        }\n\n        public bool HasSameTargetContainer(OverlayDropZoneBase dropZone)\n        {\n            if (dropZone == null)\n                return false;\n\n            return dropZone.targetContainer == targetContainer && dropZone.targetSection == targetSection;\n        }\n\n        protected void SetHidden(bool hidden)\n        {\n            EnableInClassList(hiddenState, hidden);\n        }\n\n        public virtual void Deactivate(Overlay draggedOverlay)\n        {\n            visible = false;\n            pickingMode = PickingMode.Ignore;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayGhostDropZone.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor.Overlays\n{\n    class OverlayGhostDropZone : OverlayDropZoneBase\n    {\n        public override OverlayContainer targetContainer => m_Container;\n        public override OverlayContainerSection targetSection => m_Section;\n\n        readonly OverlayContainer m_Container;\n        readonly OverlayContainerSection m_Section;\n\n        OverlayGhostDropZone(OverlayContainer container, OverlayContainerSection section)\n        {\n            m_Container = container;\n            m_Section = section;\n        }\n\n        public static OverlayGhostDropZone Create(Overlay overlay)\n        {\n            bool found = overlay.container.GetOverlayIndex(overlay, out var section, out int index);\n            OverlayGhostDropZone dropZone = new OverlayGhostDropZone(overlay.container, section);\n            if (found)\n            {\n                overlay.container.GetSectionElement(section)?.Insert(index, dropZone);\n                dropZone.style.width = overlay.rootVisualElement.layout.width;\n                dropZone.style.height = overlay.rootVisualElement.layout.height;\n            }\n\n            return dropZone;\n        }\n\n        public override void DropOverlay(Overlay overlay) {} //This case is handled in the drag as a cancel\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayInsertIndicator.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    class OverlayInsertIndicator : VisualElement\n    {\n        const string k_ClassName = \"unity-overlay-insert-indicator\";\n        const string k_VerticalState = k_ClassName + \"--vertical\";\n        const string k_Horizontal = k_ClassName + \"--horizontal\";\n        const string k_VisualClass = k_ClassName + \"__visual\";\n        const string k_MarkerClass = k_ClassName + \"__marker\";\n        const string k_FirstVisibleClass = k_ClassName + \"--first-visible\";\n        const string k_InToolbarClass = k_ClassName + \"--in-toolbar\";\n\n        readonly VisualElement m_Visual;\n        readonly VisualElement m_Marker;\n        readonly VisualElement m_RenderOnTopParent;\n\n        public OverlayInsertIndicator(VisualElement renderOnTopParent)\n        {\n            pickingMode = PickingMode.Ignore;\n            AddToClassList(k_ClassName);\n\n            m_Marker = new VisualElement();\n            m_Marker.AddToClassList(k_MarkerClass);\n            Add(m_Marker);\n\n            m_RenderOnTopParent = renderOnTopParent;\n            m_Visual = new VisualElement();\n            m_Visual.AddToClassList(k_VisualClass);\n            m_Marker.RegisterCallback<GeometryChangedEvent>(MarkerGeometryChanged);\n            RegisterCallback<AttachToPanelEvent>(OnAttach);\n            RegisterCallback<DetachFromPanelEvent>(OnDetach);\n        }\n\n        void OnAttach(AttachToPanelEvent evt)\n        {\n            m_RenderOnTopParent.Add(m_Visual);\n            m_Visual.style.display = DisplayStyle.None; // We don't want the visual to show before the size has been set\n        }\n\n        void OnDetach(DetachFromPanelEvent evt)\n        {\n            m_Visual.RemoveFromHierarchy();\n        }\n\n        void MarkerGeometryChanged(GeometryChangedEvent evt)\n        {\n            var targetRect = m_RenderOnTopParent.WorldToLocal(m_Marker.worldBound);\n#pragma warning disable CS0618 // Type or member is obsolete\n            m_Visual.transform.position = targetRect.position;\n#pragma warning restore CS0618 // Type or member is obsolete\n            m_Visual.style.width = targetRect.width;\n            m_Visual.style.height = targetRect.height;\n            m_Visual.style.display = DisplayStyle.Flex;\n        }\n\n        public void Setup(bool vertical, bool inToolbar, bool firstVisible)\n        {\n            style.width = StyleKeyword.Null;\n            style.height = StyleKeyword.Null;\n            EnableInClassList(k_VerticalState, vertical);\n            EnableInClassList(k_Horizontal, !vertical);\n            EnableInClassList(k_FirstVisibleClass, firstVisible);\n            m_Visual.EnableInClassList(k_InToolbarClass, inToolbar);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayMenuItem.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    sealed class OverlayMenuItem : VisualElement\n    {\n        const string k_UxmlPath = \"UXML/Overlays/overlay-menu-item.uxml\";\n        const string k_VisibilityIconClass = \"overlay-menu-item__visibility-icon\";\n        const string k_ListItemClass = \"unity-list-view__item\";\n        const string k_MenuItemClass = \"overlay-menu-item\";\n\n\n        readonly Label m_Title;\n        readonly VisualElement m_VisibilityIcon;\n        Overlay m_Overlay;\n\n        static VisualTreeAsset s_TreeAsset;\n\n        public Overlay overlay\n        {\n            get => m_Overlay;\n            set\n            {\n                if (m_Overlay != null)\n                {\n                    m_Overlay.displayedChanged -= OnOverlayDisplayChanged;\n                    if (m_Overlay.canvas != null)\n                        m_Overlay.canvas.overlaysEnabledChanged -= OnOverlayEnabledChanged;\n                }\n\n                m_Overlay = value;\n                name = overlay.rootVisualElement.name;\n                m_Title.text = string.IsNullOrEmpty(overlay.displayName)\n                    ? m_Overlay.GetType().Name\n                    : overlay.displayName;\n\n                UpdateIconVisibilityState();\n\n                if (m_Overlay != null)\n                {\n                    m_Overlay.displayedChanged += OnOverlayDisplayChanged;\n                    if (m_Overlay.canvas != null)\n                    {\n                        OnOverlayEnabledChanged(m_Overlay.canvas.overlaysEnabled);\n                        m_Overlay.canvas.overlaysEnabledChanged += OnOverlayEnabledChanged;\n                    }\n                }\n            }\n        }\n\n        public OverlayMenuItem()\n        {\n            if (s_TreeAsset == null)\n                s_TreeAsset = EditorGUIUtility.Load(k_UxmlPath) as VisualTreeAsset;\n\n            s_TreeAsset.CloneTree(this);\n\n            m_Title = this.Q<Label>(\"DisplayName\");\n            m_VisibilityIcon = this.Q(\"VisibilityIcon\");\n\n            RegisterCallback<MouseOverEvent>(OnMouseEnter);\n            RegisterCallback<MouseOutEvent>(OnMouseLeave);\n            this.AddManipulator(new Clickable(OnClick));\n        }\n\n        void OnOverlayDisplayChanged(bool state)\n        {\n            UpdateIconVisibilityState();\n        }\n\n        void UpdateIconVisibilityState()\n        {\n            if (m_Overlay == null)\n                return;\n\n            m_VisibilityIcon.EnableInClassList(k_VisibilityIconClass + \"--visible\", m_Overlay.displayed);\n            m_VisibilityIcon.EnableInClassList(k_VisibilityIconClass + \"--invisible\", !m_Overlay.displayed);\n        }\n\n        void OnOverlayEnabledChanged(bool visibility)\n        {\n            SetEnabled(visibility);\n\n            //Icon highlighted\n            m_VisibilityIcon.EnableInClassList(k_VisibilityIconClass + \"-enabled\", visibility);\n            //Text color\n            EnableInClassList(k_MenuItemClass + \"-enabled\", visibility);\n            //Background highlighted\n            EnableInClassList(k_ListItemClass + \"-enabled\", visibility);\n        }\n\n        void OnClick()\n        {\n            if (m_Overlay == null)\n                return;\n\n            m_Overlay.displayed = !m_Overlay.displayed;\n        }\n\n        void OnMouseLeave(MouseOutEvent evt)\n        {\n            m_Overlay?.SetHighlightEnabled(false);\n        }\n\n        void OnMouseEnter(MouseOverEvent evt)\n        {\n            m_Overlay?.SetHighlightEnabled(enabledSelf);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayPlacement.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    public abstract partial class Overlay\n    {\n        internal struct LockedAnchor : IDisposable\n        {\n            Overlay m_Target;\n\n            public LockedAnchor(Overlay target)\n            {\n                m_Target = target;\n                m_Target.m_LockAnchor = true;\n            }\n\n            public void Dispose()\n            {\n                m_Target.m_LockAnchor = false;\n            }\n        }\n\n        internal SnapCorner floatingSnapCorner\n        {\n            get => m_FloatingSnapCorner;\n            private set => m_FloatingSnapCorner = value;\n        }\n\n        internal Vector2 floatingSnapOffset\n        {\n            get => m_FloatingSnapOffset + m_SnapOffsetDelta;\n\n            private set\n            {\n                if (m_FloatingSnapOffset == value)\n                    return;\n\n                m_FloatingSnapOffset = value;\n                m_SnapOffsetDelta = Vector2.zero;\n                UpdateAbsolutePosition();\n                floatingPositionChanged?.Invoke(floatingPosition);\n            }\n        }\n\n        // overlay floating position in window\n        public Vector2 floatingPosition\n        {\n            get => SnapToFloatingPosition(floatingSnapCorner, m_LockAnchor ? m_FloatingSnapOffset : floatingSnapOffset);\n            set\n            {\n                var position = canvas.EnsureOverlapsWindow(new Rect(value, rootVisualElement.rect.size)).position;\n                UpdateSnapping(position);\n            }\n        }\n\n        public bool floating\n        {\n            get => m_Floating;\n            internal set\n            {\n                if (m_Floating == value) return;\n                m_Floating = value;\n                OnFloatingChanged(value);\n            }\n        }\n        \n        internal event Action<OverlayContainer> dockingCompleted;\n\n        void OnFloatingChanged(bool floating)\n        {\n            if (floating)\n                UpdateAbsolutePosition();\n\n            floatingChanged?.Invoke(floating);\n        }\n\n        internal bool DockAt(OverlayContainer container, OverlayContainerSection section)\n        {\n            return DockAt(container, section, container.ContainsOverlay(this, section) ? container.GetSectionCount(section) - 1 : container.GetSectionCount(section));\n        }\n\n        // The index must be either less or equal to the section count if this overlay is not in already in the container.\n        // If the overlay is already in the container, the index must be less than the section count\n        internal bool DockAt(OverlayContainer container, OverlayContainerSection section, int index)\n        {\n            //If the overlay is staying in the same container\n            var existsInContainer = container.GetOverlayIndex(this, out var originSection, out var originIndex);\n            if (existsInContainer)\n            {\n                if (originSection == section && originIndex == index)\n                    return true;\n            }\n\n            this.container?.RemoveOverlay(this);\n\n            this.container = container;\n\n            int sectionCount = container.GetSectionCount(section);\n            if (index > sectionCount)\n            {\n                Debug.LogWarning(\"Trying to dock overlay at an invalid index. Docking at the end of the section instead.\");\n                index = sectionCount;\n            }\n\n            this.container.InsertOverlay(this, section, index);\n\n            floating = container is FloatingOverlayContainer;\n\n            if(!existsInContainer)\n                RebuildContent();\n            \n            dockingCompleted?.Invoke(container);\n            \n            return true;\n        }\n\n        internal bool DockBefore(Overlay target)\n        {\n            if (target.container == null)\n                throw new ArgumentException(\"Target overlay has an invalid container\", nameof(target));\n\n            var targetContainer = target.container;\n            targetContainer.GetOverlayIndex(target, out var section, out var targetIndex);\n            if (container == targetContainer)\n            {\n                container.GetOverlayIndex(this, out var thisSection, out var thisIndex);\n                if( thisIndex < targetIndex && thisSection == section)\n                    targetIndex--;\n\n            }\n            return DockAt(targetContainer, section, targetIndex);\n        }\n\n        internal bool DockAfter(Overlay target)\n        {\n            if (target.container == null)\n                throw new ArgumentException(\"Target overlay has an invalid container\", nameof(target));\n\n            var targetContainer = target.container;\n            targetContainer.GetOverlayIndex(target, out var section, out var targetIndex);\n            if (container == targetContainer)\n            {\n                container.GetOverlayIndex(this, out var thisSection, out var thisIndex);\n                if( thisIndex < targetIndex && thisSection == section)\n                    targetIndex--;\n\n            }\n            return DockAt(targetContainer, section, targetIndex + 1);\n        }\n\n        public void Undock()\n        {\n            if (floating)\n                return;\n\n            DockAt(canvas.floatingContainer, OverlayContainerSection.BeforeSpacer);\n        }\n\n        internal void BringToFront()\n        {\n            if (!(container is FloatingOverlayContainer))\n                return;\n\n            DockAt(container, OverlayContainerSection.BeforeSpacer, container.GetSectionCount(OverlayContainerSection.BeforeSpacer) -1);\n        }\n\n        internal void SetSnappingOffset(Vector2 snapOffset, Vector2 snapOffsetDelta)\n        {\n            m_FloatingSnapOffset = snapOffset;\n            m_SnapOffsetDelta = snapOffsetDelta;\n            UpdateAbsolutePosition();\n            floatingPositionChanged?.Invoke(floatingPosition);\n        }\n\n        Vector2 SnapToFloatingPosition(SnapCorner corner, Vector2 snapPosition)\n        {\n            switch (corner)\n            {\n                case SnapCorner.TopLeft:\n                    return snapPosition;\n                case SnapCorner.TopRight:\n                    return new Vector2(canvas.floatingContainer.localBound.width + snapPosition.x, snapPosition.y);\n                case SnapCorner.BottomLeft:\n                    return new Vector2(snapPosition.x, canvas.floatingContainer.localBound.height + snapPosition.y);\n                case SnapCorner.BottomRight:\n                    return canvas.floatingContainer.localBound.size + snapPosition;\n                default:\n                    return Vector2.zero;\n            }\n        }\n\n        void FloatingToSnapPosition(Vector2 position, out Vector2 snapOffset)\n        {\n            Rect containerRect = canvas.floatingContainer.localBound;\n            Rect overlayRect = new Rect(position, rootVisualElement.localBound.size);\n            Vector2 snapCornerPosition;\n            switch (floatingSnapCorner)\n            {\n                case SnapCorner.TopRight:\n                    snapCornerPosition = containerRect.position + new Vector2(containerRect.width, 0);\n                    break;\n                case SnapCorner.BottomLeft:\n                    snapCornerPosition = containerRect.position + new Vector2(0, containerRect.height);\n                    break;\n                case SnapCorner.BottomRight:\n                    snapCornerPosition = containerRect.max;\n                    break;\n                case SnapCorner.TopLeft:\n                default:\n                    snapCornerPosition = containerRect.position;\n                    break;\n            }\n\n            snapOffset = overlayRect.position - snapCornerPosition;\n        }\n\n        void FloatingToSnapPosition(Vector2 position, out SnapCorner snapCorner, out Vector2 snapOffset)\n        {\n            Rect containerRect = canvas.floatingContainer.localBound;\n            var aTopLeft = containerRect.position;\n            var aTopRight = containerRect.position + new Vector2(containerRect.width, 0);\n            var aBottomLeft = containerRect.position + new Vector2(0, containerRect.height);\n            var aBottomRight = containerRect.max;\n\n            Rect overlayRect = new Rect(position, rootVisualElement.localBound.size);\n            var bTopLeft = overlayRect.position;\n            var bTopRight = overlayRect.position + new Vector2(overlayRect.width, 0);\n            var bBottomLeft = overlayRect.position + new Vector2(0, overlayRect.height);\n            var bBottomRight = overlayRect.max;\n\n            var topLeft = bTopLeft - aTopLeft;\n            var topRight = bTopRight - aTopRight;\n            var bottomLeft = bBottomLeft - aBottomLeft;\n            var bottomRight = bBottomRight - aBottomRight;\n\n            snapOffset = topLeft;\n            snapCorner = SnapCorner.TopLeft;\n\n            if (topRight.sqrMagnitude < snapOffset.sqrMagnitude)\n            {\n                snapOffset = overlayRect.position - aTopRight;\n                snapCorner = SnapCorner.TopRight;\n            }\n\n            if (bottomLeft.sqrMagnitude < snapOffset.sqrMagnitude)\n            {\n                snapOffset = overlayRect.position - aBottomLeft;\n                snapCorner = SnapCorner.BottomLeft;\n            }\n\n            if (bottomRight.sqrMagnitude < snapOffset.sqrMagnitude)\n            {\n                snapOffset = overlayRect.position - aBottomRight;\n                snapCorner = SnapCorner.BottomRight;\n            }\n        }\n\n        internal void OnGeometryChanged(GeometryChangedEvent evt)\n        {\n            if (evt.newRect.size != evt.oldRect.size && canvas.overlaysEnabled)\n            {\n                if (!m_ContentsChanged)\n                    using (new LockedAnchor(this))\n                        floatingPosition = floatingPosition;\n            }\n\n            // When visual state changes, we need to wait until geometry recalculates to enforce bounds clamping\n            if(m_ContentsChanged)\n                floatingPosition = floatingPosition;\n\n            m_ContentsChanged = false;\n        }\n\n        void UpdateSnapping(Vector2 position)\n        {\n            //Protect against an update to the position while the canvas hasn't had its first geometry pass\n            if (float.IsNaN(position.x) || float.IsNaN(position.y))\n                return;\n\n            if (m_LockAnchor)\n            {\n                //Anchor and position are locked, we only update the offsetDelta\n                FloatingToSnapPosition(position, out var snapOffset);\n                m_SnapOffsetDelta = snapOffset - m_FloatingSnapOffset;\n            }\n            else\n            {\n                FloatingToSnapPosition(position, out var snapCorner, out var snapOffset);\n                floatingSnapCorner = snapCorner;\n                floatingSnapOffset = snapOffset;\n            }\n        }\n\n        internal void UpdateAbsolutePosition()\n        {\n            if (rootVisualElement.resolvedStyle.position == Position.Absolute)\n#pragma warning disable CS0618 // Type or member is obsolete\n                rootVisualElement.transform.position = floatingPosition;\n#pragma warning restore CS0618 // Type or member is obsolete\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayPopup.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    class OverlayPopup : VisualElement\n    {\n        const int k_Margin = 4;\n\n        internal enum Anchor\n        {\n            TopLeft,\n            TopRight,\n            BottomLeft,\n            BottomRight,\n            Center\n        }\n\n        // FocusOutEvent.originalMousePosition is not valid, so we keep track of where the mouse is when clicking.\n        bool m_CursorIsOverPopup;\n        public bool containsCursor => m_CursorIsOverPopup;\n        const string k_OutsideToolbar = \"overlay-popup--outside-toolbar\";\n        const string k_FromHorizontal = \"overlay-popup--from-horizontal\";\n        const string k_FromVertical = \"overlay-popup--from-vertical\";\n        const string k_Clamped = \"overlay-popup--clamped\";\n\n        public Overlay overlay { get; private set; }\n\n        bool m_ShouldRecalculateAnchors;\n        bool m_UseMargins;\n        bool m_Horizontal;\n        Rect m_TargetRect;\n        Vector2 m_Margin = Vector2.zero;\n        Anchor m_PopupAnchor = Anchor.Center;\n        Anchor m_TargetAnchor = Anchor.Center;\n\n        internal static void GetAnchors(Rect targetElement, Rect container, bool horizontal, Vector2 size, out Anchor popupAnchor, out Anchor targetAnchor, out Vector2 margin)\n        {\n            float DistanceToEdge(float targetPos, float edgePos)\n            {\n                return Mathf.Abs(edgePos - targetPos);\n            }\n\n            float distAbove = DistanceToEdge(targetElement.yMin, container.yMin);\n            float distBelow = DistanceToEdge(targetElement.yMax, container.yMax);\n            float distLeft = DistanceToEdge(targetElement.xMin, container.xMin);\n            float distRight = DistanceToEdge(targetElement.xMax, container.xMax);\n\n            bool showUnder = distBelow >= size.y || distBelow > distAbove;\n            bool showRight = distRight >= size.x || distRight > distLeft;\n\n            if (horizontal)\n            {\n                if (showUnder)\n                {\n                    popupAnchor = showRight ? Anchor.TopLeft : Anchor.TopRight;\n                    targetAnchor = showRight ? Anchor.BottomLeft : Anchor.BottomRight;\n                }\n                else\n                {\n                    popupAnchor = showRight ? Anchor.BottomLeft : Anchor.BottomRight;\n                    targetAnchor = showRight ? Anchor.TopLeft : Anchor.TopRight;\n                }\n\n                margin = new Vector2(0, showUnder ? k_Margin : -k_Margin);\n            }\n            else\n            {\n                if (showUnder)\n                {\n                    popupAnchor = showRight ? Anchor.TopLeft : Anchor.TopRight;\n                    targetAnchor = showRight ? Anchor.TopRight : Anchor.TopLeft;\n                }\n                else\n                {\n                    popupAnchor = showRight ? Anchor.BottomLeft : Anchor.BottomRight;\n                    targetAnchor = showRight ? Anchor.BottomRight : Anchor.BottomLeft;\n                }\n\n                margin = new Vector2(showRight ? k_Margin : -k_Margin, 0);\n            }\n        }\n\n        internal static Rect PlaceNextToTarget(Vector2 size, Rect targetRect, Rect containerRect, Anchor popupAnchor, Anchor targetAnchor, Vector2 margin)\n        {\n            Vector2 targetPos = targetRect.center;\n            switch (targetAnchor)\n            {\n                case Anchor.TopLeft: targetPos = new Vector2(targetRect.xMin, targetRect.yMin); break;\n                case Anchor.TopRight: targetPos = new Vector2(targetRect.xMax, targetRect.yMin); break;\n                case Anchor.BottomLeft: targetPos = new Vector2(targetRect.xMin, targetRect.yMax); break;\n                case Anchor.BottomRight: targetPos = new Vector2(targetRect.xMax, targetRect.yMax); break;\n            }\n\n            var popupRect = new Rect(targetPos, size);\n            popupRect.position += margin;\n\n            switch (popupAnchor)\n            {\n                case Anchor.TopRight: popupRect.position -= new Vector2(size.x, 0); break;\n                case Anchor.BottomLeft: popupRect.position -= new Vector2(0, size.y); break;\n                case Anchor.BottomRight: popupRect.position -= new Vector2(size.x, size.y); break;\n                case Anchor.Center: popupRect.position -= new Vector2(size.x * .5f, size.y * .5f); break;\n            }\n\n            return OverlayUtilities.ClampRectToRect(popupRect, containerRect);\n        }\n\n        void UpdatePosition(Vector2 size)\n        {\n            var targetRect = m_TargetRect;\n            var containerRect = parent.rect;\n\n            EnableInClassList(k_Clamped, size.x < containerRect.size.x || size.y < containerRect.size.y);\n\n            style.translate = PlaceNextToTarget(size, targetRect, containerRect, m_PopupAnchor, m_TargetAnchor, m_UseMargins ? m_Margin : Vector2.zero).position;\n        }\n\n        OverlayPopup(Overlay overlay, Rect targetRect, bool horizontal = true, bool includeMargins = false)\n        {\n            name = \"overlay-popup\";\n            this.overlay = overlay;\n            m_TargetRect = targetRect;\n            m_Horizontal = horizontal;\n            m_UseMargins = includeMargins;\n            Overlay.treeAsset.CloneTree(this);\n\n            this.Q(Overlay.k_CollapsedContent)?.RemoveFromHierarchy();\n            this.Q(null, Overlay.k_Header)?.RemoveFromHierarchy();\n\n            focusable = true;\n            pickingMode = PickingMode.Position;\n            AddToClassList(Overlay.ussClassName);\n            style.position = Position.Absolute;\n\n            Refresh();\n\n            RegisterCallback<MouseEnterEvent>(evt => m_CursorIsOverPopup = true);\n            RegisterCallback<MouseLeaveEvent>(evt => m_CursorIsOverPopup = false);\n            RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);\n        }\n\n        void OnGeometryChanged(GeometryChangedEvent evt)\n        {\n            // Only update when size changes\n            if (evt.oldRect.size == evt.newRect.size)\n                return;\n\n            if (m_ShouldRecalculateAnchors)\n            {\n                GetAnchors(m_TargetRect, parent.rect, m_Horizontal, evt.newRect.size, out m_PopupAnchor, out m_TargetAnchor, out m_Margin);\n                m_ShouldRecalculateAnchors = false;\n            }\n\n            UpdatePosition(evt.newRect.size);\n        }\n\n        public void Refresh()\n        {\n            var root = this.Q(\"overlay-content\");\n\n            root.Clear();\n\n            root.renderHints = RenderHints.ClipWithScissors;\n            style.maxHeight = StyleKeyword.Null;\n            style.maxWidth = StyleKeyword.Null;\n\n            root.Add(overlay.GetSimpleHeader());\n            root.Add(overlay.CreatePanelContent());\n\n            root.Focus();\n        }\n\n        public static OverlayPopup CreateUnderOverlay(Overlay overlay)\n        {\n            var popup = new OverlayPopup(overlay, overlay.canvas.rootVisualElement.WorldToLocal(overlay.collapsedButtonRect), !overlay.isInToolbar || overlay.activeLayout != Layout.VerticalToolbar, true);\n            popup.m_ShouldRecalculateAnchors = true;\n\n            if (overlay.layout == Layout.HorizontalToolbar)\n                popup.EnableInClassList(k_FromHorizontal, true);\n            else if (overlay.layout == Layout.VerticalToolbar)\n                popup.EnableInClassList(k_FromVertical, true);\n\n            if (!overlay.isInToolbar)\n                popup.EnableInClassList(k_OutsideToolbar, true);\n\n            return popup;\n        }\n\n        public static OverlayPopup CreateAtPosition(OverlayCanvas canvas, Overlay overlay, Vector2 position)\n        {\n            return new OverlayPopup(overlay, new Rect(canvas.rootVisualElement.WorldToLocal(position), Vector2.zero))\n            {\n                m_ShouldRecalculateAnchors = true,\n            };\n        }\n\n        public static OverlayPopup CreateAtCanvasCenter(OverlayCanvas canvas, Overlay overlay)\n        {\n            return new OverlayPopup(overlay, new Rect(canvas.rootVisualElement.rect.size / 2, Vector2.zero));\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayPopupWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.ComponentModel;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    // This is an ugly hack to get popup windows to close when clicking on a button while the popup is already open.\n    // The problem is that popup windows close when losing focus, which clicking the trigger button does. So the button\n    // is clicked, the window loses focus and closes, then the mouse up on button requests a new window.\n    [EditorBrowsable(EditorBrowsableState.Never)]\n    abstract class PopupWindowBase : EditorWindow\n    {\n        static double s_LastClosedTime;\n        static Rect s_LastActivatorRect;\n\n        static bool ShouldShowWindow(Rect activatorRect)\n        {\n            const double kJustClickedTime = 0.2;\n            bool justClosed = (EditorApplication.timeSinceStartup - s_LastClosedTime) < kJustClickedTime;\n            if (!justClosed || activatorRect != s_LastActivatorRect)\n            {\n                s_LastActivatorRect = activatorRect;\n                return true;\n            }\n            return false;\n        }\n\n        public static T Show<T>(VisualElement trigger, Vector2 size) where T : EditorWindow\n        {\n            return Show<T>(GUIUtility.GUIToScreenRect(trigger.worldBound), size);\n        }\n\n        public static T Show<T>(Rect activatorRect, Vector2 size) where T : EditorWindow\n        {\n            var windows = Resources.FindObjectsOfTypeAll<T>();\n\n            if (windows.Any())\n            {\n                foreach (var window in windows)\n                    window.Close();\n                return default;\n            }\n\n            if (ShouldShowWindow(activatorRect))\n            {\n                var popup = CreateInstance<T>();\n\n                popup.hideFlags = HideFlags.DontSave;\n                popup.ShowAsDropDown(activatorRect, size);\n                return popup;\n            }\n\n            return default;\n        }\n\n        void OnEnableINTERNAL()\n        {\n            AssemblyReloadEvents.beforeAssemblyReload += Close;\n        }\n\n        void OnDisableINTERNAL()\n        {\n            s_LastClosedTime = EditorApplication.timeSinceStartup;\n            AssemblyReloadEvents.beforeAssemblyReload -= Close;\n        }\n    }\n\n    abstract class OverlayPopupWindow : PopupWindowBase\n    {\n        const float k_BorderWidth = 1;\n\n        protected virtual void OnEnable()\n        {\n            Color borderColor = EditorGUIUtility.isProSkin ? new Color(0.44f, 0.44f, 0.44f, 1f) : new Color(0.51f, 0.51f, 0.51f);\n\n            rootVisualElement.style.borderLeftWidth = k_BorderWidth;\n            rootVisualElement.style.borderTopWidth = k_BorderWidth;\n            rootVisualElement.style.borderRightWidth = k_BorderWidth;\n            rootVisualElement.style.borderBottomWidth = k_BorderWidth;\n            rootVisualElement.style.borderLeftColor = borderColor;\n            rootVisualElement.style.borderTopColor = borderColor;\n            rootVisualElement.style.borderRightColor = borderColor;\n            rootVisualElement.style.borderBottomColor = borderColor;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayPreset.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor.Overlays\n{\n    sealed class OverlayPreset : ScriptableObject, IOverlayPreset, ISerializationCallbackReceiver\n    {\n        [SerializeField, HideInInspector]\n        string m_RawWindowType;\n\n        [SerializeField, HideInInspector]\n        SaveData[] m_SaveData;\n\n        Type m_TargetType;\n\n        public Type targetWindowType\n        {\n            get => m_TargetType;\n            set => m_TargetType = value;\n        }\n\n        public SaveData[] saveData\n        {\n            get => m_SaveData;\n            set => m_SaveData = value;\n        }\n\n        void OnEnable()\n        {\n            hideFlags = HideFlags.DontSave;\n        }\n\n        public void OnBeforeSerialize()\n        {\n            m_RawWindowType = targetWindowType.AssemblyQualifiedName;\n        }\n\n        public void OnAfterDeserialize()\n        {\n            targetWindowType = Type.GetType(m_RawWindowType);\n        }\n\n        public void ApplyCustomData(OverlayCanvas canvas) {}\n\n        public bool CanApplyToWindow(Type windowType)\n        {\n            return targetWindowType != null && targetWindowType.IsAssignableFrom(windowType);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayPresetManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor.Overlays\n{\n    interface IOverlayPreset\n    {\n        SaveData[] saveData { get; }\n        Type targetWindowType { get; }\n        bool CanApplyToWindow(Type windowType);\n        void ApplyCustomData(OverlayCanvas canvas);\n        string name { get; }\n    }\n\n    sealed class DefaultOverlayPreset : IOverlayPreset\n    {\n        readonly static SaveData[] m_EmptySave = new SaveData[0];\n\n        public SaveData[] saveData => m_EmptySave;\n        public Type targetWindowType => null;\n\n        public bool CanApplyToWindow(Type windowType) => true;\n\n        public void ApplyCustomData(OverlayCanvas canvas)\n        {\n            // We set these package overlays manually for backward compatibility now that we don't have a Default save file\n            if (canvas.TryGetOverlay(\"Scene View/Navmesh Display\", out var overlay)) overlay.displayed = false;\n            if (canvas.TryGetOverlay(\"Scene View/Agent Display\", out overlay)) overlay.displayed = false;\n            if (canvas.TryGetOverlay(\"Scene View/Obstacle Display\", out overlay)) overlay.displayed = false;\n            if (canvas.TryGetOverlay(\"Scene View/Occlusion Culling\", out overlay)) overlay.displayed = false;\n        }\n\n        public string name => OverlayPresetManager.defaultPresetName;\n    }\n\n    // This is responsible for loading and saving OverlayPresets. It does not serialize presets in the manager, but\n    // rather loads and saves from the various locations that presets can exist.\n    sealed class OverlayPresetManager : ScriptableSingleton<OverlayPresetManager>\n    {\n        static Dictionary<Type, Dictionary<string, OverlayPreset>> loadedPresets => instance.m_Presets;\n\n        [NonSerialized]\n        Dictionary<Type, Dictionary<string, OverlayPreset>> m_Presets;\n\n        const string k_FileExtension = \"overlay\";\n        const string k_PresetAssetsName = \"OverlayPresets.asset\";\n        internal const string defaultPresetName = \"Default\";\n        static string k_PreferencesAssetPath => Path.Combine(InternalEditorUtility.unityPreferencesFolder, \"OverlayPresets/\" + k_PresetAssetsName);\n        static string k_ResourcesAssetPath => Path.Combine(EditorApplication.applicationContentsPath, \"Resources/OverlayPresets/\" + k_PresetAssetsName);\n        static string preferencesPath => FileUtil.CombinePaths(InternalEditorUtility.unityPreferencesFolder, \"OverlayPresets\");\n\n        void OnEnable()\n        {\n            AssemblyReloadEvents.beforeAssemblyReload += CleanUpPresets;\n            ReloadAllPresets();\n        }\n\n        internal static void SaveOverlayStateToFile(string path, EditorWindow window)\n        {\n            var preset = CreateInstance<OverlayPreset>();\n            preset.name = Path.GetFileNameWithoutExtension(path);\n            preset.targetWindowType = window.GetType();\n            window.overlayCanvas.CopySaveData(out var saveData);\n            preset.saveData = saveData;\n\n            try\n            {\n                SaveToFile(new List<OverlayPreset> {preset}, path);\n            }\n            finally\n            {\n                DestroyImmediate(preset);\n            }\n        }\n\n        internal static OverlayPreset CreatePresetFromOverlayState(string presetName, EditorWindow window)\n        {\n            var windowType = window.GetType();\n            if (!TryGetPreset(windowType, presetName, out var preset))\n            {\n                preset = CreateInstance<OverlayPreset>();\n                preset.name = presetName;\n                preset.targetWindowType = windowType;\n\n                AddPreset(preset);\n            }\n\n            window.overlayCanvas.CopySaveData(out var data);\n            preset.saveData = data;\n            SaveAllPreferences();\n\n            return preset;\n        }\n\n        static void AddPreset(OverlayPreset preset)\n        {\n            if (!loadedPresets.TryGetValue(preset.targetWindowType, out var presets))\n                loadedPresets.Add(preset.targetWindowType, presets = new Dictionary<string, OverlayPreset>());\n\n            if (!presets.ContainsKey(preset.name))\n                presets.Add(preset.name, preset);\n            else\n                presets[preset.name] = preset;\n        }\n\n        // used by tests\n        internal static void RevertPreferencesPresetsToDefault()\n        {\n            if (File.Exists(k_PreferencesAssetPath))\n                FileUtil.DeleteFileOrDirectory(k_PreferencesAssetPath);\n        }\n\n        static void SaveAllPreferences()\n        {\n            List<OverlayPreset> presets = new List<OverlayPreset>();\n            foreach (var presetsForWindow in loadedPresets)\n            {\n                foreach (var preset in presetsForWindow.Value)\n                {\n                    presets.Add(preset.Value);\n                }\n            }\n            SaveToFile(presets, k_PreferencesAssetPath);\n        }\n\n        internal static void DeletePreset(OverlayPreset preset)\n        {\n            if (preset != null && preset.targetWindowType != null\n                && loadedPresets.TryGetValue(preset.targetWindowType, out var presets)\n                && presets.Remove(preset.name))\n            {\n                DestroyImmediate(preset);\n                SaveAllPreferences();\n            }\n        }\n\n        internal static bool TryGetPreset(Type windowType, string presetName, out OverlayPreset preset)\n        {\n            var currentType = windowType;\n            while (currentType != null)\n            {\n                if (loadedPresets.TryGetValue(currentType, out var p))\n                    if (p.TryGetValue(presetName, out preset))\n                        return true;\n\n                currentType = currentType.BaseType;\n            }\n            foreach (var i in windowType.GetInterfaces())\n            {\n                if (loadedPresets.TryGetValue(i, out var p))\n                    if (p.TryGetValue(presetName, out preset))\n                        return true;\n            }\n\n            preset = null;\n            return false;\n        }\n\n        public static bool Exists(Type windowType, string presetName)\n        {\n            return TryGetPreset(windowType, presetName, out _);\n        }\n\n        public static IOverlayPreset GetDefaultPreset(Type windowType)\n        {\n            if (TryGetPreset(windowType, defaultPresetName, out OverlayPreset preset))\n                return preset;\n\n            return new DefaultOverlayPreset();\n        }\n\n        internal static IEnumerable<IOverlayPreset> GetAllPresets(Type windowType)\n        {\n            List<IOverlayPreset> presets = new List<IOverlayPreset>();\n\n            // Add a default preset if the user hasn't overwritten it\n            if (!TryGetPreset(windowType, defaultPresetName, out OverlayPreset preset))\n                presets.Add(new DefaultOverlayPreset());\n\n            foreach (var i in windowType.GetInterfaces())\n            {\n                if (loadedPresets.TryGetValue(i, out var p))\n                    presets.AddRange(p.Values);\n            }\n\n            while (windowType != null && typeof(EditorWindow).IsAssignableFrom(windowType))\n            {\n                if (loadedPresets.TryGetValue(windowType, out var p))\n                    presets.AddRange(p.Values);\n\n                windowType = windowType.BaseType;\n            }\n\n            return presets;\n        }\n\n        internal static void ReloadAllPresets()\n        {\n            CleanUpPresets();\n            instance.m_Presets = LoadAllPresets();\n        }\n\n        static void CleanUpPresets()\n        {\n            // Ensure that no zombie overlay presets remains\n            foreach (var preset in Resources.FindObjectsOfTypeAll<OverlayPreset>())\n            {\n                if (!EditorUtility.IsPersistent(preset))\n                    DestroyImmediate(preset);\n            }\n        }\n\n        static Dictionary<Type, Dictionary<string, OverlayPreset>> LoadAllPresets()\n        {\n            var results = new Dictionary<Type, Dictionary<string, OverlayPreset>>();\n\n            if (!Directory.Exists(preferencesPath))\n                Directory.CreateDirectory(preferencesPath);\n            if (!File.Exists(k_PreferencesAssetPath))\n                RevertPreferencesPresetsToDefault();\n\n            List<Object> loaded = new List<Object>(64);\n\n            // load preference based presets\n            var builtin = InternalEditorUtility.LoadSerializedFileAndForget(k_PreferencesAssetPath);\n\n            // this is necessary for users who tried out overlays preview builds. the registered class ID changed\n            // from 13987 to 13988 during development. we correct that case here. can remove this check in 2022.\n            if (builtin.Length < 1)\n            {\n                RevertPreferencesPresetsToDefault();\n                builtin = InternalEditorUtility.LoadSerializedFileAndForget(k_PreferencesAssetPath);\n            }\n\n            loaded.AddRange(builtin);\n\n            foreach (var rawPreset in loaded)\n            {\n                var preset = rawPreset as OverlayPreset;\n\n                if (preset != null && preset.targetWindowType != null)\n                {\n                    if (!results.TryGetValue(preset.targetWindowType, out var presets))\n                    {\n                        presets = new Dictionary<string, OverlayPreset>();\n                        results.Add(preset.targetWindowType, presets);\n                    }\n\n                    if (presets.ContainsKey(preset.name))\n                    {\n                        Debug.LogWarning($\"Failed to load the overlay preset with name {preset.name}. A preset with that name already existed in that window type.\");\n                        continue;\n                    }\n                    presets.Add(preset.name, preset);\n                }\n            }\n\n            return results;\n        }\n\n        internal static void SaveToFile(IList<OverlayPreset> presets, string path)\n        {\n            var parentLayoutFolder = Path.GetDirectoryName(path);\n\n            if (!string.IsNullOrEmpty(parentLayoutFolder))\n            {\n                if (!Directory.Exists(parentLayoutFolder))\n                    Directory.CreateDirectory(parentLayoutFolder);\n                InternalEditorUtility.SaveToSerializedFileAndForget(presets.Cast<Object>().ToArray(), path, true);\n            }\n        }\n\n        internal static OverlayPreset LoadFromFile(string path)\n        {\n            if (Path.GetExtension(path) != \".\" + k_FileExtension)\n            {\n                Debug.LogFormat(L10n.Tr(\"Overlay preset files must have the {0} extension to be valid.\"), k_FileExtension);\n                return null;\n            }\n            var rawPresets = InternalEditorUtility.LoadSerializedFileAndForget(path);\n            if (rawPresets != null)\n            {\n                //Get the first preset in the file. .overlay files should only ever contained one\n                foreach (var rawPreset in rawPresets)\n                {\n                    if (rawPreset is OverlayPreset preset)\n                    {\n                        preset.name = Path.GetFileNameWithoutExtension(path);\n                        return preset;\n                    }\n                }\n            }\n\n            return null;\n        }\n\n        public static void GenerateMenu(IGenericMenu menu, string pathPrefix, EditorWindow window)\n        {\n            var presets = GetAllPresets(window.GetType());\n            foreach (var preset in presets)\n            {\n                menu.AddItem(pathPrefix + preset.name, false, () =>\n                {\n                    window.overlayCanvas.ApplyPreset(preset);\n                });\n            }\n\n            menu.AddSeparator(pathPrefix);\n\n            menu.AddItem(L10n.Tr($\"{pathPrefix}Save Preset...\"), false, () =>\n            {\n                SaveOverlayPreset.ShowWindow(window, name =>\n                {\n                    var preset = CreatePresetFromOverlayState(name, window);\n                    SaveAllPreferences();\n                    window.overlayCanvas.ApplyPreset(preset);\n                });\n            });\n\n            menu.AddItem(L10n.Tr($\"{pathPrefix}Save Preset To File...\"), false, () =>\n            {\n                string path = EditorUtility.SaveFilePanel(\"Save window preset to disk...\", \"\", \"NewOverlayPreset\", k_FileExtension);\n                if (!string.IsNullOrEmpty(path))\n                {\n                    SaveOverlayStateToFile(path, window);\n                    EditorUtility.RevealInFinder(path);\n                }\n            });\n\n            menu.AddItem(L10n.Tr($\"{pathPrefix}Load Preset From File...\"), false, () =>\n            {\n                var filePath = EditorUtility.OpenFilePanel(\"Load preset from disk...\", \"\", k_FileExtension);\n                if (!string.IsNullOrEmpty(filePath))\n                {\n                    var preset = LoadFromFile(filePath);\n                    bool failed = false;\n                    if (preset == null)\n                    {\n                        EditorUtility.DisplayDialog(\n                            L10n.Tr(\"Load Overlay Preset From Disk\"),\n                            string.Format(L10n.Tr(\"Failed to load the chosen preset, the file may not be a .{0} or was corrupted.\"), k_FileExtension),\n                            L10n.Tr(\"OK\"));\n                        failed = true;\n                    }\n                    else if (!preset.CanApplyToWindow(window.GetType()))\n                    {\n                        EditorUtility.DisplayDialog(\n                            L10n.Tr(\"Load Overlay Preset From Disk\"),\n                            string.Format(L10n.Tr(\"Trying to load an overlay preset with the name {0}. This preset targets the window type {0} which isn't valid for this window.\"), preset.targetWindowType),\n                            L10n.Tr(\"OK\"));\n                        failed = true;\n                    }\n\n                    if (Exists(preset.targetWindowType, preset.name))\n                    {\n                        if (!EditorUtility.DisplayDialog(\n                            L10n.Tr(\"Load Overlay Preset From Disk\"),\n                            string.Format(L10n.Tr(\"Trying to load an overlay preset with the name {0}. This name is already in used in the window, do you want to overwrite it?\"), preset.name),\n                            L10n.Tr(\"Yes\"), L10n.Tr(\"No\")))\n                        {\n                            failed = true;\n                        }\n                    }\n\n                    if (failed)\n                    {\n                        if (!EditorUtility.IsPersistent(preset))\n                            DestroyImmediate(preset);\n                        return;\n                    }\n\n                    AddPreset(preset);\n                    window.overlayCanvas.ApplyPreset(preset);\n                }\n            });\n\n            foreach (var rawPreset in presets)\n            {\n                // Only add the ability to delete asset presets and not the ones created from code\n                if (rawPreset is OverlayPreset preset)\n                {\n                    menu.AddItem(L10n.Tr($\"{pathPrefix}Delete Preset/{preset.name}\"), false, () =>\n                    {\n\t                    DeletePreset(preset);\n\t                    window.overlayCanvas.SetLastAppliedPresetName(OverlayCanvas.k_DefaultPresetName);\n\t                    window.overlayCanvas.afterOverlaysInitialized.Invoke();\n                    });\n                }\n            }\n\n            menu.AddItem(L10n.Tr($\"{pathPrefix}Revert All Saved Presets\"), false, () =>\n            {\n                if (EditorUtility.DisplayDialog(\n                    L10n.Tr(\"Revert All Saved Presets\"),\n                    L10n.Tr(\"Unity is about to delete all overlay presets that are not loaded from files in project and restore default settings.\"),\n                    L10n.Tr(\"Continue\"), L10n.Tr(\"Cancel\")))\n                {\n                    RevertPreferencesPresetsToDefault();\n                    ReloadAllPresets();\n                    window.overlayCanvas.ApplyPreset(GetDefaultPreset(window.GetType()));\n                }\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayResizer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing Cursor = UnityEngine.UIElements.Cursor;\n\nnamespace UnityEditor.Overlays\n{\n    class OverlayResizerGroup : VisualElement\n    {\n        const float k_CornerSize = 8;\n        const float k_SideSize = 6;\n        const float k_MinDistanceFromEdge = 10;\n\n        [Flags]\n        enum Direction\n        {\n            Left = 1 << 0,\n            Bottom = 1 << 1,\n            Top = 1 << 2,\n            Right = 1 << 3,\n\n            TopLeft = Top | Left,\n            TopRight = Top | Right,\n            BottomLeft = Bottom | Left,\n            BottomRight = Bottom | Right,\n        }\n\n        class OverlayResizer : VisualElement\n        {\n            readonly Direction m_Direction;\n            readonly Overlay m_Overlay;\n            readonly bool m_ModifyPosition;\n\n            Vector2 m_OriginalMousePosition;\n            Rect m_OriginalRect;\n            Rect m_ContainerRect;\n            Vector2 m_MinSize;\n            Vector2 m_MaxSize;\n            bool m_Active;\n\n            public OverlayResizer(Overlay overlay, Direction direction)\n            {\n                m_Overlay = overlay;\n                m_Direction = direction;\n\n                style.position = Position.Absolute;\n\n                bool hasLeft = HasDirection(Direction.Left);\n                bool hasRight = HasDirection(Direction.Right);\n                bool hasTop = HasDirection(Direction.Top);\n                bool hasBottom = HasDirection(Direction.Bottom);\n                bool isCorner = HasMultipleDirections();\n\n                var size = isCorner ? k_CornerSize : k_SideSize;\n\n                if (hasLeft) style.left = -size * .5f;\n                if (hasRight) style.right = -size * .5f;\n                if (hasTop) style.top = -size * .5f;\n                if (hasBottom) style.bottom = -size * .5f;\n\n                style.width = hasLeft || hasRight ? size : new Length(100, LengthUnit.Percent);\n                style.height = hasTop || hasBottom ? size : new Length(100, LengthUnit.Percent);\n\n                m_ModifyPosition = HasDirection(Direction.Left) || HasDirection(Direction.Top);\n\n                style.cursor = new Cursor { defaultCursorId = (int)GetCursor(direction) };\n\n                RegisterCallback<MouseDownEvent>(OnMouseDown);\n                RegisterCallback<MouseMoveEvent>(OnMouseMove);\n                RegisterCallback<MouseUpEvent>(OnMouseUp);\n            }\n\n            void OnMouseDown(MouseDownEvent evt)\n            {\n                var container = m_Overlay.rootVisualElement.GetFirstAncestorOfType<OverlayContainer>();\n\n\n                var overlayPosition = m_Overlay.rootVisualElement.layout.position;\n                if (container != null)\n                    overlayPosition = m_Overlay.rootVisualElement.parent.ChangeCoordinatesTo(container, overlayPosition);\n\n                m_OriginalRect = new Rect(\n                    m_Overlay.floating ?  m_Overlay.floatingPosition : overlayPosition,\n                    m_Overlay.size);\n\n                m_ContainerRect = container?.rect ?? new Rect(float.NegativeInfinity,float.NegativeInfinity,float.PositiveInfinity,float.PositiveInfinity);\n                m_OriginalMousePosition = evt.mousePosition;\n                m_MaxSize = m_Overlay.maxSize;\n                m_MinSize = m_Overlay.minSize;\n\n                this.CaptureMouse();\n                evt.StopPropagation();\n                m_Active = true;\n            }\n\n            void OnMouseMove(MouseMoveEvent evt)\n            {\n                if (m_Active)\n                {\n                    var translation = evt.mousePosition - m_OriginalMousePosition;\n                    var rect = ResizeRect(m_OriginalRect, translation);\n\n                    m_Overlay.size = rect.size;\n\n                    if (m_ModifyPosition && m_Overlay.floating)\n                        m_Overlay.floatingPosition = rect.position;\n\n                    evt.StopPropagation();\n                }\n            }\n\n            void OnMouseUp(MouseUpEvent evt)\n            {\n                if (m_Active)\n                {\n                    evt.StopPropagation();\n                    this.ReleaseMouse();\n                    m_Active = false;\n                }\n            }\n\n            Rect ResizeRect(Rect rect, Vector2 delta)\n            {\n                delta = ClampDeltaToMinMax(delta, rect);\n                if (HasDirection(Direction.Left))\n                    rect.xMin = Mathf.Max(m_ContainerRect.xMin, rect.xMin + delta.x);\n                else if (HasDirection(Direction.Right))\n                    rect.xMax = Mathf.Min(m_ContainerRect.xMax, rect.xMax + delta.x);\n\n                if (HasDirection(Direction.Top))\n                    rect.yMin = Mathf.Max(m_ContainerRect.yMin, rect.yMin + delta.y);\n                else if (HasDirection(Direction.Bottom))\n                    rect.yMax = Mathf.Min(m_ContainerRect.yMax, rect.yMax + delta.y);\n\n                return rect;\n            }\n\n            Vector2 ClampDeltaToMinMax(Vector2 delta, Rect rect)\n            {\n                if (HasDirection(Direction.Left))\n                    delta.x = rect.width - Mathf.Clamp(rect.width - delta.x, m_MinSize.x, m_MaxSize.x);\n                else if (HasDirection(Direction.Right))\n                    delta.x = Mathf.Clamp(rect.width + delta.x, m_MinSize.x, m_MaxSize.x) - rect.width;\n\n                if (HasDirection(Direction.Top))\n                    delta.y = rect.height - Mathf.Clamp(rect.height - delta.y, m_MinSize.y, m_MaxSize.y);\n                else if (HasDirection(Direction.Bottom))\n                    delta.y = Mathf.Clamp(rect.height + delta.y, m_MinSize.y, m_MaxSize.y) - rect.height;\n\n                return delta;\n            }\n\n            static MouseCursor GetCursor(Direction direction)\n            {\n                MouseCursor cursorStyle = MouseCursor.Arrow;\n\n                switch (direction)\n                {\n                    case Direction.TopLeft:\n                    case Direction.BottomRight:\n                        cursorStyle = MouseCursor.ResizeUpLeft;\n                        break;\n                    case Direction.TopRight:\n                    case Direction.BottomLeft:\n                        cursorStyle = MouseCursor.ResizeUpRight;\n                        break;\n                    case Direction.Left:\n                    case Direction.Right:\n                        cursorStyle = MouseCursor.ResizeHorizontal;\n                        break;\n                    case Direction.Top:\n                    case Direction.Bottom:\n                        cursorStyle = MouseCursor.ResizeVertical;\n                        break;\n\n                }\n                return cursorStyle;\n            }\n\n            public bool HasDirection(Direction target)\n            {\n                return (m_Direction & target) == target;\n            }\n\n            public bool HasMultipleDirections()\n            {\n                return (m_Direction & (m_Direction - 1)) != 0;\n            }\n        }\n\n        readonly Overlay m_Overlay;\n        readonly OverlayResizer[] m_Resizers;\n\n        public OverlayResizerGroup(Overlay overlay)\n        {\n            this.StretchToParentSize();\n            pickingMode = PickingMode.Ignore;\n\n            m_Resizers = new []\n            {\n                new OverlayResizer(overlay, Direction.Top) { name = \"ResizerTop\" },\n                new OverlayResizer(overlay, Direction.Bottom) { name = \"ResizerBottom\" },\n                new OverlayResizer(overlay, Direction.Left) { name = \"ResizerLeft\" },\n                new OverlayResizer(overlay, Direction.Right) { name = \"ResizerRight\" },\n                new OverlayResizer(overlay, Direction.TopLeft) { name = \"ResizerTopLeft\" },\n                new OverlayResizer(overlay, Direction.TopRight) { name = \"ResizerTopRight\" },\n                new OverlayResizer(overlay, Direction.BottomLeft) { name = \"ResizerBottomLeft\" },\n                new OverlayResizer(overlay, Direction.BottomRight) { name = \"ResizerBottomRight\" },\n            };\n\n            m_Overlay = overlay;\n            foreach (var resizer in m_Resizers)\n                Add(resizer);\n\n            overlay.containerChanged += OnOverlayContainerChanged;\n            overlay.layoutChanged += OnOverlayLayoutChanged;\n            overlay.floatingPositionChanged += OnOverlayPositionChanged;\n            overlay.collapsedChanged += OnOverlayCollaspedChanged;\n            overlay.dockingCompleted += OnOverlayDockingCompleted;\n            overlay.rootVisualElement.RegisterCallback<AttachToPanelEvent>(OnAttachedToPanel);\n            overlay.rootVisualElement.RegisterCallback<DetachFromPanelEvent>(OnDetachedFromPanel);\n            overlay.rootVisualElement.RegisterCallback<GeometryChangedEvent>(OnOverlayGeometryChanged);\n            \n            UpdateResizerVisibility();\n        }\n\n        void OnOverlayLayoutChanged(Layout layout)\n        {\n            UpdateResizerVisibility();\n        }\n\n        void OnOverlayContainerChanged(OverlayContainer container)\n        {\n            UpdateResizerVisibility();\n        }\n\n        void OnOverlayGeometryChanged(GeometryChangedEvent evt)\n        {\n            UpdateResizerVisibility();\n        }\n\n        void OnOverlayPositionChanged(Vector3 position)\n        {\n            UpdateResizerVisibility();\n        }\n\n        void OnOverlayCollaspedChanged(bool collapsed)\n        {\n            UpdateResizerVisibility();\n        }\n\n        void OnOverlayDockingCompleted(OverlayContainer container)\n        {\n            TryConstrainResizableOverlaySize();\n        }\n        \n        void OnAttachedToPanel(AttachToPanelEvent evt)\n        {\n            m_Overlay.canvas.rootVisualElement.RegisterCallback<GeometryChangedEvent>(OnOverlayCanvasGeometryChanged);\n        }\n\n        void OnDetachedFromPanel(DetachFromPanelEvent evt)\n        {\n            m_Overlay.canvas.rootVisualElement.UnregisterCallback<GeometryChangedEvent>(OnOverlayCanvasGeometryChanged);\n        }\n        \n        void OnOverlayCanvasGeometryChanged(GeometryChangedEvent evt)\n        {\n            TryConstrainResizableOverlaySize();\n        }\n        \n        void TryConstrainResizableOverlaySize()\n        {\n            if (!m_Overlay.IsResizable() || !m_Overlay.sizeOverridden)\n                return;\n            \n            var container = m_Overlay.rootVisualElement.GetFirstAncestorOfType<OverlayContainer>() ?? m_Overlay.container;\n            if (container == null || m_Overlay.rootVisualElement.parent == null)\n                return;\n\n            var cornerDocked = container is not FloatingOverlayContainer && container is not ToolbarOverlayContainer;\n            var largerThanContainer = (m_Overlay.size.x > container.rect.width || m_Overlay.size.y > container.rect.height);\n            \n            if (cornerDocked && largerThanContainer)\n                m_Overlay.size = new Vector2(Mathf.Min(m_Overlay.size.x, container.rect.width), Mathf.Min(m_Overlay.size.y, container.rect.height));\n        }\n\n        bool ContainerCanShowResizer(OverlayResizer resizer)\n        {\n            var container = m_Overlay.container;\n            if (container == null)\n                return false;\n\n            if (container is FloatingOverlayContainer)\n                return true;\n\n            if (container is ToolbarOverlayContainer)\n                return false;\n\n            var alignment = container.resolvedStyle.alignItems;\n            bool hide = false;\n\n            // Check the opposite direction. If the content is align to one side, hide resizer on that side\n            switch (alignment)\n            {\n                case Align.FlexStart:\n                    hide |= resizer.HasDirection(container.isHorizontal ? Direction.Top : Direction.Left);\n                    break;\n\n                case Align.FlexEnd:\n                    hide |= resizer.HasDirection(container.isHorizontal ? Direction.Bottom : Direction.Right);\n                    break;\n            }\n\n            return !hide;\n        }\n\n        void UpdateResizerVisibility()\n        {\n            bool globalHide = !m_Overlay.IsResizable();\n            foreach (var resizer in m_Resizers)\n            {\n                bool hide = globalHide || !ContainerCanShowResizer(resizer);\n\n                if (resizer.HasMultipleDirections())\n                {\n                    hide |= Mathf.Approximately(m_Overlay.minSize.x, m_Overlay.maxSize.x);\n                    hide |= Mathf.Approximately(m_Overlay.minSize.y, m_Overlay.maxSize.y);\n                }\n                else\n                {\n                    if (resizer.HasDirection(Direction.Left) || resizer.HasDirection(Direction.Right))\n                        hide |= Mathf.Approximately(m_Overlay.minSize.x, m_Overlay.maxSize.x);\n\n                    if (resizer.HasDirection(Direction.Top) || resizer.HasDirection(Direction.Bottom))\n                        hide |= Mathf.Approximately(m_Overlay.minSize.y, m_Overlay.maxSize.y);\n                }\n\n                if (m_Overlay.canvas != null)\n                {\n                    var canvas = m_Overlay.canvas.rootVisualElement;\n                    var canvasRect = canvas.rect;\n                    var overlayRect = canvas.WorldToLocal(m_Overlay.rootVisualElement.worldBound);\n\n                    if (resizer.HasDirection(Direction.Left))\n                        hide |= overlayRect.xMin <= k_MinDistanceFromEdge;\n\n                    if (resizer.HasDirection(Direction.Right))\n                        hide |= overlayRect.xMax >= canvasRect.xMax - k_MinDistanceFromEdge;\n\n                    if (resizer.HasDirection(Direction.Top))\n                        hide |= overlayRect.yMin <= k_MinDistanceFromEdge;\n\n                    if (resizer.HasDirection(Direction.Bottom))\n                        hide |= overlayRect.yMax >= canvasRect.yMax - k_MinDistanceFromEdge;\n                }\n\n\n                resizer.style.display = hide ? DisplayStyle.None : DisplayStyle.Flex;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayToolbar.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n\nusing UnityEditor.Toolbars;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    public class OverlayToolbar : VisualElement\n    {\n        public OverlayToolbar()\n        {\n            EditorToolbarUtility.LoadStyleSheets(\"EditorToolbar\", this);\n            AddToClassList(\"unity-toolbar-overlay\");\n        }\n\n        public void SetupChildrenAsButtonStrip()\n        {\n            EditorToolbarUtility.SetupChildrenAsButtonStrip(this);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/OverlayUtilities.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing System.Text.RegularExpressions;\nusing UnityEditor.EditorTools;\nusing UnityEngine;\n\nnamespace UnityEditor.Overlays\n{\n    public interface ISupportsOverlays {}\n\n    static class OverlayUtilities\n    {\n        internal class OverlayEditorWindowAssociation\n        {\n            public Type overlay;\n            public Type editorWindowType;\n            public string overlayId;\n        }\n\n        static OverlayEditorWindowAssociation[] s_Overlays;\n        static readonly Dictionary<Type, List<Type>> s_OverlaysTypeAssociations = new Dictionary<Type, List<Type>>();\n        internal const string nullWindowTypeErrorMsg = \"{0} editor window type cannot be null.\";\n        const float k_ClampOffset = 0.001f; //Used to make sure we're not clamping exactly on the bounds (which was causing issues)\n\n        static OverlayEditorWindowAssociation[] overlays\n        {\n            get\n            {\n                if (s_Overlays == null)\n                {\n                    Type[] ovrls = TypeCache.GetTypesWithAttribute<OverlayAttribute>()\n                        .Where(x => !x.IsAbstract)\n                        .ToArray();\n\n                    int len = ovrls.Length;\n                    var overlayWindows = new List<OverlayEditorWindowAssociation>(len);\n\n                    for (int i = 0; i < len; i++)\n                    {\n                        var overlayAttribute = (OverlayAttribute)ovrls[i].GetCustomAttributes(typeof(OverlayAttribute), false).FirstOrDefault();\n\n                        // Overlays that are implemented as instances don't need to define a target editor window.\n                        if (overlayAttribute?.editorWindowType == null)\n                            continue;\n\n                        overlayWindows.Add(new OverlayEditorWindowAssociation\n                        {\n                            overlay = ovrls[i],\n                            editorWindowType = overlayAttribute.editorWindowType,\n                            overlayId = overlayAttribute.id\n                        });\n                    }\n\n                    s_Overlays = overlayWindows.ToArray();\n                }\n\n                return s_Overlays;\n            }\n        }\n\n        // This ensures that the rect is at least partly contained within the boundary. Use ClampRectToRect if the rect needs to be fully within.\n        public static Rect EnsureRectOverlapsRect(Rect rect, Rect boundary)\n        {\n            if (rect.x > boundary.xMax)\n                rect.x = boundary.xMax;\n\n            if (rect.xMax < boundary.xMin)\n                rect.x = (boundary.xMin) - rect.width;\n\n            if (rect.y > boundary.yMax)\n                rect.y = boundary.yMax;\n\n            if (rect.y < boundary.yMin)\n                rect.y = boundary.yMin;\n\n            return rect;\n        }\n\n        public static Rect ClampRectToRect(Rect rect, Rect clampingRect)\n        {\n            rect.position -= rect.max - ClampPositionToRect(rect.max, clampingRect);\n            rect.position = ClampPositionToRect(rect.position, clampingRect);\n            return rect;\n        }\n\n        public static Vector2 ClampPositionToRect(Vector2 position, Rect clampingRect)\n        {\n            //keep mouse position within bounds for picking, mathf.epsilon is too small\n            position.x = Mathf.Clamp(position.x, clampingRect.xMin + k_ClampOffset,\n                clampingRect.xMax - k_ClampOffset);\n            position.y = Mathf.Clamp(position.y, clampingRect.yMin + k_ClampOffset,\n                clampingRect.yMax - k_ClampOffset);\n            return position;\n        }\n\n        static bool OverlayWindowTypeEquatesTo(Type windowType, Type overlayWindowType)\n        {\n            return overlayWindowType != null && overlayWindowType.IsAssignableFrom(windowType);\n        }\n\n        internal static List<Type> GetOverlaysForType(Type windowType, Func<OverlayEditorWindowAssociation, bool> filter = null)\n        {\n            List<Type> res;\n\n            if (s_OverlaysTypeAssociations.TryGetValue(windowType, out res))\n                return res;\n\n            s_OverlaysTypeAssociations.Add(windowType, res = new List<Type>());\n\n            for (int i = 0, c = overlays.Length; i < c; i++)\n            {\n                var shouldAddOverlayType = filter == null ?\n                    OverlayWindowTypeEquatesTo(windowType, overlays[i].editorWindowType) :\n                    OverlayWindowTypeEquatesTo(windowType, overlays[i].editorWindowType) && filter(overlays[i]);\n                if (shouldAddOverlayType)\n                    res.Add(overlays[i].overlay);\n            }\n\n            return res;\n        }\n\n        public static OverlayAttribute GetAttribute(Type window, Type overlay)\n        {\n            return overlay.GetCustomAttribute<OverlayAttribute>() ?? new OverlayAttribute(window, overlay.Name);\n        }\n\n        public static Overlay CreateOverlay(Type type)\n        {\n            Overlay overlay = null;\n\n            // Reflection is super slow, avoid it if this this a known type.\n            if (type == typeof(EditorToolSettingsOverlay))\n                overlay = new EditorToolSettingsOverlay();\n            else if (type == typeof(SearchToolBar))\n                overlay = new SearchToolBar();\n            else if (type == typeof(TransformToolsOverlayToolBar))\n                overlay = new TransformToolsOverlayToolBar();\n            else if (type == typeof(SceneViewToolBar))\n                overlay = new SceneViewToolBar();\n            else if (type == typeof(SceneViewCameraModeToolbar))\n                overlay = new SceneViewCameraModeToolbar();\n            else if (type == typeof(GridAndSnapToolBar))\n                overlay = new GridAndSnapToolBar();\n            else\n            {\n                var ctor = type.GetConstructor(\n                    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,\n                    null,\n                    Type.EmptyTypes, null);\n\n                overlay = ctor?.Invoke(null) as Overlay;\n\n                if (overlay == null)\n                {\n                    Debug.LogWarning($\"Overlay of type {type} can not be instantiated. Make sure this type contains a \" +\n                        \"parameter-less constructor and inherits the Overlay type.\");\n                    return null;\n                }\n            }\n\n            overlay.Initialize(GetAttribute(null, type));\n            return overlay;\n        }\n\n        internal static bool GetIsDefaultDisplayFromAttribute(Type type)\n        {\n            if (Attribute.IsDefined(type, typeof(OverlayAttribute)))\n            {\n                var attributes = type.GetCustomAttributes(typeof(OverlayAttribute), true);\n                for (int i = 0, c = attributes.Length; i < c; i++)\n                    if (attributes[i] is OverlayAttribute)\n                        return ((OverlayAttribute)attributes[i]).defaultDisplay;\n            }\n            return false;\n        }\n\n        internal static string GetDisplayNameFromAttribute(Type type)\n        {\n            if (Attribute.IsDefined(type, typeof(OverlayAttribute)))\n            {\n                var attributes = type.GetCustomAttributes(typeof(OverlayAttribute), true);\n                for (int i = 0, c = attributes.Length; i < c; i++)\n                    if (attributes[i] is OverlayAttribute)\n                        return ((OverlayAttribute)attributes[i]).displayName;\n            }\n            return string.Empty;\n        }\n\n        internal static string GetSignificantLettersForIcon(string s)\n        {\n            if (string.IsNullOrEmpty(s))\n                return string.Empty;\n\n            var folders = s.Split('/');\n            var last = folders[folders.Length - 1];\n            if (string.IsNullOrEmpty(last))\n                return string.Empty;\n\n            var words = last.Trim().Split(' ');\n            if (words.Length == 1)\n            {\n                var regex = new Regex(@\"[A-Z][^A-Z]*\", RegexOptions.Compiled);\n                var matches = regex.Matches(words[0]);\n                if (matches == null || matches.Count == 0)\n                    return words[0].Length > 1 ? words[0].Substring(0, 2) : words[0][0].ToString();\n\n                if (matches.Count == 1)\n                    return matches[0].Length > 1 ? matches[0].Value.Substring(0, 2) : matches[0].Value[0].ToString();\n\n                return matches[0].Value.Substring(0, 1) + matches[1].Value.Substring(0, 1);\n            }\n\n            return words[0].Substring(0, 1) + words[1].Substring(0, 1);\n        }\n\n        internal static bool EnsureValidId(IEnumerable<Overlay> existing, Overlay overlay)\n        {\n            if (overlay == null)\n                return false;\n            var id = string.IsNullOrEmpty(overlay.id) ? $\"{overlay.GetType()}\" : overlay.id;\n            var ret = EnsureUniqueId(existing.Select(x => x.id), id);\n            if (string.IsNullOrEmpty(ret))\n                return false;\n            overlay.id = ret;\n            return true;\n        }\n\n        static string EnsureUniqueId(IEnumerable<string> existing, string name)\n        {\n            if (!existing.Contains(name))\n                return name;\n\n            // 256 has no special meaning, it's just a failsafe to prevent this method from locking up the editor\n            // in the event that someone is incorrectly using AddOverlay. We'll throw an exception in EnsureValidId\n            // to let the user know that they're doing it wrong (there aren't many legitimate cases for more than a\n            // couple overlays of the same type, let alone 100+).\n            for (int n = 0; n < 256; ++n)\n            {\n                var inc = $\"{name} ({n})\";\n                if (!existing.Contains(inc))\n                    return inc;\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/SaveOverlayPreset.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing UnityEngine;\n\nnamespace UnityEditor.Overlays\n{\n    [EditorWindowTitle(title = \"Save Window Preset\")]\n    sealed class SaveOverlayPreset : EditorWindow\n    {\n        bool m_DidFocus;\n        const int k_Width = 200;\n        const int k_Height = 48;\n        const int k_HelpBoxHeight = 40;\n\n        static readonly string k_InvalidChars = EditorUtility.GetInvalidFilenameChars();\n        static readonly string s_InvalidCharsFormatString = L10n.Tr(\"Invalid characters: {0}\");\n        string m_CurrentInvalidChars = \"\";\n\n        string m_PresetName = \"Default\";\n        EditorWindow m_Window;\n\n        Action<string> save;\n        internal static SaveOverlayPreset ShowWindow(EditorWindow window, Action<string> callback)\n        {\n            SaveOverlayPreset w = GetWindowDontShow<SaveOverlayPreset>();\n            w.m_Window = window;\n            w.save = callback;\n            w.m_PresetName = window.overlayCanvas.lastAppliedPresetName;\n            if (string.IsNullOrEmpty(w.m_PresetName))\n                w.m_PresetName = \"Default\";\n            w.minSize = w.maxSize = new Vector2(k_Width, k_Height);\n            w.ShowAuxWindow();\n            return w;\n        }\n\n        void UpdateCurrentInvalidChars()\n        {\n            m_CurrentInvalidChars = new string(m_PresetName.Intersect(k_InvalidChars).Distinct().ToArray());\n        }\n\n        void OnEnable()\n        {\n            titleContent = GetLocalizedTitleContent();\n        }\n\n        void OnGUI()\n        {\n            GUILayout.Space(5);\n            Event evt = Event.current;\n            bool hitEnter = evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter);\n            bool hitEscape = evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.Escape);\n            if (hitEscape)\n            {\n                Close();\n                GUIUtility.ExitGUI();\n            }\n            GUI.SetNextControlName(\"m_PreferencesName\");\n            EditorGUI.BeginChangeCheck();\n            m_PresetName = EditorGUILayout.TextField(m_PresetName);\n            m_PresetName = m_PresetName.TrimEnd();\n            if (EditorGUI.EndChangeCheck())\n            {\n                UpdateCurrentInvalidChars();\n            }\n\n            if (!m_DidFocus)\n            {\n                m_DidFocus = true;\n                EditorGUI.FocusTextInControl(\"m_PreferencesName\");\n            }\n\n            if (m_CurrentInvalidChars.Length != 0)\n            {\n                EditorGUILayout.HelpBox(string.Format(s_InvalidCharsFormatString, m_CurrentInvalidChars), MessageType.Warning);\n                minSize = new Vector2(k_Width, k_Height + k_HelpBoxHeight);\n            }\n            else\n            {\n                minSize = new Vector2(k_Width, k_Height);\n            }\n\n            bool canSaveLayout = m_PresetName.Length > 0 && m_CurrentInvalidChars.Length == 0;\n            EditorGUI.BeginDisabled(!canSaveLayout);\n\n            if (GUILayout.Button(\"Save\") || hitEnter && canSaveLayout)\n            {\n                Close();\n\n                if (OverlayPresetManager.Exists(m_Window.GetType(), m_PresetName))\n                {\n                    if (!EditorUtility.DisplayDialog(\"Overwrite preset?\",\n                        \"Do you want to overwrite '\" + m_PresetName + \"' preset?\",\n                        \"Overwrite\", \"Cancel\"))\n                        GUIUtility.ExitGUI();\n                }\n\n                save(m_PresetName);\n\n                GUIUtility.ExitGUI();\n            }\n            else\n            {\n                m_DidFocus = false;\n            }\n\n            EditorGUI.EndDisabled();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/ToolbarDropZone.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor.Overlays\n{\n    sealed class ToolbarDropZone : OverlayContainerDropZone\n    {\n        public ToolbarDropZone(OverlayContainer container) : base(container, Placement.Start) { }\n\n        protected override bool ShouldEnable(Overlay draggedOverlay)\n        {\n            return !targetContainer.HasVisibleOverlays();\n        }\n\n        public override void Activate(Overlay draggedOverlay)\n        {\n            base.Activate(draggedOverlay);\n\n            SetHidden(true);\n        }\n\n        public override void UpdateHover(OverlayDropZoneBase hovered)\n        {\n            base.UpdateHover(hovered);\n\n            SetHidden(hovered != this);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Overlays/ToolbarOverlay.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Toolbars;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Overlays\n{\n    public abstract class ToolbarOverlay : Overlay, ICreateToolbar\n    {\n        readonly string[] m_ToolbarElementIds;\n        public virtual IEnumerable<string> toolbarElements => m_ToolbarElementIds;\n\n        protected ToolbarOverlay(params string[] toolbarElementIds)\n        {\n            m_ToolbarElementIds = toolbarElementIds ?? Array.Empty<string>();\n        }\n\n        [Obsolete(\"Use Overlay.CreateContent(Layout.Horizontal)\")]\n        public VisualElement CreateHorizontalToolbarContent() => CreatePanelContent();\n\n        [Obsolete(\"Use Overlay.CreateContent(Layout.Vertical)\")]\n        public VisualElement CreateVerticalToolbarContent() => CreatePanelContent();\n\n        public override VisualElement CreatePanelContent()\n        {\n            return new EditorToolbar(toolbarElements, containerWindow).rootVisualElement;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PackageManagerUtilityInternal.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEditor.PackageManager;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    /// <summary>\n    /// PackageManager helper class.\n    /// </summary>\n    internal static class PackageManagerUtilityInternal\n    {\n        /// <summary>\n        /// Returns the list of visible packages\n        /// </summary>\n        /// <param name=\"skipHiddenPackages\">Whether or not to skip packages that have the property hideInEditor set to true. Default is true</param>\n        /// <returns>An array of package information ordered by display name.</returns>\n        public static PackageManager.PackageInfo[] GetAllVisiblePackages(bool skipHiddenPackages = true)\n        {\n            return PackageManager.PackageInfo.GetAllRegisteredPackages().Where(info =>\n                !IsHidden(info) && (!skipHiddenPackages || !info.hideInEditor)).\n                OrderBy(info => string.IsNullOrEmpty(info.displayName) ? info.name : info.displayName,\n                    StringComparer.InvariantCultureIgnoreCase).ToArray();\n        }\n\n        /// <summary>\n        /// Determines whether or not a path belongs to a visible package\n        /// <param name=\"path\">The path to check.</param>\n        /// <returns>A boolean, true if path belongs to a visible package. False otherwise.</returns>\n        /// </summary>\n        public static bool IsPathInVisiblePackage(string path)\n        {\n            if (string.IsNullOrEmpty(path))\n                return false;\n\n            var package = PackageManager.PackageInfo.FindForAssetPath(path);\n            if (package == null)\n                return true;\n\n            return !IsHidden(package) && !package.hideInEditor;\n        }\n\n        private static int s_HiddenPackagesCount = -1;\n\n        /// <summary>\n        /// Count of hidden packages.\n        /// In this case, a package is considered hidden if the hideInEditor property is true and overrides the IsHidden value.\n        /// </summary>\n        public static int HiddenPackagesCount\n        {\n            get\n            {\n                if (s_HiddenPackagesCount == -1)\n                {\n                    s_HiddenPackagesCount = PackageManager.PackageInfo.GetAllRegisteredPackages().Count(info =>\n                        !IsHidden(info) && info.hideInEditor);\n                }\n\n                return s_HiddenPackagesCount;\n            }\n        }\n\n        [UsedByNativeCode]\n        internal static void OnPackageManagerResolve()\n        {\n            s_HiddenPackagesCount = -1;\n        }\n\n        // We want to hide modules and non-embedded features\n        // \"IsHidden\" is different from \"hideInEditor\".\n        // \"hideInEditor\" is an option that can be toggled by package developers.\n        private static bool IsHidden(PackageManager.PackageInfo info)\n        {\n            return info.type == \"module\" || (info.type == \"feature\" && info.source != PackageSource.Embedded);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PackageUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace UnityEditor\n{\n#pragma warning disable 649\n    [StructLayout(LayoutKind.Sequential)]\n    [Serializable]\n    [NativeType(CodegenOptions.Custom, \"MonoImportPackageItem\", Header = \"Editor/Mono/PackageUtility.bindings.h\")]\n    [NativeAsStruct]\n    internal class ImportPackageItem\n    {\n        public string existingAssetPath;\n        public string exportedAssetPath;\n        public string destinationAssetPath;\n        public string sourceFolder;\n        public string previewPath;\n        public string guid;\n        public int    enabledStatus;\n        public bool   isFolder;\n        public bool   exists;\n        public bool   assetChanged;\n        public bool   pathConflict;\n        public bool   projectAsset;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    [Serializable]\n    [NativeAsStruct]\n    [NativeType(CodegenOptions.Custom, \"MonoExportPackageItem\", Header = \"Editor/Mono/PackageUtility.bindings.h\")]\n    internal class ExportPackageItem\n    {\n        public string assetPath;\n        public string guid;\n        public bool   isFolder;\n        public int    enabledStatus;\n    }\n\n    //*undocumented*\n    [StructLayout(LayoutKind.Sequential)]\n    [NativeType(CodegenOptions.Custom, \"MonoPackageInfo\", Header = \"Editor/Src/PackageUtility.h\")]\n    public struct PackageInfo\n    {\n        public string packagePath;\n        public string jsonInfo;\n        public string iconURL;\n\n        [FreeFunction]\n        internal static extern PackageInfo[] GetPackageList();\n\n        [FreeFunction]\n        internal static extern PackageInfo GetPackageInfo(string packagePath);\n    }\n\n    [NativeHeader(\"Editor/Mono/PackageUtility.bindings.h\")]\n    internal class PackageUtility\n    {\n        [NativeThrows]\n        public static extern ExportPackageItem[] BuildExportPackageItemsList(string[] guids, bool dependencies);\n        [NativeThrows]\n        public static extern ExportPackageItem[] BuildExportPackageItemsListWithPackageManagerWarning(string[] guids, bool dependencies, bool warnPackageManagerDependencies);\n        [NativeThrows]\n        public static extern void ExportPackage(string[] guids, string fileName);\n        [NativeThrows]\n        public static extern void ExportPackageAndPackageManagerManifest(string[] guids, string fileName);\n        public static extern ImportPackageItem[] ExtractAndPrepareAssetList(string packagePath, out string packageIconPath, out string packageManagerDependenciesPath);\n\n        [FreeFunction(\"DelayedImportPackageAssets\")]\n        public static extern void ImportPackageAssets(string packageName, ImportPackageItem[] items);\n\n        [FreeFunction(\"DelayedImportPackageAssetsWithOrigin\")]\n        public static extern void ImportPackageAssetsWithOrigin(AssetOrigin origin, ImportPackageItem[] items);\n\n        [FreeFunction(\"ImportPackageAssets\")]\n        public static extern void ImportPackageAssetsImmediately(string packageName, ImportPackageItem[] items);\n\n        [FreeFunction(\"ImportPackageCancelledGUI\")]\n        public static extern void ImportPackageAssetsCancelledFromGUI(string packageName, ImportPackageItem[] items);\n\n        [FreeFunction(\"TickPackageImport\")]\n        public static extern void TickPackageImport();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Performance.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.CompilerServices;\nusing UnityEngine.Bindings;\n\n[assembly: InternalsVisibleTo(\"Unity.PerformanceTracking.Editor\")]\n\nnamespace UnityEditor.Profiling\n{\n    [NativeHeader(\"Editor/Src/Utility/Performance.h\"),\n     StaticAccessor(\"Performance::Bindings\", StaticAccessorType.DoubleColon)]\n    internal struct EditorPerformanceTracker : IDisposable\n    {\n        private volatile bool m_Disposed;\n        private readonly int m_WatchHandle;\n\n        public EditorPerformanceTracker(string name)\n        {\n            m_Disposed = false;\n            m_WatchHandle = StartTracker(name);\n        }\n\n        public EditorPerformanceTracker(ulong handle)\n        {\n            m_Disposed = false;\n            var isMainThread = UnityEditorInternal.InternalEditorUtility.CurrentThreadIsMainThread();\n            if (!isMainThread || !TryStartTrackerByHandle(handle, out m_WatchHandle))\n                m_WatchHandle = -1;\n        }\n\n        public void Dispose()\n        {\n            if (m_Disposed)\n                return;\n            if (m_WatchHandle != -1)\n                StopTracker(m_WatchHandle);\n            m_Disposed = true;\n        }\n\n        internal const ulong InvalidTrackerHandle = ulong.MaxValue;\n        private static extern ulong GetOrCreateTrackerHandleImpl(string trackerName, Type context);\n\n        // This method is for internal use only. If you do not provide a type, we cannot\n        // map the marker to an assembly.\n        internal static ulong GetOrCreateTrackerHandle(string trackerName) => GetOrCreateTrackerHandleImpl(trackerName, null);\n\n        public static ulong GetOrCreateTrackerHandle(string trackerName, Type context)\n        {\n            if (context == null)\n            {\n                throw new ArgumentNullException(nameof(context));\n            }\n\n            return GetOrCreateTrackerHandleImpl(trackerName, context);\n        }\n\n        public static extern bool TryStartTrackerByHandle(ulong trackerHandle, out int trackerToken);\n\n        public static extern string[] GetAvailableTrackers();\n        public static extern bool Exists(string trackerName);\n        public static extern void Reset(string trackerName);\n        public static extern int GetSampleCount(string trackerName);\n        public static extern double GetLastTime(string trackerName);\n        public static extern double GetPeakTime(string trackerName);\n        public static extern double GetAverageTime(string trackerName);\n        public static extern double GetTotalTime(string trackerName);\n        public static extern double GetTotalUsage(string trackerName);\n        public static extern double GetTimestamp(string trackerName);\n        public static extern void LogCallstack(string trackerName);\n        public static extern void GetCallstack(string trackerName, Action<string> onCallstackCaptured);\n\n        internal static extern int StartTracker(string trackerName);\n        internal static extern void StopTracker(int trackerToken);\n        internal static extern bool IsTrackerActive(int trackerToken);\n    }\n\n    struct EditorPerformanceMarker\n    {\n        private readonly ulong m_TrackerHandle;\n\n        // This constructor is for internal use only. If you do not provide a type, we cannot attribute it to\n        // any assembly.\n        internal EditorPerformanceMarker(string name)\n        {\n            m_TrackerHandle = EditorPerformanceTracker.GetOrCreateTrackerHandle(name);\n        }\n\n        public EditorPerformanceMarker(string name, Type type)\n        {\n            m_TrackerHandle = EditorPerformanceTracker.GetOrCreateTrackerHandle(name, type);\n        }\n\n        [MethodImpl(256)] // 256 : Aggressive inlining\n        public AutoScope Auto()\n        {\n            return new AutoScope(m_TrackerHandle);\n        }\n\n        public struct AutoScope : IDisposable\n        {\n            private int m_WatchHandle;\n\n            [MethodImpl(256)]\n            internal AutoScope(ulong trackerHandle)\n            {\n                EditorPerformanceTracker.TryStartTrackerByHandle(trackerHandle, out m_WatchHandle);\n            }\n\n            [MethodImpl(256)]\n            public void Dispose()\n            {\n                EditorPerformanceTracker.StopTracker(m_WatchHandle);\n                m_WatchHandle = -1;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PerformanceTools/FrameDebugger.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing System.Runtime.InteropServices;\n\nnamespace UnityEditorInternal.FrameDebuggerInternal\n{\n    [NativeHeader(\"Editor/Mono/PerformanceTools/FrameDebugger.bindings.h\")]\n    [StaticAccessor(\"FrameDebugger\", StaticAccessorType.DoubleColon)]\n    internal sealed class FrameDebuggerUtility\n    {\n        public extern static void SetEnabled(bool enabled, int remotePlayerGUID);\n        public extern static int GetRemotePlayerGUID();\n        public extern static bool receivingRemoteFrameEventData { [NativeName(\"IsReceivingRemoteFrameEventData\")] get; }\n        public extern static bool locallySupported { [NativeName(\"IsSupported\")] get; }\n        [NativeName(\"FinalDrawCallCount\")] public extern static int count { get; }\n        [NativeName(\"DrawCallLimit\")] public extern static int limit { get; set; }\n        [NativeName(\"FrameEventsHash\")] public extern static int eventsHash { get; }\n        [NativeName(\"FrameEventDataHash\")] public extern static uint eventDataHash { get; }\n        public extern static void SetRenderTargetDisplayOptions(int rtIndex, Vector4 channels, float blackLevel, float whiteLevel);\n        [NativeName(\"GetProfilerEventName\")] public extern static string GetFrameEventInfoName(int index);\n        public extern static Object GetFrameEventObject(int index);\n        [FreeFunction(\"FrameDebuggerBindings::GetBatchBreakCauseStrings\")] public extern static string[] GetBatchBreakCauseStrings();\n\n        public static FrameDebuggerEvent[] GetFrameEvents() { return (FrameDebuggerEvent[])GetFrameEventsImpl(); }\n        [NativeName(\"GetFrameEvents\")] extern private static System.Array GetFrameEventsImpl();\n\n        // Returns false, if frameEventData holds data from previous selected frame\n        public static bool GetFrameEventData(int index, FrameDebuggerEventData frameDebuggerEventData)\n        {\n            // native code will poke and modify the FrameDebuggerEventData object fields\n            // directly via a pointer to it\n            var handle = GCHandle.Alloc(frameDebuggerEventData, GCHandleType.Pinned);\n            GetFrameEventDataImpl(handle.AddrOfPinnedObject());\n            handle.Free();\n            return frameDebuggerEventData.m_FrameEventIndex == index;\n        }\n\n        [FreeFunction(\"FrameDebuggerBindings::GetFrameEventDataImpl\")]\n        extern private static void GetFrameEventDataImpl(System.IntPtr frameDebuggerEventData);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PerformanceTools/FrameDebugger.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\n\nusing UnityEngine;\nusing UnityEngine.Profiling;\nusing UnityEngine.Networking.PlayerConnection;\n\nusing UnityEditorInternal;\nusing UnityEditorInternal.FrameDebuggerInternal;\n\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.Networking.PlayerConnection;\nusing UnityEditor.Rendering.Analytics;\n\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    internal class FrameDebuggerWindow : EditorWindow\n    {\n        // Serialized\n        [SerializeField] private float m_TreeWidth = FrameDebuggerStyles.Window.k_MinTreeWidth;\n        [SerializeField] private TreeViewState m_TreeViewState;\n\n        // Private\n        private int m_EnablingWaitCounter = 0;\n        private int m_RepaintFrames = k_NeedToRepaintFrames;\n        private int m_FrameEventsHash;\n        private bool m_ShowTabbedErrorBox;\n        private bool m_HasOpenedPlaymodeView;\n        private Rect m_SearchRect;\n        private string m_SearchString = String.Empty;\n        private IConnectionState m_AttachToPlayerState;\n        private FrameDebuggerTreeView m_TreeView;\n        private FrameDebuggerEventDetailsView m_EventDetailsView;\n        private FrameDebuggerToolbarView m_Toolbar;\n\n        // Statics\n        private static List<FrameDebuggerWindow> s_FrameDebuggers = new List<FrameDebuggerWindow>();\n\n        // Constants\n\n        // Sometimes when disabling the frame debugger, the UI does not update automatically -\n        // the repaint happens, but we still think there's zero events present\n        // (on Mac at least). Haven't figured out why, so whenever changing the\n        // enable/limit state, just repaint a couple of times. Yeah...\n        private const int k_NeedToRepaintFrames = 4;\n\n        // Properties\n        private bool IsDisabledInEditor => !FrameDebugger.enabled;\n        private bool IsEnablingFrameDebugger => m_EnablingWaitCounter < k_NeedToRepaintFrames;\n        private bool HasEventHashChanged => FrameDebuggerUtility.eventsHash != m_FrameEventsHash;\n        \n        private readonly Lazy<GUIContent> m_HelpButtonContent = new(() => EditorGUIUtility.TrIconContent(\"_Help\", \"Open Manual (in a web browser)\"));\n\n\n        [ShortcutManagement.Shortcut(\"Analysis/FrameDebugger/Enable\")]\n        public static void OpenWindowAndToggleEnabled()\n        {\n            FrameDebuggerWindow frameDebuggerWindow = OpenWindow();\n            frameDebuggerWindow.ToggleFrameDebuggerEnabled();\n        }\n\n        [MenuItem(\"Window/Analysis/Frame Debugger\", false, 10)]\n        public static FrameDebuggerWindow OpenWindow()\n        {\n            var wnd = GetWindow(typeof(FrameDebuggerWindow)) as FrameDebuggerWindow;\n            wnd.titleContent = EditorGUIUtility.TrTextContent(\"Frame Debugger\");\n            wnd.minSize = new Vector2(1000f, 500f);\n            return wnd;\n        }\n        \n        void ShowButton(Rect r)\n        {\n            if (GUI.Button(r, m_HelpButtonContent.Value, EditorStyles.iconButton))\n            {\n                var url = $\"https://docs.unity3d.com/{Help.GetShortReleaseVersion()}/Documentation/Manual/FrameDebugger.html\";\n                Help.BrowseURL(url);\n            }\n        }\n\n        internal void ToggleFrameDebuggerEnabled()\n        {\n            if (FrameDebugger.enabled)\n                DisableFrameDebugger();\n            else\n                EnableFrameDebugger();\n        }\n\n        internal override void OnResized()\n        {\n            if (PopupWindowWithoutFocus.IsVisible())\n                PopupWindowWithoutFocus.Hide();\n\n            base.OnResized();\n        }\n\n        internal void ChangeFrameEventLimit(int newLimit)\n        {\n            if (newLimit <= 0 || newLimit > FrameDebuggerUtility.count)\n                return;\n\n            FrameDebuggerUtility.limit = newLimit;\n            m_EventDetailsView?.OnNewFrameEventSelected();\n            m_TreeView?.SelectFrameEventIndex(newLimit);\n        }\n\n        internal void ChangeFrameEventLimit(int newLimit, FrameDebuggerTreeView.FrameDebuggerTreeViewItem originalItem)\n        {\n            if (newLimit <= 0 || newLimit > FrameDebuggerUtility.count)\n                return;\n\n            FrameDebuggerUtility.limit = newLimit;\n            m_EventDetailsView?.OnNewFrameEventSelected();\n            m_TreeView?.SelectFrameEventIndex(newLimit);\n        }\n\n        internal void OnConnectedProfilerChange()\n        {\n            DisableFrameDebugger();\n            EnableFrameDebugger();\n        }\n\n        internal static void RepaintAll()\n        {\n            foreach (var fd in s_FrameDebuggers)\n                fd.Repaint();\n        }\n\n        internal void ReselectItemOnCountChange()\n        {\n            if (m_TreeView == null)\n                return;\n\n            m_TreeView.ReselectFrameEventIndex();\n        }\n\n        internal void RepaintAllNeededThings()\n        {\n            // indicate that editor needs a redraw (mostly to get offscreen cameras rendered)\n            EditorApplication.SetSceneRepaintDirty();\n\n            // Note: do NOT add GameView.RepaintAll here; that would cause really confusing\n            // behaviors when there are offscreen (rendering into RTs) cameras.\n\n            // redraw ourselves\n            Repaint();\n        }\n\n        internal void DrawSearchField(string str)\n        {\n            m_SearchString = EditorGUI.ToolbarSearchField(m_SearchRect, str, false);\n        }\n\n        // OnGUI does not always get called, which causes issues when profiling a remote player.\n        // We need to call repaint in order to get the data without having to move the mouse\n        // and to get things like foldouts to open/collapse normally etc.\n        void Update()\n        {\n            if (IsDisabledInEditor)\n                return;\n\n            if (IsEnablingFrameDebugger || m_AttachToPlayerState.connectedToTarget == ConnectionTarget.Player)\n                RepaintOnLimitChange();\n        }\n\n        private void OnGUI()\n        {\n            // We always draw the top toolbar with the enable/disable/etc...\n            bool repaint = DrawToolBar();\n\n            // If the debugger has not been enabled...\n            if (IsDisabledInEditor)\n                DrawDisabledFrameDebugger();\n\n            // After first clicking the enable button we need to wait a few frames before starting to draw...\n            else if (IsEnablingFrameDebugger)\n                HandleEnablingFrameDebugger();\n\n            // Draw the enabled debugger...\n            else\n                DrawEnabledFrameDebugger(repaint);\n        }\n\n        private bool DrawToolBar()\n        {\n            if (m_Toolbar == null)\n                m_Toolbar = new FrameDebuggerToolbarView();\n\n            Profiler.BeginSample(\"DrawToolbar\");\n            bool repaint = m_Toolbar.DrawToolbar(this, m_AttachToPlayerState);\n            Profiler.EndSample();\n\n            return repaint;\n        }\n\n        private void DrawDisabledFrameDebugger()\n        {\n            GUI.enabled = true;\n            if (!FrameDebuggerUtility.locallySupported)\n            {\n                string warningMessage = (FrameDebuggerHelper.isOnLinuxOpenGL) ? FrameDebuggerStyles.EventDetails.k_WarningLinuxOpenGLMsg : FrameDebuggerStyles.EventDetails.k_WarningMultiThreadedMsg;\n                EditorGUILayout.HelpBox(warningMessage, MessageType.Warning, true);\n            }\n\n            EditorGUILayout.HelpBox(FrameDebuggerStyles.EventDetails.k_DescriptionString, MessageType.Info, true);\n\n            if (m_ShowTabbedErrorBox)\n                EditorGUILayout.HelpBox(FrameDebuggerStyles.EventDetails.k_TabbedWithPlaymodeErrorString, MessageType.Error, true);\n        }\n\n        private void HandleEnablingFrameDebugger()\n        {\n            // Make sure the PlayMode window is enabled and shown...\n            if (!OpenPlayModeView())\n                return;\n\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            m_EnablingWaitCounter++;\n            if (m_EnablingWaitCounter == k_NeedToRepaintFrames)\n            {\n                FrameDebuggerEvent[] descs = FrameDebuggerUtility.GetFrameEvents();\n                m_TreeView = new FrameDebuggerTreeView(descs, m_TreeViewState, this, new Rect(50, 50, 500, 100));\n                m_FrameEventsHash = FrameDebuggerUtility.eventsHash;\n                ChangeFrameEventLimit(FrameDebuggerUtility.count);\n            }\n        }\n\n        private bool CheckIfFDIsDockedWithGameWindow(DockArea da, PlayModeView gameWindow)\n        {\n            for (int i = 0; i < da.m_Panes.Count; i++)\n                if (gameWindow == da.m_Panes[i])\n                    return true;\n            return false;\n        }\n\n        private bool OpenPlayModeView()\n        {\n            if (m_HasOpenedPlaymodeView)\n                return true;\n\n            // When debugging remote players, we can ignore this check as it doesn't render to the Game Window.\n            if (!FrameDebugger.IsLocalEnabled() && m_AttachToPlayerState.connectedToTarget != ConnectionTarget.Editor)\n                return true;\n\n            PlayModeView mainGameWindow = PlayModeView.GetMainPlayModeView();\n            List<PlayModeView> allGameWindows = PlayModeView.GetAllPlayModeViewWindows();\n            if (mainGameWindow || allGameWindows.Count > 0)\n            {\n                PlayModeView gameWindowToUse = mainGameWindow;\n\n                // The Frame Debugger and Game Window can not be docked together in\n                // the panes list (tabs) as both need to be shown in the Editor.\n                bool isFDInTheSamePaneAsGameWindow = false;\n                DockArea da = m_Parent as DockArea;\n                if (da)\n                    isFDInTheSamePaneAsGameWindow |= CheckIfFDIsDockedWithGameWindow(da, mainGameWindow);\n\n                // If it's docked, check if there are other game windows available to use\n                if (isFDInTheSamePaneAsGameWindow && allGameWindows.Count > 1)\n                {\n                    for (int i = 0; i < allGameWindows.Count; i++)\n                    {\n                        if (CheckIfFDIsDockedWithGameWindow(da, allGameWindows[i]))\n                            continue;\n\n                        isFDInTheSamePaneAsGameWindow = false;\n                        gameWindowToUse = allGameWindows[i];\n                        break;\n                    }\n                }\n\n                // When we can't enable the FD debugger, we display an error box informing the\n                // user to undock the Frame Debugger Window so it's not tabbed with the Game Window.\n                if (isFDInTheSamePaneAsGameWindow)\n                {\n                    m_ShowTabbedErrorBox = true;\n                    return false;\n                }\n                // Otherwise we show the Game Window\n                else\n                {\n                    gameWindowToUse.ShowTab();\n                    m_HasOpenedPlaymodeView = true;\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        private void DrawEnabledFrameDebugger(bool repaint)\n        {\n            int oldLimit = FrameDebuggerUtility.limit;\n            FrameDebuggerEvent[] descs = FrameDebuggerUtility.GetFrameEvents();\n\n            // captured frame event contents have changed, rebuild the tree data\n            if (HasEventHashChanged)\n            {\n                m_TreeView.m_DataSource.SetEvents(descs);\n                m_FrameEventsHash = FrameDebuggerUtility.eventsHash;\n            }\n\n            float toolbarHeight = EditorStyles.toolbar.fixedHeight;\n\n            Rect dragRect = new Rect(m_TreeWidth, toolbarHeight, FrameDebuggerStyles.Window.k_ResizerWidth, position.height - toolbarHeight);\n            dragRect = EditorGUIUtility.HandleHorizontalSplitter(dragRect, position.width, FrameDebuggerStyles.Window.k_MinTreeWidth, FrameDebuggerStyles.Window.k_MinDetailsWidth);\n            m_TreeWidth = dragRect.x;\n\n            // Search area\n            m_SearchRect = EditorGUILayout.GetControlRect();\n            m_SearchRect.width = m_TreeWidth - 5;\n            DrawSearchField(m_SearchString);\n\n            Rect listRect = new Rect(\n                0,\n                toolbarHeight + m_SearchRect.y,\n                m_TreeWidth,\n                position.height - toolbarHeight - m_SearchRect.height - 5\n            );\n\n            Rect currentEventRect = new Rect(\n                m_TreeWidth,\n                toolbarHeight,\n                position.width - m_TreeWidth,\n                position.height - toolbarHeight\n            );\n\n            Profiler.BeginSample(\"DrawTree\");\n            m_TreeView.m_TreeView.searchString = m_SearchString;\n            m_TreeView.DrawTree(listRect);\n            Profiler.EndSample();\n\n            EditorGUIUtility.DrawHorizontalSplitter(dragRect);\n\n            Profiler.BeginSample(\"DrawEventDetails\");\n            m_EventDetailsView.DrawEventDetails(currentEventRect, descs, m_AttachToPlayerState.connectedToTarget == ConnectionTarget.Editor);\n            Profiler.EndSample();\n\n            if (repaint || oldLimit != FrameDebuggerUtility.limit)\n                RepaintOnLimitChange();\n\n            if (m_RepaintFrames > 0)\n            {\n                m_TreeView.SelectFrameEventIndex(FrameDebuggerUtility.limit);\n                RepaintAllNeededThings();\n                --m_RepaintFrames;\n            }\n        }\n\n        private void OnDidOpenScene()\n        {\n            DisableFrameDebugger();\n        }\n\n        private void OnPauseStateChanged(PauseState state)\n        {\n            RepaintOnLimitChange();\n        }\n\n        private void OnPlayModeStateChanged(PlayModeStateChange state)\n        {\n            RepaintOnLimitChange();\n        }\n\n        private void OnEnable()\n        {\n            if (m_AttachToPlayerState == null)\n                m_AttachToPlayerState = PlayerConnectionGUIUtility.GetConnectionState(this);\n\n            wantsLessLayoutEvents = true;\n            autoRepaintOnSceneChange = true;\n            s_FrameDebuggers.Add(this);\n            EditorApplication.pauseStateChanged += OnPauseStateChanged;\n            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;\n            m_RepaintFrames = k_NeedToRepaintFrames;\n\n            GraphicsToolLifetimeAnalytic.WindowOpened<FrameDebuggerWindow>();\n        }\n\n        private void OnDisable()\n        {\n            m_AttachToPlayerState?.Dispose();\n            m_AttachToPlayerState = null;\n\n            s_FrameDebuggers.Remove(this);\n            EditorApplication.pauseStateChanged -= OnPauseStateChanged;\n            EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;\n\n            DisableFrameDebugger();\n\n            GraphicsToolLifetimeAnalytic.WindowClosed<FrameDebuggerWindow>();\n        }\n\n        private void EnableFrameDebugger()\n        {\n            if (FrameDebugger.enabled)\n                return;\n\n            bool enablingLocally = !FrameDebugger.enabled && m_AttachToPlayerState.connectedToTarget == ConnectionTarget.Editor;\n            if (enablingLocally && !FrameDebuggerUtility.locallySupported)\n                return;\n\n            m_ShowTabbedErrorBox = false;\n            m_HasOpenedPlaymodeView = false;\n            if (!OpenPlayModeView())\n                return;\n\n            // pause play mode if needed\n            if (enablingLocally)\n                if (EditorApplication.isPlaying && !EditorApplication.isPaused)\n                    EditorApplication.isPaused = true;\n\n            FrameDebuggerUtility.SetEnabled(true, ProfilerDriver.connectedProfiler);\n\n            if (m_TreeViewState == null)\n                m_TreeViewState = new TreeViewState();\n\n            if (m_EventDetailsView == null)\n                m_EventDetailsView = new FrameDebuggerEventDetailsView(this);\n\n            m_EnablingWaitCounter = 0;\n            m_EventDetailsView.Reset();\n            RepaintOnLimitChange();\n\n            GraphicsToolUsageAnalytic.ActionPerformed<FrameDebuggerWindow>(nameof(EnableFrameDebugger), Array.Empty<string>());\n        }\n\n        private void DisableFrameDebugger()\n        {\n            if (!FrameDebugger.enabled)\n                return;\n\n            // if it was true before, we disabled and ask the game scene to repaint\n            if (FrameDebugger.IsLocalEnabled())\n                EditorApplication.SetSceneRepaintDirty();\n\n            FrameDebuggerUtility.SetEnabled(false, FrameDebuggerUtility.GetRemotePlayerGUID());\n\n            if (m_EventDetailsView != null)\n            {\n                m_EventDetailsView.OnDisable();\n                m_EventDetailsView = null;\n            }\n\n            m_HasOpenedPlaymodeView = false;\n            FrameDebuggerStyles.OnDisable();\n            m_TreeViewState = null;\n            m_TreeView = null;\n\n            GraphicsToolUsageAnalytic.ActionPerformed<FrameDebuggerWindow>(nameof(DisableFrameDebugger), Array.Empty<string>());\n        }\n\n        internal void RepaintOnLimitChange()\n        {\n            m_RepaintFrames = k_NeedToRepaintFrames;\n            RepaintAllNeededThings();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PerformanceTools/FrameDebuggerData.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEditor;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditorInternal.FrameDebuggerInternal\n{\n    // match enum FrameEventType on C++ side!\n    // match kFrameEventTypeNames names array!\n    internal enum FrameEventType\n    {\n        // ReSharper disable InconsistentNaming\n        ClearNone = 0,\n        ClearColor,\n        ClearDepth,\n        ClearColorDepth,\n        ClearStencil,\n        ClearColorStencil,\n        ClearDepthStencil,\n        ClearAll,\n        SetRenderTarget,\n        ResolveRT,\n        ResolveDepth,\n        GrabIntoRT,\n        StaticBatch,\n        DynamicBatch,\n        Mesh,\n        DynamicGeometry,\n        GLDraw,\n        SkinOnGPU,\n        DrawProcedural,\n        DrawProceduralIndirect,\n        DrawProceduralIndexed,\n        DrawProceduralIndexedIndirect,\n        ComputeDispatch,\n        RayTracingDispatch,\n        PluginEvent,\n        InstancedMesh,\n        BeginSubpass,\n        SRPBatch,\n        HierarchyLevelBreak,\n        HybridBatch,\n        ConfigureFoveatedRendering,\n        // ReSharper restore InconsistentNaming\n    }\n\n    // Match C++ ScriptingShaderKeywordInfo memory layout!\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct ShaderKeywordInfo\n    {\n        public string m_Name;\n        public int m_Flags;\n        public bool m_IsGlobal;\n        public bool m_IsDynamic;\n    };\n\n    // Match C++ ScriptingShaderFloatInfo memory layout!\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct ShaderFloatInfo\n    {\n        public string m_Name;\n        public int m_Flags;\n        public float m_Value;\n    }\n\n    // Match C++ ScriptingShaderIntInfo memory layout!\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct ShaderIntInfo\n    {\n        public string m_Name;\n        public int m_Flags;\n        public int m_Value;\n    }\n\n    // Match C++ ScriptingShaderVectorInfo memory layout!\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct ShaderVectorInfo\n    {\n        public string m_Name;\n        public int m_Flags;\n        public Vector4 m_Value;\n    }\n\n    // Match C++ ScriptingShaderMatrixInfo memory layout!\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct ShaderMatrixInfo\n    {\n        public string m_Name;\n        public int m_Flags;\n        public Matrix4x4 m_Value;\n    }\n\n    // Match C++ ScriptingShaderTextureInfo memory layout!\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct ShaderTextureInfo\n    {\n        public string m_Name;\n        public int m_Flags;\n        public string m_TextureName;\n        public Texture m_Value;\n    }\n\n    // Match C++ ScriptingShaderBufferInfo memory layout!\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct ShaderBufferInfo\n    {\n        public string m_Name;\n        public int m_Flags;\n    }\n\n    // Match C++ ScriptingShaderBufferInfo memory layout!\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct ShaderConstantBufferInfo\n    {\n        public string m_Name;\n        public int m_Flags;\n    }\n\n    // Match C++ ScriptingShaderInfo memory layout!\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct ShaderInfo\n    {\n        public ShaderKeywordInfo[] m_Keywords;\n        public ShaderFloatInfo[] m_Floats;\n        public ShaderIntInfo[] m_Ints;\n        public ShaderVectorInfo[] m_Vectors;\n        public ShaderMatrixInfo[] m_Matrices;\n        public ShaderTextureInfo[] m_Textures;\n        public ShaderBufferInfo[] m_Buffers;\n        public ShaderConstantBufferInfo[] m_CBuffers;\n    }\n\n    // Match C++ ScriptingFrameDebuggerEventData memory layout!\n    [StructLayout(LayoutKind.Sequential)]\n    internal class FrameDebuggerEventData\n    {\n        public int m_FrameEventIndex;\n        public int m_RTDisplayIndex;\n        public int m_VertexCount;\n        public int m_IndexCount;\n        public int m_InstanceCount;\n        public int m_DrawCallCount;\n        public string m_OriginalShaderName;\n        public string m_RealShaderName;\n        public string m_PassName;\n        public string m_PassLightMode;\n        public int m_ShaderInstanceID;\n        public int m_SubShaderIndex;\n        public int m_ShaderPassIndex;\n        public string shaderKeywords;\n        public int m_ComponentInstanceID;\n        public Mesh m_Mesh;\n        public int m_MeshInstanceID;\n        public int m_MeshSubset;\n        public int[] m_MeshInstanceIDs;\n\n        // state for compute shader dispatches\n        public int m_ComputeShaderInstanceID;\n        public string m_ComputeShaderName;\n        public string m_ComputeShaderKernelName;\n        public int m_ComputeShaderThreadGroupsX;\n        public int m_ComputeShaderThreadGroupsY;\n        public int m_ComputeShaderThreadGroupsZ;\n        public int m_ComputeShaderGroupSizeX;\n        public int m_ComputeShaderGroupSizeY;\n        public int m_ComputeShaderGroupSizeZ;\n\n        // state for ray tracing shader dispatches\n        public int m_RayTracingShaderInstanceID;\n        public bool m_RayTracingIndirectDispatch;\n        public string m_RayTracingShaderName;\n        public string m_RayTracingShaderPassName;\n        public string m_RayTracingShaderRayGenShaderName;\n        public string m_RayTracingShaderAccelerationStructureName;\n        public int m_RayTracingShaderAccelerationStructureSize;\n        public int m_RayTracingShaderMaxRecursionDepth;\n        public int m_RayTracingShaderWidth;\n        public int m_RayTracingShaderHeight;\n        public int m_RayTracingShaderDepth;\n        public int m_RayTracingShaderMissShaderCount;\n        public int m_RayTracingShaderCallableShaderCount;\n\n        // active render target info\n        public string m_RenderTargetName;\n        public int m_RenderTargetWidth;\n        public int m_RenderTargetHeight;\n        public int m_RenderTargetFormat;\n        public int m_RenderTargetDimension;\n        public int m_RenderTargetCubemapFace;\n        public int m_RenderTargetFoveatedRenderingMode;\n        public int m_RenderTargetLoadAction;\n        public int m_RenderTargetStoreAction;\n        public int m_RenderTargetDepthLoadAction;\n        public int m_RenderTargetDepthStoreAction;\n        public float m_RenderTargetClearColorR;\n        public float m_RenderTargetClearColorG;\n        public float m_RenderTargetClearColorB;\n        public float m_RenderTargetClearColorA;\n        public float m_RenderTargetClearDepth;\n        public uint m_RenderTargetClearStencil;\n        public short m_RenderTargetCount;\n        public sbyte m_RenderTargetHasDepthTexture;\n        public sbyte m_RenderTargetHasStencilBits;\n        public sbyte m_RenderTargetMemoryless;\n        public bool m_RenderTargetIsBackBuffer;\n        public RenderTexture m_RenderTargetRenderTexture;\n\n        // shader state\n        public FrameDebuggerBlendState m_BlendState;\n        public FrameDebuggerRasterState m_RasterState;\n        public FrameDebuggerDepthState m_DepthState;\n        public FrameDebuggerStencilState m_StencilState;\n        public int m_StencilRef;\n\n        // clear event data\n        public float m_ClearColorR;\n        public float m_ClearColorG;\n        public float m_ClearColorB;\n        public float m_ClearColorA;\n        public float m_ClearDepth;\n        public uint  m_ClearStencil;\n\n        public int m_BatchBreakCause;\n        public ShaderInfo m_ShaderInfo;\n    }\n\n    // Match C++ MonoFrameDebuggerEvent memory layout!\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct FrameDebuggerEvent\n    {\n        public FrameEventType m_Type;\n        public UnityEngine.Object m_Obj;\n    }\n\n    // Match C++ ScriptingFrameDebuggerBlendState memory layout!\n    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]\n    internal struct FrameDebuggerBlendState\n    {\n        public uint m_WriteMask;\n        public BlendMode m_SrcBlend;\n        public BlendMode m_DstBlend;\n        public BlendMode m_SrcBlendAlpha;\n        public BlendMode m_DstBlendAlpha;\n        public BlendOp m_BlendOp;\n        public BlendOp m_BlendOpAlpha;\n    }\n\n    // Match C++ ScriptingFrameDebuggerRasterState memory layout!\n    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]\n    internal struct FrameDebuggerRasterState\n    {\n        public CullMode m_CullMode;\n        public int m_DepthBias;\n        public float m_SlopeScaledDepthBias;\n        public bool m_DepthClip;\n        public bool m_Conservative;\n    }\n\n    // Match C++ ScriptingFrameDebuggerDepthState memory layout!\n    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]\n    internal struct FrameDebuggerDepthState\n    {\n        public int m_DepthWrite;\n        public CompareFunction m_DepthFunc;\n    }\n\n    // Match C++ ScriptingFrameDebuggerStencilState memory layout!\n    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]\n    internal struct FrameDebuggerStencilState\n    {\n        public bool m_StencilEnable;\n        public byte m_ReadMask;\n        public byte m_WriteMask;\n        public byte m_Padding;\n        public CompareFunction m_StencilFuncFront;\n        public StencilOp m_StencilPassOpFront;\n        public StencilOp m_StencilFailOpFront;\n        public StencilOp m_StencilZFailOpFront;\n        public CompareFunction m_StencilFuncBack;\n        public StencilOp m_StencilPassOpBack;\n        public StencilOp m_StencilFailOpBack;\n        public StencilOp m_StencilZFailOpBack;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PerformanceTools/FrameDebuggerEventDetailsView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEditor.AnimatedValues;\nusing UnityEngine;\nusing UnityEngine.Experimental.Rendering;\nusing UnityEngine.Profiling;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditorInternal.FrameDebuggerInternal\n{\n    internal class FrameDebuggerEventDetailsView\n    {\n        // Render target view options\n        [NonSerialized] private int m_RTIndex;\n        [NonSerialized] private int m_MeshIndex = 0;\n        [NonSerialized] private int m_RTIndexLastSet = 0;\n        [NonSerialized] private int m_RTSelectedChannel;\n        [NonSerialized] private float m_RTBlackLevel;\n        [NonSerialized] private float m_RTWhiteLevel = 1.0f;\n        [NonSerialized] private float m_RTBlackMinLevel;\n        [NonSerialized] private float m_RTWhiteMaxLevel = 1.0f;\n\n        // Private\n        [Flags]\n        public enum SelectedColorChannel\n        {\n            None = 0,\n            R = 1 << 0,\n            G = 1 << 1,\n            B = 1 << 2,\n            A = 1 << 3,\n            All = R | G | B | A\n        }\n\n        private SelectedColorChannel m_SelectedColorChannel = SelectedColorChannel.All;\n        private Vector2 m_ScrollViewVector = Vector2.zero;\n        private Vector4 m_SelectedMask = Vector4.one;\n        private AnimBool[] m_FoldoutAnimators = null;\n        private MeshPreview m_Preview;\n        private CachedEventDisplayData m_CachedEventData = null;\n        private FrameDebuggerWindow m_FrameDebugger = null;\n        private Lazy<FrameDebuggerEventData> m_CurEventData = new Lazy<FrameDebuggerEventData>(() => new FrameDebuggerEventData());\n        private RenderTexture m_RenderTargetRenderTextureCopy = null;\n\n        // Constants / Readonly\n        private const int k_NumberGUISections = 11;\n        private readonly string[] k_foldoutKeys = new string[]{\n            \"FrameDebuggerFoldout0\",\n            \"FrameDebuggerFoldout1\",\n            \"FrameDebuggerFoldout2\",\n            \"FrameDebuggerFoldout3\",\n            \"FrameDebuggerFoldout4\",\n            \"FrameDebuggerFoldout5\",\n            \"FrameDebuggerFoldout6\",\n            \"FrameDebuggerFoldout7\",\n            \"FrameDebuggerFoldout8\",\n            \"FrameDebuggerFoldout9\",\n            \"FrameDebuggerFoldout10\",\n        };\n\n        // Properties\n        private FrameDebuggerEvent curEvent { get; set; }\n        private FrameDebuggerEventData curEventData => m_CurEventData.Value;\n        private int curEventIndex => FrameDebuggerUtility.limit - 1;\n\n        // Internal functions\n        internal FrameDebuggerEventDetailsView(FrameDebuggerWindow frameDebugger)\n        {\n            m_FrameDebugger = frameDebugger;\n        }\n\n        internal void Reset()\n        {\n            m_RTSelectedChannel = 0;\n            m_SelectedColorChannel = SelectedColorChannel.All;\n            m_RTIndex = 0;\n            m_RTBlackLevel = 0.0f;\n            m_RTBlackMinLevel = 0.0f;\n            m_RTWhiteLevel = 1.0f;\n            m_RTWhiteMaxLevel = 1.0f;\n        }\n\n        internal void OnNewFrameEventSelected()\n        {\n            m_MeshIndex = 0;\n            m_Preview?.Dispose();\n            m_Preview = null;\n        }\n\n        internal void OnDisable()\n        {\n            if (m_CachedEventData != null)\n                m_CachedEventData.OnDisable();\n\n            // Release the texture...\n            FrameDebuggerHelper.ReleaseTemporaryTexture(ref m_RenderTargetRenderTextureCopy);\n\n            m_Preview?.Dispose();\n            m_Preview = null;\n            Reset();\n        }\n\n        internal void DrawEventDetails(Rect rect, FrameDebuggerEvent[] descs, bool isDebuggingEditor)\n        {\n            // Early out if the frame is not valid\n            if (!FrameDebuggerHelper.IsAValidFrame(curEventIndex, descs.Length))\n                return;\n\n            // Making sure we only initialize once. We do that in the Layout event, which is called before repaint\n            if (Event.current.type == EventType.Layout)\n                Initialize(curEventIndex, descs);\n\n            if (m_CachedEventData == null)\n                return;\n\n            // Make sure the window is scrollable...\n            GUILayout.BeginArea(rect);\n            m_ScrollViewVector = EditorGUILayout.BeginScrollView(m_ScrollViewVector);\n\n            // Toolbar\n            Profiler.BeginSample(\"DrawToolbar\");\n            DrawRenderTargetToolbar();\n            Profiler.EndSample();\n\n            // Title\n            Profiler.BeginSample(\"DrawTitle\");\n            GUILayout.BeginHorizontal(FrameDebuggerStyles.EventDetails.s_TitleHorizontalStyle);\n            EditorGUILayout.LabelField(m_CachedEventData.m_Title, FrameDebuggerStyles.EventDetails.s_TitleStyle);\n            GUILayout.EndHorizontal();\n            if (Event.current.type == EventType.ContextClick)\n                ShaderPropertyCopyValueMenu(GUILayoutUtility.GetLastRect(), FrameDebuggerStyles.EventDetails.s_CopyEventText, () => m_CachedEventData.copyString);\n            Profiler.EndSample();\n\n            // Output & Mesh\n            // We disable Output and Mesh for Compute and Ray Tracing events\n            bool shouldDrawOutput = !m_CachedEventData.m_IsComputeEvent && !m_CachedEventData.m_IsRayTracingEvent;\n            Profiler.BeginSample(\"DrawOutputAndMesh\");\n            DrawOutputFoldout(rect, shouldDrawOutput, isDebuggingEditor);\n            Profiler.EndSample();\n\n            // Event Details\n            Profiler.BeginSample(\"DrawDetails\");\n            DrawDetails(rect);\n            Profiler.EndSample();\n\n            Profiler.BeginSample(\"DrawMeshFoldout\");\n            bool shouldDrawMesh = shouldDrawOutput && !FrameDebugger.IsRemoteEnabled();\n            DrawMeshFoldout(rect, shouldDrawMesh, isDebuggingEditor);\n            Profiler.EndSample();\n\n            ShaderPropertyCollection[] shaderProperties = m_CachedEventData.m_ShaderProperties;\n            if (shaderProperties != null && shaderProperties.Length > 0)\n            {\n                // Shader keywords & properties...\n                Profiler.BeginSample(\"DrawKeywords\");\n                DrawShaderData(ShaderPropertyType.Keyword, 2, FrameDebuggerStyles.EventDetails.s_FoldoutKeywordsText, m_CachedEventData.m_Keywords);\n                Profiler.EndSample();\n\n                Profiler.BeginSample(\"DrawTextureProperties\");\n                DrawShaderData(ShaderPropertyType.Texture, 3, FrameDebuggerStyles.EventDetails.s_FoldoutTexturesText, m_CachedEventData.m_Textures);\n                Profiler.EndSample();\n\n                Profiler.BeginSample(\"DrawIntProperties\");\n                DrawShaderData(ShaderPropertyType.Int, 4, FrameDebuggerStyles.EventDetails.s_FoldoutIntsText, m_CachedEventData.m_Ints);\n                Profiler.EndSample();\n\n                Profiler.BeginSample(\"DrawFloatProperties\");\n                DrawShaderData(ShaderPropertyType.Float, 5, FrameDebuggerStyles.EventDetails.s_FoldoutFloatsText, m_CachedEventData.m_Floats);\n                Profiler.EndSample();\n\n                Profiler.BeginSample(\"DrawVectorProperties\");\n                DrawShaderData(ShaderPropertyType.Vector, 6, FrameDebuggerStyles.EventDetails.s_FoldoutVectorsText, m_CachedEventData.m_Vectors);\n                Profiler.EndSample();\n\n                Profiler.BeginSample(\"DrawMatrixProperties\");\n                DrawShaderData(ShaderPropertyType.Matrix, 7, FrameDebuggerStyles.EventDetails.s_FoldoutMatricesText, m_CachedEventData.m_Matrices);\n                Profiler.EndSample();\n\n                Profiler.BeginSample(\"DrawBufferProperties\");\n                DrawShaderData(ShaderPropertyType.Buffer, 8, FrameDebuggerStyles.EventDetails.s_FoldoutBuffersText, m_CachedEventData.m_Buffers);\n                Profiler.EndSample();\n\n                Profiler.BeginSample(\"DrawConstantBufferProperties\");\n                DrawShaderData(ShaderPropertyType.CBuffer, 9, FrameDebuggerStyles.EventDetails.s_FoldoutCBufferText, m_CachedEventData.m_CBuffers);\n                Profiler.EndSample();\n            }\n\n            EditorGUILayout.EndScrollView();\n            GUILayout.EndArea();\n        }\n\n        ///////////////////////////////////////////////\n        // PRIVATE\n        ///////////////////////////////////////////////\n\n        private void Initialize(int curEventIndex, FrameDebuggerEvent[] descs)\n        {\n            Profiler.BeginSample(\"Initialize\");\n\n            uint eventDataHash = FrameDebuggerUtility.eventDataHash;\n            bool isReceivingFrameEventData = FrameDebugger.IsRemoteEnabled() && FrameDebuggerUtility.receivingRemoteFrameEventData;\n            bool isFrameEventDataValid = curEventIndex == curEventData.m_FrameEventIndex;\n\n            if (!isFrameEventDataValid\n                 || m_CachedEventData == null\n                 || !m_CachedEventData.m_IsValid\n                 || m_CachedEventData.m_Index != curEventIndex\n                 || (eventDataHash != 0 && (eventDataHash != m_CachedEventData.m_Hash))\n                )\n            {\n                if (m_CachedEventData == null)\n                    m_CachedEventData = new CachedEventDisplayData();\n\n                // Release the texture...\n                FrameDebuggerHelper.ReleaseTemporaryTexture(ref m_RenderTargetRenderTextureCopy);\n\n                isFrameEventDataValid = FrameDebuggerUtility.GetFrameEventData(curEventIndex, curEventData);\n                m_CachedEventData.m_IsValid = false;\n            }\n\n            // event type and draw call info\n            curEvent = descs[curEventIndex];\n            FrameEventType eventType = curEvent.m_Type;\n\n            // Rebuild strings...\n            if (isFrameEventDataValid)\n            {\n                if (!m_CachedEventData.m_IsValid || m_CachedEventData.m_Index != curEventIndex || m_CachedEventData.m_Type != eventType)\n                {\n                    m_CachedEventData.m_Hash = eventDataHash;\n                    m_CachedEventData.Initialize(curEvent, curEventData);\n                }\n            }\n\n            if (m_FoldoutAnimators == null || m_FoldoutAnimators.Length == 0)\n            {\n                m_FoldoutAnimators = new AnimBool[k_NumberGUISections];\n                for (int i = 0; i < m_FoldoutAnimators.Length; i++)\n                {\n                    bool val = EditorPrefs.HasKey(k_foldoutKeys[i]) ? EditorPrefs.GetBool(k_foldoutKeys[i]) : false;\n                    m_FoldoutAnimators[i] = new AnimBool(val);\n                }\n            }\n            Profiler.EndSample();\n        }\n\n        private void DrawRenderTargetToolbar()\n        {\n            if (m_CachedEventData.m_IsRayTracingEvent)\n                return;\n\n            bool isDepthOnlyRT = GraphicsFormatUtility.IsDepthFormat((GraphicsFormat)curEventData.m_RenderTargetFormat);\n            bool isClearAction = (int)curEvent.m_Type <= 7;\n            bool hasShowableDepth = (curEventData.m_RenderTargetHasDepthTexture != 0);\n            bool hasStencil = (curEventData.m_RenderTargetHasStencilBits != 0);\n            int showableRTCount = curEventData.m_RenderTargetCount;\n\n            if (hasShowableDepth)\n                showableRTCount++;\n\n            GUILayout.BeginHorizontal(FrameDebuggerStyles.EventToolbar.s_HorizontalStyle);\n\n            // MRT to show\n            EditorGUI.BeginChangeCheck();\n            GUI.enabled = showableRTCount > 1;\n\n            var rtNames = new GUIContent[showableRTCount + (hasStencil ? 1 : 0)];\n            for (var i = 0; i < showableRTCount; ++i)\n                rtNames[i] = FrameDebuggerStyles.EventToolbar.s_MRTLabels[i];\n\n            if (hasShowableDepth)\n                rtNames[curEventData.m_RenderTargetCount] = FrameDebuggerStyles.EventToolbar.s_DepthLabel;\n\n            if (hasStencil)\n                rtNames[rtNames.Length - 1] = FrameDebuggerStyles.EventToolbar.s_StencilLabel;\n\n            // Render Target Selection\n            // --------------------------------\n            // The UI Dropdown and FrameDebugger use different\n            // indices so we need to convert between the two:\n            //              Dropdown           Frame Debugger\n            // Depth   | Penultimate item   |       -1\n            // Stencil | Last item          |       -2\n\n            // If we showed depth/stencil before then try to keep showing depth/stencil\n            // otherwise try to keep showing color\n            if (m_RTIndexLastSet == -1)\n                m_RTIndex = hasShowableDepth ? showableRTCount - 1 : 0;\n            else if (m_RTIndexLastSet == -2)\n                m_RTIndex = hasStencil ? showableRTCount : 0;\n            else if (m_RTIndex > curEventData.m_RenderTargetCount)\n                m_RTIndex = 0;\n\n            m_RTIndex = EditorGUILayout.Popup(m_RTIndex, rtNames, FrameDebuggerStyles.EventToolbar.s_PopupLeftStyle, GUILayout.Width(70));\n\n            int rtIndexToSet = m_RTIndex;\n            if (hasShowableDepth && rtIndexToSet == (showableRTCount - 1))\n                rtIndexToSet = -1;\n\n            if (hasStencil && rtIndexToSet == showableRTCount)\n                rtIndexToSet = showableRTCount > 1 ? -2 : -1;\n\n            // --------------------------------\n\n            GUI.enabled = !isDepthOnlyRT;\n\n            SelectedColorChannel channelToDisplay = SelectedColorChannel.None;\n\n            bool forceUpdate = false;\n            \n            // Negative RT index: display depth or stencil buffer\n            bool isDepthOrStencilSelected = m_RTIndexLastSet < 0;\n\n            bool shouldDisableChannelButtons = isDepthOnlyRT || isClearAction || isDepthOrStencilSelected;\n            GUI.enabled = shouldDisableChannelButtons;\n            UInt32 componentCount = GraphicsFormatUtility.GetComponentCount((GraphicsFormat)curEventData.m_RenderTargetFormat);\n            GUILayout.BeginHorizontal();\n            {\n                for (int i = 0; i < FrameDebuggerStyles.EventToolbar.s_ChannelLabels.Length; i++)\n                {\n                    SelectedColorChannel channelFlag = (SelectedColorChannel)(1 << i);\n\n                    GUI.enabled = !shouldDisableChannelButtons && componentCount > i;\n\n                    if (GUILayout.Toggle(\n                            m_SelectedColorChannel.HasFlag(channelFlag),\n                            FrameDebuggerStyles.EventToolbar.s_ChannelLabels[i],\n                            FrameDebuggerStyles.EventToolbar.s_ChannelStyle))\n                    {\n                        // Update selected channel and channelToDisplay\n                        m_RTSelectedChannel = i + 1;\n                        channelToDisplay |= channelFlag;\n                    }\n                }\n\n                GUI.enabled = true;\n\n                // Force the channel to be \"All\" when:\n                if (isDepthOnlyRT || isClearAction || isDepthOrStencilSelected) // Showing Shadows/Depth/Clear\n                    channelToDisplay = SelectedColorChannel.All;\n                else if (m_RTSelectedChannel < 4 && componentCount < m_RTSelectedChannel) // Channel index is higher then the number available channels\n                    channelToDisplay = SelectedColorChannel.All;\n\n                if (channelToDisplay != m_SelectedColorChannel)\n                {\n                    forceUpdate = true;\n                    m_SelectedColorChannel = channelToDisplay;\n                }\n            }\n            GUILayout.EndHorizontal();\n\n            GUI.enabled = true;\n\n            // levels\n            GUILayout.BeginHorizontal(FrameDebuggerStyles.EventToolbar.s_LevelsHorizontalStyle);\n            GUILayout.Label(FrameDebuggerStyles.EventToolbar.s_LevelsHeader);\n\n            float blackMinLevel = EditorGUILayout.DelayedFloatField(m_RTBlackMinLevel);\n            float blackLevel = m_RTBlackLevel;\n            float whiteLevel = m_RTWhiteLevel;\n            EditorGUILayout.MinMaxSlider(ref blackLevel, ref whiteLevel, m_RTBlackMinLevel, m_RTWhiteMaxLevel, GUILayout.MinWidth(300.0f));\n            float whiteMaxLevel = EditorGUILayout.DelayedFloatField(m_RTWhiteMaxLevel);\n\n            if (blackMinLevel < whiteMaxLevel)\n            {\n                m_RTBlackMinLevel = blackMinLevel;\n                m_RTWhiteMaxLevel = whiteMaxLevel;\n\n                m_RTBlackLevel = Mathf.Clamp(blackLevel, m_RTBlackMinLevel, whiteLevel);\n                m_RTWhiteLevel = Mathf.Clamp(whiteLevel, blackLevel, m_RTWhiteMaxLevel);\n            }\n\n            if (EditorGUI.EndChangeCheck()\n                || (!isDepthOnlyRT && (rtIndexToSet != m_RTIndexLastSet))\n                || forceUpdate)\n            {\n                m_SelectedMask = new Vector4(\n                    channelToDisplay.HasFlag(SelectedColorChannel.R) ? 1.0f : 0.0f, // x (Red)\n                    channelToDisplay.HasFlag(SelectedColorChannel.G) ? 1.0f : 0.0f, // y (Green)\n                    channelToDisplay.HasFlag(SelectedColorChannel.B) ? 1.0f : 0.0f, // z (Blue)\n                    channelToDisplay.HasFlag(SelectedColorChannel.A) ? 1.0f : 0.0f  // w (Alpha)\n                );\n                FrameDebuggerUtility.SetRenderTargetDisplayOptions(rtIndexToSet, m_SelectedMask, m_RTBlackLevel, m_RTWhiteLevel);\n                m_FrameDebugger.RepaintAllNeededThings();\n                m_RTIndexLastSet = rtIndexToSet;\n                FrameDebuggerHelper.ReleaseTemporaryTexture(ref m_RenderTargetRenderTextureCopy);\n            }\n            else if (m_RTIndexLastSet == -2 && showableRTCount <= 1)\n            {\n                m_RTIndexLastSet = -1;\n                FrameDebuggerUtility.SetRenderTargetDisplayOptions(-1, m_SelectedMask, m_RTBlackLevel, m_RTWhiteLevel);\n            }\n\n            GUILayout.EndHorizontal();\n            GUILayout.FlexibleSpace();\n            GUILayout.EndHorizontal();\n\n            GUI.enabled = true;\n        }\n\n        private void DrawOutputFoldout(Rect rect, bool shouldDrawOutput, bool isDebuggingEditor)\n        {\n            if (BeginFoldoutBox(0, shouldDrawOutput, FrameDebuggerStyles.EventDetails.s_FoldoutOutputText, out float fadePercent, null))\n            {\n                if (shouldDrawOutput)\n                {\n                    EditorGUILayout.BeginVertical();\n                    {\n                        float viewportWidth = rect.width - 30f;\n                        float viewportHeightFaded = FrameDebuggerStyles.EventDetails.k_MaxViewportHeight * fadePercent;\n                        float renderTargetWidth = m_CachedEventData.m_RenderTargetWidth;\n                        float renderTargetHeight = m_CachedEventData.m_RenderTargetHeight;\n\n                        float scaledRenderTargetWidth = renderTargetWidth;\n                        float scaledRenderTargetHeight = renderTargetHeight;\n\n                        if (scaledRenderTargetWidth > viewportWidth)\n                        {\n                            float scale = viewportWidth / scaledRenderTargetWidth;\n                            scaledRenderTargetWidth *= scale;\n                            scaledRenderTargetHeight *= scale;\n                        }\n\n                        if (scaledRenderTargetHeight > FrameDebuggerStyles.EventDetails.k_MaxViewportHeight)\n                        {\n                            float scale = FrameDebuggerStyles.EventDetails.k_MaxViewportHeight / scaledRenderTargetHeight;\n                            scaledRenderTargetWidth *= scale;\n                            scaledRenderTargetHeight = FrameDebuggerStyles.EventDetails.k_MaxViewportHeight;\n                        }\n\n                        DrawTargetTexture(rect, viewportWidth, viewportHeightFaded, renderTargetWidth, renderTargetHeight, scaledRenderTargetWidth, scaledRenderTargetHeight, fadePercent, isDebuggingEditor);\n                    }\n                    GUILayout.EndVertical();\n                }\n            }\n            EndFoldoutBox();\n        }\n\n        private void DrawTargetTexture(Rect rect, float viewportWidth, float viewportHeight, float renderTargetWidth, float renderTargetHeight, float scaledRenderTargetWidth, float scaledRenderTargetHeight, float fadePercent, bool isDebuggingEditor)\n        {\n            EditorGUILayout.BeginHorizontal(FrameDebuggerStyles.EventDetails.s_RenderTargetMeshBackgroundStyle);\n            Rect previewRect = GUILayoutUtility.GetRect(viewportWidth, viewportHeight);\n\n            // Early out if the texture is so small it can not be drawn...\n            int scaledTexWidthInt = (int) scaledRenderTargetWidth;\n            int scaledTexHeightInt = (int) scaledRenderTargetHeight;\n            if (scaledTexWidthInt <= 0 || scaledTexHeightInt <= 0)\n            {\n                EditorGUILayout.EndHorizontal();\n                return;\n            }\n\n            // We insert a dummy Draw Texture call when not repainting.\n            if (Event.current.type != EventType.Repaint)\n            {\n                GUI.DrawTexture(Rect.zero, null, ScaleMode.ScaleAndCrop, false, (scaledRenderTargetWidth / scaledRenderTargetHeight));\n                EditorGUILayout.EndHorizontal();\n                return;\n            }\n\n            float yPos = previewRect.y;\n            if (viewportHeight > scaledRenderTargetHeight)\n                yPos += (viewportHeight - scaledRenderTargetHeight) * 0.5f;\n\n            float xPos = 10f + Mathf.Max(viewportWidth * 0.5f - scaledRenderTargetWidth * 0.5f, 0f);\n\n            // This is a weird one. When opening/closing the foldout, the image\n            // shifts a tiny bit to the right. This magic code prevents that.\n            if (fadePercent < 1f)\n                xPos -= 7f;\n\n            Rect textureRect = new Rect(xPos, yPos, scaledRenderTargetWidth, scaledRenderTargetHeight);\n\n            if (m_RenderTargetRenderTextureCopy)\n            {\n                GUI.DrawTexture(textureRect, m_RenderTargetRenderTextureCopy, ScaleMode.ScaleAndCrop, false, (scaledRenderTargetWidth / scaledRenderTargetHeight));\n            }\n            else if (m_CachedEventData.m_RenderTargetRenderTexture && previewRect.height > 1.0f)\n            {\n                GraphicsFormat targetTextureFormat = m_CachedEventData.m_RenderTargetFormat;\n                uint componentCount = GraphicsFormatUtility.GetComponentCount(targetTextureFormat);\n\n                // On some devices the backbuffer gives the None Graphics Format. To prevent us\n                // displaying a black & white texture we force the channels to the selected mask.\n                bool shouldForceSelectedMask = targetTextureFormat == GraphicsFormat.None && m_CachedEventData.m_RenderTargetIsBackBuffer;\n                Vector4 channels = (!m_CachedEventData.m_RenderTargetIsDepthOnlyRT && (componentCount > 1 || shouldForceSelectedMask)) ? m_SelectedMask : new Vector4(1, 0, 0, 0);\n\n                bool linearColorSpace = QualitySettings.activeColorSpace == ColorSpace.Linear;\n                bool textureSRGB = GraphicsFormatUtility.IsSRGBFormat(targetTextureFormat);\n                bool undoOutputSRGB = (isDebuggingEditor && (!linearColorSpace || textureSRGB)) ? false : true;\n                bool shouldYFlip = m_CachedEventData.m_RenderTargetIsBackBuffer && isDebuggingEditor && SystemInfo.graphicsUVStartsAtTop;\n                Vector4 levels = new Vector4(m_RTBlackLevel, m_RTWhiteLevel, 0f, 0f);\n\n                // Get a temporary texture...\n                int renderTargetWidthInt = (int)renderTargetWidth;\n                int renderTargetHeightInt = (int)renderTargetHeight;\n                m_RenderTargetRenderTextureCopy = RenderTexture.GetTemporary(renderTargetWidthInt, renderTargetHeightInt);\n\n                // Blit with the settings from the toolbar...\n                FrameDebuggerHelper.BlitToRenderTexture(\n                    ref m_CachedEventData.m_RenderTargetRenderTexture,\n                    ref m_RenderTargetRenderTextureCopy,\n                    renderTargetWidthInt,\n                    renderTargetHeightInt,\n                    channels,\n                    levels,\n                    shouldYFlip,\n                    undoOutputSRGB\n                );\n\n                // Draw the texture to the screen...\n                GUI.DrawTexture(textureRect, m_RenderTargetRenderTextureCopy, ScaleMode.ScaleAndCrop, false, (scaledRenderTargetWidth / scaledRenderTargetHeight));\n            }\n\n            EditorGUILayout.EndHorizontal();\n        }\n\n        private void DrawMeshFoldout(Rect rect, bool shouldDrawMesh, bool isDebuggingEditor)\n        {\n            // Not supported on remote players so we change the foldout header to show that.\n            GUIContent header;\n            bool shouldDraw;\n            if (FrameDebugger.IsRemoteEnabled())\n            {\n                shouldDraw = false;\n                header = FrameDebuggerStyles.EventDetails.s_FoldoutMeshNotSupportedText;\n            }\n            else\n            {\n                shouldDraw = shouldDrawMesh && m_CachedEventData.m_Meshes != null && m_CachedEventData.m_Meshes.Length > 0;\n                header = FrameDebuggerStyles.EventDetails.s_FoldoutMeshText;\n            }\n\n\n            if (BeginFoldoutBox(10, shouldDraw, header, out float fadePercent, null) && shouldDraw)\n            {\n                // Safety checks as things can get go wrong when switching between editor and remote...\n                m_MeshIndex = Mathf.Min(m_MeshIndex, m_CachedEventData.m_Meshes.Length - 1);\n                for (int i = 0; i < m_CachedEventData.m_Meshes.Length; i++)\n                {\n                    if (m_CachedEventData.m_Meshes[i] == null)\n                    {\n                        EndFoldoutBox();\n                        return;\n                    }\n                }\n\n                // Draw the Mesh Preview\n                EditorGUILayout.BeginHorizontal();\n                EditorGUILayout.BeginVertical();\n                {\n                    float viewportWidth = rect.width - 30f;\n                    float viewportHeightFaded = FrameDebuggerStyles.EventDetails.k_MaxViewportHeight * fadePercent;\n                    float renderTargetWidth = m_CachedEventData.m_RenderTargetWidth;\n                    float renderTargetHeight = m_CachedEventData.m_RenderTargetHeight;\n\n                    float scaledRenderTargetWidth = renderTargetWidth;\n                    float scaledRenderTargetHeight = renderTargetHeight;\n\n                    if (scaledRenderTargetWidth > viewportWidth)\n                    {\n                        float scale = viewportWidth / scaledRenderTargetWidth;\n                        scaledRenderTargetWidth *= scale;\n                        scaledRenderTargetHeight *= scale;\n                    }\n\n                    if (scaledRenderTargetHeight > FrameDebuggerStyles.EventDetails.k_MaxViewportHeight)\n                    {\n                        float scale = FrameDebuggerStyles.EventDetails.k_MaxViewportHeight / scaledRenderTargetHeight;\n                        scaledRenderTargetWidth *= scale;\n                        scaledRenderTargetHeight = FrameDebuggerStyles.EventDetails.k_MaxViewportHeight;\n                    }\n\n                    DrawEventMesh(viewportWidth, viewportHeightFaded, scaledRenderTargetWidth);\n                }\n                GUILayout.EndVertical();\n                EditorGUILayout.EndHorizontal();\n\n                // Draw the list of meshes to select from...\n                EditorGUILayout.BeginHorizontal();\n                EditorGUILayout.LabelField(FrameDebuggerStyles.EventDetails.s_FoldoutMeshText, FrameDebuggerStyles.EventDetails.s_MonoLabelStyle);\n                EditorGUILayout.EndHorizontal();\n\n                bool clicked = false;\n                GUIStyle style;\n                for (int i = 0; i < m_CachedEventData.m_Meshes.Length; i++)\n                {\n                    if (m_CachedEventData.m_Meshes[i] == null)\n                        continue;\n\n                    style = (i == m_MeshIndex) ? FrameDebuggerStyles.EventDetails.s_MonoLabelBoldPaddingStyle : FrameDebuggerStyles.EventDetails.s_MonoLabelStylePadding;\n\n                    // Draw...\n                    EditorGUILayout.BeginHorizontal();\n                        // Mesh Name to select for the preview...\n                        clicked = GUILayout.Button(m_CachedEventData.m_Meshes[i].name, style);\n\n                        // Object Field to ping the object in the Project View\n                        GUI.enabled = false;\n                        EditorGUILayout.ObjectField(m_CachedEventData.m_Meshes[i], typeof(Mesh), true, GUILayout.Width(FrameDebuggerStyles.EventDetails.k_ShaderObjectFieldWidth));\n                        GUI.enabled = true;\n                    EditorGUILayout.EndHorizontal();\n\n                    // Update the mesh index if the label was clicked...\n                    if (clicked)\n                        m_MeshIndex = Mathf.Min(i, m_CachedEventData.m_Meshes.Length - 1);\n                }\n\n                if (m_Preview != null && m_CachedEventData.m_Meshes[m_MeshIndex] != null)\n                    m_Preview.mesh = m_CachedEventData.m_Meshes[m_MeshIndex];\n            }\n            EndFoldoutBox();\n        }\n\n        private void DrawEventMesh(float viewportWidth, float viewportHeight, float texWidth)\n        {\n            if (viewportHeight - FrameDebuggerStyles.EventDetails.k_MeshBottomToolbarHeight < 1.0f)\n                return;\n\n            if (m_CachedEventData.m_Meshes == null || m_CachedEventData.m_Meshes.Length == 0 || m_CachedEventData.m_Meshes[m_MeshIndex] == null)\n            {\n                DrawEventMeshBackground(viewportWidth, viewportHeight);\n                return;\n            }\n\n            if (m_Preview == null)\n                m_Preview = new MeshPreview(m_CachedEventData.m_Meshes[m_MeshIndex]);\n            else if (m_Preview.mesh == null)\n                m_Preview.mesh = m_CachedEventData.m_Meshes[m_MeshIndex];\n\n            // We need this rect called here to push the control buttons below the Mesh...\n            Rect previewRect = GUILayoutUtility.GetRect(viewportWidth - 100, viewportHeight - FrameDebuggerStyles.EventDetails.k_MeshBottomToolbarHeight, GUILayout.ExpandHeight(false));\n\n            // Rectangle for the buttons...\n            Rect rect = EditorGUILayout.BeginHorizontal(GUIContent.none, EditorStyles.toolbar, GUILayout.Height(FrameDebuggerStyles.EventDetails.k_MeshBottomToolbarHeight));\n            {\n                GUILayout.FlexibleSpace();\n                m_Preview.OnPreviewSettings();\n            }\n            EditorGUILayout.EndHorizontal();\n\n            var evt = Event.current;\n            if (FrameDebuggerHelper.IsHoveringRect(previewRect) || evt.type != EventType.ScrollWheel)\n            {\n                m_Preview?.OnPreviewGUI(previewRect, EditorStyles.helpBox);\n            }\n        }\n\n        private void DrawEventMeshBackground(float viewportWidth, float viewportHeight)\n        {\n            EditorGUILayout.BeginHorizontal(FrameDebuggerStyles.EventDetails.s_RenderTargetMeshBackgroundStyle, GUILayout.Width(viewportWidth));\n            GUILayoutUtility.GetRect(viewportWidth, viewportHeight);\n            EditorGUILayout.EndHorizontal();\n        }\n\n        private void DrawDetails(Rect rect)\n        {\n            bool isFoldoutOpen = BeginFoldoutBox(1, true, FrameDebuggerStyles.EventDetails.s_FoldoutEventDetailsText, out float fadePercent, () => m_CachedEventData.detailsCopyString);\n            if (!isFoldoutOpen)\n            {\n                EndFoldoutBox();\n                return;\n            }\n\n            GUIStyle style = FrameDebuggerStyles.EventDetails.s_MonoLabelStyle;\n\n            // Size, Color Actions, Blending, Z, Stencil...\n            EditorGUILayout.BeginHorizontal();\n            EditorGUILayout.LabelField(m_CachedEventData.details, style, GUILayout.MinWidth(m_CachedEventData.m_DetailsGUIWidth), GUILayout.MinHeight(m_CachedEventData.m_DetailsGUIHeight));\n            EditorGUILayout.EndHorizontal();\n\n            // Shader\n            if (m_CachedEventData.m_ShouldDisplayRealAndOriginalShaders)\n            {\n                EditorGUILayout.BeginHorizontal();\n                EditorGUILayout.LabelField(FrameDebuggerStyles.EventDetails.s_RealShaderText, style, GUILayout.Width(FrameDebuggerStyles.EventDetails.k_ShaderLabelWidth));\n                if (m_CachedEventData.m_RealShader == null)\n                    EditorGUILayout.LabelField(m_CachedEventData.m_RealShaderName, style);\n                else\n                {\n                    GUI.enabled = false;\n                    EditorGUILayout.ObjectField(m_CachedEventData.m_RealShader, typeof(Shader), true, GUILayout.Width(FrameDebuggerStyles.EventDetails.k_ShaderObjectFieldWidth));\n                    GUI.enabled = true;\n                }\n                EditorGUILayout.EndHorizontal();\n\n                EditorGUILayout.BeginHorizontal();\n                EditorGUILayout.LabelField(FrameDebuggerStyles.EventDetails.s_OriginalShaderText, GUILayout.Width(FrameDebuggerStyles.EventDetails.k_ShaderLabelWidth));\n                if (m_CachedEventData.m_OriginalShader == null)\n                    EditorGUILayout.LabelField(m_CachedEventData.m_OriginalShaderName, style);\n                else\n                {\n                    GUI.enabled = false;\n                    EditorGUILayout.ObjectField(m_CachedEventData.m_OriginalShader, typeof(Shader), true, GUILayout.Width(FrameDebuggerStyles.EventDetails.k_ShaderObjectFieldWidth));\n                    GUI.enabled = true;\n                }\n                EditorGUILayout.EndHorizontal();\n            }\n\n            EndFoldoutBox();\n        }\n\n        private void DrawShaderData(ShaderPropertyType propType, int foldoutIndex, GUIContent foldoutText, ShaderPropertyCollection shaderProperties)\n        {\n            ShaderPropertyDisplayInfo[] propertyDisplayInfo = shaderProperties.m_Data;\n\n            // We disable and hide keywords and shader properties for clear and resolve events or when we don't have any data.\n            bool shouldDisplayProperties = !m_CachedEventData.m_IsClearEvent && !m_CachedEventData.m_IsResolveEvent;\n            bool shouldDraw = shouldDisplayProperties && propertyDisplayInfo != null && propertyDisplayInfo.Length > 0;\n            bool isFoldoutOpen = BeginFoldoutBox(foldoutIndex, shouldDraw, foldoutText, out float fadePercent, () => shaderProperties.copyString);\n\n            if (!shouldDraw || !isFoldoutOpen)\n            {\n                EndFoldoutBox();\n                return;\n            }\n\n            GUILayout.BeginVertical(FrameDebuggerStyles.EventDetails.s_PropertiesBottomMarginStyle);\n\n            GUILayout.BeginHorizontal(FrameDebuggerStyles.EventDetails.s_PropertiesLeftMarginStyle);\n            GUILayout.Label(shaderProperties.m_Header, FrameDebuggerStyles.EventDetails.s_MonoLabelBoldStyle);\n            GUILayout.EndHorizontal();\n\n            for (int i = 0; i < propertyDisplayInfo.Length; i++)\n            {\n                ShaderPropertyDisplayInfo data = propertyDisplayInfo[i];\n                if (!data.m_IsArray)\n                {\n                    Texture textureToDisplay = data.m_TextureCopy != null ? data.m_TextureCopy as Texture : data.m_Texture;\n                    if (textureToDisplay == null)\n                    {\n                        GUILayout.BeginHorizontal(FrameDebuggerStyles.EventDetails.s_PropertiesLeftMarginStyle);\n                        GUILayout.Label(data.m_PropertyString, FrameDebuggerStyles.EventDetails.s_MonoLabelNoWrapStyle);\n                    }\n                    else\n                    {\n                        GUILayout.BeginHorizontal();\n\n                        // Texture Preview..\n                        // for 2D textures, we want to display them directly as a preview (this will make render textures display their contents) but\n                        // for cube maps and other non-2D types DrawPreview does not do anything useful right now, so get their asset type icon at least\n                        bool isTex2D = textureToDisplay.dimension == TextureDimension.Tex2D;\n                        Texture previewTexture = isTex2D ? textureToDisplay : AssetPreview.GetMiniThumbnail(textureToDisplay);\n                        Rect previewRect = GUILayoutUtility.GetRect(10, 10, FrameDebuggerStyles.EventDetails.s_TextureButtonStyle);\n                        previewRect.width = 10;\n                        previewRect.height = 10;\n                        previewRect.x += 4f;\n                        previewRect.y += 6f;\n\n                        GUI.DrawTexture(previewRect, previewTexture, ScaleMode.StretchToFill, false);\n                        GUILayout.Label(data.m_PropertyString, FrameDebuggerStyles.EventDetails.s_MonoLabelNoWrapStyle);\n\n                        if (FrameDebuggerHelper.IsCurrentEventMouseDown() && FrameDebuggerHelper.IsClickingRect(previewRect))\n                        {\n                            PopupWindowWithoutFocus.Show(\n                                previewRect,\n                                new ObjectPreviewPopup(textureToDisplay),\n                                new[] { PopupLocation.Left, PopupLocation.Below, PopupLocation.Right }\n                            );\n                        }\n                    }\n                    GUILayout.EndHorizontal();\n                }\n                else\n                {\n                    GUILayout.BeginVertical(FrameDebuggerStyles.EventDetails.s_PropertiesLeftMarginStyle);\n\n                    data.m_IsFoldoutOpen = EditorGUILayout.Foldout(data.m_IsFoldoutOpen, data.m_FoldoutString, FrameDebuggerStyles.EventDetails.s_ArrayFoldoutStyle);\n                    if (data.m_IsFoldoutOpen)\n                        GUILayout.Label(data.m_PropertyString, data.m_ArrayGUIStyle);\n\n                    GUILayout.EndVertical();\n                }\n                propertyDisplayInfo[i] = data;\n\n                if (Event.current.type == EventType.ContextClick)\n                    ShaderPropertyCopyValueMenu(GUILayoutUtility.GetLastRect(), FrameDebuggerStyles.EventDetails.s_CopyPropertyText, () => data.copyString);\n            }\n            GUILayout.EndVertical();\n            EndFoldoutBox();\n        }\n\n        private bool BeginFoldoutBox(int foldoutIndex, bool hasData, GUIContent header, out float fadePercent, Func<string> copyStringAction = null)\n        {\n            GUI.enabled = hasData;\n\n            EditorGUILayout.BeginVertical(FrameDebuggerStyles.EventDetails.s_FoldoutCategoryBoxStyle);\n            Rect r = GUILayoutUtility.GetRect(2, 21);\n\n            EditorGUI.BeginChangeCheck();\n            bool expanded = EditorGUI.FoldoutTitlebar(r, header, m_FoldoutAnimators[foldoutIndex].target, true, EditorStyles.inspectorTitlebarFlat, EditorStyles.inspectorTitlebarText);\n            if (EditorGUI.EndChangeCheck())\n            {\n                bool newState = !m_FoldoutAnimators[foldoutIndex].target;\n                EditorPrefs.SetBool(k_foldoutKeys[foldoutIndex], newState);\n\n                // If Shift is being held down, we change the state for all of them...\n                if (Event.current.shift || Event.current.alt)\n                    for (int i = m_FoldoutAnimators.Length - 1; i >= 0; i--)\n                        m_FoldoutAnimators[i].target = newState;\n                else\n                    m_FoldoutAnimators[foldoutIndex].target = newState;\n            }\n\n            if (Event.current.type == EventType.ContextClick)\n                if (copyStringAction != null && FrameDebuggerStyles.EventDetails.s_FoldoutCopyText[foldoutIndex] != null && copyStringAction != null)\n                    ShaderPropertyCopyValueMenu(r, FrameDebuggerStyles.EventDetails.s_FoldoutCopyText[foldoutIndex], copyStringAction);\n\n            GUI.enabled = true;\n            EditorGUI.indentLevel++;\n            fadePercent = m_FoldoutAnimators[foldoutIndex].faded;\n\n            return EditorGUILayout.BeginFadeGroup(m_FoldoutAnimators[foldoutIndex].faded);\n        }\n\n        private void EndFoldoutBox()\n        {\n            EditorGUILayout.EndFadeGroup();\n            EditorGUI.indentLevel--;\n            EditorGUILayout.EndVertical();\n        }\n\n        private void ShaderPropertyCopyValueMenu(Rect valueRect, GUIContent menuText, Func<string> textToCopy)\n        {\n            Profiler.BeginSample(\"ShaderPropertyCopyValueMenu\");\n            var e = Event.current;\n\n            // Copy function\n            if (valueRect.Contains(e.mousePosition))\n            {\n                e.Use();\n\n                GenericMenu menu = new GenericMenu();\n                menu.AddItem(menuText, false, delegate {\n                    if (textToCopy != null)\n                        EditorGUIUtility.systemCopyBuffer = textToCopy();\n                });\n                menu.ShowAsContext();\n            }\n\n            Profiler.EndSample();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PerformanceTools/FrameDebuggerEventDisplayData.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Text;\nusing System.Collections.Generic;\n\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEngine.Profiling;\nusing UnityEngine.Experimental.Rendering;\n\nusing UnityEditor;\n\nnamespace UnityEditorInternal.FrameDebuggerInternal\n{\n    internal struct ShaderPropertyCollection\n    {\n        internal string m_TypeName;\n        internal string m_Header;\n        internal string m_HeaderFormat;\n        internal string m_Format;\n        internal ShaderPropertyDisplayInfo[] m_Data;\n\n        internal void GetCopyText(ref StringBuilder sb)\n        {\n            sb.AppendLine(FrameDebuggerStyles.EventDetails.s_DashesString);\n            sb.AppendLine(m_TypeName);\n            sb.AppendLine(FrameDebuggerStyles.EventDetails.s_DashesString);\n\n            if (m_Data.Length == 0)\n            {\n                sb.AppendLine(\"<Empty>\");\n                sb.AppendLine();\n                return;\n            }\n\n            sb.AppendLine(m_Header);\n            for (int i = 0; i < m_Data.Length; i++)\n                m_Data[i].GetCopyText(ref sb);\n            sb.AppendLine();\n        }\n\n        internal string copyString\n        {\n            get\n            {\n                StringBuilder sb = new StringBuilder(4096);\n                GetCopyText(ref sb);\n                return sb.ToString();\n            }\n        }\n\n        internal void Clear()\n        {\n            for (int i = 0; i < m_Data.Length; i++)\n                m_Data[i].Clear();\n            m_Data = null;\n        }\n    }\n\n    internal struct ShaderPropertyDisplayInfo\n    {\n        internal bool m_IsArray;\n        internal bool m_IsFoldoutOpen;\n        internal string m_FoldoutString;\n        internal string m_PropertyString;\n        internal Texture m_Texture;\n        internal GUIStyle m_ArrayGUIStyle;\n        internal RenderTexture m_TextureCopy;\n\n        internal string copyString\n        {\n            get\n            {\n                StringBuilder sb = new StringBuilder(4096);\n                GetCopyText(ref sb);\n                return sb.ToString();\n            }\n        }\n\n        internal void Clear()\n        {\n            // We only need to destroy the copy texture as the other one is\n            // directly from source so it could be an asset in the project, etc.\n            if (m_TextureCopy != null)\n            {\n                FrameDebuggerHelper.DestroyTexture(ref m_TextureCopy);\n                m_TextureCopy = null;\n            }\n        }\n\n        internal void GetCopyText(ref StringBuilder sb)\n        {\n            if (!m_IsArray)\n                sb.AppendLine(m_PropertyString);\n            else\n            {\n                sb.AppendLine(m_FoldoutString);\n                sb.AppendLine(m_PropertyString);\n            }\n        }\n    }\n\n    internal enum ShaderPropertyType\n    {\n        Keyword = 0,\n        Texture = 1,\n        Int = 2,\n        Float = 3,\n        Vector = 4,\n        Matrix = 5,\n        Buffer = 6,\n        CBuffer = 7,\n    }\n\n    // Cached data built from FrameDebuggerEventData.\n    // Only need to rebuild them when event data actually changes.\n    internal class CachedEventDisplayData\n    {\n        internal int m_Index;\n        internal int m_RTDisplayIndex;\n        internal int m_RenderTargetWidth;\n        internal int m_RenderTargetHeight;\n        internal int m_RenderTargetShowableRTCount;\n        internal uint m_Hash;\n        internal bool m_IsValid;\n        internal bool m_IsClearEvent;\n        internal bool m_IsResolveEvent;\n        internal bool m_IsComputeEvent;\n        internal bool m_IsRayTracingEvent;\n        internal bool m_IsConfigureFoveatedEvent;\n        internal bool m_ShouldDisplayRealAndOriginalShaders;\n        internal bool m_RenderTargetIsBackBuffer;\n        internal bool m_RenderTargetIsDepthOnlyRT;\n        internal bool m_RenderTargetHasShowableDepth;\n        internal bool m_RenderTargetHasStencilBits;\n        internal float m_DetailsGUIWidth;\n        internal float m_DetailsGUIHeight;\n        internal string m_Title;\n        internal string m_RealShaderName;\n        internal string m_OriginalShaderName;\n        internal string m_RayTracingShaderName;\n        internal string m_RayTracingGenerationShaderName;\n        internal Mesh[] m_Meshes;\n        internal GUIContent[] m_MeshNames;\n        internal RenderTexture m_RenderTargetRenderTexture;\n        internal FrameEventType m_Type;\n        internal GraphicsFormat m_RenderTargetFormat;\n        internal UnityEngine.Object m_RealShader;\n        internal UnityEngine.Object m_OriginalShader;\n\n        internal string copyString\n        {\n            get\n            {\n                string detailsString = detailsCopyString;\n                m_StringBuilder.Clear();\n                m_StringBuilder.AppendLine(FrameDebuggerStyles.EventDetails.s_EqualsString);\n                m_StringBuilder.AppendLine(m_Title);\n                m_StringBuilder.AppendLine(FrameDebuggerStyles.EventDetails.s_EqualsString);\n                m_StringBuilder.AppendLine();\n                m_StringBuilder.AppendLine(detailsString);\n\n                for (int i = 0; i < m_ShaderProperties.Length; i++)\n                    m_ShaderProperties[i].GetCopyText(ref m_StringBuilder);\n\n                return m_StringBuilder.ToString();\n            }\n        }\n\n        internal string detailsCopyString\n        {\n            get\n            {\n                StringBuilder sb = new StringBuilder(4096);\n                sb.AppendLine(FrameDebuggerStyles.EventDetails.s_DashesString);\n                sb.AppendLine(\"Details\");\n                sb.AppendLine(FrameDebuggerStyles.EventDetails.s_DashesString);\n                sb.AppendLine(details);\n\n                if (m_ShouldDisplayRealAndOriginalShaders)\n                {\n                    sb.AppendFormat(k_TwoColumnFormat, FrameDebuggerStyles.EventDetails.s_RealShaderText, m_RealShaderName);\n                    sb.AppendLine();\n                    sb.AppendFormat(k_TwoColumnFormat, FrameDebuggerStyles.EventDetails.s_OriginalShaderText, m_OriginalShaderName);\n                    sb.AppendLine();\n                }\n                return sb.ToString();\n            }\n        }\n\n        private string m_Details;\n        internal string details\n        {\n            get\n            {\n                if (string.IsNullOrEmpty(m_Details))\n                    m_Details = m_DetailsStringBuilder.ToString();\n\n                return m_Details;\n            }\n        }\n\n        private string m_MeshNamesString;\n        internal string meshNames\n        {\n            get\n            {\n                if (string.IsNullOrEmpty(m_MeshNamesString))\n                    m_MeshNamesString = m_MeshStringBuilder.ToString();\n\n                return m_MeshNamesString;\n            }\n        }\n        internal ShaderPropertyCollection[] m_ShaderProperties;\n        internal ShaderPropertyCollection m_Keywords => m_ShaderProperties[(int)ShaderPropertyType.Keyword];\n        internal ShaderPropertyCollection m_Textures => m_ShaderProperties[(int)ShaderPropertyType.Texture];\n        internal ShaderPropertyCollection m_Ints     => m_ShaderProperties[(int)ShaderPropertyType.Int];\n        internal ShaderPropertyCollection m_Floats   => m_ShaderProperties[(int)ShaderPropertyType.Float];\n        internal ShaderPropertyCollection m_Vectors  => m_ShaderProperties[(int)ShaderPropertyType.Vector];\n        internal ShaderPropertyCollection m_Matrices => m_ShaderProperties[(int)ShaderPropertyType.Matrix];\n        internal ShaderPropertyCollection m_Buffers  => m_ShaderProperties[(int)ShaderPropertyType.Buffer];\n        internal ShaderPropertyCollection m_CBuffers => m_ShaderProperties[(int)ShaderPropertyType.CBuffer];\n\n        // Private\n        private int m_MaxNameLength;\n        private int m_MaxStageLength;\n        private int m_MaxTexSizeLength;\n        private int m_MaxSampleTypeLength;\n        private int m_MaxColorFormatLength;\n        private int m_MaxDepthFormatLength;\n        private int dataTypeEnumLength => Enum.GetNames(typeof(ShaderPropertyType)).Length;\n        private StringBuilder m_StringBuilder = new StringBuilder(32768);\n        private StringBuilder m_DetailsStringBuilder = new StringBuilder(4096);\n        private StringBuilder m_MeshStringBuilder = new StringBuilder(64);\n\n        // Constants\n        private const int k_MinNameLength = 38;\n        private const int k_MinStageLength = 5; // \"Stage\".Length\n        private const int k_MinTexSizeLength = 11; // \"65536x65536\".Length\n        private const int k_MinSampleTypeLength = 12; // \"Sampler Type\".Length\n        private const int k_MinColorFormatLength = 12; // \"Color Format\".Length\n        private const int k_MinDepthFormatLength = 19; // \"DepthStencil Format\".Length\n        private const int k_ColumnSpace = 2;\n        private const int k_MaxDecimalNumbers = 7;\n        private const int k_MaxNaturalNumber = 10 + k_MaxDecimalNumbers + 1 + 1; // + decimal point + sign\n        private const string k_TwoColumnFormat  = \"{0, -22}{1, -35}\";\n        private const string k_FourColumnFormat = \"{0, -22}{1, -35}{2, -22}{3, -10}\";\n        private static string s_IntPrecision = k_MaxNaturalNumber + \":F0\";\n        private static string s_FloatPrecision = k_MaxNaturalNumber + \":F\" + k_MaxDecimalNumbers;\n        private const string k_NotAvailableString = FrameDebuggerStyles.EventDetails.k_NotAvailable;\n\n        // Structs\n        private struct ShaderPropertySortingInfo : IComparable<ShaderPropertySortingInfo>\n        {\n            internal string m_Name;\n            internal int m_ArrayIndex;\n\n            public int CompareTo(ShaderPropertySortingInfo other)\n            {\n                return string.Compare(m_Name, other.m_Name);\n            }\n        }\n\n        internal void Initialize(FrameDebuggerEvent curEvent, FrameDebuggerEventData curEventData)\n        {\n            Clear();\n\n            BuildCurEventDataStrings(curEvent, curEventData);\n            BuildShaderPropertyData(curEventData);\n\n            if (curEventData.m_RenderTargetRenderTexture != null)\n            {\n                m_RenderTargetRenderTexture = curEventData.m_RenderTargetRenderTexture;\n\n                RenderTextureDescriptor desc = curEventData.m_RenderTargetRenderTexture.descriptor;\n                if (desc.width > 0 && desc.height > 0)\n                {\n                    m_RenderTargetWidth = desc.width;\n                    m_RenderTargetHeight = desc.height;\n                }\n                else\n                {\n                    m_RenderTargetWidth = curEventData.m_RenderTargetWidth;\n                    m_RenderTargetHeight = curEventData.m_RenderTargetHeight;\n                }\n                m_IsValid = true;\n            }\n            else\n            {\n                m_RenderTargetWidth = curEventData.m_RenderTargetWidth;\n                m_RenderTargetHeight = curEventData.m_RenderTargetHeight;\n                m_IsValid = m_IsComputeEvent || m_IsRayTracingEvent;\n            }\n        }\n\n        private void BuildShaderPropertyData(FrameDebuggerEventData curEventData)\n        {\n            ShaderInfo shaderInfo = curEventData.m_ShaderInfo;\n            m_ShaderProperties= new ShaderPropertyCollection[dataTypeEnumLength];\n            m_ShaderProperties[(int)ShaderPropertyType.Keyword] = GetShaderData(ShaderPropertyType.Keyword, \"Keywords\", ref shaderInfo, shaderInfo.m_Keywords.Length);\n            m_ShaderProperties[(int)ShaderPropertyType.Float]   = GetShaderData(ShaderPropertyType.Float, \"Floats\", ref shaderInfo, shaderInfo.m_Floats.Length);\n            m_ShaderProperties[(int)ShaderPropertyType.Int]     = GetShaderData(ShaderPropertyType.Int, \"Ints\", ref shaderInfo, shaderInfo.m_Ints.Length);\n            m_ShaderProperties[(int)ShaderPropertyType.Vector]  = GetShaderData(ShaderPropertyType.Vector, \"Vectors\", ref shaderInfo, shaderInfo.m_Vectors.Length);\n            m_ShaderProperties[(int)ShaderPropertyType.Matrix]  = GetShaderData(ShaderPropertyType.Matrix, \"Matrices\", ref shaderInfo, shaderInfo.m_Matrices.Length);\n            m_ShaderProperties[(int)ShaderPropertyType.Texture] = GetShaderData(ShaderPropertyType.Texture, \"Textures\", ref shaderInfo, shaderInfo.m_Textures.Length);\n            m_ShaderProperties[(int)ShaderPropertyType.Buffer]  = GetShaderData(ShaderPropertyType.Buffer, \"Buffers\", ref shaderInfo, shaderInfo.m_Buffers.Length);\n            m_ShaderProperties[(int)ShaderPropertyType.CBuffer] = GetShaderData(ShaderPropertyType.CBuffer, \"Constant Buffers\", ref shaderInfo, shaderInfo.m_CBuffers.Length);\n        }\n\n        private ShaderPropertyCollection GetShaderData(ShaderPropertyType propType, string typeName, ref ShaderInfo shaderInfo, int arrayLength)\n        {\n            ShaderPropertyCollection displayInfo = new ShaderPropertyCollection();\n            displayInfo.m_TypeName = typeName;\n            GetFormatAndHeader(propType, ref shaderInfo, ref displayInfo);\n\n            // Clear and Resolve events often have properties from the previous events\n            // tied to them. We therefore force it to skip them.\n            // TODO: Fix this properly in C++ land.\n            if (m_IsClearEvent || m_IsResolveEvent)\n                arrayLength = 0;\n\n            // Check the data and create structs for valid ones...\n            List<ShaderPropertySortingInfo> myList = new List<ShaderPropertySortingInfo>();\n            for (int index = 0; index < arrayLength; index++)\n                if (CreateShaderPropertyDisplayInfo(propType, index, ref shaderInfo, out ShaderPropertySortingInfo propDisplayInfo))\n                    myList.Add(propDisplayInfo);\n\n            // Sort it...\n            myList.Sort();\n\n            // Fill the ordered structs with data...\n            ShaderPropertyDisplayInfo[] myArr = new ShaderPropertyDisplayInfo[myList.Count];\n            for (int index = 0; index < myList.Count; index++)\n                GetShaderPropertyData(propType, myList[index].m_ArrayIndex, myList[index].m_Name, ref displayInfo, ref shaderInfo, ref myArr[index]);\n\n            // Assign the array and return\n            displayInfo.m_Data = myArr;\n            return displayInfo;\n        }\n\n        private void GetFormatAndHeader(ShaderPropertyType dataType, ref ShaderInfo shaderInfo, ref ShaderPropertyCollection displayData)\n        {\n            // To keep the lines dynamic that scales with the various properties, we\n            // count the characters for various fields so we can adjust the text formatting\n            CountCharacters(dataType, shaderInfo);\n\n            // Every property starts with the name + scope\n            displayData.m_Format = \"{0, \" + -m_MaxNameLength + \"}{1, \" + -m_MaxStageLength + \"}\";\n            displayData.m_HeaderFormat = string.Empty;\n\n            switch (dataType)\n            {\n                case ShaderPropertyType.Keyword:\n                    displayData.m_Format += \"{2, -12}{3, -9}\";\n                    displayData.m_Header = String.Format(displayData.m_Format, \"Name\", \"Stage\", \"Scope\", \"Dynamic\");\n                    break;\n                case ShaderPropertyType.Float:\n                    displayData.m_Format += \"{2, \" + s_FloatPrecision + \"}\";\n                    displayData.m_Header = String.Format(displayData.m_Format, \"Name\", \"Stage\", \"Value\");\n                    break;\n                case ShaderPropertyType.Int:\n                    displayData.m_Format += \"{2, \" + s_IntPrecision + \"}\";\n                    displayData.m_Header = String.Format(displayData.m_Format, \"Name\", \"Stage\", \"Value\");\n                    break;\n                case ShaderPropertyType.Vector:\n                    displayData.m_Format += \"{2, \" + s_FloatPrecision + \"}{3, \" + s_FloatPrecision + \"}{4, \" + s_FloatPrecision + \"}{5, \" + s_FloatPrecision + \"}\";\n                    displayData.m_Header = String.Format(displayData.m_Format, \"Name\", \"Stage\", \"Value(R)\", \"Value(G)\", \"Value(B)\", \"Value(A)\");\n                    break;\n                case ShaderPropertyType.Matrix:\n                    displayData.m_HeaderFormat = \"{0, \" + -m_MaxNameLength + \"}{1, \" + -m_MaxStageLength + \"}{2, \" + s_FloatPrecision + \"}{3, \" + s_FloatPrecision + \"}{4, \" + s_FloatPrecision + \"}{5, \" + s_FloatPrecision + \"}\";\n                    displayData.m_Format = \"{0, \" + -m_MaxNameLength + \"}{1, \" + -m_MaxStageLength + \"}{2, \" + s_FloatPrecision + \"}{3, \" + s_FloatPrecision + \"}{4, \" + s_FloatPrecision + \"}{5, \" + s_FloatPrecision + \"}\\n\"\n                                       + \"{6, \" + -m_MaxNameLength + \"}{7, \" + -m_MaxStageLength + \"}{8, \" + s_FloatPrecision + \"}{9, \" + s_FloatPrecision + \"}{10, \" + s_FloatPrecision + \"}{11, \" + s_FloatPrecision + \"}\\n\"\n                                       + \"{12, \" + -m_MaxNameLength + \"}{13, \" + -m_MaxStageLength + \"}{14, \" + s_FloatPrecision + \"}{15, \" + s_FloatPrecision + \"}{16, \" + s_FloatPrecision + \"}{17, \" + s_FloatPrecision + \"}\\n\"\n                                       + \"{18, \" + -m_MaxNameLength + \"}{19, \" + -m_MaxStageLength + \"}{20, \" + s_FloatPrecision + \"}{21, \" + s_FloatPrecision + \"}{22, \" + s_FloatPrecision + \"}{23, \" + s_FloatPrecision + \"}\";\n                    displayData.m_Header = String.Format(displayData.m_HeaderFormat, \"Name\", \"Stage\", \"Column 0\", \"Column 1\", \"Column 2\", \"Column 3\");\n                    break;\n                case ShaderPropertyType.Texture:\n                    displayData.m_Format += \"{2, \" + -m_MaxTexSizeLength + \"}{3, \" + -m_MaxSampleTypeLength + \"}{4, \" + -m_MaxColorFormatLength + \"}{5, \" + -m_MaxDepthFormatLength + \"}{6}\";\n                    displayData.m_HeaderFormat = displayData.m_Format;\n                    displayData.m_Header = String.Format(displayData.m_HeaderFormat, \"Name\", \"Stage\", \"Size\", \"Sampler Type\", \"Color Format\", \"DepthStencil Format\", \"Texture\");\n                    break;\n                case ShaderPropertyType.Buffer:\n                    displayData.m_Format = \"{0, \" + -m_MaxNameLength + \"}\";\n                    displayData.m_Header = String.Format(displayData.m_Format, \"Name\");\n                    break;\n                case ShaderPropertyType.CBuffer:\n                    displayData.m_Format = \"{0, \" + -m_MaxNameLength + \"}\";\n                    displayData.m_Header = String.Format(displayData.m_Format, \"Name\");\n                    break;\n                default:\n                    return;\n            }\n        }\n\n        private bool CreateShaderPropertyDisplayInfo(ShaderPropertyType dataType, int arrayIndex, ref ShaderInfo shaderInfo, out ShaderPropertySortingInfo data)\n        {\n            int flags;\n            string name;\n            data = new ShaderPropertySortingInfo();\n            switch (dataType)\n            {\n                case ShaderPropertyType.Keyword: flags = shaderInfo.m_Keywords[arrayIndex].m_Flags; name = shaderInfo.m_Keywords[arrayIndex].m_Name; break;\n                case ShaderPropertyType.Float:   flags = shaderInfo.m_Floats[arrayIndex].m_Flags;   name = shaderInfo.m_Floats[arrayIndex].m_Name; break;\n                case ShaderPropertyType.Int:     flags = shaderInfo.m_Ints[arrayIndex].m_Flags;     name = shaderInfo.m_Ints[arrayIndex].m_Name; break;\n                case ShaderPropertyType.Vector:  flags = shaderInfo.m_Vectors[arrayIndex].m_Flags;  name = shaderInfo.m_Vectors[arrayIndex].m_Name; break;\n                case ShaderPropertyType.Matrix:  flags = shaderInfo.m_Matrices[arrayIndex].m_Flags; name = shaderInfo.m_Matrices[arrayIndex].m_Name; break;\n                case ShaderPropertyType.Texture: flags = shaderInfo.m_Textures[arrayIndex].m_Flags; name = shaderInfo.m_Textures[arrayIndex].m_Name; break;\n                case ShaderPropertyType.Buffer:  flags = 1;                                         name = shaderInfo.m_Buffers[arrayIndex].m_Name; break;\n                case ShaderPropertyType.CBuffer: flags = 1;                                         name = shaderInfo.m_CBuffers[arrayIndex].m_Name; break;\n                default: return false;\n            }\n\n            // We get a lot of rubbish data sent in. Needs investigation to why...\n            if (dataType != ShaderPropertyType.Keyword && dataType != ShaderPropertyType.Texture && dataType != ShaderPropertyType.Buffer && dataType != ShaderPropertyType.CBuffer)\n                if (FrameDebuggerHelper.GetNumberOfValuesFromFlags(flags) <= 0)\n                    return false;\n\n            data.m_Name = name;\n            data.m_ArrayIndex = arrayIndex;\n            return true;\n        }\n\n        private string GetArrayIndexString(int nameLength, int numOfValues, int currentIndex)\n        {\n            int numOfSpaces = nameLength + (FrameDebuggerHelper.CountDigits(numOfValues) - FrameDebuggerHelper.CountDigits(currentIndex));\n            return $\"{new string(' ', numOfSpaces)}[{currentIndex}]\";\n        }\n\n        private bool GetShaderPropertyData(ShaderPropertyType dataType, int arrayIndex, string name, ref ShaderPropertyCollection propertyTypeDisplayData, ref ShaderInfo shaderInfo, ref ShaderPropertyDisplayInfo data)\n        {\n            m_StringBuilder.Clear();\n            data = new ShaderPropertyDisplayInfo();\n\n            // Create and return the data...\n            string stage;\n            int numOfValues;\n            switch (dataType)\n            {\n                case ShaderPropertyType.Keyword:\n                    Profiler.BeginSample(\"Keyword\");\n                    ShaderKeywordInfo keywordInfo = shaderInfo.m_Keywords[arrayIndex];\n                    data.m_PropertyString = m_StringBuilder.AppendFormat(propertyTypeDisplayData.m_Format,\n                        name,\n                        FrameDebuggerHelper.GetShaderStageString(keywordInfo.m_Flags),\n                        keywordInfo.m_IsGlobal ? \"Global\" : \"Local\",\n                        keywordInfo.m_IsDynamic ? \"Yes\" : \"No\").ToString();\n                    Profiler.EndSample();\n                    break;\n\n                case ShaderPropertyType.Texture:\n                    Profiler.BeginSample(\"Texture\");\n                    ShaderTextureInfo textureInfo = shaderInfo.m_Textures[arrayIndex];\n                    stage = FrameDebuggerHelper.GetShaderStageString(textureInfo.m_Flags);\n\n                    Texture texture = textureInfo.m_Value;\n                    string samplerType;\n                    string size;\n                    string colorFormat;\n                    string depthStencilFormat;\n                    string textureName = textureInfo.m_TextureName;\n                    if (texture != null)\n                    {\n                        if (texture.dimension == TextureDimension.Tex2DArray)\n                            samplerType = \"Tex2D-Array\";\n                        else if (texture.dimension == TextureDimension.CubeArray)\n                            samplerType = \"Cube-Array\";\n                        else\n                            samplerType =  $\"{texture.dimension}\";\n\n                        size = FrameDebuggerHelper.GetSize(ref texture);\n                        colorFormat = FrameDebuggerHelper.GetColorFormat(ref texture);\n                        depthStencilFormat = FrameDebuggerHelper.GetDepthStencilFormat(ref texture);\n\n                        // We need to do a blit for when MSAA is enabled or when trying to show depth.\n                        // The ObjectPreview doesn't currently support RenderTextures with only depth...\n                        int volumeDepth = FrameDebuggerHelper.GetVolumeDepth(ref texture);\n                        int msaaVal = FrameDebuggerHelper.GetMSAAValue(ref texture);\n                        bool isDepthTex = FrameDebuggerHelper.IsADepthTexture(ref texture);\n                        if (msaaVal > 1 || isDepthTex)\n                        {\n                            data.m_TextureCopy = new RenderTexture(texture.width, texture.height, 0, RenderTextureFormat.ARGB32);\n                            FrameDebuggerHelper.BlitToRenderTexture(\n                                ref texture,\n                                ref data.m_TextureCopy,\n                                texture.width,\n                                texture.height,\n                                volumeDepth,\n                                Vector4.one,\n                                new Vector4(0f, 1f, 0f, 0f),\n                                false,\n                                false\n                            );\n                        }\n                        else\n                            data.m_Texture = texture;\n                    }\n                    else\n                    {\n                        samplerType = FrameDebuggerStyles.EventDetails.k_NotAvailable;\n                        size = FrameDebuggerStyles.EventDetails.k_NotAvailable;\n                        colorFormat = FrameDebuggerStyles.EventDetails.k_NotAvailable;\n                        depthStencilFormat = FrameDebuggerStyles.EventDetails.k_NotAvailable;\n                    }\n\n                    data.m_PropertyString = m_StringBuilder.AppendFormat(propertyTypeDisplayData.m_HeaderFormat, name, stage, size, samplerType, colorFormat, depthStencilFormat, textureName).ToString();\n                    Profiler.EndSample();\n                    break;\n\n                case ShaderPropertyType.Int:\n                    Profiler.BeginSample(\"Int\");\n                    ShaderIntInfo intInfo = shaderInfo.m_Ints[arrayIndex];\n                    numOfValues = FrameDebuggerHelper.GetNumberOfValuesFromFlags(intInfo.m_Flags);\n                    stage = FrameDebuggerHelper.GetShaderStageString(intInfo.m_Flags);\n                    data.m_IsArray = numOfValues > 1;\n                    data.m_ArrayGUIStyle = CreateArrayGUIStyle(numOfValues);\n\n                    if (!data.m_IsArray)\n                        data.m_PropertyString = String.Format(propertyTypeDisplayData.m_Format, name, stage, intInfo.m_Value);\n                    else\n                    {\n                        m_StringBuilder.Clear();\n                        data.m_FoldoutString = String.Format(propertyTypeDisplayData.m_Format, $\"{name}[{numOfValues}]\", stage, string.Empty, string.Empty, string.Empty, string.Empty);\n                        for (int k = arrayIndex; k < arrayIndex + numOfValues; k++)\n                        {\n                            int value = shaderInfo.m_Ints[k].m_Value;\n                            m_StringBuilder.AppendFormat(propertyTypeDisplayData.m_Format,\n                                                         GetArrayIndexString(name.Length, numOfValues, k - arrayIndex),\n                                                         string.Empty,\n                                                         value).AppendLine();\n                        }\n\n                        // Remove last linebreak\n                        if (m_StringBuilder.Length > 2)\n                            m_StringBuilder.Length--;\n\n                        data.m_PropertyString = m_StringBuilder.ToString();\n                    }\n                    Profiler.EndSample();\n                    break;\n\n                case ShaderPropertyType.Float:\n                    Profiler.BeginSample(\"Float\");\n                    ShaderFloatInfo floatInfo = shaderInfo.m_Floats[arrayIndex];\n                    numOfValues = FrameDebuggerHelper.GetNumberOfValuesFromFlags(floatInfo.m_Flags);\n                    stage = FrameDebuggerHelper.GetShaderStageString(floatInfo.m_Flags);\n                    data.m_IsArray = numOfValues > 1;\n                    data.m_ArrayGUIStyle = CreateArrayGUIStyle(numOfValues);\n\n                    if (!data.m_IsArray)\n                        data.m_PropertyString = String.Format(propertyTypeDisplayData.m_Format, name, stage, floatInfo.m_Value);\n                    else\n                    {\n                        m_StringBuilder.Clear();\n\n                        data.m_FoldoutString = m_StringBuilder.AppendFormat(propertyTypeDisplayData.m_Format, $\"{name}[{numOfValues}]\", stage, string.Empty, string.Empty, string.Empty, string.Empty).ToString();\n                        m_StringBuilder.Clear();\n                        for (int k = arrayIndex; k < arrayIndex + numOfValues; k++)\n                        {\n                            float value = shaderInfo.m_Floats[k].m_Value;\n                            m_StringBuilder.AppendFormat(propertyTypeDisplayData.m_Format,\n                                                         GetArrayIndexString(name.Length, numOfValues, k - arrayIndex),\n                                                         string.Empty,\n                                                         value).AppendLine();\n                        }\n\n                        // Remove last linebreak\n                        if (numOfValues > 1 && m_StringBuilder.Length > 2)\n                            m_StringBuilder.Length--;\n\n                        data.m_PropertyString = m_StringBuilder.ToString();\n                    }\n                    Profiler.EndSample();\n                    break;\n\n                case ShaderPropertyType.Vector:\n                    Profiler.BeginSample(\"Vector\");\n                    ShaderVectorInfo vectorInfo = shaderInfo.m_Vectors[arrayIndex];\n                    numOfValues = FrameDebuggerHelper.GetNumberOfValuesFromFlags(vectorInfo.m_Flags);\n                    stage = FrameDebuggerHelper.GetShaderStageString(vectorInfo.m_Flags);\n                    data.m_IsArray = numOfValues > 1;\n                    data.m_ArrayGUIStyle = CreateArrayGUIStyle(numOfValues);\n\n                    if (!data.m_IsArray)\n                        data.m_PropertyString = String.Format(propertyTypeDisplayData.m_Format, name, stage, vectorInfo.m_Value.x, vectorInfo.m_Value.y, vectorInfo.m_Value.z, vectorInfo.m_Value.w);\n                    else\n                    {\n                        m_StringBuilder.Clear();\n                        data.m_FoldoutString = String.Format(propertyTypeDisplayData.m_Format, $\"{name}[{numOfValues}]\", stage, string.Empty, string.Empty, string.Empty, string.Empty);\n                        for (int k = arrayIndex; k < arrayIndex + numOfValues; k++)\n                        {\n                            Vector4 value = shaderInfo.m_Vectors[k].m_Value;\n                            m_StringBuilder.AppendFormat(propertyTypeDisplayData.m_Format,\n                                                         GetArrayIndexString(name.Length, numOfValues, k - arrayIndex),\n                                                         string.Empty,\n                                                         value.x,\n                                                         value.y,\n                                                         value.z,\n                                                         value.w).AppendLine();\n                        }\n\n                        // Remove last linebreak\n                        if (numOfValues > 1 && m_StringBuilder.Length > 2)\n                            m_StringBuilder.Length--;\n\n                        data.m_PropertyString = m_StringBuilder.ToString();\n                    }\n\n                    Profiler.EndSample();\n                    break;\n\n                case ShaderPropertyType.Matrix:\n                    Profiler.BeginSample(\"Matrix\");\n                    ShaderMatrixInfo matrixInfo = shaderInfo.m_Matrices[arrayIndex];\n                    numOfValues = FrameDebuggerHelper.GetNumberOfValuesFromFlags(matrixInfo.m_Flags);\n                    stage = FrameDebuggerHelper.GetShaderStageString(matrixInfo.m_Flags);\n                    data.m_IsArray = numOfValues > 1;\n                    data.m_ArrayGUIStyle = CreateArrayGUIStyle(numOfValues * 4);\n\n                    if (!data.m_IsArray)\n                    {\n                        Matrix4x4 value = matrixInfo.m_Value;\n                        data.m_PropertyString = m_StringBuilder.AppendFormat(propertyTypeDisplayData.m_Format,\n                                         name, stage, value.m00, value.m01, value.m02, value.m03,\n                                         string.Empty, string.Empty, value.m10, value.m11, value.m12, value.m13,\n                                         string.Empty, string.Empty, value.m20, value.m21, value.m22, value.m23,\n                                         string.Empty, string.Empty, value.m30, value.m31, value.m32, value.m33).ToString();\n                    }\n                    else\n                    {\n                        m_StringBuilder.Clear();\n                        data.m_FoldoutString = m_StringBuilder.AppendFormat(propertyTypeDisplayData.m_HeaderFormat, $\"{name}[{numOfValues}]\", stage, string.Empty, string.Empty, string.Empty, string.Empty).ToString();\n                        m_StringBuilder.Clear();\n                        for (int k = arrayIndex; k < arrayIndex + numOfValues; k++)\n                        {\n                            Matrix4x4 value = shaderInfo.m_Matrices[k].m_Value;\n                            m_StringBuilder.AppendFormat(propertyTypeDisplayData.m_Format,\n                                                         GetArrayIndexString(name.Length, numOfValues, k - arrayIndex),\n                                                                       string.Empty, value.m00, value.m01, value.m02, value.m03,\n                                                         string.Empty, string.Empty, value.m10, value.m11, value.m12, value.m13,\n                                                         string.Empty, string.Empty, value.m20, value.m21, value.m22, value.m23,\n                                                         string.Empty, string.Empty, value.m30, value.m31, value.m32, value.m33).AppendLine();\n                        }\n\n                        // Remove last linebreak\n                        if (numOfValues > 1 && m_StringBuilder.Length > 2)\n                            m_StringBuilder.Length--;\n\n                        data.m_PropertyString = m_StringBuilder.ToString();\n                    }\n                    Profiler.EndSample();\n                    break;\n\n                case ShaderPropertyType.Buffer:\n                    Profiler.BeginSample(\"Buffer\");\n                    ShaderBufferInfo bufferInfo = shaderInfo.m_Buffers[arrayIndex];\n                    data.m_PropertyString = String.Format(propertyTypeDisplayData.m_Format, name);\n                    Profiler.EndSample();\n                    break;\n\n                case ShaderPropertyType.CBuffer:\n                    Profiler.BeginSample(\"Constant Buffer\");\n                    ShaderConstantBufferInfo constantBufferInfo = shaderInfo.m_CBuffers[arrayIndex];\n                    data.m_PropertyString = String.Format(propertyTypeDisplayData.m_Format, name);\n                    Profiler.EndSample();\n                    break;\n\n                default:\n                    return false;\n            }\n\n            return true;\n        }\n\n        private GUIStyle CreateArrayGUIStyle(int numOfValues)\n        {\n            // GUIStyle.CalcSizeWithConstraints() is super expensive so to avoid that we set a fixed\n            // height and width so that function can early out. The width doesn't matter due as the\n            // Vertical layout above makes sure it doesn't go too far but needs to be set for the early out.\n            GUIStyle style = new GUIStyle(FrameDebuggerStyles.EventDetails.s_MonoLabelNoWrapStyle);\n            style.fixedWidth = 1000f;\n            style.fixedHeight = 16 * numOfValues;\n            return style;\n        }\n\n        internal void OnDisable()\n        {\n            Clear();\n        }\n\n        private void Clear()\n        {\n            FrameDebuggerHelper.DestroyTexture(ref m_RenderTargetRenderTexture);\n            m_StringBuilder.Clear();\n            m_DetailsStringBuilder.Clear();\n            m_MeshStringBuilder.Clear();\n            m_Details = string.Empty;\n            m_MeshNamesString = string.Empty;\n            m_RealShaderName = string.Empty;\n            m_RealShader = null;\n            m_OriginalShaderName = string.Empty;\n            m_OriginalShader = null;\n            m_ShouldDisplayRealAndOriginalShaders = false;\n\n            if (m_ShaderProperties != null)\n            {\n                for (int i = 0; i < m_ShaderProperties.Length; i++)\n                {\n                    if (!m_ShaderProperties[i].Equals(default(ShaderPropertyCollection)))\n                        m_ShaderProperties[i].Clear();\n                }\n                m_ShaderProperties = null;\n            }\n        }\n\n        private void BuildCurEventDataStrings(FrameDebuggerEvent curEvent, FrameDebuggerEventData curEventData)\n        {\n            // Initialize some key settings\n            m_Index = FrameDebuggerUtility.limit - 1;\n            m_Type = curEvent.m_Type;\n            m_RTDisplayIndex = curEventData.m_RTDisplayIndex;\n\n            m_IsClearEvent = FrameDebuggerHelper.IsAClearEvent(m_Type);\n            m_IsResolveEvent = FrameDebuggerHelper.IsAResolveEvent(m_Type);\n            m_IsComputeEvent = FrameDebuggerHelper.IsAComputeEvent(m_Type);\n            m_IsRayTracingEvent = FrameDebuggerHelper.IsARayTracingEvent(m_Type);\n            m_IsConfigureFoveatedEvent = FrameDebuggerHelper.IsAConfigureFoveatedRenderingEvent(m_Type);\n\n            m_RenderTargetIsBackBuffer = curEventData.m_RenderTargetIsBackBuffer;\n            m_RenderTargetFormat = (GraphicsFormat)curEventData.m_RenderTargetFormat;\n            m_RenderTargetIsDepthOnlyRT = GraphicsFormatUtility.IsDepthFormat(m_RenderTargetFormat);\n            m_RenderTargetHasShowableDepth = (curEventData.m_RenderTargetHasDepthTexture != 0);\n            m_RenderTargetHasStencilBits = (curEventData.m_RenderTargetHasStencilBits != 0);\n            m_RenderTargetShowableRTCount = curEventData.m_RenderTargetCount;\n\n            // Event title\n            int eventTypeInt = (int)m_Type;\n            var eventObj = FrameDebuggerUtility.GetFrameEventObject(m_Index);\n            if (eventObj)\n                m_Title = $\"Event #{m_Index + 1} {FrameDebuggerStyles.s_FrameEventTypeNames[eventTypeInt]} {eventObj.name}\";\n            else\n                m_Title = $\"Event #{m_Index + 1} {FrameDebuggerStyles.s_FrameEventTypeNames[eventTypeInt]}\";\n\n            // Collect data into a string builder based on the event type...\n            if (m_IsComputeEvent)\n                BuildComputeEventDataStrings(curEvent, curEventData);\n            else if (m_IsRayTracingEvent)\n                BuildRayTracingEventDataStrings(curEvent, curEventData);\n            else if (m_IsClearEvent)\n                BuildClearEventDataStrings(curEvent, curEventData);\n            else\n                BuildDrawCallEventDataStrings(curEvent, curEventData);\n\n            // Create a string out of the string builder\n            m_Details = m_DetailsStringBuilder.ToString();\n\n            // Calculate the width and height so the scrollbar functions correctly for the details\n            GUIContent content = new GUIContent(m_Details);\n            Vector2 guiContentSize = FrameDebuggerStyles.EventDetails.s_MonoLabelStyle.CalcSize(content);\n            m_DetailsGUIWidth = guiContentSize.x + 12; // Add small margin to the width\n            m_DetailsGUIHeight = guiContentSize.y;\n        }\n\n        private void BuildRayTracingEventDataStrings(FrameDebuggerEvent curEvent, FrameDebuggerEventData curEventData)\n        {\n            bool hasAccelerationName = curEventData.m_RayTracingShaderAccelerationStructureName.Length > 0;\n            string rayTracingMaxRecursionDepth     = $\"{curEventData.m_RayTracingShaderMaxRecursionDepth}\";\n            string rayTracingDispatchSize          = $\"{curEventData.m_RayTracingShaderWidth} x {curEventData.m_RayTracingShaderHeight} x {curEventData.m_RayTracingShaderDepth}\";\n            string rayTracingAccelerationStructure = hasAccelerationName ? $\"{curEventData.m_RayTracingShaderAccelerationStructureName} ({curEventData.m_RayTracingShaderAccelerationStructureSize} KB)\" : k_NotAvailableString;\n            string rayTracingMissShaderCount       = $\"{curEventData.m_RayTracingShaderMissShaderCount}\";\n            string rayTracingCallableShaderCount   = $\"{curEventData.m_RayTracingShaderCallableShaderCount}\";\n            string rayTracingPassName              = $\"{curEventData.m_RayTracingShaderPassName}\";\n            m_RayTracingShaderName                 = $\"{curEventData.m_RayTracingShaderName}\";\n            m_RayTracingGenerationShaderName       = $\"{curEventData.m_RayTracingShaderRayGenShaderName}\";\n\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Max. Recursion Depth\", rayTracingMaxRecursionDepth).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Dispatch Size\", rayTracingDispatchSize).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Indirect Call\", curEventData.m_RayTracingIndirectDispatch ? \"Yes\" : \"No\").AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Accel. Structure\", rayTracingAccelerationStructure).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Miss Shader Count\", rayTracingMissShaderCount).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Callable Shader Count\", rayTracingCallableShaderCount).AppendLine();\n            m_DetailsStringBuilder.AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Pass\", rayTracingPassName).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Ray Tracing Shader\", m_RayTracingShaderName).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Ray Generation Shader\", m_RayTracingGenerationShaderName).AppendLine();\n        }\n\n        private void BuildComputeEventDataStrings(FrameDebuggerEvent curEvent, FrameDebuggerEventData curEventData)\n        {\n            bool hasGroups = curEventData.m_ComputeShaderThreadGroupsX != 0 || curEventData.m_ComputeShaderThreadGroupsY != 0 || curEventData.m_ComputeShaderThreadGroupsZ != 0;\n            string computeThreadGroups    = hasGroups ? $\"{curEventData.m_ComputeShaderThreadGroupsX}x{curEventData.m_ComputeShaderThreadGroupsY}x{curEventData.m_ComputeShaderThreadGroupsZ}\" : \"Indirect dispatch\";\n            string computeThreadGroupSize = curEventData.m_ComputeShaderGroupSizeX > 0 ? $\"{curEventData.m_ComputeShaderGroupSizeX}x{curEventData.m_ComputeShaderGroupSizeY}x{curEventData.m_ComputeShaderGroupSizeZ}\" : k_NotAvailableString;\n            string computeShaderKernel    = curEventData.m_ComputeShaderKernelName;\n            string computeShaderName      = curEventData.m_ComputeShaderName;\n\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Thread Groups\", computeThreadGroups).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Thread Group Size\", computeThreadGroupSize).AppendLine();\n            m_DetailsStringBuilder.AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Kernel\", computeShaderKernel).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Compute Shader\", computeShaderName).AppendLine();\n        }\n\n        private void BuildClearEventDataStrings(FrameDebuggerEvent curEvent, FrameDebuggerEventData curEventData)\n        {\n            string target = curEventData.m_RenderTargetName;\n\n            int typeInt         = (int)curEvent.m_Type;\n            string clearColor   = (typeInt & 1) != 0 ? $\"({curEventData.m_RenderTargetClearColorR:F2}, {curEventData.m_RenderTargetClearColorG:F2}, {curEventData.m_RenderTargetClearColorB:F2}, {curEventData.m_RenderTargetClearColorA:F2})\" : k_NotAvailableString;\n            string clearDepth   = (typeInt & 2) != 0 ? curEventData.m_ClearDepth.ToString(\"f3\") : k_NotAvailableString;\n            string clearStencil = (typeInt & 4) != 0 ? FrameDebuggerHelper.GetStencilString((int)curEventData.m_ClearStencil) : k_NotAvailableString;\n\n            string size         = $\"{curEventData.m_RenderTargetWidth}x{curEventData.m_RenderTargetHeight}\";\n            string format       = $\"{m_RenderTargetFormat}\";\n\n            bool hasColorActions = curEventData.m_RenderTargetLoadAction != -1;\n            bool hasDepthActions = curEventData.m_RenderTargetDepthLoadAction != -1;\n            string colorActions = hasColorActions ? $\"{(RenderBufferLoadAction)curEventData.m_RenderTargetLoadAction} / {(RenderBufferStoreAction)curEventData.m_RenderTargetStoreAction}\" : k_NotAvailableString;\n            string depthActions = hasDepthActions ? $\"{(RenderBufferLoadAction)curEventData.m_RenderTargetDepthLoadAction} / {(RenderBufferStoreAction)curEventData.m_RenderTargetDepthStoreAction}\" : k_NotAvailableString;\n\n            m_DetailsStringBuilder.Append(FrameDebuggerStyles.EventDetails.s_RenderTargetText).AppendLine();\n            m_DetailsStringBuilder.Append(target).AppendLine();\n            m_DetailsStringBuilder.AppendLine();\n\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Size\", size).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Format\", format).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Color Actions\", colorActions).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Depth Actions\", depthActions).AppendLine();\n            m_DetailsStringBuilder.AppendLine();\n\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Clear Color\",  clearColor).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Clear Depth\",  clearDepth).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Clear Stencil\", clearStencil).AppendLine();\n        }\n\n        private void BuildDrawCallEventDataStrings(FrameDebuggerEvent curEvent, FrameDebuggerEventData curEventData)\n        {\n            m_ShouldDisplayRealAndOriginalShaders = true;\n\n            //\n            FrameDebuggerRasterState rasterState = curEventData.m_RasterState;\n            FrameDebuggerDepthState depthState = curEventData.m_DepthState;\n            FrameDebuggerBlendState blendState = curEventData.m_BlendState;\n\n            // Shader names\n            m_RealShaderName = curEventData.m_RealShaderName;\n            m_RealShader = Shader.Find(m_RealShaderName);\n            m_OriginalShaderName = curEventData.m_OriginalShaderName;\n            m_OriginalShader = Shader.Find(m_OriginalShaderName);\n\n            //\n            bool isResolveOrConfigureFov = m_IsResolveEvent || m_IsConfigureFoveatedEvent;\n            bool hasColorActions = curEventData.m_RenderTargetLoadAction != -1;\n            bool hasDepthActions = curEventData.m_RenderTargetDepthLoadAction != -1;\n            bool isStencilEnabled = curEventData.m_StencilState.m_StencilEnable;\n\n            // Gather the necessary strings...\n            string target = curEventData.m_RenderTargetName;\n            string batchbreakCause = FrameDebuggerStyles.EventDetails.s_BatchBreakCauses[curEventData.m_BatchBreakCause];\n            FrameDebuggerHelper.SpliceText(ref batchbreakCause, 85);\n\n            string size         = $\"{curEventData.m_RenderTargetWidth}x{curEventData.m_RenderTargetHeight}\";\n            string format       = $\"{m_RenderTargetFormat}\";\n            string colorActions = hasColorActions ? $\"{(RenderBufferLoadAction)curEventData.m_RenderTargetLoadAction} / {(RenderBufferStoreAction)curEventData.m_RenderTargetStoreAction}\" : k_NotAvailableString;\n            string depthActions = hasDepthActions ? $\"{(RenderBufferLoadAction)curEventData.m_RenderTargetDepthLoadAction} / {(RenderBufferStoreAction)curEventData.m_RenderTargetDepthStoreAction}\" : k_NotAvailableString;\n\n            string zClip        = !isResolveOrConfigureFov ? rasterState.m_DepthClip.ToString() : k_NotAvailableString;\n            string zTest        = !isResolveOrConfigureFov ? depthState.m_DepthFunc.ToString() : k_NotAvailableString;\n            string zWrite       = !isResolveOrConfigureFov ? (depthState.m_DepthWrite == 0 ? \"Off\" : \"On\") : k_NotAvailableString;\n            string cull         = !isResolveOrConfigureFov ? rasterState.m_CullMode.ToString() : k_NotAvailableString;\n            string conservative = !isResolveOrConfigureFov ? rasterState.m_Conservative.ToString() : k_NotAvailableString;\n            string offset       = !isResolveOrConfigureFov ? $\"{rasterState.m_SlopeScaledDepthBias}, {rasterState.m_DepthBias}\" : k_NotAvailableString;\n            string memoryless   = !isResolveOrConfigureFov ? (curEventData.m_RenderTargetMemoryless != 0 ? \"Yes\" : \"No\") : k_NotAvailableString;\n            string foveatedRendering = FrameDebuggerHelper.GetFoveatedRenderingModeString(curEventData.m_RenderTargetFoveatedRenderingMode);\n\n            bool hasGroups = curEventData.m_ComputeShaderThreadGroupsX != 0 || curEventData.m_ComputeShaderThreadGroupsY != 0 || curEventData.m_ComputeShaderThreadGroupsZ != 0;\n            string computeShaderKernel    = m_IsComputeEvent ? curEventData.m_ComputeShaderKernelName : k_NotAvailableString;\n            string computeThreadGroups    = m_IsComputeEvent && hasGroups ? $\"{curEventData.m_ComputeShaderThreadGroupsX}x{curEventData.m_ComputeShaderThreadGroupsY}x{curEventData.m_ComputeShaderThreadGroupsZ}\" : m_IsComputeEvent ? \"Indirect dispatch\" : k_NotAvailableString;\n            string computeThreadGroupSize = m_IsComputeEvent && curEventData.m_ComputeShaderGroupSizeX > 0 ? $\"{curEventData.m_ComputeShaderGroupSizeX}x{curEventData.m_ComputeShaderGroupSizeY}x{curEventData.m_ComputeShaderGroupSizeZ}\" : k_NotAvailableString;\n\n            string passName = $\"{(string.IsNullOrEmpty(curEventData.m_PassName) ? k_NotAvailableString : curEventData.m_PassName)} ({curEventData.m_ShaderPassIndex})\";\n            string lightModeName = string.IsNullOrEmpty(curEventData.m_PassLightMode) ? k_NotAvailableString : curEventData.m_PassLightMode;\n\n            // Format them all together...\n            m_DetailsStringBuilder.Append(FrameDebuggerStyles.EventDetails.s_RenderTargetText).AppendLine();\n            m_DetailsStringBuilder.Append(target).AppendLine();\n            m_DetailsStringBuilder.AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Size\", size, \"ZClip\", zClip).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Format\", format, \"ZTest\", zTest).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Color Actions\", colorActions, \"ZWrite\", zWrite).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Depth Actions\", depthActions, \"Cull\", cull).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Memoryless\", memoryless, \"Conservative\", conservative).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Foveated Rendering\", foveatedRendering, \"Offset\", offset).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, string.Empty, string.Empty, string.Empty, string.Empty).AppendLine();\n\n            if (isResolveOrConfigureFov)\n            {\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"ColorMask\", k_NotAvailableString, \"Stencil\", string.Empty).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Blend Color\", k_NotAvailableString, \"Stencil Ref\", k_NotAvailableString).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Blend Alpha\", k_NotAvailableString, \"Stencil ReadMask\", k_NotAvailableString).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"BlendOp Color\", k_NotAvailableString, \"Stencil WriteMask\", k_NotAvailableString).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"BlendOp Alpha\", k_NotAvailableString, \"Stencil Comp\", k_NotAvailableString).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, string.Empty, string.Empty, \"Stencil Pass\", k_NotAvailableString).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"DrawInstanced Calls\", k_NotAvailableString, \"Stencil Fail\", k_NotAvailableString).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Instances\", k_NotAvailableString, \"Stencil ZFail\", k_NotAvailableString).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Draw Calls\", \"1\", string.Empty, string.Empty).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Vertices\", k_NotAvailableString, string.Empty, string.Empty).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Indices\", k_NotAvailableString, string.Empty, string.Empty).AppendLine();\n            }\n            else\n            {\n                string colorMask = FrameDebuggerHelper.GetColorMask(blendState.m_WriteMask);\n                string blendColor = $\"{blendState.m_SrcBlend} / {blendState.m_DstBlend}\";\n                string blendAlpha = $\"{blendState.m_SrcBlendAlpha} / {blendState.m_DstBlendAlpha}\";\n                string blendOpColor = blendState.m_BlendOp.ToString();\n                string blendOpAlpha = blendState.m_BlendOpAlpha.ToString();\n\n                string stencilRef = isStencilEnabled ? FrameDebuggerHelper.GetStencilString(curEventData.m_StencilRef) : k_NotAvailableString;\n                string stencilReadMask = isStencilEnabled && curEventData.m_StencilState.m_ReadMask != 255 ? FrameDebuggerHelper.GetStencilString(curEventData.m_StencilState.m_ReadMask) : k_NotAvailableString;\n                string stencilWriteMask = isStencilEnabled && curEventData.m_StencilState.m_WriteMask != 255 ? FrameDebuggerHelper.GetStencilString(curEventData.m_StencilState.m_WriteMask) : k_NotAvailableString;\n                string stencilComp = k_NotAvailableString;\n                string stencilPass = k_NotAvailableString;\n                string stencilFail = k_NotAvailableString;\n                string stencilZFail = k_NotAvailableString;\n\n                if (isStencilEnabled)\n                {\n                    CullMode cullMode = curEventData.m_RasterState.m_CullMode;\n\n                    // Only show *Front states when CullMode is set to Back.\n                    if (cullMode == CullMode.Back)\n                    {\n                        stencilComp  = $\"{curEventData.m_StencilState.m_StencilFuncFront}\";\n                        stencilPass  = $\"{curEventData.m_StencilState.m_StencilPassOpFront}\";\n                        stencilFail  = $\"{curEventData.m_StencilState.m_StencilFailOpFront}\";\n                        stencilZFail = $\"{curEventData.m_StencilState.m_StencilZFailOpFront}\";\n                    }\n                    // Only show *Back states when CullMode is set to Front.\n                    else if (cullMode == CullMode.Front)\n                    {\n                        stencilComp  = $\"{curEventData.m_StencilState.m_StencilFuncBack}\";\n                        stencilPass  = $\"{curEventData.m_StencilState.m_StencilPassOpBack}\";\n                        stencilFail  = $\"{curEventData.m_StencilState.m_StencilFailOpBack}\";\n                        stencilZFail = $\"{curEventData.m_StencilState.m_StencilZFailOpBack}\";\n                    }\n                    // Show both *Front and *Back states for two-sided geometry.\n                    else\n                    {\n                        stencilComp  = $\"{curEventData.m_StencilState.m_StencilFuncFront} / {curEventData.m_StencilState.m_StencilFuncBack}\";\n                        stencilPass  = $\"{curEventData.m_StencilState.m_StencilPassOpFront} / {curEventData.m_StencilState.m_StencilPassOpBack}\";\n                        stencilFail  = $\"{curEventData.m_StencilState.m_StencilFailOpFront} / {curEventData.m_StencilState.m_StencilFailOpBack}\";\n                        stencilZFail = $\"{curEventData.m_StencilState.m_StencilZFailOpFront} / {curEventData.m_StencilState.m_StencilZFailOpBack}\";\n                    }\n                }\n\n                string drawInstancedCalls = curEventData.m_InstanceCount > 1 ? $\"{curEventData.m_DrawCallCount}\" : k_NotAvailableString;\n                string drawInstances      = curEventData.m_InstanceCount > 1 ? $\"{curEventData.m_InstanceCount}\" : k_NotAvailableString;\n                string drawCalls          = curEventData.m_InstanceCount > 1 ? k_NotAvailableString                : $\"{curEventData.m_DrawCallCount}\";\n\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"ColorMask\", colorMask, \"Stencil\", string.Empty).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Blend Color\", blendColor, \"Stencil Ref\", stencilRef).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Blend Alpha\", blendAlpha, \"Stencil ReadMask\", stencilReadMask).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"BlendOp Color\", blendOpColor, \"Stencil WriteMask\", stencilWriteMask).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"BlendOp Alpha\", blendOpAlpha, \"Stencil Comp\", stencilComp).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, string.Empty, string.Empty, \"Stencil Pass\", stencilPass).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"DrawInstanced Calls\", drawInstancedCalls, \"Stencil Fail\", stencilFail).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Instances\", drawInstances, \"Stencil ZFail\", stencilZFail).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Draw Calls\", drawCalls, string.Empty, string.Empty).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Vertices\", curEventData.m_VertexCount.ToString(), string.Empty, string.Empty).AppendLine();\n                m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, \"Indices\", curEventData.m_IndexCount.ToString(), string.Empty, string.Empty).AppendLine();\n            }\n\n            m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, string.Empty, string.Empty, string.Empty, string.Empty).AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_FourColumnFormat, FrameDebuggerStyles.EventDetails.s_BatchCauseText, string.Empty, string.Empty, string.Empty).AppendLine();\n            m_DetailsStringBuilder.Append(batchbreakCause).AppendLine();\n            m_DetailsStringBuilder.AppendLine();\n\n            if (curEventData.m_MeshInstanceIDs != null && curEventData.m_MeshInstanceIDs.Length > 0)\n            {\n                HashSet<int> meshIDs = new HashSet<int>();\n                for (int i = 0; i < curEventData.m_MeshInstanceIDs.Length; i++)\n                {\n                    int id = curEventData.m_MeshInstanceIDs[i];\n                    Mesh mesh = EditorUtility.InstanceIDToObject(id) as Mesh;\n                    if (mesh != null)\n                        meshIDs.Add(id);\n                }\n\n                List<Mesh> meshes = new List<Mesh>();\n                foreach (int id in meshIDs)\n                {\n                    Mesh mesh = EditorUtility.InstanceIDToObject(id) as Mesh;\n                    meshes.Add(mesh);\n                }\n\n                m_Meshes = meshes.ToArray();\n                m_MeshNames = new GUIContent[meshes.Count];\n                for (var i = 0; i < m_Meshes.Length; ++i)\n                {\n                    m_MeshNames[i] = EditorGUIUtility.TrTextContent(m_Meshes[i].name, string.Empty);\n\n                    if (i == 0)\n                        m_MeshStringBuilder.AppendFormat(k_TwoColumnFormat, \"Meshes\", m_MeshNames[i].text);\n                    else\n                        m_MeshStringBuilder.AppendFormat(k_TwoColumnFormat, string.Empty, m_MeshNames[i].text);\n\n                    m_MeshStringBuilder.AppendLine();\n                }\n            }\n            else\n            {\n                if (curEventData.m_Mesh == null || curEventData.m_Mesh.name == string.Empty)\n                {\n                    m_MeshStringBuilder.AppendFormat(k_TwoColumnFormat, \"Mesh\", k_NotAvailableString);\n                    m_Meshes = null;\n                    m_MeshNames = null;\n                }\n                else\n                {\n                    m_Meshes = new Mesh[] { curEventData.m_Mesh };\n                    m_MeshNames = new GUIContent[1];\n                    m_MeshNames[0] = EditorGUIUtility.TrTextContent(curEventData.m_Mesh.name, string.Empty);\n                    m_MeshStringBuilder.AppendFormat(k_TwoColumnFormat, \"Mesh\", m_MeshNames[0].text);\n                }\n                m_MeshStringBuilder.AppendLine();\n            }\n\n            m_DetailsStringBuilder.Append(m_MeshStringBuilder);\n\n            m_DetailsStringBuilder.AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"LightMode\", lightModeName);\n            m_DetailsStringBuilder.AppendLine();\n            m_DetailsStringBuilder.AppendFormat(k_TwoColumnFormat, \"Pass\", passName);\n        }\n\n        private void CountCharacters(ShaderPropertyType dataType, ShaderInfo shaderInfo)\n        {\n            m_MaxNameLength = k_MinNameLength;\n            m_MaxStageLength = k_MinStageLength;\n            m_MaxTexSizeLength = k_MinTexSizeLength;\n            m_MaxSampleTypeLength = k_MinSampleTypeLength;\n            m_MaxColorFormatLength = k_MinColorFormatLength;\n            m_MaxDepthFormatLength = k_MinDepthFormatLength;\n\n            switch (dataType)\n            {\n                case ShaderPropertyType.Keyword:\n                    for (int i = 0; i < shaderInfo.m_Keywords.Length; i++)\n                    {\n                        m_MaxNameLength = Mathf.Max(m_MaxNameLength, shaderInfo.m_Keywords[i].m_Name.Length);\n                        m_MaxStageLength = Mathf.Max(m_MaxStageLength, FrameDebuggerHelper.GetShaderStageString(shaderInfo.m_Keywords[i].m_Flags).Length);\n                    }\n                    break;\n                case ShaderPropertyType.Texture:\n                    for (int i = 0; i < shaderInfo.m_Textures.Length; i++)\n                    {\n                        m_MaxNameLength = Mathf.Max(m_MaxNameLength, shaderInfo.m_Textures[i].m_Name.Length);\n                        m_MaxStageLength = Mathf.Max(m_MaxStageLength, FrameDebuggerHelper.GetShaderStageString(shaderInfo.m_Textures[i].m_Flags).Length);\n\n                        Texture texture = shaderInfo.m_Textures[i].m_Value;\n                        if (texture != null)\n                        {\n                            m_MaxColorFormatLength = Mathf.Max(m_MaxColorFormatLength, FrameDebuggerHelper.GetColorFormat(ref texture).Length);\n                            m_MaxDepthFormatLength = Mathf.Max(m_MaxDepthFormatLength, FrameDebuggerHelper.GetDepthStencilFormat(ref texture).Length);\n                            m_MaxTexSizeLength = Mathf.Max(m_MaxTexSizeLength, FrameDebuggerHelper.GetSize(ref texture).Length);\n                            m_MaxSampleTypeLength = Mathf.Max(m_MaxSampleTypeLength, $\"{texture.dimension}\".Length);\n                        }\n                    }\n                    break;\n                case ShaderPropertyType.Int:\n                    for (int i = 0; i < shaderInfo.m_Ints.Length; i++)\n                    {\n                        int numOfValues = FrameDebuggerHelper.GetNumberOfValuesFromFlags(shaderInfo.m_Ints[i].m_Flags);\n                        int arrayChars = numOfValues > 1 ? FrameDebuggerHelper.CountDigits(numOfValues) + 2 : 0;\n                        m_MaxNameLength = Mathf.Max(m_MaxNameLength, shaderInfo.m_Ints[i].m_Name.Length + arrayChars);\n                        m_MaxStageLength = Mathf.Max(m_MaxStageLength, FrameDebuggerHelper.GetShaderStageString(shaderInfo.m_Ints[i].m_Flags).Length);\n                    }\n                    break;\n                case ShaderPropertyType.Float:\n                    for (int i = 0; i < shaderInfo.m_Floats.Length; i++)\n                    {\n                        int numOfValues = FrameDebuggerHelper.GetNumberOfValuesFromFlags(shaderInfo.m_Floats[i].m_Flags);\n                        int arrayChars = numOfValues > 1 ? FrameDebuggerHelper.CountDigits(numOfValues) + 2 : 0;\n                        m_MaxNameLength = Mathf.Max(m_MaxNameLength, shaderInfo.m_Floats[i].m_Name.Length + arrayChars);\n                        m_MaxStageLength = Mathf.Max(m_MaxStageLength, FrameDebuggerHelper.GetShaderStageString(shaderInfo.m_Floats[i].m_Flags).Length);\n                    }\n                    break;\n                case ShaderPropertyType.Vector:\n                    for (int i = 0; i < shaderInfo.m_Vectors.Length; i++)\n                    {\n                        int numOfValues = FrameDebuggerHelper.GetNumberOfValuesFromFlags(shaderInfo.m_Vectors[i].m_Flags);\n                        int arrayChars = numOfValues > 1 ? FrameDebuggerHelper.CountDigits(numOfValues) + 2 : 0;\n                        m_MaxNameLength = Mathf.Max(m_MaxNameLength, shaderInfo.m_Vectors[i].m_Name.Length + arrayChars);\n                        m_MaxStageLength = Mathf.Max(m_MaxStageLength, FrameDebuggerHelper.GetShaderStageString(shaderInfo.m_Vectors[i].m_Flags).Length);\n                    }\n                    break;\n                case ShaderPropertyType.Matrix:\n                    for (int i = 0; i < shaderInfo.m_Matrices.Length; i++)\n                    {\n                        int numOfValues = FrameDebuggerHelper.GetNumberOfValuesFromFlags(shaderInfo.m_Matrices[i].m_Flags);\n                        int arrayChars = numOfValues > 1 ? FrameDebuggerHelper.CountDigits(numOfValues) + 2 : 0;\n                        m_MaxNameLength = Mathf.Max(m_MaxNameLength, shaderInfo.m_Matrices[i].m_Name.Length + arrayChars);\n                        m_MaxStageLength = Mathf.Max(m_MaxStageLength, FrameDebuggerHelper.GetShaderStageString(shaderInfo.m_Matrices[i].m_Flags).Length);\n                    }\n                    break;\n                case ShaderPropertyType.Buffer:\n                    for (int i = 0; i < shaderInfo.m_Buffers.Length; i++)\n                    {\n                        m_MaxNameLength = Mathf.Max(m_MaxNameLength, shaderInfo.m_Buffers[i].m_Name.Length);\n                        m_MaxStageLength = Mathf.Max(m_MaxStageLength, FrameDebuggerHelper.GetShaderStageString(shaderInfo.m_Buffers[i].m_Flags).Length);\n                    }\n                    break;\n                case ShaderPropertyType.CBuffer:\n                    for (int i = 0; i < shaderInfo.m_CBuffers.Length; i++)\n                    {\n                        m_MaxNameLength = Mathf.Max(m_MaxNameLength, shaderInfo.m_CBuffers[i].m_Name.Length);\n                        m_MaxStageLength = Mathf.Max(m_MaxStageLength, FrameDebuggerHelper.GetShaderStageString(shaderInfo.m_CBuffers[i].m_Flags).Length);\n                    }\n                    break;\n                default:\n                    break;\n            }\n\n            m_MaxNameLength += k_ColumnSpace;\n            m_MaxStageLength += k_ColumnSpace;\n            m_MaxTexSizeLength += k_ColumnSpace;\n            m_MaxSampleTypeLength += k_ColumnSpace;\n            m_MaxColorFormatLength += k_ColumnSpace;\n            m_MaxDepthFormatLength += k_ColumnSpace;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PerformanceTools/FrameDebuggerHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Text;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEngine.Experimental.Rendering;\nusing UnityEditor.Rendering;\nusing UnityEditor;\n\nnamespace UnityEditorInternal.FrameDebuggerInternal\n{\n    internal class FrameDebuggerHelper\n    {\n        // Constants\n        private const int k_ArraySizeBitMask = 0x3FF;\n        private const int k_ShaderTypeBits = (int)ShaderType.Count;\n\n        // Properties\n        internal static bool isOnLinuxOpenGL => Application.platform == RuntimePlatform.LinuxEditor && SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLCore;\n        internal static Material frameDebuggerMaterial\n        {\n            get {\n                if (s_Material == null)\n                    s_Material = new Material(Resources.GetBuiltinResource<Material>(\"PerformanceTools/FrameDebuggerRenderTargetDisplay.mat\"));\n\n                return s_Material;\n            }\n        }\n\n        // Utility functions...\n        internal static bool IsAValidFrame(int curEventIndex, int descsLength) => (curEventIndex >= 0 && curEventIndex < descsLength);\n        internal static bool IsAClearEvent(FrameEventType eventType) => eventType >= FrameEventType.ClearNone && eventType <= FrameEventType.ClearAll;\n        internal static bool IsAResolveEvent(FrameEventType eventType) => eventType == FrameEventType.ResolveRT || eventType == FrameEventType.ResolveDepth;\n        internal static bool IsAComputeEvent(FrameEventType eventType) => eventType == FrameEventType.ComputeDispatch;\n        internal static bool IsARayTracingEvent(FrameEventType eventType) => eventType == FrameEventType.RayTracingDispatch;\n        internal static bool IsAConfigureFoveatedRenderingEvent(FrameEventType eventType) => eventType == FrameEventType.ConfigureFoveatedRendering;\n        internal static bool IsAHiddenEvent(FrameEventType eventType) => eventType == FrameEventType.BeginSubpass;\n        internal static bool IsAHierarchyLevelBreakEvent(FrameEventType eventType) => eventType == FrameEventType.HierarchyLevelBreak;\n        internal static bool IsCurrentEventMouseDown() => Event.current.type == EventType.MouseDown;\n        internal static bool IsClickingRect(Rect rect) => rect.Contains(Event.current.mousePosition) && Event.current.type == EventType.MouseDown;\n        internal static bool IsHoveringRect(Rect rect) => rect.Contains(Event.current.mousePosition);\n        internal static bool IsARenderTexture(ref Texture t) => t != null && (t as RenderTexture) != null;\n        internal static bool IsADepthTexture(ref Texture t) => IsARenderTexture(ref t) && ((t as RenderTexture).graphicsFormat == GraphicsFormat.None);\n\n\n        // Private Static Variables\n        private static Material s_Material = null;\n        private static StringBuilder s_StringBuilder = new StringBuilder();\n\n        // Functions\n        private struct ShaderPropertyIDs\n        {\n            internal const string _MSAA_2 = \"_MSAA_2\";\n            internal const string _MSAA_4 = \"_MSAA_4\";\n            internal const string _MSAA_8 = \"_MSAA_8\";\n            internal const string _TEX2DARRAY = \"_TEX2DARRAY\";\n            internal const string _CUBEMAP = \"_CUBEMAP\";\n            internal static int _Levels = Shader.PropertyToID(\"_Levels\");\n            internal static int _MainTex = Shader.PropertyToID(\"_MainTex\");\n            internal static int _MainTexDepth = Shader.PropertyToID(\"_MainTexDepth\");\n            internal static int _Channels = Shader.PropertyToID(\"_Channels\");\n            internal static int _ShouldYFlip = Shader.PropertyToID(\"_ShouldYFlip\");\n            internal static int _UndoOutputSRGB = Shader.PropertyToID(\"_UndoOutputSRGB\");\n            internal static int _MainTexWidth = Shader.PropertyToID(\"_MainTexWidth\");\n            internal static int _MainTexHeight = Shader.PropertyToID(\"_MainTexHeight\");\n        }\n\n        internal static void BlitToRenderTexture(\n            ref Texture t,\n            ref RenderTexture output,\n            int width,\n            int height,\n            int depth,\n            Vector4 channels,\n            Vector4 levels,\n            bool shouldYFlip,\n            bool undoOutputSRGB)\n        {\n            if (t == null || output == null)\n                return;\n\n            output.name = t.name;\n            int msaaValue = GetMSAAValue(ref t);\n            TextureDimension samplerType = t.dimension;\n            SetMaterialProperties(width, height, depth, samplerType, msaaValue, channels, levels, shouldYFlip, undoOutputSRGB);\n            frameDebuggerMaterial.SetTexture(ShaderPropertyIDs._MainTex, t);\n\n            Blit(ref output);\n        }\n\n        internal static void BlitToRenderTexture(\n            ref RenderTexture rt,\n            ref RenderTexture output,\n            int width,\n            int height,\n            Vector4 channels,\n            Vector4 levels,\n            bool shouldYFlip,\n            bool undoOutputSRGB)\n        {\n            if (rt == null || output == null)\n                return;\n\n            output.name = rt.name;\n\n            int msaaValue = GetMSAAValue(ref rt);\n            TextureDimension samplerType = rt.dimension;\n            SetMaterialProperties(width, height, rt.volumeDepth, samplerType, msaaValue, channels, levels, shouldYFlip, undoOutputSRGB);\n            frameDebuggerMaterial.SetTexture(ShaderPropertyIDs._MainTex, rt);\n\n            Blit(ref output);\n        }\n\n        private static void SetMaterialProperties(\n            int width,\n            int height,\n            int depth,\n            TextureDimension samplerType,\n            int msaaValue,\n            Vector4 channels,\n            Vector4 levels,\n            bool shouldYFlip,\n            bool undoOutputSRGB)\n        {\n            Material mat = frameDebuggerMaterial;\n\n            frameDebuggerMaterial.DisableKeyword(ShaderPropertyIDs._TEX2DARRAY);\n            frameDebuggerMaterial.DisableKeyword(ShaderPropertyIDs._CUBEMAP);\n            if (samplerType == TextureDimension.Tex2DArray)\n                frameDebuggerMaterial.EnableKeyword(ShaderPropertyIDs._TEX2DARRAY);\n            else if (samplerType == TextureDimension.CubeArray)\n                frameDebuggerMaterial.EnableKeyword(ShaderPropertyIDs._CUBEMAP);\n\n            mat.DisableKeyword(ShaderPropertyIDs._MSAA_2);\n            mat.DisableKeyword(ShaderPropertyIDs._MSAA_4);\n            mat.DisableKeyword(ShaderPropertyIDs._MSAA_8);\n\n            if (msaaValue == 2)\n                mat.EnableKeyword(ShaderPropertyIDs._MSAA_2);\n            else if (msaaValue == 4)\n                mat.EnableKeyword(ShaderPropertyIDs._MSAA_4);\n            else if (msaaValue == 8)\n                mat.EnableKeyword(ShaderPropertyIDs._MSAA_8);\n\n            // Create the RenderTexture\n            mat.SetFloat(ShaderPropertyIDs._MainTexWidth, width);\n            mat.SetFloat(ShaderPropertyIDs._MainTexHeight, height);\n            mat.SetFloat(ShaderPropertyIDs._MainTexDepth, depth);\n            mat.SetVector(ShaderPropertyIDs._Channels, channels);\n            mat.SetVector(ShaderPropertyIDs._Levels, levels);\n            mat.SetFloat(ShaderPropertyIDs._ShouldYFlip, shouldYFlip ? 1.0f : 0.0f);\n            mat.SetFloat(ShaderPropertyIDs._UndoOutputSRGB, undoOutputSRGB ? 1.0f : 0.0f);\n        }\n\n        private static void Blit(ref RenderTexture rt)\n        {\n            // Remember currently active render texture\n            RenderTexture currentActiveRT = RenderTexture.active;\n\n            // Blit to the Render Texture\n            Graphics.Blit(null, rt, frameDebuggerMaterial, 0);\n\n            // Restore previously active render texture\n            RenderTexture.active = currentActiveRT;\n        }\n\n        internal static int GetVolumeDepth(ref Texture t)\n        {\n            RenderTexture rt = t as RenderTexture;\n            return GetVolumeDepth(ref rt);\n        }\n\n        internal static int GetVolumeDepth(ref RenderTexture rt)\n        {\n            if (rt != null)\n                return rt.volumeDepth;\n\n            return 1;\n        }\n\n        internal static int GetMSAAValue(ref Texture t)\n        {\n            RenderTexture rt = t as RenderTexture;\n            return GetMSAAValue(ref rt);\n        }\n\n        internal static int GetMSAAValue(ref RenderTexture rt)\n        {\n            if (rt != null && rt.bindTextureMS)\n                return rt.antiAliasing;\n\n            return 1;\n        }\n\n        internal static string GetFoveatedRenderingModeString(int fovMode)\n        {\n            switch ((FoveatedRenderingMode)fovMode)\n            {\n                case FoveatedRenderingMode.Disabled:\n                    return \"Disabled\";\n                default:\n                    return \"Enabled\";\n            }\n        }\n\n        internal static string GetStencilString(int stencil)\n        {\n            const int k_NumOfUsedStencilBits = 8;\n            return $\"(0b{Convert.ToString(stencil, 2).PadLeft(k_NumOfUsedStencilBits, '0')}) {stencil}\";\n        }\n\n        internal static string GetColorMask(uint mask)\n        {\n            string colorMask = String.Empty;\n            if (mask == 0)\n                colorMask = \"0\";\n            else\n            {\n                if ((mask & 8) != 0)\n                    colorMask += 'R';\n\n                if ((mask & 4) != 0)\n                    colorMask += 'G';\n\n                if ((mask & 2) != 0)\n                    colorMask += 'B';\n\n                if ((mask & 1) != 0)\n                    colorMask += 'A';\n            }\n\n            return colorMask;\n        }\n\n        internal static string GetColorFormat(ref Texture t)\n        {\n            switch (t)\n            {\n                case Texture2D texture2D:\n                    return texture2D.format.ToString();\n\n                case Cubemap cubemap:\n                    return cubemap.format.ToString();\n\n                case Texture2DArray texture2DArray:\n                    return texture2DArray.format.ToString();\n\n                case Texture3D texture3D:\n                    return texture3D.format.ToString();\n\n                case CubemapArray cubemapArray:\n                    return cubemapArray.format.ToString();\n\n                case RenderTexture renderTexture:\n                    return renderTexture.graphicsFormat.ToString();\n\n                case null:\n                default:\n                    return string.Empty;\n            }\n        }\n\n        internal static string GetSize(ref Texture t)\n        {\n            if (t == null)\n                return string.Empty;\n\n            string size = $\"{t.width}x{t.height}\";\n\n            switch (t)\n            {\n                case Texture2DArray texture2DArray:\n                    size += $\"x{texture2DArray.depth}\";\n                    break;\n\n                case Texture3D texture3D:\n                    size += $\"x{texture3D.depth}\";\n                    break;\n\n                case CubemapArray cubemapArray:\n                    size += $\"x{cubemapArray.cubemapCount}\";\n                    break;\n\n                case RenderTexture renderTexture when renderTexture.dimension != TextureDimension.Tex2D:\n                    size += $\"x{renderTexture.volumeDepth}\";\n                    break;\n            }\n\n            return size;\n        }\n\n        internal static string GetDepthStencilFormat(ref Texture t)\n        {\n            // Render Textures are the only ones who have this as they are split in to 2 textures...\n            if (IsARenderTexture(ref t))\n                return (t as RenderTexture).depthStencilFormat.ToString();\n\n            return FrameDebuggerStyles.EventDetails.k_NotAvailable;\n        }\n\n        internal static int GetNumberOfValuesFromFlags(int flags)\n        {\n            return (flags >> k_ShaderTypeBits) & k_ArraySizeBitMask;\n        }\n\n        internal static string GetShaderStageString(int flags)\n        {\n            s_StringBuilder.Clear();\n\n            // Lowest bits of flags are set for each shader stage that property is used in; matching ShaderType C++ enum\n            const int k_VertexShaderFlag = (1 << 1);\n            const int k_FragmentShaderFlag = (1 << 2);\n            const int k_GeometryShaderFlag = (1 << 3);\n            const int k_HullShaderFlag = (1 << 4);\n            const int k_DomainShaderFlag = (1 << 5);\n\n            if ((flags & k_VertexShaderFlag) != 0)\n                s_StringBuilder.Append(\"vs/\");\n\n            if ((flags & k_FragmentShaderFlag) != 0)\n                s_StringBuilder.Append(\"fs/\");\n\n            if ((flags & k_GeometryShaderFlag) != 0)\n                s_StringBuilder.Append(\"gs/\");\n\n            if ((flags & k_HullShaderFlag) != 0)\n                s_StringBuilder.Append(\"hs/\");\n\n            if ((flags & k_DomainShaderFlag) != 0)\n                s_StringBuilder.Append(\"ds/\");\n\n            if (s_StringBuilder.Length == 0)\n                return FrameDebuggerStyles.EventDetails.k_NotAvailable;\n\n            s_StringBuilder.Remove(s_StringBuilder.Length - 1, 1);\n            return s_StringBuilder.ToString();\n        }\n\n        internal static void DestroyTexture(ref Texture t)\n        {\n            if (t == null)\n                return;\n\n            RenderTexture rt = t as RenderTexture;\n            if (rt != null)\n                DestroyTexture(ref rt);\n            else\n            {\n                Texture.DestroyImmediate(t);\n                t = null;\n            }\n        }\n\n        internal static void DestroyTexture(ref RenderTexture rt)\n        {\n            if (rt == null)\n                return;\n\n            rt.Release();\n            RenderTexture.DestroyImmediate(rt);\n            rt = null;\n        }\n\n        internal static void ReleaseTemporaryTexture(ref RenderTexture rt)\n        {\n            if (rt == null)\n                return;\n\n            RenderTexture.ReleaseTemporary(rt);\n            rt = null;\n        }\n\n        // May look a bit silly but seems to be a pretty fast way of doing this :)\n        // https://stackoverflow.com/a/51099524\n        internal static int CountDigits(int num)\n        {\n            if (num >= 0)\n            {\n                if (num < 10) return 1;\n                if (num < 100) return 2;\n                if (num < 1000) return 3;\n                if (num < 10000) return 4;\n                if (num < 100000) return 5;\n                if (num < 1000000) return 6;\n                if (num < 10000000) return 7;\n                if (num < 100000000) return 8;\n                if (num < 1000000000) return 9;\n                return 10;\n            }\n            else\n            {\n                if (num > -10) return 2;\n                if (num > -100) return 3;\n                if (num > -1000) return 4;\n                if (num > -10000) return 5;\n                if (num > -100000) return 6;\n                if (num > -1000000) return 7;\n                if (num > -10000000) return 8;\n                if (num > -100000000) return 9;\n                return 10;\n            }\n        }\n\n        internal static void SpliceText(ref string text, int maxWidth)\n        {\n            if (string.IsNullOrEmpty(text) || text.Length <= maxWidth)\n                return;\n\n            StringBuilder sb = new StringBuilder(text.Length * 2);\n            while (text.Length > 0)\n            {\n                if (text.Length <= maxWidth)\n                {\n                    sb.Append(text);\n                    break;\n                }\n\n                string chunk = text.Substring(0, maxWidth);\n                if (char.IsWhiteSpace(text[maxWidth]))\n                {\n                    sb.AppendLine(chunk);\n                    text = text.Substring(chunk.Length + 1);\n                }\n                else\n                {\n                    int splitIndex = chunk.LastIndexOf(' ');\n                    if (splitIndex != -1)\n                        chunk = chunk.Substring(0, splitIndex);\n                    text = text.Substring(chunk.Length + (splitIndex == -1 ? 0 : 1));\n                    sb.AppendLine(chunk);\n                }\n            }\n            text = sb.ToString();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PerformanceTools/FrameDebuggerStyles.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditorInternal.FrameDebuggerInternal\n{\n    internal static class FrameDebuggerStyles\n    {\n        // match enum FrameEventType on C++ side!\n        internal static readonly string[] s_FrameEventTypeNames = new[]\n        {\n            \"Clear (nothing)\",\n            \"Clear (color)\",\n            \"Clear (Depth)\",\n            \"Clear (color+depth)\",\n            \"Clear (stencil)\",\n            \"Clear (color+stencil)\",\n            \"Clear (depth+stencil)\",\n            \"Clear (color+depth+stencil)\",\n            \"SetRenderTarget\",\n            \"Resolve Color\",\n            \"Resolve Depth\",\n            \"Grab RenderTexture\",\n            \"Static Batch\",\n            \"Dynamic Batch\",\n            \"Draw Mesh\",\n            \"Draw Dynamic\",\n            \"Draw GL\",\n            \"GPU Skinning\",\n            \"Draw Procedural\",\n            \"Draw Procedural Indirect\",\n            \"Draw Procedural Indexed\",\n            \"Draw Procedural Indexed Indirect\",\n            \"Compute\",\n            \"Ray Tracing Dispatch\",\n            \"Plugin Event\",\n            \"Draw Mesh (instanced)\",\n            \"Begin Subpass\",\n            \"SRP Batch\",\n            \"\",                 // on purpose empty string for kFrameEventHierarchyLevelBreak\n            \"Hybrid Batch Group\",\n            \"Configure Foveated Rendering\",\n        };\n\n        // General settings for the Frame Debugger Window and layout\n        internal struct Window\n        {\n            internal const int k_StartWindowWidth = 1024;\n            internal const float k_MinTreeWidth = k_StartWindowWidth * 0.33f;\n            internal const float k_ResizerWidth = 5f;\n            internal const float k_MinDetailsWidth = 200f;\n        }\n\n        // Tree\n        internal struct Tree\n        {\n            internal static readonly GUIStyle s_RowText = new GUIStyle(EditorStyles.label);\n            internal static readonly GUIStyle s_RowTextBold = new GUIStyle(EditorStyles.boldLabel);\n            internal static readonly GUIStyle s_RowTextRight = new GUIStyle(EditorStyles.boldLabel)\n            {\n                alignment = TextAnchor.MiddleRight\n            };\n\n            internal const string k_UnknownScopeString = \"<unknown scope>\";\n        }\n\n        // Top Toolbar\n        internal struct TopToolbar\n        {\n            internal static readonly GUIContent s_RecordButtonEnable = EditorGUIUtility.TrTextContent(L10n.Tr(\"Enable\"));\n            internal static readonly GUIContent s_RecordButtonDisable = EditorGUIUtility.TrTextContent(L10n.Tr(\"Disable\"));\n            internal static readonly GUIContent s_PrevFrame = EditorGUIUtility.TrIconContent(\"Profiler.PrevFrame\", \"Go back one frame\");\n            internal static readonly GUIContent s_NextFrame = EditorGUIUtility.TrIconContent(\"Profiler.NextFrame\", \"Go one frame forwards\");\n            internal static readonly GUIContent s_LevelsHeader = EditorGUIUtility.TrTextContent(\"Levels\", \"Render target display black/white intensity levels\");\n        }\n\n        // Event Toolbar in the Event Details window\n        internal struct EventToolbar\n        {\n            private const float k_ToolbarHeight = 22f;\n            private const float k_ChannelButtonWidth = 30f;\n\n            internal static readonly GUIStyle s_HorizontalStyle = new GUIStyle(EditorStyles.toolbar)\n            {\n                fixedHeight = k_ToolbarHeight + 1f\n            };\n            internal static readonly GUIStyle s_ChannelHeaderStyle = new GUIStyle(EditorStyles.toolbarLabel)\n            {\n                fixedHeight = k_ToolbarHeight\n            };\n            internal static readonly GUIStyle s_ChannelStyle = new GUIStyle(EditorStyles.toolbarButton)\n            {\n                fixedWidth = k_ChannelButtonWidth,\n                fixedHeight = k_ToolbarHeight,\n                border = new RectOffset(1,0,0,0)\n            };\n            internal static readonly GUIStyle s_PopupLeftStyle = new GUIStyle(EditorStyles.toolbarDropDown)\n            {\n                fixedHeight = k_ToolbarHeight\n            };\n            internal static readonly GUIStyle s_LevelsHorizontalStyle = new GUIStyle(EditorStyles.toolbarButton)\n            {\n                margin = new RectOffset(0, 4, 0, 0),\n                padding = new RectOffset(0, 4, 0, 0),\n                fixedHeight = k_ToolbarHeight\n            };\n\n            internal static readonly GUIContent s_DepthLabel = EditorGUIUtility.TrTextContent(\"Depth\", \"Show depth buffer\");\n            internal static readonly GUIContent s_StencilLabel = EditorGUIUtility.TrTextContent(\"Stencil\", \"Show stencil buffer\");\n\n            internal static readonly GUIContent[] s_ChannelLabels = new[]\n            {\n                EditorGUIUtility.TrTextContent(\"R\", \"Shows the selected channel from the Render Target\"),\n                EditorGUIUtility.TrTextContent(\"G\", \"Shows the selected channel from the Render Target\"),\n                EditorGUIUtility.TrTextContent(\"B\", \"Shows the selected channel from the Render Target\"),\n                EditorGUIUtility.TrTextContent(\"A\", \"Shows the selected channel from the Render Target\"),\n            };\n\n            internal static readonly GUIContent s_LevelsHeader = EditorGUIUtility.TrTextContent(\"Levels\", \"Render target display black/white intensity levels\");\n            internal static readonly GUIContent[] s_MRTLabels = new[]\n            {\n                EditorGUIUtility.TrTextContent(\"RT 0\", \"Show render target #0\"),\n                EditorGUIUtility.TrTextContent(\"RT 1\", \"Show render target #1\"),\n                EditorGUIUtility.TrTextContent(\"RT 2\", \"Show render target #2\"),\n                EditorGUIUtility.TrTextContent(\"RT 3\", \"Show render target #3\"),\n                EditorGUIUtility.TrTextContent(\"RT 4\", \"Show render target #4\"),\n                EditorGUIUtility.TrTextContent(\"RT 5\", \"Show render target #5\"),\n                EditorGUIUtility.TrTextContent(\"RT 6\", \"Show render target #6\"),\n                EditorGUIUtility.TrTextContent(\"RT 7\", \"Show render target #7\")\n            };\n        }\n\n        // Event Details Window\n        internal struct EventDetails\n        {\n            private const int k_Indent1 = 5;\n            private const int k_Indent2 = 20;\n\n            internal const float k_MaxViewportHeight = 355f;\n\n            internal const float k_VerticalLabelWidth = 150f;\n            internal const float k_VerticalValueWidth = 250f;\n            internal const float k_MeshNameWidth = k_VerticalLabelWidth + k_VerticalValueWidth;\n\n            internal const int k_PropertyNameMaxChars = 30;\n            internal const int k_TextureFormatMaxChars = 19;\n\n            internal const int k_ShaderLabelWidth = 155;\n            internal const int k_ShaderObjectFieldWidth = 450;\n\n            internal const float k_MeshBottomToolbarHeight = 21f;\n            internal const float k_ArrayValuePopupBtnWidth = 2.0f;\n\n            internal const string k_FloatFormat = \"F7\";\n            internal const string k_IntFormat = \"d\";\n            internal const string k_NotAvailable = \"-\";\n\n            internal static string s_DashesString = new string('-', 30);\n            internal static string s_EqualsString = new string('=', 30);\n\n\n            internal static readonly GUIStyle s_ArrayFoldoutStyle = new GUIStyle(EditorStyles.foldout)\n            {\n                margin = new RectOffset(-29, 0, 0, 0),\n            };\n\n            internal static readonly GUIStyle s_TitleHorizontalStyle = new GUIStyle(EditorStyles.label)\n            {\n                margin = new RectOffset(0, 0, 0, 10),\n            };\n\n            internal static readonly GUIStyle s_TitleStyle = new GUIStyle(EditorStyles.largeLabel)\n            {\n                padding = new RectOffset(k_Indent1, 0, k_Indent1, 0),\n                fontStyle = FontStyle.Bold,\n                fontSize = 18,\n                fixedHeight = 50,\n            };\n\n            internal static readonly GUIStyle s_FoldoutCategoryBoxStyle = new GUIStyle(EditorStyles.helpBox);\n\n            internal static readonly GUIStyle s_MonoLabelStyle = new GUIStyle(EditorStyles.label)\n            {\n                alignment = TextAnchor.UpperLeft\n            };\n            internal static readonly GUIStyle s_MonoLabelStylePadding = new GUIStyle(EditorStyles.label)\n            {\n                alignment = TextAnchor.UpperLeft,\n                padding = new RectOffset(25, 0, 0, 0),\n            };\n\n            internal static readonly GUIStyle s_MonoLabelBoldPaddingStyle = new GUIStyle(EditorStyles.label)\n            {\n                alignment = TextAnchor.UpperLeft,\n                padding = new RectOffset(25, 0, 0, 0),\n            };\n\n            internal static readonly GUIStyle s_MonoLabelNoWrapStyle = new GUIStyle(EditorStyles.label)\n            {\n                padding = new RectOffset(0, 0, 0, 0),\n                margin = new RectOffset(0, 0, 2, 0),\n            };\n\n            internal static readonly GUIStyle s_MonoLabelBoldStyle = new GUIStyle(EditorStyles.label)\n            {\n                padding = new RectOffset(0, 0, 0, 0),\n                margin = new RectOffset(0, 0, 0, 0),\n            };\n\n            internal static readonly GUIStyle s_OutputMeshTabStyle = new GUIStyle(\"LargeButton\")\n            {\n                padding = new RectOffset(0, 0, 0, 0),\n                margin = new RectOffset(-2, 0, 0, 0),\n            };\n\n            internal static readonly GUIStyle s_RenderTargetMeshBackgroundStyle = new GUIStyle();\n\n            internal static readonly GUIStyle s_PropertiesBottomMarginStyle = new GUIStyle(EditorStyles.label)\n            {\n                margin = new RectOffset(0, 0, 0, 10)\n            };\n\n            internal static readonly GUIStyle s_PropertiesLeftMarginStyle = new GUIStyle(EditorStyles.label)\n            {\n                margin = new RectOffset(k_Indent2, 0, 0, 0),\n                padding = new RectOffset(0, 0, 0, 0),\n            };\n\n            internal static readonly GUIStyle s_TextureButtonStyle = new GUIStyle()\n            {\n                fixedWidth = 20f,\n                margin = new RectOffset(0, 10, 0, 0),\n            };\n\n            internal const string k_WarningMultiThreadedMsg = \"The Frame Debugger requires multi-threaded renderer. If this error persists, try starting the Editor with -force-gfx-mt command line argument.\";\n            internal const string k_WarningLinuxOpenGLMsg = k_WarningMultiThreadedMsg + \" On Linux, the editor does not support a multi-threaded renderer when using OpenGL.\";\n            internal const string k_DescriptionString = \"Frame Debugger lets you step through draw calls and see how exactly frame is rendered. Click Enable!\";\n            internal const string k_TabbedWithPlaymodeErrorString = \"Frame Debugger can not be docked with the Game Window when trying to debug the editor.\";\n            internal static readonly GUIContent s_RenderTargetText = EditorGUIUtility.TrTextContent(\"RenderTarget\");\n            internal static readonly GUIContent s_CopyEventText = EditorGUIUtility.TrTextContent(\"Copy Event Info\");\n            internal static readonly GUIContent s_CopyPropertyText = EditorGUIUtility.TrTextContent(\"Copy Property\");\n            internal static readonly GUIContent[] s_FoldoutCopyText =\n            {\n                EditorGUIUtility.TrTextContent(\"Copy Output\"),\n                EditorGUIUtility.TrTextContent(\"Copy All Details\"),\n                EditorGUIUtility.TrTextContent(\"Copy All Keyword Properties\"),\n                EditorGUIUtility.TrTextContent(\"Copy All Texture Properties\"),\n                EditorGUIUtility.TrTextContent(\"Copy All Integer Properties\"),\n                EditorGUIUtility.TrTextContent(\"Copy All Float Properties\"),\n                EditorGUIUtility.TrTextContent(\"Copy All Vector Properties\"),\n                EditorGUIUtility.TrTextContent(\"Copy All Matrix Properties\"),\n                EditorGUIUtility.TrTextContent(\"Copy All Buffer Properties\"),\n                EditorGUIUtility.TrTextContent(\"Copy All Constant Buffer Properties\")\n            };\n            internal static readonly GUIContent s_RealShaderText = EditorGUIUtility.TrTextContent(\"Used Shader\", \"The shader used in this draw call.\");\n            internal static readonly GUIContent s_OriginalShaderText = EditorGUIUtility.TrTextContent(\"Original Shader\", \"The shader originally set to be used in this draw call.\");\n            internal static readonly GUIContent s_RayTracingShaderText = EditorGUIUtility.TrTextContent(\"Ray Tracing Shader\", \"\");\n            internal static readonly GUIContent s_RayTracingGenerationShaderText = EditorGUIUtility.TrTextContent(\"Ray Generation Shader\", \"\");\n            internal static readonly GUIContent s_ComputeShaderText = EditorGUIUtility.TrTextContent(\"Compute Shader\", \"\");\n            internal static readonly GUIContent s_BatchCauseText = EditorGUIUtility.TrTextContent(\"Batch cause\");\n            internal static readonly GUIContent s_PassLightModeText = EditorGUIUtility.TrTextContent(\"Pass\\nLightMode\");\n            internal static readonly GUIContent s_ArrayPopupButtonText = EditorGUIUtility.TrTextContent(\"...\");\n            internal static readonly GUIContent s_FoldoutOutputText = EditorGUIUtility.TrTextContent(\"Output\");\n            internal static readonly GUIContent s_FoldoutMeshText = EditorGUIUtility.TrTextContent(\"Meshes\");\n            internal static readonly GUIContent s_FoldoutMeshNotSupportedText = EditorGUIUtility.TrTextContent(\"Meshes - Not supported\");\n            internal static readonly GUIContent s_FoldoutEventDetailsText = EditorGUIUtility.TrTextContent(\"Details\");\n            internal static readonly GUIContent s_FoldoutTexturesText = EditorGUIUtility.TrTextContent(\"Textures\");\n            internal static readonly GUIContent s_FoldoutKeywordsText = EditorGUIUtility.TrTextContent(\"Keywords\");\n            internal static readonly GUIContent s_FoldoutFloatsText = EditorGUIUtility.TrTextContent(\"Floats\");\n            internal static readonly GUIContent s_FoldoutIntsText = EditorGUIUtility.TrTextContent(\"Ints\");\n            internal static readonly GUIContent s_FoldoutVectorsText = EditorGUIUtility.TrTextContent(\"Vectors\");\n            internal static readonly GUIContent s_FoldoutMatricesText = EditorGUIUtility.TrTextContent(\"Matrices\");\n            internal static readonly GUIContent s_FoldoutBuffersText = EditorGUIUtility.TrTextContent(\"Buffers\");\n            internal static readonly GUIContent s_FoldoutCBufferText = EditorGUIUtility.TrTextContent(\"Constant Buffers\");\n            internal static readonly GUIContent s_NotAvailableText = EditorGUIUtility.TrTextContent(k_NotAvailable);\n            internal static Texture2D s_RenderTargetMeshBackgroundTexture = null;\n            internal static readonly string[] s_BatchBreakCauses = FrameDebuggerUtility.GetBatchBreakCauseStrings();\n        }\n\n        // Constructor\n        static FrameDebuggerStyles()\n        {\n            float greyVal = 0.2196079f;\n            EventDetails.s_RenderTargetMeshBackgroundTexture = MakeTex(1, 1, new Color(greyVal, greyVal, greyVal, 1f));\n            EventDetails.s_RenderTargetMeshBackgroundStyle.normal.background = EventDetails.s_RenderTargetMeshBackgroundTexture;\n\n            Font monospacedFont = EditorGUIUtility.Load(\"Fonts/RobotoMono/RobotoMono-Regular.ttf\") as Font;\n            Font monospacedBoldFont = EditorGUIUtility.Load(\"Fonts/RobotoMono/RobotoMono-Bold.ttf\") as Font;\n            EventDetails.s_MonoLabelStyle.font = monospacedFont;\n            EventDetails.s_MonoLabelStylePadding.font = monospacedFont;\n            EventDetails.s_MonoLabelNoWrapStyle.font = monospacedFont;\n            EventDetails.s_ArrayFoldoutStyle.font = monospacedFont;\n\n            EventDetails.s_MonoLabelBoldStyle.font = monospacedBoldFont;\n            EventDetails.s_MonoLabelBoldPaddingStyle.font = monospacedBoldFont;\n        }\n\n        private static Texture2D MakeTex(int width, int height, Color col)\n        {\n            Color[] pix = new Color[width * height];\n            for (int i = 0; i < pix.Length; i++)\n                pix[i] = col;\n\n            Texture2D result = new Texture2D(width, height);\n            result.SetPixels(pix);\n            result.Apply();\n\n            return result;\n        }\n\n        internal static void OnDisable()\n        {\n            UnityEngine.Object.DestroyImmediate(EventDetails.s_RenderTargetMeshBackgroundTexture);\n            EventDetails.s_RenderTargetMeshBackgroundTexture = null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PerformanceTools/FrameDebuggerToolbarView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nusing UnityEngine;\nusing UnityEngine.Profiling;\nusing UnityEngine.Networking.PlayerConnection;\n\nusing UnityEditor;\nusing UnityEditorInternal;\nusing UnityEditorInternal.FrameDebuggerInternal;\nusing UnityEditor.Networking.PlayerConnection;\n\n\nnamespace UnityEditorInternal.FrameDebuggerInternal\n{\n    internal class FrameDebuggerToolbarView\n    {\n        // Non-Serialized\n        [NonSerialized] private int m_PrevEventsLimit = 0;\n        [NonSerialized] private int m_PrevEventsCount = 0;\n\n        // Returns true if repaint is needed\n        public bool DrawToolbar(FrameDebuggerWindow frameDebugger, IConnectionState m_AttachToPlayerState)\n        {\n            Profiler.BeginSample(\"DrawToolbar\");\n            GUILayout.BeginHorizontal(EditorStyles.toolbar);\n\n            DrawEnableDisableButton(frameDebugger, m_AttachToPlayerState, out bool needsRepaint);\n            DrawConnectionDropdown(frameDebugger, m_AttachToPlayerState, out bool isEnabled);\n\n            GUI.enabled = isEnabled;\n\n            DrawEventLimitSlider(frameDebugger, out int newLimit);\n            DrawPrevNextButtons(frameDebugger, ref newLimit);\n\n            GUILayout.EndHorizontal();\n            Profiler.EndSample();\n\n            return needsRepaint;\n        }\n\n        private void DrawEnableDisableButton(FrameDebuggerWindow frameDebuggerWindow, IConnectionState m_AttachToPlayerState, out bool needsRepaint)\n        {\n            needsRepaint = false;\n\n            EditorGUI.BeginChangeCheck();\n\n            bool wasEnabled = GUI.enabled;\n            GUI.enabled = m_AttachToPlayerState.connectedToTarget != ConnectionTarget.Editor || FrameDebuggerUtility.locallySupported;\n            GUIContent button = (FrameDebugger.enabled) ? FrameDebuggerStyles.TopToolbar.s_RecordButtonDisable : FrameDebuggerStyles.TopToolbar.s_RecordButtonEnable;\n            GUILayout.Toggle(FrameDebugger.enabled, button, EditorStyles.toolbarButtonLeft, GUILayout.MinWidth(80));\n            GUI.enabled = wasEnabled;\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                frameDebuggerWindow.ToggleFrameDebuggerEnabled();\n                needsRepaint = true;\n            }\n        }\n\n        private void DrawConnectionDropdown(FrameDebuggerWindow frameDebuggerWindow, IConnectionState m_AttachToPlayerState, out bool isEnabled)\n        {\n            PlayerConnectionGUILayout.ConnectionTargetSelectionDropdown(m_AttachToPlayerState, EditorStyles.toolbarDropDown);\n            isEnabled = FrameDebugger.enabled;\n            if (isEnabled && ProfilerDriver.connectedProfiler != FrameDebuggerUtility.GetRemotePlayerGUID())\n            {\n                // Switch from local to remote debugger or vice versa\n                frameDebuggerWindow.OnConnectedProfilerChange();\n            }\n        }\n\n        private void DrawEventLimitSlider(FrameDebuggerWindow frameDebuggerWindow, out int newLimit)\n        {\n            newLimit = 0;\n\n            EditorGUI.BeginChangeCheck();\n\n            bool wasEnabled = GUI.enabled;\n            GUI.enabled = FrameDebuggerUtility.count > 1;\n\n            // We need to use Slider instead of IntSlider due to a bug where the invisible label makes\n            // the mouse cursor different when hovering over the leftmost 10-20% of the slider (UUM-17184)\n            // We add 0.5 to make it switch between frames like when we use a IntSlider.\n            newLimit = (int) (0.5f + EditorGUILayout.Slider(FrameDebuggerUtility.limit, 1, FrameDebuggerUtility.count));\n\n            GUI.enabled = wasEnabled;\n\n            if (EditorGUI.EndChangeCheck())\n                frameDebuggerWindow.ChangeFrameEventLimit(newLimit);\n        }\n\n        private void DrawPrevNextButtons(FrameDebuggerWindow frameDebuggerWindow, ref int newLimit)\n        {\n            bool wasEnabled = GUI.enabled;\n\n            GUI.enabled = newLimit > 1;\n            if (GUILayout.Button(FrameDebuggerStyles.TopToolbar.s_PrevFrame, EditorStyles.toolbarButton))\n                frameDebuggerWindow.ChangeFrameEventLimit(newLimit - 1);\n\n            GUI.enabled = newLimit < FrameDebuggerUtility.count;\n            if (GUILayout.Button(FrameDebuggerStyles.TopToolbar.s_NextFrame, EditorStyles.toolbarButtonRight))\n                frameDebuggerWindow.ChangeFrameEventLimit(newLimit + 1);\n\n            // If we had last event selected, and something changed in the scene so that\n            // number of events is different - then try to keep the last event selected.\n            if (m_PrevEventsLimit == m_PrevEventsCount)\n                if (FrameDebuggerUtility.count != m_PrevEventsCount && FrameDebuggerUtility.limit == m_PrevEventsLimit)\n                    frameDebuggerWindow.ChangeFrameEventLimit(FrameDebuggerUtility.count);\n\n            // The number of events has changed...\n            if (FrameDebuggerUtility.count != m_PrevEventsCount)\n            {\n                frameDebuggerWindow.ReselectItemOnCountChange();\n            }\n\n            m_PrevEventsLimit = FrameDebuggerUtility.limit;\n            m_PrevEventsCount = FrameDebuggerUtility.count;\n\n            GUI.enabled = wasEnabled;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PerformanceTools/FrameDebuggerTreeView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Globalization;\nusing UnityEditor.IMGUI.Controls;\nusing Object = UnityEngine.Object;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewGUI = UnityEditor.IMGUI.Controls.TreeViewGUI<int>;\nusing TreeViewDataSource = UnityEditor.IMGUI.Controls.TreeViewDataSource<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditorInternal.FrameDebuggerInternal\n{\n    internal class FrameDebuggerTreeView\n    {\n        internal readonly TreeViewController m_TreeView;\n        internal FrameDebuggerTreeViewDataSource m_DataSource;\n        private readonly FrameDebuggerWindow m_FrameDebugger;\n\n        public FrameDebuggerTreeView(FrameDebuggerEvent[] frameEvents, TreeViewState treeViewState, FrameDebuggerWindow window, Rect startRect)\n        {\n            m_FrameDebugger = window;\n            m_TreeView = new TreeViewController(window, treeViewState);\n            m_DataSource = new FrameDebuggerTreeViewDataSource(m_TreeView, frameEvents);\n            var gui = new FrameDebuggerTreeViewGUI(m_TreeView);\n            m_TreeView.Init(startRect, m_DataSource, gui, null);\n            m_TreeView.ReloadData();\n            m_TreeView.selectionChangedCallback += SelectionChanged;\n            m_TreeView.itemSingleClickedCallback += ItemSingleClicked;\n            m_TreeView.itemDoubleClickedCallback += PingFrameEventObject;\n        }\n\n        void ItemSingleClicked(int selectedID)\n        {\n            if (Event.current.type == EventType.MouseDown && EditorGUI.actionKey)\n                PingFrameEventObject(selectedID);\n        }\n\n        void SelectionChanged(int[] selectedIDs)\n        {\n            if (selectedIDs.Length < 1)\n                return;\n\n            int id = selectedIDs[0];\n            int eventIndex = id;\n            FrameDebuggerTreeViewItem originalItem = null;\n\n            // For tree hierarchy nodes, their IDs are not the frame event indices;\n            // fetch the ID from the node itself in that case.\n            // IDs for hierarchy nodes are negative and need to stay consistently ordered so\n            // that tree expanded state behaves well when something in the scene changes.\n            //\n            // When selecting a hierarchy node, we want it's last child event to be set as the limit,\n            // so that rendered state corresponds to \"everything up to and including this whole sub-tree\".\n            if (eventIndex <= 0)\n            {\n                originalItem = m_TreeView.FindItem(id) as FrameDebuggerTreeViewItem;\n                FrameDebuggerTreeViewItem item = m_TreeView.FindItem(id) as FrameDebuggerTreeViewItem;\n                if (item != null)\n                    eventIndex = item.m_EventIndex;\n\n                // If still has no valid ID, do nothing.\n                if (eventIndex <= 0)\n                    return;\n            }\n\n            m_FrameDebugger.ChangeFrameEventLimit(eventIndex, originalItem);\n        }\n\n        private void PingFrameEventObject(int selectedID)\n        {\n            Object obj = FrameDebuggerUtility.GetFrameEventObject(selectedID - 1);\n            if (obj != null)\n                EditorGUIUtility.PingObject(obj);\n            m_FrameDebugger.DrawSearchField(string.Empty);\n        }\n\n        public void ReselectFrameEventIndex()\n        {\n            FrameDebuggerTreeViewItem item = GetSelectedTreeViewItem();\n            if (item != null)\n                SetSelection(item.m_EventIndex);\n        }\n\n        public void SelectFrameEventIndex(int eventIndex)\n        {\n            // Check if we'd end up selecting same \"frame event\":\n            // different tree nodes could result in the same frame debugger event\n            // limit, e.g. a hierarchy node sets last child event as the limit.\n            // If the limit event is the same, then do not change the currently selected item.\n            FrameDebuggerTreeViewItem item = GetSelectedTreeViewItem();\n            if (item == null || item.m_EventIndex != eventIndex)\n                SetSelection(eventIndex);\n        }\n\n        private FrameDebuggerTreeViewItem GetSelectedTreeViewItem()\n        {\n            int[] selection = m_TreeView.GetSelection();\n            if (selection.Length > 0)\n                return m_TreeView.FindItem(selection[0]) as FrameDebuggerTreeViewItem;\n\n            return null;\n        }\n\n        private void SetSelection(int eventIndex)\n        {\n            m_TreeView.SetSelection(new[] { eventIndex }, true);\n            m_FrameDebugger.RepaintOnLimitChange();\n        }\n\n        public void DrawTree(Rect rect)\n        {\n            int keyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard);\n            m_TreeView.OnGUI(rect, keyboardControlID);\n        }\n\n        // Item for TreeView\n        // ID is different for leaf nodes (actual frame events) vs hierarchy nodes (parent profiler nodes):\n        // - leaf node IDs are frame event indices (always > 0).\n        // - hierarchy node IDs are always negative; to get frame event index we want we need to lookup the node and get it from m_EventIndex.\n        public class FrameDebuggerTreeViewItem : TreeViewItem\n        {\n            public FrameDebuggerEvent m_FrameEvent;\n            public int m_ChildEventCount;\n            public int m_EventIndex;\n\n            public FrameDebuggerTreeViewItem(int id, int depth, FrameDebuggerTreeViewItem parent, string displayName)\n                : base(id, depth, parent, displayName)\n            {\n                m_EventIndex = id;\n            }\n        }\n\n        // GUI for TreeView\n        private class FrameDebuggerTreeViewGUI : TreeViewGUI\n        {\n            private const float kSmallMargin = 4;\n\n            public FrameDebuggerTreeViewGUI(TreeViewController treeView)\n                : base(treeView)\n            {\n            }\n\n            protected override Texture GetIconForItem(TreeViewItem item)\n            {\n                return null;\n            }\n\n            private int childCounter = 0;\n\n            protected override void OnContentGUI(Rect rect, int row, TreeViewItem itemRaw, string label, bool selected, bool focused, bool useBoldFont, bool isPinging)\n            {\n                if (Event.current.type != EventType.Repaint)\n                    return;\n\n                FrameDebuggerTreeViewItem item = (FrameDebuggerTreeViewItem)itemRaw;\n                GUIContent tempContent;\n                GUIStyle style;\n\n                bool isParent = (item.hasChildren);\n                childCounter = (isParent) ? 1 : (childCounter + 1);\n\n                // Draw background\n                tempContent = EditorGUIUtility.TempContent(\"\");\n                style = FrameDebuggerStyles.Tree.s_RowText;\n                style.Draw(rect, tempContent, false, false, false, false);\n\n                // indent\n                float indent = GetContentIndent(item);\n                rect.x += indent;\n                rect.width -= indent;\n\n                // child event count\n                if (isParent)\n                {\n                    tempContent = EditorGUIUtility.TempContent(item.m_ChildEventCount.ToString(CultureInfo.InvariantCulture));\n\n                    Rect r = rect;\n                    r.width -= kSmallMargin;\n                    style = FrameDebuggerStyles.Tree.s_RowTextRight;\n                    style.Draw(r, tempContent, false, false, false, false);\n\n                    // reduce width of available space for the name, so that it does not overlap event count\n                    rect.width -= style.CalcSize(tempContent).x + kSmallMargin * 2;\n                }\n\n\n                // draw event name\n                if (string.IsNullOrEmpty(item.displayName))\n                    tempContent = EditorGUIUtility.TempContent(FrameDebuggerStyles.Tree.k_UnknownScopeString);\n                else\n                    tempContent = EditorGUIUtility.TempContent(item.displayName);\n\n                style = isParent ? FrameDebuggerStyles.Tree.s_RowTextBold : FrameDebuggerStyles.Tree.s_RowText;\n                style.Draw(rect, tempContent, false, false, false, selected && focused);\n            }\n\n            protected override void RenameEnded()\n            {\n            }\n        }\n\n        // Data source for TreeView\n\n        internal class FrameDebuggerTreeViewDataSource : TreeViewDataSource\n        {\n            private FrameDebuggerEvent[] m_FrameEvents;\n\n            public override bool IsRenamingItemAllowed(TreeViewItem item) => false;\n            public override bool CanBeMultiSelected(TreeViewItem item) => false;\n\n            public FrameDebuggerTreeViewDataSource(TreeViewController treeView, FrameDebuggerEvent[] frameEvents) : base(treeView)\n            {\n                m_FrameEvents = frameEvents;\n                rootIsCollapsable = false;\n                showRootItem = false;\n            }\n\n            public void SetEvents(FrameDebuggerEvent[] frameEvents)\n            {\n                bool wasEmpty = m_FrameEvents == null || m_FrameEvents.Length < 1;\n\n                m_FrameEvents = frameEvents;\n                m_NeedRefreshRows = true;\n                ReloadData();\n\n                // Only expand whole events tree if it was empty before.\n                // If we already had something in there, we want to preserve user's expanded items.\n                if (wasEmpty)\n                    SetExpandedWithChildren(m_RootItem, true);\n            }\n\n            // Used while building the tree data source; represents current tree hierarchy level\n            private class FrameDebuggerTreeHierarchyLevel\n            {\n                internal readonly FrameDebuggerTreeViewItem item;\n                internal readonly List<TreeViewItem> children;\n                internal FrameDebuggerTreeHierarchyLevel(int depth, int id, string name, FrameDebuggerTreeViewItem parent)\n                {\n                    item = new FrameDebuggerTreeViewItem(id, depth, parent, name);\n                    children = new List<TreeViewItem>();\n                }\n            }\n\n            private static void CloseLastHierarchyLevel(List<FrameDebuggerTreeHierarchyLevel> eventStack, int prevFrameEventIndex)\n            {\n                var idx = eventStack.Count - 1;\n                eventStack[idx].item.children = eventStack[idx].children;\n                eventStack[idx].item.m_EventIndex = prevFrameEventIndex;\n\n                if (eventStack[idx].item.parent != null)\n                    ((FrameDebuggerTreeViewItem)eventStack[idx].item.parent).m_ChildEventCount += eventStack[idx].item.m_ChildEventCount;\n\n                eventStack.RemoveAt(idx);\n            }\n\n            public override void FetchData()\n            {\n                FrameDebuggerTreeHierarchyLevel rootLevel = new FrameDebuggerTreeHierarchyLevel(0, 0, string.Empty, null);\n\n                // Hierarchy levels of a tree being built\n                List<FrameDebuggerTreeHierarchyLevel> eventStack = new List<FrameDebuggerTreeHierarchyLevel>();\n                eventStack.Add(rootLevel);\n\n                int hierarchyIDCounter = -1;\n                for (int i = 0; i < m_FrameEvents.Length; ++i)\n                {\n                    // This will be a slash-delimited string, e.g. Foo/Bar/Baz.\n                    // Add \"/\" in front to account for the single (invisible) root item\n                    // that the TreeView always has.\n                    string context = \"/\" + (FrameDebuggerUtility.GetFrameEventInfoName(i) ?? string.Empty);\n                    string[] names = context.Split('/');\n\n                    // find matching hierarchy level\n                    int level = 0;\n                    while (level < eventStack.Count && level < names.Length)\n                    {\n                        if (names[level] != eventStack[level].item.displayName)\n                            break;\n\n                        ++level;\n                    }\n\n                    // close all the further levels from previous events in the stack\n                    while (eventStack.Count > 0 && eventStack.Count > level)\n                        CloseLastHierarchyLevel(eventStack, i);\n\n                    if (FrameDebuggerHelper.IsAHierarchyLevelBreakEvent(m_FrameEvents[i].m_Type))\n                        continue;\n\n                    // add all further levels for current event\n                    for (int j = level; j < names.Length; ++j)\n                    {\n                        FrameDebuggerTreeHierarchyLevel parent = eventStack[eventStack.Count - 1];\n                        FrameDebuggerTreeHierarchyLevel newLevel = new FrameDebuggerTreeHierarchyLevel(eventStack.Count - 1, --hierarchyIDCounter, names[j], parent.item);\n                        parent.children.Add(newLevel.item);\n                        eventStack.Add(newLevel);\n                    }\n\n                    if (FrameDebuggerHelper.IsAHiddenEvent(m_FrameEvents[i].m_Type))\n                        continue;\n\n                    // add leaf event to current level\n                    Object eventObj = FrameDebuggerUtility.GetFrameEventObject(i);\n                    string displayName = FrameDebuggerStyles.s_FrameEventTypeNames[(int)m_FrameEvents[i].m_Type];\n\n                    if (eventObj)\n                        displayName += \" \" + eventObj.name;\n\n                    FrameDebuggerTreeHierarchyLevel parentEvent = eventStack[eventStack.Count - 1];\n\n                    int leafEventID = i + 1;\n                    FrameDebuggerTreeViewItem item = new FrameDebuggerTreeViewItem(leafEventID, eventStack.Count - 1, parentEvent.item, displayName);\n\n                    item.m_FrameEvent = m_FrameEvents[i];\n                    parentEvent.children.Add(item);\n                    ++parentEvent.item.m_ChildEventCount;\n                }\n\n                while (eventStack.Count > 0)\n                    CloseLastHierarchyLevel(eventStack, m_FrameEvents.Length);\n\n                m_RootItem = rootLevel.item;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Picking/PickingIncludeExcludeList.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing Unity.Collections;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public struct PickingIncludeExcludeList : IDisposable\n    {\n        NativeArray<int> m_IncludeRenderers, m_ExcludeRenderers, m_IncludeEntities, m_ExcludeEntities;\n        public NativeArray<int> IncludeRenderers => m_IncludeRenderers;\n        public NativeArray<int> ExcludeRenderers => m_ExcludeRenderers;\n        public NativeArray<int> IncludeEntities => m_IncludeEntities;\n        public NativeArray<int> ExcludeEntities => m_ExcludeEntities;\n\n        public PickingIncludeExcludeList(List<int> includeRendererInstanceIDs, List<int> excludeRendererInstanceIDs, List<int> includeEntityIndices, List<int> excludeEntityIndices, Allocator allocator = Allocator.Persistent)\n        {\n            m_IncludeRenderers = ArrayFromList(includeRendererInstanceIDs, allocator);\n            m_ExcludeRenderers = ArrayFromList(excludeRendererInstanceIDs, allocator);\n            m_IncludeEntities = ArrayFromList(includeEntityIndices, allocator);\n            m_ExcludeEntities = ArrayFromList(excludeEntityIndices, allocator);\n        }\n\n        public void Dispose()\n        {\n            if (IncludeRenderers.IsCreated) IncludeRenderers.Dispose();\n            if (ExcludeRenderers.IsCreated) ExcludeRenderers.Dispose();\n            if (IncludeEntities.IsCreated) IncludeEntities.Dispose();\n            if (ExcludeEntities.IsCreated) ExcludeEntities.Dispose();\n        }\n\n        private static NativeArray<int> ArrayFromList(List<int> list, Allocator allocator)\n        {\n            if (list == null || list.Count == 0)\n                return new NativeArray<int>();\n\n            var array = new NativeArray<int>(list.Count, allocator, NativeArrayOptions.UninitializedMemory);\n            // Use explicit copy length because the internal list might be longer than Count, which causes an error\n            NativeArray<int>.Copy(NoAllocHelpers.ExtractArrayFromList(list), array, list.Count);\n            return array;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Picking/PickingObject.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Runtime.InteropServices;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [StructLayout(LayoutKind.Sequential)]\n    struct PickingObject : System.IEquatable<PickingObject>\n    {\n        Object m_Target;\n        int m_MaterialIndex;\n\n        public Object target => m_Target;\n        public int materialIndex => m_MaterialIndex;\n\n        public static PickingObject Empty => new PickingObject(null);\n        public int GetInstanceID() => m_Target == null ? 0 : m_Target.GetInstanceID();\n\n        public PickingObject(Object obj, int matIndex = 0)\n        {\n            m_Target = obj;\n            m_MaterialIndex = Mathf.Max(0, matIndex);\n        }\n\n        public static explicit operator Object(PickingObject picking) => picking.target;\n        public static explicit operator PickingObject(Object @object) => new PickingObject(@object);\n\n        public static bool operator ==(PickingObject lhs, PickingObject rhs) => lhs.Equals(rhs);\n        public static bool operator !=(PickingObject lhs, PickingObject rhs) => !(lhs == rhs);\n\n        public bool Equals(PickingObject other)\n        {\n            return Equals(m_Target, other.m_Target)\n                && m_MaterialIndex == other.m_MaterialIndex;\n        }\n\n        public override bool Equals(object obj)\n        {\n            return obj is PickingObject other && Equals(other);\n        }\n\n        public override string ToString()\n        {\n            return $\"{m_Target} ({materialIndex})\";\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                var hashCode = (m_Target != null ? m_Target.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ m_MaterialIndex;\n                return hashCode;\n            }\n        }\n\n        public bool TryGetComponent<T>(out T value) where T : Component\n        {\n            return TryGetComponent<T>(target, out value);\n        }\n\n        internal static bool TryGetComponent<T>(Object obj, out T value) where T : Component\n        {\n            if (obj is T cast)\n                value = cast;\n            else if (obj is GameObject go)\n                return go.TryGetComponent(out value);\n            else if (obj is Component component)\n                return component.TryGetComponent(out value);\n            else\n                value = null;\n\n            return value != null;\n        }\n\n        public bool TryGetParent(out Transform parent)\n        {\n            if (TryGetComponent<Transform>(out var transform))\n                return (parent = transform.parent) != null;\n            parent = null;\n            return false;\n        }\n\n        public bool TryGetGameObject(out GameObject gameObject)\n        {\n            if (target is GameObject go)\n                gameObject = go;\n            else if (target is Component component)\n                gameObject = component.gameObject;\n            else\n                gameObject = null;\n            return gameObject != null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlatformSupport/PlatformIconField.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System;\nusing System.Linq;\nusing System.Collections;\nusing System.Collections.Generic;\nusing Object = UnityEngine.Object;\nusing UnityEditorInternal;\n\nnamespace UnityEditor.PlatformSupport\n{\n    internal class PlatformIconFieldGroup\n    {\n        internal class IconFieldGroupInfo\n        {\n            public PlatformIconKind m_Kind;\n            public string m_Label;\n            public bool m_State;\n            public int m_SetIconSlots;\n            public int m_IconSlotCount;\n            public string m_KindDescription;\n\n            public override bool Equals(object obj)\n            {\n                var info = obj as IconFieldGroupInfo;\n                if (ReferenceEquals(info, null))\n                    return false;\n                if (ReferenceEquals(info, this))\n                    return true;\n                return info.m_Label == m_Label;\n            }\n\n            public override int GetHashCode()\n            {\n                return this.m_Label.GetHashCode();\n            }\n        }\n\n        public BuildTargetGroup targetGroup { get; protected set; }\n        internal Dictionary<IconFieldGroupInfo, Dictionary<IconFieldGroupInfo, PlatformIconField[]>> m_IconsFields =\n            new Dictionary<IconFieldGroupInfo, Dictionary<IconFieldGroupInfo, PlatformIconField[]>>();\n\n        internal Dictionary<PlatformIconKind, PlatformIcon[]> m_PlatformIconsByKind = new Dictionary<PlatformIconKind, PlatformIcon[]>();\n\n        internal PlatformIconFieldGroup(BuildTargetGroup targetGroup)\n        {\n            this.targetGroup = targetGroup;\n        }\n\n        internal PlatformIconField CreatePlatformIconField(PlatformIcon icon)\n        {\n            if (icon.maxLayerCount > 1)\n                return new PlatformIconFieldMultiLayer(icon, targetGroup);\n\n            return new PlatformIconFieldSingleLayer(icon, targetGroup);\n        }\n\n        public bool IsEmpty()\n        {\n            return !(m_IconsFields.Count > 0);\n        }\n\n        public void SetPlatformIcons(PlatformIcon[] icons, PlatformIconKind kind)\n        {\n            m_PlatformIconsByKind[kind] = icons;\n\n            IconFieldGroupInfo kindKey = new IconFieldGroupInfo();\n            kindKey.m_Kind = kind;\n            kindKey.m_Label = kind.ToString();\n            kindKey.m_KindDescription = kind.description;\n\n            Dictionary<IconFieldGroupInfo, PlatformIconField[]> kindDictionary;\n\n            if (!m_IconsFields.ContainsKey(kindKey))\n            {\n                kindKey.m_State = false;\n                kindDictionary = new Dictionary<IconFieldGroupInfo, PlatformIconField[]>();\n            }\n            else\n            {\n                kindDictionary = m_IconsFields[kindKey];\n            }\n\n            var groupedBySubKind = icons.GroupBy(i => i.iconSubKind);\n\n            foreach (var subKindGroup in groupedBySubKind)\n            {\n                var subKindIcons = subKindGroup.ToArray().Select(i => CreatePlatformIconField(i)).ToArray();\n\n                IconFieldGroupInfo subKindKey = new IconFieldGroupInfo();\n                subKindKey.m_Kind = null;\n                subKindKey.m_Label = subKindGroup.Key;\n                subKindKey.m_IconSlotCount = subKindIcons.Length;\n                subKindKey.m_SetIconSlots = PlayerSettings.GetNonEmptyPlatformIconCount(subKindGroup.ToArray());\n\n                if (!kindDictionary.ContainsKey(subKindKey))\n                    subKindKey.m_State = false;\n\n                kindKey.m_IconSlotCount += subKindKey.m_IconSlotCount;\n                kindKey.m_SetIconSlots += subKindKey.m_SetIconSlots;\n\n                kindDictionary[subKindKey] = subKindIcons;\n            }\n\n            m_IconsFields[kindKey] = kindDictionary;\n        }\n\n        public void Reset()\n        {\n            foreach (var group in m_IconsFields)\n                foreach (var subgroup in group.Value)\n                    foreach (var field in subgroup.Value)\n                        field.platformIcon.SetTextures(null);\n            foreach (var kind in m_PlatformIconsByKind)\n                foreach (var icon in kind.Value)\n                    icon.SetTextures(null);\n        }\n    }\n\n    abstract class PlatformIconField\n    {\n        protected const int kSlotSize = 64;\n        protected const float kHeaderHeight = 18;\n        protected const int kMaxElementHeight = 116;\n        protected const int kMaxPreviewSize = 86;\n        protected const int kIconSpacing = 8;\n\n        public PlatformIcon platformIcon { get; protected set; }\n        protected BuildTargetGroup m_TargetGroup;\n        protected string m_HeaderString;\n        protected string m_SizeLabel;\n\n        // TODO move the styles to an uinified location for this & ReorderableList.\n        internal ReorderableList.Defaults s_Defaults = new ReorderableList.Defaults();\n\n        internal PlatformIconField(PlatformIcon platformIcon, BuildTargetGroup targetGroup)\n        {\n            this.platformIcon = platformIcon;\n            m_TargetGroup = targetGroup;\n            m_HeaderString = this.platformIcon.description;\n            m_SizeLabel = string.Format(\"{0}x{1}px\", platformIcon.width, platformIcon.height);\n        }\n\n        public static Rect GetContentRect(Rect rect, float paddingVertical = 0, float paddingHorizontal = 0)\n        {\n            Rect r = rect;\n\n            r.yMin += paddingVertical;\n            r.yMax -= paddingVertical;\n            r.xMin += paddingHorizontal;\n            r.xMax -= paddingHorizontal;\n            return r;\n        }\n\n        internal abstract void DrawAt();\n    }\n\n    class PlatformIconFieldSingleLayer : PlatformIconField\n    {\n        private bool m_ShowSizeLabel = true;\n        private string m_PlatformName;\n\n        internal PlatformIconFieldSingleLayer(PlatformIcon platformIcon, BuildTargetGroup targetGroup) : base(platformIcon, targetGroup)\n        {\n            m_PlatformName = PlayerSettings.GetPlatformName(m_TargetGroup);\n        }\n\n        void DrawHeader(Rect headerRect)\n        {\n            // draw the background on repaint\n            if (Event.current.type == EventType.Repaint)\n                s_Defaults.DrawHeaderBackground(headerRect);\n\n            // apply the padding to get the internal rect\n            headerRect.xMin += ReorderableList.Defaults.padding;\n            headerRect.xMax -= ReorderableList.Defaults.padding;\n            headerRect.height -= 2;\n            headerRect.y += 1;\n\n            m_ShowSizeLabel = headerRect.width > (EditorGUIUtility.labelWidth  + kSlotSize + kIconSpacing + 24);\n\n\n            string sizeLabelString = m_HeaderString;\n            if (!m_ShowSizeLabel)\n                sizeLabelString += string.Format(\"({0})\", m_SizeLabel);\n\n            GUI.Label(headerRect, LocalizationDatabase.GetLocalizedString(sizeLabelString), EditorStyles.label);\n        }\n\n        void DrawElement(Rect elementRect)\n        {\n            int slotWidth = kMaxPreviewSize;\n            int slotHeight = (int)((float)platformIcon.height / platformIcon.height * slotWidth);  // take into account the aspect ratio\n            int previewWidth = Mathf.Min(slotWidth, platformIcon.width);\n            int previewHeight = (int)((float)platformIcon.height * previewWidth / platformIcon.width);  // take into account the aspect ratio\n\n            if (Event.current.type == EventType.Repaint)\n                s_Defaults.boxBackground.Draw(elementRect, false, false, false, false);\n\n            float width = Mathf.Min(elementRect.width, EditorGUIUtility.labelWidth + 4 + kSlotSize + kIconSpacing + kMaxPreviewSize);\n            Rect elementContentRect = GetContentRect(elementRect, 6f, 12f);\n            Rect textureRect =\n                new Rect(elementContentRect.x + elementContentRect.width - kMaxPreviewSize - slotWidth - kIconSpacing,\n                    elementContentRect.y, slotWidth, slotHeight);\n\n            Texture2D texture = (Texture2D)EditorGUI.ObjectField(\n                textureRect,\n                platformIcon.GetTexture(0),\n                typeof(Texture2D),\n                false);\n\n            platformIcon.SetTexture(texture, 0);\n\n            // Preview\n            Rect previewRect = new Rect(elementContentRect.x + elementContentRect.width - kMaxPreviewSize, elementContentRect.y, previewWidth, previewHeight);\n\n            GUI.Box(previewRect, \"\");\n            Texture2D closestIcon = platformIcon.GetPreviewTextures()[0]; // 0 is 1st layer\n            if (closestIcon != null)\n                GUI.DrawTexture(GetContentRect(previewRect, 1, 1), closestIcon);\n\n            //Do not show size label if there is not enough space for it in the body.\n            if (m_ShowSizeLabel)\n            {\n                GUI.Label(new Rect(elementContentRect.x, elementContentRect.y, width - kSlotSize - kIconSpacing, 20),\n                    m_SizeLabel);\n            }\n        }\n\n        internal override void DrawAt()\n        {\n            Rect rect = GUILayoutUtility.GetRect(0, kMaxElementHeight + kIconSpacing, GUILayout.ExpandWidth(true));\n\n            Rect headerRect = new Rect(rect.x, rect.y, rect.width, kHeaderHeight);\n            Rect elementRect = new Rect(rect.x, rect.y + kHeaderHeight, rect.width, rect.height - kHeaderHeight - kIconSpacing);\n\n            DrawHeader(headerRect);\n            DrawElement(elementRect);\n        }\n    }\n\n    class PlatformIconFieldMultiLayer : PlatformIconField\n    {\n        ReorderableIconLayerList m_IconLayers;\n\n        void EnsureMinimumNumberOfTextures()\n        {\n            while (m_IconLayers.textures.Count < m_IconLayers.minItems)\n                m_IconLayers.textures.Add(null);\n        }\n\n        internal PlatformIconFieldMultiLayer(PlatformIcon platformIcon, BuildTargetGroup targetGroup) : base(platformIcon, targetGroup)\n        {\n            bool showControls = this.platformIcon.minLayerCount != this.platformIcon.maxLayerCount;\n\n            m_IconLayers = new ReorderableIconLayerList(platformIcon.draggable, showControls);\n            m_IconLayers.headerString = string.Format(\"{0} ({1})\", this.platformIcon.description, m_SizeLabel);\n            m_IconLayers.minItems = this.platformIcon.minLayerCount;\n            m_IconLayers.maxItems = this.platformIcon.maxLayerCount;\n\n            string[] customLayerLabels = platformIcon.kind.customLayerLabels;\n            if (customLayerLabels != null && customLayerLabels.Length > 0)\n                m_IconLayers.SetElementLabels(platformIcon.kind.customLayerLabels);\n\n            int slotWidth = kMaxPreviewSize;\n            int slotHeight = (int)((float)platformIcon.height / platformIcon.height * slotWidth);\n            m_IconLayers.SetImageSize(slotWidth, slotHeight);\n\n            m_IconLayers.textures = platformIcon.GetTextures().ToList();\n            EnsureMinimumNumberOfTextures();\n        }\n\n        internal override void DrawAt()\n        {\n            m_IconLayers.textures = platformIcon.GetTextures().ToList();\n            m_IconLayers.previewTextures =  platformIcon.GetPreviewTextures().ToList();\n            EnsureMinimumNumberOfTextures();\n\n            m_IconLayers.DoLayoutList();\n            EditorGUILayout.Space();\n\n            var validLayerCount = this.platformIcon.GetValidLayerCount();\n\n            // Don't show warning if no layers are set in that case the default placeholder icon will be used.\n            if (validLayerCount > 0 && validLayerCount < this.platformIcon.minLayerCount)\n            {\n                var errorMsg = string.Format(\"{0} icons require at least {1} layers to be set with valid textures, however currently only {2} {3} set.\",\n                    this.platformIcon.kind.ToString(),\n                    this.platformIcon.minLayerCount,\n                    validLayerCount,\n                    validLayerCount == 1 ? \"layer is\" : \"layers are\"\n                );\n\n                EditorGUILayout.Space();\n                EditorGUILayout.HelpBox(errorMsg, MessageType.Error);\n                EditorGUILayout.Space();\n            }\n\n            platformIcon.SetTextures(m_IconLayers.textures.ToArray());\n\n            EditorGUILayout.Space();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlatformSupport/PlayerSettingsPlatformIcons.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing System.Collections.Generic;\n\nusing UnityEngine.Bindings;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditor.Build;\n\nnamespace UnityEditor\n{\n    internal struct PlatformIconStruct\n    {\n        [NativeName(\"m_Width\")]\n        public int Width;\n        [NativeName(\"m_Height\")]\n        public int Height;\n        [NativeName(\"m_Kind\")]\n        public int Kind;\n        [NativeName(\"m_SubKind\")]\n        public string SubKind;\n        [NativeName(\"m_Textures\")]\n        public Texture2D[] Textures;\n    }\n\n    internal struct LegacyPlatformIcon\n    {\n        [NativeName(\"m_Icon\")]\n        public Texture2D Icon;\n        [NativeName(\"m_Width\")]\n        public int Width;\n        [NativeName(\"m_Height\")]\n        public int Height;\n        [NativeName(\"m_Kind\")]\n        public IconKind Kind;\n    }\n\n    internal struct LegacyBuildTargetIcons\n    {\n        [NativeName(\"m_BuildTarget\")]\n        public string BuildTarget;\n        [NativeName(\"m_Icons\")]\n        public LegacyPlatformIcon[] Icons;\n    }\n\n    internal struct BuildTargetIcons\n    {\n        [NativeName(\"m_BuildTarget\")]\n        public string BuildTarget;\n        [NativeName(\"m_Icons\")]\n        public PlatformIconStruct[] Icons;\n    }\n\n    public class PlatformIcon\n    {\n        internal List<Texture2D> m_Textures;\n        private Texture2D[] m_PreviewTextures;\n\n        public int layerCount\n        {\n            get\n            {\n                return m_Textures.Count;\n            }\n            set\n            {\n                value = Math.Clamp(value, minLayerCount, maxLayerCount);\n\n                if (value < m_Textures.Count)\n                    m_Textures.RemoveRange(value, m_Textures.Count - 1);\n                else if (value > m_Textures.Count)\n                    m_Textures.AddRange(new Texture2D[value - m_Textures.Count]);\n            }\n        }\n\n        public int maxLayerCount  { get; private set; }\n        public int minLayerCount  { get; private set; }\n        internal string description  { get; private set; }\n        public int width { get; private set; }\n        public int height { get; private set; }\n        internal bool draggable { get; set; }\n\n        public PlatformIconKind kind { get; private set; }\n        internal string iconSubKind { get; private set; }\n\n        internal PlatformIconStruct GetPlatformIconStruct()\n        {\n            PlatformIconStruct platformIconStruct = new PlatformIconStruct();\n            platformIconStruct.Textures = m_Textures.ToArray();\n            platformIconStruct.Width = width;\n            platformIconStruct.Height = height;\n            platformIconStruct.Kind = kind.kind;\n            platformIconStruct.SubKind = iconSubKind;\n\n            return platformIconStruct;\n        }\n\n        internal bool IsEmpty()\n        {\n            return m_Textures.Count(t => t != null) == 0;\n        }\n\n        internal static PlatformIcon[] GetRequiredPlatformIconsByType(PlatformIconKind kind, IReadOnlyDictionary<PlatformIconKind, PlatformIcon[]> requiredIcons)\n        {\n            if (kind != PlatformIconKind.Any)\n                return requiredIcons[kind];\n\n            return requiredIcons.Values.SelectMany(i => i).ToArray();\n        }\n\n        internal PlatformIcon(int width, int height, int minLayerCount, int maxLayerCount, string iconSubKind, string description, PlatformIconKind kind, bool draggable = true)\n        {\n            this.width = width;\n            this.height = height;\n            this.iconSubKind = iconSubKind;\n            this.description = description;\n            this.minLayerCount = minLayerCount;\n            this.maxLayerCount = maxLayerCount;\n            this.kind = kind;\n            this.draggable = draggable;\n\n            m_Textures = new List<Texture2D>();\n        }\n\n        public Texture2D GetTexture(int layer = 0)\n        {\n            if (layer < 0 || layer >= maxLayerCount)\n                throw new ArgumentOutOfRangeException($\"Attempting to retrieve icon layer {layer}, while the icon only contains {layerCount} layers!\");\n            return layer < layerCount ? m_Textures[layer] : null;\n        }\n\n        public Texture2D[] GetTextures()\n        {\n            return m_Textures.ToArray();\n        }\n\n        internal void SetPreviewTextures(Texture2D[] textures)\n        {\n            m_PreviewTextures = textures;\n        }\n\n        internal Texture2D[] GetPreviewTextures()\n        {\n            return m_PreviewTextures;\n        }\n\n        public void SetTexture(Texture2D texture, int layer = 0)\n        {\n            if (layer < 0 || layer >= maxLayerCount)\n            {\n                throw new ArgumentOutOfRangeException($\"Attempting to set icon layer {layer}, while icon only supports {maxLayerCount} layers!\");\n            }\n            if (layer > m_Textures.Count - 1)\n            {\n                for (int i = m_Textures.Count; i <= layer; i++)\n                    m_Textures.Add(null);\n            }\n\n            m_Textures[layer] = texture;\n        }\n\n        public void SetTextures(params Texture2D[] textures)\n        {\n            if (textures == null || textures.Length == 0 || textures.Count(t => t != null) == 0)\n            {\n                m_Textures.Clear();\n                return;\n            }\n            else if (textures.Length > maxLayerCount || textures.Length < minLayerCount)\n            {\n                throw new InvalidOperationException($\"Attempting to assign an incorrect amount of layers to an PlatformIcon, trying to assign {textures.Length} textures while the Icon requires atleast {minLayerCount} but no more than {maxLayerCount} layers\");\n            }\n\n            m_Textures = textures.ToList();\n        }\n\n        internal int GetValidLayerCount()\n        {\n            var validLayerCount = m_Textures.Count(t => t != null);\n            var previewTexturesCount = GetPreviewTextures().Count(t => t != null);\n\n            return Math.Max(previewTexturesCount, validLayerCount);\n        }\n\n        public override string ToString() { return string.Format(\"({0}x{1}) {2}\", width, height, description); }\n    }\n\n    public class PlatformIconKind\n    {\n        internal static readonly PlatformIconKind Any = new PlatformIconKind(-1, \"Any\", \"\", NamedBuildTarget.Unknown);\n\n        internal int kind { get; private set; }\n        internal string platform { get; private set; }\n        internal string[] customLayerLabels { get; private set; }\n        internal string description { get; set; }\n        private string kindString { get; set; }\n\n        internal PlatformIconKind(int kind, string kindString, string description, NamedBuildTarget platform, string[] customLayerLabels = null)\n        {\n            this.kind = kind;\n            this.platform = platform.TargetName;\n            this.kindString = kindString;\n            this.customLayerLabels = customLayerLabels;\n            this.description = description;\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (obj == null || GetType() != obj.GetType())\n                return false;\n\n            return kind == ((PlatformIconKind)obj).kind && platform == ((PlatformIconKind)obj).platform;\n        }\n\n        public override int GetHashCode()\n        {\n            return kind.GetHashCode();\n        }\n\n        public override string ToString() { return kindString; }\n    }\n\n    [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n    public partial class PlayerSettings : UnityEngine.Object\n    {\n        // TODO: once we move the icon stuff to a common editor plugin, move it there as well\n        internal static void InitIconsStructs(NamedBuildTarget buildTarget)\n        {\n            // This forces icon structures to be initialized in PlayerSettings on Editor start if needed\n            // If we don't do this, the following might happen:\n            // * Create new project\n            // * ProjectSettings.asset will have its m_BuildTargetPlatformIcons structure empty\n            // * But once you build to Android/iOS/tvOS or any platform which uses IIconPlatformProperties, it will initialize m_BuildTargetPlatformIcons\n            // * Causing ProjectSettings.asset to change after you clicked build\n            // * This is bad for incremental builds, at least for the 2nd/sequential build, it will see that ProjectSettings.asset has changed and will start rebuilding resources\n            if (!BuildTargetDiscovery.TryGetBuildTarget(BuildPipeline.GetBuildTargetByName(buildTarget.TargetName), out var iBuildTarget))\n                return;\n            var requiredIcons = iBuildTarget.IconPlatformProperties?.GetRequiredPlatformIcons();\n            if (requiredIcons == null)\n                return;\n\n            foreach(var icon in requiredIcons.Keys)\n            {\n                // Init the internal structures with empty icons\n                GetPlatformIcons(buildTarget, icon);\n            }\n        }\n\n        internal static PlatformIcon[] GetPlatformIconsFromStruct(PlatformIcon[] icons, PlatformIconKind kind, PlatformIconStruct[] serializedIcons)\n        {\n            foreach (var icon in icons)\n            {\n                foreach (var serializedIcon in serializedIcons)\n                {\n                    var requiredKind = kind.Equals(PlatformIconKind.Any) ? (int)serializedIcon.Kind : kind.kind;\n                    if (icon.kind.kind != requiredKind || icon.iconSubKind != serializedIcon.SubKind) continue;\n                    if (icon.width != serializedIcon.Width || icon.height != serializedIcon.Height) continue;\n                    var serializedTextures = serializedIcon.Textures.Take(icon.maxLayerCount).ToArray();\n                    var textures = new Texture2D[serializedTextures.Length > icon.minLayerCount\n                                                 ? serializedTextures.Length\n                                                 : icon.minLayerCount];\n\n                    for (int i = 0; i < serializedTextures.Length; i++)\n                        textures[i] = serializedTextures[i];\n\n                    icon.SetTextures(textures);\n                    break;\n                }\n            }\n\n            return icons;\n        }\n\n        [Obsolete(\"Use GetPlatformIcons(NamedBuildTarget , PlatformIconKind) instead\")]\n        public static PlatformIcon[] GetPlatformIcons(BuildTargetGroup platform, PlatformIconKind kind) =>\n            GetPlatformIcons(NamedBuildTarget.FromBuildTargetGroup(platform), kind);\n\n        // Loops through 'requiredIconSlots' and fills it with icons that are already serialized.\n        public static PlatformIcon[] GetPlatformIcons(NamedBuildTarget buildTarget, PlatformIconKind kind)\n        {\n            if (!BuildTargetDiscovery.TryGetBuildTarget(BuildPipeline.GetBuildTargetByName(buildTarget.TargetName), out var iBuildTarget))\n                return Array.Empty<PlatformIcon>();\n            var requiredIcons = iBuildTarget.IconPlatformProperties?.GetRequiredPlatformIcons();\n            if (requiredIcons == null)\n                return Array.Empty<PlatformIcon>();\n\n            var icons = PlatformIcon.GetRequiredPlatformIconsByType(kind, requiredIcons);\n            var serializedIcons = GetPlatformIconsInternal(buildTarget.TargetName, kind.kind);\n\n            if (serializedIcons.Length <= 0)\n            {\n                ImportLegacyIcons(buildTarget.TargetName, kind, icons);\n                SetPlatformIcons(buildTarget, kind, icons);\n\n                foreach (var icon in icons)\n                    if (icon.IsEmpty())\n                        icon.SetTextures(null);\n            }\n            else\n            {\n                icons = GetPlatformIconsFromStruct(icons, kind, serializedIcons);\n            }\n            return icons;\n        }\n\n        [Obsolete(\"Use SetPlatformIcons(NamedBuildTarget , PlatformIconKind) instead\")]\n        public static void SetPlatformIcons(BuildTargetGroup platform, PlatformIconKind kind, PlatformIcon[] icons) =>\n            SetPlatformIcons(NamedBuildTarget.FromBuildTargetGroup(platform), kind, icons);\n\n        public static void SetPlatformIcons(NamedBuildTarget buildTarget, PlatformIconKind kind, PlatformIcon[] icons)\n        {\n            if (!BuildTargetDiscovery.TryGetBuildTarget(BuildPipeline.GetBuildTargetByName(buildTarget.TargetName), out var iBuildTarget))\n                return;\n\n            var requiredIcons = iBuildTarget.IconPlatformProperties?.GetRequiredPlatformIcons();\n            if (requiredIcons == null)\n                return;\n\n            var requiredIconCount = PlatformIcon.GetRequiredPlatformIconsByType(kind, requiredIcons).Length;\n\n            PlatformIconStruct[] iconStructs;\n            if (icons == null)\n                iconStructs = new PlatformIconStruct[0];\n            else if (requiredIconCount != icons.Length)\n            {\n                throw new InvalidOperationException($\"Attempting to set an incorrect number of icons for {buildTarget.TargetName} {kind} kind, it requires {requiredIconCount} icons but trying to assign {icons.Length}.\");\n            }\n            else\n            {\n                iconStructs = icons.Select(\n                    i => i.GetPlatformIconStruct()\n                    ).ToArray();\n            }\n\n            SetPlatformIconsInternal(buildTarget.TargetName, iconStructs, kind.kind);\n        }\n\n        [Obsolete(\"Use GetSupportedIconKinds(NamedBuildTarget) instead\")]\n        public static PlatformIconKind[] GetSupportedIconKindsForPlatform(BuildTargetGroup platform) =>\n            GetSupportedIconKinds(NamedBuildTarget.FromBuildTargetGroup(platform));\n\n        public static PlatformIconKind[] GetSupportedIconKinds(NamedBuildTarget buildTarget)\n        {\n            if (BuildTargetDiscovery.TryGetBuildTarget(BuildPipeline.GetBuildTargetByName(buildTarget.TargetName), out var iBuildTarget))\n            {\n                var requiredIcons = iBuildTarget.IconPlatformProperties?.GetRequiredPlatformIcons();\n                if (requiredIcons != null)\n                    return requiredIcons.Keys.ToArray();\n            }\n            return new PlatformIconKind[] { };\n        }\n\n        internal static int GetNonEmptyPlatformIconCount(PlatformIcon[] icons)\n        {\n            return icons.Count(i => !i.IsEmpty());\n        }\n\n        internal static int GetValidPlatformIconCount(PlatformIcon[] icons)\n        {\n            return icons.Count(\n                i => i.GetTextures().Count(t => t != null) >= i.minLayerCount && i.layerCount <= i.maxLayerCount\n            );\n        }\n\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        [NativeMethod(Name = \"SetIconsForPlatform\")]\n        extern internal static void SetPlatformIconsInternal(string platform, PlatformIconStruct[] icons, int kind);\n\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        extern internal static LegacyBuildTargetIcons[] SetPlatformIconsForTargetIcons(string platform, Texture2D[] icons, IconKind kind, LegacyBuildTargetIcons[] allIcons);\n\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        extern internal static BuildTargetIcons[] SetIconsForPlatformForTargetIcons(string platform, PlatformIconStruct[] icons, int kind, BuildTargetIcons[] allIcons);\n\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        [NativeMethod(Name = \"GetIconsForPlatform\")]\n        extern internal static PlatformIconStruct[] GetPlatformIconsInternal(string platform, int kind);\n\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        extern internal static Texture2D[] GetPlatformIconsForTargetIcons(string platform, IconKind kind, LegacyBuildTargetIcons[] allIcons);\n\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        [NativeMethod(Name = \"GetIconsForPlatformFromTargetIcons\")]\n        extern internal static PlatformIconStruct[] GetPlatformIconsFromTargetIcons(string platform, int kind, BuildTargetIcons[] allIcons);\n\n        extern internal static Texture2D GetPlatformIconForSize(string platform, int width, int height, IconKind kind = IconKind.Application);\n\n        // Get the texture that will be used as the display icon at a specified size for the specified platform.\n        internal static extern Texture2D GetPlatformIconForSizeForTargetIcons(string platform, int width, int height, IconKind kind, LegacyBuildTargetIcons[] allIcons);\n\n        // Get the texture that will be used as the display icon at a specified size for the specified platform.\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        extern internal static Texture2D GetPlatformIconAtSize(string platform, int width, int height, int kind, string subKind = \"\", int layer = 0);\n\n        // Get the texture that will be used as the display icon at a specified size for the specified platform.\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        extern internal static Texture2D GetPlatformIconAtSizeForTargetIcons(string platform, int width, int height, BuildTargetIcons[] allIcons, int kind, string subKind = \"\", int layer = 0);\n\n        internal static void ClearSetIconsForPlatform(NamedBuildTarget buildTarget)\n        {\n            SetPlatformIcons(buildTarget, PlatformIconKind.Any, null);\n        }\n\n        // Old API methods, will be made obsolete when the new API is implemented for all platforms,\n        // currently it functions as a wrapper for the new API for all platforms that support it (iOS, Android & tvOS).\n        [Obsolete(\"Use SetIcons(NamedBuildTarget, Texture2D[], IconKind) instead\")]\n        public static void SetIconsForTargetGroup(BuildTargetGroup platform, Texture2D[] icons, IconKind kind) =>\n            SetIcons(NamedBuildTarget.FromBuildTargetGroup(platform), icons, kind);\n\n        public static void SetIcons(NamedBuildTarget buildTarget, Texture2D[] icons, IconKind kind)\n        {\n            if (BuildTargetDiscovery.TryGetBuildTarget(BuildPipeline.GetBuildTargetByName(buildTarget.TargetName), out var iBuildTarget) &&\n                iBuildTarget.IconPlatformProperties != null)\n            {\n                var platformIconKind = iBuildTarget.IconPlatformProperties.GetPlatformIconKindFromEnumValue(kind);\n                if (platformIconKind != null)\n                {\n                    PlatformIcon[] platformIcons = GetPlatformIcons(buildTarget, platformIconKind);\n\n                    for (var i = 0; i < icons.Length; i++)\n                        platformIcons[i].SetTexture(icons[i], 0);\n\n                    SetPlatformIcons(buildTarget, platformIconKind, platformIcons);\n                }\n            }\n            else\n                SetIconsForPlatform(buildTarget.TargetName, icons, kind);\n        }\n\n        [Obsolete(\"Use SetIcons(NamedBuildTarget, Texture2D[], IconKind) instead\")]\n        // Assign a list of icons for the specified platform.\n        public static void SetIconsForTargetGroup(BuildTargetGroup platform, Texture2D[] icons) =>\n            SetIcons(NamedBuildTarget.FromBuildTargetGroup(platform), icons, IconKind.Any);\n\n        // Returns the list of assigned icons for the specified platform of a specific kind.\n        [Obsolete(\"Use GetIcons(NamedBuildTarget, IconKind) instead\")]\n        public static Texture2D[] GetIconsForTargetGroup(BuildTargetGroup platform, IconKind kind) =>\n            GetIcons(NamedBuildTarget.FromBuildTargetGroup(platform), kind);\n\n        public static Texture2D[] GetIcons(NamedBuildTarget buildTarget, IconKind kind)\n        {\n            if (BuildTargetDiscovery.TryGetBuildTarget(BuildPipeline.GetBuildTargetByName(buildTarget.TargetName), out var iBuildTarget))\n            {\n                var platformIconKind = iBuildTarget.IconPlatformProperties?.GetPlatformIconKindFromEnumValue(kind);\n                return platformIconKind == null ?\n                    GetIconsForPlatform(iBuildTarget.TargetName, kind) :\n                    GetPlatformIcons(buildTarget, platformIconKind).Select(t => t.GetTexture(0)).ToArray();\n            }\n            return PlayerSettings.GetIconsForPlatform(buildTarget.TargetName, kind);\n        }\n\n        internal static void ImportLegacyIcons(string platform, PlatformIconKind kind, PlatformIcon[] platformIcons)\n        {\n            if (!Enum.IsDefined(typeof(IconKind), kind.kind))\n                return;\n\n            IconKind iconKind = (IconKind)kind.kind;\n\n            Texture2D[] legacyIcons = GetIconsForPlatform(platform, iconKind);\n            int[] legacyIconWidths = GetIconWidthsForPlatform(platform, iconKind);\n            int[] legacyIconHeights  = GetIconHeightsForPlatform(platform, iconKind);\n\n            for (var i = 0; i < legacyIcons.Length; i++)\n            {\n                foreach (var icon in platformIcons)\n                {\n                    if (icon.width == legacyIconWidths[i] && icon.height == legacyIconHeights[i])\n                    {\n                        icon.SetTextures(legacyIcons[i]);\n                    }\n                }\n            }\n        }\n\n        internal static void ImportLegacyIcons(BuildTargetGroup platform, PlatformIconKind kind, PlatformIcon[] platformIcons)\n        {\n            ImportLegacyIcons(GetPlatformName(platform), kind, platformIcons);\n        }\n\n        // Returns the list of assigned icons for the specified platform.\n        [Obsolete(\"Use GetIcons(NamedBuildTarget, IconKind) instead\")]\n        public static Texture2D[] GetIconsForTargetGroup(BuildTargetGroup platform) =>\n            GetIcons(NamedBuildTarget.FromBuildTargetGroup(platform), IconKind.Any);\n\n        // Returns a list of icon sizes for the specified platform of a specific kind.\n        [Obsolete(\"Use GetIconSizes(NamedBuildTarget, IconKind) instead\")]\n        public static int[] GetIconSizesForTargetGroup(BuildTargetGroup platform, IconKind kind) =>\n            GetIconSizes(NamedBuildTarget.FromBuildTargetGroup(platform), kind);\n\n        public static int[] GetIconSizes(NamedBuildTarget buildTarget, IconKind kind)\n        {\n            if (BuildTargetDiscovery.TryGetBuildTarget(BuildPipeline.GetBuildTargetByName(buildTarget.TargetName), out var iBuildTarget))\n            {\n                var platformIconKind = iBuildTarget.IconPlatformProperties?.GetPlatformIconKindFromEnumValue(kind);\n                return platformIconKind == null ?\n                    GetIconWidthsForPlatform(iBuildTarget.TargetName, kind) :\n                    GetPlatformIcons(buildTarget, platformIconKind).Select(s => s.width).ToArray();\n            }\n            return GetIconWidthsForPlatform(buildTarget.TargetName, kind);\n        }\n\n        // Returns a list of icon sizes for the specified platform.\n        [Obsolete(\"Use GetIconSizes(NamedBuildTarget) instead\")]\n        public static int[] GetIconSizesForTargetGroup(BuildTargetGroup platform) =>\n            GetIconSizes(NamedBuildTarget.FromBuildTargetGroup(platform), IconKind.Any);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlatformSupport/ProvisioningProfile.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Text.RegularExpressions;\nusing System.IO;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace UnityEditor.PlatformSupport\n{\n    internal class iOSEditorPrefKeys\n    {\n        public readonly static string kDefaultiOSAutomaticallySignBuild     = \"DefaultiOSAutomaticallySignBuild\";\n        public readonly static string kDefaultiOSAutomaticSignTeamId        = \"DefaultiOSAutomaticSignTeamId\";\n\n        public readonly static string kDefaultiOSProvisioningProfileUUID    = \"DefaultiOSProvisioningProfileUUID\";\n        public readonly static string kDefaulttvOSProvisioningProfileUUID   = \"DefaulttvOSProvisioningProfileUUID\";\n        public readonly static string kDefaultVisionOSProvisioningProfileUUID   = \"DefaultVisionOSProvisioningProfileUUID\";\n        public readonly static string kDefaultiOSProvisioningProfileType    = \"kDefaultiOSProvisioningProfileType\";\n        public readonly static string kDefaulttvOSProvisioningProfileType   = \"kDefaulttvOSProvisioningProfileType\";\n        public readonly static string kDefaultVisionOSProvisioningProfileType   = \"kDefaultVisionOSProvisioningProfileType\";\n    }\n\n    internal class ProvisioningProfile\n    {\n        private string m_UUID = string.Empty;\n        private ProvisioningProfileType m_Type = ProvisioningProfileType.Development;\n\n        public string UUID { get { return m_UUID; } set { m_UUID = value; } }\n        public ProvisioningProfileType type { get { return m_Type; } set { m_Type = value; } }\n\n        // regex patterns used for finding specific parts of data from a provisioning profile\n        static readonly string s_PatternUUID   = \"<key>UUID<\\\\/key>[\\n\\t]*<string>((\\\\w*\\\\-?){5})\";\n        private static readonly string s_PatternDeveloperCertificates =\n            \"<key>DeveloperCertificates<\\\\/key>[\\n\\t]*<array>[\\n\\t]*<data>([\\\\w\\\\/+=]+)<\\\\/data>\";\n        static readonly string s_DistributionPattern = \"iPhone Distribution: \";\n\n        internal static ProvisioningProfile ParseProvisioningProfileAtPath(string pathToFile)\n        {\n            ProvisioningProfile profile = new ProvisioningProfile();\n            parseFile(pathToFile, profile);\n            return profile;\n        }\n\n        private ProvisioningProfile() {}\n\n        public ProvisioningProfile(string UUID, ProvisioningProfileType type)\n        {\n            m_UUID = UUID;\n            m_Type = type;\n        }\n\n        internal static void parseFile(string filePath, ProvisioningProfile profile)\n        {\n            var provisioningFileContents = File.ReadAllText(filePath);\n            Match matchUUID = Regex.Match(provisioningFileContents, s_PatternUUID, RegexOptions.Singleline);\n            if (matchUUID.Success)\n            {\n                profile.UUID = matchUUID.Groups[1].Value;\n            }\n\n            Match matchCertificate = Regex.Match(provisioningFileContents, s_PatternDeveloperCertificates,\n                RegexOptions.Singleline);\n            if (matchCertificate.Success)\n            {\n                string value = matchCertificate.Groups[1].Value;\n                string decodedCertificate = Encoding.UTF8.GetString(Convert.FromBase64String(value));\n\n                if (decodedCertificate.Contains(s_DistributionPattern))\n                {\n                    profile.type = ProvisioningProfileType.Distribution;\n                }\n                else\n                {\n                    profile.type = ProvisioningProfileType.Development;\n                }\n            }\n        }\n\n        internal static readonly string[] DefaultProvisioningProfileSearchPaths = new string[]\n        {\n            \"{Home}/Library/MobileDevice/Provisioning Profiles\",\n        };\n\n        internal static ProvisioningProfile FindLocalProfileByUUID(string UUID, string[] searchPaths = null)\n        {\n            var localProfilePath = LoadLocalProfiles(searchPaths).FirstOrDefault(p => p.Contains(UUID));\n\n            if (localProfilePath != null && File.Exists(localProfilePath))\n            {\n                return ParseProvisioningProfileAtPath(localProfilePath);\n            }\n            return null;\n        }\n\n        internal static List<string> LoadLocalProfiles(string[] searchPaths = null)\n        {\n            if (searchPaths == null)\n                searchPaths = DefaultProvisioningProfileSearchPaths;\n\n            List<string> localProfiles = new List<string>();\n            foreach (var path in searchPaths)\n            {\n                var profilesFolder =\n                    path.Replace(\"{Home}\", Environment.GetFolderPath(Environment.SpecialFolder.Personal));\n\n                if (!Directory.Exists(profilesFolder))\n                    continue;\n\n                foreach (var file in Directory.GetFiles(profilesFolder))\n                {\n                    if (Path.GetExtension(file) == \".mobileprovision\")\n                    {\n                        localProfiles.Add(file);\n                    }\n                }\n            }\n            return localProfiles;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlatformSupport/ProvisioningProfileGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditor.Modules;\nusing UnityEditorInternal;\n\nnamespace UnityEditor.PlatformSupport\n{\n    internal class ProvisioningProfileGUI\n    {\n        internal delegate void ProvisioningProfileChangedDelegate(ProvisioningProfile profile);\n\n        internal static void ShowProvisioningProfileUIWithProperty(GUIContent titleWithToolTip, ProvisioningProfile profile, SerializedProperty profileIDProp, SerializedProperty profileTypeProp)\n        {\n            GUILayout.BeginHorizontal();\n            GUILayout.Label(titleWithToolTip, EditorStyles.label);\n\n            Rect controlRect = EditorGUILayout.GetControlRect(false, 0);\n            GUIContent labelID = EditorGUIUtility.TrTextContent(\"Profile ID:\");\n            EditorGUI.BeginProperty(controlRect, labelID, profileIDProp);\n\n            if (GUILayout.Button(\"Browse\", EditorStyles.miniButton))\n            {\n                ProvisioningProfile provisioningProfile = Browse(\"\");\n                if (provisioningProfile != null && !string.IsNullOrEmpty(provisioningProfile.UUID))\n                {\n                    profile = provisioningProfile;\n                    profileIDProp.stringValue = profile.UUID;\n                    profileTypeProp.intValue = (int)profile.type;\n                    profileIDProp.serializedObject.ApplyModifiedProperties();\n                    profileTypeProp.serializedObject.ApplyModifiedProperties();\n                    GUI.FocusControl(\"\");\n                }\n                GUIUtility.ExitGUI();\n            }\n\n            EditorGUI.EndProperty();\n            GUILayout.EndHorizontal();\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.indentLevel++;\n\n            EditorGUI.BeginProperty(controlRect, labelID, profileIDProp);\n            profile.UUID = EditorGUILayout.TextField(labelID, profile.UUID);\n            EditorGUI.EndProperty();\n\n            GUIContent labelType = EditorGUIUtility.TrTextContent(\"Profile Type:\");\n\n            EditorGUI.BeginProperty(controlRect, labelType, profileTypeProp);\n            profile.type = (ProvisioningProfileType)EditorGUILayout.EnumPopup(labelType, profile.type);\n            EditorGUI.EndProperty();\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                profileIDProp.stringValue = profile.UUID;\n                profileTypeProp.intValue = (int)profile.type;\n            }\n\n            EditorGUI.indentLevel--;\n        }\n\n        internal static void ShowProvisioningProfileUIWithCallback(GUIContent titleWithToolTip, ProvisioningProfile profile, ProvisioningProfileChangedDelegate callback)\n        {\n            GUILayout.BeginHorizontal();\n            GUILayout.Label(titleWithToolTip, EditorStyles.label);\n\n            if (GUILayout.Button(\"Browse\", EditorStyles.miniButton))\n            {\n                ProvisioningProfile provisioningProfile = Browse(\"\");\n                if (provisioningProfile != null && !string.IsNullOrEmpty(provisioningProfile.UUID))\n                {\n                    profile = provisioningProfile;\n                    callback(profile);\n\n                    GUI.FocusControl(\"\");\n                }\n                GUIUtility.ExitGUI();\n            }\n\n            GUILayout.EndHorizontal();\n\n            EditorGUI.BeginChangeCheck();\n            EditorGUI.indentLevel++;\n\n            GUIContent labelID = EditorGUIUtility.TrTextContent(\"Profile ID:\");\n            GUIContent labelType = EditorGUIUtility.TrTextContent(\"Profile Type:\");\n\n            profile.UUID = EditorGUILayout.TextField(labelID, profile.UUID);\n            profile.type = (ProvisioningProfileType)EditorGUILayout.EnumPopup(labelType, profile.type);\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                callback(profile);\n            }\n\n            EditorGUI.indentLevel--;\n        }\n\n        internal static ProvisioningProfile Browse(string path)\n        {\n            var msg = \"Select the Provising Profile used for Manual Signing\";\n\n            var defaultFolder = path;\n\n            if (InternalEditorUtility.inBatchMode)\n            {\n                return null;\n            }\n\n            ProvisioningProfile provisioningProfile = null;\n            do\n            {\n                path = EditorUtility.OpenFilePanel(msg, defaultFolder, \"mobileprovision\");\n\n                // user pressed cancel?\n                if (path.Length == 0)\n                    return null;\n            }\n            while (!GetProvisioningProfileId(path, out provisioningProfile));\n\n            return provisioningProfile;\n        }\n\n        internal static bool GetProvisioningProfileId(string filePath, out ProvisioningProfile provisioningProfile)\n        {\n            ProvisioningProfile profile = ProvisioningProfile.ParseProvisioningProfileAtPath(filePath);\n            provisioningProfile = profile;\n            return profile.UUID != null;\n        }\n\n        internal static void ShowUIWithDefaults(string provisioningPrefUUIDKey, string provisioningPrefTypeKey, SerializedProperty enableAutomaticSigningProp, GUIContent automaticSigningGUI, SerializedProperty manualSigningIDProp, SerializedProperty manualSigningProfileTypeProp, GUIContent manualSigningProfileGUI, SerializedProperty appleDevIDProp, GUIContent teamIDGUIContent)\n        {\n            string oldTeamID = GetDefaultStringValue(appleDevIDProp, iOSEditorPrefKeys.kDefaultiOSAutomaticSignTeamId);\n            string newTeamID = null;\n            Rect controlRect = EditorGUILayout.GetControlRect(true, 0);\n            EditorGUI.BeginProperty(controlRect, teamIDGUIContent, appleDevIDProp);\n            EditorGUI.BeginChangeCheck();\n            newTeamID = EditorGUILayout.TextField(teamIDGUIContent, oldTeamID);\n            if (EditorGUI.EndChangeCheck())\n            {\n                appleDevIDProp.stringValue = newTeamID;\n            }\n            EditorGUI.EndProperty();\n\n            int signingValue = GetDefaultAutomaticSigningValue(enableAutomaticSigningProp, iOSEditorPrefKeys.kDefaultiOSAutomaticallySignBuild);\n            bool oldValue = GetBoolForAutomaticSigningValue(signingValue);\n            Rect toggleRect = EditorGUILayout.GetControlRect(true, 0);\n            EditorGUI.BeginProperty(toggleRect, automaticSigningGUI, enableAutomaticSigningProp);\n            bool newValue = EditorGUILayout.Toggle(automaticSigningGUI, oldValue);\n\n            if (newValue != oldValue)\n            {\n                enableAutomaticSigningProp.intValue = GetIntValueForAutomaticSigningBool(newValue);\n            }\n            EditorGUI.EndProperty();\n\n            if (!newValue)\n            {\n                ShowProvisioningProfileUIWithDefaults(provisioningPrefUUIDKey, provisioningPrefTypeKey, manualSigningIDProp, manualSigningProfileTypeProp, manualSigningProfileGUI);\n            }\n        }\n\n        private static void ShowProvisioningProfileUIWithDefaults(string defaultPreferenceKey, string provisioningPrefTypeKey, SerializedProperty uuidProp, SerializedProperty typeProp, GUIContent title)\n        {\n            string uuidVal = uuidProp.stringValue;\n            ProvisioningProfileType typeVal = (ProvisioningProfileType)typeProp.intValue;\n            if (string.IsNullOrEmpty(uuidVal))\n            {\n                uuidVal = EditorPrefs.GetString(defaultPreferenceKey);\n                typeVal = string.IsNullOrEmpty(uuidVal) ? typeVal : (ProvisioningProfileType)EditorPrefs.GetInt(provisioningPrefTypeKey);\n            }\n\n            ProvisioningProfileGUI.ShowProvisioningProfileUIWithProperty(title, new ProvisioningProfile(uuidVal, typeVal), uuidProp, typeProp);\n        }\n\n        private static bool GetBoolForAutomaticSigningValue(int signingValue)\n        {\n            return signingValue == (int)iOSAutomaticallySignValue.AutomaticallySignValueTrue;\n        }\n\n        private static int GetIntValueForAutomaticSigningBool(bool automaticallySign)\n        {\n            return (int)(automaticallySign ? iOSAutomaticallySignValue.AutomaticallySignValueTrue : iOSAutomaticallySignValue.AutomaticallySignValueFalse);\n        }\n\n        private static int GetDefaultAutomaticSigningValue(SerializedProperty prop, string editorPropKey)\n        {\n            int val = prop.intValue;\n            if (val == (int)iOSAutomaticallySignValue.AutomaticallySignValueNotSet)\n            {\n                val = (int)(EditorPrefs.GetBool(editorPropKey) ? iOSAutomaticallySignValue.AutomaticallySignValueTrue : iOSAutomaticallySignValue.AutomaticallySignValueFalse);\n            }\n            return val;\n        }\n\n        private static string GetDefaultStringValue(SerializedProperty prop, string editorPrefKey)\n        {\n            string val = prop.stringValue;\n            if (string.IsNullOrEmpty(val))\n            {\n                val = EditorPrefs.GetString(editorPrefKey, \"\");\n            }\n            return val;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlatformSupport/ReorderableTextureList.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\n\nnamespace UnityEditor.PlatformSupport\n{\n    class ReorderableIconLayerList\n    {\n        UnityEditorInternal.ReorderableList m_List;\n\n        public delegate void ChangedCallbackDelegate(ReorderableIconLayerList list);\n\n        // Used to notify about element order and content changes. The textures list\n        // must not be changed during the execution of the callback.\n        public ChangedCallbackDelegate onChangedCallback = null;\n\n        public List<Texture2D> textures\n        {\n            get { return (List<Texture2D>)m_List.list; }\n            set { m_List.list = value; }\n        }\n\n        public List<Texture2D> previewTextures { get; set; }\n\n        public string headerString = \"\";\n\n        const int kSlotSize = 86;\n        const int kIconSpacing = 6;\n\n        public int m_ImageWidth = 20;\n        public int m_ImageHeight = 20;\n        public int minItems = 1;\n        public int maxItems = 5;\n\n\n        public void SetElementLabels(params string[] labels)\n        {\n            m_useCustomLayerLabel = true;\n            m_layerLabels = labels;\n        }\n\n        private bool m_useCustomLayerLabel;\n        private string[] m_layerLabels;\n\n        string GetElementLabel(int index)\n        {\n            if (m_useCustomLayerLabel)\n                return m_layerLabels[index];\n\n            string namestr = LocalizationDatabase.GetLocalizedString(\"Layer {0}\");\n            string label = String.Format(namestr, index);\n\n            return label;\n        }\n\n        public ReorderableIconLayerList(bool draggable = true, bool showControls = true)\n        {\n            m_List = new UnityEditorInternal.ReorderableList(new List<Texture2D>(), typeof(Texture2D), draggable, true, showControls, showControls);\n            m_List.onAddCallback = OnAdd;\n            m_List.onRemoveCallback = OnRemove;\n            m_List.onReorderCallback = OnChange;\n            m_List.drawElementCallback = OnElementDraw;\n            m_List.drawHeaderCallback = OnHeaderDraw;\n            m_List.onCanAddCallback = OnCanAdd;\n            m_List.onCanRemoveCallback = OnCanRemove;\n\n            UpdateElementHeight();\n        }\n\n        public void SetImageSize(int width, int height)\n        {\n            m_ImageWidth = width;\n            m_ImageHeight = height;\n            UpdateElementHeight();\n        }\n\n        void UpdateElementHeight()\n        {\n            m_List.elementHeight = kSlotSize * ((float)m_ImageHeight / m_ImageWidth);\n        }\n\n        bool OnCanAdd(UnityEditorInternal.ReorderableList list)\n        {\n            return list.count < maxItems;\n        }\n\n        bool OnCanRemove(UnityEditorInternal.ReorderableList list)\n        {\n            if (list.count <= minItems)\n                return false;\n            return true;\n        }\n\n        void OnAdd(UnityEditorInternal.ReorderableList list)\n        {\n            textures.Add(null);\n            m_List.index = textures.Count - 1;\n            OnChange(list);\n        }\n\n        void OnRemove(UnityEditorInternal.ReorderableList list)\n        {\n            textures.RemoveAt(list.index);\n            list.index = 0;\n            OnChange(list);\n        }\n\n        void OnChange(UnityEditorInternal.ReorderableList list)\n        {\n            if (onChangedCallback != null)\n                onChangedCallback(this);\n        }\n\n        void OnElementDraw(Rect rect, int index, bool isActive, bool isFocused)\n        {\n            string label = GetElementLabel(index);\n\n            float width = Mathf.Min(rect.width, EditorGUIUtility.labelWidth + 4 + kSlotSize + kIconSpacing);\n            GUI.Label(new Rect(rect.x, rect.y, width - kSlotSize - kIconSpacing, 20), label);\n\n            // Texture slot\n            int slotWidth = kSlotSize;\n            int slotHeight = (int)((float)m_ImageHeight / m_ImageWidth * kSlotSize);  // take into account the aspect ratio\n            var textureRect = new Rect(rect.x + rect.width  - slotWidth - slotWidth - kIconSpacing, rect.y, slotWidth, slotHeight);\n\n            EditorGUI.BeginChangeCheck();\n            textures[index] = (Texture2D)EditorGUI.ObjectField(textureRect, textures[index], typeof(Texture2D), false);\n            if (EditorGUI.EndChangeCheck())\n                OnChange(m_List);\n\n            // Preview\n            Rect previewRect = new Rect(rect.x + rect.width - slotWidth, rect.y, slotWidth, slotHeight);\n\n            GUI.Box(previewRect, \"\");\n\n            Texture2D closestIcon = previewTextures[index];\n\n            if (closestIcon != null)\n                GUI.DrawTexture(PlatformIconField.GetContentRect(previewRect, 1, 1), previewTextures[index]);\n        }\n\n        void OnHeaderDraw(Rect rect)\n        {\n            GUI.Label(rect, LocalizationDatabase.GetLocalizedString(headerString), EditorStyles.label);\n        }\n\n        public void DoLayoutList()\n        {\n            m_List.DoLayoutList();\n        }\n    }\n} // namespace UnityEditor.AppleTV\n"
  },
  {
    "path": "Editor/Mono/PlayModeView/PlayModeAnalytics.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Analytics;\n\nnamespace UnityEditor\n{\n\n    internal class PlayModeAnalytics\n    {\n        internal class BaseData : IAnalytic.IData\n        {\n            [SerializeField] public string PlayModeEvent;\n        }\n\n        internal class SimulatorEnableData : BaseData\n        {\n            [SerializeField] public string[] SimulatorPlugins;\n        }\n\n        internal class SimulatorDeviceData : BaseData\n        {\n            [SerializeField] public string DeviceName;\n        }\n\n        [AnalyticInfo(eventName: \"playModeUsage\", vendorKey: \"unity.playModeUsage\")]\n        internal class Analytic : IAnalytic\n        {\n            public Analytic(BaseData data)\n            {\n                m_data = data;\n            }\n\n            public bool TryGatherData(out IAnalytic.IData data, out Exception error)\n            {\n                error = null;\n                data = m_data;\n                return data != null;\n            }\n\n            private BaseData m_data = null;\n        }\n\n        public static void GameViewEnableEvent()\n        {\n            SendPlayModeEvent(new BaseData() { PlayModeEvent = \"Game OnEnable\" });\n        }\n\n        public static void GameViewDisableEvent()\n        {\n            SendPlayModeEvent(new BaseData() { PlayModeEvent = \"Game OnDisable\" });\n        }\n\n        public static void SimulatorEnableEvent(string[] pluginNames)\n        {\n            SendPlayModeEvent(new SimulatorEnableData() { PlayModeEvent = \"Simulator OnEnable\", SimulatorPlugins = pluginNames });\n        }\n\n        public static void SimulatorDisableEvent()\n        {\n            SendPlayModeEvent(new BaseData() { PlayModeEvent = \"Simulator OnDisable\" });\n        }\n\n        public static void SimulatorSelectDeviceEvent(string deviceName)\n        {\n            SendPlayModeEvent(new SimulatorDeviceData() { PlayModeEvent = \"Simulator Device\", DeviceName = deviceName });\n        }\n\n        private static void SendPlayModeEvent(BaseData data)\n        {\n            EditorAnalytics.SendAnalytic(new PlayModeAnalytics.Analytic(data));\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayModeView/PlayModeView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing Unity.Collections;\nusing UnityEditor.Modules;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Experimental.Rendering;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    internal static class PreviewEditorWindow\n    {\n        internal static void RepaintAll()\n        {\n            PlayModeView.RepaintAll();\n        }\n    }\n\n    [Serializable]\n    internal abstract class PlayModeView : EditorWindow\n    {\n        static List<PlayModeView> s_PlayModeViews = new List<PlayModeView>();\n\n        private static PlayModeView s_LastFocused;\n\n        static PlayModeView s_RenderingView;\n\n        private readonly string m_ViewsCache = Path.GetFullPath(Directory.GetCurrentDirectory() + \"/Library/PlayModeViewStates/\");\n        private static readonly string m_OpenGameViewOnPlay = \"OpenGameViewOnEnteringPlayMode\";\n\n        [SerializeField] private List<string> m_SerializedViewNames = new List<string>();\n        [SerializeField] private List<string> m_SerializedViewValues = new List<string>();\n        [SerializeField] string m_PlayModeViewName;\n        [SerializeField] bool m_ShowGizmos;\n        [SerializeField] int m_TargetDisplay;\n        [SerializeField] Color m_ClearColor;\n        [SerializeField] Vector2 m_TargetSize;\n        [SerializeField] FilterMode m_TextureFilterMode = FilterMode.Point;\n        [SerializeField] HideFlags m_TextureHideFlags = HideFlags.HideAndDontSave;\n        [SerializeField] bool m_RenderIMGUI;\n        [SerializeField] EnterPlayModeBehavior m_EnterPlayModeBehavior;\n        [SerializeField] bool m_UseMipMap;\n\n        protected bool m_SwitchingPlayModeViewType = false;\n\n        private const int k_MaxSupportedDisplays = 8;\n\n        static Dictionary<Type, string> s_AvailableWindowTypes;\n\n        internal Vector2 viewPadding\n        {\n            get;\n            private protected set;\n        }\n\n        internal float viewMouseScale\n        {\n            get;\n            private protected set;\n        }\n\n        protected string playModeViewName\n        {\n            get { return m_PlayModeViewName; }\n            set { m_PlayModeViewName = value; }\n        }\n\n        protected bool showGizmos\n        {\n            get { return m_ShowGizmos; }\n            set\n            {\n                m_ShowGizmos = value;\n            }\n        }\n\n        public  int targetDisplay\n        {\n            get { return m_TargetDisplay; }\n            protected set\n            {\n                if (m_TargetDisplay != value)\n                    SetDisplayViewSize(value, m_TargetSize);\n\n                m_TargetDisplay = value;\n            }\n        }\n\n        protected Color clearColor\n        {\n            get { return m_ClearColor; }\n            set { m_ClearColor = value; }\n        }\n\n        internal Vector2 targetSize\n        {\n            get { return m_TargetSize; }\n            set\n            {\n                if (this == GetMainPlayModeView())\n                    SetMainPlayModeViewSize(value);\n\n                if (m_TargetSize != value)\n                    SetDisplayViewSize(m_TargetDisplay, value);\n\n                m_TargetSize = value;\n            }\n        }\n\n        protected FilterMode textureFilterMode\n        {\n            get { return m_TextureFilterMode; }\n            set { m_TextureFilterMode = value; }\n        }\n\n        protected HideFlags textureHideFlags\n        {\n            get { return m_TextureHideFlags; }\n            set { m_TextureHideFlags = value; }\n        }\n\n        protected bool renderIMGUI\n        {\n            get { return m_RenderIMGUI; }\n            set { m_RenderIMGUI = value; }\n        }\n\n        public EnterPlayModeBehavior enterPlayModeBehavior\n        {\n            get => m_EnterPlayModeBehavior;\n            set => SetPlayModeWindowsStates(value);\n        }\n\n        public const int kFullscreenInvalidIdx = -1;\n        public const int kFullscreenNone = 0;\n\n        [Obsolete(\"PlayModeView.maximizeOnPlay is obsolete. Use PlayModeView.enterPlayModeBehavior instead\")]\n        public bool maximizeOnPlay\n        {\n            get { return m_EnterPlayModeBehavior == EnterPlayModeBehavior.PlayMaximized; }\n            set { m_EnterPlayModeBehavior = value ? EnterPlayModeBehavior.PlayMaximized : EnterPlayModeBehavior.PlayFocused; }\n        }\n\n        protected bool useMipMap\n        {\n            get { return m_UseMipMap; }\n            set { m_UseMipMap = value; }\n        }\n\n        public static bool openWindowOnEnteringPlayMode\n        {\n            get => EditorPrefs.GetBool(m_OpenGameViewOnPlay, true);\n            set\n            {\n                if (EditorPrefs.GetBool(m_OpenGameViewOnPlay) != value)\n                {\n                    EditorPrefs.SetBool(m_OpenGameViewOnPlay, value);\n                    RepaintAll();\n                }\n            }\n        }\n\n        RenderTexture m_TargetTexture;\n        ColorSpace m_CurrentColorSpace = ColorSpace.Uninitialized;\n\n        [FreeFunction]\n        extern protected static bool NeedToPerformRendering();\n\n        protected static bool renderViewCallNeededInOnGUI =>\n            !EditorApplication.isPlaying ||\n            (EditorApplication.isPlaying && NeedToPerformRendering() && !Unsupported.IsEditorPlayerLoopWaiting());\n\n\n        class RenderingView : IDisposable\n        {\n            bool disposed = false;\n\n            public RenderingView(PlayModeView playModeView)\n            {\n                PlayModeView.s_RenderingView = playModeView;\n            }\n\n            public void Dispose()\n            {\n                Dispose(true);\n                GC.SuppressFinalize(this);\n            }\n\n            // Protected implementation of Dispose pattern.\n            protected virtual void Dispose(bool disposing)\n            {\n                if (disposed)\n                    return;\n\n                if (disposing)\n                {\n                    PlayModeView.s_RenderingView = null;\n                }\n\n                disposed = true;\n            }\n        }\n\n        protected PlayModeView()\n        {\n            RegisterWindow();\n            SetDisplayViewSize(m_TargetDisplay, m_TargetSize);\n        }\n\n        protected RenderTexture RenderView(Vector2 mousePosition, bool clearTexture)\n        {\n            using (var renderingView = new RenderingView(this))\n            {\n                SetPlayModeViewSize(targetSize);\n\n                // The target size and GUI rects are communicated to C++ as floats throughout the engine. This means the final size in pixels\n                // of the view will be calculated in C++ so we have to ensure we use the C++ float rounding conventions here. Failure to do so\n                // may result in subtly differences and subtle bugs (like the Screen class thinking something sized 640.5 is 641 pixels but the\n                // RenderTexture being allocated here only being 640 pixels in size with standard C# rounding used by Mathf.RoundToInt.\n                // So we use the c++ AwayFromZero convention when rounding here.\n                int width = (int)Math.Round(targetSize.x, MidpointRounding.AwayFromZero);\n                int height = (int)Math.Round(targetSize.y, MidpointRounding.AwayFromZero);\n\n                var currentTargetDisplay = 0;\n                if (ModuleManager.ShouldShowMultiDisplayOption())\n                {\n                    // Display Targets can have valid targets from 0 to 7.\n                    System.Diagnostics.Debug.Assert(targetDisplay < k_MaxSupportedDisplays, \"Display Target is Out of Range\");\n                    currentTargetDisplay = targetDisplay;\n                }\n\n                bool hdr = (m_Parent != null && m_Parent.actualView == this && m_Parent.hdrActive);\n                ConfigureTargetTexture(width, height, clearTexture, playModeViewName, hdr);\n\n                if (Event.current == null || Event.current.type != EventType.Repaint)\n                    return m_TargetTexture;\n\n                Vector2 oldOffset = GUIUtility.s_EditorScreenPointOffset;\n                GUIUtility.s_EditorScreenPointOffset = Vector2.zero;\n                SavedGUIState oldState = SavedGUIState.Create();\n\n                if (m_TargetTexture.IsCreated())\n                    EditorGUIUtility.RenderPlayModeViewCamerasInternal(m_TargetTexture, currentTargetDisplay, mousePosition, showGizmos, renderIMGUI);\n\n                oldState.ApplyAndForget();\n                GUIUtility.s_EditorScreenPointOffset = oldOffset;\n\n                return m_TargetTexture;\n            }\n        }\n\n        protected static string GetWindowTitle(Type type)\n        {\n            var attributes = type.GetCustomAttributes(typeof(EditorWindowTitleAttribute), true);\n            return attributes.Length > 0 ? ((EditorWindowTitleAttribute)attributes[0]).title : type.Name;\n        }\n\n        internal static Dictionary<Type, string> GetAvailableWindowTypes()\n        {\n            return s_AvailableWindowTypes ?? (s_AvailableWindowTypes = TypeCache.GetTypesDerivedFrom(typeof(PlayModeView)).OrderBy(GetWindowTitle).ToDictionary(t => t, GetWindowTitle));\n        }\n\n        private void SetSerializedViews(Dictionary<string, string> serializedViews)\n        {\n            m_SerializedViewNames = serializedViews.Keys.ToList();\n            m_SerializedViewValues = serializedViews.Values.ToList();\n        }\n\n        private string GetTypeName()\n        {\n            return GetType().ToString();\n        }\n\n        private Dictionary<string, string> ListsToDictionary(List<string> keys, List<string> values)\n        {\n            var dict = keys.Select((key, val) => new { key, val = values[val] }).ToDictionary(x => x.key, x => x.val);\n            return dict;\n        }\n\n        protected internal void SwapMainWindow(Type type)\n        {\n            if (type.BaseType != typeof(PlayModeView))\n                throw new ArgumentException(\"Type should derive from \" + typeof(PlayModeView).Name);\n            if (type.Name != GetType().Name)\n            {\n                var serializedViews = ListsToDictionary(m_SerializedViewNames, m_SerializedViewValues);\n\n                // Clear serialized views so they wouldn't be serialized again\n                m_SerializedViewNames.Clear();\n                m_SerializedViewValues.Clear();\n\n                var guid = GUID.Generate();\n                var serializedViewPath = Path.GetFullPath(Path.Combine(m_ViewsCache, guid.ToString()));\n                if (!Directory.Exists(m_ViewsCache))\n                    Directory.CreateDirectory(m_ViewsCache);\n\n                InternalEditorUtility.SaveToSerializedFileAndForget(new[] {this}, serializedViewPath, true);\n                serializedViews.Add(GetTypeName(), serializedViewPath);\n\n                PlayModeView window = null;\n                if (serializedViews.ContainsKey(type.ToString()))\n                {\n                    var path = serializedViews[type.ToString()];\n                    serializedViews.Remove(type.ToString());\n                    if (File.Exists(path))\n                    {\n                        window = InternalEditorUtility.LoadSerializedFileAndForget(path)[0] as PlayModeView;\n                        File.Delete(path);\n                    }\n                }\n\n                if (!window)\n                    window = CreateInstance(type) as PlayModeView;\n\n                window.autoRepaintOnSceneChange = true;\n\n                window.SetSerializedViews(serializedViews);\n\n                if (m_Parent is DockArea dockAreaParent)\n                {\n                    // Mark that this view is the one switching out so when we do the tab management we don't have\n                    //   the old tab rewrite the desired size when GameView.OnBackgroundResized() is called during\n                    //   SplitView.Reflow().\n                    m_SwitchingPlayModeViewType = true;\n\n                    dockAreaParent.AddTab(window);\n                    dockAreaParent.RemoveTab(this);\n                    DestroyImmediate(this, true);\n                }\n                else if (m_Parent is MaximizedHostView maximizedParent)\n                {\n                    maximizedParent.actualView = window;\n                    DestroyImmediate(this, true);\n                }\n            }\n            RemoveDisabledWindows();\n        }\n\n        private void ClearTargetTexture()\n        {\n            if (m_TargetTexture.IsCreated())\n            {\n                var previousTarget = RenderTexture.active;\n                RenderTexture.active = m_TargetTexture;\n                GL.Clear(true, true, clearColor);\n                RenderTexture.active = previousTarget;\n            }\n        }\n\n        private void ConfigureTargetTexture(int width, int height, bool clearTexture, string name, bool hdr)\n        {\n            // make sure we actually support R16G16B16A16_SFloat\n            GraphicsFormat format = (hdr && SystemInfo.IsFormatSupported(GraphicsFormat.R16G16B16A16_SFloat, GraphicsFormatUsage.Render)) ? GraphicsFormat.R16G16B16A16_SFloat : SystemInfo.GetGraphicsFormat(DefaultFormat.LDR);\n\n            // Requires destroying the entire RT object and recreating it if\n            // 1. color space is changed;\n            // 2. using mipmap is changed.\n            // 3. HDR backbuffer mode for the view has changed\n\n            if (m_TargetTexture && (m_CurrentColorSpace != QualitySettings.activeColorSpace || m_TargetTexture.useMipMap != m_UseMipMap || m_TargetTexture.graphicsFormat != format))\n            {\n                UnityEngine.Object.DestroyImmediate(m_TargetTexture);\n            }\n            if (!m_TargetTexture)\n            {\n                m_CurrentColorSpace = QualitySettings.activeColorSpace;\n                m_TargetTexture = new RenderTexture(0, 0, format, SystemInfo.GetGraphicsFormat(DefaultFormat.DepthStencil));\n                m_TargetTexture.name = name + \" RT\";\n                m_TargetTexture.filterMode = textureFilterMode;\n                m_TargetTexture.hideFlags = textureHideFlags;\n                m_TargetTexture.useMipMap = useMipMap;\n            }\n\n            // Changes to these attributes require a release of the texture\n            if (m_TargetTexture.width != width || m_TargetTexture.height != height)\n            {\n                m_TargetTexture.Release();\n                m_TargetTexture.width = width;\n                m_TargetTexture.height = height;\n                m_TargetTexture.antiAliasing = 1;\n                clearTexture = true;\n            }\n\n            m_TargetTexture.Create();\n\n            if (clearTexture)\n            {\n                ClearTargetTexture();\n            }\n        }\n\n        internal static PlayModeView GetRenderingView()\n        {\n            return s_RenderingView;\n        }\n\n        internal static PlayModeView GetMainPlayModeView()\n        {\n            if (s_LastFocused == null && s_PlayModeViews != null)\n            {\n                RemoveDisabledWindows();\n                if (s_PlayModeViews.Count > 0)\n                    s_LastFocused = s_PlayModeViews[0];\n            }\n\n            return s_LastFocused;\n        }\n\n        internal static List<PlayModeView> GetAllPlayModeViewWindows()\n        {\n            return s_PlayModeViews;\n        }\n\n        internal static PlayModeView GetCorrectPlayModeViewToFocus()\n        {\n            if (s_PlayModeViews != null)\n            {\n                RemoveDisabledWindows();\n                foreach (var view in s_PlayModeViews)\n                {\n                    if (view.enterPlayModeBehavior == EnterPlayModeBehavior.PlayFocused || view.enterPlayModeBehavior == EnterPlayModeBehavior.PlayMaximized)\n                    {\n                        s_LastFocused = view;\n                        return view;\n                    }\n                }\n            }\n            return GetMainPlayModeView();\n        }\n\n        internal static PlayModeView GetLastFocusedPlayModeView()\n        {\n            return s_LastFocused;\n        }\n\n        private static void RemoveDisabledWindows()\n        {\n            if (s_PlayModeViews == null)\n                return;\n            s_PlayModeViews.RemoveAll(window => window == null);\n        }\n\n        internal static Vector2 GetMainPlayModeViewTargetSize()\n        {\n            var prevWindow = GetMainPlayModeView();\n            if (prevWindow)\n                return prevWindow.GetPlayModeViewSize();\n            return new Vector2(640f, 480f);\n        }\n\n        internal Vector2 GetPlayModeViewSize()\n        {\n            return targetSize;\n        }\n\n        private void RegisterWindow()\n        {\n            RemoveDisabledWindows();\n            if (!s_PlayModeViews.Contains(this))\n            {\n                s_PlayModeViews.Add(this);\n                m_EnterPlayModeBehavior = s_PlayModeViews.Count == 1 ? EnterPlayModeBehavior.PlayFocused : EnterPlayModeBehavior.PlayUnfocused;\n            }\n        }\n\n        public bool IsShowingGizmos()\n        {\n            return showGizmos;\n        }\n\n        public void SetShowGizmos(bool value)\n        {\n            showGizmos = value;\n            Repaint();\n        }\n\n        protected void SetVSync(bool enable)\n        {\n            m_Parent.EnableVSync(enable);\n        }\n\n        protected void SetFocus(bool focused)\n        {\n            if (!focused && s_LastFocused == this)\n            {\n                InternalEditorUtility.OnGameViewFocus(false);\n            }\n            else if (focused)\n            {\n                InternalEditorUtility.OnGameViewFocus(true);\n                m_Parent.SetAsLastPlayModeView();\n                m_Parent.SetMainPlayModeViewSize(targetSize);\n                Display.activeEditorGameViewTarget  = m_TargetDisplay;\n                s_LastFocused = this;\n                // AddLastView(s_LastFocused);\n                Repaint();\n            }\n            SetDisplayViewSize(m_TargetDisplay, m_TargetSize);\n        }\n\n        [RequiredByNativeCode]\n        internal static void IsPlayModeViewOpen(out bool isPlayModeViewOpen)\n        {\n            isPlayModeViewOpen = GetMainPlayModeView() != null;\n        }\n\n        internal static void RepaintAll()\n        {\n            if (s_PlayModeViews == null)\n                return;\n\n            foreach (PlayModeView playModeView in s_PlayModeViews)\n                playModeView.Repaint();\n        }\n\n        public enum EnterPlayModeBehavior\n        {\n            PlayFocused,\n            PlayMaximized,\n            PlayUnfocused\n        }\n\n        void SetPlayModeWindowsStates(EnterPlayModeBehavior behavior)\n        {\n            if(m_EnterPlayModeBehavior == behavior)\n                return;\n\n            m_EnterPlayModeBehavior = behavior;\n            OnEnterPlayModeBehaviorChange();\n\n            if (behavior != EnterPlayModeBehavior.PlayMaximized)\n                return;\n\n            foreach (var view in s_PlayModeViews)\n            {\n                if (view == this || view.m_EnterPlayModeBehavior != EnterPlayModeBehavior.PlayMaximized)\n                    continue;\n\n                // Only one play mode view can be maximized at a time.\n                view.m_EnterPlayModeBehavior = EnterPlayModeBehavior.PlayUnfocused;\n                view.OnEnterPlayModeBehaviorChange();\n                view.Repaint();\n            }\n        }\n\n        protected virtual void OnEnterPlayModeBehaviorChange() {}\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayModeView/PlayModeWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public class PlayModeWindow\n    {\n        static Type s_SimulatorWindowType =\n            PlayModeView.GetAvailableWindowTypes().Keys.FirstOrDefault(x => x.Name.Contains(\"SimulatorWindow\"));\n\n        PlayModeWindow()\n        {\n        }\n\n        public enum PlayModeViewTypes\n        {\n            GameView,\n            SimulatorView\n        }\n\n        public static void GetRenderingResolution(out uint width, out uint height)\n        {\n            var view = GetOrCreateWindow();\n            width = (uint)view.targetSize.x;\n            height = (uint)view.targetSize.y;\n        }\n\n        public static void SetCustomRenderingResolution(uint width, uint height, string baseName)\n        {\n            var win = GetOrCreateWindow();\n            var gameView = win as GameView;\n\n            if (gameView != null)\n            {\n                gameView.SetCustomResolution(new Vector2(width, height), baseName);\n            }\n            else\n            {\n                Debug.LogError($\"The {win.GetType().Name} does not support custom resolution\");\n            }\n        }\n\n        public static void SetPlayModeFocused(bool focused)\n        {\n            GetOrCreateWindow().enterPlayModeBehavior = focused\n                ? PlayModeView.EnterPlayModeBehavior.PlayFocused\n                : PlayModeView.EnterPlayModeBehavior.PlayMaximized;\n        }\n\n        public static bool GetPlayModeFocused()\n        {\n            return GetOrCreateWindow().enterPlayModeBehavior == PlayModeView.EnterPlayModeBehavior.PlayFocused;\n        }\n\n        public static PlayModeViewTypes GetViewType()\n        {\n            var type = GetOrCreateWindow().GetType();\n            if (type == typeof(GameView))\n                return PlayModeViewTypes.GameView;\n            if (type == s_SimulatorWindowType)\n                return PlayModeViewTypes.SimulatorView;\n\n            throw new Exception(\"Unsupported PlayModeView type\");\n        }\n\n        public static void SetViewType(PlayModeViewTypes type)\n        {\n            var view = GetOrCreateWindow();\n            switch (type)\n            {\n                case PlayModeViewTypes.GameView:\n                    view.SwapMainWindow(typeof(GameView));\n                    return;\n                case PlayModeViewTypes.SimulatorView:\n                {\n                    // DeviceSim is a Module that might be disabled in the future.\n                    if (s_SimulatorWindowType == null)\n                    {\n                        throw new Exception(\"Cannot find the SimulatorWindow type.\");\n                    }\n                    view.SwapMainWindow(s_SimulatorWindowType);\n                    return;\n                }\n                default:\n                    throw new Exception(\"Unsupported PlayModeView type\");\n            }\n        }\n\n        static PlayModeView GetOrCreateWindow()\n        {\n            var view = PlayModeView.GetMainPlayModeView();\n            if (view == null)\n            {\n                return EditorWindow.CreateWindow<GameView>();\n            }\n\n            return view;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Playables/PlayableOutputEditorExtensions.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Playables;\n\nnamespace UnityEditor.Playables\n{\n    public static class PlayableOutputEditorExtensions\n    {\n        public static string GetEditorName<U>(this U output) where U : struct, IPlayableOutput\n        {\n            return output.GetHandle().GetEditorName();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Playables/Playables.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\nusing UnityEngine.Playables;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Playables\n{\n    [NativeHeader(\"Editor/Src/Playables/Playables.bindings.h\")]\n    static public class Utility\n    {\n        static public event Action<PlayableGraph> graphCreated;\n        static public event Action<PlayableGraph> destroyingGraph;\n\n        [RequiredByNativeCode]\n        static private void OnPlayableGraphCreated(PlayableGraph graph)\n        {\n            if (graphCreated != null)\n                graphCreated(graph);\n        }\n\n        [RequiredByNativeCode]\n        static private void OnDestroyingPlayableGraph(PlayableGraph graph)\n        {\n            if (destroyingGraph != null)\n                destroyingGraph(graph);\n        }\n\n        extern static public PlayableGraph[] GetAllGraphs();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerConnectionLogReceiver.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEditorInternal;\nusing System.Linq;\nusing UnityEngine.Networking.PlayerConnection;\nusing UnityEditor.Networking.PlayerConnection;\nusing System.Text;\n\nnamespace UnityEditor\n{\n    internal class PlayerConnectionLogReceiver : ScriptableSingleton<PlayerConnectionLogReceiver>\n    {\n        static readonly Guid logMessageId = new Guid(\"394ada03-8ba0-4f26-b001-1a6cdeb05a62\");\n        static readonly Guid cleanLogMessageId = new Guid(\"3ded2dda-cdf2-46d8-a3f6-01741741e7a9\");\n        static readonly Guid logMessageIdMultiple = new Guid(\"5970345b-a9ef-448e-9706-aa42fb3e68e1\");\n        static readonly Guid cleanLogMessageIdMultiple = new Guid(\"b86c7bd8-e37d-4b1c-9a63-72f4b5d8112d\");\n        const string prefsKey = \"PlayerConnectionLoggingState\";\n\n        internal enum ConnectionState\n        {\n            Disconnected,\n            CleanLog,\n            FullLog\n        }\n\n        [SerializeField]\n        ConnectionState state = ConnectionState.Disconnected;\n\n        void OnEnable()\n        {\n            State = (ConnectionState)EditorPrefs.GetInt(prefsKey, (int)ConnectionState.CleanLog);\n        }\n\n        internal ConnectionState State\n        {\n            get\n            {\n                return state;\n            }\n            set\n            {\n                if (state == value)\n                    return;\n\n                switch (state)\n                {\n                    case ConnectionState.CleanLog:\n                        EditorConnection.instance.Unregister(cleanLogMessageId, LogMessage);\n                        EditorConnection.instance.Unregister(cleanLogMessageIdMultiple, LogMessageMultiple);\n                        break;\n\n                    case ConnectionState.FullLog:\n                        EditorConnection.instance.Unregister(logMessageId, LogMessage);\n                        EditorConnection.instance.Unregister(logMessageIdMultiple, LogMessageMultiple);\n                        break;\n                }\n                state = value;\n                switch (state)\n                {\n                    case ConnectionState.CleanLog:\n                        EditorConnection.instance.Register(cleanLogMessageId, LogMessage);\n                        EditorConnection.instance.Register(cleanLogMessageIdMultiple, LogMessageMultiple);\n                        break;\n\n                    case ConnectionState.FullLog:\n                        EditorConnection.instance.Register(logMessageId, LogMessage);\n                        EditorConnection.instance.Register(logMessageIdMultiple, LogMessageMultiple);\n                        break;\n                }\n                EditorPrefs.SetInt(prefsKey, (int)state);\n            }\n        }\n\n        [ThreadStatic]\n        static System.Text.StringBuilder s_LogBuilder;\n\n        void LogMessage(MessageEventArgs messageEventArgs)\n        {\n            if (s_LogBuilder == null)\n                s_LogBuilder = new System.Text.StringBuilder(1024);\n            else\n                s_LogBuilder.Clear();\n\n            var logType = (LogType)messageEventArgs.data[0];\n            if (!Enum.IsDefined(typeof(LogType), logType))\n                logType = LogType.Log;\n            var oldStackTraceType = Application.GetStackTraceLogType(logType);\n\n            // We don't want stack traces from editor code in player log messages.\n            Application.SetStackTraceLogType(logType, StackTraceLogType.None);\n            var name = ConnectionUIHelper.GetPlayerNameFromId(messageEventArgs.playerId);\n            var t = ConnectionUIHelper.GetPlayerType(ProfilerDriver.GetConnectionIdentifier(messageEventArgs.playerId));\n\n            s_LogBuilder.Append(\"<i>\");\n            s_LogBuilder.Append(t);\n            s_LogBuilder.Append(\" \\\"\");\n            s_LogBuilder.Append(name);\n            s_LogBuilder.Append(\"\\\"</i> \");\n            ReadOnlySpan<byte> utf8String = messageEventArgs.data.AsSpan<byte>(4);\n            s_LogBuilder.Append(System.Text.Encoding.UTF8.GetString(utf8String));\n\n            Debug.unityLogger.Log(logType, s_LogBuilder.ToString());\n            Application.SetStackTraceLogType(logType, oldStackTraceType);\n        }\n\n        void LogMessageMultiple(MessageEventArgs messageEventArgs)\n        {\n            ReadOnlySpan<byte> payload = messageEventArgs.data.AsSpan<byte>();\n            var payloadLength = payload.Length;\n\n            if (payloadLength <= 0) return;\n\n            var name = ConnectionUIHelper.GetPlayerNameFromId(messageEventArgs.playerId);\n            var t = ConnectionUIHelper.GetPlayerType(ProfilerDriver.GetConnectionIdentifier(messageEventArgs.playerId));\n\n            var prefix = $\"<i>{t} \\\"{name}\\\"</i> \";\n            var prefixUtf8Length = Encoding.UTF8.GetByteCount(prefix);\n            var prefixUtf8Bytes = new byte[prefixUtf8Length];\n            var prefixUtf8Span = new Span<byte>(prefixUtf8Bytes);\n            Encoding.UTF8.GetBytes(prefix, prefixUtf8Span);\n\n            var messagePrefix = new UTF8StringView(prefixUtf8Span);\n\n            static UTF8StringView ReadString(ReadOnlySpan<byte> payload, ref int offset)\n            {\n                var bytesLength = BitConverter.ToInt32(payload.Slice(offset, 4));\n                offset += 4;\n\n                if (bytesLength == 0)\n                    return default;\n                if (bytesLength < 0)\n                    throw new Exception(\"Received corrupted message\");\n\n                var utf8String = payload.Slice(offset, bytesLength);\n                offset += bytesLength;\n\n                unsafe\n                {\n                    fixed(byte* ptr = &utf8String[0])\n                        return new UTF8StringView(ptr, bytesLength);\n                }\n            }\n\n            static LogMessageFlags FlagsFromType(LogType type)\n            {\n                switch (type)\n                {\n                    case LogType.Warning: return LogMessageFlags.DebugWarning;\n                    case LogType.Error: return LogMessageFlags.DebugError;\n                    case LogType.Assert: return LogMessageFlags.DebugAssert;\n                    case LogType.Exception: return LogMessageFlags.DebugException;\n                }\n                return LogMessageFlags.DebugLog;\n            }\n\n            for (var offset = 0; offset < payloadLength;)\n            {\n                var logType = (LogType)BitConverter.ToInt32(payload.Slice(offset, 4));\n                offset += 4;\n\n                var message = ReadString(payload, ref offset);\n                var timestamp = ReadString(payload, ref offset);\n                var stacktrace = ReadString(payload, ref offset);\n\n                var log = new LogEntryStruct\n                {\n                    messagePrefix = messagePrefix,\n                    message = message,\n                    timestamp = timestamp,\n                    callstack = stacktrace,\n                    mode = FlagsFromType(logType) | LogMessageFlags.kStacktraceIsPostprocessed\n                };\n                ConsoleWindow.AddMessage(ref log);\n                Console.WriteLine(messagePrefix.ToString() + message.ToString());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerPrefsSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditor\n{\n    internal class PlayerPrefsSettings\n    {\n        [MenuItem(\"Edit/Clear All PlayerPrefs\", false, 15000, false)]\n        static void ClearPlayerPrefs()\n        {\n            if (EditorUtility.DisplayDialog(\"Clear All PlayerPrefs\",\n                \"Are you sure you want to clear all PlayerPrefs? \" +\n                \"This action cannot be undone.\", \"Yes\", \"No\"))\n            {\n                PlayerPrefs.DeleteAll();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettings.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Linq;\nusing System.Text;\nusing UnityEditor.Build;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEditor.Modules;\nusing UnityEditor.Build.Profile;\n\nnamespace UnityEditor\n{\n    // Resolution dialog setting\n    [Obsolete(\"The Display Resolution Dialog has been removed.\", false)]\n    public enum ResolutionDialogSetting\n    {\n        // Never show the resolutions dialog.\n        Disabled = 0,\n\n        // Show the resolutions dialog on first launch.\n        Enabled = 1,\n\n        // Hide the resolutions dialog on first launch.\n        HiddenByDefault = 2,\n    }\n\n    public enum ScriptingImplementation\n    {\n        Mono2x = 0,\n        IL2CPP = 1,\n        WinRTDotNET = 2,\n        [Obsolete(\"CoreCLR support is still a work in progress and is disabled for now.\")] // Hide from intellisense while CORECLR_FIXME\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        CoreCLR = 3,\n    }\n\n    // Must be in sync with Il2CppCompilerConfiguration enum in SerializationMetaFlags.h\n    public enum Il2CppCompilerConfiguration\n    {\n        Debug = 0,\n        Release = 1,\n        Master = 2,\n    }\n\n    // Must be in sync with Il2CppStacktraceInformation enum in SerializationMetaFlags.h\n    public enum Il2CppStacktraceInformation\n    {\n        MethodOnly = 0,\n        MethodFileLineNumber = 1,\n    }\n\n    // Mac fullscreen mode\n    public enum MacFullscreenMode\n    {\n        [Obsolete(\"Capture Display mode is deprecated, Use FullscreenWindow instead\")]\n        CaptureDisplay = 0,\n\n        // Fullscreen window.\n        FullscreenWindow = 1,\n\n        // Fullscreen window with Dock and Menu bar.\n        FullscreenWindowWithDockAndMenuBar = 2,\n    }\n\n    [Obsolete(\"D3D9 support has been removed\")]\n    public enum D3D9FullscreenMode\n    {\n        [Obsolete(\"D3D9 support has been removed\")]\n        ExclusiveMode = 0,\n        [Obsolete(\"D3D9 support has been removed\")]\n        FullscreenWindow = 1,\n    }\n\n    // Direct3D 11 fullscreen mode\n    public enum D3D11FullscreenMode\n    {\n        // Exclusive mode.\n        ExclusiveMode = 0,\n\n        // Fullscreen window.\n        FullscreenWindow = 1,\n    }\n\n    // Must be in sync with StereoRenderingPath enum in GfxDeviceTypes.h\n    public enum StereoRenderingPath\n    {\n        // Slow multi pass method ( For reference only )\n        MultiPass = 0,\n\n        // Single pass stereo rendering\n        SinglePass = 1,\n\n        // Single pass stereo rendering with instancing\n        Instancing = 2\n    }\n\n    // Managed code stripping level - must be in sync with StrippingLevel enum in BuildTargetPlatformSpecific.h\n    public enum StrippingLevel\n    {\n        // Managed code stripping is disabled\n        Disabled = 0,\n\n        // Unused parts of managed code are stripped away\n        StripAssemblies = 1,\n\n        // Managed method bodies are stripped away. AOT platforms only.\n        StripByteCode = 2,\n\n        // Lightweight mscorlib version will be used at expense of limited compatibility.\n        UseMicroMSCorlib = 3\n    }\n\n    // Script call optimization level\n    public enum ScriptCallOptimizationLevel\n    {\n        // Default setting\n        SlowAndSafe = 0,\n\n        // Script method call overhead decreased at the expense of limited compatibility.\n        FastButNoExceptions = 1\n    }\n\n    // Default mobile device orientation\n    public enum UIOrientation\n    {\n        // Portrait\n        Portrait = 0,\n\n        // Portrait upside down\n        PortraitUpsideDown = 1,\n\n        // Landscape: clockwise from Portrait\n        LandscapeRight = 2,\n\n        // Landscape : counter-clockwise from Portrait\n        LandscapeLeft = 3,\n\n        // Auto Rotation Enabled\n        AutoRotation = 4\n    }\n\n    // Scripting runtime version\n    [Obsolete(\"ScriptingRuntimeVersion has been deprecated in 2019.3 now that legacy mono has been removed\")]\n    public enum ScriptingRuntimeVersion\n    {\n        // .NET 3.5\n        Legacy = 0,\n\n        // .NET 4.6\n        Latest = 1\n    }\n\n    // .NET API compatibility level\n    public enum ApiCompatibilityLevel\n    {\n        // .NET 2.0\n        NET_2_0 = 1,\n\n        // .NET 2.0 Subset\n        NET_2_0_Subset = 2,\n\n        // .NET 4.6\n        NET_4_6 = 3,\n\n        // unity_web profile, currently unused. Formerly used by Samsung TV\n        NET_Web = 4,\n\n        // micro profile, used by Mono scripting backend if stripping level is set to \"Use micro mscorlib\"\n        NET_Micro = 5,\n\n        // .NET Standard 2.0\n        NET_Standard_2_0 = 6,\n\n        // Latest .NET Standard version Unity supports\n        NET_Standard = NET_Standard_2_0,\n\n        // .NET Framework 8 + .NET Standard 2.1 APIs\n        NET_Unity_4_8 = NET_4_6,\n    }\n\n\n    // Editor Assembly compatibility level\n    public enum EditorAssembliesCompatibilityLevel\n    {\n        // For now it will be the same as #2. In future updates, the default will be the same as #3.\n        Default = 1,\n        NET_Unity_4_8 = 2,\n        NET_Standard = 3,\n    }\n\n    public enum ManagedStrippingLevel\n    {\n        Disabled = 0,\n        Low = 1,\n        Medium = 2,\n        High = 3,\n        Minimal = 4,\n    }\n\n    // What to do on uncaught .NET exception (on iOS)\n    [Obsolete(\"The enum is deprecated and will be removed in a future release.\")]\n    public enum ActionOnDotNetUnhandledException\n    {\n        // Silent exit\n        SilentExit = 0,\n\n        // Crash\n        Crash = 1\n    }\n\n    [Obsolete(\"SplashScreenStyle deprecated, Use PlayerSettings.SplashScreen.UnityLogoStyle instead\")]\n    public enum SplashScreenStyle\n    {\n        Light = 0,\n        Dark = 1\n    }\n\n    // Must be in sync with GraphicsJobMode enum in GfxDeviceTypes.h\n    public enum GraphicsJobMode\n    {\n        Native = 0,\n        Legacy = 1,\n        Split\n    }\n\n    // Must be in sync with GfxThreadingMode enum in GfxDeviceTypes.h\n    public enum GfxThreadingMode\n    {\n        // Direct threading mode.\n        // Main thread writes native graphics commands and submits them directly.\n        Direct = 0,\n\n        // SingleThreaded mode.\n        // Main thread writes Unity graphics commands that it later reads and converts to native graphics commands.\n        NonThreaded = 1,\n\n        // MultiThreaded mode.\n        // Main thread writes Unity graphics commands. A Render thread reads Unity graphics commands and converts them to native graphics commands.\n        Threaded = 2,\n\n        // Legacy Graphics Jobs (\"Jobified Rendering\").\n        // Main thread writes Unity graphics commands and starts worker threads to do the same.\n        // A Render thread reads Unity graphics commands and converts them to native graphics commands.\n        ClientWorkerJobs = 3,\n\n        // Native Graphics Jobs.\n        // Main thread writes Unity graphics commands.\n        // Render thread reads Unity graphics commands and converts them to native graphics commands.\n        // The render thread also starts worker threads to write native graphics commands.\n        ClientWorkerNativeJobs = 4,\n\n        // Native Graphics Jobs without Render Thread.\n        // Main thread writes native graphics commands, starts worker threads to do the same, and submits them directly.\n        DirectNativeJobs = 5,\n\n        // Split Graphics Jobs.\n        // Main thread starts worker threads to write Unity graphics commands.\n        // Render thread reads Unity graphics commands converts them to native graphics commands.\n        // The render thread also starts worker threads to write native graphics commands.\n        SplitJobs = 6\n    }\n\n    // Must be in sync with MeshDeformation enum in GfxDeviceTypes.h\n    public enum MeshDeformation\n    {\n        CPU = 0,\n        GPU = 1,\n        GPUBatched = 2\n    }\n\n    // Must be in sync with IconKind enum in EditorOnlyPlayerSettings.h\n    public enum IconKind\n    {\n        Any = -1,\n        Application = 0,\n        Settings = 1,\n        Notification = 2,\n        Spotlight = 3,\n        Store = 4\n    }\n\n    // Keep in synch with LightmapEncodingQuality enum from GfxDeviceTypes.h\n    internal enum LightmapEncodingQuality\n    {\n        Low = 0,\n        Normal = 1,\n        High = 2\n    }\n\n    // Keep in synch with HDRCubemapEncodingQuality enum from GfxDeviceTypes.h\n    internal enum HDRCubemapEncodingQuality\n    {\n        Low = 0,\n        Normal = 1,\n        High = 2\n    }\n\n    // Must be in sync with ShaderPrecisionModel enum in EditorOnlyPlayerSettings.h\n    public enum ShaderPrecisionModel\n    {\n        PlatformDefault = 0,\n        Unified = 1,\n    }\n\n    public enum NormalMapEncoding\n    {\n        XYZ = 0,\n        DXT5nm = 1\n    }\n\n    public enum TextureCompressionFormat\n    {\n        Unknown = 0,\n        ETC = 1,\n        ETC2 = 2,\n        ASTC = 3,\n        [Obsolete(\"Texture compression format PVRTC has been deprecated and will be removed in a future release\")]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        PVRTC = 4,\n        DXTC = 5,\n        BPTC = 6,\n        DXTC_RGTC = 7\n    }\n\n    public enum InsecureHttpOption\n    {\n        NotAllowed = 0,\n        DevelopmentOnly = 1,\n        AlwaysAllowed = 2,\n    }\n\n    // Windows platform input APIs\n    // Keep in sync with WindowsGamepadBackendHint enum from PlayerSettings.h\n    public enum WindowsGamepadBackendHint\n    {\n        // Backend selected automatically based on platform support\n        WindowsGamepadBackendHintDefault = 0,\n\n        // XInput\n        WindowsGamepadBackendHintXInput = 1,\n\n        // GameInput\n        WindowsGamepadBackendHintWindowsGamingInput = 2\n    }\n\n    // Set of player settings that require an editor restart\n    // Keep in sync with PlayerSettingsRequiringRestart in PlayerSettings.h\n    internal enum PlayerSettingsRequiringRestart\n    {\n        IncrementalGC = 0,\n        ActiveInputHandling = 1,\n        GraphicsJobs = 2,\n        VirtualTexturing = 3,\n    }\n\n    // Player Settings is where you define various parameters for the final game that you will build in Unity. Some of these values are used in the Resolution Dialog that launches when you open a standalone game.\n    [NativeClass(null)]\n    [NativeHeader(\"Editor/Mono/PlayerSettings.bindings.h\")]\n    [NativeHeader(\"Runtime/Misc/BuildSettings.h\")]\n    [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n    [NativeHeader(\"Runtime/Misc/PlayerSettingsSplashScreen.h\")]\n    [StaticAccessor(\"GetPlayerSettings()\")]\n    public sealed partial class PlayerSettings : UnityEngine.Object\n    {\n        private PlayerSettings() {}\n\n        private static SerializedObject _serializedObject;\n\n        [FreeFunction(\"GetPlayerSettingsPtr\")]\n        private static extern UnityEngine.Object InternalGetPlayerSettingsObject();\n\n        internal static void ValidateBuildTargetNameParameter(string buildTargetName, bool unknownIsValid = false)\n        {\n            // The empty string is the valid form of BuildTargetGroup.Unknown, so don't throw an execption for that case.\n            if (BuildPipeline.GetBuildTargetGroupByName(buildTargetName) == BuildTargetGroup.Unknown && (!unknownIsValid || buildTargetName != \"\"))\n                throw new ArgumentException($\"The provided target platform group name ({buildTargetName}) is not valid.\");\n        }\n\n        internal static SerializedObject GetSerializedObject()\n        {\n            if (_serializedObject == null || _serializedObject.targetObject != InternalGetPlayerSettingsObject())\n                _serializedObject = new SerializedObject(InternalGetPlayerSettingsObject());\n            return _serializedObject;\n        }\n\n        internal static SerializedProperty FindProperty(string name)\n        {\n            SerializedProperty property = GetSerializedObject().FindProperty(name);\n            if (property == null)\n                Debug.LogError(\"Failed to find:\" + name);\n            return property;\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern void SetPropertyInt(string name, int value, BuildTargetGroup target);\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static void SetPropertyInt(string name, int value)\n        {\n            SetPropertyInt(name, value, BuildTargetGroup.Unknown);\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static void SetPropertyInt(string name, int value, BuildTarget target)\n        {\n            SetPropertyInt(name, value, BuildPipeline.GetBuildTargetGroup(target));\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern int GetPropertyInt(string name, BuildTargetGroup target);\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static int GetPropertyInt(string name)\n        {\n            return GetPropertyInt(name, BuildTargetGroup.Unknown);\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static bool GetPropertyOptionalInt(string name, ref int value, BuildTargetGroup target)\n        {\n            value = GetPropertyInt(name, target);\n            return true;\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static bool GetPropertyOptionalInt(string name, ref int value)\n        {\n            value = GetPropertyInt(name, BuildTargetGroup.Unknown);\n            return true;\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern void SetPropertyBool(string name, bool value, BuildTargetGroup target);\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static void SetPropertyBool(string name, bool value)\n        {\n            SetPropertyBool(name, value, BuildTargetGroup.Unknown);\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static void SetPropertyBool(string name, bool value, BuildTarget target)\n        {\n            SetPropertyBool(name, value, BuildPipeline.GetBuildTargetGroup(target));\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern bool GetPropertyBool(string name, BuildTargetGroup target);\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static bool GetPropertyBool(string name)\n        {\n            return GetPropertyBool(name, BuildTargetGroup.Unknown);\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static bool GetPropertyOptionalBool(string name, ref bool value, BuildTargetGroup target)\n        {\n            value = GetPropertyBool(name, target);\n            return true;\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static bool GetPropertyOptionalBool(string name, ref bool value)\n        {\n            value = GetPropertyBool(name, BuildTargetGroup.Unknown);\n            return true;\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern void SetPropertyString(string name, string value, BuildTargetGroup target);\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static void SetPropertyString(string name, string value)\n        {\n            SetPropertyString(name, value, BuildTargetGroup.Unknown);\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static void SetPropertyString(string name, string value, BuildTarget target)\n        {\n            SetPropertyString(name, value, BuildPipeline.GetBuildTargetGroup(target));\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern string GetPropertyString(string name, BuildTargetGroup target);\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static string GetPropertyString(string name)\n        {\n            return GetPropertyString(name, BuildTargetGroup.Unknown);\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static bool GetPropertyOptionalString(string name, ref string value, BuildTargetGroup target)\n        {\n            value = GetPropertyString(name, target);\n            return true;\n        }\n\n        [Obsolete(\"Use explicit API instead.\")]\n        public static bool GetPropertyOptionalString(string name, ref string value)\n        {\n            value = GetPropertyString(name, BuildTargetGroup.Unknown);\n            return true;\n        }\n\n        internal static extern void SetDirty();\n\n        // The name of your company.\n        public static extern string companyName { get; set; }\n\n        // The name of your product.\n        public static extern string productName { get; set; }\n\n        [Obsolete(\"Use PlayerSettings.SplashScreen.show instead\")]\n        [StaticAccessor(\"GetPlayerSettings().GetSplashScreenSettings()\")]\n        public static extern bool showUnitySplashScreen { get; set; }\n\n        [Obsolete(\"Use PlayerSettings.SplashScreen.unityLogoStyle instead\")]\n        [StaticAccessor(\"GetPlayerSettings().GetSplashScreenSettings()\")]\n        [NativeProperty(\"SplashScreenLogoStyle\")]\n        public static extern SplashScreenStyle splashScreenStyle { get; set; }\n\n        /// Cloud project id.\n        [Obsolete(\"cloudProjectId is deprecated, use CloudProjectSettings.projectId instead\")]\n        public static extern string cloudProjectId { get; }\n\n        internal static extern void SetCloudProjectId(string projectId);\n\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        internal static extern void SetCloudServiceEnabled(string serviceKey, bool enabled);\n\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        internal static extern bool GetCloudServiceEnabled(string serviceKey);\n\n        /// Uniquely identifies your product.\n        public static Guid productGUID\n        {\n            get { return new Guid(productGUIDRaw); }\n        }\n\n        /// *undocumented*\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        private static extern byte[] productGUIDRaw { get; }\n\n        // Set the color space for the current project\n        public static extern ColorSpace colorSpace { get; set; }\n\n        // Default horizontal dimension of stand-alone player window.\n        public static extern int defaultScreenWidth { get; set; }\n\n        // Default vertical dimension of stand-alone player window.\n        public static extern int defaultScreenHeight { get; set; }\n\n        // Default horizontal dimension of web player window.\n        public static extern int defaultWebScreenWidth { get; set; }\n\n        // Default vertical dimension of web player window.\n        public static extern int defaultWebScreenHeight { get; set; }\n\n        // Defines the behaviour of the Resolution Dialog on product launch.\n        [Obsolete(\"displayResolutionDialog has been removed.\", false)]\n        public static extern ResolutionDialogSetting displayResolutionDialog { get; set; }\n\n        // If enabled, the game will default to fullscreen mode.\n        [Obsolete(\"(defaultIsFullScreen is deprecated, use fullScreenMode instead\")]\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern bool defaultIsFullScreen { get; set; }\n\n        // If enabled, the game will default to native resolution in fullscreen mode.\n        public static extern bool defaultIsNativeResolution { get; set; }\n\n        // If enabled, the game will render at retina resolution\n        public static extern bool macRetinaSupport { get; set; }\n\n        // If enabled, your game will continue to run after lost focus.\n        public static extern bool runInBackground { get; set; }\n\n        // Defines if fullscreen games should darken secondary displays.\n        [Obsolete(\"captureSingleScreen has been removed.\", false)]\n        public static bool captureSingleScreen { get; set; }\n\n        // Write a log file with debugging information.\n        public static extern bool usePlayerLog { get; set; }\n\n        // Use resizable window in standalone player builds.\n        public static extern bool resizableWindow { get; set; }\n\n        // Should resolution be reset when native window size changes. Shared between iOS & Android platforms.\n        public static extern bool resetResolutionOnWindowResize { get; set; }\n\n        /// Bake collision meshes into the mesh asset.\n        public static extern bool bakeCollisionMeshes { get; set; }\n\n        // Enable receipt validation for the Mac App Store.\n        public static extern bool useMacAppStoreValidation { get; set; }\n\n        // Enable advanced optimiztions for Dedicated Server builds\n        public static extern bool dedicatedServerOptimizations { get; set; }\n\n        // Define how to handle fullscreen mode in Mac OS X standalones\n        [Obsolete(\"macFullscreenMode is deprecated, use fullScreenMode instead\")]\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern MacFullscreenMode macFullscreenMode { get; set; }\n\n        // Define how to handle fullscreen mode with Direct3D 9\n        [Obsolete(\"d3d9FullscreenMode is deprecated, use fullScreenMode instead\")]\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern D3D9FullscreenMode d3d9FullscreenMode { get; set; }\n\n        // Define how to handle fullscreen mode with Direct3D 11\n        [Obsolete(\"d3d11FullscreenMode is deprecated, use fullScreenMode instead\")]\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern D3D11FullscreenMode d3d11FullscreenMode { get; set; }\n\n        [NativeProperty(\"FullscreenMode\")]\n        public static extern FullScreenMode fullScreenMode { get; set; }\n\n        [Obsolete(\"This API is obsolete, and should no longer be used. Please use XRManagerSettings in the XR Management package instead.\")]\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern bool virtualRealitySupported { get; set; }\n\n        [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        internal class PlayerSettings360StereoCapture\n        {\n            public static extern bool enable360StereoCapture\n            {\n                get;\n                set;\n            }\n        }\n\n        public static bool enable360StereoCapture\n        {\n            get { return PlayerSettings360StereoCapture.enable360StereoCapture; }\n            set { PlayerSettings360StereoCapture.enable360StereoCapture = value; }\n        }\n\n        [Obsolete(\"singlePassStereoRendering will be deprecated. Use stereoRenderingPath instead.\")]\n        public static bool singlePassStereoRendering\n        {\n            get { return stereoRenderingPath == StereoRenderingPath.SinglePass; }\n            set { stereoRenderingPath = value ? StereoRenderingPath.SinglePass : StereoRenderingPath.MultiPass; }\n        }\n\n        public static extern StereoRenderingPath stereoRenderingPath { get; set; }\n\n        [Obsolete(\"protectGraphicsMemory is deprecated. This field has no effect.\", false)]\n        public static bool protectGraphicsMemory { get { return false; } set {} }\n\n        public static extern bool enableFrameTimingStats { get; set; }\n        public static extern bool enableOpenGLProfilerGPURecorders { get; set; }\n\n        public static extern bool allowHDRDisplaySupport { get; set; }\n        public static extern bool useHDRDisplay { get; set; }\n\n        [Obsolete(\"D3DHDRBitDepth has been replaced by hdrBitDepth. (UnityUpgradable) -> hdrBitDepth\", true)]\n        public static extern D3DHDRDisplayBitDepth D3DHDRBitDepth { [NativeName(\"GetHDRBitDepthForObseleteEnum\")] get; [NativeName(\"SetHDRBitDepthForObseleteEnum\")] set; }\n\n        public static extern HDRDisplayBitDepth hdrBitDepth { get; set; }\n\n        // What happens with the fullscreen Window when it runs in the background\n\n        public static extern bool visibleInBackground { get; set; }\n\n        // What happens the user presses OS specific full screen switch key combination\n\n        public static extern bool allowFullscreenSwitch { get; set; }\n\n        // Restrict standalone players to a single concurrent running instance.\n        public static extern bool forceSingleInstance { get; set; }\n\n        public static extern bool useFlipModelSwapchain { get; set; }\n\n        [NativeProperty(TargetType = TargetType.Field)]\n        public static extern bool openGLRequireES31\n        {\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n            get;\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n            set;\n        }\n\n        [NativeProperty(TargetType = TargetType.Field)]\n        public static extern bool openGLRequireES31AEP\n        {\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n            get;\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n            set;\n        }\n\n        [NativeProperty(TargetType = TargetType.Field)]\n        public static extern bool openGLRequireES32\n        {\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n            get;\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n            set;\n        }\n\n        // Set Maximum Vertex Threshold for Sprite Batching.\n        public static extern int spriteBatchVertexThreshold { get; set; }\n\n        // Set Maxomum Batch Vertex Count\n        internal static extern int spriteBatchMaxVertexCount { get; set; }\n\n        // The image to display in the Resolution Dialog window.\n        [Obsolete(\"resolutionDialogBanner has been removed.\", false)]\n        public static extern Texture2D resolutionDialogBanner { get; set; }\n\n        // The image to display on the Virtual Reality splash screen.\n        [StaticAccessor(\"GetPlayerSettings().GetSplashScreenSettings()\")]\n        public static extern Texture2D virtualRealitySplashScreen { get; set; }\n\n        // The bundle identifier of the iPhone application.\n        [Obsolete(\"iPhoneBundleIdentifier is deprecated. Use PlayerSettings.SetApplicationIdentifier(NamedBuildTarget.iOS) instead.\")]\n        public static string iPhoneBundleIdentifier\n        {\n            get { return GetApplicationIdentifier(NamedBuildTarget.iOS); }\n            set { SetApplicationIdentifier(NamedBuildTarget.iOS, value); }\n        }\n\n        // Note: If an empty list is returned, no icons are assigned specifically to the specified platform at this point,\n        [NativeMethod(\"GetPlatformIcons\")]\n        internal static extern Texture2D[] GetIconsForPlatform(string platform, IconKind kind);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern Texture2D[] GetIconsForPlatformByKind(int layerCount, string platform, int kind, string subKind, int width, int height);\n\n        internal static void SetIconsForPlatform(string platform, Texture2D[] icons)\n        {\n            SetIconsForPlatform(platform, icons, IconKind.Any);\n        }\n\n        [NativeThrows]\n        [NativeMethod(\"SetPlatformIcons\")]\n        internal static extern void SetIconsForPlatform(string platform, Texture2D[] icons, IconKind kind);\n\n        [NativeMethod(\"GetPlatformIconWidths\")]\n        internal static extern int[] GetIconWidthsForPlatform(string platform, IconKind kind);\n\n        [NativeMethod(\"GetPlatformIconHeights\")]\n        internal static extern int[] GetIconHeightsForPlatform(string platform, IconKind kind);\n\n        [NativeMethod(\"GetPlatformIconKinds\")]\n        internal static extern IconKind[] GetIconKindsForPlatform(string platform);\n\n        public static extern UnityEngine.Object[] GetPreloadedAssets();\n\n        public static extern void SetPreloadedAssets(UnityEngine.Object[] assets);\n\n        internal static string GetPlatformName(BuildTargetGroup targetGroup)\n        {\n            return BuildPipeline.GetBuildTargetGroupName(targetGroup);\n        }\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void GetBatchingForPlatform(BuildTarget platform, out int staticBatching, out int dynamicBatching);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetBatchingForPlatform(BuildTarget platform, int staticBatching, int dynamicBatching);\n\n        public static bool GetStaticBatchingForPlatform(BuildTarget platform)\n        {\n            PlayerSettings.GetBatchingForPlatform(platform, out var staticBatching, out _);\n            return staticBatching > 0;\n        }\n\n        public static void SetStaticBatchingForPlatform(BuildTarget platform, bool enable)\n        {\n            PlayerSettings.GetBatchingForPlatform(platform, out _, out var dynamicBatching);\n            PlayerSettings.SetBatchingForPlatform(platform, enable == true ? 1 : 0, dynamicBatching);\n        }\n\n        public static bool GetDynamicBatchingForPlatform(BuildTarget platform)\n        {\n\n            PlayerSettings.GetBatchingForPlatform(platform, out _, out var dynamicBatching);\n            return dynamicBatching > 0;\n        }\n\n        public static void SetDynamicBatchingForPlatform(BuildTarget platform, bool enable)\n        {\n            PlayerSettings.GetBatchingForPlatform(platform, out var staticBatching, out _);\n            PlayerSettings.SetBatchingForPlatform(platform, staticBatching, enable == true ? 1 : 0);\n        }\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern int GetShaderChunkSizeInMBForPlatform(BuildTarget buildTarget);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern void SetShaderChunkSizeInMBForPlatform(BuildTarget buildTarget, int sizeInMegabytes);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern int GetShaderChunkCountForPlatform(BuildTarget buildTarget);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern void SetShaderChunkCountForPlatform(BuildTarget buildTarget, int chunkCount);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern int GetDefaultShaderChunkSizeInMB();\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern void SetDefaultShaderChunkSizeInMB(int sizeInMegabytes);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern int GetDefaultShaderChunkCount();\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern void SetDefaultShaderChunkCount(int chunkCount);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern bool GetOverrideShaderChunkSettingsForPlatform(BuildTarget buildTarget);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern void SetOverrideShaderChunkSettingsForPlatform(BuildTarget buildTarget, bool value);\n\n        [NativeMethod(\"GetLightmapEncodingQuality\")]\n        internal static extern LightmapEncodingQuality GetLightmapEncodingQualityForPlatform(BuildTarget platform);\n\n        [NativeMethod(\"SetLightmapEncodingQuality\")]\n        internal static extern void SetLightmapEncodingQualityForPlatform(BuildTarget platform, LightmapEncodingQuality encodingQuality);\n\n        [NativeMethod(\"GetHDRCubemapEncodingQuality\")]\n        internal static extern HDRCubemapEncodingQuality GetHDRCubemapEncodingQualityForPlatform(BuildTarget platform);\n\n        [NativeMethod(\"SetHDRCubemapEncodingQuality\")]\n        internal static extern void SetHDRCubemapEncodingQualityForPlatform(BuildTarget platform, HDRCubemapEncodingQuality encodingQuality);\n\n        [FreeFunction(\"GetTargetPlatformGraphicsAPIAvailability\")]\n        internal static extern UnityEngine.Rendering.GraphicsDeviceType[] GetSupportedGraphicsAPIs(BuildTarget platform);\n\n        [NativeMethod(\"GetPlatformGraphicsAPIs\")]\n        public static extern UnityEngine.Rendering.GraphicsDeviceType[] GetGraphicsAPIs(BuildTarget platform);\n\n        public static void SetGraphicsAPIs(BuildTarget platform, UnityEngine.Rendering.GraphicsDeviceType[] apis)\n        {\n            SetGraphicsAPIsImpl(platform, apis);\n            // we do cache api list in player settings editor, so if we update from script we should forcibly update cache\n            PlayerSettingsEditor.SyncEditors(platform);\n        }\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        private static extern void SetGraphicsAPIsImpl(BuildTarget platform, UnityEngine.Rendering.GraphicsDeviceType[] apis);\n\n        [NativeMethod(\"GetPlatformAutomaticGraphicsAPIs\")]\n        public static extern bool GetUseDefaultGraphicsAPIs(BuildTarget platform);\n\n        public static void SetUseDefaultGraphicsAPIs(BuildTarget platform, bool automatic)\n        {\n            SetUseDefaultGraphicsAPIsImpl(platform, automatic);\n            // we do cache api list in player settings editor, so if we update from script we should forcibly update cache\n            PlayerSettingsEditor.SyncEditors(platform);\n        }\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        private static extern void SetUseDefaultGraphicsAPIsImpl(BuildTarget platform, bool automatic);\n\n        // Set the output color space for the current project. This setting only\n        // defines the format of the final framebuffer and render textures\n        internal static extern ColorGamut[] GetColorGamuts();\n\n        internal static void SetColorGamuts(ColorGamut[] colorSpaces)\n        {\n            SetColorGamutsImpl(colorSpaces);\n            // Color space data is cached in player settings editor\n            PlayerSettingsEditor.SyncEditors(BuildTarget.NoTarget);\n        }\n\n        [NativeMethod(\"SetColorGamuts\")]\n        private static extern void SetColorGamutsImpl(ColorGamut[] colorSpaces);\n\n        internal static extern string[] templateCustomKeys { get; set; }\n\n        public static extern void SetTemplateCustomValue(string name, string value);\n\n        public static extern string GetTemplateCustomValue(string name);\n\n        internal static extern string spritePackerPolicy\n        {\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly().spritePackerPolicy\")]\n            [NativeMethod(\"c_str\")]\n            get;\n\n            [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n            set;\n        }\n\n        // TargetGroup no longer defines the entire build targets space. Now build targets are better\n        // identified by a string key (wrapped into NamedBuildTarget), so all the following methods are being replaced.\n\n        [Obsolete(\"Use GetScriptingDefineSymbols(NamedBuildTarget buildTarget) instead\")]\n        public static string GetScriptingDefineSymbolsForGroup(BuildTargetGroup targetGroup) =>\n            GetScriptingDefineSymbols(NamedBuildTarget.FromBuildTargetGroup(targetGroup));\n\n        [Obsolete(\"Use GetScriptingDefineSymbols(NamedBuildTarget buildTarget, out string[] defines) instead\")]\n        public static void GetScriptingDefineSymbolsForGroup(BuildTargetGroup targetGroup, out string[] defines) =>\n            defines = ScriptingDefinesHelper.ConvertScriptingDefineStringToArray(GetScriptingDefineSymbolsForGroup(targetGroup));\n\n        [Obsolete(\"Use SetScriptingDefineSymbols(NamedBuildTarget buildTarget, string defines) instead\")]\n        public static void SetScriptingDefineSymbolsForGroup(BuildTargetGroup targetGroup, string defines) =>\n            SetScriptingDefineSymbols(NamedBuildTarget.FromBuildTargetGroup(targetGroup), defines);\n\n        [Obsolete(\"Use SetScriptingDefineSymbols(NamedBuildTarget buildTarget, string[] defines) instead\")]\n        public static void SetScriptingDefineSymbolsForGroup(BuildTargetGroup targetGroup, string[] defines) =>\n            SetScriptingDefineSymbols(NamedBuildTarget.FromBuildTargetGroup(targetGroup), defines);\n\n        [Obsolete(\"Use GetAdditionalCompilerArguments(NamedBuildTarget buildTarget) instead\")]\n        public static string[] GetAdditionalCompilerArgumentsForGroup(BuildTargetGroup targetGroup) =>\n            GetAdditionalCompilerArguments(NamedBuildTarget.FromBuildTargetGroup(targetGroup));\n\n        [Obsolete(\"Use SetAdditionalCompilerArguments(NamedBuildTarget buildTarget, string[] additionalCompilerArguments) instead\")]\n        public static void SetAdditionalCompilerArgumentsForGroup(BuildTargetGroup targetGroup, string[] additionalCompilerArguments) =>\n            SetAdditionalCompilerArguments(NamedBuildTarget.FromBuildTargetGroup(targetGroup), additionalCompilerArguments);\n\n        [Obsolete(\"Use GetArchitecture(NamedBuildTarget buildTarget) instead\")]\n        public static int GetArchitecture(BuildTargetGroup targetGroup) =>\n            GetArchitecture(NamedBuildTarget.FromBuildTargetGroup(targetGroup));\n\n        [Obsolete(\"Use SetArchitecture(NamedBuildTarget buildTarget, int architecture) instead\")]\n        public static void SetArchitecture(BuildTargetGroup targetGroup, int architecture) =>\n            SetArchitecture(NamedBuildTarget.FromBuildTargetGroup(targetGroup), architecture);\n\n        [Obsolete(\"Use GetScriptingBackend(NamedBuildTarget buildTarget) instead\")]\n        public static ScriptingImplementation GetScriptingBackend(BuildTargetGroup targetGroup) =>\n            GetScriptingBackend(NamedBuildTarget.FromBuildTargetGroup(targetGroup));\n\n        [Obsolete(\"Use SetScriptingBackend(NamedBuildTarget buildTarget, ScriptingImplementation backend) instead\")]\n        public static void SetScriptingBackend(BuildTargetGroup targetGroup, ScriptingImplementation backend) =>\n            SetScriptingBackend(NamedBuildTarget.FromBuildTargetGroup(targetGroup), backend);\n\n        [Obsolete(\"Use GetDefaultScriptingBackend(NamedBuildTarget buildTarget) instead\")]\n        public static ScriptingImplementation GetDefaultScriptingBackend(BuildTargetGroup targetGroup) =>\n            GetDefaultScriptingBackend(NamedBuildTarget.FromBuildTargetGroup(targetGroup));\n\n        [Obsolete(\"Use GetApplicationIdentifier(NamedBuildTarget buildTarget) instead\")]\n        public static string GetApplicationIdentifier(BuildTargetGroup targetGroup) =>\n            GetApplicationIdentifier(NamedBuildTarget.FromBuildTargetGroup(targetGroup));\n\n        [Obsolete(\"Use SetApplicationIdentifier(NamedBuildTarget buildTarget, string identifier) instead\")]\n        public static void SetApplicationIdentifier(BuildTargetGroup targetGroup, string identifier) =>\n            SetApplicationIdentifier(NamedBuildTarget.FromBuildTargetGroup(targetGroup), identifier);\n\n        [Obsolete(\"Use GetIl2CppCompilerConfiguration(NamedBuildTarget buildTarget) instead\")]\n        public static Il2CppCompilerConfiguration GetIl2CppCompilerConfiguration(BuildTargetGroup targetGroup) =>\n            GetIl2CppCompilerConfiguration(NamedBuildTarget.FromBuildTargetGroup(targetGroup));\n\n        [Obsolete(\"Use SetIl2CppCompilerConfiguration(NamedBuildTarget buildTarget, Il2CppCompilerConfiguration configuration) instead\")]\n        public static void SetIl2CppCompilerConfiguration(BuildTargetGroup targetGroup, Il2CppCompilerConfiguration configuration) =>\n            SetIl2CppCompilerConfiguration(NamedBuildTarget.FromBuildTargetGroup(targetGroup), configuration);\n\n        [Obsolete(\"GetIncrementalIl2CppBuild has no impact on the build process\")]\n        public static bool GetIncrementalIl2CppBuild(BuildTargetGroup targetGroup) =>\n            GetIncrementalIl2CppBuild(NamedBuildTarget.FromBuildTargetGroup(targetGroup));\n\n        [Obsolete(\"SetIncrementalIl2CppBuild has no impact on the build process\")]\n        public static void SetIncrementalIl2CppBuild(BuildTargetGroup targetGroup, bool enabled) =>\n            SetIncrementalIl2CppBuild(NamedBuildTarget.FromBuildTargetGroup(targetGroup), enabled);\n\n        [Obsolete(\"Use SetManagedStrippingLevel(NamedBuildTarget buildTarget, ManagedStrippingLevel level) instead\")]\n        public static void SetManagedStrippingLevel(BuildTargetGroup targetGroup, ManagedStrippingLevel level) =>\n            SetManagedStrippingLevel(NamedBuildTarget.FromBuildTargetGroup(targetGroup), level);\n\n        [Obsolete(\"Use GetManagedStrippingLevel(NamedBuildTarget buildTarget) instead\")]\n        public static ManagedStrippingLevel GetManagedStrippingLevel(BuildTargetGroup targetGroup) =>\n            GetManagedStrippingLevel(NamedBuildTarget.FromBuildTargetGroup(targetGroup));\n\n        [Obsolete(\"Use GetApiCompatibilityLevel(NamedBuildTarget buildTarget) instead\")]\n        public static ApiCompatibilityLevel GetApiCompatibilityLevel(BuildTargetGroup buildTargetGroup) =>\n            GetApiCompatibilityLevel(NamedBuildTarget.FromBuildTargetGroup(buildTargetGroup));\n\n        [Obsolete(\"Use SetApiCompatibilityLevel(NamedBuildTarget buildTarget, ApiCompatibilityLevel value) instead\")]\n        public static void SetApiCompatibilityLevel(BuildTargetGroup buildTargetGroup, ApiCompatibilityLevel value) =>\n            SetApiCompatibilityLevel(NamedBuildTarget.FromBuildTargetGroup(buildTargetGroup), value);\n\n        [Obsolete(\"Use GetMobileMTRendering(NamedBuildTarget buildTarget) instead\")]\n        public static bool GetMobileMTRendering(BuildTargetGroup targetGroup) =>\n            GetMobileMTRendering(NamedBuildTarget.FromBuildTargetGroup(targetGroup));\n\n        [Obsolete(\"Use SetMobileMTRendering(NamedBuildTarget buildTarget, bool enable) instead\")]\n        public static void SetMobileMTRendering(BuildTargetGroup targetGroup, bool enable) =>\n            SetMobileMTRendering(NamedBuildTarget.FromBuildTargetGroup(targetGroup), enable);\n\n        [Obsolete(\"Use GetNormalMapEncoding(NamedBuildTarget buildTarget) instead\")]\n        public static NormalMapEncoding GetNormalMapEncoding(BuildTargetGroup platform) =>\n            GetNormalMapEncoding(NamedBuildTarget.FromBuildTargetGroup(platform));\n\n        [Obsolete(\"Use SetNormalMapEncoding(NamedBuildTarget buildTarget, NormalMapEncoding encoding) instead\")]\n        public static void SetNormalMapEncoding(BuildTargetGroup platform, NormalMapEncoding encoding) =>\n            SetNormalMapEncoding(NamedBuildTarget.FromBuildTargetGroup(platform), encoding);\n\n\n        // Get user-specified symbols for script compilation for the given build target name.\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        [NativeMethod(\"GetUserScriptingDefineSymbols\")]\n        private static extern string GetScriptingDefineSymbolsInternal(string buildTargetName);\n        public static string GetScriptingDefineSymbols(NamedBuildTarget buildTarget) =>\n            GetScriptingDefineSymbolsInternal(buildTarget.TargetName);\n        public static void GetScriptingDefineSymbols(NamedBuildTarget buildTarget, out string[] defines) =>\n            defines = ScriptingDefinesHelper.ConvertScriptingDefineStringToArray(GetScriptingDefineSymbols(buildTarget));\n\n        // Set user-specified symbols for script compilation for the given build target group.\n        public static void SetScriptingDefineSymbols(NamedBuildTarget buildTarget, string defines)\n        {\n            if (!string.IsNullOrEmpty(defines))\n                defines = string.Join(\";\", ScriptingDefinesHelper.ConvertScriptingDefineStringToArray(defines));\n\n            BuildProfileContext.UpdateScriptingDefineSymbolsInActivePlayerSettingsOverride(buildTarget, defines);\n\n            SetScriptingDefineSymbolsInternal(buildTarget.TargetName, defines);\n        }\n\n        public static void SetScriptingDefineSymbols(NamedBuildTarget buildTarget, string[] defines)\n        {\n            if (defines == null)\n                throw new ArgumentNullException(nameof(defines));\n\n            SetScriptingDefineSymbols(buildTarget, ScriptingDefinesHelper.ConvertScriptingDefineArrayToString(defines));\n        }\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        [NativeMethod(\"SetUserScriptingDefineSymbols\")]\n        private static extern void SetScriptingDefineSymbolsInternal(string buildTargetName, string defines);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        [NativeMethod(\"GetAdditionalCompilerArguments\")]\n        private static extern string[] GetAdditionalCompilerArgumentsInternal(string buildTargetName);\n        public static string[] GetAdditionalCompilerArguments(NamedBuildTarget buildTarget) =>\n            GetAdditionalCompilerArgumentsInternal(buildTarget.TargetName);\n\n        public static void SetAdditionalCompilerArguments(NamedBuildTarget buildTarget, string[] additionalCompilerArguments)\n        {\n            if (additionalCompilerArguments == null)\n                throw new ArgumentNullException(nameof(additionalCompilerArguments));\n\n            SetAdditionalCompilerArgumentsInternal(buildTarget.TargetName, additionalCompilerArguments);\n        }\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        [NativeMethod(\"SetAdditionalCompilerArguments\")]\n        private static extern void SetAdditionalCompilerArgumentsInternal(string buildTargetName, string[] additionalCompilerArguments);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        [NativeMethod(\"GetPlatformArchitecture\")]\n        private static extern int GetArchitectureInternal(string buildTargetName);\n        public static int GetArchitecture(NamedBuildTarget buildTarget) => GetArchitectureInternal(buildTarget.TargetName);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        [NativeMethod(\"SetPlatformArchitecture\")]\n        private static extern void SetArchitectureInternal(string buildTargetName, int architecture);\n        public static void SetArchitecture(NamedBuildTarget buildTarget, int architecture) =>\n            SetArchitectureInternal(buildTarget.TargetName, architecture);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        [NativeMethod(\"GetPlatformScriptingBackend\")]\n        private static extern ScriptingImplementation GetScriptingBackendInternal(string buildTargetName);\n        public static ScriptingImplementation GetScriptingBackend(NamedBuildTarget buildTarget) =>\n            GetScriptingBackendInternal(buildTarget.TargetName);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        [NativeMethod(\"SetPlatformScriptingBackend\")]\n        private static extern void SetScriptingBackendInternal(string buildTargetName, ScriptingImplementation backend);\n        public static void SetScriptingBackend(NamedBuildTarget buildTarget, ScriptingImplementation backend) =>\n            SetScriptingBackendInternal(buildTarget.TargetName, backend);\n\n        [FreeFunction(\"GetDefaultScriptingBackendForGroup\")]\n        internal static extern ScriptingImplementation GetDefaultScriptingBackendForGroup(BuildTargetGroup targetGroup);\n        public static ScriptingImplementation GetDefaultScriptingBackend(NamedBuildTarget buildTarget)\n        {\n            return GetDefaultScriptingBackendForGroup(buildTarget.ToBuildTargetGroup());\n        }\n\n        [NativeThrows]\n        [NativeMethod(\"GetCaptureStartupLogs\")]\n        private static extern bool GetCaptureStartupLogsInternal(string buildTargetName);\n        public static bool GetCaptureStartupLogs(NamedBuildTarget buildTarget) =>\n            GetCaptureStartupLogsInternal(buildTarget.TargetName);\n\n        [NativeThrows]\n        [NativeMethod(\"SetCaptureStartupLogs\")]\n        private static extern void SetCaptureStartupLogsInternal(string buildTargetName, bool enable);\n        public static void SetCaptureStartupLogs(NamedBuildTarget buildTarget, bool enable) =>\n            SetCaptureStartupLogsInternal(buildTarget.TargetName, enable);\n\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        internal static extern bool IsApplicationIdentifierValid(string name, BuildTargetGroup targetGroup);\n\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        internal static extern string SanitizeApplicationIdentifier(string name, BuildTargetGroup targetGroup);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        [NativeMethod(\"SetApplicationIdentifier\")]\n        private static extern void SetApplicationIdentifierInternal(string buildTargetName, string identifier);\n        public static void SetApplicationIdentifier(NamedBuildTarget buildTarget, string identifier) =>\n            SetApplicationIdentifierInternal(buildTarget.TargetName, identifier);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        [NativeMethod(\"GetApplicationIdentifier\")]\n        private static extern string GetApplicationIdentifierInternal(string buildTargetName);\n        public static string GetApplicationIdentifier(NamedBuildTarget buildTarget) =>\n            GetApplicationIdentifierInternal(buildTarget.TargetName);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        [NativeMethod(\"GetApplicationBuildNumber\")]\n        internal static extern string GetBuildNumber(string buildTargetName);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        [NativeMethod(\"SetApplicationBuildNumber\")]\n        internal static extern void SetBuildNumber(string buildTargetName, string buildNumber);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        [NativeMethod(\"SetIl2CppCompilerConfiguration\")]\n        private static extern void SetIl2CppCompilerConfigurationInternal(string buildTargetName, Il2CppCompilerConfiguration configuration);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        [NativeMethod(\"GetIl2CppCompilerConfiguration\")]\n        private static extern Il2CppCompilerConfiguration GetIl2CppCompilerConfigurationInternal(string buildTargetName);\n        public static Il2CppCompilerConfiguration GetIl2CppCompilerConfiguration(NamedBuildTarget buildTarget) =>\n            GetIl2CppCompilerConfigurationInternal(buildTarget.TargetName);\n\n        public static void SetIl2CppCompilerConfiguration(NamedBuildTarget buildTarget, Il2CppCompilerConfiguration configuration)\n        {\n            var scriptingImpl = ModuleManager.GetScriptingImplementations(buildTarget);\n            if (scriptingImpl != null && !scriptingImpl.AllowIL2CPPCompilerConfigurationSelection())\n            {\n                Debug.LogWarning($\"The C++ compiler configuration option does not apply to the {buildTarget.TargetName} platform as it is configured. Set the configuration in the generated IDE project instead.\");\n                return;\n            }\n\n            SetIl2CppCompilerConfigurationInternal(buildTarget.TargetName, configuration);\n        }\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        [NativeMethod(\"GetIl2CppStacktraceInformation\")]\n        private static extern Il2CppStacktraceInformation GetIl2CppStacktraceInformationInternal(string buildTargetName);\n        public static Il2CppStacktraceInformation GetIl2CppStacktraceInformation(NamedBuildTarget buildTarget) =>\n            GetIl2CppStacktraceInformationInternal(buildTarget.TargetName);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        [NativeMethod(\"SetIl2CppStacktraceInformation\")]\n        private static extern void SetIl2CppStacktraceInformationInternal(string buildTargetName, Il2CppStacktraceInformation option);\n        public static void SetIl2CppStacktraceInformation(NamedBuildTarget buildTarget, Il2CppStacktraceInformation option)\n        {\n            if (buildTarget == NamedBuildTarget.WebGL && option == Il2CppStacktraceInformation.MethodFileLineNumber)\n            {\n                Debug.LogWarning(\"The \\\"Method Name, File Name, and Line Number\\\" option for IL2CPP stack traces is not supported on WebGL.\");\n                option = Il2CppStacktraceInformation.MethodOnly;\n            }\n            SetIl2CppStacktraceInformationInternal(buildTarget.TargetName, option);\n        }\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        [NativeMethod(\"GetPlatformIncrementalIl2CppBuild\")]\n        private static extern bool GetIncrementalIl2CppBuildInternal(string buildTargetName);\n        [Obsolete(\"GetIncrementalIl2CppBuild has no impact on the build process\")]\n        public static bool GetIncrementalIl2CppBuild(NamedBuildTarget buildTarget) => GetIncrementalIl2CppBuildInternal(buildTarget.TargetName);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        [NativeMethod(\"SetPlatformIncrementalIl2CppBuild\")]\n        private static extern void SetIncrementalIl2CppBuildInternal(string buildTargetName, bool enabled);\n        [Obsolete(\"SetIncrementalIl2CppBuild has no impact on the build process\")]\n        public static void SetIncrementalIl2CppBuild(NamedBuildTarget buildTarget, bool enabled) =>\n            SetIncrementalIl2CppBuildInternal(buildTarget.TargetName, enabled);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        [NativeMethod(\"SetManagedStrippingLevel\")]\n        private static extern void SetManagedStrippingLevelInternal(string buildTargetName, ManagedStrippingLevel level);\n        public static void SetManagedStrippingLevel(NamedBuildTarget buildTarget, ManagedStrippingLevel level) =>\n            SetManagedStrippingLevelInternal(buildTarget.TargetName, level);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        [NativeMethod(\"GetManagedStrippingLevel\")]\n        private static extern ManagedStrippingLevel GetManagedStrippingLevelInternal(string buildTargetName);\n        public static ManagedStrippingLevel GetManagedStrippingLevel(NamedBuildTarget buildTarget) => GetManagedStrippingLevelInternal(buildTarget.TargetName);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        [NativeMethod(\"GetApiCompatibilityLevel\")]\n        private static extern ApiCompatibilityLevel GetApiCompatibilityLevelInternal(string buildTargetName);\n        public static ApiCompatibilityLevel GetApiCompatibilityLevel(NamedBuildTarget buildTarget) => GetApiCompatibilityLevelInternal(buildTarget.TargetName);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        [NativeMethod(\"SetApiCompatibilityLevel\")]\n        private static extern void SetApiCompatibilityLevelInternal(string buildTargetName, ApiCompatibilityLevel value);\n        public static void SetApiCompatibilityLevel(NamedBuildTarget buildTarget, ApiCompatibilityLevel value) =>\n            SetApiCompatibilityLevelInternal(buildTarget.TargetName, value);\n\n        internal static extern bool defaultEditorAssembliesCompatibilityLevel\n        {\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n            get;\n        }\n\n        internal static ApiCompatibilityLevel EditorAssemblyCompatibilityToApiCompatibility(EditorAssembliesCompatibilityLevel level)\n        {\n            switch (level)\n            {\n                case EditorAssembliesCompatibilityLevel.NET_Standard:\n                    {\n                        return ApiCompatibilityLevel.NET_Standard_2_0;\n                    }\n                default:\n                    {\n                        return ApiCompatibilityLevel.NET_Unity_4_8;\n                    }\n            }\n        }\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        [NativeMethod(\"GetEditorAssembliesCompatibilityLevel\")]\n        private static extern EditorAssembliesCompatibilityLevel GetEditorAssembliesCompatibilityLevelInternal();\n        public static EditorAssembliesCompatibilityLevel GetEditorAssembliesCompatibilityLevel() => GetEditorAssembliesCompatibilityLevelInternal();\n\n        [NativeMethod(\"GetEditorOnly().HasAnyNetFXCompatibilityLevel\")]\n        private extern bool HasAnyNetFXCompatibilityLevelInternal();\n\n        internal bool HasAnyNetFXCompatibilityLevel()\n        {\n            return HasAnyNetFXCompatibilityLevelInternal();\n        }\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        [NativeMethod(\"SetEditorAssembliesCompatibilityLevel\")]\n        private static extern void SetEditorAssembliesCompatibilityLevelInternal(EditorAssembliesCompatibilityLevel value);\n        public static void SetEditorAssembliesCompatibilityLevel(EditorAssembliesCompatibilityLevel value) => SetEditorAssembliesCompatibilityLevelInternal(value);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        [NativeMethod(\"GetIl2CppCodeGeneration\")]\n        private static extern Il2CppCodeGeneration GetIl2CppCodeGenerationInternal(string buildTargetName);\n        public static Il2CppCodeGeneration GetIl2CppCodeGeneration(NamedBuildTarget buildTarget) => GetIl2CppCodeGenerationInternal(buildTarget.TargetName);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        [NativeMethod(\"SetIl2CppCodeGeneration\")]\n        private static extern void SetIl2CppCodeGenerationInternal(string buildTargetName, Il2CppCodeGeneration value);\n        public static void SetIl2CppCodeGeneration(NamedBuildTarget buildTarget, Il2CppCodeGeneration value) =>\n            SetIl2CppCodeGenerationInternal(buildTarget.TargetName, value);\n\n        [NativeThrows]\n        [NativeMethod(\"SetMobileMTRendering\")]\n        private static extern void SetMobileMTRenderingInternal(string buildTargetName, bool enable);\n        public static void SetMobileMTRendering(NamedBuildTarget buildTarget, bool enable) =>\n            SetMobileMTRenderingInternal(buildTarget.TargetName, enable);\n\n        [NativeThrows]\n        [NativeMethod(\"GetMobileMTRendering\")]\n        private static extern bool GetMobileMTRenderingInternal(string buildTargetName);\n        public static bool GetMobileMTRendering(NamedBuildTarget buildTarget) => GetMobileMTRenderingInternal(buildTarget.TargetName);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        [NativeMethod(\"GetNormalMapEncoding\")]\n        private static extern NormalMapEncoding GetNormalMapEncodingInternal(string buildTargetName);\n        public static NormalMapEncoding GetNormalMapEncoding(NamedBuildTarget buildTarget) => GetNormalMapEncodingInternal(buildTarget.TargetName);\n\n        [NativeThrows]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        [NativeMethod(\"SetNormalMapEncoding\")]\n        private static extern void SetNormalMapEncodingInternal(string buildTargetName, NormalMapEncoding encoding);\n        public static void SetNormalMapEncoding(NamedBuildTarget buildTarget, NormalMapEncoding encoding) =>\n            SetNormalMapEncodingInternal(buildTarget.TargetName, encoding);\n\n        [Obsolete(\"assemblyVersionValidation has been deprecated due to the introduction of binding redirects\")]\n        public static bool assemblyVersionValidation\n        {\n            get => false;\n            set { }\n        }\n\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly().additionalIl2CppArgs\")]\n        [NativeMethod(\"c_str\")]\n        public static extern string GetAdditionalIl2CppArgs();\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern void SetAdditionalIl2CppArgs(string additionalArgs);\n\n        [Obsolete(\"ScriptingRuntimeVersion has been deprecated in 2019.3 due to the removal of legacy mono\")]\n        public static ScriptingRuntimeVersion scriptingRuntimeVersion\n        {\n            get { return ScriptingRuntimeVersion.Latest; }\n\n            set {}\n        }\n\n        public static extern bool suppressCommonWarnings\n        {\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n            get;\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n            set;\n        }\n\n        public static extern bool allowUnsafeCode\n        {\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n            get;\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n            set;\n        }\n\n        internal static extern bool UseDeterministicCompilation\n        {\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n            get;\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n            set;\n        }\n\n        [Obsolete(\"Use of reference assemblies is always enabled\")]\n        public static bool useReferenceAssemblies\n        {\n            get { return true; }\n            set {}\n        }\n\n        internal static extern bool gcWBarrierValidation\n        {\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n            get;\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n            set;\n        }\n\n        public static extern bool gcIncremental\n        {\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n            get;\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n            set;\n        }\n\n        // Xbox 360 title id\n        [Obsolete(\"Xbox 360 has been removed in >=5.5\")]\n        public static string xboxTitleId\n        {\n            get { return String.Empty; }\n            set {}\n        }\n\n        // Xbox 360 ImageXex override configuration file path\n        [Obsolete(\"Xbox 360 has been removed in >=5.5\")]\n        public static string xboxImageXexFilePath\n        {\n            get { return String.Empty; }\n        }\n\n        // Xbox 360 SPA file path\n        [Obsolete(\"Xbox 360 has been removed in >=5.5\")]\n        public static string xboxSpaFilePath\n        {\n            get { return String.Empty; }\n        }\n\n        // Xbox 360 auto-generation of _SPAConfig.cs\n        [Obsolete(\"Xbox 360 has been removed in >=5.5\")]\n        public static bool xboxGenerateSpa\n        {\n            get { return false; }\n        }\n\n        // Xbox 360 Enable XboxLive guest accounts\n        [Obsolete(\"Xbox 360 has been removed in >=5.5\")]\n        public static bool xboxEnableGuest\n        {\n            get { return false; }\n        }\n\n        // Xbox 360 Kinect resource file deployment\n        [Obsolete(\"Xbox 360 has been removed in >=5.5\")]\n        public static bool xboxDeployKinectResources\n        {\n            get { return false; }\n        }\n\n        // Xbox 360 Kinect Head Orientation file deployment\n        [Obsolete(\"Xbox 360 has been removed in >=5.5\")]\n        public static bool xboxDeployKinectHeadOrientation\n        {\n            get { return false; }\n            set {}\n        }\n\n        // Xbox 360 Kinect Head Position file deployment\n        [Obsolete(\"Xbox 360 has been removed in >=5.5\")]\n        public static bool xboxDeployKinectHeadPosition\n        {\n            get { return false; }\n            set {}\n        }\n\n        // Xbox 360 splash screen\n        [Obsolete(\"Xbox 360 has been removed in >=5.5\")]\n        public static Texture2D xboxSplashScreen\n        {\n            get { return null; }\n        }\n\n        [Obsolete(\"Xbox 360 has been removed in >=5.5\")]\n        public static int xboxAdditionalTitleMemorySize\n        {\n            get { return 0; }\n            set {}\n        }\n\n        // Xbox 360 Kinect title flag - if false, the Kinect APIs are inactive\n        [Obsolete(\"Xbox 360 has been removed in >=5.5\")]\n        public static bool xboxEnableKinect\n        {\n            get { return false; }\n        }\n\n        // Xbox 360 Kinect automatic skeleton tracking.\n        [Obsolete(\"Xbox 360 has been removed in >=5.5\")]\n        public static bool xboxEnableKinectAutoTracking\n        {\n            get { return false; }\n        }\n\n        // Xbox 360 Kinect Enable Speech Engine\n        [Obsolete(\"Xbox 360 has been removed in >=5.5\")]\n        public static bool xboxEnableSpeech\n        {\n            get { return false; }\n        }\n\n        // Xbox 360 Kinect Speech DB\n        [Obsolete(\"Xbox 360 has been removed in >=5.5\")]\n        public static UInt32 xboxSpeechDB\n        {\n            get { return 0; }\n        }\n\n        [NativeProperty(\"GPUSkinning\")]\n        public static extern bool gpuSkinning { get; set; }\n\n        [NativeProperty(\"MeshDeformation\")]\n        public static extern MeshDeformation meshDeformation { get; set; }\n\n        public static bool graphicsJobs\n        {\n            get { return GetGraphicsJobsForPlatform(EditorUserBuildSettings.activeBuildTarget); }\n            set { SetGraphicsJobsForPlatform(EditorUserBuildSettings.activeBuildTarget, value); }\n        }\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern bool GetGraphicsJobsForPlatform(BuildTarget platform);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetGraphicsJobsForPlatform(BuildTarget platform, bool graphicsJobs);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern bool GetEditorGfxJobOverride();\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetEditorGfxJobOverride(bool gfxJobsAllow);\n\n        public static GraphicsJobMode graphicsJobMode\n        {\n            get { return GetGraphicsJobModeForPlatform(EditorUserBuildSettings.activeBuildTarget); }\n            set { SetGraphicsJobModeForPlatform(EditorUserBuildSettings.activeBuildTarget, value); }\n        }\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern GraphicsJobMode GetGraphicsJobModeForPlatform(BuildTarget platform);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetGraphicsJobModeForPlatform(BuildTarget platform, GraphicsJobMode gfxJobMode);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern GfxThreadingMode GetGraphicsThreadingModeForPlatform(BuildTarget platform);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetGraphicsThreadingModeForPlatform(BuildTarget platform, GfxThreadingMode gfxJobMode);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern bool GetSwitchGraphicsJobsSyncAfterKick();\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetSwitchGraphicsJobsSyncAfterKick(bool syncAfterKick);\n\n        [StaticAccessor(\"GetPlayerSettings()\")]\n        public static extern bool GetWsaHolographicRemotingEnabled();\n\n        [StaticAccessor(\"GetPlayerSettings()\")]\n        public static extern void SetWsaHolographicRemotingEnabled(bool enabled);\n\n        // Xbox 360 Pix Texture Capture\n        public static extern bool xboxPIXTextureCapture { get; }\n\n        // Xbox 360 Avatars\n        public static extern bool xboxEnableAvatar { get; }\n\n        // Xbox One resolution options\n        public static extern int xboxOneResolution { get; }\n\n        /// Whether internal profiler is enabled on iOS\n        public static extern bool enableInternalProfiler { get; set; }\n\n        /// What to do on unhandled .NET exceptions on iOS\n        [Obsolete(\"Non-functional. The property will be removed in a future release.\")]\n        public static extern ActionOnDotNetUnhandledException actionOnDotNetUnhandledException { get; set; }\n\n        /// Whether to log Objective-C uncaught exceptions on iOS\n        public static extern bool logObjCUncaughtExceptions { get; set; }\n\n        /// Whether to enable the Crash Reporter API on iOS\n        public static extern bool enableCrashReportAPI { get; set; }\n\n        // Application (before 5.6 bundle) identifier was shared between iOS, Android and Tizen TV platforms before 5.6.\n        public static string applicationIdentifier\n        {\n            get { return GetApplicationIdentifier(NamedBuildTarget.FromActiveSettings(EditorUserBuildSettings.activeBuildTarget)); }\n            set\n            {\n                Debug.LogWarning(\"PlayerSettings.applicationIdentifier only changes the identifier for the currently active platform. Please use SetApplicationIdentifier to set it for any platform\");\n                SetApplicationIdentifier(NamedBuildTarget.FromActiveSettings(EditorUserBuildSettings.activeBuildTarget), value);\n            }\n        }\n\n        // Application bundle version for the VisionOS platform\n        [NativeProperty(\"VisionOSApplicationVersion\")]\n        public static extern string visionOSBundleVersion { get; set; }\n\n        // Application bundle version for the TVOS platform\n        [NativeProperty(\"TVOSApplicationVersion\")]\n        public static extern string tvOSBundleVersion { get; set; }\n\n        // Application bundle version shared between iOS & Android platforms\n        [NativeProperty(\"ApplicationVersion\")]\n        public static extern string bundleVersion { get; set; }\n\n        // Should status bar be hidden. Shared between iOS & Android platforms\n        [NativeProperty(\"UIStatusBarHidden\")]\n        public static extern bool statusBarHidden { get; set; }\n\n        // Code stripping level\n        [Obsolete(\"strippingLevel is deprecated, Use PlayerSettings.GetManagedStrippingLevel()/PlayerSettings.SetManagedStrippingLevel() instead. StripByteCode and UseMicroMSCorlib are no longer supported.\")]\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern StrippingLevel strippingLevel { get; set; }\n\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        internal static extern void ReinitialiseShaderCompiler(string platformSDKEnvVar, string EnvVarValue);\n\n        // Strip Engine code\n        public static extern bool stripEngineCode { get; set; }\n\n        // Default screen orientation for mobiles\n        [NativeProperty(\"DefaultScreenOrientation\")]\n        public static extern UIOrientation defaultInterfaceOrientation { get; set; }\n\n        // Is auto-rotation to portrait supported?\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern bool allowedAutorotateToPortrait { get; set; }\n\n        // Is auto-rotation to portrait upside-down supported?\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern bool allowedAutorotateToPortraitUpsideDown { get; set; }\n\n        // Is auto-rotation to landscape right supported?\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern bool allowedAutorotateToLandscapeRight { get; set; }\n\n        // Is auto-rotation to landscape left supported?\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern bool allowedAutorotateToLandscapeLeft { get; set; }\n\n        // Let the OS autorotate the screen as the device orientation changes.\n        [NativeProperty(\"UseAnimatedAutoRotation\")]\n        public static extern bool useAnimatedAutorotation { get; set; }\n\n        // 32-bit Display Buffer is used\n        public static extern bool use32BitDisplayBuffer { get; set; }\n\n        // Preserve framebuffer alpha, iOS and Android only. Enables rendering Unity on top of native UI.\n        public static extern bool preserveFramebufferAlpha { get; set; }\n\n        // .NET API compatibility level\n        [Obsolete(\"apiCompatibilityLevel is deprecated. Use PlayerSettings.GetApiCompatibilityLevel()/PlayerSettings.SetApiCompatibilityLevel() instead.\")]\n        public static ApiCompatibilityLevel apiCompatibilityLevel\n        {\n            get { return GetApiCompatibilityLevel(EditorUserBuildSettings.activeBuildTargetGroup); }\n            set { SetApiCompatibilityLevel(EditorUserBuildSettings.activeBuildTargetGroup, value); }\n        }\n\n        // Should unused [[Mesh]] components be excluded from game build?\n        public static extern bool stripUnusedMeshComponents { get; set; }\n\n        // Don't do fuzzy variant selection in the player. If the requested variant is not there, use error shader.\n        public static extern bool strictShaderVariantMatching { get; set; }\n\n        // Should unused mips be excluded from texture build?\n        public static extern bool mipStripping { get; set; }\n\n        // Is the advanced version being used?\n        [StaticAccessor(\"GetBuildSettings()\")]\n        [NativeProperty(\"hasAdvancedVersion\", TargetType.Field)]\n        public static extern bool advancedLicense { get; }\n\n        // Additional AOT compilation options. Shared by AOT platforms.\n        [Obsolete(\"This setting is no longer used.\")]\n        public static extern string aotOptions { get; set; }\n\n        public static extern Texture2D defaultCursor { get; set; }\n\n        public static extern Vector2 cursorHotspot { get; set; }\n\n        // Accelerometer update frequency\n        public static extern int accelerometerFrequency { get; set; }\n\n        // Is multi-threaded rendering enabled?\n        public static extern bool MTRendering { get; set; }\n\n        [NativeMethod(\"GetStackTraceType\")]\n        public static extern StackTraceLogType GetStackTraceLogType(LogType logType);\n\n        [NativeMethod(\"SetStackTraceType\")]\n        public static extern void SetStackTraceLogType(LogType logType, StackTraceLogType stackTraceType);\n\n        [NativeMethod(\"GetGlobalStackTraceType\")]\n        internal static extern StackTraceLogType GetGlobalStackTraceLogType(LogType logType);\n\n        [NativeMethod(\"SetGlobalStackTraceType\")]\n        internal static extern void SetGlobalStackTraceLogType(LogType logType, StackTraceLogType stackTraceType);\n\n        [Obsolete(\"Use UnityEditor.PlayerSettings.SetGraphicsAPIs/GetGraphicsAPIs instead\")]\n        public static bool useDirect3D11\n        {\n            get { return GetUseDefaultGraphicsAPIs(BuildTarget.StandaloneWindows); }\n            set {}  // setter does nothing; D3D11 is always the fallback\n        }\n\n        internal static extern bool submitAnalytics { get; set; }\n\n        [Obsolete(\"Use VREditor.GetStereoDeviceEnabled instead\")]\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        public static extern bool stereoscopic3D { get; set; }\n\n        // Defines whether the application will request audio focus, muting all other audio sources.\n        public static extern bool muteOtherAudioSources { get; set; }\n\n        internal static extern bool playModeTestRunnerEnabled { get; set; }\n\n        internal static extern bool runPlayModeTestAsEditModeTest { get; set; }\n\n        // Defines whether the BlendShape weight range in SkinnedMeshRenderers is clamped\n        public static extern bool legacyClampBlendShapeWeights { get; set; }\n\n        // If enabled, metal API validation will be turned on in the editor\n        [NativeProperty(\"MetalAPIValidation\")]\n        public static extern bool enableMetalAPIValidation\n        {\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            get;\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            set;\n        }\n\n        [FreeFunction(\"GetPlayerSettings().GetLightmapStreamingEnabled\")]\n        internal static extern bool GetLightmapStreamingEnabledForPlatformGroup(BuildTargetGroup platformGroup);\n\n        [FreeFunction(\"GetPlayerSettings().SetLightmapStreamingEnabled\")]\n        internal static extern void SetLightmapStreamingEnabledForPlatformGroup(BuildTargetGroup platformGroup, bool lightmapStreamingEnabled);\n\n        [FreeFunction(\"GetPlayerSettings().GetLightmapStreamingPriority\")]\n        internal static extern int GetLightmapStreamingPriorityForPlatformGroup(BuildTargetGroup platformGroup);\n\n        [FreeFunction(\"GetPlayerSettings().SetLightmapStreamingPriority\")]\n        internal static extern void SetLightmapStreamingPriorityForPlatformGroup(BuildTargetGroup platformGroup, int lightmapStreamingPriority);\n\n        [FreeFunction(\"GetPlayerSettings().GetLoadStoreDebugModeEnabled\")]\n        internal static extern bool GetLoadStoreDebugModeEnabledForPlatformGroup(BuildTargetGroup platformGroup);\n\n        [FreeFunction(\"GetPlayerSettings().SetLoadStoreDebugModeEnabled\")]\n        internal static extern void SetLoadStoreDebugModeEnabledForPlatformGroup(BuildTargetGroup platformGroup, bool loadStoreDebugModeEnabled);\n\n        [FreeFunction(\"GetPlayerSettings().GetLoadStoreDebugModeEditorOnly\")]\n        internal static extern bool GetLoadStoreDebugModeEditorOnlyForPlatformGroup(BuildTargetGroup platformGroup);\n\n        [FreeFunction(\"GetPlayerSettings().SetLoadStoreDebugModeEditorOnly\")]\n        internal static extern void SetLoadStoreDebugModeEditorOnlyForPlatformGroup(BuildTargetGroup platformGroup, bool loadStoreDebugModeEnabled);\n\n        [FreeFunction(\"GetPlayerSettings().GetDisableOldInputManagerSupport\")]\n        internal static extern bool GetDisableOldInputManagerSupport();\n\n        [FreeFunction(\"GetPlayerSettings().GetWindowsGamepadBackendHint\")]\n        internal static extern WindowsGamepadBackendHint GetWindowsGamepadBackendHint();\n\n        [FreeFunction(\"GetPlayerSettings().SetWindowsGamepadBackendHint\")]\n        internal static extern void SetWindowsGamepadBackendHint(WindowsGamepadBackendHint value);\n\n        // The input API backend used on Windows platforms\n        public static WindowsGamepadBackendHint windowsGamepadBackendHint\n        {\n            get { return GetWindowsGamepadBackendHint(); }\n            set { SetWindowsGamepadBackendHint(value); }\n        }\n\n        [StaticAccessor(\"GetPlayerSettings()\")]\n        [NativeMethod(\"GetVirtualTexturingSupportEnabled\")]\n        public static extern bool GetVirtualTexturingSupportEnabled();\n\n        [StaticAccessor(\"GetPlayerSettings()\")]\n        [NativeMethod(\"SetVirtualTexturingSupportEnabled\")]\n        public static extern void SetVirtualTexturingSupportEnabled(bool enabled);\n\n        [StaticAccessor(\"GetPlayerSettings()\")]\n        [NativeMethod(\"OnVirtualTexturingChanged\")]\n        internal static extern bool OnVirtualTexturingChanged();\n\n        public static extern InsecureHttpOption insecureHttpOption { get; set; }\n\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        public static extern ShaderPrecisionModel GetShaderPrecisionModel();\n\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        public static extern void SetShaderPrecisionModel(ShaderPrecisionModel model);\n\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        internal static extern TextureCompressionFormat GetDefaultTextureCompressionFormat(BuildTarget platform);\n\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        internal static extern void SetDefaultTextureCompressionFormat(BuildTarget platform, TextureCompressionFormat format);\n\n        [NativeMethod(\"GetTextureCompressionFormats\")]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\")]\n        internal static extern TextureCompressionFormat[] GetTextureCompressionFormatsImpl(BuildTarget platform);\n\n        [NativeMethod(\"SetTextureCompressionFormats\")]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\")]\n        internal static extern void SetTextureCompressionFormatsImpl(BuildTarget platform, TextureCompressionFormat[] formats);\n\n        [FreeFunction(\"GetPlayerSettings().GetEditorOnly().RecompileScripts\")]\n        internal static extern void RecompileScripts(string reason, bool refreshProject = true);\n\n        internal static extern bool isHandlingScriptRecompile\n        {\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            get;\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            set;\n        }\n\n        // note that we dont expose it in ui (yet) and keep it hidden on purpose\n        // when the time comes we can totally rename this before making it public\n        [NativeProperty(\"IOSCopyPluginsCodeInsteadOfSymlink\")]\n        internal static extern bool iosCopyPluginsCodeInsteadOfSymlink\n        {\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            get;\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            set;\n        }\n\n        [StaticAccessor(\"PlayerSettings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetOverridePlayerSettingsInternal(PlayerSettings playerSettings);\n\n        [StaticAccessor(\"PlayerSettings\", StaticAccessorType.DoubleColon)]\n        internal static extern bool IsGlobalManagerPlayerSettings(PlayerSettings playerSettings);\n\n        [StaticAccessor(\"PlayerSettings\", StaticAccessorType.DoubleColon)]\n        internal static extern string SerializeAsYAMLString(PlayerSettings playerSettings);\n\n        [StaticAccessor(\"PlayerSettings\", StaticAccessorType.DoubleColon)]\n        internal static extern PlayerSettings DeserializeFromYAMLString(string yamlSettings);\n\n        [StaticAccessor(\"PlayerSettings\", StaticAccessorType.DoubleColon)]\n        internal static extern void UpdatePlayerSettingsObjectFromYAML(PlayerSettings playerSettings, string yamlSettings);\n\n        internal static extern bool platformRequiresReadableAssets { get; set; }\n\n        /*\n         * Internal instance methods used when accessing settings outside of the global static instance.\n         * Referenced by PlayerSettingsEditor when reading/writing to a non-active player settings object.\n         */\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern string GetScriptingDefineSymbols_Internal(PlayerSettings instance, string buildTargetName);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetScriptingDefineSymbols_Internal(PlayerSettings instance, string buildTargetName, string defines);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void GetBatchingForPlatform_Internal(PlayerSettings instance, BuildTarget platform, out int staticBatching, out int dynamicBatching);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetBatchingForPlatform_Internal(PlayerSettings instance, BuildTarget platform, int staticBatching, int dynamicBatching);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern int GetDefaultShaderChunkSizeInMB_Internal(PlayerSettings instance);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetDefaultShaderChunkSizeInMB_Internal(PlayerSettings instance, int sizeInMegabytes);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern int GetDefaultShaderChunkCount_Internal(PlayerSettings instance);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetDefaultShaderChunkCount_Internal(PlayerSettings instance, int chunkCount);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern bool GetOverrideShaderChunkSettingsForPlatform_Internal(PlayerSettings instance, BuildTarget buildTarget);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetOverrideShaderChunkSettingsForPlatform_Internal(PlayerSettings instance, BuildTarget buildTarget, bool value);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern int GetShaderChunkSizeInMBForPlatform_Internal(PlayerSettings instance, BuildTarget buildTarget);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetShaderChunkSizeInMBForPlatform_Internal(PlayerSettings instance, BuildTarget buildTarget, int sizeInMegabytes);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern int GetShaderChunkCountForPlatform_Internal(PlayerSettings instance, BuildTarget buildTarget);\n\n        // --- Graphics Job\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern bool GetGraphicsJobsForPlatform_Internal(PlayerSettings instance, BuildTarget platform);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetGraphicsJobsForPlatform_Internal(PlayerSettings instance, BuildTarget platform, bool graphicsJobs);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern GraphicsJobMode GetGraphicsJobModeForPlatform_Internal(PlayerSettings instance, BuildTarget platform);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetGraphicsJobModeForPlatform_Internal(PlayerSettings instance, BuildTarget platform, GraphicsJobMode gfxJobMode);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetGraphicsThreadingModeForPlatform_Internal(PlayerSettings instance, BuildTarget platform, GfxThreadingMode gfxJobMode);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetShaderChunkCountForPlatform_Internal(PlayerSettings instance, BuildTarget buildTarget, int chunkCount);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern NormalMapEncoding GetNormalMapEncoding_Internal(PlayerSettings instance, string platform);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetNormalMapEncoding_Internal(PlayerSettings instance, string platform, NormalMapEncoding encoding);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern ScriptingImplementation GetScriptingBackend_Internal(PlayerSettings playerSettings, string buildTargetGroupName);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern bool ShouldSyncShaderPrecisionModel(PlayerSettings prev, PlayerSettings next);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SyncShaderPrecisionModel();\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SyncVirtualTexturingState(PlayerSettings settings);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern PlayerSettingsRequiringRestart[] GetSettingsRequiringRestart(PlayerSettings prevSettings, PlayerSettings newSettings, BuildTarget prevBuildTarget, BuildTarget newBuildTarget);\n\n        /*\n         * Internal non-static getter/setters referenced when reading/writing to non-active player settings object.\n         */\n\n        [NativeMethod(\"GetLightmapStreamingEnabled\")]\n        internal extern bool GetLightmapStreamingEnabledForPlatformGroup_Internal(BuildTargetGroup platformGroup);\n\n        [NativeMethod(\"SetLightmapStreamingEnabled\")]\n        internal extern void SetLightmapStreamingEnabledForPlatformGroup_Internal(BuildTargetGroup platformGroup, bool lightmapStreamingEnabled);\n\n        [NativeMethod(\"GetLightmapStreamingPriority\")]\n        internal extern int GetLightmapStreamingPriorityForPlatformGroup_Internal(BuildTargetGroup platformGroup);\n\n        [NativeMethod(\"SetLightmapStreamingPriority\")]\n        internal extern void SetLightmapStreamingPriorityForPlatformGroup_Internal(BuildTargetGroup platformGroup, int lightmapStreamingPriority);\n\n        [NativeMethod(\"GetLightmapEncodingQuality\")]\n        internal extern LightmapEncodingQuality GetLightmapEncodingQualityForPlatform_Internal(BuildTarget platform);\n\n        [NativeMethod(\"SetLightmapEncodingQuality\")]\n        internal extern void SetLightmapEncodingQualityForPlatform_Internal(BuildTarget platform, LightmapEncodingQuality encodingQuality);\n\n        [NativeMethod(\"GetHDRCubemapEncodingQuality\")]\n        internal extern HDRCubemapEncodingQuality GetHDRCubemapEncodingQualityForPlatform_Internal(BuildTarget platform);\n\n        [NativeMethod(\"SetHDRCubemapEncodingQuality\")]\n        internal extern void SetHDRCubemapEncodingQualityForPlatform_Internal(BuildTarget platform, HDRCubemapEncodingQuality encodingQuality);\n\n\n        // Load / Store\n        [NativeMethod(\"GetLoadStoreDebugModeEnabled\")]\n        internal extern bool GetLoadStoreDebugModeEnabledForPlatformGroup_Internal(BuildTargetGroup platformGroup);\n\n        [NativeMethod(\"SetLoadStoreDebugModeEnabled\")]\n        internal extern void SetLoadStoreDebugModeEnabledForPlatformGroup_Internal(BuildTargetGroup platformGroup, bool loadStoreDebugModeEnabled);\n\n        [NativeMethod(\"GetLoadStoreDebugModeEditorOnly\")]\n        internal extern bool GetLoadStoreDebugModeEditorOnlyForPlatformGroup_Internal(BuildTargetGroup platformGroup);\n\n        [NativeMethod(\"SetLoadStoreDebugModeEditorOnly\")]\n        internal extern void SetLoadStoreDebugModeEditorOnlyForPlatformGroup_Internal(BuildTargetGroup platformGroup, bool loadStoreDebugModeEnabled);\n\n        // Mobile Rendering\n        [NativeThrows]\n        [NativeMethod(\"SetMobileMTRendering\")]\n        internal extern void SetMobileMTRenderingInternal_Instance(string buildTargetName, bool enable);\n\n        [NativeThrows]\n        [NativeMethod(\"GetMobileMTRendering\")]\n        internal extern bool GetMobileMTRenderingInternal_Instance(string buildTargetName);\n\n        // Graphics APIs\n        [NativeMethod(\"GetPlatformAutomaticGraphicsAPIs\")]\n        internal extern bool GetUseDefaultGraphicsAPIs_Internal(BuildTarget platform);\n\n        internal void SetUseDefaultGraphicsAPIs_Internal(BuildTarget platform, bool automatic)\n        {\n            SetUseDefaultGraphicsAPIsImpl_Internal(this, platform, automatic);\n            // we do cache api list in player settings editor, so if we update from script we should forcibly update cache\n            PlayerSettingsEditor.SyncEditors(platform);\n        }\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        private static extern void SetUseDefaultGraphicsAPIsImpl_Internal(PlayerSettings instance, BuildTarget platform, bool automatic);\n\n        [NativeMethod(\"GetPlatformGraphicsAPIs\")]\n        internal extern UnityEngine.Rendering.GraphicsDeviceType[] GetGraphicsAPIs_Internal(BuildTarget platform);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        private static extern void SetGraphicsAPIsImpl_Internal(PlayerSettings instance, BuildTarget platform, UnityEngine.Rendering.GraphicsDeviceType[] apis);\n\n        internal void SetGraphicsAPIs_Internal(BuildTarget platform, UnityEngine.Rendering.GraphicsDeviceType[] apis, bool shouldSync)\n        {\n            SetGraphicsAPIsImpl_Internal(this, platform, apis);\n            // we do cache api list in player settings editor, so if we update from script we should forcibly update cache\n            if (shouldSync)\n                PlayerSettingsEditor.SyncEditors(platform);\n        }\n\n        [NativeMethod(\"GetColorGamuts\")]\n        internal extern ColorGamut[] GetColorGamuts_Internal();\n\n        [NativeMethod(\"SetColorGamuts\")]\n        internal extern void SetColorGamuts_Internal(ColorGamut[] colorSpaces);\n\n        [StaticAccessor(\"PlayerSettingsBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void EnsureUnityConnectSettingsEqual(PlayerSettings target, PlayerSettings source);\n\n        [NativeMethod(\"SetTemplateCustomKeys\")]\n        internal extern void SetTemplateCustomKeys_Internal(string[] templateCustomKeys);\n\n        [NativeMethod(\"SetTemplateCustomValue\")]\n        internal extern void SetTemplateCustomValue_Internal(string name, string value);\n\n        [NativeMethod(\"GetTemplateCustomValue\")]\n        internal extern string GetTemplateCustomValue_Internal(string name);\n\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettings.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nusing EditorGraphicsSettings = UnityEditor.Rendering.EditorGraphicsSettings;\n\nnamespace UnityEditor\n{\n    // deprecated in 2018.1\n    [Obsolete(\"Use AndroidArchitecture instead. (UnityUpgradable) -> AndroidArchitecture\", false)]\n    public enum AndroidTargetDevice\n    {\n        [Obsolete(\"Use AndroidArchitecture.All instead. (UnityUpgradable) -> AndroidArchitecture.All\", false)]\n        FAT        = 0,\n        //ARMv6    = 1,\n        //Emulator = 2,\n        [Obsolete(\"Use AndroidArchitecture.ARMv7 instead. (UnityUpgradable) -> AndroidArchitecture.ARMv7\", false)]\n        ARMv7      = 3,\n        //x86      = 4,\n    }\n    // deprecated in 5.1.\n    [Obsolete(\"TargetGlesGraphics is ignored, use SetGraphicsAPIs/GetGraphicsAPIs APIs\", false)]\n    public enum TargetGlesGraphics\n    {\n        OpenGLES_1_x    = 0,\n        OpenGLES_2_0    = 1,\n        OpenGLES_3_0    = 2,\n        Automatic       = -1,\n    }\n    [Obsolete(\"TargetIOSGraphics is ignored, use SetGraphicsAPIs/GetGraphicsAPIs APIs\", false)]\n    public enum TargetIOSGraphics\n    {\n        OpenGLES_2_0    = 2,\n        OpenGLES_3_0    = 3,\n        Metal           = 4,\n        Automatic       = -1,\n    }\n    // deprecated in 5.3\n    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n    [Obsolete(\"Use Screen.SetResolution APIs\", true)]\n    public enum iOSTargetResolution\n    {\n        Native = 0,\n        ResolutionAutoPerformance = 3,\n        ResolutionAutoQuality = 4,\n        Resolution320p = 5,\n        Resolution640p = 6,\n        Resolution768p = 7\n    }\n    // deprecated in 5.5\n    [Obsolete(\"targetOSVersion is obsolete, use targetOSVersionString\", false)]\n    public enum iOSTargetOSVersion\n    {\n        iOS_4_0 = 10,\n        iOS_4_1 = 12,\n        iOS_4_2 = 14,\n        iOS_4_3 = 16,\n        iOS_5_0 = 18,\n        iOS_5_1 = 20,\n        iOS_6_0 = 22,\n        iOS_7_0 = 24,\n        iOS_7_1 = 26,\n        iOS_8_0 = 28,\n        iOS_8_1 = 30,\n        Unknown = 999,\n    }\n\n    // deprecated in 5.6\n    [Flags]\n    [Obsolete(\"Use UnityEngine.iOS.SystemGestureDeferMode instead. (UnityUpgradable) -> [UnityEngine] UnityEngine.iOS.SystemGestureDeferMode\", true)]\n    public enum iOSSystemGestureDeferMode: uint\n    {\n        None = 0,\n        TopEdge = 1 << 0,\n        LeftEdge = 1 << 1,\n        BottomEdge = 1 << 2,\n        RightEdge = 1 << 3,\n        All = TopEdge | LeftEdge | BottomEdge | RightEdge\n    }\n\n    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n    [Obsolete(\"AspectRatio enum has been deprecated and its functionality has been removed from Unity.\", false)]\n    public enum AspectRatio\n    {\n        // Undefined aspect ratios.\n        AspectOthers = 0,\n\n        // 4:3 aspect ratio.\n        Aspect4by3 = 1,\n\n        // 5:4 aspect ratio.\n        Aspect5by4 = 2,\n\n        // 16:10 aspect ratio.\n        Aspect16by10 = 3,\n\n        // 16:9 aspect ratio.\n        Aspect16by9 = 4,\n    }\n\n    partial class PlayerSettings\n    {\n        // deprecated since forever\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"The option alwaysDisplayWatermark is deprecated and is always false\", true)]\n        public static bool alwaysDisplayWatermark { get { return false; } set {} }\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"Use AssetBundles instead for streaming data\", true)]\n        public static int firstStreamedLevelWithResources { get { return 0; } set {} }\n\n        // deprecated in 5.1.\n        [Obsolete(\"targetGlesGraphics is ignored, use SetGraphicsAPIs/GetGraphicsAPIs APIs\", false)]\n        public static TargetGlesGraphics targetGlesGraphics { get { return TargetGlesGraphics.Automatic; } set {} }\n        [Obsolete(\"targetIOSGraphics is ignored, use SetGraphicsAPIs/GetGraphicsAPIs APIs\", false)]\n        public static TargetIOSGraphics targetIOSGraphics { get { return TargetIOSGraphics.Automatic; } set {} }\n\n        // deprecated in 5.5\n        [Obsolete(\"Use PlayerSettings.iOS.locationUsageDescription instead (UnityUpgradable) -> UnityEditor.PlayerSettings/iOS.locationUsageDescription\", false)]\n        public static string locationUsageDescription { get { return iOS.locationUsageDescription; } set { iOS.locationUsageDescription = value; } }\n\n        // deprecated in 5.5\n        [Obsolete(\"renderingPath is ignored, use UnityEditor.Rendering.TierSettings with UnityEditor.Rendering.SetTierSettings/GetTierSettings instead\", false)]\n        public static RenderingPath renderingPath { get { return EditorGraphicsSettings.GetCurrentTierSettings().renderingPath; } set {} }\n        [Obsolete(\"mobileRenderingPath is ignored, use UnityEditor.Rendering.TierSettings with UnityEditor.Rendering.SetTierSettings/GetTierSettings instead\", false)]\n        public static RenderingPath mobileRenderingPath { get { return EditorGraphicsSettings.GetCurrentTierSettings().renderingPath; } set {} }\n\n        // deprecated in 5.6\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"Use PlayerSettings.applicationIdentifier instead (UnityUpgradable) -> UnityEditor.PlayerSettings.applicationIdentifier\", true)]\n        public static string bundleIdentifier { get { return applicationIdentifier; } set { applicationIdentifier = value; } }\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"HasAspectRatio is deprecated, Unity supports all aspect ratios.\", false)]\n        public static bool HasAspectRatio(AspectRatio aspectRatio) => true;\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"SetAspectRatio is deprecated, Unity supports all aspect ratios.\", false)]\n        public static void SetAspectRatio(AspectRatio aspectRatio, bool enable) { }\n    }\n\n    partial class PlayerSettings\n    {\n        [Obsolete(\"Use PlayerSettings.Android.keystorePass instead (UnityUpgradable) -> UnityEditor.PlayerSettings/Android.keystorePass\", true)]\n        public static string keystorePass { get; set; }\n        [Obsolete(\"Use PlayerSettings.Android.keyaliasPass instead (UnityUpgradable) -> UnityEditor.PlayerSettings/Android.keyaliasPass\", true)]\n        public static string keyaliasPass { get; set; }\n\n        partial class Android\n        {\n            // deprecated in 2018.1\n            [Obsolete(\"Use targetArchitectures instead. (UnityUpgradable) -> targetArchitectures\", false)]\n            public static AndroidTargetDevice targetDevice\n            {\n                get\n                {\n                    switch (targetArchitectures)\n                    {\n                        case AndroidArchitecture.ARMv7:\n                            return AndroidTargetDevice.ARMv7;\n                        default:\n                            return AndroidTargetDevice.FAT;\n                    }\n                }\n                set\n                {\n                    targetArchitectures = AndroidArchitecture.ARMv7;\n                }\n            }\n\n            [Obsolete(\"minifyWithR8 is obsolete and has no effect anymore, since Android Gradle Plugin 7.0 always uses R8\", false)]\n            public static bool minifyWithR8 { get { return true; } set {} }\n\n            [Obsolete(\"Renamed to match UI. Please use splitApplicationBinary instead. (UnityUpgradable) -> splitApplicationBinary\", false)]\n            public static extern bool useAPKExpansionFiles\n            {\n                [NativeMethod(\"GetAndroidSplitApplicationBinary\")]\n                get;\n                [NativeMethod(\"SetAndroidSplitApplicationBinary\")]\n                set;\n            }\n        }\n\n        partial class iOS\n        {\n            // deprecated in 5.0\n            [Obsolete(\"exitOnSuspend is deprecated, use appInBackgroundBehavior\", false)]\n            public static bool exitOnSuspend\n            {\n                get { return appInBackgroundBehavior == iOSAppInBackgroundBehavior.Exit; }\n                set { appInBackgroundBehavior = iOSAppInBackgroundBehavior.Exit; }\n            }\n\n            // deprecated in 5.3\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use Screen.SetResolution at runtime\", true)]\n            public static iOSTargetResolution targetResolution { get { return 0; } set {} }\n\n            // deprecated in 5.5\n            [Obsolete(\"Use PlayerSettings.muteOtherAudioSources instead (UnityUpgradable) -> UnityEditor.PlayerSettings.muteOtherAudioSources\", false)]\n            public static bool overrideIPodMusic { get { return PlayerSettings.muteOtherAudioSources; } set { PlayerSettings.muteOtherAudioSources = value; } }\n        }\n    }\n}\n\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsAndroid.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing System;\nusing System.Text.RegularExpressions;\n\nnamespace UnityEditor\n{\n    // Android CPU architecture.\n    // Matches enum in EditorOnlyPlayerSettings.h.\n    [Flags]\n    public enum AndroidArchitecture : uint\n    {\n        // Invalid architecture\n        None = 0,\n\n        // armeabi-v7a\n        ARMv7 = 1 << 0,\n\n        // arm64-v8a\n        ARM64 = 1 << 1,\n\n        // x86\n        [Obsolete(\"X86 is no longer supported.\")]\n        X86 = 1 << 2,\n\n        // x86_64\n        X86_64 = 1 << 3,\n\n        // All architectures\n        All = 0xffffffff,\n    }\n\n    // Target devices.\n    [Obsolete(\"AndroidTargetDevices is deprecated since ChromeOS is no longer supported.\")]\n    public enum AndroidTargetDevices\n    {\n        // All devices. The Android aplication is allowed to run on all devices.\n        AllDevices = 0,\n        // Only run the Android aplication on mobile phones, tablets, and TV devices, not on any Chrome OS devices.\n        PhonesTabletsAndTVDevicesOnly = 1,\n        // Only run the Android application on Chrome OS devices, not on any Android mobile phones, tablets, or TV devices.\n        ChromeOSDevicesOnly = 2,\n    }\n\n    // Supported Android SDK versions\n    public enum AndroidSdkVersions\n    {\n        // Set target API level to latest installed\n        AndroidApiLevelAuto = 0,\n\n        // Android 4.1, \"Jelly Bean\", API level 16\n        [Obsolete(PlayerSettings.Android.MinSupportedAPILevelWarning, true)]\n        AndroidApiLevel16 = 16,\n\n        // Android 4.2, \"Jelly Bean\", API level 17\n        [Obsolete(PlayerSettings.Android.MinSupportedAPILevelWarning, true)]\n        AndroidApiLevel17 = 17,\n\n        // Android 4.3, \"Jelly Bean\", API level 18\n        [Obsolete(PlayerSettings.Android.MinSupportedAPILevelWarning, true)]\n        AndroidApiLevel18 = 18,\n\n        // Android 4.4, \"KitKat\", API level 19\n        [Obsolete(PlayerSettings.Android.MinSupportedAPILevelWarning, true)]\n        AndroidApiLevel19 = 19,\n\n        // Android 5.0, \"Lollipop\", API level 21\n        [Obsolete(PlayerSettings.Android.MinSupportedAPILevelWarning, true)]\n        AndroidApiLevel21 = 21,\n\n        // Android 5.1, \"Lollipop\", API level 22\n        [Obsolete(PlayerSettings.Android.MinSupportedAPILevelWarning, true)]\n        AndroidApiLevel22 = 22,\n\n        // Android 6.0, \"Marshmallow\", API level 23\n        AndroidApiLevel23 = 23,\n\n        // Android 7.0, \"Nougat\", API level 24\n        AndroidApiLevel24 = 24,\n\n        // Android 7.1, \"Nougat\", API level 25\n        AndroidApiLevel25 = 25,\n\n        // Android 8.0, \"Oreo\", API level 26\n        AndroidApiLevel26 = 26,\n\n        // Android 8.1, \"Oreo\", API level 27\n        AndroidApiLevel27 = 27,\n\n        // Android 9.0, \"Pie\", API level 28\n        AndroidApiLevel28 = 28,\n\n        // Android 10.0, API level 29\n        AndroidApiLevel29 = 29,\n\n        // Android 11.0, API level 30\n        AndroidApiLevel30 = 30,\n\n        // Android 12.0, API level 31\n        AndroidApiLevel31 = 31,\n\n        // Android 12L, API level 32\n        AndroidApiLevel32 = 32,\n\n        // Android 13.0, API level 33\n        AndroidApiLevel33 = 33,\n\n        // Android 14.0, API level 34\n        AndroidApiLevel34 = 34,\n\n        // Android 15.0, API level 35\n        AndroidApiLevel35 = 35,\n\n        // Android 16.0, API level 36\n        AndroidApiLevel36 = 36,\n    }\n\n    // Preferred application install location\n    public enum AndroidPreferredInstallLocation\n    {\n        // Let the OS decide, app doesn't have any preferences\n        Auto = 0,\n\n        // Prefer external, if possible. Install to internal otherwise\n        PreferExternal = 1,\n\n        // Force installation into internal memory. Needed for things like Live Wallpapers\n        ForceInternal = 2,\n    }\n\n    public enum AndroidShowActivityIndicatorOnLoading\n    {\n        // Large == progressBarStyleLarge\n        Large = 0,\n\n        // Inversed Large == progressBarStyleLargeInverse\n        InversedLarge = 1,\n\n        // Small == progressBarStyleSmall\n        Small = 2,\n\n        // Inversed Small == progressBarStyleSmallInverse\n        InversedSmall = 3,\n\n        // Don't Show\n        DontShow = -1,\n    }\n\n    // Gamepad support level for Android TV\n    public enum AndroidGamepadSupportLevel\n    {\n        // Game is fully operational with a D-pad, no gamepad needed\n        SupportsDPad = 0,\n\n        // Works with a gamepad, but does not require it\n        SupportsGamepad = 1,\n\n        // Requires a gamepad for gameplay\n        RequiresGamepad = 2,\n    }\n\n    // Android splash screen scale modes\n    public enum AndroidSplashScreenScale\n    {\n        // Center\n        Center = 0,\n\n        // Scale to fit\n        ScaleToFit = 1,\n\n        // Scale to fill\n        ScaleToFill = 2,\n    }\n\n    // Android screen blit types\n    public enum AndroidBlitType\n    {\n        // Always blit\n        Always = 0,\n\n        // Never blit\n        Never = 1,\n\n        // Automatic\n        Auto = 2,\n    }\n\n    //internal struct AndroidBanner\n    internal struct AndroidBanner\n    {\n        public int width;\n        public int height;\n        public Texture2D banner;\n    }\n\n    public enum AndroidAutoRotationBehavior\n    {\n        User = 1,\n        Sensor = 2,\n    }\n\n    [Flags]\n    public enum AndroidApplicationEntry : uint\n    {\n        /// <summary>\n        /// Include entry which derives from Activity\n        /// - Activity https://developer.android.com/reference/android/app/Activity\n        /// </summary>\n        Activity = 1 << 0,\n        /// <summary>\n        /// Include entry which derives from Game Activity https://developer.android.com/games/agdk/game-activity\n        /// </summary>\n        GameActivity = 1 << 1\n    }\n\n    [Obsolete(\"AndroidDeviceFilterData is obsolete. Use UnityEngine.VulkanDeviceFilterData instead.\")]\n    public struct AndroidDeviceFilterData\n    {\n        public string vendorName;\n        public string deviceName;\n        public string brandName;\n        public string productName;\n        public string androidOsVersionString;\n        public string vulkanApiVersionString;\n        public string driverVersionString;\n    }\n\n    // Player Settings is where you define various parameters for the final game that you will build in Unity. Some of these values are used in the Resolution Dialog that launches when you open a standalone game.\n    public partial class PlayerSettings : UnityEngine.Object\n    {\n        // Android specific player settings\n        [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        public partial class Android\n        {\n            internal const string MinSupportedAPILevelWarning = \"Minimum supported Android API level is 23 (Android 6.0 Marshmallow). Please use AndroidApiLevel23 or higher\";\n\n            // Disable Depth and Stencil Buffers\n            public static extern bool disableDepthAndStencilBuffers { get; set; }\n\n            // 24-bit Depth Buffer is used\n            [Obsolete(\"use24BitDepthBuffer is deprecated, use disableDepthAndStencilBuffers instead.\")]\n            public static bool use24BitDepthBuffer\n            {\n                get { return !disableDepthAndStencilBuffers; }\n                set {}\n            }\n\n            // Default horizontal dimension of Android player window.\n            public static extern int defaultWindowWidth\n            {\n                [NativeMethod(\"GetAndroidDefaultWindowWidth\")]\n                get;\n                [NativeMethod(\"SetAndroidDefaultWindowWidth\")]\n                set;\n            }\n\n            // Default vertical dimension of Android player window.\n            public static extern int defaultWindowHeight\n            {\n                [NativeMethod(\"GetAndroidDefaultWindowHeight\")]\n                get;\n                [NativeMethod(\"SetAndroidDefaultWindowHeight\")]\n                set;\n            }\n\n            // Minimum horizontal dimension of Android player window.\n            public static extern int minimumWindowWidth\n            {\n                [NativeMethod(\"GetAndroidMinimumWindowWidth\")]\n                get;\n                [NativeMethod(\"SetAndroidMinimumWindowWidth\")]\n                set;\n            }\n\n            // Minimum vertical dimension of Android player window.\n            public static extern int minimumWindowHeight\n            {\n                [NativeMethod(\"GetAndroidMinimumWindowHeight\")]\n                get;\n                [NativeMethod(\"SetAndroidMinimumWindowHeight\")]\n                set;\n            }\n\n            [Obsolete(\"resizableWindow has been deprecated and renamed to match Android documentation. Please use resizeableActivity instead. (UnityUpgradable) -> resizeableActivity\", false)]\n            // Should application resizing be allowed (deprecated old naming).\n            public static bool resizableWindow\n            {\n                set => resizeableActivity = value;\n                get => resizeableActivity;\n            }\n\n            // Should application resizing be allowed (new naming).\n            public static extern bool resizeableActivity\n            {\n                [NativeMethod(\"GetAndroidResizeableActivity\")]\n                get;\n                [NativeMethod(\"SetAndroidResizeableActivity\")]\n                set;\n            }\n\n            public static bool runWithoutFocus\n            {\n                set => runInBackground = value;\n                get => runInBackground;\n            }\n\n            // Full screen mode. Full screen window or windowed.\n            public static extern FullScreenMode fullscreenMode\n            {\n                [NativeMethod(\"GetAndroidFullscreenMode\")]\n                get;\n                [NativeMethod(\"SetAndroidFullscreenMode\")]\n                set;\n            }\n\n            public static extern AndroidAutoRotationBehavior autoRotationBehavior\n            {\n                [NativeMethod(\"GetAndroidAutoRotationBehavior\")]\n                get;\n                [NativeMethod(\"SetAndroidAutoRotationBehavior\")]\n                set;\n            }\n\n            // Android bundle version code\n            public static extern int bundleVersionCode\n            {\n                [NativeMethod(\"GetAndroidBundleVersionCode\")]\n                get;\n                [NativeMethod(\"SetAndroidBundleVersionCode\")]\n                set;\n            }\n\n            // Minimal Android SDK version\n            public static extern AndroidSdkVersions minSdkVersion\n            {\n                [NativeMethod(\"GetAndroidMinSdkVersion\")]\n                get;\n                [NativeMethod(\"SetAndroidMinSdkVersion\")]\n                set;\n            }\n\n            // Target Android SDK version\n            public static extern AndroidSdkVersions targetSdkVersion\n            {\n                [NativeMethod(\"GetAndroidTargetSdkVersion\")]\n                get;\n                [NativeMethod(\"SetAndroidTargetSdkVersion\")]\n                set;\n            }\n\n            // Preferred application install location\n            public static extern AndroidPreferredInstallLocation preferredInstallLocation\n            {\n                [NativeMethod(\"GetAndroidPreferredInstallLocation\")]\n                get;\n                [NativeMethod(\"SetAndroidPreferredInstallLocation\")]\n                set;\n            }\n\n            // Force internet permission flag\n            public static extern bool forceInternetPermission\n            {\n                [NativeMethod(\"GetForceAndroidInternetPermission\")]\n                get;\n                [NativeMethod(\"SetForceAndroidInternetPermission\")]\n                set;\n            }\n\n            // Force SD card permission\n            public static extern bool forceSDCardPermission\n            {\n                [NativeMethod(\"GetForceAndroidSDCardPermission\")]\n                get;\n                [NativeMethod(\"SetForceAndroidSDCardPermission\")]\n                set;\n            }\n\n            // Android TV compatible build\n            public static extern bool androidTVCompatibility { get; set; }\n\n            // Android TV - is it a game or a regular app\n            public static extern bool androidIsGame { get; set; }\n\n            // Google Tango mixed reality support\n            public static extern bool ARCoreEnabled { get; set; }\n\n            // Whether Android banner is added to the APK\n            internal static extern bool androidBannerEnabled { get; set; }\n\n            // Gamepad support level for Android TV\n            internal static extern AndroidGamepadSupportLevel androidGamepadSupportLevel { get; set; }\n\n            [Obsolete(\"ChromeOS is no longer supported.\")]\n            public static bool chromeosInputEmulation { get; set; }\n\n            // Returns Android banner list\n            internal static extern AndroidBanner[] GetAndroidBanners();\n\n            internal static extern Texture2D GetAndroidBannerForHeight(int height);\n            internal static extern Texture2D GetAndroidBannerForHeightCustomList(int height, AndroidBanner[] allBanners);\n\n            internal static extern void SetAndroidBanners(Texture2D[] banners);\n            internal static extern AndroidBanner[] SetAndroidBannersCustomList(Texture2D[] banners, AndroidBanner[] allBanners);\n\n            //*undocumented*\n            // only available in developer builds for now.\n            internal static extern bool createWallpaper\n            {\n                [NativeMethod(\"GetCreateAndroidWallpaper\")]\n                get;\n                [NativeMethod(\"SetCreateAndroidWallpaper\")]\n                set;\n            }\n\n            // Targeted CPU architectures.\n            public static extern AndroidArchitecture targetArchitectures\n            {\n                [NativeMethod(\"GetAndroidTargetArchitectures\")]\n                get;\n                [NativeMethod(\"SetAndroidTargetArchitectures\")]\n                set;\n            }\n\n            // Enable Armv9 Security Features - Pointer Authentication (PAuth, PAC) and Branch Target Identification (BTI) for Arm64 builds\n            public static extern bool enableArmv9SecurityFeatures\n            {\n                [NativeMethod(\"GetEnableArmv9SecurityFeatures\")]\n                get;\n                [NativeMethod(\"SetEnableArmv9SecurityFeatures\")]\n                set;\n            }\n\n            // Enable Armv8.5a MTE - Memory Tagging for Arm64 builds\n            internal static extern bool enableArm64MTE\n            {\n                [NativeMethod(\"GetEnableArm64MTE\")]\n                get;\n                [NativeMethod(\"SetEnableArm64MTE\")]\n                set;\n            }\n\n            // Support different CPU architectures with each APK (a.k.a. Multiple APK support).\n            public static extern bool buildApkPerCpuArchitecture\n            {\n                [NativeMethod(\"GetBuildApkPerCpuArchitecture\")]\n                get;\n                [NativeMethod(\"SetBuildApkPerCpuArchitecture\")]\n                set;\n            }\n\n            [Obsolete(\"androidTargetDevices is deprecated since ChromeOS is no longer supported.\")]\n            public static AndroidTargetDevices androidTargetDevices { get; set; }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeProperty(\"androidSplashScreen\", TargetType.Field)]\n            internal static extern Texture2D splashScreen { get; }\n\n            // Android splash screen scale mode\n            public static extern AndroidSplashScreenScale splashScreenScale\n            {\n                [NativeMethod(\"GetAndroidSplashScreenScale\")]\n                get;\n                [NativeMethod(\"SetAndroidSplashScreenScale\")]\n                set;\n            }\n\n            [NativeProperty(\"androidUseCustomKeystore\", TargetType.Function)]\n            public static extern bool useCustomKeystore\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            internal static extern string ConvertAndroidKeystorePath(string keystoreName);\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            internal static extern string ConvertAndroidKeystoreNameToFullPath(string keystoreName);\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            internal static extern string ConvertAndroidKeystoreNameToPath(string keystoreName);\n\n            // Android keystore name\n            public static extern string keystoreName\n            {\n                [NativeMethod(\"GetAndroidKeystorePath\")]\n                get;\n                [NativeMethod(\"SetAndroidKeystorePath\")]\n                set;\n            }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            internal static extern string GetAndroidKeystoreFullPath();\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            internal static extern string GetAndroidKeystoresDedicatedLocationKey();\n\n            // Android keystore password\n            public static extern string keystorePass\n            {\n                [NativeMethod(\"GetAndroidKeystorePass\")]\n                get;\n                [NativeMethod(\"SetAndroidKeystorePass\")]\n                set;\n            }\n\n            // Android key alias name\n            public static extern string keyaliasName\n            {\n                [NativeMethod(\"GetAndroidKeyaliasName\")]\n                get;\n                [NativeMethod(\"SetAndroidKeyaliasName\")]\n                set;\n            }\n\n            // Android key alias password\n            public static extern string keyaliasPass\n            {\n                [NativeMethod(\"GetAndroidKeyaliasPass\")]\n                get;\n                [NativeMethod(\"SetAndroidKeyaliasPass\")]\n                set;\n            }\n\n            // License verification flag\n            public static extern bool licenseVerification\n            {\n                [NativeMethod(\"GetAndroidLicenseVerification\")]\n                get;\n            }\n            public static extern bool splitApplicationBinary\n            {\n                [NativeMethod(\"GetAndroidSplitApplicationBinary\")]\n                get;\n                [NativeMethod(\"SetAndroidSplitApplicationBinary\")]\n                set;\n            }\n\n            // Application should show ActivityIndicator when loading\n            public static extern AndroidShowActivityIndicatorOnLoading showActivityIndicatorOnLoading\n            {\n                [NativeMethod(\"GetAndroidShowActivityIndicatorOnLoading\")]\n                get;\n                [NativeMethod(\"SetAndroidShowActivityIndicatorOnLoading\")]\n                set;\n            }\n\n            // Android screen blit type\n            public static extern AndroidBlitType blitType\n            {\n                [NativeMethod(\"GetAndroidBlitType\")]\n                get;\n                [NativeMethod(\"SetAndroidBlitType\")]\n                set;\n            }\n\n            // enum { Legacy Wide Screen (1.86) = 0, Super Wide Screen (2.1) = 1, Custom = 2 }\n            internal static extern int supportedAspectRatioMode\n            {\n                [NativeMethod(\"GetAndroidSupportedAspectRatio\")]\n                get;\n                [NativeMethod(\"SetAndroidSupportedAspectRatio\")]\n                set;\n            }\n\n            // Maximum aspect ratio that is supported by the app. Black bars are added by Android OS if supportedAspectRatio is smaller than the screen aspect ratio.\n            public static float maxAspectRatio\n            {\n                get { return GetAndroidMaxAspectRatio(); }\n                set { SetAndroidMaxAspectRatioInternal(value); }\n            }\n\n            public static float minAspectRatio\n            {\n                get { return GetAndroidMinAspectRatio(); }\n                set { SetAndroidMinAspectRatioInternal(value); }\n            }\n\n            internal static extern float GetAndroidMaxAspectRatio();\n            internal static extern float GetAndroidMinAspectRatio();\n\n            private static void SetAndroidMaxAspectRatioInternal(float value)\n            {\n                if (value < 1.86f)\n                {\n                    Debug.LogWarning($\"Maximum Aspect Ratio must be greater or equal to 1.86. {value} is too small, setting to 1.86 instead.\");\n                    SetAndroidMaxAspectRatio(1.86f);\n                }\n                else\n                {\n                    SetAndroidMaxAspectRatio(value);\n                }\n\n                SetAndroidSupportedAspectRatio(2); // set supported aspect ratio mode to \"Custom\"\n            }\n\n            private static void SetAndroidMinAspectRatioInternal(float value)\n            {\n                if (value < 1.0f)\n                {\n                    Debug.LogWarning($\"Minimum Aspect Ratio must be greater or equal to 1.0. {value} is too small, setting to 1.0 instead.\");\n                    SetAndroidMinAspectRatio(1.0f);\n                }\n                else\n                {\n                    SetAndroidMinAspectRatio(value);\n                }\n\n                SetAndroidSupportedAspectRatio(2); // set supported aspect ratio mode to \"Custom\"\n            }\n\n            internal static extern void SetAndroidSupportedAspectRatio(int value);\n\n            internal static extern void SetAndroidMaxAspectRatio(float value);\n\n            internal static extern void SetAndroidMinAspectRatio(float value);\n\n            internal static extern bool useLowAccuracyLocation\n            {\n                [NativeMethod(\"GetAndroidUseLowAccuracyLocation\")]\n                get;\n            }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"GetAndroidMinSupportedAPILevel\")]\n            internal static extern int GetMinSupportedAPILevel();\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"GetAndroidMinTargetAPILevel\")]\n            internal static extern int GetMinTargetAPILevel();\n\n            // Start application in fullscreen mode\n            public static extern bool startInFullscreen\n            {\n                [NativeMethod(\"GetAndroidStartInFullscreen\")]\n                get;\n                [NativeMethod(\"SetAndroidStartInFullscreen\")]\n                set;\n            }\n\n            // Allow the application to render outside the safe area.\n            public static extern bool renderOutsideSafeArea\n            {\n                [NativeMethod(\"GetAndroidRenderOutsideSafeArea\")]\n                get;\n                [NativeMethod(\"SetAndroidRenderOutsideSafeArea\")]\n                set;\n            }\n\n            // Minify java code in release build\n            [NativeProperty(\"AndroidMinifyRelease\", TargetType.Function)]\n            public static extern bool minifyRelease { get; set; }\n            // Minify java code in development build\n            [NativeProperty(\"AndroidMinifyDebug\", TargetType.Function)]\n            public static extern bool minifyDebug { get; set; }\n\n            // Validate release App Bundle size after build\n            internal static extern bool validateAppBundleSize { get; set; }\n\n            // App Bundle size which should cause warning message appear\n            internal static extern int appBundleSizeToValidate { get; set; }\n\n            public static extern bool optimizedFramePacing\n            {\n                [NativeMethod(\"GetAndroidUseSwappy\")]\n                get;\n                [NativeMethod(\"SetAndroidUseSwappy\")]\n                set;\n            }\n\n            public static TextureCompressionFormat[] textureCompressionFormats\n            {\n                get\n                {\n                    return GetTextureCompressionFormatsImpl(BuildTarget.Android);\n                }\n                set\n                {\n                    if (value == null || value.Length == 0)\n                    {\n                        throw new ArgumentException($\"Android textureCompressionFormats can't be null or empty\");\n                    }\n                    foreach (var format in value)\n                    {\n                        if (format == TextureCompressionFormat.Unknown || format == TextureCompressionFormat.BPTC)\n                        {\n                            throw new ArgumentException($\"{format} can't be used as a target texture compression for Android\");\n                        }\n                    }\n                    SetTextureCompressionFormatsImpl(BuildTarget.Android, value);\n                }\n            }\n\n            // Google Play App Dependencies info.\n            [NativeProperty(\"AndroidReportGooglePlayAppDependencies\", TargetType.Function)]\n            public static extern bool reportGooglePlayAppDependencies { get; set; }\n\n            public static extern AndroidApplicationEntry applicationEntry\n            {\n                [NativeMethod(\"GetAndroidApplicationEntry\")]\n                get;\n                [NativeMethod(\"SetAndroidApplicationEntry\")]\n                set;\n            }\n\n            // Add enableOnBackInvokedCallback flag to AndroidManifest\n            [NativeProperty(\"AndroidPredictiveBackSupport\", TargetType.Function)]\n            public static extern bool predictiveBackSupport { get; set; }\n\n            [Obsolete(\"GetAndroidVulkanDenyFilterListImpl is deprecated. Use the androidVulkanDeviceFilterListAsset instead.\")]\n            internal static extern AndroidDeviceFilterData[] GetAndroidVulkanDenyFilterListImpl();\n\n            [Obsolete(\"SetAndroidVulkanDenyFilterListImpl is deprecated. Use the androidVulkanDeviceFilterListAsset instead.\")]\n            internal static extern void SetAndroidVulkanDenyFilterListImpl(AndroidDeviceFilterData[] filterData);\n\n            [Obsolete(\"GetAndroidVulkanAllowFilterListImpl is deprecated. Use the androidVulkanDeviceFilterListAsset instead.\")]\n            internal static extern AndroidDeviceFilterData[] GetAndroidVulkanAllowFilterListImpl();\n\n            [Obsolete(\"SetAndroidVulkanAllowFilterListImpl is deprecated. Use the androidVulkanDeviceFilterListAsset instead.\")]\n            internal static extern void SetAndroidVulkanAllowFilterListImpl(AndroidDeviceFilterData[] filterData);\n\n            public static extern VulkanDeviceFilterLists androidVulkanDeviceFilterListAsset { get; set; }\n\n\n            [Obsolete(\"vendorNameString is obsolete. Use VulkanDeviceFilterLists api instead.\")]\n            private static readonly string vendorNameString = \"vendorName\";\n\n            [Obsolete(\"deviceNameString is obsolete. Use VulkanDeviceFilterLists api instead.\")]\n            private static readonly string deviceNameString = \"deviceName\";\n\n            [Obsolete(\"brandNameString is obsolete. Use VulkanDeviceFilterLists api instead.\")]\n            private static readonly string brandNameString = \"brandName\";\n\n            [Obsolete(\"productNameString is obsolete. Use VulkanDeviceFilterLists api instead.\")]\n            private static readonly string productNameString = \"productName\";\n\n            [Obsolete(\"vulkanApiVersionStringValue is obsolete. Use VulkanDeviceFilterLists api instead.\")]\n            private static readonly string vulkanApiVersionStringValue = \"vulkanApiVersionString\";\n\n            [Obsolete(\"driverVersionStringValue is obsolete. Use VulkanDeviceFilterLists api instead.\")]\n            private static readonly string driverVersionStringValue = \"driverVersionString\";\n\n            // Keep in sync with same error message in VulkanDeviceFilterLists.Bindings.cs\n            [Obsolete(\"versionErrorMessage is obsolete. Use VulkanDeviceFilterLists api instead.\")]\n            private static readonly string versionErrorMessage = \"Version information should be formatted as:\" +\n                \"\\n1. 'MajorVersion.MinorVersion.PatchVersion' where MinorVersion and PatchVersion are optional and must only \" +\n                \"contain numbers, or \\n2. Hex number beginning with '0x' (max 4-bytes)\";\n\n            // Keep in sync with validVersionString in VulkanDeviceFilterLists.Bindings.cs\n            [Obsolete(\"validVersionString is obsolete. Use VulkanDeviceFilterLists api instead.\")]\n            private static readonly Regex validVersionString = new Regex(@\"(^[0-9]+(\\.[0-9]+){0,2}$)|(^0(x|X)([A-Fa-f0-9]{1,8})$)\", RegexOptions.Compiled);\n\n            [Obsolete(\"CheckVersion is obsolete. Use VulkanDeviceFilterLists api instead.\")]\n            internal static void CheckVersion(string value, string filterName, string fieldName)\n            {\n                if (!validVersionString.IsMatch(value))\n                    throw new ArgumentException($\"Invalid version string in {filterName} for {fieldName}=\\\"{value}\\\": {versionErrorMessage}\");\n            }\n\n            [Obsolete(\"CheckRegex is obsolete. Use VulkanDeviceFilterLists api instead.\")]\n            internal static void CheckRegex(string value, string filterName, string fieldName)\n            {\n                try\n                {\n                    // Try to create a regex from the input string to determine if it is a valid regex\n                    Regex regex = new Regex(value);\n                }\n                catch (ArgumentException e)\n                {\n                    throw new ArgumentException($\"Invalid Regular Expression in {filterName} for {fieldName}=\\\"{value}\\\": {e.Message}\");\n                }\n            }\n\n            [Obsolete(\"CheckAllFilterData is obsolete. Use VulkanDeviceFilterLists api instead.\")]\n            internal static void CheckAllFilterData(AndroidDeviceFilterData[] filterDataList, string filterName)\n            {\n                // The check will throw an exception if there's an issue with the data.\n                // We need to check the data here, as an invalid regex on the native side, can crash the game.\n                foreach (var filterData in filterDataList)\n                {\n                    if (!String.IsNullOrEmpty(filterData.vendorName))\n                        CheckRegex(filterData.vendorName, filterName, vendorNameString);\n                    if (!String.IsNullOrEmpty(filterData.deviceName))\n                        CheckRegex(filterData.deviceName, filterName, deviceNameString);\n                    if (!String.IsNullOrEmpty(filterData.brandName))\n                        CheckRegex(filterData.brandName, filterName, brandNameString);\n                    if (!String.IsNullOrEmpty(filterData.productName))\n                        CheckRegex(filterData.productName, filterName, productNameString);\n\n                    if (!String.IsNullOrEmpty(filterData.vulkanApiVersionString))\n                        CheckVersion(filterData.vulkanApiVersionString, filterName, vulkanApiVersionStringValue);\n                    if (!String.IsNullOrEmpty(filterData.driverVersionString))\n                        CheckVersion(filterData.driverVersionString, filterName, driverVersionStringValue);\n                }\n            }\n\n            // Note: Deprecation will be immediate in Unity 7. But this field will exist in Unity 6.\n            [Obsolete(\"androidVulkanDenyFilterList is deprecated, and is replaced by androidVulkanDeviceFilterListAsset.\")]\n            public static AndroidDeviceFilterData[] androidVulkanDenyFilterList\n            {\n                get\n                {\n                    return GetAndroidVulkanDenyFilterListImpl();\n                }\n                set\n                {\n                    if (value == null || value.Length == 0)\n                        return;\n\n                    CheckAllFilterData(value, \"Vulkan Deny filter list\");\n                    SetAndroidVulkanDenyFilterListImpl(value);\n                }\n            }\n\n            // Note: Deprecation will be immediate in Unity 7. But this field will exist in Unity 6.\n            [Obsolete(\"androidVulkanAllowFilterList is deprecated, and is replaced by androidVulkanDeviceFilterListAsset.\")]\n            public static AndroidDeviceFilterData[] androidVulkanAllowFilterList\n            {\n                get\n                {\n                    return GetAndroidVulkanAllowFilterListImpl();\n                }\n                set\n                {\n                    if (value == null || value.Length == 0)\n                        return;\n\n                    CheckAllFilterData(value, \"Vulkan Allow filter list\");\n                    SetAndroidVulkanAllowFilterListImpl(value);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsDefaultTextureCompressionHandler.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditorInternal;\nusing UnityEngine;\n\n\nnamespace UnityEditor\n{\n    internal abstract class PlayerSettingsDefaultTextureCompressionHandler\n    {\n        private SerializedProperty m_BuildTargetDefaultTextureCompressionFormat;\n        private SerializedObject m_SerializedObject;\n        private SerializedProperty m_TextureArraySerializedProperty;\n        private GUIContent m_TextureCompressionFormatsGUI;\n        private GUIContent[] m_DefaultTextureCompressionFormatNames = Array.Empty<GUIContent>();\n        private TextureCompressionFormat[] m_LastSavedFormat;\n        private List<TextureCompressionFormat> m_StoredTextureCompressionList;\n        private bool m_IsDirty = false;\n        private bool m_ToBeUpdated = true;\n        private bool m_AllowMultipleTextureCompression = true;\n        private ReorderableList m_TextureCompressionsList;\n        private Func<TextureCompressionFormat[]> m_AvailableTextureCompressionsProvider;\n        private Func<bool> m_IsActivePlayerSettingsEditor;\n        private Action m_EditorSerialization;\n\n        private const string k_BuildTargetKey = \"m_BuildTarget\";\n        private const string k_FormatsKey = \"m_Formats\";\n        private const string k_BuildTargetDefaultTextureCompressionFormatName = \"m_BuildTargetDefaultTextureCompressionFormat\";\n\n        protected abstract string PlatformName { get; }\n\n        protected abstract TextureCompressionFormat[] CurrentPlatformGlobalEditorTextureFormat { get; set; }\n\n        protected abstract string ToString(TextureCompressionFormat textureCompression);\n\n        protected void SetDefaultTextureCompressionFormatNames(GUIContent[] textureCompressionFormatNames)\n        {\n            m_DefaultTextureCompressionFormatNames = textureCompressionFormatNames;\n        }\n\n        private ReorderableList TextureCompressionsList\n        {\n            get\n            {\n                if (m_TextureCompressionsList == null)\n                {\n                    var textureCompressionsList = GetStoredCompressionFormatOrDefaultOne();\n                    m_TextureCompressionsList = new ReorderableList(textureCompressionsList, typeof(TextureCompressionFormat), true, true, true, true)\n                    {\n                        onCanRemoveCallback = (list) => true,\n                        onRemoveCallback = RemoveTextureCompressionElement,\n                        onReorderCallback = ReorderTextureCompressionElement,\n                        drawHeaderCallback = (rect) => GUI.Label(rect, m_TextureCompressionFormatsGUI, EditorStyles.label),\n                        onAddDropdownCallback = AddTextureCompressionElement,\n                        drawElementCallback = DrawTextureCompressionElement,\n                        onChangedCallback = Onchanged,\n                        elementHeight = 16\n                    };\n                }\n\n                return m_TextureCompressionsList;\n            }\n        }\n\n\n        private SerializedProperty TextureFormatArraySerializedProperty\n        {\n            get\n            {\n                if (m_TextureArraySerializedProperty == null)\n                {\n                    foreach (SerializedProperty element in m_BuildTargetDefaultTextureCompressionFormat)\n                    {\n                        var buildTarget = element.FindPropertyRelative(k_BuildTargetKey).stringValue;\n                        if (buildTarget == PlatformName)\n                        {\n                            m_TextureArraySerializedProperty = element.FindPropertyRelative(k_FormatsKey);\n                        }\n                    }\n\n                    if (m_TextureArraySerializedProperty == null)\n                    {\n                        int index = m_BuildTargetDefaultTextureCompressionFormat.arraySize;\n                        m_BuildTargetDefaultTextureCompressionFormat.InsertArrayElementAtIndex(index);\n                        var newElement = m_BuildTargetDefaultTextureCompressionFormat.GetArrayElementAtIndex(index);\n                        newElement.FindPropertyRelative(k_BuildTargetKey).stringValue = PlatformName;\n                        m_TextureArraySerializedProperty = newElement.FindPropertyRelative(k_FormatsKey);\n                        var availableTextures = m_AvailableTextureCompressionsProvider();\n                        if (availableTextures.Length > 0)\n                        {\n                            int[] formats = new int[] {(int) availableTextures[0]};\n                            m_TextureArraySerializedProperty.SetValue(SerializedPropertyExtensions.Setter, formats);\n                            m_SerializedObject.ApplyModifiedProperties();\n                        }\n                    }\n                }\n\n                return m_TextureArraySerializedProperty;\n            }\n        }\n\n        public List<TextureCompressionFormat> StoredTextureCompressionList\n        {\n            get\n            {\n                if (m_StoredTextureCompressionList == null)\n                {\n                    m_StoredTextureCompressionList = GetStoredCompressionFormatOrDefaultOne();\n                }\n\n                return m_StoredTextureCompressionList;\n            }\n\n            private set { m_StoredTextureCompressionList = value; }\n        }\n\n        protected bool IsActivePlayerSettingsEditor\n        {\n            get\n            {\n                if (m_IsActivePlayerSettingsEditor != null)\n                {\n                    return m_IsActivePlayerSettingsEditor.Invoke();\n                }\n\n                return false;\n            }\n        }\n\n        public void Reset()\n        {\n            m_TextureArraySerializedProperty = null;\n            m_TextureCompressionsList = null;\n            m_LastSavedFormat = null;\n            m_StoredTextureCompressionList = null;\n            m_IsDirty = false;\n            m_ToBeUpdated = true;\n        }\n\n        public PlayerSettingsDefaultTextureCompressionHandler(Func<TextureCompressionFormat[]> availableTextureCompressionsProvider, bool allowMultipleTextureCompression = true)\n        {\n            m_AvailableTextureCompressionsProvider = availableTextureCompressionsProvider;\n            m_AllowMultipleTextureCompression = allowMultipleTextureCompression;\n        }\n\n        public PlayerSettingsDefaultTextureCompressionHandler SetupSerializedObject(SerializedObject serializedObject, string variableName = k_BuildTargetDefaultTextureCompressionFormatName)\n        {\n            m_SerializedObject = serializedObject;\n            m_BuildTargetDefaultTextureCompressionFormat = FindPropertyAssert(variableName);\n            return this;\n        }\n\n        public PlayerSettingsDefaultTextureCompressionHandler SetEditorSerializationAction(Action editorSerialization)\n        {\n            m_EditorSerialization = editorSerialization;\n            return this;\n        }\n\n        public PlayerSettingsDefaultTextureCompressionHandler SetIsActivePlayerSettingsEditor(Func<bool> isActivePlayerSettingsEditor)\n        {\n            m_IsActivePlayerSettingsEditor = isActivePlayerSettingsEditor;\n            return this;\n        }\n\n        public PlayerSettingsDefaultTextureCompressionHandler SetGUIContent(GUIContent guiContent)\n        {\n            m_TextureCompressionFormatsGUI = guiContent;\n            return this;\n        }\n\n        private SerializedProperty FindPropertyAssert(string name)\n        {\n            var property = m_SerializedObject.FindProperty(name);\n            if (property == null)\n            {\n                Debug.LogError($\"Failed to find: {name}\");\n            }\n\n            return property;\n        }\n\n        public void RenderingSectionGUI()\n        {\n            if (m_AllowMultipleTextureCompression)\n            {\n                RenderAsReorderableList();\n            }\n            else\n            {\n                RenderAsDropdown();\n            }\n        }\n\n        void RenderAsReorderableList()\n        {\n            EditorGUILayout.Space();\n            var updated = false;\n            if (m_IsDirty)\n            {\n                updated = UpdateSerialization();\n            }\n\n            TextureCompressionsList.DoLayoutList();\n            if (updated || m_ToBeUpdated)\n            {\n                var textureCompressions = GetStoredCompressionFormatOrDefaultOne();\n                TextureCompressionsList.list = textureCompressions;\n                m_ToBeUpdated = false;\n            }\n\n            EditorGUILayout.Space();\n        }\n\n        void RenderAsDropdown()\n        {\n            if (StoredTextureCompressionList.Count == 0)\n                return;\n\n            var availableTextureCompressions = m_AvailableTextureCompressionsProvider();\n            var oldFormat = StoredTextureCompressionList[0];\n            var newFormat = PlayerSettingsEditor.BuildEnumPopup(m_TextureCompressionFormatsGUI, oldFormat, availableTextureCompressions, m_DefaultTextureCompressionFormatNames);\n\n            if (newFormat != oldFormat)\n            {\n                StoredTextureCompressionList[0] = newFormat;\n                UpdateSerialization();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        private List<TextureCompressionFormat> GetTextureCompressionFormatFromSerialization(SerializedProperty serializedProperty)\n        {\n            var formats = new List<TextureCompressionFormat>();\n            if (serializedProperty != null)\n            {\n                var arraysize = serializedProperty.arraySize;\n                for (var i = 0; i < arraysize; i++)\n                {\n                    var format = (TextureCompressionFormat)serializedProperty.GetArrayElementAtIndex(i).intValue;\n                    formats.Add(format);\n                }\n            }\n\n            return formats;\n        }\n\n        private List<TextureCompressionFormat> GetStoredCompressionFormatOrDefaultOne()\n        {\n            var formats = GetTextureCompressionFormatFromSerialization(TextureFormatArraySerializedProperty);\n\n            if (formats.Count > 0)\n            {\n                return formats;\n            }\n\n            if (CurrentPlatformGlobalEditorTextureFormat != null)\n            {\n                return CurrentPlatformGlobalEditorTextureFormat.ToList();\n            }\n\n            return new List<TextureCompressionFormat>();\n        }\n\n        private bool UpdateTextureCompressionFormatSerialization(SerializedProperty serializedProperty, TextureCompressionFormat[] formats)\n        {\n            var same = m_LastSavedFormat != null && m_LastSavedFormat.Length == formats.Length && m_LastSavedFormat.SequenceEqual(formats);\n            if (same) return false;\n            m_LastSavedFormat = formats;\n            var intValues = Array.ConvertAll(formats, format => (int)format);\n            serializedProperty.SetValue(SerializedPropertyExtensions.Setter, intValues);\n\n            return true;\n        }\n\n        private bool UpdateSerialization()\n        {\n            var updated = UpdateTextureCompressionFormatSerialization(TextureFormatArraySerializedProperty, StoredTextureCompressionList.ToArray());\n            if (updated)\n            {\n                m_BuildTargetDefaultTextureCompressionFormat.serializedObject.ApplyModifiedProperties();\n                if (IsActivePlayerSettingsEditor)\n                {\n                    CurrentPlatformGlobalEditorTextureFormat = StoredTextureCompressionList.ToArray();\n                    m_EditorSerialization?.Invoke();\n                }\n\n                m_SerializedObject.ApplyModifiedProperties();\n\n                TextureCompressionsList.list = StoredTextureCompressionList;\n            }\n\n            m_IsDirty = false;\n            return updated;\n        }\n\n        private void AddTextureCompressionElement(Rect rect, ReorderableList list)\n        {\n            var availableTextureCompressions = m_AvailableTextureCompressionsProvider();\n            var names = availableTextureCompressions\n                .Select(m => ToString(m))\n                .ToArray();\n            var enabled = availableTextureCompressions\n                .Select(m => !list.list.Contains(m))\n                .ToArray();\n\n            EditorUtility.DisplayCustomMenu(rect, names, enabled, null, AddTextureCompressionMenuSelected, availableTextureCompressions);\n        }\n\n        private void AddTextureCompressionMenuSelected(object userData, string[] options, int selected)\n        {\n            var textureCompressions = (TextureCompressionFormat[])userData;\n            if (textureCompressions[selected] == TextureCompressionFormat.DXTC_RGTC)\n            {\n                StoredTextureCompressionList.Remove(TextureCompressionFormat.DXTC);\n            }\n            else if (textureCompressions[selected] == TextureCompressionFormat.DXTC)\n            {\n                StoredTextureCompressionList.Remove(TextureCompressionFormat.DXTC_RGTC);\n            }\n\n            StoredTextureCompressionList.Add(textureCompressions[selected]);\n            m_IsDirty = true;\n        }\n\n        private string GetTextureFormatAsAString(TextureCompressionFormat[] formats)\n        {\n            return String.Join(\",\", formats);\n        }\n\n        private void Onchanged(ReorderableList list)\n        {\n            m_IsDirty = true;\n        }\n\n        private void RemoveTextureCompressionElement(ReorderableList list)\n        {\n            // don't allow removing the last TextureCompression\n            if (StoredTextureCompressionList.Count < 2)\n            {\n                EditorApplication.Beep();\n                return;\n            }\n\n            StoredTextureCompressionList.RemoveAt(list.index);\n            m_IsDirty = true;\n        }\n\n        private void ReorderTextureCompressionElement(ReorderableList list)\n        {\n            var textureCompressionsList = (List<TextureCompressionFormat>)list.list;\n            StoredTextureCompressionList = textureCompressionsList;\n            m_IsDirty = true;\n        }\n\n        private void DrawTextureCompressionElement(Rect rect, int index, bool selected, bool focused)\n        {\n            var textureCompression = TextureCompressionsList.list[index];\n            GUI.Label(rect, ToString((TextureCompressionFormat)textureCompression), EditorStyles.label);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsEmbeddedLinux.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityObject = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    public partial class PlayerSettings : UnityObject\n    {\n        [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        public sealed partial class EmbeddedLinux\n        {\n            // Custom path to store data files\n            [NativeProperty(\"HmiPlayerDataPath\")]\n            public static extern string playerDataPath { get; set; }\n\n            [NativeProperty(\"HmiForceSRGBBlit\")]\n            public static extern bool forceSRGBBlit { get; set; }\n\n            [NativeProperty(\"EmbeddedLinuxEnableGamepadInput\")]\n            public static extern bool enableGamepadInput { get; set; }\n\n            [NativeProperty(\"HmiCpuConfiguration\")]\n            public static extern int[] cpuConfiguration { get; set; }\n\n            [NativeProperty(\"HmiLoadingImage\")]\n            public static extern Texture2D hmiLoadingImage { get; set; }\n\n            [NativeProperty(\"HmiLogStartupTiming\")]\n            public static extern bool hmiLogStartupTiming { get; set; }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsFacebook.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Collections;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    public partial class PlayerSettings : UnityEngine.Object\n    {\n        [Obsolete(\"Facebook support was removed in 2019.3\", true)]\n        public partial class Facebook\n        {\n            public static string sdkVersion\n            {\n                get { throw new NotImplementedException(\"Facebook support was removed in 2019.3\"); }\n                set { throw new NotImplementedException(\"Facebook support was removed in 2019.3\"); }\n            }\n\n            public static string appId\n            {\n                get { throw new NotImplementedException(\"Facebook support was removed in 2019.3\"); }\n                set { throw new NotImplementedException(\"Facebook support was removed in 2019.3\"); }\n            }\n\n            public static bool useCookies\n            {\n                get { throw new NotImplementedException(\"Facebook support was removed in 2019.3\"); }\n                set { throw new NotImplementedException(\"Facebook support was removed in 2019.3\"); }\n            }\n\n            internal static bool useLogging\n            {\n                get { throw new NotImplementedException(\"Facebook support was removed in 2019.3\"); }\n                set { throw new NotImplementedException(\"Facebook support was removed in 2019.3\"); }\n            }\n\n            public static bool useStatus\n            {\n                get { throw new NotImplementedException(\"Facebook support was removed in 2019.3\"); }\n                set { throw new NotImplementedException(\"Facebook support was removed in 2019.3\"); }\n            }\n\n            internal static bool useXfbml\n            {\n                get { throw new NotImplementedException(\"Facebook support was removed in 2019.3\"); }\n                set { throw new NotImplementedException(\"Facebook support was removed in 2019.3\"); }\n            }\n\n            public static bool useFrictionlessRequests\n            {\n                get { throw new NotImplementedException(\"Facebook support was removed in 2019.3\"); }\n                set { throw new NotImplementedException(\"Facebook support was removed in 2019.3\"); }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsIOS.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\nusing UnityEditor.PlatformSupport;\nusing UnityEngine.Bindings;\n\nusing UnityEngine;\nusing UnityEditor.Build;\n\nnamespace UnityEditor\n{\n    // AppleMobile CPU architecture.\n    // Matches enum in EditorOnlyPlayerSettings.h.\n    // For Device\n    [Flags]\n    public enum AppleMobileArchitecture : uint\n    {\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"ARMv7 is no longer supported\", true)]\n        ARMv7 = 0,\n\n        ARM64 = 1 << 0,\n        Universal = 1 << 1\n    }\n\n    // For Simulator\n    public enum AppleMobileArchitectureSimulator\n    {\n        X86_64 = 0,\n        ARM64 = 1 << 0,\n        Universal = 1 << 1\n    }\n\n    // Supported iOS SDK versions\n    public enum iOSSdkVersion\n    {\n        // Device SDK\n        DeviceSDK = 988,\n        // Simulator SDK\n        SimulatorSDK = 989\n    }\n\n    // Target iOS device\n    public enum iOSTargetDevice\n    {\n        // iPhone/iPod Only\n        iPhoneOnly = 0,\n\n        // iPad Only\n        iPadOnly = 1,\n\n        // Universal : iPhone/iPod + iPad\n        iPhoneAndiPad = 2,\n    }\n\n    // \"Show Loading Indicator\" enums for the Player Settings\n    // Keep in sync with iOSDevice.bindings.cs ActivityIndicatorStyle which is the user script API\n    public enum iOSShowActivityIndicatorOnLoading\n    {\n        // Don't Show\n        DontShow = -1,\n\n        // WhiteLarge - Deprecated\n        [Obsolete(\"WhiteLarge Activity Indicator has been deprecated by Apple. Use Large instead (UnityUpgradable) -> Large\", true)]\n        WhiteLarge = 0,\n\n        // White - Deprecated\n        [Obsolete(\"White Activity Indicator has been deprecated by Apple. Use Medium instead (UnityUpgradable) -> Medium\", true)]\n        White = 1,\n\n        // Gray - Deprecated\n        [Obsolete(\"Gray Activity Indicator has been deprecated by Apple. Use Medium instead (UnityUpgradable) -> Medium\", true)]\n        Gray = 2,\n\n        // Medium (Old White and Gray)\n        Medium = 100,\n\n        // Large (Old WhiteLarge)\n        Large = 101,\n    }\n\n    // iOS status bar style\n    public enum iOSStatusBarStyle\n    {\n        // Default syle: iOS picks the automatically based on the user interface style.\n        Default = 0,\n\n        // A light status bar, intended for use on dark backgrounds\n        LightContent = 1,\n\n        // A dark status bar, intended for use on light backgrounds\n        DarkContent = 2,\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"BlackTranslucent has no effect, use LightContent instead (UnityUpgradable) -> LightContent\", true)]\n        BlackTranslucent = -1,\n\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        [Obsolete(\"BlackOpaque has no effect, use LightContent instead (UnityUpgradable) -> LightContent\", true)]\n        BlackOpaque = -1,\n    }\n\n    public enum iOSAppInBackgroundBehavior\n    {\n        Custom = -1,\n        Suspend = 0,\n\n        [Obsolete(\"UIApplicationExitsOnSuspend is no longer supported in iOS 13, use Custom or Suspend instead (UnityUpgradable) -> Custom\", true)]\n        Exit = 1,\n    }\n\n    [Flags]\n    public enum iOSBackgroundMode: uint\n    {\n        None                            = 0,\n        AudioAirplayPiP                 = 1 << 0,\n        LocationUpdates                 = 1 << 1,\n        VoiceOverIP                     = 1 << 2,\n        NewsstandDownloads              = 1 << 3,\n        ExternalAccessoryCommunication  = 1 << 4,\n        UsesBluetoothLEAccessory        = 1 << 5,\n        ActsAsABluetoothLEAccessory     = 1 << 6,\n        BackgroundFetch                 = 1 << 7,\n        RemoteNotifications             = 1 << 8,\n        Processing                      = 1 << 9,\n        NearbyInteraction               = 1 << 10,\n        NetworkAuthentication           = 1 << 11,\n        PushToTalk                      = 1 << 12,\n\n        // Obsolete/renamed values\n        [Obsolete(\"iOSBackgroundMode.Audio has been deprecated. Use AudioAirplayPiP instead (UnityUpgradable) -> AudioAirplayPiP\", true)]\n        Audio                           = AudioAirplayPiP,\n        [Obsolete(\"iOSBackgroundMode.Location has been deprecated. Use LocationUpdates instead (UnityUpgradable) -> LocationUpdates\", true)]\n        Location                        = LocationUpdates,\n        [Obsolete(\"iOSBackgroundMode.VoIP has been deprecated. Use VoiceOverIP instead (UnityUpgradable) -> VoiceOverIP\", true)]\n        VoIP                            = VoiceOverIP,\n        [Obsolete(\"iOSBackgroundMode.NewsstandContent has been deprecated. Use NewsstandDownloads instead (UnityUpgradable) -> NewsstandDownloads\", true)]\n        NewsstandContent                = NewsstandDownloads,\n        [Obsolete(\"iOSBackgroundMode.ExternalAccessory has been deprecated. Use ExternalAccessoryCommunication instead (UnityUpgradable) -> ExternalAccessoryCommunication\", true)]\n        ExternalAccessory               = ExternalAccessoryCommunication,\n        [Obsolete(\"iOSBackgroundMode.BluetoothCentral has been deprecated. Use UsesBluetoothLEAccessory instead (UnityUpgradable) -> UsesBluetoothLEAccessory\", true)]\n        BluetoothCentral                = UsesBluetoothLEAccessory,\n        [Obsolete(\"iOSBackgroundMode.BluetoothPeripheral has been deprecated. Use ActsAsABluetoothLEAccessory instead (UnityUpgradable) -> ActsAsABluetoothLEAccessory\", true)]\n        BluetoothPeripheral             = ActsAsABluetoothLEAccessory,\n        [Obsolete(\"iOSBackgroundMode.Fetch has been deprecated. Use BackgroundFetch instead (UnityUpgradable) -> BackgroundFetch\", true)]\n        Fetch                           = BackgroundFetch,\n        [Obsolete(\"iOSBackgroundMode.RemoteNotification has been deprecated. Use RemoteNotifications instead (UnityUpgradable) -> RemoteNotifications\", true)]\n        RemoteNotification              = RemoteNotifications,\n    }\n\n    public enum iOSLaunchScreenImageType\n    {\n        iPhonePortraitImage = 0,\n        iPhoneLandscapeImage = 1,\n        iPadImage = 2,\n    }\n\n    // extern splash screen type (on iOS)\n    public enum iOSLaunchScreenType\n    {\n        Default = 0,\n        ImageAndBackgroundRelative = 1,\n        ImageAndBackgroundConstant = 4,\n        CustomStoryboard = 5,\n\n        [Obsolete(\"CustomXib is no longer supported. Use CustomStoryboard instead\", true)]\n        CustomXib = 2,\n\n        [Obsolete(\"Launch Images are no longer supported by Apple. (UnityUpgradable) -> Default\", true)]\n        None = 3,\n    }\n\n    internal enum iOSAutomaticallySignValue\n    {\n        AutomaticallySignValueNotSet = 0,\n        AutomaticallySignValueTrue  = 1,\n        AutomaticallySignValueFalse = 2\n    }\n\n    public enum ProvisioningProfileType\n    {\n        Automatic,\n        Development,\n        Distribution\n    }\n\n    public class iOSDeviceRequirement\n    {\n        SortedDictionary<string, string> m_Values = new SortedDictionary<string, string>();\n        public IDictionary<string, string> values { get { return m_Values; } }\n    }\n\n    [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n    [NativeHeader(\"Editor/Src/PlayerSettingsIOS.bindings.h\")]\n    internal partial class iOSDeviceRequirementGroup\n    {\n        private PlayerSettings m_PlayerSettings;\n        private string m_VariantName;\n\n        [FreeFunction(\"PlayerSettingsIOSBindings::SetOrAddDeviceRequirementForVariantNameImpl\")]\n        extern private static void SetOrAddDeviceRequirementForVariantNameImpl(PlayerSettings playerSettings, string name, int index, [Unmarshalled] string[] keys, [Unmarshalled] string[] values);\n\n        [FreeFunction(\"PlayerSettingsIOSBindings::RemoveIOSDeviceRequirementForVariantNameImpl\")]\n        extern private static void RemoveIOSDeviceRequirementForVariantNameImpl(PlayerSettings playerSettings, string name, int index);\n\n        internal iOSDeviceRequirementGroup(string variantName)\n            : this(null, variantName)\n        {}\n\n        internal iOSDeviceRequirementGroup(PlayerSettings playerSettings, string variantName)\n        {\n            m_PlayerSettings = playerSettings;\n            m_VariantName = variantName;\n        }\n\n        [FreeFunction(\"PlayerSettingsIOSBindings::GetDeviceRequirementForVariantNameImpl\")]\n        extern private static void GetDeviceRequirementForVariantNameImplInternal(PlayerSettings playerSettings, string name, int index, [Out] string[] keys, [Out] string[] values);\n\n        [FreeFunction(\"PlayerSettingsIOSBindings::GetDeviceRequirementForVariantCount\")]\n        extern private static int GetDeviceRequirementForVariantCount(PlayerSettings playerSettings, string name, int index);\n\n        private static void GetDeviceRequirementForVariantNameImpl(PlayerSettings playerSettings, string name, int index, out string[] keys, out string[] values)\n        {\n            int requirementCount = GetDeviceRequirementForVariantCount(playerSettings, name, index);\n            keys = new string[requirementCount];\n            values = new string[requirementCount];\n            GetDeviceRequirementForVariantNameImplInternal(playerSettings, name, index, keys, values);\n        }\n\n        public int count\n        {\n            get\n            {\n                return (m_PlayerSettings != null)\n                    ? PlayerSettings.iOS.GetIOSDeviceRequirementCountForVariantName_Internal(m_PlayerSettings, m_VariantName)\n                    : PlayerSettings.iOS.GetIOSDeviceRequirementCountForVariantName(m_VariantName);\n            }\n        }\n\n        public iOSDeviceRequirement this[int index]\n        {\n            get\n            {\n                string[] keys;\n                string[] values;\n                GetDeviceRequirementForVariantNameImpl(m_PlayerSettings, m_VariantName, index, out keys, out values);\n                var result = new iOSDeviceRequirement();\n                for (int i = 0; i < keys.Length; ++i)\n                {\n                    result.values.Add(keys[i], values[i]);\n                }\n                return result;\n            }\n            set\n            {\n                SetOrAddDeviceRequirementForVariantNameImpl(m_PlayerSettings, m_VariantName, index, value.values.Keys.ToArray(),\n                    value.values.Values.ToArray());\n            }\n        }\n\n        public void RemoveAt(int index)\n        {\n            RemoveIOSDeviceRequirementForVariantNameImpl(m_PlayerSettings, m_VariantName, index);\n        }\n\n        public void Add(iOSDeviceRequirement requirement)\n        {\n            SetOrAddDeviceRequirementForVariantNameImpl(m_PlayerSettings, m_VariantName, -1, requirement.values.Keys.ToArray(),\n                requirement.values.Values.ToArray());\n        }\n    }\n\n\n    // Player Settings is where you define various parameters for the final game that you will build in Unity. Some of these values are used in the Resolution Dialog that launches when you open a standalone game.\n    public partial class PlayerSettings : UnityEngine.Object\n    {\n        // iOS specific player settings\n        [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n        [NativeHeader(\"Editor/Src/EditorUserBuildSettings.h\")]\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        public partial class iOS\n        {\n            // iOS application display name\n            [NativeProperty(\"ProductName\")]\n            public extern static string applicationDisplayName { get; set; }\n\n            // iOS bundle build number\n            public static string buildNumber\n            {\n                get { return PlayerSettings.GetBuildNumber(NamedBuildTarget.iOS.TargetName); }\n                set { PlayerSettings.SetBuildNumber(NamedBuildTarget.iOS.TargetName, value); }\n            }\n            public extern static bool disableDepthAndStencilBuffers  { get; set; }\n\n            // Script calling optimization\n            private extern static int  scriptCallOptimizationInternal\n            {\n                [NativeMethod(\"GetiPhoneScriptCallOptimization\")]\n                get;\n                [NativeMethod(\"SetiPhoneScriptCallOptimization\")]\n                set;\n            }\n            public static ScriptCallOptimizationLevel scriptCallOptimization\n            {\n                get { return (ScriptCallOptimizationLevel)scriptCallOptimizationInternal; }\n                set { scriptCallOptimizationInternal = (int)value; }\n            }\n\n            // Active iOS SDK version used for build\n            private extern static int sdkVersionInternal\n            {\n                [NativeMethod(\"GetiPhoneSdkVersion\")]\n                get;\n                [NativeMethod(\"SetiPhoneSdkVersion\")]\n                set;\n            }\n            public static iOSSdkVersion sdkVersion\n            {\n                get { return (iOSSdkVersion)sdkVersionInternal; }\n                set { sdkVersionInternal = (int)value; }\n            }\n\n            // Simulator Architectures\n            private extern static int simulatorSdkArchitectureInternal\n            {\n                [NativeMethod(\"GetiOSSimulatorArchitecture\")]\n                get;\n                [NativeMethod(\"SetiOSSimulatorArchitecture\")]\n                set;\n            }\n            public static AppleMobileArchitectureSimulator simulatorSdkArchitecture\n            {\n                get { return (AppleMobileArchitectureSimulator)simulatorSdkArchitectureInternal; }\n                set { simulatorSdkArchitectureInternal = (int)value; }\n            }\n\n            [FreeFunction]\n            private extern static string iOSTargetOSVersionObsoleteEnumToString(int val);\n\n            [FreeFunction]\n            private extern static int iOSTargetOSVersionStringToObsoleteEnum(string val);\n\n            // Deployment minimal version of iOS\n            [Obsolete(\"OBSOLETE warning targetOSVersion is obsolete, use targetOSVersionString\")]\n            public static iOSTargetOSVersion targetOSVersion\n            {\n                get\n                {\n                    return (iOSTargetOSVersion)iOSTargetOSVersionStringToObsoleteEnum(targetOSVersionString);\n                }\n                set\n                {\n                    targetOSVersionString = iOSTargetOSVersionObsoleteEnumToString((int)value);\n                }\n            }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"GetiOSMinimumVersionString\")]\n            static extern string GetMinimumVersionString();\n\n            internal static readonly Version minimumOsVersion = new Version(GetMinimumVersionString());\n\n            [NativeProperty(\"iOSTargetOSVersion\")]\n            public extern static string targetOSVersionString\n            {\n                [NativeMethod(\"GetiOSTargetOSVersion\")]\n                get;\n                [NativeMethod(\"SetiOSTargetOSVersion\")]\n                set;\n            }\n\n            // Targeted device\n            [NativeProperty(\"TargetDevice\")]\n            private extern static int  targetDeviceInternal { get; set; }\n\n\n            // Active iOS SDK version used for build\n            public static iOSTargetDevice targetDevice\n            {\n                get { return (iOSTargetDevice)targetDeviceInternal; }\n                set { targetDeviceInternal = (int)value; }\n            }\n\n            // Icon is prerendered\n            [NativeProperty(\"UIPrerenderedIcon\")]\n            public extern static bool prerenderedIcon { get; set; }\n\n            // Application requires persistent WiFi\n            [NativeProperty(\"UIRequiresPersistentWiFi\")]\n            public extern static bool requiresPersistentWiFi  { get; set; }\n\n            // Require Full Screen on iOS for iOS 9.0 Multitasking support\n            [NativeProperty(\"UIRequiresFullScreen\")]\n            public extern static bool requiresFullScreen  { get; set; }\n\n            // Status bar style\n            [NativeProperty(\"UIStatusBarStyle\")]\n            private extern static int  statusBarStyleInternal { get; set; }\n\n\n            [NativeProperty(\"UIStatusBarStyle\")]\n            public static iOSStatusBarStyle statusBarStyle\n            {\n                get { return (iOSStatusBarStyle)statusBarStyleInternal; }\n                set { statusBarStyleInternal = (int)value; }\n            }\n\n            // On iPhone 10 the home button is implemented as a system gesture. (swipe up\n            // from the lower edge). This might interfere with games that use swipes as\n            // an interaction method. iOS provides a way to reduce the chance of unwanted\n            // interaction by marking edges as \"protected\" edges, so the system gesture\n            // is not recognized on the first swipe, but on the second if it comes\n            // immediately afterwards.\n            [NativeProperty(\"DeferSystemGesturesMode\")]\n            private extern static int deferSystemGesturesModeInternal { get; set; }\n\n            public static UnityEngine.iOS.SystemGestureDeferMode deferSystemGesturesMode\n            {\n                get { return (UnityEngine.iOS.SystemGestureDeferMode)deferSystemGesturesModeInternal; }\n                set { deferSystemGesturesModeInternal = (int)value; }\n            }\n\n            [NativeProperty(\"HideHomeButton\")]\n            public extern static bool hideHomeButton { get; set; }\n\n            [NativeProperty(\"IOSAppInBackgroundBehavior\")]\n            private extern static int  appInBackgroundBehaviorInternal\n            {\n                [FreeFunction(\"PlayerSettingsIOSBindings::GetAppInBackgroundBehavior\")]\n                get;\n\n                [FreeFunction(\"PlayerSettingsIOSBindings::SetAppInBackgroundBehavior\")]\n                set;\n            }\n\n            public static iOSAppInBackgroundBehavior appInBackgroundBehavior\n            {\n                get { return (iOSAppInBackgroundBehavior)appInBackgroundBehaviorInternal; }\n                set { appInBackgroundBehaviorInternal = (int)value; }\n            }\n\n            [NativeProperty(\"IOSBackgroundModes\")]\n            private extern static int  backgroundModesInternal { get; set; }\n\n            [NativeProperty(\"IOSAppInBackgroundBehavior\")]\n            public static iOSBackgroundMode backgroundModes\n            {\n                get { return (iOSBackgroundMode)backgroundModesInternal; }\n                set { backgroundModesInternal = (int)value; }\n            }\n\n            [NativeProperty(\"IOSMetalForceHardShadows\")]\n            public extern static bool forceHardShadowsOnMetal\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [Obsolete(\"Use PlayerSettings.insecureHttpOption\", false)]\n            public static bool allowHTTPDownload\n            {\n                get { return PlayerSettings.insecureHttpOption == InsecureHttpOption.AlwaysAllowed; }\n                set { PlayerSettings.insecureHttpOption = value ? InsecureHttpOption.AlwaysAllowed : InsecureHttpOption.NotAllowed; }\n            }\n\n            [NativeProperty(\"AppleDeveloperTeamID\")]\n            private extern static string appleDeveloperTeamIDInternal\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            public static string appleDeveloperTeamID\n            {\n                get\n                {\n                    return appleDeveloperTeamIDInternal.Length < 1 ?\n                        EditorPrefs.GetString(\"DefaultiOSAutomaticSignTeamId\") : appleDeveloperTeamIDInternal;\n                }\n                set { appleDeveloperTeamIDInternal = value; }\n            }\n\n\n            [NativeProperty(\"iOSManualProvisioningProfileID\")]\n            private extern static string iOSManualProvisioningProfileIDInternal\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            public static string iOSManualProvisioningProfileID\n            {\n                get\n                {\n                    return String.IsNullOrEmpty(iOSManualProvisioningProfileIDInternal) ?\n                        EditorPrefs.GetString(\"DefaultiOSProvisioningProfileUUID\") : iOSManualProvisioningProfileIDInternal;\n                }\n                set\n                {\n                    iOSManualProvisioningProfileIDInternal = value;\n                }\n            }\n\n\n            [NativeProperty(\"tvOSManualProvisioningProfileID\")]\n            private extern static string tvOSManualProvisioningProfileIDInternal\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            public static string tvOSManualProvisioningProfileID\n            {\n                get\n                {\n                    return String.IsNullOrEmpty(tvOSManualProvisioningProfileIDInternal) ?\n                        EditorPrefs.GetString(\"DefaulttvOSProvisioningProfileUUID\") : tvOSManualProvisioningProfileIDInternal;\n                }\n                set\n                {\n                    tvOSManualProvisioningProfileIDInternal = value;\n                }\n            }\n\n\n            [NativeProperty(\"VisionOSManualProvisioningProfileID\")]\n            private extern static string VisionOSManualProvisioningProfileIDInternal\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            public static string VisionOSManualProvisioningProfileID\n            {\n                get\n                {\n                    return String.IsNullOrEmpty(VisionOSManualProvisioningProfileIDInternal) ?\n                        EditorPrefs.GetString(\"DefaultVisionOSProvisioningProfileUUID\") : VisionOSManualProvisioningProfileIDInternal;\n                }\n                set\n                {\n                    VisionOSManualProvisioningProfileIDInternal = value;\n                }\n            }\n\n            [NativeProperty(\"tvOSManualProvisioningProfileType\")]\n            public static extern ProvisioningProfileType tvOSManualProvisioningProfileType\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"iOSManualProvisioningProfileType\")]\n            public static extern ProvisioningProfileType iOSManualProvisioningProfileType\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"VisionOSManualProvisioningProfileType\")]\n            public static extern ProvisioningProfileType VisionOSManualProvisioningProfileType\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"AppleEnableAutomaticSigning\")]\n            private extern static int appleEnableAutomaticSigningInternal\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            public static bool appleEnableAutomaticSigning\n            {\n                get\n                {\n                    return appleEnableAutomaticSigningInternal == (int)iOSAutomaticallySignValue.AutomaticallySignValueNotSet ?\n                        EditorPrefs.GetBool(\"DefaultiOSAutomaticallySignBuild\") :\n                        (iOSAutomaticallySignValue)appleEnableAutomaticSigningInternal == iOSAutomaticallySignValue.AutomaticallySignValueTrue;\n                }\n                set\n                {\n                    appleEnableAutomaticSigningInternal = value ?\n                        (int)iOSAutomaticallySignValue.AutomaticallySignValueTrue :\n                        (int)iOSAutomaticallySignValue.AutomaticallySignValueFalse;\n                }\n            }\n\n\n            [NativeProperty(\"CameraUsageDescription\")]\n            public extern static string cameraUsageDescription { get; set; }\n\n            [NativeProperty(\"LocationUsageDescription\")]\n            public extern static string locationUsageDescription { get; set; }\n\n            [NativeProperty(\"MicrophoneUsageDescription\")]\n            public extern static string microphoneUsageDescription { get; set; }\n\n            [NativeProperty(\"IOSShowActivityIndicatorOnLoading\")]\n            private extern static int  showActivityIndicatorOnLoadingInternal { get; set; }\n\n            // Application should show ActivityIndicator when loading\n            [NativeProperty(\"IOSAppInBackgroundBehavior\")]\n            public static iOSShowActivityIndicatorOnLoading showActivityIndicatorOnLoading\n            {\n                get { return (iOSShowActivityIndicatorOnLoading)showActivityIndicatorOnLoadingInternal; }\n                set { showActivityIndicatorOnLoadingInternal = (int)value; }\n            }\n\n            [NativeProperty(\"UseOnDemandResources\")]\n            public extern static bool useOnDemandResources  { get; set; }\n\n            // will be public\n            [NativeMethod(Name = \"GetIOSVariantsWithDeviceRequirements\")]\n            extern internal static string[] GetAssetBundleVariantsWithDeviceRequirements();\n            [NativeMethod(Name = \"GetIOSVariantsWithDeviceRequirements_Internal\")]\n            [StaticAccessor(\"PlayerSettings\", StaticAccessorType.DoubleColon)]\n            extern internal static string[] GetAssetBundleVariantsWithDeviceRequirements_Internal(PlayerSettings instance);\n\n            internal static extern int GetIOSDeviceRequirementCountForVariantName(string name);\n            internal static extern int GetIOSDeviceRequirementCountForVariantName_Internal(PlayerSettings instance, string name);\n\n            private static bool CheckAssetBundleVariantHasDeviceRequirements(string name)\n            {\n                return GetIOSDeviceRequirementCountForVariantName(name) > 0;\n            }\n            private static bool CheckAssetBundleVariantHasDeviceRequirements_Internal(PlayerSettings instance, string name)\n            {\n                return GetIOSDeviceRequirementCountForVariantName_Internal(instance, name) > 0;\n            }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeProperty(\"iOSLaunchScreenPortrait\", TargetType.Field)]\n            internal extern static Texture2D launchScreenPortrait { get; }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeProperty(\"iOSLaunchScreenLandscape\", TargetType.Field)]\n            internal extern static Texture2D launchScreenLandscape { get; }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeProperty(\"iOSLaunchScreeniPadImage\", TargetType.Field)]\n            internal extern static Texture2D launchScreeniPadImage { get; }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            [NativeMethod(Name = \"SetiOSLaunchScreenImage\")]\n            private extern static void SetLaunchScreenImageInternal(Texture2D image, int type);\n\n            public static void SetLaunchScreenImage(Texture2D image, iOSLaunchScreenImageType type)\n            {\n                SetLaunchScreenImageInternal(image, (int)type);\n            }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            private extern static void SetiOSLaunchScreenType(int type, int device);\n\n            public static void SetiPhoneLaunchScreenType(iOSLaunchScreenType type)\n            {\n                SetiOSLaunchScreenType((int)type, 0);\n            }\n\n            public static void SetiPadLaunchScreenType(iOSLaunchScreenType type)\n            {\n                SetiOSLaunchScreenType((int)type, 1);\n            }\n\n            // will be public\n            internal static iOSDeviceRequirementGroup GetDeviceRequirementsForAssetBundleVariant(string name)\n            {\n                if (!CheckAssetBundleVariantHasDeviceRequirements(name))\n                    return null;\n                return new iOSDeviceRequirementGroup(name);\n            }\n            internal static iOSDeviceRequirementGroup GetDeviceRequirementsForAssetBundleVariant_Internal(PlayerSettings instance, string name)\n            {\n                if (!CheckAssetBundleVariantHasDeviceRequirements_Internal(instance, name))\n                    return null;\n                return new iOSDeviceRequirementGroup(instance, name);\n            }\n\n            // will be public\n            internal static void RemoveDeviceRequirementsForAssetBundleVariant(string name)\n            {\n                var group = GetDeviceRequirementsForAssetBundleVariant(name);\n                for (int i = 0; i < group.count; ++i)\n                    group.RemoveAt(0);\n            }\n\n            // will be public\n            internal static iOSDeviceRequirementGroup AddDeviceRequirementsForAssetBundleVariant(string name)\n            {\n                return new iOSDeviceRequirementGroup(name);\n            }\n            internal static iOSDeviceRequirementGroup AddDeviceRequirementsForAssetBundleVariant_Internal(PlayerSettings instance, string name)\n            {\n                return new iOSDeviceRequirementGroup(instance, name);\n            }\n\n            [NativeProperty(\"iOSURLSchemes\", false, TargetType.Function)]\n            public extern static string[] iOSUrlSchemes\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"iOSRequireARKit\")]\n            internal extern static bool requiresARKitSupport\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            internal extern static bool appleEnableProMotion\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n\n            [NativeProperty(\"iOSAutomaticallyDetectAndAddCapabilities\")]\n            internal extern static bool automaticallyDetectAndAddCapabilities\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n\n            internal static bool IsTargetVersionEqualOrHigher(Version requiredVersion)\n            {\n                Version requestedVersion;\n                try\n                {\n                    requestedVersion = new Version(targetOSVersionString);\n                }\n                catch (Exception)\n                {\n                    requestedVersion = minimumOsVersion;\n                }\n                return requestedVersion >= requiredVersion;\n            }\n\n            internal static string[] GetURLSchemes()\n            {\n                return iOSUrlSchemes;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsLumin.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\nusing UnityObject = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    public partial class PlayerSettings : UnityObject\n    {\n        [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n        public sealed partial class Lumin\n        {\n            [NativeProperty(\"LuminIconModelFolderPath\")]\n            public extern static string iconModelFolderPath\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"LuminIconPortalFolderPath\")]\n            public extern static string iconPortalFolderPath\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"LuminCertificatePath\")]\n            public extern static string certificatePath\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"LuminSignPackage\")]\n            public extern static bool signPackage\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"LuminIsChannelApp\")]\n            public extern static bool isChannelApp\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"LuminVersionCode\")]\n            public extern static int versionCode\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"LuminVersionName\")]\n            public extern static string versionName\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsMacOS.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.Build;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    public partial class PlayerSettings : UnityEngine.Object\n    {\n        [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        public class macOS\n        {\n            public static string buildNumber\n            {\n                get { return PlayerSettings.GetBuildNumber(NamedBuildTarget.Standalone.TargetName); }\n                set { PlayerSettings.SetBuildNumber(NamedBuildTarget.Standalone.TargetName, value); }\n            }\n\n            [NativeProperty(\"MacAppStoreCategory\")]\n            public extern static string applicationCategoryType  { get; set; }\n\n            // these four WERE internal because we are not yet sure if we want to have them back in general PlayerSettings\n            // as we have several platforms that might want to use it\n            [NativeProperty(\"CameraUsageDescription\")]\n            public extern static string cameraUsageDescription { get; set; }\n\n            [NativeProperty(\"MicrophoneUsageDescription\")]\n            public extern static string microphoneUsageDescription { get; set; }\n\n            [NativeProperty(\"BluetoothUsageDescription\")]\n            public extern static string bluetoothUsageDescription { get; set; }\n\n            [NativeProperty(\"macOSURLSchemes\", false, TargetType.Function)]\n            public extern static string[] urlSchemes\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"macOSTargetOSVersion\")]\n            public extern static string targetOSVersion { get; set; }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"GetMacOSMinimumVersionString\")]\n            internal static extern string GetMinimumVersionString();\n            internal static readonly Version minimumOsVersion = new Version(GetMinimumVersionString());\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsPS4.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing System;\nusing System.Runtime.CompilerServices;\n\nnamespace UnityEditor\n{\n    public sealed partial class PlayerSettings\n    {\n        [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n        public sealed partial class PS4\n        {\n            public enum PS4AppCategory\n            {\n                Application = 0,    // Application package.\n                Patch = 1,          // Patch\n                Remaster = 2,       // Remaster package\n            }\n\n            public enum PS4RemotePlayKeyAssignment\n            {\n                None = -1,\n                PatternA = 0,\n                PatternB = 1,\n                PatternC = 2,\n                PatternD = 3,\n                PatternE = 4,\n                PatternF = 5,\n                PatternG = 6,\n                PatternH = 7,\n            }\n\n            public enum PS4EnterButtonAssignment\n            {\n                CircleButton = 0,\n                CrossButton = 1,\n                SystemDefined = 2,\n            }\n\n            public enum PlayStationVREyeToEyeDistanceSettings\n            {\n                PerUser = 0,\n                ForceDefault = 1,\n                DynamicModeAtRuntime = 2,\n            }\n\n            [NativeProperty(\"ps4NPTrophyPackPath\")] extern public static string npTrophyPackPath { get; set; }\n            [NativeProperty(\"ps4NPAgeRating\", false, TargetType.Field)] extern public static int npAgeRating { get; set; }\n            [NativeProperty(\"ps4NPTitleSecret\", false, TargetType.Function)] extern public static string npTitleSecret { get; set; }\n            [NativeProperty(\"ps4ParentalLevel\", false, TargetType.Field)] extern public static int parentalLevel { get; set; }\n            [NativeProperty(\"ps4ApplicationParam1\", false, TargetType.Field)] extern public static int applicationParameter1 { get; set; }\n            [NativeProperty(\"ps4ApplicationParam2\", false, TargetType.Field)] extern public static int applicationParameter2 { get; set; }\n            [NativeProperty(\"ps4ApplicationParam3\", false, TargetType.Field)] extern public static int applicationParameter3 { get; set; }\n            [NativeProperty(\"ps4ApplicationParam4\", false, TargetType.Field)] extern public static int applicationParameter4 { get; set; }\n            [NativeProperty(\"ps4Passcode\", false, TargetType.Function)] extern public static string passcode { get; set; }\n            [NativeProperty(\"monoEnv\", false, TargetType.Function)] extern public static string monoEnv { get; set; }\n            [NativeProperty(TargetType = TargetType.Field)] extern public static bool playerPrefsSupport { get; set; }\n            [NativeProperty(TargetType = TargetType.Field)] extern public static bool restrictedAudioUsageRights { get; set; }\n            [NativeProperty(\"ps4UseResolutionFallback\", false, TargetType.Field)] extern public static bool useResolutionFallback { get; set; }\n            [NativeProperty(\"ps4ContentID\", false, TargetType.Function)] extern public static string contentID { get; set; }\n            [NativeProperty(\"ps4Category\", false, TargetType.Field)] extern public static PS4AppCategory category { get; set; }\n            [NativeProperty(\"ps4AppType\", false, TargetType.Field)] extern public static int appType { get; set; }\n            [NativeProperty(\"ps4MasterVersion\", false, TargetType.Function)] extern public static string masterVersion { get; set; }\n            [NativeProperty(\"ps4AppVersion\", false, TargetType.Function)] extern public static string appVersion { get; set; }\n            [NativeProperty(\"ps4RemotePlayKeyAssignment\", false, TargetType.Field)] extern public static PS4RemotePlayKeyAssignment remotePlayKeyAssignment { get; set; }\n            [NativeProperty(\"ps4RemotePlayKeyMappingDir\", false, TargetType.Function)] extern public static string remotePlayKeyMappingDir { get; set; }\n            [NativeProperty(\"ps4PlayTogetherPlayerCount\", false, TargetType.Field)] extern public static int playTogetherPlayerCount { get; set; }\n            [NativeProperty(\"ps4EnterButtonAssignment\", false, TargetType.Field)] extern public static PS4EnterButtonAssignment enterButtonAssignment { get; set; }\n            [NativeProperty(\"ps4ParamSfxPath\", false, TargetType.Function)] extern public static string paramSfxPath { get; set; }\n            [NativeProperty(\"ps4VideoOutPixelFormat\", false, TargetType.Field)] extern public static int videoOutPixelFormat { get; set; }\n            [NativeProperty(\"ps4VideoOutInitialWidth\", false, TargetType.Field)] extern public static int videoOutInitialWidth { get; set; }\n\n            [Obsolete(\"videoOutResolution is deprecated. Use PlayerSettings.PS4.videoOutInitialWidth and PlayerSettings.PS4.videoOutReprojectionRate to control initial display resolution and reprojection rate.\")]\n            public static int videoOutResolution\n            {\n                get\n                {\n                    int reprojectionRate = videoOutReprojectionRate;\n                    int initialWidth = videoOutInitialWidth;\n                    switch (reprojectionRate)\n                    { // if we have any projection rates then assume we have 1920x1080 res\n                        case 60:\n                            return 5; // 1920By1080_VR60\n                        case 90:\n                            return 6; // 1920By1080_VR90\n                        case 120:\n                            return 7; // 1920By1080_VR120\n                        default:\n                            switch (initialWidth)\n                            {\n                                case 1280:\n                                    return 0; // 1280By720\n                                case 1440:\n                                    return 1; // 1440By810\n                                case 1600:\n                                    return 2; // 1660By900\n                                case 1760:\n                                    return 3; // 1760By990\n                                default:\n                                case 1920:\n                                    return 4; // 1920By1080\n                            }\n                    }\n                }\n                set\n                {\n                    int reprojectionRate = 0;\n                    int initialWidth = 1920;\n                    switch (value)\n                    {\n                        case 0:\n                            initialWidth = 1280;\n                            break;\n                        case 1:\n                            initialWidth = 1440;\n                            break;\n                        case 2:\n                            initialWidth = 1600;\n                            break;\n                        case 3:\n                            initialWidth = 1760;\n                            break;\n                        case 4:\n                            initialWidth = 1920;\n                            break;\n                        case 5:\n                            reprojectionRate = 60;\n                            break;\n                        case 6:\n                            reprojectionRate = 90;\n                            break;\n                        case 7:\n                            reprojectionRate = 120;\n                            break;\n                    }\n                    videoOutInitialWidth = initialWidth;\n                    videoOutReprojectionRate = reprojectionRate;\n                }\n            }\n\n            public static string SdkOverride\n            {\n                get\n                {\n                    return SdkOverrideInternal;\n                }\n\n                set\n                {\n                    SdkOverrideInternal = value;\n\n                    string newSDK = value;\n                    if (String.IsNullOrEmpty(newSDK))\n                    {\n                        // newSDK is an empty path which is perfectly valid for the player settings and the UI where an empty path means \"use the SDK set in the\n                        // system environment\".  We need the underlying environment to always have a valid SDK path so use the SDK that was set in SCE_ORBIS_SDK_DIR\n                        // when the editor was launched, which we recorded in the SCE_ORBIS_SDK_DIR_ORIGINAL env var.\n                        newSDK = Environment.GetEnvironmentVariable(\"SCE_ORBIS_SDK_DIR_ORIGINAL\");\n                    }\n                    Environment.SetEnvironmentVariable(\"SCE_ORBIS_SDK_DIR\", newSDK);\n                    UnityEditor.PlayerSettings.ReinitialiseShaderCompiler(\"SCE_ORBIS_SDK_DIR\", newSDK);\n                }\n            }\n\n            [NativeProperty(\"ps4VideoOutBaseModeInitialWidth\", false, TargetType.Field)] extern public static int videoOutBaseModeInitialWidth { get; set; }\n            [NativeProperty(\"ps4VideoOutReprojectionRate\", false, TargetType.Field)] extern public static int videoOutReprojectionRate { get; set; }\n            [NativeProperty(\"ps4PronunciationXMLPath\", false, TargetType.Function)] extern public static string PronunciationXMLPath { get; set; }\n            [NativeProperty(\"ps4PronunciationSIGPath\", false, TargetType.Function)] extern public static string PronunciationSIGPath { get; set; }\n            [NativeProperty(\"ps4BackgroundImagePath\", false, TargetType.Function)] extern public static string BackgroundImagePath { get; set; }\n            [NativeProperty(\"ps4StartupImagePath\", false, TargetType.Function)] extern public static string StartupImagePath { get; set; }\n            [NativeProperty(\"ps4StartupImagesFolder\", false, TargetType.Function)] extern public static string startupImagesFolder { get; set; }\n            [NativeProperty(\"ps4IconImagesFolder\", false, TargetType.Function)] extern public static string iconImagesFolder { get; set; }\n            [NativeProperty(\"ps4SaveDataImagePath\", false, TargetType.Function)] extern public static string SaveDataImagePath { get; set; }\n            [NativeProperty(\"ps4SdkOverride\", false, TargetType.Function)] extern private static string SdkOverrideInternal { get; set; }\n            [NativeProperty(\"ps4BGMPath\", false, TargetType.Function)] extern public static string BGMPath { get; set; }\n            [NativeProperty(\"ps4ShareFilePath\", false, TargetType.Function)] extern public static string ShareFilePath { get; set; }\n            [NativeProperty(\"ps4ShareOverlayImagePath\", false, TargetType.Function)] extern public static string ShareOverlayImagePath { get; set; }\n            [NativeProperty(\"ps4PrivacyGuardImagePath\", false, TargetType.Function)] extern public static string PrivacyGuardImagePath { get; set; }\n            [NativeProperty(\"ps4ExtraSceSysFile\", false, TargetType.Function)] extern public static string ExtraSceSysFile { get; set; }\n            [NativeProperty(\"ps4PatchDayOne\", false, TargetType.Field)] extern public static bool patchDayOne { get; set; }\n            [NativeProperty(\"ps4PatchPkgPath\", false, TargetType.Function)] extern public static string PatchPkgPath { get; set; }\n            [NativeProperty(\"ps4PatchLatestPkgPath\", false, TargetType.Function)] extern public static string PatchLatestPkgPath { get; set; }\n            [NativeProperty(\"ps4PatchChangeinfoPath\", false, TargetType.Function)] extern public static string PatchChangeinfoPath { get; set; }\n            [NativeProperty(\"ps4NPtitleDatPath\", false, TargetType.Function)] extern public static string NPtitleDatPath { get; set; }\n            [NativeProperty(\"ps4pnSessions\", false, TargetType.Field)] extern public static bool pnSessions { get; set; }\n            [NativeProperty(\"ps4pnPresence\", false, TargetType.Field)] extern public static bool pnPresence { get; set; }\n            [NativeProperty(\"ps4pnFriends\", false, TargetType.Field)] extern public static bool pnFriends { get; set; }\n            [NativeProperty(\"ps4pnGameCustomData\", false, TargetType.Field)] extern public static bool pnGameCustomData { get; set; }\n            [NativeProperty(\"ps4DownloadDataSize\", false, TargetType.Field)] extern public static int downloadDataSize { get; set; }\n            [NativeProperty(\"ps4GarlicHeapSize\", false, TargetType.Field)] extern public static int garlicHeapSize { get; set; }\n            [NativeProperty(\"ps4ProGarlicHeapSize\", false, TargetType.Field)] extern public static int proGarlicHeapSize { get; set; }\n            [NativeProperty(\"ps4ReprojectionSupport\", false, TargetType.Field)] extern public static bool reprojectionSupport { get; set; }\n            [NativeProperty(\"ps4UseAudio3dBackend\", false, TargetType.Field)] extern public static bool useAudio3dBackend { get; set; }\n            [NativeProperty(\"ps4Audio3dVirtualSpeakerCount\", false, TargetType.Field)] extern public static int audio3dVirtualSpeakerCount { get; set; }\n            [Obsolete(\"Use PlayerSettings.SetIl2CppCompilerConfiguration() instead.\")] public static int scriptOptimizationLevel { get; set; }\n            [NativeProperty(\"ps4UseLowGarlicFragmentationMode\", true, TargetType.Field)] extern public static bool useLowGarlicFragmentationMode { get; set; }\n            [NativeProperty(\"ps4SocialScreenEnabled\", false, TargetType.Field)] extern public static int socialScreenEnabled { get; set; }\n            [NativeProperty(\"ps4attribUserManagement\", false, TargetType.Field)] extern public static bool attribUserManagement { get; set; }\n            [NativeProperty(\"ps4attribMoveSupport\", false, TargetType.Field)] extern public static bool attribMoveSupport { get; set; }\n            [NativeProperty(\"ps4attrib3DSupport\", false, TargetType.Field)] extern public static bool attrib3DSupport { get; set; }\n            [NativeProperty(\"ps4attribShareSupport\", false, TargetType.Field)] extern public static bool attribShareSupport { get; set; }\n            [NativeProperty(\"ps4attribExclusiveVR\", false, TargetType.Field)] extern public static bool attribExclusiveVR { get; set; }\n            [NativeProperty(\"ps4disableAutoHideSplash\", false, TargetType.Field)] extern public static bool disableAutoHideSplash { get; set; }\n            [NativeProperty(\"ps4attribCpuUsage\", false, TargetType.Field)] extern public static int attribCpuUsage { get; set; }\n            [NativeProperty(\"ps4videoRecordingFeaturesUsed\", false, TargetType.Field)] extern public static bool videoRecordingFeaturesUsed { get; set; }\n            [NativeProperty(\"ps4contentSearchFeaturesUsed\", false, TargetType.Field)] extern public static bool contentSearchFeaturesUsed { get; set; }\n            [NativeProperty(\"ps4attribEyeToEyeDistanceSettingVR\", false, TargetType.Field)] extern public static PlayStationVREyeToEyeDistanceSettings attribEyeToEyeDistanceSettingVR { get; set; }\n            [NativeProperty(\"ps4IncludedModules\", false, TargetType.Function)] extern public static string[] includedModules { get; set; }\n            [NativeProperty(TargetType = TargetType.Field)] extern public static bool enableApplicationExit { get; set; }\n            [NativeProperty(TargetType = TargetType.Field)] extern public static bool resetTempFolder { get; set; }\n            [NativeProperty(TargetType = TargetType.Field)] extern public static int playerPrefsMaxSize { get; set; }\n            [NativeProperty(\"ps4attribVROutputEnabled\", false, TargetType.Field)] extern public static bool attribVROutputEnabled { get; set; }\n            [NativeProperty(\"ps4CompatibilityPS5\", false, TargetType.Field)] extern public static bool compatibilityPS5 { get; set; }\n            [NativeProperty(\"ps4AllowPS5Detection\", false, TargetType.Field)] extern public static bool allowPS5Detection { get; set; }\n            [NativeProperty(\"ps4GPU800MHz\", false, TargetType.Field)] extern public static bool gpu800MHz { get; set; }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsQNX.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityObject = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    public partial class PlayerSettings : UnityObject\n    {\n        [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n        [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n        public sealed partial class QNX\n        {\n            // Custom path to store data files\n            [NativeProperty(\"HmiPlayerDataPath\")]\n            public static extern string playerDataPath { get; set; }\n\n            [NativeProperty(\"HmiForceSRGBBlit\")]\n            public static extern bool forceSRGBBlit { get; set; }\n\n            [NativeProperty(\"HmiCpuConfiguration\")]\n            public static extern int[] cpuConfiguration { get; set; }\n\n            [NativeProperty(\"HmiLoadingImage\")]\n            public static extern Texture2D hmiLoadingImage { get; set; }\n\n            [NativeProperty(\"HmiLogStartupTiming\")]\n            public static extern bool hmiLogStartupTiming { get; set; }\n\n\n            [NativeProperty(\"qnxGraphicConfPath\", false, TargetType.Function)]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            public static extern string graphicConfPath { get; set; }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsSplashScreen.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Collections.Generic;\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Internal;\n\nnamespace UnityEditor\n{\n    public partial class PlayerSettings\n    {\n        partial struct SplashScreenLogo\n        {\n            [ExcludeFromDocs]\n            public static PlayerSettings.SplashScreenLogo Create(float duration)\n            {\n                Sprite logo = null;\n                return PlayerSettings.SplashScreenLogo.Create(duration, logo);\n            }\n\n            [ExcludeFromDocs]\n            public static PlayerSettings.SplashScreenLogo Create()\n            {\n                Sprite logo = null;\n                float duration = k_MinLogoTime;\n                return PlayerSettings.SplashScreenLogo.Create(duration, logo);\n            }\n\n            public static PlayerSettings.SplashScreenLogo Create([DefaultValue(\"k_MinLogoTime\")] float duration, [DefaultValue(\"null\")] Sprite logo)\n            {\n                return new PlayerSettings.SplashScreenLogo\n                {\n                    m_Duration = duration,\n                    m_Logo = logo\n                };\n            }\n\n            [ExcludeFromDocs]\n            public static PlayerSettings.SplashScreenLogo CreateWithUnityLogo()\n            {\n                float duration = k_MinLogoTime;\n                return PlayerSettings.SplashScreenLogo.CreateWithUnityLogo(duration);\n            }\n\n            public static PlayerSettings.SplashScreenLogo CreateWithUnityLogo([DefaultValue(\"k_MinLogoTime\")] float duration)\n            {\n                return new PlayerSettings.SplashScreenLogo\n                {\n                    m_Duration = duration,\n                    m_Logo = PlayerSettings.SplashScreenLogo.s_UnityLogo\n                };\n            }\n        }\n\n        [StaticAccessor(\"GetPlayerSettings().GetSplashScreenSettings()\", StaticAccessorType.Dot)]\n        [NativeHeader(\"Editor/Mono/PlayerSettingsSplashScreen.bindings.h\")]\n        public partial class SplashScreen\n        {\n            [NativeName(\"SplashScreenAnimation\")]\n            public static extern AnimationMode animationMode { get; set; }\n\n            [NativeName(\"SplashScreenBackgroundZoom\")]\n            public static extern float animationBackgroundZoom { get; set; }\n\n            [NativeName(\"SplashScreenLogoZoom\")]\n            public static extern float animationLogoZoom { get; set; }\n\n            public static extern Sprite background\n            {\n                [FreeFunction(\"GetSplashScreenBackgroundSourceLandscape\")]\n                get;\n                [FreeFunction(\"SetSplashScreenBackgroundSourceLandscape\")]\n                set;\n            }\n\n            public static extern Sprite backgroundPortrait\n            {\n                [FreeFunction(\"GetSplashScreenBackgroundSourcePortrait\")]\n                get;\n                [FreeFunction(\"SetSplashScreenBackgroundSourcePortrait\")]\n                set;\n            }\n\n            public static extern bool blurBackgroundImage\n            {\n                [FreeFunction(\"GetBlurSplashScreenBackground\")]\n                get;\n                [FreeFunction(\"SetBlurSplashScreenBackground\")]\n                set;\n            }\n\n            [NativeName(\"SplashScreenBackgroundColor\")]\n            public static extern Color backgroundColor { get; set; }\n\n            [NativeName(\"SplashScreenDrawMode\")]\n            public static extern DrawMode drawMode { get; set; }\n\n            [NativeName(\"SplashScreenLogos\")]\n            public static extern SplashScreenLogo[] logos { get; [FreeFunction(\"SetLogos\")] set; }\n\n            [NativeName(\"SplashScreenOverlayOpacity\")]\n            public static extern float overlayOpacity { get; set; }\n\n            [NativeName(\"ShowUnitySplashScreen\")]\n            public static extern bool show { get; set; }\n\n            [NativeName(\"ShowUnitySplashLogo\")]\n            public static extern bool showUnityLogo { get; set; }\n\n            [NativeName(\"SplashScreenLogoStyle\")]\n            public static extern UnityLogoStyle unityLogoStyle { get; set; }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsSplashScreen.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor\n{\n    public partial class PlayerSettings : UnityEngine.Object\n    {\n        public partial class SplashScreen\n        {\n            public enum AnimationMode\n            {\n                Static = 0,\n                Dolly = 1,\n                Custom = 2\n            }\n\n            public enum DrawMode\n            {\n                UnityLogoBelow = 0,\n                AllSequential = 1\n            }\n\n            public enum UnityLogoStyle\n            {\n                DarkOnLight = 0,\n                LightOnDark = 1\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsSwitch.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing System;\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Collections.Generic;\nusing System.IO;\n\nnamespace UnityEditor\n{\n    // Player Settings is where you define various parameters for the final game that you will build in Unity. Some of these values are used in the Resolution Dialog that launches when you open a standalone game.\n    public sealed partial class PlayerSettings\n    {\n        // Nintendo Switch specific player settings\n        [NativeHeader(\"Editor/Mono/PlayerSettingsSwitch.bindings.h\")]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n        public sealed partial class Switch\n        {\n            public enum ScreenResolutionBehavior\n            {\n                Manual = 0,\n                OperationMode = 1,\n                PerformanceMode = 2,\n                Both = 3\n            }\n\n            private enum SupportedNpadStyleBits\n            {\n                FullKey = 1,\n                Handheld = 2,\n                JoyDual = 4,\n                JoyLeft = 8,\n                JoyRight = 16,\n            }\n\n            [Flags]\n            public enum SupportedNpadStyle\n            {\n                FullKey = (1 << SupportedNpadStyleBits.FullKey),\n                Handheld = (1 << SupportedNpadStyleBits.Handheld),\n                JoyDual = (1 << SupportedNpadStyleBits.JoyDual),\n                JoyLeft = (1 << SupportedNpadStyleBits.JoyLeft),\n                JoyRight = (1 << SupportedNpadStyleBits.JoyRight),\n            }\n\n            // Socket Memory Pool Size\n            [NativeProperty(\"switchSocketMemoryPoolSize\", TargetType.Field)]\n            extern public static int socketMemoryPoolSize { get; set; }\n\n            // Socket Allocator Pool Size\n            [NativeProperty(\"switchSocketAllocatorPoolSize\", TargetType.Field)]\n            extern public static int socketAllocatorPoolSize { get; set; }\n\n            // Socket Concurrency Limit\n            [NativeProperty(\"switchSocketConcurrencyLimit\", TargetType.Field)]\n            extern public static int socketConcurrencyLimit { get; set; }\n\n            // Whether to enable use of the Nintendo Switch CPU Profiler.\n            [NativeProperty(\"switchUseCPUProfiler\", TargetType.Field)]\n            extern public static bool useSwitchCPUProfiler { get; set; }\n\n            // Whether to enable file system trace on Nintendo Switch CPU Profiler.\n            [NativeProperty(\"switchEnableFileSystemTrace\", TargetType.Field)]\n            extern public static bool enableFileSystemTrace { get; set; }\n\n            // What LTO setting to use on Switch.\n            [NativeProperty(\"switchLTOSetting\", TargetType.Field)]\n            extern public static int switchLTOSetting { get; set; }\n\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static int queueCommandMemory\n            {\n                [NativeMethod(\"GetSwitchQueueCommandMemory\")]\n                get;\n                [NativeMethod(\"SetSwitchQueueCommandMemory\")]\n                set;\n            }\n\n            [StaticAccessor(\"PlayerSettings\", StaticAccessorType.DoubleColon)]\n            extern public static int defaultSwitchQueueCommandMemory { get; }\n\n            [StaticAccessor(\"PlayerSettings\", StaticAccessorType.DoubleColon)]\n            extern public static int minimumSwitchQueueCommandMemory { get; }\n\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static int queueControlMemory\n            {\n                [NativeMethod(\"GetSwitchQueueControlMemory\")]\n                get;\n                [NativeMethod(\"SetSwitchQueueControlMemory\")]\n                set;\n            }\n\n            [StaticAccessor(\"PlayerSettings\", StaticAccessorType.DoubleColon)]\n            extern public static int defaultSwitchQueueControlMemory { get; }\n\n            [StaticAccessor(\"PlayerSettings\", StaticAccessorType.DoubleColon)]\n            extern public static int minimumSwitchQueueControlMemory { get; }\n\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static int queueComputeMemory\n            {\n                [NativeMethod(\"GetSwitchQueueComputeMemory\")]\n                get;\n                [NativeMethod(\"SetSwitchQueueComputeMemory\")]\n                set;\n            }\n\n            [StaticAccessor(\"PlayerSettings\", StaticAccessorType.DoubleColon)]\n            extern public static int defaultSwitchQueueComputeMemory { get; }\n\n            // GPU Pool information.\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static int NVNShaderPoolsGranularity\n            {\n                [NativeMethod(\"GetSwitchNVNShaderPoolsGranularity\")]\n                get;\n                [NativeMethod(\"SetSwitchNVNShaderPoolsGranularity\")]\n                set;\n            }\n\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static int NVNDefaultPoolsGranularity\n            {\n                [NativeMethod(\"GetSwitchNVNDefaultPoolsGranularity\")]\n                get;\n                [NativeMethod(\"SetSwitchNVNDefaultPoolsGranularity\")]\n                set;\n            }\n\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static int NVNOtherPoolsGranularity\n            {\n                [NativeMethod(\"GetSwitchNVNOtherPoolsGranularity\")]\n                get;\n                [NativeMethod(\"SetSwitchNVNOtherPoolsGranularity\")]\n                set;\n            }\n\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static int GpuScratchPoolGranularity\n            {\n                [NativeMethod(\"GetSwitchGpuScratchPoolGranularity\")]\n                get;\n                [NativeMethod(\"SetSwitchGpuScratchPoolGranularity\")]\n                set;\n            }\n\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static bool AllowGpuScratchShrinking\n            {\n                [NativeMethod(\"GetSwitchAllowGpuScratchShrinking\")]\n                get;\n                [NativeMethod(\"SetSwitchAllowGpuScratchShrinking\")]\n                set;\n            }\n\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static int NVNMaxPublicTextureIDCount\n            {\n                [NativeMethod(\"GetSwitchNVNMaxPublicTextureIDCount\")]\n                get;\n                [NativeMethod(\"SetSwitchNVNMaxPublicTextureIDCount\")]\n                set;\n            }\n\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static int NVNMaxPublicSamplerIDCount\n            {\n                [NativeMethod(\"GetSwitchNVNMaxPublicSamplerIDCount\")]\n                get;\n                [NativeMethod(\"SetSwitchNVNMaxPublicSamplerIDCount\")]\n                set;\n            }\n\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static int NVNGraphicsFirmwareMemory\n            {\n                [NativeMethod(\"GetSwitchNVNGraphicsFirmwareMemory\")]\n                get;\n                [NativeMethod(\"SetSwitchNVNGraphicsFirmwareMemory\")]\n                set;\n            }\n\n            [StaticAccessor(\"PlayerSettings\", StaticAccessorType.DoubleColon)]\n            extern public static int defaultSwitchNVNGraphicsFirmwareMemory { get; }\n\n            [StaticAccessor(\"PlayerSettings\", StaticAccessorType.DoubleColon)]\n            extern public static int minimumSwitchNVNGraphicsFirmwareMemory { get; }\n\n            [StaticAccessor(\"PlayerSettings\", StaticAccessorType.DoubleColon)]\n            extern public static int maximumSwitchNVNGraphicsFirmwareMemory { get; }\n\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static int switchMaxWorkerMultiple\n            {\n                [NativeMethod(\"GetSwitchKMaxWorkerMultiple\")]\n                get;\n                [NativeMethod(\"SetSwitchKMaxWorkerMultiple\")]\n                set;\n            }\n\n            // Controls the behavior of Switch's auto-changing screen resolution\n            [NativeProperty(\"switchScreenResolutionBehavior\", TargetType.Field)]\n            extern public static ScreenResolutionBehavior screenResolutionBehavior { get; set; }\n\n            [NativeProperty(\"switchNMETAOverride\", TargetType.Function)]\n            extern static private string NMETAOverrideInternal { get; set; }\n\n            public static string NMETAOverride\n            {\n                get\n                {\n                    string path = NMETAOverrideInternal;\n\n                    if (string.IsNullOrEmpty(path))\n                        return \"\";\n\n                    return path;\n                }\n                set\n                {\n                    NMETAOverrideInternal = value;\n                }\n            }\n\n            public static string NMETAOverrideFullPath\n            {\n                get\n                {\n                    string path = NMETAOverrideInternal;\n\n                    if (string.IsNullOrEmpty(path))\n                        return \"\";\n\n                    if (!Path.IsPathRooted(path))\n                        path = Path.GetFullPath(path);\n\n                    return path;\n                }\n            }\n\n            public static string[] compilerFlags\n            {\n                get\n                {\n                    return compilerFlagsInternal.Split(new char[] {' '});\n                }\n                set\n                {\n                    compilerFlagsInternal = string.Join(\" \", value);\n                }\n            }\n\n            [NativeProperty(\"switchCompilerFlags\", TargetType.Function)]\n            extern private static string compilerFlagsInternal { get; set; }\n\n            //Additional NSO Dependencies\n            [NativeProperty(\"switchNSODependencies\", TargetType.Function)]\n            extern public static string nsoDependencies { get; set; }\n\n            [NativeProperty(\"switchSupportedNpadStyles\", TargetType.Field)]\n            extern public static SupportedNpadStyle supportedNpadStyles { get; set; }\n\n            [NativeProperty(\"switchNativeFsCacheSize\", TargetType.Field)]\n            extern public static int nativeFsCacheSize { get; set; }\n\n            [NativeProperty(\"switchIsHoldTypeHorizontal\", TargetType.Field)]\n            extern public static bool isHoldTypeHorizontal { get; set; }\n\n            [NativeProperty(\"switchSupportedNpadCount\", TargetType.Field)]\n            extern public static int supportedNpadCount { get; set; }\n\n            [NativeProperty(\"switchEnableTouchScreen\", TargetType.Field)]\n            extern public static bool enableTouchScreen { get; set; }\n\n            // SocketConfigEnabled\n            [NativeProperty(\"switchSocketConfigEnabled\", TargetType.Field)]\n            extern public static bool socketConfigEnabled { get; set; }\n\n            // Tcp Initial Send Buffer Size\n            [NativeProperty(\"switchTcpInitialSendBufferSize\", TargetType.Field)]\n            extern public static int tcpInitialSendBufferSize { get; set; }\n\n            // Tcp Initial Receive Buffer Size\n            [NativeProperty(\"switchTcpInitialReceiveBufferSize\", TargetType.Field)]\n            extern public static int tcpInitialReceiveBufferSize { get; set; }\n\n            // Tcp Auto Send Buffer Size Max\n            [NativeProperty(\"switchTcpAutoSendBufferSizeMax\", TargetType.Field)]\n            extern public static int tcpAutoSendBufferSizeMax { get; set; }\n\n            // Tcp Auto Receive Buffer Size Max\n            [NativeProperty(\"switchTcpAutoReceiveBufferSizeMax\", TargetType.Field)]\n            extern public static int tcpAutoReceiveBufferSizeMax { get; set; }\n\n            // Udp Send Buffer Size\n            [NativeProperty(\"switchUdpSendBufferSize\", TargetType.Field)]\n            extern public static int udpSendBufferSize { get; set; }\n\n            // Udp Receive Buffer Size\n            [NativeProperty(\"switchUdpReceiveBufferSize\", TargetType.Field)]\n            extern public static int udpReceiveBufferSize { get; set; }\n\n            // Socket Buffer Efficiency\n            [NativeProperty(\"switchSocketBufferEfficiency\", TargetType.Field)]\n            extern public static int socketBufferEfficiency { get; set; }\n\n            // Socket Initialize Enabled\n            [NativeProperty(\"switchSocketInitializeEnabled\", TargetType.Field)]\n            extern public static bool socketInitializeEnabled { get; set; }\n\n            // Network Interface Manager Initialize Enabled\n            [NativeProperty(\"switchNetworkInterfaceManagerInitializeEnabled\", TargetType.Field)]\n            extern public static bool networkInterfaceManagerInitializeEnabled { get; set; }\n\n            // HTCS for player connection\n            [NativeProperty(\"switchDisableHTCSPlayerConnection\", TargetType.Field)]\n            extern public static bool disableHTCSPlayerConnection { get; set; }\n\n            // Forces all FMOD threads to use nn::os::LowestThreadPriority\n            [NativeProperty(\"switchUseLegacyFmodPriorities\", TargetType.Field)]\n            extern public static bool switchUseLegacyFmodPriorities { get; set; }\n\n            // Controls if calls to nn::os::YieldThread are swapped with calls to nn::os::SleepThread({switchMicroSleepForYieldTime}us)\n            [NativeProperty(\"switchUseMicroSleepForYield\", TargetType.Field)]\n            extern public static bool switchUseMicroSleepForYield { get; set; }\n\n            // Number of micro seconds used by switchUseMicroSleepForYield\n            [NativeProperty(\"switchMicroSleepForYieldTime\", TargetType.Field)]\n            extern public static int switchMicroSleepForYieldTime { get; set; }\n\n            //Enable the RamDisk support\n            [NativeProperty(\"switchEnableRamDiskSupport\", TargetType.Field)]\n            extern public static bool switchEnableRamDiskSupport { get; set; }\n\n            //To specify how much space should be allocated for the ram disk\n            [NativeProperty(\"switchRamDiskSpaceSize\", TargetType.Field)]\n            extern public static int switchRamDiskSpaceSize { get; set; }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsSwitch.deprecated.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor;\n\n//==== OBSOLETE PLAYER SETTINGS ===//\n//These are used ONLY to upgrade a NMETA Player Settings to an NMETA file//\n\npublic sealed partial class PlayerSettings\n{\n    [NativeHeader(\"Editor/Mono/PlayerSettingsSwitch.bindings.h\")]\n    public sealed partial class Switch\n    {\n        const string kPlayerSettingsAreObsoletedWarning = \"NMETA Player Settings are obsolete\";\n\n        [NativeProperty(\"switchUpgradedPlayerSettingsToNMETA\", TargetType.Field)]\n        extern internal static bool HasUpgradedPlayerSettingsToNMETA { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        internal enum Languages\n        {\n            AmericanEnglish = 0,\n            BritishEnglish = 1,\n            Japanese = 2,\n            French = 3,\n            German = 4,\n            LatinAmericanSpanish = 5,\n            Spanish = 6,\n            Italian = 7,\n            Dutch = 8,\n            CanadianFrench = 9,\n            Portuguese = 10,\n            Russian = 11,\n            SimplifiedChinese = 12,\n            TraditionalChinese = 13,\n            Korean = 14,\n            BrazilianPortuguese = 15,\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        internal enum StartupUserAccount\n        {\n            None = 0,\n            Required = 1,\n            RequiredWithNetworkServiceAccountAvailable = 2\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        internal enum LogoHandling\n        {\n            Auto = 0,\n            Manual = 1\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        internal enum LogoType\n        {\n            LicensedByNintendo = 0,\n            [Obsolete(\"This attribute is no longer available as of NintendoSDK 4.3.\", true)]\n            DistributedByNintendo = 1,\n            Nintendo = 2\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        internal enum ApplicationAttribute\n        {\n            None = 0,\n            Demo = 1\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        internal enum RatingCategories\n        {\n            CERO = 0,\n            GRACGCRB = 1,\n            GSRMR = 2,\n            ESRB = 3,\n            ClassInd = 4,\n            USK = 5,\n            PEGI = 6,\n            PEGIPortugal = 7,\n            PEGIBBFC = 8,\n            Russian = 9,\n            ACB = 10,\n            OFLC = 11,\n            IARCGeneric = 12,\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchApplicationID\", TargetType.Function)]\n        extern internal static string applicationID { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        extern internal static string[] titleNames\n        {\n            [NativeMethod(\"GetSwitchTitleNames\")]\n            get;\n            [NativeMethod(\"SetSwitchTitleNames\")]\n            set;\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        extern internal static string[] publisherNames\n        {\n            [NativeMethod(\"GetSwitchPublisherNames\")]\n            get;\n            [NativeMethod(\"SetSwitchPublisherNames\")]\n            set;\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        extern internal static Texture2D[] icons\n        {\n            [NativeMethod(\"GetSwitchIcons\")]\n            get;\n            [NativeMethod(\"SetSwitchIcons\")]\n            set;\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        extern internal static Texture2D[] smallIcons\n        {\n            [NativeMethod(\"GetSwitchSmallIcons\")]\n            get;\n            [NativeMethod(\"SetSwitchSmallIcons\")]\n            set;\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchAllowsVideoCapturing\", TargetType.Field)]\n        extern internal static bool isVideoCapturingEnabled { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchAllowsRuntimeAddOnContentInstall\", TargetType.Field)]\n        extern internal static bool isRuntimeAddOnContentInstallEnabled { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchDataLossConfirmation\", TargetType.Field)]\n        extern internal static bool isDataLossConfirmationEnabled { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchUserAccountLockEnabled\", TargetType.Field)]\n        extern internal static bool isUserAccountLockEnabled { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchRatingsMask\", TargetType.Field)]\n        extern internal static int ratingsMask { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        extern internal static string[] localCommunicationIds\n        {\n            [NativeMethod(\"GetSwitchLocalCommunicationIds\")]\n            get;\n            [NativeMethod(\"SetSwitchLocalCommunicationIds\")]\n            set;\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchParentalControl\", TargetType.Field)]\n        extern internal static bool isUnderParentalControl { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchAllowsScreenshot\", TargetType.Field)]\n        extern internal static bool isScreenshotEnabled { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        internal static int cardSpecClock\n        {\n            get { return cardSpecClockInternal; }\n            set { cardSpecClockInternal = (value > 0) ? value : -1; }\n        }\n\n        [NativeProperty(\"switchCardSpecClock\", TargetType.Field)]\n        extern static int cardSpecClockInternal { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        internal static string manualHTMLPath\n        {\n            get\n            {\n                string path = manualHTMLPathInternal;\n\n                if (string.IsNullOrEmpty(path))\n                    return \"\";\n\n                string fullPath = path;\n\n                if (!Path.IsPathRooted(fullPath))\n                    fullPath = Path.GetFullPath(fullPath);\n\n                if (!Directory.Exists(fullPath))\n                    return \"\";\n\n                return fullPath;\n            }\n            set { manualHTMLPathInternal = string.IsNullOrEmpty(value) ? \"\" : value; }\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        internal static string accessibleURLPath\n        {\n            get\n            {\n                string path = accessibleURLPathInternal;\n\n                if (string.IsNullOrEmpty(path))\n                    return \"\";\n\n                string fullPath = path;\n\n                if (!Path.IsPathRooted(fullPath))\n                    fullPath = Path.GetFullPath(fullPath);\n\n                return fullPath;\n            }\n            set { accessibleURLPathInternal = string.IsNullOrEmpty(value) ? \"\" : value; }\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        internal static string legalInformationPath\n        {\n            get\n            {\n                string path = legalInformationPathInternal;\n\n                if (string.IsNullOrEmpty(path))\n                    return \"\";\n\n                if (!Path.IsPathRooted(path))\n                    path = Path.GetFullPath(path);\n\n                return path;\n            }\n            set { legalInformationPathInternal = string.IsNullOrEmpty(value) ? \"\" : value; }\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchManualHTML\", TargetType.Function)]\n        extern static string manualHTMLPathInternal { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchAccessibleURLs\", TargetType.Function)]\n        extern static string accessibleURLPathInternal { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchLegalInformation\", TargetType.Function)]\n        extern static string legalInformationPathInternal { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchMainThreadStackSize\", TargetType.Field)]\n        extern internal static int mainThreadStackSize { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchPresenceGroupId\", TargetType.Function)]\n        extern internal static string presenceGroupId { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchLogoHandling\", TargetType.Field)]\n        extern internal static LogoHandling logoHandling { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        extern internal static string releaseVersion\n        {\n            [NativeMethod(\"GetSwitchReleaseVersion\")]\n            get;\n            [NativeMethod(\"SetSwitchReleaseVersion\")]\n            set;\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchDisplayVersion\", TargetType.Function)]\n        extern internal static string displayVersion { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchStartupUserAccount\", TargetType.Field)]\n        extern internal static StartupUserAccount startupUserAccount { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchSupportedLanguagesMask\", TargetType.Field)]\n        extern internal static int supportedLanguages { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchLogoType\", TargetType.Field)]\n        extern internal static LogoType logoType { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchApplicationErrorCodeCategory\", TargetType.Function)]\n        extern internal static string applicationErrorCodeCategory { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchUserAccountSaveDataSize\", TargetType.Field)]\n        extern internal static int userAccountSaveDataSize { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchUserAccountSaveDataJournalSize\", TargetType.Field)]\n        extern internal static int userAccountSaveDataJournalSize { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchApplicationAttribute\", TargetType.Field)]\n        extern internal static ApplicationAttribute applicationAttribute { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        internal static int cardSpecSize\n        {\n            get { return cardSpecSizeInternal; }\n            set { cardSpecSizeInternal = (value > 0) ? value : -1; }\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchCardSpecSize\", TargetType.Field)]\n        extern private static int cardSpecSizeInternal { get; set; }\n\n        // System Memory (used for virtual memory mapping).\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        [NativeProperty(\"switchSystemResourceMemory\", TargetType.Field)]\n        extern internal static int systemResourceMemory { get; set; }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        internal static int GetRatingAge(RatingCategories category)\n        {\n            return ratingAgeArray[(int)category];\n        }\n\n        [Obsolete(kPlayerSettingsAreObsoletedWarning)]\n        extern internal static int[] ratingAgeArray\n        {\n            [NativeMethod(\"GetSwitchRatingAges\")]\n            get;\n            [NativeMethod(\"SetSwitchRatingAges\")]\n            set;\n        }\n\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsTVOS.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Build;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    public enum tvOSSdkVersion\n    {\n        Device = 0,\n        Simulator = 1\n    }\n\n    [System.Obsolete(\"targetOSVersion is obsolete. Use targetOSVersionString instead.\", false)]\n    public enum tvOSTargetOSVersion\n    {\n        Unknown = 0,\n        tvOS_9_0 = 900,\n        tvOS_9_1 = 901,\n    }\n\n    // Player Settings is where you define various parameters for the final game that you will build in Unity. Some of these values are used in the Resolution Dialog that launches when you open a standalone game.\n    public partial class PlayerSettings : UnityEngine.Object\n    {\n        // tvOS specific player settings\n        [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n        [NativeHeader(\"Editor/Src/EditorUserBuildSettings.h\")]\n        [StaticAccessor(\"GetPlayerSettings()\")]\n        public partial class tvOS\n        {\n            // Sdk Version\n            private static extern int sdkVersionInt\n            {\n                [NativeMethod(\"GettvOSSdkVersion\")]\n                get;\n                [NativeMethod(\"SettvOSSdkVersion\")]\n                set;\n            }\n            public static tvOSSdkVersion sdkVersion\n            {\n                get { return (tvOSSdkVersion)sdkVersionInt; }\n                set { sdkVersionInt = (int)value; }\n            }\n\n            // Simulator Architectures\n            private extern static int simulatorSdkArchitectureInternal\n            {\n                [NativeMethod(\"GettvOSSimulatorArchitecture\")]\n                get;\n                [NativeMethod(\"SettvOSSimulatorArchitecture\")]\n                set;\n            }\n            public static AppleMobileArchitectureSimulator simulatorSdkArchitecture\n            {\n                get { return (AppleMobileArchitectureSimulator)simulatorSdkArchitectureInternal; }\n                set { simulatorSdkArchitectureInternal = (int)value; }\n            }\n\n            // tvOS bundle build number\n            public static string buildNumber\n            {\n                get { return PlayerSettings.GetBuildNumber(NamedBuildTarget.tvOS.TargetName); }\n                set { PlayerSettings.SetBuildNumber(NamedBuildTarget.tvOS.TargetName, value); }\n            }\n\n            [System.Obsolete(\"targetOSVersion is obsolete. Use targetOSVersionString instead.\", false)]\n            public static tvOSTargetOSVersion targetOSVersion\n            {\n                get\n                {\n                    string version = targetOSVersionString;\n                    if (version == \"9.0\")\n                        return tvOSTargetOSVersion.tvOS_9_0;\n                    else if (version == \"9.1\")\n                        return tvOSTargetOSVersion.tvOS_9_1;\n                    return tvOSTargetOSVersion.Unknown;\n                }\n                set\n                {\n                    string version = \"\";\n                    if (value == tvOSTargetOSVersion.tvOS_9_0)\n                        version = \"9.0\";\n                    else if (value == tvOSTargetOSVersion.tvOS_9_1)\n                        version = \"9.1\";\n\n                    targetOSVersionString = version;\n                }\n            }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"GettvOSMinimumVersionString\")]\n            static extern string GetMinimumVersionString();\n\n            internal static readonly Version minimumOsVersion = new Version(GetMinimumVersionString());\n\n            public static extern string targetOSVersionString\n            {\n                [NativeMethod(\"GettvOSTargetOSVersion\")]\n                get;\n                [NativeMethod(\"SettvOSTargetOSVersion\")]\n                set;\n            }\n\n            [NativeProperty(\"tvOSSmallIconLayers\", TargetType.Function)]\n            private static extern Texture2D[] smallIconLayers\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            internal static Texture2D[] GetSmallIconLayers() { return smallIconLayers; }\n            internal static void SetSmallIconLayers(Texture2D[] layers) { smallIconLayers = layers; }\n\n\n            [NativeProperty(\"tvOSSmallIconLayers2x\", TargetType.Function)]\n            private static extern Texture2D[] smallIconLayers2x\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            internal static Texture2D[] GetSmallIconLayers2x() { return smallIconLayers2x; }\n            internal static void SetSmallIconLayers2x(Texture2D[] layers) { smallIconLayers2x = layers; }\n\n\n            [NativeProperty(\"tvOSLargeIconLayers\", TargetType.Function)]\n            private static extern Texture2D[] largeIconLayers\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            internal static Texture2D[] GetLargeIconLayers() { return largeIconLayers; }\n            internal static void SetLargeIconLayers(Texture2D[] layers) { largeIconLayers = layers; }\n\n\n            [NativeProperty(\"tvOSLargeIconLayers2x\", TargetType.Function)]\n            private static extern Texture2D[] largeIconLayers2x\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            internal static Texture2D[] GetLargeIconLayers2x() { return largeIconLayers2x; }\n            internal static void SetLargeIconLayers2x(Texture2D[] layers) { largeIconLayers2x = layers; }\n\n\n            [NativeProperty(\"tvOSTopShelfImageLayers\", TargetType.Function)]\n            private static extern Texture2D[] topShelfImageLayers\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            internal static Texture2D[] GetTopShelfImageLayers() { return topShelfImageLayers; }\n            internal static void SetTopShelfImageLayers(Texture2D[] layers) { topShelfImageLayers = layers; }\n\n\n            [NativeProperty(\"tvOSTopShelfImageLayers2x\", TargetType.Function)]\n            private static extern Texture2D[] topShelfImageLayers2x\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            internal static Texture2D[] GetTopShelfImageLayers2x() { return topShelfImageLayers2x; }\n            internal static void SetTopShelfImageLayers2x(Texture2D[] layers) { topShelfImageLayers2x = layers; }\n\n            [NativeProperty(\"tvOSTopShelfImageWideLayers\", TargetType.Function)]\n            private static extern Texture2D[] topShelfImageWideLayers\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            internal static Texture2D[] GetTopShelfImageWideLayers() { return topShelfImageWideLayers; }\n            internal static void SetTopShelfImageWideLayers(Texture2D[] layers) { topShelfImageWideLayers = layers; }\n\n\n            [NativeProperty(\"tvOSTopShelfImageWideLayers2x\", TargetType.Function)]\n            private static extern Texture2D[] topShelfImageWideLayers2x\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            internal static Texture2D[] GetTopShelfImageWideLayers2x() { return topShelfImageWideLayers2x; }\n            internal static void SetTopShelfImageWideLayers2x(Texture2D[] layers) { topShelfImageWideLayers2x = layers; }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeProperty(\"appleTVSplashScreen\", TargetType.Field)]\n            internal static extern Texture2D splashScreen { get; }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeProperty(\"appleTVSplashScreen2x\", TargetType.Field)]\n            internal static extern Texture2D splashScreen2x { get; }\n\n            // AppleTV Enable extended game controller\n            public static extern bool requireExtendedGameController\n            {\n                [NativeMethod(\"GettvOSRequireExtendedGameController\")]\n                get;\n                [NativeMethod(\"SettvOSRequireExtendedGameController\")]\n                set;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsVisionOS.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Build;\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    public enum VisionOSSdkVersion\n    {\n        Device = 0,\n        Simulator = 1\n    }\n\n    // Player Settings is where you define various parameters for the final game that you will build in Unity. Some of these values are used in the Resolution Dialog that launches when you open a standalone game.\n    public partial class PlayerSettings : UnityEngine.Object\n    {\n        // VisionOS specific player settings\n        [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n        [NativeHeader(\"Editor/Src/EditorUserBuildSettings.h\")]\n        [StaticAccessor(\"GetPlayerSettings()\")]\n        public sealed partial class VisionOS\n        {\n            private static extern int sdkVersionInt\n            {\n                [NativeMethod(\"GetVisionOSSdkVersion\")]\n                get;\n                [NativeMethod(\"SetVisionOSSdkVersion\")]\n                set;\n            }\n\n            public static VisionOSSdkVersion sdkVersion\n            {\n                get { return (VisionOSSdkVersion)sdkVersionInt; }\n                set { sdkVersionInt = (int)value; }\n            }\n\n            // visionos bundle build number\n            public static string buildNumber\n            {\n                get { return PlayerSettings.GetBuildNumber(NamedBuildTarget.VisionOS.TargetName); }\n                set { PlayerSettings.SetBuildNumber(NamedBuildTarget.VisionOS.TargetName, value); }\n            }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeMethod(\"GetVisionOSMinimumVersionString\")]\n            static extern string GetMinimumVersionString();\n\n            internal static readonly Version minimumOsVersion = new Version(GetMinimumVersionString());\n\n            public static extern string targetOSVersionString\n            {\n                [NativeMethod(\"GetVisionOSTargetOSVersion\")]\n                get;\n                [NativeMethod(\"SetVisionOSTargetOSVersion\")]\n                set;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsVulkan.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\nusing System;\n\nnamespace UnityEditor\n{\n    public partial class PlayerSettings : UnityEngine.Object\n    {\n        public static extern bool vulkanEnableSetSRGBWrite { get; set; }\n\n        private static extern UInt32 GetVulkanNumSwapchainBuffersImpl();\n        private static extern void SetVulkanNumSwapchainBuffersImpl(UInt32 value);\n\n        // NOTE: While in the editor, changing this value can be destructive so we force 3 swapchain buffers while running in the editor.\n        public static UInt32 vulkanNumSwapchainBuffers\n        {\n            get\n            {\n                // Must match the value PlayerSettings::kFixedEditorVulkanSwapchainBufferCount in native code, \n                // explicitly report the current value being used.\n                const UInt32 kFixedEditorVulkanSwapchainBufferCount = 3;\n                if (EditorApplication.isPlaying)\n                    return kFixedEditorVulkanSwapchainBufferCount;\n                else\n                return GetVulkanNumSwapchainBuffersImpl();\n            }\n\n            set => SetVulkanNumSwapchainBuffersImpl(value);\n        }\n\n        public static extern bool vulkanEnableLateAcquireNextImage { get; set; }\n\n        [Obsolete(\"Vulkan SW command buffers are deprecated, vulkanUseSWCommandBuffers will be ignored.\")]\n        public static bool vulkanUseSWCommandBuffers { get { return false; } set {} }\n\n        public static extern bool vulkanEnablePreTransform { get; set; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsWSA.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    // Player Settings is where you define various parameters for the final game that you will build in Unity. Some of these values are used in the Resolution Dialog that launches when you open a standalone game.\n    public sealed partial class PlayerSettings : UnityEngine.Object\n    {\n        public enum WSAApplicationShowName\n        {\n            NotSet = 0,\n            AllLogos = 1,\n            NoLogos = 2,\n            StandardLogoOnly = 3,\n            WideLogoOnly = 4,\n        }\n\n        public enum WSADefaultTileSize\n        {\n            NotSet = 0,\n            Medium = 1,\n            Wide = 2,\n        }\n\n        public enum WSAApplicationForegroundText\n        {\n            //notSet = 0,\n            Light = 1,\n            Dark = 2,\n        }\n\n        // match these with the capabilities listed in MetroCapabilities.h\n        public enum WSACapability\n        {\n            EnterpriseAuthentication = 0,\n            InternetClient = 1,\n            InternetClientServer = 2,\n            MusicLibrary = 3,\n            PicturesLibrary = 4,\n            PrivateNetworkClientServer = 5,\n            RemovableStorage = 6,\n            SharedUserCertificates = 7,\n            VideosLibrary = 8,\n            WebCam = 9,\n            Proximity = 10,\n            Microphone = 11,\n            Location = 12,\n            HumanInterfaceDevice = 13,\n            AllJoyn = 14,\n            BlockedChatMessages = 15,\n            Chat = 16,\n            CodeGeneration = 17,\n            Objects3D = 18,\n            PhoneCall = 19,\n            UserAccountInformation = 20,\n            VoipCall = 21,\n            Bluetooth = 22,\n            SpatialPerception = 23,\n            InputInjectionBrokered = 24,\n            Appointments = 25,\n            BackgroundMediaPlayback = 26,\n            Contacts = 27,\n            LowLevelDevices = 28,\n            OfflineMapsManagement = 29,\n            PhoneCallHistoryPublic = 30,\n            PointOfService = 31,\n            RecordedCallsFolder = 32,\n            RemoteSystem = 33,\n            SystemManagement = 34,\n            UserDataTasks = 35,\n            UserNotificationListener = 36,\n            GazeInput = 37\n        }\n\n        // match these with the capabilities listed in MetroCapabilities.h\n        public enum WSATargetFamily\n        {\n            Desktop = 0,\n            Mobile = 1,\n            Xbox = 2,\n            Holographic = 3,\n            Team = 4,\n            IoT = 5,\n            IoTHeadless = 6,\n        }\n\n        public enum WSAImageScale\n        {\n            _100 = 100,\n            _125 = 125,\n            _150 = 150,\n            _200 = 200,\n            _400 = 400,\n\n            Target16 = 16,\n            Target24 = 24,\n            Target32 = 32,\n            Target48 = 48,\n            Target256 = 256,\n\n            [Obsolete(\"Image scale 80 is not used in Universal Windows Platform\", false)]\n            _80 = 80,\n            [Obsolete(\"Image scale 140 is not used in Universal Windows Platform\", false)]\n            _140 = 140,\n            [Obsolete(\"Image scale 180 is not used in Universal Windows Platform\", false)]\n            _180 = 180,\n            [Obsolete(\"Image scale 240 is not used in Universal Windows Platform\", false)]\n            _240 = 240,\n        }\n\n        public enum WSAImageType\n        {\n            // Generic\n            PackageLogo = 1,\n            SplashScreenImage = 2,\n\n            // Values of 11-20 used to be Windows Store 8.1 images\n            // Values of 21-30 used to be Windows Store 8.1 images\n\n            // UWP\n            UWPSquare44x44Logo = 31,\n            UWPSquare71x71Logo = 32,\n            UWPSquare150x150Logo = 33,\n            UWPSquare310x310Logo = 34,\n            UWPWide310x150Logo = 35,\n        }\n\n        // Keep in sync with WSAInputSource in PlayerSettings.h\n        public enum WSAInputSource\n        {\n            CoreWindow = 0,\n            IndependentInputSource = 1,\n            SwapChainPanel = 2,\n        }\n\n        [RequiredByNativeCode]\n        public struct WSASupportedFileType\n        {\n            public string contentType;\n            public string fileType;\n        }\n\n        public struct WSAFileTypeAssociations\n        {\n            public string name;\n            public WSASupportedFileType[] supportedFileTypes;\n        }\n\n        [NativeHeader(\"Editor/Mono/PlayerSettingsWSA.bindings.h\")]\n        [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n        [StaticAccessor(\"PlayerSettingsBindings::WSA\", StaticAccessorType.DoubleColon)]\n        public sealed partial class WSA\n        {\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            [NativeProperty(\"wsaTransparentSwapchain\", TargetType.Field)]\n            public static extern bool transparentSwapchain { get; set; }\n\n            public static extern string packageName { get; set; }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static extern string packageLogo { get; set; }\n\n            private static extern string GetWSAImage(WSAImageType type, WSAImageScale scale);\n\n            private static extern void SetWSAImage(string image, WSAImageType type, WSAImageScale scale);\n\n            private static extern string packageVersionRaw { get; set; }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"PlayerSettings.WSA.commandLineArgsFile is deprecated\", error: true)]\n            public static string commandLineArgsFile { get { return string.Empty; } set {} }\n\n            [NativeThrows]\n            public static extern bool SetCertificate(string path, string password);\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeProperty(\"metroCertificatePath\", TargetType.Field)]\n            public static extern string certificatePath { get; }\n\n            internal static extern string certificatePassword { get; }\n\n            private static string NullIfEmpty(string value)\n            {\n                return String.IsNullOrEmpty(value) ? null : value;\n            }\n\n            public static string certificateSubject\n            {\n                get { return NullIfEmpty(internalCertificateSubject); }\n            }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeProperty(\"metroCertificateSubject\", TargetType.Field)]\n            private static extern string internalCertificateSubject { get; }\n\n            public static string certificateIssuer\n            {\n                get { return NullIfEmpty(internalCertificateIssuer); }\n            }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeProperty(\"metroCertificateIssuer\", TargetType.Field)]\n            private static extern string internalCertificateIssuer { get; }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            [NativeProperty(\"metroCertificateNotAfter\", TargetType.Field)]\n            private static extern long certificateNotAfterRaw { get; }\n\n            public static extern string applicationDescription { get; set; }\n\n            public static extern string tileShortName { get; set; }\n\n            [NativeProperty(\"metroTileShowName\", TargetType.Field)]\n            public static extern WSAApplicationShowName tileShowName\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"metroMediumTileShowName\", TargetType.Field)]\n            public static extern bool mediumTileShowName\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"metroLargeTileShowName\", TargetType.Field)]\n            public static extern bool largeTileShowName\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"metroWideTileShowName\", TargetType.Field)]\n            public static extern bool wideTileShowName\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"metroDefaultTileSize\", TargetType.Field)]\n            public static extern WSADefaultTileSize defaultTileSize\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"metroTileForegroundText\", TargetType.Field)]\n            public static extern WSAApplicationForegroundText tileForegroundText\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"metroTileBackgroundColor\", TargetType.Field)]\n            public static extern Color tileBackgroundColor\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [Obsolete(\"PlayerSettings.WSA.enableIndependentInputSource is deprecated. Use PlayerSettings.WSA.inputSource.\", false)]\n            public static bool enableIndependentInputSource\n            {\n                get { return inputSource == WSAInputSource.IndependentInputSource; }\n                set { inputSource = value ? WSAInputSource.IndependentInputSource : WSAInputSource.CoreWindow; }\n            }\n\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            [NativeProperty(\"metroInputSource\", TargetType.Field)]\n            public static extern WSAInputSource inputSource { get; set; }\n\n            [NativeProperty(\"metroSupportStreamingInstall\", TargetType.Field)]\n            public static extern bool supportStreamingInstall\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"metroLastRequiredScene\", TargetType.Field)]\n            public static extern int lastRequiredScene\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"metroSplashScreenUseBackgroundColor\", TargetType.Field)]\n            private static extern bool splashScreenUseBackgroundColor\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"metroSplashScreenBackgroundColor\", TargetType.Field)]\n            private static extern Color splashScreenBackgroundColorRaw\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"syncCapabilities\", TargetType.Field)]\n            public static extern bool syncCapabilities\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            private static extern void InternalSetCapability(string name, string value);\n\n            private static extern string InternalGetCapability(string name);\n\n            private static extern void InternalSetTargetDeviceFamily(string name, string value);\n\n            private static extern string InternalGetTargetDeviceFamily(string name);\n\n            // Workaround for Case 756100 - properties (and probably functions) in nested+nested class are not correctly bound, causing MissingMethodException when calling them from C#\n            internal static extern string internalProtocolName { get; set; }\n\n            internal static WSAFileTypeAssociations internalFileTypeAssociations\n            {\n                get\n                {\n                    return new WSAFileTypeAssociations { name = metroFTAName, supportedFileTypes = metroFTAFileTypes };\n                }\n\n                set\n                {\n                    metroFTAName = value.name;\n                    metroFTAFileTypes = value.supportedFileTypes;\n                }\n            }\n\n            private static extern string metroFTAName { get; set; }\n\n            [NativeProperty(\"metroFTAFileTypes\", TargetType.Function)]\n            private static extern WSASupportedFileType[] metroFTAFileTypes\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            public static extern string vcxProjDefaultLanguage { get; set; }\n\n            public static class Declarations\n            {\n                public static string protocolName\n                {\n                    get\n                    {\n                        return PlayerSettings.WSA.internalProtocolName;\n                    }\n                    set\n                    {\n                        PlayerSettings.WSA.internalProtocolName = value;\n                    }\n                }\n\n                public static WSAFileTypeAssociations fileTypeAssociations\n                {\n                    get\n                    {\n                        return PlayerSettings.WSA.internalFileTypeAssociations;\n                    }\n                    set\n                    {\n                        PlayerSettings.WSA.internalFileTypeAssociations = value;\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsWSA.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Text.RegularExpressions;\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    public sealed partial class PlayerSettings : UnityEngine.Object\n    {\n        public sealed partial class WSA\n        {\n            internal static string ValidatePackageVersion(string value)\n            {\n                Regex metroPackageVersionRegex = new Regex(@\"^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$\", (RegexOptions.Compiled | RegexOptions.CultureInvariant));\n\n                if (metroPackageVersionRegex.IsMatch(value))\n                {\n                    return value;\n                }\n                else\n                {\n                    return \"1.0.0.0\";\n                }\n            }\n\n            internal static void ValidateWSAImageType(WSAImageType type)\n            {\n                switch (type)\n                {\n                    case WSAImageType.PackageLogo:\n                    case WSAImageType.SplashScreenImage:\n                    case WSAImageType.UWPSquare44x44Logo:\n                    case WSAImageType.UWPSquare71x71Logo:\n                    case WSAImageType.UWPSquare150x150Logo:\n                    case WSAImageType.UWPSquare310x310Logo:\n                    case WSAImageType.UWPWide310x150Logo:\n                        return;\n                    default:\n                        throw new Exception(\"Unknown WSA image type: \" + type);\n                }\n            }\n\n            internal static void ValidateWSAImageScale(WSAImageScale scale)\n            {\n                switch (scale)\n                {\n                    case WSAImageScale._100:\n                    case WSAImageScale._125:\n                    case WSAImageScale._150:\n                    case WSAImageScale._200:\n                    case WSAImageScale._400:\n                    case WSAImageScale.Target16:\n                    case WSAImageScale.Target24:\n                    case WSAImageScale.Target32:\n                    case WSAImageScale.Target48:\n                    case WSAImageScale.Target256:\n                        return;\n                    default:\n                        throw new Exception(\"Unknown image scale: \" + scale);\n                }\n            }\n\n            public static string GetVisualAssetsImage(WSAImageType type, WSAImageScale scale)\n            {\n                ValidateWSAImageType(type);\n                ValidateWSAImageScale(scale);\n                return GetWSAImage(type, scale);\n            }\n\n            public static void SetVisualAssetsImage(string image, WSAImageType type, WSAImageScale scale)\n            {\n                ValidateWSAImageType(type);\n                ValidateWSAImageScale(scale);\n                SetWSAImage(image, type, scale);\n            }\n\n            public static System.Version packageVersion\n            {\n                get\n                {\n                    try\n                    {\n                        return new System.Version(ValidatePackageVersion(packageVersionRaw));\n                    }\n                    catch (Exception ex)\n                    {\n                        throw new Exception(string.Format(\"{0}, the raw string was {1}\", ex.Message, packageVersionRaw));\n                    }\n                }\n                set { packageVersionRaw = value.ToString(); }\n            }\n\n\n            public static System.DateTime? certificateNotAfter\n            {\n                get\n                {\n                    long value = certificateNotAfterRaw;\n                    if (value != 0)\n                        return System.DateTime.FromFileTime(value);\n                    else\n                        return null;\n                }\n            }\n\n            public static Color? splashScreenBackgroundColor\n            {\n                get\n                {\n                    if (splashScreenUseBackgroundColor)\n                        return splashScreenBackgroundColorRaw;\n                    else\n                        return null;\n                }\n                set\n                {\n                    splashScreenUseBackgroundColor = value.HasValue;\n                    if (value.HasValue)\n                        splashScreenBackgroundColorRaw = value.Value;\n                }\n            }\n\n            public static void SetCapability(WSACapability capability, bool value)\n            {\n                InternalSetCapability(capability.ToString(), value.ToString());\n            }\n\n            public static bool GetCapability(WSACapability capability)\n            {\n                string stringValue = InternalGetCapability(capability.ToString());\n\n                if (string.IsNullOrEmpty(stringValue)) return false;\n\n                try\n                {\n                    return (bool)System.ComponentModel.TypeDescriptor.GetConverter(typeof(bool)).ConvertFromString(stringValue);\n                }\n                catch\n                {\n                    Debug.LogError(\"Failed to parse value  ('\" + capability + \",\" + stringValue + \"') to bool type.\");\n                    return false;\n                }\n            }\n\n            public static void SetTargetDeviceFamily(WSATargetFamily family, bool value)\n            {\n                InternalSetTargetDeviceFamily(family.ToString(), value.ToString());\n            }\n\n            public static bool GetTargetDeviceFamily(WSATargetFamily family)\n            {\n                string stringValue = InternalGetTargetDeviceFamily(family.ToString());\n\n                if (string.IsNullOrEmpty(stringValue)) return false;\n\n                try\n                {\n                    return (bool)System.ComponentModel.TypeDescriptor.GetConverter(typeof(bool)).ConvertFromString(stringValue);\n                }\n                catch\n                {\n                    Debug.LogError(\"Failed to parse value  ('\" + family + \",\" + stringValue + \"') to bool type.\");\n                    return false;\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeTileLogo80\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileLogo80 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileLogo80 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeTileLogo\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileLogo is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileLogo is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeTileLogo140\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileLogo140 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileLogo140 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeTileLogo180\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileLogo180 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileLogo180 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeTileWideLogo80\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileWideLogo80 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileWideLogo80 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeTileWideLogo\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileWideLogo is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileWideLogo is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeTileWideLogo140\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileWideLogo140 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileWideLogo140 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeTileWideLogo180\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileWideLogo180 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileWideLogo180 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeTileSmallLogo80\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileSmallLogo80 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileSmallLogo80 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeTileSmallLogo\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileSmallLogo is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileSmallLogo is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeTileSmallLogo140\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileSmallLogo140 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileSmallLogo140 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeTileSmallLogo180\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileSmallLogo180 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeTileSmallLogo180 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeSmallTile80\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeSmallTile80 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeSmallTile80 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeSmallTile\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeSmallTile is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeSmallTile is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeSmallTile140\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeSmallTile140 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeSmallTile140 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeSmallTile180\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeSmallTile180 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeSmallTile180 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeLargeTile80\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeLargeTile80 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeLargeTile80 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeLargeTile\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeLargeTile is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeLargeTile is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeLargeTile140\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeLargeTile140 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeLargeTile140 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeLargeTile180\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeLargeTile180 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeLargeTile180 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeSplashScreenImage\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeSplashScreenImage is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeSplashScreenImage is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeSplashScreenImageScale140\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeSplashScreenImageScale140 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeSplashScreenImageScale140 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string storeSplashScreenImageScale180\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeSplashScreenImageScale180 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.storeSplashScreenImageScale180 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneAppIcon\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneAppIcon is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneAppIcon is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneAppIcon140\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneAppIcon140 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneAppIcon140 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneAppIcon240\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneAppIcon240 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneAppIcon240 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneSmallTile\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneSmallTile is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneSmallTile is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneSmallTile140\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneSmallTile140 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneSmallTile140 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneSmallTile240\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneSmallTile240 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneSmallTile240 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneMediumTile\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneMediumTile is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneMediumTile is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneMediumTile140\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneMediumTile140 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneMediumTile140 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneMediumTile240\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneMediumTile240 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneMediumTile240 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneWideTile\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneWideTile is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneWideTile is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneWideTile140\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneWideTile140 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneWideTile140 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneWideTile240\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneWideTile240 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneWideTile240 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneSplashScreenImage\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneSplashScreenImage is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneSplashScreenImage is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneSplashScreenImageScale140\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneSplashScreenImageScale140 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneSplashScreenImageScale140 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string phoneSplashScreenImageScale240\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneSplashScreenImageScale240 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.phoneSplashScreenImageScale240 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string packageLogo140\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.packageLogo140 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.packageLogo140 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string packageLogo180\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.packageLogo180 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.packageLogo180 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"Use GetVisualAssetsImage()/SetVisualAssetsImage()\", true)]\n            public static string packageLogo240\n            {\n                get\n                {\n                    throw new NotSupportedException(\"PlayerSettings.packageLogo240 is deprecated. Use GetVisualAssetsImage() instead.\");\n                }\n                set\n                {\n                    throw new NotSupportedException(\"PlayerSettings.packageLogo240 is deprecated. Use SetVisualAssetsImage() instead.\");\n                }\n            }\n\n            [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n            [Obsolete(\"PlayerSettings.enableLowLatencyPresentationAPI is deprecated. It is now always enabled.\", true)]\n            public static bool enableLowLatencyPresentationAPI\n            {\n                get\n                {\n                    return true;\n                }\n                set\n                {\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsWebGL.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing System;\n\nnamespace UnityEditor\n{\n    public enum WebGLExceptionSupport\n    {\n        None = 0,\n        ExplicitlyThrownExceptionsOnly = 1,\n        FullWithoutStacktrace = 2,\n        FullWithStacktrace = 3\n    }\n\n    public enum WebGLCompressionFormat\n    {\n        Brotli,\n        Gzip,\n        Disabled\n    }\n\n    public enum WebGLLinkerTarget\n    {\n        Asm,\n        Wasm,\n        [Obsolete(\"WebGLLinkerTarget.Both mode is no longer supported. Instead you can create separate asm.js and WebAssembly builds and download the appropriate one depending on the browser capabilities.\", true)]\n        Both\n    }\n\n    public enum WebGLWasmArithmeticExceptions\n    {\n        [Obsolete(\"WebGLWasmArithmeticExceptions.Throw mode is no longer supported. WebAssembly arithmetic exceptions are always ignored.\")]\n        Throw,\n        Ignore\n    }\n\n    public enum WebGLDebugSymbolMode\n    {\n        Off = 0,\n        External = 1,\n        Embedded = 2\n    }\n\n    public enum WebGLMemoryGrowthMode\n    {\n        None = 0,\n        Linear = 1,\n        Geometric = 2\n    }\n\n    public enum WebGLPowerPreference\n    {\n        Default = 0,\n        LowPower = 1,\n        HighPerformance = 2\n    }\n\n    public sealed partial class PlayerSettings : UnityEngine.Object\n    {\n        [NativeHeader(\"Editor/Mono/PlayerSettingsWebGL.bindings.h\")]\n        public sealed class WebGL\n        {\n            [NativeProperty(\"webGLMemorySize\", TargetType.Field)]\n            public extern static int memorySize\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLExceptionSupport\", TargetType.Field)]\n            public extern static WebGLExceptionSupport exceptionSupport\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLDataCaching\", TargetType.Field)]\n            public extern static bool dataCaching\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"WebGLEmscriptenArgs\")]\n            public extern static string emscriptenArgs\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"WebGLModulesDirectory\")]\n            public extern static string modulesDirectory\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"WebGLTemplate\")]\n            public extern static string template\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLAnalyzeBuildSize\", TargetType.Field)]\n            public extern static bool analyzeBuildSize\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLUseEmbeddedResources\", TargetType.Field)]\n            public extern static bool useEmbeddedResources\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [Obsolete(\"useWasm Property deprecated. Use linkerTarget instead\")]\n            public static bool useWasm\n            {\n                get { return linkerTarget != WebGLLinkerTarget.Asm; }\n                set { linkerTarget = value ? WebGLLinkerTarget.Both : WebGLLinkerTarget.Asm; }\n            }\n\n            [NativeProperty(\"webGLThreadsSupport\", TargetType.Field)]\n            public extern static bool threadsSupport\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLLinkerTarget\", TargetType.Field)]\n            public extern static WebGLLinkerTarget linkerTarget\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLCompressionFormat\", TargetType.Field)]\n            public extern static WebGLCompressionFormat compressionFormat\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLNameFilesAsHashes\", TargetType.Field)]\n            public extern static bool nameFilesAsHashes\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLDebugSymbols\", TargetType.Field)]\n            public extern static WebGLDebugSymbolMode debugSymbolMode\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLShowDiagnostics\", TargetType.Field)]\n            public extern static bool showDiagnostics\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [Obsolete(\"debugSymbols Property deprecated. Property has been replaced by debugSymbolMode property.\", false)]\n            public static bool debugSymbols\n            {\n                get { return debugSymbolMode != WebGLDebugSymbolMode.Off; }\n                set { debugSymbolMode = value ? WebGLDebugSymbolMode.External : WebGLDebugSymbolMode.Off; }\n            }\n\n            [Obsolete(\"wasmStreaming Property deprecated. WebAssembly streaming will be automatically used when decompressionFallback is disabled and vice versa.\", true)]\n            [NativeProperty(\"webGLWasmStreaming\", TargetType.Field)]\n            public extern static bool wasmStreaming\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLDecompressionFallback\", TargetType.Field)]\n            public extern static bool decompressionFallback\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLWasmArithmeticExceptions\", TargetType.Field)]\n            public extern static WebGLWasmArithmeticExceptions wasmArithmeticExceptions\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLInitialMemorySize\", TargetType.Field)]\n            public extern static int initialMemorySize\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLMaximumMemorySize\", TargetType.Field)]\n            public extern static int maximumMemorySize\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLMemoryGrowthMode\", TargetType.Field)]\n            public extern static WebGLMemoryGrowthMode memoryGrowthMode\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLMemoryLinearGrowthStep\", TargetType.Field)]\n            public extern static int linearMemoryGrowthStep\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLMemoryGeometricGrowthStep\", TargetType.Field)]\n            public extern static float geometricMemoryGrowthStep\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLMemoryGeometricGrowthCap\", TargetType.Field)]\n            public extern static int memoryGeometricGrowthCap\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLPowerPreference\", TargetType.Field)]\n            public extern static WebGLPowerPreference powerPreference\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLWebAssemblyTable\", TargetType.Field)]\n            public extern static bool webAssemblyTable\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLWebAssemblyBigInt\", TargetType.Field)]\n            public extern static bool webAssemblyBigInt\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webGLCloseOnQuit\", TargetType.Field)]\n            public extern static bool closeOnQuit\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webWasm2023\", TargetType.Field)]\n            public extern static bool wasm2023\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)] get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)] set;\n            }\n\n            [NativeProperty(\"webEnableSubmoduleStrippingCompatibility\", TargetType.Field)]\n            public extern static bool enableSubmoduleStrippingCompatibility\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PlayerSettingsXboxOne.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System;\n\nnamespace UnityEditor\n{\n    [Obsolete(\"The XDK Xbox One platform was removed in 2021.1\", false)]\n    public enum XboxOneEncryptionLevel\n    {\n        None = 0,\n        DevkitCompatible = 1,\n        FullEncryption = 2\n    }\n\n    [Obsolete(\"The XDK Xbox One platform was removed in 2021.1\", false)]\n    public enum XboxOnePackageUpdateGranularity\n    {\n        Chunk = 1,\n        File = 2\n    }\n\n    [Obsolete(\"The XDK Xbox One platform was removed in 2021.1\", false)]\n    public enum XboxOneLoggingLevel\n    {\n        AllLogging = 4,\n        WarningsAndErrors = 2,\n        ErrorsOnly = 1\n    }\n\n    [Obsolete(\"Mono script compiler is no longer supported.\")]\n    public enum ScriptCompiler\n    {\n        Mono = 0,\n        Roslyn = 1\n    }\n\n    public sealed partial class PlayerSettings\n    {\n\n        [Obsolete(\"The XDK Xbox One platform was removed in 2021.1\", false)]\n\n        [NativeHeader(\"Runtime/Misc/PlayerSettings.h\")]\n        [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n        public sealed partial class XboxOne\n        {\n            [NativeProperty(\"XboxOneXTitleMemory\", TargetType.Field)]\n            extern public static int XTitleMemory\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"XboxOneLoggingLevel\")]\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static XboxOneLoggingLevel defaultLoggingLevel { get; set; }\n\n            // Xbox One product id\n            [NativeProperty(\"XboxOneProductId\", false, TargetType.Function)]\n            extern public static string ProductId { get; set; }\n\n            // Xbox One update key required to ship updates\n            [NativeProperty(\"XboxOneUpdateKey\", false, TargetType.Function)]\n            extern public static string UpdateKey { get; set; }\n\n            // Xbox One App Sandbox Id\n            [Obsolete(\"SandboxId is obsolete please remove\")]\n            [NativeProperty(\"XboxOneSandboxId\", false, TargetType.Function)]\n            extern public static string SandboxId { get; set; }\n\n            // Xbox One App Content Id\n            [NativeProperty(\"XboxOneContentId\", false, TargetType.Function)]\n            extern public static string ContentId { get; set; }\n\n            // Xbox One App Title Id\n            [NativeProperty(\"XboxOneTitleId\", false, TargetType.Function)]\n            extern public static string TitleId { get; set; }\n\n            // Xbox One App Title SCID\n            [NativeProperty(\"XboxOneSCId\", false, TargetType.Function)]\n            extern public static string SCID { get; set; }\n\n            [NativeProperty(\"XboxOneEnableGPUVariability\", TargetType.Field)]\n            extern public static bool EnableVariableGPU\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            [NativeProperty(\"XboxOnePresentImmediateThreshold\")]\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static UInt32 PresentImmediateThreshold { get; set; }\n\n            [NativeProperty(\"XboxOneEnable7thCore\")]\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static bool Enable7thCore { get; set; }\n\n            [NativeProperty(\"XboxOneDisableKinectGpuReservation\")]\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static bool DisableKinectGpuReservation { get; set; }\n\n            [NativeProperty(\"XboxEnablePIXSampling\")]\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static bool EnablePIXSampling { get; set; }\n\n            // Path of the os image shipped with this app.\n            [NativeProperty(\"XboxOneGameOsOverridePath\", false, TargetType.Function)]\n            extern public static string GameOsOverridePath { get; set; }\n\n            // Packaging manifest used to build this app\n            [NativeProperty(\"XboxOnePackagingOverridePath\", false, TargetType.Function)]\n            extern public static string PackagingOverridePath { get; set; }\n\n            // Encryption option used when making this package\n            [NativeProperty(\"XboxOnePackageEncryption\", TargetType.Field)]\n            extern public static XboxOneEncryptionLevel PackagingEncryption\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            // The update granularity used when making a package.\n            [NativeProperty(\"XboxOnePackageUpdateGranularity\", TargetType.Field)]\n            extern public static XboxOnePackageUpdateGranularity PackageUpdateGranularity\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            // Xbox One override auto generated identity name in app manifest (does not work with app manifest override).\n            [NativeProperty(\"XboxOneOverrideIdentityName\", false, TargetType.Function)]\n            extern public static string OverrideIdentityName { get; set; }\n\n            // Xbox One override auto generated identity publisher in app manifest (does not work with app manifest override).\n            [NativeProperty(\"XboxOneOverrideIdentityPublisher\", false, TargetType.Function)]\n            extern public static string OverrideIdentityPublisher { get; set; }\n\n            // Optional override path for app manifest.\n            [NativeProperty(\"XboxOneAppManifestOverridePath\", false, TargetType.Function)]\n            extern public static string AppManifestOverridePath { get; set; }\n\n            // Returns true if this project represents DLC / content.\n            [NativeProperty(\"XboxOneIsContentPackage\", TargetType.Field)]\n            extern public static bool IsContentPackage\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            // Returns true Xbox Compatibility mode should be set to max in manifest\n            [NativeProperty(\"XboxOneEnhancedXboxCompatibilityMode\", TargetType.Field)]\n            extern public static bool EnhancedXboxCompatibilityMode\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n            // Version used in AppManifest\n            [NativeProperty(\"XboxOneVersion\", false, TargetType.Function)]\n            extern public static string Version { get; set; }\n\n            // Description used in AppManifest\n            [NativeProperty(\"XboxOneDescription\", false, TargetType.Function)]\n            extern public static string Description { get; set; }\n\n            // *undocumented*\n            [NativeMethod(\"SetXboxOneCapability\")]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            extern public static void SetCapability(string capability, bool value);\n\n            // *undocumented*\n            [NativeMethod(\"GetXboxOneCapability\")]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            extern public static bool GetCapability(string capability);\n\n\n            [NativeMethod(\"SetXboxOneLanguage\")]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            extern public static void SetSupportedLanguage(string language, bool enabled);\n\n            [NativeMethod(\"GetXboxOneLanguage\")]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            extern public static bool GetSupportedLanguage(string language);\n\n\n            [NativeMethod(\"RemoveXboxOneSocketDefinition\")]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            extern public static void RemoveSocketDefinition(string name);\n\n            [NativeMethod(\"SetXboxOneSocketDefinition\")]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            extern public static void SetSocketDefinition(string name, string port, int protocol, int[] usages, string templateName, int sessionRequirment, int[] deviceUsages);\n\n            [NativeMethod(\"GetXboxOneSocketDefinition\")]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            extern private static void GetSocketDefinitionInternal(string name, out string port, out int protocol, [Out] int[] usages, out string templateName, out int sessionRequirment, [Out] int[] deviceUsages);\n\n            public static void GetSocketDefinition(string name, out string port, out int protocol, out int[] usages, out string templateName, out int sessionRequirment, out int[] deviceUsages)\n            {\n                int numUsages = GetXboxOneSocketDefinitionNumUsages(name);\n                int numDeviceUsages = GetXboxOneSocketDefinitionNumDeviceUsages(name);\n                if (numUsages < 0 || numDeviceUsages < 0)\n                    throw new ArgumentException(\"Could not find socket definition \" + name + \".\");\n\n                usages = new int[numUsages];\n                deviceUsages = new int[numDeviceUsages];\n\n                GetSocketDefinitionInternal(name, out port, out protocol, usages, out templateName, out sessionRequirment, deviceUsages);\n            }\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            extern public static string[] SocketNames\n            {\n                [NativeMethod(\"GetXboxOneSocketNames\")]\n                get;\n            }\n\n            [NativeMethod(\"GetXboxOneSocketDefinitionNumUsages\")]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            extern private static int GetXboxOneSocketDefinitionNumUsages(string name);\n\n            [NativeMethod(\"GetXboxOneSocketDefinitionNumDeviceUsages\")]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            extern private static int GetXboxOneSocketDefinitionNumDeviceUsages(string name);\n\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            extern public static string[] AllowedProductIds\n            {\n                [NativeMethod(\"GetXboxOneAllowedProductIds\")]\n                get;\n            }\n\n            [NativeMethod(\"RemoveXboxOneAllowedProductId\")]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            extern public static void RemoveAllowedProductId(string id);\n\n            [NativeMethod(\"AddXboxOneAllowedProductId\")]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            extern public static bool AddAllowedProductId(string id);\n\n            [NativeMethod(\"UpdateXboxOneAllowedProductId\")]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            extern public static void UpdateAllowedProductId(int idx, string id);\n\n            // *undocumented*\n            [Obsolete(\"Starting May 11th 2020 any new base game submission releasing digital only, \" +\n                \"digital and disc, or disc only, should not include a ratings element in the \" +\n                \"AppxManifest. This ratings policy update applies to all Xbox supported ratings. \" +\n                \"New base submissions that come in on or after this date will be \" +\n                \"rejected by your Microsoft Representative if a ratings element is present.\", false)]\n            [NativeMethod(\"SetXboxOneGameRating\")]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n            extern public static void SetGameRating(string name, int value);\n\n            // *undocumented*\n            [Obsolete(\"Starting May 11th 2020 any new base game submission releasing digital only, \" +\n                \"digital and disc, or disc only, should not include a ratings element in the \" +\n                \"AppxManifest. This ratings policy update applies to all Xbox supported ratings. \" +\n                \"New base submissions that come in on or after this date will be \" +\n                \"rejected by your Microsoft Representative if a ratings element is present.\", false)]\n            [NativeMethod(\"GetXboxOneGameRating\")]\n            [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n            extern public static int GetGameRating(string name);\n\n            // The presence of any other value than 0 for this property will result in a PLS reservation in your app manifest.\n            public static uint PersistentLocalStorageSize\n            {\n                get { return persistentLocalStorageSizeInternal; }\n                set\n                {\n                    if (value < 256 || value >= 4096)\n                        throw new ArgumentException(string.Format(\"PersistentLocalStorageSize must be between 256 and 4096, but was {0}\", value));\n\n                    persistentLocalStorageSizeInternal = value;\n                }\n            }\n\n            [NativeProperty(\"XboxOnePersistentLocalStorageSize\", TargetType.Field)]\n            extern private static uint persistentLocalStorageSizeInternal\n            {\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnly()\", StaticAccessorType.Dot)]\n                get;\n                [StaticAccessor(\"GetPlayerSettings().GetEditorOnlyForUpdate()\", StaticAccessorType.Dot)]\n                set;\n            }\n\n            // Enable/Disable Type Optimization in C++ Compiler 'Master' build, applies to LTCG.\n            [NativeProperty(\"XboxOneEnableTypeOptimization\")]\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static bool EnableTypeOptimization { get; set; }\n\n            // Whether we have enabled mono trace logs on xboxOne for debugging purposes.\n            [NativeProperty(\"XboxOneMonoLoggingLevel\")]\n            [StaticAccessor(\"GetPlayerSettings()\", StaticAccessorType.Dot)]\n            extern public static int monoLoggingLevel { get; set; }\n\n            // Compiler to use for user script\n            [Obsolete(\"Mono script compiler is no longer supported.\")]\n            public static ScriptCompiler scriptCompiler\n            {\n                get\n                {\n                    return ScriptCompiler.Roslyn;\n                }\n                set\n                {\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PluginDesc.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace UnityEditorInternal\n{\n    internal struct PluginDesc\n    {\n        public string pluginPath;\n        public CPUArch architecture;\n    }\n\n    internal enum CPUArch\n    {\n        Any,\n        x86,\n        ARMv7\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Plugins/PluginsHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.Modules;\nusing UnityEditor;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditorInternal\n{\n    internal class PluginsHelper\n    {\n        [RequiredByNativeCode]\n        public static bool CheckFileCollisions(BuildTarget buildTarget, string[] defineConstraints)\n        {\n            // Checks that plugins don't collide with each other\n            IPluginImporterExtension pluginImporterExtension = null;\n            if (ModuleManager.IsPlatformSupported(buildTarget))\n                pluginImporterExtension = ModuleManager.GetPluginImporterExtension(buildTarget);\n            if (pluginImporterExtension == null)\n            {\n                // Some platforms don't have platform specific settings for plugins, but we still want to check that plugins don't collide, use default path in this case\n                if (BuildPipeline.GetBuildTargetGroup(buildTarget) == BuildTargetGroup.Standalone)\n                    pluginImporterExtension = new DesktopPluginImporterExtension();\n                else\n                    pluginImporterExtension = new DefaultPluginImporterExtension(null);\n            }\n\n            if (pluginImporterExtension.CheckFileCollisions(BuildPipeline.GetBuildTargetName(buildTarget), defineConstraints))\n                return true;\n\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PointCreator.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing UnityEngine;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal interface ICreatablePoint\n    {\n        void AddPositions(List<Vector3> newPositions);\n    }\n\n    internal class PointCreator\n    {\n        private static List<Vector3> s_CreationPoints = new List<Vector3>();\n        private static bool s_IsCreating;\n\n        private static bool GetCreationPoint(out Vector3 position, bool useRaycast, LayerMask raycastMask, float raycastNormalOffset)\n        {\n            position = Event.current.mousePosition;\n            Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);\n            if (useRaycast)\n            {\n                position.y = Screen.height - position.y;\n                RaycastHit hit = new RaycastHit();\n                if (Physics.Raycast(ray, out hit, float.MaxValue, raycastMask))\n                {\n                    position = hit.point;\n                    if (!Mathf.Approximately(raycastNormalOffset, 0.0f))\n                    {\n                        var offset = new Vector3(hit.normal.x * raycastNormalOffset, hit.normal.y * raycastNormalOffset, hit.normal.z * raycastNormalOffset);\n                        position += offset;\n                    }\n                }\n                else\n                    return false;\n            }\n            else\n            {\n                var offset = new Vector3(ray.direction.x * raycastNormalOffset, ray.direction.y * raycastNormalOffset, ray.direction.z * raycastNormalOffset);\n                position = ray.origin + offset;\n            }\n            return true;\n        }\n\n        public static void CreatePoints(ICreatablePoint pointCreator, bool allowDrawing, bool useRaycast, LayerMask raycastMask, float raycastNormalOffset, float minDistanceBetweenPoints)\n        {\n            int id = GUIUtility.GetControlID(FocusType.Passive);\n\n            if (Event.current.alt && Event.current.type != EventType.Repaint)\n                return;\n\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.Layout:\n                    HandleUtility.AddDefaultControl(id);\n                    break;\n\n                case EventType.MouseDown:\n                    if (HandleUtility.nearestControl == id && evt.button == 0)\n                    {\n                        s_IsCreating = true;\n                        s_CreationPoints.Clear();\n                        Vector3 pos;\n                        if (GetCreationPoint(out pos, useRaycast, raycastMask, raycastNormalOffset))\n                        {\n                            s_CreationPoints.Add(pos);\n                        }\n\n                        // Use the mouse down event so no other controls get them\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    // If we got the mousedown event, the mouseup is ours as well - this is where we clean up.\n                    if (evt.button == 0)\n                    {\n                        s_IsCreating = false;\n\n                        // Selection has changed. set GUI.changed to true so caller can react (e.g. repaint inspector).\n                        GUI.changed = true;\n\n                        pointCreator.AddPositions(s_CreationPoints);\n\n                        s_CreationPoints.Clear();\n                        GUIUtility.hotControl = 0;\n                        evt.Use();\n                    }\n                    break;\n                case EventType.MouseDrag:\n                    if (s_IsCreating && allowDrawing)\n                    {\n                        Vector3 pos;\n                        if (GetCreationPoint(out pos, useRaycast, raycastMask, raycastNormalOffset))\n                        {\n                            if (s_CreationPoints.Count == 0)\n                            {\n                                s_CreationPoints.Add(pos);\n                            }\n                            else if (Vector3.Distance(s_CreationPoints[s_CreationPoints.Count - 1], pos) >= minDistanceBetweenPoints)\n                            {\n                                s_CreationPoints.Add(pos);\n                            }\n                        }\n\n                        evt.Use();\n                    }\n                    break;\n            }\n        }\n\n        public static void Draw()\n        {\n            if (s_CreationPoints.Count > 0)\n            {\n                Handles.color = Color.yellow;\n                Handles.DrawAAPolyLine(15, s_CreationPoints.Count, s_CreationPoints.ToArray());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PointEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing UnityEngine;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    /// Semi-Generic point editor.\n    /// A Point editor basically let you drag around an array of Vector3 points in the scene view.\n\n    /// In order to maximize flexibility, all communication goes through the IEditablePoint interface.\n    /// The point editor uses this to make callbacks to your editor so no assumptions about your data structure is made.\n    internal interface IEditablePoint\n    {\n        /// Get the world-space position of a specific point\n        Vector3 GetPosition(int idx);\n        /// Set the world-space position of a specific point\n        void SetPosition(int idx, Vector3 position);\n        /// Get the default color for points\n        Color GetDefaultColor();\n        /// Get tje selected color for points\n        Color GetSelectedColor();\n        /// Scale of the spheres to draw\n        float GetPointScale();\n        /// Get the positions of the points\n        IEnumerable<Vector3> GetPositions();\n\n        Vector3[] GetUnselectedPositions();\n        Vector3[] GetSelectedPositions();\n\n        int Count { get; }\n    }\n\n    internal class PointEditor\n    {\n        // Various variables to keep track of the state of selection rects.\n        // Since the user can not be dragging inside more than one thing (they only have one mouse), we can\n        // just have these be static.\n        //\n        // The point on screen that the user started dragging a selection rect from.\n        private static Vector2 s_StartMouseDragPosition;\n        // The selection at the start of the drag. Using this and the start mousepos,\n        // we can reconstruct the selection live during the drag so the user will always see the drag.\n        private static List<int> s_StartDragSelection;\n\n        private static bool s_DidDrag;\n\n        /// Move the selected points using standard handles. returns true if point moved\n        public static bool MovePoints(IEditablePoint points, Transform cloudTransform, List<int> selection)\n        {\n            if (selection.Count == 0)\n                return false;\n\n            // Editing for the case where we're in a 3D sceneview\n            if (Camera.current)\n            {\n                var handlePos = Vector3.zero;\n                handlePos = Tools.pivotMode == PivotMode.Pivot ?\n                    points.GetPosition(selection[0]) :\n                    selection.Aggregate(handlePos, (current, index) => current + points.GetPosition(index)) / selection.Count;\n\n                if (cloudTransform != null)\n                    handlePos = cloudTransform.TransformPoint(handlePos);\n\n                var newPos = Handles.PositionHandle(handlePos,\n                    Tools.pivotRotation == PivotRotation.Local && cloudTransform != null ? cloudTransform.rotation : Quaternion.identity);\n                if (GUI.changed)\n                {\n                    Vector3 delta;\n                    if (cloudTransform != null)\n                        delta = cloudTransform.InverseTransformPoint(newPos) - cloudTransform.InverseTransformPoint(handlePos);\n                    else\n                        delta = newPos - handlePos;\n\n                    foreach (int i in selection)\n                        points.SetPosition(i, points.GetPosition(i) + delta);\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public static int FindNearest(Vector2 point, Transform cloudTransform, IEditablePoint points)\n        {\n            var r = HandleUtility.GUIPointToWorldRay(point);\n\n            var found = new Dictionary<int, float>();\n            for (var i = 0; i < points.Count; i++)\n            {\n                float distance = 0;\n                Vector3 collisionPoint = Vector3.zero;\n\n                Vector3 position = cloudTransform != null ? cloudTransform.TransformPoint(points.GetPosition(i)) : points.GetPosition(i);\n                if (MathUtils.IntersectRaySphere(r, position, (points.GetPointScale() / 2.0f), ref distance, ref collisionPoint))\n                {\n                    //Only care if we start outside a probe\n                    if (distance > 0)\n                    {\n                        found.Add(i, distance);\n                    }\n                }\n            }\n\n            if (found.Count <= 0) return -1;\n\n            var sorted = found.OrderBy(x => x.Value);\n            return sorted.First().Key;\n        }\n\n        private static List<int> s_SelectionStart;\n        // This function implements selection of points. Returns true is selection changes\n        public static bool SelectPoints(IEditablePoint points, Transform cloudTransform, ref List<int> selection)\n        {\n            int id = GUIUtility.GetControlID(FocusType.Passive);\n\n            if (Event.current.alt && Event.current.type != EventType.Repaint)\n                return false;\n\n            bool selectionChanged = false;\n            Event evt = Event.current;\n            switch (evt.GetTypeForControl(id))\n            {\n                case EventType.Layout:\n                    // Tell the handles system that we're the default tool (the one that should get focus when user clicks on nothing else.)\n                    HandleUtility.AddDefaultControl(id);\n                    break;\n\n                case EventType.MouseDown:\n                    // If we got a left-mouse down (HandleUtility.nearestControl== id is only true when the user clicked outside any handles),\n                    // we should begin selecting.\n                    if ((HandleUtility.nearestControl == id) && evt.button == 0)\n                    {\n                        // If neither shift nor control is held down, we'll clear the selection as the fist thing.\n                        if (!evt.shift && !EditorGUI.actionKey)\n                        {\n                            selection.Clear();\n                            selectionChanged = true;\n                        }\n\n                        s_SelectionStart = new List<int>(selection);\n                        // Grab focus so that we can do a rect selection.\n                        GUIUtility.hotControl = id;\n                        // And remember where the drag was from.\n                        s_StartMouseDragPosition = evt.mousePosition;\n\n                        // Also remember the selection at the start so additive rect selection will work correctly\n                        s_StartDragSelection = new List<int>(selection);\n\n                        // Use the mouse down event so no other controls get them\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseDrag:\n                    // The user dragged the mouse (and we have the focus from MouseDown). We have a rect selection here\n                    if (GUIUtility.hotControl == id && evt.button == 0)\n                    {\n                        s_DidDrag = true;\n                        // Start by resetting the selection to what it was when the drag began.\n                        selection.Clear();\n                        selection.AddRange(s_StartDragSelection);\n\n                        // now, we'll go over every point and see if it's inside the Rect defined by the mouse position and\n                        // the start drag position\n                        Rect r = FromToRect(s_StartMouseDragPosition, evt.mousePosition);\n\n                        using (new Handles.DrawingScope())\n                        {\n                            if (cloudTransform != null)\n                                Handles.matrix = cloudTransform.localToWorldMatrix;\n\n                            // Go over all the points and add them if they are inside the rect\n                            for (int i = 0; i < points.Count; i++)\n                            {\n                                var point = HandleUtility.WorldToGUIPointWithDepth(points.GetPosition(i));\n\n                                // the point has to be within the selection and in front of the camera\n                                if (r.Contains(point) && point.z > 0.0f)\n                                {\n                                    if (EditorGUI.actionKey)\n                                    {\n                                        if (s_SelectionStart.Contains(i))\n                                        {\n                                            selection.Remove(i);\n                                        }\n                                    }\n                                    else\n                                    {\n                                        if (!s_SelectionStart.Contains(i))\n                                        {\n                                            selection.Add(i);\n                                        }\n                                    }\n                                }\n                            }\n                        }\n\n                        // We'll assume the selection has changed and set GUI.changed to true.\n                        // Worst case, somebody will validate a bit too much, but oh well.\n                        GUI.changed = true;\n                        evt.Use();\n                    }\n                    break;\n\n                case EventType.MouseUp:\n                    // If we got the mousedown event, the mouseup is ours as well - this is where we clean up.\n                    if (GUIUtility.hotControl == id && evt.button == 0)\n                    {\n                        //Dragging vs clicking\n                        if (!s_DidDrag)\n                        {\n                            // Find out if it was on top of a point.\n                            int selectedPoint = FindNearest(s_StartMouseDragPosition, cloudTransform, points);\n\n                            // We found a point. We either need to make it selected or add it to an existing selection.\n                            if (selectedPoint != -1)\n                            {\n                                // If neither shift nor action is held down, simply set selection to the picked point.\n                                if (!evt.shift && !EditorGUI.actionKey)\n                                {\n                                    selection.Add(selectedPoint);\n                                }\n                                else\n                                {\n                                    // Shift was held down. This means we need to add/remove the point\n                                    int alreadyInSelection = selection.IndexOf(selectedPoint);\n                                    if (alreadyInSelection != -1) selection.RemoveAt(alreadyInSelection);\n                                    else selection.Add(selectedPoint);\n                                }\n                            }\n\n                            // Selection has changed. set GUI.changed to true so caller can react (e.g. repaint inspector).\n                            GUI.changed = true;\n                            selectionChanged = true;\n                        }\n\n\n                        // Clean up various stuff.\n                        s_StartDragSelection = null;\n                        s_StartMouseDragPosition = Vector2.zero;\n                        s_DidDrag = false;\n\n                        // Release the mouse focus\n                        GUIUtility.hotControl = 0;\n\n                        // use the event\n                        evt.Use();\n                    }\n                    break;\n                case EventType.Repaint:\n                    // If we have focus and the mouse has been moved, we'll the draw selection rect.\n                    if (GUIUtility.hotControl == id && evt.mousePosition != s_StartMouseDragPosition)\n                    {\n                        GUIStyle gs = \"SelectionRect\";\n                        Handles.BeginGUI();\n                        gs.Draw(FromToRect(s_StartMouseDragPosition, evt.mousePosition), false, false, false, false);\n                        Handles.EndGUI();\n                    }\n                    break;\n            }\n            if (selectionChanged)\n                selection = selection.Distinct().ToList();\n            return selectionChanged;\n        }\n\n        /// Draw the points in points array. All selected points will be drawn blue, for unselected,\n        /// points.GetColor will be called to get the color of each point\n        public static void Draw(IEditablePoint points, Transform cloudTransform, List<int> selection, bool twoPassDrawing)\n        {\n            LightProbeVisualization.DrawPointCloud(\n                points.GetUnselectedPositions(),\n                points.GetSelectedPositions(),\n                points.GetDefaultColor(),\n                points.GetSelectedColor(),\n                points.GetPointScale(),\n                cloudTransform);\n        }\n\n        // Small helper: Build a rect and make sure that rect has positive size so Rect.Contains works correctly.\n        static Rect FromToRect(Vector2 from, Vector2 to)\n        {\n            var r = new Rect(from.x, from.y, to.x - from.x, to.y - from.y);\n\n            if (r.width < 0)\n            {\n                r.x += r.width;\n                r.width = -r.width;\n            }\n            if (r.height < 0)\n            {\n                r.y += r.height;\n                r.height = -r.height;\n            }\n            return r;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PolygonEditor.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing System;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/PolygonEditor.h\")]\n    internal partial class PolygonEditor\n    {\n        [NativeThrows]\n        extern public static void StartEditing([NotNull] Collider2D collider);\n        [NativeThrows]\n        extern public static void ApplyEditing([NotNull] Collider2D collider);\n\n        [StaticAccessor(\"PolygonEditor::Get()\", StaticAccessorType.Dot)]\n        extern public static void StopEditing();\n\n        [StaticAccessor(\"PolygonEditor::Get()\", StaticAccessorType.Dot)]\n        extern public static bool GetNearestPoint(Vector2 point, out int pathIndex, out int pointIndex, out float distance);\n\n        [StaticAccessor(\"PolygonEditor::Get()\", StaticAccessorType.Dot)]\n        extern public static bool GetNearestEdge(Vector2 point, out int pathIndex, out int pointIndex0, out int pointIndex1, out float distance, bool loop);\n\n        [StaticAccessor(\"PolygonEditor::Get()\", StaticAccessorType.Dot)]\n        extern public static int GetPathCount();\n\n        [StaticAccessor(\"PolygonEditor::Get()\", StaticAccessorType.Dot)]\n        extern public static int GetPointCount(int pathIndex);\n\n        [StaticAccessor(\"PolygonEditor::Get()\", StaticAccessorType.Dot)]\n        extern public static bool GetPoint(int pathIndex, int pointIndex, out Vector2 point);\n\n        [StaticAccessor(\"PolygonEditor::Get()\", StaticAccessorType.Dot)]\n        extern public static void SetPoint(int pathIndex, int pointIndex, Vector2 value);\n\n        [StaticAccessor(\"PolygonEditor::Get()\", StaticAccessorType.Dot)]\n        extern public static void InsertPoint(int pathIndex, int pointIndex, Vector2 value);\n\n        [StaticAccessor(\"PolygonEditor::Get()\", StaticAccessorType.Dot)]\n        extern public static void RemovePoint(int pathIndex, int pointIndex);\n\n        [StaticAccessor(\"PolygonEditor::Get()\", StaticAccessorType.Dot)]\n        extern public static void TestPointMove(int pathIndex, int pointIndex, Vector2 movePosition, out bool leftIntersect, out bool rightIntersect, bool loop);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PostprocessScene.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.Build;\n\nnamespace UnityEditor\n{\n    internal class UnityBuildPostprocessor : IProcessSceneWithReport\n    {\n        public int callbackOrder { get { return 0; } }\n\n        public void OnProcessScene(UnityEngine.SceneManagement.Scene scene, Build.Reporting.BuildReport report)\n        {\n            int staticBatching, dynamicBatching;\n            PlayerSettings.GetBatchingForPlatform(EditorUserBuildSettings.activeBuildTarget, out staticBatching, out dynamicBatching);\n            if (staticBatching != 0)\n            {\n                using (StaticBatchingUtility.s_CombineMarker.Auto())\n                {\n                    ulong sceneHash = Hash128.Compute(AssetDatabase.AssetPathToGUID(scene.path)).u64_0;\n                    StaticBatchingEditorHelper.CombineAllStaticMeshesForScenePostProcessing(sceneHash, scene);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Prefabs/PrefabFamilyPopup.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\nusing UnityEditor.SceneManagement;\nusing System.Linq;\nusing System;\nusing UnityEngine.Assertions;\n\nnamespace UnityEditor\n{\n    class PrefabFamilyPopup : PopupWindowContent\n    {\n        GameObject m_Target;\n        string m_TargetPath;\n        string m_TargetGUID;\n\n        struct AncestorItem\n        {\n            public string assetPath;\n            public int overrideCount;\n        }\n        AncestorItem[] m_AncestorItems;\n        OverridesCounterForPrefabAssets m_OverridesCounter;\n        int numRows => m_AncestorItems.Length;\n\n        bool m_DisplayChildren = false;\n        ObjectListArea m_ListArea;\n        ObjectListAreaState m_ListAreaState = new ObjectListAreaState() { m_GridSize = 56 };\n        SavedInt m_SavedGridSize = new SavedInt(\"PrefabFamilyPopup.GridSize\", 56);\n        int[] m_Results = null;\n        Delayer m_Debounce;\n        SearchFilter m_SearchFilter;\n        string m_SearchFilterString = \"\";\n        Vector2 m_Scroll = Vector2.zero;\n        IEnumerator<HierarchyProperty> m_Enumerator = null;\n        const int k_MinIconSize = 20;\n\n        static bool s_Open = false;\n        bool m_Debug = false;\n\n        float m_WindowWidth, m_NamesWidth, m_MaxNameWidth, m_NoResultsX, m_OverridesX;\n\n        const int k_MaxSearchIterationPerFrame = 500;\n        const int k_MaxTableRows = 10;\n        const float k_MinWindowWidth = 300f, k_MaxWindowWidth = 700f;\n        const float k_HeaderHeight = 28f;\n        const float k_EntryHeight = 20f;\n        const float k_SliderWidth = 55f;\n        const float k_SearchHeight = 150f;\n        const float k_Padding = 3f;\n        const float k_OffsetX = 6f;\n        const float k_SplitWidth = 1f;\n        readonly float k_MinNameWidth;\n        readonly float k_TitleWidth = k_OffsetX + 50f;\n        readonly float k_OverridesWidth = k_SplitWidth + EditorStyles.miniLabel.CalcSize(Styles.overridesLabel).x + 2 * k_Padding;\n        readonly float k_ScrollbarWidth = GUI.skin.verticalScrollbar.fixedWidth + GUI.skin.verticalScrollbar.margin.left;\n        readonly float k_ScrollbarHeight = GUI.skin.horizontalScrollbar.fixedHeight + GUI.skin.horizontalScrollbar.margin.top;\n\n\n        public static class Colors\n        {\n            static Color header_l = new Color32(0xDF, 0xDF, 0xDF, 0xFF);\n            static Color header_d = new Color(0.5f, 0.5f, 0.5f, 0.2f);\n\n            static Color[] rows_l = new Color[2]\n            {\n                new Color32(0xC8, 0xC8, 0xC8, 0xFF),\n                new Color32(0xCE, 0xCE, 0xCE, 0xFF)\n            };\n\n            static Color[] rows_d = new Color[2]\n            {\n                new Color32(0x38, 0x38, 0x38, 0xFF),\n                new Color32(0x3E, 0x3E, 0x3E, 0xFF)\n            };\n\n            public static Color headerBackground { get { return EditorGUIUtility.isProSkin ? Colors.header_d : Colors.header_l; } }\n            public static Color rowBackground(int i) => EditorGUIUtility.isProSkin ? Colors.rows_d[i % 2] : Colors.rows_l[i % 2];\n        }\n\n        public static class Styles\n        {\n            public static readonly GUIContent rootLabel = EditorGUIUtility.TrTextContent(\"Root\", \"The root of the Prefab Variant hierarchy\");\n            public static readonly GUIContent selectedLabel = EditorGUIUtility.TrTextContent(\"Current\", \"The currently selected Prefab\");\n            public static readonly GUIContent titlePrefixLabel = EditorGUIUtility.TrTextContent(\"Variant Family of\");\n            public static readonly GUIContent ancestorLabel = EditorGUIUtility.TrTextContent(\"Ancestors\");\n            public static readonly GUIContent overridesLabel = EditorGUIUtility.TrTextContent(\"Overrides\");\n            public static readonly GUIContent childrenLabel = EditorGUIUtility.TrTextContent(\"Children\");\n            public static readonly GUIContent noResultsLabel = EditorGUIUtility.TrTextContent(\"No results\");\n            public static readonly GUIContent noChildrenLabel = EditorGUIUtility.TrTextContent(\"This Prefab doesn't have any children.\\nPrefab Variants created from this Prefab\\nwill be listed here.\");\n            public static readonly GUIStyle searchBackground = new GUIStyle(\"ProjectBrowserIconAreaBg\");\n            public static readonly GUIStyle centered = new GUIStyle(EditorStyles.label) { alignment = TextAnchor.MiddleCenter };\n            public static readonly GUIStyle boldRightAligned = new GUIStyle(EditorStyles.boldLabel)\n            {\n                alignment = TextAnchor.MiddleRight,\n                fontSize = (int)(1.1f * EditorStyles.boldLabel.fontSize)\n            };\n            public static readonly GUIStyle boldNumber = new GUIStyle(EditorStyles.boldLabel)\n            {\n                fontSize = (int)(0.9f * EditorStyles.boldLabel.fontSize)\n            };\n\n            public static readonly GUIStyle searchFieldStyle = new GUIStyle(EditorStyles.toolbarSearchField)\n            {\n                margin = new RectOffset(5, 4, 4, 5)\n            };\n        }\n\n        internal PrefabFamilyPopup(GameObject target)\n        {\n            if (isOpen)\n                throw new InvalidOperationException(\"PrefabFamilyPopup is already open\");\n\n            this.m_Target = target;\n            m_TargetPath = AssetDatabase.GetAssetPath(target);\n            m_TargetGUID = AssetDatabase.AssetPathToGUID(m_TargetPath);\n\n            k_MinNameWidth = k_MinWindowWidth - (k_TitleWidth + k_SplitWidth + k_OverridesWidth);\n\n            m_SearchFilter = new SearchFilter()\n            {\n                classNames = new string[] { \"Prefab\" },\n                searchArea = SearchFilter.SearchArea.AllAssets\n            };\n            m_Debounce = Delayer.Debounce(_ =>\n            {\n                SearchFilterChanged();\n                editorWindow.Repaint();\n            });\n\n            Init();\n        }\n\n        public override void OnOpen()\n        {\n            base.OnOpen();\n            s_Open = true;\n\n            if (m_Debug)\n                Debug.Log(\"[PrefabFamilyPopup] Open\");\n        }\n\n        public override void OnClose()\n        {\n            base.OnClose();\n            s_Open = false;\n\n            EditorApplication.update -= CalculateOverrideCountsTimeSliced;\n            if (m_ListArea != null)\n                m_ListArea.OnDestroy();\n\n            if (m_Debug)\n                Debug.Log(\"[PrefabFamilyPopup] Close\");\n        }\n\n        bool isVariant { get { return PrefabUtility.GetCorrespondingObjectFromSource(m_Target) != null; } }\n\n        public static bool isOpen => s_Open;\n\n        public static string ObjectToGUID(Object asset)\n        {\n            Assert.IsNotNull(asset);\n\n            string guid;\n            AssetDatabase.TryGetGUIDAndLocalFileIdentifier(asset, out guid, out long _);\n            return guid;\n\n        }\n\n        AncestorItem[] GetAncestorItems()\n        {\n            if (!isVariant)\n                throw new InvalidOperationException(\"GetAncestorItems() should only be called for prefab variants\");\n\n            var items = new List<AncestorItem>();\n\n            var currentGUID = ObjectToGUID(m_Target);\n            while (!string.IsNullOrEmpty(currentGUID))\n            {\n                var assetPath = AssetDatabase.GUIDToAssetPath(currentGUID);\n                Assert.IsNotNull(assetPath);\n\n                items.Add(new AncestorItem { assetPath = assetPath, overrideCount = -1 });\n\n                var instanceID = AssetDatabase.GetMainAssetInstanceID(assetPath);\n                currentGUID = PrefabUtility.GetVariantParentGUID(instanceID);\n            }\n\n            return items.ToArray();\n        }\n\n\n        void Init()\n        {\n            if (isVariant)\n            {\n                m_NamesWidth = k_MinNameWidth;\n                m_AncestorItems = GetAncestorItems();\n                foreach (var item in m_AncestorItems)\n                {\n                    var prefabName = System.IO.Path.GetFileNameWithoutExtension(item.assetPath);\n                    m_NamesWidth = Mathf.Max(GUI.skin.label.CalcSize(EditorGUIUtility.TempContent(prefabName)).x + 40, m_NamesWidth);\n                }\n\n                m_OverridesCounter = new OverridesCounterForPrefabAssets(m_AncestorItems.Select(x => AssetDatabase.LoadAssetAtPath<GameObject>(x.assetPath)).ToList());\n                EditorApplication.update += CalculateOverrideCountsTimeSliced;\n\n                float scrollBarWidthOffset = numRows >= k_MaxTableRows ? k_ScrollbarWidth : 0;\n                m_MaxNameWidth = k_MaxWindowWidth - (k_TitleWidth + k_SplitWidth + k_OverridesWidth) - scrollBarWidthOffset;\n\n                float prevWidth = m_WindowWidth;\n                if (m_NamesWidth <= k_MinNameWidth)\n                    m_WindowWidth = k_MinWindowWidth;\n                else if (m_NamesWidth >= m_MaxNameWidth)\n                    m_WindowWidth = k_MaxWindowWidth;\n                else\n                    m_WindowWidth = k_TitleWidth + m_NamesWidth + k_SplitWidth + k_OverridesWidth;\n\n                m_OverridesX = m_WindowWidth - k_OverridesWidth - scrollBarWidthOffset;\n            }\n            else\n            {\n                // Just showing children area\n                var titleWidth = GUI.skin.label.CalcSize(EditorGUIUtility.TempContent(m_Target.name)).x + GUI.skin.label.CalcSize(Styles.titlePrefixLabel).x + 60;\n                m_WindowWidth = Mathf.Min(k_MaxWindowWidth, Mathf.Max(titleWidth, k_MinWindowWidth));\n            }\n\n            m_NoResultsX = (m_WindowWidth - EditorStyles.label.CalcSize(Styles.noResultsLabel).x) * 0.5f;\n        }\n\n        void CalculateOverrideCountsTimeSliced()\n        {\n            if (m_OverridesCounter.MoveNext())\n            {\n                if (m_OverridesCounter.changedCount)\n                {\n                    for (int i = 0; i < m_AncestorItems.Count(); ++i)\n                    {\n                        m_AncestorItems[i].overrideCount = m_OverridesCounter.GetCurrentOverrideCount(i);\n                    }\n\n                    editorWindow?.Repaint();\n                }\n            }\n            else\n            {\n                EditorApplication.update -= CalculateOverrideCountsTimeSliced;\n                if (m_Debug)\n                    Debug.Log(\"[PrefabFamilyPopup] Timesliced overrides calculation done\");\n            }\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            if (m_Target == null)\n            {\n                editorWindow.Close();\n                return Vector2.one;\n            }\n\n            var height = k_HeaderHeight;\n\n            if (isVariant)\n            {\n                // Horizontal scrollbar\n                if (m_NamesWidth > m_MaxNameWidth)\n                    height += k_ScrollbarHeight;\n\n                // Ancestors table\n                height += Mathf.Min(numRows, k_MaxTableRows) * k_EntryHeight + k_EntryHeight;\n            }\n\n            // Children list\n            height += k_EntryHeight;\n            if (!isVariant || m_DisplayChildren)\n                height += k_SearchHeight;\n\n            return new Vector2(m_WindowWidth, height);\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            if (m_Target == null)\n            {\n                editorWindow.Close();\n                return;\n            }\n\n            // Escape closes the window\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)\n            {\n                editorWindow.Close();\n                GUIUtility.ExitGUI();\n            }\n\n            DrawHeader();\n\n            float height = k_HeaderHeight;\n            if (isVariant)\n                height += DrawVariantHierarchy();\n            height += DrawChildrenLabel(height);\n\n            if (!isVariant || m_DisplayChildren)\n                DrawChildren(height);\n        }\n\n        void DrawHeader()\n        {\n            Rect headerRect = GUILayoutUtility.GetRect(20, m_WindowWidth, k_HeaderHeight, k_HeaderHeight);\n            EditorGUI.DrawRect(headerRect, Colors.headerBackground);\n\n            float labelSize = Styles.boldRightAligned.CalcSize(Styles.titlePrefixLabel).x;\n\n            Rect labelRect = new Rect(k_OffsetX, headerRect.y + k_Padding, labelSize, EditorGUIUtility.singleLineHeight);\n            Rect contentRect = new Rect(labelRect.x + labelRect.width + k_Padding, labelRect.y, m_WindowWidth, labelRect.height);\n\n            GUI.Label(labelRect, Styles.titlePrefixLabel, Styles.boldRightAligned);\n            DoObjectLabel(contentRect, AssetDatabase.GetAssetPath(m_Target), EditorStyles.boldLabel);\n\n            labelRect.y = labelRect.height + 2 * k_Padding;\n        }\n\n        float DrawVariantHierarchy()\n        {\n            // Draw table header\n            Rect entryRect = new Rect(0, k_HeaderHeight, m_WindowWidth, k_EntryHeight);\n            EditorGUI.DrawRect(entryRect, Colors.rowBackground(0));\n\n            var labelRect = entryRect;\n            labelRect.x = k_TitleWidth;\n            GUI.Label(labelRect, Styles.ancestorLabel, EditorStyles.miniLabel);\n\n            labelRect.x = m_OverridesX + k_Padding;\n            GUI.Label(labelRect, Styles.overridesLabel, EditorStyles.miniLabel);\n\n            float tableHeight = Mathf.Min(numRows, k_MaxTableRows) * k_EntryHeight + (m_NamesWidth > m_MaxNameWidth ? k_ScrollbarHeight : 0);\n            float realHeight = numRows * k_EntryHeight + (m_NamesWidth > m_MaxNameWidth ? k_ScrollbarHeight : 0);\n            var tableRect = new Rect(0, k_HeaderHeight + k_EntryHeight, m_WindowWidth - 1, tableHeight);\n\n            m_Scroll.y = GUI.BeginScrollView(tableRect, m_Scroll, new Rect(tableRect) { width = tableRect.width - k_ScrollbarWidth, height = realHeight }).y;\n            {\n                // Draw overrides and locks table\n                for (int i = 0; i < m_AncestorItems.Length; i++)\n                {\n                    entryRect.y = k_HeaderHeight + (i+1) * k_EntryHeight;\n                    EditorGUI.DrawRect(entryRect, Colors.rowBackground(i+1));\n\n                    DisplayOverridesAndLocks(entryRect, m_AncestorItems[m_AncestorItems.Length - 1 - i]);\n                }\n\n                var scrollRect = new Rect(k_TitleWidth, k_HeaderHeight + k_EntryHeight, Mathf.Min(m_NamesWidth, m_MaxNameWidth), numRows * k_EntryHeight);\n                m_Scroll.x = GUI.BeginScrollView(new Rect(scrollRect) { height = scrollRect.height + k_ScrollbarHeight }, m_Scroll, new Rect(scrollRect) { width = m_NamesWidth }).x;\n                {\n                    // Draw scrollable table\n                    entryRect.x = k_TitleWidth;\n                    for (int i = 0; i < m_AncestorItems.Length; i++)\n                    {\n                        entryRect.y = k_HeaderHeight + (i + 1) * k_EntryHeight;\n                        var assetPath = m_AncestorItems[m_AncestorItems.Length - 1 - i].assetPath;\n\n                        DoObjectLabel(entryRect, assetPath);\n                    }\n                }\n                GUI.EndScrollView();\n\n\n                // Draw selected label\n                labelRect.x = k_OffsetX;\n                labelRect.y = k_HeaderHeight + numRows * k_EntryHeight;\n                labelRect.width = k_TitleWidth - labelRect.x;\n                GUI.Label(labelRect, Styles.selectedLabel);\n\n                // Draw root label\n                if (labelRect.y != k_HeaderHeight + k_EntryHeight)\n                {\n                    labelRect.y = k_HeaderHeight + k_EntryHeight;\n                    GUI.Label(labelRect, Styles.rootLabel);\n                }\n\n                // Draw vertical splits\n                Rect splitBar = new Rect(m_OverridesX - k_SplitWidth, k_HeaderHeight, k_SplitWidth, (numRows + 1) * k_EntryHeight);\n                EditorGUI.DrawRect(splitBar, Colors.headerBackground);\n            }\n            GUI.EndScrollView();\n\n            float height = tableHeight + k_EntryHeight;\n            return height;\n        }\n\n        float DrawChildrenLabel(float yMin)\n        {\n            var labelRect = new Rect(k_OffsetX, yMin, 100, k_EntryHeight);\n            if (isVariant)\n                m_DisplayChildren = EditorGUI.Foldout(labelRect, m_DisplayChildren, Styles.childrenLabel, true);\n            else\n                EditorGUI.LabelField(labelRect, Styles.childrenLabel);\n\n            if (!isVariant || m_DisplayChildren)\n            {\n                if (m_ListArea == null)\n                    InitListArea();\n\n                labelRect = new Rect(labelRect.x + 70, labelRect.y + 2, k_SliderWidth, EditorGUI.kSingleLineHeight);\n                if (m_Results.Length != 0)\n                    EditorGUI.LabelField(labelRect, m_Results.Length.ToString(), Styles.boldNumber);\n\n                EditorGUI.BeginChangeCheck();\n                labelRect.x = m_WindowWidth - k_OffsetX - k_SliderWidth;\n                var newGridSize = (int)GUI.HorizontalSlider(labelRect, m_ListArea.gridSize, m_ListArea.minGridSize, m_ListArea.maxGridSize);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    m_ListArea.gridSize = m_SavedGridSize.value = newGridSize;\n                }\n            }\n\n            return k_EntryHeight;\n        }\n\n        void DrawChildren(float yMin)\n        {\n            int listKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard);\n\n            var backgroundRect = new Rect(0, yMin, m_WindowWidth, k_SearchHeight);\n            GUI.Label(backgroundRect, GUIContent.none, Styles.searchBackground);\n\n            EditorGUI.BeginChangeCheck();\n            var searchRect = new Rect(k_OffsetX + k_Padding, backgroundRect.y + k_Padding, m_WindowWidth - 2 * k_OffsetX - k_Padding, Styles.searchFieldStyle.fixedHeight);\n            m_SearchFilterString = EditorGUI.ToolbarSearchField(searchRect, m_SearchFilterString, false);\n            if (EditorGUI.EndChangeCheck())\n                m_Debounce.Execute();\n\n            if (m_Enumerator != null)\n                Search();\n\n            yMin = searchRect.height + (m_ListArea.gridSize < k_MinIconSize ? 11f : 0f);\n            var listRect = new Rect(k_Padding, searchRect.y + yMin, m_WindowWidth - 2 * k_Padding, k_SearchHeight - yMin - k_Padding);\n\n            m_ListArea.OnGUI(listRect, listKeyboardControlID);\n\n            if (m_Enumerator == null && m_Results.Length == 0)\n            {\n                var labelRect = new Rect(m_NoResultsX, backgroundRect.y + 69f, m_WindowWidth, EditorGUI.kSingleLineHeight);\n                EditorGUI.LabelField(backgroundRect, m_SearchFilter.nameFilter.Length == 0 ? Styles.noChildrenLabel : Styles.noResultsLabel, Styles.centered);\n            }\n        }\n\n        void InitListArea()\n        {\n            m_ListAreaState.m_GridSize = m_SavedGridSize;\n            m_ListArea = new ObjectListArea(m_ListAreaState, editorWindow, false)\n            {\n                allowDeselection = true,\n                allowMultiSelect = false,\n                allowRenaming = false,\n                allowBuiltinResources = true,\n            };\n\n            m_ListArea.itemSelectedCallback += (bool doubleClicked) =>\n            {\n                if (m_ListArea.GetSelection().Length == 0)\n                    return;\n                var selection = m_ListArea.GetSelection()[0];\n                if (doubleClicked)\n                {\n                    Selection.SetActiveObjectWithContext(EditorUtility.InstanceIDToObject(selection), null);\n                    Event.current.Use();\n                    editorWindow.Close();\n                    GUIUtility.ExitGUI();\n                }\n                else\n                {\n                    EditorGUIUtility.PingObject(selection);\n                    Event.current.Use();\n                }\n            };\n\n            SearchFilterChanged();\n        }\n\n        static IEnumerator<HierarchyProperty> FindInAllAssets(SearchFilter searchFilter)\n        {\n            var rootPaths = new List<string>();\n            rootPaths.Add(\"Assets\");\n            foreach (var package in PackageManagerUtilityInternal.GetAllVisiblePackages(false))\n            {\n                if (package.source == PackageManager.PackageSource.Local)\n                    rootPaths.Add(package.assetPath);\n            }\n\n            foreach (var rootPath in rootPaths)\n            {\n                var property = new HierarchyProperty(rootPath, false);\n                property.SetSearchFilter(searchFilter);\n                while (property.Next(null))\n                    yield return property;\n            }\n        }\n\n        void SearchFilterChanged()\n        {\n            m_SearchFilter.nameFilter = m_SearchFilterString;\n\n            var size = GetWindowSize();\n            var rect = new Rect(0, size.y - k_SearchHeight, size.x, k_SearchHeight);\n\n            m_ListArea.Init(rect, HierarchyType.Assets, new SearchFilter(), true, SearchService.SearchSessionOptions.Default);\n            m_Enumerator = FindInAllAssets(m_SearchFilter);\n            m_Results = new int[0];\n        }\n\n        void Search()\n        {\n            var newResults = new List<int>();\n\n            var maxAddCount = k_MaxSearchIterationPerFrame;\n            while (--maxAddCount >= 0)\n            {\n                if (!m_Enumerator.MoveNext())\n                {\n                    m_Enumerator = null;\n                    break;\n                }\n\n                var currentInstanceID = m_Enumerator.Current.instanceID;\n                var variantParentGUID = PrefabUtility.GetVariantParentGUID(currentInstanceID);\n                if (variantParentGUID == m_TargetGUID)\n                {\n                    newResults.Add(currentInstanceID);\n                }\n            }\n\n            int newCount = newResults.Count;\n            int i = m_Results.Length;\n            Array.Resize(ref m_Results, m_Results.Length + newCount);\n            for (var j = 0; j < newCount && i < m_Results.Length; ++j, ++i)\n                m_Results[i] = newResults[j];\n\n            m_ListArea.ShowObjectsInList(m_Results);\n        }\n\n        void DisplayOverridesAndLocks(Rect rect, AncestorItem item)\n        {\n            rect.x = m_OverridesX;\n            rect.width = k_OverridesWidth;\n            string text;\n            if (item.overrideCount == -1)\n                text = string.Empty;\n            else if (item.overrideCount == 0)\n                text = \"-\";\n            else if (item.overrideCount >= 10000)\n                text = \"+9999\";\n            else\n                text = item.overrideCount.ToString();\n            GUI.Label(rect, GUIContent.Temp(text, item.overrideCount.ToString()), Styles.centered);\n        }\n\n        void DoObjectLabel(Rect rect, string assetPath)\n        {\n            DoObjectLabel(rect, assetPath, GUI.skin.label);\n        }\n\n        void DoObjectLabel(Rect rect, string assetPath, GUIStyle style)\n        {\n            if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && rect.Contains(Event.current.mousePosition))\n            {\n                // One click shows where the referenced object is\n                if (Event.current.clickCount == 1)\n                {\n                    GUIUtility.keyboardControl = GUIUtility.GetControlID(FocusType.Keyboard);\n\n                    var instanceID = AssetDatabase.GetMainAssetInstanceID(assetPath);\n                    EditorGUIUtility.PingObject(instanceID);\n                    Event.current.Use();\n                }\n                // Double click changes selection to referenced object\n                else if (Event.current.clickCount == 2)\n                {\n                    var instanceID = AssetDatabase.GetMainAssetInstanceID(assetPath);\n                    Selection.activeInstanceID = instanceID;\n                    Event.current.Use();\n                    editorWindow.Close();\n                    GUIUtility.ExitGUI();\n                }\n            }\n\n            var icon = AssetDatabase.GetCachedIcon(assetPath);\n            var name = System.IO.Path.GetFileNameWithoutExtension(assetPath);\n            GUI.Label(rect, EditorGUIUtility.TempContent(name, icon), style);\n        }\n    }\n\n    [Serializable]\n    class PrefabAssetInfo\n    {\n        [SerializeField]\n        public Hash128 prefabFileHash;\n\n        [SerializeField]\n        public int overrideCount;\n    }\n\n    static class PrefabAssetStateCache\n    {\n        static StateCache<PrefabAssetInfo> s_StateCache = new StateCache<PrefabAssetInfo>(\"Library/StateCache/PrefabAssetInfo/\");\n\n        public static void SetState(string guid, PrefabAssetInfo obj)\n        {\n            var key = GetPrefabAssetIdentifier(guid);\n            s_StateCache.SetState(key, obj);\n        }\n\n        public static PrefabAssetInfo GetState(string guid)\n        {\n            var id = GetPrefabAssetIdentifier(guid);\n            var cachedPrefabAssetInfo = s_StateCache.GetState(id);\n            if (cachedPrefabAssetInfo == null)\n                return null; // not cached yet\n\n            var currentPrefabSourceFileHash = AssetDatabase.GetSourceAssetFileHash(guid);\n            if (currentPrefabSourceFileHash != cachedPrefabAssetInfo.prefabFileHash)\n                return null; // cache is out of sync\n\n            return cachedPrefabAssetInfo;\n        }\n        public static Hash128 GetPrefabAssetIdentifier(string guid)\n        {\n            if (string.IsNullOrEmpty(guid))\n                throw new ArgumentNullException(nameof(guid));\n\n            return Hash128.Compute(guid);\n        }\n    }\n\n    class OverridesCounterForPrefabAssets\n    {\n        List<GameObject> m_PrefabAssetRoots;\n        List<int> m_OverridesCount;\n        int m_CurrentAssetIndex;\n        int m_CurrentStep;\n        bool m_ChangedCount;\n\n        bool m_Debug = false;\n\n        public OverridesCounterForPrefabAssets(List<GameObject> prefabInstanceRoots)\n        {\n            m_PrefabAssetRoots = prefabInstanceRoots;\n            m_OverridesCount = new List<int>();\n            m_OverridesCount.AddRange(new int[prefabInstanceRoots.Count]);\n        }\n\n        public bool changedCount => m_ChangedCount;\n\n        public int GetCurrentOverrideCount(int assetIndex)\n        {\n            return m_OverridesCount[assetIndex];\n        }\n\n        bool IsDone()\n        {\n            return m_CurrentAssetIndex >= m_PrefabAssetRoots.Count -1; // No more prefabs to process (last prefab is the root prefab which does not have overrides)\n        }\n\n        // Returns true if overrides count changed during the update\n        public bool MoveNext()\n        {\n            if (IsDone())\n                return false;\n\n            var assetRoot = m_PrefabAssetRoots[m_CurrentAssetIndex];\n            var startCount = m_OverridesCount[m_CurrentAssetIndex];\n\n            switch (m_CurrentStep)\n            {\n                case 0:\n                    {\n                        // First check if we have cached overides count for the prefab\n                        var path = AssetDatabase.GetAssetPath(assetRoot);\n                        var guid = AssetDatabase.AssetPathToGUID(path);\n                        var cachedPrefabAssetInfo = PrefabAssetStateCache.GetState(guid);\n                        if (cachedPrefabAssetInfo != null)\n                        {\n                            m_OverridesCount[m_CurrentAssetIndex] = cachedPrefabAssetInfo.overrideCount;\n                            m_ChangedCount = true;\n                            m_CurrentAssetIndex++;\n                            if (m_Debug)\n                                Debug.Log($\"[OverridesCounterForPrefabAssets] Using cached overridecount {cachedPrefabAssetInfo.overrideCount} ({path})\");\n                            return true;\n                        }\n                    }\n                    break;\n                case 1:\n                    PropertyModification[] mods = PrefabUtility.GetPropertyModifications(assetRoot);\n                    foreach (PropertyModification mod in mods)\n                    {\n                        if (mod.target == null)\n                            continue;\n\n                        if (!PrefabUtility.IsDefaultOverride(mod))\n                            m_OverridesCount[m_CurrentAssetIndex]++;\n                    }\n                    break;\n                case 2:\n                    m_OverridesCount[m_CurrentAssetIndex] += PrefabOverridesUtility.GetAddedComponents(assetRoot).Count;\n                    break;\n                case 3:\n                    m_OverridesCount[m_CurrentAssetIndex] += PrefabOverridesUtility.GetRemovedComponents(assetRoot).Count;\n                    break;\n                case 4:\n                    m_OverridesCount[m_CurrentAssetIndex] += PrefabOverridesUtility.GetAddedGameObjects(assetRoot).Count;\n                    break;\n                default:\n                    {\n                        // Cache result\n                        var path = AssetDatabase.GetAssetPath(assetRoot);\n                        var guid = AssetDatabase.AssetPathToGUID(path);\n                        var prefabAssetInfo = new PrefabAssetInfo();\n                        prefabAssetInfo.overrideCount = m_OverridesCount[m_CurrentAssetIndex];\n                        prefabAssetInfo.prefabFileHash = AssetDatabase.GetSourceAssetFileHash(guid);\n                        PrefabAssetStateCache.SetState(guid, prefabAssetInfo);\n                        if (m_Debug)\n                            Debug.Log($\"[OverridesCounterForPrefabAssets] Set cached overridecount {prefabAssetInfo.overrideCount} for {path}\");\n\n                        // Move to next asset\n                        m_CurrentAssetIndex++;\n                        m_CurrentStep = 0;\n                    }\n                    break;\n            }\n\n            if (m_Debug)\n                Debug.Log($\"[OverridesCounterForPrefabAssets] Current asset index: {m_CurrentAssetIndex}, current step: {m_CurrentStep}\");\n\n            m_CurrentStep++;\n\n            // Simulate heavy calculation\n            if (m_Debug)\n                System.Threading.Thread.Sleep(500);\n\n            m_ChangedCount = m_OverridesCount[m_CurrentAssetIndex] != startCount;\n\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Prefabs/PrefabImporter.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing Object = UnityEngine.Object;\nusing System;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/AssetPipeline/PrefabImporter.h\")]\n    [ExcludeFromPreset]\n    internal class PrefabImporter : AssetImporter\n    {\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Prefabs/PrefabImporterEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor.AssetImporters;\nusing UnityEditor.SceneManagement;\nusing UnityEditor.UIElements;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(PrefabImporter))]\n    [CanEditMultipleObjects]\n    internal class PrefabImporterEditor : AssetImporterEditor\n    {\n        static class Styles\n        {\n            public static GUIContent missingScriptsHelpText = EditorGUIUtility.TrTextContent(\"Prefab has missing scripts. Open Prefab to fix the issue.\");\n            public static GUIContent missingSerializeReferenceHelpText = EditorGUIUtility.TrTextContent(\"Prefab has missing SerializeReference Types. Open Prefab to fix the issue. Changing the Prefab directly will cause those types to be lost.\");\n            public static GUIContent multiSelectionMissingScriptsHelpText = EditorGUIUtility.TrTextContent(\"Some of the selected Prefabs have missing scripts and needs to be fixed before editing them. Click to Open Prefab to fix the issue.\");\n            public static GUIContent savingFailedHelpText = EditorGUIUtility.TrTextContent(\"Saving has failed. Check the Console window to get more insight into what needs to be fixed on the Prefab Asset.\\n\\nOpen Prefab to fix the issue.\");\n            public static GUIContent variantOfText = EditorGUIUtility.TrTextContent(\"Variant Parent\");\n            public static string localizedTitleMultiplePrefabs = L10n.Tr(\"Prefab Assets\");\n            public static string localizedTitleSinglePrefab = L10n.Tr(\"Prefab Asset\");\n            public static GUIStyle openButtonStyle = \"AC Button\";\n            public static readonly GUIContent hierarchyIcon = EditorGUIUtility.IconContent(\"UnityEditor.SceneHierarchyWindow\");\n            public const int kHierarchyIconWidth = 44;\n        }\n\n        int m_HasMixedBaseVariants = -1;\n        double m_NextUpdate;\n        List<string> m_PrefabsWithMissingScript = new List<string>();\n        bool m_SavingHasFailed;\n        bool m_ContainsMissingSerializeReferenceType;\n\n        struct TrackedAsset\n        {\n            public GameObject asset;\n            public string guid;\n            public Hash128 hash;\n        }\n\n        readonly List<Component> m_TempComponentsResults = new List<Component>();\n        readonly List<TrackedAsset> m_DirtyPrefabAssets = new List<TrackedAsset>();\n        internal bool m_HasPendingChanges;\n\n        public override bool showImportedObject { get { return !hasMissingScripts; } }\n\n        internal override bool CanOpenMultipleObjects() { return false; }\n        internal override bool ShouldTryToMakeEditableOnOpen() { return false; }\n\n        bool isTextFieldCaretShowing\n        {\n            get { return EditorGUI.IsEditingTextField() && !EditorGUIUtility.textFieldHasSelection; }\n        }\n\n        internal bool readyToAutoSave\n        {\n            get { return !m_SavingHasFailed && !hasMissingScripts && GUIUtility.hotControl == 0 && !isTextFieldCaretShowing && !EditorApplication.isCompiling; }\n        }\n\n        bool hasMissingScripts\n        {\n            get { return m_PrefabsWithMissingScript.Count > 0; }\n        }\n\n        public override void OnEnable()\n        {\n            base.OnEnable();\n            ObjectChangeEvents.changesPublished += ObjectChangeEventPublished;\n        }\n\n        public override void OnDisable()\n        {\n            if (m_HasPendingChanges)\n            {\n                EditorApplication.update -= WaitToApplyChanges;\n                m_HasPendingChanges = false;\n                SaveDirtyPrefabAssets(false);\n            }\n\n            ObjectChangeEvents.changesPublished -= ObjectChangeEventPublished;\n            base.OnDisable();\n        }\n\n        private void ObjectChangeEventPublished(ref ObjectChangeEventStream stream)\n        {\n            if (m_HasPendingChanges)\n                return;\n\n            for (int i = 0; i < stream.length; ++i)\n            {\n                int instanceId = 0;\n                if (stream.GetEventType(i) == ObjectChangeKind.ChangeGameObjectOrComponentProperties)\n                {\n                    stream.GetChangeGameObjectOrComponentPropertiesEvent(i, out var changeGameObjectOrComponent);\n                    instanceId = changeGameObjectOrComponent.instanceId;\n                }\n                else if (stream.GetEventType(i) == ObjectChangeKind.ChangeGameObjectStructure)\n                {\n                    stream.GetChangeGameObjectStructureEvent(i, out var changeGameObject);\n                    instanceId = changeGameObject.instanceId;\n                }\n\n                if (instanceId == 0)\n                    continue;\n\n                var asset = EditorUtility.InstanceIDToObject(instanceId);\n                if (IsTargetAsset(asset))\n                {\n                    if (CanSave())\n                    {\n                        SaveDirtyPrefabAssets(true);\n                    }\n                    else\n                    {\n                        m_HasPendingChanges = true;\n                        EditorApplication.update += WaitToApplyChanges;\n                    }\n                    return;\n                }\n            }\n        }\n\n        protected override void Awake()\n        {\n            base.Awake();\n\n            m_ContainsMissingSerializeReferenceType = false;\n            foreach (var prefabAssetRoot in assetTargets)\n            {\n                if (PrefabUtility.HasInvalidComponent(prefabAssetRoot))\n                {\n                    m_PrefabsWithMissingScript.Add(AssetDatabase.GetAssetPath(prefabAssetRoot));\n                }\n\n                if (PrefabUtility.IsPartOfPrefabAsset(prefabAssetRoot) && PrefabUtility.HasManagedReferencesWithMissingTypes(prefabAssetRoot))\n                {\n                    m_ContainsMissingSerializeReferenceType = true;\n                }\n            }\n            m_PrefabsWithMissingScript.Sort();\n        }\n\n        void OnDestroy()\n        {\n            // Ensure to save unsaved changes (regardless of hotcontrol etc)\n            if (!m_SavingHasFailed && !hasMissingScripts)\n                SaveDirtyPrefabAssets(false);\n        }\n\n        /// <summary>\n        /// Determines whether auto-saving of the Prefab Asset is currently allowed.\n        /// Auto-saving is disabled if a UI field is focused or the CurveEditorWindow, ColorPicker or GradientPicker is visible.\n        /// </summary>\n        /// <returns>Returns true if auto-saving is allowed; otherwise, returns false.</returns>\n        internal bool CanSave() => !EditorFocusMonitor.AreBindableElementsSelected() &&\n            readyToAutoSave &&\n            !CurveEditorWindow.visible &&\n            !ColorPicker.visible &&\n            !GradientPicker.visible;\n\n        void WaitToApplyChanges()\n        {\n            var time = EditorApplication.timeSinceStartup;\n            if (time > m_NextUpdate)\n            {\n                m_NextUpdate = time + 0.2;\n\n                if (CanSave())\n                    SaveDirtyPrefabAssets(true);\n            }\n        }\n\n        // Internal for testing framework\n        internal void SaveDirtyPrefabAssets(bool reloadInspectors)\n        {\n            if (assetTargets == null)\n                return;\n\n            if (assetTarget == null)\n                return;\n\n            if (reloadInspectors && !CanSave())\n                Debug.LogWarning(\"SaveDirtyPrefabAssets should not be called when CanSave is false and reloading inspectors.\");\n\n            m_DirtyPrefabAssets.Clear();\n            foreach (var asset in assetTargets)\n            {\n                // The asset could have been deleted when this method is called from OnDestroy().\n                // E.g delete the selected prefab asset from the Project Browser.\n                if (asset == null)\n                    continue;\n\n                if (!EditorUtility.IsPersistent(asset))\n                    continue;\n\n                if (!(asset is GameObject))\n                    continue;\n\n                var rootGameObject = (GameObject)asset;\n                if (IsDirty(rootGameObject))\n                {\n                    string currentGuid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(rootGameObject));\n                    var changeTracking = new TrackedAsset()\n                    {\n                        asset = rootGameObject,\n                        guid = currentGuid,\n                        hash = AssetDatabase.GetSourceAssetFileHash(currentGuid)\n                    };\n                    m_DirtyPrefabAssets.Add(changeTracking);\n                }\n            }\n\n            if (m_DirtyPrefabAssets.Count > 0)\n            {\n                AssetDatabase.StartAssetEditing();\n                try\n                {\n                    foreach (var trackedAsset in m_DirtyPrefabAssets)\n                    {\n                        bool savedSuccesfully;\n                        PrefabUtility.SavePrefabAsset(trackedAsset.asset, out savedSuccesfully);\n                        if (!savedSuccesfully)\n                        {\n                            string title = L10n.Tr(\"Saving Failed\");\n                            string message = L10n.Tr(\"Check the Console window to get more insight into what needs to be fixed on the Prefab Asset.\\n\\nYou can open Prefab Mode to fix any issues on child GameObjects\");\n                            EditorUtility.DisplayDialog(title, message, L10n.Tr(\"OK\"));\n\n                            m_SavingHasFailed = true;\n                            break;\n                        }\n                    }\n                }\n                finally\n                {\n                    AssetDatabase.StopAssetEditing();\n\n                    if (reloadInspectors)\n                    {\n                        foreach (var trackedAsset in m_DirtyPrefabAssets)\n                        {\n                            if (AssetDatabase.GetSourceAssetFileHash(trackedAsset.guid) != trackedAsset.hash)\n                            {\n                                // We only call ForceReloadInspectors (and not ForceRebuildInspectors) to ensure local inspector state\n                                // is not destroyed, such as a foldout state maintained by an editor (case 1255013).\n                                // And we need to reload Prefab asset inspectors in order for the preview to be regenerated since the preview shows\n                                // an instantiated Prefab. E.g disable a MeshRenderer on a Prefab Asset and the mesh should be hidden in the preview.\n                                EditorUtility.ForceReloadInspectors();\n                                break;\n                            }\n                        }\n                    }\n\n                    // We reset the flag after the changes have been applied in order to avoid a new change being detected from the save operation.\n                    if (m_HasPendingChanges)\n                    {\n                        EditorApplication.update -= WaitToApplyChanges;\n                        m_HasPendingChanges = false;\n                    }\n                }\n            }\n        }\n\n        bool IsTargetAsset(Object obj)\n        {\n            if (assetTargets == null)\n                return false;\n\n            if (obj is Component component)\n                obj = component.gameObject;\n\n            foreach (var asset in assetTargets)\n            {\n                if (obj == asset)\n                    return true;\n            }\n            return false;\n        }\n\n        bool IsDirty(GameObject prefabAssetRoot)\n        {\n            if (prefabAssetRoot == null)\n                return false;\n\n            if (EditorUtility.IsDirty(prefabAssetRoot))\n                return true;\n\n            // For Prefab Variant Asset we need to also check if the instance handle is dirty\n            // since this happens when the list of removed component changes\n            var instanceHandle = PrefabUtility.GetPrefabInstanceHandle(prefabAssetRoot);\n            if (instanceHandle != null)\n                if (EditorUtility.IsDirty(instanceHandle))\n                    return true;\n\n            prefabAssetRoot.GetComponents(m_TempComponentsResults);\n            foreach (var component in m_TempComponentsResults)\n            {\n                if (EditorUtility.IsDirty(component))\n                    return true;\n\n                if (component is Renderer)\n                {\n                    Renderer r = component as Renderer;\n                    foreach (Material mat in r.sharedMaterials)\n                    {\n                        if (EditorUtility.IsDirty(mat) && AssetDatabase.IsSubAsset(mat))\n                            return AssetDatabase.GetAssetPath(mat) == AssetDatabase.GetAssetPath(prefabAssetRoot);\n                    }\n                }\n            }\n\n            return false;\n        }\n\n        void CacheHasMixedBaseVariants()\n        {\n            if (m_HasMixedBaseVariants >= 0)\n                return; // already cached\n\n            var firstVariantParent = PrefabUtility.GetCorrespondingObjectFromSource(assetTarget);\n            if (firstVariantParent == null)\n                return;\n\n            m_HasMixedBaseVariants = 0;\n            foreach (var t in assetTargets)\n            {\n                var variantParent = PrefabUtility.GetCorrespondingObjectFromSource(t);\n                if (variantParent != firstVariantParent)\n                {\n                    m_HasMixedBaseVariants = 1;\n                    break;\n                }\n            }\n        }\n\n        protected override bool needsApplyRevert => false;\n\n        internal override string targetTitle\n        {\n            get\n            {\n                if (assetTargets == null || assetTargets.Length == 1 || !m_AllowMultiObjectAccess)\n                    return assetTarget != null ? assetTarget.name + \" (\" + Styles.localizedTitleSinglePrefab + \")\" : Styles.localizedTitleSinglePrefab;\n                else\n                    return assetTargets.Length + \" \" + Styles.localizedTitleMultiplePrefabs;\n            }\n        }\n\n        void PrefabFamilyButton()\n        {\n            if (EditorGUILayout.DropdownButton(GUIContent.none, FocusType.Passive, GUILayout.MaxWidth(Styles.kHierarchyIconWidth)))\n            {\n                if (!PrefabFamilyPopup.isOpen)\n                    PopupWindow.Show(GUILayoutUtility.topLevel.GetLast(), new PrefabFamilyPopup((GameObject)assetTarget));\n                GUIUtility.ExitGUI();\n            }\n            var rect = new Rect(GUILayoutUtility.topLevel.GetLast());\n            rect.x += 6;\n            EditorGUI.LabelField(rect, Styles.hierarchyIcon);\n        }\n\n        internal override void OnHeaderControlsGUI()\n        {\n            GUILayout.FlexibleSpace();\n\n            using (new EditorGUI.DisabledScope(targets.Length != 1))\n            {\n                PrefabFamilyButton();\n            }\n\n            if (!ShouldHideOpenButton())\n            {\n                var assets = assetTargets;\n                ShowOpenButton(assets, assetTarget != null);\n            }\n\n            var variantParent = PrefabUtility.GetCorrespondingObjectFromSource(assetTarget) as GameObject;\n            if (variantParent != null)\n            {\n                // OnHeaderControlsGUI() is called within a BeginHorizontal() scope so to create a new line\n                // we end and start a new BeginHorizontal().\n                EditorGUILayout.EndHorizontal();\n                EditorGUILayout.BeginHorizontal();\n                using (new EditorGUI.DisabledScope(true))\n                {\n                    CacheHasMixedBaseVariants();\n                    EditorGUI.showMixedValue = m_HasMixedBaseVariants == 1;\n                    var oldLabelWidth = EditorGUIUtility.labelWidth;\n                    EditorGUIUtility.labelWidth = 90;\n                    EditorGUILayout.ObjectField(Styles.variantOfText, variantParent, typeof(GameObject), false);\n                    EditorGUIUtility.labelWidth = oldLabelWidth;\n                    EditorGUI.showMixedValue = false;\n                }\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            if (assetTarget is DefaultAsset)\n            {\n                return;\n            }\n\n            if (hasMissingScripts)\n            {\n                if (assetTargets.Length > 1)\n                {\n                    // List all assets that have missing scripts (but only if we have a multi-selection)\n                    GUILayout.Space(5);\n                    EditorGUILayout.HelpBox(Styles.multiSelectionMissingScriptsHelpText.text, MessageType.Warning, true);\n                    using (new EditorGUILayout.HorizontalScope())\n                    {\n                        GUILayout.Space(10);\n\n                        using (new EditorGUILayout.VerticalScope())\n                        {\n                            foreach (var prefabAssetPath in m_PrefabsWithMissingScript)\n                            {\n                                if (GUILayout.Button(prefabAssetPath, EditorStyles.label))\n                                {\n                                    PrefabStageUtility.OpenPrefab(prefabAssetPath);\n                                }\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    EditorGUILayout.HelpBox(Styles.missingScriptsHelpText.text, MessageType.Warning, true);\n                }\n            }\n            else if (m_SavingHasFailed)\n            {\n                EditorGUILayout.HelpBox(Styles.savingFailedHelpText.text, MessageType.Warning, true);\n            }\n            else if (m_ContainsMissingSerializeReferenceType)\n            {\n                EditorGUILayout.HelpBox(Styles.missingSerializeReferenceHelpText.text, MessageType.Warning, true);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Prefabs/PrefabInstanceChangedListener.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [InitializeOnLoad]\n    class PrefabInstanceChangedListener\n    {\n        static PrefabInstanceChangedListener()\n        {\n            ObjectChangeEvents.changesPublished += OnObjectChanged;\n        }\n\n        private static void OnObjectChanged(ref ObjectChangeEventStream stream)\n        {\n            for (int i = 0; i < stream.length; ++i)\n            {\n                var eventType = stream.GetEventType(i);\n\n                switch (eventType)\n                {\n                    case ObjectChangeKind.ChangeGameObjectOrComponentProperties:\n                    {\n                        stream.GetChangeGameObjectOrComponentPropertiesEvent(i, out var e);\n\n                        OnGameObjectChanged(TryGetGameObject(e.instanceId));\n                    }\n                    break;\n\n                    case ObjectChangeKind.ChangeGameObjectParent:\n                    {\n                        stream.GetChangeGameObjectParentEvent(i, out var e);\n\n                        if (e.previousParentInstanceId != 0)\n                            OnGameObjectChanged(TryGetGameObject(e.previousParentInstanceId));\n\n                        if (e.newParentInstanceId != 0)\n                            OnGameObjectChanged(TryGetGameObject(e.newParentInstanceId));\n                    }\n                    break;\n\n                    case ObjectChangeKind.ChangeGameObjectStructure:\n                    {\n                        stream.GetChangeGameObjectStructureEvent(i, out var e);\n\n                        OnGameObjectChanged(TryGetGameObject(e.instanceId));\n                    }\n                    break;\n\n                    case ObjectChangeKind.ChangeGameObjectStructureHierarchy:\n                    {\n                        stream.GetChangeGameObjectStructureHierarchyEvent(i, out var e);\n\n                        OnGameObjectChanged(TryGetGameObject(e.instanceId));\n                    }\n                    break;\n\n                    case ObjectChangeKind.UpdatePrefabInstances:\n                    {\n                        stream.GetUpdatePrefabInstancesEvent(i, out var e);\n\n                        for (int index = 0; index < e.instanceIds.Length; index++)\n                            OnGameObjectChanged(TryGetGameObject(e.instanceIds[index]));\n                    }\n                    break;\n\n                    case ObjectChangeKind.CreateGameObjectHierarchy:\n                    {\n                        stream.GetCreateGameObjectHierarchyEvent(i, out var e);\n\n                        GameObject go = TryGetGameObject(e.instanceId);\n                        if (go != null && go.transform.parent)\n                        {\n                            go = go.transform.parent.gameObject;\n\n                            OnGameObjectChanged(go);\n                        }\n                    }\n                    break;\n\n                    case ObjectChangeKind.DestroyGameObjectHierarchy:\n                    {\n                        stream.GetDestroyGameObjectHierarchyEvent(i, out var e);\n\n                        GameObject goParent = TryGetGameObject(e.parentInstanceId);\n                        if (goParent != null)\n                            OnGameObjectChanged(goParent);\n                    }\n                    break;\n                }\n            }\n        }\n\n        private static GameObject TryGetGameObject(int instanceId)\n        {\n            Component comp = EditorUtility.InstanceIDToObject(instanceId) as Component;\n            if (comp)\n                return comp.gameObject;\n\n            return EditorUtility.InstanceIDToObject(instanceId) as GameObject;\n        }\n\n        private static void OnGameObjectChanged(GameObject go)\n        {\n            if (!go)\n                return;\n\n            PrefabUtility.ClearPrefabInstanceNonDefaultOverridesCache(go);\n            PrefabUtility.ClearPrefabInstanceUnusedOverridesCache(go);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Prefabs/PrefabOverrides/PrefabOverride.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Assertions;\nusing UnityObject = UnityEngine.Object;\n\n\nnamespace UnityEditor.SceneManagement\n{\n    public abstract class PrefabOverride\n    {\n        public abstract void Apply(string prefabAssetPath, InteractionMode mode);\n        public abstract void Revert(InteractionMode mode);\n\n        public void Apply()\n        {\n            var asset = GetAssetObject();\n            Apply(AssetDatabase.GetAssetPath(asset), InteractionMode.UserAction);\n        }\n\n        public void Apply(string prefabAssetPath)\n        {\n            Apply(prefabAssetPath, InteractionMode.UserAction);\n        }\n\n        public void Apply(InteractionMode mode)\n        {\n            var asset = GetAssetObject();\n            Apply(AssetDatabase.GetAssetPath(asset), mode);\n        }\n\n        public void Revert()\n        {\n            Revert(InteractionMode.UserAction);\n        }\n\n        protected UnityObject FindApplyTargetAssetObject(string prefabAssetPath)\n        {\n            var assetObject = GetAssetObject();\n            while (assetObject != null)\n            {\n                string assetPath = AssetDatabase.GetAssetPath(assetObject);\n                if (assetPath == prefabAssetPath)\n                    return assetObject;\n                assetObject = PrefabUtility.GetCorrespondingObjectFromSource(assetObject);\n            }\n            return null;\n        }\n\n        public abstract UnityObject GetAssetObject();\n\n        // Returns the object the override relates to.\n        // For ObjectOverride, it's the object on the instance that has the overrides.\n        // For AddedComponent, it's the added component on the instance.\n        // For AddedGameObject, it's the added GameObject on the instance.\n        // For RemovedComponent, it's the component on the Prefab Asset corresponding to the removed component on the instance.\n        // For RemovedGameObject, it's the GameObject on the Prefab Asset corresponding to the removed GameObject on the instance.\n        internal abstract UnityObject GetObject();\n\n        internal void HandleApplyMenuItems(GenericMenu menu, GenericMenu.MenuFunction2 applyAction)\n        {\n            bool isObjectOverride = this is ObjectOverride;\n            Object obj = isObjectOverride ? GetObject() : GetAssetObject();\n            bool isObjectOverrideAllDefaultOverridesComparedToOriginalSource =\n                isObjectOverride ? PrefabUtility.IsObjectOverrideAllDefaultOverridesComparedToOriginalSource(obj) : false;\n\n            bool isRemovedGameObjectOverride = this is RemovedGameObject;\n            bool isRemovedNestedPrefabRoot = isRemovedGameObjectOverride && PrefabUtility.IsAssetANestedPrefabRoot(obj);\n\n            PrefabUtility.HandleApplyMenuItems(\n                null,\n                obj,\n                (menuItemContent, sourceObject, instanceOrAssetObject) =>\n                {\n                    string prefabAssetPath = AssetDatabase.GetAssetPath(sourceObject);\n                    GameObject rootObject = PrefabUtility.GetRootGameObject(sourceObject);\n                    bool isPersistent = EditorUtility.IsPersistent(instanceOrAssetObject);\n\n                    if (!PrefabUtility.IsPartOfPrefabThatCanBeAppliedTo(rootObject) || (!isPersistent && !PrefabUtility.HasApplicableObjectOverridesForTarget(instanceOrAssetObject, sourceObject, false)))\n                        menu.AddDisabledItem(menuItemContent);\n                    else\n                        menu.AddItem(menuItemContent, false, applyAction, prefabAssetPath);\n                },\n                isObjectOverrideAllDefaultOverridesComparedToOriginalSource,\n                !isObjectOverride,\n                !isRemovedNestedPrefabRoot);\n        }\n    }\n\n    public class ObjectOverride : PrefabOverride\n    {\n        public UnityObject instanceObject { get; set; }\n        public PrefabOverride coupledOverride { get; set; }\n\n        public override void Apply(string prefabAssetPath, InteractionMode mode)\n        {\n            PrefabUtility.ApplyObjectOverride(\n                instanceObject,\n                prefabAssetPath,\n                mode);\n        }\n\n        public override void Revert(InteractionMode mode)\n        {\n            PrefabUtility.RevertObjectOverride(\n                instanceObject,\n                mode);\n        }\n\n        public override UnityObject GetAssetObject()\n        {\n            return PrefabUtility.GetCorrespondingObjectFromSource(instanceObject);\n        }\n\n        internal override UnityObject GetObject()\n        {\n            return instanceObject;\n        }\n    }\n\n    public class AddedComponent : PrefabOverride\n    {\n        public Component instanceComponent { get; set; }\n\n        public override void Apply(string prefabAssetPath, InteractionMode mode)\n        {\n            PrefabUtility.ApplyAddedComponent(\n                instanceComponent,\n                prefabAssetPath,\n                mode);\n        }\n\n        public override void Revert(InteractionMode mode)\n        {\n            PrefabUtility.RevertAddedComponent(\n                instanceComponent,\n                mode);\n        }\n\n        public override UnityObject GetAssetObject()\n        {\n            return PrefabUtility.GetCorrespondingObjectFromSource(instanceComponent.gameObject);\n        }\n\n        internal override UnityObject GetObject()\n        {\n            return instanceComponent;\n        }\n    }\n\n    public class RemovedComponent : PrefabOverride\n    {\n        public GameObject containingInstanceGameObject { get; set; }\n        public Component assetComponent { get; set; }\n\n        public override void Apply(string prefabAssetPath, InteractionMode mode)\n        {\n            PrefabUtility.ApplyRemovedComponent(\n                containingInstanceGameObject,\n                (Component)FindApplyTargetAssetObject(prefabAssetPath),\n                mode);\n        }\n\n        public override void Revert(InteractionMode mode)\n        {\n            PrefabUtility.RevertRemovedComponent(\n                containingInstanceGameObject,\n                assetComponent,\n                mode);\n        }\n\n        public override UnityObject GetAssetObject()\n        {\n            return assetComponent;\n        }\n\n        internal override UnityObject GetObject()\n        {\n            return assetComponent;\n        }\n    }\n\n    public class AddedGameObject : PrefabOverride\n    {\n        public GameObject instanceGameObject { get; set; }\n        public int siblingIndex { get; set; }\n\n        public override void Apply(string prefabAssetPath, InteractionMode mode)\n        {\n            PrefabUtility.ApplyAddedGameObject(\n                instanceGameObject,\n                prefabAssetPath,\n                mode);\n        }\n\n        public override void Revert(InteractionMode mode)\n        {\n            PrefabUtility.RevertAddedGameObject(\n                instanceGameObject,\n                mode);\n        }\n\n        public override UnityObject GetAssetObject()\n        {\n            GameObject parent = instanceGameObject.transform.parent.gameObject;\n            return PrefabUtility.GetCorrespondingObjectFromSource(parent);\n        }\n\n        internal override UnityObject GetObject()\n        {\n            return instanceGameObject;\n        }\n    }\n\n    public class RemovedGameObject : PrefabOverride\n    {\n        public GameObject parentOfRemovedGameObjectInInstance { get; set; }\n        public GameObject assetGameObject { get; set; }\n\n        public override void Apply(string prefabAssetPath, InteractionMode mode)\n        {\n            PrefabUtility.ApplyRemovedGameObject(\n                parentOfRemovedGameObjectInInstance,\n                (GameObject)FindApplyTargetAssetObject(prefabAssetPath),\n                mode);\n        }\n\n        public override void Revert(InteractionMode mode)\n        {\n            PrefabUtility.RevertRemovedGameObject(\n                parentOfRemovedGameObjectInInstance,\n                assetGameObject,\n                mode);\n        }\n\n        public override UnityObject GetAssetObject()\n        {\n            return assetGameObject;\n        }\n\n        internal override UnityObject GetObject()\n        {\n            return assetGameObject;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesTreeView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.SceneManagement;\nusing UnityEditor.UIElements;\nusing UnityEngine.UIElements;\nusing Object = UnityEngine.Object;\nusing TreeView = UnityEditor.IMGUI.Controls.TreeView<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewUtility = UnityEditor.IMGUI.Controls.TreeViewUtility<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    class PrefabOverridesTreeView : TreeView\n    {\n        PrefabOverrides m_AllModifications;\n        bool m_Debug = false;\n        string m_PrefabAssetPath { get; set; }\n        GameObject m_PrefabInstanceRoot { get; set; }\n        GameObject m_PrefabAssetRoot { get; set; }\n        int m_LastShownPreviewWindowRowID = -1;\n        PrefabOverridesWindow m_Window;\n\n        enum ToggleValue { FALSE, TRUE, MIXED }\n        enum ItemType { PREFAB_OBJECT, ADDED_OBJECT, REMOVED_OBJECT }\n\n        class PrefabOverridesTreeViewItem : TreeViewItem\n        {\n            public PrefabOverridesTreeViewItem(int id, int depth, string displayName) : base(id, depth, displayName)\n            {\n            }\n\n            public PrefabOverride singleModification;\n            public Texture overlayIcon;\n\n            public ToggleValue included { get; set; }\n            public ItemType type\n            {\n                get { return m_Type; }\n                set\n                {\n                    m_Type = value;\n\n                    overlayIcon = null;\n                    if (m_Type == ItemType.ADDED_OBJECT)\n                        overlayIcon = EditorGUIUtility.IconContent(\"PrefabOverlayAdded Icon\").image;\n                    else if (m_Type == ItemType.REMOVED_OBJECT)\n                        overlayIcon = EditorGUIUtility.IconContent(\"PrefabOverlayRemoved Icon\").image;\n                }\n            }\n            ItemType m_Type;\n\n            public Object obj\n            {\n                get { return m_Obj; }\n                set\n                {\n                    m_Obj = value;\n                    icon = (m_Obj is GameObject) ? PrefabUtility.GetIconForGameObject((GameObject)m_Obj) : AssetPreview.GetMiniThumbnail(m_Obj);\n                }\n            }\n            Object m_Obj;\n\n            public string propertyPath { get; set; }\n        }\n\n        // Represents all possible modifications to a Prefab instance.\n        class PrefabOverrides\n        {\n            List<ObjectOverride> m_ObjectOverrides = new List<ObjectOverride>();\n            List<AddedComponent> m_AddedComponents = new List<AddedComponent>();\n            List<RemovedComponent> m_RemovedComponents = new List<RemovedComponent>();\n            List<AddedGameObject> m_AddedGameObjects = new List<AddedGameObject>();\n            List<RemovedGameObject> m_RemovedGameObjects = new List<RemovedGameObject>();\n\n            public List<ObjectOverride> objectOverrides { get { return m_ObjectOverrides; } set { m_ObjectOverrides = value; } }\n            public List<AddedComponent> addedComponents { get { return m_AddedComponents; } set { m_AddedComponents = value; } }\n            public List<RemovedComponent> removedComponents { get { return m_RemovedComponents; } set { m_RemovedComponents = value; } }\n            public List<AddedGameObject> addedGameObjects { get { return m_AddedGameObjects; } set { m_AddedGameObjects = value; } }\n            public List<RemovedGameObject> removedGameObjects { get { return m_RemovedGameObjects; } set { m_RemovedGameObjects = value; } }\n        }\n\n        static PrefabOverrides GetPrefabOverrides(GameObject prefabInstance, bool includeDefaultOverrides = false)\n        {\n            if (!PrefabUtility.IsPartOfNonAssetPrefabInstance(prefabInstance))\n            {\n                Debug.LogError(\"GeneratePrefabOverrides should only be called with GameObjects that are part of a prefab\");\n                return new PrefabOverrides();\n            }\n\n            var mods = new PrefabOverrides();\n            mods.objectOverrides = PrefabOverridesUtility.GetObjectOverrides(prefabInstance, includeDefaultOverrides);\n            mods.addedComponents = PrefabOverridesUtility.GetAddedComponents(prefabInstance);\n            mods.removedComponents = PrefabOverridesUtility.GetRemovedComponents(prefabInstance);\n            mods.addedGameObjects = PrefabOverridesUtility.GetAddedGameObjects(prefabInstance);\n            mods.removedGameObjects = PrefabOverridesUtility.GetRemovedGameObjects(prefabInstance);\n            return mods;\n        }\n\n        public bool hasModifications { get; private set; }\n\n        public bool hasApplicableModifications { get; private set; }\n\n        public bool IsValidTargetPrefabInstance()\n        {\n            if (m_PrefabInstanceRoot == null)\n                return false;\n\n            return PrefabUtility.GetPrefabInstanceStatus(m_PrefabInstanceRoot) == PrefabInstanceStatus.Connected;\n        }\n\n        public PrefabOverridesTreeView(GameObject selectedGameObject, TreeViewState state, PrefabOverridesWindow window) : base(state)\n        {\n            m_SelectedGameObject = selectedGameObject;\n            m_Window = window;\n            rowHeight = 18f;\n            enableItemHovering = true;\n        }\n\n        public void SetApplyTarget(GameObject prefabInstanceRoot, GameObject prefabAssetRoot, string prefabAssetPath)\n        {\n            m_PrefabInstanceRoot = prefabInstanceRoot;\n            m_PrefabAssetRoot = prefabAssetRoot;\n            m_PrefabAssetPath = prefabAssetPath;\n            Reload();\n            ExpandAll();\n            EnableAllItems(true);\n        }\n\n        public void CullNonExistingItemsFromSelection()\n        {\n            for (int i = state.selectedIDs.Count - 1; i >= 0; i--)\n            {\n                if (TreeViewUtility.FindItem(state.selectedIDs[i], rootItem) == null)\n                    state.selectedIDs.RemoveAt(i);\n            }\n\n            if (state.selectedIDs.Count != 1 && PopupWindowWithoutFocus.IsVisible())\n                PopupWindowWithoutFocus.Hide();\n        }\n\n        void BuildPrefabOverridesPerObject(out Dictionary<int, PrefabOverrides> instanceIDToPrefabOverridesMap)\n        {\n            instanceIDToPrefabOverridesMap = new Dictionary<int, PrefabOverrides>();\n\n            foreach (var modifiedObject in m_AllModifications.objectOverrides)\n            {\n                int instanceID = 0;\n                if (modifiedObject.instanceObject is GameObject)\n                    instanceID = modifiedObject.instanceObject.GetInstanceID();\n                else if (modifiedObject.instanceObject is Component)\n                    instanceID = ((Component)modifiedObject.instanceObject).gameObject.GetInstanceID();\n\n                if (instanceID != 0)\n                {\n                    PrefabOverrides modificationsForObject = GetPrefabOverridesForObject(instanceID, instanceIDToPrefabOverridesMap);\n                    modificationsForObject.objectOverrides.Add(modifiedObject);\n                }\n            }\n\n            foreach (var addedGameObject in m_AllModifications.addedGameObjects)\n            {\n                int instanceID = addedGameObject.instanceGameObject.GetInstanceID();\n                PrefabOverrides modificationsForObject = GetPrefabOverridesForObject(instanceID, instanceIDToPrefabOverridesMap);\n                modificationsForObject.addedGameObjects.Add(addedGameObject);\n            }\n\n            foreach (var removedGameObject in m_AllModifications.removedGameObjects)\n            {\n                int instanceID = removedGameObject.parentOfRemovedGameObjectInInstance.gameObject.GetInstanceID();\n                PrefabOverrides modificationsForObject = GetPrefabOverridesForObject(instanceID, instanceIDToPrefabOverridesMap);\n                modificationsForObject.removedGameObjects.Add(removedGameObject);\n            }\n\n            foreach (var addedComponent in m_AllModifications.addedComponents)\n            {\n                // This is possible if there's a component with a missing script.\n                if (addedComponent.instanceComponent == null)\n                    continue;\n                int instanceID = addedComponent.instanceComponent.gameObject.GetInstanceID();\n                PrefabOverrides modificationsForObject = GetPrefabOverridesForObject(instanceID, instanceIDToPrefabOverridesMap);\n                modificationsForObject.addedComponents.Add(addedComponent);\n            }\n\n            foreach (var removedComponent in m_AllModifications.removedComponents)\n            {\n                // This is possible if there's a component with a missing script.\n                if (removedComponent.assetComponent == null)\n                    continue;\n                int instanceID = removedComponent.containingInstanceGameObject.gameObject.GetInstanceID();\n                PrefabOverrides modificationsForObject = GetPrefabOverridesForObject(instanceID, instanceIDToPrefabOverridesMap);\n                modificationsForObject.removedComponents.Add(removedComponent);\n            }\n        }\n\n        internal void ComparisonPopupClosed(Object instanceObject, bool ownerNeedsRefresh)\n        {\n            if(ownerNeedsRefresh)\n                ReloadOverridesDisplay();\n\n            if (instanceObject != null && instanceObject is GameObject)\n                SyncTreeViewItemNameForGameObject((GameObject)instanceObject);\n        }\n\n        void SyncTreeViewItemNameForGameObject(GameObject gameObject)\n        {\n            if (gameObject == null)\n                return;\n\n            foreach (var item in GetRows())\n            {\n                var poItem = item as PrefabOverridesTreeViewItem;\n                if (poItem != null && poItem.obj == gameObject)\n                {\n                    item.displayName = poItem.obj.name;\n                    Repaint();\n                    return;\n                }\n            }\n        }\n\n        protected override TreeViewItem BuildRoot()\n        {\n            Debug.Assert(m_PrefabInstanceRoot != null, \"We should always have a valid apply target\");\n\n            // Inner prefab asset root.\n            m_AllModifications = GetPrefabOverrides(m_PrefabInstanceRoot, false);\n\n            Dictionary<int, PrefabOverrides> instanceIDToPrefabOverridesMap;\n            BuildPrefabOverridesPerObject(out instanceIDToPrefabOverridesMap);\n\n            var hiddenRoot = new TreeViewItem { id = 0, depth = -1, displayName = \"Hidden Root\" };\n            var idSequence = new IdSequence();\n\n            hasApplicableModifications = false;\n            hasModifications = AddTreeViewItemRecursive(hiddenRoot, m_PrefabInstanceRoot, instanceIDToPrefabOverridesMap, idSequence);\n            if (!hasModifications)\n                hiddenRoot.AddChild(new TreeViewItem { id = 1, depth = 0, displayName = \"No Overrides\" });\n            else\n            {\n                bool CanAnyPropertiesBeApplied()\n                {\n                    if (m_AllModifications.addedComponents.Count != 0 || m_AllModifications.removedComponents.Count != 0 || m_AllModifications.addedGameObjects.Count != 0 || m_AllModifications.removedGameObjects.Count != 0)\n                        return true;\n\n                    foreach (var objectOverride in m_AllModifications.objectOverrides)\n                    {\n                        if (PrefabUtility.HasApplicableObjectOverrides(objectOverride.instanceObject, false))\n                            return true;\n                    }\n\n                    return false;\n                }\n\n                hasApplicableModifications = CanAnyPropertiesBeApplied();\n            }\n\n            if (m_Debug)\n                AddDebugItems(hiddenRoot, idSequence);\n\n            return hiddenRoot;\n        }\n\n        void AddDebugItems(TreeViewItem hiddenRoot, IdSequence idSequence)\n        {\n            var debugItem = new TreeViewItem(idSequence.get(), 0, \"<Debug raw list of modifications>\");\n            foreach (var mod in m_AllModifications.addedGameObjects)\n                debugItem.AddChild(new TreeViewItem(idSequence.get(), debugItem.depth + 1, mod.instanceGameObject.name + \" (Added GameObject)\"));\n            foreach (var mod in m_AllModifications.removedGameObjects)\n                debugItem.AddChild(new TreeViewItem(idSequence.get(), debugItem.depth + 1, mod.assetGameObject.name + \" (Removed GameObject)\"));\n            foreach (var mod in m_AllModifications.addedComponents)\n                debugItem.AddChild(new TreeViewItem(idSequence.get(), debugItem.depth + 1, mod.instanceComponent.GetType() + \" (Added Component)\"));\n            foreach (var mod in m_AllModifications.removedComponents)\n                debugItem.AddChild(new TreeViewItem(idSequence.get(), debugItem.depth + 1, mod.assetComponent.GetType() + \" (Removed Component)\"));\n\n            hiddenRoot.AddChild(new TreeViewItem()); // spacer\n            hiddenRoot.AddChild(debugItem);\n        }\n\n        // Returns true if input gameobject or any of its descendants have modifications, otherwise returns false.\n        bool AddTreeViewItemRecursive(TreeViewItem parentItem, GameObject gameObject, Dictionary<int, PrefabOverrides> prefabOverrideMap, IdSequence idSequence)\n        {\n            var gameObjectItem = new PrefabOverridesTreeViewItem\n                (\n                gameObject.GetInstanceID(),\n                parentItem.depth + 1,\n                gameObject.name\n                );\n            gameObjectItem.obj = gameObject;\n\n            // We don't know yet if this item should be added to the parent.\n            bool shouldAddGameObjectItemToParent = false;\n\n            PrefabOverrides objectModifications;\n            prefabOverrideMap.TryGetValue(gameObject.GetInstanceID(), out objectModifications);\n            if (objectModifications != null)\n            {\n                // Added GameObject - note that this earlies out!\n                AddedGameObject addedGameObjectData = objectModifications.addedGameObjects.Find(x => x.instanceGameObject == gameObject);\n                if (addedGameObjectData != null)\n                {\n                    gameObjectItem.singleModification = addedGameObjectData;\n                    gameObjectItem.type = ItemType.ADDED_OBJECT;\n\n                    parentItem.AddChild(gameObjectItem);\n                    return true;\n                }\n                else\n                {\n                    // Modified GameObject\n                    ObjectOverride modifiedGameObjectData = objectModifications.objectOverrides.Find(x => x.instanceObject == gameObject);\n                    if (modifiedGameObjectData != null)\n                    {\n                        gameObjectItem.singleModification = modifiedGameObjectData;\n                        gameObjectItem.type = ItemType.PREFAB_OBJECT;\n                        shouldAddGameObjectItemToParent = true;\n                    }\n                }\n\n                // Added components and component modifications\n                foreach (var component in gameObject.GetComponents(typeof(Component)))\n                {\n                    // GetComponents will return Missing Script components as null, we will skip them here to prevent NullReferenceExceptions. (case 1197599)\n                    if (component == null)\n                        continue;\n\n                    // Skip coupled components (they are merged into the display of their owning component)\n                    if (component.IsCoupledComponent())\n                        continue;\n\n                    var componentItem = new PrefabOverridesTreeViewItem\n                        (\n                        component.GetInstanceID(),\n                        gameObjectItem.depth + 1,\n                        ObjectNames.GetInspectorTitle(component)\n                        );\n                    componentItem.obj = component;\n\n                    AddedComponent addedComponentData = objectModifications.addedComponents.Find(x => x.instanceComponent == component);\n                    if (addedComponentData != null)\n                    {\n                        // Skip coupled components (they are merged into the display of their owning component)\n                        if (addedComponentData.instanceComponent.IsCoupledComponent())\n                            continue;\n\n                        componentItem.singleModification = addedComponentData;\n                        componentItem.type = ItemType.ADDED_OBJECT;\n                        gameObjectItem.AddChild(componentItem);\n                        shouldAddGameObjectItemToParent = true;\n                    }\n                    else\n                    {\n                        var coupledComponent = component.GetCoupledComponent();\n                        ObjectOverride modifiedObjectData = objectModifications.objectOverrides.Find(x => x.instanceObject == component);\n                        ObjectOverride modifiedCoupledObjectData = (coupledComponent != null) ? objectModifications.objectOverrides.Find(x => x.instanceObject == coupledComponent) : null;\n\n                        if (modifiedObjectData != null || modifiedCoupledObjectData != null)\n                        {\n                            // If only the coupled component has modifications, create an\n                            // ObjectOverride object for the main component since it doesn't exist yet.\n                            if (modifiedObjectData == null)\n                                modifiedObjectData = new ObjectOverride() { instanceObject = component };\n\n                            modifiedObjectData.coupledOverride = modifiedCoupledObjectData;\n\n                            componentItem.singleModification = modifiedObjectData;\n                            componentItem.type = ItemType.PREFAB_OBJECT;\n                            gameObjectItem.AddChild(componentItem);\n                            shouldAddGameObjectItemToParent = true;\n                        }\n                    }\n                }\n\n                // Removed components\n                foreach (var removedComponent in objectModifications.removedComponents)\n                {\n                    // Skip coupled components (they are merged into the display of their owning component)\n                    if (removedComponent.assetComponent.IsCoupledComponent())\n                        continue;\n\n                    var removedComponentItem = new PrefabOverridesTreeViewItem\n                        (\n                        idSequence.get(),\n                        gameObjectItem.depth + 1,\n                        ObjectNames.GetInspectorTitle(removedComponent.assetComponent)\n                        );\n                    removedComponentItem.obj = removedComponent.assetComponent;\n                    removedComponentItem.singleModification = removedComponent;\n                    removedComponentItem.type = ItemType.REMOVED_OBJECT;\n                    gameObjectItem.AddChild(removedComponentItem);\n                    shouldAddGameObjectItemToParent = true;\n                }\n            }\n\n            // Recurse into children\n            foreach (Transform childTransform in gameObject.transform)\n            {\n                var childGameObject = childTransform.gameObject;\n                shouldAddGameObjectItemToParent |= AddTreeViewItemRecursive(gameObjectItem, childGameObject, prefabOverrideMap, idSequence);\n            }\n\n            if (objectModifications != null)\n            {\n                // Removed GameObjects\n                foreach (var removedGameObject in objectModifications.removedGameObjects)\n                {\n                    string objectName = removedGameObject.assetGameObject.name;\n                    var instanceModifications = PrefabUtility.GetPropertyModifications(gameObject);\n                    foreach (var mod in instanceModifications)\n                    {\n                        if (mod.target == removedGameObject.assetGameObject && mod.propertyPath == \"m_Name\")\n                        {\n                            objectName = mod.value;\n                            break;\n                        }\n                    }\n\n                    var removedGameObjectItem = new PrefabOverridesTreeViewItem\n                        (\n                        idSequence.get(),\n                        gameObjectItem.depth + 1,\n                        objectName\n                        );\n                    removedGameObjectItem.obj = removedGameObject.assetGameObject;\n                    removedGameObjectItem.singleModification = removedGameObject;\n                    removedGameObjectItem.type = ItemType.REMOVED_OBJECT;\n                    gameObjectItem.AddChild(removedGameObjectItem);\n                    shouldAddGameObjectItemToParent = true;\n                }\n            }\n\n            if (shouldAddGameObjectItemToParent)\n            {\n                parentItem.AddChild(gameObjectItem);\n                if (maxDepthItem == null || gameObjectItem.depth > maxDepthItem.depth)\n                    maxDepthItem = gameObjectItem;\n\n                return true;\n            }\n\n            return false;\n        }\n\n        static PrefabOverrides GetPrefabOverridesForObject(int instanceID, Dictionary<int, PrefabOverrides> map)\n        {\n            PrefabOverrides modificationsForObject;\n            if (!map.TryGetValue(instanceID, out modificationsForObject))\n            {\n                modificationsForObject = new PrefabOverrides();\n                map[instanceID] = modificationsForObject;\n            }\n            return modificationsForObject;\n        }\n\n        public void EnableAllItems(bool enable)\n        {\n            var topItem = rootItem.children[0] as PrefabOverridesTreeViewItem;\n            if (topItem != null)\n                UpdateChildrenIncludedState(topItem, enable);\n        }\n\n        static void UpdateChildrenIncludedState(PrefabOverridesTreeViewItem item, bool v)\n        {\n            item.included = v ? ToggleValue.TRUE : ToggleValue.FALSE;\n            if (item.hasChildren)\n            {\n                foreach (var child in item.children)\n                {\n                    UpdateChildrenIncludedState(child as PrefabOverridesTreeViewItem, v);\n                }\n            }\n        }\n\n        protected override void RowGUI(RowGUIArgs args)\n        {\n            baseIndent = 4f;\n\n            var item = args.item as PrefabOverridesTreeViewItem;\n            if (item == null)\n                return;\n\n            // Grey out items that does not have overrides\n            using (new EditorGUI.DisabledScope(item.singleModification == null))\n            {\n                base.RowGUI(args);\n            }\n\n            // Draw overlay icon.\n            if (Event.current.type == EventType.Repaint)\n            {\n                if (item.overlayIcon != null)\n                {\n                    Rect rect = GetRowRect(args.row);\n                    rect.xMin += GetContentIndent(args.item);\n                    rect.width = 16;\n                    GUI.DrawTexture(rect, item.overlayIcon, ScaleMode.ScaleToFit);\n                }\n            }\n        }\n\n        internal void ReloadOverridesDisplay()\n        {\n            // Driven properties are ignored when collecting overrides.\n            // Properties that affect which properties are driven may have changed\n            // due to an apply or revert since we last reloaded the overrides display.\n            // Execute a layout call to get driven properties into a stable state\n            // before collecting overrides.\n            Canvas.ForceUpdateCanvases();\n\n            if (m_Window != null)\n                m_Window.RefreshStatus();\n        }\n\n        protected override void SelectionChanged(IList<int> selectedIds)\n        {\n            DoPreviewPopup();\n        }\n\n        protected override void SingleClickedItem(int id)\n        {\n            // Ensure preview is shown when clicking on an already selected item\n            // (the preview might have been closed).\n            DoPreviewPopup();\n        }\n\n        void DoPreviewPopup()\n        {\n            if (state.selectedIDs.Count != 1)\n            {\n                PopupWindowWithoutFocus.Hide();\n                return;\n            }\n\n            var item = FindItem(state.selectedIDs[0], rootItem) as PrefabOverridesTreeViewItem;\n\n            if (item == null || item.obj == null)\n                return;\n\n            if (PopupWindowWithoutFocus.IsVisible())\n            {\n                if (item.id == m_LastShownPreviewWindowRowID)\n                    return;\n            }\n\n            int row = FindRowOfItem(item);\n            if (row == -1)\n                return;\n\n            Rect buttonRect = GetRowRect(row);\n            buttonRect.width = EditorGUIUtility.currentViewWidth;\n            Object rowObject = item.obj;\n\n            Object instance, source;\n            if (item.type == ItemType.REMOVED_OBJECT)\n            {\n                instance = null;\n                source = rowObject;\n            }\n            else if (item.type == ItemType.ADDED_OBJECT)\n            {\n                instance = rowObject;\n                source = null;\n            }\n            else\n            {\n                instance = rowObject;\n                source = PrefabUtility.GetCorrespondingObjectFromSource(rowObject);\n            }\n\n            m_LastShownPreviewWindowRowID = item.id;\n            PopupWindowWithoutFocus.Show(\n                buttonRect,\n                new ComparisonViewPopup(source, instance, item.singleModification, this),\n                new[] { PopupLocation.Right, PopupLocation.Left, PopupLocation.Below });\n        }\n\n        public GameObject selectedGameObject\n        {\n            get { return m_SelectedGameObject; }\n        }\n\n        GameObject m_SelectedGameObject;\n\n        public float maxItemWidth { get { return maxDepthItem != null ? GetContentIndent(maxDepthItem) + k_FixedContentWidth : 0; } }\n\n        const float k_FixedContentWidth = 150f;\n        TreeViewItem maxDepthItem { get; set; }\n\n        struct ChangedModification\n        {\n            public Object target { get; set; }\n            public string propertyPath { get; set; }\n        }\n\n        public PrefabOverride FindOverride(int itemId)\n        {\n            var item = FindItem(itemId, rootItem) as PrefabOverridesTreeViewItem;\n            if (item == null)\n                return null;\n            return item.singleModification;\n        }\n\n        class IdSequence\n        {\n            public int get() { return m_NextId++; }\n            int m_NextId = 1;\n        }\n\n        class ComparisonViewPopup : PopupWindowContent\n        {\n            readonly PrefabOverridesTreeView m_Owner;\n            readonly PrefabOverride m_Modification;\n            readonly Object m_Source;\n            readonly Object m_Instance;\n            readonly bool m_Unappliable;\n\n            bool m_OwnerNeedsRefresh;\n\n            static class Styles\n            {\n                public const string ussPath = \"StyleSheets/Prefab/ComparisonViewPopup.uss\";\n                public const string rootClass = \"unity-prefab-compare__root\";\n                public const string dualViewClass = \"unity-prefab-compare-dual\";\n                public const string headerClass = \"unity-prefab-compare__header\";\n                public const string cellClass = \"unity-prefab-compare__cell\";\n                public const string contentClass = \"unity-prefab-compare__content\";\n                public const string rightClass = \"unity-prefab-compare__right\";\n                public const string headerButtonClass = \"unity-prefab-compare__header-buttons\";\n\n                public static GUIStyle headerGroupStyle = new GUIStyle();\n                public static GUIContent sourceContent = EditorGUIUtility.TrTextContent(\"Prefab Source\");\n                public static GUIContent instanceContent = EditorGUIUtility.TrTextContent(\"Override\");\n                public static GUIContent removedContent = EditorGUIUtility.TrTextContent(\"Removed\");\n                public static GUIContent addedContent = EditorGUIUtility.TrTextContent(\"Added\");\n                public static GUIContent noModificationsContent = EditorGUIUtility.TrTextContent(\"No Overrides\");\n                public static GUIContent applyContent = EditorGUIUtility.TrTextContent(\"Apply\", \"Apply overrides on this object.\");\n                public static GUIContent revertContent = EditorGUIUtility.TrTextContent(\"Revert\", \"Revert overrides on this object.\");\n\n                static Styles()\n                {\n                    headerGroupStyle.padding = new RectOffset(0, 0, 3, 3);\n                }\n            }\n\n            public ComparisonViewPopup(Object source, Object instance, PrefabOverride modification, PrefabOverridesTreeView owner)\n            {\n                m_Owner = owner;\n                m_Source = source;\n                m_Instance = instance;\n                m_Modification = modification;\n                if (modification != null)\n                    m_Unappliable = !PrefabUtility.IsPartOfPrefabThatCanBeAppliedTo(modification.GetAssetObject());\n                else\n                    m_Unappliable = false;\n\n                if (modification is ObjectOverride)\n                    Undo.postprocessModifications += RecheckOverrideStatus;\n            }\n\n            public override void OnClose()\n            {\n                Undo.postprocessModifications -= RecheckOverrideStatus;\n                m_Owner.ComparisonPopupClosed(m_Instance, m_OwnerNeedsRefresh);\n                base.OnClose();\n            }\n\n            UndoPropertyModification[] RecheckOverrideStatus(UndoPropertyModification[] modifications)\n            {\n                if (m_Instance == null || !PrefabUtility.HasObjectOverride(m_Instance))\n                {\n                    // Delay update and close since if there's multiple undo events, RecheckOverrideStatus\n                    // gets called for each, and we only want to recheck after the last one.\n                    // This fixes an issue where the tree view would still show a component with no more\n                    // modifications on it, if it was a component with a coupled component.\n                    EditorApplication.tick -= UpdateAndCloseOnNextTick;\n                    EditorApplication.tick += UpdateAndCloseOnNextTick;\n                }\n                return modifications;\n            }\n\n            void UpdateAndCloseOnNextTick()\n            {\n                EditorApplication.tick -= UpdateAndCloseOnNextTick;\n                UpdateAndClose();\n            }\n\n            public override VisualElement CreateGUI()\n            {\n                var root = new VisualElement();\n                root.AddStyleSheetPath(Styles.ussPath);\n                root.AddToClassList(Styles.rootClass);\n                if (m_Modification != null && m_Source != null && m_Instance != null)\n                    root.AddToClassList(Styles.dualViewClass);\n\n                root.Add(CreateHeader());\n\n                if (m_Modification != null)\n                    root.Add(CreateComparisonView());\n\n                return root;\n            }\n\n            VisualElement CreateHeader()\n            {\n                var container = new VisualElement();\n                container.AddToClassList(Styles.headerClass);\n\n                if (m_Modification == null)\n                {\n                    container.Add(CreateHeaderCell(Styles.noModificationsContent.text));\n                    return container;\n                }\n\n                if (m_Source != null && m_Instance != null)\n                {\n                    var sourceHeader = CreateHeaderCell(Styles.sourceContent.text);\n                    var instanceHeader = CreateHeaderCell(Styles.instanceContent.text);\n                    instanceHeader.AddToClassList(Styles.rightClass);\n                    instanceHeader.Add(CreateHeaderButtons());\n\n                    container.Add(sourceHeader);\n                    container.Add(instanceHeader);\n                }\n                else\n                {\n                    string headerContentText = m_Source != null ? Styles.removedContent.text : Styles.addedContent.text;\n                    var header = CreateHeaderCell(headerContentText);\n                    header.Add(CreateHeaderButtons());\n                    container.Add(header);\n                }\n\n                return container;\n            }\n\n            VisualElement CreateHeaderButtons()\n            {\n                var container = new IMGUIContainer(DrawRevertApplyButtons);\n                container.AddToClassList(Styles.headerButtonClass);\n                return container;\n            }\n\n            VisualElement CreateComparisonView()\n            {\n                var comparisonView = new ScrollView\n                {\n                    mode = ScrollViewMode.Vertical,\n                    verticalScrollerVisibility = ScrollerVisibility.Auto\n                };\n                comparisonView.RegisterCallback<SerializedObjectChangeEvent>(OnObjectChanged);\n\n                if (m_Source != null && m_Instance != null)\n                    comparisonView.Add(CreateDualObjectView());\n                else\n                    comparisonView.Add(CreateSingleObjectView());\n\n                return comparisonView;\n            }\n\n            void OnObjectChanged(SerializedObjectChangeEvent obj)\n            {\n                m_OwnerNeedsRefresh = true;\n            }\n\n            VisualElement CreateSingleObjectView()\n            {\n                if (m_Source != null)\n                {\n                    var inspector = CreateObjectInspector(m_Source, EditorGUIUtility.ComparisonViewMode.Original);\n                    inspector.enabledSelf = false;\n                    return inspector;\n                }\n                else\n                {\n                    var inspector = CreateObjectInspector(m_Instance, EditorGUIUtility.ComparisonViewMode.Original);\n                    inspector.enabledSelf = true;\n                    return inspector;\n                }\n            }\n\n            VisualElement CreateDualObjectView()\n            {\n                var sourceInspector = CreateObjectInspector(m_Source, EditorGUIUtility.ComparisonViewMode.Original);\n                var instanceInspector = CreateObjectInspector(m_Instance, EditorGUIUtility.ComparisonViewMode.Modified);\n\n                sourceInspector.enabledSelf = false;\n                sourceInspector.AddToClassList(Styles.cellClass);\n                instanceInspector.AddToClassList(Styles.cellClass);\n                instanceInspector.AddToClassList(Styles.rightClass);\n\n                var container = new VisualElement();\n                container.AddToClassList(Styles.contentClass);\n                container.Add(sourceInspector);\n                container.Add(instanceInspector);\n                return container;\n            }\n\n            void DrawRevertApplyButtons()\n            {\n                GUILayout.BeginHorizontal(Styles.headerGroupStyle);\n                GUILayout.FlexibleSpace();\n\n                if (GUILayout.Button(Styles.revertContent, EditorStyles.miniButton, GUILayout.Width(55)))\n                {\n                    m_Modification.Revert();\n                    UpdateAndClose();\n                    GUIUtility.ExitGUI();\n                }\n\n                using (new EditorGUI.DisabledScope(m_Unappliable))\n                {\n                    Rect applyRect = GUILayoutUtility.GetRect(GUIContent.none, \"MiniPulldown\", GUILayout.Width(55));\n                    if (EditorGUI.DropdownButton(applyRect, Styles.applyContent, FocusType.Passive))\n                    {\n                        GenericMenu menu = new GenericMenu();\n                        m_Modification.HandleApplyMenuItems(menu, Apply);\n                        menu.DropDown(applyRect);\n                    }\n                }\n\n                GUILayout.EndHorizontal();\n            }\n\n            void Apply(object prefabAssetPathObject)\n            {\n                string prefabAssetPath = (string)prefabAssetPathObject;\n                if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(prefabAssetPath, PrefabUtility.SaveVerb.Apply))\n                    return;\n                m_Modification.Apply(prefabAssetPath);\n                EditorUtility.ForceRebuildInspectors(); // handles applying RemovedComponents\n\n                UpdateAndClose();\n            }\n\n            void UpdateAndClose()\n            {\n                m_OwnerNeedsRefresh = true;\n                editorWindow?.Close();\n            }\n\n            static VisualElement CreateObjectInspector(Object obj, EditorGUIUtility.ComparisonViewMode viewMode)\n            {\n                var container = new VisualElement();\n                var inspector = new InspectorElement(obj) { comparisonViewMode = viewMode };\n                if (inspector.boundObject != null)\n                    inspector.TrackSerializedObjectValue(inspector.boundObject);\n\n                container.Add(new IMGUIContainer(() => DrawObjectHeader(inspector.editor, viewMode)));\n                container.Add(inspector);\n                return container;\n            }\n\n            static VisualElement CreateHeaderCell(string label)\n            {\n                var headerCell = new VisualElement();\n                headerCell.AddToClassList(Styles.cellClass);\n                headerCell.Add(new Label(label));\n                return headerCell;\n            }\n\n            static void DrawObjectHeader(Editor editor, EditorGUIUtility.ComparisonViewMode viewMode)\n            {\n                if (editor == null) return;\n                if (editor.target is GameObject)\n                    editor.DrawHeader();\n                else\n                {\n                    EditorGUIUtility.comparisonViewMode = viewMode;\n                    EditorGUIUtility.hierarchyMode = true;\n                    EditorGUILayout.InspectorTitlebar(true, editor);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor.SceneManagement\n{\n    internal class PrefabOverridesUtility\n    {\n        static List<Component> s_ComponentList = new List<Component>();\n        static List<Component> s_AssetComponentList = new List<Component>();\n\n        static void ThrowExceptionIfNullOrNotPartOfPrefabInstance(GameObject prefabInstance)\n        {\n            if (prefabInstance == null)\n                throw new ArgumentNullException(nameof(prefabInstance));\n\n            if (!PrefabUtility.IsPartOfPrefabInstance(prefabInstance))\n                throw new ArgumentException(\"Provided GameObject is not a Prefab instance\");\n        }\n\n        public static List<ObjectOverride> GetObjectOverrides(GameObject prefabInstance, bool includeDefaultOverrides = false)\n        {\n            ThrowExceptionIfNullOrNotPartOfPrefabInstance(prefabInstance);\n\n            var prefabInstanceRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(prefabInstance);\n\n            // From root of instance traverse all child go and detect any GameObjects or components\n            // that are not part of that source prefab objects component list (these must be added)\n            TransformVisitor transformVisitor = new TransformVisitor();\n            var modifiedObjects = new List<ObjectOverride>();\n\n            Func<Transform, object, bool> checkMethod;\n            if (includeDefaultOverrides)\n                checkMethod = CheckForModifiedObjectsIncludingDefaultOverrides;\n            else\n                checkMethod = CheckForModifiedObjectsExcludingDefaultOverrides;\n            transformVisitor.VisitPrefabInstanceTransforms(prefabInstanceRoot.transform, checkMethod, modifiedObjects);\n            return modifiedObjects;\n        }\n\n        static bool CheckForModifiedObjectsIncludingDefaultOverrides(Transform transform, object userData)\n        {\n            var modifiedObjects = (List<ObjectOverride>)userData;\n            return CheckForModifiedObjects(transform, modifiedObjects, true);\n        }\n\n        static bool CheckForModifiedObjectsExcludingDefaultOverrides(Transform transform, object userData)\n        {\n            var modifiedObjects = (List<ObjectOverride>)userData;\n            return CheckForModifiedObjects(transform, modifiedObjects, false);\n        }\n\n        static bool CheckForModifiedObjects(Transform transform, List<ObjectOverride> modifiedObjects, bool includeDefaultOverrides)\n        {\n            GameObject gameObject = transform.gameObject;\n            if (PrefabUtility.HasObjectOverride(gameObject, includeDefaultOverrides))\n                modifiedObjects.Add(new ObjectOverride() { instanceObject = gameObject });\n\n            s_ComponentList.Clear();\n            gameObject.GetComponents(s_ComponentList);\n            foreach (var component in s_ComponentList)\n            {\n                // This is possible if there's a component with a missing script.\n                if (component == null)\n                    continue;\n\n                if (PrefabUtility.HasObjectOverride(component, includeDefaultOverrides))\n                    modifiedObjects.Add(new ObjectOverride() { instanceObject = component });\n            }\n\n            // Clear the list to avoid holding static references to components\n            s_ComponentList.Clear();\n\n            return true;\n        }\n\n        public static List<AddedComponent> GetAddedComponents(GameObject prefabInstance)\n        {\n            ThrowExceptionIfNullOrNotPartOfPrefabInstance(prefabInstance);\n\n            var prefabInstanceRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(prefabInstance);\n\n            // From root of instance traverse all child go and detect any components that are not part of that source prefab objects component list (these must be added)\n            TransformVisitor transformVisitor = new TransformVisitor();\n            var addedComponents = new List<AddedComponent>();\n            transformVisitor.VisitPrefabInstanceTransforms(prefabInstanceRoot.transform, CheckForAddedComponents, addedComponents);\n            return addedComponents;\n        }\n\n        // Return value indicates if caller should traverse children of the the input transform or not\n        static bool CheckForAddedComponents(Transform transform, object userData)\n        {\n            try\n            {\n                s_ComponentList.Clear();\n                transform.gameObject.GetComponents(s_ComponentList);\n\n                var assetGameObject = PrefabUtility.GetCorrespondingObjectFromSource(transform.gameObject);\n                if (assetGameObject == null)\n                    return false; // If this is an added normal GameObject then we do not record added components\n\n                foreach (var component in s_ComponentList)\n                {\n                    // This is possible if there's a component with a missing script.\n                    if (component == null)\n                        continue;\n\n                    // Don't list DontSave objects as they won't get applied or reverted.\n                    if ((component.hideFlags & HideFlags.DontSaveInEditor) != 0)\n                        continue;\n\n                    bool isAddedObject = PrefabUtility.GetCorrespondingObjectFromSource(component) == null;\n                    if (isAddedObject)\n                    {\n                        var addedComponents = (List<AddedComponent>)userData;\n                        addedComponents.Add(new AddedComponent() {instanceComponent = component});\n                    }\n                }\n\n                return true;\n            }\n            finally\n            {\n                s_ComponentList.Clear();\n            }\n        }\n\n        public static List<RemovedComponent> GetRemovedComponents(GameObject prefabInstance)\n        {\n            ThrowExceptionIfNullOrNotPartOfPrefabInstance(prefabInstance);\n\n            var prefabInstanceRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(prefabInstance);\n\n            // From root of asset traverse all children and detect any Components that are not present on the instance object (these must be deleted)\n            var removedComponents = new List<RemovedComponent>();\n            TransformVisitor transformVisitor = new TransformVisitor();\n            transformVisitor.VisitPrefabInstanceTransforms(prefabInstanceRoot.transform, CheckForRemovedComponents, removedComponents);\n            return removedComponents;\n        }\n\n        public static List<RemovedComponent> GetRemovedComponentsForSingleGameObject(GameObject prefabInstance)\n        {\n            ThrowExceptionIfNullOrNotPartOfPrefabInstance(prefabInstance);\n\n            var removedComponents = new List<RemovedComponent>();\n            CheckForRemovedComponents(prefabInstance.transform, removedComponents);\n            return removedComponents;\n        }\n\n        // Return value indicates if caller should traverse children of the the input transform or not\n        static bool CheckForRemovedComponents(Transform transform, object userData)\n        {\n            try\n            {\n                GameObject instanceGameObject = transform.gameObject;\n                GameObject assetGameObject = PrefabUtility.GetCorrespondingObjectFromSource(instanceGameObject);\n                if (assetGameObject == null)\n                    return false; // skip added GameObjects (non of its components will be in the asset)\n\n                // Compare asset with instance component lists\n                s_ComponentList.Clear();\n                instanceGameObject.GetComponents(s_ComponentList);\n\n                s_AssetComponentList.Clear();\n                assetGameObject.GetComponents(s_AssetComponentList);\n\n                // Find asset objects that no instance objects are referencing\n                foreach (var assetComponent in s_AssetComponentList)\n                {\n                    // This is possible if there's a component with a missing script.\n                    if (assetComponent == null)\n                        continue;\n\n                    bool found = false;\n                    foreach (var instanceComponent in s_ComponentList)\n                    {\n                        // This is possible if there's a component with a missing script.\n                        if (instanceComponent == null)\n                            continue;\n\n                        if (PrefabUtility.GetCorrespondingObjectFromSource(instanceComponent) == assetComponent)\n                        {\n                            found = true;\n                            break;\n                        }\n                    }\n\n                    if (!found)\n                    {\n                        List<RemovedComponent> removedComponents = (List<RemovedComponent>)userData;\n                        removedComponents.Add(new RemovedComponent() {assetComponent = assetComponent, containingInstanceGameObject = instanceGameObject});\n                    }\n                }\n            }\n            finally\n            {\n                // Clear the lists to avoid holding static references to components\n                s_ComponentList.Clear();\n                s_AssetComponentList.Clear();\n            }\n\n            return true;\n        }\n\n        public static List<RemovedGameObject> GetRemovedGameObjects(GameObject prefabInstance)\n        {\n            ThrowExceptionIfNullOrNotPartOfPrefabInstance(prefabInstance);\n\n            var prefabInstanceRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(prefabInstance);\n\n            // From root of asset traverse all children and detect any GameObjects that are not present on the instance object (these must be deleted)\n            var removedGameObjects = new List<RemovedGameObject>();\n            TransformVisitor transformVisitor = new TransformVisitor();\n            transformVisitor.VisitPrefabInstanceTransforms(prefabInstanceRoot.transform, CheckForRemovedGameObjects, removedGameObjects);\n            return removedGameObjects;\n        }\n\n        // Return value indicates if caller should traverse children of the the input transform or not\n        static bool CheckForRemovedGameObjects(Transform transform, object userData)\n        {\n            // Look for removed children GameObjects of instanceGameObject\n            GameObject instanceGameObject = transform.gameObject;\n            GameObject assetGameObject = PrefabUtility.GetCorrespondingObjectFromSource(instanceGameObject);\n            if (assetGameObject == null)\n                return false; // skip added GameObjects\n\n            Transform assetTransform = assetGameObject.GetComponent<Transform>();\n            foreach (Transform assetChild in assetTransform)\n            {\n                bool found = false;\n                foreach (Transform instanceChild in transform)\n                {\n                    if (PrefabUtility.GetCorrespondingObjectFromSource(instanceChild.gameObject) == assetChild.gameObject)\n                    {\n                        found = true;\n                        break;\n                    }\n                }\n\n                if (!found)\n                {\n                    List<RemovedGameObject> removedGameObjects = (List<RemovedGameObject>)userData;\n                    removedGameObjects.Add(new RemovedGameObject() { parentOfRemovedGameObjectInInstance = instanceGameObject, assetGameObject = assetChild.gameObject });\n                }\n            }\n            return true;\n        }\n\n        internal class AddedGameObjectUserData\n        {\n            public List<AddedGameObject> addedGameObjects;\n            public GameObject contextGameObject;\n        }\n\n        public static List<AddedGameObject> GetAddedGameObjects(GameObject prefabInstance)\n        {\n            ThrowExceptionIfNullOrNotPartOfPrefabInstance(prefabInstance);\n\n            var prefabInstanceRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(prefabInstance);\n\n            // From root instance traverse all children and detect any GameObjects that are not a prefab gameobject (these must be added)\n            TransformVisitor transformVisitor = new TransformVisitor();\n            var addedGameObjects = new List<AddedGameObject>();\n\n            transformVisitor.VisitAndConditionallyEnterChildren(\n                prefabInstanceRoot.transform,\n                CheckForAddedGameObjectAndIfSoAddItAndReturnFalse,\n                new AddedGameObjectUserData() { addedGameObjects = addedGameObjects, contextGameObject = prefabInstanceRoot });\n            return addedGameObjects;\n        }\n\n        static bool CheckForAddedGameObjectAndIfSoAddItAndReturnFalse(Transform transform, object userData)\n        {\n            // Don't list DontSave objects or their children as they won't get applied or reverted.\n            if ((transform.gameObject.hideFlags & HideFlags.DontSaveInEditor) != 0)\n                return false;\n\n            var addedGameObjectUserData = (AddedGameObjectUserData)userData;\n            if (IsAddedGameObject(addedGameObjectUserData.contextGameObject, transform.gameObject))\n            {\n                var addedGameObjects = addedGameObjectUserData.addedGameObjects;\n                addedGameObjects.Add(new AddedGameObject() { instanceGameObject = transform.gameObject, siblingIndex = transform.GetSiblingIndex() });\n                return false;\n            }\n            return true;\n        }\n\n        internal static bool IsAddedGameObject(GameObject contextGameObject, GameObject gameObject)\n        {\n            // The context GameObject itself can never have status as being added to itself.\n            if (gameObject == contextGameObject)\n                return false;\n\n            if (!PrefabUtility.IsAddedGameObjectOverride(gameObject))\n                return false;\n\n            // We now know that the GameObject is added to *some* Prefab,\n            // but is it added to the Prefab in question?\n            // It is if its parent belong to the same Prefab as the context GameObject.\n            return (\n                PrefabUtility.GetCorrespondingObjectFromSource(gameObject.transform.parent).root ==\n                PrefabUtility.GetCorrespondingObjectFromSource(contextGameObject.transform).root);\n        }\n\n        internal static void CheckForInvalidComponent(Transform transform, object userData)\n        {\n            try\n            {\n                GameObject instanceGameObject = transform.gameObject;\n                var GOList = (List<GameObject>)userData;\n                if (!EditorUtility.IsPersistent(instanceGameObject))\n                {\n                    s_ComponentList.Clear();\n                    instanceGameObject.GetComponents(s_ComponentList);\n\n                    foreach (var component in s_ComponentList)\n                    {\n                        if (component == null)\n                        {\n                            GOList.Add(instanceGameObject);\n                            return;\n                        }\n                    }\n\n                    var assetGameObject = PrefabUtility.GetCorrespondingObjectFromSource(instanceGameObject);\n                    if (assetGameObject == null)\n                        return;\n\n                    s_AssetComponentList.Clear();\n                    assetGameObject.GetComponents(s_AssetComponentList);\n\n                    foreach (var assetComponent in s_AssetComponentList)\n                    {\n                        if (assetComponent == null)\n                        {\n                            GOList.Add(instanceGameObject);\n                            return;\n                        }\n                    }\n                }\n                else\n                {\n                    s_AssetComponentList.Clear();\n                    instanceGameObject.GetComponents(s_AssetComponentList);\n\n                    foreach (var assetComponent in s_AssetComponentList)\n                    {\n                        if (assetComponent == null)\n                        {\n                            GOList.Add(instanceGameObject);\n                            return;\n                        }\n                    }\n                }\n            }\n            finally\n            {\n                // Clear the lists to avoid holding static references to components\n                s_ComponentList.Clear();\n                s_AssetComponentList.Clear();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor;\nusing UnityEngine;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.SceneManagement;\nusing System.Text;\nusing static UnityEditor.GameObjectTreeViewGUI;\nusing Object = UnityEngine.Object;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    internal class PrefabOverridesWindow : PopupWindowContent\n    {\n        RectOffset k_TreeViewPadding = new RectOffset(0, 0, 4, 4);\n        const float k_HeaderHeight = 60f;\n        const float k_ButtonWidth = 120;\n        const float k_ButtonWidthVariant = 201;\n        const float k_ButtonWidthPadding = 10; //Padding in case the text is long to give the window a bit of margins around the buttons\n        const float k_HeaderLeftMargin = 6;\n        const float k_NoOverridesLabelHeight = 26f;\n        const float k_UnusedOverridesButtonHeight = 26f;\n        const float k_RowPadding = 6;\n        float m_ApplyButtonHeight = 0;\n        GameObject[] m_SelectedGameObjects = null;\n\n        // TreeView not used when there are multiple Prefabs.\n        TreeViewState m_TreeViewState;\n        PrefabOverridesTreeView m_TreeView;\n\n        GUIContent m_StageContent = new GUIContent();\n        GUIContent m_InstanceContent = new GUIContent();\n        GUIContent m_RevertAllContent = new GUIContent();\n        GUIContent m_ApplyAllContent = new GUIContent();\n        GUIContent m_RevertSelectedContent = new GUIContent();\n        GUIContent m_ApplySelectedContent = new GUIContent();\n\n        float m_ButtonWidth;\n        float m_ApplyButtonWidth;\n        bool m_AnyOverrides;\n        bool m_HasApplicableOverrides;\n        bool m_InvalidComponentOnInstance;\n        bool m_ModelPrefab;\n        bool m_Immutable;\n        bool m_InvalidComponentOnAsset;\n        bool m_HasManagedReferencesWithMissingTypesOnAsset;\n        bool m_UnusedOverridesExist;\n        static class Styles\n        {\n            public static GUIContent revertAllContent = EditorGUIUtility.TrTextContent(\"Revert All\", \"Revert all overrides.\");\n            public static GUIContent revertSelectedContent = EditorGUIUtility.TrTextContent(\"Revert Selected\", \"Revert selected overrides.\");\n            public static GUIContent applyAllContent = EditorGUIUtility.TrTextContent(\"Apply All\", \"Apply all overrides to Prefab source '{0}'.\");\n            public static GUIContent applySelectedContent = EditorGUIUtility.TrTextContent(\"Apply Selected\", \"Apply selected overrides to Prefab source '{0}'.\");\n            public static GUIContent applyAllToBaseContent = EditorGUIUtility.TrTextContent(\"Apply All to Prefab Variant parent\", \"Apply all overrides to Prefab Variant parent '{0}'.\");\n            public static GUIContent applySelectedToBaseContent = EditorGUIUtility.TrTextContent(\"Apply Selected to Prefab Variant parent\", \"Apply selected overrides to Prefab Variant parent '{0}'.\");\n            public static GUIContent titleLabelDefault = EditorGUIUtility.TrTextContent(\"Review, Revert or Apply Overrides\");\n            public static GUIContent titleLabelNoApply = EditorGUIUtility.TrTextContent(\"Review or Revert Overrides\");\n            public static GUIContent noOverridesText = EditorGUIUtility.TrTextContent(\"No overrides\");\n            public static GUIContent instanceLabel = EditorGUIUtility.TrTextContent(\"on\");\n            public static GUIContent contextLabel = EditorGUIUtility.TrTextContent(\"in\");\n            public static GUIContent removeUnusedOverridesButtonContent = EditorGUIUtility.TrTextContentWithIcon(\"Unused overrides\", EditorGUIUtility.LoadIcon(\"Clear\"));\n\n            public static string nonApplicableTooltipApply = L10n.Tr(\"There are no overrides that can be applied to Prefab source '{0}'.\");\n            public static string nonApplicableTooltipRevert = L10n.Tr(\"There are no overrides that can be reverted.\");\n\n            public static GUIContent infoMultiple = EditorGUIUtility.TrTextContent(\"Multiple Prefabs selected. Cannot show overrides.\");\n            public static GUIContent infoMultipleNoApply = EditorGUIUtility.TrTextContent(\"Multiple Prefabs selected. Cannot show overrides.\\nApplying is not possible for one or more Prefabs. Select individual Prefabs for details.\");\n\n            // Messages related to the overrides list.\n            public static GUIContent infoModel = EditorGUIUtility.TrTextContent(\"Applying to a Model Prefab is not possible.\");\n\n            // Messages related to reasons for inability to apply.\n            public static GUIContent warningInvalidAsset = EditorGUIUtility.TrTextContent(\"The Prefab file contains an invalid script. Applying is not possible. Enter Prefab Mode and either remove the script component or recover the script.\");\n            public static GUIContent warningHasManagedReferencesWithMissingTypes = EditorGUIUtility.TrTextContent(\"The Prefab file contains missing SerializeReference types. Applying is not possible. Enter Prefab Mode to see more details.\");\n            public static GUIContent warningInvalidInstance = EditorGUIUtility.TrTextContent(\"The Prefab instance contains an invalid script. Applying is not possible. Remove or recover the script.\");\n            public static GUIContent warningImmutable = EditorGUIUtility.TrTextContent(\"The Prefab file is immutable. Applying is not possible.\");\n\n            public static GUIStyle boldRightAligned;\n            public static GUIStyle rightAligned;\n            public static GUIStyle removeOverridesButtonLineStyle = \"TV Line\";\n            public static GUIStyle removeOverridesButtonSelectionStyle = \"TV Selection\";\n\n            static Styles()\n            {\n                boldRightAligned = new GUIStyle(EditorStyles.boldLabel);\n                boldRightAligned.alignment = TextAnchor.MiddleRight;\n\n                rightAligned = new GUIStyle(EditorStyles.label);\n                rightAligned.alignment = TextAnchor.MiddleRight;\n\n                removeOverridesButtonLineStyle.alignment = TextAnchor.MiddleLeft;\n                removeOverridesButtonLineStyle.padding.left = 7;\n            }\n        }\n\n        internal PrefabOverridesWindow(GameObject selectedGameObject)\n        {\n            m_SelectedGameObjects = new GameObject[] { selectedGameObject };\n            m_TreeViewState = new TreeViewState();\n            m_TreeView = new PrefabOverridesTreeView(selectedGameObject, m_TreeViewState, this);\n\n            GameObject prefabAssetRoot = PrefabUtility.GetCorrespondingObjectFromSource(selectedGameObject);\n\n            m_TreeView.SetApplyTarget(selectedGameObject, prefabAssetRoot, AssetDatabase.GetAssetPath(prefabAssetRoot));\n\n            // m_TreeView.SetApplyTarget already reloads the TreeView so don't do it again in RefreshStatus.\n            RefreshStatus(false);\n        }\n\n        internal PrefabOverridesWindow(GameObject[] selectedGameObjects)\n        {\n            m_SelectedGameObjects = selectedGameObjects;\n            RefreshStatus();\n        }\n\n        public override void OnOpen()\n        {\n            Undo.undoRedoEvent += OnUndoRedoPerformed;\n            Selection.selectionChanged += OnSelectionChange;\n            base.OnOpen();\n        }\n\n        public override void OnClose()\n        {\n            Undo.undoRedoEvent -= OnUndoRedoPerformed;\n            Selection.selectionChanged -= OnSelectionChange;\n            base.OnClose();\n        }\n\n        void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            RefreshStatus();\n        }\n\n        // This function is called when the Property Context Menu Item 'Go To Value in Prefab X' is selected,\n        // which opens prefab mode (case SMT-145) and therefore requires the PrefabOverridesWindow to close.\n        // As just calling editorWindow.Close() would cause the entire Editor to minimize for unknown reasons,\n        // we put the InspectorWindow in focus to close the window and to prevent minimization of the Editor.\n        void OnSelectionChange()\n        {\n            if (InspectorWindow.GetAllInspectorWindows().Length != 0)\n                InspectorWindow.GetAllInspectorWindows()[0].Focus();\n        }\n\n        internal void RefreshStatus(bool reloadTreeView = true)\n        {\n            if (m_TreeView != null && reloadTreeView)\n            {\n                if (!m_TreeView.IsValidTargetPrefabInstance())\n                {\n                    editorWindow.Close();\n                    return;\n                }\n\n                m_TreeView.Reload();\n                m_TreeView.CullNonExistingItemsFromSelection();\n            }\n\n            m_AnyOverrides = false;\n            m_InvalidComponentOnInstance = false;\n            m_ModelPrefab = false;\n            m_Immutable = false;\n            m_InvalidComponentOnAsset = false;\n            m_HasManagedReferencesWithMissingTypesOnAsset = false;\n\n            for (int i = 0; i < m_SelectedGameObjects.Length; i++)\n                UpdateStatusChecks(m_SelectedGameObjects[i]);\n\n            if (m_SelectedGameObjects.Length == 1)\n                UpdateTextSingle(PrefabUtility.GetCorrespondingObjectFromSource(m_SelectedGameObjects[0]));\n            else\n                UpdateTextMultiple();\n\n            m_UnusedOverridesExist = PrefabUtility.HavePrefabInstancesUnusedOverrides(m_SelectedGameObjects);\n        }\n\n        void UpdateStatusChecks(GameObject prefabInstanceRoot)\n        {\n            // Can't reset values inside this method, since it's called consecutively for each target.\n\n            if (PrefabUtility.HasPrefabInstanceAnyOverrides(prefabInstanceRoot, false))\n                m_AnyOverrides = true;\n            if (PrefabUtility.HasInvalidComponent(prefabInstanceRoot))\n                m_InvalidComponentOnInstance = true;\n\n            GameObject prefabAssetRoot = PrefabUtility.GetCorrespondingObjectFromSource(prefabInstanceRoot);\n\n            if (PrefabUtility.IsPartOfModelPrefab(prefabAssetRoot))\n                m_ModelPrefab = true;\n            if (PrefabUtility.IsPartOfImmutablePrefab(prefabAssetRoot))\n                m_Immutable = true;\n            if (PrefabUtility.HasInvalidComponent(prefabAssetRoot))\n                m_InvalidComponentOnAsset = true;\n\n            if (PrefabUtility.HasManagedReferencesWithMissingTypes(prefabAssetRoot))\n                m_HasManagedReferencesWithMissingTypesOnAsset = true;\n\n            m_HasApplicableOverrides = m_TreeView == null || m_TreeView.hasApplicableModifications;\n        }\n\n        bool IsShowingActionButton()\n        {\n            return m_AnyOverrides;\n        }\n\n        bool IsShowingUnusedOverridesButton()\n        {\n            return m_UnusedOverridesExist;\n        }\n\n        bool HasMultiSelection()\n        {\n            return m_SelectedGameObjects.Length > 1;\n        }\n\n        bool IsShowingApplyWarning()\n        {\n            return\n                !HasMultiSelection() &&\n                m_AnyOverrides &&\n                !m_ModelPrefab &&\n                (m_InvalidComponentOnInstance || m_InvalidComponentOnAsset || m_HasManagedReferencesWithMissingTypesOnAsset || m_Immutable);\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            return CalculateWindowSize();\n        }\n\n        Vector2 CalculateWindowSize()\n        {\n            const float k_MaxAllowedTreeViewWidth = 1800f;\n            const float k_MaxAllowedTreeViewHeight = 1000f;\n            var width = 300f;\n            var height = k_HeaderHeight;\n\n            // Match the call order as in OnGUI() to ensure the correct height is calculated\n\n            if (!IsShowingActionButton())\n            {\n                if (IsShowingUnusedOverridesButton())\n                    height += k_UnusedOverridesButtonHeight;\n                else\n                    height += k_NoOverridesLabelHeight;\n\n                return new Vector2(width, height);\n            }\n\n            if (HasMultiSelection())\n            {\n                if (m_InvalidComponentOnAsset || m_HasManagedReferencesWithMissingTypesOnAsset || m_InvalidComponentOnInstance || m_ModelPrefab || m_Immutable)\n                    height += CalcHeightForHelpBox(Styles.infoMultipleNoApply, MessageType.Info, width);\n                else\n                    height += CalcHeightForHelpBox(Styles.infoMultiple, MessageType.Info, width);\n\n                if (m_UnusedOverridesExist)\n                    height += k_UnusedOverridesButtonHeight + k_RowPadding;\n                else\n                    height += 2;\n            }\n            else\n            {\n                height += k_TreeViewPadding.top;\n                if (m_TreeView.hasModifications)\n                {\n                    height += Mathf.Min(k_MaxAllowedTreeViewHeight, m_TreeView.totalHeight);\n                    width = Mathf.Max(Mathf.Min(m_TreeView.maxItemWidth, k_MaxAllowedTreeViewWidth), width);\n                }\n\n                if (m_AnyOverrides)\n                {\n                    if (m_UnusedOverridesExist)\n                        height += k_UnusedOverridesButtonHeight + k_RowPadding;\n\n                    if (m_ModelPrefab)\n                        height += CalcHeightForHelpBox(Styles.infoModel, MessageType.Info, width);\n                }\n\n                if (IsShowingApplyWarning())\n                {\n                    if (m_InvalidComponentOnAsset)\n                        height += CalcHeightForHelpBox(Styles.warningInvalidAsset, MessageType.Warning, width);\n                    else if (m_InvalidComponentOnInstance)\n                        height += CalcHeightForHelpBox(Styles.warningInvalidInstance, MessageType.Warning, width);\n                    else if (m_HasManagedReferencesWithMissingTypesOnAsset)\n                        height += CalcHeightForHelpBox(Styles.warningHasManagedReferencesWithMissingTypes, MessageType.Warning, width);\n                    else if (m_Immutable)\n                        height += CalcHeightForHelpBox(Styles.warningImmutable, MessageType.Warning, width);\n                }\n            }\n\n            if (m_ApplyButtonHeight == 0)\n                m_ApplyButtonHeight = GUI.skin.button.CalcHeight(Styles.applySelectedContent, width) + GUI.skin.button.margin.top + GUI.skin.button.margin.bottom;\n\n            height += m_ApplyButtonHeight + k_RowPadding;\n\n            //In case the text is long\n            width = Mathf.Max(width, m_ApplyButtonWidth + m_ButtonWidth + k_ButtonWidthPadding);\n\n            return new Vector2(width, height);\n        }\n\n        float CalcHeightForHelpBox(GUIContent content, MessageType messageType, float width)\n        {\n            var tempContent = EditorGUIUtility.TempContent(content.text, EditorGUIUtility.GetHelpIcon(messageType));\n            return EditorStyles.helpBox.CalcHeight(tempContent, width) + EditorStyles.helpBox.margin.top + EditorStyles.helpBox.margin.bottom;\n        }\n\n        Color headerBgColor { get { return EditorGUIUtility.isProSkin ? new Color(0.5f, 0.5f, 0.5f, 0.2f) : new Color(0.9f, 0.9f, 0.9f, 0.6f); } }\n        Color horizontalLineColor = new Color(0.5f, 0.5f, 0.5f, 0.3f);\n        public override void OnGUI(Rect rect)\n        {\n            // Escape closes the window\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)\n            {\n                editorWindow.Close();\n                GUIUtility.ExitGUI();\n            }\n\n            Rect headerRect = GUILayoutUtility.GetRect(20, 10000, k_HeaderHeight, k_HeaderHeight);\n            EditorGUI.DrawRect(headerRect, headerBgColor);\n\n            float titleLabelSize = 0;\n            if (m_ModelPrefab || m_Immutable || m_InvalidComponentOnInstance)\n            {\n                titleLabelSize = EditorStyles.boldLabel.CalcSize(Styles.titleLabelNoApply).x;\n                Rect titleLabelRect = new Rect(headerRect.x + k_HeaderLeftMargin, headerRect.y, titleLabelSize, headerRect.height);\n                titleLabelRect.height = EditorGUIUtility.singleLineHeight;\n                GUI.Label(titleLabelRect, Styles.titleLabelNoApply, Styles.boldRightAligned);\n            }\n            else\n            {\n                titleLabelSize = EditorStyles.boldLabel.CalcSize(Styles.titleLabelDefault).x;\n                Rect titleLabelRect = new Rect(headerRect.x + k_HeaderLeftMargin, headerRect.y, titleLabelSize, headerRect.height);\n                titleLabelRect.height = EditorGUIUtility.singleLineHeight;\n                GUI.Label(titleLabelRect, Styles.titleLabelDefault, Styles.boldRightAligned);\n            }\n\n            float labelSize = EditorStyles.label.CalcSize(Styles.instanceLabel).x;\n\n            headerRect.height = EditorGUIUtility.singleLineHeight;\n\n            Rect labelRect = new Rect(headerRect.x + k_HeaderLeftMargin, headerRect.y + 20, labelSize, headerRect.height);\n            Rect contentRect = headerRect;\n            contentRect.xMin = labelRect.xMax;\n            contentRect.y = labelRect.y;\n\n            GUI.Label(labelRect, Styles.instanceLabel, Styles.rightAligned);\n            GUI.Label(contentRect, m_InstanceContent, EditorStyles.label);\n\n            labelRect.y += EditorGUIUtility.singleLineHeight;\n            contentRect.y += EditorGUIUtility.singleLineHeight;\n            GUI.Label(labelRect, Styles.contextLabel, Styles.rightAligned);\n            GUI.Label(contentRect, m_StageContent, EditorStyles.label);\n\n            // If we know there are no overrides and thus no meaningful actions we just show that and nothing more.\n            if (!IsShowingActionButton())\n            {\n                if (m_UnusedOverridesExist)\n                {\n                    DrawUnusedOverridesButton();\n                    GUILayout.Space(k_RowPadding);\n                }\n                else\n                {\n                    EditorGUILayout.LabelField(Styles.noOverridesText);\n                }\n                return;\n            }\n\n            // Display tree view and/or instructions related to it.\n            if (HasMultiSelection())\n            {\n                if (m_InvalidComponentOnAsset || m_HasManagedReferencesWithMissingTypesOnAsset || m_InvalidComponentOnInstance || m_ModelPrefab || m_Immutable)\n                    EditorGUILayout.HelpBox(Styles.infoMultipleNoApply.text, MessageType.Info);\n                else\n                    EditorGUILayout.HelpBox(Styles.infoMultiple.text, MessageType.Info);\n\n                if (m_UnusedOverridesExist)\n                {\n                    DrawUnusedOverridesButton();\n                    GUILayout.Space(k_RowPadding);\n                }\n                else\n                {\n                    GUILayout.Space(2);\n                }\n            }\n            else\n            {\n                GUILayout.Space(k_TreeViewPadding.top);\n\n                if (m_TreeView.hasModifications)\n                {\n                    Rect treeViewRect = GUILayoutUtility.GetRect(100, 10000, 0, 10000);\n                    m_TreeView.OnGUI(treeViewRect);\n                }\n\n                if (m_AnyOverrides)\n                {\n                    if (m_UnusedOverridesExist)\n                    {\n                        DrawUnusedOverridesButton();\n                        GUILayout.Space(k_RowPadding);\n                    }\n\n                    if (m_ModelPrefab)\n                        EditorGUILayout.HelpBox(Styles.infoModel.text, MessageType.Info);\n                }\n\n                if (IsShowingApplyWarning())\n                {\n                    // Display warnings about edge cases that make it impossible to apply.\n                    // Model Prefabs are not an edge case and not needed to warn about so it's\n                    // not included here but rather combined into the info message above.\n                    if (m_InvalidComponentOnAsset)\n                        EditorGUILayout.HelpBox(Styles.warningInvalidAsset.text, MessageType.Warning);\n                    else if (m_InvalidComponentOnInstance)\n                        EditorGUILayout.HelpBox(Styles.warningInvalidInstance.text, MessageType.Warning);\n                    else if (m_HasManagedReferencesWithMissingTypesOnAsset)\n                        EditorGUILayout.HelpBox(Styles.warningHasManagedReferencesWithMissingTypes.text, MessageType.Warning);\n                    else if (m_Immutable)\n                        EditorGUILayout.HelpBox(Styles.warningImmutable.text, MessageType.Warning);\n                }\n            }\n\n            // Display action buttons (Revert All and Apply All)\n            GUILayout.BeginHorizontal();\n            GUILayout.FlexibleSpace();\n\n            using (new EditorGUI.DisabledScope(m_InvalidComponentOnAsset || m_HasManagedReferencesWithMissingTypesOnAsset))\n            {\n                if (m_TreeView != null && m_TreeView.GetSelection().Count > 1)\n                {\n                    if (GUILayout.Button(m_RevertSelectedContent, GUILayout.Width(m_ButtonWidth)))\n                    {\n                        if (OperateSelectedOverrides(PrefabUtility.OverrideOperation.Revert))\n                        {\n                            RefreshStatus();\n                            // We don't close the window even if there are no more overrides left.\n                            // We want to diplay explicit confirmation, since it's not a given outcome\n                            // when using Revert Selected. Only Revert All button closes the window.\n                        }\n                    }\n\n                    using (new EditorGUI.DisabledScope(m_Immutable || m_InvalidComponentOnInstance))\n                    {\n                        if (GUILayout.Button(m_ApplySelectedContent, GUILayout.Width(m_ButtonWidth)))\n                        {\n                            if (OperateSelectedOverrides(PrefabUtility.OverrideOperation.Apply))\n                            {\n                                RefreshStatus();\n                                // We don't close the window even if there are no more overrides left.\n                                // We want to diplay explicit confirmation, since it's not a given outcome\n                                // when using Apply Selected. Only Apply All button closes the window.\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (GUILayout.Button(m_RevertAllContent, GUILayout.Width(m_ButtonWidth)))\n                    {\n                        if (RevertAll() && editorWindow != null)\n                        {\n                            editorWindow.Close();\n                            GUIUtility.ExitGUI();\n                        }\n                    }\n\n                    using (new EditorGUI.DisabledScope(m_Immutable || m_InvalidComponentOnInstance || !m_HasApplicableOverrides))\n                    {\n                        if (GUILayout.Button(m_ApplyAllContent, GUILayout.Width(m_ApplyButtonWidth)))\n                        {\n                            if (ApplyAll() && editorWindow != null)\n                            {\n                                editorWindow.Close();\n                                GUIUtility.ExitGUI();\n                            }\n                        }\n                    }\n                }\n            }\n\n            GUILayout.EndHorizontal();\n            GUILayout.Space(k_RowPadding);\n        }\n\n        void DrawUnusedOverridesButton()\n        {\n            Rect buttonRect = GUILayoutUtility.GetRect(100, 10000, k_NoOverridesLabelHeight, k_NoOverridesLabelHeight);\n\n            var isHovered = buttonRect.Contains(UnityEngine.Event.current.mousePosition);\n            if (isHovered)\n            {\n                GUIView.current.MarkHotRegion(GUIClip.UnclipToWindow(buttonRect));\n\n                using (new GUI.BackgroundColorScope(GameObjectStyles.hoveredBackgroundColor))\n                {\n                    GUI.Label(buttonRect, GUIContent.none, GameObjectStyles.hoveredItemBackgroundStyle);\n                }\n            }\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                if (UnusedOverridesViewPopup.s_IsOpen)\n                    Styles.removeOverridesButtonSelectionStyle.Draw(buttonRect, false, false, true, true);\n\n                Rect buttonBorder = new Rect(buttonRect.x, buttonRect.y, buttonRect.width, 1);\n                EditorGUI.DrawRect(buttonBorder, horizontalLineColor);// Upper border.\n\n                buttonBorder.y = buttonRect.y + buttonRect.height;\n                EditorGUI.DrawRect(buttonBorder, horizontalLineColor);// Lower border.\n\n                Styles.removeOverridesButtonLineStyle.Draw(buttonRect, Styles.removeUnusedOverridesButtonContent, false, false, UnusedOverridesViewPopup.s_IsOpen, true);\n            }\n\n            if (GUI.Button(buttonRect, GUIContent.none, GUIStyle.none))\n            {\n                PopupWindowWithoutFocus.Show(buttonRect,\n                    new UnusedOverridesViewPopup(m_SelectedGameObjects, this),\n                    new[] { PopupLocation.Left, PopupLocation.Right });\n            }\n        }\n\n        bool ApplyAll()\n        {\n            // Collect Prefab Asset paths and also check if there's more than one of the same.\n            HashSet<string> prefabAssetPaths = new HashSet<string>();\n            bool multipleOfSame = false;\n            for (int i = 0; i < m_SelectedGameObjects.Length; i++)\n            {\n                string prefabAssetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(m_SelectedGameObjects[i]);\n                if (prefabAssetPaths.Contains(prefabAssetPath))\n                    multipleOfSame = true;\n                else\n                    prefabAssetPaths.Add(prefabAssetPath);\n            }\n\n            // If more than one instance of the same Prefab Asset, show dialog to user.\n            if (multipleOfSame && !EditorUtility.DisplayDialog(\n                L10n.Tr(\"Multiple instances of same Prefab Asset\"),\n                L10n.Tr(\"Multiple instances of the same Prefab Asset were detected. Potentially conflicting overrides will be applied sequentially and will overwrite each other.\"),\n                L10n.Tr(\"OK\"),\n                L10n.Tr(\"Cancel\")))\n                return false;\n\n            // Make sure assets are checked out in version control.\n            if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(prefabAssetPaths.ToArray(), PrefabUtility.SaveVerb.Apply))\n                return false;\n\n            PrefabUtility.ApplyPrefabInstances(m_SelectedGameObjects, InteractionMode.UserAction);\n\n            EditorUtility.ForceRebuildInspectors();\n            return true;\n        }\n\n        bool RevertAll()\n        {\n            for (int i = 0; i < m_SelectedGameObjects.Length; i++)\n                PrefabUtility.RevertPrefabInstance(m_SelectedGameObjects[i], InteractionMode.UserAction);\n\n            EditorUtility.ForceRebuildInspectors();\n            return true;\n        }\n\n        bool OperateSelectedOverrides(PrefabUtility.OverrideOperation operation)\n        {\n            List<PrefabOverride> overrides = new List<PrefabOverride>();\n\n            // Get all overrides from selection. Immediately accept any overrides with no dependencies.\n            var selection = m_TreeView.GetSelection();\n            for (int i = 0; i < selection.Count; i++)\n            {\n                PrefabOverride singleOverride = m_TreeView.FindOverride(selection[i]);\n                if (singleOverride != null)\n                    overrides.Add(singleOverride);\n            }\n\n            bool success = PrefabUtility.ProcessMultipleOverrides(m_SelectedGameObjects[0], overrides, operation, InteractionMode.UserAction);\n            if (success)\n                EditorUtility.ForceRebuildInspectors();\n            return success;\n        }\n\n        void UpdateTextSingle(GameObject prefabAsset)\n        {\n            Texture2D icon = (Texture2D)AssetDatabase.GetCachedIcon(AssetDatabase.GetAssetPath(prefabAsset));\n            string name = prefabAsset.name;\n            UpdateText(icon, name);\n        }\n\n        void UpdateTextMultiple()\n        {\n            Texture icon = EditorGUIUtility.IconContent(\"Prefab Icon\").image;\n            string name = \"(Multiple Prefabs)\";\n            UpdateText(icon, name);\n        }\n\n        void UpdateText(Texture assetIcon, string assetName)\n        {\n            var stage = SceneManagement.StageNavigationManager.instance.currentStage;\n            if (stage is MainStage)\n            {\n                m_StageContent.image = EditorGUIUtility.IconContent(\"SceneAsset Icon\").image;\n                m_StageContent.text = \"Scene\";\n            }\n            else if (stage is PrefabStage)\n            {\n                m_StageContent.image = (Texture2D)AssetDatabase.GetCachedIcon(stage.assetPath);\n                m_StageContent.text = System.IO.Path.GetFileNameWithoutExtension(stage.assetPath);\n            }\n\n            m_InstanceContent.image = assetIcon;\n            m_InstanceContent.text = assetName;\n\n            m_RevertAllContent = Styles.revertAllContent;\n            m_RevertSelectedContent = Styles.revertSelectedContent;\n\n            m_ButtonWidth = k_ButtonWidth;\n            m_ApplyButtonWidth = k_ButtonWidth;\n            var applyAllContent = new GUIContent(Styles.applyAllContent);\n            var revertAllContent = new GUIContent(Styles.revertAllContent);\n            var applySelectedContent = Styles.applySelectedContent;\n            if (stage is PrefabStage && PrefabUtility.IsPartOfVariantPrefab(AssetDatabase.LoadAssetAtPath<Object>(stage.assetPath)))\n            {\n                applyAllContent = Styles.applyAllToBaseContent;\n                m_ApplyButtonWidth = k_ButtonWidthVariant;\n                applySelectedContent = Styles.applySelectedToBaseContent;\n\n            }\n\n            if (!m_HasApplicableOverrides)\n            {\n                applyAllContent.tooltip = Styles.nonApplicableTooltipApply;\n                revertAllContent.tooltip = Styles.nonApplicableTooltipRevert;\n            }\n\n            m_ApplyAllContent = new GUIContent(applyAllContent.text, string.Format(applyAllContent.tooltip, assetName));\n            m_RevertAllContent = new GUIContent(revertAllContent.text, revertAllContent.tooltip);\n            m_ApplySelectedContent.text = applySelectedContent.text;\n            m_ApplySelectedContent.tooltip = string.Format(applySelectedContent.tooltip, assetName);\n        }\n    }\n\n    internal class UnusedOverridesViewPopup : PopupWindowContent\n    {\n        const float k_HeaderHeight = 25f;\n        const float k_BodyLineHeight = 16f;\n        const float k_ButtonWidth = 80f;\n        const float k_ViewWidthPadding = 20f;\n        const float k_BodyTextPadding = 10f;\n        const float k_BodyTextPaddingSmall = 6f;\n        const int k_LeftPaddingWidth = 10;\n        const int k_RemoveButtonRightMargin = 6;\n        const int k_MaxEntries = 3;\n\n        Vector2 m_ViewSize = new Vector2(250f, k_HeaderHeight);\n\n        static class Styles\n        {\n            public static GUIStyle borderStyle = new GUIStyle(\"grey_border\");\n            public static GUIStyle headerLabel = new GUIStyle(EditorStyles.boldLabel);\n            public static GUIStyle headerStyle = new GUIStyle(EditorStyles.boldLabel);\n            public static GUIStyle bodyStyle = new GUIStyle(EditorStyles.label);\n            public static GUIStyle logHintStyle = new GUIStyle(EditorStyles.label);\n            public static GUIStyle headerGroupStyle = new GUIStyle();\n            public static GUIContent headerContentBaseSingular = EditorGUIUtility.TrTextContent(\"unused override\");\n            public static GUIContent headerContentBasePlural = EditorGUIUtility.TrTextContent(\"unused overrides\");\n            public static GUIContent editorLogHint = EditorGUIUtility.TrTextContent(\"Details will be written to the Editor log.\");\n            public static GUIContent buttonContent = EditorGUIUtility.TrTextContent(\"Remove\");\n            public static GUIContent headerContent = EditorGUIUtility.TrTextContent(\"{0} unused overrides\");\n            public static GUIContent unusedRemovedComponentsContentSingular = EditorGUIUtility.TrTextContent(\"{0} has 1 unused removed component\");\n            public static GUIContent unusedRemovedComponentsContentPlural = EditorGUIUtility.TrTextContent(\"{0} has {1} unused removed components\");\n            public static GUIContent unusedRemovedGameObjectsContentSingular = EditorGUIUtility.TrTextContent(\"{0} has 1 unused removed GameObject\");\n            public static GUIContent unusedRemovedGameObjectsContentPlural = EditorGUIUtility.TrTextContent(\"{0} has {1} unused removed GameObjects\");\n            public static GUIContent headerContentSingular = EditorGUIUtility.TrTextContent(\"1 unused override\");\n            public static GUIContent extraOverridesContent = EditorGUIUtility.TrTextContent(\"and {0} others\");\n            public static GUIContent extraInstancesContent = EditorGUIUtility.TrTextContent(\"on {0} instances\");\n            public static GUIContent pathOnInstanceContent = EditorGUIUtility.TrTextContent(\"on\");\n\n            static Styles()\n            {\n                headerLabel.padding = new RectOffset(3, 3, 3, 3);\n\n                headerGroupStyle.padding = new RectOffset(0, 0, 3, 3);\n\n                headerStyle.alignment = TextAnchor.MiddleLeft;\n                headerStyle.padding.left = k_LeftPaddingWidth;\n                headerStyle.padding.top = 1;\n\n                bodyStyle.alignment = TextAnchor.UpperLeft;\n                bodyStyle.padding.left = k_LeftPaddingWidth;\n                bodyStyle.padding.top = 1;\n\n                logHintStyle.alignment = TextAnchor.MiddleLeft;\n                logHintStyle.padding.left = k_LeftPaddingWidth;\n                logHintStyle.padding.top = 1;\n            }\n        }\n\n        public static bool s_IsOpen;\n        PrefabOverridesWindow m_Owner;\n        GameObject[] m_SelectedGameObjects;\n        PrefabUtility.InstanceOverridesInfo[] m_InstanceOverridesInfos;\n        PrefabUtility.InstanceOverridesInfo m_SingleInstanceWithUnusedMods;\n        List<GUIContent> m_OverridesContent;\n        GUIContent m_RemainingOverridesInfo = null;\n        string m_HeaderText = string.Empty;\n        int m_SelectedInstanceCount = 0;\n        int m_AffectedInstanceCount = 0;\n        int m_UnusedOverridesCount = 0;\n        int m_UsedOverridesCount = 0;\n        int m_UnusedRemovedGameObjectsCount = 0;\n        int m_UnusedRemovedComponentsCount = 0;\n\n        public UnusedOverridesViewPopup(GameObject[] selectedGameObjects, PrefabOverridesWindow owner)\n        {\n            m_SelectedGameObjects = selectedGameObjects;\n            m_Owner = owner;\n\n            m_InstanceOverridesInfos = PrefabUtility.GetPrefabInstancesOverridesInfos(m_SelectedGameObjects);\n\n            CalculateStatistics();\n\n            float logHintWidth = GetTextWidth(Styles.editorLogHint.text, Styles.bodyStyle);\n            float headerWidth = BuildHeaderText();\n            float maxSummaryLineWidth = BuildMultilineSummary();\n\n            float maxWidth = (headerWidth > logHintWidth) ? headerWidth : logHintWidth;\n            if (maxSummaryLineWidth > maxWidth)\n                maxWidth = maxSummaryLineWidth;\n\n            m_ViewSize.x = maxWidth + k_ViewWidthPadding;\n\n            var lineHeight = GetTextHeight(\"a\", Styles.bodyStyle);\n            float height = k_HeaderHeight + k_BodyTextPadding + (lineHeight * m_OverridesContent.Count) + (k_BodyTextPadding * 2) + k_BodyTextPaddingSmall;\n            height += (m_RemainingOverridesInfo != null) ? k_BodyTextPaddingSmall + EditorStyles.label.lineHeight : 0;\n            m_ViewSize.y = height;\n        }\n\n        public override void OnOpen()\n        {\n            s_IsOpen = true;\n        }\n\n        public override void OnClose()\n        {\n            s_IsOpen = false;\n            base.OnClose();\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            return new Vector2(m_ViewSize.x, m_ViewSize.y + k_HeaderHeight);\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            Rect headerRect = new Rect(rect.x, rect.y, rect.width, k_HeaderHeight);\n            DrawHeader(headerRect);\n\n            Rect bodyRect = new Rect(rect.x, rect.y + k_HeaderHeight + k_BodyTextPadding, rect.width, rect.height - k_HeaderHeight - k_BodyLineHeight);\n            GUILayout.BeginArea(bodyRect);\n\n            foreach (GUIContent lineContent in m_OverridesContent)\n            {\n                GUILayout.Label(lineContent.text, Styles.bodyStyle);\n            }\n\n            if (m_RemainingOverridesInfo != null)\n            {\n                GUILayout.Space(k_BodyTextPaddingSmall);\n                GUILayout.Label(m_RemainingOverridesInfo, Styles.bodyStyle);\n            }\n\n            GUILayout.Space(k_BodyTextPadding * 2);\n            GUILayout.Label(Styles.editorLogHint, Styles.bodyStyle);\n            GUILayout.Space(k_BodyTextPaddingSmall);\n            GUILayout.EndArea();\n        }\n\n        void DrawHeader(Rect rect)\n        {\n            EditorGUI.LabelField(rect, m_HeaderText, Styles.headerStyle);\n            GUI.Label(new Rect(rect.x, rect.y, rect.width, rect.height), GUIContent.none, Styles.borderStyle);\n\n            DrawRemoveButton(rect);\n        }\n\n        void DrawRemoveButton(Rect rect)\n        {\n            GUILayout.BeginArea(rect);\n            GUILayout.BeginHorizontal(Styles.headerGroupStyle);\n            GUILayout.FlexibleSpace();\n\n            if (GUILayout.Button(Styles.buttonContent, EditorStyles.miniButton, GUILayout.Width(k_ButtonWidth)))\n            {\n                PrefabUtility.RemovePrefabInstanceUnusedOverrides(m_InstanceOverridesInfos, InteractionMode.UserAction);\n                editorWindow.Close();\n                m_Owner.RefreshStatus();\n                GUIUtility.ExitGUI();\n            }\n            GUILayout.Space(k_BodyTextPaddingSmall);\n            GUILayout.EndHorizontal();\n            GUILayout.EndArea();\n        }\n\n        void CalculateStatistics()\n        {\n            m_SingleInstanceWithUnusedMods = m_InstanceOverridesInfos[0];\n            m_SelectedInstanceCount = m_InstanceOverridesInfos.Count();\n\n            if (m_SelectedInstanceCount > 1)\n            {\n                foreach (PrefabUtility.InstanceOverridesInfo instanceMods in m_InstanceOverridesInfos)\n                {\n                    if (instanceMods.unusedOverrideCount == 0)\n                        continue;\n\n                    m_AffectedInstanceCount++;\n                    m_UnusedOverridesCount += instanceMods.unusedMods.Length;\n                    m_UsedOverridesCount += instanceMods.usedMods.Length;\n                    m_UnusedRemovedGameObjectsCount += instanceMods.unusedRemovedGameObjectCount;\n                    m_UnusedRemovedComponentsCount += instanceMods.unusedRemovedComponentCount;\n                    m_SingleInstanceWithUnusedMods = instanceMods;\n                }\n            }\n            else\n            {\n                m_AffectedInstanceCount = 1;\n                m_UnusedOverridesCount = m_SingleInstanceWithUnusedMods.unusedMods.Length;\n                m_UsedOverridesCount = m_SingleInstanceWithUnusedMods.usedMods.Length;\n                m_UnusedRemovedGameObjectsCount = m_SingleInstanceWithUnusedMods.unusedRemovedGameObjectCount;\n                m_UnusedRemovedComponentsCount = m_SingleInstanceWithUnusedMods.unusedRemovedComponentCount;\n            }\n\n            m_UnusedOverridesCount += m_UnusedRemovedComponentsCount;\n            m_UnusedOverridesCount += m_UnusedRemovedGameObjectsCount;\n        }\n\n        float BuildHeaderText()\n        {\n            if (m_UnusedOverridesCount > 1)\n                m_HeaderText = string.Format(Styles.headerContent.text, m_UnusedOverridesCount);\n            else\n                m_HeaderText = Styles.headerContentSingular.text;\n\n            return GetTextWidth(m_HeaderText, Styles.headerStyle) + k_ViewWidthPadding + k_ButtonWidth;\n        }\n\n        float BuildMultilineSummary()\n        {\n            m_OverridesContent = new List<GUIContent>();\n            int remainingAffectedInstanceCount = m_AffectedInstanceCount;\n            float maxLineWidth = 0;\n\n            foreach (PrefabUtility.InstanceOverridesInfo instanceMods in m_InstanceOverridesInfos)\n            {\n                int initialOverridesCount = m_OverridesContent.Count;\n\n                foreach (PropertyModification mod in instanceMods.unusedMods)\n                {\n                    if (m_OverridesContent.Count >= k_MaxEntries)\n                        break;\n\n                    string itemText = mod.propertyPath + \" \" + Styles.pathOnInstanceContent.text + \" \" + instanceMods.instance.name;\n                    m_OverridesContent.Add(new GUIContent(itemText));\n                }\n\n                if (instanceMods.unusedRemovedGameObjectCount > 0 && m_OverridesContent.Count < k_MaxEntries)\n                {\n                    string itemText = string.Empty;\n                    if (instanceMods.unusedRemovedGameObjectCount > 1)\n                        itemText = string.Format(Styles.unusedRemovedGameObjectsContentPlural.text, instanceMods.instance.name, instanceMods.unusedRemovedGameObjectCount);\n                    else\n                        itemText = string.Format(Styles.unusedRemovedGameObjectsContentSingular.text, instanceMods.instance.name);\n\n                    m_OverridesContent.Add(new GUIContent(itemText));\n                }\n\n                if (instanceMods.unusedRemovedComponentCount > 0 && m_OverridesContent.Count < k_MaxEntries)\n                {\n                    string itemText = string.Empty;\n                    if (instanceMods.unusedRemovedComponentCount > 1)\n                        itemText = string.Format(Styles.unusedRemovedComponentsContentPlural.text, instanceMods.instance.name, instanceMods.unusedRemovedComponentCount);\n                    else\n                        itemText = string.Format(Styles.unusedRemovedComponentsContentSingular.text, instanceMods.instance.name);\n\n                    m_OverridesContent.Add(new GUIContent(itemText));\n                }\n\n                int entriesFromThisInstance = m_OverridesContent.Count - initialOverridesCount;\n\n                bool addedLines = entriesFromThisInstance > 0;\n                if (addedLines && instanceMods.unusedMods.Length <= entriesFromThisInstance)\n                    remainingAffectedInstanceCount--;\n            }\n\n            foreach (var content in m_OverridesContent)\n            {\n                float w = GetTextWidth(content.text, Styles.bodyStyle);\n                maxLineWidth = Math.Max(w, maxLineWidth);\n            }\n\n            int remainingUnusedOverridesCount = m_UnusedOverridesCount - k_MaxEntries;\n            if (remainingUnusedOverridesCount > 0)\n            {\n                string remainingOverridesInfo = string.Format(Styles.extraOverridesContent.text, remainingUnusedOverridesCount);\n\n                if (remainingAffectedInstanceCount > 1)\n                    remainingOverridesInfo += \" \" + string.Format(Styles.extraInstancesContent.text, remainingAffectedInstanceCount);\n\n                remainingOverridesInfo += \".\";\n                m_RemainingOverridesInfo = new GUIContent(remainingOverridesInfo);\n\n                float w = GetTextWidth(m_RemainingOverridesInfo.text, Styles.bodyStyle);\n                maxLineWidth = Math.Max(w, maxLineWidth);\n            }\n\n            return maxLineWidth;\n        }\n\n        float GetTextWidth(string text, GUIStyle style)\n        {\n            var content = GUIContent.Temp(text);\n            return style.CalcSize(content).x;\n        }\n\n        float GetTextHeight(string text, GUIStyle style)\n        {\n            var content = GUIContent.Temp(text);\n            return style.CalcSize(content).y;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Prefabs/PrefabOverrides/TransformVisitor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Assertions;\n\nnamespace UnityEditor.SceneManagement\n{\n    class TransformVisitor\n    {\n        public void VisitAll(Transform transform, Action<Transform, object> visitorFunc, object userData)\n        {\n            Assert.IsNotNull(transform, \"Please provide a valid transform\");\n            Assert.IsNotNull(visitorFunc, \"Please provide a valid visitorFunc\");\n\n            VisitAllRecursively(transform, visitorFunc, userData);\n        }\n\n        static void VisitAllRecursively(Transform transform, Action<Transform, object> visitorFunc, object userData)\n        {\n            visitorFunc(transform, userData);\n            for (int i = 0; i < transform.childCount; ++i)\n                VisitAllRecursively(transform.GetChild(i), visitorFunc, userData);\n        }\n\n        // Let visitorFunc return true for continue visiting, false for early out.\n        public void VisitAndAllowEarlyOut(Transform transform, Func<Transform, object, bool> visitorFunc, object userData)\n        {\n            Assert.IsNotNull(transform, \"Please provide a valid transform\");\n            Assert.IsNotNull(visitorFunc, \"Please provide a valid visitorFunc\");\n\n            VisitAndAllowEarlyOutRecursively(transform, visitorFunc, userData);\n        }\n\n        static bool VisitAndAllowEarlyOutRecursively(Transform transform, Func<Transform, object, bool> visitorFunc, object userData)\n        {\n            if (!visitorFunc(transform, userData))\n                return false;\n\n            for (int i = 0; i < transform.childCount; ++i)\n            {\n                if (!VisitAndAllowEarlyOutRecursively(transform.GetChild(i), visitorFunc, userData))\n                    return false;\n            }\n            return true;\n        }\n\n        // Let visitorFunc return true for entering children, false for skipping them.\n        public void VisitAndConditionallyEnterChildren(Transform transform, Func<Transform, object, bool> visitorFunc, object userData)\n        {\n            Assert.IsNotNull(transform, \"Please provide a valid transform\");\n            Assert.IsNotNull(visitorFunc, \"Please provide a valid visitorFunc\");\n\n            VisitAndConditionallyEnterChildrenRecursively(transform, visitorFunc, userData);\n        }\n\n        static void VisitAndConditionallyEnterChildrenRecursively(Transform transform, Func<Transform, object, bool> visitorFunc, object userData)\n        {\n            if (!visitorFunc(transform, userData))\n                return;\n\n            for (int i = 0; i < transform.childCount; ++i)\n                VisitAndConditionallyEnterChildrenRecursively(transform.GetChild(i), visitorFunc, userData);\n        }\n\n        // Only visit transforms under the same PrefabInstance\n        public void VisitPrefabInstanceTransforms(Transform transform, Func<Transform, object, bool> visitorFunc, object userData)\n        {\n            Assert.IsNotNull(transform, \"Please provide a valid transform\");\n            Assert.IsNotNull(visitorFunc, \"Please provide a valid visitorFunc\");\n            Assert.IsNotNull(PrefabUtility.GetPrefabInstanceHandle(transform), \"Please provide a Prefab instance\");\n\n            VisitPrefabInstanceTransformsRecursively(transform, visitorFunc, userData);\n        }\n\n        static void VisitPrefabInstanceTransformsRecursively(Transform transform, Func<Transform, object, bool> visitorFunc, object userData)\n        {\n            if (!visitorFunc(transform, userData))\n                return;\n\n            var prefabInstanceHandle = PrefabUtility.GetPrefabInstanceHandle(transform);\n            for (int i = 0; i < transform.childCount; ++i)\n            {\n                var child = transform.GetChild(i);\n                if (PrefabUtility.GetPrefabInstanceHandle(child) == prefabInstanceHandle)\n                    VisitPrefabInstanceTransformsRecursively(child, visitorFunc, userData);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Prefabs/PrefabReplaceUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    static class PrefabReplaceUtility\n    {\n        static bool s_CreateOverrides = false;\n        static PrefabOverridesOptions s_PrefabOverideOptions = PrefabOverridesOptions.KeepAllPossibleOverrides;\n\n        internal static void ReplaceCurrentSelectionWithPrefabUsingObjectPicker(object userdata)\n        {\n            var args = ((GameObject, PrefabOverridesOptions, bool))userdata;\n            var contextClickedGameObject = args.Item1;\n            var prefabOverrideOptions = args.Item2;\n            var createOverrides = args.Item3;\n\n            s_CreateOverrides = createOverrides;\n            s_PrefabOverideOptions = prefabOverrideOptions;\n            ObjectSelector.get.Show(null, typeof(GameObject), contextClickedGameObject, false, null, null, OnObjectSelectorSelectionUpdated, false);\n        }\n\n        private static void OnObjectSelectorSelectionUpdated(UnityEngine.Object obj)\n        {\n            var selectedPrefabAsset = (GameObject)obj;\n            if (selectedPrefabAsset == null)\n                return;\n\n            if (!EditorUtility.IsPersistent(selectedPrefabAsset))\n                return;\n\n            var contextClickedGameObject = ObjectSelector.get.objectBeingEdited as GameObject;\n            List<GameObject> listOfInstanceRoots;\n            List<GameObject> listOfPlainGameObjects;\n            FindGameObjectsToReplace(contextClickedGameObject, out listOfPlainGameObjects, out listOfInstanceRoots);\n\n            if (listOfInstanceRoots.Count == 0 && listOfPlainGameObjects.Count == 0)\n                return;\n\n            if (listOfInstanceRoots.Count > 0)\n                PrefabUtility.ReplacePrefabAssetOfPrefabInstances(listOfInstanceRoots.ToArray(), selectedPrefabAsset, GetPrefabReplacingSettingsForUI(s_PrefabOverideOptions), InteractionMode.UserAction);\n            if (listOfPlainGameObjects.Count > 0)\n                PrefabUtility.ConvertToPrefabInstances(listOfPlainGameObjects.ToArray(), selectedPrefabAsset, GetConvertToPrefabInstanceSettingsForUI(s_CreateOverrides), InteractionMode.UserAction);\n\n            if (contextClickedGameObject != null && !Selection.Contains(contextClickedGameObject))\n                Selection.activeGameObject = contextClickedGameObject;\n        }\n\n        internal static bool HasInstancesAnyOverrides(List<GameObject> listOfInstanceRoots)\n        {\n            foreach (var root in listOfInstanceRoots)\n                if (PrefabUtility.HasPrefabInstanceAnyOverrides(root, false))\n                    return true;\n\n            return false;\n        }\n\n        internal static bool AddReplaceMenuItemsToMenuBasedOnCurrentSelection(GenericMenu menu, string parentMenuItemPath, GameObject contextGameObject, List<GameObject> listOfInstanceRoots, List<GameObject> listOfPlainGameObjects, GameObject prefabAsset)\n        {\n            if (listOfInstanceRoots.Count == 0 && listOfPlainGameObjects.Count == 0)\n                return false;\n\n            string GetMenuItemText(string text, string parentMenuItemPath, bool needsObjectSelector)\n            {\n                return string.Format(\"{0}{1}{2}\", parentMenuItemPath, text, (needsObjectSelector ? \"...\" : \"\"));\n            }\n\n            bool needObjectSelector = prefabAsset == null;\n            var replaceText = L10n.Tr(\"Replace\");\n            var replaceAndKeepOverridesText = L10n.Tr(\"Replace and Keep Overrides\");\n            var reconnectPrefabText = L10n.Tr(\"Reconnect Prefab\");\n            var replaceAndReconnectPrefabText = L10n.Tr(\"Replace and Reconnect Prefab\");\n\n            if (listOfInstanceRoots.Count > 0)\n            {\n                var hasAnyOverrides = HasInstancesAnyOverrides(listOfInstanceRoots);\n\n                if (hasAnyOverrides)\n                {\n                    var text1 = new GUIContent(GetMenuItemText(replaceText, parentMenuItemPath, needObjectSelector));\n                    var text2 = new GUIContent(GetMenuItemText(replaceAndKeepOverridesText, parentMenuItemPath, needObjectSelector));\n\n                    if (needObjectSelector)\n                    {\n                        menu.AddItem(text1, false, ReplaceCurrentSelectionWithPrefabUsingObjectPicker, (contextGameObject, PrefabOverridesOptions.ClearAllNonDefaultOverrides, true));\n                        menu.AddItem(text2, false, ReplaceCurrentSelectionWithPrefabUsingObjectPicker, (contextGameObject, PrefabOverridesOptions.KeepAllPossibleOverrides, false));\n                    }\n                    else\n                    {\n                        menu.AddItem(text1, false, MenuActionForConvertAndReplacePrefabInstance, (contextGameObject, listOfInstanceRoots, PrefabOverridesOptions.ClearAllNonDefaultOverrides, listOfPlainGameObjects, true, prefabAsset));\n                        menu.AddItem(text2, false, MenuActionForConvertAndReplacePrefabInstance, (contextGameObject, listOfInstanceRoots, PrefabOverridesOptions.KeepAllPossibleOverrides, listOfPlainGameObjects, false, prefabAsset));\n                    }\n                }\n                else // no overrides on instances\n                {\n                    var text1 = new GUIContent(GetMenuItemText(replaceText, parentMenuItemPath, needObjectSelector));\n                    GUIContent text2 = null;\n                    if (listOfPlainGameObjects.Count > 0)\n                        text2 = new GUIContent(GetMenuItemText(replaceAndReconnectPrefabText, parentMenuItemPath, needObjectSelector));\n                    else\n                        text2 = new GUIContent(GetMenuItemText(replaceAndKeepOverridesText, parentMenuItemPath, needObjectSelector));\n\n                    if (needObjectSelector)\n                    {\n                        menu.AddItem(text1, false, ReplaceCurrentSelectionWithPrefabUsingObjectPicker, (contextGameObject, PrefabOverridesOptions.KeepAllPossibleOverrides, false));\n                        if (listOfPlainGameObjects.Count > 0)\n                            menu.AddItem(text2, false, ReplaceCurrentSelectionWithPrefabUsingObjectPicker, (contextGameObject, PrefabOverridesOptions.ClearAllNonDefaultOverrides, true));\n                        else\n                            menu.AddDisabledItem(text2, false);\n                    }\n                    else\n                    {\n                        menu.AddItem(text1, false, MenuActionForConvertAndReplacePrefabInstance, (contextGameObject, listOfInstanceRoots, PrefabOverridesOptions.KeepAllPossibleOverrides, listOfPlainGameObjects, false, prefabAsset));\n                        if (listOfPlainGameObjects.Count > 0)\n                            menu.AddItem(text2, false, MenuActionForConvertAndReplacePrefabInstance, (contextGameObject, listOfInstanceRoots, PrefabOverridesOptions.ClearAllNonDefaultOverrides, listOfPlainGameObjects, true, prefabAsset));\n                        else\n                            menu.AddDisabledItem(text2, false);\n                    }\n                }\n            }\n            else if (listOfPlainGameObjects.Count > 0)\n            {\n                // Only plain gameobjects\n                var text1 = new GUIContent(GetMenuItemText(replaceText, parentMenuItemPath, needObjectSelector));\n                var text2 = new GUIContent(GetMenuItemText(reconnectPrefabText, parentMenuItemPath, needObjectSelector));\n\n                if (needObjectSelector)\n                {\n                    menu.AddItem(text1, false, ReplaceCurrentSelectionWithPrefabUsingObjectPicker, (contextGameObject, PrefabOverridesOptions.KeepAllPossibleOverrides, false));\n                    menu.AddItem(text2, false, ReplaceCurrentSelectionWithPrefabUsingObjectPicker, (contextGameObject, PrefabOverridesOptions.ClearAllNonDefaultOverrides, true));\n                }\n                else\n                {\n                    menu.AddItem(text1, false, MenuActionForConvertAndReplacePrefabInstance, (contextGameObject, listOfInstanceRoots, PrefabOverridesOptions.KeepAllPossibleOverrides, listOfPlainGameObjects, false, prefabAsset));\n                    menu.AddItem(text2, false, MenuActionForConvertAndReplacePrefabInstance, (contextGameObject, listOfInstanceRoots, PrefabOverridesOptions.ClearAllNonDefaultOverrides, listOfPlainGameObjects, true, prefabAsset));\n                }\n            }\n\n            return true;\n        }\n\n        // Returns true if this this function uses the event and propagation of the drag should be stopped after this\n        internal static bool GetDragVisualModeAndShowMenuWithReplaceMenuItemsWhenNeeded(GameObject droppedUponGameObject, bool draggingUpon, bool perform, bool addAsChildMenuItem, bool dragInHierarchy, out DragAndDropVisualMode cursorVisualMode)\n        {\n            cursorVisualMode = DragAndDropVisualMode.None;\n\n            GameObject prefabAsset = TryGetSinglePrefabAssetFromDraggedObjects();\n            if (prefabAsset == null)\n                return false;\n\n            if (Event.current == null)\n                return false;\n\n            if (!dragInHierarchy || EditorGUI.actionKey)\n            {\n                if (!draggingUpon)\n                {\n                    cursorVisualMode = DragAndDropVisualMode.Rejected;\n                    return true;\n                }\n\n                List<GameObject> listOfInstanceRoots;\n                List<GameObject> listOfPlainGameObjects;\n                FindGameObjectsToReplace(droppedUponGameObject, out listOfPlainGameObjects, out listOfInstanceRoots);\n\n                if (listOfInstanceRoots.Count == 0 && listOfPlainGameObjects.Count == 0)\n                {\n                    cursorVisualMode = DragAndDropVisualMode.Rejected;\n                    return true;\n                }\n\n                cursorVisualMode = DragAndDropVisualMode.Link;\n\n                if (perform)\n                {\n                    if (!dragInHierarchy && listOfInstanceRoots.Count > 0 && listOfPlainGameObjects.Count == 0 && !HasInstancesAnyOverrides(listOfInstanceRoots))\n                    {\n                        return false; // don't show the drag menu when we know we will only have one menuitem over the objectfield in the Inspector\n                    }\n\n                    Event.current.Use();\n\n                    var menu = new GenericMenu();\n\n                    AddReplaceMenuItemsToMenuBasedOnCurrentSelection(menu, \"\", droppedUponGameObject, listOfInstanceRoots, listOfPlainGameObjects, prefabAsset);\n                    if (addAsChildMenuItem)\n                    {\n                        menu.AddSeparator(\"\");\n                        menu.AddItem(EditorGUIUtility.TrTextContent(\"Add as Child\"), false, MenuActionForInstantiateDraggedPrefabAsChild, (droppedUponGameObject, prefabAsset));\n                    }\n                    menu.AddSeparator(\"\");\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Cancel\"), false, () => {/*nop*/ });\n                    menu.ShowAsContext();\n                }\n                return true;\n            }\n            return false;\n        }\n\n        internal static GameObject TryGetSinglePrefabAssetFromDraggedObjects()\n        {\n            var draggedObjects = DragAndDrop.objectReferences;\n            GameObject prefabAsset = null;\n            foreach (var draggedObject in draggedObjects)\n            {\n                if (draggedObject is GameObject && EditorUtility.IsPersistent(draggedObject))\n                {\n                    if (prefabAsset == null)\n                        prefabAsset = (GameObject)draggedObject;\n                    else\n                        return null;\n                }\n            }\n            return prefabAsset;\n        }\n\n        internal static void FindGameObjectsToReplace(GameObject droppedUponGameObject, out List<GameObject> listOfPlainGameObjects, out List<GameObject> listOfInstanceRoots)\n        {\n            listOfInstanceRoots = new List<GameObject>();\n            listOfPlainGameObjects = new List<GameObject>();\n\n            // Dropping on single\n            if (droppedUponGameObject != null && !Selection.gameObjects.Contains(droppedUponGameObject))\n            {\n                if (PrefabUtility.IsOutermostPrefabInstanceRoot(droppedUponGameObject))\n                    listOfInstanceRoots.Add(droppedUponGameObject);\n                else if (!PrefabUtility.IsPartOfAnyPrefab(droppedUponGameObject))\n                    listOfPlainGameObjects.Add(droppedUponGameObject);\n\n                return;\n            }\n\n            // Dropping on selection: need to find the common roots\n            var selectedGameObjects = Selection.GetFiltered<GameObject>(SelectionMode.TopLevel | SelectionMode.ExcludePrefab | SelectionMode.Editable);\n            foreach (var go in selectedGameObjects)\n            {\n                if (PrefabUtility.IsOutermostPrefabInstanceRoot(go))\n                    listOfInstanceRoots.Add(go);\n                else if (!PrefabUtility.IsPartOfNonAssetPrefabInstance(go))\n                    listOfPlainGameObjects.Add(go);\n            }\n        }\n\n        static void MenuActionForConvertAndReplacePrefabInstance(object userData)\n        {\n            var args = ((GameObject, List<GameObject>, PrefabOverridesOptions, List<GameObject>, bool, GameObject))userData;\n            var contextGameObject = args.Item1;\n            var droppedOnInstances = args.Item2;\n            var overrideOptionsOnReplace = args.Item3;\n            var droppedOnGameObjects = args.Item4;\n            var createOverridesOnConvert = args.Item5;\n            var prefabAssetRoot = args.Item6;\n\n            Undo.IncrementCurrentGroup();\n\n            if (droppedOnInstances.Count > 0)\n                PrefabUtility.ReplacePrefabAssetOfPrefabInstances(droppedOnInstances.ToArray(), prefabAssetRoot, GetPrefabReplacingSettingsForUI(overrideOptionsOnReplace), InteractionMode.UserAction);\n            if (droppedOnGameObjects.Count > 0)\n                PrefabUtility.ConvertToPrefabInstances(droppedOnGameObjects.ToArray(), prefabAssetRoot, GetConvertToPrefabInstanceSettingsForUI(createOverridesOnConvert), InteractionMode.UserAction);\n\n            if (contextGameObject != null && !Selection.Contains(contextGameObject))\n                Selection.activeGameObject = contextGameObject;\n\n            Undo.IncrementCurrentGroup();\n        }\n\n        static void MenuActionForInstantiateDraggedPrefabAsChild(object userData)\n        {\n            var args = ((GameObject, GameObject))userData;\n            var droppedUponGameObject = args.Item1;\n            var prefabAssetRoot = args.Item2;\n\n            Undo.IncrementCurrentGroup();\n\n            var childInstanceIDs = GetChildrenInstanceIDs(droppedUponGameObject);\n            PrefabUtility.InstantiateDraggedPrefabUpon(droppedUponGameObject, prefabAssetRoot);\n            var newChildren = GetNewChildren(droppedUponGameObject, childInstanceIDs);\n            if (newChildren != null && newChildren.Count > 0)\n                Selection.instanceIDs = newChildren.ToArray();\n\n            Undo.IncrementCurrentGroup();\n        }\n\n        static HashSet<int> GetChildrenInstanceIDs(GameObject parent)\n        {\n            var childInstanceIDs = new HashSet<int>();\n            var transform = parent.transform;\n            var childCount = transform.childCount;\n            for (int i = 0; i < childCount; i++)\n            {\n                var childInstanceID = transform.GetChild(i).gameObject.GetInstanceID();\n                childInstanceIDs.Add(childInstanceID);\n            }\n            return childInstanceIDs;\n        }\n\n        static List<int> GetNewChildren(GameObject parent, HashSet<int> oldChildren)\n        {\n            var newChildren = new List<int>();\n            var transform = parent.transform;\n            var childCount = transform.childCount;\n            for (int i = 0; i < childCount; i++)\n            {\n                var childInstanceID = transform.GetChild(i).gameObject.GetInstanceID();\n                if (!oldChildren.Contains(childInstanceID))\n                    newChildren.Add(childInstanceID);\n            }\n            return newChildren;\n        }\n\n        public static ConvertToPrefabInstanceSettings GetConvertToPrefabInstanceSettingsForUI(bool createOverrides)\n        {\n            return new ConvertToPrefabInstanceSettings\n            {\n                objectMatchMode = ObjectMatchMode.ByHierarchy,\n                componentsNotMatchedBecomesOverride = createOverrides,\n                gameObjectsNotMatchedBecomesOverride = createOverrides,\n                recordPropertyOverridesOfMatches = createOverrides,\n                changeRootNameToAssetName = true,\n                logInfo = false\n            };\n        }\n\n        public static PrefabReplacingSettings GetPrefabReplacingSettingsForUI(PrefabOverridesOptions prefabOverridesOptions)\n        {\n            return new PrefabReplacingSettings\n            {\n                objectMatchMode = ObjectMatchMode.ByHierarchy,\n                prefabOverridesOptions = prefabOverridesOptions,\n                changeRootNameToAssetName = true,\n                logInfo = false\n            };\n        }\n\n    }\n\n    internal static class PrefabReplaceSettingsUserPreferences\n    {\n        static SavedInt m_ObjectMatchMode = new SavedInt(\"PrefabReplace.ObjectMatchMode\", (int)ObjectMatchMode.ByHierarchy);\n        static SavedBool m_GameObjectsNotMatchedBecomesOverride = new SavedBool(\"PrefabReplace.GameObjectsNotMatchedBecomesOverride\", true);\n        static SavedBool m_ComponentsNotMatchedBecomesOverride = new SavedBool(\"PrefabReplace.ComponentsNotMatchedBecomesOverride\", true);\n        static SavedInt m_ClearOverridesOptions = new SavedInt(\"PrefabReplace.ClearOverridesOptions\", (int)PrefabOverridesOptions.KeepAllPossibleOverrides);\n        static SavedBool m_UseAssetName = new SavedBool(\"PrefabReplace.UseAssetName\", true);\n        static SavedBool m_LogInfo = new SavedBool(\"PrefabReplace.LogInfo\", false);\n\n        public static ObjectMatchMode objectMatchMode { get { return (ObjectMatchMode)m_ObjectMatchMode.value; } set { m_ObjectMatchMode.value = Convert.ToInt32(value); } }\n        public static PrefabOverridesOptions prefabOverridesOptions { get { return (PrefabOverridesOptions)m_ClearOverridesOptions.value; } set { m_ClearOverridesOptions.value = Convert.ToInt32(value); } }\n\n        public static bool gameObjectsNotMatchedBecomesOverride { get { return m_GameObjectsNotMatchedBecomesOverride.value; } set { m_GameObjectsNotMatchedBecomesOverride.value = value; } }\n        public static bool componentsNotMatchedBecomesOverride { get { return m_ComponentsNotMatchedBecomesOverride.value; } set { m_ComponentsNotMatchedBecomesOverride.value = value; } }\n        public static bool useAssetName { get { return m_UseAssetName.value; } set { m_UseAssetName.value = value; } }\n        public static bool logInfo { get { return m_LogInfo.value; } set { m_LogInfo.value = value; } }\n\n        public static ConvertToPrefabInstanceSettings GetConvertToPrefabInstancePreferences()\n        {\n            return new ConvertToPrefabInstanceSettings\n            {\n                objectMatchMode = objectMatchMode,\n                componentsNotMatchedBecomesOverride = componentsNotMatchedBecomesOverride,\n                gameObjectsNotMatchedBecomesOverride = gameObjectsNotMatchedBecomesOverride,\n                changeRootNameToAssetName = useAssetName,\n                logInfo = logInfo\n            };\n        }\n\n        public static PrefabReplacingSettings GetPrefabReplacingPreferences()\n        {\n            return new PrefabReplacingSettings\n            {\n                objectMatchMode = objectMatchMode,\n                prefabOverridesOptions = prefabOverridesOptions,\n                logInfo = logInfo\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Prefabs/PrefabUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing System.IO;\nusing UnityEditor.Utils;\nusing UnityEngine.Bindings;\nusing Object = UnityEngine.Object;\nusing UnityEngine.SceneManagement;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/Prefabs/Prefab.h\")]\n    [NativeHeader(\"Editor/Src/Prefabs/PrefabCreation.h\")]\n    [NativeHeader(\"Editor/Src/Prefabs/PrefabConnection.h\")]\n    [NativeHeader(\"Editor/Src/Prefabs/PrefabInstance.h\")]\n    [NativeHeader(\"Editor/Src/Prefabs/ReplacePrefabInstance.h\")]\n    [NativeHeader(\"Editor/Mono/Prefabs/PrefabUtility.bindings.h\")]\n    public sealed partial class PrefabUtility\n    {\n        [StaticAccessor(\"PrefabInstance\", StaticAccessorType.DoubleColon)]\n        extern internal static int defaultOverridesCount { get; }\n\n        [StaticAccessor(\"PrefabInstance\", StaticAccessorType.DoubleColon)]\n        extern internal static int defaultOverridesCountUsingRectTransform { get; }\n\n        // Returns the corresponding GameObject/Component from /source/, or null if it can't be found.\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static Object GetCorrespondingObjectFromSource_internal([NotNull] Object obj);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static Object GetCorrespondingObjectFromSourceInAsset_internal([NotNull] Object obj, [NotNull] Object prefabAssetHandle);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static Object GetCorrespondingObjectFromSourceAtPath_internal([NotNull] Object obj, string prefabAssetPath);\n\n        // Retrieves the prefab object representation.\n        [Obsolete(\"Use GetPrefabInstanceHandle for Prefab instances. Handles for Prefab Assets has been discontinued.\")]\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern public static Object GetPrefabObject(Object targetObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern public static Object GetPrefabInstanceHandle(Object instanceComponentOrGameObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static string GetAssetPathOfSourcePrefab(Object targetObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static Object GetPrefabAssetHandle(Object assetComponentOrGameObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern public static bool HasManagedReferencesWithMissingTypes(Object assetComponentOrGameObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static GameObject GetPrefabInstanceRootGameObject(Object instanceComponentOrGameObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static GameObject GetPrefabAssetRootGameObject(Object assetComponentOrGameObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static bool HasObjectOverride(Object componentOrGameObject, bool includeDefaultOverrides = false);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static bool HasPrefabInstanceUnusedOverrides_Internal(GameObject gameObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static int GetPrefabInstanceUnusedRemovedComponentCount_Internal(GameObject gameObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static int GetPrefabInstanceUnusedRemovedGameObjectCount_Internal([NotNull] GameObject gameObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static string TryGetCurrentPropertyPathFromOldPropertyPath_Internal(GameObject gameObject, Object target, string propertyPath);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static bool HasPrefabInstanceNonDefaultOverrides_CachedForUI_Internal(GameObject gameObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static bool HasPrefabInstanceUnusedOverrides_CachedForUI_Internal(GameObject gameObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static void ClearPrefabInstanceNonDefaultOverridesCache_Internal(GameObject gameObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static void ClearPrefabInstanceUnusedOverridesCache_Internal(GameObject gameObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static InstanceOverridesInfo GetPrefabInstanceOverridesInfo_Internal(GameObject gameObject);\n\n        // Extract all modifications that are applied to the prefab instance compared to the parent prefab.\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern public static PropertyModification[] GetPropertyModifications(Object targetPrefab);\n\n        // Assigns all modifications that are applied to the prefab instance compared to the parent prefab.\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern public static void SetPropertyModifications(Object targetPrefab, PropertyModification[] modifications);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern internal static bool HasApplicableObjectOverridesForTarget([NotNull] Object targetPrefab, [NotNull] Object applyTarget, bool includeDefaultOverrides);\n\n        [NativeMethod(\"PrefabUtilityBindings::FindNearestInstanceOfAsset\", IsFreeFunction = true)]\n        extern internal static GameObject FindNearestInstanceOfAsset(Object componentOrGameObjectInstance, Object prefab);\n\n        [FreeFunction]\n        extern public static bool HasPrefabInstanceAnyOverrides(GameObject instanceRoot, bool includeDefaultOverrides);\n\n        // Instantiate an asset that is referenced by a prefab and use it on the prefab instance.\n        [Obsolete(\"InstantiateAttachedAsset is deprecated\")]\n        public static Object InstantiateAttachedAsset(Object targetObject) { return null; }\n\n        // Force record property modifications by comparing against the parent prefab.\n        [FreeFunction]\n        extern public static void RecordPrefabInstancePropertyModifications([NotNull] Object targetObject);\n\n        // Force re-merging all prefab instances of this prefab.\n        [Obsolete(\"MergeAllPrefabInstances is deprecated. Prefabs are merged automatically. There is no need to call this method.\")]\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern public static void MergeAllPrefabInstances(Object targetObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern private static void MergePrefabInstance_internal([NotNull] Object gameObjectOrComponent);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern private static MergeStatus GetMergeStatus(GameObject componentOrGameObject);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern private static GameObject[] FindAllInstancesOfPrefab_internal([NotNull] GameObject prefabRoot, int sceneHandle);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern private static GameObject[] UnpackPrefabInstanceAndReturnNewOutermostRoots_internal(GameObject instanceRoot, PrefabUnpackMode unpackMode);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern static private Object InstantiatePrefab_internal(Object target, Scene destinationScene, Transform parent);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern static private bool ReplacePrefabAssetOfPrefabInstance_Internal([NotNull] GameObject instanceRoot, [NotNull] GameObject assetRootRoot, PrefabReplacingSettings settings);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern static private bool ConvertToPrefabInstance_Internal([NotNull] GameObject plainGameObject, [NotNull] GameObject assetRootRoot, ConvertToPrefabInstanceSettings settings);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern static private bool InstantiateDraggedPrefabUpon_Internal([NotNull] GameObject draggedUponGameObject, [NotNull] GameObject assetRootRoot);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern private static GameObject LoadPrefabContentsIntoPreviewScene_Internal(string prefabPath, Scene scene);\n\n        public static void LoadPrefabContentsIntoPreviewScene(string prefabPath, Scene scene)\n        {\n            LoadPrefabContentsIntoPreviewScene_Internal(prefabPath, scene);\n        }\n\n        public static void LoadPrefabContentsIntoPreviewScene(string prefabPath, Scene scene, out GameObject rootGameObject)\n        {\n            rootGameObject = LoadPrefabContentsIntoPreviewScene_Internal(prefabPath, scene);\n        }\n\n        [Obsolete(\"Use ConvertToPrefabInstance() or ReplacePrefabAssetOfPrefabInstance() which has settings for better control.\")]\n        public static GameObject ConnectGameObjectToPrefab(GameObject go, GameObject sourcePrefab)\n        {\n            if (GetPrefabInstanceStatus(go) == PrefabInstanceStatus.NotAPrefab)\n            {\n                var settings = new ConvertToPrefabInstanceSettings();\n                ConvertToPrefabInstance(go, sourcePrefab, settings, InteractionMode.AutomatedAction);\n            }\n            else if (IsOutermostPrefabInstanceRoot(go))\n            {\n                var settings = new PrefabReplacingSettings();\n                ReplacePrefabAssetOfPrefabInstance(go, sourcePrefab, settings, InteractionMode.AutomatedAction);\n            }\n\n            return go;\n        }\n\n        // Returns the topmost game object that has the same prefab parent as /target/\n        [FreeFunction]\n        [Obsolete(\"FindRootGameObjectWithSameParentPrefab is deprecated, please use GetOutermostPrefabInstanceRoot instead.\")]\n        extern public static GameObject FindRootGameObjectWithSameParentPrefab([NotNull] GameObject target);\n\n        // Returns root game object of the prefab instance. Given an instance object the function finds the prefab\n        // and uses the prefab root game object to find the matching instance root game object\n        [NativeMethod(\"FindInstanceRootGameObject\", IsFreeFunction = true)]\n        [Obsolete(\"FindValidUploadPrefabInstanceRoot is deprecated, please use GetOutermostPrefabInstanceRoot instead.\")]\n        extern public static GameObject FindValidUploadPrefabInstanceRoot([NotNull] GameObject target);\n\n        // Resets the properties of the component or game object to the parent prefab state\n        [Obsolete(\"Use RevertObjectOverride.\")]\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern public static bool ResetToPrefabState(Object obj);\n\n        // Resets the properties of the component or game object to the parent prefab state\n        [NativeMethod(\"PrefabUtilityBindings::ResetToPrefabState\", IsFreeFunction = true)]\n        extern private static bool RevertObjectOverride_Internal(Object obj);\n\n        [FreeFunction]\n        extern public static bool IsAddedComponentOverride([NotNull] Object component);\n\n        // Resets the properties of all objects in the prefab, including child game objects and components that were added to the prefab instance\n        [Obsolete(\"Use the overload that takes an InteractionMode parameter.\")]\n        [FreeFunction]\n        extern public static bool RevertPrefabInstance([NotNull] GameObject go);\n\n        // Resets the properties of all objects in the prefab, including child game objects and components that were added to the prefab instance\n        [NativeMethod(\"RevertPrefabInstance\", IsFreeFunction = true)]\n        extern private static bool RevertPrefabInstance_Internal([NotNull] GameObject go);\n\n        // Helper function to find the prefab root of an object\n        [FreeFunction]\n        [Obsolete(\"Use GetOutermostPrefabInstanceRoot if source is a Prefab instance or source.transform.root.gameObject if source is a Prefab Asset object.\")]\n        extern public static GameObject FindPrefabRoot([NotNull] GameObject source);\n\n        internal static GameObject CreateVariant(GameObject assetRoot, string path)\n        {\n            if (assetRoot == null)\n                throw new ArgumentNullException(\"The inputObject is null\");\n\n            if (!IsPartOfPrefabAsset(assetRoot))\n                throw new ArgumentException(\"Given input object is not a prefab asset\");\n\n            if (assetRoot.transform.root.gameObject != assetRoot)\n                throw new ArgumentException(\"Object to create variant from has to be a Prefab root\");\n\n            if (path == null)\n                throw new ArgumentNullException(\"The path is null\");\n\n            var assetRootObjectPath = AssetDatabase.GetAssetPath(assetRoot);\n            if (Paths.AreEqual(path, assetRootObjectPath, true))\n                throw new ArgumentException(\"Creating a variant of an object into the source file of the input object is not allowed\");\n\n            if (!Paths.IsValidAssetPath(path, \".prefab\"))\n                throw new ArgumentException(\"Given path is not valid: '\" + path + \"'\");\n\n            return CreateVariant_Internal(assetRoot, path);\n        }\n\n        [NativeMethod(\"CreateVariant\", IsFreeFunction = true)]\n        extern private static GameObject CreateVariant_Internal([NotNull] GameObject original, string path);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern private static GameObject SavePrefab_Internal([NotNull] GameObject root, string path, bool connectToInstance, out bool success);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static GameObject ApplyPrefabInstance_Internal([NotNull] GameObject root);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern private static GameObject SaveAsPrefabAsset_Internal([NotNull] GameObject root, string path, out bool success);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern private static GameObject SaveAsPrefabAssetAndConnect_Internal([NotNull] GameObject root, string path, out bool success);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern private static GameObject SavePrefabAsset_Internal([NotNull] GameObject root, out bool success);\n\n        internal static void AddGameObjectsToPrefabAndConnect(GameObject[] gameObjects, Object targetPrefab)\n        {\n            if (gameObjects == null)\n                throw new ArgumentNullException(\"gameObjects\");\n\n            if (gameObjects.Length == 0)\n                throw new ArgumentException(\"gameObjects array is empty\");\n\n            if (targetPrefab == null)\n                throw new ArgumentNullException(\"targetPrefab\");\n\n            if (!PrefabUtility.IsPartOfPrefabAsset(targetPrefab))\n                throw new ArgumentException(\"Target Prefab has to be a Prefab Asset\");\n\n            Object targetPrefabInstance = null;\n\n            var targetPrefabObject = PrefabUtility.GetPrefabAssetHandle(targetPrefab);\n\n            foreach (GameObject go in gameObjects)\n            {\n                if (go == null)\n                    throw new ArgumentException(\"GameObject in input 'gameObjects' array is null\");\n\n                if (EditorUtility.IsPersistent(go))  // Prefab asset\n                    throw new ArgumentException(\"Game object is part of a prefab\");\n\n                var parentPrefabInstance = GetParentPrefabInstance(go);\n                if (parentPrefabInstance == null)\n                    throw new ArgumentException(\"GameObject is not (directly) parented under a target Prefab instance.\");\n\n                if (targetPrefabInstance == null)\n                {\n                    targetPrefabInstance = parentPrefabInstance;\n                    if (!IsPrefabInstanceObjectOf(go.transform.parent, targetPrefabObject))\n                        throw new ArgumentException(\"GameObject is not parented under a target Prefab instance.\");\n                }\n                else\n                {\n                    if (parentPrefabInstance != targetPrefabInstance)\n                    {\n                        throw new ArgumentException(\"GameObjects must be parented under the same Prefab instance.\");\n                    }\n                }\n\n                if (PrefabUtility.IsPartOfNonAssetPrefabInstance(go))\n                {\n                    var correspondingGO = PrefabUtility.GetCorrespondingObjectFromSource(go);\n                    var correspondingGOPrefabObject = PrefabUtility.GetPrefabAssetHandle(correspondingGO);\n                    if (targetPrefabObject == correspondingGOPrefabObject)\n                        throw new ArgumentException(\"GameObject is already part of target prefab\");\n                }\n            }\n\n            string prefabGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(targetPrefab));\n            if (!VerifyNestingFromScript(gameObjects, prefabGUID, null))\n                throw new ArgumentException(\"Cyclic nesting detected\");\n\n            AddGameObjectsToPrefabAndConnect_Internal(gameObjects, targetPrefab);\n        }\n\n        [NativeMethod(\"AddGameObjectsToPrefabAndConnect\", IsFreeFunction = true)]\n        extern private static void AddGameObjectsToPrefabAndConnect_Internal([NotNull] GameObject[] gameObjects, [NotNull] Object prefab);\n\n        [NativeMethod(\"VerifyNestingFromScript\", IsFreeFunction = true)]\n        extern private static bool VerifyNestingFromScript([NotNull] GameObject[] gameObjects, [NotNull] string targetPrefabGUID, Object prefabInstance);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern internal static Component[] GetRemovedComponents([NotNull] Object prefabInstance);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern static void SetRemovedComponents([NotNull] Object prefabInstance, [NotNull] Component[] removedComponents);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern internal static GameObject[] GetRemovedGameObjects([NotNull] Object prefabInstance);\n\n        [StaticAccessor(\"PrefabUtilityBindings\", StaticAccessorType.DoubleColon)]\n        [NativeThrows]\n        extern static void SetRemovedGameObjects([NotNull] Object prefabInstance, [NotNull] GameObject[] removedGameObjects);\n\n        // Returns true if the object is part of a any type of prefab, asset or instance\n        [FreeFunction]\n        extern public static bool IsPartOfAnyPrefab([NotNull] Object componentOrGameObject);\n\n        [FreeFunction]\n        extern internal static void SetHasSubscribersToAllowRecordingPrefabPropertyOverrides(bool hasSubscribers);\n\n        // Returns true if the object is an asset,\n        // does not matter if the asset is a regular prefab, a variant or Model\n        // Is false for all non-persistent objects\n        [FreeFunction]\n        extern public static bool IsPartOfPrefabAsset([NotNull] Object componentOrGameObject);\n\n        // Returns true if the object is an instance of a prefab,\n        // regardless of whether the instance is a regular prefab, a variant or model.\n        // Also returns if the asset is missing.\n        // Is also true for prefab instances inside persistent prefab assets -\n        // use IsPartOfNonAssetPrefabInstance to exclude those.\n        [FreeFunction]\n        extern public static bool IsPartOfPrefabInstance([NotNull] Object componentOrGameObject);\n\n        // Returns true if the object is an instance of a prefab,\n        // regardless of whether the instance is a regular prefab, a variant or model.\n        // Also returns true if the asset is missing.\n        // Is false for prefab instances inside persistent prefab assets -\n        // use IsPartOfPrefabInstance to include those.\n        // Note that prefab instances in prefab mode are not assets/persistent since technically,\n        // the object edited in Prefab Mode is not the persistent prefab asset itself.\n        [FreeFunction]\n        extern public static bool IsPartOfNonAssetPrefabInstance([NotNull] Object componentOrGameObject);\n\n        // We need a version of IsPartOfNonAssetPrefabInstance that uses an instanceID in order to handle missing monobehaviors\n        // which leads to managed null references (unity null) even though we have a native object. See handling for missing\n        // scripts for Prefab instances in GenericInspector.cs\n        [FreeFunction]\n        extern internal static bool IsInstanceIDPartOfNonAssetPrefabInstance(int componentOrGameObjectInstanceID);\n\n        // Returns true if the object is from a regular prefab or instance of regular prefab\n        [FreeFunction]\n        extern public static bool IsPartOfRegularPrefab([NotNull] Object componentOrGameObject);\n\n        // Returns true if the object is from a model prefab or instance of model prefab\n        [FreeFunction]\n        extern public static bool IsPartOfModelPrefab([NotNull] Object componentOrGameObject);\n\n        // Return true if the object is part of a Variant no matter if the object is an instance or asset object\n        [FreeFunction]\n        extern public static bool IsPartOfVariantPrefab([NotNull] Object componentOrGameObject);\n\n        // Returns true if the object is from a Prefab Asset which is not editable, or an instance of such a Prefab\n        // Examples are Model Prefabs and Prefabs in read-only folders.\n        [FreeFunction]\n        extern public static bool IsPartOfImmutablePrefab([NotNull] Object componentOrGameObject);\n\n        [FreeFunction]\n        extern public static bool IsPrefabAssetMissing([NotNull] Object instanceComponentOrGameObject);\n\n        [FreeFunction]\n        extern public static GameObject GetOutermostPrefabInstanceRoot([NotNull] Object componentOrGameObject);\n\n        [FreeFunction]\n        extern public static GameObject GetNearestPrefabInstanceRoot([NotNull] Object componentOrGameObject);\n\n        [FreeFunction]\n        extern internal static GameObject GetOriginalSourceOrVariantRoot([NotNull] Object instanceOrAsset);\n\n        [FreeFunction]\n        extern public static GameObject GetOriginalSourceRootWhereGameObjectIsAdded([NotNull] GameObject gameObject);\n\n        [NativeMethod(\"PrefabUtilityBindings::ApplyPrefabAddedComponent\", IsFreeFunction = true, ThrowsException = true)]\n        extern private static void ApplyAddedComponent([NotNull] Component addedComponent, [NotNull] Object applyTargetPrefabObject);\n\n        [NativeMethod(\"PrefabUtilityBindings::IsDefaultOverride\", IsFreeFunction = true)]\n        extern public static bool IsDefaultOverride(PropertyModification modification);\n\n        [NativeMethod(\"PrefabUtilityBindings::IsDefaultOverridePropertyPath\", IsFreeFunction = true)]\n        extern internal static bool IsDefaultOverridePropertyPath(string propertyPath);\n\n        [FreeFunction]\n        extern internal static bool CheckIfAddingPrefabWouldResultInCyclicNesting(Object prefabAssetThatIsAddedTo, Object prefabAssetThatWillBeAdded);\n\n        [FreeFunction]\n        extern internal static bool WasCreatedAsPrefabInstancePlaceholderObject(Object componentOrGameObject);\n\n        [FreeFunction]\n        extern internal static void ShowCyclicNestingWarningDialog();\n\n        [NativeMethod(\"PrefabUtilityBindings::GetVariantParentGUID_Internal\", IsFreeFunction = true, ThrowsException = true)]\n        extern internal static string GetVariantParentGUID(int prefabAssetInstanceID);\n\n        internal static string GetVariantParentGUID(GameObject prefabAsset)\n        {\n            if (prefabAsset == null)\n                throw new ArgumentNullException(nameof(prefabAsset));\n            return GetVariantParentGUID(prefabAsset.GetInstanceID());\n        }\n\n        [FreeFunction]\n        extern internal static bool IsPathInStreamingAssets(string path);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Prefabs/PrefabUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEditor.Utils;\nusing UnityEngine.SceneManagement;\nusing UnityEditor.SceneManagement;\nusing Object = UnityEngine.Object;\nusing RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute;\nusing UnityEngine.Bindings;\nusing UnityEngine.Assertions;\n\nnamespace UnityEditor\n{\n    public enum PrefabAssetType\n    {\n        NotAPrefab = 0,\n        Regular = 1,\n        Model = 2,\n        Variant = 3,\n        MissingAsset = 4\n    }\n\n    public enum PrefabInstanceStatus\n    {\n        NotAPrefab = 0,\n        Connected = 1,\n        [Obsolete(\"PrefabInstanceStatus.Disconnected has been deprecated and is not used. Prefabs can not be in a disconnected state.\")]\n        Disconnected = 2,\n        MissingAsset = 3\n    }\n\n    // Enum for the PrefabUtility.UnpackPrefabInstance function.\n    public enum PrefabUnpackMode\n    {\n        OutermostRoot = 0,\n        Completely = 1,\n    }\n\n    // The type of a prefab object as returned by PrefabUtility.GetPrefabType.\n    [Obsolete(\"PrefabType no longer tells everything about Prefab instance.\")]\n    public enum PrefabType\n    {\n        // The object is not a prefab nor an instance of a prefab.\n        None = 0,\n        // The object is a user created prefab asset.\n        Prefab = 1,\n        // The object is an imported 3D model asset.\n        ModelPrefab = 2,\n        // The object is an instance of a user created prefab.\n        PrefabInstance = 3,\n        // The object is an instance of an imported 3D model.\n        ModelPrefabInstance = 4,\n        // The object was an instance of a prefab, but the original prefab could not be found.\n        MissingPrefabInstance = 5,\n        // The object is an instance of a user created prefab, but the connection is broken.\n        [Obsolete(\"PrefabType.DisconnectedPrefabInstance has been deprecated and is not used. Prefabs can not be in a disconnected state.\")]\n        DisconnectedPrefabInstance = 6,\n        // The object is an instance of an imported 3D model, but the connection is broken.\n        [Obsolete(\"PrefabType.DisconnectedModelPrefabInstance has been deprecated and is not used. Prefabs can not be in a disconnected state.\")]\n        DisconnectedModelPrefabInstance = 7,\n    }\n\n    // Flags for the PrefabUtility.ReplacePrefab function.\n    [Flags]\n    [Obsolete(\"This has turned into the more explicit APIs, SavePrefabAsset, SaveAsPrefabAsset, SaveAsPrefabAssetAndConnect\")]\n    public enum ReplacePrefabOptions\n    {\n        // Replaces prefabs by matching pre-existing connections to the prefab.\n        Default = 0,\n        // Connects the passed objects to the prefab after uploading the prefab.\n        ConnectToPrefab = 1,\n        // Replaces the prefab using name based lookup in the transform hierarchy.\n        ReplaceNameBased = 2,\n    }\n\n    public enum ObjectMatchMode\n    {\n        NoMatchingPerformed = 0,\n        ByName = 1,\n        ByHierarchy = 2\n    }\n\n    [Flags]\n    public enum PrefabOverridesOptions\n    {\n        KeepAllPossibleOverrides = 0,\n        ClearNonDefaultPropertyOverrides = 1,\n        ClearAddedComponents = 2,\n        ClearRemovedComponents = 4,\n        ClearAddedGameObjects = 8,\n        ClearRemovedGameObjects = 16,\n        ClearAllOverridesExceptPropertyOverrides = ClearAddedComponents + ClearRemovedComponents + ClearAddedGameObjects + ClearRemovedGameObjects,\n        ClearAllNonDefaultOverrides = ClearNonDefaultPropertyOverrides + ClearAddedComponents + ClearRemovedComponents + ClearAddedGameObjects + ClearRemovedGameObjects,\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    [NativeAsStruct]\n    public class PrefabReplacingSettings\n    {\n        public ObjectMatchMode objectMatchMode { get; set; } = ObjectMatchMode.ByName;\n        public PrefabOverridesOptions prefabOverridesOptions { get; set; } = PrefabOverridesOptions.KeepAllPossibleOverrides;\n        public bool changeRootNameToAssetName { get; set; } = true;\n        public bool logInfo { get; set; } = false;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    [NativeAsStruct]\n    public class ConvertToPrefabInstanceSettings\n    {\n        public ObjectMatchMode objectMatchMode { get; set; } = ObjectMatchMode.ByHierarchy;\n        public bool componentsNotMatchedBecomesOverride { get; set; } = false;\n        public bool gameObjectsNotMatchedBecomesOverride { get; set; } = false;\n        public bool recordPropertyOverridesOfMatches { get; set; } = false;\n        public bool changeRootNameToAssetName { get; set; } = true;\n        public bool logInfo { get; set; } = false;\n    }\n\n    // This must match C++ MergeStatus\n    internal enum MergeStatus\n    {\n        NotMerged,                       // Initial state, before trying to merge\n        NormalMerge,                     // Prefab source was found and merged successfully\n        MergedAsMissing,                 // Prefab source was missing and the Prefab couldn't be merged\n        MergedAsMissingWithSceneBackup   // Prefab source was missing, but Prefab data was found in the scene file - no merging was done\n    }\n\n    internal struct PropertyValueOriginInfo\n    {\n        public GameObject asset { get; private set; }\n        public string contextMenuText { get; private set; }\n        public string info { get; private set; }\n\n        public PropertyValueOriginInfo(GameObject asset, string contextMenuText, string info)\n        {\n            this.asset = asset;\n            this.contextMenuText = contextMenuText;\n            this.info = info;\n        }\n\n        public PropertyValueOriginInfo(string info)\n        {\n            asset = null;\n            contextMenuText = null;\n            this.info = info;\n        }\n    }\n\n    internal delegate void AddApplyMenuItemDelegate(GUIContent menuItem, Object sourceObject, Object instanceOrAssetObject);\n\n    public sealed partial class PrefabUtility\n    {\n        internal static class GameObjectStyles\n        {\n            public static Texture2D gameObjectIcon = EditorGUIUtility.LoadIconRequired(\"UnityEngine/GameObject Icon\");\n            public static Texture2D prefabIcon = EditorGUIUtility.LoadIconRequired(\"Prefab Icon\");\n        }\n\n        private const string kMaterialExtension = \".mat\";\n        internal const string kDummyPrefabStageRootObjectName = \"Prefab Mode in Context\";\n\n        [RequiredByNativeCode]\n        internal static void ExtractSelectedObjectsFromPrefab()\n        {\n            var assetsToReload = new HashSet<string>();\n            string folder = null;\n            foreach (var selectedObj in Selection.objects)\n            {\n                var path = AssetDatabase.GetAssetPath(selectedObj);\n\n                // use the first selected element as the basis for the folder path where all the materials will be extracted\n                if (folder == null)\n                {\n                    folder = EditorUtility.SaveFolderPanel(\"Select Materials Folder\", FileUtil.DeleteLastPathNameComponent(path), \"\");\n                    if (String.IsNullOrEmpty(folder))\n                    {\n                        // cancel the extraction if the user did not select a folder\n                        return;\n                    }\n\n                    folder = FileUtil.GetProjectRelativePath(folder);\n                }\n\n                // TODO: [bogdanc 3/6/2017] if we want this function really generic, we need to know what extension the new asset files should have\n                var extension = selectedObj is Material ? kMaterialExtension : String.Empty;\n                var newAssetPath = FileUtil.CombinePaths(folder, selectedObj.name) + extension;\n                newAssetPath = AssetDatabase.GenerateUniqueAssetPath(newAssetPath);\n\n                var error = AssetDatabase.ExtractAsset(selectedObj, newAssetPath);\n                if (String.IsNullOrEmpty(error))\n                {\n                    assetsToReload.Add(path);\n                }\n            }\n\n            foreach (var path in assetsToReload)\n            {\n                AssetDatabase.WriteImportSettingsIfDirty(path);\n                AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);\n            }\n        }\n\n        internal static void ExtractMaterialsFromAsset(Object[] targets, string destinationPath)\n        {\n            var assetsToReload = new HashSet<string>();\n            foreach (var t in targets)\n            {\n                var importer = t as AssetImporter;\n\n                var materials = AssetDatabase.LoadAllAssetsAtPath(importer.assetPath).Where(x => x.GetType() == typeof(Material)).ToArray();\n\n                foreach (var material in materials)\n                {\n                    var newAssetPath = FileUtil.CombinePaths(destinationPath, material.name) + kMaterialExtension;\n                    newAssetPath = AssetDatabase.GenerateUniqueAssetPath(newAssetPath);\n\n                    var error = AssetDatabase.ExtractAsset(material, newAssetPath);\n                    if (String.IsNullOrEmpty(error))\n                    {\n                        assetsToReload.Add(importer.assetPath);\n                    }\n                }\n            }\n\n            foreach (var path in assetsToReload)\n            {\n                AssetDatabase.WriteImportSettingsIfDirty(path);\n                AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);\n            }\n        }\n\n        static void ThrowExceptionIfNotValidPrefabInstanceObject(Object prefabInstanceObject, bool isApply)\n        {\n            if (!(prefabInstanceObject is GameObject || prefabInstanceObject is Component))\n                throw new ArgumentException(\"Calling apply or revert methods on an object which is not a GameObject or Component is not supported.\", nameof(prefabInstanceObject));\n            if (prefabInstanceObject == null)\n                throw new NullReferenceException(\"Cannot apply or revert object. Object is null.\");\n            if (!PrefabUtility.IsPartOfPrefabInstance(prefabInstanceObject))\n                throw new ArgumentException(\"Calling apply or revert methods on an object which is not part of a Prefab instance is not supported.\", nameof(prefabInstanceObject));\n\n            // We support revert operations on Prefab Assets, but not apply operations.\n            if (isApply)\n                ThrowExceptionIfInstanceIsPersistent(prefabInstanceObject);\n        }\n\n        static void ThrowExceptionIfAllPrefabInstanceObjectsAreInvalid(Object[] prefabInstanceObjects, bool isApply)\n        {\n            foreach (var obj in prefabInstanceObjects)\n            {\n                if (obj != null && (obj is GameObject || obj is Component) && IsPartOfPrefabInstance(obj) && !(isApply && EditorUtility.IsPersistent(obj)))\n                    return;\n            }\n\n            // Throw exception if all objects are invalid\n            throw new ArgumentException(\"Cannot apply or revert on any of the objects. Attempt with individual objects for details.\", nameof(prefabInstanceObjects));\n        }\n\n        static void ThrowExceptionIfInstanceIsPersistent(Object prefabInstanceObject)\n        {\n            if (EditorUtility.IsPersistent(prefabInstanceObject))\n                throw new ArgumentException(\"Calling apply methods on an instance which is part of a Prefab Asset is not supported.\", nameof(prefabInstanceObject));\n        }\n\n        public static GameObject[] FindAllInstancesOfPrefab(GameObject prefabRoot)\n        {\n            return FindAllInstancesOfPrefab_internal(prefabRoot, 0);\n        }\n\n        public static GameObject[] FindAllInstancesOfPrefab(GameObject prefabRoot, Scene scene)\n        {\n            if (!scene.IsValid())\n            {\n                throw new ArgumentException(\"Input scene is not valid: Could not be found.\");\n            }\n\n            return FindAllInstancesOfPrefab_internal(prefabRoot, scene.handle);\n        }\n\n        public static void MergePrefabInstance(GameObject instanceRoot)\n        {\n            MergePrefabInstance_internal(instanceRoot);\n        }\n\n        public static void RevertPrefabInstance(GameObject instanceRoot, InteractionMode action)\n        {\n            ThrowExceptionIfNotValidPrefabInstanceObject(instanceRoot, false);\n\n            GameObject prefabInstanceRoot = GetOutermostPrefabInstanceRoot(instanceRoot);\n\n            var actionName = \"Revert Prefab Instance\";\n\n            if (action == InteractionMode.UserAction)\n                Undo.RegisterFullObjectHierarchyUndo(prefabInstanceRoot, actionName);\n\n            RevertPrefabInstance_Internal(prefabInstanceRoot);\n\n            if (action == InteractionMode.UserAction)\n                Undo.FlushTrackedObjects();\n        }\n\n        public static void ApplyPrefabInstance(GameObject instanceRoot, InteractionMode action)\n        {\n            ApplyPrefabInstance(instanceRoot, action, undoFlushTrackedObjects:true);\n        }\n\n        static void ApplyPrefabInstance(GameObject instanceRoot, InteractionMode action, bool undoFlushTrackedObjects)\n        {\n            DateTime startTime = DateTime.UtcNow;\n\n            ThrowExceptionIfNotValidPrefabInstanceObject(instanceRoot, true);\n\n            using (new AtomicUndoScope())\n            {\n                GameObject prefabInstanceRoot = GetOutermostPrefabInstanceRoot(instanceRoot);\n\n                var actionName = \"Apply instance to prefab\";\n                Object correspondingSourceObject = GetCorrespondingObjectFromSource(prefabInstanceRoot);\n\n                if (action == InteractionMode.UserAction)\n                {\n                    Undo.RegisterFullObjectHierarchyUndo(correspondingSourceObject, actionName); // handles changes to existing objects and object what will be deleted but not objects that are created\n                    Undo.RegisterFullObjectHierarchyUndo(prefabInstanceRoot, actionName);\n                }\n\n                ApplyPrefabInstance(prefabInstanceRoot);\n\n                if (undoFlushTrackedObjects && action == InteractionMode.UserAction)\n                    Undo.FlushTrackedObjects();\n            }\n\n            Analytics.SendApplyEvent(\n                Analytics.ApplyScope.EntirePrefab,\n                instanceRoot,\n                null,\n                action,\n                startTime,\n                false\n            );\n        }\n\n        public static void ApplyPrefabInstances(GameObject[] instanceRoots, InteractionMode action)\n        {\n            if (instanceRoots == null)\n                throw new ArgumentNullException(nameof(instanceRoots));\n\n            foreach (var instanceRoot in instanceRoots)\n            {\n                ThrowExceptionIfNotValidPrefabInstanceObject(instanceRoot, true);\n            }\n\n            // Apply sequentially but import after all input have been saved to disk\n            AssetDatabase.StartAssetEditing();\n            try\n            {\n                foreach (var instanceRoot in instanceRoots)\n                {\n                    ApplyPrefabInstance(instanceRoot, action, undoFlushTrackedObjects:false);\n                }\n            }\n            finally\n            {\n                AssetDatabase.StopAssetEditing();\n            }\n\n            if (action == InteractionMode.UserAction)\n                Undo.FlushTrackedObjects(); // Needs to be called after StopAssetEditing() to fix UUM-6917\n        }\n\n        public static void RemoveUnusedOverrides(GameObject[] prefabInstances, InteractionMode action)\n        {\n            if (prefabInstances == null)\n                throw new ArgumentNullException(nameof(prefabInstances));\n\n            HashSet<GameObject> rootSet = new HashSet<GameObject>(prefabInstances.Length);\n            foreach (var gameObject in prefabInstances)\n            {\n                if (gameObject == null)\n                    throw new ArgumentException(\"Input array contains null elements.\", nameof(prefabInstances));\n                if (!PrefabUtility.IsPartOfPrefabInstance(gameObject))\n                    throw new ArgumentException(\"Input array contains objects which are not part of a Prefab instance.\", nameof(prefabInstances));\n\n                rootSet.Add(PrefabUtility.GetOutermostPrefabInstanceRoot(gameObject));\n            }\n            \n            InstanceOverridesInfo[] instanceOverridesInfos = rootSet.Select(PrefabUtility.GetPrefabInstanceOverridesInfo_Internal).ToArray();\n            PrefabUtility.RemovePrefabInstanceUnusedOverrides(instanceOverridesInfos, action);\n        }\n\n        private static void MapObjectReferencePropertyToSourceIfApplicable(SerializedProperty property, Object prefabSourceObject)\n        {\n            var referencedObject = property.objectReferenceValue;\n            if (referencedObject == null)\n            {\n                return;\n            }\n            referencedObject = GetCorrespondingObjectFromSourceInAsset(referencedObject, prefabSourceObject);\n            if (referencedObject != null)\n            {\n                property.objectReferenceValue = referencedObject;\n            }\n        }\n\n        static bool WarnIfInAnimationMode(OverrideOperation overrideOperation, InteractionMode action)\n        {\n            if (!AnimationMode.InAnimationMode())\n                return false;\n\n            if (action == InteractionMode.AutomatedAction)\n            {\n                switch (overrideOperation)\n                {\n                    case OverrideOperation.Apply:\n                        throw new InvalidOperationException(\"Cannot apply overriden properties in Animation Mode.\");\n                    case OverrideOperation.Revert:\n                        throw new InvalidOperationException(\"Cannot revert overriden properties in Animation Mode.\");\n                }\n            }\n            else if (action == InteractionMode.UserAction)\n            {\n                var message = L10n.Tr(\"Overriden properties cannot be applied or reverted when in Animation Mode.\\n\\nDisable Animation Mode and try again.\");\n                switch (overrideOperation)\n                {\n                    case OverrideOperation.Apply:\n                        EditorUtility.DisplayDialog(\n                            L10n.Tr(\"Cannot apply property override to Prefab\"),\n                            message,\n                            L10n.Tr(\"OK\"));\n                        break;\n                    case OverrideOperation.Revert:\n                        EditorUtility.DisplayDialog(\n                            L10n.Tr(\"Cannot revert property override\"),\n                            message,\n                            L10n.Tr(\"OK\"));\n                        break;\n                }\n            }\n            return true;\n        }\n\n        public static event Action<GameObject> prefabInstanceApplying;\n        public static event Action<GameObject> prefabInstanceApplied;\n\n        [RequiredByNativeCode]\n        internal static void Internal_CallPrefabInstanceApplying(GameObject instanceRoot)\n        {\n            Assert.IsNotNull(instanceRoot);\n\n            prefabInstanceApplying?.Invoke(instanceRoot);\n        }\n\n        [RequiredByNativeCode]\n        internal static void Internal_CallPrefabInstanceApplied(GameObject instanceRoot)\n        {\n            Assert.IsNotNull(instanceRoot);\n\n            prefabInstanceApplied?.Invoke(instanceRoot);\n        }\n\n        internal static void RaiseApplyingEvent(SerializedObject serializedObject)\n        {\n            GameObject outermostRoot = GetOutermostPrefabInstanceRoot(serializedObject.targetObject);\n            if (outermostRoot != null)\n                Internal_CallPrefabInstanceApplying(outermostRoot);\n        }\n\n        internal static void RaiseAppliedEvent(SerializedObject serializedObject)\n        {\n            foreach (Object targetObject in serializedObject.targetObjects)\n            {\n                if (PrefabUtility.IsPartOfNonAssetPrefabInstance(targetObject))\n                {\n                    GameObject outermostRoot = GetOutermostPrefabInstanceRoot(targetObject);\n                    if (outermostRoot != null)\n                    {\n                        Internal_CallPrefabInstanceApplied(outermostRoot);\n                    }\n                }\n            }\n        }\n\n        public static void ApplyPropertyOverride(SerializedProperty instanceProperty, string assetPath, InteractionMode action)\n        {\n            DateTime startTime = DateTime.UtcNow;\n\n            Object prefabInstanceObject = instanceProperty.serializedObject.targetObject;\n            ThrowExceptionIfNotValidPrefabInstanceObject(prefabInstanceObject, true);\n\n            if (WarnIfInAnimationMode(OverrideOperation.Apply, action))\n                return;\n\n            ApplyPropertyOverrides(prefabInstanceObject, instanceProperty, assetPath, true, action);\n\n            Analytics.SendApplyEvent(\n                Analytics.ApplyScope.PropertyOverride,\n                prefabInstanceObject,\n                assetPath,\n                action,\n                startTime,\n                IsPropertyOverrideDefaultOverrideComparedToAnySource(instanceProperty)\n            );\n        }\n\n        // This method is called both from ApplyPropertyOverride and ApplyObjectOverride.\n        // In the former case, optionalSingleInstanceProperty is passed along as is the only property that should be processed.\n        // In the latter, all properties in the prefabInstanceObject are iterated.\n        // An alternative approach was considered where the method takes an array of SerializedProperties,\n        // but since there can be thousands of those in a component, and they would each have to be copied from the iterator,\n        // it's better to handle properties inline as the iterator iterates over them.\n        // This does mean that we need to cache the SerializedObjects that end up being touched.\n        // Those are that of the prefabInstanceObject itself, and the chain of corresponding object\n        // all the way to the Prefab at the specified assetPath.\n        // Since calling ApplyModifiedProperties on a SerializedObject can trigger a whole chain of imports,\n        // we don't want to create and call ApplyModifiedProperties more than once for each SerializedObject, hence the caching.\n        // We also can't swap the inner and outer loop, iterating the chain of corresponding objects in the outer loop\n        // and the SerializedProperties in the inner loop, since we only process overridden properties, so it would\n        // again require storing information about that for each property in some kind of list, which we want to avoid.\n        static void ApplyPropertyOverrides(Object prefabInstanceObject, SerializedProperty optionalSingleInstanceProperty, string assetPath, bool allowApplyDefaultOverride, InteractionMode action)\n        {\n            if (WarnIfInAnimationMode(OverrideOperation.Apply, action))\n                return;\n\n            Object prefabSourceObject = GetCorrespondingObjectFromSourceAtPath(prefabInstanceObject, assetPath);\n            if (prefabSourceObject == null)\n                return;\n\n            SerializedObject prefabSourceSerializedObject = new SerializedObject(prefabSourceObject);\n\n            // Cache SerializedObjects used.\n            var serializedObjects = new List<SerializedObject>();\n            var changedObjects = new HashSet<SerializedObject>();\n\n            HandleApplySingleProperties(prefabInstanceObject, optionalSingleInstanceProperty, assetPath, prefabSourceObject, prefabSourceSerializedObject, serializedObjects, changedObjects, allowApplyDefaultOverride, action);\n\n            // Ensure importing of saved Prefab Assets only kicks in after all Prefab Asset have been saved\n            AssetDatabase.StartAssetEditing();\n\n            try\n            {\n                Action<SerializedObject> saveIfChanged = (SerializedObject serializedObject) =>\n                {\n                    if (changedObjects.Contains(serializedObject))\n                    {\n                        bool applySuccess = action == InteractionMode.UserAction ? serializedObject.ApplyModifiedProperties() : serializedObject.ApplyModifiedPropertiesWithoutUndo();\n                        if (applySuccess)\n                        {\n                            SaveChangesToPrefabFileIfPersistent(serializedObject);\n\n                            if (action == InteractionMode.UserAction)\n                            {\n                                Undo.FlushUndoRecordObjects(); // flush'es ensure that SavePrefab() on undo/redo on the source happens in the right order\n                            }\n                        }\n                    }\n                };\n\n                // Case 1292519\n                // The Prefab to which the changes are applied is added first in serializedObjects by ApplySingleProperty - it must be saved first\n                // The rest of the objects are collected in reverse dependency order in ApplySingleProperty - starting from the instance where the changes are made down to the original Prefab\n                // Apply the changes and save them in dependency order (reversed array order) to make sure dependent values are saved after the values they depend upon\n                if (serializedObjects.Count > 0)\n                {\n                    saveIfChanged(serializedObjects[0]);\n                    for (int i = serializedObjects.Count - 1; i > 0; i--)\n                    {\n                        saveIfChanged(serializedObjects[i]);\n                    }\n                }\n            }\n            finally\n            {\n                AssetDatabase.StopAssetEditing();\n            }\n\n            foreach (var serializedObject in serializedObjects)\n            {\n                if (changedObjects.Contains(serializedObject))\n                {\n                    RaiseAppliedEvent(serializedObject);\n                }\n            }\n        }\n\n        static void HandleApplySingleProperties(\n            Object prefabInstanceObject,\n            SerializedProperty optionalSingleInstanceProperty,\n            string assetPath, Object prefabSourceObject,\n            SerializedObject prefabSourceSerializedObject,\n            List<SerializedObject> serializedObjects,\n            HashSet<SerializedObject> changedObjects,\n            bool allowApplyDefaultOverride,\n            InteractionMode action\n        )\n        {\n            bool isObjectOnRootInAsset = IsObjectOnRootInAsset(prefabInstanceObject, assetPath);\n\n            SerializedProperty property = null;\n            SerializedProperty endProperty = null;\n            if (optionalSingleInstanceProperty != null)\n            {\n                bool cancel;\n                property = GetArrayPropertyIfGivenPropertyIsPartOfArrayElementInInstanceWhichDoesNotExistInAsset(\n                    optionalSingleInstanceProperty,\n                    prefabSourceSerializedObject,\n                    action,\n                    out cancel);\n\n                if (cancel)\n                    return;\n\n                if (property == null)\n                {\n                    // We didn't find any mismatching array so just use the property the user supplied.\n                    property = optionalSingleInstanceProperty.Copy();\n                }\n                endProperty = property.GetEndProperty();\n            }\n            else\n            {\n                // Note: Mismatching array sizes are not a problem when applying entire component,\n                // since array sizes will always be applied before array content.\n                SerializedObject so = new SerializedObject(prefabInstanceObject);\n                property = so.GetIterator();\n            }\n\n            bool allowWarnAboutApplyingPartsOfManagedReferences = property.isReferencingAManagedReferenceField;\n\n            if (!property.hasVisibleChildren)\n            {\n                if (property.prefabOverride)\n                    ApplySinglePropertyAndRemoveOverride(property, prefabSourceSerializedObject, prefabSourceObject, isObjectOnRootInAsset, true, allowWarnAboutApplyingPartsOfManagedReferences, allowApplyDefaultOverride, serializedObjects, changedObjects, action, out _);\n            }\n            else\n            {\n                if (property.prefabOverride && property.propertyType == SerializedPropertyType.ManagedReference)\n                {\n                    bool skipRestOfProperties = false;\n                    ApplySinglePropertyAndRemoveOverride(property, prefabSourceSerializedObject, prefabSourceObject, isObjectOnRootInAsset, false, allowWarnAboutApplyingPartsOfManagedReferences, allowApplyDefaultOverride, serializedObjects, changedObjects, action, out skipRestOfProperties);\n                    if (skipRestOfProperties)\n                        return;\n\n                    allowWarnAboutApplyingPartsOfManagedReferences = false; // The managed reference was applied to the Asset so do not check for sub properties\n                }\n\n                var visitedManagedReferenceProperties = new HashSet<long>();\n                bool visitChildren = property.hasVisibleChildren;\n\n                while (property.Next(visitChildren) && (endProperty == null || !SerializedProperty.EqualContents(property, endProperty)))\n                {\n                    // If we apply a property that has child properties that are object references, and if they\n                    // reference non-asset objects, those references will get lost, since ApplySingleProperty\n                    // only patches up references in the provided property; not its children.\n                    // This could be fixed by letting ApplySingleProperty patch up all its child properties as well,\n                    // but then calling ApplySingleProperty n times would result in time complexity n*log(n).\n                    // Instead we only call ApplySingleProperty for visible leaf properties - the ones that actually\n                    // contain the data.\n                    // Technically, leaf properties contain the data, but we're using visible leafs here, which\n                    // corresponds to leaf nodes as shown in the Inspector. Note, this is not related to foldout\n                    // expanded state; it's related to the fact that some nodes can have flags that hide them.\n                    // Furthermore, special property types - like object references, which is what we're particularly\n                    // interested in - are hardcoded to have their child nodes hidden. We need to call\n                    // ApplySingleProperty on the object reference property and not its hidden children, so we use\n                    // hasHiddenChildren, not hasChildren, to determine which properties to call the method on.\n                    // Applying all visible leaf properties applies all data only once and ensures that when an\n                    // object reference is applied, it's via its own property and not a parent property.\n\n                    // NOTE: all property modifications are leafs except in the context of managed references.\n                    // Managed references can be overriden (and have visible children).\n                    bool isManagedReferenceRoot = property.propertyType == SerializedPropertyType.ManagedReference;\n                    bool skipRestOfProperties = false;\n                    if (property.prefabOverride && (isManagedReferenceRoot || !property.hasVisibleChildren))\n                        ApplySinglePropertyAndRemoveOverride(property, prefabSourceSerializedObject, prefabSourceObject, isObjectOnRootInAsset, false, allowWarnAboutApplyingPartsOfManagedReferences, allowApplyDefaultOverride, serializedObjects, changedObjects, action, out skipRestOfProperties);\n\n                    if (skipRestOfProperties)\n                        break;\n\n                    // Avoid cyclic mangaged references\n                    if (isManagedReferenceRoot)\n                    {\n                        if (visitedManagedReferenceProperties.Add(property.managedReferenceId))\n                            visitChildren = property.hasVisibleChildren; // First time seeing managed reference, so allow entering children if needed\n                        else\n                            visitChildren = false;\n                    }\n                    else\n                    {\n                        visitChildren = property.hasVisibleChildren;\n                    }\n                }\n            }\n        }\n\n        internal static PropertyValueOriginInfo GetPropertyValueOriginInfo(SerializedProperty property)\n        {\n            if (property == null)\n                return new PropertyValueOriginInfo(\"The property is null\");\n\n            if (property.prefabOverride)\n                return new PropertyValueOriginInfo(\"The property value is overriden in the currently open object\");\n\n            if (IsDefaultOverridePropertyPath(property.propertyPath))\n                return new PropertyValueOriginInfo(\"The property is a default override property\");\n\n            Object targetObject = property.serializedObject.targetObject;\n\n            if (targetObject == null)\n                return new PropertyValueOriginInfo(\"The targetObject of the property is null\");\n\n            // When there are multiple targetObjects (multi-selection), check if they are instances of the same asset\n            if (property.serializedObject.targetObjectsCount > 1)\n            {\n                Object previousTargetObj = null;\n                foreach (Object targetObj in property.serializedObject.targetObjects)\n                {\n                    if (targetObj == null)\n                        return new PropertyValueOriginInfo(\"The targetObject of the property is null\");\n\n                    if (GetCorrespondingObjectFromSource(targetObj) == null)\n                        return new PropertyValueOriginInfo(\"The targetObject does not have a source\");\n\n                    if (previousTargetObj != null && (AssetDatabase.GetAssetPath(GetCorrespondingObjectFromSource(targetObj)) != AssetDatabase.GetAssetPath(GetCorrespondingObjectFromSource(previousTargetObj))))\n                        return new PropertyValueOriginInfo(\"The targetObjects are instances of different assets\");\n\n                    previousTargetObj = targetObj;\n                }\n            }\n\n            Object source = GetCorrespondingObjectFromSource(targetObject);\n\n            if (source != null && IsPartOfModelPrefab(source))\n                source = null;\n\n            SerializedProperty propertyInSource = (source == null) ? null : new SerializedObject(source).FindProperty(property.propertyPath);\n\n            // Loop through sources to find the origin of the property value\n            while (propertyInSource != null)\n            {\n                // Check if the property is a prefab override in the current source\n                if (propertyInSource.prefabOverride)\n                    return new PropertyValueOriginInfo(GetPrefabAssetRootGameObject(source), \"Value Override\", \"The returned asset has overriden the original property value\");\n\n                Object nextSource = GetCorrespondingObjectFromSource(source);\n\n                if (nextSource != null && IsPartOfModelPrefab(nextSource))\n                    nextSource = null;\n\n                SerializedProperty propertyInNextSource = (nextSource == null) ? null : new SerializedObject(nextSource).FindProperty(property.propertyPath);\n\n                // If the property does not exist in the the next source, the current source is the property origin\n                if (propertyInNextSource == null)\n                    return new PropertyValueOriginInfo(GetPrefabAssetRootGameObject(source), \"Original Value\", \"The returned asset is the origin of the property and its current value\");\n\n                source = nextSource;\n                propertyInSource = propertyInNextSource;\n            }\n\n            return new PropertyValueOriginInfo(\"The property does not have a source\");\n        }\n\n        static void SaveChangesToPrefabFileIfPersistent(SerializedObject serializedObject)\n        {\n            if (!EditorUtility.IsPersistent(serializedObject.targetObject))\n                return;\n\n            GameObject go = serializedObject.targetObject as GameObject;\n            if (go == null)\n            {\n                var cmp = serializedObject.targetObject as Component;\n                if (cmp != null)\n                    go = cmp.gameObject;\n            }\n\n            if (go != null)\n            {\n                SavePrefabAsset(go.transform.root.gameObject);\n            }\n        }\n\n        // Returns null if property is not part of array where whole array needs to be appled.\n        static SerializedProperty GetArrayPropertyIfGivenPropertyIsPartOfArrayElementInInstanceWhichDoesNotExistInAsset(\n            SerializedProperty optionalSingleInstanceProperty,\n            SerializedObject prefabSourceSerializedObject,\n            InteractionMode action,\n            out bool cancel)\n        {\n            cancel = false;\n\n            // Check if the property is part of an array with mismatching size,\n            // and in that case make the property be that entire array.\n            string propertyPath = optionalSingleInstanceProperty.propertyPath;\n            int fullPropertyPathLength = optionalSingleInstanceProperty.propertyPath.Length;\n            int startSearchIndex = 0;\n            const string arrayElementIndexPrefix = \".Array.data[\";\n            // We need to handle nested arrays, hence the while loop.\n            while (startSearchIndex < fullPropertyPathLength)\n            {\n                int arrayPropertySplitIndex = propertyPath.IndexOf(arrayElementIndexPrefix, startSearchIndex);\n\n                // Break if no array was found in property path.\n                if (arrayPropertySplitIndex < 0)\n                    return null;\n\n                // Find property path for array.\n                string arrayPropertyPath = propertyPath.Substring(0, arrayPropertySplitIndex);\n\n                // Find array element index start and length up front since we need it either way.\n                int arrayElementIndexStart = arrayPropertySplitIndex + arrayElementIndexPrefix.Length;\n                int arrayElementIndexLength = propertyPath.IndexOf(']', arrayElementIndexStart) - arrayElementIndexStart;\n\n                // Check if found array has different length on instance than on Asset.\n                SerializedProperty arrayPropertyOnInstance = optionalSingleInstanceProperty.serializedObject.FindProperty(arrayPropertyPath);\n                SerializedProperty arrayPropertyOnAsset = prefabSourceSerializedObject.FindProperty(arrayPropertyPath);\n\n                // With the ManagedReferences feature we no longer guarantee that the Prefab Asset will have the same property so we need to check\n                // if it exists (could be a base class without any properties)\n                if (arrayPropertyOnAsset == null)\n                {\n                    WarnIfApplyingManagedReferenceFieldIsNotPossible(optionalSingleInstanceProperty, null, action);\n                    cancel = true;\n                    return null;\n                }\n\n                if (arrayPropertyOnInstance.arraySize > arrayPropertyOnAsset.arraySize)\n                {\n                    // Array size mismatches. Check if the property the user is attempting to apply\n                    // resides in an element which exceeds the array in the Prefab Asset.\n                    string arrayElementIndexString = propertyPath.Substring(arrayElementIndexStart, arrayElementIndexLength);\n                    int indexInArray;\n                    if (!int.TryParse(arrayElementIndexString, out indexInArray))\n                    {\n                        // This should not be able to happen, but fallback by using array.\n                        Debug.LogError(\"Misformed arrayElementIndexString \" + arrayElementIndexString);\n                        return arrayPropertyOnInstance;\n                    }\n\n                    if (indexInArray >= arrayPropertyOnAsset.arraySize)\n                    {\n                        if (action == InteractionMode.UserAction && !EditorUtility.DisplayDialog(\n                            \"Mismatching array size\",\n                            string.Format(\"The property is part of an array element which does not exist in the source Prefab because the corresponding array there is shorter. Do you want to apply the entire array '{0}'?\", arrayPropertyOnInstance.displayName),\n                            \"Apply Array\",\n                            \"Cancel\"))\n                        {\n                            cancel = true;\n                            return null;\n                        }\n\n                        return arrayPropertyOnInstance;\n                    }\n                }\n\n                // Array does not mismatch, so look if there are other arrays (deeper in property path) that do.\n                startSearchIndex = arrayPropertySplitIndex + arrayElementIndexPrefix.Length + arrayElementIndexLength + 1;\n            }\n            return null;\n        }\n\n        // Since method is called for each overridden property in a component.\n        // That may be thousands of times if a component has lots of array data.\n        // We provide as much information as possible to the method as parameters\n        // so we don't have to recalculate it for each call.\n        static void ApplySinglePropertyAndRemoveOverride(\n            SerializedProperty instanceProperty,\n            SerializedObject prefabSourceSerializedObject,\n            Object applyTarget,\n            bool isObjectOnRootInAsset,\n            bool singlePropertyOnly,\n            bool allowWarnAboutApplyingPartsOfManagedReferences,\n            bool allowApplyDefaultOverride,\n            List<SerializedObject> serializedObjects,\n            HashSet<SerializedObject> changedObjects,\n            InteractionMode action,\n            out bool skipRestOfProperties)\n        {\n            skipRestOfProperties = false;\n\n            if (!allowApplyDefaultOverride && isObjectOnRootInAsset && IsPropertyOverrideDefaultOverrideComparedToAnySource(instanceProperty))\n            {\n                if (singlePropertyOnly)\n                {\n                    // Neither of these will not happen from our own editor interface since we don't display\n                    // any menus to apply for default-override properties in the first place.\n                    if (action == InteractionMode.AutomatedAction)\n                        Debug.LogWarning(\"Cannot apply default-override property, since it is protected from being applied or reverted.\");\n                    else\n                        EditorUtility.DisplayDialog(\n                            L10n.Tr(\"Cannot apply default-override property\"),\n                            L10n.Tr(\"Default-override properties are protected from being applied or reverted.\"),\n                            L10n.Tr(\"OK\"));\n                }\n                return;\n            }\n\n            var sourceSerializedObjInChangedSet = changedObjects.Contains(prefabSourceSerializedObject);\n            SerializedProperty sourceProperty = prefabSourceSerializedObject.FindProperty(instanceProperty.propertyPath);\n            if (sourceProperty == null)\n            {\n                // Special handling for arrays\n                bool cancel;\n                var instanceArrayProperty = GetArrayPropertyIfGivenPropertyIsPartOfArrayElementInInstanceWhichDoesNotExistInAsset(instanceProperty, prefabSourceSerializedObject, InteractionMode.AutomatedAction, out cancel);\n                if (instanceArrayProperty != null)\n                {\n                    if (!sourceSerializedObjInChangedSet)\n                        RaiseApplyingEvent(instanceArrayProperty.serializedObject);\n\n                    prefabSourceSerializedObject.CopyFromSerializedProperty(instanceArrayProperty);\n\n                    if (!sourceSerializedObjInChangedSet)\n                    {\n                        changedObjects.Add(prefabSourceSerializedObject);\n                        sourceSerializedObjInChangedSet = true;\n                    }\n\n                    sourceProperty = prefabSourceSerializedObject.FindProperty(instanceProperty.propertyPath);\n                    if (sourceProperty == null)\n                    {\n                        Debug.LogError($\"ApplySingleProperty full array copy error: SerializedProperty could not be found for {instanceProperty.propertyPath}. Please report a bug.\");\n                        return;\n                    }\n                }\n            }\n\n            if (allowWarnAboutApplyingPartsOfManagedReferences && WarnIfApplyingManagedReferenceFieldIsNotPossible(instanceProperty, sourceProperty, action))\n            {\n                skipRestOfProperties = true;\n                return;\n            }\n\n            if (sourceProperty == null)\n            {\n                // If we reach here we need to investigate the situation in which it happens and fix it\n                Debug.LogError($\"ApplySinglePropertyAndRemoveOverride error: Unhandled situation for {instanceProperty.propertyPath}. Please report a bug.\");\n                skipRestOfProperties = true;\n                return;\n            }\n\n            if (!sourceSerializedObjInChangedSet)\n                RaiseApplyingEvent(instanceProperty.serializedObject);\n\n            // Copy overridden property value to asset\n            if (instanceProperty.propertyType == SerializedPropertyType.ManagedReference)\n            {\n                // For a managed reference root property we assign the entire object reference value so we can handle if the Asset value is null from start, since in\n                // this case we cannot use CopyFromSerializedProperty as we do for normal properties.\n                sourceProperty.managedReferenceValue = instanceProperty.managedReferenceValue;\n            }\n            else\n            {\n                prefabSourceSerializedObject.CopyFromSerializedProperty(instanceProperty);\n            }\n\n            if (!sourceSerializedObjInChangedSet)\n                changedObjects.Add(prefabSourceSerializedObject);\n\n            // Abort if property has reference to object in scene.\n            if (sourceProperty.propertyType == SerializedPropertyType.ObjectReference)\n            {\n                if (PrefabUtility.CanPropertyBeAppliedToTarget(instanceProperty, applyTarget))\n                    MapObjectReferencePropertyToSourceIfApplicable(sourceProperty, applyTarget);\n                else\n                {\n                    // The property is a reference to a non-persistent object (scene object which could not be mapped to the asset.\n                    // It can not be applied.\n\n                    // Give a warning if the user tried to specifically apply this property.\n                    if (singlePropertyOnly)\n                    {\n                        if (action == InteractionMode.AutomatedAction)\n                            Debug.LogWarning(\"Cannot apply reference to scene object that is not part of apply target prefab.\");\n                        else\n                            EditorUtility.DisplayDialog(\n                                L10n.Tr(\"Cannot apply reference to object in scene\"),\n                                L10n.Tr(\"A reference to an object in the scene cannot be applied to the Prefab asset.\"),\n                                L10n.Tr(\"OK\"));\n                    }\n                    return;\n                }\n            }\n\n            // Apply target SerializedObject should get ApplyModifiedProperties called first.\n            if (serializedObjects.Count == 0)\n                serializedObjects.Add(prefabSourceSerializedObject);\n\n            // Clear overrides for property in Prefab instance and outer Prefabs that are using(nesting) the Prefab source.\n            // Otherwise applied modification would appear to jump back to the value it had before applying.\n            Object prefabInstanceObject = instanceProperty.serializedObject.targetObject;\n            Object prefabSourceObject = prefabSourceSerializedObject.targetObject;\n            Object outerPrefabObject = prefabInstanceObject;\n            int sourceIndex = 1;\n            while (outerPrefabObject != prefabSourceObject)\n            {\n                SerializedObject outerPrefabSerializedObject;\n                if (sourceIndex >= serializedObjects.Count)\n                {\n                    outerPrefabSerializedObject = new SerializedObject(outerPrefabObject);\n                    serializedObjects.Add(outerPrefabSerializedObject);\n                }\n                else\n                {\n                    outerPrefabSerializedObject = serializedObjects[sourceIndex];\n                }\n\n                // Case 1172835: When applying a new array size to an inner Prefab, this change won't yet have propagated to the outer Prefabs.\n                // This means properties inside the array may not yet exist here.\n                // To handle this, we first copy the serialized value (which correctly handles array size changes)\n                // before we clear the overrides below (by setting outerPrefabProp.prefabOverride = false).\n                var propertyType = instanceProperty.propertyType;\n                if (propertyType == SerializedPropertyType.ArraySize)\n                {\n                    // Do not add outerPrefabSerializedObject to changedObjects\n                    // CopyFromSerializedProperty is necessary to make \"index\" propertyPaths out of original bounds valid to be able to clear dangling prefabOverrides\n                    // as noted in the comment for Case 1172835, but it should not be applied/saved if there are no prefabOverrides\n                    outerPrefabSerializedObject.CopyFromSerializedProperty(instanceProperty);\n                }\n\n                SerializedProperty outerPrefabProp = outerPrefabSerializedObject.FindProperty(instanceProperty.propertyPath);\n                if (outerPrefabProp != null && outerPrefabProp.prefabOverride)\n                {\n                    outerPrefabProp.prefabOverride = false;\n                    changedObjects.Add(outerPrefabSerializedObject);\n                }\n                if (outerPrefabProp == null)\n                    Debug.LogError($\"ApplySingleProperty clear overrides error: SerializedProperty could not be found for {instanceProperty.propertyPath}. Please report a bug.\");\n\n                outerPrefabObject = PrefabUtility.GetCorrespondingObjectFromSource(outerPrefabObject);\n                sourceIndex++;\n            }\n        }\n\n        internal static void RevertPropertyOverrides(SerializedProperty[] instanceProperties, InteractionMode action)\n        {\n            if (WarnIfInAnimationMode(OverrideOperation.Revert, action))\n                return;\n\n            foreach (var property in instanceProperties)\n                if (WarnIfRevertingManagedReferenceIsNotPossible(property, action))\n                    return;\n\n            var firstSerializedObject = instanceProperties[0].serializedObject;\n\n            bool isSameSerializedObject = true;\n            foreach (var prop in instanceProperties)\n            {\n                if (prop.serializedObject != firstSerializedObject)\n                    isSameSerializedObject = false;\n            }\n\n            if (isSameSerializedObject)\n                RaiseRevertingEvents(firstSerializedObject);\n\n            foreach (var property in instanceProperties)\n                RevertPropertyOverride(property, action, !isSameSerializedObject);\n\n            if (isSameSerializedObject)\n                RaiseRevertedEvents(firstSerializedObject);\n        }\n\n        public static void RevertPropertyOverride(SerializedProperty instanceProperty, InteractionMode action)\n        {\n            RevertPropertyOverride(instanceProperty, action, true);\n        }\n\n        internal static void RevertPropertyOverride(SerializedProperty instanceProperty, InteractionMode action, bool raiseRevertEvents)\n        {\n            if (WarnIfInAnimationMode(OverrideOperation.Revert, action))\n                return;\n\n            ThrowExceptionIfAllPrefabInstanceObjectsAreInvalid(instanceProperty.serializedObject.targetObjects, false);\n\n            if (WarnIfRevertingManagedReferenceIsNotPossible(instanceProperty, action))\n                return;\n\n            if (raiseRevertEvents)\n                RaiseRevertingEvents(instanceProperty.serializedObject);\n\n            instanceProperty.prefabOverride = false;\n\n            // Because prefabOverride changed ApplyModifiedProperties will do a prefab merge causing the revert.\n            if (action == InteractionMode.UserAction)\n                instanceProperty.serializedObject.ApplyModifiedProperties();\n            else\n                instanceProperty.serializedObject.ApplyModifiedPropertiesWithoutUndo();\n\n            if (raiseRevertEvents)\n                RaiseRevertedEvents(instanceProperty.serializedObject);\n        }\n\n        internal static bool IsPropertyBeingDrivenByPrefabStage(SerializedProperty property)\n        {\n            Object target = property.serializedObject.targetObject;\n            GameObject go = GetGameObject(target);\n            if (go != null && go.scene.IsValid() && EditorSceneManager.IsPreviewScene(go.scene))\n            {\n                var prefabStage = SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();\n                if (prefabStage != null && prefabStage.mode == SceneManagement.PrefabStage.Mode.InContext)\n                {\n                    var propertyPath = (property.isReferencingAManagedReferenceField ? property.managedReferencePropertyPath : property.propertyPath);\n                    ScriptableObject driver = prefabStage;\n                    if (\n                        (DrivenPropertyManagerInternal.IsDriving(driver, target, propertyPath))\n                        ||\n                        ((target is Transform || target is ParticleSystem || property.propertyType == SerializedPropertyType.Color) && DrivenPropertyManagerInternal.IsDrivingPartial(driver, target, propertyPath)))\n                    {\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        internal static void RaiseRevertingEvents(SerializedObject serializedObject)\n        {\n            foreach (Object targetObject in serializedObject.targetObjects)\n            {\n                GameObject outermostRoot = GetOutermostPrefabInstanceRoot(targetObject);\n                if (outermostRoot != null)\n                    Internal_CallPrefabInstanceReverting(outermostRoot);\n            }\n        }\n\n        internal static void RaiseRevertedEvents(SerializedObject serializedObject)\n        {\n            foreach (Object targetObject in serializedObject.targetObjects)\n            {\n                GameObject outermostRoot = GetOutermostPrefabInstanceRoot(targetObject);\n                if (outermostRoot != null)\n                    Internal_CallPrefabInstanceReverted(outermostRoot);\n            }\n        }\n\n        static bool WarnIfApplyingManagedReferenceFieldIsNotPossible(SerializedProperty instanceProperty, SerializedProperty sourceProperty, InteractionMode action)\n        {\n            bool isReferencingAManagedReferenceField = instanceProperty.isReferencingAManagedReferenceField;\n            if (!isReferencingAManagedReferenceField)\n                return false;\n\n            if (sourceProperty != null)\n            {\n                // Even if we find the propertyPath on the source object we also need to validate if this is a managed reference to the correct source object, except when\n                // applying an entire object because then entire state is transfered to the asset and can merged back to the instance so here we don't show the dialog.\n                bool applyingNotPossible = instanceProperty.managedReferencePropertyPath != sourceProperty.managedReferencePropertyPath;\n                if (applyingNotPossible)\n                {\n                    string title = L10n.Tr(\"Mismatching Objects\");\n                    string errorMsg = L10n.Tr(\"Cannot apply SerializeReference field since the Prefab instance is referencing a new object compared to the Prefab Asset.\\n\\nThis means that the changes from the Prefab Asset cannot be merged back to the Prefab instance.\\n\\nYou can apply the root of the field or the entire component\");\n                    if (action == InteractionMode.AutomatedAction)\n                        throw new InvalidOperationException(title + \": \" + errorMsg + $\"(instance property { instanceProperty.managedReferencePropertyPath}, asset property { sourceProperty.managedReferencePropertyPath})\");\n                    else\n                        EditorUtility.DisplayDialog(\n                            title,\n                            errorMsg,\n                            L10n.Tr(\"OK\"));\n                    return true;\n                }\n            }\n            else\n            {\n                // Special handling for managed references.\n                // If we have a valid managedReferencePropertyPath then the types must be different since we could not find the\n                // propertyPath on the Prefab Asset, tell the user that this is not supported.\n                if (!string.IsNullOrEmpty(instanceProperty.managedReferencePropertyPath))\n                {\n                    string title = L10n.Tr(\"Mismatching Types\");\n                    string errorMsg = L10n.Tr(\"Cannot apply a SerializeReference sub field when the type from the Prefab instance is different from the Prefab Asset.\\n\\nYou can apply the root of the field or the entire component\");\n                    if (action == InteractionMode.AutomatedAction)\n                        throw new InvalidOperationException(title + \": \" + errorMsg);\n                    else\n                        EditorUtility.DisplayDialog(\n                            title,\n                            errorMsg,\n                            L10n.Tr(\"OK\"));\n\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        static bool WarnIfRevertingManagedReferenceIsNotPossible(SerializedProperty instanceProperty, InteractionMode action)\n        {\n            if (!instanceProperty.isReferencingAManagedReferenceField)\n                return false;\n\n            var instanceObject = instanceProperty.serializedObject.targetObject;\n            var prefabSourceObject = GetCorrespondingObjectFromSource(instanceObject);\n            SerializedObject prefabSourceSerializedObject = new SerializedObject(prefabSourceObject);\n            SerializedProperty sourceProperty = prefabSourceSerializedObject.FindProperty(instanceProperty.propertyPath);\n\n            string errorMsg = \"\";\n            string title = \"\";\n            if (sourceProperty != null)\n            {\n                // Object mismatch:\n                bool revertingNotPossible = instanceProperty.managedReferencePropertyPath != sourceProperty.managedReferencePropertyPath;\n                if (revertingNotPossible)\n                {\n                    title = L10n.Tr(\"Mismatching Objects\");\n                    errorMsg = L10n.Tr(\"Cannot revert a single SerializeReference field since the Prefab instance is referencing a new object compared to the Prefab Asset.\\n\\nThis means that the entire object is considered an override, cannot revert parts of it.\\n\\nYou can revert the root of the serialized reference or the entire component.\");\n                }\n            }\n            else\n            {\n                // Type mismatch:\n                title = L10n.Tr(\"Mismatching Types\");\n                errorMsg = L10n.Tr(\"Cannot revert a parts of a SerializeReference property since the Prefab instance is referencing a different type compared to the Prefab Asset.\\n\\nYou can revert the root of the serialized reference or the entire component.\");\n            }\n\n            bool warnUser = !string.IsNullOrEmpty(errorMsg);\n            if (warnUser)\n            {\n                if (action == InteractionMode.AutomatedAction)\n                {\n                    throw new InvalidOperationException(title + \": \" + errorMsg);\n                }\n                else if (action == InteractionMode.UserAction)\n                {\n                    EditorUtility.DisplayDialog(title, errorMsg, L10n.Tr(\"OK\"));\n                }\n            }\n\n            return warnUser;\n        }\n\n        public static void ApplyObjectOverride(Object instanceComponentOrGameObject, string assetPath, InteractionMode action)\n        {\n            DateTime startTime = DateTime.UtcNow;\n\n            ThrowExceptionIfNotValidPrefabInstanceObject(instanceComponentOrGameObject, true);\n\n            if (WarnIfInAnimationMode(OverrideOperation.Apply, action))\n                return;\n\n            ApplyPropertyOverrides(instanceComponentOrGameObject, null, assetPath, false, action);\n\n            if (action == InteractionMode.UserAction)\n            {\n                Component instanceComponent = instanceComponentOrGameObject as Component;\n                if (instanceComponent != null)\n                {\n                    Component coupledComponent = instanceComponent.GetCoupledComponent();\n                    if (coupledComponent != null)\n                        ApplyPropertyOverrides(coupledComponent, null, assetPath, false, action);\n                }\n            }\n\n            Analytics.SendApplyEvent(\n                Analytics.ApplyScope.ObjectOverride,\n                instanceComponentOrGameObject,\n                assetPath,\n                action,\n                startTime,\n                IsObjectOverrideAllDefaultOverridesComparedToOriginalSource(instanceComponentOrGameObject)\n            );\n        }\n\n        public static void RevertObjectOverride(Object instanceComponentOrGameObject, InteractionMode action)\n        {\n            ThrowExceptionIfNotValidPrefabInstanceObject(instanceComponentOrGameObject, false);\n\n            if (WarnIfInAnimationMode(OverrideOperation.Revert, action))\n                return;\n\n            if (action == InteractionMode.UserAction)\n                Undo.RegisterCompleteObjectUndo(instanceComponentOrGameObject, \"Revert component property overrides\");\n            PrefabUtility.RevertObjectOverride_Internal(instanceComponentOrGameObject);\n\n            if (action == InteractionMode.UserAction)\n            {\n                Component instanceComponent = instanceComponentOrGameObject as Component;\n                if (instanceComponent != null)\n                {\n                    Component coupledComponent = instanceComponent.GetCoupledComponent();\n                    if (coupledComponent != null)\n                    {\n                        Undo.RegisterCompleteObjectUndo(coupledComponent, \"Revert component property overrides\");\n                        PrefabUtility.RevertObjectOverride_Internal(coupledComponent);\n                    }\n                }\n            }\n        }\n\n        static bool DidComponentOrderChange(Component[] originalComponentOrder, Component[] newComponentOrder)\n        {\n            if (originalComponentOrder.Length != newComponentOrder.Length)\n                return true;\n\n            for (int i = 0; i < originalComponentOrder.Length; ++i)\n            {\n                if (originalComponentOrder[i] != newComponentOrder[i])\n                    return true;\n            }\n\n            return false;\n        }\n\n        public static void ApplyAddedComponent(Component component, string assetPath, InteractionMode action)\n        {\n            DateTime startTime = DateTime.UtcNow;\n\n            if (component == null)\n                throw new ArgumentNullException(nameof(component), \"Cannot apply added component. Component is null.\");\n\n            if (!PrefabUtility.IsAddedComponentOverride(component))\n                throw new ArgumentException(\"Cannot apply added component. Component is not an added component override on a Prefab instance.\", nameof(component));\n\n            ThrowExceptionIfInstanceIsPersistent(component);\n\n            try\n            {\n                GameObject prefabSourceGameObject = GetCorrespondingObjectFromSourceAtPath(component.gameObject, assetPath);\n                if (prefabSourceGameObject == null)\n                    return;\n\n                var originalComponentOrder = component.gameObject.GetComponents<Component>();\n\n                var actionName = \"Apply Added Component\";\n                if (action == InteractionMode.UserAction)\n                {\n                    string dependentComponents = string.Join(\n                        \", \",\n                        GetAddedComponentDependencies(component, OverrideOperation.Apply).Select(e => ObjectNames.GetInspectorTitle(e)).ToArray());\n                    if (!string.IsNullOrEmpty(dependentComponents))\n                    {\n                        string error = String.Format(\n                            L10n.Tr(\"Can't apply added component {0} because it depends on {1}.\"),\n                            ObjectNames.GetInspectorTitle(component),\n                            dependentComponents);\n                        EditorUtility.DisplayDialog(L10n.Tr(\"Can't apply added component\"), error, L10n.Tr(\"OK\"));\n                        return;\n                    }\n\n                    Undo.RegisterFullObjectHierarchyUndo(prefabSourceGameObject, actionName);\n                    Undo.RegisterFullObjectHierarchyUndo(component, actionName);\n                }\n\n                var instanceRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(component);\n                Internal_CallPrefabInstanceApplying(instanceRoot);\n\n                PrefabUtility.ApplyAddedComponent(component, prefabSourceGameObject);\n\n                if (action == InteractionMode.UserAction)\n                {\n                    Undo.RegisterCreatedObjectUndo(GetCorrespondingObjectFromOriginalSource(component), actionName);\n\n                    var coupledComponent = component.GetCoupledComponent();\n                    if (coupledComponent != null)\n                    {\n                        PrefabUtility.ApplyAddedComponent(coupledComponent, prefabSourceGameObject);\n                        Undo.RegisterCreatedObjectUndo(GetCorrespondingObjectFromOriginalSource(coupledComponent), actionName);\n                    }\n\n                    var postApplyComponentOrder = component.gameObject.GetComponents<Component>();\n                    bool orderChanged = DidComponentOrderChange(originalComponentOrder, postApplyComponentOrder);\n                    if (orderChanged)\n                    {\n                        EditorUtility.DisplayDialog(L10n.Tr(\"Notice!\"), L10n.Tr(\"Some component(s) changed position because of other added components in the variant/nesting chain.\"), L10n.Tr(\"OK\"));\n                    }\n                }\n\n                Internal_CallPrefabInstanceApplied(instanceRoot);\n            }\n            catch (ArgumentException exception)\n            {\n                if (action == InteractionMode.UserAction)\n                {\n                    EditorUtility.DisplayDialog(\n                        L10n.Tr(\"Can't add component\"),\n                        exception.Message,\n                        L10n.Tr(\"OK\"));\n                    Undo.RevertAllInCurrentGroup();\n                }\n                else\n                {\n                    throw exception;\n                }\n            }\n\n            Analytics.SendApplyEvent(\n                Analytics.ApplyScope.AddedComponent,\n                component,\n                assetPath,\n                action,\n                startTime,\n                false\n            );\n        }\n\n        public static void RevertAddedComponent(Component component, InteractionMode action)\n        {\n            if (component == null)\n                throw new ArgumentNullException(nameof(component), \"Cannot revert added component. Component is null.\");\n\n            if (!PrefabUtility.IsAddedComponentOverride(component))\n                throw new ArgumentException(\"Cannot revert added component. Component is not an added component override on a Prefab instance.\", nameof(component));\n\n            var prefabInstanceGameObject = component.gameObject;\n\n            PrefabUtility.Internal_CallPrefabInstanceReverting(prefabInstanceGameObject);\n\n            if (action == InteractionMode.UserAction)\n            {\n                string dependentComponents = string.Join(\n                    \", \",\n                    GetAddedComponentDependencies(component, OverrideOperation.Revert).Select(e => ObjectNames.GetInspectorTitle(e)).ToArray());\n                if (!string.IsNullOrEmpty(dependentComponents))\n                {\n                    string error = String.Format(\n                        L10n.Tr(\"Can't revert added component {0} because {1} depends on it.\"),\n                        ObjectNames.GetInspectorTitle(component),\n                        dependentComponents);\n                    EditorUtility.DisplayDialog(L10n.Tr(\"Can't revert added component\"), error, L10n.Tr(\"OK\"));\n                    return;\n                }\n\n                var coupledComponent = component.GetCoupledComponent();\n\n                Undo.DestroyObjectImmediate(component);\n                if (coupledComponent != null)\n                    Undo.DestroyObjectImmediate(coupledComponent);\n            }\n            else\n                Object.DestroyImmediate(component, true);\n\n            // Remerge the Prefab instance to make any suppressed components show up if no longer suppressed\n            // For the Prefab assets this is not necessary because they will be remerged by the importer when saved\n            if (!PrefabUtility.IsPartOfPrefabAsset(prefabInstanceGameObject))\n            {\n                PrefabUtility.MergePrefabInstance_internal(prefabInstanceGameObject);\n            }\n\n            PrefabUtility.Internal_CallPrefabInstanceReverted(prefabInstanceGameObject);\n        }\n\n        private static bool IsPrefabInstanceObjectOf(Object instance, Object source)\n        {\n            var o = instance;\n            while (o != null)\n            {\n                if (o == source)\n                {\n                    return true;\n                }\n\n                if (GetPrefabAssetHandle(o) == source)\n                {\n                    return true;\n                }\n\n                o = GetCorrespondingObjectFromSource(o);\n            }\n            return false;\n        }\n\n        internal static void RemoveRemovedComponentOverridesWhichAreInvalid(Object prefabInstanceObject)\n        {\n            var removedComponents = GetRemovedComponents(prefabInstanceObject);\n            if (removedComponents.Length == 0)\n                return;\n\n            var rootGameObject = GetOutermostPrefabInstanceRoot(prefabInstanceObject);\n            if (rootGameObject == null)\n                return;\n            var assetRootTransform = GetCorrespondingObjectFromSource(rootGameObject.transform);\n            if (assetRootTransform == null)\n                return;\n\n            var filteredRemovedComponents = new List<Component>();\n            foreach (var assetComponent in removedComponents)\n            {\n                if (assetComponent != null && assetComponent.transform.root == assetRootTransform)\n                {\n                    filteredRemovedComponents.Add(assetComponent);\n                }\n            }\n\n            if (filteredRemovedComponents.Count != removedComponents.Length)\n                SetRemovedComponents(prefabInstanceObject, filteredRemovedComponents.ToArray());\n        }\n\n        // We can't use the same pattern of identifying the prefab asset via assetPath only,\n        // since when the component is removed in the instance, the only way to identify which component it is,\n        // is via the corresponding component on the asset. We find it by matching FileIds. Additionally supplying an assetPath would be redundant.\n        public static void ApplyRemovedComponent(GameObject instanceGameObject, Component assetComponent, InteractionMode action)\n        {\n            DateTime startTime = DateTime.UtcNow;\n\n            ThrowExceptionIfNotValidPrefabInstanceObject(instanceGameObject, true);\n\n            if (assetComponent == null)\n                throw new ArgumentNullException(nameof(assetComponent), \"Prefab source may not be null.\");\n\n            var actionName = \"Apply Prefab removed component\";\n\n            if (action == InteractionMode.UserAction)\n            {\n                string dependentComponents = string.Join(\n                    \", \",\n                    GetRemovedComponentDependencies(assetComponent, instanceGameObject, OverrideOperation.Apply).Select(e => ObjectNames.GetInspectorTitle(e)).ToArray());\n                if (!string.IsNullOrEmpty(dependentComponents))\n                {\n                    string error = String.Format(\n                        L10n.Tr(\"Can't apply removed component {0} because {1} component in the Prefab Asset depends on it.\"),\n                        ObjectNames.GetInspectorTitle(assetComponent),\n                        dependentComponents);\n                    EditorUtility.DisplayDialog(L10n.Tr(\"Can't apply removed component\"), error, L10n.Tr(\"OK\"));\n                    return;\n                }\n            }\n\n            string assetPath = AssetDatabase.GetAssetPath(assetComponent);\n            GameObject assetRoot = GetRootGameObject(assetComponent);\n\n            Component coupledAssetComponent = null;\n            byte[] originalFileContent = null;\n            if (action == InteractionMode.UserAction)\n            {\n                coupledAssetComponent = assetComponent.GetCoupledComponent();\n                if (!FileUtil.ReadFileContentBinary(assetPath, out originalFileContent, out string errorMessage))\n                    Debug.LogError($\"No undo was registered when removing {assetComponent.name} from {assetRoot.name}. \\nError: {errorMessage}\", assetRoot);\n            }\n\n            var prefabInstanceObject = PrefabUtility.GetPrefabInstanceHandle(instanceGameObject);\n\n            PrefabUtility.Internal_CallPrefabInstanceApplying(instanceGameObject);\n            if (action == InteractionMode.UserAction)\n                Undo.RegisterCompleteObjectUndo(prefabInstanceObject, actionName);\n\n            // Having registered undo on the Prefab instance we can now apply the removed component override\n            using (var scope = new EditPrefabContentsScope(assetPath))\n            {\n                //Search components in file that matches the FileIds of componentInAsset\n                bool DeleteCorrespondingComponent(Component componentInAsset)\n                {\n                    if (componentInAsset == null)\n                        return false;\n\n                    var assetComponentId = Unsupported.GetFileIDHint(componentInAsset);\n                    var componentsOfTypeInAsset = scope.prefabContentsRoot.GetComponentsInChildren(componentInAsset.GetType(), true);\n\n                    foreach (var component in componentsOfTypeInAsset)\n                    {\n                        if (Unsupported.GetOrGenerateFileIDHint(component) == assetComponentId)\n                        {\n                            Object.DestroyImmediate(component);\n                            return true;\n                        }\n                    }\n                    Debug.LogError($\"Component {componentInAsset} could not be found and deleted from corresponding asset.\");\n                    return false;\n                }\n\n                if (DeleteCorrespondingComponent(assetComponent))\n                {\n                    RemoveRemovedComponentOverride(instanceGameObject, assetComponent);\n\n                    if (DeleteCorrespondingComponent(coupledAssetComponent))\n                        RemoveRemovedComponentOverride(instanceGameObject, coupledAssetComponent);\n                }\n            }\n\n            // Register undo for the changed asset\n            if (action == InteractionMode.UserAction && originalFileContent != null)\n            {\n                var guid = AssetDatabase.GUIDFromAssetPath(assetPath);\n                if (FileUtil.ReadFileContentBinary(assetPath, out byte[] newFileContent, out string errorMessage))\n                    Undo.RegisterFileChangeUndo(guid, originalFileContent, newFileContent);\n                else\n                    Debug.LogError($\"No undo was registered when removing {assetComponent.name} from {assetRoot.name}. \\nError: {errorMessage}\", assetRoot);\n            }\n\n            // Ensure correct action name after asset undo\n            Undo.SetCurrentGroupName(actionName);\n\n            RemoveRemovedComponentOverridesWhichAreInvalid(prefabInstanceObject);\n\n            PrefabUtility.Internal_CallPrefabInstanceApplied(instanceGameObject);\n\n            Analytics.SendApplyEvent(\n                Analytics.ApplyScope.RemovedComponent,\n                instanceGameObject,\n                AssetDatabase.GetAssetPath(assetComponent),\n                action,\n                startTime,\n                false\n            );\n        }\n\n        private static void RemoveRemovedComponentOverride(Object instanceObject, Component assetComponent)\n        {\n            var removedComponents = PrefabUtility.GetRemovedComponents(instanceObject);\n            int index = -1;\n            for (int i = 0; i < removedComponents.Length; i++)\n            {\n                if (IsPrefabInstanceObjectOf(removedComponents[i], assetComponent))\n                {\n                    index = i;\n                    break;\n                }\n            }\n            if (index != -1)\n            {\n                var filteredRemovedComponents = (from c in removedComponents where c != removedComponents[index] select c).ToArray();\n                PrefabUtility.SetRemovedComponents(instanceObject, filteredRemovedComponents);\n            }\n        }\n\n        public static void RevertRemovedComponent(GameObject instanceGameObject, Component assetComponent, InteractionMode action)\n        {\n            ThrowExceptionIfNotValidPrefabInstanceObject(instanceGameObject, false);\n\n            // Check dependencies\n            string dependentComponents = string.Join(\n                \", \",\n                GetRemovedComponentDependencies(assetComponent, instanceGameObject, OverrideOperation.Revert).Select(e => ObjectNames.GetInspectorTitle(e)).ToArray());\n            if (!string.IsNullOrEmpty(dependentComponents))\n            {\n                string error = String.Format(\n                    L10n.Tr(\"Can't revert removed component {0} because it depends on {1}.\"),\n                    ObjectNames.GetInspectorTitle(assetComponent),\n                    dependentComponents);\n                if (action == InteractionMode.UserAction)\n                {\n                    EditorUtility.DisplayDialog(L10n.Tr(\"Can't revert removed component\"), error, L10n.Tr(\"OK\"));\n                }\n                else\n                {\n                    Debug.LogError(error);\n                }\n                return;\n            }\n\n            PrefabUtility.Internal_CallPrefabInstanceReverting(instanceGameObject);\n\n            var actionName = \"Revert Prefab removed component\";\n            var prefabInstanceObject = PrefabUtility.GetPrefabInstanceHandle(instanceGameObject);\n\n            if (action == InteractionMode.UserAction)\n            {\n                Undo.RegisterCompleteObjectUndo(instanceGameObject, actionName);\n            }\n\n            RemoveRemovedComponentOverride(prefabInstanceObject, assetComponent);\n\n            if (action == InteractionMode.UserAction)\n            {\n                foreach (var component in instanceGameObject.GetComponents<Component>())\n                {\n                    if (IsPrefabInstanceObjectOf(component, assetComponent))\n                    {\n                        Undo.RegisterCreatedObjectUndo(component, actionName);\n                        break;\n                    }\n                }\n\n                var coupledAssetComponent = assetComponent.GetCoupledComponent();\n                if (coupledAssetComponent != null)\n                {\n                    RemoveRemovedComponentOverride(prefabInstanceObject, coupledAssetComponent);\n                    foreach (var component in instanceGameObject.GetComponents<Component>())\n                    {\n                        if (IsPrefabInstanceObjectOf(component, coupledAssetComponent))\n                        {\n                            Undo.RegisterCreatedObjectUndo(component, actionName);\n                            break;\n                        }\n                    }\n                }\n            }\n\n            PrefabUtility.Internal_CallPrefabInstanceReverted(instanceGameObject);\n        }\n\n        private static void RemoveRemovedGameObjectOverridesWhichAreNull(Object prefabInstanceObject)\n        {\n            var removedGameObjects = PrefabUtility.GetRemovedGameObjects(prefabInstanceObject);\n            var filteredRemovedGameObjects = (from go in removedGameObjects where go != null select go).ToArray();\n            PrefabUtility.SetRemovedGameObjects(prefabInstanceObject, filteredRemovedGameObjects);\n        }\n\n        public static void ApplyRemovedGameObject(GameObject gameObjectInInstance, GameObject assetGameObject, InteractionMode action)\n        {\n            DateTime startTime = DateTime.UtcNow;\n\n            ThrowExceptionIfNotValidPrefabInstanceObject(gameObjectInInstance, true);\n\n            if (assetGameObject == null)\n                throw new ArgumentNullException(nameof(assetGameObject), \"Prefab source must not be null.\");\n            if (!IsPrefabInstanceObjectOf(gameObjectInInstance, PrefabUtility.GetPrefabAssetHandle(assetGameObject)))\n                throw new ArgumentException(\"Prefab instance must match Prefab source.\");\n            if (assetGameObject.transform.root == assetGameObject.transform)\n                throw new ArgumentException(\"The asset GameObject cannot be the root as the root cannot be removed as an override.\");\n\n            var actionName = \"Apply Prefab removed GameObject\";\n            var prefabInstanceObject = PrefabUtility.GetPrefabInstanceHandle(gameObjectInInstance);\n            GameObject prefabInstanceRoot = GetOutermostPrefabInstanceRoot(gameObjectInInstance);\n\n            if (prefabInstanceObject == null)\n                throw new ArgumentNullException(nameof(prefabInstanceObject), \"Prefab instance must not be null.\");\n\n            PrefabUtility.Internal_CallPrefabInstanceApplying(prefabInstanceRoot);\n\n            string assetPath = AssetDatabase.GetAssetPath(assetGameObject);\n            GameObject assetRoot = GetRootGameObject(assetGameObject);\n            byte[] originalFileContent = null;\n\n            if (action == InteractionMode.UserAction)\n            {\n                if (!FileUtil.ReadFileContentBinary(assetPath, out originalFileContent, out string errorMessage))\n                    Debug.LogError($\"No undo was registered when removing GameObject {assetGameObject.name} from {assetRoot.name}. \\nError: {errorMessage}\", assetRoot);\n            }\n\n            using (var scope = new EditPrefabContentsScope(assetPath))\n            {\n                var assetGOId = Unsupported.GetFileIDHint(assetGameObject);\n                var transformsInAsset = scope.prefabContentsRoot.GetComponentsInChildren(typeof(Transform), true);\n\n                bool success = false;\n                foreach (var transform in transformsInAsset)\n                {\n                    if (Unsupported.GetOrGenerateFileIDHint(transform.gameObject) == assetGOId)\n                    {\n                        Object.DestroyImmediate(transform.gameObject);\n                        success = true;\n                        break;\n                    }\n                }\n\n                if (!success)\n                    Debug.LogError($\"GameObject {assetGameObject} could not be found and deleted from corresponding asset.\");\n            }\n\n            if (action == InteractionMode.UserAction && originalFileContent != null)\n            {\n                var guid = AssetDatabase.GUIDFromAssetPath(assetPath);\n                if (FileUtil.ReadFileContentBinary(assetPath, out byte[] newFileContent, out string errorMessage))\n                {\n                    Undo.RegisterFileChangeUndo(guid, originalFileContent, newFileContent);\n                    Undo.RegisterFullObjectHierarchyUndo(prefabInstanceRoot, actionName);\n                }\n                else\n                    Debug.LogError($\"No undo was registered when removing GameObject {assetGameObject.name} from {assetRoot.name}. \\nError: {errorMessage}\", assetRoot);\n            }\n\n            RemoveRemovedGameObjectOverridesWhichAreNull(prefabInstanceObject);\n\n            Analytics.SendApplyEvent(\n                Analytics.ApplyScope.RemovedGameObject,\n                gameObjectInInstance,\n                AssetDatabase.GetAssetPath(assetGameObject),\n                action,\n                startTime,\n                false\n            );\n\n            PrefabUtility.Internal_CallPrefabInstanceApplied(prefabInstanceRoot);\n        }\n\n        public static void ApplyAddedGameObject(GameObject gameObject, string assetPath, InteractionMode action)\n        {\n            ApplyAddedGameObjects(new GameObject[] { gameObject}, assetPath, action);\n        }\n\n        public static void ApplyAddedGameObjects(GameObject[] gameObjects, string assetPath, InteractionMode action)\n        {\n            DateTime startTime = DateTime.UtcNow;\n\n            if (gameObjects == null)\n                throw new ArgumentNullException(nameof(gameObjects), \"Cannot apply added GameObjects. GameObjects array is null.\");\n\n            if (!gameObjects.Any())\n                throw new ArgumentException(nameof(gameObjects), \"No GameObjects in array.\");\n\n            foreach (GameObject go in gameObjects)\n            {\n                if (go == null)\n                    throw new ArgumentException(nameof(go), \"Input GameObject is null.\");\n\n                if (!IsAddedGameObjectOverride(go))\n                    throw new ArgumentException(nameof(go), $\"Cannot apply added GameObject. GameObject '{go.name}' is not an added GameObject override on a Prefab instance.\");\n\n                ThrowExceptionIfInstanceIsPersistent(go);\n            }\n\n            if (gameObjects.Length > 1 && !HasSameParent(gameObjects))\n                throw new ArgumentException(nameof(gameObjects), \"ApplyAddedGameObjects requires that GameObjects share the same parent.\");\n\n            GameObject gameObject = gameObjects[0];\n            Transform instanceParent = gameObject.transform.parent;\n            if (instanceParent == null)\n                return;\n\n            GameObject prefabSourceGameObjectParent = GetCorrespondingObjectFromSourceAtPath(instanceParent.gameObject, assetPath);\n            if (prefabSourceGameObjectParent == null)\n                return;\n\n            var instanceRoot = GetOutermostPrefabInstanceRoot(instanceParent);\n            if (instanceRoot == null)\n                return;\n\n            var sourceRoot = prefabSourceGameObjectParent.transform.root.gameObject;\n            byte[] originalFileContent = null;\n\n            PrefabUtility.Internal_CallPrefabInstanceApplying(instanceRoot);\n            var actionName = \"Apply Added GameObject\";\n            if (action == InteractionMode.UserAction)\n            {\n                if (!FileUtil.ReadFileContentBinary(assetPath, out originalFileContent, out string errorMessage))\n                    Debug.LogError($\"No undo was registered when removing GameObjects from '{sourceRoot.name}'. \\nError: {errorMessage}\", sourceRoot);\n                else\n                    Undo.RegisterFullObjectHierarchyUndo(instanceRoot, actionName);\n            }\n\n            AddGameObjectsToPrefabAndConnect(gameObjects, prefabSourceGameObjectParent);\n\n            SavePrefabAsset(sourceRoot);\n\n            if (action == InteractionMode.UserAction && originalFileContent != null)\n            {\n                var guid = AssetDatabase.GUIDFromAssetPath(assetPath);\n                if (!FileUtil.ReadFileContentBinary(assetPath, out byte[] newFileContent, out string errorMessage))\n                    Debug.LogError($\"No undo was registered when removing GameObjects from '{sourceRoot.name}'. \\nError: {errorMessage}\", sourceRoot);\n                else\n                    Undo.RegisterFileChangeUndo(guid, originalFileContent, newFileContent);\n            }\n\n            for (int i = 0; i < gameObjects.Length; i++)\n            {\n                GameObject go = gameObjects[i];\n\n                if (action == InteractionMode.UserAction)\n                {\n                    var createdAssetObject = GetCorrespondingObjectFromSourceInAsset(go, prefabSourceGameObjectParent);\n                    if (createdAssetObject != null)\n                    {\n                        Undo.RegisterCreatedObjectUndoToFrontOfUndoQueue(createdAssetObject, actionName);\n                    }\n                }\n\n                Analytics.SendApplyEvent(\n                    Analytics.ApplyScope.AddedGameObject,\n                    instanceRoot,\n                    assetPath,\n                    action,\n                    startTime,\n                    false\n                );\n            }\n\n            PrefabUtility.Internal_CallPrefabInstanceApplied(instanceRoot);\n            EditorUtility.ForceRebuildInspectors();\n        }\n\n        internal static bool HasSameParent(GameObject[] gameObjects)\n        {\n            if (gameObjects == null || !gameObjects.Any() || gameObjects[0] == null)\n                throw new ArgumentException(nameof(gameObjects), \"Array is invalid.\");\n\n            Transform goParent = gameObjects[0].transform.parent;\n\n            if (goParent == null)\n                throw new ArgumentException(nameof(goParent), \"Object is a parentless root.\");\n\n            foreach (GameObject go in gameObjects)\n            {\n                if (go.transform.parent != goParent)\n                    return false;\n            }\n\n            return true;\n        }\n\n        private static void RemoveRemovedGameObjectOverride(Object instanceObject, GameObject assetGameObject)\n        {\n            var removedGameObjects = PrefabUtility.GetRemovedGameObjects(instanceObject);\n            int index = -1;\n            for (int i = 0; i < removedGameObjects.Length; i++)\n            {\n                //Walk the inheritance chain as you can give the base of a variant as the source asset\n                if (IsPrefabInstanceObjectOf(removedGameObjects[i], assetGameObject))\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            if (index != -1)\n            {\n                var filteredRemovedGameObjects = (from go in removedGameObjects where go != removedGameObjects[index] select go).ToArray();\n                PrefabUtility.SetRemovedGameObjects(instanceObject, filteredRemovedGameObjects);\n            }\n        }\n\n        public static void RevertRemovedGameObject(GameObject gameObjectInInstance, GameObject assetGameObject, InteractionMode action)\n        {\n            ThrowExceptionIfNotValidPrefabInstanceObject(gameObjectInInstance, false);\n\n            if (assetGameObject == null)\n                throw new ArgumentNullException(nameof(assetGameObject), \"Prefab source may not be null.\");\n            if (!IsPrefabInstanceObjectOf(gameObjectInInstance, PrefabUtility.GetPrefabAssetHandle(assetGameObject)))\n                throw new ArgumentException(\"Prefab instance should match Prefab source.\");\n            if (assetGameObject.transform.root == assetGameObject.transform)\n                throw new ArgumentException(\"The asset GameObject cannot be the root as the root cannot be removed as an override.\");\n\n            var actionName = \"Revert Prefab removed GameObject\";\n            var prefabInstanceHandle = PrefabUtility.GetPrefabInstanceHandle(gameObjectInInstance);\n\n            GameObject prefabInstanceRoot = GetOutermostPrefabInstanceRoot(gameObjectInInstance);\n\n            if (action == InteractionMode.UserAction)\n                Undo.RegisterFullObjectHierarchyUndo(prefabInstanceRoot, actionName);\n\n            RemoveRemovedGameObjectOverride(prefabInstanceHandle, assetGameObject);\n        }\n\n        public static void RevertAddedGameObject(GameObject gameObject, InteractionMode action)\n        {\n            if (gameObject == null)\n                throw new ArgumentNullException(nameof(gameObject), \"Cannot revert added GameObject. GameObject is null.\");\n\n            if (!IsAddedGameObjectOverride(gameObject))\n                throw new ArgumentException(\"Cannot revert added GameObject. GameObject is not an added GameObject override on a Prefab instance.\", nameof(gameObject));\n\n            ThrowExceptionIfInstanceIsPersistent(gameObject);\n\n            GameObject instance = PrefabUtility.GetOutermostPrefabInstanceRoot(gameObject.transform.parent);\n            PrefabUtility.Internal_CallPrefabInstanceReverting(instance);\n\n            if (action == InteractionMode.UserAction)\n                Undo.DestroyObjectImmediate(gameObject);\n            else\n                Object.DestroyImmediate(gameObject);\n\n            PrefabUtility.Internal_CallPrefabInstanceReverted(instance);\n        }\n\n        public static List<ObjectOverride> GetObjectOverrides(GameObject prefabInstance, bool includeDefaultOverrides = false)\n        {\n            return PrefabOverridesUtility.GetObjectOverrides(prefabInstance, includeDefaultOverrides);\n        }\n\n        public static List<AddedComponent> GetAddedComponents(GameObject prefabInstance)\n        {\n            return PrefabOverridesUtility.GetAddedComponents(prefabInstance);\n        }\n\n        public static List<RemovedComponent> GetRemovedComponents(GameObject prefabInstance)\n        {\n            return PrefabOverridesUtility.GetRemovedComponents(prefabInstance);\n        }\n\n        public static List<AddedGameObject> GetAddedGameObjects(GameObject prefabInstance)\n        {\n            return PrefabOverridesUtility.GetAddedGameObjects(prefabInstance);\n        }\n\n        public static List<RemovedGameObject> GetRemovedGameObjects(GameObject prefabInstance)\n        {\n            return PrefabOverridesUtility.GetRemovedGameObjects(prefabInstance);\n        }\n\n        internal static void HandleApplyRevertMenuItems(\n            string thingThatChanged,\n            Object instanceObject,\n            AddApplyMenuItemDelegate addApplyMenuItemAction,\n            Action<GUIContent> addRevertMenuItemAction,\n            bool isAllDefaultOverridesComparedToOriginalSource = false,\n            int targetCount = 1)\n        {\n            if (targetCount == 1)\n                HandleApplyMenuItems(thingThatChanged, instanceObject, addApplyMenuItemAction, isAllDefaultOverridesComparedToOriginalSource);\n\n            HandleRevertMenuItem(thingThatChanged, addRevertMenuItemAction);\n        }\n\n        internal static void HandleApplyMenuItems(\n            string thingThatChanged,\n            Object instanceOrAssetObject,\n            AddApplyMenuItemDelegate addApplyMenuItemAction,\n            bool isAllDefaultOverridesComparedToOriginalSource = false,\n            bool includeSelfAsTarget = false,\n            bool includeOriginalSelfAsTarget = true)\n        {\n            // If thingThatChanged word is empty, apply menu items directly into menu.\n            // Otherwise, insert as sub-menu named after thingThatChanged.\n            if (thingThatChanged == null)\n                thingThatChanged = String.Empty;\n            if (thingThatChanged != String.Empty)\n                thingThatChanged += \"/\";\n\n            List<Object> applyTargets = GetApplyTargets(instanceOrAssetObject, isAllDefaultOverridesComparedToOriginalSource, includeSelfAsTarget, includeOriginalSelfAsTarget);\n            if (applyTargets == null || applyTargets.Count == 0)\n                return;\n\n            for (int i = 0; i < applyTargets.Count; i++)\n            {\n                Object source = applyTargets[i];\n                GameObject sourceRoot = GetRootGameObject(source);\n\n                var translatedText = L10n.Tr(\"Apply as Override in Prefab '{0}'\");\n                if (i == applyTargets.Count - 1)\n                    translatedText = L10n.Tr(\"Apply to Prefab '{0}'\");\n                GUIContent applyContent = new GUIContent(thingThatChanged + String.Format(translatedText, sourceRoot.name));\n                addApplyMenuItemAction(applyContent, source, instanceOrAssetObject);\n            }\n        }\n\n        internal static void HandleRevertMenuItem(\n            string thingThatChanged,\n            Action<GUIContent> addRevertMenuItemAction)\n        {\n            // If thingThatChanged word is empty, apply menu items directly into menu.\n            // Otherwise, insert as sub-menu named after thingThatChanged.\n            if (thingThatChanged == null)\n                thingThatChanged = String.Empty;\n            if (thingThatChanged != String.Empty)\n                thingThatChanged += \"/\";\n\n            GUIContent revertContent = new GUIContent(thingThatChanged + L10n.Tr(\"Revert\"));\n            addRevertMenuItemAction(revertContent);\n        }\n\n        private static Object GetParentPrefabInstance(GameObject gameObject)\n        {\n            var parent = gameObject.transform.parent;\n            if (parent == null)\n            {\n                return null;\n            }\n            return GetPrefabInstanceHandle(parent);\n        }\n\n        internal static GameObject GetGameObject(Object componentOrGameObject)\n        {\n            GameObject go = componentOrGameObject as GameObject;\n            if (go != null)\n                return go;\n\n            Component comp = componentOrGameObject as Component;\n            if (comp != null)\n                return comp.gameObject;\n\n            return null;\n        }\n\n        internal static GameObject GetRootGameObject(Object componentOrGameObject)\n        {\n            GameObject go = GetGameObject(componentOrGameObject);\n            if (go == null)\n                return null;\n\n            return go.transform.root.gameObject;\n        }\n\n        public static bool IsAnyPrefabInstanceRoot(GameObject gameObject)\n        {\n            GameObject prefabInstanceRoot = GetNearestPrefabInstanceRoot(gameObject);\n            return (gameObject == prefabInstanceRoot);\n        }\n\n        public static bool IsOutermostPrefabInstanceRoot(GameObject gameObject)\n        {\n            GameObject prefabInstanceRoot = GetOutermostPrefabInstanceRoot(gameObject);\n            return (gameObject == prefabInstanceRoot);\n        }\n\n        public static string GetPrefabAssetPathOfNearestInstanceRoot(Object instanceComponentOrGameObject)\n        {\n            return AssetDatabase.GetAssetPath(GetOriginalSourceOrVariantRoot(instanceComponentOrGameObject));\n        }\n\n        [Obsolete(\"The concept of disconnecting Prefab instances has been deprecated. This method always returns False.\")]\n        public static bool IsDisconnectedFromPrefabAsset(Object componentOrGameObject)\n        {\n            return false;\n        }\n\n        [Obsolete(\"The concept of disconnecting Prefab instances has been deprecated. This method does nothing.\")]\n        public static void DisconnectPrefabInstance(Object targetObject)\n        {\n        }\n\n        [Obsolete(\"This method does nothing. Use PrefabUtility.RevertPrefabInstance.\", false)]\n        public static bool ReconnectToLastPrefab(GameObject go)\n        {\n            return false;\n        }\n\n        public static Texture2D GetIconForGameObject(GameObject gameObject)\n        {\n            if (IsAnyPrefabInstanceRoot(gameObject))\n            {\n                if (IsPrefabAssetMissing(gameObject))\n                    return GameObjectStyles.prefabIcon;\n\n                string assetPath = GetPrefabAssetPathOfNearestInstanceRoot(gameObject);\n                return (Texture2D)AssetDatabase.GetCachedIcon(assetPath);\n            }\n            else\n            {\n                return GameObjectStyles.gameObjectIcon;\n            }\n        }\n\n        [Obsolete(\"Use GetCorrespondingObjectFromSource.\")]\n        public static Object GetPrefabParent(Object obj)\n        {\n            return GetCorrespondingObjectFromSource(obj);\n        }\n\n        // Creates an empty prefab at given path.\n        [Obsolete(\"The concept of creating a completely empty Prefab has been discontinued. You can however use SaveAsPrefabAsset with an empty GameObject.\")]\n        public static Object CreateEmptyPrefab(string path)\n        {\n            // This is here to simulate previous behaviour\n            if (Path.GetExtension(path) != \".prefab\")\n            {\n                Debug.LogError(\"Create Prefab path must use .prefab extension\");\n                return null;\n            }\n\n            var empty = new GameObject(\"EmptyPrefab\");\n            bool success;\n            var assetObject = SaveAsPrefabAsset(empty, path, out success);\n            Object.DestroyImmediate(empty);\n            return PrefabUtility.GetPrefabObject(assetObject);\n        }\n\n        public static GameObject SavePrefabAsset(GameObject asset)\n        {\n            bool savedSuccesfully;\n            return SavePrefabAsset(asset, out savedSuccesfully);\n        }\n\n        public static GameObject SavePrefabAsset(GameObject asset, out bool savedSuccessfully)\n        {\n            if (asset == null)\n                throw new ArgumentNullException(\"Parameter prefabAssetGameObject is null\");\n\n            // Include model check even though models are also immutable, since we can give a more clear exception message.\n            if (IsPartOfModelPrefab(asset))\n                throw new ArgumentException(\"Can't save a Model Prefab\");\n\n            if (IsPartOfImmutablePrefab(asset))\n                throw new ArgumentException(\"Can't save an immutable Prefab\");\n\n            string path = AssetDatabase.GetAssetPath(asset);\n            if (String.IsNullOrEmpty(path))\n                throw new ArgumentException(\"Can't save a Prefab instance\");\n\n            var root = asset.transform.root.gameObject;\n            if (root != asset)\n                throw new ArgumentException(\"GameObject to save Prefab from must be a Prefab root\");\n\n            return SavePrefabAsset_Internal(root, out savedSuccessfully);\n        }\n\n        internal static void ValidatePath(GameObject instanceRoot, string path)\n        {\n            if (String.IsNullOrEmpty(path))\n                throw new ArgumentNullException(\"path is null or empty\");\n\n            if (!Paths.IsValidAssetPath(path, \".prefab\"))\n                throw new ArgumentException(\"Given path is not valid: '\" + path + \"'\");\n\n            if (Directory.Exists(path))\n                throw new ArgumentException(\"Overwriting a folder with an Asset is not allowed: '\" + path + \"'\");\n\n            string directory = Path.GetDirectoryName(path);\n\n            // We allow relative paths outside the Assets folder so we do not throw if isValidAssetFolder is false\n            bool isRootFolder = false;\n            bool isImmutableFolder = false;\n            bool isValidAssetFolder = AssetDatabase.TryGetAssetFolderInfo(directory, out isRootFolder, out isImmutableFolder);\n\n            if (isValidAssetFolder && isImmutableFolder)\n                throw new ArgumentException(\"Saving Prefab to immutable folder is not allowed: '\" + path + \"'\");\n\n            if (directory.Length > 0 && !Directory.Exists(directory))\n                throw new ArgumentException(\"Given path does not exist: '\" + path + \"'\");\n\n            if (isValidAssetFolder)\n            {\n                string projectRelativePath = Path.IsPathRooted(path) ? FileUtil.GetProjectRelativePath(path) : path;\n                string prefabGUID = AssetDatabase.AssetPathToGUID(projectRelativePath);\n                if (!VerifyNestingFromScript(new GameObject[] { instanceRoot }, prefabGUID, PrefabUtility.GetPrefabInstanceHandle(instanceRoot)))\n                    throw new ArgumentException(\"Cyclic nesting detected\");\n            }\n        }\n\n        private static void SaveAsPrefabAssetArgumentCheck(GameObject instanceRoot, string path, bool connectToInstance)\n        {\n            if (instanceRoot == null)\n                throw new ArgumentNullException(\"Parameter root is null\");\n\n            if (EditorUtility.IsPersistent(instanceRoot) && connectToInstance)\n                throw new ArgumentException(\"Can't save persistent Objects and connect them to the saved Prefab\");\n\n            if (IsPartOfNonAssetPrefabInstance(instanceRoot))\n            {\n                // A PrefabInstance with missing asset can be correctly restored only if CorrespondingObjects info is available\n                // CorrespondingObject info is available when a PrefabInstance with missing asset was merged before deleting the asset (kNormalMerge) or when it has a scene backup (kMergedAsMissingWithSceneBackup)\n                var mergeStatus = GetMergeStatus(instanceRoot);\n                var hasCorrespondingSourceObjectInfo = mergeStatus == MergeStatus.NormalMerge || mergeStatus == MergeStatus.MergedAsMissingWithSceneBackup;\n                if (IsPrefabAssetMissing(instanceRoot) && !hasCorrespondingSourceObjectInfo)\n                    throw new ArgumentException(\"Can't save Prefab instance with missing asset and scene backup as a Prefab. You may unpack the instance and save the unpacked GameObjects as a Prefab.\");\n            }\n\n            var actualInstanceRoot = GetOutermostPrefabInstanceRoot(instanceRoot);\n            if (actualInstanceRoot)\n            {\n                if (actualInstanceRoot != instanceRoot)\n                    throw new ArgumentException(\"Can't save part of a Prefab instance as a Prefab\");\n            }\n\n            ValidatePath(instanceRoot, path);\n        }\n\n        private static void ReplacePrefabArgumentCheck(GameObject root, string path)\n        {\n            if (root == null)\n                throw new ArgumentNullException(\"Parameter root is null\");\n\n            ValidatePath(root, path);\n        }\n\n        public static GameObject SaveAsPrefabAsset(GameObject instanceRoot, string assetPath, out bool success)\n        {\n            SaveAsPrefabAssetArgumentCheck(instanceRoot, assetPath, false);\n\n            return SaveAsPrefabAsset_Internal(instanceRoot, assetPath, out success);\n        }\n\n        public static GameObject SaveAsPrefabAsset(GameObject instanceRoot, string assetPath)\n        {\n            bool success;\n            return SaveAsPrefabAsset(instanceRoot, assetPath, out success);\n        }\n\n        public static GameObject SaveAsPrefabAssetAndConnect(GameObject instanceRoot, string assetPath, InteractionMode action)\n        {\n            bool success;\n            return SaveAsPrefabAssetAndConnect(instanceRoot, assetPath, action, out success);\n        }\n\n        public static GameObject SaveAsPrefabAssetAndConnect(GameObject instanceRoot, string assetPath, InteractionMode action, out bool success)\n        {\n            SaveAsPrefabAssetArgumentCheck(instanceRoot, assetPath, true);\n\n            if (IsPathInStreamingAssets(assetPath))\n                throw new ArgumentException(\"Can't connect a Prefab in the StreamingAssets folder to GameObjects in the scene. To save a Prefab to the StreamingAssets folder use SaveAsPrefabAsset instead.\");\n\n            var actionName = \"Connect to Prefab\";\n\n            if (action == InteractionMode.UserAction)\n            {\n                Undo.RegisterFullObjectHierarchyUndo(instanceRoot, actionName);\n            }\n\n            var assetRoot = SaveAsPrefabAssetAndConnect_Internal(instanceRoot, assetPath, out success);\n\n            if (!success)\n            {\n                return null;\n            }\n\n            if (action == InteractionMode.UserAction)\n            {\n                Undo.RecordCreatedObject(GetPrefabInstanceHandle(instanceRoot), actionName);\n            }\n\n            return assetRoot;\n        }\n\n        internal static void ApplyPrefabInstance(GameObject instance)\n        {\n            if (instance == null)\n                throw new ArgumentNullException(nameof(instance));\n\n            // Include model check even though models are also immutable, since we can give a more clear exception message.\n            if (IsPartOfModelPrefab(instance))\n                throw new ArgumentException(\"Can't apply to a Model Prefab\");\n\n            if (IsPartOfImmutablePrefab(instance))\n                throw new ArgumentException(\"Can't apply to an immutable Prefab\");\n\n            if (!IsPartOfNonAssetPrefabInstance(instance))\n                throw new ArgumentException(\"Provided GameObject is not a Prefab instance\");\n\n            var root = GetOutermostPrefabInstanceRoot(instance);\n            if (root != instance)\n                throw new ArgumentException(\"GameObject to save Prefab from must be a Prefab root\");\n\n            var assetObject = GetCorrespondingObjectFromSource(instance);\n            string path = AssetDatabase.GetAssetPath(assetObject);\n\n            SaveAsPrefabAssetArgumentCheck(instance, path, true);\n\n            Internal_CallPrefabInstanceApplying(instance);\n\n            ApplyPrefabInstance_Internal(instance);\n\n            Internal_CallPrefabInstanceApplied(instance);\n        }\n\n        // Can't use UnityUpgradable since it doesn't currently support swapping parameter order.\n        [Obsolete(\"Use SaveAsPrefabAsset instead.\")]\n        public static GameObject CreatePrefab(string path, GameObject go)\n        {\n            return SaveAsPrefabAsset(go, path);\n        }\n\n        [Obsolete(\"Use SaveAsPrefabAsset or SaveAsPrefabAssetAndConnect instead.\")]\n        public static GameObject CreatePrefab(string path, GameObject go, ReplacePrefabOptions options)\n        {\n            if ((options & ReplacePrefabOptions.ConnectToPrefab) != 0)\n                return SaveAsPrefabAssetAndConnect(go, path, InteractionMode.AutomatedAction);\n            else\n                return SaveAsPrefabAsset(go, path);\n        }\n\n        // Instantiates the given prefab.\n        public static Object InstantiatePrefab(Object assetComponentOrGameObject)\n        {\n            return InstantiatePrefab_internal(assetComponentOrGameObject, EditorSceneManager.GetTargetSceneForNewGameObjects(), null);\n        }\n\n        // Instantiates the given prefab in a given scene\n        public static Object InstantiatePrefab(Object assetComponentOrGameObject, Scene destinationScene)\n        {\n            return InstantiatePrefab_internal(assetComponentOrGameObject, destinationScene, null);\n        }\n\n        public static Object InstantiatePrefab(Object assetComponentOrGameObject, Transform parent)\n        {\n            return InstantiatePrefab_internal(assetComponentOrGameObject, EditorSceneManager.GetTargetSceneForNewGameObjects(), parent);\n        }\n\n        internal static void ThrowIfInvalidAssetForReplacePrefabInstance(GameObject prefabAsset, InteractionMode action)\n        {\n            if (prefabAsset == null)\n                throw new ArgumentNullException(nameof(prefabAsset));\n\n            if (!EditorUtility.IsPersistent(prefabAsset))\n                throw new ArgumentException(\"Input Prefab asset is not an asset object. Input asset: \" + prefabAsset.name, nameof(prefabAsset));\n\n            var assetPath = AssetDatabase.GetAssetPath(prefabAsset);\n            if (assetPath.StartsWith(\"Library/\"))\n                throw new InvalidOperationException(string.Format(\"Cannot replace the Prefab instance since the Prefab Asset is invalid for instance replacement. Prefab Asset path: \" + assetPath));\n\n            // Recording undo does not handle missing scripts\n            var gameObjectsWithInvalidScript = FindGameObjectsWithInvalidComponent(prefabAsset);\n            if (action == InteractionMode.UserAction && gameObjectsWithInvalidScript.Count > 0)\n                throw new InvalidOperationException(string.Format($\"Cannot replace the Prefab instance with the Prefab Asset '{AssetDatabase.GetAssetPath(prefabAsset)}' because it has a missing script. GameObject '{gameObjectsWithInvalidScript[0].name}' in the Prefab Asset has a missing script.\"));\n        }\n\n        internal static void ThrowIfInvalidArgumentsForReplacePrefabInstance(GameObject prefabInstanceRoot, GameObject prefabAssetRoot, bool checkValidAsset, InteractionMode mode)\n        {\n            if (prefabInstanceRoot == null)\n                throw new ArgumentNullException(nameof(prefabInstanceRoot));\n\n            if (prefabAssetRoot == null)\n                throw new ArgumentNullException(nameof(prefabAssetRoot));\n\n            if (checkValidAsset)\n                ThrowIfInvalidAssetForReplacePrefabInstance(prefabAssetRoot, mode);\n\n            if (!IsPartOfNonAssetPrefabInstance(prefabInstanceRoot))\n                throw new InvalidOperationException(string.Format(\"Input '{0}' is not a Prefab instance, for plain GameObjects use ConvertToPrefabInstance() instead\", prefabInstanceRoot.name));\n\n            if (!IsOutermostPrefabInstanceRoot(prefabInstanceRoot))\n                throw new ArgumentException(\"Input instance is not an outermost Prefab instance root. Input instance: \" + prefabInstanceRoot.name, nameof(prefabInstanceRoot));\n            if (EditorUtility.IsPersistent(prefabInstanceRoot))\n                throw new ArgumentException(\"Input instance root is from a Prefab asset, this is not supported. Input instance: \" + prefabInstanceRoot.name, nameof(prefabInstanceRoot));\n\n            if (PrefabStageUtility.IsGameObjectThePrefabRootInAnyPrefabStage(prefabInstanceRoot))\n                throw new InvalidOperationException(\"Replacing the root Prefab instance in a Variant is not supported since it will break all overrides for existing instances of this Variant, including their positions and rotations.\" + prefabInstanceRoot.name);\n            if (IsAnyPrefabInstanceRoot(prefabInstanceRoot) && EditorSceneManager.IsPreviewSceneObject(prefabInstanceRoot) && prefabInstanceRoot.transform.parent == null) // EditPrefabContentsScope handling\n                throw new InvalidOperationException(\"Replacing the Variant parent is not supported since it will break all overrides for existing instances of this Variant, including their positions and rotations.\" + prefabInstanceRoot.name);\n            if (prefabInstanceRoot.transform.GetType() != prefabAssetRoot.transform.GetType())\n                throw new InvalidOperationException(string.Format(\"Cannot replace the Prefab instance '{0}' with root transform of type {1} with a Prefab asset with root transform of type {2}. Transform types must match.\", prefabInstanceRoot.name, prefabInstanceRoot.transform.GetType().Name, prefabAssetRoot.transform.GetType().Name));\n\n            if (prefabInstanceRoot.hideFlags.HasFlag(HideFlags.DontSaveInEditor) || prefabInstanceRoot.transform.hideFlags.HasFlag(HideFlags.DontSaveInEditor))\n                throw new ArgumentException(\"Input instance root is using the HideFlags.DontSaveInEditor flag which is not supported when replacing: Input instance: \" + prefabInstanceRoot.name, nameof(prefabInstanceRoot));\n\n            if (mode == InteractionMode.UserAction)\n            {\n                // Recording undo does not handle missing scripts\n                var gameObjectsWithInvalidScript = FindGameObjectsWithInvalidComponent(prefabInstanceRoot);\n                if (gameObjectsWithInvalidScript.Count > 0)\n                    throw new InvalidOperationException(string.Format($\"Cannot replace the Prefab instance when it has a missing script. GameObject '{gameObjectsWithInvalidScript[0].name}' has a missing script. Use InteractionMode.AutomatedAction to force the replace.\"));\n            }\n        }\n\n        public static void ReplacePrefabAssetOfPrefabInstances(GameObject[] prefabInstanceRoots, GameObject prefabAssetRoot, InteractionMode mode)\n        {\n            ReplacePrefabAssetOfPrefabInstances(prefabInstanceRoots, prefabAssetRoot, new PrefabReplacingSettings(), mode);\n        }\n\n        public static void ReplacePrefabAssetOfPrefabInstances(GameObject[] prefabInstanceRoots, GameObject prefabAssetRoot, PrefabReplacingSettings settings, InteractionMode mode)\n        {\n            if (prefabInstanceRoots == null)\n                throw new ArgumentNullException(nameof(prefabInstanceRoots));\n\n            if (prefabInstanceRoots.Length == 0)\n                throw new ArgumentException(nameof(prefabInstanceRoots) + \" has no objects\");\n\n            if (settings == null)\n                throw new ArgumentNullException(nameof(settings));\n\n            ThrowIfInvalidAssetForReplacePrefabInstance(prefabAssetRoot, mode);\n            foreach (var go in prefabInstanceRoots)\n                ThrowIfInvalidArgumentsForReplacePrefabInstance(go, prefabAssetRoot, false, mode);\n\n            foreach (var go in prefabInstanceRoots)\n                ReplacePrefabAssetOfPrefabInstance_NoInputValidation(go, prefabAssetRoot, settings, mode);\n\n            EditorUtility.ForceRebuildInspectors();\n        }\n\n        public static void ReplacePrefabAssetOfPrefabInstance(GameObject prefabInstanceRoot, GameObject prefabAssetRoot, InteractionMode mode)\n        {\n            ReplacePrefabAssetOfPrefabInstance(prefabInstanceRoot, prefabAssetRoot, new PrefabReplacingSettings(), mode);\n        }\n\n        public static void ReplacePrefabAssetOfPrefabInstance(GameObject prefabInstanceRoot, GameObject prefabAssetRoot, PrefabReplacingSettings settings, InteractionMode mode)\n        {\n            ThrowIfInvalidArgumentsForReplacePrefabInstance(prefabInstanceRoot, prefabAssetRoot, true, mode);\n            if (settings == null)\n                throw new ArgumentNullException(nameof(settings));\n\n            ReplacePrefabAssetOfPrefabInstance_NoInputValidation(prefabInstanceRoot, prefabAssetRoot, settings, mode);\n\n            EditorUtility.ForceRebuildInspectors();\n        }\n\n        private static void ReplacePrefabAssetOfPrefabInstance_NoInputValidation(GameObject prefabInstanceRoot, GameObject prefabAssetRoot, PrefabReplacingSettings settings, InteractionMode mode)\n        {\n            if (GetCorrespondingConnectedObjectFromSource(prefabInstanceRoot) == prefabAssetRoot)\n            {\n                // No need to replace, already using the input Prefab Asset\n                return;\n            }\n\n            var undoActionName = \"Replace Prefab Instance\";\n            if (mode == InteractionMode.UserAction)\n            {\n                Undo.FlushTrackedObjects();\n                Undo.SetCurrentGroupName(undoActionName);\n                Undo.RegisterFullObjectHierarchyUndo(prefabInstanceRoot, undoActionName);\n            }\n\n            bool success = ReplacePrefabAssetOfPrefabInstance_Internal(prefabInstanceRoot, prefabAssetRoot, settings);\n            if (!success)\n            {\n                Debug.LogError(string.Format(\"Replace Prefab Instance failed for instance '{0}' using asset '{1}' at '{2}'\", prefabInstanceRoot.name, prefabAssetRoot.name, AssetDatabase.GetAssetPath(prefabAssetRoot)), prefabInstanceRoot);\n            }\n\n            if (mode == InteractionMode.UserAction)\n                Undo.FlushTrackedObjects();\n        }\n\n        internal static void ThrowIfInvalidArgumentsForConvertToPrefabInstance(GameObject plainGameObject, GameObject prefabAssetRoot, bool checkValidAsset, InteractionMode mode)\n        {\n            if (plainGameObject == null)\n                throw new ArgumentNullException(nameof(plainGameObject));\n\n            if (prefabAssetRoot == null)\n                throw new ArgumentNullException(nameof(prefabAssetRoot));\n\n            if (IsPartOfNonAssetPrefabInstance(plainGameObject))\n                throw new InvalidOperationException(string.Format(\"Input '{0}' is not a plain GameObject, it is already a Prefab instance. Use ReplacePrefabAssetOfPrefabInstance() instead.\", plainGameObject.name));\n\n            if (EditorUtility.IsPersistent(plainGameObject))\n                throw new ArgumentException(\"Input is from a Prefab asset, this is not supported. Input GameObject: \" + plainGameObject.name, nameof(plainGameObject));\n\n            if (checkValidAsset)\n                ThrowIfInvalidAssetForReplacePrefabInstance(prefabAssetRoot, mode);\n\n            if (plainGameObject.transform.GetType() != prefabAssetRoot.transform.GetType())\n                throw new InvalidOperationException(string.Format(\"Cannot convert the GameObject '{0}' with root transform of type {1} with a Prefab asset with root transform of type {2}. Transform types must match.\", plainGameObject.name, plainGameObject.transform.GetType().Name, prefabAssetRoot.transform.GetType().Name));\n\n            // Prefab Mode and EditPrefabContents scope handling\n            if (PrefabStageUtility.IsGameObjectThePrefabRootInAnyPrefabStage(plainGameObject) || (EditorSceneManager.IsPreviewSceneObject(plainGameObject) && plainGameObject.transform.parent == null))\n                throw new InvalidOperationException(\"Replacing the root GameObject in a Prefab with a Prefab instance is not supported since it will break all overrides for existing instances of this Prefab, including their positions and rotations.\" + plainGameObject.name);\n\n            if (plainGameObject.hideFlags.HasFlag(HideFlags.DontSaveInEditor) || plainGameObject.transform.hideFlags.HasFlag(HideFlags.DontSaveInEditor))\n                throw new ArgumentException(\"Input GameObject is using the HideFlags.DontSaveInEditor flag which is not supported when converting to Prefab instance: GameObject: \" + plainGameObject.name, nameof(plainGameObject));\n\n            if (mode == InteractionMode.UserAction)\n            {\n                // Recording undo does not handle missing scripts\n                var gameObjectsWithInvalidScript = FindGameObjectsWithInvalidComponent(plainGameObject);\n                if (gameObjectsWithInvalidScript.Count > 0)\n                    throw new InvalidOperationException(string.Format($\"Cannot convert the GameObject when it has a missing script. GameObject '{gameObjectsWithInvalidScript[0].name}' has a missing script. This is not supported by the Undo system. Use InteractionMode.AutomatedAction instead.\"));\n            }\n        }\n\n        public static void ConvertToPrefabInstance(GameObject plainGameObject, GameObject prefabAssetRoot, ConvertToPrefabInstanceSettings settings, InteractionMode mode)\n        {\n            ThrowIfInvalidArgumentsForConvertToPrefabInstance(plainGameObject, prefabAssetRoot, true, mode);\n\n            ConvertToPrefabInstance_NoInputValidation(plainGameObject, prefabAssetRoot, settings, mode);\n\n            EditorUtility.ForceRebuildInspectors();\n        }\n\n        public static void ConvertToPrefabInstances(GameObject[] plainGameObjects, GameObject prefabAssetRoot, ConvertToPrefabInstanceSettings settings, InteractionMode mode)\n        {\n            if (plainGameObjects == null)\n                throw new ArgumentNullException(nameof(plainGameObjects));\n\n            if (plainGameObjects.Length == 0)\n                throw new ArgumentException(nameof(plainGameObjects) + \" has no objects\");\n\n            foreach(var go in plainGameObjects)\n                if (go == null)\n                    throw new ArgumentException(nameof(plainGameObjects) + \" has a null GameObject\");\n\n            if (settings == null)\n                throw new ArgumentNullException(nameof(settings));\n\n            ThrowIfInvalidAssetForReplacePrefabInstance(prefabAssetRoot, mode);\n\n            var topLevelGameObjects = GetTopLevelGameObjects(plainGameObjects);\n            foreach (var go in topLevelGameObjects)\n                ThrowIfInvalidArgumentsForConvertToPrefabInstance(go, prefabAssetRoot, false, mode);\n\n            foreach (var go in topLevelGameObjects)\n                ConvertToPrefabInstance_NoInputValidation(go, prefabAssetRoot, settings, mode);\n\n            EditorUtility.ForceRebuildInspectors();\n        }\n\n        private static void ConvertToPrefabInstance_NoInputValidation(GameObject plainGameObject, GameObject prefabAssetRoot, ConvertToPrefabInstanceSettings settings, InteractionMode mode)\n        {\n            var undoActionName = \"Convert to Prefab Instance\";\n            if (mode == InteractionMode.UserAction)\n            {\n                Undo.FlushTrackedObjects();\n\n                // Make sure all instance are unpacked so the merge code can delete GameObjects that are not matched\n                TransformVisitor visitor = new TransformVisitor();\n                visitor.VisitAll(plainGameObject.transform, (transform, userdata) => {\n                    GameObject go = transform.gameObject;\n                    if (IsOutermostPrefabInstanceRoot(go))\n                    {\n                        UnpackPrefabInstance(go, PrefabUnpackMode.Completely, InteractionMode.UserAction);\n                    }\n                }, null);\n\n                Undo.SetCurrentGroupName(undoActionName);\n                Undo.RegisterFullObjectHierarchyUndo(plainGameObject, undoActionName);\n            }\n\n            bool success = ConvertToPrefabInstance_Internal(plainGameObject, prefabAssetRoot, settings);\n            if (!success)\n            {\n                Debug.LogError(string.Format(\"Converting plain GameObject to Prefab instance failed for GameObject '{0}' using asset '{1}' at '{2}'\", plainGameObject.name, prefabAssetRoot.name, AssetDatabase.GetAssetPath(prefabAssetRoot)), plainGameObject);\n            }\n\n            if (mode == InteractionMode.UserAction)\n                Undo.FlushTrackedObjects();\n        }\n\n        static bool ContainsParent(GameObject go, HashSet<GameObject> gameObjectSet)\n        {\n            Transform parent = go.transform.parent;\n            while (parent)\n            {\n                if (gameObjectSet.Contains(parent.gameObject))\n                    break;\n                parent = parent.parent;\n            }\n\n            if (parent == null)\n                return false;\n            else\n                return true;\n        }\n\n        static List<GameObject> GetTopLevelGameObjects(GameObject[] gameObjects)\n        {\n            List<GameObject> result = new List<GameObject>();\n            HashSet<GameObject> gameObjectHashSet = new HashSet<GameObject>(gameObjects);\n\n            foreach (var go in gameObjects)\n            {\n                if (!ContainsParent(go, gameObjectHashSet))\n                    result.Add(go);\n            }\n\n            return result;\n        }\n\n        internal static void InstantiateDraggedPrefabUpon(GameObject draggedUponGameObject, GameObject prefabAssetRoot)\n        {\n            InstantiateDraggedPrefabUpon_Internal(draggedUponGameObject, prefabAssetRoot);\n        }\n\n        [Obsolete(\"Use SaveAsPrefabAsset with a path instead.\")]\n        public static GameObject ReplacePrefab(GameObject go, Object targetPrefab)\n        {\n            return ReplacePrefab(go, targetPrefab, ReplacePrefabOptions.Default);\n        }\n\n        [Obsolete(\"Use SaveAsPrefabAsset or SaveAsPrefabAssetAndConnect with a path instead.\")]\n        public static GameObject ReplacePrefab(GameObject go, Object targetPrefab, ReplacePrefabOptions replaceOptions)\n        {\n            var targetPrefabObject = PrefabUtility.GetPrefabObject(targetPrefab);\n\n            // Previously ReplacePrefab didn't throw any exceptions\n            // This reimplements the previous error handling\n            if (targetPrefabObject == null)\n            {\n                Debug.LogError(\"The object you are trying to replace does not exist or is not a Prefab.\");\n                return null;\n            }\n\n            if (!EditorUtility.IsPersistent(targetPrefabObject))\n            {\n                Debug.LogError(\"The Prefab you are trying to replace is not a Prefab Asset but a Prefab instance. Please use PrefabUtility.GetCorrespondingObject().\", targetPrefab);\n                return null;\n            }\n\n            if (HideFlags.DontSaveInEditor == (HideFlags.DontSaveInEditor & go.hideFlags))\n            {\n                Debug.LogError(\"The root GameObject of the Prefab source cannot be marked with DontSaveInEditor as it would create an empty Prefab.\", go);\n                return null;\n            }\n\n            // Make sure the source object is not the same as the target prefab\n            Object sourcePrefab = PrefabUtility.GetPrefabObject(go);\n            if (sourcePrefab != null)\n            {\n                if (sourcePrefab == targetPrefabObject)\n                {\n                    Debug.LogError(\"A prefab asset cannot replace itself\", go);\n                    return null;\n                }\n            }\n\n            var assetPath = AssetDatabase.GetAssetPath(targetPrefabObject);\n\n            ReplacePrefabArgumentCheck(go, assetPath);\n\n            bool connectToInstance = ((replaceOptions & ReplacePrefabOptions.ConnectToPrefab) != 0) && !EditorUtility.IsPersistent(go);\n\n            bool success = false;\n            return SavePrefab_Internal(go, assetPath, connectToInstance, out success);\n        }\n\n        // Returns the corresponding object from its immediate source from a connected Prefab,\n        // or null if it can't be found\n        internal static TObject GetCorrespondingConnectedObjectFromSource<TObject>(TObject componentOrGameObject) where TObject : Object\n        {\n            return (TObject)GetCorrespondingObjectFromSource_internal(componentOrGameObject);\n        }\n\n        // Returns the corresponding object from its immediate source, or null if it can't be found.\n        public static TObject GetCorrespondingObjectFromSource<TObject>(TObject componentOrGameObject) where TObject : Object\n        {\n            return (TObject)GetCorrespondingObjectFromSource_internal(componentOrGameObject);\n        }\n\n        // Returns the corresponding object from its original source, or null if it can't be found.\n        public static TObject GetCorrespondingObjectFromOriginalSource<TObject>(TObject componentOrGameObject) where TObject : Object\n        {\n            return (TObject)GetCorrespondingObjectFromOriginalSource_Internal(componentOrGameObject);\n        }\n\n        internal static TObject GetCorrespondingObjectFromSourceInAsset<TObject>(TObject instanceOrAsset, Object prefabAssetHandle) where TObject : Object\n        {\n            return (TObject)GetCorrespondingObjectFromSourceInAsset_internal(instanceOrAsset, prefabAssetHandle);\n        }\n\n        public static TObject GetCorrespondingObjectFromSourceAtPath<TObject>(TObject componentOrGameObject, string assetPath) where TObject : Object\n        {\n            return (TObject)GetCorrespondingObjectFromSourceAtPath_internal(componentOrGameObject, assetPath);\n        }\n\n        // Call native functon instead once it exists.\n        private static Object GetCorrespondingObjectFromOriginalSource_Internal(Object instanceOrAsset)\n        {\n            var sourceObjectInPrefabAsset = instanceOrAsset;\n\n            // First one is mandatory for non-persistant asset,\n            // since we want the result to be null if there's asset object at all.\n            if (!EditorUtility.IsPersistent(sourceObjectInPrefabAsset))\n            {\n                sourceObjectInPrefabAsset = GetCorrespondingObjectFromSource(sourceObjectInPrefabAsset);\n                if (sourceObjectInPrefabAsset == null)\n                    return null;\n            }\n\n            while (true)\n            {\n                var inner = GetCorrespondingObjectFromSource(sourceObjectInPrefabAsset);\n                if (inner == null)\n                    return sourceObjectInPrefabAsset;\n                sourceObjectInPrefabAsset = inner;\n            }\n        }\n\n        // Given an object, returns its prefab type (None, if it's not a prefab)\n        [Obsolete(\"Use GetPrefabAssetType and GetPrefabInstanceStatus to get the full picture about Prefab types.\")]\n        public static PrefabType GetPrefabType(Object target)\n        {\n            if (!IsPartOfAnyPrefab(target))\n                return PrefabType.None;\n\n            bool isModel = IsPartOfModelPrefab(target);\n\n            if (IsPartOfPrefabAsset(target))\n            {\n                if (isModel)\n                    return PrefabType.ModelPrefab;\n\n                return PrefabType.Prefab;\n            }\n\n            if (IsPrefabAssetMissing(target))\n                return PrefabType.MissingPrefabInstance;\n\n            if (isModel)\n                return PrefabType.ModelPrefabInstance;\n\n            return PrefabType.PrefabInstance;\n        }\n\n        // Called after prefab instances in the scene have been updated\n        public delegate void PrefabInstanceUpdated(GameObject instance);\n        public static PrefabInstanceUpdated prefabInstanceUpdated;\n        private static DelegateWithPerformanceTracker<PrefabInstanceUpdated> m_PrefabInstanceUpdated = new DelegateWithPerformanceTracker<PrefabInstanceUpdated>($\"{nameof(PrefabUtility)}.{nameof(prefabInstanceUpdated)}\");\n\n        [RequiredByNativeCode]\n        private static void Internal_CallPrefabInstanceUpdated(GameObject instance)\n        {\n            foreach (var evt in m_PrefabInstanceUpdated.UpdateAndInvoke(prefabInstanceUpdated))\n                evt(instance);\n        }\n\n        public static bool IsAddedGameObjectOverride(GameObject gameObject)\n        {\n            if (gameObject == null)\n                throw new ArgumentNullException(nameof(gameObject), \"GameObject is null.\");\n\n            Transform parent = gameObject.transform.parent;\n            if (parent == null)\n                return false;\n\n            // Can't be added to a prefab instance if the parent is not part of a prefab instance.\n            GameObject parentAsset = (GameObject)PrefabUtility.GetCorrespondingObjectFromSource(parent.gameObject);\n            if (parentAsset == null)\n                return false;\n\n            GameObject asset = (GameObject)PrefabUtility.GetCorrespondingObjectFromSource(gameObject);\n\n            // If object is not part of a prefab (but the parent is) we know it's added.\n            if (asset == null)\n                return true;\n\n            // We know now that the object is part of a prefab.\n            // If the root of that prefab, then it can't be part of the parent prefab, and must be added.\n            // This check works regardless of whether this prefab instance is an instance of the same\n            // prefab asset as the parent is an instance of (e.g. instance of A is added under instance of A),\n            // or not (instance of B is added under instance of A).\n            return (asset.transform.parent == null);\n        }\n\n        internal static bool IsAllAddedGameObjectOverrides(GameObject[] gameObjects)\n        {\n            foreach (GameObject go in gameObjects)\n            {\n                if (!PrefabUtility.IsAddedGameObjectOverride(go))\n                    return false;\n            }\n            return true;\n        }\n\n        // Called before the prefab is saved to hdd (called after AssetModificationProcessor.OnWillSaveAssets and before OnPostprocessAllAssets)\n        internal static event Action<GameObject, string> savingPrefab;\n        [RequiredByNativeCode]\n        static void Internal_SavingPrefab(GameObject gameObject, string path)\n        {\n            if (savingPrefab != null)\n                savingPrefab(gameObject, path);\n        }\n\n        internal static event Action prefabInstanceModificationCacheCleared;\n        [RequiredByNativeCode]\n        static void Internal_PrefabInstanceModificationCacheCleared()\n        {\n            if (prefabInstanceModificationCacheCleared != null)\n                prefabInstanceModificationCacheCleared();\n        }\n\n        internal enum SaveVerb\n        {\n            Save,\n            Apply\n        }\n\n        [RequiredByNativeCode]\n        internal static bool PromptAndCheckoutPrefabIfNeeded_Internal(string[] assetPaths, SaveVerb saveVerb)\n        {\n            return PromptAndCheckoutPrefabIfNeeded(assetPaths, saveVerb);\n        }\n\n        internal static bool PromptAndCheckoutPrefabIfNeeded(string assetPath, SaveVerb saveVerb)\n        {\n            return PromptAndCheckoutPrefabIfNeeded(new string[] { assetPath }, saveVerb);\n        }\n\n        internal static bool PromptAndCheckoutPrefabIfNeeded(string[] assetPaths, SaveVerb saveVerb)\n        {\n            // Some strings in these dialogs are nearly identical.\n            // They are included like this instead of being created programatically\n            // in order for localization strings to have sufficient context.\n\n            string prefabNoun = assetPaths.Length > 1 ? L10n.Tr(\"Prefabs\") : L10n.Tr(\"Prefab\");\n            bool result = AssetDatabase.MakeEditable(\n                assetPaths,\n                string.Format(\n                    saveVerb == SaveVerb.Save ?\n                    L10n.Tr(\"The version control requires you to check out the {0} before saving changes.\") :\n                    L10n.Tr(\"The version control requires you to check out the {0} before applying changes.\"),\n                    prefabNoun\n                )\n            );\n\n            if (!result)\n                EditorUtility.DisplayDialog(\n                    String.Format(\n                        saveVerb == SaveVerb.Save ?\n                        L10n.Tr(\"Could not save {0}\") :\n                        L10n.Tr(\"Could not apply to {0}\"),\n                        prefabNoun),\n                    String.Format(\n                        saveVerb == SaveVerb.Save ?\n                        L10n.Tr(\"It was not possible to check out the {0} so the save operation has been canceled.\") :\n                        L10n.Tr(\"It was not possible to check out the {0} so the apply operation has been canceled.\"),\n                        prefabNoun),\n                    L10n.Tr(\"OK\"));\n\n            return result;\n        }\n\n        public static event Action<GameObject> prefabInstanceReverting;\n        public static event Action<GameObject> prefabInstanceReverted;\n\n        [RequiredByNativeCode]\n        internal static void Internal_CallPrefabInstanceReverting(GameObject instanceRoot)\n        {\n            Assert.IsNotNull(instanceRoot);\n\n            prefabInstanceReverting?.Invoke(instanceRoot);\n        }\n\n        [RequiredByNativeCode]\n        internal static void Internal_CallPrefabInstanceReverted(GameObject instanceRoot)\n        {\n            Assert.IsNotNull(instanceRoot);\n\n            prefabInstanceReverted?.Invoke(instanceRoot);\n        }\n\n        public static event Action<GameObject, PrefabUnpackMode> prefabInstanceUnpacking;\n        public static event Action<GameObject, PrefabUnpackMode> prefabInstanceUnpacked;\n\n        public static void UnpackPrefabInstance(GameObject instanceRoot, PrefabUnpackMode unpackMode, InteractionMode action)\n        {\n            if (instanceRoot == null)\n                throw new ArgumentNullException(nameof(instanceRoot));\n\n            if (!IsPartOfNonAssetPrefabInstance(instanceRoot))\n                throw new ArgumentException(\"UnpackPrefabInstance must be called with a Prefab instance.\");\n\n            if (!IsOutermostPrefabInstanceRoot(instanceRoot))\n                throw new ArgumentException(\"UnpackPrefabInstance must be called with a root Prefab instance GameObject.\");\n\n            if (action == InteractionMode.UserAction)\n            {\n                var undoActionName = \"Unpack Prefab instance\";\n                Undo.RegisterFullObjectHierarchyUndo(instanceRoot, undoActionName);\n                var newInstanceRoots = UnpackPrefabInstanceAndReturnNewOutermostRoots(instanceRoot, unpackMode);\n                foreach (var newInstanceRoot in newInstanceRoots)\n                {\n                    var prefabInstance = PrefabUtility.GetPrefabInstanceHandle(newInstanceRoot);\n                    if (prefabInstance)\n                    {\n                        Undo.RegisterCreatedObjectUndo(prefabInstance, undoActionName);\n                    }\n                }\n            }\n            else\n            {\n                UnpackPrefabInstanceAndReturnNewOutermostRoots(instanceRoot, unpackMode);\n            }\n\n            if (action == InteractionMode.UserAction)\n                Undo.FlushTrackedObjects();\n        }\n\n        public static GameObject[] UnpackPrefabInstanceAndReturnNewOutermostRoots(GameObject instanceRoot, PrefabUnpackMode unpackMode)\n        {\n            if (instanceRoot == null)\n                throw new ArgumentNullException(nameof(instanceRoot));\n\n            prefabInstanceUnpacking?.Invoke(instanceRoot, unpackMode);\n\n            // The user can delete the instance in the prefabInstanceUnpacking callback\n            if (instanceRoot == null)\n                throw new InvalidOperationException($\"The input '{nameof(instanceRoot)}' was destroyed in the prefabInstanceUnpacking callback\");\n\n            var newRoots = UnpackPrefabInstanceAndReturnNewOutermostRoots_internal(instanceRoot, unpackMode);\n            prefabInstanceUnpacked?.Invoke(instanceRoot, unpackMode);\n\n            return newRoots;\n        }\n\n        public static void UnpackAllInstancesOfPrefab(GameObject prefabRoot, PrefabUnpackMode unpackMode, InteractionMode action)\n        {\n            var prefabInstances = FindAllInstancesOfPrefab(prefabRoot);\n            foreach (var prefabInstance in prefabInstances)\n            {\n                UnpackPrefabInstance(prefabInstance, unpackMode, action);\n            }\n        }\n\n        internal static List<GameObject> FindGameObjectsWithInvalidComponent(GameObject rootOfSearch)\n        {\n            TransformVisitor transformVisitor = new TransformVisitor();\n            var gameObjectsWithInvalidComponent = new List<GameObject>();\n            transformVisitor.VisitAll(rootOfSearch.transform, PrefabOverridesUtility.CheckForInvalidComponent, gameObjectsWithInvalidComponent);\n            return gameObjectsWithInvalidComponent;\n        }\n\n        internal static bool HasInvalidComponent(GameObject rootOfSearch)\n        {\n            return FindGameObjectsWithInvalidComponent(rootOfSearch).Count > 0;\n        }\n\n        internal static bool HasInvalidComponent(Object componentOrGameObject)\n        {\n            if (componentOrGameObject == null)\n                return true;\n\n            if (componentOrGameObject is Component)\n            {\n                Component comp = (Component)componentOrGameObject;\n                componentOrGameObject = (GameObject)comp.gameObject;\n            }\n\n            if (!(componentOrGameObject is GameObject))\n                return false;\n\n            return HasInvalidComponent((GameObject)componentOrGameObject);\n        }\n\n        public static bool IsPartOfPrefabThatCanBeAppliedTo(Object componentOrGameObject)\n        {\n            if (componentOrGameObject == null)\n                return false;\n\n            if (IsPartOfImmutablePrefab(componentOrGameObject))\n                return false;\n\n            if (!EditorUtility.IsPersistent(componentOrGameObject))\n                componentOrGameObject = GetCorrespondingObjectFromSource(componentOrGameObject);\n\n            if (HasInvalidComponent(componentOrGameObject))\n                return false;\n\n            if (PrefabUtility.HasManagedReferencesWithMissingTypes(componentOrGameObject))\n                return false;\n\n            return true;\n        }\n\n        public static PrefabInstanceStatus GetPrefabInstanceStatus(Object componentOrGameObject)\n        {\n            if (!PrefabUtility.IsPartOfNonAssetPrefabInstance(componentOrGameObject))\n                return PrefabInstanceStatus.NotAPrefab;\n\n            if (PrefabUtility.IsPrefabAssetMissing(componentOrGameObject))\n                return PrefabInstanceStatus.MissingAsset;\n\n            return PrefabInstanceStatus.Connected;\n        }\n\n        public static PrefabAssetType GetPrefabAssetType(Object componentOrGameObject)\n        {\n            if (!PrefabUtility.IsPartOfAnyPrefab(componentOrGameObject))\n                return PrefabAssetType.NotAPrefab;\n\n            if (PrefabUtility.IsPrefabAssetMissing(componentOrGameObject))\n                return PrefabAssetType.MissingAsset;\n\n            if (PrefabUtility.IsPartOfVariantPrefab(componentOrGameObject))\n                return PrefabAssetType.Variant;\n\n            if (PrefabUtility.IsPartOfModelPrefab(componentOrGameObject))\n                return PrefabAssetType.Model;\n\n            return PrefabAssetType.Regular;\n        }\n\n        public static GameObject LoadPrefabContents(string assetPath)\n        {\n            if (string.IsNullOrEmpty(assetPath))\n                throw new ArgumentNullException(\"assetPath\", \"Prefab Asset path is null or empty\");\n\n            if (!File.Exists(assetPath))\n                throw new ArgumentException(string.Format(\"Path: {0}, does not exist\", assetPath));\n\n            if (Path.GetExtension(assetPath) != \".prefab\")\n                throw new ArgumentException(string.Format(\"Path: {0}, is not a prefab file\", assetPath));\n\n            var previewScene = EditorSceneManager.NewPreviewScene();\n            var rootGameObject = LoadPrefabContentsIntoPreviewScene_Internal(assetPath, previewScene);\n            previewScene.SetPathAndGuid(assetPath, AssetDatabase.AssetPathToGUID(assetPath));\n\n            if (rootGameObject == null)\n            {\n                EditorSceneManager.ClosePreviewScene(previewScene);\n                throw new ArgumentException(string.Format(\"Could not load Prefab contents at path {0}.\", assetPath));\n            }\n\n            return rootGameObject;\n        }\n\n        public static void UnloadPrefabContents(GameObject contentsRoot)\n        {\n            if (!EditorSceneManager.IsPreviewSceneObject(contentsRoot))\n            {\n                throw new ArgumentException(\"Specified object is not part of Prefab contents\");\n            }\n            var scene = contentsRoot.scene;\n            UnloadPrefabContents(scene);\n        }\n\n        private static void UnloadPrefabContents(Scene scene)\n        {\n            if (!scene.IsValid())\n            {\n                throw new ArgumentException(\"Scene is not valid\");\n            }\n            EditorSceneManager.ClosePreviewScene(scene);\n        }\n\n        internal static bool CanPropertyBeAppliedToSource(SerializedProperty property)\n        {\n            if (property.hasMultipleDifferentValues)\n                return false;\n\n            if (property.propertyType != SerializedPropertyType.ObjectReference\n                || property.objectReferenceValue == null\n                || EditorUtility.IsPersistent(property.objectReferenceValue))\n                return true;\n\n            Object referenceSource = GetCorrespondingObjectFromSource(property.objectReferenceValue);\n            if (referenceSource == null)\n                return false;  //Points to object not in prefab\n\n            Object applyTarget = GetCorrespondingObjectFromSource(property.m_SerializedObject.targetObject);\n            if (applyTarget == null)\n                return false;  //Added components/gameobjects. Can never be applied to\n\n            var target = PrefabUtility.GetPrefabInstanceHandle(property.objectReferenceValue);\n            var source = PrefabUtility.GetPrefabInstanceHandle(property.serializedObject.targetObject);\n            return target == source;\n        }\n\n        internal static bool CanPropertyBeAppliedToTarget(SerializedProperty property, Object applyTarget)\n        {\n            if (property.hasMultipleDifferentValues || applyTarget == null)\n                return false;\n\n            if (property.propertyType != SerializedPropertyType.ObjectReference\n                || property.objectReferenceValue == null\n                || EditorUtility.IsPersistent(property.objectReferenceValue))\n                return true;\n\n            var referenceRootInScene = FindNearestInstanceOfAsset(property.objectReferenceValue, applyTarget);\n            if (referenceRootInScene == null)\n                return false;\n\n            var targetReference = FindNearestInstanceOfAsset(property.serializedObject.targetObject, applyTarget);\n            if (targetReference == null)\n                return false;\n\n            return referenceRootInScene == targetReference;\n        }\n\n        internal static bool HasApplicableObjectOverrides(Object componentOrGameObjectInInstance, bool includeDefaultOverrides)\n        {\n            var applyTarget = GetCorrespondingObjectFromSource(componentOrGameObjectInInstance);\n            return HasApplicableObjectOverridesForTarget(componentOrGameObjectInInstance, applyTarget, includeDefaultOverrides);\n        }\n\n        // Since an override can be applied to multiple different apply targets, what is not a default override\n        // compared to e.g. the outermost apply target may still be a default override compared to e.g. the innermost.\n        // For example, if you have child Prefab B inside Prefab A in the scene and try want to apply the position of B,\n        // the position is not a default override if applying to A, but is if applying to B.\n        // This can be used to determine which apply targets are valid to apply to.\n        internal static bool IsPropertyOverrideDefaultOverrideComparedToAnySource(SerializedProperty property)\n        {\n            if (property == null || !property.prefabOverride)\n                return false;\n\n            Object componentOrGameObject = property.serializedObject.targetObject;\n\n            // Only Transform, RectTransform (derived from Transform) and GameObject can have default overrides.\n            if (!(componentOrGameObject is Transform || componentOrGameObject is GameObject))\n                return false;\n\n            Object innermostInstance = componentOrGameObject;\n            Object source = GetCorrespondingObjectFromSource(innermostInstance);\n            if (source == null)\n                return false;\n\n            while (source != null)\n            {\n                Object newSource = GetCorrespondingObjectFromSource(source);\n                if (newSource == null)\n                    break;\n                innermostInstance = source;\n                source = newSource;\n            }\n\n            SerializedObject innermostInstanceSO = new SerializedObject(innermostInstance);\n            return innermostInstanceSO.FindProperty(property.propertyPath).isDefaultOverride;\n        }\n\n        internal static bool HasPrefabInstanceNonDefaultOverrides_CachedForUI(GameObject gameObject)\n        {\n            if (gameObject == null)\n                throw new ArgumentNullException(nameof(gameObject));\n\n            return HasPrefabInstanceNonDefaultOverrides_CachedForUI_Internal(gameObject);\n        }\n\n        internal static bool HasPrefabInstanceUnusedOverrides_CachedForUI(GameObject gameObject)\n        {\n            if (gameObject == null)\n                throw new ArgumentNullException(nameof(gameObject));\n\n            return HasPrefabInstanceUnusedOverrides_CachedForUI_Internal(gameObject);\n        }\n\n        internal static bool HasPrefabInstanceNonDefaultOverridesOrUnusedOverrides_CachedForUI(GameObject gameObject)\n        {\n            if (gameObject == null)\n                throw new ArgumentNullException(nameof(gameObject));\n\n            return HasPrefabInstanceNonDefaultOverrides_CachedForUI_Internal(gameObject) || HasPrefabInstanceUnusedOverrides_CachedForUI_Internal(gameObject);\n        }\n\n        internal static void ClearPrefabInstanceNonDefaultOverridesCache(GameObject gameObject)\n        {\n            if (gameObject == null)\n                throw new ArgumentNullException(nameof(gameObject));\n\n            ClearPrefabInstanceNonDefaultOverridesCache_Internal(gameObject);\n        }\n\n        internal static void ClearPrefabInstanceUnusedOverridesCache(GameObject gameObject)\n        {\n            if (gameObject == null)\n                throw new ArgumentNullException(nameof(gameObject));\n\n            ClearPrefabInstanceUnusedOverridesCache_Internal(gameObject);\n        }\n\n        internal static bool HasPrefabInstanceUnusedOverrides(GameObject gameObject)\n        {\n            if (gameObject == null)\n                throw new ArgumentNullException(nameof(gameObject));\n\n            return HasPrefabInstanceUnusedOverrides_Internal(gameObject);\n        }\n\n        // Same as IsPropertyOverrideDefaultOverrideComparedToAnySource, but checks if it's the case for all overrides\n        // on the object.\n        internal static bool IsObjectOverrideAllDefaultOverridesComparedToOriginalSource(Object componentOrGameObject)\n        {\n            // Only Transform, RectTransform (derived from Transform) and GameObject can have default overrides.\n            if (!(componentOrGameObject is Transform || componentOrGameObject is GameObject))\n                return false;\n\n            Object innermostInstance = componentOrGameObject;\n            Object source = GetCorrespondingObjectFromSource(innermostInstance);\n            if (source == null)\n                return false;\n\n            while (source != null)\n            {\n                Object newSource = GetCorrespondingObjectFromSource(source);\n                if (newSource == null)\n                    break;\n                innermostInstance = source;\n                source = newSource;\n            }\n\n            SerializedObject passedSO = new SerializedObject(componentOrGameObject);\n            SerializedObject innermostInstanceSO = new SerializedObject(innermostInstance);\n            SerializedProperty property = passedSO.GetIterator();\n            bool anyOverrides = false;\n            while (property.Next(true))\n            {\n                if (property.prefabOverride)\n                {\n                    if (!innermostInstanceSO.FindProperty(property.propertyPath).isDefaultOverride)\n                        return false;\n\n                    anyOverrides = true;\n                }\n            }\n\n            if (!anyOverrides)\n                return false;\n\n            return true;\n        }\n\n        internal static bool IsObjectOnRootInAsset(Object componentOrGameObject, string assetPath)\n        {\n            GameObject go = GetGameObject(componentOrGameObject);\n            GameObject goInAsset = GetCorrespondingObjectFromSourceAtPath(go, assetPath);\n            if (goInAsset == null)\n                return false;\n            return goInAsset.transform.root == goInAsset.transform;\n        }\n\n        internal static bool IsAssetANestedPrefabRoot(Object assetObject)\n        {\n            GameObject gameObject = assetObject as GameObject;\n            if (gameObject == null)\n                return false;\n\n            var correspondingGameObjectFromSource = PrefabUtility.GetCorrespondingObjectFromSource(gameObject);\n            while (correspondingGameObjectFromSource != null)\n            {\n                var rootGameObject = PrefabUtility.GetRootGameObject(correspondingGameObjectFromSource);\n                if (correspondingGameObjectFromSource == rootGameObject)\n                    return true;\n                correspondingGameObjectFromSource = PrefabUtility.GetCorrespondingObjectFromSource(correspondingGameObjectFromSource);\n            }\n\n            return false;\n        }\n\n        internal static List<Object> GetApplyTargets(Object instanceOrAssetObject, bool isAllDefaultOverridesComparedToOriginalSource, bool includeSelfAsTarget = false, bool includeOriginalSelfAsTarget = true)\n        {\n            List<Object> applyTargets = new List<Object>();\n\n            GameObject instanceGameObject = instanceOrAssetObject as GameObject;\n            if (instanceGameObject == null)\n                instanceGameObject = (instanceOrAssetObject as Component).gameObject;\n\n            Object source = instanceOrAssetObject;\n            if (!EditorUtility.IsPersistent(source) || !includeSelfAsTarget)\n                source = PrefabUtility.GetCorrespondingObjectFromSource(source);\n            if (source == null)\n                return applyTargets;\n\n            while (source != null)\n            {\n                if (isAllDefaultOverridesComparedToOriginalSource)\n                {\n                    // Default overrides properties are select properties on the root GameObject (like name)\n                    // and root Transform (like position and rotation, but not scale).\n                    // If we're dealing with an override that's a default override compared to the original\n                    // source, it will also be a default override compared to any Prefab Variants of the\n                    // original source that might be in the chain of corresponding objects. It will however\n                    // not be a default override compared to Prefabs that use the original source as a nested\n                    // Prefab, because those Prefabs have a different root GameObject.\n                    // So for each corresponding object we need to check if it's the Prefab root GameObject\n                    // or Transform. If it is, the overrides will be default overrides compared to that Prefab,\n                    // and so it shouldn't be possible to apply to it, so we don't add it as an apply target.\n                    // Note that for changed components that have some overrides that can be default overrides,\n                    // and some not, we do allow applying, but only the properties that are not default\n                    // overrides will be applied.\n                    GameObject sourceGo = GetGameObject(source);\n                    if (sourceGo.transform.root == sourceGo.transform)\n                        break;\n                }\n\n                if (includeOriginalSelfAsTarget || PrefabUtility.GetCorrespondingObjectFromSource(source) != null)\n                    applyTargets.Add(source);\n\n                source = PrefabUtility.GetCorrespondingObjectFromSource(source);\n            }\n\n            return applyTargets;\n        }\n\n        internal enum OverrideOperation\n        {\n            Apply,\n            Revert\n        }\n\n        // Applying/reverting multiple overrides at once is surprisingly tricky because\n        // we have to handle components with dependencies on other components in just the right order.\n        internal static bool ProcessMultipleOverrides(GameObject prefabInstanceRoot, List<PrefabOverride> overrides, PrefabUtility.OverrideOperation operation, InteractionMode mode)\n        {\n            if (WarnIfInAnimationMode(operation, mode))\n                return false;\n\n            Dictionary<PrefabOverride, List<Component>> overrideDependencies =\n                new Dictionary<PrefabOverride, List<Component>>();\n            List<PrefabOverride> acceptedOverrides = new List<PrefabOverride>();\n            List<PrefabOverride> acceptedRemovedComponentOverrides = new List<PrefabOverride>();\n            List<PrefabOverride> remainingOverrides = new List<PrefabOverride>();\n            HashSet<Object> acceptedOverrideObjects = new HashSet<Object>();\n\n            // Iterate over overrides. Immediately accept any overrides with no dependencies.\n            // Otherwise save dependencies in dictionary for quick lookup.\n            for (int i = 0; i < overrides.Count; i++)\n            {\n                PrefabOverride singleOverride = overrides[i];\n                if (singleOverride == null)\n                    continue;\n                bool hasDependencies = false;\n\n                RemovedComponent removedComponent = singleOverride as RemovedComponent;\n                if (removedComponent != null)\n                {\n                    var deps = PrefabUtility.GetRemovedComponentDependencies(\n                        removedComponent.assetComponent,\n                        removedComponent.containingInstanceGameObject,\n                        operation);\n                    if (deps.Count > 0)\n                    {\n                        overrideDependencies[singleOverride] = deps;\n                        hasDependencies = true;\n                    }\n                }\n\n                AddedComponent addedComponent = singleOverride as AddedComponent;\n                if (addedComponent != null)\n                {\n                    var deps = PrefabUtility.GetAddedComponentDependencies(\n                        addedComponent.instanceComponent,\n                        operation);\n                    if (deps.Count > 0)\n                    {\n                        overrideDependencies[singleOverride] = deps;\n                        hasDependencies = true;\n                    }\n                }\n\n                if (hasDependencies)\n                {\n                    remainingOverrides.Add(singleOverride);\n                }\n                else\n                {\n                    if (singleOverride is RemovedComponent)\n                        acceptedRemovedComponentOverrides.Add(singleOverride);\n                    else\n                        acceptedOverrides.Add(singleOverride);\n                    acceptedOverrideObjects.Add(singleOverride.GetObject());\n                }\n            }\n\n            // Iteratively accept overrides whose dependencies are all in the accepted overrides.\n            // Theoretically this algorithm is worst case n*n.\n            // However, long dependency chains are uncommon, so in practise it's much closer to just n.\n            while (true)\n            {\n                bool didAcceptNewOverrides = false;\n\n                for (int i = remainingOverrides.Count - 1; i >= 0; i--)\n                {\n                    var o = remainingOverrides[i];\n                    var dependencies = overrideDependencies[o];\n                    bool allDependenciesSatisfied = true;\n                    for (int j = 0; j < dependencies.Count; j++)\n                    {\n                        if (!acceptedOverrideObjects.Contains(dependencies[j]))\n                        {\n                            allDependenciesSatisfied = false;\n                            break;\n                        }\n                    }\n                    if (allDependenciesSatisfied)\n                    {\n                        if (o is RemovedComponent)\n                            acceptedRemovedComponentOverrides.Add(o);\n                        else\n                            acceptedOverrides.Add(o);\n                        acceptedOverrideObjects.Add(o.GetObject());\n                        remainingOverrides.RemoveAt(i);\n                        didAcceptNewOverrides = true;\n                    }\n                }\n\n                if (!didAcceptNewOverrides)\n                    break;\n            }\n\n            if (remainingOverrides.Count > 0)\n            {\n                string dependenciesString = \"\";\n                foreach (var singleOverride in remainingOverrides)\n                {\n                    var dependencies = overrideDependencies[singleOverride];\n                    foreach (var dep in dependencies)\n                    {\n                        // The dependency direction is different for apply versus revert AND for added versus removed components.\n                        bool dependsOnOther = (singleOverride is AddedComponent) ^ (operation == PrefabUtility.OverrideOperation.Revert);\n                        dependenciesString += \"\\n\" + string.Format(\n                            dependsOnOther ? L10n.Tr(\"{0} depends on {1}\") : L10n.Tr(\"{0} is depended on by {1}\"),\n                            ObjectNames.GetInspectorTitle(singleOverride.GetObject()),\n                            ObjectNames.GetInspectorTitle(dep));\n                    }\n                }\n\n                string error = null;\n                string dialogTitle = null;\n                if (operation == PrefabUtility.OverrideOperation.Apply)\n                {\n                    dialogTitle = L10n.Tr(\"Can't apply selected overrides\");\n                    error = L10n.Tr(\"Can't apply selected overrides due to dependencies with non-selected overrides:\") + dependenciesString;\n                }\n                else\n                {\n                    dialogTitle = L10n.Tr(\"Can't revert selected overrides\");\n                    error = L10n.Tr(\"Can't revert selected overrides due to dependencies with non-selected overrides.\") + dependenciesString;\n                }\n\n                if (mode == InteractionMode.UserAction)\n                {\n                    EditorUtility.DisplayDialog(dialogTitle, error, L10n.Tr(\"OK\"));\n                }\n                else\n                {\n                    throw new ArgumentException(error);\n                }\n\n                return false;\n            }\n\n            if (operation == PrefabUtility.OverrideOperation.Apply)\n            {\n                if (mode == InteractionMode.UserAction)\n                {\n                    // Make sure asset is checked out in version control.\n                    string prefabAssetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefabInstanceRoot);\n                    if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(prefabAssetPath, PrefabUtility.SaveVerb.Apply))\n                        return false;\n                }\n\n                // Apply overrides *in the order* they were added, but all removed components first, so removed\n                // and added component of same type can't cause GameObject to temporarily have two at once.\n                for (int i = 0; i < acceptedRemovedComponentOverrides.Count; i++)\n                    acceptedRemovedComponentOverrides[i].Apply(mode);\n                for (int i = 0; i < acceptedOverrides.Count; i++)\n                    acceptedOverrides[i].Apply(mode);\n            }\n            else\n            {\n                // Revert overrides *in the order* they were added, but all removed components last, so removed\n                // and added component of same type can't cause GameObject to temporarily have two at once.\n                for (int i = 0; i < acceptedOverrides.Count; i++)\n                    acceptedOverrides[i].Revert(mode);\n                for (int i = 0; i < acceptedRemovedComponentOverrides.Count; i++)\n                    acceptedRemovedComponentOverrides[i].Revert(mode);\n            }\n\n            return true;\n        }\n\n        internal static List<Component> GetAddedComponentDependencies(Component component, OverrideOperation op)\n        {\n            GameObject instanceGameObject = component.gameObject;\n            List<Component> addedComponentsOnGO =\n                GetAddedComponents(instanceGameObject)\n                    .Select(e => e.instanceComponent)\n                    .Where(e => e.gameObject == instanceGameObject)\n                    .ToList();\n            if (op == OverrideOperation.Apply)\n                // We can't apply an added component if it depends on a different added component.\n                // This would violate a dependency in the asset.\n                return GetComponentsWhichThisDependsOn(component, addedComponentsOnGO);\n            else\n                // We can't revert an added component if another added component depends on it.\n                // This would violate a dependency in the instance.\n                return GetComponentsWhichDependOnThis(component, addedComponentsOnGO);\n        }\n\n        internal static List<Component> GetRemovedComponentDependencies(Component assetComponent, GameObject instanceGameObject, OverrideOperation op)\n        {\n            GameObject assetGameObject = assetComponent.gameObject;\n            List<Component> removedComponentsOnAssetGO =\n                GetRemovedComponents(instanceGameObject)\n                    .Select(e => e.assetComponent)\n                    .Where(e => e.gameObject == assetGameObject)\n                    .ToList();\n            if (op == OverrideOperation.Apply)\n                // We can't apply a removed component if another removed component depends on it.\n                // This would violate a dependency in the asset.\n                return GetComponentsWhichDependOnThis(assetComponent, removedComponentsOnAssetGO);\n            else\n                // We can't revert a removed component if it depends on another removed component.\n                // This would violate a dependency in the instance.\n                return GetComponentsWhichThisDependsOn(assetComponent, removedComponentsOnAssetGO);\n        }\n\n        static List<Component> GetComponentsWhichDependOnThis(Component component, List<Component> componentsToConsider)\n        {\n            List<Component> dependencies = new List<Component>();\n            var componentType = component.GetType();\n\n            // Iterate all components.\n            for (int i = 0; i < componentsToConsider.Count; i++)\n            {\n                var comp = componentsToConsider[i];\n\n                // Ignore component itself.\n                if (comp == component)\n                    continue;\n\n                var requiredComps = comp.GetType().GetCustomAttributes(typeof(RequireComponent), inherit: true);\n                foreach (RequireComponent reqComp in requiredComps)\n                {\n                    if (reqComp.m_Type0 == componentType || reqComp.m_Type1 == componentType || reqComp.m_Type2 == componentType)\n                    {\n                        // We might get the same component type requirement from multiple sources.\n                        // Make sure we don't add the same component more than once.\n                        if (!dependencies.Contains(comp))\n                            dependencies.Add(comp);\n                    }\n                }\n            }\n            return dependencies;\n        }\n\n        static List<Component> GetComponentsWhichThisDependsOn(Component component, List<Component> componentsToConsider)\n        {\n            var requiredComps = component.GetType().GetCustomAttributes(typeof(RequireComponent), inherit: true);\n            List<Component> dependencies = new List<Component>();\n            if (requiredComps.Count() == 0)\n                return dependencies;\n\n            // Iterate all components.\n            for (int i = 0; i < componentsToConsider.Count; i++)\n            {\n                var comp = componentsToConsider[i];\n\n                // Ignore component itself.\n                if (comp == component)\n                    continue;\n\n                var componentType = comp.GetType();\n                foreach (RequireComponent reqComp in requiredComps)\n                {\n                    if (reqComp.m_Type0 == componentType || reqComp.m_Type1 == componentType || reqComp.m_Type2 == componentType)\n                    {\n                        // We might get the same component type requirement from multiple sources.\n                        // Make sure we don't add the same component more than once.\n                        if (!dependencies.Contains(comp))\n                            dependencies.Add(comp);\n                    }\n                }\n            }\n            return dependencies;\n        }\n\n        [StructLayout(LayoutKind.Sequential)]\n        [RequiredByNativeCode]\n        [NativeAsStruct]\n        internal sealed class InstanceOverridesInfo\n        {\n            public InstanceOverridesInfo(GameObject prefabInstance, PropertyModification[] usedMods, PropertyModification[] unusedMods, int unusedRemovedGameObjectCount, int unusedRemovedComponentCount)\n            {\n                this.instance = prefabInstance;\n                this.usedMods = usedMods;\n                this.unusedMods = unusedMods;\n                this.unusedRemovedGameObjectCount = unusedRemovedGameObjectCount;\n                this.unusedRemovedComponentCount = unusedRemovedComponentCount;\n            }\n\n            public GameObject instance { get; }\n            public PropertyModification[] usedMods { get; }\n            public PropertyModification[] unusedMods { get; }\n            public int unusedRemovedGameObjectCount { get; }\n            public int unusedRemovedComponentCount { get; }\n\n            public int unusedOverrideCount => unusedMods.Length + unusedRemovedGameObjectCount + unusedRemovedComponentCount;\n        }\n\n        internal static bool HavePrefabInstancesUnusedOverrides(GameObject[] gameObjects)\n        {\n            if (gameObjects == null || !gameObjects.Any())\n                return false;\n\n            foreach (GameObject go in gameObjects)\n            {\n                var outerMostPrefabInstance = PrefabUtility.GetOutermostPrefabInstanceRoot(go);\n\n                if (PrefabUtility.HasPrefabInstanceUnusedOverrides_Internal(outerMostPrefabInstance))\n                    return true;\n            }\n\n            return false;\n        }\n\n        internal static InstanceOverridesInfo[] GetPrefabInstancesOverridesInfos(GameObject[] selectedGameObjects)\n        {\n            if (selectedGameObjects == null || selectedGameObjects.Length == 0)\n                return new InstanceOverridesInfo[] {};\n\n            List<InstanceOverridesInfo> allInstanceMods = new List<InstanceOverridesInfo>();\n\n            foreach (GameObject go in selectedGameObjects)\n            {\n                var outerMostInstance = PrefabUtility.GetOutermostPrefabInstanceRoot(go);\n                if (outerMostInstance == null)\n                    continue;\n\n                if (PrefabUtility.HasPrefabInstanceNonDefaultOverridesOrUnusedOverrides_CachedForUI(outerMostInstance))\n                {\n                    InstanceOverridesInfo instancePropMods = GetPrefabInstanceOverridesInfo(outerMostInstance);\n                    allInstanceMods.Add(instancePropMods);\n                }\n            }\n\n            return allInstanceMods.ToArray();\n        }\n\n        internal static InstanceOverridesInfo GetPrefabInstanceOverridesInfo(GameObject selectedGameObject)\n        {\n            return GetPrefabInstanceOverridesInfo_Internal(selectedGameObject);\n        }\n\n        internal static bool DoRemovePrefabInstanceUnusedOverridesDialog(InstanceOverridesInfo[] instanceOverridesInfos)\n        {\n            string titleCheckForUnusedOverrides = EditorGUIUtility.TrTextContent(\"Remove Unused Overrides\").text;\n            string msgNoOverridesWereFound = EditorGUIUtility.TrTextContent(\"No unused overrides were found.\").text;\n\n            string title = titleCheckForUnusedOverrides;\n            string message = string.Empty;\n\n            if (instanceOverridesInfos == null || !instanceOverridesInfos.Any())\n            {\n                title = titleCheckForUnusedOverrides;\n                message = msgNoOverridesWereFound;\n                EditorUtility.DisplayDialog(title, message, L10n.Tr(\"OK\"));\n                return false;\n            }\n\n            string titleRemoveUnusedOverrides = EditorGUIUtility.TrTextContent(\"Remove unused overrides?\").text;\n            string msgDetailsWrittenToTheLog = EditorGUIUtility.TrTextContent(\"Details will be written to the Editor log.\").text;\n            string msgUsedOverridesCount = EditorGUIUtility.TrTextContent(\"Used overrides count\").text;\n\n            string msgAskRemoveMultipleOverridesFromMultipleInstances = EditorGUIUtility.TrTextContent(\"Do you want to remove {0} unused overrides from {1} Prefab instances?\").text;\n            string msgAskRemoveSingleOverrideFromMultipleInstances = EditorGUIUtility.TrTextContent(\"Do you want to remove 1 unused override from {0} Prefab instances?\").text;\n            string msgAskRemoveMultipleOverridesFromSingleInstance = EditorGUIUtility.TrTextContent(\"Do you want to remove {0} unused overrides from '{1}'?\").text;\n            string msgAskRemoveSingleOverrideFromSingleInstance = EditorGUIUtility.TrTextContent(\"Do you want to remove 1 unused override from '{0}'?\").text;\n\n            PrefabUtility.InstanceOverridesInfo currInstanceWithUnusedMods = instanceOverridesInfos[0];\n            int affectedInstanceCount = 0;\n            int unusedOverridesCount = 0;\n            int usedOverridesCount = 0;\n            int selectedInstanceCount = instanceOverridesInfos.Length;\n\n            if (selectedInstanceCount > 1)\n            {\n                foreach (PrefabUtility.InstanceOverridesInfo instanceMods in instanceOverridesInfos)\n                {\n                    if (instanceMods.unusedOverrideCount == 0)\n                        continue;\n\n                    affectedInstanceCount++;\n                    unusedOverridesCount += instanceMods.unusedOverrideCount;\n                    usedOverridesCount += instanceMods.usedMods.Length;\n                    currInstanceWithUnusedMods = instanceMods;\n                }\n\n                if (unusedOverridesCount > 0)\n                {\n                    if (affectedInstanceCount > 1)\n                    {\n                        if (unusedOverridesCount > 1)\n                            message = string.Format(msgAskRemoveMultipleOverridesFromMultipleInstances, unusedOverridesCount, affectedInstanceCount);\n                        else\n                            message = string.Format(msgAskRemoveSingleOverrideFromMultipleInstances, affectedInstanceCount);\n                    }\n                    else// Single instance\n                    {\n                        if (unusedOverridesCount > 1)\n                            message = string.Format(msgAskRemoveMultipleOverridesFromSingleInstance, unusedOverridesCount, currInstanceWithUnusedMods.instance.name);\n                        else\n                            message = string.Format(msgAskRemoveSingleOverrideFromSingleInstance, currInstanceWithUnusedMods.instance.name);\n                    }\n                }\n            }\n            else// Single selection\n            {\n                unusedOverridesCount = currInstanceWithUnusedMods.unusedOverrideCount;\n                usedOverridesCount = currInstanceWithUnusedMods.usedMods.Length;\n                if (unusedOverridesCount > 0)\n                {\n                    affectedInstanceCount = 1;\n                    if (unusedOverridesCount > 1)\n                        message = string.Format(msgAskRemoveMultipleOverridesFromSingleInstance, unusedOverridesCount, currInstanceWithUnusedMods.instance.name);\n                    else\n                        message = string.Format(msgAskRemoveSingleOverrideFromSingleInstance, currInstanceWithUnusedMods.instance.name);\n                }\n            }\n\n            if (unusedOverridesCount > 0)\n            {\n                title = titleRemoveUnusedOverrides;\n                message += \"\\n\\n\" + msgDetailsWrittenToTheLog;\n                if (EditorUtility.DisplayDialog(title, message, L10n.Tr(\"Remove\"), L10n.Tr(\"Cancel\")))\n                    return true;\n            }\n            else\n            {\n                title = titleCheckForUnusedOverrides;\n                message = msgNoOverridesWereFound;\n                EditorUtility.DisplayDialog(title, message, L10n.Tr(\"OK\"));\n                return false;\n            }\n\n            return false;\n        }\n\n        internal static void RemovePrefabInstanceUnusedOverrides(InstanceOverridesInfo[] instanceOverridesInfos, InteractionMode interactionMode = InteractionMode.UserAction)\n        {\n            foreach (InstanceOverridesInfo ipmods in instanceOverridesInfos)\n            {\n                if (ipmods.unusedOverrideCount != 0 && interactionMode == InteractionMode.UserAction)\n                {\n                    Undo.RegisterCompleteObjectUndo(ipmods.instance, \"Remove unused overrides\");\n                }\n\n                PrefabUtility.RemovePrefabInstanceUnusedOverrides(ipmods, out RemovedModifications removedModificationsCount);\n\n                if (interactionMode == InteractionMode.UserAction)\n                {\n                    if (removedModificationsCount.unusedMods > 0)\n                    {\n                        LogRemovedPropertyOverrides(ipmods.instance, ipmods.unusedMods);\n                    }\n                    if (removedModificationsCount.unusedRemovedGameObjectCount > 0)\n                    {\n                        LogRemovedUnusedRemovedGameObjects(ipmods.instance, ipmods.unusedRemovedGameObjectCount);\n                    }\n                    if (removedModificationsCount.unusedRemovedComponentCount > 0)\n                    {\n                        LogRemovedUnusedRemovedComponents(ipmods.instance, ipmods.unusedRemovedComponentCount);\n                    }\n                }\n            }\n\n            if (interactionMode == InteractionMode.UserAction)\n                Undo.FlushTrackedObjects();\n        }\n\n        private struct RemovedModifications\n        {\n            public int unusedMods;\n            public int unusedRemovedGameObjectCount;\n            public int unusedRemovedComponentCount;\n        }\n\n        private static bool RemovePrefabInstanceUnusedOverrides(InstanceOverridesInfo iovInfo, out RemovedModifications removedModificationsCount)\n        {\n            if (iovInfo.instance == null)\n                throw new ArgumentNullException(nameof(iovInfo), \"InstanceOverridesInfo.instance was null\");\n            else if (iovInfo.unusedMods == null)\n                throw new ArgumentNullException(nameof(iovInfo), \"InstanceOverridesInfo.unusedMods was null\");\n            else if (iovInfo.usedMods == null)\n                throw new ArgumentNullException(nameof(iovInfo), \"InstanceOverridesInfo.usedMods was null\");\n\n            removedModificationsCount = new RemovedModifications\n            {\n                unusedMods = iovInfo.unusedMods.Length,\n                unusedRemovedGameObjectCount = iovInfo.unusedRemovedGameObjectCount,\n                unusedRemovedComponentCount = iovInfo.unusedRemovedComponentCount  \n            };\n\n            bool removedAny = iovInfo.unusedOverrideCount != 0;\n            if (removedAny)\n            {\n                if (iovInfo.unusedMods.Length > 0)\n                {\n                    SetPropertyModifications(iovInfo.instance, iovInfo.usedMods);\n                }\n\n                if (iovInfo.unusedRemovedGameObjectCount > 0)\n                {\n                    PrefabUtility.RemoveRemovedGameObjectOverridesWhichAreNull(iovInfo.instance);\n                }\n\n                if (iovInfo.unusedRemovedComponentCount > 0)\n                {\n                    PrefabUtility.RemoveRemovedComponentOverridesWhichAreInvalid(iovInfo.instance);\n                }\n            }\n            return removedAny;\n        }\n\n        internal static bool LogRemovedPropertyOverrides(GameObject instance, PropertyModification[] mods)\n        {\n            if (mods.Length == 0)\n                return false;\n\n            System.Text.StringBuilder info = new System.Text.StringBuilder();\n\n            if (mods.Length > 1)\n                info.AppendLine(\"Removed \" + mods.Length + \" unused overrides from instance '\" + instance.name + \"':\");\n            else\n                info.AppendLine(\"Removed 1 unused override from instance '\" + instance.name + \"':\");\n\n            foreach (PropertyModification mod in mods)\n            {\n                if (mod.target == null)\n                    info.AppendLine(\"   '\" + mod.propertyPath + \"' refers to a non-existent object.\");\n                else\n                    info.AppendLine(\"   '\" + mod.propertyPath + \"' refers to a non-existent property.\");\n            }\n\n            System.Console.Write(info.ToString(), instance);\n            return true;\n        }\n\n        internal static bool LogRemovedUnusedRemovedGameObjects(GameObject instance, int unusedRemovedGameObjectsCount)\n        {\n            if (unusedRemovedGameObjectsCount == 0)\n                return false;\n\n            System.Text.StringBuilder info = new System.Text.StringBuilder();\n\n            if (unusedRemovedGameObjectsCount > 1)\n                info.AppendLine(\"Removed \" + unusedRemovedGameObjectsCount + \" unused removed GameObjects from instance '\" + instance.name + \"'\");\n            else\n                info.AppendLine(\"Removed 1 unused removed GameObject from instance '\" + instance.name + \"'\");\n\n            System.Console.Write(info.ToString(), instance);\n\n            return true;\n        }\n\n        internal static bool LogRemovedUnusedRemovedComponents(GameObject instance, int unusedRemovedComponentCount)\n        {\n            if (unusedRemovedComponentCount == 0)\n                return false;\n\n            System.Text.StringBuilder info = new System.Text.StringBuilder();\n\n            if (unusedRemovedComponentCount > 1)\n                info.AppendLine(\"Removed \" + unusedRemovedComponentCount + \" unused removed components from instance '\" + instance.name + \"'\");\n            else\n                info.AppendLine(\"Removed 1 unused removed component from instance '\" + instance.name + \"'\");\n\n            System.Console.Write(info.ToString(), instance);\n\n            return true;\n        }\n\n        private static event Func<UnityEngine.Object, bool> m_AllowRecordingPrefabPropertyOverridesFor;\n\n        internal static event Func<UnityEngine.Object, bool> allowRecordingPrefabPropertyOverridesFor\n        {\n            add\n            {\n                m_AllowRecordingPrefabPropertyOverridesFor += value;\n                SetHasSubscribersToAllowRecordingPrefabPropertyOverrides(true);\n            }\n            remove\n            {\n                m_AllowRecordingPrefabPropertyOverridesFor -= value;\n                if (m_AllowRecordingPrefabPropertyOverridesFor == null)\n                    SetHasSubscribersToAllowRecordingPrefabPropertyOverrides(false);\n            }\n        }\n\n\n        [RequiredByNativeCode]\n        static bool AllowRecordingPrefabPropertyOverridesFor(UnityEngine.Object componentOrGameObject)\n        {\n            if (m_AllowRecordingPrefabPropertyOverridesFor == null)\n            {\n                Debug.LogError(\"We should not be calling into managed from native if we have no subscribers.\");\n                return true;\n            }\n\n\n            foreach (Func<UnityEngine.Object, bool> deleg in m_AllowRecordingPrefabPropertyOverridesFor.GetInvocationList())\n            {\n                if (deleg(componentOrGameObject) == false)\n                    return false;\n            }\n\n            return true;\n        }\n\n        internal static class Analytics\n        {\n            public enum ApplyScope\n            {\n                PropertyOverride,\n                ObjectOverride,\n                AddedComponent,\n                RemovedComponent,\n                AddedGameObject,\n                RemovedGameObject,\n                EntirePrefab\n            }\n\n            public enum ApplyTarget\n            {\n                OnlyTarget,\n                Outermost,\n                Innermost,\n                Middle\n            }\n\n            [Serializable]\n            class EventData\n            {\n                public ApplyScope applyScope;\n                public bool userAction;\n                public string activeGUIView;\n                public ApplyTarget applyTarget;\n                public int applyTargetCount;\n            }\n\n            public static void SendApplyEvent(\n                ApplyScope applyScope,\n                Object instance,\n                string applyTargetPath,\n                InteractionMode interactionMode,\n                DateTime startTime,\n                bool defaultOverrideComparedToSomeSources\n            )\n            {\n                var duration = DateTime.UtcNow.Subtract(startTime);\n\n                var eventData = new EventData();\n                eventData.applyScope = applyScope;\n                eventData.userAction = (interactionMode == InteractionMode.UserAction);\n                eventData.activeGUIView = GUIView.GetTypeNameOfMostSpecificActiveView();\n\n                // Calculate apply target and apply target count relation.\n                var applyTargets = GetApplyTargets(instance, defaultOverrideComparedToSomeSources);\n                if (applyTargets == null)\n                {\n                    eventData.applyTarget = ApplyTarget.OnlyTarget;\n                    eventData.applyTargetCount = 0;\n                }\n                else if (applyTargets.Count <= 1)\n                {\n                    eventData.applyTarget = ApplyTarget.OnlyTarget;\n                    eventData.applyTargetCount = applyTargets.Count;\n                }\n                else\n                {\n                    eventData.applyTargetCount = applyTargets.Count;\n\n                    int index = -1;\n                    for (int i = 0; i < applyTargets.Count; i++)\n                    {\n                        if (AssetDatabase.GetAssetPath(applyTargets[i]) == applyTargetPath)\n                        {\n                            index = i;\n                            break;\n                        }\n                    }\n\n                    if (index == 0)\n                        eventData.applyTarget = ApplyTarget.Outermost;\n                    else if (index == applyTargets.Count - 1)\n                        eventData.applyTarget = ApplyTarget.Innermost;\n                    else\n                        eventData.applyTarget = ApplyTarget.Middle;\n                }\n\n                UsabilityAnalytics.SendEvent(\"prefabApply\", startTime, duration, true, eventData);\n            }\n        }\n\n        [RequiredByNativeCode]\n        static void OnPrefabSavingEnded(long ticks)\n        {\n            var duration = new TimeSpan(ticks);\n            var saveStartTime = DateTime.UtcNow.Subtract(duration);\n\n            UsabilityAnalytics.SendEvent(\"prefabSave\", saveStartTime, duration, true, null);\n        }\n\n        public struct EditPrefabContentsScope : IDisposable\n        {\n            public readonly string assetPath;\n            public readonly GameObject prefabContentsRoot;\n            Scene scene;\n\n            public EditPrefabContentsScope(string assetPath)\n            {\n                this.assetPath = assetPath;\n                prefabContentsRoot = LoadPrefabContents(assetPath);\n                scene = prefabContentsRoot.scene;\n            }\n\n            public void Dispose()\n            {\n                if (prefabContentsRoot != null)\n                {\n                    SaveAsPrefabAsset(prefabContentsRoot, assetPath);\n                }\n                else\n                {\n                    Debug.LogError(\"Prefab root is null: Saving an empty prefab we would create an invalid Prefab Asset\");\n                }\n\n                UnloadPrefabContents(scene);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Prefabs/PropertyModification.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Runtime.InteropServices;\nusing Object = UnityEngine.Object;\nusing UnityEngine.Scripting;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    // Defines a single modified property.\n    [System.Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    [RequiredByNativeCode]\n    [NativeAsStruct]\n    public sealed class PropertyModification\n    {\n        // Object that will be modified\n        public Object target;\n        // Property path of the property being modified (Matches as SerializedProperty.propertyPath)\n        public string propertyPath;\n        // The value being applied\n        public string value;\n        // The value being applied when it is a object reference (which can not be represented as a string)\n        public Object objectReference;\n\n        internal void Apply()\n        {\n            ApplyPropertyModificationToObject(target, this);\n        }\n\n        internal void ApplyToObject(Object obj)\n        {\n            ApplyPropertyModificationToObject(obj, this);\n        }\n\n        [NativeMethod(\"ApplyPropertyModificationToObject\", IsFreeFunction = true)]\n        [NativeHeader(\"Editor/Src/Prefabs/PropertyModification.h\")]\n        extern internal static void ApplyPropertyModificationToObject([NotNull] Object target, PropertyModification value);\n\n        [NativeMethod(\"ApplyPropertyModificationsToObject\", IsFreeFunction = true)]\n        [NativeHeader(\"Editor/Src/Prefabs/PropertyModification.h\")]\n        extern internal static void ApplyPropertyModificationsToObject([NotNull] Object target, PropertyModification[] value);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PreferencesWindow/AssetPipelinePreferences.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    internal enum AssetPipelineAutoRefreshMode\n    {\n        Disabled = 0,\n        Enabled = 1,\n        EnabledOutsidePlaymode = 2\n    }\n\n    internal class AssetPipelinePreferences : PreferencesProvider\n    {\n        class Properties\n        {\n            public static readonly GUIContent autoRefresh = EditorGUIUtility.TrTextContent(\"Auto Refresh\", \"Automatically import changed assets.\");\n            public static readonly GUIContent desiredImportWorkerCountPctOfLogicalCPUs = EditorGUIUtility.TrTextContent(\"Import Worker Count %\", \"Desired asset import worker count for new projects in percentage of available logical CPU cores.\");\n            public static readonly GUIContent desiredImportWorkerCountPctOfLogicalCPUsLearnMore = new GUIContent(\"Learn more...\", \"Go to import worker documentation.\");\n            public static readonly GUIContent directoryMonitoring = EditorGUIUtility.TrTextContent(\"Directory Monitoring\", \"Monitor directories instead of scanning all project files to detect asset changes.\");\n            public static readonly GUIContent compressAssetsOnImport = EditorGUIUtility.TrTextContent(\"Compress Textures on Import\", \"Disable to skip texture compression during import process (textures will be imported into uncompressed formats, and compressed when making a build). This preference is per project and local to a single user, to prevent cross project pollution.\");\n            public static readonly GUIContent verifySavingAssets = EditorGUIUtility.TrTextContent(\"Verify Saving Assets\", \"Show confirmation dialog whenever Unity saves any assets.\");\n            public static readonly GUIContent enterSafeModeDialog = EditorGUIUtility.TrTextContent(\"Show Enter Safe Mode Dialog\", \"Show confirmation dialog when Unity would enter Safe Mode due to script compilation errors.\");\n\n            public static readonly GUIContent cacheServer = new GUIContent(\"Unity Accelerator (Cache Server)\");\n            public static readonly GUIContent cacheServerDefaultMode = new GUIContent(\"Default Mode\", \"Specifies if Accelerator should be enabled or disabled by default. This can be overridden per project in editor settings.\");\n            public static readonly GUIContent cacheServerIPLabel = new GUIContent(\"Default IP address\", \"This IP address is used for the Accelerator if not overridden in the editor settings per project.\");\n            public static readonly GUIContent cacheServerLearnMore = new GUIContent(\"Learn more...\", \"Open Unity Accelerator documentation.\");\n        }\n\n        AssetPipelineAutoRefreshMode m_AutoRefresh;\n        bool m_DirectoryMonitoring;\n        bool m_CompressAssetsOnImport;\n        bool m_VerifySavingAssets;\n        bool m_EnterSafeModeDialog;\n        float m_DesiredImportWorkerCountPctOfLogicalCPUs;\n\n        const string kDesiredImportWorkerCountPctOfLogicalCPUsKey = \"DesiredImportWorkerCountPctOfLogicalCPUs\";\n        const float kDefaultDesiredImportWorkerCountPctOfLogicalCPUs = 0.25f;\n\n        const string kCacheServerIPAddressKey = \"CacheServer2IPAddress\";\n        const string kCacheServerModeKey = \"CacheServer2Mode\";\n\n        const string kModeKey = \"CacheServerMode\";\n        const string kDeprecatedEnabledKey = \"CacheServerEnabled\";\n\n        static bool s_CacheServerPrefsLoaded;\n        static bool s_HasPendingChanges;\n        enum ConnectionState { Unknown, Success, Failure }\n\n        static ConnectionState s_ConnectionState;\n        static string s_CacheServer2IPAddress;\n\n        enum CacheServer2Mode { Enabled, Disabled }\n        static CacheServer2Mode s_CacheServer2Mode;\n\n        public enum CacheServerMode { Local, Remote, Disabled }\n        static CacheServerMode s_CacheServerMode;\n        static bool s_EnableCustomPath;\n        static string s_CachePath;\n\n        public static bool IsCacheServerEnabled\n        {\n            get\n            {\n                ReadCacheServerPreferences();\n                return s_CacheServer2Mode == CacheServer2Mode.Enabled;\n            }\n        }\n\n        public static string CacheServerAddress\n        {\n            get\n            {\n                ReadCacheServerPreferences();\n                return s_CacheServer2IPAddress;\n            }\n        }\n\n        private static float GetDesiredImportWorkerCountPctOfLogicalCPUs()\n        {\n            return EditorPrefs.GetFloat(kDesiredImportWorkerCountPctOfLogicalCPUsKey, kDefaultDesiredImportWorkerCountPctOfLogicalCPUs);\n        }\n\n        public AssetPipelineAutoRefreshMode AutoRefreshModeEditorPref\n        {\n            get\n            {\n                var legacyAutoRefreshMode = EditorPrefs.GetBool(\"kAutoRefresh\") ? AssetPipelineAutoRefreshMode.Enabled : AssetPipelineAutoRefreshMode.Disabled;\n                return (AssetPipelineAutoRefreshMode)EditorPrefs.GetInt(\"kAutoRefreshMode\", (int)legacyAutoRefreshMode);\n            }\n            set\n            {\n                EditorPrefs.SetInt(\"kAutoRefreshMode\", (int)value);\n            }\n        }\n\n        void ReadAssetImportPreferences()\n        {\n            m_AutoRefresh = AutoRefreshModeEditorPref;\n            m_DirectoryMonitoring = EditorPrefs.GetBool(\"DirectoryMonitoring\", true);\n            m_VerifySavingAssets = EditorPrefs.GetBool(\"VerifySavingAssets\", false);\n\n            // This used to be a preference, but we now get it from the Editor User Settings\n            // because having a cross project preference that affects imports causes a lot of\n            // problems which we would like to avoid\n            m_CompressAssetsOnImport = EditorUserSettings.compressAssetsOnImport;\n            m_EnterSafeModeDialog = EditorPrefs.GetBool(\"EnterSafeModeDialog\", true);\n            m_DesiredImportWorkerCountPctOfLogicalCPUs = GetDesiredImportWorkerCountPctOfLogicalCPUs();\n        }\n\n        void WriteAssetImportPreferences()\n        {\n            AutoRefreshModeEditorPref = m_AutoRefresh;\n            bool doRefreshSettings = false;\n\n            bool oldDirectoryMonitoring = EditorPrefs.GetBool(\"DirectoryMonitoring\", true);\n            if (oldDirectoryMonitoring != m_DirectoryMonitoring)\n            {\n                EditorPrefs.SetBool(\"DirectoryMonitoring\", m_DirectoryMonitoring);\n                doRefreshSettings = true;\n            }\n\n            float oldDesiredImportWorkerCountPctOfLogicalCPUs = EditorPrefs.GetFloat(kDesiredImportWorkerCountPctOfLogicalCPUsKey, kDefaultDesiredImportWorkerCountPctOfLogicalCPUs);\n            if (oldDesiredImportWorkerCountPctOfLogicalCPUs != m_DesiredImportWorkerCountPctOfLogicalCPUs)\n            {\n                EditorPrefs.SetFloat(kDesiredImportWorkerCountPctOfLogicalCPUsKey, m_DesiredImportWorkerCountPctOfLogicalCPUs);\n                doRefreshSettings = true;\n            }\n\n            EditorPrefs.SetBool(\"VerifySavingAssets\", m_VerifySavingAssets);\n            EditorPrefs.SetBool(\"EnterSafeModeDialog\", m_EnterSafeModeDialog);\n\n            if (doRefreshSettings)\n                AssetDatabase.RefreshSettings();\n        }\n\n        static void ReadCacheServerPreferences()\n        {\n            if (s_CacheServerPrefsLoaded)\n                return;\n            s_CacheServer2IPAddress = EditorPrefs.GetString(kCacheServerIPAddressKey, s_CacheServer2IPAddress);\n            s_CacheServer2Mode = (CacheServer2Mode)EditorPrefs.GetInt(kCacheServerModeKey, (int)CacheServer2Mode.Disabled);\n            s_CacheServerMode = (CacheServerMode)EditorPrefs.GetInt(kModeKey, (int)(EditorPrefs.GetBool(kDeprecatedEnabledKey) ? CacheServerMode.Remote : CacheServerMode.Disabled));\n            s_CachePath = EditorPrefs.GetString(LocalCacheServer.PathKey);\n            s_EnableCustomPath = EditorPrefs.GetBool(LocalCacheServer.CustomPathKey);\n            s_CacheServerPrefsLoaded = true;\n        }\n\n        static void WriteCacheServerPreferences()\n        {\n            CacheServerMode oldMode = (CacheServerMode)EditorPrefs.GetInt(kModeKey);\n            var oldPath = EditorPrefs.GetString(LocalCacheServer.PathKey);\n            var oldCustomPath = EditorPrefs.GetBool(LocalCacheServer.CustomPathKey);\n            bool changedDir = false;\n            if (oldMode != s_CacheServerMode && oldMode == CacheServerMode.Local)\n                changedDir = true;\n            if (s_EnableCustomPath && oldPath != s_CachePath)\n                changedDir = true;\n            if (s_EnableCustomPath != oldCustomPath && s_CachePath != LocalCacheServer.GetCacheLocation() && s_CachePath != \"\")\n                changedDir = true;\n            if (changedDir)\n            {\n                var message = s_CacheServerMode == CacheServerMode.Local ?\n                    \"You have changed the location of the local cache storage.\" :\n                    \"You have disabled the local cache.\";\n                message += \" Do you want to delete the old locally cached data at \" + LocalCacheServer.GetCacheLocation() + \"?\";\n                if (EditorUtility.DisplayDialog(\"Delete old Cache\", message, \"Delete\", \"Don't Delete\"))\n                {\n                    LocalCacheServer.Clear();\n                }\n            }\n\n            EditorPrefs.SetString(kCacheServerIPAddressKey, s_CacheServer2IPAddress);\n            EditorPrefs.SetInt(kCacheServerModeKey, (int)s_CacheServer2Mode);\n            EditorPrefs.SetInt(kModeKey, (int)s_CacheServerMode);\n            EditorPrefs.SetString(LocalCacheServer.PathKey, s_CachePath);\n            EditorPrefs.SetBool(LocalCacheServer.CustomPathKey, s_EnableCustomPath);\n            LocalCacheServer.Setup();\n\n            AssetDatabase.RefreshSettings();\n\n            if (changedDir)\n            {\n                //Call ExitGUI after bringing up a dialog to avoid an exception\n                EditorGUIUtility.ExitGUI();\n            }\n        }\n\n        public override void OnActivate(string searchContext, VisualElement rootElement)\n        {\n            base.OnActivate(searchContext, rootElement);\n            ReadAssetImportPreferences();\n        }\n\n        [SettingsProvider]\n        internal static SettingsProvider CreateSettingsProvider()\n        {\n            var p = new AssetPipelinePreferences(\"Preferences/Asset Pipeline\", GetSearchKeywordsFromGUIContentProperties<Properties>());\n            p.guiHandler = searchContext =>\n            {\n                using (new SettingsWindow.GUIScope())\n                    p.ShowGUI();\n            };\n            return p;\n        }\n\n        void ShowGUI()\n        {\n            EditorGUIUtility.labelWidth = 200f;\n            AssetImportGUI();\n\n            if (!s_CacheServerPrefsLoaded)\n            {\n                ReadCacheServerPreferences();\n                bool shouldTryConnect = s_ConnectionState == ConnectionState.Unknown &&\n                    s_CacheServer2Mode != CacheServer2Mode.Disabled;\n                if (shouldTryConnect)\n                {\n                    var isConnected = AssetDatabase.IsConnectedToCacheServer();\n                    s_ConnectionState = isConnected ? ConnectionState.Success : ConnectionState.Failure;\n                }\n            }\n            {\n                EditorGUILayout.Space();\n                GUILayout.BeginHorizontal();\n                GUILayout.Label(Properties.cacheServer, EditorStyles.boldLabel);\n                if (GUILayout.Button(Properties.cacheServerLearnMore, EditorStyles.linkLabel))\n                {\n                    // Known issue with Docs redirect - versioned pages might not open offline docs\n                    var help = Help.FindHelpNamed(\"UnityAccelerator\");\n                    Help.BrowseURL(help);\n                }\n                GUILayout.EndHorizontal();\n                EditorGUI.BeginChangeCheck();\n\n                EditorGUILayout.Space();\n                CacheServerGUI();\n\n                if (EditorGUI.EndChangeCheck())\n                    s_HasPendingChanges = true;\n\n                // Only commit changes when we don't have an active hot control, to avoid restarting the cache server all the time while the slider is dragged, slowing down the UI.\n                if (s_HasPendingChanges && GUIUtility.hotControl == 0)\n                {\n                    s_HasPendingChanges = false;\n                    WriteCacheServerPreferences();\n                    ReadCacheServerPreferences();\n                }\n            }\n\n        }\n\n        void AssetImportGUI()\n        {\n            EditorGUI.BeginChangeCheck();\n\n            DoAutoRefreshMode();\n            DoImportWorkerCount();\n            DoDirectoryMonitoring();\n\n            bool oldCompressOnImport = m_CompressAssetsOnImport;\n            m_CompressAssetsOnImport = EditorGUILayout.Toggle(Properties.compressAssetsOnImport, oldCompressOnImport);\n            m_VerifySavingAssets = EditorGUILayout.Toggle(Properties.verifySavingAssets, m_VerifySavingAssets);\n            m_EnterSafeModeDialog = EditorGUILayout.Toggle(Properties.enterSafeModeDialog, m_EnterSafeModeDialog);\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (GUI.changed && m_CompressAssetsOnImport != oldCompressOnImport)\n                    EditorUserSettings.compressAssetsOnImport = m_CompressAssetsOnImport;\n                WriteAssetImportPreferences();\n                ReadAssetImportPreferences();\n            }\n        }\n\n        void DoAutoRefreshMode()\n        {\n            m_AutoRefresh = (AssetPipelineAutoRefreshMode)EditorGUILayout.EnumPopup(Properties.autoRefresh, m_AutoRefresh);\n        }\n\n        void DoImportWorkerCount()\n        {\n            GUILayout.BeginHorizontal();\n\n            var val = EditorGUILayout.FloatField(Properties.desiredImportWorkerCountPctOfLogicalCPUs, m_DesiredImportWorkerCountPctOfLogicalCPUs * 100.0f);\n            m_DesiredImportWorkerCountPctOfLogicalCPUs = Mathf.Clamp(val / 100f, 0f, 1f);\n\n            if (GUILayout.Button(Properties.desiredImportWorkerCountPctOfLogicalCPUsLearnMore, EditorStyles.linkLabel))\n            {\n                // Known issue with Docs redirect - versioned pages might not open offline docs\n                var help = Help.FindHelpNamed(\"ParallelImport\");\n                Help.BrowseURL(help);\n            }\n\n            GUILayout.EndHorizontal();\n        }\n\n        void DoDirectoryMonitoring()\n        {\n            bool isWindows = Application.platform == RuntimePlatform.WindowsEditor;\n            using (new EditorGUI.DisabledScope(!isWindows))\n            {\n                m_DirectoryMonitoring = EditorGUILayout.Toggle(Properties.directoryMonitoring, m_DirectoryMonitoring);\n                if (!isWindows)\n                    EditorGUILayout.HelpBox(\"Directory monitoring currently only available on windows\", MessageType.Info, true);\n            }\n        }\n\n        internal static bool ParseCacheServerAddress(string input, out string ip, out UInt16 port)\n        {\n            var address = input.Split(':');\n            ip = address[0];\n            port = 0;\n            if (address.Length == 2)\n            {\n                try\n                {\n                    port = UInt16.Parse(address[1]);\n                }\n                catch (Exception e)\n                {\n                    Debug.LogError($\"{e.Message} Exception thrown attempting to parse the port '{address[1]}'. Please double check the 'Default IP Address' and try again.\");\n                    return false;\n                }\n            }\n            else if (address.Length > 2)\n            {\n                Debug.LogError($\"Failure attempting to parse the address '{input}' as multiple ports were detected. Please double check the 'Default IP Address' and try again.\");\n                return false;\n            }\n            return true;\n        }\n\n        static void CacheServerGUI()\n        {\n            bool changeStateBeforeControls = GUI.changed;\n\n            s_CacheServer2Mode = (CacheServer2Mode)EditorGUILayout.EnumPopup(Properties.cacheServerDefaultMode, s_CacheServer2Mode);\n\n            s_CacheServer2IPAddress = EditorGUILayout.TextField(Properties.cacheServerIPLabel, s_CacheServer2IPAddress);\n\n            if (GUI.changed != changeStateBeforeControls)\n            {\n                s_ConnectionState = ConnectionState.Unknown;\n            }\n\n            EditorGUILayout.Space();\n\n            if (GUILayout.Button(\"Check Connection\", GUILayout.Width(150)))\n            {\n                if (ParseCacheServerAddress(s_CacheServer2IPAddress, out var ip, out var port) && AssetDatabase.CanConnectToCacheServer(ip, port))\n                    s_ConnectionState = ConnectionState.Success;\n                else\n                    s_ConnectionState = ConnectionState.Failure;\n\n            }\n\n            GUILayout.Space(-25);\n\n            switch (s_ConnectionState)\n            {\n                case ConnectionState.Success:\n                    EditorGUILayout.HelpBox(\"Connection successful.\", MessageType.Info, false);\n                    break;\n\n                case ConnectionState.Failure:\n                    EditorGUILayout.HelpBox(\"Connection failed.\", MessageType.Warning, false);\n                    break;\n\n                case ConnectionState.Unknown:\n                    GUILayout.Space(44);\n                    break;\n            }\n        }\n\n        public AssetPipelinePreferences(string path, IEnumerable<string> keywords = null) : base(path, keywords)\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PreferencesWindow/CollectionsPreferences.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor;\nusing UnityEditor.SceneManagement;\nusing UnityEngine.SceneManagement;\nusing Unity.Collections;\nusing Unity.Collections.LowLevel.Unsafe;\nusing Unity.Jobs.LowLevel.Unsafe;\nusing UnityEngine;\nusing UnityEngine.Analytics;\n\n\ninternal class JobsMenuProvider: SettingsProvider\n{\n    private static int savedJobWorkerCount = JobsUtility.JobWorkerCount;\n\n    class JobsProperties\n    {\n        public static readonly GUIContent jobSystem = EditorGUIUtility.TrTextContent(\"Job System\");\n        public static readonly GUIContent useJobThreads = EditorGUIUtility.TrTextContent(\"Use Job Threads\");\n        public static readonly GUIContent enableJobsDebugger = EditorGUIUtility.TrTextContent(\"Enable Jobs Debugger\");\n        public static readonly GUIContent leakDetectionLevel = EditorGUIUtility.TrTextContent(\"Leak Detection Level\");\n        public static readonly GUIContent graphicsThreadingMode = EditorGUIUtility.TrTextContent(\"Graphics Threading Mode\");\n        public static readonly GUIContent allowGraphicsJobsInEditor = EditorGUIUtility.TrTextContent(\"Allow Graphics Jobs in Editor\");\n    }\n\n    [SettingsProvider]\n    private static SettingsProvider JobsPreferencesItem()\n    {\n        var provider = new JobsMenuProvider(\"Preferences/Jobs\", GetSearchKeywordsFromGUIContentProperties<JobsProperties>()) { label = \"Jobs\" };\n        provider.guiHandler = searchContext => { OnGUI(searchContext, provider.ShowJobsProvider); };\n        return provider;\n    }\n\n    private void ShowJobsProvider(string searchContext)\n    {\n        GUILayout.BeginHorizontal();\n        GUILayout.Label(JobsProperties.jobSystem, EditorStyles.boldLabel);\n        GUILayout.EndHorizontal();\n\n        var originalWidth = EditorGUIUtility.labelWidth;\n        EditorGUIUtility.labelWidth = 200f;\n        EditorGUILayout.LabelField(\"For safety, these values are reset on editor restart.\");\n\n        bool madeChange = false;\n\n        bool oldWorkerCount = (JobsUtility.JobWorkerCount > 0);\n        bool newWorkerCount = EditorGUILayout.Toggle(JobsProperties.useJobThreads, oldWorkerCount);\n        if (newWorkerCount != oldWorkerCount)\n        {\n            madeChange = true;\n            SwitchUseJobThreads();\n        }\n\n        bool oldUseJobsDebugger = JobsUtility.JobDebuggerEnabled;\n        var newUseJobsDebugger = EditorGUILayout.Toggle(JobsProperties.enableJobsDebugger, JobsUtility.JobDebuggerEnabled);\n        if (newUseJobsDebugger != oldUseJobsDebugger)\n        {\n            madeChange = true;\n            SetUseJobsDebugger(newUseJobsDebugger);\n        }\n\n        var oldLeakDetectionMode = NativeLeakDetection.Mode;\n        var newLeakDetectionMode = (NativeLeakDetectionMode)EditorGUILayout.EnumPopup(JobsProperties.leakDetectionLevel, oldLeakDetectionMode);\n        if (newLeakDetectionMode != oldLeakDetectionMode)\n        {\n            madeChange = true;\n            SetLeakDetection(newLeakDetectionMode);\n        }\n\n        EditorGUILayout.Space();\n        GUILayout.BeginHorizontal();\n        GUILayout.Label(JobsProperties.graphicsThreadingMode, EditorStyles.boldLabel);\n        GUILayout.EndHorizontal();\n\n        //Starting here\n        EditorGUI.BeginChangeCheck();\n\n        bool oldAllowEditorGraphicsJobs = PlayerSettings.GetEditorGfxJobOverride();\n        bool newAllowEditorGraphicsJobs = oldAllowEditorGraphicsJobs;\n\n        if (GUI.enabled)\n        {\n            newAllowEditorGraphicsJobs = EditorGUILayout.Toggle(JobsProperties.allowGraphicsJobsInEditor, oldAllowEditorGraphicsJobs);\n        }\n        else\n        {\n            EditorGUILayout.Toggle(JobsProperties.allowGraphicsJobsInEditor, oldAllowEditorGraphicsJobs);\n        }\n\n        if (EditorGUI.EndChangeCheck() && (newAllowEditorGraphicsJobs != oldAllowEditorGraphicsJobs))\n        {\n            madeChange = true;\n            SetAllowEditorGraphicsJobs(newAllowEditorGraphicsJobs);\n            //From Player Settings graphics jobs on/off change: \n\n            bool restartEditor = CheckApplyEditorGraphicsJobsModeChange();\n            if (restartEditor)\n            {\n                EditorApplication.RequestCloseAndRelaunchWithCurrentArguments();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        if (madeChange)\n            Telemetry.LogMenuPreferences(new Telemetry(new Telemetry.MenuPreferencesEvent\n            {\n                allowJobInEditor = newAllowEditorGraphicsJobs,\n                useJobsThreads = newUseJobsDebugger,\n                enableJobsDebugger = newUseJobsDebugger,\n                nativeLeakDetectionMode = newLeakDetectionMode\n            }));\n\n        EditorGUIUtility.labelWidth = originalWidth;\n    }\n\n    private static void OnGUI(string searchContext, Action<string> drawAction)\n    {\n        using (new SettingsWindow.GUIScope())\n            drawAction(searchContext);\n    }\n\n    static void SwitchUseJobThreads()\n    {\n        if (JobsUtility.JobWorkerCount > 0)\n        {\n            savedJobWorkerCount = JobsUtility.JobWorkerCount;\n            JobsUtility.JobWorkerCount = 0;\n        }\n        else\n        {\n            JobsUtility.JobWorkerCount = savedJobWorkerCount;\n            if (savedJobWorkerCount == 0)\n            {\n                JobsUtility.ResetJobWorkerCount();\n            }\n        }\n    }\n\n    static bool CheckApplyEditorGraphicsJobsModeChange()\n    {\n        bool doRestart = false;\n        // If we have dirty scenes we need to save or discard changes before we restart editor.\n        // Otherwise user will get a dialog later on where they can click cancel and put editor in a bad device state.\n        var dirtyScenes = new List<Scene>();\n        for (int i = 0; i < EditorSceneManager.sceneCount; ++i)\n        {\n            var scene = EditorSceneManager.GetSceneAt(i);\n            if (scene.isDirty)\n                dirtyScenes.Add(scene);\n        }\n        if (dirtyScenes.Count != 0)\n        {\n            var result = EditorUtility.DisplayDialogComplex(\"Changing editor graphics jobs mode\",\n                \"You've changed the active graphics jobs mode. This requires a restart of the Editor. Do you want to save the Scene when restarting?\",\n                \"Save and Restart\", \"Cancel Changing API\", \"Discard Changes and Restart\");\n            if (result == 1)\n            {\n                doRestart = false; // Cancel was selected\n            }\n            else\n            {\n                doRestart = true;\n                if (result == 0) // Save and Restart was selected\n                {\n                    for (int i = 0; i < dirtyScenes.Count; ++i)\n                    {\n                        var saved = EditorSceneManager.SaveScene(dirtyScenes[i]);\n                        if (saved == false)\n                        {\n                            doRestart = false;\n                        }\n                    }\n                }\n                else // Discard Changes and Restart was selected\n                {\n                    for (int i = 0; i < dirtyScenes.Count; ++i)\n                        EditorSceneManager.ClearSceneDirtiness(dirtyScenes[i]);\n                }\n            }\n        }\n        else\n        {\n            doRestart = EditorUtility.DisplayDialog(\"Changing editor graphics jobs mode\",\n                \"You've changed the active graphics jobs mode. This requires a restart of the Editor.\",\n                \"Restart Editor\", \"Not now\");\n        }\n        \n        return doRestart;\n    }\n\n    static void SetAllowEditorGraphicsJobs(bool value)\n    {\n        PlayerSettings.SetEditorGfxJobOverride(value);\n    }\n\n    static void SetUseJobsDebugger(bool value)\n    {\n        JobsUtility.JobDebuggerEnabled = value;\n    }\n\n    static void SetLeakDetection(NativeLeakDetectionMode value)\n    {\n        switch (value)\n        {\n            case NativeLeakDetectionMode.Disabled:\n                {\n                    Debug.LogWarning(\"Leak detection has been disabled. Leak warnings will not be generated, and all leaks up to now are forgotten.\");\n                    break;\n                }\n            case NativeLeakDetectionMode.Enabled:\n                {\n                    Debug.Log(\"Leak detection has been enabled. Leak warnings will be generated upon domain reload.\");\n                    break;\n                }\n            case NativeLeakDetectionMode.EnabledWithStackTrace:\n                {\n                    Debug.Log(\"Leak detection with stack traces has been enabled. Leak warnings will be generated upon domain reload.\");\n                    break;\n                }\n            default:\n                {\n                    throw new Exception($\"Unhandled {nameof(NativeLeakDetectionMode)}\");\n                }\n        }\n\n        NativeLeakDetection.Mode = value;\n    }\n\n    [AnalyticInfo(eventName: \"collectionsMenuPreferences\", vendorKey: \"unity.collections\")]\n    internal struct Telemetry : IAnalytic\n    {\n        public Telemetry(MenuPreferencesEvent data) { m_data = data; }\n\n        [Serializable]\n        internal struct MenuPreferencesEvent : IAnalytic.IData\n        {\n            public bool enableJobsDebugger;\n            public bool useJobsThreads;\n            public bool allowJobInEditor;\n            public NativeLeakDetectionMode nativeLeakDetectionMode;\n        }\n\n        public bool TryGatherData(out IAnalytic.IData data, out Exception error)\n        {\n            error = null;\n            data = m_data;\n            return data != null;\n        }\n\n        public static void LogMenuPreferences(Telemetry analytics)\n        {\n        EditorAnalytics.SendAnalytic(analytics);\n        }\n      \n        MenuPreferencesEvent m_data;\n    }\n\n    public JobsMenuProvider(string path, IEnumerable<string> keywords = null)\n            : base(path, SettingsScope.User, keywords)\n    {\n    }\n\n}\n"
  },
  {
    "path": "Editor/Mono/PreferencesWindow/PreferencesItem.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor\n{\n    [Obsolete(\"[PreferenceItem] is deprecated. Use [SettingsProvider] instead.\")]\n    [AttributeUsage(AttributeTargets.Method)]\n    public sealed partial class PreferenceItem : Attribute\n    {\n        public PreferenceItem(string name) { this.name = name; }\n        public string name;\n        [RequiredSignature]\n        private static void signature() {}\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.Analytics;\nusing UnityEditor.Modules;\nusing UnityEditorInternal;\nusing System.Collections.Generic;\nusing System;\nusing System.IO;\nusing System.Linq;\nusing JetBrains.Annotations;\nusing Unity.CodeEditor;\nusing UnityEngine.UIElements;\nusing UnityEditor.Experimental;\nusing UnityEditor.SceneManagement;\nusing UnityEditor.UIElements;\n\nnamespace UnityEditor\n{\n    internal class PreferencesProvider : SettingsProvider\n    {\n        internal enum CodeOptimization\n        {\n            Debug,\n            Release\n        }\n\n        static class Constants\n        {\n            public static readonly GUIStyle errorLabel = \"WordWrappedLabel\";\n            public static readonly GUIStyle warningIcon = \"CN EntryWarn\";\n            public static readonly GUIStyle cacheFolderLocation = \"CacheFolderLocation\";\n        }\n\n        class Styles\n        {\n            public static readonly GUIContent browse = EditorGUIUtility.TrTextContent(\"Browse...\");\n            public static readonly GUIStyle clearBindingButton = new GUIStyle(GUI.skin.button);\n\n            static Styles()\n            {\n                clearBindingButton.margin.top = 0;\n            }\n        }\n\n        class GeneralProperties\n        {\n            public static readonly GUIContent loadPreviousProjectOnStartup = EditorGUIUtility.TrTextContent(\"Load Previous Project on Startup\");\n            public static readonly GUIContent disableEditorAnalytics = EditorGUIUtility.TrTextContent(\"Disable Editor Analytics\");\n            public static readonly GUIContent autoSaveScenesBeforeBuilding = EditorGUIUtility.TrTextContent(\"Auto-save scenes before building\");\n            public static readonly GUIContent scriptChangesDuringPlay = EditorGUIUtility.TrTextContent(\"Script Changes While Playing\");\n            public static readonly GUIContent editorFont = EditorGUIUtility.TrTextContent(\"Editor Font\");\n            public static readonly GUIContent editorTextRenderingMode = EditorGUIUtility.TrTextContent(\"Editor Default Text Rendering Mode\");\n            public static readonly GUIContent editorTextSharpness = EditorGUIUtility.TrTextContent(\"Editor Text Sharpness\");\n            public static readonly GUIContent editorSkin = EditorGUIUtility.TrTextContent(\"Editor Theme\");\n            public static readonly GUIContent[] editorSkinOptions = { EditorGUIUtility.TrTextContent(\"Light\"), EditorGUIUtility.TrTextContent(\"Dark\") };\n            public static readonly GUIContent hierarchyHeader = EditorGUIUtility.TrTextContent(\"Hierarchy window\");\n            public static readonly GUIContent enableAlphaNumericSorting = EditorGUIUtility.TrTextContent(\"Enable Alphanumeric Sorting\", \"If enabled then you can choose between Transform sorting and Alphabetical sorting in the Hierarchy.\");\n            public static readonly GUIContent defaultPrefabMode = EditorGUIUtility.TrTextContent(\"Default Prefab Mode\", \"This mode will be used when opening Prefab Mode from a Prefab instance in the Hierarchy.\");\n            public static readonly GUIContent applicationFrameThrottling = EditorGUIUtility.TrTextContent(\"Frame Throttling (milliseconds)\", \"The number of milliseconds the Editor can idle between frames.\");\n            public static readonly GUIContent inputMaxProcessTime = EditorGUIUtility.TrTextContent(\"Input Throttling (milliseconds)\", \"The maximum number of milliseconds the Editor will take to process user inputs.\");\n            public static readonly GUIContent interactionMode = EditorGUIUtility.TrTextContent(\"Interaction Mode\", \"Specifies how long the Editor can idle before it updates.\");\n            public static readonly GUIContent enterPlayModeSettingsFocusGameView = EditorGUIUtility.TrTextContent(\"Open Game View On Play\", \"Open a Game view window when you enter Play mode.\");\n            public static readonly GUIContent enableExtendedDynamicHints = EditorGUIUtility.TrTextContent(\"Enable extended Dynamic Hints\", \"Check this to enable extended Dynamic Hints. If available, extended Dynamic Hints will display more information when a property, object or tool is hovered for enough time, or when a Dynamic Hint is displayed\");\n            public static readonly GUIContent[] interactionModes =\n            {\n                EditorGUIUtility.TrTextContent(\"Default\", \"The Editor can idle up to 4 ms per frame.\"),\n                EditorGUIUtility.TrTextContent(\"No Throttling\", \"The Editor does not idle. It runs as fast as possible.\"),\n                EditorGUIUtility.TrTextContent(\"Monitor Refresh Rate\", \"The Editor can idle up to whatever the monitor's refresh rate is, in milliseconds.\"),\n                EditorGUIUtility.TrTextContent(\"Custom\", \"You specify how many milliseconds per frame the Editor can idle.\"),\n            };\n            public static readonly GUIContent progressDialogDelay = EditorGUIUtility.TrTextContent(\"Busy Progress Delay\", \"Delay in seconds before 'Unity is busy' progress bar shows up.\");\n            public static readonly GUIContent enableSnapping = EditorGUIUtility.TrTextContent(\"Graph Snapping\", \"If enabled, GraphElements in Graph Views (such as Shader Graph) align with one another when you move them. If disabled, GraphElements move freely.\");\n\n            public static readonly GUIContent packageManagerLogLevel = EditorGUIUtility.TrTextContent(\"Package Manager Log Level\",\n                \"Determines the level of detail when the Package Manager writes information to log files.\\n\"\n                + \"\\nFrom least detailed to most detailed:\"\n                + \"\\n* Error: unexpected errors and failures only.\"\n                + \"\\n* Warn: abnormal situations that can lead to issues.\"\n                + \"\\n* Info: high-level informational messages.\"\n                + \"\\n* Verbose: detailed informational messages.\"\n                + \"\\n* Debug: high-level debugging messages.\"\n                + \"\\n* Silly: detailed debugging messages.\");\n            public static readonly GUIContent packageManagerLogLevelOverridden = EditorGUIUtility.TrTextContent(\"Package Manager Log Level currently overridden by -enablePackageManagerTraces command-line argument.\");\n\n            public static readonly GUIContent performBumpMapCheck = EditorGUIUtility.TrTextContent(\"Perform Bump Map Check\", \"Enables Bump Map Checks upon import of Materials. This checks that textures used in a normal map material slot are actually defined as normal maps.\");\n            public static readonly GUIContent enableExtendedLogging = EditorGUIUtility.TrTextContent(\"Timestamp Editor log entries\", \"Adds timestamp and thread Id to Editor.log messages.\");\n            public static readonly GUIContent enableShortcutHelperBar = EditorGUIUtility.TrTextContent(\"Enable Shortcut Helper Bar\", \"Enables the Shortcut Helper Bar in the status bar at the bottom of the main Unity Editor window.\");\n            public static readonly GUIContent enablePlayModeTooltips = EditorGUIUtility.TrTextContent(\"Enable PlayMode Tooltips\", \"Enables tooltips in the editor while in play mode.\");\n            public static readonly GUIContent showSecondaryWindowsInTaskbar = EditorGUIUtility.TrTextContent(\"Show All Windows in Taskbar\",\n                @\"Enabling this setting allows undocked windows to be minimized in the OS taskbar.\nBy default, Windows will combine these under a single taskbar item.\");\n\n            public static readonly GUIContent useProjectPathInTitle = EditorGUIUtility.TrTextContent(\"Use Project Path in Window Title\", \"If enabled the Project's name is replaced in the main window title with the Project's path on disk.\");\n        }\n\n        class ExternalProperties\n        {\n            public static readonly GUIContent codeOptimizationOnStartup = EditorGUIUtility.TrTextContent(\"Code Optimization On Startup\");\n            public static readonly GUIContent changingThisSettingRequiresRestart = EditorGUIUtility.TrTextContent(\"Changing this setting requires a restart to take effect.\");\n            public static readonly GUIContent revisionControlDiffMerge = EditorGUIUtility.TrTextContent(\"Revision Control Diff/Merge\");\n            public static readonly GUIContent externalScriptEditor = EditorGUIUtility.TrTextContent(\"External Script Editor\");\n            public static readonly GUIContent imageApplication = EditorGUIUtility.TrTextContent(\"Image application\");\n        }\n\n        class UIScalingProperties\n        {\n            public static readonly GUIContent editorContentScaling = EditorGUIUtility.TrTextContent(\"Editor icons and text scaling\");\n            public static readonly GUIContent defaultContentScaling = EditorGUIUtility.TrTextContent(\"Use default desktop setting\");\n            public static readonly GUIContent currentContentScaling = EditorGUIUtility.TrTextContent(\"Current scaling\");\n            public static readonly GUIContent customContentScaling = EditorGUIUtility.TrTextContent(\"Use custom scaling value\");\n        }\n\n        class ColorsProperties\n        {\n            public static readonly GUIContent userDefaults = EditorGUIUtility.TrTextContent(\"Use Defaults\");\n        }\n\n        class GICacheProperties\n        {\n            public static readonly GUIContent maxCacheSize = EditorGUIUtility.TrTextContent(\"Maximum Cache Size (GB)\", \"The size of the GI Cache folder will be kept below this maximum value when possible. A background job will periodically clean up the oldest unused files.\");\n            public static readonly GUIContent customCacheLocation = EditorGUIUtility.TrTextContent(\"Custom cache location\", \"Specify the GI Cache folder location.\");\n            public static readonly GUIContent cacheFolderLocation = EditorGUIUtility.TrTextContent(\"Cache Folder Location\", \"The GI Cache folder is shared between all projects.\");\n            public static readonly GUIContent cacheCompression = EditorGUIUtility.TrTextContent(\"Cache compression\", \"Use fast realtime compression for the GI cache files to reduce the size of generated data. Disable it and clean the cache if you need access to the raw data generated by Enlighten.\");\n            public static readonly GUIContent cantChangeCacheSettings = EditorGUIUtility.TrTextContent(\"Cache settings can't be changed while lightmapping is being computed.\");\n            public static readonly GUIContent cleanCache = EditorGUIUtility.TrTextContent(\"Clean Cache\");\n            public static readonly GUIContent browseGICacheLocation = EditorGUIUtility.TrTextContent(\"Browse for GI Cache location\");\n            public static readonly GUIContent cacheSizeIs = EditorGUIUtility.TrTextContent(\"Cache size is\");\n            public static readonly GUIContent pleaseWait = EditorGUIUtility.TrTextContent(\"Please wait...\");\n        }\n\n        class SceneViewProperties\n        {\n            public static readonly GUIContent enableFilteringWhileSearching = EditorGUIUtility.TrTextContent(\"Enable filtering while searching\", \"If enabled, searching will cause non-matching items in the scene view to be greyed out\");\n            public static readonly GUIContent enableFilteringWhileLodGroupEditing = EditorGUIUtility.TrTextContent(\"Enable filtering while editing LOD groups\", \"If enabled, editing LOD groups will cause other objects in the scene view to be greyed out\");\n            public static readonly GUIContent handlesLineThickness = EditorGUIUtility.TrTextContent(\"Line Thickness\", \"Thickness of manipulator tool handle lines\");\n            public static readonly GUIContent placementMode = EditorGUIUtility.TrTextContent(\"3D Placement Mode\", \"Select where newly created 3D objects are placed in the scene.\");\n            public static readonly GUIContent createObjectsAtWorldOrigin = EditorGUIUtility.TrTextContent(\"World Origin\");\n            public static readonly GUIContent createObjectsAtRaycastToScenePivot = EditorGUIUtility.TrTextContent(\"Scene Intersection\");\n            public static readonly GUIContent createObjectsAtScenePivot = EditorGUIUtility.TrTextContent(\"Scene Pivot\");\n            public static readonly GUIContent enableConstrainProportionsScalingForNewObjects = EditorGUIUtility.TrTextContent(\"Create Objects with Constrained Proportions scale on\", \"If enabled, scale in the transform component will be set to constrain proportions for new GameObjects by default\");\n            public static readonly GUIContent useInspectorExpandedStateContent = EditorGUIUtility.TrTextContent(\"Auto-hide gizmos\", \"Automatically hide gizmos of Components collapsed in the Inspector\");\n            public static readonly GUIContent ignoreAlwaysRefreshWhenNotFocused = EditorGUIUtility.TrTextContent(\"Refresh the Scene view only when the Editor is in focus.\", \"If enabled, ignore the \\\"Always Refresh\\\" flag on the Scene view when the Editor is not the foregrounded application.\");\n        }\n\n        class LanguageProperties\n        {\n            public static readonly GUIContent editorLanguageExperimental = EditorGUIUtility.TrTextContent(\"Editor Language (Experimental)\");\n            public static readonly GUIContent editorLanguage = EditorGUIUtility.TrTextContent(\"Editor language\");\n            public static readonly GUIContent localizeCompileMessages = EditorGUIUtility.TrTextContent(\"Localize compiler messages\");\n        }\n\n        class DeveloperModeProperties\n        {\n            public static readonly GUIContent developerMode = EditorGUIUtility.TrTextContent(\"Developer Mode\", \"Enable or disable developer mode features.\");\n            public static readonly GUIContent generateOnPostprocessAllAssets = EditorGUIUtility.TrTextContent(\"Generate OnPostprocessAllAssets Dependency Diagram\", \"Generates a graphviz diagram to show OnPostprocessAllAssets dependencies.\");\n            public static readonly GUIContent showRepaintDots = EditorGUIUtility.TrTextContent(\"Show Repaint Dots\", \"Enable or disable the colored dots that flash when an EditorWindow repaints.\");\n            public static readonly GUIContent redirectionServer = EditorGUIUtility.TrTextContent(\"Documentation Server\", \"Select the documentation redirection server.\");\n        }\n\n        private List<IPreferenceWindowExtension> prefWinExtensions;\n\n        private bool m_ReopenLastUsedProjectOnStartup;\n        private bool m_EnableEditorAnalytics;\n        private bool m_AnalyticSettingChangedThisSession = false;\n        private bool m_AutoSaveScenesBeforeBuilding;\n        private ScriptChangesDuringPlayOptions m_ScriptCompilationDuringPlay;\n        private bool m_DeveloperMode;\n        private bool m_ShowRepaintDots;\n        private bool m_DeveloperModeDirty;\n        private bool m_ScriptDebugInfoEnabled;\n        private string m_GpuDeviceInUse;\n        private string m_GpuDevice;\n        private string[] m_CachedGpuDevices;\n        private bool m_ContentScaleChangedThisSession;\n        private int m_ContentScalePercentValue;\n        private bool m_TaskbarBehaviorChangedThisSession;\n        private bool m_TaskbarBehaviorValue;\n        private bool m_EnableConstrainProportionsScalingForNewObjects;\n        private string[] m_CustomScalingLabels = {\"100%\", \"125%\", \"150%\", \"175%\", \"200%\", \"225%\", \"250%\", \"300%\", \"350%\"};\n        private int[] m_CustomScalingValues = { 100, 125, 150, 175, 200, 225, 250, 300, 350 };\n        private bool m_EnableExtendedLogging;\n        private readonly string kContentScalePrefKey = \"CustomEditorUIScale\";\n        private readonly string kWindowsTaskbarPrefKey = \"WindowsTaskbarBehavior\";\n\n        private struct GICacheSettings\n        {\n            public bool m_EnableCustomPath;\n            public int m_MaximumSize;\n            public string m_CachePath;\n            public int m_CompressionLevel; // GICache compression level, corresponds to CompressionLevel in Compression.h\n        }\n        private GICacheSettings m_GICacheSettings;\n\n        private RefString m_ScriptEditorPath = new RefString(\"\");\n        private RefString m_ImageAppPath = new RefString(\"\");\n        private static int m_DiffToolIndex;\n\n        // how many menu items come before the actual list of languages\n        // (Default + separator)\n        private const int k_LangListMenuOffset = 2;\n\n        private string m_SelectedLanguage;\n        private static GUIContent[] m_EditorLanguageNames;\n        private bool m_EnableEditorLocalization;\n        private static SystemLanguage[] m_stableLanguages = { SystemLanguage.English };\n        private bool m_EnableCompilerMessagesLocalization;\n\n        EditorTextRenderingMode m_EditorTextRenderingMode = EditorTextRenderingMode.SDF;\n        private float m_EditorTextSharpness = 0.0f;\n        private bool m_AllowAlphaNumericHierarchy = false;\n        private PrefabStage.Mode m_DefaultPrefabModeFromHierarchy = PrefabStage.Mode.InContext;\n        private GOCreationCommands.PlacementMode m_CreatePlacementMode = GOCreationCommands.PlacementMode.SceneIntersection;\n        private float m_ProgressDialogDelay = 3.0f;\n        private bool m_GraphSnapping;\n        private bool m_EnableExtendedDynamicHints\n        {\n            get { return TooltipView.s_EnableExtendedDynamicHints; }\n            set { TooltipView.s_EnableExtendedDynamicHints.value = value; }\n        }\n\n        private string[] m_ScriptApps;\n        private string[] m_ImageApps;\n        private static string[] m_DiffTools;\n\n        private static string m_CustomDiffToolPath = \"\";\n        private static string[] m_CustomDiffToolArguments = new[] {\"\", \"\", \"\"};\n\n        private string m_noDiffToolsMessage = string.Empty;\n\n        private string[] m_ScriptAppDisplayNames;\n        private string[] m_ImageAppDisplayNames;\n        private const string kRecentScriptAppsKey = \"RecentlyUsedScriptApp\";\n        private const string kRecentImageAppsKey = \"RecentlyUsedImageApp\";\n\n        private static readonly string k_ExpressNotSupportedMessage = L10n.Tr(\n            \"Unfortunately Visual Studio Express does not allow itself to be controlled by external applications. \" +\n            \"You can still use it by manually opening the Visual Studio project file, but Unity cannot automatically open files for you when you doubleclick them. \" +\n            \"\\n(This does work with Visual Studio Pro)\"\n        );\n\n        private const int kRecentAppsCount = 10;\n\n        SortedDictionary<string, List<KeyValuePair<string, PrefColor>>> s_CachedColors = null;\n\n        private List<GUIContent> m_SystemFonts = new List<GUIContent>();\n        private const int k_browseButtonWidth = 80;\n\n        class RefString\n        {\n            public RefString(string s) { str = s; }\n            public string str;\n            public static implicit operator string(RefString s) { return s.str; }\n            public override string ToString()\n            {\n                return str;\n            }\n        }\n\n        public PreferencesProvider(string path, IEnumerable<string> keywords = null)\n            : base(path, SettingsScope.User, keywords)\n        {\n        }\n\n        public override void OnActivate(string searchContext, VisualElement rootElement)\n        {\n            base.OnActivate(searchContext, rootElement);\n            prefWinExtensions = ModuleManager.GetPreferenceWindowExtensions();\n            ReadPreferences();\n        }\n\n        internal static bool useProjectPathInTitle\n        {\n            get\n            {\n                return EditorPrefs.GetBool(\"UseProjectPathInTitle\", false);\n            }\n            set\n            {\n                if(value != EditorPrefs.GetBool(\"UseProjectPathInTitle\", false))\n                {\n                    EditorPrefs.SetBool(\"UseProjectPathInTitle\", value);\n                    EditorApplication.UpdateMainWindowTitle();\n                }\n            }\n        }\n\n\n        [SettingsProvider]\n        internal static SettingsProvider CreateGeneralProvider()\n        {\n            var settings = new PreferencesProvider(\"Preferences/_General\", GetSearchKeywordsFromGUIContentProperties<GeneralProperties>()) { label = \"General\" };\n            settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowGeneral); };\n            settings.activateHandler = (searchContext, rootElement) => { settings.EnableGeneral(); };\n            return settings;\n        }\n\n        [SettingsProvider]\n        internal static SettingsProvider CreateExternalToolsProvider()\n        {\n            var settings = new PreferencesProvider(\"Preferences/External Tools\", GetSearchKeywordsFromGUIContentProperties<ExternalProperties>());\n            settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowExternalApplications); };\n            return settings;\n        }\n\n        [SettingsProvider]\n        internal static SettingsProvider CreateColorsProvider()\n        {\n            var settings = new PreferencesProvider(\"Preferences/Colors\", GetSearchKeywordsFromGUIContentProperties<ColorsProperties>().Concat(OrderPrefs(PrefSettings.Prefs<PrefColor>()).Values.SelectMany(l => l).Select(pair => pair.Key)));\n            settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowColors); };\n            return settings;\n        }\n\n        [UsedImplicitly, SettingsProvider]\n        internal static SettingsProvider CreateGICacheProvider()\n        {\n            if (UnityEditor.MPE.ProcessService.level == UnityEditor.MPE.ProcessLevel.Secondary && !UnityEditor.MPE.ProcessService.HasCapability(\"enable-gi\"))\n                return null;\n            var settings = new PreferencesProvider(\"Preferences/GI Cache\", GetSearchKeywordsFromGUIContentProperties<GICacheProperties>());\n            settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowGICache); };\n            return settings;\n        }\n\n        [UsedImplicitly, SettingsProvider]\n        internal static SettingsProvider CreateSceneViewProvider()\n        {\n            var settings = new PreferencesProvider(\"Preferences/Scene View\", GetSearchKeywordsFromGUIContentProperties<SceneViewProperties>());\n            settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowSceneView); };\n            return settings;\n        }\n\n        [UsedImplicitly, SettingsProvider]\n        internal static SettingsProvider CreateLanguagesProvider()\n        {\n            var editorLanguages = LocalizationDatabase.GetAvailableEditorLanguages();\n            if (m_EditorLanguageNames == null || m_EditorLanguageNames.Length != editorLanguages.Length)\n            {\n                m_EditorLanguageNames = new GUIContent[editorLanguages.Length];\n\n                for (int i = 0; i < editorLanguages.Length; ++i)\n                {\n                    var culture = LocalizationDatabase.GetCulture(editorLanguages[i]);\n                    var langName = new System.Globalization.CultureInfo(culture).NativeName;\n\n                    // Due to the issue 1088990, workaround for both Chinese is necessary.\n                    // This workaround should be removed just after the fix.\n                    if (editorLanguages[i] == SystemLanguage.ChineseSimplified)\n                    {\n                        byte[] letters = { 0xE7, 0xAE, 0x80, 0xE4, 0xBD, 0x93, 0xE4, 0xB8, 0xAD, 0xE6, 0x96, 0x87 };\n                        langName = System.Text.Encoding.UTF8.GetString(letters);\n                    }\n                    else if (editorLanguages[i] == SystemLanguage.ChineseTraditional)\n                    {\n                        byte[] letters = { 0xE7, 0xB9, 0x81, 0xE9, 0xAB, 0x94, 0xE4, 0xB8, 0xAD, 0xE6, 0x96, 0x87 };\n                        langName = System.Text.Encoding.UTF8.GetString(letters);\n                    }\n\n                    // not in stable languages list - display it as experimental language\n                    if (ArrayUtility.FindIndex(m_stableLanguages, v => v == editorLanguages[i]) < 0)\n                    {\n                        m_EditorLanguageNames[i] = EditorGUIUtility.TextContent(string.Format(\"{0} (Experimental)\", langName));\n                    }\n                    else\n                    {\n                        m_EditorLanguageNames[i] = EditorGUIUtility.TextContent(langName);\n                    }\n                }\n                ArrayUtility.Insert(ref m_EditorLanguageNames, 0, EditorGUIUtility.TextContent(\"\"));\n                GUIContent defaultLanguage = EditorGUIUtility.TextContent(string.Format(\"Default ( {0} )\", LocalizationDatabase.GetDefaultEditorLanguage().ToString()));\n                ArrayUtility.Insert(ref m_EditorLanguageNames, 0, defaultLanguage);\n            }\n\n            if (editorLanguages.Length > 1)\n            {\n                var settings = new PreferencesProvider(\"Preferences/Languages\");\n                settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowLanguage); };\n                return settings;\n            }\n\n            return null;\n        }\n\n        [UsedImplicitly, SettingsProvider]\n        internal static SettingsProvider CreateUIScalingProvider()\n        {\n            if (Application.platform == RuntimePlatform.WindowsEditor)\n            {\n                var settings = new PreferencesProvider(\"Preferences/UIScaling\", GetSearchKeywordsFromGUIContentProperties<UIScalingProperties>()) { label = \"UI Scaling\" };\n                settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowUIScaling); };\n                return settings;\n            }\n\n            return null;\n        }\n\n        [SettingsProvider]\n        internal static SettingsProvider CreateDeveloperModeProvider()\n        {\n            // Only show this section if this is a source build or we're already in developer mode.\n            if (!(Unsupported.IsSourceBuild() || Unsupported.IsDeveloperMode()))\n                return null;\n            var settings = new PreferencesProvider(\"Preferences/Developer Mode\", GetSearchKeywordsFromGUIContentProperties<DeveloperModeProperties>());\n            settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowDeveloperMode); };\n            return settings;\n        }\n\n        // Group Preference sections with the same name\n        private static void OnGUI(string searchContext, Action<string> drawAction)\n        {\n            using (new SettingsWindow.GUIScope())\n                drawAction(searchContext);\n        }\n\n        private void ShowExternalApplications(string searchContext)\n        {\n            // Applications\n\n            EditorUtility.SelectMenuItemFunction selectMenuItemAction = AppsListClickRuntimePlatformExtension;\n            FilePopup(ExternalProperties.externalScriptEditor, ScriptEditorUtility.GetExternalScriptEditor(), ref m_ScriptAppDisplayNames, ref m_ScriptApps, m_ScriptEditorPath, CodeEditor.SystemDefaultPath, OnScriptEditorChanged, selectMenuItemAction);\n\n            CodeEditor.Editor.CurrentCodeEditor.OnGUI();\n\n            GUILayout.Space(10f);\n\n            FilePopup(ExternalProperties.imageApplication, m_ImageAppPath, ref m_ImageAppDisplayNames, ref m_ImageApps, m_ImageAppPath, \"internal\", null);\n\n            GUILayout.Space(10f);\n\n            {\n                m_DiffToolIndex = EditorGUILayout.Popup(ExternalProperties.revisionControlDiffMerge, m_DiffToolIndex, m_DiffTools);\n                if (m_DiffToolIndex == m_DiffTools.Length - 1)\n                {\n                    GUILayout.BeginHorizontal();\n                    m_CustomDiffToolPath = EditorGUILayout.DelayedTextField(\"Tool Path\", m_CustomDiffToolPath);\n\n                    if (GUILayout.Button(\"Browse\", GUILayout.Width(k_browseButtonWidth)))\n                    {\n                        string path = EditorUtility.OpenFilePanel(\"Browse for application\", \"\", InternalEditorUtility.GetApplicationExtensionForRuntimePlatform(Application.platform));\n                        if (path.Length != 0)\n                        {\n                            m_CustomDiffToolPath = path;\n                        }\n                    }\n\n                    GUILayout.EndHorizontal();\n                    m_CustomDiffToolArguments[0] = EditorGUILayout.DelayedTextField(\"Two-way diff command line\", m_CustomDiffToolArguments[0]);\n                    m_CustomDiffToolArguments[1] = EditorGUILayout.DelayedTextField(\"Three-way diff command line\", m_CustomDiffToolArguments[1]);\n                    m_CustomDiffToolArguments[2] = EditorGUILayout.DelayedTextField(\"Merge arguments\", m_CustomDiffToolArguments[2]);\n                }\n            }\n\n            if (m_noDiffToolsMessage != string.Empty)\n            {\n                GUILayout.BeginHorizontal(EditorStyles.helpBox);\n                GUILayout.Label(\"\", Constants.warningIcon);\n                GUILayout.Label(m_noDiffToolsMessage, Constants.errorLabel);\n                GUILayout.EndHorizontal();\n            }\n\n            GUILayout.Space(10f);\n\n            foreach (IPreferenceWindowExtension extension in prefWinExtensions)\n            {\n                if (extension.HasExternalApplications())\n                {\n                    GUILayout.Space(10f);\n                    extension.ShowExternalApplications();\n                }\n            }\n\n            ApplyChangesToPrefs();\n        }\n\n        private void OnScriptEditorChanged()\n        {\n            CodeEditor.Editor.SetCodeEditor(m_ScriptEditorPath);\n        }\n\n        private void EnableGeneral()\n        {\n            var fontNames = new List<string>(EditorResources.supportedFontNames);\n\n            fontNames.Sort();\n\n            // Remove the default font and prepend it with the '(Default)' suffix\n            fontNames.Remove(EditorResources.GetDefaultFont());\n            fontNames.Insert(0, EditorResources.GetDefaultFont() + \" (Default)\");\n\n            foreach (var fontName in fontNames)\n            {\n                m_SystemFonts.Add(new GUIContent(fontName));\n            }\n        }\n\n        private void ShowGeneral(string searchContext)\n        {\n            // Options\n            m_ReopenLastUsedProjectOnStartup = EditorGUILayout.Toggle(GeneralProperties.loadPreviousProjectOnStartup, m_ReopenLastUsedProjectOnStartup);\n\n            bool enableEditorAnalyticsOld = m_EnableEditorAnalytics;\n\n            using (new EditorGUI.DisabledScope(m_AnalyticSettingChangedThisSession))\n            {\n                m_EnableEditorAnalytics = !EditorGUILayout.Toggle(GeneralProperties.disableEditorAnalytics, !m_EnableEditorAnalytics);\n                if (enableEditorAnalyticsOld != m_EnableEditorAnalytics)\n                {\n                    m_AnalyticSettingChangedThisSession = true;\n                    EditorAnalytics.enabled = m_EnableEditorAnalytics;\n                }\n                if (m_AnalyticSettingChangedThisSession)\n                {\n                    EditorGUILayout.HelpBox(ExternalProperties.changingThisSettingRequiresRestart.text, MessageType.Warning);\n                }\n            }\n\n            m_AutoSaveScenesBeforeBuilding = EditorGUILayout.Toggle(GeneralProperties.autoSaveScenesBeforeBuilding, m_AutoSaveScenesBeforeBuilding);\n            m_ScriptCompilationDuringPlay = (ScriptChangesDuringPlayOptions)EditorGUILayout.EnumPopup(GeneralProperties.scriptChangesDuringPlay, m_ScriptCompilationDuringPlay);\n\n            CodeOptimization codeOptimization = (CodeOptimization)EditorGUILayout.EnumPopup(ExternalProperties.codeOptimizationOnStartup, m_ScriptDebugInfoEnabled ? CodeOptimization.Debug : CodeOptimization.Release);\n            m_ScriptDebugInfoEnabled = (codeOptimization == CodeOptimization.Debug ? true : false);\n\n            int newSkin = EditorGUILayout.Popup(GeneralProperties.editorSkin, !EditorGUIUtility.isProSkin ? 0 : 1, GeneralProperties.editorSkinOptions);\n            if ((!EditorGUIUtility.isProSkin ? 0 : 1) != newSkin)\n                InternalEditorUtility.SwitchSkinAndRepaintAllViews();\n\n            if (LocalizationDatabase.currentEditorLanguage == SystemLanguage.English)\n            {\n                EditorGUI.BeginChangeCheck();\n                var userFontName = EditorPrefs.GetString(\"user_editor_font\", null);\n                int selectedFontIndex = Math.Max(0, m_SystemFonts.FindIndex(f => f.text == userFontName));\n                selectedFontIndex = EditorGUILayout.Popup(GeneralProperties.editorFont, selectedFontIndex, m_SystemFonts.ToArray());\n                if (EditorGUI.EndChangeCheck())\n                {\n                    if (selectedFontIndex == 0)\n                    {\n                        EditorPrefs.DeleteKey(\"user_editor_font\");\n                    }\n                    else\n                    {\n                        var selectedFontName = m_SystemFonts[selectedFontIndex].text;\n                        EditorPrefs.SetString(\"user_editor_font\", selectedFontName);\n                    }\n\n                    // Refresh skin to get new font\n                    Unsupported.ClearSkinCache();\n\n                    // Force a domain reload to get arround caching issue\n                    EditorUtility.RequestScriptReload();\n                    //EditorApplication.RequestRepaintAllTexts(VersionChangeType.Layout | VersionChangeType.Repaint);\n                }\n            }\n\n            EditorGUI.BeginChangeCheck();\n            m_EditorTextRenderingMode = (EditorTextRenderingMode)EditorGUILayout.EnumPopup(GeneralProperties.editorTextRenderingMode, m_EditorTextRenderingMode);\n            if (EditorGUI.EndChangeCheck())\n            {\n                EditorPrefs.SetInt(\"EditorTextRenderingMode\", (int)m_EditorTextRenderingMode);\n                EditorTextSettings.SetEditorTextRenderingMode(m_EditorTextRenderingMode);\n                EditorApplication.UpdateEditorTextRenderingMode(m_EditorTextRenderingMode);\n\n                // Force a domain reload to get arround caching issue (changing to bitmap might change the sizes that the code is not expecting to change)\n                //EditorApplication.RequestRepaintAllTexts(VersionChangeType.Layout | VersionChangeType.Repaint);\n                EditorUtility.RequestScriptReload();\n            }\n\n            if (EditorTextSettings.currentEditorTextRenderingMode == EditorTextRenderingMode.SDF)\n                m_EditorTextSharpness = EditorGUILayout.Slider(GeneralProperties.editorTextSharpness, m_EditorTextSharpness, -0.5f, 1.0f);\n\n            if (InternalEditorUtility.IsGpuDeviceSelectionSupported())\n            {\n                // Cache gpu devices\n                if (m_CachedGpuDevices == null)\n                {\n                    var devices = InternalEditorUtility.GetGpuDevices();\n                    m_CachedGpuDevices = new string[devices.Length + 1];\n                    m_CachedGpuDevices[0] = \"Automatic\";\n                    Array.Copy(devices, 0, m_CachedGpuDevices, 1, devices.Length);\n                }\n\n                // Try to find selected gpu device\n                var currentGpuDeviceIndex = Array.FindIndex(m_CachedGpuDevices, gpuDevice => m_GpuDevice == gpuDevice);\n                if (currentGpuDeviceIndex == -1)\n                    currentGpuDeviceIndex = 0;\n\n                if (string.IsNullOrEmpty(m_GpuDeviceInUse))\n                {\n                    m_GpuDeviceInUse = m_CachedGpuDevices[currentGpuDeviceIndex];\n\n                    if (string.IsNullOrEmpty(m_GpuDevice))\n                    {\n                        m_GpuDevice = m_GpuDeviceInUse;\n                    }\n                }\n\n                var newGpuDeviceIndex = EditorGUILayout.Popup(\"Device To Use\", currentGpuDeviceIndex, m_CachedGpuDevices);\n                if (currentGpuDeviceIndex != newGpuDeviceIndex)\n                {\n                    m_GpuDevice = m_CachedGpuDevices[newGpuDeviceIndex];\n                }\n\n                if (m_GpuDevice != m_GpuDeviceInUse)\n                {\n                    EditorGUILayout.HelpBox(ExternalProperties.changingThisSettingRequiresRestart.text, MessageType.Warning);\n                }\n            }\n\n            if (Application.platform == RuntimePlatform.WindowsEditor)\n            {\n                var progressDialogDelay = EditorGUILayout.FloatField(GeneralProperties.progressDialogDelay, m_ProgressDialogDelay);\n                progressDialogDelay = Mathf.Clamp(progressDialogDelay, 0.1f, 1000.0f);\n                if (progressDialogDelay != m_ProgressDialogDelay)\n                {\n                    EditorUtility.BusyProgressDialogDelayChanged(progressDialogDelay);\n                    m_ProgressDialogDelay = progressDialogDelay;\n                }\n            }\n            m_GraphSnapping = EditorGUILayout.Toggle(GeneralProperties.enableSnapping, m_GraphSnapping);\n\n            GameView.openWindowOnEnteringPlayMode = EditorGUILayout.Toggle(GeneralProperties.enterPlayModeSettingsFocusGameView, GameView.openWindowOnEnteringPlayMode);\n\n            useProjectPathInTitle = EditorGUILayout.Toggle(GeneralProperties.useProjectPathInTitle, useProjectPathInTitle);\n\n            DrawInteractionModeOptions();\n\n            DrawPackageManagerOptions();\n            DrawDynamicHintsOptions();\n            DrawPerformBumpMapCheck();\n\n            m_EnableExtendedLogging = EditorGUILayout.Toggle(GeneralProperties.enableExtendedLogging, m_EnableExtendedLogging);\n\n            DrawEnableHelperBar();\n            DrawEnableTooltipsInPlayMode();\n            EditorGUILayout.Space();\n\n            GUILayout.Label(GeneralProperties.hierarchyHeader, EditorStyles.boldLabel);\n\n            EditorGUI.indentLevel++;\n            bool oldAlphaNumeric = m_AllowAlphaNumericHierarchy;\n            m_AllowAlphaNumericHierarchy = EditorGUILayout.Toggle(GeneralProperties.enableAlphaNumericSorting, m_AllowAlphaNumericHierarchy);\n            m_DefaultPrefabModeFromHierarchy = (PrefabStage.Mode)EditorGUILayout.EnumPopup(GeneralProperties.defaultPrefabMode, m_DefaultPrefabModeFromHierarchy);\n            EditorGUI.indentLevel--;\n\n            EditorGUILayout.Space();\n\n            if (Application.platform == RuntimePlatform.WindowsEditor)\n            {\n                bool existingBehaviorValue = m_TaskbarBehaviorValue;\n                m_TaskbarBehaviorValue = EditorGUILayout.Toggle(GeneralProperties.showSecondaryWindowsInTaskbar, existingBehaviorValue);\n\n                if (existingBehaviorValue != m_TaskbarBehaviorValue)\n                {\n                    m_TaskbarBehaviorChangedThisSession = true;\n                }\n\n                if (m_TaskbarBehaviorChangedThisSession)\n                {\n                    EditorGUILayout.HelpBox(ExternalProperties.changingThisSettingRequiresRestart.text, MessageType.Warning);\n                }\n            }\n\n            ApplyChangesToPrefs();\n\n            if (oldAlphaNumeric != m_AllowAlphaNumericHierarchy)\n                EditorApplication.DirtyHierarchyWindowSorting();\n        }\n\n        enum InteractionMode\n        {\n            Default,                // 4 ms\n            NoThrottling,           // 0 ms (will never idle)\n            MonitorRefreshRate,     // ~16 ms\n            Custom                  // Between 1 ms and 33 ms\n        }\n\n        private void DrawInteractionModeOptions()\n        {\n            const int defaultIdleTimeMs = 4;\n            const string idleTimePrefKeyName = \"ApplicationIdleTime\";\n            const string interactionModePrefKeyName = \"InteractionMode\";\n            const string inputMaxProcessTimeKeyName = \"InputMaxProcessTime\";\n            var monitorRefreshDelayMs = Math.Min(1000, (int)(1000.0 / Screen.currentResolution.refreshRateRatio.value));\n            var idleTimeMs = EditorPrefs.GetInt(idleTimePrefKeyName, defaultIdleTimeMs);\n            var inputMaxProcessTime = EditorPrefs.GetInt(inputMaxProcessTimeKeyName, 100);\n            var interactionModeOption = (InteractionMode)EditorPrefs.GetInt(interactionModePrefKeyName, (int)InteractionMode.Default);\n\n            if (Event.current.type == EventType.MouseDown)\n                GeneralProperties.interactionModes[(int)InteractionMode.MonitorRefreshRate].text = $\"Monitor Refresh Rate ({monitorRefreshDelayMs} ms)\";\n\n            EditorGUI.BeginChangeCheck();\n            interactionModeOption = (InteractionMode)EditorGUILayout.Popup(GeneralProperties.interactionMode, (int)interactionModeOption, GeneralProperties.interactionModes);\n            if (interactionModeOption == InteractionMode.Default)\n            {\n                if (EditorGUI.EndChangeCheck())\n                {\n                    EditorPrefs.DeleteKey(idleTimePrefKeyName);\n                    EditorPrefs.DeleteKey(interactionModePrefKeyName);\n                    EditorApplication.UpdateInteractionModeSettings();\n                }\n            }\n            else if (interactionModeOption == InteractionMode.NoThrottling)\n            {\n                if (EditorGUI.EndChangeCheck())\n                {\n                    EditorPrefs.SetInt(idleTimePrefKeyName, 0);\n                    EditorPrefs.SetInt(interactionModePrefKeyName, (int)interactionModeOption);\n                    EditorApplication.UpdateInteractionModeSettings();\n                }\n            }\n            else if (interactionModeOption == InteractionMode.MonitorRefreshRate)\n            {\n                if (EditorGUI.EndChangeCheck())\n                {\n                    EditorPrefs.SetInt(idleTimePrefKeyName, monitorRefreshDelayMs);\n                    EditorPrefs.SetInt(interactionModePrefKeyName, (int)interactionModeOption);\n                    EditorApplication.UpdateInteractionModeSettings();\n                }\n            }\n            else\n            {\n                idleTimeMs = EditorGUILayout.IntSlider(GeneralProperties.applicationFrameThrottling, idleTimeMs, 0, 33);\n                if (Application.platform == RuntimePlatform.WindowsEditor)\n                    inputMaxProcessTime = EditorGUILayout.IntSlider(GeneralProperties.inputMaxProcessTime, inputMaxProcessTime, 1, 200);\n                if (EditorGUI.EndChangeCheck())\n                {\n                    EditorPrefs.SetInt(idleTimePrefKeyName, idleTimeMs);\n                    EditorPrefs.SetInt(inputMaxProcessTimeKeyName, inputMaxProcessTime);\n                    EditorPrefs.SetInt(interactionModePrefKeyName, (int)interactionModeOption);\n                    EditorApplication.UpdateInteractionModeSettings();\n                }\n            }\n        }\n\n        private void DrawDynamicHintsOptions()\n        {\n            m_EnableExtendedDynamicHints = EditorGUILayout.Toggle(GeneralProperties.enableExtendedDynamicHints, m_EnableExtendedDynamicHints);\n        }\n\n        private void DrawPackageManagerOptions()\n        {\n            bool isLogLevelOverridden = Application.HasARGV(\"enablePackageManagerTraces\");\n            using (new EditorGUI.DisabledScope(isLogLevelOverridden))\n            {\n                var packageManagerLogLevel = (PackageManager.LogLevel)EditorGUILayout.EnumPopup(GeneralProperties.packageManagerLogLevel, PackageManager.Client.LogLevel);\n                if (packageManagerLogLevel != PackageManager.Client.LogLevel)\n                {\n                    PackageManager.Client.LogLevel = packageManagerLogLevel;\n                }\n                if (isLogLevelOverridden)\n                {\n                    EditorGUILayout.HelpBox(GeneralProperties.packageManagerLogLevelOverridden.text, MessageType.Info, true);\n                }\n            }\n        }\n\n        void DrawPerformBumpMapCheck()\n        {\n            const string bumpMapChecksKeyName = \"PerformBumpMapChecks\";\n            var bumpMapChecks = EditorPrefs.GetBool(bumpMapChecksKeyName, true);\n\n            EditorGUI.BeginChangeCheck();\n            bumpMapChecks = EditorGUILayout.Toggle(GeneralProperties.performBumpMapCheck, bumpMapChecks);\n            if (EditorGUI.EndChangeCheck())\n            {\n                EditorPrefs.SetBool(bumpMapChecksKeyName, bumpMapChecks);\n            }\n        }\n\n        void DrawEnableHelperBar()\n        {\n            const string shortcutHelperBarKeyName = \"EnableShortcutHelperBar\";\n            var enableShortcutHelperBar = EditorPrefs.GetBool(shortcutHelperBarKeyName, false);\n\n            EditorGUI.BeginChangeCheck();\n            enableShortcutHelperBar = EditorGUILayout.Toggle(GeneralProperties.enableShortcutHelperBar, enableShortcutHelperBar);\n            if (EditorGUI.EndChangeCheck())\n            {\n                EditorPrefs.SetBool(shortcutHelperBarKeyName, enableShortcutHelperBar);\n                ShortcutManagement.ShortcutHelperBarUtility.RemoveAppStatusBarClient();\n            }\n        }\n\n        void DrawEnableTooltipsInPlayMode()\n        {\n            const string tooltipsKeyName = \"EnableTooltipsInPlayMode\";\n            var enableTooltips = EditorPrefs.GetBool(tooltipsKeyName, false);\n\n            EditorGUI.BeginChangeCheck();\n            enableTooltips = EditorGUILayout.Toggle(GeneralProperties.enablePlayModeTooltips, enableTooltips);\n            if (EditorGUI.EndChangeCheck())\n            {\n                EditorPrefs.SetBool(tooltipsKeyName, enableTooltips);\n\n                // Transfer native\n                EditorApplication.UpdateTooltipsInPlayModeSettings();\n            }\n        }\n\n        public void ApplyChangesToPrefs(bool force = false)\n        {\n            if (GUI.changed || force)\n            {\n                WritePreferences();\n                ReadPreferences();\n                settingsWindow.Repaint();\n            }\n        }\n\n        internal static SortedDictionary<string, List<KeyValuePair<string, T>>> OrderPrefs<T>(IEnumerable<KeyValuePair<string, T>> input)\n            where T : IPrefType\n        {\n            SortedDictionary<string, List<KeyValuePair<string, T>>> retval = new SortedDictionary<string, List<KeyValuePair<string, T>>>();\n\n            foreach (KeyValuePair<string, T> kvp in input)\n            {\n                int idx = kvp.Key.IndexOf('/');\n                string first, second;\n                if (idx == -1)\n                {\n                    first = \"General\";\n                    second = kvp.Key;\n                }\n                else\n                {\n                    first = kvp.Key.Substring(0, idx);\n                    second = kvp.Key.Substring(idx + 1);\n                }\n                if (!retval.ContainsKey(first))\n                {\n                    List<KeyValuePair<string, T>> inner = new List<KeyValuePair<string, T>> {new KeyValuePair<string, T>(second, kvp.Value)};\n                    retval.Add(first, new List<KeyValuePair<string, T>>(inner));\n                }\n                else\n                {\n                    retval[first].Add(new KeyValuePair<string, T>(second, kvp.Value));\n                }\n            }\n\n            return retval;\n        }\n\n        private void RevertColors()\n        {\n            PrefSettings.RevertAll<PrefColor>();\n        }\n\n        private void ShowColors(string searchContext)\n        {\n            if (s_CachedColors == null)\n            {\n                s_CachedColors = OrderPrefs(PrefSettings.Prefs<PrefColor>());\n            }\n\n            var changedColor = false;\n            PrefColor ccolor = null;\n\n            // some pref colors are very long, and changing them would mean invalidating any user-defined colors.\n            // as a compromise, we'll clip the label with an ellipses and show the full text in a tooltip.\n            var clipping = EditorStyles.label.clipping;\n            EditorStyles.label.clipping = TextClipping.Ellipsis;\n\n            foreach (KeyValuePair<string, List<KeyValuePair<string, PrefColor>>> category in s_CachedColors)\n            {\n                GUILayout.Label(category.Key, EditorStyles.boldLabel);\n                foreach (KeyValuePair<string, PrefColor> kvp in category.Value)\n                {\n                    EditorGUI.BeginChangeCheck();\n                    Color c = EditorGUILayout.ColorField(EditorGUIUtility.TempContent(kvp.Key, kvp.Key), kvp.Value.Color);\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        ccolor = kvp.Value;\n                        ccolor.Color = c;\n                        changedColor = true;\n                    }\n                }\n                if (ccolor != null)\n                    PrefSettings.Set(ccolor.Name, ccolor);\n            }\n            EditorStyles.label.clipping = clipping;\n\n            GUILayout.Space(5f);\n\n            if (GUILayout.Button(ColorsProperties.userDefaults, GUILayout.Width(120)))\n            {\n                RevertColors();\n                changedColor = true;\n            }\n\n            if (changedColor)\n                EditorApplication.RequestRepaintAllViews();\n        }\n\n        private void ShowSceneView(string searchContext)\n        {\n            EditorGUI.BeginChangeCheck();\n\n            GUILayout.Label(\"General\", EditorStyles.boldLabel);\n\n            var oldLabelWidth = EditorGUIUtility.labelWidth;\n            var toggleLabelWidth = EditorStyles.label.CalcSize(SceneViewProperties.ignoreAlwaysRefreshWhenNotFocused).x;\n            EditorGUIUtility.labelWidth = toggleLabelWidth;\n\n            GUIContent PlacementModeToGUIContent(GOCreationCommands.PlacementMode mode)\n            {\n                if (mode == GOCreationCommands.PlacementMode.SceneIntersection)\n                    return SceneViewProperties.createObjectsAtRaycastToScenePivot;\n                else if(mode == GOCreationCommands.PlacementMode.WorldOrigin)\n                    return SceneViewProperties.createObjectsAtWorldOrigin;\n                else if(mode == GOCreationCommands.PlacementMode.ScenePivot)\n                    return SceneViewProperties.createObjectsAtScenePivot;\n\n                return GUIContent.none;\n            }\n            void AddItem(GenericMenu menu, GOCreationCommands.PlacementMode mode)\n            {\n                menu.AddItem(PlacementModeToGUIContent(mode), m_CreatePlacementMode == mode, mode =>\n                {\n                    m_CreatePlacementMode = (GOCreationCommands.PlacementMode)mode;\n                    WritePreferences();\n                }, mode);\n            }\n            EditorGUILayout.BeginHorizontal();\n            EditorGUILayout.LabelField(SceneViewProperties.placementMode);\n            if (EditorGUILayout.DropdownButton(PlacementModeToGUIContent(m_CreatePlacementMode), FocusType.Keyboard))\n            {\n                var menu = new GenericMenu();\n                AddItem(menu, GOCreationCommands.PlacementMode.SceneIntersection);\n                AddItem(menu, GOCreationCommands.PlacementMode.WorldOrigin);\n                AddItem(menu, GOCreationCommands.PlacementMode.ScenePivot);\n                menu.ShowAsContext();\n            }\n            EditorGUILayout.EndHorizontal();\n\n            m_EnableConstrainProportionsScalingForNewObjects = EditorGUILayout.Toggle(SceneViewProperties.enableConstrainProportionsScalingForNewObjects, m_EnableConstrainProportionsScalingForNewObjects);\n            AnnotationUtility.useInspectorExpandedState = EditorGUILayout.Toggle(SceneViewProperties.useInspectorExpandedStateContent, AnnotationUtility.useInspectorExpandedState);\n            SceneView.s_PreferenceIgnoreAlwaysRefreshWhenNotFocused.value = EditorGUILayout.Toggle(SceneViewProperties.ignoreAlwaysRefreshWhenNotFocused, SceneView.s_PreferenceIgnoreAlwaysRefreshWhenNotFocused);\n\n            GUILayout.Label(\"Handles\", EditorStyles.boldLabel);\n            Handles.s_LineThickness.value = EditorGUILayout.IntSlider(SceneViewProperties.handlesLineThickness, (int)Handles.s_LineThickness.value, 1, 5);\n\n            GUILayout.Label(\"Search\", EditorStyles.boldLabel);\n            SceneView.s_PreferenceEnableFilteringWhileSearching.value = EditorGUILayout.Toggle(SceneViewProperties.enableFilteringWhileSearching, SceneView.s_PreferenceEnableFilteringWhileSearching);\n            SceneView.s_PreferenceEnableFilteringWhileLodGroupEditing.value  = EditorGUILayout.Toggle(SceneViewProperties.enableFilteringWhileLodGroupEditing, SceneView.s_PreferenceEnableFilteringWhileLodGroupEditing);\n\n            EditorGUIUtility.labelWidth = oldLabelWidth;\n\n            if (EditorGUI.EndChangeCheck())\n            {\n                WritePreferences();\n                SceneView.RepaintAll();\n            }\n        }\n\n        private void ShowGICache(string searchContext)\n        {\n            EditorGUI.BeginChangeCheck();\n            {\n                // Show Gigabytes to the user.\n                const int kMinSizeInGigabytes = 5;\n                const int kMaxSizeInGigabytes = 200;\n\n                // Write size in GigaBytes.\n                m_GICacheSettings.m_MaximumSize = EditorGUILayout.IntSlider(GICacheProperties.maxCacheSize, m_GICacheSettings.m_MaximumSize, kMinSizeInGigabytes, kMaxSizeInGigabytes);\n            }\n            GUILayout.BeginHorizontal();\n            {\n                if (Lightmapping.isRunning)\n                {\n                    GUIContent warning = EditorGUIUtility.TextContent(GICacheProperties.cantChangeCacheSettings.text);\n                    EditorGUILayout.HelpBox(warning.text, MessageType.Warning, true);\n                }\n            }\n            GUILayout.EndHorizontal();\n\n            using (new EditorGUI.DisabledScope(Lightmapping.isRunning))\n            {\n                m_GICacheSettings.m_EnableCustomPath = EditorGUILayout.Toggle(GICacheProperties.customCacheLocation, m_GICacheSettings.m_EnableCustomPath);\n\n                // browse for cache folder if not per project\n                if (m_GICacheSettings.m_EnableCustomPath)\n                {\n                    GUIStyle style = EditorStyles.miniButton;\n                    GUILayout.BeginHorizontal();\n                    EditorGUILayout.PrefixLabel(GICacheProperties.cacheFolderLocation, style);\n                    Rect r = GUILayoutUtility.GetRect(GUIContent.none, style);\n                    GUIContent guiText = string.IsNullOrEmpty(m_GICacheSettings.m_CachePath) ? Styles.browse : new GUIContent(m_GICacheSettings.m_CachePath);\n                    if (EditorGUI.DropdownButton(r, guiText, FocusType.Passive, style))\n                    {\n                        string pathToOpen = m_GICacheSettings.m_CachePath;\n                        string path = EditorUtility.OpenFolderPanel(GICacheProperties.browseGICacheLocation.text, pathToOpen, \"\");\n                        if (!string.IsNullOrEmpty(path))\n                        {\n                            m_GICacheSettings.m_CachePath = path;\n                            WritePreferences();\n                        }\n                    }\n                    GUILayout.EndHorizontal();\n                }\n                else\n                    m_GICacheSettings.m_CachePath = \"\";\n\n                // We use toggle for now, 0 means kCompressionLevelNone, 1 - kCompressionLevelFastest.\n                m_GICacheSettings.m_CompressionLevel = EditorGUILayout.Toggle(GICacheProperties.cacheCompression, m_GICacheSettings.m_CompressionLevel == 1) ? 1 : 0;\n\n                if (GUILayout.Button(GICacheProperties.cleanCache, GUILayout.Width(120)))\n                {\n                    EditorUtility.DisplayProgressBar(GICacheProperties.cleanCache.text, GICacheProperties.pleaseWait.text, 0.0F);\n                    Lightmapping.Clear();\n                    EditorUtility.DisplayProgressBar(GICacheProperties.cleanCache.text, GICacheProperties.pleaseWait.text, 0.5F);\n                    UnityEditor.Lightmapping.ClearDiskCache();\n                    EditorUtility.ClearProgressBar();\n                }\n\n                if (UnityEditor.Lightmapping.diskCacheSize >= 0)\n                    GUILayout.Label(GICacheProperties.cacheSizeIs.text + \" \" + EditorUtility.FormatBytes(UnityEditor.Lightmapping.diskCacheSize));\n                else\n                    GUILayout.Label(GICacheProperties.cacheSizeIs.text + \" is being calculated...\");\n\n                GUILayout.Label(GICacheProperties.cacheFolderLocation.text + \":\");\n                GUILayout.Label(UnityEditor.Lightmapping.diskCachePath, Constants.cacheFolderLocation);\n            }\n\n            if (EditorGUI.EndChangeCheck())\n                WritePreferences();\n        }\n\n        private void ShowLanguage(string searchContext)\n        {\n            var enable_localization = EditorGUILayout.Toggle(LanguageProperties.editorLanguageExperimental, m_EnableEditorLocalization);\n            if (enable_localization != m_EnableEditorLocalization)\n            {\n                m_EnableEditorLocalization = enable_localization;\n                m_SelectedLanguage = LocalizationDatabase.GetDefaultEditorLanguage().ToString();\n            }\n\n            EditorGUI.BeginDisabledGroup(!m_EnableEditorLocalization);\n            {\n                SystemLanguage[] editorLanguages = LocalizationDatabase.GetAvailableEditorLanguages();\n\n                int idx = 0;\n                for (int i = 0; i < editorLanguages.Length; i++)\n                {\n                    if (editorLanguages[i].ToString().Equals(m_SelectedLanguage))\n                    {\n                        idx = k_LangListMenuOffset + i;\n                        break;\n                    }\n                }\n\n                int sel = EditorGUILayout.Popup(LanguageProperties.editorLanguage, idx, m_EditorLanguageNames);\n                m_SelectedLanguage = (sel == 0) ? LocalizationDatabase.GetDefaultEditorLanguage().ToString() :\n                    editorLanguages[sel - k_LangListMenuOffset].ToString();\n\n                m_EnableCompilerMessagesLocalization = EditorGUILayout.Toggle(LanguageProperties.localizeCompileMessages, m_EnableCompilerMessagesLocalization);\n            }\n            EditorGUI.EndDisabledGroup();\n\n            if (!m_SelectedLanguage.Equals(LocalizationDatabase.currentEditorLanguage.ToString()))\n            {\n                SystemLanguage lang = (SystemLanguage)Enum.Parse(typeof(SystemLanguage), m_SelectedLanguage);\n                EditorGUIUtility.NotifyLanguageChanged(lang);\n                EditorUtility.RequestScriptReload();\n            }\n\n            ApplyChangesToPrefs();\n        }\n\n        private void ShowUIScaling(string searchContext)\n        {\n            EditorGUI.BeginChangeCheck();\n            if (Application.platform == RuntimePlatform.WindowsEditor)\n            {\n                GUILayout.Label(UIScalingProperties.editorContentScaling, EditorStyles.boldLabel);\n\n                GUILayout.Space(5);\n\n                GUILayout.BeginVertical();\n                var currentScaling = CurrentEditorScalingValue;\n\n                bool customScaling = EditorPrefs.HasKey(kContentScalePrefKey) && m_ContentScalePercentValue > 0;\n                bool useDesktopScaling = EditorGUILayout.Toggle(UIScalingProperties.defaultContentScaling, !customScaling);\n\n                if ((!customScaling) != useDesktopScaling)\n                {\n                    m_ContentScaleChangedThisSession = true;\n\n                    if (useDesktopScaling)\n                    {\n                        EditorPrefs.DeleteKey(kContentScalePrefKey);\n                        m_ContentScalePercentValue = -1;\n                    }\n                    else\n                    {\n                        if (m_ContentScalePercentValue < 0)\n                            m_ContentScalePercentValue = currentScaling;\n                    }\n                }\n\n                using (new EditorGUI.DisabledScope(useDesktopScaling))\n                {\n                    int displayedScaleValue = (m_ContentScalePercentValue > 0) ? m_ContentScalePercentValue : currentScaling;\n\n                    GUILayout.BeginHorizontal();\n                    GUILayout.Label(UIScalingProperties.currentContentScaling, GUILayout.Width(EditorGUIUtility.labelWidth));\n                    GUILayout.Label(currentScaling + \"%\");\n                    GUILayout.EndHorizontal();\n\n                    displayedScaleValue = EditorGUILayout.IntPopup(UIScalingProperties.customContentScaling.text, displayedScaleValue, m_CustomScalingLabels, m_CustomScalingValues);\n                    if (m_ContentScalePercentValue != displayedScaleValue && m_ContentScalePercentValue >= 0)\n                    {\n                        m_ContentScaleChangedThisSession = true;\n                        m_ContentScalePercentValue = displayedScaleValue;\n                    }\n                }\n\n\n                if (m_ContentScaleChangedThisSession)\n                    EditorGUILayout.HelpBox(ExternalProperties.changingThisSettingRequiresRestart.text, MessageType.Warning);\n\n                GUILayout.EndVertical();\n            }\n            if (EditorGUI.EndChangeCheck())\n                WritePreferences();\n\n            ApplyChangesToPrefs();\n        }\n\n        private void ShowDeveloperMode(string searchContext)\n        {\n            EditorGUI.BeginChangeCheck();\n\n            GUILayout.BeginHorizontal();\n            m_DeveloperMode = EditorGUILayout.Toggle(DeveloperModeProperties.developerMode, m_DeveloperMode, GUILayout.ExpandWidth(false));\n            GUILayout.EndHorizontal();\n\n            using (new EditorGUI.DisabledScope(!m_DeveloperMode))\n            {\n                m_ShowRepaintDots = EditorGUILayout.Toggle(DeveloperModeProperties.showRepaintDots, m_ShowRepaintDots);\n                m_DeveloperModeDirty = EditorGUI.EndChangeCheck();\n\n                EditorGUI.BeginChangeCheck();\n\n                var docServer = (Help.DocRedirectionServer)EditorGUILayout.EnumPopup(DeveloperModeProperties.redirectionServer, Help.docRedirectionServer);\n\n                if (EditorGUI.EndChangeCheck())\n                {\n                    Help.docRedirectionServer = docServer;\n                }\n\n                if (GUILayout.Button(DeveloperModeProperties.generateOnPostprocessAllAssets))\n                {\n                    AssetPostprocessingInternal.s_OnPostprocessAllAssetsCallbacks.GenerateDependencyDiagram(\"OnPostprocessAllAssets.dot\");\n                }\n            }\n\n            if (m_DeveloperModeDirty)\n            {\n                ApplyChangesToPrefs();\n                EditorApplication.UpdateMainWindowTitle();\n            }\n        }\n\n        private void WriteRecentAppsList(string[] paths, string path, string prefsKey)\n        {\n            int appIndex = 0;\n            // first write the selected app (if it's not a built-in one)\n            if (path.Length != 0)\n            {\n                EditorPrefs.SetString(prefsKey + appIndex, path);\n                ++appIndex;\n            }\n            // write the other apps\n            for (int i = 0; i < paths.Length; ++i)\n            {\n                if (appIndex >= kRecentAppsCount)\n                    break;     // stop when we wrote up to the limit\n                if (paths[i].Length == 0)\n                    continue;     // do not write built-in app into recently used list\n                if (paths[i] == path)\n                    continue;     // this is a selected app, do not write it twice\n                EditorPrefs.SetString(prefsKey + appIndex, paths[i]);\n                ++appIndex;\n            }\n        }\n\n        private void WritePreferences()\n        {\n            CodeEditor.Editor.SetCodeEditor(m_ScriptEditorPath);\n\n            EditorPrefs.SetString(\"kImagesDefaultApp\", m_ImageAppPath);\n            EditorPrefs.SetString(\"kDiffsDefaultApp\", m_DiffTools.Length == 0 ? \"\" : m_DiffTools[m_DiffToolIndex]);\n\n            InternalEditorUtility.SetCustomDiffToolPrefs(m_CustomDiffToolPath, m_CustomDiffToolArguments[0], m_CustomDiffToolArguments[1], m_CustomDiffToolArguments[2]);\n\n            WriteRecentAppsList(m_ScriptApps, m_ScriptEditorPath, kRecentScriptAppsKey);\n            WriteRecentAppsList(m_ImageApps, m_ImageAppPath, kRecentImageAppsKey);\n\n            if (m_ContentScaleChangedThisSession)\n            {\n                EditorPrefs.SetInt(kContentScalePrefKey, m_ContentScalePercentValue);\n            }\n\n            if (m_TaskbarBehaviorChangedThisSession)\n            {\n                if (m_TaskbarBehaviorValue)\n                {\n                    EditorPrefs.SetBool(kWindowsTaskbarPrefKey, m_TaskbarBehaviorValue);\n                }\n                else\n                {\n                    EditorPrefs.DeleteKey(kWindowsTaskbarPrefKey);\n                }\n            }\n\n            EditorPrefs.SetBool(\"ReopenLastUsedProjectOnStartup\", m_ReopenLastUsedProjectOnStartup);\n            EditorPrefs.SetBool(\"EnableEditorAnalytics\", m_EnableEditorAnalytics);\n            EditorPrefs.SetBool(\"SaveScenesBeforeBuilding\", m_AutoSaveScenesBeforeBuilding);\n            EditorPrefs.SetInt(\"ScriptCompilationDuringPlay\", (int)m_ScriptCompilationDuringPlay);\n\n            // The Preferences window always writes all preferences, we don't want this behavior since we\n            // want the default value to just match \"IsSourceBuild\" until the developer has explicitly changed it.\n            if (m_DeveloperModeDirty)\n            {\n                EditorPrefs.SetBool(\"DeveloperMode\", m_DeveloperMode);\n                // Repaint all views to show/hide debug repaint indicator\n                InternalEditorUtility.RepaintAllViews();\n            }\n\n            EditorGUI.s_ShowRepaintDots.value = m_ShowRepaintDots;\n\n            EditorPrefs.SetBool(\"ScriptDebugInfoEnabled\", m_ScriptDebugInfoEnabled);\n\n            EditorPrefs.SetBool(\"Editor.kEnableEditorLocalization\", m_EnableEditorLocalization);\n            EditorPrefs.SetString(\"Editor.kEditorLocale\", m_SelectedLanguage);\n            EditorPrefs.SetBool(\"Editor.kEnableCompilerMessagesLocalization\", m_EnableCompilerMessagesLocalization);\n\n            EditorPrefs.SetInt(\"EditorTextRenderingMode\", (int)m_EditorTextRenderingMode);\n            EditorPrefs.SetFloat($\"EditorTextSharpness_{EditorResources.GetFont(FontDef.Style.Normal).name}\", m_EditorTextSharpness);\n            EditorTextSettings.SetEditorTextRenderingMode(m_EditorTextRenderingMode);\n            EditorApplication.RequestRepaintAllTexts(VersionChangeType.Repaint);\n\n            EditorPrefs.SetBool(\"AllowAlphaNumericHierarchy\", m_AllowAlphaNumericHierarchy);\n            EditorPrefs.SetInt(\"DefaultPrefabModeFromHierarchy\", (int)m_DefaultPrefabModeFromHierarchy);\n\n            EditorPrefs.SetFloat(\"EditorBusyProgressDialogDelay\", m_ProgressDialogDelay);\n            GOCreationCommands.s_PlacementMode = m_CreatePlacementMode;\n            EditorPrefs.SetString(\"GpuDeviceName\", m_GpuDevice);\n\n            EditorPrefs.SetBool(\"GICacheEnableCustomPath\", m_GICacheSettings.m_EnableCustomPath);\n            EditorPrefs.SetInt(\"GICacheMaximumSizeGB\", m_GICacheSettings.m_MaximumSize);\n            EditorPrefs.SetString(\"GICacheFolder\", m_GICacheSettings.m_CachePath);\n            EditorPrefs.SetInt(\"GICacheCompressionLevel\", m_GICacheSettings.m_CompressionLevel);\n\n            foreach (IPreferenceWindowExtension extension in prefWinExtensions)\n            {\n                extension.WritePreferences();\n            }\n            UnityEditor.Lightmapping.UpdateCachePath();\n\n            EditorPrefs.SetBool(\"GraphSnapping\", m_GraphSnapping);\n\n            EditorPrefs.SetBool(\"EnableConstrainProportionsTransformScale\", m_EnableConstrainProportionsScalingForNewObjects);\n            EditorPrefs.SetBool(\"UseInspectorExpandedState\", AnnotationUtility.useInspectorExpandedState);\n            EditorPrefs.SetBool(\"EnableExtendedLogging\", m_EnableExtendedLogging);\n        }\n\n        private int CurrentEditorScalingValue\n        {\n            get {return Mathf.RoundToInt(GUIUtility.pixelsPerPoint * 100); }\n        }\n\n        private void ReadPreferences()\n        {\n            m_ScriptEditorPath.str = ScriptEditorUtility.GetExternalScriptEditor();\n\n            m_ImageAppPath.str = EditorPrefs.GetString(\"kImagesDefaultApp\");\n\n            m_ScriptApps = BuildAppPathList(m_ScriptEditorPath, kRecentScriptAppsKey, CodeEditor.SystemDefaultPath);\n\n            var foundScriptEditorPaths = CodeEditor.Editor.GetFoundScriptEditorPaths();\n\n            foreach (var apps in m_ScriptApps)\n            {\n                foundScriptEditorPaths[apps] = CodeEditor.Editor.GetInstallationForPath(apps).Name;\n            }\n\n            m_ScriptApps = new[] { \"\" }.Concat(foundScriptEditorPaths.Keys).ToArray();\n            m_ScriptAppDisplayNames = new[] { \"Open by file extension\" }.Concat(foundScriptEditorPaths.Values).ToArray();\n\n            m_ImageApps = BuildAppPathList(m_ImageAppPath, kRecentImageAppsKey, \"\");\n\n            //BuildFriendlyAppNameList(m_ScriptApps, foundScriptEditorPaths, \"Open by file extension\");\n\n            m_ImageAppDisplayNames = BuildFriendlyAppNameList(m_ImageApps, null,\n                L10n.Tr(\"Open by file extension\"));\n\n            m_DiffTools = InternalEditorUtility.GetAvailableDiffTools();\n\n            ReloadCustomDiffToolData();\n\n            if ((m_DiffTools == null || (m_DiffTools.Length == 1 && m_CustomDiffToolPath.Equals(\"\"))))\n            {\n                m_noDiffToolsMessage = InternalEditorUtility.GetNoDiffToolsDetectedMessage();\n            }\n\n            string diffTool = EditorPrefs.GetString(\"kDiffsDefaultApp\");\n            m_DiffToolIndex = ArrayUtility.IndexOf(m_DiffTools, diffTool);\n            if (m_DiffToolIndex == -1)\n                m_DiffToolIndex = 0;\n\n            m_ReopenLastUsedProjectOnStartup = EditorPrefs.GetBool(\"ReopenLastUsedProjectOnStartup\");\n\n            m_EnableEditorAnalytics = EditorPrefs.GetBool(\"EnableEditorAnalyticsV2\", EditorPrefs.GetBool(\"EnableEditorAnalytics\", true));\n\n            m_AutoSaveScenesBeforeBuilding = EditorPrefs.GetBool(\"SaveScenesBeforeBuilding\");\n            m_ScriptCompilationDuringPlay = (ScriptChangesDuringPlayOptions)EditorPrefs.GetInt(\"ScriptCompilationDuringPlay\", 0);\n\n            m_DeveloperMode = Unsupported.IsDeveloperMode();\n            m_ShowRepaintDots = EditorGUI.s_ShowRepaintDots.value;\n\n            m_GICacheSettings.m_EnableCustomPath = EditorPrefs.GetBool(\"GICacheEnableCustomPath\");\n            m_GICacheSettings.m_CachePath = EditorPrefs.GetString(\"GICacheFolder\");\n            m_GICacheSettings.m_MaximumSize = EditorPrefs.GetInt(\"GICacheMaximumSizeGB\", 10);\n            m_GICacheSettings.m_CompressionLevel = EditorPrefs.GetInt(\"GICacheCompressionLevel\");\n\n            m_ScriptDebugInfoEnabled = EditorPrefs.GetBool(\"ScriptDebugInfoEnabled\", false);\n            m_EnableEditorLocalization = EditorPrefs.GetBool(\"Editor.kEnableEditorLocalization\", true);\n            m_SelectedLanguage = EditorPrefs.GetString(\"Editor.kEditorLocale\", LocalizationDatabase.GetDefaultEditorLanguage().ToString());\n            m_EnableCompilerMessagesLocalization = EditorPrefs.GetBool(\"Editor.kEnableCompilerMessagesLocalization\", false);\n            m_EditorTextRenderingMode = (EditorTextRenderingMode)EditorPrefs.GetInt(\"EditorTextRenderingMode\", (int)EditorTextRenderingMode.SDF);\n            m_EditorTextSharpness = EditorPrefs.GetFloat($\"EditorTextSharpness_{EditorResources.GetFont(FontDef.Style.Normal).name}\", 0.0f);\n            EditorTextSettings.SetCurrentEditorSharpness(m_EditorTextSharpness);\n\n            m_AllowAlphaNumericHierarchy = EditorPrefs.GetBool(\"AllowAlphaNumericHierarchy\", false);\n            m_DefaultPrefabModeFromHierarchy = GetDefaultPrefabModeForHierarchy();\n            m_ProgressDialogDelay = EditorPrefs.GetFloat(\"EditorBusyProgressDialogDelay\", 3.0f);\n\n            m_CreatePlacementMode = GOCreationCommands.s_PlacementMode;\n            var create3DObjectsAtOrigin = EditorPrefs.GetBool(\"Create3DObject.PlaceAtWorldOrigin\", false);\n            if (create3DObjectsAtOrigin && !EditorPrefs.HasKey(\"Create3DObject.PlacementMode\"))\n            {\n                // Parse old preference to try and respect old pref\n                GOCreationCommands.s_PlacementMode = m_CreatePlacementMode = GOCreationCommands.PlacementMode.WorldOrigin;\n            }\n\n            m_GpuDevice = EditorPrefs.GetString(\"GpuDeviceName\");\n\n            m_EnableConstrainProportionsScalingForNewObjects = EditorPrefs.GetBool(\"EnableConstrainProportionsTransformScale\", false);\n            AnnotationUtility.useInspectorExpandedState = EditorPrefs.GetBool(\"UseInspectorExpandedState\", false);\n\n            if (EditorPrefs.HasKey(kContentScalePrefKey))\n            {\n                m_ContentScalePercentValue = EditorPrefs.GetInt(kContentScalePrefKey, CurrentEditorScalingValue);\n                m_ContentScaleChangedThisSession = m_ContentScalePercentValue != CurrentEditorScalingValue;\n            }\n            else\n            {\n                m_ContentScalePercentValue  = CurrentEditorScalingValue;\n                m_ContentScaleChangedThisSession = false;\n            }\n\n            if (EditorPrefs.HasKey(kWindowsTaskbarPrefKey))\n            {\n                m_TaskbarBehaviorValue = EditorPrefs.GetBool(kWindowsTaskbarPrefKey, false);\n            }\n\n            foreach (IPreferenceWindowExtension extension in prefWinExtensions)\n            {\n                extension.ReadPreferences();\n            }\n\n            m_GraphSnapping = EditorPrefs.GetBool(\"GraphSnapping\", true);\n            m_EnableExtendedLogging = EditorPrefs.GetBool(\"EnableExtendedLogging\", false);\n        }\n\n        internal static void ReloadCustomDiffToolData()\n        {\n            m_CustomDiffToolPath = EditorPrefs.GetString(\"customDiffToolPath\", m_CustomDiffToolPath);\n            m_CustomDiffToolArguments[0] = EditorPrefs.GetString(\"twoWayDiffArguments\", m_CustomDiffToolArguments[0]);\n            m_CustomDiffToolArguments[1] = EditorPrefs.GetString(\"threeWayDiffArguments\", m_CustomDiffToolArguments[1]);\n            m_CustomDiffToolArguments[2] = EditorPrefs.GetString(\"mergeArguments\", m_CustomDiffToolArguments[2]);\n            InternalEditorUtility.SetCustomDiffToolData(m_CustomDiffToolPath, m_CustomDiffToolArguments[0], m_CustomDiffToolArguments[1], m_CustomDiffToolArguments[2]);\n        }\n\n        internal static void ForceEnableCustomTool()\n        {\n            // If diff tools are not initialized yet, get available ones\n            if (m_DiffTools == null)\n                m_DiffTools = InternalEditorUtility.GetAvailableDiffTools();\n\n            if (m_DiffTools == null || m_DiffTools.Length == 0)\n                return;\n\n            m_DiffToolIndex = m_DiffTools.Length - 1;\n            EditorPrefs.SetString(\"kDiffsDefaultApp\", m_DiffTools[m_DiffToolIndex]);\n\n            if (EditorWindow.HasOpenInstances<PreferenceSettingsWindow>())\n                EditorWindow.GetWindow<PreferenceSettingsWindow>().Repaint();\n        }\n\n        class AppsListUserData\n        {\n            public AppsListUserData(string[] paths, RefString str, Action onChanged)\n            {\n                this.paths = paths;\n                this.str = str;\n                this.onChanged = onChanged;\n            }\n\n            public string[] paths;\n            public RefString str;\n            public Action onChanged;\n        }\n\n        void AppsListClickRuntimePlatformExtension(object userData, string[] options, int selected)\n        {\n            AppsListUserData ud = (AppsListUserData)userData;\n            if (options[selected] == L10n.Tr(\"Browse...\"))\n            {\n                string path = EditorUtility.OpenFilePanel(\"Browse for application\", \"\", InternalEditorUtility.GetApplicationExtensionForRuntimePlatform(Application.platform));\n                if (path.Length != 0)\n                {\n                    // browsed to new application\n                    ud.str.str = path;\n                    if (ud.onChanged != null)\n                        ud.onChanged();\n                }\n            }\n            else\n            {\n                // value comes from the list\n                ud.str.str = ud.paths[selected];\n                if (ud.onChanged != null)\n                    ud.onChanged();\n            }\n\n            WritePreferences();\n            ReadPreferences();\n        }\n\n        void AppsListClickNoRuntimePlatformExtension(object userData, string[] options, int selected)\n        {\n            AppsListUserData ud = (AppsListUserData)userData;\n            if (options[selected] == L10n.Tr(\"Browse...\"))\n            {\n                string path = EditorUtility.OpenFilePanel(\"Browse for application\", \"\", \"\");\n                if (path.Length != 0)\n                {\n                    // browsed to new application\n                    ud.str.str = path;\n                    if (ud.onChanged != null)\n                        ud.onChanged();\n                }\n            }\n            else\n            {\n                // value comes from the list\n                ud.str.str = ud.paths[selected];\n                if (ud.onChanged != null)\n                    ud.onChanged();\n            }\n\n            WritePreferences();\n            ReadPreferences();\n        }\n\n        private void FilePopup(GUIContent label, string selectedString, ref string[] names, ref string[] paths, RefString outString, string defaultString, Action onChanged)\n        {\n            FilePopup(label, selectedString, ref names, ref paths, outString, defaultString, onChanged, AppsListClickRuntimePlatformExtension);\n        }\n\n        private void FilePopup(GUIContent label, string selectedString, ref string[] names, ref string[] paths, RefString outString, string defaultString, Action onChanged, EditorUtility.SelectMenuItemFunction ApplicationsListOnClick)\n        {\n            GUIStyle style = EditorStyles.popup;\n            GUILayout.BeginHorizontal();\n            EditorGUILayout.PrefixLabel(label, style);\n\n            int[] selected = new int[0];\n            if (paths.Contains(selectedString))\n                selected = new[] { Array.IndexOf(paths, selectedString) };\n            GUIContent text = new GUIContent(selected.Length == 0 ? defaultString : names[selected[0]]);\n            Rect r = GUILayoutUtility.GetRect(GUIContent.none, style);\n            AppsListUserData ud = new AppsListUserData(paths, outString, onChanged);\n            if (EditorGUI.DropdownButton(r, text, FocusType.Passive, style))\n            {\n                if (names[names.Length - 1] != Styles.browse.text)\n                {\n                    ArrayUtility.Add(ref names, Styles.browse.text);\n                }\n                EditorUtility.DisplayCustomMenu(r, names, selected, ApplicationsListOnClick, ud, false);\n            }\n            GUILayout.EndHorizontal();\n        }\n\n        private string[] BuildAppPathList(string userAppPath, string recentAppsKey, string stringForInternalEditor)\n        {\n            // built-in (internal) is always the first\n            string[] apps = new string[1];\n            apps[0] = stringForInternalEditor;\n\n            // current user setting\n            if (!String.IsNullOrEmpty(userAppPath) && Array.IndexOf(apps, userAppPath) == -1)\n                ArrayUtility.Add(ref apps, userAppPath);\n\n            // add any recently used apps\n            for (int i = 0; i < kRecentAppsCount; ++i)\n            {\n                string path = EditorPrefs.GetString(recentAppsKey + i);\n                if (!File.Exists(path))\n                {\n                    path = \"\";\n                    EditorPrefs.SetString(recentAppsKey + i, path);\n                }\n\n                if (path.Length != 0 && Array.IndexOf(apps, path) == -1)\n                    ArrayUtility.Add(ref apps, path);\n            }\n\n            return apps;\n        }\n\n        private string[] BuildFriendlyAppNameList(string[] appPathList, Dictionary<string, string> appPathToName, string defaultBuiltIn)\n        {\n            var list = new List<string>();\n            for (int i = 0; i < appPathList.Length; ++i)\n            {\n                var appPath = appPathList[i];\n\n                if (appPath == CodeEditor.SystemDefaultPath)     // use built-in\n                    list.Add(defaultBuiltIn);\n                else\n                {\n                    if (appPathToName != null && appPathToName.ContainsKey(appPath))\n                        list.Add(appPathToName[appPath]);\n                    else\n                        list.Add(appPath);\n                }\n            }\n\n            return list.ToArray();\n        }\n\n        internal static PrefabStage.Mode GetDefaultPrefabModeForHierarchy()\n        {\n            return (PrefabStage.Mode)EditorPrefs.GetInt(\"DefaultPrefabModeFromHierarchy\", (int)PrefabStage.Mode.InContext);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PresetLibraries/ColorPresetLibrary.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [AssetFileNameExtension(\"colors\")]\n    [ExcludeFromPreset]\n    class ColorPresetLibrary : PresetLibrary\n    {\n        [SerializeField]\n        List<ColorPreset> m_Presets = new List<ColorPreset>();\n        Texture2D m_ColorSwatch;\n        Texture2D m_ColorSwatchTriangular;\n        Texture2D m_MiniColorSwatchTriangular;\n        Texture2D m_CheckerBoard;\n        Texture2D m_Selection;\n        public const int kSwatchSize = 14;\n        public const int kMiniSwatchSize = 8;\n\n        void OnDestroy()\n        {\n            if (m_ColorSwatch != null)\n                DestroyImmediate(m_ColorSwatch);\n\n            if (m_ColorSwatchTriangular != null)\n                DestroyImmediate(m_ColorSwatchTriangular);\n\n            if (m_MiniColorSwatchTriangular != null)\n                DestroyImmediate(m_MiniColorSwatchTriangular);\n\n            if (m_CheckerBoard != null)\n                DestroyImmediate(m_CheckerBoard);\n\n            if (m_Selection != null)\n                DestroyImmediate(m_Selection);\n        }\n\n        public override int Count()\n        {\n            return m_Presets.Count;\n        }\n\n        public override object GetPreset(int index)\n        {\n            return m_Presets[index].color;\n        }\n\n        public override void Add(object presetObject, string presetName)\n        {\n            Color color = (Color)presetObject;\n            m_Presets.Add(new ColorPreset(color, presetName));\n        }\n\n        public override void Replace(int index, object newPresetObject)\n        {\n            Color color = (Color)newPresetObject;\n            m_Presets[index].color = color;\n        }\n\n        public override void Remove(int index)\n        {\n            m_Presets.RemoveAt(index);\n        }\n\n        public override void Move(int index, int destIndex, bool insertAfterDestIndex)\n        {\n            PresetLibraryHelpers.MoveListItem(m_Presets, index, destIndex, insertAfterDestIndex);\n        }\n\n        public override void Draw(Rect rect, int index)\n        {\n            DrawInternal(rect, m_Presets[index].color);\n        }\n\n        public override void Draw(Rect rect, object presetObject)\n        {\n            DrawInternal(rect, (Color)presetObject);\n        }\n\n        public void DrawSelection(Rect rect)\n        {\n            using (new GUI.ColorScope(ColorPicker.SwatchSelectionColor))\n                GUI.DrawTexture(rect, m_Selection);\n        }\n\n        private void Init()\n        {\n            if (m_ColorSwatch == null)\n                m_ColorSwatch = CreateColorSwatchWithBorder(kSwatchSize, kSwatchSize, false);\n\n            if (m_ColorSwatchTriangular == null)\n                m_ColorSwatchTriangular = CreateColorSwatchWithBorder(kSwatchSize, kSwatchSize, true);\n\n            if (m_MiniColorSwatchTriangular == null)\n                m_MiniColorSwatchTriangular = CreateColorSwatchWithBorder(kMiniSwatchSize, kMiniSwatchSize, true);\n\n            if (m_CheckerBoard == null)\n                m_CheckerBoard = GradientEditor.CreateCheckerTexture(2, 2, 3, new Color(0.8f, 0.8f, 0.8f), new Color(0.5f, 0.5f, 0.5f));\n\n            if (m_Selection == null)\n                m_Selection = CreateSelectionTexture(14, 14);\n        }\n\n        private void DrawInternal(Rect rect, Color preset)\n        {\n            Init();\n\n            bool isHDR = preset.maxColorComponent > 1f;\n\n            // Normalize color if HDR to give some color hint (otherwise it likely is just white)\n            if (isHDR)\n                preset = preset.RGBMultiplied(1f / preset.maxColorComponent);\n\n            Color orgColor = GUI.color;\n            if ((int)rect.height == kSwatchSize)\n            {\n                if (preset.a > 0.97f)\n                    RenderSolidSwatch(rect, preset);\n                else\n                    RenderSwatchWithAlpha(rect, preset, m_ColorSwatchTriangular);\n\n                if (isHDR)\n                    GUI.Label(rect, \"h\");\n            }\n            else\n            {\n                // The Add preset button swatch\n                RenderSwatchWithAlpha(rect, preset, m_MiniColorSwatchTriangular);\n            }\n\n            // comparing as Color32 is more robust due to floating point precision issues in Color comparison\n            if (((Color32)ColorPicker.color).Equals((Color32)preset))\n                DrawSelection(rect);\n\n            GUI.color = orgColor;\n        }\n\n        private void RenderSolidSwatch(Rect rect, Color preset)\n        {\n            GUI.color = preset;\n            GUI.DrawTexture(rect, m_ColorSwatch);\n        }\n\n        private void RenderSwatchWithAlpha(Rect rect, Color preset, Texture2D swatchTexture)\n        {\n            Rect r2 = new Rect(rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2);\n\n            // Background checkers\n            GUI.color = Color.white;\n            Rect texCoordsRect = new Rect(0, 0, r2.width / m_CheckerBoard.width, r2.height / m_CheckerBoard.height);\n            GUI.DrawTextureWithTexCoords(r2, m_CheckerBoard, texCoordsRect, false);\n\n            // Alpha color\n            GUI.color = preset;\n            GUI.DrawTexture(rect, EditorGUIUtility.whiteTexture);\n\n            // Solid color in half triangle\n            GUI.color = new Color(preset.r, preset.g, preset.b, 1f);\n            GUI.DrawTexture(rect, swatchTexture);\n        }\n\n        public override string GetName(int index)\n        {\n            return m_Presets[index].name;\n        }\n\n        public override void SetName(int index, string presetName)\n        {\n            m_Presets[index].name = presetName;\n        }\n\n        public void CreateDebugColors()\n        {\n            for (int i = 0; i < 2000; ++i)\n                m_Presets.Add(new ColorPreset(new Color(Random.Range(0.2f, 1f), Random.Range(0.2f, 1f), Random.Range(0.2f, 1f), 1f), \"Preset Color \" + i));\n        }\n\n        internal static Texture2D CreateSelectionTexture(int width, int height)\n        {\n            var selectionTex = new Texture2D(width, height);\n            var colors = new Color[selectionTex.width * selectionTex.height];\n\n            const int borderWidth = 2;\n            for (int i = 0; i < width; i++)\n            {\n                for (int j = 0; j < height; j++)\n                {\n                    var col = Color.clear;\n                    if (i < borderWidth || j < borderWidth ||\n                        i > width - borderWidth - 1 || j > height - borderWidth - 1)\n                    {\n                        col = Color.white;\n                    }\n                    colors[j + i * width] = col;\n                }\n            }\n\n            selectionTex.SetPixels(colors);\n            selectionTex.Apply();\n\n            return selectionTex;\n        }\n\n        internal static Texture2D CreateColorSwatchWithBorder(int width, int height, bool triangular)\n        {\n            Texture2D texture = new Texture2D(width, height, TextureFormat.RGBA32, false);\n            texture.hideFlags = HideFlags.HideAndDontSave;\n            Color[] pixels = new Color[width * height];\n            Color transparent = new Color(1, 1, 1, 0f);\n            if (triangular)\n            {\n                for (int i = 0; i < height; i++)\n                    for (int j = 0; j < width; j++)\n                    {\n                        if (i < width - j)\n                            pixels[j + i * width] = Color.white;\n                        else\n                            pixels[j + i * width] = transparent;\n                    }\n            }\n            else\n            {\n                for (int i = 0; i < height * width; i++)\n                    pixels[i] = Color.white;\n            }\n\n            // first row\n            for (int i = 0; i < width; i++)\n                pixels[i] = Color.gray3;\n\n            // last row\n            for (int i = 0; i < width; i++)\n                pixels[(height - 1) * width + i] = Color.gray3;\n\n            // first col\n            for (int i = 0; i < height; i++)\n                pixels[i * width] = Color.gray3;\n\n            // last col\n            for (int i = 0; i < height; i++)\n                pixels[i * width + width - 1] = Color.gray3;\n\n            texture.SetPixels(pixels);\n            texture.Apply();\n            return texture;\n        }\n\n        [System.Serializable]\n        class ColorPreset\n        {\n            [SerializeField]\n            string m_Name;\n\n            [SerializeField]\n            Color m_Color;\n\n            public ColorPreset(Color preset, string presetName)\n            {\n                color = preset;\n                name = presetName;\n            }\n\n            public ColorPreset(Color preset, Color preset2, string presetName)\n            {\n                color = preset;\n                name = presetName;\n            }\n\n            public Color color\n            {\n                get { return m_Color; }\n                set { m_Color = value; }\n            }\n\n            public string name\n            {\n                get { return m_Name; }\n                set { m_Name = value; }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PresetLibraries/CurvePresetLibrary.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [AssetFileNameExtension(\"curves\", \"curvesNormalized\", \"particleCurves\", \"particleCurvesSigned\", \"particleDoubleCurves\", \"particleDoubleCurvesSigned\")]\n    [ExcludeFromPreset]\n    class CurvePresetLibrary : PresetLibrary\n    {\n        [SerializeField]\n        List<CurvePreset> m_Presets = new List<CurvePreset>();\n\n        public override int Count()\n        {\n            return m_Presets.Count;\n        }\n\n        public override object GetPreset(int index)\n        {\n            return m_Presets[index].curve;\n        }\n\n        public override void Add(object presetObject, string presetName)\n        {\n            AnimationCurve curve = presetObject as AnimationCurve;\n            if (curve == null)\n            {\n                Debug.LogError(\"Wrong type used in CurvePresetLibrary\");\n                return;\n            }\n\n            AnimationCurve copy = new AnimationCurve(curve.keys);\n            copy.preWrapMode = curve.preWrapMode;\n            copy.postWrapMode = curve.postWrapMode;\n            m_Presets.Add(new CurvePreset(copy, presetName));\n        }\n\n        public override void Replace(int index, object newPresetObject)\n        {\n            AnimationCurve curve = newPresetObject as AnimationCurve;\n            if (curve == null)\n            {\n                Debug.LogError(\"Wrong type used in CurvePresetLibrary\");\n                return;\n            }\n            AnimationCurve copy = new AnimationCurve(curve.keys);\n            copy.preWrapMode = curve.preWrapMode;\n            copy.postWrapMode = curve.postWrapMode;\n\n            m_Presets[index].curve = copy;\n        }\n\n        public override void Remove(int index)\n        {\n            m_Presets.RemoveAt(index);\n        }\n\n        public override void Move(int index, int destIndex, bool insertAfterDestIndex)\n        {\n            PresetLibraryHelpers.MoveListItem(m_Presets, index, destIndex, insertAfterDestIndex);\n        }\n\n        public override void Draw(Rect rect, int index)\n        {\n            DrawInternal(rect, m_Presets[index].curve);\n        }\n\n        public override void Draw(Rect rect, object presetObject)\n        {\n            DrawInternal(rect, presetObject as AnimationCurve);\n        }\n\n        private void DrawInternal(Rect rect, AnimationCurve animCurve)\n        {\n            if (animCurve == null)\n                return;\n            EditorGUIUtility.DrawCurveSwatch(rect, animCurve, null, new Color(0.8f, 0.8f, 0.8f, 1.0f), EditorGUI.kCurveBGColor);\n        }\n\n        public override string GetName(int index)\n        {\n            return m_Presets[index].name;\n        }\n\n        public override void SetName(int index, string presetName)\n        {\n            m_Presets[index].name = presetName;\n        }\n\n        [System.Serializable]\n        class CurvePreset\n        {\n            [SerializeField]\n            string m_Name;\n\n            [SerializeField]\n            AnimationCurve m_Curve;\n\n            public CurvePreset(AnimationCurve preset, string presetName)\n            {\n                curve = preset;\n                name = presetName;\n            }\n\n            public CurvePreset(AnimationCurve preset, AnimationCurve preset2, string presetName)\n            {\n                curve = preset;\n                name = presetName;\n            }\n\n            public AnimationCurve curve\n            {\n                get { return m_Curve; }\n                set { m_Curve = value; }\n            }\n\n            public string name\n            {\n                get { return m_Name; }\n                set { m_Name = value; }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PresetLibraries/CurvePresetsContentsForPopupWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal enum CurveLibraryType\n    {\n        Unbounded,\n        NormalizedZeroToOne\n    }\n\n\n    internal class CurvePresetsContentsForPopupWindow : PopupWindowContent\n    {\n        PresetLibraryEditor<CurvePresetLibrary> m_CurveLibraryEditor;\n        PresetLibraryEditorState m_CurveLibraryEditorState;\n        AnimationCurve m_Curve;\n        CurveLibraryType m_CurveLibraryType;\n        bool m_WantsToClose = false;\n        System.Action<AnimationCurve> m_PresetSelectedCallback;\n\n        public AnimationCurve curveToSaveAsPreset {get {return m_Curve; } set {m_Curve = value; }}\n\n        public CurvePresetsContentsForPopupWindow(AnimationCurve animCurve, CurveLibraryType curveLibraryType, System.Action<AnimationCurve> presetSelectedCallback)\n        {\n            m_CurveLibraryType = curveLibraryType;\n            m_Curve = animCurve;\n            m_PresetSelectedCallback = presetSelectedCallback;\n        }\n\n        public static string GetBasePrefText(CurveLibraryType curveLibraryType)\n        {\n            return GetExtension(curveLibraryType);\n        }\n\n        public string currentPresetLibrary\n        {\n            get\n            {\n                InitIfNeeded();\n                return m_CurveLibraryEditor.currentLibraryWithoutExtension;\n            }\n            set\n            {\n                InitIfNeeded();\n                m_CurveLibraryEditor.currentLibraryWithoutExtension = value;\n            }\n        }\n\n        static string GetExtension(CurveLibraryType curveLibraryType)\n        {\n            switch (curveLibraryType)\n            {\n                case CurveLibraryType.NormalizedZeroToOne: return PresetLibraryLocations.GetCurveLibraryExtension(true);\n                case CurveLibraryType.Unbounded: return PresetLibraryLocations.GetCurveLibraryExtension(false);\n                default:\n                    Debug.LogError(\"Enum not handled!\");\n                    return \"curves\";\n            }\n        }\n\n        public override void OnClose()\n        {\n            m_CurveLibraryEditorState.TransferEditorPrefsState(false);\n        }\n\n        public PresetLibraryEditor<CurvePresetLibrary> GetPresetLibraryEditor()\n        {\n            return m_CurveLibraryEditor;\n        }\n\n        public void InitIfNeeded()\n        {\n            if (m_CurveLibraryEditorState == null)\n            {\n                m_CurveLibraryEditorState = new PresetLibraryEditorState(GetBasePrefText(m_CurveLibraryType));\n                m_CurveLibraryEditorState.TransferEditorPrefsState(true);\n            }\n\n            if (m_CurveLibraryEditor == null)\n            {\n                var saveLoadHelper = new ScriptableObjectSaveLoadHelper<CurvePresetLibrary>(GetExtension(m_CurveLibraryType), SaveType.Text);\n                m_CurveLibraryEditor = new PresetLibraryEditor<CurvePresetLibrary>(saveLoadHelper, m_CurveLibraryEditorState, ItemClickedCallback);\n                m_CurveLibraryEditor.addDefaultPresets += AddDefaultPresetsToLibrary;\n                m_CurveLibraryEditor.presetsWasReordered += OnPresetsWasReordered;\n                m_CurveLibraryEditor.previewAspect = 4f;\n                m_CurveLibraryEditor.minMaxPreviewHeight = new Vector2(24f, 24f);\n                m_CurveLibraryEditor.showHeader = true;\n            }\n        }\n\n        void OnPresetsWasReordered()\n        {\n            InternalEditorUtility.RepaintAllViews();\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            InitIfNeeded();\n\n            m_CurveLibraryEditor.OnGUI(rect, m_Curve);\n\n            if (m_WantsToClose)\n                editorWindow.Close();\n        }\n\n        void ItemClickedCallback(int clickCount, object presetObject)\n        {\n            AnimationCurve curve = presetObject as AnimationCurve;\n            if (curve == null)\n                Debug.LogError(\"Incorrect object passed \" + presetObject);\n\n            m_PresetSelectedCallback(curve);\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            return new Vector2(240, 330);\n        }\n\n        void AddDefaultPresetsToLibrary(PresetLibrary presetLibrary)\n        {\n            CurvePresetLibrary curveDefaultLib = presetLibrary as CurvePresetLibrary;\n            if (curveDefaultLib == null)\n            {\n                Debug.Log(\"Incorrect preset library, should be a CurvePresetLibrary but was a \" + presetLibrary.GetType());\n                return;\n            }\n\n            List<AnimationCurve> defaults = new List<AnimationCurve>();\n            defaults.Add(new AnimationCurve(CurveEditorWindow.GetConstantKeys(1f)));\n            defaults.Add(new AnimationCurve(CurveEditorWindow.GetLinearKeys()));\n            defaults.Add(new AnimationCurve(CurveEditorWindow.GetEaseInKeys()));\n            defaults.Add(new AnimationCurve(CurveEditorWindow.GetEaseOutKeys()));\n            defaults.Add(new AnimationCurve(CurveEditorWindow.GetEaseInOutKeys()));\n\n            foreach (AnimationCurve preset in defaults)\n                curveDefaultLib.Add(preset, \"\");\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PresetLibraries/DoubleCurvePresetLibrary.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    class DoubleCurve\n    {\n        [SerializeField]\n        AnimationCurve m_MinCurve;\n\n        [SerializeField]\n        AnimationCurve m_MaxCurve;\n\n        [SerializeField]\n        bool m_SignedRange;\n\n\n        public DoubleCurve(AnimationCurve minCurve, AnimationCurve maxCurve, bool signedRange)\n        {\n            // Ensure not to hold references to other curves\n            AnimationCurve copy;\n            if (minCurve != null)\n            {\n                copy = new AnimationCurve(minCurve.keys);\n                m_MinCurve = copy;\n            }\n\n            if (maxCurve != null)\n            {\n                copy = new AnimationCurve(maxCurve.keys);\n                m_MaxCurve = copy;\n            }\n            else\n            {\n                Debug.LogError(\"Ensure that maxCurve is not null when creating a double curve. The minCurve can be null for single curves\");\n            }\n\n            m_SignedRange = signedRange;\n        }\n\n        public AnimationCurve minCurve\n        {\n            get { return m_MinCurve; }\n            set { m_MinCurve = value; }\n        }\n\n        public AnimationCurve maxCurve\n        {\n            get { return m_MaxCurve; }\n            set { m_MaxCurve = value; }\n        }\n\n        public bool signedRange\n        {\n            get { return m_SignedRange; }\n            set { m_SignedRange = value; }\n        }\n\n        public bool IsSingleCurve()\n        {\n            return minCurve == null || minCurve.length == 0;\n        }\n    }\n\n    [ExcludeFromPreset]\n    class DoubleCurvePresetLibrary : PresetLibrary\n    {\n        [SerializeField]\n        List<DoubleCurvePreset> m_Presets = new List<DoubleCurvePreset>();\n\n        readonly Rect kUnsignedRange = new Rect(0, 0, 1, 1); // Vertical range 0...1\n        readonly Rect kSignedRange = new Rect(0, -1, 1, 2); // Vertical range -1...1\n        readonly Rect kDefaultRange = new Rect(0, 0, -1, -1); // Default range triggers a range to be calculated.\n\n        bool m_UseRanges = true;\n\n        public bool useRanges\n        {\n            get { return m_UseRanges; }\n            set { m_UseRanges = value; }\n        }\n\n        public override int Count()\n        {\n            return m_Presets.Count;\n        }\n\n        public override object GetPreset(int index)\n        {\n            return m_Presets[index].doubleCurve;\n        }\n\n        public override void Add(object presetObject, string presetName)\n        {\n            DoubleCurve doubleCurve = presetObject as DoubleCurve;\n            if (doubleCurve == null)\n            {\n                Debug.LogError(\"Wrong type used in DoubleCurvePresetLibrary: Should be a DoubleCurve\");\n                return;\n            }\n            m_Presets.Add(new DoubleCurvePreset(doubleCurve, presetName));\n        }\n\n        public override void Replace(int index, object newPresetObject)\n        {\n            DoubleCurve doubleCurve = newPresetObject as DoubleCurve;\n            if (doubleCurve == null)\n            {\n                Debug.LogError(\"Wrong type used in DoubleCurvePresetLibrary\");\n                return;\n            }\n            m_Presets[index].doubleCurve = doubleCurve;\n        }\n\n        public override void Remove(int index)\n        {\n            m_Presets.RemoveAt(index);\n        }\n\n        public override void Move(int index, int destIndex, bool insertAfterDestIndex)\n        {\n            PresetLibraryHelpers.MoveListItem(m_Presets, index, destIndex, insertAfterDestIndex);\n        }\n\n        public override void Draw(Rect rect, int index)\n        {\n            DrawInternal(rect, m_Presets[index].doubleCurve);\n        }\n\n        public override void Draw(Rect rect, object presetObject)\n        {\n            DrawInternal(rect, presetObject as DoubleCurve);\n        }\n\n        private void DrawInternal(Rect rect, DoubleCurve doubleCurve)\n        {\n            if (doubleCurve == null)\n            {\n                Debug.Log(\"DoubleCurve is null\");\n                return;\n            }\n\n            if (m_UseRanges)\n                EditorGUIUtility.DrawRegionSwatch(rect, doubleCurve.maxCurve, doubleCurve.minCurve, new Color(0.8f, 0.8f, 0.8f, 1.0f), EditorGUI.kCurveBGColor, doubleCurve.signedRange ? kSignedRange : kUnsignedRange);\n            else\n                EditorGUIUtility.DrawRegionSwatch(rect, doubleCurve.maxCurve, doubleCurve.minCurve, new Color(0.8f, 0.8f, 0.8f, 1.0f), EditorGUI.kCurveBGColor, kDefaultRange);\n        }\n\n        public override string GetName(int index)\n        {\n            return m_Presets[index].name;\n        }\n\n        public override void SetName(int index, string presetName)\n        {\n            m_Presets[index].name = presetName;\n        }\n\n        [System.Serializable]\n        class DoubleCurvePreset\n        {\n            [SerializeField]\n            string m_Name;\n\n            [SerializeField]\n            DoubleCurve m_DoubleCurve;\n\n            public DoubleCurvePreset(DoubleCurve doubleCurvePreset, string presetName)\n            {\n                doubleCurve = doubleCurvePreset;\n                name = presetName;\n            }\n\n            public DoubleCurve doubleCurve\n            {\n                get { return m_DoubleCurve; }\n                set { m_DoubleCurve = value; }\n            }\n\n            public string name\n            {\n                get { return m_Name; }\n                set { m_Name = value; }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PresetLibraries/DoubleCurvePresetsContentsForPopupWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class DoubleCurvePresetsContentsForPopupWindow : PopupWindowContent\n    {\n        PresetLibraryEditor<DoubleCurvePresetLibrary> m_CurveLibraryEditor;\n        PresetLibraryEditorState m_CurveLibraryEditorState;\n        DoubleCurve m_DoubleCurve;\n        bool m_WantsToClose = false;\n\n        public DoubleCurve doubleCurveToSave\n        {\n            get {return m_DoubleCurve; }\n            set {m_DoubleCurve = value; }\n        }\n\n        System.Action<DoubleCurve> m_PresetSelectedCallback;\n\n        public DoubleCurvePresetsContentsForPopupWindow(DoubleCurve doubleCurveToSave, System.Action<DoubleCurve> presetSelectedCallback)\n        {\n            m_DoubleCurve = doubleCurveToSave;\n            m_PresetSelectedCallback = presetSelectedCallback;\n        }\n\n        public override void OnClose()\n        {\n            m_CurveLibraryEditorState.TransferEditorPrefsState(false);\n        }\n\n        public PresetLibraryEditor<DoubleCurvePresetLibrary> GetPresetLibraryEditor()\n        {\n            return m_CurveLibraryEditor;\n        }\n\n        bool IsSingleCurve(DoubleCurve doubleCurve)\n        {\n            return doubleCurve.minCurve == null || doubleCurve.minCurve.length == 0;\n        }\n\n        string GetEditorPrefBaseName()\n        {\n            return PresetLibraryLocations.GetParticleCurveLibraryExtension(m_DoubleCurve.IsSingleCurve(), m_DoubleCurve.signedRange);\n        }\n\n        public void InitIfNeeded()\n        {\n            if (m_CurveLibraryEditorState == null)\n            {\n                m_CurveLibraryEditorState = new PresetLibraryEditorState(GetEditorPrefBaseName());\n                m_CurveLibraryEditorState.TransferEditorPrefsState(true);\n            }\n\n            if (m_CurveLibraryEditor == null)\n            {\n                var extension = PresetLibraryLocations.GetParticleCurveLibraryExtension(m_DoubleCurve.IsSingleCurve(), m_DoubleCurve.signedRange);\n                var saveLoadHelper = new ScriptableObjectSaveLoadHelper<DoubleCurvePresetLibrary>(extension, SaveType.Text);\n                m_CurveLibraryEditor = new PresetLibraryEditor<DoubleCurvePresetLibrary>(saveLoadHelper, m_CurveLibraryEditorState, ItemClickedCallback);\n                m_CurveLibraryEditor.addDefaultPresets += AddDefaultPresetsToLibrary;\n                m_CurveLibraryEditor.presetsWasReordered = PresetsWasReordered;\n                m_CurveLibraryEditor.previewAspect = 4f;\n                m_CurveLibraryEditor.minMaxPreviewHeight = new Vector2(24f, 24f);\n                m_CurveLibraryEditor.showHeader = true;\n            }\n        }\n\n        void PresetsWasReordered()\n        {\n            InspectorWindow.RepaintAllInspectors();\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            InitIfNeeded();\n\n            m_CurveLibraryEditor.OnGUI(rect, m_DoubleCurve);\n\n            if (m_WantsToClose)\n                editorWindow.Close();\n        }\n\n        void ItemClickedCallback(int clickCount, object presetObject)\n        {\n            DoubleCurve doubleCurve = presetObject as DoubleCurve;\n            if (doubleCurve == null)\n                Debug.LogError(\"Incorrect object passed \" + presetObject);\n\n            m_PresetSelectedCallback(doubleCurve);\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            return new Vector2(240, 330);\n        }\n\n        void AddDefaultPresetsToLibrary(PresetLibrary presetLibrary)\n        {\n            DoubleCurvePresetLibrary doubleCurveDefaultLib = presetLibrary as DoubleCurvePresetLibrary;\n            if (doubleCurveDefaultLib == null)\n            {\n                Debug.Log(\"Incorrect preset library, should be a DoubleCurvePresetLibrary but was a \" + presetLibrary.GetType());\n                return;\n            }\n\n            bool signedRange = m_DoubleCurve.signedRange;\n            List<DoubleCurve> defaults = new List<DoubleCurve>();\n            if (IsSingleCurve(m_DoubleCurve))\n            {\n                defaults = GetUnsignedSingleCurveDefaults(signedRange);\n            }\n            else\n            {\n                if (signedRange)\n                {\n                    defaults = GetSignedDoubleCurveDefaults();\n                }\n                else\n                {\n                    defaults = GetUnsignedDoubleCurveDefaults();\n                }\n            }\n\n            foreach (DoubleCurve preset in defaults)\n            {\n                doubleCurveDefaultLib.Add(preset, \"\");\n            }\n        }\n\n        static List<DoubleCurve> GetUnsignedSingleCurveDefaults(bool signedRange)\n        {\n            List<DoubleCurve> defaults = new List<DoubleCurve>();\n            defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetConstantKeys(1f)), signedRange));\n            defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetLinearKeys()), signedRange));\n            defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetLinearMirrorKeys()), signedRange));\n            defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetEaseInKeys()), signedRange));\n            defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetEaseInMirrorKeys()), signedRange));\n            defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetEaseOutKeys()), signedRange));\n            defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetEaseOutMirrorKeys()), signedRange));\n            defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetEaseInOutKeys()), signedRange));\n            defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetEaseInOutMirrorKeys()), signedRange));\n            return defaults;\n        }\n\n        static List<DoubleCurve> GetUnsignedDoubleCurveDefaults()\n        {\n            List<DoubleCurve> defaults = new List<DoubleCurve>();\n            defaults.Add(new DoubleCurve(new AnimationCurve(CurveEditorWindow.GetConstantKeys(0f)), new AnimationCurve(CurveEditorWindow.GetConstantKeys(1f)), false));\n            return defaults;\n        }\n\n        static List<DoubleCurve> GetSignedDoubleCurveDefaults()\n        {\n            List<DoubleCurve> defaults = new List<DoubleCurve>();\n            defaults.Add(new DoubleCurve(new AnimationCurve(CurveEditorWindow.GetConstantKeys(-1f)), new AnimationCurve(CurveEditorWindow.GetConstantKeys(1f)), true));\n            return defaults;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PresetLibraries/GradientPresetLibrary.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [AssetFileNameExtension(\"gradients\")]\n    [ExcludeFromPreset]\n    class GradientPresetLibrary : PresetLibrary\n    {\n        [SerializeField]\n        List<GradientPreset> m_Presets = new List<GradientPreset>();\n\n        public override int Count()\n        {\n            return m_Presets.Count;\n        }\n\n        public override object GetPreset(int index)\n        {\n            return m_Presets[index].gradient;\n        }\n\n        public override void Add(object presetObject, string presetName)\n        {\n            Gradient gradient = presetObject as Gradient;\n            if (gradient == null)\n            {\n                Debug.LogError(\"Wrong type used in GradientPresetLibrary\");\n                return;\n            }\n\n            Gradient copy = new Gradient();\n            copy.alphaKeys = gradient.alphaKeys;\n            copy.colorKeys = gradient.colorKeys;\n            copy.mode = gradient.mode;\n            m_Presets.Add(new GradientPreset(copy, presetName));\n        }\n\n        public override void Replace(int index, object newPresetObject)\n        {\n            Gradient gradient = newPresetObject as Gradient;\n            if (gradient == null)\n            {\n                Debug.LogError(\"Wrong type used in GradientPresetLibrary\");\n                return;\n            }\n\n            Gradient copy = new Gradient();\n            copy.alphaKeys = gradient.alphaKeys;\n            copy.colorKeys = gradient.colorKeys;\n            copy.mode = gradient.mode;\n            m_Presets[index].gradient = copy;\n        }\n\n        public override void Remove(int index)\n        {\n            m_Presets.RemoveAt(index);\n        }\n\n        public override void Move(int index, int destIndex, bool insertAfterDestIndex)\n        {\n            PresetLibraryHelpers.MoveListItem(m_Presets, index, destIndex, insertAfterDestIndex);\n        }\n\n        public override void Draw(Rect rect, int index)\n        {\n            DrawInternal(rect, m_Presets[index].gradient, ColorSpace.Gamma);\n        }\n\n        public override void Draw(Rect rect, object presetObject)\n        {\n            DrawInternal(rect, presetObject as Gradient, ColorSpace.Gamma);\n        }\n\n        public void Draw(Rect rect, object presetObject, ColorSpace colorSpace)\n        {\n            DrawInternal(rect, presetObject as Gradient, colorSpace);\n        }\n\n        private void DrawInternal(Rect rect, Gradient gradient, ColorSpace colorSpace)\n        {\n            if (gradient == null)\n                return;\n            GradientEditor.DrawGradientWithBackground(rect, gradient, colorSpace == ColorSpace.Linear);\n        }\n\n        public override string GetName(int index)\n        {\n            return m_Presets[index].name;\n        }\n\n        public override void SetName(int index, string presetName)\n        {\n            m_Presets[index].name = presetName;\n        }\n\n        public void DebugCreateTonsOfPresets()\n        {\n            int count = 150; // well not a ton, but..\n            string autoName = \"Preset_\";\n            for (int i = 0; i < count; ++i)\n            {\n                List<GradientColorKey> cols = new List<GradientColorKey>();\n                int numColors = (int)Random.Range(3, 8);\n                for (int j = 0; j < numColors; ++j)\n                    cols.Add(new GradientColorKey(new Color(Random.value, Random.value, Random.value), Random.value));\n\n                List<GradientAlphaKey> alps = new List<GradientAlphaKey>();\n                int numAlphas = (int)Random.Range(3, 8);\n                for (int j = 0; j < numAlphas; ++j)\n                    alps.Add(new GradientAlphaKey(Random.value, Random.value));\n\n                Gradient g = new Gradient();\n                g.colorKeys = cols.ToArray();\n                g.alphaKeys = alps.ToArray();\n                Add(g, autoName + (i + 1));\n            }\n        }\n\n        [System.Serializable]\n        class GradientPreset\n        {\n            [SerializeField]\n            string m_Name;\n\n            [SerializeField]\n            Gradient m_Gradient;\n\n            public GradientPreset(Gradient preset, string presetName)\n            {\n                gradient = preset;\n                name = presetName;\n            }\n\n            public Gradient gradient\n            {\n                get { return m_Gradient; }\n                set { m_Gradient = value; }\n            }\n\n            public string name\n            {\n                get { return m_Name; }\n                set { m_Name = value; }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PresetLibraries/PopupWindowContentForNewLibrary.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class PopupWindowContentForNewLibrary : PopupWindowContent\n    {\n        string m_NewLibraryName = \"\";\n        int m_SelectedIndexInPopup = 0;\n        string m_ErrorString = null;\n        Rect m_WantedSize;\n\n        Func<string, PresetFileLocation, string> m_CreateLibraryCallback;\n\n        class Texts\n        {\n            public GUIContent header = EditorGUIUtility.TrTextContent(\"Create New Library\");\n            public GUIContent name = EditorGUIUtility.TrTextContent(\"Name\");\n            public GUIContent location = EditorGUIUtility.TrTextContent(\"Location\");\n            public GUIContent[] fileLocations = new[] {EditorGUIUtility.TrTextContent(\"Preferences Folder\"), EditorGUIUtility.TrTextContent(\"Project Folder\")};\n            public PresetFileLocation[] fileLocationOrder = new[] { PresetFileLocation.PreferencesFolder, PresetFileLocation.ProjectFolder }; // must match order of fileLocations above\n        }\n        static Texts s_Texts;\n\n        public PopupWindowContentForNewLibrary(Func<string, PresetFileLocation, string> createLibraryCallback)\n        {\n            m_CreateLibraryCallback = createLibraryCallback;\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            if (s_Texts == null)\n                s_Texts = new Texts();\n\n            KeyboardHandling(editorWindow);\n\n            float labelWidth = 80f;\n\n            Rect size = EditorGUILayout.BeginVertical();\n            if (Event.current.type != EventType.Layout)\n                m_WantedSize = size;\n\n            // Header\n            GUILayout.BeginHorizontal();\n            {\n                GUILayout.Label(s_Texts.header, EditorStyles.boldLabel);\n            } GUILayout.EndHorizontal();\n\n            EditorGUI.BeginChangeCheck();\n            {\n                // Name\n                GUILayout.BeginHorizontal();\n                {\n                    GUILayout.Label(s_Texts.name, GUILayout.Width(labelWidth));\n\n                    EditorGUI.FocusTextInControl(\"NewLibraryName\");\n                    GUI.SetNextControlName(\"NewLibraryName\");\n                    m_NewLibraryName = GUILayout.TextField(m_NewLibraryName);\n                } GUILayout.EndHorizontal();\n\n                // Location\n                GUILayout.BeginHorizontal();\n                {\n                    GUILayout.Label(s_Texts.location, GUILayout.Width(labelWidth));\n                    m_SelectedIndexInPopup = EditorGUILayout.Popup(m_SelectedIndexInPopup, s_Texts.fileLocations);\n                }\n                GUILayout.EndHorizontal();\n            }\n            if (EditorGUI.EndChangeCheck())\n                m_ErrorString = null;\n\n            // Create\n            GUILayout.BeginHorizontal();\n            {\n                if (!string.IsNullOrEmpty(m_ErrorString))\n                {\n                    Color orgColor = GUI.color;\n                    GUI.color = new Color(1, 0.8f, 0.8f);\n                    GUILayout.Label(GUIContent.Temp(m_ErrorString), EditorStyles.helpBox);\n                    GUI.color = orgColor;\n                }\n\n                GUILayout.FlexibleSpace();\n                if (GUILayout.Button(GUIContent.Temp(\"Create\")))\n                {\n                    CreateLibraryAndCloseWindow(editorWindow);\n                }\n            } GUILayout.EndHorizontal();\n\n            GUILayout.Space(15);\n\n            EditorGUILayout.EndVertical();\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            return new Vector2(350, m_WantedSize.height > 0 ? m_WantedSize.height : 90);\n        }\n\n        void KeyboardHandling(EditorWindow editorWindow)\n        {\n            Event evt = Event.current;\n            switch (evt.type)\n            {\n                case EventType.KeyDown:\n                    switch (evt.keyCode)\n                    {\n                        case KeyCode.KeypadEnter:\n                        case KeyCode.Return:\n                            CreateLibraryAndCloseWindow(editorWindow);\n                            break;\n                        case KeyCode.Escape:\n                            editorWindow.Close();\n                            break;\n                    }\n                    break;\n            }\n        }\n\n        void CreateLibraryAndCloseWindow(EditorWindow editorWindow)\n        {\n            PresetFileLocation fileLocation = s_Texts.fileLocationOrder[m_SelectedIndexInPopup];\n            m_ErrorString = m_CreateLibraryCallback(m_NewLibraryName, fileLocation);\n            if (string.IsNullOrEmpty(m_ErrorString))\n                editorWindow.Close();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PresetLibraries/PresetLibrary.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    // Derive and implement interface for your own preset library. See GradientPresetLibrary.cs for example.\n    internal abstract class PresetLibrary : ScriptableObject\n    {\n        public abstract int Count();\n        public abstract object GetPreset(int index);\n        public abstract void Add(object presetObject, string presetName);\n        public abstract void Replace(int index, object newPresetObject);\n        public abstract void Remove(int index);\n        public abstract void Move(int index, int destIndex, bool insertAfterDestIndex);\n        public abstract void Draw(Rect rect, int index);\n        public abstract void Draw(Rect rect, object presetObject);\n        public abstract string GetName(int index);\n        public abstract void SetName(int index, string name);\n    }\n\n\n    internal static class PresetLibraryHelpers\n    {\n        public static void MoveListItem<T>(List<T> list, int index, int destIndex, bool insertAfterDestIndex)\n        {\n            if (index < 0 || destIndex < 0)\n            {\n                Debug.LogError(\"Invalid preset move\");\n                return;\n            }\n\n            if (index == destIndex)\n                return;\n\n            if (destIndex > index)\n                destIndex--;\n            if (insertAfterDestIndex && destIndex < list.Count - 1)\n                destIndex++;\n\n            var item = list[index];\n            list.RemoveAt(index);\n            list.Insert(destIndex, item);\n        }\n    }\n}   // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/PresetLibraries/PresetLibraryEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.IO;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing RenameOverlay = UnityEditor.RenameOverlay<int>;\n\nnamespace UnityEditor\n{\n    // Client code should allocate and ensure its being serialized (e.g as a field in an EditorWindow)\n    [System.Serializable]\n    internal class PresetLibraryEditorState\n    {\n        public enum ItemViewMode { Grid, List }\n\n        [SerializeField]\n        private ItemViewMode m_ItemViewMode;\n        public float m_PreviewHeight = 32f;\n        public Vector2 m_ScrollPosition;\n        public string m_CurrrentLibrary = PresetLibraryLocations.defaultPresetLibraryPath;\n        public int m_HoverIndex = -1;\n        public RenameOverlay m_RenameOverlay = new RenameOverlay();\n        public string m_Prefix;\n\n        static public ItemViewMode GetItemViewMode(string prefix)\n        {\n            return (ItemViewMode)EditorPrefs.GetInt(prefix + \"ViewMode\", (int)ItemViewMode.Grid);\n        }\n\n        public PresetLibraryEditorState(string prefix)\n        {\n            m_Prefix = prefix;\n        }\n\n        public ItemViewMode itemViewMode\n        {\n            get { return m_ItemViewMode; }\n            set\n            {\n                if (m_ItemViewMode != value)\n                {\n                    m_ItemViewMode = value;\n                    InspectorWindow.RepaintAllInspectors(); // if inspector is showing a preset library we want it to follow the state\n                    EditorPrefs.SetInt(m_Prefix + \"ViewMode\", (int)m_ItemViewMode);\n                }\n            }\n        }\n\n        public void TransferEditorPrefsState(bool load)\n        {\n            if (load)\n            {\n                m_ItemViewMode = (ItemViewMode)EditorPrefs.GetInt(m_Prefix + \"ViewMode\", (int)m_ItemViewMode);\n                m_PreviewHeight = EditorPrefs.GetFloat(m_Prefix + \"ItemHeight\", m_PreviewHeight);\n                m_ScrollPosition.y = EditorPrefs.GetFloat(m_Prefix + \"Scroll\", m_ScrollPosition.y);\n                m_CurrrentLibrary = EditorPrefs.GetString(m_Prefix + \"CurrentLib\", m_CurrrentLibrary);\n            }\n            else // save\n            {\n                EditorPrefs.SetInt(m_Prefix + \"ViewMode\", (int)m_ItemViewMode);\n                EditorPrefs.SetFloat(m_Prefix + \"ItemHeight\", m_PreviewHeight);\n                EditorPrefs.SetFloat(m_Prefix + \"Scroll\", m_ScrollPosition.y);\n                EditorPrefs.SetString(m_Prefix + \"CurrentLib\", m_CurrrentLibrary);\n            }\n        }\n    }\n\n\n    internal partial class PresetLibraryEditor<T> where T : PresetLibrary\n    {\n        class Styles\n        {\n            public GUIStyle innerShadowBg = GetStyle(\"InnerShadowBg\");\n            public GUIStyle optionsButton = GetStyle(\"PaneOptions\");\n            public GUIStyle newPresetStyle = new GUIStyle(EditorStyles.boldLabel);\n            public GUIContent plusButtonText = EditorGUIUtility.TrTextContent(\"\", \"Add new preset\");\n            public GUIContent plusButtonTextNotCheckedOut = EditorGUIUtility.TrTextContent(\"\", \"To add presets you need to press the 'Check out' button below\");\n            public GUIContent header = EditorGUIUtility.TrTextContent(\"Presets\");\n            public GUIContent newPreset = EditorGUIUtility.TrTextContent(\"New\");\n\n            public Styles()\n            {\n                newPresetStyle.alignment = TextAnchor.MiddleCenter;\n                newPresetStyle.normal.textColor = Color.white;\n            }\n\n            static GUIStyle GetStyle(string styleName)\n            {\n                return styleName; // Implicit construction of GUIStyle\n            }\n        }\n        static Styles s_Styles;\n\n        class DragState\n        {\n            public int dragUponIndex { get; set; }\n            public int draggingIndex { get; set; }\n            public bool insertAfterIndex { get; set; }\n            public Rect dragUponRect { get; set; }\n            public bool IsDragging() {return draggingIndex != -1; }\n            public DragState() {dragUponIndex = -1; draggingIndex = -1; }\n        }\n        DragState m_DragState = new DragState();\n\n        readonly VerticalGrid m_Grid = new VerticalGrid();\n        readonly PresetLibraryEditorState m_State;\n        readonly ScriptableObjectSaveLoadHelper<T> m_SaveLoadHelper;\n        readonly System.Action<int, object> m_ItemClickedCallback;      // <click count, clicked preset>\n\n        public System.Action<PresetLibrary> addDefaultPresets;\n        public System.Action presetsWasReordered;\n\n        // layout\n        const float kGridLabelHeight = 16f;\n        const float kCheckoutButtonMaxWidth = 100f;\n        const float kCheckoutButtonMargin = 2f;\n        Vector2 m_MinMaxPreviewHeight = new Vector2(14, 64);\n        float m_PreviewAspect = 8f;\n        bool m_ShowAddNewPresetItem = true;\n        bool m_ShowedScrollBarLastFrame = false;\n        bool m_IsOpenForEdit = true;\n        PresetFileLocation m_PresetLibraryFileLocation;\n        public float contentHeight { get; private set; }\n        float topAreaHeight { get { return 20f; } }\n        float versionControlAreaHeight { get { return 20f; } }\n        float gridWidth { get; set; }\n\n        public bool wantsToCreateLibrary { get; set; }\n        public bool showHeader { get; set; }\n        public float settingsMenuRightMargin { get; set; }\n        public bool alwaysShowScrollAreaHorizontalLines {get; set; }\n        public bool useOnePixelOverlappedGrid {get; set; }\n        public RectOffset marginsForList {get; set; }\n        public RectOffset marginsForGrid {get; set; }\n\n        public PresetLibraryEditor(ScriptableObjectSaveLoadHelper<T> helper,\n                                   PresetLibraryEditorState state,\n                                   System.Action<int, object> itemClickedCallback\n        )\n        {\n            m_SaveLoadHelper = helper;\n            m_State = state;\n            m_ItemClickedCallback = itemClickedCallback;\n            settingsMenuRightMargin = 10;\n            useOnePixelOverlappedGrid = false;\n            alwaysShowScrollAreaHorizontalLines = true;\n            marginsForList = new RectOffset(10, 10, 5, 5);\n            marginsForGrid = new RectOffset(5, 5, 5, 5);\n            m_PresetLibraryFileLocation = PresetLibraryLocations.GetFileLocationFromPath(currentLibraryWithoutExtension);\n        }\n\n        public void InitializeGrid(float availableWidth)\n        {\n            T lib = GetCurrentLib();\n            if (lib != null)\n            {\n                if (availableWidth > 0f)\n                    SetupGrid(availableWidth, lib.Count());\n            }\n            else\n                Debug.LogError(\"Could not load preset library \" + currentLibraryWithoutExtension);\n        }\n\n        void Repaint()\n        {\n            // Repaints current view\n            HandleUtility.Repaint();\n        }\n\n        public string currentLibraryWithoutExtension\n        {\n            get\n            {\n                return m_State.m_CurrrentLibrary;\n            }\n            set\n            {\n                m_State.m_CurrrentLibrary = Path.ChangeExtension(value, null); // ensure no extension\n                m_PresetLibraryFileLocation = PresetLibraryLocations.GetFileLocationFromPath(m_State.m_CurrrentLibrary);\n                OnLayoutChanged();\n            }\n        }\n\n        public float previewAspect\n        {\n            get { return m_PreviewAspect; }\n            set { m_PreviewAspect = value; }\n        }\n\n        public Vector2 minMaxPreviewHeight\n        {\n            get { return m_MinMaxPreviewHeight; }\n            set\n            {\n                m_MinMaxPreviewHeight = value;\n                previewHeight = previewHeight; // clamps to min max\n            }\n        }\n\n        public float previewHeight\n        {\n            get { return m_State.m_PreviewHeight; }\n            set\n            {\n                m_State.m_PreviewHeight = Mathf.Clamp(value, minMaxPreviewHeight.x, minMaxPreviewHeight.y);\n            }\n        }\n\n        public PresetLibraryEditorState.ItemViewMode itemViewMode\n        {\n            get { return m_State.itemViewMode; }\n            set\n            {\n                m_State.itemViewMode = value;\n                OnLayoutChanged();\n            }\n        }\n\n        bool drawLabels {get {return m_State.itemViewMode == PresetLibraryEditorState.ItemViewMode.List; }}\n\n        // Returns an error string. If no errors occured then null is returned\n        string CreateNewLibraryCallback(string libraryName, PresetFileLocation fileLocation)\n        {\n            if (libraryName.Contains(\":\"))\n                return \"A filename cannot contain the following character ':'\";\n\n            string defaultPath = PresetLibraryLocations.GetDefaultFilePathForFileLocation(fileLocation);\n\n            if (libraryName.StartsWith(\"\\\\\") || libraryName.StartsWith(\"/\"))\n                libraryName = libraryName.Substring(1);\n\n            string pathWithoutExtension = Path.Combine(defaultPath, libraryName);\n            if (CreateNewLibrary(pathWithoutExtension) != null)\n                currentLibraryWithoutExtension = pathWithoutExtension;\n            return PresetLibraryManager.instance.GetLastError();\n        }\n\n        void OnLayoutChanged()\n        {\n            T lib = GetCurrentLib();\n            if (lib == null || gridWidth <= 0f)\n                return;\n\n            SetupGrid(gridWidth, lib.Count());\n        }\n\n        void SetupGrid(float width, int itemCount)\n        {\n            if (width < 1f)\n            {\n                Debug.LogError(\"Invalid width \" + width + \", \" + Event.current.type);\n                return;\n            }\n\n            if (m_ShowAddNewPresetItem)\n                itemCount++;\n\n            m_Grid.useFixedHorizontalSpacing = useOnePixelOverlappedGrid;\n            m_Grid.fixedHorizontalSpacing = useOnePixelOverlappedGrid ? -1 : 0;\n\n            switch (m_State.itemViewMode)\n            {\n                case PresetLibraryEditorState.ItemViewMode.Grid:\n\n                    m_Grid.fixedWidth = width;\n                    m_Grid.topMargin = marginsForGrid.top;\n                    m_Grid.bottomMargin = marginsForGrid.bottom;\n                    m_Grid.leftMargin = marginsForGrid.left;\n                    m_Grid.rightMargin = marginsForGrid.right;\n                    m_Grid.verticalSpacing = useOnePixelOverlappedGrid ? -1 : 2;\n                    m_Grid.minHorizontalSpacing = 1f;\n                    m_Grid.itemSize = new Vector2(m_State.m_PreviewHeight * m_PreviewAspect, m_State.m_PreviewHeight); // no text\n                    m_Grid.InitNumRowsAndColumns(itemCount, int.MaxValue);\n                    break;\n                case PresetLibraryEditorState.ItemViewMode.List:\n                    m_Grid.fixedWidth = width;\n                    m_Grid.topMargin = marginsForList.top;\n                    m_Grid.bottomMargin = marginsForList.bottom;\n                    m_Grid.leftMargin = marginsForList.left;\n                    m_Grid.rightMargin = marginsForList.right;\n                    m_Grid.verticalSpacing = 2f;\n                    m_Grid.minHorizontalSpacing = 0f;\n                    m_Grid.itemSize = new Vector2(width - m_Grid.leftMargin, m_State.m_PreviewHeight);\n                    m_Grid.InitNumRowsAndColumns(itemCount, int.MaxValue);\n                    break;\n            }\n\n\n            float gridHeight = m_Grid.CalcRect(itemCount - 1, 0f).yMax + m_Grid.bottomMargin;\n            contentHeight = topAreaHeight + gridHeight + (m_IsOpenForEdit ? 0 : versionControlAreaHeight);\n        }\n\n        public void OnGUI(Rect rect, object presetObject)\n        {\n            // If removing this early out grid setup needs to be ignored for layout and used events\n            if (rect.width < 2f)\n                return;\n\n            m_State.m_RenameOverlay.OnEvent();\n\n            T lib = GetCurrentLib();\n\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            Rect topArea = new Rect(rect.x, rect.y, rect.width, topAreaHeight);\n            Rect presetRect = new Rect(rect.x, topArea.yMax, rect.width, rect.height - topAreaHeight);\n\n            TopArea(topArea);\n            ListArea(presetRect, lib, presetObject);\n        }\n\n        void TopArea(Rect rect)\n        {\n            GUI.BeginGroup(rect);\n            {\n                if (showHeader)\n                    GUI.Label(new Rect(10, 0, rect.width - 20, rect.height), s_Styles.header);\n\n                const float optionsButtonWidth = 16f;\n                const float optionsButtonHeight = 16f;\n                Rect buttonRect = new Rect(rect.width - optionsButtonWidth - settingsMenuRightMargin, (rect.height - optionsButtonHeight) * 0.5f, optionsButtonWidth, rect.height);\n                if (Event.current.type == EventType.Repaint)\n                    s_Styles.optionsButton.Draw(buttonRect, false, false, false, false);\n\n                // We want larger click area than the button icon\n                buttonRect.y = 0f;\n                buttonRect.height = rect.height;\n                buttonRect.width = 24f;\n                if (GUI.Button(buttonRect, GUIContent.none, GUIStyle.none))\n                    SettingsMenu.Show(buttonRect, this);\n\n                if (wantsToCreateLibrary)\n                {\n                    wantsToCreateLibrary = false;\n                    PopupWindow.Show(buttonRect, new PopupWindowContentForNewLibrary(CreateNewLibraryCallback));\n                    EditorGUIUtility.ExitGUI();\n                }\n            } GUI.EndGroup();\n        }\n\n        Rect GetDragRect(Rect itemRect)\n        {\n            int extraHorz = Mathf.FloorToInt(m_Grid.horizontalSpacing * 0.5f + 0.5f);\n            int extraVert = Mathf.FloorToInt(m_Grid.verticalSpacing * 0.5f + 0.5f);\n            return new RectOffset(extraHorz, extraHorz, extraVert, extraVert).Add(itemRect);\n        }\n\n        void ClearDragState()\n        {\n            m_DragState.dragUponIndex = -1;\n            m_DragState.draggingIndex = -1;\n        }\n\n        void DrawHoverEffect(Rect itemRect, bool drawAsSelection)\n        {\n            Color orgColor = GUI.color;\n            GUI.color = new Color(0, 0, 0.4f, drawAsSelection ? 0.8f : 0.3f);\n            Rect hoverRect = new RectOffset(3, 3, 3, 3).Add(itemRect);\n            GUI.Label(hoverRect, GUIContent.none, EditorStyles.helpBox);\n            GUI.color = orgColor;\n        }\n\n        private string pathWithExtension\n        {\n            get { return currentLibraryWithoutExtension + \".\" + m_SaveLoadHelper.fileExtensionWithoutDot; }\n        }\n\n        void VersionControlArea(Rect rect)\n        {\n            if (rect.width > kCheckoutButtonMaxWidth)\n                rect = new Rect(rect.xMax - kCheckoutButtonMaxWidth - kCheckoutButtonMargin, rect.y + kCheckoutButtonMargin, kCheckoutButtonMaxWidth, rect.height - kCheckoutButtonMargin * 2);\n\n            if (GUI.Button(rect, \"Check out\", EditorStyles.miniButton))\n                AssetDatabase.MakeEditable(pathWithExtension);\n        }\n\n        void ListArea(Rect rect, PresetLibrary lib, object newPresetObject)\n        {\n            if (lib == null)\n                return;\n\n            Event evt = Event.current;\n\n            if (m_PresetLibraryFileLocation == PresetFileLocation.ProjectFolder && evt.type == EventType.Repaint)\n                m_IsOpenForEdit = AssetDatabase.IsOpenForEdit(pathWithExtension);\n            else if (m_PresetLibraryFileLocation == PresetFileLocation.PreferencesFolder)\n                m_IsOpenForEdit = true;\n\n            if (!m_IsOpenForEdit)\n            {\n                Rect versionControlRect = new Rect(rect.x, rect.yMax - versionControlAreaHeight, rect.width, versionControlAreaHeight);\n                VersionControlArea(versionControlRect);\n                rect.height -= versionControlAreaHeight;\n            }\n\n            // To ensure we setup grid to visible rect we need to run once to check if scrollbar is taking up screen estate.\n            // To optimize the first width is based on the last frame and we therefore most likely will only run once.\n            for (int i = 0; i < 2; i++)\n            {\n                gridWidth = m_ShowedScrollBarLastFrame ? rect.width - 17 : rect.width;\n                SetupGrid(gridWidth, lib.Count());\n                bool isShowingScrollBar = m_Grid.height > rect.height;\n                if (isShowingScrollBar == m_ShowedScrollBarLastFrame)\n                    break;\n                else\n                    m_ShowedScrollBarLastFrame = isShowingScrollBar;\n            }\n\n            // Draw horizontal lines for scrollview content to clip against\n            if ((m_ShowedScrollBarLastFrame || alwaysShowScrollAreaHorizontalLines) && Event.current.type == EventType.Repaint)\n            {\n                Rect scrollEdgeRect = new RectOffset(1, 1, 1, 1).Add(rect);\n                scrollEdgeRect.height = 1;\n                EditorGUI.DrawRect(scrollEdgeRect, new Color(0, 0, 0, 0.3f));\n                scrollEdgeRect.y += rect.height + 1;\n                EditorGUI.DrawRect(scrollEdgeRect, new Color(0, 0, 0, 0.3f));\n            }\n\n            Rect contentRect = new Rect(0, 0, 1, m_Grid.height);\n            m_State.m_ScrollPosition = GUI.BeginScrollView(rect, m_State.m_ScrollPosition, contentRect);\n            {\n                int startIndex, endIndex;\n                float yOffset = 0f;\n                int maxIndex = m_ShowAddNewPresetItem ? lib.Count() : lib.Count() - 1;\n                bool isGridVisible = m_Grid.IsVisibleInScrollView(rect.height, m_State.m_ScrollPosition.y, yOffset, maxIndex, out startIndex, out endIndex);\n                bool drawDragInsertionMarker = false;\n                if (isGridVisible)\n                {\n                    // Handle renaming overlay before item handling because its needs mouse input first to end renaming if clicked outside\n                    if (GetRenameOverlay().IsRenaming() && !GetRenameOverlay().isWaitingForDelay)\n                    {\n                        if (!m_State.m_RenameOverlay.OnGUI())\n                        {\n                            EndRename();\n                            evt.Use();\n                        }\n                        Repaint();\n                    }\n\n                    for (int i = startIndex; i <= endIndex; ++i)\n                    {\n                        int itemControlID = i + 1000000;\n\n                        Rect itemRect = m_Grid.CalcRect(i, yOffset);\n                        Rect previewRect = itemRect;\n                        Rect labelRect = itemRect;\n                        switch (m_State.itemViewMode)\n                        {\n                            case PresetLibraryEditorState.ItemViewMode.List:\n                                previewRect.width = m_State.m_PreviewHeight * m_PreviewAspect;\n                                labelRect.x += previewRect.width + 8f;\n                                labelRect.width -= previewRect.width + 10f;\n                                labelRect.height = kGridLabelHeight;\n                                labelRect.y = itemRect.yMin + (itemRect.height - kGridLabelHeight) * 0.5f;\n                                break;\n\n                            case PresetLibraryEditorState.ItemViewMode.Grid:\n                                // only preview is shown: no label\n                                break;\n                        }\n\n                        // Add new preset button\n                        if (m_ShowAddNewPresetItem && i == lib.Count())\n                        {\n                            CreateNewPresetButton(previewRect, newPresetObject, lib, m_IsOpenForEdit);\n                            continue;\n                        }\n\n                        // Rename overlay\n                        bool isRenamingThisItem = IsRenaming(i);\n                        if (isRenamingThisItem)\n                        {\n                            Rect renameRect = labelRect;\n                            renameRect.y -= 1f; renameRect.x -= 1f; // adjustment to fit perfectly\n                            m_State.m_RenameOverlay.editFieldRect = renameRect;\n                        }\n\n                        // Handle event\n                        switch (evt.type)\n                        {\n                            case EventType.Repaint:\n                                if (m_State.m_HoverIndex == i)\n                                {\n                                    if (itemRect.Contains(evt.mousePosition))\n                                    {\n                                        // TODO: We need a better hover effect so disabling for now...\n                                        //if (!GetRenameOverlay().IsRenaming ())\n                                        //  DrawHoverEffect (itemRect, false);\n                                    }\n                                    else\n                                        m_State.m_HoverIndex = -1;\n                                }\n\n                                if (m_DragState.draggingIndex == i || GUIUtility.hotControl == itemControlID)\n                                    DrawHoverEffect(itemRect, false);\n\n                                DrawPreset(lib, previewRect, lib.GetPreset(i));\n\n                                if (!isRenamingThisItem && drawLabels)\n                                    GUI.Label(labelRect, GUIContent.Temp(lib.GetName(i)));\n\n                                if (m_DragState.dragUponIndex == i && m_DragState.draggingIndex != m_DragState.dragUponIndex)\n                                    drawDragInsertionMarker = true;\n\n                                // We delete presets on alt-click\n                                if (GUIUtility.hotControl == 0 && Event.current.alt && m_IsOpenForEdit)\n                                    EditorGUIUtility.AddCursorRect(itemRect, MouseCursor.ArrowMinus);\n\n                                break;\n                            case EventType.MouseDown:\n                                if (evt.button == 0 && itemRect.Contains(evt.mousePosition))\n                                {\n                                    GUIUtility.hotControl = itemControlID;\n                                    if (evt.clickCount == 1)\n                                    {\n                                        m_ItemClickedCallback(evt.clickCount, lib.GetPreset(i));\n                                        evt.Use();\n                                    }\n                                }\n                                break;\n                            case EventType.MouseDrag:\n                                if (GUIUtility.hotControl == itemControlID && m_IsOpenForEdit)\n                                {\n                                    DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), itemControlID);\n                                    if (delay.CanStartDrag())\n                                    {\n                                        // Start drag\n                                        DragAndDrop.PrepareStartDrag();\n                                        DragAndDrop.SetGenericData(\"DraggingPreset\", i);\n                                        DragAndDrop.StartDrag(\"\");\n                                        m_DragState.draggingIndex = i;\n                                        m_DragState.dragUponIndex = i;\n                                        GUIUtility.hotControl = 0;\n                                    }\n                                    evt.Use();\n                                }\n                                break;\n\n                            case EventType.DragUpdated:\n                            case EventType.DragPerform:\n                            {\n                                Rect dragRect = GetDragRect(itemRect);\n                                if (dragRect.Contains(evt.mousePosition))\n                                {\n                                    m_DragState.dragUponIndex = i;\n                                    m_DragState.dragUponRect = itemRect;\n\n                                    if (m_State.itemViewMode == PresetLibraryEditorState.ItemViewMode.List)\n                                        m_DragState.insertAfterIndex = ((evt.mousePosition.y - dragRect.y) / dragRect.height) > 0.5f;\n                                    else\n                                        m_DragState.insertAfterIndex = ((evt.mousePosition.x - dragRect.x) / dragRect.width) > 0.5f;\n\n                                    bool perform = evt.type == EventType.DragPerform;\n                                    if (perform)\n                                    {\n                                        if (m_DragState.draggingIndex >= 0)\n                                        {\n                                            MovePreset(m_DragState.draggingIndex, m_DragState.dragUponIndex, m_DragState.insertAfterIndex);\n                                            DragAndDrop.AcceptDrag();\n                                        }\n                                        ClearDragState();\n                                    }\n                                    DragAndDrop.visualMode = DragAndDropVisualMode.Move;\n                                    evt.Use();\n                                }\n                            }\n                            break;\n                            case EventType.DragExited:\n                                if (m_DragState.IsDragging())\n                                {\n                                    ClearDragState();\n                                    evt.Use();\n                                }\n                                break;\n\n                            case EventType.MouseUp:\n                                if (GUIUtility.hotControl == itemControlID)\n                                {\n                                    GUIUtility.hotControl = 0;\n                                    if (evt.button == 0 && itemRect.Contains(evt.mousePosition))\n                                    {\n                                        if (Event.current.alt && m_IsOpenForEdit)\n                                        {\n                                            DeletePreset(i);\n                                            evt.Use();\n                                        }\n                                    }\n                                }\n                                break;\n                            case EventType.ContextClick:\n                                if (itemRect.Contains(evt.mousePosition))\n                                {\n                                    PresetContextMenu.Show(m_IsOpenForEdit, i, newPresetObject, this);\n                                    evt.Use();\n                                }\n                                break;\n                            case EventType.MouseMove:\n                                if (itemRect.Contains(evt.mousePosition))\n                                {\n                                    if (m_State.m_HoverIndex != i)\n                                    {\n                                        m_State.m_HoverIndex = i;\n                                        Repaint();\n                                    }\n                                }\n                                else if (m_State.m_HoverIndex == i)\n                                {\n                                    m_State.m_HoverIndex = -1;\n                                    Repaint();\n                                }\n\n                                break;\n                        }\n                    } // end foreach item\n\n                    // Draw above all items\n                    if (drawDragInsertionMarker)\n                        DrawDragInsertionMarker();\n                }\n            } GUI.EndScrollView();\n        }\n\n        void DrawDragInsertionMarker()\n        {\n            if (!m_DragState.IsDragging())\n                return;\n\n            Rect dragRect = GetDragRect(m_DragState.dragUponRect);\n            Rect insertRect;\n            const float inserterThickness = 2f;\n            const float halfInserter = inserterThickness * 0.5f;\n            if (m_State.itemViewMode == PresetLibraryEditorState.ItemViewMode.List)\n            {\n                if (m_DragState.insertAfterIndex)\n                    insertRect = new Rect(dragRect.xMin, dragRect.yMax - halfInserter, dragRect.width, inserterThickness);\n                else\n                    insertRect = new Rect(dragRect.xMin, dragRect.yMin - halfInserter, dragRect.width, inserterThickness);\n            }\n            else // grid\n            {\n                if (m_DragState.insertAfterIndex)\n                    insertRect = new Rect(dragRect.xMax - halfInserter, dragRect.yMin, inserterThickness, dragRect.height);\n                else\n                    insertRect = new Rect(dragRect.xMin - halfInserter, dragRect.yMin, inserterThickness, dragRect.height);\n            }\n            EditorGUI.DrawRect(insertRect, new Color(0.3f, 0.3f, 1.0f));\n        }\n\n        protected virtual void DrawPreset(PresetLibrary lib, Rect rect, object presetObject)\n        {\n            lib.Draw(rect, presetObject);\n        }\n\n        void CreateNewPresetButton(Rect buttonRect, object newPresetObject, PresetLibrary lib, bool isOpenForEdit)\n        {\n            using (new EditorGUI.DisabledScope(!isOpenForEdit))\n            {\n                if (GUI.Button(buttonRect, isOpenForEdit ? s_Styles.plusButtonText : s_Styles.plusButtonTextNotCheckedOut))\n                {\n                    int newIndex = CreateNewPreset(newPresetObject, \"\");\n                    if (drawLabels)\n                        BeginRenaming(\"\", newIndex, 0f);\n                    InspectorWindow.RepaintAllInspectors(); // If inspecting a preset libarary we want to show the new preset there as well\n                }\n\n                if (Event.current.type == EventType.Repaint)\n                {\n                    Rect rect2 = new RectOffset(-3, -3, -3, -3).Add(buttonRect);\n                    DrawPreset(lib, rect2, newPresetObject);\n\n                    if (buttonRect.width > 30)\n                    {\n                        LabelWithOutline(buttonRect, s_Styles.newPreset, new Color(0.1f, 0.1f, 0.1f), s_Styles.newPresetStyle);\n                    }\n                    else\n                    {\n                        if (lib.Count() == 0 && isOpenForEdit)\n                        {\n                            buttonRect.x = buttonRect.xMax + 5f;\n                            buttonRect.width = 200;\n                            buttonRect.height = EditorGUI.kSingleLineHeight;\n                            using (new EditorGUI.DisabledScope(true))\n                            {\n                                GUI.Label(buttonRect, \"Click to add new preset\");\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        static void LabelWithOutline(Rect rect, GUIContent content, Color outlineColor, GUIStyle style)\n        {\n            const int outlineWidth = 1;\n\n            Color orgColor = GUI.color;\n            GUI.color = outlineColor;\n            for (int i = -outlineWidth; i <= outlineWidth; ++i)\n            {\n                for (int j = -outlineWidth; j <= outlineWidth; ++j)\n                {\n                    if (i == 0 && j == 0)\n                        continue;\n\n                    Rect outlineRect = rect;\n                    outlineRect.x += j;\n                    outlineRect.y += i;\n                    GUI.Label(outlineRect, content, style);\n                }\n            }\n            GUI.color = orgColor;\n\n            GUI.Label(rect, content, style);\n        }\n\n        bool IsRenaming(int itemID)\n        {\n            return GetRenameOverlay().IsRenaming() && GetRenameOverlay().userData == itemID && !GetRenameOverlay().isWaitingForDelay;\n        }\n\n        RenameOverlay GetRenameOverlay()\n        {\n            return m_State.m_RenameOverlay;\n        }\n\n        void BeginRenaming(string name, int itemIndex, float delay)\n        {\n            GetRenameOverlay().BeginRename(name, itemIndex, delay);\n        }\n\n        void EndRename()\n        {\n            if (!GetRenameOverlay().userAcceptedRename)\n                return;\n\n            // We are done renaming (user accepted/rejected, we lost focus etc, other grabbed renameOverlay etc.)\n            string name = string.IsNullOrEmpty(GetRenameOverlay().name) ? GetRenameOverlay().originalName : GetRenameOverlay().name;\n            int itemIndex = GetRenameOverlay().userData; // we passed in an instanceID as userData\n\n            T lib = GetCurrentLib();\n            if (itemIndex >= 0 && itemIndex < lib.Count())\n            {\n                lib.SetName(itemIndex, name);\n                SaveCurrentLib();\n            }\n\n            // Ensure cleanup\n            GetRenameOverlay().EndRename(true);\n        }\n\n        public T GetCurrentLib()\n        {\n            T lib = PresetLibraryManager.instance.GetLibrary<T>(m_SaveLoadHelper, currentLibraryWithoutExtension);\n            if (lib == null)\n            {\n                // If current library not found then get the default library (or create the default library if not present)\n                lib = PresetLibraryManager.instance.GetLibrary<T>(m_SaveLoadHelper, PresetLibraryLocations.defaultPresetLibraryPath);\n                if (lib == null)\n                {\n                    lib = CreateNewLibrary(PresetLibraryLocations.defaultPresetLibraryPath);\n                    if (lib != null)\n                    {\n                        // Add default set of presets\n                        if (addDefaultPresets != null)\n                        {\n                            addDefaultPresets(lib);\n                            PresetLibraryManager.instance.SaveLibrary(m_SaveLoadHelper, lib, PresetLibraryLocations.defaultPresetLibraryPath);\n                        }\n                    }\n                    else\n                    {\n                        Debug.LogError(\"Could not create Default preset library \" + PresetLibraryManager.instance.GetLastError());\n                    }\n                }\n\n                currentLibraryWithoutExtension = PresetLibraryLocations.defaultPresetLibraryPath;\n            }\n            return lib;\n        }\n\n        public void UnloadUsedLibraries()\n        {\n            PresetLibraryManager.instance.UnloadAllLibrariesFor(m_SaveLoadHelper);\n        }\n\n        public void DeletePreset(int presetIndex)\n        {\n            T lib = GetCurrentLib();\n            if (lib == null)\n                return;\n\n            if (presetIndex < 0 || presetIndex >= lib.Count())\n            {\n                Debug.LogError(\"DeletePreset: Invalid index: out of bounds\");\n                return;\n            }\n\n            lib.Remove(presetIndex);\n            SaveCurrentLib();\n            if (presetsWasReordered != null)\n                presetsWasReordered();\n\n            OnLayoutChanged();\n        }\n\n        public void ReplacePreset(int presetIndex, object presetObject)\n        {\n            T lib = GetCurrentLib();\n            if (lib == null)\n                return;\n\n            if (presetIndex < 0 || presetIndex >= lib.Count())\n            {\n                Debug.LogError(\"ReplacePreset: Invalid index: out of bounds\");\n                return;\n            }\n\n            lib.Replace(presetIndex, presetObject);\n            SaveCurrentLib();\n            if (presetsWasReordered != null)\n                presetsWasReordered();\n        }\n\n        public void MovePreset(int presetIndex, int destPresetIndex, bool insertAfterDestIndex)\n        {\n            T lib = GetCurrentLib();\n            if (lib == null)\n                return;\n\n            if (presetIndex < 0 || presetIndex >= lib.Count())\n            {\n                Debug.LogError(\"ReplacePreset: Invalid index: out of bounds\");\n                return;\n            }\n\n            lib.Move(presetIndex, destPresetIndex, insertAfterDestIndex);\n            SaveCurrentLib();\n            if (presetsWasReordered != null)\n                presetsWasReordered();\n        }\n\n        // returns index of newly created preset. -1 if no library to add to.\n        public int CreateNewPreset(object presetObject, string presetName)\n        {\n            T lib = GetCurrentLib();\n            if (lib == null)\n            {\n                Debug.Log(\"No current library selected!\");\n                return -1;\n            }\n\n            lib.Add(presetObject, presetName);\n            SaveCurrentLib();\n            if (presetsWasReordered != null)\n                presetsWasReordered();\n\n            Repaint();\n            OnLayoutChanged();\n            return lib.Count() - 1;\n        }\n\n        public void SaveCurrentLib()\n        {\n            T lib = GetCurrentLib();\n            if (lib == null)\n            {\n                Debug.Log(\"No current library selected!\");\n                return;\n            }\n            PresetLibraryManager.instance.SaveLibrary(m_SaveLoadHelper, lib, currentLibraryWithoutExtension);\n            InternalEditorUtility.RepaintAllViews();\n        }\n\n        public T CreateNewLibrary(string presetLibraryPathWithoutExtension)\n        {\n            T newLib = PresetLibraryManager.instance.CreateLibrary<T>(m_SaveLoadHelper, presetLibraryPathWithoutExtension);\n            if (newLib != null)\n            {\n                PresetLibraryManager.instance.SaveLibrary(m_SaveLoadHelper, newLib, presetLibraryPathWithoutExtension);\n                InternalEditorUtility.RepaintAllViews(); // Needed because we call this function from another window\n            }\n            return newLib;\n        }\n\n        public void RevealCurrentLibrary()\n        {\n            if (m_PresetLibraryFileLocation == PresetFileLocation.PreferencesFolder)\n                EditorUtility.RevealInFinder(Path.GetFullPath(pathWithExtension));\n            else\n                EditorGUIUtility.PingObject(AssetDatabase.GetMainAssetInstanceID(pathWithExtension));\n        }\n\n        internal class PresetContextMenu\n        {\n            static PresetLibraryEditor<T> s_Caller;\n            static int s_PresetIndex;\n\n            static internal void Show(bool isOpenForEdit, int presetIndex, object newPresetObject, PresetLibraryEditor<T> caller)\n            {\n                s_Caller = caller;\n                s_PresetIndex = presetIndex;\n\n                GUIContent replaceText = EditorGUIUtility.TrTextContent(\"Replace\");\n                GUIContent deleteText = EditorGUIUtility.TrTextContent(\"Delete\");\n                GUIContent renameText = EditorGUIUtility.TrTextContent(\"Rename\");\n                GUIContent moveToText = EditorGUIUtility.TrTextContent(\"Move To First\");\n\n                GenericMenu menu = new GenericMenu();\n                if (isOpenForEdit)\n                {\n                    menu.AddItem(replaceText, false, new PresetContextMenu().Replace, newPresetObject);\n                    menu.AddItem(deleteText, false, new PresetContextMenu().Delete, 0);\n                    if (caller.drawLabels)\n                        menu.AddItem(renameText, false, new PresetContextMenu().Rename, 0);\n                    menu.AddItem(moveToText, false, new PresetContextMenu().MoveToTop, 0);\n                }\n                else\n                {\n                    menu.AddDisabledItem(replaceText);\n                    menu.AddDisabledItem(deleteText);\n                    if (caller.drawLabels)\n                        menu.AddDisabledItem(renameText);\n                    menu.AddDisabledItem(moveToText);\n                }\n                menu.ShowAsContext();\n            }\n\n            private void Delete(object userData)\n            {\n                s_Caller.DeletePreset(s_PresetIndex);\n            }\n\n            private void Replace(object userData)\n            {\n                object newPresetObject = userData;\n                s_Caller.ReplacePreset(s_PresetIndex, newPresetObject);\n            }\n\n            private void Rename(object userData)\n            {\n                string name = s_Caller.GetCurrentLib().GetName(s_PresetIndex);\n                s_Caller.BeginRenaming(name, s_PresetIndex, 0.0f);\n            }\n\n            private void MoveToTop(object userData)\n            {\n                s_Caller.MovePreset(s_PresetIndex, 0, false);\n            }\n        }\n    }\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/PresetLibraries/PresetLibraryEditorMenu.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.IO;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal partial class PresetLibraryEditor<T> where T : PresetLibrary\n    {\n        class SettingsMenu\n        {\n            static PresetLibraryEditor<T> s_Owner;\n\n            class ViewModeData\n            {\n                public GUIContent text;\n                public int itemHeight;\n                public PresetLibraryEditorState.ItemViewMode viewmode;\n            }\n\n            public static void Show(Rect activatorRect, PresetLibraryEditor<T> owner)\n            {\n                s_Owner = owner;\n\n                GenericMenu menu = new GenericMenu();\n\n                // View modes\n                int minItemHeight = (int)s_Owner.minMaxPreviewHeight.x;\n                int maxItemHeight = (int)s_Owner.minMaxPreviewHeight.y;\n                List<ViewModeData> viewModeData;\n                if (minItemHeight == maxItemHeight)\n                {\n                    viewModeData = new List<ViewModeData>\n                    {\n                        new ViewModeData {text = EditorGUIUtility.TrTextContent(\"Grid\"), itemHeight = minItemHeight, viewmode = PresetLibraryEditorState.ItemViewMode.Grid},\n                        new ViewModeData {text = EditorGUIUtility.TrTextContent(\"List\"), itemHeight = minItemHeight, viewmode = PresetLibraryEditorState.ItemViewMode.List},\n                    };\n                }\n                else\n                {\n                    viewModeData = new List<ViewModeData>\n                    {\n                        new ViewModeData {text = EditorGUIUtility.TrTextContent(\"Small Grid\"), itemHeight = minItemHeight, viewmode = PresetLibraryEditorState.ItemViewMode.Grid},\n                        new ViewModeData {text = EditorGUIUtility.TrTextContent(\"Large Grid\"), itemHeight = maxItemHeight, viewmode = PresetLibraryEditorState.ItemViewMode.Grid},\n                        new ViewModeData {text = EditorGUIUtility.TrTextContent(\"Small List\"), itemHeight = minItemHeight, viewmode = PresetLibraryEditorState.ItemViewMode.List},\n                        new ViewModeData {text = EditorGUIUtility.TrTextContent(\"Large List\"), itemHeight = maxItemHeight, viewmode = PresetLibraryEditorState.ItemViewMode.List}\n                    };\n                }\n\n                for (int i = 0; i < viewModeData.Count; ++i)\n                {\n                    bool currentSelected = s_Owner.itemViewMode == viewModeData[i].viewmode && (int)s_Owner.previewHeight == viewModeData[i].itemHeight;\n                    menu.AddItem(viewModeData[i].text, currentSelected, ViewModeChange, viewModeData[i]);\n                }\n                menu.AddSeparator(\"\");\n\n                // Available libraries (show user libraries first then project libraries)\n                List<string> preferencesLibs;\n                List<string> projectLibs;\n                PresetLibraryManager.instance.GetAvailableLibraries(s_Owner.m_SaveLoadHelper, out preferencesLibs, out projectLibs);\n                preferencesLibs.Sort();\n                projectLibs.Sort();\n\n                string currentLibWithExtension = s_Owner.currentLibraryWithoutExtension + \".\" + s_Owner.m_SaveLoadHelper.fileExtensionWithoutDot;\n\n                string projectFolderTag = \" (Project)\";\n                foreach (string libPath in preferencesLibs)\n                {\n                    string libName = Path.GetFileNameWithoutExtension(libPath);\n                    menu.AddItem(new GUIContent(libName), currentLibWithExtension == libPath, LibraryModeChange, libPath);\n                }\n                foreach (string libPath in projectLibs)\n                {\n                    string libName = Path.GetFileNameWithoutExtension(libPath);\n                    menu.AddItem(new GUIContent(libName + projectFolderTag), currentLibWithExtension == libPath, LibraryModeChange, libPath);\n                }\n                menu.AddSeparator(\"\");\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Create New Library...\"), false, CreateLibrary, 0);\n                if (HasDefaultPresets())\n                {\n                    menu.AddSeparator(\"\");\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Add Factory Presets To Current Library\"), false, AddDefaultPresetsToCurrentLibrary, 0);\n                }\n                menu.AddSeparator(\"\");\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Reveal Current Library Location\"), false, RevealCurrentLibrary, 0);\n                menu.DropDown(activatorRect);\n            }\n\n            static void ViewModeChange(object userData)\n            {\n                ViewModeData viewModeData = (ViewModeData)userData;\n                s_Owner.itemViewMode = viewModeData.viewmode;\n                s_Owner.previewHeight = viewModeData.itemHeight;\n            }\n\n            static void LibraryModeChange(object userData)\n            {\n                string libPath = (string)userData;\n                s_Owner.currentLibraryWithoutExtension = libPath;\n            }\n\n            static void CreateLibrary(object userData)\n            {\n                s_Owner.wantsToCreateLibrary = true;\n            }\n\n            static void RevealCurrentLibrary(object userData)\n            {\n                s_Owner.RevealCurrentLibrary();\n            }\n\n            static bool HasDefaultPresets()\n            {\n                return s_Owner.addDefaultPresets != null;\n            }\n\n            static void AddDefaultPresetsToCurrentLibrary(object userData)\n            {\n                if (s_Owner.addDefaultPresets != null)\n                    s_Owner.addDefaultPresets(s_Owner.GetCurrentLib());\n\n                s_Owner.SaveCurrentLib();\n            }\n        }\n    }\n} // UnityEditor\n"
  },
  {
    "path": "Editor/Mono/PresetLibraries/PresetLibraryManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.IO;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    internal enum PresetFileLocation { PreferencesFolder, ProjectFolder } // ProjectFolder: We look in all Editor folders in Assets\n\n    internal static class PresetLibraryLocations\n    {\n        public static string defaultLibraryLocation\n        {\n            get { return GetDefaultFilePathForFileLocation(PresetFileLocation.PreferencesFolder); }\n        }\n\n        public static string defaultPresetLibraryPath\n        {\n            get { return Path.Combine(defaultLibraryLocation, defaultLibraryName); }\n        }\n\n        public static string defaultLibraryName\n        {\n            get { return \"Default\"; }\n        }\n\n        public static List<string> GetAvailableFilesWithExtensionOnTheHDD(PresetFileLocation fileLocation, string fileExtensionWithoutDot)\n        {\n            List<string> folderPaths = GetDirectoryPaths(fileLocation);\n            List<string> files = GetFilesWithExentionFromFolders(folderPaths, fileExtensionWithoutDot);\n            for (int i = 0; i < files.Count; ++i)\n                files[i] = ConvertToUnitySeperators(files[i]);\n            return files;\n        }\n\n        public static string GetDefaultFilePathForFileLocation(PresetFileLocation fileLocation)\n        {\n            switch (fileLocation)\n            {\n                case PresetFileLocation.PreferencesFolder:\n                    return InternalEditorUtility.unityPreferencesFolder + \"/Presets/\";\n\n                case PresetFileLocation.ProjectFolder:\n                    return \"Assets/Editor/\";\n\n                default:\n                    Debug.LogError(\"Enum not handled!\");\n                    return \"\";\n            }\n        }\n\n        static List<string> GetDirectoryPaths(PresetFileLocation fileLocation)\n        {\n            List<string> folderPaths = new List<string>();\n            switch (fileLocation)\n            {\n                case PresetFileLocation.PreferencesFolder:\n                    folderPaths.Add(GetDefaultFilePathForFileLocation(PresetFileLocation.PreferencesFolder));\n                    break;\n\n                case PresetFileLocation.ProjectFolder:\n                    string[] editorFolders = Directory.GetDirectories(\"Assets/\", \"Editor\", SearchOption.AllDirectories);\n                    folderPaths.AddRange(editorFolders);\n                    break;\n\n                default:\n                    Debug.LogError(\"Enum not handled!\");\n                    break;\n            }\n\n            return folderPaths;\n        }\n\n        static List<string> GetFilesWithExentionFromFolders(List<string> folderPaths, string fileExtensionWithoutDot)\n        {\n            // First get all potential files\n            var files = new List<string>();\n            foreach (string editorFolder in folderPaths)\n            {\n                string[] filePaths = Directory.GetFiles(editorFolder, \"*.\" + fileExtensionWithoutDot);\n                files.AddRange(filePaths);\n            }\n            return files;\n        }\n\n        public static PresetFileLocation GetFileLocationFromPath(string path)\n        {\n            if (path.Contains(InternalEditorUtility.unityPreferencesFolder))\n                return PresetFileLocation.PreferencesFolder;\n            if (path.Contains(\"Assets/\"))\n                return PresetFileLocation.ProjectFolder;\n\n            Debug.LogError(\"Could not determine preset file location type \" + path);\n            return PresetFileLocation.ProjectFolder;\n        }\n\n        static string ConvertToUnitySeperators(string path)\n        {\n            return path.Replace('\\\\', '/');\n        }\n\n        static public string GetParticleCurveLibraryExtension(bool singleCurve, bool signedRange)\n        {\n            string extension = \"particle\";\n            if (singleCurve)\n                extension += \"Curves\";\n            else\n                extension += \"DoubleCurves\";\n\n            if (signedRange)\n                extension += \"Signed\";\n            else\n                extension += \"\";\n\n            return extension;\n        }\n\n        static public string GetCurveLibraryExtension(bool normalized)\n        {\n            if (normalized)\n                return \"curvesNormalized\";\n            return \"curves\";\n        }\n    }\n\n\n    internal class PresetLibraryManager : ScriptableSingleton<PresetLibraryManager>\n    {\n        static string s_LastError = null;\n        private List<LibraryCache> m_LibraryCaches = new List<LibraryCache>();\n\n        private HideFlags libraryHideFlag\n        {\n            get { return HideFlags.DontSave; } // Use of DontSave prevents library from being nulled when going out of playmode\n        }\n\n        // Returns lists of filepaths for libraries with a given extension found on the HDD\n        public void GetAvailableLibraries<T>(ScriptableObjectSaveLoadHelper<T> helper, out List<string> preferencesLibs, out List<string> projectLibs) where T : ScriptableObject\n        {\n            preferencesLibs = PresetLibraryLocations.GetAvailableFilesWithExtensionOnTheHDD(PresetFileLocation.PreferencesFolder, helper.fileExtensionWithoutDot);\n            projectLibs = PresetLibraryLocations.GetAvailableFilesWithExtensionOnTheHDD(PresetFileLocation.ProjectFolder, helper.fileExtensionWithoutDot);\n        }\n\n        string GetLibaryNameFromPath(string filePath)\n        {\n            return Path.GetFileNameWithoutExtension(filePath);\n        }\n\n        public T CreateLibrary<T>(ScriptableObjectSaveLoadHelper<T> helper, string presetLibraryPathWithoutExtension) where T : ScriptableObject\n        {\n            string libraryName = GetLibaryNameFromPath(presetLibraryPathWithoutExtension);\n            if (!InternalEditorUtility.IsValidFileName(libraryName))\n            {\n                string invalid = InternalEditorUtility.GetDisplayStringOfInvalidCharsOfFileName(libraryName);\n                if (invalid.Length > 0)\n                    s_LastError = string.Format(\"A library filename cannot contain the following character{0}:  {1}\", invalid.Length > 1 ? \"s\" : \"\", invalid);\n                else\n                    s_LastError = \"Invalid filename\";\n                return null;\n            }\n\n            if (GetLibrary(helper, presetLibraryPathWithoutExtension) != null)\n            {\n                s_LastError = \"Library '\" + libraryName + \"' already exists! Ensure a unique name.\";\n                return null;\n            }\n\n            T library = helper.Create();\n            library.hideFlags = libraryHideFlag;\n            LibraryCache set = GetPresetLibraryCache(helper.fileExtensionWithoutDot);\n            set.loadedLibraries.Add(library);\n            set.loadedLibraryIDs.Add(presetLibraryPathWithoutExtension);\n            s_LastError = null;\n            return library;\n        }\n\n        public T GetLibrary<T>(ScriptableObjectSaveLoadHelper<T> helper, string presetLibraryPathWithoutExtension) where T : ScriptableObject\n        {\n            LibraryCache set = GetPresetLibraryCache(helper.fileExtensionWithoutDot);\n\n            // Did we already load the lib\n            for (int i = 0; i < set.loadedLibraryIDs.Count; ++i)\n            {\n                if (set.loadedLibraryIDs[i] == presetLibraryPathWithoutExtension)\n                {\n                    if (set.loadedLibraries[i] != null)\n                        return set.loadedLibraries[i] as T;\n                    else\n                    {\n                        // The library has been destroyed. Remove it from the lists so it can be reloaded\n                        set.loadedLibraries.RemoveAt(i);\n                        set.loadedLibraryIDs.RemoveAt(i);\n                        Debug.LogError(\"Invalid library detected: Reload \" + set.loadedLibraryIDs[i] + \" from HDD\");\n                        break;\n                    }\n                }\n            }\n\n            // Debug.Log (\"Not loaded yet \" + typeof(T));\n\n            // Can we find on the hdd\n            T library = helper.Load(presetLibraryPathWithoutExtension);\n\n            if (library != null)\n            {\n                library.hideFlags = libraryHideFlag; // ensure correct hideflag with pre 4.3 versions\n                set.loadedLibraries.Add(library);\n                set.loadedLibraryIDs.Add(presetLibraryPathWithoutExtension);\n                return library;\n            }\n\n            // Debug.Log (\"Not found on hdd\");\n\n            return null;\n        }\n\n        public void UnloadAllLibrariesFor<T>(ScriptableObjectSaveLoadHelper<T> helper) where T : ScriptableObject\n        {\n            for (int i = 0; i < m_LibraryCaches.Count; ++i)\n            {\n                if (m_LibraryCaches[i].identifier == helper.fileExtensionWithoutDot)\n                {\n                    m_LibraryCaches[i].UnloadScriptableObjects();\n                    m_LibraryCaches.RemoveAt(i);\n                    break;\n                }\n            }\n        }\n\n        public void SaveLibrary<T>(ScriptableObjectSaveLoadHelper<T> helper, T library, string presetLibraryPathWithoutExtension) where T : ScriptableObject\n        {\n            bool fileExistedBeforeSaving = File.Exists(presetLibraryPathWithoutExtension + \".\" + helper.fileExtensionWithoutDot);\n\n            helper.Save(library, presetLibraryPathWithoutExtension);\n\n            if (!fileExistedBeforeSaving)\n                AssetDatabase.Refresh();\n        }\n\n        public string GetLastError()\n        {\n            string errorString = s_LastError;\n            s_LastError = null;\n            return errorString;\n        }\n\n        private LibraryCache GetPresetLibraryCache(string identifier)\n        {\n            foreach (LibraryCache libraryCache in m_LibraryCaches)\n                if (libraryCache.identifier == identifier)\n                    return libraryCache;\n\n            // Add if not found\n            LibraryCache set = new LibraryCache(identifier);\n            m_LibraryCaches.Add(set);\n            return set;\n        }\n\n        private class LibraryCache\n        {\n            string m_Identifier; // Identifier for a group of libraries. For now its the file extension\n\n            // Should have been a Dictonary but we cannot serialize those properly yet...\n            List<ScriptableObject> m_LoadedLibraries = new List<ScriptableObject>(); // 1:1 with m_LoadedLibraryIDs\n            List<string> m_LoadedLibraryIDs = new List<string>(); // 1:1 with m_LoadedLibraries\n\n            // Interface\n            public string identifier { get { return m_Identifier; } }\n            public List<ScriptableObject> loadedLibraries { get { return m_LoadedLibraries; } }\n            public List<string> loadedLibraryIDs { get { return m_LoadedLibraryIDs; } } // List of paths without extension\n            public void UnloadScriptableObjects()\n            {\n                foreach (ScriptableObject sobj in m_LoadedLibraries)\n                    ScriptableObject.DestroyImmediate(sobj);\n                m_LoadedLibraries.Clear();\n                m_LoadedLibraryIDs.Clear();\n            }\n\n            public LibraryCache(string identifier)\n            {\n                m_Identifier = identifier;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/PresetLibraries/ScriptableObjectSaveLoadHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditorInternal;\nusing System.IO;\n\nnamespace UnityEditor\n{\n    public enum SaveType { Binary, Text }\n\n\n    // Class for making it easy to save and load ScriptableObjects manually (i.e without using the AssetDatabase)\n\n    class ScriptableObjectSaveLoadHelper<T> where T : ScriptableObject\n    {\n        public string fileExtensionWithoutDot { get; private set; }\n        private SaveType saveType { get; set; }\n\n        public ScriptableObjectSaveLoadHelper(string fileExtensionWithoutDot, SaveType saveType)\n        {\n            this.saveType = saveType;\n            this.fileExtensionWithoutDot = fileExtensionWithoutDot.TrimStart('.'); // Ensure no dot\n        }\n\n        // If 'filePath' does not include an extension the local 'fileExtensionWithoutDot' is used.\n        public T Load(string filePath)\n        {\n            filePath = AppendFileExtensionIfNeeded(filePath);\n\n            // Try to load\n            if (!string.IsNullOrEmpty(filePath))\n            {\n                Object[] objects = InternalEditorUtility.LoadSerializedFileAndForget(filePath);\n                if (objects != null && objects.Length > 0)\n                    return objects[0] as T;\n            }\n\n            return null;\n        }\n\n        public T Create()\n        {\n            T t = ScriptableObject.CreateInstance<T>();\n            return t;\n        }\n\n        // If 'filePath' does not include an extension the local 'fileExtensionWithoutDot' is used.\n        public void Save(T t, string filePath)\n        {\n            if (t == null)\n            {\n                Debug.LogError(\"Cannot save scriptableObject: its null!\");\n                return;\n            }\n\n            if (string.IsNullOrEmpty(filePath))\n            {\n                Debug.LogError(\"Invalid path: '\" + filePath + \"'\");\n                return;\n            }\n\n            // Ensure folder exists\n            string folderPath = Path.GetDirectoryName(filePath);\n            if (!Directory.Exists(folderPath))\n            {\n                Directory.CreateDirectory(folderPath);\n            }\n\n            filePath = AppendFileExtensionIfNeeded(filePath);\n\n            InternalEditorUtility.SaveToSerializedFileAndForget(new[] { t }, filePath, saveType == SaveType.Text);\n        }\n\n        public override string ToString()\n        {\n            return string.Format(\"{0}, {1}\", fileExtensionWithoutDot, saveType);\n        }\n\n        string AppendFileExtensionIfNeeded(string path)\n        {\n            if (!Path.HasExtension(path) && !string.IsNullOrEmpty(fileExtensionWithoutDot))\n                return path + \".\" + fileExtensionWithoutDot;\n            return path;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Progress/AssemblyInfo.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Runtime.CompilerServices;\n[assembly: InternalsVisibleTo(\"Unity.Modules.Progress.Tests.Editor\")]\n"
  },
  {
    "path": "Editor/Mono/Progress/Progress.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing UnityEngine.Assertions;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    [StaticAccessor(\"Editor::Progress\", StaticAccessorType.DoubleColon)]\n    [NativeHeader(k_NativeHeader)]\n    public static partial class Progress\n    {\n        const string k_NativeHeader = \"Editor/Src/AsyncProgress/Progress.h\";\n\n        // Keep in sync with Editor\\src\\Progress.h\n        [NativeType(Header = k_NativeHeader)]\n        public enum Status\n        {\n            Running,\n            Succeeded,\n            Failed,\n            Canceled,\n            Paused\n        }\n\n        [Flags, NativeType(Header = k_NativeHeader)]\n        public enum Options\n        {\n            None = 0 << 0,\n            Sticky = 1 << 0,\n            Indefinite = 1 << 1,\n            Synchronous = 1 << 2,\n            Managed = 1 << 3,\n            Unmanaged = 1 << 4\n        }\n\n        [NativeType(Header = k_NativeHeader)]\n        public enum TimeDisplayMode\n        {\n            NoTimeShown,\n            ShowRunningTime,\n            ShowRemainingTime\n        }\n\n        [NativeType(Header = k_NativeHeader)]\n        public enum Priority\n        {\n            Unresponsive = 0,\n            Idle = 1,\n            Low = 2,\n            Normal = 6,\n            High = 10\n        }\n\n        [Flags, NativeType(Header = k_NativeHeader)]\n        internal enum Updates : uint\n        {\n            NothingChanged = 0,\n            StatusChanged = 1,\n            ProgressChanged = 1 << 1,\n            DescriptionChanged = 1 << 2,\n            TimeDisplayModeChanged = 1 << 3,\n            RemainingTimeChanged = 1 << 4,\n            PriorityChanged = 1 << 5,\n            CancellableChanged = 1 << 6,\n            PausableChanged = 1 << 7,\n            StepLabelChanged = 1 << 8,\n            CurrentStepChanged = 1 << 9,\n            TotalStepsChanged = 1 << 10,\n            ElapsedTimeSinceLastPauseChanged = 1 << 11,\n            LastResumeTimeChanged = 1 << 12,\n            EndTimeChanged = 1 << 13,\n            EverythingChanged = 0xffffffff\n        }\n\n        [NativeType(Header = k_NativeHeader)]\n        internal enum ExplicitLoggingState\n        {\n            NotSet,\n            Enabled,\n            Disabled\n        }\n\n        [StructLayout(LayoutKind.Sequential)]\n        [NativeHeader(k_NativeHeader)]\n        [RequiredByNativeCode(GenerateProxy = true)]\n        internal struct ProgressIdAndUpdates\n        {\n            public int id;\n            public Updates updates;\n        }\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = true, Name = \"Editor::Progress::Start\")]\n        private static extern int Internal_Start(string name, string description, Options options, int parentId);\n\n        public static int Start(string name, string description = null, Options options = Options.None, int parentId = -1)\n        {\n            // Automatically set C# progress as managed so they get canceled when a domain reload occurs.\n            if ((options & Options.Unmanaged) == 0)\n                options |= Options.Managed;\n            return Internal_Start(name, description, options, parentId);\n        }\n\n        [ThreadSafe]\n        public static extern void Finish(int id, Status status = Status.Succeeded);\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = true, Name = \"Editor::Progress::Remove\")]\n        private static extern int Internal_Remove(int id, bool forceSynchronous);\n\n        public static int Remove(int id)\n        {\n            return Remove(id, false);\n        }\n\n        public static int Remove(int id, bool forceSynchronous)\n        {\n            return Internal_Remove(id, forceSynchronous);\n        }\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = true, Name = \"Editor::Progress::Report\")]\n        private static extern void Internal_Report(int id, float progress, string description = null);\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = true, Name = \"Editor::Progress::Report\")]\n        private static extern void Internal_Report_Items(int id, int currentStep, int totalSteps, string description = null);\n\n        public static void Report(int id, float progress)\n        {\n            Internal_Report(id, progress);\n        }\n\n        public static void Report(int id, int currentStep, int totalSteps)\n        {\n            Internal_Report_Items(id, currentStep, totalSteps);\n        }\n\n        public static void Report(int id, float progress, string description)\n        {\n            Internal_Report(id, progress, description);\n            if (string.IsNullOrEmpty(description))\n                SetDescription(id, description);\n        }\n\n        public static void Report(int id, int currentStep, int totalSteps, string description)\n        {\n            Internal_Report_Items(id, currentStep, totalSteps, description);\n            if (string.IsNullOrEmpty(description))\n                SetDescription(id, description);\n        }\n\n        public static extern bool Cancel(int id);\n\n        [ThreadSafe]\n        internal static extern void RegisterCancelCallbackFromScript(int id, Func<bool> callback);\n\n        public static void RegisterCancelCallback(int id, Func<bool> callback)\n        {\n            RegisterCancelCallbackFromScript(id, callback);\n        }\n\n        [ThreadSafe]\n        public static extern void UnregisterCancelCallback(int id);\n\n        public static extern bool Pause(int id);\n        public static extern bool Resume(int id);\n\n        [ThreadSafe]\n        internal static extern void RegisterPauseCallbackFromScript(int id, Func<bool, bool> callback);\n\n        public static void RegisterPauseCallback(int id, Func<bool, bool> callback)\n        {\n            RegisterPauseCallbackFromScript(id, callback);\n        }\n\n        [ThreadSafe]\n        public static extern void UnregisterPauseCallback(int id);\n\n        public static extern int GetCount();\n\n        internal static extern int[] GetManagedNotifiedIds();\n\n        public static extern int[] GetCountPerStatus();\n\n        public static extern float GetProgress(int id);\n        public static extern int GetCurrentStep(int id);\n        public static extern int GetTotalSteps(int id);\n\n        public static extern string GetName(int id);\n\n        public static extern string GetDescription(int id);\n\n        [ThreadSafe]\n        public static extern void SetDescription(int id, string description);\n\n        public static extern long GetStartDateTime(int id);\n\n        public static extern long GetEndDateTime(int id);\n\n        public static extern long GetUpdateDateTime(int id);\n\n        public static extern int GetParentId(int id);\n\n        public static extern int GetId(int index);\n\n        public static extern bool IsCancellable(int id);\n\n        public static extern bool IsPausable(int id);\n\n        public static extern Status GetStatus(int id);\n\n        public static extern Options GetOptions(int id);\n\n        [ThreadSafe]\n        public static extern void SetTimeDisplayMode(int id, TimeDisplayMode displayMode);\n\n        [ThreadSafe]\n        public static extern void SetRemainingTime(int id, long seconds);\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = true, Name = \"Editor::Progress::SetPriority\")]\n        private static extern void Internal_SetPriority(int id, int priority);\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = true, Name = \"Editor::Progress::SetPriority\")]\n        private static extern void Internal_SetPriority_Enum(int id, Priority priority);\n\n        public static void SetPriority(int id, int priority)\n        {\n            Internal_SetPriority(id, priority);\n        }\n\n        public static void SetPriority(int id, Priority priority)\n        {\n            Internal_SetPriority_Enum(id, priority);\n        }\n\n        public static extern TimeDisplayMode GetTimeDisplayMode(int id);\n\n        public static extern bool Exists(int id);\n\n        public static extern long GetRemainingTime(int id);\n\n        public static extern int GetPriority(int id);\n\n        public static extern void ClearRemainingTime(int id);\n\n        internal static extern long GetLastResumeDateTime(int id);\n\n        internal static extern long GetElapsedTimeUntilLastPause(int id);\n\n        [ThreadSafe]\n        public static extern void SetStepLabel(int id, string label);\n\n        public static extern string GetStepLabel(int id);\n\n        public static void ShowDetails(bool shouldReposition = true)\n        {\n            ProgressWindow.ShowDetails(shouldReposition);\n        }\n\n        private static List<Item> s_ProgressItems = new List<Item>(8);\n        private static bool s_Initialized;\n        private static float s_Progress;\n        private static bool s_ProgressDirty = true;\n        private static TimeSpan s_RemainingTime = TimeSpan.Zero;\n        private static bool s_RemainingTimeDirty = true;\n        private static DateTime s_LastRemainingTimeUpdate = DateTime.Now;\n\n        public static event Action<Item[]> added;\n        public static event Action<Item[]> updated;\n        public static event Action<Item[]> removed;\n\n        public static IEnumerable<Item> EnumerateItems()\n        {\n            if (!s_Initialized)\n                RestoreProgressItems();\n            return s_ProgressItems;\n        }\n\n        public static Item GetProgressById(int id)\n        {\n            foreach (var progressItem in EnumerateItems())\n            {\n                if (progressItem.id == id)\n                    return progressItem;\n            }\n            return null;\n        }\n\n        public static int GetRunningProgressCount()\n        {\n            return GetCountPerStatus()[(int)Status.Running];\n        }\n\n        public static bool running => GetRunningProgressCount() > 0;\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = false, Name = \"Editor::Progress::GetGlobalProgress\")]\n        private static extern float Internal_GetGlobalProgress();\n\n        public static float globalProgress\n        {\n            get\n            {\n                if (!s_ProgressDirty)\n                    return s_Progress;\n                s_Progress = Internal_GetGlobalProgress();\n                s_ProgressDirty = false;\n                return s_Progress;\n            }\n        }\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = false, Name = \"Editor::Progress::GetGlobalRemainingTime\")]\n        private static extern long Internal_GetGlobalRemainingTime();\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = false, Name = \"Editor::Progress::Internal_ClearLogs\")]\n        internal static extern void ClearLogs();\n\n        public static TimeSpan globalRemainingTime\n        {\n            get\n            {\n                if (s_RemainingTimeDirty)\n                {\n                    s_RemainingTime = Item.SecToTimeSpan(Internal_GetGlobalRemainingTime());\n                    s_LastRemainingTimeUpdate = DateTime.Now;\n                    s_RemainingTimeDirty = false;\n                }\n\n                var duration = (DateTime.Now - s_LastRemainingTimeUpdate).Duration();\n                return s_RemainingTime - new TimeSpan(duration.Days, duration.Hours, duration.Minutes, duration.Seconds);\n            }\n        }\n\n        [RequiredByNativeCode]\n        private static void OnOperationStateCreated(int id)\n        {\n            if (!s_Initialized)\n                RestoreProgressItems();\n            var item = CreateProgressItem(id);\n\n            s_ProgressDirty = true;\n            s_RemainingTimeDirty = true;\n            added?.Invoke(new[] {item});\n        }\n\n        [RequiredByNativeCode]\n        private static void OnOperationStateChanged(int id, Updates progressUpdates)\n        {\n            if (!s_Initialized)\n                RestoreProgressItems();\n\n            var item = GetProgressById(id);\n            Assert.IsNotNull(item);\n\n            s_ProgressDirty = true;\n            s_RemainingTimeDirty = true;\n            item.Dirty(progressUpdates);\n\n            updated?.Invoke(new[] {item});\n            item.ClearUpdates();\n        }\n\n        [RequiredByNativeCode]\n        private static void OnOperationsStateChanged(ReadOnlySpan<ProgressIdAndUpdates> progressUpdates)\n        {\n            if (!s_Initialized)\n                RestoreProgressItems();\n            if (progressUpdates.Length == 0) return;\n\n            var items = new Item[progressUpdates.Length];\n\n            for (var i = 0; i < progressUpdates.Length; i++)\n            {\n                ref readonly var update = ref progressUpdates[i];\n                var item = GetProgressById(update.id);\n                Assert.IsNotNull(item);\n                item.Dirty(update.updates);\n                items[i] = item;\n            }\n\n            s_ProgressDirty = true;\n            s_RemainingTimeDirty = true;\n\n            updated?.Invoke(items);\n            foreach (var item in items)\n            {\n                item.ClearUpdates();\n            }\n        }\n\n        [RequiredByNativeCode]\n        private static void OnOperationStateRemoved(int id)\n        {\n            if (!s_Initialized)\n                RestoreProgressItems();\n\n            var item = GetProgressById(id);\n            Assert.IsNotNull(item);\n\n            s_ProgressDirty = true;\n            s_RemainingTimeDirty = true;\n            s_ProgressItems.Remove(item);\n\n            removed?.Invoke(new[] {item});\n        }\n\n        [RequiredByNativeCode]\n        private static void OnOperationsStateRemoved(int[] ids)\n        {\n            if (!s_Initialized)\n                RestoreProgressItems();\n\n            var items = new Item[ids.Length];\n            var i = 0;\n            foreach (var id in ids)\n            {\n                var item = GetProgressById(id);\n                items[i++] = item;\n                Assert.IsNotNull(item);\n                s_ProgressItems.Remove(item);\n            }\n\n            s_ProgressDirty = true;\n            s_RemainingTimeDirty = true;\n\n\n            removed?.Invoke(items);\n        }\n\n        private static void RestoreProgressItems()\n        {\n            if (s_Initialized)\n                return;\n\n            s_ProgressItems.Clear();\n\n            var alreadyCreatedIds = GetManagedNotifiedIds();\n            foreach (var id in alreadyCreatedIds)\n            {\n                CreateProgressItem(id);\n            }\n            s_Initialized = true;\n            s_ProgressDirty = true;\n            s_RemainingTimeDirty = true;\n        }\n\n        private static Item CreateProgressItem(int id)\n        {\n            // It is possible for this function to be called during\n            // RestoreProgressItems and right after in OnOperationStateCreated,\n            // for the same id, if the progress comes from C++ and\n            // the C# Progress class has not been initialized before. Therefore,\n            // we have to check if the progress already exists in our list\n            // otherwise we will have duplicates.\n            var currentItem = s_ProgressItems.FirstOrDefault(i => i.id == id);\n            if (currentItem != null)\n                return currentItem;\n            var item = new Item(id);\n            s_ProgressItems.Add(item);\n            return item;\n        }\n\n        internal static float GetMaxElapsedTime()\n        {\n            if (s_ProgressItems.Count == 0)\n                return 0.0f;\n\n            var maxElapsedTime = -1.0f;\n            foreach (var progressItem in s_ProgressItems)\n            {\n                var elapsedTime = progressItem.elapsedTime;\n                if (elapsedTime > maxElapsedTime)\n                    maxElapsedTime = elapsedTime;\n            }\n\n            return maxElapsedTime;\n        }\n\n        // Anything below this line is for testing purposes only.\n        internal static void ClearProgressItems()\n        {\n            s_ProgressItems.Clear();\n            s_Initialized = false;\n            s_ProgressDirty = true;\n            s_RemainingTimeDirty = true;\n            s_Progress = 0f;\n            s_RemainingTime = TimeSpan.Zero;\n            s_LastRemainingTimeUpdate = DateTime.Now;\n        }\n\n        internal static ExplicitLoggingState errorLoggingState\n        {\n            get => GetExplicitErrorLoggingState();\n            set => SetExplicitErrorLoggingState(value);\n        }\n        internal static ExplicitLoggingState warningLoggingState\n        {\n            get => GetExplicitWarningLoggingState();\n            set => SetExplicitWarningLoggingState(value);\n        }\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = false, Name = \"Editor::Progress::Internal_GetExplicitErrorLoggingState\")]\n        static extern ExplicitLoggingState GetExplicitErrorLoggingState();\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = false, Name = \"Editor::Progress::Internal_GetExplicitWarningLoggingState\")]\n        static extern ExplicitLoggingState GetExplicitWarningLoggingState();\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = false, Name = \"Editor::Progress::Internal_SetExplicitErrorLoggingState\")]\n        static extern void SetExplicitErrorLoggingState(ExplicitLoggingState state);\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = false, Name = \"Editor::Progress::Internal_SetExplicitWarningLoggingState\")]\n        static extern void SetExplicitWarningLoggingState(ExplicitLoggingState state);\n\n        internal static bool manualUpdate\n        {\n            get => IsManualUpdate();\n            set => SetManualUpdate(value);\n        }\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = false, Name = \"Editor::Progress::Internal_IsManualUpdate\")]\n        static extern bool IsManualUpdate();\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = false, Name = \"Editor::Progress::Internal_SetManualUpdate\")]\n        static extern void SetManualUpdate(bool manualUpdate);\n\n        [NativeMethod(IsFreeFunction = true, IsThreadSafe = false, Name = \"Editor::Progress::ForceUpdateProgress\")]\n        internal static extern void ForceUpdate();\n    }\n\n    static class ProgressEnumExtensions\n    {\n        public static bool HasAny(this Progress.Updates flags, Progress.Updates f)\n        {\n            if (f == Progress.Updates.NothingChanged && flags == Progress.Updates.NothingChanged)\n                return true;\n            return (f & flags) != 0;\n        }\n\n        public static bool HasAll(this Progress.Updates flags, Progress.Updates all) => (flags & all) == all;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Progress/Progress.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Diagnostics;\n\nnamespace UnityEditor\n{\n    public static partial class Progress\n    {\n        [DebuggerDisplay(\"name={name}\")]\n        public class Item\n        {\n            struct CachedValue<T>\n            {\n                readonly Func<int, T> m_UpdateCallback;\n                T m_LocalValue;\n                bool m_Updated;\n\n                public T GetValue(int id)\n                {\n                    if (!m_Updated)\n                    {\n                        m_LocalValue = m_UpdateCallback(id);\n                        m_Updated = true;\n                    }\n\n                    return m_LocalValue;\n                }\n\n                public CachedValue(Func<int, T> updateCallback)\n                {\n                    m_UpdateCallback = updateCallback;\n                    m_Updated = false;\n                    m_LocalValue = default(T);\n                }\n\n                public void Dirty()\n                {\n                    m_Updated = false;\n                }\n\n                public bool IsDirty()\n                {\n                    return !m_Updated;\n                }\n\n                // For testing purposes\n                public void SetLocalValue(T value)\n                {\n                    m_LocalValue = value;\n                    m_Updated = true;\n                }\n            }\n\n            CachedValue<string> m_Name = new CachedValue<string>(GetName);\n            CachedValue<string> m_Description = new CachedValue<string>(GetDescription);\n            CachedValue<float> m_Progress = new CachedValue<float>(GetProgress);\n            CachedValue<int> m_CurrentStep = new CachedValue<int>(GetCurrentStep);\n            CachedValue<int> m_TotalSteps = new CachedValue<int>(GetTotalSteps);\n            CachedValue<string> m_StepsLabel = new CachedValue<string>(GetStepLabel);\n            CachedValue<int> m_ParentId = new CachedValue<int>(GetParentId);\n            CachedValue<DateTime> m_StartTime = new CachedValue<DateTime>(id => MSecToDateTime(GetStartDateTime(id)));\n            CachedValue<DateTime> m_EndTime = new CachedValue<DateTime>(id => MSecToDateTime(GetEndDateTime(id)));\n            CachedValue<DateTime> m_UpdateTime = new CachedValue<DateTime>(id => MSecToDateTime(GetUpdateDateTime(id)));\n            CachedValue<Status> m_Status = new CachedValue<Status>(GetStatus);\n            CachedValue<Options> m_Options = new CachedValue<Options>(GetOptions);\n            CachedValue<TimeDisplayMode> m_TimeDisplayMode = new CachedValue<TimeDisplayMode>(GetTimeDisplayMode);\n            CachedValue<TimeSpan> m_RemainingTime = new CachedValue<TimeSpan>(id => SecToTimeSpan(GetRemainingTime(id)));\n            CachedValue<int> m_Priority = new CachedValue<int>(GetPriority);\n            CachedValue<DateTime> m_LastResumeTime = new CachedValue<DateTime>(id => MSecToDateTime(GetLastResumeDateTime(id)));\n            CachedValue<TimeSpan> m_ElapsedTimeUntilLastPause = new CachedValue<TimeSpan>(id => MSecToTimeSpan(GetElapsedTimeUntilLastPause(id)));\n            DateTime m_LastRemainingTime;\n\n            public string name => m_Name.GetValue(id);\n            public string description => m_Description.GetValue(id);\n            public int id { get; internal set; }\n            public float progress => m_Progress.GetValue(id);\n            public int currentStep => m_CurrentStep.GetValue(id);\n            public int totalSteps => m_TotalSteps.GetValue(id);\n            public string stepLabel => m_StepsLabel.GetValue(id);\n            public int parentId => m_ParentId.GetValue(id);\n            public DateTime startTime => m_StartTime.GetValue(id);\n            public DateTime endTime => m_EndTime.GetValue(id);\n            public DateTime updateTime => m_UpdateTime.GetValue(id);\n            public Status status => m_Status.GetValue(id);\n            public Options options => m_Options.GetValue(id);\n            public TimeDisplayMode timeDisplayMode => m_TimeDisplayMode.GetValue(id);\n            public int priority => m_Priority.GetValue(id);\n\n            public TimeSpan remainingTime\n            {\n                get\n                {\n                    if (m_RemainingTime.IsDirty())\n                    {\n                        m_LastRemainingTime = DateTime.Now;\n                    }\n\n                    var duration = (DateTime.Now - m_LastRemainingTime).Duration();\n                    return m_RemainingTime.GetValue(id) - new TimeSpan(duration.Days, duration.Hours, duration.Minutes, duration.Seconds);\n                }\n            }\n\n            public bool finished => status != Status.Running && status != Status.Paused;\n            public bool running => status == Status.Running;\n            public bool paused => status == Status.Paused;\n            public bool responding => !running || (DateTime.Now.ToUniversalTime() - updateTime) <= TimeSpan.FromSeconds(5f) || (priority >= (int)Priority.Idle && priority < (int)Priority.Normal);\n            public bool cancellable => IsCancellable(id);\n            public bool pausable => IsPausable(id);\n            public bool indefinite => running && (progress == -1f || (options & Options.Indefinite) == Options.Indefinite);\n            public float elapsedTime\n            {\n                get\n                {\n                    if (finished)\n                    {\n                        var executionTime = endTime - startTime;\n                        return (float)executionTime.TotalSeconds;\n                    }\n                    else\n                        return paused ? (float)elapsedTimeUntilLastPause.TotalSeconds : (float)(elapsedTimeUntilLastPause + (DateTime.UtcNow - lastResumeTime)).TotalSeconds;\n                }\n            }\n\n            public bool exists => Exists(id);\n            internal DateTime lastResumeTime => m_LastResumeTime.GetValue(id);\n            internal TimeSpan elapsedTimeUntilLastPause => m_ElapsedTimeUntilLastPause.GetValue(id);\n\n            internal Updates lastUpdates { get; private set; }\n\n            internal Item(int id)\n            {\n                this.id = id;\n            }\n\n            public void Report(float newProgress)\n            {\n                Progress.Report(id, newProgress);\n            }\n\n            public void Report(int newCurrentStep, int newTotalSteps)\n            {\n                Progress.Report(id, newCurrentStep, newTotalSteps);\n            }\n\n            public void Report(float newProgress, string newDescription)\n            {\n                Progress.Report(id, newProgress, newDescription);\n            }\n\n            public void Report(int newCurrentStep, int newTotalSteps, string newDescription)\n            {\n                Progress.Report(id, newCurrentStep, newTotalSteps, newDescription);\n            }\n\n            public bool Cancel()\n            {\n                return Progress.Cancel(id);\n            }\n\n            public bool Pause()\n            {\n                return Progress.Pause(id);\n            }\n\n            public bool Resume()\n            {\n                return Progress.Resume(id);\n            }\n\n            public void Finish(Status finishedStatus = Status.Succeeded)\n            {\n                Progress.Finish(id, finishedStatus);\n            }\n\n            public int Remove()\n            {\n                return Progress.Remove(id);\n            }\n\n            public void RegisterCancelCallback(Func<bool> callback)\n            {\n                Progress.RegisterCancelCallback(id, callback);\n            }\n\n            public void UnregisterCancelCallback()\n            {\n                Progress.UnregisterCancelCallback(id);\n            }\n\n            public void RegisterPauseCallback(Func<bool, bool> callback)\n            {\n                Progress.RegisterPauseCallback(id, callback);\n            }\n\n            public void UnregisterPauseCallback()\n            {\n                Progress.UnregisterPauseCallback(id);\n            }\n\n            public void SetDescription(string newDescription)\n            {\n                Progress.SetDescription(id, newDescription);\n            }\n\n            public void SetTimeDisplayMode(TimeDisplayMode mode)\n            {\n                Progress.SetTimeDisplayMode(id, mode);\n            }\n\n            public void SetRemainingTime(long seconds)\n            {\n                Progress.SetRemainingTime(id, seconds);\n            }\n\n            public void SetPriority(int priority)\n            {\n                Progress.SetPriority(id, priority);\n            }\n\n            public void SetPriority(Priority priority)\n            {\n                Progress.SetPriority(id, priority);\n            }\n\n            public void ClearRemainingTime()\n            {\n                Progress.ClearRemainingTime(id);\n            }\n\n            public void SetStepLabel(string label)\n            {\n                Progress.SetStepLabel(id, label);\n            }\n\n            internal void Dirty(Updates updates)\n            {\n                lastUpdates = updates;\n\n                // If the item was updated, update time is always updated\n                m_UpdateTime.Dirty();\n\n                if (updates.HasAny(Updates.DescriptionChanged))\n                    m_Description.Dirty();\n                if (updates.HasAny(Updates.PriorityChanged))\n                    m_Priority.Dirty();\n                if (updates.HasAny(Updates.ProgressChanged))\n                    m_Progress.Dirty();\n                if (updates.HasAny(Updates.CurrentStepChanged))\n                    m_CurrentStep.Dirty();\n                if (updates.HasAny(Updates.TotalStepsChanged))\n                    m_TotalSteps.Dirty();\n                if (updates.HasAny(Updates.StepLabelChanged))\n                    m_StepsLabel.Dirty();\n                if (updates.HasAny(Updates.StatusChanged))\n                    m_Status.Dirty();\n                if (updates.HasAny(Updates.RemainingTimeChanged))\n                    m_RemainingTime.Dirty();\n                if (updates.HasAny(Updates.TimeDisplayModeChanged))\n                    m_TimeDisplayMode.Dirty();\n                if (updates.HasAny(Updates.LastResumeTimeChanged))\n                    m_LastResumeTime.Dirty();\n                if (updates.HasAny(Updates.ElapsedTimeSinceLastPauseChanged))\n                    m_ElapsedTimeUntilLastPause.Dirty();\n                if (updates.HasAny(Updates.EndTimeChanged))\n                    m_EndTime.Dirty();\n            }\n\n            internal void ClearUpdates()\n            {\n                lastUpdates = Updates.NothingChanged;\n            }\n\n            internal void SetUpdateTime(DateTime time)\n            {\n                m_UpdateTime.SetLocalValue(time);\n            }\n\n            internal static DateTime MSecToDateTime(long msec)\n            {\n                return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(msec);\n            }\n\n            internal static TimeSpan SecToTimeSpan(long sec)\n            {\n                return new TimeSpan(0, 0, 0, (int)sec);\n            }\n\n            internal static TimeSpan MSecToTimeSpan(long msec)\n            {\n                return new TimeSpan(0, 0, 0, 0, (int)msec);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Progress/ProgressOrderComparer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    internal class ProgressOrderComparer : IComparer<Progress.Item>\n    {\n        bool m_Reverse;\n\n        public ProgressOrderComparer(bool reverse = false)\n        {\n            m_Reverse = reverse;\n        }\n\n        public int Compare(Progress.Item source, Progress.Item compared)\n        {\n            int compare = CompareStatus(source.status, compared.status);\n            if (compare == 0)\n            {\n                compare = source.priority.CompareTo(compared.priority);\n                if (compare == 0)\n                    compare = source.startTime.CompareTo(compared.startTime);\n                if (compare == 0)\n                    compare = source.id.CompareTo(compared.id);\n            }\n\n            if (m_Reverse)\n                return compare * -1;\n            return compare;\n        }\n\n        private static int CompareStatus(Progress.Status statusSource, Progress.Status statusToCompare)\n        {\n            // Pause and Running have the same priority (we don't want the item to change position when clicking pause/resume)\n            if ((statusSource == Progress.Status.Running || statusSource == Progress.Status.Paused) && (statusToCompare != Progress.Status.Running && statusToCompare != Progress.Status.Paused))\n                return 1;\n            if (statusSource == Progress.Status.Failed && (statusToCompare != Progress.Status.Failed && statusToCompare != Progress.Status.Running && statusToCompare != Progress.Status.Paused))\n                return 1;\n            if (statusSource == Progress.Status.Canceled && statusToCompare == Progress.Status.Succeeded)\n                return 1;\n            if (statusSource == statusToCompare\n                // Same thing, Pause and Running have the same priority (we don't want the item to change position when clicking pause/resume)\n                || (statusSource == Progress.Status.Running || statusSource == Progress.Status.Paused) && (statusToCompare == Progress.Status.Running || statusToCompare == Progress.Status.Paused))\n                return 0;\n            return -1;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ProgressScope.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor;\n\ninternal partial struct ProgressScope\n{\n    [FreeFunction(\"ProgressScope::PushScope\")]\n    internal static extern UIntPtr ProgressBarPushScope(string title, string info, float length = 1.0f, bool cancellable = false, bool skippable = false, bool forceUpdate = false, bool forceDisplay = false);\n    [FreeFunction(\"ProgressScope::SetText\")]\n    internal static extern void ProgressBarSetText(string info, bool forceUpdate = false, bool forceDisplay = false);\n    [FreeFunction(\"ProgressScope::PopScope\")]\n    internal static extern void ProgressBarPopScope(UIntPtr scope);\n}\n"
  },
  {
    "path": "Editor/Mono/ProgressScope.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor;\n\ninternal partial struct ProgressScope : IDisposable\n{\n    private UIntPtr scope;\n\n    public ProgressScope(string title, string text, float length = 1f, bool cancellable = false, bool skippable = false, bool forceUpdate = false, bool forceDisplay = false)\n    {\n        scope = ProgressBarPushScope(title, text, length, cancellable, skippable, forceUpdate, forceDisplay);\n    }\n\n    public void SetText(string text, bool forceUpdate = false, bool forceDisplay = false)\n    {\n        ProgressBarSetText(text, forceUpdate, forceDisplay);\n    }\n\n    public void Dispose()\n    {\n        ProgressBarPopScope(scope);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ProjectBrowser/AssetClipboardUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing UnityEditor.Build.Content;\nusing UnityEngine;\nusing UnityEngine.Internal;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal static class AssetClipboardUtility\n    {\n        static HashSet<ObjectIdentifier> assetClipboard = new HashSet<ObjectIdentifier>();\n        static PerformedAction performedAction = PerformedAction.None;\n        internal static void DuplicateSelectedAssets()\n        {\n            performedAction = PerformedAction.None;\n            Selection.objects = DuplicateAssets(Selection.objects).ToArray();\n        }\n\n        internal static void CutCopySelectedAssets(PerformedAction action)\n        {\n            performedAction = action;\n\n            if (Selection.objects.Length > 0)\n                CutCopyAssets(Selection.objects);\n        }\n\n        internal static void PasteSelectedAssets(bool isTwoColumnView)\n        {\n            string targetPath;\n\n            // If we are using OneColumnLayout rely on object selection, otherwise rely on active folder\n            if (!isTwoColumnView && Selection.objects.Length == 1)\n            {\n                targetPath = AssetDatabase.GetAssetPath(Selection.activeObject);\n\n                // If selected object is folder, make sure we paste into it.\n                if (AssetDatabase.IsValidFolder(targetPath))\n                {\n                    targetPath += \"/\";\n                }\n                else\n                {\n                    targetPath = Path.GetDirectoryName(targetPath);\n                }\n            }\n            else\n            {\n                targetPath = ProjectWindowUtil.GetActiveFolderPath();\n            }\n\n            switch (performedAction)\n            {\n                case PerformedAction.Copy:\n                    Selection.objects = PasteCopiedAssets(targetPath).ToArray();\n                    break;\n                case PerformedAction.Cut:\n                    Selection.objects = PasteCutAssets(targetPath).ToArray();\n                    performedAction = PerformedAction.None;\n                    break;\n            }\n        }\n\n        internal static IEnumerable<Object> DuplicateAssets(IEnumerable<Object> assets)\n        {\n            CutCopyAssets(assets);\n            return PasteCopiedAssets();\n        }\n\n        internal static IEnumerable<Object> DuplicateAssets(IEnumerable<int> instanceIDs)\n        {\n            return DuplicateAssets(instanceIDs.Select(id => EditorUtility.InstanceIDToObject(id)));\n        }\n\n        static void CutCopyAssets(IEnumerable<Object> assets)\n        {\n            Reset();\n            foreach (var asset in assets)\n            {\n                ObjectIdentifier.GetObjectIdentifierFromObject(asset, out var identifier);\n                assetClipboard.Add(identifier);\n            }\n        }\n\n        // file names must match m_Name of the main asset in a duplicate\n        // therefore object names may not contain invalid characters or path separators\n        static readonly Regex k_MatchInvalidObjAssetNameChars = new(\n            $@\"({string.Join('|', Path.GetInvalidFileNameChars().Select(c=> Regex.Escape(c.ToString())))}|/|\\\\)\"\n        );\n\n        static IEnumerable<Object> PasteCopiedAssets(string destination = null)\n        {\n            Object firstDuplicatedObjectToFail = null;\n            List<string> pastedObjects = new List<string>();\n\n            foreach (var item in assetClipboard)\n            {\n                var asset = ObjectIdentifier.ToObject(item);\n                var assetPath = AssetDatabase.GetAssetPath(asset);\n\n                // if duplicating a sub-asset, then create a copy next to the main asset file\n                if (asset != null && !String.IsNullOrEmpty(assetPath) && AssetDatabase.IsSubAsset(asset))\n                {\n                    if (asset is ISubAssetNotDuplicatable || asset is GameObject)\n                    {\n                        firstDuplicatedObjectToFail = firstDuplicatedObjectToFail ? firstDuplicatedObjectToFail : asset;\n                        continue;\n                    }\n\n                    var extension = NativeFormatImporterUtility.GetExtensionForAsset(asset);\n\n                    // sanitize and warn about object names that are not valid asset names\n                    var newAssetName = asset.name;\n                    bool invalidName = false;\n                    // use the same replacement character, '_' that the asset database uses for other invalid characters\n                    const string kReplacement = \"_\";\n\n                    if (string.IsNullOrEmpty(newAssetName))\n                    {\n                        newAssetName = kReplacement;\n                        invalidName = true;\n                    }\n                    else if (k_MatchInvalidObjAssetNameChars.IsMatch(newAssetName))\n                    {\n                        newAssetName = k_MatchInvalidObjAssetNameChars.Replace(newAssetName, kReplacement);\n                        invalidName = true;\n                    }\n\n                    if (invalidName)\n                        Debug.LogWarning($\"Duplicated object '{asset.name}' does not have a valid name for an asset. The new asset will be called '{newAssetName}'.\");\n\n                    var newPath = AssetDatabase.GenerateUniqueAssetPath(\n                        string.Format(\"{0}{1}{2}.{3}\",\n                            Path.GetDirectoryName(assetPath),\n                            Path.DirectorySeparatorChar,\n                            newAssetName,\n                            extension)\n                    );\n\n                    assetPath = GetValidPath(newPath, destination);\n                    AssetDatabase.CreateAsset(Object.Instantiate(asset), assetPath);\n                    pastedObjects.Add(assetPath);\n                }\n                // Otherwise duplicate the main asset file\n                else if (EditorUtility.IsPersistent(asset))\n                {\n                    var newPath = AssetDatabase.GenerateUniqueAssetPath(GetValidPath(assetPath, destination));\n                    if (newPath.Length > 0 && AssetDatabase.CopyAsset(assetPath, newPath))\n                        pastedObjects.Add(newPath);\n                }\n            }\n\n            if (firstDuplicatedObjectToFail != null)\n            {\n                var errString = string.Format(\n                    \"Duplication error: One or more sub assets (with types of {0}) can not be duplicated directly, use the appropriate editor instead\",\n                    firstDuplicatedObjectToFail.GetType().Name\n                );\n\n                Debug.LogError(errString, firstDuplicatedObjectToFail);\n            }\n\n            return pastedObjects.Select(AssetDatabase.LoadMainAssetAtPath);\n        }\n\n        static IEnumerable<Object> PasteCutAssets(string destination = null)\n        {\n            List<string> pastedObjects = new List<string>();\n            string[] assetPaths = new string[assetClipboard.Count];\n\n            int counter = 0;\n            foreach (var item in assetClipboard)\n            {\n                assetPaths[counter] = AssetDatabase.GetAssetPath(ObjectIdentifier.ToObject(item));\n                counter++;\n            }\n\n            if (counter > 0)\n                Undo.RegisterAssetsMoveUndo(assetPaths);\n\n            counter = 0;\n            foreach (var item in assetClipboard)\n            {\n                var assetPath = assetPaths[counter];\n                var validPath = GetValidPath(assetPath, destination);\n                var obj = AssetDatabase.LoadAssetAtPath(validPath, typeof(Object));\n                var newPath = assetPath != validPath && obj != null ? AssetDatabase.GenerateUniqueAssetPath(validPath) : validPath;\n\n                if (String.IsNullOrEmpty(AssetDatabase.ValidateMoveAsset(assetPath, newPath)))\n                {\n                    AssetDatabase.MoveAsset(assetPath, newPath);\n                    pastedObjects.Add(newPath);\n                }\n\n                counter++;\n            }\n\n            Reset();\n            AssetDatabase.Refresh();\n\n            return pastedObjects.Select(AssetDatabase.LoadMainAssetAtPath);\n        }\n\n        // Returns list of duplicated instanceIDs\n        internal static int[] DuplicateFolders(int[] instanceIDs)\n        {\n            CutCopySelectedFolders(instanceIDs, PerformedAction.Copy);\n            return PasteFoldersAfterCopy();\n        }\n\n        internal static void CutCopySelectedFolders(int[] instanceIDs, PerformedAction action)\n        {\n            Reset();\n            performedAction = action;\n            AssetDatabase.Refresh();\n\n            int assetsFolderInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(\"Assets\");\n\n            foreach (int instanceID in instanceIDs)\n            {\n                if (instanceID == assetsFolderInstanceID)\n                    continue;\n\n                ObjectIdentifier.GetObjectIdentifierFromInstanceID(instanceID, out var identifier);\n                assetClipboard.Add(identifier);\n            }\n        }\n\n        internal static int[] PasteFolders()\n        {\n            if (performedAction == PerformedAction.Cut)\n            {\n                return PasteFoldersAfterCut(ProjectWindowUtil.GetActiveFolderPath());\n            }\n            else\n            {\n                return PasteFoldersAfterCopy(ProjectWindowUtil.GetActiveFolderPath());\n            }\n        }\n\n        static int[] PasteFoldersAfterCopy(string destination = null)\n        {\n            List<string> copiedPaths = new List<string>();\n            bool failed = false;\n            foreach (var item in assetClipboard)\n            {\n                string assetPath = AssetDatabase.GetAssetPath(ObjectIdentifier.ToObject(item));\n                var newPath = AssetDatabase.GenerateUniqueAssetPath(GetValidPath(assetPath, destination));\n\n                if (newPath.Length != 0)\n                    failed |= !AssetDatabase.CopyAsset(assetPath, newPath);\n                else\n                    failed = true;\n\n                if (!failed)\n                {\n                    copiedPaths.Add(newPath);\n                }\n            }\n\n            AssetDatabase.Refresh();\n\n            int[] copiedAssets = new int[copiedPaths.Count];\n            for (int i = 0; i < copiedPaths.Count; i++)\n            {\n                copiedAssets[i] = AssetDatabase.LoadMainAssetAtPath(copiedPaths[i]).GetInstanceID();\n            }\n\n            return copiedAssets;\n        }\n\n        static int[] PasteFoldersAfterCut(string destination = null)\n        {\n            List<string> pastedObjects = new List<string>();\n            string[] assetPaths = new string[assetClipboard.Count];\n\n            int counter = 0;\n            foreach (var item in assetClipboard)\n            {\n                assetPaths[counter] = AssetDatabase.GetAssetPath(ObjectIdentifier.ToObject(item));\n                counter++;\n            }\n\n            if (counter > 0)\n                Undo.RegisterAssetsMoveUndo(assetPaths);\n\n            counter = 0;\n            foreach (var item in assetClipboard)\n            {\n                var assetPath = assetPaths[counter];\n\n                var newPath = AssetDatabase.GenerateUniqueAssetPath(GetValidPath(assetPath, destination));\n                if (String.IsNullOrEmpty(AssetDatabase.MoveAsset(assetPath, newPath)))\n                {\n                    pastedObjects.Add(newPath);\n                    counter++;\n                }\n            }\n\n            Reset();\n            performedAction = PerformedAction.None;\n            AssetDatabase.Refresh();\n\n            int[] copiedAssets = new int[pastedObjects.Count];\n\n            for (int i = 0; i < pastedObjects.Count; i++)\n            {\n                copiedAssets[i] = AssetDatabase.LoadMainAssetAtPath(pastedObjects[i]).GetInstanceID();\n            }\n\n            return copiedAssets;\n        }\n\n        internal static bool CanPaste()\n        {\n            return performedAction != PerformedAction.None;\n        }\n\n        internal static bool HasCutAsset(int instanceID)\n        {\n            if (performedAction == PerformedAction.Cut)\n            {\n                Object obj = EditorUtility.InstanceIDToObject(instanceID);\n                ObjectIdentifier.GetObjectIdentifierFromInstanceID(instanceID, out var identifier);\n                return obj != null && assetClipboard.Contains(identifier);\n            }\n\n            return false;\n        }\n\n        internal static void CancelCut()\n        {\n            Reset();\n            performedAction = PerformedAction.None;\n        }\n\n        static void Reset()\n        {\n            assetClipboard.Clear();\n        }\n\n        static string GetValidPath(string assetPath, string target)\n        {\n            if (target == null)\n                return assetPath;\n\n            string[] pathSplit = assetPath.Split('/');\n            return target + '/' + pathSplit[pathSplit.Length - 1];\n        }\n\n        internal enum PerformedAction\n        {\n            Cut,\n            Copy,\n            None\n        };\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ProjectBrowser/CachedFilteredHierachy.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Experimental;\nusing UnityEngine.Assertions;\n\nnamespace UnityEditor\n{\n    internal partial class FilteredHierarchy\n    {\n        public class FilterResult\n        {\n            public int instanceID;\n            public string name;\n            public bool hasChildren;\n            public int colorCode;\n            public bool isMainRepresentation;\n            public bool hasFullPreviewImage;\n            public IconDrawStyle iconDrawStyle;\n            public bool isFolder;\n            public HierarchyType type;\n            public Texture2D icon\n            {\n                get\n                {\n                    if (m_Icon == null)\n                    {\n                        if (type == HierarchyType.Assets)\n                        {\n                            // Note: Do not set m_Icon as GetCachedIcon uses its own cache that is cleared on reaching a max limit.\n                            // This is because when having e.g very large projects (1000s of textures with unique icons) we do not want all icons loaded\n                            // at the same time so don't keep a reference in m_Icon here\n                            string path = instanceID == 0 ? null : AssetDatabase.GetAssetPath(instanceID);\n\n                            if (path != null)\n                                // Finding icon based on only file extension fails in several ways, and a different approach have to be found.\n                                // Using InternalEditorUtility.FindIconForFile first in revision f25945218bb6 / 29b23dbe4b5c introduced several regressions.\n                                //  - Doesn't support custom user-assigned icons for monoscripts.\n                                //  - Doesn't support open/closed folder icon destinction.\n                                //  - The change only affected Two-Column mode in Project View and not One-Column mode, adding inconsistency.\n                                //  - Doesn't support showing different icons for different prefab types, such as prefab variants.\n                                // Support for specific file types based on file extensiom have to be supported inside AssetDatabase.GetCachedIcon\n                                // itself to work correctly and universally. for e.g. uxml files from within GetCachedIcon without relying on FindIconForFile.\n                                return AssetDatabase.GetCachedIcon(path) as Texture2D;\n\n                            path = string.IsNullOrEmpty(m_Guid) ? null : AssetDatabase.GUIDToAssetPath(m_Guid);\n                            if (path != null)\n                                return UnityEditorInternal.InternalEditorUtility.FindIconForFile(path);\n                        }\n                        else if (type == HierarchyType.GameObjects)\n                        {\n                            // GameObject thumbnail can be set to m_Icon since its an actual icon which means we have a limited set of them\n                            Object go = EditorUtility.InstanceIDToObject(instanceID);\n                            m_Icon = AssetPreview.GetMiniThumbnail(go);\n                        }\n                        else\n                        {\n                            Assert.IsTrue(false, \"Unhandled HierarchyType\");\n                        }\n                    }\n                    return m_Icon;\n                }\n                set\n                {\n                    m_Icon = value;\n                }\n            }\n            private Texture2D m_Icon;\n\n            internal string m_Guid;\n\n            public string guid\n            {\n                get\n                {\n                    if (type == HierarchyType.Assets)\n                    {\n                        if (instanceID != 0 && string.IsNullOrEmpty(m_Guid))\n                        {\n                            string path = AssetDatabase.GetAssetPath(instanceID);\n                            if (path != null)\n                                m_Guid = AssetDatabase.AssetPathToGUID(path);\n                        }\n                        return m_Guid;\n                    }\n                    return null;\n                }\n            }\n        }\n\n        SearchFilter m_SearchFilter = new SearchFilter();\n        FilterResult[] m_Results = new FilterResult[0];     // When filtering of folder we have all sub assets here\n        FilterResult[] m_VisibleItems = new FilterResult[0]; // Subset of m_Results used for showing/hiding sub assets\n\n        SearchService.SceneSearchSessionHandler m_SearchSessionHandler = new SearchService.SceneSearchSessionHandler();\n        SearchService.SearchSessionOptions m_SearchSessionOptions;\n\n        HierarchyType m_HierarchyType;\n\n        public const int maxSearchAddCount = 12000;\n\n        public FilteredHierarchy(HierarchyType type)\n        {\n            m_HierarchyType = type;\n            m_SearchSessionOptions = SearchService.SearchSessionOptions.Default;\n        }\n\n        public FilteredHierarchy(HierarchyType type, SearchService.SearchSessionOptions searchSessionOptions)\n        {\n            m_HierarchyType = type;\n            m_SearchSessionOptions = searchSessionOptions;\n        }\n\n        public HierarchyType hierarchyType\n        {\n            get { return m_HierarchyType; }\n        }\n\n        public FilterResult[] results\n        {\n            get\n            {\n                if (m_VisibleItems.Length > 0)\n                    return m_VisibleItems;\n                return m_Results;\n            }\n        }\n        public SearchFilter searchFilter\n        {\n            get { return m_SearchFilter; }\n            set\n            {\n                if (m_SearchFilter.SetNewFilter(value))\n                    ResultsChanged();\n            }\n        }\n\n        public bool foldersFirst { get; set; }\n\n        public void SetResults(int[] instanceIDs)\n        {\n            var instanceIdSet = new HashSet<int>(instanceIDs);\n            if (m_HierarchyType ==  HierarchyType.Assets)\n            {\n                var idsUnderEachRoot = new Dictionary<string, int>();\n                for (int i = 0; i < instanceIDs.Length; ++i)\n                {\n                    var rootPath = \"Assets\";\n\n                    var path = AssetDatabase.GetAssetPath(instanceIDs[i]);\n                    var packageInfo = PackageManager.PackageInfo.FindForAssetPath(path);\n                    // Find the right rootPath if folderPath is part of a package\n                    if (packageInfo != null)\n                        rootPath = packageInfo.assetPath;\n\n                    if (!idsUnderEachRoot.ContainsKey(rootPath))\n                        idsUnderEachRoot.Add(rootPath, 0);\n                    ++idsUnderEachRoot[rootPath];\n                }\n\n                SetAssetsResults(instanceIdSet, idsUnderEachRoot);\n            }\n            else\n            {\n                HierarchyProperty property = new HierarchyProperty(m_HierarchyType, false);\n                property.Reset();\n\n                System.Array.Resize(ref m_Results, instanceIDs.Length);\n                for (int i = 0; i < instanceIDs.Length; ++i)\n                {\n                    if (property.Find(instanceIDs[i], null))\n                        CopyPropertyData(ref m_Results[i], property);\n                }\n            }\n        }\n\n        internal void SetResults(int[] instanceIDs, string[] rootPaths)\n        {\n            var instanceIdSet = new HashSet<int>(instanceIDs);\n            if (m_HierarchyType == HierarchyType.Assets)\n            {\n                var idsUnderEachRoot = new Dictionary<string, int>();\n                foreach (var rootPath in rootPaths)\n                {\n                    if (!idsUnderEachRoot.ContainsKey(rootPath))\n                        idsUnderEachRoot.Add(rootPath, 0);\n                    ++idsUnderEachRoot[rootPath];\n                }\n                SetAssetsResults(instanceIdSet, idsUnderEachRoot);\n            }\n            else\n            {\n                HierarchyProperty property = new HierarchyProperty(m_HierarchyType, false);\n                property.Reset();\n\n                System.Array.Resize(ref m_Results, instanceIDs.Length);\n                for (int i = 0; i < instanceIDs.Length; ++i)\n                {\n                    if (property.Find(instanceIDs[i], null))\n                        CopyPropertyData(ref m_Results[i], property);\n                }\n            }\n        }\n\n        void SetAssetsResults(HashSet<int> instanceIdsSet, Dictionary<string, int> idsUnderEachRoot)\n        {\n            System.Array.Resize(ref m_Results, instanceIdsSet.Count);\n            var currentResultIndex = 0;\n            var rootPaths = idsUnderEachRoot.Keys.ToArray();\n            var idCounts = idsUnderEachRoot.Values.ToArray();\n            for (var i = 0; i < rootPaths.Length; ++i)\n            {\n                var rootPath = rootPaths[i];\n                var nbIds = idCounts[i];\n                HierarchyProperty property = new HierarchyProperty(rootPath, false);\n                var propertiesFound = 0;\n                while (property.Next(null) && propertiesFound < nbIds)\n                {\n                    var instanceId = property.GetInstanceIDIfImported();\n                    if (instanceIdsSet.Contains(instanceId))\n                    {\n                        ++propertiesFound;\n                        CopyPropertyData(ref m_Results[currentResultIndex], property);\n                        ++currentResultIndex;\n                    }\n                }\n            }\n        }\n\n        void CopyPropertyData(ref FilterResult result, HierarchyProperty property)\n        {\n            if (result == null)\n                result = new FilterResult();\n\n            result.instanceID = property.GetInstanceIDIfImported();\n            result.name = property.name;\n            result.hasChildren = property.hasChildren;\n            result.colorCode = property.colorCode;\n            result.isMainRepresentation = property.isMainRepresentation;\n            result.hasFullPreviewImage = property.hasFullPreviewImage;\n            result.iconDrawStyle = property.iconDrawStyle;\n            result.isFolder = property.isFolder;\n            result.type = hierarchyType;\n\n            // If this is not the main representation, cache the icon, as we don't have an API to access it later.\n            // Otherwise, don't - as this may cause Textures to load unintendedly (e.g if we have 3000 search results we do not want to load icons before needed when rendering)\n            if (!property.isMainRepresentation)\n                result.icon = property.icon;\n            else if (property.isFolder && !property.hasChildren)\n                result.icon = EditorGUIUtility.FindTexture(EditorResources.emptyFolderIconName);\n            else\n                result.icon = null;\n\n            if (m_HierarchyType == HierarchyType.Assets)\n                result.m_Guid = property.guid;\n        }\n\n        void SearchAllAssets(SearchFilter.SearchArea area)\n        {\n            if (m_HierarchyType == HierarchyType.Assets)\n            {\n                List<FilterResult> list = new List<FilterResult>();\n                list.AddRange(m_Results);\n\n                var maxAddCount = maxSearchAddCount;\n                m_SearchFilter.searchArea = area;\n                var enumerator = AssetDatabase.EnumerateAllAssets(m_SearchFilter);\n                while (enumerator.MoveNext() && --maxAddCount >= 0)\n                {\n                    var result = new FilterResult();\n                    CopyPropertyData(ref result, enumerator.Current);\n                    list.Add(result);\n                }\n\n                m_Results = list.ToArray();\n            }\n            else if (m_HierarchyType == HierarchyType.GameObjects)\n            {\n                HierarchyProperty property = new HierarchyProperty(m_HierarchyType, false);\n                m_SearchSessionHandler.BeginSession(() =>\n                {\n                    return new SearchService.SceneSearchContext\n                    {\n                        searchFilter = m_SearchFilter,\n                        rootProperty = property,\n                        requiredTypeNames = m_SearchFilter.classNames,\n                        requiredTypes = searchFilter.classNames.Select(name => TypeCache.GetTypesDerivedFrom<Object>().FirstOrDefault(t => name == t.FullName || name == t.Name))\n                    };\n                }, m_SearchSessionOptions);\n\n                var searchQuery = m_SearchFilter.originalText;\n                m_SearchSessionHandler.BeginSearch(searchQuery);\n\n                if (m_SearchFilter.sceneHandles != null &&\n                    m_SearchFilter.sceneHandles.Length > 0)\n                {\n                    property.SetCustomScenes(m_SearchFilter.sceneHandles);\n                }\n\n                var newResults = new List<FilterResult>();\n                while (property.Next(null))\n                {\n                    if (!m_SearchSessionHandler.Filter(searchQuery, property))\n                        continue;\n                    FilterResult newResult = new FilterResult();\n                    CopyPropertyData(ref newResult, property);\n                    newResults.Add(newResult);\n                }\n                int elements = newResults.Count;\n                elements = Mathf.Min(elements, maxSearchAddCount);\n\n                int i = m_Results.Length;\n                System.Array.Resize(ref m_Results, m_Results.Length + elements);\n                for (var j = 0; j < elements && i < m_Results.Length; ++j, ++i)\n                {\n                    m_Results[i] = newResults[j];\n                }\n\n                m_SearchSessionHandler.EndSearch();\n            }\n        }\n\n        void SearchInFolders()\n        {\n            List<FilterResult> list = new List<FilterResult>();\n            List<string> baseFolders = new List<string>();\n            baseFolders.AddRange(ProjectWindowUtil.GetBaseFolders(m_SearchFilter.folders));\n            if (baseFolders.Remove(PackageManager.Folders.GetPackagesPath()))\n            {\n                var packages = PackageManagerUtilityInternal.GetAllVisiblePackages(m_SearchFilter.skipHidden);\n                foreach (var package in packages)\n                {\n                    if (!baseFolders.Contains(package.assetPath))\n                        baseFolders.Add(package.assetPath);\n                }\n            }\n\n            m_SearchFilter.searchArea = SearchFilter.SearchArea.SelectedFolders;\n            foreach (string folderPath in baseFolders)\n            {\n                // Ensure we do not have a filter when finding folder\n                HierarchyProperty property = new HierarchyProperty(folderPath);\n                property.SetSearchFilter(m_SearchFilter);\n\n                // Set filter after we found the folder\n                int folderDepth = property.depth;\n                int[] expanded = null; // enter all children of folder\n                while (property.NextWithDepthCheck(expanded, folderDepth + 1))\n                {\n                    FilterResult result = new FilterResult();\n                    CopyPropertyData(ref result, property);\n                    list.Add(result);\n                }\n            }\n            m_Results = list.ToArray();\n        }\n\n        void FolderBrowsing()\n        {\n            // We are not concerned with assets being added multiple times as we only show the contents\n            // of each selected folder. This is an issue when searching recursively into child folders.\n            List<FilterResult> list = new List<FilterResult>();\n            HierarchyProperty property;\n            foreach (string folderPath in m_SearchFilter.folders)\n            {\n                if (folderPath == PackageManager.Folders.GetPackagesPath())\n                {\n                    var packages = PackageManagerUtilityInternal.GetAllVisiblePackages(m_SearchFilter.skipHidden);\n                    foreach (var package in packages)\n                    {\n                        var packageFolderInstanceId = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(package.assetPath);\n                        property = new HierarchyProperty(package.assetPath);\n                        if (property.Find(packageFolderInstanceId, null))\n                        {\n                            FilterResult result = new FilterResult();\n                            CopyPropertyData(ref result, property);\n                            result.name = !string.IsNullOrEmpty(package.displayName) ? package.displayName : package.name;\n                            list.Add(result);\n                        }\n                    }\n                    continue;\n                }\n\n                if (m_SearchFilter.skipHidden && !PackageManagerUtilityInternal.IsPathInVisiblePackage(folderPath))\n                    continue;\n\n                int folderInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(folderPath);\n                property = new HierarchyProperty(folderPath);\n                property.SetSearchFilter(m_SearchFilter);\n\n                int folderDepth = property.depth;\n                int[] expanded = { folderInstanceID };\n                Dictionary<string , List<FilterResult>> subAssets = new Dictionary<string, List<FilterResult>>();\n                List<FilterResult> parentAssets = new List<FilterResult>();\n                while (property.Next(expanded))\n                {\n                    if (property.depth <= folderDepth)\n                        break; // current property is outside folder\n\n                    FilterResult result = new FilterResult();\n                    CopyPropertyData(ref result, property);\n                    //list.Add(result);\n\n                    // Fetch sub assets by expanding the main asset (ignore folders)\n                    if (property.hasChildren && !property.isFolder)\n                    {\n                        parentAssets.Add(result);\n                        List<FilterResult>  subAssetList = new List<FilterResult>();\n                        subAssets.Add(result.guid, subAssetList);\n                        System.Array.Resize(ref expanded, expanded.Length + 1);\n                        expanded[expanded.Length - 1] = property.instanceID;\n                    }\n                    else\n                    {\n                        List<FilterResult> subAssetList;\n                        if (subAssets.TryGetValue(result.guid, out subAssetList))\n                        {\n                            subAssetList.Add(result);\n                            subAssets[result.guid] = subAssetList;\n                        }\n                        else\n                        {\n                            parentAssets.Add(result);\n                        }\n                    }\n                }\n                parentAssets.Sort((result1, result2) => EditorUtility.NaturalCompare(result1.name, result2.name));\n                foreach (FilterResult result in parentAssets)\n                {\n                    list.Add(result);\n                    List<FilterResult> subAssetList;\n                    if (subAssets.TryGetValue(result.guid, out subAssetList))\n                    {\n                        subAssetList.Sort((result1, result2) => EditorUtility.NaturalCompare(result1.name, result2.name));\n                        foreach (FilterResult subasset in subAssetList)\n                        {\n                            list.Add(subasset);\n                        }\n                    }\n                }\n            }\n            m_Results = list.ToArray();\n        }\n\n        void AddResults()\n        {\n            switch (m_SearchFilter.GetState())\n            {\n                case SearchFilter.State.FolderBrowsing:          FolderBrowsing();  break;\n                case SearchFilter.State.SearchingInAllAssets:    SearchAllAssets(SearchFilter.SearchArea.AllAssets); break;\n                case SearchFilter.State.SearchingInAssetsOnly:   SearchAllAssets(SearchFilter.SearchArea.InAssetsOnly); break;\n                case SearchFilter.State.SearchingInPackagesOnly: SearchAllAssets(SearchFilter.SearchArea.InPackagesOnly); break;\n                case SearchFilter.State.SearchingInFolders:      SearchInFolders(); break;\n                case SearchFilter.State.EmptySearchFilter: /*do nothing*/ break;\n                default: Debug.LogError(\"Unhandled enum!\"); break;\n            }\n        }\n\n        public void ResultsChanged()\n        {\n            m_Results = new FilterResult[0];\n            if (m_SearchFilter.GetState() != SearchFilter.State.EmptySearchFilter)\n            {\n                AddResults();\n\n                // When filtering on folder we use the order we get from BaseHiearchyProperty.cpp (to keep indented children under parent) otherwise we sort\n                if (m_SearchFilter.IsSearching())\n                {\n                    System.Array.Sort(m_Results, (result1, result2) => EditorUtility.NaturalCompare(result1.name, result2.name));\n                }\n\n                if (foldersFirst)\n                {\n                    for (int nonFolderPos = 0; nonFolderPos < m_Results.Length; ++nonFolderPos)\n                    {\n                        if (m_Results[nonFolderPos].isFolder)\n                            continue;\n\n                        for (int folderPos = nonFolderPos + 1; folderPos < m_Results.Length; ++folderPos)\n                        {\n                            if (!m_Results[folderPos].isFolder)\n                                continue;\n\n                            FilterResult folder = m_Results[folderPos];\n                            int length = folderPos - nonFolderPos;\n                            System.Array.Copy(m_Results, nonFolderPos, m_Results, nonFolderPos + 1, length);\n                            m_Results[nonFolderPos] = folder;\n                            break;\n                        }\n                    }\n                }\n            }\n            else\n            {\n                // Reset visible flags if filter string is empty (see BaseHiearchyProperty::SetSearchFilter)\n                if (m_HierarchyType == HierarchyType.GameObjects)\n                {\n                    HierarchyProperty gameObjects = new HierarchyProperty(HierarchyType.GameObjects, false);\n                    gameObjects.SetSearchFilter(m_SearchFilter);\n                    m_SearchSessionHandler.EndSession();\n                }\n            }\n        }\n\n        public void RefreshVisibleItems(List<int> expandedInstanceIDs)\n        {\n            bool isSearching = m_SearchFilter.IsSearching();\n            List<FilterResult> visibleItems = new List<FilterResult>();\n            for (int i = 0; i < m_Results.Length; ++i)\n            {\n                visibleItems.Add(m_Results[i]);\n                if (m_Results[i].isMainRepresentation && m_Results[i].hasChildren && !m_Results[i].isFolder)\n                {\n                    bool isParentExpanded = expandedInstanceIDs.IndexOf(m_Results[i].instanceID) >= 0;\n                    bool addSubItems = isParentExpanded || isSearching;\n                    int numSubItems = AddSubItemsOfMainRepresentation(i, addSubItems ? visibleItems : null);\n                    i += numSubItems;\n                }\n            }\n\n            m_VisibleItems = visibleItems.ToArray();\n        }\n\n        public List<int> GetSubAssetInstanceIDs(int mainAssetInstanceID)\n        {\n            for (int i = 0; i < m_Results.Length; ++i)\n            {\n                if (m_Results[i].instanceID == mainAssetInstanceID)\n                {\n                    List<int> subAssetInstanceIDs = new List<int>();\n                    int index = i + 1; // Start after the main representation\n                    while (index < m_Results.Length && !m_Results[index].isMainRepresentation)\n                    {\n                        subAssetInstanceIDs.Add(m_Results[index].instanceID);\n                        index++;\n                    }\n                    return subAssetInstanceIDs;\n                }\n            }\n            Debug.LogError(\"Not main rep \" + mainAssetInstanceID);\n            return new List<int>();\n        }\n\n        public int AddSubItemsOfMainRepresentation(int mainRepresentionIndex, List<FilterResult> visibleItems)\n        {\n            int count = 0;\n            int index = mainRepresentionIndex + 1; // Start after the main representation\n            while (index < m_Results.Length && !m_Results[index].isMainRepresentation)\n            {\n                if (visibleItems != null)\n                    visibleItems.Add(m_Results[index]);\n                index++;\n                count++;\n            }\n            return count;\n        }\n    }\n\n    internal class FilteredHierarchyProperty : IHierarchyProperty\n    {\n        FilteredHierarchy m_Hierarchy;\n        int m_Position = -1;\n\n        public static IHierarchyProperty CreateHierarchyPropertyForFilter(FilteredHierarchy filteredHierarchy)\n        {\n            if (filteredHierarchy.searchFilter.GetState() != SearchFilter.State.EmptySearchFilter)\n                return new FilteredHierarchyProperty(filteredHierarchy);\n            else\n                return new HierarchyProperty(filteredHierarchy.hierarchyType, false);\n        }\n\n        public FilteredHierarchyProperty(FilteredHierarchy filter)\n        {\n            m_Hierarchy = filter;\n        }\n\n        public void Reset()\n        {\n            m_Position = -1;\n        }\n\n        public int instanceID\n        {\n            get\n            {\n                var id = m_Hierarchy.results[m_Position].instanceID;\n                if (id == 0)\n                    m_Hierarchy.results[m_Position].instanceID = AssetDatabase.GetMainAssetInstanceID(guid);\n                return m_Hierarchy.results[m_Position].instanceID;\n            }\n        }\n\n        public Object pptrValue\n        {\n            get { return EditorUtility.InstanceIDToObject(instanceID); }\n        }\n\n        public string name\n        {\n            get { return m_Hierarchy.results[m_Position].name; }\n        }\n\n        public bool hasChildren\n        {\n            get { return m_Hierarchy.results[m_Position].hasChildren; }\n        }\n\n        public bool isMainRepresentation\n        {\n            get { return m_Hierarchy.results[m_Position].isMainRepresentation; }\n        }\n\n        public bool hasFullPreviewImage\n        {\n            get { return m_Hierarchy.results[m_Position].hasFullPreviewImage; }\n        }\n\n        public IconDrawStyle iconDrawStyle\n        {\n            get { return m_Hierarchy.results[m_Position].iconDrawStyle; }\n        }\n\n        public bool isFolder\n        {\n            get { return m_Hierarchy.results[m_Position].isFolder; }\n        }\n\n        public GUID[] dynamicDependencies\n        {\n            get { return new GUID[] {}; }\n        }\n\n        public int depth\n        {\n            get { return 0; }\n        }\n\n        public int row\n        {\n            get { return m_Position; }\n        }\n\n        public int colorCode\n        {\n            get { return m_Hierarchy.results[m_Position].colorCode; }\n        }\n\n        public bool IsExpanded(int[] expanded)\n        {\n            return false;\n        }\n\n        public string guid\n        {\n            get { return m_Hierarchy.results[m_Position].guid; }\n        }\n\n        public bool isValid\n        {\n            get { return m_Hierarchy.results != null && m_Position < m_Hierarchy.results.Length && m_Position >= 0; }\n        }\n\n        public Texture2D icon\n        {\n            get { return m_Hierarchy.results[m_Position].icon; }\n        }\n\n        public bool Next(int[] expanded)\n        {\n            m_Position++;\n            return m_Position < m_Hierarchy.results.Length;\n        }\n\n        public bool NextWithDepthCheck(int[] expanded, int minDepth)\n        {\n            // Depth check does not make sense for filtered properties as tree info is lost\n            return Next(expanded);\n        }\n\n        public bool Previous(int[] expanded)\n        {\n            m_Position--;\n            return m_Position >= 0;\n        }\n\n        public bool Parent()\n        {\n            return false;\n        }\n\n        public int[] ancestors\n        {\n            get\n            {\n                return new int[0];\n            }\n        }\n\n        public bool Find(int _instanceID, int[] expanded)\n        {\n            Reset();\n            while (Next(expanded))\n            {\n                if (instanceID == _instanceID)\n                    return true;\n            }\n            return false;\n        }\n\n        public int[] FindAllAncestors(int[] instanceIDs)\n        {\n            return new int[0];\n        }\n\n        public bool Skip(int count, int[] expanded)\n        {\n            m_Position += count;\n            return m_Position < m_Hierarchy.results.Length;\n        }\n\n        public int CountRemaining(int[] expanded)\n        {\n            return m_Hierarchy.results.Length - m_Position - 1;\n        }\n\n        public int GetInstanceIDIfImported()\n        {\n            return m_Hierarchy.results[m_Position].instanceID;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ProjectBrowser/GlobSearchUtilities.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text.RegularExpressions;\n\nnamespace UnityEditor\n{\n    static class GlobSearchUtilities\n    {\n        static readonly Regex k_BasicSymbolsRegex = new Regex(@\"(?<range>\\\\\\[..+?\\])|(?<dstarfold>\\\\\\*\\\\\\*/)|(?<dstar>\\\\\\*\\\\\\*)|(?<star>\\\\\\*)|(?<single>\\\\\\?)\");\n        static readonly Regex k_ComplexSymbolsRegex = new Regex(@\"(?<or>\\\\\\(.+?(?:\\\\\\|.+?)+\\\\\\))\");\n        static Dictionary<string, Func<string, string>> s_GlobToRegexMatch;\n\n        static GlobSearchUtilities()\n        {\n            s_GlobToRegexMatch = new Dictionary<string, Func<string, string>>();\n\n            //Match any number of characters, where characters exist - end in a fold.\n            s_GlobToRegexMatch.Add(\"dstarfold\", match => \"(.+/)?\");\n\n            //Match any number of characters\n            s_GlobToRegexMatch.Add(\"dstar\", match => \".*\");\n\n            //Match any number of non-\"/\" characters\n            s_GlobToRegexMatch.Add(\"star\", match => @\"[^/]*\");\n\n            //Match a single non-\"/\" character\n            s_GlobToRegexMatch.Add(\"single\", match => @\"[^/]\");\n            s_GlobToRegexMatch.Add(\"range\", match => match.Replace(@\"\\[\", \"[\"));\n            s_GlobToRegexMatch.Add(\"or\", match => match.Replace(@\"\\(\", \"(\").Replace(@\"\\|\", \"|\").Replace(@\"\\)\", \")\"));\n        }\n\n        static string GlobToRegex(string glob)\n        {\n            // Escape any glob character that could be interpreted in the regex\n            var regex = Regex.Escape(glob);\n\n            // Handle basic symbols replacement first\n            regex = k_BasicSymbolsRegex.Replace(regex, ReplaceGlobGroups);\n\n            // Complex patterns are replaced in a second pass because they may contain basic symbols that we want to replace first.\n            regex = k_ComplexSymbolsRegex.Replace(regex, ReplaceGlobGroups);\n\n            // Add ^ and $ to make sure the search is always done on the full path.\n            // Searches like \"Editor\" should match the same as \"**Editor\" and looks only for Editor folders or file in any subfolder\n            // This is why we are always adding optional folder path at the beginning and option folder ending character in the end.\n            return $\"^(.+/)?{regex}/?$\";\n        }\n\n        static string ReplaceGlobGroups(Match match)\n        {\n            foreach (var replace in s_GlobToRegexMatch)\n            {\n                if (match.Groups[replace.Key].Success)\n                {\n                    return replace.Value(match.Value);\n                }\n            }\n\n            return match.Value;\n        }\n\n        static bool IsRegexValid(string regex)\n        {\n            try\n            {\n                // Regex.Match throws and ArgumentException when the regex is not valid,\n                // we use this to make sure the generated regex can be used during a search.\n                Regex.Match(\"\", regex);\n            }\n            catch (ArgumentException)\n            {\n                return false;\n            }\n\n            return true;\n        }\n\n        internal static IEnumerable<string> GlobToRegex(this SearchFilter filter)\n        {\n            return filter.globs.Select(GlobToRegex).Where(IsRegexValid);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ProjectBrowser/ProjectBrowser.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.ProjectWindowCallback;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.IO;\nusing System.Text.RegularExpressions;\nusing UnityEditor.AssetImporters;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.PackageManager;\nusing UnityEditor.TreeViewExamples;\nusing UnityEditorInternal;\nusing UnityEngine.Scripting;\nusing Object = UnityEngine.Object;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\n\nnamespace UnityEditor\n{\n    // The title is also used for fetching the project window tab icon: Project.png\n    [EditorWindowTitle(title = \"Project\", icon = \"Project\")]\n    internal class ProjectBrowser : EditorWindow, IHasCustomMenu, ISearchableContainer\n    {\n        public const int kPackagesFolderInstanceId = int.MaxValue;\n        public const int kAssetCreationInstanceID_ForNonExistingAssets = Int32.MaxValue - 1;\n\n        private static readonly Color kFadedOutAssetsColor = new Color(1, 1, 1, 0.5f);\n\n        public static Color GetAssetItemColor(int instanceID)\n        {\n            return (EditorUtility.isInSafeMode && !InternalEditorUtility.AssetReference.IsAssetImported(instanceID)) || AssetClipboardUtility.HasCutAsset(instanceID) ? GUI.color * kFadedOutAssetsColor : GUI.color;\n        }\n\n        private static readonly int[] k_EmptySelection = new int[0];\n\n        private bool isFolderTreeViewContextClicked = false;\n\n        private const string k_WarningImmutableSelectionFormat = \"The operation \\\"{0}\\\" cannot be executed because the selection or package is read-only.\";\n\n        private const string k_WarningRootFolderDeletionFormat = \"The operation \\\"{0}\\\" cannot be executed because the selection is a root folder.\";\n\n        private const string k_ImmutableSelectionActionFormat = \" The operation \\\"{0}\\\" is not allowed in an immutable package.\";\n\n        // Alive ProjectBrowsers\n        private static List<ProjectBrowser> s_ProjectBrowsers = new List<ProjectBrowser>();\n        public static List<ProjectBrowser> GetAllProjectBrowsers()\n        {\n            return s_ProjectBrowsers;\n        }\n\n        public static ProjectBrowser s_LastInteractedProjectBrowser;\n\n        internal enum ItemType\n        {\n            Asset,\n            SavedFilter,\n        }\n\n        enum ViewMode\n        {\n            OneColumn,\n            TwoColumns\n        }\n\n        public enum SearchViewState\n        {\n            NotSearching,\n            AllAssets,\n            InAssetsOnly,\n            InPackagesOnly,\n            SubFolders\n        }\n\n        // Styles used in the object selector\n        class Styles\n        {\n            public GUIStyle bottomBarBg = \"ProjectBrowserBottomBarBg\";\n            public GUIStyle topBarBg = \"ProjectBrowserTopBarBg\";\n            public GUIStyle selectedPathLabel = \"Label\";\n            public GUIStyle exposablePopup = GetStyle(\"ExposablePopupMenu\");\n            public GUIStyle exposablePopupItem = GetStyle(\"ExposablePopupItem\");\n            public GUIStyle lockButton = \"IN LockButton\";\n            public GUIStyle separator = \"ArrowNavigationRight\";\n\n            public GUIContent m_FilterByLabel = EditorGUIUtility.TrIconContent(\"FilterByLabel\", \"Search by Label\");\n            public GUIContent m_FilterByType = EditorGUIUtility.TrIconContent(\"FilterByType\", \"Search by Type\");\n            public GUIContent m_FilterByImportLog = EditorGUIUtility.TrIconContent(\"d_console.erroricon.inactive.sml\", \"Search by Import Log Type\");\n            public GUIContent m_CreateDropdownContent = EditorGUIUtility.IconContent(\"CreateAddNew\");\n            public GUIContent m_SaveFilterContent = EditorGUIUtility.TrIconContent(\"Favorite\", \"Save search\");\n            public GUIContent m_PackageContentDefault = new GUIContent(\"\", \"\");\n            public GUIContent m_PackagesContentNotVisible = EditorGUIUtility.TrIconContent(\"PBrowserPackagesNotVisible\", \"Number of hidden packages, click to display packages.\");\n            public GUIContent m_PackagesContentVisible = EditorGUIUtility.TrIconContent(\"PBrowserPackagesVisible\", \"Number of displayed packages, click to hide packages.\");\n            public GUIContent m_EmptyFolderText = EditorGUIUtility.TrTextContent(\"This folder is empty\");\n            public GUIContent m_SearchIn = EditorGUIUtility.TrTextContent(\"Search:\");\n\n            public Styles()\n            {\n                selectedPathLabel.alignment = TextAnchor.MiddleLeft;\n            }\n\n            static GUIStyle GetStyle(string styleName)\n            {\n                return styleName; // Implicit construction of GUIStyle\n            }\n        }\n\n        static Styles s_Styles;\n        static int s_HashForSearchField = \"ProjectBrowserSearchField\".GetHashCode();\n\n        // Search filter\n        [SerializeField]\n        SearchFilter m_SearchFilter;\n        string m_OldSearch;\n        bool m_SyncSearch;\n\n        [NonSerialized]\n        string m_SearchFieldText = \"\";\n\n        // Display state\n        [SerializeField]\n        ViewMode m_ViewMode = ViewMode.TwoColumns;\n        [SerializeField]\n        int m_StartGridSize = 16;\n        [SerializeField]\n        string[] m_LastFolders = new string[0];\n        [SerializeField]\n        float m_LastFoldersGridSize = -1f;\n        [SerializeField]\n        string m_LastProjectPath;\n        [SerializeField]\n        EditorGUIUtility.EditorLockTracker m_LockTracker = new EditorGUIUtility.EditorLockTracker();\n\n        internal bool isLocked\n        {\n            get { return m_LockTracker.isLocked; }\n            set { m_LockTracker.isLocked = value; }\n        }\n\n        public string searchText => m_SearchFieldText;\n\n        bool m_EnableOldAssetTree = true;\n        bool m_FocusSearchField;\n        string m_SelectedPath;\n        GUIContent m_SelectedPathContent = new GUIContent();\n        bool m_DidSelectSearchResult = false;\n        bool m_ItemSelectedByRightClickThisEvent = false;\n        bool m_InternalSelectionChange = false; // to know when selection change originated in project view itself\n        SearchFilter.SearchArea m_LastLocalAssetsSearchArea = SearchFilter.SearchArea.InAssetsOnly;\n        PopupList.InputData m_AssetLabels;\n        PopupList.InputData m_ObjectTypes;\n        PopupList.InputData m_LogTypes;\n        bool m_UseTreeViewSelectionInsteadOfMainSelection;\n        bool useTreeViewSelectionInsteadOfMainSelection\n        {\n            get { return m_UseTreeViewSelectionInsteadOfMainSelection; }\n            set { m_UseTreeViewSelectionInsteadOfMainSelection = value; }\n        }\n\n\n        // Folder TreeView\n        [SerializeField]\n        TreeViewStateWithAssetUtility m_FolderTreeState;\n        TreeViewController m_FolderTree;\n        int m_TreeViewKeyboardControlID;\n\n        // Full Asset TreeViewState\n        [SerializeField]\n        TreeViewStateWithAssetUtility m_AssetTreeState;\n        TreeViewController m_AssetTree;\n\n        // Icon/List area\n        [SerializeField]\n        ObjectListAreaState m_ListAreaState; // state that survives assembly reloads\n        ObjectListArea m_ListArea;\n        internal ObjectListArea ListArea // Exposed for usage in tests\n        {\n            get { return m_ListArea; }\n\n            // Used for tests only;\n            set { m_ListArea = value; }\n        }\n        int m_ListKeyboardControlID;\n        bool m_GrabKeyboardFocusForListArea = false;\n\n        // List area header: breadcrumbs or search area menu\n        List<KeyValuePair<GUIContent, string>> m_BreadCrumbs = new List<KeyValuePair<GUIContent, string>>();\n        bool m_BreadCrumbLastFolderHasSubFolders = false;\n        ExposablePopupMenu m_SearchAreaMenu;\n\n        // Keep/Skip Hidden Packages\n        [SerializeField]\n        bool m_SkipHiddenPackages;\n\n        // Layout\n        const float k_MinHeight = 250;\n        const float k_MinWidthOneColumn = 230f;// could be 205 with special handling\n        const float k_MinWidthTwoColumns = 230f;\n        static float k_ToolbarHeight => EditorGUI.kWindowToolbarHeight;\n        static float k_BottomBarHeight => EditorGUI.kWindowToolbarHeight;\n        [SerializeField]\n        float m_DirectoriesAreaWidth = k_MinWidthTwoColumns / 2;\n        const float k_ResizerWidth = 5f;\n        const float k_SliderWidth = 55f;\n        [NonSerialized]\n        float m_SearchAreaMenuOffset = -1f;\n        [NonSerialized]\n        Rect m_ListAreaRect;\n        [NonSerialized]\n        Rect m_TreeViewRect;\n        [NonSerialized]\n        Rect m_BottomBarRect;\n        [NonSerialized]\n        Rect m_ListHeaderRect;\n        [NonSerialized]\n        private int m_LastFramedID = -1;\n\n        // Used by search menu bar\n        [NonSerialized]\n        public GUIContent m_SearchAllAssets = EditorGUIUtility.TrTextContent(\"All\");\n        [NonSerialized]\n        public GUIContent m_SearchInPackagesOnly = EditorGUIUtility.TrTextContent(\"In Packages\");\n        [NonSerialized]\n        public GUIContent m_SearchInAssetsOnly = EditorGUIUtility.TrTextContent(\"In Assets\");\n        [NonSerialized]\n        public GUIContent m_SearchInFolders = new GUIContent(\"\"); // updated when needed\n\n        [NonSerialized]\n        private string m_lastSearchFilter;\n        [NonSerialized]\n        private Action m_NextSearchOffDelegate;\n\n        internal static float searchUpdateDelaySeconds => SearchUtils.debounceThresholdMs / 1000f;\n\n        ProjectBrowser()\n        {\n        }\n\n        /* Keep for debugging\n        void TestProjectItemOverlayCallback (string guid, Rect selectionRect)\n        {\n            GUI.Label (selectionRect, GUIContent.none, EditorStyles.helpBox);\n        }*/\n\n        void OnEnable()\n        {\n            titleContent = GetLocalizedTitleContent();\n            s_ProjectBrowsers.Add(this);\n            EditorApplication.projectChanged += OnProjectChanged;\n            EditorApplication.pauseStateChanged += OnPauseStateChanged;\n            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;\n            EditorApplication.assetLabelsChanged += OnAssetLabelsChanged;\n            EditorApplication.assetBundleNameChanged += OnAssetBundleNameChanged;\n            AssemblyReloadEvents.afterAssemblyReload += OnAfterAssemblyReload;\n            s_LastInteractedProjectBrowser = this;\n\n            SearchService.SearchService.syncSearchChanged += OnSyncSearchChanged;\n\n            // Keep for debugging\n            //EditorApplication.projectWindowItemOnGUI += TestProjectItemOverlayCallback;\n        }\n\n        void OnAfterAssemblyReload()\n        {\n            // Repaint to ensure ProjectBrowser UI is initialized. This fixes the issue where a new script is created from the application menu\n            // bar while the project browser ui was not initialized.\n            Repaint();\n        }\n\n        void OnDisable()\n        {\n            SearchService.SearchService.syncSearchChanged -= OnSyncSearchChanged;\n            EditorApplication.pauseStateChanged -= OnPauseStateChanged;\n            EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;\n            EditorApplication.projectChanged -= OnProjectChanged;\n            EditorApplication.assetLabelsChanged -= OnAssetLabelsChanged;\n            EditorApplication.assetBundleNameChanged -= OnAssetBundleNameChanged;\n            AssemblyReloadEvents.afterAssemblyReload -= OnAfterAssemblyReload;\n            s_ProjectBrowsers.Remove(this);\n        }\n\n        private void OnSyncSearchChanged(SearchService.SearchService.SyncSearchEvent evt, string syncViewId, string searchQuery)\n        {\n            if (SearchService.ProjectSearch.HasEngineOverride())\n            {\n                if (evt == SearchService.SearchService.SyncSearchEvent.StartSession)\n                {\n                    m_OldSearch = m_SearchFilter.originalText;\n                }\n\n                if (syncViewId == SearchService.ProjectSearch.GetActiveSearchEngine().GetType().FullName)\n                {\n                    SetSearch(searchQuery);\n                    m_SyncSearch = true;\n                }\n                else if (m_SyncSearch)\n                {\n                    m_SyncSearch = false;\n                    SetSearch(m_OldSearch);\n                    TopBarSearchSettingsChanged();\n                }\n\n                if (evt == SearchService.SearchService.SyncSearchEvent.EndSession)\n                {\n                    m_SyncSearch = false;\n                    TopBarSearchSettingsChanged(false);\n                }\n            }\n        }\n\n        void OnPauseStateChanged(PauseState state)\n        {\n            EndRenaming();\n        }\n\n        void OnPlayModeStateChanged(PlayModeStateChange state)\n        {\n            EndRenaming();\n        }\n\n        void OnAssetLabelsChanged()\n        {\n            if (Initialized()) // Otherwise Init will handle this\n            {\n                SetupAssetLabelList();\n                if (m_SearchFilter.IsSearching())\n                    InitListArea(); // Ensure to refresh search results: we could have results based on previous label settings\n            }\n        }\n\n        void OnAssetBundleNameChanged()\n        {\n            if (m_ListArea != null)\n                InitListArea();\n        }\n\n        void Awake()\n        {\n            if (m_ListAreaState != null)\n            {\n                m_ListAreaState.OnAwake();\n            }\n\n            if (m_FolderTreeState != null)\n            {\n                m_FolderTreeState.OnAwake();\n                m_FolderTreeState.expandedIDs = new List<int>(InternalEditorUtility.expandedProjectWindowItems);\n            }\n\n            if (m_AssetTreeState != null)\n            {\n                m_AssetTreeState.OnAwake();\n                m_AssetTreeState.expandedIDs = new List<int>(InternalEditorUtility.expandedProjectWindowItems);\n            }\n\n            if (m_SearchFilter != null)\n            {\n                EnsureValidFolders();\n            }\n        }\n\n        static internal ItemType GetItemType(int instanceID)\n        {\n            if (SavedSearchFilters.IsSavedFilter(instanceID))\n                return ItemType.SavedFilter;\n\n            return ItemType.Asset;\n        }\n\n        // Return the logical path that user has active. Used when you need to create new assets from outside the project browser.\n        internal string GetActiveFolderPath()\n        {\n            if (m_ViewMode == ViewMode.TwoColumns && m_SearchFilter.GetState() == SearchFilter.State.FolderBrowsing && m_SearchFilter.folders.Length > 0)\n                return m_SearchFilter.folders[0];\n\n            return \"Assets\";\n        }\n\n        private bool IsInsideHiddenPackage(string path)\n        {\n            if (!m_SkipHiddenPackages)\n                return false;\n\n            return !PackageManagerUtilityInternal.IsPathInVisiblePackage(path);\n        }\n\n        void EnsureValidFolders()\n        {\n            if (m_SearchFilter == null)\n                return;\n\n            HashSet<string> validFolders = new HashSet<string>();\n            foreach (string folder in m_SearchFilter.folders)\n            {\n                if (folder == PackageManager.Folders.GetPackagesPath())\n                {\n                    validFolders.Add(folder);\n                    continue;\n                }\n                if (AssetDatabase.IsValidFolder(folder))\n                {\n                    if (IsInsideHiddenPackage(folder))\n                        continue;\n\n                    validFolders.Add(folder);\n                }\n                else\n                {\n                    // The folder does not exist (could have been deleted) now find first valid parent folder\n                    string parentFolder = folder;\n                    for (int i = 0; i < 30; ++i)\n                    {\n                        if (String.IsNullOrEmpty(parentFolder))\n                            break;\n\n                        parentFolder = ProjectWindowUtil.GetContainingFolder(parentFolder);\n                        if (!String.IsNullOrEmpty(parentFolder) && AssetDatabase.IsValidFolder(parentFolder))\n                        {\n                            if (IsInsideHiddenPackage(parentFolder))\n                                continue;\n\n                            validFolders.Add(parentFolder);\n                            break;\n                        }\n                    }\n                }\n            }\n\n            m_SearchFilter.folders = validFolders.ToArray();\n        }\n\n        private void ResetViews()\n        {\n            if (m_AssetTree != null)\n            {\n                m_AssetTree.ReloadData();\n                SetSearchFoldersFromCurrentSelection(); // We could have moved, deleted or renamed a folder so ensure we get folder paths by instanceID\n            }\n\n            if (m_FolderTree != null)\n            {\n                m_FolderTree.ReloadData();\n                SetSearchFolderFromFolderTreeSelection(); // We could have moved, deleted or renamed a folder so ensure we get folders paths by instanceID\n            }\n\n            EnsureValidFolders();\n            if (m_ListArea != null)\n                InitListArea();\n\n            RefreshSelectedPath();\n\n            m_BreadCrumbs.Clear();\n        }\n\n        private void OnProjectChanged()\n        {\n            ResetViews();\n        }\n\n        public bool Initialized()\n        {\n            return m_ListArea != null;\n        }\n\n        public void Init()\n        {\n            if (Initialized())\n                return;\n\n            if (s_Styles == null)\n            {\n                s_Styles = new Styles();\n            }\n\n            m_FocusSearchField = false;\n\n            bool firstTimeInit = m_SearchFilter == null;\n            if (firstTimeInit)\n                m_DirectoriesAreaWidth = Mathf.Min(position.width / 2, 200);\n\n            // m_SearchFilter is serialized\n            if (m_SearchFilter == null)\n                m_SearchFilter = new SearchFilter();\n\n            m_SearchFieldText = m_SearchFilter.FilterToSearchFieldString();\n\n            CalculateRects(); // setup m_TreeViewRect and m_ListAreaRect before calling InitListArea and TreeViews\n            RefreshSelectedPath();\n            SetupDroplists();\n\n            // m_ListAreaState is serialized\n\n            if (m_ListAreaState == null)\n                m_ListAreaState = new ObjectListAreaState();\n            m_ListAreaState.m_RenameOverlay.isRenamingFilename = true;\n\n            m_ListArea = new ObjectListArea(m_ListAreaState, this, false);\n            m_ListArea.allowDeselection = true;\n            m_ListArea.allowDragging = true;\n            m_ListArea.allowFocusRendering = true;\n            m_ListArea.allowMultiSelect = true;\n            m_ListArea.allowRenaming = true;\n            m_ListArea.allowBuiltinResources = false;\n            m_ListArea.allowUserRenderingHook = true;\n            m_ListArea.allowFindNextShortcut = true;\n            m_ListArea.foldersFirst = GetShouldShowFoldersFirst();\n            m_ListArea.repaintCallback += Repaint;\n            m_ListArea.itemSelectedCallback += ListAreaItemSelectedCallback;\n            m_ListArea.keyboardCallback += ListAreaKeyboardCallback;\n            m_ListArea.gotKeyboardFocus += ListGotKeyboardFocus;\n            m_ListArea.drawLocalAssetHeader += DrawLocalAssetHeader;\n            m_ListArea.gridSize = m_StartGridSize;\n\n            m_StartGridSize = Mathf.Clamp(m_StartGridSize, m_ListArea.minGridSize, m_ListArea.maxGridSize);\n            m_LastFoldersGridSize = Mathf.Min(m_LastFoldersGridSize, m_ListArea.maxGridSize);\n\n            m_SearchAreaMenu = new ExposablePopupMenu();\n\n            // m_FolderTreeState is our serialized state (ensure not to reassign it if our serialization system has created it for us)\n            if (m_FolderTreeState == null)\n                m_FolderTreeState = new TreeViewStateWithAssetUtility();\n            m_FolderTreeState.renameOverlay.isRenamingFilename = true;\n\n            // Full asset treeview\n            if (m_AssetTreeState == null)\n                m_AssetTreeState = new TreeViewStateWithAssetUtility();\n            m_AssetTreeState.renameOverlay.isRenamingFilename = true;\n\n            InitViewMode(m_ViewMode);\n\n            EnsureValidSetup();\n\n            RefreshSearchText();\n            SyncFilterGUI();\n            InitListArea();\n        }\n\n        public void SetSearch(string searchString)\n        {\n            SetSearch(SearchFilter.CreateSearchFilterFromString(searchString));\n        }\n\n        public void SetSearch(SearchFilter searchFilter)\n        {\n            if (!Initialized())\n                Init();\n\n            m_SearchFilter = searchFilter;\n            m_SearchFieldText = searchFilter.FilterToSearchFieldString();\n\n            TopBarSearchSettingsChanged();\n        }\n\n        internal void RefreshSearchIfFilterContains(string searchString)\n        {\n            if (!Initialized() || !m_SearchFilter.IsSearching())\n                return;\n\n            if (m_SearchFieldText.IndexOf(searchString) >= 0)\n            {\n                InitListArea();\n            }\n        }\n\n        void SetSearchViewState(SearchViewState state)\n        {\n            switch (state)\n            {\n                case SearchViewState.AllAssets:\n                    m_SearchFilter.searchArea = SearchFilter.SearchArea.AllAssets;\n                    break;\n                case SearchViewState.InAssetsOnly:\n                    m_SearchFilter.searchArea = SearchFilter.SearchArea.InAssetsOnly;\n                    break;\n                case SearchViewState.InPackagesOnly:\n                    m_SearchFilter.searchArea = SearchFilter.SearchArea.InPackagesOnly;\n                    break;\n                case SearchViewState.SubFolders:\n                    m_SearchFilter.searchArea = SearchFilter.SearchArea.SelectedFolders;\n                    break;\n                case SearchViewState.NotSearching:\n                    Debug.LogError(\"Invalid search mode as setter\");\n                    break;\n            }\n\n            // Sync gui to state\n            InitSearchMenu();\n            InitListArea();\n        }\n\n        SearchViewState GetSearchViewState()\n        {\n            switch (m_SearchFilter.GetState())\n            {\n                case SearchFilter.State.SearchingInAllAssets: return SearchViewState.AllAssets;\n                case SearchFilter.State.SearchingInAssetsOnly: return SearchViewState.InAssetsOnly;\n                case SearchFilter.State.SearchingInPackagesOnly: return SearchViewState.InPackagesOnly;\n                case SearchFilter.State.SearchingInFolders: return SearchViewState.SubFolders;\n            }\n            return SearchViewState.NotSearching;\n        }\n\n        void SearchButtonClickedCallback(ExposablePopupMenu.ItemData itemClicked)\n        {\n            if (!itemClicked.m_On) // Behave like radio buttons: a button that is on cannot be turned off\n            {\n                SetSearchViewState((SearchViewState)itemClicked.m_UserData);\n\n                if (m_SearchFilter.searchArea == SearchFilter.SearchArea.AllAssets ||\n                    m_SearchFilter.searchArea == SearchFilter.SearchArea.InAssetsOnly ||\n                    m_SearchFilter.searchArea == SearchFilter.SearchArea.InPackagesOnly ||\n                    m_SearchFilter.searchArea == SearchFilter.SearchArea.SelectedFolders)\n                    m_LastLocalAssetsSearchArea = m_SearchFilter.searchArea;\n            }\n        }\n\n        void InitSearchMenu()\n        {\n            SearchViewState state = GetSearchViewState();\n            if (state == SearchViewState.NotSearching)\n                return;\n\n            List<ExposablePopupMenu.ItemData> buttonData = new List<ExposablePopupMenu.ItemData>();\n\n            GUIStyle onStyle = s_Styles.exposablePopupItem;\n            GUIStyle offStyle = s_Styles.exposablePopupItem;\n            bool hasFolderSelected = m_SearchFilter.folders.Length > 0;\n\n            bool on = state == SearchViewState.AllAssets;\n            buttonData.Add(new ExposablePopupMenu.ItemData(m_SearchAllAssets, on ? onStyle : offStyle, on, true, (int)SearchViewState.AllAssets));\n            on = state == SearchViewState.InPackagesOnly;\n            buttonData.Add(new ExposablePopupMenu.ItemData(m_SearchInPackagesOnly, on ? onStyle : offStyle, on, true, (int)SearchViewState.InPackagesOnly));\n            on = state == SearchViewState.InAssetsOnly;\n            buttonData.Add(new ExposablePopupMenu.ItemData(m_SearchInAssetsOnly, on ? onStyle : offStyle, on, true, (int)SearchViewState.InAssetsOnly));\n            on = state == SearchViewState.SubFolders;\n            buttonData.Add(new ExposablePopupMenu.ItemData(m_SearchInFolders, on ? onStyle : offStyle, on, hasFolderSelected, (int)SearchViewState.SubFolders));\n\n            GUIContent popupButtonContent = m_SearchAllAssets;\n            switch (state)\n            {\n                case SearchViewState.AllAssets:\n                    popupButtonContent = m_SearchAllAssets;\n                    break;\n                case SearchViewState.InPackagesOnly:\n                    popupButtonContent = m_SearchInPackagesOnly;\n                    break;\n                case SearchViewState.InAssetsOnly:\n                    popupButtonContent = m_SearchInAssetsOnly;\n                    break;\n                case SearchViewState.SubFolders:\n                    popupButtonContent = m_SearchInFolders;\n                    break;\n                case SearchViewState.NotSearching:\n                    popupButtonContent = m_SearchInAssetsOnly;\n                    break;\n                default:\n                    Debug.LogError(\"Unhandled enum\");\n                    break;\n            }\n\n            ExposablePopupMenu.PopupButtonData popListData = new ExposablePopupMenu.PopupButtonData(popupButtonContent, s_Styles.exposablePopup);\n            m_SearchAreaMenu.Init(buttonData, 10f, 450f, popListData, SearchButtonClickedCallback);\n        }\n\n        void RefreshSearchText()\n        {\n            if (m_SearchFilter.folders.Length > 0)\n            {\n                string[] baseFolders = ProjectWindowUtil.GetBaseFolders(m_SearchFilter.folders);\n\n                string folderText = \"\";\n                string toolTip = \"\";\n                int maxShow = 3;\n                for (int i = 0; i < baseFolders.Length && i < maxShow; ++i)\n                {\n                    var baseFolder = baseFolders[i];\n                    var packageInfo = PackageManager.PackageInfo.FindForAssetPath(baseFolder);\n                    if (packageInfo != null && !string.IsNullOrEmpty(packageInfo.displayName))\n                        baseFolder = Regex.Replace(baseFolder, @\"^\" + packageInfo.assetPath, PackageManager.Folders.GetPackagesPath() + \"/\" + packageInfo.displayName);\n                    if (i > 0)\n                        folderText += \", \";\n                    string folderName = Path.GetFileName(baseFolder);\n                    folderText += \"'\" + folderName + \"'\";\n\n                    if (i == 0 && folderName != \"Assets\" && folderName != PackageManager.Folders.GetPackagesPath())\n                        toolTip = baseFolder;\n                }\n                if (baseFolders.Length > maxShow)\n                    folderText += \" +\";\n\n                m_SearchInFolders.text = folderText;\n                m_SearchInFolders.tooltip = toolTip;\n            }\n            else\n            {\n                m_SearchInFolders.text = \"Selected folder\";\n                m_SearchInFolders.tooltip = \"\";\n            }\n\n            m_BreadCrumbs.Clear();\n            InitSearchMenu();\n        }\n\n        void EnsureValidSetup()\n        {\n            if (m_LastProjectPath != Directory.GetCurrentDirectory())\n            {\n                // Clear project specific serialized state\n                m_SearchFilter = new SearchFilter();\n                m_LastFolders = new string[0];\n                SyncFilterGUI();\n\n                // If we have a selection try to frame it (could be a non asset object)\n                if (Selection.activeInstanceID != 0)\n                    FrameObjectPrivate(Selection.activeInstanceID, !m_LockTracker.isLocked, false);\n\n                // If we did not frame anything above ensure to show Assets folder in two column mode\n                if (m_ViewMode == ViewMode.TwoColumns && !IsShowingFolderContents())\n                    SelectAssetsFolder();\n\n                m_LastProjectPath = Directory.GetCurrentDirectory();\n            }\n\n            // In two column do not allow empty search filter, at least show the Assets folders\n            if (m_ViewMode == ViewMode.TwoColumns && m_SearchFilter.GetState() == SearchFilter.State.EmptySearchFilter)\n            {\n                SelectAssetsFolder();\n            }\n        }\n\n        void OnGUIAssetCallback(int instanceID, Rect rect)\n        {\n            // User hook for rendering stuff on top of assets\n            if (EditorApplication.projectWindowItemOnGUI != null)\n            {\n                string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(instanceID));\n                EditorApplication.projectWindowItemOnGUI(guid, rect);\n            }\n\n            if (EditorApplication.projectWindowItemInstanceOnGUI != null)\n            {\n                EditorApplication.projectWindowItemInstanceOnGUI(instanceID, rect);\n            }\n        }\n\n        private void InitOneColumnView()\n        {\n            m_AssetTree = new TreeViewController(this, m_AssetTreeState);\n            m_AssetTree.deselectOnUnhandledMouseDown = true;\n            m_AssetTree.selectionChangedCallback += AssetTreeSelectionCallback;\n            m_AssetTree.keyboardInputCallback += AssetTreeKeyboardInputCallback;\n            m_AssetTree.contextClickItemCallback += AssetTreeViewContextClick;\n            m_AssetTree.contextClickOutsideItemsCallback += AssetTreeViewContextClickOutsideItems;\n            m_AssetTree.itemDoubleClickedCallback += AssetTreeItemDoubleClickedCallback;\n            m_AssetTree.onGUIRowCallback += OnGUIAssetCallback;\n            m_AssetTree.dragEndedCallback += AssetTreeDragEnded;\n\n            var data = new AssetsTreeViewDataSource(m_AssetTree, m_SkipHiddenPackages);\n            data.foldersFirst = GetShouldShowFoldersFirst();\n\n            m_AssetTree.Init(m_TreeViewRect,\n                data,\n                new AssetsTreeViewGUI(m_AssetTree),\n                new AssetsTreeViewDragging(m_AssetTree)\n            );\n            m_AssetTree.ReloadData();\n        }\n\n        private void InitTwoColumnView()\n        {\n            m_FolderTree = new TreeViewController(this, m_FolderTreeState);\n            m_FolderTree.deselectOnUnhandledMouseDown = false;\n            m_FolderTree.selectionChangedCallback += FolderTreeSelectionCallback;\n            m_FolderTree.contextClickItemCallback += FolderTreeViewContextClick;\n            m_FolderTree.onGUIRowCallback += OnGUIAssetCallback;\n            m_FolderTree.dragEndedCallback += FolderTreeDragEnded;\n            m_FolderTree.Init(m_TreeViewRect,\n                new ProjectBrowserColumnOneTreeViewDataSource(m_FolderTree, m_SkipHiddenPackages),\n                new ProjectBrowserColumnOneTreeViewGUI(m_FolderTree),\n                new ProjectBrowserColumnOneTreeViewDragging(m_FolderTree)\n            );\n            m_FolderTree.ReloadData();\n        }\n\n        void InitViewMode(ViewMode viewMode)\n        {\n            m_ViewMode = viewMode;\n\n            // Reset\n            m_FolderTree = null;\n            m_AssetTree = null;\n\n            useTreeViewSelectionInsteadOfMainSelection = false;\n\n            switch (m_ViewMode)\n            {\n                case ViewMode.OneColumn:\n                    InitOneColumnView();\n                    break;\n                case ViewMode.TwoColumns:\n                    InitTwoColumnView();\n                    break;\n            }\n\n            float minWidth = (m_ViewMode == ViewMode.OneColumn) ? k_MinWidthOneColumn : k_MinWidthTwoColumns;\n            //if (position.width < minWidth)\n            //  Debug.LogError (\"ProjectBrowser: Ensure that mode cannot be changed resulting in an invalid min width: \" + minWidth + \" (cur width \" + position.width + \")\");\n\n            minSize = new Vector2(minWidth, k_MinHeight);\n            maxSize = new Vector2(10000, 10000);\n        }\n\n        private bool GetShouldShowFoldersFirst()\n        {\n            return Application.platform != RuntimePlatform.OSXEditor;\n        }\n\n        // Called when user changes view mode\n        void SetViewMode(ViewMode newViewMode)\n        {\n            if (m_ViewMode == newViewMode)\n                return;\n\n            EndRenaming();\n            InitViewMode(m_ViewMode == ViewMode.OneColumn ? ViewMode.TwoColumns : ViewMode.OneColumn);\n\n            // Ensure same selection is framed in new view mode\n            if (Selection.activeInstanceID != 0)\n                FrameObjectPrivate(Selection.activeInstanceID, !m_LockTracker.isLocked, false);\n\n            RepaintImmediately();\n        }\n\n        public void EndRenaming()\n        {\n            if (m_AssetTree != null)\n                m_AssetTree.EndNameEditing(true);\n\n            if (m_FolderTree != null)\n                m_FolderTree.EndNameEditing(true);\n\n            if (m_ListArea != null)\n                m_ListArea.EndRename(true);\n        }\n\n        Dictionary<string, string[]> GetTypesDisplayNames()\n        {\n            return new Dictionary<string, string[]>\n            {\n                { \"Animation Clip\", new [] { \"AnimationClip\" } },\n                { \"Audio Clip\", new [] { \"AudioClip\"} },\n                { \"Audio Mixer\", new [] { \"AudioMixer\" } },\n                { \"Compute Shader\", new [] { \"ComputeShader\" } },\n                { \"Font\", new [] { \"Font\" } },\n                { \"GUI Skin\", new [] { \"GUISkin\" } },\n                { \"Graph\", new [] { \"GraphAsset\", \"VisualEffectAsset\", \"ScriptGraphAsset\" } },\n                { \"Material\", new [] { \"Material\" } },\n                { \"Mesh\", new [] { \"Mesh\" } },\n                { \"Model\", new [] { \"Model\" } },\n                { \"Physics Material\", new [] { \"PhysicsMaterial\" } },\n                { \"Prefab\", new [] { \"Prefab\" } },\n                { \"Scene\", new [] { \"Scene\"} },\n                { \"Script\", new [] { \"Script\" } },\n                { \"Shader\", new [] { \"Shader\" } },\n                { \"Sprite\", new [] { \"Sprite\" } },\n                { \"Texture\", new [] { \"Texture\" } },\n                { \"Video Clip\", new [] { \"VideoClip\" } },\n                { \"Visual Effect Asset\", new [] { \"VisualEffectAsset\", \"VisualEffectSubgraph\" } },\n\n                // \"Texture2D\",\n                // \"RenderTexture\",\n                // \"Cubemap\",\n                // \"MovieTexture\",\n            };\n        }\n\n        public void TypeListCallback(PopupList.ListElement element)\n        {\n            if (!Event.current.control)\n            {\n                // Clear all selection except for clicked element\n                foreach (var item in m_ObjectTypes.m_ListElements)\n                    if (item != element)\n                        item.selected = false;\n            }\n\n            // Toggle clicked element\n            element.selected = !element.selected;\n            string[] selectedDisplayNames = m_ObjectTypes.m_ListElements.Where(x => x.selected).SelectMany(x => x.types).ToArray();\n\n            m_SearchFilter.classNames = selectedDisplayNames;\n            m_SearchFieldText = m_SearchFilter.FilterToSearchFieldString();\n\n            TopBarSearchSettingsChanged();\n            Repaint();\n        }\n\n        public void AssetLabelListCallback(PopupList.ListElement element)\n        {\n            if (!Event.current.control)\n            {\n                // Clear all selection except for clicked element\n                foreach (var item in m_AssetLabels.m_ListElements)\n                    if (item != element)\n                        item.selected = false;\n            }\n\n            // Toggle clicked element\n            element.selected = !element.selected;\n            m_SearchFilter.assetLabels = (from item in m_AssetLabels.m_ListElements where item.selected select item.text).ToArray();\n\n            m_SearchFieldText = m_SearchFilter.FilterToSearchFieldString();\n\n            TopBarSearchSettingsChanged();\n            Repaint();\n        }\n\n        public void LogTypeListCallback(PopupList.ListElement element)\n        {\n            if (!Event.current.control)\n            {\n                // Clear all selection except for clicked element\n                foreach (var item in m_LogTypes.m_ListElements)\n                    if (item != element)\n                        item.selected = false;\n            }\n\n            // Toggle clicked element\n            element.selected = !element.selected;\n\n            m_SearchFilter.importLogFlags = element.selected ? (UnityEditor.AssetImporters.ImportLogFlags)Enum.Parse(typeof(UnityEditor.AssetImporters.ImportLogFlags), element.types.First()) : ImportLogFlags.None;\n            m_SearchFieldText = m_SearchFilter.FilterToSearchFieldString();\n\n            TopBarSearchSettingsChanged();\n            Repaint();\n        }\n\n        void SetupDroplists()\n        {\n            SetupAssetLabelList();\n            SetupLogTypeList();\n\n            // Types\n            m_ObjectTypes = new PopupList.InputData();\n            m_ObjectTypes.m_CloseOnSelection = false;\n            m_ObjectTypes.m_AllowCustom = false;\n            m_ObjectTypes.m_OnSelectCallback = TypeListCallback;\n            m_ObjectTypes.m_SortAlphabetically = false;\n            m_ObjectTypes.m_MaxCount = 0;\n            var types = GetTypesDisplayNames();\n            foreach (var keyPair in types)\n            {\n                m_ObjectTypes.AddElement(keyPair.Key, keyPair.Value);\n            }\n            m_ObjectTypes.m_ListElements[0].selected = true;\n        }\n\n        void SetupAssetLabelList()\n        {\n            // List of predefined asset labels (and in the future also user defined ones)\n            Dictionary<string, float> tags = AssetDatabase.GetAllLabels();\n\n            // AssetLabels\n            m_AssetLabels = new PopupList.InputData();\n            m_AssetLabels.m_CloseOnSelection = false;\n            m_AssetLabels.m_AllowCustom = true;\n            m_AssetLabels.m_OnSelectCallback = AssetLabelListCallback;\n            m_AssetLabels.m_MaxCount = 15;\n            m_AssetLabels.m_SortAlphabetically = true;\n\n            foreach (var pair in tags)\n            {\n                PopupList.ListElement element = m_AssetLabels.NewOrMatchingElement(pair.Key);\n                if (element.filterScore < pair.Value)\n                    element.filterScore = pair.Value;\n            }\n        }\n\n        void SetupLogTypeList()\n        {\n            m_LogTypes = new PopupList.InputData();\n            m_LogTypes.m_CloseOnSelection = false;\n            m_LogTypes.m_AllowCustom = false;\n            m_LogTypes.m_OnSelectCallback = LogTypeListCallback;\n            m_LogTypes.m_MaxCount = 2;\n            m_LogTypes.m_SortAlphabetically = true;\n\n            m_LogTypes.AddElement(\"Warnings\", new string[] { \"Warning\" });\n            m_LogTypes.AddElement(\"Errors\", new string[] { \"Error\" });\n        }\n\n        void SyncFilterGUI()\n        {\n            // Sync Labels\n            List<string> assetLabels = new List<string>(m_SearchFilter.assetLabels);\n            foreach (PopupList.ListElement item in m_AssetLabels.m_ListElements)\n                item.selected = assetLabels.Contains(item.text);\n\n            // Sync Type\n            List<string> classNames = new List<string>(m_SearchFilter.classNames);\n            foreach (PopupList.ListElement item in m_ObjectTypes.m_ListElements)\n                item.selected = classNames.Contains(item.text);\n\n            // Sync Text field\n            m_SearchFieldText = m_SearchFilter.FilterToSearchFieldString();\n        }\n\n        void ShowFolderContents(int folderInstanceID, bool revealAndFrameInFolderTree)\n        {\n            if (m_ViewMode != ViewMode.TwoColumns)\n                Debug.LogError(\"ShowFolderContents should only be called in two column mode\");\n\n            if (folderInstanceID == 0)\n                return;\n\n            string folderPath = AssetDatabase.GetAssetPath(folderInstanceID);\n            if (folderInstanceID == kPackagesFolderInstanceId)\n                folderPath = PackageManager.Folders.GetPackagesPath();\n\n            if (!m_SkipHiddenPackages || PackageManagerUtilityInternal.IsPathInVisiblePackage(folderPath))\n            {\n                m_SearchFilter.ClearSearch();\n                m_SearchFilter.folders = new[] { folderPath };\n                m_SearchFilter.skipHidden = m_SkipHiddenPackages;\n                m_FolderTree.SetSelection(new[] { folderInstanceID }, revealAndFrameInFolderTree);\n                FolderTreeSelectionChanged(true);\n            }\n        }\n\n        bool IsShowingFolderContents()\n        {\n            return m_SearchFilter.folders.Length > 0;\n        }\n\n        void ListGotKeyboardFocus()\n        {\n        }\n\n        void ListAreaKeyboardCallback()\n        {\n            if (Event.current.type == EventType.KeyDown)\n            {\n                switch (Event.current.keyCode)\n                {\n                    case KeyCode.Return:\n                    case KeyCode.KeypadEnter:\n                        if (Application.platform == RuntimePlatform.OSXEditor)\n                        {\n                            if (m_ListArea.BeginRename(0f))\n                                Event.current.Use();\n                        }\n                        else // WindowsEditor\n                        {\n                            Event.current.Use();\n                            OpenListAreaSelection();\n                        }\n                        break;\n\n                    case KeyCode.DownArrow:\n                        if (Application.platform == RuntimePlatform.OSXEditor && Event.current.command)\n                        {\n                            Event.current.Use();\n                            OpenListAreaSelection();\n                        }\n                        break;\n                    case KeyCode.UpArrow:\n                        if (Application.platform == RuntimePlatform.OSXEditor && Event.current.command && m_ViewMode == ViewMode.TwoColumns)\n                        {\n                            ShowParentFolderOfCurrentlySelected();\n                            Event.current.Use();\n                        }\n                        break;\n                    case KeyCode.Backspace:\n                        if (Application.platform != RuntimePlatform.OSXEditor && m_ViewMode == ViewMode.TwoColumns)\n                        {\n                            ShowParentFolderOfCurrentlySelected();\n                            Event.current.Use();\n                        }\n                        break;\n                    case KeyCode.F2:\n                        if (Application.platform != RuntimePlatform.OSXEditor)\n                        {\n                            if (m_ListArea.BeginRename(0f))\n                                Event.current.Use();\n                        }\n                        break;\n                }\n            }\n        }\n\n        void ShowParentFolderOfCurrentlySelected()\n        {\n            if (IsShowingFolderContents())\n            {\n                int[] selectedFolderInstanceIDs = m_FolderTree.GetSelection();\n                if (selectedFolderInstanceIDs.Length == 1)\n                {\n                    TreeViewItem item = m_FolderTree.FindItem(selectedFolderInstanceIDs[0]);\n                    if (item != null && item.parent != null && item.id != AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(\"Assets\"))\n                    {\n                        SetFolderSelection(new[] { item.parent.id }, true);\n                        m_ListArea.Frame(item.id, true, false);\n                        Selection.activeInstanceID = item.id;\n                    }\n                }\n            }\n        }\n\n        void OpenListAreaSelection()\n        {\n            int[] selectedInstanceIDs = m_ListArea.GetSelection();\n            int selectionCount = selectedInstanceIDs.Length;\n            if (selectionCount > 0)\n            {\n                int numFolders = 0;\n                foreach (int instanceID in selectedInstanceIDs)\n                    if (ProjectWindowUtil.IsFolder(instanceID))\n                        numFolders++;\n\n                bool allFolders = numFolders == selectionCount;\n                if (allFolders)\n                {\n                    OpenSelectedFolders();\n                    GUIUtility.ExitGUI(); // Exit because if we are mouse clicking to open we are in the middle of iterating list area items..\n                }\n                else\n                {\n                    // If any assets in selection open them instead of opening folder\n                    OpenAssetSelection(selectedInstanceIDs);\n\n                    Repaint();\n                    GUIUtility.ExitGUI(); // Exit because if we are mouse clicking to open we are in the middle of iterating list area items..\n                }\n            }\n        }\n\n        static void OpenAssetSelection(int[] selectedInstanceIDs)\n        {\n            foreach (int id in selectedInstanceIDs)\n            {\n                if (AssetDatabase.Contains(id))\n                    AssetDatabase.OpenAsset(id);\n            }\n            GUIUtility.ExitGUI();\n        }\n\n        void SetAsLastInteractedProjectBrowser()\n        {\n            s_LastInteractedProjectBrowser = this;\n        }\n\n        void RefreshSelectedPath()\n        {\n            if (Selection.activeObject != null)\n            {\n                m_SelectedPath = AssetDatabase.GetAssetPath(Selection.activeObject);\n                if (!string.IsNullOrEmpty(m_SelectedPath) && IsInsideHiddenPackage(m_SelectedPath))\n                {\n                    m_SelectedPath = string.Empty;\n                    Selection.activeObject = null;\n                }\n            }\n            else\n            {\n                m_SelectedPath = string.Empty;\n            }\n\n            if (!string.IsNullOrEmpty(m_SelectedPath))\n            {\n                m_SelectedPathContent = new GUIContent(m_SelectedPath, AssetDatabase.GetCachedIcon(m_SelectedPath))\n                {\n                    tooltip = m_SelectedPath\n                };\n            }\n            else\n            {\n                m_SelectedPathContent = new GUIContent();\n            }\n        }\n\n        static void OpenSelectedFolders()\n        {\n            ProjectBrowser projectBrowser = s_LastInteractedProjectBrowser;\n\n            if (projectBrowser != null)\n            {\n                int[] selectedInstanceIDs = projectBrowser.m_ListArea?.GetSelection();\n\n                if (selectedInstanceIDs == null || selectedInstanceIDs.Length == 0)\n                    return;\n\n                projectBrowser.EndPing();\n\n                if (projectBrowser.m_ViewMode == ViewMode.TwoColumns)\n                {\n                    projectBrowser.SetFolderSelection(selectedInstanceIDs, false);\n                }\n                else if (projectBrowser.m_ViewMode == ViewMode.OneColumn)\n                {\n                    projectBrowser.ClearSearch(); // shows tree instead of search\n                    projectBrowser.m_AssetTree.Frame(selectedInstanceIDs[0], true, false);\n                    projectBrowser.m_AssetTree.data.SetExpanded(selectedInstanceIDs[0], true);\n                }\n\n                projectBrowser.Repaint();\n            }\n        }\n\n        // Called from EditorHelper\n        [RequiredByNativeCode]\n        static void OpenSelectedFoldersInInternalExplorer()\n        {\n            if (!IsFolderTreeViewContextClick())\n            {\n                OpenSelectedFolders();\n            }\n        }\n\n        // Also called from list when navigating by keys\n        void ListAreaItemSelectedCallback(bool doubleClicked)\n        {\n            SetAsLastInteractedProjectBrowser();\n\n            int[] instanceIDs = m_ListArea.GetSelection();\n            if (instanceIDs.Length > 0)\n            {\n                Selection.instanceIDs = instanceIDs;\n                m_SearchFilter.searchArea = m_LastLocalAssetsSearchArea; // local asset was selected\n                m_InternalSelectionChange = true;\n            }\n            else\n            {\n                Selection.activeObject = null;\n            }\n\n            if (Selection.instanceIDs != m_ListArea.GetSelection())\n            {\n                m_ListArea.InitSelection(Selection.instanceIDs);\n            }\n\n            m_FocusSearchField = false;\n\n            if (Event.current.button == 1 && Event.current.type == EventType.MouseDown)\n                m_ItemSelectedByRightClickThisEvent = true;\n\n            RefreshSelectedPath();\n\n            m_DidSelectSearchResult = m_SearchFilter.IsSearching();\n\n            if (doubleClicked)\n                OpenListAreaSelection();\n        }\n\n        void OnGotFocus()\n        {\n        }\n\n        void OnLostFocus()\n        {\n            isFolderTreeViewContextClicked = false;\n            // Added because this window uses RenameOverlay\n            EndRenaming();\n        }\n\n        bool CanFrameAsset(int instanceID)\n        {\n            var path = AssetDatabase.GetAssetPath(instanceID);\n            if (string.IsNullOrEmpty(path))\n                return false;\n\n            HierarchyProperty h = new HierarchyProperty(HierarchyType.Assets, false);\n            if (h.Find(instanceID, null))\n                return true;\n\n            var packageInfo = PackageManager.PackageInfo.FindForAssetPath(path);\n            if (packageInfo != null)\n            {\n                h = new HierarchyProperty(packageInfo.assetPath, false);\n                if (h.Find(instanceID, null))\n                    return true;\n            }\n            return false;\n        }\n\n        void OnSelectionChange()\n        {\n            // We do not want to init our UI on OnSelectionChange because EditorStyles might not be allocated yet (at play/stop)\n            if (m_ListArea == null)\n                return;\n\n            // Keep for debugging\n            //Debug.Log (\"OnSelectionChange (ProjectBrowser): \" + DebugUtils.ListToString(new List<int>(Selection.instanceIDs)));\n\n            // The list area selection state is based on the main selection (both in search mode and folderbrowsing)\n            m_ListArea.InitSelection(Selection.instanceIDs);\n\n            int instanceID = Selection.instanceIDs.Length > 0 ? Selection.instanceIDs[Selection.instanceIDs.Length - 1] : 0;\n            if (m_ViewMode == ViewMode.OneColumn)\n            {\n                // If searching we are not showing the asset tree but we set selection anyways to ensure its\n                // setup when clearing search\n                bool revealSelectionAndFrameLast = !m_LockTracker.isLocked && CanFrameAsset(instanceID) && Selection.instanceIDs.Length <= 1;\n                m_AssetTree.SetSelection(Selection.instanceIDs, revealSelectionAndFrameLast);\n            }\n            else if (m_ViewMode == ViewMode.TwoColumns)\n            {\n                if (!m_InternalSelectionChange)\n                {\n                    bool frame = !m_LockTracker.isLocked && Selection.instanceIDs.Length > 0 && CanFrameAsset(instanceID);\n                    if (frame)\n                    {\n                        // If searching we keep the search when framing. If folder browsing we change folder\n                        // and frame current selection in its folder\n                        if (m_SearchFilter.IsSearching())\n                        {\n                            m_ListArea.Frame(instanceID, true, false);\n                        }\n                        else\n                        {\n                            FrameObjectInTwoColumnMode(instanceID, true, false);\n                        }\n                    }\n                }\n            }\n\n            m_InternalSelectionChange = false;\n\n            RefreshSelectedPath();\n            Repaint();\n        }\n\n        void SetFoldersInSearchFilter(int[] selectedInstanceIDs)\n        {\n            m_SearchFilter.folders = GetFolderPathsFromInstanceIDs(selectedInstanceIDs);\n            EnsureValidFolders();\n\n            if (selectedInstanceIDs.Length > 0)\n            {\n                if (m_LastFoldersGridSize > 0)\n                    m_ListArea.gridSize = (int)m_LastFoldersGridSize;\n            }\n        }\n\n        internal void SetFolderSelection(int[] selectedInstanceIDs, bool revealSelectionAndFrameLastSelected)\n        {\n            SetFolderSelection(selectedInstanceIDs, revealSelectionAndFrameLastSelected, true);\n        }\n\n        private void SetFolderSelection(int[] selectedInstanceIDs, bool revealSelectionAndFrameLastSelected, bool folderWasSelected)\n        {\n            m_FolderTree.SetSelection(selectedInstanceIDs, revealSelectionAndFrameLastSelected);\n            SetFoldersInSearchFilter(selectedInstanceIDs);\n            FolderTreeSelectionChanged(folderWasSelected);\n        }\n\n        void AssetTreeItemDoubleClickedCallback(int instanceID)\n        {\n            OpenAssetSelection(Selection.instanceIDs);\n        }\n\n        void AssetTreeKeyboardInputCallback()\n        {\n            if (Event.current.type == EventType.KeyDown)\n            {\n                switch (Event.current.keyCode)\n                {\n                    case KeyCode.Return:\n                    case KeyCode.KeypadEnter:\n                        if (Application.platform == RuntimePlatform.WindowsEditor)\n                        {\n                            Event.current.Use();\n                            OpenAssetSelection(Selection.instanceIDs);\n                        }\n                        break;\n\n                    case KeyCode.DownArrow:\n                        if (Application.platform == RuntimePlatform.OSXEditor && Event.current.command)\n                        {\n                            Event.current.Use();\n                            OpenAssetSelection(Selection.instanceIDs);\n                        }\n                        break;\n                }\n            }\n        }\n\n        void AssetTreeSelectionCallback(int[] selectedTreeViewInstanceIDs)\n        {\n            SetAsLastInteractedProjectBrowser();\n\n            if (selectedTreeViewInstanceIDs.Length > 0)\n                Selection.SetSelectionWithActiveInstanceID(selectedTreeViewInstanceIDs, selectedTreeViewInstanceIDs[0]);\n            else\n                Selection.activeInstanceID = 0;\n\n            // The selection could be cancelled if an Inspector with hasUnsavedChanges is opened.\n            // In that case, let's update the tree so the highlight is set back to the actual selection.\n            if (Selection.instanceIDs != selectedTreeViewInstanceIDs)\n                m_AssetTree.SetSelection(Selection.instanceIDs, true);\n\n            RefreshSelectedPath();\n            SetSearchFoldersFromCurrentSelection();\n            RefreshSearchText();\n        }\n\n        void SetSearchFoldersFromCurrentSelection()\n        {\n            HashSet<string> folders = new HashSet<string>();\n\n            foreach (int instanceID in Selection.instanceIDs)\n            {\n                if (instanceID == kPackagesFolderInstanceId)\n                {\n                    folders.Add(PackageManager.Folders.GetPackagesPath());\n                    continue;\n                }\n\n                if (!AssetDatabase.Contains(instanceID))\n                    continue;\n\n                string path = AssetDatabase.GetAssetPath(instanceID);\n                if (AssetDatabase.IsValidFolder(path))\n                {\n                    if (IsInsideHiddenPackage(path))\n                        continue;\n\n                    folders.Add(path);\n                }\n                else\n                {\n                    // Add containing folder of the selected asset\n                    string folderPath = ProjectWindowUtil.GetContainingFolder(path);\n                    if (!String.IsNullOrEmpty(folderPath))\n                    {\n                        if (IsInsideHiddenPackage(folderPath))\n                            continue;\n\n                        folders.Add(folderPath);\n                    }\n                }\n            }\n\n            // Set them as folders in search filter (so search in folder works correctly)\n            m_SearchFilter.folders = ProjectWindowUtil.GetBaseFolders(folders.ToArray());\n\n            // Keep for debugging\n            // Debug.Log (\"Search folders: \" + DebugUtils.ListToString(new List<string>(m_SearchFilter.folders)));\n        }\n\n        void SetSearchFolderFromFolderTreeSelection()\n        {\n            if (m_FolderTree == null)\n                return;\n\n            m_SearchFilter.folders = GetFolderPathsFromInstanceIDs(m_FolderTree.GetSelection());\n\n            if (m_SearchFilter.folders.Length != 0)\n                return;\n\n            //If we fail to find the folder path from the selected ID then probably the selection could be from Favorites.\n            //At any point of time there can only be one selection from Favorites..\n            //The Favorites have a custom InstanceID(starting from 1000000000) different from Assets and are saved in a cache,\n            //Since we cant get the path from the AssetsUtility with these InstanceIDs we need to get them from cache.\n            if (m_FolderTree.GetSelection().Length == 1)\n            {\n                int selectionID = m_FolderTree.GetSelection()[0];\n                ItemType type = GetItemType(selectionID);\n                if (type == ItemType.SavedFilter)\n                {\n                    SearchFilter filter = SavedSearchFilters.GetFilter(selectionID);\n\n                    // Check if the filter is valid (the root of filters are not an actual filter)\n                    if (ValidateFilter(selectionID, filter))\n                    {\n                        m_SearchFilter = filter;\n                    }\n                }\n            }\n        }\n\n        void FolderTreeSelectionCallback(int[] selectedTreeViewInstanceIDs)\n        {\n            SetAsLastInteractedProjectBrowser();\n\n            // Assumes only asset folders can be multi selected\n            int firstTreeViewInstanceID = 0;\n            if (selectedTreeViewInstanceIDs.Length > 0)\n                firstTreeViewInstanceID = selectedTreeViewInstanceIDs[0];\n\n            bool folderWasSelected = false;\n            if (firstTreeViewInstanceID != 0)\n            {\n                ItemType type = GetItemType(firstTreeViewInstanceID);\n\n                if (type == ItemType.Asset)\n                {\n                    SetFoldersInSearchFilter(selectedTreeViewInstanceIDs);\n\n                    folderWasSelected = true;\n                }\n\n                if (type == ItemType.SavedFilter)\n                {\n                    SearchFilter filter = SavedSearchFilters.GetFilter(firstTreeViewInstanceID);\n\n                    // Check if the filter is valid (the root of filters are not an actual filter)\n                    if (ValidateFilter(firstTreeViewInstanceID, filter))\n                    {\n                        m_SearchFilter = filter;\n                        EnsureValidFolders();\n                        float previewSize = filter.GetState() == SearchFilter.State.FolderBrowsing ?\n                            m_LastFoldersGridSize :\n                            SavedSearchFilters.GetPreviewSize(firstTreeViewInstanceID);\n                        if (previewSize > 0f)\n                            m_ListArea.gridSize = Mathf.Clamp((int)previewSize, m_ListArea.minGridSize, m_ListArea.maxGridSize);\n                        SyncFilterGUI();\n                    }\n                }\n            }\n\n            FolderTreeSelectionChanged(folderWasSelected);\n        }\n\n        bool ValidateFilter(int savedFilterID, SearchFilter filter)\n        {\n            if (filter == null)\n                return false;\n\n            // Folder validation\n            SearchFilter.State state = filter.GetState();\n            if (state == SearchFilter.State.FolderBrowsing || state == SearchFilter.State.SearchingInFolders)\n            {\n                foreach (string folderPath in filter.folders)\n                {\n                    int instanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(folderPath);\n                    if (instanceID == 0)\n                    {\n                        if (EditorUtility.DisplayDialog(\"Folder not found\", \"The folder '\" + folderPath + \"' might have been deleted or belong to another project. Do you want to delete the favorite?\", \"Delete\", \"Cancel\"))\n                        {\n                            SavedSearchFilters.RemoveSavedFilter(savedFilterID);\n                            GUIUtility.ExitGUI(); // exit gui since we are iterating items we just reloaded\n                        }\n\n                        return false;\n                    }\n                }\n            }\n            return true;\n        }\n\n        void ShowAndHideFolderTreeSelectionAsNeeded()\n        {\n            if (m_ViewMode == ViewMode.TwoColumns && m_FolderTree != null)\n            {\n                bool isSavedFilterSelected = false;\n                int[] selection = m_FolderTree.GetSelection();\n                if (selection.Length > 0)\n                {\n                    isSavedFilterSelected = GetItemType(selection[0]) == ItemType.SavedFilter;\n                }\n\n                SearchViewState state = GetSearchViewState();\n                switch (state)\n                {\n                    case SearchViewState.AllAssets:\n                    case SearchViewState.InAssetsOnly:\n                    case SearchViewState.InPackagesOnly:\n                    case SearchViewState.SubFolders:\n                    case SearchViewState.NotSearching:\n                        {\n                            if (!isSavedFilterSelected)\n                                m_FolderTree.SetSelection(GetFolderInstanceIDs(m_SearchFilter.folders), true);\n                        }\n                        break;\n                }\n            }\n        }\n\n        // This method is being used by the EditorTests/Searching tests\n        public string[] GetCurrentVisibleNames()\n        {\n            return m_ListArea.GetCurrentVisibleNames();\n        }\n\n        void InitListArea()\n        {\n            ShowAndHideFolderTreeSelectionAsNeeded();\n\n            m_SearchFilter.skipHidden = m_SkipHiddenPackages;\n\n            m_ListArea?.InitForSearch(m_ListAreaRect, HierarchyType.Assets,\n                m_SearchFilter, false,\n                s => AssetDatabase.GetMainAssetInstanceID(s));\n            m_ListArea?.InitSelection(Selection.instanceIDs);\n        }\n\n        void OnInspectorUpdate()\n        {\n            if (m_ListArea != null)\n                m_ListArea.OnInspectorUpdate();\n        }\n\n        void OnDestroy()\n        {\n            if (m_ListArea != null)\n                m_ListArea.OnDestroy();\n\n            if (this == s_LastInteractedProjectBrowser)\n                s_LastInteractedProjectBrowser = null;\n        }\n\n        static void DeleteFilter(int filterInstanceID)\n        {\n            if (SavedSearchFilters.GetRootInstanceID() == filterInstanceID)\n            {\n                string title = \"Cannot Delete\";\n                EditorUtility.DisplayDialog(title, \"Deleting the 'Filters' root is not allowed\", \"OK\");\n            }\n            else\n            {\n                string title = \"Delete selected favorite?\";\n                if (EditorUtility.DisplayDialog(title, \"You cannot undo this action.\", \"Delete\", \"Cancel\"))\n                {\n                    SavedSearchFilters.RemoveSavedFilter(filterInstanceID);\n                }\n            }\n        }\n\n        [UsedByNativeCode]\n        internal static string GetSelectedPath()\n        {\n            if (s_LastInteractedProjectBrowser == null)\n                return string.Empty;\n\n            return s_LastInteractedProjectBrowser.m_SelectedPath;\n        }\n\n        // Also called from C++ (used for AssetsMenu check if selection is Packages folder)\n        [UsedByNativeCode]\n        internal static bool SelectionIsPackagesRootFolder()\n        {\n            var pb = s_LastInteractedProjectBrowser;\n            if (pb == null)\n                return false;\n\n            if (pb.m_ViewMode == ViewMode.OneColumn &&\n                pb.m_AssetTree != null &&\n                pb.m_AssetTree.IsSelected(kPackagesFolderInstanceId))\n            {\n                return true;\n            }\n\n            if (pb.m_ViewMode == ViewMode.TwoColumns &&\n                (pb.useTreeViewSelectionInsteadOfMainSelection || Selection.activeInstanceID == 0) &&\n                pb.m_FolderTree != null &&\n                pb.m_FolderTree.IsSelected(kPackagesFolderInstanceId))\n            {\n                return true;\n            }\n\n            return Selection.activeInstanceID == kPackagesFolderInstanceId;\n        }\n\n        private static bool ShouldDiscardCommandsEventsForImmutablePackages()\n        {\n            var evt = Event.current;\n            if ((evt.type == EventType.ExecuteCommand || evt.type == EventType.ValidateCommand || evt.keyCode == KeyCode.Escape) &&\n                (evt.commandName == EventCommandNames.Cut ||\n                 evt.commandName == EventCommandNames.Paste ||\n                 evt.commandName == EventCommandNames.Delete ||\n                 evt.commandName == EventCommandNames.SoftDelete ||\n                 evt.commandName == EventCommandNames.Duplicate))\n            {\n                if (AssetsMenuUtility.SelectionHasImmutable())\n                    return true;\n\n                if (SelectionIsPackagesRootFolder())\n                    return true;\n            }\n\n            return false;\n        }\n\n        private static bool ShouldDiscardCommandsEventsForRootFolders()\n        {\n            return ((Event.current.type == EventType.ExecuteCommand || Event.current.type == EventType.ValidateCommand) &&\n                Event.current.commandName == EventCommandNames.Delete ||\n                Event.current.commandName == EventCommandNames.SoftDelete)\n                && !CanDeleteSelectedAssets();\n        }\n\n        void HandleCommandEventsForTreeView()\n        {\n            // Handle all event for tree view\n            var evt = Event.current;\n            EventType eventType = evt.type;\n            if (eventType == EventType.ExecuteCommand || eventType == EventType.ValidateCommand)\n            {\n                bool execute = eventType == EventType.ExecuteCommand;\n\n                int[] instanceIDs = m_FolderTree.GetSelection();\n                if (instanceIDs.Length == 0)\n                    return;\n\n                // Only one type can be selected at a time (and savedfilters can only be single-selected)\n                ItemType itemType = GetItemType(instanceIDs[0]);\n\n                // Check if event made on immutable package\n                if (itemType == ItemType.Asset)\n                {\n                    if (ShouldDiscardCommandsEventsForImmutablePackages())\n                    {\n                        EditorUtility.DisplayDialog(L10n.Tr(\"Invalid Operation\"), L10n.Tr(string.Format(k_ImmutableSelectionActionFormat, Event.current.commandName)), L10n.Tr(\"OK\"));\n                        return;\n                    }\n                    if (ShouldDiscardCommandsEventsForRootFolders())\n                    {\n                        EditorUtility.DisplayDialog(L10n.Tr(\"Invalid Operation\"), L10n.Tr(\"Deleting a root folder is not allowed.\"), L10n.Tr(\"OK\"));\n                        return;\n                    }\n                }\n\n                if (evt.commandName == EventCommandNames.Delete || evt.commandName == EventCommandNames.SoftDelete)\n                {\n                    evt.Use();\n                    if (execute)\n                    {\n                        if (itemType == ItemType.SavedFilter)\n                        {\n                            System.Diagnostics.Debug.Assert(instanceIDs.Length == 1); //We do not support multiselection for filters\n                            DeleteFilter(instanceIDs[0]);\n                            GUIUtility.ExitGUI(); // exit gui since we are iterating items we just reloaded\n                        }\n                        else if (itemType == ItemType.Asset)\n                        {\n                            bool askIfSure = Event.current.commandName == EventCommandNames.SoftDelete;\n                            DeleteSelectedAssets(askIfSure);\n                            if (askIfSure)\n                                Focus(); // Workaround that we do not get focus back when dialog is closed\n                        }\n                    }\n                    GUIUtility.ExitGUI();\n                }\n                else if (evt.commandName == EventCommandNames.Duplicate)\n                {\n                    if (execute)\n                    {\n                        if (itemType == ItemType.SavedFilter)\n                        {\n                            // TODO copy filter (get new name as assets)\n                        }\n                        else if (itemType == ItemType.Asset)\n                        {\n                            evt.Use();\n                            int[] copiedFolders = AssetClipboardUtility.DuplicateFolders(instanceIDs);\n                            SetFolderSelection(copiedFolders, true);\n                            GUIUtility.ExitGUI();\n                        }\n                    }\n                    else\n                    {\n                        evt.Use();\n                    }\n                }\n                else if (evt.commandName == EventCommandNames.Cut)\n                {\n                    evt.Use();\n                    if (execute && itemType == ItemType.Asset)\n                    {\n                        AssetClipboardUtility.CutCopySelectedFolders(instanceIDs, AssetClipboardUtility.PerformedAction.Cut);\n                        GUIUtility.ExitGUI();\n                    }\n                }\n                else if (evt.commandName == EventCommandNames.Copy)\n                {\n                    evt.Use();\n                    if (execute && itemType == ItemType.Asset)\n                    {\n                        AssetClipboardUtility.CutCopySelectedFolders(instanceIDs, AssetClipboardUtility.PerformedAction.Copy);\n                        GUIUtility.ExitGUI();\n                    }\n                }\n                else if (evt.commandName == EventCommandNames.Paste)\n                {\n                    evt.Use();\n                    if (execute && itemType == ItemType.Asset && AssetClipboardUtility.CanPaste())\n                    {\n                        int[] copiedFolders = AssetClipboardUtility.PasteFolders();\n                        SetFolderSelection(copiedFolders, true);\n                        GUIUtility.ExitGUI();\n                    }\n                }\n                else if (evt.keyCode == KeyCode.Escape)\n                {\n                    evt.Use();\n                    AssetClipboardUtility.CancelCut();\n                    GUIUtility.ExitGUI();\n                }\n            }\n        }\n\n        public const string FocusProjectWindowCommand = \"FocusProjectWindow\";\n\n        void HandleCommandEvents()\n        {\n            // Check if event made on immutable package\n            if (ShouldDiscardCommandsEventsForImmutablePackages())\n            {\n                Debug.LogFormat(LogType.Warning, LogOption.NoStacktrace, null, k_WarningImmutableSelectionFormat, Event.current.commandName);\n                return;\n            }\n            // Check if event is delete on root folder\n            // Note that if the folder is in favorite, there is no need for root check.\n            // Because we only remove it from the favorite list, not delete the asset.\n            if (!SelectionIsFavorite() && ShouldDiscardCommandsEventsForRootFolders())\n            {\n                Debug.LogFormat(LogType.Warning, LogOption.NoStacktrace, null, k_WarningRootFolderDeletionFormat, Event.current.commandName);\n                return;\n            }\n\n            var evt = Event.current;\n            EventType eventType = evt.type;\n            if (eventType == EventType.ExecuteCommand || eventType == EventType.ValidateCommand || evt.keyCode == KeyCode.Escape)\n            {\n                bool execute = eventType == EventType.ExecuteCommand;\n\n                if (evt.commandName == EventCommandNames.Delete || evt.commandName == EventCommandNames.SoftDelete)\n                {\n                    evt.Use();\n                    if (execute)\n                    {\n                        bool askIfSure = evt.commandName == EventCommandNames.SoftDelete;\n                        DeleteSelectedAssets(askIfSure);\n                        if (askIfSure)\n                            Focus(); // Workaround that we do not get focus back when dialog is closed\n                    }\n                    GUIUtility.ExitGUI();\n                }\n                else if (evt.commandName == EventCommandNames.Duplicate)\n                {\n                    if (execute)\n                    {\n                        evt.Use();\n                        AssetClipboardUtility.DuplicateSelectedAssets();\n                        GUIUtility.ExitGUI();\n                    }\n                    else\n                    {\n                        Object[] selectedAssets = Selection.GetFiltered(typeof(Object), SelectionMode.Assets);\n                        if (selectedAssets.Length != 0)\n                            evt.Use();\n                    }\n                }\n                else if (evt.commandName == EventCommandNames.Cut)\n                {\n                    evt.Use();\n                    AssetClipboardUtility.CutCopySelectedAssets(AssetClipboardUtility.PerformedAction.Cut);\n                    Repaint();\n                }\n                else if (evt.commandName == EventCommandNames.Copy)\n                {\n                    evt.Use();\n                    AssetClipboardUtility.CutCopySelectedAssets(AssetClipboardUtility.PerformedAction.Copy);\n                }\n                else if (evt.commandName == EventCommandNames.Paste)\n                {\n                    evt.Use();\n                    if (execute)\n                        AssetClipboardUtility.PasteSelectedAssets(m_ViewMode == ViewMode.TwoColumns);\n                }\n                else if (evt.keyCode == KeyCode.Escape)\n                {\n                    AssetClipboardUtility.CancelCut();\n                    Repaint();\n                    GUIUtility.ExitGUI();\n                }\n                else if (evt.commandName == FocusProjectWindowCommand)\n                {\n                    if (execute)\n                    {\n                        FrameObjectPrivate(Selection.activeInstanceID, true, false);\n                        evt.Use();\n                        Focus();\n                        GUIUtility.ExitGUI();\n                    }\n                    else\n                    {\n                        evt.Use();\n                    }\n                }\n                else if (evt.commandName == EventCommandNames.SelectAll)\n                {\n                    if (execute)\n                        SelectAll();\n                    evt.Use();\n                }\n                // Frame selected assets\n                else if (evt.commandName == EventCommandNames.FrameSelected)\n                {\n                    if (execute)\n                    {\n                        FrameObjectPrivate(Selection.activeInstanceID, true, false);\n                        evt.Use();\n                        GUIUtility.ExitGUI();\n                    }\n                    evt.Use();\n                }\n                else if (evt.commandName == EventCommandNames.Find)\n                {\n                    if (execute)\n                        m_FocusSearchField = true;\n                    evt.Use();\n                }\n            }\n        }\n\n        void SelectAll()\n        {\n            if (m_ViewMode == ViewMode.OneColumn)\n            {\n                if (m_SearchFilter.IsSearching())\n                {\n                    m_ListArea.SelectAll();\n                }\n                else\n                {\n                    int[] instanceIDs = m_AssetTree.GetRowIDs();\n                    m_AssetTree.SetSelection(instanceIDs, false);\n                    AssetTreeSelectionCallback(instanceIDs);\n                }\n            }\n            else if (m_ViewMode == ViewMode.TwoColumns)\n            {\n                m_ListArea.SelectAll();\n            }\n            else\n            {\n                Debug.LogError(\"Missing implementation for ViewMode \" + m_ViewMode);\n            }\n        }\n\n        float GetListHeaderHeight()\n        {\n            if (!m_SearchFilter.IsSearching())\n                return k_ToolbarHeight;\n            return m_SearchFilter.GetState() == SearchFilter.State.EmptySearchFilter ? 0f : k_ToolbarHeight;\n        }\n\n        void CalculateRects()\n        {\n            float listHeaderHeight = GetListHeaderHeight();\n            if (m_ViewMode == ViewMode.OneColumn)\n            {\n                m_ListAreaRect = new Rect(0, EditorGUI.kWindowToolbarHeight + listHeaderHeight, position.width, position.height - k_ToolbarHeight - listHeaderHeight - k_BottomBarHeight);\n                m_TreeViewRect = new Rect(0, EditorGUI.kWindowToolbarHeight, position.width, position.height - k_ToolbarHeight - k_BottomBarHeight);\n                m_BottomBarRect = new Rect(0, position.height - k_BottomBarHeight, position.width, k_BottomBarHeight);\n                m_ListHeaderRect = new Rect(0, EditorGUI.kWindowToolbarHeight, position.width, listHeaderHeight);\n            }\n            else //if (m_ViewMode == ViewMode.TwoColumns)\n            {\n                float listWidth = position.width - m_DirectoriesAreaWidth;\n\n                m_ListAreaRect = new Rect(m_DirectoriesAreaWidth, EditorGUI.kWindowToolbarHeight + listHeaderHeight, listWidth, position.height - k_ToolbarHeight - listHeaderHeight - k_BottomBarHeight);\n                m_TreeViewRect = new Rect(0, EditorGUI.kWindowToolbarHeight, m_DirectoriesAreaWidth, position.height - k_ToolbarHeight);\n                m_BottomBarRect = new Rect(m_DirectoriesAreaWidth, position.height - k_BottomBarHeight, listWidth, k_BottomBarHeight);\n                m_ListHeaderRect = new Rect(m_ListAreaRect.x, EditorGUI.kWindowToolbarHeight, m_ListAreaRect.width, listHeaderHeight);\n            }\n        }\n\n        void EndPing()\n        {\n            if (m_ViewMode == ViewMode.OneColumn)\n            {\n                m_AssetTree.EndPing();\n            }\n            else\n            {\n                m_FolderTree.EndPing();\n                m_ListArea.EndPing();\n            }\n        }\n\n        void OnEvent()\n        {\n            // Let components handle new event\n            if (m_AssetTree != null)\n                m_AssetTree.OnEvent();\n\n            if (m_FolderTree != null)\n                m_FolderTree.OnEvent();\n\n            if (m_ListArea != null)\n                m_ListArea.OnEvent();\n        }\n\n        void OnGUI()\n        {\n            // Initialize m_Styles\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            if (!Initialized())\n                Init();\n\n            // We grab keyboard control ids early to ensure consistency (for focus rendering)\n            m_ListKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard);\n            m_TreeViewKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard);\n\n            OnEvent();\n\n            m_ItemSelectedByRightClickThisEvent = false;\n\n            // Size splitterRects for different areas of the browser\n            ResizeHandling(position.height - k_ToolbarHeight);\n            CalculateRects();\n\n            Event evt = Event.current;\n\n            Rect ProjectBrowserRect = new Rect(0, 0, position.width, position.height);\n            if (evt.type == EventType.MouseDown && ProjectBrowserRect.Contains(evt.mousePosition))\n            {\n                EndPing();\n                SetAsLastInteractedProjectBrowser();\n            }\n\n            if (m_GrabKeyboardFocusForListArea)\n            {\n                m_GrabKeyboardFocusForListArea = false;\n                GUIUtility.keyboardControl = m_ListKeyboardControlID;\n            }\n\n            GUI.BeginGroup(ProjectBrowserRect, GUIContent.none);\n\n            TopToolbar();\n            BottomBar();\n\n            if (m_ViewMode == ViewMode.OneColumn)\n            {\n                if (m_SearchFilter.IsSearching())\n                {\n                    SearchAreaBar();\n                    if (GUIUtility.keyboardControl == m_TreeViewKeyboardControlID)\n                        GUIUtility.keyboardControl = m_ListKeyboardControlID; // AssetTree is not shown so we can steal keyboard control\n                    m_ListArea.OnGUI(m_ListAreaRect, m_ListKeyboardControlID);\n                }\n                else\n                {\n                    if (GUIUtility.keyboardControl == m_ListKeyboardControlID)\n                        GUIUtility.keyboardControl = m_TreeViewKeyboardControlID; // List is not shown so we can steal keyboard control\n                    m_AssetTree.OnGUI(m_TreeViewRect, m_TreeViewKeyboardControlID);\n                }\n            }\n            else // ViewMode.TwoColumns\n            {\n                if (m_SearchFilter.IsSearching())\n                    SearchAreaBar();\n                else\n                    BreadCrumbBar();\n\n                // Folders\n                m_FolderTree.OnGUI(m_TreeViewRect, m_TreeViewKeyboardControlID);\n\n                // List Content\n                m_ListArea.OnGUI(m_ListAreaRect, m_ListKeyboardControlID);\n\n                // Vertical splitter line between folders and content (drawn before listarea so listarea ping is drawn on top of line)\n                EditorGUIUtility.DrawHorizontalSplitter(new Rect(m_ListAreaRect.x + 1f, EditorGUI.kWindowToolbarHeight, 1, m_TreeViewRect.height));\n\n                if (m_SearchFilter.GetState() == SearchFilter.State.FolderBrowsing && m_ListArea.numItemsDisplayed == 0)\n                {\n                    Vector2 size = EditorStyles.label.CalcSize(s_Styles.m_EmptyFolderText);\n                    Rect textRect = new Rect(m_ListAreaRect.x + 2f + Mathf.Max(0, (m_ListAreaRect.width - size.x) * 0.5f), m_ListAreaRect.y + 10f, size.x, 20f);\n                    using (new EditorGUI.DisabledScope(true))\n                    {\n                        GUI.Label(textRect, s_Styles.m_EmptyFolderText, EditorStyles.label);\n                    }\n                }\n            }\n\n            // Handle ListArea context click after ListArea.OnGUI\n            HandleContextClickInListArea(m_ListAreaRect);\n\n            // Ensure we save current grid size\n            if (m_ListArea.gridSize != m_StartGridSize)\n            {\n                m_StartGridSize = m_ListArea.gridSize;\n                if (m_SearchFilter.GetState() == SearchFilter.State.FolderBrowsing)\n                    m_LastFoldersGridSize = m_ListArea.gridSize;\n            }\n\n            GUI.EndGroup();\n\n            if (m_ViewMode == ViewMode.TwoColumns)\n                useTreeViewSelectionInsteadOfMainSelection = GUIUtility.keyboardControl == m_TreeViewKeyboardControlID;\n\n            // Handle command events AFTER tree and list view since commands events should be handled by text fields first (rename overlay + search field)\n            // Let folder/filters tree view try to handle command events first if it has keyboard focus\n            if (m_ViewMode == ViewMode.TwoColumns && GUIUtility.keyboardControl == m_TreeViewKeyboardControlID)\n                HandleCommandEventsForTreeView();\n            HandleCommandEvents();\n        }\n\n        void HandleContextClickInListArea(Rect listRect)\n        {\n            Event evt = Event.current;\n\n            switch (evt.type)\n            {\n                case EventType.MouseDown:\n                    // This section handles selecting the folders showing their content, if right clicked outside items.\n                    // We do this to ensure our assets context menu is operating on the active folder(s)\n                    if (m_ViewMode == ViewMode.TwoColumns && m_SearchFilter.GetState() == SearchFilter.State.FolderBrowsing && evt.button == 1 && !m_ItemSelectedByRightClickThisEvent)\n                    {\n                        if (m_SearchFilter.folders.Length > 0 && listRect.Contains(evt.mousePosition))\n                        {\n                            m_InternalSelectionChange = true;\n                            Selection.instanceIDs = GetFolderInstanceIDs(m_SearchFilter.folders);\n                        }\n                    }\n                    break;\n\n                case EventType.ContextClick:\n                    if (listRect.Contains(evt.mousePosition))\n                    {\n                        GUIUtility.hotControl = 0;\n\n                        // In safe mode non-scripts assets aren't selectable and therefore if you context click a non-script\n                        // asset, then a context menu shouldn't be displayed.\n                        if (!EditorUtility.isInSafeMode || Selection.instanceIDs.Length > 0)\n                        {\n                            // Context click in list area\n                            EditorUtility.DisplayPopupMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), \"Assets/\", null);\n                        }\n\n                        evt.Use();\n                    }\n                    break;\n            }\n        }\n\n        void AssetTreeViewContextClick(int clickedItemID)\n        {\n            Event evt = Event.current;\n\n            if (clickedItemID == 0)\n            {\n                // For non selectable assets, don't show context menu. Selection is deselected\n                m_AssetTree.SetSelection(k_EmptySelection, false);\n                AssetTreeSelectionCallback(k_EmptySelection);\n            }\n            else\n            {\n                // Context click with a selected Asset\n                EditorUtility.DisplayPopupMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), \"Assets/\", null);\n            }\n\n            evt.Use();\n        }\n\n        void AssetTreeViewContextClickOutsideItems()\n        {\n            Event evt = Event.current;\n\n            // Deselect all\n            if (m_AssetTree.GetSelection().Length > 0)\n            {\n                m_AssetTree.SetSelection(k_EmptySelection, false);\n                AssetTreeSelectionCallback(k_EmptySelection);\n            }\n\n            // Context click with no selected assets\n            EditorUtility.DisplayPopupMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), \"Assets/\", null);\n\n            evt.Use();\n        }\n\n        void FolderTreeViewContextClick(int clickedItemID)\n        {\n            isFolderTreeViewContextClicked = true;\n            Event evt = Event.current;\n            System.Diagnostics.Debug.Assert(evt.type == EventType.ContextClick);\n            if (SavedSearchFilters.IsSavedFilter(clickedItemID))\n            {\n                // Context click with a selected Filter\n                if (clickedItemID != SavedSearchFilters.GetRootInstanceID())\n                    SavedFiltersContextMenu.Show(clickedItemID);\n            }\n            else\n            {\n                // Context click on a folder (asset)\n                EditorUtility.DisplayPopupMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), \"Assets/\", null);\n            }\n            evt.Use();\n        }\n\n        static bool IsFolderTreeViewContextClick()\n        {\n            ProjectBrowser projectBrowser = s_LastInteractedProjectBrowser;\n\n            if (projectBrowser == null)\n            {\n                return true; // return true to ignore Context menu's 'Open' option in folder tree in the ProjectBrowser\n            }\n            else if (projectBrowser.isFolderTreeViewContextClicked)\n            {\n                projectBrowser.isFolderTreeViewContextClicked = false;\n                return true;\n            }\n            else\n            {\n                return false;\n            }\n        }\n\n        void AssetTreeDragEnded(int[] draggedInstanceIds, bool draggedItemsFromOwnTreeView)\n        {\n            // We only change selection if 'draggedItemsFromOwnTreeView' == true.\n            // This ensures that we do not override the selection that might have been set before\n            // calling this callback when dragging e.g a gameobject to the projectbrowser (case 628939)\n            if (draggedInstanceIds != null && draggedItemsFromOwnTreeView)\n            {\n                m_AssetTree.SetSelection(draggedInstanceIds, true);\n                m_AssetTree.NotifyListenersThatSelectionChanged(); // behave as if selection was performed in treeview\n                Repaint();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        void FolderTreeDragEnded(int[] draggedInstanceIds, bool draggedItemsFromOwnTreeView)\n        {\n            // In the folder tree we do not want to change selection as we do in the full asset tree when dragging is performed.\n            // We do not want to change folder when dragging assets to folders (convention of both OSX and Win)\n        }\n\n        // This is our search field\n        void TopToolbar()\n        {\n            GUILayout.BeginHorizontal(EditorStyles.toolbar);\n            {\n                float listWidth = position.width - m_DirectoriesAreaWidth;\n                float spaceBetween = 4f;\n                bool compactMode = listWidth < 500; // We need quite some space for filtering text\n                if (!compactMode)\n                {\n                    spaceBetween = 10f;\n                }\n\n                CreateDropdown();\n                GUILayout.FlexibleSpace();\n\n                GUILayout.Space(spaceBetween * 2f);\n                SearchField();\n                TypeDropDown();\n                AssetLabelsDropDown();\n                LogTypeDropDown();\n                if (m_ViewMode == ViewMode.TwoColumns)\n                {\n                    ButtonSaveFilter();\n                }\n                ToggleHiddenPackagesVisibility();\n            }\n            GUILayout.EndHorizontal();\n        }\n\n        void SetOneColumn()\n        {\n            SetViewMode(ViewMode.OneColumn);\n            EnsureValidSetup();\n        }\n\n        void SetTwoColumns()\n        {\n            SetViewMode(ViewMode.TwoColumns);\n            EnsureValidSetup();\n        }\n\n        internal bool IsTwoColumns()\n        {\n            return m_ViewMode == ViewMode.TwoColumns;\n        }\n\n        void OpenTreeViewTestWindow()\n        {\n            GetWindow<TreeViewTestWindow>();\n        }\n\n        void ToggleExpansionAnimationPreference()\n        {\n            bool oldValue = EditorPrefs.GetBool(TreeViewController.kExpansionAnimationPrefKey, false);\n            EditorPrefs.SetBool(TreeViewController.kExpansionAnimationPrefKey, !oldValue);\n            EditorUtility.RequestScriptReload();\n        }\n\n        public virtual void AddItemsToMenu(GenericMenu menu)\n        {\n            if (m_EnableOldAssetTree)\n            {\n                GUIContent assetTreeText = EditorGUIUtility.TrTextContent(\"One Column Layout\");\n                GUIContent assetBrowserText = EditorGUIUtility.TrTextContent(\"Two Column Layout\");\n\n                menu.AddItem(assetTreeText, m_ViewMode == ViewMode.OneColumn, SetOneColumn);\n                if (position.width >= k_MinWidthTwoColumns)\n                    menu.AddItem(assetBrowserText, m_ViewMode == ViewMode.TwoColumns, SetTwoColumns);\n                else\n                    menu.AddDisabledItem(assetBrowserText);\n\n                m_LockTracker.AddItemsToMenu(menu);\n\n                if (Unsupported.IsDeveloperMode())\n                {\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"DEVELOPER/Open TreeView Test Window...\"), false, OpenTreeViewTestWindow);\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"DEVELOPER/Use TreeView Expansion Animation\"), EditorPrefs.GetBool(TreeViewController.kExpansionAnimationPrefKey, false), ToggleExpansionAnimationPreference);\n                }\n            }\n        }\n\n        float DrawLocalAssetHeader(Rect r)\n        {\n            return 0;\n        }\n\n        void ResizeHandling(float height)\n        {\n            if (m_ViewMode == ViewMode.OneColumn)\n                return;\n\n            // Handle folders vs. items splitter\n            const float minDirectoriesAreaWidth = 50f;\n            const float minAssetsAreaWidth = 50f;\n            Rect dragRect = new Rect(m_DirectoriesAreaWidth, EditorGUI.kWindowToolbarHeight, k_ResizerWidth, height);\n            dragRect = EditorGUIUtility.HandleHorizontalSplitter(dragRect, position.width, minDirectoriesAreaWidth, minAssetsAreaWidth);\n            m_DirectoriesAreaWidth = dragRect.x;\n        }\n\n        void ButtonSaveFilter()\n        {\n            // Only show when we have a active filter\n            using (new EditorGUI.DisabledScope(!m_SearchFilter.IsSearching()))\n            {\n                if (GUILayout.Button(s_Styles.m_SaveFilterContent, EditorStyles.toolbarButtonRight))\n                {\n                    ProjectBrowserColumnOneTreeViewGUI ProjectBrowserTreeViewGUI = m_FolderTree.gui as ProjectBrowserColumnOneTreeViewGUI;\n                    if (ProjectBrowserTreeViewGUI != null)\n                    {\n                        bool createNewFilter = true;\n                        // If a filter is selected save to that filter\n                        int[] treeViewSelection = m_FolderTree.GetSelection();\n                        if (treeViewSelection.Length == 1)\n                        {\n                            int instanceID = treeViewSelection[0];\n                            bool isRootFilter = SavedSearchFilters.GetRootInstanceID() == instanceID;\n\n                            // Ask if filter should be overwritten\n                            if (SavedSearchFilters.IsSavedFilter(instanceID) && !isRootFilter)\n                            {\n                                createNewFilter = false;\n                                string title = \"Overwrite Filter?\";\n                                string text = \"Do you want to overwrite '\" + SavedSearchFilters.GetName(instanceID) + \"' or create a new filter?\";\n                                int result = 2; // cancel\n                                result = EditorUtility.DisplayDialogComplex(title, text, \"Overwrite\", \"Create\", \"Cancel\");\n                                if (result == 0)\n                                    SavedSearchFilters.UpdateExistingSavedFilter(instanceID, m_SearchFilter, listAreaGridSize);\n                                else if (result == 1)\n                                    createNewFilter = true;\n                            }\n                        }\n\n                        // Otherwise create new item in tree\n                        if (createNewFilter)\n                        {\n                            // User wants to create new filter. We re-focus to ensure rename overlay gets input (dialog stole our focus and we might not get it back)\n                            Focus();\n                            ProjectBrowserTreeViewGUI.BeginCreateSavedFilter(m_SearchFilter);\n                        }\n                    }\n                }\n            }\n        }\n\n        void CreateDropdown()\n        {\n            var isInReadOnlyContext = AssetsMenuUtility.SelectionHasImmutable() || SelectionIsPackagesRootFolder() || !ModeService.HasCapability(ModeCapability.AllowAssetCreation, true);\n            EditorGUI.BeginDisabledGroup(isInReadOnlyContext);\n            Rect r = GUILayoutUtility.GetRect(s_Styles.m_CreateDropdownContent, EditorStyles.toolbarCreateAddNewDropDown);\n            if (EditorGUI.DropdownButton(r, s_Styles.m_CreateDropdownContent, FocusType.Passive, EditorStyles.toolbarCreateAddNewDropDown))\n            {\n                GUIUtility.hotControl = 0;\n                EditorUtility.DisplayPopupMenu(r, \"Assets/Create\", null);\n            }\n            EditorGUI.EndDisabledGroup();\n        }\n\n        void AssetLabelsDropDown()\n        {\n            // Labels button\n            Rect r = GUILayoutUtility.GetRect(s_Styles.m_FilterByLabel, EditorStyles.toolbarButton);\n            if (EditorGUI.DropdownButton(r, s_Styles.m_FilterByLabel, FocusType.Passive, EditorStyles.toolbarButton))\n            {\n                PopupWindow.Show(r, new PopupList(m_AssetLabels));\n            }\n        }\n\n        void TypeDropDown()\n        {\n            // Object type button\n            Rect r = GUILayoutUtility.GetRect(s_Styles.m_FilterByType, EditorStyles.toolbarButton);\n            if (EditorGUI.DropdownButton(r, s_Styles.m_FilterByType, FocusType.Passive, EditorStyles.toolbarButton))\n            {\n                PopupWindow.Show(r, new PopupList(m_ObjectTypes));\n            }\n        }\n\n        void LogTypeDropDown()\n        {\n            //Log type button\n            Rect r = GUILayoutUtility.GetRect(s_Styles.m_FilterByImportLog, EditorStyles.toolbarButton);\n            if (EditorGUI.DropdownButton(r, s_Styles.m_FilterByImportLog, FocusType.Passive, EditorStyles.toolbarButton))\n            {\n                PopupWindow.Show(r, new PopupList(m_LogTypes));\n            }\n        }\n\n        private void ToggleHiddenPackagesVisibility()\n        {\n            s_Styles.m_PackageContentDefault = m_SkipHiddenPackages ? s_Styles.m_PackagesContentNotVisible : s_Styles.m_PackagesContentVisible;\n            s_Styles.m_PackageContentDefault.text = PackageManagerUtilityInternal.HiddenPackagesCount.ToString();\n            var skipHiddenPackage = GUILayout.Toggle(m_SkipHiddenPackages, s_Styles.m_PackageContentDefault, EditorStyles.toolbarButtonRight);\n\n            if (skipHiddenPackage != m_SkipHiddenPackages)\n            {\n                m_SkipHiddenPackages = skipHiddenPackage;\n                EndRenaming();\n\n                if (m_AssetTree != null)\n                {\n                    var dataSource = m_AssetTree.data as AssetsTreeViewDataSource;\n                    dataSource.skipHiddenPackages = m_SkipHiddenPackages;\n                }\n\n                if (m_FolderTree != null)\n                {\n                    var dataSource = m_FolderTree.data as ProjectBrowserColumnOneTreeViewDataSource;\n                    dataSource.skipHiddenPackages = m_SkipHiddenPackages;\n                }\n\n                ResetViews();\n            }\n        }\n\n        void SearchField()\n        {\n            Rect rect = GUILayoutUtility.GetRect(0, EditorGUILayout.kLabelFloatMaxW * 1.5f, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.toolbarSearchFieldWithJump, GUILayout.MinWidth(65), GUILayout.MaxWidth(300));\n            int searchFieldControlID = EditorGUIUtility.GetControlID(s_HashForSearchField, FocusType.Passive, rect); // We use 'Passive' to ensure we only tab between folder tree and list area. Focus search field by using Ctrl+F.\n\n            if (m_FocusSearchField)\n            {\n                GUIUtility.keyboardControl = searchFieldControlID;\n                EditorGUIUtility.editingTextField = true;\n                if (Event.current.type == EventType.Repaint)\n                    m_FocusSearchField = false;\n            }\n\n            Event evt = Event.current;\n            if (GUIUtility.keyboardControl == searchFieldControlID)\n            {\n                // On arrow down/up switch to control selection in list area\n                if (evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.DownArrow || evt.keyCode == KeyCode.UpArrow))\n                {\n                    if (!m_ListArea.IsLastClickedItemVisible())\n                        m_ListArea.SelectFirst();\n\n                    GUIUtility.keyboardControl = m_ListKeyboardControlID;\n                    evt.Use();\n                }\n\n                SearchService.SearchService.HandleSearchEvent(this, evt, m_SearchFieldText);\n            }\n\n            m_lastSearchFilter = EditorGUI.ToolbarSearchField(\n                searchFieldControlID,\n                rect,\n                m_SearchFieldText,\n                m_SyncSearch ? EditorStyles.toolbarSearchFieldWithJumpSynced : EditorStyles.toolbarSearchFieldWithJump,\n                string.IsNullOrEmpty(m_SearchFieldText) ? EditorStyles.toolbarSearchFieldCancelButtonWithJumpEmpty : EditorStyles.toolbarSearchFieldCancelButtonWithJump);\n\n            if (m_lastSearchFilter != m_SearchFieldText || m_FocusSearchField)\n            {\n                // Update filter with string\n                m_SearchFieldText = m_lastSearchFilter;\n\n                m_NextSearchOffDelegate?.Invoke();\n                m_NextSearchOffDelegate = EditorApplication.CallDelayed(UpdateSearchDelayed, searchUpdateDelaySeconds);\n            }\n\n            SearchService.SearchService.DrawOpenSearchButton(this, m_SearchFieldText);\n        }\n\n        void UpdateSearchDelayed()\n        {\n            m_SearchFilter.SearchFieldStringToFilter(m_SearchFieldText);\n            SyncFilterGUI();\n            TopBarSearchSettingsChanged();\n            Repaint();\n        }\n\n        void TopBarSearchSettingsChanged(bool keyboardValidation = true)\n        {\n            if (!m_SearchFilter.IsSearching())\n            {\n                if (m_DidSelectSearchResult)\n                {\n                    m_DidSelectSearchResult = false;\n                    FrameObjectPrivate(Selection.activeInstanceID, true, false);\n                    if (GUIUtility.keyboardControl == 0 && keyboardValidation)\n                    {\n                        // Ensure item has focus for visual feedback and instant key navigation\n                        if (m_ViewMode == ViewMode.OneColumn)\n                            GUIUtility.keyboardControl = m_TreeViewKeyboardControlID;\n                        else if (m_ViewMode == ViewMode.TwoColumns)\n                            GUIUtility.keyboardControl = m_ListKeyboardControlID;\n                    }\n                }\n                else if (m_ViewMode == ViewMode.TwoColumns)\n                {\n                    // Revert to last selected folders\n                    if (GUIUtility.keyboardControl == 0 || !keyboardValidation || SelectionIsFavorite())\n                    {\n                        RevertToLastSelectedFolder(false);\n                    }\n                }\n            }\n            else\n            {\n                if (m_ViewMode == ViewMode.TwoColumns && SelectionIsFavorite())\n                    RevertToLastSelectedFolder(false);\n                InitSearchMenu();\n            }\n\n            InitListArea();\n        }\n\n        internal static int GetFolderInstanceID(string folderPath)\n        {\n            return folderPath == PackageManager.Folders.GetPackagesPath()\n                ? kPackagesFolderInstanceId\n                : AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(folderPath);\n        }\n\n        static int[] GetFolderInstanceIDs(string[] folders)\n        {\n            int[] folderInstanceIDs = new int[folders.Length];\n\n            for (int i = 0; i < folders.Length; ++i)\n            {\n                folderInstanceIDs[i] = GetFolderInstanceID(folders[i]);\n            }\n            return folderInstanceIDs;\n        }\n\n        static string[] GetFolderPathsFromInstanceIDs(int[] instanceIDs)\n        {\n            List<string> paths = new List<string>();\n            foreach (int instanceID in instanceIDs)\n            {\n                if (instanceID == kPackagesFolderInstanceId)\n                {\n                    paths.Add(PackageManager.Folders.GetPackagesPath());\n                    continue;\n                }\n                string path = AssetDatabase.GetAssetPath(instanceID);\n                if (!String.IsNullOrEmpty(path))\n                    paths.Add(path);\n            }\n            return paths.ToArray();\n        }\n\n        void ClearSearch()\n        {\n            m_SearchFilter.ClearSearch();\n            m_SearchFilter.skipHidden = m_SkipHiddenPackages;\n\n            // Clear GUI\n            m_SearchFieldText = \"\";\n            m_AssetLabels.DeselectAll();\n            m_ObjectTypes.DeselectAll();\n            m_DidSelectSearchResult = false;\n        }\n\n        void FolderTreeSelectionChanged(bool folderWasSelected)\n        {\n            if (folderWasSelected)\n            {\n                SearchViewState state = GetSearchViewState();\n                if (state == SearchViewState.AllAssets || state == SearchViewState.InAssetsOnly ||\n                    state == SearchViewState.InPackagesOnly)\n                {\n                    // Clear all except folders if folder is set\n                    string[] folders = m_SearchFilter.folders;\n                    ClearSearch();\n                    m_SearchFilter.folders = folders;\n\n                    // Ensures that when selecting folders we start local asset search next time we search\n                    m_SearchFilter.searchArea = m_LastLocalAssetsSearchArea;\n                }\n\n                m_LastFolders = m_SearchFilter.folders;\n            }\n\n            // End any rename that might be in progress.\n            EndRenaming();\n\n            RefreshSearchText();\n            InitListArea();\n        }\n\n        void IconSizeSlider(Rect r)\n        {\n            // Slider\n            EditorGUI.BeginChangeCheck();\n            int newGridSize = (int)GUI.HorizontalSlider(r, m_ListArea.gridSize, m_ListArea.minGridSize, m_ListArea.maxGridSize);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_ListArea.gridSize = newGridSize;\n            }\n        }\n\n        void SearchAreaBar()\n        {\n            // Background\n            GUI.Label(m_ListHeaderRect, GUIContent.none, s_Styles.topBarBg);\n\n            const float kMargin = 5f;\n            Rect rect = m_ListHeaderRect;\n            rect.x += kMargin;\n            rect.height -= 1;\n            rect.width -= 2 * kMargin;\n\n            GUIStyle style = EditorStyles.boldLabel;\n\n            GUI.Label(rect, s_Styles.m_SearchIn, style);\n            if (m_SearchAreaMenuOffset < 0f)\n                m_SearchAreaMenuOffset = style.CalcSize(s_Styles.m_SearchIn).x;\n\n            rect.x += m_SearchAreaMenuOffset + 7f;\n            rect.width -= m_SearchAreaMenuOffset + 7f;\n            rect.width = m_SearchAreaMenu.OnGUI(rect);\n        }\n\n        void BreadCrumbBar()\n        {\n            if (m_ListHeaderRect.height <= 0f)\n                return;\n\n            if (m_SearchFilter.folders.Length == 0)\n                return;\n\n            Event evt = Event.current;\n\n            // Give keyboard focus to list area if we mouse down in breadcrumbs\n            if (evt.type == EventType.MouseDown && m_ListHeaderRect.Contains(evt.mousePosition))\n            {\n                GUIUtility.keyboardControl = m_ListKeyboardControlID;\n                Repaint();\n            }\n\n            if (m_BreadCrumbs.Count == 0)\n            {\n                var path = m_SearchFilter.folders[0];\n                if (IsInsideHiddenPackage(path))\n                {\n                    m_BreadCrumbLastFolderHasSubFolders = false;\n                }\n                else\n                {\n                    var folderNames = new List<string>();\n                    var folderDisplayNames = new List<string>();\n                    var packagesMountPoint = PackageManager.Folders.GetPackagesPath();\n                    var packageInfo = PackageManager.PackageInfo.FindForAssetPath(path);\n                    if (packageInfo != null)\n                    {\n                        // Packages root\n                        folderNames.Add(packagesMountPoint);\n                        folderDisplayNames.Add(packagesMountPoint);\n\n                        // Package name/displayname\n                        folderNames.Add(packageInfo.name);\n                        folderDisplayNames.Add(string.IsNullOrEmpty(packageInfo.displayName)\n                            ? packageInfo.name\n                            : packageInfo.displayName);\n\n                        // Rest of the path;\n                        if (path != packageInfo.assetPath)\n                        {\n                            var subpaths = Regex.Replace(path, @\"^\" + packageInfo.assetPath + \"/\", \"\").Split('/');\n                            folderNames.AddRange(subpaths);\n                            folderDisplayNames.AddRange(subpaths);\n                        }\n                    }\n                    else\n                    {\n                        folderNames.AddRange(path.Split('/'));\n                        folderDisplayNames = folderNames;\n                    }\n\n                    var folderPath = \"\";\n                    var i = 0;\n                    foreach (var folderName in folderNames)\n                    {\n                        if (!string.IsNullOrEmpty(folderPath))\n                            folderPath += \"/\";\n                        folderPath += folderName;\n\n                        m_BreadCrumbs.Add(new KeyValuePair<GUIContent, string>(new GUIContent(folderDisplayNames[i++]), folderPath));\n                    }\n\n                    if (path == packagesMountPoint)\n                    {\n                        m_BreadCrumbLastFolderHasSubFolders = PackageManagerUtilityInternal.GetAllVisiblePackages(m_SkipHiddenPackages).Length > 0;\n                    }\n                }\n            }\n\n            // Background\n            GUI.Label(m_ListHeaderRect, GUIContent.none, s_Styles.topBarBg);\n\n            // Folders\n            Rect rect = m_ListHeaderRect;\n            rect.y += s_Styles.topBarBg.padding.top;\n            rect.x += s_Styles.topBarBg.padding.left;\n            if (m_SearchFilter.folders.Length == 1)\n            {\n                for (int i = 0; i < m_BreadCrumbs.Count; ++i)\n                {\n                    bool lastElement = i == m_BreadCrumbs.Count - 1;\n                    GUIStyle style = lastElement ? EditorStyles.boldLabel : EditorStyles.label; //EditorStyles.miniBoldLabel : EditorStyles.miniLabel;//\n                    GUIContent folderContent = m_BreadCrumbs[i].Key;\n                    string folderPath = m_BreadCrumbs[i].Value;\n                    Vector2 size = style.CalcSize(folderContent);\n                    rect.width = size.x;\n                    if (GUI.Button(rect, folderContent, style))\n                    {\n                        ShowFolderContents(GetFolderInstanceID(folderPath), false);\n                    }\n\n                    rect.x += size.x;\n                    if (!lastElement || m_BreadCrumbLastFolderHasSubFolders)\n                    {\n                        Rect buttonRect = new Rect(rect.x, rect.y + (rect.height - s_Styles.separator.fixedHeight) / 2, s_Styles.separator.fixedWidth, s_Styles.separator.fixedHeight);\n                        if (EditorGUI.DropdownButton(buttonRect, GUIContent.none, FocusType.Passive, s_Styles.separator))\n                        {\n                            string currentSubFolder = \"\";\n                            if (!lastElement)\n                                currentSubFolder = m_BreadCrumbs[i + 1].Value;\n                            BreadCrumbListMenu.Show(folderPath, currentSubFolder, buttonRect, this);\n                        }\n                    }\n                    rect.x += s_Styles.separator.fixedWidth;\n                }\n            }\n            else if (m_SearchFilter.folders.Length > 1)\n            {\n                GUI.Label(rect, GUIContent.Temp(\"Showing multiple folders...\"), EditorStyles.miniLabel);\n            }\n        }\n\n        void BottomBar()\n        {\n            if (m_BottomBarRect.height == 0f)\n                return;\n\n            Rect rect = m_BottomBarRect;\n\n            // Background\n            GUI.Label(rect, GUIContent.none, s_Styles.bottomBarBg);\n\n            // Icons are fixed size in One Column mode, so only show icon size slider in Two Columns mode\n            bool showIconSizeSlider = m_ViewMode == ViewMode.TwoColumns || m_SearchFilter.IsSearching();\n            if (showIconSizeSlider)\n            {\n                Rect sliderRect = new Rect(rect.x + rect.width - k_SliderWidth - 16f\n                    , rect.y + rect.height - (m_BottomBarRect.height + EditorGUI.kSingleLineHeight) / 2, k_SliderWidth,\n                    m_BottomBarRect.height);\n                IconSizeSlider(sliderRect);\n            }\n\n            // File path\n            EditorGUIUtility.SetIconSize(new Vector2(16, 16)); // If not set we see icons scaling down if text is being cropped\n            const float k_Margin = 2;\n            rect.width -= k_Margin * 2;\n            rect.x += k_Margin;\n            rect.height = k_BottomBarHeight;\n\n            if (showIconSizeSlider)\n            {\n                rect.width -= k_SliderWidth + 14f;\n            }\n\n            GUI.Label(rect, m_SelectedPathContent, s_Styles.selectedPathLabel);\n            EditorGUIUtility.SetIconSize(new Vector2(0, 0));\n        }\n\n        public void SelectAssetsFolder()\n        {\n            ShowFolderContents(AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(\"Assets\"), true);\n        }\n\n        string ValidateCreateNewAssetPath(string pathName)\n        {\n            // Normally we create assets relative to current selected asset. If no asset is selected we normally create the asset in the root folder (Assets)\n            // but in two column mode we want to create the asset in the currently shown folder if no asset is selected. (fix case 550484)\n            if (m_ViewMode == ViewMode.TwoColumns && m_SearchFilter.GetState() == SearchFilter.State.FolderBrowsing && m_SearchFilter.folders.Length > 0)\n            {\n                // Ensure pathName is not already a full asset path\n                if (!pathName.StartsWith(\"assets/\", StringComparison.CurrentCultureIgnoreCase))\n                {\n                    // If no assets are selected we use first currently shown folder path\n                    if (Selection.GetFiltered(typeof(Object), SelectionMode.Assets).Length == 0)\n                    {\n                        pathName = Path.Combine(m_SearchFilter.folders[0], pathName);\n                        pathName = pathName.Replace(\"\\\\\", \"/\");\n                    }\n                }\n            }\n            return pathName;\n        }\n\n        internal void BeginPreimportedNameEditing(int instanceID, EndNameEditAction endAction, string pathName, Texture2D icon, string resourceFile, bool selectAssetBeingCreated)\n        {\n            if (!Initialized())\n                Init();\n\n            // End any rename that might be active, this will also end any asset currently being created\n            EndRenaming();\n\n            bool isCreatingNewFolder = endAction is DoCreateFolder;\n\n            if (m_ViewMode == ViewMode.TwoColumns)\n            {\n                if (m_SearchFilter.GetState() != SearchFilter.State.FolderBrowsing)\n                {\n                    // Force select the Assets folder as default when no folders are selected\n                    SelectAssetsFolder();\n                }\n\n                pathName = ValidateCreateNewAssetPath(pathName);\n\n                if (m_ListAreaState.m_CreateAssetUtility.BeginNewAssetCreation(instanceID, endAction, pathName, icon, resourceFile, selectAssetBeingCreated))\n                {\n                    ShowFolderContents(AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(m_ListAreaState.m_CreateAssetUtility.folder), true);\n                    m_ListArea.BeginNamingNewAsset(m_ListAreaState.m_CreateAssetUtility.originalName, instanceID, isCreatingNewFolder);\n                }\n            }\n            else if (m_ViewMode == ViewMode.OneColumn)\n            {\n                // If search is active put new asset under selected folder otherwise in Assets\n                if (m_SearchFilter.IsSearching())\n                {\n                    ClearSearch();\n                }\n\n                // Create in tree\n                AssetsTreeViewGUI defaultTreeViewGUI = m_AssetTree.gui as AssetsTreeViewGUI;\n                if (defaultTreeViewGUI != null)\n                    defaultTreeViewGUI.BeginCreateNewAsset(instanceID, endAction, pathName, icon, resourceFile, selectAssetBeingCreated);\n                else\n                    Debug.LogError(\"Not valid defaultTreeViewGUI!\");\n            }\n        }\n\n        public void FrameObject(int instanceID, bool ping)\n        {\n            m_LockTracker.StopPingIcon();\n\n            bool canFrame = CanFrameAsset(instanceID);\n            if (!canFrame)\n            {\n                // Check if we can frame the main asset from the same asset path instead.\n                // This ensures that Components or child GameObject of Prefabs or hidden sub assets will\n                // still be located and pinged in the Project Browser (case 1262196).\n                var path = AssetDatabase.GetAssetPath(instanceID);\n                if (!string.IsNullOrEmpty(path))\n                {\n                    var mainObject = AssetDatabase.LoadMainAssetAtPath(path);\n                    if (mainObject != null)\n                    {\n                        canFrame = CanFrameAsset(mainObject.GetInstanceID());\n                        if (canFrame)\n                            instanceID = mainObject.GetInstanceID();\n                    }\n                }\n            }\n\n            bool frame = ping || canFrame;\n            if (frame && m_LockTracker.isLocked)\n            {\n                frame = false;\n\n                // If the item is visible then we can ping it however if it requires revealing then we can not and should indicate why(locked project view).\n                if (canFrame &&\n                    ((m_ViewMode == ViewMode.TwoColumns && m_ListArea != null && !m_ListArea.IsShowing(instanceID))\n                    || (m_ViewMode == ViewMode.OneColumn && m_AssetTree != null && m_AssetTree.data.GetRow(instanceID) == -1)))\n                {\n                    Repaint();\n                    m_LockTracker.PingIcon();\n                }\n            }\n\n            FrameObjectPrivate(instanceID, frame, ping);\n            if (s_LastInteractedProjectBrowser == this)\n            {\n                m_GrabKeyboardFocusForListArea = true;\n            }\n        }\n\n        private void FrameObjectPrivate(int instanceID, bool frame, bool ping)\n        {\n            if (instanceID == 0 || m_ListArea == null)\n                return;\n\n            // If framing the same instance as the last one we do not remove the ping\n            // since issuing first a ping and then a framing should still show the ping.\n            if (m_LastFramedID != instanceID)\n                EndPing();\n            m_LastFramedID = instanceID;\n\n            ClearSearch();\n\n            if (m_ViewMode == ViewMode.TwoColumns)\n            {\n                FrameObjectInTwoColumnMode(instanceID, frame, ping);\n            }\n            else if (m_ViewMode == ViewMode.OneColumn)\n            {\n                // Clear search to switch back to tree view\n                m_AssetTree.Frame(instanceID, frame, ping);\n            }\n        }\n\n        private void FrameObjectInTwoColumnMode(int instanceID, bool frame, bool ping)\n        {\n            int folderInstanceID = 0;\n\n            if (instanceID == kPackagesFolderInstanceId)\n                folderInstanceID = kPackagesFolderInstanceId;\n            else\n            {\n                string assetPath = AssetDatabase.GetAssetPath(instanceID);\n                if (!String.IsNullOrEmpty(assetPath))\n                {\n                    string containingFolder = ProjectWindowUtil.GetContainingFolder(assetPath);\n                    if (!String.IsNullOrEmpty(containingFolder))\n                        folderInstanceID = GetFolderInstanceID(containingFolder);\n\n                    if (folderInstanceID == 0)\n                        folderInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(\"Assets\");\n                }\n            }\n\n            // Could be a scene gameobject\n            if (folderInstanceID != 0)\n            {\n                m_FolderTree.Frame(folderInstanceID, frame, ping);\n                if (frame)\n                    ShowFolderContents(folderInstanceID, true);\n                m_ListArea.Frame(instanceID, frame, ping);\n            }\n        }\n\n        // Also called from C++ (used for AssetSelection overriding)\n        [UsedByNativeCode]\n        internal static int[] GetTreeViewFolderSelection(bool forceUseTreeViewSelection = false)\n        {\n            // Since we can delete entire folder hierarchies with the returned selection we need to be very careful. We therefore require the following:\n            // - The folder/favorite tree view must have keyboard focus\n            // Note we cannot require window focus (focusedWindow) since on OSX window focus is lost to popup window when right clicking\n            ProjectBrowser ob = s_LastInteractedProjectBrowser;\n\n            if (ob != null && (ob.useTreeViewSelectionInsteadOfMainSelection || forceUseTreeViewSelection) && ob.m_FolderTree != null)\n            {\n                return s_LastInteractedProjectBrowser.m_FolderTree.GetSelection();\n            }\n\n            return k_EmptySelection;\n        }\n\n        public float listAreaGridSize\n        {\n            get { return m_ListArea.gridSize; }\n        }\n\n        [UsedByNativeCode]\n        internal static bool CanDeleteSelectedAssets()\n        {\n            var treeViewSelection = GetTreeViewFolderSelection();\n            var instanceIDs = treeViewSelection.Length > 0 ? new List<int>(treeViewSelection) : new List<int>(Selection.instanceIDs);\n\n            var objectsToDelete = new HashSet<int>();\n            foreach (var instanceID in instanceIDs)\n            {\n                if (instanceID == AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(\"Assets\") || instanceID == kPackagesFolderInstanceId)\n                {\n                    return false;\n                }\n\n                if (AssetDatabase.IsMainAsset(instanceID))\n                {\n                    var path = AssetDatabase.GetAssetPath(instanceID);\n                    bool isRootFolder, isImmutable;\n                    if (string.IsNullOrEmpty(path) || !AssetDatabase.TryGetAssetFolderInfo(path, out isRootFolder, out isImmutable) || isRootFolder || isImmutable)\n                    {\n                        return false;\n                    }\n\n                    objectsToDelete.Add(instanceID);\n                }\n            }\n\n            return objectsToDelete.Count != 0;\n        }\n\n        [UsedByNativeCode]\n        internal static void DeleteSelectedAssets(bool askIfSure)\n        {\n            int[] treeViewSelection = GetTreeViewFolderSelection();\n\n            List<int> instanceIDs;\n            if (treeViewSelection.Length > 0)\n                instanceIDs = new List<int>(treeViewSelection);\n            else\n                instanceIDs = new List<int>(Selection.instanceIDs);\n\n            if (instanceIDs.Count == 0)\n                return;\n\n            if (ProjectWindowUtil.DeleteAssets(instanceIDs, askIfSure))\n            {\n                // Ensure selection is cleared since StopAssetEditing() will restore selection from a backup saved in StartAssetEditing.\n                Selection.instanceIDs = k_EmptySelection;\n            }\n        }\n\n        [UsedByNativeCode]\n        internal static void RenameSelectedAssets()\n        {\n            ProjectBrowser ob = s_LastInteractedProjectBrowser;\n            if (ob != null)\n            {\n                if (ob.useTreeViewSelectionInsteadOfMainSelection && ob.m_FolderTree != null)\n                {\n                    ob.m_FolderTree.BeginNameEditing(0f);\n                }\n                else if (ob.m_ViewMode == ViewMode.OneColumn && !ob.m_SearchFilter.IsSearching() && ob.m_AssetTree != null)\n                {\n                    ob.m_AssetTree.BeginNameEditing(0f);\n                }\n                else if (ob.m_ListArea != null)\n                {\n                    ob.m_ListArea.BeginRename(0f);\n                }\n                else\n                {\n                    return;\n                }\n\n                // We need to ensure that we start with focus in the rename overlay (UUM-48858)\n                ob.Focus();\n                ob.Repaint();\n            }\n        }\n\n        internal IHierarchyProperty GetHierarchyPropertyUsingFilter(string textFilter)\n        {\n            FilteredHierarchy filteredHierarchy = new FilteredHierarchy(HierarchyType.Assets);\n            filteredHierarchy.searchFilter = SearchFilter.CreateSearchFilterFromString(textFilter);\n            IHierarchyProperty property = FilteredHierarchyProperty.CreateHierarchyPropertyForFilter(filteredHierarchy);\n            return property;\n        }\n\n        internal void ShowObjectsInList(int[] instanceIDs)\n        {\n            if (!Initialized())\n                Init();\n\n            if (m_ViewMode == ViewMode.TwoColumns)\n            {\n                m_ListArea.ShowObjectsInList(instanceIDs);\n                m_FolderTree.SetSelection(k_EmptySelection, false); // Remove selection from folder tree since we show custom list (press F to focus)\n            }\n            else if (m_ViewMode == ViewMode.OneColumn)\n            {\n                foreach (int instanceID in Selection.instanceIDs)\n                    m_AssetTree.Frame(instanceID, true, false);\n            }\n        }\n\n        // Called from AssetsMenu\n        [RequiredByNativeCode]\n        static void ShowSelectedObjectsInLastInteractedProjectBrowser()\n        {\n            // Only one ProjectBrowser can have focus at a time so if we find one just return that one\n            if (s_LastInteractedProjectBrowser != null)\n            {\n                int[] instanceIDs = Selection.instanceIDs;\n\n                s_LastInteractedProjectBrowser.ShowObjectsInList(instanceIDs);\n            }\n        }\n\n        // Called from DockArea\n        protected virtual void ShowButton(Rect r)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            if (m_LockTracker.ShowButton(r, s_Styles.lockButton))\n                Repaint();\n        }\n\n        internal bool SelectionIsFavorite()\n        {\n            if (m_FolderTree == null)\n                return false;\n\n            if (m_FolderTree.GetSelection().Length != 1)\n                return false;\n\n            int selectionID = m_FolderTree.GetSelection()[0];\n            ItemType type = GetItemType(selectionID);\n            return type == ItemType.SavedFilter;\n        }\n\n        private void RevertToLastSelectedFolder(bool folderWasSelected)\n        {\n            if (m_LastFolders != null && m_LastFolders.Length > 0)\n            {\n                m_SearchFilter.folders = m_LastFolders;\n                if (m_FolderTree != null)\n                    SetFolderSelection(GetFolderInstanceIDs(m_LastFolders), true, folderWasSelected);\n            }\n        }\n\n        internal class SavedFiltersContextMenu\n        {\n            int m_SavedFilterInstanceID;\n\n            static internal void Show(int savedFilterInstanceID)\n            {\n                // Curve context menu\n                GUIContent delete = EditorGUIUtility.TrTextContent(\"Delete\");\n\n                GenericMenu menu = new GenericMenu();\n                menu.AddItem(delete, false, new SavedFiltersContextMenu(savedFilterInstanceID).Delete);\n\n                menu.ShowAsContext();\n            }\n\n            private SavedFiltersContextMenu(int savedFilterInstanceID)\n            {\n                m_SavedFilterInstanceID = savedFilterInstanceID;\n            }\n\n            private void Delete()\n            {\n                DeleteFilter(m_SavedFilterInstanceID);\n            }\n        }\n\n        internal class BreadCrumbListMenu\n        {\n            static ProjectBrowser m_Caller;\n            string m_SubFolder;\n\n            static internal void Show(string folder, string currentSubFolder, Rect activatorRect, ProjectBrowser caller)\n            {\n                m_Caller = caller;\n\n                // List of sub folders\n                var subFolders = new List<string>();\n                var subFolderDisplayNames = new List<string>();\n                if (folder == Folders.GetPackagesPath())\n                {\n                    foreach (var package in PackageManagerUtilityInternal.GetAllVisiblePackages(caller.m_SkipHiddenPackages))\n                    {\n                        subFolders.Add(package.assetPath);\n                        var displayName = !string.IsNullOrEmpty(package.displayName) ? package.displayName : package.name;\n                        subFolderDisplayNames.Add(displayName);\n                    }\n                }\n                else\n                {\n                    subFolders.AddRange(AssetDatabase.GetSubFolders(folder));\n                    foreach (var subFolderPath in subFolders)\n                        subFolderDisplayNames.Add(Path.GetFileName(subFolderPath));\n                }\n\n                var menu = new GenericMenu { allowDuplicateNames = true };\n                if (subFolders.Count > 0)\n                {\n                    var i = 0;\n                    foreach (var subFolderPath in subFolders)\n                    {\n                        menu.AddItem(new GUIContent(subFolderDisplayNames[i++]), subFolderPath == currentSubFolder, new BreadCrumbListMenu(subFolderPath).SelectSubFolder);\n                        menu.ShowAsContext();\n                    }\n                }\n                else\n                {\n                    menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"No sub folders...\"));\n                }\n\n                menu.DropDown(activatorRect);\n            }\n\n            private BreadCrumbListMenu(string subFolder)\n            {\n                m_SubFolder = subFolder;\n            }\n\n            private void SelectSubFolder()\n            {\n                int folderInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(m_SubFolder);\n                if (folderInstanceID != 0)\n                    m_Caller.ShowFolderContents(folderInstanceID, false);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ProjectBrowser/ProjectBrowserColumnOne.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.IO;\nusing UnityEditor.Experimental;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditorInternal;\nusing UnityEngine;\n\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing LazyTreeViewDataSource = UnityEditor.IMGUI.Controls.LazyTreeViewDataSource<int>;\nusing TreeViewUtility = UnityEditor.IMGUI.Controls.TreeViewUtility<int>;\n\nnamespace UnityEditor\n{\n    // Used for type check\n    class SearchFilterTreeItem : TreeViewItem\n    {\n        bool m_IsFolder;\n        public SearchFilterTreeItem(int id, int depth, TreeViewItem parent, string displayName, bool isFolder)\n            : base(id, depth, parent, displayName)\n        {\n            m_IsFolder = isFolder;\n        }\n\n        public bool isFolder {get {return m_IsFolder; }}\n    }\n\n    //------------------------------------------------\n    // GUI section\n\n    internal class ProjectBrowserColumnOneTreeViewGUI : AssetsTreeViewGUI\n    {\n        const float k_DistBetweenRootTypes = 15f;\n        Texture2D k_FavoritesIcon = EditorGUIUtility.FindTexture(\"Favorite Icon\");\n        Texture2D k_FavoriteFolderIcon = EditorGUIUtility.FindTexture(\"FolderFavorite Icon\");\n        Texture2D k_FavoriteFilterIcon = EditorGUIUtility.FindTexture(\"Search Icon\");\n        bool m_IsCreatingSavedFilter = false;\n\n        public ProjectBrowserColumnOneTreeViewGUI(TreeViewController treeView) : base(treeView)\n        {\n        }\n\n        // ------------------\n        // Size section\n\n\n        override public Vector2 GetTotalSize()\n        {\n            Vector2 totalSize = base.GetTotalSize();\n\n            totalSize.y += k_DistBetweenRootTypes * 1; // assumes that we have two root\n\n            return totalSize;\n        }\n\n        public override Rect GetRowRect(int row, float rowWidth)\n        {\n            var rows = m_TreeView.data.GetRows();\n            return new Rect(0, GetTopPixelOfRow(row, rows), rowWidth, k_LineHeight);\n        }\n\n        float GetTopPixelOfRow(int row, IList<TreeViewItem> rows)\n        {\n            float topPixel = row * k_LineHeight;\n\n            // Assumes Saved filter are second root\n            TreeViewItem item = rows[row];\n            ProjectBrowser.ItemType type = ProjectBrowser.GetItemType(item.id);\n            if (type == ProjectBrowser.ItemType.Asset)\n                topPixel += k_DistBetweenRootTypes;\n\n            return topPixel;\n        }\n\n        override public int GetNumRowsOnPageUpDown(TreeViewItem fromItem, bool pageUp, float heightOfTreeView)\n        {\n            return (int)Mathf.Floor(heightOfTreeView / k_LineHeight) - 1; // -1 is fast fix for space between roots\n        }\n\n        // Should return the row number of the first and last row thats fits in the pixel rect defined by top and height\n        override public void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible)\n        {\n            float topPixel = m_TreeView.state.scrollPos.y;\n            float heightInPixels = m_TreeView.GetTotalRect().height;\n\n            firstRowVisible = (int)Mathf.Floor(topPixel / k_LineHeight);\n            lastRowVisible = firstRowVisible + (int)Mathf.Ceil(heightInPixels / k_LineHeight);\n\n            float rowsPerSpaceBetween = k_DistBetweenRootTypes / k_LineHeight;\n            firstRowVisible -= (int)Mathf.Ceil(2 * rowsPerSpaceBetween); // for now we just add extra rows to ensure all rows are visible\n            lastRowVisible += (int)Mathf.Ceil(2 * rowsPerSpaceBetween);\n\n            firstRowVisible = Mathf.Max(firstRowVisible, 0);\n            lastRowVisible = Mathf.Min(lastRowVisible,  m_TreeView.data.rowCount - 1);\n        }\n\n        // ------------------\n        // Row Gui section\n\n        override public void OnRowGUI(Rect rowRect, TreeViewItem item, int row, bool selected, bool focused)\n        {\n            bool useBoldFont = IsVisibleRootNode(item);\n            DoItemGUI(rowRect, row, item, selected, focused, useBoldFont);\n        }\n\n        bool IsVisibleRootNode(TreeViewItem item)\n        {\n            return (m_TreeView.data as ProjectBrowserColumnOneTreeViewDataSource).IsVisibleRootNode(item);\n        }\n\n        protected override Texture GetIconForItem(TreeViewItem item)\n        {\n            if (item != null && item.icon != null)\n            {\n                var icon = item.icon;\n                var folderItem = item as AssetsTreeViewDataSource.FolderTreeItemBase;\n                if (folderItem != null)\n                {\n                    if (folderItem.IsEmpty)\n                        icon = emptyFolderTexture;\n                    else if (m_TreeView.data.IsExpanded(folderItem))\n                        icon = openFolderTexture;\n                }\n\n                return icon;\n            }\n\n            SearchFilterTreeItem searchFilterItem = item as SearchFilterTreeItem;\n            if (searchFilterItem != null)\n            {\n                if (IsVisibleRootNode(item))\n                    return k_FavoritesIcon;\n                if (searchFilterItem.isFolder)\n                    return k_FavoriteFolderIcon;\n                else\n                    return k_FavoriteFilterIcon;\n            }\n            return base.GetIconForItem(item);\n        }\n\n        public static float GetListAreaGridSize()\n        {\n            float previewSize = -1f;\n            if (ProjectBrowser.s_LastInteractedProjectBrowser != null)\n                previewSize = ProjectBrowser.s_LastInteractedProjectBrowser.listAreaGridSize;\n            return previewSize;\n        }\n\n        virtual internal void BeginCreateSavedFilter(SearchFilter filter)\n        {\n            string savedFilterName = \"New Saved Search\";\n\n            m_IsCreatingSavedFilter = true;\n            int instanceID = SavedSearchFilters.AddSavedFilter(savedFilterName, filter, GetListAreaGridSize());\n            m_TreeView.Frame(instanceID, true, false);\n\n            // Start naming the asset\n            m_TreeView.state.renameOverlay.BeginRename(savedFilterName, instanceID, 0f);\n        }\n\n        override protected void RenameEnded()\n        {\n            int instanceID = GetRenameOverlay().userData;\n            ProjectBrowser.ItemType type = ProjectBrowser.GetItemType(instanceID);\n\n            if (m_IsCreatingSavedFilter)\n            {\n                // Create saved filter\n                m_IsCreatingSavedFilter = false;\n\n                if (GetRenameOverlay().userAcceptedRename)\n                {\n                    SavedSearchFilters.SetName(instanceID,  GetRenameOverlay().name);\n                    m_TreeView.SetSelection(new[] { instanceID }, true);\n                }\n                else\n                    SavedSearchFilters.RemoveSavedFilter(instanceID);\n            }\n            else if (type == ProjectBrowser.ItemType.SavedFilter)\n            {\n                // Renamed saved filter\n                if (GetRenameOverlay().userAcceptedRename)\n                {\n                    SavedSearchFilters.SetName(instanceID,  GetRenameOverlay().name);\n                }\n            }\n            else\n            {\n                // Let base handle renaming of folders\n                base.RenameEnded();\n\n                // Ensure to sync filter to new folder name (so we still show the contents of the folder)\n                if (GetRenameOverlay().userAcceptedRename)\n                    m_TreeView.NotifyListenersThatSelectionChanged();\n            }\n        }\n    }\n\n\n    //------------------------------------------------\n    // DataSource section\n\n    internal class ProjectBrowserColumnOneTreeViewDataSource : LazyTreeViewDataSource\n    {\n        static string kProjectBrowserString = \"ProjectBrowser\";\n        static Texture2D s_FolderIcon = EditorGUIUtility.FindTexture(EditorResources.folderIconName);\n\n        public bool skipHiddenPackages { get; set; }\n\n        public ProjectBrowserColumnOneTreeViewDataSource(TreeViewController treeView, bool skipHidden) : base(treeView)\n        {\n            showRootItem = false;\n            rootIsCollapsable = false;\n            skipHiddenPackages = skipHidden;\n            SavedSearchFilters.AddChangeListener(ReloadData); // We reload on change\n        }\n\n        public override bool IsExpandable(TreeViewItem item)\n        {\n            return item.hasChildren && (item != m_RootItem || rootIsCollapsable);\n        }\n\n        public override bool CanBeMultiSelected(TreeViewItem item)\n        {\n            return ProjectBrowser.GetItemType(item.id) != ProjectBrowser.ItemType.SavedFilter;\n        }\n\n        public override bool CanBeParent(TreeViewItem item)\n        {\n            return !(item is SearchFilterTreeItem) || SavedSearchFilters.AllowsHierarchy();\n        }\n\n        public bool IsVisibleRootNode(TreeViewItem item)\n        {\n            // The main root Item is invisible the next level is visible root items\n            return (item.parent != null && item.parent.parent == null);\n        }\n\n        public override bool IsRenamingItemAllowed(TreeViewItem item)\n        {\n            // The 'Assets' root and 'Filters' roots are not allowed to be renamed\n            if (IsVisibleRootNode(item))\n                return false;\n\n            switch (ProjectBrowser.GetItemType(item.id))\n            {\n                case ProjectBrowser.ItemType.Asset:\n                    return InternalEditorUtility.CanRenameAsset(item.id);\n                case ProjectBrowser.ItemType.SavedFilter:\n                    return true;\n                default:\n                    return false;\n            }\n        }\n\n        public override void FetchData()\n        {\n            bool firstInitialize = !isInitialized;\n            m_RootItem = new TreeViewItem(0, 0, null, \"Invisible Root Item\");\n            SetExpanded(m_RootItem, true); // ensure always visible\n\n            // We want three roots: Favorites, Assets, and Packages\n            List<TreeViewItem> visibleRoots = new List<TreeViewItem>();\n\n            // Favorites root\n            TreeViewItem savedFiltersRootItem = SavedSearchFilters.ConvertToTreeView();\n            visibleRoots.Add(savedFiltersRootItem);\n\n            // Assets root\n            int assetsFolderInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(\"Assets\");\n            int depth = 0;\n            string displayName = \"Assets\";\n            AssetsTreeViewDataSource.RootTreeItem assetRootItem = new AssetsTreeViewDataSource.RootTreeItem(assetsFolderInstanceID, depth, m_RootItem, displayName);\n            assetRootItem.icon = s_FolderIcon;\n            visibleRoots.Add(assetRootItem);\n\n            // Packages root\n            displayName = PackageManager.Folders.GetPackagesPath();\n            AssetsTreeViewDataSource.RootTreeItem packagesRootItem = new AssetsTreeViewDataSource.RootTreeItem(ProjectBrowser.kPackagesFolderInstanceId, depth, m_RootItem, displayName);\n            packagesRootItem.icon = s_FolderIcon;\n            visibleRoots.Add(packagesRootItem);\n\n            m_RootItem.children = visibleRoots;\n\n            // Set global expanded state for roots from EditorPrefs (must be before building the rows)\n            if (firstInitialize)\n            {\n                foreach (TreeViewItem item in m_RootItem.children)\n                {\n                    bool expanded = EditorPrefs.GetBool(kProjectBrowserString + item.displayName, true);\n                    SetExpanded(item, expanded);\n                }\n            }\n\n            // Build rows\n            //-----------\n            m_Rows = new List<TreeViewItem>(100);\n\n            // Favorites\n            savedFiltersRootItem.parent = m_RootItem;\n            m_Rows.Add(savedFiltersRootItem);\n            if (IsExpanded(savedFiltersRootItem))\n            {\n                foreach (var f in savedFiltersRootItem.children)\n                    m_Rows.Add(f);\n            }\n            else\n            {\n                savedFiltersRootItem.children = CreateChildListForCollapsedParent();\n            }\n\n            // Asset folders\n            m_Rows.Add(assetRootItem);\n            ReadAssetDatabase(\"Assets\", assetRootItem, depth + 1, m_Rows);\n\n            // Individual Package folders (under the Packages root item)\n            m_Rows.Add(packagesRootItem);\n            var packages = PackageManagerUtilityInternal.GetAllVisiblePackages(skipHiddenPackages);\n            if (IsExpanded(packagesRootItem))\n            {\n                depth++;\n                foreach (var package in packages)\n                {\n                    var packageFolderInstanceId = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(package.assetPath);\n\n                    displayName = !string.IsNullOrEmpty(package.displayName) ? package.displayName : package.name;\n                    AssetsTreeViewDataSource.PackageTreeItem packageItem = new AssetsTreeViewDataSource.PackageTreeItem(packageFolderInstanceId, depth, packagesRootItem, displayName);\n                    packageItem.icon = s_FolderIcon;\n                    packagesRootItem.AddChild(packageItem);\n                    m_Rows.Add(packageItem);\n                    ReadAssetDatabase(package.assetPath, packageItem, depth + 1, m_Rows);\n                }\n            }\n            else\n            {\n                if (packages.Length > 0)\n                    packagesRootItem.children = CreateChildListForCollapsedParent();\n            }\n\n            m_NeedRefreshRows = false;\n        }\n\n        static bool HasSubFolders(IHierarchyProperty property)\n        {\n            var path = AssetDatabase.GUIDToAssetPath(property.guid);\n            var subFolders = AssetDatabase.GetSubFolders(path);\n            return subFolders.Length > 0;\n        }\n\n        private void ReadAssetDatabase(string assetFolderRootPath, TreeViewItem parent, int baseDepth, IList<TreeViewItem> allRows)\n        {\n            // Read from Assets directory\n            IHierarchyProperty property = new HierarchyProperty(assetFolderRootPath);\n            property.Reset();\n\n            if (!IsExpanded(parent))\n            {\n                if (HasSubFolders(property))\n                    parent.children = CreateChildListForCollapsedParent();\n                return;\n            }\n\n            Texture2D folderIcon = EditorGUIUtility.FindTexture(EditorResources.folderIconName);\n\n            List<TreeViewItem> allFolders = new List<TreeViewItem>();\n            var expandedIDs = m_TreeView.state.expandedIDs.ToArray();\n            while (property.Next(expandedIDs))\n            {\n                if (property.isFolder)\n                {\n                    AssetsTreeViewDataSource.FolderTreeItem folderItem = new AssetsTreeViewDataSource.FolderTreeItem(property.guid, !property.hasChildren, property.GetInstanceIDIfImported(), baseDepth + property.depth, null, property.name);\n                    folderItem.icon = folderIcon;\n                    allFolders.Add(folderItem);\n                    allRows.Add(folderItem);\n                    if (!IsExpanded(folderItem))\n                    {\n                        if (HasSubFolders(property))\n                            folderItem.children = CreateChildListForCollapsedParent();\n                    }\n                    else // expanded status does not get updated when deleting/moving folders. We need to check if the expanded folder still has subFolders when reading the AssetDatabase\n                    {\n                        if (!HasSubFolders(property))\n                            SetExpanded(folderItem, false);\n                    }\n                }\n            }\n\n            // Fix references\n            TreeViewUtility.SetChildParentReferences(allFolders, parent);\n        }\n\n        public override void SetExpandedWithChildren(int id, bool expand)\n        {\n            base.SetExpandedWithChildren(id, expand);\n            PersistExpandedState(id, expand);\n        }\n\n        public override bool SetExpanded(int id, bool expand)\n        {\n            if (base.SetExpanded(id, expand))\n            {\n                PersistExpandedState(id, expand);\n                return true;\n            }\n            return false;\n        }\n\n        void PersistExpandedState(int id, bool expand)\n        {\n            // Persist expanded state for ProjectBrowsers\n            InternalEditorUtility.expandedProjectWindowItems = expandedIDs.ToArray();\n\n            if (m_RootItem.hasChildren)\n            {\n                // Set global expanded state of roots (Assets folder and Favorites root)\n                foreach (TreeViewItem item in m_RootItem.children)\n                    if (item.id == id)\n                        EditorPrefs.SetBool(kProjectBrowserString + item.displayName, expand);\n            }\n        }\n\n        protected override void GetParentsAbove(int id, HashSet<int> parentsAbove)\n        {\n            if (SavedSearchFilters.IsSavedFilter(id))\n            {\n                parentsAbove.Add(SavedSearchFilters.GetRootInstanceID());\n            }\n            else\n            {\n                // AssetDatabase folders (in Assets or Packages)\n                var path = AssetDatabase.GetAssetPath(id);\n                if (Directory.Exists(path))\n                    parentsAbove.UnionWith(ProjectWindowUtil.GetAncestors(id));\n            }\n        }\n\n        protected override void GetParentsBelow(int id, HashSet<int> parentsBelow)\n        {\n            var extra = GetParentsBelow(id);\n            parentsBelow.UnionWith(extra);\n        }\n\n        private HashSet<int> GetParentsBelow(int id)\n        {\n            // Add all children expanded ids to hashset\n            HashSet<int> parentsBelow = new HashSet<int>();\n\n            // Check if packages instance\n            if (id == ProjectBrowser.kPackagesFolderInstanceId)\n            {\n                parentsBelow.Add(id);\n                var packages = PackageManagerUtilityInternal.GetAllVisiblePackages(skipHiddenPackages);\n                foreach (var package in packages)\n                {\n                    var packageFolderInstanceId = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(package.assetPath);\n                    parentsBelow.UnionWith(GetParentsBelow(packageFolderInstanceId));\n                }\n                return parentsBelow;\n            }\n\n            var path = AssetDatabase.GetAssetPath(id);\n            IHierarchyProperty search = new HierarchyProperty(path);\n            if (search.Find(id, null))\n            {\n                parentsBelow.Add(id);\n\n                int depth = search.depth;\n                while (search.Next(null) && search.depth > depth)\n                {\n                    if (search.isFolder && search.hasChildren)\n                        parentsBelow.Add(search.instanceID);\n                }\n            }\n            return parentsBelow;\n        }\n    }\n\n    internal class ProjectBrowserColumnOneTreeViewDragging : AssetsTreeViewDragging\n    {\n        public ProjectBrowserColumnOneTreeViewDragging(TreeViewController treeView) : base(treeView)\n        {\n        }\n\n        public override void StartDrag(TreeViewItem draggedItem, List<int> draggedItemIDs)\n        {\n            if (SavedSearchFilters.IsSavedFilter(draggedItem.id))\n            {\n                // Root Filters Item is not allowed to be dragged\n                if (draggedItem.id == SavedSearchFilters.GetRootInstanceID())\n                    return;\n            }\n\n            ProjectWindowUtil.StartDrag(draggedItem.id, draggedItemIDs);\n        }\n\n        public override DragAndDropVisualMode DoDrag(TreeViewItem parentItem, TreeViewItem targetItem, bool perform, DropPosition dropPos)\n        {\n            if (targetItem == null)\n                return DragAndDropVisualMode.None;\n\n            object savedFilterData = DragAndDrop.GetGenericData(ProjectWindowUtil.k_DraggingFavoriteGenericData);\n\n            // Dragging saved filter\n            if (savedFilterData != null)\n            {\n                int instanceID = (int)savedFilterData;\n                if (targetItem is SearchFilterTreeItem && parentItem is SearchFilterTreeItem)// && targetItem.id != draggedInstanceID && parentItem.id != draggedInstanceID)\n                {\n                    bool validMove = SavedSearchFilters.CanMoveSavedFilter(instanceID, parentItem.id, targetItem.id, dropPos == DropPosition.Below);\n                    if (validMove && perform)\n                    {\n                        SavedSearchFilters.MoveSavedFilter(instanceID, parentItem.id, targetItem.id, dropPos == DropPosition.Below);\n                        m_TreeView.SetSelection(new[] { instanceID }, false);\n                        m_TreeView.NotifyListenersThatSelectionChanged();\n                    }\n                    return validMove ? DragAndDropVisualMode.Copy : DragAndDropVisualMode.None;\n                }\n                return DragAndDropVisualMode.None;\n            }\n            // Dragging of folders into filters\n            else\n            {\n                // Check if we are dragging a single folder\n                if (targetItem is SearchFilterTreeItem)\n                {\n                    string genericData = DragAndDrop.GetGenericData(ProjectWindowUtil.k_IsFolderGenericData) as string;\n                    if (genericData == \"isFolder\")\n                    {\n                        if (perform)\n                        {\n                            Object[] objs = DragAndDrop.objectReferences;\n                            if (objs.Length > 0)\n                            {\n                                string path = AssetDatabase.GetAssetPath(objs[0].GetInstanceID());\n                                if (!string.IsNullOrEmpty(path))\n                                {\n                                    // TODO: Fix with new AssetDatabase API when it is ready (GetName)\n                                    string folderName = new DirectoryInfo(path).Name;\n                                    SearchFilter searchFilter = new SearchFilter();\n                                    searchFilter.folders = new[] {path};\n                                    bool addAsChild = targetItem == parentItem;\n\n                                    float previewSize = ProjectBrowserColumnOneTreeViewGUI.GetListAreaGridSize();\n                                    int instanceID = SavedSearchFilters.AddSavedFilterAfterInstanceID(folderName, searchFilter, previewSize, targetItem.id, addAsChild);\n                                    m_TreeView.SetSelection(new[] { instanceID }, false);\n                                    m_TreeView.NotifyListenersThatSelectionChanged();\n                                }\n                                else\n                                {\n                                    Debug.Log(\"Could not get asset path from id \" + objs[0].GetInstanceID());\n                                }\n                            }\n                        }\n                        return DragAndDropVisualMode.Copy; // Allow dragging folders to filters\n                    }\n                    return DragAndDropVisualMode.None; // Assets that are not folders are not allowed to be dragged to filters\n                }\n            }\n            //  Assets are handled by base\n            return base.DoDrag(parentItem, targetItem, perform, dropPos);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ProjectBrowser/ProjectBrowserPopups.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace UnityEditor\n{\n    internal class PopupList : PopupWindowContent\n    {\n        public delegate void OnSelectCallback(ListElement element);\n        static EditorGUI.RecycledTextEditor s_RecycledEditor = new EditorGUI.RecycledTextEditor();\n        static string s_TextFieldName = \"ProjectBrowserPopupsTextField\";\n        static int s_TextFieldHash = s_TextFieldName.GetHashCode();\n        public enum Gravity\n        {\n            Top,\n            Bottom\n        }\n\n        public class ListElement\n        {\n            public GUIContent m_Content;\n            private float m_FilterScore;\n            private bool m_Selected;\n            private bool m_WasSelected;\n            private bool m_PartiallySelected;\n            private bool m_Enabled;\n            private string[] m_Types;\n\n            public ListElement(string text, bool selected, float score) : this(text, new [] { text }, selected, score) { }\n\n            public ListElement(string text, string[] types, bool selected, float score)\n            {\n                m_Content = new GUIContent(text);\n                if (!string.IsNullOrEmpty(m_Content.text))\n                {\n                    char[] a = m_Content.text.ToCharArray();\n                    a[0] = char.ToUpper(a[0]);\n                    m_Content.text = new string(a);\n                }\n                m_Types = types;\n                m_Selected = selected;\n                filterScore = score;\n                m_PartiallySelected = false;\n                m_Enabled = true;\n            }\n\n            public ListElement(string text, bool selected)\n            {\n                m_Content = new GUIContent(text);\n                m_Selected = selected;\n                filterScore = 0;\n                m_PartiallySelected = false;\n                m_Enabled = true;\n            }\n\n            public ListElement(string text) : this(text, false)\n            {\n            }\n\n            public float filterScore\n            {\n                get\n                {\n                    return m_WasSelected ? float.MaxValue : m_FilterScore;\n                }\n                set\n                {\n                    m_FilterScore = value;\n                    ResetScore();\n                }\n            }\n\n            public bool selected\n            {\n                get\n                {\n                    return m_Selected;\n                }\n                set\n                {\n                    m_Selected = value;\n                    if (m_Selected)\n                        m_WasSelected = true;\n                }\n            }\n\n            public bool enabled\n            {\n                get\n                {\n                    return m_Enabled;\n                }\n                set\n                {\n                    m_Enabled = value;\n                }\n            }\n\n            public bool partiallySelected\n            {\n                get\n                {\n                    return m_PartiallySelected;\n                }\n                set\n                {\n                    m_PartiallySelected = value;\n                    if (m_PartiallySelected)\n                        m_WasSelected = true;\n                }\n            }\n\n            public string text\n            {\n                get\n                {\n                    return m_Content.text;\n                }\n                set\n                {\n                    m_Content.text = value;\n                }\n            }\n\n            public IEnumerable<string> types\n            {\n                get\n                {\n                    return m_Types;\n                }\n            }\n\n            public void ResetScore()\n            {\n                m_WasSelected = m_Selected || m_PartiallySelected;\n            }\n        }\n\n        public class InputData\n        {\n            public List<ListElement> m_ListElements;\n            public bool m_CloseOnSelection;\n            public bool m_AllowCustom;\n            public bool m_EnableAutoCompletion = true;\n            public bool m_SortAlphabetically;\n            public OnSelectCallback m_OnSelectCallback;\n            public int m_MaxCount;\n\n            public InputData()\n            {\n                m_ListElements = new List<ListElement>();\n            }\n\n            public void DeselectAll()\n            {\n                foreach (ListElement element in m_ListElements)\n                {\n                    element.selected = false;\n                    element.partiallySelected = false;\n                }\n            }\n\n            public void ResetScores()\n            {\n                foreach (var element in m_ListElements)\n                    element.ResetScore();\n            }\n\n            public virtual IEnumerable<ListElement> BuildQuery(string prefix)\n            {\n                if (prefix == \"\")\n                    return m_ListElements;\n                else\n                    return m_ListElements.Where(\n                        element => element.m_Content.text.StartsWith(prefix, System.StringComparison.OrdinalIgnoreCase)\n                    );\n            }\n\n            public IEnumerable<ListElement> GetFilteredList(string prefix)\n            {\n                IEnumerable<ListElement> res = BuildQuery(prefix);\n                if (m_MaxCount > 0)\n                    res = res.OrderByDescending(element => element.filterScore).Take(m_MaxCount);\n                if (m_SortAlphabetically)\n                    return res.OrderBy(element => element.text.ToLower());\n                else\n                    return res;\n            }\n\n            public int GetFilteredCount(string prefix)\n            {\n                IEnumerable<ListElement> res = BuildQuery(prefix);\n                if (m_MaxCount > 0)\n                    res = res.Take(m_MaxCount);\n                return res.Count();\n            }\n\n            public void AddElement(string label, string[] types)\n            {\n                var res = new ListElement(label, types, false, -1);\n                m_ListElements.Add(res);\n            }\n\n            public ListElement NewOrMatchingElement(string label)\n            {\n                foreach (var element in m_ListElements)\n                {\n                    if (element.text.Equals(label, StringComparison.OrdinalIgnoreCase))\n                        return element;\n                }\n\n                var res = new ListElement(label, false, -1);\n                m_ListElements.Add(res);\n                return res;\n            }\n        }\n\n        private class Styles\n        {\n            public GUIStyle menuItem = \"MenuItem\";\n            public GUIStyle menuItemMixed = \"MenuItemMixed\";\n            public GUIStyle background = \"grey_border\";\n            public GUIStyle customTextField;\n            public GUIStyle customTextFieldCancelButton;\n            public GUIStyle customTextFieldCancelButtonEmpty;\n            public Styles()\n            {\n                customTextField = new GUIStyle(EditorStyles.toolbarSearchField);\n                customTextFieldCancelButton = new GUIStyle(EditorStyles.toolbarSearchFieldCancelButton);\n                customTextFieldCancelButtonEmpty = new GUIStyle(EditorStyles.toolbarSearchFieldCancelButtonEmpty);\n            }\n        }\n\n        // Static\n        static Styles s_Styles;\n\n        // State\n        private InputData m_Data;\n\n        // Layout\n        const float k_LineHeight = 16;\n        const float k_TextFieldHeight = 16;\n        const float k_Margin = 10;\n        Gravity m_Gravity;\n\n        string m_EnteredTextCompletion = \"\";\n        string m_EnteredText = \"\";\n        int m_SelectedCompletionIndex = 0;\n\n        public PopupList(InputData inputData) : this(inputData, null) {}\n\n        public PopupList(InputData inputData, string initialSelectionLabel)\n        {\n            m_Data = inputData;\n            m_Data.ResetScores();\n            SelectNoCompletion();\n            m_Gravity = Gravity.Top;\n            if (initialSelectionLabel != null)\n            {\n                m_EnteredTextCompletion = initialSelectionLabel;\n                UpdateCompletion();\n            }\n        }\n\n        public override void OnClose()\n        {\n            if (m_Data != null)\n                m_Data.ResetScores();\n        }\n\n        public virtual float GetWindowHeight()\n        {\n            int count = (m_Data.m_MaxCount == 0) ? m_Data.GetFilteredCount(m_EnteredText) : m_Data.m_MaxCount;\n            return count * k_LineHeight + 2 * k_Margin + (m_Data.m_AllowCustom ? k_TextFieldHeight : 0);\n        }\n\n        public virtual float GetWindowWidth()\n        {\n            return 150f;\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            return new Vector2(GetWindowWidth(), GetWindowHeight());\n        }\n\n        public override void OnGUI(Rect windowRect)\n        {\n            Event evt = Event.current;\n            // We do not use the layout event\n            if (evt.type == EventType.Layout)\n                return;\n\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            if (evt.type == EventType.KeyDown && evt.keyCode == KeyCode.Escape)\n            {\n                editorWindow.Close();\n                GUIUtility.ExitGUI();\n            }\n\n            if (m_Gravity == Gravity.Bottom)\n            {\n                DrawList(editorWindow, windowRect);\n                DrawCustomTextField(editorWindow, windowRect);\n            }\n            else\n            {\n                DrawCustomTextField(editorWindow, windowRect);\n                DrawList(editorWindow, windowRect);\n            }\n\n            // Background with 1 pixel border (rendered above content)\n            if (evt.type == EventType.Repaint)\n                s_Styles.background.Draw(new Rect(windowRect.x, windowRect.y, windowRect.width, windowRect.height), false, false, false, false);\n        }\n\n        private void DrawCustomTextField(EditorWindow editorWindow, Rect windowRect)\n        {\n            if (!m_Data.m_AllowCustom)\n                return;\n\n            Event evt = Event.current;\n            bool enableAutoCompletion = m_Data.m_EnableAutoCompletion;\n            bool closeWindow = false;\n            bool useEventBeforeTextField = false;\n            bool clearText = false;\n\n            string textBeforeEdit = CurrentDisplayedText();\n\n            // Handle \"special\" keyboard input\n            if (evt.type == EventType.KeyDown)\n            {\n                switch (evt.keyCode)\n                {\n                    case KeyCode.Comma:\n                    case KeyCode.Space:\n                    case KeyCode.Tab:\n                    case KeyCode.Return:\n                        if (textBeforeEdit != \"\")\n                        {\n                            // Toggle state\n                            if (m_Data.m_OnSelectCallback != null)\n                                m_Data.m_OnSelectCallback(m_Data.NewOrMatchingElement(textBeforeEdit));\n\n                            if (evt.keyCode == KeyCode.Tab || evt.keyCode == KeyCode.Comma)\n                                clearText = true;  // to ease multiple entries (it is unlikely that the same filter is used more than once)\n\n                            // Auto close\n                            if (m_Data.m_CloseOnSelection || evt.keyCode == KeyCode.Return)\n                                closeWindow = true;\n                        }\n                        useEventBeforeTextField = true;\n                        break;\n                    case KeyCode.Delete:\n                    case KeyCode.Backspace:\n                        enableAutoCompletion = false;\n                        // Don't use the event yet, so the textfield below can get it and delete the selection\n                        break;\n\n                    case KeyCode.DownArrow:\n                        ChangeSelectedCompletion(1);\n                        useEventBeforeTextField = true;\n                        break;\n\n                    case KeyCode.UpArrow:\n                        ChangeSelectedCompletion(-1);\n                        useEventBeforeTextField = true;\n                        break;\n                    case KeyCode.None:\n                        if (evt.character == ' ' || evt.character == ',')\n                            useEventBeforeTextField = true;\n                        break;\n                }\n            }\n\n            string textFieldText;\n            // Draw textfield\n            {\n                bool dummy = false;\n                Rect pos = new Rect(windowRect.x + k_Margin / 2, windowRect.y + (m_Gravity == Gravity.Top ? (k_Margin / 2) : (windowRect.height - k_TextFieldHeight - k_Margin / 2)), windowRect.width - k_Margin - 14, k_TextFieldHeight);\n\n                GUI.SetNextControlName(s_TextFieldName);\n                EditorGUI.FocusTextInControl(s_TextFieldName);\n                int id = EditorGUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, pos);\n\n                if (useEventBeforeTextField)\n                    evt.Use();  // We have to delay this until after we get the control id, otherwise the id we get is just -1\n\n                if (GUIUtility.keyboardControl == 0)\n                    GUIUtility.keyboardControl = id;\n\n                textFieldText =  EditorGUI.DoTextField(s_RecycledEditor, id, pos, textBeforeEdit, s_Styles.customTextField, null, out dummy, false, false, false);\n                Rect buttonRect = pos;\n                buttonRect.x += pos.width;\n                buttonRect.width = 14;\n                // Draw \"clear textfield\" button (X)\n                if ((GUI.Button(buttonRect, GUIContent.none, textFieldText != \"\" ? s_Styles.customTextFieldCancelButton : s_Styles.customTextFieldCancelButtonEmpty) && textFieldText != \"\")\n                    || clearText)\n                {\n                    textFieldText = EditorGUI.s_OriginalText = s_RecycledEditor.text = \"\";\n                    s_RecycledEditor.cursorIndex = 0;\n                    s_RecycledEditor.selectIndex = 0;\n                    enableAutoCompletion = false;\n                }\n            }\n\n            // Handle autocompletion\n            if (textBeforeEdit != textFieldText)\n            {\n                m_EnteredText = (0 <= s_RecycledEditor.cursorIndex && s_RecycledEditor.cursorIndex < textFieldText.Length) ? textFieldText.Substring(0, s_RecycledEditor.cursorIndex) : textFieldText;\n\n                if (enableAutoCompletion)\n                    UpdateCompletion();\n                else\n                    SelectNoCompletion();\n            }\n\n            if (closeWindow)\n                editorWindow.Close();\n        }\n\n        private string CurrentDisplayedText()\n        {\n            return m_EnteredTextCompletion != \"\" ? m_EnteredTextCompletion : m_EnteredText;\n        }\n\n        private void UpdateCompletion()\n        {\n            if (!m_Data.m_EnableAutoCompletion)\n                return;\n            IEnumerable<string> query = m_Data.GetFilteredList(m_EnteredText).Select(element => element.text);\n\n            if (m_EnteredTextCompletion != \"\" && m_EnteredTextCompletion.StartsWith(m_EnteredText, System.StringComparison.OrdinalIgnoreCase))\n            {\n                m_SelectedCompletionIndex = query.TakeWhile(element => element != m_EnteredTextCompletion).Count();\n                // m_EnteredTextCompletion is already correct\n            }\n            else\n            {\n                // Clamp m_SelectedCompletionIndex to 0..query.Count () - 1\n                if (m_SelectedCompletionIndex < 0)\n                    m_SelectedCompletionIndex = 0;\n                else if (m_SelectedCompletionIndex >= query.Count())\n                    m_SelectedCompletionIndex = query.Count() - 1;\n\n                m_EnteredTextCompletion = query.Skip(m_SelectedCompletionIndex).DefaultIfEmpty(\"\").FirstOrDefault();\n            }\n            AdjustRecycledEditorSelectionToCompletion();\n        }\n\n        private void ChangeSelectedCompletion(int change)\n        {\n            int count = m_Data.GetFilteredCount(m_EnteredText);\n            if (m_SelectedCompletionIndex == -1 && change < 0)  // specal case for initial selection\n                m_SelectedCompletionIndex = count;\n\n            int index = count > 0 ? (m_SelectedCompletionIndex + change + count) % count : 0;\n            SelectCompletionWithIndex(index);\n        }\n\n        private void SelectCompletionWithIndex(int index)\n        {\n            m_SelectedCompletionIndex = index;\n            m_EnteredTextCompletion = \"\";\n            UpdateCompletion();\n        }\n\n        private void SelectNoCompletion()\n        {\n            m_SelectedCompletionIndex = -1;\n            m_EnteredTextCompletion = \"\";\n            AdjustRecycledEditorSelectionToCompletion();\n        }\n\n        private void AdjustRecycledEditorSelectionToCompletion()\n        {\n            if (m_EnteredTextCompletion != \"\")\n            {\n                s_RecycledEditor.text = m_EnteredTextCompletion;\n                EditorGUI.s_OriginalText = m_EnteredTextCompletion;\n                s_RecycledEditor.cursorIndex = m_EnteredText.Length;\n                s_RecycledEditor.selectIndex = m_EnteredTextCompletion.Length; //the selection goes from s_RecycledEditor.cursorIndex (already set by DoTextField) to s_RecycledEditor.selectIndex\n            }\n        }\n\n        private void DrawList(EditorWindow editorWindow, Rect windowRect)\n        {\n            Event evt = Event.current;\n\n            int i = -1;\n            foreach (var element in m_Data.GetFilteredList(m_EnteredText))\n            {\n                i++;\n                Rect rect = new Rect(windowRect.x, windowRect.y + k_Margin + i * k_LineHeight + (m_Gravity == Gravity.Top && m_Data.m_AllowCustom ? k_TextFieldHeight : 0), windowRect.width, k_LineHeight);\n\n                switch (evt.type)\n                {\n                    case EventType.Repaint:\n                    {\n                        GUIStyle style = element.partiallySelected ? s_Styles.menuItemMixed : s_Styles.menuItem;\n                        bool selected = element.selected || element.partiallySelected;\n                        bool focused = false;\n                        bool isHover = i == m_SelectedCompletionIndex;\n                        bool isActive = selected;\n\n                        using (new EditorGUI.DisabledScope(!element.enabled))\n                        {\n                            GUIContent content = element.m_Content;\n                            style.Draw(rect, content, isHover, isActive, selected, focused);\n                        }\n                    }\n                    break;\n                    case EventType.MouseDown:\n                    {\n                        if (Event.current.button == 0 && rect.Contains(Event.current.mousePosition) && element.enabled)\n                        {\n                            // Toggle state\n                            if (m_Data.m_OnSelectCallback != null)\n                                m_Data.m_OnSelectCallback(element);\n\n                            evt.Use();\n\n                            // Auto close\n                            if (m_Data.m_CloseOnSelection)\n                                editorWindow.Close();\n                        }\n                    }\n                    break;\n                    case EventType.MouseMove:\n                    {\n                        if (rect.Contains(Event.current.mousePosition))\n                        {\n                            SelectCompletionWithIndex(i);\n                            evt.Use();\n                        }\n                    }\n                    break;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ProjectBrowser/ProjectWindowUtil.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Text.RegularExpressions;\nusing UnityEditor.Audio;\nusing UnityEditor.Compilation;\nusing UnityEditor.ProjectWindowCallback;\nusing UnityEditor.SceneManagement;\nusing UnityEditorInternal;\nusing UnityEditor.Experimental;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEditor.Utils;\nusing UnityEditor.VersionControl;\nusing UnityEngine;\nusing UnityEditor.U2D;\nusing UnityEngine.Internal;\nusing UnityEngine.Audio;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing Object = UnityEngine.Object;\nusing UnityEngine.U2D;\n\nnamespace UnityEditor\n{\n    internal class DragAndDropDelay\n    {\n        public Vector2 mouseDownPosition;\n\n        public bool CanStartDrag()\n        {\n            return Vector2.Distance(mouseDownPosition, Event.current.mousePosition) > 6;\n        }\n    }\n\n    // Callbacks to be used when creating assets via the project window\n    // You can extend the EndNameEditAction and write your own callback\n    // It is done this way instead of via a delegate because the action\n    // needs to survive an assembly reload.\n    namespace ProjectWindowCallback\n    {\n        public abstract class EndNameEditAction : ScriptableObject\n        {\n            public virtual void OnEnable()\n            {\n                hideFlags = HideFlags.HideAndDontSave;\n            }\n\n            public abstract void Action(int instanceId, string pathName, string resourceFile);\n            public virtual void Cancelled(int instanceId, string pathName, string resourceFile) {}\n\n            public virtual void CleanUp()\n            {\n                DestroyImmediate(this);\n            }\n        }\n\n        internal class DoCreateNewDefaultAsset : EndNameEditAction\n        {\n            public override void Action(int instanceId, string pathName, string resourceFile)\n            {\n                var cleanPath = AssetDatabase.GenerateUniqueAssetPath(pathName);\n                AssetDatabase.CreateAsset(EditorUtility.InstanceIDToObject(instanceId),\n                    cleanPath);\n                var obj = AssetDatabase.LoadMainAssetAtPath(cleanPath);\n                var name = obj.name;\n                ObjectFactory.FinalizeObjectAndAwake(obj);\n                obj.name = name;\n                AssetDatabase.SaveAssetIfDirty(obj);\n                ProjectWindowUtil.FrameObjectInProjectWindow(instanceId);\n            }\n\n            public override void Cancelled(int instanceId, string pathName, string resourceFile)\n            {\n                Selection.activeObject = null;\n            }\n        }\n\n        internal class DoCreateNewAsset : EndNameEditAction\n        {\n            public override void Action(int instanceId, string pathName, string resourceFile)\n            {\n                AssetDatabase.CreateAsset(EditorUtility.InstanceIDToObject(instanceId),\n                    AssetDatabase.GenerateUniqueAssetPath(pathName));\n                ProjectWindowUtil.FrameObjectInProjectWindow(instanceId);\n            }\n\n            public override void Cancelled(int instanceId, string pathName, string resourceFile)\n            {\n                Selection.activeObject = null;\n            }\n        }\n\n        internal class DoCreateFolder : EndNameEditAction\n        {\n            public override void Action(int instanceId, string pathName, string resourceFile)\n            {\n                string guid = AssetDatabase.CreateFolder(Path.GetDirectoryName(pathName), Path.GetFileName(pathName));\n                Object o = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid), typeof(Object));\n                ProjectWindowUtil.ShowCreatedAsset(o);\n            }\n        }\n\n        internal class DoCreateScene : EndNameEditAction\n        {\n            public override void Action(int instanceId, string pathName, string resourceFile)\n            {\n                bool createDefaultGameObjects = true;\n                if (EditorSceneManager.CreateSceneAsset(pathName, createDefaultGameObjects))\n                {\n                    Object sceneAsset = AssetDatabase.LoadAssetAtPath(pathName, typeof(SceneAsset));\n                    ProjectWindowUtil.ShowCreatedAsset(sceneAsset);\n                }\n            }\n        }\n\n        internal class DoCreateFolderWithTemplates : EndNameEditAction\n        {\n            public string ResourcesTemplatePath = \"Resources/ScriptTemplates\";\n\n            public bool UseCustomPath = false;\n\n            public IList<string> templates { get; set; }\n\n            public override void Action(int instanceId, string pathName, string resourceFile)\n            {\n                var fileName = Path.GetFileName(pathName);\n                string guid = AssetDatabase.CreateFolder(Path.GetDirectoryName(pathName), fileName);\n                string basePath = UseCustomPath ? ResourcesTemplatePath :\n                    Path.Combine(EditorApplication.applicationContentsPath, ResourcesTemplatePath);\n\n                foreach (var template in templates ?? Enumerable.Empty<string>())\n                {\n                    var templateNameWithoutTxt = template.Replace(\".txt\", string.Empty);\n                    var templateExtension = Path.GetExtension(templateNameWithoutTxt);\n\n                    ProjectWindowUtil.CreateScriptAssetFromTemplate(Path.Combine(pathName, fileName + templateExtension), Path.Combine(basePath, template));\n                }\n\n                Object o = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid), typeof(Object));\n                ProjectWindowUtil.ShowCreatedAsset(o);\n            }\n        }\n\n        internal class DoCreatePrefab : EndNameEditAction\n        {\n            public override void Action(int instanceId, string pathName, string resourceFile)\n            {\n                var empty = new GameObject(\"New Prefab\");\n                try\n                {\n                    Object o = PrefabUtility.SaveAsPrefabAsset(empty, pathName, out _);\n                    ProjectWindowUtil.ShowCreatedAsset(o);\n                }\n                finally\n                {\n                    DestroyImmediate(empty);\n                }\n            }\n        }\n\n        internal class DoCreatePrefabVariant : EndNameEditAction\n        {\n            public override void Action(int instanceId, string pathName, string resourceFile)\n            {\n                GameObject go = AssetDatabase.LoadAssetAtPath<GameObject>(resourceFile);\n                Object o = PrefabUtility.CreateVariant(go, pathName);\n                ProjectWindowUtil.ShowCreatedAsset(o);\n            }\n        }\n\n        internal class DoCreateScriptAsset : EndNameEditAction\n        {\n            public override void Action(int instanceId, string pathName, string resourceFile)\n            {\n                Object o = ProjectWindowUtil.CreateScriptAssetFromTemplate(pathName, resourceFile);\n                ProjectWindowUtil.ShowCreatedAsset(o);\n            }\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal class DoCreateAssetWithContent : EndNameEditAction\n        {\n            public string filecontent;\n            public override void Action(int instanceId, string pathName, string resourceFile)\n            {\n                Object o = ProjectWindowUtil.CreateScriptAssetWithContent(pathName, filecontent);\n                ProjectWindowUtil.ShowCreatedAsset(o);\n            }\n        }\n\n        internal class DoCreateAnimatorController : EndNameEditAction\n        {\n            public override void Action(int instanceId, string pathName, string resourceFile)\n            {\n                Animations.AnimatorController controller = Animations.AnimatorController.CreateAnimatorControllerAtPath(pathName);\n                ProjectWindowUtil.ShowCreatedAsset(controller);\n            }\n        }\n\n        internal class DoCreateAudioMixer : EndNameEditAction\n        {\n            public override void Action(int instanceId, string pathName, string resourceFile)\n            {\n                AudioMixerController controller = AudioMixerController.CreateMixerControllerAtPath(pathName);\n\n                // Check if the output group should be initialized (instanceID is stored in the resource file) TODO: rename 'resourceFile' to 'userData' so it's more obvious that it can be used by all EndNameEditActions\n                if (!string.IsNullOrEmpty(resourceFile))\n                {\n                    int outputInstanceID;\n                    if (System.Int32.TryParse(resourceFile, out outputInstanceID))\n                    {\n                        var outputGroup = InternalEditorUtility.GetObjectFromInstanceID(outputInstanceID) as AudioMixerGroupController;\n                        if (outputGroup != null)\n                            controller.outputAudioMixerGroup = outputGroup;\n                    }\n                }\n                ProjectWindowUtil.ShowCreatedAsset(controller);\n            }\n        }\n\n        internal class DoCreateAudioRandomContainer : EndNameEditAction\n        {\n            public Object[] selection;\n\n            private bool ActiveSelectionIsAudioClipList()\n            {\n                return selection.Length > 0 && selection.All(obj => obj.GetType() == typeof(AudioClip));\n            }\n\n            private void CreateAudioRandomContainer(string path)\n            {\n                var container = new AudioRandomContainer { name = Path.GetFileName(path) };\n\n                AssetDatabase.CreateAsset(container, path);\n                ProjectWindowUtil.ShowCreatedAsset(container);\n            }\n\n            private void CreateAudioRandomContainerFromSelectedClips(string path)\n            {\n                var audioClips = selection.Select(obj => obj as AudioClip).ToArray();\n                var container = new AudioRandomContainer { name = Path.GetFileName(path) };\n\n                container.elements = audioClips.Select(audioClip =>\n                {\n                    var element = new AudioContainerElement();\n                    element.audioClip = audioClip;\n                    element.hideFlags = HideFlags.HideInHierarchy;\n                    return element;\n                }).ToArray();\n\n                AssetDatabase.CreateAsset(container, path);\n\n                foreach (var element in container.elements)\n                {\n                    AssetDatabase.AddObjectToAsset(element, container);\n                    AssetDatabase.TryGetGUIDAndLocalFileIdentifier(element, out var guid, out var localId);\n                    var clipName = element.audioClip.name;\n                    element.name = $\"{clipName}_{{{localId}}}\";\n                }\n\n                AssetDatabase.SaveAssetIfDirty(container);\n\n                ProjectWindowUtil.ShowCreatedAsset(container);\n            }\n\n            public override void Action(int instanceId, string path, string resourceFile)\n            {\n                if (ActiveSelectionIsAudioClipList())\n                {\n                    CreateAudioRandomContainerFromSelectedClips(path);\n                }\n                else\n                {\n                    CreateAudioRandomContainer(path);\n                }\n            }\n        }\n    }\n\n    public class ProjectWindowUtil\n    {\n        [MenuItem(\"Assets/Create/GUI Skin\", false, -18)]\n        public static void CreateNewGUISkin()\n        {\n            GUISkin skin = ScriptableObject.CreateInstance<GUISkin>();\n            GUISkin original = Resources.GetBuiltinResource(typeof(GUISkin), \"GameSkin/GameSkin.guiskin\") as GUISkin;\n            if (original)\n                EditorUtility.CopySerialized(original, skin);\n            else\n                Debug.LogError(\"Internal error: unable to load builtin GUIskin\");\n\n            CreateAsset(skin, \"New GUISkin.guiskin\");\n        }\n\n        // Returns the path of currently selected folder. If multiple are selected, returns the first one.\n        internal static string GetActiveFolderPath()\n        {\n            ProjectBrowser projectBrowser = GetProjectBrowserIfExists();\n\n            if (projectBrowser == null)\n                return \"Assets\";\n\n            return projectBrowser.GetActiveFolderPath();\n        }\n\n        internal static bool TryGetActiveFolderPath(out string path)\n        {\n            ProjectBrowser projectBrowser = GetProjectBrowserIfExists();\n\n            path = string.Empty;\n\n            if (projectBrowser == null || !projectBrowser.IsTwoColumns())\n                return false;\n\n            path = projectBrowser.GetActiveFolderPath();\n\n            return true;\n        }\n\n        internal static void EndNameEditAction(EndNameEditAction action, int instanceId, string pathName, string resourceFile, bool accepted)\n        {\n            pathName = AssetDatabase.GenerateUniqueAssetPath(pathName);\n            if (action != null)\n            {\n                if (accepted)\n                    action.Action(instanceId, pathName, resourceFile);\n                else\n                    action.Cancelled(instanceId, pathName, resourceFile);\n                action.CleanUp();\n            }\n        }\n\n        [UsedByNativeCode]\n        private static void CreateDefaultAsset(Object asset, string pathName)\n        {\n            StartNameEditingIfProjectWindowExists(asset.GetInstanceID(), ScriptableObject.CreateInstance<DoCreateNewDefaultAsset>(), pathName, AssetPreview.GetMiniThumbnail(asset), null);\n        }\n\n        // Create a standard Object-derived asset.\n        [RequiredByNativeCode]\n        public static void CreateAsset(Object asset, string pathName)\n        {\n            StartNameEditingIfProjectWindowExists(asset.GetInstanceID(), ScriptableObject.CreateInstance<DoCreateNewAsset>(), pathName, AssetPreview.GetMiniThumbnail(asset), null);\n        }\n\n        // Create a folder\n        [RequiredByNativeCode]\n        [ShortcutManagement.ShortcutAttribute(\"Project Browser/Create/Folder\", typeof(ProjectBrowser), KeyCode.N, ShortcutManagement.ShortcutModifiers.Shift | ShortcutManagement.ShortcutModifiers.Action)]\n        public static void CreateFolder()\n        {\n            StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateFolder>(), \"New Folder\", EditorGUIUtility.IconContent(EditorResources.emptyFolderIconName).image as Texture2D, null);\n        }\n\n        internal static void CreateFolderWithTemplates(string defaultName, params string[] templates)\n        {\n            var folderIcon = templates != null && templates.Length > 0\n                ? EditorResources.folderIconName\n                : EditorResources.emptyFolderIconName;\n\n            var endNameEditAction = ScriptableObject.CreateInstance<DoCreateFolderWithTemplates>();\n            endNameEditAction.templates = templates;\n            StartNameEditingIfProjectWindowExists(0, endNameEditAction, defaultName, EditorGUIUtility.IconContent(folderIcon).image as Texture2D, null);\n        }\n\n        internal static void CreateFolderWithTemplatesWithCustomResourcesPath(string defaultName, string customResPath, params string[] templates)\n        {\n            var folderIcon = templates != null && templates.Length > 0\n                ? EditorResources.folderIconName\n                : EditorResources.emptyFolderIconName;\n\n            var endNameEditAction = ScriptableObject.CreateInstance<DoCreateFolderWithTemplates>();\n            endNameEditAction.templates = templates;\n            endNameEditAction.ResourcesTemplatePath = customResPath;\n            endNameEditAction.UseCustomPath = true;\n            StartNameEditingIfProjectWindowExists(0, endNameEditAction, defaultName, EditorGUIUtility.IconContent(folderIcon).image as Texture2D, null);\n        }\n\n        [RequiredByNativeCode]\n        public static void CreateScene()\n        {\n            StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateScene>(), \"New Scene.unity\", EditorGUIUtility.FindTexture(typeof(SceneAsset)), null);\n        }\n\n        [MenuItem(\"Assets/Create/Scene/Prefab\", false, 21)]\n        static void CreatePrefab()\n        {\n            StartNameEditingIfProjectWindowExists(\n                0,\n                ScriptableObject.CreateInstance<DoCreatePrefab>(),\n                \"New Prefab.prefab\",\n                EditorGUIUtility.FindTexture(\"Prefab Icon\"),\n                null);\n        }\n\n        [MenuItem(\"Assets/Create/Scene/Prefab Variant\", true)]\n        static bool CreatePrefabVariantValidation()\n        {\n            var gameObjects = Selection.gameObjects;\n            if (gameObjects == null || gameObjects.Length == 0)\n                return false;\n\n            foreach (var go in gameObjects)\n            {\n                if (go == null || !EditorUtility.IsPersistent(go))\n                    return false;\n            }\n            return true;\n        }\n\n        [MenuItem(\"Assets/Create/Scene/Prefab Variant\", false, 22)]\n        static void CreatePrefabVariant()\n        {\n            var gameObjects = Selection.gameObjects;\n            if (gameObjects == null || gameObjects.Length == 0)\n                return;\n\n            if (gameObjects.Length == 1)\n            {\n                var go = gameObjects[0];\n                if (go == null || !EditorUtility.IsPersistent(go))\n                    return;\n\n                string sourcePath = AssetDatabase.GetAssetPath(go);\n                string sourceDir = Path.GetDirectoryName(sourcePath).ConvertSeparatorsToUnity();\n                string variantPath = GetPrefabVariantPath(sourceDir, go);\n\n                StartNameEditingIfProjectWindowExists(\n                    0,\n                    ScriptableObject.CreateInstance<DoCreatePrefabVariant>(),\n                    variantPath,\n                    EditorGUIUtility.FindTexture(\"PrefabVariant Icon\"),\n                    sourcePath);\n            }\n            else if (gameObjects.Length > 1)\n            {\n                CreatePrefabVariants(gameObjects);\n            }\n        }\n\n        [MenuItem(\"Assets/Create/Prefab Variant\", true)]\n        static bool CreatePrefabVariantShortcutValidation() => CreatePrefabVariantValidation();\n        [MenuItem(\"Assets/Create/Prefab Variant\", false, -215)]\n        static void CreatePrefabVariantShortcut() => CreatePrefabVariant();\n\n        static GameObject[] CreatePrefabVariants(GameObject[] gameObjects)\n        {\n            if (gameObjects == null)\n                return null;\n\n            foreach (var go in gameObjects)\n            {\n                if (go == null || !EditorUtility.IsPersistent(go))\n                    return null;\n            }\n\n            var createdVariants = new List<GameObject>();\n            foreach (var go in gameObjects)\n            {\n                string sourcePath = AssetDatabase.GetAssetPath(go);\n                string sourceDir = Path.GetDirectoryName(sourcePath).ConvertSeparatorsToUnity();\n                string variantPath = GetPrefabVariantPath(sourceDir, go);\n                variantPath = AssetDatabase.GenerateUniqueAssetPath(variantPath);\n\n                var variant = PrefabUtility.CreateVariant(go, variantPath);\n                if (variant != null)\n                    createdVariants.Add(variant);\n            }\n\n            if (createdVariants.Count > 0)\n            {\n                Selection.objects = createdVariants.ToArray();\n                FrameObjectInProjectWindow(createdVariants.Last().GetInstanceID());\n            }\n\n            return createdVariants.ToArray();\n        }\n\n        static string GetPrefabVariantPath(string folder, GameObject gameObject)\n        {\n            if (PrefabUtility.IsPartOfModelPrefab(gameObject))\n                return string.Format(\"{0}/{1}.prefab\", folder, gameObject.name);\n            else\n                return string.Format(\"{0}/{1} Variant.prefab\", folder, gameObject.name);\n        }\n\n        public static void CreateAssetWithContent(string filename, string content, Texture2D icon = null)\n        {\n            var action = ScriptableObject.CreateInstance<DoCreateAssetWithContent>();\n            action.filecontent = content;\n            StartNameEditingIfProjectWindowExists(0, action, filename, icon, null);\n        }\n\n        [RequiredByNativeCode]\n        public static void CreateScriptAssetFromTemplateFile(string templatePath, string defaultNewFileName)\n        {\n            if (templatePath == null)\n                throw new ArgumentNullException(nameof(templatePath));\n            if (!File.Exists(templatePath))\n                throw new FileNotFoundException($\"The template file \\\"{templatePath}\\\" could not be found.\", templatePath);\n\n            if (string.IsNullOrEmpty(defaultNewFileName))\n                defaultNewFileName = Path.GetFileName(templatePath);\n\n            Texture2D icon = null;\n            switch (Path.GetExtension(defaultNewFileName))\n            {\n                case \".cs\":\n                    icon = EditorGUIUtility.IconContent(\"cs Script Icon\").image as Texture2D;\n                    break;\n                case \".shader\":\n                    icon = EditorGUIUtility.IconContent<Shader>().image as Texture2D;\n                    break;\n                case \".asmdef\":\n                    icon = EditorGUIUtility.IconContent<AssemblyDefinitionAsset>().image as Texture2D;\n                    break;\n                case \".asmref\":\n                    icon = EditorGUIUtility.IconContent<AssemblyDefinitionReferenceAsset>().image as Texture2D;\n                    break;\n                default:\n                    icon = EditorGUIUtility.IconContent<TextAsset>().image as Texture2D;\n                    break;\n            }\n            StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateScriptAsset>(), defaultNewFileName, icon, templatePath);\n        }\n\n        public static void ShowCreatedAsset(Object o)\n        {\n            // Show it\n            Selection.activeObject = o;\n            if (o)\n                FrameObjectInProjectWindow(o.GetInstanceID());\n        }\n\n        [RequiredByNativeCode]\n        static private void CreateAnimatorController()\n        {\n            var icon = EditorGUIUtility.IconContent<Animations.AnimatorController>().image as Texture2D;\n            StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateAnimatorController>(), \"New Animator Controller.controller\", icon, null);\n        }\n\n        [RequiredByNativeCode]\n        static private void CreateAudioMixer()\n        {\n            var icon = EditorGUIUtility.IconContent<AudioMixerController>().image as Texture2D;\n            StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateAudioMixer>(), \"NewAudioMixer.mixer\", icon, null);\n        }\n\n        [RequiredByNativeCode]\n        static internal void CreateAudioRandomContainer()\n        {\n            var icon = EditorGUIUtility.IconContent<AudioRandomContainer>().image as Texture2D;\n            var scriptableObject = ScriptableObject.CreateInstance<DoCreateAudioRandomContainer>();\n\n            scriptableObject.selection = Selection.objects;\n\n            StartNameEditingIfProjectWindowExists(0, scriptableObject, \"New Audio Random Container.asset\", icon, null);\n        }\n\n        internal static string SetLineEndings(string content, LineEndingsMode lineEndingsMode)\n        {\n            const string windowsLineEndings = \"\\r\\n\";\n            const string unixLineEndings = \"\\n\";\n\n            string preferredLineEndings;\n\n            switch (lineEndingsMode)\n            {\n                case LineEndingsMode.OSNative:\n                    if (Application.platform == RuntimePlatform.WindowsEditor)\n                        preferredLineEndings = windowsLineEndings;\n                    else\n                        preferredLineEndings = unixLineEndings;\n                    break;\n                case LineEndingsMode.Unix:\n                    preferredLineEndings = unixLineEndings;\n                    break;\n                case LineEndingsMode.Windows:\n                    preferredLineEndings = windowsLineEndings;\n                    break;\n                default:\n                    preferredLineEndings = unixLineEndings;\n                    break;\n            }\n\n            content = Regex.Replace(content, @\"\\r\\n?|\\n\", preferredLineEndings);\n\n            return content;\n        }\n\n        public static Object CreateScriptAssetWithContent(string assetPath, string scriptContent)\n        {\n            AssetModificationProcessorInternal.OnWillCreateAsset(assetPath);\n\n            scriptContent = SetLineEndings(scriptContent, EditorSettings.lineEndingsForNewScripts);\n\n            string fullPath = Path.GetFullPath(assetPath);\n            File.WriteAllText(fullPath, scriptContent);\n\n            // Import the asset\n            AssetDatabase.ImportAsset(assetPath);\n\n            return AssetDatabase.LoadAssetAtPath(assetPath, typeof(Object));\n        }\n\n        internal static string RemoveOrInsertNamespace(string content, string rootNamespace)\n        {\n            var rootNamespaceBeginTag = \"#ROOTNAMESPACEBEGIN#\";\n            var rootNamespaceEndTag = \"#ROOTNAMESPACEEND#\";\n\n            if (!content.Contains(rootNamespaceBeginTag) || !content.Contains(rootNamespaceEndTag))\n                return content;\n\n            if (string.IsNullOrEmpty(rootNamespace))\n            {\n                content = Regex.Replace(content, $\"((\\\\r\\\\n)|\\\\n)?[ \\\\t]*{rootNamespaceBeginTag}[ \\\\t]*\", string.Empty);\n                content = Regex.Replace(content, $\"((\\\\r\\\\n)|\\\\n)?[ \\\\t]*{rootNamespaceEndTag}[ \\\\t]*\", string.Empty);\n\n                return content;\n            }\n\n            // Use first found newline character as newline for entire file after replace.\n            var newline = content.Contains(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\";\n            var contentLines = new List<string>(content.Split(new[] { \"\\r\\n\", \"\\r\", \"\\n\" }, StringSplitOptions.None));\n\n            int i = 0;\n\n            for (; i < contentLines.Count; ++i)\n            {\n                if (contentLines[i].Contains(rootNamespaceBeginTag))\n                    break;\n            }\n\n            var beginTagLine = contentLines[i];\n\n            // Use the whitespace between beginning of line and #ROOTNAMESPACEBEGIN# as identation.\n            var indentationString = beginTagLine.Substring(0, beginTagLine.IndexOf(\"#\"));\n\n            contentLines[i] = $\"namespace {rootNamespace}\";\n            contentLines.Insert(i + 1, \"{\");\n\n            i += 2;\n\n            for (; i < contentLines.Count; ++i)\n            {\n                var line = contentLines[i];\n\n                if (String.IsNullOrEmpty(line) || line.Trim().Length == 0)\n                    continue;\n\n                if (line.Contains(rootNamespaceEndTag))\n                {\n                    contentLines[i] = \"}\";\n                    break;\n                }\n\n                contentLines[i] = $\"{indentationString}{line}\";\n            }\n\n            return string.Join(newline, contentLines.ToArray());\n        }\n\n        internal static string PreprocessScriptAssetTemplate(string pathName, string resourceContent)\n        {\n            string rootNamespace = null;\n\n            if (Path.GetExtension(pathName) == \".cs\")\n            {\n                rootNamespace = CompilationPipeline.GetAssemblyRootNamespaceFromScriptPath(pathName);\n            }\n\n            string content = resourceContent;\n\n            // #NOTRIM# is a special marker that is used to mark the end of a line where we want to leave whitespace. prevent editors auto-stripping it by accident.\n            content = content.Replace(\"#NOTRIM#\", \"\");\n\n            // macro replacement\n            string baseFile = Path.GetFileNameWithoutExtension(pathName);\n\n            content = content.Replace(\"#NAME#\", baseFile);\n            string baseFileNoSpaces = baseFile.Replace(\" \", \"\");\n            content = content.Replace(\"#SCRIPTNAME#\", baseFileNoSpaces);\n\n            content = RemoveOrInsertNamespace(content, rootNamespace);\n\n            // if the script name begins with an uppercase character we support a lowercase substitution variant\n            if (char.IsUpper(baseFileNoSpaces, 0))\n            {\n                baseFileNoSpaces = char.ToLower(baseFileNoSpaces[0]) + baseFileNoSpaces.Substring(1);\n                content = content.Replace(\"#SCRIPTNAME_LOWER#\", baseFileNoSpaces);\n            }\n            else\n            {\n                // still allow the variant, but change the first character to upper and prefix with \"my\"\n                baseFileNoSpaces = \"my\" + char.ToUpper(baseFileNoSpaces[0]) + baseFileNoSpaces.Substring(1);\n                content = content.Replace(\"#SCRIPTNAME_LOWER#\", baseFileNoSpaces);\n            }\n\n            return content;\n        }\n\n        internal static Object CreateScriptAssetFromTemplate(string pathName, string resourceFile)\n        {\n            string content = File.ReadAllText(resourceFile);\n            return CreateScriptAssetWithContent(pathName, PreprocessScriptAssetTemplate(pathName, content));\n        }\n\n        public static void StartNameEditingIfProjectWindowExists(int instanceID, EndNameEditAction endAction, string pathName, Texture2D icon, string resourceFile)\n        {\n            StartNameEditingIfProjectWindowExists(instanceID, endAction, pathName, icon, resourceFile, true);\n        }\n\n        public static void StartNameEditingIfProjectWindowExists(int instanceID, EndNameEditAction endAction, string pathName, Texture2D icon, string resourceFile, bool selectAssetBeingCreated)\n        {\n            // instanceID 0 is used for assets that haven't been imported, which can conflict with\n            // asset under creations, which might also use instanceID 0. To avoid this conflict the instanceID\n            // is changed if 0.\n            if (instanceID == 0)\n                instanceID = ProjectBrowser.kAssetCreationInstanceID_ForNonExistingAssets;\n\n            ProjectBrowser pb = GetProjectBrowserIfExists();\n            if (pb)\n            {\n                pb.Focus();\n                pb.BeginPreimportedNameEditing(instanceID, endAction, pathName, icon, resourceFile, selectAssetBeingCreated);\n                pb.Repaint();\n            }\n            else\n            {\n                if (!pathName.StartsWith(\"assets/\", StringComparison.CurrentCultureIgnoreCase))\n                    pathName = \"Assets/\" + pathName;\n                EndNameEditAction(endAction, instanceID, pathName, resourceFile, true);\n                if (selectAssetBeingCreated)\n                    Selection.activeObject = EditorUtility.InstanceIDToObject(instanceID);\n            }\n        }\n\n        static ProjectBrowser GetProjectBrowserIfExists()\n        {\n            return ProjectBrowser.s_LastInteractedProjectBrowser;\n        }\n\n        internal static void FrameObjectInProjectWindow(int instanceID)\n        {\n            ProjectBrowser pb = GetProjectBrowserIfExists();\n            if (pb)\n            {\n                pb.FrameObject(instanceID, false);\n            }\n        }\n\n        // InstanceIDs larger than this is considered a favorite by the projectwindows\n        internal static int k_FavoritesStartInstanceID = 1000000000;\n        internal static string k_DraggingFavoriteGenericData = \"DraggingFavorite\";\n        internal static string k_IsFolderGenericData = \"IsFolder\";\n\n        internal static bool IsFavoritesItem(int instanceID)\n        {\n            return instanceID >= k_FavoritesStartInstanceID && instanceID != ProjectBrowser.kPackagesFolderInstanceId;\n        }\n\n        internal static void StartDrag(int draggedInstanceID, List<int> selectedInstanceIDs)\n        {\n            if (draggedInstanceID == ProjectBrowser.kPackagesFolderInstanceId)\n                return;\n\n            DragAndDrop.PrepareStartDrag();\n\n            string title = \"\";\n            if (IsFavoritesItem(draggedInstanceID))\n            {\n                DragAndDrop.SetGenericData(k_DraggingFavoriteGenericData, draggedInstanceID);\n            }\n            else\n            {\n                // Normal assets dragging\n                bool isFolder = IsFolder(draggedInstanceID);\n                DragAndDrop.objectReferences = GetDragAndDropObjects(draggedInstanceID, selectedInstanceIDs);\n                DragAndDrop.SetGenericData(k_IsFolderGenericData, isFolder ? \"isFolder\" : \"\");\n                string[] paths = GetDragAndDropPaths(draggedInstanceID, selectedInstanceIDs);\n                if (paths.Length > 0)\n                    DragAndDrop.paths = paths;\n\n                if (DragAndDrop.objectReferences.Length > 1)\n                    title = \"<Multiple>\";\n                else\n                    title = ObjectNames.GetDragAndDropTitle(InternalEditorUtility.GetObjectFromInstanceID(draggedInstanceID));\n            }\n\n            DragAndDrop.StartDrag(title);\n        }\n\n        internal static Object[] GetDragAndDropObjects(int draggedInstanceID, List<int> selectedInstanceIDs)\n        {\n            List<Object> outList = new List<Object>(selectedInstanceIDs.Count);\n            if ((Event.current.control || Event.current.command) && !selectedInstanceIDs.Contains(draggedInstanceID))\n            {\n                selectedInstanceIDs.Add(draggedInstanceID);\n            }\n            if (selectedInstanceIDs.Contains(draggedInstanceID))\n            {\n                for (int i = 0; i < selectedInstanceIDs.Count; ++i)\n                {\n                    Object obj = InternalEditorUtility.GetObjectFromInstanceID(selectedInstanceIDs[i]);\n                    if (obj != null)\n                        outList.Add(obj);\n                }\n            }\n            else\n            {\n                Object obj = InternalEditorUtility.GetObjectFromInstanceID(draggedInstanceID);\n                if (obj != null)\n                    outList.Add(obj);\n            }\n            return outList.ToArray();\n        }\n\n        internal static string[] GetDragAndDropPaths(int draggedInstanceID, List<int> selectedInstanceIDs)\n        {\n            // Assets\n            List<string> paths = new List<string>();\n            foreach (int instanceID in selectedInstanceIDs)\n            {\n                if (AssetDatabase.IsMainAsset(instanceID))\n                {\n                    string path = AssetDatabase.GetAssetPath(instanceID);\n                    paths.Add(path);\n                }\n            }\n\n            string dragPath = AssetDatabase.GetAssetPath(draggedInstanceID);\n            if (!string.IsNullOrEmpty(dragPath))\n            {\n                if (paths.Contains(dragPath))\n                {\n                    return paths.ToArray();\n                }\n                else if (Event.current.control || Event.current.command)\n                {\n                    paths.Add(dragPath);\n                    return paths.ToArray();\n                }\n                else\n                {\n                    return new[] { dragPath };\n                }\n            }\n            return new string[0];\n        }\n\n        // Returns instanceID of folders (and main asset if input is a subasset) up until and including the Assets folder\n        public static int[] GetAncestors(int instanceID)\n        {\n            HashSet<int> ancestors = new HashSet<int>();\n            GetAncestors(instanceID, ancestors);\n            return ancestors.ToArray();\n        }\n\n        internal static void GetAncestors(int instanceID, HashSet<int> ancestors)\n        {\n            // Ensure we handle packages root folder\n            if (instanceID == ProjectBrowser.kPackagesFolderInstanceId)\n                return;\n\n            // Ensure we add the main asset as ancestor if input is a sub-asset\n            int mainAssetInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(AssetDatabase.GetAssetPath(instanceID));\n            bool isSubAsset = mainAssetInstanceID != instanceID;\n            if (isSubAsset)\n                ancestors.Add(mainAssetInstanceID);\n\n            // Find ancestors of main asset\n            string currentFolderPath = GetContainingFolder(AssetDatabase.GetAssetPath(mainAssetInstanceID));\n            while (!string.IsNullOrEmpty(currentFolderPath))\n            {\n                int currentInstanceID = ProjectBrowser.GetFolderInstanceID(currentFolderPath);\n                ancestors.Add(currentInstanceID);\n                currentFolderPath = GetContainingFolder(AssetDatabase.GetAssetPath(currentInstanceID));\n            }\n        }\n\n        public static bool IsFolder(int instanceID)\n        {\n            return AssetDatabase.IsValidFolder(AssetDatabase.GetAssetPath(instanceID));\n        }\n\n        // Returns containing folder if possible otherwise null.\n        // Trims any trailing forward slashes\n        public static string GetContainingFolder(string path)\n        {\n            if (string.IsNullOrEmpty(path))\n                return null;\n\n            path = path.Trim('/');\n            int pos = path.LastIndexOf(\"/\", StringComparison.Ordinal);\n            if (pos != -1)\n            {\n                return path.Substring(0, pos);\n            }\n\n            // Could not determine containing folder\n            return null;\n        }\n\n        // Input the following list:\n        //  assets/flesh/big\n        //  assets/icons/duke\n        //  assets/icons/duke/snake\n        //  assets/icons/duke/zoo\n        //\n        // ... And the returned list becomes:\n        //  assets/flesh/big\n        //  assets/icons/duke\n\n        // Returned paths are trimmed for ending slashes\n        public static string[] GetBaseFolders(string[] folders)\n        {\n            if (folders.Length <= 1)\n                return folders;\n\n            List<string> result = new List<string>();\n            List<string> sortedFolders = new List<string>(folders);\n\n            // Remove forward slashes before sorting otherwise will \"Assets 1/\" come before \"Assets/\"\n            // which we do not want in the find base folders section below\n            for (int i = 0; i < sortedFolders.Count; ++i)\n                sortedFolders[i] = sortedFolders[i].Trim('/');\n\n            sortedFolders.Sort();\n\n            // Ensure folder paths are ending with '/' so e.g: \"assets/\" is not found in \"assets 1/\".\n            // If we did not end with '/' then \"assets\" could be found in \"assets 1\"\n            // which is not what we want when finding base folders\n            for (int i = 0; i < sortedFolders.Count; ++i)\n                if (!sortedFolders[i].EndsWith(\"/\"))\n                    sortedFolders[i] = sortedFolders[i] + \"/\";\n\n            // Find base folders\n            // We assume sortedFolders is sorted with less first. E.g: {assets/, assets/icons/}\n            string curPath = sortedFolders[0];\n            result.Add(curPath);\n            for (int i = 1; i < sortedFolders.Count; ++i)\n            {\n                // Ensure path matches from start of curPath (to ensure \"assets/monkey\" and \"npc/assets/monkey\" both are returned as base folders)\n                bool startOfPathMatches = sortedFolders[i].IndexOf(curPath, StringComparison.Ordinal) == 0;\n                if (!startOfPathMatches)\n                {\n                    // Add tested path if not part of current path and use tested path as new base\n                    result.Add(sortedFolders[i]);\n                    curPath = sortedFolders[i];\n                }\n            }\n\n            // Remove forward slashes again (added above)\n            for (int i = 0; i < result.Count; ++i)\n                result[i] = result[i].Trim('/');\n\n            return result.ToArray();\n        }\n\n        static bool AnyTargetMaterialHasChildren(string[] targetPaths)\n        {\n            GUID[] guids = targetPaths.Select(path => AssetDatabase.GUIDFromAssetPath(path)).ToArray();\n\n            Func<string, bool> HasChildrenInPath = (string rootPath) => {\n                var property = new HierarchyProperty(rootPath, false);\n                property.SetSearchFilter(new SearchFilter { classNames = new string[] { \"Material\" }, searchArea = SearchFilter.SearchArea.AllAssets });\n                while (property.Next(null))\n                {\n                    GUID parent;\n                    var child = InternalEditorUtility.GetLoadedObjectFromInstanceID(property.GetInstanceIDIfImported()) as Material;\n                    if (child)\n                    {\n                        if (AssetDatabase.IsForeignAsset(child))\n                            continue;\n                        parent = AssetDatabase.GUIDFromAssetPath(AssetDatabase.GetAssetPath(child.parent));\n                    }\n                    else\n                    {\n                        var path = AssetDatabase.GUIDToAssetPath(property.guid);\n                        if (!path.EndsWith(\".mat\", StringComparison.OrdinalIgnoreCase))\n                            continue;\n                        parent = EditorMaterialUtility.GetMaterialParentFromFile(path);\n                    }\n\n                    for (int i = 0; i < guids.Length; i++)\n                    {\n                        if (guids[i] == parent)\n                            return true;\n                    }\n                }\n                return false;\n            };\n\n            if (HasChildrenInPath(\"Assets\"))\n                return true;\n            foreach (var package in PackageManagerUtilityInternal.GetAllVisiblePackages(false))\n            {\n                if (package.source == PackageManager.PackageSource.Local && HasChildrenInPath(package.assetPath))\n                    return true;\n            }\n            return false;\n        }\n\n        static void ReparentMaterialChildren(string assetPath)\n        {\n            var toDelete = AssetDatabase.LoadAssetAtPath<Material>(assetPath);\n            var toDeleteGUID = AssetDatabase.GUIDFromAssetPath(assetPath);\n            var newParent = toDelete.parent;\n\n            Action<string> ReparentInPath = (string rootPath) => {\n                var property = new HierarchyProperty(rootPath, false);\n                property.SetSearchFilter(new SearchFilter { classNames = new string[] { \"Material\" }, searchArea = SearchFilter.SearchArea.AllAssets });\n                while (property.Next(null))\n                {\n                    var child = InternalEditorUtility.GetLoadedObjectFromInstanceID(property.GetInstanceIDIfImported()) as Material;\n                    if (!child)\n                    {\n                        // First check guid from file to avoid loading all materials in memory\n                        string path = AssetDatabase.GUIDToAssetPath(property.guid);\n                        if (EditorMaterialUtility.GetMaterialParentFromFile(path) != toDeleteGUID)\n                            continue;\n                        child = AssetDatabase.LoadAssetAtPath<Material>(path);\n                    }\n                    if (child != null && child.parent == toDelete && !AssetDatabase.IsForeignAsset(child))\n                        child.parent = newParent;\n                }\n            };\n\n            ReparentInPath(\"Assets\");\n            foreach (var package in PackageManagerUtilityInternal.GetAllVisiblePackages(false))\n            {\n                if (package.source == PackageManager.PackageSource.Local)\n                    ReparentInPath(package.assetPath);\n            }\n        }\n\n        // Deletes the assets of the instance IDs, with an optional user confirmation dialog.\n        // Returns true if the delete operation was successfully performed on all assets.\n        // Note: Zero input assets always returns true.\n        // Also note that the operation cannot be undone even if some operations failed.\n        internal static bool DeleteAssets(List<int> instanceIDs, bool askIfSure)\n        {\n            if (instanceIDs.Count == 0)\n                return true;\n\n            bool foundAssetsFolder = instanceIDs.IndexOf(AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(\"Assets\")) >= 0;\n            if (foundAssetsFolder)\n            {\n                EditorUtility.DisplayDialog(L10n.Tr(\"Cannot Delete\"), L10n.Tr(\"Deleting the 'Assets' folder is not allowed\"), L10n.Tr(\"OK\"));\n                return false;\n            }\n\n            bool reparentMaterials = false;\n            var paths = GetMainPathsOfAssets(instanceIDs).ToArray();\n\n            if (paths.Length == 0)\n                return false;\n\n            if (askIfSure)\n            {\n                string title;\n                if (paths.Length > 1)\n                {\n                    title = L10n.Tr(\"Delete selected assets?\");\n                }\n                else\n                {\n                    title = L10n.Tr(\"Delete selected asset?\");\n                }\n\n                int maxCount = 3;\n                bool containsMaterial = false;\n\n                var infotext = new StringBuilder();\n                for (int i = 0; i < paths.Length; ++i)\n                {\n                    if (i < maxCount)\n                        infotext.AppendLine(paths[i]);\n\n                    if (paths[i].EndsWith(\".mat\", StringComparison.OrdinalIgnoreCase))\n                    {\n                        containsMaterial = true;\n                        if (i >= maxCount)\n                            break;\n                    }\n                }\n\n                if (paths.Length > maxCount)\n                {\n                    infotext.AppendLine(\"...\");\n                }\n                infotext.AppendLine(\"\");\n                infotext.AppendLine(L10n.Tr(\"You cannot undo the delete assets action.\"));\n\n                if (containsMaterial)\n                {\n                    // If the assets to be deleted contain a material, check for its children.\n                    // Warning: AnyTargetMaterialHasChildren will load assets so it can be costly.\n                    containsMaterial = AnyTargetMaterialHasChildren(paths);\n                }\n\n                if (containsMaterial)\n                {\n                    infotext.AppendLine();\n                    string name = (paths.Length == 1) ? \"This Material\" : \"One or more of these Material(s)\";\n                    infotext.AppendLine(name + \" is inherited by one or more children. Deleting will result in the children re-mapping to their closest remaining ancestor. Would you like to proceed with re-parenting?\");\n\n                    bool dialogOptionIndex = EditorUtility.DisplayDialog(title, infotext.ToString(), L10n.Tr(\"Delete and re-parent children\"), L10n.Tr(\"Cancel\"));\n\n                    if (dialogOptionIndex)\n                        reparentMaterials = true;\n                    else\n                        return false;\n                }\n                else if (!EditorUtility.DisplayDialog(title, infotext.ToString(), L10n.Tr(\"Delete\"), L10n.Tr(\"Cancel\")))\n                    return false;\n            }\n\n            bool success = true;\n            List<string> failedPaths = new List<string>();\n\n            AssetDatabase.StartAssetEditing();\n\n            if (reparentMaterials)\n            {\n                for (int i = 0; i < paths.Length; i++)\n                {\n                    if (paths[i].EndsWith(\".mat\", StringComparison.OrdinalIgnoreCase))\n                        ReparentMaterialChildren(paths[i]);\n                }\n            }\n\n            if (!AssetDatabase.MoveAssetsToTrash(paths, failedPaths))\n                success = false;\n\n            AssetDatabase.StopAssetEditing();\n\n            if (!success)\n            {\n                var vcsOffline = false;\n                if (!EditorUserSettings.WorkOffline)\n                {\n                    var vco = VersionControlManager.activeVersionControlObject;\n                    if (vco != null)\n                        vcsOffline = !vco.isConnected;\n                    else if (Provider.enabled)\n                        vcsOffline = !Provider.isActive;\n                }\n                var message = vcsOffline ?\n                    L10n.Tr(\"Some assets could not be deleted.\\nMake sure you are connected to your Version Control server or \\\"Work Offline\\\" is enabled.\") :\n                    L10n.Tr(\"Some assets could not be deleted.\\nMake sure nothing is keeping a hook on them, like a loaded DLL for example.\");\n\n                EditorUtility.DisplayDialog(L10n.Tr(\"Cannot Delete\"), message, L10n.Tr(\"OK\"));\n            }\n\n            PackageManager.Client.Resolve(false);\n\n            return success;\n        }\n\n        internal static IEnumerable<string> GetMainPathsOfAssets(IEnumerable<int> instanceIDs)\n        {\n            foreach (var instanceID in instanceIDs)\n            {\n                if (AssetDatabase.IsMainAsset(instanceID))\n                {\n                    yield return AssetDatabase.GetAssetPath(instanceID);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ProjectBrowser/SavedSearchFilter.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.IO;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing Object = UnityEngine.Object;\n\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewUtility = UnityEditor.IMGUI.Controls.TreeViewUtility<int>;\n\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    internal class SavedFilter\n    {\n        public string m_Name;\n        public int m_Depth;             // Can be used for tree view representation\n        public float m_PreviewSize = -1f; // if -1f then preview size is not applied when set\n        public int m_ID;\n        public SearchFilter m_Filter;\n\n        public SavedFilter(string name, SearchFilter filter, int depth, float previewSize)\n        {\n            m_Name = name;\n            m_Depth = depth;\n            m_Filter = filter;\n            m_PreviewSize = previewSize;\n        }\n    }\n\n\n    [FilePathAttribute(\"SearchFilters\", FilePathAttribute.Location.PreferencesFolder)]\n    internal class SavedSearchFilters : ScriptableSingleton<SavedSearchFilters>\n    {\n        // The order if this list is the order they will be shown in the UI\n        [SerializeField]\n        List<SavedFilter> m_SavedFilters;\n\n        // Callback when saved filters have changed\n        System.Action m_SavedFiltersChanged;\n        // Callback when saved filters have been initialized\n        System.Action m_SavedFiltersInitialized;\n        bool m_AllowHierarchy = false;\n\n        // --------------------\n        // Static interface\n\n        // returns is instanceID given to the SavedFilter\n        public static int AddSavedFilter(string displayName, SearchFilter filter, float previewSize)\n        {\n            int instanceID = instance.Add(displayName, filter, previewSize, GetRootInstanceID(), true); // using 0 adds filter after the root\n            return instanceID;\n        }\n\n        public static int AddSavedFilterAfterInstanceID(string displayName, SearchFilter filter, float previewSize, int insertAfterID, bool addAsChild)\n        {\n            int instanceID = instance.Add(displayName, filter, previewSize, insertAfterID, addAsChild);\n            return instanceID;\n        }\n\n        public static void RemoveSavedFilter(int instanceID)\n        {\n            instance.Remove(instanceID);\n        }\n\n        public static bool IsSavedFilter(int instanceID)\n        {\n            return instance.IndexOf(instanceID) >= 0;\n        }\n\n        public static int GetRootInstanceID()\n        {\n            return instance.GetRoot();\n        }\n\n        public static SearchFilter GetFilter(int instanceID)\n        {\n            SavedFilter sf = instance.Find(instanceID);\n            if (sf != null && sf.m_Filter != null)\n                return ObjectCopier.DeepClone(sf.m_Filter);\n            return null;\n        }\n\n        public static int GetFilterInstanceID(string name, string searchFieldString)\n        {\n            if (instance.m_SavedFilters != null && instance.m_SavedFilters.Count > 0)\n            {\n                foreach (SavedFilter sf in instance.m_SavedFilters)\n                {\n                    if ((string.IsNullOrEmpty(name) || sf.m_Name == name) && sf.m_Filter.FilterToSearchFieldString() == searchFieldString)\n                    {\n                        return sf.m_ID;\n                    }\n                }\n            }\n\n            return 0;\n        }\n\n        public static float GetPreviewSize(int instanceID)\n        {\n            SavedFilter sf = instance.Find(instanceID);\n            if (sf != null)\n                return sf.m_PreviewSize;\n            return -1f;\n        }\n\n        public static string GetName(int instanceID)\n        {\n            SavedFilter filter = instance.Find(instanceID);\n            if (filter != null)\n                return filter.m_Name;\n\n            Debug.LogError(\"Could not find saved filter \" + instanceID + \" \" + instance);\n            return \"\";\n        }\n\n        public static void SetName(int instanceID, string name)\n        {\n            SavedFilter filter = instance.Find(instanceID);\n            if (filter != null)\n            {\n                filter.m_Name = name;\n                instance.Changed();\n            }\n            else\n                Debug.LogError(\"Could not set name of saved filter \" + instanceID + \" \" + instance);\n        }\n\n        public static void UpdateExistingSavedFilter(int instanceID, SearchFilter filter, float previewSize)\n        {\n            instance.UpdateFilter(instanceID, filter, previewSize);\n        }\n\n        public static TreeViewItem ConvertToTreeView()\n        {\n            return instance.BuildTreeView();\n        }\n\n        public static void RefreshSavedFilters()\n        {\n            instance.Changed();\n        }\n\n        public static void AddChangeListener(System.Action callback)\n        {\n            instance.m_SavedFiltersChanged -= callback; // ensures its not added twice\n            instance.m_SavedFiltersChanged += callback;\n        }\n\n        internal static void AddInitializedListener(System.Action callback)\n        {\n            instance.m_SavedFiltersInitialized -= callback; // ensures its not added twice\n            instance.m_SavedFiltersInitialized += callback;\n        }\n\n        internal static void RemoveInitializedListener(System.Action callback)\n        {\n            instance.m_SavedFiltersInitialized -= callback;\n        }\n\n        public static void MoveSavedFilter(int instanceID, int parentInstanceID, int targetInstanceID, bool after)\n        {\n            instance.Move(instanceID, parentInstanceID, targetInstanceID, after);\n        }\n\n        public static bool CanMoveSavedFilter(int instanceID, int parentInstanceID, int targetInstanceID, bool after)\n        {\n            return instance.IsValidMove(instanceID, parentInstanceID, targetInstanceID, after);\n        }\n\n        public static bool AllowsHierarchy()\n        {\n            return instance.m_AllowHierarchy;\n        }\n\n        // ------------\n        // Impl\n\n        bool IsValidMove(int instanceID, int parentInstanceID, int targetInstanceID, bool after)\n        {\n            int index = IndexOf(instanceID);\n            int parentIndex = IndexOf(parentInstanceID);\n            int targetIndex = IndexOf(targetInstanceID);\n\n            if (index < 0 || parentIndex < 0 || targetIndex < 0)\n            {\n                Debug.LogError(\"Move of a SavedFilter has invalid input: \" + index + \" \" + parentIndex + \" \" + targetIndex);\n                return false;\n            }\n\n            if (instanceID == targetInstanceID)\n            {\n                //Debug.LogError (\"Cannot move to same position\");\n                return false;\n            }\n\n            // Remove range from list (there could be children that is also moved)\n            for (int i = index + 1; i < m_SavedFilters.Count; ++i)\n            {\n                if (m_SavedFilters[i].m_Depth > m_SavedFilters[index].m_Depth)\n                {\n                    if (i == targetIndex || i == parentIndex)\n                    {\n                        //Debug.LogError (\"Cannot move filter to a child location \");\n                        return false;\n                    }\n                }\n                else\n                    break;\n            }\n\n            // Valid move\n            return true;\n        }\n\n        void Move(int instanceID, int parentInstanceID, int targetInstanceID, bool after)\n        {\n            if (!IsValidMove(instanceID, parentInstanceID, targetInstanceID, after))\n                return;\n\n            int index = IndexOf(instanceID);\n            int parentIndex = IndexOf(parentInstanceID);\n            int targetIndex = IndexOf(targetInstanceID);\n\n            SavedFilter filter = m_SavedFilters[index];\n            SavedFilter parent = m_SavedFilters[parentIndex];\n\n\n            int depthChange = 0;\n            if (m_AllowHierarchy)\n                depthChange = (parent.m_Depth + 1) - filter.m_Depth;\n\n            // Remove range from list (there could be children that is also moved)\n            List<SavedFilter> moveList = GetSavedFilterAndChildren(instanceID);\n            m_SavedFilters.RemoveRange(index, moveList.Count);\n\n            // Update depth\n            foreach (SavedFilter s in moveList)\n                s.m_Depth += depthChange;\n\n            // Insert after target\n            targetIndex = IndexOf(targetInstanceID);\n            if (targetIndex != -1)\n            {\n                if (after)\n                    targetIndex += 1;\n                m_SavedFilters.InsertRange(targetIndex, moveList);\n            }\n            Changed();\n        }\n\n        void UpdateFilter(int instanceID, SearchFilter filter, float previewSize)\n        {\n            SavedFilter savedFilter = Find(instanceID);\n            if (savedFilter != null)\n            {\n                SearchFilter copiedFilter = null;\n                if (filter != null)\n                {\n                    copiedFilter = ObjectCopier.DeepClone(filter);\n                    savedFilter.m_Filter = copiedFilter;\n                }\n\n                savedFilter.m_PreviewSize = previewSize;\n                Changed();\n            }\n            else\n            {\n                Debug.LogError(\"Could not find saved filter \" + instanceID + \" \" + instance);\n            }\n        }\n\n        int GetNextAvailableID()\n        {\n            List<int> allIDs = new List<int>();\n            foreach (SavedFilter sf in m_SavedFilters)\n                if (sf.m_ID >= ProjectWindowUtil.k_FavoritesStartInstanceID)\n                    allIDs.Add(sf.m_ID);\n            allIDs.Sort();\n\n            // Now try find\n            int result = ProjectWindowUtil.k_FavoritesStartInstanceID;\n            int i = 0;\n            while (i < 1000)\n            {\n                if (allIDs.BinarySearch(result) < 0)\n                    return result;\n\n                result++;\n                i++;\n            }\n\n            Debug.LogError(\"Could not assign valid ID to saved filter \" + DebugUtils.ListToString(allIDs) + \" \" + result);\n            return ProjectWindowUtil.k_FavoritesStartInstanceID + 1000;\n        }\n\n        int Add(string displayName, SearchFilter filter, float previewSize, int insertAfterInstanceID, bool addAsChild)\n        {\n            SearchFilter filterCopy = null;\n            if (filter != null)\n                filterCopy = ObjectCopier.DeepClone(filter);\n\n            // Clear unused data before saving\n            if (filterCopy.GetState() == SearchFilter.State.SearchingInAllAssets ||\n                filterCopy.GetState() == SearchFilter.State.SearchingInAssetsOnly ||\n                filterCopy.GetState() == SearchFilter.State.SearchingInPackagesOnly)\n            {\n                filterCopy.folders = new string[0];\n            }\n\n            int afterIndex = 0; // add after root index\n            if (insertAfterInstanceID != 0)\n            {\n                afterIndex = IndexOf(insertAfterInstanceID);\n                if (afterIndex == -1)\n                {\n                    Debug.LogError(\"Invalid insert position\");\n                    return 0;\n                }\n            }\n\n            int depth = m_SavedFilters[afterIndex].m_Depth + (addAsChild ? 1 : 0);\n\n            SavedFilter savedFilter = new SavedFilter(displayName, filterCopy, depth, previewSize);\n            savedFilter.m_ID = GetNextAvailableID();\n\n            if (m_SavedFilters.Count == 0)\n            {\n                m_SavedFilters.Add(savedFilter);\n            }\n            else\n            {\n                m_SavedFilters.Insert(afterIndex + 1, savedFilter); // insert after wanted index\n            }\n\n            // Select new Saved filter\n            //Selection.activeInstanceID = savedFilter.m_ID;\n\n            Changed();\n            return savedFilter.m_ID;\n        }\n\n        List<SavedFilter> GetSavedFilterAndChildren(int instanceID)\n        {\n            List<SavedFilter> result = new List<SavedFilter>();\n            int index = IndexOf(instanceID);\n            if (index >= 0)\n            {\n                result.Add(m_SavedFilters[index]);\n                for (int i = index + 1; i < m_SavedFilters.Count; ++i)\n                {\n                    if (m_SavedFilters[i].m_Depth > m_SavedFilters[index].m_Depth)\n                        result.Add(m_SavedFilters[i]);\n                    else\n                        break;\n                }\n            }\n\n            return result;\n        }\n\n        void Remove(int instanceID)\n        {\n            int index = IndexOf(instanceID);\n            if (index >= 1)\n            {\n                List<SavedFilter> deleteList = GetSavedFilterAndChildren(instanceID);\n                if (deleteList.Count > 0)\n                {\n                    m_SavedFilters.RemoveRange(index, deleteList.Count);\n                    Changed();\n                }\n            }\n        }\n\n        int IndexOf(int instanceID)\n        {\n            for (int i = 0; i < m_SavedFilters.Count; ++i)\n                if (m_SavedFilters[i].m_ID == instanceID)\n                    return i;\n\n            return -1;\n        }\n\n        SavedFilter Find(int instanceID)\n        {\n            int index = IndexOf(instanceID);\n            if (index >= 0)\n                return m_SavedFilters[index];\n            return null;\n        }\n\n        void Init()\n        {\n            // Data is serialized to hdd so this code is only run first time (if we did not provide a default set of saved filters)\n            if (m_SavedFilters == null || m_SavedFilters.Count == 0)\n            {\n                m_SavedFilters = new List<SavedFilter>();\n\n                // Ensure we have a root at depth 0\n                m_SavedFilters.Add(new SavedFilter(\"Favorites\", null, 0, -1f));\n            }\n\n            // Always set root filter data (is serialized so we need to set it here to affect serialized data)\n            SearchFilter filter = new SearchFilter();\n            filter.classNames = new string[0];\n            m_SavedFilters[0].m_Name = \"Favorites\";\n            m_SavedFilters[0].m_Filter = filter;\n            m_SavedFilters[0].m_Depth = 0;\n            m_SavedFilters[0].m_ID = ProjectWindowUtil.k_FavoritesStartInstanceID;\n\n            // At init check if all have valid ids (for patching up ids old saved filters)\n            for (int i = 0; i < m_SavedFilters.Count; ++i)\n                if (m_SavedFilters[i].m_ID < ProjectWindowUtil.k_FavoritesStartInstanceID)\n                    m_SavedFilters[i].m_ID = GetNextAvailableID();\n\n            // Ensure depth is valid\n            if (!m_AllowHierarchy)\n                for (int i = 1; i < m_SavedFilters.Count; ++i)\n                    m_SavedFilters[i].m_Depth = 1;\n\n            if (m_SavedFiltersInitialized != null && m_SavedFilters.Count > 1)\n            {\n                m_SavedFiltersInitialized();\n            }\n        }\n\n        int GetRoot()\n        {\n            if (m_SavedFilters != null && m_SavedFilters.Count > 0)\n                return m_SavedFilters[0].m_ID;\n            return 0;\n        }\n\n        // Utility function for building a tree view from saved filter state. Returns root of tree\n        TreeViewItem BuildTreeView()\n        {\n            Init();\n\n            if (m_SavedFilters.Count == 0)\n            {\n                Debug.LogError(\"BuildTreeView: No saved filters! We should at least have a root\");\n                return null;\n            }\n\n            TreeViewItem root = null;\n\n            // Create rest of nodes\n            List<TreeViewItem> items = new List<TreeViewItem>();\n            for (int i = 0; i < m_SavedFilters.Count; ++i)\n            {\n                SavedFilter savedFilter = m_SavedFilters[i];\n                int instanceID = savedFilter.m_ID;\n                int depth = savedFilter.m_Depth;\n                bool isFolder = savedFilter.m_Filter.GetState() == SearchFilter.State.FolderBrowsing;\n                TreeViewItem item = new SearchFilterTreeItem(instanceID, depth, null, savedFilter.m_Name, isFolder);\n                if (i == 0)\n                    root = item;\n                else\n                {\n                    items.Add(item);\n                }\n            }\n\n            // Fix child/parent references\n            TreeViewUtility.SetChildParentReferences(items, root);\n\n            return root;\n        }\n\n        void Changed()\n        {\n            bool saveAsText = true;\n            Save(saveAsText);\n\n            // Notify listeners of change\n            if (m_SavedFiltersChanged != null)\n                m_SavedFiltersChanged();\n        }\n\n        public override string ToString()\n        {\n            string text = \"Saved Filters \";\n            for (int i = 0; i < m_SavedFilters.Count; ++i)\n            {\n                int instanceID = m_SavedFilters[i].m_ID;\n                SavedFilter s = m_SavedFilters[i];\n                text += string.Format(\": {0} ({1})({2})({3}) \", s.m_Name, instanceID, s.m_Depth, s.m_PreviewSize);\n            }\n            return text;\n        }\n    }\n\n\n    // Provides a method for performing a deep copy of an object.\n    // Binary Serialization is used to perform the copy.\n    // Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx\n    internal static class ObjectCopier\n    {\n        // Perform a deep Copy of the source object.\n        public static T DeepClone<T>(T source)\n        {\n            if (!typeof(T).IsSerializable)\n            {\n                throw new ArgumentException(\"The type must be serializable.\", \"source\");\n            }\n\n            // Don't serialize a null object, simply return the default for that object\n            if (Object.ReferenceEquals(source, null))\n            {\n                return default(T);\n            }\n\n            System.Runtime.Serialization.IFormatter formatter =\n                new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();\n            Stream stream = new MemoryStream();\n            using (stream)\n            {\n                formatter.Serialize(stream, source);\n                stream.Seek(0, SeekOrigin.Begin);\n                return (T)formatter.Deserialize(stream);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ProjectBrowser/SearchFilter.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.AssetImporters;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [System.Serializable]\n    [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n    internal class SearchFilter\n    {\n        public enum SearchArea\n        {\n            AllAssets,\n            InAssetsOnly,\n            InPackagesOnly,\n            SelectedFolders\n        }\n\n        public enum State\n        {\n            EmptySearchFilter,\n            FolderBrowsing,\n            SearchingInAllAssets,\n            SearchingInAssetsOnly,\n            SearchingInPackagesOnly,\n            SearchingInFolders\n        }\n\n        // Searching\n        [SerializeField]\n        private string m_NameFilter = \"\";\n        [SerializeField]\n        private string[] m_ClassNames = new string[0];\n        [SerializeField]\n        private string[] m_AssetLabels = new string[0];\n        [SerializeField]\n        private string[] m_AssetBundleNames = new string[0];\n        [SerializeField]\n        private int[] m_ReferencingInstanceIDs = new int[0];\n        [SerializeField]\n        private int[] m_SceneHandles;\n        [SerializeField]\n        private bool m_ShowAllHits = false;         // If true then just one filter must match to show an object, if false then all filters must match to show an object\n        [SerializeField]\n        private bool m_SkipHidden = false;\n        [SerializeField]\n        SearchArea m_SearchArea = SearchArea.InAssetsOnly;\n        // Folder browsing\n        [SerializeField]\n        private string[] m_Folders = new string[0];\n        [SerializeField]\n        private string[] m_Globs = new string[0];\n\n        [SerializeField]\n        private int[] m_ProductIds = new int[0];\n\n        [SerializeField]\n        private bool m_AnyWithAssetOrigin = false;\n\n        [SerializeField]\n        private string m_OriginalText = \"\";\n        [SerializeField]\n        private ImportLogFlags m_ImportLogFlags;\n\n        [SerializeField]\n        private bool m_FilterByTypeIntersection;\n\n        // Interface\n        public string nameFilter { get { return m_NameFilter; } set { m_NameFilter = value; }}\n        public string[] classNames { get { return m_ClassNames; } set { m_ClassNames = value; }}\n        public string[] assetLabels { get { return m_AssetLabels; } set { m_AssetLabels = value; }}\n        public string[] assetBundleNames { get { return m_AssetBundleNames; } set { m_AssetBundleNames = value; }}\n        public int[] referencingInstanceIDs { get { return m_ReferencingInstanceIDs; } set { m_ReferencingInstanceIDs = value; }}\n        public int[] sceneHandles { get { return m_SceneHandles; } set { m_SceneHandles = value; }}\n        public bool showAllHits { get { return m_ShowAllHits; } set { m_ShowAllHits = value; }}\n        public bool skipHidden { get { return m_SkipHidden; } set { m_SkipHidden = value; }}\n        public string[] folders { get { return m_Folders; } set { m_Folders = value; }}\n        public SearchArea searchArea {  get { return m_SearchArea; } set { m_SearchArea = value; }}\n        public string[] globs { get { return m_Globs; } set { m_Globs = value; }}\n        public int[] productIds { get { return m_ProductIds; } set { m_ProductIds = value; }}\n\n        // When set to true, the search filter will keep those assets that contain AssetOrigin information\n        public bool anyWithAssetOrigin { get { return m_AnyWithAssetOrigin; } set { m_AnyWithAssetOrigin = value; }}\n        public string originalText { get => m_OriginalText; set => m_OriginalText = value; }\n        public ImportLogFlags importLogFlags { get => m_ImportLogFlags; set => m_ImportLogFlags = value; }\n        internal bool filterByTypeIntersection { get => m_FilterByTypeIntersection; set => m_FilterByTypeIntersection = value; }\n\n        public void ClearSearch()\n        {\n            m_NameFilter = \"\";\n            m_OriginalText = \"\";\n            m_ClassNames = new string[0];\n            m_AssetLabels = new string[0];\n            m_AssetBundleNames = new string[0];\n            m_ReferencingInstanceIDs = new int[0];\n            m_SceneHandles = new int[0];\n            m_Globs = new string[0];\n            m_ProductIds = new int[0];\n            m_AnyWithAssetOrigin = false;\n            m_ShowAllHits = false;\n            m_SkipHidden = false;\n            m_ImportLogFlags = ImportLogFlags.None;\n            m_FilterByTypeIntersection = false;\n        }\n\n        bool IsNullOrEmpty<T>(T[] list)\n        {\n            return (list == null || list.Length == 0);\n        }\n\n        public State GetState()\n        {\n            bool isSearchActive = !string.IsNullOrEmpty(m_NameFilter) ||\n                !IsNullOrEmpty(m_AssetLabels) ||\n                !IsNullOrEmpty(m_ClassNames) ||\n                !IsNullOrEmpty(m_AssetBundleNames) ||\n                !IsNullOrEmpty(m_Globs) ||\n                !IsNullOrEmpty(m_ProductIds) ||\n                !IsNullOrEmpty(m_ReferencingInstanceIDs) ||\n                m_ImportLogFlags != ImportLogFlags.None;\n\n            bool foldersActive = !IsNullOrEmpty(m_Folders);\n\n            if (isSearchActive)\n            {\n                if (foldersActive && m_SearchArea == SearchArea.SelectedFolders)\n                    return State.SearchingInFolders;\n\n                if (m_SearchArea == SearchArea.InAssetsOnly)\n                    return State.SearchingInAssetsOnly;\n\n                if (m_SearchArea == SearchArea.InPackagesOnly)\n                    return State.SearchingInPackagesOnly;\n\n                return State.SearchingInAllAssets;\n            }\n            else if (foldersActive)\n            {\n                return State.FolderBrowsing;\n            }\n\n            return State.EmptySearchFilter;\n        }\n\n        public bool IsSearching()\n        {\n            State state = GetState();\n            return (state == State.SearchingInAllAssets ||\n                state == State.SearchingInAssetsOnly ||\n                state == State.SearchingInPackagesOnly ||\n                state == State.SearchingInFolders);\n        }\n\n        public bool SetNewFilter(SearchFilter newFilter)\n        {\n            bool changed = false;\n\n            if (newFilter.m_NameFilter != m_NameFilter)\n            {\n                m_NameFilter = newFilter.m_NameFilter;\n                changed = true;\n            }\n\n            if (newFilter.m_OriginalText != m_OriginalText)\n            {\n                m_OriginalText = newFilter.m_OriginalText;\n                changed = true;\n            }\n\n            if (newFilter.m_ClassNames != m_ClassNames)\n            {\n                m_ClassNames = newFilter.m_ClassNames;\n                changed = true;\n            }\n\n            if (newFilter.m_Folders != m_Folders)\n            {\n                m_Folders = newFilter.m_Folders;\n                changed = true;\n            }\n\n            if (newFilter.m_AssetLabels != m_AssetLabels)\n            {\n                m_AssetLabels = newFilter.m_AssetLabels;\n                changed = true;\n            }\n\n            if (newFilter.m_AssetBundleNames != m_AssetBundleNames)\n            {\n                m_AssetBundleNames = newFilter.m_AssetBundleNames;\n                changed = true;\n            }\n\n            if (newFilter.m_ReferencingInstanceIDs != m_ReferencingInstanceIDs)\n            {\n                m_ReferencingInstanceIDs = newFilter.m_ReferencingInstanceIDs;\n                changed = true;\n            }\n\n            if (newFilter.m_SceneHandles != m_SceneHandles)\n            {\n                m_SceneHandles = newFilter.m_SceneHandles;\n                changed = true;\n            }\n\n            if (newFilter.m_SearchArea != m_SearchArea)\n            {\n                m_SearchArea = newFilter.m_SearchArea;\n                changed = true;\n            }\n\n            if (newFilter.m_ImportLogFlags != m_ImportLogFlags)\n            {\n                m_ImportLogFlags = newFilter.m_ImportLogFlags;\n                changed = true;\n            }\n\n            m_ShowAllHits = newFilter.m_ShowAllHits;\n\n            if (newFilter.m_SkipHidden != m_SkipHidden)\n            {\n                m_SkipHidden = newFilter.m_SkipHidden;\n                changed = true;\n            }\n\n            if (newFilter.m_Globs != m_Globs)\n            {\n                m_Globs = newFilter.m_Globs;\n                changed = true;\n            }\n\n            if (newFilter.m_ProductIds != m_ProductIds)\n            {\n                m_ProductIds = newFilter.m_ProductIds;\n                changed = true;\n            }\n\n            if (newFilter.m_AnyWithAssetOrigin != m_AnyWithAssetOrigin)\n            {\n                m_AnyWithAssetOrigin = newFilter.m_AnyWithAssetOrigin;\n                changed = true;\n            }\n\n            if (newFilter.m_FilterByTypeIntersection != m_FilterByTypeIntersection)\n            {\n                m_FilterByTypeIntersection = newFilter.m_FilterByTypeIntersection;\n                changed = true;\n            }\n\n            return changed;\n        }\n\n        // Debug\n        public override string ToString()\n        {\n            string result = \"SearchFilter: \";\n\n            result += string.Format(\"[Area: {0}, State: {1}]\", m_SearchArea, GetState());\n\n            if (!string.IsNullOrEmpty(m_NameFilter))\n                result += \"[Name: \" + m_NameFilter + \"]\";\n\n            if (m_AssetLabels != null && m_AssetLabels.Length > 0)\n                result += \"[Labels: \" + m_AssetLabels[0] + \"]\";\n\n            if (m_AssetBundleNames != null && m_AssetBundleNames.Length > 0)\n                result += \"[AssetBundleNames: \" + m_AssetBundleNames[0] + \"]\";\n\n            if (m_ClassNames != null && m_ClassNames.Length > 0)\n                result += \"[Types: \" + m_ClassNames[0] + \" (\" + m_ClassNames.Length + \")]\";\n\n            if (m_ReferencingInstanceIDs != null && m_ReferencingInstanceIDs.Length > 0)\n                result += \"[RefIDs: \" + m_ReferencingInstanceIDs[0] + \"]\";\n\n            if (m_Folders != null && m_Folders.Length > 0)\n                result += \"[Folders: \" + m_Folders[0] + \"]\";\n\n            if (m_Globs != null && m_Globs.Length > 0)\n                result += \"[Glob: \" + m_Globs[0] + \"]\";\n\n            if (m_ProductIds != null && m_ProductIds.Length > 0)\n                result += \"[AssetOrigin.ProductIds: \" + m_ProductIds[0] + \"]\";\n\n            result += \"[AnyWithAssetOrigin: \" + anyWithAssetOrigin + \"]\";\n            result += \"[ShowAllHits: \" + showAllHits + \"]\";\n            result += \"[SkipHidden: \" + skipHidden + \"]\";\n\n            if (m_ImportLogFlags == (ImportLogFlags.Error | ImportLogFlags.Warning))\n            {\n                result += $\"[ImportLog: {ImportLog.Filters.AllIssuesStr}]\";\n            }\n            else if (m_ImportLogFlags == ImportLogFlags.Error)\n            {\n                result += $\"[ImportLog: {ImportLog.Filters.ErrorsStr}]\";\n            }\n            else if (m_ImportLogFlags == ImportLogFlags.Warning)\n            {\n                result += $\"[ImportLog: {ImportLog.Filters.WarningsStr}]\";\n            }\n\n            if (m_FilterByTypeIntersection)\n            {\n                result += $\"[FilterByTypeIntersection]\";\n            }\n\n            return result;\n        }\n\n        string FormatFilterTokenForSearchEngine(string token)\n        {\n            if (SearchService.ProjectSearch.HasEngineOverride())\n                return $\"{token}=\";\n            return $\"{token}:\";\n        }\n\n        internal string FilterToSearchFieldString()\n        {\n            string result = \"\";\n            if (!string.IsNullOrEmpty(m_NameFilter))\n                result += m_NameFilter;\n\n            // See SearchUtility.cs for search tokens\n            AddToString(FormatFilterTokenForSearchEngine(\"t\"), m_ClassNames, ref result);\n            AddToString(FormatFilterTokenForSearchEngine(\"l\"), m_AssetLabels, ref result);\n            AddToString(\"b:\", m_AssetBundleNames, ref result);\n            AddToString(\"glob:\", m_Globs.Select(a => $\"\\\"{a}\\\"\").ToArray(), ref result);\n            AddToString(\"assetorigin.productid:\", m_ProductIds.Select(o => $\"\\\"{o}\\\"\").ToArray(), ref result);\n\n            if (m_ImportLogFlags == (ImportLogFlags.Error | ImportLogFlags.Warning))\n            {\n                result += $\" {ImportLog.Filters.SearchToken}:{ImportLog.Filters.AllIssuesStr}\";\n            }\n            else if (m_ImportLogFlags == ImportLogFlags.Error)\n            {\n                result += $\" {ImportLog.Filters.SearchToken}:{ImportLog.Filters.ErrorsStr}\";\n            }\n            else if (m_ImportLogFlags == ImportLogFlags.Warning)\n            {\n                result += $\" {ImportLog.Filters.SearchToken}:{ImportLog.Filters.WarningsStr}\";\n            }\n\n            return result;\n        }\n\n        void AddToString<T>(string prefix, T[] list, ref string result)\n        {\n            if (list == null)\n                return;\n            if (result == null)\n                result = \"\";\n\n            foreach (T item in list)\n            {\n                if (!string.IsNullOrEmpty(result))\n                    result += \" \";\n                result += prefix + item;\n            }\n        }\n\n        // Keeps current SearchArea\n        internal void SearchFieldStringToFilter(string searchString)\n        {\n            ClearSearch();\n\n            if (string.IsNullOrEmpty(searchString))\n                return;\n\n            SearchUtility.ParseSearchString(searchString, this);\n        }\n\n        internal static SearchFilter CreateSearchFilterFromString(string searchText)\n        {\n            SearchFilter searchFilter = new SearchFilter();\n            SearchUtility.ParseSearchString(searchText, searchFilter);\n            return searchFilter;\n        }\n\n        // Split text into words separated by whitespace but handle quotes\n        // E.g 'one man' becomes:   'one', 'man'\n        // E.g '\"one man' becomes:  'one', 'man'\n        // E.g '\"one man\"' becomes: 'one man'\n        public static string[] Split(string text)\n        {\n            if (string.IsNullOrEmpty(text))\n                return new string[0];\n\n            List<string> words = new List<string>();\n            foreach (Match m in Regex.Matches(text, \"\\\".+?\\\"|\\\\S+\"))\n            {\n                words.Add(m.Value.Replace(\"\\\"\", \"\"));   // remove quotes\n            }\n\n            return words.ToArray();\n        }\n    } // end of class SearchFilter\n}\n"
  },
  {
    "path": "Editor/Mono/ProjectBrowser/SearchableEditorWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing Object = UnityEngine.Object;\nusing System;\n\nnamespace UnityEditor\n{\n    public class SearchableEditorWindow : EditorWindow\n    {\n        public enum SearchMode { All, Name, Type, Label, AssetBundleName }\n        public enum SearchModeHierarchyWindow { All, Name, Type }\n\n        internal static SearchFilter CreateFilter(string searchString, SearchMode searchMode)\n        {\n            SearchFilter filter = new SearchFilter();\n            if (string.IsNullOrEmpty(searchString))\n                return filter;\n\n            switch (searchMode)\n            {\n                case SearchMode.All:\n                    if (!SearchUtility.ParseSearchString(searchString, filter))\n                    {\n                        // Use search string for all SearchModes: name, types and labels\n                        filter.nameFilter = searchString;\n                        filter.classNames = new[] { searchString };\n                        filter.assetLabels = new[] { searchString };\n                        filter.assetBundleNames = new[] { searchString };\n                        filter.showAllHits = true;\n                    }\n                    break;\n                case SearchMode.Name:\n                    filter.nameFilter = searchString;\n                    break;\n                case SearchMode.Type:\n                    filter.classNames = new[] { searchString };\n                    break;\n                case SearchMode.Label:\n                    filter.assetLabels = new[] { searchString };\n                    break;\n                case SearchMode.AssetBundleName:\n                    filter.assetBundleNames = new[] { searchString };\n                    break;\n            }\n\n            return filter;\n        }\n\n        static List<SearchableEditorWindow> searchableWindows = new List<SearchableEditorWindow>();\n        private static int s_SearchableEditorWindowSearchField = \"SearchableEditorWindowSearchField\".GetHashCode();\n\n        internal HierarchyType m_HierarchyType = HierarchyType.Assets;\n        internal string m_SearchFilter = \"\";\n        internal SearchMode m_SearchMode = SearchMode.All;\n        bool m_FocusSearchField = false;\n        bool m_HasSearchFilterFocus = false;\n        protected int m_SearchGroup;\n\n        internal const float k_SearchTimerDelaySecs = 0.250f;\n        private double m_NextSearch = double.MaxValue;\n        internal bool m_SyncSearch;\n        internal string m_OldSearch;\n        string m_SearchStringDebounced;\n        Action m_DeregisterDebounceCall;\n\n        [MenuItem(\"CONTEXT/Component/Find References In Scene\", secondaryPriority = 15)]\n        private static void OnSearchForReferencesToComponent(MenuCommand command)\n        {\n            var component = command.context as Component;\n            if (component)\n                SearchForReferencesToInstanceID(component.GetInstanceID());\n        }\n\n        [MenuItem(\"CONTEXT/Component/Properties...\", priority = 99999)]\n        private static void OnOpenPropertiesToComponent(MenuCommand command)\n        {\n            var component = command.context as Component;\n            if (!component)\n                return;\n\n            PropertyEditor.OpenPropertyEditor(component);\n        }\n\n        [MenuItem(\"Assets/Find References In Scene\", false, 25)]\n        private static void OnSearchForReferences()\n        {\n            SearchForReferencesToInstanceID(Selection.activeInstanceID);\n        }\n\n        [MenuItem(\"Assets/Find References In Scene\", true)]\n        private static bool OnSearchForReferencesValidate()\n        {\n            Object obj = Selection.activeObject;\n            if (obj != null)\n            {\n                if (AssetDatabase.Contains(obj))\n                {\n                    string path = AssetDatabase.GetAssetPath(obj);\n                    return !System.IO.Directory.Exists(path);\n                }\n            }\n\n            return false;\n        }\n\n        [MenuItem(\"Assets/Find References In Project\", false, 26)]\n        private static void OnSearchForReferencesInProject()\n        {\n            SearchForReferencesInProject(Selection.activeObject);\n        }\n\n        [MenuItem(\"Assets/Find References In Project\", true)]\n        private static bool OnSearchForReferencesInProjectValidate()\n        {\n            return Selection.activeObject && Selection.activeObject != null;\n        }\n\n        virtual public void OnEnable()\n        {\n            SearchService.SearchService.syncSearchChanged += OnSyncSearchChanged;\n            searchableWindows.Add(this);\n        }\n\n        virtual public void OnDisable()\n        {\n            SearchService.SearchService.syncSearchChanged -= OnSyncSearchChanged;\n            searchableWindows.Remove(this);\n            m_DeregisterDebounceCall = null;\n        }\n\n        private void OnSyncSearchChanged(SearchService.SearchService.SyncSearchEvent evt, string syncViewId, string searchQuery)\n        {\n            if (SearchService.SceneSearch.HasEngineOverride())\n            {\n                if (evt == SearchService.SearchService.SyncSearchEvent.StartSession)\n                {\n                    // When starting a synced session, back the current search to restore it\n                    m_OldSearch = m_SearchFilter;\n                }\n\n                if (syncViewId == SearchService.SceneSearch.GetActiveSearchEngine().GetType().FullName)\n                {\n                    SetSearchFilter(searchQuery, (SearchMode)searchMode, true, true);\n                    m_SyncSearch = true;\n                }\n                else if (m_SyncSearch)\n                {\n                    // When changing the source id, restore old search so user is not affected\n                    m_SyncSearch = false;\n                    if (string.IsNullOrEmpty(m_OldSearch))\n                    {\n                        ClearSearchFilter();\n                    }\n                    else\n                    {\n                        SetSearchFilter(m_OldSearch, (SearchMode)searchMode, true, true);\n                    }\n                }\n\n                if (evt == SearchService.SearchService.SyncSearchEvent.EndSession)\n                {\n                    m_SyncSearch = false;\n                }\n            }\n        }\n\n        void OnInspectorUpdate()\n        {\n            // if it's time for a search we do it\n            if (EditorApplication.timeSinceStartup > m_NextSearch)\n            {\n                m_NextSearch = double.MaxValue;\n                Repaint();\n                EditorApplication.Internal_CallSearchHasChanged();\n            }\n        }\n\n        internal bool hasSearchFilter\n        {\n            get { return m_SearchFilter != \"\"; }\n        }\n\n        internal bool hasSearchFilterFocus\n        {\n            get { return m_HasSearchFilterFocus; }\n            set { m_HasSearchFilterFocus = value; }\n        }\n\n        internal SearchMode searchMode\n        {\n            get { return m_SearchMode; }\n            set { m_SearchMode = value; }\n        }\n\n        internal static void SearchForReferencesInProject(UnityEngine.Object obj)\n        {\n            CommandService.Execute(\"OpenToFindReferenceOnObject\", CommandHint.Menu, obj);\n        }\n\n        internal static void SearchForReferencesToInstanceID(int instanceID)\n        {\n            string searchFilter;\n\n            // Don't remove \"Assets\" prefix, we need to support Packages as well (https://fogbugz.unity3d.com/f/cases/1161019/)\n            string path = AssetDatabase.GetAssetPath(instanceID);\n            if (path.IndexOf(' ') != -1)\n                path = '\"' + path + '\"';\n\n            if (AssetDatabase.IsMainAsset(instanceID))\n                searchFilter = \"ref:\" + path;\n            else\n                searchFilter = \"ref:\" + instanceID + \":\" + path;\n\n            foreach (SearchableEditorWindow sw in searchableWindows)\n            {\n                if (sw.m_HierarchyType == HierarchyType.GameObjects)\n                {\n                    sw.SetSearchFilter(searchFilter, SearchMode.All, false, false);\n                    sw.m_HasSearchFilterFocus = true;\n                    sw.Repaint();\n                }\n            }\n        }\n\n        internal void UnfocusSearchField()\n        {\n            if (hasSearchFilterFocus)\n                GUIUtility.keyboardControl = 0;\n        }\n\n        internal void FocusSearchField()\n        {\n            m_FocusSearchField = true;\n        }\n\n        internal void ClearSearchFilter()\n        {\n            SetSearchFilter(\"\", m_SearchMode, true, false);\n            // Reset current editor. This is needed, so if the user types into a search field, and then\n            // a new object is selected, which is not in the filter, with the editor still having keyboard focus,\n            // the search field gets properly cleared.\n\n            if (EditorGUI.s_RecycledEditor != null)\n                EditorGUI.s_RecycledEditor.EndEditing();\n        }\n\n        internal void SelectPreviousSearchResult()\n        {\n            foreach (SearchableEditorWindow sw in searchableWindows)\n            {\n                if (sw is SceneHierarchyWindow)\n                {\n                    ((SceneHierarchyWindow)sw).SelectPrevious();\n                    return;\n                }\n            }\n        }\n\n        internal void SelectNextSearchResult()\n        {\n            foreach (SearchableEditorWindow sw in searchableWindows)\n            {\n                if (sw is SceneHierarchyWindow)\n                {\n                    ((SceneHierarchyWindow)sw).SelectNext();\n                    return;\n                }\n            }\n        }\n\n        internal virtual void SetSearchFilter(string searchFilter, SearchMode mode, bool setAll, bool delayed)\n        {\n            m_SearchMode = mode;\n            m_SearchFilter = searchFilter;\n\n            if (setAll)\n            {\n                foreach (SearchableEditorWindow sw in searchableWindows)\n                {\n                    if (sw != this && sw.m_HierarchyType == m_HierarchyType && m_SearchGroup == sw.m_SearchGroup && sw.m_HierarchyType != HierarchyType.Assets)\n                        sw.SetSearchFilter(m_SearchFilter, m_SearchMode, false, delayed);\n                }\n            }\n\n            if (delayed)\n            {\n                m_NextSearch = EditorApplication.timeSinceStartup + k_SearchTimerDelaySecs;\n            }\n            else\n            {\n                Repaint();\n                EditorApplication.Internal_CallSearchHasChanged();\n            }\n        }\n\n        internal virtual void ClickedSearchField()\n        {\n        }\n\n        internal void SearchFieldGUI()\n        {\n            SearchFieldGUI(EditorGUILayout.kLabelFloatMaxW * 1.5f);\n        }\n\n        void SetSearchFilterDebounced()\n        {\n            SetSearchFilter(m_SearchStringDebounced, searchMode, true, true);\n            m_SearchStringDebounced = \"\";\n        }\n\n        internal void SearchFieldGUI(float maxWidth)\n        {\n            Rect rect = GUILayoutUtility.GetRect(EditorGUILayout.kLabelFloatMaxW * 0.2f, maxWidth, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.toolbarSearchFieldWithJump);\n\n            var drawSearchPopupButton = ModeService.HasCapability(ModeCapability.SearchPopupButton, true);\n            if (!drawSearchPopupButton)\n            {\n                // Add a 2px margin if the search popup button is not drawn; we don't want a margin between the search\n                // field and the button if the button is present.\n                rect.xMax -= 2f;\n            }\n\n            if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition))\n                ClickedSearchField();\n\n            GUI.SetNextControlName(\"SearchFilter\");\n            if (m_FocusSearchField)\n            {\n                EditorGUI.FocusTextInControl(\"SearchFilter\");\n                if (Event.current.type == EventType.Repaint)\n                    m_FocusSearchField = false;\n            }\n\n            int searchMode = (int)m_SearchMode;\n\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape && GUI.GetNameOfFocusedControl() == \"SearchFilter\")\n                SetSearchFilter(\"\", (SearchMode)searchMode, true, true);\n\n            string[] enumStrings = System.Enum.GetNames(m_HierarchyType == HierarchyType.GameObjects ? typeof(SearchModeHierarchyWindow) : typeof(SearchMode));\n            int searchFieldControlId = GUIUtility.GetControlID(s_SearchableEditorWindowSearchField, FocusType.Keyboard, rect);\n\n            EditorGUI.BeginChangeCheck();\n            string searchFilter =\n                EditorGUI.ToolbarSearchField(\n                    searchFieldControlId,\n                    rect,\n                    enumStrings,\n                    ref searchMode,\n                    m_SearchFilter,\n                    m_SyncSearch ? EditorStyles.toolbarSearchFieldWithJumpPopupSynced : EditorStyles.toolbarSearchFieldWithJumpPopup,\n                    m_SyncSearch ? EditorStyles.toolbarSearchFieldWithJumpSynced : EditorStyles.toolbarSearchFieldWithJump,\n                    string.IsNullOrEmpty(m_SearchFilter) ? EditorStyles.toolbarSearchFieldCancelButtonWithJumpEmpty : EditorStyles.toolbarSearchFieldCancelButtonWithJump);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_SearchMode = (SearchMode)searchMode;\n                m_SearchStringDebounced = searchFilter;\n                m_DeregisterDebounceCall?.Invoke();\n                m_DeregisterDebounceCall = EditorApplication.CallDelayed(SetSearchFilterDebounced, SearchUtils.debounceThresholdMs / 1000f);\n            }\n\n            m_HasSearchFilterFocus = GUIUtility.keyboardControl == searchFieldControlId;\n\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape && m_SearchFilter != \"\" && GUIUtility.hotControl == 0)\n            {\n                m_SearchFilter = \"\";\n                SetSearchFilter(\"\", (SearchMode)searchMode, true, true);\n                Event.current.Use();\n                m_HasSearchFilterFocus = false;\n            }\n\n            if (m_HasSearchFilterFocus)\n            {\n                SearchService.SearchService.HandleSearchEvent(this, Event.current, m_SearchFilter);\n            }\n\n            if (drawSearchPopupButton)\n            {\n                SearchService.SearchService.DrawOpenSearchButton(this, m_SearchFilter);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ProjectTemplateWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEditorInternal;\n\nnamespace UnityEditor\n{\n    internal class ProjectTemplateWindow : EditorWindow\n    {\n        string m_Path;\n        string m_Name;\n        string m_DisplayName;\n        string m_Description;\n        string m_DefaultScene;\n        string m_Version;\n\n        [MenuItem(\"internal:Project/Save As Template...\")]\n        internal static void SaveAsTemplate()\n        {\n            var window = EditorWindow.GetWindow<ProjectTemplateWindow>();\n            window.Show();\n        }\n\n        void OnEnable()\n        {\n            titleContent = EditorGUIUtility.TrTextContent(\"Save Template\");\n        }\n\n        string ReadJsonString(JSONValue json, string key)\n        {\n            if (json.ContainsKey(key) && !json[key].IsNull())\n            {\n                return json[key].AsString();\n            }\n            return null;\n        }\n\n        void OnGUI()\n        {\n            if (GUILayout.Button(\"Select Folder\", GUILayout.Width(100)))\n            {\n                m_Path = EditorUtility.SaveFolderPanel(\"Choose target folder\", \"\", \"\");\n                var packageJsonPath = Path.Combine(m_Path, \"package.json\");\n                if (File.Exists(packageJsonPath))\n                {\n                    var packageJson = File.ReadAllText(packageJsonPath);\n                    var json = new JSONParser(packageJson).Parse();\n                    m_Name = ReadJsonString(json, \"name\");\n                    m_DisplayName = ReadJsonString(json, \"displayName\");\n                    m_Description = ReadJsonString(json, \"description\");\n                    m_DefaultScene = ReadJsonString(json, \"defaultScene\");\n                    m_Version = ReadJsonString(json, \"version\");\n                }\n            }\n            EditorGUILayout.TextField(\"Path:\", m_Path);\n\n            m_Name = EditorGUILayout.TextField(\"Name:\", m_Name);\n            m_DisplayName = EditorGUILayout.TextField(\"Display name:\", m_DisplayName);\n            m_Description = EditorGUILayout.TextField(\"Description:\", m_Description);\n            m_DefaultScene = EditorGUILayout.TextField(\"Default scene:\", m_DefaultScene);\n            m_Version = EditorGUILayout.TextField(\"Version:\", m_Version);\n\n            if (GUILayout.Button(\"Save\", GUILayout.Width(100)))\n            {\n                if (String.IsNullOrEmpty(m_Path))\n                {\n                    m_Path = EditorUtility.SaveFolderPanel(\"Save template to folder\", \"\", \"\");\n                }\n                AssetDatabase.SaveAssets();\n                EditorUtility.SaveProjectAsTemplate(m_Path, m_Name, m_DisplayName, m_Description, m_DefaultScene, m_Version);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/RegistryUtil.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\n\nnamespace UnityEditorInternal\n{\n    //*undocumented*\n    public enum RegistryView\n    {\n        Default = 0,\n        _32 = 1,\n        _64 = 2,\n    }\n\n    //*undocumented*\n    [NativeType(Header = \"Editor/Mono/RegistryUtil.bindings.h\")]\n    public class RegistryUtil\n    {\n        public static extern uint GetRegistryUInt32Value(string subKey, string valueName, uint defaultValue, RegistryView view);\n\n        public static extern string GetRegistryStringValue(string subKey, string valueName, string defaultValue, RegistryView view);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/RemoteInput/Remoting.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\nusing Unity.Collections;\nusing Unity.Collections.LowLevel.Unsafe;\n\n[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(\"Unity.Remoting.Editor\")]\n\nnamespace UnityEditor.Remoting\n{\n    [NativeHeader(\"Editor/Mono/RemoteInput/Remoting.bindings.h\")]\n    internal partial class RemotingInternal\n    {\n        extern static private void ReceiveData(IntPtr buffer, int bufferSize);\n\n        extern static public void SetConnectedExternally(bool connected);\n        static public unsafe void ReceiveData(NativeArray<byte> buffer, int bufferSize) { ReceiveData((IntPtr)buffer.GetUnsafeReadOnlyPtr(), bufferSize); }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/RemoveLegacyMenuItems.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    [InitializeOnLoad]\n    static class RemoveLegacyRPMenuItems\n    {\n        static RemoveLegacyRPMenuItems()\n        {\n            EditorApplication.delayCall += RemoveBIRPMenuItems;\n        }\n\n        static void RemoveBIRPMenuItems()\n        {\n            if (QualitySettings.renderPipeline == null && GraphicsSettings.defaultRenderPipeline == null) return;\n\n            Menu.RemoveMenuItem(\"Assets/Create/Shader/Standard Surface Shader\");\n            Menu.RemoveMenuItem(\"Assets/Create/Shader/Image Effect Shader\");\n            Menu.RemoveMenuItem(\"Assets/Create/Shader/Unlit Shader\");\n\n            Menu.RemoveMenuItem(\"Assets/Create/Shader Graph/BuiltIn/Lit Shader Graph\");\n            Menu.RemoveMenuItem(\"Assets/Create/Shader Graph/BuiltIn/Unlit Shader Graph\");\n            Menu.RemoveMenuItem(\"Assets/Create/Shader Graph/BuiltIn/Canvas Shader Graph\");\n\n            Menu.RemoveMenuItem(\"Assets/Create/Rendering/Lens Flare\");\n\n            Menu.RemoveMenuItem(\"Component/Effects/Projector\");\n            Menu.RemoveMenuItem(\"Component/Effects/Halo\");\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/RenderDoc/RenderDoc.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor;\nusing UnityEditor.SceneManagement;\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditorInternal\n{\n    [NativeHeader(\"Editor/Src/RenderDoc/RenderDoc.h\")]\n    [StaticAccessor(\"RenderDoc\", StaticAccessorType.DoubleColon)]\n    public static partial class RenderDoc\n    {\n        [WindowAction]\n        static WindowAction RenderDocGlobalAction()\n        {\n            // Developer-mode render doc button to enable capturing any HostView content/panels\n            var action = WindowAction.CreateWindowActionButton(\"RenderDoc\", CaptureRenderDoc, null, ContainerWindow.kButtonWidth + 1, RenderDocCaptureButton);\n            action.validateHandler = ShowRenderDocButton;\n            return action;\n        }\n\n        public static extern bool IsInstalled();\n        public static extern bool IsLoaded();\n        public static extern bool IsSupported();\n        public static extern void Load();\n\n        public static void BeginCaptureRenderDoc(EditorWindow window)\n            => window.m_Parent.BeginCaptureRenderDoc();\n        public static void EndCaptureRenderDoc(EditorWindow window)\n            => window.m_Parent.EndCaptureRenderDoc();\n\n        static EditorWindow s_EditorWindowScheduledForCapture = null;\n        static GUIContent s_RenderDocContent;\n        internal static bool RenderDocCaptureButton(EditorWindow view, WindowAction self, Rect r)\n        {\n            if (s_RenderDocContent == null)\n                s_RenderDocContent = EditorGUIUtility.TrIconContent(\"FrameCapture\", RenderDocUtil.openInRenderDocTooltip);\n\n            Rect r2 = new Rect(r.xMax - r.width, r.y, r.width, r.height);\n            return GUI.Button(r2, s_RenderDocContent, EditorStyles.iconButton);\n        }\n\n        private static void CaptureRenderDoc(EditorWindow view, WindowAction self)\n        {\n            if (view is GameView)\n                view.m_Parent.CaptureRenderDocScene();\n            else\n                view.m_Parent.CaptureRenderDocFullContent();\n        }\n\n        private static bool ShowRenderDocButton(EditorWindow view, WindowAction self)\n        {\n            return Unsupported.IsDeveloperMode() && IsLoaded() && IsSupported();\n        }\n\n        internal static void LoadRenderDoc()\n        {\n            if (IsInstalled() && !IsLoaded() && EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())\n            {\n                ShaderUtil.RequestLoadRenderDoc();\n            }\n        }\n\n        [Shortcut(RenderDocUtil.captureRenderDocShortcutID, KeyCode.C, ShortcutModifiers.Alt)]\n        internal static void CaptureRenderDoc()\n        {\n            if (IsInstalled() && !IsLoaded())\n            {\n                s_EditorWindowScheduledForCapture = EditorWindow.focusedWindow;\n                LoadRenderDoc();\n            }\n            else if (EditorWindow.focusedWindow != null)\n            {\n                CaptureRenderDoc(EditorWindow.focusedWindow, null);\n            }\n        }\n\n        [RequiredByNativeCode]\n        static void RenderDocLoaded()\n        {\n            if (s_EditorWindowScheduledForCapture != null)\n            {\n                s_EditorWindowScheduledForCapture.Focus();\n                CaptureRenderDoc();\n                s_EditorWindowScheduledForCapture = null;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/RenderDoc/RenderDocUtil.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.IO;\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class RenderDocUtil\n    {\n        public const string captureRenderDocShortcutID = \"Window/Capture frame with RenderDoc\";\n        public const string openInRenderDocTooltip = \"Capture the current view and open in RenderDoc\";\n\n        public static GUIContent LoadRenderDocMenuItem => EditorGUIUtility.TrTextContent($\"Load RenderDoc \" +\n            $\"{KeyCombination.SequenceToMenuString(ShortcutManager.instance.GetShortcutBinding(captureRenderDocShortcutID).keyCombinationSequence)}\");\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/RenderPipelineGlobalSettingsEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Reflection;\nusing UnityEditor.UIElements;\nusing UnityEngine.Rendering;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor.Rendering\n{\n    [CustomEditor(typeof(RenderPipelineGlobalSettings), editorForChildClasses: true)]\n    public class RenderPipelineGlobalSettingsEditor : Editor\n    {\n        static class Strings\n        {\n            public static readonly string k_WarningAttributeMessage = $\"{nameof(RenderPipelineGlobalSettings)} should be used with {nameof(SupportedOnRenderPipelineAttribute)}\";\n            public static readonly string k_WarningEditionMessage = $\"{nameof(RenderPipelineGlobalSettings)} should be edited from Project Settings > Graphics\";\n            public const string k_OpenGraphicsSettingsPanel = \"Open Project Settings > Graphics ...\";\n        }\n\n        public override VisualElement CreateInspectorGUI()\n        {\n            VisualElement root = new();\n\n            var attribute = target.GetType().GetCustomAttribute<SupportedOnRenderPipelineAttribute>();\n            if (attribute == null)\n                root.Add(new HelpBox(Strings.k_WarningAttributeMessage, HelpBoxMessageType.Warning));\n\n            root.Add(new HelpBox(Strings.k_WarningEditionMessage, HelpBoxMessageType.Warning));\n            var button = new Button() { text = Strings.k_OpenGraphicsSettingsPanel };\n            button.clicked += () => SettingsService.OpenProjectSettings(GraphicsSettingsProvider.s_GraphicsSettingsProviderPath);\n            root.Add(button);\n\n            if (Unsupported.IsDeveloperMode())\n            {\n                var property = serializedObject.FindProperty(\"m_Settings\");\n                UnityEngine.Debug.Assert(property != null);\n                root.Add(new PropertyField(property));\n            }\n\n            return root;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/RenderPipelineGraphicsSettingsCollectionPropertyDrawer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing UnityEditor.UIElements;\nusing UnityEditor.UIElements.ProjectSettings;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEngine.UIElements;\nusing UnityEditor.Categorization;\n\nnamespace UnityEditor.Rendering.GraphicsSettingsInspectors\n{\n    //internal for tests\n    [CustomPropertyDrawer(typeof(RenderPipelineGraphicsSettingsCollection))]\n    internal class RenderPipelineGraphicsSettingsCollectionPropertyDrawer : PropertyDrawer\n    {\n        const string k_LineClass = \"contextual-menu-button--handler\";\n        const string k_GraphicsSettingsClass = \"project-settings-section__graphics-settings\";\n        const string k_GraphicsSettingsHighlightableClass = \"graphics-settings__highlightable\";\n        const string k_GraphicsSettingsContentFollowupClass = \"project-settings-section__content-followup\";\n\n        internal struct SettingsInfo : ICategorizable\n        {\n            public SerializedProperty property { get; private set; }\n            public Type type { get; private set; }\n            public HelpURLAttribute helpURLAttribute { get; private set; }\n            public bool onlyForDevMode { get; private set; }\n            public IRenderPipelineGraphicsSettings target => property?.boxedValue as IRenderPipelineGraphicsSettings;\n            \n            public static SettingsInfo? ExtractFrom(SerializedProperty property)\n            {\n                //boxedProperty can be null if we keep in the list a data blob for a type that have disappears\n                //this can happens if user remove a IRenderPipelineGraphicsSettings from his project for instance\n                Type type = property?.boxedValue?.GetType();\n                if (type == null || !typeof(IRenderPipelineGraphicsSettings).IsAssignableFrom(type))\n                    return null;\n\n                // If GraphicsSettings is hidden, discard it\n                bool hidden = type.GetCustomAttribute<HideInInspector>() != null;\n                if (!Unsupported.IsDeveloperMode() && hidden)\n                    return null;\n\n                return new SettingsInfo()\n                {\n                    property = property.Copy(),\n                    type = type,\n                    helpURLAttribute = type.GetCustomAttribute<HelpURLAttribute>(),\n                    onlyForDevMode = hidden,\n                };\n            }\n        }\n\n        //internal for tests\n        internal static List<Category<LeafElement<SettingsInfo>>> Categorize(SerializedProperty property)\n        {\n            List<SettingsInfo> elements = new();\n\n            var propertyIterator = property.Copy();\n            var end = propertyIterator.GetEndProperty();\n            propertyIterator.NextVisible(true);\n            while (!SerializedProperty.EqualContents(propertyIterator, end))\n            {\n                var info = SettingsInfo.ExtractFrom(propertyIterator);\n                if (info == null)\n                {\n                    propertyIterator.NextVisible(false);\n                    continue; //remove array length and hidden properties\n                }\n                elements.Add(info.Value);\n                propertyIterator.NextVisible(false);\n            }\n\n            return elements.SortByCategory();\n        }\n\n        void DrawHelpButton(VisualElement root, HelpURLAttribute helpURLAttribute)\n        {\n            if (helpURLAttribute?.URL != null)\n            {\n                var button = new Button(Background.FromTexture2D(EditorGUIUtility.LoadIcon(\"_Help\")), () => Help.BrowseURL(helpURLAttribute.URL));\n                root.Add(button);\n            }\n        }\n\n        void ShowContextualMenu(Rect rect, List<LeafElement<SettingsInfo>> siblings)\n        {\n            List<(IRenderPipelineGraphicsSettings target, SerializedProperty property)> targets = new(siblings.Count);\n            foreach (SettingsInfo sibling in siblings)\n                targets.Add((sibling.target, sibling.property));\n\n            var contextualMenu = new GenericMenu(); //use ImGUI for now, need to be updated later\n            RenderPipelineGraphicsSettingsContextMenuManager.PopulateContextMenu(targets, ref contextualMenu);\n            contextualMenu.DropDown(new Rect(rect.position + Vector2.up * rect.size.y, Vector2.zero), shouldDiscardMenuOnSecondClick: true);\n        }\n\n        void DrawContextualMenuButton(VisualElement root, LeafElement<SettingsInfo> settingsInfo)\n        {\n            var button = new Button(Background.FromTexture2D(EditorGUIUtility.LoadIcon(\"pane options\")));\n            button.clicked += () => ShowContextualMenu(button.worldBound, settingsInfo.parent.content);\n            root.Add(button);\n        }\n\n        void DrawHeader(VisualElement root, Category<LeafElement<SettingsInfo>> category)\n        {\n            var line = new VisualElement();\n            line.style.flexDirection = FlexDirection.Row;\n            line.AddToClassList(k_LineClass);\n\n            var label = new Label(category.name);\n            label.AddToClassList(ProjectSettingsSection.Styles.header);\n            line.Add(label);\n\n            root.Add(line);\n\n            var firstSetting = category[0];\n            DrawHelpButton(line, firstSetting.data.helpURLAttribute);\n            DrawContextualMenuButton(line, firstSetting);\n        }\n\n        void DrawContent(VisualElement root, SettingsInfo settingsInfo, bool first)\n        {\n            var graphicsSettings = new PropertyField(settingsInfo.property)\n            {\n                name = settingsInfo.type.Name,\n                classList =\n                {\n                    ProjectSettingsSection.Styles.content,\n                    k_GraphicsSettingsClass,\n                }\n            };\n            if (!first)\n                graphicsSettings.classList.Add(k_GraphicsSettingsContentFollowupClass);\n            root.Add(graphicsSettings);\n        }\n\n        public override VisualElement CreatePropertyGUI(SerializedProperty property)\n        {\n            var root = new VisualElement { name = \"GlobalSettingsCollection\" };\n            var graphicsSettings = property.FindPropertyRelative(\"m_List\");\n            Debug.Assert(graphicsSettings != null);\n\n            foreach (var category in Categorize(graphicsSettings))\n            {\n                DrawHeader(root, category);\n\n                DrawContent(root, category[0], first: true);\n                for (int i = 1; i < category.count; ++i)\n                    DrawContent(root, category[i], first: false);\n            }\n\n            return root;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/RenderPipelineGraphicsSettingsContextMenu.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Inspector.GraphicsSettingsInspectors;\nusing UnityEditor.Rendering.Settings;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor.Rendering\n{\n    // We need a base non generic to fetch with TypeCache. But User should use the\n    // generic type as the generic is used to retrieve the IRenderPipelineGraphicsSettings\n    // used.\n\n    #region Deprecated interface definition\n    // This version indicates that it will be applied to any IRenderPipelineGraphicsSettings\n    // UUM-99684: This interface is deprecated because the PropertyDrawer is cached internally by unity editor and will be null after domain reload\n    [Obsolete(\"IRenderPipelineGraphicsSettingsContextMenu is deprecated and will be removed in a future release. Use IRenderPipelineGraphicsSettingsContextMenu2 instead. #from(6000.0)\")]\n    public interface IRenderPipelineGraphicsSettingsContextMenu\n    {\n        void PopulateContextMenu(IRenderPipelineGraphicsSettings setting, PropertyDrawer drawer, ref GenericMenu menu);\n\n        int priority => 0;\n    }\n\n    // This version is specialized for T only\n    // UUM-99684: This interface is deprecated because the PropertyDrawer is cached internally by unity editor and will be null after domain reload\n    [Obsolete(\"IRenderPipelineGraphicsSettingsContextMenu<T> is deprecated and will be removed in a future release. Use IRenderPipelineGraphicsSettingsContextMenu2<T> instead. #from(6000.0)\")]\n    public interface IRenderPipelineGraphicsSettingsContextMenu<T> : IRenderPipelineGraphicsSettingsContextMenu\n        where T : class, IRenderPipelineGraphicsSettings\n    {\n        void PopulateContextMenu(T setting, PropertyDrawer drawer, ref GenericMenu menu);\n        void IRenderPipelineGraphicsSettingsContextMenu.PopulateContextMenu(IRenderPipelineGraphicsSettings setting, PropertyDrawer drawer, ref GenericMenu menu)\n            => PopulateContextMenu(setting as T, drawer, ref menu);\n    }\n\n    [Obsolete]\n    struct OldRenderPipelineGraphicsSettingsContextMenuComparer : IComparer<IRenderPipelineGraphicsSettingsContextMenu>, IComparer<(IRenderPipelineGraphicsSettingsContextMenu, IEnumerable<(IRenderPipelineGraphicsSettings, SerializedProperty)>)>\n    {\n        //Sorting is done first by priority, but when priority\n        //are the same, we sort by type name to have a stable result.\n        public int Compare(IRenderPipelineGraphicsSettingsContextMenu m1, IRenderPipelineGraphicsSettingsContextMenu m2)\n        {\n            var compResult = m1.priority.CompareTo(m2.priority);\n            if (compResult == 0)\n                compResult = m1.GetType().FullName.CompareTo(m2.GetType().FullName);\n            return compResult;\n        }\n\n        public int Compare((IRenderPipelineGraphicsSettingsContextMenu, IEnumerable<(IRenderPipelineGraphicsSettings, SerializedProperty)>) m1, (IRenderPipelineGraphicsSettingsContextMenu, IEnumerable<(IRenderPipelineGraphicsSettings, SerializedProperty)>) m2)\n            => Compare(m1.Item1, m2.Item1);\n    }\n    #endregion\n\n    // This version indicates that it will be applied to any IRenderPipelineGraphicsSettings\n    public interface IRenderPipelineGraphicsSettingsContextMenu2\n    {\n        void PopulateContextMenu(IRenderPipelineGraphicsSettings setting, SerializedProperty property, ref GenericMenu menu);\n\n        int priority => 0;\n    }\n    \n    // This version is specialized for T only\n    public interface IRenderPipelineGraphicsSettingsContextMenu2<T> : IRenderPipelineGraphicsSettingsContextMenu2\n        where T : class, IRenderPipelineGraphicsSettings\n    {\n        void PopulateContextMenu(T setting, SerializedProperty property, ref GenericMenu menu);\n        void IRenderPipelineGraphicsSettingsContextMenu2.PopulateContextMenu(IRenderPipelineGraphicsSettings setting, SerializedProperty property, ref GenericMenu menu)\n            => PopulateContextMenu(setting as T, property, ref menu);\n    }\n\n    struct RenderPipelineGraphicsSettingsContextMenuComparer : IComparer<IRenderPipelineGraphicsSettingsContextMenu2>, IComparer<(IRenderPipelineGraphicsSettingsContextMenu2, IEnumerable<(IRenderPipelineGraphicsSettings, SerializedProperty)>)>\n    {\n        //Sorting is done first by priority, but when priority\n        //are the same, we sort by type name to have a stable result.\n        public int Compare(IRenderPipelineGraphicsSettingsContextMenu2 m1, IRenderPipelineGraphicsSettingsContextMenu2 m2)\n        {\n            var compResult = m1.priority.CompareTo(m2.priority);\n            if (compResult == 0)\n                compResult = m1.GetType().FullName.CompareTo(m2.GetType().FullName);\n            return compResult;\n        }\n\n        public int Compare((IRenderPipelineGraphicsSettingsContextMenu2, IEnumerable<(IRenderPipelineGraphicsSettings, SerializedProperty)>) m1, (IRenderPipelineGraphicsSettingsContextMenu2, IEnumerable<(IRenderPipelineGraphicsSettings, SerializedProperty)>) m2)\n            => Compare(m1.Item1, m2.Item1);\n    }\n\n    static class RenderPipelineGraphicsSettingsContextMenuManager\n    {\n        // typeof(IRenderPipelineGraphicsSettings2) is used for global menu entries.\n        // typeof(IRenderPipelineGraphicsSettings) is used for global menu entries.\n\n        #region Deprecated interface list initialization\n        // still supporting old IRenderPipelineGraphicsSettings, though it is sorted out as to be inserted after.\n        // all obsolete handling (caching and sorting before call) is below under pragma\n#pragma warning disable CS0618 // Type or member is obsolete\n        static Lazy<Dictionary<Type, List<IRenderPipelineGraphicsSettingsContextMenu>>> s_OldMenuEntries = new(OldInitialize);\n\n        static Dictionary<Type, List<IRenderPipelineGraphicsSettingsContextMenu>> OldInitialize()\n        {\n#pragma warning disable CS0612 // Type or member is obsolete\n            OldRenderPipelineGraphicsSettingsContextMenuComparer comparer = new();\n#pragma warning restore CS0612 // Type or member is obsolete\n            Dictionary<Type, List<IRenderPipelineGraphicsSettingsContextMenu>> contextMenus = new();\n\n            Type GetTargetGraphicsSettingsType(Type menuType)\n            {\n                var interfaces = menuType.GetInterfaces();\n                foreach (var @interface in interfaces)\n                    if (@interface.IsGenericType && @interface.GetGenericTypeDefinition() == typeof(IRenderPipelineGraphicsSettingsContextMenu<>))\n                        return @interface.GetGenericArguments()[0];\n                return typeof(IRenderPipelineGraphicsSettings);\n            }\n\n            void AddToList(Type menuType)\n            {\n                if (menuType.IsAbstract || !typeof(IRenderPipelineGraphicsSettingsContextMenu).IsAssignableFrom(menuType))\n                    return;\n\n                Type rpgsType = GetTargetGraphicsSettingsType(menuType);\n                if (!contextMenus.ContainsKey(rpgsType))\n                    contextMenus[rpgsType] = new();\n\n                var instance = Activator.CreateInstance(menuType, true) as IRenderPipelineGraphicsSettingsContextMenu;\n                contextMenus[rpgsType].Add(instance);\n            }\n\n            foreach (Type menuType in TypeCache.GetTypesDerivedFrom<IRenderPipelineGraphicsSettingsContextMenu>())\n                AddToList(menuType);\n\n            foreach (var list in contextMenus.Values)\n                list.Sort(comparer);\n\n            return contextMenus;\n        }\n#pragma warning restore CS0618 // Type or member is obsolete\n        #endregion\n\n        static Lazy<Dictionary<Type, List<IRenderPipelineGraphicsSettingsContextMenu2>>> s_MenuEntries = new(Initialize);\n\n        static Dictionary<Type, List<IRenderPipelineGraphicsSettingsContextMenu2>> Initialize()\n        {\n            RenderPipelineGraphicsSettingsContextMenuComparer comparer = new();\n            Dictionary<Type, List<IRenderPipelineGraphicsSettingsContextMenu2>> contextMenus = new();\n\n            Type GetTargetGraphicsSettingsType(Type menuType)\n            {\n                var interfaces = menuType.GetInterfaces();\n                foreach (var @interface in interfaces)\n                    if (@interface.IsGenericType && @interface.GetGenericTypeDefinition() == typeof(IRenderPipelineGraphicsSettingsContextMenu2<>))\n                        return @interface.GetGenericArguments()[0];\n                return typeof(IRenderPipelineGraphicsSettings);\n            }\n\n            void AddToList(Type menuType)\n            {\n                if (menuType.IsAbstract || !typeof(IRenderPipelineGraphicsSettingsContextMenu2).IsAssignableFrom(menuType))\n                    return;\n\n                Type rpgsType = GetTargetGraphicsSettingsType(menuType);\n                if (!contextMenus.ContainsKey(rpgsType))\n                    contextMenus[rpgsType] = new();\n\n                var instance = Activator.CreateInstance(menuType, true) as IRenderPipelineGraphicsSettingsContextMenu2;\n                contextMenus[rpgsType].Add(instance);\n            }\n\n            foreach (Type menuType in TypeCache.GetTypesDerivedFrom<IRenderPipelineGraphicsSettingsContextMenu2>())\n                AddToList(menuType);\n\n            foreach (var list in contextMenus.Values)\n                list.Sort(comparer);\n\n            return contextMenus;\n        }\n\n        delegate void Populator(ref GenericMenu menu);\n\n        static IEnumerable<Populator> FilteredAndOrderedPopulatorsFor(IEnumerable<(IRenderPipelineGraphicsSettings target, SerializedProperty property)> graphicsSettings)\n        {\n            var defaultMenuPopulators = s_MenuEntries.Value.GetValueOrDefault(typeof(IRenderPipelineGraphicsSettings));\n            List<(IRenderPipelineGraphicsSettingsContextMenu2 populator, IEnumerable<(IRenderPipelineGraphicsSettings target, SerializedProperty property)> data)> contextMenus = new();\n            foreach(var defaultMenuPopulator in defaultMenuPopulators)\n                contextMenus.Add((defaultMenuPopulator, graphicsSettings));\n            foreach(var settings in graphicsSettings)\n                if (s_MenuEntries.Value.TryGetValue(settings.target.GetType(), out var additionalSpecificMenuPopulators))\n                    foreach (var populator in additionalSpecificMenuPopulators)\n                        contextMenus.Add((populator, new (IRenderPipelineGraphicsSettings target, SerializedProperty property)[] { settings }));\n\n            RenderPipelineGraphicsSettingsContextMenuComparer comparer = new();\n            contextMenus.Sort(comparer);\n            foreach (var contextMenu in contextMenus)\n                foreach (var target in contextMenu.data)\n                    yield return (ref GenericMenu menu) => contextMenu.populator.PopulateContextMenu(target.target, target.property, ref menu);\n\n            \n            #region Deprecated interface old call logic recreated\n            //Following can be removed once we remove the obsolete IRenderPipelineGraphicsSettingsContextMenu\n#pragma warning disable CS0618 // Type or member is obsolete\n            var oldDefaultMenuPopulators = s_OldMenuEntries.Value.GetValueOrDefault(typeof(IRenderPipelineGraphicsSettings));\n            List<(IRenderPipelineGraphicsSettingsContextMenu populator, IEnumerable<(IRenderPipelineGraphicsSettings target, SerializedProperty property)> data)> oldContextMenus = new();\n            if (oldDefaultMenuPopulators != null) //can happens, Reset is using the new version\n            {\n                foreach(var defaultMenuPopulator in oldDefaultMenuPopulators)\n                    oldContextMenus.Add((defaultMenuPopulator, graphicsSettings));\n            }\n            foreach(var settings in graphicsSettings)\n                if (s_OldMenuEntries.Value.TryGetValue(settings.target.GetType(), out var additionalSpecificMenuPopulators))\n                    foreach (var populator in additionalSpecificMenuPopulators)\n                        oldContextMenus.Add((populator, new (IRenderPipelineGraphicsSettings target, SerializedProperty property)[] { settings }));\n\n#pragma warning disable CS0612 // Type or member is obsolete\n            OldRenderPipelineGraphicsSettingsContextMenuComparer oldComparer = new();\n#pragma warning restore CS0612 // Type or member is obsolete\n            oldContextMenus.Sort(oldComparer);\n            foreach (var contextMenu in oldContextMenus)\n                foreach (var target in contextMenu.data)\n                    yield return (ref GenericMenu menu) => contextMenu.populator.PopulateContextMenu(target.target, ScriptAttributeUtility.GetHandler(target.property).propertyDrawer, ref menu);\n#pragma warning restore CS0618 // Type or member is obsolete\n            #endregion\n        }\n\n        //Note: Once IRenderPipelineGraphicsSettingsContextMenu can be fully removed, SerializedProperty property can be removed too\n        static internal void PopulateContextMenu(IEnumerable<(IRenderPipelineGraphicsSettings target, SerializedProperty property)> graphicsSettings, ref GenericMenu menu)\n        {\n            foreach (var populator in FilteredAndOrderedPopulatorsFor(graphicsSettings))\n                populator.Invoke(ref menu);\n        }\n    }\n\n    struct ResetImplementation : IRenderPipelineGraphicsSettingsContextMenu2\n    {\n        const string k_Label = \"Reset\";\n        // Keeping space in case one want to modify after the Reset\n        public int priority => int.MaxValue - 1;\n\n        List<IRenderPipelineGraphicsSettings> targets;\n\n        public void PopulateContextMenu(IRenderPipelineGraphicsSettings setting, SerializedProperty _, ref GenericMenu menu)\n        {\n            if (menu.menuItems.Count > 0)\n            {\n                if (menu.menuItems[menu.menuItems.Count - 1].userData is ResetImplementation implementation)\n                {\n                    implementation.targets.Add(setting);\n                    return;\n                }\n                else if (!menu.menuItems[menu.menuItems.Count - 1].separator)\n                    menu.AddSeparator(\"\");\n            }\n\n            if (EditorApplication.isPlaying)\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(k_Label), false);\n            else\n            {\n                targets = new() { setting };\n                menu.AddItem(EditorGUIUtility.TrTextContent(k_Label), false, (implementation) => Reset((ResetImplementation)implementation), this);\n            }\n        }\n\n        static void Reset(ResetImplementation implementation)\n        {\n            var alreadyOpenedWindow = EditorWindow.GetWindow<ProjectSettingsWindow>();\n            var renderPipelineType = RenderPipelineEditorUtility.GetPipelineTypeFromPipelineAssetType(GraphicsSettingsInspectorUtility.GetRenderPipelineAssetTypeForSelectedTab(alreadyOpenedWindow.rootVisualElement));\n            foreach (var target in implementation.targets)\n                RenderPipelineGraphicsSettingsManager.ResetRenderPipelineGraphicsSettings(target.GetType(), renderPipelineType);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/RenderPipelineResourcesEditorUtils.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Reflection;\nusing UnityEngine;\nusing UnityEngine.Assertions;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor.Rendering\n{\n    /// <summary>\n    /// Utility class for <see cref=\"RenderPipelineResources\"/> in Editor\n    /// </summary>\n    static class RenderPipelineResourcesEditorUtils\n    {\n        public enum ResultStatus\n        {\n            NothingToUpdate, //There was nothing to reload\n            InvalidPathOrNameFound, //Encountered a path that do not exist\n            ResourceReloaded, //Some resources got reloaded\n            SkipedDueToNotMainThread, //Worker Thread cannot fully load resources\n        }\n\n        internal static bool TryReloadContainedNullFields(IRenderPipelineResources resource, out ResultStatus result, out string message)\n        {\n            message = string.Empty;\n\n            result = ResultStatus.NothingToUpdate;\n\n            try\n            {\n                if (AssetDatabase.IsAssetImportWorkerProcess())\n                    result = ResultStatus.SkipedDueToNotMainThread;\n                else if (new Reloader(resource).hasChanged)\n                    result = ResultStatus.ResourceReloaded;\n            }\n            catch (InvalidImportException e)\n            {\n                message = e.Message;\n                result = ResultStatus.InvalidPathOrNameFound;\n                return false;\n            }\n\n            return true;\n        }\n\n        /// <summary>\n        /// Looks for resources in the given <paramref name=\"resource\"/> object and reload\n        /// the ones that are missing or broken.\n        /// This version will still return null value without throwing error if the issue\n        /// is due to AssetDatabase being not ready. But in this case the assetDatabaseNotReady\n        /// result will be true.\n        /// </summary>\n        /// <param name=\"resource\">The object containing reload-able resources</param>\n        /// <returns> The status </returns>\n        public static ResultStatus TryReloadContainedNullFields(IRenderPipelineResources resource)\n        {\n            ResultStatus result;\n            try\n            {\n                if (!TryReloadContainedNullFields(resource, out result, out var message))\n                    Debug.LogError(message);\n            }\n            catch (Exception e)\n            {\n                throw e;\n            }\n\n            return result;\n        }\n\n        \n        // Important: This is not meant to work with resources in Unity. This is only for packages and User code.\n        // If we need to make it work for Unity core, one want to update Reloader.GetRootPathForType(...)\n        struct Reloader\n        {\n            IRenderPipelineResources mainContainer;\n            string root;\n            public bool hasChanged { get; private set; }\n\n            public Reloader(IRenderPipelineResources container)\n            {\n                mainContainer = container;\n                hasChanged = false;\n                root = GetRootPathForType(container.GetType());\n                ReloadNullFields(container);\n            }\n\n            static string GetRootPathForType(Type type)\n            {\n                //Warning: PackageManager.PackageInfo.FindForAssembly will always provide null in Worker thread\n                var packageInfo = PackageManager.PackageInfo.FindForAssembly(type.Assembly);\n                return packageInfo == null ? \"Assets/\" : $\"Packages/{packageInfo.name}/\";\n            }\n\n            (string[] paths, SearchType location, bool isField) GetResourcesPaths(FieldInfo fieldInfo)\n            {\n                var attr = fieldInfo.GetCustomAttribute<ResourcePathsBaseAttribute>(inherit: false);\n                return (attr?.paths, attr?.location ?? default, attr?.isField ?? default);\n            }\n\n            string GetFullPath(string path, SearchType location)\n                => location == SearchType.ProjectPath\n                ? $\"{root}{path}\"\n                : path;\n\n            bool IsNull(System.Object container, FieldInfo info)\n                => IsNull(info.GetValue(container));\n\n            bool IsNull(System.Object field)\n                => field == null || field.Equals(null);\n\n            bool ConstructArrayIfNeeded(System.Object container, FieldInfo info, int length)\n            {\n                if (IsNull(container, info) || ((Array)info.GetValue(container)).Length != length)\n                {\n                    info.SetValue(container, Activator.CreateInstance(info.FieldType, length));\n                    return true;\n                }\n\n                return false;\n            }\n\n            void ReloadNullFields(System.Object container)\n            {\n                foreach (var fieldInfo in container.GetType()\n                    .GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))\n                {\n                    //Skip element that do not have path\n                    (string[] paths, SearchType location, bool isField) = GetResourcesPaths(fieldInfo);\n                    if (paths == null)\n                        continue;\n\n                    //Field case: reload if null\n                    if (isField)\n                    {\n                        hasChanged |= SetAndLoadIfNull(container, fieldInfo, GetFullPath(paths[0], location), location);\n                        continue;\n                    }\n\n                    //Array case: Find each null element and reload them\n                    hasChanged |= ConstructArrayIfNeeded(container, fieldInfo, paths.Length);\n                    var array = (Array)fieldInfo.GetValue(container);\n                    for (int index = 0; index < paths.Length; ++index)\n                        hasChanged |= SetAndLoadIfNull(array, index, GetFullPath(paths[index], location), location);\n                }\n            }\n\n            bool SetAndLoadIfNull(System.Object container, FieldInfo info, string path, SearchType location)\n            {\n                if (IsNull(container, info))\n                {\n                    info.SetValue(container, Load(path, info.FieldType, location));\n                    return true;\n                }\n\n                return false;\n            }\n\n            bool SetAndLoadIfNull(Array array, int index, string path, SearchType location)\n            {\n                var element = array.GetValue(index);\n                if (IsNull(element))\n                {\n                    array.SetValue(Load(path, array.GetType().GetElementType(), location), index);\n                    return true;\n                }\n\n                return false;\n            }\n\n            UnityEngine.Object Load(string path, Type type, SearchType location)\n            {\n                // Check if asset exist.\n                // Direct loading can be prevented by AssetDatabase being reloading.\n                var guid = AssetDatabase.AssetPathToGUID(path);\n                if (location == SearchType.ProjectPath && String.IsNullOrEmpty(guid))\n                    throw new InvalidImportException($\"Failed to find {path} in {location}.\");\n\n                UnityEngine.Object result = type == typeof(Shader)\n                    ? LoadShader(path, location)\n                    : LoadNonShaderAssets(path, type, location);\n                \n                if (IsNull(result))\n                    switch (location)\n                    {\n                        case SearchType.ProjectPath:\n                            CheckTypeMismatch(path, type);\n                            throw new InvalidImportException($\"Cannot load. Path {path} is correct but AssetDatabase cannot load now.\");\n                        case SearchType.ShaderName: throw new InvalidImportException($\"Failed to find {path} in {location}.\");\n                        case SearchType.BuiltinPath: throw new InvalidImportException($\"Failed to find {path} in {location}.\");\n                        case SearchType.BuiltinExtraPath: throw new InvalidImportException($\"Failed to find {path} in {location}.\");\n                    }\n                    \n                return result;\n            }\n\n            UnityEngine.Object LoadShader(string path, SearchType location)\n            {\n                switch (location)\n                {\n                    case SearchType.ShaderName:\n                    case SearchType.BuiltinPath:\n                    case SearchType.BuiltinExtraPath:\n                        return Shader.Find(path);\n                    case SearchType.ProjectPath:\n                        return AssetDatabase.LoadAssetAtPath(path, typeof(Shader));\n                    default:\n                        throw new NotImplementedException($\"Unknown {location}\");\n                }\n            }\n\n            UnityEngine.Object LoadNonShaderAssets(string path, Type type, SearchType location)\n                => location switch\n                {\n                    SearchType.BuiltinPath => UnityEngine.Resources.GetBuiltinResource(type, path), //log error if path is wrong and return null\n                    SearchType.BuiltinExtraPath => AssetDatabase.GetBuiltinExtraResource(type, path), //log error if path is wrong and return null\n                    SearchType.ProjectPath => AssetDatabase.LoadAssetAtPath(path, type), //return null if path is wrong\n                    SearchType.ShaderName => throw new ArgumentException($\"{nameof(SearchType.ShaderName)} is only available for Shaders.\"),\n                    _ => throw new NotImplementedException($\"Unknown {location}\")\n                };\n\n            void CheckTypeMismatch(string path, Type expectedType)\n            {\n                UnityEngine.Object[] assets = AssetDatabase.LoadAllAssetsAtPath(path);\n                if (assets == null)\n                    return;\n                bool foundCandidate = false;\n                foreach (var asset in assets)\n                    if (expectedType.IsAssignableFrom(asset.GetType()))\n                    {\n                        foundCandidate = true;\n                        break;\n                    }\n                if (!foundCandidate)\n                    throw new InvalidImportException($\"Host type is not matching any asset type at Path {path}.\");\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/RuntimeInitializeOnLoadManager.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine.Bindings;\n\nnamespace UnityEngine\n{\n    [StructLayout(LayoutKind.Sequential)]\n    internal sealed partial class RuntimeInitializeMethodInfo\n    {\n        string      m_FullClassName;\n        string      m_MethodName;\n        int         m_OrderNumber = 0;\n        bool            m_IsUnityClass = false;\n\n        internal string fullClassName { get { return m_FullClassName; } set { m_FullClassName = value; } }\n        internal string methodName { get { return m_MethodName; } set { m_MethodName = value; } }\n        internal int orderNumber { get { return m_OrderNumber; } set { m_OrderNumber = value; } }\n        internal bool isUnityClass { get { return m_IsUnityClass; } set { m_IsUnityClass = value; } }\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    [Serializable]\n    internal class RuntimeInitializeClassInfo\n    {\n        public string assemblyName;\n        public string nameSpace;\n        public string className;\n        public string methodName;\n        public int loadTypes;\n    }\n\n    [NativeHeader(\"Runtime/Misc/RuntimeInitializeOnLoadManager.h\")]\n    [StaticAccessorAttribute(\"GetRuntimeInitializeOnLoadManager()\")]\n    internal sealed partial class RuntimeInitializeOnLoadManager\n    {\n        extern internal static string[] dontStripClassNames { get; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SJSON.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Text;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Collections;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nusing JSONObject = System.Collections.IDictionary;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/SJSON.h\"),\n     StaticAccessor(\"SJSON\", StaticAccessorType.DoubleColon)]\n    internal static class SJSON\n    {\n        public static extern string Encode([NotNull] JSONObject t);\n        public static extern string EncodeObject(object o);\n        [NativeThrows] public static extern JSONObject Decode([NotNull] byte[] sjson);\n        [NativeThrows] public static extern object DecodeObject([NotNull] byte[] sjson);\n\n        public static JSONObject Load(string path)\n        {\n            if (String.IsNullOrEmpty(path))\n                throw new ArgumentNullException(nameof(path));\n            var readResult = File.ReadAllBytes(path);\n            try\n            {\n                return Decode(readResult);\n            }\n            catch (UnityException ex)\n            {\n                throw new UnityException(ex.Message.Replace(\"(memory)\", $\"({path})\"));\n            }\n        }\n\n        public static JSONObject LoadString(string json)\n        {\n            if (String.IsNullOrEmpty(json))\n                throw new ArgumentNullException(nameof(json));\n\n            try\n            {\n                return Decode(Encoding.UTF8.GetBytes(json));\n            }\n            catch (UnityException ex)\n            {\n                throw new UnityException(ex.Message.Replace(\"(memory)\", \"(string)\"), ex);\n            }\n        }\n\n        public static byte[] GetBytes(JSONObject data)\n        {\n            if (data == null)\n                throw new ArgumentNullException(nameof(data));\n\n            return Encoding.UTF8.GetBytes(Encode(data));\n        }\n\n        public static bool Save(JSONObject h, string path)\n        {\n            var s = Encode(h);\n            if (File.Exists(path))\n            {\n                var oldS = File.ReadAllText(path, Encoding.GetEncoding(0));\n                if (s.Equals(oldS))\n                    return false;\n            }\n\n            var bytes = Encoding.UTF8.GetBytes(s);\n            File.WriteAllBytes(path, bytes);\n            return true;\n        }\n\n        [RequiredByNativeCode]\n        internal static JSONObject CreateJSONObject()\n        {\n            return new Dictionary<string, object>(1);\n        }\n\n        [RequiredByNativeCode]\n        internal static void AddJSONKeyValue(JSONObject ht, string key, object value)\n        {\n            ht.Add(key, value);\n        }\n\n        [RequiredByNativeCode]\n        internal static string[] GetKeys(JSONObject ht)\n        {\n            return ht.Keys.Cast<string>().ToArray();\n        }\n\n        [RequiredByNativeCode]\n        internal static object GetValue(JSONObject ht, string key)\n        {\n            return ht[key];\n        }\n\n        [RequiredByNativeCode]\n        internal static int GetArrayCount(object obj)\n        {\n            var list = obj as ICollection;\n            if (list != null)\n                return list.Count;\n\n            var array = obj as Array;\n            if (array != null)\n                return array.Length;\n\n            var count = 0;\n            var enumerable = obj as IEnumerable;\n            if (enumerable != null)\n            {\n                foreach (var e in enumerable)\n                    count++;\n            }\n            return count;\n        }\n\n        [RequiredByNativeCode]\n        internal static object GetArrayElement(object obj, int index)\n        {\n            var list = obj as IList;\n            if (list != null)\n                return list[index];\n\n            var enumerable = obj as IEnumerable;\n            if (enumerable == null)\n                return null;\n\n            return Enumerable.ElementAt(enumerable.Cast<object>(), index);\n        }\n\n        internal static bool TryGetValue(JSONObject data, string key, out object value)\n        {\n            value = null;\n            if (data == null || !data.Contains(key))\n                return false;\n\n            value = data[key];\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SaveAssetsProcessor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor\n{\n    [Obsolete(\"Use UnityEditor.AssetModificationProcessor\")]\n    public class SaveAssetsProcessor : UnityEditor.AssetModificationProcessor {}\n}\n"
  },
  {
    "path": "Editor/Mono/SavedGUIState.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngineInternal;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Mono/SavedGUIState.bindings.h\")]\n    internal struct SavedGUIState\n    {\n        private GUILayoutUtility.LayoutCacheState layoutCache;\n        private IntPtr guiState;\n        private Vector2 screenManagerSize;\n        private GUISkin skin;\n        private int instanceID;\n        private GenericStack scrollViewStates;\n\n        private static extern void Internal_SetupSavedGUIState(out IntPtr state, out Vector2 screenManagerSize);\n\n        private static extern void Internal_ApplySavedGUIState(IntPtr state, Vector2 screenManagerSize);\n\n        internal static extern int Internal_GetGUIDepth();\n\n        internal static SavedGUIState Create()\n        {\n            SavedGUIState state = new SavedGUIState();\n            if (Internal_GetGUIDepth() > 0)\n            {\n                state.skin = GUI.skin;\n                state.layoutCache = GUILayoutUtility.current.State;\n                state.instanceID = GUIUtility.s_OriginalID;\n                if (GUI.scrollViewStates.Count != 0)\n                {\n                    state.scrollViewStates = GUI.scrollViewStates;\n                    GUI.scrollViewStates = new GenericStack();\n                }\n\n                Internal_SetupSavedGUIState(out state.guiState, out state.screenManagerSize);\n            }\n            return state;\n        }\n\n        internal void ApplyAndForget()\n        {\n            if (layoutCache.layoutGroups != null)\n            {\n                GUILayoutUtility.current.CopyState(layoutCache);\n                GUI.skin = skin;\n                GUIUtility.s_OriginalID = instanceID;\n\n                if (scrollViewStates != null)\n                {\n                    GUI.scrollViewStates = scrollViewStates;\n                }\n\n                Internal_ApplySavedGUIState(guiState, screenManagerSize);\n                GUIClip.Reapply();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneHierarchy.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing UnityEngine.Scripting;\nusing UnityEditor.SceneManagement;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.ShortcutManagement;\nusing UnityEditorInternal;\nusing UnityEngine.Assertions;\nusing System.Text;\nusing UnityEngine.UIElements;\nusing TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewDataSource = UnityEditor.IMGUI.Controls.TreeViewDataSource<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    [Serializable]\n    internal class SceneHierarchy\n    {\n        string kContextMenuItemCut { get { return \"Cut \" + Menu.GetHotkey(\"Edit/Cut\"); } }\n        string kContextMenuItemCopy { get { return \"Copy \" + Menu.GetHotkey(\"Edit/Copy\"); } }\n        string kContextMenuItemPaste { get { return \"Paste \" + Menu.GetHotkey(\"Edit/Paste\"); } }\n        string kContextMenuItemDuplicate { get { return \"Duplicate \" + Menu.GetHotkey(\"Edit/Duplicate\"); } }\n        string kContextMenuItemDelete { get { return \"Delete \" + Menu.GetHotkey(\"Edit/Delete\"); } }\n        string kContextMenuItemPasteAsChildKeepLocalTransform { get { return \"Paste Special/Paste as Child (Keep Local Transform) \" + Menu.GetHotkey(\"Edit/Paste Special/Paste as Child (Keep Local Transform)\"); } }\n\n        static class Styles\n        {\n            const string kCustomSorting = \"CustomSorting\";\n            const string kWarningSymbol = \"console.warnicon.sml\";\n            const string kWarningMessage = \"The current sorting method is taking a lot of time. Consider using 'Transform Sort' in playmode for better performance.\";\n\n            public static GUIContent defaultSortingContent = EditorGUIUtility.TrIconContent(kCustomSorting);\n            public static GUIContent createContent = EditorGUIUtility.IconContent(\"CreateAddNew\");\n            public static GUIContent fetchWarning = new GUIContent(\"\", EditorGUIUtility.FindTexture(kWarningSymbol), kWarningMessage);\n\n            public static GUIStyle lockButton = \"IN LockButton\";\n\n            public static GUIContent renamingEnabledContent = EditorGUIUtility.TrTextContent(\"Rename New Objects\");\n            public static GUIContent setOriginLabel = new GUIContent(\"Set as Default Parent\");\n            public static GUIContent clearOriginLabel = new GUIContent(\"Clear Default Parent\");\n        }\n\n        EditorWindow m_EditorWindow;\n\n        int m_FrameRequestID;\n        bool m_FrameRequestPing;\n        Scene[] m_CustomScenes;\n\n        public Scene[] customScenes\n        {\n            get { return m_CustomScenes; }\n            set { m_CustomScenes = value; Init(); }\n        }\n\n        Transform m_CustomParentForNewGameObjects;\n\n        public Transform customParentForNewGameObjects\n        {\n            set\n            {\n                m_CustomParentForNewGameObjects = value;\n                if (m_TreeView != null && m_TreeView.dragging != null)\n                    ((GameObjectsTreeViewDragging)m_TreeView.dragging).parentForDraggedObjectsOutsideItems = m_CustomParentForNewGameObjects;\n            }\n        }\n\n        GameObjectsTreeViewDragging.CustomDraggingDelegate m_CustomDragHandler;\n        public void SetCustomDragHandler(GameObjectsTreeViewDragging.CustomDraggingDelegate handler)\n        {\n            m_CustomDragHandler = handler;\n            if (m_TreeView != null && m_TreeView.dragging != null)\n                ((GameObjectsTreeViewDragging)m_TreeView.dragging).SetCustomDragHandler(handler);\n        }\n\n        public bool hasCustomScenes\n        {\n            get { return customScenes != null && customScenes.Length > 0; }\n        }\n\n        public Rect position { get; set; }\n        const int kInvalidSceneHandle = 0;\n        bool m_RectSelectInProgress;\n\n        TreeViewController m_TreeView;\n        [SerializeField]\n        TreeViewState m_TreeViewState;\n\n        [SerializeField]\n        List<string> m_ExpandedScenes = new List<string>(); // saved in layout so we can expand on next Unity session (expanded state is saved per window)\n        int m_TreeViewKeyboardControlID;\n\n        [SerializeField]\n        private int m_CurrenRootInstanceID = 0;\n        [SerializeField]\n        EditorGUIUtility.EditorLockTracker m_LockTracker = new EditorGUIUtility.EditorLockTracker();\n\n        internal bool isLocked\n        {\n            get { return m_LockTracker.isLocked; }\n            set { m_LockTracker.isLocked = value; }\n        }\n\n        [NonSerialized]\n        List<string> m_ParentNamesForSelectedSearchResult = new List<string>();\n\n        string m_SearchFilter;\n        SearchableEditorWindow.SearchModeHierarchyWindow m_SearchMode = SearchableEditorWindow.SearchModeHierarchyWindow.All;\n\n        [NonSerialized]\n        private int m_LastFramedID = -1;\n        [NonSerialized]\n        bool m_TreeViewReloadNeeded;\n        [NonSerialized]\n        bool m_SelectionSyncNeeded;\n        [NonSerialized]\n        bool m_FrameOnSelectionSync;\n        [NonSerialized]\n        bool m_DidSelectSearchResult;\n        [NonSerialized]\n        double m_LastUserInteractionTime;\n        [NonSerialized]\n        bool m_IgnoreNextHierarchyChangedEvent;\n\n        public static bool s_Debug\n        {\n            get { return SessionState.GetBool(\"HierarchyWindowDebug\", false); }\n            set { SessionState.SetBool(\"HierarchyWindowDebug\", value); }\n        }\n\n        public static bool s_DebugPrefabStage\n        {\n            get { return SessionState.GetBool(\"PrefabStageDebug\", false); }\n            set { SessionState.SetBool(\"PrefabStageDebug\", value); }\n        }\n\n        internal static bool s_DebugPersistingExpandedState\n        {\n            get { return SessionState.GetBool(\"ExpandedStateDebug\", false); }\n            set { SessionState.SetBool(\"ExpandedStateDebug\", value); }\n        }\n\n        internal static bool s_DebugPreviewScenes\n        {\n            get { return EditorSceneManager.GetPreviewScenesVisibleInHierarchy(); }\n            set\n            {\n                EditorSceneManager.SetPreviewScenesVisibleInHierarchy(value);\n                SceneHierarchyWindow.ReloadAllHierarchyWindows();\n            }\n        }\n\n        internal bool hasSearchFilter\n        {\n            get { return !string.IsNullOrEmpty(m_SearchFilter); }\n        }\n\n        [SerializeField]\n        string m_CurrentSortingName = \"\"; // serialize as string\n\n        Dictionary<string, HierarchySorting> m_SortingObjects = null;\n        bool m_AllowAlphaNumericalSort;\n\n        string currentSortingName\n        {\n            get { return m_CurrentSortingName; }\n            set\n            {\n                m_CurrentSortingName = value;\n\n                // Ensure backwards compability (if current sort is not found, default to transform sort)\n                if (!m_SortingObjects.ContainsKey(m_CurrentSortingName))\n                {\n                    m_CurrentSortingName = GetNameForType(typeof(TransformSorting));\n                }\n\n                // Sync treeview with new sort state\n                dataSource.sortingState = m_SortingObjects[m_CurrentSortingName];\n            }\n        }\n\n        public bool hasSortMethods { get { return m_SortingObjects != null && m_SortingObjects.Count > 1; } }\n\n        public int treeViewKeyboardControlID { get { return m_TreeViewKeyboardControlID; } }\n\n        bool treeViewReloadNeeded\n        {\n            get { return m_TreeViewReloadNeeded; }\n            set\n            {\n                m_TreeViewReloadNeeded = value;\n                if (value)\n                {\n                    Repaint();\n                    if (s_Debug)\n                        Debug.Log(\"Reload treeview on next event\");\n                }\n            }\n        }\n\n        bool selectionSyncNeeded\n        {\n            get { return m_SelectionSyncNeeded; }\n            set\n            {\n                m_SelectionSyncNeeded = value;\n                if (value)\n                {\n                    Repaint();\n                    if (s_Debug)\n                        Debug.Log(\"Selection sync and frameing on next event\");\n                }\n            }\n        }\n\n        Rect treeViewRect\n        {\n            get { return position; }\n        }\n\n        internal TreeViewState treeViewState\n        {\n            get { return m_TreeViewState; }\n        }\n\n        internal TreeViewController treeView\n        {\n            get\n            {\n                if (m_TreeView == null)\n                    Init();\n                return m_TreeView;\n            }\n        }\n\n        public List<GameObject> GetExpandedGameObjects()\n        {\n            dataSource.EnsureFullyInitialized();\n\n            var gameObjects = new List<GameObject>();\n            for (int i = 0; i < m_TreeView.data.rowCount; ++i)\n            {\n                var item = (GameObjectTreeViewItem)m_TreeView.data.GetItem(i);\n                if (item.hasChildren && m_TreeView.data.IsExpanded(item))\n                {\n                    if (item.objectPPTR is GameObject)\n                        gameObjects.Add((GameObject)item.objectPPTR);\n                }\n            }\n            return gameObjects;\n        }\n\n        void Repaint()\n        {\n            // m_EditorWindow is null before Awake is called on startup (we have events like OnBecameVisible and OnFocus which is called before Awake)\n            if (m_EditorWindow != null)\n                m_EditorWindow.Repaint();\n        }\n\n        void Init()\n        {\n            if (m_TreeViewState == null)\n                m_TreeViewState = new TreeViewState();\n            m_TreeViewState.searchString = \"\"; // search string is controlled by m_SearchFilter, clearing old layouts, case 1346524\n\n            if (m_SortingObjects == null)\n                SetUpSortMethodLists();\n\n            m_TreeView = new TreeViewController(m_EditorWindow, m_TreeViewState);\n            m_TreeView.itemDoubleClickedCallback += TreeViewItemDoubleClicked;\n            m_TreeView.selectionChangedCallback += TreeViewSelectionChanged;\n            m_TreeView.onGUIRowCallback += OnRowGUICallback;\n            m_TreeView.dragEndedCallback += OnDragEndedCallback;\n            m_TreeView.contextClickItemCallback += ItemContextClick;\n            m_TreeView.contextClickOutsideItemsCallback += ContextClickOutsideItems;\n            m_TreeView.deselectOnUnhandledMouseDown = true;\n\n            // Both when showing all gos and a sub tree we hide the root\n            bool showRootItem = false;\n            bool rootItemIsCollapsable = false;\n\n            var dataSource = new GameObjectTreeViewDataSource(m_TreeView, m_CurrenRootInstanceID, showRootItem, rootItemIsCollapsable);\n            var dragging = new GameObjectsTreeViewDragging(m_TreeView);\n            var gui = new GameObjectTreeViewGUI(m_TreeView, false);\n\n            dataSource.searchMode = m_SearchMode;\n            dataSource.searchString = m_SearchFilter;\n            dataSource.scenes = m_CustomScenes;\n            dataSource.sortingState = m_SortingObjects[m_CurrentSortingName];\n            dragging.parentForDraggedObjectsOutsideItems = m_CustomParentForNewGameObjects;\n            dragging.SetCustomDragHandler(m_CustomDragHandler);\n            gui.renameEnded += ItemRenameEnded;\n\n            m_TreeView.Init(treeViewRect, dataSource, gui, dragging);\n            m_TreeView.ReloadData();\n        }\n\n        void ItemRenameEnded(bool userAcceptedRename, int itemID, string name, string originalName)\n        {\n            if (userAcceptedRename && name != originalName)\n            {\n                // Handle reloading immediately when an internal change happens instead of waiting for\n                // the delayed OnHierarchyChange event (fixes case 981190)\n                ObjectNames.SetNameSmartWithInstanceID(itemID, name);\n                m_IgnoreNextHierarchyChangedEvent = true;\n                ReloadData();\n\n                EditorApplication.RepaintAnimationWindow();\n            }\n        }\n\n        bool AreCustomScenesValid(Scene[] customScenes)\n        {\n            if (customScenes == null)\n                return true;\n\n            foreach (var scene in customScenes)\n                if (!scene.IsValid())\n                    return false;\n\n            return true;\n        }\n\n        void SetUpSortMethodLists()\n        {\n            m_SortingObjects = new Dictionary<string, HierarchySorting>();\n\n            var transformSorting = new TransformSorting();\n            m_SortingObjects.Add(GetNameForType(transformSorting.GetType()), transformSorting);\n\n            // The user have to activate AlphabeticalSorting in the preferences (we ensure AlphabeticalSorting is added for integration tests)\n            if (m_AllowAlphaNumericalSort || !InternalEditorUtility.isHumanControllingUs)\n            {\n                var alphabeticalSorting = new AlphabeticalSorting();\n                m_SortingObjects.Add(GetNameForType(alphabeticalSorting.GetType()), alphabeticalSorting);\n            }\n\n            // Ensure to reconstruct state setup when setting sorting name\n            currentSortingName = m_CurrentSortingName;\n        }\n\n        string GetNameForType(Type type)\n        {\n            return type.Name;\n        }\n\n        void SortFunctionCallback(SceneHierarchySortingWindow.InputData data)\n        {\n            SetSortFunction(data.m_TypeName);\n        }\n\n        public void SetSortFunction(Type sortType)\n        {\n            SetSortFunction(GetNameForType(sortType));\n        }\n\n        void SetSortFunction(string sortTypeName)\n        {\n            if (!m_SortingObjects.ContainsKey(sortTypeName))\n            {\n                Debug.LogError(\"Invalid search type name: \" + sortTypeName);\n                return;\n            }\n\n            currentSortingName = sortTypeName;\n            ReloadData();\n        }\n\n        internal void SetupForTesting()\n        {\n            m_AllowAlphaNumericalSort = true;\n            SetUpSortMethodLists();\n        }\n\n        public void DirtySortingMethods()\n        {\n            m_AllowAlphaNumericalSort = EditorPrefs.GetBool(\"AllowAlphaNumericHierarchy\", false);\n            SetUpSortMethodLists();\n            //m_SceneHierarchy.SetSelection((treeView.GetSelection(), true);\n            ReloadData();\n        }\n\n        public void SetFocusAndEnsureSelectedItem()\n        {\n            GUIUtility.keyboardControl = m_TreeViewKeyboardControlID;\n            EditorGUIUtility.editingTextField = false;\n\n            if (m_TreeView.data.rowCount > 0)\n            {\n                if (m_TreeView.IsLastClickedPartOfRows())\n                {\n                    m_TreeView.Frame(m_TreeViewState.lastClickedID, true, false);\n                }\n                else\n                {\n                    m_TreeView.SetSelection(new[] { m_TreeView.data.GetRows()[0].id }, true);\n                    m_TreeView.NotifyListenersThatSelectionChanged();\n                }\n            }\n        }\n\n        public void SetCurrentRootInstanceID(int instanceID)\n        {\n            m_CurrenRootInstanceID = instanceID;\n            Init();\n            EditorGUIUtility.ExitGUI(); // exit gui since this can be called while iterating items\n        }\n\n        public int[] GetExpandedIDs()\n        {\n            return m_TreeViewState.expandedIDs.ToArray();\n        }\n\n        // This method is being used by the EditorTests/Searching tests\n        public string[] GetCurrentVisibleObjects()\n        {\n            var rows = m_TreeView.data.GetRows();\n            var result = new string[rows.Count];\n\n            for (int i = 0; i < rows.Count; ++i)\n                result[i] = rows[i].displayName;\n            return result;\n        }\n\n        internal void SelectPrevious()\n        {\n            m_TreeView.OffsetSelection(-1);\n        }\n\n        internal void SelectNext()\n        {\n            m_TreeView.OffsetSelection(1);\n        }\n\n        IEnumerable<string> GetExpandedSceneNames()\n        {\n            List<string> expandedScenes = new List<string>();\n            for (int i = 0; i < SceneManager.sceneCount; ++i)\n            {\n                Scene scene = SceneManager.GetSceneAt(i);\n                if (treeView.data.IsExpanded(scene.handle))\n                {\n                    expandedScenes.Add(scene.name);\n                }\n            }\n            return expandedScenes;\n        }\n\n        void SetScenesExpanded(List<string> sceneNames)\n        {\n            List<int> sceneHandles = new List<int>();\n            foreach (string sceneName in sceneNames)\n            {\n                Scene scene = SceneManager.GetSceneByName(sceneName);\n                if (scene.IsValid())\n                {\n                    sceneHandles.Add(scene.handle);\n                }\n            }\n            if (sceneHandles.Count > 0)\n                treeView.data.SetExpandedIDs(sceneHandles.ToArray());\n        }\n\n        void PlayModeStateChanged(PlayModeStateChange state)\n        {\n            treeViewReloadNeeded = true;\n        }\n\n        void OnSceneCreated(Scene scene, NewSceneSetup setup, NewSceneMode mode)\n        {\n            ClearSearchSessionIfAny();\n            ExpandTreeViewItem(scene.handle, true);\n        }\n\n        void OnSceneOpened(Scene scene, OpenSceneMode mode)\n        {\n            ClearSearchSessionIfAny();\n            ExpandTreeViewItem(scene.handle, true);\n        }\n\n        void ClearSearchSessionIfAny()\n        {\n            var dataSource = treeView.data as GameObjectTreeViewDataSource;\n            if (dataSource != null && !string.IsNullOrEmpty(dataSource.searchString))\n            {\n                var oldSearch = dataSource.searchString;\n                dataSource.searchString = \"\";\n                dataSource.searchString = oldSearch;\n            }\n        }\n\n        internal void ExpandTreeViewItem(int id, bool expand)\n        {\n            var dataSource = treeView.data as TreeViewDataSource;\n            if (dataSource != null)\n                dataSource.SetExpanded(id, expand);\n        }\n\n        public virtual void Awake(EditorWindow editorWindow)\n        {\n            m_EditorWindow = editorWindow;\n\n            if (m_TreeViewState != null)\n            {\n                // Clear states that should not survive between restarts of Unity\n                m_TreeViewState.OnAwake();\n            }\n        }\n\n        public virtual void OnBecameVisible()\n        {\n            // We need to ensure Hierarchy window is reloaded when becoming visible because\n            // while it is hidden it does not receive OnHierarchyChanged callbacks (case 611409)\n            // During assembly reload editor windows are recreated, at that point scene count is 0 so ignore that event\n            if (SceneManager.sceneCount > 0)\n            {\n                treeViewReloadNeeded = true;\n            }\n        }\n\n        public virtual void OnLostFocus()\n        {\n            // On lost focus can be called before OnEnable have been called\n            if (m_TreeView != null)\n            {\n                // Added because this window uses RenameOverlay\n                m_TreeView.EndNameEditing(true);\n            }\n        }\n\n        public virtual void OnEnable()\n        {\n            Assert.IsTrue(m_EditorWindow != null, \"Editor Window is null. It should survive assembly reload\");\n\n            EditorApplication.projectChanged += ReloadData; // Required to know if a prefab gets deleted. Better way of doing this?\n            EditorApplication.editorApplicationQuit += OnQuit;\n            EditorApplication.projectWasLoaded += OnProjectWasLoaded;\n            EditorApplication.refreshHierarchy += Repaint;\n            EditorApplication.dirtyHierarchySorting += DirtySortingMethods;\n            EditorSceneManager.newSceneCreated += OnSceneCreated;\n            EditorSceneManager.sceneOpened += OnSceneOpened;\n            RectSelection.rectSelectionStarting += SceneViewRectSelectionStarting;\n            RectSelection.rectSelectionFinished += SceneViewRectSelectionFinished;\n            EditorApplication.playModeStateChanged += PlayModeStateChanged;\n\n            m_AllowAlphaNumericalSort = EditorPrefs.GetBool(\"AllowAlphaNumericHierarchy\", false) || !InternalEditorUtility.isHumanControllingUs; // Always allow alphasorting when running automated tests so we can test alpha sorting\n            SetUpSortMethodLists();\n\n            if (!AreCustomScenesValid(m_CustomScenes))\n                m_CustomScenes = null;\n\n            if (m_TreeViewKeyboardControlID == 0)\n                m_TreeViewKeyboardControlID = EditorGUIUtility.GetPermanentControlID();\n        }\n\n        public virtual void OnDisable()\n        {\n            EditorApplication.projectChanged -= ReloadData;\n            EditorApplication.editorApplicationQuit -= OnQuit;\n            EditorApplication.projectWasLoaded -= OnProjectWasLoaded;\n            EditorApplication.refreshHierarchy -= Repaint;\n            EditorApplication.dirtyHierarchySorting -= DirtySortingMethods;\n            EditorSceneManager.newSceneCreated -= OnSceneCreated;\n            EditorSceneManager.sceneOpened -= OnSceneOpened;\n            RectSelection.rectSelectionStarting -= SceneViewRectSelectionStarting;\n            RectSelection.rectSelectionFinished -= SceneViewRectSelectionFinished;\n            EditorApplication.playModeStateChanged -= PlayModeStateChanged;\n        }\n\n        internal void OnProjectWasLoaded()\n        {\n            // Game objects will have new instanceIDs in a new Unity session, so clear\n            // the expanded state on project start up (we still need this even though we also clear in OnQuit to be sure if loading a old layout)\n            m_TreeViewState.expandedIDs.Clear();\n\n            // If only one scene ensure it is expanded (new project)\n            if (SceneManager.sceneCount == 1)\n            {\n                treeView.data.SetExpanded(SceneManager.GetSceneAt(0).handle, true);\n            }\n\n            // Ensure scenes are expanded from last session\n            SetScenesExpanded(m_ExpandedScenes);\n        }\n\n        public virtual void OnQuit()\n        {\n            m_ExpandedScenes = GetExpandedSceneNames().ToList();\n\n            // Game objects will have new instanceIDs in the next Unity session, so clear all state before serializing to layout to prevent saving redundant data\n            m_TreeViewState = new TreeViewState();\n        }\n\n        public virtual void OnDestroy()\n        {\n        }\n\n        void SceneViewRectSelectionStarting()\n        {\n            m_RectSelectInProgress = true;\n        }\n\n        void SceneViewRectSelectionFinished()\n        {\n            m_RectSelectInProgress = false;\n            selectionSyncNeeded = true;\n            SyncIfNeeded();\n            Repaint();\n        }\n\n        void SyncIfNeeded()\n        {\n            if (treeViewReloadNeeded)\n            {\n                treeViewReloadNeeded = false;\n                ReloadData();\n            }\n\n            if (selectionSyncNeeded)\n            {\n                selectionSyncNeeded = false;\n\n                bool userJustInteracted = (EditorApplication.timeSinceStartup - m_LastUserInteractionTime) < 0.2;\n                bool frame = (!isLocked || m_FrameOnSelectionSync || userJustInteracted) && !m_RectSelectInProgress;\n                bool animatedFraming = userJustInteracted && frame;\n                m_FrameOnSelectionSync = false;\n\n                treeView.SetSelection(Selection.instanceIDs, frame, animatedFraming);\n            }\n        }\n\n        void DetectUserInteraction()\n        {\n            Event evt = Event.current;\n            if (evt.type != EventType.Layout && evt.type != EventType.Repaint)\n            {\n                m_LastUserInteractionTime = EditorApplication.timeSinceStartup;\n            }\n\n            if (evt.type == EventType.MouseDown && position.Contains(evt.mousePosition))\n            {\n                treeView.EndPing();\n            }\n        }\n\n        public void OnGUI(Rect rect)\n        {\n            position = rect;\n\n            OnEvent();\n            SyncIfNeeded();\n            DetectUserInteraction();\n\n            float searchPathHeight = DoSearchResultPathGUI();\n            DoTreeView(searchPathHeight);\n\n            DoSceneVisibilityBackgroundOverflow(searchPathHeight);\n\n            DoPingRequest();\n            ExecuteCommands();\n            HandleKeyboard();\n        }\n\n        // TODO: Make sure it checks its own scenes: Here we assume we alw\n        public static bool IsSceneHeaderInHierarchyWindow(Scene scene)\n        {\n            return scene.IsValid();\n        }\n\n        void TreeViewItemDoubleClicked(int instanceID)\n        {\n            bool setActiveScene = false;\n\n            Scene scene = EditorSceneManager.GetSceneByHandle(instanceID);\n            if (IsSceneHeaderInHierarchyWindow(scene))\n            {\n                setActiveScene = true;\n            }\n            else if (SubSceneGUI.IsUsingSubScenes())\n            {\n                var gameObject = EditorUtility.InstanceIDToObject(instanceID) as GameObject;\n                if (gameObject != null && SubSceneGUI.IsSubSceneHeader(gameObject))\n                {\n                    scene = SubSceneGUI.GetSubScene(gameObject);\n                    setActiveScene = true;\n                }\n            }\n\n            if (setActiveScene)\n            {\n                // scene header selected\n                if (scene.isLoaded && SceneManager.CanSetAsActiveScene(scene))\n                    SceneManager.SetActiveScene(scene);\n            }\n            else\n            {\n                SceneView.FrameLastActiveSceneView();\n                EditorGUIUtility.ExitGUI();\n            }\n        }\n\n        public void SetExpandedRecursive(int id, bool expand)\n        {\n            TreeViewItem item = treeView.data.FindItem(id);\n\n            // If the item is null reload the data as the scene might have changed.\n            if (item == null)\n            {\n                ReloadData();\n                item = treeView.data.FindItem(id);\n            }\n\n            if (item != null)\n                treeView.data.SetExpandedWithChildren(item, expand);\n        }\n\n        void OnRowGUICallback(int itemID, Rect rect)\n        {\n            GameObjectTreeViewGUI.UserCallbackRowGUI(itemID, rect);\n        }\n\n        void OnDragEndedCallback(int[] draggedInstanceIds, bool draggedItemsFromOwnTreeView)\n        {\n            // We only change selection if 'draggedItemsFromOwnTreeView' == true.\n            // This ensures that we do not override the selection that might have been set before\n            // calling this callback when dragging e.g a prefab to the hierarchy (case 628939)\n            if (draggedInstanceIds != null && draggedItemsFromOwnTreeView)\n            {\n                ReloadData();\n                treeView.SetSelection(draggedInstanceIds, true);\n                treeView.NotifyListenersThatSelectionChanged(); // behave as if selection was performed in treeview\n                GameObjectTreeViewGUI.RemoveInvalidActiveParentObjects();\n                Repaint();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        bool IsRenaming()\n        {\n            return m_TreeView != null && m_TreeView.state.renameOverlay.IsRenaming();\n        }\n\n        public void ReloadData()\n        {\n            int rowCountBeforeReloading = 0;\n            if (IsRenaming())\n                rowCountBeforeReloading = m_TreeView.data.rowCount;\n\n            if (m_TreeView == null)\n                Init();\n            else\n                m_TreeView.ReloadData();\n\n            if (IsRenaming())\n            {\n                // Ensure renaming is ended if the item being renamed is no longer part\n                // of the rows or if the row count changed (new objects deleted/added).\n                // If the renamed item is present then ensure it is visible to the user.\n                int id = m_TreeView.state.renameOverlay.userData;\n                bool endRenaming = m_TreeView.data.rowCount != rowCountBeforeReloading;\n                if (!endRenaming)\n                    endRenaming = m_TreeView.data.GetRows().FirstOrDefault(item => item.id == id) == null;\n                if (endRenaming)\n                    m_TreeView.EndNameEditing(false);\n                else\n                    m_TreeView.Frame(id, true, false);\n            }\n        }\n\n        GameObjectTreeViewDataSource dataSource { get { return (GameObjectTreeViewDataSource)treeView.data; } }\n        GameObjectsTreeViewDragging dragging { get { return (GameObjectsTreeViewDragging)treeView.dragging; } }\n\n        public void SetSearchFilter(string searchString, SearchableEditorWindow.SearchModeHierarchyWindow searchMode)\n        {\n            // Search didnt change do nothing.\n            if (m_SearchMode == searchMode && m_SearchFilter == searchString)\n                return;\n\n            m_SearchMode = searchMode;\n            m_SearchFilter = searchString;\n\n            // Reload tree with new search data\n            dataSource.searchMode = searchMode;\n            dataSource.searchString = searchString;\n            ReloadData();\n\n            // If the user clears the search we frame the last selection he made during the search\n            if (m_DidSelectSearchResult && string.IsNullOrEmpty(searchString))\n            {\n                m_DidSelectSearchResult = false;\n                FrameObjectPrivate(Selection.activeInstanceID, true, false, false);\n\n                // Ensure item has focus for visual feedback and instant key navigation\n                if (GUIUtility.keyboardControl == 0)\n                    GUIUtility.keyboardControl = m_TreeViewKeyboardControlID;\n            }\n        }\n\n        void TreeViewSelectionChanged(int[] ids)\n        {\n            //Last selected should be the active selected object to reflect the behavior of the scene view selection\n            int active = ids.Length > 0 ? ids[ids.Length - 1] : 0;\n            Selection.SetSelectionWithActiveInstanceID(ids, active);\n\n            if (!IsTreeViewSelectionInSyncWithBackend())\n            {\n                selectionSyncNeeded = true;\n            }\n\n            m_DidSelectSearchResult = !string.IsNullOrEmpty(m_SearchFilter);\n        }\n\n        bool IsTreeViewSelectionInSyncWithBackend()\n        {\n            if (m_TreeView != null)\n                return m_TreeView.state.selectedIDs.SequenceEqual(Selection.instanceIDs);\n            return false;\n        }\n\n        public void OnSelectionChange()\n        {\n            if (!IsTreeViewSelectionInSyncWithBackend())\n            {\n                selectionSyncNeeded = true;\n            }\n            else\n            {\n                if (s_Debug)\n                    Debug.Log(\"OnSelectionChange: Selection is already in sync so no framing will happen\");\n            }\n        }\n\n        public void OnHierarchyChange()\n        {\n            if (m_IgnoreNextHierarchyChangedEvent)\n            {\n                m_IgnoreNextHierarchyChangedEvent = false;\n                return;\n            }\n\n            treeViewReloadNeeded = true;\n        }\n\n        void OnEvent()\n        {\n            treeView.OnEvent();\n        }\n\n        // Tree view item handle their own scene visibility background.\n        // So the background doesn't stop if we don't have enough item to fill the entire tree view rect, we draw the background in the unused space.\n        private void DoSceneVisibilityBackgroundOverflow(float reservedFooterSpace)\n        {\n            float treeViewHeight = treeView.gui.GetTotalSize().y;\n            Rect rectWithNoRows = treeViewRect;\n\n            //If the tree view already covers the entire rect, we don't need to fill the overflow\n            if (rectWithNoRows.height <= treeViewHeight)\n                return;\n\n            rectWithNoRows.yMin += treeViewHeight;\n            rectWithNoRows.height -= reservedFooterSpace;\n\n            SceneVisibilityHierarchyGUI.DrawBackground(rectWithNoRows);\n        }\n\n        void DoTreeView(float searchPathHeight)\n        {\n            // subtract the search path height from the available height.\n            Rect rect = treeViewRect;\n            rect.height -= searchPathHeight;\n            treeView.OnGUI(rect, m_TreeViewKeyboardControlID);\n        }\n\n        /*\n         * NOTE: AddCreateGameObjectItemsToMenu() cooks existing menu, so that make sure menu entries are added to\n         *               localization entry.\n         * @Localization(\"Create Empty\", \"MenuItem\")\n         * @Localization(\"Create Empty Child\", \"MenuItem\")\n         */\n        void AddCreateGameObjectItemsToMenu(GenericMenu menu, UnityEngine.Object[] context, bool includeCreateEmptyChild, bool useCreateEmptyParentMenuItem, bool includeGameObjectInPath, int targetSceneHandle, MenuUtils.ContextMenuOrigin origin)\n        {\n            ScriptingMenuItem[] menus = Menu.GetMenuItems(\"GameObject\", true, false);\n            int previousMenuItemPosition = -1;\n\n            foreach (var menuItem in menus)\n            {\n                string path = menuItem.path;\n\n                string hotkey = Menu.GetHotkey(menuItem.path);\n\n                UnityEngine.Object[] tempContext = context;\n                if (!includeCreateEmptyChild && path.ToLower() == \"GameObject/Create Empty Child\".ToLower())\n                    continue;\n\n                if (!useCreateEmptyParentMenuItem && path.ToLower() == \"GameObject/Create Empty Parent\".ToLower())\n                {\n                    if (GOCreationCommands.ValidateCreateEmptyParent())\n                        menu.AddItem(EditorGUIUtility.TrTextContent(\"Create Empty Parent \" + hotkey), false, GOCreationCommands.CreateEmptyParent);\n                    continue;\n                }\n\n                // The first item after the GameObject creation menu items\n                if (path.ToLower() == GameObjectUtility.GetFirstItemPathAfterGameObjectCreationMenuItems().ToLower())\n                    continue;\n\n                string menupath = path;\n\n                // cut away \"GameObject/\"\n                if (!includeGameObjectInPath)\n                    menupath = path.Substring(11);\n\n                if (!string.IsNullOrEmpty(hotkey))\n                    menupath += \" \" + hotkey;\n\n                MenuUtils.ExtractOnlyEnabledMenuItem(menuItem,\n                    menu,\n                    menupath,\n                    tempContext,\n                    targetSceneHandle,\n                    BeforeCreateGameObjectMenuItemWasExecuted,\n                    AfterCreateGameObjectMenuItemWasExecuted,\n                    origin,\n                    previousMenuItemPosition);\n\n                previousMenuItemPosition = menuItem.priority;\n            }\n\n            MenuUtils.RemoveInvalidMenuItems(menu);\n        }\n\n        void BeforeCreateGameObjectMenuItemWasExecuted(string menuPath, UnityEngine.Object[] contextObjects, MenuUtils.ContextMenuOrigin origin, int userData)\n        {\n            int sceneHandle = userData;\n            if (origin == MenuUtils.ContextMenuOrigin.Scene || origin == MenuUtils.ContextMenuOrigin.Subscene)\n                GOCreationCommands.forcePlaceObjectsAtWorldOrigin = true;\n            EditorSceneManager.SetTargetSceneForNewGameObjects(sceneHandle);\n        }\n\n        void AfterCreateGameObjectMenuItemWasExecuted(string menuPath, UnityEngine.Object[] contextObjects, MenuUtils.ContextMenuOrigin origin, int userData)\n        {\n            EditorSceneManager.SetTargetSceneForNewGameObjects(kInvalidSceneHandle);\n            GOCreationCommands.forcePlaceObjectsAtWorldOrigin = false;\n            // Ensure framing when creating game objects even if we are locked\n            if (isLocked)\n                m_FrameOnSelectionSync = true;\n        }\n\n        public void GameObjectCreateDropdownButton()\n        {\n            Rect rect = GUILayoutUtility.GetRect(Styles.createContent, EditorStyles.toolbarCreateAddNewDropDown, null);\n            bool mouseOver = rect.Contains(Event.current.mousePosition);\n            if (Event.current.type == EventType.Repaint)\n                EditorStyles.toolbarCreateAddNewDropDown.Draw(rect, Styles.createContent, mouseOver, false, false, false);\n\n            if (Event.current.type == EventType.MouseDown && mouseOver)\n            {\n                GUIUtility.hotControl = 0;\n\n                GenericMenu menu = new GenericMenu();\n                var targetSceneHandle = m_CustomParentForNewGameObjects != null ? m_CustomParentForNewGameObjects.gameObject.scene.handle : kInvalidSceneHandle;\n                // The context should be null, just like it is in the main menu. Case 1185434.\n                AddCreateGameObjectItemsToMenu(menu, null, true, true, false, targetSceneHandle, MenuUtils.ContextMenuOrigin.Toolbar);\n\n                SceneHierarchyHooks.AddCustomItemsToCreateMenu(menu);\n\n                menu.DropDown(rect);\n\n                Event.current.Use();\n            }\n        }\n\n        public void SortMethodsDropDownButton()\n        {\n            if (hasSortMethods)\n            {\n                // Labels button\n                GUIContent content = m_SortingObjects[currentSortingName].content;\n                if (content == null)\n                {\n                    content = Styles.defaultSortingContent;\n                    content.tooltip = currentSortingName;\n                }\n\n                Rect r = GUILayoutUtility.GetRect(content, EditorStyles.toolbarButtonRight);\n                if (EditorGUI.DropdownButton(r, content, FocusType.Passive, EditorStyles.toolbarButtonRight))\n                {\n                    // Build list items\n                    var sortFunctionItems = new List<SceneHierarchySortingWindow.InputData>();\n                    foreach (var entry in m_SortingObjects)\n                    {\n                        var data = new SceneHierarchySortingWindow.InputData();\n                        data.m_TypeName = entry.Key;\n                        data.m_Name = ObjectNames.NicifyVariableName(entry.Key); //entry.Key == class name;\n                        data.m_Selected = entry.Key == m_CurrentSortingName;\n                        sortFunctionItems.Add(data);\n                    }\n\n                    // Show popup\n                    if (SceneHierarchySortingWindow.ShowAtPosition(new Vector2(r.x, r.y + r.height), sortFunctionItems, SortFunctionCallback))\n                    {\n                        GUIUtility.ExitGUI();\n                    }\n                }\n            }\n        }\n\n        bool GetIsNotEditable()\n        {\n            GameObject[] selected = Selection.gameObjects;\n            for (int i = 0; i < selected.Length; i++)\n            {\n                if ((selected[i].hideFlags & HideFlags.NotEditable) != 0)\n                    return true;\n            }\n            return false;\n        }\n\n        static bool IsChildOfSelectionOrSelected(Transform transform)\n        {\n            if (transform == null)\n                return false;\n\n            GameObject[] selected = Selection.gameObjects;\n            for (int i = 0; i < selected.Length; i++)\n            {\n                var current = transform;\n                while (current != null)\n                {\n                    if (selected[i] == current.gameObject)\n                        return true;\n                    current = current.parent;\n                }\n            }\n\n            return false;\n        }\n\n        void ExecuteCommands()\n        {\n            Event evt = Event.current;\n\n            if (evt.type != EventType.ExecuteCommand && evt.type != EventType.ValidateCommand)\n            {\n                return;\n            }\n\n            bool execute = evt.type == EventType.ExecuteCommand;\n            // If the custom parent for new objects is set we don't allow cut, copy or duplicate any ancestors of this object\n            // as it might be context objects (as in Prefab Mode in Context).\n            bool allowCutCopyAndDuplicate = m_CustomParentForNewGameObjects == null\n                                            || !IsChildOfSelectionOrSelected(m_CustomParentForNewGameObjects.parent);\n\n            if (evt.commandName == EventCommandNames.Delete || evt.commandName == EventCommandNames.SoftDelete)\n            {\n                if (execute && !IsChildOfSelectionOrSelected(m_CustomParentForNewGameObjects))\n                    DeleteGO();\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n            else if (evt.commandName == EventCommandNames.Duplicate)\n            {\n                if (execute && allowCutCopyAndDuplicate)\n                    DuplicateGO();\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n            else if (evt.commandName == EventCommandNames.Rename)\n            {\n                if (execute)\n                    RenameGO();\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n            else if (evt.commandName == EventCommandNames.Cut)\n            {\n                if (allowCutCopyAndDuplicate)\n                    ClipboardUtility.CutGO();\n                GUIUtility.ExitGUI();\n            }\n            else if (evt.commandName == EventCommandNames.Copy)\n            {\n                if (execute && allowCutCopyAndDuplicate)\n                    ClipboardUtility.CopyGO();\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n            else if (evt.commandName == EventCommandNames.Paste)\n            {\n                if (execute)\n                    PasteGO();\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n            else if (evt.commandName == EventCommandNames.SelectAll)\n            {\n                if (execute)\n                    SelectAll();\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n            else if (evt.commandName == EventCommandNames.DeselectAll)\n            {\n                if (execute)\n                    DeselectAll();\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n            else if (evt.commandName == EventCommandNames.InvertSelection)\n            {\n                if (execute)\n                    InvertSelection();\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n            else if (evt.commandName == EventCommandNames.SelectChildren)\n            {\n                if (execute)\n                    SelectChildren();\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n            else if (evt.commandName == EventCommandNames.SelectPrefabRoot)\n            {\n                if (execute)\n                    SelectPrefabRoot();\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n            else if (evt.commandName == EventCommandNames.UndoRedoPerformed)\n            {\n                ReloadData();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        void HandleKeyboard()\n        {\n            Event evt = Event.current;\n\n            if (evt.keyCode == KeyCode.Escape && CutBoard.CanGameObjectsBePasted())\n            {\n                ClipboardUtility.ResetCutboardAndRepaintHierarchyWindows();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        void CreateSubSceneGameObjectContextClick(GenericMenu menu, int contextClickedItemID)\n        {\n            // For Sub Scenes GameObjects, have menu items for cut, paste and delete.\n            // Not copy or duplicate, since multiple of the same Sub Scene is not supported anyway.\n\n            menu.AddItem(EditorGUIUtility.TrTextContent(kContextMenuItemCut), false, ClipboardUtility.CutGO);\n            if (CutBoard.CanGameObjectsBePasted() || Unsupported.CanPasteGameObjectsFromPasteboard())\n                menu.AddItem(EditorGUIUtility.TrTextContent(kContextMenuItemPaste), false, PasteGO);\n            else\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(kContextMenuItemPaste));\n\n            if (ClipboardUtility.CanPasteAsChild())\n            {\n                menu.AddItem(EditorGUIUtility.TrTextContent(kContextMenuItemPasteAsChildKeepLocalTransform), false, () => ClipboardUtility.PasteGOAsChild(false));\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Paste as Child (Keep World Transform)\"), false, () => ClipboardUtility.PasteGOAsChild(true));\n            }\n            else\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Paste Special\"));\n\n            menu.AddSeparator(\"\");\n\n            if (IsChildOfSelectionOrSelected(m_CustomParentForNewGameObjects))\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Delete GameObject\"));\n            else\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Delete GameObject\"), false, DeleteGO);\n        }\n\n        void PopulateGenericMenuWithPrefabMenuItems(GenericMenu menu, int contextClickedItemID)\n        {\n            GameObject go = null;\n            string assetPath = null;\n            GameObject prefabAsset = null;\n            if (m_TreeViewState.selectedIDs.Count == 1)\n            {\n                GameObjectTreeViewItem item = treeView.FindItem(m_TreeViewState.selectedIDs[0]) as GameObjectTreeViewItem;\n                if (item != null && (item.objectPPTR as GameObject) != null)\n                {\n                    go = (GameObject)(item.objectPPTR);\n                    assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(go);\n                    prefabAsset = (GameObject)AssetDatabase.LoadMainAssetAtPath(assetPath);\n                }\n            }\n\n            var contextClickedGameObject = contextClickedItemID == 0 ? null : EditorUtility.InstanceIDToObject(contextClickedItemID) as GameObject;\n            var isSelectPrefabRootAvailable = IsSelectPrefabRootAvailable();\n\n            if (contextClickedGameObject != null || !string.IsNullOrEmpty(assetPath))\n                menu.AddSeparator(\"\");\n\n            if (!string.IsNullOrEmpty(assetPath))\n            {\n                if (PrefabUtility.IsPartOfModelPrefab(prefabAsset))\n                {\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Prefab/Open Model\"), false, () =>\n                    {\n                        AssetDatabase.OpenAsset(prefabAsset);\n                    });\n                }\n                else\n                {\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Prefab/Open Asset in Context\"), false, () =>\n                    {\n                        PrefabStageUtility.OpenPrefab(assetPath, go, PrefabStage.Mode.InContext, StageNavigationManager.Analytics.ChangeType.EnterViaInstanceHierarchyContextMenu);\n                    });\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Prefab/Open Asset in Isolation\"), false, () =>\n                    {\n                        PrefabStageUtility.OpenPrefab(assetPath, go, PrefabStage.Mode.InIsolation, StageNavigationManager.Analytics.ChangeType.EnterViaInstanceHierarchyContextMenu);\n                    });\n                }\n            }\n\n            if (!string.IsNullOrEmpty(assetPath))\n            {\n                menu.AddSeparator(\"Prefab/\");\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Prefab/Select Asset\"), false, () =>\n                {\n                    Selection.activeObject = prefabAsset;\n                    EditorGUIUtility.PingObject(prefabAsset.GetInstanceID());\n                });\n            }\n\n            if (isSelectPrefabRootAvailable)\n            {\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Prefab/Select Root\"), false, SelectPrefabRoot);\n            }\n\n            GameObject sourceRoot = GetSourceRootWhereGameObjectIsAddedAsOverride(go);\n            if (sourceRoot != null)\n            {\n                var s = PrefabUtility.GetOriginalSourceRootWhereGameObjectIsAdded(go);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Prefab/Go to Added GameObject in '\" + sourceRoot.name + \"'\"), false, () =>\n                {\n                    PrefabStageUtility.OpenPrefab(AssetDatabase.GetAssetPath(sourceRoot), PrefabUtility.GetNearestPrefabInstanceRoot(go), PrefabStage.Mode.InIsolation);\n                });\n            }\n\n            GameObject[] selectedGOs = Selection.gameObjects;\n\n            if (selectedGOs.Any() && PrefabUtility.IsAllAddedGameObjectOverrides(selectedGOs))\n            {\n                go = selectedGOs[0];\n                // Handle added GameObject or prefab.\n                Transform parentTransform = go.transform.parent;\n                PrefabUtility.HandleApplyRevertMenuItems(\n                    (selectedGOs.Length > 1) ? \"Added GameObjects\" : \"Added GameObject\",\n                    parentTransform.gameObject,\n                    (menuItemContent, sourceGo, _) =>\n                    {\n                        GameObject rootGo = PrefabUtility.GetRootGameObject(sourceGo);\n                        if (!PrefabUtility.IsPartOfPrefabThatCanBeAppliedTo(rootGo) || EditorUtility.IsPersistent(parentTransform) || !PrefabUtility.HasSameParent(selectedGOs))\n                            menu.AddDisabledItem(menuItemContent);\n                        else\n                        {\n                            string assetPath = AssetDatabase.GetAssetPath(sourceGo);\n                            TargetChoiceHandler.ObjectInstanceAndSourcePathInfo[] childInfos = new TargetChoiceHandler.ObjectInstanceAndSourcePathInfo[selectedGOs.Length];\n                            for (int i = 0; i < selectedGOs.Length; i++)\n                            {\n                                GameObject go = selectedGOs[i];\n                                TargetChoiceHandler.ObjectInstanceAndSourcePathInfo info = new TargetChoiceHandler.ObjectInstanceAndSourcePathInfo();\n                                info.instanceObject = go;\n                                info.assetPath = assetPath;\n                                childInfos[i] = info;\n                            }\n\n                            menu.AddItem(menuItemContent, false, TargetChoiceHandler.ApplyPrefabAddedGameObjects, childInfos);\n                        }\n                    },\n                    (menuItemContent) =>\n                    {\n                        menu.AddItem(menuItemContent, false, TargetChoiceHandler.RevertPrefabAddedGameObjects, selectedGOs);\n                    }\n                );\n            }\n\n            if (contextClickedGameObject != null)\n            {\n                menu.AddSeparator(\"Prefab/\");\n                List<GameObject> listOfInstanceRoots;\n                List<GameObject> listOfPlainGameObjects;\n                PrefabReplaceUtility.FindGameObjectsToReplace(contextClickedGameObject, out listOfPlainGameObjects, out listOfInstanceRoots);\n\n                var multiselection = listOfInstanceRoots.Count > 1 || listOfPlainGameObjects.Count > 1;\n\n                PrefabReplaceUtility.AddReplaceMenuItemsToMenuBasedOnCurrentSelection(menu, \"Prefab/\", contextClickedGameObject, listOfInstanceRoots, listOfPlainGameObjects, null);\n            }\n\n            if (AnyOutermostPrefabRoots())\n            {\n                menu.AddSeparator(\"Prefab/\");\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Prefab/Unpack\"), false, UnpackPrefab);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Prefab/Unpack Completely\"), false, UnpackPrefabCompletely);\n                menu.AddSeparator(\"Prefab/\");\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Prefab/Remove Unused Overrides...\"), false, RemoveSelectedPrefabInstanceUnusedOverrides);\n            }\n        }\n\n        void CreateGameObjectContextClick(GenericMenu menu, int contextClickedItemID)\n        {\n            bool itemIsSelected = Selection.gameObjects.Length > 0;\n            // If the custom parent for new objects is set we don't allow cut, copy or duplicate any ancestors of this object\n            // as it might be context objects (as in Prefab Mode in Context).\n            bool allowCutCopyAndDuplicate = m_CustomParentForNewGameObjects == null\n                                            || !IsChildOfSelectionOrSelected(m_CustomParentForNewGameObjects.parent);\n\n            if (itemIsSelected && allowCutCopyAndDuplicate)\n                menu.AddItem(EditorGUIUtility.TrTextContent(kContextMenuItemCut), false, ClipboardUtility.CutGO);\n            else\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(kContextMenuItemCut));\n            if (itemIsSelected && allowCutCopyAndDuplicate)\n                menu.AddItem(EditorGUIUtility.TrTextContent(kContextMenuItemCopy), false, ClipboardUtility.CopyGO);\n            else\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(kContextMenuItemCopy));\n            if (CutBoard.CanGameObjectsBePasted() || Unsupported.CanPasteGameObjectsFromPasteboard())\n                menu.AddItem(EditorGUIUtility.TrTextContent(kContextMenuItemPaste), false, PasteGO);\n            else\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(kContextMenuItemPaste));\n            if (ClipboardUtility.CanPasteAsChild())\n            {\n                menu.AddItem(EditorGUIUtility.TrTextContent(kContextMenuItemPasteAsChildKeepLocalTransform), false, () => ClipboardUtility.PasteGOAsChild(false));\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Paste Special/Paste as Child (Keep World Transform)\"), false, () => ClipboardUtility.PasteGOAsChild(true));\n            }\n            else\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Paste Special\"));\n\n            if (itemIsSelected && !hasSearchFilter && m_TreeViewState.selectedIDs.Count == 1 && !GetIsNotEditable())\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Rename\"), false, RenameGO);\n            else\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Rename\"));\n\n            if (itemIsSelected && allowCutCopyAndDuplicate)\n                menu.AddItem(EditorGUIUtility.TrTextContent(kContextMenuItemDuplicate), false, DuplicateGO);\n            else\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(kContextMenuItemDuplicate));\n\n            if (m_CustomParentForNewGameObjects != null && IsChildOfSelectionOrSelected(m_CustomParentForNewGameObjects) || !itemIsSelected)\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(kContextMenuItemDelete));\n            else\n                menu.AddItem(EditorGUIUtility.TrTextContent(kContextMenuItemDelete), false, DeleteGO);\n\n\n            menu.AddSeparator(\"\");\n\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Select All\"), false, SelectAll);\n\n            if (itemIsSelected)\n            {\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Deselect All\"), false, DeselectAll);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Invert Selection\"), false, InvertSelection);\n            }\n            else\n            {\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Deselect All\"));\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Invert Selection\"));\n            }\n\n            if (IsSelectChildrenAvailable())\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Select Children\"), false, SelectChildren);\n            else\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Select Children\"));\n\n            menu.AddSeparator(\"\");\n            if (Selection.activeGameObject)\n            {\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Find References in Scene\"), false, FindReferenceInScene);\n            }\n            else\n            {\n                menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Find References in Scene\"));\n            }\n\n            menu.AddSeparator(\"\");\n\n            GameObject selectedObject = null;\n            if (Selection.objects.Length > 0)\n                selectedObject = Selection.objects[Selection.objects.Length - 1] as GameObject;\n\n            if (Selection.count == 0 && treeView.hoveredItem == null || selectedObject && (selectedObject.name == PrefabUtility.kDummyPrefabStageRootObjectName || PrefabStageUtility.IsGameObjectThePrefabRootInAnyPrefabStage(selectedObject)))\n            {\n                menu.AddDisabledItem(Styles.setOriginLabel);\n            }\n            else if (selectedObject && (selectedObject.GetInstanceID() != GetDefaultParentForSession(selectedObject.scene.guid) || EditorSceneManager.GetActiveScene().guid != selectedObject.scene.guid))\n            {\n                menu.AddItem(Styles.setOriginLabel, false, () =>\n                {\n                    SetDefaultParentObject(false);\n                });\n            }\n            else\n            {\n                menu.AddItem(Styles.clearOriginLabel, false, () => { ClearDefaultParentObject(); });\n            }\n\n            // Prefab menu items that only make sense if a single object is selected.\n            PopulateGenericMenuWithPrefabMenuItems(menu, contextClickedItemID);\n\n            GameObject[] selectedGameObjects = Selection.transforms.Select(t => t.gameObject).ToArray();\n\n            // All Create GameObject menu items\n            {\n                menu.AddSeparator(\"\");\n\n                int targetSceneForCreation = selectedGameObjects.Length > 0\n                    ? selectedGameObjects.Last().scene.handle\n                    : SceneManager.GetActiveScene().handle;\n\n                // Set the context of each MenuItem to the current selection, so the created gameobjects will be added as children\n                // Sets includeCreateEmptyChild to false, since that item is superfluous here (the normal \"Create Empty\" is added as a child anyway)\n                AddCreateGameObjectItemsToMenu(menu,\n                    selectedGameObjects,\n                    false,\n                    false,\n                    false,\n                    targetSceneForCreation,\n                    contextClickedItemID == 0\n                    ? MenuUtils.ContextMenuOrigin.None\n                    : MenuUtils.ContextMenuOrigin.GameObject);\n            }\n\n            SceneHierarchyHooks.AddCustomGameObjectContextMenuItems(menu, contextClickedItemID == 0 ? null : (GameObject)EditorUtility.InstanceIDToObject(contextClickedItemID));\n\n            if (selectedGameObjects.Length > 0)\n            {\n                menu.AddSeparator(\"\");\n                menu.AddItem(new GUIContent(\"Properties...\"), false, () => PropertyEditor.OpenPropertyEditorOnSelection());\n            }\n        }\n\n        internal void PopulateDropdownMenuWithPrefabMenuItems(DropdownMenu menu)\n        {\n            if (m_TreeViewState.selectedIDs.Count != 1) return;\n\n            int selectedGameObjectInstanceID = m_TreeViewState.selectedIDs[0];\n            GenericMenu genericMenuForGettingPrefabItems = new GenericMenu();\n            PopulateGenericMenuWithPrefabMenuItems(genericMenuForGettingPrefabItems, selectedGameObjectInstanceID);\n\n            for (int i = 0, prefabMenuItemsCount = genericMenuForGettingPrefabItems.menuItems.Count; i < prefabMenuItemsCount; ++i)\n            {\n                GenericMenu.MenuItem menuItem = genericMenuForGettingPrefabItems.menuItems[i];\n                if (menuItem.separator)\n                    menu.AppendSeparator(menuItem.content.text);\n                else if (menuItem.func2 != null && menuItem.userData != null)\n                    menu.AppendAction(menuItem.content.text, action => { menuItem.func2(menuItem.userData); });\n                else if (menuItem.func != null)\n                    menu.AppendAction(menuItem.content.text, action => { menuItem.func(); });\n                else\n                    menu.AppendAction(menuItem.content.text, action => { }, DropdownMenuAction.Status.Disabled);\n            }\n        }\n\n        private void FindReferenceInScene()\n        {\n            var selectedObject = Selection.activeObject;\n            if (!selectedObject)\n                return;\n            SearchableEditorWindow.SearchForReferencesToInstanceID(selectedObject.GetInstanceID());\n        }\n\n        private void FindReferenceInProject()\n        {\n            var selectedObject = Selection.activeObject;\n            if (!selectedObject)\n                return;\n            SearchableEditorWindow.SearchForReferencesInProject(selectedObject);\n        }\n\n        protected void AddCreateGameObjectItemsToSceneMenu(GenericMenu menu, Scene scene)\n        {\n            AddCreateGameObjectItemsToMenu(menu, Selection.transforms.Select(t => t.gameObject).ToArray(), false, false, true, scene.handle, MenuUtils.ContextMenuOrigin.Scene);\n        }\n\n        protected void AddCreateGameObjectItemsToSubSceneMenu(GenericMenu menu, Scene scene)\n        {\n            AddCreateGameObjectItemsToMenu(menu, new UnityEngine.Object[0], false, true, true, scene.handle, MenuUtils.ContextMenuOrigin.Subscene);\n        }\n\n        internal bool CanScenesBeReloaded(Scene[] scenes)\n        {\n            foreach (var scene in scenes)\n            {\n                var path = scene.path;\n                if (string.IsNullOrEmpty(path))\n                    return false;\n\n                if (!System.IO.File.Exists(path))\n                    return false;\n            }\n            return true;\n        }\n\n        internal void CreateSceneHeaderContextClick(GenericMenu menu, Scene scene)\n        {\n            if (!IsSceneHeaderInHierarchyWindow(scene))\n            {\n                Debug.LogError(\"Context clicked item is not a scene\");\n                return;\n            }\n\n            bool hasMultipleScenes = EditorSceneManager.sceneCount > 1;\n\n            // Set active\n            if (scene.isLoaded)\n            {\n                var content = EditorGUIUtility.TrTextContent(\"Set Active Scene\");\n                if (hasMultipleScenes && SceneManager.CanSetAsActiveScene(scene))\n                    menu.AddItem(content, false, SetSceneActive, scene);\n                else\n                    menu.AddDisabledItem(content);\n                menu.AddSeparator(\"\");\n            }\n\n            // Save\n            if (scene.isLoaded)\n            {\n                if (!EditorApplication.isPlaying || EditorSceneManager.IsAuthoringScene(scene))\n                {\n                    menu.AddItem(EditorGUIUtility.TrTextContent(\"Save Scene\"), false, SaveSelectedScenes, scene);\n                    if (!scene.isSubScene)\n                        menu.AddItem(EditorGUIUtility.TrTextContent(\"Save Scene As\"), false, SaveSceneAs, scene);\n                    if (hasMultipleScenes)\n                        menu.AddItem(EditorGUIUtility.TrTextContent(\"Save All\"), false, SaveAllScenes, scene);\n                    else\n                        menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Save All\"));\n                }\n                else\n                {\n                    menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Save Scene\"));\n                    menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Save Scene As\"));\n                    menu.AddDisabledItem(EditorGUIUtility.TrTextContent(\"Save All\"));\n                }\n                menu.AddSeparator(\"\");\n            }\n\n            bool isUnloadOrRemoveValid = SceneManager.loadedSceneCount != GetNumLoadedScenesInSelection();\n\n            if (!scene.isSubScene)\n            {\n                if (scene.isLoaded)\n                {\n                    // Unload\n                    var content = EditorGUIUtility.TrTextContent(\"Unload Scene\");\n                    bool canUnloadScenes = isUnloadOrRemoveValid && !EditorApplication.isPlaying && !string.IsNullOrEmpty(scene.path);\n                    if (canUnloadScenes)\n                        menu.AddItem(content, false, UnloadSelectedScenes, scene);\n                    else\n                        menu.AddDisabledItem(content);\n                }\n                else\n                {\n                    // Load\n                    var content = EditorGUIUtility.TrTextContent(\"Load Scene\");\n                    bool canLoadScenes = !EditorApplication.isPlaying;\n                    if (canLoadScenes)\n                        menu.AddItem(content, false, LoadSelectedScenes, scene);\n                    else\n                        menu.AddDisabledItem(content);\n                }\n\n                // Remove\n                var removeContent = EditorGUIUtility.TrTextContent(\"Remove Scene\");\n                bool selectedAllScenes = GetSelectedScenes().Count == EditorSceneManager.sceneCount;\n                bool canRemoveScenes = isUnloadOrRemoveValid && !selectedAllScenes && !EditorApplication.isPlaying;\n                if (canRemoveScenes)\n                    menu.AddItem(removeContent, false, RemoveSelectedScenes, scene);\n                else\n                    menu.AddDisabledItem(removeContent);\n            }\n\n            // Discard changes\n            if (scene.isLoaded)\n            {\n                var content = EditorGUIUtility.TrTextContent(\"Discard changes\");\n                var selectedSceneHandles = GetSelectedScenes();\n                var modifiedScenes = GetModifiedScenes(selectedSceneHandles);\n                bool canReload = modifiedScenes.Length > 0 && CanScenesBeReloaded(modifiedScenes);\n                bool canDiscardChanges = !EditorApplication.isPlaying && canReload;\n                if (canDiscardChanges)\n                    menu.AddItem(content, false, DiscardChangesInSelectedScenes, scene);\n                else\n                    menu.AddDisabledItem(content);\n            }\n\n            // Ping Scene Asset\n            menu.AddSeparator(\"\");\n            var selectAssetContent = EditorGUIUtility.TrTextContent(\"Find In Project\");\n            if (!string.IsNullOrEmpty(scene.path))\n                menu.AddItem(selectAssetContent, false, SelectSceneAsset, scene);\n            else\n                menu.AddDisabledItem(selectAssetContent);\n\n            if (!scene.isSubScene)\n            {\n                var addSceneContent = EditorGUIUtility.TrTextContent(\"Add New Scene\");\n                if (!EditorApplication.isPlaying)\n                    menu.AddItem(addSceneContent, false, AddNewScene, scene);\n                else\n                    menu.AddDisabledItem(addSceneContent);\n            }\n\n            menu.AddSeparator(\"\");\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Prefab/Remove Unused Overrides...\"), false, RemoveAllPrefabInstancesUnusedOverridesFromSceneForMenuItem, scene);\n\n            // Set the context of each MenuItem to the current selection, so the created gameobjects will be added as children\n            // Sets includeCreateEmptyChild to false, since that item is superfluous here (the normal \"Create Empty\" is added as a child anyway)\n            if (scene.isLoaded)\n            {\n                menu.AddSeparator(\"\");\n                if (scene.isSubScene)\n                    AddCreateGameObjectItemsToSubSceneMenu(menu, scene);\n                else\n                    AddCreateGameObjectItemsToSceneMenu(menu, scene);\n            }\n        }\n\n        int GetNumLoadedScenesInSelection()\n        {\n            int loadedScenes = 0;\n            foreach (int handle in GetSelectedScenes())\n            {\n                if (EditorSceneManager.GetSceneByHandle(handle).isLoaded)\n                    loadedScenes++;\n            }\n            return loadedScenes;\n        }\n\n        // returns selected scene handles\n        List<int> GetSelectedScenes()\n        {\n            var selectedSceneHandles = new List<int>();\n            int[] instanceIDs = m_TreeView.GetSelection();\n            foreach (int id in instanceIDs)\n            {\n                if (IsSceneHeaderInHierarchyWindow(EditorSceneManager.GetSceneByHandle(id)))\n                {\n                    selectedSceneHandles.Add(id);\n                }\n                else\n                {\n                    GameObject gameObject = EditorUtility.InstanceIDToObject(id) as GameObject;\n                    if (gameObject)\n                    {\n                        var subSceneInfo = SubSceneGUI.GetSubSceneInfo(gameObject);\n                        if (subSceneInfo.isValid && subSceneInfo.scene.IsValid())\n                            selectedSceneHandles.Add(subSceneInfo.scene.handle);\n                    }\n                }\n            }\n\n            return selectedSceneHandles;\n        }\n\n        void ContextClickOutsideItems()\n        {\n            Event evt = Event.current;\n            evt.Use();\n\n            // Clear selection when clicking outside items so the new game object is\n            // added to the last loaded scene in the Hierarchy (otherwise it would be parented\n            // to current selcection)\n            Selection.activeInstanceID = 0;\n\n            var menu = new GenericMenu();\n\n            CreateGameObjectContextClick(menu, 0);\n\n            menu.ShowAsContext();\n        }\n\n        void ItemContextClick(int contextClickedItemID)\n        {\n            Event evt = Event.current;\n\n            evt.Use();\n            var menu = new GenericMenu();\n\n            Scene scene = EditorSceneManager.GetSceneByHandle(contextClickedItemID);\n            bool clickedSceneHeader = IsSceneHeaderInHierarchyWindow(scene);\n\n            if (clickedSceneHeader)\n            {\n                CreateSceneHeaderContextClick(menu, scene);\n                // Let users add extra items.\n                SceneHierarchyHooks.AddCustomSceneHeaderContextMenuItems(menu, scene);\n            }\n            else\n            {\n                GameObject gameObject = EditorUtility.InstanceIDToObject(contextClickedItemID) as GameObject;\n                var subSceneInfo = SubSceneGUI.GetSubSceneInfo(gameObject);\n                if (subSceneInfo.isValid)\n                {\n                    CreateSubSceneGameObjectContextClick(menu, contextClickedItemID);\n                    menu.AddSeparator(string.Empty);\n\n                    if (subSceneInfo.scene.IsValid())\n                    {\n                        // Sub scenes where the scene object exists can reuse menu for regular scenes.\n                        CreateSceneHeaderContextClick(menu, subSceneInfo.scene);\n                    }\n                    else\n                    {\n                        // Sub scenes where only the info exists, but not the scene object, need special handling.\n                        SubSceneGUI.CreateClosedSubSceneContextClick(menu, subSceneInfo);\n                    }\n                    // Let users add extra items.\n                    SceneHierarchyHooks.AddCustomSubSceneHeaderContextMenuItems(menu, subSceneInfo);\n                }\n                else\n                {\n                    CreateGameObjectContextClick(menu, contextClickedItemID);\n                }\n            }\n\n            menu.ShowAsContext();\n        }\n\n        void PasteGO()\n        {\n            ClipboardUtility.PasteGO(m_CustomParentForNewGameObjects);\n        }\n\n        void DuplicateGO()\n        {\n            ClipboardUtility.DuplicateGO(m_CustomParentForNewGameObjects);\n        }\n\n        void RenameGO()\n        {\n            treeView.BeginNameEditing(0f);\n        }\n\n        internal void RenameNewGO()\n        {\n            // end renaming if any GO has active one\n            treeView.EndNameEditing(true);\n\n            if (m_EditorWindow != null)\n                m_EditorWindow.Focus();\n\n            treeViewReloadNeeded = true;\n            SyncIfNeeded();\n            RenameGO();\n        }\n\n        void DeleteGO()\n        {\n            Unsupported.DeleteGameObjectSelection();\n        }\n\n        bool AnyOutermostPrefabRoots()\n        {\n            var gameObjects = Selection.gameObjects;\n            for (int i = 0; i < gameObjects.Length; i++)\n            {\n                var go = gameObjects[i];\n                if (go != null && PrefabUtility.IsPartOfNonAssetPrefabInstance(go) && PrefabUtility.IsOutermostPrefabInstanceRoot(go))\n                    return true;\n            }\n            return false;\n        }\n\n        void UnpackPrefab()\n        {\n            var gameObjects = Selection.gameObjects;\n            for (int i = 0; i < gameObjects.Length; i++)\n            {\n                var go = gameObjects[i];\n                if (go != null && PrefabUtility.IsPartOfNonAssetPrefabInstance(go) && PrefabUtility.IsOutermostPrefabInstanceRoot(go))\n                    PrefabUtility.UnpackPrefabInstance(go, PrefabUnpackMode.OutermostRoot, InteractionMode.UserAction);\n            }\n        }\n\n        void UnpackPrefabCompletely()\n        {\n            var gameObjects = Selection.gameObjects;\n            for (int i = 0; i < gameObjects.Length; i++)\n            {\n                var go = gameObjects[i];\n                if (go != null && PrefabUtility.IsPartOfNonAssetPrefabInstance(go) && PrefabUtility.IsOutermostPrefabInstanceRoot(go))\n                    PrefabUtility.UnpackPrefabInstance(go, PrefabUnpackMode.Completely, InteractionMode.UserAction);\n            }\n        }\n\n        void RemoveAllPrefabInstancesUnusedOverridesFromSceneForMenuItem(object userData)\n        {\n            RemoveAllPrefabInstancesUnusedOverridesFromScene((Scene)userData);\n        }\n\n        void RemoveSelectedPrefabInstanceUnusedOverrides()\n        {\n            PrefabUtility.InstanceOverridesInfo[] instanceOverrideInfos = PrefabUtility.GetPrefabInstancesOverridesInfos(Selection.gameObjects);\n\n            AskUserToRemovePrefabInstanceUnusedOverrides(instanceOverrideInfos);\n        }\n\n        void RemoveAllPrefabInstancesUnusedOverridesFromScene(Scene scene)\n        {\n            if (!scene.IsValid())\n                return;\n\n            PrefabUtility.InstanceOverridesInfo[] instanceOverridesInfos = null;\n\n            List<GameObject> gos = GetScenePrefabInstancesWithNonDefaultOverrides(scene);\n            if (gos != null && gos.Any())\n                instanceOverridesInfos = PrefabUtility.GetPrefabInstancesOverridesInfos(gos.ToArray());\n\n            AskUserToRemovePrefabInstanceUnusedOverrides(instanceOverridesInfos);\n        }\n\n        bool AskUserToRemovePrefabInstanceUnusedOverrides(PrefabUtility.InstanceOverridesInfo[] instanceOverridesInfos)\n        {\n            if (PrefabUtility.DoRemovePrefabInstanceUnusedOverridesDialog(instanceOverridesInfos))\n            {\n                PrefabUtility.RemovePrefabInstanceUnusedOverrides(instanceOverridesInfos, InteractionMode.UserAction);\n                return true;\n            }\n\n            return false;\n        }\n\n        List<GameObject> GetScenePrefabInstancesWithNonDefaultOverrides(Scene scene)\n        {\n            List<GameObject> gameObjects = new List<GameObject>();\n            TransformVisitor visitor = new TransformVisitor();\n\n            var roots = scene.GetRootGameObjects();\n            foreach (var root in roots)\n            {\n                visitor.VisitAll(root.transform, (transform, list) => {\n                    GameObject go = transform.gameObject;\n                    if (PrefabUtility.IsOutermostPrefabInstanceRoot(go) && PrefabUtility.HasPrefabInstanceNonDefaultOverridesOrUnusedOverrides_CachedForUI(go))\n                    {\n                        gameObjects.Add(go);\n                    }\n                }, null);\n            }\n\n            return gameObjects;\n        }\n\n        void SetSceneActive(object userData)\n        {\n            Scene scene = (Scene)userData;\n            EditorSceneManager.SetActiveScene(scene);\n        }\n\n        private static string GetDefaultParentKeyForScene(string sceneGUID)\n        {\n            return String.Format(\"DefaultParentObject-{0}\", sceneGUID);\n        }\n\n        [Shortcut(\"Hierarchy View/Set as Default Parent\")]\n        private static void SetOriginShortcut()\n        {\n            SetDefaultParentObject(true);\n            SceneHierarchyWindow.lastInteractedHierarchyWindow?.Repaint();\n        }\n\n        internal static int GetDefaultParentForSession(string sceneGUID)\n        {\n            return SessionState.GetInt(GetDefaultParentKeyForScene(sceneGUID), 0);\n        }\n\n        internal static void SetDefaultParentForSession(string sceneGUID, int instanceID)\n        {\n            SessionState.SetInt(GetDefaultParentKeyForScene(sceneGUID), instanceID);\n        }\n\n        [RequiredByNativeCode]\n        internal static void UpdateSessionStateInfoAndActiveParentObjectValuesForScene(string sceneGUID, int id)\n        {\n            SetDefaultParentForSession(sceneGUID, id);\n            GameObjectTreeViewGUI.UpdateActiveParentObjectValuesForScene(sceneGUID, id);\n        }\n\n        internal static void SetDefaultParentObject(bool toggle, GameObject defaultParentObject = null)\n        {\n            UnityEngine.GameObject lastSelectedObject = null;\n            int id = 0;\n\n            if (defaultParentObject != null)\n            {\n                lastSelectedObject = defaultParentObject;\n                id = lastSelectedObject.GetInstanceID();\n            }\n            else if (Selection.objects.Length > 0)\n            {\n                lastSelectedObject = Selection.objects[Selection.objects.Length - 1] as GameObject;\n                if (lastSelectedObject != null && !PrefabStageUtility.IsGameObjectThePrefabRootInAnyPrefabStage(lastSelectedObject))\n                    id = lastSelectedObject.GetInstanceID();\n            }\n\n            var sceneGUID = \"\";\n            Scene scene;\n\n            if (lastSelectedObject)\n            {\n                // entering a prefab from within a prefab creates a dummy object\n                // we don't want it to be selectable as an origin object\n                if (lastSelectedObject.name == PrefabUtility.kDummyPrefabStageRootObjectName)\n                    return;\n\n                sceneGUID = lastSelectedObject.scene.guid;\n                scene = lastSelectedObject.scene;\n            }\n            else\n            {\n                scene = EditorSceneManager.GetActiveScene();\n                sceneGUID = scene.guid;\n            }\n\n            string undoText = \"Set Default Parent Object\";\n            int currentlySetID = GetDefaultParentForSession(sceneGUID);\n\n            var objectInstanceID = lastSelectedObject ? lastSelectedObject.GetInstanceID() : 0;\n            var isPrefabStage = PrefabStageUtility.IsPrefabStageScene(scene);\n\n            // if we're toggling an object that is already the default parent object in an inactive scene,\n            // we set the active scene and leave the same object as the active parent\n            // this is to avoid confusion because active parent objects are not highlighted in inactive scenes\n            if (toggle && currentlySetID == objectInstanceID && sceneGUID != EditorSceneManager.GetActiveScene().guid && !isPrefabStage)\n            {\n                EditorSceneManager.SetActiveScene(scene);\n                return;\n            }\n\n            // we check if we're toggling inside the active scene\n            // if yes - we deactivate the current active parent object\n            // if not - we allow setting a new parent object immediately without unsetting the previous object first\n            // (it gets overriden on the first shortcut click)\n            if (toggle && currentlySetID != 0 && (sceneGUID == EditorSceneManager.GetActiveScene().guid || isPrefabStage))\n            {\n                if (lastSelectedObject == null)\n                    return;\n\n                id = 0;\n                undoText = \"Clear Default Parent Object\";\n            }\n\n            if (toggle && currentlySetID != 0 || lastSelectedObject != null)\n            {\n                InternalEditorUtility.RegisterSetDefaultParentObjectUndo(sceneGUID, GetDefaultParentForSession(sceneGUID), undoText);\n                if (!isPrefabStage)\n                    EditorSceneManager.SetActiveScene(scene);\n            }\n\n            UpdateSessionStateInfoAndActiveParentObjectValuesForScene(sceneGUID, id);\n        }\n\n        internal static void ClearDefaultParentObject(string sceneGUID = \"\")\n        {\n            UnityEngine.GameObject lastSelectedObject = null;\n\n            if (sceneGUID == \"\")\n            {\n                if (Selection.objects.Length > 0)\n                {\n                    lastSelectedObject = Selection.objects[Selection.objects.Length - 1] as GameObject;\n                }\n                if (lastSelectedObject)\n                    sceneGUID = lastSelectedObject.scene.guid;\n                else\n                    sceneGUID = EditorSceneManager.GetActiveScene().guid;\n            }\n\n            InternalEditorUtility.RegisterSetDefaultParentObjectUndo(sceneGUID, GetDefaultParentForSession(sceneGUID), \"Clear Default Parent Object\");\n            UpdateSessionStateInfoAndActiveParentObjectValuesForScene(sceneGUID, 0);\n        }\n\n        private void LoadSelectedScenes(object userdata)\n        {\n            List<int> selectedScenes = GetSelectedScenes();\n            foreach (var id in selectedScenes)\n            {\n                var scene = EditorSceneManager.GetSceneByHandle(id);\n                if (!scene.isLoaded)\n                    EditorSceneManager.OpenScene(scene.path, OpenSceneMode.Additive);\n            }\n\n            EditorApplication.RequestRepaintAllViews();\n        }\n\n        private void SaveSceneAs(object userdata)\n        {\n            Scene scene = (Scene)userdata;\n            if (scene.isLoaded)\n            {\n                EditorSceneManager.SaveSceneAs(scene);\n            }\n        }\n\n        private void SaveAllScenes(object userdata)\n        {\n            EditorSceneManager.SaveOpenScenes();\n        }\n\n        void SaveSelectedScenes(object userdata)\n        {\n            List<int> selectedScenes = GetSelectedScenes();\n            foreach (var id in selectedScenes)\n            {\n                var scene = EditorSceneManager.GetSceneByHandle(id);\n                if (scene.isLoaded)\n                    EditorSceneManager.SaveScene(scene);\n            }\n        }\n\n        void UnloadSelectedScenes(object userdata)\n        {\n            const bool removeScenesFromHierarchy = false;\n            CloseSelectedScenes(removeScenesFromHierarchy);\n        }\n\n        void RemoveSelectedScenes(object userData)\n        {\n            const bool removeScenesFromHierarchy = true;\n            CloseSelectedScenes(removeScenesFromHierarchy);\n        }\n\n        bool UserAllowedDiscardingChanges(Scene[] modifiedScenes)\n        {\n            string title = LocalizationDatabase.GetLocalizedString(\"Discard Changes\");\n            string message = LocalizationDatabase.GetLocalizedString(\"Are you sure you want to discard the changes in the following scenes:\\n\\n   {0}\\n\\nYour changes will be lost.\");\n\n            string sceneNames = string.Join(\"\\n   \", modifiedScenes.Select(scene => scene.name).ToArray());\n            message = string.Format(message, sceneNames);\n\n            return EditorUtility.DisplayDialog(title, message, LocalizationDatabase.GetLocalizedString(\"OK\"), LocalizationDatabase.GetLocalizedString(\"Cancel\"));\n        }\n\n        void DiscardChangesInSelectedScenes(object userData)\n        {\n            var expandedSceneNames = GetExpandedSceneNames();\n            var selectedSceneHandles = GetSelectedScenes();\n            var modifiedScenes = GetModifiedScenes(selectedSceneHandles);\n            var modifiedScenesWithSavePath = modifiedScenes.Where(scene => !string.IsNullOrEmpty(scene.path)).ToArray();\n\n            if (!UserAllowedDiscardingChanges(modifiedScenesWithSavePath))\n                return;\n\n            if (modifiedScenesWithSavePath.Length != modifiedScenes.Length)\n                Debug.LogWarning(\"Discarding changes in a scene that have not yet been saved is not supported. Save the scene first or create a new scene.\");\n\n            foreach (var scene in modifiedScenesWithSavePath)\n            {\n                EditorSceneManager.ReloadScene(scene);\n            }\n\n            // When reloading a single scene it will be given a new scene handle which will collapse it in the Hierarchy.\n            // Here we ensure same scene are expanded\n            if (SceneManager.sceneCount == 1)\n                SetScenesExpanded(expandedSceneNames.ToList());\n\n            EditorApplication.RequestRepaintAllViews();\n        }\n\n        Scene[] GetModifiedScenes(List<int> handles)\n        {\n            return handles.Select(handle => EditorSceneManager.GetSceneByHandle(handle)).Where(scene => scene.isDirty).ToArray();\n        }\n\n        void CloseSelectedScenes(bool removeScenes)\n        {\n            var selectedSceneHandles = GetSelectedScenes();\n\n            var modifiedScenes = GetModifiedScenes(selectedSceneHandles);\n            bool userCancelled = !EditorSceneManager.SaveModifiedScenesIfUserWantsTo(modifiedScenes);\n            if (userCancelled)\n                return;\n\n            foreach (var id in selectedSceneHandles)\n                EditorSceneManager.CloseScene(EditorSceneManager.GetSceneByHandle(id), removeScenes);\n\n            EditorApplication.RequestRepaintAllViews();\n        }\n\n        void AddNewScene(object userData)\n        {\n            // Check for existing untitled scene\n            Scene untitledScene = EditorSceneManager.GetSceneByPath(\"\");\n            if (untitledScene.IsValid())\n            {\n                var title = EditorGUIUtility.TrTextContent(\"Save Untitled Scene\").text;\n                var subTitle = EditorGUIUtility.TrTextContent(\"Existing Untitled scene needs to be saved before creating a new scene. Only one untitled scene is supported at a time.\").text;\n                if (EditorUtility.DisplayDialog(title, subTitle, \"Save\", \"Cancel\"))\n                {\n                    if (!EditorSceneManager.SaveScene(untitledScene))\n                        return;\n                }\n                else\n                    return;\n            }\n\n            Scene newScene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Additive);\n\n            // Move new scene after context clicked scene\n            Scene scene = (Scene)userData;\n            if (scene.IsValid())\n                EditorSceneManager.MoveSceneAfter(newScene, scene);\n        }\n\n        void SelectSceneAsset(object userData)\n        {\n            Scene scene = (Scene)userData;\n            var sceneObject = AssetDatabase.LoadMainAssetAtPath(scene.path);\n            Selection.activeObject = sceneObject;\n            EditorGUIUtility.PingObject(sceneObject);\n        }\n\n        void SelectAll()\n        {\n            int[] instanceIDs = treeView.GetRowIDs();\n            treeView.SetSelection(instanceIDs, false);\n            TreeViewSelectionChanged(instanceIDs);\n        }\n\n        void DeselectAll()\n        {\n            int[] instanceIDs = new int[0];\n            treeView.SetSelection(instanceIDs, false);\n            TreeViewSelectionChanged(instanceIDs);\n        }\n\n        void InvertSelection()\n        {\n            int[] instanceIDs = treeView.GetRowIDs().Except(treeView.GetSelection()).ToArray();\n            treeView.SetSelection(instanceIDs, true);\n            TreeViewSelectionChanged(instanceIDs);\n        }\n\n        bool IsSelectChildrenAvailable()\n        {\n            foreach (var id in treeView.GetSelection())\n            {\n                var scene = EditorSceneManager.GetSceneByHandle(id);\n                if (IsSceneHeaderInHierarchyWindow(scene) && scene.isLoaded)\n                {\n                    foreach (var rootGameObject in scene.GetRootGameObjects())\n                    {\n                        if (rootGameObject.transform.GetComponentsInChildren<Transform>(true).Length > 1)\n                            return true;\n                    }\n                }\n                else\n                {\n                    var go = InternalEditorUtility.GetObjectFromInstanceID(id) as GameObject;\n                    if (go != null)\n                    {\n                        if (go.transform.GetComponentsInChildren<Transform>(true).Length > 1)\n                            return true;\n                    }\n                }\n            }\n\n            return false;\n        }\n\n        void SelectChildren()\n        {\n            List<int> instanceIDs = new List<int>(treeView.GetSelection());\n            foreach (var id in treeView.GetSelection())\n            {\n                var scene = EditorSceneManager.GetSceneByHandle(id);\n                if (IsSceneHeaderInHierarchyWindow(scene))\n                {\n                    foreach (var rootGameObject in scene.GetRootGameObjects())\n                    {\n                        instanceIDs.Add(rootGameObject.GetInstanceID());\n                        instanceIDs.AddRange(rootGameObject.transform.GetComponentsInChildren<Transform>(true).Select(t => t.gameObject.GetInstanceID()));\n                    }\n                }\n                else\n                {\n                    var go = InternalEditorUtility.GetObjectFromInstanceID(id) as GameObject;\n                    if (go != null)\n                        instanceIDs.AddRange(go.transform.GetComponentsInChildren<Transform>(true).Select(t => t.gameObject.GetInstanceID()));\n                }\n            }\n\n            var newSelection = instanceIDs.Distinct().ToArray();\n            treeView.SetSelection(newSelection, true);\n\n            TreeViewSelectionChanged(newSelection);\n        }\n\n        private bool IsSelectPrefabRootAvailable()\n        {\n            foreach (var id in treeView.GetSelection())\n            {\n                var go = InternalEditorUtility.GetObjectFromInstanceID(id) as GameObject;\n                if (go != null)\n                {\n                    var root = PrefabUtility.GetOutermostPrefabInstanceRoot(go);\n                    if (root != null)\n                    {\n                        return true;\n                    }\n                }\n            }\n\n            return false;\n        }\n\n        private void SelectPrefabRoot()\n        {\n            List<int> instanceIDs = new List<int>(treeView.GetSelection().Length);\n            foreach (var id in treeView.GetSelection())\n            {\n                var go = InternalEditorUtility.GetObjectFromInstanceID(id) as GameObject;\n                if (go != null)\n                {\n                    var root = PrefabUtility.GetOutermostPrefabInstanceRoot(go);\n                    if (root != null)\n                    {\n                        instanceIDs.Add(root.GetInstanceID());\n                    }\n                }\n            }\n\n            var newSelection = instanceIDs.Distinct().ToArray();\n            treeView.SetSelection(newSelection, true);\n            TreeViewSelectionChanged(newSelection);\n        }\n\n        static internal GameObject GetSourceRootWhereGameObjectIsAddedAsOverride(GameObject go)\n        {\n            if (go == null)\n                return null;\n\n            var source = PrefabUtility.GetCorrespondingObjectFromSource(go);\n\n            while (source != null)\n            {\n                if (PrefabUtility.IsAddedGameObjectOverride(source))\n                    return PrefabUtility.GetPrefabAssetRootGameObject(source);\n\n                source = PrefabUtility.GetCorrespondingObjectFromSource(source);\n            }\n\n            return null;\n        }\n\n        public void CollapseAll()\n        {\n            treeViewState.expandedIDs.Clear();\n            ReloadData();\n        }\n\n        public void ExpandAll()\n        {\n            int[] instanceIDs = treeView.GetRowIDs();\n            foreach (var id in instanceIDs)\n                SetExpandedRecursive(id, true);\n            ReloadData();\n        }\n\n        public virtual void AddItemsToWindowMenu(GenericMenu menu)\n        {\n            menu.AddItem(EditorGUIUtility.TrTextContent(\"Collapse All\"), false, CollapseAll);\n            menu.AddSeparator(\"\");\n            m_LockTracker.AddItemsToMenu(menu);\n\n            menu.AddItem(Styles.renamingEnabledContent, SceneHierarchyWindow.s_EnterRenameModeForNewGO, SceneHierarchyWindow.SwitchEnterRenameModeForNewGO);\n\n            if (Unsupported.IsDeveloperMode())\n            {\n                menu.AddItem(new GUIContent(\"DEVELOPER/Debug Mode - Hierarchy \"), s_Debug, () => s_Debug = !s_Debug);\n                menu.AddItem(new GUIContent(\"DEVELOPER/Debug Mode - Prefab Scene\"), s_DebugPrefabStage, () => s_DebugPrefabStage = !s_DebugPrefabStage);\n                menu.AddItem(new GUIContent(\"DEVELOPER/Debug Mode - Expanded State Persistence\"), s_DebugPersistingExpandedState, () => s_DebugPersistingExpandedState = !s_DebugPersistingExpandedState);\n                menu.AddItem(new GUIContent(\"DEVELOPER/Debug Mode - Preview Scenes\"), s_DebugPreviewScenes, () => s_DebugPreviewScenes = !s_DebugPreviewScenes);\n            }\n        }\n\n        private void DoPingRequest()\n        {\n            if (m_FrameRequestID != 0)\n            {\n                FrameObjectPrivate(m_FrameRequestID, true, m_FrameRequestPing, true);\n                m_FrameRequestID = 0;\n            }\n        }\n\n        public void FrameObject(int instanceID, bool ping)\n        {\n            m_FrameRequestID = instanceID;\n            m_FrameRequestPing = ping;\n            treeViewReloadNeeded = true;\n            Repaint();\n        }\n\n        private void FrameObjectPrivate(int instanceID, bool frame, bool ping, bool animatedFraming)\n        {\n            if (instanceID == 0)\n                return;\n\n            // If framing the same instance as the last one we do not remove the ping\n            // since issuing first a ping and then a framing should still show the ping.\n            if (m_LastFramedID != instanceID)\n                treeView.EndPing();\n\n            m_LastFramedID = instanceID;\n\n            treeView.Frame(instanceID, frame, ping, animatedFraming);\n\n            FrameObjectPrivate(InternalEditorUtility.GetGameObjectInstanceIDFromComponent(instanceID), frame, ping, animatedFraming);\n        }\n\n        internal virtual void DoWindowLockButton(Rect r)\n        {\n            m_LockTracker.ShowButton(r, Styles.lockButton);\n        }\n\n        float DoSearchResultPathGUI()\n        {\n            if (!hasSearchFilter)\n                return 0;\n\n            const float rowHeight = 18f;\n            const float minTreeViewHeight = 32;\n            float treeViewHeight = treeViewRect.height;\n\n            var names = m_ParentNamesForSelectedSearchResult;\n            names.Clear();\n            names.Add(\"Path:\");\n\n            if (m_TreeView.HasSelection())\n            {\n                int selectedID = m_TreeView.GetSelection()[0];\n                TransformPath.AddGameObjectNames(selectedID, names);\n\n                float maxHeight = Math.Max(0, treeViewHeight - minTreeViewHeight);\n                int maxNumVisibleRows = Mathf.FloorToInt(maxHeight / rowHeight);\n                int removeRows = names.Count - maxNumVisibleRows;\n                if (removeRows > 0)\n                {\n                    int index = names.Count / 2 - removeRows / 2;\n                    bool addElipsis = maxNumVisibleRows >= 2;\n                    names.RemoveRange(index, removeRows + (addElipsis ? 1 : 0));\n                    if (addElipsis)\n                        names.Insert(index, \"...\");\n                }\n            }\n\n            float height = names.Count * rowHeight;\n\n            Rect backgroundRect = treeViewRect;\n            backgroundRect.yMin += treeViewHeight - height;\n            GUI.Label(backgroundRect, GUIContent.none, EditorStyles.inspectorBig);\n\n            Rect rowRect = treeViewRect;\n            rowRect.xMin += 10f;\n            rowRect.height = rowHeight;\n            rowRect.y = treeViewRect.yMax - height + (rowHeight - EditorGUI.kSingleLineHeight) / 2;\n            for (int i = 0; i < names.Count; ++i)\n            {\n                GUI.Label(rowRect, names[i]);\n                rowRect.y += rowHeight;\n                if (i == 0)\n                    rowRect.xMin += 10f;\n            }\n\n            return height;\n        }\n\n        public void GetSelectedScenes(List<Scene> scenes)\n        {\n            foreach (var selectedID in treeViewState.selectedIDs)\n            {\n                var scene = EditorSceneManager.GetSceneByHandle(selectedID);\n\n                if (scene.IsValid())\n                {\n                    scenes.Add(scene);\n                }\n            }\n        }\n\n        static class TransformPath\n        {\n            public static void AddGameObjectNames(int gameObjectInstanceID, List<string> list)\n            {\n                var gameObject = InternalEditorUtility.GetObjectFromInstanceID(gameObjectInstanceID) as GameObject;\n                if (gameObject == null)\n                    return;\n\n                AddGameObjectNames(gameObject, list);\n            }\n\n            public static void AddGameObjectNames(GameObject target, List<string> list)\n            {\n                Transform transform = target.transform;\n                while (transform != null)\n                {\n                    list.Add(transform.gameObject.name);\n                    transform = transform.parent;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneHierarchyHooks.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing System;\nusing System.Runtime.InteropServices;\n\n\nnamespace UnityEditor.SceneManagement\n{\n    public static class SceneHierarchyHooks\n    {\n        [StructLayout(LayoutKind.Sequential)]\n        [UnityEngine.Bindings.NativeType(IntermediateScriptingStructName = \"SceneHierarchyHooks_SubSceneInfo\")]\n        public struct SubSceneInfo\n        {\n            public Transform transform;\n            public Scene scene;\n            [UnityEngine.Bindings.Ignore] public SceneAsset sceneAsset;\n            [UnityEngine.Bindings.Ignore] public string sceneName;  // TODO: remove when when we have changed our examples to use 'provideSubSceneName'\n            [UnityEngine.Bindings.Ignore] public Color32 color;\n\n            public bool isValid\n            {\n                get { return transform != null; }\n            }\n        }\n\n        public static Func<SubSceneInfo[]> provideSubScenes;\n        public static Func<SubSceneInfo, string> provideSubSceneName;\n        public static event Action<GenericMenu, GameObject> addItemsToGameObjectContextMenu;\n        public static event Action<GenericMenu, Scene> addItemsToSceneHeaderContextMenu;\n        public static event Action<GenericMenu, SubSceneInfo> addItemsToSubSceneHeaderContextMenu;\n        public static event Action<GenericMenu> addItemsToCreateMenu;\n\n        public static void ReloadAllSceneHierarchies()\n        {\n            foreach (var window in SceneHierarchyWindow.GetAllSceneHierarchyWindows())\n                window.sceneHierarchy.ReloadData();\n        }\n\n        static void RefreshSubSceneInfo()\n        {\n            if (SubSceneGUI.IsUsingSubScenes())\n                SubSceneGUI.FetchSubSceneInfo();\n        }\n\n        public static bool CanSetNewParent(Transform transform, Transform newParent)\n        {\n            if (transform == null)\n                throw new ArgumentNullException(\"transform\");\n\n            if (newParent == null)\n                return true;\n\n            RefreshSubSceneInfo();\n            var parentIsChild = SubSceneGUI.IsChildOrSameAsOtherTransform(newParent, transform);\n            return !parentIsChild;\n        }\n\n        public static bool CanMoveTransformToScene(Transform transform, Scene scene)\n        {\n            if (transform == null)\n                throw new ArgumentNullException(\"transform\");\n\n            if (!scene.IsValid())\n                throw new ArgumentException(\"The scene is not valid\", \"scene\");\n\n            RefreshSubSceneInfo();\n            var subSceneInfo = SubSceneGUI.GetSubSceneInfo(scene);\n            if (!subSceneInfo.isValid)\n                return true;  // scene is a root and is always valid to move into\n\n            if (transform == subSceneInfo.transform)\n                return false;  // cannot move a SubScene's transform parent into itself\n\n            return CanSetNewParent(transform, subSceneInfo.transform);\n        }\n\n        internal static void AddCustomGameObjectContextMenuItems(GenericMenu menu, GameObject gameObject)\n        {\n            addItemsToGameObjectContextMenu?.Invoke(menu, gameObject);\n        }\n\n        internal static void AddCustomSceneHeaderContextMenuItems(GenericMenu menu, Scene scene)\n        {\n            addItemsToSceneHeaderContextMenu?.Invoke(menu, scene);\n        }\n\n        internal static void AddCustomSubSceneHeaderContextMenuItems(GenericMenu menu, SubSceneInfo subSceneInfo)\n        {\n            addItemsToSubSceneHeaderContextMenu?.Invoke(menu, subSceneInfo);\n        }\n\n        internal static void AddCustomItemsToCreateMenu(GenericMenu menu)\n        {\n            addItemsToCreateMenu?.Invoke(menu);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneHierarchySortingWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class SceneHierarchySortingWindow : EditorWindow\n    {\n        public delegate void OnSelectCallback(InputData element);\n\n        private class Styles\n        {\n            public GUIStyle background = \"grey_border\";\n            public GUIStyle menuItem = \"MenuToggleItem\";\n        }\n\n        public class InputData\n        {\n            public string m_TypeName;\n            public string m_Name;\n            public bool m_Selected;\n        }\n\n        private static SceneHierarchySortingWindow s_SceneHierarchySortingWindow;\n        private static long s_LastClosedTime;\n        private static Styles s_Styles;\n\n        private List<InputData> m_Data;\n        private OnSelectCallback m_Callback;\n\n        const float kFrameWidth = 1f;\n\n        private float GetHeight()\n        {\n            return EditorGUI.kSingleLineHeight * m_Data.Count;\n        }\n\n        private float GetWidth()\n        {\n            float width = 0f;\n\n            foreach (InputData item in m_Data)\n            {\n                float itemWidth = 0;\n                itemWidth = s_Styles.menuItem.CalcSize(GUIContent.Temp(item.m_Name)).x;\n\n                if (itemWidth > width)\n                    width = itemWidth;\n            }\n            return width;\n        }\n\n        private void OnEnable()\n        {\n            AssemblyReloadEvents.beforeAssemblyReload += Close;\n            hideFlags = HideFlags.DontSave;\n            wantsMouseMove = true;\n        }\n\n        private void OnDisable()\n        {\n            AssemblyReloadEvents.beforeAssemblyReload -= Close;\n            s_LastClosedTime = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond;\n        }\n\n        internal static bool ShowAtPosition(Vector2 pos, List<InputData> data, OnSelectCallback callback)\n        {\n            // We could not use realtimeSinceStartUp since it is set to 0 when entering/exitting playmode, we assume an increasing time when comparing time.\n            long nowMilliSeconds = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond;\n            bool justClosed = nowMilliSeconds < s_LastClosedTime + 50;\n            if (!justClosed)\n            {\n                Event.current.Use();\n                if (s_SceneHierarchySortingWindow == null)\n                    s_SceneHierarchySortingWindow = CreateInstance<SceneHierarchySortingWindow>();\n                s_SceneHierarchySortingWindow.Init(pos, data, callback);\n                return true;\n            }\n            return false;\n        }\n\n        private void Init(Vector2 pos, List<InputData> data, OnSelectCallback callback)\n        {\n            // Has to be done before calling Show / ShowWithMode\n            //pos = GUIUtility.GUIToScreenPoint(pos);\n\n\n            Rect buttonRect = new Rect(pos.x, pos.y - 16, 16, 16); // fake a button: we know we are showing it below the bottonRect if possible\n            buttonRect = GUIUtility.GUIToScreenRect(buttonRect);\n            data.Sort(\n                delegate(InputData lhs, InputData rhs)\n                {\n                    return lhs.m_Name.CompareTo(rhs.m_Name);\n                });\n            m_Data = data;\n            m_Callback = callback;\n\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            var windowHeight = 2f * kFrameWidth + GetHeight();\n            var windowWidth = 2f * kFrameWidth + GetWidth();\n            var windowSize = new Vector2(windowWidth, windowHeight);\n\n            ShowAsDropDown(buttonRect, windowSize);\n        }\n\n        internal void OnGUI()\n        {\n            // We do not use the layout event\n            if (Event.current.type == EventType.Layout)\n                return;\n\n            if (Event.current.type == EventType.MouseMove)\n                Event.current.Use();\n\n            // Content\n            Draw();\n\n            // Background with 1 pixel border\n            GUI.Label(new Rect(0, 0, position.width, position.height), GUIContent.none, s_Styles.background);\n        }\n\n        private void Draw()\n        {\n            var drawPos = new Rect(kFrameWidth, kFrameWidth, position.width - 2 * kFrameWidth, EditorGUI.kSingleLineHeight);\n\n            foreach (InputData data in m_Data)\n            {\n                DrawListElement(drawPos, data);\n                drawPos.y += EditorGUI.kSingleLineHeight;\n            }\n        }\n\n        void DrawListElement(Rect rect, InputData data)\n        {\n            EditorGUI.BeginChangeCheck();\n            GUI.Toggle(rect, data.m_Selected, EditorGUIUtility.TempContent(data.m_Name), s_Styles.menuItem);\n            if (EditorGUI.EndChangeCheck())\n            {\n                m_Callback(data);\n                Close();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneHierarchyStageHandling.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.SceneManagement;\nusing UnityEditor.VersionControl;\nusing TreeViewGUI = UnityEditor.IMGUI.Controls.TreeViewGUI<int>;\n\n\nnamespace UnityEditor\n{\n    class SceneHierarchyStageHandling\n    {\n        static class Styles\n        {\n            public static GUIStyle stageHeaderBg;\n            public static GUIStyle leftArrow = \"ArrowNavigationLeft\";\n\n            static Styles()\n            {\n                stageHeaderBg = new GUIStyle(\"HeaderButton\");\n                stageHeaderBg.border = new RectOffset(3, 3, 3, 3);\n            }\n        }\n\n        SceneHierarchyWindow m_SceneHierarchyWindow;\n\n        GUIContent m_StageHeaderContent;\n        bool m_LastStageUnsavedChangesState;\n\n        Stage currentStage { get { return StageNavigationManager.instance.currentStage; } }\n\n        public SceneHierarchyStageHandling(SceneHierarchyWindow sceneHierarchyWindow)\n        {\n            m_SceneHierarchyWindow = sceneHierarchyWindow;\n        }\n\n        public void OnEnable()\n        {\n            StageNavigationManager.instance.stageChanged += OnStageChanged;\n            StageNavigationManager.instance.beforeSwitchingAwayFromStage += OnBeforeSwitchingAwayFromStage;\n\n            // To support expanded state of new unsaved GameObject in stages across domain reloading we do not load the\n            // last saved expanded state here but instead rely on the fact that the Hierarchy serializes its own expanded state already.\n            currentStage.SyncSceneHierarchyToStage(m_SceneHierarchyWindow);\n        }\n\n        public void OnDisable()\n        {\n            StageNavigationManager.instance.currentStage.SaveHierarchyState(m_SceneHierarchyWindow);\n\n            StageNavigationManager.instance.stageChanged -= OnStageChanged;\n            StageNavigationManager.instance.beforeSwitchingAwayFromStage -= OnBeforeSwitchingAwayFromStage;\n        }\n\n        void OnBeforeSwitchingAwayFromStage(Stage stage)\n        {\n            // Clear parent object for the prefab stage if one was set\n            if (stage is PrefabStage)\n                SceneHierarchy.SetDefaultParentForSession(stage.GetSceneAt(stage.sceneCount - 1).guid, 0);\n\n            stage.SaveHierarchyState(m_SceneHierarchyWindow);\n        }\n\n        void OnStageChanged(Stage previousStage, Stage newStage)\n        {\n            if (previousStage is MainStage)\n                previousStage.SaveHierarchyState(m_SceneHierarchyWindow); // Non-main stages are saved before they are destroyed\n            newStage.SyncSceneHierarchyToStage(m_SceneHierarchyWindow);\n\n            newStage.LoadHierarchyState(m_SceneHierarchyWindow);\n\n            m_StageHeaderContent = GUIContent.none; // Stage header content is being rebuild on demand in a OnGUI code path (required since it uses EditorStyles)\n\n            if (m_SceneHierarchyWindow.hasSearchFilter)\n            {\n                m_SceneHierarchyWindow.SetSearchFilter(string.Empty, m_SceneHierarchyWindow.searchMode, true);\n                m_SceneHierarchyWindow.UnfocusSearchField();\n            }\n        }\n\n        internal void CacheStageHeaderContent()\n        {\n            Stage stage = currentStage;\n            if (stage == null || !stage.isValid)\n            {\n                m_StageHeaderContent = GUIContent.none;\n                return;\n            }\n\n            m_StageHeaderContent = stage.CreateHeaderContent();\n            if (m_StageHeaderContent == null)\n                m_StageHeaderContent = new GUIContent(stage.GetType().Name);\n\n            // Make room for version control overlay icons.\n            // GUIStyles don't allow controlling the space between icon and text.\n            // We could add spacing by splitting text and icon into two rects and two draw operations,\n            // but just adding a space character is a lot simpler and ends up amounting to the same thing.\n            // This is cached text so there is minimal overhead.\n            if (VersionControlUtils.isVersionControlConnected)\n                m_StageHeaderContent.text = \" \" + m_StageHeaderContent.text;\n\n            if (stage.hasUnsavedChanges)\n                m_StageHeaderContent.text += \"*\";\n        }\n\n        static void ShowStageContextMenu(Stage stage)\n        {\n            GenericMenu menu = new GenericMenu();\n            stage.BuildContextMenuForStageHeader(menu);\n            if (menu.menuItems.Count > 0)\n                menu.ShowAsContext();\n        }\n\n        public void StageHeaderGUI(Rect rect)\n        {\n            var stage = currentStage;\n            if (stage == null || !stage.isValid)\n                return;\n\n            if (m_StageHeaderContent == null || m_StageHeaderContent == GUIContent.none || m_LastStageUnsavedChangesState == stage.hasUnsavedChanges)\n                CacheStageHeaderContent();\n            m_LastStageUnsavedChangesState = stage.hasUnsavedChanges;\n\n            // Background\n            GUI.Box(rect, GUIContent.none, Styles.stageHeaderBg);\n\n            Rect interactionRect = new Rect(\n                rect.x,\n                rect.y,\n                Styles.leftArrow.fixedWidth + Styles.leftArrow.margin.horizontal,\n                rect.height - 1); /*bottom borer*/\n\n            // Back button\n            if (Event.current.type == EventType.Repaint)\n            {\n                // Resets the fixed size to stretch the button\n                float oldW = Styles.leftArrow.fixedWidth, oldH = Styles.leftArrow.fixedHeight;\n\n                Styles.leftArrow.fixedWidth = 0; Styles.leftArrow.fixedHeight = 0;\n                Styles.leftArrow.Draw(interactionRect, GUIContent.none, interactionRect.Contains(Event.current.mousePosition), false, false, false);\n                Styles.leftArrow.fixedWidth = oldW; Styles.leftArrow.fixedHeight = oldH;\n            }\n\n            if (GUI.Button(interactionRect, GUIContent.none, GUIStyle.none))\n            {\n                StageNavigationManager.instance.NavigateBack(StageNavigationManager.Analytics.ChangeType.NavigateBackViaHierarchyHeaderLeftArrow);\n            }\n\n            // Options button\n            Rect optionsButtonRect = new Rect();\n            if (stage.showOptionsButton)\n            {\n                if (GameObjectTreeViewGUI.DoOptionsButton(rect, out optionsButtonRect))\n                {\n                    ShowStageContextMenu(stage);\n                }\n            }\n\n            // Icon and name (and context click on background)\n            EditorGUIUtility.SetIconSize(new Vector2(16, 16));\n            float contentWidth = TreeViewGUI.Styles.lineBoldStyle.CalcSize(m_StageHeaderContent).x;\n            float xStart = Styles.leftArrow.margin.left + Styles.leftArrow.fixedWidth;\n            float space = (optionsButtonRect.width > 0 ? optionsButtonRect.xMin : rect.width) - xStart;\n            float offsetFromStart = xStart + Mathf.Max(0, (space - contentWidth) / 2);\n            Rect labelRect = new Rect(offsetFromStart, rect.y + 2, space, 20);\n\n            if (GUI.Button(labelRect, m_StageHeaderContent, stage.isAssetMissing ? BreadcrumbBar.DefaultStyles.labelBoldMissing : BreadcrumbBar.DefaultStyles.labelBold))\n            {\n                Event evt = Event.current;\n                if (evt.button == 0)\n                {\n                    EditorGUIUtility.PingObject(AssetDatabase.LoadMainAssetAtPath(stage.assetPath));\n                }\n                else if (evt.button == 1)\n                {\n                    ShowStageContextMenu(stage);\n                }\n            }\n            EditorGUIUtility.SetIconSize(Vector2.zero);\n\n            // Version control overlay icons\n            if (VersionControlUtils.isVersionControlConnected && EditorUserSettings.hierarchyOverlayIcons)\n            {\n                Rect overlayRect = labelRect;\n                overlayRect.width = 16;\n                overlayRect.y += (overlayRect.height - 16) / 2;\n                overlayRect.height = 16;\n\n                // The source asset could have been deleted while open inside the stage so the library object might be null here (case 1086613)\n                var asset = AssetDatabase.LoadMainAssetAtPath(stage.assetPath);\n                if (asset != null)\n                    AssetsTreeViewGUI.OnIconOverlayGUI(asset.GetInstanceID(), overlayRect, true);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneHierarchyWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEditor.SceneManagement;\nusing UnityEngine.SceneManagement;\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    [EditorWindowTitle(title = \"Hierarchy\", useTypeNameAsIconName = true)]\n    internal class SceneHierarchyWindow : SearchableEditorWindow, IHasCustomMenu, IPropertySourceOpener, ISearchableContainer\n    {\n        public static SceneHierarchyWindow lastInteractedHierarchyWindow { get { return s_LastInteractedHierarchy; } }\n        static SceneHierarchyWindow s_LastInteractedHierarchy;\n        public static List<SceneHierarchyWindow> GetAllSceneHierarchyWindows() { return s_SceneHierarchyWindows; }\n        static List<SceneHierarchyWindow> s_SceneHierarchyWindows = new List<SceneHierarchyWindow>();\n\n        internal static SavedBool s_EnterRenameModeForNewGO = new SavedBool(\"SceneHierarchyWindow.RenameNewObjects\", true);\n\n        static class Styles\n        {\n            public const float kStageHeaderHeight = 25f;\n        }\n\n        [SerializeField]\n        SceneHierarchy m_SceneHierarchy;\n        SceneHierarchyStageHandling m_StageHandling;\n\n        [SerializeField]\n        string m_WindowGUID;\n        public string windowGUID { get { return m_WindowGUID; } }\n\n        public SceneHierarchy sceneHierarchy { get { return m_SceneHierarchy; } }\n\n        bool showingStageHeader { get { return !(StageNavigationManager.instance.currentStage is MainStage); } }\n\n        public string searchText => m_SearchFilter;\n\n        void Awake()\n        {\n            m_HierarchyType = HierarchyType.GameObjects;\n\n            if (string.IsNullOrEmpty(m_WindowGUID))\n                m_WindowGUID = GUID.Generate().ToString();\n\n            if (m_SceneHierarchy == null)\n                m_SceneHierarchy = new SceneHierarchy();\n\n            m_SceneHierarchy.Awake(this);\n        }\n\n        public override void OnEnable()\n        {\n            base.OnEnable();\n\n            s_LastInteractedHierarchy = this;\n            s_SceneHierarchyWindows.Add(this);\n\n            m_SceneHierarchy.position = treeViewRect; // ensure SceneHierarchy has a valid rect before initializing in OnEnable\n            m_SceneHierarchy.OnEnable();\n            m_StageHandling = new SceneHierarchyStageHandling(this);\n            m_StageHandling.OnEnable();\n\n            titleContent = GetLocalizedTitleContent();\n            wantsLessLayoutEvents = true;\n            wantsMouseEnterLeaveWindow = true;\n\n            PrefabUtility.prefabInstanceModificationCacheCleared += OnPrefabInstanceModificationCacheCleared;\n        }\n\n        private void OnPrefabInstanceModificationCacheCleared()\n        {\n            Repaint();\n        }\n\n        public override void OnDisable()\n        {\n            base.OnDisable();\n\n            s_SceneHierarchyWindows.Remove(this);\n\n            m_SceneHierarchy.OnDisable();\n            m_StageHandling.OnDisable();\n\n            PrefabUtility.prefabInstanceModificationCacheCleared -= OnPrefabInstanceModificationCacheCleared;\n        }\n\n        internal override void ClickedSearchField()\n        {\n            // End renaming any GameObjects (case 1078881)\n            m_SceneHierarchy.treeView.EndNameEditing(true);\n        }\n\n        void OnDestroy()\n        {\n            // Set another existing hierarchy as last interacted if available\n            if (s_LastInteractedHierarchy == this)\n            {\n                s_LastInteractedHierarchy = null;\n                foreach (var hierarchy in s_SceneHierarchyWindows)\n                    if (hierarchy != this)\n                        s_LastInteractedHierarchy = hierarchy;\n            }\n\n            m_SceneHierarchy.OnDestroy();\n        }\n\n        void OnBecameVisible()\n        {\n            m_SceneHierarchy.OnBecameVisible();\n        }\n\n        void OnLostFocus()\n        {\n            m_SceneHierarchy.OnLostFocus();\n        }\n\n        void OnSelectionChange()\n        {\n            m_SceneHierarchy.OnSelectionChange();\n        }\n\n        void OnHierarchyChange()\n        {\n            m_SceneHierarchy.OnHierarchyChange();\n        }\n\n        void OnProjectWasLoaded()\n        {\n            m_SceneHierarchy.OnProjectWasLoaded();\n        }\n\n        void OnQuit()\n        {\n            m_SceneHierarchy.OnQuit();\n        }\n\n        void OnGUI()\n        {\n            Rect sceneHierarchyRect = new Rect(0, 0, position.width, position.height);\n            Event evt = Event.current;\n            if (evt.type == EventType.MouseDown && sceneHierarchyRect.Contains(evt.mousePosition))\n            {\n                s_LastInteractedHierarchy = this;\n            }\n\n            DoToolbarLayout();\n            DoSceneHierarchy();\n\n            ExecuteCommands();\n        }\n\n        public Object hoveredObject => sceneHierarchy.treeView.hoveredItem != null ? Object.FindObjectFromInstanceID(sceneHierarchy.treeView.hoveredItem.id) : null;\n\n        public void ReloadData()\n        {\n            m_SceneHierarchy.ReloadData();\n        }\n\n        void DoSceneHierarchy()\n        {\n            if (showingStageHeader)\n            {\n                m_StageHandling.StageHeaderGUI(stageHeaderRect);\n            }\n\n            m_SceneHierarchy.OnGUI(treeViewRect);\n        }\n\n        Rect stageHeaderRect\n        {\n            get { return new Rect(0, EditorGUI.kWindowToolbarHeight, position.width, Styles.kStageHeaderHeight); }\n        }\n\n        Rect treeViewRect\n        {\n            get\n            {\n                float startY = EditorGUI.kWindowToolbarHeight + (showingStageHeader ? Styles.kStageHeaderHeight : 0);\n                return new Rect(0, startY, position.width, position.height - startY);\n            }\n        }\n\n        void DoToolbarLayout()\n        {\n            // Gameobject popup dropdown\n            GUILayout.BeginHorizontal(EditorStyles.toolbar);\n\n            m_SceneHierarchy.GameObjectCreateDropdownButton();\n\n            //Search field GUI\n            GUILayout.Space(6);\n\n            GUILayout.FlexibleSpace();\n            Event evt = Event.current;\n\n            // When searchfield has focus give keyboard focus to the tree view on Down/UpArrow\n            if (hasSearchFilterFocus && evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.DownArrow || evt.keyCode == KeyCode.UpArrow))\n            {\n                m_SceneHierarchy.SetFocusAndEnsureSelectedItem();\n                evt.Use();\n            }\n\n            SearchFieldGUI();\n\n            // Sortmethod GUI\n            if (m_SceneHierarchy.hasSortMethods)\n            {\n                m_SceneHierarchy.SortMethodsDropDownButton();\n            }\n\n            GUILayout.EndHorizontal();\n        }\n\n        void ExecuteCommands()\n        {\n            Event evt = Event.current;\n\n            if (evt.type != EventType.ExecuteCommand && evt.type != EventType.ValidateCommand)\n                return;\n\n            if (evt.commandName == \"Find\")\n            {\n                if (evt.type == EventType.ExecuteCommand)\n                    FocusSearchField();\n                evt.Use();\n            }\n            else if (evt.commandName == \"FrameSelected\")\n            {\n                if (evt.type == EventType.ExecuteCommand)\n                {\n                    FrameObject(Selection.activeInstanceID, false);\n                }\n                evt.Use();\n                GUIUtility.ExitGUI();\n            }\n        }\n\n        internal override void SetSearchFilter(string searchFilter, SearchableEditorWindow.SearchMode searchMode, bool setAll, bool delayed = false)\n        {\n            base.SetSearchFilter(searchFilter, searchMode, setAll, delayed);\n            m_SceneHierarchy.SetSearchFilter(searchFilter, (SearchableEditorWindow.SearchModeHierarchyWindow)searchMode);\n        }\n\n        // This method is being used by the EditorTests/TreeViewControl tests\n        internal int[] GetExpandedIDs()\n        {\n            return m_SceneHierarchy.GetExpandedIDs();\n        }\n\n        // This method is being used by the EditorTests/Searching tests\n        public string[] GetCurrentVisibleObjects()\n        {\n            return m_SceneHierarchy.GetCurrentVisibleObjects();\n        }\n\n        internal void SelectPrevious()\n        {\n            m_SceneHierarchy.SelectPrevious();\n        }\n\n        internal void SelectNext()\n        {\n            m_SceneHierarchy.SelectNext();\n        }\n\n        // Called from DockArea\n        protected virtual void ShowButton(Rect rect)\n        {\n            m_SceneHierarchy.DoWindowLockButton(rect);\n        }\n\n        public void SetExpandedRecursive(int id, bool expand)\n        {\n            m_SceneHierarchy.SetExpandedRecursive(id, expand);\n        }\n\n        internal void SetExpanded(int id, bool expand)\n        {\n            m_SceneHierarchy.ExpandTreeViewItem(id, expand);\n        }\n\n        public void FrameObject(int instanceID, bool ping)\n        {\n            // To be able to frame the object we need to clear the search filter\n            SetSearchFilter(\"\", SearchableEditorWindow.SearchMode.All, true);\n            UnfocusSearchField();\n            m_SceneHierarchy.FrameObject(instanceID, ping);\n        }\n\n        void OnSceneSelectionStateChanged(Scene selectedScene)\n        {\n            m_SceneHierarchy.customScenes = selectedScene.IsValid() ? new[] { selectedScene } : null;\n            Repaint();\n        }\n\n        public virtual void AddItemsToMenu(GenericMenu menu)\n        {\n            m_SceneHierarchy.AddItemsToWindowMenu(menu);\n        }\n\n        public void GetSelectedScenes(List<Scene> scenes)\n        {\n            m_SceneHierarchy.GetSelectedScenes(scenes);\n        }\n\n        internal static void RebuildStageHeaderInAll()\n        {\n            var sceneHierarchyWindows = SceneHierarchyWindow.GetAllSceneHierarchyWindows();\n            foreach (SceneHierarchyWindow sceneHierarchyWindow in sceneHierarchyWindows)\n                sceneHierarchyWindow.RebuildStageHeader();\n        }\n\n        internal static void ReloadAllHierarchyWindows()\n        {\n            var sceneHierarchyWindows = SceneHierarchyWindow.GetAllSceneHierarchyWindows();\n            foreach (SceneHierarchyWindow sceneHierarchyWindow in sceneHierarchyWindows)\n                sceneHierarchyWindow.ReloadData();\n        }\n\n        internal void RebuildStageHeader()\n        {\n            m_StageHandling.CacheStageHeaderContent();\n        }\n\n        [MenuItem(\"Edit/Paste Special/Paste as Child (Keep Local Transform) %#V\", false, 103)]\n        static void PasteAsChildKeepLocal() => ClipboardUtility.PasteGOAsChild(false);\n\n        [MenuItem(\"Edit/Paste Special/Paste as Child (Keep World Transform)\", false, 104)]\n        static void PasteAsChildKeepWorld() => ClipboardUtility.PasteGOAsChild(true);\n\n        [MenuItem(\"Edit/Paste Special/Paste as Child (Keep Local Transform) %#V\", true, 103)]\n        [MenuItem(\"Edit/Paste Special/Paste as Child (Keep World Transform)\", true, 104)]\n        static bool ValidatePasteAsChild() => ClipboardUtility.CanPasteAsChild();\n\n        internal static SceneHierarchyWindow GetSceneHierarchyWindowToFocusForNewGameObjects()\n        {\n            // Prioritize last interacted if showing (even if locked)\n            if (lastInteractedHierarchyWindow != null && lastInteractedHierarchyWindow.IsSelectedTab())\n                return lastInteractedHierarchyWindow;\n\n            var hierarchies = GetAllSceneHierarchyWindows();\n            if (hierarchies.Count == 0)\n                return null;\n\n            // Otherwise find any window that is showing\n            foreach (var hierarchy in hierarchies)\n            {\n                if (hierarchy.IsSelectedTab())\n                    return hierarchy;\n            }\n\n            // If none is showing then prefer the last interacted one\n            if (lastInteractedHierarchyWindow != null)\n                return lastInteractedHierarchyWindow;\n\n            // Otherwise use any\n            return hierarchies[0];\n        }\n\n        [UsedByNativeCode]\n        internal static void FrameAndRenameNewGameObject()\n        {\n            SceneHierarchyWindow hierarchyWindow = GetSceneHierarchyWindowToFocusForNewGameObjects();\n\n            if (hierarchyWindow == null)\n                return;\n\n            SceneHierarchy sceneHierarchy = hierarchyWindow.m_SceneHierarchy;\n\n            GameObject go = Selection.activeGameObject;\n\n            if (go != null)\n            {\n                sceneHierarchy.treeView?.Frame(go.GetInstanceID(), true, false);\n            }\n\n            if (s_EnterRenameModeForNewGO.value)\n            {\n                sceneHierarchy.RenameNewGO();\n            }\n        }\n\n        internal static void SwitchEnterRenameModeForNewGO()\n        {\n            s_EnterRenameModeForNewGO.value = !s_EnterRenameModeForNewGO.value;\n        }\n    }\n\n    internal abstract class HierarchySorting\n    {\n        public virtual GUIContent content { get { return null; } }\n    }\n\n    internal class TransformSorting : HierarchySorting\n    {\n        readonly ScalableGUIContent m_Content = new ScalableGUIContent(null, \"Transform Child Order\", \"DefaultSorting\");\n        public override GUIContent content { get { return m_Content; } }\n    }\n\n    internal class AlphabeticalSorting : HierarchySorting\n    {\n        readonly ScalableGUIContent m_Content = new ScalableGUIContent(null, \"Alphabetical Order\", \"AlphabeticalSorting\");\n        public override GUIContent content { get { return m_Content; } }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/EditorSceneManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing UnityEngine.SceneManagement;\n\nnamespace UnityEditor.SceneManagement\n{\n    public sealed partial class EditorSceneManager\n    {\n        public delegate void SceneManagerSetupRestoredCallback(Scene[] scenes);\n        public delegate void NewSceneCreatedCallback(Scene scene, NewSceneSetup setup, NewSceneMode mode);\n        public delegate void SceneOpeningCallback(string path, OpenSceneMode mode);\n        public delegate void SceneOpenedCallback(Scene scene, OpenSceneMode mode);\n        public delegate void SceneClosingCallback(Scene scene, bool removingScene);\n        public delegate void SceneClosedCallback(Scene scene);\n        public delegate void SceneSavingCallback(Scene scene, string path);\n        public delegate void SceneSavedCallback(Scene scene);\n        public delegate void SceneDirtiedCallback(Scene scene);\n\n        public static event SceneManagerSetupRestoredCallback sceneManagerSetupRestored\n        {\n            add => m_SceneManagerSetupRestoredEvent.Add(value);\n            remove => m_SceneManagerSetupRestoredEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<SceneManagerSetupRestoredCallback> m_SceneManagerSetupRestoredEvent = new EventWithPerformanceTracker<SceneManagerSetupRestoredCallback>($\"{nameof(EditorSceneManager)}.{nameof(sceneManagerSetupRestored)}\");\n\n        public static event NewSceneCreatedCallback newSceneCreated\n        {\n            add => m_NewSceneCreatedEvent.Add(value);\n            remove => m_NewSceneCreatedEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<NewSceneCreatedCallback> m_NewSceneCreatedEvent = new EventWithPerformanceTracker<NewSceneCreatedCallback>($\"{nameof(EditorSceneManager)}.{nameof(newSceneCreated)}\");\n\n        public static event SceneOpeningCallback sceneOpening\n        {\n            add => m_SceneOpeningEvent.Add(value);\n            remove => m_SceneOpeningEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<SceneOpeningCallback> m_SceneOpeningEvent = new EventWithPerformanceTracker<SceneOpeningCallback>($\"{nameof(EditorSceneManager)}.{nameof(sceneOpening)}\");\n\n        public static event SceneOpenedCallback sceneOpened\n        {\n            add => m_SceneOpenedEvent.Add(value);\n            remove => m_SceneOpenedEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<SceneOpenedCallback> m_SceneOpenedEvent = new EventWithPerformanceTracker<SceneOpenedCallback>($\"{nameof(EditorSceneManager)}.{nameof(sceneOpened)}\");\n\n        public static event SceneClosingCallback sceneClosing\n        {\n            add => m_SceneClosingEvent.Add(value);\n            remove => m_SceneClosingEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<SceneClosingCallback> m_SceneClosingEvent = new EventWithPerformanceTracker<SceneClosingCallback>($\"{nameof(EditorSceneManager)}.{nameof(sceneClosing)}\");\n\n        public static event SceneClosedCallback sceneClosed\n        {\n            add => m_SceneClosedEvent.Add(value);\n            remove => m_SceneClosedEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<SceneClosedCallback> m_SceneClosedEvent = new EventWithPerformanceTracker<SceneClosedCallback>($\"{nameof(EditorSceneManager)}.{nameof(sceneClosed)}\");\n        public static event SceneSavingCallback sceneSaving\n        {\n            add => m_SceneSavingEvent.Add(value);\n            remove => m_SceneSavingEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<SceneSavingCallback> m_SceneSavingEvent = new EventWithPerformanceTracker<SceneSavingCallback>($\"{nameof(EditorSceneManager)}.{nameof(sceneSaving)}\");\n        public static event SceneSavedCallback sceneSaved\n        {\n            add => m_SceneSavedEvent.Add(value);\n            remove => m_SceneSavedEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<SceneSavedCallback> m_SceneSavedEvent = new EventWithPerformanceTracker<SceneSavedCallback>($\"{nameof(EditorSceneManager)}.{nameof(sceneSaved)}\");\n        public static event SceneDirtiedCallback sceneDirtied\n        {\n            add => m_SceneDirtiedEvent.Add(value);\n            remove => m_SceneDirtiedEvent.Remove(value);\n        }\n        private static EventWithPerformanceTracker<SceneDirtiedCallback> m_SceneDirtiedEvent = new EventWithPerformanceTracker<SceneDirtiedCallback>($\"{nameof(EditorSceneManager)}.{nameof(sceneDirtied)}\");\n\n        [RequiredByNativeCode]\n        private static void Internal_SceneManagerSetupRestored(Scene[] scenes)\n        {\n            foreach (var evt in m_SceneManagerSetupRestoredEvent)\n                evt(scenes);\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_NewSceneCreated(Scene scene, NewSceneSetup setup, NewSceneMode mode)\n        {\n            foreach (var evt in m_NewSceneCreatedEvent)\n                evt(scene, setup, mode);\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_SceneOpening(string path, OpenSceneMode mode)\n        {\n            foreach (var evt in m_SceneOpeningEvent)\n                evt(path, mode);\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_SceneOpened(Scene scene, OpenSceneMode mode)\n        {\n            foreach (var evt in m_SceneOpenedEvent)\n                evt(scene, mode);\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_SceneClosing(Scene scene, bool removingScene)\n        {\n            foreach (var evt in m_SceneClosingEvent)\n                evt(scene, removingScene);\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_SceneClosed(Scene scene)\n        {\n            foreach (var evt in m_SceneClosedEvent)\n                evt(scene);\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_SceneSaving(Scene scene, string path)\n        {\n            foreach (var evt in m_SceneSavingEvent)\n                evt(scene, path);\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_SceneSaved(Scene scene)\n        {\n            foreach (var evt in m_SceneSavedEvent)\n                evt(scene);\n        }\n\n        [RequiredByNativeCode]\n        private static void Internal_SceneDirtied(Scene scene)\n        {\n            foreach (var evt in m_SceneDirtiedEvent)\n                evt(scene);\n        }\n\n        [RequiredByNativeCode]\n        private static Transform Internal_GetParentTransformForNewGameObjects()\n        {\n            var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();\n            if (prefabStage != null)\n                return prefabStage.prefabContentsRoot.transform;\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/SceneSetup.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\n\n// The setup information for a scene in the SceneManager.\n\nnamespace UnityEditor.SceneManagement\n{\n    [StructLayout(LayoutKind.Sequential)]\n    [Serializable]\n    public class SceneSetup\n    {\n        [SerializeField]\n        private string m_Path = null;\n        [SerializeField]\n        private bool m_IsLoaded = false;\n        [SerializeField]\n        private bool m_IsActive = false;\n        [SerializeField]\n        private bool m_IsSubScene = false;\n\n        public string path\n        {\n            get { return m_Path; }\n            set { m_Path = value; }\n        }\n\n        public bool isLoaded\n        {\n            get { return m_IsLoaded; }\n            set { m_IsLoaded = value; }\n        }\n\n        public bool isActive\n        {\n            get { return m_IsActive; }\n            set { m_IsActive = value; }\n        }\n\n        public bool isSubScene\n        {\n            get { return m_IsSubScene; }\n            set { m_IsSubScene = value; }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/AssetEvents.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor\n{\n    class AssetEvents : AssetPostprocessor\n    {\n        public delegate void AssetsChangedOnHDD(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths);\n        public static event AssetsChangedOnHDD assetsChangedOnHDD;\n\n        static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)\n        {\n            if (assetsChangedOnHDD != null)\n                assetsChangedOnHDD(importedAssets, deletedAssets, movedAssets, movedFromAssetPaths);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/AvatarConfigurationStage.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\n\nnamespace UnityEditor.SceneManagement\n{\n    [Serializable]\n    internal class AvatarConfigurationStage : PreviewSceneStage\n    {\n        AvatarEditor m_AvatarEditor;\n\n        string m_AssetPath;\n        public override string assetPath { get { return m_AssetPath; } }\n\n        GameObject m_GameObject;\n        public GameObject gameObject { get { return m_GameObject; } }\n\n        internal static AvatarConfigurationStage CreateStage(string assetPath, AvatarEditor avatarEditor)\n        {\n            AvatarConfigurationStage stage = CreateInstance<AvatarConfigurationStage>();\n            stage.Init(assetPath, avatarEditor);\n            return stage;\n        }\n\n        private void Init(string modelAssetPath, AvatarEditor avatarEditor)\n        {\n            m_AssetPath = modelAssetPath;\n            m_AvatarEditor = avatarEditor;\n        }\n\n        protected internal override bool OnOpenStage()\n        {\n            base.OnOpenStage();\n\n            if (!File.Exists(assetPath))\n            {\n                Debug.LogError(\"ActivateStage called on AvatarEditingStage with an invalid path: Model file not found \" + assetPath);\n                return false;\n            }\n\n            // Get Model Prefab\n            GameObject prefab = AssetDatabase.LoadMainAssetAtPath(assetPath) as GameObject;\n            if (prefab == null)\n                return false;\n\n            // Instantiate character\n            m_GameObject = Instantiate(prefab);\n            SceneManager.MoveGameObjectToScene(m_GameObject, scene);\n\n            return true;\n        }\n\n        protected override void OnCloseStage()\n        {\n            m_AvatarEditor.CleanupEditor();\n\n            base.OnCloseStage();\n        }\n\n        protected internal override void OnFirstTimeOpenStageInSceneView(SceneView sceneView)\n        {\n            Selection.activeObject = m_GameObject;\n\n            // Frame in scene view\n            sceneView.FrameSelected(false, true);\n\n            // Setup Scene view state\n            sceneView.sceneViewState.showFlares = false;\n            sceneView.sceneViewState.alwaysRefresh = false;\n            sceneView.sceneViewState.showFog = false;\n            sceneView.sceneViewState.showSkybox = false;\n            sceneView.sceneViewState.showImageEffects = false;\n            sceneView.sceneViewState.showParticleSystems = false;\n            sceneView.sceneLighting = false;\n        }\n\n        protected internal override GUIContent CreateHeaderContent()\n        {\n            return new GUIContent(\n                \"Avatar Configuration\",\n                EditorGUIUtility.IconContent(\"Avatar Icon\").image);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/BreadcrumbBar.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor.IMGUI.Controls\n{\n    class BreadcrumbBar\n    {\n        List<Item> m_Breadcrumbs = new List<Item>();\n\n        public static class DefaultStyles\n        {\n            public static GUIStyle label;\n            public static GUIStyle labelMissing;\n            public static GUIStyle labelBold;\n            public static GUIStyle labelBoldMissing;\n            public static GUIStyle background;\n            public static GUIStyle separatorLine = \"BreadcrumbsSeparator\";\n            public static GUIStyle separatorArrow = \"ArrowNavigationRight\";\n\n            static DefaultStyles()\n            {\n                label = new GUIStyle(EditorStyles.label);\n                label.alignment = TextAnchor.MiddleLeft;\n                label.margin = new RectOffset(0, 0, 0, 0);\n\n                labelMissing = new GUIStyle(label);\n                labelMissing.normal.textColor = GameObjectTreeViewGUI.GameObjectStyles.brokenPrefabLabel.normal.textColor;\n\n                labelBold = new GUIStyle(label);\n                labelBold.fontStyle = FontStyle.Bold;\n\n                labelBoldMissing = new GUIStyle(labelMissing);\n                labelBoldMissing.fontStyle = FontStyle.Bold;\n\n                background = new GUIStyle(\"ProjectBrowserTopBarBg\");\n                background.padding = new RectOffset(4, 4, 0, 0);\n                background.border = new RectOffset(3, 3, 3, 3);\n                background.fixedHeight = 25f;\n            }\n        }\n\n        public enum SeparatorStyle\n        {\n            None,\n            Line,\n            Arrow\n        }\n\n        public class Item\n        {\n            public GUIContent content { get; set; }\n            public GUIStyle guistyle { get; set; }\n            public object userdata { get; set; }\n            public SeparatorStyle separatorstyle { get; set; }\n        }\n\n        public event Action<Item> onBreadCrumbClicked = null;\n        public List<Item> breadcrumbs { get { return m_Breadcrumbs; } }\n\n        float lastBreadcrumbWidth { get; set; }\n\n        public void SetBreadCrumbs(List<Item> breadCrumbItems)\n        {\n            m_Breadcrumbs = breadCrumbItems;\n\n            // Set default style if needed\n            foreach (var item in m_Breadcrumbs)\n                if (item.guistyle == null)\n                    item.guistyle = DefaultStyles.label;\n\n            if (m_Breadcrumbs.Count > 0)\n            {\n                EditorGUIUtility.SetIconSize(new Vector2(16, 16));\n                var lastItem = m_Breadcrumbs[m_Breadcrumbs.Count - 1];\n                lastBreadcrumbWidth = lastItem.guistyle.CalcSize(lastItem.content).x;\n                EditorGUIUtility.SetIconSize(new Vector2(0, 0));\n            }\n        }\n\n        public void OnGUI()\n        {\n            EditorGUIUtility.SetIconSize(new Vector2(16, 16));\n            for (int i = 0; i < m_Breadcrumbs.Count; ++i)\n            {\n                Item item = m_Breadcrumbs[i];\n\n                if (item.separatorstyle != SeparatorStyle.None)\n                {\n                    var separatorGUIStyle = item.separatorstyle == SeparatorStyle.Arrow ? DefaultStyles.separatorArrow : DefaultStyles.separatorLine;\n                    GUILayout.Label(GUIContent.none, separatorGUIStyle);\n                }\n\n                // Ensures last breadcrumb does not shrink\n                var minWidth = (i == m_Breadcrumbs.Count - 1) ? lastBreadcrumbWidth : 32;\n\n                if (GUILayout.Button(item.content, item.guistyle, GUILayout.MinWidth(minWidth)))\n                {\n                    if (onBreadCrumbClicked != null)\n                        onBreadCrumbClicked(item);\n                }\n            }\n            GUILayout.FlexibleSpace();\n            EditorGUIUtility.SetIconSize(new Vector2(0, 0));\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/MainStage.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\n\nnamespace UnityEditor.SceneManagement\n{\n    public sealed class MainStage : Stage\n    {\n        static StateCache<MainStageHierarchyState> s_StateCache = new StateCache<MainStageHierarchyState>(\"Library/StateCache/MainStageHierarchy/\");\n\n        internal static MainStage CreateMainStage()\n        {\n            var mainStage = CreateInstance<MainStage>();\n            mainStage.name = \"MainStage\";\n            return mainStage;\n        }\n\n        internal override int sceneCount { get { return SceneManager.sceneCount; } }\n\n        internal override Scene GetSceneAt(int index)\n        {\n            return SceneManager.GetSceneAt(index);\n        }\n\n        protected internal override bool OnOpenStage()\n        {\n            // do nothing as the main stage is always in memory\n            return true;\n        }\n\n        protected override void OnCloseStage()\n        {\n            Debug.LogError(\"The MainStage should not be destroyed. This is not supported.\");\n        }\n\n        protected internal override GUIContent CreateHeaderContent()\n        {\n            return new GUIContent(\n                \"Scenes\",\n                EditorGUIUtility.IconContent(\"SceneAsset Icon\").image);\n        }\n\n        internal override BreadcrumbBar.Item CreateBreadcrumbItem()\n        {\n            BreadcrumbBar.Item item = base.CreateBreadcrumbItem();\n            item.separatorstyle = BreadcrumbBar.SeparatorStyle.None;\n            return item;\n        }\n\n        internal override ulong GetSceneCullingMask()\n        {\n            return SceneCullingMasks.MainStageSceneViewObjects;\n        }\n\n        internal override void SyncSceneViewToStage(SceneView sceneView)\n        {\n            sceneView.customScene = new Scene();\n            sceneView.customParentForNewGameObjects = null;\n\n            // NOTE: We always set overrideSceneCullingMask to ensure the gizmo handling in the Entities package works (in dots search for 'gizmo hack').\n            // This ensures normal picking works with the livelink since the SceneCullingMasks.MainStageSceneViewObjects is part of the mask while the gizmo bit is also set.\n            // When the gizmo hack is removed in dots we can set 'sceneView.overrideSceneCullingMask = 0'.\n            sceneView.overrideSceneCullingMask = GetSceneCullingMask();\n        }\n\n        internal override void SyncSceneHierarchyToStage(SceneHierarchyWindow sceneHierarchyWindow)\n        {\n            var sceneHierarchy = sceneHierarchyWindow.sceneHierarchy;\n            sceneHierarchy.customScenes = null;\n            sceneHierarchy.customParentForNewGameObjects = null;\n            sceneHierarchy.SetCustomDragHandler(null);\n        }\n\n        internal override void PlaceGameObjectInStage(GameObject rootGameObject)\n        {\n            if (rootGameObject.transform.parent != null)\n                throw new ArgumentException(\"GameObject has a transform parent, only root GameObjects are valid\", \"rootGameObject\");\n\n            if (StageUtility.GetStageHandle(rootGameObject) != StageUtility.GetMainStageHandle())\n                SceneManager.MoveGameObjectToScene(rootGameObject, SceneManager.GetActiveScene());\n        }\n\n        internal override void SaveHierarchyState(SceneHierarchyWindow hierarchyWindow)\n        {\n            if (!isValid)\n                return;\n\n            Hash128 key = StageUtility.CreateWindowAndStageIdentifier(hierarchyWindow.windowGUID, this);\n            var state = s_StateCache.GetState(key);\n            if (state == null)\n                state = new MainStageHierarchyState();\n            state.SaveStateFromHierarchy(hierarchyWindow, this);\n            s_StateCache.SetState(key, state);\n        }\n\n        MainStageHierarchyState GetStoredHierarchyState(SceneHierarchyWindow hierarchyWindow)\n        {\n            Hash128 key = StageUtility.CreateWindowAndStageIdentifier(hierarchyWindow.windowGUID, this);\n            return s_StateCache.GetState(key);\n        }\n\n        internal override void LoadHierarchyState(SceneHierarchyWindow hierarchy)\n        {\n            if (!isValid)\n                return;\n\n            var state = GetStoredHierarchyState(hierarchy);\n            if (state != null)\n                state.LoadStateIntoHierarchy(hierarchy, this);\n            else\n                OnFirstTimeOpenStageInSceneHierachyWindow(hierarchy);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/MainStageHierarchyState.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.SceneManagement;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\n\nnamespace UnityEditor\n{\n    [Serializable]\n    class MainStageHierarchyState\n    {\n        [SerializeField]\n        float m_ScrollY;\n        [SerializeField]\n        List<int> m_ExpandedSceneGameObjectInstanceIDs = new List<int>();\n        [SerializeField]\n        int m_LastClickedInstanceID;\n        [SerializeField]\n        string[] m_OpenSceneGUIDs = null;\n\n        public void SaveStateFromHierarchy(SceneHierarchyWindow hierarchy, Stage stage)\n        {\n            var lastClickedGameObject = EditorUtility.InstanceIDToObject(hierarchy.sceneHierarchy.treeViewState.lastClickedID) as GameObject;\n            m_LastClickedInstanceID = lastClickedGameObject != null ? lastClickedGameObject.GetInstanceID() : 0;\n            m_ExpandedSceneGameObjectInstanceIDs = hierarchy.sceneHierarchy.treeViewState.expandedIDs;\n\n            m_ScrollY = hierarchy.sceneHierarchy.treeViewState.scrollPos.y;\n\n            m_OpenSceneGUIDs = GetCurrentSceneGUIDs();\n\n            if (SceneHierarchy.s_DebugPersistingExpandedState)\n                DebugLog(\"Saving\", stage);\n        }\n\n        public void LoadStateIntoHierarchy(SceneHierarchyWindow hierarchy, Stage stage)\n        {\n            // Restore expanded state always\n            hierarchy.sceneHierarchy.treeViewState.expandedIDs = m_ExpandedSceneGameObjectInstanceIDs;\n\n            // Restore selection and scroll value when requested\n            if (stage.setSelectionAndScrollWhenBecomingCurrentStage)\n            {\n                Selection.activeInstanceID = m_LastClickedInstanceID;\n\n                // We only want to set scroll position if none of the scene that were open\n                // when the scroll was recorded have been closed in the mean time.\n                // (Why do we apply selection and expanded state regardless then?\n                // Because for those it still make sense to apply it even if only\n                // some of the scenes that were open originally are still open, and\n                // for the rest it will have no effect anyway.)\n                bool anyOfScenesWereClosed = false;\n                if (m_OpenSceneGUIDs != null)\n                {\n                    var currentSceneGUIDs = GetCurrentSceneGUIDs();\n                    for (int i = 0; i < m_OpenSceneGUIDs.Length; i++)\n                    {\n                        if (!currentSceneGUIDs.Contains(m_OpenSceneGUIDs[i]))\n                        {\n                            anyOfScenesWereClosed = true;\n                            break;\n                        }\n                    }\n                }\n                if (!anyOfScenesWereClosed)\n                    hierarchy.sceneHierarchy.treeViewState.scrollPos.y = m_ScrollY;\n            }\n\n            if (SceneHierarchy.s_DebugPersistingExpandedState)\n                DebugLog(\"Restoring\", stage);\n        }\n\n        void DebugLog(string prefix, Stage stage)\n        {\n            Debug.Log(prefix + (stage.GetType().ToString()) + string.Format(\"-main stage: {0}, -scrollY: {1}, -selection {2}, -setSelection {3}\",\n                DebugUtils.ListToString(m_ExpandedSceneGameObjectInstanceIDs),\n                m_ScrollY,\n                m_LastClickedInstanceID,\n                stage.setSelectionAndScrollWhenBecomingCurrentStage));\n        }\n\n        string[] GetCurrentSceneGUIDs()\n        {\n            int count = SceneManager.sceneCount;\n            string[] sceneGUIDs = new string[count];\n            for (int i = 0; i < count; i++)\n                sceneGUIDs[i] = SceneManager.GetSceneAt(i).guid;\n            return sceneGUIDs;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Collections.ObjectModel;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor.Callbacks;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEngine.Assertions;\nusing UnityEngine.SceneManagement;\nusing UnityEngine.Scripting.APIUpdating;\nusing TreeViewDragging = UnityEditor.IMGUI.Controls.TreeViewDragging<int>;\n\nnamespace UnityEditor.SceneManagement\n{\n    [Serializable]\n    [MovedFrom(\"UnityEditor.Experimental.SceneManagement\")]\n    public sealed partial class PrefabStage : PreviewSceneStage\n    {\n        static class Styles\n        {\n            public static GUIContent autoSaveGUIContent = EditorGUIUtility.TrTextContent(\"Auto Save\", \"When Auto Save is enabled, every change you make is automatically saved to the Prefab Asset. Disable Auto Save if you experience long import times.\");\n            public static GUIContent saveButtonContent = EditorGUIUtility.TrTextContent(\"Save\");\n            public static GUIContent checkoutButtonContent = EditorGUIUtility.TrTextContent(\"Check Out\");\n            public static GUIContent autoSavingBadgeContent = EditorGUIUtility.TrTextContent(\"Auto Saving...\");\n            public static GUIContent immutablePrefabContent = EditorGUIUtility.TrTextContent(\"Immutable Prefab\");\n            public static GUIStyle saveToggle;\n            public static GUIStyle button;\n            public static GUIStyle savingBadge = \"Badge\";\n            public static GUIStyle exposablePopup = \"ExposablePopupMenu\";\n            public static GUIStyle exposablePopupItem = \"ExposablePopupItem\";\n            public static GUIContent contextLabel = EditorGUIUtility.TrTextContent(\"Context:\");\n            public static GUIContent[] contextRenderModeTexts = new[] { EditorGUIUtility.TrTextContent(\"Normal\"), EditorGUIUtility.TrTextContent(\"Gray\"), EditorGUIUtility.TrTextContent(\"Hidden\") };\n            public static StageUtility.ContextRenderMode[] contextRenderModeOptions = new[] { StageUtility.ContextRenderMode.Normal, StageUtility.ContextRenderMode.GreyedOut, StageUtility.ContextRenderMode.Hidden };\n            public static GUIContent showOverridesLabel = EditorGUIUtility.TrTextContent(\"Show Overrides\", \"Visualize property overrides from the Prefab instance on the Prefab Asset. Overrides on the root Transform are always visualized.\");\n            public static GUIContent showOverridesLabelWithTooManyOverridesTooltip = EditorGUIUtility.TrTextContent(\"Show Overrides\", \"Show Overrides are disabled because there are too many overrides to visualize. Overrides on the root Transform are always visualized though.\");\n\n            static Styles()\n            {\n                saveToggle = EditorStyles.toggle;\n\n                button = EditorStyles.miniButton;\n                button.margin.top = button.margin.bottom = 0;\n            }\n        }\n\n        internal static string s_PrefabInContextPreviewValuesTooltip = L10n.Tr(\"This property is previewing the overridden value on the Prefab instance.\\n\\nTo edit this property, open this Prefab Asset in isolation by pressing the modifier key [Alt] while you open it.\");\n\n        public enum Mode\n        {\n            InIsolation,\n            InContext\n        }\n\n        public static event Action<PrefabStage> prefabStageOpened;\n        public static event Action<PrefabStage> prefabStageClosing;\n        public static event Action<PrefabStage> prefabStageDirtied;\n        public static event Action<GameObject> prefabSaving;\n        public static event Action<GameObject> prefabSaved;\n\n        internal static event Action<PrefabStage> prefabStageSavedAsNewPrefab;\n        internal static event Action<PrefabStage> prefabStageReloaded; // Used by tests.\n\n        internal static List<PrefabStage> m_AllPrefabStages = new List<PrefabStage>();\n        static StateCache<PrefabStageHierarchyState> s_StateCache = new StateCache<PrefabStageHierarchyState>(\"Library/StateCache/PrefabStageHierarchy/\");\n\n        GameObject m_PrefabContentsRoot; // Prefab asset being edited\n        string m_PrefabAssetPath;\n        GameObject m_OpenedFromInstanceRoot;\n        GameObject m_OpenedFromInstanceObject;\n        ulong m_FileIdForOpenedFromInstanceObject;\n        Stage m_ContextStage = null;\n        Mode m_Mode;\n        int m_InitialSceneDirtyID;\n        int m_LastSceneDirtyID;\n        bool m_IgnoreNextAssetImportedEventForCurrentPrefab;\n        bool m_PrefabWasChangedOnDisk;\n        bool m_StageDirtiedFired;\n        bool m_IsPrefabInImmutableFolder;\n        bool m_IsPrefabInValidAssetFolder;\n        HideFlagUtility m_HideFlagUtility;\n        Texture2D m_PrefabFileIcon;\n        bool m_TemporarilyDisableAutoSave;\n        float m_LastSavingDuration = 0f;\n        Transform m_LastRootTransform;\n        const float kDurationBeforeShowingSavingBadge = 1.0f;\n        static ExposablePopupMenu s_ContextRenderModeSelector;\n        Hash128 m_InitialFileHash;\n        byte[] m_InitialFileContent;\n        Hash128 m_LastPrefabSourceFileHash;\n        bool m_NeedsReloadingWhenReturningToStage;\n        bool m_IsAssetMissing;\n        bool m_TemporarilyDisablePatchAllOverridenProperties;\n        const int k_MaxNumberOfOverridesToVisualize = 2000;\n\n        internal static SavedBool s_PatchAllOverriddenProperties = new SavedBool(\"InContextEditingPatchOverriddenProperties\", false);\n\n        [System.Serializable]\n        struct PatchedProperty\n        {\n            public PropertyModification modification;\n            public UnityEngine.Object targetInContent;\n        }\n        List<PatchedProperty> m_PatchedProperties;\n\n        bool m_AnalyticsDidUserModify;\n        bool m_AnalyticsDidUserSave;\n\n        internal static PrefabStage CreatePrefabStage(string prefabAssetPath, GameObject openedFromInstanceObject, PrefabStage.Mode prefabStageMode, Stage contextStage)\n        {\n            PrefabStage prefabStage = CreateInstance<PrefabStage>();\n            try\n            {\n                prefabStage.OneTimeInitialize(prefabAssetPath, openedFromInstanceObject, prefabStageMode, contextStage);\n            }\n            catch\n            {\n                DestroyImmediate(prefabStage);\n                throw;\n            }\n            return prefabStage;\n        }\n\n        // Used for tests, if nothing else.\n        internal static ReadOnlyCollection<PrefabStage> allPrefabStages { get { return m_AllPrefabStages.AsReadOnly(); } }\n\n        private PrefabStage()\n        {\n        }\n\n        void OneTimeInitialize(string prefabAssetPath, GameObject openedFromInstanceGameObject, PrefabStage.Mode prefabStageMode, Stage contextStage)\n        {\n            if (scene.IsValid())\n                Debug.LogError(\"PrefabStage is already initialized. Please report a bug.\");\n\n            m_PrefabAssetPath = prefabAssetPath;\n            CachePrefabFolderInfo();\n            SetOpenedFromInstanceObject(openedFromInstanceGameObject);\n\n            if (prefabStageMode == PrefabStage.Mode.InContext)\n                m_ContextStage = contextStage;\n            m_Mode = prefabStageMode;\n        }\n\n        bool IsOpenedFromInstanceObjectValid()\n        {\n            return m_OpenedFromInstanceObject != null && PrefabUtility.IsPartOfPrefabInstance(m_OpenedFromInstanceObject);\n        }\n\n        static GameObject FindPrefabInstanceRootThatMatchesPrefabAssetPath(GameObject prefabInstanceObject, string prefabAssetPath)\n        {\n            if (prefabInstanceObject == null)\n                throw new ArgumentNullException(nameof(prefabInstanceObject));\n\n            if (string.IsNullOrEmpty(prefabAssetPath))\n                throw new ArgumentNullException(nameof(prefabAssetPath));\n\n            if (PrefabUtility.GetCorrespondingObjectFromSourceAtPath(prefabInstanceObject, prefabAssetPath) == null)\n            {\n                //Variants with broken parents\n                if (AssetDatabase.LoadMainAssetAtPath(prefabAssetPath) is BrokenPrefabAsset)\n                    return prefabInstanceObject;\n                else\n                    throw new ArgumentException($\"'{nameof(prefabInstanceObject)}' is not related to the Prefab at path: '{prefabAssetPath}'\");\n            }\n\n            Transform transform = prefabInstanceObject.transform;\n            while (transform != null)\n            {\n                var assetObject = PrefabUtility.GetCorrespondingObjectFromSourceAtPath(transform, prefabAssetPath);\n                if (assetObject != null && assetObject.parent == null)\n                    return transform.gameObject;\n\n                transform = transform.parent;\n            }\n\n            return null;\n        }\n\n        void SetOpenedFromInstanceObject(GameObject go)\n        {\n            if (go != null)\n            {\n                if (!PrefabUtility.IsPartOfPrefabInstance(go))\n                    throw new ArgumentException(\"Prefab Mode: GameObject must be part of a Prefab instance, or null.\", nameof(go));\n\n                m_OpenedFromInstanceObject = go;\n                m_OpenedFromInstanceRoot = FindPrefabInstanceRootThatMatchesPrefabAssetPath(go, m_PrefabAssetPath);\n                if (m_OpenedFromInstanceRoot == null)\n                    throw new ArgumentException($\"Prefab Mode: The 'openedFromInstance' GameObject '{go.name}' is unrelated to the Prefab Asset '{m_PrefabAssetPath}'.\");\n\n                m_FileIdForOpenedFromInstanceObject = Unsupported.GetOrGenerateFileIDHint(go);\n            }\n            else\n            {\n                m_OpenedFromInstanceObject = null;\n                m_OpenedFromInstanceRoot = null;\n                m_FileIdForOpenedFromInstanceObject = 0;\n            }\n        }\n\n        void ReconstructInContextStateIfNeeded()\n        {\n            // The previous PrefabStage can have been reloaded if user chose to discard changes when entering this PrefabStage,\n            // which means we need to update our reference to m_OpenedFromInstanceObject to the newly loaded GameObject\n            // (the old GameObject was deleted as part of reloading the PrefabStage).\n            bool needsReconstruction = m_OpenedFromInstanceObject == null && m_FileIdForOpenedFromInstanceObject != 0;\n            if (!needsReconstruction)\n                return;\n\n            var history = StageNavigationManager.instance.stageHistory;\n            int index = history.IndexOf(this);\n            int previousIndex = index - 1;\n            var previousStage = history[previousIndex];\n            var previousPrefabStage = previousStage as PrefabStage;\n            if (previousPrefabStage)\n            {\n                var go = PrefabStageUtility.FindFirstGameObjectThatMatchesFileID(previousPrefabStage.prefabContentsRoot.transform, m_FileIdForOpenedFromInstanceObject, true);\n                if (go != null)\n                {\n                    if (PrefabUtility.IsPartOfPrefabInstance(go))\n                        SetOpenedFromInstanceObject(go);\n                }\n                else\n                {\n                    // Could not find GameObject with fileID: m_FileIdForOpenedFromInstanceObject, this can happen if inserting a variant parent in a Variant and then discarding changes when entering in-context of the new base\n                }\n            }\n        }\n\n        internal bool analyticsDidUserModify { get { return m_AnalyticsDidUserModify; } }\n        internal bool analyticsDidUserSave { get { return m_AnalyticsDidUserSave; } }\n\n        static class Icons\n        {\n            public static Texture2D prefabVariantIcon = EditorGUIUtility.LoadIconRequired(\"PrefabVariant Icon\");\n            public static Texture2D prefabIcon = EditorGUIUtility.LoadIconRequired(\"Prefab Icon\");\n        }\n\n        protected override void OnEnable()\n        {\n            base.OnEnable();\n            PrefabUtility.savingPrefab += OnSavingPrefab;\n            PrefabUtility.prefabInstanceUpdated += OnPrefabInstanceUpdated;\n            AssetEvents.assetsChangedOnHDD += OnAssetsChangedOnHDD;\n            Undo.undoRedoEvent += UndoRedoPerformed;\n            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;\n\n            m_AllPrefabStages.Add(this);\n        }\n\n        protected override void OnDisable()\n        {\n            base.OnDisable();\n            PrefabUtility.savingPrefab -= OnSavingPrefab;\n            PrefabUtility.prefabInstanceUpdated -= OnPrefabInstanceUpdated;\n            AssetEvents.assetsChangedOnHDD -= OnAssetsChangedOnHDD;\n            Undo.undoRedoEvent -= UndoRedoPerformed;\n            EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;\n\n            // Also cleanup any potential registered event handlers\n            EditorApplication.update -= DelayedFraming;\n            EditorApplication.update -= PerformDelayedAutoSave;\n\n            m_AllPrefabStages.Remove(this);\n        }\n\n        public GameObject prefabContentsRoot\n        {\n            get\n            {\n                if (m_PrefabContentsRoot == null)\n                    throw new InvalidOperationException(\"Requesting 'prefabContentsRoot' from Awake and OnEnable is not supported\"); // The Prefab stage's m_PrefabContentsRoot is not yet set when we call Awake and OnEnable on user scripts when loading a Prefab\n                return m_PrefabContentsRoot;\n            }\n        }\n\n        public GameObject openedFromInstanceRoot\n        {\n            get { return m_OpenedFromInstanceRoot; }\n        }\n\n        public GameObject openedFromInstanceObject\n        {\n            get { return m_OpenedFromInstanceObject; }\n        }\n\n        public Mode mode\n        {\n            get { return m_Mode; }\n        }\n\n        bool isCurrentStage\n        {\n            get { return StageUtility.GetCurrentStage() == this; }\n        }\n\n        public override ulong GetCombinedSceneCullingMaskForCamera()\n        {\n            if (m_Mode == Mode.InIsolation)\n            {\n                return GetSceneCullingMask();\n            }\n            else if (m_Mode == Mode.InContext)\n            {\n                var stageHistory = StageNavigationManager.instance.stageHistory;\n                if (this == stageHistory.Last())\n                {\n                    ulong mask = GetSceneCullingMask();\n                    int count = stageHistory.Count;\n                    for (int i = count - 2; i >= 0; i--)\n                    {\n                        var stage = stageHistory[i];\n                        if (stage)\n                        {\n                            mask |= stage.GetSceneCullingMask();\n\n                            var prefabStage = stage as PrefabStage;\n                            if (prefabStage)\n                            {\n                                if (prefabStage.mode != Mode.InContext)\n                                    break;\n                            }\n                        }\n                    }\n\n                    // Remove the MainStagePrefabInstanceObjectsOpenInPrefabMode bit from the camera's scenecullingmask. By removing that bit we ensure we hide the MainStage Prefab instance\n                    // when editing its Prefab Asset in context. Since the MainStage Prefab instance GameObjects have the MainStagePrefabInstanceObjectsOpenInPrefabMode\n                    // set when as override-scenecullingmask when entering Prefab Mode in Context for MainStage instances.\n                    mask &= ~SceneCullingMasks.MainStagePrefabInstanceObjectsOpenInPrefabMode;\n                    return mask;\n                }\n                else\n                {\n                    Debug.LogError(\"We should only call GetOverrideSceneCullingMask() for the current stage\");\n                    return 0;\n                }\n            }\n            else\n            {\n                Debug.LogError(\"Unhandled PrefabStage.Mode\");\n                return 0;\n            }\n        }\n\n        internal override Stage GetContextStage()\n        {\n            if (m_ContextStage != null)\n                return m_ContextStage;\n            return this;\n        }\n\n        internal override Color GetBackgroundColor()\n        {\n            // Case 1255995 - Workaround for OSX 10.15 driver issue with Intel 630 cards\n            Color opaqueBackground = SceneView.kSceneViewPrefabBackground.Color;\n            opaqueBackground.a = 1;\n            return opaqueBackground;\n        }\n\n        public bool IsPartOfPrefabContents(GameObject gameObject)\n        {\n            if (gameObject == null)\n                return false;\n            Transform tr = gameObject.transform;\n            Transform instanceRootTransform = prefabContentsRoot.transform;\n            while (tr != null)\n            {\n                if (tr == instanceRootTransform)\n                    return true;\n                tr = tr.parent;\n            }\n            return false;\n        }\n\n        internal override bool showOptionsButton { get { return true; } }\n\n        public override string assetPath { get { return m_PrefabAssetPath; } }\n\n        internal override bool SupportsSaving() { return true; }\n        internal override bool hasUnsavedChanges { get { return scene.dirtyID != m_InitialSceneDirtyID; } }\n\n        internal bool showingSavingLabel\n        {\n            get;\n            private set;\n        }\n\n        internal Texture2D prefabFileIcon\n        {\n            get { return m_PrefabFileIcon; }\n        }\n\n        string GetPrefabFileName()\n        {\n            return Path.GetFileNameWithoutExtension(m_PrefabAssetPath);\n        }\n\n        internal bool autoSave\n        {\n            get\n            {\n                return EditorSettings.prefabModeAllowAutoSave && !m_TemporarilyDisableAutoSave && StageNavigationManager.instance.autoSave;\n            }\n            set\n            {\n                if (!EditorSettings.prefabModeAllowAutoSave)\n                    return;\n                m_TemporarilyDisableAutoSave = false;\n                StageNavigationManager.instance.autoSave = value;\n            }\n        }\n\n        internal bool temporarilyDisableAutoSave\n        {\n            get { return m_TemporarilyDisableAutoSave || isAssetMissing; }\n        }\n\n        internal override bool isValid\n        {\n            get { return m_PrefabContentsRoot != null && m_PrefabContentsRoot.scene == scene; }\n        }\n\n        internal override bool isAssetMissing\n        {\n            get { return m_IsAssetMissing; }\n        }\n\n        void OnPrefabInstanceUpdated(GameObject instance)\n        {\n            if (mode == Mode.InContext && m_OpenedFromInstanceRoot != null)\n            {\n                // We check against the outerMostInstanceRoot since that is what will be updated when\n                // we change that or any nested prefabs. E.g having PrefabA instance (that have nested PrefabB) in the Scene and we can enter\n                // Prefab Mode in Context for prefabB from the scene. Then adding a child; it will then be instanceA that will need to have\n                // its objects visibility updated.\n                var outerMostInstanceRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(m_OpenedFromInstanceRoot);\n                bool canHaveChangedCurrentlyHiddenObjects = outerMostInstanceRoot == instance;\n                if (canHaveChangedCurrentlyHiddenObjects)\n                {\n                    SetPrefabInstanceHiddenForInContextEditing(true); // if new GameObjects was added to the instance this will ensure to mark them hidden as well\n                }\n            }\n        }\n\n        void SetPrefabInstanceHiddenForInContextEditing(bool hide)\n        {\n            // In Playmode all instances have been unpacked so we need to check if the PrefabInstanceHandle have been deleted\n            if (m_OpenedFromInstanceRoot != null && PrefabUtility.GetPrefabInstanceHandle(m_OpenedFromInstanceRoot) != null)\n                StageUtility.SetPrefabInstanceHiddenForInContextEditing(m_OpenedFromInstanceRoot, hide);\n        }\n\n        void UpdateSortableComponentsWithStagePriority(int stagePriority)\n        {\n            List<Renderer> rendererList = new List<Renderer>();\n            List<Canvas> canvasList = new List<Canvas>();\n\n            // Renderer components requires to know there is stage priority when entering context and isolation\n            // mode. If this is not shared, their sorting order will not be evaluated accordingly since they are not\n            // in the same layer.\n            m_PrefabContentsRoot.GetComponentsInChildren<Renderer>(true, rendererList);\n            m_PrefabContentsRoot.GetComponentsInChildren<Canvas>(true, canvasList);\n\n            foreach (Renderer renderer in rendererList)\n                renderer.stagePriority = (byte)stagePriority;\n\n            foreach (Canvas canvas in canvasList)\n                canvas.stagePriority = (byte)stagePriority;\n        }\n\n        bool LoadStage()\n        {\n            if (scene.IsValid())\n            {\n                Debug.LogError(\"LoadStage: we haven't cleared the previous scene before loading a new scene\");\n                return false;\n            }\n\n            if (!File.Exists(m_PrefabAssetPath))\n            {\n                Debug.LogError(\"LoadStage: Prefab file not found \" + m_PrefabAssetPath);\n                return false;\n            }\n\n            ReconstructInContextStateIfNeeded();\n            if (m_Mode == Mode.InContext && !IsOpenedFromInstanceObjectValid())\n            {\n                // The Prefab instance used for opening Prefab Mode In Context has become invalid. Opening in Isolation instead.\n                SetOpenedFromInstanceObject(null);\n                m_ContextStage = null;\n                m_Mode = Mode.InIsolation;\n            }\n\n            // Ensure scene is set before calling LoadPrefabIntoPreviewScene() so the user can request the current\n            // the PrefabStage in their OnEnable and other callbacks (if they use ExecuteInEditMode or ExecuteAlways)\n            bool isUIPrefab = PrefabStageUtility.IsUIPrefab(m_PrefabAssetPath);\n\n            switch (m_Mode)\n            {\n                case Mode.InIsolation:\n                    scene = PrefabStageUtility.GetEnvironmentSceneOrEmptyScene(isUIPrefab);\n                    break;\n                case Mode.InContext:\n                    scene = EditorSceneManager.NewPreviewScene();\n                    break;\n                default:\n                    Debug.LogError(\"Unhandled enum\");\n                    break;\n            }\n\n            m_PrefabContentsRoot = PrefabStageUtility.LoadPrefabIntoPreviewScene(m_PrefabAssetPath, scene);\n            if (m_PrefabContentsRoot != null)\n            {\n                scene.SetPathAndGuid(m_PrefabAssetPath, AssetDatabase.AssetPathToGUID(m_PrefabAssetPath));\n                // Corresponds to which breadcrumb this is.\n                var stagePriority = StageNavigationManager.instance.stageHistory.IndexOf(this);\n\n                if (isUIPrefab)\n                {\n                    UpdateSortableComponentsWithStagePriority(stagePriority);\n\n                    if (m_Mode == Mode.InIsolation && m_PrefabContentsRoot.transform.parent == null)\n                        PrefabStageUtility.HandleUIReparentingIfNeeded(m_PrefabContentsRoot, stagePriority);\n                }\n\n                m_PrefabFileIcon = DeterminePrefabFileIconFromInstanceRootGameObject();\n                m_LastRootTransform = m_PrefabContentsRoot.transform;\n                m_InitialSceneDirtyID = scene.dirtyID;\n                m_StageDirtiedFired = false;\n                UpdateEnvironmentHideFlags();\n\n                if (m_Mode == Mode.InContext)\n                {\n                    SetPrefabInstanceHiddenForInContextEditing(true);\n\n                    Transform instanceParent = openedFromInstanceRoot.transform.parent;\n                    if (instanceParent != null)\n                    {\n                        // Insert dummy parent which ensure Prefab contents is aligned same as Prefab instance.\n                        GameObject dummyParent = new GameObject(PrefabUtility.kDummyPrefabStageRootObjectName);\n                        EditorSceneManager.MoveGameObjectToScene(dummyParent, scene);\n                        dummyParent.transform.SetParent(m_PrefabContentsRoot.transform.parent, false);\n\n                        // Make Prefab content parent match alignment of Prefab instance parent.\n                        // This code doesn't reliably handle cases where the parent matrix is non-orthogonal.\n                        dummyParent.transform.localScale = instanceParent.lossyScale;\n                        dummyParent.transform.rotation = instanceParent.rotation;\n                        dummyParent.transform.position = instanceParent.position;\n\n                        RectTransform instanceRectParent = instanceParent as RectTransform;\n                        if (instanceRectParent != null)\n                        {\n                            RectTransform rect = dummyParent.AddComponent<RectTransform>();\n                            rect.sizeDelta = instanceRectParent.rect.size;\n                            rect.pivot = instanceRectParent.pivot;\n                            Canvas dummyCanvas = dummyParent.AddComponent<Canvas>();\n                            Canvas instanceCanvas = openedFromInstanceRoot.GetComponentInParent<Canvas>();\n                            if (instanceCanvas != null)\n                            {\n                                dummyCanvas.sortingOrder = instanceCanvas.sortingOrder;\n                                dummyCanvas.referencePixelsPerUnit = instanceCanvas.referencePixelsPerUnit;\n                                dummyCanvas.stagePriority = (byte)stagePriority;\n                                dummyCanvas.sortingLayerID = instanceCanvas.sortingLayerID;\n                            }\n                        }\n\n                        m_PrefabContentsRoot.transform.SetParent(dummyParent.transform, false);\n                    }\n                }\n            }\n            else\n            {\n                // Invalid setup\n                CleanupBeforeClosing();\n            }\n\n            return isValid;\n        }\n\n        // Returns true if opened successfully (this method should only be called from the StageNavigationManager)\n        protected internal override bool OnOpenStage()\n        {\n            if (!isCurrentStage)\n            {\n                Debug.LogError(\"Only opening the current PrefabStage is supported. Please report a bug\");\n                return false;\n            }\n\n            bool success = OpenStage();\n            if (success)\n            {\n                var guid = AssetDatabase.AssetPathToGUID(m_PrefabAssetPath);\n                m_InitialFileHash = AssetDatabase.GetSourceAssetFileHash(guid);\n                if (!FileUtil.ReadFileContentBinary(assetPath, out m_InitialFileContent, out string errorMessage))\n                    Debug.LogError($\"No undo will be registered for {m_PrefabContentsRoot.name}. \\nError: {errorMessage}\");\n            }\n\n            return success;\n        }\n\n        bool OpenStage()\n        {\n            bool reloading = scene.IsValid();\n            if (reloading)\n            {\n                CleanupBeforeReloading();\n            }\n\n            if (LoadStage())\n            {\n                if (mode == Mode.InContext)\n                {\n                    RecordPatchedPropertiesForContent();\n                    ApplyPatchedPropertiesToContent();\n                }\n                prefabStageOpened?.Invoke(this);\n\n                // Update environment scene objects after the 'prefabStageOpened' user callback so we can ensure: correct hideflags and\n                // that our prefab root is not under a prefab instance (which would mark it as an added object).\n                // Note: The user can have reparented and created new GameObjects in the environment scene during this callback.\n                EnsureParentOfPrefabRootIsUnpacked();\n                UpdateEnvironmentHideFlags();\n                UpdateLastPrefabSourceFileHashIfNeeded();\n\n                var sceneHierarchyWindows = SceneHierarchyWindow.GetAllSceneHierarchyWindows();\n                foreach (SceneHierarchyWindow sceneHierarchyWindow in sceneHierarchyWindows)\n                    sceneHierarchyWindow.FrameObject(prefabContentsRoot.GetInstanceID(), false);\n\n                return true;\n            }\n            return false;\n        }\n\n        protected override void OnCloseStage()\n        {\n            if (isValid)\n                prefabStageClosing?.Invoke(this);\n\n            var initialFileContent = m_InitialFileContent;\n            var path = m_PrefabAssetPath;\n            var guid = AssetDatabase.AssetPathToGUID(m_PrefabAssetPath);\n            var currentPrefabSourceFileHash = AssetDatabase.GetSourceAssetFileHash(guid);\n\n            CleanupBeforeClosing();\n\n            if (initialFileContent?.Length > 0 && currentPrefabSourceFileHash != m_InitialFileHash)\n            {\n                if (FileUtil.ReadFileContentBinary(path, out byte[] newFileContent, out string errorMessage))\n                    Undo.RegisterFileChangeUndo(AssetDatabase.GUIDFromAssetPath(path), initialFileContent, newFileContent);\n                else\n                    Debug.LogError($\"No undo will be registered for {m_PrefabContentsRoot.name}. \\nError: {errorMessage}\");\n\n            }\n        }\n\n        protected internal override void OnReturnToStage()\n        {\n            if (m_NeedsReloadingWhenReturningToStage)\n            {\n                m_NeedsReloadingWhenReturningToStage = false;\n\n                if (m_Mode == Mode.InContext && m_OpenedFromInstanceObject == null)\n                {\n                    // By clearing the contents root this stage becomes invalid which\n                    // will be handled the StageNavigationManager by returning to the\n                    // main stage\n                    m_PrefabContentsRoot = null;\n                    return;\n                }\n\n                ReloadStage();\n            }\n        }\n\n        internal bool HasPatchedPropertyModificationsFor(UnityEngine.Object obj, string partialPropertyName)\n        {\n            if (m_PatchedProperties == null)\n                return false;\n            foreach (var patchedProperty in m_PatchedProperties)\n            {\n                if (patchedProperty.targetInContent == obj && patchedProperty.modification.propertyPath.Contains(partialPropertyName))\n                    return true;\n            }\n            return false;\n        }\n\n        internal bool ContainsTransformPrefabPropertyPatchingFor(GameObject[] gameObjects, string partialPropertyName)\n        {\n            if (gameObjects == null || gameObjects.Length == 0 || m_PatchedProperties == null)\n                return false;\n\n            for (int i = 0; i < gameObjects.Length; i++)\n                if (HasPatchedPropertyModificationsFor(gameObjects[i].transform, partialPropertyName))\n                    return true;\n\n            return false;\n        }\n\n        void RecordPatchedPropertiesForContent()\n        {\n            m_PatchedProperties = new List<PatchedProperty>();\n\n            if (openedFromInstanceRoot == null)\n                return;\n\n            if (PrefabUtility.GetPrefabInstanceStatus(openedFromInstanceRoot) != PrefabInstanceStatus.Connected)\n                return;\n\n            var contentObjectsFromFileID = new Dictionary<ulong, UnityEngine.Object>();\n            var instanceTransformsFromFileID = new Dictionary<ulong, Transform>();\n            var targetsToSerializedTargets = new Dictionary<UnityEngine.Object, SerializedObject>();\n\n            TransformVisitor visitor = new TransformVisitor();\n\n            visitor.VisitAll(prefabContentsRoot.transform, (transform, dict) => {\n                contentObjectsFromFileID[Unsupported.GetOrGenerateFileIDHint(transform.gameObject)] = transform.gameObject;\n                Component[] components = transform.GetComponents<Component>();\n                for (int i = components.Length - 1; i >= 0; i--)\n                {\n                    if (components[i] == null)\n                        continue;\n                    contentObjectsFromFileID[Unsupported.GetOrGenerateFileIDHint(components[i])] = components[i];\n                }\n            }, null);\n\n            visitor.VisitAndAllowEarlyOut(openedFromInstanceRoot.transform, (transform, dict) => {\n                // If the GameObject is not hidden in the scene, it's not part of the Prefab instance\n                // that we're hiding because we're opening its Asset. That means it's not an object we\n                // should use as source for the patching of properties on the Prefab Asset content.\n                if (!StageUtility.IsPrefabInstanceHiddenForInContextEditing(transform.gameObject))\n                    return false;\n\n                Transform assetTransform = PrefabUtility.GetCorrespondingObjectFromSourceAtPath(transform, assetPath);\n                // Added GameObjects have no corresponding asset object\n                if (assetTransform != null)\n                    instanceTransformsFromFileID[Unsupported.GetLocalIdentifierInFileForPersistentObject(assetTransform)] = transform;\n                return true;\n            }, null);\n\n            // Note: openedFromInstance is not necessarily a Prefab root, as it might be a nested Prefab.\n            var instanceAndCorrespondingObjectChain = new List<(GameObject prefabObject, PropertyModification[] mods)>();\n            GameObject prefabObject = openedFromInstanceRoot;\n            int numOverrides = 0;\n            while (AssetDatabase.GetAssetPath(prefabObject) != assetPath)\n            {\n                Assert.IsTrue(PrefabUtility.IsPartOfPrefabInstance(prefabObject));\n                PropertyModification[] mods = PrefabUtility.GetPropertyModifications(prefabObject);\n                instanceAndCorrespondingObjectChain.Add((prefabObject, mods));\n                prefabObject = PrefabUtility.GetCorrespondingObjectFromSource(prefabObject);\n                numOverrides += mods.Length;\n            }\n\n            // Patching properties is expensive therefore we disable patching when there is an excessive\n            // amount of overrides (case 1370904)\n            m_TemporarilyDisablePatchAllOverridenProperties = numOverrides >= k_MaxNumberOfOverridesToVisualize;\n\n            bool onlyPatchRootTransform = !showOverrides;\n\n            // Run through same objects, but from innermost out so outer overrides are applied last.\n            for (int i = instanceAndCorrespondingObjectChain.Count - 1; i >= 0; i--)\n            {\n                prefabObject = instanceAndCorrespondingObjectChain[i].prefabObject;\n                var mods = instanceAndCorrespondingObjectChain[i].mods;\n\n                UnityEngine.Object lastTarget = null;\n                UnityEngine.Object lastTargetInContent = null;\n                SerializedObject lastInstanceTransformSO = null;\n                foreach (PropertyModification mod in mods)\n                {\n                    if (mod.target == null)\n                        continue;\n\n                    if (onlyPatchRootTransform && !(mod.target is Transform))\n                        continue;\n\n                    UnityEngine.Object targetInContent = null;\n                    SerializedObject instanceTransformSO = null;\n\n                    // Optimization to avoid doing work to find matching object in Prefab contents\n                    // for a target we already saw. Performs best if modifications are sorted by target.\n                    if (mod.target == lastTarget)\n                    {\n                        targetInContent = lastTargetInContent;\n                        instanceTransformSO = lastInstanceTransformSO;\n                    }\n                    else\n                    {\n                        targetInContent = null;\n                        UnityEngine.Object targetInOpenAsset = PrefabUtility.GetCorrespondingObjectFromSourceAtPath(mod.target, assetPath);\n                        if (targetInOpenAsset != null)\n                        {\n                            ulong fileID = Unsupported.GetLocalIdentifierInFileForPersistentObject(targetInOpenAsset);\n                            contentObjectsFromFileID.TryGetValue(fileID, out targetInContent);\n                            Transform transform;\n                            if (instanceTransformsFromFileID.TryGetValue(fileID, out transform))\n                            {\n                                instanceTransformSO = new SerializedObject(transform);\n                            }\n                        }\n                        lastTarget = mod.target;\n                        lastTargetInContent = targetInContent;\n                        lastInstanceTransformSO = instanceTransformSO;\n                    }\n\n                    if (targetInContent != null)\n                    {\n                        // Don't patch root name, as Prefab Mode doesn't support changing that.\n                        if (targetInContent == prefabContentsRoot && mod.propertyPath == \"m_Name\")\n                            continue;\n\n                        if (onlyPatchRootTransform && targetInContent != prefabContentsRoot.transform)\n                            continue;\n\n                        if (instanceTransformSO != null)\n                        {\n                            // If properties on a Prefab instance are driven, they are serialized as 0,\n                            // which means their Prefab override values will be 0 as well.\n                            // Patching over values of 0 for Prefab Mode in Context is no good,\n                            // so get the actual current value from the instance instead.\n                            PropertyModification modFromValue = instanceTransformSO.ExtractPropertyModification(mod.propertyPath);\n                            if (modFromValue != null)\n                                mod.value = modFromValue.value;\n                        }\n\n                        if (!targetsToSerializedTargets.ContainsKey(targetInContent))\n                        {\n                            targetsToSerializedTargets[targetInContent] = new SerializedObject(targetInContent);\n                        }\n                        var serializedTargetInContent = targetsToSerializedTargets[targetInContent];\n                        var serializedPropertyInContent = serializedTargetInContent.FindProperty(mod.propertyPath);\n                        if (serializedPropertyInContent != null)\n                        {\n                            // Ignore [SerializedReference] modifications\n                            if (serializedPropertyInContent.propertyType == SerializedPropertyType.ManagedReference)\n                            {\n                                continue;\n                            }\n\n                            // Ignore non persistent ObjectReference modifications\n                            if (serializedPropertyInContent.propertyType == SerializedPropertyType.ObjectReference && mod.objectReference != null && !IsPersistent(mod.objectReference))\n                            {\n                                continue;\n                            }\n                        }\n\n                        // Info for ManagedReference fields can't be retrieved using the property path\n                        // All overrides for ManagedReference fields start with \"managedReferences[\"\n                        if (mod.propertyPath.StartsWith(\"managedReferences[\"))\n                        {\n                            // [SerializedReference] - it can't be applied in all scenarios, ignore it\n                            continue;\n                        }\n\n                        DrivenPropertyManager.TryRegisterProperty(this, targetInContent, mod.propertyPath);\n                        m_PatchedProperties.Add(new PatchedProperty() { modification = mod, targetInContent = targetInContent });\n                    }\n                }\n            }\n\n            // Apply patched properties from outer stage where applicable.\n            // This is so that changes that were patched when going in Prefab Mode in Context\n            // don't suddenly change when digging in deeper into nested Prefab or Variant bases.\n            var stageHistory = StageNavigationManager.instance.stageHistory;\n            int selfIndex = stageHistory.IndexOf(this);\n            if (selfIndex >= 1)\n            {\n                PrefabStage previous = stageHistory[selfIndex - 1] as PrefabStage;\n                if (previous != null && previous.mode == Mode.InContext && previous.m_PatchedProperties != null)\n                {\n                    List<PatchedProperty> previousPatchedProperties = previous.m_PatchedProperties;\n                    UnityEngine.Object lastTarget = null;\n                    UnityEngine.Object lastTargetInContent = null;\n                    for (int i = previousPatchedProperties.Count - 1; i >= 0; i--)\n                    {\n                        PatchedProperty patch = previousPatchedProperties[i];\n                        PropertyModification mod = patch.modification;\n                        if (mod.target == null)\n                            continue;\n\n                        UnityEngine.Object targetInContent = null;\n                        if (mod.target == lastTarget)\n                        {\n                            targetInContent = lastTargetInContent;\n                        }\n                        else\n                        {\n                            targetInContent = null;\n                            UnityEngine.Object targetInOpenAsset = PrefabUtility.GetCorrespondingObjectFromSourceAtPath(mod.target, assetPath);\n                            if (targetInOpenAsset != null)\n                            {\n                                ulong fileID = Unsupported.GetLocalIdentifierInFileForPersistentObject(targetInOpenAsset);\n                                contentObjectsFromFileID.TryGetValue(fileID, out targetInContent);\n                            }\n                            lastTarget = mod.target;\n                            lastTargetInContent = targetInContent;\n                        }\n\n                        if (targetInContent != null)\n                        {\n                            // Don't patch root name, as Prefab Mode doesn't support changing that.\n                            // Root can be a different object than it was in outer Stage, så check again here.\n                            if (targetInContent == prefabContentsRoot && mod.propertyPath == \"m_Name\")\n                                continue;\n\n                            // Root can be a different object than it was in outer Stage, så check again here.\n                            if (onlyPatchRootTransform && targetInContent != prefabContentsRoot.transform)\n                                continue;\n\n                            DrivenPropertyManager.TryRegisterProperty(this, targetInContent, mod.propertyPath);\n                            m_PatchedProperties.Add(new PatchedProperty() { modification = mod, targetInContent = targetInContent });\n                        }\n                    }\n                }\n            }\n        }\n\n        void ApplyPatchedPropertiesToContent()\n        {\n            if (m_PatchedProperties.Count == 0)\n                return;\n\n            var modificationsPerTargetInContent = new Dictionary<UnityEngine.Object, List<PropertyModification>>();\n            UnityEngine.Object lastTargetInContent = null;\n            int lastTargetID = 0;\n            for (int i = m_PatchedProperties.Count - 1; i >= 0; i--)\n            {\n                PatchedProperty patchedProperty = m_PatchedProperties[i];\n                PropertyModification modification = patchedProperty.modification;\n                UnityEngine.Object targetInContent = patchedProperty.targetInContent;\n\n                // If an object was destroyed, but later recreated with undo or redo, we have to recreate the reference to it.\n                if (targetInContent == null)\n                {\n                    // Patched properties are grouped by targetInContent, so we can easily ensure we\n                    // only make one attempt per target just by comparing with the previous target.\n                    int targetID = targetInContent.GetInstanceID();\n                    if (targetID == lastTargetID)\n                        targetInContent = lastTargetInContent;\n                    else\n                        targetInContent = UnityEditorInternal.InternalEditorUtility.GetObjectFromInstanceID(targetID);\n\n                    // Assign the struct back to the array if it worked.\n                    if (targetInContent != null)\n                    {\n                        patchedProperty.targetInContent = targetInContent;\n                        m_PatchedProperties[i] = patchedProperty;\n                    }\n                    lastTargetInContent = targetInContent;\n                    lastTargetID = targetID;\n                }\n\n                // Group modifications per target for batch apply\n                if (targetInContent != null)\n                {\n                    List<PropertyModification> list;\n                    if (!modificationsPerTargetInContent.TryGetValue(targetInContent, out list))\n                    {\n                        list = new List<PropertyModification>();\n                        modificationsPerTargetInContent[targetInContent] = list;\n                    }\n                    list.Add(modification);\n                }\n\n\n                // If GameObject.active is an override, applying the value via PropertyModification\n                // is not sufficient to actually change active state of the object,\n                // nor is calling AwakeFromLoad(kAnimationAwakeFromLoad) afterwards,\n                // so explicitly set it here.\n                GameObject targetGameObject = targetInContent as GameObject;\n                if (targetGameObject != null && modification.propertyPath == \"m_IsActive\")\n                    targetGameObject.SetActive(modification.value != \"0\");\n            }\n\n            // Batch apply modifications per object (to optimize for large objects, case 1370904)\n            foreach (var kvp in modificationsPerTargetInContent)\n            {\n                var targetInContent = kvp.Key;\n                var mods = kvp.Value;\n                PropertyModification.ApplyPropertyModificationsToObject(targetInContent, mods.ToArray());\n            }\n\n            StageUtility.CallAwakeFromLoadOnSubHierarchy(m_PrefabContentsRoot);\n        }\n\n        void UndoRedoPerformed(in UndoRedoInfo info)\n        {\n            if (m_Mode == Mode.InContext)\n            {\n                ApplyPatchedPropertiesToContent();\n            }\n        }\n\n        void CleanupBeforeReloading()\n        {\n            // Only clear state that is being reloaded but keep InContext editing state etc\n            PrefabStageUtility.DestroyPreviewScene(scene);\n            m_HideFlagUtility = null;\n        }\n\n        void CleanupBeforeClosing()\n        {\n            if (m_Mode == Mode.InContext)\n            {\n                SetPrefabInstanceHiddenForInContextEditing(false);\n            }\n\n            if (m_PrefabContentsRoot != null && m_PrefabContentsRoot.scene != scene)\n            {\n                UnityEngine.Object.DestroyImmediate(m_PrefabContentsRoot);\n            }\n\n            if (scene.IsValid())\n                PrefabStageUtility.DestroyPreviewScene(scene); // Automatically deletes all GameObjects in scene\n\n            m_PrefabContentsRoot = null;\n            m_OpenedFromInstanceRoot = null;\n            m_OpenedFromInstanceObject = null;\n            m_HideFlagUtility = null;\n            m_PrefabAssetPath = null;\n            m_InitialFileContent = null;\n            m_InitialFileHash = new Hash128();\n            m_InitialSceneDirtyID = 0;\n            m_StageDirtiedFired = false;\n            m_LastSceneDirtyID = 0;\n            m_IgnoreNextAssetImportedEventForCurrentPrefab = false;\n            m_PrefabWasChangedOnDisk = false;\n        }\n\n        void ReloadStage()\n        {\n            if (SceneHierarchy.s_DebugPrefabStage)\n                Debug.Log(\"RELOADING Prefab at \" + m_PrefabAssetPath);\n\n            if (!isCurrentStage)\n            {\n                Debug.LogError(\"Only reloading the current PrefabStage is supported. Please report a bug\");\n                return;\n            }\n\n            var sceneHierarchyWindows = SceneHierarchyWindow.GetAllSceneHierarchyWindows();\n            foreach (SceneHierarchyWindow sceneHierarchyWindow in sceneHierarchyWindows)\n                SaveHierarchyState(sceneHierarchyWindow);\n\n            if (OpenStage())\n            {\n                foreach (SceneView sceneView in SceneView.sceneViews)\n                    SyncSceneViewToStage(sceneView);\n\n                foreach (SceneHierarchyWindow sceneHierarchyWindow in sceneHierarchyWindows)\n                {\n                    SyncSceneHierarchyToStage(sceneHierarchyWindow);\n                    LoadHierarchyState(sceneHierarchyWindow);\n                }\n\n                prefabStageReloaded?.Invoke(this);\n            }\n\n            if (SceneHierarchy.s_DebugPrefabStage)\n                Debug.Log(\"RELOADING done\");\n        }\n\n        internal override void SyncSceneViewToStage(SceneView sceneView)\n        {\n            // The reason we need to set customScene even though we also set overrideSceneCullingMask is\n            // because the RenderSettings of the customScene is used to override lighting settings for this SceneView.\n            PrefabStage prefabStage = GetContextStage() as PrefabStage;\n            sceneView.customScene = prefabStage == null ? default(Scene) : prefabStage.scene;\n            sceneView.customParentForNewGameObjects = prefabContentsRoot.transform;\n            switch (mode)\n            {\n                case PrefabStage.Mode.InIsolation:\n                    sceneView.overrideSceneCullingMask = 0;\n                    break;\n                case PrefabStage.Mode.InContext:\n                    sceneView.overrideSceneCullingMask = GetCombinedSceneCullingMaskForCamera();\n                    break;\n                default:\n                    Debug.LogError(\"Unhandled enum\");\n                    break;\n            }\n        }\n\n        internal override void SyncSceneHierarchyToStage(SceneHierarchyWindow sceneHierarchyWindow)\n        {\n            var sceneHierarchy = sceneHierarchyWindow.sceneHierarchy;\n            sceneHierarchy.customScenes = new[] { scene };\n            sceneHierarchy.customParentForNewGameObjects = prefabContentsRoot.transform;\n            sceneHierarchy.SetCustomDragHandler(PrefabModeDraggingHandler);\n        }\n\n        protected internal override void OnFirstTimeOpenStageInSceneView(SceneView sceneView)\n        {\n            // Default to scene view lighting if scene itself does not have any lights\n            if (!HasAnyActiveLights(scene))\n                sceneView.sceneLighting = false;\n\n            // Default to not showing skybox if user did not specify a custom environment scene.\n            if (string.IsNullOrEmpty(scene.path))\n                sceneView.sceneViewState.showSkybox = false;\n\n            // For UI to frame properly we need to delay one full Update for the layouting to have been processed\n            EditorApplication.update += DelayedFraming;\n        }\n\n        internal override void OnFirstTimeOpenStageInSceneHierachyWindow(SceneHierarchyWindow sceneHierarchyWindow)\n        {\n            var expandedIDs = new List<int>();\n            AddParentsBelowButIgnoreNestedPrefabsRecursive(prefabContentsRoot.transform, expandedIDs);\n            expandedIDs.Sort();\n            sceneHierarchyWindow.sceneHierarchy.treeViewState.expandedIDs = expandedIDs;\n        }\n\n        void AddParentsBelowButIgnoreNestedPrefabsRecursive(Transform transform, List<int> gameObjectInstanceIDs)\n        {\n            gameObjectInstanceIDs.Add(transform.gameObject.GetInstanceID());\n\n            int count = transform.childCount;\n            for (int i = 0; i < count; ++i)\n            {\n                var child = transform.GetChild(i);\n                if (child.childCount > 0 && !PrefabUtility.IsAnyPrefabInstanceRoot(child.gameObject))\n                {\n                    AddParentsBelowButIgnoreNestedPrefabsRecursive(child, gameObjectInstanceIDs);\n                }\n            }\n        }\n\n        static DragAndDropVisualMode PrefabModeDraggingHandler(GameObjectTreeViewItem parentItem, GameObjectTreeViewItem targetItem, TreeViewDragging.DropPosition dropPos, bool perform)\n        {\n            var prefabStage = StageNavigationManager.instance.currentStage as PrefabStage;\n            if (prefabStage == null)\n                throw new InvalidOperationException(\"PrefabModeDraggingHandler should only be called in Prefab Mode\");\n\n            // Disallow dropping as sibling to the prefab instance root (In Prefab Mode we only want to show one root).\n            if (parentItem != null && parentItem.parent == null && dropPos != TreeViewDragging.DropPosition.Upon)\n                return DragAndDropVisualMode.Rejected;\n\n            // Disallow dragging scenes into the hierarchy when it is in Prefab Mode (we do not support multi-scenes for prefabs yet)\n            foreach (var dragged in DragAndDrop.objectReferences)\n            {\n                if (dragged is SceneAsset)\n                    return DragAndDropVisualMode.Rejected;\n            }\n\n            // Check for cyclic nesting (only on perform since it is an expensive operation)\n            if (perform)\n            {\n                var prefabAssetThatIsAddedTo = AssetDatabase.LoadMainAssetAtPath(prefabStage.assetPath);\n\n                if (prefabAssetThatIsAddedTo is BrokenPrefabAsset)\n                    return DragAndDropVisualMode.None;\n\n                foreach (var dragged in DragAndDrop.objectReferences)\n                {\n                    if (dragged is GameObject && EditorUtility.IsPersistent(dragged))\n                    {\n                        var prefabAssetThatWillBeAdded = dragged;\n                        if (PrefabUtility.CheckIfAddingPrefabWouldResultInCyclicNesting(prefabAssetThatIsAddedTo, prefabAssetThatWillBeAdded))\n                        {\n                            PrefabUtility.ShowCyclicNestingWarningDialog();\n                            return DragAndDropVisualMode.Rejected;\n                        }\n                    }\n                }\n            }\n\n            return DragAndDropVisualMode.None;\n        }\n\n        static bool HasAnyActiveLights(Scene scene)\n        {\n            foreach (var gameObject in scene.GetRootGameObjects())\n            {\n                if (gameObject.GetComponentsInChildren<Light>(false).Length > 0)\n                    return true;\n            }\n\n            return false;\n        }\n\n        int m_DelayCounter;\n        void DelayedFraming()\n        {\n            if (m_DelayCounter++ == 1)\n            {\n                EditorApplication.update -= DelayedFraming;\n                m_DelayCounter = 0;\n\n                if(!IsPartOfPrefabContents(Selection.activeGameObject))\n                    Selection.activeGameObject = prefabContentsRoot;\n\n                // Frame the Prefab\n                foreach (SceneView sceneView in SceneView.sceneViews)\n                    sceneView.FrameSelected(false, true);\n            }\n        }\n\n        internal override string GetErrorMessage()\n        {\n            if (m_PrefabContentsRoot == null)\n                return L10n.Tr(\"Error: The Prefab contents root has been deleted.\\n\\nPrefab: \") + m_PrefabAssetPath;\n\n            if (m_PrefabContentsRoot.scene != scene)\n                return L10n.Tr(\"Error: The root GameObject of the opened Prefab has been moved out of the Prefab Stage scene by a script.\\n\\nPrefab: \") + m_PrefabAssetPath;\n\n            return null;\n        }\n\n        protected internal override GUIContent CreateHeaderContent()\n        {\n            var label = Path.GetFileNameWithoutExtension(m_PrefabAssetPath);\n            var icon = AssetDatabase.GetCachedIcon(m_PrefabAssetPath);\n            return new GUIContent(label, icon);\n        }\n\n        internal override BreadcrumbBar.Item CreateBreadcrumbItem()\n        {\n            GUIContent content = CreateHeaderContent();\n\n            var history = StageNavigationManager.instance.stageHistory;\n            bool isLastCrumb = this == history.Last();\n            var style = isLastCrumb ? BreadcrumbBar.DefaultStyles.labelBold : BreadcrumbBar.DefaultStyles.label;\n            var separatorstyle = mode == Mode.InIsolation ? BreadcrumbBar.SeparatorStyle.Line : BreadcrumbBar.SeparatorStyle.Arrow;\n            if (isAssetMissing)\n            {\n                style = isLastCrumb ? BreadcrumbBar.DefaultStyles.labelBoldMissing : BreadcrumbBar.DefaultStyles.labelMissing;\n                content.tooltip = L10n.Tr(\"Prefab Asset has been deleted.\");\n            }\n\n            return new BreadcrumbBar.Item\n            {\n                content = content,\n                guistyle = style,\n                userdata = this,\n                separatorstyle = separatorstyle\n            };\n        }\n\n        internal override void Tick()\n        {\n            if (!isValid)\n                return;\n\n            if (hasUnsavedChanges)\n            {\n                m_AnalyticsDidUserModify = true;\n\n                if (!m_StageDirtiedFired)\n                {\n                    m_StageDirtiedFired = true;\n                    if (prefabStageDirtied != null)\n                        prefabStageDirtied(this);\n                }\n            }\n\n            UpdateEnvironmentHideFlagsIfNeeded();\n            HandleAutoSave();\n            HandlePrefabChangedOnDisk();\n            DetectSceneDirtinessChange();\n            DetectPrefabFileIconChange();\n            DetectPrefabRootTransformChange();\n        }\n\n        void DetectPrefabRootTransformChange()\n        {\n            var currentTransform = m_PrefabContentsRoot.transform;\n            if (currentTransform != m_LastRootTransform)\n            {\n                foreach (SceneView sceneView in SceneView.sceneViews)\n                    SyncSceneViewToStage(sceneView);\n\n                var sceneHierarchyWindows = SceneHierarchyWindow.GetAllSceneHierarchyWindows();\n                foreach (SceneHierarchyWindow sceneHierarchyWindow in sceneHierarchyWindows)\n                    SyncSceneHierarchyToStage(sceneHierarchyWindow);\n            }\n            m_LastRootTransform = currentTransform;\n        }\n\n        void DetectPrefabFileIconChange()\n        {\n            var icon = DeterminePrefabFileIconFromInstanceRootGameObject();\n            if (icon != m_PrefabFileIcon)\n            {\n                m_PrefabFileIcon = icon;\n                SceneView.RebuildBreadcrumbBarInAll();\n                SceneHierarchyWindow.RebuildStageHeaderInAll();\n            }\n        }\n\n        void DetectSceneDirtinessChange()\n        {\n            if (scene.dirtyID != m_LastSceneDirtyID)\n            {\n                // We want to make sure that all the new sortable components (e.g, canvas, renderer) being added have\n                // the correct StagePriority assigned to them. Otherwise they won't be sorted accordingly when in\n                // context/isolation mode.\n                if (PrefabStageUtility.IsUIPrefab(m_PrefabAssetPath))\n                    UpdateSortableComponentsWithStagePriority(StageNavigationManager.instance.stageHistory.IndexOf(this));\n\n                SceneView.RepaintAll();\n            }\n            m_LastSceneDirtyID = scene.dirtyID;\n        }\n\n        void UpdateEnvironmentHideFlagsIfNeeded()\n        {\n            if (m_HideFlagUtility == null)\n                m_HideFlagUtility = new HideFlagUtility(scene, m_PrefabContentsRoot);\n            m_HideFlagUtility.UpdateEnvironmentHideFlagsIfNeeded();\n        }\n\n        void UpdateEnvironmentHideFlags()\n        {\n            if (m_HideFlagUtility == null)\n                m_HideFlagUtility = new HideFlagUtility(scene, m_PrefabContentsRoot);\n            m_HideFlagUtility.UpdateEnvironmentHideFlags();\n        }\n\n        void EnsureParentOfPrefabRootIsUnpacked()\n        {\n            var parent = m_PrefabContentsRoot.transform.parent;\n            if (parent != null)\n            {\n                if (PrefabUtility.IsPartOfPrefabInstance(parent))\n                {\n                    var outerMostPrefabInstance = PrefabUtility.GetOutermostPrefabInstanceRoot(parent);\n                    PrefabUtility.UnpackPrefabInstance(outerMostPrefabInstance, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);\n                }\n            }\n        }\n\n        bool isTextFieldCaretShowing\n        {\n            get { return EditorGUI.IsEditingTextField() && !EditorGUIUtility.textFieldHasSelection; }\n        }\n\n        bool readyToAutoSave\n        {\n            get { return m_PrefabContentsRoot != null && hasUnsavedChanges && GUIUtility.hotControl == 0 && !isTextFieldCaretShowing && !EditorApplication.isCompiling; }\n        }\n\n        void HandleAutoSave()\n        {\n            if (IsPrefabInImmutableFolder())\n                return;\n\n            if (autoSave && readyToAutoSave)\n            {\n                AutoSave();\n            }\n        }\n\n        void HandlePrefabChangedOnDisk()\n        {\n            if (m_PrefabWasChangedOnDisk)\n            {\n                m_PrefabWasChangedOnDisk = false;\n\n                if (!isCurrentStage)\n                {\n                    return;\n                }\n\n                if (!File.Exists(m_PrefabAssetPath))\n                    return;\n\n                if (hasUnsavedChanges)\n                {\n                    var title = L10n.Tr(\"Prefab Has Been Changed on Disk\");\n                    var message = string.Format(L10n.Tr(\"You have modifications to the Prefab '{0}' that was changed on disk while in Prefab Mode. Do you want to keep your changes or reload the Prefab and discard your changes?\"), m_PrefabContentsRoot.name);\n                    bool keepChanges = EditorUtility.DisplayDialog(title, message, L10n.Tr(\"Keep Changes\"), L10n.Tr(\"Discard Changes\"));\n                    if (!keepChanges)\n                        ReloadStage();\n                }\n                else\n                {\n                    ReloadStage();\n                }\n            }\n        }\n\n        public void ClearDirtiness()\n        {\n            EditorSceneManager.ClearSceneDirtiness(scene);\n            m_InitialSceneDirtyID = scene.dirtyID;\n            m_StageDirtiedFired = false;\n        }\n\n        bool PromptIfMissingVariantParentForVariant()\n        {\n            if (PrefabUtility.IsPrefabAssetMissing(m_PrefabContentsRoot))\n            {\n                string title = L10n.Tr(\"Saving Variant Failed\");\n                string message = L10n.Tr(\"Can't save the Prefab Variant when its parent Prefab is missing. You have to unpack the root GameObject or recover the missing parent Prefab in order to save the Prefab Variant\");\n                if (autoSave)\n                    message += L10n.Tr(\"\\n\\nAuto Save has been temporarily disabled.\");\n                EditorUtility.DisplayDialog(title, message, L10n.Tr(\"OK\"));\n                m_TemporarilyDisableAutoSave = true;\n                return true;\n            }\n            return false;\n        }\n\n        // Returns true if we can continue. Either the user saved changes or user discarded changes. Returns false if the user cancelled switching stage.\n        internal override bool AskUserToSaveModifiedStageBeforeSwitchingStage()\n        {\n            // Allow user to save any unsaved changes only after recompiling have finished so any new scripts can be\n            // saved properly to the Prefab file (but only if the stage is valid)\n            if (isValid)\n            {\n                if (EditorApplication.isCompiling && hasUnsavedChanges)\n                {\n                    SceneView.ShowNotification(\"Compiling must finish before you can exit Prefab Mode\");\n                    SceneView.RepaintAll();\n                    return false;\n                }\n\n                bool continueDestroyingScene = AskUserToSaveDirtySceneBeforeDestroyingScene();\n                if (!continueDestroyingScene)\n                    return false;\n            }\n\n            return true;\n        }\n\n        // Returns true if saved succesfully (internal so we can use it in Tests)\n        internal bool SavePrefab()\n        {\n            if (!isValid)\n                return false;\n\n            m_AnalyticsDidUserSave = true;\n            m_AnalyticsDidUserModify = true;\n\n            if (SceneHierarchy.s_DebugPrefabStage)\n                Debug.Log(\"SAVE PREFAB\");\n\n            if (prefabSaving != null)\n                prefabSaving(m_PrefabContentsRoot);\n\n            var startTime = EditorApplication.timeSinceStartup;\n\n            if (PromptIfMissingVariantParentForVariant())\n                return false;\n\n            // The user can have deleted required folders\n            var folder = Path.GetDirectoryName(m_PrefabAssetPath);\n            if (!Directory.Exists(folder))\n                Directory.CreateDirectory(folder);\n\n            bool savedSuccesfully;\n            PrefabUtility.SaveAsPrefabAsset(m_PrefabContentsRoot, m_PrefabAssetPath, out savedSuccesfully);\n            m_LastSavingDuration = (float)(EditorApplication.timeSinceStartup - startTime);\n\n            if (savedSuccesfully)\n            {\n                ClearDirtiness();\n\n                if (prefabSaved != null)\n                    prefabSaved(m_PrefabContentsRoot);\n\n                // After saving the Prefab any Prefab instances in the environment scene\n                // that are dependent on the saved Prefab will have lost their hideflags\n                // so here we set them again.\n                UpdateEnvironmentHideFlags();\n            }\n            else\n            {\n                string title = L10n.Tr(\"Saving Failed\");\n                string message = L10n.Tr(\"Saving failed. Check the Console window to get more insight into what needs to be fixed.\");\n                if (autoSave)\n                    message += L10n.Tr(\"\\n\\nAuto Save has been temporarily disabled.\");\n                EditorUtility.DisplayDialog(title, message, L10n.Tr(\"OK\"));\n\n                m_TemporarilyDisableAutoSave = true;\n                m_IgnoreNextAssetImportedEventForCurrentPrefab = false;\n            }\n\n            if (SceneHierarchy.s_DebugPrefabStage)\n                Debug.Log(\"SAVE PREFAB ended\");\n\n            showingSavingLabel = false;\n\n            return savedSuccesfully;\n        }\n\n        internal bool SaveAsNew(string newPath, bool asCopy)\n        {\n            if (!isValid)\n                return false;\n\n            if (newPath == m_PrefabAssetPath)\n            {\n                throw new ArgumentException(\"Cannot save as new prefab using the same path\");\n            }\n\n            if (asCopy)\n            {\n                // Keep current open prefab and save copy at newPath\n                string oldName = m_PrefabContentsRoot.name;\n                m_PrefabContentsRoot.name = Path.GetFileNameWithoutExtension(newPath);\n                PrefabUtility.SaveAsPrefabAsset(m_PrefabContentsRoot, newPath);\n                m_PrefabContentsRoot.name = oldName;\n            }\n            else\n            {\n                // Change the current open prefab and save\n                m_PrefabContentsRoot.name = Path.GetFileNameWithoutExtension(newPath);\n                m_PrefabAssetPath = newPath;\n                CachePrefabFolderInfo();\n                ClearDirtiness();\n                PrefabUtility.SaveAsPrefabAsset(m_PrefabContentsRoot, newPath);\n\n                if (prefabStageSavedAsNewPrefab != null)\n                    prefabStageSavedAsNewPrefab(this);\n            }\n\n            return true;\n        }\n\n        internal override bool SaveAsNew()\n        {\n            Assert.IsTrue(m_PrefabContentsRoot != null, \"We should have a valid m_PrefabContentsRoot when saving to prefab asset\");\n\n            string directoryOfCurrentPrefab = Path.GetDirectoryName(m_PrefabAssetPath);\n            string nameOfCurrentPrefab = Path.GetFileNameWithoutExtension(m_PrefabAssetPath);\n            string relativePath;\n            while (true)\n            {\n                relativePath = EditorUtility.SaveFilePanelInProject(\"Save Prefab\", nameOfCurrentPrefab + \" Copy\", \"prefab\", \"\", directoryOfCurrentPrefab);\n\n                // Cancel pressed\n                if (string.IsNullOrEmpty(relativePath))\n                    return false;\n\n                if (relativePath == m_PrefabAssetPath)\n                {\n                    if (EditorUtility.DisplayDialog(L10n.Tr(\"Save Prefab has failed\"), L10n.Tr(\"Overwriting the same path as another open prefab is not allowed.\"), L10n.Tr(\"Try Again\"), L10n.Tr(\"Cancel\")))\n                        continue;\n\n                    return false;\n                }\n                break;\n            }\n\n            return SaveAsNew(relativePath, false);\n        }\n\n        void PerformDelayedAutoSave()\n        {\n            EditorApplication.update -= PerformDelayedAutoSave;\n            Save();\n        }\n\n        void AutoSave()\n        {\n            showingSavingLabel = m_LastSavingDuration > kDurationBeforeShowingSavingBadge;\n            if (showingSavingLabel)\n            {\n                // Save delayed if we want to show the save badge while saving.\n                foreach (SceneView sceneView in SceneView.sceneViews)\n                    sceneView.Repaint();\n\n                EditorApplication.update += PerformDelayedAutoSave;\n            }\n            else\n            {\n                // Save directly if we don't want to show the saving badge\n                Save();\n            }\n        }\n\n        // Returns true if prefab was saved.\n        internal override bool Save()\n        {\n            if (m_PrefabContentsRoot == null)\n            {\n                Debug.LogError(\"We should have a valid m_PrefabContentsRoot when saving to prefab asset\");\n                return false;\n            }\n\n            if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(m_PrefabAssetPath, PrefabUtility.SaveVerb.Save))\n            {\n                // If user doesn't want to check out prefab asset, or it cannot be,\n                // it doesn't make sense to keep auto save on.\n                m_TemporarilyDisableAutoSave = true;\n                return false;\n            }\n\n            bool showCancelButton = !autoSave;\n            if (!CheckRenamedPrefabRootWhenSaving(showCancelButton))\n                return false;\n\n            return SavePrefab();\n        }\n\n        internal override void DiscardChanges()\n        {\n            if (hasUnsavedChanges)\n                ReloadStage();\n        }\n\n        // Returns true if we should continue saving\n        bool CheckRenamedPrefabRootWhenSaving(bool showCancelButton)\n        {\n            var prefabFilename = GetPrefabFileName();\n            if (m_PrefabContentsRoot.name != prefabFilename)\n            {\n                string folder = Path.GetDirectoryName(m_PrefabAssetPath);\n                string extension = Path.GetExtension(m_PrefabAssetPath);\n                string newPath = Path.Combine(folder, m_PrefabContentsRoot.name + extension);\n                string errorMsg = AssetDatabase.ValidateMoveAsset(m_PrefabAssetPath, newPath);\n\n                if (!string.IsNullOrEmpty(errorMsg))\n                {\n                    var t = L10n.Tr(\"Rename Prefab File Not Possible\");\n                    var m = string.Format(L10n.Tr(\"The Prefab file name must match the Prefab root GameObject name but there is already a Prefab asset with the file name '{0}' in the same folder. The root GameObject name will therefore be changed back to match the Prefab file name when saving.\"), m_PrefabContentsRoot.name);\n\n                    if (showCancelButton)\n                    {\n                        if (EditorUtility.DisplayDialog(t, m, L10n.Tr(\"OK\"), L10n.Tr(\"Cancel Save\")))\n                        {\n                            RenameInstanceRootToMatchPrefabFile();\n                            return true;\n                        }\n                        else\n                        {\n                            return false; // Cancel saving\n                        }\n                    }\n\n                    EditorUtility.DisplayDialog(t, m, L10n.Tr(\"OK\"));\n                    RenameInstanceRootToMatchPrefabFile();\n                    return true;\n                }\n\n                var title = L10n.Tr(\"Rename Prefab File?\");\n                var message = string.Format(L10n.Tr(\"The Prefab file name must match the Prefab root GameObject name. Do you want to rename the file to '{0}' or use the old name '{1}' for both?\"), m_PrefabContentsRoot.name, prefabFilename);\n\n                if (showCancelButton)\n                {\n                    int option = EditorUtility.DisplayDialogComplex(title, message, L10n.Tr(\"Rename File\"), L10n.Tr(\"Use Old Name\"), L10n.Tr(\"Cancel Save\"));\n                    switch (option)\n                    {\n                        // Rename prefab file\n                        case 0:\n                            RenamePrefabFileToMatchPrefabInstanceName();\n                            return true;\n                        // Rename the root GameObject to file name\n                        case 1:\n                            RenameInstanceRootToMatchPrefabFile();\n                            return true;\n                        // Cancel saving\n                        case 2:\n                            return false;\n                    }\n                }\n                else\n                {\n                    bool renameFile = EditorUtility.DisplayDialog(title, message, L10n.Tr(\"Rename File\"), L10n.Tr(\"Use Old Name\"));\n                    if (renameFile)\n                        RenamePrefabFileToMatchPrefabInstanceName();\n                    else\n                        RenameInstanceRootToMatchPrefabFile();\n                    return true;\n                }\n            }\n            return true;\n        }\n\n        internal void RenameInstanceRootToMatchPrefabFile()\n        {\n            m_PrefabContentsRoot.name = GetPrefabFileName();\n        }\n\n        internal void RenamePrefabFileToMatchPrefabInstanceName()\n        {\n            string newPrefabFileName = m_PrefabContentsRoot.name;\n\n            if (SceneHierarchy.s_DebugPrefabStage)\n                Debug.LogFormat(\"RENAME Prefab Asset: '{0} to '{1}'\", m_PrefabAssetPath, newPrefabFileName);\n\n            // If we don't ignore the next import event we will reload the current prefab and hereby loosing the current selection (inspector goes blank)\n            // Since we have made the change ourselves (rename) we don't need to reload our instances.\n            m_IgnoreNextAssetImportedEventForCurrentPrefab = true;\n\n            string errorMsg = AssetDatabase.RenameAsset(m_PrefabAssetPath, newPrefabFileName);\n            if (!string.IsNullOrEmpty(errorMsg))\n                Debug.LogError(errorMsg);\n\n            if (SceneHierarchy.s_DebugPrefabStage)\n                Debug.Log(\"RENAME done\");\n        }\n\n        // Returns false if the user clicked Cancel to save otherwise returns true (ok to continue to destroying scene)\n        internal bool AskUserToSaveDirtySceneBeforeDestroyingScene()\n        {\n            if (!hasUnsavedChanges || m_PrefabContentsRoot == null)\n                return true; // no changes to save or no root to save; continue\n\n            if (IsPrefabInImmutableFolder())\n            {\n                var header = L10n.Tr(\"Immutable Prefab\");\n                var message = L10n.Tr(\"The Prefab was changed in Prefab Mode but is in a read-only folder so the changes cannot be saved.\");\n                var buttonOK = L10n.Tr(\"OK\");\n                var buttonCancel = L10n.Tr(\"Cancel\");\n\n                if (EditorUtility.DisplayDialog(header, message, buttonOK, buttonCancel))\n                    return true; // OK: continue to close stage\n                return false; // Cancel closing stage\n            }\n\n            // Rare condition. Prefab should have already been saved if auto-save is enabled,\n            // but it's possible it hasn't, so save when exiting just in case.\n            if (autoSave)\n                return Save();\n\n            int dialogResult = EditorUtility.DisplayDialogComplex(\"Prefab Has Been Modified\", \"Do you want to save the changes you made in Prefab Mode? Your changes will be lost if you don't save them.\", \"Save\", \"Discard Changes\", \"Cancel\");\n            switch (dialogResult)\n            {\n                case 0:\n                    return Save(); // save changes and continue current operation\n\n                case 1:\n                    // The user have accepted to discard changes\n                    if (hasUnsavedChanges && !m_IsAssetMissing)\n                        ReloadStage();\n                    return true; // continue current operation\n\n                case 2:\n                    return false; // cancel and discontinue current operation\n\n                default:\n                    throw new InvalidOperationException(\"Unhandled dialog result \" + dialogResult);\n            }\n        }\n\n        internal void OnSavingPrefab(GameObject gameObject, string path)\n        {\n            // We care about 'irrelevant prefab paths' since the 'irrelevant' prefab could be a nested prefab to the\n            // current prefab being edited (this would result in our current prefab being reimported due to the dependency).\n            // For nested prefabs the prefab merging code will take care of updating the current GameObjects loaded\n            // so in this case do not reload the prefab even though the path shows up in AssetsChangedOnHDD event.\n\n            bool savedBySelf = gameObject == m_PrefabContentsRoot;\n            bool irrelevantPath = path != m_PrefabAssetPath;\n            if (savedBySelf || irrelevantPath)\n            {\n                m_IgnoreNextAssetImportedEventForCurrentPrefab = true;\n            }\n        }\n\n        bool UpdateLastPrefabSourceFileHashIfNeeded()\n        {\n            var guid = AssetDatabase.AssetPathToGUID(m_PrefabAssetPath);\n            var prefabSourceFileHash = AssetDatabase.GetSourceAssetFileHash(guid);\n            if (m_LastPrefabSourceFileHash != prefabSourceFileHash)\n            {\n                m_LastPrefabSourceFileHash = prefabSourceFileHash;\n                return true;\n            }\n            return false;\n        }\n\n        internal void OnAssetsChangedOnHDD(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)\n        {\n            if (SceneHierarchy.s_DebugPrefabStage)\n                Debug.LogFormat(\"AssetDatabase Event: Current Prefab: {0}, *ImportedAssets: {1}, *DeletedAssets: {2}, *MovedAssets: {3}, *MovedFromAssetPaths: {4}\", m_PrefabAssetPath, DebugUtils.ListToString(importedAssets), DebugUtils.ListToString(deletedAssets), DebugUtils.ListToString(movedAssets), DebugUtils.ListToString(movedFromAssetPaths));\n\n            // Prefab was moved (update cached path)\n            for (int i = 0; i < movedFromAssetPaths.Length; ++i)\n            {\n                if (movedFromAssetPaths[i].Equals(m_PrefabAssetPath, StringComparison.OrdinalIgnoreCase))\n                {\n                    m_PrefabAssetPath = movedAssets[i];\n                    break;\n                }\n            }\n\n            for (int i = 0; i < deletedAssets.Length; ++i)\n            {\n                if (deletedAssets[i] == m_PrefabAssetPath)\n                {\n                    m_IsAssetMissing = true;\n                    break;\n                }\n            }\n\n            // Detect if our Prefab was modified on HDD outside Prefab Mode (in that case we should ask the user if he wants to reload it)\n            for (int i = 0; i < importedAssets.Length; ++i)\n            {\n                if (importedAssets[i] == m_PrefabAssetPath)\n                {\n                    m_IsAssetMissing = false;\n                    if (UpdateLastPrefabSourceFileHashIfNeeded() && !m_IgnoreNextAssetImportedEventForCurrentPrefab)\n                    {\n                        if (isCurrentStage)\n                        {\n                            m_PrefabWasChangedOnDisk = true;\n                        }\n                        else\n                        {\n                            m_NeedsReloadingWhenReturningToStage = true;\n                        }\n                    }\n\n                    // Reset the ignore flag when we finally have imported the saved prefab (We set this flag when saving the Prefab from Prefab Mode)\n                    // Note we can get multiple OnAssetsChangedOnHDD events before the Prefab imported event if e.g folders of the Prefab path needs to be reimported first.\n                    m_IgnoreNextAssetImportedEventForCurrentPrefab = false;\n                    break;\n                }\n            }\n        }\n\n        // This method is not called from the SceneView if the SceneView does not support stage handling\n        internal override void OnPreSceneViewRender(SceneView sceneView)\n        {\n            StaticOcclusionCullingVisualization.showOcclusionCulling = false;\n\n            if (mode != Mode.InContext)\n                return;\n\n            StageUtility.EnableHidingForInContextEditingInSceneView(true);\n            StageUtility.SetFocusedScene(scene);\n            StageUtility.SetFocusedSceneContextRenderMode(StageNavigationManager.instance.contextRenderMode);\n            sceneView.SetSceneViewFilteringForStages(StageNavigationManager.instance.contextRenderMode == StageUtility.ContextRenderMode.GreyedOut);\n        }\n\n        // This method is not called from the SceneView if the SceneView does not support stage handling\n        internal override void OnPostSceneViewRender(SceneView sceneView)\n        {\n            StaticOcclusionCullingVisualization.showOcclusionCulling = OcclusionCullingWindow.isVisible;\n\n            if (mode != Mode.InContext)\n                return;\n\n            StageUtility.EnableHidingForInContextEditingInSceneView(false);\n            StageUtility.SetFocusedScene(default(Scene));\n            StageUtility.SetFocusedSceneContextRenderMode(StageUtility.ContextRenderMode.Normal);\n            sceneView.SetSceneViewFilteringForStages(false);\n        }\n\n        Texture2D DeterminePrefabFileIconFromInstanceRootGameObject()\n        {\n            bool partOfInstance = PrefabUtility.IsPartOfNonAssetPrefabInstance(prefabContentsRoot);\n            if (partOfInstance)\n                return Icons.prefabVariantIcon;\n            return Icons.prefabIcon;\n        }\n\n        internal override void OnControlsGUI(SceneView sceneView)\n        {\n            GUILayout.Space(15);\n            if (mode == Mode.InContext)\n            {\n                InContextModeSelector(sceneView);\n                GUILayout.Space(15);\n                VisualizeOverridesToggle();\n                GUILayout.Space(15);\n            }\n            SaveButtons(sceneView);\n        }\n\n        internal override void PlaceGameObjectInStage(GameObject rootGameObject)\n        {\n            if (this != null && isValid)\n                rootGameObject.transform.SetParent(prefabContentsRoot.transform, true);\n        }\n\n        internal override void SaveHierarchyState(SceneHierarchyWindow hierarchyWindow)\n        {\n            if (!isValid)\n                return;\n\n            Hash128 key = StageUtility.CreateWindowAndStageIdentifier(hierarchyWindow.windowGUID, this);\n            var state = s_StateCache.GetState(key);\n            if (state == null)\n                state = new PrefabStageHierarchyState();\n            state.SaveStateFromHierarchy(hierarchyWindow, this);\n            s_StateCache.SetState(key, state);\n        }\n\n        PrefabStageHierarchyState GetStoredHierarchyState(SceneHierarchyWindow hierarchyWindow)\n        {\n            Hash128 key = StageUtility.CreateWindowAndStageIdentifier(hierarchyWindow.windowGUID, this);\n            return s_StateCache.GetState(key);\n        }\n\n        internal override void LoadHierarchyState(SceneHierarchyWindow hierarchy)\n        {\n            if (!isValid)\n                return;\n\n            var state = GetStoredHierarchyState(hierarchy);\n            if (state != null)\n                state.LoadStateIntoHierarchy(hierarchy, this);\n            else\n                OnFirstTimeOpenStageInSceneHierachyWindow(hierarchy);\n        }\n\n        void InitContextRenderModeSelector()\n        {\n            if (m_Mode != Mode.InContext)\n                return;\n\n            List<ExposablePopupMenu.ItemData> buttonData = new List<ExposablePopupMenu.ItemData>();\n\n            GUIStyle onStyle = Styles.exposablePopupItem;\n            GUIStyle offStyle = Styles.exposablePopupItem;\n            var currentState = StageNavigationManager.instance.contextRenderMode;\n\n            for (int i = 0; i < Styles.contextRenderModeTexts.Length; ++i)\n            {\n                bool on = currentState == Styles.contextRenderModeOptions[i];\n                buttonData.Add(new ExposablePopupMenu.ItemData(Styles.contextRenderModeTexts[i], on ? onStyle : offStyle, on, true, Styles.contextRenderModeOptions[i]));\n            }\n\n            GUIContent popupButtonContent = Styles.contextRenderModeTexts[(int)currentState];\n\n            ExposablePopupMenu.PopupButtonData popListData = new ExposablePopupMenu.PopupButtonData(popupButtonContent, Styles.exposablePopup);\n            s_ContextRenderModeSelector.Init(Styles.contextLabel, buttonData, 4f, 50, popListData, ContextRenderModeClickedCallback);\n            s_ContextRenderModeSelector.rightAligned = true;\n        }\n\n        void ContextRenderModeClickedCallback(ExposablePopupMenu.ItemData itemClicked)\n        {\n            // Behave like radio buttons: a button that is on cannot be turned off\n            if (!itemClicked.m_On)\n            {\n                var selectedMode = (StageUtility.ContextRenderMode)itemClicked.m_UserData;\n                StageNavigationManager.instance.contextRenderMode = selectedMode;\n\n                // Ensure to recalc widths and selected texts\n                InitContextRenderModeSelector();\n            }\n        }\n\n        void InContextModeSelector(SceneView sceneView)\n        {\n            if (s_ContextRenderModeSelector == null)\n            {\n                s_ContextRenderModeSelector = new ExposablePopupMenu();\n                InitContextRenderModeSelector();\n            }\n\n            EditorGUI.BeginChangeCheck();\n            var rect = GUILayoutUtility.GetRect(s_ContextRenderModeSelector.widthOfPopupAndLabel, s_ContextRenderModeSelector.widthOfButtonsAndLabel, 0, 22);\n            s_ContextRenderModeSelector.OnGUI(rect);\n            if (EditorGUI.EndChangeCheck())\n            {\n                SceneView.RepaintAll();\n            }\n        }\n\n        internal bool showOverrides\n        {\n            get\n            {\n                return s_PatchAllOverriddenProperties.value && !m_TemporarilyDisablePatchAllOverridenProperties;\n            }\n            set\n            {\n                if (m_TemporarilyDisablePatchAllOverridenProperties)\n                    return;\n\n                if (value == s_PatchAllOverriddenProperties.value)\n                    return;\n\n                s_PatchAllOverriddenProperties.value = value;\n\n                var stageHistory = StageNavigationManager.instance.stageHistory;\n                foreach (var stage in stageHistory)\n                {\n                    PrefabStage prefabStage = stage as PrefabStage;\n                    if (prefabStage != null)\n                        prefabStage.RefreshPatchedProperties();\n                }\n\n                PropertyEditor.ClearAndRebuildAll();\n            }\n        }\n\n        void RefreshPatchedProperties()\n        {\n            DrivenPropertyManager.UnregisterProperties(this);\n            RecordPatchedPropertiesForContent();\n            ApplyPatchedPropertiesToContent();\n        }\n\n        void VisualizeOverridesToggle()\n        {\n            using (new EditorGUI.DisabledScope(!IsOpenedFromInstanceObjectValid() || m_TemporarilyDisablePatchAllOverridenProperties))\n            {\n                EditorGUI.BeginChangeCheck();\n                var content = m_TemporarilyDisablePatchAllOverridenProperties ? Styles.showOverridesLabelWithTooManyOverridesTooltip : Styles.showOverridesLabel;\n                bool patchAll = GUILayout.Toggle(showOverrides, content);\n                if (EditorGUI.EndChangeCheck())\n                    showOverrides = patchAll;\n            }\n        }\n\n        void CachePrefabFolderInfo()\n        {\n            bool isRootFolder;\n            m_IsPrefabInValidAssetFolder = AssetDatabase.TryGetAssetFolderInfo(m_PrefabAssetPath, out isRootFolder, out m_IsPrefabInImmutableFolder);\n        }\n\n        bool IsPrefabInImmutableFolder()\n        {\n            return !m_IsPrefabInValidAssetFolder || m_IsPrefabInImmutableFolder;\n        }\n\n        void SaveButtons(SceneView sceneView)\n        {\n            if (IsPrefabInImmutableFolder())\n            {\n                GUILayout.Label(Styles.immutablePrefabContent, EditorStyles.boldLabel);\n                return;\n            }\n\n            StatusQueryOptions opts = EditorUserSettings.allowAsyncStatusUpdate ? StatusQueryOptions.UseCachedAsync : StatusQueryOptions.UseCachedIfPossible;\n            bool openForEdit = AssetDatabase.IsOpenForEdit(assetPath, opts);\n\n            if (showingSavingLabel)\n            {\n                GUILayout.Label(Styles.autoSavingBadgeContent, Styles.savingBadge);\n                GUILayout.Space(4);\n            }\n\n            if (!autoSave)\n            {\n                using (new EditorGUI.DisabledScope((!openForEdit || !hasUnsavedChanges) && !isAssetMissing))\n                {\n                    if (GUILayout.Button(Styles.saveButtonContent, Styles.button))\n                        Save();\n                }\n            }\n\n            if (EditorSettings.prefabModeAllowAutoSave)\n            {\n                bool autoSaveForScene = autoSave;\n                EditorGUI.BeginChangeCheck();\n                autoSaveForScene = GUILayout.Toggle(autoSaveForScene, Styles.autoSaveGUIContent, Styles.saveToggle);\n                if (EditorGUI.EndChangeCheck())\n                    autoSave = autoSaveForScene;\n            }\n\n            if (!openForEdit)\n            {\n                if (GUILayout.Button(Styles.checkoutButtonContent, Styles.button))\n                    AssetDatabase.MakeEditable(assetPath);\n            }\n        }\n\n        internal const HideFlags kVisibleEnvironmentObjectHideFlags = HideFlags.DontSave | HideFlags.NotEditable;\n        internal const HideFlags kNotVisibleEnvironmentObjectHideFlags = HideFlags.DontSave | HideFlags.NotEditable | HideFlags.HideInHierarchy;\n\n        class HideFlagUtility\n        {\n            int m_LastSceneDirtyID = -1;\n            List<GameObject> m_Roots = new List<GameObject>();\n            GameObject m_PrefabInstanceRoot;\n            Scene m_Scene;\n\n            public HideFlagUtility(Scene scene, GameObject prefabInstanceRoot)\n            {\n                m_Scene = scene;\n                m_PrefabInstanceRoot = prefabInstanceRoot;\n            }\n\n            public void UpdateEnvironmentHideFlagsIfNeeded()\n            {\n                if (m_LastSceneDirtyID == m_Scene.dirtyID)\n                    return;\n                m_LastSceneDirtyID = m_Scene.dirtyID;\n                UpdateEnvironmentHideFlags();\n            }\n\n            public void UpdateEnvironmentHideFlags()\n            {\n                ValidatePreviewSceneConsistency();\n\n                // We use hideflags to hide all environment objects (and make them non-editable since the user cannot save them)\n                GameObject rootOfPrefabInstance = GetRoot(m_PrefabInstanceRoot);\n\n                // Set all environment root hierarchies\n                m_Scene.GetRootGameObjects(m_Roots);\n                foreach (GameObject go in m_Roots)\n                {\n                    if (go == rootOfPrefabInstance)\n                        continue;\n\n                    SetHideFlagsRecursively(go.transform, kNotVisibleEnvironmentObjectHideFlags);\n                }\n\n                if (rootOfPrefabInstance != m_PrefabInstanceRoot)\n                {\n                    // Our prefab instance root might be a child of an environment object. Here we set those environment objects hidden (leaving the root prefab instance unchanged)\n                    SetHideFlagsRecursivelyWithIgnore(rootOfPrefabInstance.transform, m_PrefabInstanceRoot.transform, kNotVisibleEnvironmentObjectHideFlags);\n\n                    // And finally we ensure the ancestors of the prefab root are visible\n                    Transform current = m_PrefabInstanceRoot.transform.parent;\n                    while (current != null)\n                    {\n                        if (current.hideFlags != kVisibleEnvironmentObjectHideFlags)\n                            current.gameObject.hideFlags = kVisibleEnvironmentObjectHideFlags;\n                        current = current.parent;\n                    }\n                }\n            }\n\n            static GameObject GetRoot(GameObject go)\n            {\n                Transform current = go.transform;\n                while (true)\n                {\n                    if (current.parent == null)\n                        return current.gameObject;\n                    current = current.parent;\n                }\n            }\n\n            static void SetHideFlagsRecursively(Transform transform, HideFlags hideFlags)\n            {\n                if (transform.hideFlags != hideFlags)\n                    transform.gameObject.hideFlags = hideFlags;\n\n                for (int i = 0; i < transform.childCount; i++)\n                    SetHideFlagsRecursively(transform.GetChild(i), hideFlags);\n            }\n\n            static void SetHideFlagsRecursivelyWithIgnore(Transform transform, Transform ignoreThisTransform, HideFlags hideFlags)\n            {\n                if (transform == ignoreThisTransform)\n                    return;\n\n                if (transform.gameObject.hideFlags != hideFlags)\n                    transform.gameObject.hideFlags = hideFlags;  // GameObject also sets all components so check before setting\n\n                for (int i = 0; i < transform.childCount; i++)\n                    SetHideFlagsRecursivelyWithIgnore(transform.GetChild(i), ignoreThisTransform, hideFlags);\n            }\n\n            void ValidatePreviewSceneConsistency()\n            {\n                if (!ValidatePreviewSceneState.ValidatePreviewSceneObjectState(m_PrefabInstanceRoot))\n                {\n                    ValidatePreviewSceneState.LogErrors();\n                }\n            }\n        }\n\n        static class ValidatePreviewSceneState\n        {\n            static List<string> m_Errors = new List<string>();\n\n            public static void LogErrors()\n            {\n                string combinedErrors = string.Join(\"\\n\", m_Errors.ToArray());\n                Debug.LogError(\"Inconsistent preview object state:\\n\" + combinedErrors);\n            }\n\n            static public bool ValidatePreviewSceneObjectState(GameObject root)\n            {\n                m_Errors.Clear();\n                TransformVisitor visitor = new TransformVisitor();\n                visitor.VisitAll(root.transform, ValidateGameObject, null);\n                return m_Errors.Count == 0;\n            }\n\n            static void ValidateGameObject(Transform transform, object userData)\n            {\n                GameObject go = transform.gameObject;\n                if (!EditorSceneManager.IsPreviewSceneObject(go))\n                {\n                    m_Errors.Add(\"   GameObject not correctly marked as PreviewScene object: \" + go.name);\n                }\n\n                var components = go.GetComponents<Component>();\n                foreach (var c in components)\n                {\n                    if (c == null)\n                    {\n                        // This can happen if a monobehaviour has a missing script.\n                        // In this case the check can not be made. Could be fixed\n                        // by moving the component iteration to native code.\n                        continue;\n                    }\n                    if (!EditorSceneManager.IsPreviewSceneObject(c))\n                        m_Errors.Add(string.Format(\"   Component {0} not correctly marked as PreviewScene object: (GameObject: {1})\", c.GetType().Name, go.name));\n                }\n            }\n        }\n\n        void OnPlayModeStateChanged(PlayModeStateChange playmodeState)\n        {\n            if (playmodeState == PlayModeStateChange.ExitingEditMode)\n            {\n                bool blockPrefabModeInPlaymode = PrefabStageUtility.CheckIfAnyComponentShouldBlockPrefabModeInPlayMode(assetPath);\n                if (blockPrefabModeInPlaymode)\n                {\n                    StageNavigationManager.instance.GoToMainStage(StageNavigationManager.Analytics.ChangeType.GoToMainViaPlayModeBlocking);\n                }\n            }\n\n            if (playmodeState == PlayModeStateChange.EnteredEditMode)\n            {\n                // When exiting play mode we reload scenes and if we are in in Prefab Mode in Context we need to reconstruct the hidden state\n                // for the the instance in the previous stage (this is setup when entering Prefab Mode in Context)\n                if (mode == Mode.InContext && m_OpenedFromInstanceRoot != null)\n                    SetPrefabInstanceHiddenForInContextEditing(true);\n            }\n        }\n\n        [OnOpenAsset]\n        static bool OnOpenAsset(int instanceID, int line)\n        {\n            string assetPath = AssetDatabase.GetAssetPath(instanceID);\n\n            if (assetPath.EndsWith(\".prefab\", StringComparison.OrdinalIgnoreCase))\n            {\n                // The 'line' parameter can be used for passing an instanceID of a prefab instance\n                GameObject instanceRoot = line == -1 ? null : EditorUtility.InstanceIDToObject(line) as GameObject;\n                var prefabStageMode = instanceRoot != null ? PrefabStage.Mode.InContext : PrefabStage.Mode.InIsolation;\n                PrefabStageUtility.OpenPrefab(assetPath, instanceRoot, prefabStageMode, StageNavigationManager.Analytics.ChangeType.EnterViaAssetOpened);\n                return true;\n            }\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.SceneManagement\n{\n    public sealed partial class PrefabStage : PreviewSceneStage\n    {\n        // Not using API Updater for now since it doesn't support updating to a virtual property,\n        // and this caused API Updader tests to fail.\n        // (UnityUpgradable) -> assetPath\n        [Obsolete(\"prefabAssetPath has been deprecated. Use assetPath instead.\")]\n        public string prefabAssetPath\n        {\n            get { return m_PrefabAssetPath; }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing System.Collections.Generic;\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEngine.SceneManagement;\nusing UnityEngine.Scripting;\nusing UnityEngine.Scripting.APIUpdating;\n\n\nnamespace UnityEditor.SceneManagement\n{\n    [MovedFrom(\"UnityEditor.Experimental.SceneManagement\")]\n    public static class PrefabStageUtility\n    {\n        [Shortcut(\"Stage/Enter Prefab Mode\", KeyCode.P, displayName = \"Stage/Edit Prefab in Context\")]\n        static void EnterInContextPrefabModeShortcut()\n        {\n            EnterPrefabModeFromCurrentSelection(PrefabStage.Mode.InContext);\n        }\n\n        [Shortcut(\"Stage/Edit Prefab in Isolation\")]\n        static void EnterIsolationPrefabModeShortcut()\n        {\n            EnterPrefabModeFromCurrentSelection(PrefabStage.Mode.InIsolation);\n        }\n\n        static void EnterPrefabModeFromCurrentSelection(PrefabStage.Mode preferredMode)\n        {\n            var activeGameObject = Selection.activeGameObject;\n            if (activeGameObject == null)\n                return;\n\n            if (PrefabUtility.IsPartOfAnyPrefab(activeGameObject))\n            {\n                var prefabPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(activeGameObject);\n                if (!string.IsNullOrEmpty(prefabPath) && prefabPath.EndsWith(\".prefab\", StringComparison.OrdinalIgnoreCase))\n                {\n                    PrefabStage.Mode prefabStageMode = preferredMode;\n                    GameObject openedFromInstance = null;\n                    if (preferredMode == PrefabStage.Mode.InContext)\n                    {\n                        openedFromInstance = !EditorUtility.IsPersistent(activeGameObject) ? activeGameObject : null;\n                        prefabStageMode = openedFromInstance != null ? PrefabStage.Mode.InContext : PrefabStage.Mode.InIsolation;\n                    }\n\n                    OpenPrefab(prefabPath, openedFromInstance, prefabStageMode);\n                }\n            }\n        }\n\n        public static PrefabStage OpenPrefab(string prefabAssetPath)\n        {\n            return OpenPrefab(prefabAssetPath, null, PrefabStage.Mode.InIsolation);\n        }\n\n        public static PrefabStage OpenPrefab(string prefabAssetPath, GameObject openedFromInstance)\n        {\n            var prefabStageMode = openedFromInstance != null ? PrefabStage.Mode.InContext : PrefabStage.Mode.InIsolation;\n            return OpenPrefab(prefabAssetPath, openedFromInstance, prefabStageMode, StageNavigationManager.Analytics.ChangeType.EnterViaUnknown);\n        }\n\n        internal static PrefabStage OpenPrefab(string prefabAssetPath, GameObject openedFromInstance, StageNavigationManager.Analytics.ChangeType changeTypeAnalytics)\n        {\n            var prefabStageMode = openedFromInstance != null ? PrefabStage.Mode.InContext : PrefabStage.Mode.InIsolation;\n            return OpenPrefab(prefabAssetPath, openedFromInstance, prefabStageMode, changeTypeAnalytics);\n        }\n\n        public static PrefabStage OpenPrefab(string prefabAssetPath, GameObject openedFromInstance, PrefabStage.Mode prefabStageMode)\n        {\n            return OpenPrefab(prefabAssetPath, openedFromInstance, prefabStageMode, StageNavigationManager.Analytics.ChangeType.EnterViaUnknown);\n        }\n\n        internal static PrefabStage OpenPrefab(string prefabAssetPath, GameObject openedFromInstance, PrefabStage.Mode prefabStageMode, StageNavigationManager.Analytics.ChangeType changeTypeAnalytics)\n        {\n            if (string.IsNullOrEmpty(prefabAssetPath))\n                throw new ArgumentNullException(nameof(prefabAssetPath));\n\n            if (openedFromInstance != null && !PrefabUtility.IsPartOfPrefabInstance(openedFromInstance))\n                throw new ArgumentException(\"GameObject must be part of a Prefab instance, or null.\", nameof(openedFromInstance));\n\n            if (!prefabAssetPath.EndsWith(\".prefab\", StringComparison.OrdinalIgnoreCase))\n                throw new ArgumentException(\"Incorrect file extension: \" + prefabAssetPath + \". Must be '.prefab'\", nameof(prefabAssetPath));\n\n            if (AssetDatabase.LoadMainAssetAtPath(prefabAssetPath) == null)\n                throw new ArgumentException(\"Prefab not found at path \" + prefabAssetPath, nameof(prefabAssetPath));\n\n            return OpenPrefabMode(prefabAssetPath, openedFromInstance, prefabStageMode, changeTypeAnalytics);\n        }\n\n        static PrefabStage GetExistingPrefabStage(string prefabAssetPath, GameObject openedFromInstance, PrefabStage.Mode prefabStageMode)\n        {\n            var stageHistory = StageNavigationManager.instance.stageHistory;\n            for (int i = 1; i < stageHistory.Count; i++)\n            {\n                var prefabStage = stageHistory[i] as PrefabStage;\n                if (prefabStage != null && prefabStage.assetPath == prefabAssetPath)\n                {\n                    // If PrefabStage.Mode did not match on existing PrefabStage we do not reuse the stage\n                    // so we create a new PrefabStage with the correct mode\n                    if (prefabStage.mode == prefabStageMode)\n                        return prefabStage;\n                }\n            }\n            return null;\n        }\n\n        internal static PrefabStage OpenPrefabMode(string prefabAssetPath, GameObject openedFromInstance, PrefabStage.Mode prefabStageMode, StageNavigationManager.Analytics.ChangeType changeTypeAnalytics)\n        {\n            if (EditorApplication.isPlaying)\n            {\n                bool blockPrefabModeInPlaymode = CheckIfAnyComponentShouldBlockPrefabModeInPlayMode(prefabAssetPath);\n                if (blockPrefabModeInPlaymode)\n                    return null;\n            }\n\n            PrefabStage prevPrefabStage = GetCurrentPrefabStage();\n            bool setAsFirstItemAfterMainStage = prevPrefabStage == null || !IsPartOfPrefabStage(openedFromInstance, prevPrefabStage);\n\n            var previousSelection = Selection.activeGameObject;\n            UInt64 previousFileID = (openedFromInstance != null) ? GetFileIDForCorrespondingObjectFromSourceAtPath(previousSelection, prefabAssetPath) : 0;\n\n            // Ensure valid prefabStageMode (if no context then do not allow Prefab Mode in Context)\n            if (openedFromInstance == null && prefabStageMode != PrefabStage.Mode.InIsolation)\n                prefabStageMode = PrefabStage.Mode.InIsolation;\n\n            Stage contextStage = null;\n            if (prefabStageMode == PrefabStage.Mode.InContext)\n            {\n                var stageHistory = StageNavigationManager.instance.stageHistory;\n                contextStage = stageHistory[stageHistory.Count - 1].GetContextStage();\n            }\n\n            var prefabStage = GetExistingPrefabStage(prefabAssetPath, openedFromInstance, prefabStageMode);\n            if (prefabStage == null)\n                prefabStage = PrefabStage.CreatePrefabStage(prefabAssetPath, openedFromInstance, prefabStageMode, contextStage);\n            if (StageNavigationManager.instance.SwitchToStage(prefabStage, setAsFirstItemAfterMainStage, changeTypeAnalytics))\n            {\n                // If selection did not change by switching stage by us or user (or if current selection is not part of\n                // the opened prefab stage) then handle automatic selection in new prefab mode.\n                if (Selection.activeGameObject == previousSelection || !prefabStage.IsPartOfPrefabContents(Selection.activeGameObject))\n                {\n                    HandleSelectionWhenSwithingToNewPrefabMode(GetCurrentPrefabStage().prefabContentsRoot, previousFileID);\n                }\n\n                SceneView.RepaintAll();\n                return prefabStage;\n            }\n            else\n            {\n                // Failed to switch to new stage\n                return null;\n            }\n        }\n\n        static void HandleSelectionWhenSwithingToNewPrefabMode(GameObject prefabContentsRoot, UInt64 previousFileID)\n        {\n            GameObject newSelection = null;\n\n            if (previousFileID != 0)\n                newSelection = FindFirstGameObjectThatMatchesFileID(prefabContentsRoot.transform, previousFileID, true);\n\n            if (newSelection == null)\n                newSelection = prefabContentsRoot;\n\n            Selection.activeGameObject = newSelection;\n\n            // For Prefab Mode we restore the last expanded tree view state for the opened Prefab. For usability\n            // if a child GameObject on the Prefab Instance is selected when entering the Prefab Asset Mode we select the corresponding\n            // child GameObject in the Asset. Here we ensure that selction is revealed and framed in the Scene hierarchy.\n            if (newSelection != prefabContentsRoot)\n            {\n                foreach (SceneHierarchyWindow shw in SceneHierarchyWindow.GetAllSceneHierarchyWindows())\n                    shw.FrameObject(newSelection.GetInstanceID(), false);\n            }\n        }\n\n        static bool IsPartOfPrefabStage(GameObject gameObject, PrefabStage prefabStage)\n        {\n            if (gameObject == null)\n                return false;\n            return FindGameObjectRecursive(prefabStage.prefabContentsRoot.transform, gameObject);\n        }\n\n        static bool FindGameObjectRecursive(Transform transform, GameObject gameObject)\n        {\n            if (transform.gameObject == gameObject)\n                return true;\n\n            for (int i = 0; i < transform.childCount; ++i)\n            {\n                if (FindGameObjectRecursive(transform.GetChild(i), gameObject))\n                    return true;\n            }\n            return false;\n        }\n\n        static UInt64 GetFileIDForCorrespondingObjectFromSourceAtPath(GameObject gameObject, string prefabAssetPath)\n        {\n            if (gameObject == null)\n                return 0;\n\n            if (EditorUtility.IsPersistent(gameObject))\n                return 0;\n\n            if (!PrefabUtility.IsPartOfNonAssetPrefabInstance(gameObject))\n                return 0;\n\n            GameObject assetGameObject = PrefabUtility.GetCorrespondingObjectFromSourceAtPath(gameObject, prefabAssetPath);\n            if (assetGameObject == null)\n                return 0;\n\n            return Unsupported.GetOrGenerateFileIDHint(assetGameObject);\n        }\n\n        // Returns true any component in prefab is blocking Prefab Mode in Play Mode\n        internal static bool CheckIfAnyComponentShouldBlockPrefabModeInPlayMode(string prefabAssetPath)\n        {\n            var assetRoot = AssetDatabase.LoadAssetAtPath<GameObject>(prefabAssetPath);\n            if (assetRoot == null)\n                return false;\n            var monoBehaviors = assetRoot.GetComponentsInChildren<MonoBehaviour>(true);  // also check the inactive since these can be made active while in play mode\n            var warnList = new List<MonoBehaviour>();\n            foreach (var m in monoBehaviors)\n            {\n                if (m != null && !m.allowPrefabModeInPlayMode)\n                    warnList.Add(m);\n            }\n\n            if (warnList.Count > 0)\n            {\n                string blockingNames = string.Join(\", \", warnList.Select(e => MonoScript.FromMonoBehaviour(e).name).Distinct().ToArray());\n                if (blockingNames.Length > 1000)\n                    blockingNames = blockingNames.Substring(0, 1000) + \"\\n...\";\n                return EditorUtility.DisplayDialog(\n                    L10n.Tr(\"Risk of unwanted modifications\"),\n                    string.Format(\n                        L10n.Tr(\"The following scripts on the Prefab open in Prefab Mode use the [ExecuteInEditMode] attribute which means they may accidentally affect or be affected by Play Mode:\\n\\n{0}\\n\\nSee the documentation for [ExecuteInEditMode] and [ExecuteAlways] for info on how to make scripts compatible with Prefab Mode during Play Mode.\"),\n                        blockingNames),\n                    L10n.Tr(\"Exit Prefab Mode\"), L10n.Tr(\"Ignore\"));\n            }\n            return false;\n        }\n\n        [RequiredByNativeCode]\n        public static PrefabStage GetCurrentPrefabStage()\n        {\n            return StageNavigationManager.instance.currentStage as PrefabStage;\n        }\n\n        public static PrefabStage GetPrefabStage(GameObject gameObject)\n        {\n            return StageUtility.GetStage(gameObject) as PrefabStage;\n        }\n\n        [RequiredByNativeCode]\n        internal static bool SaveCurrentModifiedPrefabStagesIfUserWantsTo()\n        {\n            // Returns false if the user clicked Cancel to save otherwise returns true\n            var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();\n            if (prefabStage != null)\n                return prefabStage.AskUserToSaveModifiedStageBeforeSwitchingStage();\n\n            return true;\n        }\n\n        [UsedByNativeCode]\n        internal static bool IsAssetPathOpenInAnyPrefabStage(string path)\n        {\n            foreach (var stage in StageNavigationManager.instance.stageHistory)\n            {\n                var prefabStage = stage as PrefabStage;\n                if (prefabStage != null && prefabStage.isValid && prefabStage.assetPath == path)\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        [UsedByNativeCode]\n        internal static bool IsGameObjectThePrefabRootInAnyPrefabStage(GameObject gameObject)\n        {\n            PrefabStage prefabStage = GetCurrentPrefabStage();\n            if (prefabStage != null && prefabStage.isValid)\n            {\n                return prefabStage.prefabContentsRoot == gameObject;\n            }\n            return false;\n        }\n\n        [UsedByNativeCode]\n        internal static bool IsPrefabStageScene(Scene scene)\n        {\n            foreach (var prefabStage in PrefabStage.allPrefabStages)\n                if (prefabStage.scene == scene)\n                    return true;\n            return false;\n        }\n\n        static bool IsDynamicallyCreatedDuringLoad(GameObject gameObject)\n        {\n            return Unsupported.GetFileIDHint(gameObject) == 0;\n        }\n\n        static UInt64 GetPersistentPrefabOrVariantFileIdentifier(GameObject gameObject)\n        {\n            var handle = PrefabUtility.GetPrefabInstanceHandle(gameObject);\n            if (handle != null)\n                return Unsupported.GetLocalIdentifierInFileForPersistentObject(handle);\n\n            return Unsupported.GetLocalIdentifierInFileForPersistentObject(gameObject);\n        }\n\n        static UInt64 GetPrefabOrVariantFileID(GameObject gameObject)\n        {\n            var handle = PrefabUtility.GetPrefabInstanceHandle(gameObject);\n            if (handle != null)\n                return Unsupported.GetFileIDHint(handle);\n\n            return Unsupported.GetFileIDHint(gameObject);\n        }\n\n        internal static GameObject FindFirstGameObjectThatMatchesFileID(Transform searchRoot, UInt64 fileID, bool generate)\n        {\n            GameObject result = null;\n            var transformVisitor = new TransformVisitor();\n            transformVisitor.VisitAndAllowEarlyOut(searchRoot,\n                (transform, userdata) =>\n                {\n                    UInt64 id = generate ?\n                        Unsupported.GetOrGenerateFileIDHint(transform.gameObject) :\n                        GetPrefabOrVariantFileID(transform.gameObject);\n                    if (id == fileID)\n                    {\n                        result = transform.gameObject;\n                        return false; // stop searching\n                    }\n                    return true; // continue searching\n                }\n                , null);\n\n            return result;\n        }\n\n        static void RemoveBrokenPrefabRootsIfNeeded(string prefabAssetPath, GameObject[] environmentRoots, GameObject[] rootsAfterLoadingPrefab, GameObject rootGameObject)\n        {\n            var rootsLoadedFromFile = rootsAfterLoadingPrefab.Except(environmentRoots).ToList();\n\n            // Filter out the subset of roots that were loaded from the Prefab file (there can be dynamically created environment objects,\n            // created from Awake and OnEnable calls from user land, if they use ExecuteAlways or ExecuteInEditMode.\n            rootsLoadedFromFile.RemoveAll(x => IsDynamicallyCreatedDuringLoad(x));\n\n            if (rootsLoadedFromFile.Count >= 2)\n            {\n                Debug.LogError(string.Format(\"Prefab Mode: Broken Prefab with multiple roots detected ('{0}')\", prefabAssetPath));\n                foreach (var go in rootsLoadedFromFile)\n                {\n                    if (go != rootGameObject)\n                    { \n                        UnityEngine.Object.DestroyImmediate(go);\n                    }\n                }\n            }\n        }\n\n        internal static GameObject LoadPrefabIntoPreviewScene(string prefabAssetPath, Scene previewScene)\n        {\n            var prefabName = Path.GetFileNameWithoutExtension(prefabAssetPath);\n            previewScene.name = prefabName;\n\n            // Get start roots from scene (before loading in the the Prefab)\n            var environmentRoots = previewScene.GetRootGameObjects();\n            GameObject rootGameObject = null;\n\n            // Load Prefab into scene\n            try\n            {\n                PrefabUtility.LoadPrefabContentsIntoPreviewScene(prefabAssetPath, previewScene, out rootGameObject);\n            }\n            catch (Exception e)\n            {\n                Debug.LogError(string.Format(\"Loading Prefab failed: {0}\", e.Message));\n                return null;\n            }\n\n            var rootsAfterLoadingPrefab = previewScene.GetRootGameObjects();\n            RemoveBrokenPrefabRootsIfNeeded(prefabAssetPath, environmentRoots, rootsAfterLoadingPrefab, rootGameObject);\n\n            return rootGameObject;\n        }\n\n        static string GetEnvironmentScenePathForPrefab(bool isUIPrefab)\n        {\n            string environmentEditingScenePath = \"\";\n\n            // If prefab root has RectTransform, try to use UI environment.\n            if (isUIPrefab)\n            {\n                if (EditorSettings.prefabUIEnvironment != null)\n                    environmentEditingScenePath = AssetDatabase.GetAssetPath(EditorSettings.prefabUIEnvironment);\n            }\n            // Else try to use regular environment.\n            // Note, if the prefab is a UI object we deliberately don't use the regular environment as fallback,\n            // since our empty scene with auto-generated Canvas is likely a better fallback than an environment\n            // designed for non-UI objects.\n            else\n            {\n                if (EditorSettings.prefabRegularEnvironment != null)\n                    environmentEditingScenePath = AssetDatabase.GetAssetPath(EditorSettings.prefabRegularEnvironment);\n            }\n\n            return environmentEditingScenePath;\n        }\n\n        static Scene LoadOrCreatePreviewScene(string environmentEditingScenePath)\n        {\n            Scene previewScene;\n            if (!string.IsNullOrEmpty(environmentEditingScenePath))\n            {\n                previewScene = EditorSceneManager.OpenPreviewScene(environmentEditingScenePath);\n                var roots = previewScene.GetRootGameObjects();\n                var visitor = new TransformVisitor();\n                foreach (var root in roots)\n                {\n                    visitor.VisitAll(root.transform, AppendEnvironmentName, null);\n                }\n            }\n            else\n            {\n                previewScene = CreateDefaultPreviewScene();\n            }\n\n            return previewScene;\n        }\n\n        static void AppendEnvironmentName(Transform transform, object userData)\n        {\n            transform.gameObject.name += \" (Environment)\";\n        }\n\n        static Scene CreateDefaultPreviewScene()\n        {\n            Scene previewScene = EditorSceneManager.NewPreviewScene();\n\n            // Setup default render settings for this preview scene\n            Unsupported.SetOverrideLightingSettings(previewScene);\n            UnityEngine.RenderSettings.defaultReflectionMode = UnityEngine.Rendering.DefaultReflectionMode.Custom;\n            UnityEngine.RenderSettings.customReflectionTexture = GetDefaultReflection();   // ensure chrome materials do not render black\n            UnityEngine.RenderSettings.skybox = AssetDatabase.GetBuiltinExtraResource<Material>(\"Default-Skybox.mat\");\n            UnityEngine.RenderSettings.ambientMode = AmbientMode.Skybox;\n            UnityEditorInternal.InternalEditorUtility.CalculateAmbientProbeFromSkybox();\n            Unsupported.RestoreOverrideLightingSettings();\n\n            return previewScene;\n        }\n\n        static Cubemap s_DefaultReflection;\n        static Cubemap GetDefaultReflection()\n        {\n            const string path = \"PrefabMode/DefaultReflectionForPrefabMode.exr\";\n            if (s_DefaultReflection == null)\n            {\n                s_DefaultReflection = EditorGUIUtility.Load(path) as Cubemap;\n            }\n\n            if (s_DefaultReflection == null)\n                Debug.LogError(\"Could not find: \" + path);\n            return s_DefaultReflection;\n        }\n\n        internal static void DestroyPreviewScene(Scene previewScene)\n        {\n            if (previewScene.IsValid())\n            {\n                Undo.ClearUndoSceneHandle(previewScene);\n                EditorSceneManager.ClosePreviewScene(previewScene);\n            }\n        }\n\n        internal static Scene GetEnvironmentSceneOrEmptyScene(bool isUIPrefab)\n        {\n            // Create the environment scene and move the prefab root to this scene to ensure\n            // the correct rendersettings (skybox etc) are used in Prefab Mode.\n            string environmentEditingScenePath = GetEnvironmentScenePathForPrefab(isUIPrefab);\n            Scene environmentScene = LoadOrCreatePreviewScene(environmentEditingScenePath);\n            return environmentScene;\n        }\n\n        internal static bool IsUIPrefab(string prefabAssetPath)\n        {\n            // We require a RectTransform and a CanvasRenderer to be considered a UI prefab.\n            // E.g 3D TextMeshPro uses RectTransform but a MeshRenderer so should not be considered a UI prefab\n            // This function needs to be peformant since it is called every time a prefab is opened in a prefab stage.\n            var root = AssetDatabase.LoadMainAssetAtPath(prefabAssetPath) as GameObject;\n            if (root == null)\n                return false;\n\n            // In principle, RectTransforms can be used for other things than UI,\n            // so only treat as UI Prefab if it has both a RectTransform on the root\n            // AND either a Canvas on the root or a CanvasRenderer somewhere in the hierarchy.\n            bool rectTransformOnRoot = root.GetComponent<RectTransform>() != null;\n            bool uiSpecificComponentPresent = (root.GetComponent<Canvas>() != null || root.GetComponentInChildren<CanvasRenderer>(true) != null);\n            return rectTransformOnRoot && uiSpecificComponentPresent;\n        }\n\n        internal static void HandleUIReparentingIfNeeded(GameObject instanceRoot, int stagePriority)\n        {\n            // We need a Canvas in order to render UI so ensure the prefab instance is under a Canvas\n            Canvas canvas = instanceRoot.GetComponent<Canvas>();\n            if (canvas != null)\n            {\n                // We have a Canvas. Check if it's suitable to use as root Canvas.\n                if (canvas.renderMode == RenderMode.WorldSpace)\n                {\n                    // Do nothing; do not early out and use Canvas as root Canvas.\n                    // We can't know if a World Space Canvas was a root or not in all cases,\n                    // but it's important to not make it a root if its RectTransform\n                    // has stretching (non-identical min and max anchors); otherwise it will\n                    // be previewed stretching to a single point (or less!).\n                    // The downsides of making a World Space Canvas that was a root into a\n                    // nested Canvas in Prefab Mode are less severe (a few settings on the\n                    // Canvas component will be hidden), so we make it always nested\n                    // as the lesser evil. Note that regardless, there is no data loss,\n                    // since World Space canvases don't drive their RectTransform.\n                }\n                else\n                {\n                    // A Screen Space Canvas whose RectTransform values are not all 0\n                    // can't have been driven when it was created, which means it can't\n                    // have been a root Canvas. In that case it shouldn't be used as root\n                    // Canvas here either, since that would cause its RectTransform values\n                    // to be overridden with driven values, and then serialized as 0.\n                    RectTransform rt = (RectTransform)canvas.transform;\n                    if (rt.sizeDelta == Vector2.zero && rt.anchorMin == Vector2.zero && rt.anchorMax == Vector2.zero && rt.pivot == Vector2.zero)\n                        return; // Use as root.\n                }\n            }\n\n            GameObject canvasGameObject = GetOrCreateCanvasGameObject(instanceRoot, stagePriority);\n            instanceRoot.transform.SetParent(canvasGameObject.transform, false);\n        }\n\n        static GameObject GetOrCreateCanvasGameObject(GameObject instanceRoot, int stagePriority)\n        {\n            Canvas canvas = GetCanvasInScene(instanceRoot);\n            if (canvas != null)\n            {\n                canvas.stagePriority = (byte)stagePriority;\n                return canvas.gameObject;\n            }\n\n            const string kUILayerName = \"UI\";\n\n            // Create canvas root for the UI\n            GameObject root = EditorUtility.CreateGameObjectWithHideFlags(\"Canvas (Environment)\", HideFlags.DontSave);\n            root.layer = LayerMask.NameToLayer(kUILayerName);\n            canvas = root.AddComponent<Canvas>();\n            canvas.renderMode = RenderMode.ScreenSpaceOverlay;\n            canvas.stagePriority = (byte)stagePriority;\n            SceneManager.MoveGameObjectToScene(root, instanceRoot.scene);\n            return root;\n        }\n\n        static Canvas GetCanvasInScene(GameObject instanceRoot)\n        {\n            Scene scene = instanceRoot.scene;\n            foreach (GameObject go in scene.GetRootGameObjects())\n            {\n                // Do not search for Canvas's under the prefab root since we want to\n                // have a Canvas for the prefab root\n                if (go == instanceRoot)\n                    continue;\n                var canvas = go.GetComponentInChildren<Canvas>();\n                if (canvas != null)\n                    return canvas;\n            }\n            return null;\n        }\n\n        internal static PrefabStage.Mode GetPrefabStageModeFromModifierKeys()\n        {\n            // Update GetPrefabButtonContent if this logic changes\n            var defaultPrefabMode = PreferencesProvider.GetDefaultPrefabModeForHierarchy();\n            var alternativePrefabMode = (defaultPrefabMode == PrefabStage.Mode.InContext) ? PrefabStage.Mode.InIsolation : PrefabStage.Mode.InContext;\n\n            return Event.current.alt ? alternativePrefabMode : defaultPrefabMode;\n        }\n\n        internal static GUIContent GetPrefabButtonContent(int instanceID)\n        {\n            GUIContent result;\n            var defaultPrefabMode = PreferencesProvider.GetDefaultPrefabModeForHierarchy();\n            var modifierKey = Application.platform == RuntimePlatform.OSXEditor ? \"Option\" : \"Alt\";\n            switch (defaultPrefabMode)\n            {\n                case PrefabStage.Mode.InContext:\n                    result = new GUIContent(\"\", null, $\"Open Prefab Asset in context.\\nPress the {modifierKey} modifier key to open in isolation.\");\n                    break;\n                case PrefabStage.Mode.InIsolation:\n                    result = new GUIContent(\"\", null, $\"Open Prefab Asset in isolation.\\nPress the {modifierKey} modifier key to open in context.\");\n                    break;\n                default:\n                    result = new GUIContent(\"\");\n                    Debug.LogError(\"Unhandled defaultPrefabMode enum\");\n                    break;\n            }\n            return result;\n        }\n    }\n}\n\n\n// We keep a dummy UnityEditor.Experimental.SceneManagement namespace declared because the API Updater does\n// not yet support removing the 'using some.namespace.xyz' declarations in files if there is no usage of\n// classes of that namespace in the file. E.g consider this user script which currently is not updated:\n//\n// using UnityEditor.Experimental.SceneManagement;\n// public class SomeClass: MonoBehaviour\n// {\n//      void Update() { };\n// }\n//\n// We can remove the UnityEditor.Experimental.SceneManagement namespace below when the APIUpdater supports updating the above test script\nnamespace UnityEditor.Experimental.SceneManagement\n{\n    class Dummy\n    {\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/PrefabStageHierarchyState.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.SceneManagement;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [Serializable]\n    class PrefabStageHierarchyState\n    {\n        [SerializeField]\n        float m_ScrollY;\n        [SerializeField]\n        List<UInt64> m_ExpandedPrefabGameObjectFileIDs = new List<UInt64>();\n        [SerializeField]\n        UInt64 m_LastClickedFileID;\n\n        public void SaveStateFromHierarchy(SceneHierarchyWindow hierarchy, Stage stage)\n        {\n            var lastClickedGameObject = EditorUtility.InstanceIDToObject(hierarchy.sceneHierarchy.treeViewState.lastClickedID) as GameObject;\n            m_LastClickedFileID = lastClickedGameObject != null ? Unsupported.GetOrGenerateFileIDHint(lastClickedGameObject) : 0;\n            m_ExpandedPrefabGameObjectFileIDs = GetExpandedGameObjectFileIDs(hierarchy);\n\n            m_ScrollY = hierarchy.sceneHierarchy.treeViewState.scrollPos.y;\n\n            if (SceneHierarchy.s_DebugPersistingExpandedState)\n                DebugLog(\"Saving\", stage);\n        }\n\n        public void LoadStateIntoHierarchy(SceneHierarchyWindow hierarchy, Stage stage)\n        {\n            // Restore expanded state always\n            RestoreExandedStateFromFileIDs(hierarchy, stage as PrefabStage, m_ExpandedPrefabGameObjectFileIDs, m_LastClickedFileID);\n\n            // Restore selection and scroll value when requested\n            if (stage.setSelectionAndScrollWhenBecomingCurrentStage)\n            {\n                Selection.activeInstanceID = hierarchy.sceneHierarchy.treeViewState.lastClickedID;\n                hierarchy.sceneHierarchy.treeViewState.scrollPos.y = m_ScrollY;\n            }\n\n            if (SceneHierarchy.s_DebugPersistingExpandedState)\n                DebugLog(\"Restoring\", stage);\n        }\n\n        static List<UInt64> GetExpandedGameObjectFileIDs(SceneHierarchyWindow hierarchy)\n        {\n            var fileIDs = new List<UInt64>();\n            var expandedGameObjects = hierarchy.sceneHierarchy.GetExpandedGameObjects();\n            foreach (var go in expandedGameObjects)\n            {\n                UInt64 fileID = Unsupported.GetOrGenerateFileIDHint(go);\n                if (fileID != 0)\n                    fileIDs.Add(fileID);\n            }\n            return fileIDs;\n        }\n\n        static void RestoreExandedStateFromFileIDs(SceneHierarchyWindow hierarchy, PrefabStage prefabStage, List<UInt64> expandedGameObjectFileIDs, UInt64 lastClickedFileID)\n        {\n            var searchRoot = prefabStage.prefabContentsRoot;\n            var fileIDToInstanceIDMapper = new FileIDToInstanceIDMapper(searchRoot.transform, expandedGameObjectFileIDs, lastClickedFileID);\n            hierarchy.sceneHierarchy.treeViewState.lastClickedID = fileIDToInstanceIDMapper.instanceID;\n            hierarchy.sceneHierarchy.treeViewState.expandedIDs = fileIDToInstanceIDMapper.instanceIDs;\n            hierarchy.sceneHierarchy.treeViewState.expandedIDs.Sort(); // required to be sorted (see TreeViewState)\n        }\n\n        class FileIDToInstanceIDMapper\n        {\n            readonly List<UInt64> m_FileIDs;\n            readonly UInt64 m_FileID = 0;\n\n            public List<int> instanceIDs = new List<int>();\n            public int instanceID = 0;\n\n            public FileIDToInstanceIDMapper(Transform searchRoot, List<UInt64> fileIDs, UInt64 fileID)\n            {\n                m_FileIDs = fileIDs;\n                m_FileID = fileID;\n\n                var transformVisitor = new TransformVisitor();\n                transformVisitor.VisitAll(searchRoot, AddGameObjectIfMatching, null);\n            }\n\n            public void AddGameObjectIfMatching(Transform transform, object userData)\n            {\n                UInt64 fileID = Unsupported.GetOrGenerateFileIDHint(transform.gameObject);\n                if (m_FileIDs.Contains(fileID))\n                    instanceIDs.Add(transform.gameObject.GetInstanceID());\n                if (fileID == m_FileID)\n                    instanceID = transform.gameObject.GetInstanceID();\n            }\n        }\n\n        void DebugLog(string prefix, Stage stage)\n        {\n            Debug.Log(prefix + (stage.GetType().ToString()) + string.Format(\"-prefab stage: {0}, -scrollY: {1}, -selection {2}, -setSelection {3}\",\n                DebugUtils.ListToString(m_ExpandedPrefabGameObjectFileIDs),\n                m_ScrollY,\n                m_LastClickedFileID,\n                stage.setSelectionAndScrollWhenBecomingCurrentStage));\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/PreviewSceneStage.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\n\nnamespace UnityEditor.SceneManagement\n{\n    public abstract class PreviewSceneStage : Stage\n    {\n        Scene m_Scene;\n        public Scene scene { get { return m_Scene; } protected set { m_Scene = value; } }\n\n        internal override int sceneCount { get { return 1; } }\n\n        internal override Scene GetSceneAt(int index)\n        {\n            if (index != 0)\n                throw new IndexOutOfRangeException();\n            return m_Scene;\n        }\n\n        protected PreviewSceneStage()\n        {\n        }\n\n        protected internal override bool OnOpenStage()\n        {\n            m_Scene = EditorSceneManager.NewPreviewScene();\n            return true;\n        }\n\n        protected override void OnCloseStage()\n        {\n            if (scene.IsValid())\n            {\n                Undo.ClearUndoSceneHandle(scene);\n                EditorSceneManager.ClosePreviewScene(scene);\n            }\n        }\n\n        internal override void PlaceGameObjectInStage(GameObject rootGameObject)\n        {\n            if (this != null && scene.IsValid())\n                SceneManager.MoveGameObjectToScene(rootGameObject, scene);\n        }\n\n        internal override void SyncSceneHierarchyToStage(SceneHierarchyWindow sceneHierarchyWindow)\n        {\n            var sceneHierarchy = sceneHierarchyWindow.sceneHierarchy;\n            sceneHierarchy.customScenes = new[] { scene };\n        }\n\n        public override StageHandle stageHandle\n        {\n            get { return StageHandle.GetStageHandle(scene); }\n        }\n\n        internal override ulong GetSceneCullingMask()\n        {\n            return EditorSceneManager.GetSceneCullingMask(scene);\n        }\n\n        internal override void SyncSceneViewToStage(SceneView sceneView)\n        {\n            sceneView.customScene = scene;\n            sceneView.overrideSceneCullingMask = 0;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/SceneViewCameraState.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [Serializable]\n    class SceneViewCameraState\n    {\n        public SceneView.CameraMode cameraMode;\n        public bool sceneLighting;\n        public bool audioPlay;\n        public SceneView.SceneViewState sceneViewState;\n        public bool in2DMode;\n        public Vector3 pivot;\n        public Quaternion rotation;\n        public float size;\n        public bool orthographic;\n        internal bool debugDrawModesUseInteractiveLightBakingData;\n\n        public void SaveStateFromSceneView(SceneView view)\n        {\n            cameraMode = view.cameraMode;\n            sceneLighting = view.sceneLighting;\n            audioPlay = view.audioPlay;\n            sceneViewState = new SceneView.SceneViewState(view.sceneViewState);\n            in2DMode = view.in2DMode;\n            pivot = view.pivot;\n            rotation = view.rotation;\n            size = view.size;\n            orthographic = view.orthographic;\n            debugDrawModesUseInteractiveLightBakingData = view.debugDrawModesUseInteractiveLightBakingData;\n        }\n\n        public void RestoreStateToSceneView(SceneView view)\n        {\n            view.cameraMode = cameraMode;\n            view.sceneLighting = sceneLighting;\n            view.audioPlay = audioPlay;\n            view.sceneViewState = new SceneView.SceneViewState(sceneViewState);\n            view.in2DMode = in2DMode;\n            view.pivot = pivot;\n            if (!view.in2DMode)\n                view.rotation = rotation;\n            view.size = size;\n            view.orthographic = orthographic;\n            view.debugDrawModesUseInteractiveLightBakingData = debugDrawModesUseInteractiveLightBakingData;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/Stage.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Collections.ObjectModel;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\n\nnamespace UnityEditor.SceneManagement\n{\n    public abstract class Stage : ScriptableObject\n    {\n        static List<Stage> s_AllStages = new List<Stage>();\n        internal static ReadOnlyCollection<Stage> allStages {  get { return s_AllStages.AsReadOnly(); } }\n\n        // Stage interface\n\n        // Called when the user have accepted to switch away from previous stage. This method should load stage contents.\n        // Should return 'true' if the stage was opened succesfully otherwise 'false'.\n        protected internal abstract bool OnOpenStage();\n\n        // Called when the stage is destroyed (when OnDestroy() is called). Should unload the contents of the stage.\n        // Only called if OnOpenStage was called.\n        protected abstract void OnCloseStage();\n\n        // Called when returning to a previous open stage (e.g by clicking a non-current breadcrumb)\n        protected internal virtual void OnReturnToStage() {}\n\n        internal bool opened { get; set; }\n\n        internal virtual bool isValid { get { return true; } }\n\n        internal virtual bool isAssetMissing { get { return false; } }\n\n        public virtual string assetPath { get { return string.Empty; } }\n\n        internal virtual bool showOptionsButton { get { return false; } }\n\n        internal abstract int sceneCount { get; }\n        internal abstract Scene GetSceneAt(int index);\n\n        internal virtual bool SupportsSaving() { return false; }\n        internal virtual bool hasUnsavedChanges { get { return false; } }\n        internal virtual bool Save()\n        {\n            if (!SupportsSaving() || !hasUnsavedChanges)\n                return true;\n            throw new System.NotImplementedException(\"This Stage returns true for SupportsSaving() but has not implemented an override for the Save() method.\");\n        }\n\n        internal virtual void DiscardChanges()\n        {\n            if (!SupportsSaving() || !hasUnsavedChanges)\n                return;\n            throw new System.NotImplementedException(\"This Stage returns true for SupportsSaving() but has not implemented an override for the DiscardChanges() method.\");\n        }\n\n        static internal void ShowDiscardChangesDialog(Stage stage)\n        {\n            string title = LocalizationDatabase.GetLocalizedString(\"Discard Changes\");\n            string message = LocalizationDatabase.GetLocalizedString(\"Are you sure you want to discard the changes to:\\n\\n  {0}\\n\\nYour changes will be lost.\");\n\n            message = string.Format(message, System.IO.Path.GetFileName(stage.assetPath));\n\n            if (EditorUtility.DisplayDialog(title, message, LocalizationDatabase.GetLocalizedString(\"OK\"), LocalizationDatabase.GetLocalizedString(\"Cancel\")))\n                stage.DiscardChanges();\n        }\n\n        internal virtual void BuildContextMenuForStageHeader(GenericMenu menu)\n        {\n            if (SupportsSaving())\n            {\n                var saveText = EditorGUIUtility.TrTextContent(\"Save\");\n                var discardText = EditorGUIUtility.TrTextContent(\"Discard changes\");\n\n                // Save\n                if (hasUnsavedChanges)\n                {\n                    menu.AddItem(saveText, false, () =>\n                    {\n                        Save();\n                    });\n                }\n                else\n                {\n                    menu.AddDisabledItem(saveText);\n                }\n\n                menu.AddSeparator(\"\");\n\n                // Discard changes\n                if (hasUnsavedChanges && !isAssetMissing)\n                {\n                    menu.AddItem(discardText, false, () =>\n                    {\n                        ShowDiscardChangesDialog(this);\n                    });\n                }\n                else\n                {\n                    menu.AddDisabledItem(discardText);\n                }\n            }\n        }\n\n        internal virtual bool SaveAsNew()\n        {\n            if (!SupportsSaving())\n                return true;\n            throw new System.NotImplementedException(\"This Stage returns true for SupportsSaving() but has not implemented an override for the SaveAsNew() method.\");\n        }\n\n        // Transient state since it is set every time we switch stage\n        internal bool setSelectionAndScrollWhenBecomingCurrentStage { get; set; } = true;\n\n        internal virtual string GetErrorMessage()\n        {\n            return null;\n        }\n\n        protected internal abstract GUIContent CreateHeaderContent();\n\n        internal virtual BreadcrumbBar.Item CreateBreadcrumbItem()\n        {\n            var history = StageNavigationManager.instance.stageHistory;\n            bool isLastCrumb = this == history.Last();\n            var style = isLastCrumb ? BreadcrumbBar.DefaultStyles.labelBold : BreadcrumbBar.DefaultStyles.label;\n\n            return new BreadcrumbBar.Item\n            {\n                content = CreateHeaderContent(),\n                guistyle = style,\n                userdata = this,\n                separatorstyle = BreadcrumbBar.SeparatorStyle.Line\n            };\n        }\n\n        internal virtual ulong GetSceneCullingMask() { return EditorSceneManager.DefaultSceneCullingMask; }\n\n        public virtual StageHandle stageHandle\n        {\n            get { return StageHandle.GetMainStageHandle(); }\n        }\n\n        public virtual ulong GetCombinedSceneCullingMaskForCamera() { return GetSceneCullingMask(); }\n\n        internal virtual Stage GetContextStage() { return this; }\n\n        internal virtual Color GetBackgroundColor()\n        {\n            // Case 1255995 - Workaround for OSX 10.15 driver issue with Intel 630 cards\n            Color opaqueBackground = SceneView.kSceneViewBackground.Color;\n            opaqueBackground.a = 1;\n            return opaqueBackground;\n        }\n\n        // Called before and after the Scene view renders.\n        internal virtual void OnPreSceneViewRender(SceneView sceneView) {}\n        internal virtual void OnPostSceneViewRender(SceneView sceneView) {}\n\n        // Called when new stage is created, after script reloads, and possibly at other times by the stage itself.\n        internal abstract void SyncSceneViewToStage(SceneView sceneView);\n        internal abstract void SyncSceneHierarchyToStage(SceneHierarchyWindow sceneHierarchyWindow);\n\n        internal virtual void SaveHierarchyState(SceneHierarchyWindow hierarchyWindow) {}\n        internal virtual void LoadHierarchyState(SceneHierarchyWindow hierarchyWindow) {}\n\n        // Called after respective sync methods first time this stage is opened in this window.\n        protected internal virtual void OnFirstTimeOpenStageInSceneView(SceneView sceneView) {}\n        internal virtual void OnFirstTimeOpenStageInSceneHierachyWindow(SceneHierarchyWindow sceneHierarchyWindow) {}\n\n        internal virtual void OnControlsGUI(SceneView sceneView) {}\n\n        internal virtual void Tick()\n        {\n        }\n\n        // Called on the the current stage when trying to switch to new stage. Should return true if it OK to continue to switch away\n        // from current stage. False if not ok to continue.\n        internal virtual bool AskUserToSaveModifiedStageBeforeSwitchingStage()\n        {\n            return true;\n        }\n\n        internal abstract void PlaceGameObjectInStage(GameObject rootGameObject);\n\n        // Used for writing state files to HDD\n        // Should typically be a persistent unique hash per content shown.\n        // For stages that use the assetPath property, the hash is by default based on the asset GUID.\n        protected internal virtual Hash128 GetHashForStateStorage()\n        {\n            if (!string.IsNullOrEmpty(assetPath))\n                return Hash128.Compute(AssetDatabase.AssetPathToGUID(assetPath));\n\n            // If no assetPath is specified, the default behavior is that\n            // every stage of the same type will reuse the same state files.\n            return new Hash128();\n        }\n\n        // Lifetime callbacks from ScriptableObject\n        private void Awake()\n        {\n        }\n\n        private void OnDestroy()\n        {\n            if (opened)\n            {\n                OnCloseStage();\n                opened = false;\n            }\n        }\n\n        protected virtual void OnEnable()\n        {\n            hideFlags = HideFlags.HideAndDontSave;\n            s_AllStages.Add(this);\n        }\n\n        protected virtual void OnDisable()\n        {\n            s_AllStages.Remove(this);\n        }\n\n        public T FindComponentOfType<T>() where T : Component\n        {\n            return stageHandle.FindComponentOfType<T>();\n        }\n\n        public T[] FindComponentsOfType<T>() where T : Component\n        {\n            return stageHandle.FindComponentsOfType<T>();\n        }\n    }\n\n    public struct StageHandle : System.IEquatable<StageHandle>\n    {\n        private bool m_IsMainStage;\n        private Scene m_CustomScene;\n\n        internal bool isMainStage { get { return m_IsMainStage; } }\n        internal Scene customScene { get { return m_CustomScene; } }\n\n        public bool Contains(GameObject gameObject)\n        {\n            if (!IsValid())\n                throw new System.Exception(\"Stage is not valid.\");\n\n            Scene goScene = gameObject.scene;\n            if (goScene.IsValid() && EditorSceneManager.IsPreviewScene(goScene))\n                return goScene == customScene;\n            else\n                return isMainStage;\n        }\n\n        public T FindComponentOfType<T>() where T : Component\n        {\n            if (!IsValid())\n                throw new System.Exception(\"Stage is not valid.\");\n\n            T[] components = Resources.FindObjectsOfTypeAll<T>();\n            if (isMainStage)\n            {\n                for (int i = 0; i < components.Length; i++)\n                {\n                    T obj = components[i];\n                    if (!EditorUtility.IsPersistent(obj) && !EditorSceneManager.IsPreviewScene(obj.gameObject.scene))\n                        return obj;\n                }\n            }\n            else\n            {\n                for (int i = 0; i < components.Length; i++)\n                {\n                    T obj = components[i];\n                    if (obj.gameObject.scene == customScene)\n                        return obj;\n                }\n            }\n            return null;\n        }\n\n        public T[] FindComponentsOfType<T>() where T : Component\n        {\n            if (!IsValid())\n                throw new System.Exception(\"Stage is not valid.\");\n\n            T[] components = Resources.FindObjectsOfTypeAll<T>();\n            List<T> componentList = new List<T>();\n            if (isMainStage)\n            {\n                for (int i = 0; i < components.Length; i++)\n                {\n                    T obj = components[i];\n                    if (!EditorUtility.IsPersistent(obj) && !EditorSceneManager.IsPreviewScene(obj.gameObject.scene))\n                        componentList.Add(obj);\n                }\n            }\n            else\n            {\n                for (int i = 0; i < components.Length; i++)\n                {\n                    T obj = components[i];\n                    if (obj.gameObject.scene == customScene)\n                        componentList.Add(obj);\n                }\n            }\n            return componentList.ToArray();\n        }\n\n        // Use public API StageUtility.GetMainStage\n        internal static StageHandle GetMainStageHandle()\n        {\n            return new StageHandle() { m_IsMainStage = true };\n        }\n\n        // Use public API StageUtility.GetCurrentStage\n        internal static StageHandle GetCurrentStageHandle()\n        {\n            if (StageNavigationManager.instance != null && StageNavigationManager.instance.currentStage != null)\n                return StageNavigationManager.instance.currentStage.stageHandle;\n            return new StageHandle() { m_IsMainStage = true };\n        }\n\n        // Use public API StageUtility.GetStage\n        internal static StageHandle GetStageHandle(Scene scene)\n        {\n            if (scene.IsValid() && EditorSceneManager.IsPreviewScene(scene))\n                return new StageHandle() { m_CustomScene = scene };\n            else\n                return new StageHandle() { m_IsMainStage = true };\n        }\n\n        public bool IsValid()\n        {\n            return m_IsMainStage ^ m_CustomScene.IsValid();\n        }\n\n        public static bool operator==(StageHandle s1, StageHandle s2)\n        {\n            return s1.Equals(s2);\n        }\n\n        public static bool operator!=(StageHandle s1, StageHandle s2)\n        {\n            return !s1.Equals(s2);\n        }\n\n        public override bool Equals(object other)\n        {\n            if (!(other is StageHandle))\n                return false;\n\n            StageHandle rhs = (StageHandle)other;\n            return m_IsMainStage == rhs.m_IsMainStage && m_CustomScene == rhs.m_CustomScene;\n        }\n\n        public bool Equals(StageHandle other)\n        {\n            return m_IsMainStage == other.m_IsMainStage && m_CustomScene == other.m_CustomScene;\n        }\n\n        public override int GetHashCode()\n        {\n            if (m_IsMainStage)\n                return 1;\n            return m_CustomScene.GetHashCode();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/StageNavigationHistory.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Collections.ObjectModel;\nusing UnityEngine;\n\nnamespace UnityEditor.SceneManagement\n{\n    [Serializable]\n    internal class StageNavigationHistory\n    {\n        [SerializeField]\n        List<Stage> m_History = new List<Stage>();\n\n        [SerializeField]\n        int m_CurrentIndex = -1;\n\n        internal StageNavigationHistory()\n        {\n        }\n\n        internal void Init()\n        {\n            SetMainStage(MainStage.CreateMainStage());\n        }\n\n        public Stage currentStage\n        {\n            get\n            {\n                if (m_CurrentIndex < 0 || m_CurrentIndex >= m_History.Count)\n                    throw new InvalidOperationException(\"StageNavigationHistory has not been initialized yet.\");\n\n                if (m_History[m_CurrentIndex] == null)\n                    throw new InvalidOperationException(\"StageNavigationHistory is missing a stage at index: \" + m_CurrentIndex);\n\n                return m_History[m_CurrentIndex];\n            }\n            // No setter since invoking code should explicitly specify desired effect on history.\n        }\n\n        public List<Stage> GetHistory()\n        {\n            return m_History;\n        }\n\n        // Always keeps main stage\n        public List<Stage> ClearHistory()\n        {\n            var removedStages = new List<Stage>();\n            if (m_History.Count > 1)\n            {\n                removedStages = m_History.GetRange(1, m_History.Count - 1);\n                m_History.RemoveRange(1, m_History.Count - 1);\n            }\n            return removedStages;\n        }\n\n        public void AddStage(Stage stage)\n        {\n            m_History.Add(stage);\n            m_CurrentIndex = m_History.Count - 1;\n        }\n\n        public List<Stage> ClearForwardHistoryAfterCurrentStage()\n        {\n            if (m_CurrentIndex >= 0)\n            {\n                int start = m_CurrentIndex + 1;\n                int count = m_History.Count - start;\n                var removed = m_History.GetRange(start, count);\n                m_History.RemoveRange(start, count);\n                return removed;\n            }\n            return new List<Stage>();\n        }\n\n        public List<Stage> ClearForwardHistoryAndAddItem(Stage stage)\n        {\n            if (stage == currentStage)\n                return new List<Stage>();\n\n            var removed = ClearForwardHistoryAfterCurrentStage();\n            AddStage(stage);\n            return removed;\n        }\n\n        public bool TrySetToIndexOfItem(Stage stage)\n        {\n            for (int i = 0; i < m_History.Count; ++i)\n            {\n                if (m_History[i] == stage)\n                {\n                    m_CurrentIndex = i;\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        public int GetStageCount()\n        {\n            return m_History.Count;\n        }\n\n        public bool CanGoForward()\n        {\n            if (m_History.Count <= 1)\n                return false;\n\n            if (m_CurrentIndex >= m_History.Count - 1)\n                return false;\n\n            return true;\n        }\n\n        public bool CanGoBackward()\n        {\n            if (m_History.Count <= 1)\n                return false;\n\n            if (m_CurrentIndex == 0)\n                return false;\n\n            return true;\n        }\n\n        public Stage GetPrevious()\n        {\n            if (!CanGoBackward())\n                return null;\n\n            return m_History[m_CurrentIndex - 1];\n        }\n\n        public Stage GetNext()\n        {\n            if (!CanGoForward())\n                return null;\n\n            return m_History[m_CurrentIndex + 1];\n        }\n\n        internal MainStage GetMainStage()\n        {\n            if (m_History.Count == 0 || m_History[0] == null)\n                SetMainStage(MainStage.CreateMainStage());\n\n            return (MainStage)m_History[0];\n        }\n\n        void SetMainStage(MainStage mainStage)\n        {\n            if (mainStage == null)\n                throw new ArgumentNullException(\"mainStage\");\n\n            if (m_History.Count > 0 && m_History[0] != null)\n                throw new InvalidOperationException(\"The MainStage is already set\");\n\n            if (m_History.Count == 0)\n                m_History.Add(mainStage);\n            else\n                m_History[0] = mainStage;\n\n            if (m_CurrentIndex < 0)\n            {\n                m_CurrentIndex = 0;\n            }\n\n            mainStage.opened = true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.Assertions;\nusing UnityEngine.SceneManagement;\nusing UnityEngine.Scripting;\nusing System.Collections.ObjectModel;\n\nnamespace UnityEditor.SceneManagement\n{\n    internal class StageNavigationManager : ScriptableSingleton<StageNavigationManager>\n    {\n        StageNavigationHistory m_NavigationHistory;                                 // Not marked with SerializeField since it should be reset on every restart of Unity\n        SavedBool m_AutoSave = new SavedBool(\"PrefabEditing.AutoSave\", true);\n        SavedInt m_ContextRenderMode = new SavedInt(\"PrefabEditing.ContextRenderMode\", (int)StageUtility.ContextRenderMode.GreyedOut);\n        Analytics m_Analytics = new Analytics();\n        [NonSerialized]\n        double m_NextUpdate;\n        [NonSerialized]\n        bool m_DebugLogging = false;\n\n        public event Action<Stage, Stage> stageChanging;                             // previousStage, newStage\n        public event Action<Stage, Stage> stageChanged;                              // previousStage, newStage\n        public event Action<Stage> beforeSwitchingAwayFromStage;\n        public event Action<Stage> afterSuccessfullySwitchedToStage;\n\n        internal Stage currentStage\n        {\n            get { return m_NavigationHistory.currentStage; }\n            // No setter since invoking code should explicitly specify desired effect on history.\n        }\n\n        internal MainStage mainStage\n        {\n            get { return m_NavigationHistory.GetMainStage(); }\n        }\n\n        internal List<Stage> stageHistory\n        {\n            get { return m_NavigationHistory.GetHistory(); }\n        }\n\n        internal bool autoSave\n        {\n            get { return m_AutoSave.value; }\n            set { m_AutoSave.value = value; }\n        }\n        internal StageUtility.ContextRenderMode contextRenderMode\n        {\n            get { return (StageUtility.ContextRenderMode)m_ContextRenderMode.value; }\n            set { m_ContextRenderMode.value = (int)value; }\n        }\n\n        internal Analytics analytics\n        {\n            get { return m_Analytics; }\n        }\n\n        void OnEnable()\n        {\n            if (m_NavigationHistory == null)\n            {\n                m_NavigationHistory = new StageNavigationHistory();\n                m_NavigationHistory.Init();\n            }\n\n            EditorApplication.update += Update;\n            EditorSceneManager.sceneOpened += OnSceneOpened;\n            EditorSceneManager.newSceneCreated += OnNewSceneCreated;\n            EditorApplication.editorApplicationQuit += OnQuit;\n        }\n\n        void OnDisable()\n        {\n            EditorApplication.update -= Update;\n            EditorSceneManager.sceneOpened -= OnSceneOpened;\n            EditorSceneManager.newSceneCreated -= OnNewSceneCreated;\n            EditorApplication.editorApplicationQuit -= OnQuit;\n        }\n\n        void OnQuit()\n        {\n            // Ensure we destroy the prefab stages so all hidden editor objects (environment objects are hidden)\n            // are removed before closing down. Currently editor objects should be cleaned up if they have interest\n            // in transform changes before shutting down.\n            GoToMainStage(Analytics.ChangeType.GoToMainViaQuitApplication);\n        }\n\n        internal Stage GetStage(Scene scene)\n        {\n            var inputStageHandle = StageHandle.GetStageHandle(scene);\n            foreach (var stage in stageHistory)\n            {\n                if (stage.stageHandle == inputStageHandle)\n                    return stage;\n            }\n            return null;\n        }\n\n        void OnSceneOpened(Scene scene, OpenSceneMode mode)\n        {\n            if (!(currentStage is MainStage))\n            {\n                GoToMainStage(Analytics.ChangeType.GoToMainViaSceneOpened); // Do not set previous selection as this would e.g remove the selection from the Project Browser when double clicking a scene asset\n            }\n        }\n\n        void OnNewSceneCreated(Scene scene, NewSceneSetup setup, NewSceneMode mode)\n        {\n            if (!(currentStage is MainStage))\n            {\n                GoToMainStage(Analytics.ChangeType.GoToMainViaNewSceneCreated);\n            }\n        }\n\n        void Update()\n        {\n            var time = EditorApplication.timeSinceStartup;\n            if (time > m_NextUpdate)\n            {\n                m_NextUpdate = time + 0.2;\n                ValidateAndTickStages(true);\n            }\n        }\n\n        // internal for testing\n        internal void ValidateAndTickStages(bool showDialogIfInvalid)\n        {\n            var stageHistory = m_NavigationHistory.GetHistory();\n            foreach (var stage in stageHistory)\n            {\n                if (stage == null)\n                {\n                    if (showDialogIfInvalid)\n                        EditorUtility.DisplayDialog(\"Stage Error\", \"A stage has been destroyed unexpectedly.\\n\\nReturning to the MainStage.\", \"OK\");\n                    GoToMainStage(Analytics.ChangeType.Unknown);\n                    return;\n                }\n            }\n\n            if (!currentStage.isValid)\n            {\n                var errorMsg = currentStage.GetErrorMessage();\n                if (showDialogIfInvalid)\n                    EditorUtility.DisplayDialog(\"Stage Error\", errorMsg, \"OK\");\n                GoToMainStage(Analytics.ChangeType.Unknown);\n                return;\n            }\n\n            foreach (var stage in stageHistory)\n            {\n                stage.Tick();\n            }\n        }\n\n        internal void NavigateBack(Analytics.ChangeType stageChangeAnalytics)\n        {\n            if (m_NavigationHistory.CanGoBackward())\n            {\n                var previousStage = m_NavigationHistory.GetPrevious();\n                SwitchToStage(previousStage, false, stageChangeAnalytics);\n            }\n        }\n\n        internal void GoToMainStage(Analytics.ChangeType stageChangeAnalytics)\n        {\n            if (currentStage is MainStage)\n                return;\n\n            SwitchToStage(m_NavigationHistory.GetMainStage(), false, stageChangeAnalytics);\n        }\n\n        static void StopAnimationPlaybackAndPreviewing()\n        {\n            var animWindows = AnimationWindow.GetAllAnimationWindows();\n            foreach (var animWindow in animWindows)\n            {\n                animWindow.previewing = false;\n                animWindow.playing = false;\n            }\n        }\n\n        internal bool SwitchToStage(Stage stage, bool setAsFirstItemAfterMainStage, Analytics.ChangeType changeTypeAnalytics)\n        {\n            if (stage == null)\n            {\n                Debug.LogError(\"Cannot switch to new stage. Input stage is null\");\n                return false;\n            }\n\n            bool setPreviousSelection = stage.opened;\n\n            StopAnimationPlaybackAndPreviewing();\n\n            Stage previousStage = currentStage;\n            if (!previousStage.AskUserToSaveModifiedStageBeforeSwitchingStage())\n            {\n                // User canceled switching stage.\n                // If the history contains the new stage we do not destroy it (the user\n                // can have clicked a previous stage in the breadcrumb bar).\n                if (!stageHistory.Contains(stage))\n                    DestroyImmediate(stage);\n                return false;\n            }\n\n            // User accepted to switch stage (and lose any data if not saved)\n            // Here we save current Hierarchy and SceneView stage state\n            beforeSwitchingAwayFromStage?.Invoke(previousStage);\n\n            // Used by the Avatar Editor to exit its editing mode before opening new stage\n            stageChanging?.Invoke(previousStage, stage);\n\n            // Set/Add stage in m_NavigationHistory (and detect what stages should be removed)\n            if (m_DebugLogging)\n                Debug.Log(\"Set Navigation History (setAsFirstItemAfterMainStage \" + setAsFirstItemAfterMainStage);\n\n            var deleteStages = new List<Stage>();\n            if (setAsFirstItemAfterMainStage)\n            {\n                deleteStages = m_NavigationHistory.ClearHistory();\n                m_NavigationHistory.AddStage(stage);\n            }\n            else\n            {\n                if (m_NavigationHistory.TrySetToIndexOfItem(stage))\n                    deleteStages = m_NavigationHistory.ClearForwardHistoryAfterCurrentStage();\n                else\n                    deleteStages = m_NavigationHistory.ClearForwardHistoryAndAddItem(stage);\n            }\n\n            m_Analytics.ChangingStageStarted(previousStage);\n\n            if (m_DebugLogging)\n                Debug.Log(\"Activate new stage\");\n\n            // Activate stage after setting up the history above so objects loaded during ActivateStage can query current stage\n            bool success;\n            try\n            {\n                if (!stage.opened)\n                {\n                    stage.opened = true;\n                    success = stage.OnOpenStage();\n                }\n                else\n                {\n                    stage.OnReturnToStage();\n                    success = stage.isValid;\n                }\n\n                if (success)\n                {\n                    if (m_DebugLogging)\n                        Debug.Log(\"Deactivate previous stage\");\n\n                    // Here the Hierarchy and SceneView sync's up to the new stage\n                    stage.setSelectionAndScrollWhenBecomingCurrentStage = setPreviousSelection;\n                    stageChanged?.Invoke(previousStage, stage);\n                }\n            }\n            catch (Exception e)\n            {\n                success = false;\n                Debug.LogError(\"Error while changing Stage: \" + e);\n            }\n\n            if (success)\n            {\n                // Activation and changing stage succeeded. Now destroy removed stages\n                if (m_DebugLogging)\n                    Debug.Log(\"Destroying \" + deleteStages.Count + \" stages\");\n\n                // A previous existing stage can have been requested to set as the current so don't delete that\n                deleteStages.Remove(stage);\n\n                DeleteStagesInReverseOrder(deleteStages);\n\n                // Here we update state that relies on old scenes having been destroyed entirely.\n                afterSuccessfullySwitchedToStage?.Invoke(stage);\n\n                m_Analytics.ChangingStageEnded(stage, changeTypeAnalytics);\n\n                // Unload assets that are no longer referenced after switching stages (UUM-49014).\n                // If a user is opening one Prefab Asset after another this ensures that we still\n                // keep assets in memory to a minimum.\n                // We don't do this if the \"force GC on scene load\" setting isn't enabled as it indicates the user would rather keep assets in memory.\n                if ((stage.stageHandle.isMainStage || setAsFirstItemAfterMainStage) && EditorSettings.forceAssetUnloadAndGCOnSceneLoad)\n                {\n                    EditorUtility.UnloadUnusedAssetsImmediate();\n                }\n            }\n            else\n            {\n                if (m_DebugLogging)\n                    Debug.Log(\"Switching stage failed (\" + stage + \")\");\n\n                RecoverFromStageChangeError(previousStage, deleteStages);\n            }\n\n            return success;\n        }\n\n        struct PreviewSceneLeakDetection\n        {\n            Type m_StageType;\n            Scene m_Scene;\n\n            internal void Init(PreviewSceneStage previewSceneStage)\n            {\n                m_StageType = null;\n                m_Scene = default(Scene);\n\n                if (previewSceneStage != null)\n                {\n                    m_StageType = previewSceneStage.GetType();\n                    m_Scene = previewSceneStage.scene;\n                }\n            }\n\n            internal void LogErrorIfPreviewSceneWasNotDestroyed()\n            {\n                if (m_StageType != null && m_Scene.IsValid())\n                    Debug.LogError($\"Stage type '{m_StageType}' did not clean up properly: A PreviewScene was leaked. Ensure to call 'base.OnCloseStage()' from your implementation of OnCloseStage().\");\n            }\n        }\n\n        static void DeleteStagesInReverseOrder(List<Stage> stagesToDelete)\n        {\n            var previewSceneLeakDetection = new PreviewSceneLeakDetection();\n\n            // Remove in reverse order of added (simulates going back one stage at a time)\n            for (int i = stagesToDelete.Count - 1; i >= 0; --i)\n            {\n                var removeStage = stagesToDelete[i];\n                if (removeStage != null)\n                {\n                    previewSceneLeakDetection.Init(removeStage as PreviewSceneStage);\n                    DestroyImmediate(removeStage);\n                    previewSceneLeakDetection.LogErrorIfPreviewSceneWasNotDestroyed();\n                }\n            }\n        }\n\n        void RecoverFromStageChangeError(Stage previousStage, List<Stage> deleteStages)\n        {\n            // Recover by going back to main stage\n            if (m_NavigationHistory.TrySetToIndexOfItem(m_NavigationHistory.GetMainStage()))\n            {\n                var lastStages = m_NavigationHistory.ClearForwardHistoryAfterCurrentStage();\n                if (lastStages.Count > 0)\n                    deleteStages.InsertRange(0, lastStages); // Insert at start so we ensure the same order as in history\n\n                try\n                {\n                    // Here the Hierarchy and SceneView sync's up to the new stage\n                    stageChanged?.Invoke(previousStage, m_NavigationHistory.GetMainStage());\n                }\n                catch (Exception e)\n                {\n                    Debug.LogError(\"Error while recovering from Stage change error: \" + e);\n                }\n\n                DeleteStagesInReverseOrder(deleteStages);\n            }\n            else\n                Debug.LogError(\"Could not set MainStage to recover from error\");\n        }\n\n        public void PlaceGameObjectInCurrentStage(GameObject gameObject)\n        {\n            if (gameObject != null && gameObject.transform.parent == null)\n                currentStage.PlaceGameObjectInStage(gameObject);\n        }\n\n        [RequiredByNativeCode]\n        internal static void Internal_PlaceGameObjectInCurrentStage(GameObject go)\n        {\n            instance.PlaceGameObjectInCurrentStage(go);\n        }\n\n        [RequiredByNativeCode]\n        internal static bool Internal_HasCurrentNonMainStage()\n        {\n            return !(instance.currentStage is MainStage);\n        }\n\n        [RequiredByNativeCode]\n        internal static bool Internal_CurrentNonMainStageSupportsSaving()\n        {\n            return instance.currentStage.SupportsSaving();\n        }\n\n        [RequiredByNativeCode]\n        internal static void Internal_SaveCurrentStage()\n        {\n            var stage = instance.currentStage;\n            if (stage != null && stage.SupportsSaving() && stage.hasUnsavedChanges)\n                stage.Save();\n        }\n\n        [RequiredByNativeCode]\n        internal static void Internal_SaveCurrentStageAsNew()\n        {\n            var stage = instance.currentStage;\n            if (stage != null && stage.SupportsSaving())\n                stage.SaveAsNew();\n        }\n\n        [Serializable]\n        internal class Analytics\n        {\n            public enum ChangeType\n            {\n                Unknown,\n                EnterViaInstanceHierarchyRightArrow,\n                EnterViaInstanceHierarchyContextMenu,\n                EnterViaInstanceInspectorOpenButton,\n                EnterViaAssetInspectorOpenButton,\n                EnterViaAssetOpened,\n                EnterViaUnknown,\n                GoToMainViaSceneOpened,\n                GoToMainViaNewSceneCreated,\n                GoToMainViaPlayModeBlocking,\n                GoToMainViaQuitApplication,\n                GoToMainViaAvatarSetup,\n                GoToMainViaUnknown,\n                NavigateBackViaHierarchyHeaderLeftArrow,\n                NavigateBackViaUnknown,\n                NavigateViaBreadcrumb,\n            }\n\n            public enum StageType\n            {\n                MainStage,\n                PrefabStage,\n                Unknown,\n            }\n\n            [Serializable]\n            class EventData\n            {\n                public ChangeType changeType;\n                public StageType existingStage;\n                public StageType newStage;\n                public int existingBreadcrumbCount;\n                public int newBreadcrumbCount;\n                public bool autoSaveEnabled;\n                public bool didUserModify;\n                public bool didUserSave;\n            }\n            EventData m_EventData;\n            DateTime m_StartedTime;\n\n            public void ChangingStageStarted(Stage previousStage)\n            {\n                m_StartedTime = DateTime.UtcNow;\n\n                m_EventData = new EventData();\n                m_EventData.existingStage = GetStageType(previousStage);\n                m_EventData.existingBreadcrumbCount = StageNavigationManager.instance.stageHistory.Count;\n                if (previousStage is PrefabStage)\n                {\n                    var prefabStage = (PrefabStage)previousStage;\n                    m_EventData.didUserModify = prefabStage.analyticsDidUserModify;\n                    m_EventData.didUserSave = prefabStage.analyticsDidUserSave;\n                }\n            }\n\n            public void ChangingStageEnded(Stage newStage, Analytics.ChangeType changeTypeAnalytics)\n            {\n                m_EventData.changeType = changeTypeAnalytics;\n                m_EventData.newStage = GetStageType(newStage);\n                m_EventData.newBreadcrumbCount = StageNavigationManager.instance.stageHistory.Count;\n                m_EventData.autoSaveEnabled = StageNavigationManager.instance.autoSave;\n                var duration = DateTime.UtcNow.Subtract(m_StartedTime);\n\n                UsabilityAnalytics.SendEvent(\"stageChange\", m_StartedTime, duration, true, m_EventData);\n            }\n\n            static StageType GetStageType(Stage stage)\n            {\n                if (stage is MainStage)\n                    return StageType.MainStage;\n                if (stage is PrefabStage)\n                    return StageType.PrefabStage;\n                return StageType.Unknown;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/StageUtility.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.SceneManagement;\n\nnamespace UnityEditor.SceneManagement\n{\n    [NativeHeader(\"Editor/Src/SceneManager/StageUtility.bindings.h\")]\n    public static partial class StageUtility\n    {\n        [NativeThrows]\n        [StaticAccessor(\"StageUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static bool IsGameObjectRenderedInSameStageAsSceneInternal(GameObject gameObject, int sceneHandle);\n\n        [NativeThrows]\n        [StaticAccessor(\"StageUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static bool IsGameObjectRenderedByCameraInternal(GameObject gameObject, Camera camera);\n\n        [NativeThrows]\n        [StaticAccessor(\"StageUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static bool IsTheMainStageRenderedByCameraInternal(Camera camera);\n\n        [NativeThrows]\n        [StaticAccessor(\"StageUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static void SetSceneToRenderInSameStageAsOtherSceneInternal(int sceneHandle, int otherSceneHandle);\n\n        [NativeThrows]\n        [StaticAccessor(\"StageUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static void SetSceneToRenderInMainStageInternal(int sceneHandle);\n\n\n        [NativeThrows]\n        [StaticAccessor(\"StageUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static bool IsGameObjectInTheMainStageInternal(GameObject gameObject);\n\n        [NativeThrows]\n        [StaticAccessor(\"StageUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static bool IsGameObjectInSameStageAsSceneInternal(GameObject gameObject, int sceneHandle);\n\n        [StaticAccessor(\"StageUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static void SetPrefabInstanceHiddenForInContextEditingInternal([NotNull] GameObject gameObject, bool hide);\n\n        [StaticAccessor(\"StageUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static bool IsPrefabInstanceHiddenForInContextEditingInternal([NotNull] GameObject gameObject);\n\n        [StaticAccessor(\"StageUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static void EnableHidingForInContextEditingInSceneViewInternal(bool enable);\n\n        [StaticAccessor(\"StageUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static void SetFocusedSceneInternal(int sceneHandle);\n\n        [StaticAccessor(\"StageUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static Scene GetFocusedSceneInternal();\n\n        [StaticAccessor(\"StageUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static void SetFocusedSceneContextRenderModeInternal(StageUtility.ContextRenderMode contextRenderMode);\n\n        [StaticAccessor(\"StageUtilityBindings\", StaticAccessorType.DoubleColon)]\n        extern private static void CallAwakeFromLoadOnSubHierarchyInternal([NotNull] GameObject prefabInstanceRoot);\n\n        [StaticAccessor(\"StageUtility\", StaticAccessorType.DoubleColon)]\n        extern internal static bool IsGizmoCulledBySceneCullingMasksOrFocusedScene([NotNull] GameObject gameObject, [NotNull] Camera camera);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneManagement/StageManager/StageUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.SceneManagement\n{\n    public static partial class StageUtility\n    {\n        internal enum ContextRenderMode\n        {\n            Normal,\n            GreyedOut,\n            Hidden\n        }\n\n        [Shortcut(\"Stage/Go Back\")]\n        static void GoBackShortcut()\n        {\n            StageUtility.GoBackToPreviousStage();\n        }\n\n        public static bool IsGameObjectRenderedByCamera(GameObject gameObject, Camera camera)\n        {\n            return IsGameObjectRenderedByCameraInternal(gameObject, camera);\n        }\n\n        public static bool IsGameObjectRenderedByCameraAndPartOfEditableScene(GameObject gameObject, Camera camera)\n        {\n            if (!IsGameObjectRenderedByCamera(gameObject, camera))\n                return false;\n\n            var scene = GetFocusedScene();\n            if (scene.handle == 0)\n                return true;\n\n            return gameObject.scene == scene;\n        }\n\n        internal static void SetSceneToRenderInStage(Scene scene, StageHandle stageHandle)\n        {\n            if (!stageHandle.IsValid())\n                throw new System.ArgumentException(\"Stage is not valid.\", nameof(stageHandle));\n            if (stageHandle.isMainStage)\n                SetSceneToRenderInMainStageInternal(scene.handle);\n            else\n                SetSceneToRenderInSameStageAsOtherSceneInternal(scene.handle, stageHandle.customScene.handle);\n        }\n\n        public static Stage GetCurrentStage()\n        {\n            return StageNavigationManager.instance.currentStage;\n        }\n\n        public static MainStage GetMainStage()\n        {\n            return StageNavigationManager.instance.mainStage;\n        }\n\n        public static Stage GetStage(GameObject gameObject)\n        {\n            return GetStage(gameObject.scene);\n        }\n\n        public static Stage GetStage(Scene scene)\n        {\n            return StageNavigationManager.instance.GetStage(scene);\n        }\n\n        public static StageHandle GetCurrentStageHandle()\n        {\n            return StageHandle.GetCurrentStageHandle();\n        }\n\n        public static StageHandle GetMainStageHandle()\n        {\n            return StageHandle.GetMainStageHandle();\n        }\n\n        public static StageHandle GetStageHandle(GameObject gameObject)\n        {\n            return StageHandle.GetStageHandle(gameObject.scene);\n        }\n\n        public static StageHandle GetStageHandle(Scene scene)\n        {\n            return StageHandle.GetStageHandle(scene);\n        }\n\n        [RequiredByNativeCode]\n        public static void GoToMainStage()\n        {\n            StageNavigationManager.instance.GoToMainStage(StageNavigationManager.Analytics.ChangeType.GoToMainViaUnknown);\n        }\n\n        public static void GoBackToPreviousStage()\n        {\n            StageNavigationManager.instance.NavigateBack(StageNavigationManager.Analytics.ChangeType.NavigateBackViaUnknown);\n        }\n\n        public static void GoToStage(Stage stage, bool setAsFirstItemAfterMainStage)\n        {\n            StageNavigationManager.instance.SwitchToStage(stage, setAsFirstItemAfterMainStage, StageNavigationManager.Analytics.ChangeType.Unknown);\n        }\n\n        public static void PlaceGameObjectInCurrentStage(GameObject gameObject)\n        {\n            StageNavigationManager.instance.PlaceGameObjectInCurrentStage(gameObject);\n        }\n\n        internal static Hash128 CreateWindowAndStageIdentifier(string windowGUID, Stage stage)\n        {\n            Hash128 hash = stage.GetHashForStateStorage();\n            hash.Append(windowGUID);\n            hash.Append(stage.GetType().FullName);\n            return hash;\n        }\n\n        internal static void SetPrefabInstanceHiddenForInContextEditing(GameObject gameObject, bool hide)\n        {\n            SetPrefabInstanceHiddenForInContextEditingInternal(gameObject, hide);\n        }\n\n        internal static bool IsPrefabInstanceHiddenForInContextEditing(GameObject gameObject)\n        {\n            return IsPrefabInstanceHiddenForInContextEditingInternal(gameObject);\n        }\n\n        internal static void EnableHidingForInContextEditingInSceneView(bool enable)\n        {\n            EnableHidingForInContextEditingInSceneViewInternal(enable);\n        }\n\n        internal static void SetFocusedScene(Scene scene)\n        {\n            SetFocusedSceneInternal(scene.IsValid() ? scene.handle : 0);\n        }\n\n        internal static Scene GetFocusedScene()\n        {\n            return GetFocusedSceneInternal();\n        }\n\n        internal static void SetFocusedSceneContextRenderMode(ContextRenderMode contextRenderMode)\n        {\n            SetFocusedSceneContextRenderModeInternal(contextRenderMode);\n        }\n\n        internal static void CallAwakeFromLoadOnSubHierarchy(GameObject prefabInstanceRoot)\n        {\n            CallAwakeFromLoadOnSubHierarchyInternal(prefabInstanceRoot);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneModeWindows/DefaultLightingExplorerExtension.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Linq;\nusing UnityEngine.Rendering;\nusing UnityEngine.U2D;\nusing UnityEditor.SceneManagement;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    public class DefaultLightingExplorerExtension : ILightingExplorerExtension\n    {\n        private static class Styles\n        {\n            public static readonly GUIContent[] ProjectionStrings = { EditorGUIUtility.TrTextContent(\"Infinite\"), EditorGUIUtility.TrTextContent(\"Box\") };\n            public static readonly GUIContent[] LightmapEmissiveStrings = { EditorGUIUtility.TrTextContent(\"Realtime\"), EditorGUIUtility.TrTextContent(\"Baked\") };\n            public static readonly GUIContent Name = EditorGUIUtility.TrTextContent(\"Name\");\n            public static readonly GUIContent Enabled = EditorGUIUtility.TrTextContent(\"Enabled\");\n            public static readonly GUIContent Type = EditorGUIUtility.TrTextContent(\"Type\");\n            public static readonly GUIContent Shape = EditorGUIUtility.TrTextContent(\"Shape\");\n            public static readonly GUIContent Mode = EditorGUIUtility.TrTextContent(\"Mode\");\n            public static readonly GUIContent Color = EditorGUIUtility.TrTextContent(\"Color\");\n            public static readonly GUIContent Range = EditorGUIUtility.TrTextContent(\"Range\");\n            public static readonly GUIContent Intensity = EditorGUIUtility.TrTextContent(\"Intensity\");\n            public static readonly GUIContent IndirectMultiplier = EditorGUIUtility.TrTextContent(\"Indirect Multiplier\");\n            public static readonly GUIContent ShadowType = EditorGUIUtility.TrTextContent(\"Shadows\");\n            public static readonly GUIContent Projection = EditorGUIUtility.TrTextContent(\"Projection\");\n            public static readonly GUIContent HDR = EditorGUIUtility.TrTextContent(\"HDR\");\n            public static readonly GUIContent ShadowDistance = EditorGUIUtility.TrTextContent(\"Shadow Distance\");\n            public static readonly GUIContent NearPlane = EditorGUIUtility.TrTextContent(\"Near Plane\");\n            public static readonly GUIContent FarPlane = EditorGUIUtility.TrTextContent(\"Far Plane\");\n            public static readonly GUIContent GlobalIllumination = EditorGUIUtility.TrTextContent(\"Global Illumination\");\n            public static readonly GUIContent SelectObjects = EditorGUIUtility.TextContent(\"\");\n            public static readonly GUIContent SelectObjectsButton = EditorGUIUtility.TrTextContentWithIcon(\"\", \"Find References in Scene\", \"UnityEditor.FindDependencies\");\n\n            public static readonly GUIContent LightCookieSprite = EditorGUIUtility.TrTextContent(\"Sprite\");\n            public static readonly GUIContent FallOff = EditorGUIUtility.TrTextContent(\"Falloff\");\n            public static readonly GUIContent FallOffStrength = EditorGUIUtility.TrTextContent(\"Falloff Strength\");\n            public static readonly GUIContent TargetSortingLayer = EditorGUIUtility.TrTextContent(\"Target Sorting Layer\");\n            public static readonly GUIContent All = EditorGUIUtility.TrTextContent(\"All\");\n            public static readonly GUIContent None = EditorGUIUtility.TrTextContent(\"None\");\n            public static readonly GUIContent Mixed = EditorGUIUtility.TrTextContent(\"Mixed...\");\n            public static readonly GUIContent ShadowIntensityEnabled = EditorGUIUtility.TrTextContent(\"Shadow\");\n            public static readonly GUIContent ShadowIntensity = EditorGUIUtility.TrTextContent(\"Shadow Strength\");\n            public static readonly GUIContent Light2DParametric = EditorGUIUtility.TrTextContentWithIcon(\"Parametric\", \"Parametric Lights have been deprecated. To continue, upgrade your Parametric Lights to Freeform Lights to enjoy similar light functionality.\", MessageType.Warning);\n\n            public static readonly GUIContent[] LightmapBakeTypeTitles = { EditorGUIUtility.TrTextContent(\"Realtime\"), EditorGUIUtility.TrTextContent(\"Mixed\"), EditorGUIUtility.TrTextContent(\"Baked\") };\n            public static readonly int[] LightmapBakeTypeValues = { (int)LightmapBakeType.Realtime, (int)LightmapBakeType.Mixed, (int)LightmapBakeType.Baked };\n\n            public static readonly GUIContent[] LightTypeTitles = { EditorGUIUtility.TrTextContent(\"Spot\"), EditorGUIUtility.TrTextContent(\"Directional\"), EditorGUIUtility.TrTextContent(\"Point\"), EditorGUIUtility.TrTextContent(\"Area (baked only)\") };\n            public static readonly int[] LightTypeValues = { (int)LightType.Spot, (int)LightType.Directional, (int)LightType.Point, (int)LightType.Rectangle };\n\n            public static readonly GUIContent[] LightShapeTitles = { EditorGUIUtility.TrTextContent(\"Rectangle\"), EditorGUIUtility.TrTextContent(\"Disc\") };\n            public static readonly int[] LightShapeValues = { (int)LightType.Rectangle, (int)LightType.Disc };\n\n            public static readonly GUIContent[] Light2DTypeTitles = { EditorGUIUtility.TrTextContent(\"Freeform\"), EditorGUIUtility.TrTextContent(\"Sprite\"), EditorGUIUtility.TrTextContent(\"Spot\"), EditorGUIUtility.TrTextContent(\"Global\") };\n            public static readonly int[] Light2DTypeValues = Enumerable.Range(0, Light2DTypeTitles.Length).ToArray();\n        }\n\n        public virtual LightingExplorerTab[] GetContentTabs()\n        {\n            return new[]\n            {\n                new LightingExplorerTab(\"Lights\", GetLights, GetLightColumns, true),\n                new LightingExplorerTab(\"2D Lights\", Get2DLights, Get2DLightColumns, true),\n                new LightingExplorerTab(\"Reflection Probes\", GetReflectionProbes, GetReflectionProbeColumns, true),\n                new LightingExplorerTab(\"Light Probes\", GetLightProbes, GetLightProbeColumns, true),\n                new LightingExplorerTab(\"Static Emissives\", GetEmissives, GetEmissivesColumns, false)\n            };\n        }\n\n        public virtual void OnEnable() {}\n        public virtual void OnDisable() {}\n\n        private static bool IsEditable(Object target)\n        {\n            return ((target.hideFlags & HideFlags.NotEditable) == 0);\n        }\n\n        protected static System.Collections.Generic.IEnumerable<T> GetObjectsForLightingExplorer<T>() where T : UnityEngine.Component\n        {\n            var objects = Resources.FindObjectsOfTypeAll<T>().Where((T obj) =>\n            {\n                return !EditorUtility.IsPersistent(obj) && !obj.hideFlags.HasFlag(HideFlags.HideInHierarchy) && !obj.hideFlags.HasFlag(HideFlags.HideAndDontSave);\n            });\n\n            var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();\n            // No prefab mode.\n            if (prefabStage == null)\n            {\n                // Return all object instances in the scene including prefab instances, but not those that are in prefab assets.\n                return objects;\n            }\n            // In Context prefab mode with Normal rendering mode\n            else if (prefabStage.mode == PrefabStage.Mode.InContext &&\n                    StageNavigationManager.instance.contextRenderMode == StageUtility.ContextRenderMode.Normal)\n            {\n                // Return all object instances in the scene and objects in the opened prefab asset, but not objects in the opened prefab instance.\n                return objects.Where((T obj) =>\n                {\n                    return !StageUtility.IsPrefabInstanceHiddenForInContextEditing(obj.gameObject);\n                });\n            }\n            // All remaining cases, e.g. In Context with Hidden or GrayedOut rendering mode, or In Isolation prefab mode.\n            else\n            {\n                // Return only objects in the opened prefab asset.\n                return objects.Where((T obj) =>\n                {\n                    return EditorSceneManager.IsPreviewSceneObject(obj);\n                });\n            }\n        }\n\n        protected internal virtual UnityEngine.Object[] GetLights()\n        {\n            return GetObjectsForLightingExplorer<Light>().ToArray();\n        }\n\n        protected internal virtual UnityEngine.Object[] Get2DLights()\n        {\n            return GetObjectsForLightingExplorer<Light2DBase>().ToArray();\n        }\n\n        protected virtual  LightingExplorerTableColumn[] Get2DLightColumns()\n        {\n            return new[]\n            {\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.Enabled, \"m_Enabled\", 50), // 0: Enabled\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 1: Name\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Enum, Styles.Type, \"m_LightType\", 100, (r, prop, dep) => // 2\n                {\n                    if (prop != null)\n                    {\n                        if (prop.intValue != (int)Light2DType.Parametric)\n                        {\n                            EditorGUI.BeginProperty(r, GUIContent.none, prop);\n                            EditorGUI.BeginChangeCheck();\n                            int lightType = EditorGUI.IntPopup(r, prop.intValue - 1, Styles.Light2DTypeTitles, Styles.Light2DTypeValues);\n                            if (EditorGUI.EndChangeCheck())\n                                prop.intValue = lightType + 1;\n                            EditorGUI.EndProperty();\n                        }\n                        else\n                        {\n                            EditorGUI.LabelField(r, Styles.Light2DParametric);\n                        }\n                    }\n                }), // 2: LightType\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Color, Styles.Color, \"m_Color\", 100, (r, prop, dep) => // 3\n                {\n                    if (prop != null)\n                        EditorGUI.PropertyField(r, prop, GUIContent.none);\n                }), // 3: Color\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Custom, Styles.LightCookieSprite, \"m_LightCookieSprite\", 70, (r, prop, dep) => // 4\n                {\n                    if (prop != null)\n                    {\n                        var hasSpriteField = dep.Length > 0 && (dep[0].enumValueIndex == (int)Light2DType.Sprite);\n                        if (hasSpriteField)\n                        {\n                            EditorGUI.BeginProperty(r, GUIContent.none, prop);\n                            EditorGUI.BeginChangeCheck();\n                            var sprite = EditorGUI.ObjectField(r, prop.objectReferenceValue, typeof(Sprite), false);\n                            if (EditorGUI.EndChangeCheck())\n                                prop.objectReferenceValue = sprite;\n                            EditorGUI.EndProperty();\n                        }\n                    }\n                }, null, null, new[] { 2 }), // 4: Sprite\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Float, Styles.Intensity, \"m_Intensity\", 60, (r, prop, dep) => // 5\n                {\n                    if (prop != null)\n                    {\n                        EditorGUI.BeginProperty(r, GUIContent.none, prop);\n                        EditorGUI.BeginChangeCheck();\n                        var intensity = EditorGUI.FloatField(r, prop.floatValue);\n                        if (EditorGUI.EndChangeCheck())\n                            prop.floatValue = intensity < 0f ? 0f : intensity;\n                        EditorGUI.EndProperty();\n                    }\n                }), // 5: Intensity\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Float, Styles.FallOff, \"m_ShapeLightFalloffSize\", 60, (r, prop, dep) => // 6\n                {\n                    if (prop != null)\n                    {\n                        var hasFalloff = dep.Length > 0 && (dep[0].enumValueIndex == (int)Light2DType.Freeform);\n                        if (hasFalloff)\n                        {\n                            EditorGUI.BeginProperty(r, GUIContent.none, prop);\n                            EditorGUI.BeginChangeCheck();\n                            var falloff = EditorGUI.FloatField(r, prop.floatValue);\n                            if (EditorGUI.EndChangeCheck())\n                                prop.floatValue = falloff < 0f ? 0f : falloff;\n                            EditorGUI.EndProperty();\n                        }\n                    }\n                }, null, null, new[] { 2 }),  // 6: Falloff\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Float, Styles.FallOffStrength, \"m_FalloffIntensity\", 120, (r, prop, dep) => // 7\n                {\n                    if (prop != null)\n                    {\n                        var hasFalloff = dep.Length > 0 && (dep[0].enumValueIndex == (int)Light2DType.Freeform || dep[0].enumValueIndex == (int)Light2DType.Point);\n                        if (hasFalloff)\n                        {\n                            EditorGUI.BeginProperty(r, GUIContent.none, prop);\n                            EditorGUI.BeginChangeCheck();\n                            var newValue = EditorGUI.Slider(r, prop.floatValue, 0f, 1f);\n                            if (EditorGUI.EndChangeCheck())\n                                prop.floatValue = Mathf.Clamp01(newValue);\n                            EditorGUI.EndProperty();\n                        }\n                    }\n                }, null, null, new[] { 2 }),  // 7: Falloff intensity\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.TargetSortingLayer, \"m_ApplyToSortingLayers\", 120, // 8\n                    (r, prop, dep) =>\n                    {\n                        if (prop != null && prop.isArray)\n                        {\n                            var allSortingLayers = SortingLayer.layers;\n\n                            var propArraySize = prop.arraySize;\n                            if (propArraySize == allSortingLayers.Length)\n                                EditorGUI.LabelField(r, Styles.All);\n                            else if (propArraySize == 1)\n                                EditorGUI.LabelField(r, SortingLayer.IDToName(prop.GetArrayElementAtIndex(0).intValue));\n                            else if (propArraySize == 0)\n                                EditorGUI.LabelField(r, Styles.None);\n                            else\n                                EditorGUI.LabelField(r, Styles.Mixed);\n                        }\n                    }), // 8: Target Sorting Layer\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Custom, Styles.ShadowIntensityEnabled, \"m_ShadowsEnabled\", 50, (r, prop, dep) => // 9\n                {\n                    if (prop != null)\n                    {\n                        var hasShadow = dep.Length > 0 && (dep[0].enumValueIndex != (int)Light2DType.Global);\n                        if (hasShadow)\n                        {\n                            float off = Mathf.Max(0.0f, ((r.width / 2) - 8));\n                            r.x += off;\n                            r.width -= off;\n                            EditorGUI.PropertyField(r, prop, GUIContent.none);\n                        }\n                    }\n                }, null, null, new[] { 2 }), // 9: Shadow Intensity Enabled\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Custom, Styles.ShadowIntensity, \"m_ShadowIntensity\", 140, (r, prop, dep) => // 10\n                {\n                    if (prop != null)\n                    {\n                        var hasShadow = dep.Length > 0 && (dep[0].enumValueIndex != (int)Light2DType.Global);\n                        if (hasShadow)\n                        {\n                            var shadowIntensityEnabled = dep[1].boolValue;\n\n                            EditorGUI.BeginDisabled(!shadowIntensityEnabled);\n                            EditorGUI.BeginChangeCheck();\n                            var shadowIntensityProp = dep[0].serializedObject.FindProperty(\"m_ShadowIntensity\");\n\n                            var newShadowIntensity = EditorGUI.Slider(r, shadowIntensityProp.floatValue, 0f, 1f);\n                            if (EditorGUI.EndChangeCheck())\n                            {\n                                shadowIntensityProp.floatValue = Mathf.Clamp01(newShadowIntensity);\n                            }\n\n                            EditorGUI.EndDisabled();\n                        }\n                    }\n                } , null, null, new[] { 2, 9 })// 10: Shadow Intensity\n            };\n        }\n\n        protected virtual LightingExplorerTableColumn[] GetLightColumns()\n        {\n            return new[]\n            {\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.Enabled, \"m_Enabled\", 50), // 0: Enabled\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 1: Name\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Enum, Styles.Type, \"m_Type\", 120, (r, prop, dep) =>\n                {\n                    // To the user, we will only display it as a area light, but under the hood, we have Rectangle and Disc. This is not to confuse people\n                    // who still use our legacy light inspector.\n\n                    int selectedLightType = prop.intValue;\n\n                    if (!Styles.LightTypeValues.Contains(prop.intValue))\n                    {\n                        if (prop.intValue == (int)LightType.Disc)\n                        {\n                            selectedLightType = (int)LightType.Rectangle;\n                        }\n                        else\n                        {\n                            Debug.LogError(\"Light type is not supported by the Light Explorer.\");\n                        }\n                    }\n\n                    EditorGUI.BeginProperty(r, GUIContent.none, prop);\n                    EditorGUI.BeginChangeCheck();\n                    int type = EditorGUI.IntPopup(r, selectedLightType, Styles.LightTypeTitles, Styles.LightTypeValues);\n\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        prop.intValue = type;\n                    }\n                    EditorGUI.EndProperty();\n                }),      // 2: Type\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Enum, Styles.Shape, \"m_Type\", 120, (r, prop, dep) =>\n                {\n                    // This is only appliable to the Area lights that have a shape. For the other lights, nothing will be shown\n                    if (Styles.LightShapeValues.Contains(prop.intValue))\n                    {\n                        EditorGUI.BeginProperty(r, GUIContent.none, prop);\n                        EditorGUI.BeginChangeCheck();\n                        int type = EditorGUI.IntPopup(r, prop.intValue, Styles.LightShapeTitles, Styles.LightShapeValues);\n\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            prop.intValue = type;\n                        }\n                        EditorGUI.EndProperty();\n                    }\n                }),      // 3: Shape\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Enum, Styles.Mode, \"m_Lightmapping\", 70, (r, prop, dep) =>\n                {\n                    bool areaLight = dep.Length > 1 && (dep[0].enumValueIndex == (int)LightType.Rectangle || dep[0].enumValueIndex == (int)LightType.Disc);\n\n                    using (new EditorGUI.DisabledScope(areaLight))\n                    {\n                        EditorGUI.BeginProperty(r, GUIContent.none, prop);\n                        EditorGUI.BeginChangeCheck();\n                        int newval = EditorGUI.IntPopup(r, prop.intValue, Styles.LightmapBakeTypeTitles, Styles.LightmapBakeTypeValues);\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            prop.intValue = newval;\n                        }\n                        EditorGUI.EndProperty();\n                    }\n                }, null, null, new int[] { 2 }),     // 4: Mode\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Color, Styles.Color, \"m_Color\", 70), // 5: Color\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Float, Styles.Range, \"m_Range\", 60, (r, prop, dep) => \n                {\n                    var lightType = prop.serializedObject.FindProperty(\"m_Type\");\n                    if (lightType != null)\n                    {\n                        bool directionalLight = lightType.enumValueIndex == (int)LightType.Directional;\n                        if (!directionalLight)\n                        {\n                            EditorGUI.PropertyField(r, prop, GUIContent.none);\n                        }\n                    }\n                }), // 6: Range\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Float, Styles.Intensity, \"m_Intensity\", 60), // 7: Intensity\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Float, Styles.IndirectMultiplier, \"m_BounceIntensity\", 110, (r, prop, dep) =>\n                {\n                    bool realtimeLight = dep.Length > 1 && dep[0].intValue == (int)LightmapBakeType.Realtime;\n\n                    if (!(realtimeLight && !SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime)))\n                    {\n                        EditorGUI.PropertyField(r, prop, GUIContent.none);\n                    }\n                }, null, null, new int[] { 4 }), // 8: Indirect Multiplier\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Enum, Styles.ShadowType, \"m_Shadows.m_Type\", 100, (r, prop, dep) =>\n                {\n                    bool areaLight = dep.Length > 1 && (dep[0].enumValueIndex == (int)LightType.Rectangle || dep[0].enumValueIndex == (int)LightType.Disc);\n\n                    if (areaLight)\n                    {\n                        EditorGUI.BeginProperty(r, GUIContent.none, prop);\n                        EditorGUI.BeginChangeCheck();\n                        bool shadows = EditorGUI.Toggle(r, prop.intValue != (int)LightShadows.None);\n\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            prop.intValue = shadows ? (int)LightShadows.Soft : (int)LightShadows.None;\n                        }\n                        EditorGUI.EndProperty();\n                    }\n                    else\n                    {\n                        EditorGUI.PropertyField(r, prop, GUIContent.none);\n                    }\n                }, null, null, new int[] { 2 }),     // 9: Shadow Type\n            };\n        }\n\n        protected internal virtual UnityEngine.Object[] GetReflectionProbes()\n        {\n            return GetObjectsForLightingExplorer<ReflectionProbe>().ToArray();\n        }\n\n        protected virtual LightingExplorerTableColumn[] GetReflectionProbeColumns()\n        {\n            return new[]\n            {\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.Enabled, \"m_Enabled\", 50), // 0: Enabled\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200),  // 1: Name\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Int, Styles.Mode, \"m_Mode\", 70, (r, prop, dep) =>\n                {\n                    EditorGUI.IntPopup(r, prop, ReflectionProbeEditor.Styles.reflectionProbeMode, ReflectionProbeEditor.Styles.reflectionProbeModeValues, GUIContent.none);\n                }),     // 2: Mode\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Int, Styles.Projection, \"m_BoxProjection\", 80, (r, prop, dep) =>\n                {\n                    int[] opts = { 0, 1 };\n                    prop.boolValue = EditorGUI.IntPopup(r, prop.boolValue ? 1 : 0, Styles.ProjectionStrings, opts) == 1;\n                }),     // 3: Projection\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.HDR, \"m_HDR\", 35),  // 4: HDR\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Float, Styles.ShadowDistance, \"m_ShadowDistance\", 35), // 5: Shadow Distance\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Float, Styles.NearPlane, \"m_NearClip\", 70), // 6: Near Plane\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Float, Styles.FarPlane, \"m_FarClip\", 70), // 7: Far Plane\n            };\n        }\n\n        protected internal virtual UnityEngine.Object[] GetLightProbes()\n        {\n            return GetObjectsForLightingExplorer<LightProbeGroup>().ToArray();\n        }\n\n        protected virtual LightingExplorerTableColumn[] GetLightProbeColumns()\n        {\n            return new[]\n            {\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.Enabled, \"m_Enabled\", 50), // 0: Enabled\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 1: Name\n            };\n        }\n\n        protected internal virtual UnityEngine.Object[] GetEmissives()\n        {\n            return GetObjectsForLightingExplorer<MeshRenderer>().Where((MeshRenderer mr) =>\n            {\n                return GameObjectUtility.AreStaticEditorFlagsSet(mr.gameObject, StaticEditorFlags.ContributeGI);\n            }).SelectMany(meshRenderer => meshRenderer.sharedMaterials).Where((Material m) =>\n\n            {\n                return m != null && ((m.globalIlluminationFlags & MaterialGlobalIlluminationFlags.AnyEmissive) != 0) && m.HasProperty(\"_EmissionColor\");\n            }).Distinct().ToArray();\n        }\n\n        protected virtual LightingExplorerTableColumn[] GetEmissivesColumns()\n        {\n            return new[]\n            {\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Custom, Styles.SelectObjects, \"m_LightmapFlags\", 20, (r, prop, dep) =>\n                {\n                    if (GUI.Button(r, Styles.SelectObjectsButton, \"label\"))\n                    {\n                        SearchableEditorWindow.SearchForReferencesToInstanceID(prop.serializedObject.targetObject.GetInstanceID());\n                    }\n                }),     // 0: Icon\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 1: Name\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Int, Styles.GlobalIllumination, \"m_LightmapFlags\", 120, (r, prop, dep) =>\n                {\n                    if (!prop.serializedObject.targetObject.GetType().Equals(typeof(Material)))\n                        return;\n\n                    using (new EditorGUI.DisabledScope(!IsEditable(prop.serializedObject.targetObject)))\n                    {\n                        MaterialGlobalIlluminationFlags giFlags = ((prop.intValue & (int)MaterialGlobalIlluminationFlags.BakedEmissive) != 0) ? MaterialGlobalIlluminationFlags.BakedEmissive : MaterialGlobalIlluminationFlags.RealtimeEmissive;\n\n                        int[] lightmapEmissiveValues = { (int)MaterialGlobalIlluminationFlags.RealtimeEmissive, (int)MaterialGlobalIlluminationFlags.BakedEmissive };\n\n                        EditorGUI.BeginProperty(r, GUIContent.none, prop);\n                        EditorGUI.BeginChangeCheck();\n\n                        giFlags = (MaterialGlobalIlluminationFlags)EditorGUI.IntPopup(r, (int)giFlags, Styles.LightmapEmissiveStrings, lightmapEmissiveValues);\n\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            Material material = (Material)prop.serializedObject.targetObject;\n                            Undo.RecordObject(material, $\"Modify Emission Flags of {material.name}\");\n                            material.globalIlluminationFlags = giFlags;\n                            EditorUtility.SetDirty(material);\n\n                            prop.serializedObject.Update();\n                        }\n                        EditorGUI.EndProperty();\n                    }\n                }),     // 2: GI\n                new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Custom, Styles.Color, \"m_Shader\", 120, (r, prop, dep) =>\n                {\n                    if (!prop.serializedObject.targetObject.GetType().Equals(typeof(Material)))\n                        return;\n\n                    using (new EditorGUI.DisabledScope(!IsEditable(prop.serializedObject.targetObject)))\n                    {\n                        Material material = (Material)prop.serializedObject.targetObject;\n\n                        Color color = material.GetColor(\"_EmissionColor\");\n\n                        EditorGUI.BeginProperty(r, GUIContent.none, prop);\n                        EditorGUI.BeginChangeCheck();\n                        Color newValue = EditorGUI.ColorField(r, GUIContent.Temp(\"\"), color, true, false, true);\n\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            Undo.RecordObject(material, $\"Modify Emission Flags of {material.name}\");\n                            material.SetColor(\"_EmissionColor\", newValue);\n                            EditorUtility.SetDirty(material);\n                        }\n                        EditorGUI.EndProperty();\n                    }\n                }, (lhs, rhs) =>\n                    {\n                        float lh, ls, lv, rh, rs, rv;\n                        Color.RGBToHSV(((Material)lhs.serializedObject.targetObject).GetColor(\"_EmissionColor\"), out lh, out ls, out lv);\n                        Color.RGBToHSV(((Material)rhs.serializedObject.targetObject).GetColor(\"_EmissionColor\"), out rh, out rs, out rv);\n                        return lv.CompareTo(rv);\n                    }, (target, source) =>\n                    {\n                        Material sourceMaterial = (Material)source.serializedObject.targetObject;\n                        Color color = sourceMaterial.GetColor(\"_EmissionColor\");\n\n                        Material targetMaterial = (Material)target.serializedObject.targetObject;\n                        Undo.RecordObject(targetMaterial, $\"Modify Emission Flags of {targetMaterial.name}\");\n                        targetMaterial.SetColor(\"_EmissionColor\", color);\n                        EditorUtility.SetDirty(targetMaterial);\n                    }) // 3: Color\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneModeWindows/LightingExplorerExtensionAttribute.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n﻿using System;\nusing UnityEditor.Rendering;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor;\n\n[Obsolete($\"{nameof(LightingExplorerExtensionAttribute)} is deprecated. Use {nameof(SupportedOnRenderPipelineAttribute)} instead. #from(23.1) (UnityUpgradable) -> UnityEngine.Rendering.SupportedOnRenderPipelineAttribute\", false)]\n[AttributeUsage(AttributeTargets.Class)]\npublic class LightingExplorerExtensionAttribute : ScriptableRenderPipelineExtensionAttribute\n{\n    public LightingExplorerExtensionAttribute(Type renderPipeline)\n        : base(renderPipeline) {}\n}\n"
  },
  {
    "path": "Editor/Mono/SceneModeWindows/LightingExplorerTab.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing System.Linq;\n\nnamespace UnityEditor\n{\n    public class LightingExplorerTab\n    {\n        SerializedPropertyTable m_LightTable;\n        GUIContent m_Title;\n\n        internal GUIContent title { get { return m_Title; } }\n\n        public LightingExplorerTab(string title, Func<UnityEngine.Object[]> objects, Func<LightingExplorerTableColumn[]> columns)\n            : this(title, objects, columns, true) {}\n\n        public LightingExplorerTab(string title, Func<UnityEngine.Object[]> objects, Func<LightingExplorerTableColumn[]> columns, bool showFilterGUI)\n        {\n            if (objects() == null)\n                throw new ArgumentException(\"Objects are not allowed to be null\", \"objects\");\n\n            if (columns() == null)\n                throw new ArgumentException(\"Columns are not allowed to be null\", \"columns\");\n\n            m_LightTable = new SerializedPropertyTable(title.Replace(\" \", string.Empty), new SerializedPropertyDataStore.GatherDelegate(objects), () => {\n                return columns().Select(item => item.internalColumn).ToArray();\n            }, showFilterGUI);\n            m_Title = EditorGUIUtility.TrTextContent(title);\n        }\n\n        internal void OnDisable()\n        {\n            if (m_LightTable != null)\n                m_LightTable.OnDisable();\n        }\n\n        internal void OnInspectorUpdate()\n        {\n            if (m_LightTable != null)\n                m_LightTable.OnInspectorUpdate();\n        }\n\n        internal void OnSelectionChange(int[] instanceIDs)\n        {\n            if (m_LightTable != null)\n                m_LightTable.OnSelectionChange(instanceIDs);\n        }\n\n        internal void OnSelectionChange()\n        {\n            if (m_LightTable != null)\n                m_LightTable.OnSelectionChange();\n        }\n\n        internal void OnHierarchyChange()\n        {\n            if (m_LightTable != null)\n                m_LightTable.OnHierarchyChange();\n        }\n\n        internal void OnGUI()\n        {\n            EditorGUI.indentLevel += 1;\n\n            int cur_indent = EditorGUI.indentLevel;\n            float cur_indent_px = EditorGUI.indent;\n            EditorGUI.indentLevel = 0;\n\n            EditorGUILayout.BeginHorizontal();\n            GUILayout.Space(cur_indent_px);\n\n            using (new EditorGUILayout.VerticalScope())\n            {\n                if (m_LightTable != null)\n                    m_LightTable.OnGUI();\n            }\n\n            EditorGUILayout.EndHorizontal();\n            EditorGUILayout.Space();\n            EditorGUI.indentLevel = cur_indent;\n\n            EditorGUI.indentLevel -= 1;\n        }\n    }\n\n    public sealed class LightingExplorerTableColumn\n    {\n        public enum DataType\n        {\n            Name = 0,\n            Checkbox = 1,\n            Enum = 2,\n            Int = 3,\n            Float = 4,\n            Color = 5,\n            // ..\n            Custom = 20\n        }\n\n        SerializedPropertyTreeView.Column m_Column;\n\n        internal SerializedPropertyTreeView.Column internalColumn { get { return m_Column; } }\n\n        public delegate void OnGUIDelegate(Rect r, SerializedProperty prop, SerializedProperty[] dependencies);\n        public delegate int ComparePropertiesDelegate(SerializedProperty lhs, SerializedProperty rhs);\n        public delegate void CopyPropertiesDelegate(SerializedProperty target, SerializedProperty source);\n\n        public LightingExplorerTableColumn(DataType type, GUIContent headerContent, string propertyName = null, int width = 100, OnGUIDelegate onGUIDelegate = null, ComparePropertiesDelegate compareDelegate = null, CopyPropertiesDelegate copyDelegate = null, int[] dependencyIndices = null)\n        {\n            m_Column = new SerializedPropertyTreeView.Column();\n\n            m_Column.headerContent          = headerContent;\n            m_Column.width                  = width;\n            m_Column.minWidth               = width / 2;\n            m_Column.propertyName           = propertyName;\n            m_Column.dependencyIndices      = dependencyIndices;\n\n            m_Column.sortedAscending        = true;\n            m_Column.sortingArrowAlignment  = TextAlignment.Center;\n            m_Column.autoResize             = true;\n            m_Column.allowToggleVisibility  = true;\n            m_Column.headerTextAlignment    = type == DataType.Checkbox ? TextAlignment.Center : TextAlignment.Left;\n\n            switch (type)\n            {\n                case DataType.Name:\n                    m_Column.compareDelegate = SerializedPropertyTreeView.DefaultDelegates.CompareName;\n                    m_Column.drawDelegate    = SerializedPropertyTreeView.DefaultDelegates.DrawName;\n                    m_Column.filter          = new SerializedPropertyFilters.Name();\n                    break;\n\n                case DataType.Checkbox:\n                    m_Column.compareDelegate = SerializedPropertyTreeView.DefaultDelegates.CompareCheckbox;\n                    m_Column.drawDelegate    = SerializedPropertyTreeView.DefaultDelegates.DrawCheckbox;\n                    break;\n\n                case DataType.Enum:\n                    m_Column.compareDelegate = SerializedPropertyTreeView.DefaultDelegates.CompareEnum;\n                    m_Column.drawDelegate    = SerializedPropertyTreeView.DefaultDelegates.DrawDefault;\n                    break;\n\n                case DataType.Int:\n                    m_Column.compareDelegate = SerializedPropertyTreeView.DefaultDelegates.CompareInt;\n                    m_Column.drawDelegate    = SerializedPropertyTreeView.DefaultDelegates.DrawDefault;\n                    break;\n\n                case DataType.Float:\n                    m_Column.compareDelegate = SerializedPropertyTreeView.DefaultDelegates.CompareFloat;\n                    m_Column.drawDelegate    = SerializedPropertyTreeView.DefaultDelegates.DrawDefault;\n                    break;\n\n                case DataType.Color:\n                    m_Column.compareDelegate = SerializedPropertyTreeView.DefaultDelegates.CompareColor;\n                    m_Column.drawDelegate    = SerializedPropertyTreeView.DefaultDelegates.DrawDefault;\n                    break;\n\n                default:\n                    break;\n            }\n\n            if (onGUIDelegate != null)\n            {\n                // when allowing the user to draw checkboxes, we will make sure that the rect is in the center\n                if (type == DataType.Checkbox)\n                {\n                    m_Column.drawDelegate = (r, prop, dep) => {\n                        float off = System.Math.Max(0.0f, ((r.width / 2) - 8));\n                        r.x += off;\n                        r.width -= off;\n                        onGUIDelegate(r, prop, dep);\n                    };\n                }\n                else\n                    m_Column.drawDelegate = new SerializedPropertyTreeView.Column.DrawEntry(onGUIDelegate);\n            }\n\n            if (compareDelegate != null)\n                m_Column.compareDelegate = new SerializedPropertyTreeView.Column.CompareEntry(compareDelegate);\n\n            if (copyDelegate != null)\n                m_Column.copyDelegate = new SerializedPropertyTreeView.Column.CopyDelegate(copyDelegate);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneModeWindows/LightingExplorerWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEditor.Rendering;\nusing System.Linq;\nusing System;\n\nnamespace UnityEditor\n{\n    //Attribute that should be deprecated in 2020.1\n    //Will be replaced by ScriptableRenderPipelineAttribute\n    //Kept for package compatibility and user SRP compatibility at the moment\n\n    public interface ILightingExplorerExtension\n    {\n        LightingExplorerTab[] GetContentTabs();\n\n        void OnEnable();\n        void OnDisable();\n    }\n\n    [EditorWindowTitle(title = \"Light Explorer\", icon = \"Lighting\")]\n    internal class LightingExplorerWindow : EditorWindow\n    {\n        LightingExplorerTab[] m_TableTabs;\n        GUIContent[] m_TabTitles;\n\n        int m_SelectedTab = 0;\n\n        System.Type m_CurrentSRPType = null;\n        ILightingExplorerExtension m_CurrentLightingExplorerExtension = null;\n        static ILightingExplorerExtension s_DefaultLightingExplorerExtension = null;\n\n        [MenuItem(\"Window/Rendering/Light Explorer\", priority = 2, secondaryPriority = 1)]\n        static void CreateLightingExplorerWindow()\n        {\n            LightingExplorerWindow window = EditorWindow.GetWindow<LightingExplorerWindow>();\n            window.minSize = new Vector2(500, 250);\n            window.Show();\n        }\n\n        void OnEnable()\n        {\n            titleContent = GetLocalizedTitleContent();\n\n            UpdateTabs();\n\n            EditorApplication.searchChanged += Repaint;\n            Repaint();\n        }\n\n        void OnDisable()\n        {\n            OnDisableTabsAndExtension();\n            EditorApplication.searchChanged -= Repaint;\n        }\n\n        void OnDisableTabsAndExtension()\n        {\n            if (m_TableTabs != null)\n            {\n                for (int i = 0; i < m_TableTabs.Length; i++)\n                {\n                    m_TableTabs[i].OnDisable();\n                }\n            }\n\n            if (m_CurrentLightingExplorerExtension != null)\n            {\n                m_CurrentLightingExplorerExtension.OnDisable();\n            }\n        }\n\n        void OnInspectorUpdate()\n        {\n            if (m_TableTabs != null && (int)m_SelectedTab >= 0 && (int)m_SelectedTab < m_TableTabs.Length)\n            {\n                m_TableTabs[(int)m_SelectedTab].OnInspectorUpdate();\n            }\n        }\n\n        void OnSelectionChange()\n        {\n            if (m_TableTabs != null)\n            {\n                for (int i = 0; i < m_TableTabs.Length; i++)\n                {\n                    if (i == (m_TableTabs.Length - 1)) // last tab containing materials\n                    {\n                        int[] selectedIds = UnityEngine.Object.FindObjectsByType<MeshRenderer>(UnityEngine.FindObjectsSortMode.InstanceID).Where((MeshRenderer mr) => {\n                            return Selection.instanceIDs.Contains(mr.gameObject.GetInstanceID());\n                        }).SelectMany(meshRenderer => meshRenderer.sharedMaterials).Where((Material m) => {\n                                return m != null && (m.globalIlluminationFlags & MaterialGlobalIlluminationFlags.AnyEmissive) != 0;\n                            }).Select(m => m.GetInstanceID()).Union(Selection.instanceIDs).Distinct().ToArray();\n\n                        m_TableTabs[i].OnSelectionChange(selectedIds);\n                    }\n                    else\n                        m_TableTabs[i].OnSelectionChange();\n                }\n            }\n\n            Repaint();\n        }\n\n        void OnHierarchyChange()\n        {\n            if (m_TableTabs != null)\n            {\n                for (int i = 0; i < m_TableTabs.Length; i++)\n                {\n                    m_TableTabs[i].OnHierarchyChange();\n                }\n            }\n        }\n\n        void OnGUI()\n        {\n            UpdateTabs();\n\n            EditorGUIUtility.labelWidth = 130;\n\n            EditorGUILayout.Space();\n            EditorGUILayout.BeginHorizontal();\n\n            GUILayout.FlexibleSpace();\n            if (m_TabTitles != null)\n                m_SelectedTab = GUILayout.Toolbar(m_SelectedTab, m_TabTitles, \"LargeButton\", GUI.ToolbarButtonSize.FitToContents);\n            GUILayout.FlexibleSpace();\n\n            EditorGUILayout.EndHorizontal();\n            EditorGUILayout.Space();\n\n            EditorGUILayout.BeginHorizontal();\n            if (m_TableTabs != null && (int)m_SelectedTab >= 0 && (int)m_SelectedTab < m_TableTabs.Length)\n                m_TableTabs[(int)m_SelectedTab].OnGUI();\n            EditorGUILayout.Space();\n            EditorGUILayout.EndHorizontal();\n\n            EditorGUILayout.Space();\n        }\n\n        private System.Type GetSRPType()\n        {\n            System.Type SRPType = null;\n\n            if (GraphicsSettings.currentRenderPipeline != null)\n            {\n                SRPType = GraphicsSettings.currentRenderPipeline.GetType();\n            }\n\n            return SRPType;\n        }\n\n        private void UpdateTabs()\n        {\n            var SRPType = GetSRPType();\n\n            if (m_CurrentLightingExplorerExtension == null || m_CurrentSRPType != SRPType)\n            {\n                m_CurrentSRPType = SRPType;\n\n                OnDisableTabsAndExtension();\n\n                m_CurrentLightingExplorerExtension = GetLightExplorerExtension(SRPType);\n                m_CurrentLightingExplorerExtension.OnEnable();\n\n                m_SelectedTab = EditorSettings.defaultBehaviorMode == EditorBehaviorMode.Mode2D ? /* 2D Lights */ 1 : /* Lights */ 0;\n\n                if (m_CurrentLightingExplorerExtension.GetContentTabs() == null || m_CurrentLightingExplorerExtension.GetContentTabs().Length == 0)\n                {\n                    throw new ArgumentException(\"There must be atleast 1 content tab defined for the Lighting Explorer.\");\n                }\n\n                m_TableTabs =  m_CurrentLightingExplorerExtension.GetContentTabs();\n                m_TabTitles = m_TableTabs != null ? m_TableTabs.Select(item => item.title).ToArray() : null;\n            }\n        }\n\n        ILightingExplorerExtension GetDefaultLightingExplorerExtension()\n        {\n            return s_DefaultLightingExplorerExtension ??= new DefaultLightingExplorerExtension();\n        }\n\n        ILightingExplorerExtension GetLightExplorerExtension(Type currentSRPType)\n        {\n            if (currentSRPType == null)\n                return GetDefaultLightingExplorerExtension();\n\n            var extensionType = RenderPipelineEditorUtility.GetDerivedTypesSupportedOnCurrentPipeline<ILightingExplorerExtension>().FirstOrDefault();\n            if (extensionType == null)\n                return GetDefaultLightingExplorerExtension();\n\n            var extension = (ILightingExplorerExtension) Activator.CreateInstance(extensionType);\n            return extension;\n            // no light explorer extension found for current srp, return the default one\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneModeWindows/LightingWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngineInternal;\nusing UnityEngine.Rendering;\nusing System.Text;\nusing System.Globalization;\nusing System.Linq;\n\nnamespace UnityEditor\n{\n    [EditorWindowTitle(title = \"Lighting\", icon = \"Lighting\")]\n    internal class LightingWindow : EditorWindow\n    {\n        static class Styles\n        {\n            public static readonly GUIContent[] modeStrings =\n            {\n                EditorGUIUtility.TrTextContent(\"Scene\"),\n                EditorGUIUtility.TrTextContent(\"Environment\"),\n                EditorGUIUtility.TrTextContent(\"Realtime Lightmaps\"),\n                EditorGUIUtility.TrTextContent(\"Baked Lightmaps\")\n            };\n\n            public static readonly GUIStyle labelStyle = EditorStyles.wordWrappedMiniLabel;\n            public static readonly GUIStyle buttonStyle = \"LargeButton\";\n            public static readonly GUIContent continuousBakeLabel = EditorGUIUtility.TrTextContent(\"Auto Generate\", \"Generate lighting data in the Scene when there are changes that affect Scene lighting, such as modifications to lights, materials, or geometry. This option is only available when there is a Lighting Settings Asset assigned in the Lighting Window.\");\n            public static readonly GUIContent bakeLabel = EditorGUIUtility.TrTextContent(\"Generate Lighting\", \"Generates the lightmap data for the current active scene. This lightmap data (for realtime and baked global illumination) is stored in the GI Cache. For GI Cache settings see the Preferences panel.\");\n            public static readonly GUIContent bakeLabelAnythingCompiling = EditorGUIUtility.TrTextContent(\"Generate Lighting\", \"Generate Lighting is currently unavailable. Waiting for asynchronous shader compilation.\");\n            public static readonly GUIContent cancelLabel = EditorGUIUtility.TrTextContent(\"Cancel\");\n\n            public static readonly GUIContent progressiveGPUBakingDevice = EditorGUIUtility.TrTextContent(\"GPU Baking Device\", \"Will list all available GPU devices.\");\n            public static readonly GUIContent progressiveGPUUnknownDeviceInfo = EditorGUIUtility.TrTextContent(\"No devices found. Please start an initial bake to make this information available.\");\n            public static readonly GUIContent progressiveGPUChangeWarning = EditorGUIUtility.TrTextContent(\"Changing the compute device used by the Progressive GPU Lightmapper requires the editor to be relaunched. Do you want to change device and restart?\");\n            public static readonly GUIContent gpuBakingProfile = EditorGUIUtility.TrTextContent(\"GPU Baking Profile\", \"The profile chosen for trading off between performance and memory usage when baking using the GPU.\");\n\n            public static readonly GUIContent bakeOnSceneLoad = EditorGUIUtility.TrTextContent(\"Bake On Scene Load\", \"Whether to automatically generate lighting for Scenes that do not have valid lighting data when first opened.\"); \n\n            public static readonly GUIContent invalidEnvironmentLabel = EditorGUIUtility.TrTextContentWithIcon(\"Baked environment lighting does not match the current Scene state. Generate Lighting to update this.\", MessageType.Warning);\n            public static readonly GUIContent unsupportedDenoisersLabel = EditorGUIUtility.TrTextContentWithIcon(\"Unsupported denoiser selected\", MessageType.Error);\n\n            public static readonly int[] progressiveGPUUnknownDeviceValues = { 0 };\n            public static readonly GUIContent[] progressiveGPUUnknownDeviceStrings =\n            {\n                EditorGUIUtility.TrTextContent(\"Unknown\"),\n            };\n\n            // Keep in sync with BakingProfile.h::BakingProfile\n            public static readonly int bakingProfileDefault = 2;\n            public static readonly int[] bakingProfileValues = { 0, 1, 2, 3, 4 };\n            public static readonly GUIContent[] bakingProfileStrings =\n            {\n                EditorGUIUtility.TrTextContent(\"Highest Performance\"),\n                EditorGUIUtility.TrTextContent(\"High Performance\"),\n                EditorGUIUtility.TrTextContent(\"Automatic\"),\n                EditorGUIUtility.TrTextContent(\"Low Memory Usage\"),\n                EditorGUIUtility.TrTextContent(\"Lowest Memory Usage\"),\n            };\n\n            public static string[] BakeModeStrings =\n            {\n                \"Bake Reflection Probes\",\n                \"Clear Baked Data\"\n            };\n\n            public static readonly string BakingPausedHelpText = $\"{Styles.bakeLabel.text} is currently unavailable. Waiting for asynchronous shader compilation to finish...\";\n        }\n\n        public interface WindowTab\n        {\n            void OnEnable();\n            void OnDisable();\n            void OnGUI();\n            void OnSummaryGUI();\n            void OnSelectionChange();\n            bool HasHelpGUI();\n        }\n\n        enum BakeMode\n        {\n            BakeReflectionProbes = 0,\n            Clear = 1\n        }\n\n        enum Mode\n        {\n            LightingSettings = 0,\n            EnvironmentSettings,\n            RealtimeLightmaps,\n            BakedLightmaps\n        }\n\n        string kGlobalIlluminationUnityManualPage = $\"https://docs.unity3d.com/{Application.unityVersionVer}.{Application.unityVersionMaj}/Documentation/Manual/lighting-window.html\";\n\n        const string m_LightmappingDeviceIndexKey = \"lightmappingDeviceIndex\";\n        const string m_BakingProfileKey = \"lightmappingBakingProfile\";\n\n        int m_SelectedModeIndex = 0;\n        List<Mode> m_Modes = null;\n        GUIContent[] m_ModeStrings;\n\n        Dictionary<Mode, WindowTab> m_Tabs = new Dictionary<Mode, WindowTab>();\n\n        static SerializedObject m_LightingSettings;\n\n        bool m_IsRealtimeSupported = false;\n        bool m_IsBakedSupported = false;\n        bool m_IsEnvironmentSupported = false;\n\n        static SerializedObject lightingSettings\n        {\n            get\n            {\n                // if we set a new scene as the active scene, we need to make sure to respond to those changes\n                if (m_LightingSettings == null || m_LightingSettings.targetObject == null || m_LightingSettings.targetObject != Lightmapping.lightingSettingsInternal)\n                {\n                    var targetObject = Lightmapping.lightingSettingsInternal;\n\n                    if (targetObject == null)\n                    {\n                        targetObject = Lightmapping.lightingSettingsDefaults;\n                    }\n\n                    m_LightingSettings = new SerializedObject(targetObject);\n                }\n                return m_LightingSettings;\n            }\n        }\n\n        // for internal debug use only\n        internal void SetSelectedTabIndex(int index)\n        {\n            m_SelectedModeIndex = index;\n        }\n\n        LightingWindow()\n        {\n            m_Tabs.Add(Mode.LightingSettings, new LightingWindowLightingTab());\n            m_Tabs.Add(Mode.EnvironmentSettings, new LightingWindowEnvironmentTab());\n            m_Tabs.Add(Mode.RealtimeLightmaps, new LightingWindowLightmapPreviewTab(LightmapType.DynamicLightmap));\n            m_Tabs.Add(Mode.BakedLightmaps, new LightingWindowLightmapPreviewTab(LightmapType.StaticLightmap));\n\n            var customWindowTabs = TypeCache.GetTypesDerivedFrom<LightingWindowTab>();\n            foreach (Type tabType in customWindowTabs)\n            {\n                var tab = Activator.CreateInstance(tabType) as LightingWindowTab;\n                m_Tabs.Add((Mode)tabType.Name.GetHashCode(), tab);\n                tab.m_Parent = this;\n            }\n        }\n\n        // Repaint when MRays/sec changes\n        float m_LastRepaintedMraysPerSec;\n        protected void Update()\n        {\n            float totalNow = Lightmapping.GetLightmapBakePerformanceTotal();\n            if (Math.Abs(totalNow - m_LastRepaintedMraysPerSec) < s_MraysPerSecRepaintThreshold)\n                return;\n\n            m_LastRepaintedMraysPerSec = totalNow;\n            Repaint();\n        }\n\n        void OnEnable()\n        {\n            s_Window = this;\n\n            titleContent = GetLocalizedTitleContent();\n\n            foreach (var pair in m_Tabs)\n                pair.Value.OnEnable();\n\n            Undo.undoRedoEvent += OnUndoRedo;\n            Lightmapping.lightingDataUpdated += Repaint;\n\n            Repaint();\n        }\n\n        void OnDisable()\n        {\n            foreach (var pair in m_Tabs)\n                pair.Value.OnDisable();\n\n            Undo.undoRedoEvent -= OnUndoRedo;\n            Lightmapping.lightingDataUpdated -= Repaint;\n        }\n\n        private void OnUndoRedo(in UndoRedoInfo info)\n        {\n            Repaint();\n        }\n\n        void OnBecameVisible()\n        {\n            RepaintSceneAndGameViews();\n        }\n\n        void OnBecameInvisible()\n        {\n            RepaintSceneAndGameViews();\n        }\n\n        void OnSelectionChange()\n        {\n            if (m_Modes == null)\n                return;\n\n            foreach (var pair in m_Tabs)\n            {\n                if (m_Modes.Contains(pair.Key))\n                    pair.Value.OnSelectionChange();\n            }\n\n            Repaint();\n        }\n\n        static internal void RepaintSceneAndGameViews()\n        {\n            SceneView.RepaintAll();\n            PlayModeView.RepaintAll();\n        }\n\n        void OnGUI()\n        {\n            // This is done so that we can adjust the UI when the user swiches SRP\n            SetupModes();\n\n            lightingSettings.Update();\n\n            // reset index to settings page if one of the tabs went away\n            if (m_SelectedModeIndex < 0 || m_SelectedModeIndex >= m_Modes.Count)\n                m_SelectedModeIndex = 0;\n\n            Mode selectedMode = m_Modes[m_SelectedModeIndex];\n\n            DrawTopBarGUI(selectedMode);\n\n            EditorGUILayout.Space();\n\n            if (m_Tabs.ContainsKey(selectedMode))\n                m_Tabs[selectedMode].OnGUI();\n\n            // Draw line to separate the bottom portion of the window from the tab being displayed\n            Rect lineRect = GUILayoutUtility.topLevel.PeekNext();\n            lineRect.height = 1;\n            EditorGUI.DrawDelimiterLine(lineRect);\n            EditorGUILayout.Space();\n\n            DrawBottomBarGUI(selectedMode);\n\n            lightingSettings.ApplyModifiedProperties();\n        }\n\n        void SetupModes()\n        {\n            if (m_Modes == null)\n            {\n                m_Modes = new List<Mode>();\n            }\n\n            bool isRealtimeSupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime);\n            bool isBakedSupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Baked);\n            bool isEnvironmentSupported = !(SupportedRenderingFeatures.active.overridesEnvironmentLighting && SupportedRenderingFeatures.active.overridesFog && SupportedRenderingFeatures.active.overridesOtherLightingSettings);\n\n            if (m_IsRealtimeSupported != isRealtimeSupported || m_IsBakedSupported != isBakedSupported || m_IsEnvironmentSupported != isEnvironmentSupported)\n            {\n                m_Modes.Clear();\n\n                m_IsBakedSupported = isBakedSupported;\n                m_IsRealtimeSupported = isRealtimeSupported;\n                m_IsEnvironmentSupported = isEnvironmentSupported;\n            }\n\n            // if nothing has changed since last time and we have data, we return\n            if (m_Modes.Count > 0)\n                return;\n\n            List<GUIContent> modeStringList = new List<GUIContent>();\n\n            m_Modes.Add(Mode.LightingSettings);\n            modeStringList.Add(Styles.modeStrings[(int)Mode.LightingSettings]);\n\n            if (m_IsEnvironmentSupported)\n            {\n                m_Modes.Add(Mode.EnvironmentSettings);\n                modeStringList.Add(Styles.modeStrings[(int)Mode.EnvironmentSettings]);\n            }\n\n            if (m_IsRealtimeSupported)\n            {\n                m_Modes.Add(Mode.RealtimeLightmaps);\n                modeStringList.Add(Styles.modeStrings[(int)Mode.RealtimeLightmaps]);\n            }\n\n            if (m_IsBakedSupported)\n            {\n                m_Modes.Add(Mode.BakedLightmaps);\n                modeStringList.Add(Styles.modeStrings[(int)Mode.BakedLightmaps]);\n            }\n\n            foreach (var pair in m_Tabs)\n            {\n                var customTab = pair.Value as LightingWindowTab;\n                if (customTab == null) continue;\n\n                int priority = customTab.priority < 0 ? m_Modes.Count : Mathf.Min(customTab.priority, m_Modes.Count);\n                m_Modes.Insert(priority, pair.Key);\n                modeStringList.Insert(priority, customTab.titleContent);\n            }\n\n            Debug.Assert(m_Modes.Count == modeStringList.Count);\n\n            m_ModeStrings = modeStringList.ToArray();\n        }\n\n        internal void SetToolbarDirty()\n        {\n            m_Modes = null;\n        }\n\n        void DrawHelpGUI()\n        {\n            var iconSize = EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.helpIcon);\n            var rect = GUILayoutUtility.GetRect(iconSize.x, iconSize.y);\n\n            if (GUI.Button(rect, EditorGUI.GUIContents.helpIcon, EditorStyles.iconButton))\n            {\n                Help.ShowHelpPage(kGlobalIlluminationUnityManualPage);\n            }\n        }\n\n        void DrawSettingsGUI(Mode mode)\n        {\n            if (mode == Mode.LightingSettings || mode == Mode.EnvironmentSettings)\n            {\n                var iconSize = EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.titleSettingsIcon);\n                var rect = GUILayoutUtility.GetRect(iconSize.x, iconSize.y);\n\n                if (EditorGUI.DropdownButton(rect, EditorGUI.GUIContents.titleSettingsIcon, FocusType.Passive, EditorStyles.iconButton))\n                {\n                    if (mode == Mode.LightingSettings)\n                        EditorUtility.DisplayCustomMenu(rect, new[] { EditorGUIUtility.TrTextContent(\"Reset\") }, -1, ResetLightingSettings, null);\n                    else if (mode == Mode.EnvironmentSettings)\n                        EditorUtility.DisplayCustomMenu(rect, new[] { EditorGUIUtility.TrTextContent(\"Reset\") }, -1, ResetEnvironmentSettings, null);\n                }\n            }\n        }\n\n        void ResetLightingSettings(object userData, string[] options, int selected)\n        {\n            if (Lightmapping.lightingSettingsInternal != null)\n            {\n                Undo.RecordObjects(new[] { Lightmapping.lightingSettingsInternal }, \"Reset Lighting Settings\");\n                Unsupported.SmartReset(Lightmapping.lightingSettingsInternal);\n            }\n        }\n\n        void ResetEnvironmentSettings(object userData, string[] options, int selected)\n        {\n            Undo.RecordObjects(new[] { RenderSettings.GetRenderSettings() }, \"Reset Environment Settings\");\n            Unsupported.SmartReset(RenderSettings.GetRenderSettings());\n        }\n\n        void DrawToolbarRange(int start, int end)\n        {\n            var strings = new GUIContent[end - start];\n            Array.Copy(m_ModeStrings, start, strings, 0, strings.Length);\n\n            EditorGUILayout.BeginHorizontal();\n            GUILayout.FlexibleSpace();\n            m_SelectedModeIndex = GUILayout.Toolbar(m_SelectedModeIndex - start, strings, Styles.buttonStyle, GUI.ToolbarButtonSize.FitToContents) + start;\n            GUILayout.FlexibleSpace();\n            EditorGUILayout.EndHorizontal();\n        }\n\n        void DrawTopBarGUI(Mode selectedMode)\n        {\n            EditorGUILayout.Space();\n            EditorGUILayout.BeginHorizontal();\n\n            if (m_Tabs[selectedMode].HasHelpGUI())\n                GUILayout.Space(EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.helpIcon).x);\n\n            GUILayout.FlexibleSpace();\n\n            if (m_Modes.Count > 1)\n            {\n                // Split the toolbar if it doesn't fit horizontally\n                bool requireSplit = false;\n                float width = position.width - 2 * 16;\n                for (int i = 0; i < m_ModeStrings.Length; i++)\n                {\n                    width -= Styles.buttonStyle.CalcSize(m_ModeStrings[i]).x;\n                    if (width <= 0)\n                    {\n                        requireSplit = true;\n                        break;\n                    }\n                }\n\n                if (requireSplit)\n                {\n                    // Simply split in two to avoid weird layouts\n                    int half = Mathf.CeilToInt(m_ModeStrings.Length / 2.0f);\n\n                    EditorGUILayout.BeginVertical();\n                    DrawToolbarRange(0, half);\n                    DrawToolbarRange(half, m_ModeStrings.Length);\n                    EditorGUILayout.EndVertical();\n                }\n                else\n                    m_SelectedModeIndex = GUILayout.Toolbar(m_SelectedModeIndex, m_ModeStrings, Styles.buttonStyle, GUI.ToolbarButtonSize.FitToContents);\n            }\n\n            GUILayout.FlexibleSpace();\n\n            var customTab = m_Tabs[selectedMode] as LightingWindowTab;\n            if (customTab != null)\n                customTab.OnHeaderSettingsGUI();\n            else\n            {\n                DrawHelpGUI();\n                DrawSettingsGUI(selectedMode);\n            }\n\n            EditorGUILayout.EndHorizontal();\n            EditorGUILayout.Space();\n        }\n\n        internal static void FocusTab(LightingWindowTab tab)\n        {\n            EditorApplication.update += WaitForWindow;\n            void WaitForWindow()\n            {\n                // Open window in case it's closed\n                var window = GetWindow<LightingWindow>(utility: false, title: null, focus: false);\n                if (window == null || window.m_Modes == null)\n                    return;\n\n                EditorApplication.update -= WaitForWindow;\n\n                // Select active tab\n                var newMode = (Mode)tab.GetType().Name.GetHashCode();\n                if (window.m_Modes.Contains(newMode))\n                {\n                    window.m_SelectedModeIndex = window.m_Modes.IndexOf(newMode);\n                    window.Repaint();\n                }\n            }\n        }\n\n        void BakeDropDownCallback(object data)\n        {\n            BakeMode mode = (BakeMode)data;\n\n            switch (mode)\n            {\n                case BakeMode.Clear:\n                    DoClear();\n                    break;\n                case BakeMode.BakeReflectionProbes:\n                    DoBakeReflectionProbes();\n                    break;\n            }\n        }\n\n        void DrawGPUDeviceSelector()\n        {\n            // GPU lightmapper device selection.\n            if (Lightmapping.GetLightingSettingsOrDefaultsFallback().lightmapper == LightingSettings.Lightmapper.ProgressiveGPU)\n            {\n                DeviceAndPlatform[] devicesAndPlatforms = Lightmapping.GetLightmappingGpuDevices();\n                if (devicesAndPlatforms.Length > 0)\n                {\n                    int[] lightmappingDeviceIndices = Enumerable.Range(0, devicesAndPlatforms.Length).ToArray();\n                    GUIContent[] lightmappingDeviceStrings = devicesAndPlatforms.Select(x => new GUIContent(x.name)).ToArray();\n\n                    int bakingDeviceAndPlatform = -1;\n                    string configDeviceAndPlatform = EditorUserSettings.GetConfigValue(m_LightmappingDeviceIndexKey);\n                    if (configDeviceAndPlatform != null)\n                    {\n                        bakingDeviceAndPlatform = Int32.Parse(configDeviceAndPlatform);\n                        bakingDeviceAndPlatform = Mathf.Clamp(bakingDeviceAndPlatform, 0, devicesAndPlatforms.Length - 1); // Removing a GPU and rebooting invalidates the saved value.\n                    }\n                    else\n                        bakingDeviceAndPlatform = Lightmapping.GetLightmapBakeGPUDeviceIndex();\n\n                    Debug.Assert(bakingDeviceAndPlatform != -1);\n\n                    EditorGUI.BeginChangeCheck();\n                    using (new EditorGUI.DisabledScope(devicesAndPlatforms.Length < 2))\n                    {\n                        bakingDeviceAndPlatform = EditorGUILayout.IntPopup(Styles.progressiveGPUBakingDevice, bakingDeviceAndPlatform, lightmappingDeviceStrings, lightmappingDeviceIndices);\n                    }\n                    if (EditorGUI.EndChangeCheck())\n                    {\n                        if (EditorUtility.DisplayDialog(\"Warning\", Styles.progressiveGPUChangeWarning.text, \"OK\", \"Cancel\"))\n                        {\n                            EditorUserSettings.SetConfigValue(m_LightmappingDeviceIndexKey, bakingDeviceAndPlatform.ToString());\n                            DeviceAndPlatform selectedDeviceAndPlatform = devicesAndPlatforms[bakingDeviceAndPlatform];\n                            EditorApplication.CloseAndRelaunch(new string[] { \"-OpenCL-PlatformAndDeviceIndices\", selectedDeviceAndPlatform.platformId.ToString(), selectedDeviceAndPlatform.deviceId.ToString() });\n                        }\n                    }\n                }\n                else\n                {\n                    // To show when we are still fetching info, so that the UI doesn't pop around too much for no reason\n                    using (new EditorGUI.DisabledScope(true))\n                    {\n                        EditorGUILayout.IntPopup(Styles.progressiveGPUBakingDevice, 0, Styles.progressiveGPUUnknownDeviceStrings, Styles.progressiveGPUUnknownDeviceValues);\n                    }\n\n                    EditorGUILayout.HelpBox(Styles.progressiveGPUUnknownDeviceInfo.text, MessageType.Info);\n                }\n            }\n        }\n\n        void DrawBakingProfileSelector()\n        {\n            // Handle the baking profile setting\n            using (new EditorGUI.DisabledScope(Lightmapping.GetLightingSettingsOrDefaultsFallback().lightmapper != LightingSettings.Lightmapper.ProgressiveGPU))\n            {\n                int bakingProfile = Styles.bakingProfileDefault;\n                string bakingProfileString = EditorUserSettings.GetConfigValue(m_BakingProfileKey);\n                if (bakingProfileString != null)\n                {\n                    if (Int32.TryParse(bakingProfileString, out int bakingProfileStoredValue))\n                    {\n                        const Int32 maxBakingProfile = 4; // Keep in sync with kMaxBakingProfile (C++).\n                        if (bakingProfileStoredValue >= 0 && bakingProfileStoredValue <= maxBakingProfile)\n                            bakingProfile = bakingProfileStoredValue;\n                    }\n                }\n                bakingProfile = EditorGUILayout.IntPopup(Styles.gpuBakingProfile, bakingProfile, Styles.bakingProfileStrings, Styles.bakingProfileValues);\n                EditorUserSettings.SetConfigValue(m_BakingProfileKey, bakingProfile.ToString());\n            }\n        }\n\n        void DrawBakeOnLoadSelector()\n        {\n            var selected = (Lightmapping.BakeOnSceneLoadMode)EditorGUILayout.EnumPopup(Styles.bakeOnSceneLoad, Lightmapping.bakeOnSceneLoad);\n            if (selected != Lightmapping.bakeOnSceneLoad)\n            {\n                Undo.RecordObject(LightmapEditorSettings.GetLightmapSettings(), \"Change Bake On Load Setting\");\n                Lightmapping.bakeOnSceneLoad = selected;\n            }\n        }\n\n        void DrawBottomBarGUI(Mode selectedMode)\n        {\n            using (new EditorGUI.DisabledScope(EditorApplication.isPlayingOrWillChangePlaymode))\n            {\n                // Preamble with warnings.\n                if (Lightmapping.lightingDataAsset && !Lightmapping.lightingDataAsset.isValid)\n                {\n                    EditorGUILayout.HelpBox(Lightmapping.lightingDataAsset.validityErrorMessage, MessageType.Warning);\n                }\n\n                // Bake settings.\n                DrawGPUDeviceSelector();\n                DrawBakingProfileSelector();\n                DrawBakeOnLoadSelector();\n\n                {\n                    // Bake button if we are not currently baking\n                    bool showBakeButton = Lightmapping.shouldBakeInteractively || !Lightmapping.isRunning;\n                    if (showBakeButton)\n                    {\n                        bool anythingCompiling = ShaderUtil.anythingCompiling;\n                        using (new EditorGUI.DisabledScope(anythingCompiling))\n                        {\n                            var customTab = m_Tabs[selectedMode] as LightingWindowTab;\n                            if (customTab != null)\n                                customTab.OnBakeButtonGUI();\n                            else\n                            {\n                                GUIContent guiContent = anythingCompiling ? Styles.bakeLabelAnythingCompiling : Styles.bakeLabel;\n                                if (EditorGUI.LargeSplitButtonWithDropdownList(guiContent, Styles.BakeModeStrings, BakeDropDownCallback, disableMainButton: !SelectedDenoisersSupported()))\n                                {\n                                    DoBake();\n\n                                    // DoBake could've spawned a save scene dialog. This breaks GUI on mac (Case 490388).\n                                    // We work around this with an ExitGUI here.\n                                    GUIUtility.ExitGUI();\n                                }\n                            }\n                        }\n                    }\n                    // Cancel button if we are currently baking\n                    else\n                    {\n                        if (GUILayout.Button(Styles.cancelLabel, Styles.buttonStyle))\n                        {\n                            Lightmapping.Cancel();\n                        }\n                    }\n                }\n\n                // Per-tab summaries.\n                if (m_Tabs.ContainsKey(selectedMode))\n                {\n                    GUILayout.BeginVertical(EditorStyles.helpBox);\n                    m_Tabs[selectedMode].OnSummaryGUI();\n                    GUILayout.EndVertical();\n                }\n            }\n        }\n\n        private void DoBake()\n        {\n            Lightmapping.BakeAsync();\n        }\n\n        private void DoClear()\n        {\n            Lightmapping.ClearLightingDataAsset();\n            Lightmapping.Clear();\n        }\n\n        private void DoBakeReflectionProbes()\n        {\n            Lightmapping.BakeAllReflectionProbesSnapshots();\n        }\n\n        internal static VisualisationGITexture[] GetRealTimeLightmaps()\n        {\n            return LightmapVisualizationUtility.GetRealtimeGITextures(GITextureType.Irradiance);\n        }\n\n        internal static void GatherRealTimeLightmapStats(ref int lightmapCount, ref long totalMemorySize, ref Dictionary<LightmapSize, int> sizes)\n        {\n            var realTimeLightMaps = GetRealTimeLightmaps();\n            foreach (var lmap in realTimeLightMaps)\n            {\n                if (lmap.texture == null)\n                    continue;\n                lightmapCount++;\n\n                LightmapSize ls = new() { width = lmap.texture.width, height = lmap.texture.height};\n                if (sizes.ContainsKey(ls))\n                    sizes[ls]++;\n                else\n                    sizes.Add(ls, 1);\n\n                totalMemorySize += TextureUtil.GetStorageMemorySizeLong(lmap.texture);\n            }\n        }\n\n        internal static void GatherRunningBakeLightmapStats(ref int lightmapCount, ref long totalMemorySize, ref Dictionary<LightmapSize, int> sizes, ref bool shadowmaskMode)\n        {\n            RunningBakeInfo info = Lightmapping.GetRunningBakeInfo();\n            lightmapCount = info.lightmapSizes.Length;\n\n            foreach (var ld in info.lightmapSizes)\n                if (sizes.ContainsKey(ld))\n                    sizes[ld]++;\n                else\n                   sizes.Add(ld, 1);\n\n            shadowmaskMode = false;\n        }\n\n        internal static void GatherBakedLightmapStats(ref int lightmapCount, ref long totalMemorySize, ref Dictionary<LightmapSize, int> sizes, ref bool shadowmaskMode)\n        {\n            foreach (LightmapData ld in LightmapSettings.lightmaps)\n            {\n                if (ld.lightmapColor == null)\n                    continue;\n                lightmapCount++;\n\n                LightmapSize ls = new() { width = ld.lightmapColor.width, height = ld.lightmapColor.height};\n                if (sizes.ContainsKey(ls))\n                    sizes[ls]++;\n                else\n                    sizes.Add(ls, 1);\n\n                totalMemorySize += TextureUtil.GetStorageMemorySizeLong(ld.lightmapColor);\n                if (ld.lightmapDir)\n                    totalMemorySize += TextureUtil.GetStorageMemorySizeLong(ld.lightmapDir);\n\n                if (ld.shadowMask)\n                {\n                    totalMemorySize += TextureUtil.GetStorageMemorySizeLong(ld.shadowMask);\n                    shadowmaskMode = true;\n                }\n            }\n        }\n\n        internal static void GatherProbeStats(ref ulong probeCount, ref long totalMemorySize)\n        {\n            RunningBakeInfo info = Lightmapping.GetRunningBakeInfo();\n            probeCount = info.probePositions;\n\n            totalMemorySize = 0;\n        }\n\n        internal static void DisplaySummaryLine(string outputString, int lightmapCount, long totalMemorySize)\n        {\n            GUILayout.BeginVertical();\n            GUILayout.BeginHorizontal();\n\n            GUILayout.Label(outputString.ToString(), Styles.labelStyle);\n            // Push the memory size stats to the right of the screen for better alignment\n            GUILayout.FlexibleSpace();\n            if (totalMemorySize != 0)\n            {\n                GUILayout.Label(EditorUtility.FormatBytes(totalMemorySize), Styles.labelStyle, GUILayout.MinWidth(70));\n            }\n\n            GUILayout.EndHorizontal();\n            GUILayout.EndVertical();\n        }\n\n        static void FormatSizesString(ref StringBuilder sizesString, Dictionary<LightmapSize, int> sizes)\n        {\n            bool first = true;\n            foreach (KeyValuePair<LightmapSize, int> s in sizes)\n            {\n                sizesString.Append(first ? \": \" : \", \");\n                first = false;\n                sizesString.Append(s.Value.ToString(CultureInfo.InvariantCulture.NumberFormat));\n                sizesString.Append(\"x\");\n                sizesString.Append(\"(\");\n                sizesString.Append(s.Key.width.ToString(CultureInfo.InvariantCulture.NumberFormat));\n                sizesString.Append(\"x\");\n                sizesString.Append(s.Key.height.ToString(CultureInfo.InvariantCulture.NumberFormat));\n                sizesString.Append(\"px\");\n                sizesString.Append(\")\");\n            }\n        }\n\n        internal static void AddPlural(ref StringBuilder s, int n)\n        {\n            if (n > 0)\n                s.Append(\"s\");\n        }\n\n        internal static void Summary()\n        {\n            if (!SelectedDenoisersSupported() && !Lightmapping.isRunning)\n            {\n                using (new EditorGUIUtility.IconSizeScope(Vector2.one * 14))\n                {\n                    GUILayout.BeginVertical();\n                    GUILayout.Label(Styles.unsupportedDenoisersLabel, EditorStyles.wordWrappedMiniLabel);\n                    GUILayout.EndVertical();\n                }\n            }\n            bool outdatedEnvironment = RenderSettings.WasUsingAutoEnvironmentBakingWithNonDefaultSettings();\n            if (outdatedEnvironment && !Lightmapping.isRunning)\n            {\n                using (new EditorGUIUtility.IconSizeScope(Vector2.one * 14))\n                {\n                    GUILayout.BeginVertical();\n                    GUILayout.Label(Styles.invalidEnvironmentLabel, EditorStyles.wordWrappedMiniLabel);\n                    GUILayout.EndVertical();\n                }\n            }\n\n            // Show the number of lightmaps. These are the lightmaps that will be baked or is being baked.\n            {\n                StringBuilder outputString = new();\n\n                string prefix = Lightmapping.isRunning ? \"Generating \" : string.Empty;\n\n                // Gather and show light probe stats (we only have this while baking is running)\n                if (Lightmapping.isRunning)\n                {\n                    ulong probesCount = 0;\n                    long probeMemorySize = 0;\n\n                    GatherProbeStats(ref probesCount, ref probeMemorySize);\n                    if (probesCount > 0)\n                    {\n                        outputString.Append($\"{prefix}{probesCount.ToString(\"N0\")} probe\");\n                        outputString.Append(probesCount > 1 ? \"s\" : string.Empty);\n                        DisplaySummaryLine(outputString.ToString(), 0, 0);\n                        outputString.Clear();\n                    }\n                }\n\n                // Gather and show baked lightmap stats\n                bool shadowmaskMode = false;\n                long bakedTotalMemorySize = 0;\n                int bakedLightmapCount = 0;\n                var bakedLightmapSizes = new Dictionary<LightmapSize, int>();\n\n                if (Lightmapping.isRunning)\n                    GatherRunningBakeLightmapStats(ref bakedLightmapCount, ref bakedTotalMemorySize, ref bakedLightmapSizes, ref shadowmaskMode);\n                else\n                    GatherBakedLightmapStats(ref bakedLightmapCount, ref bakedTotalMemorySize, ref bakedLightmapSizes, ref shadowmaskMode);\n                if (bakedLightmapCount > 0)\n                {\n                    outputString.Append($\"{prefix}{bakedLightmapCount.ToString(\"N0\")} baked lightmap\");\n                    outputString.Append(bakedLightmapCount > 1 ? \"s\" : string.Empty);\n                    outputString.Append(shadowmaskMode ? \" with Shadowmask\" : string.Empty);\n                    outputString.Append(shadowmaskMode && bakedLightmapCount > 1 ? \"s\" : string.Empty);\n                    FormatSizesString(ref outputString, bakedLightmapSizes);\n                    DisplaySummaryLine(outputString.ToString(), bakedLightmapCount, bakedTotalMemorySize);\n                    outputString.Clear();\n                }\n\n                // Gather and show realtime lightmap stats\n                long rtTotalMemorySize = 0;\n                int rtLightmapCount = 0;\n                var rtLightmapSizes = new Dictionary<LightmapSize, int>();\n                GatherRealTimeLightmapStats(ref rtLightmapCount, ref rtTotalMemorySize, ref rtLightmapSizes);\n                if (rtLightmapCount > 0)\n                {\n                    outputString.Append($\"{prefix}{rtLightmapCount.ToString(\"N0\")} realtime lightmap\");\n                    outputString.Append(rtLightmapCount > 1 ? \"s\" : string.Empty);\n                    FormatSizesString(ref outputString, rtLightmapSizes);\n                    DisplaySummaryLine(outputString.ToString(), rtLightmapCount, rtTotalMemorySize);\n                    outputString.Clear();\n                }\n            }\n\n            GUILayout.BeginVertical();\n\n            // We show baking device and performance even when not baking, so the user can see the information after a long bake:\n            {\n                if (Lightmapping.GetLightingSettingsOrDefaultsFallback().lightmapper == LightingSettings.Lightmapper.ProgressiveGPU)\n                {\n                    string deviceName = Lightmapping.GetLightmapBakeGPUDeviceName();\n                    if (deviceName.Length > 0)\n                        GUILayout.Label(\"Baking device: \" + deviceName, Styles.labelStyle);\n                }\n                float mraysPerSec = Lightmapping.GetLightmapBakePerformanceTotal();\n                {\n                    string text;\n                    if (mraysPerSec >= 0.0)\n                        text = @$\"Bake Performance: {mraysPerSec.ToString(\"N2\")} mrays/sec\";\n                    else\n                        text = \"\";\n                    GUILayout.Label(text, Styles.labelStyle);\n                }\n            }\n\n            if (!Lightmapping.isRunning)\n            {\n                float bakeTime = Lightmapping.GetLightmapBakeTimeTotal();\n                if (bakeTime >= 0.0)\n                {\n                    int time = (int)bakeTime;\n                    int timeH = time / 3600;\n                    time -= 3600 * timeH;\n                    int timeM = time / 60;\n                    time -= 60 * timeM;\n                    int timeS = time;\n                    int decimalPart = (int)(bakeTime % 1 * 100);\n\n                    GUILayout.Label($\"Total Bake Time: {timeH:00}:{timeM:00}:{timeS:00}.{decimalPart:00}\", Styles.labelStyle);\n                }\n            }\n            GUILayout.EndVertical();\n        }\n\n        static bool SelectedDenoisersSupported()\n        {\n            // Only show the error if the user is in Advanced mode\n            if (lightingSettings.FindProperty(\"m_PVRFilteringMode\").enumValueIndex != 2)\n                return true;\n\n            bool usingAO = lightingSettings.FindProperty(\"m_AO\").boolValue;\n\n            LightingSettings lsa;\n            return\n                Lightmapping.TryGetLightingSettings(out lsa) &&\n                DenoiserSupported(lsa.denoiserTypeDirect) &&\n                DenoiserSupported(lsa.denoiserTypeIndirect) &&\n                (!usingAO || (usingAO && DenoiserSupported(lsa.denoiserTypeAO)));\n        }\n\n        static bool DenoiserSupported(LightingSettings.DenoiserType denoiserType)\n        {\n            if (denoiserType == LightingSettings.DenoiserType.Optix)\n                return Lightmapping.IsOptixDenoiserSupported();\n            if (denoiserType == LightingSettings.DenoiserType.OpenImage)\n                return Lightmapping.IsOpenImageDenoiserSupported();\n\n            return true;\n        }\n\n        internal static LightingWindow s_Window;\n        private static readonly double s_MraysPerSecRepaintThreshold = 0.01;\n        internal static bool isShown => s_Window && !s_Window.docked;\n\n        [MenuItem(\"Window/Rendering/Lighting %9\", false, 1)]\n        internal static void CreateLightingWindow()\n        {\n            LightingWindow window = EditorWindow.GetWindow<LightingWindow>();\n            window.minSize = new Vector2(390, 390);\n            window.Show();\n            s_Window = window;\n        }\n\n        internal static void DestroyLightingWindow()\n        {\n            s_Window.Close();\n            s_Window = null;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor\n{\n    internal class LightingWindowBakeSettings\n    {\n        bool m_LightingSettingsReadOnlyMode;\n        SerializedObject m_LightingSettings;\n        SharedLightingSettingsEditor m_LightingSettingsEditor;\n\n        SerializedObject lightingSettings\n        {\n            get\n            {\n                // if we set a new scene as the active scene, we need to make sure to respond to those changes\n                if (m_LightingSettings == null || m_LightingSettings.targetObject == null || m_LightingSettings.targetObject != Lightmapping.lightingSettingsInternal)\n                {\n                    var targetObject = Lightmapping.lightingSettingsInternal;\n                    m_LightingSettingsReadOnlyMode = false;\n\n                    if (targetObject == null)\n                    {\n                        targetObject = Lightmapping.lightingSettingsDefaults;\n                        m_LightingSettingsReadOnlyMode = true;\n                    }\n\n                    SerializedObject lso = m_LightingSettings = new SerializedObject(targetObject);\n\n                    if (lso != null)\n                    {\n                        m_LightingSettingsEditor.UpdateSettings(lso);\n                    }\n                }\n\n                return m_LightingSettings;\n            }\n        }\n\n        public void OnEnable()\n        {\n            if (m_LightingSettingsEditor == null)\n                m_LightingSettingsEditor = new SharedLightingSettingsEditor();\n\n            m_LightingSettingsEditor.OnEnable();\n        }\n\n        public void OnDisable()\n        {\n            if (m_LightingSettings != null)\n                m_LightingSettings.Dispose();\n        }\n\n        public void OnGUI()\n        {\n            lightingSettings.Update();\n\n            using (new EditorGUI.DisabledScope(m_LightingSettingsReadOnlyMode))\n            {\n                m_LightingSettingsEditor.OnGUI(false, false);\n            }\n\n            lightingSettings.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneModeWindows/LightingWindowEnvironmentTab.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing Object = UnityEngine.Object;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEditor.Rendering;\n\nnamespace UnityEditor\n{\n    public abstract class LightingWindowEnvironmentSection\n    {\n        public virtual void OnEnable() {}\n        public virtual void OnDisable() {}\n        public virtual void OnInspectorGUI() {}\n    }\n\n    internal class LightingWindowEnvironmentTab : LightingWindow.WindowTab\n    {\n        class Styles\n        {\n            public static readonly GUIContent OtherSettings = EditorGUIUtility.TrTextContent(\"Other Settings\");\n        }\n\n        class DefaultEnvironmentSectionExtension : LightingWindowEnvironmentSection\n        {\n            Editor m_EnvironmentEditor;\n\n            Editor environmentEditor\n            {\n                get\n                {\n                    if (m_EnvironmentEditor == null || m_EnvironmentEditor.target == null)\n                    {\n                        Editor.CreateCachedEditor(RenderSettings.GetRenderSettings(), typeof(LightingEditor), ref m_EnvironmentEditor);\n                    }\n\n                    return m_EnvironmentEditor;\n                }\n            }\n\n            public override void OnInspectorGUI()\n            {\n                environmentEditor.OnInspectorGUI();\n            }\n\n            public override void OnDisable()\n            {\n                if (m_EnvironmentEditor != null)\n                {\n                    Object.DestroyImmediate(m_EnvironmentEditor);\n                    m_EnvironmentEditor = null;\n                }\n            }\n        }\n\n        LightingWindowEnvironmentSection m_EnvironmentSection;\n        Editor          m_FogEditor;\n        Editor          m_OtherRenderingEditor;\n        SavedBool       m_ShowOtherSettings;\n        Object          m_RenderSettings = null;\n        Vector2         m_ScrollPosition = Vector2.zero;\n        Type            m_SRP;\n\n        Object renderSettings\n        {\n            get\n            {\n                if (m_RenderSettings == null || m_RenderSettings != RenderSettings.GetRenderSettings())\n                    m_RenderSettings = RenderSettings.GetRenderSettings();\n\n                return m_RenderSettings;\n            }\n        }\n\n        LightingWindowEnvironmentSection environmentEditor\n        {\n            get\n            {\n                var currentSRP = GraphicsSettings.currentRenderPipelineAssetType;\n                if (m_EnvironmentSection != null && m_SRP != currentSRP)\n                {\n                    m_SRP = currentSRP;\n                    m_EnvironmentSection.OnDisable();\n                    m_EnvironmentSection = null;\n                }\n\n                if (m_EnvironmentSection == null)\n                {\n                    var extensionType = RenderPipelineEditorUtility.GetDerivedTypesSupportedOnCurrentPipeline<LightingWindowEnvironmentSection>().FirstOrDefault() ?? typeof(DefaultEnvironmentSectionExtension);\n                    LightingWindowEnvironmentSection extension = (LightingWindowEnvironmentSection)Activator.CreateInstance(extensionType);\n                    m_EnvironmentSection = extension;\n                    m_EnvironmentSection.OnEnable();\n                }\n\n                return m_EnvironmentSection;\n            }\n        }\n\n        Editor fogEditor\n        {\n            get\n            {\n                if (m_FogEditor == null || m_FogEditor.target == null || m_FogEditor.target != RenderSettings.GetRenderSettings())\n                {\n                    Editor.CreateCachedEditor(renderSettings, typeof(FogEditor), ref m_FogEditor);\n                }\n\n                return m_FogEditor;\n            }\n        }\n\n        Editor otherRenderingEditor\n        {\n            get\n            {\n                if (m_OtherRenderingEditor == null || m_OtherRenderingEditor.target == null || m_OtherRenderingEditor.target != RenderSettings.GetRenderSettings())\n                {\n                    Editor.CreateCachedEditor(renderSettings, typeof(OtherRenderingEditor), ref m_OtherRenderingEditor);\n                }\n\n                return m_OtherRenderingEditor;\n            }\n        }\n\n        public void OnEnable()\n        {\n            m_SRP = GraphicsSettings.currentRenderPipelineAssetType;\n            m_ShowOtherSettings = new SavedBool($\"LightingWindow.ShowOtherSettings\", true);\n        }\n\n        public void OnDisable()\n        {\n            ClearCachedProperties();\n        }\n\n        void ClearCachedProperties()\n        {\n            if (m_EnvironmentSection != null)\n            {\n                m_EnvironmentSection.OnDisable();\n                m_EnvironmentSection = null;\n            }\n            if (m_FogEditor != null)\n            {\n                Object.DestroyImmediate(m_FogEditor);\n                m_FogEditor = null;\n            }\n            if (m_OtherRenderingEditor != null)\n            {\n                Object.DestroyImmediate(m_OtherRenderingEditor);\n                m_OtherRenderingEditor = null;\n            }\n        }\n\n        public void OnGUI()\n        {\n            EditorGUIUtility.hierarchyMode = true;\n\n            m_ScrollPosition = EditorGUILayout.BeginScrollView(m_ScrollPosition);\n\n            if (!SupportedRenderingFeatures.active.overridesEnvironmentLighting)\n                environmentEditor.OnInspectorGUI();\n\n            OtherSettingsGUI();\n\n            EditorGUILayout.EndScrollView();\n        }\n\n        public void OnSummaryGUI()\n        {\n            LightingWindow.Summary();\n        }\n\n        public void OnSelectionChange()\n        {\n        }\n\n        void OtherSettingsGUI()\n        {\n            if (SupportedRenderingFeatures.active.overridesFog && SupportedRenderingFeatures.active.overridesOtherLightingSettings)\n                return;\n\n            m_ShowOtherSettings.value = EditorGUILayout.FoldoutTitlebar(m_ShowOtherSettings.value, Styles.OtherSettings, true);\n\n            if (m_ShowOtherSettings.value)\n            {\n                EditorGUI.indentLevel++;\n\n                if (!SupportedRenderingFeatures.active.overridesFog)\n                    fogEditor.OnInspectorGUI();\n\n                if (!SupportedRenderingFeatures.active.overridesOtherLightingSettings)\n                    otherRenderingEditor.OnInspectorGUI();\n\n                EditorGUI.indentLevel--;\n                EditorGUILayout.Space();\n            }\n        }\n\n        public bool HasHelpGUI()\n        {\n            return true;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/SceneModeWindows/LightingWindowLightingTab.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngineInternal;\nusing Object = UnityEngine.Object;\nusing UnityEngine.Rendering;\nusing UnityEditor.Rendering;\nusing System.Globalization;\n\nnamespace UnityEditor\n{\n    internal class LightingWindowLightingTab : LightingWindow.WindowTab\n    {\n        class Styles\n        {\n            public static readonly GUIContent newLightingSettings = EditorGUIUtility.TrTextContent(\"New\", \"Create a new Lighting Settings Asset with default settings.\");\n            public static readonly GUIContent cloneLightingSettings = EditorGUIUtility.TrTextContent(\"Clone\", \"Create a new Lighting Settings Asset based on the current settings.\");\n            public static readonly GUIContent lightingSettings = EditorGUIUtility.TrTextContent(\"Lighting Settings\");\n        }\n\n        SavedBool m_ShowLightingSettings;\n        Vector2 m_ScrollPosition = Vector2.zero;\n        LightingWindowBakeSettings m_BakeSettings;\n\n        SerializedObject m_LightmapSettings;\n        SerializedProperty m_LightingSettingsAsset;\n\n        SerializedObject lightmapSettings\n        {\n            get\n            {\n                // if we set a new scene as the active scene, we need to make sure to respond to those changes\n                if (m_LightmapSettings == null || m_LightmapSettings.targetObject != LightmapEditorSettings.GetLightmapSettings())\n                {\n                    m_LightmapSettings = new SerializedObject(LightmapEditorSettings.GetLightmapSettings());\n                    m_LightingSettingsAsset = m_LightmapSettings.FindProperty(\"m_LightingSettings\");\n                }\n\n                return m_LightmapSettings;\n            }\n        }\n\n        public void OnEnable()\n        {\n            m_BakeSettings = new LightingWindowBakeSettings();\n            m_BakeSettings.OnEnable();\n\n            m_ShowLightingSettings = new SavedBool(\"LightingWindow.ShowLightingSettings\", true);\n        }\n\n        public void OnDisable()\n        {\n            m_BakeSettings.OnDisable();\n        }\n\n        public void OnGUI()\n        {\n            EditorGUIUtility.hierarchyMode = true;\n\n            lightmapSettings.Update();\n\n            m_ScrollPosition = EditorGUILayout.BeginScrollView(m_ScrollPosition);\n\n            LightingSettingsGUI();\n\n            m_BakeSettings.OnGUI();\n\n            EditorGUILayout.EndScrollView();\n\n            lightmapSettings.ApplyModifiedProperties();\n        }\n\n        public void OnSummaryGUI()\n        {\n            LightingWindow.Summary();\n        }\n\n        public void OnSelectionChange()\n        {\n        }\n\n        private void CreateLightingSettings(LightingSettings from = null)\n        {\n            LightingSettings ls;\n            if (from == null)\n            {\n                ls = new LightingSettings();\n                ls.name = \"New Lighting Settings\";\n            }\n            else\n            {\n                ls = Object.Instantiate(from);\n                ls.name = string.IsNullOrEmpty(from.name) ? \"New Lighting Settings\" : from.name;\n            }\n            Undo.RecordObject(m_LightmapSettings.targetObject, \"New Lighting Settings\");\n            Lightmapping.lightingSettingsInternal = ls;\n            ProjectWindowUtil.CreateAsset(ls, (ls.name + \".lighting\"));\n        }\n\n        void LightingSettingsGUI()\n        {\n            m_ShowLightingSettings.value = EditorGUILayout.FoldoutTitlebar(m_ShowLightingSettings.value, Styles.lightingSettings, true);\n\n            if (m_ShowLightingSettings.value)\n            {\n                ++EditorGUI.indentLevel;\n\n                GUILayout.BeginHorizontal();\n                EditorGUILayout.PropertyField(m_LightingSettingsAsset, GUIContent.Temp(\"Lighting Settings Asset\"));\n\n                if (GUILayout.Button(Styles.newLightingSettings, EditorStyles.miniButtonLeft, GUILayout.Width(50)))\n                    CreateLightingSettings();\n                else if (GUILayout.Button(Styles.cloneLightingSettings, EditorStyles.miniButtonRight, GUILayout.Width(50)))\n                    CreateLightingSettings(Lightmapping.GetLightingSettingsOrDefaultsFallback());\n\n                GUILayout.EndHorizontal();\n                EditorGUILayout.Space();\n\n                --EditorGUI.indentLevel;\n            }\n        }\n\n        public bool HasHelpGUI()\n        {\n            return true;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Collections;\nusing System.Linq;\nusing UnityEditor.AnimatedValues;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngineInternal;\nusing Object = UnityEngine.Object;\nusing System.Globalization;\n\nnamespace UnityEditor\n{\n    internal class LightingWindowLightmapPreviewTab : LightingWindow.WindowTab\n    {\n        LightmapType m_LightmapType         = LightmapType.NoLightmap;\n        Vector2 m_ScrollPosition            = Vector2.zero;\n        bool m_ShouldScrollToLightmapIndex  = false;\n\n        int m_ActiveGameObjectLightmapIndex     = -1; // the object the user selects in the scene\n        int m_SelectedLightmapIndex             = 0;\n\n        SavedBool m_ShowBakedLightmaps = new SavedBool(\"LightingWindow.ShowBakedLightmaps\", true);\n        SavedBool m_ShowPreviewLightmaps = new SavedBool(\"LightingWindow.ShowPreviewLightmaps\", true);\n\n        // realtime lightmaps\n        Hash128 m_ActiveGameObjectTextureHash   = new Hash128(); // the object the user selects in the scene\n\n        SerializedObject m_LightmapSettings;\n\n        static class Styles\n        {\n            public static readonly GUIStyle SelectedLightmapHighlight = \"LightmapEditorSelectedHighlight\";\n            public static readonly GUIContent LightingDataAsset = EditorGUIUtility.TrTextContent(\"Lighting Data Asset\", \"A different LightingData.asset can be assigned here. These assets are generated by baking a scene in the OnDemand mode.\");\n            public static readonly GUIContent OpenPreview = EditorGUIUtility.TrTextContent(\"View\");\n\n            public static readonly GUIStyle OpenPreviewStyle = EditorStyles.objectFieldThumb.name + \"LightmapPreviewOverlay\";\n\n            public static readonly GUIContent BakedLightmapsFoldoutTitle = EditorGUIUtility.TrTextContent(\"Baked Lightmaps\");\n            public static readonly GUIContent PreviewLightmapsFoldoutTitle = EditorGUIUtility.TrTextContent(\"Preview Lightmaps\");\n        }\n\n        public LightingWindowLightmapPreviewTab(LightmapType type)\n        {\n            m_LightmapType = type;\n        }\n\n        private bool isRealtimeLightmap\n        {\n            get\n            {\n                return m_LightmapType == LightmapType.DynamicLightmap;\n            }\n        }\n\n        private bool showDebugInfo\n        {\n            get\n            {\n                return !isRealtimeLightmap && Unsupported.IsDeveloperMode();\n            }\n        }\n\n        public void OnSelectionChange()\n        {\n            MeshRenderer renderer;\n            Terrain terrain = null;\n\n            // if the active object in the selection is a renderer or a terrain, we're interested in it's lightmapIndex\n            if (Selection.activeGameObject == null ||\n                ((renderer = Selection.activeGameObject.GetComponent<MeshRenderer>()) == null &&\n                 (terrain = Selection.activeGameObject.GetComponent<Terrain>()) == null))\n            {\n                m_ActiveGameObjectLightmapIndex = -1;\n                m_ActiveGameObjectTextureHash = new Hash128();\n                return;\n            }\n            if (isRealtimeLightmap)\n            {\n                Hash128 inputSystemHash;\n                if ((renderer != null && Lightmapping.GetInputSystemHash(renderer.GetInstanceID(), out inputSystemHash))\n                    || (terrain != null && Lightmapping.GetInputSystemHash(terrain.GetInstanceID(), out inputSystemHash)))\n                {\n                    m_ActiveGameObjectTextureHash = inputSystemHash;\n                }\n                else\n                    m_ActiveGameObjectTextureHash = new Hash128();\n            }\n            else\n                m_ActiveGameObjectLightmapIndex = renderer != null ? renderer.lightmapIndex : terrain.lightmapIndex;\n\n            m_ShouldScrollToLightmapIndex = true;\n        }\n\n        public void OnEnable()\n        {\n            InitSettings();\n        }\n\n        public void OnDisable()\n        {\n        }\n\n        public void OnGUI()\n        {\n            InitSettings();\n\n            m_LightmapSettings.Update();\n\n            m_ScrollPosition = GUILayout.BeginScrollView(m_ScrollPosition);\n\n            if (!isRealtimeLightmap)\n            {\n                EditorGUI.BeginChangeCheck();\n                var lda = (LightingDataAsset)EditorGUILayout.ObjectField(Styles.LightingDataAsset, Lightmapping.lightingDataAsset, typeof(LightingDataAsset), true);\n                if (EditorGUI.EndChangeCheck())\n                    Lightmapping.lightingDataAsset = lda;\n                GUILayout.Space(10);\n            }\n            else\n            {\n                GUILayout.Space(30);\n            }\n\n            DebugInfoSection();\n\n            if (isRealtimeLightmap)\n            {\n                VisualisationGITexture[] realtimeLightmaps = LightmapVisualizationUtility.GetRealtimeGITextures(GITextureType.Irradiance);\n                LightmapListGUI(realtimeLightmaps, lm => lm.texture, lm => lm.hash, false, false);\n            }\n            else\n            {\n                var interactiveLightmaps = InteractiveLightBaking.GetLightmapData();\n                if (interactiveLightmaps.numLightmaps > 0 && Lightmapping.shouldBakeInteractively) // Hide preview lightmaps when not in preview mode\n                {\n                    m_ShowPreviewLightmaps.value = EditorGUILayout.Foldout(m_ShowPreviewLightmaps.value, Styles.PreviewLightmapsFoldoutTitle);\n\n                    if (m_ShowPreviewLightmaps)\n                    {\n                        LightmapListGUI(interactiveLightmaps.lightmaps, lm => lm, lm => new Hash128(), true, true);\n                    }\n                }\n\n                LightmapData[] lightmaps = LightmapSettings.lightmaps;\n                if (lightmaps.Length > 0)\n                {\n                    m_ShowBakedLightmaps.value = EditorGUILayout.Foldout(m_ShowBakedLightmaps.value, Styles.BakedLightmapsFoldoutTitle);\n\n                    if (m_ShowBakedLightmaps)\n                    {\n                        LightmapListGUI(lightmaps, lm => lm.lightmapColor, lm => new Hash128(), false, true);\n                    }\n                }\n            }\n\n            GUILayout.EndScrollView();\n        }\n\n        public void OnSummaryGUI()\n        {\n            LightingWindow.Summary();\n        }\n\n        public bool HasHelpGUI()\n        {\n            return false;\n        }\n\n        private void InitSettings()\n        {\n            if (m_LightmapSettings == null || m_LightmapSettings.targetObject == null || m_LightmapSettings.targetObject != LightmapEditorSettings.GetLightmapSettings())\n            {\n                m_LightmapSettings = new SerializedObject(LightmapEditorSettings.GetLightmapSettings());\n            }\n        }\n\n        private void LightmapListGUI<T>(T[] lightmaps, Func<T, Texture2D> getTexture, Func<T, Hash128> getHash, bool useInteractiveLightBakingData, bool showCompressionDetails)\n        {\n            int length = lightmaps.Length;\n\n            if (m_SelectedLightmapIndex >= length)\n                m_SelectedLightmapIndex = 0;\n\n            for (int i = 0; i < length; i++)\n            {\n                Texture2D texture = getTexture(lightmaps[i]);\n\n                if (texture != null)\n                {\n                    GUILayout.BeginHorizontal();\n                    GUILayout.Space(10);\n\n                    Hash128 hash = getHash(lightmaps[i]);\n\n                    LightmapField(texture, i, hash, useInteractiveLightBakingData);\n\n                    GUILayout.Space(5);\n                    GUILayout.BeginVertical();\n                    GUILayout.Label(\"Index: \" + i, EditorStyles.miniBoldLabel);\n                    GUILayout.Label(\"Size: \" + texture.width + \"x\" + texture.height, EditorStyles.miniBoldLabel);\n\n                    if (showCompressionDetails)\n                    {\n                        GUILayout.Label(\"Format: \" + texture.format + (Lightmapping.GetLightingSettingsOrDefaultsFallback().lightmapCompression == LightmapCompression.None ? \" (uncompressed)\" : \" (compressed)\"), EditorStyles.miniBoldLabel);\n                    }\n                    else\n                    {\n                        GUILayout.Label(\"Format: \" + texture.format, EditorStyles.miniBoldLabel);\n                    }\n\n                    GUILayout.EndVertical();\n                    GUILayout.FlexibleSpace();\n                    GUILayout.EndHorizontal();\n                    GUILayout.Space(5);\n                }\n            }\n        }\n\n        private void LightmapField(Texture2D lightmap, int index, Hash128 hash, bool useInteractiveLightBakingData)\n        {\n            Rect rect = GUILayoutUtility.GetRect(100, 100, EditorStyles.objectField);\n            Rect buttonRect = new Rect(rect.xMax - 35, rect.yMax - 14, 35, 14);\n\n            if (EditorGUI.Toggle(rect, index == m_SelectedLightmapIndex, EditorStyles.objectFieldThumb))\n            {\n                m_SelectedLightmapIndex = index;\n\n                if ((buttonRect.Contains(Event.current.mousePosition) && Event.current.clickCount == 1) ||\n                    (rect.Contains(Event.current.mousePosition) && Event.current.clickCount == 2))\n                {\n                    if (isRealtimeLightmap)\n                        LightmapPreviewWindow.CreateLightmapPreviewWindow(m_SelectedLightmapIndex, true, true, useInteractiveLightBakingData);\n                    else\n                        LightmapPreviewWindow.CreateLightmapPreviewWindow(m_SelectedLightmapIndex, false, true, useInteractiveLightBakingData);\n                }\n                else if (rect.Contains(Event.current.mousePosition) && Event.current.clickCount == 1)\n                {\n                    Object actualTargetObject = lightmap;\n                    Component com = actualTargetObject as Component;\n                    if (com)\n                        actualTargetObject = com.gameObject;\n                    EditorGUI.PingObjectOrShowPreviewOnClick(actualTargetObject, GUILayoutUtility.GetLastRect());\n                }\n            }\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                rect = EditorStyles.objectFieldThumb.padding.Remove(rect);\n                EditorGUI.DrawPreviewTexture(rect, lightmap);\n\n                Styles.OpenPreviewStyle.Draw(rect, Styles.OpenPreview, false, false, false, false);\n\n                if ((!isRealtimeLightmap && index == m_ActiveGameObjectLightmapIndex) || (isRealtimeLightmap && hash == m_ActiveGameObjectTextureHash))\n                {\n                    Styles.SelectedLightmapHighlight.Draw(rect, false, false, false, false);\n\n                    if (m_ShouldScrollToLightmapIndex)\n                    {\n                        GUI.ScrollTo(rect);\n\n                        m_ShouldScrollToLightmapIndex = false;\n                        GUIView.current.Repaint();\n                    }\n                }\n            }\n        }\n\n        //***** DEBUG DATA *****//\n\n        const string kEditorPrefsTransmissionTextures = \"LightingWindowGlobalMapsTT\";\n        const string kEditorPrefsGeometryData = \"LightingWindowGlobalMapsGD\";\n        const string kEditorPrefsInFlight = \"LightingWindowGlobalMapsIF\";\n        const string kEditorPrefsMaterialTextures = \"LightingWindowGlobalMapsMT\";\n        const string kEditorPrefsLightProbes = \"LightingWindowGlobalLightProbes\";\n\n        private static string SizeString(float size)\n        {\n            if (size < 0)\n                return \"unknown\";\n            float val = size;\n            string[] scale = new string[] { \"TB\", \"GB\", \"MB\", \"KB\", \"Bytes\" };\n            int idx = scale.Length - 1;\n            while (val > 1000.0f && idx >= 0)\n            {\n                val /= 1000f;\n                idx--;\n            }\n\n            if (idx < 0)\n                return \"<error>\";\n\n            return string.Format(\"{0:0.##} {1}\", val, scale[idx]);\n        }\n\n        private void DebugInfoSection()\n        {\n            if (!showDebugInfo)\n                return;\n\n            float oldWidth = EditorGUIUtility.labelWidth;\n            EditorGUIUtility.labelWidth = 400.0f;\n\n            {\n                float gpuMemory = Lightmapping.ComputeTotalGPUMemoryUsageInBytes();\n                if (gpuMemory > 0.0f)\n                {\n                    string foldoutGPUMemoryGPU = String.Format(\"Total GPU memory ({0})\", SizeString(gpuMemory));\n                    EditorGUILayout.FoldoutTitlebar(false, new GUIContent(foldoutGPUMemoryGPU), true);\n                    if (GUILayout.Button(\"Dump detail to Editor.log\", EditorStyles.miniButton, GUILayout.ExpandWidth(false)))\n                    {\n                        Lightmapping.LogGPUMemoryStatistics();\n                    }\n                }\n            }\n\n            EditorGUILayout.Space();\n            EditorGUIUtility.labelWidth = oldWidth;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/SceneModeWindows/LightingWindowTab.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing Object = UnityEngine.Object;\nusing UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEditor.Rendering;\n\nnamespace UnityEditor\n{\n    public abstract class LightingWindowTab : LightingWindow.WindowTab\n    {\n        internal LightingWindow m_Parent;\n        GUIContent m_TitleContent;\n        int m_Priority = -1;\n\n        public GUIContent titleContent\n        {\n            get => m_TitleContent ?? (m_TitleContent = new GUIContent());\n            set {\n                m_TitleContent = value;\n                if (m_Parent != null)\n                    m_Parent.SetToolbarDirty();\n            }\n        }\n\n        public int priority\n        {\n            get => m_Priority;\n            set {\n                m_Priority = value;\n                if (m_Parent != null)\n                    m_Parent.SetToolbarDirty();\n            }\n        }\n\n        public virtual void OnEnable() { }\n        public virtual void OnDisable() { }\n        public virtual void OnGUI() { }\n        public virtual void OnHeaderSettingsGUI() { }\n        public virtual void OnBakeButtonGUI() { }\n        public virtual void OnSelectionChange() { }\n        public virtual bool HasHelpGUI() { return false; }\n\n        public virtual void OnSummaryGUI()\n        {\n            LightingWindow.Summary();\n        }\n\n        public void FocusTab()\n        {\n            LightingWindow.FocusTab(this);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneModeWindows/LightmapPreviewWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Collections;\nusing System.Linq;\nusing UnityEditor.AnimatedValues;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngineInternal;\n\nnamespace UnityEditor\n{\n    [EditorWindowTitle(title = \"Viewer\", icon = \"Lighting\")]\n    internal class LightmapPreviewWindow : EditorWindow\n    {\n        // UI selections etc\n        [SerializeField]\n        ZoomableArea m_ZoomablePreview = null;\n        [SerializeField]\n        bool m_ShowUVOverlay = true;\n        [SerializeField]\n        int m_SelectedPreviewTextureOptionIndex = 0;\n        [SerializeField]\n        float m_ExposureSliderValue = 0.0f;\n\n        float m_ExposureSliderMax = 16f; // this value can be altered by the user\n\n        // Lightmap specifiers\n        [SerializeField]\n        int m_LightmapIndex = -1;\n        [SerializeField]\n        int m_InstanceID = -1;\n        [SerializeField]\n        bool m_IsRealtimeLightmap = false;\n\n        Hash128 m_RealtimeTextureHash = new Hash128();\n        VisualisationGITexture m_CachedTexture;\n        GameObject[] m_CachedTextureObjects;\n\n        int m_ActiveGameObjectLightmapIndex = -1; // the object the user selects in the scene\n        int m_ActiveGameObjectInstanceId = -1; // for instance based non-atlas textures such as baked emissive for Progressive\n        Hash128 m_ActiveGameObjectTextureHash = new Hash128(); // the object the user selects in the scene\n\n        GITextureType[] kRealtimePreviewTextureTypes =\n        {\n            GITextureType.Irradiance,\n            GITextureType.Directionality,\n            GITextureType.Albedo,\n            GITextureType.Emissive,\n            GITextureType.Charting\n        };\n\n        GITextureType[] kInstanceBasedBakedPreviewTextureTypes =\n        {\n            GITextureType.Baked,\n            GITextureType.BakedDirectional,\n            GITextureType.BakedShadowMask,\n            GITextureType.BakedAlbedo,\n            GITextureType.BakedEmissive,\n            GITextureType.BakedCharting,\n            GITextureType.BakedTexelValidity,\n            GITextureType.BakedUVOverlap,\n            GITextureType.BakedLightmapCulling\n        };\n\n        GITextureType[] kIndexBasedBakedPreviewTextureTypes =\n        {\n            GITextureType.Baked,\n            GITextureType.BakedDirectional,\n            GITextureType.BakedShadowMask,\n            GITextureType.BakedCharting,\n            GITextureType.BakedTexelValidity,\n            GITextureType.BakedUVOverlap,\n            GITextureType.BakedLightmapCulling\n        };\n\n        static class Styles\n        {\n            public static readonly GUIContent[] RealtimePreviewTextureOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Realtime Indirect\"),\n                EditorGUIUtility.TrTextContent(\"Realtime Directionality\"),\n                EditorGUIUtility.TrTextContent(\"Realtime Albedo\"),\n                EditorGUIUtility.TrTextContent(\"Realtime Emissive\"),\n                EditorGUIUtility.TrTextContent(\"UV Charts\")\n            };\n\n            public static readonly GUIContent[] InstanceBasedBakedPreviewTextureOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Baked Lightmap\"),\n                EditorGUIUtility.TrTextContent(\"Baked Directionality\"),\n                EditorGUIUtility.TrTextContent(\"Baked Shadowmask\"),\n                EditorGUIUtility.TrTextContent(\"Baked Albedo\"),\n                EditorGUIUtility.TrTextContent(\"Baked Emissive\"),\n                EditorGUIUtility.TrTextContent(\"Baked UV Charts\"),\n                EditorGUIUtility.TrTextContent(\"Baked Texel Validity\"),\n                EditorGUIUtility.TrTextContent(\"Baked UV Overlap\"),\n            };\n\n            public static readonly GUIContent[] IndexBasedBakedPreviewTextureOptions =\n            {\n                EditorGUIUtility.TrTextContent(\"Baked Lightmap\"),\n                EditorGUIUtility.TrTextContent(\"Baked Directionality\"),\n                EditorGUIUtility.TrTextContent(\"Baked Shadowmask\"),\n                EditorGUIUtility.TrTextContent(\"Baked UV Charts\"),\n                EditorGUIUtility.TrTextContent(\"Baked Texel Validity\"),\n                EditorGUIUtility.TrTextContent(\"Baked UV Overlap\"),\n            };\n\n            public static readonly GUIStyle PreviewLabel = new GUIStyle(EditorStyles.whiteLabel);\n\n            public static readonly GUIContent TextureNotAvailableRealtime = EditorGUIUtility.TrTextContent(\"The texture is not available at the moment.\");\n            public static readonly GUIContent TextureNotAvailableBaked = EditorGUIUtility.TrTextContent(\"The texture is not available at the moment.\\nPlease try to rebake the current scene, and make sure that this object is set to 'Contribute Global Illumination' if it's meant to be baked.\");\n            public static readonly GUIContent TextureNotAvailableBakedShadowmask = EditorGUIUtility.TrTextContent(\"The texture is not available at the moment.\\nPlease make sure that Mixed Lights affect this GameObject and that it is set to 'Contribute Global Illumination'.\");\n            public static readonly GUIContent TextureLoading = EditorGUIUtility.TrTextContent(\"Loading...\");\n            public static readonly GUIContent UVOverlayIcon = EditorGUIUtility.TrIconContent(\"ToggleUVOverlay\", \"Toggles the UV Overlay for all the objects in the lightmap. The currently selected object will be highlighted. \");\n        }\n\n        public int lightmapIndex\n        {\n            set { m_LightmapIndex = value; }\n        }\n\n        public int instanceID\n        {\n            set { m_InstanceID = value; }\n        }\n\n        public bool isRealtimeLightmap\n        {\n            get { return m_IsRealtimeLightmap; }\n            set { m_IsRealtimeLightmap = value; }\n        }\n\n        // this seperates between lightsmaps that we opened from a specific index, or the ones that are connected to an object (where the index can change)\n        private bool isIndexBased\n        {\n            get { return m_InstanceID == -1; }\n        }\n\n        private GITextureType[] currentPreviewTextureTypes\n        {\n            get\n            {\n                if (isRealtimeLightmap)\n                    return kRealtimePreviewTextureTypes;\n                else if (isIndexBased)\n                    return kIndexBasedBakedPreviewTextureTypes;\n                else\n                    return kInstanceBasedBakedPreviewTextureTypes;\n            }\n        }\n\n        private GUIContent[] currentPreviewTextureOptions\n        {\n            get\n            {\n                if (isRealtimeLightmap)\n                    return Styles.RealtimePreviewTextureOptions;\n                else if (isIndexBased)\n                    return Styles.IndexBasedBakedPreviewTextureOptions;\n                else\n                    return Styles.InstanceBasedBakedPreviewTextureOptions;\n            }\n        }\n\n        public bool useInteractiveLightBakingData { get; set; }\n\n        private string lightmapTitle\n        {\n            get\n            {\n                string prefix = \"\";\n                if (isRealtimeLightmap)\n                    prefix = \"Realtime \";\n                else if (useInteractiveLightBakingData)\n                    prefix = \"Preview \";\n\n                if (isIndexBased) return $\"{prefix}Lightmap Index {m_LightmapIndex}\";\n\n                var obj = EditorUtility.InstanceIDToObject(m_InstanceID);\n\n                if (obj)\n                    return $\"{prefix}Lightmap for '{obj.name}'\";\n\n                return $\"{prefix}Lightmap\";\n            }\n        }\n\n        private float exposure\n        {\n            get { return SelectedTextureTypeNeedsExposureControl() ? m_ExposureSliderValue : 0.0f; }\n        }\n\n        public static void CreateLightmapPreviewWindow(int lightmapId, bool realtimeLightmap, bool indexBased, bool useInteractiveLightBakingData)\n        {\n            LightmapPreviewWindow window = EditorWindow.CreateInstance<LightmapPreviewWindow>();\n            window.minSize = new Vector2(360, 390);\n            window.isRealtimeLightmap = realtimeLightmap;\n\n            if (indexBased)\n                window.lightmapIndex = lightmapId;\n            else\n                window.instanceID = lightmapId;\n\n            window.useInteractiveLightBakingData = useInteractiveLightBakingData;\n\n            window.Show();\n        }\n\n        void OnEnable()\n        {\n            titleContent = GetLocalizedTitleContent();\n            Lightmapping.lightingDataUpdated += Repaint;\n        }\n\n        void OnDisable()\n        {\n            Lightmapping.lightingDataUpdated -= Repaint;\n        }\n\n        void OnBecameVisible()\n        {\n            UpdateActiveGameObjectSelection();\n            Repaint();\n        }\n\n        void OnSelectionChange()\n        {\n            UpdateActiveGameObjectSelection();\n            Repaint();\n        }\n\n        void OnGUI()\n        {\n            EditorGUILayout.BeginHorizontal(GUIContent.none, EditorStyles.toolbar, GUILayout.Height(EditorGUI.kWindowToolbarHeight));\n\n            GUILayout.Label(lightmapTitle, \"BoldLabel\");\n            GUILayout.FlexibleSpace();\n\n            DrawPreviewSettings();\n\n            EditorGUILayout.EndHorizontal();\n\n            EditorGUILayout.BeginVertical();\n            {\n                var previewRect = new Rect(0, EditorGUI.kWindowToolbarHeight, position.width, position.height);\n\n                GUI.BeginGroup(previewRect);\n                DrawPreview(new Rect(0, -1, position.width, position.height - EditorGUI.kWindowToolbarHeight - 1));\n                GUI.EndGroup();\n            }\n\n            EditorGUILayout.EndVertical();\n        }\n\n        private void DrawPreviewSettings()\n        {\n            using (new EditorGUI.DisabledScope(!SelectedTextureTypeNeedsExposureControl()))\n            {\n                m_ExposureSliderValue = EditorGUIInternal.ExposureSlider(m_ExposureSliderValue, ref m_ExposureSliderMax, EditorStyles.toolbarSlider);\n            }\n\n            m_ShowUVOverlay = GUILayout.Toggle(m_ShowUVOverlay, Styles.UVOverlayIcon, EditorStyles.toolbarButton);\n\n            Rect dropRect = GUILayoutUtility.GetRect(14, 160, EditorGUI.kWindowToolbarHeight, EditorGUI.kWindowToolbarHeight);\n            GUIContent[] options = currentPreviewTextureOptions;\n            GITextureType[] types = currentPreviewTextureTypes;\n\n            if ((m_SelectedPreviewTextureOptionIndex < 0 || m_SelectedPreviewTextureOptionIndex >= options.Length) || !LightmapVisualizationUtility.IsTextureTypeEnabled(types[m_SelectedPreviewTextureOptionIndex]))\n            {\n                m_SelectedPreviewTextureOptionIndex = 0;\n            }\n\n            if (EditorGUI.DropdownButton(dropRect, options[m_SelectedPreviewTextureOptionIndex], FocusType.Passive, EditorStyles.toolbarDropDownRight))\n            {\n                GenericMenu menu = new GenericMenu();\n\n                for (int i = 0; i < options.Length; i++)\n                {\n                    if (LightmapVisualizationUtility.IsTextureTypeEnabled(types[i]))\n                        menu.AddItem(options[i], m_SelectedPreviewTextureOptionIndex == i, SelectPreviewTextureIndex, options.ElementAt(i));\n                    else\n                        menu.AddDisabledItem(options.ElementAt(i));\n                }\n                menu.DropDown(dropRect);\n            }\n        }\n\n        private static Rect ComputeMeshUVBounds(Mesh mesh)\n        {\n            var vertices = mesh.uv2;\n            if (vertices == null || vertices.Length == 0)\n                vertices = mesh.uv;\n            Vector2 minVert = Vector3.positiveInfinity, maxVert = Vector3.negativeInfinity;\n            foreach (Vector3 vertex in vertices)\n            {\n                if (vertex.x < minVert.x)\n                    minVert.x = vertex.x;\n                if (vertex.y < minVert.y)\n                    minVert.y = vertex.y;\n                if (vertex.x > maxVert.x)\n                    maxVert.x = vertex.x;\n                if (vertex.y > maxVert.y)\n                    maxVert.y = vertex.y;\n            }\n            Rect uvBounds = new Rect(minVert, maxVert - minVert);\n            return uvBounds;\n        }\n\n        private static void HandleUVChartClick(Rect textureRect, GameObject[] renderers)\n        {\n            Vector2 uv = (Event.current.mousePosition - textureRect.position) / textureRect.size;\n            uv.y = 1.0f - uv.y; // Texture coord Y is opposite of UI coord Y.\n\n            GameObject smallestSelectedRenderer = null;\n            float smallestSelectedRendererSize = float.MaxValue;\n\n            foreach (GameObject cachedTextureObject in renderers)\n            {\n                // Each renderer could be either a MeshRenderer or a Terrain. Get the lightmap ST regardless.\n                MeshRenderer meshRenderer = cachedTextureObject.GetComponent<MeshRenderer>();\n                Vector4 lightmapScaleOffset;\n                if (meshRenderer != null)\n                {\n                    lightmapScaleOffset = meshRenderer.lightmapScaleOffset;\n                }\n                else\n                {\n                    Terrain terrain = cachedTextureObject.GetComponent<Terrain>();\n                    if (terrain == null)\n                        continue;\n                    lightmapScaleOffset = terrain.lightmapScaleOffset;\n                }\n\n                // Check if we are in stamp/ST rectangle, which may include padding around the UV layout.\n                Rect stampRectangle = new Rect(lightmapScaleOffset.z, lightmapScaleOffset.w, lightmapScaleOffset.x, lightmapScaleOffset.y);\n                if (stampRectangle.Contains(uv))\n                {\n                    // Scale the stamp rectangle to the pixel rectangle, which tightly bounds the UV layout. (Terrains never have padding)\n                    Rect pixelRectangle = stampRectangle;\n                    if (meshRenderer != null)\n                    {\n                        Rect uvBounds = ComputeMeshUVBounds(meshRenderer.GetComponent<MeshFilter>().sharedMesh);\n                        pixelRectangle.x += uvBounds.x * pixelRectangle.width;\n                        pixelRectangle.y += uvBounds.y * pixelRectangle.height;\n                        pixelRectangle.width *= uvBounds.width;\n                        pixelRectangle.height *= uvBounds.height;\n                    }\n\n                    // If we are inside the pixel rectangle, keep track of the smallest chart with this criteria.\n                    // We don't immediately select the first hit, in order to support overlapping/hole-filling lightmap layouts.\n                    if (pixelRectangle.Contains(uv))\n                    {\n                        float chartSize = pixelRectangle.width * pixelRectangle.height;\n                        if (chartSize < smallestSelectedRendererSize)\n                        {\n                            smallestSelectedRendererSize = chartSize;\n                            smallestSelectedRenderer = cachedTextureObject;\n                        }\n                    }\n                }\n            }\n\n            if (smallestSelectedRenderer != null)\n            {\n                Selection.activeGameObject = smallestSelectedRenderer;\n                EditorGUIUtility.PingObject(smallestSelectedRenderer);\n            }\n        }\n\n        private void DrawPreview(Rect r)\n        {\n            if (r.height <= 0)\n                return;\n\n            if (m_ZoomablePreview == null)\n            {\n                m_ZoomablePreview = new ZoomableArea(true);\n\n                m_ZoomablePreview.hRangeMin = 0.0f;\n                m_ZoomablePreview.vRangeMin = 0.0f;\n\n                m_ZoomablePreview.hRangeMax = 1.0f;\n                m_ZoomablePreview.vRangeMax = 1.0f;\n\n                m_ZoomablePreview.SetShownHRange(0, 1);\n                m_ZoomablePreview.SetShownVRange(0, 1);\n\n                m_ZoomablePreview.uniformScale = true;\n                m_ZoomablePreview.scaleWithWindow = true;\n            }\n\n            m_ZoomablePreview.rect = r;\n\n            m_ZoomablePreview.BeginViewGUI();\n\n            m_ZoomablePreview.hSlider = m_ZoomablePreview.shownArea.width < 1;\n            m_ZoomablePreview.vSlider = m_ZoomablePreview.shownArea.height < 1;\n\n            Rect drawableArea = m_ZoomablePreview.drawRect;\n            GITextureType textureType = GetSelectedTextureType();\n\n            UpdateCachedTexture(textureType);\n\n            if (m_CachedTexture.textureAvailability == GITextureAvailability.GITextureNotAvailable || m_CachedTexture.textureAvailability == GITextureAvailability.GITextureUnknown)\n            {\n                if (!isRealtimeLightmap)\n                {\n                    if (textureType == GITextureType.BakedShadowMask)\n                        GUI.Label(drawableArea, Styles.TextureNotAvailableBakedShadowmask, Styles.PreviewLabel);\n                    else\n                        GUI.Label(drawableArea, Styles.TextureNotAvailableBaked, Styles.PreviewLabel);\n                }\n                else\n                    GUI.Label(drawableArea, Styles.TextureNotAvailableRealtime, Styles.PreviewLabel);\n\n                return;\n            }\n\n            if (m_CachedTexture.textureAvailability == GITextureAvailability.GITextureLoading && m_CachedTexture.texture == null)\n            {\n                GUI.Label(drawableArea, Styles.TextureLoading, Styles.PreviewLabel);\n                return;\n            }\n\n            LightmapType lightmapType = LightmapVisualizationUtility.GetLightmapType(textureType);\n\n            switch (Event.current.type)\n            {\n                // 'F' will zoom to uv bounds\n                case EventType.ValidateCommand:\n                case EventType.ExecuteCommand:\n\n                    if (Event.current.commandName == EventCommandNames.FrameSelected && IsActiveGameObjectInLightmap(textureType))\n                    {\n                        // There are instance based baked textures where we don't get any STs and can't do the framing\n                        if (!isRealtimeLightmap && !LightmapVisualizationUtility.IsAtlasTextureType(textureType))\n                            break;\n\n                        Vector4 lightmapTilingOffset = LightmapVisualizationUtility.GetLightmapTilingOffset(lightmapType);\n\n                        Vector2 min = new Vector2(lightmapTilingOffset.z, lightmapTilingOffset.w);\n                        Vector2 max = min + new Vector2(lightmapTilingOffset.x, lightmapTilingOffset.y);\n\n                        min = Vector2.Max(min, Vector2.zero);\n                        max = Vector2.Min(max, Vector2.one);\n\n                        Texture2D texture = m_CachedTexture.texture;\n                        Rect textureRect = new Rect(r.x, r.y, texture.width, texture.height);\n                        textureRect = ResizeRectToFit(textureRect, drawableArea);\n\n                        float offsetX = 0.0f, offsetY = 0.0f;\n\n                        if (textureRect.height == drawableArea.height)\n                            offsetX = (drawableArea.width - textureRect.width) / drawableArea.width;\n                        else\n                            offsetY = (drawableArea.height - textureRect.height) / drawableArea.height;\n\n                        // Make sure that the focus rectangle is a even square\n                        Rect rect = new Rect(min.x, min.y, max.x - min.x, max.y - min.y);\n                        rect.width = rect.height = Mathf.Max(rect.width, rect.height);\n                        rect.x -= (offsetX * min.x);\n                        rect.y += (offsetY * (1 - max.y));\n\n                        m_ZoomablePreview.shownArea = rect;\n                        Event.current.Use();\n                    }\n                    break;\n\n                case EventType.Repaint:\n                case EventType.MouseDown:\n                {\n                    Texture2D texture = m_CachedTexture.texture;\n\n                    if (texture)\n                    {\n                        Rect textureRect = new Rect(r.x, r.y, texture.width, texture.height);\n                        textureRect = ResizeRectToFit(textureRect, drawableArea);\n                        textureRect = ScaleRectByZoomableArea(textureRect, m_ZoomablePreview);\n\n                        const int padding = 5;\n                        textureRect.x += padding;\n                        textureRect.width -= padding * 2;\n                        textureRect.height -= padding;\n\n                        // Scale and draw texture and uv's\n                        if (Event.current.type == EventType.Repaint)\n                        {\n                            // Texture shouldn't be filtered since it will make previewing really blurry\n                            FilterMode prevMode = texture.filterMode;\n                            texture.filterMode = FilterMode.Point;\n\n                            LightmapVisualizationUtility.DrawTextureWithUVOverlay(texture,\n                                (m_ShowUVOverlay && IsActiveGameObjectInLightmap(textureType)) ? Selection.activeGameObject : null,\n                                m_ShowUVOverlay ? m_CachedTextureObjects : new GameObject[] { }, drawableArea, textureRect, textureType, exposure, useInteractiveLightBakingData);\n                            texture.filterMode = prevMode;\n                        }\n                        // Handle clicking on a UV chart to select the renderer\n                        else if (Event.current.type == EventType.MouseDown && m_ShowUVOverlay)\n                        {\n                            HandleUVChartClick(textureRect, m_CachedTextureObjects);\n                        }\n                    }\n                }\n                break;\n            }\n\n            m_ZoomablePreview.EndViewGUI();\n        }\n\n        private void SelectPreviewTextureIndex(object textureOption)\n        {\n            GUIContent[] options = currentPreviewTextureOptions;\n\n            m_SelectedPreviewTextureOptionIndex = Array.IndexOf(options, textureOption);\n        }\n\n        private GITextureType GetSelectedTextureType()\n        {\n            GUIContent[] options = currentPreviewTextureOptions;\n            GITextureType[] types = currentPreviewTextureTypes;\n\n            if ((m_SelectedPreviewTextureOptionIndex < 0 || m_SelectedPreviewTextureOptionIndex >= options.Length) || !LightmapVisualizationUtility.IsTextureTypeEnabled(types[m_SelectedPreviewTextureOptionIndex]))\n            {\n                m_SelectedPreviewTextureOptionIndex = 0;\n            }\n\n            return types[m_SelectedPreviewTextureOptionIndex];\n        }\n\n        private bool SelectedTextureTypeNeedsExposureControl()\n        {\n            var textureType = GetSelectedTextureType();\n\n            // it only make sense to allow the user to adjust the exposure on these textures\n            return textureType == GITextureType.BakedEmissive || textureType == GITextureType.Baked ||\n                textureType == GITextureType.Emissive || textureType == GITextureType.Irradiance;\n        }\n\n        private bool IsActiveGameObjectInLightmap(GITextureType textureType)\n        {\n            if (isRealtimeLightmap)\n                return (m_ActiveGameObjectTextureHash == m_RealtimeTextureHash);\n\n            if (LightmapVisualizationUtility.IsAtlasTextureType(textureType))\n                return (m_ActiveGameObjectLightmapIndex == m_LightmapIndex);\n\n            return (m_ActiveGameObjectInstanceId == m_InstanceID);\n        }\n\n        private void UpdateActiveGameObjectSelection()\n        {\n            MeshRenderer renderer = null;\n            Terrain terrain = null;\n\n            // if the selected active object (also active in the hierarchy) is a renderer or a terrain, we check its index etc.\n            // otherwise bail\n            if (Selection.activeGameObject == null || !Selection.activeGameObject.activeInHierarchy ||\n                (!Selection.activeGameObject.TryGetComponent(out renderer) &&\n                 !Selection.activeGameObject.TryGetComponent(out terrain)))\n            {\n                m_ActiveGameObjectLightmapIndex = -1;\n                m_ActiveGameObjectInstanceId = -1;\n                m_ActiveGameObjectTextureHash = new Hash128();\n                return;\n            }\n\n            if (isRealtimeLightmap)\n            {\n                Hash128 inputSystemHash;\n                if ((renderer != null && Lightmapping.GetInputSystemHash(renderer.GetInstanceID(), out inputSystemHash))\n                    || (terrain != null && Lightmapping.GetInputSystemHash(terrain.GetInstanceID(), out inputSystemHash)))\n                {\n                    m_ActiveGameObjectTextureHash = inputSystemHash;\n                }\n                else\n                    m_ActiveGameObjectTextureHash = new Hash128();\n            }\n            else\n            {\n                m_ActiveGameObjectInstanceId = renderer != null ? renderer.GetInstanceID() : terrain.GetInstanceID();\n\n                if (useInteractiveLightBakingData)\n                    m_ActiveGameObjectLightmapIndex = InteractiveLightBaking.GetLightmapIndexFromRenderer(m_ActiveGameObjectInstanceId);\n                else\n                    m_ActiveGameObjectLightmapIndex = renderer != null ? renderer.lightmapIndex : terrain.lightmapIndex;\n            }\n        }\n\n        private void UpdateCachedTexture(GITextureType textureType)\n        {\n            if (isIndexBased)\n            {\n                if (isRealtimeLightmap)\n                {\n                    Hash128[] mainHashes = Lightmapping.GetMainSystemHashes();\n\n                    if (!m_RealtimeTextureHash.isValid || !mainHashes.Contains(m_RealtimeTextureHash))\n                    {\n                        m_RealtimeTextureHash = mainHashes.ElementAtOrDefault(m_LightmapIndex);\n                    }\n                }\n            }\n            else // instance based\n            {\n                if (isRealtimeLightmap)\n                {\n                    Hash128 systemHash;\n\n                    if (!Lightmapping.GetInputSystemHash(m_InstanceID, out systemHash))\n                    {\n                        m_CachedTexture.textureAvailability = GITextureAvailability.GITextureNotAvailable;\n                        return;\n                    }\n                    m_RealtimeTextureHash = systemHash;\n                }\n                else if (useInteractiveLightBakingData)\n                {\n                    ushort lightmapIndex = InteractiveLightBaking.GetLightmapIndexFromRenderer(m_InstanceID);\n                    if (lightmapIndex >= 0xFFFF)\n                    {\n                        m_CachedTexture.textureAvailability = GITextureAvailability.GITextureNotAvailable;\n                        return;\n                    }\n\n                    m_LightmapIndex = lightmapIndex;\n                }\n                else\n                {\n                    int lightmapIndex;\n                    if (!Lightmapping.GetLightmapIndex(m_InstanceID, out lightmapIndex))\n                    {\n                        m_CachedTexture.textureAvailability = GITextureAvailability.GITextureNotAvailable;\n                        return;\n                    }\n\n                    m_LightmapIndex = lightmapIndex;\n                }\n            }\n\n            Hash128 contentHash = isRealtimeLightmap ? LightmapVisualizationUtility.GetRealtimeGITextureHash(m_RealtimeTextureHash, textureType) :\n                LightmapVisualizationUtility.GetBakedGITextureHash(m_LightmapIndex, m_InstanceID, textureType, useInteractiveLightBakingData);\n\n            // if we need to fetch a new texture\n            if (m_CachedTexture.texture == null || m_CachedTexture.type != textureType || m_CachedTexture.contentHash != contentHash || m_CachedTexture.contentHash == new Hash128())\n            {\n                m_CachedTexture = isRealtimeLightmap ?\n                    LightmapVisualizationUtility.GetRealtimeGITexture(m_RealtimeTextureHash, textureType) :\n                    LightmapVisualizationUtility.GetBakedGITexture(m_LightmapIndex, m_InstanceID, textureType, useInteractiveLightBakingData);\n            }\n\n            if (!m_ShowUVOverlay)\n                return; // if we don't wanna show any overlay\n\n            if (m_CachedTexture.texture == null || m_CachedTexture.textureAvailability == GITextureAvailability.GITextureNotAvailable || m_CachedTexture.textureAvailability == GITextureAvailability.GITextureUnknown)\n                return; // if we dont have a texture\n\n            // fetch Renderers\n\n            if (isRealtimeLightmap)\n                m_CachedTextureObjects = LightmapVisualizationUtility.GetRealtimeGITextureRenderers(m_RealtimeTextureHash);\n            else if (LightmapVisualizationUtility.IsAtlasTextureType(textureType))\n                m_CachedTextureObjects = LightmapVisualizationUtility.GetBakedGITextureRenderers(m_LightmapIndex, useInteractiveLightBakingData);\n            else // if it's an instance based baked lightmap, we only have 1 object in it\n                m_CachedTextureObjects = new GameObject[] {};\n        }\n\n        private Rect ResizeRectToFit(Rect rect, Rect to)\n        {\n            float widthScale = to.width / rect.width;\n            float heightScale = to.height / rect.height;\n            float scale = Mathf.Min(widthScale, heightScale);\n\n            float width = (int)Mathf.Round((rect.width * scale));\n            float height = (int)Mathf.Round((rect.height * scale));\n\n            return new Rect(rect.x, rect.y, width, height);\n        }\n\n        private Rect ScaleRectByZoomableArea(Rect rect, ZoomableArea zoomableArea)\n        {\n            float x = -(zoomableArea.shownArea.x / zoomableArea.shownArea.width) * (rect.x + zoomableArea.rect.width);\n            float y = ((zoomableArea.shownArea.y - (1f - zoomableArea.shownArea.height)) / zoomableArea.shownArea.height) * zoomableArea.rect.height;\n\n            float width = rect.width / zoomableArea.shownArea.width;\n            float height = rect.height / zoomableArea.shownArea.height;\n\n            return new Rect(rect.x + x, rect.y + y, width, height);\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/SceneModeWindows/OcclusionCullingWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing System.IO;\nusing UnityEditor.Overlays;\nusing UnityEngine.SceneManagement;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [EditorWindowTitle(title = \"Occlusion\", icon = \"Occlusion\")]\n    internal class OcclusionCullingWindow : EditorWindow\n    {\n        static bool s_IsVisible = false;\n\n        private bool m_PreVis;\n        private bool m_ClearCacheData = true;\n        private bool m_ClearBakeData = true;\n        private string m_Warning;\n\n        static OcclusionCullingWindow ms_OcclusionCullingWindow;\n        Vector2 m_ScrollPosition = Vector2.zero;\n        Mode m_Mode = Mode.AreaSettings;\n\n        static Styles s_Styles;\n\n        class Styles\n        {\n            public GUIContent[] ModeToggles =\n            {\n                EditorGUIUtility.TrTextContent(\"Object\"),\n                EditorGUIUtility.TrTextContent(\"Bake\"),\n                EditorGUIUtility.TrTextContent(\"Visualization\")\n            };\n            public GUIStyle labelStyle = EditorStyles.wordWrappedMiniLabel;\n            public GUIContent emptyAreaSelection = EditorGUIUtility.TrTextContent(\"Select a Mesh Renderer or an Occlusion Area from the scene.\");\n            public GUIContent emptyCameraSelection = EditorGUIUtility.TrTextContent(\"Select a Camera from the scene.\");\n            public GUIContent visualizationNote = EditorGUIUtility.TrTextContent(\"The visualization may not correspond to current bake settings and Occlusion Area placements if they have been changed since last bake.\");\n            public GUIContent seeVisualizationInScene = EditorGUIUtility.TrTextContent(\"See the occlusion culling visualization in the Scene View based on the selected Camera.\");\n            public GUIContent noOcclusionData = EditorGUIUtility.TrTextContent(\"No occlusion data has been baked.\");\n            public GUIContent smallestHole = EditorGUIUtility.TrTextContent(\"Smallest Hole\", \"Smallest hole in the geometry through which the camera is supposed to see. The single float value of the parameter represents the diameter of the imaginary smallest hole, i.e. the maximum extent of a 3D object that fits through the hole.\");\n            public GUIContent backfaceThreshold = EditorGUIUtility.TrTextContent(\"Backface Threshold\", \"The backface threshold is a size optimization that reduces unnecessary details by testing backfaces. A value of 100 is robust and never removes any backfaces. A value of 5 aggressively reduces the data based on locations with visible backfaces. The idea is that typically valid camera positions cannot see many backfaces. For example, geometry under terrain and inside solid objects can be removed.\");\n            public GUIContent farClipPlane = EditorGUIUtility.TrTextContent(\"Far Clip Plane\", \"Far Clip Plane used during baking. This should match the largest far clip plane used by any camera in the scene. A value of 0.0 sets the far plane to Infinity.\");\n            public GUIContent smallestOccluder = EditorGUIUtility.TrTextContent(\"Smallest Occluder\", \"The size of the smallest object that will be used to hide other objects when doing occlusion culling. For example, if a value of 4 is chosen, then all the objects that are higher or wider than 4 meters will block visibility and the objects that are smaller than that will not. This value is a tradeoff between occlusion accuracy and storage size.\");\n            public GUIContent defaultParameterText = EditorGUIUtility.TrTextContent(\"Default Parameters\", \"The default parameters guarantee that any given scene computes fast and the occlusion culling results are good. As the parameters are always scene specific, better results will be achieved when fine tuning the parameters on a scene to scene basis. All the parameters are dependent on the unit scale of the scene and it is imperative that the unit scale parameter is set correctly before setting the default values.\");\n        }\n\n        enum Mode\n        {\n            AreaSettings = 0,\n            BakeSettings = 1,\n            Visualization = 2\n        }\n\n        internal static bool isVisible\n        {\n            get { return (ms_OcclusionCullingWindow != null) ? s_IsVisible : false; }\n        }\n\n        void OnBecameVisible()\n        {\n            if (s_IsVisible == true) return;\n\n            s_IsVisible = true;\n            StaticOcclusionCullingVisualization.showOcclusionCulling = true;\n            SceneView.RepaintAll();\n        }\n\n        void OnBecameInvisible()\n        {\n            s_IsVisible = false;\n\n            StaticOcclusionCullingVisualization.showOcclusionCulling = false;\n            SceneView.RepaintAll();\n        }\n\n        void OnSelectionChange()\n        {\n            if (m_Mode == Mode.AreaSettings || m_Mode == Mode.Visualization)\n                Repaint();\n        }\n\n        void OnEnable()\n        {\n            titleContent = GetLocalizedTitleContent();\n            ms_OcclusionCullingWindow = this;\n            autoRepaintOnSceneChange = true;\n            EditorApplication.searchChanged += Repaint;\n            Repaint();\n        }\n\n        void OnDisable()\n        {\n            ms_OcclusionCullingWindow = null;\n            EditorApplication.searchChanged -= Repaint;\n        }\n\n        static void BackgroundTaskStatusChanged()\n        {\n            if (ms_OcclusionCullingWindow)\n                ms_OcclusionCullingWindow.Repaint();\n        }\n\n        [MenuItem(\"Window/Rendering/Occlusion Culling\", false, 101)]\n        static void GenerateWindow()\n        {\n            var window = GetWindow<OcclusionCullingWindow>(typeof(InspectorWindow));\n            window.minSize = new Vector2(300, 250);\n        }\n\n        void SummaryGUI()\n        {\n            GUILayout.BeginVertical(EditorStyles.helpBox);\n\n            if (StaticOcclusionCulling.umbraDataSize == 0)\n            {\n                GUILayout.Label(s_Styles.noOcclusionData, s_Styles.labelStyle);\n            }\n            else\n            {\n                GUILayout.Label(\"Last bake:\", s_Styles.labelStyle);\n\n                GUILayout.BeginHorizontal();\n\n                GUILayout.BeginVertical();\n                GUILayout.Label(\"Occlusion data size \", s_Styles.labelStyle);\n                GUILayout.EndVertical();\n\n                GUILayout.BeginVertical();\n                GUILayout.Label(EditorUtility.FormatBytes(StaticOcclusionCulling.umbraDataSize), s_Styles.labelStyle);\n                GUILayout.EndVertical();\n\n                GUILayout.EndHorizontal();\n            }\n\n            GUILayout.EndVertical();\n        }\n\n        OcclusionArea CreateNewArea()\n        {\n            GameObject go = new GameObject(\"Occlusion Area\");\n            OcclusionArea oa = go.AddComponent<OcclusionArea>();\n            Selection.activeGameObject = go;\n            return oa;\n        }\n\n        void AreaSelectionGUI()\n        {\n            bool emptySelection = true;\n            GameObject[] gos;\n            Type focusType = SceneModeUtility.SearchBar(typeof(Renderer), typeof(OcclusionArea));\n            EditorGUILayout.Space();\n\n            // Occlusion Areas\n            OcclusionArea[] oas = SceneModeUtility.GetSelectedObjectsOfType<OcclusionArea>(out gos);\n            if (gos.Length > 0)\n            {\n                emptySelection = false;\n                EditorGUILayout.MultiSelectionObjectTitleBar(oas);\n                using (var so = new SerializedObject(oas))\n                {\n                    EditorGUILayout.PropertyField(so.FindProperty(\"m_IsViewVolume\"));\n                    so.ApplyModifiedProperties();\n                }\n            }\n\n            // Renderers\n            Renderer[] renderers = SceneModeUtility.GetSelectedObjectsOfType<Renderer>(out gos, typeof(MeshRenderer), typeof(SkinnedMeshRenderer));\n            if (gos.Length > 0)\n            {\n                emptySelection = false;\n                EditorGUILayout.MultiSelectionObjectTitleBar(renderers);\n                using (var goso = new SerializedObject(gos))\n                {\n                    SceneModeUtility.StaticFlagField(\"Occluder Static\", goso.FindProperty(\"m_StaticEditorFlags\"), (int)StaticEditorFlags.OccluderStatic);\n                    SceneModeUtility.StaticFlagField(\"Occludee Static\", goso.FindProperty(\"m_StaticEditorFlags\"), (int)StaticEditorFlags.OccludeeStatic);\n                    goso.ApplyModifiedProperties();\n                }\n            }\n\n            if (emptySelection)\n            {\n                GUILayout.Label(s_Styles.emptyAreaSelection, EditorStyles.helpBox);\n                if (focusType == typeof(OcclusionArea))\n                {\n                    EditorGUIUtility.labelWidth = 80;\n                    EditorGUILayout.Space();\n                    EditorGUILayout.BeginHorizontal();\n                    EditorGUILayout.PrefixLabel(\"Create New\");\n                    if (GUILayout.Button(\"Occlusion Area\", EditorStyles.miniButton, GUILayout.ExpandWidth(false)))\n                        CreateNewArea();\n                    EditorGUILayout.EndHorizontal();\n                }\n            }\n        }\n\n        void CameraSelectionGUI()\n        {\n            SceneModeUtility.SearchBar(typeof(Camera));\n            EditorGUILayout.Space();\n\n            Camera cam = null;\n            if (Selection.activeGameObject)\n                cam = Selection.activeGameObject.GetComponent<Camera>();\n\n            // Camera\n            if (cam)\n            {\n                Camera[] cameras = new Camera[] { cam };\n                EditorGUILayout.MultiSelectionObjectTitleBar(cameras);\n                EditorGUILayout.HelpBox(s_Styles.seeVisualizationInScene.text, MessageType.Info);\n            }\n            else\n            {\n                GUILayout.Label(s_Styles.emptyCameraSelection, EditorStyles.helpBox);\n            }\n        }\n\n        void BakeSettings()\n        {\n            // Button for setting default values\n            float buttonWidth = 150;\n            if (GUILayout.Button(\"Set default parameters\", GUILayout.Width(buttonWidth)))\n            {\n                Undo.RegisterCompleteObjectUndo(StaticOcclusionCulling.occlusionCullingSettings, \"Set Default Parameters\");\n                GUIUtility.keyboardControl = 0; // Force focus out from potentially selected field for default parameters setting\n                StaticOcclusionCulling.SetDefaultOcclusionBakeSettings();\n            }\n\n            // Label for default parameter setting\n            GUILayout.Label(s_Styles.defaultParameterText.tooltip, EditorStyles.helpBox);\n\n            // Edit Smallest Occluder\n            EditorGUI.BeginChangeCheck();\n            float smallestOccluder = EditorGUILayout.FloatField(s_Styles.smallestOccluder, StaticOcclusionCulling.smallestOccluder);\n            smallestOccluder = Math.Clamp(smallestOccluder, 0.0f, float.MaxValue);\n            if (EditorGUI.EndChangeCheck())\n            {\n                Undo.RegisterCompleteObjectUndo(StaticOcclusionCulling.occlusionCullingSettings, \"Change Smallest Occluder\");\n                StaticOcclusionCulling.smallestOccluder = smallestOccluder;\n            }\n\n            // Edit smallest hole\n            EditorGUI.BeginChangeCheck();\n            float smallestHole = EditorGUILayout.FloatField(s_Styles.smallestHole, StaticOcclusionCulling.smallestHole);\n            smallestHole = Math.Clamp(smallestHole, 0.0f, float.MaxValue);\n            if (EditorGUI.EndChangeCheck())\n            {\n                Undo.RegisterCompleteObjectUndo(StaticOcclusionCulling.occlusionCullingSettings, \"Change Smallest Hole\");\n                StaticOcclusionCulling.smallestHole = smallestHole;\n            }\n\n            // Edit backface threshold\n            EditorGUI.BeginChangeCheck();\n            float backfaceThreshold = EditorGUILayout.Slider(s_Styles.backfaceThreshold, StaticOcclusionCulling.backfaceThreshold, 5.0F, 100.0F);\n            if (EditorGUI.EndChangeCheck())\n            {\n                Undo.RegisterCompleteObjectUndo(StaticOcclusionCulling.occlusionCullingSettings, \"Change Backface Threshold\");\n                StaticOcclusionCulling.backfaceThreshold = backfaceThreshold;\n            }\n        }\n\n        void BakeButtons()\n        {\n            float buttonWidth = 95;\n            GUILayout.BeginHorizontal();\n            GUILayout.FlexibleSpace();\n\n            bool allowBaking = !EditorApplication.isPlayingOrWillChangePlaymode;\n            bool bakeRunning = StaticOcclusionCulling.isRunning;\n\n            GUI.enabled = !bakeRunning && allowBaking;\n            if (CustomDropdownButton(\"Clear\", buttonWidth))\n            {\n                if (m_ClearBakeData)\n                {\n                    StaticOcclusionCulling.Clear();\n                }\n\n                if (m_ClearCacheData)\n                {\n                    StaticOcclusionCulling.RemoveCacheFolder();\n                }\n            }\n\n            GUI.enabled = allowBaking;\n            if (bakeRunning)\n            {\n                if (GUILayout.Button(\"Cancel\", GUILayout.Width(buttonWidth)))\n                    StaticOcclusionCulling.Cancel();\n            }\n            else\n            {\n                if (GUILayout.Button(\"Bake\", GUILayout.Width(buttonWidth)))\n                {\n                    StaticOcclusionCulling.GenerateInBackground();\n                }\n            }\n\n            GUILayout.EndHorizontal();\n            GUI.enabled = true;\n        }\n\n        private bool CustomDropdownButton(string name, float width, params GUILayoutOption[] options)\n        {\n            var content = EditorGUIUtility.TrTextContent(name);\n            var rect = GUILayoutUtility.GetRect(content, EditorStyles.dropDownList, options);\n\n            var halfDiff = (width - rect.width) / 2f;\n            rect.xMin -= halfDiff;\n            rect.xMax += halfDiff;\n            var currPos = rect.position;\n            currPos.x -= halfDiff;\n            rect.position = currPos;\n\n            var dropDownRect = rect;\n            const float kDropDownButtonWidth = 20f;\n            dropDownRect.xMin = dropDownRect.xMax - kDropDownButtonWidth;\n\n            string[] names = { \"Bake Data\", \"Cache Data\" };\n            bool[] values = { m_ClearBakeData, m_ClearCacheData };\n            if (Event.current.type == EventType.MouseDown && dropDownRect.Contains(Event.current.mousePosition))\n            {\n                var menu = new GenericMenu();\n                for (int i = 0; i != names.Length; i++)\n                    menu.AddItem(new GUIContent(names[i]), values[i], CustomDropdownCallback, i);\n\n                menu.DropDown(rect);\n                Event.current.Use();\n\n                return false;\n            }\n\n            return GUI.Button(rect, content, EditorStyles.dropDownList);\n        }\n\n        private void CustomDropdownCallback(object userData)\n        {\n            int index = (int)userData;\n            if (index == 0)\n            {\n                m_ClearBakeData = !m_ClearBakeData;\n            }\n            else if (index == 1)\n            {\n                m_ClearCacheData = !m_ClearCacheData;\n            }\n        }\n\n        void ModeToggle()\n        {\n            EditorGUILayout.BeginHorizontal();\n            GUILayout.FlexibleSpace();\n            using (var check = new EditorGUI.ChangeCheckScope())\n            {\n                m_Mode = (Mode)GUILayout.Toolbar((int)m_Mode, s_Styles.ModeToggles, \"LargeButton\", GUI.ToolbarButtonSize.FitToContents);\n                if (check.changed)\n                {\n                    if (m_Mode == Mode.Visualization && StaticOcclusionCulling.umbraDataSize > 0)\n                        StaticOcclusionCullingVisualization.showPreVisualization = false;\n                    else\n                        StaticOcclusionCullingVisualization.showPreVisualization = true;\n                    SceneView.RepaintAll();\n                }\n            }\n            GUILayout.FlexibleSpace();\n            EditorGUILayout.EndHorizontal();\n        }\n\n        void OnGUI()\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            // Make sure the tab jumps to visualization if we're in visualize mode.\n            // (Don't do the reverse. Since tabs can't be marked disabled, the user\n            // will be confused if the visualization tab can't be clicked, and that\n            // would be the result if we changed the tab away from visualization\n            // whenever showPreVisualization is false.)\n            if (m_Mode != Mode.Visualization && StaticOcclusionCullingVisualization.showPreVisualization == false)\n                m_Mode = Mode.Visualization;\n\n            EditorGUILayout.Space();\n            ModeToggle();\n            EditorGUILayout.Space();\n\n            m_ScrollPosition = EditorGUILayout.BeginScrollView(m_ScrollPosition);\n            switch (m_Mode)\n            {\n                case Mode.AreaSettings:\n                    AreaSelectionGUI();\n                    break;\n                case Mode.BakeSettings:\n                    BakeSettings();\n                    break;\n                case Mode.Visualization:\n                    if (StaticOcclusionCulling.umbraDataSize > 0)\n                    {\n                        CameraSelectionGUI();\n                        GUILayout.FlexibleSpace();\n                        GUILayout.Label(s_Styles.visualizationNote, EditorStyles.helpBox);\n                    }\n                    else\n                    {\n                        GUILayout.Label(s_Styles.noOcclusionData, EditorStyles.helpBox);\n                    }\n                    break;\n            }\n            EditorGUILayout.EndScrollView();\n\n            EditorGUILayout.Space();\n\n            BakeButtons();\n\n            EditorGUILayout.Space();\n\n            // Info GUI\n            SummaryGUI();\n        }\n\n        void OnDidOpenScene()\n        {\n            StaticOcclusionCulling.InvalidatePrevisualisationData();\n            Repaint();\n        }\n\n        void SetShowVolumePreVis()\n        {\n            StaticOcclusionCullingVisualization.showPreVisualization = true;\n            if (m_Mode == Mode.Visualization)\n                m_Mode = Mode.AreaSettings;\n            if (ms_OcclusionCullingWindow)\n                ms_OcclusionCullingWindow.Repaint();\n            SceneView.RepaintAll();\n        }\n\n        void SetShowVolumeCulling()\n        {\n            StaticOcclusionCullingVisualization.showPreVisualization = false;\n            m_Mode = Mode.Visualization;\n            if (ms_OcclusionCullingWindow)\n                ms_OcclusionCullingWindow.Repaint();\n            SceneView.RepaintAll();\n        }\n\n        bool ShowModePopup(Rect popupRect)\n        {\n            // Visualization mode popup\n            int tomeSize = StaticOcclusionCulling.umbraDataSize;\n\n            // We can only change the preVis state during layout mode. However, the Tome data could be emptied at anytime, which will immediately disable preVis.\n            // We need to detect this and force a repaint, so we can change the state.\n            if (m_PreVis != StaticOcclusionCullingVisualization.showPreVisualization)\n                SceneView.RepaintAll();\n\n            if (Event.current.type == EventType.Layout)\n                m_PreVis = StaticOcclusionCullingVisualization.showPreVisualization;\n\n            string[] options = new string[] { \"Edit\", \"Visualize\" };\n            int selected = m_PreVis ? 0 : 1;\n            if (EditorGUI.DropdownButton(popupRect, new GUIContent(options[selected]), FocusType.Passive, EditorStyles.popup))\n            {\n                GenericMenu menu = new GenericMenu();\n                menu.AddItem(new GUIContent(options[0]), selected == 0, SetShowVolumePreVis);\n                if (tomeSize > 0)\n                    menu.AddItem(new GUIContent(options[1]), selected == 1, SetShowVolumeCulling);\n                else\n                    menu.AddDisabledItem(new GUIContent(options[1]));\n\n                menu.Popup(popupRect, selected);\n            }\n            return m_PreVis;\n        }\n\n        void DisplayControls()\n        {\n            if (!s_IsVisible)\n                return;\n\n            bool temp;\n\n            // See if pre-vis is set to true.\n            // If we don't have any Tome data, act as if pvs is true, but don't actually set it to true\n            // - that way it will act like it switches to false (the default value) by itself as soon as pvs data has been build,\n            // which better leads to discovery of this feature.\n\n            bool preVis = ShowModePopup(GUILayoutUtility.GetRect(170, EditorGUIUtility.singleLineHeight));\n\n            if (Event.current.type == EventType.Layout)\n            {\n                m_Warning = \"\";\n\n                if (!preVis)\n                {\n                    if (StaticOcclusionCullingVisualization.previewOcclucionCamera == null)\n                        m_Warning = \"No camera selected for occlusion preview.\";\n                    else if (!StaticOcclusionCullingVisualization.isPreviewOcclusionCullingCameraInPVS)\n                        m_Warning = \"Camera is not inside an Occlusion View Area.\";\n                }\n            }\n\n            int legendHeight = 12;\n\n            if (!string.IsNullOrEmpty(m_Warning))\n            {\n                Rect warningRect = GUILayoutUtility.GetRect(100, legendHeight + 19);\n                warningRect.x += EditorGUI.indent;\n                warningRect.width -= EditorGUI.indent;\n                GUI.Label(warningRect, m_Warning, EditorStyles.helpBox);\n            }\n            else\n            {\n                // Show legend / volume toggles\n                Rect legendRect = GUILayoutUtility.GetRect(200, legendHeight);\n                legendRect.x += EditorGUI.indent;\n                legendRect.width -= EditorGUI.indent;\n                Rect viewLegendRect = new Rect(legendRect.x, legendRect.y, legendRect.width, legendRect.height);\n\n                if (preVis)\n                    EditorGUI.DrawLegend(viewLegendRect, Color.white, \"View Volumes\", StaticOcclusionCullingVisualization.showViewVolumes);\n                else\n                    EditorGUI.DrawLegend(viewLegendRect, Color.white, \"Camera Volumes\", StaticOcclusionCullingVisualization.showViewVolumes);\n\n                temp = GUI.Toggle(viewLegendRect, StaticOcclusionCullingVisualization.showViewVolumes, \"\", GUIStyle.none);\n                if (temp != StaticOcclusionCullingVisualization.showViewVolumes)\n                {\n                    StaticOcclusionCullingVisualization.showViewVolumes = temp;\n                    SceneView.RepaintAll();\n                }\n\n                if (!preVis)\n                {\n                    // TODO: FORE REALS cleanup this bad code BUG: 496650\n                    legendRect = GUILayoutUtility.GetRect(100, legendHeight);\n                    legendRect.x += EditorGUI.indent;\n                    legendRect.width -= EditorGUI.indent;\n                    viewLegendRect = new Rect(legendRect.x, legendRect.y, legendRect.width, legendRect.height);\n                    EditorGUI.DrawLegend(viewLegendRect, Color.green, \"Visibility Lines\", StaticOcclusionCullingVisualization.showVisibilityLines);\n\n                    temp = GUI.Toggle(viewLegendRect, StaticOcclusionCullingVisualization.showVisibilityLines, \"\", GUIStyle.none);\n                    if (temp != StaticOcclusionCullingVisualization.showVisibilityLines)\n                    {\n                        StaticOcclusionCullingVisualization.showVisibilityLines = temp;\n                        SceneView.RepaintAll();\n                    }\n\n                    legendRect = GUILayoutUtility.GetRect(100, legendHeight);\n                    legendRect.x += EditorGUI.indent;\n                    legendRect.width -= EditorGUI.indent;\n                    viewLegendRect = new Rect(legendRect.x, legendRect.y, legendRect.width, legendRect.height);\n                    EditorGUI.DrawLegend(viewLegendRect, Color.grey, \"Portals\", StaticOcclusionCullingVisualization.showPortals);\n\n                    temp = GUI.Toggle(viewLegendRect, StaticOcclusionCullingVisualization.showPortals, \"\", GUIStyle.none);\n                    if (temp != StaticOcclusionCullingVisualization.showPortals)\n                    {\n                        StaticOcclusionCullingVisualization.showPortals = temp;\n                        SceneView.RepaintAll();\n                    }\n                }\n\n                // Geometry culling toggle\n                if (!preVis)\n                {\n                    temp = GUILayout.Toggle(StaticOcclusionCullingVisualization.showGeometryCulling, \"Occlusion culling\");\n                    if (temp != StaticOcclusionCullingVisualization.showGeometryCulling)\n                    {\n                        StaticOcclusionCullingVisualization.showGeometryCulling = temp;\n                        SceneView.RepaintAll();\n                    }\n                }\n            }\n        }\n\n        [Overlay(typeof(SceneView), k_OverlayId, k_DisplayName)]\n        class SceneViewOcclusionCullingOverlay : TransientSceneViewOverlay\n        {\n            const string k_OverlayId = \"Scene View/Occlusion Culling\";\n            const string k_DisplayName = \"Occlusion Culling\";\n\n            OcclusionCullingWindow m_Window;\n\n            public override bool visible\n            {\n                get { return s_IsVisible && StaticOcclusionCullingVisualization.showOcclusionCulling; }\n            }\n\n            public override void OnGUI()\n            {\n                if (m_Window == null)\n                {\n                    var wins = Resources.FindObjectsOfTypeAll(typeof(OcclusionCullingWindow)) as OcclusionCullingWindow[];\n                    m_Window = wins.Length > 0 ? wins[0] : null;\n                }\n\n                if (m_Window != null)\n                {\n                    m_Window.DisplayControls();\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneModeWindows/SceneModeUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    public static class SceneModeUtility\n    {\n        class SceneModeData : ScriptableSingleton<SceneModeData>\n        {\n            public string focusTypeName = null;\n            public SceneHierarchyWindow hierarchyWindow = null;\n        }\n\n        private static Type s_FocusType = null;\n        private static Type focusType\n        {\n            get\n            {\n                if(s_FocusType == null && focusTypeName != null)\n                    s_FocusType = Type.GetType(focusTypeName);\n\n                return s_FocusType;\n            }\n            set\n            {\n                s_FocusType = value;\n                focusTypeName = s_FocusType?.AssemblyQualifiedName;\n            }\n        }\n\n        private static string focusTypeName\n        {\n            get => SceneModeData.instance.focusTypeName;\n            set => SceneModeData.instance.focusTypeName = value;\n        }\n\n        private static SceneHierarchyWindow hierarchyWindow\n        {\n            get => SceneModeData.instance.hierarchyWindow;\n            set => SceneModeData.instance.hierarchyWindow = value;\n        }\n\n\n        private static GUIContent s_NoneButtonContent = null;\n\n        private class Styles\n        {\n            public GUIStyle typeButton = \"SearchModeFilter\";\n        }\n        private static Styles s_Styles;\n        private static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } }\n\n        public static T[] GetSelectedObjectsOfType<T>(out GameObject[] gameObjects, params Type[] types) where T : Object\n        {\n            if (types.Length == 0)\n                types = new Type[] { typeof(T) };\n\n            List<GameObject> gameObjectList = new List<GameObject>();\n            List<T> components = new List<T>();\n\n            Transform[] selectedTransforms = Selection.GetTransforms(SelectionMode.ExcludePrefab | SelectionMode.Editable);\n            foreach (Transform t in selectedTransforms)\n            {\n                foreach (Type type in types)\n                {\n                    Object comp = t.gameObject.GetComponent(type);\n                    if (comp != null)\n                    {\n                        gameObjectList.Add(t.gameObject);\n                        components.Add((T)comp);\n                        break;\n                    }\n                }\n            }\n            gameObjects = gameObjectList.ToArray();\n            return components.ToArray();\n        }\n\n        public static void SearchForType(Type type)\n        {\n            Object[] wins = Resources.FindObjectsOfTypeAll(typeof(SceneHierarchyWindow));\n            SceneHierarchyWindow win = wins.Length > 0 ? (wins[0] as SceneHierarchyWindow) : null;\n\n            if (win)\n            {\n                hierarchyWindow = win;\n                if (type == null || type == typeof(GameObject))\n                {\n                    focusType = null;\n                    win.ClearSearchFilter();\n                }\n                else\n                {\n                    focusType = type;\n                    if (win.searchMode == SearchableEditorWindow.SearchMode.Name)\n                        win.searchMode = SearchableEditorWindow.SearchMode.All;\n                    win.SetSearchFilter(\"t:\" + type.Name, win.searchMode, false);\n                    win.hasSearchFilterFocus = true;\n                }\n            }\n            else\n                focusType = null;\n        }\n\n        public static Type SearchBar(params Type[] types)\n        {\n            if (s_NoneButtonContent == null)\n            {\n                s_NoneButtonContent = EditorGUIUtility.IconContent(\"sv_icon_none\");\n                s_NoneButtonContent.text = \"None\";\n            }\n\n            if (s_FocusType != null &&\n                (hierarchyWindow == null || hierarchyWindow.m_SearchFilter != \"t:\" + s_FocusType.Name))\n            {\n                focusType = null;\n            }\n\n            GUILayout.Label(\"Scene Filter:\");\n\n            EditorGUILayout.BeginHorizontal();\n\n            {\n                GUIContent label = EditorGUIUtility.TempContent(\n                    \"All\",\n                    AssetPreview.GetMiniTypeThumbnail(typeof(GameObject)));\n                if (TypeButton(label, focusType == null, styles.typeButton))\n                    SceneModeUtility.SearchForType(null);\n            }\n\n            for (int i = 0; i < types.Length; i++)\n            {\n                Type type = types[i];\n                Texture2D icon = null;\n                if (type == typeof(Renderer))\n                    icon = EditorGUIUtility.IconContent<MeshRenderer>().image as Texture2D;\n                else if (type == typeof(Terrain))\n                    icon = EditorGUIUtility.IconContent<Terrain>().image as Texture2D;\n                else\n                    icon = AssetPreview.GetMiniTypeThumbnail(type);\n                string name = ObjectNames.NicifyVariableName(type.Name) + \"s\";\n                GUIContent label = EditorGUIUtility.TempContent(name, icon);\n                if (TypeButton(label, type == focusType, styles.typeButton))\n                    SceneModeUtility.SearchForType(type);\n            }\n            GUILayout.FlexibleSpace();\n            EditorGUILayout.EndHorizontal();\n\n            return focusType;\n        }\n\n        private static bool TypeButton(GUIContent label, bool selected, GUIStyle style)\n        {\n            EditorGUIUtility.SetIconSize(new Vector2(16f, 16f));\n            bool newSelected = GUILayout.Toggle(selected, label, style);\n            EditorGUIUtility.SetIconSize(Vector2.zero);\n            return newSelected && (newSelected != selected);\n        }\n\n        public static bool StaticFlagField(string label, SerializedProperty property, int flag)\n        {\n            bool oldToggle = (property.intValue & flag) != 0;\n            bool oldDifferent = (property.hasMultipleDifferentValuesBitwise & flag) != 0;\n            EditorGUI.showMixedValue = oldDifferent;\n            EditorGUI.BeginChangeCheck();\n            var toggle = EditorGUILayout.Toggle(label, oldToggle);\n            if (EditorGUI.EndChangeCheck())\n            {\n                if (!SetStaticFlags(property.serializedObject.targetObjects, flag, toggle))\n                    return oldToggle && !oldDifferent;\n                return toggle;\n            }\n            EditorGUI.showMixedValue = false;\n            return toggle && !oldDifferent;\n        }\n\n        public static bool SetStaticFlags(Object[] targetObjects, int changedFlags, bool flagValue)\n        {\n            bool allFlagsAreChanged = (changedFlags == int.MaxValue);\n            var msgChangedFlags = changedFlags;\n            if (msgChangedFlags < 0 && !allFlagsAreChanged)\n            {\n                //In order to have a list of human readable list of changed flags,\n                //we need to filter out bits that does not correspont to any option.\n                int allPossibleValues = 0;\n                var values = Enum.GetValues(typeof(StaticEditorFlags));\n                foreach (var value in values)\n                {\n                    allPossibleValues |= (int)value;\n                }\n\n                msgChangedFlags = msgChangedFlags & allPossibleValues;\n            }\n            StaticEditorFlags flag = allFlagsAreChanged ?\n                (StaticEditorFlags)0 :\n                (StaticEditorFlags)Enum.Parse(typeof(StaticEditorFlags), msgChangedFlags.ToString());\n\n\n            // Should we include child objects?\n            GameObjectUtility.ShouldIncludeChildren includeChildren = GameObjectUtility.DisplayUpdateChildrenDialogIfNeeded(targetObjects.OfType<GameObject>(), \"Change Static Flags\",\n                allFlagsAreChanged ?\n                \"Do you want to \" + (flagValue ? \"enable\" : \"disable\") + \" the static flags for all the child objects as well?\" :\n                \"Do you want to \" + (flagValue ? \"enable\" : \"disable\") + \" the \" + ObjectNames.NicifyVariableName(flag.ToString()) + \" flag for all the child objects as well?\");\n\n            if (includeChildren == GameObjectUtility.ShouldIncludeChildren.Cancel)\n            {\n                EditorGUIUtility.ExitGUI();\n                return false;\n            }\n            var objects = GetObjects(targetObjects, includeChildren == GameObjectUtility.ShouldIncludeChildren.IncludeChildren);\n            Undo.RecordObjects(objects, \"Change Static Flags\");\n\n            // Calculate new flags value separately for each object so other flags are not affected.\n            foreach (GameObject go in objects)\n            {\n                int goFlags = (int)GameObjectUtility.GetStaticEditorFlags(go);\n\n                // Following change is for backward compatibility after fixing case 1221145\n                if (goFlags < 0)\n                    goFlags = int.MaxValue;\n\n                // MaxValue will cause issues when changing it to other values so we set it to the max possible value\n                // that Static Editor flags can have before doing anything else with it\n                if (goFlags == int.MaxValue && flagValue == false)\n                    goFlags = (int)Math.Pow(2, Enum.GetNames(typeof(StaticEditorFlags)).Length - 1) - 1;\n\n                goFlags = flagValue ?\n                    goFlags | changedFlags :\n                    goFlags & ~changedFlags;\n                GameObjectUtility.SetStaticEditorFlags(go, (StaticEditorFlags)goFlags);\n            }\n\n            return true;\n        }\n\n        static void GetObjectsRecurse(Transform root, List<GameObject> arr)\n        {\n            arr.Add(root.gameObject);\n            foreach (Transform t in root)\n                GetObjectsRecurse(t, arr);\n        }\n\n        public static GameObject[] GetObjects(Object[] gameObjects, bool includeChildren)\n        {\n            List<GameObject> allObjects = new List<GameObject>();\n            if (!includeChildren)\n            {\n                foreach (GameObject go in gameObjects)\n                    allObjects.Add(go);\n            }\n            else\n            {\n                foreach (GameObject go in gameObjects)\n                    GetObjectsRecurse(go.transform, allObjects);\n            }\n            return allObjects.ToArray();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneObjectIdentifier.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [Serializable]\n    [NativeHeader(\"Editor/Src/SceneObjectIdentifier.h\")]\n    struct SceneObjectIdentifier : IEquatable<SceneObjectIdentifier>, IComparable<SceneObjectIdentifier>\n    {\n        internal ulong TargetObject;\n        internal ulong TargetPrefab;\n\n        public int CompareTo(SceneObjectIdentifier other)\n        {\n            if (TargetObject != other.TargetObject)\n                return TargetObject.CompareTo(other.TargetObject);\n            if (TargetPrefab != other.TargetPrefab)\n                return TargetPrefab.CompareTo(other.TargetPrefab);\n            return 0;\n        }\n\n        public bool Equals(SceneObjectIdentifier other)\n        {\n            return TargetObject == other.TargetObject && TargetPrefab == other.TargetPrefab;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneView/CameraFlyModeContext.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    enum SceneInputAxis : int\n    {\n        Right = 0,\n        Up = 1,\n        Forward = 2,\n        Left = 3,\n        Down = 4,\n        Backward = 5\n    }\n\n    static class SceneNavigationInput\n    {\n        static Vector3 m_PreviousVector;\n        public static float deltaTime => s_Timer.Update();\n        static TimeHelper s_Timer = new TimeHelper();\n        static readonly MovementVector s_CurrentInputVector = new MovementVector();\n\n        public static bool moving => !Mathf.Approximately(currentInputVector.sqrMagnitude, 0f);\n        public static Vector3 currentInputVector => s_CurrentInputVector.direction;\n        public static MovementVector input => s_CurrentInputVector;\n\n        // helper class keeps track of the last pressed direction key per-axis. this allows fps view to continue working\n        // when inverse keys on the same axis are pressed and released simultaneously.\n        public class MovementVector\n        {\n            // x, y, z, -x, -y, -z\n            readonly bool[] m_Pressed = new bool[6] { false, false, false, false, false, false };\n            Vector3 m_Direction = Vector3.zero;\n\n            public Vector3 direction => m_Direction;\n\n            static SceneInputAxis InverseAxis(SceneInputAxis i) => (int) i > 2 ? i - 3 : i + 3;\n\n            public bool this[SceneInputAxis i]\n            {\n                get => m_Pressed[(int) i];\n\n                set\n                {\n                    // on key down, apply direction. on key up, check if the corresponding opposite key is pressed and\n                    // set direction to inverse if true, or 0 if no key on axis is pressed.\n                    // ReSharper disable once AssignmentInConditionalExpression\n                    if (m_Pressed[(int)i] = value)\n                        m_Direction[(int)i % 3] = (int) i > 2 ? -1 : 1;\n                    else if (m_Pressed[(int)InverseAxis(i)])\n                        m_Direction[(int)i % 3] = (int) i > 2 ? 1 : -1;\n                    else\n                        m_Direction[(int)i % 3] = 0f;\n                }\n            }\n        }\n\n        public static void Update()\n        {\n            if (moving && Mathf.Approximately(m_PreviousVector.sqrMagnitude, 0f))\n                s_Timer.Begin();\n\n            m_PreviousVector = currentInputVector;\n        }\n    }\n\n    [PriorityContext, ReserveModifiers(ShortcutModifiers.Shift)]\n    class CameraFlyModeContext : ClutchShortcutContext\n    {\n        EditorWindow m_Window;\n        public EditorWindow window\n        {\n            get => m_Window;\n            set => m_Window = value;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneView/PickingShortcutContext.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n\n\nnamespace UnityEditor\n{\n    class SceneViewPickingShortcutContext : SceneViewMotion.SceneViewContext, ShortcutManagement.IHelperBarShortcutContext\n    {\n        public override bool active => ViewHasFocusAndViewportUnderMouse && Tools.current != Tool.View;\n        public bool helperBarActive => base.active && Tools.current != Tool.View;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneView/RectSelection.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    // Handles picking/selection in the scene view (both \"click\" type and \"drag-rect\" type)\n    class RectSelection\n    {\n        public enum SelectionType { Normal, Additive, Subtractive }\n\n        Vector2 m_SelectMousePoint;\n        Vector2 m_StartPoint;\n\n        SelectionType m_CurrentSelectionType;\n\n        Object[] m_SelectionStart = null;\n        Object[] m_CurrentSelection = null;\n\n        Dictionary<GameObject, bool> m_LastSelection;\n\n        readonly SceneViewPickingShortcutContext m_SceneViewPickingShortcutContext = new SceneViewPickingShortcutContext();\n\n        public static event Action rectSelectionStarting = delegate { };\n        public static event Action rectSelectionFinished = delegate { };\n\n        bool m_IsNearestControl = false;\n\n        const string k_PickingEventCommandName = \"SceneViewPickingEventCommand\";\n        const string k_SetRectSelectionHotControlEventCommandName = \"SetRectSelectionHotControlEventCommand\";\n\n        const string k_RectSelectionNormal = \"Scene View/Box Select\";\n        const string k_RectSelectionAdditive = \"Scene View/Add Box Select\";\n        const string k_RectSelectionSubtractive = \"Scene View/Invert Box Select\";\n        const string k_PickingNormal = \"Scene View/Select\";\n        const string k_PickingAdditive = \"Scene View/Add Select\";\n        const string k_PickingSubtractive = \"Scene View/Invert Select\";\n\n        readonly int k_RectSelectionID = GUIUtility.GetPermanentControlID();\n\n        public void RegisterShortcutContext()\n        {\n            ShortcutIntegration.instance.contextManager.RegisterToolContext(m_SceneViewPickingShortcutContext);\n        }\n\n        public void UnregisterShortcutContext()\n        {\n            ShortcutIntegration.instance.contextManager.DeregisterToolContext(m_SceneViewPickingShortcutContext);\n        }\n\n        [ClutchShortcut(k_RectSelectionNormal, typeof(SceneViewPickingShortcutContext), KeyCode.Mouse0)]\n        static void OnNormalRectSelection(ShortcutArguments args)\n        {\n            if (args.context is SceneViewPickingShortcutContext ctx && ctx.window != null && ctx.window.rectSelection != null)\n                ctx.window.rectSelection.OnRectSelection(args, SelectionType.Normal, ctx.window);\n        }\n\n        [ClutchShortcut(k_RectSelectionAdditive, typeof(SceneViewPickingShortcutContext), KeyCode.Mouse0, ShortcutModifiers.Shift)]\n        static void OnAdditiveRectSelection(ShortcutArguments args)\n        {\n            if (args.context is SceneViewPickingShortcutContext ctx && ctx.window != null && ctx.window.rectSelection != null)\n                ctx.window.rectSelection.OnRectSelection(args, SelectionType.Additive, ctx.window);\n        }\n\n        [ClutchShortcut(k_RectSelectionSubtractive, typeof(SceneViewPickingShortcutContext), KeyCode.Mouse0, ShortcutModifiers.Action)]\n        static void OnSubtractiveRectSelection(ShortcutArguments args)\n        {\n            if (args.context is SceneViewPickingShortcutContext ctx && ctx.window != null && ctx.window.rectSelection != null)\n                ctx.window.rectSelection.OnRectSelection(args, SelectionType.Subtractive, ctx.window);\n        }\n\n        void OnRectSelection(ShortcutArguments args, SelectionType selectionType, SceneView view)\n        {\n            // Validating that the hotControl is either equal to 0 or k_RectSelectionID allows to only start the rect selection\n            // when no other tool overrides the shortcut key and to change modifiers while rect selecting.\n            if (args.stage == ShortcutStage.Begin && (GUIUtility.hotControl == 0 || GUIUtility.hotControl == k_RectSelectionID))\n            {\n                m_CurrentSelectionType = selectionType;\n                StartRectSelection(view);\n            }\n            else if (args.stage == ShortcutStage.End)\n            {\n                CompleteRectSelection();\n            }\n        }\n\n        [Shortcut(k_PickingNormal, typeof(SceneViewPickingShortcutContext), KeyCode.Mouse0)]\n        static void OnNormalPicking(ShortcutArguments args)\n        {\n            if (args.context is SceneViewPickingShortcutContext ctx && ctx.window != null && ctx.window.rectSelection != null)\n                ctx.window.rectSelection.DelayPicking(ctx.window, SelectionType.Normal);\n        }\n\n        [Shortcut(k_PickingAdditive, typeof(SceneViewPickingShortcutContext), KeyCode.Mouse0, ShortcutModifiers.Shift)]\n        static void OnAdditivePicking(ShortcutArguments args)\n        {\n            if (args.context is SceneViewPickingShortcutContext ctx && ctx.window != null && ctx.window.rectSelection != null)\n                ctx.window.rectSelection.DelayPicking(ctx.window, SelectionType.Additive);\n        }\n\n        [Shortcut(k_PickingSubtractive, typeof(SceneViewPickingShortcutContext), KeyCode.Mouse0, ShortcutModifiers.Action)]\n        static void OnSubtractivePicking(ShortcutArguments args)\n        {\n            if (args.context is SceneViewPickingShortcutContext ctx && ctx.window != null && ctx.window.rectSelection != null)\n                ctx.window.rectSelection.DelayPicking(ctx.window, SelectionType.Subtractive);\n        }\n\n        // Delaying the picking to a command event is necessary because some HandleUtility methods\n        // need to be called in an OnGUI.\n        void DelayPicking(SceneView sceneview, SelectionType selectionType)\n        {\n            if (sceneview == null)\n                return;\n\n            m_CurrentSelectionType = selectionType;\n            sceneview.SendEvent(EditorGUIUtility.CommandEvent(k_PickingEventCommandName));\n        }\n\n        void Pick(SelectionType selectionType, Vector2 mousePos, Event evt)\n        {\n            if (selectionType == SelectionType.Subtractive || selectionType == SelectionType.Additive)\n            {\n                // For shift, we check if EXACTLY the active GO is hovered by mouse and then subtract. Otherwise additive.\n                // For control/cmd, we check if ANY of the selected GO is hovered by mouse and then subtract. Otherwise additive.\n                // Control/cmd takes priority over shift.\n                var hovered = HandleUtility.PickObject(mousePos, false);\n\n                var handledIt = false;\n\n                // shift-click deselects only if the active GO is exactly what we clicked on\n                if (selectionType != SelectionType.Subtractive && Selection.activeObject == hovered.target)\n                {\n                    UpdateSelection(m_SelectionStart, hovered.target, SelectionType.Subtractive, false);\n                    handledIt = true;\n                }\n\n                // ctrl-click deselects everything up to prefab root, that is already selected\n                if (!handledIt && selectionType == SelectionType.Subtractive)\n                {\n                    var selectedObjects = Selection.objects;\n                    hovered.TryGetComponent<Transform>(out var hoveredTransform);\n                    var hoveredRoot = HandleUtility.FindSelectionBaseForPicking(hoveredTransform);\n                    var deselectList = new List<Object>();\n\n                    while (hovered.target != null)\n                    {\n                        foreach (var obj in selectedObjects)\n                        {\n                            if (obj.Equals(hovered.target))\n                            {\n                                deselectList.Add(hovered.target);\n                                break;\n                            }\n                        }\n\n                        if (hovered.target == hoveredRoot)\n                            break;\n\n                        if (!hovered.TryGetParent(out var parent))\n                            break;\n\n                        hovered = new PickingObject(parent.gameObject);\n                    }\n\n                    if (deselectList.Count > 0)\n                    {\n                        UpdateSelection(m_SelectionStart, deselectList.ToArray(), SelectionType.Subtractive, false);\n                        handledIt = true;\n                    }\n                }\n\n                // we did not deselect anything, so add the new thing into selection instead\n                if (!handledIt)\n                {\n                    var picked = HandleUtility.PickObject(mousePos, true);\n                    UpdateSelection(m_SelectionStart, picked.target, SelectionType.Additive, false);\n                }\n            }\n            else // With no modifier keys, we do the \"cycle through overlapped\" picking logic in SceneViewPicking.cs\n            {\n                var picked = SceneViewPicking.PickGameObject(mousePos);\n                UpdateSelection(m_SelectionStart, picked.target, selectionType, false);\n            }\n\n            evt.Use();\n        }\n\n        public void OnGUI(bool isLastActiveSceneView)\n        {\n            Event evt = Event.current;\n\n            Handles.BeginGUI();\n\n            switch (evt.GetTypeForControl(k_RectSelectionID))\n            {\n                case EventType.Layout:\n                case EventType.MouseMove:\n                    // Only add default control if the Scene view is focused. Otherwise, can\n                    // cause issues when multiple Scene views open.\n                    if (!Tools.viewToolActive && isLastActiveSceneView)\n                        HandleUtility.AddDefaultControl(k_RectSelectionID);\n                    break;\n                case EventType.MouseDown:\n                    HandleOnMouseDown(evt);\n                    break;\n                case EventType.MouseUp:\n                    HandleOnMouseUp();\n                    break;\n                case EventType.MouseDrag:\n                    if (GUIUtility.hotControl == k_RectSelectionID && m_IsNearestControl)\n                    {\n                        m_SelectMousePoint = evt.mousePosition;\n                        GameObject[] rectObjs = HandleUtility.PickRectObjects(EditorGUIExt.FromToRect(m_StartPoint, m_SelectMousePoint));\n                        m_CurrentSelection = rectObjs;\n                        bool setIt = false;\n\n                        if (m_LastSelection == null)\n                        {\n                            m_LastSelection = new Dictionary<GameObject, bool>();\n                            setIt = true;\n                        }\n\n                        setIt |= m_LastSelection.Count != rectObjs.Length;\n\n                        if (!setIt)\n                        {\n                            Dictionary<GameObject, bool> set = new Dictionary<GameObject, bool>(rectObjs.Length);\n                            foreach (GameObject g in rectObjs)\n                                set.Add(g, false);\n\n                            foreach (GameObject g in m_LastSelection.Keys)\n                            {\n                                if (!set.ContainsKey(g))\n                                {\n                                    setIt = true;\n                                    break;\n                                }\n                            }\n                        }\n\n                        if (setIt)\n                        {\n                            m_LastSelection = new Dictionary<GameObject, bool>(rectObjs.Length);\n\n                            foreach (GameObject g in rectObjs)\n                                m_LastSelection.Add(g, false);\n\n                            UpdateSelection(m_SelectionStart, rectObjs, m_CurrentSelectionType, true);\n                        }\n\n                        evt.Use();\n                    }\n                    break;\n                case EventType.KeyDown: // Escape\n                    if (evt.keyCode == KeyCode.Escape && GUIUtility.hotControl == k_RectSelectionID)\n                    {\n                        CompleteRectSelection();\n\n                        GUIUtility.hotControl = 0;\n\n                        // Set the current selection to the previous selection.\n                        Selection.objects = m_SelectionStart;\n\n                        HandleOnMouseUp();\n                    }\n                    break;\n                case EventType.Repaint:\n                    if (GUIUtility.hotControl == k_RectSelectionID && m_IsNearestControl && m_StartPoint != m_SelectMousePoint)\n                    {\n                        EditorStyles.selectionRect.Draw(EditorGUIExt.FromToRect(m_StartPoint, m_SelectMousePoint),\n                            GUIContent.none, false, false, false, false);\n                    }\n                    break;\n                case EventType.ExecuteCommand:\n                    if (evt.commandName == k_PickingEventCommandName && m_IsNearestControl)\n                    {\n                        Pick(m_CurrentSelectionType, m_StartPoint, evt);\n                    }\n                    else if (evt.commandName == k_SetRectSelectionHotControlEventCommandName)\n                    {\n                        GUIUtility.hotControl = k_RectSelectionID;\n                        evt.Use();\n                    }\n                    break;\n            }\n\n            Handles.EndGUI();\n        }\n\n        void HandleOnMouseDown(Event evt)\n        {\n            if (m_IsNearestControl)\n                m_IsNearestControl = false;\n\n            if (GUIUtility.hotControl == 0 && HandleUtility.nearestControl == k_RectSelectionID)\n            {\n                m_StartPoint = evt.mousePosition;\n                m_SelectMousePoint = m_StartPoint;\n                m_IsNearestControl = true;\n            }\n\n            m_SelectionStart = Selection.objects;\n            m_CurrentSelection = null;\n            m_LastSelection = null;\n        }\n\n        void HandleOnMouseUp()\n        {\n            if (GUIUtility.hotControl == k_RectSelectionID)\n            {\n                m_IsNearestControl = false;\n                GUIUtility.hotControl = 0;\n            }\n        }\n\n        void CompleteRectSelection()\n        {\n            ActiveEditorTracker.delayFlushDirtyRebuild = false;\n            ActiveEditorTracker.RebuildAllIfNecessary();\n            rectSelectionFinished();\n        }\n\n        void StartRectSelection(SceneView view)\n        {\n            ActiveEditorTracker.delayFlushDirtyRebuild = true;\n\n            // The hot control needs to be set in an OnGUI call.\n            view.SendEvent(EditorGUIUtility.CommandEvent(k_SetRectSelectionHotControlEventCommandName));\n\n            rectSelectionStarting();\n\n            // This is needed to update the selection in case the modifier keys changed.\n            UpdateSelection(m_SelectionStart, m_CurrentSelection, m_CurrentSelectionType, true);\n        }\n\n        void UpdateSelection(Object[] existingSelection, Object newObject, SelectionType type, bool isRectSelection)\n        {\n            Object[] objs;\n            if (newObject == null)\n            {\n                objs = new Object[0];\n            }\n            else\n            {\n                objs = new Object[1];\n                objs[0] = newObject;\n            }\n\n            UpdateSelection(existingSelection, objs, type, isRectSelection);\n        }\n\n        static void UpdateSelection(Object[] existingSelection, Object[] newObjects, SelectionType type, bool isRectSelection)\n        {\n            if (existingSelection == null || newObjects == null)\n                return;\n\n            Object[] newSelection;\n\n            switch (type)\n            {\n                case SelectionType.Additive:\n                    if (newObjects.Length > 0)\n                    {\n                        newSelection = new Object[existingSelection.Length + newObjects.Length];\n                        Array.Copy(existingSelection, newSelection, existingSelection.Length);\n                        Array.Copy(newObjects, 0, newSelection, existingSelection.Length, newObjects.Length);\n                        Object active = isRectSelection ? newSelection[0] : newObjects[0];\n                        Selection.SetSelectionWithActiveObject(newSelection, active);\n                    }\n                    else\n                    {\n                        Selection.objects = existingSelection;\n                    }\n                    break;\n\n                case SelectionType.Subtractive:\n                    Dictionary<Object, bool> set = new Dictionary<Object, bool>(existingSelection.Length);\n                    foreach (Object g in existingSelection)\n                        set.Add(g, false);\n                    foreach (Object g in newObjects)\n                    {\n                        if (set.ContainsKey(g))\n                            set.Remove(g);\n                    }\n                    newSelection = new Object[set.Keys.Count];\n                    set.Keys.CopyTo(newSelection, 0);\n                    Selection.objects = newSelection;\n                    break;\n\n                case SelectionType.Normal:\n                default:\n                    Selection.objects = newObjects;\n                    break;\n            }\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/SceneView/SceneOrientationGizmo.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor;\nusing UnityEditor.AnimatedValues;\nusing UnityEditor.Overlays;\nusing UnityEngine;\nusing UnityEngine.Experimental.Rendering;\nusing UnityEngine.UIElements;\nusing Object = UnityEngine.Object;\nusing BlendMode = UnityEngine.Rendering.BlendMode;\n\n[Overlay(typeof(SceneView), \"Orientation\", true, priority = (int)OverlayPriority.Orientation, defaultDockZone = DockZone.RightColumn, defaultDockPosition = DockPosition.Top, defaultDockIndex = 0)]\n[Icon(\"Icons/Overlays/OrientationGizmo.png\")]\nsealed class SceneOrientationGizmo : IMGUIOverlay\n{\n    static readonly Color k_PickingClearColor = Color.magenta;\n    const int kRotationSize = 100;\n    const float kRotationLockedAlpha = 0.4f;\n    const int kPerspOrthoLabelHeight = 16;\n    const string k_ShowOrientationHeader = \"overlay-show-orientation-header\";\n    const string k_ShowOrientationBackground = \"overlay-show-orientation-background\";\n\n    static Quaternion[] kDirectionRotations =\n    {\n        Quaternion.LookRotation(new Vector3(-1, 0, 0)),\n        Quaternion.LookRotation(new Vector3(0, -1, 0)),\n        Quaternion.LookRotation(new Vector3(0, 0, -1)),\n        Quaternion.LookRotation(new Vector3(1, 0, 0)),\n        Quaternion.LookRotation(new Vector3(0, 1, 0)),\n        Quaternion.LookRotation(new Vector3(0, 0, 1)),\n    };\n\n    internal static string[] kDirNames =\n    { \"Right\", \"Top\", \"Front\", \"Left\", \"Bottom\", \"Back\", \"Iso\", \"Persp\", \"2D\" };\n\n    internal static string[] kMenuDirNames =\n    { \"Free\", \"Right\", \"Top\", \"Front\", \"Left\", \"Bottom\", \"Back\", \"\", \"Perspective\", \"\", \"Show background\" };\n\n    static readonly GUIContent[] s_HandleAxisLabels =\n    {\n        new GUIContent(\"x\"), new GUIContent(\"y\"), new GUIContent(\"z\")\n    };\n\n    bool showBackGround\n    {\n        get\n        {\n            if (!EditorPrefs.HasKey(k_ShowOrientationBackground))\n                showBackGround = false;\n\n            return EditorPrefs.GetBool(k_ShowOrientationBackground);\n        }\n        set\n        {\n            if (EditorPrefs.HasKey(k_ShowOrientationBackground))\n            {\n                var currentValue = EditorPrefs.GetBool(k_ShowOrientationBackground);\n                if (currentValue == value) return;\n            }\n\n            EditorPrefs.SetBool(k_ShowOrientationBackground, value);\n            UpdateHeaderAndBackground();\n        }\n    }\n\n    int[] m_ViewDirectionControlIDs;\n    int m_CenterButtonControlID;\n    int m_RotationLockControlID;\n    int m_PerspectiveIsoControlID;\n    readonly Color k_RTBackground = new Color(1, 1, 1, 0);\n    RenderTexture m_RenderTexture;\n    Camera m_Camera;\n\n    int currentDir = 7;\n    internal AnimBool[] dirVisible = { new AnimBool(true), new AnimBool(true), new AnimBool(true) };\n\n    internal AnimBool[] dirNameVisible =\n    {\n        new AnimBool(), new AnimBool(), new AnimBool(), new AnimBool(), new AnimBool(), new AnimBool(),\n        new AnimBool(), new AnimBool(), new AnimBool()\n    };\n\n    float faded2Dgray\n    {\n        get { return dirNameVisible[8].faded; }\n    }\n\n    float fadedRotationLock\n    {\n        get { return Mathf.Lerp(kRotationLockedAlpha, 1.0f, m_RotationLocked.faded); }\n    }\n\n    AnimBool m_RotationLocked = new AnimBool();\n    AnimBool m_Visible = new AnimBool();\n\n    float fadedVisibility\n    {\n        get\n        {\n            return m_Visible.faded * fadedRotationLock;\n        }\n    }\n\n    static class Styles\n    {\n        public static GUIStyle viewLabelStyleLeftAligned = \"SC ViewLabelLeftAligned\";\n        public static GUIStyle viewLabelStyleCentered = \"SC ViewLabelCentered\";\n        public static GUIStyle viewAxisLabelStyle = \"SC ViewAxisLabel\";\n        public static GUIStyle lockStyle = \"CenteredLabel\";\n        public static GUIContent unlockedRotationIcon = EditorGUIUtility.TrIconContent(\"LockIcon\", \"Click to lock the rotation in the current direction.\");\n        public static GUIContent lockedRotationIcon = EditorGUIUtility.TrIconContent(\"LockIcon-On\", \"Click to unlock the rotation.\");\n    }\n\n    struct BlendingScope : IDisposable\n    {\n        int m_srcMode;\n        int m_dstMode;\n\n        public BlendingScope(BlendMode srcMode, BlendMode dstMode)\n        {\n            m_srcMode = (int)HandleUtility.handleMaterial.GetFloat(\"_BlendSrcMode\");\n            HandleUtility.handleMaterial.SetFloat(\"_BlendSrcMode\", (int)srcMode);\n\n            m_dstMode = (int)HandleUtility.handleMaterial.GetFloat(\"_BlendDstMode\");\n            HandleUtility.handleMaterial.SetFloat(\"_BlendDstMode\", (int)dstMode);\n        }\n\n        public void Dispose()\n        {\n            HandleUtility.handleMaterial.SetFloat(\"_BlendSrcMode\", m_srcMode);\n            HandleUtility.handleMaterial.SetFloat(\"_BlendDstMode\", m_dstMode);\n        }\n    }\n\n    public SceneOrientationGizmo()\n    {\n        collapsedChanged += OnCollapsedChanged;\n    }\n\n    void OnCollapsedChanged(bool _)\n    {\n        UpdateHeaderAndBackground();\n    }\n\n    const string k_OrientationVisibilityOff = \"orientation-visibility-off\";\n    void UpdateOverlayDisplay(bool visibility)\n    {\n        m_HasMenuEntry = visibility;\n        rootVisualElement.EnableInClassList(k_OrientationVisibilityOff, !visibility);\n    }\n\n    void UpdateHeaderAndBackground()\n    {\n        var headerElement = rootVisualElement.Q(className: \"overlay-header\");\n        if (headerElement != null)\n            if (!collapsed)\n                headerElement.BringToFront();\n            else\n                headerElement.SendToBack();\n\n        rootVisualElement.EnableInClassList(k_ShowOrientationHeader, !collapsed);\n        rootVisualElement.EnableInClassList(k_ShowOrientationBackground, !collapsed && !showBackGround);\n    }\n\n    public override void OnCreated()\n    {\n        if (!(containerWindow is SceneView view))\n        {\n            Debug.LogError(\"Scene Orientation Overlay was added to an EditorWindow that is not a Scene View.\");\n            return;\n        }\n\n        SetupRenderTexture();\n\n        // Register fade animators for cones\n        for (int i = 0; i < dirVisible.Length; i++)\n            dirVisible[i].valueChanged.AddListener(view.Repaint);\n        for (int i = 0; i < dirNameVisible.Length; i++)\n            dirNameVisible[i].valueChanged.AddListener(view.Repaint);\n\n        m_RotationLocked.valueChanged.AddListener(view.Repaint);\n        m_Visible.valueChanged.AddListener(view.Repaint);\n\n        // Set correct label to be enabled from beginning\n        int labelIndex = GetLabelIndexForView(view, view.rotation * Vector3.forward, view.orthographic);\n        for (int i = 0; i < dirNameVisible.Length; i++)\n            dirNameVisible[i].value = (i == labelIndex);\n        m_RotationLocked.value = !view.isRotationLocked;\n        m_Visible.value = (labelIndex != 8);\n\n        GameObject cameraGO = EditorUtility.CreateGameObjectWithHideFlags(\"SceneCamera\", HideFlags.HideAndDontSave, typeof(Camera));\n        m_Camera = cameraGO.GetComponent<Camera>();\n        m_Camera.enabled = false;\n        m_Camera.cameraType = CameraType.SceneView;\n\n        SwitchDirNameVisible(labelIndex);\n\n        if (m_ViewDirectionControlIDs == null)\n        {\n            m_ViewDirectionControlIDs = new int[kDirectionRotations.Length];\n            for (int i = 0; i < m_ViewDirectionControlIDs.Length; ++i)\n                m_ViewDirectionControlIDs[i] = GUIUtility.GetPermanentControlID();\n\n            m_CenterButtonControlID = GUIUtility.GetPermanentControlID();\n            m_RotationLockControlID = GUIUtility.GetPermanentControlID();\n            m_PerspectiveIsoControlID = GUIUtility.GetPermanentControlID();\n        }\n    }\n\n    public override void OnWillBeDestroyed()\n    {\n        if (m_RenderTexture != null)\n            m_RenderTexture.Release();\n        Object.DestroyImmediate(m_RenderTexture);\n        if (m_Camera != null)\n            Object.DestroyImmediate(m_Camera.gameObject);\n    }\n\n    internal override void OnContentRebuild()\n    {\n        UpdateHeaderAndBackground();\n    }\n\n    void AxisSelectors(SceneView view, Camera cam, float size, float sgn, bool hovered)\n    {\n        for (int h = kDirectionRotations.Length - 1; h >= 0; h--)\n        {\n            Quaternion q1 = kDirectionRotations[h];\n            float a = dirVisible[h % 3].faded;\n            Vector3 direction = kDirectionRotations[h] * Vector3.forward;\n            float dot = Vector3.Dot(view.camera.transform.forward, direction);\n\n            if (dot <= 0.0 && sgn > 0.0f)\n                continue;\n\n            if (dot > 0.0 && sgn < 0.0f)\n                continue;\n\n            Color c;\n            switch (h)\n            {\n                case 0:\n                    c = Handles.xAxisColor;\n                    break;\n                case 1:\n                    c = Handles.yAxisColor;\n                    break;\n                case 2:\n                    c = Handles.zAxisColor;\n                    break;\n                default:\n                    c = Handles.centerColor;\n                    break;\n            }\n\n            if (view.in2DMode)\n            {\n                c = Color.Lerp(c, Color.gray, faded2Dgray);\n            }\n\n            c.a *= a * fadedVisibility;\n\n            //Not displaying the axis when rotation is locked and axis invisible otherwise One Zero blending not working fine\n            if (!(view.isRotationLocked && c.a < Mathf.Epsilon))\n            {\n                if (QualitySettings.activeColorSpace == ColorSpace.Linear)\n                    c = c.linear;\n\n                Handles.color = c;\n\n                if (c.a <= 0.1f || view.isRotationLocked)\n                    GUI.enabled = false;\n\n                // axis widget when drawn behind label\n                if (sgn > 0 && Handles.Button(m_ViewDirectionControlIDs[h], q1 * Vector3.forward * size * -1.2f, q1,\n                    size, size * 0.7f, Handles.ConeHandleCap, hovered))\n                {\n                    if (!view.in2DMode && !view.isRotationLocked)\n                        ViewAxisDirection(view, h);\n                }\n\n                // primary axes have text labels\n                if (h < 3)\n                {\n                    GUI.color = new Color(1, 1, 1, dirVisible[h].faded * fadedVisibility);\n\n                    // Label pos is a bit further out than the end of the cone\n                    Vector3 pos = direction;\n                    // Remove some of the perspective to avoid labels in front\n                    // being much further away from the gizmo due to perspective\n                    pos += dot * view.camera.transform.forward * -0.5f;\n                    // Also remove some of the spacing difference caused by rotation\n                    pos = (pos * 0.7f + pos.normalized * 1.5f) * size;\n                    Handles.Label(-pos, s_HandleAxisLabels[h], Styles.viewAxisLabelStyle);\n                }\n\n                // axis widget when drawn in front of label\n                // Adding the hovered parameter to avoid all the axis proximity checks that are time consuming\n                // when the cursor is not hovering the Orientation Gizmo\n                if (sgn < 0 && Handles.Button(m_ViewDirectionControlIDs[h], q1 * Vector3.forward * size * -1.2f, q1,\n                    size, size * 0.7f, Handles.ConeHandleCap, hovered))\n                {\n                    if (!view.in2DMode && !view.isRotationLocked)\n                        ViewAxisDirection(view, h);\n                }\n            }\n\n            Handles.color = Color.white;\n            GUI.color = Color.white;\n            GUI.enabled = true;\n        }\n    }\n\n    void DisplayContextMenu(Rect buttonOrCursorRect, SceneView view)\n    {\n        int[] selectedItems = new int[view.orthographic ? 2 : 3];\n        selectedItems[0] = currentDir >= 6 ? 0 : currentDir + 1;\n\n        selectedItems[1] = showBackGround ? 10 : 0;\n\n        if (!view.orthographic)\n            selectedItems[2] = 8;\n\n        EditorUtility.DisplayCustomMenu(buttonOrCursorRect, kMenuDirNames, selectedItems, ContextMenuDelegate, view);\n        GUIUtility.ExitGUI();\n    }\n\n    void ContextMenuDelegate(object userData, string[] options, int selected)\n    {\n        SceneView view = userData as SceneView;\n        if (view == null)\n            return;\n\n        if (selected == 0)\n        {\n            // \"free\" selected\n            ViewFromNiceAngle(view, false);\n        }\n        else if (selected >= 1 && selected <= 6)\n        {\n            // one of axes was selected\n            int axis = selected - 1;\n            ViewAxisDirection(view, axis);\n        }\n        else if (selected == 8)\n        {\n            // perspective / ortho toggled\n            ViewSetOrtho(view, !view.orthographic);\n        }\n        else if (selected == 10)\n        {\n            showBackGround = !showBackGround;\n        }\n    }\n\n    void DrawIsoStatusSymbol(Vector3 center, SceneView view, float alpha)\n    {\n        float persp = 1 - Mathf.Clamp01(view.m_Ortho.faded * 1.2f - 0.1f);\n        Vector3 up = Vector3.up * 3;\n        Vector3 right = Vector3.right * 10;\n        Vector3 pos = center - right * 0.5f;\n\n        Handles.color = new Color(1, 1, 1, 0.6f * alpha);\n        Handles.DrawAAPolyLine(pos + up * (1 - persp), pos + right + up * (1 + persp * 0.5f));\n        Handles.DrawAAPolyLine(pos, pos + right);\n        Handles.DrawAAPolyLine(pos - up * (1 - persp), pos + right - up * (1 + persp * 0.5f));\n    }\n\n    void DrawRotationLock(SceneView view, Rect rect)\n    {\n        const float clickWidth = 24;\n        const float clickHeight = 24;\n        float lockCenterX = (rect.width / EditorGUIUtility.pixelsPerPoint) - 16;\n        float lockCenterY = 17;\n        Rect lockRect = new Rect(lockCenterX - (clickWidth / 2), lockCenterY - (clickHeight / 2), clickWidth,\n            clickHeight);\n        Color c = Handles.centerColor;\n        c.a *= m_Visible.faded;\n        if (c.a > 0.0f)\n        {\n            var prevColor = GUI.color;\n            GUI.color = c;\n            var content = (view.isRotationLocked) ? Styles.lockedRotationIcon : Styles.unlockedRotationIcon;\n            if (GUI.Button(lockRect, m_RotationLockControlID, content, Styles.lockStyle) && !view.in2DMode)\n            {\n                view.isRotationLocked = !view.isRotationLocked;\n                m_RotationLocked.target = !view.isRotationLocked;\n            }\n\n            GUI.color = prevColor;\n        }\n    }\n\n    void DrawLabels(SceneView view, Rect rect)\n    {\n        Rect labelRect = new Rect(\n            rect.width - kRotationSize + 17,\n            kRotationSize - 8,\n            kRotationSize - 17 * 2,\n            kPerspOrthoLabelHeight);\n\n        // Button (overlayed over the labels) to toggle between iso and perspective\n        if (!view.in2DMode && !view.isRotationLocked)\n        {\n            using (new EditorGUI.DisabledScope(view.viewpoint.hasActiveViewpoint))\n            {\n                if (GUI.Button(labelRect, m_PerspectiveIsoControlID, GUIContent.none, Styles.viewLabelStyleLeftAligned))\n                {\n                    if (Event.current.button == 1)\n                        DisplayContextMenu(labelRect, view);\n                    else\n                        ViewSetOrtho(view, !view.orthographic);\n                }\n            }\n        }\n\n        // Labels\n        if (Event.current.type == EventType.Repaint)\n        {\n            int index2D = 8;\n\n            // Calculate the weighted average width of the labels so we can do smart centering of the labels.\n            Rect slidingLabelRect = labelRect;\n            float width = 0;\n            float weightSum = 0;\n            for (int i = 0; i < kDirNames.Length; i++)\n            {\n                if (i == index2D) // Future proof even if we add more labels after the 2D one\n                    continue;\n                weightSum += dirNameVisible[i].faded;\n                if (dirNameVisible[i].faded > 0)\n                    width +=\n                        Styles.viewLabelStyleLeftAligned.CalcSize(EditorGUIUtility.TempContent(kDirNames[i])).x *\n                        dirNameVisible[i].faded;\n            }\n\n            if (weightSum > 0)\n                width /= weightSum;\n\n            // Offset the label rect based on the label width\n            slidingLabelRect.x += 37 - width * 0.5f;\n\n            // Round to int AFTER the floating point calculations\n            slidingLabelRect.x = Mathf.RoundToInt(slidingLabelRect.x);\n\n            // Currently selected axis label. Since they cross-fade upon selection,\n            // more than one might be drawn at the same time.\n            // First draw the regular ones - all except the 2D label. They use the slidingLabelRect.\n            for (int i = 0; i < dirNameVisible.Length && i < kDirNames.Length; i++)\n            {\n                if (i == index2D) // Future proof even if we add more labels after the 2D one\n                    continue;\n                Color c = Handles.centerColor;\n                c.a *= dirNameVisible[i].faded * fadedRotationLock;\n                if (c.a > 0.0f)\n                {\n                    GUI.color = c;\n                    GUI.Label(slidingLabelRect, kDirNames[i], Styles.viewLabelStyleLeftAligned);\n                }\n            }\n\n            // Then draw just the label for 2D. It uses the original labelRect, and with a style where the text is horizontally centered.\n            {\n                Color c = Handles.centerColor;\n                c.a *= faded2Dgray * fadedVisibility;\n                if (c.a > 0.0f)\n                {\n                    GUI.color = c;\n                    GUI.Label(labelRect, kDirNames[index2D], Styles.viewLabelStyleCentered);\n                }\n            }\n\n            // Draw the iso status symbol - the passed Vector3 is the center\n            if (faded2Dgray < 1)\n            {\n                DrawIsoStatusSymbol(new Vector3(slidingLabelRect.x - 8, slidingLabelRect.y + 8.5f, 0), view,\n                    (1 - faded2Dgray) * fadedRotationLock);\n            }\n        }\n    }\n\n    void SetupRenderTexture()\n    {\n        GraphicsFormat format = SystemInfo.IsFormatSupported(GraphicsFormat.R16G16B16A16_SFloat, GraphicsFormatUsage.Render)\n            ? GraphicsFormat.R16G16B16A16_SFloat\n            : SystemInfo.GetGraphicsFormat(DefaultFormat.LDR);\n\n        if (m_RenderTexture != null)\n        {\n            if (m_RenderTexture.graphicsFormat != format)\n                Object.DestroyImmediate(m_RenderTexture);\n        }\n\n        int size = (int)(kRotationSize * EditorGUIUtility.pixelsPerPoint);\n\n        if (m_RenderTexture == null)\n            m_RenderTexture = new RenderTexture(size, size, 24, format, 1) { hideFlags = HideFlags.HideAndDontSave };\n\n        if (m_RenderTexture.width != size || m_RenderTexture.height != size)\n        {\n            m_RenderTexture.Release();\n            m_RenderTexture.width = m_RenderTexture.height = size;\n        }\n\n        m_RenderTexture.Create();\n    }\n\n    void SetupCamera(SceneView view)\n    {\n        var scene = view.camera.transform;\n        m_Camera.CopyFrom(view.camera);\n        m_Camera.transform.rotation = scene.rotation;\n\n        m_Camera.enabled = false;\n        m_Camera.allowHDR = false;\n        m_Camera.allowMSAA = false;\n        m_Camera.clearFlags = CameraClearFlags.Color;\n        m_Camera.backgroundColor = k_PickingClearColor;\n\n        m_Camera.targetTexture = m_RenderTexture;\n        m_Camera.clearFlags = CameraClearFlags.SolidColor;\n        m_Camera.backgroundColor = Color.clear;\n\n        if (m_Camera.orthographic)\n            m_Camera.orthographicSize = .5f;\n\n        m_Camera.cullingMask = 0;\n        m_Camera.transform.position = m_Camera.transform.rotation * new Vector3(0, 0, -5);\n        m_Camera.clearFlags = CameraClearFlags.Nothing;\n        m_Camera.nearClipPlane = .1f;\n        m_Camera.farClipPlane = 10;\n        m_Camera.fieldOfView = view.m_Ortho.Fade(70, 0);\n    }\n\n    public override void OnGUI()\n    {\n        if (!(containerWindow is SceneView view))\n            return;\n\n        Rect gizmoRect = new Rect(0, 0, kRotationSize, kRotationSize);\n        GUILayoutUtility.GetRect(gizmoRect.width, gizmoRect.height + kPerspOrthoLabelHeight);\n\n        Event evt = Event.current;\n\n        if (evt.type == EventType.MouseDown && evt.button == 1\n            && !view.in2DMode\n            && !view.isRotationLocked\n            && gizmoRect.Contains(evt.mousePosition))\n        {\n            DisplayContextMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), view);\n            evt.Use();\n        }\n\n        // Usually this does nothing, but when dragging the window between monitors that have different scaling\n        // it can resize the RT as necessary.\n        SetupRenderTexture();\n        SetupCamera(view);\n\n        //Handle transparency when rotation is locked\n        using (new BlendingScope(\n            view.isRotationLocked ? BlendMode.One : BlendMode.SrcAlpha,\n            view.isRotationLocked ? BlendMode.Zero : BlendMode.OneMinusSrcAlpha))\n        {\n            using (new GUI.GroupScope(gizmoRect))\n            {\n                var temp = RenderTexture.active;\n                Handles.SetCamera(gizmoRect, m_Camera);\n\n                if (evt.type == EventType.Repaint)\n                {\n                    RenderTexture.active = m_RenderTexture;\n                    GL.Clear(false, true, k_RTBackground);\n                    Handles.ClearCamera(gizmoRect, m_Camera);\n                    GUIClip.Internal_PushParentClip(Matrix4x4.identity, GUIClip.GetParentMatrix(), gizmoRect);\n                }\n\n                DoOrientationHandles(view, m_Camera, gizmoRect.Contains(evt.mousePosition));\n\n                if (evt.type == EventType.Repaint)\n                    GUIClip.Internal_PopParentClip();\n\n                RenderTexture.active = temp;\n            }\n\n            GUI.Label(gizmoRect, m_RenderTexture);\n\n            Rect labelRect = gizmoRect;\n            labelRect.y += gizmoRect.height;\n            DrawLabels(view, labelRect);\n        }\n    }\n\n    void DoOrientationHandles(SceneView view, Camera camera, bool isMouseHovering)\n    {\n        Handles.BeginGUI();\n        DrawRotationLock(view, camera.pixelRect);\n        Handles.EndGUI();\n\n        // animate visibility of three axis widgets\n        for (int i = 0; i < 3; ++i)\n        {\n            Vector3 direction = kDirectionRotations[i] * Vector3.forward;\n            dirVisible[i].target = Mathf.Abs(Vector3.Dot(camera.transform.forward, direction)) < 0.9f;\n        }\n\n        float size = HandleUtility.GetHandleSize(Vector3.zero) * .2f;\n\n        // Do axes behind the center one\n        AxisSelectors(view, camera, size, -1.0f, isMouseHovering);\n\n        // Do center handle\n        Color centerColor = Handles.centerColor;\n        centerColor = Color.Lerp(centerColor, Color.gray, faded2Dgray);\n        centerColor.a *= fadedVisibility;\n        if (centerColor.a <= 0.1f || view.isRotationLocked)\n            GUI.enabled = false;\n\n        Handles.color = centerColor;\n        if (Handles.Button(m_CenterButtonControlID, Vector3.zero, Quaternion.identity, size * 0.8f, size,\n            Handles.CubeHandleCap) && !view.in2DMode && !view.isRotationLocked)\n        {\n            if (Event.current.clickCount == 2)\n                view.FrameSelected();\n            else\n            {\n                // If middle-click or shift-click, choose a perspective view from a nice angle,\n                // similar to in Unity 3.5.\n                if (Event.current.shift || Event.current.button == 2)\n                    ViewFromNiceAngle(view, true);\n                // Else, toggle perspective\n                else\n                    ViewSetOrtho(view, !view.orthographic);\n            }\n        }\n\n        // Do axes in front of the center one\n        AxisSelectors(view, camera, size, 1.0f, isMouseHovering);\n\n        GUI.enabled = true;\n\n        if (!view.in2DMode && !view.isRotationLocked)\n        {\n            // Swipe handling\n            if (Event.current.type == EditorGUIUtility.swipeGestureEventType)\n            {\n                // Get swipe dir as Vector3\n                Event evt = Event.current;\n                Vector3 swipeDir;\n                if (evt.delta.y > 0)\n                    swipeDir = Vector3.up;\n                else if (evt.delta.y < 0)\n                    swipeDir = -Vector3.up;\n                else if (evt.delta.x < 0) // delta x inverted for some reason\n                    swipeDir = Vector3.right;\n                else\n                    swipeDir = -Vector3.right;\n\n                // Inverse swipe dir, so swiping down will go to top view etc.\n                // This is consistent with how we do orbiting, where moving the mouse down sees the object more from above etc.\n                // Also, make swipe dir point almost 45 degrees in towards the camera.\n                // This means the swipe will pick the closest axis in the swiped direction,\n                // instead of picking the one closest to being 90 degrees away.\n                Vector3 goalVector = -swipeDir - Vector3.forward * 0.9f;\n\n                // Transform swipe dir by camera transform, so up is camera's local up, etc.\n                goalVector = view.camera.transform.TransformDirection(goalVector);\n\n                // Get global axis that's closest to the swipe dir vector\n                float bestDotProduct = 0;\n                int dir = 0;\n                for (int i = 0; i < 6; i++)\n                {\n                    // Note that kDirectionRotations are not the forward direction of each dir;\n                    // it's the back direction *towards* the camera.\n                    float dotProduct = Vector3.Dot(kDirectionRotations[i] * -Vector3.forward, goalVector);\n                    if (dotProduct > bestDotProduct)\n                    {\n                        bestDotProduct = dotProduct;\n                        dir = i;\n                    }\n                }\n\n                // Look along chosen axis\n                ViewAxisDirection(view, dir);\n                Event.current.Use();\n            }\n        }\n    }\n\n    internal void ViewAxisDirection(SceneView view, int dir, bool ortho)\n    {\n        view.LookAt(view.pivot, kDirectionRotations[dir], view.size, ortho);\n        // Set label to according direction\n        SwitchDirNameVisible(dir);\n    }\n\n    internal void ViewAxisDirection(SceneView view, int dir)\n    {\n        // If holding shift or clicking with middle mouse button, orthographic is enforced, otherwise not altered.\n        // Note: This function can also be called from a context menu where Event.current is null.\n        bool ortho = view.orthographic ||\n            Event.current != null && (Event.current.shift || Event.current.button == 2);\n\n        ViewAxisDirection(view, dir, ortho);\n    }\n\n    internal void ViewSetOrtho(SceneView view, bool ortho)\n    {\n        view.LookAt(view.pivot, view.rotation, view.size, ortho);\n    }\n\n    internal void ViewSetUnityDefault(SceneView view)\n    {\n        // Unity default point of view\n        view.LookAt(view.pivot, Quaternion.LookRotation(new Vector3(-1, -.7f, -1)), view.size, view.orthographic);\n    }\n\n    internal void ViewSetMayaDefault(SceneView view)\n    {\n        // Maya default point of view\n        view.LookAt(view.pivot, Quaternion.LookRotation(new Vector3(1, -.7f, -1)), view.size, view.orthographic);\n    }\n\n    internal void ViewSetMaxDefault(SceneView view)\n    {\n        // 3DSMax default point of view\n        view.LookAt(view.pivot, Quaternion.LookRotation(new Vector3(1, -.7f, 1)), view.size, view.orthographic);\n    }\n\n    internal void UpdateGizmoLabel(SceneView view, Vector3 direction, bool ortho)\n    {\n        SwitchDirNameVisible(GetLabelIndexForView(view, direction, ortho));\n    }\n\n    internal int GetLabelIndexForView(SceneView view, Vector3 direction, bool ortho)\n    {\n        if (!view.in2DMode)\n        {\n            // If the view is axis aligned, find the correct axis.\n            if (IsAxisAligned(direction))\n                for (int i = 0; i < 6; i++)\n                    if (Vector3.Dot(kDirectionRotations[i] * Vector3.forward, direction) > 0.9f)\n                        return i;\n\n            // If the view is not axis aligned, set label to Iso or Persp.\n            return ortho ? 6 : 7;\n        }\n\n        return 8; // 2D mode\n    }\n\n    internal void ViewFromNiceAngle(SceneView view, bool forcePerspective)\n    {\n        // Use dir that's the same as the current one in the x-z plane, but placed a bit above middle vertically.\n        // (Same as old dir except it had the x-z dir fixed.)\n        Vector3 dir = view.rotation * Vector3.forward;\n        dir.y = 0;\n        if (dir == Vector3.zero)\n            // When the view is top or bottom, the closest nice view is to look approx. towards z.\n            dir = Vector3.forward;\n        else\n            // Otherwise pick dir based on existing dir.\n            dir = dir.normalized;\n        // Look at object a bit from above.\n        dir.y = -0.5f;\n\n        bool ortho = forcePerspective ? false : view.orthographic;\n        view.LookAt(view.pivot, Quaternion.LookRotation(dir), view.size, ortho);\n        SwitchDirNameVisible(ortho ? 6 : 7);\n    }\n\n    bool IsAxisAligned(Vector3 v)\n    {\n        return (Mathf.Abs(v.x * v.y) < 0.0001f && Mathf.Abs(v.y * v.z) < 0.0001f && Mathf.Abs(v.z * v.x) < 0.0001f);\n    }\n\n    void SwitchDirNameVisible(int newVisible)\n    {\n        if (newVisible == currentDir)\n            return;\n\n        dirNameVisible[currentDir].target = false;\n        currentDir = newVisible;\n        dirNameVisible[currentDir].target = true;\n\n        // Fade whole Scene View Gizmo in / out when switching 2D mode.\n        if (newVisible == 8)\n        {\n            UpdateOverlayDisplay(false);\n            m_Visible.speed = 0.3f;\n        }\n        else\n        {\n            UpdateOverlayDisplay(true);\n            m_Visible.speed = 2f;\n        }\n\n        m_Visible.target = (newVisible != 8);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneView/SceneView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Linq;\nusing System.Linq.Expressions;\nusing System.Reflection;\nusing UnityEditor.Actions;\nusing UnityEditor.AnimatedValues;\nusing UnityEditor.SceneManagement;\nusing UnityEditor.ShortcutManagement;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Profiling;\nusing UnityEngine.Rendering;\nusing UnityEngine.Experimental.Rendering;\nusing UnityEngine.SceneManagement;\nusing Object = UnityEngine.Object;\nusing RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute;\nusing UnityEditor.EditorTools;\nusing UnityEditor.Overlays;\nusing UnityEditor.Profiling;\nusing UnityEditor.UIElements;\nusing UnityEngine.Serialization;\nusing UnityEngine.UIElements;\nusing Component = UnityEngine.Component;\nusing static UnityEditor.SceneViewMotion;\n\nnamespace UnityEditor\n{\n    [EditorWindowTitle(title = \"Scene\", useTypeNameAsIconName = true)]\n    public partial class SceneView : SearchableEditorWindow, IHasCustomMenu, ISupportsOverlays\n    {\n        [Serializable]\n        public struct CameraMode\n        {\n            internal CameraMode(DrawCameraMode drawMode, string name, string section, bool show = true)\n            {\n                this.drawMode = drawMode;\n                this.name = name;\n                this.section = section;\n                this.show = show;\n            }\n\n            public DrawCameraMode drawMode;\n            public string name;\n            public string section;\n            internal bool show;\n\n            public static bool operator==(CameraMode a, CameraMode z)\n            {\n                return a.drawMode == z.drawMode && a.name == z.name && a.section == z.section;\n            }\n\n            public static bool operator!=(CameraMode a, CameraMode z)\n            {\n                return !(a == z);\n            }\n\n            public override bool Equals(System.Object otherObject)\n            {\n                if (ReferenceEquals(otherObject, null))\n                    return false;\n                if (!(otherObject is CameraMode))\n                    return false;\n                return this == (CameraMode)otherObject;\n            }\n\n            public override int GetHashCode()\n            {\n                return ToString().GetHashCode();\n            }\n\n            public override string ToString()\n            {\n                return string.Format(\"{0}||{1}||{2}\", drawMode, name, section);\n            }\n        }\n\n        static SceneView s_LastActiveSceneView;\n\n        [RequiredByNativeCode]\n        internal static DrawCameraMode[] GetInteractiveDrawCameraModeValues()\n        {\n            List<DrawCameraMode> drawCameraModes = new List<DrawCameraMode>();\n            foreach (SceneView sceneView in SceneView.sceneViews)\n            {\n                if (sceneView.usesInteractiveLightBakingData)\n                    drawCameraModes.Add(sceneView.cameraMode.drawMode);\n            }\n            return drawCameraModes.ToArray();\n        }\n\n        internal static bool NeedsInteractiveBaking()\n        {\n            foreach (SceneView sceneView in SceneView.sceneViews)\n            {\n                if (sceneView.usesInteractiveLightBakingData)\n                    return true;\n            }\n            return false;\n        }\n\n        static string GetLegacyOverlayId(OverlayWindow overlayData)\n        {\n            return \"legacy-overlay::\" + overlayData.title.text;\n        }\n\n        internal void ShowLegacyOverlay(OverlayWindow overlayData)\n        {\n            var overlay = overlayCanvas.GetOrCreateOverlay<LegacyOverlay>(GetLegacyOverlayId(overlayData));\n\n            if (overlay != null)\n            {\n                overlay.displayName = overlayData.title.text;\n                overlay.data = overlayData;\n                overlay.showRequested = true;\n            }\n        }\n\n        void LegacyOverlayPreOnGUI()\n        {\n            if (Event.current.type == EventType.Layout)\n                foreach (var overlay in overlayCanvas.overlays)\n                    if(overlay is LegacyOverlay legacyOverlay)\n                        legacyOverlay.showRequested = false;\n        }\n\n        public static Action<SceneView, SceneView> lastActiveSceneViewChanged;\n\n        static SceneView s_CurrentDrawingSceneView;\n\n        public static SceneView lastActiveSceneView\n        {\n            get\n            {\n                if (s_LastActiveSceneView == null && s_SceneViews.Count > 0)\n                    lastActiveSceneView = s_SceneViews[0] as SceneView;\n                return s_LastActiveSceneView;\n            }\n\n            private set\n            {\n                if (value == s_LastActiveSceneView)\n                    return;\n                var oldValue = s_LastActiveSceneView;\n                s_LastActiveSceneView = value;\n                lastActiveSceneViewChanged?.Invoke(oldValue, value);\n                MoveOverlaysToActiveView(oldValue, value);\n            }\n        }\n\n        public static SceneView currentDrawingSceneView { get { return s_CurrentDrawingSceneView; } }\n\n        internal static readonly PrefColor kSceneViewBackground = new PrefColor(\"Scene/Background\", 0.278431f, 0.278431f, 0.278431f, 1);\n        internal static readonly PrefColor kSceneViewPrefabBackground = new PrefColor(\"Scene/Background for Prefabs\", 0.132f, 0.231f, 0.330f, 1);\n        static readonly PrefColor kSceneViewWire = new PrefColor(\"Scene/Wireframe\", 0.0f, 0.0f, 0.0f, 0.5f);\n        static readonly PrefColor kSceneViewWireOverlay = new PrefColor(\"Scene/Wireframe Overlay\", 0.0f, 0.0f, 0.0f, 0.25f);\n        static readonly PrefColor kSceneViewSelectedOutline = new PrefColor(\"Scene/Selected Outline\", 255.0f / 255.0f, 102.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f);\n        static readonly PrefColor kSceneViewSelectedSubmeshOutline = new PrefColor(\"Scene/Selected Material Highlight\", 200.0f / 255.0f, 0f / 255.0f, 0f / 255.0f, 100.0f / 255.0f);\n        static readonly PrefColor kSceneViewSelectedChildrenOutline = new PrefColor(\"Scene/Selected Children Outline\", 94.0f / 255.0f, 119.0f / 255.0f, 155.0f / 255.0f, 0.0f / 255.0f);\n        static readonly PrefColor kSceneViewSelectedWire = new PrefColor(\"Scene/Wireframe Selected\", 94.0f / 255.0f, 119.0f / 255.0f, 155.0f / 255.0f, 64.0f / 255.0f);\n\n        internal static Color kSceneViewFrontLight = new Color(0.769f, 0.769f, 0.769f, 1);\n        internal static Color kSceneViewUpLight = new Color(0.212f, 0.227f, 0.259f, 1);\n        internal static Color kSceneViewMidLight = new Color(0.114f, 0.125f, 0.133f, 1);\n        internal static Color kSceneViewDownLight = new Color(0.047f, 0.043f, 0.035f, 1);\n\n        const string k_StyleCommon = \"StyleSheets/SceneView/SceneViewCommon.uss\";\n        const string k_StyleDark = \"StyleSheets/SceneView/SceneViewDark.uss\";\n        const string k_StyleLight = \"StyleSheets/SceneView/SceneViewLight.uss\";\n\n        public static Color selectedOutlineColor => kSceneViewSelectedOutline.Color;\n        public bool isUsingSceneFiltering => UseSceneFiltering();\n\n        internal static SavedBool s_PreferenceIgnoreAlwaysRefreshWhenNotFocused = new SavedBool(\"SceneView.ignoreAlwaysRefreshWhenNotFocused\", false);\n        internal static SavedBool s_PreferenceEnableFilteringWhileSearching = new SavedBool(\"SceneView.enableFilteringWhileSearching\", true);\n        internal static SavedBool s_PreferenceEnableFilteringWhileLodGroupEditing = new SavedBool(\"SceneView.enableFilteringWhileLodGroupEditing\", true);\n\n        internal static SavedFloat s_DrawModeExposure = new SavedFloat(\"SceneView.drawModeExposure\", 0.0f);\n        private static SavedBool s_DrawBackfaceHighlights = new SavedBool(\"SceneView.drawBackfaceHighlights\", false);\n        internal static event Action<bool> onDrawBackfaceHighlightsChanged;\n\n        [RequiredByNativeCode]\n        internal static float GetDrawModeExposure()\n        {\n            return SceneView.s_DrawModeExposure;\n        }\n\n        [RequiredByNativeCode]\n        internal static bool GetDrawBackfaceHighlights()\n        {\n            return SceneView.s_DrawBackfaceHighlights;\n        }\n\n        internal static void SetDrawBackfaceHighlights(bool value)\n        {\n            if (value != SceneView.s_DrawBackfaceHighlights.value)\n            {\n                SceneView.s_DrawBackfaceHighlights.value = value;\n                onDrawBackfaceHighlightsChanged?.Invoke(value);\n            }\n        }\n\n        static readonly HashSet<DrawCameraMode> s_ShowExposureDrawCameraModes = new HashSet<DrawCameraMode>()\n        {\n            DrawCameraMode.BakedEmissive, DrawCameraMode.BakedLightmap,\n            DrawCameraMode.RealtimeEmissive, DrawCameraMode.RealtimeIndirect\n        };\n        internal bool showExposureSettings => s_ShowExposureDrawCameraModes.Contains(this.cameraMode.drawMode);\n\n        static readonly HashSet<DrawCameraMode> s_ShowLightmapResolutionDrawCameraModes = new HashSet<DrawCameraMode>()\n        {\n            DrawCameraMode.BakedEmissive, DrawCameraMode.RealtimeEmissive,\n            DrawCameraMode.BakedLightmap,  DrawCameraMode.RealtimeIndirect,\n            DrawCameraMode.BakedDirectionality, DrawCameraMode.RealtimeDirectionality,\n            DrawCameraMode.BakedAlbedo, DrawCameraMode.RealtimeAlbedo,\n            DrawCameraMode.BakedCharting, DrawCameraMode.RealtimeCharting,\n            DrawCameraMode.BakedTexelValidity, DrawCameraMode.BakedUVOverlap,\n            DrawCameraMode.ShadowMasks, DrawCameraMode.Systems,\n            DrawCameraMode.GIContributorsReceivers, DrawCameraMode.BakedLightmapCulling,\n            DrawCameraMode.BakedIndices, DrawCameraMode.LightOverlap,\n        };\n        internal bool showLightmapResolutionToggle => s_ShowLightmapResolutionDrawCameraModes.Contains(this.cameraMode.drawMode);\n\n        internal bool showBackfaceHighlightsToggle => this.showLightmapResolutionToggle;\n\n        static readonly HashSet<DrawCameraMode> s_ShowInteractiveLightBakingToggleCameraModes = new HashSet<DrawCameraMode>()\n        {\n            DrawCameraMode.BakedLightmap, DrawCameraMode.BakedDirectionality,\n            DrawCameraMode.ShadowMasks, DrawCameraMode.BakedAlbedo,\n            DrawCameraMode.BakedEmissive, DrawCameraMode.BakedCharting,\n            DrawCameraMode.BakedTexelValidity, DrawCameraMode.BakedUVOverlap,\n            DrawCameraMode.BakedIndices, DrawCameraMode.LightOverlap,\n        };\n        internal bool currentDrawModeMayUseInteractiveLightBakingData => s_ShowInteractiveLightBakingToggleCameraModes.Contains(this.cameraMode.drawMode);\n\n        internal bool showLightingVisualizationPanel => this.showExposureSettings || this.showBackfaceHighlightsToggle || this.showLightmapResolutionToggle || this.currentDrawModeMayUseInteractiveLightBakingData;\n\n        internal static Transform GetDefaultParentObjectIfSet()\n        {\n            Transform parentObject = null;\n            var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();\n            string activeSceneGUID = prefabStage != null ? prefabStage.scene.guid : EditorSceneManager.GetActiveScene().guid;\n            int id = SceneHierarchy.GetDefaultParentForSession(activeSceneGUID);\n            if (id != 0)\n            {\n                var objectFromInstanceID = EditorUtility.InstanceIDToObject(id) as GameObject;\n                parentObject = objectFromInstanceID?.gameObject?.transform;\n            }\n\n            return parentObject;\n        }\n\n        static void OnSelectedObjectWasDestroyed(int unused)\n        {\n            s_ActiveEditorsDirty = true;\n            s_SelectionCacheDirty = true;\n        }\n\n        static void OnNonSelectedObjectWasDestroyed(int instanceID)\n        {\n            if ((!s_ActiveEditorsDirty) || (!s_SelectionCacheDirty))\n            {\n                if (s_CachedChildRenderersForOutliningHashSet != null && s_CachedChildRenderersForOutliningHashSet.Contains(instanceID))\n                {\n                    s_ActiveEditorsDirty = true;\n                    s_SelectionCacheDirty = true;\n                }\n            }\n        }\n\n        static void OnEditorTrackerRebuilt()\n        {\n            s_ActiveEditorsDirty = true;\n            s_SelectionCacheDirty = true;\n        }\n\n        internal static void SetActiveEditorsDirty(bool forceRepaint = false)\n        {\n            s_ActiveEditorsDirty = true;\n            //Needs to force repaint the scene in case the inspector :\n            //- switched from Normal to Debug mode (or inverse)\n            //- visible inspector changed and inspector modes changed\n            if(forceRepaint)\n                RepaintAll();\n        }\n\n        static List<Editor> s_ActiveEditors = new List<Editor>();\n\n        static bool s_ActiveEditorsDirty;\n        static bool s_SelectionCacheDirty;\n\n        internal static IEnumerable<Editor> activeEditors\n        {\n            get\n            {\n                CollectActiveEditors();\n                return s_ActiveEditors;\n            }\n        }\n\n        static void CollectActiveEditors()\n        {\n            if (!s_ActiveEditorsDirty)\n                return;\n\n            s_ActiveEditorsDirty = false;\n            s_ActiveEditors.Clear();\n\n            bool activeSharedTracker = false;\n            foreach (var inspector in InspectorWindow.GetInspectors())\n            {\n                if(inspector.isLocked)\n                {\n                    foreach (var editor in inspector.tracker.activeEditors)\n                        s_ActiveEditors.Add(editor);\n                }\n                else if(!activeSharedTracker\n                    &&  inspector.isVisible\n                    &&  inspector.inspectorMode == InspectorMode.Normal)\n                {\n                    activeSharedTracker = true;\n                    foreach (var editor in inspector.tracker.activeEditors)\n                        s_ActiveEditors.Add(editor);\n                }\n            }\n\n            //Just a fallback in case no editor is visible or locked\n            if(!activeSharedTracker)\n            {\n                if (s_SharedTracker == null)\n                    s_SharedTracker = ActiveEditorTracker.sharedTracker;\n\n                foreach (var editor in s_SharedTracker.activeEditors)\n                    s_ActiveEditors.Add(editor);\n            }\n\n        }\n\n        [SerializeField]\n        string m_WindowGUID;\n        internal string windowGUID => m_WindowGUID;\n\n        //Used internally to set the overlay layout to the same than the previous sceneview\n        SceneView m_PreviousScene = null;\n\n        [SerializeField] bool m_Gizmos = true;\n        public bool drawGizmos\n        {\n            get => m_Gizmos;\n            set\n            {\n                if (m_Gizmos == value) return;\n\n                m_Gizmos = value;\n                drawGizmosChanged?.Invoke(value);\n            }\n        }\n\n        const float kSubmeshPingDuration = 1.0f;\n\n        internal bool isPingingObject { get; set; } = false;\n        internal float alphaMultiplier { get; set; } = 0;\n        internal int submeshOutlineMaterialId { get; set; } = 0;\n\n        Scene m_CustomScene;\n        protected internal Scene customScene\n        {\n            get { return m_CustomScene; }\n            set\n            {\n                m_CustomScene = value;\n                m_Camera.scene = m_CustomScene;\n\n                var stage = StageUtility.GetStageHandle(m_CustomScene);\n                StageUtility.SetSceneToRenderInStage(m_CustomLightsScene, stage);\n            }\n        }\n\n        [SerializeField] ulong m_OverrideSceneCullingMask;\n        internal ulong overrideSceneCullingMask\n        {\n            get { return m_OverrideSceneCullingMask; }\n            set\n            {\n                m_OverrideSceneCullingMask = value;\n                m_Camera.overrideSceneCullingMask = value;\n            }\n        }\n\n        SceneViewStageHandling m_StageHandling;\n\n        public Rect cameraViewport => cameraViewVisualElement.rect;\n\n        Transform m_CustomParentForNewGameObjects;\n        protected internal Transform customParentForDraggedObjects\n        {\n            get => customParentForNewGameObjects;\n            set => customParentForNewGameObjects = value;\n        }\n\n        internal Transform customParentForNewGameObjects\n        {\n            get => m_CustomParentForNewGameObjects;\n            set => m_CustomParentForNewGameObjects = value;\n        }\n\n        [NonSerialized]\n        static readonly Quaternion kDefaultRotation = Quaternion.LookRotation(new Vector3(-1, -.7f, -1));\n\n        const float kDefaultViewSize = 10f;\n\n        [NonSerialized]\n        static readonly Vector3 kDefaultPivot = Vector3.zero;\n\n        const float kOrthoThresholdAngle = 3f;\n        const float kOneOverSqrt2 = 0.707106781f;\n        // Don't allow scene view zoom/size to go to crazy high values, or otherwise various\n        // operations will start going to infinities etc.\n        internal const float k_MaxSceneViewSize = 3.2e34f;\n        // Limit the max draw distance to Sqrt(float.MaxValue) because transparent sorting function uses dist^2, and\n        // Asserts that values are finite.\n        internal const float k_MaxCameraFarClip = 1.844674E+19f;\n        internal const float k_MinCameraNearClip = 1e-5f;\n\n        [NonSerialized]\n        static ActiveEditorTracker s_SharedTracker;\n\n        [SerializeField]\n        bool m_SceneIsLit = true;\n\n        [Obsolete(\"m_SceneLighting has been deprecated. Use sceneLighting instead (UnityUpgradable) -> UnityEditor.SceneView.sceneLighting\", true)]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public bool m_SceneLighting = true;\n\n        public bool sceneLighting\n        {\n            get => m_SceneIsLit;\n            set\n            {\n                if (m_SceneIsLit != value)\n                {\n                    m_SceneIsLit = value;\n                    sceneLightingChanged?.Invoke(value);\n                }\n            }\n        }\n\n        public event Func<CameraMode, bool> onValidateCameraMode;\n        public event Action<CameraMode> onCameraModeChanged;\n        public event Action<bool> gridVisibilityChanged;\n        internal event Action<bool> sceneLightingChanged;\n        internal event Action<bool> sceneAudioChanged;\n        internal event Action<bool> debugDrawModesUseInteractiveLightBakingDataChanged;\n        internal event Action<bool> sceneVisActiveChanged;\n        internal event Action<bool> drawGizmosChanged;\n        internal event Action<bool> modeChanged2D;\n\n        // used by tests\n        internal bool m_WasFocused = false;\n\n        static int[] s_CachedParentRenderersForOutlining, s_CachedChildRenderersForOutlining;\n        static HashSet<int> s_CachedChildRenderersForOutliningHashSet;\n\n        [Serializable]\n        public class SceneViewState\n        {\n            [SerializeField, FormerlySerializedAs(\"showMaterialUpdate\")]\n            bool m_AlwaysRefresh;\n\n            public bool showFog = true;\n\n            // marked obsolete by @karlh 2020/4/14\n            [EditorBrowsable(EditorBrowsableState.Never)]\n            [Obsolete(\"Obsolete msg (UnityUpgradable) -> alwaysRefresh\")]\n            public bool showMaterialUpdate\n            {\n                get => m_AlwaysRefresh;\n                set => m_AlwaysRefresh = value;\n            }\n\n            public bool alwaysRefresh\n            {\n                get => m_AlwaysRefresh;\n                set => m_AlwaysRefresh = value;\n            }\n\n            public bool showClouds\n            {\n                get => m_ShowClouds;\n                set => m_ShowClouds = value;\n            }\n\n            public bool showSkybox = true;\n            public bool showFlares = true;\n            public bool showImageEffects = true;\n            public bool showParticleSystems = true;\n            public bool showVisualEffectGraphs = true;\n            bool m_ShowClouds = true;\n\n            public bool fogEnabled => fxEnabled && showFog;\n            // marked obsolete by @karlh 2020/4/14\n            [EditorBrowsable(EditorBrowsableState.Never)]\n            [Obsolete(\"Obsolete msg (UnityUpgradable) -> alwaysRefreshEnabled\")]\n            public bool materialUpdateEnabled => alwaysRefreshEnabled;\n            public bool alwaysRefreshEnabled => fxEnabled && alwaysRefresh;\n            public bool skyboxEnabled => fxEnabled && showSkybox;\n            public bool cloudsEnabled => fxEnabled && showClouds;\n            public bool flaresEnabled => fxEnabled && showFlares;\n            public bool imageEffectsEnabled => fxEnabled && showImageEffects;\n            public bool particleSystemsEnabled => fxEnabled && showParticleSystems;\n            public bool visualEffectGraphsEnabled => fxEnabled && showVisualEffectGraphs;\n\n            internal event Action<bool> fxEnableChanged;\n\n            [SerializeField]\n            bool m_FxEnabled = true;\n\n            public SceneViewState()\n            {\n            }\n\n            public SceneViewState(SceneViewState other)\n            {\n                fxEnabled = other.fxEnabled;\n                showFog = other.showFog;\n                alwaysRefresh = other.alwaysRefresh;\n                showSkybox = other.showSkybox;\n                showClouds = other.showClouds;\n                showFlares = other.showFlares;\n                showImageEffects = other.showImageEffects;\n                showParticleSystems = other.showParticleSystems;\n                showVisualEffectGraphs = other.showVisualEffectGraphs;\n            }\n\n            [Obsolete(\"IsAllOn() has been deprecated. Use allEnabled instead (UnityUpgradable) -> allEnabled\")]\n            public bool IsAllOn()\n            {\n                return allEnabled;\n            }\n\n            public bool allEnabled\n            {\n                get\n                {\n                    bool all =  showFog && alwaysRefresh && showSkybox && showClouds && showFlares && showImageEffects && showParticleSystems;\n                    if (UnityEngine.VFX.VFXManager.activateVFX)\n                        all = all && showVisualEffectGraphs;\n                    return all;\n                }\n            }\n\n            [Obsolete(\"Toggle() has been deprecated. Use SetAllEnabled() instead (UnityUpgradable) -> SetAllEnabled(*)\")]\n            public void Toggle(bool value)\n            {\n                SetAllEnabled(value);\n            }\n\n            public void SetAllEnabled(bool value)\n            {\n                showFog = value;\n                alwaysRefresh = value;\n                showSkybox = value;\n                showClouds = value;\n                showFlares = value;\n                showImageEffects = value;\n                showParticleSystems = value;\n                showVisualEffectGraphs = value;\n            }\n\n            public bool fxEnabled\n            {\n                get => m_FxEnabled;\n                set\n                {\n                    if (m_FxEnabled == value) return;\n\n                    m_FxEnabled = value;\n                    fxEnableChanged?.Invoke(value);\n                }\n            }\n        }\n\n        [SerializeField]\n        private bool m_2DMode;\n        public bool in2DMode\n        {\n            get => m_Viewpoint.hasActiveViewpoint ? m_Viewpoint.is2DViewpoint : m_2DMode;\n            set\n            {\n                if (m_2DMode != value)\n                {\n                    m_2DMode = value;\n                    On2DModeChange();\n                    modeChanged2D?.Invoke(value);\n                }\n            }\n        }\n\n        bool m_WasIn2DMode;\n\n        [SerializeField]\n        bool m_isRotationLocked = false;\n        public bool isRotationLocked\n        {\n            get => m_isRotationLocked;\n            set => m_isRotationLocked = value;\n        }\n\n        internal static List<CameraMode> userDefinedModes { get; } = new List<CameraMode>();\n\n        [SerializeField]\n        bool m_PlayAudio = false;\n\n        [Obsolete(\"m_AudioPlay has been deprecated. Use audioPlay instead (UnityUpgradable) -> audioPlay\", true)]\n        public bool m_AudioPlay = false;\n\n        public bool audioPlay\n        {\n            get => m_PlayAudio;\n\n            set\n            {\n                if (value == m_PlayAudio)\n                    return;\n                m_PlayAudio = value;\n                sceneAudioChanged?.Invoke(value);\n                RefreshAudioPlay();\n            }\n        }\n\n        static SceneView s_AudioSceneView;\n\n        [SerializeField]\n        bool m_DebugDrawModesUseInteractiveLightBakingData = false;\n\n        internal bool debugDrawModesUseInteractiveLightBakingData\n        {\n            get => m_DebugDrawModesUseInteractiveLightBakingData;\n\n            set\n            {\n                if (value == m_DebugDrawModesUseInteractiveLightBakingData)\n                    return;\n                m_DebugDrawModesUseInteractiveLightBakingData = value;\n                debugDrawModesUseInteractiveLightBakingDataChanged?.Invoke(m_DebugDrawModesUseInteractiveLightBakingData);\n\n                // Force repaint to update lightmap previews immediately\n                Lightmapping.Internal_CallLightingDataUpdatedFunctions();\n            }\n        }\n\n        internal bool usesInteractiveLightBakingData => this.debugDrawModesUseInteractiveLightBakingData && this.currentDrawModeMayUseInteractiveLightBakingData;\n\n        [SerializeField]\n        // used by Tests/EditModeAndPlayModeTests/SceneView/CameraFlyModeContextTests\n        internal AnimVector3 m_Position = new AnimVector3(kDefaultPivot);\n\n#pragma warning disable 618\n        [Obsolete(\"OnSceneFunc() has been deprecated. Use System.Action instead.\")]\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public delegate void OnSceneFunc(SceneView sceneView);\n\n        // Marked obsolete 2018-11-28\n        [Obsolete(\"onSceneGUIDelegate has been deprecated. Use duringSceneGui instead.\")]\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public static OnSceneFunc onSceneGUIDelegate;\n#pragma warning restore 618\n\n        public static event Action<SceneView> beforeSceneGui;\n        public static event Action<SceneView> duringSceneGui;\n\n        internal static event Func<SceneView, VisualElement> addCustomVisualElementToSceneView;\n\n        // Used for performance tests\n        internal static event Action<SceneView> onGUIStarted;\n        internal static event Action<SceneView> onGUIEnded;\n\n        [Obsolete(\"Use cameraMode instead\", false)]\n        public DrawCameraMode m_RenderMode = 0;\n\n        [Obsolete(\"Use cameraMode instead\", false)]\n        public DrawCameraMode renderMode\n        {\n            get => m_CameraMode.drawMode;\n            set\n            {\n                if (value == DrawCameraMode.UserDefined)\n                    throw new ArgumentException(\"Use cameraMode to set user-defined modes\");\n                cameraMode = SceneRenderModeWindow.GetBuiltinCameraMode(value);\n            }\n        }\n\n        [SerializeField]\n        CameraMode m_CameraMode;\n\n        internal SceneOrientationGizmo m_OrientationGizmo;\n\n        public CameraMode cameraMode\n        {\n            get\n            {\n                // fix for case 969889 where the toolbar is empty when we haven't fully initialized the value\n                if (string.IsNullOrEmpty(m_CameraMode.name))\n                {\n                    m_CameraMode = SceneRenderModeWindow.GetBuiltinCameraMode(m_CameraMode.drawMode);\n                }\n                return m_CameraMode;\n            }\n            set\n            {\n                if (!IsValidCameraMode(value))\n                {\n                    throw new ArgumentException(string.Format(\"The provided camera mode {0} is not registered!\", value));\n                }\n                m_CameraMode = value;\n\n                if (onCameraModeChanged != null)\n                    onCameraModeChanged(m_CameraMode);\n            }\n        }\n\n        [Obsolete(\"m_ValidateTrueMetals has been deprecated. Use validateTrueMetals instead (UnityUpgradable) -> validateTrueMetals\", true)]\n        public bool m_ValidateTrueMetals = false;\n\n        [SerializeField]\n        bool m_DoValidateTrueMetals = false;\n\n        public bool validateTrueMetals\n        {\n            get => m_DoValidateTrueMetals;\n\n            set\n            {\n                if (m_DoValidateTrueMetals == value)\n                    return;\n\n                m_DoValidateTrueMetals = value;\n                Shader.SetGlobalFloat(\"_CheckPureMetal\", m_DoValidateTrueMetals ? 1.0f : 0.0f);\n            }\n        }\n\n        [SerializeField]\n        SceneViewState m_SceneViewState;\n\n        public SceneViewState sceneViewState\n        {\n            get { return m_SceneViewState; }\n            set { m_SceneViewState = value; }\n        }\n\n        [SerializeField]\n        SceneViewGrid m_Grid;\n\n        public bool showGrid\n        {\n            get => sceneViewGrids.showGrid;\n            set => sceneViewGrids.showGrid = value;\n        }\n\n        [SerializeField]\n        internal AnimQuaternion m_Rotation = new AnimQuaternion(kDefaultRotation);\n\n        // How large an area the scene view covers (measured vertically)\n        [SerializeField]\n        AnimFloat m_Size = new AnimFloat(kDefaultViewSize);\n\n        [SerializeField]\n        internal AnimBool m_Ortho = new AnimBool();\n\n        [NonSerialized]\n        Camera m_Camera;\n\n        VisualElement m_CameraViewVisualElement;\n\n        static readonly string s_CameraRectVisualElementName = \"unity-scene-view-camera-rect\";\n\n        internal VisualElement cameraViewVisualElement\n        {\n            get\n            {\n                if (m_CameraViewVisualElement == null)\n                    m_CameraViewVisualElement = CreateCameraRectVisualElement();\n                return m_CameraViewVisualElement;\n            }\n        }\n\n        static List<Overlay> s_ActiveViewOverlays = new List<Overlay>();\n\n        [Serializable]\n        public class CameraSettings\n        {\n            const float defaultEasingDuration = .4f;\n            internal const float kAbsoluteSpeedMin = .0001f;\n            internal const float kAbsoluteSpeedMax = 10000f;\n            const float kAbsoluteEasingDurationMin = .1f;\n            const float kAbsoluteEasingDurationMax = 2f;\n\n            [SerializeField]\n            float m_Speed;\n            [SerializeField]\n            float m_SpeedNormalized;\n            [SerializeField]\n            float m_SpeedMin;\n            [SerializeField]\n            float m_SpeedMax;\n            [SerializeField]\n            bool m_EasingEnabled;\n            [SerializeField]\n            float m_EasingDuration;\n            [SerializeField]\n            bool m_AccelerationEnabled;\n\n            [SerializeField]\n            float m_FieldOfViewHorizontalOrVertical; // either horizontal or vertical depending on aspect ratio\n            [SerializeField]\n            float m_NearClip;\n            [SerializeField]\n            float m_FarClip;\n            [SerializeField]\n            bool m_DynamicClip;\n            [SerializeField]\n            bool m_OcclusionCulling;\n\n            public CameraSettings()\n            {\n                m_Speed = 1f;\n                m_SpeedNormalized = .5f;\n                m_SpeedMin = .01f;\n                m_SpeedMax = 2f;\n                m_EasingEnabled = true;\n                m_EasingDuration = defaultEasingDuration;\n                fieldOfView = kDefaultPerspectiveFov;\n                m_DynamicClip = true;\n                m_OcclusionCulling = false;\n                m_NearClip = .03f;\n                m_FarClip = 10000f;\n                m_AccelerationEnabled = true;\n            }\n\n            internal CameraSettings(CameraSettings other)\n            {\n                m_Speed = other.m_Speed;\n                m_SpeedNormalized = other.m_SpeedNormalized;\n                m_SpeedMin = other.m_SpeedMin;\n                m_SpeedMax = other.m_SpeedMax;\n                m_EasingEnabled = other.m_EasingEnabled;\n                m_EasingDuration = other.m_EasingDuration;\n                fieldOfView = other.fieldOfView;\n                m_DynamicClip = other.m_DynamicClip;\n                m_OcclusionCulling = other.m_OcclusionCulling;\n                m_NearClip = other.m_NearClip;\n                m_FarClip = other.m_FarClip;\n                m_AccelerationEnabled = other.m_AccelerationEnabled;\n            }\n\n            public float speed\n            {\n                get\n                {\n                    return m_Speed;\n                }\n                set\n                {\n                    speedNormalized = Mathf.InverseLerp(m_SpeedMin, m_SpeedMax, value);\n                }\n            }\n\n            public float speedNormalized\n            {\n                get\n                {\n                    return m_SpeedNormalized;\n                }\n                set\n                {\n                    m_SpeedNormalized = Mathf.Clamp01(value);\n                    m_Speed = Mathf.Lerp(m_SpeedMin, m_SpeedMax, m_SpeedNormalized);\n                }\n            }\n\n            public float speedMin\n            {\n                get => m_SpeedMin;\n                set => SetSpeedMinMax(value, m_SpeedMax);\n            }\n\n            public float speedMax\n            {\n                get => m_SpeedMax;\n                set => SetSpeedMinMax(m_SpeedMin, value);\n            }\n\n            // Easing is applied when starting and stopping movement. When enabled, the camera will lerp from it's\n            // current speed to the target speed over the course of `CameraSettings.easingDuration` seconds.\n            public bool easingEnabled\n            {\n                get { return m_EasingEnabled; }\n                set { m_EasingEnabled = value; }\n            }\n\n            // How many seconds should the camera take to go from stand-still to initial full speed. When setting an animated value\n            // speed, use `1 / duration`.\n            public float easingDuration\n            {\n                get\n                {\n                    return m_EasingDuration;\n                }\n                set\n                {\n                    // Clamp and round to 1 decimal point\n                    m_EasingDuration = (float)Math.Round(Mathf.Clamp(value, kAbsoluteEasingDurationMin, kAbsoluteEasingDurationMax), 1);\n                }\n            }\n\n            // When acceleration is enabled, camera speed is continuously increased while in motion. When acceleration\n            // is disabled, speed is a constant value defined by `CameraSettings.speed`\n            public bool accelerationEnabled\n            {\n                get { return m_AccelerationEnabled; }\n                set { m_AccelerationEnabled = value; }\n            }\n\n            // this ensures that the resolution the slider snaps to is sufficient given the minimum speed, and the\n            // range of appropriate values\n            internal float RoundSpeedToNearestSignificantDecimal(float value)\n            {\n                if (value <= speedMin)\n                    return speedMin;\n\n                if (value >= speedMax)\n                    return speedMax;\n\n                float rng = speedMax - speedMin;\n                int min_rnd = speedMin < .001f ? 4 : speedMin < .01f ? 3 : speedMin < .1f ? 2 : speedMin < 1f ? 1 : 0;\n                int rng_rnd = rng < .1f ? 3 : rng < 1f ? 2 : rng < 10f ? 1 : 0;\n                return (float)Math.Round(value, Mathf.Max(min_rnd, rng_rnd));\n            }\n\n            internal void SetSpeedMinMax(float min, float max)\n            {\n                // Clamp min to valid ranges\n                float minRange = min < .001f ? .0001f : min < .01f ? .001f : min < .1f ? .01f : min < 1f ? .1f : 1f;\n                min = Mathf.Clamp(min, kAbsoluteSpeedMin, kAbsoluteSpeedMax - minRange);\n                max = Mathf.Clamp(max, min + minRange, kAbsoluteSpeedMax);\n\n                m_SpeedMin = min;\n                m_SpeedMax = max;\n\n                // This will clamp the speed to the new range\n                speed = m_Speed;\n            }\n\n            internal void SetClipPlanes(float near, float far)\n            {\n                farClip = Mathf.Clamp(far, float.Epsilon, k_MaxCameraFarClip);\n                nearClip = Mathf.Max(k_MinCameraNearClip, near);\n            }\n\n            public float fieldOfView\n            {\n                get { return m_FieldOfViewHorizontalOrVertical; }\n                set { m_FieldOfViewHorizontalOrVertical = value; }\n            }\n\n            public float nearClip\n            {\n                get { return m_NearClip; }\n                set { m_NearClip = value; }\n            }\n\n            public float farClip\n            {\n                get { return m_FarClip; }\n                set { m_FarClip = value; }\n            }\n\n            public bool dynamicClip\n            {\n                get { return m_DynamicClip; }\n                set { m_DynamicClip = value; }\n            }\n\n            public bool occlusionCulling\n            {\n                get { return m_OcclusionCulling; }\n                set { m_OcclusionCulling = value; }\n            }\n        }\n\n        [SerializeField]\n        private CameraSettings m_CameraSettings;\n\n        public CameraSettings cameraSettings\n        {\n            get { return m_CameraSettings; }\n            set { m_CameraSettings = value; }\n        }\n\n        internal Vector2 GetDynamicClipPlanes()\n        {\n            float farClip = Mathf.Clamp(2000f * size, 1000f, k_MaxCameraFarClip);\n            float nearClip = Mathf.Max(k_MinCameraNearClip, farClip * 0.000005f);\n            return new Vector2(nearClip, farClip);\n        }\n\n        internal SceneViewGrid sceneViewGrids\n        {\n            get { return m_Grid; }\n        }\n\n        public void ResetCameraSettings()\n        {\n            m_CameraSettings = new CameraSettings();\n        }\n\n        // Thomas Tu: 2019-06-20. Will be marked as Obsolete.\n        // We need to deal with code dependency in packages first.\n        internal bool showGlobalGrid { get { return showGrid; } set { showGrid = value; } }\n\n        [SerializeField]\n        private Quaternion m_LastSceneViewRotation = Quaternion.identity;\n\n        public Quaternion lastSceneViewRotation\n        {\n            get\n            {\n                if (m_LastSceneViewRotation.Equals(new Quaternion(0f, 0f, 0f, 0f)))\n                    m_LastSceneViewRotation = Quaternion.identity;\n                return m_LastSceneViewRotation;\n            }\n            set { m_LastSceneViewRotation = value; }\n        }\n\n        [SerializeField]\n        private bool m_LastSceneViewOrtho;\n\n        // Cursor rect handling\n        private struct CursorRect\n        {\n            public Rect rect;\n            public MouseCursor cursor;\n            public CursorRect(Rect rect, MouseCursor cursor)\n            {\n                this.rect = rect;\n                this.cursor = cursor;\n            }\n        }\n        private static MouseCursor s_LastCursor = MouseCursor.Arrow;\n        private static readonly List<CursorRect> s_MouseRects = new List<CursorRect>();\n\n        internal static void AddCursorRect(Rect rect, MouseCursor cursor)\n        {\n            var eventType = Event.current.type;\n            if (eventType == EventType.Repaint || eventType == EventType.MouseMove)\n                s_MouseRects.Add(new CursorRect(rect, cursor));\n        }\n\n        static float GetPerspectiveCameraDistance(float objectSize, float fov)\n        {\n            //        A\n            //        |\\        We want to place camera at a\n            //        | \\       distance that, at the given FOV,\n            //        |  \\      would enclose a sphere of radius\n            //     _..+.._\\     \"size\". Here |BC|=size, and we\n            //   .'   |   '\\    need to find |AB|. ACB is a right\n            //  /     |    _C   angle, andBAC is half the FOV. So\n            // |      | _-   |  that gives: sin(BAC)=|BC|/|AB|,\n            // |      B      |  and thus |AB|=|BC|/sin(BAC).\n            // |             |\n            //  \\           /\n            //   '._     _.'\n            //      `````\n            return objectSize / Mathf.Sin(fov * 0.5f * Mathf.Deg2Rad);\n        }\n\n        public float cameraDistance\n        {\n            get\n            {\n                float res;\n                if (!camera.orthographic)\n                {\n                    float fov = m_Ortho.Fade(perspectiveFov, 0);\n                    res = GetPerspectiveCameraDistance(size, fov);\n                }\n                else\n                    res = size * 2f;\n\n                // clamp to allowed range in case scene view size was huge\n                return Mathf.Clamp(res, -k_MaxSceneViewSize, k_MaxSceneViewSize);\n            }\n        }\n\n        [System.NonSerialized]\n        Scene m_CustomLightsScene;\n        [System.NonSerialized]\n        Light[] m_Light = new Light[3];\n\n        RectSelection m_RectSelection;\n\n        internal RectSelection rectSelection => m_RectSelection;\n\n        SceneViewMotion m_SceneViewMotion;\n\n        internal SceneViewMotion sceneViewMotion => m_SceneViewMotion;\n\n        [SerializeField]\n        SceneViewViewpoint m_Viewpoint = new SceneViewViewpoint();\n\n        internal SceneViewViewpoint viewpoint => m_Viewpoint;\n\n        const float kDefaultPerspectiveFov = 60;\n\n        static ArrayList s_SceneViews = new ArrayList();\n        public static ArrayList sceneViews { get { return s_SceneViews; } }\n\n        static List<Camera> s_AllSceneCameraList = new List<Camera>();\n        static Camera[] s_AllSceneCameras = new Camera[] {};\n\n        static Material s_AlphaOverlayMaterial;\n        static Material s_DeferredOverlayMaterial;\n        static Shader s_ShowOverdrawShader;\n        static Shader s_ShowMipsShader;\n        static Shader s_ShowTextureStreamingShader;\n        static Shader s_AuraShader;\n        static Material s_FadeMaterial;\n        static Material s_ApplyFilterMaterial;\n        static Texture2D s_MipColorsTexture;\n\n        // Handle Dragging of stuff over scene view\n        //static ArrayList s_DraggedEditors = null;\n        //static GameObject[] s_PickedObject = { null };\n\n        internal static class Styles\n        {\n            public static GUIContent toolsContent = EditorGUIUtility.TrIconContent(\"SceneViewTools\", \"Hide or show the Component Editor Tools panel in the Scene view.\");\n            public static GUIContent lighting = EditorGUIUtility.TrIconContent(\"SceneviewLighting\", \"When toggled on, the Scene lighting is used. When toggled off, a light attached to the Scene view camera is used.\");\n            public static GUIContent fx = EditorGUIUtility.TrIconContent(\"SceneviewFx\", \"Toggle skybox, fog, and various other effects.\");\n            public static GUIContent audioPlayContent = EditorGUIUtility.TrIconContent(\"SceneviewAudio\", \"Toggle audio on or off.\");\n            public static GUIContent gizmosContent = EditorGUIUtility.TrTextContent(\"Gizmos\", \"Toggle visibility of all Gizmos in the Scene view\");\n            public static GUIContent gizmosDropDownContent = EditorGUIUtility.TrTextContent(\"\", \"Toggle the visibility of different Gizmos in the Scene view.\");\n            public static GUIContent mode2DContent = EditorGUIUtility.TrIconContent(\"SceneView2D\", \"When toggled on, the Scene is in 2D view. When toggled off, the Scene is in 3D view.\");\n            public static GUIContent gridXToolbarContent = EditorGUIUtility.TrIconContent(\"GridAxisX\", \"Toggle the visibility of the grid\");\n            public static GUIContent gridYToolbarContent = EditorGUIUtility.TrIconContent(\"GridAxisY\", \"Toggle the visibility of the grid\");\n            public static GUIContent gridZToolbarContent = EditorGUIUtility.TrIconContent(\"GridAxisZ\", \"Toggle the visibility of the grid\");\n            public static GUIContent metalFrameCaptureContent = EditorGUIUtility.TrIconContent(\"FrameCapture\", \"Capture the current view and open in Xcode frame debugger\");\n            public static GUIContent sceneVisToolbarButtonContent = EditorGUIUtility.TrIconContent(\"SceneViewVisibility\", \"Number of hidden objects, click to toggle scene visibility\");\n            public static GUIStyle gizmoButtonStyle;\n            public static GUIContent sceneViewCameraContent = EditorGUIUtility.TrIconContent(\"SceneViewCamera\", \"Settings for the Scene view camera.\");\n\n            static Styles()\n            {\n                gizmoButtonStyle = \"GV Gizmo DropDown\";\n            }\n        }\n\n        internal float pingStartTime { get; set; } = 0;\n\n        double m_StartSearchFilterTime = -1;\n        RenderTexture m_SceneTargetTexture;\n        int m_MainViewControlID;\n\n        public Camera camera { get { return m_Camera; } }\n\n        [SerializeField]\n        Shader m_ReplacementShader;\n        [SerializeField]\n        string m_ReplacementString;\n        [SerializeField]\n        bool m_SceneVisActive = true;\n\n        internal bool sceneVisActive\n        {\n            get => m_SceneVisActive;\n            set\n            {\n                if (m_SceneVisActive == value) return;\n\n                m_SceneVisActive = value;\n                sceneVisActiveChanged?.Invoke(value);\n            }\n        }\n\n        string m_SceneVisHiddenCount = \"0\";\n\n        public void SetSceneViewShaderReplace(Shader shader, string replaceString)\n        {\n            m_ReplacementShader = shader;\n            m_ReplacementString = replaceString;\n        }\n\n        internal bool m_ShowSceneViewWindows = false;\n        internal EditorCache m_DragEditorCache;\n\n        // While Locking the view to object, we have different behaviour for different scenarios:\n        // Smooth camera behaviour: User dragging the handles\n        // Instant camera behaviour: Position changed externally (via inspector, physics or scripts etc.)\n        internal enum DraggingLockedState\n        {\n            NotDragging, // Default state. Scene view camera is snapped to selected object instantly\n            Dragging, // User is dragging from handles. Scene view camera holds still.\n            LookAt // Temporary state after dragging or selection change, where we return scene view camera smoothly to selected object\n        }\n        DraggingLockedState m_DraggingLockedState;\n        internal DraggingLockedState draggingLocked { set { m_DraggingLockedState = value; } get { return m_DraggingLockedState; } }\n\n        [SerializeField]\n        private Object m_LastLockedObject;\n\n        [SerializeField]\n        private CameraMode m_LastDebugDrawMode = SceneRenderModeWindow.defaultCameraMode;\n        //internal for tests\n        internal CameraMode lastDebugDrawMode => m_LastDebugDrawMode;\n\n        [SerializeField]\n        bool m_ViewIsLockedToObject;\n        internal bool viewIsLockedToObject\n        {\n            get { return m_ViewIsLockedToObject; }\n            set\n            {\n                if (value)\n                    m_LastLockedObject = Selection.activeObject;\n                else\n                    m_LastLockedObject = null;\n\n                m_ViewIsLockedToObject = value;\n                draggingLocked = DraggingLockedState.LookAt;\n            }\n        }\n\n        [RequiredByNativeCode]\n        static void FrameSelectedMenuItem(bool locked)\n        {\n            var command = locked ? EventCommandNames.FrameSelectedWithLock : EventCommandNames.FrameSelected;\n\n            var win = mouseOverWindow;\n            var ret = win != null && win.SendEvent(EditorGUIUtility.CommandEvent(command));\n\n            if (ret)\n            {\n                // In case the window under the mouse handle the Focus event, it should be focused on.\n                win.Focus();\n            }\n            else\n            {\n                // Otherwise get the current focused window to handle that event.\n                win = focusedWindow;\n                ret = win != null && win.SendEvent(EditorGUIUtility.CommandEvent(command));\n            }\n\n            // if no hovered or focused window used the frame command, send the command to the last active scene view.\n            // as a special case, if the window that used the frame command was hierarchy, also send a frame event to\n            // the last active scene view.\n            if ((!ret || win is SceneHierarchyWindow) && lastActiveSceneView != null)\n                lastActiveSceneView.SendEvent(EditorGUIUtility.CommandEvent(command));\n        }\n\n        [RequiredByNativeCode]\n        public static bool FrameLastActiveSceneView()\n        {\n            if (lastActiveSceneView == null)\n                return false;\n            return lastActiveSceneView.SendEvent(EditorGUIUtility.CommandEvent(EventCommandNames.FrameSelected));\n        }\n\n        public static bool FrameLastActiveSceneViewWithLock()\n        {\n            if (lastActiveSceneView == null)\n                return false;\n            return lastActiveSceneView.SendEvent(EditorGUIUtility.CommandEvent(EventCommandNames.FrameSelectedWithLock));\n        }\n\n        private static List<Camera> GetAllSceneCamerasAsList()\n        {\n            s_AllSceneCameraList.Clear();\n            for (int i = 0; i < s_SceneViews.Count; ++i)\n            {\n                Camera cam = ((SceneView)s_SceneViews[i]).m_Camera;\n                if (cam != null)\n                    s_AllSceneCameraList.Add(cam);\n            }\n\n            return s_AllSceneCameraList;\n        }\n\n        [RequiredByNativeCode]\n        public static Camera[] GetAllSceneCameras()\n        {\n            List<Camera> newSceneCameras = GetAllSceneCamerasAsList();\n            if (newSceneCameras.Count == s_AllSceneCameras.Length)\n            {\n                bool cacheValid = true;\n                for (int i = 0; i < newSceneCameras.Count; ++i)\n                {\n                    if (!Object.ReferenceEquals(s_AllSceneCameras[i], newSceneCameras[i]))\n                    {\n                        cacheValid = false;\n                        break;\n                    }\n                }\n                if (cacheValid)\n                    return s_AllSceneCameras;\n            }\n\n            s_AllSceneCameras = newSceneCameras.ToArray();\n            return s_AllSceneCameras;\n        }\n\n        [RequiredByNativeCode]\n        public static void RepaintAll()\n        {\n            foreach (SceneView sv in s_SceneViews)\n            {\n                sv.Repaint();\n            }\n        }\n\n        internal override void SetSearchFilter(string searchFilter, SearchMode mode, bool setAll, bool delayed)\n        {\n            if (m_SearchFilter == \"\" || searchFilter == \"\")\n                m_StartSearchFilterTime = EditorApplication.timeSinceStartup;\n\n            base.SetSearchFilter(searchFilter, mode, setAll, delayed);\n        }\n\n        internal void OnLostFocus()\n        {\n            if (lastActiveSceneView == this)\n            {\n                m_SceneViewMotion.ResetMotion();\n                m_SceneViewMotion.CompleteSceneViewMotionTool();\n            }\n        }\n\n        private void OnBeforeRemovedAsTab()\n        {\n            m_PreviousScene = null;\n        }\n\n        //Internal for tests\n        internal void OnAddedAsTab()\n        {\n            var inPlayMode = (EditorApplication.isPlaying || EditorApplication.isPaused);\n            if (inPlayMode && m_Parent.vSyncEnabled)\n                m_Parent.EnableVSync(false);\n        }\n\n        public override void OnEnable()\n        {\n            baseRootVisualElement.Insert(0, prefabToolbar);\n            rootVisualElement.Add(cameraViewVisualElement);\n\n            m_SceneViewMotion = new SceneViewMotion();\n\n            rootVisualElement.RegisterCallback<MouseEnterEvent>(e => m_SceneViewMotion.viewportsUnderMouse = true);\n            rootVisualElement.RegisterCallback<MouseLeaveEvent>(e => m_SceneViewMotion.viewportsUnderMouse = false);\n            rootVisualElement.RegisterCallback<MouseEnterWindowEvent>(e => m_SceneViewMotion.viewportsUnderMouse = true);\n            rootVisualElement.RegisterCallback<MouseLeaveWindowEvent>(e => m_SceneViewMotion.viewportsUnderMouse = false);\n\n            m_OrientationGizmo = overlayCanvas.overlays.FirstOrDefault(x => x is SceneOrientationGizmo) as SceneOrientationGizmo;\n\n            titleContent = GetLocalizedTitleContent();\n\n            m_RectSelection = new RectSelection();\n\n            if (s_SceneViews.Count == 0)\n            {\n                m_SceneViewMotion.RegisterShortcutContexts();\n                m_RectSelection.RegisterShortcutContext();\n            }\n\n            m_Viewpoint.cameraLookThroughStateChanged += OnViewpointChanged;\n            m_SceneViewMotion.CompleteSceneViewMotionTool();\n            m_Viewpoint.AssignSceneView(this);\n\n            if (m_Grid == null)\n                m_Grid = new SceneViewGrid();\n\n            sceneViewGrids.OnEnable(this);\n\n            ResetGridPivot();\n\n            autoRepaintOnSceneChange = true;\n\n            m_Rotation.valueChanged.AddListener(Repaint);\n            m_Position.valueChanged.AddListener(Repaint);\n            m_Size.valueChanged.AddListener(Repaint);\n            m_Ortho.valueChanged.AddListener(Repaint);\n            sceneViewGrids.gridVisibilityChanged += GridOnGridVisibilityChanged;\n\n            wantsMouseMove = true;\n            wantsLessLayoutEvents = true;\n            wantsMouseEnterLeaveWindow = true;\n            s_SceneViews.Add(this);\n\n            UpdateHiddenObjectCount();\n\n            ObjectFactory.componentWasAdded += OnComponentWasAdded;\n            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;\n\n            EditorApplication.modifierKeysChanged += RepaintAll; // Because we show handles on shift\n            SceneVisibilityManager.visibilityChanged += VisibilityChanged;\n            SceneVisibilityManager.currentStageIsIsolated += CurrentStageIsolated;\n            ActiveEditorTracker.editorTrackerRebuilt += OnEditorTrackerRebuilt;\n            Selection.selectedObjectWasDestroyed += OnSelectedObjectWasDestroyed;\n            Selection.nonSelectedObjectWasDestroyed += OnNonSelectedObjectWasDestroyed;\n            Lightmapping.lightingDataUpdated += RepaintAll;\n\n            // UUM-102090: as m_LastDebugDrawMode was serialized with an incorrect value at some point (UUM-96180),\n            // we ensure on enable that the serialized value is correctly set.\n            if (lastDebugDrawMode.drawMode == DrawCameraMode.GIContributorsReceivers)\n                m_LastDebugDrawMode = SceneRenderModeWindow.defaultCameraMode;\n            onCameraModeChanged += delegate\n            {\n                if (cameraMode.drawMode == DrawCameraMode.ShadowCascades) sceneLighting = true;\n\n                // If this a draw mode for debugging purposes, take note of it, so we can toggle back and forth between it and the previous mode.\n                if (cameraMode.drawMode != DrawCameraMode.Textured && cameraMode.drawMode != DrawCameraMode.Wireframe && cameraMode.drawMode != DrawCameraMode.TexturedWire)\n                {\n                    m_LastDebugDrawMode = cameraMode;\n                }\n            };\n\n            m_DraggingLockedState = DraggingLockedState.NotDragging;\n\n            CreateSceneCameraAndLights();\n\n            m_WasIn2DMode = in2DMode;\n            if (in2DMode)\n                LookAt(pivot, Quaternion.identity, size, true, true);\n\n            if (m_CameraMode.drawMode == DrawCameraMode.UserDefined && !userDefinedModes.Contains(m_CameraMode))\n                AddCameraMode(m_CameraMode.name, m_CameraMode.section);\n\n            base.OnEnable();\n\n            if (SupportsStageHandling())\n            {\n                m_StageHandling = new SceneViewStageHandling(this);\n                m_StageHandling.OnEnable();\n            }\n\n            s_ActiveEditorsDirty = true;\n\n            baseRootVisualElement.styleSheets.Add(EditorGUIUtility.Load(k_StyleCommon) as StyleSheet);\n            baseRootVisualElement.styleSheets.Add(EditorGUIUtility.Load(EditorGUIUtility.isProSkin ? k_StyleDark : k_StyleLight) as StyleSheet);\n\n            s_SelectionCacheDirty = true;\n        }\n\n        IMGUIContainer m_PrefabToolbar;\n\n        IMGUIContainer prefabToolbar\n        {\n            get\n            {\n                if (m_PrefabToolbar == null)\n                {\n                    m_PrefabToolbar = new IMGUIContainer()\n                    {\n                        onGUIHandler = () =>\n                        {\n                            if (m_StageHandling != null && m_StageHandling.isShowingBreadcrumbBar)\n                            {\n                                m_PrefabToolbar.style.height = m_StageHandling.breadcrumbHeight;\n                                m_StageHandling.BreadcrumbGUI();\n                            }\n                            else\n                            {\n                                m_PrefabToolbar.style.height = 0;\n                            }\n                        },\n                        name = VisualElementUtils.GetUniqueName(\"prefab-toolbar\"),\n                        pickingMode = PickingMode.Position,\n                        viewDataKey = name,\n                        renderHints = RenderHints.ClipWithScissors\n                    };\n                    UIElementsEditorUtility.AddDefaultEditorStyleSheets(m_PrefabToolbar);\n                    m_PrefabToolbar.style.overflow = UnityEngine.UIElements.Overflow.Hidden;\n                }\n\n                return m_PrefabToolbar;\n            }\n        }\n\n        VisualElement CreateCameraRectVisualElement()\n        {\n            var root = new IMGUIContainer()\n            {\n                onGUIHandler = OnSceneGUI,\n                name = s_CameraRectVisualElementName,\n                pickingMode = PickingMode.Position,\n                viewDataKey = name,\n                renderHints = RenderHints.ClipWithScissors,\n                requireMeasureFunction = false\n            };\n\n            UIElementsEditorUtility.AddDefaultEditorStyleSheets(root);\n            root.style.overflow = Overflow.Hidden;\n            root.style.flexGrow = 1;\n\n            if (addCustomVisualElementToSceneView != null)\n            {\n                foreach (var del in addCustomVisualElementToSceneView.GetInvocationList())\n                {\n                    root.Add((VisualElement)del.DynamicInvoke(this));\n                }\n            }\n\n            return root;\n        }\n\n        void OnComponentWasAdded(Component component)\n        {\n            var renderer = component as Renderer;\n            if (renderer != null)\n                s_SelectionCacheDirty = true;\n        }\n\n        void GridOnGridVisibilityChanged(bool visible)\n        {\n            gridVisibilityChanged?.Invoke(visible);\n        }\n\n        protected virtual bool SupportsStageHandling()\n        {\n            return true;\n        }\n\n        void CurrentStageIsolated(bool isolated)\n        {\n            if (isolated)\n            {\n                m_SceneVisActive = true;\n                Repaint();\n            }\n        }\n\n        void VisibilityChanged()\n        {\n            UpdateHiddenObjectCount();\n            Repaint();\n        }\n\n        void UpdateHiddenObjectCount()\n        {\n            int hiddenGameObjects = SceneVisibilityState.GetHiddenObjectCount();\n            m_SceneVisHiddenCount = hiddenGameObjects.ToString();\n        }\n\n        public SceneView()\n        {\n            m_HierarchyType = HierarchyType.GameObjects;\n\n            // Note: Rendering for Scene view picking depends on the depth buffer of the window\n            depthBufferBits = 32;\n        }\n\n        internal void Awake()\n        {\n            if (string.IsNullOrEmpty(m_WindowGUID))\n                m_WindowGUID = GUID.Generate().ToString();\n\n            // Try copy last active scene view window settings if creating a new window\n            if (sceneViewState == null && m_CameraSettings == null && lastActiveSceneView != null)\n            {\n                CopyLastActiveSceneViewSettings();\n            }\n            else\n            {\n                if (sceneViewState == null)\n                {\n                    m_SceneViewState = new SceneViewState();\n                }\n\n                if (m_CameraSettings == null)\n                {\n                    m_CameraSettings = new CameraSettings();\n                }\n            }\n\n            if (m_2DMode || EditorSettings.defaultBehaviorMode == EditorBehaviorMode.Mode2D)\n            {\n                m_LastSceneViewRotation = Quaternion.LookRotation(new Vector3(-1, -.7f, -1));\n                m_LastSceneViewOrtho = false;\n                m_Rotation.value = Quaternion.identity;\n                m_Ortho.value = true;\n                if(!m_2DMode)\n                {\n                    m_2DMode = true;\n                    modeChanged2D?.Invoke(m_2DMode);\n                }\n\n                // Enforcing Rect tool as the default in 2D mode.\n                if (Tools.current == Tool.Move)\n                    Tools.current = Tool.Rect;\n            }\n\n            m_PreviousScene = lastActiveSceneView;\n        }\n\n        internal static void AlignCameraWithView(Camera camera)\n        {\n            if (s_SceneViews.Count >= 1)\n            {\n                var view = lastActiveSceneView;\n                if (view == null) return;\n\n                if (view.in2DMode)\n                {\n                    var sceneCamera = view.camera;\n\n                    var worldMiddle = sceneCamera.ScreenToWorldPoint(new Vector4(0f, 0f, 0f, 3f));\n                    var invMiddle = sceneCamera.transform.InverseTransformPoint(worldMiddle);\n\n                    var worldTop = sceneCamera.ScreenToWorldPoint(new Vector3(0f, sceneCamera.pixelHeight, 0.3f));\n                    var invTop = sceneCamera.transform.InverseTransformPoint(worldTop);\n\n                    var size = Mathf.Abs((invTop - invMiddle).y / 2f);\n\n                    camera.orthographicSize = size;\n\n                    var pos = sceneCamera.transform.position;\n\n                    // maintain current camera z pos as it is either a user set value, or the default from GOCreationCommands\n                    camera.transform.position = new Vector3(pos.x, pos.y, camera.transform.position.z);\n                }\n                else\n                    view.AlignWithView(camera.transform);\n            }\n        }\n\n        internal static Camera GetLastActiveSceneViewCamera()\n        {\n            SceneView view = lastActiveSceneView;\n            return view ? view.camera : null;\n        }\n\n        public override void OnDisable()\n        {\n            EditorApplication.modifierKeysChanged -= RepaintAll;\n            EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;\n            SceneVisibilityManager.visibilityChanged -= VisibilityChanged;\n            SceneVisibilityManager.currentStageIsIsolated -= CurrentStageIsolated;\n            Lightmapping.lightingDataUpdated -= RepaintAll;\n            ActiveEditorTracker.editorTrackerRebuilt -= OnEditorTrackerRebuilt;\n            Selection.selectedObjectWasDestroyed -= OnSelectedObjectWasDestroyed;\n            Selection.nonSelectedObjectWasDestroyed -= OnNonSelectedObjectWasDestroyed;\n            sceneViewGrids.gridVisibilityChanged -= GridOnGridVisibilityChanged;\n\n            sceneViewGrids.OnDisable(this);\n\n            if (viewpoint.hasActiveViewpoint)\n                viewpoint.ClearViewpoint();\n\n            if (m_Camera)\n                DestroyImmediate(m_Camera.gameObject, true);\n            if (m_Light[0])\n                DestroyImmediate(m_Light[0].gameObject, true);\n            if (m_Light[1])\n                DestroyImmediate(m_Light[1].gameObject, true);\n            if (m_Light[2])\n                DestroyImmediate(m_Light[2].gameObject, true);\n\n            EditorSceneManager.ClosePreviewScene(m_CustomLightsScene);\n\n            if (s_MipColorsTexture)\n                DestroyImmediate(s_MipColorsTexture, true);\n\n            s_SceneViews.Remove(this);\n\n            if (s_SceneViews.Count == 0)\n            {\n                m_SceneViewMotion.UnregisterShortcutContexts();\n                m_RectSelection.UnregisterShortcutContext();\n            }\n\n            if (s_LastActiveSceneView == this)\n                lastActiveSceneView = s_SceneViews.Count > 0 ? s_SceneViews[0] as SceneView : null;\n\n            CleanupEditorDragFunctions();\n            if (m_StageHandling != null)\n                m_StageHandling.OnDisable();\n            ObjectFactory.componentWasAdded -= OnComponentWasAdded;\n\n            base.OnDisable();\n        }\n\n        public void OnDestroy()\n        {\n            if (audioPlay)\n                audioPlay = false;\n        }\n\n        internal void OnPlayModeStateChanged(PlayModeStateChange state)\n        {\n            if (audioPlay)\n                audioPlay = false;\n        }\n\n        // This has to be called explicitly from SceneViewStageHandling to ensure,\n        // this happens *after* SceneViewStageHandling has updated the camera scene.\n        // Thus, we can't just register to the StageNavigationManager.instance.stageChanged\n        // event since that would not guarantee the order dependency.\n        internal void OnStageChanged(Stage previousStage, Stage newStage)\n        {\n            VisibilityChanged();\n            // audioPlay may be different in the new stage,\n            // so update regardless of whether it's on or off.\n            // Not if we're in Play Mode however, as audio preview\n            // is entirely disabled in that case.\n            if (!EditorApplication.isPlaying)\n                RefreshAudioPlay();\n        }\n\n        internal override void OnMaximized()\n        {\n            m_SceneViewMotion.CompleteSceneViewMotionTool();\n            Repaint();\n        }\n\n        internal void ToolbarSearchFieldGUI()\n        {\n            if (m_MainViewControlID != GUIUtility.keyboardControl\n                && Event.current.type == EventType.KeyDown\n                && !string.IsNullOrEmpty(m_SearchFilter)\n            )\n            {\n                switch (Event.current.keyCode)\n                {\n                    case KeyCode.UpArrow:\n                    case KeyCode.DownArrow:\n                        if (Event.current.keyCode == KeyCode.UpArrow)\n                            SelectPreviousSearchResult();\n                        else\n                            SelectNextSearchResult();\n\n                        FrameSelected(false);\n                        Event.current.Use();\n                        GUIUtility.ExitGUI();\n                        return;\n                }\n            }\n\n            EditorGUIUtility.labelWidth = 0;\n            SearchFieldGUI(EditorGUILayout.kLabelFloatMaxW);\n        }\n\n        // This method should be called after the audio play button has been toggled,\n        // and after other events that require a refresh.\n        void RefreshAudioPlay()\n        {\n            if ((s_AudioSceneView != null) && (s_AudioSceneView != this))\n            {\n                // turn *other* sceneview off\n                if (s_AudioSceneView.m_PlayAudio)\n                {\n                    s_AudioSceneView.m_PlayAudio = false;\n                    s_AudioSceneView.sceneAudioChanged?.Invoke(false);\n                    s_AudioSceneView.Repaint();\n                }\n            }\n\n            // We have to find all loaded AudioSources, not just the ones in main scenes.\n            var sources = (AudioSource[])Resources.FindObjectsOfTypeAll(typeof(AudioSource));\n            foreach (AudioSource source in sources)\n            {\n                if (EditorUtility.IsPersistent(source))\n                    continue;\n\n                if (source.playOnAwake)\n                {\n                    if (!m_PlayAudio || !StageUtility.IsGameObjectRenderedByCamera(source.gameObject, m_Camera))\n                    {\n                        source.Stop();\n                    }\n                    else\n                    {\n                        if (!source.isPlaying && source.isActiveAndEnabled)\n                            source.Play();\n                    }\n                }\n            }\n\n            // We have to find all loaded ReverbZones, not just the ones in main scenes.\n            var zones = (AudioReverbZone[])Resources.FindObjectsOfTypeAll(typeof(AudioReverbZone));\n            foreach (AudioReverbZone zone in zones)\n            {\n                if (EditorUtility.IsPersistent(zone))\n                    continue;\n\n                zone.active = m_PlayAudio && StageUtility.IsGameObjectRenderedByCamera(zone.gameObject, m_Camera);\n            }\n\n            AudioUtil.SetListenerTransform(m_PlayAudio ? m_Camera.transform : null);\n\n            s_AudioSceneView = this;\n\n\n            if (m_PlayAudio)\n            {\n                AudioMixerWindow.RepaintAudioMixerWindow();\n            }\n        }\n\n        void OnSelectionChange()\n        {\n            if (Selection.activeObject != null && m_LastLockedObject != Selection.activeObject)\n                viewIsLockedToObject = false;\n\n            m_WasFocused = false;\n\n            s_SelectionCacheDirty = true;\n\n            Repaint();\n        }\n\n        public virtual void AddItemsToMenu(GenericMenu menu)\n        {\n            if (RenderDoc.IsInstalled() && !RenderDoc.IsLoaded())\n            {\n                menu.AddItem(RenderDocUtil.LoadRenderDocMenuItem, false, RenderDoc.LoadRenderDoc);\n            }\n        }\n\n        public static void AddOverlayToActiveView<T>(T overlay) where T : Overlay\n        {\n            s_ActiveViewOverlays.Add(overlay);\n            if(lastActiveSceneView != null)\n                lastActiveSceneView.overlayCanvas.Add(overlay);\n        }\n\n        public static void RemoveOverlayFromActiveView<T>(T overlay) where T : Overlay\n        {\n            if (!s_ActiveViewOverlays.Remove(overlay))\n                return;\n            if (lastActiveSceneView != null)\n                lastActiveSceneView.overlayCanvas.Remove(overlay);\n        }\n\n        static void MoveOverlaysToActiveView(SceneView previous, SceneView active)\n        {\n            if (previous != null)\n            {\n                foreach (var overlay in s_ActiveViewOverlays)\n                    previous.overlayCanvas.Remove(overlay);\n            }\n\n            if (active != null)\n            {\n                foreach (var overlay in s_ActiveViewOverlays)\n                    active.overlayCanvas.Add(overlay);\n            }\n        }\n\n        private static bool ValidateMenuMoveToFrontOrBack(Transform[] transforms, bool isFront)\n        {\n            if (transforms.Length == 0)\n            {\n                return false;\n            }\n\n            int alreadyInPlaceCounter = 0;\n            foreach (Transform transform in transforms)\n            {\n                if (transform == null || transform.parent == null || PrefabUtility.IsPartOfNonAssetPrefabInstance(transform.parent))\n                {\n                    return false;\n                }\n\n                int alreadyInPlaceSiblingIndex = isFront ? 0 : transform.parent.childCount - 1;\n                if (transform.GetSiblingIndex() == alreadyInPlaceSiblingIndex)\n                {\n                    alreadyInPlaceCounter += 1;\n                }\n            }\n\n            return alreadyInPlaceCounter < transforms.Length;\n        }\n\n        private static void RegisterMenuMoveChildrenUndo(Transform[] transforms, string message)\n        {\n            var parents = new HashSet<Transform>();\n            foreach (Transform t in transforms)\n            {\n                if (!parents.Contains(t.parent))\n                {\n                    Undo.RegisterChildrenOrderUndo(t.parent, message);\n                    parents.Add(t.parent);\n                }\n            }\n        }\n\n        [MenuItem(\"GameObject/Set as first sibling %=\", secondaryPriority = 1)]\n        internal static void MenuMoveToFront()\n        {\n            var selectedTransforms = Selection.transforms;\n\n            RegisterMenuMoveChildrenUndo(selectedTransforms, \"Set as first sibling\");\n            foreach (Transform t in selectedTransforms)\n            {\n                t.SetAsFirstSibling();\n            }\n        }\n\n        [MenuItem(\"GameObject/Set as first sibling %=\", true)]\n        internal static bool ValidateMenuMoveToFront()\n        {\n            return ValidateMenuMoveToFrontOrBack(Selection.transforms, true);\n        }\n\n        [MenuItem(\"GameObject/Set as last sibling %-\", secondaryPriority = 2)]\n        internal static void MenuMoveToBack()\n        {\n            var selectedTransforms = Selection.transforms;\n\n            RegisterMenuMoveChildrenUndo(selectedTransforms, \"Set as last sibling\");\n            foreach (Transform t in selectedTransforms)\n            {\n                t.SetAsLastSibling();\n            }\n        }\n\n        [MenuItem(\"GameObject/Set as last sibling %-\", true)]\n        internal static bool ValidateMenuMoveToBack()\n        {\n            return ValidateMenuMoveToFrontOrBack(Selection.transforms, false);\n        }\n\n        [MenuItem(\"GameObject/Move To View %&f\", secondaryPriority = 3)]\n        internal static void MenuMoveToView()\n        {\n            if (ValidateMoveToView())\n                lastActiveSceneView.MoveToView();\n        }\n\n        [MenuItem(\"GameObject/Move To View %&f\", true)]\n        static bool ValidateMoveToView()\n        {\n            return lastActiveSceneView != null && (Selection.transforms.Length != 0);\n        }\n\n        [MenuItem(\"GameObject/Align With View %#f\", secondaryPriority = 4)]\n        internal static void MenuAlignWithView()\n        {\n            if (ValidateAlignWithView())\n                lastActiveSceneView.AlignWithView();\n        }\n\n        [MenuItem(\"GameObject/Align With View %#f\", true)]\n        internal static bool ValidateAlignWithView()\n        {\n            return lastActiveSceneView != null && (Selection.activeTransform != null);\n        }\n\n        [MenuItem(\"GameObject/Align View to Selected\", secondaryPriority = 5)]\n        internal static void MenuAlignViewToSelected()\n        {\n            if (ValidateAlignViewToSelected())\n                lastActiveSceneView.AlignViewToObject(Selection.activeTransform);\n        }\n\n        [MenuItem(\"GameObject/Align View to Selected\", true)]\n        internal static bool ValidateAlignViewToSelected()\n        {\n            return lastActiveSceneView != null && (Selection.activeTransform != null);\n        }\n\n        [MenuItem(\"GameObject/Toggle Active State &#a\", secondaryPriority = 6)]\n        internal static void ActivateSelection()\n        {\n            if (Selection.activeTransform != null)\n            {\n                GameObject[] gos = Selection.gameObjects;\n                Undo.RecordObjects(gos, \"Toggle Active State\");\n                bool val = !Selection.activeGameObject.activeSelf;\n                foreach (GameObject go in gos)\n                    go.SetActive(val);\n            }\n        }\n\n        [MenuItem(\"GameObject/Toggle Active State &#a\", true)]\n        internal static bool ValidateActivateSelection()\n        {\n            return (Selection.activeTransform != null);\n        }\n\n        static void CreateMipColorsTexture()\n        {\n            if (s_MipColorsTexture)\n                return;\n            s_MipColorsTexture = new Texture2D(32, 32, TextureFormat.RGBA32, true) {hideFlags = HideFlags.HideAndDontSave};\n            Color[] colors = new Color[6];\n            colors[0] = new Color(0.0f, 0.0f, 1.0f, 0.8f);\n            colors[1] = new Color(0.0f, 0.5f, 1.0f, 0.4f);\n            colors[2] = new Color(1.0f, 1.0f, 1.0f, 0.0f); // optimal level\n            colors[3] = new Color(1.0f, 0.7f, 0.0f, 0.2f);\n            colors[4] = new Color(1.0f, 0.3f, 0.0f, 0.6f);\n            colors[5] = new Color(1.0f, 0.0f, 0.0f, 0.8f);\n            int mipCount = Mathf.Min(6, s_MipColorsTexture.mipmapCount);\n            for (int mip = 0; mip < mipCount; ++mip)\n            {\n                int width = Mathf.Max(s_MipColorsTexture.width >> mip, 1);\n                int height = Mathf.Max(s_MipColorsTexture.height >> mip, 1);\n                Color[] cols = new Color[width * height];\n                for (int i = 0; i < cols.Length; ++i)\n                    cols[i] = colors[mip];\n                s_MipColorsTexture.SetPixels(cols, mip);\n            }\n            s_MipColorsTexture.filterMode = FilterMode.Trilinear;\n            s_MipColorsTexture.Apply(false);\n            Shader.SetGlobalTexture(\"_SceneViewMipcolorsTexture\", s_MipColorsTexture);\n        }\n\n        bool m_ForceSceneViewFiltering;\n        bool m_ForceSceneViewFilteringForLodGroupEditing;\n        bool m_ForceSceneViewFilteringForStageHandling;\n        double m_lastRenderedTime;\n\n        internal void SetSceneViewFiltering(bool enable)\n        {\n            m_ForceSceneViewFiltering = enable;\n        }\n\n        internal void SetSceneViewFilteringForLODGroups(bool enable)\n        {\n            m_ForceSceneViewFilteringForLodGroupEditing = enable;\n        }\n\n        internal void SetSceneViewFilteringForStages(bool enable)\n        {\n            m_ForceSceneViewFilteringForStageHandling = enable;\n        }\n\n        bool forceSceneViewFilteringForLodGroupEditing => m_ForceSceneViewFilteringForLodGroupEditing && s_PreferenceEnableFilteringWhileLodGroupEditing;\n\n        bool UseSceneFiltering()\n        {\n            return (!string.IsNullOrEmpty(m_SearchFilter) && s_PreferenceEnableFilteringWhileSearching) || forceSceneViewFilteringForLodGroupEditing || m_ForceSceneViewFilteringForStageHandling || m_ForceSceneViewFiltering;\n        }\n\n        internal bool SceneViewIsRenderingHDR()\n        {\n            return m_Camera != null && m_Camera.allowHDR;\n        }\n\n        void OnFocus()\n        {\n            lastActiveSceneView = this;\n        }\n\n        void HandleClickAndDragToFocus()\n        {\n            Event evt = Event.current;\n\n            if (evt.type == EventType.MouseDrag)\n                draggingLocked = DraggingLockedState.Dragging;\n            else if (GUIUtility.hotControl == 0 && draggingLocked == DraggingLockedState.Dragging)\n                draggingLocked = DraggingLockedState.LookAt;\n\n            // UUM-90436. UITK's MouseEnterEvent/MouseEnterWindowEvent callbacks that\n            // drive `viewportsUnderMouse` seem to not fire reliably when a pen tablet is used.\n            if (!sceneViewMotion.viewportsUnderMouse &&\n                (evt.type == EventType.MouseDown || evt.type == EventType.MouseMove))\n                sceneViewMotion.viewportsUnderMouse = true;\n\n            if (evt.type == EventType.MouseDown)\n            {\n                Tools.s_ButtonDown = evt.button;\n\n                if (Application.platform == RuntimePlatform.OSXEditor)\n                    Focus();\n            }\n            // this is necessary because FPS tool won't get is cleanup logic\n            // executed if another control uses the Event (i.e OnSceneGUI) (case 777346)\n            else if (evt.type == EventType.MouseUp && Tools.s_ButtonDown == evt.button)\n            {\n                Tools.s_ButtonDown = -1;\n            }\n        }\n\n        private void SetupFogAndShadowDistance(out bool oldFog, out float oldShadowDistance)\n        {\n            oldFog = RenderSettings.fog;\n            oldShadowDistance = QualitySettings.shadowDistance;\n            if (Event.current.type == EventType.Repaint)\n            {\n                if (!sceneViewState.fogEnabled)\n                    Unsupported.SetRenderSettingsUseFogNoDirty(false);\n                if (m_Camera.orthographic)\n                    Unsupported.SetQualitySettingsShadowDistanceTemporarily(QualitySettings.shadowDistance + 0.5f * cameraDistance);\n            }\n        }\n\n        private void RestoreFogAndShadowDistance(bool oldFog, float oldShadowDistance)\n        {\n            if (Event.current.type == EventType.Repaint)\n            {\n                Unsupported.SetRenderSettingsUseFogNoDirty(oldFog);\n                Unsupported.SetQualitySettingsShadowDistanceTemporarily(oldShadowDistance);\n            }\n        }\n\n        private void CreateCameraTargetTexture(Rect cameraRect, bool hdr)\n        {\n            // make sure we actually support R16G16B16A16_SFloat\n            GraphicsFormat format = (hdr && SystemInfo.IsFormatSupported(GraphicsFormat.R16G16B16A16_SFloat, GraphicsFormatUsage.Render)) ? GraphicsFormat.R16G16B16A16_SFloat : SystemInfo.GetGraphicsFormat(DefaultFormat.LDR);\n\n            if (m_SceneTargetTexture != null)\n            {\n                if (m_SceneTargetTexture.graphicsFormat != format)\n                {\n                    Object.DestroyImmediate(m_SceneTargetTexture);\n                    m_SceneTargetTexture = null;\n                }\n            }\n\n            Rect actualCameraRect = Handles.GetCameraRect(cameraRect);\n            int width = (int)Mathf.Max(1f, actualCameraRect.width);\n            int height = (int)Mathf.Max(1f, actualCameraRect.height);\n\n            if (m_SceneTargetTexture == null)\n            {\n                m_SceneTargetTexture = new RenderTexture(0, 0, format, SystemInfo.GetGraphicsFormat(DefaultFormat.DepthStencil))\n                {\n                    name = \"SceneView RT\",\n                    antiAliasing = 1,\n                    hideFlags = HideFlags.HideAndDontSave\n                };\n            }\n            if (m_SceneTargetTexture.width != width || m_SceneTargetTexture.height != height)\n            {\n                m_SceneTargetTexture.Release();\n                m_SceneTargetTexture.width = width;\n                m_SceneTargetTexture.height = height;\n            }\n            m_SceneTargetTexture.Create();\n        }\n\n        public bool IsCameraDrawModeSupported(CameraMode mode)\n        {\n            if (!Handles.IsCameraDrawModeSupported(m_Camera, mode.drawMode))\n                return false;\n            return (onValidateCameraMode == null ||\n                onValidateCameraMode.GetInvocationList().All(validate => ((Func<CameraMode, bool>)validate)(mode)));\n        }\n\n        public bool IsCameraDrawModeEnabled(CameraMode mode)\n        {\n            if (!Handles.IsCameraDrawModeEnabled(m_Camera, mode.drawMode))\n                return false;\n            return (onValidateCameraMode == null ||\n                onValidateCameraMode.GetInvocationList().All(validate => ((Func<CameraMode, bool>)validate)(mode)));\n        }\n\n        internal bool IsSceneCameraDeferred()\n        {\n            bool usingScriptableRenderPipeline = (GraphicsSettings.currentRenderPipeline != null);\n            if (m_Camera == null || usingScriptableRenderPipeline)\n                return false;\n            if (m_Camera.actualRenderingPath == RenderingPath.DeferredShading)\n                return true;\n            return false;\n        }\n\n        internal static bool DoesCameraDrawModeSupportDeferred(DrawCameraMode mode)\n        {\n            // many of special visualization modes don't support deferred shading/lighting\n            // overdraw/mipmaps visualizations need special forward shader\n            // various lightmaps/visualization modes, don't use deferred for safety (previous code also did not use deferred)\n            return\n                mode == DrawCameraMode.Normal ||\n                mode == DrawCameraMode.Textured ||\n                mode == DrawCameraMode.TexturedWire ||\n                mode == DrawCameraMode.ShadowCascades ||\n                mode == DrawCameraMode.RenderPaths ||\n                mode == DrawCameraMode.AlphaChannel ||\n                mode == DrawCameraMode.DeferredDiffuse ||\n                mode == DrawCameraMode.DeferredSpecular ||\n                mode == DrawCameraMode.DeferredSmoothness ||\n                mode == DrawCameraMode.DeferredNormal ||\n                mode == DrawCameraMode.RealtimeCharting ||\n                mode == DrawCameraMode.Systems ||\n                mode == DrawCameraMode.Clustering ||\n                mode == DrawCameraMode.LitClustering ||\n                mode == DrawCameraMode.RealtimeAlbedo ||\n                mode == DrawCameraMode.RealtimeEmissive ||\n                mode == DrawCameraMode.RealtimeIndirect ||\n                mode == DrawCameraMode.RealtimeDirectionality ||\n                mode == DrawCameraMode.BakedLightmap ||\n                mode == DrawCameraMode.ValidateAlbedo ||\n                mode == DrawCameraMode.ValidateMetalSpecular;\n        }\n\n        internal static bool DoesCameraDrawModeSupportHDR(DrawCameraMode mode)\n        {\n            // HDR/Tonemap only supported on regular views, and not on any special visualizations\n            return mode == DrawCameraMode.Textured || mode == DrawCameraMode.TexturedWire;\n        }\n\n        private void PrepareCameraTargetTexture(Rect cameraRect)\n        {\n            // Always render camera into a RT\n            bool hdr = SceneViewIsRenderingHDR();\n            CreateCameraTargetTexture(cameraRect, hdr);\n            m_Camera.targetTexture = m_SceneTargetTexture;\n\n            // Do not use deferred rendering when using search filtering or wireframe/overdraw/mipmaps rendering modes.\n            if (UseSceneFiltering() || !DoesCameraDrawModeSupportDeferred(m_CameraMode.drawMode))\n            {\n                if (IsSceneCameraDeferred())\n                    m_Camera.renderingPath = RenderingPath.Forward;\n            }\n        }\n\n        private void PrepareCameraReplacementShader()\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            // Set scene view colors\n            Handles.SetSceneViewColors(kSceneViewWire, kSceneViewWireOverlay, kSceneViewSelectedOutline, kSceneViewSelectedChildrenOutline, kSceneViewSelectedWire);\n\n            // Setup shader replacement if needed by overlay mode\n            if (m_CameraMode.drawMode == DrawCameraMode.Overdraw)\n            {\n                // show overdraw\n                if (!s_ShowOverdrawShader)\n                    s_ShowOverdrawShader = EditorGUIUtility.LoadRequired(\"SceneView/SceneViewShowOverdraw.shader\") as Shader;\n                m_Camera.SetReplacementShader(s_ShowOverdrawShader, \"RenderType\");\n            }\n            else if (m_CameraMode.drawMode == DrawCameraMode.Mipmaps)\n            {\n                Texture.SetStreamingTextureMaterialDebugProperties();\n\n                // show mip levels\n                if (!s_ShowMipsShader)\n                    s_ShowMipsShader = EditorGUIUtility.LoadRequired(\"SceneView/SceneViewShowMips.shader\") as Shader;\n                if (s_ShowMipsShader != null && s_ShowMipsShader.isSupported)\n                {\n                    CreateMipColorsTexture();\n                    m_Camera.SetReplacementShader(s_ShowMipsShader, \"RenderType\");\n                }\n                else\n                {\n                    m_Camera.SetReplacementShader(m_ReplacementShader, m_ReplacementString);\n                }\n            }\n            else if (m_CameraMode.drawMode == DrawCameraMode.TextureStreaming)\n            {\n                Texture.SetStreamingTextureMaterialDebugProperties();\n\n                // show mip levels\n                if (!s_ShowTextureStreamingShader)\n                    s_ShowTextureStreamingShader = EditorGUIUtility.LoadRequired(\"SceneView/SceneViewShowTextureStreaming.shader\") as Shader;\n                if (s_ShowTextureStreamingShader != null && s_ShowTextureStreamingShader.isSupported)\n                {\n                    m_Camera.SetReplacementShader(s_ShowTextureStreamingShader, \"RenderType\");\n                }\n                else\n                {\n                    m_Camera.SetReplacementShader(m_ReplacementShader, m_ReplacementString);\n                }\n            }\n            else\n            {\n                m_Camera.SetReplacementShader(m_ReplacementShader, m_ReplacementString);\n            }\n        }\n\n        bool SceneCameraRendersIntoRT()\n        {\n            return m_Camera.targetTexture != null;\n        }\n\n        private void DoDrawCamera(Rect windowSpaceCameraRect, Rect groupSpaceCameraRect, out bool pushedGUIClipNeedsToBePopped)\n        {\n            pushedGUIClipNeedsToBePopped = false;\n\n            if (!m_Camera.gameObject.activeInHierarchy)\n                return;\n\n            bool oldAsync = ShaderUtil.allowAsyncCompilation;\n            ShaderUtil.allowAsyncCompilation = EditorSettings.asyncShaderCompilation;\n\n            DrawGridParameters gridParam = sceneViewGrids.PrepareGridRender(camera, pivot, m_Rotation.target, size, m_Ortho.target);\n\n            Event evt = Event.current;\n\n            if (UseSceneFiltering())\n            {\n                bool sceneRendersToRT = SceneCameraRendersIntoRT();\n                if (sceneRendersToRT)\n                {\n                    GUIClip.Push(groupSpaceCameraRect, Vector2.zero, Vector2.zero, true);\n                    GUIClip.Internal_PushParentClip(Matrix4x4.identity, GUIClip.GetParentMatrix(), groupSpaceCameraRect);\n                }\n\n                if (evt.type == EventType.Repaint)\n                    RenderFilteredScene(groupSpaceCameraRect);\n\n                DrawPingedObjectSubmeshOutlineIfNeeded();\n\n                if (sceneRendersToRT)\n                {\n                    GUIClip.Internal_PopParentClip();\n                    GUIClip.Pop();\n                }\n\n                if (evt.type == EventType.Repaint)\n                    RenderTexture.active = null;\n\n                GUI.EndGroup();\n\n                GUI.BeginGroup(windowSpaceCameraRect);\n                if (evt.type == EventType.Repaint)\n                    Graphics.DrawTexture(groupSpaceCameraRect, m_SceneTargetTexture, new Rect(0, 0, 1, 1), 0, 0, 0, 0, GUI.color, GUI.blitMaterial);\n                Handles.SetCamera(groupSpaceCameraRect, m_Camera);\n            }\n            else\n            {\n                // If the camera is rendering into a Render Texture we need to reset the offsets of the GUIClip stack\n                // otherwise all GUI drawing after here will get offset incorrectly.\n                if (SceneCameraRendersIntoRT())\n                {\n                    GUIClip.Push(new Rect(0f, 0f, position.width, position.height), Vector2.zero, Vector2.zero, true);\n                    GUIClip.Internal_PushParentClip(Matrix4x4.identity, GUIClip.GetParentMatrix(), groupSpaceCameraRect);\n                    pushedGUIClipNeedsToBePopped = true;\n                }\n                Handles.DrawCameraStep1(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode, gridParam, drawGizmos, true);\n\n                if (evt.type == EventType.Repaint)\n                {\n                    if (s_SelectionCacheDirty)\n                    {\n                        HandleUtility.FilterInstanceIDs(Selection.gameObjects, out s_CachedParentRenderersForOutlining, out s_CachedChildRenderersForOutlining, out s_CachedChildRenderersForOutliningHashSet);\n                        s_SelectionCacheDirty = false;\n                    }\n\n                    OutlineDrawMode selectionOutlineWireFlags = 0;\n                    if (AnnotationUtility.showSelectionOutline) selectionOutlineWireFlags |= OutlineDrawMode.SelectionOutline;\n                    if (AnnotationUtility.showSelectionWire) selectionOutlineWireFlags |= OutlineDrawMode.SelectionWire;\n                    if (selectionOutlineWireFlags != 0)\n                        Handles.DrawOutlineOrWireframeInternal(kSceneViewSelectedOutline, kSceneViewSelectedChildrenOutline, 1 - alphaMultiplier, s_CachedParentRenderersForOutlining, s_CachedChildRenderersForOutlining, selectionOutlineWireFlags);\n                }\n\n                DrawRenderModeOverlay(groupSpaceCameraRect);\n\n                DrawPingedObjectSubmeshOutlineIfNeeded();\n            }\n\n            ShaderUtil.allowAsyncCompilation = oldAsync;\n        }\n\n        void DrawPingedObjectSubmeshOutlineIfNeeded()\n        {\n            if (isPingingObject)\n            {\n                var currentTime = Time.realtimeSinceStartup;\n                if (currentTime - pingStartTime > kSubmeshPingDuration)\n                {\n                    isPingingObject = false;\n                    alphaMultiplier = 0;\n                    submeshOutlineMaterialId = 0;\n                }\n                else\n                {\n                    var elapsed = currentTime - pingStartTime;\n                    float t = (float)elapsed / (float)kSubmeshPingDuration;\n                    alphaMultiplier = Mathf.SmoothStep(1, 0, t);\n                    if (Event.current.type == EventType.Repaint)\n                    {\n                        Handles.DrawSubmeshOutline(kSceneViewSelectedSubmeshOutline, kSceneViewSelectedSubmeshOutline, alphaMultiplier, submeshOutlineMaterialId);\n                        Repaint();\n                    }\n                }\n            }\n        }\n\n        void RenderFilteredScene(Rect groupSpaceCameraRect)\n        {\n            var oldRenderingPath = m_Camera.renderingPath;\n\n            // First pass: Draw the scene normally in destination render texture, save color buffer for later\n            DoClearCamera(groupSpaceCameraRect);\n            Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode, drawGizmos);\n\n            var colorDesc = m_SceneTargetTexture.descriptor;\n            colorDesc.depthBufferBits = 0;\n            var colorRT = RenderTexture.GetTemporary(colorDesc);\n            colorRT.name = \"SavedColorRT\";\n            Graphics.Blit(m_SceneTargetTexture, colorRT);\n\n            // Second pass: Blit the scene faded out in the scene target texture\n            float fade = UseSceneFiltering() ? 1f : Mathf.Clamp01((float)(EditorApplication.timeSinceStartup - m_StartSearchFilterTime));\n            if (!s_FadeMaterial)\n                s_FadeMaterial = EditorGUIUtility.LoadRequired(\"SceneView/SceneViewGrayscaleEffectFade.mat\") as Material;\n            s_FadeMaterial.SetFloat(\"_Fade\", fade);\n            Graphics.Blit(colorRT, m_SceneTargetTexture, s_FadeMaterial);\n\n            // Third pass: Draw aura for objects which meet the search filter, but are occluded. Save color buffer for later.\n            m_Camera.renderingPath = RenderingPath.Forward;\n            if (!s_AuraShader)\n                s_AuraShader = EditorGUIUtility.LoadRequired(\"SceneView/SceneViewAura.shader\") as Shader;\n            m_Camera.SetReplacementShader(s_AuraShader, \"\");\n            Handles.SetCameraFilterMode(m_Camera, Handles.CameraFilterMode.ShowFiltered);\n            Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode, drawGizmos);\n\n            var fadedDesc = m_SceneTargetTexture.descriptor;\n            colorDesc.depthBufferBits = 0;\n            var fadedRT = RenderTexture.GetTemporary(fadedDesc);\n            fadedRT.name = \"FadedColorRT\";\n            Graphics.Blit(m_SceneTargetTexture, fadedRT);\n\n            // Fourth pass: Draw objects which do meet filter in a mask\n\n            // cache old state, we need to disable post and similar for the mask pass\n            var oldSceneViewState = sceneViewState.fxEnabled;\n            var oldImageEffects = sceneViewState.imageEffectsEnabled;\n            UpdateImageEffects(false);\n            sceneViewState.fxEnabled = false;\n            var skybox = RenderSettings.skybox;\n            RenderSettings.skybox = null;\n\n            RenderTexture.active = m_SceneTargetTexture;\n            GL.Clear(false, true, Color.clear);\n            m_Camera.ResetReplacementShader();\n            Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode, drawGizmos);\n\n            // restore old state\n            UpdateImageEffects(oldImageEffects);\n            sceneViewState.fxEnabled = oldSceneViewState;\n            RenderSettings.skybox = skybox;\n\n            // Final pass: Blit the faded scene where the mask isn't set\n            if (!s_ApplyFilterMaterial)\n                s_ApplyFilterMaterial = EditorGUIUtility.LoadRequired(\"SceneView/SceneViewApplyFilter.mat\") as Material;\n            s_ApplyFilterMaterial.SetTexture(\"_MaskTex\", m_SceneTargetTexture);\n            Graphics.Blit(fadedRT, colorRT, s_ApplyFilterMaterial);\n            Graphics.Blit(colorRT, m_SceneTargetTexture);\n\n            RenderTexture.ReleaseTemporary(colorRT);\n            RenderTexture.ReleaseTemporary(fadedRT);\n\n            OutlineDrawMode selectionDrawModeMask = 0;\n            if (AnnotationUtility.showSelectionOutline)\n                selectionDrawModeMask |= OutlineDrawMode.SelectionOutline;\n            if (AnnotationUtility.showSelectionWire)\n               selectionDrawModeMask |= OutlineDrawMode.SelectionWire;\n\n            if (Event.current.type == EventType.Repaint && selectionDrawModeMask != 0)\n            {\n                if (s_SelectionCacheDirty)\n                {\n                    HandleUtility.FilterInstanceIDs(Selection.gameObjects, out s_CachedParentRenderersForOutlining, out s_CachedChildRenderersForOutlining, out s_CachedChildRenderersForOutliningHashSet);\n                    s_SelectionCacheDirty = false;\n                }\n\n                Handles.DrawOutlineOrWireframeInternal(kSceneViewSelectedOutline, kSceneViewSelectedChildrenOutline, 1 - alphaMultiplier, s_CachedParentRenderersForOutlining, s_CachedChildRenderersForOutlining, selectionDrawModeMask);\n                Handles.Internal_FinishDrawingCamera(m_Camera, drawGizmos);\n            }\n\n            // Reset camera\n            m_Camera.SetReplacementShader(m_ReplacementShader, m_ReplacementString);\n            m_Camera.renderingPath = oldRenderingPath;\n\n            if (fade < 1)\n                Repaint();\n        }\n\n        void DoClearCamera(Rect cameraRect)\n        {\n            // Clear (color/skybox)\n            // We do funky FOV interpolation when switching between ortho and perspective. However,\n            // for the skybox we always want to use the same FOV.\n            float skyboxFOV = GetVerticalFOV(m_CameraSettings.fieldOfView);\n            float realFOV = m_Camera.fieldOfView;\n\n            var clearFlags = m_Camera.clearFlags;\n            if (GraphicsSettings.currentRenderPipeline != null)\n                m_Camera.clearFlags = CameraClearFlags.Color;\n            m_Camera.fieldOfView = skyboxFOV;\n            Handles.ClearCamera(cameraRect, m_Camera);\n            m_Camera.clearFlags = clearFlags;\n            m_Camera.fieldOfView = realFOV;\n        }\n\n        void SetupCustomSceneLighting()\n        {\n            if (m_SceneIsLit)\n                return;\n            m_Light[0].transform.rotation = m_Camera.transform.rotation;\n            if (Event.current.type == EventType.Repaint)\n                InternalEditorUtility.SetCustomLighting(m_Light, kSceneViewMidLight);\n        }\n\n        void CleanupCustomSceneLighting()\n        {\n            if (m_SceneIsLit)\n                return;\n            if (Event.current.type == EventType.Repaint)\n                InternalEditorUtility.RemoveCustomLighting();\n        }\n\n        // Give editors a chance to kick in. Disable in search mode, editors rendering to the scene\n        void HandleViewToolCursor(Rect cameraRect)\n        {\n            if (!Tools.viewToolActive || Event.current.type != EventType.Repaint)\n                return;\n            // In case multiple scene views are opened, we only want to set the cursor for the one being hovered\n            // Skip if the mouse is over an overlay or an area that should not use a custom cursor\n            if (mouseOverWindow is SceneView view && (mouseOverWindow != this || !view.sceneViewMotion.viewportsUnderMouse))\n                return;\n\n            var cursor = MouseCursor.Arrow;\n            switch (Tools.viewTool)\n            {\n                case ViewTool.Pan:\n                    cursor = MouseCursor.Pan;\n                    break;\n                case ViewTool.Orbit:\n                    cursor = MouseCursor.Orbit;\n                    break;\n                case ViewTool.FPS:\n                    cursor = MouseCursor.FPS;\n                    break;\n                case ViewTool.Zoom:\n                    cursor = MouseCursor.Zoom;\n                    break;\n            }\n\n            if (cursor != MouseCursor.Arrow)\n                AddCursorRect(cameraRect, cursor);\n        }\n\n        private static bool ComponentHasImageEffectAttribute(Component c)\n        {\n            if (c == null)\n                return false;\n            return Attribute.IsDefined(c.GetType(), typeof(ImageEffectAllowedInSceneView));\n        }\n\n        void UpdateImageEffects(bool enable)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            Camera mainCam = GetMainCamera();\n            if (!enable || mainCam == null)\n            {\n                ComponentUtility.DestroyComponentsMatching(m_Camera.gameObject, ComponentHasImageEffectAttribute);\n                return;\n            }\n\n            ComponentUtility.ReplaceComponentsIfDifferent(mainCam.gameObject, m_Camera.gameObject, ComponentHasImageEffectAttribute);\n        }\n\n        void DoOnPreSceneGUICallbacks(Rect cameraRect)\n        {\n            // Don't do callbacks in search mode, as editors calling Handles.BeginGUI\n            // will break camera setup.\n            if (hasSearchFilter)\n                return;\n\n            CallOnPreSceneGUI();\n        }\n\n        // Virtual/Abstract methods are not supported by the APIUpdater\n        [Obsolete(\"OnGUI has been deprecated. Use OnSceneGUI instead.\")]\n        protected virtual void OnGUI() {}\n\n        protected virtual void OnSceneGUI() => DoOnGUI();\n\n        void DoOnGUI()\n        {\n            onGUIStarted?.Invoke(this);\n\n            Event evt = Event.current;\n\n            //overlay.displayed cannot be changed during the layout event\n            if (evt.type != EventType.Layout)\n            {\n                bool shouldShow = lastActiveSceneView == this;\n                foreach(var overlay in overlayCanvas.overlays)\n                {\n                    if(overlay is ITransientOverlay transient)\n                        overlay.displayed = shouldShow && transient.visible;\n                }\n            }\n\n            LegacyOverlayPreOnGUI();\n            s_CurrentDrawingSceneView = this;\n\n            if (evt.type == EventType.Layout)\n            {\n                s_MouseRects.Clear();\n                Tools.InvalidateHandlePosition(); // Some cases that should invalidate the cached position are not handled correctly yet so we refresh it once per frame\n            }\n\n            sceneViewGrids.UpdateGridColor();\n\n            Color origColor = GUI.color;\n            Rect origCameraRect = m_Camera.rect;\n            Rect windowSpaceCameraRect = cameraViewport;\n\n            //If we know the window space camera rect is invalid, we can early-out here\n            if(windowSpaceCameraRect.width <= 0 || windowSpaceCameraRect.height <= 0)\n                return;\n\n            HandleClickAndDragToFocus();\n\n            BeginWindows();\n\n            if (evt.type == EventType.Layout)\n                m_ShowSceneViewWindows = (lastActiveSceneView == this);\n\n            SetupFogAndShadowDistance(out var oldFog, out var oldShadowDistance);\n\n            GUI.skin = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Scene);\n\n            // Don't apply any playmode tinting to scene views\n            GUI.color = Color.white;\n\n            EditorGUIUtility.labelWidth = 100;\n\n            SetupCamera();\n            RenderingPath oldRenderingPath = m_Camera.renderingPath;\n\n            // Use custom scene RenderSettings (if currently showing a custom scene)\n            bool restoreOverrideRenderSettings = false;\n            if (m_CustomScene.IsValid())\n                restoreOverrideRenderSettings = Unsupported.SetOverrideLightingSettings(m_CustomScene);\n\n            m_StageHandling?.StartOnGUI();\n\n            SetupCustomSceneLighting();\n\n            GUI.BeginGroup(windowSpaceCameraRect);\n\n            Rect groupSpaceCameraRect = new Rect(0, 0, windowSpaceCameraRect.width, windowSpaceCameraRect.height);\n            Rect groupSpaceCameraRectInPixels = EditorGUIUtility.PointsToPixels(groupSpaceCameraRect);\n\n            HandleViewToolCursor(windowSpaceCameraRect);\n\n            PrepareCameraTargetTexture(groupSpaceCameraRectInPixels);\n            DoClearCamera(groupSpaceCameraRectInPixels);\n\n            m_Camera.cullingMask = Tools.visibleLayers;\n\n            Handles.SetCamera(groupSpaceCameraRectInPixels, m_Camera);\n\n            DoOnPreSceneGUICallbacks(groupSpaceCameraRectInPixels);\n\n            PrepareCameraReplacementShader();\n\n            // Unfocus search field on mouse clicks into content, so that key presses work to navigate.\n            m_MainViewControlID = GUIUtility.GetControlID(FocusType.Keyboard);\n            if (evt.GetTypeForControl(m_MainViewControlID) == EventType.MouseDown && groupSpaceCameraRect.Contains(evt.mousePosition))\n                GUIUtility.keyboardControl = m_MainViewControlID;\n\n            // Draw camera\n            bool pushedGUIClipNeedsToBePopped;\n            DoDrawCamera(windowSpaceCameraRect, groupSpaceCameraRect, out pushedGUIClipNeedsToBePopped);\n\n            CleanupCustomSceneLighting();\n\n            if (restoreOverrideRenderSettings)\n                Unsupported.RestoreOverrideLightingSettings();\n\n            //Ensure that the target texture is clamped [0-1]\n            //This is needed because otherwise gizmo rendering gets all\n            //messed up (think HDR target with value of 50 + alpha blend gizmo... gonna be white!)\n\n            bool hdrDisplayActive = (m_Parent != null && m_Parent.actualView == this && m_Parent.hdrActive);\n            if (!UseSceneFiltering() && evt.type == EventType.Repaint && GraphicsFormatUtility.IsIEEE754Format(m_SceneTargetTexture.graphicsFormat) && !hdrDisplayActive)\n            {\n                var rtDesc = m_SceneTargetTexture.descriptor;\n                rtDesc.graphicsFormat = SystemInfo.GetGraphicsFormat(DefaultFormat.LDR);\n                rtDesc.depthBufferBits = 0;\n                RenderTexture ldrSceneTargetTexture = RenderTexture.GetTemporary(rtDesc);\n                ldrSceneTargetTexture.name = \"LDRSceneTarget\";\n                Graphics.Blit(m_SceneTargetTexture, ldrSceneTargetTexture);\n                Graphics.Blit(ldrSceneTargetTexture, m_SceneTargetTexture);\n                Graphics.SetRenderTarget(m_SceneTargetTexture.colorBuffer, m_SceneTargetTexture.depthBuffer);\n                RenderTexture.ReleaseTemporary(ldrSceneTargetTexture);\n            }\n\n            if (!UseSceneFiltering() && !isPingingObject)\n            {\n                // Blit to final target RT in deferred mode\n                if (m_Camera.gameObject.activeInHierarchy)\n                    Handles.DrawCameraStep2(m_Camera, m_CameraMode.drawMode, drawGizmos);\n            }\n\n            RestoreFogAndShadowDistance(oldFog, oldShadowDistance);\n\n            m_Camera.renderingPath = oldRenderingPath;\n\n            if (!UseSceneFiltering())\n            {\n                if (evt.type == EventType.Repaint)\n                {\n                    Profiler.BeginSample(\"SceneView.BlitRT\");\n                    Graphics.SetRenderTarget(null);\n                }\n\n                // If we reset the offsets pop that clip off now.\n                if (pushedGUIClipNeedsToBePopped)\n                {\n                    GUIClip.Internal_PopParentClip();\n                    GUIClip.Pop();\n                }\n\n                if (evt.type == EventType.Repaint)\n                {\n                    Graphics.DrawTexture(groupSpaceCameraRect, m_SceneTargetTexture, new Rect(0, 0, 1, 1), 0, 0, 0, 0, GUI.color, EditorGUIUtility.GUITextureBlit2SRGBMaterial);\n                    Profiler.EndSample();\n                }\n            }\n\n            // By this time the 3D scene is done being drawn, and we're left with gizmos, handles and SceneViewGUI stuff.\n            // Reusing the same 3D scene render target, we draw those things and blit them on the back buffer without\n            // doing sRGB conversions on them since they were always intended to draw without sRGB conversions.\n            GUIClip.Push(new Rect(0f, 0f, m_SceneTargetTexture.width, m_SceneTargetTexture.height), Vector2.zero, Vector2.zero, true);\n\n            if (evt.type == EventType.Repaint)\n            {\n                Graphics.SetRenderTarget(m_SceneTargetTexture);\n                GL.Clear(false, true, new Color(0, 0, 0, 0)); // Only clear color. Keep depth intact.\n                GUIClip.Internal_PushParentClip(Matrix4x4.identity, GUIClip.GetParentMatrix(), groupSpaceCameraRect);\n            }\n\n            // Calling OnSceneGUI before DefaultHandles, so users can use events before the Default Handles\n            HandleSelectionAndOnSceneGUI();\n\n            // Draw default scene manipulation tools (Move/Rotate/...)\n            DefaultHandles();\n\n            // Handle scene view motion when this scene view is active (always after duringSceneGui and Tools, so that\n            // user tools can access RMB and alt keys if they want to override the event)\n            // Do not pass the camera transform to the SceneViewMotion calculations.\n            // The camera transform is calculation *output* not *input*.\n            // Avoiding using it as input too avoids errors accumulating.\n            m_SceneViewMotion.DoViewTool(this);\n\n            // Update active viewpoint if there's one.\n            // Must happen after SceneViewMotion.DoViewTool() so it knows\n            // it needs to reflect a motion to the viewpoint (regardless of their nature).\n            m_Viewpoint.UpdateViewpointMotion(m_Position.isAnimating || m_Rotation.isAnimating || m_Size.isAnimating);\n\n            Handles.SetCameraFilterMode(Camera.current, UseSceneFiltering() ? Handles.CameraFilterMode.ShowFiltered : Handles.CameraFilterMode.Off);\n\n            // Handle scene commands after EditorTool.OnSceneGUI so that tools can handle commands\n            if (evt.type == EventType.ExecuteCommand || evt.type == EventType.ValidateCommand || evt.keyCode == KeyCode.Escape)\n                CommandsGUI();\n\n            Handles.SetCameraFilterMode(Camera.current, Handles.CameraFilterMode.Off);\n            Handles.SetCameraFilterMode(m_Camera, Handles.CameraFilterMode.Off);\n\n            // Handle Dragging of stuff over scene view\n            HandleDragging(evt);\n\n            if (evt.type == EventType.Repaint)\n            {\n                Graphics.SetRenderTarget(null);\n                GUIClip.Internal_PopParentClip();\n            }\n\n            GUIClip.Pop();\n\n            GUI.EndGroup();\n            GUI.BeginGroup(windowSpaceCameraRect);\n\n            if (evt.type == EventType.Repaint)\n            {\n                // Blit the results with a pre-multiplied alpha shader to compose them correctly on top of the 3D scene on the back buffer\n                Graphics.DrawTexture(groupSpaceCameraRect, m_SceneTargetTexture, new Rect(0, 0, 1, 1), 0, 0, 0, 0, GUI.color, EditorGUIUtility.GUITextureBlitSceneGUIMaterial);\n            }\n\n            GUI.EndGroup();\n            GUI.color = origColor;\n\n            EndWindows();\n\n            HandleMouseCursor();\n\n            s_CurrentDrawingSceneView = null;\n            m_Camera.rect = origCameraRect;\n\n            if (m_Viewpoint.hasActiveViewpoint)\n                m_Viewpoint.OnGUIDrawCameraOverscan();\n\n            onGUIEnded?.Invoke(this);\n            if (m_StageHandling != null)\n                m_StageHandling.EndOnGUI();\n        }\n\n        [Shortcut(\"Scene View/Menu\", typeof(SceneViewViewport), KeyCode.Mouse1)]\n        static void OpenActionMenu(ShortcutArguments args)\n        {\n            // The mouseOverWindow check is necessary for MacOS because right-clicking does not\n            // focus the window under the cursor. This is so the action menu does not appear\n            // when the scene view is in focus and a right-click on another window occurs.\n            if (mouseOverWindow?.GetType() != typeof(SceneView))\n                return;\n\n            var mousePos = PointerDeviceState.GetPointerPosition(PointerId.mousePointerId, ContextType.Editor);\n            var ve = focusedWindow.rootVisualElement.panel.Pick(mousePos);\n            if (ve == null)\n                return;\n\n            var context = args.context as SceneViewViewport;\n            if(context == null)\n                return;\n\n            if (ve == context.window.cameraViewVisualElement)\n            {\n                ContextMenuUtility.ShowActionMenu();\n                // UUM-61727 - Force an InputEvent in IMGUI so the ContextMenu will actually open on all platforms\n                context.window.SendEvent(new Event { type = EventType.Layout });\n            }\n        }\n\n        internal void SwitchToRenderMode(DrawCameraMode mode, bool sceneLighting = true)\n        {\n            this.sceneLighting = sceneLighting;\n            this.cameraMode = GetBuiltinCameraMode(mode);\n        }\n\n        internal void SwitchToRenderMode(CameraMode mode, bool sceneLighting = true)\n        {\n            this.sceneLighting = sceneLighting;\n            this.cameraMode = mode;\n        }\n\n        internal void SwitchToUnlit() => SwitchToRenderMode(DrawCameraMode.Textured, false);\n\n        internal void ToggleLastDebugDrawMode()\n        {\n            if (cameraMode.drawMode == lastDebugDrawMode.drawMode)\n            {\n                SwitchToRenderMode(DrawCameraMode.Textured);\n            }\n            else\n            {\n                SwitchToRenderMode(lastDebugDrawMode);\n            }\n        }\n\n        [Shortcut(\"Scene View/Render Mode/Wireframe\", typeof(SceneView), KeyCode.Alpha1, ShortcutModifiers.Alt)]\n        static void SetWireframeMode(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                view.SwitchToRenderMode(DrawCameraMode.Wireframe);\n            }\n        }\n\n\n        [Shortcut(\"Scene View/Render Mode/Shaded Wireframe\", typeof(SceneView), KeyCode.Alpha2, ShortcutModifiers.Alt)]\n        static void SetShadedWireframeMode(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                view.SwitchToRenderMode(DrawCameraMode.TexturedWire);\n            }\n        }\n\n        [Shortcut(\"Scene View/Render Mode/Unlit\", typeof(SceneView), KeyCode.Alpha3, ShortcutModifiers.Alt)]\n        static void SetUnlitMode(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                view.SwitchToUnlit();\n            }\n        }\n\n        [Shortcut(\"Scene View/Render Mode/Shaded\", typeof(SceneView), KeyCode.Alpha4, ShortcutModifiers.Alt)]\n        static void SetShadedMode(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                view.SwitchToRenderMode(DrawCameraMode.Normal);\n            }\n        }\n\n        [Shortcut(\"Scene View/Render Mode/Last Debug Draw Mode\", typeof(SceneView), KeyCode.Alpha6, ShortcutModifiers.Alt)]\n        static void SetLastDebugDrawMode(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                view.SwitchToRenderMode(view.m_LastDebugDrawMode);\n            }\n        }\n\n        [Shortcut(\"Scene View/Toggle 2D Mode\", typeof(SceneView), KeyCode.Alpha2)]\n        [FormerlyPrefKeyAs(\"Tools/2D Mode\", \"2\")]\n        static void Toggle2DMode(ShortcutArguments args)\n        {\n            var window = args.context as SceneView;\n            if (window != null)\n                window.in2DMode = !window.in2DMode;\n        }\n\n        [Shortcut(\"Scene View/Toggle Orthographic Projection\", typeof(SceneView))]\n        static void ToggleOrthoView(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                if (!view.isRotationLocked)\n                    view.m_OrientationGizmo?.ViewSetOrtho(view, !view.orthographic);\n            }\n        }\n\n        [Shortcut(\"Scene View/Set Orthographic Right View\", typeof(SceneView))]\n        static void SetOrthoRightView(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                if (!view.isRotationLocked)\n                    view.m_OrientationGizmo?.ViewAxisDirection(view, 0, true);\n            }\n        }\n\n        [Shortcut(\"Scene View/Set Right View\", typeof(SceneView))]\n        static void SetRightView(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                if (!view.isRotationLocked)\n                    view.m_OrientationGizmo?.ViewAxisDirection(view, 0, view.orthographic);\n            }\n        }\n\n        [Shortcut(\"Scene View/Set Top View\", typeof(SceneView))]\n        static void SetTopView(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                if (!view.isRotationLocked)\n                    view.m_OrientationGizmo?.ViewAxisDirection(view, 1, view.orthographic);\n            }\n        }\n\n        [Shortcut(\"Scene View/Set Orthographic Top View\", typeof(SceneView))]\n        static void SetOrthoTopView(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                if (!view.isRotationLocked)\n                    view.m_OrientationGizmo?.ViewAxisDirection(view, 1, true);\n            }\n        }\n\n        [Shortcut(\"Scene View/Set Front View\", typeof(SceneView))]\n        static void SetFrontView(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                if (!view.isRotationLocked)\n                    view.m_OrientationGizmo?.ViewAxisDirection(view, 2, view.orthographic);\n            }\n        }\n\n        [Shortcut(\"Scene View/Set Orthographic Front View\", typeof(SceneView))]\n        static void SetOrthoFrontView(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                if (!view.isRotationLocked)\n                    view.m_OrientationGizmo?.ViewAxisDirection(view, 2, true);\n            }\n        }\n\n        [Shortcut(\"Scene View/Set Left View\", typeof(SceneView))]\n        static void SetLeftView(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                if (!view.isRotationLocked)\n                    view.m_OrientationGizmo?.ViewAxisDirection(view, 3, view.orthographic);\n            }\n        }\n\n        [Shortcut(\"Scene View/Set Orthographic Left View\", typeof(SceneView))]\n        static void SetOrthoLeftView(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                if (!view.isRotationLocked)\n                    view.m_OrientationGizmo?.ViewAxisDirection(view, 3, true);\n            }\n        }\n\n        [Shortcut(\"Scene View/Set Bottom View\", typeof(SceneView))]\n        static void SetBottomView(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                if (!view.isRotationLocked)\n                    view.m_OrientationGizmo?.ViewAxisDirection(view, 4, view.orthographic);\n            }\n        }\n\n        [Shortcut(\"Scene View/Set Orthographic Bottom View\", typeof(SceneView))]\n        static void SetOrthoBottomView(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                if (!view.isRotationLocked)\n                    view.m_OrientationGizmo?.ViewAxisDirection(view, 4, true);\n            }\n        }\n\n        [Shortcut(\"Scene View/Set Back View\", typeof(SceneView))]\n        static void SetBackView(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                if (!view.isRotationLocked)\n                    view.m_OrientationGizmo?.ViewAxisDirection(view, 5, view.orthographic);\n            }\n        }\n\n        [Shortcut(\"Scene View/Set Orthographic Back View\", typeof(SceneView))]\n        static void SetOrthoBackView(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                if (!view.isRotationLocked)\n                    view.m_OrientationGizmo?.ViewAxisDirection(view, 5, true);\n            }\n        }\n\n        [Shortcut(\"Scene View/Set Free View\", typeof(SceneView))]\n        static void SetFreeView(ShortcutArguments args)\n        {\n            var view = args.context as SceneView;\n            if (view != null)\n            {\n                if (!view.isRotationLocked)\n                    view.m_OrientationGizmo?.ViewFromNiceAngle(view, false);\n            }\n        }\n\n        void HandleMouseCursor()\n        {\n            // In case multiple scene views are opened, we only want to set the cursor for the one being hovered\n            if (mouseOverWindow is SceneView && mouseOverWindow != this)\n                return;\n\n            Event evt = Event.current;\n            Rect cursorRect = new Rect(0, 0, position.width, position.height);\n            var checkMouseRects = evt.type == EventType.Repaint;\n\n            // Determine if mouse is inside a new cursor rect\n            if (checkMouseRects)\n            {\n                bool repaintView = false;\n                MouseCursor cursor = MouseCursor.Arrow;\n\n                foreach (CursorRect r in s_MouseRects)\n                {\n                    if (r.rect.Contains(evt.mousePosition))\n                    {\n                        cursor = r.cursor;\n                        cursorRect = r.rect;\n                        repaintView = true;\n                    }\n                }\n\n                var cursorChanged = cursor != s_LastCursor;\n                if (cursorChanged)\n                {\n                    s_LastCursor = cursor;\n                    InternalEditorUtility.ResetCursor();\n                }\n                if (repaintView || cursorChanged)\n                {\n                    Repaint();\n                }\n            }\n\n            // Apply the one relevant cursor rect\n            if (checkMouseRects && s_LastCursor != MouseCursor.Arrow)\n                EditorGUIUtility.AddCursorRect(cursorRect, s_LastCursor);\n        }\n\n        void DrawRenderModeOverlay(Rect cameraRect)\n        {\n            // show destination alpha channel\n            if (m_CameraMode.drawMode == DrawCameraMode.AlphaChannel)\n            {\n                if (!s_AlphaOverlayMaterial)\n                    s_AlphaOverlayMaterial = EditorGUIUtility.LoadRequired(\"SceneView/SceneViewAlphaMaterial.mat\") as Material;\n                Handles.BeginGUI();\n                if (Event.current.type == EventType.Repaint)\n                    Graphics.DrawTexture(cameraRect, EditorGUIUtility.whiteTexture, s_AlphaOverlayMaterial);\n                Handles.EndGUI();\n            }\n\n            // show one of deferred buffers\n            if (m_CameraMode.drawMode == DrawCameraMode.DeferredDiffuse ||\n                m_CameraMode.drawMode == DrawCameraMode.DeferredSpecular ||\n                m_CameraMode.drawMode == DrawCameraMode.DeferredSmoothness ||\n                m_CameraMode.drawMode == DrawCameraMode.DeferredNormal)\n            {\n                if (!s_DeferredOverlayMaterial)\n                    s_DeferredOverlayMaterial = EditorGUIUtility.LoadRequired(\"SceneView/SceneViewDeferredMaterial.mat\") as Material;\n                Handles.BeginGUI();\n                if (Event.current.type == EventType.Repaint)\n                {\n                    s_DeferredOverlayMaterial.SetFloat(\"_DisplayMode\", (float)((int)m_CameraMode.drawMode - (int)DrawCameraMode.DeferredDiffuse));\n                    Graphics.DrawTexture(cameraRect, EditorGUIUtility.whiteTexture, s_DeferredOverlayMaterial);\n                }\n                Handles.EndGUI();\n            }\n        }\n\n        private void HandleSelectionAndOnSceneGUI()\n        {\n            m_RectSelection.OnGUI(this == lastActiveSceneView);\n            CallOnSceneGUI();\n        }\n\n        // Center point of the scene view. Modify it to move the sceneview immediately, or use LookAt to animate it nicely.\n        public Vector3 pivot { get { return m_Position.value; } set { m_Position.value = value; } }\n\n        // The direction of the scene view.\n        public Quaternion rotation\n        {\n            get => in2DMode ? Quaternion.identity : m_Rotation.value;\n\n            set\n            {\n                if (in2DMode)\n                    Debug.LogWarning(\"SceneView rotation is fixed to identity when in 2D mode. This will be an error in future versions of Unity.\");\n                else\n                    m_Rotation.value = value;\n            }\n        }\n\n        static float ValidateSceneSize(float value)\n        {\n            if (value == 0f || float.IsNaN(value))\n                return float.Epsilon;\n            if (value > k_MaxSceneViewSize)\n                return k_MaxSceneViewSize;\n            if (value < -k_MaxSceneViewSize)\n                return -k_MaxSceneViewSize;\n            return value;\n        }\n\n        public float size\n        {\n            get { return m_Size.value; }\n            set { m_Size.value = ValidateSceneSize(value); }\n        }\n\n        // ReSharper disable once UnusedMember.Global - used only in editor tests\n        internal float targetSize\n        {\n            get { return m_Size.target; }\n            set { m_Size.target = ValidateSceneSize(value); }\n        }\n\n        float perspectiveFov => m_CameraSettings.fieldOfView;\n\n        public bool orthographic\n        {\n            get { return m_Ortho.value; }\n            set\n            {\n                m_Ortho.value = value;\n                m_OrientationGizmo?.UpdateGizmoLabel(this, m_Rotation.target * Vector3.forward, m_Ortho.target);\n            }\n        }\n\n        public void FixNegativeSize()\n        {\n            if (size == 0f)\n                size = float.Epsilon;\n\n            float fov = perspectiveFov;\n\n            if (size < 0)\n            {\n                float distance = GetPerspectiveCameraDistance(size, fov);\n                Vector3 p = m_Position.value + rotation * new Vector3(0, 0, -distance);\n                size = -size;\n                distance = GetPerspectiveCameraDistance(size, fov);\n                m_Position.value = p + rotation * new Vector3(0, 0, distance);\n            }\n        }\n\n        internal float CalcCameraDist()\n        {\n            float fov = m_Ortho.Fade(perspectiveFov, 0);\n            if (fov > kOrthoThresholdAngle)\n            {\n                m_Camera.orthographic = false;\n                return GetPerspectiveCameraDistance(size, fov);\n            }\n            return 0;\n        }\n\n        void ResetIfNaN()\n        {\n            // If you zoom out enough, m_Position would get corrupted with no way to reset it,\n            // even after restarting Unity. Crude hack to at least get the scene view working again!\n            if (Single.IsInfinity(m_Position.value.x) || Single.IsNaN(m_Position.value.x))\n                m_Position.value = Vector3.zero;\n            if (Single.IsInfinity(m_Rotation.value.x) || Single.IsNaN(m_Rotation.value.x))\n                m_Rotation.value = Quaternion.identity;\n        }\n\n        internal static Camera GetMainCamera()\n        {\n            // main camera, if we have any\n            var mainCamera = Camera.main;\n            if (mainCamera != null)\n                return mainCamera;\n\n            // if we have one camera, return it\n            Camera[] allCameras = Camera.allCameras;\n            if (allCameras != null && allCameras.Length == 1)\n                return allCameras[0];\n\n            // otherwise no \"main\" camera\n            return null;\n        }\n\n        // Note: this can return \"use player settings\" value too!\n        // In order to check things like \"is using deferred\", use IsUsingDeferredRenderingPath\n        internal static RenderingPath GetSceneViewRenderingPath()\n        {\n            var mainCamera = GetMainCamera();\n            if (mainCamera != null)\n                return mainCamera.renderingPath;\n            return RenderingPath.UsePlayerSettings;\n        }\n\n        internal static bool IsUsingDeferredRenderingPath()\n        {\n            RenderingPath renderingPath = GetSceneViewRenderingPath();\n            return (renderingPath == RenderingPath.DeferredShading) ||\n                (renderingPath == RenderingPath.UsePlayerSettings && Rendering.EditorGraphicsSettings.GetCurrentTierSettings().renderingPath == RenderingPath.DeferredShading);\n        }\n\n        internal bool CheckDrawModeForRenderingPath(DrawCameraMode mode)\n        {\n            RenderingPath path = m_Camera.actualRenderingPath;\n            if (mode == DrawCameraMode.DeferredDiffuse ||\n                mode == DrawCameraMode.DeferredSpecular ||\n                mode == DrawCameraMode.DeferredSmoothness ||\n                mode == DrawCameraMode.DeferredNormal)\n            {\n                return path == RenderingPath.DeferredShading;\n            }\n            return true;\n        }\n\n        private void UpdateSceneCameraSettings()\n        {\n            var mainCamera = GetMainCamera();\n\n            m_Camera.useInteractiveLightBakingData = usesInteractiveLightBakingData;\n\n            if (mainCamera != null)\n            {\n                // update physical camera properties\n                m_Camera.iso = mainCamera.iso;\n                m_Camera.shutterSpeed = mainCamera.shutterSpeed;\n                m_Camera.aperture = mainCamera.aperture;\n                m_Camera.anamorphism = mainCamera.anamorphism;\n\n                // try to match main camera's hdr and depth texture settings if unambiguous main camera exists\n                m_Camera.allowHDR = mainCamera.allowHDR;\n                m_Camera.depthTextureMode = mainCamera.depthTextureMode;\n                m_Camera.clearStencilAfterLightingPass = mainCamera.clearStencilAfterLightingPass;\n            }\n\n            if (!m_SceneIsLit || !DoesCameraDrawModeSupportHDR(m_CameraMode.drawMode))\n            {\n                m_Camera.allowHDR = false;\n                m_Camera.depthTextureMode = DepthTextureMode.None;\n                m_Camera.clearStencilAfterLightingPass = false;\n            }\n        }\n\n        void SetupCamera()\n        {\n            if (m_CameraMode.drawMode == DrawCameraMode.Overdraw)\n            {\n                // overdraw\n                m_Camera.backgroundColor = Color.black;\n            }\n            else\n            {\n                if (m_StageHandling != null)\n                    m_Camera.backgroundColor = StageNavigationManager.instance.currentStage.GetBackgroundColor();\n                else\n                    m_Camera.backgroundColor = kSceneViewBackground;\n            }\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                bool enableImageEffects = m_CameraMode.drawMode == DrawCameraMode.Textured && sceneViewState.imageEffectsEnabled;\n                UpdateImageEffects(enableImageEffects);\n            }\n\n            EditorUtility.SetCameraAnimateMaterials(m_Camera, sceneViewState.alwaysRefreshEnabled);\n            ParticleSystemEditorUtils.renderInSceneView = m_SceneViewState.particleSystemsEnabled;\n            UnityEngine.VFX.VFXManager.renderInSceneView = m_SceneViewState.visualEffectGraphsEnabled;\n            SceneVisibilityManager.instance.enableSceneVisibility = m_SceneVisActive;\n            m_Camera.renderCloudsInSceneView = m_SceneViewState.cloudsEnabled;\n            ResetIfNaN();\n\n            m_Camera.transform.rotation = GetTransformRotation();\n            m_Camera.transform.position = GetTransformPosition();\n\n            if (m_Viewpoint.hasActiveViewpoint)\n            {\n                bool isPerspective = m_Ortho.Fade(perspectiveFov, 0) > kOrthoThresholdAngle;\n                m_Viewpoint.ApplyCameraLensFromViewpoint(isPerspective);\n            }\n            else\n                ApplyDefaultCameraLens();\n\n            // In 2D mode, camera position z should not go to positive value\n            if (in2DMode && m_Camera.transform.position.z >= 0)\n            {\n                var p = m_Camera.transform.position;\n                // when clamping the camera distance, choose a point far from origin to avoid obscuring objects with the\n                // near clip plane. see https://fogbugz.unity3d.com/f/cases/1353387/\n                var z = -(100f + m_Camera.nearClipPlane + 0.01f);\n                m_Camera.farClipPlane += p.z - z;\n                p.z = z;\n                m_Camera.transform.position = p;\n            }\n\n            m_Camera.renderingPath = GetSceneViewRenderingPath();\n            if (!CheckDrawModeForRenderingPath(m_CameraMode.drawMode))\n                m_CameraMode = GetBuiltinCameraMode(DrawCameraMode.Textured);\n\n            UpdateSceneCameraSettings();\n\n            if (m_CameraMode.drawMode == DrawCameraMode.Textured ||\n                m_CameraMode.drawMode == DrawCameraMode.TexturedWire ||\n                m_CameraMode.drawMode == DrawCameraMode.UserDefined)\n            {\n                Handles.EnableCameraFlares(m_Camera, sceneViewState.flaresEnabled);\n                Handles.EnableCameraSkybox(m_Camera, sceneViewState.skyboxEnabled);\n            }\n            else\n            {\n                Handles.EnableCameraFlares(m_Camera, false);\n                Handles.EnableCameraSkybox(m_Camera, false);\n            }\n\n            // Update the light\n            m_Light[0].transform.position = m_Camera.transform.position;\n            m_Light[0].transform.rotation = m_Camera.transform.rotation;\n\n            // Update audio engine\n            if (m_PlayAudio)\n            {\n                AudioUtil.SetListenerTransform(m_Camera.transform);\n                AudioUtil.UpdateAudio();\n            }\n\n            if (m_ViewIsLockedToObject && Selection.gameObjects.Length > 0)\n            {\n                var bounds = InternalEditorUtility.CalculateSelectionBounds(false);\n                switch (draggingLocked)\n                {\n                    case (DraggingLockedState.Dragging):\n                        // While dragging via handles, we don't want to move the camera\n                        break;\n                    case (DraggingLockedState.LookAt):\n                        if (!m_Position.value.Equals(m_Position.target))\n                            Frame(bounds, EditorApplication.isPlaying);\n                        else\n                            draggingLocked = DraggingLockedState.NotDragging;\n                        break;\n                    case (DraggingLockedState.NotDragging):\n                        // Once framed, we only need to lock position rather than all the parameters Frame() sets\n                        m_Position.value = bounds.center;\n                        break;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Applies CameraSettings properties to the camera.\n        /// </summary>\n        internal void ApplyDefaultCameraLens()\n        {\n            float fov = m_Ortho.Fade(perspectiveFov, 0);\n\n            if (fov > kOrthoThresholdAngle)\n            {\n                // View is in perspective mode.\n                m_Camera.orthographic = false;\n                m_Camera.fieldOfView = GetVerticalFOV(fov);\n            }\n            else\n            {\n                // View is orthographic.\n                m_Camera.orthographic = true;\n                m_Camera.orthographicSize = GetVerticalOrthoSize();\n            }\n\n            if (cameraSettings.dynamicClip)\n            {\n                var clip = GetDynamicClipPlanes();\n                m_Camera.nearClipPlane = clip.x;\n                m_Camera.farClipPlane = clip.y;\n            }\n            else\n            {\n                m_Camera.nearClipPlane = m_CameraSettings.nearClip;\n                m_Camera.farClipPlane = m_CameraSettings.farClip;\n            }\n\n            m_Camera.useOcclusionCulling = m_CameraSettings.occlusionCulling;\n        }\n\n        void OnBecameVisible()\n        {\n            var inPlayMode = (EditorApplication.isPlaying || EditorApplication.isPaused);\n            if (inPlayMode && m_Parent.vSyncEnabled)\n                m_Parent.EnableVSync(false);\n\n            EditorApplication.update += UpdateAnimatedMaterials;\n        }\n\n        void OnBecameInvisible()\n        {\n            EditorApplication.update -= UpdateAnimatedMaterials;\n        }\n\n        void UpdateAnimatedMaterials()\n        {\n            var repaint = false;\n\n            // Ensure that we in fact do want to paint when not in focus.\n            if (!EditorApplication.isFocused && s_PreferenceIgnoreAlwaysRefreshWhenNotFocused.value)\n            {\n                // We're going to capture this condition, so that it doesnt fall through.\n            }\n            else if (m_lastRenderedTime + 0.033f < EditorApplication.timeSinceStartup)\n            {\n                repaint = sceneViewState.alwaysRefreshEnabled;\n            }\n\n            repaint |= LODUtility.IsLODAnimating(m_Camera);\n\n            if (repaint)\n            {\n                m_lastRenderedTime = EditorApplication.timeSinceStartup;\n                Repaint();\n            }\n        }\n\n        // ReSharper disable once UnusedMember.Global - used in tests\n        internal Quaternion cameraTargetRotation => m_Rotation.target;\n\n        // ReSharper disable once UnusedMember.Global - used in tests\n        internal Vector3 cameraTargetPosition => m_Position.target + m_Rotation.target * new Vector3(0, 0, -cameraDistance);\n\n        // ReSharper disable once MemberCanBePrivate.Global - used in tests\n        internal float GetVerticalFOV(float aspectNeutralFOV, float multiplier = 1.0f)\n        {\n            // We want Scene view camera \"FOV\" to be the vertical FOV if the\n            // Scene view is wider than tall, and the horizontal FOV otherwise.\n            if (m_Camera.aspect < 1)\n                multiplier /= m_Camera.aspect;\n            float halfFovRad = aspectNeutralFOV * 0.5f * Mathf.Deg2Rad;\n            float halfFovTan = Mathf.Tan(halfFovRad) * multiplier;\n            return Mathf.Atan(halfFovTan) * 2 * Mathf.Rad2Deg;\n        }\n\n        float GetVerticalOrthoSize()\n        {\n            // We want scene view ortho size to enclose sphere of\n            // radius \"size\". If scene view is more tall than wide,\n            // we want to take that into account so that the bounds\n            // fit in horizontally.\n            float res = size;\n            if (m_Camera.aspect < 1.0)\n                res /= m_Camera.aspect;\n            return res;\n        }\n\n        /// <summary>\n        /// Get the final representation of the rotation data that\n        /// will be applied to the camera transform.\n        /// </summary>\n        /// <returns></returns>\n        internal Quaternion GetTransformRotation()\n        {\n            return in2DMode && !m_Rotation.isAnimating ? Quaternion.identity : m_Rotation.value;\n        }\n\n        /// <summary>\n        /// Get the final representation of the position data that\n        /// will be applied to the camera transform.\n        /// </summary>\n        /// <returns></returns>\n        internal Vector3 GetTransformPosition()\n        {\n            return m_Position.value + m_Camera.transform.rotation * new Vector3(0, 0, -cameraDistance);\n        }\n\n        // Look at a specific point.\n        public void LookAt(Vector3 point)\n        {\n            FixNegativeSize();\n            m_Position.target = point;\n        }\n\n        // Look at a specific point from a given direction.\n        public void LookAt(Vector3 point, Quaternion direction)\n        {\n            FixNegativeSize();\n            m_Position.target = point;\n            m_Rotation.target = direction;\n            m_OrientationGizmo?.UpdateGizmoLabel(this, direction * Vector3.forward, m_Ortho.target);\n        }\n\n        // Look directly at a specific point from a given direction.\n        public void LookAtDirect(Vector3 point, Quaternion direction)\n        {\n            FixNegativeSize();\n            m_Position.value = point;\n            m_Rotation.value = direction;\n            m_OrientationGizmo?.UpdateGizmoLabel(this, direction * Vector3.forward, m_Ortho.target);\n        }\n\n        // Look at a specific point from a given direction with a given zoom level.\n        public void LookAt(Vector3 point, Quaternion direction, float newSize)\n        {\n            FixNegativeSize();\n            m_Position.target = point;\n            m_Rotation.target = direction;\n            m_Size.target = ValidateSceneSize(Mathf.Abs(newSize));\n            m_OrientationGizmo?.UpdateGizmoLabel(this, direction * Vector3.forward, m_Ortho.target);\n        }\n\n        // Look directionally at a specific point from a given direction with a given zoom level.\n        public void LookAtDirect(Vector3 point, Quaternion direction, float newSize)\n        {\n            FixNegativeSize();\n            m_Position.value = point;\n            m_Rotation.value = direction;\n            size = Mathf.Abs(newSize);\n            m_OrientationGizmo?.UpdateGizmoLabel(this, direction * Vector3.forward, m_Ortho.target);\n        }\n\n        // Look at a specific point from a given direction with a given zoom level, enabling and disabling perspective\n        public void LookAt(Vector3 point, Quaternion direction, float newSize, bool ortho)\n        {\n            LookAt(point, direction, newSize, ortho, false);\n        }\n\n        // Look at a specific point from a given direction with a given zoom level, enabling and disabling perspective\n        public void LookAt(Vector3 point, Quaternion direction, float newSize, bool ortho, bool instant)\n        {\n            m_SceneViewMotion.ResetMotion();\n            FixNegativeSize();\n\n            if (instant)\n            {\n                m_Position.value = point;\n                m_Rotation.value = direction;\n                size = Mathf.Abs(newSize);\n                m_Ortho.value = ortho;\n                draggingLocked = DraggingLockedState.NotDragging;\n            }\n            else\n            {\n                m_Position.target = point;\n                m_Rotation.target = direction;\n                m_Size.target = ValidateSceneSize(Mathf.Abs(newSize));\n                m_Ortho.target = ortho;\n            }\n\n            m_OrientationGizmo?.UpdateGizmoLabel(this, direction * Vector3.forward, m_Ortho.target);\n        }\n\n        internal void UpdateOrientationGizmos()\n        {\n            m_OrientationGizmo?.UpdateGizmoLabel(this, rotation * Vector3.forward, m_Ortho.target);\n        }\n\n        void DefaultHandles()\n        {\n            // Note event state.\n            EditorGUI.BeginChangeCheck();\n            bool IsDragEvent = Event.current.GetTypeForControl(GUIUtility.hotControl) == EventType.MouseDrag;\n            bool IsMouseUpEvent = Event.current.GetTypeForControl(GUIUtility.hotControl) == EventType.MouseUp;\n\n            EditorToolManager.OnToolGUI(this);\n\n            // If we are actually dragging the object(s) then disable 2D physics movement.\n            if (EditorGUI.EndChangeCheck() && EditorApplication.isPlaying && IsDragEvent)\n                Physics2D.SetEditorDragMovement(true, Selection.gameObjects);\n\n            // If we have finished dragging the object(s) then enable 2D physics movement.\n            if (EditorApplication.isPlaying && IsMouseUpEvent)\n                Physics2D.SetEditorDragMovement(false, Selection.gameObjects);\n        }\n\n        void CleanupEditorDragFunctions()\n        {\n            m_DragEditorCache?.Dispose();\n            m_DragEditorCache = null;\n        }\n\n        bool CallEditorDragFunctions(IList<Object> dragAndDropObjects)\n        {\n            Event evt = Event.current;\n\n            SpriteUtility.OnSceneDrag(this);\n\n            if (evt.type == EventType.Used || dragAndDropObjects.Count == 0) return true;\n\n            if (m_DragEditorCache == null)\n                m_DragEditorCache = new EditorCache(EditorFeatures.OnSceneDrag);\n\n            bool allHandled = true;\n\n            // We iterate through dragged items backwards to preserve the alphabetical order\n            // of GameObjects when they are created in hierarchy once drag is performed\n            for (int i = dragAndDropObjects.Count - 1; i >= 0; i--)\n            {\n                if (dragAndDropObjects[i] == null)\n                    continue;\n\n                EditorWrapper w = m_DragEditorCache[dragAndDropObjects[i]];\n\n                if (w == null)\n                {\n                    allHandled = false;\n                    continue;\n                }\n                w.OnSceneDrag(this, dragAndDropObjects.Count - 1 - i);\n            }\n\n            return allHandled;\n        }\n\n        internal static bool CanDoDrag(ICollection<Object> objects)\n        {\n            if (objects.Count < 2) return true;\n\n            int gameObjectCount = 0;\n            int assetCount = 0;\n            int materialCount = 0;\n\n            // Only allow dragging multiple GameObjects, or multiple non-GameObjects, but not mixed sets.\n            // For example when dragging GameObjects and Materials would sometimes apply material to\n            // already existing scene object, and other times to the object being spawned. It depends\n            // on the order in which the user selects those assets. We decided it was not an intuitive\n            // behavior and it should just not be allowed.\n            // Also we don't want multiple materials be dropped into scene because there is no case\n            // where we can handle it in a way that benefit the user. For example multiple skybox\n            // materials doesn't make sense and dropping multiple materials onto geometry will only\n            // drop the first material on the hovered material entry.\n            foreach (Object obj in objects)\n            {\n                if (obj.GetType() == typeof(GameObject))\n                {\n                    gameObjectCount++;\n                }\n                else\n                {\n                    assetCount++;\n                    if (obj.GetType() == typeof(Material))\n                    {\n                        materialCount++;\n                    }\n                }\n\n                if (gameObjectCount > 0 && assetCount > 0 || materialCount > 1) return false;\n            }\n\n            return true;\n        }\n\n        internal void HandleDragging(Event evt)\n        {\n            Object[] dragAndDropObjects = DragAndDrop.objectReferences;\n\n            switch (evt.type)\n            {\n                case EventType.DragPerform:\n                case EventType.DragUpdated:\n                    if (evt.type == EventType.DragPerform && GameObjectInspector.s_CyclicNestingDetected)\n                    {\n                        PrefabUtility.ShowCyclicNestingWarningDialog();\n                        return;\n                    }\n\n                    if (!CanDoDrag(dragAndDropObjects))\n                    {\n                        DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;\n                        return;\n                    }\n\n                    bool isPerform = evt.type == EventType.DragPerform;\n                    GameObject pickedObject = null;\n                    Transform parentTransform = null;\n                    bool dropHandled = false;\n\n                    // Allow user defined Custom Drop Handler\n                    if (DragAndDrop.HasHandler(DragAndDropWindowTarget.sceneView))\n                    {\n                        PickObject(ref pickedObject, ref parentTransform);\n                        Vector3 worldPosition = HandleUtility.PlaceObject(Event.current.mousePosition, out Vector3 placedPosition, out _) ? placedPosition : pivot;\n                        DragAndDrop.visualMode = DragAndDrop.DropOnSceneWindow(pickedObject, worldPosition, Event.current.mousePosition, parentTransform, isPerform);\n                        dropHandled = DragAndDrop.visualMode != DragAndDropVisualMode.None;\n                    }\n\n                    // Allow editor Wrapper Drop Handler\n                    var allObjectsHandled = false;\n                    if (!dropHandled)\n                    {\n                        allObjectsHandled = CallEditorDragFunctions(dragAndDropObjects);\n                    }\n\n                    if (evt.type == EventType.Used || allObjectsHandled)\n                        return;\n\n                    // C++ legacy Drop Handler\n                    if (!dropHandled)\n                    {\n                        if (pickedObject == null || parentTransform == null)\n                            PickObject(ref pickedObject, ref parentTransform);\n\n                        Vector3 worldPosition = HandleUtility.PlaceObject(Event.current.mousePosition, out Vector3 placedPosition, out _) ? placedPosition : pivot;\n                        DragAndDrop.visualMode = InternalEditorUtility.SceneViewDrag(pickedObject, worldPosition, Event.current.mousePosition, parentTransform, isPerform);\n                    }\n\n                    evt.Use();\n                    if (isPerform && DragAndDrop.visualMode != DragAndDropVisualMode.None && DragAndDrop.visualMode != DragAndDropVisualMode.Rejected)\n                    {\n                        DragAndDrop.AcceptDrag();\n                        // Bail out as state can be messed up by now.\n                        GUIUtility.ExitGUI();\n                    }\n                    break;\n                case EventType.DragExited:\n                    CallEditorDragFunctions(dragAndDropObjects);\n                    CleanupEditorDragFunctions();\n                    break;\n            }\n        }\n\n        void PickObject(ref GameObject dropUpon, ref Transform parentTransform)\n        {\n            var defaultParentObject = GetDefaultParentObjectIfSet();\n            parentTransform = defaultParentObject != null ? defaultParentObject : customParentForDraggedObjects;\n            dropUpon = HandleUtility.PickGameObject(Event.current.mousePosition, true);\n        }\n\n        void CommandsGUI()\n        {\n            // @TODO: Validation should be more accurate based on what the view supports\n\n            bool execute = Event.current.type == EventType.ExecuteCommand;\n\n            switch (Event.current.commandName)\n            {\n                case EventCommandNames.Find:\n                    if (execute)\n                        FocusSearchField();\n                    Event.current.Use();\n                    break;\n                case EventCommandNames.FrameSelected:\n                    if (execute && Tools.s_ButtonDown != 1)\n                    {\n                        FrameSelected(false);\n                    }\n                    Event.current.Use();\n                    break;\n                case EventCommandNames.FrameSelectedWithLock:\n                    if (execute && Tools.s_ButtonDown != 1)\n                    {\n                        FrameSelected(true);\n                    }\n                    Event.current.Use();\n                    break;\n                case EventCommandNames.SoftDelete:\n                case EventCommandNames.Delete:\n                    if (execute)\n                        Unsupported.DeleteGameObjectSelection();\n                    Event.current.Use();\n                    break;\n                case EventCommandNames.Duplicate:\n                    if (execute)\n                    {\n                        ClipboardUtility.DuplicateGO(customParentForNewGameObjects);\n                    }\n                    Event.current.Use();\n                    break;\n                case EventCommandNames.Copy:\n                    if (execute)\n                    {\n                        ClipboardUtility.CopyGO();\n                    }\n                    Event.current.Use();\n                    break;\n                case EventCommandNames.Cut:\n                    if (execute)\n                    {\n                        ClipboardUtility.CutGO();\n                    }\n                    Event.current.Use();\n                    break;\n                case EventCommandNames.Paste:\n                    if (execute)\n                    {\n                        ClipboardUtility.PasteGO(customParentForNewGameObjects);\n                    }\n                    Event.current.Use();\n                    break;\n                case EventCommandNames.SelectAll:\n                    if (execute)\n                    {\n                        var gameObjects = FindObjectsByType<GameObject>(FindObjectsSortMode.InstanceID);\n                        var objs = new List<Object>(gameObjects.Length);\n                        foreach (var go in gameObjects)\n                            if (SceneVisibilityManager.instance.IsSelectable(go))\n                                objs.Add(go);\n                        Selection.objects = objs.ToArray();\n                    }\n\n                    Event.current.Use();\n                    break;\n                case EventCommandNames.DeselectAll:\n                    if (execute)\n                        Selection.activeGameObject = null;\n                    Event.current.Use();\n                    break;\n                case EventCommandNames.InvertSelection:\n                    if (execute)\n                    {\n                        Selection.objects = FindObjectsByType<GameObject>(FindObjectsSortMode.InstanceID).Except(Selection.gameObjects).Where(SceneVisibilityManager.instance.IsSelectable).ToArray();\n                    }\n                    Event.current.Use();\n                    break;\n                case EventCommandNames.SelectChildren:\n                    if (execute)\n                    {\n                        List<GameObject> gameObjects = new List<GameObject>(Selection.gameObjects);\n                        foreach (var gameObject in Selection.gameObjects)\n                        {\n                            gameObjects.AddRange(gameObject.transform.GetComponentsInChildren<Transform>(true).Select(t => t.gameObject));\n                        }\n                        Selection.objects = gameObjects.Distinct().Cast<Object>().ToArray();\n                    }\n                    Event.current.Use();\n                    break;\n                case EventCommandNames.SelectPrefabRoot:\n                    if (execute)\n                    {\n                        List<GameObject> gameObjects = new List<GameObject>(Selection.gameObjects.Length);\n                        foreach (var gameObject in Selection.gameObjects)\n                        {\n                            var root = PrefabUtility.GetOutermostPrefabInstanceRoot(gameObject);\n                            if (root != null)\n                            {\n                                gameObjects.Add(root);\n                            }\n                        }\n                        Selection.objects = gameObjects.Distinct().Cast<Object>().ToArray();\n                    }\n                    Event.current.Use();\n                    break;\n            }\n            // Detect if we are canceling 'Cut' operation\n            if (Event.current.keyCode == KeyCode.Escape && CutBoard.hasCutboardData)\n            {\n                ClipboardUtility.ResetCutboardAndRepaintHierarchyWindows();\n                Repaint();\n            }\n        }\n\n        public void AlignViewToObject(Transform t)\n        {\n            FixNegativeSize();\n            size = 10;\n            LookAt(t.position + t.forward * CalcCameraDist(), t.rotation);\n        }\n\n        public void AlignWithView()\n        {\n            FixNegativeSize();\n            Vector3 center = camera.transform.position;\n            Vector3 dif = center - Tools.handlePosition;\n            Quaternion delta = Quaternion.Inverse(Selection.activeTransform.rotation) * camera.transform.rotation;\n            float angle;\n            Vector3 axis;\n            delta.ToAngleAxis(out angle, out axis);\n            axis = Selection.activeTransform.TransformDirection(axis);\n\n            Undo.RecordObjects(Selection.transforms, \"Align with view\");\n\n            foreach (Transform t in Selection.transforms)\n            {\n                t.position += dif;\n                t.RotateAround(center, axis, angle);\n            }\n        }\n\n        public void MoveToView()\n        {\n            FixNegativeSize();\n            Vector3 dif = pivot - Tools.handlePosition;\n            if (in2DMode) dif.z = 0f;\n\n            Undo.RecordObjects(Selection.transforms, \"Move to view\");\n\n            foreach (Transform t in Selection.transforms)\n            {\n                t.position += dif;\n            }\n        }\n\n        public void MoveToView(Transform target)\n        {\n            var pos = pivot;\n            if (in2DMode) pos.z = target.position.z;\n            target.position = pos;\n        }\n\n        internal void AlignWithView(Transform target)\n        {\n            target.position = camera.transform.position;\n            target.rotation = camera.transform.rotation;\n        }\n\n        internal bool IsGameObjectInThisSceneView(GameObject gameObject)\n        {\n            if (gameObject == null)\n                return false;\n\n            return !StageUtility.IsGizmoCulledBySceneCullingMasksOrFocusedScene(gameObject, camera);\n        }\n\n        public bool FrameSelected()\n        {\n            return FrameSelected(false);\n        }\n\n        public bool FrameSelected(bool lockView)\n        {\n            return FrameSelected(lockView, false);\n        }\n\n        public virtual bool FrameSelected(bool lockView, bool instant)\n        {\n            if (!IsGameObjectInThisSceneView(Selection.activeGameObject))\n                return false;\n\n            viewIsLockedToObject = lockView;\n            FixNegativeSize();\n\n            Bounds bounds;\n            if (!m_WasFocused)\n            {\n                bounds = InternalEditorUtility.CalculateSelectionBounds(false, false, true);\n            }\n            else\n            {\n                bounds = new Bounds(Tools.handlePosition, Vector3.one);\n            }\n\n            // Check active editor for OnGetFrameBounds\n            foreach (Editor editor in activeEditors)\n            {\n                MethodInfo hasBoundsMethod = editor.GetType().GetMethod(\"HasFrameBounds\", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);\n\n                if (hasBoundsMethod != null)\n                {\n                    object hasBounds = hasBoundsMethod.Invoke(editor, null);\n                    if (hasBounds is bool && (bool)hasBounds)\n                    {\n                        MethodInfo getBoundsMethod = editor.GetType().GetMethod(\"OnGetFrameBounds\", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);\n\n                        if (getBoundsMethod != null)\n                        {\n                            object obj = getBoundsMethod.Invoke(editor, null);\n                            if (obj is Bounds)\n                                bounds = (Bounds)obj;\n                        }\n                    }\n                }\n            }\n\n            m_WasFocused = !m_WasFocused;\n            return Frame(bounds, EditorApplication.isPlaying || instant);\n        }\n\n        public bool Frame(Bounds bounds, bool instant = true)\n        {\n            float newSize = bounds.extents.magnitude;\n\n            if (float.IsInfinity(newSize))\n                return false;\n\n            // If we have no size to focus on, bound default 10 units\n            if (newSize < Mathf.Epsilon)\n                newSize = 10;\n\n            // We snap instantly into target on playmode, because things might be moving fast and lerping lags behind\n            LookAt(bounds.center, m_Rotation.target, newSize, m_Ortho.value, instant);\n\n            return true;\n        }\n\n        void CreateSceneCameraAndLights()\n        {\n            GameObject cameraGO = EditorUtility.CreateGameObjectWithHideFlags(\"SceneCamera\", HideFlags.HideAndDontSave, typeof(Camera));\n            cameraGO.AddComponent<FlareLayer>();\n\n            m_Camera = cameraGO.GetComponent<Camera>();\n            m_Camera.enabled = false;\n            m_Camera.cameraType = CameraType.SceneView;\n            m_Camera.scene = m_CustomScene;\n            if (m_OverrideSceneCullingMask != 0)\n                m_Camera.overrideSceneCullingMask = m_OverrideSceneCullingMask;\n\n            m_CustomLightsScene = EditorSceneManager.NewPreviewScene();\n            m_CustomLightsScene.name = \"CustomLightsScene-SceneView\" + m_WindowGUID;\n            for (int i = 0; i < 3; i++)\n            {\n                GameObject lightGO = EditorUtility.CreateGameObjectWithHideFlags(\"SceneLight\", HideFlags.HideAndDontSave, typeof(Light));\n                m_Light[i] = lightGO.GetComponent<Light>();\n                m_Light[i].type = LightType.Directional;\n                m_Light[i].intensity = 1.0f;\n                m_Light[i].enabled = false;\n                SceneManager.MoveGameObjectToScene(lightGO, m_CustomLightsScene);\n            }\n            m_Light[0].color = kSceneViewFrontLight;\n\n            m_Light[1].color = kSceneViewUpLight - kSceneViewMidLight;\n            m_Light[1].transform.LookAt(Vector3.down);\n            m_Light[1].renderMode = LightRenderMode.ForceVertex;\n\n            m_Light[2].color = kSceneViewDownLight - kSceneViewMidLight;\n            m_Light[2].transform.LookAt(Vector3.up);\n            m_Light[2].renderMode = LightRenderMode.ForceVertex;\n\n            HandleUtility.handleMaterial.SetColor(\"_SkyColor\", kSceneViewUpLight * 1.5f);\n            HandleUtility.handleMaterial.SetColor(\"_GroundColor\", kSceneViewDownLight * 1.5f);\n            HandleUtility.handleMaterial.SetColor(\"_Color\", kSceneViewFrontLight * 1.5f);\n        }\n\n        struct EditorActionCache\n        {\n            private readonly Dictionary<Type, Action<Editor>> m_Cache;\n            private readonly string m_MethodName;\n\n            public EditorActionCache(string methodName)\n            {\n                m_MethodName = methodName;\n                m_Cache = new Dictionary<Type, Action<Editor>>();\n            }\n\n            public Action<Editor> GetAction(Type type)\n            {\n                if (!m_Cache.TryGetValue(type, out var onSceneGui))\n                {\n                    MethodInfo method = type.GetMethod(\n                        m_MethodName,\n                        BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy,\n                        null,\n                        Type.EmptyTypes,\n                        null);\n                    if (method == null)\n                        m_Cache[type] = null;\n                    else\n                    {\n                        var param = Expression.Parameter(typeof(Editor), \"a\");\n                        onSceneGui = m_Cache[type] = Expression.Lambda<Action<Editor>>(\n                            Expression.Call(Expression.Convert(param, type), method),\n                            param\n                        ).Compile();\n                    }\n                }\n\n                return onSceneGui;\n            }\n        }\n\n        private static EditorActionCache s_OnSceneGuiCache = new EditorActionCache(\"OnSceneGUI\");\n        private static EditorActionCache s_OnPreSceneGuiCache = new EditorActionCache(\"OnPreSceneGUI\");\n\n        void CallOnSceneGUI()\n        {\n            if (drawGizmos)\n            {\n                foreach (Editor editor in activeEditors)\n                {\n                    if (!EditorGUIUtility.IsGizmosAllowedForObject(editor.target))\n                        continue;\n\n                    var onSceneGui = s_OnSceneGuiCache.GetAction(editor.GetType());\n                    if (onSceneGui != null)\n                    {\n                        MethodInfo methodEnabled = editor.GetType().GetMethod(\n                            \"IsSceneGUIEnabled\",\n                            BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static |\n                            BindingFlags.FlattenHierarchy,\n                            null,\n                            Type.EmptyTypes,\n                            null);\n\n                        bool enabled = (methodEnabled != null) ? (bool) methodEnabled.Invoke(null, null) : true;\n                        if (enabled)\n                        {\n                            using (new EditorPerformanceMarker($\"Editor.{editor.GetType().Name}.OnSceneGUI\", editor.GetType()).Auto())\n                            {\n                                Editor.m_AllowMultiObjectAccess = true;\n                                bool canEditMultipleObjects = editor.canEditMultipleObjects;\n                                for (int n = 0; n < editor.targets.Length; n++)\n                                {\n                                    ResetOnSceneGUIState();\n                                    editor.referenceTargetIndex = n;\n\n                                    EditorGUI.BeginChangeCheck();\n                                    // Ironically, only allow multi object access inside OnSceneGUI if editor does NOT support multi-object editing.\n                                    // since there's no harm in going through the serializedObject there if there's always only one target.\n                                    Editor.m_AllowMultiObjectAccess = !canEditMultipleObjects;\n                                    onSceneGui(editor);\n                                    Editor.m_AllowMultiObjectAccess = true;\n                                    if (EditorGUI.EndChangeCheck())\n                                        editor.serializedObject.SetIsDifferentCacheDirty();\n\n                                }\n\n                                ResetOnSceneGUIState();\n                            }\n                        }\n\n                        // This would mean that OnSceneGUI has changed the scene and it is not drawn\n                        if (s_CurrentDrawingSceneView == null)\n                            GUIUtility.ExitGUI();\n                    }\n                }\n                EditorToolManager.InvokeOnSceneGUICustomEditorTools();\n            }\n\n\n            if (duringSceneGui != null)\n            {\n                ResetOnSceneGUIState();\n\n                if (duringSceneGui != null)\n                    duringSceneGui(this);\n\n#pragma warning disable 618\n                if (onSceneGUIDelegate != null)\n                    onSceneGUIDelegate(this);\n#pragma warning restore 618\n\n                ResetOnSceneGUIState();\n            }\n        }\n\n        void ResetOnSceneGUIState()\n        {\n            Handles.ClearHandles();\n            HandleUtility.s_CustomPickDistance = HandleUtility.kPickDistance;\n            EditorGUIUtility.ResetGUIState();\n\n            // Don't apply any playmode tinting to scene views\n            GUI.color = Color.white;\n        }\n\n        void CallOnPreSceneGUI()\n        {\n            foreach (Editor editor in activeEditors)\n            {\n                // reset the handles matrix, OnPreSceneGUI calls may change it.\n                Handles.ClearHandles();\n\n                // Don't call function for editors whose target's GameObject is not active.\n                Component comp = editor.target as Component;\n                if (comp && !comp.gameObject.activeInHierarchy)\n                    continue;\n\n                var onPreSceneGui = s_OnPreSceneGuiCache.GetAction(editor.GetType());\n\n                if (onPreSceneGui != null)\n                {\n                    using (new EditorPerformanceMarker($\"Editor.{editor.GetType().Name}.OnPreSceneGUI\", editor.GetType()).Auto())\n                    {\n                        bool canEditMultipleObjects = editor.canEditMultipleObjects;\n                        Editor.m_AllowMultiObjectAccess = true;\n                        for (int n = 0; n < editor.targets.Length; n++)\n                        {\n                            editor.referenceTargetIndex = n;\n                            // Ironically, only allow multi object access inside OnPreSceneGUI if editor does NOT support multi-object editing.\n                            // since there's no harm in going through the serializedObject there if there's always only one target.\n                            Editor.m_AllowMultiObjectAccess = !canEditMultipleObjects;\n                            onPreSceneGui(editor);\n                            Editor.m_AllowMultiObjectAccess = true;\n                        }\n                    }\n                }\n            }\n\n            if (beforeSceneGui != null)\n            {\n                Handles.ClearHandles();\n                beforeSceneGui(this);\n            }\n\n            // reset the handles matrix, calls above calls might have changed it\n            Handles.ClearHandles();\n        }\n\n        internal static void ShowNotification(string notificationText)\n        {\n            Object[] allSceneViews = Resources.FindObjectsOfTypeAll(typeof(SceneView));\n            var notificationViews = new List<EditorWindow>();\n            foreach (SceneView sceneView in allSceneViews)\n            {\n                if (sceneView.m_Parent is DockArea)\n                {\n                    var dock = (DockArea)sceneView.m_Parent;\n                    if (dock)\n                    {\n                        if (dock.actualView == sceneView)\n                        {\n                            notificationViews.Add(sceneView);\n                        }\n                    }\n                }\n            }\n\n            if (notificationViews.Count > 0)\n            {\n                foreach (EditorWindow notificationView in notificationViews)\n                    notificationView.ShowNotification(GUIContent.Temp(notificationText));\n            }\n            else\n            {\n                Debug.LogError(notificationText);\n            }\n        }\n\n        [RequiredByNativeCode]\n        static void ShowCompileErrorNotification()\n        {\n            ShowNotification(\"All compiler errors have to be fixed before you can enter playmode!\");\n        }\n\n        [RequiredByNativeCode]\n        internal static void ShowSceneViewPlayModeSaveWarning()\n        {\n            // In this case, we want to explicitly try the GameView before passing it on to whatever notificationView we have\n            var playModeView = (PlayModeView)WindowLayout.FindEditorWindowOfType(typeof(PlayModeView));\n            if (playModeView != null && playModeView.hasFocus)\n                playModeView.ShowNotification(EditorGUIUtility.TrTextContent(\"You must exit play mode to save the scene!\"));\n            else\n                ShowNotification(\"You must exit play mode to save the scene!\");\n        }\n\n        void ResetToDefaults(EditorBehaviorMode behaviorMode)\n        {\n            switch (behaviorMode)\n            {\n                case EditorBehaviorMode.Mode2D:\n                    m_2DMode = true;\n                    m_Rotation.value = Quaternion.identity;\n                    m_Position.value = kDefaultPivot;\n                    size = kDefaultViewSize;\n                    m_Ortho.value = true;\n\n                    m_LastSceneViewRotation = kDefaultRotation;\n                    m_LastSceneViewOrtho = false;\n                    break;\n\n                default: // Default to 3D mode (BUGFIX:569204)\n                    m_2DMode = false;\n                    m_Rotation.value = kDefaultRotation;\n                    m_Position.value = kDefaultPivot;\n                    size = kDefaultViewSize;\n                    m_Ortho.value = false;\n                    break;\n            }\n        }\n\n        internal void OnNewProjectLayoutWasCreated()\n        {\n            ResetToDefaults(EditorSettings.defaultBehaviorMode);\n        }\n\n        void OnViewpointChanged(bool activeViewpoint)\n        {\n            On2DModeChange();\n        }\n\n        void On2DModeChange()\n        {\n            if (m_WasIn2DMode == in2DMode)\n                return;\n\n            if (in2DMode)\n            {\n                lastSceneViewRotation = m_Rotation.target;\n                m_LastSceneViewOrtho = orthographic;\n                LookAt(pivot, Quaternion.identity, size, true);\n                if (Tools.current == Tool.Move)\n                    Tools.current = Tool.Rect;\n            }\n            else\n            {\n                LookAt(pivot, lastSceneViewRotation, size, m_LastSceneViewOrtho);\n                if (Tools.current == Tool.Rect)\n                    Tools.current = Tool.Move;\n            }\n\n            // Let's not persist the vertex snapping mode on 2D/3D mode change\n            HandleUtility.ignoreRaySnapObjects = null;\n            Tools.vertexDragging = false;\n            Tools.handleOffset = Vector3.zero;\n            UpdateOrientationGizmos();\n\n            m_WasIn2DMode = in2DMode;\n        }\n\n        public static CameraMode AddCameraMode(string name, string section)\n        {\n            if (string.IsNullOrEmpty(name))\n                throw new ArgumentException(\"Cannot be null or empty\", \"name\");\n            if (string.IsNullOrEmpty(section))\n                throw new ArgumentException(\"Cannot be null or empty\", \"section\");\n            var newMode = new CameraMode(DrawCameraMode.UserDefined, name, section);\n            if (userDefinedModes.Contains(newMode))\n                throw new InvalidOperationException(string.Format(\"A mode named {0} already exists in section {1}\", name, section));\n            userDefinedModes.Add(newMode);\n            return newMode;\n        }\n\n        private static bool IsValidCameraMode(CameraMode cameraMode)\n        {\n            foreach (var mode in Enum.GetValues(typeof(DrawCameraMode)))\n            {\n                if (SceneRenderModeWindow.DrawCameraModeExists((DrawCameraMode)mode) && cameraMode == GetBuiltinCameraMode((DrawCameraMode)mode))\n                {\n                    return true;\n                }\n            }\n\n            foreach (var tempCameraMode in userDefinedModes)\n            {\n                if (tempCameraMode == cameraMode)\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public static void ClearUserDefinedCameraModes()\n        {\n            userDefinedModes.Clear();\n        }\n\n        public static CameraMode GetBuiltinCameraMode(DrawCameraMode mode)\n        {\n            return SceneRenderModeWindow.GetBuiltinCameraMode(mode);\n        }\n\n        internal void RebuildBreadcrumbBar()\n        {\n            if (SupportsStageHandling())\n                m_StageHandling.RebuildBreadcrumbBar();\n        }\n\n        internal static void RebuildBreadcrumbBarInAll()\n        {\n            foreach (SceneView sv in s_SceneViews)\n            {\n                sv.RebuildBreadcrumbBar();\n            }\n        }\n\n        internal void ResetGridPivot()\n        {\n            sceneViewGrids.SetAllGridsPivot(Vector3.zero);\n        }\n\n        void CopyLastActiveSceneViewSettings()\n        {\n            SceneView view = lastActiveSceneView;\n            m_CameraMode = view.m_CameraMode;\n            sceneLighting = view.sceneLighting;\n            m_SceneViewState = new SceneViewState(lastActiveSceneView.m_SceneViewState);\n            m_CameraSettings = new CameraSettings(lastActiveSceneView.m_CameraSettings);\n            m_2DMode = view.m_2DMode;\n            pivot = view.pivot;\n            if(!m_2DMode)\n                rotation = view.rotation;\n            size = view.size;\n            m_Ortho.value = view.orthographic;\n            if (m_Grid == null)\n                m_Grid = new SceneViewGrid();\n            m_Grid.showGrid = view.showGrid;\n        }\n\n        internal void SetOverlayVisible(string id, bool show)\n        {\n            if (TryGetOverlay(id, out Overlay overlay))\n                overlay.displayed = show;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/SceneView/SceneViewGrid.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.AnimatedValues;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    static class GridSettings\n    {\n        const float k_GridSizeMin = 0f;\n        const float k_GridSizeMax = 1024f;\n        const int k_DefaultMultiplier = 0;\n\n        public const float defaultGridSize = 1.0f;\n\n        static SavedFloat s_GridSizeX = new SavedFloat(\"GridSizeX\", defaultGridSize);\n        static SavedFloat s_GridSizeY = new SavedFloat(\"GridSizeY\", defaultGridSize);\n        static SavedFloat s_GridSizeZ = new SavedFloat(\"GridSizeZ\", defaultGridSize);\n        static SavedInt s_GridMultiplier = new SavedInt(\"GridMultiplier\", k_DefaultMultiplier);\n\n        static Vector3 rawSize\n        {\n            get { return new Vector3(s_GridSizeX, s_GridSizeY, s_GridSizeZ); }\n        }\n\n        internal static event Action<Vector3> sizeChanged = delegate {};\n\n        internal static bool linked => Mathf.Approximately(size.x, size.y) && Mathf.Approximately(size.x, size.z);\n\n        public static Vector3 size\n        {\n            get { return ApplyMultiplier(rawSize, s_GridMultiplier); }\n            set\n            {\n                if (size == value)\n                    return;\n                ResetSizeMultiplier();\n                s_GridSizeX.value = Mathf.Min(k_GridSizeMax, Mathf.Max(k_GridSizeMin, value.x));\n                s_GridSizeY.value = Mathf.Min(k_GridSizeMax, Mathf.Max(k_GridSizeMin, value.y));\n                s_GridSizeZ.value = Mathf.Min(k_GridSizeMax, Mathf.Max(k_GridSizeMin, value.z));\n                sizeChanged(size);\n            }\n        }\n\n        internal static int sizeMultiplier\n        {\n            get { return s_GridMultiplier.value; }\n            set\n            {\n                s_GridMultiplier.value = value;\n                sizeChanged?.Invoke(size);\n            }\n        }\n\n        internal static void ResetSizeMultiplier()\n        {\n            s_GridMultiplier.value = k_DefaultMultiplier;\n        }\n\n        static Vector3 ApplyMultiplier(Vector3 value, int mul)\n        {\n            if (mul > 0)\n            {\n                for (int i = 0; i < mul; i++)\n                    value *= 2f;\n            }\n            else if (mul < 0)\n            {\n                for (int i = 0; i > mul; i--)\n                    value /= 2f;\n            }\n            return value;\n        }\n\n        public static void ResetGridSettings()\n        {\n            size = new Vector3(defaultGridSize, defaultGridSize, defaultGridSize);\n        }\n    }\n\n    [System.Serializable]\n    class SceneViewGrid\n    {\n        public const float defaultGridOpacity = .5f;\n        public const GridRenderAxis defaultRenderAxis = GridRenderAxis.Y;\n        public const bool defaultShowGrid = true;\n\n        internal event Action<bool> gridVisibilityChanged = delegate(bool b) {};\n        internal event Action<GridRenderAxis> gridRenderAxisChanged = delegate(GridRenderAxis axis) {};\n\n        internal enum GridRenderAxis\n        {\n            X,\n            Y,\n            Z,\n            All\n        }\n\n        [System.Serializable]\n        internal class Grid\n        {\n            [SerializeField]\n            AnimBool m_Fade = new AnimBool();\n\n            [SerializeField]\n            Color m_Color;\n\n            [SerializeField]\n            Vector3 m_Pivot;\n\n            [SerializeField]\n            Vector2 m_Size;\n\n            internal AnimBool fade\n            {\n                get { return m_Fade; }\n                set { m_Fade = value; }\n            }\n\n            internal Color color\n            {\n                get { return m_Color; }\n                set { m_Color = value; }\n            }\n\n            internal Vector3 pivot\n            {\n                get { return m_Pivot; }\n                set { m_Pivot = value; }\n            }\n\n            internal Vector2 size\n            {\n                get { return m_Size; }\n                set { m_Size = value; }\n            }\n\n            internal DrawGridParameters PrepareGridRender(int gridID, float opacity)\n            {\n                DrawGridParameters parameters = default(DrawGridParameters);\n                parameters.gridID = gridID;\n                parameters.pivot = pivot;\n                parameters.color = color;\n                parameters.color.a = fade.faded * opacity;\n                parameters.size = size;\n\n                return parameters;\n            }\n        }\n\n        internal static PrefColor kViewGridColor = new PrefColor(\"Scene/Grid\", .5f, .5f, .5f, .4f);\n        static float k_AngleThresholdForOrthographicGrid = 0.15f;\n\n        [SerializeField]\n        Grid xGrid = new Grid();\n\n        [SerializeField]\n        Grid yGrid = new Grid();\n\n        [SerializeField]\n        Grid zGrid = new Grid();\n\n        [SerializeField]\n        bool m_ShowGrid = defaultShowGrid;\n\n        [SerializeField]\n        GridRenderAxis m_GridAxis = defaultRenderAxis;\n\n        [SerializeField]\n        float m_gridOpacity = defaultGridOpacity;\n\n        internal bool showGrid\n        {\n            get => m_ShowGrid;\n            set\n            {\n                if (value == m_ShowGrid)\n                    return;\n                m_ShowGrid = value;\n                gridVisibilityChanged(m_ShowGrid);\n            }\n        }\n\n        internal float gridOpacity\n        {\n            get => m_gridOpacity;\n            set => m_gridOpacity = Mathf.Clamp01(value);\n        }\n\n        internal GridRenderAxis gridAxis\n        {\n            get => m_GridAxis;\n            set\n            {\n                if (m_GridAxis == value) return;\n                m_GridAxis = value;\n                gridRenderAxisChanged(value);\n            }\n        }\n\n        internal Grid activeGrid\n        {\n            get\n            {\n                if (gridAxis == GridRenderAxis.X)\n                    return xGrid;\n                else if (gridAxis == GridRenderAxis.Y)\n                    return yGrid;\n                else if (gridAxis == GridRenderAxis.Z)\n                    return zGrid;\n                return yGrid;\n            }\n        }\n\n        internal void UpdateGridColor()\n        {\n            xGrid.color = yGrid.color = zGrid.color = kViewGridColor;\n        }\n\n        internal void OnEnable(SceneView view)\n        {\n            UpdateGridColor();\n\n            GridSettings.sizeChanged += GridSizeChanged;\n\n            // hook up the anims, so repainting can work correctly\n            xGrid.fade.valueChanged.AddListener(view.Repaint);\n            yGrid.fade.valueChanged.AddListener(view.Repaint);\n            zGrid.fade.valueChanged.AddListener(view.Repaint);\n        }\n\n        internal void OnDisable(SceneView view)\n        {\n            GridSettings.sizeChanged -= GridSizeChanged;\n\n            xGrid.fade.valueChanged.RemoveListener(view.Repaint);\n            yGrid.fade.valueChanged.RemoveListener(view.Repaint);\n            zGrid.fade.valueChanged.RemoveListener(view.Repaint);\n        }\n\n        void GridSizeChanged(Vector3 size)\n        {\n            SetPivot(GridRenderAxis.X, Snapping.Snap(GetPivot(GridRenderAxis.X), GridSettings.size));\n            SetPivot(GridRenderAxis.Y, Snapping.Snap(GetPivot(GridRenderAxis.Y), GridSettings.size));\n            SetPivot(GridRenderAxis.Z, Snapping.Snap(GetPivot(GridRenderAxis.Z), GridSettings.size));\n        }\n\n        internal void SetAllGridsPivot(Vector3 pivot)\n        {\n            xGrid.pivot = pivot;\n            yGrid.pivot = pivot;\n            zGrid.pivot = pivot;\n        }\n\n        internal void SetPivot(GridRenderAxis axis, Vector3 pivot)\n        {\n            if (axis == GridRenderAxis.X)\n                xGrid.pivot = pivot;\n            else if (axis == GridRenderAxis.Y)\n                yGrid.pivot = pivot;\n            else if (axis == GridRenderAxis.Z)\n                zGrid.pivot = pivot;\n        }\n\n        internal Vector3 GetPivot(GridRenderAxis axis)\n        {\n            if (axis == GridRenderAxis.X)\n                return xGrid.pivot;\n            else if (axis == GridRenderAxis.Y)\n                return yGrid.pivot;\n            else if (axis == GridRenderAxis.Z)\n                return zGrid.pivot;\n            return Vector3.zero;\n        }\n\n        internal void ResetPivot(GridRenderAxis axis)\n        {\n            if (axis == GridRenderAxis.X)\n                xGrid.pivot = Vector3.zero;\n            else if (axis == GridRenderAxis.Y)\n                yGrid.pivot = Vector3.zero;\n            else if (axis == GridRenderAxis.Z)\n                zGrid.pivot = Vector3.zero;\n            else if (axis == GridRenderAxis.All)\n                xGrid.pivot = yGrid.pivot = zGrid.pivot = Vector3.zero;\n        }\n\n        internal void UpdateGridsVisibility(Quaternion rotation, bool orthoMode)\n        {\n            bool showX = false, showY = false, showZ = false;\n\n            if (showGrid)\n            {\n                if (orthoMode)\n                {\n                    Vector3 fwd = rotation * Vector3.forward;\n\n                    // Show xy, zy and xz planes only when straight on\n                    if (fwd == Vector3.up || fwd == Vector3.down)\n                        showY = true;\n                    else if (fwd == Vector3.left || fwd == Vector3.right)\n                        showX = true;\n                    else if (fwd == Vector3.forward || fwd == Vector3.back)\n                        showZ = true;\n                }\n\n                // Main path for perspective mode.\n                // In ortho, fallback on this path if camera is not aligned with X, Y or Z axis.\n                if (!showX && !showY && !showZ)\n                {\n                    showX = (gridAxis == GridRenderAxis.X || gridAxis == GridRenderAxis.All);\n                    showY = (gridAxis == GridRenderAxis.Y || gridAxis == GridRenderAxis.All);\n                    showZ = (gridAxis == GridRenderAxis.Z || gridAxis == GridRenderAxis.All);\n                }\n            }\n\n            xGrid.fade.target = showX;\n            yGrid.fade.target = showY;\n            zGrid.fade.target = showZ;\n        }\n\n        internal void SkipFading()\n        {\n            xGrid.fade.SkipFading();\n            yGrid.fade.SkipFading();\n            zGrid.fade.SkipFading();\n        }\n\n        void ApplySnapConstraintsInPerspectiveMode()\n        {\n            switch (gridAxis)\n            {\n                case GridRenderAxis.X:\n                    ApplySnapContraintsOnXAxis();\n                    break;\n                case GridRenderAxis.Y:\n                    ApplySnapContraintsOnYAxis();\n                    break;\n                case GridRenderAxis.Z:\n                    ApplySnapContraintsOnZAxis();\n                    break;\n            }\n        }\n\n        void ApplySnapConstraintsInOrthogonalMode()\n        {\n            if (xGrid.fade.target)\n                ApplySnapContraintsOnXAxis();\n            if (yGrid.fade.target)\n                ApplySnapContraintsOnYAxis();\n            if (zGrid.fade.target)\n                ApplySnapContraintsOnZAxis();\n        }\n\n        void ApplySnapContraintsOnXAxis()\n        {\n            Vector3 grid = GridSettings.size;\n            xGrid.size = new Vector2(grid.y, grid.z);\n        }\n\n        void ApplySnapContraintsOnYAxis()\n        {\n            Vector3 grid = GridSettings.size;\n            yGrid.size = new Vector2(grid.z, grid.x);\n        }\n\n        void ApplySnapContraintsOnZAxis()\n        {\n            Vector3 grid = GridSettings.size;\n            zGrid.size = new Vector2(grid.x, grid.y);\n        }\n\n        internal DrawGridParameters PrepareGridRender(Camera camera, Vector3 pivot, Quaternion rotation,\n            float size, bool orthoMode)\n        {\n            UpdateGridsVisibility(rotation, orthoMode);\n\n            if (orthoMode)\n            {\n                ApplySnapConstraintsInOrthogonalMode();\n                return PrepareGridRenderOrthogonalMode(camera, pivot, rotation, size);\n            }\n\n            ApplySnapConstraintsInPerspectiveMode();\n            return PrepareGridRenderPerspectiveMode(camera, pivot, rotation, size);\n        }\n\n        DrawGridParameters PrepareGridRenderPerspectiveMode(Camera camera, Vector3 pivot, Quaternion rotation,\n            float size)\n        {\n            DrawGridParameters parameters = default(DrawGridParameters);\n\n            switch (gridAxis)\n            {\n                case GridRenderAxis.X:\n                    parameters = xGrid.PrepareGridRender(0, gridOpacity);\n                    break;\n                case GridRenderAxis.Y:\n                    parameters = yGrid.PrepareGridRender(1, gridOpacity);\n                    break;\n                case GridRenderAxis.Z:\n                    parameters = zGrid.PrepareGridRender(2, gridOpacity);\n                    break;\n            }\n\n            return parameters;\n        }\n\n        DrawGridParameters PrepareGridRenderOrthogonalMode(Camera camera, Vector3 pivot, Quaternion rotation,\n            float size)\n        {\n            Vector3 direction = camera.transform.TransformDirection(new Vector3(0, 0, 1));\n\n            DrawGridParameters parameters = default(DrawGridParameters);\n\n            // Don't show orthographic grid at very shallow angles because it looks bad.\n            // It's normally already faded out by the managed animated fading values at this angle,\n            // but if it's orbited rapidly, it can end up at this angle faster than the fading has kicked in.\n            // For these cases hiding it abruptly looks better.\n            // The popping isn't noticable because the user is orbiting rapidly to begin with.\n            if (xGrid.fade.target && Mathf.Abs(direction.x) >= k_AngleThresholdForOrthographicGrid)\n                parameters = xGrid.PrepareGridRender(0, gridOpacity);\n            else if (yGrid.fade.target && Mathf.Abs(direction.y) >= k_AngleThresholdForOrthographicGrid)\n                parameters = yGrid.PrepareGridRender(1, gridOpacity);\n            else if (zGrid.fade.target && Mathf.Abs(direction.z) >= k_AngleThresholdForOrthographicGrid)\n                parameters = zGrid.PrepareGridRender(2, gridOpacity);\n\n            return parameters;\n        }\n\n        internal void Reset()\n        {\n            gridOpacity = defaultGridOpacity;\n            showGrid = defaultShowGrid;\n            gridAxis = defaultRenderAxis;\n        }\n    }\n} // namespace\n"
  },
  {
    "path": "Editor/Mono/SceneView/SceneViewMotion.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.AnimatedValues;\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class SceneViewMotion\n    {\n        const string k_TemporaryPanTool2D1 = \"Scene View/2D Pan 1\";\n        const string k_TemporaryPanTool2D2 = \"Scene View/2D Pan 2\";\n        const string k_TemporaryPanTool1 = \"Scene View/Pan 1\";\n        const string k_TemporaryPanTool2 = \"Scene View/Pan 2\";\n        const string k_TemporaryPanTool3 = \"Scene View/Pan 3\";\n        const string k_TemporaryPanTool4 = \"Scene View/Pan 4\";\n        const string k_TemporaryZoomTool1 = \"Scene View/Zoom 1\";\n        const string k_TemporaryZoomTool2 = \"Scene View/Zoom 2\";\n        const string k_TemporaryOrbitTool = \"Scene View/Orbit\";\n        const string k_TemporaryFpsTool = \"Scene View/FPS Look\";\n        const string k_PanFocusTool = \"Scene View/Focus\";\n        const string k_LockedPanTool = \"Scene View/Pan (Locked)\";\n        const string k_LockedPanFocusTool = \"Scene View/Focus (Locked)\";\n\n        const string k_PanFocusEventCommandName = \"SceneViewPanFocusEventCommand\";\n        internal const string k_SetSceneViewMotionHotControlEventCommandName = \"SetSceneViewMotionHotControlEventCommand\"; // Also used in tests.\n\n        bool m_Moving;\n        public bool viewportsUnderMouse { get; set; }\n        static readonly CameraFlyModeContext s_CameraFlyModeContext = new CameraFlyModeContext();\n\n        readonly SceneViewViewport m_SceneViewViewportContext = new SceneViewViewport();\n        readonly SceneViewViewport2D m_SceneViewViewport2DContext = new SceneViewViewport2D();\n        readonly SceneViewViewport3D m_SceneViewViewport3DContext = new SceneViewViewport3D();\n        readonly SceneViewViewportLockedPanTool m_SceneViewViewportLockedPanToolContext = new SceneViewViewportLockedPanTool();\n\n        // used by Tests/EditModeAndPlayModeTests/SceneView/CameraFlyModeContextTests\n        internal AnimVector3 m_FlySpeed = new AnimVector3(Vector3.zero);\n\n        public static event Action viewToolActiveChanged;\n\n        Vector3 m_Motion;\n\n        Vector2 m_StartMousePosition; // The start mouse position is used for the pan focus tool.\n\n        float m_FlySpeedTarget = 0f;\n        float m_StartZoom = 0f;\n        float m_ZoomSpeed = 0f;\n        float m_TotalMotion = 0f;\n        float m_FPSScrollWheelMultiplier = .01f;\n        const float k_FlySpeedAcceleration = 1.8f;\n        public const float k_FlySpeed = 9f; // Also used in tests.\n\n        readonly int k_ViewToolID = GUIUtility.GetPermanentControlID();\n\n        readonly char[] k_TrimChars = new char[] { '0' };\n\n        public Vector3 cameraSpeed\n        {\n            get { return m_FlySpeed.value; }\n        }\n\n        bool m_Drag;\n        public bool isDragging // This is used in SceneView.\n        {\n            get { return m_Drag; }\n        }\n\n        static bool s_ViewToolIsActive = false;\n        public static bool viewToolIsActive => UpdateViewToolState();\n\n        public void RegisterShortcutContexts()\n        {\n            ShortcutIntegration.instance.contextManager.RegisterToolContext(m_SceneViewViewportContext);\n            ShortcutIntegration.instance.contextManager.RegisterToolContext(m_SceneViewViewport2DContext);\n            ShortcutIntegration.instance.contextManager.RegisterToolContext(m_SceneViewViewport3DContext);\n            ShortcutIntegration.instance.contextManager.RegisterToolContext(m_SceneViewViewportLockedPanToolContext);\n            ShortcutIntegration.instance.contextManager.RegisterToolContext(s_CameraFlyModeContext);\n        }\n\n        public void UnregisterShortcutContexts()\n        {\n            ShortcutIntegration.instance.contextManager.DeregisterToolContext(m_SceneViewViewportContext);\n            ShortcutIntegration.instance.contextManager.DeregisterToolContext(m_SceneViewViewport2DContext);\n            ShortcutIntegration.instance.contextManager.DeregisterToolContext(m_SceneViewViewport3DContext);\n            ShortcutIntegration.instance.contextManager.DeregisterToolContext(m_SceneViewViewportLockedPanToolContext);\n            ShortcutIntegration.instance.contextManager.DeregisterToolContext(s_CameraFlyModeContext);\n        }\n\n        internal abstract class SceneViewContext : IShortcutContext\n        {\n            public SceneView window => EditorWindow.focusedWindow as SceneView;\n            public virtual bool active => ViewHasFocus;\n            public static bool ViewHasFocus => (EditorWindow.focusedWindow is SceneView view) && view.sceneViewMotion != null;\n            public static bool ViewHasFocusAndViewportUnderMouse => ViewHasFocus && (EditorWindow.focusedWindow as SceneView).sceneViewMotion.viewportsUnderMouse;\n        }\n\n        [ReserveModifiers(ShortcutModifiers.Shift)]\n        internal class SceneViewViewport : SceneViewContext, IHelperBarShortcutContext\n        {\n            public override bool active => ViewHasFocusAndViewportUnderMouse;\n            public bool helperBarActive => base.active;\n        }\n\n        [ReserveModifiers(ShortcutModifiers.Shift)]\n        class SceneViewViewport2D : SceneViewContext, IHelperBarShortcutContext\n        {\n            public override bool active => ViewHasFocusAndViewportUnderMouse && (window.in2DMode || window.isRotationLocked);\n            public bool helperBarActive => base.active && (window.in2DMode || window.isRotationLocked);\n        }\n\n        [ReserveModifiers(ShortcutModifiers.Shift)]\n        class SceneViewViewport3D : SceneViewContext, IHelperBarShortcutContext\n        {\n            public override bool active => ViewHasFocusAndViewportUnderMouse && !window.in2DMode && !window.isRotationLocked;\n            public bool helperBarActive => base.active && !window.in2DMode && !window.isRotationLocked;\n        }\n\n        [ReserveModifiers(ShortcutModifiers.Shift)]\n        class SceneViewViewportLockedPanTool : SceneViewContext, IHelperBarShortcutContext\n        {\n            public override bool active => ViewHasFocusAndViewportUnderMouse && Tools.current == Tool.View;\n            public bool helperBarActive => base.active && Tools.current == Tool.View;\n        }\n\n        [Shortcut(k_PanFocusTool, typeof(SceneViewViewport), KeyCode.Mouse2)]\n        [Shortcut(k_LockedPanFocusTool, typeof(SceneViewViewportLockedPanTool), KeyCode.Mouse0)]\n        static void PanFocus(ShortcutArguments args)\n        {\n            // Delaying the picking to a command event is necessary because some HandleUtility methods\n            // need to be called in an OnGUI.\n            if (args.context is SceneViewContext ctx && ctx.window != null)\n                ctx.window.SendEvent(EditorGUIUtility.CommandEvent(k_PanFocusEventCommandName));\n        }\n\n        void PanFocus(Vector2 mousePos, SceneView currentSceneView, Event evt)\n        {\n            // Move pivot to clicked point.\n            RaycastHit hit;\n            if (RaycastWorld(mousePos, out hit))\n            {\n                Vector3 currentPosition = currentSceneView.pivot - currentSceneView.rotation * Vector3.forward * currentSceneView.cameraDistance;\n                float targetSize = currentSceneView.size;\n\n                if (!currentSceneView.orthographic)\n                    targetSize = currentSceneView.size * Vector3.Dot(hit.point - currentPosition, currentSceneView.rotation * Vector3.forward) / currentSceneView.cameraDistance;\n\n                currentSceneView.LookAt(hit.point, currentSceneView.rotation, targetSize);\n            }\n\n            evt.Use();\n        }\n\n        [ClutchShortcut(k_TemporaryPanTool2D1, typeof(SceneViewViewport2D), KeyCode.Mouse1)]\n        [ClutchShortcut(k_TemporaryPanTool2D2, typeof(SceneViewViewport2D), KeyCode.Mouse0, ShortcutModifiers.Alt)]\n        [ClutchShortcut(k_TemporaryPanTool1, typeof(SceneViewViewport), KeyCode.Mouse2)]\n        [ClutchShortcut(k_TemporaryPanTool2, typeof(SceneViewViewport), KeyCode.Mouse2, ShortcutModifiers.Alt)]\n        [ClutchShortcut(k_TemporaryPanTool3, typeof(SceneViewViewport), KeyCode.Mouse0, ShortcutModifiers.Action | ShortcutModifiers.Alt)]\n        [ClutchShortcut(k_TemporaryPanTool4, typeof(SceneViewViewport), KeyCode.Mouse2, ShortcutModifiers.Action | ShortcutModifiers.Alt)]\n        [ClutchShortcut(k_LockedPanTool, typeof(SceneViewViewportLockedPanTool), KeyCode.Mouse0)]\n        static void TemporaryPan(ShortcutArguments args)\n        {\n            if (args.context is SceneViewContext ctx && ctx.window != null && ctx.window.sceneViewMotion != null)\n                ctx.window.sceneViewMotion.HandleSceneViewMotionTool(args, ViewTool.Pan, ctx.window);\n        }\n\n        [ClutchShortcut(k_TemporaryZoomTool1, typeof(SceneViewViewport), KeyCode.Mouse1, ShortcutModifiers.Alt)]\n        [ClutchShortcut(k_TemporaryZoomTool2, typeof(SceneViewViewport), KeyCode.Mouse1, ShortcutModifiers.Action | ShortcutModifiers.Alt)]\n        static void TemporaryZoom(ShortcutArguments args)\n        {\n            if (args.context is SceneViewContext ctx && ctx.window != null && ctx.window.sceneViewMotion != null)\n                ctx.window.sceneViewMotion.HandleSceneViewMotionTool(args, ViewTool.Zoom, ctx.window);\n        }\n\n        [ClutchShortcut(k_TemporaryOrbitTool, typeof(SceneViewViewport3D), KeyCode.Mouse0, ShortcutModifiers.Alt)]\n        static void TemporaryOrbit(ShortcutArguments args)\n        {\n            if (args.context is SceneViewContext ctx && ctx.window != null && ctx.window.sceneViewMotion != null)\n                ctx.window.sceneViewMotion.HandleSceneViewMotionTool(args, ViewTool.Orbit, ctx.window);\n        }\n\n        void HandleSceneViewMotionTool(ShortcutArguments args, ViewTool viewTool, SceneView view)\n        {\n            if (args.stage == ShortcutStage.Begin && GUIUtility.hotControl == 0)\n                StartSceneViewMotionTool(viewTool, view);\n            else if (args.stage == ShortcutStage.End && Tools.s_LockedViewTool == viewTool)\n                CompleteSceneViewMotionTool();\n        }\n\n        [ClutchShortcut(k_TemporaryFpsTool, typeof(SceneViewViewport3D), typeof(CameraFlyModeContext), KeyCode.Mouse1)]\n        static void TemporaryFPS(ShortcutArguments args)\n        {\n            if (!(args.context is SceneViewViewport3D context)\n                || context.window == null\n                || context.window.sceneViewMotion == null)\n                return;\n\n            if (args.stage == ShortcutStage.Begin && GUIUtility.hotControl == 0)\n            {\n                s_CameraFlyModeContext.window = context.window;\n                context.window.sceneViewMotion.StartSceneViewMotionTool(ViewTool.FPS, context.window);\n            }\n            else if (args.stage == ShortcutStage.End && Tools.s_LockedViewTool == ViewTool.FPS)\n            {\n                s_CameraFlyModeContext.window = null;\n                context.window.sceneViewMotion.CompleteSceneViewMotionTool();\n            }\n        }\n\n        // slightly different logic for arrow keys - forward and backward axes are swapped for up and down when in\n        // orthographic or 2D mode\n        static void SetCameraMoveDirectionArrow(ShortcutArguments args, SceneInputAxis axis)\n        {\n            if (!(args.context is SceneViewContext ctx) || !(ctx.window is SceneView view))\n                return;\n\n            if (args.stage == ShortcutStage.Begin)\n                view.sceneViewMotion.StartSceneViewMotionTool(ViewTool.FPS, view);\n            else if (args.stage == ShortcutStage.End)\n                view.sceneViewMotion.CompleteSceneViewMotionTool();\n\n            if (view.in2DMode || view.orthographic)\n            {\n                axis = axis switch\n                {\n                    SceneInputAxis.Forward => SceneInputAxis.Up,\n                    SceneInputAxis.Backward => SceneInputAxis.Down,\n                    _ => axis\n                };\n            }\n\n            SceneNavigationInput.input[axis] = args.stage == ShortcutStage.Begin;\n            ctx.window.Repaint();\n        }\n\n        [ClutchShortcut(\"3D Viewport/Fly Mode Forward (Alt)\", typeof(SceneViewViewport), KeyCode.UpArrow)]\n        static void WalkForwardArrow(ShortcutArguments args) => SetCameraMoveDirectionArrow(args, SceneInputAxis.Forward);\n\n        [ClutchShortcut(\"3D Viewport/Fly Mode Backward (Alt)\", typeof(SceneViewViewport), KeyCode.DownArrow)]\n        static void WalkBackwardArrow(ShortcutArguments args) => SetCameraMoveDirectionArrow(args, SceneInputAxis.Backward);\n\n        [ClutchShortcut(\"3D Viewport/Fly Mode Left (Alt)\", typeof(SceneViewViewport), KeyCode.LeftArrow)]\n        static void WalkLeftArrow(ShortcutArguments args) => SetCameraMoveDirectionArrow(args, SceneInputAxis.Left);\n\n        [ClutchShortcut(\"3D Viewport/Fly Mode Right (Alt)\", typeof(SceneViewViewport), KeyCode.RightArrow)]\n        static void WalkRightArrow(ShortcutArguments args) => SetCameraMoveDirectionArrow(args, SceneInputAxis.Right);\n\n        static void SetInputVector(ShortcutArguments args, SceneInputAxis axis)\n        {\n            SceneNavigationInput.input[axis] = args.stage == ShortcutStage.Begin;\n            var context = (CameraFlyModeContext) args.context;\n            context.window.Repaint();\n        }\n\n        [ClutchShortcut(\"3D Viewport/Fly Mode Forward\", typeof(CameraFlyModeContext), KeyCode.W)]\n        [FormerlyPrefKeyAs(\"View/FPS Forward\", \"w\")]\n        static void WalkForward(ShortcutArguments args) => SetInputVector(args, SceneInputAxis.Forward);\n\n        [ClutchShortcut(\"3D Viewport/Fly Mode Backward\", typeof(CameraFlyModeContext), KeyCode.S)]\n        [FormerlyPrefKeyAs(\"View/FPS Back\", \"s\")]\n        static void WalkBackward(ShortcutArguments args) => SetInputVector(args, SceneInputAxis.Backward);\n\n        [ClutchShortcut(\"3D Viewport/Fly Mode Left\", typeof(CameraFlyModeContext), KeyCode.A)]\n        [FormerlyPrefKeyAs(\"View/FPS Strafe Left\", \"a\")]\n        static void WalkLeft(ShortcutArguments args) => SetInputVector(args, SceneInputAxis.Left);\n\n        [ClutchShortcut(\"3D Viewport/Fly Mode Right\", typeof(CameraFlyModeContext), KeyCode.D)]\n        [FormerlyPrefKeyAs(\"View/FPS Strafe Right\", \"d\")]\n        static void WalkRight(ShortcutArguments args) => SetInputVector(args, SceneInputAxis.Right);\n\n        [ClutchShortcut(\"3D Viewport/Fly Mode Up\", typeof(CameraFlyModeContext), KeyCode.E)]\n        [FormerlyPrefKeyAs(\"View/FPS Strafe Up\", \"e\")]\n        static void WalkUp(ShortcutArguments args) => SetInputVector(args, SceneInputAxis.Up);\n\n        [ClutchShortcut(\"3D Viewport/Fly Mode Down\", typeof(CameraFlyModeContext), KeyCode.Q)]\n        [FormerlyPrefKeyAs(\"View/FPS Strafe Down\", \"q\")]\n        static void WalkDown(ShortcutArguments args) => SetInputVector(args, SceneInputAxis.Down);\n\n        void StartSceneViewMotionTool(ViewTool viewTool, SceneView view)\n        {\n            Tools.s_LockedViewTool = Tools.viewTool = viewTool;\n\n            // Set up zoom parameters\n            m_StartZoom = view.size;\n            m_ZoomSpeed = Mathf.Max(Mathf.Abs(m_StartZoom), .3f);\n            m_TotalMotion = 0;\n\n            if (Toolbar.get)\n                Toolbar.get.Repaint();\n\n            EditorGUIUtility.SetWantsMouseJumping(1);\n\n            UpdateViewToolState();\n\n            // The hot control needs to be set in an OnGUI call.\n            view.SendEvent(EditorGUIUtility.CommandEvent(k_SetSceneViewMotionHotControlEventCommandName));\n        }\n\n        public void CompleteSceneViewMotionTool()\n        {\n            Tools.viewTool = ViewTool.Pan;\n            Tools.s_LockedViewTool = ViewTool.None;\n\n            GUIUtility.hotControl = 0;\n\n            if (viewToolActiveChanged != null)\n                viewToolActiveChanged.Invoke();\n\n            Tools.s_ButtonDown = -1;\n\n            if (Toolbar.get)\n                Toolbar.get.Repaint();\n\n            EditorGUIUtility.SetWantsMouseJumping(0);\n\n            m_Drag = false;\n        }\n\n        // onGUIView is the SceneView currently receiving GUI event. It is not necesarily the currently\n        // last focused view as that's retrieved from SceneView.lastActiveSceneView.\n        public void DoViewTool(SceneView onGUIView)\n        {\n            var lastFocusedView = SceneView.lastActiveSceneView;\n            if (lastFocusedView == null)\n                return;\n\n            // In FPS mode we update the pivot for Orbit mode (see below and inside HandleMouseDrag)\n            if (Tools.s_LockedViewTool == ViewTool.FPS)\n                lastFocusedView.FixNegativeSize();\n\n            SceneNavigationInput.Update();\n            if (SceneNavigationInput.moving)\n                lastFocusedView.viewIsLockedToObject = false;\n            m_Motion = SceneNavigationInput.currentInputVector;\n\n            // If a different mouse button is clicked while the current mouse button is held down,\n            // reset the hot control to the correct id.\n            if (GUIUtility.hotControl == 0 && Tools.s_LockedViewTool != ViewTool.None)\n                GUIUtility.hotControl = k_ViewToolID;\n\n            var evt = Event.current;\n            switch (evt.GetTypeForControl(k_ViewToolID))\n            {\n                case EventType.ScrollWheel:\n                    // Default to zooming to mouse position in 2D mode without alt.\n                    // We pass onGUIView instead of lastFocusedView, because scrolling while hovering over an unfocused\n                    // must still trigger zoom on that view (and not the last focused one).\n                    HandleScrollWheel(onGUIView, lastFocusedView.in2DMode == evt.alt);\n                    break;\n                case EventType.MouseDown:\n                    if (GUIUtility.hotControl == 0)\n                        m_StartMousePosition = evt.mousePosition;\n                    break;\n                case EventType.MouseUp:\n                    if (GUIUtility.hotControl == k_ViewToolID)\n                        GUIUtility.hotControl = 0;\n                    break;\n                case EventType.KeyDown: // Escape\n                    HandleKeyDown();\n                    break;\n                case EventType.MouseDrag:\n                    HandleMouseDrag(lastFocusedView);\n                    break;\n                case EventType.Layout:\n                    if (GUIUtility.hotControl == k_ViewToolID || m_FlySpeed.isAnimating || m_Moving)\n                    {\n                        lastFocusedView.pivot = lastFocusedView.pivot + lastFocusedView.rotation * GetMovementDirection(lastFocusedView);\n                        lastFocusedView.Repaint();\n                    }\n                    break;\n                case EventType.ExecuteCommand:\n                    if (evt.commandName == k_PanFocusEventCommandName)\n                    {\n                        PanFocus(m_StartMousePosition, lastFocusedView, evt);\n                    }\n                    else if (evt.commandName == k_SetSceneViewMotionHotControlEventCommandName)\n                    {\n                        GUIUtility.hotControl = k_ViewToolID;\n                        evt.Use();\n                    }\n                    break;\n            }\n        }\n\n        static bool UpdateViewToolState()\n        {\n            bool shouldBeActive = Tools.s_LockedViewTool != ViewTool.None || Tools.current == Tool.View;\n            if (shouldBeActive != s_ViewToolIsActive)\n            {\n                s_ViewToolIsActive = shouldBeActive;\n\n                if (viewToolActiveChanged != null)\n                    viewToolActiveChanged.Invoke();\n            }\n\n            return s_ViewToolIsActive;\n        }\n\n        Vector3 GetMovementDirection(SceneView view)\n        {\n            m_Moving = m_Motion.sqrMagnitude > 0f;\n            var deltaTime = SceneNavigationInput.deltaTime;\n            var speedModifier = view.cameraSettings.speed;\n\n            if (Event.current.shift)\n                speedModifier *= 5f;\n\n            if (m_Moving)\n            {\n                if (view.cameraSettings.accelerationEnabled)\n                    m_FlySpeedTarget = m_FlySpeedTarget < Mathf.Epsilon ? k_FlySpeed : m_FlySpeedTarget * Mathf.Pow(k_FlySpeedAcceleration, deltaTime);\n                else\n                    m_FlySpeedTarget = k_FlySpeed;\n            }\n            else\n            {\n                m_FlySpeedTarget = 0f;\n            }\n\n            if (view.cameraSettings.easingEnabled)\n            {\n                m_FlySpeed.speed = 1f / view.cameraSettings.easingDuration;\n                m_FlySpeed.target = m_Motion.normalized * m_FlySpeedTarget * speedModifier;\n            }\n            else\n            {\n                m_FlySpeed.value = m_Motion.normalized * m_FlySpeedTarget * speedModifier;\n            }\n\n            return m_FlySpeed.value * deltaTime;\n        }\n\n        public void ResetMotion()\n        {\n            m_Motion = Vector3.zero;\n            m_FlySpeed.value = Vector3.zero;\n            m_Moving = false;\n        }\n\n        bool RaycastWorld(Vector2 position, out RaycastHit hit)\n        {\n            hit = new RaycastHit();\n            GameObject picked = HandleUtility.PickGameObject(position, false);\n            if (!picked)\n                return false;\n\n            Ray mouseRay = HandleUtility.GUIPointToWorldRay(position);\n\n            // Loop through all meshes and find the RaycastHit closest to the ray origin.\n            MeshFilter[] meshFil = picked.GetComponentsInChildren<MeshFilter>();\n            float minT = Mathf.Infinity;\n            foreach (MeshFilter mf in meshFil)\n            {\n                Mesh mesh = mf.sharedMesh;\n                if (!mesh || !mesh.canAccess)\n                    continue;\n\n                RaycastHit localHit;\n                if (HandleUtility.IntersectRayMesh(mouseRay, mesh, mf.transform.localToWorldMatrix, out localHit))\n                {\n                    if (localHit.distance < minT)\n                    {\n                        hit = localHit;\n                        minT = hit.distance;\n                    }\n                }\n            }\n\n            if (minT == Mathf.Infinity)\n            {\n                // If we didn't find any surface based on meshes, try with colliders.\n                Collider[] colliders = picked.GetComponentsInChildren<Collider>();\n                foreach (Collider col in colliders)\n                {\n                    RaycastHit localHit;\n                    if (col.Raycast(mouseRay, out localHit, Mathf.Infinity))\n                    {\n                        if (localHit.distance < minT)\n                        {\n                            hit = localHit;\n                            minT = hit.distance;\n                        }\n                    }\n                }\n            }\n\n            if (minT == Mathf.Infinity)\n            {\n                // If we didn't hit any mesh or collider surface, then use the transform position projected onto the ray.\n                hit.point = Vector3.Project(picked.transform.position - mouseRay.origin, mouseRay.direction) + mouseRay.origin;\n            }\n\n            return true;\n        }\n\n        private void OrbitCameraBehavior(SceneView view)\n        {\n            Event evt = Event.current;\n\n            view.FixNegativeSize();\n            Quaternion rotation = view.m_Rotation.target;\n            rotation = Quaternion.AngleAxis(evt.delta.y * .003f * Mathf.Rad2Deg, rotation * Vector3.right) * rotation;\n            rotation = Quaternion.AngleAxis(evt.delta.x * .003f * Mathf.Rad2Deg, Vector3.up) * rotation;\n\n            if (view.size < 0)\n            {\n                view.pivot = view.camera.transform.position;\n                view.size = 0;\n            }\n\n            view.rotation = rotation;\n        }\n\n        private void HandleMouseDrag(SceneView view)\n        {\n            if (!Event.current.isMouse || GUIUtility.hotControl != k_ViewToolID)\n                return;\n\n            m_Drag = true;\n            Event evt = Event.current;\n            switch (Tools.s_LockedViewTool)\n            {\n                case ViewTool.Orbit:\n                    {\n                        if (!view.in2DMode && !view.isRotationLocked)\n                        {\n                            OrbitCameraBehavior(view);\n                            view.UpdateOrientationGizmos();\n                        }\n                    }\n                    break;\n                case ViewTool.FPS:\n                    {\n                        if (!view.in2DMode && !view.isRotationLocked)\n                        {\n                            if (!view.orthographic)\n                            {\n                                view.viewIsLockedToObject = false;\n\n                                // The reason we calculate the camera position from the pivot, rotation and distance,\n                                // rather than just getting it from the camera transform is that the camera transform\n                                // is the *output* of camera motion calculations. It shouldn't be input and output at the same time,\n                                // otherwise we easily get accumulated error.\n                                // We did get accumulated error before when we did this - the camera would continuously move slightly in FPS mode\n                                // even when not holding down any arrow/ASDW keys or moving the mouse.\n                                Vector3 camPos = view.pivot - view.rotation * Vector3.forward * view.cameraDistance;\n\n                                // Normal FPS camera behavior\n                                Quaternion rotation = view.rotation;\n                                rotation = Quaternion.AngleAxis(evt.delta.y * .003f * Mathf.Rad2Deg, rotation * Vector3.right) * rotation;\n                                rotation = Quaternion.AngleAxis(evt.delta.x * .003f * Mathf.Rad2Deg, Vector3.up) * rotation;\n                                view.rotation = rotation;\n\n                                view.pivot = camPos + rotation * Vector3.forward * view.cameraDistance;\n                            }\n                            else\n                            {\n                                // We want orbit behavior in orthograpic when using FPS\n                                OrbitCameraBehavior(view);\n                            }\n\n                            view.UpdateOrientationGizmos();\n                        }\n                    }\n                    break;\n                case ViewTool.Pan:\n                    {\n                        view.viewIsLockedToObject = false;\n                        view.FixNegativeSize();\n\n                        Vector2 screenDelta = Event.current.delta;\n                        Vector3 worldDelta = ScreenToWorldDistance(view, new Vector2(-screenDelta.x, screenDelta.y));\n\n                        if (evt.shift)\n                            worldDelta *= 4;\n\n                        view.pivot += worldDelta;\n                    }\n                    break;\n                case ViewTool.Zoom:\n                    {\n                        float zoomDelta = HandleUtility.niceMouseDeltaZoom * (evt.shift ? 9 : 3);\n\n                        if (view.orthographic)\n                        {\n                            view.size = Mathf.Max(.0001f, view.size * (1 + zoomDelta * .001f));\n                        }\n                        else\n                        {\n                            m_TotalMotion += zoomDelta;\n\n                            if (m_TotalMotion < 0)\n                                view.size = m_StartZoom * (1 + m_TotalMotion * .001f);\n                            else\n                                view.size = view.size + zoomDelta * m_ZoomSpeed * .003f;\n                        }\n                    }\n                    break;\n            }\n\n            evt.Use();\n        }\n\n        public Vector3 ScreenToWorldDistance(SceneView view, Vector2 delta)\n        {\n            // Ensures that the camera matrix doesn't end up with gigantic or minuscule values in the clip to world matrix\n            const float k_MaxCameraSizeForWorldToScreen = 2.5E+7f;\n\n            // store original camera and view values\n            var camera = view.camera;\n            var near = camera.nearClipPlane;\n            var far = camera.farClipPlane;\n            var pos = camera.transform.position;\n            var rotation = camera.transform.rotation;\n            var size = view.size;\n\n            // set camera transform and clip values to safe values\n            view.size = Mathf.Min(view.size, k_MaxCameraSizeForWorldToScreen);\n            // account for the distance clamping\n            var scale = size / view.size;\n            var clip = view.GetDynamicClipPlanes();\n            view.camera.nearClipPlane = clip.x;\n            view.camera.farClipPlane = clip.y;\n            view.camera.transform.position = Vector3.zero;\n            view.camera.transform.rotation = Quaternion.identity;\n\n            // do the distance calculation\n            Vector3 pivotWorld = camera.transform.rotation * new Vector3(0f, 0f, view.cameraDistance);\n            Vector3 pivotScreen = camera.WorldToScreenPoint(pivotWorld);\n            pivotScreen += new Vector3(delta.x, delta.y, 0);\n\n            Vector3 worldDelta = camera.ScreenToWorldPoint(pivotScreen) - pivotWorld;\n            // We're clearing z here as ScreenToWorldPoint(WorldToScreenPoint(worldPoint)) does not always result in the exact same worldPoint that was inputed (for example, when camera is ortho).\n            // https://jira.unity3d.com/browse/UUM-56425\n            worldDelta.z = 0f;\n            worldDelta = rotation * worldDelta;\n            worldDelta *= EditorGUIUtility.pixelsPerPoint * scale;\n\n            // restore original cam and scene values\n            view.size = size;\n            view.camera.nearClipPlane = near;\n            view.camera.farClipPlane = far;\n            view.camera.transform.position = pos;\n            view.camera.transform.rotation = rotation;\n\n            return worldDelta;\n        }\n\n        // This can't be modified into a shortcut because Escape is an invalid key code binding.\n        private void HandleKeyDown()\n        {\n            if (Event.current.keyCode == KeyCode.Escape && GUIUtility.hotControl == k_ViewToolID)\n                CompleteSceneViewMotionTool();\n        }\n\n        void HandleScrollWheel(SceneView view, bool zoomTowardsCenter)\n        {\n            var evt = Event. current;\n            var scrollDelta = Event.current.delta.y;\n            if (Tools.s_LockedViewTool == ViewTool.FPS)\n            {\n                // On MacOS, scrolling with Shift down is interpreted as a horizontal scroll at the 0S level.\n                // On Window, due to UUM-43552 a change was done at the editor's win platform layer to mimic macOS behaviour and swap x/y deltas.\n                if ((evt.modifiers & EventModifiers.Shift) != 0 &&\n                    (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.WindowsEditor))\n                    scrollDelta = Event.current.delta.x;\n\n                float scrollWheelDelta = scrollDelta * m_FPSScrollWheelMultiplier;\n                view.cameraSettings.speedNormalized -= scrollWheelDelta;\n                float cameraSettingsSpeed = view.cameraSettings.speed;\n                string cameraSpeedDisplayValue = cameraSettingsSpeed.ToString(\n                    cameraSettingsSpeed < 0.0001f ? \"F6\" :\n                    cameraSettingsSpeed < 0.001f ? \"F5\" :\n                    cameraSettingsSpeed < 0.01f ? \"F4\" :\n                    cameraSettingsSpeed < 0.1f ? \"F3\" :\n                    cameraSettingsSpeed < 10f ? \"F2\" :\n                    \"F0\");\n\n                if (cameraSettingsSpeed < 0.1f)\n                    cameraSpeedDisplayValue = cameraSpeedDisplayValue.Trim(k_TrimChars);\n\n                GUIContent cameraSpeedContent = EditorGUIUtility.TempContent(string.Format(\"{0}{1}\",\n                    cameraSpeedDisplayValue,\n                    view.cameraSettings.accelerationEnabled ? \"x\" : \"\"));\n\n                view.ShowNotification(cameraSpeedContent, .5f);\n            }\n            else\n            {\n                // When in camera view mode, change the FoV of the selected camera instead.\n                if (view.viewpoint.hasActiveViewpoint)\n                {\n                    view.viewpoint.HandleScrollWheel(view);\n                    return;\n                }\n\n                float targetSize;\n\n                if (!view.orthographic)\n                {\n                    float relativeDelta = Mathf.Abs(view.size) * scrollDelta * .015f;\n                    const float k_MinZoomDelta = .0001f;\n                    if (relativeDelta > 0 && relativeDelta < k_MinZoomDelta)\n                        relativeDelta = k_MinZoomDelta;\n                    else if (relativeDelta < 0 && relativeDelta > -k_MinZoomDelta)\n                        relativeDelta = -k_MinZoomDelta;\n\n                    targetSize = view.size + relativeDelta;\n                }\n                else\n                {\n                    targetSize = Mathf.Abs(view.size) * (scrollDelta * .015f + 1.0f);\n                }\n\n                var initialDistance = view.cameraDistance;\n\n                if (!(float.IsNaN(targetSize) || float.IsInfinity(targetSize)))\n                {\n                    targetSize = Mathf.Min(SceneView.k_MaxSceneViewSize, targetSize);\n                    view.size = targetSize;\n                }\n\n                if (!zoomTowardsCenter && Mathf.Abs(view.cameraDistance) < 1.0e7f)\n                {\n                    var percentage = 1f - (view.cameraDistance / initialDistance);\n\n                    var mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);\n                    var mousePivot = mouseRay.origin + mouseRay.direction * initialDistance;\n                    var pivotVector = mousePivot - view.pivot;\n\n                    view.pivot += pivotVector * percentage;\n                }\n            }\n\n            Event.current.Use();\n        }\n    }\n} //namespace\n"
  },
  {
    "path": "Editor/Mono/SceneView/SceneViewOverlay.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.Overlays;\nusing UnityEngine;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    sealed class LegacyOverlay : IMGUIOverlay, ITransientOverlay\n    {\n        public OverlayWindow data { get; set; }\n\n        public bool showRequested {get; set; }\n\n        public override void OnGUI()\n        {\n            data?.sceneViewFunc?.Invoke(data.target, (SceneView)containerWindow);\n        }\n\n        public bool visible => showRequested;\n    }\n\n    // Deprecated. Use `TransientSceneViewOverlay` instead.\n    class SceneViewOverlay\n    {\n        // This enum is for better overview of the ordering of our builtin overlays\n        public enum Ordering\n        {\n            // Lower order is below high order when showed together\n            Camera = -100,\n            ClothConstraints = 0,\n            ClothSelfAndInterCollision = 100,\n            OcclusionCulling = 200,\n            Lightmapping = 300,\n            NavMesh = 400,\n            PhysicsDebug = 450,\n            TilemapRenderer = 500,\n            ParticleEffect = 600\n        }\n\n        public enum WindowDisplayOption\n        {\n            MultipleWindowsPerTarget,\n            OneWindowPerTarget,\n            OneWindowPerTitle\n        }\n\n        public delegate void WindowFunction(Object target, SceneView sceneView);\n\n        public SceneViewOverlay(SceneView sceneView) {}\n\n        public void Begin() {}\n\n        public void End() {}\n\n        const string k_ObsoleteMessage = \"Please use UnityEditor.Overlays.TransientSceneViewOverlay in place of SceneViewOverlay.\";\n\n        [Obsolete(k_ObsoleteMessage)]\n        // pass window parameter to render in sceneviews that are not the active view.\n        public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, WindowDisplayOption option)\n        {\n            Window(title, sceneViewFunc, order, null, option);\n        }\n\n        [Obsolete(k_ObsoleteMessage)]\n        // pass window parameter to render in sceneviews that are not the active view.\n        public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option, EditorWindow window = null)\n        {\n            if (Event.current.type != EventType.Layout)\n                return;\n\n            ShowWindow(new OverlayWindow(title, sceneViewFunc, order, target, option));\n        }\n\n        [Obsolete(k_ObsoleteMessage)]\n        public static void ShowWindow(OverlayWindow window)\n        {\n            if (Event.current.type != EventType.Layout)\n                return;\n\n            if (SceneView.currentDrawingSceneView == null)\n            {\n                Debug.Log(\"SceneViewOverlay.ShowWindow can only be called from the scene view GUI\");\n                return;\n            }\n\n            SceneView.currentDrawingSceneView.ShowLegacyOverlay(window);\n        }\n    }\n\n    class OverlayWindow : IComparable<OverlayWindow>\n    {\n        public OverlayWindow(GUIContent title, SceneViewOverlay.WindowFunction guiFunction, int primaryOrder, Object target,\n                             SceneViewOverlay.WindowDisplayOption option)\n        {\n            this.title = title;\n            this.sceneViewFunc = guiFunction;\n            this.primaryOrder = primaryOrder;\n            this.option = option;\n            this.target = target;\n            this.canCollapse = true;\n            this.expanded = true;\n        }\n\n        public SceneViewOverlay.WindowFunction sceneViewFunc { get;  }\n        public int primaryOrder { get; }\n        public int secondaryOrder { get; set; }\n        public Object target { get; }\n        public EditorWindow editorWindow { get; set; }\n\n        public SceneViewOverlay.WindowDisplayOption option { get; } =\n            SceneViewOverlay.WindowDisplayOption.MultipleWindowsPerTarget;\n\n        public bool canCollapse { get; set; }\n        public bool expanded { get; set; }\n\n        public GUIContent title { get; }\n\n        public int CompareTo(OverlayWindow other)\n        {\n            return 0;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneView/SceneViewOverlays.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.Overlays;\n\nnamespace UnityEditor\n{\n    public partial class SceneView\n    {\n        [Overlay(typeof(SceneView), k_OverlayID, k_DisplayName, defaultDisplay = false)]\n        internal class SceneViewIsolationOverlay : TransientSceneViewOverlay\n        {\n            public const string k_OverlayID = \"Scene View/Scene Visibility\";\n            const string k_DisplayName = \"Isolation View\";\n            bool m_ShouldDisplay;\n\n            internal static class Styles\n            {\n                public static GUIContent isolationModeExitButton = EditorGUIUtility.TrTextContent(\"Exit\", \"Exit isolation mode\");\n            }\n\n            public override bool visible => m_ShouldDisplay;\n\n            public override void OnCreated()\n            {\n                SceneVisibilityManager.currentStageIsIsolated += CurrentStageIsolated;\n                CurrentStageIsolated(SceneVisibilityState.isolation);\n            }\n\n            public override void OnWillBeDestroyed()\n            {\n                SceneVisibilityManager.currentStageIsIsolated -= CurrentStageIsolated;\n            }\n\n            void CurrentStageIsolated(bool isolated)\n            {\n                m_ShouldDisplay = isolated;\n            }\n\n            public override void OnGUI()\n            {\n                if (GUILayout.Button(Styles.isolationModeExitButton, GUILayout.MinWidth(120)))\n                {\n                    SceneVisibilityManager.instance.ExitIsolation();\n                }\n            }\n        }\n    }\n}\n// namespace\n"
  },
  {
    "path": "Editor/Mono/SceneView/SceneViewPicking.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    // No BaseSelection available:\n    // 1. Just cycle through the selection from topmost to bottom\n\n    // SelectionBase available for topmost object:\n    // 1. First click selects the base\n    // 2. Second click selects the topmost\n    // 3. All subsequent clicks cycle through the stack of overlapping objects from top to bottom, regardless of their SelectionBase status\n    // 4. When we hit the bottom, we goto 1\n\n    // Example: Scene from back to front (visually): Panel(base), Label, Image, Button(base), Image2, Label2\n    // Selection order: Button, Label2, Image2, Image, Label, Panel, goto start\n\n    class SceneViewPicking\n    {\n        static bool s_RetainHashes = false;\n        static int s_PreviousTopmostHash = 0;\n        static int s_PreviousPrefixHash = 0;\n        static readonly List<PickingObject> s_ActiveObjectFilter = new List<PickingObject>(1);\n\n        static SceneViewPicking()\n        {\n            Selection.selectionChanged += ResetHashes;\n        }\n\n        static void ResetHashes()\n        {\n            if (!s_RetainHashes)\n            {\n                s_PreviousTopmostHash = 0;\n                s_PreviousPrefixHash = 0;\n            }\n\n            s_RetainHashes = false;\n        }\n\n        public static PickingObject PickGameObject(Vector2 mousePosition)\n        {\n            s_RetainHashes = true;\n\n            var enumerator = GetAllOverlapping(mousePosition).GetEnumerator();\n\n            if (!enumerator.MoveNext())\n                return PickingObject.Empty;\n\n            PickingObject topmost = enumerator.Current;\n            var pickingBase = topmost.TryGetComponent(out Transform trs)\n                ? HandleUtility.FindSelectionBaseForPicking(trs)\n                : null;\n            // Selection base is only interesting if it's not the topmost\n            PickingObject selectionBase = new PickingObject(pickingBase);\n            PickingObject first = selectionBase.target == null ? topmost : selectionBase;\n            int topmostHash = topmost.GetHashCode();\n            int prefixHash = topmostHash;\n\n            if (Selection.activeObject == null)\n            {\n                // Nothing selected\n                // Return selection base if it exists, otherwise topmost game object\n                s_PreviousTopmostHash = topmostHash;\n                s_PreviousPrefixHash = prefixHash;\n                return first;\n            }\n\n            if (topmostHash != s_PreviousTopmostHash)\n            {\n                // Topmost game object changed\n                // Return selection base if exists and is not already selected, otherwise topmost game object\n                s_PreviousTopmostHash = topmostHash;\n                s_PreviousPrefixHash = prefixHash;\n                return Selection.activeObject == selectionBase.target ? topmost : first;\n            }\n\n            s_PreviousTopmostHash = topmostHash;\n\n            // Pick potential selection base before topmost game object\n            if (Selection.activeObject == selectionBase.target)\n            {\n                if (prefixHash == s_PreviousPrefixHash)\n                    return topmost;\n                s_PreviousPrefixHash = prefixHash;\n                return selectionBase;\n            }\n\n            s_ActiveObjectFilter.Clear();\n            s_ActiveObjectFilter.Add((PickingObject)Selection.activeObject);\n\n            // Check if active game object will appear in selection stack\n            PickingObject picked = HandleUtility.PickObject(mousePosition, false, null, s_ActiveObjectFilter);\n\n            if (picked == ((PickingObject)Selection.activeObject))\n            {\n                // Advance enumerator to active game object\n                while (enumerator.Current != ((PickingObject)Selection.activeObject))\n                {\n                    if (!enumerator.MoveNext())\n                    {\n                        s_PreviousPrefixHash = topmostHash;\n                        return first; // Should not occur\n                    }\n\n                    UpdateHash(ref prefixHash, enumerator.Current);\n                }\n            }\n\n            if (prefixHash != s_PreviousPrefixHash)\n            {\n                // Prefix hash changed, start over\n                s_PreviousPrefixHash = topmostHash;\n                return first;\n            }\n\n            // Move on to next game object\n            if (!enumerator.MoveNext())\n            {\n                s_PreviousPrefixHash = topmostHash;\n                return first; // End reached, start over\n            }\n\n            UpdateHash(ref prefixHash, enumerator.Current);\n\n            if (enumerator.Current == selectionBase)\n            {\n                // Skip selection base\n                if (!enumerator.MoveNext())\n                {\n                    s_PreviousPrefixHash = topmostHash;\n                    return first; // End reached, start over\n                }\n\n                UpdateHash(ref prefixHash, enumerator.Current);\n            }\n\n            s_PreviousPrefixHash = prefixHash;\n            return enumerator.Current;\n        }\n\n        // Get an ordered list of all visually overlapping GameObjects at the screen position from top to bottom\n        internal static IEnumerable<PickingObject> GetAllOverlapping(Vector2 position)\n        {\n            var overlapping = new List<PickingObject>();\n            var ignore = new List<PickingObject>();\n\n            while (true)\n            {\n                PickingObject res = HandleUtility.PickObject(position, false, ignore, null);\n\n                if (res.target == null)\n                    break;\n\n                if (res.TryGetGameObject(out var go) && SceneVisibilityManager.instance.IsPickingDisabled(go))\n                {\n                    ignore.Add(res);\n                    continue;\n                }\n\n                // Prevent infinite loop if object cannot be ignored (this needs to be fixed so print an error)\n                if (overlapping.Count > 0 && res == overlapping.Last())\n                {\n                    Debug.LogError($\"GetAllOverlapping failed, could not ignore game object '{res}' when picking\");\n                    break;\n                }\n\n                overlapping.Add(res);\n                ignore.Add(res);\n\n                yield return res;\n            }\n        }\n\n        static void UpdateHash(ref int hash, PickingObject obj)\n        {\n            hash = unchecked(hash * 33 + obj.GetHashCode());\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneView/SceneViewPiercingMenu.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.ShortcutManagement;\nusing UnityEditor.UIElements;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing Object = UnityEngine.Object;\nusing SelectionType = UnityEditor.RectSelection.SelectionType;\n\nnamespace UnityEditor\n{\n    static class SceneViewPiercingMenu\n    {\n        const string k_SelectionPiercingMenuCommand = \"SelectionPiercingMenuCommand\";\n\n        static void ShowSelectionPiercingMenuNormal(SceneView view) => ShowSelectionPiercingMenu(view, false);\n\n        static void ShowSelectionPiercingMenuSubtractive(SceneView view) => ShowSelectionPiercingMenu(view, true);\n\n        [Shortcut(\"Scene View/List Select\", typeof(SceneViewPickingShortcutContext), KeyCode.Mouse1, ShortcutModifiers.Action)]\n        static void OpenSelectionPiercingMenuNormal(ShortcutArguments args)\n        {\n            if (!(args.context is SceneViewPickingShortcutContext ctx) || !(ctx.window is SceneView view))\n                return;\n            OpenSelectionPiercingMenu(view, SelectionType.Normal);\n        }\n\n        [Shortcut(\"Scene View/List Deselect\", typeof(SceneViewPickingShortcutContext), KeyCode.Mouse1, ShortcutModifiers.Action | ShortcutModifiers.Shift)]\n        static void OpenSelectionPiercingMenuSubtractive(ShortcutArguments args)\n        {\n            if (!(args.context is SceneViewPickingShortcutContext ctx) || !(ctx.window is SceneView view))\n                return;\n            OpenSelectionPiercingMenu(view, SelectionType.Subtractive);\n        }\n\n        static void OpenSelectionPiercingMenu(SceneView view, SelectionType type)\n        {\n            SceneView.duringSceneGui += type == SelectionType.Normal ? ShowSelectionPiercingMenuNormal : ShowSelectionPiercingMenuSubtractive;\n            var evt = Event.current;\n\n            view.SendEvent(new Event()\n            {\n                commandName = k_SelectionPiercingMenuCommand,\n                type = EventType.ValidateCommand,\n                mousePosition = evt.mousePosition\n            });\n\n            view.SendEvent(new Event()\n            {\n                commandName = k_SelectionPiercingMenuCommand,\n                type = EventType.ExecuteCommand,\n                mousePosition = evt.mousePosition\n            });\n\n            SceneView.duringSceneGui -= type == SelectionType.Normal ? ShowSelectionPiercingMenuNormal : ShowSelectionPiercingMenuSubtractive;\n        }\n\n        // unfortunately there is no easy way to respect shortcut mappings in this case. we'll assume that action/shift\n        // are safe bets.\n        static SelectionType GetSelectionType(EventModifiers modifiers, bool forceSubtractive)\n        {\n            if (forceSubtractive)\n                return SelectionType.Subtractive;\n\n            if ((modifiers & EventModifiers.Shift) > 0)\n                return SelectionType.Additive;\n\n            if((modifiers & (EventModifiers.Command | EventModifiers.Control)) > 0)\n                return SelectionType.Subtractive;\n\n            return SelectionType.Normal;\n        }\n\n        //Used by tests in EditAndPlaymodeTests/Picking\n        internal static Object[] GetNewSelection(Object[] existing, PickingObject incoming, SelectionType type)\n        {\n            Object[] newSelection;\n\n            switch (type)\n            {\n                case SelectionType.Additive:\n                    if (incoming.target == null)\n                        return existing;\n\n                    newSelection = new Object[existing.Length + 1];\n                    Array.Copy(existing, newSelection, existing.Length);\n                    newSelection[existing.Length] = incoming.target;\n                    return newSelection;\n\n                // if target is in selection as a child, remove the parent. otherwise this is equivalent to\n                // HashSet.SymmetricExceptWith\n                case SelectionType.Subtractive:\n                    if (!incoming.TryGetComponent<Transform>(out var hoveredTransform))\n                        goto case SelectionType.Additive;\n\n                    var set = new HashSet<Object>(existing);\n                    var selectionBase = HandleUtility.FindSelectionBaseForPicking(hoveredTransform)?.transform;\n                    bool incomingPrefabRemovedFromSelection = false;\n\n                    do\n                    {\n                        incomingPrefabRemovedFromSelection |= set.Remove(hoveredTransform.gameObject);\n                        hoveredTransform = hoveredTransform.parent;\n                    } while (hoveredTransform != null && hoveredTransform != selectionBase);\n\n                    if (!incomingPrefabRemovedFromSelection)\n                        goto case SelectionType.Additive;\n\n                    newSelection = new Object[set.Count];\n                    int i = 0;\n                    foreach (var o in set)\n                        newSelection[i++] = o;\n                    return newSelection;\n\n                case SelectionType.Normal:\n                default:\n                    return new [] { incoming.target };\n            }\n        }\n\n        static void ShowSelectionPiercingMenu(SceneView sceneView, bool forceSubtractive)\n        {\n            var evt = Event.current;\n\n            if (evt.type == EventType.ValidateCommand && evt.commandName == k_SelectionPiercingMenuCommand)\n                evt.Use();\n\n            if(evt.type != EventType.ExecuteCommand || evt.commandName != k_SelectionPiercingMenuCommand)\n                return;\n\n            evt.Use();\n\n            var overlapping = new List<PickingObject>();\n            foreach(var o in SceneViewPicking.GetAllOverlapping(evt.mousePosition))\n                overlapping.Add(o);\n\n            var selectionPiercingMenu = new DropdownMenu();\n            foreach (var obj in overlapping)\n            {\n                var showInSelection = forceSubtractive && Selection.Contains(obj.target);\n                selectionPiercingMenu.AppendAction(obj.target.name,\n                    _ => Selection.objects = GetNewSelection(Selection.objects, obj, GetSelectionType(EventModifiers.None, forceSubtractive)),\n                    _ => showInSelection ? DropdownMenuAction.Status.Checked : DropdownMenuAction.Status.Normal);\n            }\n\n            if (selectionPiercingMenu.MenuItems().Count == 0)\n                selectionPiercingMenu.AppendAction(\"Nothing to Select Under Pointer\", null, DropdownMenuAction.Status.Disabled);\n\n#pragma warning disable CS0618 // Type or member is obsolete\n            selectionPiercingMenu.DoDisplayEditorMenuFromImGUI(new Rect(Event.current.mousePosition, Vector2.zero));\n#pragma warning restore CS0618 // Type or member is obsolete\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneView/SceneViewStageHandling.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.SceneManagement;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class SceneViewStageHandling\n    {\n        SceneView m_SceneView;\n        StateCache<SceneViewCameraState> m_StateCache = new StateCache<SceneViewCameraState>(\"Library/StateCache/SceneView/\");\n\n        BreadcrumbBar m_BreadcrumbBar = new BreadcrumbBar();\n        bool m_BreadcrumbInitialized;\n        Stage m_StageClickedFromBreadcrumb;\n\n        public bool isShowingBreadcrumbBar\n        {\n            get { return StageNavigationManager.instance.stageHistory.Count > 1; }\n        }\n\n        public float breadcrumbHeight { get { return BreadcrumbBar.DefaultStyles.background.fixedHeight; }}\n\n        Stage currentStage { get { return StageNavigationManager.instance.currentStage; } }\n\n        public SceneViewStageHandling(SceneView sceneView)\n        {\n            m_SceneView = sceneView;\n        }\n\n        public void OnEnable()\n        {\n            StageNavigationManager.instance.stageChanged += OnStageChanged;\n            AssetEvents.assetsChangedOnHDD += AssetsChangedOnHDD;\n\n            // We need to sync to the current stage to ensure we have the correct SceneView settings: We could have closed Unity while a prefab scene was open\n            // this means that the SceneView settings for that prefab is saved to the window layout. Opening Unity always opens the main scenes so here we ensure\n            // we have e.g the corrct sky box and other settings.\n            currentStage.SyncSceneViewToStage(m_SceneView);\n            LoadCameraState(m_SceneView, currentStage);\n        }\n\n        public void OnDisable()\n        {\n            // Ensure saving current stage settings so we can reconstruct them on OnEnable\n            SaveCameraState(m_SceneView, currentStage);\n\n            StageNavigationManager.instance.stageChanged -= OnStageChanged;\n            AssetEvents.assetsChangedOnHDD -= AssetsChangedOnHDD;\n        }\n\n        public void StartOnGUI()\n        {\n            currentStage.OnPreSceneViewRender(m_SceneView);\n        }\n\n        public void EndOnGUI()\n        {\n            currentStage.OnPostSceneViewRender(m_SceneView);\n        }\n\n        internal void RebuildBreadcrumbBar()\n        {\n            m_BreadcrumbInitialized = false;\n        }\n\n        void AssetsChangedOnHDD(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)\n        {\n            m_BreadcrumbInitialized = false;\n        }\n\n        void OnStageChanged(Stage previousStage, Stage newStage)\n        {\n            SaveCameraState(m_SceneView, previousStage);\n            newStage.SyncSceneViewToStage(m_SceneView);\n\n            var contextStage = newStage.GetContextStage();\n            if (GetStoredCameraState(m_SceneView, contextStage) == null)\n                newStage.OnFirstTimeOpenStageInSceneView(m_SceneView);\n            else\n                LoadCameraState(m_SceneView, contextStage);\n\n            m_BreadcrumbInitialized = false;\n            m_SceneView.OnStageChanged(previousStage, newStage);\n        }\n\n        void SaveCameraState(SceneView sceneView, Stage stage)\n        {\n            if (stage == null)\n                return;\n\n            // Allows stage to override which stage should be used for saving the state.\n            // Useful for Prefab Mode in Context where we want to save the context scene state.\n            Stage contextStage = stage.GetContextStage();\n\n            if (contextStage == null)\n                return;\n\n            Hash128 key = StageUtility.CreateWindowAndStageIdentifier(sceneView.windowGUID, contextStage);\n            var state = m_StateCache.GetState(key);\n            if (state == null)\n                state = new SceneViewCameraState();\n            state.SaveStateFromSceneView(sceneView);\n            m_StateCache.SetState(key, state);\n        }\n\n        SceneViewCameraState GetStoredCameraState(SceneView sceneView, Stage stage)\n        {\n            Hash128 key = StageUtility.CreateWindowAndStageIdentifier(sceneView.windowGUID, stage);\n            return m_StateCache.GetState(key);\n        }\n\n        void LoadCameraState(SceneView sceneView, Stage stage)\n        {\n            if (stage == null)\n                return;\n\n            // Allows stage to override which stage should be used for saving the state.\n            // Useful for Prefab Mode in Context where we want to save the context scene state.\n            Stage contextStage = stage.GetContextStage();\n\n            if (contextStage == null)\n                return;\n\n            var state = GetStoredCameraState(sceneView, contextStage);\n            if (state != null)\n                state.RestoreStateToSceneView(sceneView);\n        }\n\n        public void BreadcrumbGUI()\n        {\n            float breadcrumbsHeight = 17f;\n            float verticalOffset = Mathf.Floor((BreadcrumbBar.DefaultStyles.background.fixedHeight - breadcrumbsHeight) / 2f);\n            SetupBreadCrumbBarIfNeeded();\n            using (new GUILayout.VerticalScope(BreadcrumbBar.DefaultStyles.background))\n            {\n                GUILayout.Space(verticalOffset - 1);\n                using (new EditorGUILayout.HorizontalScope(GUILayout.Height(breadcrumbsHeight)))\n                {\n                    m_BreadcrumbBar.OnGUI();\n                    GUILayout.Space(10f);\n                    currentStage.OnControlsGUI(m_SceneView);\n                }\n            }\n        }\n\n        void SetupBreadCrumbBarIfNeeded()\n        {\n            if (m_BreadcrumbInitialized)\n                return;\n\n            var history = StageNavigationManager.instance.stageHistory;\n            var crumbs = new List<BreadcrumbBar.Item>();\n            foreach (var stage in history)\n            {\n                var breadcrumbItem = stage.CreateBreadcrumbItem();\n                if (breadcrumbItem != null)\n                {\n                    breadcrumbItem.userdata = stage;\n                    crumbs.Add(breadcrumbItem);\n                }\n            }\n            m_BreadcrumbBar.SetBreadCrumbs(crumbs);\n            m_BreadcrumbBar.onBreadCrumbClicked -= BreadCrumbItemClicked;\n            m_BreadcrumbBar.onBreadCrumbClicked += BreadCrumbItemClicked;\n            m_BreadcrumbInitialized = true;\n        }\n\n        void SwitchStageOnNextUpdate()\n        {\n            EditorApplication.update -= SwitchStageOnNextUpdate;\n            var stageClicked = m_StageClickedFromBreadcrumb;\n            m_StageClickedFromBreadcrumb = null;\n\n            if (stageClicked != null && stageClicked.isValid)\n                StageNavigationManager.instance.SwitchToStage(stageClicked, false, StageNavigationManager.Analytics.ChangeType.NavigateViaBreadcrumb);\n        }\n\n        void BreadCrumbItemClicked(BreadcrumbBar.Item item)\n        {\n            var stageClicked = (Stage)item.userdata;\n            if (!stageClicked.isValid)\n                return;\n\n            if (StageNavigationManager.instance.currentStage == stageClicked)\n            {\n                EditorGUIUtility.PingObject(AssetDatabase.LoadMainAssetAtPath(stageClicked.assetPath));\n            }\n            else\n            {\n                // The BreadCrumbItemClicked event is called during the SceneView's OnGUI and if we switch stage directly we might delete the\n                // target of the SceneView's activeEditors which the rest of the SceneView's OnGUI is not expecting.\n                // E.g it will cause null ref exceptions in OnSceneGUI(). Instead we delay switching until the next Update.\n                m_StageClickedFromBreadcrumb = stageClicked;\n                EditorApplication.update += SwitchStageOnNextUpdate;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneView/SceneViewToolbarStyles.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    static class SceneViewToolbarStyles\n    {\n        const string k_StyleSheet = \"StyleSheets/SceneViewToolbarElements/SceneViewToolbarElements.uss\";\n        const string k_StyleLight = \"StyleSheets/SceneViewToolbarElements/SceneViewToolbarElementsLight.uss\";\n        const string k_StyleDark = \"StyleSheets/SceneViewToolbarElements/SceneViewToolbarElementsDark.uss\";\n\n        static StyleSheet s_Style;\n        static StyleSheet s_Skin;\n        internal static  void AddStyleSheets(VisualElement ve)\n        {\n            if (s_Skin == null)\n            {\n                if (EditorGUIUtility.isProSkin)\n                    s_Skin = EditorGUIUtility.Load(k_StyleDark) as StyleSheet;\n                else\n                    s_Skin = EditorGUIUtility.Load(k_StyleLight) as StyleSheet;\n            }\n            if (s_Style == null)\n            {\n                s_Style = EditorGUIUtility.Load(k_StyleSheet) as StyleSheet;\n            }\n            ve.styleSheets.Add(s_Style);\n            ve.styleSheets.Add(s_Skin);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneView/SceneViewToolbars.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.EditorTools;\nusing UnityEditor.Overlays;\nusing UnityEditor.Toolbars;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n     // See also\n     // - UIServiceEditor/SceneView/SceneViewToolbarElements.cs\n     // - UIServiceEditor/EditorToolbar/ToolbarElements/BuiltinTools.cs\n\n    [Overlay(typeof(SceneView), k_Id, \"Tools\", true, priority = (int)OverlayPriority.Tools, defaultDockZone = DockZone.LeftColumn, defaultDockPosition = DockPosition.Top, defaultLayout = Layout.VerticalToolbar, defaultDockIndex = 0)]\n    [Icon(\"Icons/Overlays/ToolsToggle.png\")]\n    class TransformToolsOverlayToolBar : ToolbarOverlay\n    {\n        const string k_Id = \"unity-transform-toolbar\";\n        public TransformToolsOverlayToolBar() : base(\"Tools/Builtin Tools\") {}\n\n        public override void OnCreated()\n        {\n            base.OnCreated();\n            ToolManager.activeToolChanged += UpdateActiveToolIcon;\n            SceneViewMotion.viewToolActiveChanged += UpdateActiveToolIcon;\n            Tools.viewToolChanged += UpdateViewToolIcon;\n            UpdateActiveToolIcon();\n        }\n\n        public override void OnWillBeDestroyed()\n        {\n            ToolManager.activeToolChanged -= UpdateActiveToolIcon;\n            SceneViewMotion.viewToolActiveChanged -= UpdateActiveToolIcon;\n            Tools.viewToolChanged -= UpdateViewToolIcon;\n            base.OnWillBeDestroyed();\n        }\n\n        void UpdateActiveToolIcon()\n        {\n            if(Tools.viewToolActive)\n                UpdateViewToolIcon();\n            else\n                collapsedIcon = EditorToolUtility.IsManipulationTool(Tools.current) ?\n                                EditorToolUtility.GetToolbarIcon(EditorToolManager.activeTool)?.image as Texture2D :\n                                null;\n        }\n\n        void UpdateViewToolIcon()\n        {\n            if(!Tools.viewToolActive)\n                return;\n\n            switch (Tools.viewTool)\n            {\n                case ViewTool.Orbit:\n                case ViewTool.FPS:\n                    collapsedIcon = EditorGUIUtility.LoadIconRequired(\"ViewToolOrbit\");\n                    break;\n                case ViewTool.Pan:\n                    collapsedIcon = EditorGUIUtility.LoadIconRequired(\"ViewToolMove\");\n                    break;\n                case ViewTool.Zoom:\n                    collapsedIcon = EditorGUIUtility.LoadIconRequired(\"ViewToolZoom\");\n                    break;\n            }\n        }\n    }\n\n    [Overlay(typeof(SceneView), k_Id, \"View Options\", true, priority = (int)OverlayPriority.ViewOptions, defaultDockIndex = 0, defaultDockZone = DockZone.TopToolbar, defaultDockPosition = DockPosition.Bottom)]\n    [Icon(\"Icons/Overlays/ViewOptions.png\")]\n    class SceneViewToolBar : ToolbarOverlay\n    {\n        const string k_Id = \"unity-scene-view-toolbar\";\n        public SceneViewToolBar() : base(\n            \"SceneView/2D\",\n            \"SceneView/Audio\",\n            \"SceneView/Fx\",\n            \"SceneView/Scene Visibility\",\n            \"SceneView/Render Doc\",\n            \"SceneView/Metal Capture\",\n            \"SceneView/Layers\",\n            \"SceneView/Scene Camera\",\n            \"SceneView/Gizmos\") {}\n    }\n\n    [Overlay(typeof(SceneView), k_Id, \"Draw Modes\", true, priority = (int)OverlayPriority.DrawModes, defaultDockIndex = 1, defaultDockPosition = DockPosition.Bottom, defaultDockZone = DockZone.TopToolbar)]\n    [Icon(\"Icons/Overlays/ViewOptions.png\")]\n    class SceneViewCameraModeToolbar : ToolbarOverlay\n    {\n        const string k_Id = \"unity-scene-view-camera-mode-toolbar\";\n        public SceneViewCameraModeToolbar() : base(\n            \"SceneView/Common Camera Mode\",\n            \"SceneView/Camera Mode\") {}\n\n        private SceneView m_SceneView;\n\n        public override void OnCreated()\n        {\n            m_SceneView = containerWindow as SceneView;\n            m_SceneView.onCameraModeChanged += UpdateIcon;\n            UpdateIcon(m_SceneView.cameraMode);\n        }\n\n        public override void OnWillBeDestroyed()\n        {\n            m_SceneView.onCameraModeChanged -= UpdateIcon;\n        }\n\n        internal void UpdateIcon(SceneView.CameraMode cameraMode)\n        {\n            switch (cameraMode.drawMode)\n            {\n                case DrawCameraMode.Wireframe:\n                    collapsedIcon = EditorGUIUtility.LoadIconRequired(\"Toolbars/wireframe\");\n                    break;\n                case DrawCameraMode.TexturedWire:\n                    collapsedIcon = EditorGUIUtility.LoadIconRequired(\"Toolbars/ShadedWireframe\");\n                    break;\n                case DrawCameraMode.Textured when !m_SceneView.sceneLighting:\n                    collapsedIcon = EditorGUIUtility.LoadIconRequired(\"Toolbars/UnlitMode\");\n                    break;\n                case DrawCameraMode.Textured:\n                    collapsedIcon = EditorGUIUtility.LoadIconRequired(\"Toolbars/Shaded\");\n                    break;\n                default:\n                    collapsedIcon = EditorGUIUtility.LoadIconRequired(\"Toolbars/debug\");\n                    break;\n            }\n        }\n    }\n\n    [Overlay(typeof(SceneView), k_Id, \"Search\", false, priority = (int)OverlayPriority.Search, defaultDockZone = DockZone.TopToolbar, defaultDockPosition = DockPosition.Bottom, defaultDockIndex = 2)]\n    [Icon(\"Icons/Overlays/SearchOverlay.png\")]\n    class SearchToolBar : Overlay, ICreateHorizontalToolbar\n    {\n        const string k_Id = \"unity-search-toolbar\";\n\n        public OverlayToolbar CreateHorizontalToolbarContent()\n        {\n            return EditorToolbar.CreateOverlay(toolbarElements, containerWindow);\n        }\n\n        public override VisualElement CreatePanelContent()\n        {\n            return CreateHorizontalToolbarContent();\n        }\n\n        public IEnumerable<string> toolbarElements\n        {\n            get { yield return \"SceneView/Search\"; }\n        }\n    }\n\n    [Overlay(typeof(SceneView), k_Id, \"Grid and Snap\", true, priority = (int)OverlayPriority.GridAndSnap, defaultDockZone = DockZone.TopToolbar, defaultDockPosition = DockPosition.Top, defaultDockIndex = 1)]\n    [Icon(\"Icons/Overlays/GridAndSnap.png\")]\n    class GridAndSnapToolBar : ToolbarOverlay\n    {\n        const string k_Id = \"unity-grid-and-snap-toolbar\";\n\n        public GridAndSnapToolBar() : base(\n            \"Tools/Snap Size\",\n            \"SceneView/Grids\",\n            \"Tools/Snap Settings\",\n            \"SceneView/Snap Increment\") {}\n    }\n}\n// namespace\n"
  },
  {
    "path": "Editor/Mono/SceneView/SceneViewViewpoint.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing UnityEditor.ShortcutManagement;\nusing UObject = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [Serializable]\n    internal class SceneViewViewpoint\n    {\n        const float k_MouseWheelScaleSensitivityMultiplier = .01f;\n        const string k_CameraPreviewShortcutIdPrefix = \"Scene View/Camera View/\";\n        const int k_CameraFrameThickness = 2;\n\n        [Serializable]\n        internal class ViewpointSettings\n        {\n            internal const float defaultScale = 1.0f;\n            internal const float minScale = 0.001f;\n            internal const float maxScale = 10.0f;\n\n            internal const int defaultOpacity = 50;\n            internal const int minOpacity = 0;\n            internal const int maxOpacity = 100;\n\n            [SerializeField] int m_Opacity;\n            [SerializeField] float m_Scale;\n\n            internal int opacity\n            {\n                get => m_Opacity;\n                set => m_Opacity = Mathf.Clamp(value, minOpacity, maxOpacity);\n            }\n\n            internal float scale\n            {\n                get => m_Scale;\n                set\n                {\n                    m_Scale = Mathf.Clamp(value, minScale, maxScale);\n                }\n            }\n\n            internal ViewpointSettings(int defaultOpacity = defaultOpacity, float defaultScale = defaultScale)\n            {\n                m_Opacity = defaultOpacity;\n                m_Scale = defaultScale;\n            }\n        }\n\n        internal bool is2DViewpoint => hasActiveViewpoint && activeViewpoint is ICameraLensData lensData && lensData.Orthographic;\n        internal event Action<bool> cameraLookThroughStateChanged;\n\n        [SerializeField] SceneView m_SceneView;\n        [SerializeField] IViewpoint m_ActiveViewpoint;\n        [SerializeField] ViewpointSettings m_CameraOverscanSettings;\n\n        Camera m_TemporaryCamera;\n\n        Camera temporaryCamera\n        {\n            get\n            {\n                if (m_TemporaryCamera == null)\n                {\n                    m_TemporaryCamera = EditorUtility.CreateGameObjectWithHideFlags(\"Preview Camera\",\n                        HideFlags.HideAndDontSave,\n                        typeof(Camera)).GetComponent<Camera>();\n                    m_TemporaryCamera.enabled = false;\n                    m_TemporaryCamera.cameraType = CameraType.Preview;\n                }\n                return m_TemporaryCamera;\n            }\n        }\n\n        bool viewpointContextIsActive => SceneViewMotion.SceneViewContext.ViewHasFocus && hasActiveViewpoint;\n\n        bool shouldExitViewpoint => m_ActiveViewpoint != null && !m_ActiveViewpoint.TargetObject;\n\n        internal IViewpoint activeViewpoint => m_ActiveViewpoint;\n\n        internal bool hasActiveViewpoint => m_ActiveViewpoint != null && m_ActiveViewpoint.TargetObject;\n\n        internal ViewpointSettings cameraOverscanSettings\n        {\n            get => m_CameraOverscanSettings;\n            set => m_CameraOverscanSettings = value;\n        }\n\n        internal void AssignSceneView(SceneView sceneView)\n        {\n            m_SceneView = sceneView;\n        }\n\n        internal SceneViewViewpoint()\n        {\n            m_CameraOverscanSettings = new ViewpointSettings();\n        }\n\n        internal void SetViewpoint(IViewpoint view)\n        {\n            m_ActiveViewpoint = view;\n            cameraLookThroughStateChanged?.Invoke(true);\n        }\n\n        internal void ClearViewpoint()\n        {\n            if (m_ActiveViewpoint == null)\n                return;\n\n            // When the Editor goes into PlayMode, it destroyes all the overlays.\n            // At that specific moment, the SceneView's camera could be null.\n            if (m_ActiveViewpoint.TargetObject && m_SceneView.camera)\n            {\n                m_SceneView.LookAt(\n                    m_ActiveViewpoint.Position + (m_ActiveViewpoint.Rotation * Vector3.forward) * m_SceneView.CalcCameraDist(),\n                    m_ActiveViewpoint.Rotation,\n                    m_SceneView.size,\n                    false,\n                    true);\n            }\n\n            m_ActiveViewpoint = null;\n\n            if (m_TemporaryCamera)\n                UObject.DestroyImmediate(m_TemporaryCamera.gameObject);\n\n            cameraLookThroughStateChanged?.Invoke(false);\n        }\n\n        // When in Camera view.\n        // Transfer Camera's transform to the Viewpoint's transform when the SceneView's camera moves.\n        // When the active Viewpoint moves (i.e from scripts or animation), transfer the data to the SceneView's Camera.\n        internal void UpdateViewpointMotion(bool sceneViewTransformIsAnimating)\n        {\n            // Exit the viewpoint if viewpoint is unlocked and\n            // Scene View camera is moving.\n            if (shouldExitViewpoint)\n            {\n                ClearViewpoint();\n                return;\n            }\n\n            if (!hasActiveViewpoint)\n                return;\n\n            if (m_SceneView.sceneViewMotion.cameraSpeed.sqrMagnitude > Mathf.Epsilon\n                    || m_SceneView.sceneViewMotion.isDragging\n                    || sceneViewTransformIsAnimating)\n            {\n                // Camera is moving in the Scene View. Align SceneView's Camera to Viewpoint.\n                TryMoveViewpoint();\n            }\n            else\n            {\n                // Align the Viewpoint's transform to the SceneView's Camera when no system is driving the Scene View.\n                AlignSceneViewToViewpoint();\n            }\n        }\n\n        // Applies the active viewpoint camera properties to the camera.\n        internal void ApplyCameraLensFromViewpoint(bool sceneViewIsPerspective)\n        {\n            var lensData = activeViewpoint as ICameraLensData;\n\n            if (lensData == null)\n                return;\n\n            m_SceneView.camera.nearClipPlane = lensData.NearClipPlane;\n            m_SceneView.camera.farClipPlane = lensData.FarClipPlane;\n\n            float scale = cameraOverscanSettings.scale;\n\n            if (!lensData.Orthographic)\n            {\n                m_SceneView.camera.orthographic = false;\n                m_SceneView.camera.fieldOfView = m_SceneView.GetVerticalFOV(lensData.FieldOfView, scale);\n            }\n            else\n            {\n                m_SceneView.camera.orthographic = true;\n                m_SceneView.camera.orthographicSize = lensData.OrthographicSize * scale;\n            }\n        }\n\n        internal void OnGUIDrawCameraOverscan()\n        {\n            if (activeViewpoint?.TargetObject == null)\n                return;\n\n            var lensData = activeViewpoint as ICameraLensData;\n\n            if (lensData == null)\n                return;\n\n            Camera camera = activeViewpoint.TargetObject as Camera;\n\n            if (camera == null)\n            {\n                camera = temporaryCamera.GetComponent<Camera>();\n\n                ViewpointUtility.ApplyTransformData(activeViewpoint, camera.transform);\n                ViewpointUtility.ApplyCameraLensData(lensData, camera);\n            }\n\n            Vector3[] nearPlaneCorners = new Vector3[4];\n\n            // Todo: to update with Karl to remove dependency on camera reference.\n            CameraEditorUtils.TryGetFrustum(camera, nearPlaneCorners, null, out float _);\n\n            Rect viewport = m_SceneView.cameraViewport;\n            Color previous = GUI.color;\n\n            Handles.BeginGUI();\n\n            var pp0gui = HandleUtility.WorldToGUIPoint(nearPlaneCorners[0]);\n            var pp1gui = HandleUtility.WorldToGUIPoint(nearPlaneCorners[1]);\n            var pp2gui = HandleUtility.WorldToGUIPoint(nearPlaneCorners[2]);\n            var pp3gui = HandleUtility.WorldToGUIPoint(nearPlaneCorners[3]);\n\n            pp0gui = new Vector2(Mathf.RoundToInt(pp0gui.x), Mathf.RoundToInt(pp0gui.y));\n            pp1gui = new Vector2(Mathf.RoundToInt(pp1gui.x), Mathf.RoundToInt(pp1gui.y));\n            pp2gui = new Vector2(Mathf.RoundToInt(pp2gui.x), Mathf.RoundToInt(pp2gui.y));\n            pp3gui = new Vector2(Mathf.RoundToInt(pp3gui.x), Mathf.RoundToInt(pp3gui.y));\n\n            // Draw overscan\n            GUI.color = new Color(1f, 1f, 1f, (float)cameraOverscanSettings.opacity / 100f);\n            Rect top2 = Rect.MinMaxRect(0, 0, viewport.width, pp1gui.y);\n            Rect bottom2 = Rect.MinMaxRect(0, pp3gui.y, viewport.width, viewport.height);\n            Rect right2 = Rect.MinMaxRect(pp3gui.x, top2.yMax, viewport.width, bottom2.yMin);\n            Rect left2 = Rect.MinMaxRect(0f, top2.yMax, pp1gui.x, bottom2.yMin);\n\n            GUI.DrawTexture(top2, Texture2D.whiteTexture, ScaleMode.StretchToFill);\n            GUI.DrawTexture(bottom2, Texture2D.whiteTexture, ScaleMode.StretchToFill);\n            GUI.DrawTexture(left2, Texture2D.whiteTexture, ScaleMode.StretchToFill);\n            GUI.DrawTexture(right2, Texture2D.whiteTexture, ScaleMode.StretchToFill);\n\n            // Draw camera frame\n            Rect topHardEdge = Rect.MinMaxRect(pp1gui.x - k_CameraFrameThickness, pp1gui.y - k_CameraFrameThickness, pp2gui.x + k_CameraFrameThickness, pp1gui.y);\n            Rect bottomHardEdge = Rect.MinMaxRect(pp0gui.x - k_CameraFrameThickness, pp0gui.y, pp3gui.x + k_CameraFrameThickness, pp0gui.y + k_CameraFrameThickness);\n            Rect leftHardEdge = Rect.MinMaxRect(pp1gui.x - k_CameraFrameThickness, pp1gui.y - k_CameraFrameThickness, pp1gui.x, pp0gui.y + k_CameraFrameThickness);\n            Rect rightHardEdge = Rect.MinMaxRect(pp2gui.x, pp2gui.y - k_CameraFrameThickness, pp2gui.x + k_CameraFrameThickness, pp3gui.y + k_CameraFrameThickness);\n\n            GUI.color = ViewpointIsSelected() ? Color.yellow : Color.white;\n            GUI.DrawTexture(topHardEdge, Texture2D.whiteTexture, ScaleMode.StretchToFill);\n            GUI.DrawTexture(bottomHardEdge, Texture2D.whiteTexture, ScaleMode.StretchToFill);\n            GUI.DrawTexture(leftHardEdge, Texture2D.whiteTexture, ScaleMode.StretchToFill);\n            GUI.DrawTexture(rightHardEdge, Texture2D.whiteTexture, ScaleMode.StretchToFill);\n\n            Handles.EndGUI();\n\n            GUI.color = previous;\n        }\n\n        internal void HandleScrollWheel(SceneView view)\n        {\n            var evt = Event.current;\n            if ((evt.modifiers & EventModifiers.Alt) != 0)\n            {\n                UpdateFieldOfView();\n                view.Repaint();\n            }\n            else if (evt.modifiers == 0)\n            {\n                UpdateOverscan();\n                view.Repaint();\n            }\n            Event.current.Use();\n        }\n\n        void UpdateFieldOfView()\n        {\n            // Check active tool context\n            if (!viewpointContextIsActive || !(activeViewpoint is ICameraLensData))\n                return;\n\n            DoChangeFieldOfView(activeViewpoint, (int)Mathf.Sign(Event.current.delta.y));\n        }\n\n        void UpdateOverscan()\n        {\n            // Check active tool context\n            if (!viewpointContextIsActive)\n                return;\n\n            float delta = Event.current.delta.y;\n            cameraOverscanSettings.scale += delta * k_MouseWheelScaleSensitivityMultiplier;\n        }\n\n        static void DoChangeFieldOfView(IViewpoint viewpoint, int sign)\n        {\n            var lensData = viewpoint as ICameraLensData;\n\n            if (lensData.Orthographic == false)\n            {\n                if (lensData.UsePhysicalProperties)\n                {\n                    Undo.RecordObject(viewpoint.TargetObject, $\"Modified Focal Length size in {viewpoint.TargetObject.name}\");\n                    lensData.FocalLength += sign * 1f;\n                }\n                else\n                {\n                    Undo.RecordObject(viewpoint.TargetObject, $\"Modified Field of view in {viewpoint.TargetObject.name}\");\n                    lensData.FieldOfView += sign * 1f;\n                }\n            }\n            else\n            {\n                Undo.RecordObject(viewpoint.TargetObject, $\"Modified Orthographic size in {viewpoint.TargetObject.name}\");\n                lensData.OrthographicSize += sign * .025f;\n            }\n        }\n\n        // Tells if the GameObject represented by the Viewpoint is currently selected in the Hierarchy.\n        bool ViewpointIsSelected()\n        {\n            return Selection.Contains(activeViewpoint.TargetObject);\n        }\n\n        void TryMoveViewpoint()\n        {\n            activeViewpoint.Rotation = m_SceneView.GetTransformRotation();\n            activeViewpoint.Position = m_SceneView.GetTransformPosition();\n\n            if (activeViewpoint.Rotation != m_SceneView.GetTransformRotation()\n                    || activeViewpoint.Position != m_SceneView.GetTransformPosition())\n            {\n                // Viewpoint is under some constraint. Apply back to SceneView so it gives the appropriate feedback to the user.\n                AlignSceneViewToViewpoint();\n            }\n        }\n\n        void AlignSceneViewToViewpoint()\n        {\n            if (!m_SceneView.in2DMode)\n                m_SceneView.rotation = activeViewpoint.Rotation;\n\n            m_SceneView.pivot = activeViewpoint.Position + activeViewpoint.Rotation * new Vector3(0, 0, m_SceneView.cameraDistance);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneView/Viewpoint/CameraViewpoint.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class CameraViewpoint : Viewpoint<Camera>, ICameraLensData\n    {\n        public CameraViewpoint(Camera target)\n            : base(target)\n        {\n        }\n\n        public bool Orthographic\n        {\n            get => Target.orthographic;\n            set => Target.orthographic = value;\n        }\n\n        public float OrthographicSize\n        {\n            get => Target.orthographicSize;\n            set => Target.orthographicSize = value;\n        }\n\n        public float FieldOfView\n        {\n            get => Target.usePhysicalProperties ? Target.GetGateFittedFieldOfView() : Target.fieldOfView;\n            set => Target.fieldOfView = value;\n        }\n\n        public float FocalLength\n        {\n            get => Target.focalLength;\n            set => Target.focalLength = value;\n        }\n\n        public bool UsePhysicalProperties\n        {\n            get => Target.usePhysicalProperties;\n        }\n\n        public Vector2 SensorSize => Target.sensorSize;\n\n        public float NearClipPlane => Target.nearClipPlane;\n\n        public float FarClipPlane => Target.farClipPlane;\n\n        public Vector2 LensShift => Target.lensShift;\n\n        public Camera.GateFitMode GateFit => Target.gateFit;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneView/Viewpoint/ViewpointAPI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing UObject = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    interface IViewpoint\n    {\n        UObject TargetObject { get; }\n\n        Vector3 Position { get; set; }\n        Quaternion Rotation { get; set; }\n\n        VisualElement CreateVisualElement();\n    }\n\n    public interface ICameraLensData\n    {\n        float NearClipPlane { get; }\n        float FarClipPlane { get; }\n        float FieldOfView { get; set; }\n\n        bool UsePhysicalProperties { get; }\n        float FocalLength { get; set; }\n        Vector2 SensorSize { get; }\n        Vector2 LensShift { get; }\n        Camera.GateFitMode GateFit { get; }\n\n        bool Orthographic { get; set; }\n        float OrthographicSize { get; set; }\n    }\n\n    internal class ViewpointUtility\n    {\n        static internal void ApplyTransformData(IViewpoint viewpoint, Transform destination)\n        {\n            destination.transform.position = viewpoint.Position;\n            destination.transform.rotation = viewpoint.Rotation;\n        }\n\n        static internal void ApplyCameraLensData(ICameraLensData data, Camera destination)\n        {\n            destination.nearClipPlane = data.NearClipPlane;\n            destination.farClipPlane = data.FarClipPlane;\n            destination.orthographic = data.Orthographic;\n            destination.orthographicSize = data.OrthographicSize;\n            destination.fieldOfView = data.FieldOfView;\n            destination.focalLength = data.FocalLength;\n            destination.usePhysicalProperties = data.UsePhysicalProperties;\n            destination.sensorSize = data.SensorSize;\n            destination.lensShift = data.LensShift;\n            destination.gateFit = data.GateFit;\n        }\n    }\n\n    [Serializable]\n    public abstract class Viewpoint<T> : IViewpoint where T : Component\n    {\n        [SerializeField]\n        T m_Target;\n\n        public UObject TargetObject\n        {\n            get => m_Target;\n            set => m_Target = value as T;\n        }\n\n        public virtual Vector3 Position\n        {\n            get => m_Target.transform.position;\n            set\n            {\n                Undo.RecordObject(m_Target.transform, $\"Move {m_Target.name}\");\n                m_Target.transform.position = value;\n            }\n        }\n\n        public virtual Quaternion Rotation\n        {\n            get => m_Target.transform.rotation;\n            set\n            {\n                Undo.RecordObject(m_Target.transform, $\"Rotate {m_Target.name}\");\n                m_Target.transform.rotation = value;\n            }\n        }\n\n        protected T Target\n        {\n            get => m_Target;\n        }\n\n        public Viewpoint(T target)\n        {\n            m_Target = target;\n        }\n\n        public virtual VisualElement CreateVisualElement() { return null; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneView/Viewpoint/ViewpointProxyTypeCache.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    class ViewpointProxyTypeCache\n    {\n        static ViewpointProxyTypeCache[] s_Cache;\n\n        Type m_ViewpointType;\n        Type m_TranslatorType;\n\n        internal Type viewpointType { get => m_ViewpointType; }\n        internal Type translatorType { get => m_TranslatorType; }\n\n        internal static ViewpointProxyTypeCache[] caches\n        {\n            get\n            {\n                if (s_Cache == null)\n                    s_Cache = GetProxiesForViewpoints();\n                return s_Cache;\n            }\n        }\n\n        ViewpointProxyTypeCache(Type targetType, Type translatorType)\n        {\n            m_ViewpointType = targetType;\n            m_TranslatorType = translatorType;\n        }\n\n        internal static IEnumerable<ViewpointProxyTypeCache> GetSupportedCameraComponents()\n        {\n            foreach (var entry in s_Cache)\n            {\n                bool found = false;\n                foreach (Type interfaceType in entry.translatorType.GetInterfaces())\n                {\n                    if (interfaceType == typeof(ICameraLensData))\n                        found = true;\n                }\n\n                if (!found)\n                    continue;\n\n                yield return entry;\n            }\n        }\n\n        internal static Type GetTranslatorTypeForType(Type type)\n        {\n            foreach (var entry in caches)\n            {\n                if (entry.viewpointType == type)\n                    return entry.translatorType;\n            }\n            return null;\n        }\n\n        internal static Texture2D GetIcon(IViewpoint viewpoint)\n        {\n            Texture2D icon = EditorGUIUtility.GetIconForObject(viewpoint.TargetObject);\n\n            // This way works better to get the icon for the Camera component.\n            if (icon == null)\n                icon = EditorGUIUtility.FindTexture(viewpoint.TargetObject.GetType());\n\n            return icon;\n        }\n\n        static ViewpointProxyTypeCache[] GetProxiesForViewpoints()\n        {\n            (Type, Type) k_NullData = (null, null);\n\n            var types = TypeCache.GetTypesDerivedFrom<IViewpoint>();\n\n            List<Type> filteredTypes = new List<Type>();\n            foreach (var type in types)\n            {\n                if (!type.IsAbstract && !type.IsSubclassOf(typeof(MonoBehaviour)))\n                    filteredTypes.Add(type);\n            }\n\n            List<ViewpointProxyTypeCache> viewpoints = new List<ViewpointProxyTypeCache>();\n\n            foreach (Type type in filteredTypes)\n            {\n                (Type, Type) targetAndTranslatorTypes = GetGenericViewpointType(type);\n                if (targetAndTranslatorTypes == k_NullData)\n                    continue;\n\n                viewpoints.Add(new ViewpointProxyTypeCache(targetAndTranslatorTypes.Item2, type));\n            }\n            return viewpoints.ToArray();\n        }\n\n        static (Type, Type) GetGenericViewpointType(Type type)\n        {\n            Type baseT = type.BaseType;\n\n            while (baseT != null)\n            {\n                if (baseT.IsGenericType)\n                {\n                    if (baseT.GetGenericTypeDefinition() == typeof(Viewpoint<>))\n                        return (baseT, baseT.GetGenericArguments()[0]);\n                }\n                baseT = baseT.BaseType;\n            }\n            return (null, null);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneVisibility/SceneVisibilityHierarchyGUI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.Experimental;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEditor.StyleSheets;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing TreeViewGUI = UnityEditor.IMGUI.Controls.TreeViewGUI<int>;\n\n\nnamespace UnityEditor\n{\n    internal static class SceneVisibilityHierarchyGUI\n    {\n        internal static class Styles\n        {\n            public class IconState\n            {\n                public GUIContent visibleAll;\n                public GUIContent visibleMixed;\n                public GUIContent hiddenAll;\n                public GUIContent hiddenMixed;\n                public GUIContent pickingEnabledAll;\n                public GUIContent pickingEnabledMixed;\n                public GUIContent pickingDisabledAll;\n                public GUIContent pickingDisabledMixed;\n            }\n\n            public static readonly IconState iconNormal = new IconState\n            {\n                visibleAll = EditorGUIUtility.TrIconContent(\"scenevis_visible\"),\n                visibleMixed = EditorGUIUtility.TrIconContent(\"scenevis_visible-mixed\"),\n                hiddenAll = EditorGUIUtility.TrIconContent(\"scenevis_hidden\"),\n                hiddenMixed = EditorGUIUtility.TrIconContent(\"scenevis_hidden-mixed\"),\n                pickingEnabledAll = EditorGUIUtility.TrIconContent(\"scenepicking_pickable\"),\n                pickingEnabledMixed = EditorGUIUtility.TrIconContent(\"scenepicking_pickable-mixed\"),\n                pickingDisabledAll = EditorGUIUtility.TrIconContent(\"scenepicking_notpickable\"),\n                pickingDisabledMixed = EditorGUIUtility.TrIconContent(\"scenepicking_notpickable-mixed\"),\n            };\n\n            public static readonly IconState iconHovered = new IconState\n            {\n                visibleAll = EditorGUIUtility.TrIconContent(\"scenevis_visible_hover\"),\n                visibleMixed = EditorGUIUtility.TrIconContent(\"scenevis_visible-mixed_hover\"),\n                hiddenAll = EditorGUIUtility.TrIconContent(\"scenevis_hidden_hover\"),\n                hiddenMixed = EditorGUIUtility.TrIconContent(\"scenevis_hidden-mixed_hover\"),\n                pickingEnabledAll = EditorGUIUtility.TrIconContent(\"scenepicking_pickable_hover\"),\n                pickingEnabledMixed = EditorGUIUtility.TrIconContent(\"scenepicking_pickable-mixed_hover\"),\n                pickingDisabledAll = EditorGUIUtility.TrIconContent(\"scenepicking_notpickable_hover\"),\n                pickingDisabledMixed = EditorGUIUtility.TrIconContent(\"scenepicking_notpickable-mixed_hover\"),\n            };\n\n            public static readonly Color backgroundColor = EditorResources.GetStyle(\"game-object-tree-view-scene-visibility\")\n                .GetColor(\"background-color\");\n\n            public static readonly Color hoveredBackgroundColor = EditorResources.GetStyle(\"game-object-tree-view-scene-visibility\")\n                .GetColor(\"-unity-object-hovered-color\");\n\n            public static readonly Color selectedBackgroundColor = EditorResources.GetStyle(\"game-object-tree-view-scene-visibility\")\n                .GetColor(\"-unity-object-selected-color\");\n\n            public static readonly Color selectedNoFocusBackgroundColor = EditorResources.GetStyle(\"game-object-tree-view-scene-visibility\")\n                .GetColor(\"-unity-object-selected-no-focus-color\");\n\n            public static readonly GUIStyle sceneVisibilityStyle = \"SceneVisibility\";\n\n            public static Color GetItemBackgroundColor(bool isHovered, bool isSelected, bool isFocused)\n            {\n                if (isSelected)\n                {\n                    if (isFocused)\n                        return selectedBackgroundColor;\n\n                    return selectedNoFocusBackgroundColor;\n                }\n\n                if (isHovered)\n                    return hoveredBackgroundColor;\n\n                return backgroundColor;\n            }\n        }\n\n        private const int k_VisibilityIconPadding = 0;\n        private const int k_IconWidth = 16;\n\n        private static float k_sceneHeaderOverflow => GameObjectTreeViewGUI.GameObjectStyles.sceneHeaderBg.fixedHeight + 2*GameObjectTreeViewGUI.GameObjectStyles.sceneHeaderWidth - EditorGUIUtility.singleLineHeight;\n        private static bool m_PrevItemWasScene;\n\n        public const float utilityBarWidth = k_VisibilityIconPadding * 3 + k_IconWidth * 2;\n\n        public static void DrawBackground(Rect rect)\n        {\n            rect.width = utilityBarWidth;\n\n            using (new GUI.BackgroundColorScope(Styles.backgroundColor))\n            {\n                GUI.Label(rect, GUIContent.none, GameObjectTreeViewGUI.GameObjectStyles.hoveredItemBackgroundStyle);\n            }\n        }\n\n        public static void DoItemGUI(Rect rect, GameObjectTreeViewItem goItem, bool isSelected, bool isHovered, bool isFocused, bool isDragging)\n        {\n            if (Event.current.isKey || Event.current.type == EventType.Layout)\n                return;\n\n            Rect iconRect = rect;\n            iconRect.xMin += k_VisibilityIconPadding;\n            iconRect.width = k_IconWidth;\n            isHovered = isHovered && !isDragging;\n            bool isIconHovered = !isDragging && iconRect.Contains(Event.current.mousePosition);\n\n            Rect icon2Rect = rect;\n            icon2Rect.xMin += 2 * k_VisibilityIconPadding + k_IconWidth;\n            icon2Rect.width = k_IconWidth;\n            bool isIcon2Hovered = !isDragging && icon2Rect.Contains(Event.current.mousePosition);\n\n            if (isHovered)\n            {\n                GUIView.current.MarkHotRegion(GUIClip.UnclipToWindow(iconRect));\n                GUIView.current.MarkHotRegion(GUIClip.UnclipToWindow(icon2Rect));\n            }\n\n            GameObject gameObject = goItem.objectPPTR as GameObject;\n            if (gameObject)\n            {\n                // The scene header overlaps it's next item by some pixels. Displace the background so it doesn't draw on top of the scene header.\n                // Don't displace when selected or hovered (They already show on top of the header)\n                if (m_PrevItemWasScene && !isSelected && !isHovered)\n                    rect.yMin += k_sceneHeaderOverflow;\n\n                DrawItemBackground(rect, false, isSelected, isHovered, isFocused);\n                DrawGameObjectItemVisibility(iconRect, gameObject, isHovered, isIconHovered);\n                DrawGameObjectItemPicking(icon2Rect, gameObject, isHovered, isIcon2Hovered);\n\n                m_PrevItemWasScene = false;\n            }\n            else\n            {\n                Scene scene = goItem.scene;\n                if (scene.IsValid())\n                {\n                    DrawItemBackground(rect, true, isSelected, isHovered, isFocused);\n                    DrawSceneItemVisibility(iconRect, scene, isHovered, isIconHovered);\n                    DrawSceneItemPicking(icon2Rect, scene, isHovered, isIcon2Hovered);\n                    m_PrevItemWasScene = true;\n                }\n            }\n        }\n\n        private static void DrawItemBackground(Rect rect, bool isScene, bool isSelected, bool isHovered, bool isFocused)\n        {\n            if (Event.current.type != EventType.Repaint)\n                return;\n\n            rect.width = utilityBarWidth;\n\n            if (isScene)\n            {\n                if (isSelected)\n                {\n                    TreeViewGUI.Styles.selectionStyle.Draw(rect, false, false, true, isFocused);\n                }\n            }\n            else\n            {\n                using (new GUI.BackgroundColorScope(Styles.GetItemBackgroundColor(isHovered, isSelected, isFocused))\n                )\n                {\n                    GUI.Label(rect, GUIContent.none,\n                        GameObjectTreeViewGUI.GameObjectStyles.hoveredItemBackgroundStyle);\n                }\n            }\n        }\n\n        private static void DrawGameObjectItemVisibility(Rect rect, GameObject gameObject, bool isItemHovered, bool isIconHovered)\n        {\n            var isHidden = SceneVisibilityManager.instance.IsHidden(gameObject);\n            bool shouldDisplayIcon = isItemHovered || isHidden;\n            Styles.IconState iconState = isIconHovered ? Styles.iconHovered : Styles.iconNormal;\n\n            GUIContent icon;\n            if (isHidden)\n            {\n                icon = gameObject.transform.childCount == 0 || SceneVisibilityManager.instance.AreAllDescendantsHidden(gameObject)\n                    ? iconState.hiddenAll : iconState.hiddenMixed;\n            }\n            else if (!SceneVisibilityManager.instance.AreAllDescendantsVisible(gameObject))\n            {\n                icon = iconState.visibleMixed;\n                shouldDisplayIcon = true;\n            }\n            else\n            {\n                icon = iconState.visibleAll;\n            }\n\n            if (shouldDisplayIcon && GUI.Button(rect, icon, Styles.sceneVisibilityStyle))\n            {\n                SceneVisibilityManager.instance.ToggleVisibility(gameObject, !Event.current.alt);\n            }\n        }\n\n        private static void DrawGameObjectItemPicking(Rect rect, GameObject gameObject, bool isItemHovered, bool isIconHovered)\n        {\n            var isPickingDisabled = SceneVisibilityManager.instance.IsPickingDisabled(gameObject);\n            bool shouldDisplayIcon = isItemHovered || isPickingDisabled;\n            Styles.IconState iconState = isIconHovered ? Styles.iconHovered : Styles.iconNormal;\n\n            GUIContent icon;\n            if (isPickingDisabled)\n            {\n                icon = gameObject.transform.childCount == 0 || SceneVisibilityManager.instance.IsPickingDisabledOnAllDescendants(gameObject)\n                    ? iconState.pickingDisabledAll : iconState.pickingDisabledMixed;\n            }\n            else if (!SceneVisibilityManager.instance.IsPickingEnabledOnAllDescendants(gameObject))\n            {\n                icon = iconState.pickingEnabledMixed;\n                shouldDisplayIcon = true;\n            }\n            else\n            {\n                icon = iconState.pickingEnabledAll;\n            }\n\n            if (shouldDisplayIcon && GUI.Button(rect, icon, Styles.sceneVisibilityStyle))\n            {\n                SceneVisibilityManager.instance.TogglePicking(gameObject, !Event.current.alt);\n            }\n        }\n\n        private static void DrawSceneItemVisibility(Rect rect, Scene scene, bool isItemHovered, bool isIconHovered)\n        {\n            var state = SceneVisibilityManager.instance.GetSceneVisibilityState(scene);\n            bool shouldDisplayIcon = true;\n            Styles.IconState iconState = isIconHovered ? Styles.iconHovered : Styles.iconNormal;\n\n            GUIContent icon;\n            if (state == SceneVisibilityManager.SceneVisState.AllHidden)\n            {\n                icon = iconState.hiddenAll;\n            }\n            else if (state == SceneVisibilityManager.SceneVisState.Mixed)\n            {\n                icon = iconState.visibleMixed;\n            }\n            else\n            {\n                icon = iconState.visibleAll;\n                shouldDisplayIcon = isItemHovered;\n            }\n\n\n            if (shouldDisplayIcon && GUI.Button(rect, icon, Styles.sceneVisibilityStyle))\n            {\n                SceneVisibilityManager.instance.ToggleScene(scene, state);\n            }\n        }\n\n        private static void DrawSceneItemPicking(Rect rect, Scene scene, bool isItemHovered, bool isIconHovered)\n        {\n            var state = SceneVisibilityManager.instance.GetScenePickingState(scene);\n            bool shouldDisplayIcon = true;\n            Styles.IconState iconState = isIconHovered ? Styles.iconHovered : Styles.iconNormal;\n\n            GUIContent icon;\n            var enablePicking = false;\n            if (state == SceneVisibilityManager.ScenePickingState.PickingDisabledAll)\n            {\n                icon = iconState.pickingDisabledAll;\n                enablePicking = true;\n            }\n            else if (state == SceneVisibilityManager.ScenePickingState.Mixed)\n            {\n                icon = iconState.pickingEnabledMixed;\n            }\n            else\n            {\n                icon = iconState.pickingEnabledAll;\n                shouldDisplayIcon = isItemHovered;\n            }\n\n            if (shouldDisplayIcon && GUI.Button(rect, icon, Styles.sceneVisibilityStyle))\n            {\n                if (enablePicking)\n                {\n                    SceneVisibilityManager.instance.EnablePicking(scene);\n                }\n                else\n                {\n                    SceneVisibilityManager.instance.DisablePicking(scene);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneVisibility/SceneVisibilityManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.SceneManagement;\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing Scene = UnityEngine.SceneManagement.Scene;\n\nnamespace UnityEditor\n{\n    public class SceneVisibilityManager : ScriptableSingleton<SceneVisibilityManager>\n    {\n        internal class ShortcutContext : IShortcutContext\n        {\n            public bool active\n            {\n                get\n                {\n                    var focusedWindow = EditorWindow.focusedWindow;\n                    if (focusedWindow != null)\n                    {\n                        return (focusedWindow.GetType() == typeof(SceneView) ||\n                            focusedWindow.GetType() == typeof(SceneHierarchyWindow));\n                    }\n\n                    return false;\n                }\n            }\n        }\n\n        private static ShortcutContext s_ShortcutContext;\n\n        public static event Action visibilityChanged;\n\n        public static event Action pickingChanged;\n\n        internal static event Action<bool> currentStageIsIsolated;\n\n        private readonly static List<GameObject> m_RootBuffer = new List<GameObject>();\n\n        internal bool enableSceneVisibility\n        {\n            get { return SceneVisibilityState.visibilityActive; }\n            set { SceneVisibilityState.visibilityActive = value; }\n        }\n\n        internal bool enableScenePicking\n        {\n            get { return SceneVisibilityState.pickingActive; }\n            set { SceneVisibilityState.pickingActive = value; }\n        }\n\n        [InitializeOnLoadMethod]\n        private static void Initialize()\n        {\n            Undo.undoRedoEvent += UndoRedoPerformed;\n            EditorSceneManager.newSceneCreated += EditorSceneManagerOnNewSceneCreated;\n            EditorSceneManager.sceneSaving += EditorSceneManagerOnSceneSaving;\n            EditorSceneManager.sceneSaved += EditorSceneManagerOnSceneSaved;\n            EditorSceneManager.sceneOpening += EditorSceneManagerOnSceneOpening;\n            EditorSceneManager.sceneOpened += EditorSceneManagerOnSceneOpened;\n            EditorSceneManager.sceneClosing += EditorSceneManagerOnSceneClosing;\n            EditorApplication.playModeStateChanged += EditorApplicationPlayModeStateChanged;\n            StageNavigationManager.instance.afterSuccessfullySwitchedToStage += StageNavigationManagerAfterSuccessfullySwitchedToStage;\n            SceneVisibilityState.internalStructureChanged += InternalStructureChanged;\n            PreviewSceneStage stage = StageNavigationManager.instance.currentStage as PreviewSceneStage;\n            SceneVisibilityState.ForceDataUpdate();\n\n            s_ShortcutContext = new ShortcutContext();\n            EditorApplication.delayCall += () => ShortcutIntegration.instance.contextManager.RegisterToolContext(s_ShortcutContext);\n        }\n\n        private static void InternalStructureChanged()\n        {\n            instance.VisibilityChanged();\n            instance.PickableContentChanged();\n        }\n\n        private static void EditorSceneManagerOnSceneOpened(Scene scene, OpenSceneMode mode)\n        {\n            if (mode == OpenSceneMode.Single)\n            {\n                SceneVisibilityState.isolation = false;\n            }\n            if (mode == OpenSceneMode.Additive)\n            {\n                //make sure added scenes are isolated when opened if main stage is isolated\n                if (StageNavigationManager.instance.currentStage is MainStage)\n                {\n                    Undo.ClearUndo(SceneVisibilityState.GetInstance());\n                }\n            }\n        }\n\n        internal static void StageNavigationManagerAfterSuccessfullySwitchedToStage(Stage newStage)\n        {\n            RevertIsolationCurrentStage();\n            SceneVisibilityState.ForceDataUpdate();\n            if (newStage is MainStage)\n            {\n                SceneVisibilityState.CleanTempScenes();\n            }\n        }\n\n        private static void EditorApplicationPlayModeStateChanged(PlayModeStateChange state)\n        {\n            if (state == PlayModeStateChange.ExitingEditMode)\n            {\n                SceneVisibilityState.GeneratePersistentDataForAllLoadedScenes();\n            }\n        }\n\n        private static void EditorSceneManagerOnSceneSaved(Scene scene)\n        {\n            SceneVisibilityState.OnSceneSaved(scene);\n        }\n\n        private static void EditorSceneManagerOnSceneSaving(Scene scene, string path)\n        {\n            SceneVisibilityState.OnSceneSaving(scene, path);\n        }\n\n        private static void EditorSceneManagerOnSceneOpening(string path, OpenSceneMode mode)\n        {\n            RevertIsolationCurrentStage();\n            if (mode == OpenSceneMode.Single)\n                SceneVisibilityState.GeneratePersistentDataForAllLoadedScenes();\n        }\n\n        private static void EditorSceneManagerOnSceneClosing(Scene scene, bool removingScene)\n        {\n            //Scene closing is called multiple times on the same scene which messes with the scene visibility persistent data\n            if (BuildPipeline.isBuildingPlayer)\n                return;\n\n            SceneVisibilityState.GeneratePersistentDataForLoadedScene(scene);\n        }\n\n        private static void EditorSceneManagerOnNewSceneCreated(Scene scene, NewSceneSetup setup, NewSceneMode mode)\n        {\n            if (mode == NewSceneMode.Single)\n            {\n                SceneVisibilityState.GeneratePersistentDataForAllLoadedScenes();\n            }\n            //need to clear scene on new scene since all new scenes use the same GUID\n            SceneVisibilityState.ClearScene(scene);\n        }\n\n        private static void UndoRedoPerformed(in UndoRedoInfo info)\n        {\n            SceneVisibilityState.ForceDataUpdate();\n        }\n\n        public void HideAll()\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Hide All\");\n            HideAllNoUndo();\n        }\n\n        private void HideAllNoUndo()\n        {\n            Stage stage = StageNavigationManager.instance.currentStage;\n            for (int i = 0; i < stage.sceneCount; i++)\n            {\n                HideNoUndo(stage.GetSceneAt(i));\n            }\n        }\n\n        public void DisableAllPicking()\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Disable All Picking\");\n            DisableAllPickingNoUndo();\n        }\n\n        private void DisableAllPickingNoUndo()\n        {\n            PreviewSceneStage previewSceneStage = StageNavigationManager.instance.currentStage as PreviewSceneStage;\n            if (previewSceneStage != null)\n            {\n                var scene = previewSceneStage.scene;\n                SceneVisibilityState.EnablePicking(previewSceneStage.scene);\n                SceneVisibilityState.DisablePicking(scene);\n            }\n            else\n            {\n                for (int i = 0; i < SceneManager.sceneCount; i++)\n                {\n                    DisablePicking(SceneManager.GetSceneAt(i));\n                }\n            }\n        }\n\n        public void Show(GameObject gameObject, bool includeDescendants)\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Show GameObject\");\n            SceneVisibilityState.SetGameObjectHidden(gameObject, false, includeDescendants);\n        }\n\n        public void Hide(GameObject gameObject, bool includeDescendants)\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Hide GameObject\");\n            SceneVisibilityState.SetGameObjectHidden(gameObject, true, includeDescendants);\n        }\n\n        public void DisablePicking(GameObject gameObject, bool includeDescendants)\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Disable Picking GameObject\");\n            SceneVisibilityState.SetGameObjectPickingDisabled(gameObject, true, includeDescendants);\n        }\n\n        public void EnablePicking(GameObject gameObject, bool includeDescendants)\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Enable Picking GameObject\");\n            SceneVisibilityState.SetGameObjectPickingDisabled(gameObject, false, includeDescendants);\n        }\n\n        [Shortcut(\"Scene Visibility/Show All\")]\n        internal static void ShowAllShortcut()\n        {\n            instance.ShowAll();\n        }\n\n        public void ShowAll()\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Show All\");\n            Stage stage = StageNavigationManager.instance.currentStage;\n            for (int i = 0; i < stage.sceneCount; i++)\n            {\n                Show(stage.GetSceneAt(i), false);\n            }\n        }\n\n        public void EnableAllPicking()\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Enable All Picking\");\n            PreviewSceneStage previewSceneStage = StageNavigationManager.instance.currentStage as PreviewSceneStage;\n            if (previewSceneStage != null)\n            {\n                SceneVisibilityState.EnablePicking(previewSceneStage.scene);\n            }\n            else\n            {\n                for (int i = 0; i < SceneManager.sceneCount; i++)\n                {\n                    EnablePickingNoUndo(SceneManager.GetSceneAt(i));\n                }\n            }\n        }\n\n        private void Show(Scene scene, bool sendContentChangedEvent)\n        {\n            if (!scene.IsValid())\n                return;\n\n            if (!scene.isLoaded)\n                return;\n\n            SceneVisibilityState.ShowScene(scene);\n\n            if (sendContentChangedEvent)\n            {\n                VisibilityChanged();\n            }\n        }\n\n        private void EnablePickingNoUndo(Scene scene)\n        {\n            if (!scene.IsValid())\n                return;\n\n            if (!scene.isLoaded)\n                return;\n\n            SceneVisibilityState.EnablePicking(scene);\n        }\n\n        public void Show(Scene scene)\n        {\n            if (!scene.IsValid())\n                return;\n\n            if (!scene.isLoaded)\n                return;\n\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Show Scene\");\n            Show(scene, true);\n        }\n\n        public void EnablePicking(Scene scene)\n        {\n            if (!scene.IsValid())\n                return;\n\n            if (!scene.isLoaded)\n                return;\n\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Enable Picking Scene\");\n            EnablePickingNoUndo(scene);\n        }\n\n        private void HideNoUndo(Scene scene)\n        {\n            if (!scene.IsValid())\n                return;\n\n            if (!scene.isLoaded)\n                return;\n\n            SceneVisibilityState.ShowScene(scene);\n            scene.GetRootGameObjects(m_RootBuffer);\n            SceneVisibilityState.SetGameObjectsHidden(m_RootBuffer.ToArray(), true, true);\n        }\n\n        internal void DisablePickingNoUndo(Scene scene)\n        {\n            if (!scene.IsValid())\n                return;\n\n            if (!scene.isLoaded)\n                return;\n\n            SceneVisibilityState.EnablePicking(scene);\n            scene.GetRootGameObjects(m_RootBuffer);\n            SceneVisibilityState.SetGameObjectsPickingDisabled(m_RootBuffer.ToArray(), true, true);\n        }\n\n        public void Hide(Scene scene)\n        {\n            if (!scene.IsValid())\n                return;\n\n            if (!scene.isLoaded)\n                return;\n\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Hide Scene\");\n            HideNoUndo(scene);\n        }\n\n        public void DisablePicking(Scene scene)\n        {\n            if (!scene.IsValid())\n                return;\n\n            if (!scene.isLoaded)\n                return;\n\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Disable Picking Scene\");\n            DisablePickingNoUndo(scene);\n        }\n\n        public bool IsHidden(GameObject gameObject, bool includeDescendants = false)\n        {\n            if (includeDescendants)\n                return SceneVisibilityState.IsHierarchyHidden(gameObject);\n            else\n                return SceneVisibilityState.IsGameObjectHidden(gameObject);\n        }\n\n        public bool IsHidden(Scene scene)\n        {\n            if (!scene.IsValid() || !scene.isLoaded)\n                return false;\n\n            scene.GetRootGameObjects(m_RootBuffer);\n            foreach (var rootGameObject in m_RootBuffer)\n            {\n                if (!SceneVisibilityState.IsHierarchyHidden(rootGameObject))\n                    return false;\n            }\n\n            return true;\n        }\n\n        public bool IsPickingDisabled(GameObject gameObject, bool includeDescendants = false)\n        {\n            if (includeDescendants)\n                return SceneVisibilityState.IsHierarchyPickingDisabled(gameObject);\n            else\n                return SceneVisibilityState.IsGameObjectPickingDisabled(gameObject);\n        }\n\n        internal bool IsSelectable(GameObject go)\n        {\n            return IsSelectable(go, false);\n        }\n\n        internal bool IsSelectable(GameObject go, bool includeDescendants)\n        {\n            return !IsPickingDisabled(go, includeDescendants) && !IsHidden(go, includeDescendants);\n        }\n\n        public bool IsPickingDisabled(Scene scene)\n        {\n            if (!scene.IsValid() || !scene.isLoaded)\n                return false;\n\n            scene.GetRootGameObjects(m_RootBuffer);\n            foreach (var rootGameObject in m_RootBuffer)\n            {\n                if (!SceneVisibilityState.IsHierarchyPickingDisabled(rootGameObject))\n                    return false;\n            }\n\n            return true;\n        }\n\n        static bool IsIgnoredBySceneVisibility(GameObject go)\n        {\n            var hideFlags = HideFlags.HideInHierarchy;\n\n            return (go.hideFlags & hideFlags) != 0;\n        }\n\n        public bool AreAllDescendantsHidden(Scene scene)\n        {\n            return SceneVisibilityState.AreAllRootObjectsHiddenHierarchy(scene);\n        }\n\n        public bool IsPickingDisabledOnAllDescendants(Scene scene)\n        {\n            return SceneVisibilityState.IsPickingDisabledOnAllDescendants(scene);\n        }\n\n        public bool AreAnyDescendantsHidden(Scene scene)\n        {\n            if (!scene.IsValid() || !scene.isLoaded)\n                return false;\n\n            return SceneVisibilityState.HasHiddenGameObjects(scene);\n        }\n\n        public bool IsPickingDisabledOnAnyDescendant(Scene scene)\n        {\n            if (!scene.IsValid() || !scene.isLoaded)\n                return false;\n\n            return SceneVisibilityState.ContainsGameObjectsWithPickingDisabled(scene);\n        }\n\n        internal enum SceneVisState\n        {\n            AllHidden,\n            AllVisible,\n            Mixed\n        }\n\n        internal enum ScenePickingState\n        {\n            PickingDisabledAll,\n            PickingEnabledAll,\n            Mixed\n        }\n\n        internal SceneVisState GetSceneVisibilityState(Scene scene)\n        {\n            if (AreAllDescendantsHidden(scene))\n                return SceneVisState.AllHidden;\n            if (AreAnyDescendantsHidden(scene))\n                return SceneVisState.Mixed;\n            return SceneVisState.AllVisible;\n        }\n\n        internal ScenePickingState GetScenePickingState(Scene scene)\n        {\n            if (IsPickingDisabledOnAllDescendants(scene))\n                return ScenePickingState.PickingDisabledAll;\n            if (IsPickingDisabledOnAnyDescendant(scene))\n                return ScenePickingState.Mixed;\n            return ScenePickingState.PickingEnabledAll;\n        }\n\n        public void Show(GameObject[] gameObjects, bool includeDescendants)\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Show GameObjects\");\n            SceneVisibilityState.SetGameObjectsHidden(gameObjects, false, includeDescendants);\n        }\n\n        public void Hide(GameObject[] gameObjects, bool includeDescendants)\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Hide GameObjects\");\n            SceneVisibilityState.SetGameObjectsHidden(gameObjects, true, includeDescendants);\n        }\n\n        public void DisablePicking(GameObject[] gameObjects, bool includeDescendants)\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Disable Picking GameObjects\");\n            SceneVisibilityState.SetGameObjectsPickingDisabled(gameObjects, true, includeDescendants);\n        }\n\n        public void EnablePicking(GameObject[] gameObjects, bool includeDescendants)\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Enable Picking GameObjects\");\n            SceneVisibilityState.SetGameObjectsPickingDisabled(gameObjects, false, includeDescendants);\n        }\n\n        public void Isolate(GameObject gameObject, bool includeDescendants)\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Isolate GameObject\");\n\n            IsolateCurrentStage();\n            HideAllNoUndo();\n            SceneVisibilityState.SetGameObjectHidden(gameObject, false, includeDescendants);\n        }\n\n        public void Isolate(GameObject[] gameObjects, bool includeDescendants)\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Isolate GameObjects\");\n\n            IsolateCurrentStage();\n            HideAllNoUndo();\n            SceneVisibilityState.SetGameObjectsHidden(gameObjects, false, includeDescendants);\n        }\n\n        private void VisibilityChanged()\n        {\n            visibilityChanged?.Invoke();\n        }\n\n        private void PickableContentChanged()\n        {\n            pickingChanged?.Invoke();\n        }\n\n        public void ToggleVisibility(GameObject gameObject, bool includeDescendants)\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Toggle Visibility\");\n            SceneVisibilityState.SetGameObjectHidden(gameObject, !SceneVisibilityState.IsGameObjectHidden(gameObject), includeDescendants);\n        }\n\n        public void TogglePicking(GameObject gameObject, bool includeDescendants)\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Toggle Picking\");\n            SceneVisibilityState.SetGameObjectPickingDisabled(gameObject, !SceneVisibilityState.IsGameObjectPickingDisabled(gameObject), includeDescendants);\n        }\n\n        public bool AreAllDescendantsHidden(GameObject gameObject)\n        {\n            return SceneVisibilityState.AreAllChildrenHidden(gameObject);\n        }\n\n        public bool AreAllDescendantsVisible(GameObject gameObject)\n        {\n            return SceneVisibilityState.AreAllChildrenVisible(gameObject);\n        }\n\n        public bool IsPickingDisabledOnAllDescendants(GameObject gameObject)\n        {\n            return SceneVisibilityState.IsPickingDisabledOnAllChildren(gameObject);\n        }\n\n        public bool IsPickingEnabledOnAllDescendants(GameObject gameObject)\n        {\n            return SceneVisibilityState.IsPickingEnabledOnAllChildren(gameObject);\n        }\n\n        public bool IsCurrentStageIsolated()\n        {\n            return SceneVisibilityState.isolation;\n        }\n\n        private void IsolateCurrentStage()\n        {\n            SceneVisibilityState.isolation = true;\n            currentStageIsIsolated?.Invoke(true);\n        }\n\n        public void ExitIsolation()\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Exit Isolation\");\n            RevertIsolationCurrentStage();\n        }\n\n        private static void RevertIsolationCurrentStage()\n        {\n            SceneVisibilityState.isolation = false;\n            currentStageIsIsolated?.Invoke(false);\n        }\n\n        //SHORTCUTS\n        [Shortcut(\"Scene Visibility/Toggle Selection Visibility\")]\n        internal static void ToggleSelectionVisibility()\n        {\n            bool shouldHide = true;\n            foreach (var gameObject in Selection.gameObjects)\n            {\n                if (!instance.IsHidden(gameObject))\n                {\n                    break;\n                }\n\n                shouldHide = false;\n            }\n\n            instance.m_SelectedScenes.Clear();\n\n            var hierarchyWindow = SceneHierarchyWindow.lastInteractedHierarchyWindow;\n            if (shouldHide && hierarchyWindow)\n            {\n                hierarchyWindow.GetSelectedScenes(instance.m_SelectedScenes);\n\n                foreach (var scene in instance.m_SelectedScenes)\n                {\n                    if (!instance.IsHidden(scene))\n                        break;\n\n                    shouldHide = false;\n                }\n            }\n\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Toggle Selection Visibility\");\n            SceneVisibilityState.SetGameObjectsHidden(Selection.gameObjects, shouldHide, false);\n\n            foreach (var scene in instance.m_SelectedScenes)\n            {\n                if (shouldHide)\n                    instance.Hide(scene);\n                else\n                    instance.Show(scene);\n            }\n        }\n\n        [Shortcut(\"Scene Visibility/Toggle Selection And Descendants Visibility\", typeof(ShortcutContext), KeyCode.H)]\n        private static void ToggleSelectionAndDescendantsVisibility()\n        {\n            bool shouldHide = true;\n            foreach (var gameObject in Selection.gameObjects)\n            {\n                if (!instance.IsHidden(gameObject))\n                {\n                    break;\n                }\n\n                shouldHide = false;\n            }\n\n            instance.m_SelectedScenes.Clear();\n\n            var hierarchyWindow = SceneHierarchyWindow.lastInteractedHierarchyWindow;\n            if (shouldHide && hierarchyWindow)\n            {\n                hierarchyWindow.GetSelectedScenes(instance.m_SelectedScenes);\n\n                foreach (var scene in instance.m_SelectedScenes)\n                {\n                    if (!instance.IsHidden(scene))\n                        break;\n\n                    shouldHide = false;\n                }\n            }\n\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Toggle Selection And Descendants Visibility\");\n            SceneVisibilityState.SetGameObjectsHidden(Selection.gameObjects, shouldHide, true);\n\n            foreach (var scene in instance.m_SelectedScenes)\n            {\n                if (shouldHide)\n                    instance.Hide(scene);\n                else\n                    instance.Show(scene);\n            }\n        }\n\n        [Shortcut(\"Scene Picking/Toggle Picking On Selection And Descendants\", typeof(ShortcutContext), KeyCode.L)]\n        private static void ToggleSelectionAndDescendantsPicking()\n        {\n            ToggleSelectionPicking(true);\n        }\n\n        [Shortcut(\"Scene Picking/Toggle Picking On Selection\")]\n        internal static void ToggleSelectionPickable()\n        {\n            ToggleSelectionPicking(false);\n        }\n\n        private static void ToggleSelectionPicking(bool includeChildren)\n        {\n            bool shouldDisablePicking = true;\n            foreach (var gameObject in Selection.gameObjects)\n            {\n                if (!instance.IsPickingDisabled(gameObject))\n                {\n                    break;\n                }\n\n                shouldDisablePicking = false;\n            }\n\n            instance.m_SelectedScenes.Clear();\n\n            var hierarchyWindow = SceneHierarchyWindow.lastInteractedHierarchyWindow;\n            if (shouldDisablePicking && hierarchyWindow)\n            {\n                hierarchyWindow.GetSelectedScenes(instance.m_SelectedScenes);\n\n                foreach (var scene in instance.m_SelectedScenes)\n                {\n                    if (!instance.IsPickingDisabled(scene))\n                        break;\n\n                    shouldDisablePicking = false;\n                }\n            }\n\n            var undoName = includeChildren ? \"Toggle Selection And Descendants Picking\" : \"Toggle Selection Pickable\";\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), undoName);\n            SceneVisibilityState.SetGameObjectsPickingDisabled(Selection.gameObjects, shouldDisablePicking, includeChildren);\n\n            foreach (var scene in instance.m_SelectedScenes)\n            {\n                if (shouldDisablePicking)\n                    instance.DisablePicking(scene);\n                else\n                    instance.EnablePicking(scene);\n            }\n\n            if (hierarchyWindow)\n                EditorApplication.RepaintHierarchyWindow();\n        }\n\n\n        [Shortcut(\"Scene Visibility/Exit Isolation\")]\n        private static void ExitIsolationShortcut()\n        {\n            instance.ExitIsolation();\n        }\n\n        [Shortcut(\"Scene Visibility/Toggle Isolation On Selection And Descendants\", typeof(ShortcutContext), KeyCode.H, ShortcutModifiers.Shift)]\n        private static void ToggleIsolateSelectionAndDescendantsShortcut()\n        {\n            instance.ToggleIsolateSelectionAndDescendants();\n        }\n\n        List<Scene> m_SelectedScenes = new List<Scene>();\n\n        internal void ToggleIsolateSelectionAndDescendants()\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Toggle Isolation on Selection And Children\");\n\n            if (!IsCurrentStageIsolated())\n            {\n                IsolateCurrentStage();\n                HideAllNoUndo();\n\n                if (Selection.gameObjects.Length > 0)\n                {\n                    SceneVisibilityState.SetGameObjectsHidden(Selection.gameObjects, false, true);\n                }\n\n                m_SelectedScenes.Clear();\n                var hierarchyWindow = SceneHierarchyWindow.lastInteractedHierarchyWindow;\n                if (hierarchyWindow)\n                {\n                    hierarchyWindow.GetSelectedScenes(m_SelectedScenes);\n                    foreach (var scene in m_SelectedScenes)\n                    {\n                        Show(scene);\n                    }\n                }\n            }\n            else\n            {\n                RevertIsolationCurrentStage();\n            }\n        }\n\n        [Shortcut(\"Scene Visibility/Toggle Isolation on Selection\")]\n        internal static void ToggleIsolateSelectionShortcut()\n        {\n            instance.ToggleIsolateSelection();\n        }\n\n        internal void ToggleIsolateSelection()\n        {\n            Undo.RecordObject(SceneVisibilityState.GetInstance(), \"Toggle Isolation on Selection\");\n\n            if (!IsCurrentStageIsolated())\n            {\n                IsolateCurrentStage();\n                HideAllNoUndo();\n\n                if (Selection.gameObjects.Length > 0)\n                {\n                    SceneVisibilityState.SetGameObjectsHidden(Selection.gameObjects, false, false);\n                }\n\n                m_SelectedScenes.Clear();\n                var hierarchyWindow = SceneHierarchyWindow.lastInteractedHierarchyWindow;\n                if (hierarchyWindow)\n                {\n                    hierarchyWindow.GetSelectedScenes(m_SelectedScenes);\n                    foreach (var scene in m_SelectedScenes)\n                    {\n                        Show(scene);\n                    }\n                }\n            }\n            else\n            {\n                RevertIsolationCurrentStage();\n            }\n        }\n\n        internal void ToggleScene(Scene scene, SceneVisState visibilityState)\n        {\n            if (visibilityState == SceneVisState.AllVisible || visibilityState == SceneVisState.Mixed)\n            {\n                Hide(scene);\n            }\n            else\n            {\n                Show(scene);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SceneVisibility/SceneVisibilityState.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.SceneManagement;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.SceneManagement;\nusing UnityEngine.Scripting;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [NativeClass(null)]\n    [NativeType(Header = \"Editor/Src/SceneVisibility/SceneVisibilityState.h\")]\n    [StaticAccessor(\"GetSceneVisibilityState()\", StaticAccessorType.Dot)]\n    [ExcludeFromObjectFactory]\n    [ExcludeFromPreset]\n    internal class SceneVisibilityState : Object\n    {\n        [FreeFunction(\"GetSceneVisibilityState\")]\n        public static extern Object GetInstance();\n\n        public static extern void SetGameObjectHidden([NotNull] GameObject gameObject, bool isHidden, bool includeChildren);\n\n        public static extern void SetGameObjectsHidden([NotNull] GameObject[] gameObjects, bool isHidden, bool includeChildren);\n\n        public static extern bool IsGameObjectHidden([NotNull] GameObject gameObject);\n\n        public static extern bool IsHierarchyHidden([NotNull] GameObject gameObject);\n\n        public static extern void SetGameObjectPickingDisabled([NotNull] GameObject gameObject, bool pickingDisabled, bool includeChildren);\n\n        public static extern void SetGameObjectsPickingDisabled([NotNull] GameObject[] gameObjects, bool pickingDisabled, bool includeChildren);\n\n        public static extern bool IsGameObjectPickingDisabled([NotNull] GameObject gameObject);\n\n        public static extern bool IsHierarchyPickingDisabled([NotNull] GameObject gameObject);\n        public static extern bool AreAllChildrenVisible([NotNull] GameObject gameObject);\n        public static extern bool IsPickingEnabledOnAllChildren([NotNull] GameObject gameObject);\n\n        public static extern bool AreAllChildrenHidden([NotNull] GameObject gameObject);\n        public static extern bool AreAllRootObjectsHiddenHierarchy(Scene scene);\n        public static extern bool IsPickingDisabledOnAllChildren([NotNull] GameObject gameObject);\n        public static extern bool IsPickingDisabledOnAllDescendants(Scene scene);\n\n        public static extern void ShowScene(Scene scene);\n\n        public static extern void HideScene(Scene scene);\n\n        public static extern void EnablePicking(Scene scene);\n\n        public static extern void DisablePicking(Scene scene);\n\n        public static extern bool HasHiddenGameObjects(Scene scene);\n        public static extern bool ContainsGameObjectsWithPickingDisabled(Scene scene);\n\n        public static extern void ClearScene(Scene scene);\n\n        public static extern void OnSceneSaving(Scene scene, string scenePath);\n\n        public static extern void GeneratePersistentDataForAllLoadedScenes();\n\n        public static extern void GeneratePersistentDataForLoadedScene(Scene scene);\n\n        public static extern void OnSceneSaved(Scene scene);\n\n        public static extern int GetHiddenObjectCount();\n        public static extern int GetPickingDisabledObjectCount();\n        public static extern void ForceDataUpdate();\n        public static extern void CleanTempScenes();\n\n        public static Action internalStructureChanged;\n\n        [RequiredByNativeCode]\n        private static void Internal_InternalStructureChanged()\n        {\n            internalStructureChanged?.Invoke();\n        }\n\n        public static extern bool visibilityActive { get; set; }\n        public static extern bool pickingActive { get; set; }\n        public static extern bool isolation { get; set; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ScriptEditorUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing UnityEditor;\nusing UnityEditor.Utils;\n\nusing System;\nusing System.IO;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Linq;\n\nusing Unity.CodeEditor;\n\nnamespace UnityEditorInternal\n{\n    public class ScriptEditorUtility\n    {\n        // Keep in sync with enum ScriptEditorType in ExternalEditor.h\n        [Obsolete(\"This will be removed\", false)]\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public enum ScriptEditor\n        {\n            SystemDefault = 0,\n            MonoDevelop = 1,\n            VisualStudio = 2,\n            VisualStudioExpress = 3,\n            Other = 32\n        }\n\n        public struct Installation\n        {\n            public string Name;\n            public string Path;\n        }\n\n        static readonly List<Func<Installation[]>> k_PathCallbacks = new List<Func<Installation[]>>();\n\n        [Obsolete(\"Use UnityEditor.ScriptEditor.Register()\", true)]\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public static void RegisterIde(Func<Installation[]> pathCallBack)\n        {\n            k_PathCallbacks.Add(pathCallBack);\n        }\n\n        [Obsolete(\"This functionality is going to be removed. See IExternalCodeEditor for more information\", true)]\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public static ScriptEditor GetScriptEditorFromPath(string path)\n        {\n            string lowerCasePath = path.ToLower();\n\n            if (lowerCasePath == CodeEditor.SystemDefaultPath)\n                return ScriptEditor.SystemDefault;\n\n            return ScriptEditor.Other;\n        }\n\n        [RequiredByNativeCode]\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public static string GetExternalScriptEditor()\n        {\n            return CodeEditor.CurrentEditorPath;\n        }\n\n        [Obsolete(\"This method has been moved to CodeEditor.SetExternalScriptEditor\", true)]\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public static void SetExternalScriptEditor(string path)\n        {\n            CodeEditor.SetExternalScriptEditor(path);\n        }\n\n        [Obsolete(\"Use UnityEditor.ScriptEditor.GetCurrentEditor()\", true)]\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public static ScriptEditor GetScriptEditorFromPreferences()\n        {\n            return GetScriptEditorFromPath(CodeEditor.CurrentEditorInstallation);\n        }\n\n        [Obsolete(\"This method is being internalized, please use UnityEditorInternal.CodeEditorUtility.GetFoundScriptEditorPaths\", true)]\n        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n        public static Dictionary<string, string> GetFoundScriptEditorPaths(RuntimePlatform platform)\n        {\n            return CodeEditor.Editor.GetFoundScriptEditorPaths();\n        }\n\n        private static void AddIfDirectoryExists(string name, string path, Dictionary<string, string> list)\n        {\n            if (list.ContainsKey(path))\n                return;\n            if (Directory.Exists(path)) list.Add(path, name);\n            else if (File.Exists(path)) list.Add(path, name);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ScriptReloadProperties.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    [RequiredByNativeCode]\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct MonoReloadableIntPtr\n    {\n        internal IntPtr  m_IntPtr;\n    }\n\n    [RequiredByNativeCode]\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct MonoReloadableIntPtrClear\n    {\n        internal IntPtr  m_IntPtr;\n    }\n\n    internal sealed class ScriptReloadProperties : ScriptableObject\n    {\n        public bool EditorGUI_IsActuallEditing;\n        public bool EditorGUI_TextEditor_needBackup;\n        public int EditorGUI_TextEditor_cursorIndex;\n        public int EditorGUI_TextEditor_selectIndex;\n        public int EditorGUI_TextEditor_controlID;\n        public bool EditorGUI_TextEditor_hasHorizontalCursorPos;\n        public Vector2 EditorGUI_TextEditor_scrollOffset;\n        public bool EditorGUI_TextEditor_hasFocus;\n        public Vector2 EditorGUI_TextEditor_graphicalCursorPos;\n        public string EditorGUI_TextEditor_content;\n        public string EditorGUI_Current_Editing_String;\n        private bool EditorGUI_DelayedTextEditor_needBackup;\n        public int EditorGUI_DelayedTextEditor_cursorIndex;\n        public int EditorGUI_DelayedTextEditor_selectIndex;\n        public int EditorGUI_DelayedTextEditor_controlID;\n        public bool EditorGUI_DelayedTextEditor_hasHorizontalCursorPos;\n        public Vector2 EditorGUI_DelayedTextEditor_scrollOffset;\n        public bool EditorGUI_DelayedTextEditor_hasFocus;\n        public Vector2 EditorGUI_DelayedTextEditor_graphicalCursorPos;\n        public string EditorGUI_DelayedTextEditor_content;\n        public string EditorGUI_DelayedControlThatHadFocusValue;\n\n        [RequiredByNativeCode]\n        static ScriptReloadProperties Store()\n        {\n            ScriptReloadProperties obj = CreateInstance<ScriptReloadProperties>();\n            obj.hideFlags = HideFlags.HideAndDontSave;\n            obj.ManagedStore();\n            return obj;\n        }\n\n        [RequiredByNativeCode]\n        static void Load(ScriptReloadProperties properties)\n        {\n            properties.ManagedLoad();\n        }\n\n        private void ManagedStore()\n        {\n            EditorGUI_IsActuallEditing = EditorGUI.RecycledTextEditor.s_ActuallyEditing;\n\n            EditorGUI_TextEditor_needBackup = EditorGUI.s_RecycledEditorInternal != null;\n            if (EditorGUI_TextEditor_needBackup)\n            {\n                EditorGUI_TextEditor_cursorIndex = EditorGUI.s_RecycledEditor.cursorIndex;\n                EditorGUI_TextEditor_selectIndex = EditorGUI.s_RecycledEditor.selectIndex;\n                EditorGUI_TextEditor_controlID = EditorGUI.s_RecycledEditor.controlID;\n                EditorGUI_TextEditor_hasHorizontalCursorPos = EditorGUI.s_RecycledEditor.hasHorizontalCursor;\n                EditorGUI_TextEditor_scrollOffset = EditorGUI.s_RecycledEditor.scrollOffset;\n                EditorGUI_TextEditor_hasFocus = EditorGUI.s_RecycledEditor.m_HasFocus;\n                EditorGUI_TextEditor_graphicalCursorPos = EditorGUI.s_RecycledEditor.graphicalCursorPos;\n                EditorGUI_TextEditor_content = EditorGUI.s_RecycledEditor.text;\n            }\n            EditorGUI_Current_Editing_String = EditorGUI.s_RecycledCurrentEditingString;\n\n            EditorGUI_DelayedTextEditor_needBackup = EditorGUI.s_DelayedTextEditorInternal != null;\n            if(EditorGUI_DelayedTextEditor_needBackup)\n            {\n                EditorGUI_DelayedTextEditor_cursorIndex = EditorGUI.s_DelayedTextEditor.cursorIndex;\n                EditorGUI_DelayedTextEditor_selectIndex = EditorGUI.s_DelayedTextEditor.selectIndex;\n                EditorGUI_DelayedTextEditor_controlID = EditorGUI.s_DelayedTextEditor.controlID;\n                EditorGUI_DelayedTextEditor_hasHorizontalCursorPos = EditorGUI.s_DelayedTextEditor.hasHorizontalCursor;\n                EditorGUI_DelayedTextEditor_scrollOffset = EditorGUI.s_DelayedTextEditor.scrollOffset;\n                EditorGUI_DelayedTextEditor_hasFocus = EditorGUI.s_DelayedTextEditor.m_HasFocus;\n                EditorGUI_DelayedTextEditor_graphicalCursorPos = EditorGUI.s_DelayedTextEditor.graphicalCursorPos;\n                EditorGUI_DelayedTextEditor_content = EditorGUI.s_DelayedTextEditor.text;\n                EditorGUI_DelayedControlThatHadFocusValue = EditorGUI.s_DelayedTextEditor.controlThatHadFocusValue;\n            }\n        }\n\n        private void ManagedLoad()\n        {\n            EditorGUI.s_RecycledCurrentEditingString = EditorGUI_Current_Editing_String;\n            EditorGUI.RecycledTextEditor.s_ActuallyEditing = EditorGUI_IsActuallEditing;\n            if (EditorGUI_TextEditor_needBackup)\n            {\n                EditorGUI.s_RecycledEditor.text = EditorGUI_TextEditor_content;\n                EditorGUI.s_RecycledEditor.cursorIndex = EditorGUI_TextEditor_cursorIndex;\n                EditorGUI.s_RecycledEditor.selectIndex = EditorGUI_TextEditor_selectIndex;\n                EditorGUI.s_RecycledEditor.controlID = EditorGUI_TextEditor_controlID;\n                EditorGUI.s_RecycledEditor.hasHorizontalCursor = EditorGUI_TextEditor_hasHorizontalCursorPos;\n                EditorGUI.s_RecycledEditor.scrollOffset = EditorGUI_TextEditor_scrollOffset;\n                EditorGUI.s_RecycledEditor.m_HasFocus = EditorGUI_TextEditor_hasFocus;\n                EditorGUI.s_RecycledEditor.graphicalCursorPos = EditorGUI_TextEditor_graphicalCursorPos;\n            }\n\n            if (EditorGUI_DelayedTextEditor_needBackup)\n            {\n                EditorGUI.s_DelayedTextEditor.text = EditorGUI_DelayedTextEditor_content;\n                EditorGUI.s_DelayedTextEditor.cursorIndex = EditorGUI_DelayedTextEditor_cursorIndex;\n                EditorGUI.s_DelayedTextEditor.selectIndex = EditorGUI_DelayedTextEditor_selectIndex;\n                EditorGUI.s_DelayedTextEditor.controlID = EditorGUI_DelayedTextEditor_controlID;\n                EditorGUI.s_DelayedTextEditor.hasHorizontalCursor = EditorGUI_DelayedTextEditor_hasHorizontalCursorPos;\n                EditorGUI.s_DelayedTextEditor.scrollOffset = EditorGUI_DelayedTextEditor_scrollOffset;\n                EditorGUI.s_DelayedTextEditor.m_HasFocus = EditorGUI_DelayedTextEditor_hasFocus;\n                EditorGUI.s_DelayedTextEditor.graphicalCursorPos = EditorGUI_DelayedTextEditor_graphicalCursorPos;\n                EditorGUI.s_DelayedTextEditor.controlThatHadFocusValue = EditorGUI_DelayedControlThatHadFocusValue;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ScriptableSingleton.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing System.IO;\nusing UnityEditorInternal;\n\n\nnamespace UnityEditor\n{\n    // Use the FilePathAttribute when you want to have your scriptable singleton to persist between unity sessions.\n    // Example: [FilePathAttribute(\"Library/SearchFilters.ssf\", FilePathAttribute.Location.ProjectFolder)]\n    // Ensure to call Save() from client code (derived instance)\n    [AttributeUsage(AttributeTargets.Class)]\n    public class FilePathAttribute : Attribute\n    {\n        public enum Location { PreferencesFolder, ProjectFolder }\n\n        private string m_FilePath;\n        private string m_RelativePath;\n        private Location m_Location;\n\n        internal string filepath\n        {\n            get\n            {\n                if (m_FilePath == null && m_RelativePath != null)\n                {\n                    m_FilePath = CombineFilePath(m_RelativePath, m_Location);\n                    m_RelativePath = null;\n                }\n\n                return m_FilePath;\n            }\n        }\n\n        public FilePathAttribute(string relativePath, Location location)\n        {\n            if (string.IsNullOrEmpty(relativePath))\n            {\n                throw new ArgumentException(\"Invalid relative path (it is empty)\");\n            }\n\n            m_RelativePath = relativePath;\n            m_Location = location;\n        }\n\n        static string CombineFilePath(string relativePath, Location location)\n        {\n            // We do not want a slash as first char\n            if (relativePath[0] == '/')\n                relativePath = relativePath.Substring(1);\n\n            switch (location)\n            {\n                case Location.PreferencesFolder: return InternalEditorUtility.unityPreferencesFolder + \"/\" + relativePath;\n                case Location.ProjectFolder:     return relativePath;\n                default:\n                    Debug.LogError(\"Unhandled enum: \" + location);\n                    return relativePath; // fallback to ProjectFolder relative path\n            }\n        }\n    }\n\n    public class ScriptableSingleton<T> : ScriptableObject where T : ScriptableObject\n    {\n        static T s_Instance;\n\n        public static T instance\n        {\n            get\n            {\n                if (s_Instance == null)\n                    CreateAndLoad();\n\n                return s_Instance;\n            }\n        }\n\n        // On domain reload ScriptableObject objects gets reconstructed from a backup. We therefore set the s_Instance here\n        protected ScriptableSingleton()\n        {\n            if (s_Instance != null)\n            {\n                Debug.LogError(\"ScriptableSingleton already exists. Did you query the singleton in a constructor?\");\n            }\n            else\n            {\n                object casted = this;\n                s_Instance = casted as T;\n                System.Diagnostics.Debug.Assert(s_Instance != null);\n            }\n        }\n\n        private static void CreateAndLoad()\n        {\n            System.Diagnostics.Debug.Assert(s_Instance == null);\n\n            // Load\n            string filePath = GetFilePath();\n            if (!string.IsNullOrEmpty(filePath))\n            {\n                // If a file exists then load it and deserialize it.\n                // This creates an instance of T which will set s_Instance in the constructor. Then it will deserialize it and call relevant serialization callbacks.\n                InternalEditorUtility.LoadSerializedFileAndForget(filePath);\n            }\n\n            if (s_Instance == null)\n            {\n                // Create\n                T t = CreateInstance<T>();\n\n                // Editing should be allowed, but the user is responsible for calling Save() (case uum-40767)\n                t.hideFlags = HideFlags.HideAndDontSave & ~HideFlags.NotEditable;\n            }\n\n            System.Diagnostics.Debug.Assert(s_Instance != null);\n        }\n\n        protected virtual void Save(bool saveAsText)\n        {\n            if (s_Instance == null)\n            {\n                Debug.LogError(\"Cannot save ScriptableSingleton: no instance!\");\n                return;\n            }\n\n            string filePath = GetFilePath();\n            if (!string.IsNullOrEmpty(filePath))\n            {\n                string folderPath = Path.GetDirectoryName(filePath);\n                if (!Directory.Exists(folderPath))\n                    Directory.CreateDirectory(folderPath);\n\n                InternalEditorUtility.SaveToSerializedFileAndForget(new[] { s_Instance }, filePath, saveAsText);\n            }\n            else\n            {\n                Debug.LogWarning($\"Saving has no effect. Your class '{GetType()}' is missing the FilePathAttribute. Use this attribute to specify where to save your ScriptableSingleton.\\nOnly call Save() and use this attribute if you want your state to survive between sessions of Unity.\");\n            }\n        }\n\n        protected static string GetFilePath()\n        {\n            Type type = typeof(T);\n            object[] attributes = type.GetCustomAttributes(true);\n            foreach (object attr in attributes)\n            {\n                if (attr is FilePathAttribute)\n                {\n                    FilePathAttribute f = attr as FilePathAttribute;\n                    return f.filepath;\n                }\n            }\n            return string.Empty;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ScriptableSingletonDictionary.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing System.IO;\nusing UnityEditorInternal;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    // Use the LibraryFolderPathAttribute when you want to have your scriptable singleton dictionary\n    // to persist between unity sessions.\n    // Example: [LibraryFolderPathAttribute(\"EditorWindows\")]\n    [AttributeUsage(AttributeTargets.Class)]\n    class LibraryFolderPathAttribute : Attribute\n    {\n        public string folderPath { get; set; }\n        public LibraryFolderPathAttribute(string relativePath)\n        {\n            if (string.IsNullOrEmpty(relativePath))\n            {\n                Debug.LogError(\"Invalid relative path! (its null or empty)\");\n                return;\n            }\n\n            // We do not want a slash as first char.\n            if (relativePath[0] == '/')\n                throw new ArgumentException(\"Folder relative path cannot start with a slash.\");\n\n            folderPath = \"Library/\" + relativePath;\n        }\n    }\n\n    internal abstract class ScriptableSingletonDictionary<TDerived, TValue> : ScriptableObject\n        where TDerived : ScriptableObject\n        where TValue : ScriptableObject\n    {\n        private static TDerived s_Instance;\n        static readonly string k_Extension = \".pref\";\n\n        protected string m_PreferencesFileName;\n\n        public static TDerived instance\n        {\n            get\n            {\n                if (s_Instance == null)\n                {\n                    s_Instance = ScriptableObject.CreateInstance<TDerived>();\n                    s_Instance.hideFlags = HideFlags.HideAndDontSave;\n                }\n                return s_Instance;\n            }\n        }\n\n        public TValue this[string preferencesFileName]\n        {\n            get\n            {\n                return Load(preferencesFileName);\n            }\n        }\n\n        private TValue CreateNewValue()\n        {\n            TValue value = ScriptableObject.CreateInstance<TValue>();\n            value.hideFlags |= HideFlags.HideAndDontSave;\n            return value;\n        }\n\n        private string GetProjectRelativePath(string file)\n        {\n            return GetFolderPath() + \"/\" + file + k_Extension;\n        }\n\n        // Save() should be called whenever the user of this data store\n        // believes the data might have changed and needs to be updated\n        // in the pref file. Otherwise, Save() will only be called when\n        // switching between pref files by accessing with different keys.\n        public void Save(string preferencesFileName, TValue value)\n        {\n            const bool saveAsText = true;\n\n            Debug.Assert(preferencesFileName != null && value != null, \"Should always have valid key/values.\");\n            if (string.IsNullOrEmpty(preferencesFileName) || value == null)\n                return;\n\n            // if there is no key the object does not exist on disk,\n            // so there is no guid associated with it\n            string file = preferencesFileName;\n            if (string.IsNullOrEmpty(file))\n                return;\n\n            // make sure the path exists or file write will fail\n            string fullPath = Application.dataPath + \"/../\" + GetFolderPath();\n            if (!System.IO.Directory.Exists(fullPath))\n                System.IO.Directory.CreateDirectory(fullPath);\n\n            InternalEditorUtility.SaveToSerializedFileAndForget(new[] { value }, GetProjectRelativePath(file), saveAsText);\n        }\n\n        public void Clear(string preferencesFileName)\n        {\n            string fullPath = Application.dataPath + \"/../\" + GetProjectRelativePath(preferencesFileName);\n            if (System.IO.File.Exists(fullPath))\n                System.IO.File.Delete(fullPath);\n        }\n\n        private TValue Load(string preferencesFileName)\n        {\n            TValue value = null;\n            string file = preferencesFileName;\n            if (!string.IsNullOrEmpty(file))\n            {\n                var objects = InternalEditorUtility.LoadSerializedFileAndForget(GetProjectRelativePath(file));\n                if (objects != null && objects.Length > 0)\n                {\n                    value = objects[0] as TValue;\n                    if (value != null)\n                        value.hideFlags |= HideFlags.HideAndDontSave;\n                }\n            }\n\n            m_PreferencesFileName = preferencesFileName;\n            return value ?? CreateNewValue();\n        }\n\n        private string GetFolderPath()\n        {\n            Type type = this.GetType();\n            object[] attributes = type.GetCustomAttributes(true);\n            foreach (object attr in attributes)\n            {\n                if (attr is LibraryFolderPathAttribute)\n                {\n                    LibraryFolderPathAttribute f = attr as LibraryFolderPathAttribute;\n                    return f.folderPath;\n                }\n            }\n\n            // The folder path attribute is required.\n            throw new ArgumentException(\"The LibraryFolderPathAttribute[] attribute is required for this class.\");\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ScriptableWizard.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Reflection;\nusing UnityEngine;\nusing uei = UnityEngine.Internal;\n\nnamespace UnityEditor\n{\n    // Derive from this class to create an editor wizard.\n    [UIFramework(UIFrameworkUsage.IMGUI)]\n    public class ScriptableWizard : EditorWindow\n    {\n        GenericInspector m_Inspector;\n        string m_HelpString = \"\";\n        string m_ErrorString = \"\";\n        bool m_IsValid = true;\n        Vector2 m_ScrollPosition;\n        string m_CreateButton = \"Create\";\n        string m_OtherButton = \"\";\n\n        void OnDestroy()\n        {\n            DestroyImmediate(m_Inspector);\n        }\n\n        void InvokeWizardUpdate()\n        {\n            const BindingFlags kInstanceInvokeFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy;\n            var method = GetType().GetMethod(\"OnWizardUpdate\", kInstanceInvokeFlags);\n            if (method != null)\n                method.Invoke(this, null);\n        }\n\n        static class Styles\n        {\n            public const string errorText = \"Wizard Error\";\n        }\n\n        //@TODO: Force repaint if scripts recompile\n        void OnGUI()\n        {\n            EditorGUIUtility.labelWidth = 150;\n            GUILayout.Label(m_HelpString, EditorStyles.wordWrappedLabel, GUILayout.ExpandHeight(true));\n\n            // Render contents using Generic Inspector GUI\n            m_ScrollPosition = EditorGUILayout.BeginVerticalScrollView(m_ScrollPosition, false, GUI.skin.verticalScrollbar, \"OL Box\");\n            GUIUtility.GetControlID(645789, FocusType.Passive);\n            bool modified = DrawWizardGUI();\n            EditorGUILayout.EndScrollView();\n\n            // Create and Other Buttons\n            GUILayout.BeginVertical();\n            if (m_ErrorString != string.Empty)\n                GUILayout.Label(m_ErrorString, Styles.errorText, GUILayout.MinHeight(32));\n            else\n                GUILayout.Label(string.Empty, GUILayout.MinHeight(32));\n            GUILayout.FlexibleSpace();\n\n            GUILayout.BeginHorizontal();\n            GUILayout.FlexibleSpace();\n            GUI.enabled = m_IsValid;\n\n            const BindingFlags kInstanceInvokeFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy;\n            if (m_OtherButton != \"\" && GUILayout.Button(m_OtherButton, GUILayout.MinWidth(100)))\n            {\n                MethodInfo method = GetType().GetMethod(\"OnWizardOtherButton\", kInstanceInvokeFlags);\n                if (method != null)\n                {\n                    method.Invoke(this, null);\n                    GUIUtility.ExitGUI();\n                }\n                else\n                    Debug.LogError(\"OnWizardOtherButton has not been implemented in script\");\n            }\n\n            if (m_CreateButton != \"\" && GUILayout.Button(m_CreateButton, GUILayout.MinWidth(100)))\n            {\n                MethodInfo method = GetType().GetMethod(\"OnWizardCreate\", kInstanceInvokeFlags);\n                if (method != null)\n                    method.Invoke(this, null);\n                else\n                    Debug.LogError(\"OnWizardCreate has not been implemented in script\");\n                Close();\n                GUIUtility.ExitGUI();\n            }\n            GUI.enabled = true;\n\n            GUILayout.EndHorizontal();\n            GUILayout.EndVertical();\n            if (modified)\n                InvokeWizardUpdate();\n\n            GUILayout.Space(8);\n        }\n\n        protected virtual bool DrawWizardGUI()\n        {\n            if (m_Inspector == null)\n            {\n                m_Inspector = CreateInstance<GenericInspector>();\n                m_Inspector.hideFlags = HideFlags.HideAndDontSave;\n                m_Inspector.InternalSetTargets(new UnityEngine.Object[] {this});\n            }\n            return m_Inspector.DrawDefaultInspector();\n        }\n\n        public static T DisplayWizard<T>(string title) where T : ScriptableWizard\n        {\n            return DisplayWizard<T>(title, \"Create\", \"\");\n        }\n\n        public static T DisplayWizard<T>(string title, string createButtonName) where T : ScriptableWizard\n        {\n            return DisplayWizard<T>(title, createButtonName, \"\");\n        }\n\n        public static T DisplayWizard<T>(string title, string createButtonName, string otherButtonName) where T : ScriptableWizard\n        {\n            return (T)DisplayWizard(title, typeof(T), createButtonName, otherButtonName);\n        }\n\n        [uei.ExcludeFromDocsAttribute]\n        public static ScriptableWizard DisplayWizard(string title, Type klass, string createButtonName)\n        {\n            return DisplayWizard(title, klass, createButtonName, \"\");\n        }\n\n        [uei.ExcludeFromDocsAttribute]\n        public static ScriptableWizard DisplayWizard(string title, Type klass)\n        {\n            return DisplayWizard(title, klass, \"Create\", \"\");\n        }\n\n        public static ScriptableWizard DisplayWizard(string title, Type klass, [uei.DefaultValueAttribute(\"\\\"Create\\\"\")]  string createButtonName , [uei.DefaultValueAttribute(\"\\\"\\\"\")]  string otherButtonName)\n        {\n            var wizard = CreateInstance(klass) as ScriptableWizard;\n            if (wizard == null)\n                return null;\n            wizard.m_CreateButton = createButtonName;\n            wizard.m_OtherButton = otherButtonName;\n            wizard.titleContent = new GUIContent(title);\n            wizard.InvokeWizardUpdate();\n            wizard.ShowUtility();\n            return wizard;\n        }\n\n        // // Magic Methods\n\n        // // This is called when the wizard is opened or whenever the user changes something in the wizard.\n        // void OnWizardUpdate();\n\n        // // This is called when the user clicks on the Create button.\n        // void OnWizardCreate();\n\n        // Allows you to set the help text of the wizard.\n        public string helpString\n        {\n            get => m_HelpString;\n            set\n            {\n                var newString = value ?? string.Empty;\n                if (m_HelpString != newString)\n                {\n                    m_HelpString = newString;\n                    Repaint();\n                }\n            }\n        }\n\n        // Allows you to set the error text of the wizard.\n        public string errorString\n        {\n            get => m_ErrorString;\n            set\n            {\n                var newString = value ?? string.Empty;\n                if (m_ErrorString != newString)\n                {\n                    m_ErrorString = newString;\n                    Repaint();\n                }\n            }\n        }\n\n        // Allows you to set the create button text of the wizard.\n        public string createButtonName\n        {\n            get => m_CreateButton;\n            set\n            {\n                var newString = value ?? string.Empty;\n                if (m_CreateButton != newString)\n                {\n                    m_CreateButton = newString;\n                    Repaint();\n                }\n            }\n        }\n\n        // Allows you to set the other button text of the wizard.\n        public string otherButtonName\n        {\n            get => m_OtherButton;\n            set\n            {\n                var newString = value ?? string.Empty;\n                if (m_OtherButton != newString)\n                {\n                    m_OtherButton = newString;\n                    Repaint();\n                }\n            }\n        }\n\n        // Allows you to enable and disable the wizard create button, so that the user can not click it.\n        public bool isValid\n        {\n            get => m_IsValid;\n            set => m_IsValid = value;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/APIUpdater/APIUpdaterAssemblyHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nusing UnityEditor.Utils;\nusing UnityEngine;\n\nusing UnityEditor.Scripting.Compilers;\n\nnamespace UnityEditor.Scripting\n{\n    internal class APIUpdaterAssemblyHelper\n    {\n        // See AssemblyUpdater/Program.cs\n        internal const byte Success                       = 0x00;\n        internal const byte FirstSuccessStatus            = (1 << 3);\n        internal const byte FirstErrorStatus              = (1 << 7);\n\n\n        internal const byte ContainsUpdaterConfigurations = (1 << 3) + 2;\n        internal const byte UpdatesApplied                = (1 << 3) + 3;\n\n        internal static int Run(string arguments, string workingDir, out string stdOut, out string stdErr)\n        {\n            using var assemblyUpdaterProcess = new NetCoreProgram(AssemblyUpdaterPath(), arguments, psi =>\n            {\n                psi.CreateNoWindow = true;\n                psi.RedirectStandardError = true;\n                psi.RedirectStandardOutput = true;\n                psi.WorkingDirectory = workingDir;\n                psi.UseShellExecute = false;\n            });\n\n            assemblyUpdaterProcess.LogProcessStartInfo();\n            assemblyUpdaterProcess.Start();\n\n            assemblyUpdaterProcess.WaitForExit();\n\n            stdOut = assemblyUpdaterProcess.GetStandardOutputAsString();\n            stdErr = string.Join(\"\\r\\n\", assemblyUpdaterProcess.GetErrorOutput());\n\n            return assemblyUpdaterProcess.ExitCode;\n        }\n        \n        static string AssemblyUpdaterPath() => $\"{EditorApplication.applicationContentsPath}/Tools/Compilation/ApiUpdater/AssemblyUpdater.dll\";\n\n        internal static string ArgumentsForUpdateAssembly(string assemblyPath, string tempOutputPath, IEnumerable<string> updateConfigSourcePaths)\n        {\n            var assemblyFullPath = ResolveAssemblyPath(assemblyPath);\n            return \"update -a \"\n                + assemblyFullPath\n                + \" --output \" + CommandLineFormatter.PrepareFileName(tempOutputPath)\n                + APIVersionArgument()\n                + AssemblySearchPathArgument(updateConfigSourcePaths.Select(Path.GetDirectoryName).Distinct())\n                + ConfigurationProviderAssembliesPathArgument(updateConfigSourcePaths);\n        }\n\n        internal static string ArgumentsForCheckingForUpdaterConfigsOn(string assemblyPath)\n        {\n            var assemblyFullPath = ResolveAssemblyPath(assemblyPath);\n            return \"checkupdaterconfigs -a \" + assemblyFullPath\n                + TimeStampArgument()\n                + AssemblySearchPathArgument();\n        }\n\n        internal static bool IsError(int exitCode)\n        {\n            // See AssemblyUpdater/Program.cs\n            return (exitCode & (1 << 7)) != 0;\n        }\n\n        internal static bool IsUnknown(int exitCode)\n        {\n            // See AssemblyUpdater/Program.cs\n            return exitCode != 0\n                && (exitCode & FirstErrorStatus) == 0    // It is not an error code returned from AssemblyUpdater.exe\n                && (exitCode & FirstSuccessStatus) == 0; // It is not an success code returned from AssemblyUpdater.exe\n        }\n\n        private static string ResolveAssemblyPath(string assemblyPath)\n        {\n            return CommandLineFormatter.PrepareFileName(assemblyPath);\n        }\n\n        private static string AssemblySearchPathArgument(IEnumerable<string> configurationSourceDirectories = null)\n        {\n            var req = PackageManager.Client.List(offlineMode: true, includeIndirectDependencies: true);\n            while (!req.IsCompleted)\n                System.Threading.Thread.Sleep(10);\n\n            var packagePathsToSearchForAssemblies = new StringBuilder();\n\n            if (req.Status == PackageManager.StatusCode.Success)\n            {\n                foreach(var resolvedPackage in req.Result)\n                {\n                    packagePathsToSearchForAssemblies.Append($\"{Path.PathSeparator}+{resolvedPackage.resolvedPath.Escape(Path.PathSeparator)}\");\n                }\n            }\n            else\n            {\n                APIUpdaterLogger.WriteToFile(L10n.Tr($\"Unable to retrieve project configured packages; AssemblyUpdater may fail to resolve assemblies from packages. Status = {req.Error?.message} ({req.Error?.errorCode})\"));\n            }\n\n            var searchPath = NetStandardFinder.GetReferenceDirectory().Escape(Path.PathSeparator) + Path.PathSeparator\n                + NetStandardFinder.GetNetStandardCompatShimsDirectory().Escape(Path.PathSeparator) + Path.PathSeparator\n                + NetStandardFinder.GetDotNetFrameworkCompatShimsDirectory().Escape(Path.PathSeparator) + Path.PathSeparator\n                + \"+\" + Application.dataPath.Escape(Path.PathSeparator)\n                + packagePathsToSearchForAssemblies.ToString();\n\n            if (configurationSourceDirectories != null)\n            {\n                var searchPathFromConfigSources = configurationSourceDirectories.Aggregate(\"\", (acc, curr) =>  acc + $\"{Path.PathSeparator}+\" + curr.Escape(Path.PathSeparator));\n                searchPath += searchPathFromConfigSources;\n            }\n\n            return \" -s \\\"\" + searchPath + \"\\\"\";\n        }\n\n        private static string ConfigurationProviderAssembliesPathArgument(IEnumerable<string> updateConfigSourcePaths)\n        {\n            var paths = new StringBuilder();\n            foreach (var configSourcePath in updateConfigSourcePaths)\n            {\n                paths.AppendFormat(\" {0}\", CommandLineFormatter.PrepareFileName(configSourcePath));\n            }\n\n            return paths.ToString();\n        }\n\n        private static string APIVersionArgument()\n        {\n            return \" --api-version \" + Application.unityVersion + \" \";\n        }\n\n        private static string TimeStampArgument()\n        {\n            return \" --timestamp \" + DateTime.Now.Ticks + \" \";\n        }\n    }\n\n    internal static class StringExtensions\n    {\n        public static string Escape(this string str, char value) => str.Replace($\"{value}\", $\"\\\\{value}\");\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/APIUpdater/APIUpdaterHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Text;\nusing System.Runtime.InteropServices;\nusing Mono.Cecil;\nusing UnityEditor.PackageManager;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEditor.Utils;\nusing UnityEditor.VersionControl;\nusing UnityEngine;\nusing UnityEngine.Scripting.APIUpdating;\nusing static System.Environment;\n\nnamespace UnityEditor.Scripting\n{\n    internal static class APIUpdaterHelper\n    {\n        private static string ComputePlatformExecutableExtension() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? \".exe\" : string.Empty;\n\n        internal static readonly string PlatformExecutableExtensionWithDot = ComputePlatformExecutableExtension();\n\n        public static bool IsInPackage(this string filePath)\n        {\n            return EditorCompilationInterface.Instance.IsPathInPackageDirectory(filePath);\n        }\n\n        public static bool IsInAssetsFolder(this string filePath)\n        {\n            return filePath.StartsWith(\"Assets/\", StringComparison.InvariantCultureIgnoreCase);\n        }\n\n        internal static void HandlePackageFilePaths(string[] filePathsToUpdate)\n        {\n            var filesInPackages = new List<string>();\n            foreach (var path in filePathsToUpdate)\n            {\n                var absolutePath = Path.GetFullPath(path);\n                var virtualPath = FileUtil.GetLogicalPath(absolutePath);\n                if (!virtualPath.StartsWith(\"Packages/\"))\n                {\n                    // Not a packaged path - skip it\n                    continue;\n                }\n\n                filesInPackages.Add(virtualPath);\n\n                var fileAttributes = File.GetAttributes(absolutePath);\n                if ((fileAttributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)\n                    File.SetAttributes(absolutePath, fileAttributes & ~FileAttributes.ReadOnly);\n            }\n\n            PackageManager.ImmutableAssets.SetAssetsToBeModified(filesInPackages.ToArray());\n        }\n\n        internal static bool CheckReadOnlyFiles(string[] destRelativeFilePaths)\n        {\n            // Verify that all the files we need to copy are now writable\n            // Problems after API updating during ScriptCompilation if the files are not-writable\n            var readOnlyFiles = destRelativeFilePaths.Where(path => (File.GetAttributes(path) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly);\n            if (readOnlyFiles.Any())\n            {\n                Debug.LogErrorFormat(L10n.Tr(\"[API Updater] Files cannot be updated (files not writable): {0}\"), readOnlyFiles.Select(path => path).Aggregate((acc, curr) => acc + Environment.NewLine + \"\\t\" + curr));\n                return false;\n            }\n\n            return true;\n        }\n\n        internal static bool MakeEditable(IEnumerable<string> files)\n        {\n            // We're only interested in files that would be under VCS, i.e. project\n            // assets or local packages. Incoming paths might use backward slashes; replace with\n            // forward ones as that's what Unity/VCS functions operate on.\n            var versionedFiles = files.Select(f => f.Replace('\\\\', '/')).Where(VersionControlUtils.IsPathVersioned).ToArray();\n\n            // Fail if the asset database GUID can not be found for the input asset path.\n            var assetPath = versionedFiles.FirstOrDefault(f => string.IsNullOrEmpty(AssetDatabase.AssetPathToGUID(f)));\n            if (assetPath != null)\n            {\n                Debug.LogErrorFormat(L10n.Tr(\"[API Updater] Files cannot be updated (failed to add file to list): {0}\"), assetPath);\n                return false;\n            }\n\n            var notEditableFiles = new List<string>();\n            if (!AssetDatabase.MakeEditable(versionedFiles, null, notEditableFiles))\n            {\n                var notEditableList = notEditableFiles.Aggregate(string.Empty, (text, file) => text + $\"\\n\\t{file}\");\n                Debug.LogErrorFormat(L10n.Tr(\"[API Updater] Files cannot be updated (failed to check out): {0}\"), notEditableList);\n                return false;\n            }\n\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/APIUpdater/APIUpdaterLogger.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\n\nnamespace UnityEditor.Scripting\n{\n    internal class APIUpdaterLogger\n    {\n        public static void WriteToFile(string msg, params object[] args)\n        {\n            Console.WriteLine(\"[API Updater] {0}\", string.Format(msg, args));\n        }\n\n        public static void WriteErrorToConsole(string msg, params object[] args)\n        {\n            Debug.LogErrorFormat(msg, args);\n        }\n\n        public static void WriteInfoToConsole(string line)\n        {\n            Debug.Log(line);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/APIUpdater/APIUpdaterManager.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nusing UnityEditor;\nusing UnityEditor.Scripting;\nusing UnityEditor.Scripting.APIUpdater;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEditor.Utils;\nusing UnityEditor.VersionControl;\nusing UnityEditor.PackageManager;\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Threading;\n\nusing Mono.Cecil;\nusing System.Text;\n\nnamespace UnityEditorInternal.APIUpdating\n{\n    //TODO: ADRIANO:\n    //\n    // 1. If an error happen (in updater) during package adding/updating we may not update assemblies. We need to report to user.\n    //    Ex: PA (1.0) -> PB (1.0); Add PB, PA; Update PB (to 1.1) and introduce update config; if an error happen when processing PB (1.1)\n    //    we may not apply updates to PA.\n\n    //*undocumented*\n    [NativeHeader(\"Editor/Src/Scripting/APIUpdater/APIUpdaterManager.h\")]\n    [StaticAccessor(\"APIUpdaterManager::GetInstance()\", StaticAccessorType.Dot)]\n    internal static class APIUpdaterManager\n    {\n        [RequiredByNativeCode]\n        public static string[] GetDefinedSymbolsFor(string assemblyName)\n        {\n            return UnityEditor.Compilation.CompilationPipeline.GetDefinesFromAssemblyName(Path.GetFileNameWithoutExtension(assemblyName));\n        }\n\n        private const string k_AssemblyDependencyGraphFilePath = \"Library/APIUpdater/project-dependencies.graph\";\n\n        private static HashSet<AssemblyUpdateCandidate> s_AssembliesToUpdate;\n\n        internal static extern bool WaitForVCSServerConnection();\n        [NativeName(\"NumberOfTimesAsked\")]\n        public static extern int numberOfTimesAsked\n        {\n            get;\n            set;\n        }\n\n\n        public static extern bool DoesCommandLineIndicateAPIUpdatingShouldHappenWithoutConsent();\n        public static extern bool DoesCommandLineIndicateAPIUpdatingShouldBeDeclined();\n\n        public static extern void ResetNumberOfTimesAsked();\n\n        internal static extern bool isInProjectCreation\n        {\n            [NativeName(\"IsInProjectCreation\")]\n            get;\n        }\n\n        // Used by tests only\n        public static extern void MakeNextAPIUpdateOfferReturn(bool value);\n        public static extern void ResetNextAPIUpdateOfferReturn();\n\n        // Sets/gets a regular expression used to filter configuration sources assemblies\n        // by name.\n\n        public static extern string ConfigurationSourcesFilter { get; set; }\n\n        internal static extern bool AskForConsent(string[] assemblyPaths);\n\n        // These methods are used to persist the list of assemblies to be updated in the native side in order to preserve this list across domain reloads.\n        static extern void ResetListOfAssembliesToBeUpdateInNativeSide();\n        static extern void AddAssemblyToBeUpdatedInNativeSide(string assemblyName, string assemblyPath, string[] assemblyUpdateConfigSources);\n        static extern bool GetAndRemoveAssemblyToBeUpdatedFromNative(out string outAssemblyName, out string outAssemblyPath, List<string> outUpdateConfigSources);\n\n        [RequiredByNativeCode]\n        internal static void UpdateAssemblies()\n        {\n            var assembliesToUpdate = GetAssembliesToBeUpdated();\n            if (assembliesToUpdate.Count == 0)\n                return;\n\n            var assemblyPaths = assembliesToUpdate.Select(c => c.Path);\n            var anyAssemblyInAssetsFolder = assemblyPaths.Any(path => path.IndexOf(\"Assets/\", StringComparison.OrdinalIgnoreCase) != -1);\n\n            var sw = Stopwatch.StartNew();\n            var updatedCount = 0;\n\n            var assembliesToCheckCount = assembliesToUpdate.Count;\n            var tasks = assembliesToUpdate.Select(a => new AssemblyUpdaterUpdateTask(a)).ToArray();\n            foreach (var task in tasks)\n                ThreadPool.QueueUserWorkItem(RunAssemblyUpdaterTask, task);\n\n            var finishOk = false;\n            var waitEvents = tasks.Select(t => t.Event).ToArray();\n            var timeout = TimeSpan.FromSeconds(30);\n            if (WaitOnManyEvents(waitEvents, timeout))\n            {\n                if (!HandleAssemblyUpdaterErrors(tasks))\n                {\n                    updatedCount = ProcessSuccessfulUpdates(tasks);\n                    finishOk = updatedCount >= 0;\n                }\n            }\n            else\n            {\n                LogTimeoutError(tasks);\n            }\n\n            sw.Stop();\n            APIUpdaterLogger.WriteToFile(L10n.Tr(\"Update finished with {0} in {1} ms ({2}/{3} assembly(ies) updated).\"), finishOk ? L10n.Tr(\"success\") : L10n.Tr(\"error\"), sw.ElapsedMilliseconds, updatedCount >= 0 ? updatedCount : 0, assembliesToCheckCount);\n\n            PersistListOfAssembliesToUpdate();\n        }\n\n        internal static bool WaitOnManyEvents(IEnumerable<WaitHandle> waitEvents, TimeSpan timeout)\n        {\n            var timeBomb = DateTime.Now + timeout;\n            foreach (var batch in BatchWaitHandles(waitEvents))\n            {\n                if (!WaitHandle.WaitAll(batch, timeBomb - DateTime.Now))\n                {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        private static IEnumerable<WaitHandle[]> BatchWaitHandles(IEnumerable<WaitHandle> handles)\n        {\n            // According to documentation (https://docs.microsoft.com/en-us/dotnet/api/system.threading.waithandle.waitall?view=net-5.0#System_Threading_WaitHandle_WaitAll_System_Threading_WaitHandle___System_Int32)\n            // WaitAll accepts a maximum of 64 handles. So the max size of the returned batch will be 64\n            const int batchMaxSize = 64;\n            var currentBatch = new List<WaitHandle>(batchMaxSize);\n            foreach (var handle in handles)\n            {\n                currentBatch.Add(handle);\n                if (currentBatch.Count == batchMaxSize)\n                {\n                    yield return currentBatch.ToArray();\n                    currentBatch = new List<WaitHandle>(batchMaxSize);\n                }\n            }\n\n            if (currentBatch.Count > 0)\n            {\n                yield return currentBatch.ToArray();\n            }\n        }\n\n        /*\n         * We store this list at native side so it don't get lost at domain reloads\n         * Code should call `GetAssembliesToBeUpdated()` instead of using `assembliesToUpdate` direclty.\n         */\n        private static void PersistListOfAssembliesToUpdate()\n        {\n            ResetListOfAssembliesToBeUpdateInNativeSide();\n            foreach (var assembly in GetAssembliesToBeUpdated())\n            {\n                // no need to persist the dependency graph. See comment in RestoreFromNative() method.\n                AddAssemblyToBeUpdatedInNativeSide(assembly.Name, assembly.Path, assembly.UpdateConfigSources.ToArray());\n            }\n        }\n\n        private static HashSet<AssemblyUpdateCandidate> GetAssembliesToBeUpdated()\n        {\n            if (s_AssembliesToUpdate == null)\n            {\n                s_AssembliesToUpdate = new HashSet<AssemblyUpdateCandidate>();\n                RestoreFromNative();\n            }\n\n            return s_AssembliesToUpdate;\n        }\n\n        private static void RestoreFromNative()\n        {\n            string assemblyName;\n            string assemblyPath;\n            List<string> updateConfigSources = new List<string>();\n\n            while (GetAndRemoveAssemblyToBeUpdatedFromNative(out assemblyName, out assemblyPath, updateConfigSources))\n            {\n                s_AssembliesToUpdate.Add(new AssemblyUpdateCandidate\n                {\n                    Name = assemblyName,\n                    Path = assemblyPath,\n                    DependencyGraph = null, // No need to restore the dependency graph. It is only used during the collection phase (i.e, to figure out the list of\n                                            // potential candidates for updating which happens before this step.\n                    UpdateConfigSources = updateConfigSources\n                });\n\n                updateConfigSources = new List<string>();\n            }\n        }\n\n        private static void LogTimeoutError(AssemblyUpdaterCheckAssemblyPublishConfigsTask[] tasks, TimeSpan waitedTime)\n        {\n            var timedOut = tasks.Where(t => !t.Event.WaitOne(0));\n\n            var sb = new StringBuilder(L10n.Tr(\"Timeout while checking assemblies:\"));\n            foreach (var task in timedOut)\n            {\n                sb.AppendFormat(\"{1}{0}\", Environment.NewLine, task.Candidate.Path);\n            }\n\n            sb.AppendFormat(L10n.Tr(\"{0}Timeout: {1} ms\"), Environment.NewLine, waitedTime.Milliseconds);\n            sb.AppendFormat(L10n.Tr(\"{0}Update configurations from those assemblies may have not been applied.\"), Environment.NewLine);\n            APIUpdaterLogger.WriteErrorToConsole(sb.ToString());\n        }\n\n        private static void LogTimeoutError(AssemblyUpdaterUpdateTask[] tasks)\n        {\n            var completedSuccessfully = tasks.Where(t => t.Event.WaitOne(0)).ToArray();\n            var timedOutTasks = tasks.Where(t => !t.Event.WaitOne(0));\n\n            var sb = new StringBuilder(L10n.Tr(\"Timeout while updating assemblies:\"));\n            foreach (var updaterTask in timedOutTasks)\n            {\n                sb.AppendFormat(\"{1} (Output: {2}){0}\", Environment.NewLine, updaterTask.Candidate.Path, updaterTask.OutputPath);\n            }\n\n            ReportIgnoredAssembliesDueToPreviousErrors(sb, completedSuccessfully);\n\n            APIUpdaterLogger.WriteErrorToConsole(sb.ToString());\n        }\n\n        private static bool HandleAssemblyUpdaterErrors(IList<AssemblyUpdaterUpdateTask> allTasks)\n        {\n            var tasksWithErrors = allTasks.Where(t => APIUpdaterAssemblyHelper.IsError(t.Result) || APIUpdaterAssemblyHelper.IsUnknown(t.Result) || t.Exception != null).ToArray();\n            if (tasksWithErrors.Length == 0)\n                return false;\n\n            var sb = new StringBuilder(L10n.Tr(\"Unable to update following assemblies:\"));\n            foreach (var updaterTask in tasksWithErrors)\n            {\n                sb.Append(FormatErrorFromTask(updaterTask));\n            }\n\n            ReportIgnoredAssembliesDueToPreviousErrors(sb, allTasks.Except(tasksWithErrors).ToArray());\n\n            APIUpdaterLogger.WriteErrorToConsole(sb.ToString());\n            return true;\n        }\n\n        static string FormatErrorFromTask(AssemblyUpdaterUpdateTask updaterTask)\n        {\n            // this may happen if mono.exe (which we use to run AssemblyUpdater.exe) cannot run the executable\n            // and reports an error (for example, *file not found*)\n            var unknownStatusMessage = APIUpdaterAssemblyHelper.IsUnknown(updaterTask.Result)\n                ? L10n.Tr(\" does not match any return code from AssemblyUpdater.exe\")\n                : string.Empty;\n\n            var exceptionMessage = updaterTask.Exception != null\n                ? $\"{Environment.NewLine}\\tException: {updaterTask.Exception}\"\n                : string.Empty;\n\n            return string.Format(\"{1} (Name = {2}, Error = {3}{7}) (Output: {4}){0}{5}{0}{6}{0}{8}\",\n                Environment.NewLine,\n                updaterTask.Candidate.Path,\n                updaterTask.Candidate.Name,\n                updaterTask.Result,\n                updaterTask.OutputPath,\n                updaterTask.StdOut,\n                updaterTask.StdErr,\n                unknownStatusMessage,\n                exceptionMessage);\n        }\n\n        private static void ReportIgnoredAssembliesDueToPreviousErrors(StringBuilder sb, IList<AssemblyUpdaterUpdateTask> completedSuccessfully)\n        {\n            if (completedSuccessfully.Count == 0)\n                return;\n\n            sb.AppendFormat(L10n.Tr(\"Following assemblies were successfully updated but due to the failed ones above they were ignored (not copied to the destination folder):\"));\n            foreach (var updaterTask in completedSuccessfully)\n            {\n                sb.AppendFormat(\"{1}\\t(Result = {2}) (Output: {3}){0}{4}{0}\", Environment.NewLine, updaterTask.Candidate.Path, updaterTask.Result, updaterTask.OutputPath, updaterTask.StdOut);\n            }\n        }\n\n        private static int ProcessSuccessfulUpdates(AssemblyUpdaterUpdateTask[] tasks)\n        {\n            var assembliesToUpdate  = GetAssembliesToBeUpdated();\n\n            var noUpdatesRequiredAssemblies = tasks.Where(t => t.Result == APIUpdaterAssemblyHelper.Success); // Assemblies checked which does not requires updates.\n            if (noUpdatesRequiredAssemblies.Any())\n            {\n                APIUpdaterLogger.WriteToFile(\"Assemblies not requiring updates:\");\n                foreach (var noUpdateRequired in noUpdatesRequiredAssemblies)\n                {\n                    APIUpdaterLogger.WriteToFile($\"{noUpdateRequired.Candidate.Path}{FormattedStoutFrom(noUpdateRequired)}\");\n                }\n            }\n\n            var succeededUpdates = tasks.Where(t => t.Result == APIUpdaterAssemblyHelper.UpdatesApplied);\n            if (!succeededUpdates.Any())\n            {\n                assembliesToUpdate.Clear();\n                return 0;\n            }\n\n            var assembliesRequiringConsent = FilterOutLocalAndEmbeddedPackagesWhenAskingForConsent(assembliesToUpdate.Select(a => a.Path)).ToArray();\n            if (assembliesRequiringConsent.Length > 0 && !AskForConsent(assembliesRequiringConsent))\n            {\n                APIUpdaterLogger.WriteToFile(L10n.Tr(\"User declined to run APIUpdater\"));\n                return 0;\n            }\n\n            var updatedAssemblyPaths = succeededUpdates.Select(u => u.Candidate.Path).ToArray();\n            if (!CheckoutFromVCSIfNeeded(updatedAssemblyPaths))\n                return -1;\n\n            APIUpdaterHelper.HandlePackageFilePaths(updatedAssemblyPaths);\n            if (!APIUpdaterHelper.CheckReadOnlyFiles(updatedAssemblyPaths))\n                return 0;\n\n            foreach (var succeed in succeededUpdates)\n            {\n                APIUpdaterLogger.WriteToFile(\"{0}{1}\", Environment.NewLine, succeed.StdOut);\n                FileUtil.MoveFileIfExists(succeed.OutputPath, succeed.Candidate.Path);\n            }\n\n            assembliesToUpdate.Clear();\n            return succeededUpdates.Count();\n\n            bool CheckoutFromVCSIfNeeded(string[] assemblyPathsToCheck)\n            {\n                // Only try to connect to VCS if there are files under VCS that need to be updated\n                var assembliesInAssetsFolder = assemblyPathsToCheck.Where(path => path.IndexOf(\"Assets/\", StringComparison.OrdinalIgnoreCase) != -1).ToArray();\n                if (!assembliesInAssetsFolder.Any())\n                    return true;\n\n                if (!WaitForVCSServerConnection())\n                {\n                    return false;\n                }\n\n                var failedToCheckoutFiles = !APIUpdaterHelper.MakeEditable(assembliesInAssetsFolder);\n                if (failedToCheckoutFiles)\n                {\n                    assembliesToUpdate.Clear();\n                    return false;\n                }\n\n                return true;\n            }\n\n            IEnumerable<string> FilterOutLocalAndEmbeddedPackagesWhenAskingForConsent(IEnumerable<string> ass)\n            {\n                foreach (var path in ass.Select(path => path.Replace(\"\\\\\", \"/\"))) // package manager paths are always separated by /\n                {\n                    var packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssetPath(path);\n                    if (packageInfo == null || packageInfo.source == PackageSource.Local || packageInfo.source == PackageSource.Embedded)\n                        yield return path;\n                }\n            }\n\n            static string FormattedStoutFrom(AssemblyUpdaterUpdateTask task)\n            {\n                if (task.StdOut.Length == 0)\n                    return string.Empty;\n\n                return $\" (stdout below):{Environment.NewLine}{task.StdOut}{Environment.NewLine}\";\n            }\n        }\n\n        private static void RunAssemblyUpdaterTask(object o)\n        {\n            var task = (AssemblyUpdaterTask)o;\n\n            string stdOut = string.Empty;\n            string stdErr = string.Empty;\n\n            try\n            {\n                task.Result = APIUpdaterAssemblyHelper.Run(task.Arguments, AssemblyUpdaterTask.WorkingDirectory, out stdOut, out stdErr);\n            }\n            catch (Exception ex)\n            {\n                task.Exception = ex;\n            }\n            finally\n            {\n                task.StdErr = stdErr;\n                task.StdOut = stdOut;\n\n                task.Event.Set();\n            }\n        }\n\n        internal static bool HasPrecompiledAssembliesToUpdate()\n        {\n            return GetAssembliesToBeUpdated().Count > 0;\n        }\n\n        [RequiredByNativeCode]\n        internal static void ProcessImportedAssemblies(string[] assemblies)\n        {\n            var sw = Stopwatch.StartNew();\n\n            var depGraph = UpdateDependencyGraph(assemblies);\n            var sortedCandidatesForUpdating = FindCandidatesForUpdatingSortedByDependency(assemblies, depGraph);\n\n            var assembliesToUpdate = GetAssembliesToBeUpdated();\n\n            CollectImportedAssembliesToBeUpdated(assembliesToUpdate, sortedCandidatesForUpdating);\n            UpdatePublishUpdaterConfigStatusAndAddDependents(assembliesToUpdate, sortedCandidatesForUpdating, depGraph);\n\n            SaveDependencyGraph(depGraph, k_AssemblyDependencyGraphFilePath);\n\n            sw.Stop();\n            APIUpdaterLogger.WriteToFile(L10n.Tr(\"Processing imported assemblies took {0} ms ({1}/{2} assembly(ies)).\"), sw.ElapsedMilliseconds, assembliesToUpdate.Count, sortedCandidatesForUpdating.Count());\n\n            UpdateAssemblies();\n        }\n\n        private static void CollectImportedAssembliesToBeUpdated(HashSet<AssemblyUpdateCandidate> assembliesToUpdate, IEnumerable<AssemblyUpdateCandidate> candidatesForUpdating)\n        {\n            foreach (var importedCandidate in candidatesForUpdating)\n            {\n                if (importedCandidate.MayRequireUpdating)\n                    assembliesToUpdate.Add(importedCandidate);\n            }\n        }\n\n        private static void UpdatePublishUpdaterConfigStatusAndAddDependents(HashSet<AssemblyUpdateCandidate> assembliesToUpdate, IEnumerable<AssemblyUpdateCandidate> candidatesForUpdating, AssemblyDependencyGraph depGraph)\n        {\n            var tasks = candidatesForUpdating\n                .Where(a => AssemblyHelper.IsManagedAssembly(a.Path) && IsAssemblyInPackageFolder(a))\n                .Select(a => new AssemblyUpdaterCheckAssemblyPublishConfigsTask(a)).ToArray();\n\n            if (tasks.Length == 0)\n                return;\n\n            foreach (var task in tasks)\n            {\n                ThreadPool.QueueUserWorkItem(RunAssemblyUpdaterTask, task);\n            }\n\n            var waitEvents = tasks.Select(t => t.Event).ToArray();\n            var timeout = TimeSpan.FromSeconds(30);\n            if (!WaitHandle.WaitAll(waitEvents, timeout))\n            {\n                LogTimeoutError(tasks, timeout);\n            }\n\n            var nonTimedOutTasks = tasks.Where(t => t.Event.WaitOne(0)).ToArray();\n            if (HandleCheckAssemblyPublishUpdaterConfigErrors(nonTimedOutTasks))\n                return;\n\n            foreach (var task in nonTimedOutTasks)\n            {\n                if ((task.Result & APIUpdaterAssemblyHelper.ContainsUpdaterConfigurations) == APIUpdaterAssemblyHelper.ContainsUpdaterConfigurations)\n                {\n                    var importedCandidate = task.Candidate;\n\n                    importedCandidate.DependencyGraph.Status |= AssemblyStatus.PublishesUpdaterConfigurations;\n                    AddDependentAssembliesToUpdateList(assembliesToUpdate, depGraph, importedCandidate);\n                }\n            }\n        }\n\n        private static bool HandleCheckAssemblyPublishUpdaterConfigErrors(AssemblyUpdaterCheckAssemblyPublishConfigsTask[] nonTimedOutTasks)\n        {\n            var withErrors = nonTimedOutTasks.Where(t => APIUpdaterAssemblyHelper.IsError(t.Result) || t.Exception != null).ToArray();\n            if (withErrors.Length == 0)\n                return false;\n\n            var sb = new StringBuilder(L10n.Tr(\"Failed to check following assemblies for updater configurations:\\r\\n\"));\n            foreach (var failedAssemblyInfo in withErrors)\n            {\n                sb.AppendFormat(L10n.Tr(\"{0} (ret = {1}):\\r\\n{2}{3}{4}\"), failedAssemblyInfo.Candidate.Path, failedAssemblyInfo.Result, HumanMessage(\"StdOut\", failedAssemblyInfo.StdOut), HumanMessage(\"StdErr\", failedAssemblyInfo.StdErr), HumanMessage(\"Exception\", failedAssemblyInfo.Exception?.ToString()));\n            }\n            sb.Append(\"\\r\\n--------------\");\n\n            APIUpdaterLogger.WriteErrorToConsole(sb.ToString());\n\n            return true;\n        }\n\n        private static string HumanMessage(string header, string msg)\n        {\n            if (string.IsNullOrEmpty(msg))\n                return string.Empty;\n\n            return $\"{header}:\\r\\n{msg}\\r\\n\";\n        }\n\n        private static void AddDependentAssembliesToUpdateList(HashSet<AssemblyUpdateCandidate> assembliesToUpdate, AssemblyDependencyGraph depGraph, AssemblyUpdateCandidate imported)\n        {\n            var dependents = depGraph.GetDependentsOf(imported.Name);\n            var candidatesToUpdate = dependents.Select(assemblyName => CandidateForUpdatingFrom(assemblyName, depGraph));\n\n            foreach (var candidate in candidatesToUpdate.Where(c => c != null))\n                assembliesToUpdate.Add(candidate);\n        }\n\n        private static bool IsAssemblyInPackageFolder(AssemblyUpdateCandidate candidate)\n        {\n            return candidate.Path.IsInPackage();\n        }\n\n        /*\n         * Given a list of assemblies, returns those that references assemblies contributing updater configurations\n         * sorted by dependency (i.e, given assemblies, A, B & C such A -> B -> C, should return in C, B, A order)\n         */\n        private static IEnumerable<AssemblyUpdateCandidate> FindCandidatesForUpdatingSortedByDependency(IEnumerable<string> assemblyPaths, AssemblyDependencyGraph depGraph)\n        {\n            var candidates = new HashSet<AssemblyUpdateCandidate>();\n            foreach (var assemblyPath in assemblyPaths)\n            {\n                var assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);\n\n                var depInfo = depGraph.FindAssembly(assemblyName);\n                Debug.Assert(depInfo != null);\n\n                // Any referenced assemblies contains updater configs?\n                var referencedAssembliesWithUpdaterConfigs = depInfo.Dependencies.Where(a => (depGraph.FindAssembly(a.Name)?.Status & AssemblyStatus.PublishesUpdaterConfigurations) == AssemblyStatus.PublishesUpdaterConfigurations);\n                if (referencedAssembliesWithUpdaterConfigs.Any())\n                {\n                    IEnumerable<string> updateConfigSources = ResolvePathOfAssembliesWithUpdaterConfigurations(referencedAssembliesWithUpdaterConfigs);\n                    candidates.Add(new AssemblyUpdateCandidate\n                    {\n                        Name = assemblyName,\n                        Path = assemblyPath,\n                        DependencyGraph = depInfo,\n                        UpdateConfigSources = updateConfigSources\n                    });\n                }\n            }\n\n            // add the candidates sorted based on the dependency graph...\n            var result = new List<AssemblyUpdateCandidate>();\n            foreach (var assemblyName in depGraph.SortedDependents())\n            {\n                // We may have assemblies with the same name in different folders\n                // (for example GUISystem/Standalone/UnityEngine.UI.dll & GUISystem/UnityEngine.UI.dll)\n                var filteredCandidates = candidates.Where(c => CompareIgnoreCase(c.Name, assemblyName));\n                result.AddRange(filteredCandidates);\n            }\n\n            return result;\n        }\n\n        // We only resolve Unity assemblies and assemblies coming from packages.\n        // We may want to change this to support *any assembly* to contribute with updater configurations\n        private static IEnumerable<string> ResolvePathOfAssembliesWithUpdaterConfigurations(IEnumerable<AssemblyDependencyGraph.DependencyEntry> assemblies)\n        {\n            foreach (var assemblyName in assemblies)\n            {\n                var resolved = ResolveAssemblyPath(assemblyName.Name);\n                if (resolved != null)\n                    yield return Path.GetFullPath(resolved);\n            }\n        }\n\n        private static string ResolveAssemblyPath(string assemblyName)\n        {\n            //find the assembly in Data/Managed or Data/Managed/UnityEngine\n            var assemblyFileName = assemblyName + \".dll\";\n            var managedPath = GetUnityEditorManagedPath();\n            var pathInManagedFolder = Path.Combine(managedPath, assemblyFileName);\n            if (File.Exists(pathInManagedFolder))\n                return pathInManagedFolder;\n\n            var pathInUnityEngineFolder = Path.Combine(Path.Combine(managedPath, \"UnityEngine\"), assemblyFileName);\n            if (File.Exists(pathInUnityEngineFolder))\n                return pathInUnityEngineFolder;\n\n            var assetsAssemblies = new HashSet<string>(AssetDatabase.GetAllAssetPaths().Where(assetPath => Path.GetExtension(assetPath) == \".dll\").ToArray());\n\n            // If the same assembly exist in multiple folders, choose the shortest path one.\n            var resolvedList = assetsAssemblies.Where(a => CompareIgnoreCase(AssemblyNameFromPath(a), assemblyName)).ToArray();\n            var assemblyPathInAssetsFolder = resolvedList.OrderBy(path => path.Length).FirstOrDefault();\n            if (resolvedList.Length > 1)\n            {\n                APIUpdaterLogger.WriteToFile(L10n.Tr(\"Warning : Multiple matches found for assembly name '{0}'. Shortest path one ({1}) chosen as the source of updates. Full list: {2}\"), assemblyName, assemblyPathInAssetsFolder, string.Join(Environment.NewLine, resolvedList));\n            }\n\n            if (assemblyPathInAssetsFolder != null && (assemblyPathInAssetsFolder.IsInPackage() || assemblyPathInAssetsFolder.IsInAssetsFolder()))\n            {\n                return assemblyPathInAssetsFolder;\n            }\n\n            return null;\n        }\n\n        private static bool CompareIgnoreCase(string lhs, string rhs)\n        {\n            return string.Compare(lhs, rhs, StringComparison.InvariantCultureIgnoreCase) == 0;\n        }\n\n        private static AssemblyUpdateCandidate CandidateForUpdatingFrom(string candidateAssemblyName, AssemblyDependencyGraph rootDepGraph)\n        {\n            string resolvedAssemblyPath = ResolveAssemblyPath(candidateAssemblyName);\n\n            // this may happen if, for instance, after setting the dependency A -> B, *B* gets removed and *A* gets updated to a new version (we don't remove\n            // the dependency from the graph.\n            if (string.IsNullOrEmpty(resolvedAssemblyPath))\n                return null;\n\n            var depGraph = rootDepGraph.FindAssembly(candidateAssemblyName);\n            var referencesAssemblyWithUpdaterConfigs = depGraph.Dependencies.Where(depAssembly => (rootDepGraph.FindAssembly(depAssembly.Name)?.Status & AssemblyStatus.PublishesUpdaterConfigurations) == AssemblyStatus.PublishesUpdaterConfigurations);\n            var updaterConfigSources = ResolvePathOfAssembliesWithUpdaterConfigurations(referencesAssemblyWithUpdaterConfigs);\n\n            return new AssemblyUpdateCandidate\n            {\n                Name = candidateAssemblyName,\n                Path = resolvedAssemblyPath,\n                DependencyGraph = depGraph,\n                UpdateConfigSources = updaterConfigSources\n            };\n        }\n\n        private static AssemblyDependencyGraph UpdateDependencyGraph(IEnumerable<string> addedAssemblyPaths)\n        {\n            var dependencyGraph = ReadOrCreateAssemblyDependencyGraph(k_AssemblyDependencyGraphFilePath);\n            foreach (var addedAssemblyPath in addedAssemblyPaths)\n            {\n                var assemblyDependencies = AssemblyDependenciesFrom(addedAssemblyPath);\n                dependencyGraph.SetDependencies(AssemblyNameFromPath(addedAssemblyPath), assemblyDependencies);\n\n                FixUnityAssembliesStatusInDependencyGraph(dependencyGraph, assemblyDependencies);\n            }\n\n            SaveDependencyGraph(dependencyGraph, k_AssemblyDependencyGraphFilePath);\n\n            return dependencyGraph;\n        }\n\n        private static void FixUnityAssembliesStatusInDependencyGraph(AssemblyDependencyGraph dependencyGraph, IEnumerable<string> assemblyNames)\n        {\n            var unityAssemblies = assemblyNames.Where(an => an.StartsWith(\"UnityEngine\") || an.StartsWith(\"UnityEditor\"));\n            foreach (var assemblyName in unityAssemblies)\n            {\n                var dep = dependencyGraph.FindAssembly(assemblyName);\n                dep.Status |= AssemblyStatus.PublishesUpdaterConfigurations; // we know that those assemblies contains update configs\n            }\n        }\n\n        private static string[] AssemblyDependenciesFrom(string assemblyPath)\n        {\n            using (var a = AssemblyDefinition.ReadAssembly(assemblyPath, new ReaderParameters { ReadSymbols = false }))\n            {\n                return a.MainModule.AssemblyReferences.Select(assemblyReference => assemblyReference.Name).ToArray();\n            }\n        }\n\n        private static void SaveDependencyGraph(AssemblyDependencyGraph dependencyGraph, string path)\n        {\n            try\n            {\n                var targetDir = Path.GetDirectoryName(path);\n                if (!Directory.Exists(targetDir))\n                {\n                    Directory.CreateDirectory(targetDir);\n                }\n\n                using (var file = File.Open(path, System.IO.FileMode.Create))\n                {\n                    dependencyGraph.SaveTo(file);\n                }\n            }\n            catch (UnauthorizedAccessException ex)\n            {\n                APIUpdaterLogger.WriteToFile(string.Format(L10n.Tr(\"Failed to save assembly dependency graph ({0}). Exception: {1}\")), path, ex);\n            }\n            catch (IOException ex)\n            {\n                APIUpdaterLogger.WriteToFile(string.Format(L10n.Tr(\"Failed to save assembly dependency graph ({0}). Exception: {1}\")), path, ex);\n            }\n        }\n\n        private static AssemblyDependencyGraph ReadOrCreateAssemblyDependencyGraph(string assemblyDependencyGraphFilePath)\n        {\n            try\n            {\n                if (File.Exists(assemblyDependencyGraphFilePath))\n                {\n                    using (var stream = File.OpenRead(assemblyDependencyGraphFilePath))\n                    {\n                        return AssemblyDependencyGraph.LoadFrom(stream);\n                    }\n                }\n            }\n            catch (IOException e)\n            {\n                APIUpdaterLogger.WriteToFile(string.Format(L10n.Tr(\"Failed to read assembly dependency graph ({0}). Exception: {1}\")), assemblyDependencyGraphFilePath, e);\n            }\n\n            return new AssemblyDependencyGraph();\n        }\n\n        private static string AssemblyNameFromPath(string assemblyPath)\n        {\n            return Path.GetFileNameWithoutExtension(assemblyPath);\n        }\n\n        private static string GetUnityEditorManagedPath()\n        {\n            return Path.Combine(MonoInstallationFinder.GetFrameWorksFolder(), \"Managed\");\n        }\n    }\n\n    internal class AssemblyUpdateCandidate : IEquatable<AssemblyUpdateCandidate>\n    {\n        public string Name;\n        public string Path;\n        public AssemblyDependencyGraph.DependencyEntry DependencyGraph;\n        public IEnumerable<string> UpdateConfigSources;\n\n        public bool MayRequireUpdating\n        {\n            get { return UpdateConfigSources.Any(); }\n        }\n\n        public static implicit operator bool(AssemblyUpdateCandidate a)\n        {\n            return a.Name != null;\n        }\n\n        public override string ToString()\n        {\n            return string.Format(\"{0} ({1})\", Name, Path);\n        }\n\n        public override int GetHashCode()\n        {\n            return Path.GetHashCode() * 37 + Name.GetHashCode();\n        }\n\n        public override bool Equals(object obj)\n        {\n            var other = obj as AssemblyUpdateCandidate;\n            if (other == null)\n                return false;\n\n            return Equals(other);\n        }\n\n        public bool Equals(AssemblyUpdateCandidate other)\n        {\n            return other.Name == Name && other.Path == Path;\n        }\n    }\n\n    internal class AssemblyUpdaterTask\n    {\n        private AssemblyUpdateCandidate _candidate;\n\n        public string StdOut { set; get; }\n        public string StdErr { set; get; }\n\n        static AssemblyUpdaterTask()\n        {\n            WorkingDirectory = UnityEngine.Application.dataPath + \"/..\"; // We can't access this property in a \"non main thread\" so we resolve and cache it in the main thread.\n        }\n\n        public AssemblyUpdaterTask(AssemblyUpdateCandidate a)\n        {\n            _candidate = a;\n\n            Event = new ManualResetEvent(false);\n        }\n\n        public string Arguments { get; internal set; }\n\n        public EventWaitHandle Event\n        {\n            get; internal set;\n        }\n\n        public int Result { get; internal set; }\n\n        public AssemblyUpdateCandidate Candidate { get { return _candidate; } }\n        public Exception Exception { get; internal set; }\n\n        public static string WorkingDirectory { get; internal set; }\n    }\n\n    internal class AssemblyUpdaterUpdateTask : AssemblyUpdaterTask\n    {\n        public AssemblyUpdaterUpdateTask(AssemblyUpdateCandidate a) : base(a)\n        {\n            OutputPath = Path.GetTempFileName();\n            Arguments = APIUpdaterAssemblyHelper.ArgumentsForUpdateAssembly(a.Path, OutputPath, a.UpdateConfigSources);\n        }\n\n        public string OutputPath { get; internal set; }\n    }\n\n    internal class AssemblyUpdaterCheckAssemblyPublishConfigsTask : AssemblyUpdaterTask\n    {\n        public AssemblyUpdaterCheckAssemblyPublishConfigsTask(AssemblyUpdateCandidate a) : base(a)\n        {\n            Arguments = APIUpdaterAssemblyHelper.ArgumentsForCheckingForUpdaterConfigsOn(a.Path);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/APIUpdater/AssemblyDependencyGraph.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.Serialization.Formatters.Binary;\nusing System.Security.Cryptography;\n\nnamespace UnityEditor.Scripting.APIUpdater\n{\n    [Serializable]\n    internal class AssemblyDependencyGraph\n    {\n        public AssemblyDependencyGraph()\n        {\n            m_Graph = new List<DependencyEntry>();\n        }\n\n        public void AddDependencies(string root, params string[] dependencies)\n        {\n            InternalAddDependencies(root, dependencies);\n        }\n\n        public void SetDependencies(string root, params string[] dependencies)\n        {\n            var dep = FindAssembly(root);\n            if (dep == null)\n            {\n                dep = FindInDependents(root);\n            }\n\n            if (dep != null)\n            {\n                dep.Dependencies.Clear();\n            }\n\n            InternalAddDependencies(root, dependencies);\n        }\n\n        private DependencyEntry InternalAddDependencies(string root, params string[] dependencies)\n        {\n            var existingDependency = FindAssembly(root);\n            if (existingDependency == null)\n            {\n                existingDependency =  FindInDependents(root) ?? new DependencyEntry(root);\n                m_Graph.Add(existingDependency);\n            }\n\n            foreach (var dependency in dependencies)\n            {\n                var dep = FindAssembly(dependency) ?? InternalAddDependencies(dependency);\n                existingDependency.m_Dependencies.Add(dep);\n            }\n\n            return existingDependency;\n        }\n\n        private DependencyEntry FindInDependents(string root)\n        {\n            foreach (var entry in m_Graph)\n            {\n                var found = entry.m_Dependencies.FirstOrDefault(dependency => dependency.m_Name == root);\n                if (found != null)\n                    return found;\n            }\n\n            return null;\n        }\n\n        public IList<string> GetDependentsOf(string source)\n        {\n            var result = new List<string>();\n            foreach (var dependencyEntry in m_Graph)\n            {\n                if (dependencyEntry.m_Dependencies.Any(candidate => candidate.m_Name == source))\n                    result.Add(dependencyEntry.m_Name);\n            }\n\n            return result;\n        }\n\n        public IEnumerable<string> DependenciesFor(string dependent)\n        {\n            var found = FindAssembly(dependent);\n            if (found != null)\n            {\n                return found.m_Dependencies.Select(dep => dep.m_Name);\n            }\n\n            return new string[0];\n        }\n\n        public void RemoveDependencies(string dependent, params string[] dependencies)\n        {\n            if (dependencies.Length == 0)\n                return;\n\n            var entry = FindAssembly(dependent);\n            if (entry == null)\n                return;\n\n            entry.m_Dependencies.RemoveAll(candidate => dependencies.Contains(candidate.m_Name));\n        }\n\n        public void RemoveRoot(string tbr, bool updateDependents = false)\n        {\n            var toBeRemoved = m_Graph.Find(e => e.m_Name == tbr);\n            if (toBeRemoved == null)\n                return;\n\n            m_Graph.Remove(toBeRemoved);\n\n            if (updateDependents)\n            {\n                foreach (var entry in m_Graph)\n                {\n                    var danglingReference = entry.m_Dependencies.Find(e => e == toBeRemoved);\n                    if (danglingReference == null)\n                        continue;\n\n                    entry.m_Dependencies.Remove(danglingReference);\n                }\n            }\n        }\n\n        public IEnumerable<string> SortedDependents()\n        {\n            if (m_Graph.Count == 0)\n                return new string[0];\n\n            var array = m_Graph.ToArray();\n\n            m_Processed = new HashSet<string>();\n            LogCycles(array, m_Processed);\n\n            m_Processed.Clear();\n\n            bool exchangeElementsInLastPass;\n            var arrayLength = array.Length - 1;\n            do\n            {\n                exchangeElementsInLastPass = false;\n                for (int i = 0; i < arrayLength; i++)\n                {\n                    if (CompareElements(array[i], array[i + 1]) > 0)\n                    {\n                        var temp = array[i];\n                        array[i] = array[i + 1];\n                        array[i + 1] = temp;\n\n                        exchangeElementsInLastPass = true;\n                    }\n                }\n\n                arrayLength--;\n            }\n            while (exchangeElementsInLastPass);\n\n            return array.Select(e => e.m_Name);\n        }\n\n        /*\n         * Given two nodes (A & B ) in the graph\n         * A > B if A -> B (direct or indirect)\n         * A < B if B -> A (direct or indirect)\n         */\n        private int CompareElements(DependencyEntry lhs, DependencyEntry rhs)\n        {\n            var lhsDependsOnRhs = HasDirectOrIndirectDependency(lhs, rhs);\n            if (lhsDependsOnRhs)\n                return 1;\n\n            var rshDependsOnLhs = HasDirectOrIndirectDependency(rhs, lhs);\n            if (rshDependsOnLhs)\n                return -1;\n\n            return 0;\n        }\n\n        private bool HasDirectOrIndirectDependency(DependencyEntry lhs, DependencyEntry rhs)\n        {\n            var lhsDependsOnRhs = lhs.m_Dependencies.Contains(rhs);\n            if (lhsDependsOnRhs)\n                return true;\n\n            m_Processed.Clear();\n            return HasDirectOrIndirectDependencyRecursive(rhs, lhs.m_Dependencies);\n        }\n\n        bool HasDirectOrIndirectDependencyRecursive(DependencyEntry toBeLookedUp, IList<DependencyEntry> dependencies)\n        {\n            foreach (var entry in dependencies)\n            {\n                if (entry == toBeLookedUp)\n                    return true;\n\n                if (m_Processed.Contains(entry.Name))\n                {\n                    // We've found a cycle in the assemblies (which has already been logged)\n                    return false;\n                }\n\n                m_Processed.Add(entry.Name);\n                try\n                {\n                    if (HasDirectOrIndirectDependencyRecursive(toBeLookedUp, entry.m_Dependencies))\n                        return true;\n                }\n                finally\n                {\n                    m_Processed.Remove(entry.Name);\n                }\n            }\n\n            return false;\n        }\n\n        static void LogCycles(IEnumerable<DependencyEntry> entries, HashSet<string> seen)\n        {\n            foreach (var entry in entries)\n            {\n                if ((entry.Status & AssemblyStatus.NoCyclesDetected) == AssemblyStatus.NoCyclesDetected)\n                    continue;\n\n                if (seen.Contains(entry.Name))\n                {\n                    Console.WriteLine($\"[APIUpdater] Warning: Cycle detected in assembly references: {string.Join(\"->\", seen.ToArray())}->{entry.Name}. This is not supported and AssemblyUpdater may not work as expected.\");\n                    continue;\n                }\n\n                seen.Add(entry.Name);\n\n                LogCycles(entry.Dependencies, seen);\n                entry.Status |= AssemblyStatus.NoCyclesDetected;\n\n                seen.Remove(entry.Name);\n            }\n        }\n\n        /// <summary>\n        /// Serialized format:\n        ///\n        /// +---------------+------------------+-----------------------------+\n        /// |   Hash Length | Hash of Payload  | Payload (serialized data)   |\n        /// +---------------+------------------+-----------------------------+\n        /// </summary>\n        public void SaveTo(Stream stream)\n        {\n            var hasher = SHA256.Create();\n            var hash = hasher.ComputeHash(BitConverter.GetBytes(42));\n\n            long hashLength = hash.Length;\n            var h = BitConverter.GetBytes(hashLength);\n\n            stream.Write(h, 0, h.Length); // Write the hash length\n            stream.Write(hash, 0, hash.Length); // and reserve space of the \"payload\" hash.\n\n            var formatter = new BinaryFormatter();\n#pragma warning disable SYSLIB0011\n            formatter.Serialize(stream, this);\n#pragma warning restore SYSLIB0011\n\n            var endOfStream = stream.Position;\n\n            stream.Position = hash.Length + h.Length; // Position the stream in the first byte of the serialized data (i.e, skip *hash length* and *hash*\n            hash = hasher.ComputeHash(stream);\n\n            stream.Position = h.Length; // position the stream past the *hash length* (i.e, *hash first byte*)\n            stream.Write(hash, 0, hash.Length);\n\n            stream.Position = endOfStream;\n        }\n\n        public static AssemblyDependencyGraph LoadFrom(Stream stream)\n        {\n            var hashLengthArray = new byte[sizeof(long)];\n            stream.Read(hashLengthArray, 0, hashLengthArray.Length);\n\n            long hashLengthSize = BitConverter.ToInt64(hashLengthArray, 0);\n            var storedHash = new byte[hashLengthSize];\n            stream.Read(storedHash, 0, storedHash.Length);\n\n            var startOfSerializedData = stream.Position;\n            var hasher = SHA256.Create();\n            var computedHash = hasher.ComputeHash(stream);\n\n            if (storedHash.Length != computedHash.Length)\n            {\n                return null;\n            }\n\n            for (int i = 0; i < hashLengthSize; i++)\n            {\n                if (storedHash[i] != computedHash[i])\n                {\n                    return null;\n                }\n            }\n\n            stream.Position = startOfSerializedData;\n\n            var serializer = new BinaryFormatter();\n#pragma warning disable SYSLIB0011\n            return (AssemblyDependencyGraph)serializer.Deserialize(stream);\n#pragma warning restore SYSLIB0011\n        }\n\n        internal DependencyEntry FindAssembly(string dependent)\n        {\n            return m_Graph.Find(e => e.m_Name == dependent);\n        }\n\n        [Serializable]\n        internal class DependencyEntry : IComparable<DependencyEntry>\n        {\n            public string m_Name;\n            public List<DependencyEntry> m_Dependencies;\n\n            public DependencyEntry()\n            {\n            }\n\n            public DependencyEntry(string root)\n            {\n                m_Name = root;\n                m_Dependencies = new List<DependencyEntry>();\n            }\n\n            public AssemblyStatus Status { get; set; }\n\n            public string Name => m_Name;\n\n            public int CompareTo(DependencyEntry other)\n            {\n                return string.Compare(m_Name, other.m_Name, StringComparison.Ordinal);\n            }\n\n            public List<DependencyEntry> Dependencies\n            {\n                get { return m_Dependencies; }\n            }\n\n            public override string ToString()\n            {\n                return string.Format(\"{0} ({1})\", m_Name, m_Dependencies.Count);\n            }\n        }\n\n        List<DependencyEntry> m_Graph;\n        HashSet<string> m_Processed; // used to ignore cycles.\n    }\n\n    [Flags]\n    internal enum AssemblyStatus\n    {\n        None = 0x0,\n        PublishesUpdaterConfigurations = 0x02,\n        NoCyclesDetected = 0x04\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/AsyncInstantiateManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Threading;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [InitializeOnLoad]\n    static class AsyncInstantiateManager\n    {\n        static AsyncInstantiateManager()\n        {\n            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;\n        }\n\n        static void OnPlayModeStateChanged(PlayModeStateChange stateChange)\n        {\n            // Pending operations can only leak from playmode to editmode.\n            // Editmode executes AsyncInstantiate synchronously.\n            if (stateChange == PlayModeStateChange.EnteredPlayMode\n                || stateChange == PlayModeStateChange.EnteredEditMode\n                || stateChange == PlayModeStateChange.ExitingEditMode)\n                return;\n\n            CancelPendingOperations();\n        }\n\n        static void CancelPendingOperations()\n        {\n            AsyncInstantiateOperation.s_GlobalCancellation.Cancel();\n\n            // Ensure new token when no domain reload happens\n            AsyncInstantiateOperation.s_GlobalCancellation = new CancellationTokenSource();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/Compilers/CommandLineFormatter.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing UnityEngine;\n\nnamespace UnityEditor.Scripting.Compilers\n{\n    static class CommandLineFormatter\n    {\n        private static readonly Regex Quotes  = new Regex(\"\\\"\", RegexOptions.Compiled);\n\n        public static string EscapeCharsQuote(string input)\n        {\n            if (input.IndexOf('\"') == -1)\n                return \"\\\"\" + input + \"\\\"\";\n            if (input.IndexOf('\\'') == -1)\n                return \"'\" + input + \"'\";\n            return null;\n        }\n\n        public static string PrepareFileName(string input)\n        {\n            input = FileUtil.GetPhysicalPath(input);\n            if (Application.platform == RuntimePlatform.WindowsEditor)\n                return EscapeCharsWindows(input);\n            return EscapeCharsQuote(input);\n        }\n\n        public static string EscapeCharsWindows(string input)\n        {\n            if (input.Length == 0)\n                return \"\\\"\\\"\";\n            foreach (var c in input.ToCharArray())\n            {\n                if (c >= 0x00\n                    && (c <= 0x08 || c >= 0x10)\n                    && (c <= 0x1a || c >= 0x1c)\n                    && (c <= 0x1f || c == 0x7f || c == 0xff))\n                {\n                    Debug.LogWarning(\"Cannot escape control characters in string\");\n                    return \"\\\"\\\"\";\n                }\n\n                if (!char.IsLetterOrDigit(c)\n                    && (c != '_' || c != '-' || c != '.' || c != ':' || c != ',' || c != '/' || c != '@' || c != '\\\\'))\n                {\n                    return \"\\\"\" + Quotes.Replace(input, \"\\\"\\\"\") + \"\\\"\";\n                }\n            }\n            return input;\n        }\n\n        internal static string GenerateResponseFile(IEnumerable<string> arguments)\n        {\n            string tempFile = FileUtil.GetUniqueTempPathInProject();\n            File.WriteAllLines(tempFile, arguments.Where(a => a != null).ToArray());\n            return tempFile;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/Compilers/CompilerBase.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing Unity.CompilationPipeline.Common;\nusing UnityEngine;\n\nnamespace UnityEditor.Scripting.Compilers\n{\n    internal abstract class CompilerBase : IDisposable\n    {\n        public abstract string Version { get; }\n\n        public abstract void Dispose();\n        public abstract void WaitForCompilationToFinish();\n        public abstract void BeginCompiling(AssemblyInfo assemblyInfo, string[] responseFiles, OperatingSystemFamily operatingSystemFamily, string[] systemReferenceDirectories);\n        public abstract bool Poll();\n        public abstract UnityEditor.Compilation.CompilerMessage[] GetCompilerMessages();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/Compilers/CompilerOutputParserBase.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Text.RegularExpressions;\n\nnamespace UnityEditor.Scripting.Compilers\n{\n    internal abstract class CompilerOutputParserBase\n    {\n        protected static CompilerMessage CreateInternalCompilerErrorMessage(string[] compileroutput)\n        {\n            return new CompilerMessage\n            {\n                file = \"\",\n                message = String.Join(Environment.NewLine, compileroutput),\n                type = CompilerMessageType.Error,\n                line = 0,\n                column = 0,\n            };\n        }\n\n        protected internal static CompilerMessage CreateCompilerMessageFromMatchedRegex(string line, Match m, string errorId, string informationId = null)\n        {\n            CompilerMessage message = new CompilerMessage();\n\n            if (m.Groups[\"filename\"].Success)\n            {\n                message.file = m.Groups[\"filename\"].Value;\n            }\n\n            if (m.Groups[\"line\"].Success)\n            {\n                message.line = Int32.Parse(m.Groups[\"line\"].Value);\n            }\n            if (m.Groups[\"column\"].Success)\n            {\n                message.column = Int32.Parse(m.Groups[\"column\"].Value);\n            }\n\n            message.message = line;\n\n            string messageType = m.Groups[\"type\"].Value;\n\n            if (messageType == errorId)\n            {\n                message.type = CompilerMessageType.Error;\n            }\n            else if (!string.IsNullOrEmpty(informationId) && messageType == informationId)\n            {\n                message.type = CompilerMessageType.Information;\n            }\n            else\n            {\n                message.type = CompilerMessageType.Warning;\n            }\n\n            return message;\n        }\n\n        public virtual IEnumerable<CompilerMessage> Parse(string[] errorOutput, bool compilationHadFailure)\n        {\n            return Parse(errorOutput, new string[0], compilationHadFailure);\n        }\n\n        /* we want to remove the assemblyName_unused argument, but today burst uses internalsvisibleto and inherits from this class :( so we cannot change this signature*/\n        public virtual IEnumerable<CompilerMessage> Parse(string[] errorOutput, string[] standardOutput, bool compilationHadFailure, string assemblyName_unused = null)\n        {\n            var hasErrors = false;\n            var msgs = new List<CompilerMessage>();\n            var regex = GetOutputRegex();\n            var internalErrorRegex = GetInternalErrorOutputRegex();\n\n\n            foreach (var line in errorOutput)\n            {\n                if (!ShouldParseLine(line))\n                    continue;\n                //Jamplus can fail with enormous lines in the stdout, parsing of which can take 30! seconds.\n                var line2 = line.Length > 1000 ? line.Substring(0, 100) : line;\n\n                Match m = regex.Match(line2);\n                if (!m.Success)\n                {\n                    if (internalErrorRegex != null)\n                        m = internalErrorRegex.Match(line2);\n                    if (!m.Success)\n                        continue;\n                }\n                CompilerMessage message = CreateCompilerMessageFromMatchedRegex(line, m, GetErrorIdentifier(), GetInformationIdentifier());\n\n                if (message.type == CompilerMessageType.Error)\n                    hasErrors = true;\n\n                msgs.Add(message);\n            }\n            if (compilationHadFailure && !hasErrors)\n            {\n                msgs.Add(CreateInternalCompilerErrorMessage(errorOutput));\n            }\n            return msgs;\n        }\n\n        protected virtual bool ShouldParseLine(string line)\n        {\n            return true;\n        }\n\n        protected abstract string GetErrorIdentifier();\n\n        protected virtual string GetInformationIdentifier()\n        {\n            return \"info\";\n        }\n\n        protected abstract Regex GetOutputRegex();\n        protected virtual Regex GetInternalErrorOutputRegex() { return null; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/Compilers/CompilerSpecificReponseFiles.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor.Scripting.Compilers\n{\n    internal class CompilerSpecificResponseFiles\n    {\n        public const string MicrosoftCSharpCompiler = \"csc.rsp\";\n        public static string[] MicrosoftCSharpCompilerObsolete = new[] { \"mcs.rsp\" };\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/Compilers/Il2CppOutputParser.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Text;\nusing System.Text.RegularExpressions;\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor.Scripting.Compilers\n{\n    sealed class Il2CppOutputParser : CompilerOutputParserBase\n    {\n        private const string _errorIdentifier = \"IL2CPP error\";\n        private static readonly Regex sErrorRegexWithSourceInformation = new Regex(@\"\\s*(?<message>.*) in (?<filename>.*):(?<line>\\d+)\");\n\n        private readonly string _jsonFileName;\n\n        public Il2CppOutputParser(string jsonFileName)\n        {\n            _jsonFileName = jsonFileName;\n        }\n\n        public override IEnumerable<CompilerMessage> Parse(string[] errorOutput, string[] standardOutput, bool compilationHadFailure, string assemblyName_unused = null)\n        {\n            var messages = new List<CompilerMessage>();\n            if (File.Exists(_jsonFileName))\n            {\n                var jsonText = File.ReadAllText(_jsonFileName);\n                var data = JsonUtility.FromJson<Il2CppToEditorData>(jsonText);\n                foreach (var message in data.Messages)\n                    messages.Add(new CompilerMessage\n                        {message = message.Text, type = ToCompilerMessageType(message.Type)});\n            }\n            else\n            {\n                ParseMessageFromStandardOutput(standardOutput, messages);\n            }\n\n            return messages;\n        }\n\n        private static void ParseMessageFromStandardOutput(string[] standardOutput, List<CompilerMessage> messages)\n        {\n            for (int i = 0; i < standardOutput.Length; ++i)\n            {\n                var line = standardOutput[i];\n                if (line.StartsWith(_errorIdentifier))\n                {\n                    var sourceFile = string.Empty;\n                    var sourceLine = 0;\n                    var errorMessage = new StringBuilder();\n\n                    var match = sErrorRegexWithSourceInformation.Match(line);\n                    if (match.Success)\n                    {\n                        sourceFile = match.Groups[\"filename\"].Value;\n                        sourceLine = int.Parse(match.Groups[\"line\"].Value);\n                        errorMessage.AppendFormat(\"{0} in {1}:{2}\", match.Groups[\"message\"].Value, Path.GetFileName(sourceFile), sourceLine);\n                    }\n                    else\n                    {\n                        errorMessage.Append(line);\n                    }\n\n                    if (i + 1 < standardOutput.Length && standardOutput[i + 1].StartsWith(\"Additional information:\"))\n                    {\n                        errorMessage.AppendFormat(\"{0}{1}\", Environment.NewLine, standardOutput[i + 1]);\n                        ++i;\n                    }\n                    messages.Add(new CompilerMessage\n                    {\n                        file = sourceFile,\n                        line = sourceLine,\n                        message = errorMessage.ToString(),\n                        type = CompilerMessageType.Error,\n                    });\n                }\n            }\n        }\n\n        CompilerMessageType ToCompilerMessageType(Il2CppMessageType il2cppMessageType)\n        {\n            if (il2cppMessageType == Il2CppMessageType.Warning)\n                return CompilerMessageType.Warning;\n            return CompilerMessageType.Error;\n        }\n\n        protected override string GetErrorIdentifier()\n        {\n            return _errorIdentifier;\n        }\n\n        protected override string GetInformationIdentifier()\n        {\n            return default;\n        }\n\n        protected override Regex GetOutputRegex()\n        {\n            return sErrorRegexWithSourceInformation;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompilerOutputParser.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Text.RegularExpressions;\n\nnamespace UnityEditor.Scripting.Compilers\n{\n    internal class MicrosoftCSharpCompilerOutputParser : CompilerOutputParserBase\n    {\n        public static Regex sCompilerOutput = new Regex(@\"(?<filename>.+)(\\((?<line>\\d+),(?<column>\\d+)\\)):\\s*(?<type>warning|error|info)\\s*(?<id>[^:]*):\\s*(?<message>.*)\", RegexOptions.ExplicitCapture | RegexOptions.Compiled);\n\n        protected override bool ShouldParseLine(string line)\n        {\n            return line.Contains(\"warning\", StringComparison.Ordinal) ||\n                   line.Contains(\"error\", StringComparison.Ordinal) ||\n                   line.Contains(\"info\", StringComparison.Ordinal);\n        }\n\n        protected override string GetInformationIdentifier()\n        {\n            return \"info\";\n        }\n\n        protected override Regex GetOutputRegex()\n        {\n            return sCompilerOutput;\n        }\n\n        protected override string GetErrorIdentifier()\n        {\n            return \"error\";\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/Compilers/MicrosoftCSharpResponseFileProvider.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Scripting.Compilers\n{\n    internal class MicrosoftCSharpResponseFileProvider : ResponseFileProvider\n    {\n        public override string ResponseFileName { get { return CompilerSpecificResponseFiles.MicrosoftCSharpCompiler; } }\n\n        public override string[] ObsoleteResponseFileNames { get { return CompilerSpecificResponseFiles.MicrosoftCSharpCompilerObsolete; } }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/Compilers/MicrosoftResponseFileParser.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing UnityEditor.Compilation;\nusing UnityEditor.Utils;\nusing UnityEngine;\n\nnamespace UnityEditor.Scripting.Compilers\n{\n    internal static class ScriptCompilerBase\n    {\n        public class CompilerOption\n        {\n            public string Arg;\n            public string Value;\n        }\n    }\n\n    internal static class MicrosoftResponseFileParser\n    {\n        static readonly char[] CompilerOptionArgumentSeperators = {';', ','};\n\n        public static List<ScriptCompilerBase.CompilerOption> GetCompilerOptions(string responseFileContent)\n        {\n            var compilerOptions = new List<ScriptCompilerBase.CompilerOption>();\n\n            var responseFileStrings = ResponseFileTextToStrings(responseFileContent);\n\n            foreach (var line in responseFileStrings)\n            {\n                int idx = line.IndexOf(':');\n                string arg, value;\n\n                if (idx == -1)\n                {\n                    arg = line;\n                    value = \"\";\n                }\n                else\n                {\n                    arg = line.Substring(0, idx);\n                    value = line.Substring(idx + 1);\n                }\n\n                if (!string.IsNullOrEmpty(arg) && arg[0] == '-')\n                    arg = '/' + arg.Substring(1);\n\n                compilerOptions.Add(new ScriptCompilerBase.CompilerOption {Arg = arg, Value = value});\n            }\n\n            return compilerOptions;\n        }\n\n        public static List<string> GetDefines(List<ScriptCompilerBase.CompilerOption> compilerOptions)\n        {\n            List<string> defines = new List<string>(compilerOptions.Count);\n            foreach (var compilerOption in compilerOptions)\n            {\n                if (IsDefine(compilerOption))\n                {\n                    defines.AddRange(GetOptionDefines(compilerOption));\n                }\n            }\n\n            return defines;\n        }\n\n        private static string[] GetOptionDefines(ScriptCompilerBase.CompilerOption compilerOption)\n        {\n            return compilerOption.Value.Split(CompilerOptionArgumentSeperators);\n        }\n\n        public static string GetResponseFileContent(string projectDirectory, string path)\n        {\n            var responseFilePath = Paths.ConvertSeparatorsToUnity(path);\n            var projectDirectoryUnitySeperators = Paths.ConvertSeparatorsToUnity(projectDirectory);\n\n            var relativeResponseFilePath = Paths.GetPathRelativeToProjectDirectory(responseFilePath);\n            var responseFile = AssetDatabase.LoadAssetAtPath<TextAsset>(relativeResponseFilePath);\n\n            if (responseFile)\n            {\n                return responseFile.text;\n            }\n\n            if (File.Exists(responseFilePath))\n            {\n                return File.ReadAllText(responseFilePath);\n            }\n\n            return string.Empty;\n        }\n\n        public static ResponseFileData ParseResponseFileFromFile(\n            string responseFilePath,\n            string projectDirectory,\n            string[] systemReferenceDirectories)\n        {\n            responseFilePath = Paths.ConvertSeparatorsToUnity(responseFilePath);\n            projectDirectory = Paths.ConvertSeparatorsToUnity(projectDirectory);\n\n            var relativeResponseFilePath = Paths.GetPathRelativeToProjectDirectory(responseFilePath);\n\n            if (File.Exists(responseFilePath))\n            {\n                var responseFileText = File.ReadAllText(responseFilePath);\n                return ParseResponseFileText(\n                    responseFileText,\n                    responseFilePath,\n                    projectDirectory,\n                    systemReferenceDirectories);\n            }\n            else\n            {\n                var empty = new ResponseFileData\n                {\n                    Defines = new string[0],\n                    FullPathReferences = new string[0],\n                    Unsafe = false,\n                    Errors = new string[0],\n                    OtherArguments = new string[0],\n                };\n\n                return empty;\n            }\n        }\n\n        static ResponseFileData ParseResponseFileText(\n            string fileContent,\n            string fileName,\n            string projectDirectory,\n            string[] systemReferenceDirectories)\n        {\n            List<ScriptCompilerBase.CompilerOption> compilerOptions = GetCompilerOptions(fileContent);\n\n            var responseArguments = new List<string>();\n            var defines = new List<string>();\n            var references = new List<string>();\n            bool unsafeDefined = false;\n            var errors = new List<string>();\n\n            foreach (var option in compilerOptions)\n            {\n                var arg = option.Arg;\n                var value = option.Value;\n\n                if (IsDefine(option))\n                {\n                    defines.AddRange(GetOptionDefines(option));\n                }\n                else if (IsReference(option))\n                {\n                    if (TryGetReference(option, fileName, projectDirectory, systemReferenceDirectories, ref errors,\n                        out var result))\n                    {\n                        references.Add(result);\n                    }\n                }\n                else if (IsSetUnsafe(option))\n                {\n                    unsafeDefined = true;\n                }\n                else if (IsUnsetUnsafe(option))\n                {\n                    unsafeDefined = false;\n                }\n                else\n                {\n                    var valueWithColon = value.Length == 0 ? \"\" : \":\" + SafeArgString(value);\n                    responseArguments.Add(arg + valueWithColon);\n                }\n            }\n\n            var responseFileData = new ResponseFileData\n            {\n                Defines = defines.ToArray(),\n                FullPathReferences = references.ToArray(),\n                Unsafe = unsafeDefined,\n                Errors = errors.ToArray(),\n                OtherArguments = responseArguments.ToArray(),\n            };\n\n            return responseFileData;\n        }\n\n        private static string SafeArgString(string text)\n        {\n            return ContainsWhiteSpace(text) ? $\"\\\"{text}\\\"\" : text;\n        }\n\n        private static bool ContainsWhiteSpace(string text)\n        {\n            for (int i = 0; i < text.Length; i++)\n            {\n                if (char.IsWhiteSpace(text[i])) return true;\n            }\n            return false;\n        }\n\n        private static bool IsDefine(ScriptCompilerBase.CompilerOption compilerOption)\n        {\n            if (string.IsNullOrEmpty(compilerOption?.Arg))\n            {\n                return false;\n            }\n\n            return compilerOption.Arg.Equals(\"/d\", StringComparison.Ordinal)\n                || compilerOption.Arg.Equals(\"/define\", StringComparison.Ordinal);\n        }\n\n        private static bool IsReference(ScriptCompilerBase.CompilerOption compilerOption)\n        {\n            if (string.IsNullOrEmpty(compilerOption?.Arg))\n            {\n                return false;\n            }\n\n            return compilerOption.Arg.Equals(\"/r\", StringComparison.Ordinal)\n                || compilerOption.Arg.Equals(\"/reference\", StringComparison.Ordinal);\n        }\n\n        private static bool IsSetUnsafe(ScriptCompilerBase.CompilerOption compilerOption)\n        {\n            if (string.IsNullOrEmpty(compilerOption?.Arg))\n            {\n                return false;\n            }\n\n            return compilerOption.Arg.Equals(\"/unsafe\", StringComparison.Ordinal)\n                || compilerOption.Arg.Equals(\"/unsafe+\", StringComparison.Ordinal);\n        }\n\n        private static bool IsUnsetUnsafe(ScriptCompilerBase.CompilerOption compilerOption)\n        {\n            if (string.IsNullOrEmpty(compilerOption?.Arg))\n            {\n                return false;\n            }\n\n            return compilerOption.Arg.Equals(\"/unsafe\", StringComparison.Ordinal)\n                || compilerOption.Arg.Equals(\"/unsafe+\", StringComparison.Ordinal);\n        }\n\n        private static bool TryGetReference(ScriptCompilerBase.CompilerOption option, string fileName,\n            string projectDirectory, string[] systemReferenceDirectories,\n            ref List<string> errors, out string result)\n        {\n            result = null;\n            var value = option.Value;\n            if (value.Length == 0)\n            {\n                errors.Add(\"No value set for reference\");\n                return false; // break;\n            }\n\n            string[] refs = value.Split(CompilerOptionArgumentSeperators);\n\n            if (refs.Length != 1)\n            {\n                errors.Add(\"Cannot specify multiple aliases using single /reference option\");\n                return false; // break;\n            }\n\n            var reference = refs[0];\n            if (reference.Length == 0)\n            {\n                return false; // continue;\n            }\n\n            int index = reference.IndexOf('=');\n            var responseReference = index > -1 ? reference.Substring(index + 1) : reference;\n\n            var fullPathReference = responseReference;\n            bool isRooted = Path.IsPathRooted(responseReference);\n            if (!isRooted)\n            {\n                foreach (var directory in systemReferenceDirectories)\n                {\n                    var systemReferencePath = Paths.Combine(directory, responseReference);\n                    if (File.Exists(systemReferencePath))\n                    {\n                        fullPathReference = systemReferencePath;\n                        isRooted = true;\n                        break;\n                    }\n                }\n\n                var userPath = Paths.Combine(projectDirectory, responseReference);\n                if (File.Exists(userPath))\n                {\n                    fullPathReference = userPath;\n                    isRooted = true;\n                }\n            }\n\n            if (!isRooted)\n            {\n                errors.Add(\n                    $\"{fileName}: not parsed correctly: {responseReference} could not be found as a system library.\\n\" +\n                    \"If this was meant as a user reference please provide the relative path from project root (parent of the Assets folder) in the response file.\");\n                return false; // continue;\n            }\n\n            responseReference = fullPathReference.Replace('\\\\', '/');\n            result = responseReference;\n            return true;\n        }\n\n        // From:\n        // https://github.com/mono/mono/blob/c106cdc775792ceedda6da58de7471f9f5c0b86c/mcs/mcs/settings.cs\n        //\n        // settings.cs: All compiler settings\n        //\n        // Author: Miguel de Icaza (miguel@ximian.com)\n        //            Ravi Pratap  (ravi@ximian.com)\n        //            Marek Safar  (marek.safar@gmail.com)\n        //\n        //\n        // Dual licensed under the terms of the MIT X11 or GNU GPL\n        //\n        // Copyright 2001 Ximian, Inc (http://www.ximian.com)\n        // Copyright 2004-2008 Novell, Inc\n        // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)\n        static string[] ResponseFileTextToStrings(string responseFileText)\n        {\n            var args = new List<string>();\n\n            var sb = new System.Text.StringBuilder();\n\n            var textLines = responseFileText.Split('\\n', '\\r');\n\n            foreach (var line in textLines)\n            {\n                int t = line.Length;\n\n                for (int i = 0; i < t; i++)\n                {\n                    char c = line[i];\n\n                    if (c == '\"' || c == '\\'')\n                    {\n                        char end = c;\n\n                        for (i++; i < t; i++)\n                        {\n                            c = line[i];\n\n                            if (c == end)\n                                break;\n                            sb.Append(c);\n                        }\n                    }\n                    else if (c == ' ')\n                    {\n                        if (sb.Length > 0)\n                        {\n                            args.Add(sb.ToString());\n                            sb.Length = 0;\n                        }\n                    }\n                    else if (c == '#')\n                    {\n                        // skip the rest of the line if it is the start of a comment\n                        break;\n                    }\n                    else\n                        sb.Append(c);\n                }\n\n                if (sb.Length > 0)\n                {\n                    args.Add(sb.ToString());\n                    sb.Length = 0;\n                }\n            }\n\n            return args.ToArray();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/Compilers/ResponseFileProvider.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEngine;\n\nnamespace UnityEditor.Scripting.Compilers\n{\n    internal abstract class ResponseFileProvider\n    {\n        private const string k_AssetsFolder = \"Assets\";\n        public abstract string ResponseFileName { get; }\n\n        public abstract string[] ObsoleteResponseFileNames { get; }\n\n        public string ProjectPath\n        {\n            get; set;\n        }\n\n        protected ResponseFileProvider()\n        {\n            var dataPath = Application.dataPath;\n            ProjectPath = Path.GetDirectoryName(dataPath);\n        }\n\n        public List<string> Get(string folderToLookForResponseFilesIn)\n        {\n            if (!string.IsNullOrEmpty(folderToLookForResponseFilesIn) && !Path.IsPathRooted(folderToLookForResponseFilesIn))\n            {\n                folderToLookForResponseFilesIn = AssetPath.Combine(ProjectPath, folderToLookForResponseFilesIn);\n            }\n\n            var result = new List<string>();\n\n            var folderResponseFile = GetCompilerSpecific(folderToLookForResponseFilesIn);\n            if (!string.IsNullOrEmpty(folderResponseFile))\n            {\n                AddIfNotNull(result, folderResponseFile);\n            }\n            else\n            {\n                AddIfNotNull(result, GetDefaultResponseFiles());\n            }\n\n            return result;\n        }\n\n        protected string GetCompilerSpecific(string path)\n        {\n            if (string.IsNullOrEmpty(path))\n            {\n                return null;\n            }\n\n            //We only look for the specific response file in the folder.\n            var responseFilePath = AssetPath.Combine(path, ResponseFileName);\n\n            if (File.Exists(responseFilePath))\n            {\n                return responseFilePath;\n            }\n            return null;\n        }\n\n        protected string GetDefaultResponseFiles()\n        {\n            var rootResponseFilePath = AssetPath.Combine(ProjectPath, k_AssetsFolder, ResponseFileName);\n            if (File.Exists(rootResponseFilePath))\n            {\n                return rootResponseFilePath;\n            }\n\n            foreach (var obsoleteResponseFileName in ObsoleteResponseFileNames)\n            {\n                var obsoleteResponseFilePath = AssetPath.Combine(ProjectPath, k_AssetsFolder, obsoleteResponseFileName);\n                if (File.Exists(obsoleteResponseFilePath))\n                {\n                    return obsoleteResponseFilePath;\n                }\n            }\n            return null;\n        }\n\n        private static void AddIfNotNull<T>(List<T> list, T element)\n        {\n            if (element != null)\n            {\n                list.Add(element);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor.Scripting.Compilers\n{\n    /// Marks the type of a [[CompilerMessage]]\n    internal enum CompilerMessageType\n    {\n        /// The message is an error. The compilation has failed.\n        Error = 0,\n        /// The message is an warning only. If there are no error messages, the compilation has completed successfully.\n        Warning = 1,\n        // This message type is required because \"Info\" is an accepted action type in Microsoft rule set files:\n        // https://docs.microsoft.com/en-us/visualstudio/code-quality/working-in-the-code-analysis-rule-set-editor?view=vs-2019\n        Information = 2\n    }\n\n    /// This struct should be returned from GetCompilerMessages() on ScriptCompilerBase implementations\n    internal struct CompilerMessage\n    {\n        /// The text of the error or warning message\n        public string message;\n        /// The path name of the file the message refers to\n        public string file;\n        /// The line in the source file the message refers to\n        public int line;\n        /// The column of the line the message refers to\n        public int column;\n        /// The type of the message. Either Error or Warning\n        public CompilerMessageType type;\n\n        //This field is dead and not used. The reason it's still here is that its used through [InternalsVibislbeTo] by the burst package (as of oktober2020), so we cannot yet remove this\n        // ReSharper disable once NotAccessedField.Global\n        internal string assemblyName;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/Compilers/UWPReferences.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Linq;\nusing Microsoft.Win32;\n\nnamespace UnityEditor.Scripting.Compilers\n{\n    internal struct UWPExtensionSDK\n    {\n        public readonly string Name;\n        public readonly string Version;\n        public readonly string ManifestPath;\n\n        public UWPExtensionSDK(string name, string version, string manifestPath)\n        {\n            Name = name;\n            Version = version;\n            ManifestPath = manifestPath;\n        }\n    }\n\n    internal class UWPSDK\n    {\n        public readonly Version Version;\n        public readonly Version MinVSVersion;\n        public readonly IEnumerable<PreviousUWPSDK> PreviousSDKs;\n\n        public UWPSDK(Version version, Version minVSVersion, IEnumerable<PreviousUWPSDK> previousSDKs)\n        {\n            Version = version;\n            MinVSVersion = minVSVersion;\n            PreviousSDKs = previousSDKs;\n        }\n    }\n\n    internal class PreviousUWPSDK\n    {\n        public readonly Version Version;\n        public readonly bool DefaultFallback;\n\n        public PreviousUWPSDK(Version version, bool defaultFallback)\n        {\n            Version = version;\n            DefaultFallback = defaultFallback;\n        }\n    }\n\n    internal static class UWPReferences\n    {\n        private sealed class UWPExtension\n        {\n            public string Name { get; private set; }\n\n            public string[] References { get; private set; }\n\n            public UWPExtension(string manifest, string windowsKitsFolder, string sdkVersion)\n            {\n                var document = XDocument.Load(manifest);\n                var fileListElement = document.Element(\"FileList\");\n                if (fileListElement.Attribute(\"TargetPlatform\").Value != \"UAP\")\n                    throw new Exception(string.Format(\"Invalid extension manifest at \\\"{0}\\\".\", manifest));\n                Name = fileListElement.Attribute(\"DisplayName\").Value;\n                var containedApiContractsElement = fileListElement.Element(\"ContainedApiContracts\");\n                References = GetReferences(windowsKitsFolder, sdkVersion, containedApiContractsElement);\n            }\n        }\n\n        private static readonly Version kMinimumSupportedUWPVersion = new Version(10, 0, 19041, 0);\n        private static readonly PreviousUWPSDK kMinimumSupportedPreviousUWPSDK = new PreviousUWPSDK(kMinimumSupportedUWPVersion, true);\n        private static readonly UWPSDK kMinimumSupportedUWPSDK = new UWPSDK(kMinimumSupportedUWPVersion, new Version(16, 0), new[] { kMinimumSupportedPreviousUWPSDK });\n\n        public static UWPSDK MinimumSupportedUWPSDK { get { return kMinimumSupportedUWPSDK; } }\n        public static string GetBinPath(UWPSDK sdk, string architecture)\n        {\n            \n            var folder = GetWindowsKit10();\n            if (string.IsNullOrEmpty(folder))\n                return null;\n                \n            var version = SdkVersionToString(sdk.Version);\n\n            var binPath = CombinePaths(folder, \"bin\", version, architecture);\n\n            if(!Directory.Exists(binPath))\n                return null;\n\n            return binPath;\n        }\n\n        public static string[] GetReferences(UWPSDK sdk)\n        {\n            var folder = GetWindowsKit10();\n            if (string.IsNullOrEmpty(folder))\n                return new string[0];\n\n            var version = SdkVersionToString(sdk.Version);\n            var references = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);\n\n            var windowsWinMd = CombinePaths(folder, \"UnionMetadata\", version, \"Facade\", \"Windows.winmd\");\n            if (!File.Exists(windowsWinMd))\n                windowsWinMd = CombinePaths(folder, \"UnionMetadata\", \"Facade\", \"Windows.winmd\");\n\n            references.Add(windowsWinMd);\n\n            foreach (var reference in GetPlatform(folder, version))\n            {\n                references.Add(reference);\n            }\n\n            foreach (var extension in GetExtensions(folder, version))\n            {\n                foreach (var reference in extension.References)\n                {\n                    references.Add(reference);\n                }\n            }\n\n            return references.ToArray();\n        }\n\n        public static IEnumerable<UWPExtensionSDK> GetExtensionSDKs(UWPSDK sdk)\n        {\n            var windowsKit10Directory = GetWindowsKit10();\n            if (string.IsNullOrEmpty(windowsKit10Directory))\n                return new UWPExtensionSDK[0];\n\n            return GetExtensionSDKs(windowsKit10Directory, SdkVersionToString(sdk.Version));\n        }\n\n        static string SdkVersionToString(Version version)\n        {\n            var sdkVersion = version.ToString();\n\n            if (version.Minor == -1)\n                sdkVersion += \".0\";\n            if (version.Build == -1)\n                sdkVersion += \".0\";\n            if (version.Revision == -1)\n                sdkVersion += \".0\";\n\n            return sdkVersion;\n        }\n\n        public static IEnumerable<UWPSDK> GetInstalledSDKs()\n        {\n            var windowsKit10Directory = GetWindowsKit10();\n            if (string.IsNullOrEmpty(windowsKit10Directory))\n                return Enumerable.Empty<UWPSDK>();\n\n            var platformsUAP = CombinePaths(windowsKit10Directory, \"Platforms\", \"UAP\");\n            if (!Directory.Exists(platformsUAP))\n                return Enumerable.Empty<UWPSDK>();\n\n            var allSDKs = new List<UWPSDK>();\n\n            var filesUnderPlatformsUAP = Directory.GetFiles(platformsUAP, \"*\", SearchOption.AllDirectories);\n            var allPlatformXmlFiles = filesUnderPlatformsUAP.Where(f => string.Equals(\"Platform.xml\", Path.GetFileName(f), StringComparison.OrdinalIgnoreCase));\n\n            foreach (var platformXmlFile in allPlatformXmlFiles)\n            {\n                XDocument xDocument;\n\n                try\n                {\n                    xDocument = XDocument.Load(platformXmlFile);\n                }\n                catch\n                {\n                    continue;\n                }\n\n                foreach (var platformElement in xDocument.Elements(\"ApplicationPlatform\"))\n                {\n                    Version version;\n                    if (FindVersionInNode(platformElement, out version))\n                    {\n                        if (version < kMinimumSupportedUWPVersion)\n                            continue;\n\n                        var minVSVersionString = platformElement.Elements(\"MinimumVisualStudioVersion\").Select(e => e.Value).FirstOrDefault();\n\n                        // Get supported previous versionss\n                        var previousVersionPath = Path.Combine(Path.GetDirectoryName(platformXmlFile), \"PreviousPlatforms.xml\");\n                        var previousVersions = new List<PreviousUWPSDK>();\n\n                        if (File.Exists(previousVersionPath))\n                        {\n                            XNamespace xn = \"http://microsoft.com/schemas/Windows/SDK/PreviousPlatforms\";\n                            XDocument previousPlatformsDocument = null;\n\n                            try\n                            {\n                                previousPlatformsDocument = XDocument.Load(previousVersionPath);\n                            }\n                            catch\n                            {\n                            }\n\n                            if (previousPlatformsDocument != null)\n                            {\n                                var previousPlatformsElement = previousPlatformsDocument.Element(xn + \"PreviousPlatforms\");\n                                if (previousPlatformsElement != null)\n                                {\n                                    foreach (XElement previousPlatformElement in previousPlatformsElement.Elements(xn + \"ApplicationPlatform\"))\n                                    {\n                                        var versionAttribute = previousPlatformElement.Attribute(\"version\");\n                                        if (versionAttribute != null)\n                                        {\n                                            var previousVersionString = versionAttribute.Value;\n                                            bool isDefault = false;\n\n                                            var isDefaultFallbackAttribute = previousPlatformElement.Attribute(\"IsDefaultFallback\");\n                                            if (isDefaultFallbackAttribute != null)\n                                                bool.TryParse(isDefaultFallbackAttribute.Value, out isDefault);\n\n                                            var previousVersion = TryParseVersion(previousVersionString);\n                                            if (previousVersion != null && previousVersion >= kMinimumSupportedUWPVersion)\n                                                previousVersions.Add(new PreviousUWPSDK(previousVersion, isDefault));\n                                        }\n                                    }\n                                }\n                            }\n                        }\n\n                        if (previousVersions.Count == 0)\n                        {\n                            // For previous versions, only support the current version and our minimum supported version if no PreviousVersions.xml was found.\n                            previousVersions.Add(new PreviousUWPSDK(version, true));\n\n                            if (version > kMinimumSupportedUWPVersion)\n                                previousVersions.Add(new PreviousUWPSDK(kMinimumSupportedUWPVersion, false));\n                        }\n\n                        allSDKs.Add(new UWPSDK(version, TryParseVersion(minVSVersionString), previousVersions));\n                    }\n                }\n            }\n\n            return allSDKs;\n        }\n\n        // No Version.TryParse in .NET 3.5 :(\n        private static Version TryParseVersion(string s)\n        {\n            if (!string.IsNullOrEmpty(s))\n            {\n                try\n                {\n                    return new Version(s);\n                }\n                catch\n                {\n                }\n            }\n            return null;\n        }\n\n        private static bool FindVersionInNode(XElement node, out Version version)\n        {\n            for (var attribute = node.FirstAttribute; attribute != null; attribute = attribute.NextAttribute)\n            {\n                if (string.Equals(attribute.Name.LocalName, \"version\", StringComparison.OrdinalIgnoreCase))\n                {\n                    version = TryParseVersion(attribute.Value);\n                    if (version != null)\n                    {\n                        return true;\n                    }\n                }\n            }\n\n            version = null;\n            return false;\n        }\n\n        private static string[] GetPlatform(string folder, string version)\n        {\n            var platformXml = CombinePaths(folder, @\"Platforms\\UAP\", version, \"Platform.xml\");\n            if (!File.Exists(platformXml))\n                return new string[0];\n\n            var document = XDocument.Load(platformXml);\n            var applicationPlatformElement = document.Element(\"ApplicationPlatform\");\n            if (applicationPlatformElement.Attribute(\"name\").Value != \"UAP\")\n                throw new Exception(string.Format(\"Invalid platform manifest at \\\"{0}\\\".\", platformXml));\n            var containedApiContractsElement = applicationPlatformElement.Element(\"ContainedApiContracts\");\n            return GetReferences(folder, version, containedApiContractsElement);\n        }\n\n        private static string CombinePaths(params string[] paths)\n        {\n            return Path.Combine(paths);\n        }\n\n        private static IEnumerable<UWPExtensionSDK> GetExtensionSDKs(string sdkFolder, string sdkVersion)\n        {\n            var extensions = new List<UWPExtensionSDK>();\n            var extensionsFolder = Path.Combine(sdkFolder, \"Extension SDKs\");\n\n            if (!Directory.Exists(extensionsFolder))\n                return new UWPExtensionSDK[0];\n\n            foreach (var extensionFolder in Directory.GetDirectories(extensionsFolder))\n            {\n                var manifest = CombinePaths(extensionFolder, sdkVersion, \"SDKManifest.xml\");\n                var extensionName = Path.GetFileName(extensionFolder);\n\n                if (File.Exists(manifest))\n                {\n                    extensions.Add(new UWPExtensionSDK(extensionName, sdkVersion, manifest));\n                    continue;\n                }\n\n                if (extensionName == \"XboxLive\")\n                {\n                    // Workaround for XboxLive SDK bug: currently, its version is always 1.0. Microsoft said they'll fix it in the future.\n                    manifest = CombinePaths(extensionFolder, \"1.0\", \"SDKManifest.xml\");\n\n                    if (File.Exists(manifest))\n                    {\n                        extensions.Add(new UWPExtensionSDK(extensionName, \"1.0\", manifest));\n                    }\n                }\n            }\n\n            return extensions;\n        }\n\n        private static UWPExtension[] GetExtensions(string windowsKitsFolder, string version)\n        {\n            var extensions = new List<UWPExtension>();\n\n            foreach (var extensionSDK in GetExtensionSDKs(windowsKitsFolder, version))\n            {\n                try\n                {\n                    var extension = new UWPExtension(extensionSDK.ManifestPath, windowsKitsFolder, version);\n                    extensions.Add(extension);\n                }\n                catch\n                {\n                    // ignore exceptions\n                }\n            }\n\n            return extensions.ToArray();\n        }\n\n        private static string[] GetReferences(string windowsKitsFolder, string sdkVersion, XElement containedApiContractsElement)\n        {\n            var references = new List<string>();\n            foreach (var apiContractElement in containedApiContractsElement.Elements(\"ApiContract\"))\n            {\n                var name = apiContractElement.Attribute(\"name\").Value;\n                var version = apiContractElement.Attribute(\"version\").Value;\n                var reference = CombinePaths(windowsKitsFolder, \"References\", sdkVersion, name, version, name + \".winmd\");\n                if (!File.Exists(reference))\n                {\n                    reference = CombinePaths(windowsKitsFolder, \"References\", name, version, name + \".winmd\");\n\n                    if (!File.Exists(reference))\n                        continue;\n                }\n                references.Add(reference);\n            }\n            return references.ToArray();\n        }\n\n        private static string GetWindowsKit10()\n        {\n            var programFilesX86 =\n                Environment.GetEnvironmentVariable(\"ProgramFiles(x86)\")\n            ;\n            var folder = Path.Combine(programFilesX86, @\"Windows Kits\\10\\\");\n            try\n            {\n                const string keyName = @\"SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v10.0\";\n                folder = GetRegistryStringValueWrapper(keyName, \"InstallationFolder\", folder, UnityEditorInternal.RegistryView._32);\n            }\n            catch\n            {\n                // ignore exceptions\n            }\n\n            if (!Directory.Exists(folder))\n                return string.Empty;\n\n            return folder;\n        }\n\n        // Wrap this in a non-inlinable method so that when it gets JITed inside the test runner, it causes the exception\n        // inside try/catch of the parent method call.\n        [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]\n        static string GetRegistryStringValueWrapper(string subKey, string valueName, string defaultValue, UnityEditorInternal.RegistryView view)\n        {\n            return UnityEditorInternal.RegistryUtil.GetRegistryStringValue(subKey, valueName, defaultValue, view);\n        }\n\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ManagedDebugger.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\nusing UnityEditor.Compilation;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Scripting\n{\n    [InitializeOnLoad]\n    [NativeHeader(\"Editor/Src/Scripting/ManagedDebugger.h\")]\n    public sealed class ManagedDebugger\n    {\n        public static event Action<bool> debuggerAttached;\n\n        public static bool isAttached\n        {\n            get { return IsAttached(); }\n        }\n\n        public static bool isEnabled\n        {\n            get { return IsEnabled(); }\n        }\n\n        static ManagedDebugger()\n        {\n            SubscribeToCodeOptimizationChanged();\n        }\n\n        [FreeFunction(Name = \"ManagedDebugger::Disconnect\")]\n        public static extern void Disconnect();\n\n        [FreeFunction(Name = \"ManagedDebugger::IsAttached\")]\n        private static extern bool IsAttached();\n\n        [FreeFunction(Name = \"ManagedDebugger::IsEnabled\")]\n        private static extern bool IsEnabled();\n\n        [RequiredByNativeCode]\n        private static void OnDebuggerAttached(bool attached)\n        {\n            if (debuggerAttached != null)\n            {\n                debuggerAttached(attached);\n            }\n        }\n\n        private static void OnCodeOptimizationChanged(CodeOptimization codeOptimization)\n        {\n            if (CodeOptimization.Release == codeOptimization)\n            {\n                Disconnect();\n            }\n        }\n\n        private static void SubscribeToCodeOptimizationChanged()\n        {\n            CompilationPipeline.codeOptimizationChanged += OnCodeOptimizationChanged;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/NativeClassExtensionUtilities.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing System.Reflection;\n\nnamespace UnityEditor\n{\n    /// <summary>\n    /// What is this : helper class that provides functionality for dealing with managed types that actually are extensions of Native types (MonoBehaviour for example)\n    /// Motivation(s): is some rare cases, managed code needs to handle differently types that are a combination of both Native anf Managed code.\n    /// </summary>\n    class NativeClassExtensionUtilities // ScriptingRuntime\n    {\n        public static bool ExtendsANativeType(Type type)\n        {\n            return type.GetCustomAttributes(typeof(ExtensionOfNativeClassAttribute), true).Length != 0;\n        }\n\n        public static bool ExtendsANativeType(UnityEngine.Object obj)\n        {\n            return !object.ReferenceEquals(null, obj) && ExtendsANativeType(obj.GetType());\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing Bee.BeeDriver;\nusing ScriptCompilationBuildProgram.Data;\nusing UnityEditor.Scripting.ScriptCompilation;\n\nnamespace UnityEditor.Compilation\n{\n    public enum AssemblyBuilderStatus\n    {\n        NotStarted = 0,\n        IsCompiling = 1,\n        Finished = 2,\n    }\n\n    [Flags]\n    public enum AssemblyBuilderFlags\n    {\n        None = 0,\n        EditorAssembly = 1,\n        DevelopmentBuild = 2,\n    }\n\n    [Flags]\n    public enum ReferencesOptions\n    {\n        None = 0,\n        UseEngineModules = 1\n    }\n\n    [Obsolete(\"This feature is being deprecated and will be removed in the future. Similar functionality can be achieved using the Roslyn compiler\")]\n    public class AssemblyBuilder\n    {\n        public event Action<string> buildStarted;\n        public event Action<string, CompilerMessage[]> buildFinished;\n\n        public string[] scriptPaths { get; private set; }\n        public string assemblyPath { get; private set; }\n        public string[] additionalDefines { get; set; }\n        public string[] additionalReferences { get; set; }\n        public string[] excludeReferences { get; set; }\n        public ScriptCompilerOptions compilerOptions { get; set; }\n        public ReferencesOptions referencesOptions { get; set; }\n\n        public AssemblyBuilderFlags flags { get; set; }\n        public BuildTargetGroup buildTargetGroup { get; set; }\n        public BuildTarget buildTarget { get; set; }\n        public int subtarget { get; set; }\n\n        public string[] defaultReferences => GetDefaultReferences(EditorCompilationInterface.Instance);\n        public string[] defaultDefines => GetDefaultDefines(EditorCompilationInterface.Instance);\n\n        private class BeeScriptCompilationState\n        {\n            public ScriptAssembly[] assemblies;\n            public ActiveBuild ActiveBuild;\n            public EditorCompilation editorCompilation;\n            public bool finishedCompiling;\n        }\n        private BeeScriptCompilationState activeBeeBuild;\n\n\n        public AssemblyBuilder(string assemblyPath, params string[] scriptPaths)\n        {\n            if (string.IsNullOrEmpty(assemblyPath))\n                throw new ArgumentException(\"assemblyPath cannot be null or empty\");\n\n            if (scriptPaths == null || scriptPaths.Length == 0)\n                throw new ArgumentException(\"scriptPaths cannot be null or empty\");\n\n            this.scriptPaths = scriptPaths;\n            this.assemblyPath = assemblyPath;\n\n            compilerOptions = new ScriptCompilerOptions();\n            flags = AssemblyBuilderFlags.None;\n            referencesOptions = ReferencesOptions.None;\n            buildTargetGroup = EditorUserBuildSettings.activeBuildTargetGroup;\n            buildTarget = EditorUserBuildSettings.activeBuildTarget;\n        }\n\n        public bool Build()\n        {\n            return Build(EditorCompilationInterface.Instance);\n        }\n\n        internal bool Build(EditorCompilation editorCompilation)\n        {\n            if (editorCompilation.IsCompilationTaskCompiling()\n                || editorCompilation.IsAnyAssemblyBuilderCompiling())\n            {\n                return false;\n            }\n\n            if (status != AssemblyBuilderStatus.NotStarted)\n                throw new Exception(string.Format(\"Cannot start AssemblyBuilder with status {0}. Expected {1}\", status, AssemblyBuilderStatus.NotStarted));\n\n            var assembly = editorCompilation.CreateScriptAssembly(this);\n            var assemblies = assembly.AllRecursiveScripAssemblyReferencesIncludingSelf().ToArray();\n\n            // Start clean everytime\n            const string beeAssemblyBuilderDirectory = \"Library/BeeAssemblyBuilder\";\n            string beeAssemblyBuilderDirectoryInProjectDirectory =\n                string.IsNullOrEmpty(editorCompilation.projectDirectory)\n                ? beeAssemblyBuilderDirectory\n                : Path.Combine(editorCompilation.projectDirectory, beeAssemblyBuilderDirectory);\n\n            if (Directory.Exists(beeAssemblyBuilderDirectoryInProjectDirectory))\n                Directory.Delete(beeAssemblyBuilderDirectoryInProjectDirectory, true);\n\n            var debug = compilerOptions.CodeOptimization == CodeOptimization.Debug;\n\n            var buildRequest = UnityBeeDriver.BuildRequestFor(\n                EditorCompilation.ScriptCompilationBuildProgram,\n                editorCompilation,\n                $\"{(int)assembly.BuildTarget}{\"AB\"}\",\n                UnityBeeDriver.CacheMode.Off,\n                beeAssemblyBuilderDirectoryInProjectDirectory,\n                useScriptUpdater:false);\n            buildRequest.DataForBuildProgram.Add(() => BeeScriptCompilation.ScriptCompilationDataFor(\n                editorCompilation,\n                assemblies,\n                debug,\n                assembly.OutputDirectory,\n                assembly.BuildTarget,\n                true,\n                false));\n            buildRequest.Target = Constants.ScriptAssembliesTarget;\n\n            activeBeeBuild = new BeeScriptCompilationState\n            {\n                assemblies = new[] { assembly },\n                ActiveBuild =  BeeDriver.BuildAsync(buildRequest),\n                editorCompilation = editorCompilation,\n            };\n\n            editorCompilation.AddAssemblyBuilder(this);\n\n            InvokeBuildStarted();\n            return true;\n        }\n\n        private string[] GetDefaultReferences(EditorCompilation editorCompilation)\n        {\n            return editorCompilation.GetAssemblyBuilderDefaultReferences(this);\n        }\n\n        private string[] GetDefaultDefines(EditorCompilation editorCompilation)\n        {\n            return editorCompilation.GetAssemblyBuilderDefaultDefines(this);\n        }\n\n        public AssemblyBuilderStatus status\n        {\n            get\n            {\n                if (activeBeeBuild == null)\n                    return AssemblyBuilderStatus.NotStarted;\n\n                if (activeBeeBuild.finishedCompiling)\n                    return AssemblyBuilderStatus.Finished;\n\n                var activeBuildTaskObject = activeBeeBuild.ActiveBuild.TaskObject;\n                if (!activeBuildTaskObject.IsCompleted)\n                    return AssemblyBuilderStatus.IsCompiling;\n\n                var profileOutputWritingTask = activeBuildTaskObject.Result.ProfileOutputWritingTask;\n                if (!profileOutputWritingTask.IsCompleted)\n                    return AssemblyBuilderStatus.IsCompiling;\n\n                activeBeeBuild.finishedCompiling = true;\n                InvokeBuildFinished(activeBuildTaskObject.Result);\n\n                return AssemblyBuilderStatus.Finished;\n            }\n        }\n\n        private void InvokeBuildStarted()\n        {\n            try\n            {\n                buildStarted?.Invoke(assemblyPath);\n            }\n            catch (Exception e)\n            {\n                UnityEngine.Debug.LogException(e);\n            }\n            activeBeeBuild.editorCompilation.InvokeCompilationStarted(this);\n        }\n\n        private void InvokeBuildFinished(BeeDriverResult result)\n        {\n            activeBeeBuild.editorCompilation.ProcessCompilationResult(activeBeeBuild.assemblies, result, false, this);\n            try\n            {\n                buildFinished?.Invoke(assemblyPath, EditorCompilation.ConvertCompilerMessages(BeeScriptCompilation\n                    .ParseAllNodeResultsIntoCompilerMessages(result.BeeDriverMessages, result.NodeFinishedMessages, EditorCompilationInterface.Instance)\n                    .SelectMany(a => a).ToArray()));\n            }\n            catch (Exception e)\n            {\n                UnityEngine.Debug.LogException(e);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/AssemblyDefinitionException.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Compilation\n{\n    public class AssemblyDefinitionException : Exception\n    {\n        public string[] filePaths { get; }\n\n        public AssemblyDefinitionException(string message, params string[] filePaths) : base(message)\n        {\n            this.filePaths = filePaths;\n        }\n    }\n\n    [Obsolete(\"PrecompiledAssemblyException is no longer being thrown by Unity and will be removed.\")]\n    public class PrecompiledAssemblyException : Exception\n    {\n        public string[] filePaths { get; }\n\n        public PrecompiledAssemblyException(string message, params string[] filePaths) : base(message)\n        {\n            this.filePaths = filePaths;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/AssemblyFlags.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    // Keep in sync with ManagedAssemblyFlags in C++\n    [Flags]\n    enum AssemblyFlags\n    {\n        None = 0,\n        EditorOnly = (1 << 0),\n        UseForMono = (1 << 1),\n        UseForDotNet = (1 << 2),\n        FirstPass = (1 << 3),\n        ExcludedForRuntimeCode = (1 << 4),\n        UserAssembly = (1 << 5),\n        ExplicitlyReferenced = (1 << 6),\n        ExplicitReferences = (1 << 7),\n        UnityModule = (1 << 8),\n        NoEngineReferences = (1 << 9),\n        SuppressCompilerWarnings = (1 << 10),\n        ValidateAssembly = (1 << 13),\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/AssemblyGraphBuilder.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal interface IAssemblyGraphBuilder\n    {\n        Dictionary<CustomScriptAssembly, List<string>> Match(\n            IReadOnlyCollection<string> sources, bool logWarningOnMiss = true);\n    }\n\n    internal class AssemblyGraphBuilder : IAssemblyGraphBuilder\n    {\n        private readonly string _projectPath;\n        private readonly CustomScriptAssembly _globalAssemblyDefinition;\n        private readonly CustomScriptAssembly _editorAssebmlyDefinition;\n        private readonly CustomScriptAssembly _globalFirstpassAssemblyDefinition;\n        private readonly CustomScriptAssembly _editorFirstpassAssemblyDefinition;\n        static readonly string _guidFormat = \"N\";\n\n        private readonly CustomScriptAssemblyReference[] _globalFirstpassAssemblyReferences;\n\n        private PathMultidimensionalDivisionTree<CustomScriptAssembly> _npp =\n            new PathMultidimensionalDivisionTree<CustomScriptAssembly>();\n\n        public AssemblyGraphBuilder(string projectPath)\n        {\n            _projectPath = projectPath;\n            _globalAssemblyDefinition = new CustomScriptAssembly\n            {\n                Name = \"Assembly-CSharp\",\n                PathPrefix = projectPath,\n                FilePath = Path.Combine(projectPath, \"main.asmdef\"),\n                GUID = CreateNewUnityGuid(),\n                IsPredefined = true,\n            };\n\n            _editorAssebmlyDefinition = new CustomScriptAssembly\n            {\n                Name = \"Assembly-CSharp-Editor\",\n                PathPrefix = Path.Combine(projectPath, \"Editor\"),\n                FilePath = Path.Combine(projectPath, \"Editor/main-editor.asmdef\"),\n                GUID = CreateNewUnityGuid(),\n                IsPredefined = true,\n            };\n\n            _globalFirstpassAssemblyDefinition = new CustomScriptAssembly\n            {\n                Name = \"Assembly-CSharp-firstpass\",\n                PathPrefix = Path.Combine(projectPath, \"Plugins\"),\n                FilePath = Path.Combine(projectPath, \"Plugins/firstpass.asmdef\"),\n                GUID = CreateNewUnityGuid(),\n                IsPredefined = true,\n            };\n\n            _editorFirstpassAssemblyDefinition = new CustomScriptAssembly\n            {\n                Name = \"Assembly-CSharp-Editor-firstpass\",\n                PathPrefix = Path.Combine(projectPath, \"Plugins/Editor\"),\n                FilePath = Path.Combine(projectPath, \"Plugins/Editor/firstpass-editor.asmdef\"),\n                GUID = CreateNewUnityGuid(),\n                IsPredefined = true,\n            };\n\n            _globalFirstpassAssemblyReferences = new[]\n            {\n                CustomScriptAssemblyReference.FromPathAndReference(\n                    Path.Combine(projectPath, \"standard assets/standard assets.asmref\"),\n                    _globalFirstpassAssemblyDefinition.Name),\n                CustomScriptAssemblyReference.FromPathAndReference(\n                    Path.Combine(projectPath, \"pro standard assets/pro standard assets.asmref\"),\n                    _globalFirstpassAssemblyDefinition.Name),\n                CustomScriptAssemblyReference.FromPathAndReference(\n                    Path.Combine(projectPath, \"iphone standard assets/iphone standard assets.asmref\"),\n                    _globalFirstpassAssemblyDefinition.Name),\n            };\n        }\n\n        public void Initialize(IReadOnlyCollection<CustomScriptAssembly> assemblies,\n            IReadOnlyCollection<CustomScriptAssemblyReference> customScriptAssemblyReferences)\n        {\n            var assemblyByNameLookup = assemblies.ToDictionary(x => x.Name, x => x);\n            var assemblyByGuidLookup = assemblies.ToDictionary(x => x.GUID, x => x);\n\n            bool rootOverridden = assemblies.Any(x => AssetPath.ComparePaths(x.PathPrefix, _projectPath));\n            if (!rootOverridden)\n            {\n                _npp.Insert(_globalAssemblyDefinition.PathPrefix, _globalAssemblyDefinition);\n                _npp.Insert(_editorAssebmlyDefinition.PathPrefix, _editorAssebmlyDefinition);\n                _npp.Insert(_globalFirstpassAssemblyDefinition.PathPrefix, _globalFirstpassAssemblyDefinition);\n                _npp.Insert(_editorFirstpassAssemblyDefinition.PathPrefix, _editorFirstpassAssemblyDefinition);\n            }\n\n            foreach (var assemblyDef in assemblies)\n            {\n                _npp.Insert(assemblyDef.PathPrefix, assemblyDef);\n            }\n\n            if (!rootOverridden)\n            {\n                foreach (var globalFirstpassAssemblyReference in _globalFirstpassAssemblyReferences)\n                {\n                    _npp.Insert(globalFirstpassAssemblyReference.PathPrefix, _globalFirstpassAssemblyDefinition);\n                }\n            }\n\n            foreach (var assemblyReference in customScriptAssemblyReferences)\n            {\n                CustomScriptAssembly foundAssemblyDef = null;\n                var foundAssemblyDefinition = GUIDReference.IsGUIDReference(assemblyReference.Reference)\n                    ? assemblyByGuidLookup.TryGetValue(GUIDReference.GUIDReferenceToGUID(assemblyReference.Reference),\n                        out foundAssemblyDef)\n                    : assemblyByNameLookup.TryGetValue(assemblyReference.Reference, out foundAssemblyDef);\n\n                if (foundAssemblyDefinition)\n                {\n                    _npp.Insert(assemblyReference.PathPrefix, foundAssemblyDef);\n                }\n                else\n                {\n                    Console.WriteLine(\n                        $\"Assembly reference {assemblyReference.FilePath} has no target assembly definition\");\n                }\n            }\n        }\n\n        public Dictionary<CustomScriptAssembly, List<string>> Match(\n            IReadOnlyCollection<string> sources, bool logWarningOnMiss = true)\n        {\n            var assemblyNameSources = new Dictionary<CustomScriptAssembly, List<string>>();\n\n            foreach (var source in sources)\n            {\n                var sourceSpan = source.AsSpan();\n                var currentMatchingAssemblyDefinition = _npp.MatchClosest(sourceSpan, out var matchedBy);\n                currentMatchingAssemblyDefinition =\n                    CheckAndUpdateEditorSpecialFolder(currentMatchingAssemblyDefinition, sourceSpan, matchedBy);\n\n                if (currentMatchingAssemblyDefinition == null)\n                {\n                    if (logWarningOnMiss)\n                    {\n                        Console.WriteLine(\n                            $\"Script '{source}' will not be compiled because it exists outside the Assets folder and does not to belong to any assembly definition file.\");\n                    }\n\n                    continue;\n                }\n\n                if (!assemblyNameSources.TryGetValue(currentMatchingAssemblyDefinition, out var sourceList))\n                {\n                    sourceList = new List<string>();\n                    assemblyNameSources[currentMatchingAssemblyDefinition] = sourceList;\n                }\n\n                sourceList.Add(source);\n            }\n\n            return assemblyNameSources;\n        }\n\n        internal static string CreateNewUnityGuid()\n        {\n            return Guid.NewGuid().ToString(_guidFormat);\n        }\n\n        internal static ReadOnlySpan<char> GetRelativePathFromAsmdefOrAsmref(CustomScriptAssembly currentMatchingAssemblyDefinition, ReadOnlySpan<char> sourceSpan, string matchedBy)\n        {\n            if(currentMatchingAssemblyDefinition == null)\n            {\n                return sourceSpan;\n            }\n            return sourceSpan[matchedBy.Length..];\n        }\n\n        private CustomScriptAssembly CheckAndUpdateEditorSpecialFolder(\n            CustomScriptAssembly currentMatchingAssemblyDefinition, ReadOnlySpan<char> sourceSpan, string matchedBy)\n        {\n            var relativeSourceSpan = GetRelativePathFromAsmdefOrAsmref(currentMatchingAssemblyDefinition, sourceSpan, matchedBy);\n\n            if (HasEditorSpecialFolder(relativeSourceSpan))\n            {\n                if (currentMatchingAssemblyDefinition == null ||\n                    currentMatchingAssemblyDefinition == _globalAssemblyDefinition)\n                {\n                    currentMatchingAssemblyDefinition = _editorAssebmlyDefinition;\n                }\n                else if (currentMatchingAssemblyDefinition == _globalFirstpassAssemblyDefinition)\n                {\n                    currentMatchingAssemblyDefinition = _editorFirstpassAssemblyDefinition;\n                }\n            }\n\n            return currentMatchingAssemblyDefinition;\n        }\n\n        internal static bool HasEditorSpecialFolder(ReadOnlySpan<char> remainingPath)\n        {\n            const string editorLower = \"editor\";\n            const string editorUpper = \"EDITOR\";\n\n            if (remainingPath.Length < editorLower.Length)\n            {\n                return false;\n            }\n\n            int matchOffset = 0;\n            for (int i = 0; i < remainingPath.Length; i++)\n            {\n                if (editorLower[matchOffset] == remainingPath[i] || editorUpper[matchOffset] == remainingPath[i])\n                {\n                    matchOffset++;\n                    if (matchOffset < editorLower.Length)\n                    {\n                        continue;\n                    }\n\n                    // We have match the \"editor\" folder, if we are at the end of the\n                    // match or do we have a separator as our next character\n                    if (i + 1 >= remainingPath.Length\n                        || Utility.IsPathSeparator(remainingPath[i + 1]))\n                    {\n                        return true;\n                    }\n                }\n\n                // forward to next path separator or end\n                for (; i < remainingPath.Length; i++)\n                {\n                    if (Utility.IsPathSeparator(remainingPath[i]))\n                    {\n                        break;\n                    }\n                }\n\n                matchOffset = 0;\n                if (remainingPath.Length - i < editorLower.Length)\n                {\n                    return false;\n                }\n            }\n\n            return matchOffset == editorLower.Length;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/AssemblyGraphBuilderFactory.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal static class AssemblyGraphBuilderFactory\n    {\n        class AssemblyGraphBuilderKey\n        {\n            public bool Equals(AssemblyGraphBuilderKey other)\n            {\n                return string.Equals(projectPath, other.projectPath, StringComparison.Ordinal)\n                    && assemblies.SequenceEqual(other.assemblies)\n                    && customScriptAssemblyReferences.SequenceEqual(other.customScriptAssemblyReferences);\n            }\n\n            public override bool Equals(object obj)\n            {\n                if (ReferenceEquals(null, obj)) return false;\n                if (ReferenceEquals(this, obj)) return true;\n                if (obj.GetType() != this.GetType()) return false;\n                return Equals((AssemblyGraphBuilderKey) obj);\n            }\n\n            public override int GetHashCode()\n            {\n                return HashCode.Combine(projectPath, assemblies.Count, customScriptAssemblyReferences.Count);\n            }\n\n            public string projectPath;\n            public IReadOnlyCollection<CustomScriptAssembly> assemblies;\n            public IReadOnlyCollection<CustomScriptAssemblyReference> customScriptAssemblyReferences;\n        }\n\n        private static Dictionary<AssemblyGraphBuilderKey, AssemblyGraphBuilder> m_AlreadyInitializedAssemblyGraphBuilder =\n            new Dictionary<AssemblyGraphBuilderKey, AssemblyGraphBuilder>();\n\n        public static IAssemblyGraphBuilder GetOrCreate(string projectPath,\n            IReadOnlyCollection<CustomScriptAssembly> assemblies,\n            IReadOnlyCollection<CustomScriptAssemblyReference> customScriptAssemblyReferences)\n        {\n            var assemblyGraphBuilderKey = new AssemblyGraphBuilderKey\n            {\n                projectPath = projectPath,\n                assemblies = assemblies,\n                customScriptAssemblyReferences = customScriptAssemblyReferences,\n            };\n\n            if (!m_AlreadyInitializedAssemblyGraphBuilder.TryGetValue(assemblyGraphBuilderKey,\n                    out var assemblyGraphBuilder))\n            {\n                assemblyGraphBuilder = new AssemblyGraphBuilder(projectPath);\n                assemblyGraphBuilder.Initialize(assemblies, customScriptAssemblyReferences);\n                m_AlreadyInitializedAssemblyGraphBuilder[assemblyGraphBuilderKey] = assemblyGraphBuilder;\n            }\n\n            return assemblyGraphBuilder;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/AssetPath.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.Utils;\nusing File = System.IO.File;\nusing SystemPath = System.IO.Path;\n\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    static class AssetPath\n    {\n        public static readonly char Separator = '/';\n\n        /// <summary>\n        /// Compares two paths\n        /// type of slashes is ignored, so different path separators is allowed\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool ComparePaths(string left, string right)\n        {\n            var lengthDiff = left.Length - right.Length;\n            if (lengthDiff > 1 || lengthDiff < -1)\n                return false;\n\n            for (int i = 0; i < left.Length || i < right.Length; i++)\n            {\n                char leftCharLower = ' ';\n                char rightCharLower= ' ';\n                if (i < left.Length)\n                {\n                    leftCharLower = Utility.FastToLower(left[i]);\n                    leftCharLower = Utility.IsPathSeparator(leftCharLower) ? ' ' : leftCharLower;\n                }\n\n                if (i < right.Length)\n                {\n                    rightCharLower = Utility.FastToLower(right[i]);\n                    rightCharLower = Utility.IsPathSeparator(rightCharLower) ? ' ' : rightCharLower;\n                }\n\n                if (leftCharLower != rightCharLower)\n                    return false;\n            }\n\n            return true;\n        }\n\n        public static string GetFullPath(string path)\n        {\n            return ReplaceSeparators(SystemPath.GetFullPath(path.NormalizePath()));\n        }\n\n        public static string Combine(params string[] paths)\n        {\n            return ReplaceSeparators(Paths.Combine(paths));\n        }\n\n        public static string Combine(string path1, string path2)\n        {\n            return ReplaceSeparators(SystemPath.Combine(path1, path2));\n        }\n\n        public static bool IsPathRooted(string path)\n        {\n            return SystemPath.IsPathRooted(path.NormalizePath());\n        }\n\n        public static string GetFileName(string path)\n        {\n            return SystemPath.GetFileName(path.NormalizePath());\n        }\n\n        public static string GetExtension(string path)\n        {\n            return SystemPath.GetExtension(path.NormalizePath());\n        }\n\n        public static string GetDirectoryName(string path)\n        {\n            return ReplaceSeparators(SystemPath.GetDirectoryName(path.NormalizePath()));\n        }\n\n        public static string ReplaceSeparators(string path)\n        {\n            int length = path.Length;\n\n            var chars = new char[length];\n\n            for (int i = 0; i < length; ++i)\n            {\n                if (path[i] == '\\\\')\n                    chars[i] = Separator;\n                else\n                    chars[i] = path[i];\n            }\n\n            return new string(chars);\n        }\n\n        public static bool Exists(string path)\n        {\n            return File.Exists(path);\n        }\n\n        public static string GetAssemblyNameWithoutExtension(string assemblyName)\n        {\n            if (AssetPath.GetExtension(assemblyName) == \".dll\")\n                return SystemPath.GetFileNameWithoutExtension(assemblyName.NormalizePath());\n\n            return SystemPath.GetFileName(assemblyName.NormalizePath());\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/AssetPathMetaData.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Diagnostics;\nusing System.Runtime.InteropServices;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    [NativeAsStruct]\n    [StructLayout(LayoutKind.Sequential)]\n    [RequiredByNativeCode(GenerateProxy = true)]\n    [NativeHeader(\"Runtime/Scripting/ScriptingManagedProxySupport.h\")]\n    [NativeHeader(\"Runtime/ScriptingBackend/ScriptingNativeTypes.h\")]\n    [DebuggerDisplay(\"{DirectoryPath}\")]\n    class AssetPathMetaData\n    {\n        public string DirectoryPath;\n        public bool IsTestable;\n        public VersionMetaData VersionMetaData;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/AssetPathVersionMetaData.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    // Keep in sync with ManagedVersionType in C++\n    enum VersionType\n    {\n        VersionTypeUnity,\n        VersionTypePackage,\n    }\n\n    [NativeAsStruct]\n    [StructLayout(LayoutKind.Sequential)]\n    [RequiredByNativeCode(GenerateProxy = true)]\n    [NativeHeader(\"Runtime/Scripting/ScriptingManagedProxySupport.h\")]\n    class VersionMetaData\n    {\n        public string Name;\n        public string Version;\n        public VersionType Type;\n\n        public VersionMetaData(string name)\n        {\n            Name = name;\n        }\n\n        public VersionMetaData(string name, string version)\n        {\n            Name = name;\n            Version = version;\n        }\n\t\t\n        public VersionMetaData(string name, string version, VersionType type)\n        {\n            Name = name;\n            Version = version;\n\t\t\tType = type;\n        }\n    }\n\n\n    class VersionMetaDataComparer : IEqualityComparer<VersionMetaData>\n    {\n        public bool Equals(VersionMetaData current, VersionMetaData other)\n        {\n            if (current == null || other == null)\n            {\n                return current == other;\n            }\n\n            return string.Equals(current.Name, other.Name, StringComparison.Ordinal)\n                && string.Equals(current.Version, other.Version, StringComparison.Ordinal)\n                && current.Type == other.Type;\n        }\n\n        public int GetHashCode(VersionMetaData obj)\n        {\n            unchecked\n            {\n                var hashCode = (obj.Name != null ? obj.Name.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ (obj.Version != null ? obj.Version.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ obj.Type.GetHashCode();\n                return hashCode;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/AutoReferencedPackageAssemblies.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing static UnityEditor.Scripting.ScriptCompilation.EditorBuildRules;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    static class AutoReferencedPackageAssemblies\n    {\n        static HashSet<string> runtimeAssemblyNames = new HashSet<string>(new[]\n        {\n            \"UnityEngine.UI.dll\",\n        },\n            StringComparer.Ordinal);\n\n        static HashSet<string> editorAssemblyNames = new HashSet<string>(new[]\n        {\n            \"UnityEditor.UI.dll\",\n        },\n            StringComparer.Ordinal);\n\n        // Do not add automatic package references to these assemblies,\n        // as they also add themselves to all .asmdefs\n        static HashSet<string> ignoreAssemblies = new HashSet<string>(new[]\n        {\n            \"UnityEngine.TestRunner.dll\",\n            \"UnityEditor.TestRunner.dll\",\n        },\n            StringComparer.Ordinal);\n\n        static AutoReferencedPackageAssemblies()\n        {\n            editorAssemblyNames.UnionWith(runtimeAssemblyNames);\n            ignoreAssemblies.UnionWith(editorAssemblyNames);\n        }\n\n        public static void AddReferences(Dictionary<string, TargetAssembly> customTargetAssemblies, EditorScriptCompilationOptions options, Func<TargetAssembly, bool> shouldAdd)\n        {\n            if (customTargetAssemblies == null || customTargetAssemblies.Count == 0)\n                return;\n\n            bool buildingForEditor = (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor;\n\n            // Add runtime assembly references for the players and\n            // runtime and editor assembly references for the editor.\n            var autoReferencedAssemblies = buildingForEditor ? editorAssemblyNames : runtimeAssemblyNames;\n\n            var additionalReferences = new HashSet<TargetAssembly>();\n\n            foreach (var assemblyName in autoReferencedAssemblies)\n            {\n                TargetAssembly targetAssembly;\n\n                // If the automatic referenced package assemblies are in\n                // the project, then they should be add to all .asmdefs.\n                if (customTargetAssemblies.TryGetValue(assemblyName, out targetAssembly))\n                {\n                    additionalReferences.Add(targetAssembly);\n                }\n            }\n\n            // If none of the automatic references package assemblies are in\n            // the project, do not add anything.\n            if (!additionalReferences.Any())\n            {\n                return;\n            }\n\n            foreach (var entry in customTargetAssemblies)\n            {\n                var assembly = entry.Value;\n\n                if (!shouldAdd?.Invoke(assembly) ?? false)\n                {\n                    continue;\n                }\n\n                // Do not add additional references to any of the\n                // automatically referenced or ignored assemblies\n                if (ignoreAssemblies.Contains(assembly.Filename))\n                    continue;\n\n                // Add the automatic references.\n                var newReferences = assembly.References.Concat(additionalReferences).Distinct().ToList();\n                assembly.References = newReferences;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/BeeDriver/BeeScriptCompilation.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.IO;\nusing Bee.BeeDriver;\nusing Bee.BinLog;\nusing NiceIO;\nusing ScriptCompilationBuildProgram.Data;\nusing Unity.Profiling;\nusing UnityEditor.Build.Player;\nusing UnityEditor.Compilation;\nusing UnityEditor.Scripting.Compilers;\nusing UnityEngine;\nusing CompilerMessage = UnityEditor.Scripting.Compilers.CompilerMessage;\nusing CompilerMessageType = UnityEditor.Scripting.Compilers.CompilerMessageType;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal static class BeeScriptCompilation\n    {\n        internal static string ExecutableExtension => Application.platform == RuntimePlatform.WindowsEditor ? \".exe\" : \"\";\n        private static string projectPath = Path.GetDirectoryName(Application.dataPath);\n\n        public static ScriptCompilationData ScriptCompilationDataFor(\n            EditorCompilation editorCompilation,\n            ScriptAssembly[] assemblies,\n            bool debug,\n            string outputDirectory,\n            BuildTarget buildTarget,\n            bool buildingForEditor,\n            bool enableScriptUpdater,\n            string[] extraScriptingDefines = null, ScriptAssemblySettings settings = null)\n        {\n            // Need to call AssemblyDataFrom before calling CompilationPipeline.GetScriptAssemblies,\n            // as that acts on the same ScriptAssemblies, and modifies them with different build settings.\n            var cachedAssemblies = AssemblyDataFrom(assemblies);\n\n            AssemblyData[] codeGenAssemblies;\n            using (new ProfilerMarker(\"GetScriptAssembliesForCodeGen\").Auto())\n            {\n                codeGenAssemblies = buildingForEditor\n                    ? null\n                    : AssemblyDataFrom(CodeGenAssemblies(CompilationPipeline.GetScriptAssemblies(editorCompilation, AssembliesType.Editor, extraScriptingDefines)));\n            }\n\n            var movedFromExtractorPath = $\"{EditorApplication.applicationContentsPath}/Tools/Compilation/ApiUpdater/ApiUpdater.MovedFromExtractor.dll\";\n            var dotNetSdkRoslynPath = EditorApplication.applicationContentsPath + $\"/DotNetSdkRoslyn\";\n\n            var localization = \"en-US\";\n            if (LocalizationDatabase.currentEditorLanguage != SystemLanguage.English && EditorPrefs.GetBool(\"Editor.kEnableCompilerMessagesLocalization\", false))\n                localization = LocalizationDatabase.GetCulture(LocalizationDatabase.currentEditorLanguage);\n\n            var assembliesToScanForTypeDB = new HashSet<string>();\n            var searchPaths = new HashSet<string>(BuildPlayerDataGenerator.GetStaticSearchPaths(buildTarget));\n            EditorScriptCompilationOptions options;\n\n            if (settings is null)\n            {\n                options = EditorScriptCompilationOptions.BuildingIncludingTestAssemblies;\n                if (buildingForEditor)\n                    options |= EditorScriptCompilationOptions.BuildingForEditor;\n            }\n            else\n            {\n                options = settings.CompilationOptions;\n            }\n\n            foreach (var a in editorCompilation.GetAllScriptAssemblies(options, extraScriptingDefines))\n            {\n                if (!a.Flags.HasFlag(AssemblyFlags.EditorOnly))\n                {\n                    var path = a.FullPath.ToNPath();\n                    assembliesToScanForTypeDB.Add(path.ToString());\n                    searchPaths.Add(path.Parent.ToString());\n                }\n            }\n\n            var precompileAssemblies = editorCompilation.PrecompiledAssemblyProvider.GetPrecompiledAssembliesDictionary(\n                options,\n                buildTarget,\n                extraScriptingDefines);\n            if (precompileAssemblies != null)\n            {\n                foreach (var a in precompileAssemblies)\n                {\n                    if (!a.Value.Flags.HasFlag(AssemblyFlags.EditorOnly))\n                    {\n                        var path = a.Value.Path.ToNPath();\n                        assembliesToScanForTypeDB.Add(path.ToString());\n                        searchPaths.Add(path.Parent.ToString());\n                    }\n                }\n            }\n\n            return new ScriptCompilationData()\n            {\n                OutputDirectory = outputDirectory,\n                DotnetRuntimePath = NetCoreProgram.DotNetRuntimePath.ToString(),\n                DotnetRoslynPath = dotNetSdkRoslynPath,\n                MovedFromExtractorPath = movedFromExtractorPath,\n                Assemblies = cachedAssemblies,\n                CodegenAssemblies = codeGenAssemblies,\n                Debug = debug,\n                BuildTarget = buildTarget.ToString(),\n                Localization = localization,\n                EnableDiagnostics = editorCompilation.EnableDiagnostics,\n                BuildPlayerDataOutput = $\"Library/BuildPlayerData/{(buildingForEditor ? \"Editor\" : \"Player\")}\",\n                ExtractRuntimeInitializeOnLoads = !buildingForEditor,\n                AssembliesToScanForTypeDB = assembliesToScanForTypeDB.OrderBy(p => p).ToArray(),\n                SearchPaths = searchPaths.OrderBy(p => p).ToArray(),\n                EmitInfoForScriptUpdater = enableScriptUpdater\n            };\n        }\n\n        private static ScriptAssembly[] CodeGenAssemblies(ScriptAssembly[] assemblies) =>\n            assemblies\n                .Where(assembly => UnityCodeGenHelpers.IsCodeGen(FileUtil.GetPathWithoutExtension(assembly.Filename)))\n                .SelectMany(assembly => assembly.AllRecursiveScripAssemblyReferencesIncludingSelf())\n                .Distinct()\n                .OrderBy(a => a.Filename)\n                .ToArray();\n\n        private static AssemblyData[] AssemblyDataFrom(ScriptAssembly[] assemblies)\n        {\n            Array.Sort(assemblies, (a1, a2) => string.Compare(a1.Filename, a2.Filename, StringComparison.Ordinal));\n            return assemblies.Select((scriptAssembly, index) =>\n            {\n                using (new ProfilerMarker($\"AssemblyDataFrom {scriptAssembly.Filename}\").Auto())\n                    return AssemblyDataFrom(scriptAssembly, assemblies, index);\n            }).ToArray();\n        }\n\n        private static AssemblyData AssemblyDataFrom(ScriptAssembly a, ScriptAssembly[] allAssemblies, int index)\n        {\n            Array.Sort(a.Files, StringComparer.Ordinal);\n            var references = a.ScriptAssemblyReferences.Select(r => Array.IndexOf(allAssemblies, r)).ToArray();\n            Array.Sort(references);\n            return new AssemblyData\n            {\n                Name = new NPath(a.Filename).FileNameWithoutExtension,\n                SourceFiles = a.Files,\n                Defines = a.Defines,\n                PrebuiltReferences = a.References,\n                References = references,\n                AllowUnsafeCode = a.CompilerOptions.AllowUnsafeCode,\n                RuleSet = a.CompilerOptions.RoslynAnalyzerRulesetPath,\n                LanguageVersion = a.CompilerOptions.LanguageVersion,\n                Analyzers = a.CompilerOptions.RoslynAnalyzerDllPaths,\n                AdditionalFiles = a.CompilerOptions.RoslynAdditionalFilePaths,\n                AnalyzerConfigPath = a.CompilerOptions.AnalyzerConfigPath,\n                UseDeterministicCompilation = a.CompilerOptions.UseDeterministicCompilation,\n                SuppressCompilerWarnings = (a.Flags & AssemblyFlags.SuppressCompilerWarnings) != 0,\n                Asmdef = a.AsmDefPath,\n                CustomCompilerOptions = a.CompilerOptions.AdditionalCompilerArguments,\n                BclDirectories = MonoLibraryHelpers.GetSystemReferenceDirectories(a.CompilerOptions.ApiCompatibilityLevel),\n                DebugIndex = index,\n                SkipCodeGen = a.SkipCodeGen,\n                Path = projectPath,\n            };\n        }\n\n        private static CompilerMessage AsCompilerMessage(BeeDriverResult.Message message)\n        {\n            return new CompilerMessage\n            {\n                message = message.Text,\n                type = message.Kind == BeeDriverResult.MessageKind.Error\n                    ? CompilerMessageType.Error\n                    : CompilerMessageType.Warning,\n            };\n        }\n\n        /// <summary>\n        /// the returned array of compiler messages corresponds to the input array of noderesult. Each node result can result in 0,1 or more compilermessages.\n        /// We return them as an array of arrays, so on the caller side you're still able to map a compilermessage to the noderesult where it originated from,\n        /// which we need when invoking per assembly compilation callbacks.\n        /// </summary>\n        public static CompilerMessage[][] ParseAllNodeResultsIntoCompilerMessages(BeeDriverResult.Message[] beeDriverMessages, NodeFinishedMessage[] nodeResults, EditorCompilation editorCompilation)\n        {\n            // If there's any messages from the bee driver, we add one additional array to the result which contains all of the driver messages converted and augmented like the nodes messages arrays.\n            bool hasBeeDriverMessages = beeDriverMessages.Length > 0;\n            var result = new CompilerMessage[nodeResults.Length + (hasBeeDriverMessages ? 1 : 0)][];\n\n            int resultIndex = 0;\n            if (hasBeeDriverMessages)\n            {\n                result[resultIndex] = beeDriverMessages.Select(AsCompilerMessage).ToArray();\n                ++resultIndex;\n            }\n            for (int i = 0; i != nodeResults.Length; i++)\n            {\n                result[resultIndex] = ParseCompilerOutput(nodeResults[i]);\n                ++resultIndex;\n            }\n\n            //To be more kind to performance issues in situations where there are thousands of compiler messages, we're going to assume\n            //that after the first 10 compiler error messages, we get very little benefit from augmenting the rest with higher quality unity specific messaging.\n            int totalErrors = 0;\n            int nextResultToAugment = 0;\n            while (totalErrors < 10 && nextResultToAugment < result.Length)\n            {\n                UnitySpecificCompilerMessages.AugmentMessagesInCompilationErrorsWithUnitySpecificAdvice(result[nextResultToAugment], editorCompilation);\n                totalErrors += result[nextResultToAugment].Count(m => m.type == CompilerMessageType.Error);\n                ++nextResultToAugment;\n            }\n\n            return result;\n        }\n\n        public static CompilerMessage[] ParseCompilerOutput(NodeFinishedMessage nodeResult)\n        {\n            // TODO: future improvement opportunity: write a single parser that can parse warning, errors files from all tools that we use.\n            if (nodeResult.Node.Annotation.StartsWith(\"CopyFiles\", StringComparison.Ordinal))\n            {\n                if (nodeResult.ExitCode == 0)\n                {\n                    return Array.Empty<CompilerMessage>();\n                }\n                return new[]\n                {\n                    new CompilerMessage\n                    {\n                        file = nodeResult.Node.OutputFile,\n                        message = $\"{nodeResult.Node.OutputFile}: {nodeResult.Output}\",\n                        type = CompilerMessageType.Error\n                    }\n                };\n            }\n            var parser = nodeResult.Node.Annotation.StartsWith(\"ILPostProcess\", StringComparison.Ordinal)\n                ? (CompilerOutputParserBase) new PostProcessorOutputParser()\n                : (CompilerOutputParserBase) new MicrosoftCSharpCompilerOutputParser();\n\n            return parser\n                .Parse(\n                (nodeResult.Output ?? string.Empty).Split(new[] {'\\r', '\\n'},\n                    StringSplitOptions.RemoveEmptyEntries),\n                nodeResult.ExitCode != 0).ToArray();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/BeeDriver/PotentiallyUpdatableErrorMessages.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing Bee.BinLog;\nusing Bee.Serialization;\nusing NiceIO;\nusing UnityEditor.Scripting.Compilers;\nusing UnityEngine;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal static class PotentiallyUpdatableErrorMessages\n    {\n        public static bool IsAnyPotentiallyUpdatable(CompilerMessage[] messages, NodeFinishedMessage nodeResult,\n            ObjectsFromDisk dataFromBuildProgram)\n        {\n            var matches = messages\n                                    .Select(m => MicrosoftCSharpCompilerOutputParser.sCompilerOutput.Match(m.message))\n                                    .Where(m => m.Success && IsPotentiallyUpdatableDiagnostic(m))\n                                    .ToArray();\n\n            if (matches.Length == 0)\n                return false;\n\n            var localizedCompilerMessages = Helpers.LocalizeCompilerMessages(dataFromBuildProgram);\n            var compilerMessageParser = GetCompilerMessageParser();\n\n            var typeNames = matches.Select(m => MissingTypeNameFor(m, compilerMessageParser));\n\n            var assemblyData = Helpers.FindOutputDataAssemblyInfoFor(nodeResult, dataFromBuildProgram);\n            var lines = new NPath(assemblyData.MovedFromExtractorFile).ReadAllLines();\n\n            return typeNames.Any(t => lines.Contains(t));\n\n            CompilerMessageParser GetCompilerMessageParser()\n            {\n                if (!localizedCompilerMessages) return EnglishMessageParser;\n\n                return AlternativeLanguageMessageParser.TargetLanguages.Any(l => l == LocalizationDatabase.currentEditorLanguage)\n                    ? AlternativeLanguageMessageParser\n                    : EnglishMessageParser;\n            }\n\n            static bool IsPotentiallyUpdatableDiagnostic(Match match) => EnglishMessageParser.For(match.Groups[\"id\"].Value) != null;\n        }\n\n        private static string MissingTypeNameFor(Match match, CompilerMessageParser compilerMessageParser)\n        {\n            var typeNameParser = compilerMessageParser.For(match.Groups[\"id\"].Value);\n            if (typeNameParser == null)\n                return null;\n\n            var matchedMessage = typeNameParser.Match(match.Groups[\"message\"].Value);\n            return !matchedMessage.Success ? null : matchedMessage.Groups[\"type_name\"].Value;\n        }\n\n        private static CompilerMessageParser EnglishMessageParser = new(\n            //error CS0117: 'type_name' does not contain a definition for 'member_name'\n            new Regex(\"[^'`“]*['`“](?<type_name>[^'`”]+)['`”][^'`“]+['`“](?<member_name>[^'`”]+)['`”]\", RegexOptions.ExplicitCapture | RegexOptions.Compiled),\n\n            //error CS0234: The type or namespace name 'type_name' does not exist in the namespace 'namespace' (are you missing an assembly reference?)\n            new Regex(\"[^'`]*['`](?<type_name>[^']+)'[^'`]+['`](?<namespace>[^']+)'\",RegexOptions.ExplicitCapture | RegexOptions.Compiled),\n\n            //error CS0246: The type or namespace name 'type_name' could not be found (are you missing a using directive or an assembly reference?)\n            //error CS0103: The name 'type_name' does not exist in the current context\n            new Regex(\"[^'`“]*['`“](?<type_name>[^'`”]+)['`”].*\", RegexOptions.ExplicitCapture | RegexOptions.Compiled),\n            new[] { SystemLanguage.English }\n        );\n\n        // Parses compilers messages for languages that reports CS0234 in the format: text `name space name` text `type name` (for instance, simplified chinese)\n        private static CompilerMessageParser AlternativeLanguageMessageParser = EnglishMessageParser with\n        {\n            MissingType = new Regex(\"([^'`“]*['`“](?<namespace>[^'`”]+)['`”][^'`“]+['`“](?<type_name>[^'`”]+)['`”])\", RegexOptions.ExplicitCapture | RegexOptions.Compiled),\n            TargetLanguages = new[] { SystemLanguage.ChineseTraditional, SystemLanguage.ChineseSimplified, SystemLanguage.Korean }\n        };\n\n        // We have a `CompilerMessageParser` for each language that produces the errors listed in the `EnglishMessageParser` one above\n        // in a different format. For now we only have the `AlternativeLanguageMessageParser` that covers Simplified Chinese,\n        // Traditional Chinese and Korean\n        private record struct CompilerMessageParser(Regex MissingMember, Regex MissingType, Regex UnknownTypeOrNamespace, params SystemLanguage[] TargetLanguages)\n        {\n            public Regex For(string diagnosticId) => diagnosticId switch\n            {\n                \"CS0117\" => MissingMember,\n                \"CS0246\" => UnknownTypeOrNamespace,\n                \"CS0103\" => UnknownTypeOrNamespace,\n                \"CS0234\" => MissingType,\n                _ => null\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/BeeDriver/UnityBeeDriver.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.IO;\nusing System.Linq;\nusing System.Security.Cryptography;\nusing System.Threading.Tasks;\nusing System.Text;\nusing Bee.BeeDriver;\nusing BeeBuildProgramCommon.Data;\nusing NiceIO;\nusing UnityEditor.PackageManager;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing Debug = UnityEngine.Debug;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    static class UnityBeeDriver\n    {\n        internal static readonly string BeeBackendExecutable = new NPath($\"{EditorApplication.applicationContentsPath}/bee_backend{BeeScriptCompilation.ExecutableExtension}\").ToString();\n        internal static readonly string BeeCacheToolExecutable = $\"{EditorApplication.applicationContentsPath}/Tools/BuildPipeline/BeeLocalCacheTool{BeeScriptCompilation.ExecutableExtension}\";\n        internal static readonly string BeeCacheDirEnvVar = \"BEE_CACHE_DIRECTORY\";\n        internal static string BeeCacheDir => Environment.GetEnvironmentVariable(BeeCacheDirEnvVar) ?? new NPath($\"{OSUtil.GetDefaultCachePath()}/bee\").ToString(SlashMode.Native);\n\n        [Serializable]\n        internal class BeeBackendInfo\n        {\n            public string UnityVersion;\n            public string BeeBackendHash;\n        }\n\n        internal static string BeeBackendHash\n        {\n            get\n            {\n                // Using SessionState, that way we won't need to rehash on domain reload.\n                var hash = SessionState.GetString(nameof(BeeBackendHash), string.Empty);\n                if (!string.IsNullOrEmpty(hash))\n                    return hash;\n\n                using var hasher = new SHA256Managed();\n                using var stream = File.OpenRead(BeeBackendExecutable);\n                var bytes = hasher.ComputeHash(stream);\n\n                var sb = new StringBuilder();\n                foreach (var b in bytes)\n                    sb.Append(b.ToString(\"x2\", CultureInfo.InvariantCulture));\n                hash = sb.ToString();\n\n                SessionState.SetString(nameof(BeeBackendHash), hash);\n\n                return hash;\n            }\n        }\n\n        public static BeeBuildProgramCommon.Data.PackageInfo[] GetPackageInfos(string projectDirectory)\n        {\n            return PackageManager.PackageInfo.GetAllRegisteredPackages().Select(p =>\n            {\n                NPath resolvedPath = new NPath(p.resolvedPath);\n                if (resolvedPath.IsChildOf(projectDirectory))\n                    resolvedPath = resolvedPath.RelativeTo(projectDirectory);\n\n                return new BeeBuildProgramCommon.Data.PackageInfo()\n                {\n                    Name = p.name,\n                    ResolvedPath = resolvedPath.ToString(),\n                };\n            }).ToArray();\n        }\n\n        private static void RecreateDagDirectoryIfNeeded(NPath dagDirectory)\n        {\n            var beeBackendInfoPath = dagDirectory.Combine(\"bee_backend.info\");\n            var currentInfo = new BeeBackendInfo()\n            {\n                BeeBackendHash = BeeBackendHash,\n                UnityVersion = Application.unityVersion\n            };\n\n            var diskInfo = new BeeBackendInfo();\n\n            // Clear dag directory if it was produced with a different bee_backend, to avoid problem where bee_backend sometimes looses track of files.\n            if (dagDirectory.Exists())\n            {\n                // When used DeleteMode.Normal, it sometimes was causing an error on Windows:\n                //    Win32Exception: The directory is not empty.\n                //  at NiceIO.NPath + WindowsFileSystem.Directory_Delete(NiceIO.NPath path, System.Boolean recursive)[0x000f4] in C:\\buildslave\\unity\\build\\External\\NiceIO\\NiceIO.cs:1792\n\n                // Since we're recreating a directory anyways, using DeleteMode.Soft should be fine.\n                var deleteMode = DeleteMode.Soft;\n                if (beeBackendInfoPath.Exists())\n                {\n                    var contents = beeBackendInfoPath.ReadAllText();\n                    EditorJsonUtility.FromJsonOverwrite(contents, diskInfo);\n\n                    // Note: We're clearing dag directory only when bee backend hash has changed, it's fine for Unity version to be different.\n                    //       Unity version is used here for informational purposes, so we can clearly see from which Unity version the user was upgrading\n                    if (string.IsNullOrEmpty(diskInfo.BeeBackendHash) ||\n                        !diskInfo.BeeBackendHash.Equals(currentInfo.BeeBackendHash))\n                    {\n                        Console.WriteLine($\"Clearing Bee directory '{dagDirectory}', since bee backend hash ('{beeBackendInfoPath}') is different, previous hash was {diskInfo.BeeBackendHash} (Unity version: {diskInfo.UnityVersion}), current hash is {currentInfo.BeeBackendHash} (Unity version: {currentInfo.UnityVersion}).\");\n                        dagDirectory.Delete(deleteMode);\n                    }\n                }\n                else\n                {\n                    Console.WriteLine($\"Clearing Bee directory '{dagDirectory}', since bee backend information ('{beeBackendInfoPath}') is missing.\");\n                    dagDirectory.Delete(deleteMode);\n                }\n            }\n\n            dagDirectory.CreateDirectory();\n\n            // Update info, if at least of one the fields is different\n            if (string.IsNullOrEmpty(diskInfo.BeeBackendHash) ||\n                string.IsNullOrEmpty(diskInfo.UnityVersion) ||\n                !diskInfo.BeeBackendHash.Equals(currentInfo.BeeBackendHash) ||\n                !diskInfo.UnityVersion.Equals(currentInfo.UnityVersion))\n            {\n                beeBackendInfoPath.WriteAllText(EditorJsonUtility.ToJson(currentInfo, true));\n            }\n        }\n\n        public static BuildRequest BuildRequestFor(RunnableProgram buildProgram, EditorCompilation editorCompilation, string dagName, CacheMode cacheMode, string dagDirectory = null, bool useScriptUpdater = true)\n        {\n            return BuildRequestFor(buildProgram, dagName, dagDirectory, useScriptUpdater, editorCompilation.projectDirectory, new ILPostProcessingProgram(), cacheMode, StdOutModeForScriptCompilation);\n        }\n\n        public const StdOutMode StdOutModeForScriptCompilation =\n            StdOutMode.LogStartArgumentsAndExitcode | StdOutMode.LogStdOutOnFinish;\n        public const StdOutMode StdOutModeForPlayerBuilds =\n            StdOutMode.LogStartArgumentsAndExitcode | StdOutMode.Stream;\n\n        public static BuildRequest BuildRequestFor(\n                RunnableProgram buildProgram,\n                string dagName,\n                string dagDirectory,\n                bool useScriptUpdater,\n                NPath projectDirectory,\n                ILPostProcessingProgram ilpp,\n                CacheMode cacheMode,\n                StdOutMode stdoutMode,\n                RunnableProgram beeBackendProgram = null)\n        {\n            // ensure ilpp server is running before staring the backend in defered validation mode.\n            // getting the property value enforces that as it makes sure the server is running and answering a ping request\n            var ilppNamedPipeOrSocket = ilpp.EnsureRunningAndGetSocketOrNamedPipe();\n\n            NPath dagDir = dagDirectory ?? projectDirectory.Combine(\"Library/Bee\");\n            RecreateDagDirectoryIfNeeded(dagDir);\n            var performingPlayerBuild = UnityBeeDriverProfilerSession.PerformingPlayerBuild;\n            NPath profilerOutputFile =  performingPlayerBuild ? UnityBeeDriverProfilerSession.GetTraceEventsOutputForPlayerBuild() : $\"{dagDir}/fullprofile.json\";\n            return new BuildRequest()\n            {\n                BuildProgram = buildProgram,\n                BackendProgram = beeBackendProgram ?? UnityBeeBackendProgram(cacheMode, stdoutMode),\n                ProjectRoot = projectDirectory.ToString(),\n                DagName = dagName,\n                BuildStateDirectory = dagDir.EnsureDirectoryExists().ToString(),\n                ProfilerOutputFile = profilerOutputFile.ToString(),\n                // Use a null process name during a player build to avoid writing process metadata.  The player profiler will take care of writing the process metadata\n                ProfilerProcessName = performingPlayerBuild ? null : \"BeeDriver\",\n                SourceFileUpdaters = useScriptUpdater\n                    ? new[] {new UnityScriptUpdater(projectDirectory)}\n                    : Array.Empty<SourceFileUpdaterBase>(),\n                ProcessSourceFileUpdatersResult = new UnitySourceFileUpdatersResultHandler(),\n\n                DataForBuildProgram =\n                {\n                    () => new ConfigurationData\n            {\n                Il2CppDir = IL2CPPUtils.GetIl2CppFolder(),\n                Il2CppPath = IL2CPPUtils.GetExePath(\"il2cpp\"),\n                UnityLinkerPath = IL2CPPUtils.GetExePath(\"UnityLinker\"),\n                NetCoreRunPath = NetCoreRunProgram.NetCoreRunPath,\n                DotNetExe = NetCoreProgram.DotNetMuxerPath.ToString(),\n                EditorContentsPath = EditorApplication.applicationContentsPath,\n                Packages = GetPackageInfos(NPath.CurrentDirectory.ToString()),\n                UnityVersion = Application.unityVersion,\n                UnityVersionNumeric = new BeeBuildProgramCommon.Data.Version(Application.unityVersionVer, Application.unityVersionMaj, Application.unityVersionMin),\n                UnitySourceCodePath = Unsupported.IsSourceBuild(false) ? Unsupported.GetBaseUnityDeveloperFolder() : null,\n                Batchmode = InternalEditorUtility.inBatchMode,\n                EmitDataForBeeWhy = (Debug.GetDiagnosticSwitch(\"EmitDataForBeeWhy\").value as bool?)?? false,\n                        NamedPipeOrUnixSocket = ilppNamedPipeOrSocket,\n                    }\n                }\n            };\n        }\n\n        public static void RunCleanBeeCache(NPath cacheDir = null, long cacheSize = -1, bool runAsync = true)\n        {\n            // Note that cacheSize is specified as the total number of used bytes\n            // for all the files in the cache and not as the actual size of occupied\n            // blocks on the disk, which will add some overhead.\n            if (cacheSize < 0)\n                cacheSize = 256 * 1024 * 1024;\n\n            if (cacheDir == null)\n                cacheDir = BeeCacheDir;\n\n            if (runAsync)\n                Task.Run(() => RunCleanBeeCacheInternal(cacheDir, cacheSize));\n            else\n                RunCleanBeeCacheInternal(cacheDir, cacheSize);\n        }\n\n        private static void RunCleanBeeCacheInternal(NPath beeCacheDir, long targetCacheSize)\n        {\n            if (targetCacheSize < 0)\n                throw new ArgumentOutOfRangeException($\"targetCacheSize should be >= 0, got {targetCacheSize}\");\n\n            var sw = new Stopwatch();\n            sw.Start();\n\n            NPath trashDir = beeCacheDir.Combine(\"trash\");\n            trashDir.EnsureDirectoryExists();\n\n            long cacheSize = 0;\n\n            List<CacheEntry> cacheEntries = new List<CacheEntry>();\n            foreach (var subdir in beeCacheDir.Directories())\n            {\n                if (subdir.Equals(trashDir))\n                    continue;\n\n                // Each subdirectory corresponds to a deepcache entry, with the\n                // cache lookup key as the directory name. Files inside those\n                // subdirectories are the blobs referred to by the cache lookup.\n                CacheEntry entry = new(subdir);\n                foreach (var f in subdir.Files())\n                {\n                    var fileSize = f.GetFileSize();\n                    entry.Size += fileSize;\n                    entry.Timestamp = Math.Max(entry.Timestamp,\n                        new DateTimeOffset(f.GetLastWriteTimeUtc()).ToUnixTimeSeconds());\n                }\n                cacheSize += entry.Size;\n                cacheEntries.Add(entry);\n            }\n            Console.WriteLine($\"Total cache size {cacheSize}\");\n\n            foreach (var entry in cacheEntries.OrderBy(x => x.Timestamp))\n            {\n                if (cacheSize <= targetCacheSize)\n                    break;\n\n                cacheSize -= entry.Size;\n                entry.Path.Move(trashDir.Combine(entry.Path.FileName));\n            }\n\n            trashDir.Delete();\n\n            Console.WriteLine($\"Total cache size after purge {cacheSize}, took {sw.Elapsed}\");\n        }\n\n        private record struct CacheEntry {\n            public NPath Path;     // directory\n            public long Size;      // sum of file sizes in the directory\n            public long Timestamp; // most recent file mtime in the directory\n\n            public CacheEntry(NPath p)\n            {\n                Path = p;\n                Size = 0;\n                Timestamp = 0;\n            }\n        }\n\n        public enum CacheMode\n        {\n            Off,\n            ReadOnly,\n            WriteOnly,\n            ReadWrite,\n        }\n\n        internal static RunnableProgram UnityBeeBackendProgram(CacheMode cacheMode, StdOutMode stdoutMode)\n        {\n            var env = new Dictionary<string, string>()\n            {\n                { \"BEE_CACHE_BEHAVIOUR\", cacheMode switch\n                {\n                    CacheMode.Off => \"_\",\n                    CacheMode.ReadOnly => \"R\",\n                    CacheMode.WriteOnly => \"W\",\n                    CacheMode.ReadWrite => \"RW\",\n                    _ => throw new ArgumentOutOfRangeException(nameof(cacheMode), cacheMode, null)\n                }},\n                { \"CACHE_SERVER_ADDRESS\", \"none_but_bee_still_wants_us_to_set_it\" },\n                { \"REAPI_CACHE_CLIENT\", $\"\\\"{BeeCacheToolExecutable}\\\"\" },\n                { BeeCacheDirEnvVar, BeeCacheDir },\n                { \"CHROMETRACE_TIMEOFFSET\", \"unixepoch\" }\n            };\n            return new SystemProcessRunnableProgram(BeeBackendExecutable,\n                alwaysEnvironmentVariables: env,\n                stdOutMode: stdoutMode);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/BeeDriver/UnityBeeDriverProfilerSession.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\nusing Bee.Core;\nusing NiceIO;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    static class UnityBeeDriverProfilerSession\n    {\n        private static NPath m_CurrentPlayerBuildProfilerOutputFile;\n        private static int m_BeeDriverForCurrentPlayerBuildIndex;\n        private static TinyProfiler2 _tinyProfiler;\n        private static Stack<IDisposable> m_ProfilerSections = new Stack<IDisposable>();\n        private static List<Task> m_TasksToWaitForBeforeFinishing = new();\n\n        public static TinyProfiler2 ProfilerInstance => _tinyProfiler;\n\n        static public void Start(NPath path)\n        {\n            m_CurrentPlayerBuildProfilerOutputFile = path;\n            m_BeeDriverForCurrentPlayerBuildIndex = 0;\n            m_TasksToWaitForBeforeFinishing.Clear();\n            _tinyProfiler = new TinyProfiler2();\n        }\n\n        static public void Finish()\n        {\n            if (m_CurrentPlayerBuildProfilerOutputFile == null)\n                return;\n\n            foreach (var task in m_TasksToWaitForBeforeFinishing)\n                task.Wait();\n\n            _tinyProfiler.Write(m_CurrentPlayerBuildProfilerOutputFile.ToString(), new ChromeTraceOptions\n            {\n                ProcessName = \"Unity\",\n                ProcessId = System.Diagnostics.Process.GetCurrentProcess().Id,\n                ProcessSortIndex = -100\n            });\n            m_CurrentPlayerBuildProfilerOutputFile = null;\n            _tinyProfiler = null;\n        }\n\n        static public void BeginSection(string name)\n        {\n            if (m_CurrentPlayerBuildProfilerOutputFile != null)\n            {\n                m_ProfilerSections.Push(_tinyProfiler.Section(name));\n            }\n        }\n\n        static public void EndSection()\n        {\n            if (m_CurrentPlayerBuildProfilerOutputFile != null)\n            {\n                m_ProfilerSections.Pop().Dispose();\n            }\n        }\n\n        static public void AddTaskToWaitForBeforeFinishing(Task t) => m_TasksToWaitForBeforeFinishing.Add(t);\n        \n        static public bool PerformingPlayerBuild => m_CurrentPlayerBuildProfilerOutputFile != null;\n\n        static public NPath GetTraceEventsOutputForPlayerBuild()\n        {\n            if (!PerformingPlayerBuild)\n                throw new ArgumentException();\n\n            NPath path = $\"{m_CurrentPlayerBuildProfilerOutputFile.Parent}/{m_CurrentPlayerBuildProfilerOutputFile.FileName}_{m_BeeDriverForCurrentPlayerBuildIndex++}.traceevents\";\n            _tinyProfiler.AddExternalTraceEventsFile(path.ToString());\n            return path;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/BeeDriver/UnityScriptUpdater.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing System.Text.RegularExpressions;\nusing Bee.BeeDriver;\nusing Bee.Serialization;\nusing NiceIO;\nusing ScriptCompilationBuildProgram.Data;\nusing UnityEditor.Scripting.Compilers;\nusing UnityEditorInternal.APIUpdating;\nusing Bee.BinLog;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    class UnityScriptUpdater : SourceFileUpdaterBase\n    {\n        readonly string _configurationSourcesFilter;\n        NPath ProjectRoot { get; }\n        RunnableProgram _scriptUpdaterProgram { get; }\n\n        // this is the return code used by ScriptUpdater to report that\n        // some updates were not applied.\n        const int k_UpdatesToFilesInSameProjectWereNotApplied = 3;\n\n        public UnityScriptUpdater(NPath projectRoot)\n        {\n            ProjectRoot = projectRoot;\n            _scriptUpdaterProgram = DefaultScriptUpdaterProgram();\n            _configurationSourcesFilter = APIUpdaterManager.ConfigurationSourcesFilter;\n        }\n\n        static RunnableProgram DefaultScriptUpdaterProgram()\n        {\n            NPath scriptUpdaterExe = $\"{EditorApplication.applicationContentsPath}/Tools/Compilation/ApiUpdater/ScriptUpdater.dll\";\n            return new SystemProcessRunnableProgram(NetCoreRunProgram.NetCoreRunPath, new[] {scriptUpdaterExe.InQuotes()}, stdOutMode: StdOutMode.LogStdOutOnFinish);\n        }\n\n        enum CanUpdateAny\n        {\n            Certainly,\n            Maybe,\n            No,\n        }\n\n        static CanUpdateAny ContainsUpdatableCompilerMessage(NodeFinishedMessage nodeResult, ObjectsFromDisk dataFromBuildProgram)\n        {\n            if (!nodeResult.Node.Annotation.StartsWith(\"Csc\"))\n                return CanUpdateAny.No;\n\n            var compilerMessages = BeeScriptCompilation.ParseCompilerOutput(nodeResult);\n\n            bool IsOnlyMessageForThisFileLineAndColumn(CompilerMessage compilerMessage)\n            {\n                //we want to see if this is the only error on this location.  we will make an enumerable that matches all compilermessages that match this location\n                //We do Skip(1).Any() as a bit of an unconventional way to express what we care about: is there more than 1 or not.\n                return !compilerMessages.Where(m => MatchesFileLineAndColumn(compilerMessage, m)).Skip(1).Any();\n            }\n\n            var upgradableMessages = compilerMessages.Where(c => c.message.Contains(\"(UnityUpgradable\")).ToArray();\n\n            //Some (UnityUpgradable) errors can be paired with a genuine user error on the same line/column. When this happens it is a known problem\n            //that we are unable to upgrade the UnityUpgradable error. So we'll only return Certainly if there is not an other compilermessage pointing to the\n            //same file,line,column. otherwise, we return maybe, so that a failure to do the update won't print a console message saying there is a bug.\n            if (upgradableMessages.Any(IsOnlyMessageForThisFileLineAndColumn))\n                return CanUpdateAny.Certainly;\n            if (upgradableMessages.Any())\n                return CanUpdateAny.Maybe;\n\n            //The \"unknown type or namespace\" genre of messages we are not sure about. Some of these are legit user programming errors, some of them\n            //are caused because we moved/renamed a type. In this case we will run the script updater to figure out, and if no updates were produced then\n            //apparently it was a real user programming mistake instead of an updatable error;\n            if (PotentiallyUpdatableErrorMessages.IsAnyPotentiallyUpdatable(compilerMessages, nodeResult, dataFromBuildProgram))\n                return CanUpdateAny.Maybe;\n\n            return CanUpdateAny.No;\n        }\n\n        private static bool MatchesFileLineAndColumn(CompilerMessage m, CompilerMessage compilerMessage)\n        {\n            return m.column == compilerMessage.column && m.line == compilerMessage.line && m.file == compilerMessage.file;\n        }\n\n        public override Task<Results> StartIfYouCanFixProblemsInTheseMessages(in NodeFinishedMessage nodeResult,\n            ObjectsFromDisk dataFromBuildProgram, CancellationToken cancellationToken)\n        {\n            var nodeFinishedMessage = nodeResult;\n\n            var containsUpdatableCompilerMessage = ContainsUpdatableCompilerMessage(nodeFinishedMessage, dataFromBuildProgram);\n            if (containsUpdatableCompilerMessage == CanUpdateAny.No)\n                return Task.FromResult(Results.Empty);\n\n            var assemblyInfo = Helpers.FindOutputDataAssemblyInfoFor(nodeFinishedMessage, dataFromBuildProgram);\n\n            var tempOutputDirectory = new NPath($\"Temp/ScriptUpdater/{Math.Abs(nodeFinishedMessage.Node.OutputFile.GetHashCode())}\").EnsureDirectoryExists();\n            var updateTxtFile = tempOutputDirectory.MakeAbsolute().Combine(\"updates.txt\").DeleteIfExists();\n            var updaterMessagesToConsoleFile = tempOutputDirectory.MakeAbsolute().Combine($\"messages_{new Random().Next()}.txt\").DeleteIfExists();\n\n            var args = new[]\n            {\n                $\"\\\"{EditorApplication.applicationContentsPath}\\\"\",\n                $\"\\\"{tempOutputDirectory}\\\"\",\n                $\"\\\"{_configurationSourcesFilter}\\\"\",\n                assemblyInfo.ScriptUpdaterRsp.ToNPath().InQuotes(),\n                updaterMessagesToConsoleFile.InQuotes()\n            };\n\n            var runningScriptUpdater = _scriptUpdaterProgram.Start(ProjectRoot.ToString(), args);\n\n            return AwaitScriptUpdaterResults(runningScriptUpdater, updateTxtFile, updaterMessagesToConsoleFile, containsUpdatableCompilerMessage, nodeFinishedMessage.Node.OutputFile, assemblyInfo);\n        }\n\n        async Task<Results> AwaitScriptUpdaterResults(RunningProgram runningScriptUpdater, NPath updateTxtFile, NPath updaterMessagesToConsoleFile, CanUpdateAny containsUpdatableCompilerMessage, string nodeOutputFile, AssemblyData_Out assemblyInfo)\n        {\n            //when the user asks us to cancel a build, we do not want to leave stray unity script updaters laying around. we will\n            //just wait for them to finish.\n            var noToken = CancellationToken.None;\n            var scriptUpdaterResult = await runningScriptUpdater.WaitForExitAsync(noToken);\n\n            var messages = ResultsFromUpdaterImportantMessages(updaterMessagesToConsoleFile);\n            if (scriptUpdaterResult.ExitCode == k_UpdatesToFilesInSameProjectWereNotApplied)\n            {\n                return CollectResultsIfAny(messages, nodeOutputFile, updateTxtFile, CanUpdateAny.Maybe);\n            }\n            else if (scriptUpdaterResult.ExitCode != 0)\n                return ErrorResult($\"Script updater for {nodeOutputFile} failed with exitcode {scriptUpdaterResult.ExitCode} and stdout: {scriptUpdaterResult.Output}\");\n\n            if (!updateTxtFile.FileExists())\n            {\n                return WarningResult($\"Script updater for {nodeOutputFile} failed to produce updates.txt file (response file: {assemblyInfo.ScriptUpdaterRsp}, MovedFromCache: {assemblyInfo.MovedFromExtractorFile}\");\n            }\n\n            return CollectResultsIfAny(messages, nodeOutputFile, updateTxtFile, containsUpdatableCompilerMessage);\n\n            static Results ErrorResult(string message) => new()\n            {\n                Messages = new[] {new BeeDriverResult.Message(message, BeeDriverResult.MessageKind.Error)},\n                ProducedUpdates = Array.Empty<Update>()\n            };\n\n            static Results WarningResult(string message) => new()\n            {\n                Messages = new[] {new BeeDriverResult.Message(message, BeeDriverResult.MessageKind.Warning)},\n                ProducedUpdates = Array.Empty<Update>()\n            };\n\n            BeeDriverResult.Message[] ResultsFromUpdaterImportantMessages(NPath updaterMessagesToConsoleFile)\n            {\n                try\n                {\n                    var lines = Regex.Split(updaterMessagesToConsoleFile.ReadAllText(), \"^(?<kind>Warning|Error):\", RegexOptions.Multiline, TimeSpan.FromSeconds(5));\n                    if (lines.Length <= 1) // first split line is always empty..\n                        return Array.Empty<BeeDriverResult.Message>();\n\n                    // first line = warning/error, second line = actual message\n                    var messages = new List<BeeDriverResult.Message>((lines.Length - 1)/2);\n                    for (int i = 1; i < lines.Length; i+=2)\n                    {\n                        var messageKind = lines[i] switch\n                        {\n                            \"Error\" => BeeDriverResult.MessageKind.Error,\n                            \"Warning\" => BeeDriverResult.MessageKind.Warning,\n                            _ => BeeDriverResult.MessageKind.Warning,\n                        };\n                        messages.Add(new BeeDriverResult.Message(lines[i + 1], messageKind));\n                    }\n\n                    return messages.ToArray();\n                }\n                catch(System.IO.IOException)\n                {\n                    return Array.Empty<BeeDriverResult.Message>();\n                }\n            }\n\n            static Results CollectResultsIfAny(BeeDriverResult.Message[] messages, string nodeOutputFile, NPath updateTxtFile, CanUpdateAny containsUpdatableCompilerMessage)\n            {\n                var updates = Array.Empty<Update>();\n                if (updateTxtFile.FileExists())\n                {\n                    var updateLines = updateTxtFile.ReadAllLines();\n\n                    updates = updateLines.Select(ParseLineIntoUpdate).ToArray();\n                    if (updates.Contains(null))\n                        return ErrorResult($\"Script updater for {nodeOutputFile} emitted an invalid line to {updateTxtFile}\");\n\n                    if (containsUpdatableCompilerMessage == CanUpdateAny.Certainly && updates.Length == 0)\n                    {\n                        var temp = new List<BeeDriverResult.Message>(messages);\n                        temp.Add(new BeeDriverResult.Message($\"Script updater for {nodeOutputFile} expected to be able to make an update, but wasn't able to\", BeeDriverResult.MessageKind.Warning));\n                        messages = temp.ToArray();\n                    }\n                }\n\n                return new Results()\n                {\n                    Messages = messages,\n                    ProducedUpdates = updates\n                };\n            }\n        }\n\n        internal static Update ParseLineIntoUpdate(string line)\n        {\n            var separator = \" => \";\n            var indexOfSeparator = line.IndexOf(separator, StringComparison.InvariantCulture);\n            if (indexOfSeparator == -1)\n                return null;\n\n            return new Update()\n            {\n                tempFileWithNewContents = line[..indexOfSeparator],\n                originalFileWithError = line[(indexOfSeparator + separator.Length)..]\n            };\n        }\n    }\n\n    static class Helpers\n    {\n        public static AssemblyData_Out FindOutputDataAssemblyInfoFor(NodeFinishedMessage nodeResult, ObjectsFromDisk dataFromBuildProgram)\n        {\n            var scriptCompilationDataOut = dataFromBuildProgram.Get<ScriptCompilationData_Out>();\n            var outputfileForwardSlash = new NPath(nodeResult.Node.OutputFile).ToString();\n            var assemblyDataOut = scriptCompilationDataOut.Assemblies.FirstOrDefault(a => a.Path == outputfileForwardSlash);\n            return assemblyDataOut ?? throw new ArgumentException($\"Unable to find entry for {outputfileForwardSlash} in dataFromBuildProgram\");\n        }\n\n        public static bool LocalizeCompilerMessages(ObjectsFromDisk dataFromBuildProgram)\n        {\n            var scriptCompilationDataOut = dataFromBuildProgram.Get<ScriptCompilationData_Out>();\n            return scriptCompilationDataOut.LocalizeCompilerMessages;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/BeeDriver/UnityScriptUpdaterConsentAPI.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing UnityEditorInternal.APIUpdating;\n\nnamespace UnityEditor.ScriptUpdater\n{\n    class UnityScriptUpdaterConsentAPI\n    {\n        public UnitySourceFileUpdatersResultHandler.ScriptUpdaterConsentType AskFor(string[] filesToOverWrite)\n        {\n            APIUpdaterManager.numberOfTimesAsked = APIUpdaterManager.numberOfTimesAsked + 1;\n\n            if (APIUpdaterManager.isInProjectCreation)\n            {\n                Console.WriteLine(\"Skipping ScriptUpdater consent dialog because we are in project creation mode.\");\n                return UnitySourceFileUpdatersResultHandler.ScriptUpdaterConsentType.ConsentForRestOfCompilation;\n            }\n\n            if (APIUpdaterManager.DoesCommandLineIndicateAPIUpdatingShouldBeDeclined())\n            {\n                Console.WriteLine(\n                    \"Skipping ScriptUpdater consent dialog. Consent declined based on command line parameters.\");\n                return UnitySourceFileUpdatersResultHandler.ScriptUpdaterConsentType.NoConsent;\n            }\n\n            if (APIUpdaterManager.DoesCommandLineIndicateAPIUpdatingShouldHappenWithoutConsent())\n            {\n                Console.WriteLine(\n                    \"Skipping ScriptUpdater consent dialog. Consent given based on command line parameters.\");\n                return UnitySourceFileUpdatersResultHandler.ScriptUpdaterConsentType.ConsentForRestOfCompilation;\n            }\n\n            return AskThroughDialog(filesToOverWrite);\n        }\n\n        private static UnitySourceFileUpdatersResultHandler.ScriptUpdaterConsentType AskThroughDialog(string[] filesToOverWrite)\n        {\n            var selection = filesToOverWrite.Take(30).ToArray();\n            var displayedFiles = selection.SeparateWith(Environment.NewLine);\n            var omitted = filesToOverWrite.Length - selection.Length;\n            if (omitted > 0)\n                displayedFiles = displayedFiles + $\"\\n<+{omitted} more files>\";\n\n            var caption =\n                $\"Some of this projects source files refer to API that has changed. These can be automatically updated. It is recommended to have a backup of the project before updating. Do you want these files to be updated?\\n\\n{displayedFiles}\";\n            var result = EditorUtility.DisplayDialogComplex(\"Script Updating Consent\", caption,\n                \"Yes, for these and other files that might be found later\", \"No\", \"Yes, just for these files\");\n            switch (result)\n            {\n                case 0:\n                    return UnitySourceFileUpdatersResultHandler.ScriptUpdaterConsentType.ConsentForRestOfCompilation;\n                case 1:\n                    return UnitySourceFileUpdatersResultHandler.ScriptUpdaterConsentType.NoConsent;\n                case 2:\n                    return UnitySourceFileUpdatersResultHandler.ScriptUpdaterConsentType.ConsentOnce;\n                default:\n                    throw new ArgumentOutOfRangeException();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/BeeDriver/UnitySourceFileUpdatersResultHandler.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading;\nusing Bee.BeeDriver;\nusing NiceIO;\nusing UnityEditor.PackageManager;\nusing UnityEditor.ScriptUpdater;\nusing UnityEditorInternal.APIUpdating;\nusing UnityEngine;\nusing System.Threading.Tasks;\nusing UnityEditorInternal;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    class UnitySourceFileUpdatersResultHandler : SourceFileUpdatersResultHandler\n    {\n        bool m_HaveConsentToOverwriteUserScripts;\n\n        readonly UnityScriptUpdaterConsentAPI ConstentAPI;\n\n        public UnitySourceFileUpdatersResultHandler() : base(captureSynchronizationContext: true)\n        {\n            ConstentAPI = new UnityScriptUpdaterConsentAPI();\n\n            if (!InternalEditorUtility.CurrentThreadIsMainThread())\n                throw new Exception($\"{nameof(UnitySourceFileUpdatersResultHandler)} can only be created on the main thread\");\n        }\n\n\n        protected override bool ProcessUpdaterResults(SourceFileUpdaterBase.Update[] updates)\n        {\n            var problemUpdates = new List<(SourceFileUpdaterBase.Update update, Exception exception)>();\n            bool didUpdate = false;\n            void ExecuteUpdates(IEnumerable<SourceFileUpdaterBase.Update> updates)\n            {\n                foreach (var update in updates)\n                {\n                    didUpdate = true;\n                    try\n                    {\n                        Console.WriteLine(update.originalFileWithError);\n                        new NPath(update.tempFileWithNewContents).Copy(update.originalFileWithError);\n                    }\n                    catch (Exception e)\n                    {\n                        problemUpdates.Add((update, e));\n                    }\n                }\n            }\n\n            var libraryPackageCache = \"Library/PackageCache/\";\n            var(immutablePackageUpdates, nonImmutableUpdates) = updates.SplitBy(u => u.originalFileWithError.StartsWith(libraryPackageCache));\n\n            Console.WriteLine(\"[API Updater] Updated Files:\");\n            if (immutablePackageUpdates.Any())\n            {\n                var immutablePackageFiles = immutablePackageUpdates.Select(u => u.originalFileWithError).ToArray();\n                APIUpdaterHelper.HandlePackageFilePaths(immutablePackageFiles);\n                ExecuteUpdates(immutablePackageUpdates);\n            }\n\n            if (nonImmutableUpdates.Any())\n            {\n                var nonImmutableTargetFiles = nonImmutableUpdates.Select(u => u.originalFileWithError).ToArray();\n\n                if (MayOverwrite(nonImmutableTargetFiles) && PrepareForOverwritingUpdatedFiles(nonImmutableTargetFiles))\n                    ExecuteUpdates(nonImmutableUpdates);\n            }\n\n            if (problemUpdates.Any())\n            {\n                var sb = new StringBuilder();\n                sb.AppendLine(\"Unable to update the following files. Are they marked readonly?\");\n                foreach (var problem in problemUpdates)\n                    sb.AppendLine(problem.update.originalFileWithError + \" \" + problem.exception.Message);\n\n                Debug.LogError(sb.ToString());\n            }\n\n            Console.WriteLine(\"Finished running ScriptUpdaters\");\n            return didUpdate;\n        }\n\n        bool MayOverwrite(string[] files)\n        {\n            if (m_HaveConsentToOverwriteUserScripts)\n                return true;\n            var result = ConstentAPI.AskFor(files);\n            switch (result)\n            {\n                case ScriptUpdaterConsentType.ConsentOnce:\n                    return true;\n                case ScriptUpdaterConsentType.ConsentForRestOfCompilation:\n                    m_HaveConsentToOverwriteUserScripts = true;\n                    return true;\n                case ScriptUpdaterConsentType.NoConsent:\n                    return false;\n                default:\n                    throw new ArgumentOutOfRangeException();\n            }\n        }\n\n        bool PrepareForOverwritingUpdatedFiles(string[] destFiles)\n        {\n            if (!APIUpdaterManager.WaitForVCSServerConnection())\n            {\n                //if we fail to connect to the vcs server, we shouldn't overwrite versioned files.\n                //in this case we will just not do that, continue the build as normal. We have protection for only trying to script update\n                //an assembly once, and the resulting behaviour will be that the user just gets to see the compiler errors and needs to fix\n                //them herself.\n                return false;\n            }\n\n            if (!AssetDatabase.MakeEditable(destFiles))\n            {\n                Debug.LogError($\"Failed to make VCS provider make the scripts to be update editable.{Environment.NewLine}\" + string.Join(Environment.NewLine, destFiles.Select(d => d.ToString())));\n                return false;\n            }\n\n            return true;\n        }\n\n        internal enum ScriptUpdaterConsentType\n        {\n            ConsentOnce,\n            ConsentForRestOfCompilation,\n            NoConsent\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/CompilationPipeline.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.Scripting.ScriptCompilation;\nusing System.Linq;\nusing UnityEditor.Scripting.Compilers;\nusing sc = UnityEditor.Scripting.ScriptCompilation;\nusing UnityEditorInternal;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Compilation\n{\n    [Flags]\n    public enum AssemblyFlags\n    {\n        None = 0,\n        EditorAssembly = (1 << 0)\n    }\n\n    [Flags]\n    public enum RequestScriptCompilationOptions\n    {\n        None,\n        CleanBuildCache\n    }\n\n    public class ScriptCompilerOptions\n    {\n        public string RoslynAnalyzerRulesetPath { get; set; }\n        public string[] RoslynAnalyzerDllPaths { get; set; }\n        public string[] RoslynAdditionalFilePaths { get; set; }\n        public string AnalyzerConfigPath {get; set;}\n        public bool AllowUnsafeCode { get; set; }\n\n        [Obsolete(\"Use of reference assemblies is always enabled\", true)]\n        public bool EmitReferenceAssembly\n        {\n            get { throw new NotImplementedException(\"Use of reference assemblies is always enabled\"); }\n            set { throw new NotImplementedException(\"Use of reference assemblies is always enabled\"); }\n        }\n\n        internal bool UseDeterministicCompilation { get; set; }\n        public string[] AdditionalCompilerArguments { get; set; }\n        public CodeOptimization CodeOptimization { get; set; }\n        public ApiCompatibilityLevel ApiCompatibilityLevel { get; set; }\n        public EditorAssembliesCompatibilityLevel EditorAssembliesCompatibilityLevel { get; set; }\n        public string[] ResponseFiles { get; set; }\n        public string LanguageVersion { get; internal set; } // Requires a refresh sent to the Code Editor package if made public\n\n        public ScriptCompilerOptions()\n        {\n            AllowUnsafeCode = false;\n            ApiCompatibilityLevel = ApiCompatibilityLevel.NET_Unity_4_8;\n            EditorAssembliesCompatibilityLevel = EditorAssembliesCompatibilityLevel.Default;\n            ResponseFiles = new string[0];\n            RoslynAnalyzerDllPaths = new string[0];\n            RoslynAdditionalFilePaths = new string[0];\n            LanguageVersion = \"9.0\";\n        }\n\n        internal ScriptCompilerOptions(ScriptCompilerOptions scriptCompilerOptions)\n        {\n            ResponseFiles = new List<string>(scriptCompilerOptions.ResponseFiles).ToArray();\n            RoslynAnalyzerDllPaths = new List<string>(scriptCompilerOptions.RoslynAnalyzerDllPaths).ToArray();\n            RoslynAnalyzerRulesetPath = scriptCompilerOptions.RoslynAnalyzerRulesetPath;\n            AnalyzerConfigPath = scriptCompilerOptions.AnalyzerConfigPath;\n            RoslynAdditionalFilePaths = scriptCompilerOptions.RoslynAdditionalFilePaths;\n            UseDeterministicCompilation = scriptCompilerOptions.UseDeterministicCompilation;\n            AllowUnsafeCode = scriptCompilerOptions.AllowUnsafeCode;\n            CodeOptimization = scriptCompilerOptions.CodeOptimization;\n            ApiCompatibilityLevel = scriptCompilerOptions.ApiCompatibilityLevel;\n            EditorAssembliesCompatibilityLevel = scriptCompilerOptions.EditorAssembliesCompatibilityLevel;\n            AdditionalCompilerArguments = scriptCompilerOptions.AdditionalCompilerArguments;\n            LanguageVersion = scriptCompilerOptions.LanguageVersion;\n        }\n    }\n\n    public enum AssembliesType\n    {\n        Editor = 0,\n        Player = 1,\n        PlayerWithoutTestAssemblies = 2,\n    }\n\n    public enum AssemblyDefinitionReferenceType\n    {\n        Name = 0,\n        Guid = 1\n    }\n\n    public enum CodeOptimization\n    {\n        None = 0,\n        Debug = 1,\n        Release = 2\n    }\n\n    public class Assembly\n    {\n        public string name { get; private set; }\n        public string rootNamespace { get; private set; }\n        public string outputPath { get; private set; }\n        public string[] sourceFiles { get; private set; }\n        public string[] defines { get; private set; }\n        public Assembly[] assemblyReferences { get; internal set; }\n        public string[] compiledAssemblyReferences { get; private set; }\n        public AssemblyFlags flags { get; private set; }\n        public ScriptCompilerOptions compilerOptions { get; internal set; }\n\n        public string[] allReferences { get { return assemblyReferences.Select(a => a.outputPath).Concat(compiledAssemblyReferences).ToArray(); } }\n\n        public Assembly(string name,\n                        string outputPath,\n                        string[] sourceFiles,\n                        string[] defines,\n                        Assembly[] assemblyReferences,\n                        string[] compiledAssemblyReferences,\n                        AssemblyFlags flags)\n            : this(name,\n            outputPath,\n            sourceFiles,\n            defines,\n            assemblyReferences,\n            compiledAssemblyReferences,\n            flags,\n            new ScriptCompilerOptions(),\n            string.Empty)\n        {\n        }\n\n        public Assembly(string name,\n                        string outputPath,\n                        string[] sourceFiles,\n                        string[] defines,\n                        Assembly[] assemblyReferences,\n                        string[] compiledAssemblyReferences,\n                        AssemblyFlags flags,\n                        ScriptCompilerOptions compilerOptions)\n            : this(name,\n            outputPath,\n            sourceFiles,\n            defines,\n            assemblyReferences,\n            compiledAssemblyReferences,\n            flags,\n            compilerOptions,\n            string.Empty)\n        {\n        }\n\n        public Assembly(string name,\n                        string outputPath,\n                        string[] sourceFiles,\n                        string[] defines,\n                        Assembly[] assemblyReferences,\n                        string[] compiledAssemblyReferences,\n                        AssemblyFlags flags,\n                        ScriptCompilerOptions compilerOptions,\n                        string rootNamespace)\n        {\n            this.name = name;\n            this.outputPath = outputPath;\n            this.sourceFiles = sourceFiles;\n            this.defines = defines;\n            this.assemblyReferences = assemblyReferences;\n            this.compiledAssemblyReferences = compiledAssemblyReferences;\n            this.flags = flags;\n            this.compilerOptions = compilerOptions;\n            this.rootNamespace = rootNamespace;\n        }\n    }\n\n    public class ResponseFileData\n    {\n        public string[] Defines;\n        public string[] FullPathReferences;\n        public string[] Errors;\n        public string[] OtherArguments;\n        public bool Unsafe;\n    }\n\n    public struct AssemblyDefinitionPlatform\n    {\n        public string Name { get; private set; }\n        public string DisplayName { get; private set; }\n        public BuildTarget BuildTarget { get; private set; }\n        public bool HasSubtarget { get; private set; }\n        public int Subtarget { get; private set; }\n\n        internal AssemblyDefinitionPlatform(string name, string displayName, BuildTarget buildTarget, bool hasSubtarget = false, int subtarget = 0) : this()\n        {\n            Name = name;\n            DisplayName = displayName;\n            BuildTarget = buildTarget;\n            HasSubtarget = hasSubtarget;\n            Subtarget = subtarget;\n        }\n    }\n\n    public static partial class CompilationPipeline\n    {\n        static AssemblyDefinitionPlatform[] assemblyDefinitionPlatforms;\n\n        public static event Action<object> compilationStarted;\n        public static event Action<object> compilationFinished;\n        [Obsolete(\"Use compilationStarted, compilationFinished or assemblyCompilationFinished instead. Note that using any of these functions to do time measurements is a bad idea as they run async to actual compilation.\")]\n        public static event Action<string> assemblyCompilationStarted;\n        public static event Action<string> assemblyCompilationNotRequired;\n        public static event Action<string, CompilerMessage[]> assemblyCompilationFinished;\n\n        public static event Action<CodeOptimization> codeOptimizationChanged;\n\n        public static CodeOptimization codeOptimization\n        {\n            get { return IsScriptDebugInfoEnabled() ? CodeOptimization.Debug : CodeOptimization.Release; }\n            set\n            {\n                if (value == codeOptimization)\n                {\n                    return;\n                }\n\n                switch (value)\n                {\n                    case CodeOptimization.Debug:\n                    {\n                        EnableScriptDebugInfo();\n                        break;\n                    }\n\n                    case CodeOptimization.Release:\n                    {\n                        DisableScriptDebugInfo();\n                        break;\n                    }\n\n                    default:\n                    {\n                        throw new ArgumentException(string.Format(\"Invalid argument {0} provided.\", value.ToString()));\n                    }\n                }\n            }\n        }\n\n        static CompilationPipeline()\n        {\n            SubscribeToEvents(EditorCompilationInterface.Instance);\n        }\n\n        internal static void SubscribeToEvents(EditorCompilation editorCompilation)\n        {\n            editorCompilation.compilationStarted += (context) =>\n            {\n                try\n                {\n                    compilationStarted?.Invoke(context);\n                }\n                catch (Exception e)\n                {\n                    UnityEngine.Debug.Log(e);\n                }\n            };\n\n            editorCompilation.compilationFinished += (context) =>\n            {\n                try\n                {\n                    compilationFinished?.Invoke(context);\n                }\n                catch (Exception e)\n                {\n                    UnityEngine.Debug.Log(e);\n                }\n            };\n\n            editorCompilation.assemblyCompilationNotRequired += (scriptAssembly) =>\n            {\n                try\n                {\n                    assemblyCompilationNotRequired?.Invoke(scriptAssembly.FullPath);\n                }\n                catch (Exception e)\n                {\n                    UnityEngine.Debug.LogException(e);\n                }\n            };\n\n            editorCompilation.assemblyCompilationFinished += (scriptAssembly, messages) =>\n            {\n                try\n                {\n#pragma warning disable 618\n                    assemblyCompilationStarted?.Invoke(scriptAssembly.FullPath);\n#pragma warning restore 618\n                }\n                catch (Exception e)\n                {\n                    UnityEngine.Debug.LogException(e);\n                }\n\n                try\n                {\n                    assemblyCompilationFinished?.Invoke(scriptAssembly.FullPath, messages);\n                }\n                catch (Exception e)\n                {\n                    UnityEngine.Debug.LogException(e);\n                }\n            };\n        }\n\n        public static string[] GetSystemAssemblyDirectories(ApiCompatibilityLevel apiCompatibilityLevel)\n        {\n            return MonoLibraryHelpers.GetSystemReferenceDirectories(apiCompatibilityLevel);\n        }\n\n        public static ResponseFileData ParseResponseFile(string relativePath, string projectDirectory, string[] systemReferenceDirectories)\n        {\n            return MicrosoftResponseFileParser.ParseResponseFileFromFile(relativePath, projectDirectory, systemReferenceDirectories);\n        }\n\n        public static Assembly[] GetAssemblies()\n        {\n            return GetAssemblies(AssembliesType.Editor);\n        }\n\n        public static Assembly[] GetAssemblies(AssembliesType assembliesType)\n        {\n            return GetAssemblies(EditorCompilationInterface.Instance, assembliesType);\n        }\n\n        internal static Assembly[] GetAssemblies(EditorCompilation editorCompilation, AssembliesType assembliesType, string[] extraScriptingDefines = null)\n        {\n            return ToAssemblies(GetScriptAssemblies(editorCompilation, assembliesType, extraScriptingDefines));\n        }\n\n        internal static ScriptAssembly[] GetScriptAssemblies(IEditorCompilation editorCompilation, AssembliesType assembliesType, string[] extraScriptingDefines = null)\n        {\n            var options = EditorCompilationInterface.GetAdditionalEditorScriptCompilationOptions(assembliesType);\n\n            return GetScriptAssemblies(editorCompilation, options, extraScriptingDefines);\n        }\n\n        //Danger danger: this method is used by BurstAotCompiler.cs\n        internal static ScriptAssembly[] GetScriptAssemblies(IEditorCompilation editorCompilation, EditorScriptCompilationOptions options, string[] extraScriptingDefines = null)\n        {\n            var target = EditorUserBuildSettings.activeBuildTarget;\n            var buildingForEditor = (options & EditorScriptCompilationOptions.BuildingForEditor) != 0;\n\n            var unityAssemblies = InternalEditorUtility.GetUnityAssemblies(buildingForEditor, target);\n            var precompiledAssemblies = editorCompilation.PrecompiledAssemblyProvider.GetPrecompiledAssembliesDictionary(options, target, extraScriptingDefines);\n            return editorCompilation.GetAllScriptAssemblies(options, unityAssemblies, precompiledAssemblies, null);\n        }\n\n        public static string GetAssemblyNameFromScriptPath(string sourceFilePath)\n        {\n            return GetAssemblyNameFromScriptPath(EditorCompilationInterface.Instance, sourceFilePath);\n        }\n\n        public static string GetAssemblyDefinitionFilePathFromScriptPath(string sourceFilePath)\n        {\n            return GetAssemblyDefinitionFilePathFromScriptPath(EditorCompilationInterface.Instance, sourceFilePath);\n        }\n\n        public static string GetAssemblyDefinitionFilePathFromAssemblyName(string assemblyName)\n        {\n            return GetAssemblyDefinitionFilePathFromAssemblyName(EditorCompilationInterface.Instance, assemblyName);\n        }\n\n        public static string GetAssemblyDefinitionFilePathFromAssemblyReference(string reference)\n        {\n            return GetAssemblyDefinitionFilePathFromAssemblyReference(EditorCompilationInterface.Instance, reference);\n        }\n\n        public static AssemblyDefinitionReferenceType GetAssemblyDefinitionReferenceType(string reference)\n        {\n            return GUIDReference.IsGUIDReference(reference) ? AssemblyDefinitionReferenceType.Guid : AssemblyDefinitionReferenceType.Name;\n        }\n\n        public static string GUIDToAssemblyDefinitionReferenceGUID(string guid)\n        {\n            return GUIDReference.GUIDToGUIDReference(guid);\n        }\n\n        public static string AssemblyDefinitionReferenceGUIDToGUID(string reference)\n        {\n            if (GetAssemblyDefinitionReferenceType(reference) != AssemblyDefinitionReferenceType.Guid)\n                throw new ArgumentException($\"{reference} is not a GUID reference\", \"reference\");\n\n            return GUIDReference.GUIDReferenceToGUID(reference);\n        }\n\n        public static string GetAssemblyRootNamespaceFromScriptPath(string sourceFilePath)\n        {\n            var projectRootNamespace = UnityEditor.EditorSettings.projectGenerationRootNamespace;\n            return GetAssemblyRootNamespaceFromScriptPath(EditorCompilationInterface.Instance, projectRootNamespace, sourceFilePath);\n        }\n\n        public static AssemblyDefinitionPlatform[] GetAssemblyDefinitionPlatforms()\n        {\n            if (assemblyDefinitionPlatforms == null)\n            {\n                assemblyDefinitionPlatforms = CustomScriptAssembly.Platforms.Select(p => new AssemblyDefinitionPlatform(p.Name, p.DisplayName, p.BuildTarget, p.HasSubTarget, p.SubTarget)).ToArray();\n                Array.Sort(assemblyDefinitionPlatforms, CompareAssemblyDefinitionPlatformByDisplayName);\n            }\n\n            return assemblyDefinitionPlatforms;\n        }\n\n        public static string[] GetDefinesFromAssemblyName(string assemblyName)\n        {\n            return GetDefinesFromAssemblyName(EditorCompilationInterface.Instance, assemblyName);\n        }\n\n        internal static string[] GetDefinesFromAssemblyName(EditorCompilation editorCompilation, string assemblyName)\n        {\n            try\n            {\n                var assembly = editorCompilation.GetCustomTargetAssemblyFromName(assemblyName);\n\n                var scriptAssemblySettings = new ScriptAssemblySettings()\n                {\n                    BuildTarget = EditorUserBuildSettings.activeBuildTarget,\n                    CompilationOptions = EditorScriptCompilationOptions.BuildingForEditor\n                };\n\n                return editorCompilation.GetTargetAssemblyDefines(assembly, scriptAssemblySettings);\n            }\n            catch (ArgumentException)\n            {\n                return null;\n            }\n        }\n\n        public static string[] GetResponseFileDefinesFromAssemblyName(string assemblyName)\n        {\n            return GetResponseFileDefinesFromAssemblyName(EditorCompilationInterface.Instance, assemblyName);\n        }\n\n        internal static string[] GetResponseFileDefinesFromAssemblyName(EditorCompilation editorCompilation, string assemblyName)\n        {\n            try\n            {\n                var assembly = editorCompilation.GetCustomTargetAssemblyFromName(assemblyName);\n                return assembly?.ResponseFileDefines;\n            }\n            catch (ArgumentException)\n            {\n                return null;\n            }\n        }\n\n        public static string[] GetPrecompiledAssemblyNames()\n        {\n            var precompiledAssemblyProvider = EditorCompilationInterface.Instance.PrecompiledAssemblyProvider;\n            return GetPrecompiledAssemblyNames(precompiledAssemblyProvider);\n        }\n\n        internal static string[] GetPrecompiledAssemblyNames(PrecompiledAssemblyProviderBase precompiledAssemblyProvider)\n        {\n            return precompiledAssemblyProvider.GetPrecompiledAssemblies(\n                EditorScriptCompilationOptions.BuildingForEditor|EditorScriptCompilationOptions.BuildingWithAsserts,\n                EditorUserBuildSettings.activeBuildTarget)\n                .Where(x => (x.Flags & sc.AssemblyFlags.UserAssembly) == sc.AssemblyFlags.UserAssembly)\n                .Select(x => AssetPath.GetFileName(x.Path))\n                .ToArray();\n        }\n\n        public static bool IsDefineConstraintsCompatible(string[] defines, string[] defineConstraints)\n        {\n            return DefineConstraintsHelper.IsDefineConstraintsCompatible(defines, defineConstraints);\n        }\n\n        [Flags]\n        public enum PrecompiledAssemblySources\n        {\n            UserAssembly = 1 << 0,\n            UnityEngine = 1 << 1,\n            UnityEditor = 1 << 2,\n            SystemAssembly = 1 << 3,\n            UnityAssembly = 1 << 4,\n            All = ~0\n        }\n\n        public static string[] GetPrecompiledAssemblyPaths(PrecompiledAssemblySources precompiledAssemblySources)\n        {\n            var precompiledAssemblyProvider = EditorCompilationInterface.Instance.PrecompiledAssemblyProvider;\n            return GetPrecompiledAssemblyPaths(precompiledAssemblySources, precompiledAssemblyProvider).Select(FileUtil.GetPhysicalPath).ToArray();\n        }\n\n        internal static string[] GetPrecompiledAssemblyPaths(PrecompiledAssemblySources precompiledAssemblySources, PrecompiledAssemblyProviderBase precompiledAssemblyProvider)\n        {\n            return GetPrecompiledAssemblyPaths(precompiledAssemblySources, precompiledAssemblyProvider, EditorUserBuildSettings.activeBuildTarget);\n        }\n\n        internal static string[] GetPrecompiledAssemblyPaths(PrecompiledAssemblySources precompiledAssemblySources, PrecompiledAssemblyProviderBase precompiledAssemblyProvider, BuildTarget buildTarget)\n        {\n            HashSet<string> assemblyNames = new HashSet<string>();\n            sc.AssemblyFlags flags = sc.AssemblyFlags.None;\n            if ((precompiledAssemblySources & PrecompiledAssemblySources.SystemAssembly) != 0)\n            {\n                foreach (var a in MonoLibraryHelpers.GetSystemLibraryReferences(ApiCompatibilityLevel.NET_Unity_4_8))\n                {\n                    assemblyNames.Add(a);\n                }\n            }\n\n            if ((precompiledAssemblySources & (PrecompiledAssemblySources.UnityEngine | precompiledAssemblySources & PrecompiledAssemblySources.UnityAssembly)) != 0)\n                flags |= sc.AssemblyFlags.UnityModule;\n\n            if ((precompiledAssemblySources & (PrecompiledAssemblySources.UnityEditor | precompiledAssemblySources & PrecompiledAssemblySources.UnityAssembly)) != 0)\n                flags |= sc.AssemblyFlags.EditorOnly;\n\n            if ((precompiledAssemblySources & PrecompiledAssemblySources.UserAssembly) != 0)\n                flags |= sc.AssemblyFlags.UserAssembly;\n\n            var precompiledAssemblies = precompiledAssemblyProvider.GetPrecompiledAssemblies(\n                EditorScriptCompilationOptions.BuildingForEditor | EditorScriptCompilationOptions.BuildingWithAsserts,\n                buildTarget)\n                .Concat(precompiledAssemblyProvider.GetUnityAssemblies(true, buildTarget));\n\n            foreach (var a in precompiledAssemblies.Where(x => (x.Flags & flags) != 0))\n                assemblyNames.Add(a.Path);\n\n            return assemblyNames.ToArray();\n        }\n\n        public static string GetPrecompiledAssemblyPathFromAssemblyName(string assemblyName)\n        {\n            var precompiledAssemblyProvider = EditorCompilationInterface.Instance.PrecompiledAssemblyProvider;\n            return GetPrecompiledAssemblyPathFromAssemblyName(assemblyName, precompiledAssemblyProvider);\n        }\n\n        internal static string GetPrecompiledAssemblyPathFromAssemblyName(string assemblyName, PrecompiledAssemblyProviderBase precompiledAssemblyProvider, string[] extraScriptingDefines = null)\n        {\n            var precompiledAssemblies = precompiledAssemblyProvider.GetPrecompiledAssemblies(\n                EditorScriptCompilationOptions.BuildingForEditor | EditorScriptCompilationOptions.BuildingWithAsserts,\n                EditorUserBuildSettings.activeBuildTarget,\n                extraScriptingDefines);\n\n            foreach (var assembly in precompiledAssemblies)\n            {\n                if ((assembly.Flags & sc.AssemblyFlags.UserAssembly) == sc.AssemblyFlags.UserAssembly && AssetPath.GetFileName(assembly.Path) == assemblyName)\n                {\n                    return assembly.Path;\n                }\n            }\n            return null;\n        }\n\n        internal static Assembly[] ToAssemblies(ScriptAssembly[] scriptAssemblies)\n        {\n            var assemblies = new Assembly[scriptAssemblies.Length];\n\n            for (int i = 0; i < scriptAssemblies.Length; ++i)\n            {\n                var scriptAssembly = scriptAssemblies[i];\n\n                var name = AssetPath.GetAssemblyNameWithoutExtension(scriptAssembly.Filename);\n                var outputPath = scriptAssembly.FullPath;\n                var sourceFiles = scriptAssembly.Files;\n                var defines = scriptAssembly.Defines;\n                var compiledAssemblyReferences = scriptAssembly.References.Select(FileUtil.GetPhysicalPath).ToArray();\n\n                var flags = AssemblyFlags.None;\n\n                if ((scriptAssembly.Flags & sc.AssemblyFlags.EditorOnly) == sc.AssemblyFlags.EditorOnly)\n                    flags |= AssemblyFlags.EditorAssembly;\n\n                var compilerOptions = scriptAssembly.CompilerOptions;\n                compilerOptions.ResponseFiles = scriptAssembly.GetResponseFiles();\n\n                assemblies[i] = new Assembly(name,\n                    outputPath,\n                    sourceFiles,\n                    defines,\n                    null,\n                    compiledAssemblyReferences,\n                    flags,\n                    compilerOptions,\n                    scriptAssembly.RootNamespace);\n            }\n\n            var scriptAssemblyToAssembly = new Dictionary<ScriptAssembly, Assembly>();\n\n            for (int i = 0; i < scriptAssemblies.Length; ++i)\n                scriptAssemblyToAssembly.Add(scriptAssemblies[i], assemblies[i]);\n\n            for (int i = 0; i < scriptAssemblies.Length; ++i)\n            {\n                var scriptAssembly = scriptAssemblies[i];\n                var assemblyReferences = scriptAssembly.ScriptAssemblyReferences.Select(a => scriptAssemblyToAssembly[a]).Where(a => !IsInternalPlugin(a.outputPath)).ToArray();\n\n                assemblies[i].assemblyReferences = assemblyReferences;\n            }\n\n\n            return assemblies;\n        }\n\n        static bool IsInternalPlugin(string fullReference)\n        {\n            if (AssemblyHelper.IsInternalAssembly(fullReference))\n            {\n                if (!Modules.ModuleUtils.GetAdditionalReferencesForEditorCsharpProject().Contains(fullReference))\n                    return true;\n            }\n            return false;\n        }\n\n        static int CompareAssemblyDefinitionPlatformByDisplayName(AssemblyDefinitionPlatform p1, AssemblyDefinitionPlatform p2)\n        {\n            return string.Compare(p1.DisplayName, p2.DisplayName, StringComparison.OrdinalIgnoreCase);\n        }\n\n        internal static string GetAssemblyNameFromScriptPath(EditorCompilation editorCompilation, string sourceFilePath)\n        {\n            try\n            {\n                var targetAssembly = editorCompilation.GetTargetAssembly(sourceFilePath);\n                return targetAssembly.Name;\n            }\n            catch (Exception)\n            {\n                return null;\n            }\n        }\n\n        internal static string GetAssemblyDefinitionFilePathFromAssemblyName(EditorCompilation editorCompilation, string assemblyName)\n        {\n            if (editorCompilation.TryFindCustomScriptAssemblyFromAssemblyName(assemblyName, out var customScriptAssembly))\n            {\n                return customScriptAssembly.FilePath;\n            }\n\n            return null;\n        }\n\n        internal static string GetAssemblyDefinitionFilePathFromAssemblyReference(EditorCompilation editorCompilation, string reference)\n        {\n            if (editorCompilation.TryFindCustomScriptAssemblyFromAssemblyReference(reference, out var customScriptAssembly))\n            {\n                return customScriptAssembly.FilePath;\n            }\n\n            return null;\n        }\n\n        internal static string GetAssemblyRootNamespaceFromScriptPath(EditorCompilation editorCompilation, string projectRootNamespace, string sourceFilePath)\n        {\n            try\n            {\n                var csa = editorCompilation.FindCustomScriptAssemblyFromScriptPath(sourceFilePath);\n                return csa != null ? (csa.RootNamespace ?? projectRootNamespace) : projectRootNamespace;            }\n            catch (Exception)\n            {\n                return null;\n            }\n        }\n\n        internal static string GetAssemblyDefinitionFilePathFromScriptPath(EditorCompilation editorCompilation, string sourceFilePath)\n        {\n            if (editorCompilation.TryFindCustomScriptAssemblyFromScriptPath(sourceFilePath, out var customScriptAssembly))\n            {\n                return customScriptAssembly.FilePath;\n            }\n\n            return null;\n        }\n\n        public static void RequestScriptCompilation() => RequestScriptCompilation(RequestScriptCompilationOptions.None);\n        public static void RequestScriptCompilation(RequestScriptCompilationOptions options) => EditorCompilationInterface.Instance.RequestScriptCompilation(\"Requested through public api\", options);\n\n        [RequiredByNativeCode]\n        internal static void OnCodeOptimizationChanged(bool scriptDebugInfoEnabled)\n        {\n            if (codeOptimizationChanged != null)\n            {\n                codeOptimizationChanged(scriptDebugInfoEnabled ? CodeOptimization.Debug : CodeOptimization.Release);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/CompilationPipelineCommonHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal static class CompilationPipelineCommonHelper\n    {\n        const string k_UnityAssemblyPrefix = \"Unity.\";\n        const string k_CompilerClientSuffix = \".Compiler.Client\";\n\n        public static bool ShouldAdd(string assemblyName)\n        {\n            var name = AssetPath.GetAssemblyNameWithoutExtension(assemblyName);\n\n            if (name.StartsWith(k_UnityAssemblyPrefix, StringComparison.OrdinalIgnoreCase) && name.EndsWith(k_CompilerClientSuffix, StringComparison.OrdinalIgnoreCase))\n                return true;\n\n            return false;\n        }\n\n        public static void UpdateScriptAssemblyReference(ref ScriptAssembly scriptAssembly)\n        {\n            int referencesLength = scriptAssembly.References.Length;\n            var newReferences = new string[referencesLength + 1];\n            Array.Copy(scriptAssembly.References, newReferences, referencesLength);\n            newReferences[referencesLength] = AssetPath.Combine(EditorApplication.applicationContentsPath, \"Managed\", \"Unity.CompilationPipeline.Common.dll\");\n            scriptAssembly.References = newReferences;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/CompilationSetupErrorsTracker.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.Compilation;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    /// <summary>Classes implementing <c>ICompilationSetupErrorsTracker</c> are responsible for providing an interface for tracking compilation setup errors\n    /// within the editor and manage reporting those to the user as they are discovered or fixed.\n    /// </summary>\n    interface ICompilationSetupErrorsTracker\n    {\n        void SetCompilationSetupErrors(CompilationSetupErrors errors);\n        void ClearCompilationSetupErrors(CompilationSetupErrors errors);\n        bool HaveCompilationSetupErrors();\n        void LogCompilationSetupErrors(CompilationSetupErrors compilationSetupError, string[] filePaths, string message);\n    }\n\n    interface ICompilationSetupWarningTracker\n    {\n        void AddAssetWarning(string assetPath, string message);\n        void ClearAssetWarnings();\n    }\n\n    static class CompilationSetupErrorsTrackerExtensions\n    {\n        public static bool ProcessException(this ICompilationSetupErrorsTracker tracker, Exception exception)\n        {\n            var assemblyDefinitionException = exception as AssemblyDefinitionException;\n\n            if (assemblyDefinitionException != null && assemblyDefinitionException.filePaths.Length > 0)\n            {\n                tracker.LogCompilationSetupErrors(CompilationSetupErrors.LoadError, assemblyDefinitionException.filePaths, assemblyDefinitionException.Message);\n                return true;\n            }\n\n            return false;\n        }\n    }\n\n    /// <summary>Class <c>CompilationSetupErrorsTracker</c> is the default implementation of ICompilationSetupErrorsTracker\n    /// which uses native state to keep track of present errors and it communicates these errors as sticky console errors.\n    /// </summary>\n    class CompilationSetupErrorsTracker : ICompilationSetupErrorsTracker\n    {\n        public void SetCompilationSetupErrors(CompilationSetupErrors errors)\n        {\n            SetCompilationSetupErrorsNative(errors);\n        }\n\n        public void ClearCompilationSetupErrors(CompilationSetupErrors errors)\n        {\n            ClearCompilationSetupErrorsNative(errors);\n        }\n\n        public bool HaveCompilationSetupErrors()\n        {\n            return HaveCompilationSetupErrorsNative();\n        }\n\n        public void LogCompilationSetupErrors(CompilationSetupErrors compilationSetupError, string[] filePaths, string message)\n        {\n            foreach (var filePath in filePaths)\n            {\n                var messageWithPath = $\"{message} ({filePath})\";\n                LogCompilationSetupErrorNative(compilationSetupError, messageWithPath, filePath);\n            }\n        }\n\n        [FreeFunction(Name = \"SetCompilationSetupErrors\")]\n        internal static extern void SetCompilationSetupErrorsNative(CompilationSetupErrors errors);\n        [FreeFunction(Name = \"ClearCompilationSetupErrors\")]\n        internal static extern void ClearCompilationSetupErrorsNative(CompilationSetupErrors errors);\n        [FreeFunction(Name = \"HaveCompilationSetupErrors\")]\n        internal static extern bool HaveCompilationSetupErrorsNative();\n        [FreeFunction(Name = \"LogCompilationSetupError\")]\n        internal static extern void LogCompilationSetupErrorNative(CompilationSetupErrors compilationSetupError, string message, string filePath);\n    }\n\n    class CompilationSetupWarningTracker : ICompilationSetupWarningTracker\n    {\n        public void AddAssetWarning(string assetPath, string message)\n        {\n            AddAssetWarningNative(assetPath, message);\n        }\n\n        public void ClearAssetWarnings()\n        {\n            ClearCompilationAssetWarningsNative();\n        }\n\n        [FreeFunction(Name = \"AddCompilationAssetWarning\")]\n        internal static extern void AddAssetWarningNative(string assetPath, string message);\n        [FreeFunction(Name = \"ClearCompilationAssetWarnings\")]\n        internal static extern void ClearCompilationAssetWarningsNative();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/CompilerMessage.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nnamespace UnityEditor.Compilation\n{\n    public enum CompilerMessageType\n    {\n        Error = 0,\n        Warning = 1,\n        Info = 2\n    }\n\n    public struct CompilerMessage\n    {\n        public string message;\n        public string file;\n        public int line;\n        public int column;\n        public CompilerMessageType type;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing UnityEditor.Build;\nusing UnityEditor.Compilation;\nusing UnityEditor.Modules;\nusing UnityEditor.Scripting.Compilers;\nusing UnityEditorInternal;\nusing DiscoveredTargetInfo = UnityEditor.BuildTargetDiscovery.DiscoveredTargetInfo;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    // https://docs.microsoft.com/en-us/cpp/windows/changing-a-symbol-or-symbol-name-id\n    class SymbolNameRestrictions\n    {\n        private const int k_MaxLength = 247;\n\n        public static bool IsValid(string name)\n        {\n            if (string.IsNullOrEmpty(name))\n            {\n                return false;\n            }\n\n            if (name.Length > k_MaxLength)\n            {\n                return false;\n            }\n\n            // Invalid if the first character is a number.\n            if (char.IsNumber(name[0]))\n            {\n                return false;\n            }\n\n            foreach (var chr in name)\n            {\n                // Skip if it's a letter.\n                if (char.IsLetter(chr))\n                    continue;\n\n                // Skip if it's a number.\n                if (char.IsNumber(chr))\n                    continue;\n\n                // Skip if it's an underscore.\n                if (chr == '_')\n                    continue;\n\n                // Invalid for unsupported characters.\n                return false;\n            }\n\n            return true;\n        }\n    }\n\n#pragma warning disable 649\n    [Serializable]\n    class VersionDefine\n    {\n        public string name;\n        public string expression;\n        public string define;\n    }\n\n    [System.Serializable]\n    class CustomScriptAssemblyData\n    {\n        public string name;\n        public string rootNamespace;\n        public string[] references;\n\n        public string[] includePlatforms;\n        public string[] excludePlatforms;\n        public bool allowUnsafeCode;\n        public bool overrideReferences;\n        public string[] precompiledReferences;\n        public bool autoReferenced;\n        public string[] defineConstraints;\n        public VersionDefine[] versionDefines;\n        public bool noEngineReferences;\n\n        static Dictionary<string, string> renamedReferences = new Dictionary<string, string>(StringComparer.Ordinal);\n\n        static CustomScriptAssemblyData()\n        {\n            renamedReferences[\"Unity.RenderPipelines.Lightweight.Editor\"] = \"Unity.RenderPipelines.Universal.Editor\";\n            renamedReferences[\"Unity.RenderPipelines.Lightweight.Runtime\"] = \"Unity.RenderPipelines.Universal.Runtime\";\n        }\n\n        public static CustomScriptAssemblyData FromJson(string json)\n        {\n            var assemblyData = FromJsonNoFieldValidation(json);\n\n            assemblyData.ValidateFields();\n\n            return assemblyData;\n        }\n\n        public static CustomScriptAssemblyData FromJsonNoFieldValidation(string json)\n        {\n            var assemblyData = new CustomScriptAssemblyWithLegacyData();\n            assemblyData.autoReferenced = true;\n            UnityEngine.JsonUtility.FromJsonOverwrite(json, assemblyData);\n\n            UpdateRenamedReferences(assemblyData);\n            assemblyData.UpdateLegacyData();\n\n            if (assemblyData == null)\n                throw new System.Exception(\"Json file does not contain an assembly definition\");\n\n            return assemblyData;\n        }\n\n        public void ValidateFields()\n        {\n            if (string.IsNullOrEmpty(name))\n                throw new System.Exception(\"Required property 'name' not set\");\n\n            if ((excludePlatforms != null && excludePlatforms.Length > 0) &&\n                (includePlatforms != null && includePlatforms.Length > 0))\n                throw new System.Exception(\"Both 'excludePlatforms' and 'includePlatforms' are set.\");\n\n            if (autoReferenced && UnityCodeGenHelpers.IsCodeGen(name))\n            {\n                throw new Exception($\"Assembly '{name}' is a CodeGen assembly and cannot be Auto Referenced\");\n            }\n        }\n\n        public static string ToJson(CustomScriptAssemblyData data)\n        {\n            return UnityEngine.JsonUtility.ToJson(data, true);\n        }\n\n        static void UpdateRenamedReferences(CustomScriptAssemblyData data)\n        {\n            if (data.references == null || data.references.Length == 0)\n                return;\n\n            HashSet<string> additionalReferences = null;\n\n            for (int i = 0; i < data.references.Length; ++i)\n            {\n                var reference = data.references[i];\n                string newReference;\n\n                if (!renamedReferences.TryGetValue(reference, out newReference))\n                    continue;\n\n                if (additionalReferences == null)\n                    additionalReferences = new HashSet<string>();\n\n                additionalReferences.Add(newReference);\n            }\n\n            if (additionalReferences != null && additionalReferences.Count > 0)\n            {\n                for (int i = 0; i < data.references.Length; ++i)\n                {\n                    var reference = data.references[i];\n\n                    if (additionalReferences.Contains(reference))\n                        additionalReferences.Remove(reference);\n                }\n\n                if (additionalReferences.Count > 0)\n                    data.references = data.references.Concat(additionalReferences).ToArray();\n            }\n        }\n\n        [Serializable]\n        private class CustomScriptAssemblyWithLegacyData : CustomScriptAssemblyData\n        {\n            public string[] optionalUnityReferences;\n            public string Tooltip { get; private set; }\n\n            public void UpdateLegacyData()\n            {\n                if (optionalUnityReferences != null && optionalUnityReferences.Any())\n                {\n                    autoReferenced = false;\n                    overrideReferences = true;\n\n                    references = references ?? new string[0];\n                    precompiledReferences = precompiledReferences ?? new string[0];\n                    defineConstraints = defineConstraints ?? new string[0];\n\n                    AddTo(ref references, \"UnityEngine.TestRunner\", \"UnityEditor.TestRunner\");\n                    AddTo(ref precompiledReferences, \"nunit.framework.dll\");\n                    AddTo(ref defineConstraints, \"UNITY_INCLUDE_TESTS\");\n                }\n            }\n\n            private void AddTo(ref string[] array, params string[] additionalValues)\n            {\n                var z = new string[array.Length + additionalValues.Length];\n                array.CopyTo(z, 0);\n                additionalValues.CopyTo(z, array.Length);\n                array = z;\n            }\n        }\n    }\n\n    struct CustomScriptAssemblyPlatform\n    {\n        public string Name { get; private set; }\n        public string DisplayName { get; private set; }\n        public BuildTarget BuildTarget { get; private set; }\n        public bool HasSubTarget { get; private set; }\n        public int SubTarget { get; private set; }\n\n        public CustomScriptAssemblyPlatform(string name, string displayName, BuildTarget buildTarget, bool hasSubTarget = false, int subTarget = 0) : this()\n        {\n            Name = name;\n            DisplayName = displayName;\n            BuildTarget = buildTarget;\n            HasSubTarget = hasSubTarget;\n            SubTarget = subTarget;\n        }\n\n        public CustomScriptAssemblyPlatform(string name, BuildTarget buildTarget, bool hasSubTarget = false, int subTarget = 0) : this(name, name, buildTarget, hasSubTarget, subTarget) {}\n    }\n\n    [DebuggerDisplay(\"{Name}\")]\n    class CustomScriptAssembly\n    {\n        public string FilePath { get; set; }\n        public string PathPrefix { get; set; }\n        public string Name { get; set; }\n        public string RootNamespace { get; set; }\n        public string GUID { get; set; }\n        public string[] References { get; set; }\n        public string[] AdditionalPrefixes { get; set; }\n        public CustomScriptAssemblyPlatform[] IncludePlatforms { get; set; }\n        public CustomScriptAssemblyPlatform[] ExcludePlatforms { get; set; }\n\n        public AssetPathMetaData AssetPathMetaData { get; set; }\n        public ScriptCompilerOptions CompilerOptions { get; set; } = new ScriptCompilerOptions();\n\n        public bool OverrideReferences { get; set; }\n        public string[] PrecompiledReferences { get; set; }\n        public bool AutoReferenced { get; set; }\n        public string[] DefineConstraints { get; set; }\n        public VersionDefine[] VersionDefines { get; set; }\n\n        public string[] ResponseFileDefines { get; set; }\n\n        public bool NoEngineReferences { get; set; }\n\n        private AssemblyFlags assemblyFlags = AssemblyFlags.None;\n\n        public bool IsPredefined { get; set; }\n\n        public AssemblyFlags AssemblyFlags\n        {\n            get\n            {\n                if (assemblyFlags != AssemblyFlags.None)\n                    return assemblyFlags;\n\n                assemblyFlags = AssemblyFlags.UserAssembly;\n\n                if (IncludePlatforms != null && IncludePlatforms.Length == 1 && IncludePlatforms[0].BuildTarget == BuildTarget.NoTarget)\n                    assemblyFlags |= AssemblyFlags.EditorOnly;\n\n                if (OverrideReferences)\n                {\n                    assemblyFlags |= AssemblyFlags.ExplicitReferences;\n                }\n\n                if (!AutoReferenced)\n                {\n                    assemblyFlags |= AssemblyFlags.ExplicitlyReferenced;\n                }\n\n                if (NoEngineReferences)\n                {\n                    assemblyFlags |= AssemblyFlags.NoEngineReferences;\n                }\n\n                bool rootFolder, immutable;\n                bool imported = AssetDatabase.TryGetAssetFolderInfo(PathPrefix, out rootFolder, out immutable);\n\n                // Do not emit warnings for immutable (package) folders,\n                // as the user cannot do anything to fix them.\n                if (imported && immutable)\n                {\n                    assemblyFlags |= AssemblyFlags.SuppressCompilerWarnings;\n                }\n\n                return assemblyFlags;\n            }\n        }\n\n        public static List<CustomScriptAssemblyPlatform> Platforms { get; private set; }\n        public static CustomScriptAssemblyPlatform[] DeprecatedPlatforms { get; private set; }\n        public static string[] RenamedPlatforms { get; private set; }\n\n        static CustomScriptAssembly()\n        {\n            // When removing a platform from Platforms, please add it to DeprecatedPlatforms.\n            DiscoveredTargetInfo[] buildTargetList = BuildTargetDiscovery.GetBuildTargetInfoList();\n\n            // Need extra slots in array for Editor target and subtarget variants which are not included in the build target list\n            const int numEditorTargets = 1;\n\n            Platforms = new List<CustomScriptAssemblyPlatform>(buildTargetList.Length + numEditorTargets)\n            {\n                new (\"Editor\", BuildTarget.NoTarget)\n            };\n\n            for (int i = 0; i < buildTargetList.Length; i++)\n            {\n                // normal case\n                Platforms.Add(\n                    new CustomScriptAssemblyPlatform(\n                    BuildTargetDiscovery.GetScriptAssemblyName(buildTargetList[i]),\n                    buildTargetList[i].niceName,\n                    buildTargetList[i].buildTargetPlatformVal)\n                );\n\n                var extensionModule =\n                    ModuleManager.FindPlatformSupportModule(\n                        ModuleManager.GetTargetStringFromBuildTarget(buildTargetList[i].buildTargetPlatformVal));\n\n                // if this build target has extra custom assembly targets, append those\n                if(extensionModule != null)\n                {\n                    var extraScriptAssemblyPlatforms = extensionModule.GetExtraScriptAssemblyPlatforms(buildTargetList[i].buildTargetPlatformVal);\n                    if (extraScriptAssemblyPlatforms != null && extraScriptAssemblyPlatforms.Any())\n                    {\n                        foreach(var extraPlatform in extraScriptAssemblyPlatforms)\n                        {\n                            Platforms.Add(new CustomScriptAssemblyPlatform(\n                                BuildTargetDiscovery.GetScriptAssemblyName(buildTargetList[i]) + extraPlatform.AssemblyNamePostfix,\n                                extraPlatform.TargetNiceName,\n                                    buildTargetList[i].buildTargetPlatformVal,\n                                    true,\n                                    extraPlatform.Subtarget));\n                        }\n                    }\n                }\n            }\n\n#pragma warning disable 0618\n            DeprecatedPlatforms = new CustomScriptAssemblyPlatform[]\n            {\n                new CustomScriptAssemblyPlatform(\"PSMobile\", BuildTarget.PSM),\n                new CustomScriptAssemblyPlatform(\"Tizen\", BuildTarget.Tizen),\n                new CustomScriptAssemblyPlatform(\"WiiU\", BuildTarget.WiiU),\n                new CustomScriptAssemblyPlatform(\"Nintendo3DS\", BuildTarget.N3DS),\n                new CustomScriptAssemblyPlatform(\"PSVita\", BuildTarget.PSP2),\n                new CustomScriptAssemblyPlatform(\"LinuxStandalone32\", BuildTarget.StandaloneLinux),\n                new CustomScriptAssemblyPlatform(\"LinuxStandaloneUniversal\", BuildTarget.StandaloneLinuxUniversal),\n                new CustomScriptAssemblyPlatform(\"Lumin\", BuildTarget.Lumin),\n                new CustomScriptAssemblyPlatform(\"Stadia\", BuildTarget.Stadia),\n            };\n            RenamedPlatforms = new string[]\n            {\n                \"Bratwurst\",\n            };\n#pragma warning restore 0618\n        }\n\n        public bool IsCompatibleWithEditor()\n        {\n            if (ExcludePlatforms != null)\n                return ExcludePlatforms.All(p => p.BuildTarget != BuildTarget.NoTarget);\n\n            if (IncludePlatforms != null)\n                return IncludePlatforms.Any(p => p.BuildTarget == BuildTarget.NoTarget);\n\n            return true;\n        }\n\n        public bool IsCompatibleWith(BuildTarget buildTarget, int subTarget, EditorScriptCompilationOptions options, string[] defines)\n        {\n            bool buildingForEditor = (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor;\n\n            var isBuildingWithTestAssemblies = (options & EditorScriptCompilationOptions.BuildingIncludingTestAssemblies) == EditorScriptCompilationOptions.BuildingIncludingTestAssemblies;\n            var isTestAssembly = DefineConstraints != null && DefineConstraints.Any(x => x == \"UNITY_INCLUDE_TESTS\");\n            var isTestFrameworkAssembly = DefineConstraints != null && DefineConstraints.Any(x => x == \"UNITY_TESTS_FRAMEWORK\");\n            if (!buildingForEditor && (isTestAssembly || isTestFrameworkAssembly) && !isBuildingWithTestAssemblies)\n            {\n                return false;\n            }\n\n            if (defines != null && defines.Length == 0)\n            {\n                throw new ArgumentException(\"Defines cannot be empty\", nameof(defines));\n            }\n\n            // Log invalid define constraints\n            if (DefineConstraints != null)\n            {\n                for (var i = 0; i < DefineConstraints.Length; ++i)\n                {\n                    if (!DefineConstraintsHelper.IsDefineConstraintValid(DefineConstraints[i]))\n                    {\n                        throw new AssemblyDefinitionException($\"Invalid Define Constraint: \\\"{DefineConstraints[i]}\\\" at line {(i+1).ToString()}\", FilePath);\n                    }\n                }\n            }\n            var allDefines = ResponseFileDefines != null ?\n                (defines != null ? defines.Concat(ResponseFileDefines) : ResponseFileDefines)\n                : defines;\n            if (!DefineConstraintsHelper.IsDefineConstraintsCompatible_Enumerable(allDefines, DefineConstraints))\n            {\n                return false;\n            }\n\n            if (isTestAssembly && AssetPathMetaData != null && !AssetPathMetaData.IsTestable)\n            {\n                return false;\n            }\n\n            // Compatible with editor and all platforms.\n            if (IncludePlatforms == null && ExcludePlatforms == null)\n            {\n                return true;\n            }\n\n            if (buildingForEditor)\n            {\n                return IsCompatibleWithEditor();\n            }\n\n            if (ExcludePlatforms != null)\n            {\n                // build target is different\n                // OR build target matches, but subtarget for target assembly is both present and differs\n                return ExcludePlatforms.All(p =>\n                    p.BuildTarget != buildTarget ||\n                    (p.BuildTarget == buildTarget &&\n                    (p.HasSubTarget && p.SubTarget != subTarget)));\n            }\n\n            // build target matches, and if present, subtarget matches\n            return IncludePlatforms.Any(p => p.BuildTarget == buildTarget && (!p.HasSubTarget || p.SubTarget == subTarget));\n        }\n\n        public static CustomScriptAssembly Create(string name, string directory)\n        {\n            var customScriptAssembly = new CustomScriptAssembly();\n\n            var modifiedDirectory = AssetPath.ReplaceSeparators(directory);\n\n            if (modifiedDirectory.Last() != AssetPath.Separator)\n                modifiedDirectory += AssetPath.Separator.ToString();\n\n            customScriptAssembly.Name = name;\n            customScriptAssembly.RootNamespace = name ?? string.Empty;\n            customScriptAssembly.FilePath = modifiedDirectory;\n            customScriptAssembly.PathPrefix = modifiedDirectory;\n            customScriptAssembly.References = new string[0];\n            customScriptAssembly.PrecompiledReferences = new string[0];\n            customScriptAssembly.CompilerOptions = new ScriptCompilerOptions();\n            customScriptAssembly.AutoReferenced = true;\n\n            return customScriptAssembly;\n        }\n\n        public static CustomScriptAssembly FromCustomScriptAssemblyData(string path, string guid, CustomScriptAssemblyData customScriptAssemblyData)\n        {\n            if (customScriptAssemblyData == null)\n                return null;\n\n            var pathPrefix = path.Substring(0, path.Length - AssetPath.GetFileName(path).Length);\n\n            var customScriptAssembly = new CustomScriptAssembly();\n\n            customScriptAssembly.Name = customScriptAssemblyData.name;\n            customScriptAssembly.RootNamespace = customScriptAssemblyData.rootNamespace;\n            customScriptAssembly.GUID = guid;\n            customScriptAssembly.References = customScriptAssemblyData.references;\n            customScriptAssembly.FilePath = path;\n            customScriptAssembly.PathPrefix = pathPrefix;\n            customScriptAssembly.AutoReferenced = customScriptAssemblyData.autoReferenced;\n            customScriptAssembly.OverrideReferences = customScriptAssemblyData.overrideReferences;\n            customScriptAssembly.NoEngineReferences = customScriptAssemblyData.noEngineReferences;\n            customScriptAssembly.PrecompiledReferences = customScriptAssemblyData.precompiledReferences ?? new string[0];\n            customScriptAssembly.DefineConstraints = customScriptAssemblyData.defineConstraints ?? new string[0];\n            customScriptAssembly.VersionDefines = (customScriptAssemblyData.versionDefines ?? new VersionDefine[0]);\n\n            if (customScriptAssemblyData.includePlatforms != null && customScriptAssemblyData.includePlatforms.Length > 0)\n                customScriptAssembly.IncludePlatforms = GetPlatformsFromNames(customScriptAssemblyData.includePlatforms);\n\n            if (customScriptAssemblyData.excludePlatforms != null && customScriptAssemblyData.excludePlatforms.Length > 0)\n                customScriptAssembly.ExcludePlatforms = GetPlatformsFromNames(customScriptAssemblyData.excludePlatforms);\n\n            var compilerOptions = new ScriptCompilerOptions\n            {\n                AllowUnsafeCode = customScriptAssemblyData.allowUnsafeCode\n            };\n            customScriptAssembly.CompilerOptions = compilerOptions;\n\n            return customScriptAssembly;\n        }\n\n        public static CustomScriptAssemblyPlatform[] GetPlatformsFromNames(string[] names)\n        {\n            var platforms = new List<CustomScriptAssemblyPlatform>();\n\n            foreach (var name in names)\n            {\n                // Ignore deprecated platforms.\n                if (IsDeprecatedPlatformName(name))\n                    continue;\n\n                platforms.Add(GetPlatformFromName(name));\n            }\n\n            return platforms.ToArray();\n        }\n\n        public static bool IsDeprecatedPlatformName(string name)\n        {\n            foreach (var platform in DeprecatedPlatforms)\n                if (string.Equals(platform.Name, name, System.StringComparison.OrdinalIgnoreCase))\n                    return true;\n\n            foreach(var platformName in RenamedPlatforms)\n                if (string.Equals(platformName, name, System.StringComparison.OrdinalIgnoreCase))\n                    return true;\n\n            return false;\n        }\n\n        public static CustomScriptAssemblyPlatform GetPlatformFromName(string name)\n        {\n            foreach (var platform in Platforms)\n                if (string.Equals(platform.Name, name, System.StringComparison.OrdinalIgnoreCase))\n                    return platform;\n\n            var platformNames = Platforms.Select(p => string.Format(\"\\\"{0}\\\"\", p.Name)).ToArray();\n            System.Array.Sort(platformNames);\n\n            var platformsString = string.Join(\",\\n\", platformNames);\n\n            throw new System.ArgumentException(string.Format(\"Platform name '{0}' not supported.\\nSupported platform names:\\n{1}\\n\", name, platformsString));\n        }\n\n        public static CustomScriptAssemblyPlatform GetPlatformFromBuildTarget(BuildTarget buildTarget)\n        {\n            foreach (var platform in Platforms)\n                if (platform.BuildTarget == buildTarget)\n                    return platform;\n\n            throw new System.ArgumentException(string.Format(\"No CustomScriptAssemblyPlatform setup for BuildTarget '{0}'\", buildTarget));\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj)) return false;\n            if (ReferenceEquals(this, obj)) return true;\n            if (obj.GetType() != this.GetType()) return false;\n            return Equals((CustomScriptAssembly) obj);\n        }\n\n        public bool Equals(CustomScriptAssembly other)\n        {\n            return assemblyFlags == other.assemblyFlags\n                   && string.Equals(FilePath, other.FilePath, StringComparison.Ordinal)\n                   && string.Equals(PathPrefix, other.PathPrefix, StringComparison.Ordinal)\n                   && string.Equals(Name, other.Name, StringComparison.Ordinal)\n                   && string.Equals(RootNamespace, other.RootNamespace, StringComparison.Ordinal)\n                   && GUID == other.GUID\n                   && Equals(References, other.References)\n                   && Equals(AdditionalPrefixes, other.AdditionalPrefixes)\n                   && Equals(IncludePlatforms, other.IncludePlatforms)\n                   && Equals(ExcludePlatforms, other.ExcludePlatforms)\n                   && Equals(AssetPathMetaData, other.AssetPathMetaData)\n                   && Equals(CompilerOptions, other.CompilerOptions)\n                   && OverrideReferences == other.OverrideReferences\n                   && Equals(PrecompiledReferences, other.PrecompiledReferences)\n                   && AutoReferenced == other.AutoReferenced\n                   && Equals(DefineConstraints, other.DefineConstraints)\n                   && Equals(VersionDefines, other.VersionDefines)\n                   && Equals(ResponseFileDefines, other.ResponseFileDefines)\n                   && NoEngineReferences == other.NoEngineReferences\n                   && IsPredefined == other.IsPredefined;\n        }\n\n        public override int GetHashCode()\n        {\n            return GUID.GetHashCode();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssemblyReference.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    [Serializable]\n    class CustomScriptAssemblyReferenceData\n    {\n        // Disable the `x is never assigned to, and will always have its default value' warning (CS0649)\n        #pragma warning disable 649\n        public string reference;\n\n        public static CustomScriptAssemblyReferenceData FromJson(string json)\n        {\n            CustomScriptAssemblyReferenceData assemblyRefData = new CustomScriptAssemblyReferenceData();\n            UnityEngine.JsonUtility.FromJsonOverwrite(json, assemblyRefData);\n\n            if (assemblyRefData == null)\n                throw new Exception(\"Json file does not contain an assembly reference definition\");\n\n            return assemblyRefData;\n        }\n\n        public static string ToJson(CustomScriptAssemblyReferenceData data)\n        {\n            return UnityEngine.JsonUtility.ToJson(data, true);\n        }\n    }\n\n    class CustomScriptAssemblyReference\n    {\n        public bool Equals(CustomScriptAssemblyReference other)\n        {\n            return string.Equals(FilePath, other.FilePath, StringComparison.Ordinal)\n                   && string.Equals(PathPrefix, other.PathPrefix, StringComparison.Ordinal)\n                   && string.Equals(Reference, other.Reference, StringComparison.Ordinal);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj)) return false;\n            if (ReferenceEquals(this, obj)) return true;\n            if (obj.GetType() != this.GetType()) return false;\n            return Equals((CustomScriptAssemblyReference) obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return HashCode.Combine(FilePath, PathPrefix, Reference);\n        }\n\n        public string FilePath { get; set; }\n        public string PathPrefix { get; set; }\n        public string Reference { get; set; } // Name or GUID\n\n        public static CustomScriptAssemblyReference FromCustomScriptAssemblyReferenceData(string path, CustomScriptAssemblyReferenceData customScriptAssemblyReferenceData)\n        {\n            if (customScriptAssemblyReferenceData == null)\n                return null;\n\n            var pathPrefix = path.Substring(0, path.Length - AssetPath.GetFileName(path).Length);\n\n            var customScriptAssemblyReference = new CustomScriptAssemblyReference();\n            customScriptAssemblyReference.FilePath = path;\n            customScriptAssemblyReference.PathPrefix = pathPrefix;\n            customScriptAssemblyReference.Reference = customScriptAssemblyReferenceData.reference;\n\n            return customScriptAssemblyReference;\n        }\n\n        public static CustomScriptAssemblyReference FromPathAndReference(string path, string reference)\n        {\n            var pathPrefix = path.Substring(0, path.Length - AssetPath.GetFileName(path).Length);\n\n            var customScriptAssemblyReference = new CustomScriptAssemblyReference();\n            customScriptAssemblyReference.FilePath = path;\n            customScriptAssemblyReference.PathPrefix = pathPrefix;\n            customScriptAssemblyReference.Reference = reference;\n\n            return customScriptAssemblyReference;\n        }\n\n        public CustomScriptAssemblyReferenceData CreateData()\n        {\n            return new CustomScriptAssemblyReferenceData() { reference = Reference };\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/DefineConstraintsHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    static class DefineConstraintsHelper\n    {\n        public const string Not = \"!\";\n        public const string Or = \"||\";\n\n        // Characters that we consider valid whitespaces.\n        public static readonly char[] k_ValidWhitespaces = { ' ', '\\t' };\n\n        static Regex s_SplitAndKeep = null;\n\n        public enum DefineConstraintStatus\n        {\n            Compatible,\n            Incompatible,\n            Invalid,\n        }\n\n        [RequiredByNativeCode]\n        public static bool IsDefineConstraintsCompatible(string[] defines, string[] defineConstraints)\n        {\n            return IsDefineConstraintsCompatible_Enumerable(defines.AsEnumerable<string>(), defineConstraints.AsEnumerable<string>());\n        }\n\n        // This is not called IsDefineConstraintsCompatible because the bindings generator does not support overloads\n        public static bool IsDefineConstraintsCompatible_Enumerable(IEnumerable<string> defines, IEnumerable<string> defineConstraints)\n        {\n            if (defines == null && defineConstraints == null || defineConstraints == null || !defineConstraints.Any())\n            {\n                return true;\n            }\n\n            foreach (var constraint in defineConstraints)\n            {\n                if (GetDefineConstraintCompatibility(defines, constraint) != DefineConstraintStatus.Compatible)\n                {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        internal static DefineConstraintStatus GetDefineConstraintCompatibility(IEnumerable<string> defines, string defineConstraints)\n        {\n            if (string.IsNullOrEmpty(defineConstraints))\n            {\n                return DefineConstraintStatus.Invalid;\n            }\n\n            if (s_SplitAndKeep == null)\n                s_SplitAndKeep = new Regex(\"(\\\\|\\\\|)\", RegexOptions.Compiled);\n\n            // Split by \"||\" (OR) and keep it in the resulting array\n            var splitDefineConstraints = s_SplitAndKeep.Split(defineConstraints);\n\n            // Trim what we consider valid space characters\n            for (var i = 0; i < splitDefineConstraints.Length; ++i)\n            {\n                splitDefineConstraints[i] = splitDefineConstraints[i].Trim(k_ValidWhitespaces);\n            }\n\n            // Check for consecutive OR\n            for (var i = 0; i < splitDefineConstraints.Length; ++i)\n            {\n                if (splitDefineConstraints[i] == Or && (i < splitDefineConstraints.Length - 1 && splitDefineConstraints[i + 1] == Or))\n                {\n                    return DefineConstraintStatus.Invalid;\n                }\n            }\n\n            var notExpectedDefines = new HashSet<string>(splitDefineConstraints.Where(x => x.StartsWith(Not, StringComparison.Ordinal) && x != Or).Select(x => x.Substring(1)));\n            var expectedDefines = new HashSet<string>(splitDefineConstraints.Where(x => !x.StartsWith(Not, StringComparison.Ordinal) && x != Or));\n\n            if (defines == null || !defines.Any())\n            {\n                if (expectedDefines.Count > 0)\n                {\n                    return DefineConstraintStatus.Incompatible;\n                }\n\n                return DefineConstraintStatus.Compatible;\n            }\n\n            foreach (var define in expectedDefines)\n            {\n                if (!SymbolNameRestrictions.IsValid(define))\n                {\n                    return DefineConstraintStatus.Invalid;\n                }\n            }\n\n            foreach (var define in notExpectedDefines)\n            {\n                if (!SymbolNameRestrictions.IsValid(define))\n                {\n                    return DefineConstraintStatus.Invalid;\n                }\n            }\n\n            if (expectedDefines.Overlaps(notExpectedDefines))\n            {\n                var complement = new HashSet<string>(expectedDefines);\n                expectedDefines.ExceptWith(notExpectedDefines);\n                notExpectedDefines.ExceptWith(complement);\n            }\n\n            if (expectedDefines.Count == 0 && notExpectedDefines.Count == 0)\n            {\n                return DefineConstraintStatus.Invalid;\n            }\n\n            var expectedDefinesResult = DefineConstraintStatus.Incompatible;\n            foreach (var define in expectedDefines)\n            {\n                if (defines.Contains(define))\n                {\n                    expectedDefinesResult = DefineConstraintStatus.Compatible;\n                    break;\n                }\n            }\n\n            if (expectedDefines.Count > 0 && notExpectedDefines.Count == 0)\n            {\n                return expectedDefinesResult;\n            }\n\n            var notExpectedDefinesResult = DefineConstraintStatus.Compatible;\n            foreach (var define in notExpectedDefines)\n            {\n                if (defines.Contains(define))\n                {\n                    notExpectedDefinesResult = DefineConstraintStatus.Incompatible;\n                    break;\n                }\n            }\n\n            if (notExpectedDefines.Count > 0 && expectedDefines.Count == 0)\n            {\n                return notExpectedDefinesResult;\n            }\n\n            if (expectedDefinesResult == DefineConstraintStatus.Compatible || notExpectedDefinesResult == DefineConstraintStatus.Compatible)\n            {\n                return DefineConstraintStatus.Compatible;\n            }\n\n            return DefineConstraintStatus.Incompatible;\n        }\n\n        internal static bool IsDefineConstraintValid(string define)\n        {\n            if (define == null)\n            {\n                return false;\n            }\n\n            // Split define by OR symbol\n            var splitDefines = define.Split(new[] { Or }, StringSplitOptions.RemoveEmptyEntries);\n            foreach (var d in splitDefines)\n            {\n                var finalDefine = d.Trim(k_ValidWhitespaces);\n                finalDefine = finalDefine.StartsWith(Not, StringComparison.Ordinal) ? finalDefine.Substring(1) : finalDefine;\n                if (!SymbolNameRestrictions.IsValid(finalDefine))\n                {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\n// Do not add \"using System.IO\", use AssetPath methods instead\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor.Compilation;\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    // This class is intentionally immutable, avoid adding mutable state to it.\n    static class EditorBuildRules\n    {\n        internal enum UnityReferencesOptions\n        {\n            None = 0,\n            ExcludeModules = 1,\n        }\n\n        public class CompilationAssemblies\n        {\n            public PrecompiledAssembly[] UnityAssemblies { get; set; }\n            public Dictionary<string, PrecompiledAssembly> PrecompiledAssemblies { get; set; }\n            public Dictionary<string, TargetAssembly> CustomTargetAssemblies { get; set; }\n            public TargetAssembly[] PredefinedAssembliesCustomTargetReferences { get; set; }\n            public string[] EditorAssemblyReferences { get; set; }\n            public string[] RoslynAnalyzerDllPaths { get; set; }\n        }\n\n        public static Dictionary<string, TargetAssembly> predefinedTargetAssemblies { get; private set; }\n\n        private static readonly string[] s_CSharpVersionDefines =\n        {\n            \"CSHARP_7_OR_LATER\", // Incremental Compiler adds this.\n            \"CSHARP_7_3_OR_NEWER\",\n        };\n\n        static EditorBuildRules()\n        {\n            predefinedTargetAssemblies = CreatePredefinedTargetAssemblies();\n        }\n\n        public static TargetAssembly[] GetPredefinedTargetAssemblies()\n        {\n            return predefinedTargetAssemblies.Values.ToArray();\n        }\n\n        public static string[] PredefinedTargetAssemblyNames\n        {\n            get { return predefinedTargetAssemblies.Select(a => AssetPath.GetAssemblyNameWithoutExtension(a.Key)).ToArray(); }\n        }\n\n        /// <summary>\n        /// Checks the scriptPath against the pathPrefix and additionalPathPrefixes.\n        /// Returns the depth from the scriptPath where -1 indicates no match.\n        /// </summary>\n        internal static int PathFilter(string scriptPath, string pathPrefix, string lowerPathPrefix, string[] additionalPathPrefixes, string[] lowerAdditionalPathPrefixes)\n        {\n            // Find the path that is closest to the script path\n            int depth = Utility.FastStartsWith(scriptPath, pathPrefix, lowerPathPrefix) ? pathPrefix.Length : -1;\n\n            if (additionalPathPrefixes != null)\n            {\n                for (int i = 0; i < additionalPathPrefixes.Length; ++i)\n                {\n                    if (Utility.FastStartsWith(scriptPath, additionalPathPrefixes[i], lowerAdditionalPathPrefixes[i]) && additionalPathPrefixes[i].Length > depth)\n                    {\n                        depth = additionalPathPrefixes[i].Length;\n                    }\n                }\n            }\n\n            return depth;\n        }\n\n        private static string[] CombineDefineArrays(string[] defines, string[] extraPlayerDefines)\n        {\n            if (defines == null)\n                return null;\n\n            extraPlayerDefines = extraPlayerDefines ?? Array.Empty<string>();\n\n            var combined = new string[defines.Length + extraPlayerDefines.Length];\n            Array.Copy(defines, combined, defines.Length);\n            Array.Copy(extraPlayerDefines, 0, combined, defines.Length, extraPlayerDefines.Length);\n            return combined;\n        }\n\n        public static Dictionary<string, TargetAssembly> CreateTargetAssemblies(IEnumerable<CustomScriptAssembly> customScriptAssemblies)\n        {\n            if (customScriptAssemblies == null)\n                return null;\n\n            var targetAssemblies = new List<TargetAssembly>();\n            var nameToTargetAssembly = new Dictionary<string, TargetAssembly>();\n\n            // Create TargetAssemblies\n            foreach (var customAssembly in customScriptAssemblies)\n            {\n                var lowerPathPrefix = Utility.FastToLower(customAssembly.PathPrefix);\n                var lowerAdditionalPathPrefixes = customAssembly.AdditionalPrefixes?.Select(Utility.FastToLower).ToArray();\n\n                var targetAssembly = new TargetAssembly(customAssembly.Name + \".dll\",\n                    customAssembly.AssemblyFlags,\n                    TargetAssemblyType.Custom,\n                    customAssembly.PathPrefix,\n                    customAssembly.AdditionalPrefixes,\n                    path => PathFilter(path, customAssembly.PathPrefix, lowerPathPrefix, customAssembly.AdditionalPrefixes, lowerAdditionalPathPrefixes),\n                    (settings, defines) => customAssembly.IsCompatibleWith(settings.BuildTarget, settings.Subtarget, settings.CompilationOptions, CombineDefineArrays(defines, settings.ExtraGeneralDefines)),\n                    customAssembly.CompilerOptions)\n                {\n                    ExplicitPrecompiledReferences = customAssembly.PrecompiledReferences?.ToList() ?? new List<string>(),\n                    VersionDefines = customAssembly.VersionDefines != null\n                        ? customAssembly.VersionDefines.ToList() : new List<VersionDefine>(),\n                    RootNamespace = customAssembly.RootNamespace,\n                    ResponseFileDefines = customAssembly.ResponseFileDefines,\n                    AsmDefPath = customAssembly.FilePath\n                };\n\n                targetAssemblies.Add(targetAssembly);\n                nameToTargetAssembly[customAssembly.Name] = targetAssembly;\n            }\n\n            var targetAssembliesEnumerator = targetAssemblies.GetEnumerator();\n\n            // Setup references for TargetAssemblies\n            foreach (var customAssembly in customScriptAssemblies)\n            {\n                targetAssembliesEnumerator.MoveNext();\n                var targetAssembly = targetAssembliesEnumerator.Current;\n\n                if (customAssembly.References == null)\n                    continue;\n\n                foreach (var reference in customAssembly.References)\n                {\n                    TargetAssembly referenceAssembly = null;\n\n                    if (!nameToTargetAssembly.TryGetValue(reference, out referenceAssembly))\n                    {\n                        continue;\n                    }\n\n                    targetAssembly.References.Add(referenceAssembly);\n                }\n            }\n\n            var customTargetAssembliesDict = new Dictionary<string, TargetAssembly>();\n\n            foreach (var targetAssembly in targetAssemblies)\n            {\n                customTargetAssembliesDict[targetAssembly.Filename] = targetAssembly;\n            }\n\n            return customTargetAssembliesDict;\n        }\n\n        public static ScriptAssembly[] GetAllScriptAssemblies(\n            Dictionary<string, string> allSourceFiles,\n            String projectDirectory,\n            ScriptAssemblySettings settings,\n            CompilationAssemblies assemblies,\n            ISafeModeInfo safeModeInfo,\n            TargetAssemblyType onlyIncludeType = TargetAssemblyType.Undefined,\n            Func<TargetAssembly, bool> targetAssemblyCondition = null,\n            ICompilationSetupWarningTracker warningSink = null)\n        {\n            if (allSourceFiles == null || allSourceFiles.Count == 0)\n                return new ScriptAssembly[0];\n\n            var targetAssemblyFiles = new Dictionary<TargetAssembly, DirtyTargetAssembly>();\n\n            foreach (var entry in allSourceFiles)\n            {\n                var scriptFile = entry.Key;\n                var assemblyName = entry.Value;\n                var targetAssembly = GetTargetAssembly(scriptFile, assemblyName, projectDirectory, assemblies.CustomTargetAssemblies);\n\n                if (targetAssembly == null)\n                    continue;\n\n                if (!IsCompatibleWithPlatformAndDefines(targetAssembly, settings))\n                    continue;\n\n                if (targetAssemblyCondition != null && !targetAssemblyCondition(targetAssembly))\n                    continue;\n\n                // Optionally only include specific TargetAssemblyType assemblies.\n                if (onlyIncludeType != TargetAssemblyType.Undefined && targetAssembly.Type != onlyIncludeType)\n                    continue;\n\n                DirtyTargetAssembly dirtyTargetAssembly;\n\n                if (!targetAssemblyFiles.TryGetValue(targetAssembly, out dirtyTargetAssembly))\n                {\n                    dirtyTargetAssembly = new DirtyTargetAssembly();\n                    targetAssemblyFiles[targetAssembly] = dirtyTargetAssembly;\n                }\n\n                dirtyTargetAssembly.SourceFiles.Add(AssetPath.Combine(projectDirectory, scriptFile));\n            }\n\n            return ToScriptAssemblies(targetAssemblyFiles, settings, assemblies, warningSink, safeModeInfo);\n        }\n\n        internal class DirtyTargetAssembly\n        {\n            public DirtyTargetAssembly()\n            {\n                SourceFiles = new HashSet<string>();\n            }\n\n            public HashSet<string> SourceFiles { get; set; }\n        }\n\n        internal static ScriptAssembly[] ToScriptAssemblies(\n            IDictionary<TargetAssembly, DirtyTargetAssembly> targetAssemblies,\n            ScriptAssemblySettings settings,\n            CompilationAssemblies assemblies, ICompilationSetupWarningTracker warningSink, ISafeModeInfo safeModeInfo)\n        {\n            var scriptAssemblies = new ScriptAssembly[targetAssemblies.Count];\n\n            var targetToScriptAssembly = new Dictionary<TargetAssembly, ScriptAssembly>();\n            int index = 0;\n\n            bool buildingForEditor = settings.BuildingForEditor;\n            var safeModeWhiteList = new HashSet<string>(safeModeInfo.GetWhiteListAssemblyNames());\n            foreach (var entry in targetAssemblies)\n            {\n                var targetAssembly = entry.Key;\n                var dirtyTargetAssembly = entry.Value;\n                var scriptAssembly = new ScriptAssembly();\n\n                // Setup TargetAssembly -> ScriptAssembly mapping for converting references\n                scriptAssemblies[index] = scriptAssembly;\n                targetToScriptAssembly[targetAssembly] = scriptAssemblies[index++];\n\n                // Setup ScriptAssembly\n                scriptAssembly.Flags = targetAssembly.Flags;\n                scriptAssembly.BuildTarget = settings.BuildTarget;\n                scriptAssembly.OriginPath = targetAssembly.PathPrefix;\n                scriptAssembly.Filename = targetAssembly.Filename;\n                scriptAssembly.SkipCodeGen = safeModeWhiteList.Contains(targetAssembly.Filename);\n                scriptAssembly.RootNamespace = targetAssembly.Type == TargetAssemblyType.Predefined ? settings.ProjectRootNamespace : targetAssembly.RootNamespace;\n\n                scriptAssembly.OutputDirectory = settings.OutputDirectory;\n\n                var cSharpVersionDefines = targetAssembly.Defines == null ? s_CSharpVersionDefines.ToList() : targetAssembly.Defines.Concat(s_CSharpVersionDefines).ToList();\n\n                //This is used for Source Generation\n                if ((targetAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly)\n                {\n                    cSharpVersionDefines.Add(\"UNITY_EDITOR_ONLY_COMPILATION\");\n                }\n\n                scriptAssembly.Defines = cSharpVersionDefines.ToArray();\n                scriptAssembly.Files = dirtyTargetAssembly.SourceFiles.ToArray();\n                scriptAssembly.TargetAssemblyType = targetAssembly.Type;\n                scriptAssembly.AsmDefPath = targetAssembly.AsmDefPath;\n\n                if (scriptAssembly.TargetAssemblyType == TargetAssemblyType.Predefined)\n                    scriptAssembly.CompilerOptions = new ScriptCompilerOptions(settings.PredefinedAssembliesCompilerOptions);\n                else\n                    scriptAssembly.CompilerOptions = targetAssembly.CompilerOptions;\n\n                scriptAssembly.CompilerOptions.AdditionalCompilerArguments = settings.AdditionalCompilerArguments;\n\n                scriptAssembly.CompilerOptions.ApiCompatibilityLevel = settings.PredefinedAssembliesCompilerOptions.ApiCompatibilityLevel;\n\n                if ((settings.CompilationOptions & EditorScriptCompilationOptions.BuildingUseDeterministicCompilation) == EditorScriptCompilationOptions.BuildingUseDeterministicCompilation)\n                    scriptAssembly.CompilerOptions.UseDeterministicCompilation = true;\n                else\n                    scriptAssembly.CompilerOptions.UseDeterministicCompilation = false;\n\n                scriptAssembly.CompilerOptions.CodeOptimization = settings.CodeOptimization;\n            }\n\n            // Don't add the auto-referenced engine assemblies if the assembly either has the flag set, or\n            // is a codegen assembly\n            AutoReferencedPackageAssemblies.AddReferences(assemblies.CustomTargetAssemblies, settings.CompilationOptions,\n                t =>\n                {\n                    var hasNoEngineReferencesFlag = (t.Flags & AssemblyFlags.NoEngineReferences) == AssemblyFlags.NoEngineReferences;\n                    if (hasNoEngineReferencesFlag)\n                        return false;\n\n                    return !UnityCodeGenHelpers.IsCodeGen(t.Filename);\n                });\n\n            // Setup ScriptAssembly references\n            index = 0;\n            foreach (var entry in targetAssemblies)\n            {\n                var scriptAssembly = scriptAssemblies[index++];\n                AddScriptAssemblyReferences(ref scriptAssembly, entry.Key, settings, assemblies, targetToScriptAssembly, warningSink);\n\n                if (UnityCodeGenHelpers.IsCodeGen(entry.Key.Filename)\n                    ||  UnityCodeGenHelpers.IsCodeGenTest(entry.Key.Filename)\n                    || CompilationPipelineCommonHelper.ShouldAdd(entry.Key.Filename))\n                {\n                    CompilationPipelineCommonHelper.UpdateScriptAssemblyReference(ref scriptAssembly);\n                }\n\n                if (!buildingForEditor)\n                {\n                    PlatformSupportModuleHelpers.AddAdditionalPlatformSupportData(settings.CompilationExtension, ref scriptAssembly);\n                }\n                else\n                {\n                    if (settings.CompilationExtension != null)\n                        scriptAssembly.Defines = scriptAssembly.Defines.Concat(settings.CompilationExtension.GetAdditionalEditorDefines()).ToArray();\n                }\n            }\n\n            if (assemblies.RoslynAnalyzerDllPaths != null)\n                RoslynAnalyzers.SetAnalyzers(scriptAssemblies, assemblies.CustomTargetAssemblies.Values.ToArray(), assemblies.RoslynAnalyzerDllPaths, false);\n\n            return scriptAssemblies;\n        }\n\n        static bool IsPrecompiledAssemblyCompatibleWithBuildTarget(PrecompiledAssembly compiledAssembly, BuildTarget buildTarget)\n        {\n            if (buildTarget == BuildTarget.WSAPlayer)\n            {\n                // Apparently this is used for IL2CPP too. TO DO: figure out why we need this (.winmd files end up not being referenced when this gets removed)\n                bool compiledAssemblyCompatibleWithDotNet = (compiledAssembly.Flags & AssemblyFlags.UseForDotNet) == AssemblyFlags.UseForDotNet;\n                return compiledAssemblyCompatibleWithDotNet;\n            }\n\n            bool compiledAssemblyCompatibleWithMono = (compiledAssembly.Flags & AssemblyFlags.UseForMono) == AssemblyFlags.UseForMono;\n            return compiledAssemblyCompatibleWithMono;\n        }\n\n        internal static void AddScriptAssemblyReferences(ref ScriptAssembly scriptAssembly, TargetAssembly targetAssembly, ScriptAssemblySettings settings,\n            CompilationAssemblies assemblies,\n            IDictionary<TargetAssembly, ScriptAssembly> targetToScriptAssembly, ICompilationSetupWarningTracker warningSink)\n        {\n            var scriptAssemblyReferences = new List<ScriptAssembly>(targetAssembly.References.Count);\n            var references = new List<string>();\n            bool buildingForEditor = settings.BuildingForEditor;\n            bool noEngineReferences = (targetAssembly.Flags & AssemblyFlags.NoEngineReferences) == AssemblyFlags.NoEngineReferences;\n\n            bool shouldProcessPredefinedCustomTargets = assemblies.CustomTargetAssemblies != null && (targetAssembly.Type & TargetAssemblyType.Predefined) == TargetAssemblyType.Predefined;\n            var predefinedCustomTargetReferences = Enumerable.Empty<TargetAssembly>();\n            if (shouldProcessPredefinedCustomTargets && assemblies.PredefinedAssembliesCustomTargetReferences != null)\n                predefinedCustomTargetReferences = assemblies.PredefinedAssembliesCustomTargetReferences;\n\n            var unityReferences = new HashSet<string>();\n\n            // Add Unity assemblies (UnityEngine.dll, UnityEditor.dll) references, as long as the target\n            // doesn't specify that it doesn't want them.\n            if (!noEngineReferences)\n            {\n                // Add predefined custom target references in a hash-set for fast lookup\n                var predefinedCustomTargetRefs = new HashSet<string>(predefinedCustomTargetReferences.Select(x => x.Filename));\n                foreach (var unityReference in GetUnityReferences(scriptAssembly, targetAssembly,\n                             assemblies.UnityAssemblies, predefinedCustomTargetRefs, settings.CompilationOptions,\n                             UnityReferencesOptions.None))\n                {\n                    unityReferences.Add(Path.GetFileName(unityReference.Path));\n                    references.Add(unityReference.Path);\n                }\n            }\n\n            AddTestRunnerCustomReferences(ref targetAssembly, assemblies.CustomTargetAssemblies);\n\n            // Setup target assembly references\n            foreach (var reference in targetAssembly.References)\n            {\n                ScriptAssembly scriptAssemblyReference;\n\n                // If the assembly already showed up in the unity references, don't reference it here.\n                // This can happen when an assembly is configured as a unity assembly override, but\n                // overrides are disabled. The Unity assembly should take precedence in that case.\n                if (unityReferences.Contains(reference.Filename))\n                    continue;\n\n                // Add ScriptAssembly references to other dirty script assemblies that also need to be rebuilt.\n                if (targetToScriptAssembly.TryGetValue(reference, out scriptAssemblyReference))\n                {\n                    System.Diagnostics.Debug.Assert(scriptAssemblyReference != null);\n                    scriptAssemblyReferences.Add(scriptAssemblyReference);\n                }\n            }\n\n            // For predefined target assembly add references to custom target assemblies\n            if (shouldProcessPredefinedCustomTargets)\n            {\n                foreach (var customTargetAssembly in predefinedCustomTargetReferences)\n                {\n                    ScriptAssembly scriptAssemblyReference;\n\n                    // Only add ScriptAssembly reference if the custom target assembly is dirty, e.g. is in targetToScriptAssembly dictionary\n                    // Otherwise just add already compiled custom target assembly as precompiled reference.\n                    if (targetToScriptAssembly.TryGetValue(customTargetAssembly, out scriptAssemblyReference))\n                        scriptAssemblyReferences.Add(scriptAssemblyReference);\n                }\n            }\n\n            // Add pre-compiled assemblies as references\n            var allPrecompiledAssemblies = assemblies.PrecompiledAssemblies ?? new Dictionary<string, PrecompiledAssembly>(0);\n            List<PrecompiledAssembly> precompiledReferences = new List<PrecompiledAssembly>(allPrecompiledAssemblies.Count);\n            var explicitPrecompiledReferences = new List<PrecompiledAssembly>(targetAssembly.ExplicitPrecompiledReferences.Count);\n\n            if ((targetAssembly.Flags & AssemblyFlags.ExplicitReferences) == AssemblyFlags.ExplicitReferences)\n            {\n                if (!noEngineReferences)\n                {\n                    precompiledReferences.AddRange(allPrecompiledAssemblies\n                        .Where(x => (x.Value.Flags & AssemblyFlags.UserAssembly) != AssemblyFlags.UserAssembly)\n                        .Select(x => x.Value));\n                }\n\n                foreach (var explicitPrecompiledReference in targetAssembly.ExplicitPrecompiledReferences)\n                {\n                    PrecompiledAssembly assembly;\n                    if (allPrecompiledAssemblies.TryGetValue(explicitPrecompiledReference, out assembly))\n                    {\n                        explicitPrecompiledReferences.Add(assembly);\n                    }\n                }\n            }\n            else\n            {\n                var precompiledAssemblies = allPrecompiledAssemblies.Values.Where(x => (x.Flags & AssemblyFlags.ExplicitlyReferenced) != AssemblyFlags.ExplicitlyReferenced).ToList();\n\n                // if noEngineReferences, add just the non-explicitly-referenced user assemblies\n                if (noEngineReferences)\n                    precompiledReferences.AddRange(precompiledAssemblies.Where(x => (x.Flags & AssemblyFlags.UserAssembly) == AssemblyFlags.UserAssembly));\n                else\n                    precompiledReferences.AddRange(precompiledAssemblies);\n            }\n\n            AddTestRunnerPrecompiledReferences(targetAssembly, allPrecompiledAssemblies, ref precompiledReferences);\n\n            var precompiledReferenceNames = GetPrecompiledReferences(scriptAssembly, targetAssembly.Type, settings.CompilationOptions, targetAssembly.editorCompatibility, precompiledReferences, explicitPrecompiledReferences, warningSink);\n            references.AddRange(precompiledReferenceNames);\n\n            if (buildingForEditor && assemblies.EditorAssemblyReferences != null)\n                references.AddRange(assemblies.EditorAssemblyReferences);\n\n            var editorOnlyTargetAssembly = (targetAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly;\n            if (editorOnlyTargetAssembly)\n            {\n                var editorApiCompatibility = PlayerSettings.EditorAssemblyCompatibilityToApiCompatibility(PlayerSettings.GetEditorAssembliesCompatibilityLevel());\n                references.AddRange(MonoLibraryHelpers.GetSystemLibraryReferences(editorApiCompatibility));\n                references.AddRange(MonoLibraryHelpers.GetEditorExtensionsReferences(editorApiCompatibility));\n            }\n            else\n            {\n                references.AddRange(MonoLibraryHelpers.GetSystemLibraryReferences(scriptAssembly.CompilerOptions.ApiCompatibilityLevel));\n            }\n\n            scriptAssembly.ScriptAssemblyReferences = scriptAssemblyReferences.ToArray();\n            scriptAssembly.References = references.ToArray();\n        }\n\n        internal static void AddTestRunnerCustomReferences(ref TargetAssembly targetAssembly, Dictionary<string, TargetAssembly> assembliesCustomTargetAssemblies)\n        {\n            if (TestRunnerHelpers.ShouldAddTestRunnerReferences(targetAssembly) && assembliesCustomTargetAssemblies != null)\n            {\n                targetAssembly.References.AddRange(TestRunnerHelpers.GetReferences(assembliesCustomTargetAssemblies.Values));\n            }\n        }\n\n        internal static void AddTestRunnerPrecompiledReferences(TargetAssembly targetAssembly, Dictionary<string, PrecompiledAssembly> nameToPrecompiledAssemblies, ref List<PrecompiledAssembly> precompiledReferences)\n        {\n            if (TestRunnerHelpers.ShouldAddNunitReferences(targetAssembly))\n            {\n                TestRunnerHelpers.AddNunitReferences(nameToPrecompiledAssemblies, ref precompiledReferences);\n            }\n        }\n\n        public static PrecompiledAssembly[] GetUnityReferences(ScriptAssembly scriptAssembly, PrecompiledAssembly[] unityAssemblies, EditorScriptCompilationOptions options, UnityReferencesOptions unityReferencesOptions)\n        {\n            return GetUnityReferences(scriptAssembly, null, unityAssemblies, options, unityReferencesOptions);\n        }\n\n        public static PrecompiledAssembly[] GetUnityReferences(ScriptAssembly scriptAssembly, TargetAssembly targetAssembly, PrecompiledAssembly[] unityAssemblies, EditorScriptCompilationOptions options, UnityReferencesOptions unityReferencesOptions)\n        {\n            return GetUnityReferences(scriptAssembly, targetAssembly, unityAssemblies, null, options, unityReferencesOptions);\n        }\n\n        public static PrecompiledAssembly[] GetUnityReferences(ScriptAssembly scriptAssembly, TargetAssembly targetAssembly, PrecompiledAssembly[] unityAssemblies, HashSet<string> predefinedCustomTargetReferences, EditorScriptCompilationOptions options, UnityReferencesOptions unityReferencesOptions)\n        {\n            var references = new List<PrecompiledAssembly>();\n\n            bool assemblyEditorOnly = (scriptAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly;\n            bool buildingForEditor = (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor;\n            bool excludeUnityModules = unityReferencesOptions == UnityReferencesOptions.ExcludeModules;\n\n            // Add Unity assemblies (UnityEngine.dll, UnityEditor.dll) referencees.\n            if (unityAssemblies == null)\n                return references.ToArray();\n\n            foreach (var unityAssembly in unityAssemblies)\n            {\n                var isUnityModule = (unityAssembly.Flags & AssemblyFlags.UnityModule) == AssemblyFlags.UnityModule;\n\n                if (isUnityModule && excludeUnityModules)\n                    continue;\n\n                var moduleExcludedForRuntimeCode = (unityAssembly.Flags & AssemblyFlags.ExcludedForRuntimeCode) == AssemblyFlags.ExcludedForRuntimeCode;\n\n                // Add Unity editor assemblies (UnityEditor.dll) to all assemblies when building inside the editor\n                if ((buildingForEditor && !moduleExcludedForRuntimeCode) || assemblyEditorOnly)\n                {\n                    if ((unityAssembly.Flags & AssemblyFlags.UseForMono) != 0)\n                        references.Add(unityAssembly);\n                }\n                else\n                {\n                    bool unityAssemblyEditorOnly = (unityAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly;\n\n                    // Add Unity runtime assemblies (UnityEngine.dll) to all assemblies\n                    if (!unityAssemblyEditorOnly && !moduleExcludedForRuntimeCode)\n                    {\n                        if (IsPrecompiledAssemblyCompatibleWithBuildTarget(unityAssembly, scriptAssembly.BuildTarget))\n                            references.Add(unityAssembly);\n                    }\n                }\n            }\n\n            return references.ToArray();\n        }\n\n        public static List<string> GetPrecompiledReferences(ScriptAssembly scriptAssembly, TargetAssemblyType targetAssemblyType, EditorScriptCompilationOptions options, EditorCompatibility editorCompatibility, IEnumerable<PrecompiledAssembly> implicitPrecompiledAssemblies, IEnumerable<PrecompiledAssembly> explicitPrecompiledAssemblies, ICompilationSetupWarningTracker warningSink)\n        {\n            var references = new List<string>();\n\n            bool buildingForEditor = (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor;\n            bool assemblyEditorOnly = (scriptAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly;\n            bool isCustomAssembly = (targetAssemblyType & TargetAssemblyType.Custom) == TargetAssemblyType.Custom;\n\n            void AddReferenceIfMatchBuildTargetAndEditorFlag(PrecompiledAssembly precompiledAssembly, bool explicitReference)\n            {\n                bool compiledAssemblyEditorOnly = (precompiledAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly;\n\n                // Add all pre-compiled runtime assemblies as references to all script assemblies. Don't add pre-compiled editor assemblies as dependencies to runtime assemblies.\n                if (!compiledAssemblyEditorOnly || assemblyEditorOnly || (isCustomAssembly && buildingForEditor && editorCompatibility == EditorCompatibility.CompatibleWithEditor))\n                {\n                    if (IsPrecompiledAssemblyCompatibleWithBuildTarget(precompiledAssembly, scriptAssembly.BuildTarget))\n                    {\n                        references.Add(precompiledAssembly.Path);\n                    }\n                    // we don't warn on build target mismatch, as this is actually a common pattern (an asmdef with multiple references to different \"target-specific\" assemblies with the same symbols - e.g. foo.XboxOne.dll, foo.PS5.dll, foo.WebGL.dll)\n                }\n                else if (explicitReference && !string.IsNullOrEmpty(scriptAssembly.AsmDefPath))\n                {\n                    warningSink?.AddAssetWarning(scriptAssembly.AsmDefPath, $\"{scriptAssembly.Filename}: can't add reference to {precompiledAssembly.Path} as it is an editor-only assembly\");\n                }\n            }\n\n            if (implicitPrecompiledAssemblies != null)\n            {\n                foreach (var precompiledAssembly in implicitPrecompiledAssemblies)\n                {\n                    AddReferenceIfMatchBuildTargetAndEditorFlag(precompiledAssembly, false);\n                }\n            }\n            if (explicitPrecompiledAssemblies != null)\n            {\n                foreach (var precompiledAssembly in explicitPrecompiledAssemblies)\n                {\n                    AddReferenceIfMatchBuildTargetAndEditorFlag(precompiledAssembly, true);\n                }\n            }\n\n            return references;\n        }\n\n        public static List<string> GetCompiledCustomAssembliesReferences(ScriptAssembly scriptAssembly, IDictionary<string, TargetAssembly> customTargetAssemblies, string outputDirectory)\n        {\n            var references = new List<string>();\n\n            if (customTargetAssemblies != null)\n            {\n                foreach (var entry in customTargetAssemblies)\n                {\n                    var customTargetAssembly = entry.Value;\n                    var customTargetAssemblyPath = customTargetAssembly.FullPath(outputDirectory);\n\n                    // File might not exist if there are no scripts in the custom target assembly folder.\n                    if (AssetPath.Exists(customTargetAssemblyPath))\n                        references.Add(customTargetAssemblyPath);\n                }\n            }\n\n            return references;\n        }\n\n        static bool IsCompatibleWithEditor(ScriptAssemblySettings settings)\n        {\n            return (settings.CompilationOptions & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor;\n        }\n\n        public static bool IsCompatibleWithPlatformAndDefines(TargetAssembly assembly, ScriptAssemblySettings settings)\n        {\n            return assembly.IsCompatibleFunc == null || assembly.IsCompatibleFunc(settings, assembly.Defines);\n        }\n\n        public static bool IsCompatibleWithPlatformAndDefines(TargetAssembly assembly, BuildTarget buildTarget, EditorScriptCompilationOptions options)\n        {\n            var settings = new ScriptAssemblySettings\n            {\n                BuildTarget = buildTarget,\n                CompilationOptions = options\n            };\n\n            return IsCompatibleWithPlatformAndDefines(assembly, settings);\n        }\n\n        internal static Dictionary<string, TargetAssembly> CreatePredefinedTargetAssemblies()\n        {\n            var runtimeFirstPassAssemblies = new List<TargetAssembly>();\n            var runtimeAssemblies = new List<TargetAssembly>();\n            var editorFirstPassAssemblies = new List<TargetAssembly>();\n            var editorAssemblies = new List<TargetAssembly>();\n\n            var assemblies = new List<TargetAssembly>();\n\n            var scriptCompilerOptions = new ScriptCompilerOptions();\n\n            // Initialize predefined assembly targets\n            {\n                const string languageName = \"CSharp\";\n\n                var runtimeFirstPass = new TargetAssembly(\"Assembly-\" + languageName + \"-firstpass\" + \".dll\",\n                    AssemblyFlags.FirstPass | AssemblyFlags.UserAssembly,\n                    TargetAssemblyType.Predefined,\n                    null,\n                    null,\n                    FilterAssemblyInFirstpassFolder,\n                    null,\n                    scriptCompilerOptions);\n\n                var runtime = new TargetAssembly(\"Assembly-\" + languageName + \".dll\",\n                    AssemblyFlags.UserAssembly,\n                    TargetAssemblyType.Predefined,\n                    null,\n                    null,\n                    null,\n                    null,\n                    scriptCompilerOptions);\n\n                var editorFirstPass = new TargetAssembly(\"Assembly-\" + languageName + \"-Editor-firstpass\" + \".dll\",\n                    AssemblyFlags.EditorOnly | AssemblyFlags.FirstPass | AssemblyFlags.UserAssembly,\n                    TargetAssemblyType.Predefined,\n                    null,\n                    null,\n                    FilterAssemblyInFirstpassEditorFolder,\n                    (settings, defines) => IsCompatibleWithEditor(settings),\n                    scriptCompilerOptions);\n\n                var editor = new TargetAssembly(\"Assembly-\" + languageName + \"-Editor\" + \".dll\",\n                    AssemblyFlags.EditorOnly | AssemblyFlags.UserAssembly,\n                    TargetAssemblyType.Predefined,\n                    null,\n                    null,\n                    FilterAssemblyInEditorFolder,\n                    (settings, defines) => IsCompatibleWithEditor(settings),\n                    scriptCompilerOptions);\n\n                runtimeFirstPassAssemblies.Add(runtimeFirstPass);\n                runtimeAssemblies.Add(runtime);\n                editorFirstPassAssemblies.Add(editorFirstPass);\n                editorAssemblies.Add(editor);\n\n                assemblies.Add(runtimeFirstPass);\n                assemblies.Add(runtime);\n                assemblies.Add(editorFirstPass);\n                assemblies.Add(editor);\n            }\n\n            // Setup dependencies\n\n            // Runtime assemblies depend all first pass runtime assemblies\n            foreach (var assembly in runtimeAssemblies)\n                assembly.References.AddRange(runtimeFirstPassAssemblies);\n\n            // First pass editor assemblies depend on all first pass runtime assemblies\n            foreach (var assembly in editorFirstPassAssemblies)\n                assembly.References.AddRange(runtimeFirstPassAssemblies);\n\n            // Editor assemblies depend on all previous runtime and editor assemblies\n            foreach (var assembly in editorAssemblies)\n            {\n                assembly.References.AddRange(runtimeFirstPassAssemblies);\n                assembly.References.AddRange(runtimeAssemblies);\n                assembly.References.AddRange(editorFirstPassAssemblies);\n            }\n\n            return assemblies.ToDictionary(x => x.Filename);\n        }\n\n        internal static TargetAssembly[] GetTargetAssembliesWithScripts(\n            Dictionary<string, string> allScripts,\n            string projectDirectory,\n            IDictionary<string, TargetAssembly> customTargetAssemblies,\n            ScriptAssemblySettings settings)\n        {\n            return GetTargetAssembliesWithScriptsHashSet(allScripts, projectDirectory, customTargetAssemblies, settings).ToArray();\n        }\n\n        internal static HashSet<TargetAssembly> GetTargetAssembliesWithScriptsHashSet(\n            Dictionary<string, string> allScripts,\n            string projectDirectory,\n            IDictionary<string, TargetAssembly> customTargetAssemblies,\n            ScriptAssemblySettings settings)\n        {\n            var uniqueTargetAssemblies = new HashSet<TargetAssembly>();\n\n            foreach (var entry in allScripts)\n            {\n                var script = entry.Key;\n                var assemblyName = entry.Value;\n                var targetAssembly = GetTargetAssembly(script, assemblyName, projectDirectory, customTargetAssemblies);\n\n                // This can happen for scripts in packages that are not included in an .asmdef assembly\n                // and they will therefore not be compiled.\n                if (targetAssembly == null)\n                    continue;\n\n                if (!IsCompatibleWithPlatformAndDefines(targetAssembly, settings))\n                    continue;\n\n                uniqueTargetAssemblies.Add(targetAssembly);\n            }\n\n            return uniqueTargetAssemblies;\n        }\n\n        internal static TargetAssembly GetTargetAssembly(string scriptPath, string assemblyName, string projectDirectory, IDictionary<string, TargetAssembly> customTargetAssemblies)\n        {\n            TargetAssembly resultAssembly;\n\n            if (assemblyName != null &&\n                customTargetAssemblies != null &&\n                customTargetAssemblies.Count > 0 &&\n                customTargetAssemblies.TryGetValue(assemblyName, out resultAssembly))\n            {\n                return resultAssembly;\n            }\n\n            return GetPredefinedTargetAssembly(scriptPath, assemblyName);\n        }\n\n        static string ScriptPathToLowerCase(string scriptPath)\n        {\n            int length = scriptPath.Length;\n\n            var chars = new char[length + 1];\n\n            chars[0] = '/';\n\n            for (int i = 0; i < length; ++i)\n            {\n                char stringChar = scriptPath[i];\n\n                if (stringChar == '\\\\')\n                    chars[i + 1] = AssetPath.Separator;\n                else\n                    chars[i + 1] = Utility.FastToLower(stringChar);\n            }\n\n            return new string(chars);\n        }\n\n        internal static TargetAssembly GetPredefinedTargetAssembly(string scriptPath, string assemblyName = null)\n        {\n            if (assemblyName == null)\n            {\n                TargetAssembly resultAssembly = null;\n                var lowerPath = ScriptPathToLowerCase(scriptPath);\n                int highestPathDepth = -1;\n                foreach (var assembly in predefinedTargetAssemblies.Values)\n                {\n                    var pathDepth = assembly.PathFilter?.Invoke(lowerPath) ?? 0;\n                     if (pathDepth <= highestPathDepth)\n\n                    {\n                     continue;\n\n                    }\n                    resultAssembly = assembly;\n                    highestPathDepth = pathDepth;\n                }\n                return resultAssembly;\n            }\n\n            if (predefinedTargetAssemblies.TryGetValue(assemblyName, out var predefined))\n            {\n                return predefined;\n            }\n            return null;\n        }\n\n        static int FilterAssemblyInFirstpassFolder(string pathName)\n        {\n            int result;\n\n            result = FilterAssemblyPathBeginsWith(pathName, \"/assets/plugins/\");\n            if (result >= 0) return result;\n\n            result = FilterAssemblyPathBeginsWith(pathName, \"/assets/standard assets/\");\n            if (result >= 0) return result;\n\n            result = FilterAssemblyPathBeginsWith(pathName, \"/assets/pro standard assets/\");\n            if (result >= 0) return result;\n\n            result = FilterAssemblyPathBeginsWith(pathName, \"/assets/iphone standard assets/\");\n            if (result >= 0) return result;\n\n            return -1;\n        }\n\n        static int FilterAssemblyInFirstpassEditorFolder(string pathName)\n        {\n            int baseIndex = FilterAssemblyInFirstpassFolder(pathName);\n            if (baseIndex == -1) return -1;\n\n            return FilterAssemblyInEditorFolder(pathName);\n        }\n\n        static int FilterAssemblyInEditorFolder(string pathName)\n        {\n            const string editorSegment = \"/editor/\";\n            int editorSegmentIndex = pathName.IndexOf(editorSegment, StringComparison.InvariantCulture);\n            if (editorSegmentIndex == -1) return -1;\n\n            return editorSegmentIndex + editorSegment.Length;\n        }\n\n        static int FilterAssemblyPathBeginsWith(string pathName, string lowerPrefix)\n        {\n            return Utility.FastStartsWith(pathName, lowerPrefix, lowerPrefix) ? lowerPrefix.Length : -1;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing NiceIO;\nusing Bee.BeeDriver;\nusing Bee.BinLog;\nusing ScriptCompilationBuildProgram.Data;\nusing Unity.Profiling;\nusing UnityEditor.Compilation;\nusing UnityEditor.Modules;\nusing UnityEditor.Scripting.Compilers;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Assertions;\nusing UnityEngine.Profiling;\nusing CompilerMessage = UnityEditor.Scripting.Compilers.CompilerMessage;\nusing CompilerMessageType = UnityEditor.Scripting.Compilers.CompilerMessageType;\nusing Directory = System.IO.Directory;\nusing File = System.IO.File;\nusing UnityEditor.Build;\nusing UnityEngine.Pool;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal interface IEditorCompilation\n    {\n        PrecompiledAssemblyProviderBase PrecompiledAssemblyProvider { get; set; }\n\n        ScriptAssembly[] GetAllScriptAssemblies(\n            EditorScriptCompilationOptions options,\n            PrecompiledAssembly[] unityAssembliesArg,\n            Dictionary<string, PrecompiledAssembly> precompiledAssembliesArg,\n            string[] defines);\n    }\n\n    class EditorCompilation : IEditorCompilation\n    {\n        const int kLogIdentifierFor_EditorMessages = 1234;\n        const int kLogIdentifierFor_PlayerMessages = 1235;\n\n        public enum CompileStatus\n        {\n            Idle,\n            Compiling,\n            CompilationStarted,\n            CompilationFailed,\n            CompilationComplete\n        }\n\n        public enum DeleteFileOptions\n        {\n            NoLogError = 0,\n            LogError = 1,\n        }\n\n        [StructLayout(LayoutKind.Sequential)]\n        public struct TargetAssemblyInfo\n        {\n            public string Name;\n            public AssemblyFlags Flags;\n\n            public static readonly TargetAssemblyInfo Unknown = new TargetAssemblyInfo { Flags = AssemblyFlags.None, Name = null };\n        }\n\n        public struct CustomScriptAssemblyAndReference\n        {\n            public CustomScriptAssembly Assembly;\n            public CustomScriptAssembly Reference;\n        }\n\n        public PrecompiledAssemblyProviderBase PrecompiledAssemblyProvider { get; set; } = new PrecompiledAssemblyProvider();\n        public ICompilationSetupErrorsTracker CompilationSetupErrorsTracker { get; set; } = new CompilationSetupErrorsTracker();\n        public ResponseFileProvider ResponseFileProvider { get; set; } = new MicrosoftCSharpResponseFileProvider();\n        public ILoadingAssemblyDefinition loadingAssemblyDefinition { get; set; } = new LoadingAssemblyDefinition();\n        public IVersionDefinesConsoleLogs VersionDefinesConsoleLogs { get; set; } = new VersionDefinesConsoleLogs();\n        public ICompilationSetupWarningTracker CompilationSetupWarningTracker { get; set; } = new CompilationSetupWarningTracker();\n        public ISafeModeInfo SafeModeInfo { get; set; } = new SafeModeInfo();\n\n\n        public bool EnableDiagnostics => (bool)Debug.GetDiagnosticSwitch(\"EnableDomainReloadTimings\").value;\n\n        internal string projectDirectory = string.Empty;\n        Dictionary<string, string> allScripts = new Dictionary<string, string>();\n\n        bool m_ScriptsForEditorHaveBeenCompiledSinceLastDomainReload;\n        RequestScriptCompilationOptions? m_ScriptCompilationRequest = null;\n        List<CustomScriptAssemblyReference> customScriptAssemblyReferences = new List<CustomScriptAssemblyReference>();\n        Dictionary<string, TargetAssembly> customTargetAssemblies = new Dictionary<string, TargetAssembly>(); // TargetAssemblies for customScriptAssemblies.\n        PrecompiledAssembly[] unityAssemblies;\n\n        string outputDirectory;\n        bool skipCustomScriptAssemblyGraphValidation = false;\n        [Obsolete]\n        List<AssemblyBuilder> assemblyBuilders = new List<AssemblyBuilder>();\n        bool _logCompilationMessages = true;\n\n        AssetPathMetaData[] m_AssetPathsMetaData;\n        Dictionary<string, VersionMetaData> m_VersionMetaDatas;\n        private readonly CachedVersionRangesFactory<UnityVersion> m_UnityVersionRanges = new CachedVersionRangesFactory<UnityVersion>();\n        private readonly CachedVersionRangesFactory<SemVersion> m_SemVersionRanges = new CachedVersionRangesFactory<SemVersion>();\n\n        public event Action<object> compilationStarted;\n        public event Action<object> compilationFinished;\n        public event Action<ScriptAssembly> assemblyCompilationNotRequired;\n        public event Action<ScriptAssembly, UnityEditor.Compilation.CompilerMessage[]> assemblyCompilationFinished;\n\n        class BeeScriptCompilationState\n        {\n            public CancellationTokenSource CancellationTokenSource { get; set; }\n            public ScriptAssembly[] ScriptAssemblies { get; set; }\n            public ScriptAssemblySettings Settings { get; set; }\n            public ActiveBuild ActiveBuild { get; set; }\n            public NPath BeeDriverProfilerFile { get; set; }\n\n            public int AsyncProgressBarToken { get; set; }\n        }\n\n        BeeScriptCompilationState _currentBeeScriptCompilationState;\n\n        CompilerMessage[] _currentEditorCompilationCompilerMessages = new CompilerMessage[0];\n\n        public void SetProjectDirectory(string projectDirectory)\n        {\n            this.projectDirectory = projectDirectory;\n        }\n\n        public Exception[] SetAssetPathsMetaData(AssetPathMetaData[] assetPathMetaDatas)\n        {\n            m_AssetPathsMetaData = assetPathMetaDatas;\n\n            var versionMetaDataComparer = new VersionMetaDataComparer();\n\n            m_VersionMetaDatas = assetPathMetaDatas?\n                .Where(x => x.VersionMetaData != null)\n                .Select(x => x.VersionMetaData)\n                .Distinct(versionMetaDataComparer)\n                .ToDictionary(x => x.Name, x => x);\n\n            return UpdateCustomTargetAssembliesAssetPathsMetaData(\n                loadingAssemblyDefinition.CustomScriptAssemblies,\n                assetPathMetaDatas,\n                forceUpdate: true);\n        }\n\n        public void SetAdditionalVersionMetaDatas(VersionMetaData[] versionMetaDatas)\n        {\n            Assert.IsTrue(m_VersionMetaDatas != null, \"EditorCompilation.SetAssetPathsMetaData() must be called before EditorCompilation.SetAdditionalVersionMetaDatas()\");\n            foreach (var versionMetaData in versionMetaDatas)\n            {\n                m_VersionMetaDatas[versionMetaData.Name] = versionMetaData;\n            }\n        }\n\n        public AssetPathMetaData[] GetAssetPathsMetaData()\n        {\n            return m_AssetPathsMetaData;\n        }\n\n        public Dictionary<string, VersionMetaData> GetVersionMetaDatas()\n        {\n            return m_VersionMetaDatas;\n        }\n\n        private IAssemblyGraphBuilder GetAssemblyGraphBuilder()\n        {\n            return AssemblyGraphBuilderFactory.GetOrCreate(Path.Combine(projectDirectory, \"Assets\"),\n                loadingAssemblyDefinition.CustomScriptAssemblies,\n                loadingAssemblyDefinition.CustomScriptAssemblyReferences);\n        }\n\n        public void SetAllScripts(string[] allScripts)\n        {\n            Assert.IsNotNull(customTargetAssemblies);\n            var graphBuilder = GetAssemblyGraphBuilder();\n            var graph = graphBuilder.Match(allScripts);\n\n            this.allScripts.Clear();\n            foreach (var assemblyScriptsPair in graph)\n            {\n                foreach (var scriptPath in assemblyScriptsPair.Value)\n                {\n                    this.allScripts.Add(scriptPath, assemblyScriptsPair.Key.Name  + \".dll\");\n                }\n            }\n        }\n\n        public bool HaveScriptsForEditorBeenCompiledSinceLastDomainReload()\n        {\n            return m_ScriptsForEditorHaveBeenCompiledSinceLastDomainReload;\n        }\n\n        public void RequestScriptCompilation(string reason = null, RequestScriptCompilationOptions options = RequestScriptCompilationOptions.None)\n        {\n            if (reason != null)\n            {\n                Console.WriteLine($\"[ScriptCompilation] Requested script compilation because: {reason}\");\n            }\n            PrecompiledAssemblyProvider.Dirty();\n            m_ScriptCompilationRequest = options;\n            CancelActiveBuild();\n        }\n\n        internal static void ClearBeeBuildArtifacts()\n        {\n            NPath beeFolder = \"Library/Bee\";\n            if (beeFolder.DirectoryExists())\n            {\n                foreach (var path in beeFolder.Contents()\n                             .Where(p =>\n                                 // We should not delete the tundra build state file, as we then lose any information on which files we built.\n                                 // This information is used to delete stale output files which are no longer needed. If we delete this file,\n                                 // you can end up with old output files included in your builds, which we should not ship with.\n                                 p.FileName != \"TundraBuildState.state\" &&\n\n                                 // If the bee_backend.info file changes, we delete the dag folder (See `UnityBeeDriver.RecreateDagDirectoryIfNeeded`)\n                                 // which makes the above not work, unless we also keep this file.\n                                 p.FileName != \"bee_backend.info\"))\n                    path.Delete(DeleteMode.Soft);\n            }\n\n            Mono.Utils.Pram.PramDataDirectory.DeleteIfExists(DeleteMode.Soft);\n        }\n\n        public void SetAllUnityAssemblies(PrecompiledAssembly[] unityAssemblies)\n        {\n            this.unityAssemblies = unityAssemblies;\n        }\n\n        // Burst package depends on this method, so we can't remove it.\n        public void SetCompileScriptsOutputDirectory(string directory)\n        {\n            outputDirectory = directory;\n        }\n\n        public string GetCompileScriptsOutputDirectory()\n        {\n            if (string.IsNullOrEmpty(outputDirectory))\n            {\n                throw new Exception(\"Must set an output directory through SetCompileScriptsOutputDirectory before compiling\");\n            }\n            return outputDirectory;\n        }\n\n        //Used by the TestRunner package.\n        public PrecompiledAssembly[] GetAllPrecompiledAssemblies()\n        {\n            return PrecompiledAssemblyProvider.GetPrecompiledAssemblies(\n                EditorScriptCompilationOptions.BuildingForEditor | EditorScriptCompilationOptions.BuildingWithAsserts,\n                EditorUserBuildSettings.activeBuildTarget);\n        }\n\n\n\n        public void GetAssemblyDefinitionReferencesWithMissingAssemblies(out List<CustomScriptAssemblyReference> referencesWithMissingAssemblies)\n        {\n            var nameLookup = loadingAssemblyDefinition.CustomScriptAssemblies.ToDictionary(x => x.Name);\n            referencesWithMissingAssemblies = new List<CustomScriptAssemblyReference>();\n            foreach (var asmref in loadingAssemblyDefinition.CustomScriptAssemblyReferences)\n            {\n                if (!nameLookup.ContainsKey(asmref.Reference))\n                {\n                    referencesWithMissingAssemblies.Add(asmref);\n                }\n            }\n        }\n\n        public TargetAssembly GetCustomTargetAssemblyFromName(string name)\n        {\n            TargetAssembly targetAssembly;\n\n            if (name.EndsWith(\".dll\", StringComparison.Ordinal))\n            {\n                customTargetAssemblies.TryGetValue(name, out targetAssembly);\n            }\n            else\n            {\n                customTargetAssemblies.TryGetValue(name + \".dll\", out targetAssembly);\n            }\n\n            if (targetAssembly == null)\n            {\n                throw new ArgumentException(\"Assembly not found\", name);\n            }\n\n            return targetAssembly;\n        }\n\n        public TargetAssemblyInfo[] GetAllCompiledAndResolvedTargetAssemblies(\n            EditorScriptCompilationOptions options,\n            BuildTarget buildTarget,\n            out CustomScriptAssemblyAndReference[] assembliesWithMissingReference)\n        {\n            var allTargetAssemblies = GetTargetAssemblies();\n            var targetAssemblyCompiledPaths = CollectCompiledAssemblies(allTargetAssemblies);\n\n\n            var removedCustomAssemblies = new List<CustomScriptAssemblyAndReference>();\n            var assembliesWithScripts = GetTargetAssembliesWithScriptsHashSet(options);\n\n            bool removed;\n            do\n            {\n                removed = false;\n\n                if (targetAssemblyCompiledPaths.Count <= 0)\n                {\n                    continue;\n                }\n\n                foreach (var assembly in allTargetAssemblies)\n                {\n                    if (!targetAssemblyCompiledPaths.ContainsKey(assembly))\n                    {\n                        continue;\n                    }\n\n                    removed = VerifyReferencesIsCompiled(options, buildTarget, assembly, assembliesWithScripts, targetAssemblyCompiledPaths, removedCustomAssemblies, removed);\n                }\n            }\n            while (removed);\n\n            var count = targetAssemblyCompiledPaths.Count;\n            var targetAssemblies = new TargetAssemblyInfo[count];\n            int index = 0;\n\n            foreach (var entry in targetAssemblyCompiledPaths)\n            {\n                var assembly = entry.Key;\n                targetAssemblies[index++] = ToTargetAssemblyInfo(assembly);\n            }\n\n            assembliesWithMissingReference = removedCustomAssemblies.ToArray();\n            return targetAssemblies;\n        }\n\n        /// <returns>A map of all target assemblies that exists on disk and their full path</returns>\n        Dictionary<TargetAssembly, string> CollectCompiledAssemblies(TargetAssembly[] allTargetAssemblies)\n        {\n            var targetAssemblyCompiledPaths = new Dictionary<TargetAssembly, string>();\n            foreach (var assembly in allTargetAssemblies)\n            {\n                var path = assembly.FullPath(outputDirectory);\n\n                if (File.Exists(path))\n                {\n                    targetAssemblyCompiledPaths.Add(assembly, path);\n                }\n            }\n\n            return targetAssemblyCompiledPaths;\n        }\n\n        /// <summary>\n        /// Check for each compiled assembly that all its references have also been compiled.\n        /// If not, remove it from the list of compiled assemblies.\n        /// We update the removedCustomAssemblies with the assembly and the removed reference.\n        ///\n        /// References that are not compatible with the current build target, will not be checked as these haven't been compiled.\n        /// The same is true if the reference does not have any scripts,\n        /// or if the compiled assembly type is undefined or predefined\n        /// </summary>\n        /// <returns>Whether a reference was removed</returns>\n        bool VerifyReferencesIsCompiled(\n            EditorScriptCompilationOptions options,\n            BuildTarget buildTarget,\n            TargetAssembly assembly,\n            HashSet<TargetAssembly> assembliesWithScripts,\n            Dictionary<TargetAssembly, string> targetAssemblyCompiledPaths,\n            List<CustomScriptAssemblyAndReference> removedCustomAssemblies,\n            bool removed)\n        {\n            foreach (var reference in assembly.References)\n            {\n                if (!EditorBuildRules.IsCompatibleWithPlatformAndDefines(reference, buildTarget, options))\n                {\n                    continue;\n                }\n\n                if (!assembliesWithScripts.Contains(reference))\n                {\n                    continue;\n                }\n\n                if (assembly.Type == TargetAssemblyType.Predefined\n                    || assembly.Type == TargetAssemblyType.Undefined\n                    || targetAssemblyCompiledPaths.ContainsKey(reference))\n                {\n                    continue;\n                }\n\n                targetAssemblyCompiledPaths.Remove(assembly);\n\n                var removedAssemblyAndReference = new CustomScriptAssemblyAndReference\n                {\n                    Assembly = FindCustomTargetAssemblyFromTargetAssembly(assembly),\n                    Reference = FindCustomTargetAssemblyFromTargetAssembly(reference)\n                };\n                removedCustomAssemblies.Add(removedAssemblyAndReference);\n                removed = true;\n                break;\n            }\n\n            return removed;\n        }\n\n        public static Exception[] UpdateCustomScriptAssemblies(CustomScriptAssembly[] customScriptAssemblies,\n            List<CustomScriptAssemblyReference> customScriptAssemblyReferences,\n            AssetPathMetaData[] assetPathsMetaData,\n            ResponseFileProvider responseFileProvider)\n        {\n            var asmrefLookup = customScriptAssemblyReferences.ToLookup(x => x.Reference);\n\n            AddAdditionalPrefixes(customScriptAssemblies, asmrefLookup);\n            UpdateCustomTargetAssembliesResponseFileData(customScriptAssemblies, responseFileProvider);\n            return UpdateCustomTargetAssembliesAssetPathsMetaData(customScriptAssemblies, assetPathsMetaData);\n        }\n\n        /// <summary>\n        /// Assign the found references or null.\n        /// We need to assign null so as not to hold onto references that may have been removed/changed.\n        /// </summary>\n        static void AddAdditionalPrefixes(CustomScriptAssembly[] customScriptAssemblies, ILookup<string, CustomScriptAssemblyReference> asmrefLookup)\n        {\n            foreach (var assembly in customScriptAssemblies)\n            {\n                var foundAsmRefs = asmrefLookup[assembly.Name];\n\n                assembly.AdditionalPrefixes = foundAsmRefs.Any() ? foundAsmRefs.Select(ar => ar.PathPrefix).ToArray() : null;\n            }\n        }\n\n        static void UpdateCustomTargetAssembliesResponseFileData(CustomScriptAssembly[] customScriptAssemblies, ResponseFileProvider responseFileProvider)\n        {\n            foreach (var assembly in customScriptAssemblies)\n            {\n                string rspFile = responseFileProvider.Get(assembly.PathPrefix)\n                    .SingleOrDefault();\n                if (!string.IsNullOrEmpty(rspFile))\n                {\n                    var responseFileContent = MicrosoftResponseFileParser.GetResponseFileContent(Directory.GetParent(Application.dataPath).FullName, rspFile);\n                    var compilerOptions = MicrosoftResponseFileParser.GetCompilerOptions(responseFileContent);\n                    assembly.ResponseFileDefines = MicrosoftResponseFileParser.GetDefines(compilerOptions).ToArray();\n                }\n            }\n        }\n\n        static Exception[] UpdateCustomTargetAssembliesAssetPathsMetaData(\n            CustomScriptAssembly[] customScriptAssemblies,\n            AssetPathMetaData[] assetPathsMetaData,\n            bool forceUpdate = false)\n        {\n            if (assetPathsMetaData == null)\n            {\n                return new Exception[0];\n            }\n\n            var assetMetaDataPaths = new string[assetPathsMetaData.Length];\n            var lowerAssetMetaDataPaths = new string[assetPathsMetaData.Length];\n\n            for (int i = 0; i < assetPathsMetaData.Length; ++i)\n            {\n                var assetPathMetaData = assetPathsMetaData[i];\n                assetMetaDataPaths[i] = AssetPath.ReplaceSeparators(assetPathMetaData.DirectoryPath + AssetPath.Separator);\n                lowerAssetMetaDataPaths[i] = Utility.FastToLower(assetMetaDataPaths[i]);\n            }\n\n            var exceptions = new List<Exception>();\n            foreach (var assembly in customScriptAssemblies)\n            {\n                if (assembly.AssetPathMetaData != null && !forceUpdate)\n                {\n                    continue;\n                }\n\n                try\n                {\n                    for (int i = 0; i < assetMetaDataPaths.Length; ++i)\n                    {\n                        var path = assetMetaDataPaths[i];\n                        var lowerPath = lowerAssetMetaDataPaths[i];\n\n                        if (Utility.FastStartsWith(assembly.PathPrefix, path, lowerPath))\n                        {\n                            assembly.AssetPathMetaData = assetPathsMetaData[i];\n                            break;\n                        }\n                    }\n                }\n                catch (Exception e)\n                {\n                    exceptions.Add(e);\n                }\n            }\n\n            return exceptions.ToArray();\n        }\n\n        Exception[] UpdateCustomTargetAssemblies()\n        {\n            var exceptions = UpdateCustomScriptAssemblies(\n                loadingAssemblyDefinition.CustomScriptAssemblies,\n                loadingAssemblyDefinition.CustomScriptAssemblyReferences,\n                m_AssetPathsMetaData,\n                ResponseFileProvider);\n\n            if (exceptions.Length > 0)\n            {\n                CompilationSetupErrorsTracker.SetCompilationSetupErrors(CompilationSetupErrors.LoadError);\n            }\n\n            customTargetAssemblies = EditorBuildRules.CreateTargetAssemblies(loadingAssemblyDefinition.CustomScriptAssemblies);\n            return exceptions;\n        }\n\n        public void SkipCustomScriptAssemblyGraphValidation(bool skipChecks)\n        {\n            // If we have successfully compiled and reloaded all assemblies, then we can skip asmdef compilation graph checks\n            // for setup errors like cyclic references, self-references, duplicate assembly names, etc.\n            // If there is compilation errors in a Safe Mode domain or a partially loaded domain (when SafeMode is forcefully exited),\n            // then we need to keep the graph validation checks to rediscover potential setup errors in subsequent compilations.\n            skipCustomScriptAssemblyGraphValidation = skipChecks;\n        }\n\n        public IEnumerable<Exception> SetAllCustomScriptAssemblyReferenceJsons(string[] paths)\n        {\n            return SetAllCustomScriptAssemblyReferenceJsonsContents(paths, null);\n        }\n\n        public IEnumerable<Exception> SetAllCustomScriptAssemblyReferenceJsonsContents(string[] paths, string[] contents)\n        {\n            RefreshLoadingAssemblyDefinition();\n            loadingAssemblyDefinition.SetAllCustomScriptAssemblyReferenceJsonsContents(paths, contents);\n            var updateExceptions = UpdateCustomTargetAssemblies();\n            return loadingAssemblyDefinition.Exceptions.Concat(updateExceptions);\n        }\n\n        public IEnumerable<Exception> SetAllCustomScriptAssemblyJsons(string[] paths, string[] guids)\n        {\n            return SetAllCustomScriptAssemblyJsonContents(paths, null, guids);\n        }\n\n        public IEnumerable<Exception> SetAllCustomScriptAssemblyJsonContents(string[] paths, string[] contents, string[] guids)\n        {\n            RefreshLoadingAssemblyDefinition();\n            loadingAssemblyDefinition.SetAllCustomScriptAssemblyJsonContents(paths, contents, guids);\n            var updateExceptions = UpdateCustomTargetAssemblies();\n            return loadingAssemblyDefinition.Exceptions.Concat(updateExceptions);\n        }\n\n        void RefreshLoadingAssemblyDefinition()\n        {\n            loadingAssemblyDefinition.Refresh(\n                CompilationSetupErrorsTracker,\n                skipCustomScriptAssemblyGraphValidation,\n                projectDirectory);\n        }\n\n        public void ClearCustomScriptAssemblies()\n        {\n            loadingAssemblyDefinition.ClearCustomScriptAssemblies();\n        }\n\n        public bool IsPathInPackageDirectory(string path)\n        {\n            if (m_AssetPathsMetaData == null)\n            {\n                return false;\n            }\n            return m_AssetPathsMetaData.Any(p => path.StartsWith(p.DirectoryPath, StringComparison.OrdinalIgnoreCase));\n        }\n\n        public void DeleteScriptAssemblies()\n        {\n            NPath fullEditorAssemblyPath = AssetPath.Combine(projectDirectory, GetCompileScriptsOutputDirectory());\n            fullEditorAssemblyPath.DeleteIfExists(DeleteMode.Soft);\n        }\n\n        public bool TryFindCustomScriptAssemblyFromAssemblyName(string assemblyName, out CustomScriptAssembly customScriptAssembly)\n        {\n            assemblyName = AssetPath.GetAssemblyNameWithoutExtension(assemblyName);\n\n            if (loadingAssemblyDefinition.CustomScriptAssemblies == null)\n            {\n                customScriptAssembly = null;\n                return false;\n            }\n\n            foreach (var assembly in loadingAssemblyDefinition.CustomScriptAssemblies)\n            {\n                if (assembly.Name != assemblyName)\n                {\n                    continue;\n                }\n\n                customScriptAssembly = assembly;\n                return true;\n            }\n\n            customScriptAssembly = null;\n            return false;\n        }\n\n        public CustomScriptAssembly FindCustomScriptAssemblyFromAssemblyName(string assemblyName)\n        {\n            if (TryFindCustomScriptAssemblyFromAssemblyName(assemblyName, out CustomScriptAssembly customScriptAssembly))\n            {\n                return customScriptAssembly;\n            }\n\n            assemblyName = AssetPath.GetAssemblyNameWithoutExtension(assemblyName);\n\n            var result = loadingAssemblyDefinition.CustomScriptAssemblies?.FirstOrDefault(a => a.Name == assemblyName);\n            if (result != null)\n            {\n                return result;\n            }\n\n            var exceptionMessage = \"Cannot find CustomScriptAssembly with name '\" + assemblyName + \"'.\";\n\n            if (loadingAssemblyDefinition.CustomScriptAssemblies == null)\n            {\n                exceptionMessage += \" customScriptAssemblies is null.\";\n            }\n            else\n            {\n                var assemblyNames = loadingAssemblyDefinition.CustomScriptAssemblies.Select(a => a.Name);\n                var assemblyNamesString = string.Join(\", \", assemblyNames);\n                exceptionMessage += \" Assembly names: \" + assemblyNamesString;\n            }\n\n            throw new InvalidOperationException(exceptionMessage);\n        }\n\n        public bool TryFindCustomScriptAssemblyFromScriptPath(string scriptPath, out CustomScriptAssembly customScriptAssembly)\n        {\n            var fullPath = AssetPath.IsPathRooted(scriptPath)\n                ? AssetPath.GetFullPath(scriptPath)\n                : AssetPath.Combine(projectDirectory, scriptPath);\n\n            var assemblyGraphBuilder = GetAssemblyGraphBuilder();\n            var dictionary = assemblyGraphBuilder.Match(new []{fullPath});\n\n            customScriptAssembly = dictionary.Keys.SingleOrDefault();;\n\n            if (customScriptAssembly is {IsPredefined: true})\n                customScriptAssembly = null;\n\n            return customScriptAssembly != null;\n        }\n\n        public CustomScriptAssembly FindCustomScriptAssemblyFromScriptPath(string scriptPath)\n        {\n            var fullPath = AssetPath.IsPathRooted(scriptPath)\n                ? AssetPath.GetFullPath(scriptPath)\n                : AssetPath.Combine(projectDirectory, scriptPath);\n\n            var foundCustomScriptAssemblies = GetAssemblyGraphBuilder().Match(new []{fullPath});\n            return foundCustomScriptAssemblies.SingleOrDefault().Key;\n        }\n\n        public CustomScriptAssembly FindCustomTargetAssemblyFromTargetAssembly(TargetAssembly assembly)\n        {\n            var assemblyName = AssetPath.GetAssemblyNameWithoutExtension(assembly.Filename);\n            return FindCustomScriptAssemblyFromAssemblyName(assemblyName);\n        }\n\n        public bool TryFindCustomScriptAssemblyFromAssemblyReference(string reference, out CustomScriptAssembly customScriptAssembly)\n        {\n            if (!GUIDReference.IsGUIDReference(reference))\n            {\n                return TryFindCustomScriptAssemblyFromAssemblyName(reference, out customScriptAssembly);\n            }\n\n            if (loadingAssemblyDefinition.CustomScriptAssemblies != null)\n            {\n                var guid = GUIDReference.GUIDReferenceToGUID(reference);\n                var result = loadingAssemblyDefinition.CustomScriptAssemblies.FirstOrDefault(a => string.Equals(a.GUID, guid, StringComparison.OrdinalIgnoreCase));\n\n                if (result != null)\n                {\n                    customScriptAssembly = result;\n                    return true;\n                }\n            }\n\n            customScriptAssembly = null;\n            return false;\n        }\n\n        public CustomScriptAssembly FindCustomScriptAssemblyFromAssemblyReference(string reference)\n        {\n            if (TryFindCustomScriptAssemblyFromAssemblyReference(reference, out CustomScriptAssembly customScriptAssembly))\n            {\n                return customScriptAssembly;\n            }\n\n            throw new InvalidOperationException($\"Cannot find CustomScriptAssembly with reference '{reference}'\");\n        }\n\n        public CompileStatus CompileScripts(\n            EditorScriptCompilationOptions editorScriptCompilationOptions,\n            BuildTarget platform,\n            int subtarget,\n            string[] extraScriptingDefines\n        )\n        {\n            var scriptAssemblySettings = CreateScriptAssemblySettings(platform, subtarget, editorScriptCompilationOptions, extraScriptingDefines);\n\n            CompileStatus compilationResult;\n            using (new ProfilerMarker(\"Initiating Script Compilation\").Auto())\n            {\n                compilationResult = CompileScriptsWithSettings(scriptAssemblySettings);\n            }\n\n            return compilationResult;\n        }\n\n        static string PDBPath(string dllPath)\n        {\n            return dllPath.Replace(\".dll\", \".pdb\");\n        }\n\n        static string MDBPath(string dllPath)\n        {\n            return dllPath + \".mdb\";\n        }\n\n        // Delete all .dll's that aren't used anymore\n        public void DeleteUnusedAssemblies(ScriptAssemblySettings settings)\n        {\n            string fullEditorAssemblyPath = AssetPath.Combine(projectDirectory, GetCompileScriptsOutputDirectory());\n\n            if (!Directory.Exists(fullEditorAssemblyPath))\n            {\n                return;\n            }\n\n            var deleteFiles = Directory.GetFiles(fullEditorAssemblyPath).Select(AssetPath.ReplaceSeparators).ToList();\n\n            var targetAssemblies = GetTargetAssembliesWithScripts(settings);\n\n            foreach (var assembly in targetAssemblies)\n            {\n                string path = AssetPath.Combine(fullEditorAssemblyPath, assembly.Name);\n                deleteFiles.Remove(path);\n                deleteFiles.Remove(MDBPath(path));\n                deleteFiles.Remove(PDBPath(path));\n            }\n\n            foreach (var path in deleteFiles)\n            {\n                path.ToNPath().Delete(DeleteMode.Soft);\n            }\n        }\n\n        void CancelActiveBuild()\n        {\n            _currentBeeScriptCompilationState?.CancellationTokenSource.Cancel();\n        }\n\n        void WarnIfThereAreAssembliesWithoutAnyScripts(ScriptAssemblySettings scriptAssemblySettings, ScriptAssembly[] scriptAssemblies)\n        {\n            foreach (var targetAssembly in customTargetAssemblies.Values)\n            {\n                if (!EditorBuildRules.IsCompatibleWithPlatformAndDefines(targetAssembly, scriptAssemblySettings))\n                {\n                    continue;\n                }\n\n                if (scriptAssemblies.Any(s => s.Filename == targetAssembly.Filename))\n                {\n                    continue;\n                }\n\n                var customTargetAssembly = FindCustomTargetAssemblyFromTargetAssembly(targetAssembly);\n                Debug.LogWarningFormat(\n                    \"Assembly for Assembly Definition File '{0}' will not be compiled, because it has no scripts associated with it.\",\n                    customTargetAssembly.FilePath);\n            }\n        }\n\n        public IEnumerable<string> GetScriptsThatDoNotBelongToAnyAssembly()\n        {\n            return allScripts\n                .Where(e => EditorBuildRules.GetTargetAssembly(e.Key, e.Value, projectDirectory, customTargetAssemblies) == null)\n                .Select(e => e.Key);\n        }\n\n        static TargetAssembly[] GetPredefinedAssemblyReferences(IDictionary<string, TargetAssembly> targetAssemblies)\n        {\n            var targetAssembliesResult = targetAssemblies.Values\n                .Where(x => (x.Flags & AssemblyFlags.ExplicitlyReferenced) == AssemblyFlags.None)\n                .ToArray();\n            return targetAssembliesResult;\n        }\n\n        public CompileStatus CompileScriptsWithSettings(ScriptAssemblySettings scriptAssemblySettings)\n        {\n            if (m_ScriptCompilationRequest == RequestScriptCompilationOptions.CleanBuildCache)\n                scriptAssemblySettings.CompilationOptions |= EditorScriptCompilationOptions.BuildingCleanCompilation;\n\n            if (scriptAssemblySettings.CompilationOptions.HasFlag(EditorScriptCompilationOptions.BuildingCleanCompilation))\n                ClearBeeBuildArtifacts();\n\n            m_ScriptCompilationRequest = null;\n\n            DeleteUnusedAssemblies(scriptAssemblySettings);\n            VersionDefinesConsoleLogs?.ClearVersionDefineErrors();\n            m_UnityVersionRanges.Clear();\n            m_SemVersionRanges.Clear();\n\n            ScriptAssembly[] scriptAssemblies;\n            if (scriptAssemblySettings.CompilationOptions.HasFlag(EditorScriptCompilationOptions.BuildingSkipCompile))\n                scriptAssemblies = Array.Empty<ScriptAssembly>();\n            else\n            {\n                CompilationSetupWarningTracker.ClearAssetWarnings();\n                scriptAssemblies = GetAllScriptAssembliesOfType(scriptAssemblySettings,\n                    TargetAssemblyType.Undefined, CompilationSetupWarningTracker);\n            }\n\n            // Do no start compilation if there is an setup error.\n            if (CompilationSetupErrorsTracker.HaveCompilationSetupErrors())\n            {\n                return CompileStatus.Idle;\n            }\n\n            if ((scriptAssemblySettings.CompilationOptions & EditorScriptCompilationOptions.BuildingSkipCompile) == 0)\n                WarnIfThereAreAssembliesWithoutAnyScripts(scriptAssemblySettings, scriptAssemblies);\n\n            var debug = scriptAssemblySettings.CodeOptimization == CodeOptimization.Debug;\n\n            //we're going to hash the output directory path into the dag name. We do this because when users build players into different directories,\n            //we'd like to treat those as different dags. If we wouldn't do this, you could run into situations where building into directory2 will make\n            //bee delete the previously built game from directory1.\n            Hash128 hash = Hash128.Parse(scriptAssemblySettings.OutputDirectory);\n\n            var config =\n                hash.ToString().Substring(0, 5) +\n                $\"{(scriptAssemblySettings.BuildingForEditor ? \"E\" : \"P\")}\" +\n                $\"{(scriptAssemblySettings.BuildingDevelopmentBuild ? \"Dev\" : \"\")}\" +\n                $\"{(debug ? \"Dbg\" : \"\")}\" +\n                $\"{(scriptAssemblySettings.CompilationOptions.HasFlag(EditorScriptCompilationOptions.BuildingSkipCompile) ? \"SkipCompile\" : \"\")}\";\n\n            BuildTarget buildTarget = scriptAssemblySettings.BuildTarget;\n            var cacheMode = scriptAssemblySettings.CompilationOptions.HasFlag(EditorScriptCompilationOptions.BuildingCleanCompilation)\n                ? UnityBeeDriver.CacheMode.WriteOnly\n                : UnityBeeDriver.CacheMode.ReadWrite;\n            var buildRequest = UnityBeeDriver.BuildRequestFor(ScriptCompilationBuildProgram, this, $\"{(int)buildTarget}{config}\", cacheMode, useScriptUpdater: !scriptAssemblySettings.BuildingWithoutScriptUpdater);\n\n            buildRequest.DeferDagVerification = true;\n            buildRequest.ContinueBuildingAfterFirstFailure = true;\n            buildRequest.Target = scriptAssemblySettings.CompilationOptions.HasFlag(EditorScriptCompilationOptions.BuildingExtractTypeDB)\n                ? Constants.ScriptAssembliesAndTypeDBTarget\n                : Constants.ScriptAssembliesTarget;\n\n            buildRequest.DataForBuildProgram.Add(() => BeeScriptCompilation.ScriptCompilationDataFor(\n                this,\n                scriptAssemblies,\n                debug,\n                scriptAssemblySettings.OutputDirectory,\n                buildTarget,\n                scriptAssemblySettings.BuildingForEditor,\n                !scriptAssemblySettings.BuildingWithoutScriptUpdater,\n                scriptAssemblySettings.ExtraGeneralDefines, scriptAssemblySettings));\n\n            var cts = new CancellationTokenSource();\n \n            ConsoleWindow.ClearConsoleOnRecompile();\n\n            var activeBeeBuild = BeeDriver.BuildAsync(buildRequest, cts.Token);\n\n            _currentBeeScriptCompilationState = new BeeScriptCompilationState()\n            {\n                ActiveBuild = activeBeeBuild,\n                CancellationTokenSource = cts,\n                ScriptAssemblies = scriptAssemblies,\n                Settings = scriptAssemblySettings,\n                BeeDriverProfilerFile = buildRequest.ProfilerOutputFile,\n                AsyncProgressBarToken = Progress.Start(\"Compiling Scripts\")\n            };\n\n            InvokeCompilationStarted(activeBeeBuild);\n\n            return CompileStatus.CompilationStarted;\n        }\n\n        public static RunnableProgram ScriptCompilationBuildProgram { get; } = MakeScriptCompilationBuildProgram();\n\n        static RunnableProgram MakeScriptCompilationBuildProgram()\n        {\n            var buildProgramAssembly = new NPath($\"{EditorApplication.applicationContentsPath}/Tools/BuildPipeline/ScriptCompilationBuildProgram.exe\");\n            return new SystemProcessRunnableProgram($\"{EditorApplication.applicationContentsPath}/Tools/netcorerun/netcorerun{BeeScriptCompilation.ExecutableExtension}\", new[] {buildProgramAssembly.InQuotes(SlashMode.Native)}, new () {{ \"DOTNET_SYSTEM_GLOBALIZATION_INVARIANT\", \"1\" }}\n               );\n        }\n\n        public void InvokeCompilationStarted(object context)\n        {\n            compilationStarted?.Invoke(context);\n        }\n\n        public void InvokeCompilationFinished(object context)\n        {\n            compilationFinished?.Invoke(context);\n        }\n\n        public bool DoesProjectFolderHaveAnyScripts()\n        {\n            return allScripts != null && allScripts.Count > 0;\n        }\n\n        public ScriptAssemblySettings CreateScriptAssemblySettings(BuildTarget buildTarget, EditorScriptCompilationOptions options)\n        {\n            return CreateScriptAssemblySettings(buildTarget, EditorUserBuildSettings.GetActiveSubtargetFor(buildTarget), options, new string[] { });\n        }\n\n        public ScriptAssemblySettings CreateScriptAssemblySettings(BuildTarget buildTarget, int subtarget, EditorScriptCompilationOptions options)\n        {\n            return CreateScriptAssemblySettings(buildTarget, subtarget, options, new string[] { });\n        }\n\n        public ScriptAssemblySettings CreateScriptAssemblySettings(BuildTarget buildTarget, EditorScriptCompilationOptions options, string[] extraScriptingDefines)\n        {\n            return CreateScriptAssemblySettings(buildTarget, EditorUserBuildSettings.GetActiveSubtargetFor(buildTarget), options, extraScriptingDefines);\n        }\n\n        static private void ValidateSubtarget(BuildTarget buildTarget, ref int subtarget)\n        {\n            // When building for standalone, the Default subtarget means to use the current active one.\n            if (BuildPipeline.GetBuildTargetGroup(buildTarget) != BuildTargetGroup.Standalone)\n                return;\n\n            var standaloneSubtarget = (StandaloneBuildSubtarget)subtarget;\n            switch (standaloneSubtarget)\n            {\n                case StandaloneBuildSubtarget.Default:\n                    subtarget = EditorUserBuildSettings.GetActiveSubtargetFor(buildTarget);\n                    break;\n                case StandaloneBuildSubtarget.Player:\n                case StandaloneBuildSubtarget.Server:\n                    break;\n                default:\n                    throw new ArgumentException($\"Invalid subtarget {standaloneSubtarget} for build target {buildTarget}\");\n            }\n        }\n\n        public ScriptAssemblySettings CreateScriptAssemblySettings(BuildTarget buildTarget, int subtarget, EditorScriptCompilationOptions options, string[] extraScriptingDefines)\n        {\n            var predefinedAssembliesCompilerOptions = new ScriptCompilerOptions();\n            ValidateSubtarget(buildTarget, ref subtarget);\n            var namedBuildTarget = NamedBuildTarget.FromTargetAndSubtarget(buildTarget, subtarget);\n\n            if ((options & EditorScriptCompilationOptions.BuildingPredefinedAssembliesAllowUnsafeCode) == EditorScriptCompilationOptions.BuildingPredefinedAssembliesAllowUnsafeCode)\n            {\n                predefinedAssembliesCompilerOptions.AllowUnsafeCode = true;\n            }\n\n            if ((options & EditorScriptCompilationOptions.BuildingUseDeterministicCompilation) == EditorScriptCompilationOptions.BuildingUseDeterministicCompilation)\n            {\n                predefinedAssembliesCompilerOptions.UseDeterministicCompilation = true;\n            }\n\n            predefinedAssembliesCompilerOptions.ApiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(namedBuildTarget);\n\n            var tempCompilationExtension = ModuleManager.FindPlatformSupportModule(ModuleManager.GetTargetStringFromBuildTarget(buildTarget))?.CreateCompilationExtension();\n            ICompilationExtension compilationExtension =\n                ((options & EditorScriptCompilationOptions.BuildingForEditor) == 0 || tempCompilationExtension?.GetAdditionalEditorDefines().Count() > 0) ?\n                    tempCompilationExtension : null;\n\n            List<string> additionalCompilationArguments = new List<string>(PlayerSettings.GetAdditionalCompilerArguments(namedBuildTarget));\n\n            if (PlayerSettings.suppressCommonWarnings)\n            {\n                additionalCompilationArguments.Add(\"/nowarn:0169\");\n                additionalCompilationArguments.Add(\"/nowarn:0649\");\n                additionalCompilationArguments.Add(\"/nowarn:0282\");\n\n                // The msbuild tool disables warnings 1701 and 1702 by default, so Unity should do the same.\n                additionalCompilationArguments.Add(\"/nowarn:1701\");\n                additionalCompilationArguments.Add(\"/nowarn:1702\");\n            }\n\n            var additionalCompilationArgumentsArray = additionalCompilationArguments.Where(s => !string.IsNullOrEmpty(s)).Distinct().ToArray();\n\n            var settings = new ScriptAssemblySettings\n            {\n                BuildTarget = buildTarget,\n                Subtarget = subtarget,\n                OutputDirectory = GetCompileScriptsOutputDirectory(),\n                CompilationOptions = options,\n                PredefinedAssembliesCompilerOptions = predefinedAssembliesCompilerOptions,\n                CompilationExtension = compilationExtension,\n                EditorCodeOptimization = CompilationPipeline.codeOptimization,\n                ExtraGeneralDefines = extraScriptingDefines,\n                ProjectRootNamespace = EditorSettings.projectGenerationRootNamespace,\n                ProjectDirectory = projectDirectory,\n                AdditionalCompilerArguments = additionalCompilationArgumentsArray\n            };\n\n            return settings;\n        }\n\n        ScriptAssemblySettings CreateEditorScriptAssemblySettings(EditorScriptCompilationOptions options)\n        {\n            return CreateScriptAssemblySettings(EditorUserBuildSettings.activeBuildTarget, options);\n        }\n        //only used in for tests to peek in.\n        public CompilerMessage[] GetCompileMessages() => _currentEditorCompilationCompilerMessages;\n\n        public bool IsScriptCompilationRequested()\n        {\n            return m_ScriptCompilationRequest != null;\n        }\n\n        [Obsolete]\n        public bool IsAnyAssemblyBuilderCompiling()\n        {\n            if (assemblyBuilders.Count <= 0)\n            {\n                return false;\n            }\n\n            var isCompiling = false;\n\n            using var _ = HashSetPool<AssemblyBuilder>.Get(out var removeAssemblyBuilders);\n\n            // Check status of compile tasks\n            foreach (var assemblyBuilder in assemblyBuilders)\n            {\n                switch (assemblyBuilder.status)\n                {\n                    case AssemblyBuilderStatus.IsCompiling:\n                        isCompiling = true;\n                        break;\n                    case AssemblyBuilderStatus.Finished:\n                        removeAssemblyBuilders.Add(assemblyBuilder);\n                        break;\n                    case AssemblyBuilderStatus.NotStarted:\n                        break;\n                    default:\n                        throw new ArgumentOutOfRangeException($\"Unknown builder status: {assemblyBuilder.status}\");\n                }\n            }\n\n            // Remove all compile tasks that finished compiling.\n            if (removeAssemblyBuilders.Count > 0)\n            {\n                foreach (var assemblyBuilder in removeAssemblyBuilders)\n                    assemblyBuilders.Remove(assemblyBuilder);\n            }\n\n            return isCompiling;\n        }\n\n        public bool IsCompiling()\n        {\n            // Native code expects IsCompiling to be true after requesting a script reload,\n            // therefore return true if the compilation is pending\n#pragma warning disable CS0612 // Type or member is obsolete\n            return IsCompilationTaskCompiling() || IsScriptCompilationRequested() || IsAnyAssemblyBuilderCompiling();\n#pragma warning restore CS0612 // Type or member is obsolete\n        }\n\n        public bool IsCompilationTaskCompiling()\n        {\n            return _currentBeeScriptCompilationState != null;\n        }\n\n        public CompileStatus TickCompilationPipeline(EditorScriptCompilationOptions options, BuildTarget platform, int subtarget, string[] extraScriptingDefines, bool allowBlocking)\n        {\n            // Return CompileStatus.Compiling if any compile task is still compiling.\n            // This ensures that the compile tasks finish compiling before any\n            // scripts in the Assets folder are compiled and a domain reload\n            // is triggered.\n#pragma warning disable CS0612 // Type or member is obsolete\n            if (IsAnyAssemblyBuilderCompiling())\n            {\n                return CompileStatus.Compiling;\n            }\n#pragma warning restore CS0612 // Type or member is obsolete\n\n            // If we are not currently compiling and there are new dirty assemblies, start compilation.\n            if (!IsCompilationTaskCompiling() && IsScriptCompilationRequested())\n            {\n                Profiler.BeginSample(\"CompilationPipeline.CompileScripts\");\n\n                CompileStatus compileStatus;\n                try\n                {\n                    compileStatus = CompileScripts(options, platform, subtarget, extraScriptingDefines);\n                }\n                finally\n                {\n                    Profiler.EndSample();\n                }\n                if (allowBlocking)\n                    return TickCompilationPipeline(options, platform, subtarget, extraScriptingDefines, allowBlocking);\n\n                return compileStatus;\n            }\n\n            if (_currentBeeScriptCompilationState == null)\n            {\n                return CompileStatus.Idle;\n            }\n\n            var scriptCompilationState = _currentBeeScriptCompilationState;\n            var activeBuild = scriptCompilationState.ActiveBuild;\n            var activeBuildTaskObject = activeBuild.TaskObject;\n\n            if (!activeBuildTaskObject.IsCompleted)\n            {\n                if (!allowBlocking)\n                {\n                    Progress.SetDescription(scriptCompilationState.AsyncProgressBarToken, activeBuild.Status.Description);\n                    return CompileStatus.Compiling;\n                }\n\n                CompleteActiveBuildWhilePumping();\n            }\n\n            // At this point we know we completed the build - successfully or not\n            _currentBeeScriptCompilationState = null;\n\n            UnityBeeDriver.RunCleanBeeCache();\n\n            Progress.Finish(scriptCompilationState.AsyncProgressBarToken);\n\n            if (activeBuildTaskObject.IsCanceled || activeBuildTaskObject.IsFaulted)\n            {\n                if (activeBuildTaskObject.IsFaulted)\n                    Debug.LogError(\"Internal BuildSystem Error: \" + activeBuildTaskObject.Exception);\n\n                return CompileStatus.CompilationFailed;\n            }\n\n            BeeDriverResult result = activeBuildTaskObject.Result;\n\n            if (!result.Success)\n            {\n                foreach (var msg in result.NodeFinishedMessages)\n                    if (msg.ExitCode != 0)\n                    {\n                        Console.WriteLine($\"## Script Compilation Error for: {msg.Node.Annotation}\");\n                        Console.WriteLine($\"## CmdLine: {msg.CmdLine}\");\n                        Console.WriteLine($\"## Output:\");\n                        Console.WriteLine(msg.Output);\n                    }\n            }\n\n            var messagesForNodeResults = ProcessCompilationResult(scriptCompilationState.ScriptAssemblies, result, scriptCompilationState.Settings.BuildingForEditor, scriptCompilationState.ActiveBuild);\n            var compilerMessages = messagesForNodeResults.SelectMany(a => a).ToArray();\n\n            int logIdentifier = scriptCompilationState.Settings.BuildingForEditor\n                //these numbers are \"randomly picked\". they are used to so that when you log a message with a certain identifier, later all messages with that identifier can be cleared.\n                //one means \"compilation error for compiling-assemblies-for-editor\"  the other means \"compilation error for building a player\".\n                ? kLogIdentifierFor_EditorMessages\n                : kLogIdentifierFor_PlayerMessages;\n\n            var buildingForEditor = scriptCompilationState.Settings.BuildingForEditor;\n            if (buildingForEditor)\n            {\n                _currentEditorCompilationCompilerMessages = compilerMessages;\n            }\n\n            if (_logCompilationMessages)\n            {\n                LogCompilerMessages(logIdentifier, compilerMessages, buildingForEditor);\n            }\n\n            result.ProfileOutputWritingTask?.Wait();\n\n            return result.Success\n                ? CompileStatus.CompilationComplete\n                : CompileStatus.CompilationFailed;\n        }\n\n        private static void LogCompilerMessages(int logIdentifier, IEnumerable<CompilerMessage> compilerMessages, bool buildingForEditor)\n        {\n            Debug.RemoveLogEntriesByIdentifier(logIdentifier);\n            var fileInstanceIdCache = new Dictionary<string, int>();\n\n            foreach (var message in compilerMessages)\n            {\n                if (message.type == CompilerMessageType.Information)\n                {\n                    // ensure that we don't emit info messages (user cannot do anything with these and they are generated by DiagnosticSuppressors)\n                    continue;\n                }\n\n                // the instance id identifies an asset in the project window, used for pinging the asset when double clicking on a log message with a compilation error\n                var instanceId = LookupInstanceId(fileInstanceIdCache, message.file);\n\n                Debug.LogCompilerMessage(message.message, message.file, message.line, message.column,\n                    buildingForEditor, message.type == CompilerMessageType.Error, logIdentifier, instanceId);\n            }\n        }\n\n        private static int LookupInstanceId(IDictionary<string, int> fileInstanceIdCache, string filePath)\n        {\n            // in batch mode, we don't have a Console Window, so we don't need an instance id\n            if (Application.isBatchMode || string.IsNullOrEmpty(filePath))\n            {\n                return 0;\n            }\n\n            if (fileInstanceIdCache.TryGetValue(filePath, out var instanceId))\n            {\n                return instanceId;\n            }\n\n            // The AssetDatabase does not expect absolute paths. In this case, we\n            // try to get the Logical path for the supplied filePath and pass that along\n            var logicalFilePath = FileUtil.GetLogicalPath(filePath);\n            if (string.IsNullOrEmpty(logicalFilePath))\n            {\n                return 0;\n            }\n\n            var guid = AssetDatabase.GUIDFromAssetPath(logicalFilePath);\n\n            // script compilation errors can happen before the asset database is initialized, so we reserve the instance id ahead of time (it is deterministic)\n            instanceId = AssetDatabase.ReserveMonoScriptInstanceID(guid);\n\n            fileInstanceIdCache.Add(filePath, instanceId);\n\n            return instanceId;\n        }\n\n        void CompleteActiveBuildWhilePumping()\n        {\n            var synchroContext = (UnitySynchronizationContext) SynchronizationContext.Current;\n\n            var activeBuild = _currentBeeScriptCompilationState.ActiveBuild;\n            while (true)\n            {\n                var activeBuildStatus = activeBuild.Status;\n                float progress = activeBuildStatus.Progress.HasValue\n                    ? activeBuildStatus.Progress.Value.nodesFinishedOrUpToDate / (float) activeBuildStatus.Progress.Value.totalNodesQeueued\n                    : 0f;\n\n                if (EditorUtility.DisplayCancelableProgressBar(\"Compiling Scripts\", activeBuildStatus.Description, progress))\n                {\n                    EditorUtility.DisplayCancelableProgressBar(\"Compiling Scripts\", \"Canceling compilation\", 1.0f);\n                    _currentBeeScriptCompilationState.CancellationTokenSource.Cancel();\n                }\n\n                try\n                {\n                    activeBuild.TaskObject.Wait(100);\n                }\n                catch (AggregateException)\n                {\n                    // ignored\n                }\n\n                if (activeBuild.TaskObject.IsCompleted)\n                    return;\n\n                synchroContext.Exec();\n            }\n        }\n\n        public void DisableLoggingEditorCompilerMessages()\n        {\n            _logCompilationMessages = false;\n        }\n\n        public CompilerMessage[][] ProcessCompilationResult(ScriptAssembly[] assemblies, BeeDriverResult result, bool buildingForEditor, object context)\n        {\n            var compilerMessagesForNodeResults = BeeScriptCompilation.ParseAllNodeResultsIntoCompilerMessages(result.BeeDriverMessages, result.NodeFinishedMessages, this);\n            InvokeAssemblyCompilationFinished(assemblies, result, buildingForEditor, compilerMessagesForNodeResults);\n            InvokeCompilationFinished(context);\n            return compilerMessagesForNodeResults;\n        }\n\n        void InvokeAssemblyCompilationFinished(ScriptAssembly[] assemblies, BeeDriverResult beeDriverResult, bool buildingForEditor, CompilerMessage[][] compilerMessagesForNodeResults)\n        {\n            var relatedMessages = new Dictionary<string, List<int>>();\n            var requiresCallbackInvocation = new HashSet<string>();\n            for (int i = 0; i < beeDriverResult.NodeFinishedMessages.Length; i++)\n            {\n                var msg = beeDriverResult.NodeFinishedMessages[i];\n                string filePath = new NPath(msg.Node.OutputFile).FileName;\n\n                if (!relatedMessages.TryGetValue(filePath, out var list))\n                    relatedMessages[filePath] = list = new List<int>();\n                list.Add(i);\n                if (msg.ExitCode != 0 || msg.Node.Annotation.StartsWith(\"CopyFiles\", StringComparison.Ordinal))\n                    requiresCallbackInvocation.Add(filePath);\n            }\n\n            foreach (var scriptAssembly in assemblies)\n            {\n                var fileName = scriptAssembly.Filename;\n                if (!requiresCallbackInvocation.Contains(fileName))\n                {\n                    // Report that an assembly was unchanged as a result of compilation.\n                    assemblyCompilationNotRequired?.Invoke(scriptAssembly);\n                    continue;\n                }\n\n                // Only set this flag if we actually changed any assemblies\n                if (buildingForEditor)\n                    m_ScriptsForEditorHaveBeenCompiledSinceLastDomainReload = true;\n\n                IEnumerable<int> nodeResultIndicesRelatedToAssembly;\n                if (relatedMessages.TryGetValue(fileName, out var nodeResultIndices))\n                    nodeResultIndicesRelatedToAssembly = nodeResultIndices;\n                else\n                    nodeResultIndicesRelatedToAssembly = Enumerable.Empty<int>();\n\n                var messagesForAssembly = nodeResultIndicesRelatedToAssembly.SelectMany(index => compilerMessagesForNodeResults[index]).ToArray();\n                scriptAssembly.HasCompileErrors = !beeDriverResult.Success;\n                assemblyCompilationFinished?.Invoke(scriptAssembly, ConvertCompilerMessages(messagesForAssembly));\n            }\n        }\n\n        public TargetAssemblyInfo[] GetTargetAssemblyInfos(ScriptAssemblySettings scriptAssemblySettings = null)\n        {\n            TargetAssembly[] predefindTargetAssemblies = EditorBuildRules.GetPredefinedTargetAssemblies();\n\n            TargetAssemblyInfo[] targetAssemblyInfo = new TargetAssemblyInfo[predefindTargetAssemblies.Length + (customTargetAssemblies?.Count ?? 0)];\n\n            int assembliesSize = 0;\n            foreach (var assembly in predefindTargetAssemblies)\n            {\n                if (!ShouldAddTargetAssemblyToList(assembly, scriptAssemblySettings))\n                {\n                    continue;\n                }\n\n                targetAssemblyInfo[assembliesSize] = ToTargetAssemblyInfo(predefindTargetAssemblies[assembliesSize]);\n                assembliesSize++;\n            }\n\n            if (customTargetAssemblies != null)\n            {\n                foreach (var entry in customTargetAssemblies)\n                {\n                    var customTargetAssembly = entry.Value;\n\n                    if (!ShouldAddTargetAssemblyToList(customTargetAssembly, scriptAssemblySettings))\n                    {\n                        continue;\n                    }\n\n                    targetAssemblyInfo[assembliesSize] = ToTargetAssemblyInfo(customTargetAssembly);\n                    assembliesSize++;\n                }\n                Array.Resize(ref targetAssemblyInfo, assembliesSize);\n            }\n\n            return targetAssemblyInfo;\n\n            bool ShouldAddTargetAssemblyToList(TargetAssembly targetAssembly, ScriptAssemblySettings scriptAssemblySettings)\n            {\n                if (scriptAssemblySettings != null)\n                {\n                    return EditorBuildRules.IsCompatibleWithPlatformAndDefines(targetAssembly, scriptAssemblySettings);\n                }\n                return true;\n            }\n        }\n\n        TargetAssembly[] GetTargetAssemblies()\n        {\n            TargetAssembly[] predefindTargetAssemblies = EditorBuildRules.GetPredefinedTargetAssemblies();\n\n            TargetAssembly[] targetAssemblies = new TargetAssembly[predefindTargetAssemblies.Length + (customTargetAssemblies?.Count ?? 0)];\n\n            for (int i = 0; i < predefindTargetAssemblies.Length; ++i)\n            {\n                targetAssemblies[i] = predefindTargetAssemblies[i];\n            }\n\n            if (customTargetAssemblies != null)\n            {\n                int i = predefindTargetAssemblies.Length;\n                foreach (var entry in customTargetAssemblies)\n                {\n                    var customTargetAssembly = entry.Value;\n                    targetAssemblies[i] = customTargetAssembly;\n                    i++;\n                }\n            }\n\n            return targetAssemblies;\n        }\n\n        public TargetAssemblyInfo[] GetTargetAssembliesWithScripts(EditorScriptCompilationOptions options)\n        {\n            ScriptAssemblySettings settings = CreateEditorScriptAssemblySettings(EditorScriptCompilationOptions.BuildingForEditor | options);\n            return GetTargetAssembliesWithScripts(settings);\n        }\n\n        public TargetAssemblyInfo[] GetTargetAssembliesWithScripts(ScriptAssemblySettings settings)\n        {\n            UpdateAllTargetAssemblyDefines(customTargetAssemblies, EditorBuildRules.GetPredefinedTargetAssemblies(), m_VersionMetaDatas, settings);\n\n            var targetAssemblies = EditorBuildRules.GetTargetAssembliesWithScripts(allScripts, projectDirectory, customTargetAssemblies, settings);\n\n            var targetAssemblyInfos = new TargetAssemblyInfo[targetAssemblies.Length];\n\n            for (int i = 0; i < targetAssemblies.Length; ++i)\n            {\n                targetAssemblyInfos[i] = ToTargetAssemblyInfo(targetAssemblies[i]);\n            }\n\n            return targetAssemblyInfos;\n        }\n\n        public HashSet<TargetAssembly> GetTargetAssembliesWithScriptsHashSet(EditorScriptCompilationOptions options)\n        {\n            ScriptAssemblySettings settings = CreateEditorScriptAssemblySettings(EditorScriptCompilationOptions.BuildingForEditor | options);\n            var targetAssemblies = EditorBuildRules.GetTargetAssembliesWithScriptsHashSet(allScripts, projectDirectory, customTargetAssemblies, settings);\n\n            return targetAssemblies;\n        }\n\n        public TargetAssembly[] GetCustomTargetAssemblies()\n        {\n            return customTargetAssemblies.Values.ToArray();\n        }\n\n        public CustomScriptAssembly[] GetCustomScriptAssemblies()\n        {\n            return loadingAssemblyDefinition.CustomScriptAssemblies;\n        }\n\n        public PrecompiledAssembly[] GetUnityAssemblies()\n        {\n            return unityAssemblies;\n        }\n\n        public TargetAssemblyInfo GetTargetAssembly(string scriptPath)\n        {\n            string path = scriptPath;\n            if (!Path.IsPathRooted(scriptPath))\n            {\n                path = Path.Combine(projectDirectory, scriptPath);\n            }\n\n            var matchedAssembly = GetAssemblyGraphBuilder().Match(new []{path}, false);\n            if (matchedAssembly.Count == 0)\n            {\n                return TargetAssemblyInfo.Unknown;\n            }\n\n            TargetAssembly targetAssembly;\n            var scriptAssembly = matchedAssembly.Single().Key;\n\n            customTargetAssemblies.TryGetValue(scriptAssembly.Name + \".dll\", out targetAssembly);\n\n            if (targetAssembly == null)\n            {\n                if (EditorBuildRules.predefinedTargetAssemblies.TryGetValue(scriptAssembly.Name + \".dll\",\n                        out var assembly))\n                    targetAssembly = assembly;\n            }\n\n            TargetAssemblyInfo targetAssemblyInfo = ToTargetAssemblyInfo(targetAssembly);\n            return targetAssemblyInfo;\n        }\n\n        public TargetAssembly GetTargetAssemblyDetails(string scriptPath)\n        {\n            var matchedAssembly = GetAssemblyGraphBuilder().Match(new []{scriptPath});\n            return customTargetAssemblies[matchedAssembly.Single().Key.Name];\n        }\n\n        public ScriptAssembly[] GetAllEditorScriptAssemblies(EditorScriptCompilationOptions additionalOptions)\n        {\n            return GetAllScriptAssemblies(EditorScriptCompilationOptions.BuildingForEditor | EditorScriptCompilationOptions.BuildingIncludingTestAssemblies | additionalOptions, null);\n        }\n\n        public ScriptAssembly[] GetAllEditorScriptAssemblies(EditorScriptCompilationOptions additionalOptions, string[] defines)\n        {\n            return GetAllScriptAssemblies(EditorScriptCompilationOptions.BuildingForEditor | EditorScriptCompilationOptions.BuildingIncludingTestAssemblies | additionalOptions, defines);\n        }\n\n        public ScriptAssembly[] GetAllScriptAssemblies(EditorScriptCompilationOptions options, string[] defines)\n        {\n            var precompiledAssemblies = PrecompiledAssemblyProvider.GetPrecompiledAssembliesDictionary(\n                options, EditorUserBuildSettings.activeBuildTarget, defines);\n            return GetAllScriptAssemblies(options, unityAssemblies, precompiledAssemblies, defines);\n        }\n\n        public ScriptAssembly[] GetAllScriptAssemblies(\n            EditorScriptCompilationOptions options,\n            PrecompiledAssembly[] unityAssembliesArg,\n            Dictionary<string, PrecompiledAssembly> precompiledAssembliesArg,\n            string[] defines)\n        {\n            var settings = CreateEditorScriptAssemblySettings(options);\n\n            return GetAllScriptAssemblies(\n                settings,\n                unityAssembliesArg,\n                precompiledAssembliesArg,\n                defines);\n        }\n\n        public ScriptAssembly[] GetAllScriptAssemblies(\n            ScriptAssemblySettings settings,\n            PrecompiledAssembly[] unityAssembliesArg,\n            Dictionary<string, PrecompiledAssembly> precompiledAssembliesArg,\n            string[] defines,\n            Func<TargetAssembly, bool> targetAssemblyCondition = null)\n        {\n            if (defines != null)\n            {\n                settings.ExtraGeneralDefines = defines;\n            }\n\n            UpdateAllTargetAssemblyDefines(customTargetAssemblies, EditorBuildRules.GetPredefinedTargetAssemblies(), m_VersionMetaDatas, settings);\n\n            var assemblies = new EditorBuildRules.CompilationAssemblies\n            {\n                UnityAssemblies = unityAssembliesArg,\n                PrecompiledAssemblies = precompiledAssembliesArg,\n                CustomTargetAssemblies = customTargetAssemblies,\n                RoslynAnalyzerDllPaths = PrecompiledAssemblyProvider.GetRoslynAnalyzerPaths(),\n                PredefinedAssembliesCustomTargetReferences = GetPredefinedAssemblyReferences(customTargetAssemblies),\n                EditorAssemblyReferences = ModuleUtils.GetAdditionalReferencesForUserScripts(),\n            };\n\n            return EditorBuildRules.GetAllScriptAssemblies(\n                allScripts,\n                projectDirectory,\n                settings,\n                assemblies,\n                SafeModeInfo,\n                targetAssemblyCondition: targetAssemblyCondition);\n        }\n\n\n        public string[] GetTargetAssemblyDefines(TargetAssembly targetAssembly, ScriptAssemblySettings settings)\n        {\n            var versionMetaDatas = GetVersionMetaDatas();\n\n            var editorApiCompatibility = PlayerSettings.EditorAssemblyCompatibilityToApiCompatibility(PlayerSettings.GetEditorAssembliesCompatibilityLevel());\n\n            var editorOnlyCompatibleDefines = InternalEditorUtility.GetCompilationDefines(settings.CompilationOptions, settings.BuildTarget, settings.Subtarget, editorApiCompatibility, settings.ExtraGeneralDefines);\n            var playerAssembliesDefines = InternalEditorUtility.GetCompilationDefines(settings.CompilationOptions, settings.BuildTarget, settings.Subtarget, settings.PredefinedAssembliesCompilerOptions.ApiCompatibilityLevel, settings.ExtraGeneralDefines);\n\n            return GetTargetAssemblyDefines(targetAssembly, versionMetaDatas, editorOnlyCompatibleDefines, playerAssembliesDefines, settings);\n        }\n\n        // TODO: Get rid of calls to this method and ensure that the defines are always setup correctly at all times.\n        void UpdateAllTargetAssemblyDefines(IDictionary<string, TargetAssembly> customScriptAssemblies, TargetAssembly[] predefinedTargetAssemblies,\n            Dictionary<string, VersionMetaData> versionMetaDatas, ScriptAssemblySettings settings)\n        {\n            var allTargetAssemblies = customScriptAssemblies.Values.ToArray()\n                .Concat(predefinedTargetAssemblies ?? new TargetAssembly[0]);\n\n\n            var editorApiCompatibility = PlayerSettings.EditorAssemblyCompatibilityToApiCompatibility(PlayerSettings.GetEditorAssembliesCompatibilityLevel());\n\n            string[] editorOnlyCompatibleDefines = InternalEditorUtility.GetCompilationDefines(settings.CompilationOptions, settings.BuildTarget, settings.Subtarget, editorApiCompatibility, settings.ExtraGeneralDefines);\n\n            var playerAssembliesDefines = InternalEditorUtility.GetCompilationDefines(settings.CompilationOptions, settings.BuildTarget, settings.Subtarget, settings.PredefinedAssembliesCompilerOptions.ApiCompatibilityLevel, settings.ExtraGeneralDefines);\n\n            foreach (var targetAssembly in allTargetAssemblies)\n            {\n                SetTargetAssemblyDefines(targetAssembly, versionMetaDatas, editorOnlyCompatibleDefines, playerAssembliesDefines, settings);\n            }\n        }\n\n        void SetTargetAssemblyDefines(TargetAssembly targetAssembly, Dictionary<string, VersionMetaData> versionMetaDatas, string[] editorOnlyCompatibleDefines, string[] playerAssembliesDefines, ScriptAssemblySettings settings)\n        {\n            targetAssembly.Defines = GetTargetAssemblyDefines(targetAssembly, versionMetaDatas, editorOnlyCompatibleDefines, playerAssembliesDefines, settings);\n        }\n\n        string[] GetTargetAssemblyDefines(TargetAssembly targetAssembly, Dictionary<string, VersionMetaData> versionMetaDatas, string[] editorOnlyCompatibleDefines, string[] playerAssembliesDefines, ScriptAssemblySettings settings)\n        {\n            string[] settingsExtraGeneralDefines = settings.ExtraGeneralDefines;\n            int populatedVersionDefinesCount = 0;\n\n            var compilationDefines =\n                (targetAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly\n                ? editorOnlyCompatibleDefines\n                : playerAssembliesDefines;\n\n            string[] defines = new string[compilationDefines.Length + targetAssembly.VersionDefines.Count + settingsExtraGeneralDefines.Length];\n\n            Array.Copy(settingsExtraGeneralDefines, defines, settingsExtraGeneralDefines.Length);\n            populatedVersionDefinesCount += settingsExtraGeneralDefines.Length;\n            Array.Copy(compilationDefines, 0, defines, populatedVersionDefinesCount, compilationDefines.Length);\n            populatedVersionDefinesCount += compilationDefines.Length;\n\n            if (versionMetaDatas == null)\n            {\n                return defines;\n            }\n\n            var targetAssemblyVersionDefines = targetAssembly.VersionDefines;\n\n            foreach (var targetAssemblyVersionDefine in targetAssemblyVersionDefines)\n            {\n                if (!versionMetaDatas.ContainsKey(targetAssemblyVersionDefine.name))\n                {\n                    continue;\n                }\n\n                if (string.IsNullOrEmpty(targetAssemblyVersionDefine.expression))\n                {\n                    var define = targetAssemblyVersionDefine.define;\n                    if (!string.IsNullOrEmpty(define))\n                    {\n                        defines[populatedVersionDefinesCount] = define;\n                        ++populatedVersionDefinesCount;\n                    }\n\n                    continue;\n                }\n\n                try\n                {\n                    var versionMetaData = versionMetaDatas[targetAssemblyVersionDefine.name];\n                    var versionString = versionMetaData.Version;\n                    bool isValid;\n                    switch (versionMetaData.Type)\n                    {\n                        case VersionType.VersionTypeUnity:\n                        {\n                            var versionDefineExpression = m_UnityVersionRanges.GetExpression(targetAssemblyVersionDefine.expression);\n                            if (versionDefineExpression.ValidationError != null)\n                            {\n                                VersionDefinesConsoleLogs?.LogVersionDefineError(targetAssembly, versionDefineExpression.ValidationError);\n                                isValid = false;\n                                break;\n                            }\n                            var unityVersion = UnityVersionParser.Parse(versionString);\n                            isValid = versionDefineExpression.Expression.IsValid(unityVersion);\n                            break;\n                        }\n\n                        case VersionType.VersionTypePackage:\n                        {\n                            var versionDefineExpression = m_SemVersionRanges.GetExpression(targetAssemblyVersionDefine.expression);\n                            if (versionDefineExpression.ValidationError != null)\n                            {\n                                VersionDefinesConsoleLogs?.LogVersionDefineError(targetAssembly, versionDefineExpression.ValidationError);\n                                isValid = false;\n                                break;\n                            }\n                            var semVersion = SemVersionParser.Parse(versionString);\n                            isValid = versionDefineExpression.Expression.IsValid(semVersion);\n                            break;\n                        }\n\n                        default:\n                            throw new NotImplementedException($\"EditorCompilation does not recognize versionMetaData.Type {versionMetaData.Type}. UNIMPLEMENTED\");\n                    }\n\n                    if (isValid)\n                    {\n                        defines[populatedVersionDefinesCount] = targetAssemblyVersionDefine.define;\n                        ++populatedVersionDefinesCount;\n                    }\n                }\n                catch (Exception e)\n                {\n                    var asset = AssetDatabase.LoadAssetAtPath<AssemblyDefinitionAsset>(EditorCompilationInterface.Instance.FindCustomTargetAssemblyFromTargetAssembly(targetAssembly).FilePath);\n                    Debug.LogException(e, asset);\n                }\n            }\n\n            Array.Resize(ref defines, populatedVersionDefinesCount);\n            return defines;\n        }\n\n        public ScriptAssembly[] GetAllScriptAssembliesOfType(ScriptAssemblySettings settings, TargetAssemblyType type, ICompilationSetupWarningTracker warningSink)\n        {\n            using (new ProfilerMarker(nameof(GetAllScriptAssembliesOfType)).Auto())\n            {\n                var precompiledAssemblies =\n                    PrecompiledAssemblyProvider.GetPrecompiledAssembliesDictionary(settings.CompilationOptions,\n                        settings.BuildTarget, settings.ExtraGeneralDefines);\n\n                UpdateAllTargetAssemblyDefines(customTargetAssemblies, EditorBuildRules.GetPredefinedTargetAssemblies(), m_VersionMetaDatas, settings);\n\n                var assemblies = new EditorBuildRules.CompilationAssemblies\n                {\n                    UnityAssemblies = unityAssemblies,\n                    PrecompiledAssemblies = precompiledAssemblies,\n                    CustomTargetAssemblies = customTargetAssemblies,\n                    RoslynAnalyzerDllPaths = PrecompiledAssemblyProvider.GetRoslynAnalyzerPaths(),\n                    PredefinedAssembliesCustomTargetReferences = GetPredefinedAssemblyReferences(customTargetAssemblies),\n                    EditorAssemblyReferences = ModuleUtils.GetAdditionalReferencesForUserScripts(),\n                };\n\n                return EditorBuildRules.GetAllScriptAssemblies(allScripts, projectDirectory, settings, assemblies, SafeModeInfo, type, warningSink: CompilationSetupWarningTracker);\n            }\n        }\n\n        public bool IsRuntimeScriptAssembly(string assemblyNameOrPath)\n        {\n            var assemblyFilename = AssetPath.GetFileName(assemblyNameOrPath);\n\n            if (!assemblyFilename.EndsWith(\".dll\"))\n            {\n                assemblyFilename += \".dll\";\n            }\n\n            var predefinedAssemblyTargets = EditorBuildRules.GetPredefinedTargetAssemblies();\n\n            if (predefinedAssemblyTargets.Any(a => ((a.Flags & AssemblyFlags.EditorOnly) != AssemblyFlags.EditorOnly) && a.Filename == assemblyFilename))\n            {\n                return true;\n            }\n\n            if (customTargetAssemblies != null && customTargetAssemblies.Any(a => ((a.Value.Flags & AssemblyFlags.EditorOnly) != AssemblyFlags.EditorOnly) && a.Value.Filename == assemblyFilename))\n            {\n                return true;\n            }\n\n            return false;\n        }\n\n        TargetAssemblyInfo ToTargetAssemblyInfo(TargetAssembly targetAssembly)\n        {\n            TargetAssemblyInfo targetAssemblyInfo = new TargetAssemblyInfo();\n\n            if (targetAssembly != null)\n            {\n                targetAssemblyInfo.Name = targetAssembly.Filename;\n                targetAssemblyInfo.Flags = targetAssembly.Flags;\n            }\n            else\n            {\n                targetAssemblyInfo.Name = \"\";\n                targetAssemblyInfo.Flags = AssemblyFlags.None;\n            }\n\n            return targetAssemblyInfo;\n        }\n\n        static EditorScriptCompilationOptions ToEditorScriptCompilationOptions(AssemblyBuilderFlags flags)\n        {\n            EditorScriptCompilationOptions options = EditorScriptCompilationOptions.BuildingEmpty;\n\n            if ((flags & AssemblyBuilderFlags.DevelopmentBuild) == AssemblyBuilderFlags.DevelopmentBuild)\n            {\n                options |= EditorScriptCompilationOptions.BuildingDevelopmentBuild;\n            }\n\n            if ((flags & AssemblyBuilderFlags.EditorAssembly) == AssemblyBuilderFlags.EditorAssembly)\n            {\n                options |= EditorScriptCompilationOptions.BuildingForEditor;\n            }\n\n            return options;\n        }\n\n        static AssemblyFlags ToAssemblyFlags(AssemblyBuilderFlags assemblyBuilderFlags)\n        {\n            AssemblyFlags assemblyFlags = AssemblyFlags.None;\n\n            if ((assemblyBuilderFlags & AssemblyBuilderFlags.EditorAssembly) == AssemblyBuilderFlags.EditorAssembly)\n            {\n                assemblyFlags |= AssemblyFlags.EditorOnly;\n            }\n\n            return assemblyFlags;\n        }\n\n        static EditorBuildRules.UnityReferencesOptions ToUnityReferencesOptions(ReferencesOptions options)\n        {\n            var result = EditorBuildRules.UnityReferencesOptions.ExcludeModules;\n\n            if ((options & ReferencesOptions.UseEngineModules) == ReferencesOptions.UseEngineModules)\n            {\n                result = EditorBuildRules.UnityReferencesOptions.None;\n            }\n\n            return result;\n        }\n\n        [Obsolete]\n        ScriptAssembly InitializeScriptAssemblyWithoutReferencesAndDefines(AssemblyBuilder assemblyBuilder)\n        {\n            var scriptFiles = assemblyBuilder.scriptPaths.Select(p => AssetPath.Combine(projectDirectory, p)).ToArray();\n            var assemblyPath = AssetPath.Combine(projectDirectory, assemblyBuilder.assemblyPath);\n\n            var scriptAssembly = new ScriptAssembly\n            {\n                Flags = ToAssemblyFlags(assemblyBuilder.flags),\n                BuildTarget = assemblyBuilder.buildTarget,\n                Files = scriptFiles,\n                Filename = AssetPath.GetFileName(assemblyPath),\n                OutputDirectory = AssetPath.GetDirectoryName(assemblyPath),\n                CompilerOptions = new ScriptCompilerOptions(assemblyBuilder.compilerOptions),\n                ScriptAssemblyReferences = new ScriptAssembly[0],\n                RootNamespace = string.Empty\n            };\n            scriptAssembly.CompilerOptions.ApiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(NamedBuildTarget.FromActiveSettings(assemblyBuilder.buildTarget));\n\n            return scriptAssembly;\n        }\n\n        [Obsolete]\n        public ScriptAssembly CreateScriptAssembly(AssemblyBuilder assemblyBuilder)\n        {\n            var scriptAssembly = InitializeScriptAssemblyWithoutReferencesAndDefines(assemblyBuilder);\n\n            var options = ToEditorScriptCompilationOptions(assemblyBuilder.flags);\n            var referencesOptions = ToUnityReferencesOptions(assemblyBuilder.referencesOptions);\n\n            var references = GetAssemblyBuilderDefaultReferences(scriptAssembly, options, referencesOptions);\n\n            if (assemblyBuilder.additionalReferences != null && assemblyBuilder.additionalReferences.Length > 0)\n            {\n                references = references.Concat(assemblyBuilder.additionalReferences).ToArray();\n            }\n\n            if (assemblyBuilder.excludeReferences != null && assemblyBuilder.excludeReferences.Length > 0)\n            {\n                references = references.Where(r => !assemblyBuilder.excludeReferences.Contains(r)).ToArray();\n            }\n\n            var defines = GetAssemblyBuilderDefaultDefines(assemblyBuilder);\n\n            if (assemblyBuilder.additionalDefines != null)\n            {\n                defines = defines.Concat(assemblyBuilder.additionalDefines).ToArray();\n            }\n\n            scriptAssembly.References = references.ToArray();\n            scriptAssembly.Defines = defines.ToArray();\n\n            RoslynAnalyzers.SetAnalyzers(\n                new[] { scriptAssembly },\n                customTargetAssemblies.Values.ToArray(),\n                PrecompiledAssemblyProvider.GetRoslynAnalyzerPaths(),\n                true);\n\n            // AssemblyBuilder can explicitly set analyzers and rule set\n            if (assemblyBuilder.compilerOptions.RoslynAnalyzerDllPaths != null)\n                scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths = assemblyBuilder.compilerOptions.RoslynAnalyzerDllPaths\n                    .Concat(scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths)\n                    .Distinct()\n                    .ToArray();\n\n            if (!string.IsNullOrEmpty(assemblyBuilder.compilerOptions.RoslynAnalyzerRulesetPath))\n                scriptAssembly.CompilerOptions.RoslynAnalyzerRulesetPath = assemblyBuilder.compilerOptions.RoslynAnalyzerRulesetPath;\n\n\n            return scriptAssembly;\n        }\n\n        string[] GetAssemblyBuilderDefaultReferences(ScriptAssembly scriptAssembly, EditorScriptCompilationOptions options, EditorBuildRules.UnityReferencesOptions unityReferencesOptions)\n        {\n            bool buildingForEditor = (scriptAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly;\n\n            var monolithicEngineAssemblyPath = InternalEditorUtility.GetMonolithicEngineAssemblyPath();\n\n            var unityReferences = EditorBuildRules.GetUnityReferences(scriptAssembly, unityAssemblies, options, unityReferencesOptions);\n\n            var customReferences = EditorBuildRules.GetCompiledCustomAssembliesReferences(scriptAssembly, customTargetAssemblies, GetCompileScriptsOutputDirectory());\n\n            var precompiledAssemblies = PrecompiledAssemblyProvider.GetPrecompiledAssemblies(options, EditorUserBuildSettings.activeBuildTarget);\n            // todo split implicit/explicit precompiled references\n            var precompiledReferences = EditorBuildRules.GetPrecompiledReferences(scriptAssembly, TargetAssemblyType.Custom, options, EditorCompatibility.CompatibleWithEditor, precompiledAssemblies, null, null);\n            var additionalReferences = MonoLibraryHelpers.GetSystemLibraryReferences(scriptAssembly.CompilerOptions.ApiCompatibilityLevel);\n            string[] editorReferences = buildingForEditor ? ModuleUtils.GetAdditionalReferencesForUserScripts() : new string[0];\n\n            var references = new List<string>();\n\n            if (unityReferencesOptions == EditorBuildRules.UnityReferencesOptions.ExcludeModules)\n            {\n                references.Add(monolithicEngineAssemblyPath);\n            }\n\n            references.AddRange(unityReferences.Select(a => a.Path)); // unity references paths\n            references.AddRange(customReferences);\n            references.AddRange(precompiledReferences);\n            references.AddRange(editorReferences);\n            references.AddRange(additionalReferences);\n\n            var editorOnlyTargetAssembly = (options & EditorScriptCompilationOptions.BuildingEditorOnlyAssembly) == EditorScriptCompilationOptions.BuildingEditorOnlyAssembly;\n            if (editorOnlyTargetAssembly)\n            {\n                var editorApiCompatibility = PlayerSettings.EditorAssemblyCompatibilityToApiCompatibility(PlayerSettings.GetEditorAssembliesCompatibilityLevel());\n                references.AddRange(MonoLibraryHelpers.GetEditorExtensionsReferences(editorApiCompatibility));\n            }\n\n            return references.ToArray();\n        }\n\n\n#pragma warning disable CS0618 // Type or member is obsolete\n        public string[] GetAssemblyBuilderDefaultReferences(AssemblyBuilder assemblyBuilder)\n#pragma warning restore CS0618 // Type or member is obsolete\n        {\n#pragma warning disable CS0612 // Type or member is obsolete\n            var scriptAssembly = InitializeScriptAssemblyWithoutReferencesAndDefines(assemblyBuilder);\n#pragma warning restore CS0612 // Type or member is obsolete\n            var options = ToEditorScriptCompilationOptions(assemblyBuilder.flags);\n            var referencesOptions = ToUnityReferencesOptions(assemblyBuilder.referencesOptions);\n            var references = GetAssemblyBuilderDefaultReferences(scriptAssembly, options, referencesOptions);\n\n            return references;\n        }\n\n        [Obsolete]\n        public string[] GetAssemblyBuilderDefaultDefines(AssemblyBuilder assemblyBuilder)\n        {\n            var options = ToEditorScriptCompilationOptions(assemblyBuilder.flags);\n            var defines = InternalEditorUtility.GetCompilationDefines(options, assemblyBuilder.buildTarget, assemblyBuilder.subtarget);\n            return defines;\n        }\n\n        [Obsolete]\n        public void AddAssemblyBuilder(AssemblyBuilder assemblyBuilder)\n        {\n            assemblyBuilders.Add(assemblyBuilder);\n        }\n\n        public static UnityEditor.Compilation.CompilerMessage[] ConvertCompilerMessages(CompilerMessage[] messages)\n        {\n            static Compilation.CompilerMessageType TypeFor(CompilerMessageType compilerMessageType)\n            {\n                switch (compilerMessageType)\n                {\n                    case CompilerMessageType.Error:\n                        return UnityEditor.Compilation.CompilerMessageType.Error;\n                    case CompilerMessageType.Warning:\n                        return UnityEditor.Compilation.CompilerMessageType.Warning;\n                    case CompilerMessageType.Information:\n                        return UnityEditor.Compilation.CompilerMessageType.Info;\n                    default:\n                        throw new ArgumentOutOfRangeException();\n                }\n            }\n\n            return messages.Select(message => new UnityEditor.Compilation.CompilerMessage\n            {\n                message = message.message,\n                file = message.file,\n                line = message.line,\n                column = message.column,\n                type = TypeFor(message.type)\n            }).ToArray();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute;\nusing System;\nusing UnityEditor.Compilation;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing CompilerMessageType = UnityEditor.Scripting.Compilers.CompilerMessageType;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    static class EditorCompilationInterface\n    {\n        static EditorCompilation editorCompilation;\n\n        public static EditorCompilation Instance\n        {\n            get\n            {\n                if (editorCompilation == null)\n                {\n                    editorCompilation = new EditorCompilation();\n                }\n\n                return editorCompilation;\n            }\n        }\n\n        static void LogException(Exception exception)\n        {\n            bool exceptionProcessed = Instance.CompilationSetupErrorsTracker.ProcessException(exception);\n            if (exceptionProcessed)\n                return;\n            UnityEngine.Debug.LogException(exception);\n        }\n\n        static void EmitExceptionsAsErrors(IEnumerable<Exception> exceptions)\n        {\n            if (exceptions == null)\n                return;\n\n            foreach (var exception in exceptions)\n                LogException(exception);\n        }\n\n        static T EmitExceptionAsError<T>(Func<T> func, T returnValue)\n        {\n            try\n            {\n                return func();\n            }\n            catch (Exception e)\n            {\n                LogException(e);\n                return returnValue;\n            }\n        }\n\n        static void LogWarning(string warning, string assetPath)\n        {\n            var asset = AssetDatabase.LoadAssetAtPath<TextAsset>(assetPath);\n            Debug.LogWarning(warning, asset);\n        }\n\n        [RequiredByNativeCode]\n        public static void SetAssetPathsMetaData(AssetPathMetaData[] assetPathMetaDatas)\n        {\n            Instance.SetAssetPathsMetaData(assetPathMetaDatas);\n        }\n\n        [RequiredByNativeCode]\n        public static void SetAdditionalVersionMetaDatas(VersionMetaData[] versionMetaDatas)\n        {\n            Instance.SetAdditionalVersionMetaDatas(versionMetaDatas);\n        }\n\n        [RequiredByNativeCode]\n        public static void SetAllScripts(string[] allScripts)\n        {\n            Instance.SetAllScripts(allScripts);\n        }\n\n        [RequiredByNativeCode]\n        public static bool HaveScriptsForEditorBeenCompiledSinceLastDomainReload()\n        {\n            return Instance.HaveScriptsForEditorBeenCompiledSinceLastDomainReload();\n        }\n\n        [RequiredByNativeCode]\n        public static void RequestScriptCompilation(string reason)\n        {\n            Instance.RequestScriptCompilation(reason);\n        }\n\n        [RequiredByNativeCode]\n        public static void SkipCustomScriptAssemblyGraphValidation(bool skipValidation)\n        {\n            Instance.SkipCustomScriptAssemblyGraphValidation(skipValidation);\n        }\n\n        [RequiredByNativeCode]\n        public static void ClearCustomScriptAssemblies()\n        {\n            Instance.ClearCustomScriptAssemblies();\n        }\n\n        [RequiredByNativeCode]\n        public static void DeleteScriptAssemblies()\n        {\n            Instance.DeleteScriptAssemblies();\n        }\n\n        [RequiredByNativeCode]\n        public static void SetAllUnityAssemblies(PrecompiledAssembly[] unityAssemblies)\n        {\n            Instance.SetAllUnityAssemblies(unityAssemblies);\n        }\n\n        // Burst package depends on this method, so we can't remove it.\n        [RequiredByNativeCode]\n        public static void SetCompileScriptsOutputDirectory(string directory)\n        {\n            Instance.SetCompileScriptsOutputDirectory(directory);\n        }\n\n        [RequiredByNativeCode]\n        public static string GetCompileScriptsOutputDirectory()\n        {\n            return EmitExceptionAsError(() => Instance.GetCompileScriptsOutputDirectory(), string.Empty);\n        }\n\n        [RequiredByNativeCode]\n        public static void SetAllCustomScriptAssemblyReferenceJsons(string[] allAssemblyReferenceJsons, string[] allAssemblyReferenceJsonContents)\n        {\n            EmitExceptionsAsErrors(Instance.SetAllCustomScriptAssemblyReferenceJsonsContents(allAssemblyReferenceJsons, allAssemblyReferenceJsonContents));\n        }\n\n        [RequiredByNativeCode]\n        public static void SetAllCustomScriptAssemblyJsonContents(string[] allAssemblyJsonPaths, string[] allAssemblyJsonContents, string[] guids)\n        {\n            EmitExceptionsAsErrors(Instance.SetAllCustomScriptAssemblyJsonContents(allAssemblyJsonPaths, allAssemblyJsonContents, guids));\n        }\n\n        [RequiredByNativeCode]\n        public static EditorCompilation.TargetAssemblyInfo[] GetAllCompiledAndResolvedTargetAssemblies(EditorScriptCompilationOptions options, BuildTarget buildTarget)\n        {\n            EditorCompilation.CustomScriptAssemblyAndReference[] assembliesWithMissingReference = null;\n\n            var result = EmitExceptionAsError(() => Instance.GetAllCompiledAndResolvedTargetAssemblies(options, buildTarget, out assembliesWithMissingReference), new EditorCompilation.TargetAssemblyInfo[0]);\n\n            if (assembliesWithMissingReference != null && assembliesWithMissingReference.Length > 0)\n            {\n                foreach (var assemblyAndReference in assembliesWithMissingReference)\n                {\n                    LogWarning(string.Format(\"The assembly for Assembly Definition File '{0}' will not be loaded. Because the assembly for its reference '{1}'' does not exist on the file system. \" +\n                        \"This can be caused by the reference assembly not being compiled due to errors or not having any scripts associated with it.\",\n                        assemblyAndReference.Assembly.FilePath,\n                        assemblyAndReference.Reference.FilePath),\n                        assemblyAndReference.Assembly.FilePath);\n                }\n            }\n\n            // Check we do not have any assembly definition references (asmref) without matching assembly definitions (asmdef)\n            List<CustomScriptAssemblyReference> referencesWithMissingAssemblies;\n            Instance.GetAssemblyDefinitionReferencesWithMissingAssemblies(out referencesWithMissingAssemblies);\n            if (referencesWithMissingAssemblies.Count > 0)\n            {\n                foreach (var asmref in referencesWithMissingAssemblies)\n                {\n                    var warning = $\"The Assembly Definition Reference file '{asmref.FilePath}' will not be used. \";\n                    if (string.IsNullOrEmpty(asmref.Reference))\n                        warning += \"It does not contain a reference to an Assembly Definition File.\";\n                    else\n                        warning += $\"The reference to the Assembly Definition File with the name '{asmref.Reference}' could not be found.\";\n                    LogWarning(warning, asmref.FilePath);\n                }\n            }\n\n            return result;\n        }\n\n        [RequiredByNativeCode]\n        public static EditorCompilation.CompileStatus CompileScripts(EditorScriptCompilationOptions definesOptions, BuildTarget platform, int subtarget, string[] extraScriptingDefines = null)\n        {\n            return EmitExceptionAsError(() => Instance.CompileScripts(definesOptions, platform, subtarget, extraScriptingDefines),\n                EditorCompilation.CompileStatus.CompilationFailed);\n        }\n\n        [RequiredByNativeCode]\n        public static bool DoesProjectFolderHaveAnyScripts()\n        {\n            return Instance.DoesProjectFolderHaveAnyScripts();\n        }\n\n        [RequiredByNativeCode]\n        public static bool IsCompilationPending()\n        {\n            return Instance.IsScriptCompilationRequested();\n        }\n\n        [RequiredByNativeCode]\n        // Unlike IsCompiling, this will only return true if compilation has actually started (and not if compilation\n        // is requested but has not started yet). We are using this for the BuildPlayer check (to not allow starting\n        // a player build if script compilation is in progress). We do allow starting a player build if compilation is\n        // requested (with a warning), as a common flow used in user build scripts is \"Change defines -> Build Player\".\n        public static bool IsCompilationInProgress()\n        {\n#pragma warning disable CS0612 // Type or member is obsolete\n            return Instance.IsCompilationTaskCompiling() || Instance.IsAnyAssemblyBuilderCompiling();\n#pragma warning restore CS0612 // Type or member is obsolete\n        }\n\n        [RequiredByNativeCode]\n        public static void IsCompiling(out bool isCompiling)\n        {\n            isCompiling = Instance.IsCompiling();\n        }\n\n        [RequiredByNativeCode]\n        public static EditorCompilation.CompileStatus TickCompilationPipeline(EditorScriptCompilationOptions options, BuildTarget platform, int subtarget, string[] extraScriptingDefines, bool allowBlocking)\n        {\n            try\n            {\n                return Instance.TickCompilationPipeline(options, platform, subtarget, extraScriptingDefines, allowBlocking);\n            }\n            catch (Exception e)\n            {\n                LogException(e);\n                return EditorCompilation.CompileStatus.CompilationFailed;\n            }\n        }\n\n        [RequiredByNativeCode]\n        public static EditorCompilation.TargetAssemblyInfo[] GetTargetAssemblyInfos()\n        {\n            return Instance.GetTargetAssemblyInfos();\n        }\n\n        [RequiredByNativeCode]\n        public static EditorCompilation.TargetAssemblyInfo[] GetCompatibleTargetAssemblyInfos(EditorScriptCompilationOptions definesOptions, BuildTarget platform, string[] extraScriptingDefines = null)\n        {\n            var scriptAssemblySettings = Instance.CreateScriptAssemblySettings(platform, EditorUserBuildSettings.GetActiveSubtargetFor(platform), definesOptions, extraScriptingDefines);\n            return Instance.GetTargetAssemblyInfos(scriptAssemblySettings);\n        }\n\n        [RequiredByNativeCode]\n        public static EditorCompilation.TargetAssemblyInfo GetTargetAssembly(string scriptPath)\n        {\n            return Instance.GetTargetAssembly(scriptPath);\n        }\n\n        public static EditorScriptCompilationOptions GetAdditionalEditorScriptCompilationOptions(\n            AssembliesType assembliesType)\n        {\n            var options = GetAdditionalEditorScriptCompilationOptions();\n            if (EditorUserBuildSettings.development && (assembliesType == AssembliesType.Player || assembliesType == AssembliesType.PlayerWithoutTestAssemblies))\n                options |= EditorScriptCompilationOptions.BuildingDevelopmentBuild;\n\n\n            switch (assembliesType)\n            {\n                case AssembliesType.Editor:\n                    options |= EditorScriptCompilationOptions.BuildingIncludingTestAssemblies;\n                    options |= EditorScriptCompilationOptions.BuildingForEditor;\n                    break;\n                case AssembliesType.Player:\n                    options |= EditorScriptCompilationOptions.BuildingIncludingTestAssemblies;\n                    options &= ~EditorScriptCompilationOptions.BuildingForEditor;\n                    break;\n                case AssembliesType.PlayerWithoutTestAssemblies:\n                    options &= ~EditorScriptCompilationOptions.BuildingIncludingTestAssemblies;\n                    options &= ~EditorScriptCompilationOptions.BuildingForEditor;\n                    break;\n                default:\n                    throw new ArgumentOutOfRangeException(nameof(assembliesType));\n            }\n\n            return options;\n        }\n\n        public static EditorScriptCompilationOptions GetAdditionalEditorScriptCompilationOptions()\n        {\n            var options = EditorScriptCompilationOptions.BuildingEmpty;\n\n            if (PlayerSettings.allowUnsafeCode)\n                options |= EditorScriptCompilationOptions.BuildingPredefinedAssembliesAllowUnsafeCode;\n\n            if (PlayerSettings.UseDeterministicCompilation)\n                options |= EditorScriptCompilationOptions.BuildingUseDeterministicCompilation;\n\n            return options;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    // Keep in sync with EditorScriptCompilationOptions in native\n    [Flags]\n    enum EditorScriptCompilationOptions\n    {\n        BuildingEmpty = 0,\n        BuildingDevelopmentBuild = 1 << 0,\n        BuildingForEditor = 1 << 1,\n        BuildingEditorOnlyAssembly = 1 << 2,\n        BuildingForIl2Cpp = 1 << 3,\n        BuildingWithAsserts = 1 << 4,\n        BuildingIncludingTestAssemblies = 1 << 5,\n        BuildingPredefinedAssembliesAllowUnsafeCode = 1 << 6,\n        BuildingForHeadlessPlayer = 1 << 7,\n        BuildingUseDeterministicCompilation = 1 << 9,\n        BuildingWithoutScriptUpdater = 1 << 11,\n        BuildingExtractTypeDB = 1 << 12,\n        BuildingSkipCompile = 1 << 13,\n        BuildingCleanCompilation = 1 << 14,\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/EnumerableExtensions.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nstatic class EnumerableExtensions\n{\n    public static string SeparateWith(this IEnumerable<string> values, string separator)\n    {\n        return string.Join(separator, values);\n    }\n\n    public static (List<T> True, List<T> False) SplitBy<T>(this ICollection<T> collection, Func<T, bool> predicate)\n    {\n        (List<T> True, List<T> False)result = (new List<T>(collection.Count), new List<T>(collection.Count));\n        foreach (var item in collection)\n            if (predicate(item))\n                result.True.Add(item);\n            else\n                result.False.Add(item);\n        return result;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/ExpressionNotValidException.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal class ExpressionNotValidException : Exception\n    {\n        public ExpressionNotValidException(string expression)\n            : base(expression) {}\n\n        public ExpressionNotValidException(string message, string expression)\n            : base($\"{message} : {expression}\") {}\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/ExpressionTypeFactory.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal struct ExpressionTypeValue<TVersion> where TVersion : struct, IVersion<TVersion>\n    {\n        public Func<TVersion, TVersion, TVersion, bool> IsValid { get; set; }\n        public string AppliedRule { get; set; }\n    }\n\n    internal class ExpressionTypeFactory<TVersion> where TVersion : struct, IVersion<TVersion>\n    {\n        public static Dictionary<ExpressionTypeKey, ExpressionTypeValue<TVersion>> Create()\n        {\n            return new Dictionary<ExpressionTypeKey, ExpressionTypeValue<TVersion>>\n            {\n                {\n                    new ExpressionTypeKey(hasLeftVersion: true),\n                    new ExpressionTypeValue<TVersion>\n                    {\n                        IsValid = VersionRangesEvaluators<TVersion>.MinimumVersionInclusive,\n                        AppliedRule = \"x >= {0}\",\n                    }\n                },\n                {\n                    new ExpressionTypeKey(leftSymbol: '(', rightSymbol: ')', hasSeparator: true, hasLeftVersion: true),\n                    new ExpressionTypeValue<TVersion>\n                    {\n                        IsValid = VersionRangesEvaluators<TVersion>.MinimumVersionExclusive,\n                        AppliedRule = \"x > {0}\",\n                    }\n                },\n                {\n                    new ExpressionTypeKey(leftSymbol: '[', rightSymbol: ']', hasLeftVersion: true),\n                    new ExpressionTypeValue<TVersion>\n                    {\n                        IsValid = VersionRangesEvaluators<TVersion>.ExactVersionMatch,\n                        AppliedRule = \"x == {0}\",\n                    }\n                },\n                {\n                    new ExpressionTypeKey(leftSymbol: '(', rightSymbol: ']', hasSeparator: true, hasRightVersion: true),\n                    new ExpressionTypeValue<TVersion>\n                    {\n                        IsValid = VersionRangesEvaluators<TVersion>.MaximumVersionInclusive,\n                        AppliedRule = \"x <= {1}\",\n                    }\n                },\n                {\n                    new ExpressionTypeKey(leftSymbol: '(', rightSymbol: ']', hasSeparator: true, hasLeftVersion: true, hasRightVersion: true),\n                    new ExpressionTypeValue<TVersion>\n                    {\n                        IsValid = VersionRangesEvaluators<TVersion>.MixedExclusiveMinimumAndInclusiveMaximumVersion,\n                        AppliedRule = \"{0} < x <= {1}\",\n                    }\n                },\n                {\n                    new ExpressionTypeKey(leftSymbol: '(', rightSymbol: ')', hasSeparator: true, hasRightVersion: true),\n                    new ExpressionTypeValue<TVersion>\n                    {\n                        IsValid = VersionRangesEvaluators<TVersion>.MaximumVersionExclusive,\n                        AppliedRule = \"x < {1}\",\n                    }\n                },\n                {\n                    new ExpressionTypeKey(leftSymbol: '[', rightSymbol: ']', hasSeparator: true, hasLeftVersion: true, hasRightVersion: true),\n                    new ExpressionTypeValue<TVersion>\n                    {\n                        IsValid = VersionRangesEvaluators<TVersion>.ExactRangeInclusive,\n                        AppliedRule = \"{0} <= x <= {1}\",\n                    }\n                },\n                {\n                    new ExpressionTypeKey(leftSymbol: '(', rightSymbol: ')', hasSeparator: true, hasLeftVersion: true, hasRightVersion: true),\n                    new ExpressionTypeValue<TVersion>\n                    {\n                        IsValid = VersionRangesEvaluators<TVersion>.ExactRangeExclusive,\n                        AppliedRule = \"{0} < x < {1}\",\n                    }\n                },\n                {\n                    new ExpressionTypeKey(leftSymbol: '[', rightSymbol: ')', hasSeparator: true, hasLeftVersion: true, hasRightVersion: true),\n                    new ExpressionTypeValue<TVersion>\n                    {\n                        IsValid = VersionRangesEvaluators<TVersion>.MixedInclusiveMinimumAndExclusiveMaximumVersion,\n                        AppliedRule = \"{0} <= x < {1}\",\n                    }\n                },\n                {\n                    new ExpressionTypeKey(leftSymbol: '(', rightSymbol: ')', hasLeftVersion: true),\n                    new ExpressionTypeValue<TVersion>\n                    {\n                        IsValid = (left, right, version) => VersionRangesEvaluators<TVersion>.Invalid($\"({version})\"),\n                        AppliedRule = \"Invalid\",\n                    }\n                },\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/ExpressionTypeKey.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal struct ExpressionTypeKey\n    {\n        public bool Equals(ExpressionTypeKey other)\n        {\n            return m_LeftSymbol == other.m_LeftSymbol && m_RightSymbol == other.m_RightSymbol && m_HasSeparator == other.m_HasSeparator && m_HasLeftVersion == other.m_HasLeftVersion && m_HasRightVersion == other.m_HasRightVersion;\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj)) return false;\n            return obj is ExpressionTypeKey && Equals((ExpressionTypeKey)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                var hashCode = m_LeftSymbol.GetHashCode();\n                hashCode = (hashCode * 397) ^ m_RightSymbol.GetHashCode();\n                hashCode = (hashCode * 397) ^ m_HasSeparator.GetHashCode();\n                hashCode = (hashCode * 397) ^ m_HasLeftVersion.GetHashCode();\n                hashCode = (hashCode * 397) ^ m_HasRightVersion.GetHashCode();\n                return hashCode;\n            }\n        }\n\n        private readonly char m_LeftSymbol;\n        private readonly char m_RightSymbol;\n        private readonly bool m_HasSeparator;\n        private readonly bool m_HasLeftVersion;\n        private readonly bool m_HasRightVersion;\n\n        public ExpressionTypeKey(char leftSymbol = default(char), char rightSymbol = default(char), bool hasSeparator = false, bool hasLeftVersion = false, bool hasRightVersion = false)\n        {\n            m_LeftSymbol = leftSymbol;\n            m_RightSymbol = rightSymbol;\n            m_HasSeparator = hasSeparator;\n            m_HasLeftVersion = hasLeftVersion;\n            m_HasRightVersion = hasRightVersion;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/GUIDReference.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    static class GUIDReference\n    {\n        private static readonly string GUIDReferencePrefix = \"GUID:\";\n        private static readonly string GUIDReferencePrefixLowerCase = \"guid:\";\n\n        public static bool IsGUIDReference(string reference)\n        {\n            return Utility.FastStartsWith(reference, GUIDReferencePrefix, GUIDReferencePrefixLowerCase);\n        }\n\n        public static string GUIDReferenceToGUID(string reference)\n        {\n            return reference.Substring(GUIDReferencePrefix.Length);\n        }\n\n        public static string GUIDToGUIDReference(string guid)\n        {\n            return $\"{GUIDReferencePrefix}{guid}\";\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/ILPostProcessingProgram.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.IO;\nusing System.Linq;\nusing System.Security.Cryptography;\nusing System.Text;\nusing UnityEditor.Scripting.Compilers;\nusing UnityEditor.Utils;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    class ILPostProcessingProgram\n    {\n        public virtual string EnsureRunningAndGetSocketOrNamedPipe()\n        {\n            var name = EnsureRunningAndGetSocketOrNamedPipeImpl();\n            if (string.IsNullOrEmpty(name))\n            {\n                UnityEngine.Debug.LogWarning(\"IL Post Processing agent failed to start. Any IL Post Processing task will fail\");\n            }\n            return name;\n        }\n\n        [NativeHeader(\"Editor/Src/ScriptCompilation/ILPPExternalProcess.h\")]\n        [FreeFunction(\"ILPPExternalProcess::EnsureRunningAndGetSocketOrNamedPipe\", IsThreadSafe = true)]\n        private static extern string EnsureRunningAndGetSocketOrNamedPipeImpl();\n\n        [RequiredByNativeCode(GenerateProxy = true)]\n        private static void KillLingeringILPPRunner()\n        {\n            var pidFilePath = Path.Combine(\"Library\", \"ilpp.pid\");\n            if (!File.Exists(pidFilePath))\n            {\n                return;\n            }\n            int processId;\n            try\n            {\n                processId = int.Parse(File.ReadAllText(pidFilePath), CultureInfo.InvariantCulture);\n            }\n            catch(FormatException) {\n                // corrupted pid file, return\n                return;\n            }\n            try\n            {\n                var process = Process.GetProcessById(processId);\n                if(process.ProcessName == \"Unity.ILPP.Runner\" || process.ProcessName == \"Unity.ILPP.Runner.exe\")\n                {\n                    UnityEngine.Debug.Log($\"Found a lingering IL Post Processing runner process with PID {processId}. Killing it.\");\n                    process.Kill();\n                }\n            }\n            catch (ArgumentException)\n            {\n                // no process with this ID\n                return;\n            }\n            catch (InvalidOperationException)\n            {\n                // process exitted while the Process instance is manipulated\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/IVersion.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal interface IVersionTypeTraits\n    {\n        bool IsAllowedFirstCharacter(char c, bool strict = false);\n        bool IsAllowedLastCharacter(char c, bool strict = false);\n        bool IsAllowedCharacter(char c);\n    }\n\n    internal static class VersionTypeTraitsUtils\n    {\n        public static bool IsCharDigit(char c)\n        {\n            return (c >= '0' && c <= '9');\n        }\n\n        public static bool IsCharLetter(char c)\n        {\n            return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';\n        }\n    }\n\n    internal interface IVersion<TVersion> : IEquatable<TVersion>, IComparable<TVersion>, IComparable where TVersion : struct\n    {\n        bool IsInitialized { get; }\n\n        TVersion Parse(string version, bool strict = false);\n\n        IVersionTypeTraits GetVersionTypeTraits();\n    }\n\n    internal static class VersionUtils\n    {\n        public static string ConsumeVersionComponentFromString(string value, ref int cursor, Func<char, bool> isEnd)\n        {\n            int length = 0;\n            for (int i = cursor; i < value.Length; i++)\n            {\n                if (isEnd(value[i]))\n                    break;\n\n                length++;\n            }\n\n            int newIndex = cursor;\n            cursor += length;\n            return value.Substring(newIndex, length);\n        }\n\n        public static bool TryConsumeIntVersionComponentFromString(string value, ref int cursor, Func<char, bool> isEnd, out int result, bool zeroIfEmpty = false)\n        {\n            var part = ConsumeVersionComponentFromString(value, ref cursor, isEnd);\n            if (zeroIfEmpty && part.Length == 0)\n            {\n                result = 0;\n                return true;\n            }\n            return int.TryParse(part, out result);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/LoadingAssemblyDefinition.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor.Compilation;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    interface ILoadingAssemblyDefinition\n    {\n        CustomScriptAssembly[] CustomScriptAssemblies { get; }\n        Exception[] Exceptions { get; }\n        List<CustomScriptAssemblyReference> CustomScriptAssemblyReferences { get; }\n\n        void SetAllCustomScriptAssemblyJsonContents(string[] paths, string[] contents, string[] guids);\n        void SetAllCustomScriptAssemblyReferenceJsonsContents(string[] paths, string[] contents);\n        void ClearCustomScriptAssemblies();\n        void Refresh(\n            ICompilationSetupErrorsTracker trackerBase,\n            bool skipCustomScriptAssemblyGraphValidation,\n            string projectDirectory);\n    }\n\n    class LoadingAssemblyDefinition : ILoadingAssemblyDefinition\n    {\n        ICompilationSetupErrorsTracker m_CompilationSetupErrorsTracker;\n        bool m_SkipCustomScriptAssemblyGraphValidation;\n        string m_ProjectDirectory;\n\n        public CustomScriptAssembly[] CustomScriptAssemblies { get; private set; } = new CustomScriptAssembly[0];\n        public List<CustomScriptAssemblyReference> CustomScriptAssemblyReferences { get; private set; } = new List<CustomScriptAssemblyReference>();\n\n        public Exception[] Exceptions { get; private set; }\n\n        public void Refresh(\n            ICompilationSetupErrorsTracker trackerBase,\n            bool skipCustomScriptAssemblyGraphValidation,\n            string projectDirectory)\n        {\n            m_CompilationSetupErrorsTracker = trackerBase;\n            m_SkipCustomScriptAssemblyGraphValidation = skipCustomScriptAssemblyGraphValidation;\n            m_ProjectDirectory = projectDirectory;\n        }\n\n        public void SetAllCustomScriptAssemblyJsonContents(string[] paths, string[] contents, string[] guids)\n        {\n            var assemblies = new List<CustomScriptAssembly>();\n            var assemblyLowercaseNamesLookup = new Dictionary<string, CustomScriptAssembly>();\n            var exceptions = new List<Exception>();\n            var guidsToAssemblies = new Dictionary<string, CustomScriptAssembly>();\n            HashSet<string> predefinedAssemblyNames = null;\n\n            // To check if a path prefix is already being used we use a Dictionary where the key is the prefix and the value is the file path.\n            var prefixToFilePathLookup = CustomScriptAssemblyReferences.ToDictionary(x => x.PathPrefix,\n                x => new List<string> {x.FilePath}, StringComparer.OrdinalIgnoreCase);\n\n            m_CompilationSetupErrorsTracker.ClearCompilationSetupErrors(CompilationSetupErrors.LoadError);\n\n            // Load first to setup guidsToAssemblies dictionary and convert guids to assembly names\n            // before checking for assembly reference errors, so errors emit assembly names instead of guids.\n            for (var i = 0; i < paths.Length; ++i)\n            {\n                var path = paths[i];\n                var guid = guids[i];\n\n                string lowerCaseName = null;\n                CustomScriptAssembly loadedCustomScriptAssembly = null;\n\n                try\n                {\n                    var fullPath = AssetPath.IsPathRooted(path)\n                        ? AssetPath.GetFullPath(path)\n                        : AssetPath.Combine(m_ProjectDirectory, path);\n\n                    loadedCustomScriptAssembly =\n                        contents != null\n                        ? LoadCustomScriptAssemblyFromJson(fullPath, contents[i], guid)\n                        : LoadCustomScriptAssemblyFromJsonPath(fullPath, guid);\n\n                    loadedCustomScriptAssembly.References = loadedCustomScriptAssembly.References ?? new string[0];\n\n                    lowerCaseName = Utility.FastToLower(loadedCustomScriptAssembly.Name);\n                    guidsToAssemblies[Utility.FastToLower(guid)] = loadedCustomScriptAssembly;\n\n                    if (!m_SkipCustomScriptAssemblyGraphValidation)\n                    {\n                        if (predefinedAssemblyNames == null)\n                        {\n                            predefinedAssemblyNames = new HashSet<string>(EditorBuildRules.PredefinedTargetAssemblyNames);\n                            var netfw = MonoLibraryHelpers\n                                .GetSystemLibraryReferences(ApiCompatibilityLevel.NET_Unity_4_8).Select(Path.GetFileNameWithoutExtension);\n                            var netstandard21 = MonoLibraryHelpers\n                                .GetSystemLibraryReferences(ApiCompatibilityLevel.NET_Standard).Select(Path.GetFileNameWithoutExtension);\n                            predefinedAssemblyNames.UnionWith(netfw);\n                            predefinedAssemblyNames.UnionWith(netstandard21);\n                        }\n\n                        CheckPredefinedAssemblyNames(\n                            predefinedAssemblyNames,\n                            assemblyLowercaseNamesLookup,\n                            lowerCaseName,\n                            prefixToFilePathLookup,\n                            ref loadedCustomScriptAssembly);\n                    }\n                }\n                catch (Exception e)\n                {\n                    m_CompilationSetupErrorsTracker.SetCompilationSetupErrors(CompilationSetupErrors.LoadError);\n                    exceptions.Add(e);\n                }\n\n                if (loadedCustomScriptAssembly == null || m_SkipCustomScriptAssemblyGraphValidation && assemblyLowercaseNamesLookup.ContainsKey(lowerCaseName))\n                {\n                    continue;\n                }\n\n                loadedCustomScriptAssembly.References = loadedCustomScriptAssembly.References ?? new string[0];\n                assemblyLowercaseNamesLookup[lowerCaseName] = loadedCustomScriptAssembly;\n                assemblies.Add(loadedCustomScriptAssembly);\n\n                if (!prefixToFilePathLookup.TryGetValue(loadedCustomScriptAssembly.PathPrefix, out var duplicateFilePaths))\n                {\n                    duplicateFilePaths = new List<string>();\n                    prefixToFilePathLookup[loadedCustomScriptAssembly.PathPrefix] = duplicateFilePaths;\n                }\n\n                duplicateFilePaths.Add(loadedCustomScriptAssembly.FilePath);\n            }\n\n            ConvertGUIDReferencesToAssemblyNames(assemblies, guidsToAssemblies);\n\n            if (!m_SkipCustomScriptAssemblyGraphValidation)\n            {\n                CheckForReferenceErrors(assemblies, exceptions);\n            }\n\n            CustomScriptAssemblies = assemblies.ToArray();\n            Exceptions = exceptions.ToArray();\n        }\n\n        void CheckForReferenceErrors(List<CustomScriptAssembly> assemblies, List<Exception> exceptions)\n        {\n            foreach (var loadedCustomScriptAssembly in assemblies)\n            {\n                try\n                {\n                    var references = loadedCustomScriptAssembly.References.Where(r => !string.IsNullOrEmpty(r))\n                        .ToArray();\n\n                    if (references.Length == references.Distinct().Count())\n                    {\n                        continue;\n                    }\n\n                    var duplicateRefs = references.GroupBy(r => r).SelectMany(g => g.Skip(1)).ToArray();\n                    var duplicateRefsString = string.Join(\",\", duplicateRefs);\n\n                    throw new AssemblyDefinitionException(\n                        $\"Assembly has duplicate references: {duplicateRefsString}\",\n                        loadedCustomScriptAssembly.FilePath);\n                }\n                catch (Exception e)\n                {\n                    m_CompilationSetupErrorsTracker.SetCompilationSetupErrors(CompilationSetupErrors.LoadError);\n                    exceptions.Add(e);\n                }\n            }\n        }\n\n        static void ConvertGUIDReferencesToAssemblyNames(List<CustomScriptAssembly> assemblies, Dictionary<string, CustomScriptAssembly> guidsToAssemblies)\n        {\n            foreach (var assembly in assemblies)\n            {\n                for (int i = 0; i < assembly.References.Length; ++i)\n                {\n                    var reference = assembly.References[i];\n\n                    if (!GUIDReference.IsGUIDReference(reference))\n                    {\n                        continue;\n                    }\n\n                    var guid = Utility.FastToLower(GUIDReference.GUIDReferenceToGUID(reference));\n\n                    reference = guidsToAssemblies.TryGetValue(guid, out var referenceAssembly)\n                        ? referenceAssembly.Name\n                        : string.Empty;\n\n                    assembly.References[i] = reference;\n                }\n            }\n        }\n\n        public void SetAllCustomScriptAssemblyReferenceJsonsContents(string[] paths, string[] contents)\n        {\n            var assemblyRefs = new List<CustomScriptAssemblyReference>();\n            var exceptions = new List<Exception>();\n\n            // We only construct this lookup if it is required, which is when we are using guids instead of assembly names.\n            Dictionary<string, CustomScriptAssembly> guidsToAssemblies = null;\n\n            // To check if a path prefix is already being used we use a Dictionary where the key is the prefix and the value is the file path.\n            var prefixToFilePathLookup = m_SkipCustomScriptAssemblyGraphValidation ?\n                null :\n                CustomScriptAssemblies.GroupBy(x => x.PathPrefix).ToDictionary(x => x.First().PathPrefix, x => new List<string>() { x.First().FilePath }, StringComparer.OrdinalIgnoreCase);\n\n            for (var i = 0; i < paths.Length; ++i)\n            {\n                var path = paths[i];\n\n                CustomScriptAssemblyReference loadedCustomScriptAssemblyReference = null;\n\n                try\n                {\n                    var fullPath = AssetPath.IsPathRooted(path) ? AssetPath.GetFullPath(path) : AssetPath.Combine(m_ProjectDirectory, path);\n\n                    if (contents != null)\n                    {\n                        var jsonContents = contents[i];\n                        loadedCustomScriptAssemblyReference = LoadCustomScriptAssemblyReferenceFromJson(fullPath, jsonContents);\n                    }\n                    else\n                    {\n                        loadedCustomScriptAssemblyReference = LoadCustomScriptAssemblyReferenceFromJsonPath(fullPath);\n                    }\n\n                    if (!m_SkipCustomScriptAssemblyGraphValidation)\n                    {\n                        // Check both asmdef and asmref files.\n                        if (prefixToFilePathLookup.TryGetValue(loadedCustomScriptAssemblyReference.PathPrefix, out var duplicateFilePaths))\n                        {\n                            var filePaths = new List<string> {loadedCustomScriptAssemblyReference.FilePath};\n                            filePaths.AddRange(duplicateFilePaths);\n\n                            throw new AssemblyDefinitionException(\n                                $\"Folder '{loadedCustomScriptAssemblyReference.PathPrefix}' contains multiple assembly definition files\", filePaths.ToArray());\n                        }\n                    }\n\n                    // Convert GUID references to assembly names\n                    if (GUIDReference.IsGUIDReference(loadedCustomScriptAssemblyReference.Reference))\n                    {\n                        // Generate the guid to assembly lookup?\n                        guidsToAssemblies = guidsToAssemblies ?? CustomScriptAssemblies.ToDictionary(x => x.GUID);\n\n                        var guid = Utility.FastToLower(GUIDReference.GUIDReferenceToGUID(loadedCustomScriptAssemblyReference.Reference));\n                        if (guidsToAssemblies.TryGetValue(guid, out var foundAssembly))\n                        {\n                            loadedCustomScriptAssemblyReference.Reference = foundAssembly.Name;\n                        }\n                    }\n                }\n                catch (Exception e)\n                {\n                    m_CompilationSetupErrorsTracker.SetCompilationSetupErrors(CompilationSetupErrors.LoadError);\n                    exceptions.Add(e);\n                }\n\n                if (loadedCustomScriptAssemblyReference != null)\n                {\n                    assemblyRefs.Add(loadedCustomScriptAssemblyReference);\n\n                    if (m_SkipCustomScriptAssemblyGraphValidation)\n                    {\n                        continue;\n                    }\n\n                    if (!prefixToFilePathLookup.TryGetValue(loadedCustomScriptAssemblyReference.PathPrefix, out var duplicateFilePaths))\n                    {\n                        duplicateFilePaths = new List<string>();\n                        prefixToFilePathLookup[loadedCustomScriptAssemblyReference.PathPrefix] = duplicateFilePaths;\n                    }\n\n                    duplicateFilePaths.Add(loadedCustomScriptAssemblyReference.FilePath);\n                }\n            }\n\n            CustomScriptAssemblyReferences = assemblyRefs;\n            Exceptions = exceptions.ToArray();\n        }\n\n        public void ClearCustomScriptAssemblies()\n        {\n            CustomScriptAssemblies = new CustomScriptAssembly[0];\n            CustomScriptAssemblyReferences.Clear();\n        }\n\n        static void CheckPredefinedAssemblyNames(\n            HashSet<string> predefinedAssemblyNames,\n            Dictionary<string, CustomScriptAssembly> assemblyLowercaseNamesLookup,\n            string lowerCaseName,\n            Dictionary<string, List<string>> prefixToFilePathLookup,\n            ref CustomScriptAssembly loadedCustomScriptAssembly)\n        {\n            if (predefinedAssemblyNames.Contains(loadedCustomScriptAssembly.Name))\n            {\n                throw new AssemblyDefinitionException(\n                    $\"Assembly cannot be have reserved name '{loadedCustomScriptAssembly.Name}'\",\n                    loadedCustomScriptAssembly.FilePath);\n            }\n\n            if (assemblyLowercaseNamesLookup.TryGetValue(lowerCaseName, out var duplicate))\n            {\n                var filePaths = new[]\n                {\n                    loadedCustomScriptAssembly.FilePath,\n                    duplicate.FilePath\n                };\n                var errorMsg = $\"Assembly with name '{loadedCustomScriptAssembly.Name}' already exists\";\n                loadedCustomScriptAssembly = null; // Set to null to prevent it being added.\n                throw new AssemblyDefinitionException(errorMsg, filePaths);\n            }\n\n            // Check both asmdef and asmref files.\n            if (prefixToFilePathLookup.TryGetValue(loadedCustomScriptAssembly.PathPrefix,\n                out var duplicateFilePaths))\n            {\n                var filePaths = new List<string> {loadedCustomScriptAssembly.FilePath};\n                filePaths.AddRange(duplicateFilePaths);\n\n                throw new AssemblyDefinitionException(\n                    $\"Folder '{loadedCustomScriptAssembly.PathPrefix}' contains multiple assembly definition files\",\n                    filePaths.ToArray());\n            }\n        }\n\n        public static CustomScriptAssembly LoadCustomScriptAssemblyFromJson(string path, string json, string guid)\n        {\n            try\n            {\n                var customScriptAssemblyData = CustomScriptAssemblyData.FromJson(json);\n                return CustomScriptAssembly.FromCustomScriptAssemblyData(path, guid, customScriptAssemblyData);\n            }\n            catch (Exception e)\n            {\n                throw new AssemblyDefinitionException(e.Message, path);\n            }\n        }\n\n        public static CustomScriptAssembly LoadCustomScriptAssemblyFromJsonPath(string path, string guid)\n        {\n            var json = Utility.ReadTextAsset(path);\n\n            try\n            {\n                var customScriptAssemblyData = CustomScriptAssemblyData.FromJson(json);\n                return CustomScriptAssembly.FromCustomScriptAssemblyData(path, guid, customScriptAssemblyData);\n            }\n            catch (Exception e)\n            {\n                throw new AssemblyDefinitionException(e.Message, path);\n            }\n        }\n\n        static CustomScriptAssemblyReference LoadCustomScriptAssemblyReferenceFromJsonPath(string path)\n        {\n            var json = Utility.ReadTextAsset(path);\n            return LoadCustomScriptAssemblyReferenceFromJson(path, json);\n        }\n\n        static CustomScriptAssemblyReference LoadCustomScriptAssemblyReferenceFromJson(string path, string json)\n        {\n            try\n            {\n                var customScriptAssemblyRefData = CustomScriptAssemblyReferenceData.FromJson(json);\n                return CustomScriptAssemblyReference.FromCustomScriptAssemblyReferenceData(path, customScriptAssemblyRefData);\n            }\n            catch (Exception e)\n            {\n                throw new AssemblyDefinitionException(e.Message, path);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing UnityEditor.Scripting.Compilers;\nusing UnityEditor.Utils;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    static class MonoLibraryHelpers\n    {\n        static Dictionary<ApiCompatibilityLevel, string[]> cachedApiCompatibilityLevelReferences = new Dictionary<ApiCompatibilityLevel, string[]>();\n\n        [RequiredByNativeCode]\n        public static string[] GetSystemLibraryReferences(ApiCompatibilityLevel apiCompatibilityLevel)\n        {\n            return GetCachedSystemLibraryReferences(apiCompatibilityLevel);\n        }\n\n        public static IEnumerable<string> GetEditorExtensionsReferences(ApiCompatibilityLevel apiCompatibilityLevel)\n        {\n            if(apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard)\n            {\n                return Directory.GetFiles(NetStandardFinder.GetNetStandardEditorExtensionsDirectory(), \"*.dll\");\n            }\n            return Enumerable.Empty<string>();\n        }\n\n\n        static string[] FindReferencesInDirectories(this IEnumerable<string> references, string[] directories)\n        {\n            return (\n                from reference in references\n                from directory in directories\n                where File.Exists(Path.Combine(directory, reference))\n                select Path.Combine(directory, reference)\n            ).ToArray();\n        }\n\n        static string[] GetCachedSystemLibraryReferences(ApiCompatibilityLevel apiCompatibilityLevel)\n        {\n            // We cache the references because they are computed by getting files in directories on disk,\n            // which is very slow.\n            if (cachedApiCompatibilityLevelReferences.TryGetValue(apiCompatibilityLevel, out var cachedReferences))\n            {\n                return cachedReferences;\n            }\n\n            var references = new List<string>();\n\n\n            if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard)\n            {\n                references.AddRange(GetNetStandardClassLibraries());\n            }\n            else if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Unity_4_8)\n            {\n                var monoAssemblyDirectories = GetSystemReferenceDirectories(apiCompatibilityLevel);\n                var referenceFileNames = GetSystemReferences().Concat(GetNet46SystemReferences()).Concat(GetMonoProfileNetstandardFacadeReferences()).Distinct();\n                references.AddRange(referenceFileNames.FindReferencesInDirectories(monoAssemblyDirectories));\n                references.AddRange(Directory.GetFiles(Path.Combine(GetUnityReferenceProfileDirectory(), \"Facades\"), \"*.dll\"));\n            }\n            else\n            {\n                var monoAssemblyDirectories = GetSystemReferenceDirectories(apiCompatibilityLevel);\n                references.AddRange(GetSystemReferences().FindReferencesInDirectories(monoAssemblyDirectories));\n            }\n\n            var apiCompatibilityLevelReference = references.ToArray();\n            cachedApiCompatibilityLevelReferences[apiCompatibilityLevel] = apiCompatibilityLevelReference;\n\n            return apiCompatibilityLevelReference;\n        }\n\n        static string GetSystemReference(ApiCompatibilityLevel apiCompatibilityLevel)\n        {\n            if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Unity_4_8)\n                return GetUnityReferenceProfileDirectory();\n            if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_2_0)\n                return MonoInstallationFinder.GetProfileDirectory(\"2.0-api\", MonoInstallationFinder.MonoBleedingEdgeInstallation);\n\n            return MonoInstallationFinder.GetProfileDirectory(BuildPipeline.CompatibilityProfileToClassLibFolder(apiCompatibilityLevel), MonoInstallationFinder.MonoBleedingEdgeInstallation);\n        }\n\n        private static string GetUnityReferenceProfileDirectory()\n        {\n            return Path.Combine(MonoInstallationFinder.GetFrameWorksFolder(), \"UnityReferenceAssemblies\", \"unity-4.8-api\");\n        }\n\n        public static string[] GetSystemReferenceDirectories(ApiCompatibilityLevel apiCompatibilityLevel)\n        {\n            if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard)\n            {\n                var systemReferenceDirectories = new List<string>();\n                systemReferenceDirectories.Add(NetStandardFinder.GetReferenceDirectory());\n                systemReferenceDirectories.Add(NetStandardFinder.GetNetStandardCompatShimsDirectory());\n                systemReferenceDirectories.Add(NetStandardFinder.GetNetStandardExtensionsDirectory());\n                systemReferenceDirectories.Add(NetStandardFinder.GetNetStandardEditorExtensionsDirectory());\n                systemReferenceDirectories.Add(NetStandardFinder.GetDotNetFrameworkCompatShimsDirectory());\n                return systemReferenceDirectories.ToArray();\n            }\n\n            if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Unity_4_8)\n            {\n                var systemReferenceDirectories = new List<string>();\n                var frameworkDirectory = GetSystemReference(apiCompatibilityLevel);\n                systemReferenceDirectories.Add(frameworkDirectory);\n                systemReferenceDirectories.Add(Path.Combine(frameworkDirectory, \"Facades\"));\n                return systemReferenceDirectories.ToArray();\n            }\n\n            return new[] { GetSystemReference(apiCompatibilityLevel) };\n        }\n\n        static string[] GetNetStandardClassLibraries()\n        {\n            var classLibraries = new List<string>();\n\n            // Add the .NET Standard 2.0 reference assembly\n            classLibraries.Add(Path.Combine(NetStandardFinder.GetReferenceDirectory(), \"netstandard.dll\"));\n\n            // Add the .NET Standard 2.0 compat shims\n            classLibraries.AddRange(Directory.GetFiles(NetStandardFinder.GetNetStandardCompatShimsDirectory(), \"*.dll\"));\n\n            // Add the .NET Standard 2.0 extensions\n            classLibraries.AddRange(Directory.GetFiles(NetStandardFinder.GetNetStandardExtensionsDirectory(), \"*.dll\"));\n\n            // Add the .NET Framework compat shims\n            classLibraries.AddRange(Directory.GetFiles(NetStandardFinder.GetDotNetFrameworkCompatShimsDirectory(), \"*.dll\"));\n\n            return classLibraries.ToArray();\n        }\n\n        static string[] GetSystemReferences()\n        {\n            return new[]\n            {\n                \"mscorlib.dll\",\n                \"System.dll\",\n                \"System.Core.dll\",\n                \"System.Runtime.Serialization.dll\",\n                \"System.Xml.dll\",\n                \"System.Xml.Linq.dll\",\n            };\n        }\n\n        static string[] GetNet46SystemReferences()\n        {\n            return new[]\n            {\n                \"System.Numerics.dll\",\n                \"System.Numerics.Vectors.dll\",\n                \"System.Net.Http.dll\",\n                \"System.IO.Compression.dll\",\n                \"Microsoft.CSharp.dll\",\n                \"System.Data.dll\",\n            };\n        }\n\n        static string[] GetMonoProfileNetstandardFacadeReferences()\n        {\n            return new[]\n            {\n                \"mscorlib.dll\",\n                \"System.Core.dll\",\n                \"System.dll\",\n                \"System.Data.dll\",\n                \"System.Data.DataSetExtensions.dll\",\n                \"System.Drawing.dll\",\n                \"System.IO.Compression.dll\",\n                \"System.IO.Compression.FileSystem.dll\",\n                \"System.ComponentModel.Composition.dll\",\n                \"System.Net.Http.dll\",\n                \"System.Numerics.dll\",\n                \"System.Runtime.Serialization.dll\",\n                \"System.Transactions.dll\",\n                \"System.Xml.dll\",\n                \"System.Xml.Linq.dll\",\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/PathMultidimensionalDivisionTree.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine.Assertions;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal class PathMultidimensionalDivisionTree<T>\n    {\n        private readonly Node _root;\n\n        public PathMultidimensionalDivisionTree(T defaultValue = default)\n        {\n            _root = new Node(defaultValue, null, 0);\n        }\n\n        public void Insert(string key, T value)\n        {\n            if (string.IsNullOrEmpty(key))\n            {\n                throw new ArgumentNullException(nameof(key));\n            }\n\n            var keyMemory = TrimTrailingPathSeparator(key);\n            _root.SplitInsert(keyMemory, value);\n        }\n\n        public T MatchClosest(ReadOnlySpan<char> span, out string matchedBy)\n        {\n            var node = Node.MatchClosest(_root, span);\n            matchedBy = node.FullPrefix.ToString();\n            return node.Value;\n        }\n\n        private static bool IsEqualIgnoreCase(char a, char b)\n        {\n            return (Utility.IsPathSeparator(a) && Utility.IsPathSeparator(b)) || Utility.FastToLower(a) == Utility.FastToLower(b);\n        }\n\n        private static ReadOnlyMemory<char> TrimTrailingPathSeparator(string key)\n        {\n            for (int i = key.Length - 1; i >= 0; i--)\n            {\n                if (Utility.IsPathSeparator(key[i]))\n                {\n                    continue;\n                }\n\n                return key.AsMemory(0, i + 1);\n            }\n\n            return ReadOnlyMemory<char>.Empty;\n        }\n\n        private class Node\n        {\n            public T Value { get; }\n            private bool IsLeaf { get; }\n            private int OffsetFromParent { get; }\n            private ReadOnlySpan<char> StringSegment => FullPrefix.Span[OffsetFromParent..];\n            public ReadOnlyMemory<char> FullPrefix { get; private set; }\n            private List<Node> ChildNodes { get; }\n\n            public Node(T value, ReadOnlyMemory<char> fullPrefix, int offsetFromParent)\n            {\n                Value = value;\n                OffsetFromParent = offsetFromParent;\n                IsLeaf = true;\n                FullPrefix = fullPrefix;\n                ChildNodes = new List<Node>();\n            }\n\n            public Node(T value, ReadOnlyMemory<char> fullPrefix, int offsetFromParent, List<Node> nodes)\n            {\n                Value = value;\n                OffsetFromParent = offsetFromParent;\n                IsLeaf = true;\n                FullPrefix = fullPrefix;\n                ChildNodes = nodes;\n            }\n\n            private Node(ReadOnlyMemory<char> fullPrefix, int offsetFromParent, List<Node> childNodes)\n            {\n                IsLeaf = false;\n                OffsetFromParent = offsetFromParent;\n                FullPrefix = fullPrefix;\n                ChildNodes = childNodes;\n            }\n\n            private Node WithDifferentOffsetFromParent(int offsetFromParent)\n                => IsLeaf ? new Node(Value, FullPrefix, offsetFromParent, ChildNodes)\n                          : new Node(FullPrefix, offsetFromParent, ChildNodes);\n\n            private bool IsMatch(ReadOnlySpan<char> span)\n            {\n                if (span.Length < StringSegment.Length)\n                {\n                    return false;\n                }\n\n                var segmentSpan = StringSegment;\n                for (int i = 0; i < StringSegment.Length; i++)\n                {\n                    if (!IsEqualIgnoreCase(span[i], segmentSpan[i]))\n                    {\n                        return false;\n                    }\n                }\n\n                return true;\n            }\n\n            public static Node MatchClosest(Node current, ReadOnlySpan<char> span)\n            {\n                Node currentLeaf = current;\n                Next:\n                if (span.Length == 0)\n                {\n                    return currentLeaf;\n                }\n\n                foreach (var childNode in current.ChildNodes)\n                {\n                    // We can only have 1 candidate\n                    if (childNode.IsCandidate(span[0]))\n                    {\n                        if (childNode.IsMatch(span))\n                        {\n                            span = span[childNode.StringSegment.Length..];\n                            if (childNode.IsLeaf && (span.Length == 0 || Utility.IsPathSeparator(span[0])))\n                            {\n                                current = currentLeaf = childNode;\n                                goto Next;\n                            }\n                            current = childNode;\n                            goto Next;\n                        }\n\n                        return currentLeaf;\n                    }\n                }\n\n                return currentLeaf;\n            }\n\n            public void SplitInsert(ReadOnlyMemory<char> fullPrefix, T value)\n            {\n                Assert.IsTrue(fullPrefix.Length > 0);\n\n                if (ChildNodes.Count == 0)\n                {\n                    ChildNodes.Add(new Node(value, fullPrefix, this.FullPrefix.Length));\n                    return;\n                }\n\n                var currentStringSegmentSpan = fullPrefix.Span[this.FullPrefix.Length..];\n\n                for (var childIndex = 0; childIndex < ChildNodes.Count; childIndex++)\n                {\n                    var childNode = ChildNodes[childIndex];\n                    if (childNode.IsCandidate(currentStringSegmentSpan[0]))\n                    {\n                        var childSegmentSpan = childNode.StringSegment;\n                        for (int i = 0; childSegmentSpan.Length > i; i++)\n                        {\n                            if (i >= currentStringSegmentSpan.Length ||\n                                !IsEqualIgnoreCase(currentStringSegmentSpan[i], childSegmentSpan[i]))\n                            {\n                                // Split existing node\n                                var splitPoint = i + this.FullPrefix.Length;\n\n                                if (i < currentStringSegmentSpan.Length)\n                                {\n                                    // Create non-leaf node at split point, containing the new node, and the replacement\n                                    // of the existing node\n\n                                    var replacementNode = childNode.WithDifferentOffsetFromParent(splitPoint);\n                                    var newNode = new Node(value, fullPrefix, splitPoint);\n                                    var splitNode = new Node(childNode.FullPrefix[..splitPoint], childNode.OffsetFromParent,\n                                        new List<Node> { replacementNode, newNode });\n                                    ChildNodes[childIndex] = splitNode;\n                                }\n                                else\n                                {\n                                    // Create the new node as a parent to the existing one\n                                    var newNode = new Node(value, fullPrefix, childNode.OffsetFromParent,\n                                        new List<Node> { childNode.WithDifferentOffsetFromParent(fullPrefix.Length) });\n                                    ChildNodes[childIndex] = newNode;\n                                }\n\n                                return;\n                            }\n                        }\n\n                        if (currentStringSegmentSpan.Length == childSegmentSpan.Length)\n                        {\n                            // Replace existing value\n                            ChildNodes[childIndex] = new Node(value, fullPrefix, this.FullPrefix.Length, childNode.ChildNodes);\n                        }\n                        else\n                        {\n                            childNode.SplitInsert(fullPrefix, value);\n                        }\n\n                        return;\n                    }\n                }\n\n                // No candidates found add new branch to the tree\n                ChildNodes.Add(new Node(value, fullPrefix, this.FullPrefix.Length));\n            }\n\n            private bool IsCandidate(char firstCharacter)\n            {\n                return IsEqualIgnoreCase(firstCharacter, StringSegment[0]);\n            }\n\n            public override string ToString()\n            {\n                return $\"{FullPrefix[..OffsetFromParent]}|{FullPrefix[OffsetFromParent..]} ({Value}) children: {ChildNodes?.Count ?? 0}\";\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/PlatformSupportModuleHelpers.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEditor.Modules;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    static class PlatformSupportModuleHelpers\n    {\n        public static void AddAdditionalPlatformSupportData(ICompilationExtension compilationExtension, ref ScriptAssembly scriptAssembly)\n        {\n            if (compilationExtension == null)\n            {\n                return;\n            }\n\n            scriptAssembly.Defines = AddAdditionalToArray(scriptAssembly.Defines, compilationExtension.GetAdditionalDefines().ToArray());\n            scriptAssembly.References = AddAdditionalToArray(scriptAssembly.References, compilationExtension.GetAdditionalAssemblyReferences()\n                .Concat(compilationExtension.GetWindowsMetadataReferences()).ToArray());\n            scriptAssembly.Files = AddAdditionalToArray(scriptAssembly.Files, compilationExtension.GetAdditionalSourceFiles().ToArray());\n        }\n\n        private static string[] AddAdditionalToArray(string[] source, string[] extras)\n        {\n            if (extras == null)\n            {\n                return source;\n            }\n            var destinationArray = new string[source.Length + extras.Length];\n            Array.Copy(source, destinationArray, source.Length);\n            Array.Copy(extras, 0, destinationArray, source.Length, extras.Length);\n            return destinationArray;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/PostProcessorOutputParser.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Text.RegularExpressions;\nusing UnityEditor.Scripting.Compilers;\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal class PostProcessorOutputParser : CompilerOutputParserBase\n    {\n        private static Regex sCompilerOutput = new Regex(@\"(?<filename>[^:]*)\\((?<line>\\d+),(?<column>\\d+)\\):\\s*(?<type>warning|error)\\s*(?<message>.*)\", RegexOptions.ExplicitCapture | RegexOptions.Compiled);\n\n        protected override bool ShouldParseLine(string line)\n        {\n            return line.Contains(\"warning\", StringComparison.Ordinal) ||\n                   line.Contains(\"error\", StringComparison.Ordinal);\n        }\n\n        public override IEnumerable<CompilerMessage> Parse(string[] errorOutput, string[] standardOutput, bool compilationHadFailure, string assemblyName_unused = null)\n        {\n            var hasErrors = false;\n            var msgs = new List<CompilerMessage>();\n            var regex = GetOutputRegex();\n            var internalErrorRegex = GetInternalErrorOutputRegex();\n\n            var isWarningError = false;\n            var completeWarningErrors = new List<string>();\n            for (int i = 0; i < errorOutput.Length; i++)\n            {\n                if (!ShouldParseLine(errorOutput[i]))\n                {\n                    if (isWarningError)\n                        completeWarningErrors[completeWarningErrors.Count - 1] += \"\\n\" + errorOutput[i];\n\n                    continue;\n                }\n\n                if (regex.Match(errorOutput[i]).Success || (internalErrorRegex != null && internalErrorRegex.Match(errorOutput[i]).Success))\n                {\n                    completeWarningErrors.Add(errorOutput[i]);\n                    isWarningError = true;\n                }\n                else if (completeWarningErrors.Count > 0)\n                    completeWarningErrors[completeWarningErrors.Count - 1] += \"\\n\" + errorOutput[i];\n            }\n\n            foreach (var line in completeWarningErrors)\n            {\n                //Jamplus can fail with enormous lines in the stdout, parsing of which can take 30! seconds.\n                var line2 = line.Length > 1000 ? line.Substring(0, 100) : line;\n                var regrexLineToMatch = line2.Split(\"\\n\");\n                Match m = regex.Match(regrexLineToMatch[0]);\n                if (!m.Success)\n                {\n                    if (internalErrorRegex != null)\n                        m = internalErrorRegex.Match(regrexLineToMatch[0]);\n                    if (!m.Success)\n                        continue;\n                }\n                CompilerMessage message = CreateCompilerMessageFromMatchedRegex(line, m, GetErrorIdentifier(), GetInformationIdentifier());\n\n                if (message.type == CompilerMessageType.Error)\n                    hasErrors = true;\n\n                msgs.Add(message);\n            }\n            if (compilationHadFailure && !hasErrors)\n            {\n                msgs.Add(CreateInternalCompilerErrorMessage(errorOutput));\n            }\n            return msgs;\n        }\n\n        protected override string GetInformationIdentifier()\n        {\n            return default;\n        }\n\n        protected override Regex GetOutputRegex()\n        {\n            return sCompilerOutput;\n        }\n\n        protected override string GetErrorIdentifier()\n        {\n            return \"error\";\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/PrecompiledAssembly.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing UnityEditor.Compilation;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    [DebuggerDisplay(\"{Path}\")]\n    [NativeHeader(\"Editor/Src/ScriptCompilation/ScriptCompilationPipeline.h\")]\n    [NativeHeader(\"Runtime/Scripting/ScriptingTypes.h\")]\n    [StructLayout(LayoutKind.Sequential)]\n    struct PrecompiledAssembly\n    {\n        [NativeName(\"path\")]\n        public string Path;\n        [NativeName(\"flags\")]\n        public AssemblyFlags Flags;\n        [NativeName(\"redirected\")]\n        public bool Redirected;\n    }\n\n    abstract class PrecompiledAssemblyProviderBase\n    {\n        public abstract PrecompiledAssembly[] GetPrecompiledAssemblies(EditorScriptCompilationOptions compilationOptions, BuildTarget buildTarget, string[] extraScriptingDefines = null);\n        public abstract Dictionary<string, PrecompiledAssembly> GetPrecompiledAssembliesDictionary(EditorScriptCompilationOptions compilationOptions, BuildTarget buildTarget, string[] extraScriptingDefines);\n        public abstract PrecompiledAssembly[] GetUnityAssemblies(bool isEditor, BuildTarget buildTarget);\n        public abstract PrecompiledAssembly[] GetAllPrecompiledAssemblies();\n        public abstract PrecompiledAssembly[] CachedEditorPrecompiledAssemblies { get; }\n        public abstract PrecompiledAssembly[] CachedUnityAssemblies { get; }\n        public abstract void Dirty();\n        public abstract string[] GetRoslynAnalyzerPaths();\n\n        protected virtual PrecompiledAssembly[] GetUnityAssembliesInternal(bool isEditor, BuildTarget buildTarget)\n        {\n            return GetUnityAssembliesNative(isEditor, buildTarget);\n        }\n\n        protected virtual PrecompiledAssembly[] GetPrecompiledAssembliesInternal(EditorScriptCompilationOptions compilationOptions, BuildTarget target, string[] extraScriptingDefines)\n        {\n            return GetPrecompiledAssembliesNative(compilationOptions, target, extraScriptingDefines);\n        }\n\n        protected virtual PrecompiledAssembly[] GetAllPrecompiledAssembliesInternal()\n        {\n            return GetAllPrecompiledAssembliesNative();\n        }\n\n        [FreeFunction(\"GetPrecompiledAssembliesManaged\")]\n        protected static extern PrecompiledAssembly[] GetPrecompiledAssembliesNative(EditorScriptCompilationOptions compilationOptions, BuildTarget target, string[] extraScriptingDefines);\n\n        [FreeFunction(\"GetUnityAssembliesManaged\")]\n        protected static extern PrecompiledAssembly[] GetUnityAssembliesNative(bool buildingForEditor, BuildTarget target);\n\n        [FreeFunction(\"GetAllPrecompiledAssembliesManaged\")]\n        protected static extern PrecompiledAssembly[] GetAllPrecompiledAssembliesNative();\n    }\n\n    [NativeHeader(\"Editor/Src/ScriptCompilation/RoslynAnalyzers.bindings.h\")]\n    class PrecompiledAssemblyProvider : PrecompiledAssemblyProviderBase\n    {\n        private class UnityAssembliesKey\n        {\n            public UnityAssembliesKey(bool isEditor, BuildTarget buildTarget)\n            {\n                IsEditor = isEditor;\n                BuildTarget = buildTarget;\n            }\n\n            public bool IsEditor { get; }\n            public BuildTarget BuildTarget { get; }\n\n            protected bool Equals(UnityAssembliesKey other)\n            {\n                return IsEditor == other.IsEditor && BuildTarget == other.BuildTarget;\n            }\n\n            public override bool Equals(object obj)\n            {\n                if (ReferenceEquals(null, obj)) return false;\n                if (ReferenceEquals(this, obj)) return true;\n                if (obj.GetType() != this.GetType()) return false;\n                return Equals((UnityAssembliesKey)obj);\n            }\n\n            public override int GetHashCode()\n            {\n                unchecked\n                {\n                    return (IsEditor.GetHashCode() * 397) ^ (int)BuildTarget;\n                }\n            }\n        }\n\n        private Dictionary<UnityAssembliesKey, PrecompiledAssembly[]> m_UnityAssemblies;\n        public override PrecompiledAssembly[] CachedUnityAssemblies => m_UnityAssemblies?.Values\n        .SelectMany(x => x).ToArray();\n\n        private Dictionary<string, PrecompiledAssembly> m_EditorPrecompiledAssemblies;\n        private PrecompiledAssembly[] m_AllPrecompiledAssemblies;\n        public override PrecompiledAssembly[] CachedEditorPrecompiledAssemblies => m_EditorPrecompiledAssemblies?.Values.ToArray();\n\n        public override PrecompiledAssembly[] GetUnityAssemblies(bool isEditor, BuildTarget buildTarget)\n        {\n            m_UnityAssemblies = m_UnityAssemblies ?? new Dictionary<UnityAssembliesKey, PrecompiledAssembly[]>();\n\n            var unityAssembliesKey = new UnityAssembliesKey(isEditor, buildTarget);\n\n            if (m_UnityAssemblies.TryGetValue(unityAssembliesKey, out var assemblies))\n            {\n                return assemblies;\n            }\n\n            var unityAssembliesInternal = GetUnityAssembliesInternal(isEditor, buildTarget);\n\n            m_UnityAssemblies[unityAssembliesKey] = unityAssembliesInternal;\n\n            return unityAssembliesInternal;\n        }\n\n        public override PrecompiledAssembly[] GetPrecompiledAssemblies(EditorScriptCompilationOptions compilationOptions, BuildTarget buildTarget, string[] extraScriptingDefines)\n        {\n            return GetPrecompiledAssembliesDictionary(compilationOptions, buildTarget, extraScriptingDefines).Values.ToArray();\n        }\n\n        public override PrecompiledAssembly[] GetAllPrecompiledAssemblies()\n        {\n            if (m_AllPrecompiledAssemblies != null)\n                return m_AllPrecompiledAssemblies;\n\n            m_AllPrecompiledAssemblies = GetAllPrecompiledAssembliesInternal();\n            return m_AllPrecompiledAssemblies;\n        }\n\n        public override string[] GetRoslynAnalyzerPaths()\n        {\n            return GetAllRoslynAnalyzerPaths();\n        }\n\n        [FreeFunction] internal static extern string[] GetAllRoslynAnalyzerPaths();\n\n        static bool IsEditor(EditorScriptCompilationOptions options)\n        {\n            return (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor;\n        }\n        public override Dictionary<string, PrecompiledAssembly> GetPrecompiledAssembliesDictionary(EditorScriptCompilationOptions compilationOptions, BuildTarget buildTarget, string[] extraScriptingDefines)\n        {\n            bool isEditor = IsEditor(compilationOptions);\n            if (isEditor && (extraScriptingDefines == null || extraScriptingDefines.Length == 0) && m_EditorPrecompiledAssemblies != null)\n            {\n                return m_EditorPrecompiledAssemblies;\n            }\n\n            var precompiledAssembliesInternal = GetPrecompiledAssembliesInternal(compilationOptions, buildTarget, extraScriptingDefines);\n            var fileNameToPrecompiledAssembly = FilenameToPrecompiledAssembly(precompiledAssembliesInternal);\n\n            if (isEditor && (extraScriptingDefines == null || extraScriptingDefines.Length == 0))\n            {\n                m_EditorPrecompiledAssemblies = fileNameToPrecompiledAssembly;\n            }\n\n            return fileNameToPrecompiledAssembly;\n        }\n\n        public override void Dirty()\n        {\n            m_EditorPrecompiledAssemblies = null;\n            m_UnityAssemblies = null;\n            m_AllPrecompiledAssemblies = null;\n        }\n\n        private static Dictionary<string, PrecompiledAssembly> FilenameToPrecompiledAssembly(PrecompiledAssembly[] precompiledAssemblies)\n        {\n            if (precompiledAssemblies == null)\n            {\n                return new Dictionary<string, PrecompiledAssembly>(0);\n            }\n\n            var dictionary = new Dictionary<string, PrecompiledAssembly>();\n            foreach (var assembly in precompiledAssemblies)\n            {\n                var filename = AssetPath.GetFileName(assembly.Path);\n                if (!dictionary.TryGetValue(filename, out var existingAssembly))\n                {\n                    dictionary[filename] = assembly;\n                    continue;\n                }\n\n                if (existingAssembly.Redirected)\n                {\n                    dictionary[filename] = assembly;\n                }\n            }\n            return dictionary;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/RoslynAnalyzers.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal static class RoslynAnalyzers\n    {\n        private static readonly string[] Unset = null;\n        private static readonly string[] CyclicDependencies = {};\n\n        private static string[] SetAnalyzers(ScriptAssembly scriptAssembly, IEnumerable<(string scriptAssemblyFileName, string analyzerDll)> allAnalyzers, bool scanPrecompiledReferences)\n        {\n            if (scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths == Unset)\n            {\n                // If this is a cyclic chain we want to detect that and do two iterations\n                // Doing two iterations ensures that all participants in the chain will see all the analyzers of all members involved in the chain.\n                scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths = CyclicDependencies;\n            }\n            else if (scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths == CyclicDependencies)\n            {\n                // On second iteration return an empty array (this will be replaced be actual content of the cyclic chain)\n                scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths = Array.Empty<string>();\n            }\n            else\n            {\n                // Analyzers for this ScriptAssembly has already been setup\n                return scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths;\n            }\n\n            scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths =\n                scriptAssembly.ScriptAssemblyReferences\n                    .SelectMany(sa => SetAnalyzers(sa, allAnalyzers, scanPrecompiledReferences))\n                    .Concat(allAnalyzers\n                        .Where(a => a.scriptAssemblyFileName == null ||\n                                    a.scriptAssemblyFileName == scriptAssembly.Filename ||\n                                    scanPrecompiledReferences && scriptAssembly.References.Select(Path.GetFileName).Contains(a.scriptAssemblyFileName))\n                        .Select(a => a.analyzerDll))\n                    .Distinct()\n                    .ToArray();\n\n            if (scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths.Length > 0)\n            {\n                if(scriptAssembly.TargetAssemblyType == TargetAssemblyType.Predefined)\n                {\n                    var originPath = Path.ChangeExtension(scriptAssembly.Filename, null);\n                    scriptAssembly.CompilerOptions.RoslynAnalyzerRulesetPath = RuleSetFileCache.GetRuleSetFilePathInRootFolder(originPath);\n                    scriptAssembly.CompilerOptions.AnalyzerConfigPath = RoslynAnalyzerConfigFiles.GetAnalyzerConfigRootFolder(originPath);\n                }\n                else\n                {\n                    scriptAssembly.CompilerOptions.RoslynAnalyzerRulesetPath = RuleSetFileCache.GetPathForAssembly(scriptAssembly.OriginPath);\n                    scriptAssembly.CompilerOptions.AnalyzerConfigPath = RoslynAnalyzerConfigFiles.GetAnalyzerConfigForAssembly(scriptAssembly.OriginPath);\n                }\n                scriptAssembly.CompilerOptions.RoslynAdditionalFilePaths = scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths\n                    .SelectMany(a=>RoslynAdditionalFiles.GetAnalyzerAdditionalFilesForTargetAssembly(a, scriptAssembly.OriginPath))\n                    .Distinct()\n                    .ToArray();\n            }\n\n            return scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths;\n        }\n\n        internal static void SetAnalyzers(ScriptAssembly[] scriptAssemblies, TargetAssembly[] potentialAnalyzerOwners, string[] analyzerDlls, bool scanPrecompiledReferences)\n        {\n            // Figure out what assemblies own each analyzer\n            var analyzerAssemblies = analyzerDlls.Select(analyzerDll =>\n            {\n                var potentialAnalyzerOwner = potentialAnalyzerOwners\n                    .Where(targetAssembly => targetAssembly.PathFilter(analyzerDll) > 0)\n                    .OrderBy(targetAssembly => targetAssembly.PathFilter(analyzerDll))\n                    .LastOrDefault();\n\n                return (potentialOwnerOfAnalyzer: potentialAnalyzerOwner?.Filename, dll: analyzerDll);\n\n            }).ToArray();\n\n            // Null out all RoslynAnalyzerDllPaths to indicate they need to be set\n            foreach (var scriptAssembly in scriptAssemblies)\n                scriptAssembly.CompilerOptions.RoslynAnalyzerDllPaths = Unset;\n\n            foreach (var scriptAssembly in scriptAssemblies)\n                SetAnalyzers(scriptAssembly, analyzerAssemblies, scanPrecompiledReferences);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/SafeMode.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal interface ISafeModeInfo\n    {\n        string[] GetWhiteListAssemblyNames();\n    }\n\n    [NativeHeader(\"Editor/Src/ScriptCompilation/ScriptCompilationPipeline.h\")]\n    internal class SafeModeInfo : ISafeModeInfo\n    {\n        public string[] GetWhiteListAssemblyNames()\n        {\n            return GetWhiteListAssemblyNamesInternal();\n        }\n\n        [FreeFunction(\"GetSafeModeWhiteListTargetAssemblies\")]\n        public static extern string[] GetWhiteListAssemblyNamesInternal();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/ScriptAssembly.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing UnityEditor.Scripting.Compilers;\nusing UnityEditor.Compilation;\nusing UnityEditor.Modules;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    // Settings that would be common for a group of ScriptAssembly's created for the same build target.\n    class ScriptAssemblySettings\n    {\n        public BuildTarget BuildTarget { get; set; }\n        public int Subtarget { get; set; }\n        public string OutputDirectory { get; set; }\n        public EditorScriptCompilationOptions CompilationOptions { get; set; }\n        public ScriptCompilerOptions PredefinedAssembliesCompilerOptions { get; set; }\n        public string[] ExtraGeneralDefines { get; set; }\n        public string[] AdditionalCompilerArguments { get; set; }\n        public ICompilationExtension CompilationExtension { get; set; }\n        public string ProjectRootNamespace { get; set; }\n        public string ProjectDirectory { get; set; } = \".\";\n\n        public CodeOptimization EditorCodeOptimization { get; set; }\n\n        public ScriptAssemblySettings()\n        {\n            BuildTarget = BuildTarget.NoTarget;\n            Subtarget = 0;\n            PredefinedAssembliesCompilerOptions = new ScriptCompilerOptions();\n            ExtraGeneralDefines = new string[0];\n            AdditionalCompilerArguments = new string[0];\n        }\n\n        public bool BuildingForEditor\n        {\n            get { return (CompilationOptions & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor; }\n        }\n\n        public bool BuildingDevelopmentBuild\n        {\n            get { return (CompilationOptions & EditorScriptCompilationOptions.BuildingDevelopmentBuild) == EditorScriptCompilationOptions.BuildingDevelopmentBuild; }\n        }\n\n        public CodeOptimization CodeOptimization\n        {\n            get { return BuildingForEditor ? EditorCodeOptimization : BuildingDevelopmentBuild? CodeOptimization.Debug : CodeOptimization.Release; }\n        }\n\n        public bool BuildingWithoutScriptUpdater\n        {\n            get { return (CompilationOptions & EditorScriptCompilationOptions.BuildingWithoutScriptUpdater) == EditorScriptCompilationOptions.BuildingWithoutScriptUpdater; }\n        }\n    }\n\n    [DebuggerDisplay(\"{Filename}\")]\n    class ScriptAssembly\n    {\n        public string OriginPath { get; set; }\n        public AssemblyFlags Flags { get; set; }\n        public BuildTarget BuildTarget { get; set; }\n        public string Filename { get; set; }\n        public string OutputDirectory { get; set; }\n\n        /// <summary>\n        /// References to dependencies that will be built.\n        /// </summary>\n        public ScriptAssembly[] ScriptAssemblyReferences { get; set; }\n\n        /// <summary>\n        ///References to dependencies that that will *not* be built.\n        /// </summary>\n        public string[] References { get; set; }\n        public string[] Defines { get; set; }\n        public string[] Files { get; set; }\n        public string RootNamespace { get; set; }\n        public ScriptCompilerOptions CompilerOptions { get; set; }\n        public string GeneratedResponseFile { get; set; }\n        // Indicates whether the assembly had compile errors on last compilation\n        public bool HasCompileErrors { get; set; }\n        internal TargetAssemblyType TargetAssemblyType { get; set; }\n        public string AsmDefPath { get; set; }\n\n        public ScriptAssembly()\n        {\n            CompilerOptions = new ScriptCompilerOptions();\n        }\n\n        public string FullPath { get { return AssetPath.Combine(OutputDirectory, Filename); } }\n\n        public string[] GetAllReferences()\n        {\n            return References.Concat(ScriptAssemblyReferences.Select(a => a.FullPath)).ToArray();\n        }\n\n        public IEnumerable<ScriptAssembly> AllRecursiveScripAssemblyReferencesIncludingSelf() =>\n            ScriptAssemblyReferences\n                .SelectMany(a => a.AllRecursiveScripAssemblyReferencesIncludingSelf())\n                .Concat(new[] {this});\n\n        public string[] GetResponseFiles()\n        {\n            return new MicrosoftCSharpResponseFileProvider().Get(OriginPath).ToArray();\n        }\n\n        public bool SkipCodeGen { get; set; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/SemVersion.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal struct SemVersion : IVersion<SemVersion>\n    {\n        public bool IsInitialized { get; }\n\n        public int Major { get; }\n\n        public int Minor { get; }\n\n        public int Patch { get; }\n\n        public string Prerelease { get; }\n\n        public string Build { get; }\n\n        public SemVersion(int major, int minor = 0, int patch = 0, string prerelease = \"\", string build = \"\")\n        {\n            Major = major;\n            Minor = minor;\n            Patch = patch;\n\n            Prerelease = prerelease ?? \"\";\n            Build = build ?? \"\";\n            IsInitialized = true;\n        }\n\n        public static int Compare(SemVersion versionA, SemVersion versionB)\n        {\n            return versionA.CompareTo(versionB);\n        }\n\n        public static bool operator==(SemVersion left, SemVersion right)\n        {\n            return Equals(left, right);\n        }\n\n        public static bool operator!=(SemVersion left, SemVersion right)\n        {\n            return !Equals(left, right);\n        }\n\n        public static bool operator>(SemVersion left, SemVersion right)\n        {\n            return Compare(left, right) > 0;\n        }\n\n        public static bool operator>=(SemVersion left, SemVersion right)\n        {\n            return left == right || left > right;\n        }\n\n        public static bool operator<(SemVersion left, SemVersion right)\n        {\n            return Compare(left, right) < 0;\n        }\n\n        public static bool operator<=(SemVersion left, SemVersion right)\n        {\n            return left == right || left < right;\n        }\n\n        public int CompareTo(object obj)\n        {\n            return CompareTo((SemVersion)obj);\n        }\n\n        public int CompareTo(SemVersion other)\n        {\n            var result = Major.CompareTo(other.Major);\n            if (result != 0)\n            {\n                return result;\n            }\n\n            result = Minor.CompareTo(other.Minor);\n            if (result != 0)\n            {\n                return result;\n            }\n\n            result = Patch.CompareTo(other.Patch);\n            if (result != 0)\n            {\n                return result;\n            }\n\n            result = CompareExtension(Prerelease, other.Prerelease, true);\n\n            if (result != 0)\n            {\n                return result;\n            }\n\n            return 0;\n        }\n\n        private static int CompareExtension(string current, string other, bool lower = false)\n        {\n            var currentIsEmpty = string.IsNullOrEmpty(current);\n            var otherIsEmpty = string.IsNullOrEmpty(other);\n            if (currentIsEmpty && otherIsEmpty)\n                return 0;\n\n            if (currentIsEmpty)\n                return lower ? 1 : -1;\n            if (otherIsEmpty)\n                return lower ? -1 : 1;\n\n            var currentParts = current.Split('.');\n            var otherParts = other.Split('.');\n\n            for (var i = 0; i < Math.Min(currentParts.Length, otherParts.Length); i++)\n            {\n                var currentPart = currentParts[i];\n                var otherPart = otherParts[i];\n\n                int currentNumber;\n                int otherNumber;\n                var currentPartIsNumber = int.TryParse(currentPart, out currentNumber);\n                var otherPartIsNumber = int.TryParse(otherPart, out otherNumber);\n                int result;\n                if (currentPartIsNumber && otherPartIsNumber)\n                {\n                    result = currentNumber.CompareTo(otherNumber);\n                    if (result != 0)\n                    {\n                        return result;\n                    }\n                }\n                else\n                {\n                    if (currentPartIsNumber)\n                    {\n                        return -1;\n                    }\n\n                    if (otherPartIsNumber)\n                    {\n                        return 1;\n                    }\n\n                    result = string.CompareOrdinal(currentPart, otherPart);\n                    if (result != 0)\n                    {\n                        return result;\n                    }\n                }\n            }\n            return currentParts.Length.CompareTo(otherParts.Length);\n        }\n\n        public bool Equals(SemVersion other)\n        {\n            // We do not compare the Build\n            return Major == other.Major &&\n                Minor == other.Minor &&\n                Patch == other.Patch &&\n                string.Equals(Prerelease, other.Prerelease, StringComparison.Ordinal);\n        }\n\n        public override bool Equals(object other)\n        {\n            if (ReferenceEquals(other, null))\n                return false;\n\n            return other.GetType() == GetType() && Equals((SemVersion)other);\n        }\n\n        public override string ToString()\n        {\n            var version = $\"{Major}.{Minor}.{Patch}\";\n            if (!string.IsNullOrEmpty(Prerelease))\n            {\n                version += $\"-{Prerelease}\";\n            }\n            if (!string.IsNullOrEmpty(Build))\n            {\n                version += $\"+{Build}\";\n            }\n\n            return version;\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int result = Major.GetHashCode();\n                result = result * 31 + Minor.GetHashCode();\n                result = result * 31 + Patch.GetHashCode();\n                result = result * 31 + Prerelease.GetHashCode();\n                result = result * 31 + Build.GetHashCode();\n                return result;\n            }\n        }\n\n        public SemVersion Parse(string version, bool strict = false)\n        {\n            return SemVersionParser.Parse(version, strict);\n        }\n\n        public static SemVersionTypeTraits VersionTypeTraits { get; } = new SemVersionTypeTraits();\n        public IVersionTypeTraits GetVersionTypeTraits()\n        {\n            return VersionTypeTraits;\n        }\n    }\n\n\n    internal class SemVersionTypeTraits : IVersionTypeTraits\n    {\n        public bool IsAllowedFirstCharacter(char c, bool strict = false)\n        {\n            return VersionTypeTraitsUtils.IsCharDigit(c);\n        }\n\n        public bool IsAllowedLastCharacter(char c, bool strict = false)\n        {\n            return VersionTypeTraitsUtils.IsCharDigit(c) || VersionTypeTraitsUtils.IsCharLetter(c);\n        }\n\n        public bool IsAllowedCharacter(char c)\n        {\n            return VersionTypeTraitsUtils.IsCharDigit(c) || c == '.' || c == '-' || VersionTypeTraitsUtils.IsCharLetter(c);\n        }\n    }\n\n    internal static class SemVersionParser\n    {\n        public static SemVersion Parse(string version, bool strict = false)\n        {\n            if (TryParse(version, out var result) && result.HasValue)\n            {\n                return result.Value;\n            }\n            throw new ArgumentException($\"{version} is not valid Semantic Version\");\n        }\n\n        public static bool TryParse(string version, out SemVersion? result)\n        {\n            if (string.IsNullOrEmpty(version))\n            {\n                result = null;\n                return false;\n            }\n            int cursor = 0;\n\n            int major = 0;\n            int minor = 0;\n            int patch = 0;\n            string prerelease = null;\n            string build = null;\n\n            //Doing this instead because RegEx is impressively slow\n            try\n            {\n                if (!VersionUtils.TryConsumeIntVersionComponentFromString(version, ref cursor, x => !char.IsDigit(x), out major))\n                {\n                    result = null;\n                    return false;\n                }\n\n                if (cursor < version.Length && version[cursor] == '.')\n                {\n                    cursor++;\n                    VersionUtils.TryConsumeIntVersionComponentFromString(version, ref cursor, x => !char.IsDigit(x), out minor, zeroIfEmpty: true);\n                }\n\n                if (cursor < version.Length && version[cursor] == '.')\n                {\n                    cursor++;\n                    VersionUtils.TryConsumeIntVersionComponentFromString(version, ref cursor, x => !char.IsDigit(x), out patch, zeroIfEmpty: true);\n                }\n\n                if (cursor < version.Length && version[cursor] == '-')\n                {\n                    cursor++;\n                    prerelease = VersionUtils.ConsumeVersionComponentFromString(version, ref cursor, x => x == '+');\n                }\n\n                if (cursor < version.Length && version[cursor] == '+')\n                {\n                    cursor++;\n                    build = VersionUtils.ConsumeVersionComponentFromString(version, ref cursor, x => x == '\\0');\n                }\n            }\n            catch (Exception)\n            {\n                result = null;\n                return false;\n            }\n\n\n            result = new SemVersion(major, minor, patch, prerelease, build);\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/TargetAssembly.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing UnityEditor.Scripting.Compilers;\nusing UnityEditor.Compilation;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    [Flags]\n    internal enum TargetAssemblyType\n    {\n        Undefined = 0,\n        Predefined = 1,\n        Custom = 2\n    }\n\n    internal enum EditorCompatibility\n    {\n        NotCompatibleWithEditor = 0,\n        CompatibleWithEditor = 1\n    }\n\n    [DebuggerDisplay(\"{Filename}\")]\n    internal class TargetAssembly\n    {\n        public string Filename { get; private set; }\n        public AssemblyFlags Flags { get; private set; }\n        public string PathPrefix { get; private set; }\n        public string[] AdditionalPrefixes { get; set; }\n        public Func<string, int> PathFilter { get; private set; }\n        public Func<ScriptAssemblySettings, string[], bool> IsCompatibleFunc { get; private set; }\n        public List<TargetAssembly> References { get; set; }\n        public List<string> ExplicitPrecompiledReferences { get; set; }\n        public TargetAssemblyType Type { get; private set; }\n        public string[] Defines { get; set; }\n        public string[] ResponseFileDefines { get; set; }\n        public string RootNamespace { get; set; }\n        public ScriptCompilerOptions CompilerOptions { get; set; }\n        public List<VersionDefine> VersionDefines { get; set; }\n        public string AsmDefPath { get; set; }\n\n        public int MaxPathLength { get; private set; }\n\n        public TargetAssembly()\n        {\n            References = new List<TargetAssembly>();\n            Defines = null;\n        }\n\n        public TargetAssembly(string name,\n                              AssemblyFlags flags,\n                              TargetAssemblyType type,\n                              string pathPrefix,\n                              string[] additionalPrefixes,\n                              Func<string, int> pathFilter,\n                              Func<ScriptAssemblySettings, string[], bool> compatFunc,\n                              ScriptCompilerOptions compilerOptions) : this()\n        {\n            Filename = name;\n            Flags = flags;\n            PathPrefix = pathPrefix;\n            AdditionalPrefixes = additionalPrefixes;\n            PathFilter = pathFilter;\n            IsCompatibleFunc = compatFunc;\n            Type = type;\n            CompilerOptions = compilerOptions;\n            ExplicitPrecompiledReferences = new List<string>();\n            VersionDefines = new List<VersionDefine>();\n\n            if (PathPrefix != null)\n                MaxPathLength = PathPrefix.Length;\n            if (AdditionalPrefixes != null)\n                MaxPathLength = UnityEngine.Mathf.Max(MaxPathLength, AdditionalPrefixes.Max(am => am.Length));\n        }\n\n        public string FullPath(string outputDirectory)\n        {\n            return AssetPath.Combine(outputDirectory, Filename);\n        }\n\n        public EditorCompatibility editorCompatibility\n        {\n            get\n            {\n                bool isCompatibleWithEditor = IsCompatibleFunc == null ||\n                    IsCompatibleFunc(new ScriptAssemblySettings { BuildTarget = BuildTarget.NoTarget, CompilationOptions = EditorScriptCompilationOptions.BuildingForEditor }, null);\n\n                return isCompatibleWithEditor\n                    ? EditorCompatibility.CompatibleWithEditor\n                    : EditorCompatibility.NotCompatibleWithEditor;\n            }\n        }\n\n        public override string ToString()\n        {\n            return string.Format(\"{0} ({1})\", Filename, Type);\n        }\n\n        protected bool Equals(TargetAssembly other)\n        {\n            return string.Equals(Filename, other.Filename) && Flags == other.Flags && Type == other.Type;\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj)) return false;\n            if (ReferenceEquals(this, obj)) return true;\n            if (obj.GetType() != this.GetType()) return false;\n            return Equals((TargetAssembly)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                var hashCode = (Filename != null ? Filename.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ (int)Flags;\n                hashCode = (hashCode * 397) ^ (int)Type;\n                return hashCode;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/TestRunnerHelpers.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Modules;\nusing UnityEditor.Scripting.Compilers;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    static class TestRunnerHelpers\n    {\n        internal const string NunitAssemblyName = \"nunit.framework.dll\";\n        private const string k_EditorTestRunnerAssemblyName = \"UnityEditor.TestRunner.dll\";\n        private const string k_EngineTestRunnerAssemblyName = \"UnityEngine.TestRunner.dll\";\n\n        public static bool ShouldAddTestRunnerReferences(TargetAssembly targetAssembly)\n        {\n            if (UnityCodeGenHelpers.IsCodeGen(targetAssembly.Filename))\n            {\n                return false;\n            }\n\n            bool referencesTestRunnerAssembly = false;\n            foreach (var reference in targetAssembly.References)\n            {\n                referencesTestRunnerAssembly =\n                    reference.Filename.Equals(k_EditorTestRunnerAssemblyName, StringComparison.Ordinal)\n                    || reference.Filename.Equals(k_EngineTestRunnerAssemblyName, StringComparison.Ordinal);\n\n                if (referencesTestRunnerAssembly)\n                {\n                    break;\n                }\n            }\n\n            return !referencesTestRunnerAssembly\n                && !targetAssembly.Filename.Equals(k_EditorTestRunnerAssemblyName, StringComparison.Ordinal)\n                && !targetAssembly.Filename.Equals(k_EngineTestRunnerAssemblyName, StringComparison.Ordinal)\n                && (PlayerSettings.playModeTestRunnerEnabled || (targetAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly);\n        }\n\n        public static IEnumerable<TargetAssembly> GetReferences(IEnumerable<TargetAssembly> assembliesCustomTargetAssemblies)\n        {\n            return assembliesCustomTargetAssemblies.Where(x =>\n                x.Filename == k_EditorTestRunnerAssemblyName ||\n                x.Filename == k_EngineTestRunnerAssemblyName);\n        }\n\n        public static bool ShouldAddNunitReferences(TargetAssembly targetAssembly)\n        {\n            bool referencesNUnit = false;\n\n            if ((targetAssembly.Flags & AssemblyFlags.ExplicitReferences) == AssemblyFlags.ExplicitReferences)\n            {\n                foreach (var explicitPrecompiledReference in targetAssembly.ExplicitPrecompiledReferences)\n                {\n                    referencesNUnit = explicitPrecompiledReference.Equals(NunitAssemblyName, StringComparison.Ordinal);\n                    if (referencesNUnit)\n                    {\n                        break;\n                    }\n                }\n            }\n\n            return !referencesNUnit\n                && (PlayerSettings.playModeTestRunnerEnabled || (targetAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly);\n        }\n\n        public static void AddNunitReferences(Dictionary<string, PrecompiledAssembly> nameToPrecompiledAssemblies, ref List<PrecompiledAssembly> precompiledReferences)\n        {\n            PrecompiledAssembly nUnitAssembly;\n            if (nameToPrecompiledAssemblies.TryGetValue(TestRunnerHelpers.NunitAssemblyName, out nUnitAssembly))\n            {\n                precompiledReferences.Add(nUnitAssembly);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/UnityCodeGenHelpers.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal static class UnityCodeGenHelpers\n    {\n        const string k_CompilerSuffix = \".Compiler\";\n        const string k_CodeGenSuffix = \".CodeGen\";\n        const string k_CompilerTestsSuffix = \".Compiler.Tests\";\n        const string k_CodeGenTestsSuffix = \".CodeGen.Tests\";\n        const string k_CodeGenPrefix = \"Unity.\";\n\n        public static bool IsCodeGen(string assemblyName)\n        {\n            var name = AssetPath.GetAssemblyNameWithoutExtension(assemblyName);\n\n            if (name.StartsWith(k_CodeGenPrefix, StringComparison.OrdinalIgnoreCase) && name.EndsWith(k_CompilerSuffix, StringComparison.OrdinalIgnoreCase))\n                return true;\n\n            if (name.StartsWith(k_CodeGenPrefix, StringComparison.OrdinalIgnoreCase) && name.EndsWith(k_CodeGenSuffix, StringComparison.OrdinalIgnoreCase))\n                return true;\n\n            return false;\n        }\n\n        public static bool IsCodeGenTest(string assemblyName)\n        {\n            var name = AssetPath.GetAssemblyNameWithoutExtension(assemblyName);\n\n            if (name.StartsWith(k_CodeGenPrefix, StringComparison.OrdinalIgnoreCase) && name.EndsWith(k_CompilerTestsSuffix, StringComparison.OrdinalIgnoreCase))\n                return true;\n\n            if (name.StartsWith(k_CodeGenPrefix, StringComparison.OrdinalIgnoreCase) && name.EndsWith(k_CodeGenTestsSuffix, StringComparison.OrdinalIgnoreCase))\n                return true;\n\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/UnitySpecificCompilerMessageProcessor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing NiceIO;\nusing UnityEditor.Scripting.Compilers;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    static class UnitySpecificCompilerMessages\n    {\n        public static void AugmentMessagesInCompilationErrorsWithUnitySpecificAdvice(CompilerMessage[] messages, EditorCompilation editorCompilation)\n        {\n            for (int i = 0; i != messages.Length; i++)\n            {\n                //we only postprocess errors\n                if (messages[i].type != CompilerMessageType.Error)\n                    continue;\n\n                UnsafeErrorProcessor.PostProcess(ref messages[i], editorCompilation);\n                ModuleReferenceErrorProcessor.PostProcess(ref messages[i]);\n                DeterministicAssemblyVersionErrorProcessor.PostProcess(ref messages[i]);\n                CyclicAssemblyReferencesErrorProcessor.PostProcess(ref messages[i]);\n            }\n        }\n\n        internal class ModuleReferenceErrorProcessor\n        {\n            static readonly Regex messageRegex = new Regex(\"[`']UnityEngine.(\\\\w*)Module,\", RegexOptions.Compiled);\n\n            private static string GetNiceDisplayNameForModule(string name)\n            {\n                for (int i = 1; i < name.Length; i++)\n                    if (char.IsLower(name[i - 1]) && !char.IsLower(name[i]))\n                    {\n                        name = name.Insert(i, \" \");\n                        i++;\n                    }\n\n                return name;\n            }\n\n            public static void PostProcess(ref CompilerMessage message)\n            {\n                if (!(message.message.Contains(\"CS1069\") || message.message.Contains(\"CS1070\")))\n                    return;\n\n                var match = messageRegex.Match(message.message);\n                if (!match.Success)\n                    return;\n\n                var index = message.message.IndexOf(\"Consider adding a reference to that assembly.\");\n                if (index != -1)\n                    message.message = message.message.Substring(0, index);\n\n                var moduleName = match.Groups[1].Value;\n                message.message += $\"Enable the built in package '{GetNiceDisplayNameForModule(moduleName)}' in the Package Manager window to fix this error.\";\n            }\n        }\n\n        internal static class DeterministicAssemblyVersionErrorProcessor\n        {\n            public static void PostProcess(ref CompilerMessage message)\n            {\n                if (message.message.Contains(\"CS8357\"))\n                    message.message = $\"Deterministic compilation failed. You can disable Deterministic builds in Player Settings\\n{message.message}\";\n            }\n        }\n\n        internal static class UnsafeErrorProcessor\n        {\n            public static void PostProcess(ref CompilerMessage message, EditorCompilation editorCompilation)\n            {\n                if (!message.message.Contains(\"CS0227\"))\n                    return;\n\n                var customScriptAssembly = CustomScriptAssemblyFor(message, editorCompilation);\n\n                var unityUnsafeMessage = customScriptAssembly != null\n                    ? $\"Enable \\\"Allow 'unsafe' code\\\" in the inspector for '{customScriptAssembly.FilePath}' to fix this error.\"\n                    : \"Enable \\\"Allow 'unsafe' code\\\" in Player Settings to fix this error.\";\n\n                message.message += $\". {unityUnsafeMessage}\";\n            }\n\n            private static CustomScriptAssembly CustomScriptAssemblyFor(CompilerMessage m, EditorCompilation editorCompilation)\n            {\n                if (editorCompilation == null)\n                    return null;\n\n                var file = new NPath(m.file).MakeAbsolute(editorCompilation.projectDirectory);\n\n                return editorCompilation\n                    .GetCustomScriptAssemblies()\n                    .FirstOrDefault(c => file.IsChildOf(new NPath(c.PathPrefix).MakeAbsolute()));\n            }\n        }\n        internal static class CyclicAssemblyReferencesErrorProcessor\n        {\n            public static void PostProcess(ref CompilerMessage message)\n            {\n                int cyclickDependencyMessageStart = message.message.IndexOf(\"One or more cyclic dependencies detected between assemblies\");\n                if (cyclickDependencyMessageStart >= 0)\n                {\n                    int cyclickDependencyMessageEnd = message.message.IndexOf(System.Environment.NewLine, cyclickDependencyMessageStart);\n                    if (cyclickDependencyMessageEnd >= 0)\n                        message.message = message.message.Substring(cyclickDependencyMessageStart, cyclickDependencyMessageEnd - cyclickDependencyMessageStart);\n                    else\n                        message.message = message.message.Substring(cyclickDependencyMessageStart);\n                }\n            }\n        }\n\n\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/UnityVersion.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal struct UnityVersion : IVersion<UnityVersion>\n    {\n        // ReleaseType enum must stay in sync with the native enum ReleaseType in UnityVersion.h\n        public enum UnityReleaseType\n        {\n            kAlphaRelease = 0,\n            kBetaRelease,\n            kPublicRelease,\n            kChinaPublicRelease,\n            kPatchRelease,\n            kExperimentalRelease,\n            kNumUnityReleaseTypes\n        }\n\n        public bool IsInitialized { get; }\n\n        public int Major { get; }\n\n        public int Minor { get; }\n\n        public int Revision { get; }\n\n        public UnityReleaseType ReleaseType { get; }\n\n        public int IncrementalVersion { get; }\n\n        // Suffix following the parse-able part of a string UnityVersion - ignored for any functional purpose. E.g. \"2018.4.3f1-prefab-asset-editing\"\n        public string Suffix { get; }\n\n        public UnityVersion(int major, int minor = 0, int revision = 0, UnityReleaseType releaseType = UnityReleaseType.kPublicRelease, int incrementalVersion = 0, string suffix = \"\")\n        {\n            Major = major;\n            Minor = minor;\n            Revision = revision;\n            ReleaseType = releaseType;\n            IncrementalVersion = incrementalVersion;\n            Suffix = suffix;\n            IsInitialized = true;\n        }\n\n        public static int Compare(UnityVersion versionA, UnityVersion versionB)\n        {\n            return versionA.CompareTo(versionB);\n        }\n\n        public static bool operator==(UnityVersion left, UnityVersion right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator!=(UnityVersion left, UnityVersion right)\n        {\n            return !(left == right);\n        }\n\n        public static bool operator>(UnityVersion left, UnityVersion right)\n        {\n            return Compare(left, right) > 0;\n        }\n\n        public static bool operator>=(UnityVersion left, UnityVersion right)\n        {\n            return left == right || left > right;\n        }\n\n        public static bool operator<(UnityVersion left, UnityVersion right)\n        {\n            return Compare(left, right) < 0;\n        }\n\n        public static bool operator<=(UnityVersion left, UnityVersion right)\n        {\n            return left == right || left < right;\n        }\n\n        public int CompareTo(object obj)\n        {\n            return CompareTo((UnityVersion)obj);\n        }\n\n        public int CompareTo(UnityVersion other)\n        {\n            var result = Major.CompareTo(other.Major);\n            if (result != 0)\n            {\n                return result;\n            }\n\n            result = Minor.CompareTo(other.Minor);\n            if (result != 0)\n            {\n                return result;\n            }\n\n            result = Revision.CompareTo(other.Revision);\n            if (result != 0)\n            {\n                return result;\n            }\n\n            result = CompareReleaseType(ReleaseType, other.ReleaseType);\n            if (result != 0)\n            {\n                return result;\n            }\n\n            result = IncrementalVersion.CompareTo(other.IncrementalVersion);\n            if (result != 0)\n            {\n                return result;\n            }\n\n            // We do not compare the Suffix\n\n            return 0;\n        }\n\n        private static int CompareReleaseType(UnityReleaseType current, UnityReleaseType other)\n        {\n            var rt1 = current != UnityReleaseType.kChinaPublicRelease ? current : UnityReleaseType.kPublicRelease;\n            var rt2 = other != UnityReleaseType.kChinaPublicRelease ? other : UnityReleaseType.kPublicRelease;\n            return (int)rt1 - (int)rt2;\n        }\n\n        public bool Equals(UnityVersion other)\n        {\n            // We do not compare the suffix\n            return Major == other.Major &&\n                Minor == other.Minor &&\n                Revision == other.Revision &&\n                CompareReleaseType(ReleaseType, other.ReleaseType) == 0 &&\n                IncrementalVersion == other.IncrementalVersion;\n        }\n\n        public override bool Equals(object other)\n        {\n            if (ReferenceEquals(null, other))\n                return false;\n\n            return other.GetType() == GetType() && Equals((UnityVersion)other);\n        }\n\n        public override string ToString()\n        {\n            var version = $\"{Major}.{Minor}.{Revision}\";\n            if (ReleaseType != UnityReleaseType.kPublicRelease || IncrementalVersion != 0)\n            {\n                version += $\"{UnityVersionTypeTraits.k_ValidReleaseTypeSymbols[(int)ReleaseType]}\";\n\n                if (IncrementalVersion != 0)\n                {\n                    version += $\"{IncrementalVersion}\";\n                }\n            }\n            return version;\n        }\n\n        public string ToStringFull()\n        {\n            var version = ToString();\n            if (!string.IsNullOrEmpty(Suffix))\n            {\n                version += $\"{Suffix}\";\n            }\n            return version;\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int result = Major.GetHashCode();\n                result = result * 31 + Minor.GetHashCode();\n                result = result * 31 + Revision.GetHashCode();\n                result = result * 31 + GetReleaseTypeHashCode(ReleaseType);\n                result = result * 31 + IncrementalVersion.GetHashCode();\n                // We do not compare the suffix, so we do not hash it either\n                return result;\n            }\n        }\n\n        private static int GetReleaseTypeHashCode(UnityReleaseType releaseType)\n        {\n            var rt = releaseType != UnityReleaseType.kChinaPublicRelease ? releaseType : UnityReleaseType.kPublicRelease;\n            return rt.GetHashCode();\n        }\n\n        public UnityVersion Parse(string version, bool strict = false)\n        {\n            return UnityVersionParser.Parse(version, strict);\n        }\n\n        public static UnityVersionTypeTraits VersionTypeTraits { get; } = new UnityVersionTypeTraits();\n        public IVersionTypeTraits GetVersionTypeTraits()\n        {\n            return VersionTypeTraits;\n        }\n    }\n\n    internal class UnityVersionTypeTraits : IVersionTypeTraits\n    {\n        public bool IsAllowedFirstCharacter(char c, bool strict = false)\n        {\n            return VersionTypeTraitsUtils.IsCharDigit(c);\n        }\n\n        public bool IsAllowedLastCharacter(char c, bool strict = false)\n        {\n            return strict ? (VersionTypeTraitsUtils.IsCharDigit(c) || VersionTypeTraitsUtils.IsCharLetter(c)) : IsAllowedCharacter(c);\n        }\n\n        public bool IsAllowedCharacter(char c)\n        {\n            return VersionTypeTraitsUtils.IsCharDigit(c) || VersionTypeTraitsUtils.IsCharLetter(c)\n                || c == '.' || c == '-' || c == '/';\n        }\n\n        public static readonly char[] k_ValidReleaseTypeSymbols = new[]\n        {\n            'a', // UnityReleaseType.kAlphaRelease\n            'b', // UnityReleaseType.kBetaRelease\n            'f', // UnityReleaseType.kPublicRelease\n            'c', // China release, treat as 'f'\n            'p', // UnityReleaseType.kPatchRelease\n            'x', // UnityReleaseType.kExperimentalRelease\n        };\n\n        static UnityVersionTypeTraits()\n        {\n            UnityEngine.Assertions.Assert.IsTrue(k_ValidReleaseTypeSymbols.Length == (int)UnityVersion.UnityReleaseType.kNumUnityReleaseTypes);\n        }\n\n        public static bool IsAllowedUnityReleaseTypeIdentifier(char c)\n        {\n            for (int i = 0; i < k_ValidReleaseTypeSymbols.Length; i++)\n                if (k_ValidReleaseTypeSymbols[i] == c)\n                    return true;\n\n            return false;\n        }\n\n        public static UnityVersion.UnityReleaseType ParseUnityReleaseType(char releaseType)\n        {\n            if (TryParseUnityReleaseType(releaseType, out var result))\n            {\n                return result;\n            }\n            throw new ArgumentException($\"UnityVersionTypeTraits does not recognize release type symbol '{releaseType}'.\");\n        }\n\n        public static bool TryParseUnityReleaseType(char releaseType, out UnityVersion.UnityReleaseType result)\n        {\n            for (int i = (int)UnityVersion.UnityReleaseType.kAlphaRelease; i < (int)UnityVersion.UnityReleaseType.kNumUnityReleaseTypes; ++i)\n            {\n                if (releaseType == k_ValidReleaseTypeSymbols[i])\n                {\n                    result = (UnityVersion.UnityReleaseType)i;\n                    return true;\n                }\n            }\n            result = UnityVersion.UnityReleaseType.kNumUnityReleaseTypes;\n            return false;\n        }\n    }\n\n    internal static class UnityVersionParser\n    {\n        private static bool TryReadVersionNumber(string version, ref int cursor, ref int versionComponent)\n        {\n            string nextVersionComponent = VersionUtils.ConsumeVersionComponentFromString(version, ref cursor, x => !char.IsDigit(x));\n            if (!String.IsNullOrEmpty(nextVersionComponent))\n            {\n                return int.TryParse(nextVersionComponent, out versionComponent);\n            }\n            return false;\n        }\n\n        private static bool TrySkipVersionSeparator(string version, ref int cursor)\n        {\n            if (cursor < version.Length && version[cursor] == '.')\n            {\n                cursor++;\n                return cursor < version.Length; // . is not allowed to be the last symbol\n            }\n            return false;\n        }\n\n        private static bool TryReadVersionReleaseType(string version, ref int cursor, ref UnityVersion.UnityReleaseType releaseType)\n        {\n            if (cursor < version.Length && UnityVersionTypeTraits.IsAllowedUnityReleaseTypeIdentifier(version[cursor]))\n            {\n                if (UnityVersionTypeTraits.TryParseUnityReleaseType(version[cursor], out releaseType))\n                {\n                    cursor++;\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public static UnityVersion Parse(string version, bool strict = false)\n        {\n            if (TryParse(version, out var result, strict) && result.HasValue)\n            {\n                return result.Value;\n            }\n\n            throw new ArgumentException($\"'{version}' is not a valid Unity Version\");\n        }\n\n        public static bool TryParse(string version, out UnityVersion? result, bool strict = false)\n        {\n            int cursor = 0;\n\n            int major = 0;\n            int minor = 0;\n            int revision = 0;\n            // missing release type identifier means 'f' - public release, so that is the default as well\n            UnityVersion.UnityReleaseType releaseType = UnityVersion.UnityReleaseType.kPublicRelease;\n            int incrementalVersion = 0;\n            string suffix = \"\";\n            bool isValid = true;\n\n            // Doing this instead because RegEx is impressively slow\n            try\n            {\n                isValid = cursor < version.Length && TryReadVersionNumber(version, ref cursor, ref major);\n                isValid = isValid && (cursor == version.Length || TrySkipVersionSeparator(version, ref cursor));\n                isValid = isValid && (cursor == version.Length || TryReadVersionNumber(version, ref cursor, ref minor));\n                isValid = isValid && (cursor == version.Length || TrySkipVersionSeparator(version, ref cursor));\n                isValid = isValid && (cursor == version.Length || TryReadVersionNumber(version, ref cursor, ref revision));\n                isValid = isValid && (cursor == version.Length || TryReadVersionReleaseType(version, ref cursor, ref releaseType));\n                isValid = isValid && (cursor == version.Length ||\n                    // experimental 'x' releases can have any characters following the 'x', so we don't read incrementalVersion but save the rest into the suffix\n                    releaseType == UnityVersion.UnityReleaseType.kExperimentalRelease ||\n                    TryReadVersionNumber(version, ref cursor, ref incrementalVersion));\n                // if there's anything left, read the rest as suffix if experimental release or allowSuffix parse request\n                if (isValid && cursor < version.Length)\n                {\n                    if (releaseType == UnityVersion.UnityReleaseType.kExperimentalRelease || !strict)\n                        suffix = version.Substring(cursor);\n                    else\n                        isValid = false;\n                }\n            }\n            catch (Exception)\n            {\n                result = null;\n                return false;\n            }\n            if (!isValid)\n            {\n                result = null;\n                return false;\n            }\n\n            result = new UnityVersion(major, minor, revision, releaseType, incrementalVersion, suffix);\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/Utility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Globalization;\nusing System.Runtime.CompilerServices;\nusing UnityEngine;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    static class Utility\n    {\n        public static char FastToLower(char c)\n        {\n            // ASCII non-letter characters and\n            // lower case letters.\n            if (c < 'A' || (c > 'Z' && c <= 'z'))\n            {\n                return c;\n            }\n\n            if (c >= 'A' && c <= 'Z')\n            {\n                return (char)(c + 32);\n            }\n\n            return Char.ToLower(c, CultureInfo.InvariantCulture);\n        }\n\n        public static string FastToLower(string str)\n        {\n            int length = str.Length;\n\n            var chars = new char[length];\n\n            for (int i = 0; i < length; ++i)\n            {\n                chars[i] = FastToLower(str[i]);\n            }\n\n            return new string(chars);\n        }\n\n        public static bool FastStartsWith(string str, string prefix, string prefixLowercase)\n        {\n            if (str == null || prefix == null)\n            {\n                return false;\n            }\n\n            int strLength = str.Length;\n            int prefixLength = prefix.Length;\n\n            if (prefixLength > strLength)\n                return false;\n\n            int lastPrefixCharIndex = prefixLength - 1;\n\n            // Check last char in prefix is equal. Since we are comparing\n            // file paths against directory paths, the last char will be '/'.\n            if (str[lastPrefixCharIndex] != prefix[lastPrefixCharIndex])\n                return false;\n\n            for (int i = 0; i < prefixLength; ++i)\n            {\n                if (str[i] == prefix[i])\n                    continue;\n\n                char strC = FastToLower(str[i]);\n\n                if (strC != prefixLowercase[i])\n                    return false;\n            }\n\n            return true;\n        }\n\n        public static bool IsAssetsPath(string path)\n        {\n            const string assetsLowerCase = \"assets\";\n            const string assetsUpperCase = \"ASSETS\";\n\n            if (path.Length < 7)\n                return false;\n\n            if (path[6] != '/')\n                return false;\n\n            for (int i = 0; i < 6; ++i)\n            {\n                if (path[i] != assetsLowerCase[i] && path[i] != assetsUpperCase[i])\n                    return false;\n            }\n\n            return true;\n        }\n\n        public static string ReadTextAsset(string path)\n        {\n            if (IsAssetsPath(path))\n            {\n                var textAsset = AssetDatabase.LoadAssetAtPath<UnityEngine.TextAsset>(path);\n\n                if (textAsset != null)\n                    return textAsset.text;\n            }\n\n            // Support out of project reading of files for tests.\n            return System.IO.File.ReadAllText(path);\n        }\n\n        public static string FileNameWithoutExtension(string path)\n        {\n            if (string.IsNullOrEmpty(path))\n            {\n                return \"\";\n            }\n\n            var indexOfDot = -1;\n            var indexOfSlash = 0;\n            for (var i = path.Length - 1; i >= 0; i--)\n            {\n                if (indexOfDot == -1 && path[i] == '.')\n                {\n                    indexOfDot = i;\n                }\n\n                if (indexOfSlash == 0 && path[i] == '/' || path[i] == '\\\\')\n                {\n                    indexOfSlash = i + 1;\n                    break;\n                }\n            }\n\n            if (indexOfDot == -1)\n            {\n                indexOfDot = path.Length;\n            }\n\n            return path.Substring(indexOfSlash, indexOfDot - indexOfSlash);\n        }\n\n        public static bool IsPathsEqual(ReadOnlySpan<char> left, ReadOnlySpan<char> right)\n        {\n            if (left.Length != right.Length)\n                return false;\n\n            for (var index = 0; index < left.Length; index++)\n            {\n                var leftCurrentChar = left[index];\n                var rightCurrentChar = right[index];\n\n                if (IsPathSeparator(leftCurrentChar) && IsPathSeparator(rightCurrentChar))\n                {\n                    continue;\n                }\n\n                if (leftCurrentChar != rightCurrentChar)\n                    return false;\n            }\n\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPathSeparator(char character)\n        {\n            return character == '/' || character == '\\\\';\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/VersionDefineExpression.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal struct VersionDefineExpression<TVersion> where TVersion : struct, IVersion<TVersion>\n    {\n        private Func<TVersion, TVersion, TVersion, bool> m_IsValid;\n        public TVersion Left { get; }\n        public TVersion Right { get; }\n\n        private string m_AppliedRule;\n        public string AppliedRule\n        {\n            get { return string.Format(m_AppliedRule, Left, Right); }\n            set { m_AppliedRule = value; }\n        }\n\n        public VersionDefineExpression(Func<TVersion, TVersion, TVersion, bool> isValid, TVersion leftVersion, TVersion rightVersion)\n        {\n            m_IsValid = isValid;\n            m_AppliedRule = null;\n            Left = leftVersion;\n            Right = rightVersion;\n        }\n\n        public bool IsValid(TVersion version)\n        {\n            if (!version.IsInitialized)\n            {\n                throw new ArgumentNullException(nameof(version));\n            }\n\n            return m_IsValid(Left, Right, version);\n        }\n\n        public static VersionDefineExpression<TVersion> Invalid { get; } = new VersionDefineExpression<TVersion>(\n            (unused1, unused2, unused3) => false, default(TVersion), default(TVersion));\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/VersionDefinesConsoleLogs.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditorInternal;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    interface IVersionDefinesConsoleLogs\n    {\n        void LogVersionDefineError(TargetAssembly targetAssembly, ExpressionNotValidException validationError);\n        void ClearVersionDefineErrors();\n    }\n\n    [NativeHeader(\"Editor/Src/ScriptCompilation/VersionDefinesConsoleLogs.h\")]\n    class VersionDefinesConsoleLogs : IVersionDefinesConsoleLogs\n    {\n        public void LogVersionDefineError(TargetAssembly targetAssembly, ExpressionNotValidException validationError)\n        {\n            var asset = AssetDatabase.LoadAssetAtPath<AssemblyDefinitionAsset>(EditorCompilationInterface.Instance.FindCustomTargetAssemblyFromTargetAssembly(targetAssembly).FilePath);\n            var instanceID = asset.GetInstanceID();\n            InternalLogVersionDefineError(validationError, instanceID);\n        }\n\n        public void ClearVersionDefineErrors()\n        {\n            InternalClearVersionDefineErrors();\n        }\n\n        [FreeFunction(nameof(InternalLogVersionDefineError))]\n        static extern void InternalLogVersionDefineError(Exception ex, int assetInstanceID);\n\n\n        [FreeFunction(nameof(InternalClearVersionDefineErrors))]\n        static extern void InternalClearVersionDefineErrors();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/VersionRanges.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine.Assertions;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal struct VersionRanges<TVersion> where TVersion : struct, IVersion<TVersion>\n    {\n        private readonly Dictionary<ExpressionTypeKey, ExpressionTypeValue<TVersion>> m_ExpressionTypes;\n        private static readonly char[] k_LeftValidSymbols = new[] { '[', '(', };\n        private static readonly char[] k_RightValidSymbols = new[] { ']', ')', };\n        private static readonly TVersion m_versionTypeStaticFunctionalityProxy;\n\n        static VersionRanges()\n        {\n            // String representations of Version Types must not allow any of these characters, because\n            // they have other meaning inside a version range expression.\n            m_versionTypeStaticFunctionalityProxy = new TVersion();\n            IVersionTypeTraits versionTypeTraits = m_versionTypeStaticFunctionalityProxy.GetVersionTypeTraits();\n            Assert.IsFalse(versionTypeTraits.IsAllowedCharacter('*'));\n            Assert.IsFalse(versionTypeTraits.IsAllowedCharacter(','));\n            Assert.IsFalse(versionTypeTraits.IsAllowedCharacter('['));\n            Assert.IsFalse(versionTypeTraits.IsAllowedCharacter('('));\n            Assert.IsFalse(versionTypeTraits.IsAllowedCharacter(']'));\n            Assert.IsFalse(versionTypeTraits.IsAllowedCharacter(')'));\n        }\n\n        public VersionRanges(Dictionary<ExpressionTypeKey, ExpressionTypeValue<TVersion>> expressionTypes)\n        {\n            m_ExpressionTypes = expressionTypes;\n        }\n\n        public VersionDefineExpression<TVersion> GetExpression(string expression)\n        {\n            if (string.IsNullOrEmpty(expression))\n            {\n                throw new ArgumentNullException(nameof(expression));\n            }\n\n            ExpressionParsedData parsedExpressionData = ParseExpression(expression);\n            if (m_ExpressionTypes.ContainsKey(parsedExpressionData.GenerateExpressionTypeKey))\n            {\n                ExpressionTypeValue<TVersion> expressionTypeValue = m_ExpressionTypes[parsedExpressionData.GenerateExpressionTypeKey];\n\n                return new VersionDefineExpression<TVersion>(expressionTypeValue.IsValid, parsedExpressionData.leftVersion, parsedExpressionData.rightVersion)\n                {\n                    AppliedRule = expressionTypeValue.AppliedRule,\n                };\n            }\n            throw new ExpressionNotValidException($\"'{expression}' is not a valid expression\");\n        }\n\n        private static bool Contains(string array, char doContain)\n        {\n            for (int i = 0; i < array.Length; i++)\n            {\n                if (array[i] == doContain)\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        private static bool Contains(char[] array, char doContain)\n        {\n            for (int i = 0; i < array.Length; i++)\n            {\n                if (array[i] == doContain)\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        private ExpressionParsedData ParseExpression(string expression)\n        {\n            ExpressionParsedData expressionParsedData = new ExpressionParsedData();\n\n            if (expression.Length == 0)\n            {\n                return expressionParsedData;\n            }\n\n            IVersionTypeTraits versionTypeTraits = m_versionTypeStaticFunctionalityProxy.GetVersionTypeTraits();\n\n            bool hasSeperator = Contains(expression, ',');\n            char leftSymbol = default(char);\n            char rightSymbol = default(char);\n\n            int begin = 0;\n            int end = expression.Length - 1;\n\n            if (!versionTypeTraits.IsAllowedFirstCharacter(expression[0]))\n            {\n                leftSymbol = expression[0];\n                if (!Contains(k_LeftValidSymbols, leftSymbol))\n                {\n                    throw new ExpressionNotValidException($\"Invalid character '{leftSymbol}' in expression\", expression);\n                }\n\n                begin++;\n            }\n\n            var lastChar = expression[end];\n            if (!versionTypeTraits.IsAllowedLastCharacter(lastChar))\n            {\n                rightSymbol = lastChar;\n\n                if (!Contains(k_RightValidSymbols, rightSymbol))\n                {\n                    throw new ExpressionNotValidException($\"Invalid character '{rightSymbol}' in expression\", expression);\n                }\n\n                end--;\n            }\n\n            if ((leftSymbol != default(char) && rightSymbol == default(char)) ||\n                (leftSymbol == default(char) && rightSymbol != default(char)))\n            {\n                throw new ExpressionNotValidException(\"Incomplete expression, missing symbol in start or end\", expression);\n            }\n\n            int nextVersion;\n            string leftVersionString = PopVersionString(expression, begin, end, out nextVersion, versionTypeTraits);\n            var hasLeftVersion = !string.IsNullOrEmpty(leftVersionString);\n            if (hasLeftVersion)\n            {\n                expressionParsedData.leftVersion = (TVersion)m_versionTypeStaticFunctionalityProxy.Parse(leftVersionString);\n            }\n\n            int notNeeded;\n            string rightVersionString = PopVersionString(expression, nextVersion, end, out notNeeded, versionTypeTraits);\n            var hasRightVersion = !string.IsNullOrEmpty(rightVersionString);\n            if (hasRightVersion)\n            {\n                expressionParsedData.rightVersion = (TVersion)m_versionTypeStaticFunctionalityProxy.Parse(rightVersionString);\n            }\n            expressionParsedData.GenerateExpressionTypeKey = new ExpressionTypeKey(leftSymbol: leftSymbol, rightSymbol: rightSymbol, hasSeparator: hasSeperator, hasLeftVersion: hasLeftVersion, hasRightVersion: hasRightVersion);\n            return expressionParsedData;\n        }\n\n        private static string PopVersionString(string expression, int begin, int end, out int newBegin, IVersionTypeTraits versionTypeTraits)\n        {\n            newBegin = begin;\n            if (begin > end)\n            {\n                return null;\n            }\n\n            int count = 0;\n            while (newBegin <= end)\n            {\n                var value = expression[newBegin];\n\n                if (value == ',')\n                {\n                    newBegin++;\n                    break;\n                }\n\n                if (!versionTypeTraits.IsAllowedCharacter(value) && value != '*')\n                {\n                    throw new ExpressionNotValidException($\"'{value}' is not valid in the expression\");\n                }\n\n                count++;\n                newBegin++;\n            }\n\n            return expression.Substring(begin, count);\n        }\n\n        private struct ExpressionParsedData\n        {\n            public TVersion leftVersion;\n            public TVersion rightVersion;\n            public ExpressionTypeKey GenerateExpressionTypeKey;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/VersionRangesEvaluators.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    internal static class VersionRangesEvaluators<TVersion> where TVersion : struct, IVersion<TVersion>\n    {\n        public static bool MinimumVersionInclusive(TVersion left, TVersion right, TVersion version)\n        {\n            return version.Equals(left) || version.CompareTo(left) > 0; // version >= left;\n        }\n\n        public static bool MinimumVersionExclusive(TVersion left, TVersion right, TVersion version)\n        {\n            return version.CompareTo(left) > 0; // version > left;\n        }\n\n        public static bool ExactVersionMatch(TVersion left, TVersion right, TVersion version)\n        {\n            return version.Equals(left); // left == version;\n        }\n\n        public static bool MaximumVersionInclusive(TVersion left, TVersion right, TVersion version)\n        {\n            return version.Equals(right) || version.CompareTo(right) < 0; // version <= right;\n        }\n\n        public static bool MaximumVersionExclusive(TVersion left, TVersion right, TVersion version)\n        {\n            return version.CompareTo(right) < 0; // version < right;\n        }\n\n        public static bool ExactRangeInclusive(TVersion left, TVersion right, TVersion version)\n        {\n            return MinimumVersionInclusive(left, right, version)  // left <= version\n                && MaximumVersionInclusive(left, right, version); // && version <= right;\n        }\n\n        public static bool ExactRangeExclusive(TVersion left, TVersion right, TVersion version)\n        {\n            return MinimumVersionExclusive(left, right, version)  // left < version\n                && MaximumVersionExclusive(left, right, version); // && version < right;\n        }\n\n        public static bool MixedInclusiveMinimumAndExclusiveMaximumVersion(TVersion left, TVersion right, TVersion version)\n        {\n            return MinimumVersionInclusive(left, right, version)  // left <= version\n                && MaximumVersionExclusive(left, right, version); // && version < right;\n        }\n\n        public static bool MixedExclusiveMinimumAndInclusiveMaximumVersion(TVersion left, TVersion right, TVersion version)\n        {\n            return MinimumVersionExclusive(left, right, version)  // left < version\n                && MaximumVersionInclusive(left, right, version); // && version <= right;\n        }\n\n        public static bool Invalid(string expression)\n        {\n            throw new ExpressionNotValidException($\"Unknown expression: {expression}\");\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilation/VersionRangesFactory.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace UnityEditor.Scripting.ScriptCompilation\n{\n    class VersionRangesFactory<TVersion> where TVersion : struct, IVersion<TVersion>\n    {\n        VersionRanges<TVersion> m_VersionRanges;\n\n        public VersionRangesFactory()\n        {\n            m_VersionRanges = new VersionRanges<TVersion>(ExpressionTypeFactory<TVersion>.Create());\n        }\n\n        public VersionDefineExpression<TVersion> GetExpression(string expression)\n        {\n            return m_VersionRanges.GetExpression(expression);\n        }\n    }\n\n    class CachedVersionRangesFactory<TVersion> where TVersion : struct, IVersion<TVersion>\n    {\n        private VersionRangesFactory<TVersion> m_InnerFactory = new VersionRangesFactory<TVersion>();\n\n        private readonly Dictionary<string, CacheEntry> m_Cache =\n            new Dictionary<string, CacheEntry>();\n\n\n        public CacheEntry GetExpression(string expression)\n        {\n            lock (m_Cache)\n            {\n                if (m_Cache.TryGetValue(expression, out var result))\n                {\n                    return result;\n                }\n\n                try\n                {\n                    var entry = new CacheEntry(m_InnerFactory.GetExpression(expression));\n                    m_Cache[expression] = entry;\n                    return entry;\n                }\n                catch (ExpressionNotValidException ex)\n                {\n                    var entry = new CacheEntry(ex);\n                    m_Cache[expression] = entry;\n                    return entry;\n                }\n            }\n        }\n\n        public void Clear()\n        {\n            lock (m_Cache)\n            {\n                m_Cache.Clear();\n                m_InnerFactory = new VersionRangesFactory<TVersion>();\n            }\n        }\n\n        public readonly struct CacheEntry\n        {\n            public VersionDefineExpression<TVersion> Expression { get; }\n            public ExpressionNotValidException ValidationError { get; }\n\n            public CacheEntry(VersionDefineExpression<TVersion> expression)\n            {\n                Expression = expression;\n                ValidationError = null;\n            }\n\n            public CacheEntry(ExpressionNotValidException validationError)\n            {\n                Expression = VersionDefineExpression<TVersion>.Invalid;\n                ValidationError = validationError;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Scripting/ScriptCompilers.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.ComponentModel;\nusing System.Runtime.InteropServices;\nusing UnityEditor.Utils;\nusing UnityEngine;\n\nnamespace UnityEditor.Scripting\n{\n    internal static class ScriptCompilers\n    {\n        [Flags]\n        enum ProcessCreationFlags : uint\n        {\n            CREATE_NO_WINDOW = 0x08000000,\n        }\n\n        struct STARTUPINFOW\n        {\n            public uint cb;\n            [MarshalAs(UnmanagedType.LPWStr)]\n            public string lpReserved;\n            [MarshalAs(UnmanagedType.LPWStr)]\n            public string lpDesktop;\n            [MarshalAs(UnmanagedType.LPWStr)]\n            public string lpTitle;\n            public uint dwX;\n            public uint dwY;\n            public uint dwXSize;\n            public uint dwYSize;\n            public uint dwXCountChars;\n            public uint dwYCountChars;\n            public uint dwFillAttribute;\n            public uint dwFlags;\n            public ushort wShowWindow;\n            public ushort cbReserved2;\n            public IntPtr lpReserved2;\n            public IntPtr hStdInput;\n            public IntPtr hStdOutput;\n            public IntPtr hStdError;\n        }\n\n        struct PROCESS_INFORMATION\n        {\n            public IntPtr hProcess;\n            public IntPtr hThread;\n            public uint dwProcessId;\n            public uint dwThreadId;\n        }\n\n        [DllImport(\"kernel32.dll\", SetLastError = true)]\n        static extern bool CreateProcessW(\n            [MarshalAs(UnmanagedType.LPWStr)] string lpApplicationName,\n            [MarshalAs(UnmanagedType.LPWStr)] string lpCommandLine,\n            IntPtr lpProcessAttributes,\n            IntPtr lpThreadAttributes,\n            bool bInheritHandles,\n            ProcessCreationFlags dwCreationFlags,\n            IntPtr lpEnvironment,\n            [MarshalAs(UnmanagedType.LPWStr)] string lpCurrentDirectory,\n            ref STARTUPINFOW lpStartupInfo,\n            out PROCESS_INFORMATION lpProcessInformation);\n\n        internal static void Cleanup()\n        {\n            if (Application.platform == RuntimePlatform.WindowsEditor)\n            {\n                // Use CreateProcessW as opposed to C# Process class to run\n                // the script so that we could disable handle inheritance\n                STARTUPINFOW startInfo = default;\n                startInfo.cb = (uint)Marshal.SizeOf<STARTUPINFOW>();\n\n                var batFile = Paths.Combine(EditorApplication.applicationContentsPath, \"Tools\", \"RoslynScripts\", \"kill_csc_server.bat\");\n                if (!CreateProcessW(null, $\"cmd.exe /c \\\"{batFile}\\\"\", IntPtr.Zero, IntPtr.Zero, false, ProcessCreationFlags.CREATE_NO_WINDOW, IntPtr.Zero, null, ref startInfo, out var _))\n                {\n                    var lastError = Marshal.GetLastWin32Error();\n                    Debug.LogError(\"Failed to kill csc server process: \" + new Win32Exception(lastError).Message);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ScriptingDefinesHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace UnityEditor;\n\ninternal static class ScriptingDefinesHelper\n{\n    private static readonly char[] DefineSeparators = { ';', ',', ' ' };\n\n    internal static string ConvertScriptingDefineArrayToString(string[] defines)\n    {\n        if (defines == null)\n        {\n            throw new ArgumentNullException(nameof(defines));\n        }\n\n        var flattenedDefines = new List<string>();\n        foreach (var define in defines)\n        {\n            flattenedDefines.AddRange(define.Split(DefineSeparators, StringSplitOptions.RemoveEmptyEntries));\n        }\n\n        var distinctDefines = new HashSet<string>();\n        foreach (var define in flattenedDefines)\n        {\n            distinctDefines.Add(define);\n        }\n\n        return string.Join(\";\", distinctDefines);\n    }\n\n    internal static string[] ConvertScriptingDefineStringToArray(string defines)\n    {\n        var splitDefines = string.IsNullOrEmpty(defines)\n            ? Array.Empty<string>()\n            : defines.Split(DefineSeparators, StringSplitOptions.RemoveEmptyEntries);\n\n        var distinctDefines = new HashSet<string>();\n        foreach (var define in splitDefines)\n        {\n            distinctDefines.Add(define);\n        }\n\n        var distinctDefinesArray = new string[distinctDefines.Count];\n        distinctDefines.CopyTo(distinctDefinesArray);\n        return distinctDefinesArray;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Search/AdvancedObjectSelectorAttribute.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.SearchService\n{\n    delegate void AdvancedObjectSelectorHandler(AdvancedObjectSelectorEventType eventType, in AdvancedObjectSelectorParameters parameters);\n    delegate bool AdvancedObjectSelectorValidatorHandler(ObjectSelectorSearchContext context);\n\n    interface IAdvancedObjectSelectorAttribute\n    {\n        internal string id { get; }\n    }\n\n    [AttributeUsage(AttributeTargets.Method, Inherited = false)]\n    public class AdvancedObjectSelectorAttribute : Attribute, IAdvancedObjectSelectorAttribute\n    {\n        internal string id { get; }\n        internal string displayName { get; }\n        internal int defaultPriority { get; set; }\n\n        internal bool defaultActive { get; set; }\n\n        string IAdvancedObjectSelectorAttribute.id => id;\n\n        public AdvancedObjectSelectorAttribute(string id, string displayName, int defaultPriority, bool defaultActive = true)\n        {\n            this.id = id;\n            this.displayName = displayName;\n            this.defaultPriority = defaultPriority;\n            this.defaultActive = defaultActive;\n        }\n\n        public AdvancedObjectSelectorAttribute(string id, int defaultPriority, bool defaultActive = true)\n            : this(id, null, defaultPriority, defaultActive)\n        { }\n    }\n\n    [AttributeUsage(AttributeTargets.Method, Inherited = false)]\n    public class AdvancedObjectSelectorValidatorAttribute : Attribute, IAdvancedObjectSelectorAttribute\n    {\n        internal string id { get; }\n        string IAdvancedObjectSelectorAttribute.id => id;\n\n        public AdvancedObjectSelectorValidatorAttribute(string id)\n        {\n            this.id = id;\n        }\n    }\n\n    public readonly struct AdvancedObjectSelectorParameters\n    {\n        public ObjectSelectorSearchContext context { get; }\n        public Action<UnityEngine.Object, bool> selectorClosedHandler { get; }\n        public Action<UnityEngine.Object> trackingHandler { get; }\n        public string searchFilter { get; }\n\n        internal AdvancedObjectSelectorParameters(ObjectSelectorSearchContext context, Action<UnityEngine.Object, bool> selectorClosedHandler, Action<UnityEngine.Object> trackingHandler, string searchFilter)\n        {\n            this.context = context;\n            this.selectorClosedHandler = selectorClosedHandler;\n            this.trackingHandler = trackingHandler;\n            this.searchFilter = searchFilter;\n        }\n\n        internal AdvancedObjectSelectorParameters(ObjectSelectorSearchContext context)\n            : this(context, null, null, string.Empty)\n        { }\n\n        internal AdvancedObjectSelectorParameters(ObjectSelectorSearchContext context, Action<UnityEngine.Object, bool> selectorClosedHandler, Action<UnityEngine.Object> trackingHandler)\n            : this(context, selectorClosedHandler, trackingHandler, string.Empty)\n        { }\n\n        internal AdvancedObjectSelectorParameters(ObjectSelectorSearchContext context, string searchFilter)\n            : this(context, null, null, searchFilter)\n        { }\n\n        internal AdvancedObjectSelectorParameters(ISearchContext context)\n            : this((ObjectSelectorSearchContext)context, null, null, string.Empty)\n        { }\n\n        internal AdvancedObjectSelectorParameters(ISearchContext context, Action<UnityEngine.Object, bool> selectorClosedHandler, Action<UnityEngine.Object> trackingHandler)\n            : this((ObjectSelectorSearchContext)context, selectorClosedHandler, trackingHandler, string.Empty)\n        { }\n\n        internal AdvancedObjectSelectorParameters(ISearchContext context, string searchFilter)\n            : this((ObjectSelectorSearchContext)context, null, null, searchFilter)\n        { }\n    }\n\n    public enum AdvancedObjectSelectorEventType\n    {\n        BeginSession,\n        EndSession,\n        OpenAndSearch,\n        SetSearchFilter\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Search/LegacyImplementations.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine.UIElements;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor.SearchService\n{\n    // Default implementations for built-in search engines.\n    abstract class LegacySearchEngineBase : ISearchEngineBase\n    {\n        internal const string k_Name = \"Classic\";\n        public string name => k_Name;\n\n        public virtual void BeginSession(ISearchContext context)\n        {}\n\n        public virtual void EndSession(ISearchContext context)\n        {}\n\n        public virtual void BeginSearch(ISearchContext context, string query)\n        {}\n\n        public virtual void EndSearch(ISearchContext context)\n        {}\n    }\n\n    abstract class DefaultSearchEngine<T> : LegacySearchEngineBase, ISearchEngine<T>\n    {\n        public virtual IEnumerable<T> Search(ISearchContext context, string query, Action<IEnumerable<T>> asyncItemsReceived)\n        {\n            return null;\n        }\n    }\n\n    abstract class DefaultFilterEngine<T> : LegacySearchEngineBase, IFilterEngine<T>\n    {\n        public virtual bool Filter(ISearchContext context, string query, T objectToFilter)\n        {\n            return false;\n        }\n    }\n\n    abstract class DefaultObjectSelectorEngine : LegacySearchEngineBase, ISelectorEngine\n    {\n        public virtual bool SelectObject(ISearchContext context, Action<Object, bool> onObjectSelectorClosed, Action<Object> onObjectSelectedUpdated)\n        {\n            return false;\n        }\n\n        public virtual void SetSearchFilter(ISearchContext context, string searchFilter)\n        {}\n    }\n\n    // Default project search engine. Nothing is overriden. We keep returning null because\n    // of how the search is implemented in the project browser. The null value is handled there,\n    // and the default behavior is used when null is returned.\n    [ProjectSearchEngine]\n    class ProjectSearchEngine : DefaultSearchEngine<string>, IProjectSearchEngine\n    {}\n\n    // Default scene search engine.\n    [SceneSearchEngine]\n    class HierarchySearchEngine : DefaultFilterEngine<HierarchyProperty>, ISceneSearchEngine\n    {\n        public override bool Filter(ISearchContext context, string query, HierarchyProperty objectToFilter)\n        {\n            // Returning true here, since the properties have already been filtered. See BeginSearch().\n            return true;\n        }\n\n        public override void BeginSearch(ISearchContext context, string query)\n        {\n            // To get the original behavior and performance, we set the filter on the root property\n            // at the beginning of a search. This will have the effect of filtering the properties\n            // during a call to Next() or NextWithDepthCheck(), so Filter() should always return true.\n            var hierarchySearchContext = context as SceneSearchContext;\n            hierarchySearchContext?.rootProperty.SetSearchFilter(hierarchySearchContext.searchFilter);\n        }\n    }\n\n    // Default object selector engine. Nothing is overriden. We keep returning false because\n    // of how the selector is implemented in the object selector. The bool value is handled there,\n    // and the default behavior is used when false is returned.\n    [ObjectSelectorEngine]\n    class ObjectPickerEngine : DefaultObjectSelectorEngine, IObjectSelectorEngine\n    {}\n}\n"
  },
  {
    "path": "Editor/Mono/Search/ObjectSelector.Deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor.SearchService\n{\n    [Obsolete(\"ObjectSelector has been deprecated. Use ObjectSelectorSearch instead (UnityUpgradable) -> ObjectSelectorSearch\", error: true)]\n    public static class ObjectSelector\n    {\n        public const SearchEngineScope EngineScope = SearchEngineScope.ObjectSelector;\n\n        public static void RegisterEngine(IObjectSelectorEngine engine)\n        {\n            ObjectSelectorSearch.RegisterEngine(engine);\n        }\n\n        public static void UnregisterEngine(IObjectSelectorEngine engine)\n        {\n            ObjectSelectorSearch.UnregisterEngine(engine);\n        }\n    }\n\n    [Obsolete(\"ObjectSelectorHandlerAttribute has been deprecated. Use SearchContextAttribute instead.\", error: true)]\n    [AttributeUsage(AttributeTargets.Method)]\n    public class ObjectSelectorHandlerAttribute : Attribute\n    {\n        public Type attributeType { get; }\n\n        public ObjectSelectorHandlerAttribute(Type attributeType)\n        {\n            this.attributeType = attributeType;\n        }\n    }\n\n    [Obsolete(\"ObjectSelectorTargetInfo has been deprecated.\", error: true)]\n    public struct ObjectSelectorTargetInfo\n    {\n        public GlobalObjectId globalObjectId { get; }\n        public Object targetObject { get; }\n        public Type type { get; }\n\n        public ObjectSelectorTargetInfo(GlobalObjectId globalObjectId, Object targetObject = null, Type type = null)\n        {\n            this.globalObjectId = globalObjectId;\n            this.targetObject = targetObject;\n            this.type = type;\n        }\n\n        public Object LoadObject()\n        {\n            return targetObject ?? GlobalObjectId.GlobalObjectIdentifierToObjectSlow(globalObjectId);\n        }\n    }\n\n    public partial class ObjectSelectorSearchContext : ISearchContext\n    {\n        [Obsolete(\"selectorConstraint has been deprecated.\", error: true)]\n        public Func<ObjectSelectorTargetInfo, Object[], ObjectSelectorSearchContext, bool> selectorConstraint { get; set; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Search/ObjectSelectorSearch.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor.SearchService\n{\n    [AttributeUsage(AttributeTargets.Class)]\n    public class ObjectSelectorEngineAttribute : Attribute\n    {}\n\n    [Flags]\n    public enum VisibleObjects\n    {\n        None = 0,\n        Assets = 1,\n        Scene = 1 << 1,\n        All = Assets | Scene\n    }\n\n    [Flags]\n    public enum ObjectSelectorSearchEndSessionModes\n    {\n        None = 0,\n        CloseSelector = 1\n    }\n\n    public partial class ObjectSelectorSearchContext : ISearchContext\n    {\n        public Guid guid { get; } = Guid.NewGuid();\n        public SearchEngineScope engineScope { get; protected set; } = ObjectSelectorSearch.EngineScope;\n        public Object currentObject { get; set; }\n        public Object[] editedObjects { get; set; }\n        public IEnumerable<Type> requiredTypes { get; set; }\n        public IEnumerable<string> requiredTypeNames { get; set; }\n        public VisibleObjects visibleObjects { get; set; }\n        public IEnumerable<int> allowedInstanceIds { get; set; }\n        public ObjectSelectorSearchEndSessionModes endSessionModes { get; set; }\n        internal SearchFilter searchFilter { get; set; }\n    }\n\n    public interface IObjectSelectorEngine : ISelectorEngine {}\n\n    [InitializeOnLoad]\n    public static class ObjectSelectorSearch\n    {\n        static SearchApiBaseImp<ObjectSelectorEngineAttribute, IObjectSelectorEngine> s_EngineImp;\n        static SearchApiBaseImp<ObjectSelectorEngineAttribute, IObjectSelectorEngine> engineImp\n        {\n            get\n            {\n                if (s_EngineImp == null)\n                    StaticInit();\n                return s_EngineImp;\n            }\n        }\n\n        public const SearchEngineScope EngineScope = SearchEngineScope.ObjectSelector;\n\n        static ObjectSelectorSearch()\n        {\n            EditorApplication.tick += StaticInit;\n        }\n\n        private static void StaticInit()\n        {\n            EditorApplication.tick -= StaticInit;\n            s_EngineImp = s_EngineImp ?? new SearchApiBaseImp<ObjectSelectorEngineAttribute, IObjectSelectorEngine>(EngineScope, \"Object Selector\");\n        }\n\n        internal static bool SelectObject(ObjectSelectorSearchContext context, Action<Object, bool> onObjectSelectorClosed, Action<Object> onObjectSelectedUpdated)\n        {\n            var activeEngine = engineImp.activeSearchEngine;\n            try\n            {\n                return activeEngine.SelectObject(context, onObjectSelectorClosed, onObjectSelectedUpdated);\n            }\n            catch (Exception ex)\n            {\n                engineImp.HandleUserException(ex);\n                return false;\n            }\n        }\n\n        internal static void SetSearchFilter(string searchFilter, ObjectSelectorSearchContext context)\n        {\n            var activeEngine = engineImp.activeSearchEngine;\n            activeEngine.SetSearchFilter(context, searchFilter);\n        }\n\n        internal static bool HasEngineOverride()\n        {\n            return engineImp.HasEngineOverride();\n        }\n\n        internal static void BeginSession(ObjectSelectorSearchContext context)\n        {\n            engineImp.BeginSession(context);\n        }\n\n        internal static void EndSession(ObjectSelectorSearchContext context)\n        {\n            engineImp.EndSession(context);\n        }\n\n        internal static void BeginSearch(string query, ObjectSelectorSearchContext context)\n        {\n            engineImp.BeginSearch(query, context);\n        }\n\n        internal static void EndSearch(ObjectSelectorSearchContext context)\n        {\n            engineImp.EndSearch(context);\n        }\n\n        internal static IObjectSelectorEngine GetActiveSearchEngine()\n        {\n            return engineImp.GetActiveSearchEngine();\n        }\n\n        internal static void SetActiveSearchEngine(string searchEngineName)\n        {\n            engineImp.SetActiveSearchEngine(searchEngineName);\n        }\n\n        public static void RegisterEngine(IObjectSelectorEngine engine)\n        {\n            engineImp.RegisterEngine(engine);\n        }\n\n        public static void UnregisterEngine(IObjectSelectorEngine engine)\n        {\n            engineImp.UnregisterEngine(engine);\n        }\n    }\n\n    class ObjectSelectorSearchSessionHandler : SearchSessionHandler\n    {\n        public ObjectSelectorSearchSessionHandler()\n            : base(SearchEngineScope.ObjectSelector) {}\n\n        protected override void OnActiveEngineChanged(string newSearchEngineName)\n        {\n            CloseSelector();\n        }\n\n        public void CloseSelector()\n        {\n            if (context is ObjectSelectorSearchContext selectorContext)\n            {\n                // Context is set to null after EndSession, so no need to set the\n                // endSessionModes back to its original value. It is also valid that context\n                // is null when calling CloseSelector/EndSession if no session was started before.\n                selectorContext.endSessionModes |= ObjectSelectorSearchEndSessionModes.CloseSelector;\n            }\n            EndSession();\n        }\n\n        public bool SelectObject(Action<Object, bool> onObjectSelectorClosed, Action<Object> onObjectSelectedUpdated)\n        {\n            using (new SearchSessionOptionsApplicator(m_Api, m_Options))\n                return ObjectSelectorSearch.SelectObject((ObjectSelectorSearchContext)context, onObjectSelectorClosed, onObjectSelectedUpdated);\n        }\n\n        public void SetSearchFilter(string searchFilter)\n        {\n            using (new SearchSessionOptionsApplicator(m_Api, m_Options))\n                ObjectSelectorSearch.SetSearchFilter(searchFilter, (ObjectSelectorSearchContext)context);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Search/OpenSearchHelper.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing UnityEditor.ShortcutManagement;\nusing UnityEngine;\n\nnamespace UnityEditor.SearchService\n{\n    static class OpenSearchHelper\n    {\n        static class Styles\n        {\n            public static GUIContent gotoSearch = EditorGUIUtility.TrIconContent(\"SearchJump Icon\");\n        }\n\n        internal const string k_SearchMenuName = \"Edit/Search/Search All...\";\n        internal const string k_SearchAllShortcutName = $\"Main Menu/{k_SearchMenuName}\";\n        public const string k_OpenSearchInContextCommand = \"OpenQuickSearchInContext\";\n\n        static ShortcutBinding s_ShortcutBinding = ShortcutBinding.empty;\n        public static ShortcutBinding shortcutBinding\n        {\n            get\n            {\n                if (s_ShortcutBinding.Equals(ShortcutBinding.empty))\n                {\n                    UpdateBindingAndTooltip();\n                }\n\n                return s_ShortcutBinding;\n            }\n        }\n\n        static OpenSearchHelper()\n        {\n            EditorApplication.delayCall += UpdateBindingAndTooltip;\n        }\n\n        static void OnShortcutBindingChanged(ShortcutBindingChangedEventArgs obj)\n        {\n            UpdateBindingAndTooltip();\n        }\n\n        static void UpdateBindingAndTooltip()\n        {\n            ShortcutManager.instance.shortcutBindingChanged -= OnShortcutBindingChanged;\n            ShortcutManager.instance.shortcutBindingChanged += OnShortcutBindingChanged;\n            if (!IsShortcutAvailable())\n                return;\n            s_ShortcutBinding = ShortcutManager.instance.GetShortcutBinding(k_SearchAllShortcutName);\n            Styles.gotoSearch.tooltip = L10n.Tr($\"Open in Search ({s_ShortcutBinding})\");\n        }\n\n        public static void HandleSearchEvent(EditorWindow window, Event evt, string searchText)\n        {\n            if (evt.type != EventType.KeyDown)\n                return;\n\n            var keyCombination = KeyCombination.FromKeyboardInput(evt);\n            if (shortcutBinding.keyCombinationSequence.Any(shortcutCombination => keyCombination.Equals(shortcutCombination)))\n            {\n                evt.Use();\n                OpenSearchInContext(window, searchText, \"jumpShortcut\");\n            }\n        }\n\n        public static void OpenSearchInContext(EditorWindow window, string searchText, string openContext)\n        {\n            if (!CommandService.Exists(k_OpenSearchInContextCommand))\n                return;\n\n            CommandService.Execute(k_OpenSearchInContextCommand, CommandHint.Any, searchText, openContext);\n            window?.Repaint();\n        }\n\n        public static void DrawOpenButton(EditorWindow window, string searchText)\n        {\n            Rect r = GUILayoutUtility.GetRect(Styles.gotoSearch, EditorStyles.toolbarSearchFieldJumpButton, GUILayout.MaxHeight(EditorGUI.kSingleLineHeight));\n            if (EditorGUI.Button(r, Styles.gotoSearch, EditorStyles.toolbarSearchFieldJumpButton))\n            {\n                OpenSearchInContext(window, searchText, \"jumpButton\");\n            }\n        }\n\n        public static bool IsShortcutAvailable()\n        {\n            var shortcutIds = ShortcutManager.instance.GetAvailableShortcutIds();\n            return shortcutIds.Any(path => path == k_SearchAllShortcutName);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Search/Project.Deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.SearchService\n{\n    [Obsolete(\"Project has been deprecated. Use ProjectSearch instead (UnityUpgradable) -> ProjectSearch\", error: true)]\n    public static class Project\n    {\n        public const SearchEngineScope EngineScope = SearchEngineScope.Project;\n\n        public static void RegisterEngine(IProjectSearchEngine engine)\n        {\n            ProjectSearch.RegisterEngine(engine);\n        }\n\n        public static void UnregisterEngine(IProjectSearchEngine engine)\n        {\n            ProjectSearch.UnregisterEngine(engine);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Search/ProjectSearch.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace UnityEditor.SearchService\n{\n    [AttributeUsage(AttributeTargets.Class)]\n    public class ProjectSearchEngineAttribute : Attribute\n    {}\n\n    public class ProjectSearchContext : ISearchContext\n    {\n        public Guid guid { get; } = Guid.NewGuid();\n        public SearchEngineScope engineScope { get; protected set; } = ProjectSearch.EngineScope;\n        public IEnumerable<Type> requiredTypes { get; set; }\n        public IEnumerable<string> requiredTypeNames { get; set; }\n        internal SearchFilter searchFilter { get; set; }\n    }\n\n    public interface IProjectSearchEngine : ISearchEngine<string> {}\n\n    [InitializeOnLoad]\n    public static class ProjectSearch\n    {\n        static SearchApiBaseImp<ProjectSearchEngineAttribute, IProjectSearchEngine> s_EngineImp;\n        static SearchApiBaseImp<ProjectSearchEngineAttribute, IProjectSearchEngine> engineImp\n        {\n            get\n            {\n                if (s_EngineImp == null)\n                    StaticInit();\n                return s_EngineImp;\n            }\n        }\n\n        public const SearchEngineScope EngineScope = SearchEngineScope.Project;\n\n        static ProjectSearch()\n        {\n            EditorApplication.tick += StaticInit;\n        }\n\n        private static void StaticInit()\n        {\n            EditorApplication.tick -= StaticInit;\n            s_EngineImp = s_EngineImp ?? new SearchApiBaseImp<ProjectSearchEngineAttribute, IProjectSearchEngine>(EngineScope, \"Project\");\n        }\n\n        internal static IEnumerable<string> Search(string query, ProjectSearchContext context, Action<IEnumerable<string>> asyncItemsReceived)\n        {\n            var activeEngine = engineImp.activeSearchEngine;\n            try\n            {\n                return activeEngine.Search(context, query, asyncItemsReceived);\n            }\n            catch (Exception ex)\n            {\n                engineImp.HandleUserException(ex);\n                return null;\n            }\n        }\n\n        internal static bool HasEngineOverride()\n        {\n            return engineImp.HasEngineOverride();\n        }\n\n        internal static void BeginSession(ProjectSearchContext context)\n        {\n            engineImp.BeginSession(context);\n        }\n\n        internal static void EndSession(ProjectSearchContext context)\n        {\n            engineImp.EndSession(context);\n        }\n\n        internal static void BeginSearch(string query, ProjectSearchContext context)\n        {\n            engineImp.BeginSearch(query, context);\n        }\n\n        internal static void EndSearch(ProjectSearchContext context)\n        {\n            engineImp.EndSearch(context);\n        }\n\n        internal static IProjectSearchEngine GetActiveSearchEngine()\n        {\n            return engineImp.GetActiveSearchEngine();\n        }\n\n        internal static void SetActiveSearchEngine(string searchEngineName)\n        {\n            engineImp.SetActiveSearchEngine(searchEngineName);\n        }\n\n        public static void RegisterEngine(IProjectSearchEngine engine)\n        {\n            engineImp.RegisterEngine(engine);\n        }\n\n        public static void UnregisterEngine(IProjectSearchEngine engine)\n        {\n            engineImp.UnregisterEngine(engine);\n        }\n    }\n\n    class ProjectSearchSessionHandler : SearchSessionHandler\n    {\n        public ProjectSearchSessionHandler()\n            : base(SearchEngineScope.Project) {}\n\n        public IEnumerable<string> Search(string query, Action<IEnumerable<string>> asyncItemsReceived)\n        {\n            using (new SearchSessionOptionsApplicator(m_Api, m_Options))\n                return ProjectSearch.Search(query, (ProjectSearchContext)context, asyncItemsReceived);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Search/Scene.Deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor.SearchService\n{\n    [Obsolete(\"Scene has been deprecated. Use SceneSearch instead (UnityUpgradable) -> SceneSearch\", error: true)]\n    public static class Scene\n    {\n        public const SearchEngineScope EngineScope = SearchEngineScope.Scene;\n\n        public static void RegisterEngine(ISceneSearchEngine engine)\n        {\n            SceneSearch.RegisterEngine(engine);\n        }\n\n        public static void UnregisterEngine(ISceneSearchEngine engine)\n        {\n            SceneSearch.UnregisterEngine(engine);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Search/SceneSearch.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace UnityEditor.SearchService\n{\n    [AttributeUsage(AttributeTargets.Class)]\n    public class SceneSearchEngineAttribute : Attribute\n    {}\n\n    public class SceneSearchContext : ISearchContext\n    {\n        public Guid guid { get; } = Guid.NewGuid();\n        public SearchEngineScope engineScope { get; protected set; } = SceneSearch.EngineScope;\n        public IEnumerable<Type> requiredTypes { get; set; }\n        public IEnumerable<string> requiredTypeNames { get; set; }\n        public HierarchyProperty rootProperty { get; set; }\n        internal SearchFilter searchFilter { get; set; }\n    }\n\n    public interface ISceneSearchEngine : IFilterEngine<HierarchyProperty>\n    {}\n\n    [InitializeOnLoad]\n    public static class SceneSearch\n    {\n        static SearchApiBaseImp<SceneSearchEngineAttribute, ISceneSearchEngine> s_EngineImp;\n        static SearchApiBaseImp<SceneSearchEngineAttribute, ISceneSearchEngine> engineImp\n        {\n            get\n            {\n                if (s_EngineImp == null)\n                    StaticInit();\n                return s_EngineImp;\n            }\n        }\n\n        public const SearchEngineScope EngineScope = SearchEngineScope.Scene;\n\n        static SceneSearch()\n        {\n            EditorApplication.tick += StaticInit;\n        }\n\n        private static void StaticInit()\n        {\n            EditorApplication.tick -= StaticInit;\n            s_EngineImp = s_EngineImp ?? new SearchApiBaseImp<SceneSearchEngineAttribute, ISceneSearchEngine>(EngineScope, \"Scene\");\n        }\n\n        internal static bool Filter(string query, HierarchyProperty objectToFilter, SceneSearchContext context)\n        {\n            var activeEngine = engineImp.activeSearchEngine;\n            try\n            {\n                return activeEngine.Filter(context, query, objectToFilter);\n            }\n            catch (Exception ex)\n            {\n                engineImp.HandleUserException(ex);\n                return false;\n            }\n        }\n\n        internal static bool HasEngineOverride()\n        {\n            return engineImp.HasEngineOverride();\n        }\n\n        internal static void BeginSession(SceneSearchContext context)\n        {\n            engineImp.BeginSession(context);\n        }\n\n        internal static void EndSession(SceneSearchContext context)\n        {\n            engineImp.EndSession(context);\n        }\n\n        internal static void BeginSearch(string query, SceneSearchContext context)\n        {\n            engineImp.BeginSearch(query, context);\n        }\n\n        internal static void EndSearch(SceneSearchContext context)\n        {\n            engineImp.EndSearch(context);\n        }\n\n        internal static ISceneSearchEngine GetActiveSearchEngine()\n        {\n            return engineImp.GetActiveSearchEngine();\n        }\n\n        internal static void SetActiveSearchEngine(string searchEngineName)\n        {\n            engineImp.SetActiveSearchEngine(searchEngineName);\n        }\n\n        public static void RegisterEngine(ISceneSearchEngine engine)\n        {\n            engineImp.RegisterEngine(engine);\n        }\n\n        public static void UnregisterEngine(ISceneSearchEngine engine)\n        {\n            engineImp.UnregisterEngine(engine);\n        }\n    }\n\n    class SceneSearchSessionHandler : SearchSessionHandler\n    {\n        public SceneSearchSessionHandler()\n            : base(SearchEngineScope.Scene) {}\n\n        public bool Filter(string query, HierarchyProperty objectToFilter)\n        {\n            using (new SearchSessionOptionsApplicator(m_Api, m_Options))\n                return SceneSearch.Filter(query, objectToFilter, (SceneSearchContext)context);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Search/SearchService.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.Profiling;\nusing UnityEngine;\nusing Attribute = System.Attribute;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor.SearchService\n{\n    public enum SearchEngineScope\n    {\n        Scene,\n        Project,\n        ObjectSelector\n    }\n\n    public interface ISearchContext\n    {\n        Guid guid { get; }\n        SearchEngineScope engineScope { get; }\n        IEnumerable<Type> requiredTypes { get; }\n        IEnumerable<string> requiredTypeNames { get; }\n    }\n\n    public interface ISearchEngineBase\n    {\n        string name { get; }\n\n        void BeginSession(ISearchContext context);\n        void EndSession(ISearchContext context);\n\n        void BeginSearch(ISearchContext context, string query);\n        void EndSearch(ISearchContext context);\n    }\n\n    public interface ISearchEngine<T> : ISearchEngineBase\n    {\n        IEnumerable<T> Search(ISearchContext context, string query, Action<IEnumerable<T>> asyncItemsReceived);\n    }\n\n    public interface IFilterEngine<in T> : ISearchEngineBase\n    {\n        bool Filter(ISearchContext context, string query, T objectToFilter);\n    }\n\n    public interface ISelectorEngine : ISearchEngineBase\n    {\n        bool SelectObject(ISearchContext context, Action<Object, bool> onObjectSelectorClosed, Action<Object> onObjectSelectedUpdated);\n        void SetSearchFilter(ISearchContext context, string searchFilter);\n    }\n\n    struct SearchSessionOptions\n    {\n        public bool legacyOnly;\n        public static readonly SearchSessionOptions Default = new SearchSessionOptions();\n    }\n\n    struct SearchSessionOptionsApplicator : IDisposable\n    {\n        bool m_Disposed;\n\n        ISearchApi m_Api;\n        SearchSessionOptions m_Options;\n\n        string m_CurrentActiveEngine;\n\n        public SearchSessionOptionsApplicator(ISearchApi api, SearchSessionOptions options)\n        {\n            m_Api = api;\n            m_Options = options;\n            m_Disposed = false;\n            m_CurrentActiveEngine = m_Api?.activeSearchEngineName;\n\n            if (m_Options.legacyOnly)\n                m_Api?.SetActiveSearchEngine(LegacySearchEngineBase.k_Name, false);\n        }\n\n        public void Dispose()\n        {\n            if (m_Disposed)\n                return;\n\n            if (m_Options.legacyOnly)\n                m_Api?.SetActiveSearchEngine(m_CurrentActiveEngine, false);\n\n            m_Disposed = true;\n        }\n    }\n\n    class SearchSessionHandler\n    {\n        SearchEngineScope m_EngineScope;\n        bool m_WasSearching;\n        protected ISearchApi m_Api;\n        protected SearchSessionOptions m_Options;\n\n        public ISearchContext context { get; private set; }\n\n        public SearchSessionHandler(SearchEngineScope engineScope)\n        {\n            m_EngineScope = engineScope;\n            Init();\n        }\n\n        void Init(bool pullEngines = false)\n        {\n            if (pullEngines)\n                PullEngines();\n            var index = SearchService.searchApis.FindIndex(api => api.engineScope == m_EngineScope);\n            if (index >= 0)\n            {\n                m_Api = SearchService.searchApis[index];\n                m_Api.activeEngineChanged += OnActiveEngineChanged;\n            }\n        }\n\n        void PullEngines()\n        {\n            // Calling HasEngineOverride will make sure the engine apis are registered.\n            switch (m_EngineScope)\n            {\n                case SearchEngineScope.Project: ProjectSearch.HasEngineOverride();\n                    break;\n                case SearchEngineScope.Scene: SceneSearch.HasEngineOverride();\n                    break;\n                case SearchEngineScope.ObjectSelector: ObjectSelectorSearch.HasEngineOverride();\n                    break;\n            }\n        }\n\n        protected virtual void OnActiveEngineChanged(string newSearchEngineName)\n        {\n            EndSession();\n        }\n\n        public void BeginSession(Func<ISearchContext> searchContextCreator, SearchSessionOptions options)\n        {\n            if (m_WasSearching)\n                return;\n            // Do a lazy initialize if the apis were not available during creation\n            if (m_Api == null)\n            {\n                Init(true);\n                if (m_Api == null)\n                    throw new NullReferenceException(\"SearchService Apis were not initialized properly.\");\n            }\n            m_Options = options;\n            context = searchContextCreator();\n            m_WasSearching = true;\n            using (new SearchSessionOptionsApplicator(m_Api, options))\n                m_Api?.BeginSession(context);\n        }\n\n        public void BeginSession(Func<ISearchContext> searchContextCreator)\n        {\n            BeginSession(searchContextCreator, SearchSessionOptions.Default);\n        }\n\n        public void EndSession()\n        {\n            if (!m_WasSearching)\n                return;\n            m_WasSearching = false;\n            using (new SearchSessionOptionsApplicator(m_Api, m_Options))\n                m_Api?.EndSession(context);\n            context = null;\n            m_Options = SearchSessionOptions.Default;\n        }\n\n        public void BeginSearch(string query)\n        {\n            using (new SearchSessionOptionsApplicator(m_Api, m_Options))\n                m_Api?.BeginSearch(query, context);\n        }\n\n        public void EndSearch()\n        {\n            using (new SearchSessionOptionsApplicator(m_Api, m_Options))\n                m_Api?.EndSearch(context);\n        }\n    }\n\n    interface ISearchApi\n    {\n        SearchEngineScope engineScope { get; }\n        string displayName { get; }\n        IEnumerable<ISearchEngineBase> engines { get; }\n        string activeSearchEngineName { get; }\n        ISearchEngineBase GetActiveSearchEngine();\n        void SetActiveSearchEngine(string searchEngineName, bool notify = true);\n        void RegisterEngine(ISearchEngineBase engine);\n        void UnregisterEngine(ISearchEngineBase engine);\n        bool HasEngineOverride();\n        void BeginSession(ISearchContext context);\n        void EndSession(ISearchContext context);\n        void BeginSearch(string query, ISearchContext context);\n        void EndSearch(ISearchContext context);\n        ISearchEngineBase GetDefaultEngine();\n        event Action<string> activeEngineChanged;\n    }\n\n    [InitializeOnLoad]\n    static class SearchService\n    {\n        public const string keyPrefix = \"searchservice\";\n        public const string activeSearchEnginesPrefKey = keyPrefix + \".activeengines.\";\n        public static List<ISearchApi> searchApis = new List<ISearchApi>();\n\n        public enum SyncSearchEvent\n        {\n            StartSession,\n            SyncSearch,\n            EndSession\n        }\n\n        public static event Action<SyncSearchEvent, string, string> syncSearchChanged;\n\n        public static void NotifySyncSearchChanged(SyncSearchEvent evt, string syncViewId, string searchQuery)\n        {\n            syncSearchChanged?.Invoke(evt, syncViewId, searchQuery);\n        }\n\n        public static void HandleSearchEvent(EditorWindow window, Event evt, string searchText)\n        {\n            OpenSearchHelper.HandleSearchEvent(window, evt, searchText);\n        }\n\n        public static void DrawOpenSearchButton(EditorWindow window, string searchText)\n        {\n            OpenSearchHelper.DrawOpenButton(window, searchText);\n        }\n    }\n\n    class SearchApiBaseImp<TAttribute, TEngine> : ISearchApi\n        where TAttribute : Attribute\n        where TEngine : class, ISearchEngineBase\n    {\n        int m_SearchPerformanceTrackerHandle;\n\n        public SearchEngineScope engineScope { get; }\n        public string displayName { get; }\n\n        List<TEngine> engines { get; } = new List<TEngine>();\n\n        IEnumerable<ISearchEngineBase> ISearchApi.engines => engines.Cast<ISearchEngineBase>();\n\n        public string activeSearchEngineName { get; private set; }\n\n        TEngine m_ActiveSearchEngine;\n        public TEngine activeSearchEngine\n        {\n            get\n            {\n                if (m_ActiveSearchEngine == null)\n                    m_ActiveSearchEngine = GetActiveSearchEngine();\n                return m_ActiveSearchEngine;\n            }\n            private set => m_ActiveSearchEngine = value;\n        }\n\n        public event Action<string> activeEngineChanged;\n\n        public SearchApiBaseImp(SearchEngineScope engineScope, string displayName)\n        {\n            this.engineScope = engineScope;\n            this.displayName = displayName ?? throw new ArgumentNullException(nameof(displayName));\n            RegisterAllEngines();\n            LoadActiveSearchEngine();\n            SearchService.searchApis.Add(this);\n        }\n\n        public TEngine GetActiveSearchEngine()\n        {\n            if (engines.Count == 0)\n                return null;\n            var actualActiveEngineName = string.IsNullOrEmpty(activeSearchEngineName) ? GetDefaultEngine().name : activeSearchEngineName;\n            var activeEngineIndex = engines.FindIndex(engine => engine.name == actualActiveEngineName);\n            if (activeEngineIndex < 0)\n            {\n                var defaultEngine = GetDefaultEngine() ?? engines.First();\n                SetActiveSearchEngine(defaultEngine.name);\n                return defaultEngine;\n            }\n            return engines[activeEngineIndex];\n        }\n\n        ISearchEngineBase ISearchApi.GetActiveSearchEngine()\n        {\n            return GetActiveSearchEngine();\n        }\n\n        public TEngine GetDefaultEngine()\n        {\n            if (engines.Count == 0)\n                return null;\n\n            var index = engines.FindIndex(engine => engine is LegacySearchEngineBase);\n            if (index < 0)\n                return null;\n            return engines[index];\n        }\n\n        ISearchEngineBase ISearchApi.GetDefaultEngine()\n        {\n            return GetDefaultEngine();\n        }\n\n        public void SetActiveSearchEngine(string searchEngineName, bool notify = true)\n        {\n            if (string.Equals(activeSearchEngineName, searchEngineName, StringComparison.Ordinal))\n                return;\n\n            if (notify)\n                activeEngineChanged?.Invoke(searchEngineName);\n            activeSearchEngineName = searchEngineName;\n            EditorPrefs.SetString(SearchService.activeSearchEnginesPrefKey + engineScope, searchEngineName);\n            activeSearchEngine = null;\n        }\n\n        void ISearchApi.SetActiveSearchEngine(string searchEngineName, bool notify)\n        {\n            SetActiveSearchEngine(searchEngineName, notify);\n        }\n\n        public bool HasEngineOverride()\n        {\n            return !(activeSearchEngine is LegacySearchEngineBase);\n        }\n\n        public void BeginSession(ISearchContext context)\n        {\n            try\n            {\n                activeSearchEngine.BeginSession(context);\n            }\n            catch (Exception ex)\n            {\n                HandleUserException(ex);\n            }\n        }\n\n        public void EndSession(ISearchContext context)\n        {\n            try\n            {\n                activeSearchEngine.EndSession(context);\n            }\n            catch (Exception ex)\n            {\n                HandleUserException(ex);\n            }\n        }\n\n        public void BeginSearch(string query, ISearchContext context)\n        {\n            m_SearchPerformanceTrackerHandle = EditorPerformanceTracker.StartTracker($\"Search Engine {activeSearchEngineName} ({displayName})\");\n            try\n            {\n                activeSearchEngine.BeginSearch(context, query);\n            }\n            catch (Exception ex)\n            {\n                HandleUserException(ex);\n            }\n        }\n\n        public void EndSearch(ISearchContext context)\n        {\n            try\n            {\n                activeSearchEngine.EndSearch(context);\n            }\n            catch (Exception ex)\n            {\n                HandleUserException(ex);\n            }\n            if (EditorPerformanceTracker.IsTrackerActive(m_SearchPerformanceTrackerHandle))\n                EditorPerformanceTracker.StopTracker(m_SearchPerformanceTrackerHandle);\n        }\n\n        void LoadActiveSearchEngine()\n        {\n            activeSearchEngineName = EditorPrefs.GetString(SearchService.activeSearchEnginesPrefKey + engineScope, GetDefaultEngine().name);\n            m_ActiveSearchEngine = GetActiveSearchEngine();\n        }\n\n        public void RegisterEngine(TEngine engine)\n        {\n            if (engine != null && engines.FindIndex(e => e.name == engine.name) < 0)\n                engines.Add(engine);\n        }\n\n        public void UnregisterEngine(TEngine engine)\n        {\n            if (engine == null)\n                return;\n            var index = engines.FindIndex(e => e.name == engine.name);\n            if (index >= 0)\n                engines.RemoveAt(index);\n        }\n\n        void ISearchApi.RegisterEngine(ISearchEngineBase engine)\n        {\n            RegisterEngine(engine as TEngine);\n        }\n\n        void ISearchApi.UnregisterEngine(ISearchEngineBase engine)\n        {\n            UnregisterEngine(engine as TEngine);\n        }\n\n        void RegisterAllEngines()\n        {\n            var types = TypeCache.GetTypesWithAttribute<TAttribute>();\n            var instantiatedEngines = types.Select(type => Activator.CreateInstance(type));\n            foreach (var instantiatedEngine in instantiatedEngines)\n            {\n                if (instantiatedEngine is TEngine typedEngine)\n                {\n                    RegisterEngine(typedEngine);\n                }\n                else\n                {\n                    Debug.LogFormat(LogType.Warning, LogOption.NoStacktrace, null,\n                        $\"Trying to register a search engine with the attribute {typeof(TAttribute)} but it does not implement the interface {typeof(TEngine)}.\");\n                }\n            }\n        }\n\n        public void HandleUserException(Exception ex)\n        {\n            if (activeSearchEngine is LegacySearchEngineBase)\n                throw ex;\n\n            Debug.LogFormat(LogType.Error, LogOption.None, null, $\"Exception caught with search engine ({displayName}){activeSearchEngine.name}:\\n{ex}\");\n            Debug.LogFormat(LogType.Error, LogOption.None, null, $\"Setting {GetDefaultEngine().name} engine as active.\");\n\n            SetActiveSearchEngine(GetDefaultEngine().name);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SearchUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEditor.AssetImporters;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    internal class SearchUtility\n    {\n        private static void RemoveUnwantedWhitespaces(ref string searchString)\n        {\n            // Some users add a whitespace after the colon (remove it)\n            searchString = searchString.Replace(\": \", \":\");\n        }\n\n        // Supports the following syntax:\n        // 't:type' syntax (e.g 't:Texture2D' will show Texture2D objects)\n        // 'l:assetlabel' syntax (e.g 'l:architecture' will show assets with AssetLabel 'architecture')\n        // 'ref[:id]:path' syntax (e.g 'ref:1234' will show objects that references the object with instanceID 1234)\n        // 'v:versionState' syntax (e.g 'v:modified' will show objects that are modified locally)\n        // 's:softLockState' syntax (e.g 's:inprogress' will show objects that are modified by anyone (except you))\n        // 'a:area' syntax (e.g 'a:all' will s search in all assets, 'a:assets' will s search in assets folder only and 'a:packages' will s search in packages folder only)\n        // 'glob:path' syntax (e.g 'glob:Assets/**/*.{png|PNG}' will show objects in any subfolder with name ending by .png or .PNG)\n        internal static bool ParseSearchString(string searchText, SearchFilter filter)\n        {\n            if (string.IsNullOrEmpty(searchText))\n                return false;\n\n            filter.ClearSearch();\n            filter.originalText = searchText;\n\n            string searchString = string.Copy(searchText);\n            RemoveUnwantedWhitespaces(ref searchString);\n\n            bool parsed = false;\n\n            // Split filter into separate words with space or tab as separators\n            const string kFilterSeparator = \" \\t,*?\";\n\n            // Skip any separators preceding the filter\n            int pos = FindFirstPositionNotOf(searchString, kFilterSeparator);\n            if (pos == -1)\n                pos = 0;\n            while (pos < searchString.Length)\n            {\n                int endpos = searchString.IndexOfAny(kFilterSeparator.ToCharArray(), pos);\n\n                if (endpos == -1)\n                    endpos = searchString.Length;\n\n                // Check if we have quotes (may be used for pathnames) inbetween start and a /filter-separator/\n                int q1 = searchString.IndexOf('\"', pos);\n                int q2 = -1;\n                if (q1 != -1 && q1 < endpos)\n                {\n                    q2 = searchString.IndexOf('\"', q1 + 1);\n                    if (q2 != -1 && q2 > endpos - 1)\n                    {\n                        // Advance to a /filter-separator/ after the quote\n                        endpos = searchString.IndexOfAny(kFilterSeparator.ToCharArray(), q2);\n                        if (endpos == -1)\n                            endpos = searchString.Length;\n                    }\n                }\n\n                if (endpos > pos)\n                {\n                    string token = searchString.Substring(pos, endpos - pos);\n\n                    if (q1 != -1)\n                        q1 -= pos;\n\n                    if (q2 != -1)\n                        q2 -= pos;\n\n                    if (CheckForKeyWords(token, filter, q1, q2))\n                        parsed = true;\n                    else\n                        filter.nameFilter += (string.IsNullOrEmpty(filter.nameFilter) ? \"\" : \" \") + token; // force single space between name tokens\n                }\n                pos = endpos + 1;\n            }\n            return parsed;\n        }\n\n        private static bool HasFilter(string searchString, string filter)\n        {\n            // All filters are already tokenized. SO matching with startsWith instead of indexOf will help with comparison.\n            return searchString.StartsWith($\"{filter}:\") || searchString.StartsWith($\"{filter}=\");\n        }\n\n        internal static bool CheckForKeyWords(string searchString, SearchFilter filter, int quote1, int quote2)\n        {\n            bool parsed = false;\n\n            // Support: 't:type' syntax (e.g 't:Texture2D' will show Texture2D objects)\n            if (HasFilter(searchString, \"t\"))\n            {\n                string type = searchString.Substring(2);\n                List<string> tmp = new List<string>(filter.classNames);\n                tmp.Add(type);\n                filter.classNames = tmp.ToArray();\n                parsed = true;\n            }\n\n            // Support: 'l:assetlabel' syntax (e.g 'l:architecture' will show assets with AssetLabel 'architecture')\n            if (HasFilter(searchString, \"l\"))\n            {\n                string label = searchString.Substring(2);\n                List<string> tmp = new List<string>(filter.assetLabels);\n                tmp.Add(label);\n                filter.assetLabels = tmp.ToArray();\n                parsed = true;\n            }\n\n            // Support: 'a:area' syntax\n            if (HasFilter(searchString, \"a\"))\n            {\n                string areaString = searchString.Substring(2);\n                if (string.Compare(areaString, \"all\", true) == 0)\n                {\n                    filter.searchArea = SearchFilter.SearchArea.AllAssets;\n                    parsed = true;\n                }\n                else if (string.Compare(areaString, \"assets\", true) == 0)\n                {\n                    filter.searchArea = SearchFilter.SearchArea.InAssetsOnly;\n                    parsed = true;\n                }\n                else if (string.Compare(areaString, \"packages\", true) == 0)\n                {\n                    filter.searchArea = SearchFilter.SearchArea.InPackagesOnly;\n                    parsed = true;\n                }\n            }\n\n            // Support: 'b:assetBundleName' syntax (e.g 'b:materialAssetBundle' will show assets within assetBundle 'materialAssetBundle')\n            if (HasFilter(searchString, \"b\"))\n            {\n                string assetBundleName = searchString.Substring(2);\n                List<string> tmp = new List<string>(filter.assetBundleNames);\n                tmp.Add(assetBundleName);\n                filter.assetBundleNames = tmp.ToArray();\n                parsed = true;\n            }\n\n            // Support: 'ref[:id]:path' syntax (e.g 'ref:1234' will show objects that references the object with instanceID 1234)\n            if (HasFilter(searchString, \"ref\"))\n            {\n                int instanceID = 0;\n                int firstColon = 3;\n                int secondColon = searchString.IndexOf(':', firstColon + 1);\n                if (secondColon >= 0)\n                {\n                    // Instead of resolving a path passed-in pathname to an instance-id, use a supplied one.\n                    // The pathname is effectively just a UI hint of whose references we're filtering out.\n                    string refString = searchString.Substring(firstColon + 1, secondColon - firstColon - 1);\n                    int id;\n                    if (System.Int32.TryParse(refString, out id))\n                        instanceID = id;\n                    //else\n                    //  Debug.Log (\"Not valid refString to case to Integer \" + refString); // outcomment for debugging\n                }\n                else\n                {\n                    string assetPath;\n                    if (quote1 >= 0 && quote2 >= 0)\n                    {\n                        int startIndex = quote1 + 1;\n                        int count = quote2 - quote1 - 1;\n                        if (count < 0)\n                            count = searchString.Length - startIndex;\n\n                        // Strip filepath from quotes, don't prefix with Assets/, we need to support Packages/ (https://fogbugz.unity3d.com/f/cases/1161019/)\n                        assetPath = searchString.Substring(startIndex, count);\n                    }\n                    else\n                        // Otherwise use string from colon to end, don't prefix with Assets/, we need to support Packages/ (https://fogbugz.unity3d.com/f/cases/1161019/)\n                        assetPath = searchString.Substring(firstColon + 1);\n\n                    Object obj = AssetDatabase.LoadMainAssetAtPath(assetPath);\n                    if (obj == null)\n                        // Backward compatibility, in case Assets/ was strip from path\n                        obj = AssetDatabase.LoadMainAssetAtPath(\"Assets/\" + assetPath);\n\n                    if (obj != null)\n                        instanceID = obj.GetInstanceID();\n                    //else\n                    //  Debug.Log (\"Not valid assetPath \" + assetPath); // outcomment for debugging\n                }\n\n                filter.referencingInstanceIDs = new[] { instanceID };\n                parsed = true;\n            }\n\n            // Support: 'glob:path' syntax (e.g 'glob:Assets/**/*.{png|PNG}' will show objects in any subfolder with name ending by .png or .PNG)\n            if (HasFilter(searchString, \"glob\"))\n            {\n                string globValue = searchString.Substring(5);\n                if (quote1 >= 0 && quote2 >= 0)\n                {\n                    int startIndex = quote1 + 1;\n                    int count = quote2 - quote1 - 1;\n                    if (count < 0)\n                        count = searchString.Length - startIndex;\n                    globValue = searchString.Substring(startIndex, count);\n                }\n\n                var globs = new List<string>(filter.globs);\n                globs.Add(globValue);\n                filter.globs = globs.ToArray();\n                parsed = true;\n            }\n\n            if (HasFilter(searchString, ImportLog.Filters.SearchToken))\n            {\n                var label = searchString.Substring(ImportLog.Filters.SearchToken.Length + 1);\n                if (label == ImportLog.Filters.AllIssuesStr)\n                {\n                    filter.importLogFlags = ImportLogFlags.Error | ImportLogFlags.Warning;\n                    parsed = true;\n                }\n                else if (label == ImportLog.Filters.ErrorsStr)\n                {\n                    filter.importLogFlags = ImportLogFlags.Error;\n                    parsed = true;\n                }\n                else if (label == ImportLog.Filters.WarningsStr)\n                {\n                    filter.importLogFlags = ImportLogFlags.Warning;\n                    parsed = true;\n                }\n            }\n\n            return parsed;\n        }\n\n        private static int FindFirstPositionNotOf(string source, string chars)\n        {\n            if (source == null) return -1;\n            if (chars == null) return 0;\n            if (source.Length == 0) return -1;\n            if (chars.Length == 0) return 0;\n\n            for (int i = 0; i < source.Length; i++)\n            {\n                if (chars.IndexOf(source[i]) == -1)\n                    return i;\n            }\n            return -1;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Selection/ActiveEditorTracker.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityObject = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    // This is a strain for the garbage collector (Small memory for GC, big overhead for engine)\n    // Might want to add a manual dispose\n    [NativeHeader(\"Editor/Src/Selection/ActiveEditorTracker.bindings.h\")]\n    [Serializable]\n    [RequiredByNativeCode]\n    public sealed class ActiveEditorTracker\n    {\n        #pragma warning disable 649\n        MonoReloadableIntPtrClear m_Property;\n        #pragma warning restore\n\n        internal static event Action editorTrackerRebuilt;\n\n        public ActiveEditorTracker()\n        {\n            Internal_Create(this);\n        }\n\n        [FreeFunction(IsThreadSafe = true)]\n        static extern void Internal_Create(ActiveEditorTracker self);\n\n        public override bool Equals(object o)\n        {\n            var other = o as ActiveEditorTracker;\n            if (ReferenceEquals(other, null))\n                return false;\n            return m_Property.m_IntPtr == other.m_Property.m_IntPtr;\n        }\n\n        public override int GetHashCode()\n        {\n            return m_Property.m_IntPtr.GetHashCode();\n        }\n\n        [FreeFunction(IsThreadSafe = true)]\n        static extern void Internal_Dispose(ActiveEditorTracker self);\n        ~ActiveEditorTracker() { Internal_Dispose(this); }\n\n        [FreeFunction]\n        static extern void Internal_Destroy(ActiveEditorTracker self);\n        public void Destroy() { Internal_Destroy(this); }\n\n        [FreeFunction]\n        static extern Array Internal_GetActiveEditors(ActiveEditorTracker self);\n        public Editor[] activeEditors { get { return (Editor[])Internal_GetActiveEditors(this); } }\n\n        [FreeFunction]\n        static extern Editor[] Internal_GetActiveEditorsNonAllocInternal(ActiveEditorTracker self, [Unmarshalled] Editor[] editors);\n        internal static void Internal_GetActiveEditorsNonAlloc(ActiveEditorTracker self, ref Editor[] editors)\n        {\n            editors = Internal_GetActiveEditorsNonAllocInternal(self, editors);\n        }\n\n        // List<T> version\n        internal void GetObjectsLockedByThisTracker(List<UnityObject> lockedObjects)\n        {\n            GetObjectsLockedByThisTrackerInternal(lockedObjects);\n        }\n\n        [FreeFunction]\n        static extern void Internal_GetObjectsLockedByThisTrackerInternal(ActiveEditorTracker self, [NotNull] object lockedObjects);\n        internal void GetObjectsLockedByThisTrackerInternal(object lockedObjects)\n        {\n            Internal_GetObjectsLockedByThisTrackerInternal(this, lockedObjects);\n        }\n\n        // List<T> version\n        internal void SetObjectsLockedByThisTracker(List<UnityObject> toBeLocked)\n        {\n            if (toBeLocked == null)\n                throw new ArgumentNullException(\"The list 'toBeLocked' cannot be null\");\n            SetObjectsLockedByThisTrackerInternal(toBeLocked);\n        }\n\n        [FreeFunction]\n        static extern void Internal_SetObjectsLockedByThisTrackerInternal(ActiveEditorTracker self, object toBeLocked);\n        internal void SetObjectsLockedByThisTrackerInternal(object toBeLocked)\n        {\n            Internal_SetObjectsLockedByThisTrackerInternal(this, toBeLocked);\n        }\n\n        [FreeFunction]\n        static extern int Internal_GetVisible(ActiveEditorTracker self, int index);\n        public int GetVisible(int index) { return Internal_GetVisible(this, index); }\n\n        [FreeFunction]\n        static extern void Internal_SetVisible(ActiveEditorTracker self, int index, int visible);\n        public void SetVisible(int index, int visible) { Internal_SetVisible(this, index, visible); }\n\n        [FreeFunction]\n        static extern bool Internal_GetIsDirty(ActiveEditorTracker self);\n        public bool isDirty { get { return Internal_GetIsDirty(this); } }\n\n        [FreeFunction]\n        static extern void Internal_ClearDirty(ActiveEditorTracker self);\n        public void ClearDirty() { Internal_ClearDirty(this); }\n\n        [FreeFunction]\n        static extern bool Internal_GetIsLocked(ActiveEditorTracker self);\n        [FreeFunction]\n        static extern void Internal_SetIsLocked(ActiveEditorTracker self, bool value);\n        public bool isLocked\n        {\n            get { return Internal_GetIsLocked(this); }\n            set { Internal_SetIsLocked(this, value); }\n        }\n\n        [FreeFunction]\n        static extern bool Internal_HasUnsavedChanges(ActiveEditorTracker activeEditorTracker);\n        public bool hasUnsavedChanges => Internal_HasUnsavedChanges(this);\n\n        [FreeFunction]\n        static extern void Internal_UnsavedChangesStateChanged(ActiveEditorTracker self, int editorInstance, bool value);\n        internal void UnsavedChangesStateChanged(Editor editor, bool value)\n        {\n            Internal_UnsavedChangesStateChanged(this, editor.GetInstanceID(), value);\n        }\n\n        [FreeFunction]\n        static extern bool Internal_GetDelayFlushDirtyRebuild();\n\n        [FreeFunction]\n        static extern void Internal_SetDelayFlushDirtyRebuild(bool value);\n\n        // Enable or disable the ActiveEditorTracker rebuilding from ISceneInspector.DidFlushDirty calls.\n        internal static bool delayFlushDirtyRebuild\n        {\n            get { return Internal_GetDelayFlushDirtyRebuild(); }\n            set { Internal_SetDelayFlushDirtyRebuild(value); }\n        }\n\n        [FreeFunction]\n        static extern InspectorMode Internal_GetInspectorMode(ActiveEditorTracker self);\n        [FreeFunction]\n        static extern void Internal_SetInspectorMode(ActiveEditorTracker self, InspectorMode value);\n        public InspectorMode inspectorMode\n        {\n            get { return Internal_GetInspectorMode(this); }\n            set { Internal_SetInspectorMode(this, value); }\n        }\n\n        [FreeFunction]\n        static extern bool Internal_GetHasComponentsWhichCannotBeMultiEdited(ActiveEditorTracker self);\n        public bool hasComponentsWhichCannotBeMultiEdited\n        {\n            get { return Internal_GetHasComponentsWhichCannotBeMultiEdited(this); }\n        }\n\n        [FreeFunction]\n        static extern void Internal_RebuildIfNecessary(ActiveEditorTracker self);\n        public void RebuildIfNecessary() { Internal_RebuildIfNecessary(this); }\n\n        [FreeFunction]\n        static extern void Internal_RebuildAllIfNecessary();\n        internal static void RebuildAllIfNecessary() { Internal_RebuildAllIfNecessary(); }\n\n        [FreeFunction]\n        static extern void Internal_ForceRebuild(ActiveEditorTracker self);\n        public void ForceRebuild() { Internal_ForceRebuild(this); }\n\n        [FreeFunction]\n        static extern void Internal_VerifyModifiedMonoBehaviours(ActiveEditorTracker self);\n        public void VerifyModifiedMonoBehaviours() { Internal_VerifyModifiedMonoBehaviours(this); }\n\n        [FreeFunction]\n        static extern DataMode Internal_GetDataMode(ActiveEditorTracker self);\n        [FreeFunction]\n        static extern void Internal_SetDataMode(ActiveEditorTracker self, DataMode mode);\n        internal DataMode dataMode\n        {\n            get => Internal_GetDataMode(this);\n            set => Internal_SetDataMode(this, value);\n        }\n\n        [Obsolete(\"Use Editor.CreateEditor instead\")]\n        public static Editor MakeCustomEditor(UnityObject obj)\n        {\n            return Editor.CreateEditor(obj);\n        }\n\n        // Is there a custom editor for this object?\n        public static bool HasCustomEditor(UnityObject obj)\n        {\n            return CustomEditorAttributes.FindCustomEditorType(obj, false) != null;\n        }\n\n        public static ActiveEditorTracker sharedTracker\n        {\n            get\n            {\n                var tracker = new ActiveEditorTracker();\n                SetupSharedTracker(tracker);\n                return tracker;\n            }\n        }\n\n        // Only valid and rebuilds when sharedTracker is locked\n        internal static ActiveEditorTracker fallbackTracker\n        {\n            get\n            {\n                var tracker = new ActiveEditorTracker();\n                SetupFallbackTracker(tracker);\n                return tracker;\n            }\n        }\n\n        [FreeFunction(\"Internal_SetupSharedTracker\")]\n        static extern void SetupSharedTracker(ActiveEditorTracker sharedTracker);\n\n        [FreeFunction(\"Internal_SetupFallbackTracker\")]\n        static extern void SetupFallbackTracker(ActiveEditorTracker fallbackTracker);\n\n        [RequiredByNativeCode]\n        static void Internal_OnTrackerRebuild()\n        {\n            if (editorTrackerRebuilt != null)\n                editorTrackerRebuilt();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Selection/Selection.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    // SelectionMode can be used to tweak the selection returned by Selection.GetTransforms.\n    [Flags]\n    public enum SelectionMode\n    {\n        // Return the whole selection.\n        Unfiltered = 0,\n        // Only return the topmost selected transform. A selected child of another selected transform will be filtered out.\n        TopLevel = 1,\n        // Return the selection and all child transforms of the selection.\n        Deep = 2,\n        // Excludes any prefabs from the selection.\n        ExcludePrefab = 4,\n        // Excludes any objects which shall not be modified.\n        Editable = 8,\n        // Only return objects that are assets in the Asset directory.\n        Assets = 16,\n        // If the selection contains folders, also include all assets and subfolders within that folder in the file hierarchy.\n        DeepAssets = 32,\n        // Return a selection that only contains top level selection of all visible assets\n        //TopLevelAssets = 64,\n        // Renamed to Editable\n        [Obsolete(\"'OnlyUserModifiable' is obsolete. Use 'Editable' instead. (UnityUpgradeable) -> Editable\", true)]\n        OnlyUserModifiable = 8\n    }\n\n    [NativeHeader(\"Editor/Src/Gizmos/GizmoUtil.h\")]\n    [NativeHeader(\"Editor/Src/Selection/Selection.bindings.h\")]\n    [NativeHeader(\"Editor/Src/Selection/Selection.h\")]\n    [NativeHeader(\"Editor/Src/Selection/SceneInspector.h\")]\n    public sealed partial class Selection\n    {\n        // Returns the top level selection, excluding prefabs.\n        public extern static Transform[] transforms\n        {\n            [NativeMethod(\"GetTransformSelection\", true)]\n            get;\n        }\n\n        // Returns the actual game object selection. Includes prefabs, non-modifyable objects.\n        public extern static Transform activeTransform\n        {\n            [NativeMethod(\"GetActiveTransform\", true)]\n            get;\n            [NativeMethod(\"SetActiveObject\", true)]\n            set;\n        }\n\n        // Returns the actual game object selection. Includes prefabs, non-modifyable objects.\n        public extern static GameObject[] gameObjects\n        {\n            [NativeMethod(\"GetGameObjectSelection\", true)]\n            get;\n        }\n\n        // Returns the active game object. (The one shown in the inspector)\n        public extern static GameObject activeGameObject\n        {\n            [NativeMethod(\"GetActiveGO\", true)]\n            get;\n            [NativeMethod(\"SetActiveObject\", true)]\n            set;\n        }\n\n        // Returns the actual object selection. Includes prefabs, non-modifyable objects.\n        extern public static Object activeObject\n        {\n            [NativeMethod(\"GetActiveObject\", true)]\n            get;\n            [NativeMethod(\"SetActiveObject\", true)]\n            set;\n        }\n\n        [StaticAccessor(\"SelectionBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static void SetSelectionWithActiveObject([Unmarshalled] Object[] newSelection, Object activeObject);\n\n        [StaticAccessor(\"SelectionBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static void SetSelectionWithActiveInstanceID([NotNull] int[] newSelection, int activeObject);\n\n        [StaticAccessor(\"SelectionBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetFullSelection([Unmarshalled] Object[] newSelection, Object activeObject, Object context, DataMode dataModeHint);\n\n        [StaticAccessor(\"SelectionBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void SetFullSelectionByID([NotNull]int[] newSelection, int activeObjectInstanceID, int contextInstanceID, DataMode dataModeHint);\n\n        [StaticAccessor(\"SelectionBindings\", StaticAccessorType.DoubleColon)]\n        internal static extern void UpdateSelectionMetaData(Object context, DataMode dataModeHint);\n\n        // Returns the active context object\n        extern public static Object activeContext\n        {\n            [NativeMethod(\"GetActiveContext\", true)]\n            get;\n        }\n\n        internal extern static DataMode dataModeHint\n        {\n            [NativeMethod(\"GetDataModeHint\", true)]\n            get;\n        }\n\n        // Returns the instanceID of the actual object selection. Includes prefabs, non-modifiable objects.\n        [StaticAccessor(\"Selection\", StaticAccessorType.DoubleColon)]\n        [NativeName(\"ActiveID\")]\n        extern public static int activeInstanceID { get; set; }\n\n        // Returns the active context object's instance ID\n        [StaticAccessor(\"Selection\", StaticAccessorType.DoubleColon)]\n        [NativeName(\"ActiveContextID\")]\n        extern internal static int activeContextInstanceID { get; }\n\n        // The actual unfiltered selection from the Scene.\n        [StaticAccessor(\"SelectionBindings\", StaticAccessorType.DoubleColon)]\n        extern public static Object[] objects { [return: Unmarshalled]  get; [param:Unmarshalled] set; }\n\n        // The actual unfiltered selection from the Scene returned as instance ids instead of ::ref::objects.\n        [StaticAccessor(\"SelectionBindings\", StaticAccessorType.DoubleColon)]\n        public static int[] instanceIDs { get => GetInstanceIDs(); set => SetInstanceIDs(value); }\n\n        [StaticAccessor(\"SelectionBindings\", StaticAccessorType.DoubleColon)]\n        extern static int[] GetInstanceIDs();\n\n        [StaticAccessor(\"SelectionBindings\", StaticAccessorType.DoubleColon)]\n        extern static void SetInstanceIDs([NotNull] int[] instanceIDs);\n\n        [StaticAccessor(\"GetSceneTracker()\", StaticAccessorType.Dot)]\n        [NativeMethod(\"IsSelected\")]\n        extern public static bool Contains(int instanceID);\n\n        [NativeMethod(\"SetActiveObjectWithContextInternal\", true)]\n        extern public static void SetActiveObjectWithContext(Object obj, Object context);\n\n        // Allows for fine grained control of the selection type using the [[SelectionMode]] bitmask.\n        [NativeMethod(\"GetTransformSelection\", true)]\n        extern public static Transform[] GetTransforms(SelectionMode mode);\n\n        //* undocumented - utility function\n        [StaticAccessor(\"SelectionBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static Object[] GetObjectsMode(SelectionMode mode);\n\n        [StaticAccessor(\"SelectionBindings\", StaticAccessorType.DoubleColon)]\n        extern internal static string[] assetGUIDsDeepSelection\n        {\n            [NativeMethod(\"GetSelectedAssetGUIDStringsDeep\")]\n            get;\n        }\n\n        [StaticAccessor(\"SelectionBindings\", StaticAccessorType.DoubleColon)]\n        extern public static string[] assetGUIDs\n        {\n            [NativeMethod(\"GetSelectedAssetGUIDStrings\")]\n            get;\n        }\n\n        [StaticAccessor(\"Selection\", StaticAccessorType.DoubleColon)]\n        [NativeName(\"SelectionCount\")]\n        public extern static int count { get; }\n\n        [NativeMethod(\"DoAllGOsHaveConstrainProportionsEnabled\", true)]\n        internal static extern bool DoAllGOsHaveConstrainProportionsEnabled([NotNull] Object[] targetObjects);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Selection/Selection.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Scripting;\nusing System.Linq;\nusing System.Collections;\nusing System.Collections.Generic;\nusing JetBrains.Annotations;\n\nnamespace UnityEditor\n{\n    public sealed partial class Selection\n    {\n        static readonly int[] k_SingleSelectionCache = new int[1];\n\n        public static System.Action selectionChanged;\n        private static DelegateWithPerformanceTracker<System.Action> m_SelectionChangedEvent = new DelegateWithPerformanceTracker<System.Action>($\"{nameof(Selection)}.{nameof(selectionChanged)}\");\n        internal static event System.Action<int> selectedObjectWasDestroyed;\n        internal static event System.Action<int> nonSelectedObjectWasDestroyed;\n\n        [PublicAPI] // Used by packages with internal access. Not actually intended for users.\n        internal static event System.Action postProcessSelectionMetadata;\n\n        [UsedImplicitly, RequiredByNativeCode]\n        private static void Internal_SelectedObjectWasDestroyed(int instanceID)\n        {\n            if (selectedObjectWasDestroyed != null)\n                selectedObjectWasDestroyed(instanceID);\n        }\n\n        [UsedImplicitly, RequiredByNativeCode]\n        private static void Internal_NonSelectedObjectWasDestroyed(int instanceID)\n        {\n            if (nonSelectedObjectWasDestroyed != null)\n                nonSelectedObjectWasDestroyed(instanceID);\n        }\n\n        [UsedImplicitly, RequiredByNativeCode]\n        private static void Internal_PostProcessSelectionMetadata()\n        {\n            postProcessSelectionMetadata?.Invoke();\n        }\n\n        [UsedImplicitly, RequiredByNativeCode]\n        private static void Internal_CallSelectionChanged()\n        {\n            foreach (var evt in m_SelectionChangedEvent.UpdateAndInvoke(selectionChanged))\n                evt();\n        }\n\n        internal static void SetSelection(Object[] newSelection, Object newActiveObject = null, Object newActiveContext = null, DataMode newDataModeHint = default)\n        {\n            SetFullSelection(newSelection, newActiveObject, newActiveContext, newDataModeHint);\n        }\n\n        internal static void SetSelection(Object newActiveObject, Object newActiveContext = null, DataMode newDataModeHint = default)\n        {\n            var activeObjectID = newActiveObject != null ? newActiveObject.GetInstanceID() : 0;\n            var activeContextID = newActiveContext != null ? newActiveContext.GetInstanceID() : 0;\n            k_SingleSelectionCache[0] = activeObjectID;\n            SetFullSelectionByID(k_SingleSelectionCache, activeObjectID, activeContextID, newDataModeHint);\n        }\n\n        public static bool Contains(Object obj) { return Contains(obj.GetInstanceID()); }\n\n        internal static void Add(int instanceID)\n        {\n            var ids = new List<int>(Selection.instanceIDs);\n            if (ids.IndexOf(instanceID) < 0)\n            {\n                ids.Add(instanceID);\n                Selection.instanceIDs = ids.ToArray();\n            }\n        }\n\n        internal static void Add(Object obj)\n        {\n            if (obj != null)\n                Add(obj.GetInstanceID());\n        }\n\n        internal static void Remove(int instanceID)\n        {\n            var ids = new List<int>(Selection.instanceIDs);\n            ids.Remove(instanceID);\n            Selection.instanceIDs = ids.ToArray();\n        }\n\n        internal static void Remove(Object obj)\n        {\n            if (obj != null)\n                Remove(obj.GetInstanceID());\n        }\n\n        private static IEnumerable GetFilteredInternal(System.Type type, SelectionMode mode)\n        {\n            if (typeof(Component).IsAssignableFrom(type) || type.IsInterface)\n            {\n                return GetTransforms(mode).Select(t =>\n                {\n                    t.TryGetComponent(type, out var component);\n                    return component;\n                }).Where(c => !ReferenceEquals(c, null));\n            }\n            else if (typeof(GameObject).IsAssignableFrom(type))\n                return GetTransforms(mode).Select(t => t.gameObject);\n            else\n                return GetObjectsMode(mode).Where(o => o != null && type.IsAssignableFrom(o.GetType()));\n        }\n\n        public static T[] GetFiltered<T>(SelectionMode mode) // no generic constraint because we also want to allow interfaces\n        {\n            return GetFilteredInternal(typeof(T), mode).Cast<T>().ToArray();\n        }\n\n        public static Object[] GetFiltered(System.Type type, SelectionMode mode)\n        {\n            return GetFilteredInternal(type, mode).Cast<Object>().ToArray();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SelectionCommands/SelectionCommands.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEditor.ShortcutManagement;\nusing UnityEditorInternal;\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal static class SelectionCommands\n    {\n        private const int SelectionMenuPriority = 150;\n\n        [MenuItem(\"Edit/Deselect All #d\", false, SelectionMenuPriority + 1)]\n        internal static void DeselectAll()\n        {\n            InternalEditorUtility.ExecuteCommandOnKeyWindow(EventCommandNames.DeselectAll);\n        }\n\n        [MenuItem(\"Edit/Select Children #c\", false, SelectionMenuPriority + 2)]\n        internal static void SelectChildren()\n        {\n            InternalEditorUtility.ExecuteCommandOnKeyWindow(EventCommandNames.SelectChildren);\n        }\n\n        [MenuItem(\"Edit/Select Prefab Root %#r\", false, SelectionMenuPriority + 3)]\n        internal static void SelectPrefabRoot()\n        {\n            InternalEditorUtility.ExecuteCommandOnKeyWindow(EventCommandNames.SelectPrefabRoot);\n        }\n\n        [MenuItem(\"Edit/Invert Selection %i\", false, SelectionMenuPriority + 4)]\n        internal static void InvertSelection()\n        {\n            InternalEditorUtility.ExecuteCommandOnKeyWindow(EventCommandNames.InvertSelection);\n        }\n\n        [Shortcut(\"Edit/Delete\", KeyCode.Delete, ShortcutModifiers.Shift, displayName = \"Delete Current Selection\")]\n        internal static void DeleteSelectedAssetsShortcut()\n        {\n            InternalEditorUtility.ExecuteCommandOnKeyWindow(EventCommandNames.Delete);\n        }\n\n        [Shortcut(\"Edit/CopyInsert\", KeyCode.Insert, ShortcutModifiers.Action, displayName = \"Copy Insert Selection\")]\n        internal static void CopyInsertSelection()\n        {\n            InternalEditorUtility.ExecuteCommandOnKeyWindow(EventCommandNames.Copy);\n        }\n\n        [Shortcut(\"Edit/PasteInsert\", KeyCode.Insert, ShortcutModifiers.Shift, displayName = \"Paste Insert Selection\")]\n        internal static void PasteInsertSelection()\n        {\n            InternalEditorUtility.ExecuteCommandOnKeyWindow(EventCommandNames.Paste);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SerializationDebug.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Internal;\nusing UnityEngine.Scripting;\n\nusing System;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/Utility/SerializationDebug.bindings.h\")]\n    internal sealed partial class SerializationDebug\n    {\n        internal static extern string ToYAMLString(Object obj);\n\n        internal static void Log(Object obj)\n        {\n            Debug.Log(ToYAMLString(obj));\n        }\n\n        internal static void Log(SerializedObject serializerObject)\n        {\n            Debug.Log(GetLogString(serializerObject));\n        }\n\n        // GetLogString() is useful when a quick Object/SerializedObject dump is needed\n        // It can be used directly from the debugger compared to Log which will print the object in UnityEditor console with some delay\n        internal static string GetLogString(Object obj)\n        {\n            return ToYAMLString(obj);\n        }\n\n        private static string GetLogString(SerializedObject serializerObject)\n        {\n            string serializedObjectStr = \"\";\n\n            SerializedProperty property = serializerObject.GetIterator();\n            while (property.Next(property.hasVisibleChildren))\n            {\n                string propertyValue = \"\";\n                switch (property.propertyType)\n                {\n                    case SerializedPropertyType.Generic:\n                        propertyValue = \"Generic type value\";\n                        break;\n\n                    case SerializedPropertyType.Integer:\n                        propertyValue = $\"{property.intValue}\";\n                        break;\n\n                    case SerializedPropertyType.Boolean:\n                        propertyValue = $\"{property.boolValue}\";\n                        break;\n\n                    case SerializedPropertyType.Float:\n                        propertyValue = $\"{property.floatValue}\";\n                        break;\n\n                    case SerializedPropertyType.String:\n                        propertyValue = property.stringValue;\n                        break;\n\n                    case SerializedPropertyType.Color:\n                        propertyValue = $\"{property.colorValue}\";\n                        break;\n\n                    case SerializedPropertyType.ObjectReference:\n                        propertyValue = $\"{{instanceID: {property.objectReferenceInstanceIDValue} ({property.objectReferenceStringValue})}}\";\n                        break;\n\n                    case SerializedPropertyType.LayerMask:\n                        propertyValue = $\"{property.layerMaskBits}\";\n                        break;\n\n                    case SerializedPropertyType.RenderingLayerMask:\n                        propertyValue = $\"{property.layerMaskBits}\";\n                        break;\n\n                    case SerializedPropertyType.Enum:\n                        propertyValue = $\"{property.enumValueIndex}\";\n                        break;\n\n                    case SerializedPropertyType.Vector2:\n                        propertyValue = $\"{property.vector2Value}\";\n                        break;\n\n                    case SerializedPropertyType.Vector3:\n                        propertyValue = $\"{property.vector3Value}\";\n                        break;\n\n                    case SerializedPropertyType.Vector4:\n                        propertyValue = $\"{property.vector4Value}\";\n                        break;\n\n                    case SerializedPropertyType.Rect:\n                        propertyValue = $\"{property.rectValue}\";\n                        break;\n\n                    case SerializedPropertyType.ArraySize:\n                        propertyValue = $\"{property.intValue}\";\n                        break;\n\n                    case SerializedPropertyType.Character:\n                        propertyValue = $\"{(char)property.intValue}\";\n                        break;\n\n                    case SerializedPropertyType.AnimationCurve:\n                        propertyValue = $\"{property.animationCurveValue}\";\n                        break;\n\n                    case SerializedPropertyType.Bounds:\n                        propertyValue = $\"{property.boundsValue}\";\n                        break;\n\n                    case SerializedPropertyType.Gradient:\n                        propertyValue = $\"{property.gradientValue}\";\n                        break;\n\n                    case SerializedPropertyType.Quaternion:\n                        propertyValue = $\"{property.quaternionValue}\";\n                        break;\n\n                    case SerializedPropertyType.ExposedReference:\n                        propertyValue = $\"{{instanceID: {property.objectReferenceInstanceIDValue} ({property.objectReferenceStringValue})}}\";\n                        break;\n\n                    case SerializedPropertyType.FixedBufferSize:\n                        propertyValue = $\"{property.fixedBufferSize}\";\n                        break;\n\n                    case SerializedPropertyType.Vector2Int:\n                        propertyValue = $\"{property.vector2IntValue}\";\n                        break;\n\n                    case SerializedPropertyType.Vector3Int:\n                        propertyValue = $\"{property.vector3IntValue}\";\n                        break;\n\n                    case SerializedPropertyType.RectInt:\n                        propertyValue = $\"{property.rectIntValue}\";\n                        break;\n\n                    case SerializedPropertyType.BoundsInt:\n                        propertyValue = $\"{property.boundsIntValue}\";\n                        break;\n\n                    case SerializedPropertyType.ManagedReference:\n                        propertyValue = $\"{{instanceID: {property.objectReferenceInstanceIDValue} ({property.objectReferenceStringValue})}}\";\n                        break;\n\n                    case SerializedPropertyType.Hash128:\n                        propertyValue = $\"{property.hash128Value}\";\n                        break;\n                }\n\n                if (property.prefabOverride)\n                {\n                    propertyValue += \"(Prefab Override)\";\n                }\n\n                serializedObjectStr += $\"{property.propertyPath}: {propertyValue}\\n\";\n            }\n\n            return serializedObjectStr;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SerializedObject.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing System;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Src/Utility/SerializedProperty.h\")]\n    [NativeHeader(\"Editor/Src/Utility/SerializedObject.bindings.h\")]\n    [NativeHeader(\"Editor/Src/Utility/SerializedObjectCache.h\")]\n\n    // SerializedObject and [[SerializedProperty]] are classes for editing properties on objects in a completely generic way that automatically handles undo and styling UI for prefabs.\n\n    public class SerializedObject : IDisposable\n    {\n        #pragma warning disable 414\n        internal IntPtr m_NativeObjectPtr;\n\n        // Create SerializedObject for inspected object.\n        public SerializedObject(Object obj)\n        {\n            m_NativeObjectPtr = InternalCreate(new Object[] {obj}, null);\n        }\n\n        public SerializedObject(Object obj, Object context)\n        {\n            m_NativeObjectPtr = InternalCreate(new Object[] {obj}, context);\n        }\n\n        // Create SerializedObject for inspected object.\n        public SerializedObject(Object[] objs)\n        {\n            m_NativeObjectPtr = InternalCreate(objs, null);\n        }\n\n        public SerializedObject(Object[] objs, Object context)\n        {\n            m_NativeObjectPtr = InternalCreate(objs, context);\n        }\n\n        internal SerializedObject(IntPtr nativeObjectPtr)\n        {\n            m_NativeObjectPtr = nativeObjectPtr;\n        }\n\n        ~SerializedObject() { Dispose(); }\n\n        [ThreadAndSerializationSafe()]\n        public void Dispose()\n        {\n            if (m_NativeObjectPtr != IntPtr.Zero)\n            {\n                Internal_Destroy(m_NativeObjectPtr);\n                m_NativeObjectPtr = IntPtr.Zero;\n            }\n        }\n\n        [FreeFunction(\"SerializedObjectBindings::Internal_Destroy\", IsThreadSafe = true)]\n        private static extern void Internal_Destroy(IntPtr ptr);\n\n        // Get the first serialized property.\n        public SerializedProperty GetIterator()\n        {\n            SerializedProperty i = GetIterator_Internal();\n            // This is so the garbage collector won't clean up SerializedObject behind the scenes,\n            // when we are still iterating properties\n            i.m_SerializedObject = this;\n            return i;\n        }\n\n        // Find serialized property by name.\n        public SerializedProperty FindProperty(string propertyPath)\n        {\n            SerializedProperty i = GetIterator_Internal();\n            // This is so the garbage collector won't clean up SerializedObject behind the scenes,\n            // when we are still iterating properties\n            i.m_SerializedObject = this;\n            if (i.FindPropertyInternal(propertyPath))\n                return i;\n            else\n                return null;\n        }\n\n        // Find serialized property by name ignoring case.\n        internal SerializedProperty FindPropertyIgnoreCase(string propertyPath)\n        {\n            SerializedProperty i = GetIterator_Internal();\n            // This is so the garbage collector won't clean up SerializedObject behind the scenes,\n            // when we are still iterating properties\n            i.m_SerializedObject = this;\n            if (i.FindPropertyIgnoreCaseInternal(propertyPath))\n                return i;\n            else\n                return null;\n        }\n\n        /// <summary>\n        /// Given a path of the form \"managedReferences[refid].field\" this finds the first field\n        /// that references that reference id and returns a serialized property based on that path.\n        /// For example if an object \"Foo\" with id 1 is referenced by multiple fields \"a\", \"b\" and\n        /// \"c.nested\" on a MonoBehaviour (declared in that order), then calling this method with\n        /// \"managedReferences[1].x\" would return the SerializedProperty with property path \"a.x\".\n        /// </summary>\n        internal SerializedProperty FindFirstPropertyFromManagedReferencePath(string propertyPath)\n        {\n            SerializedProperty i = GetIterator_Internal();\n            // This is so the garbage collector won't clean up SerializedObject behind the scenes,\n            // when we are still iterating properties\n            i.m_SerializedObject = this;\n            if (i.FindFirstPropertyFromManagedReferencePathInternal(propertyPath))\n                return i;\n            else\n                return null;\n        }\n\n        extern public bool ApplyModifiedProperties();\n\n        // Update /hasMultipleDifferentValues/ cache on the next /Update()/ call.\n        extern public void SetIsDifferentCacheDirty();\n\n        [FreeFunction(Name = \"SerializedObjectBindings::GetIteratorInternal\", HasExplicitThis = true)]\n        extern private SerializedProperty GetIterator_Internal();\n\n        // Update serialized object's representation.\n        extern public void Update();\n\n        // Update serialized object's representation, only if the object has been modified since the last call to Update or if it is a script.\n        [Obsolete(\"UpdateIfDirtyOrScript has been deprecated. Use UpdateIfRequiredOrScript instead.\", false)]\n        [NativeName(\"UpdateIfRequiredOrScript\")]\n        extern public void UpdateIfDirtyOrScript();\n\n        // Update serialized object's representation, only if the object has been modified since the last call to Update or if it is a script.\n        extern public bool UpdateIfRequiredOrScript();\n\n        // Updates this serialized object's isExpanded value to the global inspector's expanded state for this object\n        extern internal void UpdateExpandedState();\n\n        [NativeMethod(Name = \"SerializedObjectBindings::InternalCreate\", IsFreeFunction = true, ThrowsException = true)]\n        extern static IntPtr InternalCreate(Object[] monoObjs, Object context);\n\n        internal PropertyModification ExtractPropertyModification(string propertyPath)\n        {\n            return InternalExtractPropertyModification(propertyPath) as PropertyModification;\n        }\n\n        [FreeFunction(\"SerializedObjectBindings::ExtractPropertyModification\", HasExplicitThis = true)]\n        extern private object InternalExtractPropertyModification(string propertyPath);\n\n        // The inspected object (RO).\n        public extern Object targetObject { get; }\n\n        // The inspected objects (RO).\n        public extern Object[] targetObjects { get; }\n\n        // The inspected objects (RO).\n        internal extern int targetObjectsCount { get; }\n\n        // The context object (used to resolve scene references via ExposedReference<>)\n        [NativeProperty(\"ContextObject\")]\n        public extern Object context { get; }\n\n        internal void Cache(int instanceID)\n        {\n            CacheInternal(instanceID);\n            m_NativeObjectPtr = IntPtr.Zero;\n        }\n\n        [FreeFunction(\"SerializedObjectCache::SaveToCache\", HasExplicitThis = true)]\n        private extern void CacheInternal(int instanceID);\n\n        [FreeFunction(\"SerializedObjectCache::LoadFromCache\")]\n        internal extern static SerializedObject LoadFromCache(int instanceID);\n\n        public extern bool ApplyModifiedPropertiesWithoutUndo();\n\n        // Enable/Disable live property feature globally.\n        internal extern static void EnableLivePropertyFeatureGlobally(bool value);\n\n        // Get live property global state.\n        internal extern static bool GetLivePropertyFeatureGlobalState();\n\n        // Copies a value from a SerializedProperty to the same serialized property on this serialized object.\n        public void CopyFromSerializedProperty(SerializedProperty prop)\n        {\n            if (prop == null)\n                throw new ArgumentNullException(\"prop\");\n\n            prop.Verify(SerializedProperty.VerifyFlags.IteratorNotAtEnd);\n            CopyFromSerializedPropertyInternal(prop);\n        }\n\n        [FreeFunction(\"SerializedObjectBindings::CopyFromSerializedPropertyInternal\", HasExplicitThis = true)]\n        private extern void CopyFromSerializedPropertyInternal(SerializedProperty prop);\n\n        // Copies a value from a SerializedProperty to the same serialized property on this serialized object.\n        public bool CopyFromSerializedPropertyIfDifferent(SerializedProperty prop)\n        {\n            if (prop == null)\n                throw new ArgumentNullException(\"prop\");\n\n            prop.Verify(SerializedProperty.VerifyFlags.IteratorNotAtEnd);\n            return CopyFromSerializedPropertyIfDifferentInternal(prop);\n        }\n\n        [FreeFunction(\"SerializedObjectBindings::CopyFromSerializedPropertyIfDifferentInternal\", HasExplicitThis = true)]\n        private extern bool CopyFromSerializedPropertyIfDifferentInternal(SerializedProperty prop);\n\n        public extern bool hasModifiedProperties\n        {\n            [NativeMethod(\"HasModifiedProperties\")]\n            get;\n        }\n\n        internal extern InspectorMode inspectorMode\n        {\n            get;\n            set;\n        }\n\n        internal extern DataMode inspectorDataMode\n        {\n            get;\n            set;\n        }\n\n        // Does the serialized object represents multiple objects due to multi-object editing? (RO)\n        public extern bool isEditingMultipleObjects\n        {\n            [NativeMethod(\"IsEditingMultipleObjects\")]\n            get;\n        }\n\n        public extern int maxArraySizeForMultiEditing\n        {\n            get;\n            set;\n        }\n\n        internal extern bool IsValid();\n\n        internal bool isValid => m_NativeObjectPtr != IntPtr.Zero && IsValid();\n\n        internal extern uint objectVersion\n        {\n            [NativeMethod(\"GetObjectVersion\")]\n            get;\n        }\n\n        public extern bool forceChildVisibility\n        {\n            [NativeMethod(\"GetForceChildVisibiltyFlag\")]\n            get;\n            [NativeMethod(\"SetForceChildVisibiltyFlag\")]\n            set;\n        }\n\n        [NativeMethod(\"HasAnyInstantiatedPrefabsWithValidAsset\")]\n        internal extern bool HasAnyInstantiatedPrefabsWithValidAsset();\n\n        internal static bool VersionEquals(SerializedObject x, SerializedObject y)\n        {\n            if (x == null || y == null || x.m_NativeObjectPtr == IntPtr.Zero || y.m_NativeObjectPtr == IntPtr.Zero\n                || !x.isValid || !y.isValid) return false;\n\n            return VersionEqualsInternal(x, y);\n        }\n\n        [FreeFunction(\"SerializedObjectBindings::VersionEqualsInternal\")]\n        extern static bool VersionEqualsInternal(SerializedObject x, SerializedObject y);\n\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(SerializedObject obj) => obj.m_NativeObjectPtr;\n            public static SerializedObject ConvertToManaged(IntPtr ptr) => new SerializedObject(ptr);\n        }\n\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SerializedProperty/SerializedPropertyFilters.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    internal class SerializedPropertyFilters\n    {\n        internal interface IFilter\n        {\n            bool Active();                          // returns true if filter is active, false otherwise\n            bool Filter(SerializedProperty prop);   // returns true if filtering passes\n            void OnGUI(Rect r);                     // draws the filter control\n            string SerializeState();                // returns null if there's nothing to serialize\n            void DeserializeState(string state);    // state must not be null\n        }\n\n        internal abstract class SerializableFilter : IFilter\n        {\n            public abstract bool Active();                          // returns true if filter is active, false otherwise\n            public abstract bool Filter(SerializedProperty prop);   // returns true if filtering passes\n            public abstract void OnGUI(Rect r);                     // draws the filter control\n            public string SerializeState() { return JsonUtility.ToJson(this); }\n            public void DeserializeState(string state) { JsonUtility.FromJsonOverwrite(state, this); }\n        }\n\n\n        internal class String : SerializableFilter\n        {\n            static class Styles\n            {\n                public static readonly GUIStyle searchField = \"SearchTextField\";\n                public static readonly GUIStyle searchFieldCancelButton = \"SearchCancelButton\";\n                public static readonly GUIStyle searchFieldCancelButtonEmpty = \"SearchCancelButtonEmpty\";\n            }\n\n            [SerializeField] protected string m_Text = \"\";\n            public override bool Active() { return !string.IsNullOrEmpty(m_Text); }\n            public override bool Filter(SerializedProperty prop) { return prop.stringValue.IndexOf(m_Text, 0, System.StringComparison.OrdinalIgnoreCase) >= 0; }\n            public override void OnGUI(Rect r)\n            {\n                bool empty = string.IsNullOrEmpty(m_Text);\n\n                Rect buttonRect = r;\n                buttonRect.x += (r.width - 15);\n                buttonRect.width = 15;\n                GUIStyle buttonStyle = empty ? Styles.searchFieldCancelButtonEmpty : Styles.searchFieldCancelButton;\n\n                if (GUI.Button(buttonRect, GUIContent.none, buttonStyle) && !empty)\n                {\n                    m_Text = \"\";\n                    GUIUtility.keyboardControl = 0;\n                }\n\n                m_Text = EditorGUI.TextField(r, GUIContent.none, m_Text, Styles.searchField);\n                GUI.Button(buttonRect, GUIContent.none, buttonStyle);\n            }\n        }\n\n        internal sealed class Name : String\n        {\n            public bool Filter(string str) { return str.IndexOf(m_Text, 0, System.StringComparison.OrdinalIgnoreCase) >= 0; }\n        }\n\n        internal sealed class None : IFilter\n        {\n            public bool Active() { return false; }\n            public bool Filter(SerializedProperty prop) { return true; }\n            public void OnGUI(Rect r) {}\n            public string SerializeState() { return null; }\n            public void DeserializeState(string state) {}\n        }\n        internal static readonly None s_FilterNone = new None();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SerializedProperty/SerializedPropertyTable.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine.Profiling;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    internal class SerializedPropertyTable\n    {\n        internal delegate SerializedPropertyTreeView.Column[] HeaderDelegate();\n\n        SerializedPropertyDataStore.GatherDelegate  m_GatherDelegate;\n        HeaderDelegate                              m_HeaderDelegate;\n        bool                                        m_Initialized;\n        TreeViewState                               m_TreeViewState;\n        MultiColumnHeaderState                      m_MultiColumnHeaderState;\n        SerializedPropertyTreeView                  m_TreeView;\n        SerializedPropertyDataStore                 m_DataStore;\n        float                                       m_ColumnHeaderHeight;\n        string                                      m_SerializationUID;\n        readonly float                              m_FilterHeight = 20;\n        bool                                        m_ShowFilterGUI;\n\n        public SerializedPropertyTable(string serializationUID, SerializedPropertyDataStore.GatherDelegate gatherDelegate, HeaderDelegate headerDelegate, bool showFilterGUI)\n        {\n            m_SerializationUID = serializationUID;\n            m_GatherDelegate = gatherDelegate;\n            m_HeaderDelegate = headerDelegate;\n\n            m_ShowFilterGUI = showFilterGUI;\n        }\n\n        void InitIfNeeded()\n        {\n            if (m_Initialized)\n                return;\n\n            if (m_TreeViewState == null)\n                m_TreeViewState = new TreeViewState();\n\n\n            if (m_MultiColumnHeaderState == null)\n            {\n                SerializedPropertyTreeView.Column[] columns = m_HeaderDelegate();\n\n                string[] propNames = GetPropertyNames(columns);\n\n                m_MultiColumnHeaderState = new MultiColumnHeaderState(columns);\n                m_DataStore = new SerializedPropertyDataStore(propNames, m_GatherDelegate);\n            }\n\n            var header = new MultiColumnHeader(m_MultiColumnHeaderState);\n            m_ColumnHeaderHeight = header.height;\n            m_TreeView = new SerializedPropertyTreeView(m_TreeViewState, header, m_DataStore, m_ShowFilterGUI);\n\n            m_TreeView.DeserializeState(m_SerializationUID);\n            m_TreeView.Reload();\n\n            m_Initialized = true;\n        }\n\n        string[] GetPropertyNames(SerializedPropertyTreeView.Column[] columns)\n        {\n            string[] propNames = new string[columns.Length];\n\n            for (int i = 0; i < columns.Length; i++)\n                propNames[i] = columns[i].propertyName;\n\n            return propNames;\n        }\n\n        public void OnInspectorUpdate()\n        {\n            if (m_TreeView != null)\n            {\n                m_TreeView.Update();\n            }\n        }\n\n        public void OnHierarchyChange()\n        {\n            if (m_TreeView != null)\n            {\n                m_TreeView.Update();\n            }\n        }\n\n        public void OnSelectionChange()\n        {\n            OnSelectionChange(Selection.instanceIDs);\n        }\n\n        public void OnSelectionChange(int[] instanceIDs)\n        {\n            if (m_TreeView != null)\n            {\n                m_TreeView.SetSelection(instanceIDs);\n            }\n        }\n\n        public void OnGUI()\n        {\n            Profiler.BeginSample(\"SerializedPropertyTable.OnGUI\");\n            InitIfNeeded();\n\n            Rect r = GUILayoutUtility.GetRect(0, float.MaxValue, 0, float.MaxValue);\n\n            if (Event.current.type == EventType.Layout)\n            {\n                Profiler.EndSample();\n                return;\n            }\n\n            float tableHeight = r.height - m_FilterHeight;\n            // filter rect\n            r.height = m_FilterHeight;\n            Rect filterRect = r;\n            // table rect\n            r.height = tableHeight;\n            r.y += m_FilterHeight;\n            Rect tableRect = r;\n\n            // filter\n            m_TreeView.OnFilterGUI(filterRect);\n\n            // table\n            Profiler.BeginSample(\"TreeView.OnGUI\");\n            m_TreeView.OnGUI(tableRect);\n            Profiler.EndSample();\n\n            if (m_TreeView.IsFilteredDirty())\n                m_TreeView.Reload();\n\n            Profiler.EndSample();\n        }\n\n        public void OnDisable()\n        {\n            if (m_TreeView != null)\n                m_TreeView.SerializeState(m_SerializationUID);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SerializedProperty/SerializedPropertyTreeView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine.Profiling;\nusing TreeView = UnityEditor.IMGUI.Controls.TreeView<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewUtility = UnityEditor.IMGUI.Controls.TreeViewUtility<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    internal class SerializedPropertyDataStore\n    {\n        internal class Data\n        {\n            UnityEngine.Object m_Object;\n            SerializedObject m_SerializedObject;\n            SerializedProperty[] m_Properties;\n\n            public Data(UnityEngine.Object obj, string[] props)\n            {\n                m_Object = obj;\n                m_SerializedObject = new SerializedObject(obj);\n                m_Properties = new SerializedProperty[props.Length];\n\n                for (int i = 0; i < props.Length; i++)\n                    m_Properties[i] = m_SerializedObject.FindProperty(props[i]);\n            }\n\n            public void Dispose()\n            {\n                foreach (var prop in m_Properties)\n                {\n                    if (prop != null)\n                        prop.Dispose();\n                }\n\n                m_SerializedObject.Dispose();\n\n                m_Object            = null;\n                m_SerializedObject  = null;\n                m_Properties        = null;\n            }\n\n            public string name { get { return m_Object != null ? m_Object.name : string.Empty; } }\n            public SerializedObject serializedObject { get { return m_SerializedObject; } }\n            public SerializedProperty[] properties { get { return m_Properties; } }\n\n            public int objectId\n            {\n                get\n                {\n                    if (!m_Object)\n                        return 0;\n\n                    Component comp = m_Object as Component;\n                    return comp != null ? comp.gameObject.GetInstanceID() : m_Object.GetInstanceID();\n                }\n            }\n\n            public bool activeInHierarchy\n            {\n                get\n                {\n                    if (m_Object != null && m_Object is Component)\n                    {\n                        return ((Component)m_Object).gameObject.activeInHierarchy;\n                    }\n                    if (m_Object != null && m_Object is Material) // Materials can't be shown in the hierarchy\n                    {\n                        return true;\n                    }\n\n                    return false;\n                }\n            }\n\n            public bool Update() { return m_Object != null ? m_SerializedObject.UpdateIfRequiredOrScript() : false; }\n            public void Store() { if (m_Object != null) {  m_SerializedObject.ApplyModifiedProperties(); } }\n        }\n\n        // LightTreeDataStore members\n        internal delegate UnityEngine.Object[] GatherDelegate();\n        UnityEngine.Object[] m_Objects; // only used to keep track of changes\n        bool[] m_ActiveObjects;\n        Data[] m_Elements;\n        string[] m_PropNames;\n        GatherDelegate m_GatherDel;\n\n        public Data[] GetElements() { return m_Elements; }\n\n        public SerializedPropertyDataStore(string[] propNames, GatherDelegate gatherDel)\n        {\n            m_PropNames = propNames;\n            m_GatherDel = gatherDel;\n\n            bool needsReload;\n            Repopulate(out needsReload);\n        }\n\n        ~SerializedPropertyDataStore()\n        {\n            Clear();\n        }\n\n        public bool Repopulate(out bool needsReload)\n        {\n            // this is done due to optimization reasons. we want to know if any major changes has happened to the data\n            // without having to refetch it in another place and loop through it there\n            needsReload = false;\n\n            Profiler.BeginSample(\"SerializedPropertyDataStore.Repopulate.GatherDelegate\");\n            UnityEngine.Object[] objs = m_GatherDel();\n            Profiler.EndSample();\n\n            if (m_Objects != null)\n            {\n                // If nothing's changed -> bail\n                if (objs.Length == m_Objects.Length && ArrayUtility.ArrayReferenceEquals(objs, m_Objects))\n                {\n                    // The list of objects is the same, but since some should now potentially be hidden, we need to request a reload\n                    if (!ActiveObjectsEquals(objs, m_ActiveObjects))\n                    {\n                        UpdateActiveObjects(objs);\n                        needsReload = true;\n                    }\n\n                    return false;\n                }\n\n                Clear();\n            }\n\n            UpdateActiveObjects(objs);\n\n            // Recreate data store\n            m_Objects = objs;\n            m_Elements = new Data[objs.Length];\n\n            int elementIndex = 0;\n            for (int i = 0; i < objs.Length; i++)\n            {\n                if (objs[i] == null)\n                    continue;\n\n                m_Elements[elementIndex] = new Data(objs[i], m_PropNames);\n\n                elementIndex++;\n            }\n\n            if (elementIndex < objs.Length)\n                System.Array.Resize(ref m_Elements, elementIndex);\n\n            needsReload = true;\n            return true;\n        }\n\n        // Updates the cached active objects array (m_ActiveObjects) to reflect the current state of the passed objects\n        private void UpdateActiveObjects(Object[] objs)\n        {\n            m_ActiveObjects = new bool[objs.Length];\n\n            for (int i = 0; i < objs.Length; i++)\n            {\n                if (objs[i] == null)\n                    continue;\n\n                if (objs[i] is Component)\n                {\n                    m_ActiveObjects[i] = ((Component)objs[i]).gameObject.activeInHierarchy;\n                }\n            }\n        }\n\n        private void Clear()\n        {\n            // Clear current\n            for (int i = 0; i < m_Elements.Length; i++)\n                m_Elements[i].Dispose();\n\n            m_Objects  = null;\n            m_Elements = null;\n            m_ActiveObjects = null;\n        }\n\n        private static bool ActiveObjectsEquals(Object[] objects, bool[] activeObjects)\n        {\n            if (activeObjects != null && objects.Length != activeObjects.Length)\n                return true;\n\n            for (int i = 0; i < objects.Length; i++)\n            {\n                if (objects[i] != null && objects[i] is Component)\n                {\n                    if (((Component)objects[i]).gameObject.activeInHierarchy != activeObjects[i])\n                        return false;\n                }\n            }\n            return true;\n        }\n    }\n\n    internal class SerializedPropertyTreeView : TreeView\n    {\n        internal static class Styles\n        {\n            public static readonly GUIStyle entryEven = \"OL EntryBackEven\";\n            public static readonly GUIStyle entryOdd  = \"OL EntryBackOdd\";\n            public static readonly string focusHelper = \"SerializedPropertyTreeViewFocusHelper\";\n            public static readonly string serializeFilterSelection = \"_FilterSelection\";\n            public static readonly string serializeFilterDisable   = \"_FilterDisable\";\n            public static readonly string serializeFilterInvert    = \"_FilterInvert\";\n            public static readonly string serializeTreeViewState    = \"_TreeViewState\";\n            public static readonly string serializeColumnHeaderState = \"_ColumnHeaderState\";\n            public static readonly string serializeFilter = \"_Filter_\";\n            public static readonly GUIContent filterSelection = EditorGUIUtility.TrTextContent(\"Isolate Selection\", \"Limits the table contents to the active selection.\");\n            public static readonly GUIContent showInactiveObjects = EditorGUIUtility.TrTextContent(\"Show Inactive Objects\", \"Show objects that are not active in the hierarchy but contains the component.\");\n        }\n\n        // this gets stuffed into the view and displayed on screen. It is a visible subset of the actual data\n        internal class SerializedPropertyItem : TreeViewItem\n        {\n            SerializedPropertyDataStore.Data m_Data;\n\n            public SerializedPropertyItem(int id, int depth, SerializedPropertyDataStore.Data ltd) : base(id, depth, ltd != null ? ltd.name : \"root\")\n            {\n                m_Data = ltd;\n            }\n\n            public SerializedPropertyDataStore.Data GetData() { return m_Data; }\n        }\n\n        internal class Column : MultiColumnHeaderState.Column\n        {\n            public delegate void DrawEntry(Rect r, SerializedProperty prop, SerializedProperty[] dependencies);\n            public delegate int CompareEntry(SerializedProperty lhs, SerializedProperty rhs);\n            public delegate void CopyDelegate(SerializedProperty target, SerializedProperty source);\n\n            public string                               propertyName;\n            public int[]                                dependencyIndices;\n            public DrawEntry                            drawDelegate;\n            public CompareEntry                         compareDelegate;\n            public CopyDelegate                         copyDelegate;\n            public SerializedPropertyFilters.IFilter    filter;\n\n            public static void OverwriteSerializedFields(MultiColumnHeaderState source, MultiColumnHeaderState destination)\n            {\n                destination.visibleColumns = source.visibleColumns;\n                destination.sortedColumns = source.sortedColumns;\n\n                for (int i = 0; i < destination.columns.Length; ++i)\n                {\n                    destination.columns[i].sortedAscending = source.columns[i].sortedAscending;\n                    destination.columns[i].autoResize = true;\n\n                    var sourceColumn = source.columns[i] as Column;\n                    var destColumn = destination.columns[i] as Column;\n\n                    if ((sourceColumn == null || destColumn == null) || string.Equals(sourceColumn.propertyName, destColumn.propertyName))\n                    {\n                        // Only makes sense if the property is the same property name\n                        destination.columns[i].width = source.columns[i].width;\n                    }\n                }\n            }\n        }\n\n        private struct ColumnInternal\n        {\n            public SerializedProperty[] dependencyProps;    // helper array, must be the same size as dependencyIndices\n        }\n\n        internal class DefaultDelegates\n        {\n            public static readonly Column.DrawEntry DrawDefault = (Rect r, SerializedProperty prop, SerializedProperty[] dependencies) =>\n            {\n                Profiler.BeginSample(\"PropDrawDefault\");\n                EditorGUI.PropertyField(r, prop, GUIContent.none);\n                Profiler.EndSample();\n            };\n            public static readonly Column.DrawEntry DrawCheckbox = (Rect r, SerializedProperty prop, SerializedProperty[] dependencies) =>\n            {\n                Profiler.BeginSample(\"PropDrawCheckbox\");\n                float off = System.Math.Max(0.0f, ((r.width / 2) - 8));\n                r.x += off;\n                r.width -= off;\n                EditorGUI.PropertyField(r, prop, GUIContent.none);\n                Profiler.EndSample();\n            };\n            public static readonly Column.DrawEntry DrawName = (Rect r, SerializedProperty prop, SerializedProperty[] dependencies) => {};\n\n            public static readonly Column.CompareEntry CompareFloat = (SerializedProperty lhs, SerializedProperty rhs) =>\n            {\n                return lhs.floatValue.CompareTo(rhs.floatValue);\n            };\n            public static readonly Column.CompareEntry CompareCheckbox = (SerializedProperty lhs, SerializedProperty rhs) =>\n            {\n                return lhs.boolValue.CompareTo(rhs.boolValue);\n            };\n            public static readonly Column.CompareEntry CompareEnum = (SerializedProperty lhs, SerializedProperty rhs) =>\n            {\n                return lhs.enumValueIndex.CompareTo(rhs.enumValueIndex);\n            };\n            public static readonly Column.CompareEntry CompareInt = (SerializedProperty lhs, SerializedProperty rhs) =>\n            {\n                return lhs.intValue.CompareTo(rhs.intValue);\n            };\n            public static readonly Column.CompareEntry CompareColor = (SerializedProperty lhs, SerializedProperty rhs) =>\n            {\n                float lh, ls, lv, rh, rs, rv;\n                Color.RGBToHSV(lhs.colorValue, out lh, out ls, out lv);\n                Color.RGBToHSV(rhs.colorValue, out rh, out rs, out rv);\n                return lh.CompareTo(rh);\n            };\n            public static readonly Column.CompareEntry CompareName = (SerializedProperty lhs, SerializedProperty rhs) =>\n            {\n                return 0;\n            };\n            public static readonly Column.CopyDelegate CopyDefault = (SerializedProperty target, SerializedProperty source) =>\n            {\n                target.serializedObject.CopyFromSerializedProperty(source);\n            };\n        }\n        // reference to the data store (not owned by this class)\n        SerializedPropertyDataStore m_DataStore;\n        ColumnInternal[]            m_ColumnsInternal;\n        List<TreeViewItem>          m_Items;\n        int                         m_ChangedId;\n        bool                        m_bFilterSelection;\n        bool                        m_ShowInactiveObjects;\n        int[]                       m_SelectionFilter;\n        bool                        m_ShowFilterGUI;\n\n        public SerializedPropertyTreeView(TreeViewState state, MultiColumnHeader multicolumnHeader, SerializedPropertyDataStore dataStore, bool showFilterGUI) : base(state, multicolumnHeader)\n        {\n            m_DataStore = dataStore;\n            // initialize internal data for the columns\n            int colcnt = multiColumnHeader.state.columns.Length;\n            m_ColumnsInternal = new ColumnInternal[colcnt];\n            for (int i = 0; i < colcnt; i++)\n            {\n                Column c = Col(i);\n                if (c.propertyName != null)\n                    m_ColumnsInternal[i].dependencyProps = new SerializedProperty[c.propertyName.Length];\n            }\n\n            multiColumnHeader.sortingChanged += OnSortingChanged;\n            multiColumnHeader.visibleColumnsChanged += OnVisibleColumnChanged;\n\n            showAlternatingRowBackgrounds = true;\n            showBorder = true;\n            rowHeight = EditorGUIUtility.singleLineHeight;\n\n            m_ShowFilterGUI = showFilterGUI;\n        }\n\n        public void SerializeState(string uid)\n        {\n            SessionState.SetBool(uid + Styles.serializeFilterSelection, m_bFilterSelection);\n            SessionState.SetBool(uid + Styles.showInactiveObjects, m_ShowInactiveObjects);\n\n            for (int i = 0; i < multiColumnHeader.state.columns.Length; i++)\n            {\n                var filter = Col(i).filter;\n\n                if (filter == null)\n                    continue;\n\n                string filterState = filter.SerializeState();\n\n                if (string.IsNullOrEmpty(filterState))\n                    continue;\n\n                SessionState.SetString(uid + Styles.serializeFilter + i, filterState);\n            }\n\n            SessionState.SetString(uid + Styles.serializeTreeViewState, JsonUtility.ToJson(state));\n            EditorPrefs.SetString(uid + Styles.serializeColumnHeaderState, JsonUtility.ToJson(multiColumnHeader.state));\n        }\n\n        public void DeserializeState(string uid)\n        {\n            m_bFilterSelection = SessionState.GetBool(uid + Styles.serializeFilterSelection, false);\n            m_ShowInactiveObjects = SessionState.GetBool(uid + Styles.showInactiveObjects, false);\n\n            MultiColumnHeaderState headerState = new MultiColumnHeaderState(multiColumnHeader.state.columns);\n            string columnHeaderState = EditorPrefs.GetString(uid + Styles.serializeColumnHeaderState, \"\");\n\n            if (!string.IsNullOrEmpty(columnHeaderState))\n                JsonUtility.FromJsonOverwrite(columnHeaderState, headerState);\n\n            if (MultiColumnHeaderState.CanOverwriteSerializedFields(headerState, multiColumnHeader.state))\n                Column.OverwriteSerializedFields(headerState, multiColumnHeader.state);\n\n            for (int i = 0; i < multiColumnHeader.state.columns.Length; i++)\n            {\n                var filter = Col(i).filter;\n                if (filter == null)\n                    continue;\n\n                string filterState = SessionState.GetString(uid + Styles.serializeFilter + i, null);\n                if (string.IsNullOrEmpty(filterState))\n                    continue;\n\n                filter.DeserializeState(filterState);\n            }\n\n            string treeViewState = SessionState.GetString(uid + Styles.serializeTreeViewState, \"\");\n\n            if (!string.IsNullOrEmpty(treeViewState))\n                JsonUtility.FromJsonOverwrite(treeViewState, state);\n        }\n\n        public bool IsFilteredDirty()\n        {\n            return m_ChangedId != 0 && (m_ChangedId != GUIUtility.keyboardControl || !EditorGUIUtility.editingTextField);\n        }\n\n        public void Update()\n        {\n            bool needsReload = false;\n\n            if (m_DataStore != null)\n            {\n                // If we re-populated all data, we need to clear the cached items\n                // The data can also be fine, but needs a reload without having to rebuild it all (inactive/active objects changed)\n                if (m_DataStore.Repopulate(out needsReload))\n                    m_Items = null;\n\n                if (needsReload)\n                {\n                    Reload();\n                    return;\n                }\n            }\n\n            var rows = GetRows();\n            int first, last;\n\n            GetFirstAndLastVisibleRows(out first, out last);\n\n            bool changed = false;\n\n            if (last != -1)\n            {\n                for (int i = first; i <= last; i++)\n                {\n                    changed = changed || ((SerializedPropertyItem)rows[i]).GetData().Update();\n                }\n            }\n\n            if (changed)\n                Repaint();\n        }\n\n        protected override TreeViewItem BuildRoot()\n        {\n            return new SerializedPropertyItem(-1, -1, null);\n        }\n\n        // this gets called whenever someone issues a reload() call to the parent\n        protected override IList<TreeViewItem> BuildRows(TreeViewItem root)\n        {\n            if (m_Items == null)\n            {\n                var rawData = m_DataStore.GetElements();\n                m_Items = new List<TreeViewItem>(rawData.Length);\n\n                for (int i = 0; i < rawData.Length; i++)\n                {\n                    var item = new SerializedPropertyItem(rawData[i].objectId, 0, rawData[i]);\n                    m_Items.Add(item);\n                }\n            }\n\n            // filtering\n            IEnumerable<TreeViewItem> tmprows = m_Items;\n\n            if (!m_ShowInactiveObjects && m_ShowFilterGUI)\n                tmprows = m_Items.Where((TreeViewItem item) => { return ((SerializedPropertyItem)item).GetData().activeInHierarchy; });\n\n            if (m_bFilterSelection && m_ShowFilterGUI)\n            {\n                if (m_SelectionFilter == null)\n                    m_SelectionFilter = Selection.instanceIDs;\n                tmprows = m_Items.Where((TreeViewItem item) => { return m_SelectionFilter.Contains(item.id); });\n            }\n            else\n                m_SelectionFilter = null;\n\n            tmprows = Filter(tmprows);\n\n            var rows = tmprows.ToList();\n\n            if (multiColumnHeader.sortedColumnIndex >= 0)\n                Sort(rows, multiColumnHeader.sortedColumnIndex);\n\n            m_ChangedId = 0;\n\n            // We still need to setup the child parent information for the rows since this\n            // information is used by the TreeView internal logic (navigation, dragging etc)\n            TreeViewUtility.SetParentAndChildrenForItems(rows, root);\n\n            return rows;\n        }\n\n        protected override void RowGUI(RowGUIArgs args)\n        {\n            var item = (SerializedPropertyItem)args.item;\n\n            for (int i = 0; i < args.GetNumVisibleColumns(); ++i)\n            {\n                CellGUI(args.GetCellRect(i), item, args.GetColumn(i), ref args);\n            }\n        }\n\n        void CellGUI(Rect cellRect, SerializedPropertyItem item, int columnIndex, ref RowGUIArgs args)\n        {\n            Profiler.BeginSample(\"SerializedPropertyTreeView.CellGUI\");\n            CenterRectUsingSingleLineHeight(ref cellRect);\n            var ltd = item.GetData();\n            Column column = (Column)this.multiColumnHeader.GetColumn(columnIndex);\n\n            if (column.drawDelegate == DefaultDelegates.DrawName)\n            {\n                // default drawing\n                Profiler.BeginSample(\"SerializedPropertyTreeView.OnItemGUI.LabelField\");\n                using (new EditorGUI.DisabledScope(!ltd.activeInHierarchy))\n                {\n                    DefaultGUI.Label(cellRect, ltd.name, IsSelected(args.item.id), false);\n                }\n                Profiler.EndSample();\n            }\n            else if (column.drawDelegate != null)\n            {\n                SerializedProperty[] props = ltd.properties;\n                int depcnt = column.dependencyIndices != null ? column.dependencyIndices.Length : 0;\n\n                for (int i = 0; i < depcnt; i++)\n                    m_ColumnsInternal[columnIndex].dependencyProps[i] = props[column.dependencyIndices[i]];\n\n                // allow to capture tabs\n                if (args.item.id == state.lastClickedID && HasFocus() && columnIndex == multiColumnHeader.state.visibleColumns[multiColumnHeader.state.visibleColumns[0] == 0 ? 1 : 0])\n                    GUI.SetNextControlName(Styles.focusHelper);\n\n                SerializedProperty prop = ltd.properties[columnIndex];\n\n                EditorGUI.BeginChangeCheck();\n\n                Profiler.BeginSample(\"SerializedPropertyTreeView.OnItemGUI.drawDelegate\");\n\n                column.drawDelegate(cellRect, prop, m_ColumnsInternal[columnIndex].dependencyProps);\n\n                Profiler.EndSample();\n                if (EditorGUI.EndChangeCheck())\n                {\n                    // if we changed a value in a filtered column we'll have to reload the table\n                    m_ChangedId = ((column.filter != null) && column.filter.Active()) ? GUIUtility.keyboardControl : m_ChangedId;\n                    // update all selected items if the current row was part of the selection list\n                    ltd.Store();\n\n                    var selIds = GetSelection();\n\n                    if (selIds.Contains(ltd.objectId))\n                    {\n                        IList<TreeViewItem> rows = FindRows(selIds);\n\n                        Undo.RecordObjects(rows.Select(r => ((SerializedPropertyItem)r).GetData().serializedObject.targetObject).ToArray(), \"Modify Multiple Properties\");\n\n                        foreach (var r in rows)\n                        {\n                            if (r.id == args.item.id)\n                                continue;\n\n                            var data = ((SerializedPropertyItem)r).GetData();\n\n                            if (!IsEditable(data.serializedObject.targetObject))\n                                continue;\n\n                            if (column.copyDelegate != null)\n                                column.copyDelegate(data.properties[columnIndex], prop);\n                            else\n                                DefaultDelegates.CopyDefault(data.properties[columnIndex], prop);\n\n                            data.Store();\n                        }\n                    }\n                }\n            }\n            Profiler.EndSample();\n        }\n\n        private static bool IsEditable(Object target)\n        {\n            return ((target.hideFlags & HideFlags.NotEditable) == 0);\n        }\n\n        protected override void BeforeRowsGUI()\n        {\n            var rows = GetRows();\n            int first, last;\n            GetFirstAndLastVisibleRows(out first, out last);\n\n            if (last != -1)\n            {\n                for (int i = first; i <= last; i++)\n                    ((SerializedPropertyItem)rows[i]).GetData().Update();\n            }\n\n            // don't forget to refresh selected objects that got shoved off screen\n            var selected = FindRows(GetSelection());\n            foreach (SerializedPropertyItem sel in selected)\n                sel.GetData().Update();\n\n            base.BeforeRowsGUI();\n        }\n\n        public void OnFilterGUI(Rect r)\n        {\n            EditorGUI.BeginChangeCheck();\n\n            float fullWidth = r.width;\n            float windowPadding = r.x;\n            float toggleWidth = 16;\n\n            if (m_ShowFilterGUI)\n            {\n                r.width = toggleWidth;\n                m_bFilterSelection = EditorGUI.Toggle(r, m_bFilterSelection);\n                r.x += toggleWidth;\n                r.width = GUI.skin.label.CalcSize(SerializedPropertyTreeView.Styles.filterSelection).x;\n                EditorGUI.LabelField(r, SerializedPropertyTreeView.Styles.filterSelection);\n\n                r.x += r.width + 10;\n                r.width = toggleWidth;\n                m_ShowInactiveObjects = EditorGUI.Toggle(r, m_ShowInactiveObjects);\n                r.x += toggleWidth;\n                r.width = GUI.skin.label.CalcSize(SerializedPropertyTreeView.Styles.showInactiveObjects).x;\n                EditorGUI.LabelField(r, SerializedPropertyTreeView.Styles.showInactiveObjects);\n\n                r.width = Mathf.Min(fullWidth - (r.x + r.width), 300);\n                r.x = fullWidth - r.width + windowPadding;\n            }\n            else\n            {\n                r.width = 300;\n                r.x = fullWidth - r.width + windowPadding;\n            }\n\n            for (int i = 0; i < multiColumnHeader.state.columns.Length; i++)\n            {\n                if (!IsColumnVisible(i))\n                    continue;\n\n                Column c = Col(i);\n\n                if (c.filter != null && c.filter.GetType().Equals(typeof(SerializedPropertyFilters.Name)))\n                {\n                    c.filter.OnGUI(r);\n                }\n            }\n\n            if (EditorGUI.EndChangeCheck())\n                Reload();\n        }\n\n        protected override void SelectionChanged(IList<int> selectedIds)\n        {\n            Selection.instanceIDs = selectedIds.ToArray();\n        }\n\n        protected override void KeyEvent()\n        {\n            if (Event.current.type != EventType.KeyDown)\n                return;\n\n            // We always focus as this callback only fires when the name column is selected.\n            // Tabbing through the property columns never goes through here.\n            // Also note that we're not capturing the KeyCode Tab. There are 2 tab events,\n            // one for the keycode, and one for the character code. The keycode comes first,\n            // so if we change the focus based on the keycode, we never get the second character code\n            // event as the treeview loses focus and doesn't fire the callback. The second tab event\n            // then gets handled as an ordinary tab, leading to a double tab.\n            if (Event.current.character == '\\t')\n            {\n                GUI.FocusControl(Styles.focusHelper);\n                Event.current.Use();\n            }\n        }\n\n        void OnVisibleColumnChanged(MultiColumnHeader header)\n        {\n            Reload();\n        }\n\n        void OnSortingChanged(MultiColumnHeader multiColumnHeader)\n        {\n            var rows = GetRows();\n            Sort(rows, multiColumnHeader.sortedColumnIndex);\n        }\n\n        void Sort(IList<TreeViewItem> rows, int sortIdx)\n        {\n            Debug.Assert(sortIdx >= 0);\n\n            bool ascend = multiColumnHeader.IsSortedAscending(sortIdx);\n            var comp = Col(sortIdx).compareDelegate;\n            var myRows = rows as List<TreeViewItem>;\n\n            System.Comparison<TreeViewItem> sortAscend, sortDescend;\n            if (comp == null)\n            {\n                return;\n            }\n            else if (comp == DefaultDelegates.CompareName) // special case for sorting by the object name\n            {\n                sortAscend = (TreeViewItem lhs, TreeViewItem rhs) =>\n                {\n                    return EditorUtility.NaturalCompare(((SerializedPropertyItem)lhs).GetData().name, ((SerializedPropertyItem)rhs).GetData().name);\n                };\n                sortDescend = (TreeViewItem lhs, TreeViewItem rhs) =>\n                {\n                    return -EditorUtility.NaturalCompare(((SerializedPropertyItem)lhs).GetData().name, ((SerializedPropertyItem)rhs).GetData().name);\n                };\n            }\n            else\n            {\n                sortAscend = (TreeViewItem lhs, TreeViewItem rhs) =>\n                {\n                    return comp(((SerializedPropertyItem)lhs).GetData().properties[sortIdx], ((SerializedPropertyItem)rhs).GetData().properties[sortIdx]);\n                };\n                sortDescend = (TreeViewItem lhs, TreeViewItem rhs) =>\n                {\n                    return -comp(((SerializedPropertyItem)lhs).GetData().properties[sortIdx], ((SerializedPropertyItem)rhs).GetData().properties[sortIdx]);\n                };\n            }\n\n            myRows.Sort(ascend ? sortAscend : sortDescend);\n        }\n\n        IEnumerable<TreeViewItem> Filter(IEnumerable<TreeViewItem> rows)\n        {\n            var tmp = rows;\n            int cnt = m_ColumnsInternal.Length;\n            for (int i = 0; i < cnt; i++)\n            {\n                if (!IsColumnVisible(i))\n                    continue;\n\n                Column c = Col(i);\n                int idx = i;\n                if (c.filter != null)\n                {\n                    if (!c.filter.Active())\n                        continue;\n\n                    if (c.filter.GetType().Equals(typeof(SerializedPropertyFilters.Name)))\n                    {\n                        var f = (SerializedPropertyFilters.Name)c.filter;\n                        tmp = tmp.Where((TreeViewItem item) => { return f.Filter(((SerializedPropertyItem)item).GetData().name); });\n                    }\n                    else\n                    {\n                        tmp = tmp.Where((TreeViewItem item) => { return c.filter.Filter(((SerializedPropertyItem)item).GetData().properties[idx]); });\n                    }\n                }\n            }\n\n            return tmp;\n        }\n\n        private bool IsColumnVisible(int idx)\n        {\n            for (int i = 0; i < multiColumnHeader.state.visibleColumns.Length; i++)\n                if (multiColumnHeader.state.visibleColumns[i] == idx)\n                    return true;\n\n            return false;\n        }\n\n        // casting helper\n        private Column Col(int idx) { return (Column)multiColumnHeader.state.columns[idx]; }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SerializedProperty.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing UnityEngine.Bindings;\nusing UnityEngine.Serialization;\n\nusing UnityObject = UnityEngine.Object;\nusing System.Reflection;\nusing System.Text.RegularExpressions;\nusing RefId = System.Int64;\n\nnamespace UnityEditor\n{\n    // This MUST be kept synchronized with the enum in SerializedProperty.h\n    // Type of a [[SerializedProperty]].\n    public enum SerializedPropertyType\n    {\n        // Struct, array or class that is serialized by value.\n        Generic = -1,\n        // Integer property.\n        Integer = 0,\n        // Boolean property.\n        Boolean = 1,\n        // Float property.\n        Float = 2,\n        // String property.\n        String = 3,\n        // Color property.\n        Color = 4,\n        // Reference to another object.\n        ObjectReference = 5,\n        // [[LayerMask]] property.\n        LayerMask = 6,\n        // Enumeration property.\n        Enum = 7,\n        // 2D vector property.\n        Vector2 = 8,\n        // 3D vector property.\n        Vector3 = 9,\n        // 4D vector property.\n        Vector4 = 10,\n        // Rectangle property.\n        Rect = 11,\n        // Array size property.\n        ArraySize = 12,\n        // Character property.\n        Character = 13,\n        // AnimationCurve property.\n        AnimationCurve = 14,\n\n        // Bounds property.\n        Bounds = 15,\n\n        // Gradient property.\n        Gradient = 16,\n\n        // Quaternion property.\n        Quaternion = 17,\n\n        ExposedReference = 18,\n\n        // Fixed Buffer size property\n        FixedBufferSize = 19,\n\n        // 2D int vector property.\n        Vector2Int = 20,\n\n        // 3D int vector property.\n        Vector3Int = 21,\n\n        // Rectangle with int property.\n        RectInt = 22,\n\n        // Bounds with int property.\n        BoundsInt = 23,\n\n        // Managed reference property.\n        ManagedReference = 24,\n\n        // Hash128 value\n        Hash128 = 25,\n\n        // Rendering Layer Mask property\n        RenderingLayerMask = 26\n    }\n\n    // This enum exposes extra detail, because SerializedPropertyType classifies all numeric types as Integer or Float\n    public enum SerializedPropertyNumericType\n    {\n        Unknown = 0,\n\n        // SerializedPropertyType.Integer covers all these types\n        Int8 = 1,   // sbyte\n        UInt8 = 2,  // byte\n        Int16 = 3,  // short\n        UInt16 = 4, // ushort\n        Int32 = 5,  // int\n        UInt32 = 6, // uint\n        Int64 = 7,  // long\n        UInt64 = 8, // ulong\n\n        // SerializedPropertyType.Float includes both Float and Double\n        Float = 100,\n        Double = 101,\n    }\n\n    [NativeHeader(\"Editor/Src/Utility/SerializedProperty.h\")]\n    [NativeHeader(\"Editor/Src/Utility/SerializedProperty.bindings.h\")]\n    [StructLayout(LayoutKind.Sequential)]\n    public class SerializedProperty : IDisposable\n    {\n        IntPtr m_NativePropertyPtr;\n\n        private SerializedProperty(IntPtr nativePropertyPtr)\n        {\n            m_NativePropertyPtr  = nativePropertyPtr;\n        }\n\n        // This is so the garbage collector won't clean up SerializedObject behind the scenes.\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal SerializedObject m_SerializedObject;\n        internal string m_CachedLocalizedDisplayName = \"\";\n        string m_CachedTooltip;\n\n        internal SerializedProperty() {}\n        ~SerializedProperty() { Dispose(); }\n\n        // [[SerializedObject]] this property belongs to (RO).\n        public SerializedObject serializedObject { get { return m_SerializedObject; } }\n\n        public UnityObject exposedReferenceValue\n        {\n            get\n            {\n                if (propertyType != SerializedPropertyType.ExposedReference)\n                    return null;\n\n                var defaultValue = FindPropertyRelative(\"defaultValue\");\n                if (defaultValue == null)\n                    return null;\n\n                var returnedValue = defaultValue.objectReferenceValue;\n\n                var exposedPropertyTable = serializedObject.context as IExposedPropertyTable;\n                if (exposedPropertyTable != null)\n                {\n                    SerializedProperty exposedName = FindPropertyRelative(\"exposedName\");\n                    var propertyName = new PropertyName(exposedName.stringValue);\n\n                    bool propertyFoundInTable = false;\n                    var objReference = exposedPropertyTable.GetReferenceValue(propertyName, out propertyFoundInTable);\n                    if (propertyFoundInTable == true)\n                        returnedValue = objReference;\n                }\n                return returnedValue;\n            }\n\n            set\n            {\n                if (propertyType != SerializedPropertyType.ExposedReference)\n                {\n                    throw new System.InvalidOperationException(\"Attempting to set the reference value on a SerializedProperty that is not an ExposedReference\");\n                }\n\n                var defaultValue = FindPropertyRelative(\"defaultValue\");\n\n                var exposedPropertyTable = serializedObject.context as IExposedPropertyTable;\n                if (exposedPropertyTable == null)\n                {\n                    defaultValue.objectReferenceValue = value;\n                    defaultValue.serializedObject.ApplyModifiedProperties();\n                    return;\n                }\n\n                SerializedProperty exposedName = FindPropertyRelative(\"exposedName\");\n\n                var exposedId = exposedName.stringValue;\n                if (String.IsNullOrEmpty(exposedId))\n                {\n                    exposedId = UnityEditor.GUID.Generate().ToString();\n                    exposedName.stringValue = exposedId;\n                }\n                var propertyName = new PropertyName(exposedId);\n                exposedPropertyTable.SetReferenceValue(propertyName, value);\n            }\n        }\n\n        internal bool isScript\n        {\n            get { return type == \"PPtr<MonoScript>\"; }\n        }\n\n        internal string localizedDisplayName\n        {\n            [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n            get\n            {\n                if (!this.isValidDisplayNameCache)\n                {\n                    this.isValidDisplayNameCache = true;\n                    m_CachedLocalizedDisplayName = L10n.Tr(displayName, m_SerializedObject.targetObject);\n                }\n                return m_CachedLocalizedDisplayName;\n            }\n        }\n\n        internal string[] enumLocalizedDisplayNames\n        {\n            get\n            {\n                string[] names = enumDisplayNames;\n                var res = new string[names.Length];\n                for (var i = 0; i < res.Length; ++i)\n                {\n                    res[i] = L10n.Tr(names[i], m_SerializedObject.targetObject);\n                }\n                return res;\n            }\n        }\n\n        // Returns a copy of the SerializedProperty iterator in its current state. This is useful if you want to keep a reference to the current property but continue with the iteration.\n        public SerializedProperty Copy()\n        {\n            SerializedProperty property = CopyInternal();\n            property.m_SerializedObject = m_SerializedObject;\n            property.m_CachedLocalizedDisplayName = m_CachedLocalizedDisplayName;\n            property.m_CachedTooltip = m_CachedTooltip;\n            return property;\n        }\n\n        // Retrieves the SerializedProperty at a relative path to the current property.\n        public SerializedProperty FindPropertyRelative(string relativePropertyPath)\n        {\n            SerializedProperty prop = Copy();\n            if (prop.FindPropertyRelativeInternal(relativePropertyPath))\n                return prop;\n            else\n                return null;\n        }\n\n        // Retrieves an iterator that allows you to iterator over the current nexting of a serialized property.\n        public System.Collections.IEnumerator GetEnumerator()\n        {\n            if (isArray)\n            {\n                for (int i = 0; i < arraySize; i++)\n                {\n                    yield return GetArrayElementAtIndex(i);\n                }\n            }\n            else\n            {\n                var end = GetEndProperty();\n                while (NextVisible(true) && !SerializedProperty.EqualContents(this, end))\n                {\n                    yield return this;\n                }\n            }\n        }\n\n        // Returns the element at the specified index in the array.\n        public SerializedProperty GetArrayElementAtIndex(int index)\n        {\n            SerializedProperty prop = Copy();\n            if (prop.GetArrayElementAtIndexInternal(index))\n                return prop;\n            else\n                return null;\n        }\n\n        internal void SetToValueOfTarget(UnityObject target)\n        {\n            using (SerializedObject targetObject = new SerializedObject(target))\n            {\n                using (SerializedProperty targetProperty = targetObject.FindProperty(propertyPath))\n                {\n                    if (targetProperty == null)\n                    {\n                        Debug.LogError(target.name + \" does not have the property \" + propertyPath);\n                        return;\n                    }\n\n                    try\n                    {\n                        boxedValue = targetProperty.boxedValue;\n                    }\n                    catch (NotSupportedException ex)\n                    {\n                        // Previous implementation silently did nothing for unsupported types, now moving towards more strict error handling with this warning\n                        Debug.LogWarning(ex.Message);\n                    }\n                }\n            }\n        }\n\n        public System.Object boxedValue\n        {\n            get\n            {\n                switch (propertyType)\n                {\n                    case SerializedPropertyType.Generic: return structValue;\n                    case SerializedPropertyType.Enum: goto case SerializedPropertyType.Integer;\n                    case SerializedPropertyType.Integer:\n                    {\n                        switch (numericType)\n                        {\n                            case SerializedPropertyNumericType.UInt64:\n                                return ulongValue;\n                            case SerializedPropertyNumericType.Int64:\n                                return longValue;\n                            case SerializedPropertyNumericType.UInt32:\n                                return uintValue;\n                            case SerializedPropertyNumericType.UInt16:\n                                return (System.UInt16)uintValue;\n                            case SerializedPropertyNumericType.Int16:\n                                return (System.Int16)intValue;\n                            case SerializedPropertyNumericType.UInt8:\n                                return (System.Byte)uintValue;\n                            case SerializedPropertyNumericType.Int8:\n                                return (System.SByte)intValue;\n                            default:\n                                return intValue;\n                        }\n                    }\n                    case SerializedPropertyType.Boolean: return boolValue;\n                    case SerializedPropertyType.Float:\n                    {\n                        if (numericType == SerializedPropertyNumericType.Double)\n                            return doubleValue;\n                        else\n                            return floatValue;\n                    }\n\n                    case SerializedPropertyType.String: return stringValue;\n                    case SerializedPropertyType.Color: return colorValue;\n                    case SerializedPropertyType.ObjectReference: return objectReferenceValue;\n                    case SerializedPropertyType.LayerMask: return (LayerMask)intValue;\n                    case SerializedPropertyType.RenderingLayerMask: return (RenderingLayerMask)uintValue;\n                    case SerializedPropertyType.Vector2: return vector2Value;\n                    case SerializedPropertyType.Vector3: return vector3Value;\n                    case SerializedPropertyType.Vector4: return vector4Value;\n                    case SerializedPropertyType.Rect: return rectValue;\n                    case SerializedPropertyType.ArraySize: return intValue;\n                    case SerializedPropertyType.Character: return (System.UInt16)uintValue;\n                    case SerializedPropertyType.AnimationCurve: return animationCurveValue;\n                    case SerializedPropertyType.Bounds: return boundsValue;\n                    case SerializedPropertyType.Gradient: return gradientValue;\n                    case SerializedPropertyType.Quaternion: return quaternionValue;\n                    case SerializedPropertyType.ExposedReference: return exposedReferenceValue;\n                    case SerializedPropertyType.FixedBufferSize: return intValue;\n                    case SerializedPropertyType.Vector2Int: return vector2IntValue;\n                    case SerializedPropertyType.Vector3Int: return vector3IntValue;\n                    case SerializedPropertyType.RectInt: return rectIntValue;\n                    case SerializedPropertyType.BoundsInt: return boundsIntValue;\n                    case SerializedPropertyType.ManagedReference: return managedReferenceValue;\n                    case SerializedPropertyType.Hash128: return hash128Value;\n\n                    default:\n                        throw new NotSupportedException(string.Format(\"The boxedValue property is not supported on \\\"{0}\\\" because it has an unsupported propertyType {1}.\", propertyPath, propertyType));\n                }\n            }\n\n            set\n            {\n                if (value == null && !IsBoxedValueNullable())\n                    throw new ArgumentException(\"Argument to boxedValue cannot be null\");\n\n                try\n                {\n                    // Note: typecast from System.Object enforces strict match between the boxed type and cast type.\n                    // The Convert API is used for cases where multiple types can safely and commonly be converted to the underlying SerializedProperty type.\n                    switch (propertyType)\n                    {\n                        case SerializedPropertyType.Generic: structValue = value; break;\n                        case SerializedPropertyType.Enum: goto case SerializedPropertyType.Integer;\n                        case SerializedPropertyType.ArraySize: goto case SerializedPropertyType.Integer;\n                        case SerializedPropertyType.Integer:\n                        {\n                            //Convert so that simple mismatches like sbyte to int are accepted\n                            if (numericType == SerializedPropertyNumericType.UInt64)\n                            {\n                                ulongValue = Convert.ToUInt64(value);\n                            }\n                            else\n                            {\n                                // all smaller numeric datatypes fit into the range of long and are cast back to the correct type internally\n                                longValue = Convert.ToInt64(value);\n                            }\n                            break;\n                        }\n                        case SerializedPropertyType.Boolean: boolValue = (bool)value; break;\n                        case SerializedPropertyType.Float:\n                        {\n                            if (numericType == SerializedPropertyNumericType.Double)\n                                doubleValue = Convert.ToDouble(value);\n                            else\n                                floatValue = Convert.ToSingle(value);\n                            break;\n                        }\n                        case SerializedPropertyType.String: stringValue = (string)value; break;\n                        case SerializedPropertyType.Color: colorValue = (Color)value; break;\n                        case SerializedPropertyType.ObjectReference: objectReferenceValue = (UnityEngine.Object)value; break;\n                        case SerializedPropertyType.LayerMask:\n                        {\n                            try\n                            {\n                                intValue = ((LayerMask)value).value;\n                            }\n                            catch (InvalidCastException)\n                            {\n                                intValue = Convert.ToInt32(value);\n                            }\n                            break;\n                        }\n                        case SerializedPropertyType.RenderingLayerMask:\n                        {\n                            try\n                            {\n                                uintValue = ((RenderingLayerMask)value).value;\n                            }\n                            catch (InvalidCastException)\n                            {\n                                uintValue = Convert.ToUInt32(value);\n                            }\n                            break;\n                        }\n                        case SerializedPropertyType.Vector2: vector2Value = (Vector2)value; break;\n                        case SerializedPropertyType.Vector3: vector3Value = (Vector3)value; break;\n                        case SerializedPropertyType.Vector4: vector4Value = (Vector4)value; break;\n                        case SerializedPropertyType.Rect: rectValue = (Rect)value; break;\n                        case SerializedPropertyType.Character: uintValue = Convert.ToUInt16(value); break;\n                        case SerializedPropertyType.AnimationCurve: animationCurveValue = (AnimationCurve)value; break;\n                        case SerializedPropertyType.Bounds: boundsValue = (Bounds)value; break;\n                        case SerializedPropertyType.Gradient: gradientValue = (Gradient)value; break;\n                        case SerializedPropertyType.Quaternion: quaternionValue = (Quaternion)value; break;\n                        case SerializedPropertyType.ExposedReference: exposedReferenceValue = (UnityEngine.Object)value; break;\n                        case SerializedPropertyType.Vector2Int: vector2IntValue = (Vector2Int)value; break;\n                        case SerializedPropertyType.Vector3Int: vector3IntValue = (Vector3Int)value; break;\n                        case SerializedPropertyType.RectInt: rectIntValue = (RectInt)value; break;\n                        case SerializedPropertyType.BoundsInt: boundsIntValue = (BoundsInt)value; break;\n                        case SerializedPropertyType.ManagedReference: managedReferenceValue = value; break;\n                        case SerializedPropertyType.Hash128: hash128Value = (Hash128)value; break;\n\n                        default: // FixedBufferSize is read-only\n                            throw new NotSupportedException(string.Format(\"Set on boxedValue property is not supported on \\\"{0}\\\" because it has an unsupported propertyType {1}.\", propertyPath, propertyType));\n                    }\n                }\n                catch (InvalidCastException)\n                {\n                    throw new InvalidCastException(string.Format(\"The value passed to boxedValue on \\\"{0}\\\" cannot be cast to expected propertyType {1}.\", propertyPath, propertyType));\n                }\n            }\n        }\n\n\n        private bool IsBoxedValueNullable()\n        {\n            return propertyType == SerializedPropertyType.ManagedReference || propertyType == SerializedPropertyType.ObjectReference\n                || propertyType == SerializedPropertyType.ExposedReference || propertyType == SerializedPropertyType.String;\n        }\n\n        extern private bool EndOfData();\n        extern private void SyncSerializedObjectVersion();\n\n        [Flags]\n        internal enum VerifyFlags\n        {\n            None = 0,\n            IteratorNotAtEnd = 1 << 1,\n        }\n\n        [MethodImpl(256)]\n        internal void Verify(VerifyFlags verifyFlags = VerifyFlags.None)\n        {\n            if (unsafeMode)\n                return;\n\n            if (m_NativePropertyPtr == IntPtr.Zero)\n                throw new NullReferenceException(\"SerializedProperty has been Disposed.\");\n\n            if(m_SerializedObject == null || m_SerializedObject.m_NativeObjectPtr == IntPtr.Zero)\n                throw new NullReferenceException(\"SerializedObject of SerializedProperty has been Disposed.\");\n\n            SyncSerializedObjectVersion();\n\n            if ((verifyFlags & VerifyFlags.IteratorNotAtEnd) == VerifyFlags.IteratorNotAtEnd && EndOfData())\n                throw new InvalidOperationException(\"The operation is not possible when moved past all properties (Next returned false)\");\n        }\n\n        // Move to next visible property.\n        public bool NextVisible(bool enterChildren)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            return NextVisibleInternal(enterChildren);\n        }\n\n        [NativeName(\"NextVisible\")]\n        extern private bool NextVisibleInternal(bool enterChildren);\n\n        // Remove all elements from the array.\n        public void ClearArray()\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            ClearArrayInternal();\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::ClearArray\", HasExplicitThis = true)]\n        extern private void ClearArrayInternal();\n\n        [NativeName(\"FindProperty\")]\n        extern internal bool FindPropertyInternal(string propertyPath);\n\n        [NativeName(\"FindPropertyIgnoreCase\")]\n        extern internal bool FindPropertyIgnoreCaseInternal(string propertyPath);\n\n        [NativeName(\"FindFirstPropertyFromManagedReferencePath\")]\n        extern internal bool FindFirstPropertyFromManagedReferencePathInternal(string managedReferencePath);\n\n        [ThreadAndSerializationSafe()]\n        public void Dispose()\n        {\n            if (m_NativePropertyPtr != IntPtr.Zero)\n            {\n                Internal_Destroy(m_NativePropertyPtr);\n                m_NativePropertyPtr = IntPtr.Zero;\n            }\n        }\n\n        [FreeFunction(\"SerializedPropertyBindings::Internal_Destroy\", IsThreadSafe = true)]\n        private extern static void Internal_Destroy(IntPtr ptr);\n\n        // See if contained serialized properties are equal.\n        public static bool EqualContents(SerializedProperty x, SerializedProperty y)\n        {\n            if (x == null)\n                return (y == null || y.m_NativePropertyPtr == IntPtr.Zero);\n            if (y == null)\n                return (x == null || x.m_NativePropertyPtr == IntPtr.Zero);\n\n            x.Verify();\n            y.Verify();\n\n            return EqualContentsInternal(x, y);\n        }\n\n        [FreeFunction(\"SerializedPropertyBindings::EqualContentsInternal\")]\n        private extern static bool EqualContentsInternal(SerializedProperty x, SerializedProperty y);\n\n\n        // See if raw data inside both serialized property is equal.\n        public static bool DataEquals(SerializedProperty x, SerializedProperty y)\n        {\n            if (x == null)\n                return (y == null || y.m_NativePropertyPtr == IntPtr.Zero);\n            if (y == null)\n                return (x == null || x.m_NativePropertyPtr == IntPtr.Zero);\n\n            x.Verify();\n            y.Verify();\n\n            return DataEqualsInternal(x, y);\n        }\n\n        // See if versions inside both property serialized objects are equal.\n        internal static bool VersionEquals(SerializedProperty x, SerializedProperty y)\n        {\n            if (x == null)\n                return (y == null || y.m_NativePropertyPtr == IntPtr.Zero);\n            if (y == null)\n                return (x == null || x.m_NativePropertyPtr == IntPtr.Zero);\n\n            return SerializedObject.VersionEquals(x.serializedObject, y.serializedObject);\n        }\n\n        [FreeFunction(\"SerializedPropertyBindings::DataEqualsInternal\")]\n        private extern static bool DataEqualsInternal(SerializedProperty x, SerializedProperty y);\n\n        // Does this property represent multiple different values due to multi-object editing? (RO)\n        public bool hasMultipleDifferentValues\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return HasMultipleDifferentValuesInternal() != 0;\n            }\n        }\n\n        internal int hasMultipleDifferentValuesBitwise\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return HasMultipleDifferentValuesInternal();\n            }\n        }\n\n        [NativeName(\"HasMultipleDifferentValues\")]\n        private extern int HasMultipleDifferentValuesInternal();\n\n        internal void SetBitAtIndexForAllTargetsImmediate(int index, bool value)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            SetBitAtIndexForAllTargetsImmediateInternal(index, value);\n        }\n\n        [NativeName(\"SetBitAtIndexForAllTargetsImmediate\")]\n        private extern void SetBitAtIndexForAllTargetsImmediateInternal(int index, bool value);\n\n        // Nice display name of the property (RO)\n        public string displayName\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetMangledNameInternal();\n            }\n        }\n\n        [NativeName(\"GetMangledName\")]\n        private extern string GetMangledNameInternal();\n\n        // Name of the property (RO)\n        public string name\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetNameInternal();\n            }\n        }\n\n        [FreeFunction(\"SerializedPropertyBindings::GetNameInternal\", HasExplicitThis = true)]\n        private extern string GetNameInternal();\n\n        // Type name of the property (RO)\n        public string type\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetSerializedPropertyTypeNameInternal();\n            }\n        }\n\n        [NativeName(\"GetSerializedPropertyTypeName\")]\n        private extern string GetSerializedPropertyTypeNameInternal();\n\n        // Type name of the element of an Array property (RO)\n        public string arrayElementType\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetSerializedPropertyArrayElementTypeNameInternal();\n            }\n        }\n\n        [NativeName(\"GetSerializedPropertyArrayElementTypeName\")]\n        private extern string GetSerializedPropertyArrayElementTypeNameInternal();\n\n        // Tooltip of the property (RO)\n        public string tooltip\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                if (!isValidTooltipCache)\n                {\n                    isValidTooltipCache = true;\n                    m_CachedTooltip = GetTooltipInternal();\n                    if (string.IsNullOrEmpty(m_CachedTooltip))\n                        m_CachedTooltip = ScriptAttributeUtility.GetHandler(this).tooltip ?? string.Empty;\n                }\n\n                return m_CachedTooltip;\n            }\n        }\n\n        [NativeName(\"GetTooltip\")]\n        private extern string GetTooltipInternal();\n\n        // Nesting depth of the property (RO)\n        public int depth\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetDepthInternal();\n            }\n        }\n\n        [NativeName(\"GetDepth\")]\n        private extern int GetDepthInternal();\n\n        // Full path of the property (RO)\n        private string m_PropertyPath = \"\";\n        private int m_PropertyPathHash = 0;\n        public string propertyPath\n        {\n            get\n            {\n                Verify();\n                int hash = GetHashCodeForPropertyPathInternal();\n                if (m_PropertyPathHash != hash)\n                {\n                    m_PropertyPathHash = hash;\n                    m_PropertyPath = GetPropertyPathInternal();\n                }\n                return m_PropertyPath;\n            }\n        }\n\n        [NativeName(\"GetPropertyPath\")]\n        private extern string GetPropertyPathInternal();\n\n        [NativeName(\"GetHashCodeForPropertyPath\")]\n        private extern int GetHashCodeForPropertyPathInternal();\n\n        internal int hashCodeForPropertyPathWithoutArrayIndex\n        {\n            get\n            {\n                Verify();\n                return GetHashCodeForPropertyPathWithoutArrayIndexInternal();\n            }\n        }\n\n        internal int hashCodeForPropertyPath\n        {\n            get\n            {\n                Verify();\n                return GetHashCodeForPropertyPathInternal();\n            }\n        }\n\n        [NativeName(\"GetHashCodeForPropertyPathWithoutArrayIndex\")]\n        private extern int GetHashCodeForPropertyPathWithoutArrayIndexInternal();\n\n        // Is this property editable? (RO)\n        public bool editable\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetEditableInternal();\n            }\n        }\n\n        [NativeName(\"GetEditable\")]\n        private extern bool GetEditableInternal();\n\n        [NativeName(\"IsReorderable\")]\n        internal extern bool IsReorderable();\n\n        // Is this property animated? (RO)\n        public bool isAnimated\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return IsAnimatedInternal();\n            }\n        }\n\n        [NativeName(\"IsAnimated\")]\n        private extern bool IsAnimatedInternal();\n\n        // Is this property candidate? (RO)\n        internal bool isCandidate\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return IsCandidateInternal();\n            }\n        }\n\n        [NativeName(\"IsCandidate\")]\n        private extern bool IsCandidateInternal();\n\n        // Is this property keyed? (RO)\n        internal bool isKey\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return IsKeyInternal();\n            }\n        }\n\n        [NativeName(\"IsKey\")]\n        private extern bool IsKeyInternal();\n\n        [NativeName(\"IsLiveModified\")]\n        private extern bool IsLiveModified();\n\n        // Is this property live modified?\n        internal bool isLiveModified\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return IsLiveModified();\n            }\n        }\n\n        // Is this property expanded in the inspector?\n        public bool isExpanded\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetIsExpandedInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetIsExpandedInternal(value);\n            }\n        }\n\n        [NativeName(\"GetIsExpanded\")]\n        private extern bool GetIsExpandedInternal();\n\n        [NativeName(\"SetIsExpanded\")]\n        private extern void SetIsExpandedInternal(bool value);\n\n        // Does it have child properties? (RO)\n        public bool hasChildren\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return HasChildrenInternal();\n            }\n        }\n\n        [NativeName(\"HasChildren\")]\n        private extern bool HasChildrenInternal();\n\n        // Does it have visible child properties? (RO)\n        public bool hasVisibleChildren\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return HasVisibleChildrenInternal();\n            }\n        }\n\n        [NativeName(\"HasVisibleChildren\")]\n        private extern bool HasVisibleChildrenInternal();\n\n        // Is property part of a prefab instance? (RO)\n        public bool isInstantiatedPrefab\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetIsInstantiatedPrefabInternal();\n            }\n        }\n\n        [NativeName(\"GetIsInstantiatedPrefab\")]\n        private extern bool GetIsInstantiatedPrefabInternal();\n\n        /// <summary>\n        /// A property can reference any element in the parent SerializedObject.\n        /// In the context of polymorphic serialization, those elements might be dynamic instances\n        /// not statically discoverable from the class type.\n        /// We need to take a very specific code path when we try to get the type of a field\n        /// inside such a dynamic instance through a SerializedProperty.\n        ///\n        /// @see UnityEditor.ScriptAttributeUtility.GetFieldInfoAndStaticTypeFromProperty\n        /// </summary>\n        internal bool isReferencingAManagedReferenceField\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return IsReferencingAManagedReferenceFieldInternal();\n            }\n        }\n\n        // Useful in the same context as 'isReferencingAManagedReferenceField'.\n        [NativeName(\"IsReferencingAManagedReferenceField\")]\n        private extern bool IsReferencingAManagedReferenceFieldInternal();\n\n        /// <summary>\n        /// Returns the FQN in the format \"&lt;assembly name&gt; &lt;full class name&gt;\" for the current dynamic managed reference.\n        /// </summary>\n        /// <returns></returns>\n        // Useful in the same context as 'isReferencingAManagedReferenceField'.\n        [NativeName(\"GetFullyQualifiedTypenameForCurrentTypeTree\")]\n        internal extern string GetFullyQualifiedTypenameForCurrentTypeTreeInternal();\n\n        /// <summary>\n        /// Returns the path of the current field on the dynamic reference class.\n        /// </summary>\n        // Useful in the same context as 'isReferencingAManagedReferenceField'.\n        [NativeName(\"GetPropertyPathInCurrentManagedTypeTree\")]\n        internal extern string GetPropertyPathInCurrentManagedTypeTreeInternal();\n\n\n        /// <summary>\n        /// If the current field is on a SerializeReference instance this returns the path\n        /// of the field relative the ManagedReferenceRegistry. managedReferences[refId].field\n        /// </summary>\n        internal string managedReferencePropertyPath\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetManagedReferencePropertyPathInternal();\n            }\n        }\n\n        /// <summary>\n        /// Returns the path of the current field relative to the managed reference registry managedReferences[refId].\n        /// </summary>\n        // Useful in the same context as 'isReferencingAManagedReferenceField'.\n        [NativeName(\"GetManagedReferencePropertyPath\")]\n        internal extern string GetManagedReferencePropertyPathInternal();\n\n        // Is property's value different from the prefab it belongs to?\n        public bool prefabOverride\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetPrefabOverrideInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetPrefabOverrideInternal(value);\n            }\n        }\n\n        [NativeName(\"GetPrefabOverride\")]\n        private extern bool GetPrefabOverrideInternal();\n\n        [NativeName(\"SetPrefabOverride\")]\n        private extern void SetPrefabOverrideInternal(bool value);\n\n        // Is property a default override property which is enforced to always be overridden? (RO)\n        public bool isDefaultOverride\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetIsDefaultOverrideInternal();\n            }\n        }\n\n        [NativeName(\"IsDefaultOverride\")]\n        private extern bool GetIsDefaultOverrideInternal();\n\n        // Is property a driven property (using RectTransform driven properties)? (RO)\n        internal bool isDrivenRectTransformProperty\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetIsDrivenRectTransformPropertyInternal();\n            }\n        }\n\n        [NativeName(\"IsDrivenRectTransformProperty\")]\n        private extern bool GetIsDrivenRectTransformPropertyInternal();\n\n        // Type of this property (RO).\n        public SerializedPropertyType propertyType\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return (SerializedPropertyType)GetSerializedPropertyTypeInternal();\n            }\n        }\n\n        [NativeName(\"GetSerializedPropertyType\")]\n        private extern int GetSerializedPropertyTypeInternal();\n\n        public SerializedPropertyNumericType numericType\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return (SerializedPropertyNumericType)GetNumericTypeInternal();\n            }\n        }\n\n        [NativeName(\"GetNumericType\")]\n        private extern int GetNumericTypeInternal();\n\n        // Value of an integer property.\n        public int intValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return (int)GetIntValueInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetIntValueInternal(value);\n            }\n        }\n\n        [NativeName(\"GetIntValue\")]\n        private extern long GetIntValueInternal();\n\n        [NativeName(\"SetIntValue\")]\n        private extern void SetIntValueInternal(long value);\n\n        // Value of an long property.\n        public long longValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetIntValueInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetIntValueInternal(value);\n            }\n        }\n\n        public ulong ulongValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return (ulong)GetIntValueInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetIntValueInternal((long)value);\n            }\n        }\n\n        public uint uintValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return (uint)GetIntValueInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetIntValueInternal(value);\n            }\n        }\n\n        // Value of a boolean property.\n        public bool boolValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetBoolValueInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetBoolValueInternal(value);\n            }\n        }\n\n        [NativeName(\"GetBoolValue\")]\n        private extern bool GetBoolValueInternal();\n\n        [NativeName(\"SetBoolValue\")]\n        private extern void SetBoolValueInternal(bool value);\n\n        // Value of a float property.\n        public float floatValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return (float)GetFloatValueInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetFloatValueInternal(value);\n            }\n        }\n\n        [NativeName(\"GetFloatValue\")]\n        private extern double GetFloatValueInternal();\n\n        [NativeName(\"SetFloatValue\")]\n        private extern void SetFloatValueInternal(double value);\n\n        internal double[] allDoubleValues\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetAllFloatValues();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetAllFloatValuesImmediate(value);\n            }\n        }\n        internal long[] allLongValues\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetAllIntValues();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetAllIntValuesImmediate(value);\n            }\n        }\n        extern double[] GetAllFloatValues();\n        extern void SetAllFloatValuesImmediate(double[] value);\n        extern long[] GetAllIntValues();\n        extern void SetAllIntValuesImmediate(long[] value);\n\n        // Value of a double property.\n        public double doubleValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetFloatValueInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetFloatValueInternal(value);\n            }\n        }\n\n        // Value of a string property.\n        public string stringValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetStringValueInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetStringValueInternal(value);\n            }\n        }\n\n        [NativeName(\"GetStringValue\")]\n        private extern string GetStringValueInternal();\n\n        [NativeName(\"SetStringValue\")]\n        private extern void SetStringValueInternal(string value);\n\n        // Value of a color property.\n        public Color colorValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetColorValueInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetColorValueInternal(value);\n            }\n        }\n\n        [NativeName(\"GetColorValue\")]\n        private extern Color GetColorValueInternal();\n\n        [NativeName(\"SetColorValue\")]\n        private extern void SetColorValueInternal(Color value);\n\n        // Value of a animation curve property.\n        public AnimationCurve animationCurveValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetAnimationCurveValueCopyInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetAnimationCurveValueInternal(value);\n            }\n        }\n\n        [NativeName(\"GetAnimationCurveValueCopy\")]\n        private extern AnimationCurve GetAnimationCurveValueCopyInternal();\n\n        [NativeName(\"SetAnimationCurveValue\")]\n        private extern void SetAnimationCurveValueInternal(AnimationCurve value);\n\n        // Value of a gradient property.\n        public Gradient gradientValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetGradientValueCopyInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetGradientValueInternal(value);\n            }\n        }\n\n        [NativeName(\"GetGradientValueCopy\")]\n        private extern Gradient GetGradientValueCopyInternal();\n\n        [NativeName(\"SetGradientValue\")]\n        private extern void SetGradientValueInternal(Gradient value);\n\n        // Value of an object reference property.\n        public UnityObject objectReferenceValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetPPtrValueInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetPPtrValueInternal(value);\n            }\n        }\n\n        // Value of an object reference property.\n        public object managedReferenceValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n\n                if (propertyType != SerializedPropertyType.ManagedReference)\n                {\n                    throw new System.InvalidOperationException(\n                        $\"managedReferenceValue is only available on fields with the [SerializeReference] attribute\");\n                }\n\n                return LookupInstanceByIdInternal(GetManagedReferenceIdInternal());\n            }\n            set\n            {\n                if (propertyType != SerializedPropertyType.ManagedReference)\n                {\n                    throw new System.InvalidOperationException(\n                        $\"Attempting to set the managed reference value on a SerializedProperty that is set to a '{this.type}'\");\n                }\n\n                // Make sure that the underlying base type is compatible with the current object\n                Type type;\n                var fieldInfo = UnityEditor.ScriptAttributeUtility.GetFieldInfoAndStaticTypeFromProperty(this, out type);\n                var propertyBaseType = type;\n\n                if (value != null)\n                {\n                    var valueType = value.GetType();\n                    if (valueType == typeof(UnityObject) || valueType.IsSubclassOf(typeof(UnityObject)))\n                    {\n                        throw new System.InvalidOperationException(\n                            $\"Cannot assign an object deriving from UnityEngine.Object to a managed reference. This is not supported.\");\n                    }\n                    else if (!propertyBaseType.IsAssignableFrom(valueType))\n                    {\n                        throw new System.InvalidOperationException(\n                            $\"Cannot assign an object of type '{valueType.Name}' to a managed reference with a base type of '{propertyBaseType.Name}': types are not compatible\");\n                    }\n                }\n\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetManagedReferenceValueInternal(value);\n            }\n        }\n\n        public RefId managedReferenceId\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetManagedReferenceIdInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                var referencedObj = LookupInstanceByIdInternal(value);\n                if (value != ManagedReferenceUtility.RefIdNull && referencedObj == null)\n                {\n                    throw new System.InvalidOperationException(\n                        $\"The specified managed reference id cannot be set because it is not currently assigned to an object.\");\n                }\n                managedReferenceValue = referencedObj;\n            }\n        }\n\n        [NativeName(\"GetManagedReferenceId\")]\n        private extern long GetManagedReferenceIdInternal();\n\n        // Dynamic type for the current managed reference.\n        public string managedReferenceFullTypename\n        {\n            get\n            {\n                if (propertyType != SerializedPropertyType.ManagedReference)\n                {\n                    throw new System.InvalidOperationException(\n                        $\"Attempting to get the managed reference full typename on a SerializedProperty that is set to a '{this.type}'\");\n                }\n                if (serializedObject.targetObject == null)\n                {\n                    return null;\n                }\n                return GetManagedReferenceFullTypeNameInternal();\n            }\n        }\n\n        // Static type for the current managed reference.\n        public string managedReferenceFieldTypename\n        {\n            get\n            {\n                if (propertyType != SerializedPropertyType.ManagedReference)\n                {\n                    throw new System.InvalidOperationException(\n                        $\"Attempting to get the managed reference full typename on a SerializedProperty that is set to a '{this.type}'\");\n                }\n\n                Type type;\n                var fieldInfo = UnityEditor.ScriptAttributeUtility.GetFieldInfoAndStaticTypeFromProperty(this, out type);\n\n                return $\"{type.Assembly.GetName().Name} {type.FullName.Replace(\"+\", \"/\")}\";\n            }\n        }\n\n        [NativeName(\"GetManagedReferenceFullTypeName\")]\n        private extern string GetManagedReferenceFullTypeNameInternal();\n\n        [NativeName(\"SetManagedReferenceValue\")]\n        private extern void SetManagedReferenceValueInternal(object value);\n\n        [NativeName(\"SetStructValue\")]\n        [NativeThrows]\n        internal extern void SetStructValueInternal(object value);\n\n        [NativeName(\"GetStructValue\")]\n        [NativeThrows]\n        internal extern object GetStructValueInternal(string assemblyName, string nameSpace, string className);\n\n        // exposed for public access via boxedValue\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal object structValue\n        {\n            get\n            {\n                if (isArray)\n                    throw new System.InvalidOperationException($\"'{propertyPath}' is an array so it cannot be read with boxedValue.\");\n\n                // Unlike managed references, the precise type for a struct or by-value class field is easier to determine in C#\n                // rather than at the native level, so we pass that info in.\n                UnityEditor.ScriptAttributeUtility.GetFieldInfoAndStaticTypeFromProperty(this, out Type type);\n\n                var nameSpace = type.Namespace;\n                string typeName = type.FullName.Replace(\"+\", \"/\");\n\n                if (!string.IsNullOrEmpty(nameSpace))\n                    typeName = typeName.Substring(nameSpace.Length + 1);\n\n                return GetStructValueInternal(type.Assembly.GetName().Name, nameSpace, typeName);\n            }\n\n            set\n            {\n                if (isArray)\n                    throw new System.InvalidOperationException($\"'{propertyPath}' is an array so it cannot be set with boxedValue.\");\n\n                // Retrieve the C# type info this property\n                UnityEditor.ScriptAttributeUtility.GetFieldInfoAndStaticTypeFromProperty(this, out Type propertyType);\n\n                if (propertyType.FullName != value.GetType().FullName)\n                    throw new System.InvalidOperationException(\n                        $\"The input to boxedValue has type '{value.GetType().FullName.Replace(\"+\",\"/\")}', which does not match the expected type '{propertyType.FullName.Replace(\"+\",\"/\")}'.\");\n\n                SetStructValueInternal(value);\n            }\n        }\n\n        [NativeName(\"LookupInstanceById\")]\n        private extern object LookupInstanceByIdInternal(RefId refId);\n\n        [NativeName(\"GetPPtrValue\")]\n        private extern UnityObject GetPPtrValueInternal();\n\n        [NativeName(\"SetPPtrValue\")]\n        private extern void SetPPtrValueInternal(UnityObject value);\n\n        public int objectReferenceInstanceIDValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetPPtrValueFromInstanceIDInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetPPtrValueFromInstanceIDInternal(value);\n            }\n        }\n\n        [NativeName(\"GetPPtrInstanceID\")]\n        private extern int GetPPtrValueFromInstanceIDInternal();\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::SetPPtrValueFromInstanceIDInternal\", HasExplicitThis = true)]\n        private extern void SetPPtrValueFromInstanceIDInternal(int instanceID);\n\n        internal string objectReferenceStringValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetPPtrStringValueInternal();\n            }\n        }\n\n        [NativeName(\"GetPPtrStringValue\")]\n        private extern string GetPPtrStringValueInternal();\n\n        internal bool ValidateObjectReferenceValue(UnityObject obj)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            return ValidatePPtrValueInternal(obj);\n        }\n\n        [NativeName(\"ValidatePPtrValue\")]\n        private extern bool ValidatePPtrValueInternal(UnityObject obj);\n\n        internal bool ValidateObjectReferenceValueExact(UnityObject obj)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            return ValidatePPtrValueExact(obj);\n        }\n\n        [NativeName(\"ValidatePPtrValueExact\")]\n        private extern bool ValidatePPtrValueExact(UnityObject obj);\n\n        internal string objectReferenceTypeString\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetPPtrClassNameInternal();\n            }\n        }\n\n        [NativeName(\"GetPPtrClassName\")]\n        private extern string GetPPtrClassNameInternal();\n\n        internal void AppendFoldoutPPtrValue(UnityObject obj)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            AppendFoldoutPPtrValueInternal(obj);\n        }\n\n        [NativeName(\"AppendFoldoutPPtrValue\")]\n        private extern void AppendFoldoutPPtrValueInternal(UnityObject obj);\n\n        internal extern static string GetLayerMaskStringValue(UInt32 layers);\n\n        internal UInt32 layerMaskBits\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetLayerMaskBitsInternal();\n            }\n        }\n\n        [NativeName(\"GetLayerMaskBits\")]\n        private extern UInt32 GetLayerMaskBitsInternal();\n\n        // Enum index of an enum property.\n        public int enumValueIndex\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetEnumValueIndexInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetEnumValueIndexInternal(value);\n            }\n        }\n\n        // Enum flag value\n        public int enumValueFlag\n        {\n            get { return intValue; }\n            set { intValue = value; }\n        }\n\n        [NativeName(\"GetEnumValueIndex\")]\n        private extern int GetEnumValueIndexInternal();\n\n        [NativeName(\"SetEnumValueIndex\")]\n        private extern void SetEnumValueIndexInternal(int value);\n\n        // Names of enumeration of an enum property.\n        public string[] enumNames\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetEnumNamesInternal(false);\n            }\n        }\n\n        // Names of enumeration of an enum property, nicified.\n        public string[] enumDisplayNames\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetEnumNamesInternal(true);\n            }\n        }\n\n        [NativeName(\"GetEnumNames\")]\n        private extern string[] GetEnumNamesInternal(bool nicify);\n\n        // Value of a 2D vector property.\n        public Vector2 vector2Value\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetValueVector2Internal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetValueVector2Internal(value);\n            }\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::GetValueVector2Internal\", HasExplicitThis = true)]\n        extern private Vector2 GetValueVector2Internal();\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::SetValueVector2Internal\", HasExplicitThis = true)]\n        extern private void SetValueVector2Internal(Vector2 value);\n\n        // Value of a 3D vector property.\n        public Vector3 vector3Value\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetValueVector3Internal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetValueVector3Internal(value);\n            }\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::GetValueVector3Internal\", HasExplicitThis = true)]\n        extern private Vector3 GetValueVector3Internal();\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::SetValueVector3Internal\", HasExplicitThis = true)]\n        extern private void SetValueVector3Internal(Vector3 value);\n\n        // Value of a 4D vector property.\n        public Vector4 vector4Value\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetValueVector4Internal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetValueVector4Internal(value);\n            }\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::GetValueVector4Internal\", HasExplicitThis = true)]\n        extern private Vector4 GetValueVector4Internal();\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::SetValueVector4Internal\", HasExplicitThis = true)]\n        extern private void SetValueVector4Internal(Vector4 value);\n\n        // Value of a 2D int vector property.\n        public Vector2Int vector2IntValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetValueVector2IntInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetValueVector2IntInternal(value);\n            }\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::GetValueVector2IntInternal\", HasExplicitThis = true)]\n        extern private Vector2Int GetValueVector2IntInternal();\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::SetValueVector2IntInternal\", HasExplicitThis = true)]\n        extern private void SetValueVector2IntInternal(Vector2Int value);\n\n        // Value of a 3D int vector property.\n        public Vector3Int vector3IntValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetValueVector3IntInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetValueVector3IntInternal(value);\n            }\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::GetValueVector3IntInternal\", HasExplicitThis = true)]\n        extern private Vector3Int GetValueVector3IntInternal();\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::SetValueVector3IntInternal\", HasExplicitThis = true)]\n        extern private void SetValueVector3IntInternal(Vector3Int value);\n\n        // Value of a quaternion property.\n        public Quaternion quaternionValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetValueQuaternionInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetValueQuaternionInternal(value);\n            }\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::GetValueQuaternionInternal\", HasExplicitThis = true)]\n        extern private Quaternion GetValueQuaternionInternal();\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::SetValueQuaternionInternal\", HasExplicitThis = true)]\n        extern private void SetValueQuaternionInternal(Quaternion value);\n\n        // Value of a rectangle property.\n        public Rect rectValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetValueRectInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetValueRectInternal(value);\n            }\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::GetValueRectInternal\", HasExplicitThis = true)]\n        extern private Rect GetValueRectInternal();\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::SetValueRectInternal\", HasExplicitThis = true)]\n        extern private void SetValueRectInternal(Rect value);\n\n        // Value of a rectangle int property.\n        public RectInt rectIntValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetValueRectIntInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetValueRectIntInternal(value);\n            }\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::GetValueRectIntInternal\", HasExplicitThis = true)]\n        extern private RectInt GetValueRectIntInternal();\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::SetValueRectIntInternal\", HasExplicitThis = true)]\n        extern private void SetValueRectIntInternal(RectInt value);\n\n        // Value of bounds property.\n        public Bounds boundsValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetValueBoundsInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetValueBoundsInternal(value);\n            }\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::GetValueBoundsInternal\", HasExplicitThis = true)]\n        extern private Bounds GetValueBoundsInternal();\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::SetValueBoundsInternal\", HasExplicitThis = true)]\n        extern private void SetValueBoundsInternal(Bounds value);\n\n        // Value of bounds int property.\n        public BoundsInt boundsIntValue\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetValueBoundsIntInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetValueBoundsIntInternal(value);\n            }\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::GetValueBoundsIntInternal\", HasExplicitThis = true)]\n        extern private BoundsInt GetValueBoundsIntInternal();\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::SetValueBoundsIntInternal\", HasExplicitThis = true)]\n        extern private void SetValueBoundsIntInternal(BoundsInt value);\n\n        // Value of a Hash128 property.\n        public Hash128 hash128Value\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return (Hash128)GetHash128ValueInternal();\n            }\n            set\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                SetHash128ValueInternal(value);\n            }\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::GetHash128ValueInternal\", HasExplicitThis = true)]\n        private extern Hash128 GetHash128ValueInternal();\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::SetHash128ValueInternal\", HasExplicitThis = true)]\n        private extern void SetHash128ValueInternal(Hash128 value);\n\n\n        // Move to next property.\n        public bool Next(bool enterChildren)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            return NextInternal(enterChildren);\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::NextInternal\", HasExplicitThis = true)]\n        extern private bool NextInternal(bool enterChildren);\n\n        // Move to first property of the object.\n        public void Reset()\n        {\n            Verify();\n            ResetInternal();\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::ResetInternal\", HasExplicitThis = true)]\n        extern private void ResetInternal();\n\n        // Count remaining visible properties.\n        public int CountRemaining()\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            return CountRemainingInternal();\n        }\n\n        [NativeName(\"CountRemaining\")]\n        extern private int CountRemainingInternal();\n\n        // Count visible children of this property, including this property itself.\n        public int CountInProperty()\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            return CountInPropertyInternal();\n        }\n\n        [NativeName(\"CountInProperty\")]\n        extern private int CountInPropertyInternal();\n\n        private SerializedProperty CopyInternal()\n        {\n            Verify();\n            return CopyInternalImpl();\n        }\n\n        [FreeFunction(Name = \"SerializedPropertyBindings::CopyInternal\", HasExplicitThis = true)]\n        extern private SerializedProperty CopyInternalImpl();\n\n        // Duplicates the serialized property.\n        public bool DuplicateCommand()\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            return DuplicateCommandInternal();\n        }\n\n        [NativeName(\"DuplicateCommand\")]\n        extern private bool DuplicateCommandInternal();\n\n        // Deletes the serialized property.\n        public bool DeleteCommand()\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            return DeleteCommandInternal();\n        }\n\n        [NativeName(\"DeleteCommand\")]\n        extern private bool DeleteCommandInternal();\n\n        // Retrieves the SerializedProperty that defines the end range of this property.\n        public SerializedProperty GetEndProperty()\n        {\n            return GetEndProperty(false);\n        }\n\n        // Retrieves the SerializedProperty that defines the end range of this property.\n        public SerializedProperty GetEndProperty(bool includeInvisible)\n        {\n            SerializedProperty prop = Copy();\n            if (includeInvisible)\n                prop.Next(false);\n            else\n                prop.NextVisible(false);\n            return prop;\n        }\n\n        internal bool FindPropertyRelativeInternal(string propertyPath)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            return FindRelativeProperty(propertyPath);\n        }\n\n        extern private bool FindRelativeProperty(string propertyPath);\n\n        // Is this property an array? (RO)\n        public bool isArray\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return IsArray();\n            }\n        }\n\n        extern private bool IsArray();\n\n        // The number of elements in the array.\n        public int arraySize\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetInspectableArraySize();\n            }\n            set\n            {\n                Verify();\n                ResizeArray(value);\n            }\n        }\n\n        public int minArraySize\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetMinArraySize();\n            }\n        }\n\n        extern private int GetMinArraySize();\n        extern private int GetInspectableArraySize();\n        extern private void ResizeArray(int value);\n\n        private bool GetArrayElementAtIndexInternal(int index)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            return GetArrayElementAtIndexImpl(index);\n        }\n\n        [NativeName(\"GetArrayElementAtIndex\")]\n        extern private bool GetArrayElementAtIndexImpl(int index);\n\n        // Insert an empty element at the specified index in the array.\n        // @TODO: What is the value of the element when it hasn't been set yet?\n        // SA: ::ref::isArray\n        public void InsertArrayElementAtIndex(int index)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            InsertArrayElementAtIndexInternal(index);\n        }\n\n        [NativeName(\"InsertArrayElementAtIndex\")]\n        extern private void InsertArrayElementAtIndexInternal(int index);\n\n        // Delete the element at the specified index in the array.\n        public void DeleteArrayElementAtIndex(int index)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            DeleteArrayElementAtIndexInternal(index);\n        }\n\n        [NativeName(\"DeleteArrayElementAtIndex\")]\n        extern private void DeleteArrayElementAtIndexInternal(int index);\n\n        // Move an array element from srcIndex to dstIndex.\n        public bool MoveArrayElement(int srcIndex, int dstIndex)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            return MoveArrayElementInternal(srcIndex, dstIndex);\n        }\n\n        [NativeName(\"MoveArrayElement\")]\n        extern private bool MoveArrayElementInternal(int srcIndex, int dstIndex);\n\n        // Is this property a fixed buffer? (RO)\n        public bool isFixedBuffer\n        {\n            get { return IsFixedBuffer(); }\n        }\n\n        extern private bool IsFixedBuffer();\n\n        // The number of elements in the fixed buffer (RO).\n        public int fixedBufferSize\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetFixedBufferSize();\n            }\n        }\n\n        extern private int GetFixedBufferSize();\n\n        // Is the cache for a display name string valid?\n        internal bool isValidDisplayNameCache\n        {\n            get => GetIsValidDisplayNameCache();\n            set => SetIsValidDisplayNameCache(value);\n        }\n\n        extern private bool GetIsValidDisplayNameCache();\n        extern private void SetIsValidDisplayNameCache(bool value);\n\n        // Is the cache for a tooltip string valid?\n        internal bool isValidTooltipCache\n        {\n            get => GetIsValidTooltipCache();\n            set => SetIsValidTooltipCache(value);\n        }\n\n        extern private bool GetIsValidTooltipCache();\n        extern private void SetIsValidTooltipCache(bool value);\n\n        public SerializedProperty GetFixedBufferElementAtIndex(int index)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            SerializedProperty prop = Copy();\n            if (prop.GetFixedBufferAtIndexInternal(index))\n                return prop;\n            else\n                return null;\n        }\n\n        [NativeName(\"GetFixedBufferElementAtIndex\")]\n        extern private bool GetFixedBufferAtIndexInternal(int index);\n\n        [NativeName(\"AnimationCurveValueEquals\")]\n        extern private bool AnimationCurveValueEquals(AnimationCurve curve);\n\n        internal bool ValueEquals(AnimationCurve curve)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            return AnimationCurveValueEquals(curve);\n        }\n\n        [NativeName(\"GradientValueEquals\")]\n        extern private bool GradientValueEquals(Gradient gradient);\n\n        internal bool ValueEquals(Gradient gradient)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            return GradientValueEquals(gradient);\n        }\n\n        [NativeName(\"StringValueEquals\")]\n        extern private bool StringValueEquals(string value);\n\n        internal bool ValueEquals(string value)\n        {\n            Verify(VerifyFlags.IteratorNotAtEnd);\n            return StringValueEquals(value);\n        }\n\n        internal bool unsafeMode {get; set; }\n        internal bool isValid\n        {\n            get\n            {\n                // SerializedProperty should only be accessed while the SerializedObject that created them is still alive\n                // Without this check IsValidInternal will crash in that case\n                if (m_NativePropertyPtr == IntPtr.Zero || m_SerializedObject == null || m_SerializedObject.m_NativeObjectPtr == IntPtr.Zero)\n                    return false;\n\n                return IsValidInternal();\n            }\n        }\n\n        [NativeName(\"IsValid\")]\n        extern private bool IsValidInternal();\n\n        public uint contentHash\n        {\n            get\n            {\n                Verify(VerifyFlags.IteratorNotAtEnd);\n                return GetContentHashInternal();\n            }\n        }\n\n        [NativeMethod(\"GetContentHash\")]\n        extern private uint GetContentHashInternal();\n\n        internal static class BindingsMarshaller\n        {\n            public static IntPtr ConvertToNative(SerializedProperty prop) => prop.m_NativePropertyPtr;\n            public static SerializedProperty ConvertToManaged(IntPtr ptr) => new SerializedProperty(ptr);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SerializedPropertyExtensions.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Assertions;\n\nnamespace UnityEditor\n{\n    internal static class SerializedPropertyExtensions\n    {\n        public static bool TryGetMapEntry(this SerializedProperty map, string key, out SerializedProperty entry)\n        {\n            Assert.IsTrue(map.type == \"map\" && !map.serializedObject.isEditingMultipleObjects);\n            for (int i = 0; i < map.arraySize; ++i)\n            {\n                var element = map.GetArrayElementAtIndex(i);\n                var first = element.FindPropertyRelative(\"first\").stringValue;\n                if (first == key)\n                {\n                    entry = element;\n                    return true;\n                }\n            }\n\n            entry = null;\n            return false;\n        }\n\n        public static bool TryGetMapEntry(this SerializedProperty map, int key, out SerializedProperty entry)\n        {\n            Assert.IsTrue(map.type == \"map\" && !map.serializedObject.isEditingMultipleObjects);\n            for (int i = 0; i < map.arraySize; ++i)\n            {\n                var element = map.GetArrayElementAtIndex(i);\n                var first = element.FindPropertyRelative(\"first\").intValue;\n                if (first == key)\n                {\n                    entry = element;\n                    return true;\n                }\n            }\n\n            entry = null;\n            return false;\n        }\n\n        public static bool TryGetMapEntry(this SerializedProperty map, string key, string elementMapKey, out SerializedProperty entry)\n        {\n            Assert.IsTrue(map.type == \"map\" && !map.serializedObject.isEditingMultipleObjects);\n            if (map.TryGetMapEntry(key, out var element))\n            {\n                var innerMap = element.FindPropertyRelative(\"second\");\n                Assert.IsTrue(innerMap.type == \"map\");\n                return innerMap.TryGetMapEntry(elementMapKey, out entry);\n            }\n\n            entry = null;\n            return false;\n        }\n\n        public static void SetMapValue(this SerializedProperty map, string key, int value)\n        {\n            Assert.IsTrue(map.type == \"map\" && !map.serializedObject.isEditingMultipleObjects);\n            if (map.TryGetMapEntry(key, out var entry))\n            {\n                entry.FindPropertyRelative(\"second\").intValue = value;\n            }\n            else\n            {\n                var index = map.arraySize;\n                map.arraySize += 1;\n                var element = map.GetArrayElementAtIndex(index);\n                element.FindPropertyRelative(\"first\").stringValue = key;\n                element.FindPropertyRelative(\"second\").intValue = value;\n            }\n        }\n\n        public static void SetMapValue(this SerializedProperty map, int key, string value)\n        {\n            Assert.IsTrue(map.type == \"map\" && !map.serializedObject.isEditingMultipleObjects);\n            if (map.TryGetMapEntry(key, out var entry))\n            {\n                entry.FindPropertyRelative(\"second\").stringValue = value;\n            }\n            else\n            {\n                var index = map.arraySize;\n                map.arraySize += 1;\n                var element = map.GetArrayElementAtIndex(index);\n                element.FindPropertyRelative(\"first\").intValue = key;\n                element.FindPropertyRelative(\"second\").stringValue = value;\n            }\n        }\n\n        public static void SetMapValue(this SerializedProperty map, int key, string[] value)\n        {\n            Assert.IsTrue(map.type == \"map\" && !map.serializedObject.isEditingMultipleObjects);\n            if (map.TryGetMapEntry(key, out var entry))\n            {\n                var secondProperty = entry.FindPropertyRelative(\"second\");\n                Assert.IsTrue(secondProperty.isArray);\n\n                secondProperty.arraySize = value.Length;\n                for (int i = 0; i < secondProperty.arraySize; ++i)\n                {\n                    secondProperty.GetArrayElementAtIndex(i).stringValue = value[i];\n                }\n            }\n            else\n            {\n                var index = map.arraySize;\n                map.arraySize += 1;\n                var element = map.GetArrayElementAtIndex(index);\n\n                element.FindPropertyRelative(\"first\").intValue = key;\n                var secondProperty = element.FindPropertyRelative(\"second\");\n\n                secondProperty.arraySize = value.Length;\n                for (int i = 0; i < secondProperty.arraySize; ++i)\n                {\n                    secondProperty.GetArrayElementAtIndex(i).stringValue = value[i];\n                }\n            }\n        }\n\n        public static void SetMapValue(this SerializedProperty map, string key, string value)\n        {\n            Assert.IsTrue(map.type == \"map\" && !map.serializedObject.isEditingMultipleObjects);\n            if (map.TryGetMapEntry(key, out var entry))\n            {\n                entry.FindPropertyRelative(\"second\").stringValue = value;\n            }\n            else\n            {\n                var index = map.arraySize;\n                map.arraySize += 1;\n                var element = map.GetArrayElementAtIndex(index);\n                element.FindPropertyRelative(\"first\").stringValue = key;\n                element.FindPropertyRelative(\"second\").stringValue = value;\n            }\n        }\n\n        public static void SetMapValue(this SerializedProperty map, string key, string[] value)\n        {\n            Assert.IsTrue(map.type == \"map\" && !map.serializedObject.isEditingMultipleObjects);\n            if (map.TryGetMapEntry(key, out var entry))\n            {\n                var secondProperty = entry.FindPropertyRelative(\"second\");\n                Assert.IsTrue(secondProperty.isArray);\n\n                secondProperty.arraySize = value.Length;\n                for (int i = 0; i < secondProperty.arraySize; ++i)\n                {\n                    secondProperty.GetArrayElementAtIndex(i).stringValue = value[i];\n                }\n            }\n            else\n            {\n                var index = map.arraySize;\n                map.arraySize += 1;\n                var element = map.GetArrayElementAtIndex(index);\n\n                element.FindPropertyRelative(\"first\").stringValue = key;\n                var secondProperty = element.FindPropertyRelative(\"second\");\n\n                secondProperty.arraySize = value.Length;\n                for (int i = 0; i < secondProperty.arraySize; ++i)\n                {\n                    secondProperty.GetArrayElementAtIndex(i).stringValue = value[i];\n                }\n            }\n        }\n\n        public static void SetMapValue(this SerializedProperty map, string key, string elementMapKey, string elementMapValue)\n        {\n            Assert.IsTrue(map.type == \"map\" && !map.serializedObject.isEditingMultipleObjects);\n            if (map.TryGetMapEntry(key, out var entry))\n            {\n                var innerMap = entry.FindPropertyRelative(\"second\");\n                Assert.IsTrue(innerMap.type == \"map\");\n                innerMap.SetMapValue(elementMapKey, elementMapValue);\n            }\n            else\n            {\n                var index = map.arraySize;\n                map.arraySize += 1;\n                var element = map.GetArrayElementAtIndex(index);\n                var innerMap = element.FindPropertyRelative(\"second\");\n                Assert.IsTrue(innerMap.type == \"map\");\n                element.FindPropertyRelative(\"first\").stringValue = key;\n                innerMap.SetMapValue(elementMapKey, elementMapValue);\n            }\n        }\n\n        public static void SetMapValue(this SerializedProperty map, string key, bool value)\n        {\n            Assert.IsTrue(map.type == \"map\" && !map.serializedObject.isEditingMultipleObjects);\n            if (map.TryGetMapEntry(key, out var entry))\n            {\n                entry.FindPropertyRelative(\"second\").boolValue = value;\n            }\n            else\n            {\n                var index = map.arraySize;\n                map.arraySize += 1;\n                var element = map.GetArrayElementAtIndex(index);\n                element.FindPropertyRelative(\"first\").stringValue = key;\n                element.FindPropertyRelative(\"second\").boolValue = value;\n            }\n        }\n\n        public static void SetValue<DataSourceType>(this SerializedProperty serializedProperty, Action<SerializedProperty, DataSourceType> serialziedPropertySetter, IList<DataSourceType> dstValues)\n        {\n            if (serializedProperty != null && serializedProperty.isArray && serialziedPropertySetter != null)\n            {\n                var numElementSerialized = serializedProperty.arraySize;\n                var numElementToInsert = dstValues.Count;\n                if (numElementSerialized > numElementToInsert)\n                {\n                    for (var i = numElementSerialized - 1; i >= numElementToInsert; i--)\n                    {\n                        serializedProperty.DeleteArrayElementAtIndex(i);\n                    }\n                }\n\n                for (var i = 0; i < numElementToInsert; i++)\n                {\n                    if (i >= numElementSerialized)\n                    {\n                        serializedProperty.InsertArrayElementAtIndex(i);\n                        numElementSerialized = serializedProperty.arraySize;\n                    }\n\n                    var objToEdit = serializedProperty.GetArrayElementAtIndex(i);\n                    DataSourceType newValue = dstValues[i];\n                    serialziedPropertySetter.Invoke(objToEdit, newValue);\n                }\n            }\n        }\n\n        public static void Setter(SerializedProperty serializedProperty, int value)\n        {\n            serializedProperty.intValue = value;\n        }\n\n        public static void Setter(SerializedProperty serializedProperty, double value)\n        {\n            serializedProperty.doubleValue = value;\n        }\n\n        public static void Setter(SerializedProperty serializedProperty, bool value)\n        {\n            serializedProperty.boolValue = value;\n        }\n\n        public static void Setter(SerializedProperty serializedProperty, string value)\n        {\n            serializedProperty.stringValue = value;\n        }\n\n        public static void Setter(SerializedProperty serializedProperty, long value)\n        {\n            serializedProperty.longValue = value;\n        }\n\n        public static void Setter(SerializedProperty serializedProperty, Color value)\n        {\n            serializedProperty.colorValue = value;\n        }\n\n        public static void Setter(SerializedProperty serializedProperty, AnimationCurve value)\n        {\n            serializedProperty.animationCurveValue = value;\n        }\n\n        public static void Setter(SerializedProperty serializedProperty, Bounds value)\n        {\n            serializedProperty.boundsValue = value;\n        }\n\n        public static void Setter(SerializedProperty serializedProperty, object value)\n        {\n            serializedProperty.boxedValue = value;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Settings/Providers/AssetSettingsProvider.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.Experimental;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing UnityEditor.StyleSheets;\nusing UnityEditorInternal;\nusing System.Collections.Generic;\n\nnamespace UnityEditor\n{\n    public class AssetSettingsProvider : SettingsProvider\n    {\n        static class Styles\n        {\n            public static GUIStyle settingsStyle = \"IconButton\";\n            public static StyleBlock settingsBtn => EditorResources.GetStyle(\"sb-settings-icon-btn\");\n        }\n\n        Func<Editor> m_EditorCreator;\n\n        public Editor settingsEditor { get; private set; }\n\n        public AssetSettingsProvider(string settingsWindowPath, Func<Editor> editorCreator, IEnumerable<string> keywords = null)\n            : base(settingsWindowPath, SettingsScope.Project, keywords)\n        {\n            m_EditorCreator = editorCreator;\n        }\n\n        public AssetSettingsProvider(string settingsWindowPath, Func<UnityEngine.Object> settingsGetter)\n            : this(settingsWindowPath, () => CreateEditorFromSettingsObject(settingsGetter()))\n        {\n        }\n\n        public static AssetSettingsProvider CreateProviderFromAssetPath(string settingsWindowPath, string assetPath, IEnumerable<string> keywords = null)\n        {\n            return new AssetSettingsProvider(settingsWindowPath, () =>\n            {\n                var settingsObj = AssetDatabase.LoadAllAssetsAtPath(assetPath);\n                if (settingsObj != null)\n                {\n                    return Editor.CreateEditor(settingsObj);\n                }\n                return null;\n            }, keywords);\n        }\n\n        public static AssetSettingsProvider CreateProviderFromObject(string settingsWindowPath, UnityEngine.Object settingsObj, IEnumerable<string> keywords = null)\n        {\n            return new AssetSettingsProvider(settingsWindowPath, () => CreateEditorFromSettingsObject(settingsObj), keywords);\n        }\n\n        public static AssetSettingsProvider CreateProviderFromResourcePath(string settingsWindowPath, string resourcePath, IEnumerable<string> keywords = null)\n        {\n            return new AssetSettingsProvider(settingsWindowPath, () =>\n            {\n                var resourceObj = Resources.Load(resourcePath);\n                if (resourceObj != null)\n                {\n                    return Editor.CreateEditor(resourceObj);\n                }\n                return null;\n            }, keywords);\n        }\n\n        public override void OnActivate(string searchContext, VisualElement rootElement)\n        {\n            if (settingsEditor != null)\n            {\n                UnityEngine.Object.DestroyImmediate(settingsEditor);\n            }\n            settingsEditor = m_EditorCreator?.Invoke();\n            base.OnActivate(searchContext, rootElement);\n        }\n\n        public override void OnDeactivate()\n        {\n            if (settingsEditor != null)\n            {\n                UnityEngine.Object.DestroyImmediate(settingsEditor);\n            }\n            settingsEditor = null;\n            base.OnDeactivate();\n        }\n\n        public override void OnGUI(string searchContext)\n        {\n            if (settingsEditor != null)\n            {\n                using (new EditorGUI.DisabledScope(!settingsEditor.IsEnabled()))\n                {\n                    using (new SettingsWindow.GUIScope())\n                        settingsEditor.OnInspectorGUI();\n\n                    // Emulate the Inspector by handling DnD at the native level.\n                    var remainingRect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandHeight(true));\n                    if ((Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform) && remainingRect.Contains(Event.current.mousePosition))\n                    {\n                        DragAndDrop.visualMode = DragAndDrop.DropOnInspectorWindow(new[] { settingsEditor.target }, Event.current.type == EventType.DragPerform);\n                        if (Event.current.type == EventType.DragPerform)\n                            DragAndDrop.AcceptDrag();\n                    }\n                }\n            }\n\n            base.OnGUI(searchContext);\n        }\n\n        public override void OnTitleBarGUI()\n        {\n            if (settingsEditor != null)\n            {\n                using (new EditorGUI.DisabledScope(!settingsEditor.IsEnabled()))\n                {\n                    var tagrObjects = new[] { settingsEditor.serializedObject.targetObject };\n\n                    var btnWidth = Styles.settingsBtn.GetFloat(StyleCatalogKeyword.width);\n                    var btnHeight = Styles.settingsBtn.GetFloat(StyleCatalogKeyword.height);\n                    var btnMargin = Styles.settingsBtn.GetFloat(StyleCatalogKeyword.marginTop);\n\n                    var rect = GUILayoutUtility.GetRect(btnWidth, btnHeight);\n                    rect.y = btnMargin;\n                    EditorGUIUtility.DrawEditorHeaderItems(rect, tagrObjects);\n                    var settingsRect = GUILayoutUtility.GetRect(btnWidth, btnHeight);\n                    settingsRect.y = rect.y;\n\n                    // Settings; process event even for disabled UI\n                    var wasEnabled = GUI.enabled;\n                    GUI.enabled = true;\n                    var showMenu = EditorGUI.DropdownButton(settingsRect, GUIContent.none, FocusType.Passive, EditorStyles.optionsButtonStyle);\n                    GUI.enabled = wasEnabled;\n                    if (showMenu)\n                    {\n                        EditorUtility.DisplayObjectContextMenu(settingsRect, tagrObjects, 0);\n                    }\n                }\n                base.OnTitleBarGUI();\n            }\n        }\n\n        public override void OnFooterBarGUI()\n        {\n            if (settingsEditor != null)\n                PropertyEditor.VersionControlBar(settingsEditor);\n        }\n\n        private static Editor CreateEditorFromSettingsObject(UnityEngine.Object settingsObj)\n        {\n            if (settingsObj != null)\n            {\n                return Editor.CreateEditor(settingsObj);\n            }\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Settings/RenderPipelines/RenderPipelineGraphicsSettingsManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing UnityEditor.Inspector.GraphicsSettingsInspectors;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor.Rendering.Settings\n{\n    internal static class RenderPipelineGraphicsSettingsManager\n    {\n        internal const string serializationPathToContainer = \"m_Settings\";\n        internal const string serializationPathToCollection = serializationPathToContainer + \".m_SettingsList.m_List\";\n        internal const string undoResetName = \"Reset IRenderPipelineGraphicsSettings: \";\n\n        public struct RenderPipelineGraphicsSettingsInfo\n        {\n            public Type type;\n            public bool isSupported;\n        }\n\n        internal static void PopulateRenderPipelineGraphicsSettings(RenderPipelineGlobalSettings settings)\n        {\n            if (settings == null)\n                return;\n\n            if (!GraphicsSettingsInspectorUtility.TryExtractSupportedOnRenderPipelineAttribute(settings.GetType(), out var globalSettingsSupportedOn, out var message))\n                throw new InvalidOperationException(message);\n\n            var globalSettingsRenderPipelineAssetType = globalSettingsSupportedOn.renderPipelineTypes[0];\n\n            bool assetModified = false;\n\n            List<IRenderPipelineGraphicsSettings> createdSettingsObjects = new();\n\n            foreach (var info in FetchRenderPipelineGraphicsSettingInfos(globalSettingsRenderPipelineAssetType, true))\n            {\n                UpdateRenderPipelineGlobalSettings(info, settings, out var modified, out var createdSetting);\n                assetModified |= modified;\n                if (createdSetting != null)\n                    createdSettingsObjects.Add(createdSetting);\n            }\n\n            foreach (var created in createdSettingsObjects)\n            {\n                created.Reset();\n            }\n\n            if (assetModified)\n            {\n                EditorUtility.SetDirty(settings);\n                AssetDatabase.SaveAssetIfDirty(settings);\n            }\n        }\n\n        internal static IEnumerable<RenderPipelineGraphicsSettingsInfo> FetchRenderPipelineGraphicsSettingInfos(Type globalSettingsRenderPipelineAssetType, bool includeUnsupported = false)\n        {\n            foreach (var renderPipelineGraphicsSettingsType in TypeCache.GetTypesDerivedFrom(typeof(IRenderPipelineGraphicsSettings)))\n            {\n                if (!IsSettingsValid(renderPipelineGraphicsSettingsType))\n                    continue;\n\n                // The Setting has been completely deprecated or not supported on render pipeline anymore\n                if (!IsSettingsSupported(renderPipelineGraphicsSettingsType, globalSettingsRenderPipelineAssetType, includeUnsupported, out var isSupported))\n                    continue;\n\n                yield return new RenderPipelineGraphicsSettingsInfo()\n                {\n                    type = renderPipelineGraphicsSettingsType,\n                    isSupported = isSupported\n                };\n            }\n        }\n\n        static void UpdateRenderPipelineGlobalSettings(\n            RenderPipelineGraphicsSettingsInfo renderPipelineGraphicsSettingsType,\n            RenderPipelineGlobalSettings asset,\n            out bool assetModified,\n            out IRenderPipelineGraphicsSettings createdSetting)\n        {\n            assetModified = false;\n            createdSetting = null;\n\n            var hasSettings = asset.TryGet(renderPipelineGraphicsSettingsType.type, out var renderPipelineGraphicsSettings);\n            if (!renderPipelineGraphicsSettingsType.isSupported)\n            {\n                if (!hasSettings)\n                    return;\n\n                asset.Remove(renderPipelineGraphicsSettings);\n                assetModified = true;\n                return;\n            }\n\n            if (!hasSettings && TryCreateInstance(renderPipelineGraphicsSettingsType.type, true, out renderPipelineGraphicsSettings))\n            {\n                assetModified = true;\n                createdSetting = renderPipelineGraphicsSettings;\n                asset.Add(renderPipelineGraphicsSettings);\n            }\n\n            if (renderPipelineGraphicsSettings is IRenderPipelineResources resource)\n            {\n                var reloadingStatus = RenderPipelineResourcesEditorUtils.TryReloadContainedNullFields(resource);\n                assetModified |= reloadingStatus == RenderPipelineResourcesEditorUtils.ResultStatus.ResourceReloaded;\n            }\n        }\n\n        static bool TryCreateInstance<T>(Type type, bool nonPublic, out T instance)\n        {\n            try\n            {\n                instance = (T)Activator.CreateInstance(type, nonPublic);\n                return true;\n            }\n            catch (Exception ex)\n            {\n                Debug.LogException(ex);\n            }\n\n            instance = default;\n            return false;\n        }\n\n        static bool IsSettingsSupported(Type renderPipelineGraphicsSettingsType, Type globalSettingsRenderPipelineAssetType, bool includeUnsupported, out bool isSupported)\n        {\n            isSupported = !(renderPipelineGraphicsSettingsType.GetCustomAttribute<ObsoleteAttribute>()?.IsError ?? false);\n            isSupported &= SupportedOnRenderPipelineAttribute.IsTypeSupportedOnRenderPipeline(renderPipelineGraphicsSettingsType, globalSettingsRenderPipelineAssetType);\n            return includeUnsupported || isSupported;\n        }\n\n        static bool IsSettingsValid(Type renderPipelineGraphicsSettingsType)\n        {\n            if (renderPipelineGraphicsSettingsType.IsAbstract || renderPipelineGraphicsSettingsType.IsGenericType || renderPipelineGraphicsSettingsType.IsInterface)\n                return false;\n\n            if (renderPipelineGraphicsSettingsType.GetCustomAttribute<SerializableAttribute>() == null)\n            {\n                Debug.LogWarning($\"{nameof(SerializableAttribute)} must be added to {renderPipelineGraphicsSettingsType}, the setting will be skipped\");\n                return false;\n            }\n\n            if (renderPipelineGraphicsSettingsType.GetCustomAttribute<SupportedOnRenderPipelineAttribute>() == null)\n            {\n                Debug.LogWarning($\"{nameof(SupportedOnRenderPipelineAttribute)} must be added to {renderPipelineGraphicsSettingsType}, the setting will be skipped\");\n                return false;\n            }\n\n            return true;\n        }\n\n        internal static void ResetRenderPipelineGraphicsSettings(Type graphicsSettingsType, Type renderPipelineType)\n        {\n            if (graphicsSettingsType == null || renderPipelineType == null)\n                return;\n\n            var renderPipelineGlobalSettings = EditorGraphicsSettings.GetRenderPipelineGlobalSettingsAsset(renderPipelineType);\n            if (renderPipelineGlobalSettings == null || !renderPipelineGlobalSettings.TryGet(graphicsSettingsType, out var graphicsSettingsCurrentInstance))\n                return;\n\n            if (!TryCreateInstance(graphicsSettingsType, true, out IRenderPipelineGraphicsSettings createdForCSharpDefaultValues))\n                return;\n            \n            if (createdForCSharpDefaultValues is IRenderPipelineResources resource)\n                RenderPipelineResourcesEditorUtils.TryReloadContainedNullFields(resource);\n\n            //Retrieve the SerializedProperty on the settings to reset in the global settings for the Notifier\n            var serializedGlobalSettings = new SerializedObject(renderPipelineGlobalSettings);\n            var settingsIterator = serializedGlobalSettings.FindProperty(serializationPathToCollection);\n            settingsIterator.NextVisible(true); //enter the collection\n            while (settingsIterator.boxedValue?.GetType() != graphicsSettingsType)\n                settingsIterator.NextVisible(false);\n\n            using (var notifier = new Notifier.Scope(settingsIterator))\n            {\n                //Transfer default C# values (+ null reloading for IRenderPipelineResources)\n                CopyBySerialization.Copy(createdForCSharpDefaultValues, settingsIterator);\n\n                if (serializedGlobalSettings.ApplyModifiedProperties())\n                    Undo.SetCurrentGroupName($\"{undoResetName}{graphicsSettingsType.Name}\");\n            }\n\n            graphicsSettingsCurrentInstance.Reset();\n        }\n\n        // Note: to keep reference when copying, we need to go through the serializedObject and update all field.\n        // Using directly ` property.boxedValue = value; ` change the reference. So, any local cache of the settings\n        // will be invalid after. Instead we need to shallow copy the content into the reference, as follow.\n        // As a IRenderPipelineGraphicsSettings is not a UnityEngine.Object, we need to host it in one to serialize it.\n        class CopyBySerialization : ScriptableObject\n        {\n            [SerializeReference] IRenderPipelineGraphicsSettings content;\n\n            public static void Copy(IRenderPipelineGraphicsSettings source, SerializedProperty destinationProperty)\n            {\n                if (destinationProperty == null || source == null || destinationProperty.boxedValue.GetType() != source.GetType())\n                    return;\n\n                var container = ScriptableObject.CreateInstance<CopyBySerialization>();\n                container.content = source;\n\n                // Get a SerializedProperty on the 'content' property\n                SerializedObject sp = new(container);\n                var iterator = sp.GetIterator();\n                iterator.NextVisible(true); //enter CopyBySerialization\n                while (iterator.boxedValue?.GetType() != source.GetType())\n                    iterator.NextVisible(false);\n\n                ShallowCopyContent(iterator, destinationProperty);\n\n                container.content = null;\n                UnityEngine.Object.DestroyImmediate(container);\n            }\n\n            static void ShallowCopyContent(SerializedProperty source, SerializedProperty destination)\n            {\n                void Copy(SerializedProperty source, SerializedProperty destination)\n                {\n                    if (source.propertyType == SerializedPropertyType.String)\n                    {\n                        //array are perceive as string by isArray\n                        destination.boxedValue = source.boxedValue;\n                    }\n                    else if (source.isArray)\n                    {\n                        //Array cannot directly be copied so we need to go one step deeper for them\n                        destination.arraySize = source.arraySize;\n                        source.NextVisible(true); \n                        destination.NextVisible(true);\n                    }\n\n                    destination.boxedValue = source.boxedValue;\n                }\n\n                var sourceIterator = source.Copy();\n                var destinationIterator = destination.Copy();\n                var sourceEnd = sourceIterator.GetEndProperty();\n\n                //step into\n                sourceIterator.NextVisible(true);\n                destinationIterator.NextVisible(true);\n\n                while (!SerializedProperty.EqualContents(sourceIterator, sourceEnd))\n                {\n                    Copy(sourceIterator, destinationIterator);\n                    sourceIterator.NextVisible(false);\n                    destinationIterator.NextVisible(false);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Settings/SettingsProvider.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace UnityEditor\n{\n    public enum SettingsScope\n    {\n        User,\n        Project\n    }\n\n    public class SettingsProvider\n    {\n        private string m_Label;\n        private string m_Name;\n        private HashSet<string> m_Keywords;\n        bool m_Activated;\n\n        internal SettingsWindow settingsWindow { get; set; }\n        internal string[] pathTokens { get; }\n        internal Texture2D icon { get; set; }\n\n\n        public string label\n        {\n            get\n            {\n                if (String.IsNullOrEmpty(m_Label))\n                    return m_Name;\n                return m_Label;\n            }\n            set { m_Label = L10n.Tr(value); }\n        }\n\n        public string settingsPath { get; }\n        public SettingsScope scope { get; }\n        public IEnumerable<string> keywords\n        {\n            get { return m_Keywords; }\n            set\n            {\n                m_Keywords = new HashSet<string>(value);\n            }\n        }\n\n        public Action<string> guiHandler { get; set; }\n        public Action titleBarGuiHandler { get; set; }\n        public Action footerBarGuiHandler { get; set; }\n        public Action<string, VisualElement> activateHandler { get; set; }\n        public Action deactivateHandler { get; set; }\n        public Func<string, bool> hasSearchInterestHandler { get; set; }\n        public Action inspectorUpdateHandler { get; set; }\n\n        public SettingsProvider(string path, SettingsScope scopes, IEnumerable<string> keywords = null)\n        {\n            settingsPath = path.Replace(\"\\n\", \" \").Replace(\"\\\\\", \"/\");\n            var nameIndex = settingsPath.LastIndexOf(\"/\");\n            var name = settingsPath;\n            if (nameIndex != -1)\n            {\n                name = settingsPath.Substring(nameIndex + 1);\n            }\n            m_Name = L10n.Tr(name);\n\n            pathTokens = settingsPath.Split('/');\n            this.scope = scopes;\n            m_Keywords = keywords == null ? new HashSet<string>() : new HashSet<string>(keywords);\n        }\n\n        public virtual void OnActivate(string searchContext, VisualElement rootElement)\n        {\n            activateHandler?.Invoke(searchContext, rootElement);\n        }\n\n        public virtual void OnDeactivate()\n        {\n            deactivateHandler?.Invoke();\n        }\n\n        public virtual bool HasSearchInterest(string searchContext)\n        {\n            if (hasSearchInterestHandler != null)\n            {\n                return hasSearchInterestHandler.Invoke(searchContext);\n            }\n\n            foreach (var searchKeyword in keywords)\n            {\n                if (SearchUtils.MatchSearchGroups(searchContext, searchKeyword))\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public virtual void OnGUI(string searchContext)\n        {\n            guiHandler?.Invoke(searchContext);\n        }\n\n        public virtual void OnTitleBarGUI()\n        {\n            titleBarGuiHandler?.Invoke();\n        }\n\n        public virtual void OnFooterBarGUI()\n        {\n            footerBarGuiHandler?.Invoke();\n        }\n\n        public virtual void OnInspectorUpdate()\n        {\n            inspectorUpdateHandler?.Invoke();\n        }\n\n        public void Repaint()\n        {\n            settingsWindow?.Repaint();\n        }\n\n        public void PopulateSearchKeywordsFromGUIContentProperties<T>()\n        {\n            keywords = GetSearchKeywordsFromGUIContentProperties<T>();\n        }\n\n        internal void OnFocusLost()\n        {\n            FocusLost();\n        }\n\n        protected virtual void FocusLost()\n        {\n        }\n\n        internal void Activate(string searchContext, VisualElement rootElement)\n        {\n            // If OnActivate fails, it should not be considered activated\n            if (!m_Activated)\n                OnActivate(searchContext, rootElement);\n            m_Activated = true;\n        }\n\n        internal void Deactivate()\n        {\n            if (m_Activated)\n            {\n                // Set activated=false first, so even if OnDeactivate fails it will be considered deactivated.\n                m_Activated = false;\n                OnDeactivate();\n            }\n        }\n\n        public override string ToString()\n        {\n            return $\"{GetType().Name} - {settingsPath}\";\n        }\n\n        #region Helper\n        public static IEnumerable<string> GetSearchKeywordsFromGUIContentProperties<T>()\n        {\n            return typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public)\n                .Where(field => typeof(GUIContent).IsAssignableFrom(field.FieldType))\n                .Select(field => ((GUIContent)field.GetValue(null)).text)\n                .Concat(typeof(T).GetProperties(BindingFlags.Static | BindingFlags.Public)\n                    .Where(prop => typeof(GUIContent).IsAssignableFrom(prop.PropertyType))\n                    .Select(prop => ((GUIContent)prop.GetValue(null, null)).text))\n                .Where(content => content != null)\n                .Select(content => content.ToLowerInvariant())\n                .Distinct();\n        }\n\n        public static IEnumerable<string> GetSearchKeywordsFromSerializedObject(SerializedObject serializedObject)\n            => GetSearchKeywordsFromSerializedObject(serializedObject, sp => sp.displayName);\n        \n        internal static IEnumerable<string> GetSearchKeywordsFromSerializedObject(SerializedObject serializedObject, Func<SerializedProperty, string> resolveName)\n        {\n            var keywords = new HashSet<string>();\n            var property = serializedObject.GetIterator();\n            while (property.NextVisible(true))\n            {\n                keywords.Add(resolveName(property));\n            }\n            return keywords;\n        }\n\n        public static IEnumerable<string> GetSearchKeywordsFromPath(string path)\n        {\n            var obj = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path);\n            if (obj != null)\n            {\n                return GetSearchKeywordsFromSerializedObject(new SerializedObject(obj));\n            }\n\n            return new string[] {};\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Settings/SettingsProviderAttribute.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\n\nnamespace UnityEditor\n{\n    [AttributeUsage(AttributeTargets.Method)]\n    public sealed class SettingsProviderAttribute : Attribute\n    {\n        [RequiredSignature]\n        private static SettingsProvider signature()\n        {\n            return null;\n        }\n    }\n\n    [AttributeUsage(AttributeTargets.Method)]\n    public sealed class SettingsProviderGroupAttribute : Attribute\n    {\n        [RequiredSignature]\n        private static SettingsProvider[] signature()\n        {\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Settings/SettingsService.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing System.Text;\nusing UnityEngine;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    [InitializeOnLoad]\n    public static class SettingsService\n    {\n        internal static event Action repaintAllSettingsWindow;\n\n        public static EditorWindow OpenProjectSettings(string settingsPath = null)\n        {\n            return SettingsWindow.Show(SettingsScope.Project, settingsPath);\n        }\n\n        public static EditorWindow OpenUserPreferences(string settingsPath = null)\n        {\n            return SettingsWindow.Show(SettingsScope.User, settingsPath);\n        }\n\n        public static void NotifySettingsProviderChanged()\n        {\n            settingsProviderChanged?.Invoke();\n        }\n\n        public static void RepaintAllSettingsWindow()\n        {\n            repaintAllSettingsWindow?.Invoke();\n        }\n\n        internal static IEnumerable<SettingsProvider> FilterAndWarnAgainstDuplicates(IEnumerable<SettingsProvider> settingsProviders, SettingsScope scope)\n        {\n            Dictionary<string, int> settingPaths = new Dictionary<string, int>();\n            foreach (var provider in settingsProviders)\n            {\n                if (provider.scope != scope)\n                {\n                    yield return provider;\n                    continue;\n                }\n\n                if (settingPaths.ContainsKey(provider.settingsPath))\n                {\n                    settingPaths[provider.settingsPath] += 1;\n                    continue;\n                }\n                else\n                {\n                    settingPaths.Add(provider.settingsPath, 1);\n                    yield return provider;\n                }\n            }\n\n            foreach (var settingPath in settingPaths)\n            {\n                if (settingPath.Value > 1)\n                    Debug.LogWarning($\"There are {settingPath.Value} settings providers with the same name {settingPath.Key} in {scope} scope.\");\n            }\n        }\n\n        internal static event Action settingsProviderChanged;\n        internal static SettingsProvider[] FetchSettingsProviders()\n        {\n            var settingsProviders =\n                FetchSettingProviderFromAttribute()\n                    .Concat(FetchSettingProvidersFromAttribute())\n                    .Concat(FetchPreferenceItems())\n                    .Where(provider => provider != null);\n\n            settingsProviders = FilterAndWarnAgainstDuplicates(settingsProviders, SettingsScope.Project);\n            return FilterAndWarnAgainstDuplicates(settingsProviders, SettingsScope.User).ToArray();\n        }\n\n        internal static SettingsProvider[] FetchSettingsProviders(SettingsScope scope)\n        {\n            var settingsProviders =\n                FetchSettingProviderFromAttribute()\n                    .Concat(FetchSettingProvidersFromAttribute())\n                    .Concat(FetchPreferenceItems())\n                    .Where(provider => provider != null && provider.scope == scope);\n\n            return FilterAndWarnAgainstDuplicates(settingsProviders, scope).ToArray();\n        }\n\n        public static bool Exists(string settingsPath)\n        {\n            var settingsProviders = FetchSettingsProviders();\n\n            foreach (var provider in settingsProviders)\n            {\n                if (settingsPath.Equals(provider.settingsPath, StringComparison.Ordinal))\n                    return true;\n            }\n\n            return false;\n        }\n\n        [RequiredByNativeCode]\n        internal static EditorWindow OpenUserPreferenceWindow()\n        {\n            return SettingsWindow.Show(SettingsScope.User);\n        }\n\n        private static IEnumerable<SettingsProvider> FetchPreferenceItems()\n        {\n#pragma warning disable CS0618\n            var methods = AttributeHelper.GetMethodsWithAttribute<PreferenceItem>(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);\n#pragma warning restore CS0618\n            return methods.methodsWithAttributes.Select(method =>\n            {\n                var callback = Delegate.CreateDelegate(typeof(Action), method.info) as Action;\n                if (callback != null)\n                {\n#pragma warning disable CS0618\n                    var attributeName = (method.attribute as PreferenceItem).name;\n#pragma warning restore CS0618\n                    try\n                    {\n                        return new SettingsProvider(\"Preferences/\" + attributeName, SettingsScope.User) { guiHandler = searchContext => callback() };\n                    }\n                    catch (Exception)\n                    {\n                        Debug.LogError(\"Cannot create preference wrapper for: \" + attributeName);\n                    }\n                }\n\n                return null;\n            });\n        }\n\n        private static IEnumerable<SettingsProvider> FetchSettingProviderFromAttribute()\n        {\n            var methods = AttributeHelper.GetMethodsWithAttribute<SettingsProviderAttribute>();\n            return methods.methodsWithAttributes.Select(method =>\n            {\n                try\n                {\n                    var callback = Delegate.CreateDelegate(typeof(Func<SettingsProvider>), method.info) as Func<SettingsProvider>;\n                    return callback?.Invoke();\n                }\n                catch (Exception)\n                {\n                    Debug.LogError(\"Cannot create Settings Provider for: \" + method.info.Name);\n                }\n                return null;\n            });\n        }\n\n        private static IEnumerable<SettingsProvider> FetchSettingProvidersFromAttribute()\n        {\n            var methods = AttributeHelper.GetMethodsWithAttribute<SettingsProviderGroupAttribute>();\n            return methods.methodsWithAttributes.SelectMany(method =>\n            {\n                try\n                {\n                    var callback = Delegate.CreateDelegate(typeof(Func<SettingsProvider[]>), method.info) as Func<SettingsProvider[]>;\n                    var providers = callback?.Invoke();\n                    if (providers != null)\n                    {\n                        return providers;\n                    }\n                }\n                catch (Exception)\n                {\n                    Debug.LogError(\"Cannot create Settings Providers for: \" + method.info.Name);\n                }\n\n                return new SettingsProvider[0];\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Settings/SettingsTreeView.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Linq;\nusing System.Collections.Generic;\nusing UnityEditor.Experimental;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEditor.StyleSheets;\nusing TreeView = UnityEditor.IMGUI.Controls.TreeView<int>;\nusing TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    internal class SettingsTreeView : TreeView\n    {\n        private struct SettingsNode\n        {\n            public string path;\n            public Dictionary<string, SettingsNode> children;\n        }\n\n        private static class Styles\n        {\n            public static StyleBlock tree => EditorResources.GetStyle(\"sb-settings-tree\");\n            public static GUIStyle listItem = \"SettingsListItem\";\n            public static GUIStyle treeItem = \"SettingsTreeItem\";\n        }\n\n        private bool m_ListViewMode;\n\n        public SettingsProvider[] providers { get; }\n        public SettingsProvider currentProvider { get; private set; }\n        public string searchContext { get; set; }\n\n        public delegate bool ProviderChangedHandler(SettingsProvider lastSelectedProvider, SettingsProvider newlySelectedProvider);\n        public event ProviderChangedHandler currentProviderChanged;\n\n        public SettingsTreeView(TreeViewState state, SettingsProvider[] providers)\n            : base(state)\n        {\n            this.providers = providers;\n            Reload();\n            ExpandAll();\n        }\n\n        public void FocusSelection(int selectedId)\n        {\n            List<int> selectedIDs = new List<int> { selectedId };\n            SetSelection(selectedIDs);\n            SelectionChanged(selectedIDs);\n        }\n\n        public List<SettingsProvider> GetChildrenAtPath(string path)\n        {\n            List<SettingsProvider> children = null;\n            var pathItem = FindItem(path.GetHashCode(), rootItem);\n            if (pathItem != null)\n                children = pathItem.children.Select(item => FindProviderById(item.id)).Where(p => p != null).ToList();\n            return children ?? new List<SettingsProvider>();\n        }\n\n        protected override bool CanMultiSelect(TreeViewItem item)\n        {\n            return false;\n        }\n\n        protected override void SelectionChanged(IList<int> selectedIds)\n        {\n            SettingsProvider selectedProvider = GetFirstValidProvider(selectedIds.Count > 0 ? selectedIds.First() : -1);\n            if (currentProviderChanged?.Invoke(currentProvider, selectedProvider) ?? true)\n                currentProvider = selectedProvider;\n        }\n\n        protected SettingsProvider GetFirstValidProvider(int id)\n        {\n            if (id == -1)\n                return null;\n\n            var treeViewItem = FindItem(id, rootItem);\n            var provider = FindProviderById(id);\n            while (provider == null && treeViewItem != null)\n            {\n                if (treeViewItem.children.Count <= 0)\n                    break;\n\n                treeViewItem = treeViewItem.children.First();\n                provider = FindProviderById(treeViewItem.id);\n            }\n\n            return provider;\n        }\n\n        private SettingsProvider FindProviderById(int id)\n        {\n            return providers.FirstOrDefault(p => p.settingsPath.GetHashCode() == id);\n        }\n\n        protected override void RowGUI(RowGUIArgs args)\n        {\n            var labelRect = args.rowRect;\n            var contentIndent = GetContentIndent(args.item);\n            if (!m_ListViewMode)\n            {\n                labelRect.xMin += contentIndent;\n            }\n\n            if (Styles.tree.GetBool(\"-unity-show-icon\") &&  args.item.icon != null)\n            {\n                const float k_IconSize = 16.0f;\n                var iconRect = labelRect;\n                iconRect.xMin -= k_IconSize;\n                iconRect.xMax = iconRect.xMin + k_IconSize;\n                GUI.DrawTexture(iconRect, args.item.icon);\n            }\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                var elementStyle = m_ListViewMode ? Styles.listItem : Styles.treeItem;\n                elementStyle.Draw(labelRect, args.item.displayName, args.rowRect.Contains(Event.current.mousePosition), HasFocus(), args.selected, false);\n            }\n        }\n\n        protected override bool DoesItemMatchSearch(TreeViewItem item, string search)\n        {\n            if (base.DoesItemMatchSearch(item, search))\n                return true;\n\n            var provider = FindProviderById(item.id);\n            return provider != null && provider.HasSearchInterest(search);\n        }\n\n        protected override void SearchChanged(string newSearch)\n        {\n            base.SearchChanged(newSearch);\n            var rows = GetRows();\n            if (rows.Count == 0)\n                return;\n            if (!GetSelection().Any(selectedId => rows.Any(r => r.id == selectedId)))\n                SetSelection(new[] { rows[0].id }, TreeViewSelectionOptions.FireSelectionChanged);\n        }\n\n        protected override TreeViewItem BuildRoot()\n        {\n            SettingsNode rootNode = new SettingsNode() { children = new Dictionary<string, SettingsNode>() };\n            BuildSettingsNodeTree(rootNode);\n\n            var allItems = new List<TreeViewItem>();\n            AppendSettingsNode(rootNode, \"\", 0, allItems);\n\n            var root = new TreeViewItem { id = 0, depth = -1, displayName = \"Root\" };\n            SetupParentsAndChildrenFromDepths(root, allItems);\n            return root;\n        }\n\n        private void BuildSettingsNodeTree(SettingsNode rootNode)\n        {\n            // If all provider have same root, hide the root name:\n            var allChildrenUnderSameRoot = true;\n            m_ListViewMode = true;\n            string rootName = null;\n            foreach (var provider in providers)\n            {\n                if (rootName == null)\n                    rootName = provider.pathTokens[0];\n\n                if (rootName != provider.pathTokens[0])\n                {\n                    allChildrenUnderSameRoot = false;\n                    m_ListViewMode = false;\n                }\n                else if (provider.pathTokens.Length > 2)\n                {\n                    m_ListViewMode = false;\n                }\n            }\n\n            foreach (var provider in providers)\n            {\n                SettingsNode current = rootNode;\n                var nodePath = allChildrenUnderSameRoot ? rootName : \"\";\n                for (var tokenIndex = allChildrenUnderSameRoot ?  1 : 0; tokenIndex < provider.pathTokens.Length; ++tokenIndex)\n                {\n                    var token = provider.pathTokens[tokenIndex];\n                    if (nodePath.Length > 0)\n                        nodePath += \"/\";\n                    nodePath += token;\n                    if (!current.children.ContainsKey(token))\n                    {\n                        current.children[token] = new SettingsNode() { path = nodePath, children = new Dictionary<string, SettingsNode>() };\n                    }\n\n                    current = current.children[token];\n                }\n            }\n        }\n\n        private void AppendSettingsNode(SettingsNode node, string rootPath, int depth, ICollection<TreeViewItem> items)\n        {\n            var sortedChildNames = node.children.Keys.ToList();\n            sortedChildNames.Sort();\n            foreach (var nodeName in sortedChildNames)\n            {\n                var childNode = node.children[nodeName];\n                var childNodePath = rootPath.Length == 0 ? nodeName : rootPath + \"/\" + nodeName;\n                var id = childNode.path.GetHashCode();\n                var provider = FindProviderById(id);\n                items.Add(new TreeViewItem { id = id, depth = depth, displayName = provider != null ? provider.label : nodeName, icon = provider?.icon });\n                AppendSettingsNode(childNode, childNodePath, depth + 1, items);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Settings/SettingsWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Text.RegularExpressions;\nusing UnityEditor.Experimental;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing UnityEditor.StyleSheets;\nusing UnityEngine.Bindings;\nusing TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;\n\nnamespace UnityEditor\n{\n    [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n    internal class SettingsWindow : EditorWindow, IHasCustomMenu\n    {\n        [SerializeField] private Vector2 m_PosLeft;\n        [SerializeField] private Vector2 m_PosRight;\n\n        [SerializeField] private SettingsScope m_Scope;\n        [SerializeField] public float m_SplitterPos;\n        [SerializeField] private string m_SearchText;\n        [SerializeField] private TreeViewState m_TreeViewState;\n\n        private SettingsProvider[] m_Providers;\n        private SettingsTreeView m_TreeView;\n        private TwoPaneSplitView m_Splitter;\n        private VisualElement m_SettingsPanel;\n        private VisualElement m_TreeViewContainer;\n        private VisualElement m_Toolbar;\n        private bool m_ProviderChanging;\n        private bool m_ProviderReloadNeeded;\n\n        private bool m_SearchFieldGiveFocus;\n        const string k_SearchField = \"SearchField\";\n        private const string k_MainSplitterViewDataKey =  \"settings-main-splitter__view-data-key\";\n\n        internal bool GuiCreated => m_SettingsPanel != null;\n\n        internal bool ProviderReloadNeeded => m_ProviderReloadNeeded;\n\n        struct ProviderChangingScope : IDisposable\n        {\n            SettingsWindow m_Window;\n\n            public ProviderChangingScope(SettingsWindow window)\n            {\n                m_Window = window;\n                window.m_ProviderChanging = true;\n            }\n\n            public void Dispose()\n            {\n                m_Window.m_ProviderChanging = false;\n            }\n        }\n\n        private static class ImguiStyles\n        {\n            public static readonly GUIStyle header = \"SettingsHeader\";\n            public const float searchFieldHeight = 20;\n            public const float searchFieldWidth = 300;\n        }\n\n        internal static class Styles\n        {\n            public static StyleBlock window => EditorResources.GetStyle(\"sb-settings-window\");\n            public static StyleBlock settingsPanel => EditorResources.GetStyle(\"sb-settings-panel-client-area\");\n            public static StyleBlock header => EditorResources.GetStyle(\"sb-settings-header\");\n\n            // FIXME: the highlight mesh is drawn *over* the text, hiding it. We have to reduce the alpha value of the highlight color\n            // in order to make the text readable. Blocked by jira https://jira.unity3d.com/browse/UUM-9296\n            private static float s_HighlightColorAlpha = 0.67f;\n\n            private static string s_SelectionColorTag = null;\n            public static string SelectionColorTag => s_SelectionColorTag\n                ??= $\"<mark=#{ColorUtility.ToHtmlStringRGBA(new Color(HighlightColor.r, HighlightColor.g, HighlightColor.b, s_HighlightColorAlpha))}>\";\n            public static readonly string SelectionColorEndTag = \"</mark>\";\n            private static string s_TextColorTag = null;\n            public static string TextColorTag => s_TextColorTag\n                ??= $\"<color=#{ColorUtility.ToHtmlStringRGBA(settingsPanel.GetColor(\"-unity-search-highlight-color\"))}>\";\n            public static readonly string TextColorEndTag = \"</color>\";\n            public static readonly Regex TagRegex = new(@\"<[^>]*>\", RegexOptions.Compiled);\n\n            private static Color HighlightColor => Styles.settingsPanel.GetColor(\"-unity-search-highlight-selection-color\");\n        }\n\n        public static float s_DefaultLabelWidth => Styles.window.GetFloat(\"-unity-label-width\");\n        public static float s_DefaultLayoutMaxWidth => Styles.window.GetFloat(\"-unity-max-layout-width\");\n\n        public SettingsWindow()\n            : this(SettingsScope.Project)\n        {\n        }\n\n        public SettingsWindow(SettingsScope scope)\n        {\n            m_Scope = scope;\n            titleContent.text = scope == SettingsScope.Project ? \"Project Settings\" : \"Preferences\";\n        }\n\n        internal SettingsProvider[] GetProviders()\n        {\n            return m_Providers;\n        }\n\n        internal SettingsProvider GetCurrentProvider()\n        {\n            return m_TreeView.currentProvider;\n        }\n\n        public void AddItemsToMenu(GenericMenu menu)\n        {\n            if (Unsupported.IsDeveloperMode())\n            {\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Print Provider Keywords\"), false, PrintProviderKeywords);\n                menu.AddItem(EditorGUIUtility.TrTextContent(\"Refresh providers\"), false, OnSettingsProviderChanged);\n            }\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal void SelectProviderByName(string name, bool ignoreLastSelected = true)\n        {\n            if (m_SettingsPanel == null)\n            {\n                SaveCurrentProvider(name);\n                return;\n            }\n\n            var currentSelection = m_TreeView.GetSelection();\n            var selectionID = name.GetHashCode();\n            // Check if the section is already selected to avoid the scroll bar to reset at the top of the window.\n            if (ignoreLastSelected || currentSelection.Count != 1 || currentSelection[0] != selectionID)\n                m_TreeView.FocusSelection(selectionID);\n        }\n\n        internal void OnLostFocus()\n        {\n            m_TreeView.currentProvider?.OnFocusLost();\n        }\n\n        internal void FilterProviders(string search)\n        {\n            m_SearchText = search;\n            m_TreeView.searchString = search;\n            Repaint();\n        }\n\n        internal int GetVisibleProviderCount()\n        {\n            return m_TreeView.GetRows().Count;\n        }\n\n        internal string GetPrefKeyName(string propName)\n        {\n            return $\"{nameof(SettingsWindow)}_{propName}\";\n        }\n\n        internal void OnEnable()\n        {\n            titleContent.image = EditorGUIUtility.IconContent(\"Settings\").image;\n\n            SettingsService.settingsProviderChanged -= OnSettingsProviderChanged;\n            SettingsService.settingsProviderChanged += OnSettingsProviderChanged;\n            SettingsService.repaintAllSettingsWindow -= OnRepaintAllWindows;\n            SettingsService.repaintAllSettingsWindow += OnRepaintAllWindows;\n            Undo.undoRedoEvent -= OnUndoRedoPerformed;\n            Undo.undoRedoEvent += OnUndoRedoPerformed;\n            EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;\n            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;\n\n            InitProviders();\n\n            // TODO : testing purposes to remove\n            // EditorApplication.delayCall += SetupGUI;\n        }\n\n        internal void OnDisable()\n        {\n            if (m_Splitter != null && m_Splitter.childCount >= 1)\n            {\n                EditorPrefs.SetFloat(GetPrefKeyName(nameof(m_SplitterPos)), m_Splitter.fixedPaneDimension);\n            }\n\n            DeactivateAndSaveCurrentProvider();\n\n            SettingsService.settingsProviderChanged -= OnSettingsProviderChanged;\n            SettingsService.repaintAllSettingsWindow -= OnRepaintAllWindows;\n            Undo.undoRedoEvent -= OnUndoRedoPerformed;\n            EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;\n        }\n\n        void CreateGUI()\n        {\n            // TODO : testing purposes to reenable\n            SetupGUI();\n        }\n\n        internal void Update()\n        {\n            if (m_ProviderReloadNeeded)\n                ReloadProviders();\n        }\n\n        void SetupGUI()\n        {\n            var root = rootVisualElement;\n            root.AddStyleSheetPath(\"StyleSheets/SettingsWindowCommon.uss\");\n            root.AddStyleSheetPath($\"StyleSheets/SettingsWindow{(EditorGUIUtility.isProSkin ? \"Dark\" : \"Light\")}.uss\");\n\n            root.style.flexDirection = FlexDirection.Column;\n\n            m_Toolbar = new IMGUIContainer(DrawToolbar);\n            root.Add(m_Toolbar);\n\n            m_SplitterPos = EditorPrefs.GetFloat(GetPrefKeyName(nameof(m_SplitterPos)), 150f);\n            m_Splitter = new TwoPaneSplitView(0, m_SplitterPos, TwoPaneSplitViewOrientation.Horizontal)\n            {\n                name = \"SettingsSplitter\",\n                viewDataKey = k_MainSplitterViewDataKey\n            };\n            m_Splitter.AddToClassList(\"settings-splitter\");\n            root.Add(m_Splitter);\n\n            m_TreeViewContainer = new IMGUIContainer(DrawTreeView)\n            {\n                focusOnlyIfHasFocusableControls = false,\n            };\n            m_TreeViewContainer.AddToClassList(\"settings-tree-imgui-container\");\n            m_Splitter.Add(m_TreeViewContainer);\n\n            m_SettingsPanel = new VisualElement();\n            m_SettingsPanel.AddToClassList(\"settings-panel\");\n            m_Splitter.Add(m_SettingsPanel);\n\n\n            // Restore selection after setting the ProviderChanged callback so we can activate the initial selected provider\n            RestoreSelection();\n        }\n\n        internal void InitProviders()\n        {\n            m_Providers = SettingsService.FetchSettingsProviders(m_Scope);\n            foreach (var provider in m_Providers)\n            {\n                provider.settingsWindow = this;\n                if (!provider.icon)\n                {\n                    provider.icon = EditorGUIUtility.FindTexture(\"UnityEditor/EditorSettings Icon\");\n                }\n            }\n\n            if (m_TreeView != null)\n            {\n                m_TreeView.currentProviderChanged -= ProviderChanged;\n            }\n            m_TreeViewState = m_TreeViewState ?? new TreeViewState();\n            m_TreeView = new SettingsTreeView(m_TreeViewState, m_Providers);\n            m_TreeView.searchString = m_SearchText = m_SearchText ?? string.Empty;\n            m_TreeView.currentProviderChanged += ProviderChanged;\n        }\n\n        internal void OnInspectorUpdate()\n        {\n            m_TreeView.currentProvider?.OnInspectorUpdate();\n        }\n\n        private void OnUndoRedoPerformed(in UndoRedoInfo info)\n        {\n            Repaint();\n        }\n\n        private void OnRepaintAllWindows()\n        {\n            Repaint();\n        }\n\n        private void OnPlayModeStateChanged(PlayModeStateChange state)\n        {\n            if (m_TreeView.currentProvider != null)\n            {\n                if (state == PlayModeStateChange.ExitingEditMode)\n                {\n                    ProviderChanged(m_TreeView.currentProvider, null);\n                }\n                else if (state == PlayModeStateChange.EnteredEditMode)\n                {\n                    RestoreSelection();\n                }\n            }\n        }\n\n        private void PrintProviderKeywords()\n        {\n            var sb = new StringBuilder();\n            foreach (var settingsProvider in m_Providers)\n            {\n                sb.AppendLine(settingsProvider.label);\n                foreach (var keyword in settingsProvider.keywords)\n                {\n                    sb.Append(\"    \");\n                    sb.AppendLine(keyword);\n                }\n            }\n            File.WriteAllText(\"settings_keywords.txt\", sb.ToString());\n        }\n\n        private void OnSettingsProviderChanged()\n        {\n            // Prevent infinite changing\n            if (m_ProviderChanging)\n                return;\n\n            m_ProviderReloadNeeded = true;\n        }\n\n        void ReloadProviders()\n        {\n            // Prevent recursive changing\n            if (m_ProviderChanging)\n                return;\n            DeactivateAndSaveCurrentProvider();\n            InitProviders();\n            RestoreSelection();\n            Repaint();\n            m_ProviderReloadNeeded = false;\n        }\n\n        private void RestoreSelection()\n        {\n            var lastSelectedProvider = GetSavedCurrentProvider();\n            if (!string.IsNullOrEmpty(lastSelectedProvider) && Array.Find(m_Providers, provider => provider.settingsPath == lastSelectedProvider) != null)\n            {\n                SelectProviderByName(lastSelectedProvider);\n            }\n            else if (m_Providers.Length > 0)\n            {\n                SelectProviderByName(m_Providers[0].settingsPath);\n            }\n        }\n\n        private bool ProviderChanged(SettingsProvider lastSelectedProvider, SettingsProvider newlySelectedProvider)\n        {\n            if (m_SettingsPanel == null)\n                return false;\n\n            using var pcd = new ProviderChangingScope(this);\n            // If we fail to deactivate the last provider, still continue to select the new one.\n            try\n            {\n                lastSelectedProvider?.Deactivate();\n            }\n            catch (Exception e)\n            {\n                Debug.LogException(e);\n            }\n            m_SettingsPanel.Clear();\n\n            if (newlySelectedProvider != null)\n            {\n                // If activating the new provider fails, restore the last selected provider.\n                try\n                {\n                    newlySelectedProvider?.Activate(m_SearchText, m_SettingsPanel);\n                    EditorPrefs.SetString(GetPrefKeyName(titleContent.text + \"_current_provider\"), newlySelectedProvider.settingsPath);\n                }\n                catch (Exception e)\n                {\n                    Debug.LogException(e);\n                    RestoreSelection();\n                    return false;\n                }\n            }\n\n            SetupIMGUIForCurrentProviderIfNeeded();\n            return true;\n        }\n\n        internal void SetupIMGUIForCurrentProviderIfNeeded()\n        {\n            if (m_SettingsPanel.childCount == 0)\n            {\n                var imguiContainer = new IMGUIContainer(DrawSettingsPanel);\n                imguiContainer.AddToClassList(\"settings-panel-imgui-container\");\n                m_SettingsPanel.Add(imguiContainer);\n            }\n        }\n\n        private void SetupWindowPosition()\n        {\n            var minWidth = Styles.window.GetFloat(\"min-width\");\n            // To accomodate some large labels in the settings window, min-width is being increase (case 1282739)\n            minWidth += 10;\n            var minHeight = Styles.window.GetFloat(\"min-height\");\n            minSize = new Vector2(minWidth, minHeight);\n\n            // Center the window if it has never been opened by the user.\n            if (EditorPrefs.HasKey($\"{this.GetType().FullName}h\"))\n                return; // Do nothing if the window was opened previously.\n\n            var initialWidth = Styles.window.GetFloat(\"-unity-initial-width\");\n            var initialHeight = Styles.window.GetFloat(\"-unity-initial-height\");\n            var containers = Resources.FindObjectsOfTypeAll(typeof(ContainerWindow));\n\n            Vector2 initialSize = new Vector2(Mathf.Min(initialWidth, Screen.width), Mathf.Min(initialHeight, Screen.height));\n            foreach (ContainerWindow window in containers)\n            {\n                if (window.showMode == ShowMode.MainWindow)\n                {\n                    position = new Rect(window.position.center - (initialSize / 2), initialSize);\n                    break;\n                }\n            }\n        }\n\n        private static void UpdateSearchHighlight(VisualElement container, string searchText)\n        {\n            container.Query(null, \"settings-panel\").Descendents<Label>().ForEach((label) =>\n            {\n                var text = label.text;\n                var hasHighlight = Styles.TagRegex.IsMatch(text);\n                text = Styles.TagRegex.Replace(text, String.Empty);\n                if (!SearchUtils.MatchSearchGroups(searchText, text, out var startHighlight, out var endHighlight))\n                {\n                    if (hasHighlight)\n                        label.text = text;\n                    return;\n                }\n\n                text = text.Insert(startHighlight, Styles.SelectionColorTag);\n                text = text.Insert(endHighlight + Styles.SelectionColorTag.Length + 1, Styles.SelectionColorEndTag);\n                text = $\"{Styles.TextColorTag}{text}{Styles.TextColorEndTag}\";\n                label.text = text;\n            });\n        }\n\n        private void DrawToolbar()\n        {\n            GUILayout.BeginHorizontal(EditorStyles.toolbar);\n            GUILayout.FlexibleSpace();\n\n            var e = Event.current;\n            if (e.commandName == EventCommandNames.Find)\n            {\n                if (e.type == EventType.ExecuteCommand)\n                {\n                    EditorGUI.FocusTextInControl(k_SearchField);\n                }\n\n                if (e.type != EventType.Layout)\n                    e.Use();\n            }\n\n            if (e.type == EventType.KeyDown)\n            {\n                if (e.keyCode == KeyCode.Escape || ((e.keyCode == KeyCode.UpArrow || e.keyCode == KeyCode.DownArrow) &&\n                                                    GUI.GetNameOfFocusedControl() == k_SearchField))\n                {\n                    m_SearchText = string.Empty;\n                    HandleSearchFiltering();\n                    GUIUtility.keyboardControl = m_TreeView.treeViewControlID;\n\n                    EditorApplication.delayCall += () =>\n                    {\n                        m_TreeViewContainer.Focus();\n                    };\n\n                    Repaint();\n                }\n            }\n\n            GUI.SetNextControlName(k_SearchField);\n            var searchTextRect = GUILayoutUtility.GetRect(0, ImguiStyles.searchFieldWidth, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.toolbarSearchField);\n            var searchText = EditorGUI.ToolbarSearchField(searchTextRect, m_SearchText, false);\n            if (e.type == EventType.Repaint && m_SearchFieldGiveFocus)\n            {\n                m_SearchFieldGiveFocus = false;\n                EditorGUI.FocusTextInControl(k_SearchField);\n            }\n\n            if (searchText != m_SearchText)\n            {\n                m_SearchText = searchText;\n                HandleSearchFiltering();\n            }\n\n            GUILayout.EndHorizontal();\n        }\n\n        internal string GetSearchText()\n        {\n            return m_SearchText;\n        }\n\n        private void DrawSettingsPanel()\n        {\n            if (m_TreeView.currentProvider == null)\n                return;\n\n            DrawTitleBar();\n\n            using (var scrollViewScope = new EditorGUILayout.ScrollViewScope(m_PosRight, GUILayout.ExpandWidth(true)))\n            {\n                m_PosRight = scrollViewScope.scrollPosition;\n                DrawControls();\n            }\n\n            DrawFooterBar();\n\n            var e = Event.current;\n            if (GUI.GetNameOfFocusedControl() == k_SearchField && e.type == EventType.MouseDown && e.button == 0)\n            {\n                m_SettingsPanel.Focus();\n                GUIUtility.keyboardControl = 0;\n            }\n        }\n\n        private void DrawControls()\n        {\n            using (new EditorGUI.LabelHighlightScope(m_SearchText, Styles.settingsPanel.GetColor(\"-unity-search-highlight-selection-color\"), Styles.settingsPanel.GetColor(\"-unity-search-highlight-color\")))\n            {\n                var currentWideMode = EditorGUIUtility.wideMode;\n                var inspectorWidth = m_SettingsPanel.layout.width;\n                // the inspector's width can be NaN if this is our first layout check.\n                // If that's the case we'll set wideMode to true to avoid computing too tall an inspector on the first layout calculation\n                if (!float.IsNaN(inspectorWidth))\n                {\n                    EditorGUIUtility.wideMode = inspectorWidth > Editor.k_WideModeMinWidth;\n                }\n                else\n                {\n                    EditorGUIUtility.wideMode = true;\n                }\n                m_TreeView.currentProvider.OnGUI(m_SearchText);\n                EditorGUIUtility.wideMode = currentWideMode;\n            }\n        }\n\n        private void DrawTitleBar()\n        {\n            GUILayout.BeginHorizontal();\n            GUILayout.Space(Styles.settingsPanel.GetFloat(StyleCatalogKeyword.marginLeft));\n            var headerContent = new GUIContent(m_TreeView.currentProvider.label, Styles.header.GetBool(\"-unity-show-icon\") ? m_TreeView.currentProvider.icon : null);\n            GUILayout.Label(headerContent, ImguiStyles.header, GUILayout.MaxHeight(Styles.header.GetFloat(\"max-height\")), GUILayout.MinWidth(160));\n            GUILayout.FlexibleSpace();\n            m_TreeView.currentProvider.OnTitleBarGUI();\n            GUILayout.EndHorizontal();\n        }\n\n        private void DrawFooterBar()\n        {\n            m_TreeView.currentProvider.OnFooterBarGUI();\n        }\n\n        private void DrawTreeView()\n        {\n            // Splitter's fixedPane might only be available in the next `GeometryChangedEvent`.\n            var splitterRect = m_Splitter.fixedPane?.layout ?? Rect.zero;\n            var splitterPos = splitterRect.xMax;\n            var treeWidth = splitterPos;\n            using (var scrollViewScope = new GUILayout.ScrollViewScope(m_PosLeft, GUILayout.Width(splitterPos), GUILayout.MaxWidth(splitterPos), GUILayout.MinWidth(splitterPos)))\n            {\n                m_PosLeft = scrollViewScope.scrollPosition;\n                m_TreeView.OnGUI(new Rect(0, Styles.window.GetFloat(\"margin-top\"), treeWidth, position.height - ImguiStyles.searchFieldHeight - Styles.window.GetFloat(\"margin-top\")));\n            }\n        }\n\n        private void HandleSearchFiltering()\n        {\n            m_TreeView.searchString = m_SearchText;\n            UpdateSearchHighlight(m_SettingsPanel, m_SearchText);\n        }\n\n        void DeactivateAndSaveCurrentProvider()\n        {\n            if (m_TreeView.currentProvider != null)\n            {\n                using var _ = new ProviderChangingScope(this);\n                try\n                {\n                    m_TreeView.currentProvider.Deactivate();\n                    SaveCurrentProvider(m_TreeView.currentProvider.settingsPath);\n                }\n                catch (Exception e)\n                {\n                    Debug.LogException(e);\n                }\n            }\n        }\n\n        string GetSavedCurrentProvider()\n        {\n            return EditorPrefs.GetString(GetPrefKeyName(titleContent.text + \"_current_provider\"), \"\");\n        }\n\n        void SaveCurrentProvider(string settingsPath)\n        {\n            EditorPrefs.SetString(GetPrefKeyName(titleContent.text + \"_current_provider\"), settingsPath);\n        }\n\n        [MenuItem(\"Edit/Project Settings...\", false, 20000, false)]\n        internal static void OpenProjectSettings()\n        {\n            SendTopMenuProjectSettingsEvent();\n            Show(SettingsScope.Project);\n        }\n\n        static void SendTopMenuProjectSettingsEvent()\n        {\n            EditorAnalytics.SendEventEditorGameService(new EditorGameServiceEvent\n            {\n                action = \"Project Settings\",\n                assembly_info = \"\",\n                component = \"Top Menu\",\n                package = \"Unity Editor\",\n                package_ver = \"\"\n            });\n        }\n\n        [Serializable]\n        internal struct EditorGameServiceEvent\n        {\n            public string action;\n            public string assembly_info;\n            public string component;\n            public string package;\n            public string package_ver;\n        }\n\n        internal static SettingsWindow OpenUserPreferences()\n        {\n            return Show(SettingsScope.User);\n        }\n\n        private static SettingsWindow Create(SettingsScope scope)\n        {\n            if (scope == SettingsScope.Project)\n                return CreateInstance<ProjectSettingsWindow>();\n\n            return CreateInstance<PreferenceSettingsWindow>();\n        }\n\n        internal static SettingsWindow Show(SettingsScope scopes, string settingsPath = null)\n        {\n            var settingsWindow = FindWindowByScope(scopes);\n            if (settingsWindow != null)\n                EditorGUI.FocusTextInControl(k_SearchField);\n            else\n                settingsWindow = Create(scopes);\n\n            bool ignoreLastSelection = false;\n            if (!settingsWindow.hasFocus)\n            {\n                settingsWindow.Show();\n                settingsWindow.SetupWindowPosition();\n                settingsWindow.Focus();\n                ignoreLastSelection = true;\n            }\n\n            if (settingsPath != null)\n            {\n                settingsWindow.SelectProviderByName(settingsPath, ignoreLastSelection);\n            }\n\n            EditorApplication.delayCall += () =>\n            {\n                settingsWindow.Focus();\n                settingsWindow.m_SearchFieldGiveFocus = true;\n            };\n\n            return settingsWindow;\n        }\n\n        internal static SettingsWindow FindWindowByScope(SettingsScope scopes)\n        {\n            var settingsWindows = Resources.FindObjectsOfTypeAll(typeof(SettingsWindow)).Cast<SettingsWindow>();\n            return settingsWindows.FirstOrDefault(settingsWindow => settingsWindow.m_Scope == scopes);\n        }\n\n        internal class GUIScope : GUI.Scope\n        {\n            float m_LabelWidth;\n            public GUIScope(float layoutMaxWidth)\n            {\n                m_LabelWidth = EditorGUIUtility.labelWidth;\n                EditorGUIUtility.labelWidth = s_DefaultLabelWidth;\n                GUILayout.BeginHorizontal();\n                GUILayout.Space(Styles.settingsPanel.GetFloat(StyleCatalogKeyword.marginLeft));\n                GUILayout.BeginVertical();\n                GUILayout.Space(Styles.settingsPanel.GetFloat(StyleCatalogKeyword.marginTop));\n            }\n\n            public GUIScope() : this(s_DefaultLayoutMaxWidth)\n            {\n            }\n\n            protected override void CloseScope()\n            {\n                GUILayout.EndVertical();\n                GUILayout.EndHorizontal();\n                EditorGUIUtility.labelWidth = m_LabelWidth;\n            }\n        }\n    }\n\n    [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n    internal class ProjectSettingsWindow : SettingsWindow\n    {\n        public ProjectSettingsWindow()\n            : base(SettingsScope.Project)\n        {\n        }\n    }\n\n    internal class PreferenceSettingsWindow : SettingsWindow\n    {\n        public PreferenceSettingsWindow()\n            : base(SettingsScope.User)\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Settings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEditor;\nusing System.Collections.Generic;\nusing System;\nusing System.Globalization;\nusing System.Linq;\n\nnamespace UnityEditor\n{\n    internal interface IPrefType\n    {\n        string ToUniqueString();\n        void FromUniqueString(string sstr);\n        void Load();\n    }\n\n    internal class PrefColor : IPrefType\n    {\n        string m_Name;\n        Color m_Color;\n        Color m_DefaultColor;\n\n        bool m_SeparateColors;\n        Color m_OptionalDarkColor;\n        Color m_OptionalDarkDefaultColor;\n\n        bool m_Loaded;\n\n        public PrefColor()\n        {\n            m_Loaded = true;\n        }\n\n        public PrefColor(string name, float defaultRed, float defaultGreen, float defaultBlue, float defaultAlpha)\n        {\n            this.m_Name = name;\n            this.m_Color = this.m_DefaultColor = new Color(defaultRed, defaultGreen, defaultBlue, defaultAlpha);\n            this.m_SeparateColors = false;\n            this.m_OptionalDarkColor = this.m_OptionalDarkDefaultColor = Color.clear;\n            PrefSettings.Add(this);\n            m_Loaded = false;\n        }\n\n        public PrefColor(string name, float defaultRed, float defaultGreen, float defaultBlue, float defaultAlpha, float defaultRed2, float defaultGreen2, float defaultBlue2, float defaultAlpha2)\n        {\n            this.m_Name = name;\n            this.m_Color = this.m_DefaultColor = new Color(defaultRed, defaultGreen, defaultBlue, defaultAlpha);\n            this.m_SeparateColors = true;\n            this.m_OptionalDarkColor = this.m_OptionalDarkDefaultColor = new Color(defaultRed2, defaultGreen2, defaultBlue2, defaultAlpha2);\n            PrefSettings.Add(this);\n            m_Loaded = false;\n        }\n\n        public void Load()\n        {\n            if (m_Loaded)\n                return;\n\n            m_Loaded = true;\n\n            PrefColor pk = PrefSettings.Get(m_Name, this);\n            this.m_Name = pk.m_Name;\n            this.m_Color = pk.m_Color;\n            this.m_SeparateColors = pk.m_SeparateColors;\n            this.m_OptionalDarkColor = pk.m_OptionalDarkColor;\n        }\n\n        public Color Color\n        {\n            get\n            {\n                Load();\n\n                if (m_SeparateColors && EditorGUIUtility.isProSkin)\n                    return m_OptionalDarkColor;\n\n                return m_Color;\n            }\n            set\n            {\n                Load();\n\n                if (m_SeparateColors && EditorGUIUtility.isProSkin)\n                    m_OptionalDarkColor = value;\n                else\n                    m_Color = value;\n            }\n        }\n        public string Name { get { Load(); return m_Name; } }\n\n        public static implicit operator Color(PrefColor pcolor) { return pcolor.Color; }\n\n        public string ToUniqueString()\n        {\n            Load();\n\n            if (m_SeparateColors)\n                return string.Format(\"{0};{1};{2};{3};{4};{5};{6};{7};{8}\", m_Name, m_Color.r, m_Color.g, m_Color.b, m_Color.a, m_OptionalDarkColor.r, m_OptionalDarkColor.g, m_OptionalDarkColor.b, m_OptionalDarkColor.a);\n\n            return string.Format(\"{0};{1};{2};{3};{4}\", m_Name, m_Color.r, m_Color.g, m_Color.b, m_Color.a);\n        }\n\n        public void FromUniqueString(string s)\n        {\n            Load();\n\n            string[] split = s.Split(';');\n\n            // PrefColor with a single color should have 5 substrings.\n            // PrefColor with separate colors should have 9 substrings.\n            if (split.Length != 5 && split.Length != 9)\n            {\n                Debug.LogError(\"Parsing PrefColor failed\");\n                return;\n            }\n\n            m_Name = split[0];\n            split[1] = split[1].Replace(',', '.');\n            split[2] = split[2].Replace(',', '.');\n            split[3] = split[3].Replace(',', '.');\n            split[4] = split[4].Replace(',', '.');\n            float r, g, b, a;\n            bool success = float.TryParse(split[1], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out r);\n            success &= float.TryParse(split[2], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out g);\n            success &= float.TryParse(split[3], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out b);\n            success &= float.TryParse(split[4], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out a);\n\n            if (success)\n            {\n                m_Color = new Color(r, g, b, a);\n            }\n            else\n            {\n                Debug.LogError(\"Parsing PrefColor failed\");\n            }\n\n            if (split.Length == 9)\n            {\n                m_SeparateColors = true;\n\n                split[5] = split[5].Replace(',', '.');\n                split[6] = split[6].Replace(',', '.');\n                split[7] = split[7].Replace(',', '.');\n                split[8] = split[8].Replace(',', '.');\n                success = float.TryParse(split[5], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out r);\n                success &= float.TryParse(split[6], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out g);\n                success &= float.TryParse(split[7], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out b);\n                success &= float.TryParse(split[8], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out a);\n\n                if (success)\n                {\n                    m_OptionalDarkColor = new Color(r, g, b, a);\n                }\n                else\n                {\n                    Debug.LogError(\"Parsing PrefColor failed\");\n                }\n            }\n            else\n            {\n                m_SeparateColors = false;\n                m_OptionalDarkColor = Color.clear;\n            }\n        }\n\n        internal void ResetToDefault()\n        {\n            Load();\n            m_Color = m_DefaultColor;\n            m_OptionalDarkColor = m_OptionalDarkDefaultColor;\n        }\n    }\n\n    internal class PrefSettings\n    {\n        static List<IPrefType> m_AddedPrefs = new List<IPrefType>();\n        static SortedList<string, object> m_Prefs = new SortedList<string, object>();\n        public static Action<string, Type> settingChanged;\n\n        static internal void Add(IPrefType value)\n        {\n            m_AddedPrefs.Add(value);\n        }\n\n        static internal T Get<T>(string name, T defaultValue)\n            where T : IPrefType, new()\n        {\n            Load();\n\n            if (defaultValue == null)\n                throw new System.ArgumentException(\"default can not be null\", \"defaultValue\");\n            if (m_Prefs.ContainsKey(name))\n                return (T)m_Prefs[name];\n            else\n            {\n                string sstr = EditorPrefs.GetString(name, \"\");\n                if (sstr == \"\")\n                {\n                    Set(name, defaultValue);\n                    return defaultValue;\n                }\n                else\n                {\n                    defaultValue.FromUniqueString(sstr);\n                    Set(name, defaultValue);\n                    return defaultValue;\n                }\n            }\n        }\n\n        static internal void Set<T>(string name, T value)\n            where T : IPrefType\n        {\n            Load();\n\n            EditorPrefs.SetString(name, value.ToUniqueString());\n            m_Prefs[name] = value;\n            settingChanged?.Invoke(name, typeof(T));\n        }\n\n        static internal IEnumerable<KeyValuePair<string, T>> Prefs<T>()\n            where T : IPrefType\n        {\n            Load();\n\n            foreach (KeyValuePair<string, object> kvp in m_Prefs)\n            {\n                if (kvp.Value is T)\n                    yield return new KeyValuePair<string, T>(kvp.Key, (T)kvp.Value);\n            }\n        }\n\n        static internal void RevertAll<T>()\n        {\n            foreach (KeyValuePair<string, PrefColor> kvp in Prefs<PrefColor>())\n            {\n                kvp.Value.ResetToDefault();\n                EditorPrefs.SetString(kvp.Value.Name, kvp.Value.ToUniqueString());\n                settingChanged?.Invoke(kvp.Key, typeof(T));\n            }\n        }\n\n        static void Load()\n        {\n            if (!m_AddedPrefs.Any())\n                return;\n\n            List<IPrefType> loadPrefs = new List<IPrefType>(m_AddedPrefs);\n            m_AddedPrefs.Clear();\n\n            foreach (IPrefType pref in loadPrefs)\n                pref.Load();\n        }\n    }\n\n    internal class SavedInt\n    {\n        int m_Value;\n        string m_Name;\n        bool m_Loaded;\n\n        public SavedInt(string name, int value)\n        {\n            m_Name = name;\n            m_Loaded = false;\n            m_Value = value;\n        }\n\n        private void Load()\n        {\n            if (m_Loaded)\n                return;\n\n            m_Loaded = true;\n            m_Value = EditorPrefs.GetInt(m_Name, m_Value);\n        }\n\n        public int value\n        {\n            get { Load(); return m_Value; }\n            set\n            {\n                Load();\n                if (m_Value == value)\n                    return;\n                m_Value = value;\n                EditorPrefs.SetInt(m_Name, value);\n            }\n        }\n\n        public static implicit operator int(SavedInt s)\n        {\n            return s.value;\n        }\n    }\n\n    internal class SavedFloat\n    {\n        float m_Value;\n        string m_Name;\n        bool m_Loaded;\n\n        public SavedFloat(string name, float value)\n        {\n            m_Name = name;\n            m_Loaded = false;\n            m_Value = value;\n        }\n\n        private void Load()\n        {\n            if (m_Loaded)\n                return;\n\n            m_Loaded = true;\n            m_Value = EditorPrefs.GetFloat(m_Name, m_Value);\n        }\n\n        public float value\n        {\n            get { Load(); return m_Value; }\n            set\n            {\n                Load();\n                if (m_Value == value)\n                    return;\n                m_Value = value;\n                EditorPrefs.SetFloat(m_Name, value);\n            }\n        }\n\n        public static implicit operator float(SavedFloat s)\n        {\n            return s.value;\n        }\n    }\n\n    internal class SavedBool\n    {\n        bool m_Value;\n        string m_Name;\n        bool m_Loaded;\n\n        public SavedBool(string name, bool value)\n        {\n            m_Name = name;\n            m_Loaded = false;\n            m_Value = value;\n        }\n\n        private void Load()\n        {\n            if (m_Loaded)\n                return;\n\n            m_Loaded = true;\n            m_Value = EditorPrefs.GetBool(m_Name, m_Value);\n        }\n\n        public bool value\n        {\n            get { Load(); return m_Value; }\n            set\n            {\n                Load();\n                if (m_Value == value)\n                    return;\n                m_Value = value;\n                EditorPrefs.SetBool(m_Name, value);\n            }\n        }\n\n        public static implicit operator bool(SavedBool s)\n        {\n            return s.value;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SettingsWindow/FogEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(RenderSettings))]\n    internal class FogEditor : Editor\n    {\n        internal class Styles\n        {\n            public static readonly GUIContent FogWarning = EditorGUIUtility.TrTextContent(\"Fog has no effect on opaque objects when using Deferred Shading rendering. Use the Global Fog image effect instead, which supports opaque objects.\");\n            public static readonly GUIContent FogDensity = EditorGUIUtility.TrTextContent(\"Density\", \"Controls the density of the fog effect in the Scene when using Exponential or Exponential Squared modes.\");\n            public static readonly GUIContent FogLinearStart = EditorGUIUtility.TrTextContent(\"Start\", \"Controls the distance from the camera where the fog will start in the Scene.\");\n            public static readonly GUIContent FogLinearEnd = EditorGUIUtility.TrTextContent(\"End\", \"Controls the distance from the camera where the fog will completely obscure objects in the Scene.\");\n            public static readonly GUIContent FogEnable = EditorGUIUtility.TrTextContent(\"Fog\", \"Specifies whether fog is used in the Scene or not.\");\n            public static readonly GUIContent FogColor = EditorGUIUtility.TrTextContent(\"Color\", \"Controls the color of the fog drawn in the Scene.\");\n            public static readonly GUIContent FogMode = EditorGUIUtility.TrTextContent(\"Mode\", \"Controls the mathematical function determining the way fog accumulates with distance from the camera. Options are Linear, Exponential, and Exponential Squared.\");\n        }\n\n        protected SerializedProperty m_Fog;\n        protected SerializedProperty m_FogColor;\n        protected SerializedProperty m_FogMode;\n        protected SerializedProperty m_FogDensity;\n        protected SerializedProperty m_LinearFogStart;\n        protected SerializedProperty m_LinearFogEnd;\n\n        protected SerializedObject m_RenderSettings;\n\n        SerializedObject renderSettings\n        {\n            get\n            {\n                // if we set a new scene as the active scene, we need to make sure to respond to those changes\n                if (m_RenderSettings == null || m_RenderSettings.targetObject != RenderSettings.GetRenderSettings())\n                {\n                    m_RenderSettings = new SerializedObject(RenderSettings.GetRenderSettings());\n\n                    m_Fog = m_RenderSettings.FindProperty(\"m_Fog\");\n                    m_FogColor = m_RenderSettings.FindProperty(\"m_FogColor\");\n                    m_FogMode = m_RenderSettings.FindProperty(\"m_FogMode\");\n                    m_FogDensity = m_RenderSettings.FindProperty(\"m_FogDensity\");\n                    m_LinearFogStart = m_RenderSettings.FindProperty(\"m_LinearFogStart\");\n                    m_LinearFogEnd = m_RenderSettings.FindProperty(\"m_LinearFogEnd\");\n                }\n\n                return m_RenderSettings;\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            renderSettings.Update();\n\n            EditorGUILayout.PropertyField(m_Fog, Styles.FogEnable);\n            if (m_Fog.boolValue)\n            {\n                EditorGUI.indentLevel++;\n                EditorGUILayout.PropertyField(m_FogColor, Styles.FogColor);\n                EditorGUILayout.PropertyField(m_FogMode, Styles.FogMode);\n\n                if ((FogMode)m_FogMode.intValue != FogMode.Linear)\n                {\n                    m_FogDensity.floatValue = EditorGUILayout.PowerSlider(Styles.FogDensity, m_FogDensity.floatValue, 0.0f, 1.0f, 2.0f);\n                }\n                else\n                {\n                    EditorGUILayout.PropertyField(m_LinearFogStart, Styles.FogLinearStart);\n                    EditorGUILayout.PropertyField(m_LinearFogEnd, Styles.FogLinearEnd);\n                }\n\n                if (SceneView.IsUsingDeferredRenderingPath())\n                    EditorGUILayout.HelpBox(Styles.FogWarning.text, MessageType.Info);\n\n                EditorGUI.indentLevel--;\n                EditorGUILayout.Space();\n            }\n\n            renderSettings.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SettingsWindow/LightingEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing System.Collections.Generic;\nusing UnityEngine.Rendering;\nusing UnityEditor.AnimatedValues;\nusing System.Linq;\n\nnamespace UnityEditor\n{\n    internal enum DefaultReflectionMode\n    {\n        FromSkybox = 0,\n        Custom\n    }\n\n    [CustomEditor(typeof(RenderSettings))]\n    internal class LightingEditor : Editor\n    {\n        internal static class Styles\n        {\n            static Styles() {}\n\n            public static readonly GUIContent env_top = EditorGUIUtility.TrTextContent(\"Environment\");\n            public static readonly GUIContent env_skybox_mat = EditorGUIUtility.TrTextContent(\"Skybox Material\", \"Specifies the material that is used to simulate the sky or other distant background in the Scene.\");\n            public static readonly GUIContent env_skybox_sun = EditorGUIUtility.TrTextContent(\"Sun Source\", \"Specifies the directional light that is used to indicate the direction of the sun when a procedural skybox is used. If set to None, the brightest directional light in the Scene is used to represent the sun.\");\n            public static readonly GUIContent env_amb_top = EditorGUIUtility.TrTextContent(\"Environment Lighting\");\n            public static readonly GUIContent env_amb_src = EditorGUIUtility.TrTextContent(\"Source\", \"Specifies whether to use a skybox, gradient, or color for ambient light contributed to the Scene.\");\n            public static readonly GUIContent env_amb_int = EditorGUIUtility.TrTextContent(\"Intensity Multiplier\", \"Controls the brightness of the skybox lighting in the Scene.\");\n            public static readonly GUIContent env_refl_top = EditorGUIUtility.TrTextContent(\"Environment Reflections\");\n            public static readonly GUIContent env_refl_src = EditorGUIUtility.TrTextContent(\"Source\", \"Specifies whether to use the skybox or a custom cube map for reflection effects in the Scene.\");\n            public static readonly GUIContent env_refl_res = EditorGUIUtility.TrTextContent(\"Resolution\", \"Controls the resolution for the cube map assigned to the skybox material for reflection effects in the Scene.\");\n            public static readonly GUIContent env_refl_cmp = EditorGUIUtility.TrTextContent(\"Compression\", \"Controls how Unity compresses the reflection cube maps. Options are Auto, Compressed, and Uncompressed. Auto compresses the cube maps if the compression format is suitable.\");\n            public static readonly GUIContent env_refl_int = EditorGUIUtility.TrTextContent(\"Intensity Multiplier\", \"Controls how much the skybox or custom cubemap affects reflections in the Scene. A value of 1 produces physically correct results.\");\n            public static readonly GUIContent env_refl_bnc = EditorGUIUtility.TrTextContent(\"Bounces\", \"Controls how many times a reflection includes other reflections. A value of 1 results in the Scene being rendered once so mirrored reflections will be black. A value of 2 results in mirrored reflections being visible in the Scene.\");\n            public static readonly GUIContent skyboxWarning = EditorGUIUtility.TrTextContent(\"Shader of this material does not support skybox rendering.\");\n            public static readonly GUIContent createLight = EditorGUIUtility.TrTextContent(\"Create Light\");\n            public static readonly GUIContent ambientUp = EditorGUIUtility.TrTextContent(\"Sky Color\", \"Controls the color of light emitted from the sky in the Scene.\");\n            public static readonly GUIContent ambientMid = EditorGUIUtility.TrTextContent(\"Equator Color\", \"Controls the color of light emitted from the sides of the Scene.\");\n            public static readonly GUIContent ambientDown = EditorGUIUtility.TrTextContent(\"Ground Color\", \"Controls the color of light emitted from the ground of the Scene.\");\n            public static readonly GUIContent ambient = EditorGUIUtility.TrTextContent(\"Ambient Color\", \"Controls the color of the ambient light contributed to the Scene.\");\n            public static readonly GUIContent customReflection = EditorGUIUtility.TrTextContent(\"Cubemap\", \"Specifies the custom cube map used for reflection effects in the Scene.\");\n            public static readonly GUIContent SubtractiveColor = EditorGUIUtility.TrTextContent(\"Realtime Shadow Color\", \"The color used for mixing realtime shadows with baked lightmaps in Subtractive lighting mode. The color defines the darkest point of the realtime shadow.\");\n\n            public static readonly GUIContent[] kFullAmbientSource =\n            {\n                EditorGUIUtility.TrTextContent(\"Skybox\"),\n                EditorGUIUtility.TrTextContent(\"Gradient\"),\n                EditorGUIUtility.TrTextContent(\"Color\"),\n            };\n\n            public static readonly int[] kFullAmbientSourceValues = { (int)AmbientMode.Skybox, (int)AmbientMode.Trilight, (int)AmbientMode.Flat };\n        }\n\n        protected SerializedProperty m_Sun;\n        protected SerializedProperty m_SubtractiveShadowColor;\n        protected SerializedProperty m_AmbientSource;\n        protected SerializedProperty m_AmbientSkyColor;\n        protected SerializedProperty m_AmbientEquatorColor;\n        protected SerializedProperty m_AmbientGroundColor;\n        protected SerializedProperty m_AmbientIntensity;\n\n        protected SerializedProperty m_ReflectionIntensity;\n        protected SerializedProperty m_ReflectionBounces;\n\n        protected SerializedProperty m_SkyboxMaterial;\n        protected SerializedProperty m_DefaultReflectionMode;\n        protected SerializedProperty m_DefaultReflectionResolution;\n        protected SerializedProperty m_CustomReflection;\n        protected SerializedProperty m_ReflectionCompression;\n\n        protected SerializedObject m_RenderSettings;\n        protected SerializedObject m_LightmapSettings;\n\n        SerializedObject renderSettings\n        {\n            get\n            {\n                // if we set a new scene as the active scene, we need to make sure to respond to those changes\n                if (m_RenderSettings == null || m_RenderSettings.targetObject == null || m_RenderSettings.targetObject != RenderSettings.GetRenderSettings())\n                {\n                    m_RenderSettings = new SerializedObject(RenderSettings.GetRenderSettings());\n\n                    m_Sun = m_RenderSettings.FindProperty(\"m_Sun\");\n                    m_SubtractiveShadowColor = m_RenderSettings.FindProperty(\"m_SubtractiveShadowColor\");\n                    m_AmbientSource = m_RenderSettings.FindProperty(\"m_AmbientMode\");\n                    m_AmbientSkyColor = m_RenderSettings.FindProperty(\"m_AmbientSkyColor\");\n                    m_AmbientEquatorColor = m_RenderSettings.FindProperty(\"m_AmbientEquatorColor\");\n                    m_AmbientGroundColor = m_RenderSettings.FindProperty(\"m_AmbientGroundColor\");\n                    m_AmbientIntensity = m_RenderSettings.FindProperty(\"m_AmbientIntensity\");\n                    m_ReflectionIntensity = m_RenderSettings.FindProperty(\"m_ReflectionIntensity\");\n                    m_ReflectionBounces = m_RenderSettings.FindProperty(\"m_ReflectionBounces\");\n                    m_SkyboxMaterial = m_RenderSettings.FindProperty(\"m_SkyboxMaterial\");\n                    m_DefaultReflectionMode = m_RenderSettings.FindProperty(\"m_DefaultReflectionMode\");\n                    m_DefaultReflectionResolution = m_RenderSettings.FindProperty(\"m_DefaultReflectionResolution\");\n                    m_CustomReflection = m_RenderSettings.FindProperty(\"m_CustomReflection\");\n                }\n\n                return m_RenderSettings;\n            }\n        }\n\n        SerializedObject lightmapSettings\n        {\n            get\n            {\n                // if we set a new scene as the active scene, we need to make sure to respond to those changes\n                if (m_LightmapSettings == null || m_LightmapSettings.targetObject == null || m_LightmapSettings.targetObject != LightmapEditorSettings.GetLightmapSettings())\n                {\n                    m_LightmapSettings = new SerializedObject(LightmapEditorSettings.GetLightmapSettings());\n                    m_ReflectionCompression = m_LightmapSettings.FindProperty(\"m_LightmapEditorSettings.m_ReflectionCompression\");\n                }\n\n                return m_LightmapSettings;\n            }\n        }\n\n        private bool m_bShowEnvironment;\n        private const string kShowEnvironment = \"ShowEnvironment\";\n\n        public virtual void OnEnable()\n        {\n            m_bShowEnvironment = SessionState.GetBool(kShowEnvironment, true);\n        }\n\n        public virtual void OnDisable()\n        {\n            SessionState.SetBool(kShowEnvironment, m_bShowEnvironment);\n        }\n\n        private void DrawGUI()\n        {\n            Material skyboxMaterial = m_SkyboxMaterial.objectReferenceValue as Material;\n\n            m_bShowEnvironment = EditorGUILayout.FoldoutTitlebar(m_bShowEnvironment, Styles.env_top, true);\n\n            if (m_bShowEnvironment)\n            {\n                EditorGUI.indentLevel++;\n\n                EditorGUILayout.PropertyField(m_SkyboxMaterial, Styles.env_skybox_mat);\n                if (skyboxMaterial && !EditorMaterialUtility.IsBackgroundMaterial(skyboxMaterial))\n                {\n                    EditorGUILayout.HelpBox(Styles.skyboxWarning.text, MessageType.Warning);\n                }\n\n                EditorGUILayout.PropertyField(m_Sun, Styles.env_skybox_sun);\n                EditorGUILayout.Space();\n\n                EditorGUILayout.PropertyField(m_SubtractiveShadowColor, Styles.SubtractiveColor);\n                EditorGUILayout.Space();\n\n                EditorGUILayout.LabelField(Styles.env_amb_top);\n                EditorGUI.indentLevel++;\n\n                EditorGUILayout.IntPopup(m_AmbientSource, Styles.kFullAmbientSource, Styles.kFullAmbientSourceValues, Styles.env_amb_src);\n                switch ((AmbientMode)m_AmbientSource.intValue)\n                {\n                    case AmbientMode.Trilight:\n                    {\n                        EditorGUI.BeginChangeCheck();\n                        Color newValueUp = EditorGUILayout.ColorField(Styles.ambientUp, m_AmbientSkyColor.colorValue, true, false, true);\n                        Color newValueMid = EditorGUILayout.ColorField(Styles.ambientMid, m_AmbientEquatorColor.colorValue, true, false, true);\n                        Color newValueDown = EditorGUILayout.ColorField(Styles.ambientDown, m_AmbientGroundColor.colorValue, true, false, true);\n                        if (EditorGUI.EndChangeCheck())\n                        {\n                            m_AmbientSkyColor.colorValue = newValueUp;\n                            m_AmbientEquatorColor.colorValue = newValueMid;\n                            m_AmbientGroundColor.colorValue = newValueDown;\n                        }\n                    }\n                    break;\n\n                    case AmbientMode.Flat:\n                    {\n                        EditorGUI.BeginChangeCheck();\n                        Color newValue = EditorGUILayout.ColorField(Styles.ambient, m_AmbientSkyColor.colorValue, true, false, true);\n                        if (EditorGUI.EndChangeCheck())\n                            m_AmbientSkyColor.colorValue = newValue;\n                    }\n                    break;\n\n                    case AmbientMode.Skybox:\n                        if (skyboxMaterial == null)\n                        {\n                            EditorGUI.BeginChangeCheck();\n                            Color newValue = EditorGUILayout.ColorField(Styles.ambient, m_AmbientSkyColor.colorValue, true, false, true);\n                            if (EditorGUI.EndChangeCheck())\n                                m_AmbientSkyColor.colorValue = newValue;\n                        }\n                        else\n                        {\n                            // Ambient intensity - maximum is kEmissiveRGBMMax\n                            EditorGUILayout.Slider(m_AmbientIntensity, 0.0F, 8.0F, Styles.env_amb_int);\n                        }\n                        break;\n                }\n\n                EditorGUI.indentLevel--;\n                EditorGUILayout.Space();\n\n                EditorGUILayout.LabelField(Styles.env_refl_top);\n                EditorGUI.indentLevel++;\n\n                EditorGUILayout.PropertyField(m_DefaultReflectionMode, Styles.env_refl_src);\n\n                DefaultReflectionMode defReflectionMode = (DefaultReflectionMode)m_DefaultReflectionMode.intValue;\n                switch (defReflectionMode)\n                {\n                    case DefaultReflectionMode.FromSkybox:\n                    {\n                        int[] reflectionResolutionValuesArray = null;\n                        GUIContent[] reflectionResolutionTextArray = null;\n                        ReflectionProbeEditor.GetResolutionArray(ref reflectionResolutionValuesArray, ref reflectionResolutionTextArray);\n                        EditorGUILayout.IntPopup(m_DefaultReflectionResolution, reflectionResolutionTextArray, reflectionResolutionValuesArray, Styles.env_refl_res, GUILayout.MinWidth(40));\n                    }\n                    break;\n                    case DefaultReflectionMode.Custom:\n                        EditorGUILayout.PropertyField(m_CustomReflection, Styles.customReflection);\n                        break;\n                }\n\n                EditorGUILayout.PropertyField(m_ReflectionCompression, Styles.env_refl_cmp);\n                EditorGUILayout.Slider(m_ReflectionIntensity, 0.0F, 1.0F, Styles.env_refl_int);\n                EditorGUILayout.IntSlider(m_ReflectionBounces, 1, 5, Styles.env_refl_bnc);\n\n                EditorGUI.indentLevel--;\n\n                EditorGUI.indentLevel--;\n                EditorGUILayout.Space();\n            }\n        }\n\n        public override void OnInspectorGUI()\n        {\n            renderSettings.Update();\n            lightmapSettings.Update();\n\n            DrawGUI();\n\n            renderSettings.ApplyModifiedProperties();\n            lightmapSettings.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SettingsWindow/OtherRenderingEditor.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\n\nnamespace UnityEditor\n{\n    [CustomEditor(typeof(RenderSettings))]\n    internal class OtherRenderingEditor : Editor\n    {\n        internal static class Styles\n        {\n            public static readonly GUIContent HaloStrength = EditorGUIUtility.TrTextContent(\"Halo Strength\", \"Controls the visibility of the halo effect around lights in the Scene.\");\n            public static readonly GUIContent HaloTexture = EditorGUIUtility.TrTextContent(\"Halo Texture\", \"Specifies the Texture used when drawing the halo effect around lights in the Scene\");\n            public static readonly GUIContent FlareStrength = EditorGUIUtility.TrTextContent(\"Flare Strength\", \"Controls the visibility of lens flares from lights in the Scene.\");\n            public static readonly GUIContent FlareFadeSpeed = EditorGUIUtility.TrTextContent(\"Flare Fade Speed\", \"Controls the time over which lens flares fade from view after initially appearing.\");\n            public static readonly GUIContent SpotCookie = EditorGUIUtility.TrTextContent(\"Spot Cookie\", \"Specifies the Texture mask used to cast shadows, create silhouettes, or patterned illumination when using spot lights.\");\n        }\n\n        protected SerializedProperty m_HaloStrength;\n        protected SerializedProperty m_FlareStrength;\n        protected SerializedProperty m_FlareFadeSpeed;\n        protected SerializedProperty m_HaloTexture;\n        protected SerializedProperty m_SpotCookie;\n\n        protected SerializedObject m_RenderSettings;\n\n        SerializedObject renderSettings\n        {\n            get\n            {\n                // if we set a new scene as the active scene, we need to make sure to respond to those changes\n                if (m_RenderSettings == null || m_RenderSettings.targetObject != RenderSettings.GetRenderSettings())\n                {\n                    m_RenderSettings = new SerializedObject(RenderSettings.GetRenderSettings());\n\n                    m_HaloStrength = m_RenderSettings.FindProperty(\"m_HaloStrength\");\n                    m_FlareStrength = m_RenderSettings.FindProperty(\"m_FlareStrength\");\n                    m_FlareFadeSpeed = m_RenderSettings.FindProperty(\"m_FlareFadeSpeed\");\n                    m_HaloTexture = m_RenderSettings.FindProperty(\"m_HaloTexture\");\n                    m_SpotCookie = m_RenderSettings.FindProperty(\"m_SpotCookie\");\n                }\n\n                return m_RenderSettings;\n            }\n        }\n\n        public virtual void OnDisable() {}\n\n        public override void OnInspectorGUI()\n        {\n            renderSettings.Update();\n\n            EditorGUILayout.PropertyField(m_HaloTexture, Styles.HaloTexture);\n            EditorGUILayout.Slider(m_HaloStrength, 0.0f, 1.0f, Styles.HaloStrength);\n\n            EditorGUILayout.PropertyField(m_FlareFadeSpeed, Styles.FlareFadeSpeed);\n            EditorGUILayout.Slider(m_FlareStrength, 0.0f, 1.0f, Styles.FlareStrength);\n\n            EditorGUILayout.PropertyField(m_SpotCookie, Styles.SpotCookie);\n\n            renderSettings.ApplyModifiedProperties();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ShaderUtil.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.InteropServices;\nusing UnityEditor.Build.Content;\nusing UnityEditor.Rendering;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Rendering;\nusing UnityEngine.Scripting;\nusing ShaderPlatform = UnityEngine.Rendering.GraphicsDeviceType;\nusing UnityEditor.AssetImporters;\nusing System.Runtime.CompilerServices;\n\n[assembly: InternalsVisibleTo(\"UnityEditor.ShaderUtil.Tests\")]\n[assembly: InternalsVisibleTo(\"UniversalEditorTests\")]\n\nnamespace UnityEditor\n{\n    public enum PreprocessorOverride\n    {\n        UseProjectSettings = 0,\n        ForcePlatformPreprocessor = 1,\n        ForceCachingPreprocessor = 2\n    }\n\n    [Serializable]\n    [RequiredByNativeCode]\n    [NativeHeader(\"Editor/Src/ShaderMenu.h\")]\n    public struct ShaderInfo\n    {\n        [SerializeField][NativeName(\"name\")]       internal string m_Name;\n        [SerializeField][NativeName(\"supported\")]  internal bool m_Supported;\n        [SerializeField][NativeName(\"hasErrors\")]  internal bool m_HasErrors;\n        [SerializeField][NativeName(\"hasWarnings\")] internal bool m_HasWarnings;\n\n        public string   name      { get { return m_Name; } }\n        public bool     supported { get { return m_Supported; } }\n        public bool     hasErrors { get { return m_HasErrors; } }\n        public bool hasWarnings { get { return m_HasWarnings; } }\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    public struct ShaderMessage : IEquatable<ShaderMessage>\n    {\n        public ShaderMessage(string msg, ShaderCompilerMessageSeverity sev = ShaderCompilerMessageSeverity.Error)\n        {\n            message = msg;\n            messageDetails = string.Empty;\n            file = string.Empty;\n            line = 0;\n            platform = ShaderCompilerPlatform.None;\n            severity = sev;\n        }\n\n        public string message { get; }\n        public string messageDetails { get; }\n        public string file { get; }\n        public int line { get; }\n        public ShaderCompilerPlatform platform { get; }\n        public ShaderCompilerMessageSeverity severity { get; }\n\n        public bool Equals(ShaderMessage other)\n        {\n            return string.Equals(message, other.message)\n                && string.Equals(messageDetails, other.messageDetails)\n                && string.Equals(file, other.file)\n                && line == other.line\n                && platform == other.platform\n                && severity == other.severity;\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj)) return false;\n            return obj is ShaderMessage && Equals((ShaderMessage)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                var hashCode = (message != null ? message.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ (messageDetails != null ? messageDetails.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ (file != null ? file.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ line;\n                hashCode = (hashCode * 397) ^ (int)platform;\n                hashCode = (hashCode * 397) ^ (int)severity;\n                return hashCode;\n            }\n        }\n\n        public static bool operator==(ShaderMessage left, ShaderMessage right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator!=(ShaderMessage left, ShaderMessage right)\n        {\n            return !left.Equals(right);\n        }\n    }\n\n    internal struct ShaderVariantEntriesData\n    {\n        public int[] passTypes;\n        public string[] keywordLists;\n        public string[] remainingKeywords;\n    }\n\n    [NativeHeader(\"Editor/Mono/ShaderUtil.bindings.h\")]\n    [NativeHeader(\"Editor/Src/ShaderData.h\")]\n    [NativeHeader(\"Editor/Src/ShaderMenu.h\")]\n    [NativeHeader(\"Runtime/Shaders/GpuPrograms/GpuProgramManager.h\")]\n    public sealed partial class ShaderUtil\n    {\n        extern internal static int GetAvailableShaderCompilerPlatforms();\n\n        extern internal static bool HasSurfaceShaders([NotNull] Shader s);\n        extern internal static bool HasFixedFunctionShaders([NotNull] Shader s);\n        extern internal static bool HasShaderSnippets([NotNull] Shader s);\n        extern internal static bool HasInstancing([NotNull] Shader s);\n        extern public static bool HasProceduralInstancing([NotNull] Shader s);\n        extern internal static bool HasShadowCasterPass([NotNull] Shader s);\n        extern internal static bool DoesIgnoreProjector([NotNull] Shader s);\n        extern internal static int  GetRenderQueue([NotNull] Shader s);\n        extern internal static bool HasTangentChannel([NotNull] Shader s);\n\n        extern internal static void FetchCachedMessages([NotNull] Shader s);\n        extern public static int GetShaderMessageCount([NotNull] Shader s);\n        public static ShaderMessage[] GetShaderMessages(Shader s)\n        {\n            return GetShaderMessages(s, (ShaderCompilerPlatform)0);\n        }\n\n        extern public static ShaderMessage[] GetShaderMessages([NotNull] Shader s, ShaderCompilerPlatform platform);\n        extern public static void ClearShaderMessages([NotNull] Shader s);\n        extern public static int GetComputeShaderMessageCount([NotNull] ComputeShader s);\n        extern public static ShaderMessage[] GetComputeShaderMessages([NotNull] ComputeShader s);\n\n        extern public static int GetRayTracingShaderMessageCount([NotNull] RayTracingShader s);\n        extern public static ShaderMessage[] GetRayTracingShaderMessages([NotNull] RayTracingShader s);\n        extern public static int GetRayGenerationShaderCount([NotNull] RayTracingShader s);\n        extern public static string GetRayGenerationShaderName([NotNull] RayTracingShader s, int shaderIndex);\n        extern public static int GetMissShaderCount([NotNull] RayTracingShader s);\n        extern public static string GetMissShaderName([NotNull] RayTracingShader s, int shaderIndex);\n        extern public static int GetMissShaderRayPayloadSize([NotNull] RayTracingShader s, int shaderIndex);\n        extern public static int GetCallableShaderCount([NotNull] RayTracingShader s);\n        extern public static string GetCallableShaderName([NotNull] RayTracingShader s, int shaderIndex);\n        extern public static int GetCallableShaderParamSize([NotNull] RayTracingShader s, int shaderIndex);\n\n        extern static public void ClearCachedData([NotNull] Shader s);\n\n        extern internal static int GetTextureBindingIndex(Shader s, int texturePropertyID);\n        extern internal static int GetTextureSamplerBindingIndex(Shader s, int texturePropertyID);\n        extern internal static int GetLOD(Shader s);\n        extern internal static int GetSRPBatcherCompatibilityCode(Shader s, int subShaderIdx);\n        extern internal static string GetSRPBatcherCompatibilityIssueReason(Shader s, int subShaderIdx, int err);\n\n        extern internal static ulong            GetVariantCount(Shader s, bool usedBySceneOnly);\n        extern internal static int              GetComputeShaderPlatformCount(ComputeShader s);\n        extern internal static ShaderPlatform   GetComputeShaderPlatformType(ComputeShader s, int platformIndex);\n        extern internal static int              GetComputeShaderPlatformKernelCount(ComputeShader s, int platformIndex);\n        extern internal static string           GetComputeShaderPlatformKernelName(ComputeShader s, int platformIndex, int kernelIndex);\n\n        extern internal static int              GetRayTracingShaderPlatformCount(RayTracingShader s);\n        extern internal static ShaderPlatform   GetRayTracingShaderPlatformType(RayTracingShader s, int platformIndex);\n        extern internal static bool             IsRayTracingShaderValidForPlatform(RayTracingShader s, ShaderPlatform renderer);\n\n        extern internal static void CalculateLightmapStrippingFromCurrentScene();\n        extern internal static void CalculateLightmapStrippingFromCurrentSceneForBuildProfile(\n            out bool lightmapKeepPlain, out bool lightmapKeepDirCombined, out bool lightmapKeepDynamicPlain,\n            out bool lightmapKeepDynamicDirCombined, out bool lightmapKeepShadowMask, out bool lightmapKeepSubtractive);\n        extern internal static void CalculateFogStrippingFromCurrentScene();\n        extern internal static void CalculateFogStrippingFromCurrentSceneForBuildProfile(out bool fogKeepLinear, out bool fogKeepExp, out bool fogKeepExp2);\n\n        extern internal static Rect rawViewportRect { get; set; }\n        extern internal static Rect rawScissorRect  { get; set; }\n        extern public   static bool hardwareSupportsRectRenderTexture { get; }\n        extern internal static bool hardwareSupportsFullNPOT { get; }\n        public static extern bool disableShaderOptimization { get; set; }\n\n        extern internal static void RequestLoadRenderDoc();\n        extern internal static void RecreateGfxDevice();\n        extern internal static void RecreateSkinnedMeshResources();\n        extern internal static void ReloadAllShaders();\n\n        extern public static Shader CreateShaderAsset(AssetImportContext context, string source, bool compileInitialShaderVariants);\n        public static Shader CreateShaderAsset(string source)\n        {\n            return CreateShaderAsset(null, source, true);\n        }\n\n        public static Shader CreateShaderAsset(string source, bool compileInitialShaderVariants)\n        {\n            return CreateShaderAsset(null, source, compileInitialShaderVariants);\n        }\n\n        extern public static void   UpdateShaderAsset(AssetImportContext context, [NotNull] Shader shader, [NotNull] string source, bool compileInitialShaderVariants);\n        public static void          UpdateShaderAsset(Shader shader, string source)\n        {\n            UpdateShaderAsset(null, shader, source, true);\n        }\n\n        public static void UpdateShaderAsset(Shader shader, string source, bool compileInitialShaderVariants)\n        {\n            UpdateShaderAsset(null, shader, source, compileInitialShaderVariants);\n        }\n\n        extern public static ComputeShader CreateComputeShaderAsset(AssetImportContext context, string source);\n        extern public static RayTracingShader CreateRayTracingShaderAsset(AssetImportContext context, string source);\n\n        [FreeFunction(\"GetShaderNameRegistry().AddShader\")] extern public static void RegisterShader([NotNull] Shader shader);\n\n\n        extern internal static void OpenCompiledShader(Shader shader, int mode, int externPlatformsMask, bool includeAllVariants, bool preprocessOnly, bool stripLineDirectives);\n\n        extern internal static void OpenCompiledComputeShader(ComputeShader shader, bool allVariantsAndPlatforms, bool showPreprocessed, bool stripLineDirectives);\n        extern internal static void OpenParsedSurfaceShader(Shader shader);\n        extern internal static void OpenGeneratedFixedFunctionShader(Shader shader);\n        extern internal static void OpenShaderCombinations(Shader shader, bool usedBySceneOnly);\n        extern internal static void OpenSystemShaderIncludeError(string includeName, int line);\n\n\n        extern internal static void SaveCurrentShaderVariantCollection(string path);\n        extern internal static void ClearCurrentShaderVariantCollection();\n        extern internal static int  GetCurrentShaderVariantCollectionShaderCount();\n        extern internal static int  GetCurrentShaderVariantCollectionVariantCount();\n        extern internal static bool AddNewShaderToCollection(Shader shader, ShaderVariantCollection collection);\n\n        private static extern ShaderVariantEntriesData GetShaderVariantEntriesFilteredInternal([NotNull] Shader shader, int maxEntries, string[] filterKeywords, ShaderVariantCollection excludeCollection);\n\n        internal static void GetShaderVariantEntriesFiltered(Shader shader, int maxEntries, string[] filterKeywords, ShaderVariantCollection excludeCollection, out int[] passTypes, out string[] keywordLists, out string[] remainingKeywords)\n        {\n            ShaderVariantEntriesData data = GetShaderVariantEntriesFilteredInternal(shader, maxEntries, filterKeywords, excludeCollection);\n            passTypes = data.passTypes;\n            keywordLists = data.keywordLists;\n            remainingKeywords = data.remainingKeywords;\n        }\n\n        extern internal static string[] GetAllGlobalKeywords();\n        extern internal static string[] GetShaderGlobalKeywords([NotNull] Shader shader);\n        extern internal static string[] GetShaderLocalKeywords([NotNull] Shader shader);\n\n        [FreeFunction] public static extern ShaderInfo[] GetAllShaderInfo();\n        [FreeFunction] public static extern ShaderInfo GetShaderInfo([NotNull] Shader shader);\n\n        [FreeFunction] extern internal static string GetShaderPassSourceCode([NotNull] Shader shader, int subShaderIndex, int passId);\n        [FreeFunction] extern internal static string GetShaderPassName([NotNull] Shader shader, int subShaderIndex, int passId);\n        [FreeFunction] extern internal static int GetShaderActiveSubshaderIndex([NotNull] Shader shader);\n        [FreeFunction] extern internal static int GetShaderSubshaderCount([NotNull] Shader shader);\n        [FreeFunction] extern internal static int GetShaderTotalPassCount([NotNull] Shader shader, int subShaderIndex);\n        [FreeFunction] extern internal static int GetSubshaderLOD([NotNull] Shader shader, int subShaderIndex);\n        [FreeFunction] extern internal static bool IsGrabPass([NotNull] Shader shader, int subShaderIndex, int passId);\n        [FreeFunction(\"ShaderUtil::GetShaderSerializedSubshaderCount\")] extern internal static int GetShaderSerializedSubshaderCount([NotNull] Shader shader);\n        [FreeFunction(\"ShaderUtil::FindSerializedSubShaderTagValue\")] extern internal static int FindSerializedSubShaderTagValue([NotNull] Shader shader, int subShaderIndex, int tagName);\n        [FreeFunction(\"ShaderUtil::FindPassTagValue\")] extern internal static int FindPassTagValue([NotNull] Shader shader, int subShaderIndex, int passIndex, int tagName);\n\n        extern public static bool anythingCompiling { get; }\n        extern public static bool allowAsyncCompilation { get; set; }\n        extern public static void SetAsyncCompilation([NotNull] CommandBuffer cmd, bool allow);\n        extern public static void RestoreAsyncCompilation([NotNull] CommandBuffer cmd);\n        extern public static bool IsPassCompiled([NotNull] Material material, int pass);\n        extern public static void CompilePass([NotNull] Material material, int pass, bool forceSync = false);\n\n        internal static MaterialProperty[] GetMaterialProperties(UnityEngine.Object[] mats)\n        {\n            return (MaterialProperty[])GetMaterialPropertiesImpl(mats);\n        }\n\n        extern private static System.Object GetMaterialPropertiesImpl(System.Object mats);\n\n        internal static string[] GetMaterialPropertyNames(UnityEngine.Object[] mats)\n        {\n            return GetMaterialPropertyNamesImpl(mats);\n        }\n\n        extern private static string[] GetMaterialPropertyNamesImpl(System.Object mats);\n\n        internal static MaterialProperty GetMaterialProperty(UnityEngine.Object[] mats, string name)\n        {\n            return (MaterialProperty)GetMaterialPropertyImpl(mats, name);\n        }\n\n        extern private static System.Object GetMaterialPropertyImpl(System.Object mats, string name);\n\n        internal static MaterialProperty GetMaterialProperty(UnityEngine.Object[] mats, int propertyIndex)\n        {\n            return (MaterialProperty)GetMaterialPropertyByIndex(mats, propertyIndex);\n        }\n\n        extern private static System.Object GetMaterialPropertyByIndex(System.Object mats, int propertyIndex);\n\n        internal static void ApplyProperty(MaterialProperty prop, int propertyMask, string undoName)\n        {\n            ApplyPropertyImpl(prop, propertyMask, undoName);\n        }\n\n        [NativeThrows]\n        extern private static void ApplyPropertyImpl(System.Object prop, int propertyMask, string undoName);\n\n        internal static void ApplyMaterialPropertyBlockToMaterialProperty(MaterialPropertyBlock propertyBlock, MaterialProperty materialProperty)\n        {\n            ApplyMaterialPropertyBlockToMaterialPropertyImpl(propertyBlock, materialProperty);\n        }\n\n        extern private static void ApplyMaterialPropertyBlockToMaterialPropertyImpl(System.Object propertyBlock, System.Object materialProperty);\n\n        internal static void ApplyMaterialPropertyToMaterialPropertyBlock(MaterialProperty materialProperty, int propertyMask, MaterialPropertyBlock propertyBlock)\n        {\n            ApplyMaterialPropertyToMaterialPropertyBlockImpl(materialProperty, propertyMask, propertyBlock);\n        }\n\n        extern private static void ApplyMaterialPropertyToMaterialPropertyBlockImpl(System.Object materialProperty, int propertyMask, System.Object propertyBlock);\n\n        public static string GetCustomEditorForRenderPipeline(Shader shader, string renderPipelineType)\n        {\n            if (shader == null)\n                return null;\n\n            shader.Internal_GetCustomEditorForRenderPipeline(renderPipelineType, out var rpEditor);\n            return String.IsNullOrEmpty(rpEditor) ? null : rpEditor;\n        }\n\n        public static string GetCustomEditorForRenderPipeline(Shader shader, Type renderPipelineType) => GetCustomEditorForRenderPipeline(shader, renderPipelineType?.FullName);\n        public static string GetCurrentCustomEditor(Shader shader)\n        {\n            if (shader == null)\n                return null;\n\n            var rpEditor = GetCustomEditorForRenderPipeline(shader, GraphicsSettings.currentRenderPipeline?.GetType());\n            return String.IsNullOrEmpty(rpEditor) ? shader.customEditor : rpEditor;\n        }\n\n        extern public static BuiltinShaderDefine[] GetShaderPlatformKeywordsForBuildTarget(ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget, GraphicsTier tier);\n\n        public static BuiltinShaderDefine[] GetShaderPlatformKeywordsForBuildTarget(ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget)\n        {\n            return GetShaderPlatformKeywordsForBuildTarget(shaderCompilerPlatform, buildTarget, GraphicsTier.Tier1);\n        }\n\n        extern internal static ShaderData.VariantCompileInfo CompileShaderVariant([NotNull] Shader shader, int subShaderIndex, int passId,\n            ShaderType shaderType, BuiltinShaderDefine[] platformKeywords, string[] keywords, ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget, GraphicsTier tier, bool outputForExternalTool);\n        extern internal static ShaderData.PreprocessedVariant PreprocessShaderVariant([NotNull] Shader shader, int subShaderIndex, int passId,\n            ShaderType shaderType, BuiltinShaderDefine[] platformKeywords, string[] keywords, ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget, GraphicsTier tier, bool stripLineDirectives);\n\n        [FreeFunction(\"ShaderUtil::GetPassKeywords\")] extern private static LocalKeyword[] GetPassAllStageKeywords(Shader s, in PassIdentifier passIdentifier);\n        [FreeFunction(\"ShaderUtil::GetPassKeywords\")] extern private static LocalKeyword[] GetPassStageKeywords(Shader s, in PassIdentifier passIdentifier, ShaderType shaderType);\n        [FreeFunction(\"ShaderUtil::GetPassKeywords\")] extern private static LocalKeyword[] GetPassStageKeywordsForAPI(Shader s, in PassIdentifier passIdentifier, ShaderType shaderType, ShaderCompilerPlatform shaderCompilerPlatform);\n        [FreeFunction(\"ShaderUtil::PassHasKeyword\")] extern private static bool PassAnyStageHasKeyword(Shader s, in PassIdentifier passIdentifier, uint keywordIndex);\n        [FreeFunction(\"ShaderUtil::PassHasKeyword\")] extern private static bool PassStageHasKeyword(Shader s, in PassIdentifier passIdentifier, uint keywordIndex, ShaderType shaderType);\n        [FreeFunction(\"ShaderUtil::PassHasKeyword\")] extern private static bool PassStageHasKeywordForAPI(Shader s, in PassIdentifier passIdentifier, uint keywordIndex, ShaderType shaderType, ShaderCompilerPlatform shaderCompilerPlatform);\n\n        public static LocalKeyword[] GetPassKeywords(Shader s, in PassIdentifier passIdentifier)\n        {\n            return GetPassAllStageKeywords(s, passIdentifier);\n        }\n\n        public static LocalKeyword[] GetPassKeywords(Shader s, in PassIdentifier passIdentifier, ShaderType shaderType)\n        {\n            return GetPassStageKeywords(s, passIdentifier, shaderType);\n        }\n\n        public static LocalKeyword[] GetPassKeywords(Shader s, in PassIdentifier passIdentifier, ShaderType shaderType, ShaderCompilerPlatform shaderCompilerPlatform)\n        {\n            return GetPassStageKeywordsForAPI(s, passIdentifier, shaderType, shaderCompilerPlatform);\n        }\n\n        public static bool PassHasKeyword(Shader s, in PassIdentifier passIdentifier, in LocalKeyword keyword)\n        {\n            return PassAnyStageHasKeyword(s, passIdentifier, keyword.m_Index);\n        }\n\n        public static bool PassHasKeyword(Shader s, in PassIdentifier passIdentifier, in LocalKeyword keyword, ShaderType shaderType)\n        {\n            return PassStageHasKeyword(s, passIdentifier, keyword.m_Index, shaderType);\n        }\n\n        public static bool PassHasKeyword(Shader s, in PassIdentifier passIdentifier, in LocalKeyword keyword, ShaderType shaderType, ShaderCompilerPlatform shaderCompilerPlatform)\n        {\n            return PassStageHasKeywordForAPI(s, passIdentifier, keyword.m_Index, shaderType, shaderCompilerPlatform);\n        }\n\n        extern internal static Shader[] GetShaderDependencies([NotNull] Shader shader);\n\n        [FreeFunction(\"ShaderUtil::GetCompiledData\")] extern internal static byte[] GetCompiledData(\n            Shader s, BuildUsageTagSet buildUsageTags, BuildUsageTagGlobal globalUsageTag,\n            BuildTargetSelection buildTarget, bool shouldIncludeAllVariants);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ShaderUtil.bindings.deprecated.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing ShaderPropertyFlags = UnityEngine.Rendering.ShaderPropertyFlags;\nusing TextureDimension = UnityEngine.Rendering.TextureDimension;\n\nnamespace UnityEditor\n{\n    [NativeHeader(\"Editor/Mono/ShaderUtil.bindings.h\")]\n    public partial class ShaderUtil\n    {\n        [Obsolete(\"ClearShaderErrors has been deprecated. Use ClearShaderMessages instead (UnityUpgradable) -> ClearShaderMessages(*)\", true)]\n        public static void ClearShaderErrors(Shader s) {}\n\n        [Obsolete(\"Use UnityEngine.Rendering.TextureDimension instead. (UnityUpgradable) -> UnityEngine.Rendering.TextureDimension\", true)]\n        public enum ShaderPropertyTexDim\n        {\n            [Obsolete(\"Use UnityEngine.Rendering.TextureDimension.None instead. (UnityUpgradable) -> UnityEngine.Rendering.TextureDimension.None\", true)]\n            TexDimNone = 0, // no texture\n            [Obsolete(\"Use UnityEngine.Rendering.TextureDimension.Tex2D instead. (UnityUpgradable) -> UnityEngine.Rendering.TextureDimension.Tex2D\", true)]\n            TexDim2D = 2,\n            [Obsolete(\"Use UnityEngine.Rendering.TextureDimension.Tex3D instead. (UnityUpgradable) -> UnityEngine.Rendering.TextureDimension.Tex3D\", true)]\n            TexDim3D = 3,\n            [Obsolete(\"Use UnityEngine.Rendering.TextureDimension.Cube instead. (UnityUpgradable) -> UnityEngine.Rendering.TextureDimension.Cube\", true)]\n            TexDimCUBE = 4,\n            [Obsolete(\"Use UnityEngine.Rendering.TextureDimension.Any instead. (UnityUpgradable) -> UnityEngine.Rendering.TextureDimension.Any\", true)]\n            TexDimAny = 6,\n        }\n\n        [Obsolete(\"Use UnityEngine.Rendering.ShaderPropertyType instead. (UnityUpgradable) -> UnityEngine.Rendering.ShaderPropertyType\", false)]\n        public enum ShaderPropertyType\n        {\n            Color,\n            Vector,\n            Float,\n            Range,\n            [Obsolete(\"Use UnityEngine.Rendering.ShaderPropertyType.Texture instead. (UnityUpgradable) -> UnityEngine.Rendering.ShaderPropertyType.Texture\", false)]\n            TexEnv,\n            Int,\n        }\n\n        [Obsolete(\"Use Shader.GetPropertyCount instead.\", false)]\n        public static int GetPropertyCount(Shader s)\n        {\n            if (s == null)\n                throw new ArgumentNullException(\"s\");\n            return s.GetPropertyCount();\n        }\n\n        [Obsolete(\"Use Shader.GetPropertyName instead.\", false)]\n        public static string GetPropertyName(Shader s, int propertyIdx)\n        {\n            if (s == null)\n                throw new ArgumentNullException(\"s\");\n            return s.GetPropertyName(propertyIdx);\n        }\n\n        [Obsolete(\"Use Shader.GetPropertyType instead.\", false)]\n        public static ShaderPropertyType GetPropertyType(Shader s, int propertyIdx)\n        {\n            if (s == null)\n                throw new ArgumentNullException(\"s\");\n            return (ShaderPropertyType)s.GetPropertyType(propertyIdx);\n        }\n\n        [Obsolete(\"Use Shader.GetPropertyDescription instead.\", false)]\n        public static string GetPropertyDescription(Shader s, int propertyIdx)\n        {\n            if (s == null)\n                throw new ArgumentNullException(\"s\");\n            return s.GetPropertyDescription(propertyIdx);\n        }\n\n        [Obsolete(\"Use Shader.GetPropertyRangeLimits and Shader.GetDefaultValue instead.\", false)]\n        public static float GetRangeLimits(Shader s, int propertyIdx, int defminmax)\n        {\n            if (s == null)\n                throw new ArgumentNullException(\"s\");\n            else if (defminmax < 0 || defminmax > 2)\n                throw new ArgumentException(\"defminmax should be one of 0,1,2.\");\n            return defminmax > 0\n                ? s.GetPropertyRangeLimits(propertyIdx)[defminmax - 1]\n                : s.GetPropertyDefaultFloatValue(propertyIdx);\n        }\n\n        [Obsolete(\"Use Shader.GetPropertyTextureDimension instead.\", false)]\n        public static TextureDimension GetTexDim(Shader s, int propertyIdx)\n        {\n            if (s == null)\n                throw new ArgumentNullException(\"s\");\n            return s.GetPropertyTextureDimension(propertyIdx);\n        }\n\n        [Obsolete(\"Use Shader.GetPropertyFlags and test against ShaderPropertyFlags.HideInInspector instead.\", false)]\n        public static bool IsShaderPropertyHidden(Shader s, int propertyIdx)\n        {\n            if (s == null)\n                throw new ArgumentNullException(\"s\");\n            return (s.GetPropertyFlags(propertyIdx) & ShaderPropertyFlags.HideInInspector) != 0;\n        }\n\n        [Obsolete(\"Use Shader.GetPropertyFlags and test against ShaderPropertyFlags.NonModifiableTextureData instead.\", false)]\n        public static bool IsShaderPropertyNonModifiableTexureProperty(Shader s, int propertyIdx)\n        {\n            if (s == null)\n                throw new ArgumentNullException(\"s\");\n            return (s.GetPropertyFlags(propertyIdx) & ShaderPropertyFlags.NonModifiableTextureData) != 0;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/ShaderUtil.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing UnityEditor.Rendering;\nusing UnityEngine;\nusing UnityEngine.Assertions;\nusing UnityEngine.Rendering;\nusing DebuggerDisplayAttribute = System.Diagnostics.DebuggerDisplayAttribute;\n\nnamespace UnityEditor\n{\n    public class ShaderData\n    {\n        public class Subshader\n        {\n            internal enum Type\n            {\n                Runtime,\n                Serialized\n            }\n\n            internal ShaderData m_Data;\n            internal int m_SubshaderIndex;\n            private Func<Shader, int, ShaderTagId, ShaderTagId> m_FindTagValue;\n\n            internal Subshader(ShaderData data, int subshaderIndex, Type type = Type.Runtime)\n            {\n                m_Data = data;\n                m_SubshaderIndex = subshaderIndex;\n\n                m_FindTagValue = type == Type.Serialized ? s_SerializedFindTagValue : s_RuntimeFindTagValue;\n            }\n\n            internal Shader SourceShader => m_Data.SourceShader;\n\n            public int PassCount => ShaderUtil.GetShaderTotalPassCount(m_Data.SourceShader, m_SubshaderIndex);\n\n            public int LevelOfDetail => ShaderUtil.GetSubshaderLOD(m_Data.SourceShader, m_SubshaderIndex);\n\n            private static Func<Shader, int, ShaderTagId, ShaderTagId> s_SerializedFindTagValue = (Shader sourceShader, int subshaderIndex, ShaderTagId tag) =>\n                new ShaderTagId { id = ShaderUtil.FindSerializedSubShaderTagValue(sourceShader, subshaderIndex, tag.id) };\n\n            private static Func<Shader, int, ShaderTagId, ShaderTagId> s_RuntimeFindTagValue = (Shader sourceShader, int subshaderIndex, ShaderTagId tag) =>\n            {\n                if (subshaderIndex < 0 || subshaderIndex >= sourceShader.subshaderCount)\n                {\n                    Debug.LogErrorFormat(\"Subshader index is incorrect: {0}, shader {1} has {2} subshaders.\", subshaderIndex, sourceShader, sourceShader.subshaderCount);\n                    return ShaderTagId.none;\n                }\n\n                return sourceShader.FindSubshaderTagValue(subshaderIndex, tag);\n            };\n\n            public ShaderTagId FindTagValue(ShaderTagId tag) => m_FindTagValue(SourceShader, m_SubshaderIndex, tag);\n\n            public Pass GetPass(int passIndex)\n            {\n                if (passIndex < 0 || passIndex >= PassCount)\n                {\n                    Debug.LogErrorFormat(\"Pass index is incorrect: {0}, shader {1} has {2} passes.\", passIndex, SourceShader, PassCount);\n                    return null;\n                }\n\n                return new Pass(this, passIndex);\n            }\n        }\n\n        public class Pass\n        {\n            Subshader m_Subshader;\n            int m_PassIndex;\n\n            internal Pass(Subshader subshader, int passIndex)\n            {\n                m_Subshader = subshader;\n                m_PassIndex = passIndex;\n            }\n\n            internal Shader SourceShader { get { return m_Subshader.m_Data.SourceShader; } }\n            internal int SubshaderIndex { get { return m_Subshader.m_SubshaderIndex; } }\n\n            public string SourceCode { get { return ShaderUtil.GetShaderPassSourceCode(SourceShader, SubshaderIndex, m_PassIndex); } }\n            public string Name { get { return ShaderUtil.GetShaderPassName(SourceShader, SubshaderIndex, m_PassIndex); } }\n            public bool IsGrabPass { get { return ShaderUtil.IsGrabPass(SourceShader, SubshaderIndex, m_PassIndex); } }\n\n            public UnityEngine.Rendering.ShaderTagId FindTagValue(UnityEngine.Rendering.ShaderTagId tagName)\n            {\n                int id = ShaderUtil.FindPassTagValue(SourceShader, m_Subshader.m_SubshaderIndex, m_PassIndex, tagName.id);\n                return new UnityEngine.Rendering.ShaderTagId { id = id };\n            }\n\n            public bool HasShaderStage(ShaderType shaderType)\n            {\n                return ShaderUtil.PassHasShaderStage(SourceShader, SubshaderIndex, m_PassIndex, shaderType);\n            }\n\n            internal static GraphicsTier kNoGraphicsTier = (GraphicsTier)(-1);\n\n            public VariantCompileInfo CompileVariant(ShaderType shaderType, string[] keywords,\n                ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget)\n            {\n                return CompileVariant(shaderType, keywords, shaderCompilerPlatform, buildTarget, false);\n            }\n\n            public VariantCompileInfo CompileVariant(ShaderType shaderType, string[] keywords,\n                ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget, bool forExternalTool)\n            {\n                var platformKeywords = ShaderUtil.GetShaderPlatformKeywordsForBuildTarget(shaderCompilerPlatform, buildTarget, kNoGraphicsTier);\n                return ShaderUtil.CompileShaderVariant(SourceShader, SubshaderIndex, m_PassIndex, shaderType, platformKeywords, keywords, shaderCompilerPlatform, buildTarget, kNoGraphicsTier, forExternalTool);\n            }\n\n            public VariantCompileInfo CompileVariant(ShaderType shaderType, string[] keywords,\n                ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget, GraphicsTier tier)\n            {\n                return CompileVariant(shaderType, keywords, shaderCompilerPlatform, buildTarget, tier, false);\n            }\n\n            public VariantCompileInfo CompileVariant(ShaderType shaderType, string[] keywords,\n                ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget, GraphicsTier tier, bool forExternalTool)\n            {\n                var platformKeywords = ShaderUtil.GetShaderPlatformKeywordsForBuildTarget(shaderCompilerPlatform, buildTarget, tier);\n                return ShaderUtil.CompileShaderVariant(SourceShader, SubshaderIndex, m_PassIndex, shaderType, platformKeywords, keywords, shaderCompilerPlatform, buildTarget, tier, forExternalTool);\n            }\n\n            public VariantCompileInfo CompileVariant(ShaderType shaderType, string[] keywords,\n                ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget, BuiltinShaderDefine[] platformKeywords)\n            {\n                return CompileVariant(shaderType, keywords, shaderCompilerPlatform, buildTarget, platformKeywords, false);\n            }\n\n            public VariantCompileInfo CompileVariant(ShaderType shaderType, string[] keywords,\n                ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget, BuiltinShaderDefine[] platformKeywords, bool forExternalTool)\n            {\n                return ShaderUtil.CompileShaderVariant(SourceShader, SubshaderIndex, m_PassIndex, shaderType, platformKeywords, keywords, shaderCompilerPlatform, buildTarget, kNoGraphicsTier, forExternalTool);\n            }\n\n            public VariantCompileInfo CompileVariant(ShaderType shaderType, string[] keywords,\n                ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget, BuiltinShaderDefine[] platformKeywords, GraphicsTier tier)\n            {\n                return CompileVariant(shaderType, keywords, shaderCompilerPlatform, buildTarget, platformKeywords, tier, false);\n            }\n\n            public VariantCompileInfo CompileVariant(ShaderType shaderType, string[] keywords,\n                ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget, BuiltinShaderDefine[] platformKeywords, GraphicsTier tier, bool forExternalTool)\n            {\n                return ShaderUtil.CompileShaderVariant(SourceShader, SubshaderIndex, m_PassIndex, shaderType, platformKeywords, keywords, shaderCompilerPlatform, buildTarget, tier, forExternalTool);\n            }\n\n            public PreprocessedVariant PreprocessVariant(ShaderType shaderType, string[] keywords,\n                ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget, bool stripLineDirectives)\n            {\n                var platformKeywords = ShaderUtil.GetShaderPlatformKeywordsForBuildTarget(shaderCompilerPlatform, buildTarget, kNoGraphicsTier);\n                return ShaderUtil.PreprocessShaderVariant(SourceShader, SubshaderIndex, m_PassIndex, shaderType, platformKeywords, keywords, shaderCompilerPlatform, buildTarget, kNoGraphicsTier, stripLineDirectives);\n            }\n\n            public PreprocessedVariant PreprocessVariant(ShaderType shaderType, string[] keywords,\n                ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget, GraphicsTier tier, bool stripLineDirectives)\n            {\n                var platformKeywords = ShaderUtil.GetShaderPlatformKeywordsForBuildTarget(shaderCompilerPlatform, buildTarget, tier);\n                return ShaderUtil.PreprocessShaderVariant(SourceShader, SubshaderIndex, m_PassIndex, shaderType, platformKeywords, keywords, shaderCompilerPlatform, buildTarget, tier, stripLineDirectives);\n            }\n\n            public PreprocessedVariant PreprocessVariant(ShaderType shaderType, string[] keywords,\n                ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget, BuiltinShaderDefine[] platformKeywords, bool stripLineDirectives)\n            {\n                return ShaderUtil.PreprocessShaderVariant(SourceShader, SubshaderIndex, m_PassIndex, shaderType, platformKeywords, keywords, shaderCompilerPlatform, buildTarget, kNoGraphicsTier, stripLineDirectives);\n            }\n\n            public PreprocessedVariant PreprocessVariant(ShaderType shaderType, string[] keywords,\n                ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget, BuiltinShaderDefine[] platformKeywords, GraphicsTier tier, bool stripLineDirectives)\n            {\n                return ShaderUtil.PreprocessShaderVariant(SourceShader, SubshaderIndex, m_PassIndex, shaderType, platformKeywords, keywords, shaderCompilerPlatform, buildTarget, tier, stripLineDirectives);\n            }\n        }\n\n        public int ActiveSubshaderIndex => ShaderUtil.GetShaderActiveSubshaderIndex(SourceShader);\n        public int SubshaderCount => ShaderUtil.GetShaderSubshaderCount(SourceShader);\n        public int SerializedSubshaderCount => ShaderUtil.GetShaderSerializedSubshaderCount(SourceShader);\n\n        public Shader SourceShader { get; private set; }\n\n        public Subshader ActiveSubshader\n        {\n            get\n            {\n                var index = ActiveSubshaderIndex;\n                if (index < 0 || index >= SubshaderCount)\n                    return null;\n\n                return new Subshader(this, index);\n            }\n        }\n\n        internal ShaderData(Shader sourceShader)\n        {\n            Assert.IsNotNull(sourceShader);\n            this.SourceShader = sourceShader;\n        }\n\n        public Subshader GetSubshader(int index)\n        {\n            if (index < 0 || index >= SubshaderCount)\n            {\n                Debug.LogErrorFormat(\"Subshader index is incorrect: {0}, shader {1} has {2} subshaders.\", index, SourceShader, SubshaderCount);\n                return null;\n            }\n\n            return new Subshader(this, index);\n        }\n\n        public Subshader GetSerializedSubshader(int index)\n        {\n            if (index < 0 || index >= SerializedSubshaderCount)\n            {\n                Debug.LogErrorFormat(\"Serialized Subshader index is incorrect: {0}, shader {1} has {2} serialized subshaders.\", index, SourceShader, SerializedSubshaderCount);\n                return null;\n            }\n\n            return new Subshader(this, index, Subshader.Type.Serialized);\n        }\n\n        public struct PreprocessedVariant\n        {\n            public bool Success { get; }\n            public ShaderMessage[] Messages { get; }\n            public string PreprocessedCode { get; }\n        }\n\n        //\n        // Experimental reflection information and raw compiled data access.  Used for Tiny shader export.\n        //\n        public struct VariantCompileInfo\n        {\n            public bool Success { get; }\n            public ShaderMessage[] Messages { get; }\n\n            public byte[] ShaderData { get; }\n\n            public VertexAttribute[] Attributes { get; }\n            public ConstantBufferInfo[] ConstantBuffers { get; }\n            public TextureBindingInfo[] TextureBindings { get; }\n        }\n\n        [DebuggerDisplay(\"cbuffer {Name} ({Size} bytes)\")]\n        public struct ConstantBufferInfo\n        {\n            public string Name { get; }\n            public int Size { get; }\n            public ConstantInfo[] Fields { get; }\n        }\n\n        [DebuggerDisplay(\"{ConstantType} {Name} ({DataType} {Columns}x{Rows})\")]\n        public struct ConstantInfo\n        {\n            public string Name { get; }\n            public int Index { get; }\n            public ShaderConstantType ConstantType { get; }\n            public ShaderParamType DataType { get; }\n            public int Rows { get; }\n            public int Columns { get; }\n            public int ArraySize { get; }\n\n            // only relevant if ConstantType == Struct\n            public int StructSize { get; }\n            public ConstantInfo[] StructFields { get; }\n        }\n\n        [DebuggerDisplay(\"{Dim} {Name}\")]\n        public struct TextureBindingInfo\n        {\n            public string Name { get; }\n            public int Index { get; }\n            public int SamplerIndex { get; }\n            public bool Multisampled { get; }\n            public int ArraySize { get; }\n            public TextureDimension Dim { get; }\n        }\n    }\n\n    public partial class ShaderUtil\n    {\n        public static ShaderData GetShaderData(Shader shader)\n        {\n            return new ShaderData(shader);\n        }\n\n        // GetShaderMessageCount includes warnings, this function filters them out\n        public static bool ShaderHasError(Shader shader)\n        {\n            FetchCachedMessages(shader);\n            var errors = GetShaderMessages(shader);\n            return errors.Any(x => x.severity == ShaderCompilerMessageSeverity.Error);\n        }\n\n        public static bool ShaderHasWarnings(Shader shader)\n        {\n            FetchCachedMessages(shader);\n            var errors = GetShaderMessages(shader);\n            return errors.Any(x => x.severity == ShaderCompilerMessageSeverity.Warning);\n        }\n\n        internal static extern bool PassHasShaderStage(Shader s, int subshaderIndex, int passIndex, ShaderType shaderType);\n\n        internal static bool MaterialsUseInstancingShader(SerializedProperty materialsArray)\n        {\n            if (materialsArray.hasMultipleDifferentValues)\n                return false;\n            for (int i = 0; i < materialsArray.arraySize; ++i)\n            {\n                var material = materialsArray.GetArrayElementAtIndex(i).objectReferenceValue as Material;\n                if (material != null && material.enableInstancing && material.shader != null && HasInstancing(material.shader))\n                    return true;\n            }\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Shaders/MaterialHierarchyPopup.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing Object = UnityEngine.Object;\nusing static UnityEditor.MaterialEditor;\n\nnamespace UnityEditor\n{\n    class MaterialHierarchyPopup : PopupWindowContent\n    {\n        const int k_MaxSearchIterationPerFrame = 500;\n        const int k_MaxTableRows = 10;\n        const int k_MinIconSize = 20;\n\n        const float k_MinWindowWidth = 300f, k_MaxWindowWidth = 500f;\n\n        const float k_HeaderHeight = 49f;\n        const float k_EntryHeight = 20f;\n        const float k_SliderWidth = 55f;\n        const float k_SearchHeight = 150f;\n        const float k_ConvertLabelWidth = 150f;\n\n        const float k_Padding = 3f;\n        const float k_OffsetX = 6f;\n        const float k_SplitWidth = 1f;\n\n        readonly float k_MinNameWidth;\n        readonly float k_TitleWidth = k_OffsetX + 50f;\n        readonly float k_LocksWidth = EditorStyles.miniLabel.CalcSize(Styles.locksLabel).x + 2 * k_Padding;\n        readonly float k_OverridesWidth = k_SplitWidth + EditorStyles.miniLabel.CalcSize(Styles.overridesLabel).x + 2 * k_Padding;\n\n        readonly float k_ScrollbarWidth = GUI.skin.verticalScrollbar.fixedWidth + GUI.skin.verticalScrollbar.margin.left;\n        readonly float k_ScrollbarHeight = GUI.skin.horizontalScrollbar.fixedHeight + GUI.skin.horizontalScrollbar.margin.top;\n\n        readonly MaterialEditor materialEditor;\n        readonly Material target;\n        readonly bool enabled;\n        readonly GUID targetGUID;\n        float windowWidth, namesWidth, maxNameWidth, noResultsX, locksX, overridesX;\n        Vector2 scroll = Vector2.zero;\n        int numRows;\n\n        // Children list\n        bool displayChildren;\n        ObjectListArea listArea;\n        ObjectListAreaState m_ListAreaState;\n        SavedInt m_SavedGridSize = new SavedInt(\"MaterialHierarchyPopup.GridSize\", 56);\n\n        // Search\n        readonly Delayer debounce;\n        readonly SearchFilter searchFilter;\n        int[] results = null;\n        string searchFilterString = \"\";\n        IEnumerator<HierarchyProperty> enumerator = null;\n\n        public static class Colors\n        {\n            static Color header_l = new Color32(0xDF, 0xDF, 0xDF, 0xFF);\n            static Color header_d = new Color(0.5f, 0.5f, 0.5f, 0.2f);\n\n            static Color[] rows_l = new Color[2]\n            {\n                new Color32(0xC8, 0xC8, 0xC8, 0xFF),\n                new Color32(0xCE, 0xCE, 0xCE, 0xFF)\n            };\n\n            static Color[] rows_d = new Color[2]\n            {\n                new Color32(0x38, 0x38, 0x38, 0xFF),\n                new Color32(0x3E, 0x3E, 0x3E, 0xFF)\n            };\n\n            public static Color headerBackground { get { return EditorGUIUtility.isProSkin ? Colors.header_d : Colors.header_l; } }\n            public static Color rowBackground(int i) => EditorGUIUtility.isProSkin ? Colors.rows_d[i % 2] : Colors.rows_l[i % 2];\n        }\n\n        public static class Styles\n        {\n            public static readonly GUIContent rootLabel = EditorGUIUtility.TrTextContent(\"Root\", \"The root of the hierarchy.\");\n            public static readonly GUIContent selectedLabel = EditorGUIUtility.TrTextContent(\"Current\", \"The currently selected Material.\");\n\n            public static readonly GUIContent instanceLabel = EditorGUIUtility.TrTextContent(\"Variant Family of\");\n            public static readonly GUIContent ancestorLabel = EditorGUIUtility.TrTextContent(\"Ancestors\");\n            public static readonly GUIContent overridesLabel = EditorGUIUtility.TrTextContent(\"Overrides\");\n            public static readonly GUIContent locksLabel = EditorGUIUtility.TrTextContent(\"Locks\");\n            public static readonly GUIContent childrenLabel = EditorGUIUtility.TrTextContent(\"Children\");\n            public static readonly GUIContent noResultsLabel = EditorGUIUtility.TrTextContent(\"No results\");\n            public static readonly GUIContent noChildrenLabel = EditorGUIUtility.TrTextContent(\"This Material doesn't have any children.\\nMaterial Variants created from this Material\\nwill be listed here.\");\n\n            public static readonly string[] headerPopupOptions = new string[] { \"Material\", \"Material Variant\" };\n            public static readonly GUIContent convertingLabel = EditorGUIUtility.TrTextContent(\"Converting to Material Variant\");\n            public static readonly GUIContent conversionHelpLabel = EditorGUIUtility.TrTextContent(\"To convert, select a Parent Material\");\n\n            public static readonly GUIStyle searchBackground = new GUIStyle(\"ProjectBrowserIconAreaBg\");\n            public static readonly GUIStyle centered = new GUIStyle(EditorStyles.label) { alignment = TextAnchor.MiddleCenter };\n            public static readonly GUIStyle boldRightAligned = new GUIStyle(EditorStyles.boldLabel)\n            {\n                alignment = TextAnchor.MiddleRight,\n                fontSize = (int)(1.1f * EditorStyles.boldLabel.fontSize)\n            };\n            public static readonly GUIStyle boldNumber = new GUIStyle(EditorStyles.boldLabel)\n            {\n                fontSize = (int)(0.9f * EditorStyles.boldLabel.fontSize)\n            };\n\n            public static readonly GUIStyle searchFieldStyle = new GUIStyle(EditorStyles.toolbarSearchField)\n            {\n                margin = new RectOffset(5, 4, 4, 5)\n            };\n        }\n\n        internal MaterialHierarchyPopup(Material target, bool enabled, MaterialEditor materialEditor, Rect activatorRect)\n        {\n            this.enabled = enabled;\n            this.materialEditor = materialEditor;\n            this.target = target;\n            targetGUID = AssetDatabase.GUIDFromAssetPath(AssetDatabase.GetAssetPath(target));\n\n            k_MinNameWidth = k_MinWindowWidth - (k_TitleWidth + k_SplitWidth + k_OverridesWidth + k_LocksWidth);\n\n            searchFilter = new SearchFilter()\n            {\n                classNames = new string[] { \"Material\" },\n                searchArea = SearchFilter.SearchArea.AllAssets\n            };\n            debounce = Delayer.Debounce(_ =>\n            {\n                SearchFilterChanged();\n                editorWindow.Repaint();\n            });\n\n            Init();\n        }\n\n        void Init()\n        {\n            displayChildren = !target.isVariant;\n\n            numRows = 0;\n            namesWidth = k_MinNameWidth;\n            if (target.isVariant)\n            {\n                Material current = target;\n                while (current != null)\n                {\n                    numRows++;\n                    namesWidth = Mathf.Max(GUI.skin.label.CalcSize(EditorGUIUtility.TempContent(current.name)).x + 23, namesWidth);\n                    current = current.parent;\n                }\n                numRows = Mathf.Max(numRows, 2); // at least this and his parent\n            }\n\n            float scrollBarWidthOffset = numRows >= k_MaxTableRows ? k_ScrollbarWidth : 0;\n            maxNameWidth = k_MaxWindowWidth - (k_TitleWidth + k_SplitWidth + k_OverridesWidth + k_LocksWidth) - scrollBarWidthOffset;\n\n            float prevWidth = windowWidth;\n            if (namesWidth <= k_MinNameWidth)\n                windowWidth = k_MinWindowWidth;\n            else if (namesWidth >= maxNameWidth)\n                windowWidth = k_MaxWindowWidth;\n            else\n                windowWidth = k_TitleWidth + namesWidth + k_SplitWidth + k_OverridesWidth + k_LocksWidth;\n\n            // Prevent window size from getting smaller when changing options\n            windowWidth = Mathf.Max(windowWidth, prevWidth);\n\n            locksX = windowWidth - k_LocksWidth - scrollBarWidthOffset;\n            overridesX = locksX - k_OverridesWidth;\n            noResultsX = (windowWidth - EditorStyles.label.CalcSize(Styles.noResultsLabel).x) * 0.5f;\n        }\n\n        public override void OnClose()\n        {\n            if (listArea != null)\n                listArea.OnDestroy();\n        }\n\n        public override Vector2 GetWindowSize()\n        {\n            var height = k_HeaderHeight;\n\n            if (target.isVariant)\n            {\n                // Horizontal scrollbar\n                if (namesWidth > maxNameWidth)\n                    height += k_ScrollbarHeight;\n\n                // Ancestors table\n                height += Mathf.Min(numRows, k_MaxTableRows) * k_EntryHeight + k_EntryHeight;\n            }\n\n            if (materialEditor.convertState != ConvertAction.Convert)\n            {\n                // Children list\n                height += k_EntryHeight;\n                if (displayChildren)\n                    height += k_SearchHeight;\n            }\n            else\n            {\n                // Conversion panel\n                height += 2 * k_EntryHeight + k_Padding;\n            }\n\n            return new Vector2(windowWidth, height);\n        }\n\n        public override void OnGUI(Rect rect)\n        {\n            // Escape closes the window\n            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)\n            {\n                editorWindow.Close();\n                GUIUtility.ExitGUI();\n            }\n\n            // Handle undo\n            if (target.parent != null && materialEditor.convertState == ConvertAction.Convert)\n            {\n                materialEditor.convertState = ConvertAction.None;\n                Init();\n            }\n\n            if (!DrawHeader())\n                return;\n\n            float height = k_HeaderHeight;\n            if (target.isVariant)\n                height += DrawVariantHierarchy();\n\n            height += DrawChildrenLabel(height);\n\n            if (displayChildren)\n                DrawChildren(height);\n\n            if (materialEditor.convertState == ConvertAction.Flatten)\n            {\n                materialEditor.convertState = ConvertAction.None;\n                Undo.RecordObject(target, \"Flatten Material Variant\");\n                target.parent = null;\n                Init();\n            }\n        }\n\n        bool DrawHeader()\n        {\n            Rect headerRect = GUILayoutUtility.GetRect(20, windowWidth, k_HeaderHeight, k_HeaderHeight);\n            EditorGUI.DrawRect(headerRect, Colors.headerBackground);\n\n            float labelSize = Styles.boldRightAligned.CalcSize(Styles.instanceLabel).x;\n\n            Rect labelRect = new Rect(k_OffsetX, headerRect.y + k_Padding, labelSize, EditorGUIUtility.singleLineHeight);\n            Rect contentRect = new Rect(labelRect.x + labelRect.width + k_Padding, labelRect.y, windowWidth, labelRect.height);\n\n            GUI.Label(labelRect, Styles.instanceLabel, Styles.boldRightAligned);\n            DoObjectLabel(contentRect, target, EditorStyles.boldLabel);\n\n            labelRect.y = labelRect.height + 2 * k_Padding;\n            if (materialEditor.convertState == ConvertAction.None)\n            {\n                int result;\n                labelRect.width = k_ConvertLabelWidth;\n                using (new EditorGUI.DisabledScope(!enabled))\n                    result = EditorGUI.Popup(labelRect, target.isVariant ? 1 : 0, Styles.headerPopupOptions);\n                if (result == 0 && target.isVariant)\n                    materialEditor.convertState = ConvertAction.Flatten;\n                if (result == 1 && !target.isVariant)\n                    materialEditor.convertState = ConvertAction.Convert;\n            }\n            else if (materialEditor.convertState == ConvertAction.Convert)\n            {\n                GUI.enabled = false;\n                labelRect.width = 200f;\n                EditorGUI.Button(labelRect, Styles.convertingLabel);\n                GUI.enabled = true;\n\n                // Conversion helper\n                labelRect.y = k_HeaderHeight;\n                labelRect.width = windowWidth;\n                EditorGUI.LabelField(labelRect, Styles.conversionHelpLabel);\n\n                labelRect.x = windowWidth - 14;\n                if (GUI.Button(labelRect, GUIContent.none, EditorStyles.toolbarSearchFieldCancelButton))\n                {\n                    materialEditor.convertState = ConvertAction.None;\n                    materialEditor.Repaint();\n                }\n\n                labelRect.x = k_OffsetX;\n                var oldLabelWidth = EditorGUIUtility.labelWidth;\n                EditorGUIUtility.labelWidth = 70;\n                EditorGUI.BeginChangeCheck();\n                var parent = target.parent;\n                materialEditor.ParentField(new Rect(k_OffsetX, labelRect.yMax + k_Padding, windowWidth - 2 * k_OffsetX, k_EntryHeight));\n                if (EditorGUI.EndChangeCheck() && parent != target.parent)\n                {\n                    materialEditor.convertState = ConvertAction.None;\n                    Init();\n                }\n                EditorGUIUtility.labelWidth = oldLabelWidth;\n                return false;\n            }\n\n            return true;\n        }\n\n        float DrawVariantHierarchy()\n        {\n            // Draw table header\n            Rect entryRect = new Rect(0, k_HeaderHeight, windowWidth, k_EntryHeight);\n            EditorGUI.DrawRect(entryRect, Colors.rowBackground(0));\n\n            var labelRect = entryRect;\n            labelRect.x = k_TitleWidth;\n            GUI.Label(labelRect, Styles.ancestorLabel, EditorStyles.miniLabel);\n\n            labelRect.x = overridesX + k_Padding;\n            GUI.Label(labelRect, Styles.overridesLabel, EditorStyles.miniLabel);\n\n            labelRect.x = locksX + k_Padding;\n            GUI.Label(labelRect, Styles.locksLabel, EditorStyles.miniLabel);\n\n            float tableHeight = Mathf.Min(numRows, k_MaxTableRows) * k_EntryHeight + (namesWidth > maxNameWidth ? k_ScrollbarHeight : 0);\n            float realHeight = numRows * k_EntryHeight + (namesWidth > maxNameWidth ? k_ScrollbarHeight : 0);\n            var tableRect = new Rect(0, k_HeaderHeight + k_EntryHeight, windowWidth - 1, tableHeight);\n            scroll.y = GUI.BeginScrollView(tableRect, scroll, new Rect(tableRect) { width = tableRect.width - k_ScrollbarWidth, height = realHeight }).y;\n\n            // Draw overrides and locks table\n            int i = numRows;\n            Material current = target;\n            while (current != null && i > 0)\n            {\n                entryRect.y = k_HeaderHeight + i * k_EntryHeight;\n                EditorGUI.DrawRect(entryRect, Colors.rowBackground(i--));\n\n                DisplayOverridesAndLocks(entryRect, current);\n                current = current.parent;\n            }\n\n            var scrollRect = new Rect(k_TitleWidth, k_HeaderHeight + k_EntryHeight, Mathf.Min(namesWidth, maxNameWidth), numRows * k_EntryHeight);\n            scroll.x = GUI.BeginScrollView(new Rect(scrollRect) { height = scrollRect.height + k_ScrollbarHeight }, scroll, new Rect(scrollRect) { width = namesWidth }).x;\n\n            // Draw scrollable table\n            i = numRows;\n            current = target;\n            entryRect.x = k_TitleWidth;\n            while (i != 0)\n            {\n                entryRect.y = k_HeaderHeight + i-- * k_EntryHeight;\n\n                if (current == null)\n                {\n                    GUI.Label(entryRect, EditorGUIUtility.TempContent(\"Missing (Material)\"));\n                    break;\n                }\n                DoObjectLabel(entryRect, current);\n                current = current.parent;\n            }\n\n            GUI.EndScrollView();\n\n            float height = tableHeight + k_EntryHeight;\n\n            // Draw selected label\n            labelRect.x = k_OffsetX;\n            labelRect.y = k_HeaderHeight + numRows * k_EntryHeight;\n            labelRect.width = k_TitleWidth - labelRect.x;\n            GUI.Label(labelRect, Styles.selectedLabel);\n\n            // Draw root label\n            if (labelRect.y != k_HeaderHeight + k_EntryHeight)\n            {\n                labelRect.y = k_HeaderHeight + k_EntryHeight;\n                GUI.Label(labelRect, Styles.rootLabel);\n            }\n\n            // Draw vertical splits\n            Rect splitBar = new Rect(overridesX - k_SplitWidth, k_HeaderHeight, k_SplitWidth, (numRows + 1) * k_EntryHeight);\n            EditorGUI.DrawRect(splitBar, Colors.headerBackground);\n            splitBar.x = locksX - k_SplitWidth;\n            EditorGUI.DrawRect(splitBar, Colors.headerBackground);\n\n            GUI.EndScrollView();\n\n            return height;\n        }\n\n        float DrawChildrenLabel(float yMin)\n        {\n            var labelRect = new Rect(k_OffsetX, yMin, 100, k_EntryHeight);\n            if (target.isVariant)\n                displayChildren = EditorGUI.Foldout(labelRect, displayChildren, Styles.childrenLabel, true);\n            else\n                EditorGUI.LabelField(labelRect, Styles.childrenLabel);\n\n            if (displayChildren)\n            {\n                if (listArea == null)\n                    InitListArea();\n\n                labelRect = new Rect(labelRect.x + 58 + (target.isVariant ? 12 : 0), labelRect.y + 2, k_SliderWidth, EditorGUI.kSingleLineHeight);\n                if (results.Length != 0)\n                    EditorGUI.LabelField(labelRect, results.Length.ToString(), Styles.boldNumber);\n\n                EditorGUI.BeginChangeCheck();\n                labelRect.x = windowWidth - k_OffsetX - k_SliderWidth;\n                var newGridSize = (int)GUI.HorizontalSlider(labelRect, listArea.gridSize, listArea.minGridSize, listArea.maxGridSize);\n                if (EditorGUI.EndChangeCheck())\n                    listArea.gridSize = m_SavedGridSize.value = newGridSize;\n            }\n\n            return k_EntryHeight;\n        }\n\n        void DrawChildren(float yMin)\n        {\n            var backgroundRect = new Rect(0, yMin, windowWidth, k_SearchHeight);\n            GUI.Label(backgroundRect, GUIContent.none, Styles.searchBackground);\n\n            EditorGUI.BeginChangeCheck();\n            var searchRect = new Rect(k_OffsetX + k_Padding, backgroundRect.y + k_Padding, windowWidth - 2 * k_OffsetX - k_Padding, Styles.searchFieldStyle.fixedHeight);\n            searchFilterString = EditorGUI.ToolbarSearchField(searchRect, searchFilterString, false);\n            if (EditorGUI.EndChangeCheck())\n                debounce.Execute();\n\n            if (enumerator != null)\n                Search();\n\n            yMin = searchRect.height + (listArea.gridSize < k_MinIconSize ? 11f : 0f);\n            var listRect = new Rect(k_Padding, searchRect.y + yMin, windowWidth - 2 * k_Padding, k_SearchHeight - yMin - k_Padding);\n\n            int listKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard);\n            listArea.OnGUI(listRect, listKeyboardControlID);\n\n            if (enumerator == null && results.Length == 0)\n            {\n                var labelRect = new Rect(noResultsX, backgroundRect.y + 69f, windowWidth, EditorGUI.kSingleLineHeight);\n                EditorGUI.LabelField(backgroundRect, searchFilter.nameFilter.Length == 0 ? Styles.noChildrenLabel : Styles.noResultsLabel, Styles.centered);\n            }\n        }\n\n        void InitListArea()\n        {\n            m_ListAreaState = new ObjectListAreaState() { m_GridSize = m_SavedGridSize };\n            listArea = new ObjectListArea(m_ListAreaState, editorWindow, false)\n            {\n                allowDeselection = true,\n                allowMultiSelect = false,\n                allowRenaming = false,\n                allowBuiltinResources = true,\n            };\n\n            listArea.itemSelectedCallback += (bool doubleClicked) =>\n            {\n                if (listArea.GetSelection().Length == 0)\n                    return;\n                var selection = listArea.GetSelection()[0];\n                GUIUtility.keyboardControl = GUIUtility.GetControlID(FocusType.Keyboard);\n                if (doubleClicked)\n                {\n                    Selection.SetActiveObjectWithContext(EditorUtility.InstanceIDToObject(selection), null);\n                    Event.current.Use();\n                    editorWindow.Close();\n                    GUIUtility.ExitGUI();\n                }\n                else\n                {\n                    EditorGUIUtility.PingObject(selection);\n                    Event.current.Use();\n                }\n            };\n\n            SearchFilterChanged();\n        }\n\n        static IEnumerator<HierarchyProperty> FindInAllAssets(SearchFilter searchFilter)\n        {\n            var rootPaths = new List<string>();\n            rootPaths.Add(\"Assets\");\n            foreach (var package in PackageManagerUtilityInternal.GetAllVisiblePackages(false))\n            {\n                if (package.source == PackageManager.PackageSource.Local)\n                    rootPaths.Add(package.assetPath);\n            }\n\n            foreach (var rootPath in rootPaths)\n            {\n                var property = new HierarchyProperty(rootPath, false);\n                property.SetSearchFilter(searchFilter);\n                while (property.Next(null))\n                    yield return property;\n            }\n        }\n\n        void SearchFilterChanged()\n        {\n            searchFilter.nameFilter = searchFilterString;\n\n            var size = GetWindowSize();\n            var rect = new Rect(0, size.y - k_SearchHeight, size.x, k_SearchHeight);\n\n            listArea.Init(rect, HierarchyType.Assets, new SearchFilter(), true, SearchService.SearchSessionOptions.Default);\n            enumerator = FindInAllAssets(searchFilter);\n            results = new int[0];\n        }\n\n        void Search()\n        {\n            var newResults = new List<int>();\n\n            var maxAddCount = k_MaxSearchIterationPerFrame;\n            while (--maxAddCount >= 0)\n            {\n                if (!enumerator.MoveNext())\n                {\n                    enumerator = null;\n                    break;\n                }\n                var child = InternalEditorUtility.GetLoadedObjectFromInstanceID(enumerator.Current.GetInstanceIDIfImported()) as Material;\n                if (!child)\n                {\n                    // First check guid from file to avoid loading material in memory\n                    string path = AssetDatabase.GUIDToAssetPath(enumerator.Current.guid);\n                    if (EditorMaterialUtility.GetMaterialParentFromFile(path) != targetGUID)\n                        continue;\n                    child = AssetDatabase.LoadAssetAtPath<Material>(path);\n                }\n                if (child != null && child.parent == target)\n                    newResults.Add(child.GetInstanceID());\n            }\n\n            int newElements = newResults.Count;\n            int i = results.Length;\n            System.Array.Resize(ref results, results.Length + newElements);\n            for (var j = 0; j < newElements && i < results.Length; ++j, ++i)\n                results[i] = newResults[j];\n\n            listArea.ShowObjectsInList(results);\n        }\n\n        void DisplayOverridesAndLocks(Rect rect, Material entry)\n        {\n            rect.x = overridesX;\n            rect.width = k_OverridesWidth;\n            int overrideCount = entry.overrideCount;\n            GUI.Label(rect, overrideCount == 0 ? \"-\" : overrideCount.ToString(), Styles.centered);\n\n            rect.x = locksX;\n            rect.width = k_LocksWidth;\n            int lockCount = entry.lockCount;\n            GUI.Label(rect, lockCount == 0 ? \"-\" : lockCount.ToString(), Styles.centered);\n        }\n\n        void DoObjectLabel(Rect rect, Object entry)\n        {\n            DoObjectLabel(rect, entry, GUI.skin.label);\n        }\n\n        void DoObjectLabel(Rect rect, Object entry, GUIStyle style)\n        {\n            GUI.Label(rect, AssetPreview.GetMiniThumbnail(entry));\n\n            if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && rect.Contains(Event.current.mousePosition))\n            {\n                // One click shows where the referenced object is\n                if (Event.current.clickCount == 1)\n                {\n                    GUIUtility.keyboardControl = GUIUtility.GetControlID(FocusType.Keyboard);\n\n                    EditorGUIUtility.PingObject(entry);\n                    Event.current.Use();\n                }\n                // Double click changes selection to referenced object\n                else if (Event.current.clickCount == 2)\n                {\n                    if (entry)\n                    {\n                        Selection.SetActiveObjectWithContext(entry, null);\n                        Event.current.Use();\n                        editorWindow.Close();\n                        GUIUtility.ExitGUI();\n                    }\n                }\n            }\n\n            rect.x += rect.height;\n            rect.width -= rect.height;\n            GUI.Label(rect, EditorGUIUtility.TempContent(entry.name, entry.name), style);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Shaders/ShaderKeywordFilterAttributes.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.IO;\nusing System.Runtime.CompilerServices;\nusing UnityEngine;\nusing ATarget = System.AttributeTargets;\n\nnamespace UnityEditor.ShaderKeywordFilter\n{\n    public enum FilterAction\n    {\n        Select,         // Only selected keywords will remain in the tuple\n        Remove,         // Remove specific keywords from the tuple\n        SelectOrRemove  // Select if the condition is evaluated true, remove otherwise\n    };\n\n    /* FilterAttribute and the derived attributes below enable users to control multi_compile keywords based\n     * on settings data. The attribute marks a data field with condition and filter action. If the comparison\n     * between condition and field data passes, the attribute filter action is applied to the keywords\n     * passed in as attribute arguments. Any keyword tuple (i.e. keywords from a single multi_compile) that\n     * has one of these keywords is filtered using this action. Filter actions are evaluated in the order of\n     * appearance in the data type tree. Overriding previous actions only happens if explicitly requested\n     * by the attribute.\n     */\n    [System.AttributeUsage(ATarget.Field, AllowMultiple = true)]\n    public class FilterAttribute : System.Attribute\n    {\n        public enum Precedence\n        {\n            Normal,         // Any previous filter rule will take precedence\n            Override        // This filter rule will be taken over any previous ones\n        };\n\n        public enum EvaluationMode\n        {\n            Normal,         // This filter rule applies if condition value matches with the target field data\n            Negated         // This filter rule applies if condition value does NOT match with the target field data\n        };\n\n        public FilterAttribute(FilterAction action, Precedence precedence, EvaluationMode evaluationMode, object condition, string fileName, int lineNumber, params string[] keywordNames)\n        {\n            m_Action = action;\n            m_Precedence = precedence;\n            m_EvaluationMode = evaluationMode;\n            m_Condition = condition;\n            m_Names = keywordNames;\n            m_FileName = fileName;\n            m_LineNumber = lineNumber;\n\n            if (m_DoDebugLogging)\n            {\n                // TODO - Need to add a setting around the logging/analytics/stats reporting.\n                //        Should have have levels or modes to allow the user to validate their rules.\n                Debug.LogFormat(LogType.Log, LogOption.NoStacktrace, null,\n                    \"{0} attribute declared at {1}:{2} for keyword(s) '{3}' predicated on the value '{4}'\",\n                    GetFilterActionName(m_Action), m_FileName, m_LineNumber, String.Join(\", \", m_Names), m_Condition);\n            }\n        }\n\n        internal string GetFilterActionName(FilterAction action)\n        {\n            switch (action)\n            {\n                case FilterAction.Select:\n                    return \"Select\";\n                case FilterAction.Remove:\n                    return \"Remove\";\n                case FilterAction.SelectOrRemove:\n                    return \"SelectOrRemove\";\n                default:\n                    return \"Unknown\";\n            }\n        }\n\n        internal void EnableLogging()\n        {\n            m_DoDebugLogging = true;\n        }\n\n        internal void DisableLogging()\n        {\n            m_DoDebugLogging = false;\n        }\n\n        internal string GetFormattedResolutionMessageActive(object data)\n        {\n            var s = String.Format(\"Applying {0} attribute declared at {1}:{2} because condition was '{3}'\",\n                GetFilterActionName(m_Action), m_FileName, m_LineNumber, data);\n\n            if (m_DoDebugLogging)\n                Debug.LogFormat(LogType.Log, LogOption.NoStacktrace, null, s);\n\n            return s;\n        }\n\n        internal string GetFormattedResolutionMessageInactive(object data)\n        {\n            var s = String.Format(\"Skipping {0} attribute declared at {1}:{2} because condition was '{3}'\",\n                GetFilterActionName(m_Action), m_FileName, m_LineNumber, data);\n\n            if (m_DoDebugLogging)\n                Debug.LogFormat(LogType.Log, LogOption.NoStacktrace, null, s);\n\n            return s;\n        }\n\n        internal string GetFormattedResolutionMessageOverride(object data, FilterRule originalRule)\n        {\n            var s = String.Format(\"Overriding {0} attribute for keyword '{1}' with {2} attribute declared at {3}:{4}\",\n                GetFilterActionName(originalRule.action), originalRule.keywordName, GetFilterActionName(m_Action),\n                m_FileName, m_LineNumber);\n\n            if (m_DoDebugLogging)\n                Debug.LogFormat(LogType.Log, LogOption.NoStacktrace, null, s);\n\n            return s;\n        }\n\n        internal Precedence RulePrecedence\n        {\n            get => m_Precedence;\n        }\n\n        internal string[] KeywordNames\n        {\n            get => m_Names;\n        }\n\n        internal FilterAction Action\n        {\n            get => m_Action;\n        }\n\n        // Based on input data evaluate the correct filter action (either Select or Remove).\n        // Returns false if the filter is inactive and therefore to be ignored.\n        internal bool GetActiveFilterAction(object data, out FilterAction action)\n        {\n            bool match = m_Condition.Equals(data);\n\n            if (m_EvaluationMode == EvaluationMode.Negated)\n                match = !match;\n\n            if (m_Action == FilterAction.SelectOrRemove)\n            {\n                action = match ? FilterAction.Select : FilterAction.Remove;\n                return true; // SelectOrRemove always returns an active filter action\n            }\n\n            action = m_Action;\n            return match;\n        }\n\n        static private bool m_DoDebugLogging = false;\n        private FilterAction m_Action;\n        private Precedence m_Precedence;\n        private EvaluationMode m_EvaluationMode;\n        private string[] m_Names;\n        private object m_Condition;\n        // These two record the location of this particular filter attribute declaration\n        private string m_FileName;\n        private int m_LineNumber;\n    }\n\n    public class SelectIfAttribute : FilterAttribute\n    {\n        public SelectIfAttribute(object condition, bool overridePriority = false, [CallerFilePath] string filePath = \"\", [CallerLineNumber] int lineNumber = 0, params string[] keywordNames)\n            : base(FilterAction.Select, overridePriority ? Precedence.Override : Precedence.Normal, EvaluationMode.Normal, condition, Path.GetFileName(filePath), lineNumber, keywordNames)\n        {\n        }\n    }\n\n    public class RemoveIfAttribute : FilterAttribute\n    {\n        public RemoveIfAttribute(object condition, bool overridePriority = false, [CallerFilePath] string filePath = \"\", [CallerLineNumber] int lineNumber = 0, params string[] keywordNames)\n            : base(FilterAction.Remove, overridePriority ? Precedence.Override : Precedence.Normal, EvaluationMode.Normal, condition, Path.GetFileName(filePath), lineNumber, keywordNames)\n        {\n        }\n    }\n\n    public class SelectOrRemoveAttribute : FilterAttribute\n    {\n        public SelectOrRemoveAttribute(object condition, bool overridePriority = false, [CallerFilePath] string filePath = \"\", [CallerLineNumber] int lineNumber = 0, params string[] keywordNames)\n            : base(FilterAction.SelectOrRemove, overridePriority ? Precedence.Override : Precedence.Normal, EvaluationMode.Normal, condition, Path.GetFileName(filePath), lineNumber, keywordNames)\n        {\n        }\n    }\n\n    public class SelectIfNotAttribute : FilterAttribute\n    {\n        public SelectIfNotAttribute(object condition, bool overridePriority = false, [CallerFilePath] string filePath = \"\", [CallerLineNumber] int lineNumber = 0, params string[] keywordNames)\n            : base(FilterAction.Select, overridePriority ? Precedence.Override : Precedence.Normal, EvaluationMode.Negated, condition, Path.GetFileName(filePath), lineNumber, keywordNames)\n        {\n        }\n    }\n\n    public class RemoveIfNotAttribute : FilterAttribute\n    {\n        public RemoveIfNotAttribute(object condition, bool overridePriority = false, [CallerFilePath] string filePath = \"\", [CallerLineNumber] int lineNumber = 0, params string[] keywordNames)\n            : base(FilterAction.Remove, overridePriority ? Precedence.Override : Precedence.Normal, EvaluationMode.Negated, condition, Path.GetFileName(filePath), lineNumber, keywordNames)\n        {\n        }\n    }\n\n    public class RemoveOrSelectAttribute : FilterAttribute\n    {\n        public RemoveOrSelectAttribute(object condition, bool overridePriority = false, [CallerFilePath] string filePath = \"\", [CallerLineNumber] int lineNumber = 0, params string[] keywordNames)\n            : base(FilterAction.SelectOrRemove, overridePriority ? Precedence.Override : Precedence.Normal, EvaluationMode.Negated, condition, Path.GetFileName(filePath), lineNumber, keywordNames)\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Shaders/ShaderKeywordFilterConstraintAttributes.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine.Rendering;\nusing ATarget = System.AttributeTargets;\n\nnamespace UnityEditor.ShaderKeywordFilter\n{\n    /* These constraint attributes are used for limiting which parts of the settings data\n     structure can affect the variant filtering on specific conditions (tags, graphics API, etc)*/\n    [System.AttributeUsage(ATarget.Class | ATarget.Struct | ATarget.Field, AllowMultiple = true)]\n    public class TagConstraintAttribute : System.Attribute\n    {\n        public TagConstraintAttribute(bool negate, params string[] tags)\n        {\n            m_Negate = negate;\n            m_Tags = tags;\n        }\n\n        internal bool ShouldApplyRules(params string[] currentTags)\n        {\n            for (int i = 0, n = currentTags.Length - 1; i < n; i += 2) // Tags should be in name/value pairs. Ignore possible odd one.\n            {\n                for (int j = 0, m = m_Tags.Length - 1; j < m; j += 2)\n                {\n                    if (currentTags[i].Equals(m_Tags[j]) && currentTags[i + 1].Equals(m_Tags[j + 1]))\n                        return !m_Negate;\n                }\n            }\n\n            return m_Negate;\n        }\n\n        internal bool Negated\n        {\n            get => m_Negate;\n        }\n\n        internal string[] Tags\n        {\n            get => m_Tags;\n        }\n\n        bool m_Negate;\n        string[] m_Tags;\n    }\n\n    public class ApplyRulesIfTagsEqualAttribute : TagConstraintAttribute\n    {\n        public ApplyRulesIfTagsEqualAttribute(params string[] tags)\n            : base(false, tags)\n        {\n        }\n    }\n\n    public class ApplyRulesIfTagsNotEqualAttribute : TagConstraintAttribute\n    {\n        public ApplyRulesIfTagsNotEqualAttribute(params string[] tags)\n            : base(true, tags)\n        {\n        }\n    }\n\n    [System.AttributeUsage(ATarget.Class | ATarget.Struct | ATarget.Field, AllowMultiple = false)]\n    public class GraphicsAPIConstraintAttribute : System.Attribute\n    {\n        public GraphicsAPIConstraintAttribute(bool negate, params GraphicsDeviceType[] graphicsDeviceTypes)\n        {\n            m_Negate = negate;\n            m_GraphicsDeviceTypes = graphicsDeviceTypes;\n        }\n\n        internal bool ShouldApplyRules(GraphicsDeviceType currentGraphicDeviceType)\n        {\n            foreach (var device in m_GraphicsDeviceTypes)\n            {\n                if (device == currentGraphicDeviceType)\n                    return !m_Negate;\n            }\n\n            return m_Negate;\n        }\n\n        internal bool Negated\n        {\n            get => m_Negate;\n        }\n\n        internal GraphicsDeviceType[] GraphicsAPIs\n        {\n            get => m_GraphicsDeviceTypes;\n        }\n\n        bool m_Negate;\n        GraphicsDeviceType[] m_GraphicsDeviceTypes;\n    }\n\n    public class ApplyRulesIfGraphicsAPIAttribute : GraphicsAPIConstraintAttribute\n    {\n        public ApplyRulesIfGraphicsAPIAttribute(params GraphicsDeviceType[] graphicsDeviceTypes)\n            : base(false, graphicsDeviceTypes)\n        {\n        }\n    }\n\n    public class ApplyRulesIfNotGraphicsAPIAttribute : GraphicsAPIConstraintAttribute\n    {\n        public ApplyRulesIfNotGraphicsAPIAttribute(params GraphicsDeviceType[] graphicsDeviceTypes)\n            : base(true, graphicsDeviceTypes)\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Shaders/ShaderKeywordFilterData.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing System.Runtime.CompilerServices;\nusing UnityEngine;\n\n[assembly: InternalsVisibleTo(\"Assembly-CSharp-Editor-testable\")]\n\nnamespace UnityEditor.ShaderKeywordFilter\n{\n    // An internal constraint state. This is used for tracking which constraints affect which data field/attribute.\n    // Provides the functionality to check whether the constraint state of the current pass makes a filter rule active or inactive.\n    // Note: Don't mix up with struct ConstraintState which is the interop struct for getting the state from C++.\n    internal class Constraints\n    {\n        internal Constraints(Constraints other)\n        {\n            m_TagAttributes = new List<TagConstraintAttribute>(other.m_TagAttributes);\n            m_GraphicsAPIAttributes = new List<GraphicsAPIConstraintAttribute>(other.m_GraphicsAPIAttributes);\n        }\n\n        internal Constraints(TagConstraintAttribute[] tagConstraints, GraphicsAPIConstraintAttribute[] graphicsAPIConstraints)\n        {\n            m_TagAttributes = new List<TagConstraintAttribute>(tagConstraints);\n            m_GraphicsAPIAttributes = new List<GraphicsAPIConstraintAttribute>(graphicsAPIConstraints);\n        }\n\n        internal void AddParentConstraints(Constraints parent)\n        {\n            m_TagAttributes.InsertRange(0, parent.m_TagAttributes);\n            m_GraphicsAPIAttributes.InsertRange(0, parent.m_GraphicsAPIAttributes);\n        }\n\n        internal List<TagConstraintAttribute> TagConstraints\n        {\n            get => m_TagAttributes;\n        }\n\n        internal List<GraphicsAPIConstraintAttribute> GraphicsAPIConstraints\n        {\n            get => m_GraphicsAPIAttributes;\n        }\n\n        internal bool ShouldApplyFilterRules(ConstraintState state)\n        {\n            if (state.graphicsAPIs != null)\n            {\n                bool gfxAPIMismatch = false;\n                foreach (var gfxAPIConstraint in m_GraphicsAPIAttributes)\n                {\n                    foreach (var api in state.graphicsAPIs)\n                    {\n                        gfxAPIMismatch |= !gfxAPIConstraint.ShouldApplyRules(api); // can't filter if any of the APIs must be included (DX11/DX12 shared compiler platform)\n                    }\n                }\n                if (gfxAPIMismatch)\n                    return false;\n            }\n\n            if (state.tags != null)\n            {\n                bool tagMismatch = false;\n                foreach (var tagConstraint in m_TagAttributes)\n                {\n                    tagMismatch |= !tagConstraint.ShouldApplyRules(state.tags);\n                }\n\n                if (tagMismatch)\n                    return false;\n            }\n\n            return true;\n        }\n\n        List<TagConstraintAttribute> m_TagAttributes;\n        List<GraphicsAPIConstraintAttribute> m_GraphicsAPIAttributes;\n    }\n\n    // Represents a single filter attribute in the settings tree structure.\n    // Tracks the field it's attached to and all the accumulated constraints that affect it.\n    internal struct FilterData\n    {\n        internal FilterData(string fieldName, FilterAttribute attribute, Constraints constraints, object value)\n        {\n            this.fieldName = fieldName;\n            this.attribute = attribute;\n            this.constraints = constraints;\n            this.value = value;\n        }\n\n        internal string fieldName;\n        internal FilterAttribute attribute;\n        internal Constraints constraints;\n        internal object value;\n    }\n\n    internal struct FilterStats\n    {\n        internal void CountActionUnresolved(FilterAction a)\n        {\n            switch (a)\n            {\n                case FilterAction.Select:\n                    ++m_NumberOfSelectKeywords;\n                    break;\n                case FilterAction.Remove:\n                    ++m_NumberOfRemoveKeywords;\n                    break;\n                case FilterAction.SelectOrRemove:\n                    ++m_NumberOfSelectKeywords;\n                    ++m_NumberOfRemoveKeywords;\n                    break;\n            }\n\n            // Always count against the total number of filter rules\n            ++m_NumberOfRules;\n        }\n\n        internal void CountActionResolved(FilterAction a)\n        {\n            switch (a)\n            {\n                case FilterAction.Select:\n                    ++m_NumberOfSelectKeywordsResolved;\n                    break;\n                case FilterAction.Remove:\n                    ++m_NumberOfRemoveKeywordsResolved;\n                    break;\n                case FilterAction.SelectOrRemove:\n                    // Resolved actions cannot be both\n                    break;\n            }\n        }\n\n        internal UInt32 m_NumberOfRules;                  // Total number of filter rules for a settings node\n        internal UInt32 m_NumberOfRemoveKeywords;         // Total number of remove actions (includes select or remove)\n        internal UInt32 m_NumberOfSelectKeywords;         // Total number of select actions (includes select or remove)\n        internal UInt32 m_NumberOfRemoveKeywordsResolved; // Number of remove actions based on current setting values\n        internal UInt32 m_NumberOfSelectKeywordsResolved; // Number of select actions based on current setting values\n    }\n\n    // A single instance of keyword name/FilterAction pair. Used as the output format when flattening the settings tree\n    // to an array form with GetVariantArray().\n    internal struct FilterRule\n    {\n        internal FilterRule(string keywordName, bool withEmptyKeyword, FilterAction action, string resolutionMessage)\n        {\n            this.keywordName = keywordName;\n            this.withEmptyKeyword = withEmptyKeyword;\n            this.action = action;\n            this.resolutionMessage = resolutionMessage;\n        }\n\n        internal string keywordName;\n        internal bool withEmptyKeyword;\n        internal FilterAction action;\n        internal string resolutionMessage;\n    }\n\n    // SettingsNode represents a node in the settings tree, containing filter data and child nodes.\n    // Static method GatherFilterData() is used for constructing SettingsNode tree from a type tree.\n    internal class SettingsNode\n    {\n        internal SettingsNode(string name)\n        {\n            m_Name = name;\n            m_Children = new List<SettingsNode>();\n            m_FilterData = new List<FilterData>();\n        }\n\n        private static Constraints GetConstraintAttributes(ICustomAttributeProvider ap)\n        {\n            var tagConstraints = ap.GetCustomAttributes(typeof(TagConstraintAttribute), false);\n            var graphicsAPIConstraints = ap.GetCustomAttributes(typeof(GraphicsAPIConstraintAttribute), false);\n            if (tagConstraints.Length > 0 || graphicsAPIConstraints.Length > 0)\n            {\n                return new Constraints((TagConstraintAttribute[])tagConstraints, (GraphicsAPIConstraintAttribute[])graphicsAPIConstraints);\n            }\n\n            return null;\n        }\n\n        // Traverses through the type tree of the given object to find filter attributes and creates\n        // settings tree structure out of it.\n        // Returns null if no filter attributes were found.\n        // This method is called recursively for the tree traversing purposes.\n        internal static SettingsNode GatherFilterData(string nodeName, object containerObject, HashSet<object> visited, Constraints parentConstraints = null)\n        {\n            SettingsNode node = null; // defer construction to when filter data is actually found\n            if (containerObject == null)\n                return node;\n\n            // Unity objects have their own validity checking\n            if (containerObject is UnityEngine.Object)\n            {\n                var unityObject = containerObject as UnityEngine.Object;\n                if (!unityObject)\n                    return node;\n            }\n\n            if (!visited.Add(containerObject))\n                return node;\n\n            var containerConstraints = GetConstraintAttributes(containerObject.GetType());\n            if (parentConstraints != null)\n            {\n                // Merge constraints with the parent\n                if (containerConstraints == null)\n                    containerConstraints = new Constraints(parentConstraints);\n                else\n                    containerConstraints.AddParentConstraints(parentConstraints);\n            }\n\n            // Reflect all fields from the container's type. We must manually traverse the type's inheritance chain\n            // since, otherwise, there's no way to expose private fields belonging to the type's base class.\n            const BindingFlags kFieldReflectionFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance\n                | BindingFlags.Static | BindingFlags.DeclaredOnly;\n            var fields = new List<FieldInfo>();\n            var containerType = containerObject.GetType();\n            while (containerType != null)\n            {\n                var declaredFields = containerType.GetFields(kFieldReflectionFlags);\n                fields.AddRange(declaredFields);\n                containerType = containerType.BaseType;\n            }\n\n            // Go through all fields that could potentially contain filter attributes (directly or through children)\n            foreach (var f in fields)\n            {\n                bool isConst = f.IsLiteral && !f.IsInitOnly;\n\n                // Only public fields, constants and private fields with [SerializeField] attribute are accepted sources\n                if (!f.IsPublic && !isConst && f.GetCustomAttributes(typeof(SerializeField), false).Length == 0)\n                    continue;\n\n                // Drop deprecated fields\n                if (f.GetCustomAttributes(typeof(System.ObsoleteAttribute), false).Length != 0)\n                    continue;\n\n                var value = f.GetValue(containerObject);\n                if (value == null)\n                    continue;\n\n                Type type = value.GetType();\n\n                // Enumerable (array/list) is a potential branch in the settings tree\n                if (value is IEnumerable)\n                {\n                    var enumerable = value as IEnumerable;\n\n                    // UUM-72309 - A crash occured due to a third party package throwing when accessing its enumerator.\n                    // This try/catch should prevent such issues and log an error.\n                    try\n                    {\n                        bool hasDifferentChildren = (node != null) && (node.m_Children.Count > 0);\n                        foreach (var e in enumerable)\n                        {\n                            var childVisited = new HashSet<object>(visited);\n                            SettingsNode newBranch = GatherFilterData(f.Name, e, childVisited, containerConstraints);\n                            if (newBranch != null)\n                            {\n                                if (node == null)\n                                    node = new SettingsNode(nodeName);\n\n                                if (hasDifferentChildren)\n                                {\n                                    Debug.LogError(\"ShaderKeywordFilter attributes cannot be placed on a settings tree with multiple different branches on the same level.\");\n                                }\n                                else\n                                {\n                                    node.m_Children.Add(newBranch);\n                                }\n                            }\n                        }\n                    }\n                    catch(Exception ex)\n                    {\n                        Debug.LogError($\"An error occured while processing ShaderKeywordFilter attributes; Reading node: {nodeName} and field: {f.Name}\\n {ex.Message}\");\n                    }\n                }\n                else if (!type.IsValueType || (type.IsValueType && !type.IsPrimitive && !type.IsEnum)) // class or struct\n                {\n                    var childVisited = new HashSet<object>(visited);\n                    var nestedNode = GatherFilterData(f.Name, value, childVisited, containerConstraints);\n                    if (nestedNode != null)\n                    {\n                        if (node == null)\n                            node = new SettingsNode(nodeName);\n\n                        node.m_FilterData.AddRange(nestedNode.m_FilterData);\n                        foreach (var fd in nestedNode.m_FilterData)\n                        {\n                            node.m_FilterStats.CountActionUnresolved(fd.attribute.Action);\n                        }\n\n                        if (node.m_Children.Count > 0 && nestedNode.m_Children.Count > 0)\n                        {\n                            Debug.LogError(\"ShaderKeywordFilter attributes cannot be placed on a settings tree with multiple different branches on the same level.\");\n                        }\n                        else\n                        {\n                            node.m_Children.AddRange(nestedNode.m_Children);\n                        }\n                    }\n                }\n                else // plain data fields\n                {\n                    var constraints = GetConstraintAttributes(f);\n                    if (containerConstraints != null)\n                    {\n                        // Merge constraints with parent. Each field sees all the constraints from the root up to it.\n                        if (constraints != null)\n                            constraints.AddParentConstraints(containerConstraints);\n                        else\n                            constraints = new Constraints(containerConstraints);\n                    }\n\n                    var attributes = f.GetCustomAttributes(typeof(FilterAttribute), false);\n                    foreach (var a in attributes)\n                    {\n                        if (a is FilterAttribute)\n                        {\n                            if (node == null)\n                                node = new SettingsNode(nodeName);\n\n                            var fa = a as FilterAttribute;\n                            node.m_FilterData.Add(new FilterData(f.Name, fa, constraints, value));\n                            node.m_FilterStats.CountActionUnresolved(fa.Action);\n                        }\n                    }\n                }\n            }\n\n            return node;\n        }\n\n        // Recursively traversing through the settings tree, resolving the rules on its way from\n        // the root to the leaves. When a leaf is encountered, a new SettingsVariant is added to the list.\n        // The filter rule resolving happens from root to leaf with this logic:\n        //  * Whatever rule for a specific keyword is encountered first takes precedence by default.\n        //  * Later encountered rules are ignored, unless the attribute explicitly asks for override.\n        //    In that case this override rule will take precedence.\n        internal void GetVariantArray(ConstraintState constraintState, List<SettingsVariant> variants, List<FilterRule> parentRules = null)\n        {\n            // Grab a copy of the rules resolved so far. We don't want to modify the parent data\n            // as siblings of this node could resolve things differently.\n            var currentRules = parentRules != null ? new List<FilterRule>(parentRules) : new List<FilterRule>();\n            foreach(var filter in m_FilterData)\n            {\n                // Skip the filter if constraint rules require so\n                if (filter.constraints != null)\n                {\n                    if(!filter.constraints.ShouldApplyFilterRules(constraintState))\n                        continue;\n                }\n\n                FilterAction filterAction;\n                bool isActive = filter.attribute.GetActiveFilterAction(filter.value, out filterAction);\n\n                // Early out for inactive filter attributes.\n                if (!isActive)\n                {\n                    filter.attribute.GetFormattedResolutionMessageInactive(filter.value);\n                    continue;\n                }\n\n                bool overrideRule = filter.attribute.RulePrecedence == FilterAttribute.Precedence.Override;\n                bool addRule = true;\n                bool affectsEmptyKw = false;\n\n                // check if the attribute affects \"empty keyword\" case\n                foreach (var keywordName in filter.attribute.KeywordNames)\n                {\n                    if (keywordName.Length == 0)\n                        affectsEmptyKw = true;\n                }\n\n                foreach (var keywordName in filter.attribute.KeywordNames)\n                {\n                    if (keywordName.Length == 0)\n                        continue;\n\n                    for (int i = 0; i < currentRules.Count; ++i)\n                    {\n                        if (currentRules[i].keywordName.Equals(keywordName))\n                        {\n                            if (overrideRule)\n                            {\n                                var resolutionMessage = filter.attribute.GetFormattedResolutionMessageOverride(filter.value, currentRules[i]);\n                                currentRules[i] = new FilterRule(keywordName, affectsEmptyKw, filterAction, resolutionMessage);\n                            }\n\n                            addRule = false;\n                            break;\n                        }\n                    }\n                    if (addRule)\n                    {\n                        var resolutionMessage = filter.attribute.GetFormattedResolutionMessageActive(filter.value);\n                        currentRules.Add(new FilterRule(keywordName, affectsEmptyKw, filterAction, resolutionMessage));\n                        m_FilterStats.CountActionResolved(filterAction);\n                    }\n                }\n            }\n\n            if (m_Children.Count > 0)\n            {\n                foreach (var child in m_Children)\n                {\n                    child.GetVariantArray(constraintState, variants, currentRules);\n                }\n            }\n            else\n            {\n                variants.Add(new SettingsVariant(currentRules));\n            }\n        }\n\n        internal string Name\n        {\n            get => m_Name;\n        }\n\n        internal List<SettingsNode> Children\n        {\n            get => m_Children;\n        }\n\n        internal List<FilterData> FilterData\n        {\n            get => m_FilterData;\n        }\n\n        internal FilterStats FilterStats\n        {\n            get => m_FilterStats;\n        }\n\n        string m_Name;\n        List<SettingsNode> m_Children;\n        List<FilterData> m_FilterData;\n        FilterStats m_FilterStats;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Shaders/ShaderKeywordFilterUtil.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Rendering;\nusing UnityEngine.Scripting;\n\n[assembly: InternalsVisibleTo(\"Assembly-CSharp-Editor-testable\")]\n\nnamespace UnityEditor.ShaderKeywordFilter\n{\n    // SettingsVariant represents a leaf node in the settings tree.\n    // The keyword arrays there tell which keywords need to be selected and which removed.\n    // This data is used in the native code to prune the enumeration data, thus reducing\n    // the size of enumerated variant space.\n    [RequiredByNativeCode (GenerateProxy = true)]\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct SettingsVariant\n    {\n        internal SettingsVariant(List<FilterRule> rules)\n        {\n            var selected = new List<string>();\n            var selectedMessages = new List<string>();\n            var emptyKwSelectors = new List<int>();\n            var removed = new List<string>();\n            var removedMessages = new List<string>();\n            var emptyKwRemovers = new List<int>();\n\n            foreach (var rule in rules)\n            {\n                if (rule.action == FilterAction.Select)\n                {\n                    selected.Add(rule.keywordName);\n                    if(rule.withEmptyKeyword)\n                        emptyKwSelectors.Add(selected.Count - 1);\n\n                    selectedMessages.Add(rule.resolutionMessage);\n                }\n                else if (rule.action == FilterAction.Remove)\n                {\n                    removed.Add(rule.keywordName);\n                    if (rule.withEmptyKeyword)\n                        emptyKwRemovers.Add(removed.Count - 1);\n\n                    removedMessages.Add(rule.resolutionMessage);\n                }\n            }\n\n            selectKeywords = selected.ToArray();\n            removeKeywords = removed.ToArray();\n            emptyKeywordSelectingKeywords = emptyKwSelectors.ToArray();\n            emptyKeywordRemovingKeywords = emptyKwRemovers.ToArray();\n            selectReasons = selectedMessages.ToArray();\n            removeReasons = removedMessages.ToArray();\n        }\n\n        readonly internal string[] selectKeywords;  // Keywords that have resolved to be selected in the build by a filter rule\n        readonly internal string[] selectReasons;   // Human readable message on why the keyword was selected\n        readonly internal int[] emptyKeywordSelectingKeywords; // Indices of keywords that will also retain \"empty keyword\" case\n\n        readonly internal string[] removeKeywords;  // Keywords that have resolved to be removed from the build by a filter rule\n        readonly internal string[] removeReasons;   // Human readable message on why the keyword was removed\n        readonly internal int[] emptyKeywordRemovingKeywords; // Indices of keywords that will also remove \"empty keyword\" case\n    }\n\n    // This struct is for passing the constraint state of the currently compiled shader pass from C++ to C#.\n    // It is used for comparing against the filter attribute constraints and this way\n    // we can select only the filter rules that are meeting the constraint requirements.\n    [RequiredByNativeCode (GenerateProxy = true)]\n    internal struct ConstraintState\n    {\n        internal string[] tags;\n        internal GraphicsDeviceType[] graphicsAPIs;\n    }\n\n    // This is the main class for shader keyword filtering C++/C# interop\n    [RequiredByNativeCode]\n    internal static class ShaderKeywordFilterUtil\n    {\n        internal struct CachedFilterData\n        {\n            public Hash128 dependencyHash;\n            public SettingsNode settingsNode;\n        };\n\n        // In memory cache for filter data per renderpipeline asset.\n        // This is to avoid redundant attribute search for each shader/pass/stage.\n        internal static Dictionary<string, CachedFilterData> PerAssetFilterDataCache = new Dictionary<string, CachedFilterData>();\n\n        internal static SettingsNode GetFilterDataCached(string nodeName, UnityEngine.Object containerObject)\n        {\n            string assetPath = AssetDatabase.GetAssetPath(containerObject);\n            Hash128 dependencyHash = AssetDatabase.GetAssetDependencyHash(assetPath);\n\n            CachedFilterData cachedData;\n            if (PerAssetFilterDataCache.TryGetValue(assetPath, out cachedData))\n            {\n                // Cached data is valid only if dependency hash hasn't changed\n                if (cachedData.dependencyHash == dependencyHash)\n                    return cachedData.settingsNode;\n            }\n\n            // No valid data found in the cache so we need to do the full processing\n            // and then enter the result into the cache.\n            var visited = new HashSet<object>();\n            cachedData.dependencyHash = dependencyHash;\n            cachedData.settingsNode = SettingsNode.GatherFilterData(nodeName, containerObject, visited);\n\n            PerAssetFilterDataCache[assetPath] = cachedData;\n\n            return cachedData.settingsNode;\n        }\n\n        // For the current build target with given constraint state, gets the list of active filter rule sets.\n        [RequiredByNativeCode]\n        internal static SettingsVariant[] GetKeywordFilterVariants(string buildTargetGroupName, ConstraintState constraintState)\n        {\n            var rpAssets = new List<RenderPipelineAsset>();\n            QualitySettings.GetAllRenderPipelineAssetsForPlatform(buildTargetGroupName, ref rpAssets);\n\n            // Gather the settings/attribute tree from the renderpipe assets\n            SettingsNode root = new SettingsNode(\"root\");\n            foreach(var rpAsset in rpAssets)\n            {\n                if (rpAsset == null)\n                    continue;\n\n                var node = GetFilterDataCached(rpAsset.name, rpAsset);\n                if (node != null)\n                    root.Children.Add(node);\n            }\n\n            // Extract the filter rules for each leaf node in the settings tree and return that in an array form.\n            var variants = new List<SettingsVariant>();\n            root.GetVariantArray(constraintState, variants);\n\n            // We need to return at least a blank settings variant, even if there were no rules\n            if (variants.Count == 0)\n            {\n                variants.Add(new SettingsVariant(new List<FilterRule>()));\n            }\n\n            return variants.ToArray();\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SpeedTreeMaterialFixer.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace UnityEditor\n{\n    internal static class SpeedTreeMaterialFixer\n    {\n        private class Styles\n        {\n            public readonly string Message = \"There are materials referenced by this Game Object that use the wrong version of SpeedTree shader. Do you want to fix it?\";\n            public readonly GUIContent FixSpeedTreeShaders = EditorGUIUtility.TrTextContent(\"Fix SpeedTree Shaders\");\n        }\n\n        private static Styles s_Styles = null;\n\n        private static IEnumerable<MeshRenderer> EnumerateMeshRenderers(GameObject gameObject)\n        {\n            var lodGroup = gameObject.GetComponent<LODGroup>();\n            if (lodGroup != null)\n            {\n                foreach (var lod in lodGroup.GetLODs())\n                {\n                    foreach (var renderer in lod.renderers)\n                    {\n                        if (renderer is MeshRenderer meshRenderer)\n                            yield return meshRenderer;\n                    }\n                }\n            }\n            else\n            {\n                var meshRenderer = gameObject.GetComponent<MeshRenderer>();\n                if (meshRenderer != null)\n                    yield return meshRenderer;\n            }\n        }\n\n        public static void DoFixerUI(GameObject gameObject)\n        {\n            if (s_Styles == null)\n                s_Styles = new Styles();\n\n            var defaultSpeedTree8Shader = GraphicsSettings.GetDefaultShader(DefaultShaderType.SpeedTree8);\n            if (defaultSpeedTree8Shader == null)\n                defaultSpeedTree8Shader = Shader.Find(\"Nature/SpeedTree8\");\n\n            var defaultSpeedTree7Shader = GraphicsSettings.GetDefaultShader(DefaultShaderType.SpeedTree7);\n            if (defaultSpeedTree7Shader == null)\n                defaultSpeedTree7Shader = Shader.Find(\"Nature/SpeedTree\");\n\n            if (defaultSpeedTree8Shader == null || defaultSpeedTree7Shader == null)\n                return;\n\n            HashSet<Material> materialsUsedForBothVersion = null, speedTreeV7MaterialsToFix = null, speedTreeV8MaterialsToFix = null;\n\n            foreach (var meshRenderer in EnumerateMeshRenderers(gameObject))\n            {\n                var meshFilter = meshRenderer.GetComponent<MeshFilter>();\n                if (meshFilter == null)\n                    continue;\n\n                var mesh = meshFilter.sharedMesh;\n                if (mesh == null || !EditorUtility.IsPersistent(mesh))\n                    continue;\n\n                var assetPath = AssetDatabase.GetAssetPath(mesh);\n                var speedTreeImporter = AssetImporter.GetAtPath(assetPath) as SpeedTreeImporter;\n                if (speedTreeImporter == null)\n                    continue;\n\n                if (materialsUsedForBothVersion == null)\n                {\n                    materialsUsedForBothVersion = new HashSet<Material>();\n                    speedTreeV7MaterialsToFix = new HashSet<Material>();\n                    speedTreeV8MaterialsToFix = new HashSet<Material>();\n                }\n\n                bool meshIsV8 = speedTreeImporter.isV8;\n                foreach (var material in meshRenderer.sharedMaterials)\n                {\n                    if (material == null)\n                        continue;\n\n                    // If the material is used for both v7 & v8 mesh: ignore.\n                    if (materialsUsedForBothVersion.Contains(material))\n                        continue;\n\n                    // We only fix materials with wrong speedtree shader assigned. We don't know if it's \"wrong\" if user uses their custom shaders.\n                    var wrongShader = meshIsV8 ? defaultSpeedTree7Shader : defaultSpeedTree8Shader;\n                    if (material.shader != wrongShader)\n                        continue;\n\n                    var targetMaterialSet = meshIsV8 ? speedTreeV8MaterialsToFix : speedTreeV7MaterialsToFix;\n                    var otherMaterialSet = meshIsV8 ? speedTreeV7MaterialsToFix : speedTreeV8MaterialsToFix;\n\n                    if (otherMaterialSet.Contains(material))\n                    {\n                        // rare case that the same material is used both for v7 & v8 material:\n                        materialsUsedForBothVersion.Add(material);\n                        otherMaterialSet.Remove(material);\n                    }\n                    else\n                    {\n                        targetMaterialSet.Add(material);\n                    }\n                }\n            }\n\n            // No speedtree meshes.\n            if (materialsUsedForBothVersion == null)\n                return;\n\n            if (speedTreeV7MaterialsToFix.Count > 0 || speedTreeV8MaterialsToFix.Count > 0)\n            {\n                EditorGUILayout.Space();\n                EditorGUILayout.HelpBox(s_Styles.Message, MessageType.Error);\n                GUILayout.BeginHorizontal();\n                GUILayout.FlexibleSpace();\n                if (GUILayout.Button(s_Styles.FixSpeedTreeShaders, GUILayout.ExpandWidth(false)))\n                {\n                    Undo.RecordObjects(speedTreeV7MaterialsToFix.Concat(speedTreeV8MaterialsToFix).ToArray(), \"Fix SpeedTree Shaders\");\n                    foreach (var material in speedTreeV7MaterialsToFix)\n                        material.shader = defaultSpeedTree7Shader;\n                    foreach (var material in speedTreeV8MaterialsToFix)\n                        material.shader = defaultSpeedTree8Shader;\n                }\n                GUILayout.EndHorizontal();\n            }\n\n            if (materialsUsedForBothVersion.Count != 0)\n            {\n                EditorGUILayout.Space();\n                EditorGUILayout.HelpBox(\"Some of the materials are used for both SpeedTree 7 and SpeedTree 8 assets. Unity won't be able to fix that. Please create separate materials.\", MessageType.Error);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SplashScreenLogo.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing UnityEngine;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    public partial class PlayerSettings\n    {\n        [NativeHeader(\"Runtime/Misc/PlayerSettingsSplashScreen.h\")]\n        public partial struct SplashScreenLogo\n        {\n            private const float k_MinLogoTime = 2.0f;\n            private static Sprite s_UnityLogo;\n            [NativeName(\"logo\")]\n            private Sprite m_Logo;\n            [NativeName(\"duration\")]\n            private float m_Duration;\n\n            static SplashScreenLogo()\n            {\n                s_UnityLogo = AssetDatabase.GetBuiltinExtraResource<Sprite>(\"SplashScreen/UnitySplash-Light.png\");\n            }\n\n            public Sprite logo\n            {\n                get { return m_Logo; }\n                set { m_Logo = value; }\n            }\n\n            public static Sprite unityLogo\n            {\n                get { return s_UnityLogo; }\n            }\n\n            public float duration\n            {\n                get { return Mathf.Max(m_Duration, k_MinLogoTime); }\n                set { m_Duration = Mathf.Max(value, k_MinLogoTime); }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/SpritePacker.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEditor;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Sprites\n{\n    [StructLayout(LayoutKind.Sequential)]\n    public struct AtlasSettings\n    {\n        public TextureFormat format;\n        public ColorSpace colorSpace;\n        public int compressionQuality;\n        public FilterMode filterMode;\n        public int maxWidth;\n        public int maxHeight;\n        public uint paddingPower;\n        public int anisoLevel;\n        public bool generateMipMaps;\n        public bool enableRotation;\n        public bool allowsAlphaSplitting;\n    }\n\n    [NativeHeader(\"Editor/Src/SpritePacker/SpritePacker.h\")]\n    public sealed class PackerJob\n    {\n        internal PackerJob()\n        {\n        }\n\n        [FreeFunction(\"SpritePacker::ActiveJob_AddAtlas\", ThrowsException = true)]\n        private static extern void Internal_AddAtlas(string atlasName, AtlasSettings settings);\n        [FreeFunction(\"SpritePacker::ActiveJob_AssignToAtlas\", ThrowsException = true)]\n        private static extern void Internal_AssignToAtlas(string atlasName, Sprite sprite, SpritePackingMode packingMode, SpritePackingRotation packingRotation);\n\n        public void AddAtlas(string atlasName, AtlasSettings settings)\n        {\n            Internal_AddAtlas(atlasName, settings);\n        }\n\n        public void AssignToAtlas(string atlasName, Sprite sprite, SpritePackingMode packingMode, SpritePackingRotation packingRotation)\n        {\n            Internal_AssignToAtlas(atlasName, sprite, packingMode, packingRotation);\n        }\n    }\n\n    [NativeHeader(\"Editor/Src/SpritePacker/SpritePacker.h\")]\n    public sealed partial class Packer\n    {\n        public extern static string[] atlasNames\n        {\n            [FreeFunction(\"SpritePacker::GetAvailableAtlases\")]\n            get;\n        }\n\n        [FreeFunction(\"SpritePacker::GetAtlasNameForSprite\")]\n        private static extern string Internal_GetAtlasNameForSprite(Sprite sprite);\n        [FreeFunction(\"SpritePacker::GetAtlasTextureSprite\")]\n        private static extern Texture2D Internal_GetAtlasTextureSprite(Sprite sprite);\n\n        [FreeFunction(\"SpritePacker::GetTexturesForAtlas\")]\n        public static extern Texture2D[] GetTexturesForAtlas(string atlasName);\n\n        [FreeFunction(\"SpritePacker::GetAlphaTexturesForAtlas\")]\n        public static extern Texture2D[] GetAlphaTexturesForAtlas(string atlasName);\n\n        public static void GetAtlasDataForSprite(Sprite sprite, out string atlasName, out Texture2D atlasTexture)\n        {\n            atlasName = Internal_GetAtlasNameForSprite(sprite);\n            atlasTexture = Internal_GetAtlasTextureSprite(sprite);\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Sprites/SpriteUtility.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.IO;\nusing System.Linq;\nusing UnityEditorInternal;\nusing UnityEngine;\nusing UnityEngine.Experimental.Rendering;\nusing System.Collections.Generic;\nusing UnityEngine.SceneManagement;\nusing UnityEngine.U2D.Interface;\nusing Object = UnityEngine.Object;\nusing UnityTexture2D = UnityEngine.Texture2D;\nusing UnityEditor.SceneManagement;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor\n{\n    internal static class SpriteUtility\n    {\n        static class SpriteUtilityStrings\n        {\n            public static readonly GUIContent saveAnimDialogMessage = EditorGUIUtility.TrTextContent(\"Create a new animation for the game object '{0}':\");\n            public static readonly GUIContent saveAnimDialogTitle = EditorGUIUtility.TrTextContent(\"Create New Animation\");\n            public static readonly GUIContent saveAnimDialogName = EditorGUIUtility.TrTextContent(\"New Animation\");\n            public static readonly GUIContent unableToFindSpriteRendererWarning = EditorGUIUtility.TrTextContent(\"There should be a SpriteRenderer in dragged object\");\n            public static readonly GUIContent unableToAddSpriteRendererWarning = EditorGUIUtility.TrTextContent(\"Unable to add SpriteRenderer into Gameobject.\");\n            public static readonly GUIContent failedToCreateAnimationError = EditorGUIUtility.TrTextContent(\"Failed to create animation for dragged object\");\n        }\n\n        private static Material s_PreviewSpriteDefaultMaterial;\n\n        internal static Material previewSpriteDefaultMaterial\n        {\n            get\n            {\n                if (s_PreviewSpriteDefaultMaterial == null)\n                {\n                    Shader shader = Shader.Find(\"Sprites/Default\");\n                    s_PreviewSpriteDefaultMaterial = new Material(shader);\n                }\n                return s_PreviewSpriteDefaultMaterial;\n            }\n        }\n\n        static List<Object> s_SceneDragObjects;\n        static DragType s_DragType;\n        enum DragType { NotInitialized, SpriteAnimation, CreateMultiple }\n\n        public delegate string ShowFileDialogDelegate(string title, string defaultName, string extension, string message, string defaultPath);\n        public static void OnSceneDrag(SceneView sceneView)\n        {\n            HandleSpriteSceneDrag(sceneView, new UnityEngine.U2D.Interface.Event(), DragAndDrop.objectReferences, DragAndDrop.paths, EditorUtility.SaveFilePanelInProject);\n        }\n\n        public static void HandleSpriteSceneDrag(SceneView sceneView, IEvent evt, Object[] objectReferences, string[] paths, ShowFileDialogDelegate saveFileDialog)\n        {\n            if (evt.type != EventType.DragUpdated && evt.type != EventType.DragPerform && evt.type != EventType.DragExited)\n                return;\n\n            // Return if any of the dragged objects are null, e.g. a MonoBehaviour without a managed instance\n            if (objectReferences.Any(obj => obj == null))\n                return;\n\n            // Regardless of EditorBehaviorMode or SceneView mode we don't handle if texture is dragged over a GO with renderer\n            if (objectReferences.Length == 1 && objectReferences[0] as UnityTexture2D != null)\n            {\n                GameObject go = HandleUtility.PickGameObject(evt.mousePosition, true);\n                if (go != null)\n                {\n                    var renderer = go.GetComponent<Renderer>();\n                    if (renderer != null && !(renderer is SpriteRenderer))\n                    {\n                        // There is an object where the cursor is\n                        // and we are dragging a texture. Most likely user wants to\n                        // assign texture to the GO\n                        // Case 730444: Proceed only if the go has a renderer\n                        CleanUp(true);\n                        return;\n                    }\n                }\n            }\n\n            switch (evt.type)\n            {\n                case (EventType.DragUpdated):\n                    DragType newDragType = evt.alt ? DragType.CreateMultiple : DragType.SpriteAnimation;\n\n                    if (s_DragType != newDragType || s_SceneDragObjects == null) // Either this is first time we are here OR evt.alt changed during drag\n                    {\n                        if (!ExistingAssets(objectReferences) && PathsAreValidTextures(paths)) // External drag with images that are not in the project\n                        {\n                            DragAndDrop.visualMode = DragAndDropVisualMode.Copy;\n                            s_SceneDragObjects = new List<Object>();\n                            s_DragType = newDragType;\n                        }\n                        else // Internal drag with assets from project\n                        {\n                            List<Sprite> assets = GetSpriteFromPathsOrObjects(objectReferences, paths, evt.type);\n\n                            if (assets.Count == 0)\n                                return;\n\n                            if (s_DragType != DragType.NotInitialized) // evt.alt changed during drag, so we need to cleanup and start over\n                                CleanUp(true);\n\n                            s_DragType = newDragType;\n                            CreateSceneDragObjects(assets, sceneView);\n                            IgnoreForRaycasts(s_SceneDragObjects);\n                        }\n                    }\n\n                    PositionSceneDragObjects(s_SceneDragObjects, sceneView, evt.mousePosition);\n\n                    DragAndDrop.visualMode = DragAndDropVisualMode.Copy;\n                    evt.Use();\n                    break;\n                case (EventType.DragPerform):\n                    List<Sprite> sprites = GetSpriteFromPathsOrObjects(objectReferences, paths, evt.type);\n\n                    if (sprites.Count > 0 && s_SceneDragObjects != null)\n                    {\n                        // Store current undoIndex to undo all operations done if any part of sprite creation fails\n                        int undoIndex = Undo.GetCurrentGroup();\n\n                        // For external drags, we have delayed all creation to DragPerform because only now we have the imported sprite assets\n                        if (s_SceneDragObjects.Count == 0)\n                        {\n                            CreateSceneDragObjects(sprites, sceneView);\n                            PositionSceneDragObjects(s_SceneDragObjects, sceneView, evt.mousePosition);\n                        }\n\n                        foreach (GameObject dragGO in s_SceneDragObjects)\n                        {\n                            dragGO.hideFlags = HideFlags.None;\n\n                            // When in e.g Prefab Mode ensure to reparent dragged objects under the prefab root\n                            Transform defaultObjectTransform = SceneView.GetDefaultParentObjectIfSet();\n                            if (defaultObjectTransform != null)\n                                dragGO.transform.SetParent(defaultObjectTransform, true);\n                            else if (sceneView.customParentForDraggedObjects != null)\n                                dragGO.transform.SetParent(sceneView.customParentForDraggedObjects, true);\n\n                            Undo.RegisterCreatedObjectUndo(dragGO, \"Create Sprite\");\n                            EditorUtility.SetDirty(dragGO);\n                        }\n\n                        bool createGameObject = true;\n                        if (s_DragType == DragType.SpriteAnimation && sprites.Count > 1)\n                        {\n                            createGameObject = AddAnimationToGO((GameObject)s_SceneDragObjects[0], sprites.ToArray(), saveFileDialog);\n                        }\n\n                        if (createGameObject)\n                        {\n                            Selection.objects = s_SceneDragObjects.ToArray();\n                        }\n                        else\n                        {\n                            // Revert all Create Sprite actions if animation failed to be created or was cancelled\n                            Undo.RevertAllDownToGroup(undoIndex);\n                        }\n                        CleanUp(!createGameObject);\n                        evt.Use();\n                    }\n                    break;\n                case EventType.DragExited:\n                    if (s_SceneDragObjects != null)\n                    {\n                        CleanUp(true);\n                        evt.Use();\n                    }\n                    break;\n            }\n        }\n\n        private static void IgnoreForRaycasts(List<Object> objects)\n        {\n            List<Transform> ignoredTransforms = new List<Transform>();\n\n            foreach (GameObject gameObject in objects)\n                ignoredTransforms.AddRange(gameObject.GetComponentsInChildren<Transform>());\n\n            HandleUtility.ignoreRaySnapObjects = ignoredTransforms.ToArray();\n        }\n\n        private static void PositionSceneDragObjects(List<Object> objects, SceneView sceneView, Vector2 mousePosition)\n        {\n            Vector3 position = Vector3.zero;\n            position = HandleUtility.GUIPointToWorldRay(mousePosition).GetPoint(10);\n            if (sceneView.in2DMode)\n            {\n                position.z = 0f;\n            }\n            else\n            {\n                DragAndDrop.visualMode = DragAndDropVisualMode.Copy;\n                object hit = HandleUtility.RaySnap(HandleUtility.GUIPointToWorldRay(mousePosition));\n                if (hit != null)\n                {\n                    RaycastHit rh = (RaycastHit)hit;\n                    position = rh.point;\n                }\n            }\n\n            if (Selection.activeGameObject != null)\n            {\n                Grid grid = Selection.activeGameObject.GetComponentInParent<Grid>();\n                if (grid != null)\n                {\n                    Vector3Int cell = grid.WorldToCell(position);\n                    position = grid.GetCellCenterWorld(cell);\n                }\n            }\n\n            foreach (GameObject gameObject in objects)\n            {\n                gameObject.transform.position = position;\n            }\n        }\n\n        private static void CreateSceneDragObjects(List<Sprite> sprites, SceneView sceneView)\n        {\n            if (s_SceneDragObjects == null)\n                s_SceneDragObjects = new List<Object>();\n\n            if (s_DragType == DragType.CreateMultiple)\n            {\n                foreach (Sprite sprite in sprites)\n                    s_SceneDragObjects.Add(CreateDragGO(sprite, Vector3.zero, sceneView));\n            }\n            else\n            {\n                s_SceneDragObjects.Add(CreateDragGO(sprites[0], Vector3.zero, sceneView));\n            }\n        }\n\n        private static void CleanUp(bool deleteTempSceneObject)\n        {\n            if (s_SceneDragObjects != null)\n            {\n                if (deleteTempSceneObject)\n                {\n                    foreach (GameObject gameObject in s_SceneDragObjects)\n                        Object.DestroyImmediate(gameObject, false);\n                }\n\n                s_SceneDragObjects.Clear();\n                s_SceneDragObjects = null;\n            }\n            HandleUtility.ignoreRaySnapObjects = null;\n            s_DragType = DragType.NotInitialized;\n        }\n\n        [RequiredByNativeCode]\n        static bool CreateAnimation(GameObject gameObject, Object[] frames, ShowFileDialogDelegate saveFileDialog)\n        {\n            saveFileDialog = saveFileDialog ?? EditorUtility.SaveFilePanelInProject;\n\n            // Use same name compare as when we sort in the backend: See AssetDatabase.cpp: SortChildren\n            System.Array.Sort(frames, (a, b) => EditorUtility.NaturalCompare(a.name, b.name));\n\n            Animator animator = AnimationWindowUtility.EnsureActiveAnimationPlayer(gameObject)\n                ? AnimationWindowUtility.GetClosestAnimatorInParents(gameObject.transform)\n                : null;\n\n            bool createSuccess = animator != null;\n\n            if (animator != null)\n            {\n                // Go forward with presenting user a save clip dialog\n                string message = string.Format(SpriteUtilityStrings.saveAnimDialogMessage.text, gameObject.name);\n                string newClipDirectory = ProjectWindowUtil.GetActiveFolderPath();\n                string newClipPath = saveFileDialog(SpriteUtilityStrings.saveAnimDialogTitle.text, SpriteUtilityStrings.saveAnimDialogName.text, \"anim\", message, newClipDirectory);\n\n                if (string.IsNullOrEmpty(newClipPath))\n                {\n                    Undo.ClearUndo(animator);\n                    Object.DestroyImmediate(animator);\n                    return false;\n                }\n                else\n                {\n                    AnimationClip newClip = AnimationWindowUtility.CreateNewClipAtPath(newClipPath);\n                    if (newClip != null)\n                    {\n                        AddSpriteAnimationToClip(newClip, frames);\n                        createSuccess = AnimationWindowUtility.AddClipToAnimatorComponent(animator, newClip);\n                    }\n                }\n            }\n\n            if (createSuccess == false)\n                Debug.LogError(SpriteUtilityStrings.failedToCreateAnimationError.text);\n\n            return createSuccess;\n        }\n\n        [RequiredByNativeCode]\n        static void AddSpriteAnimationToClip(AnimationClip newClip, Object[] frames)\n        {\n            // TODO Default framerate be exposed to user?\n            newClip.frameRate = 12;\n\n            // Add keyframes\n            ObjectReferenceKeyframe[] keyframes = new ObjectReferenceKeyframe[frames.Length];\n\n            for (int i = 0; i < keyframes.Length; i++)\n            {\n                keyframes[i] = new ObjectReferenceKeyframe();\n                keyframes[i].value = RemapObjectToSprite(frames[i]);\n                keyframes[i].time = i / newClip.frameRate;\n            }\n\n            // Create binding\n            EditorCurveBinding curveBinding = EditorCurveBinding.PPtrCurve(\"\", typeof(SpriteRenderer), \"m_Sprite\");\n\n            // Save curve to clip\n            AnimationUtility.SetObjectReferenceCurve(newClip, (EditorCurveBinding)curveBinding, keyframes);\n        }\n\n        public static List<Sprite> GetSpriteFromPathsOrObjects(Object[] objects, string[] paths, EventType currentEventType)\n        {\n            List<Sprite> result = new List<Sprite>();\n\n            foreach (Object obj in objects)\n            {\n                if (AssetDatabase.Contains(obj))\n                {\n                    if (obj is Sprite)\n                        result.Add(obj as Sprite);\n                    else if (obj is UnityTexture2D)\n                        result.AddRange(TextureToSprites(obj as UnityTexture2D));\n                }\n            }\n\n            // Fix case 742896. If any of the drag objects is already in the AssetDatabase, means we don't have to handle external drags.\n            // Fix case 857231. We only handle external drag if default behaviour mode is 2D\n            if (!ExistingAssets(objects) && currentEventType == EventType.DragPerform && EditorSettings.defaultBehaviorMode == EditorBehaviorMode.Mode2D)\n            {\n                HandleExternalDrag(paths, true, ref result);\n            }\n            return result;\n        }\n\n        public static bool ExistingAssets(Object[] objects)\n        {\n            foreach (Object obj in objects)\n            {\n                if (AssetDatabase.Contains(obj))\n                    return true;\n            }\n            return false;\n        }\n\n        private static void HandleExternalDrag(string[] paths, bool perform, ref List<Sprite> result)\n        {\n            foreach (var path in paths)\n            {\n                if (!ValidPathForTextureAsset(path))\n                    continue;\n\n                DragAndDrop.visualMode = DragAndDropVisualMode.Copy;\n\n                if (!perform)\n                    continue;\n\n                var newPath = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(\"Assets\", FileUtil.GetLastPathNameComponent(path)));\n                if (newPath.Length <= 0)\n                    continue;\n\n                FileUtil.CopyFileOrDirectory(path, newPath);\n                ForcedImportFor(newPath);\n\n                Sprite defaultSprite = GenerateDefaultSprite(AssetDatabase.LoadMainAssetAtPath(newPath) as UnityTexture2D);\n                if (defaultSprite != null)\n                    result.Add(defaultSprite);\n            }\n        }\n\n        private static bool PathsAreValidTextures(string[] paths)\n        {\n            if (paths == null || paths.Length == 0)\n                return false;\n\n            foreach (var path in paths)\n            {\n                if (!ValidPathForTextureAsset(path))\n                    return false;\n            }\n\n            return true;\n        }\n\n        private static void ForcedImportFor(string newPath)\n        {\n            try\n            {\n                AssetDatabase.StartAssetEditing();\n                AssetDatabase.ImportAsset(newPath);\n            }\n            finally\n            {\n                AssetDatabase.StopAssetEditing();\n            }\n        }\n\n        private static Sprite GenerateDefaultSprite(UnityTexture2D texture)\n        {\n            string assetPath = AssetDatabase.GetAssetPath(texture);\n            TextureImporter textureImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;\n            if (textureImporter == null) // could be DDS importer or other non-TextureImporter type\n                return null;\n\n            if (textureImporter.textureType != TextureImporterType.Sprite)\n                return null;\n\n            if (textureImporter.spriteImportMode == SpriteImportMode.None)\n            {\n                textureImporter.spriteImportMode = SpriteImportMode.Single;\n                AssetDatabase.WriteImportSettingsIfDirty(assetPath);\n                ForcedImportFor(assetPath);\n            }\n\n            Object firstSprite = null;\n            firstSprite = AssetDatabase.LoadAllAssetsAtPath(assetPath).FirstOrDefault(t => t is Sprite);\n\n            return firstSprite as Sprite;\n        }\n\n        public static GameObject CreateDragGO(Sprite frame, Vector3 position, SceneView sceneView)\n        {\n            string name = string.IsNullOrEmpty(frame.name) ? \"Sprite\" : frame.name;\n            name = GameObjectUtility.GetUniqueNameForSibling(null, name);\n\n            // ObjectFactory registers an Undo for the GameObject created, which we do not\n            // want for the drag preview. We register an Undo only when the user does a\n            // DragPerform to confirm the creation of the Sprite GameObject.\n            // The GameObject is cloned and returned while the original is destroyed to\n            // remove the Undo operation.\n            GameObject go = ObjectFactory.CreateGameObject(name, typeof(SpriteRenderer));\n            GameObject cloneGO = GameObject.Instantiate(go);\n            Object.DestroyImmediate(go);\n            go = cloneGO;\n            go.name = name;\n\n            SpriteRenderer spriteRenderer = go.GetComponent<SpriteRenderer>();\n            spriteRenderer.sprite = frame;\n            go.transform.position = position;\n            go.hideFlags = HideFlags.HideInHierarchy;\n\n            Scene destinationScene = GetDestinationSceneForNewGameObjectsForSceneView(sceneView);\n            // According to how GameOjectInspector.cs moves the object into scene\n            if (EditorApplication.isPlaying && !EditorSceneManager.IsPreviewScene(destinationScene))\n            {\n                SceneManager.MoveGameObjectToScene(go, destinationScene);\n            }\n\n            return go;\n        }\n\n        static Scene GetDestinationSceneForNewGameObjectsForSceneView(SceneView sceneView)\n        {\n            if (sceneView.customParentForNewGameObjects != null)\n                return sceneView.customParentForNewGameObjects.gameObject.scene;\n\n            if (sceneView.customScene.IsValid())\n                return sceneView.customScene;\n\n            return SceneManager.GetActiveScene();\n        }\n\n        public static bool AddAnimationToGO(GameObject go, Sprite[] frames, ShowFileDialogDelegate saveFileDialog)\n        {\n            SpriteRenderer spriteRenderer = go.GetComponent<SpriteRenderer>();\n            if (spriteRenderer == null)\n            {\n                Debug.LogWarning(SpriteUtilityStrings.unableToFindSpriteRendererWarning.text);\n                spriteRenderer = (SpriteRenderer)ObjectFactory.AddComponent(go, typeof(SpriteRenderer));\n                if (spriteRenderer == null)\n                {\n                    Debug.LogWarning(SpriteUtilityStrings.unableToAddSpriteRendererWarning.text);\n                    return false;\n                }\n            }\n            spriteRenderer.sprite = frames[0];\n            return CreateAnimation(go, frames, saveFileDialog);\n        }\n\n        public static GameObject DropSpriteToSceneToCreateGO(Sprite sprite, Vector3 position)\n        {\n            GameObject go = new GameObject(string.IsNullOrEmpty(sprite.name) ? \"Sprite\" : sprite.name);\n            SpriteRenderer spriteRenderer = (SpriteRenderer)ObjectFactory.AddComponent(go, typeof(SpriteRenderer));\n            spriteRenderer.sprite = sprite;\n            go.transform.position = position;\n            Selection.activeObject = go;\n\n            return go;\n        }\n\n        public static Sprite RemapObjectToSprite(Object obj)\n        {\n            if (obj is Sprite)\n                return (Sprite)obj;\n\n            if (obj is UnityTexture2D)\n            {\n                Object[] assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(obj));\n                for (int i = 0; i < assets.Length; i++)\n                {\n                    if (assets[i].GetType() == typeof(Sprite))\n                        return assets[i] as Sprite;\n                }\n            }\n            return null;\n        }\n\n        public static List<Sprite> TextureToSprites(UnityTexture2D tex)\n        {\n            Object[] assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(tex));\n            List<Sprite> result = new List<Sprite>();\n\n            for (int i = 0; i < assets.Length; i++)\n            {\n                if (assets[i].GetType() == typeof(Sprite))\n                    result.Add(assets[i] as Sprite);\n            }\n\n            if (result.Count > 0)\n                return result;\n\n            Sprite defaultSprite = GenerateDefaultSprite(tex);\n            if (defaultSprite != null)\n                result.Add(defaultSprite);\n\n            return result;\n        }\n\n        public static Sprite TextureToSprite(UnityTexture2D tex)\n        {\n            List<Sprite> sprites = TextureToSprites(tex);\n            if (sprites.Count > 0)\n                return sprites[0];\n            return null;\n        }\n\n        private static bool ValidPathForTextureAsset(string path)\n        {\n            string ext = FileUtil.GetPathExtension(path).ToLower();\n            return\n                ext == \"jpg\" ||\n                ext == \"jpeg\" ||\n                ext == \"tif\" ||\n                ext == \"tiff\" ||\n                ext == \"tga\" ||\n                ext == \"gif\" ||\n                ext == \"png\" ||\n                ext == \"psd\" ||\n                ext == \"bmp\" ||\n                ext == \"iff\" ||\n                ext == \"pict\" ||\n                ext == \"pic\" ||\n                ext == \"pct\" ||\n                ext == \"exr\" ||\n                ext == \"hdr\";\n        }\n\n        public static UnityTexture2D RenderStaticPreview(Sprite sprite, Color color, int width, int height)\n        {\n            return RenderStaticPreview(sprite, color, width, height, Matrix4x4.identity);\n        }\n\n        public static UnityTexture2D RenderStaticPreview(Sprite sprite, Color color, int width, int height, Matrix4x4 transform)\n        {\n            return SpriteInspector.BuildPreviewTexture(sprite, previewSpriteDefaultMaterial, false, width, height, color, transform);\n        }\n\n        public static UnityTexture2D CreateTemporaryDuplicate(UnityTexture2D original, int width, int height)\n        {\n            if (!ShaderUtil.hardwareSupportsRectRenderTexture || !original)\n                return null;\n\n            RenderTexture save = RenderTexture.active;\n            var savedViewport = ShaderUtil.rawViewportRect;\n\n            RenderTexture tmp = RenderTexture.GetTemporary(\n                width,\n                height,\n                0,\n                SystemInfo.GetGraphicsFormat(DefaultFormat.LDR));\n\n            Graphics.Blit(original, tmp);\n\n            RenderTexture.active = tmp;\n\n            // If the user system doesn't support this texture size, force it to use mipmap\n            bool forceUseMipMap = width >= SystemInfo.maxTextureSize || height >= SystemInfo.maxTextureSize;\n\n            UnityTexture2D copy = new UnityTexture2D(width, height, TextureFormat.RGBA32, original.mipmapCount > 1 || forceUseMipMap);\n            copy.ReadPixels(new Rect(0, 0, width, height), 0, 0);\n            copy.Apply();\n            RenderTexture.ReleaseTemporary(tmp);\n\n            EditorGUIUtility.SetRenderTextureNoViewport(save);\n            ShaderUtil.rawViewportRect = savedViewport;\n\n            copy.alphaIsTransparency = original.alphaIsTransparency;\n            return copy;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Sprites/SpriteUtilityWindow.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEditorInternal;\nusing UnityEngine.Bindings;\n\nnamespace UnityEditor\n{\n    [UIFramework(UIFrameworkUsage.IMGUI)]\n    [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n    internal class SpriteUtilityWindow : EditorWindow\n    {\n        protected class Styles\n        {\n            public readonly GUIStyle dragdot = \"U2D.dragDot\";\n            public readonly GUIStyle dragdotDimmed = \"U2D.dragDotDimmed\";\n            public readonly GUIStyle dragdotactive = \"U2D.dragDotActive\";\n            public readonly GUIStyle createRect = \"U2D.createRect\";\n            public readonly GUIStyle preToolbar = \"preToolbar\";\n            public readonly GUIStyle preButton = \"preButton\";\n            public readonly GUIStyle preLabel = \"preLabel\";\n            public readonly GUIStyle preSlider = \"preSlider\";\n            public readonly GUIStyle preSliderThumb = \"preSliderThumb\";\n            public readonly GUIStyle preBackground = \"preBackground\";\n            public readonly GUIStyle pivotdotactive = \"U2D.pivotDotActive\";\n            public readonly GUIStyle pivotdot = \"U2D.pivotDot\";\n            public static readonly GUIContent openSpriteEditor = EditorGUIUtility.TrTextContent(\"Open Sprite Editor\");\n            public static readonly GUIContent install2DPackage = EditorGUIUtility.TrTextContent(\"Install 2D Sprite Package\");\n            public static readonly GUIContent failedToInstall2DPackageTitle = EditorGUIUtility.TrTextContent(\"Installation Failed\");\n            public static readonly GUIContent failedToInstall2DPackageContent = EditorGUIUtility.TrTextContent(\"Failed to install package com.unity.2d.sprite.\\nErrorCode: {0}\\nMessage: {1}\");\n            public static readonly GUIContent install2DPackageReason = EditorGUIUtility.TrTextContent(\"The Sprite Editor window is not available because the 2D Sprite package is not installed. Click on the 'Install 2D Sprite Package' button to install the package to edit Sprites in Sprite Editor window.\");\n            public static readonly GUIContent okText = EditorGUIUtility.TrTextContent(\"OK\");\n            public readonly GUIStyle dragBorderdot = new GUIStyle();\n            public readonly GUIStyle dragBorderDotActive = new GUIStyle();\n\n            public readonly GUIStyle toolbar;\n            public readonly GUIContent alphaIcon;\n            public readonly GUIContent RGBIcon;\n            public readonly GUIStyle notice;\n\n            public readonly GUIContent smallMip;\n            public readonly GUIContent largeMip;\n\n            public Styles()\n            {\n                toolbar = new GUIStyle(EditorStyles.inspectorBig);\n                toolbar.margin.top = 0;\n                toolbar.margin.bottom = 0;\n                alphaIcon = EditorGUIUtility.IconContent(\"PreTextureAlpha\");\n                RGBIcon = EditorGUIUtility.IconContent(\"PreTextureRGB\");\n                preToolbar.border.top = 0;\n                createRect.border = new RectOffset(3, 3, 3, 3);\n\n                notice = new GUIStyle(GUI.skin.label);\n                notice.alignment = TextAnchor.MiddleCenter;\n                notice.normal.textColor = Color.yellow;\n\n                dragBorderdot.fixedHeight = 5f;\n                dragBorderdot.fixedWidth = 5f;\n                dragBorderdot.normal.background = EditorGUIUtility.whiteTexture;\n\n                dragBorderDotActive.fixedHeight = dragBorderdot.fixedHeight;\n                dragBorderDotActive.fixedWidth = dragBorderdot.fixedWidth;\n                dragBorderDotActive.normal.background = EditorGUIUtility.whiteTexture;\n\n                smallMip = EditorGUIUtility.IconContent(\"PreTextureMipMapLow\");\n                largeMip = EditorGUIUtility.IconContent(\"PreTextureMipMapHigh\");\n            }\n        }\n\n        protected void InitStyles()\n        {\n            if (m_Styles == null)\n                m_Styles = new Styles();\n        }\n\n        protected Styles m_Styles;\n\n        protected const float k_BorderMargin = 10f;\n        protected const float k_ScrollbarMargin = 16f;\n        protected const float k_InspectorWindowMargin = 8f;\n        protected const float k_InspectorWidth = 330f;\n        protected const float k_MinZoomPercentage = 0.9f;\n        protected const float k_MaxZoom = 50f;\n        protected const float k_WheelZoomSpeed = 0.03f;\n        protected const float k_MouseZoomSpeed = 0.005f;\n        protected const float k_ToolbarHeight = 17f;\n\n        protected Texture2D m_Texture;\n        protected Texture2D m_TextureAlphaOverride;\n        protected Rect m_TextureViewRect;\n        protected Rect m_TextureRect;\n\n        protected bool m_ShowAlpha = false;\n        protected float m_Zoom = -1f;\n        protected float m_MipLevel = 0;\n        protected Vector2 m_ScrollPosition = new Vector2();\n        static LaunchSpriteEditorWindowAfterDomainReload s_LaunchSpriteEditorWindowAfterDomainReload;\n\n        protected float GetMinZoom()\n        {\n            if (m_Texture == null)\n                return 1.0f;\n            // Case 654327: Add k_MaxZoom size to min check to ensure that min zoom is smaller than max zoom\n            return Mathf.Min(m_TextureViewRect.width / m_Texture.width, m_TextureViewRect.height / m_Texture.height, k_MaxZoom) * k_MinZoomPercentage;\n        }\n\n        protected void HandleZoom()\n        {\n            bool zoomMode = Event.current.alt && Event.current.button == 1;\n            if (zoomMode)\n            {\n                EditorGUIUtility.AddCursorRect(m_TextureViewRect, MouseCursor.Zoom);\n            }\n\n            if (\n                ((Event.current.type == EventType.MouseUp || Event.current.type == EventType.MouseDown) && zoomMode) ||\n                ((Event.current.type == EventType.KeyUp || Event.current.type == EventType.KeyDown) && Event.current.keyCode == KeyCode.LeftAlt)\n            )\n            {\n                Repaint();\n            }\n\n            if (Event.current.type == EventType.ScrollWheel || (Event.current.type == EventType.MouseDrag && Event.current.alt && Event.current.button == 1))\n            {\n                float zoomMultiplier = 1f - Event.current.delta.y * (Event.current.type == EventType.ScrollWheel ? k_WheelZoomSpeed : -k_MouseZoomSpeed);\n\n                // Clamp zoom\n                float wantedZoom = m_Zoom * zoomMultiplier;\n\n                float currentZoom = Mathf.Clamp(wantedZoom, GetMinZoom(), k_MaxZoom);\n\n                if (currentZoom != m_Zoom)\n                {\n                    m_Zoom = currentZoom;\n\n                    // We need to fix zoomMultiplier if we clamped wantedZoom != currentZoom\n                    if (wantedZoom != currentZoom)\n                        zoomMultiplier /= wantedZoom / currentZoom;\n\n                    Vector3 textureHalfSize = new Vector2(m_Texture.width, m_Texture.height) * 0.5f;\n                    Vector3 mousePositionWorld = Handles.inverseMatrix.MultiplyPoint3x4(Event.current.mousePosition + m_ScrollPosition);\n                    Vector3 delta = (mousePositionWorld - textureHalfSize) * (zoomMultiplier - 1f);\n\n                    m_ScrollPosition += (Vector2)Handles.matrix.MultiplyVector(delta);\n\n                    Event.current.Use();\n                }\n            }\n        }\n\n        protected void HandlePanning()\n        {\n            // You can pan by holding ALT and using left button or NOT holding ALT and using right button. ALT + right is reserved for zooming.\n            bool panMode = (!Event.current.alt && Event.current.button > 0 || Event.current.alt && Event.current.button <= 0);\n            if (panMode && GUIUtility.hotControl == 0)\n            {\n                EditorGUIUtility.AddCursorRect(m_TextureViewRect, MouseCursor.Pan);\n\n                if (Event.current.type == EventType.MouseDrag)\n                {\n                    m_ScrollPosition -= Event.current.delta;\n                    Event.current.Use();\n                }\n            }\n\n            //We need to repaint when entering or exiting the pan mode, so the mouse cursor gets refreshed.\n            if (\n                ((Event.current.type == EventType.MouseUp || Event.current.type == EventType.MouseDown) && panMode) ||\n                (Event.current.type == EventType.KeyUp || Event.current.type == EventType.KeyDown)  && Event.current.keyCode == KeyCode.LeftAlt\n            )\n            {\n                Repaint();\n            }\n        }\n\n        // Bounding values for scrollbars. Changes with zoom, because we want min/max scroll to stop at texture edges.\n        protected Rect maxScrollRect\n        {\n            get\n            {\n                float halfWidth = m_Texture.width * .5f * m_Zoom;\n                float halfHeight = m_Texture.height * .5f * m_Zoom;\n                return new Rect(-halfWidth, -halfHeight, m_TextureViewRect.width + halfWidth * 2f, m_TextureViewRect.height + halfHeight * 2f);\n            }\n        }\n\n        // Max rect in texture space that can ever be visible\n        protected Rect maxRect\n        {\n            get\n            {\n                float marginW = m_TextureViewRect.width * .5f / GetMinZoom();\n                float marginH = m_TextureViewRect.height * .5f / GetMinZoom();\n                float left = -marginW;\n                float top = -marginH;\n                float width = m_Texture.width + marginW * 2f;\n                float height = m_Texture.height + marginH * 2f;\n                return new Rect(left, top, width, height);\n            }\n        }\n\n        protected void DrawTexturespaceBackground()\n        {\n            float size = Mathf.Max(maxRect.width, maxRect.height);\n            Vector2 offset = new Vector2(maxRect.xMin, maxRect.yMin);\n\n            float halfSize = size * .5f;\n            float alpha = EditorGUIUtility.isProSkin ? 0.15f : 0.08f;\n            float gridSize = 8f;\n\n            SpriteEditorUtility.BeginLines(new Color(0f, 0f, 0f, alpha));\n            for (float v = 0; v <= size; v += gridSize)\n                SpriteEditorUtility.DrawLine(new Vector2(-halfSize + v, halfSize + v) + offset, new Vector2(halfSize + v, -halfSize + v) + offset);\n            SpriteEditorUtility.EndLines();\n        }\n\n        protected void DrawTexture()\n        {\n            float mipLevel = Mathf.Min(m_MipLevel, TextureUtil.GetMipmapCount(m_Texture) - 1);\n\n            FilterMode oldFilter = m_Texture.filterMode;\n            TextureUtil.SetFilterModeNoDirty(m_Texture, FilterMode.Point);\n\n            if (m_ShowAlpha)\n            {\n                // check if we have a valid alpha texture\n                if (m_TextureAlphaOverride != null)\n                    EditorGUI.DrawTextureTransparent(m_TextureRect, m_TextureAlphaOverride, ScaleMode.StretchToFill, 0, mipLevel);\n                // else use the original texture and display its alpha\n                else\n                    EditorGUI.DrawTextureAlpha(m_TextureRect, m_Texture, ScaleMode.StretchToFill, 0, mipLevel);\n            }\n            else\n                EditorGUI.DrawTextureTransparent(m_TextureRect, m_Texture, ScaleMode.StretchToFill, 0, mipLevel);\n\n            TextureUtil.SetFilterModeNoDirty(m_Texture, oldFilter);\n        }\n\n        protected void DrawScreenspaceBackground()\n        {\n            if (Event.current.type == EventType.Repaint)\n                m_Styles.preBackground.Draw(m_TextureViewRect, false, false, false, false);\n        }\n\n        protected void HandleScrollbars()\n        {\n            Rect horizontalScrollBarPosition = new Rect(m_TextureViewRect.xMin, m_TextureViewRect.yMax, m_TextureViewRect.width, k_ScrollbarMargin);\n            m_ScrollPosition.x = GUI.HorizontalScrollbar(horizontalScrollBarPosition, m_ScrollPosition.x, m_TextureViewRect.width, maxScrollRect.xMin, maxScrollRect.xMax);\n\n            Rect verticalScrollBarPosition = new Rect(m_TextureViewRect.xMax, m_TextureViewRect.yMin, k_ScrollbarMargin, m_TextureViewRect.height);\n            m_ScrollPosition.y = GUI.VerticalScrollbar(verticalScrollBarPosition, m_ScrollPosition.y, m_TextureViewRect.height, maxScrollRect.yMin, maxScrollRect.yMax);\n        }\n\n        protected void SetupHandlesMatrix()\n        {\n            // Offset from top left to center in view space\n            Vector3 handlesPos = new Vector3(m_TextureRect.x, m_TextureRect.yMax, 0f);\n            // We flip Y-scale because Unity texture space is bottom-up\n            Vector3 handlesScale = new Vector3(m_Zoom, -m_Zoom, 1f);\n\n            // Handle matrix is for converting between view and texture space coordinates, without taking account the scroll position.\n            // Scroll position is added separately so we can use it with GUIClip.\n            Handles.matrix = Matrix4x4.TRS(handlesPos, Quaternion.identity, handlesScale);\n        }\n\n        protected Rect DoAlphaZoomToolbarGUI(Rect area)\n        {\n            int mipCount = 1;\n            if (m_Texture != null)\n                mipCount = Mathf.Max(mipCount, TextureUtil.GetMipmapCount(m_Texture));\n\n            Rect drawArea = new Rect(area.width, 0, 0, area.height);\n            using (new EditorGUI.DisabledScope(mipCount == 1))\n            {\n                drawArea.width = m_Styles.largeMip.image.width;\n                drawArea.x -= drawArea.width;\n                GUI.Box(drawArea, m_Styles.largeMip, m_Styles.preLabel);\n\n                drawArea.width = EditorGUI.kSliderMinW;\n                drawArea.x -= drawArea.width;\n                m_MipLevel = Mathf.Round(GUI.HorizontalSlider(drawArea, m_MipLevel, mipCount - 1, 0, m_Styles.preSlider, m_Styles.preSliderThumb));\n\n                drawArea.width = m_Styles.smallMip.image.width;\n                drawArea.x -= drawArea.width;\n                GUI.Box(drawArea, m_Styles.smallMip, m_Styles.preLabel);\n            }\n\n            drawArea.width = EditorGUI.kSliderMinW;\n            drawArea.x -= drawArea.width;\n            m_Zoom = GUI.HorizontalSlider(drawArea, m_Zoom, GetMinZoom(), k_MaxZoom, m_Styles.preSlider, m_Styles.preSliderThumb);\n\n            drawArea.width = EditorGUI.kObjectFieldMiniThumbnailWidth;\n            drawArea.x -= drawArea.width + EditorGUI.kSpacing;\n            m_ShowAlpha = GUI.Toggle(drawArea, m_ShowAlpha, m_ShowAlpha ? m_Styles.alphaIcon : m_Styles.RGBIcon, \"toolbarButton\");\n\n            // Returns the area that is not used\n            return new Rect(area.x, area.y, drawArea.x, area.height);\n        }\n\n        protected void DoTextureGUI()\n        {\n            if (m_Texture == null)\n                return;\n\n            // zoom startup init\n            if (m_Zoom < 0f)\n                m_Zoom = GetMinZoom();\n\n            // Texture rect in view space\n            m_TextureRect = new Rect(\n                m_TextureViewRect.width / 2f - (m_Texture.width * m_Zoom / 2f),\n                m_TextureViewRect.height / 2f - (m_Texture.height * m_Zoom / 2f),\n                (m_Texture.width * m_Zoom),\n                (m_Texture.height * m_Zoom)\n            );\n\n            HandleScrollbars();\n            SetupHandlesMatrix();\n            DrawScreenspaceBackground();\n\n            GUIClip.Push(m_TextureViewRect, -m_ScrollPosition, Vector2.zero, false);\n\n            if (Event.current.type == EventType.Repaint)\n            {\n                DrawTexturespaceBackground();\n                DrawTexture();\n                DrawGizmos();\n            }\n\n            DoTextureGUIExtras();\n\n            GUIClip.Pop();\n\n            // Handle this after DoTextureGUIExtras in case user wants any event that is handled by Zoom or Panning\n            HandleZoom();\n            HandlePanning();\n        }\n\n        protected virtual void DoTextureGUIExtras()\n        {\n        }\n\n        protected virtual void DrawGizmos()\n        {\n        }\n\n        protected void SetNewTexture(Texture2D texture)\n        {\n            if (texture != m_Texture)\n            {\n                m_Texture = texture;\n                m_Zoom = -1;\n                m_TextureAlphaOverride = null;\n            }\n        }\n\n        protected void SetAlphaTextureOverride(Texture2D alphaTexture)\n        {\n            if (alphaTexture != m_TextureAlphaOverride)\n            {\n                m_TextureAlphaOverride = alphaTexture;\n                m_Zoom = -1;\n            }\n        }\n\n        internal override void OnResized()\n        {\n            if (m_Texture != null && Event.current != null)\n                HandleZoom();\n        }\n\n        internal static void DrawToolBarWidget(ref Rect drawRect, ref Rect toolbarRect, Action<Rect> drawAction)\n        {\n            toolbarRect.width -= drawRect.width;\n            if (toolbarRect.width < 0)\n                drawRect.width += toolbarRect.width;\n\n            if (drawRect.width > 0)\n                drawAction(drawRect);\n        }\n\n        internal static bool DoOpenSpriteEditorWindowUI()\n        {\n            var buttonText = showSpriteEditorWindow == null ? Styles.install2DPackage : Styles.openSpriteEditor;\n            GUILayout.BeginVertical();\n            var clicked = GUILayout.Button(buttonText);\n            if (showSpriteEditorWindow == null)\n                EditorGUILayout.HelpBox(Styles.install2DPackageReason.text, MessageType.Info, true);\n            GUILayout.EndVertical();\n            return clicked;\n        }\n\n        [Obsolete(\"Use SpriteUtility.SetShowSpriteEditorWindowWithObject instead\")]\n        internal static void SetShowSpriteEditorWindow(Func<bool> spriteEditorWindow)\n        {\n            if (spriteEditorWindow != null)\n                showSpriteEditorWindow = (x) => spriteEditorWindow();\n        }\n\n        internal static void SetShowSpriteEditorWindowWithObject(Func<UnityEngine.Object, bool> spriteEditorWindow)\n        {\n            if (spriteEditorWindow != null)\n                showSpriteEditorWindow = spriteEditorWindow;\n        }\n\n        internal static void SetApplySpriteEditorWindow(Action action)\n        {\n            if (action != null)\n                applySpriteEditorWindow = action;\n            else\n                applySpriteEditorWindow = () => {};\n        }\n\n        [VisibleToOtherModules(\"UnityEditor.UIBuilderModule\")]\n        internal static bool ShowSpriteEditorWindow(UnityEngine.Object obj = null)\n        {\n            if (showSpriteEditorWindow == null)\n            {\n                var installSuccess = InstallSpritePackage();\n                if (installSuccess)\n                {\n                    s_LaunchSpriteEditorWindowAfterDomainReload = ScriptableObject.CreateInstance<LaunchSpriteEditorWindowAfterDomainReload>();\n                    s_LaunchSpriteEditorWindowAfterDomainReload.selectedObject = obj;\n                }\n                return installSuccess;\n            }\n\n            return showSpriteEditorWindow(obj != null ? obj : Selection.activeObject);\n        }\n\n\n        static Func<UnityEngine.Object, bool> showSpriteEditorWindow = null;\n\n        static bool InstallSpritePackage()\n        {\n            if(s_LaunchSpriteEditorWindowAfterDomainReload != null)\n                DestroyImmediate(s_LaunchSpriteEditorWindowAfterDomainReload);\n\n            var addRequest = PackageManager.Client.Add(\"com.unity.2d.sprite\");\n            while (!addRequest.IsCompleted)\n                System.Threading.Thread.Sleep(10);\n\n            if (addRequest.Status == PackageManager.StatusCode.Failure)\n            {\n                var message = String.Format(Styles.failedToInstall2DPackageContent.text, addRequest.Error.errorCode, addRequest.Error.message);\n                EditorUtility.DisplayDialog(Styles.failedToInstall2DPackageTitle.text, message, Styles.okText.text);\n            }\n\n            return addRequest.Status == PackageManager.StatusCode.Success;\n        }\n\n        internal static void ApplySpriteEditorWindow()\n        {\n            applySpriteEditorWindow();\n        }\n\n        static Action applySpriteEditorWindow = () => {};\n    } // class\n\n    internal class LaunchSpriteEditorWindowAfterDomainReload : ScriptableObject\n    {\n        [SerializeField]\n        UnityEngine.Object m_SelectedObject;\n\n        public UnityEngine.Object selectedObject\n        {\n            get => m_SelectedObject;\n            set => m_SelectedObject = value;\n        }\n\n        public LaunchSpriteEditorWindowAfterDomainReload()\n        {\n            AssemblyReloadEvents.afterAssemblyReload += WaitForEditorApplicaionUpdate;\n        }\n\n        void WaitForEditorApplicaionUpdate()\n        {\n            AssemblyReloadEvents.afterAssemblyReload -= WaitForEditorApplicaionUpdate;\n            // Do this to ensure asset database has finish importing the assets needed by Sprite Editor Window\n            EditorApplication.update += OpenSpriteEditor;\n        }\n\n        void OpenSpriteEditor()\n        {\n            EditorApplication.update -= OpenSpriteEditor;\n            try\n            {\n                SpriteUtilityWindow.ShowSpriteEditorWindow(selectedObject);\n            }\n            catch (Exception e)\n            {\n                throw e;\n            }\n            finally\n            {\n                DestroyImmediate(this);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/StateMachine.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngineInternal;\nusing Object = UnityEngine.Object;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Collections;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\n\nnamespace UnityEditor.Animations\n{\n    public enum AnimatorConditionMode\n    {\n        If = 1,\n        IfNot = 2,\n        Greater = 3,\n        Less = 4,\n        //ExitTime = 5,\n        Equals = 6,\n        NotEqual = 7,\n    }\n\n    public enum TransitionInterruptionSource\n    {\n        None,\n        Source,\n        Destination,\n        SourceThenDestination,\n        DestinationThenSource\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/Transition.h\")]\n    public struct AnimatorCondition\n    {\n        public AnimatorConditionMode      mode                                { get {return m_ConditionMode; }     set {m_ConditionMode = value; }  }\n        public string                     parameter                           { get {return m_ConditionEvent; }    set {m_ConditionEvent = value; } }\n        public float                      threshold                           { get {return m_EventTreshold; }     set {m_EventTreshold = value; }  }\n\n        AnimatorConditionMode   m_ConditionMode;            //eConditionMode\n        string                  m_ConditionEvent;\n        float                   m_EventTreshold;// m_ParameterThreshold\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/Transition.h\")]\n    [NativeHeader(\"Modules/Animation/MecanimUtility.h\")]\n    public partial class AnimatorTransitionBase : Object\n    {\n        protected AnimatorTransitionBase() {}\n\n        public string GetDisplayName(Object source)\n        {\n            return (source is AnimatorState) ? GetDisplayNameStateSource(source as AnimatorState) : GetDisplayNameStateMachineSource(source as AnimatorStateMachine);\n        }\n\n        [NativeMethod(\"GetDisplayName\")]\n        extern internal string GetDisplayNameStateSource(AnimatorState source);\n\n        [NativeMethod(\"GetDisplayName\")]\n        extern internal string GetDisplayNameStateMachineSource(AnimatorStateMachine source);\n\n        [FreeFunction]\n        extern static internal string BuildTransitionName(string source, string destination);\n\n        extern public bool solo { get; set; }\n        extern public bool mute { get; set; }\n        extern public bool isExit { get; set; }\n\n        extern public AnimatorStateMachine destinationStateMachine\n        {\n            [NativeMethod(\"GetDstStateMachine\")]\n            get;\n            [NativeMethod(\"SetDstStateMachine\")]\n            set;\n        }\n        extern public AnimatorState destinationState\n        {\n            [NativeMethod(\"GetDstState\")]\n            get;\n            [NativeMethod(\"SetDstState\")]\n            set;\n        }\n\n        extern public AnimatorCondition[] conditions\n        {\n            get;\n            set;\n        }\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/Transition.h\")]\n    [NativeHeader(\"Editor/Src/Animation/StateMachine.bindings.h\")]\n    public class AnimatorTransition : AnimatorTransitionBase\n    {\n        public AnimatorTransition()\n        {\n            Internal_CreateAnimatorTransition(this);\n        }\n\n        [FreeFunction(\"StateMachineBindings::Internal_CreateAnimatorTransition\")]\n        extern private static void Internal_CreateAnimatorTransition([Writable] AnimatorTransition mono);\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/Transition.h\")]\n    [NativeHeader(\"Editor/Src/Animation/StateMachine.bindings.h\")]\n    [HelpURL(\"class-Transition\")]\n    public class AnimatorStateTransition : AnimatorTransitionBase\n    {\n        public AnimatorStateTransition()\n        {\n            Internal_CreateAnimatorStateTransition(this);\n        }\n\n        [FreeFunction(\"StateMachineBindings::Internal_CreateAnimatorStateTransition\")]\n        extern private static void Internal_CreateAnimatorStateTransition([Writable] AnimatorStateTransition self);\n\n        extern public float                           duration\n        {\n            [NativeMethod(\"GetTransitionDuration\")]\n            get;\n            [NativeMethod(\"SetTransitionDuration\")]\n            set;\n        }\n        extern public float                           offset\n        {\n            [NativeMethod(\"GetTransitionOffset\")]\n            get;\n            [NativeMethod(\"SetTransitionOffset\")]\n            set;\n        }\n        extern public TransitionInterruptionSource    interruptionSource\n        {\n            [NativeMethod(\"GetTransitionInterruptionSource\")]\n            get;\n            [NativeMethod(\"SetTransitionInterruptionSource\")]\n            set;\n        }\n        extern public bool                            orderedInterruption { get; set; }\n        extern public float                           exitTime { get; set; }\n        extern public bool                            hasExitTime { get; set; }\n        extern public bool                            hasFixedDuration { get; set; }\n        extern public bool                            canTransitionToSelf { get; set; }\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/StateMachine.h\")]\n    [NativeHeader(\"Editor/Src/Animation/StateMachine.bindings.h\")]\n    [NativeHeader(\"Editor/Src/Animation/StateMachineBehaviourScripting.h\")]\n    public sealed partial class AnimatorState : Object\n    {\n        public AnimatorState()\n        {\n            Internal_CreateAnimatorState(this);\n        }\n\n        [FreeFunction(\"StateMachineBindings::Internal_CreateAnimatorState\")]\n        extern private static void Internal_CreateAnimatorState([Writable] AnimatorState self);\n\n        extern public int             nameHash\n        {\n            get;\n        }\n        extern public Motion          motion { get; set; }\n        extern public float           speed { get; set; }\n        extern public float           cycleOffset { get; set; }\n        extern public bool            mirror { get; set; }\n        extern public bool            iKOnFeet { get; set; }\n        extern public bool            writeDefaultValues { get; set; }\n        extern public string          tag { get; set; }\n        extern public string          speedParameter { get; set; }\n        extern public string          cycleOffsetParameter { get; set; }\n        extern public string          mirrorParameter { get; set; }\n        extern public string          timeParameter { get; set; }\n        extern public bool            speedParameterActive\n        {\n            [NativeMethod(\"IsSpeedParameterActive\")]\n            get;\n            set;\n        }\n        extern public bool            cycleOffsetParameterActive\n        {\n            [NativeMethod(\"IsCycleOffsetParameterActive\")]\n            get;\n            set;\n        }\n        extern public bool            mirrorParameterActive\n        {\n            [NativeMethod(\"IsMirrorParameterActive\")]\n            get;\n            set;\n        }\n\n        extern public bool            timeParameterActive\n        {\n            [NativeMethod(\"IsTimeParameterActive\")]\n            get;\n            set;\n        }\n\n        extern internal void AddBehaviour(int instanceID);\n        extern internal void RemoveBehaviour(int index);\n\n        extern public AnimatorStateTransition[]   transitions { get; set; }\n\n        [FreeFunction(Name = \"ScriptingAddStateMachineBehaviourWithType\", HasExplicitThis = true)]\n        extern private ScriptableObject ScriptingAddStateMachineBehaviourWithType(Type stateMachineBehaviourType);\n\n        [TypeInferenceRule(TypeInferenceRules.TypeReferencedByFirstArgument)]\n        public StateMachineBehaviour AddStateMachineBehaviour(Type stateMachineBehaviourType)\n        {\n            return (StateMachineBehaviour)ScriptingAddStateMachineBehaviourWithType(stateMachineBehaviourType);\n        }\n\n        public T AddStateMachineBehaviour<T>() where T : StateMachineBehaviour\n        {\n            return AddStateMachineBehaviour(typeof(T)) as T;\n        }\n\n        public StateMachineBehaviour[] behaviours\n        {\n            get { return Array.ConvertAll(behaviours_Internal, so => (StateMachineBehaviour)so); }\n            set { behaviours_Internal = Array.ConvertAll(value, smb => (ScriptableObject)smb); }\n        }\n\n        [NativeName(\"Behaviours\")]\n        private extern ScriptableObject[] behaviours_Internal { get; set; }\n\n        internal extern MonoScript GetBehaviourMonoScript(int index);\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/StateMachine.h\")]\n    [NativeHeader(\"Editor/Src/Animation/StateMachine.bindings.h\")]\n    [RequiredByNativeCode]\n    public struct ChildAnimatorState\n    {\n        AnimatorState m_State;\n        Vector3       m_Position;\n\n        public AnimatorState state { get { return m_State; }  set { m_State = value; } }\n        public Vector3 position { get {return m_Position; } set {  m_Position = value; } }\n    }\n\n\n    [NativeHeader(\"Editor/Src/Animation/StateMachine.h\")]\n    [NativeHeader(\"Editor/Src/Animation/StateMachine.bindings.h\")]\n    [RequiredByNativeCode]\n    public struct  ChildAnimatorStateMachine\n    {\n        AnimatorStateMachine  m_StateMachine;\n        Vector3               m_Position;\n\n        public AnimatorStateMachine   stateMachine    { get { return m_StateMachine; }  set { m_StateMachine = value; } }\n        public Vector3                position        { get {return m_Position; } set {  m_Position = value; } }\n    }\n\n    [NativeHeader(\"Editor/Src/Animation/StateMachine.h\")]\n    [NativeHeader(\"Editor/Src/Animation/StateMachine.bindings.h\")]\n    [NativeHeader(\"Editor/Src/Animation/StateMachineBehaviourScripting.h\")]\n    public sealed partial class AnimatorStateMachine : Object\n    {\n        public AnimatorStateMachine()\n        {\n            Internal_CreateAnimatorStateMachine(this);\n        }\n\n        [FreeFunction(\"StateMachineBindings::Internal_CreateAnimatorStateMachine\")]\n        extern private static void Internal_CreateAnimatorStateMachine([Writable] AnimatorStateMachine self);\n\n        extern public ChildAnimatorState[] states { get; set; }\n\n        extern public ChildAnimatorStateMachine[] stateMachines { get; set; }\n\n        extern public AnimatorState   defaultState\n        {\n            [NativeMethod(\"DefaultState\")]\n            get;\n            set;\n        }\n\n        extern public Vector3         anyStatePosition { get; set; }\n        extern public Vector3         entryPosition { get; set; }\n        extern public Vector3         exitPosition { get; set; }\n        extern public Vector3         parentStateMachinePosition { get; set; }\n        extern public AnimatorStateTransition[]   anyStateTransitions { get; set; }\n        extern public AnimatorTransition[]    entryTransitions { get; set; }\n\n        extern public AnimatorTransition[] GetStateMachineTransitions(AnimatorStateMachine sourceStateMachine);\n\n        extern public void SetStateMachineTransitions(AnimatorStateMachine sourceStateMachine, AnimatorTransition[] transitions);\n\n        extern internal void AddBehaviour(int instanceID);\n        extern internal void RemoveBehaviour(int index);\n\n        [FreeFunction(Name = \"ScriptingAddStateMachineBehaviourWithType\", HasExplicitThis = true)]\n        extern private ScriptableObject ScriptingAddStateMachineBehaviourWithType(Type stateMachineBehaviourType);\n\n        [TypeInferenceRule(TypeInferenceRules.TypeReferencedByFirstArgument)]\n        public StateMachineBehaviour AddStateMachineBehaviour(Type stateMachineBehaviourType)\n        {\n            return (StateMachineBehaviour)ScriptingAddStateMachineBehaviourWithType(stateMachineBehaviourType);\n        }\n\n        public T AddStateMachineBehaviour<T>() where T : StateMachineBehaviour\n        {\n            return AddStateMachineBehaviour(typeof(T)) as T;\n        }\n\n        extern public string MakeUniqueStateName(string name);\n        extern public string MakeUniqueStateMachineName(string name);\n\n\n        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n        // Internals\n\n        extern internal void Clear();\n        [NativeMethod(\"RemoveState\")]\n        extern internal void RemoveStateInternal(AnimatorState state);\n        [NativeMethod(\"RemoveStateMachine\")]\n        extern internal void RemoveStateMachineInternal(AnimatorStateMachine stateMachine);\n\n        extern internal void MoveState(AnimatorState state, AnimatorStateMachine target);\n        extern internal void MoveStateMachine(AnimatorStateMachine stateMachine, AnimatorStateMachine target);\n\n        extern internal bool HasState(AnimatorState state, bool recursive);\n        extern internal bool HasStateMachine(AnimatorStateMachine state, bool recursive);\n\n        extern internal int transitionCount\n        {\n            get;\n        }\n\n        public StateMachineBehaviour[] behaviours\n        {\n            get { return Array.ConvertAll(behaviours_Internal, so => (StateMachineBehaviour)so); }\n            set { behaviours_Internal = Array.ConvertAll(value, smb => (ScriptableObject)smb); }\n        }\n\n        [NativeName(\"Behaviours\")]\n        private extern ScriptableObject[] behaviours_Internal { get; set; }\n\n        internal extern MonoScript GetBehaviourMonoScript(int index);\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/StateMachineBehaviourContext.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing UnityEngine.Scripting;\nusing UnityEditor;\nusing System.Runtime.InteropServices;\n\nnamespace UnityEditor.Animations\n{\n    [NativeHeader(\"Editor/Src/Animation/StateMachineBehaviourContext.h\")]\n    [System.Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    [NativeAsStruct]\n    public partial class StateMachineBehaviourContext\n    {\n        [NativeName(\"m_AnimatorController\")]\n        public AnimatorController           animatorController;\n        [NativeName(\"m_AnimatorObject\")]\n        public UnityEngine.Object           animatorObject;\n        [NativeName(\"m_LayerIndex\")]\n        public int                          layerIndex;\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/StaticOcclusionCulling.bindings.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEngine;\nusing UnityEngine.Bindings;\nusing Object = UnityEngine.Object;\n\nnamespace UnityEditor\n{\n    // StaticOcclusionCulling lets you perform static occlusion culling operations\n    [NativeHeader(\"Runtime/Camera/OcclusionCullingSettings.h\")]\n    [NativeHeader(\"Runtime/Camera/RendererScene.h\")]\n    [NativeHeader(\"Editor/Src/OcclusionCulling.h\")]\n    public static class StaticOcclusionCulling\n    {\n        // Used to generate static occlusion culling data. This function will not return until occlusion data is generated.\n        [NativeName(\"GenerateTome\")]\n        public static extern bool Compute();\n\n        // Used to compute static occlusion culling data asynchronously.\n        [NativeName(\"GenerateTomeInBackground\")]\n        public static extern bool GenerateInBackground();\n\n        [NativeName(\"RemoveTempFolder\")]\n        public static extern void RemoveCacheFolder();\n\n        // Used to invalidate preVisualistion debug data.\n        internal static extern void InvalidatePrevisualisationData();\n\n        // Used to cancel asynchronous generation of static occlusion culling data.\n        public static extern void Cancel();\n\n        // Used to check if asynchronous generation of static occlusion culling data is still running.\n        public static extern bool isRunning\n        {\n            [NativeName(\"IsRunning\")]\n            get;\n        }\n\n        // Clears the Tome of the opened scene\n        [NativeName(\"ClearUmbraTome\")]\n        public static extern void Clear();\n\n        // Get the OcclusionCullingSettings\n        internal static extern Object occlusionCullingSettings\n        {\n            [FreeFunction]\n            get;\n        }\n\n        [StaticAccessor(\"GetOcclusionCullingSettings()\", StaticAccessorType.Dot)]\n        [NativeProperty(TargetType = TargetType.Field)]\n        public static extern float smallestOccluder\n        {\n            [NativeName(\"GetOcclusionBakeSettings().smallestOccluder\")]\n            get;\n            [NativeName(\"GetOcclusionBakeSettingsSetDirty().smallestOccluder\")]\n            set;\n        }\n\n        [StaticAccessor(\"GetOcclusionCullingSettings()\", StaticAccessorType.Dot)]\n        [NativeProperty(TargetType = TargetType.Field)]\n        public static extern float smallestHole\n        {\n            [NativeName(\"GetOcclusionBakeSettings().smallestHole\")]\n            get;\n            [NativeName(\"GetOcclusionBakeSettingsSetDirty().smallestHole\")]\n            set;\n        }\n\n        [StaticAccessor(\"GetOcclusionCullingSettings()\", StaticAccessorType.Dot)]\n        [NativeProperty(TargetType = TargetType.Field)]\n        public static extern float backfaceThreshold\n        {\n            [NativeName(\"GetOcclusionBakeSettings().backfaceThreshold\")]\n            get;\n            [NativeName(\"GetOcclusionBakeSettingsSetDirty().backfaceThreshold\")]\n            set;\n        }\n\n        public static extern bool doesSceneHaveManualPortals\n        {\n            [NativeName(\"DoesSceneHaveManualPortals\")]\n            get;\n        }\n\n        // Returns the size in bytes that the Tome data is currently taking up in this scene on disk\n        [StaticAccessor(\"GetRendererScene()\", StaticAccessorType.Dot)]\n        public static extern int umbraDataSize { get; }\n\n        [StaticAccessor(\"GetOcclusionCullingSettings()\", StaticAccessorType.Dot)]\n        public static extern void SetDefaultOcclusionBakeSettings();\n    }\n\n    // Used to visualize static occlusion culling at development time in scene view.\n    [StaticAccessor(\"GetOcclusionCullingVisualization()\", StaticAccessorType.Arrow)]\n    [NativeHeader(\"Editor/Src/OcclusionCullingVisualizationState.h\")]\n    [NativeHeader(\"Runtime/Camera/Camera.h\")]\n    public static class StaticOcclusionCullingVisualization\n    {\n        // If set to true, visualization of target volumes is enabled.\n        public static extern bool showOcclusionCulling { get; set; }\n\n        // If set to true, the visualization lines of the PVS volumes will show all cells rather than cells after culling.\n        [NativeName(\"ShowPreVis\")]\n        public static extern bool showPreVisualization { get; set; }\n\n        // If set to true, visualization of view volumes is enabled.\n        public static extern bool showViewVolumes { get; set; }\n\n        public static extern bool showDynamicObjectBounds { get; set; }\n\n        // If set to true, visualization of portals is enabled.\n        public static extern bool showPortals { get; set; }\n\n        // If set to true, visualization of portals is enabled.\n        public static extern bool showVisibilityLines { get; set; }\n\n        // If set to true, culling of geometry is enabled.\n        public static extern bool showGeometryCulling { get; set; }\n\n        public static extern bool isPreviewOcclusionCullingCameraInPVS\n        {\n            [FreeFunction(\"IsPreviewOcclusionCullingCameraInPVS\")]\n            get;\n        }\n\n        public static extern Camera previewOcclusionCamera\n        {\n            [FreeFunction(\"FindPreviewOcclusionCamera\")]\n            get;\n        }\n\n        //*undoc*\n        // This is here because it was released on 3.0 (this is a typo)\n        public static extern Camera previewOcclucionCamera\n        {\n            [FreeFunction(\"FindPreviewOcclusionCamera\")]\n            get;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Text/BlurryTextMappingTable.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.TextCore.Text;\n\nnamespace UnityEditor\n{\n    // Stores FontAsset to ensure they are not destroyed after domain reload\n    [Serializable]\n    internal class BlurryTextCaching\n    {\n        [SerializeField]\n        private List<FontAssetEntry> m_Entries = new();\n\n        private Dictionary<Tuple<int, FontAsset, bool>, FontAsset> m_FontAssetPointSizeLookup = new();\n\n        public void InitializeLookups()\n        {\n            if (m_FontAssetPointSizeLookup.Count != 0)\n                return;\n\n            m_FontAssetPointSizeLookup.Clear();\n\n            foreach (var entry in m_Entries)\n            {\n                var key = Tuple.Create(entry.pointSize, entry.sourceFontAsset, entry.isRaster);\n                m_FontAssetPointSizeLookup.TryAdd(key, entry.correspondingFontAsset);\n            }\n        }\n\n        public void Add(FontAsset sourceFontAsset, int pointSize, bool isRaster, FontAsset correspondingFontAsset)\n        {\n            m_Entries.Add(new FontAssetEntry\n            {\n                sourceFontAsset = sourceFontAsset,\n                pointSize = pointSize,\n                isRaster = isRaster,\n                correspondingFontAsset = correspondingFontAsset\n            });\n\n            m_FontAssetPointSizeLookup.Add(Tuple.Create(pointSize, sourceFontAsset, isRaster), correspondingFontAsset);\n        }\n\n        public FontAsset Find(FontAsset sourceFontAsset, int pointSize, bool isRaster)\n        {\n            return m_FontAssetPointSizeLookup.TryGetValue(Tuple.Create(pointSize, sourceFontAsset, isRaster), out var correspondingFontAsset) ? correspondingFontAsset : null;\n        }\n\n        [Serializable]\n        private class FontAssetEntry\n        {\n            public FontAsset sourceFontAsset;\n            public FontAsset correspondingFontAsset;\n            public int pointSize;\n            public bool isRaster;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Tools/EditorActionTool.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing UnityEditor.EditorTools;\nusing UnityEngine;\n\nnamespace UnityEditor.Actions\n{\n    sealed class EditorActionTool : IDisposable\n    {\n        public EditorAction action { get; internal set; }\n        bool m_IsCancelled;\n\n        EditorActionTool() { }\n\n        public EditorActionTool(EditorAction action)\n        {\n            this.action = action;\n            this.action.actionFinished += OnActionFinished;\n\n            Selection.selectionChanged += Dispose;\n        }\n\n        public void OnGUI(EditorWindow window)\n        {\n            if (!(window is SceneView sceneView))\n                return;\n\n            var evt = Event.current;\n\n            if(evt.type == EventType.KeyDown)\n            {\n                if (evt.keyCode == KeyCode.Escape)\n                {\n                    Cancel();\n                    evt.Use();\n                    return;\n                }\n\n                if (evt.keyCode == KeyCode.Return)\n                {\n                    Dispose();\n                    evt.Use();\n                    return;\n                }\n            }\n\n            action?.OnSceneGUI(sceneView);\n        }\n\n        void OnActionFinished(EditorActionResult result) => Dispose();\n\n        public void Cancel()\n        {\n            m_IsCancelled = true;\n            Dispose();\n        }\n\n        public void Dispose()\n        {\n            if (action == null)\n                return;\n            action.actionFinished -= OnActionFinished;\n            Selection.selectionChanged -= Dispose;\n\n            action?.Finish(m_IsCancelled ? EditorActionResult.Canceled : EditorActionResult.Success);\n            action = null;\n            EditorToolManager.activeOverride = null;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Tools/EditorToolCache.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityObject = UnityEngine.Object;\n\nnamespace UnityEditor.EditorTools\n{\n    // Placeholder type for global editors to register as keys\n    struct NullTargetKey {}\n\n    [Serializable]\n    struct EditorTypeAssociation : ISerializationCallbackReceiver\n    {\n        [SerializeField]\n        string m_TargetContext, m_TargetBehaviour, m_EditorType, m_VariantGroup;\n\n        // Context and behaviour types can be null, and should be treated as universally applicable.\n        public Type targetContext { get; private set; }\n        public Type targetBehaviour { get; private set; }\n        public Type editor { get; private set; }\n        public Type variantGroup { get; private set; }\n        public int priority { get; private set; }\n        public int variantPriority { get; private set; }\n\n        public EditorTypeAssociation(Type editor, Type attributeType)\n        {\n            this.editor = editor;\n            var attrib = editor.GetCustomAttributes(attributeType, false).FirstOrDefault() as ToolAttribute;\n            targetBehaviour = attrib?.targetType ?? typeof(NullTargetKey);\n            targetContext = attrib?.targetContext;\n            variantGroup = attrib?.variantGroup;\n            priority = attrib?.toolPriority ?? ToolAttribute.defaultPriority;\n            variantPriority = attrib?.variantPriority ?? ToolAttribute.defaultPriority;\n            m_TargetContext = m_TargetBehaviour = m_EditorType = m_VariantGroup = null;\n        }\n\n        public void OnBeforeSerialize()\n        {\n            m_TargetContext = targetContext?.AssemblyQualifiedName;\n            m_TargetBehaviour = targetBehaviour?.AssemblyQualifiedName;\n            m_EditorType = editor?.AssemblyQualifiedName;\n            m_VariantGroup = variantGroup?.AssemblyQualifiedName;\n        }\n\n        public void OnAfterDeserialize()\n        {\n            if (!string.IsNullOrEmpty(m_TargetContext))\n                targetContext = Type.GetType(m_TargetContext);\n            if (!string.IsNullOrEmpty(m_TargetBehaviour))\n                targetBehaviour = Type.GetType(m_TargetBehaviour);\n            if (!string.IsNullOrEmpty(m_EditorType))\n                editor = Type.GetType(m_EditorType);\n            if (!string.IsNullOrEmpty(m_VariantGroup))\n                variantGroup = Type.GetType(m_VariantGroup);\n        }\n    }\n\n    // Defines a selection driven instance of some type, either EditorTool or EditorToolContext\n    [Serializable]\n    class ComponentEditor\n    {\n        internal enum EditorToolScope\n        {\n            NotInitialized,\n            ToolContext,\n            ComponentTool,\n            ManipulationToolOverride\n        };\n\n        [SerializeField]\n        bool m_LockedInspector;\n\n        [SerializeField]\n        Editor m_Inspector;\n\n        [SerializeField]\n        ScriptableObject m_Editor;\n\n        EditorTypeAssociation m_EditorTypeAssociation;\n        public readonly ActiveEditorTracker tracker;\n        public List<Editor> additionalEditors;\n        public EditorToolScope m_EditorToolScope;\n\n        public Editor inspector => m_Inspector;\n        public Type editorType => m_EditorTypeAssociation.editor;\n        public EditorTypeAssociation typeAssociation => m_EditorTypeAssociation;\n        public bool lockedInspector => m_LockedInspector;\n        public EditorToolScope editorToolScope => m_EditorToolScope;\n\n        public UnityObject editor => m_Editor;\n\n        public T GetEditor<T>() where T : ScriptableObject, IEditor => m_Editor as T;\n\n        public ComponentEditor(EditorTypeAssociation typeAssociation, ActiveEditorTracker tracker, Editor inspector)\n        {\n            if (typeAssociation.editor == null)\n                throw new ArgumentNullException(\"typeAssociation\");\n\n            if (!typeof(IEditor).IsAssignableFrom(typeAssociation.editor)\n                || !typeof(UnityObject).IsAssignableFrom(typeAssociation.editor))\n                throw new ArgumentException(\"Tool type must implement UnityEngine.ScriptableObject, IEditor.\", \"typeAssociation\");\n\n            this.tracker = tracker;\n\n            m_Inspector = inspector;\n            m_LockedInspector = tracker.isLocked;\n            m_EditorTypeAssociation = typeAssociation;\n            m_EditorToolScope = EditorToolScope.NotInitialized;\n        }\n\n        public UnityObject target => inspector != null ? inspector.target : null;\n\n        public UnityObject[] targets\n        {\n            get\n            {\n                if (additionalEditors == null)\n                    return inspector.targets;\n                List<UnityObject> objects = new List<UnityObject>(inspector.targets);\n                foreach (var additionalInspector in additionalEditors)\n                    foreach (var additionalTarget in additionalInspector.targets)\n                        if (!objects.Contains(additionalTarget))\n                            objects.Add(additionalTarget);\n                return objects.ToArray();\n            }\n        }\n\n        public void AddInspector(Editor addlInspector)\n        {\n            if (additionalEditors == null)\n                additionalEditors = new List<Editor>() { addlInspector };\n            else\n                additionalEditors.Add(addlInspector);\n        }\n\n        public UnityObject InstantiateEditor()\n        {\n            var toolType = editorType;\n\n            m_Editor = ScriptableObject.CreateInstance(toolType, x =>\n            {\n                ((IEditor)x).SetTargets(targets);\n                ((IEditor)x).SetTarget(target);\n            });\n\n            m_Editor.hideFlags = HideFlags.DontSave;\n\n            if(m_Editor is EditorToolContext)\n                m_EditorToolScope = EditorToolScope.ToolContext;\n            else if(m_Editor is EditorTool tool &&\n                    EditorToolUtility.GetEnumWithEditorTool(tool, EditorToolManager.activeToolContext) != Tool.Custom)\n                m_EditorToolScope = EditorToolScope.ManipulationToolOverride;\n            else\n                m_EditorToolScope = EditorToolScope.ComponentTool;\n\n            return m_Editor;\n        }\n    }\n\n    // A lookup table of component (target) to editor (tool or context). Null targets are explicitly allowed. Null\n    // target types are treated as \"global\" editors.\n    class EditorToolCache\n    {\n\n        Type m_AttributeType;\n        // Cache of the available tools as defined by EditorToolAttribute\n        EditorTypeAssociation[] s_AvailableEditorTypeAssociations = null;\n        // Type association data for all loaded tools, regardless of whether they are registered with an EditorToolAttribute.\n        Dictionary<Type, EditorTypeAssociation> m_ToolMetaData = new Dictionary<Type, EditorTypeAssociation>();\n        Dictionary<Type, List<EditorTypeAssociation>> s_EditorTargetCache = new Dictionary<Type, List<EditorTypeAssociation>>();\n\n        public EditorToolCache(Type attributeType)\n        {\n            if (!typeof(ToolAttribute).IsAssignableFrom(attributeType))\n                throw new ArgumentException(\"Attribute type must inherit ToolAttribute.\", \"attributeType\");\n            m_AttributeType = attributeType;\n        }\n\n        public int Count => availableEditorTypeAssociations.Length;\n\n        EditorTypeAssociation[] availableEditorTypeAssociations\n        {\n            get\n            {\n                if (s_AvailableEditorTypeAssociations == null)\n                {\n                    Type[] editorTools = TypeCache.GetTypesWithAttribute(m_AttributeType)\n                        .Where(x => !x.IsAbstract)\n                        .ToArray();\n                    int len = editorTools.Length;\n                    s_AvailableEditorTypeAssociations = new EditorTypeAssociation[len];\n\n                    for (int i = 0; i < len; i++)\n                        s_AvailableEditorTypeAssociations[i] = new EditorTypeAssociation(editorTools[i], m_AttributeType);\n\n                }\n\n                return s_AvailableEditorTypeAssociations;\n            }\n        }\n\n        public EditorTypeAssociation GetMetaData(Type toolType)\n        {\n            if (!m_ToolMetaData.TryGetValue(toolType, out var data))\n                m_ToolMetaData.Add(toolType, data = new EditorTypeAssociation(toolType, m_AttributeType));\n            return data;\n        }\n\n        public Type GetTargetType(Type editorType)\n        {\n            for (int i = 0, c = availableEditorTypeAssociations.Length; i < c; i++)\n                if (availableEditorTypeAssociations[i].editor == editorType)\n                    return availableEditorTypeAssociations[i].targetBehaviour == typeof(NullTargetKey)\n                        ? null\n                        : availableEditorTypeAssociations[i].targetBehaviour;\n            return null;\n        }\n\n        // Returns a reference to the cached target editor type list. If this is made public make sure to also return\n        // a copy or modify to instead populate a pre-allocated list.\n        internal IEnumerable<EditorTypeAssociation> GetEditorsForTargetType(Type target)\n        {\n            // Tools with 'null' target are considered to be Global tools\n            if (target == null)\n                target = typeof(NullTargetKey);\n\n            if (s_EditorTargetCache.TryGetValue(target, out List<EditorTypeAssociation> res))\n                return res;\n\n            s_EditorTargetCache.Add(target, res = new List<EditorTypeAssociation>());\n\n            for (int i = 0, c = availableEditorTypeAssociations.Length; i < c; i++)\n            {\n                if (availableEditorTypeAssociations[i].targetBehaviour != null\n                    && (availableEditorTypeAssociations[i].targetBehaviour.IsAssignableFrom(target)\n                        || target.IsAssignableFrom(availableEditorTypeAssociations[i].targetBehaviour)))\n                    res.Add(availableEditorTypeAssociations[i]);\n            }\n\n            return res;\n        }\n\n        void CollectEditorsForTracker(EditorToolContext ctx, ActiveEditorTracker tracker, List<ComponentEditor> editors)\n        {\n            var trackerEditors = tracker.activeEditors;\n\n            for (int i = 0, c = trackerEditors.Length; i < c; i++)\n            {\n                var editor = trackerEditors[i];\n                var target = editor != null ? editor.target : null;\n\n                if (target == null || EditorUtility.IsPersistent(target))\n                    return;\n\n                var eligible = GetEditorsForTargetType(editor.target.GetType());\n                var activeContextType = ctx == null ? typeof(GameObjectToolContext) : ctx.GetType();\n\n                foreach (var association in eligible)\n                {\n                    if (association.targetContext != null && association.targetContext != activeContextType)\n                        continue;\n\n                    // Shared trackers should create one tool per-type, regardless of how many targets are present.\n                    // The exception is locked inspectors, which can create a distinct tool instance for each target\n                    // not already represented. That means that if the shared tracker and locked inspector are inspecting\n                    // the same selection, there should only be one tool per tool type. However if the locked inspector\n                    // and selection are different, there may be duplicate tool types with different targets.\n                    var existing = editors.Find(x =>\n                        x.editorType == association.editor\n                        && (x.target == target || ReferenceEquals(x.tracker, tracker))\n                    );\n\n                    if (existing != null)\n                        existing.AddInspector(editor);\n                    else\n                        editors.Add(new ComponentEditor(association, tracker, editor));\n                }\n            }\n        }\n\n        public void InstantiateEditors(EditorToolContext ctx, List<ComponentEditor> editors)\n        {\n            editors.Clear();\n\n            // If the shared tracker is locked, use fallback tracker instance so that the active selection is always\n            // represented. Addresses case where a single locked inspector is open.\n            var shared = ActiveEditorTracker.sharedTracker;\n            var activeTracker = shared.isLocked ? ActiveEditorTracker.fallbackTracker : shared;\n\n            // We collect editors only for the tracker that represents the active selection.\n            CollectEditorsForTracker(ctx, activeTracker, editors);\n\n            foreach (var editor in editors)\n                editor.InstantiateEditor();\n        }\n\n        public List<EditorTypeAssociation> GetEditorsForVariant(EditorTypeAssociation type)\n        {\n            var tools = new List<EditorTypeAssociation>();\n            foreach(var association in availableEditorTypeAssociations)\n                if (association.variantGroup == type.variantGroup\n                    && association.targetBehaviour == type.targetBehaviour\n                    && association.targetContext == type.targetContext)\n                    tools.Add(association);\n            return tools;\n        }\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Tools/EditorToolContext.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing UnityEditor.Overlays;\nusing UnityEditor.Toolbars;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing UnityObject = UnityEngine.Object;\n\nnamespace UnityEditor.EditorTools\n{\n    // This serves as the default tool setting implementation.\n    [CustomEditor(typeof(EditorToolContext), true)]\n    class GameObjectToolContextCustomEditor : Editor, ICreateToolbar\n    {\n        string[] k_ToolbarIds = new string [0];\n\n        public IEnumerable<string> toolbarElements => k_ToolbarIds;\n\n        public EditorWindow containerWindow { get; set; }\n\n        public override VisualElement CreateInspectorGUI()\n        {\n            return new EditorToolbar(toolbarElements, containerWindow).rootVisualElement;\n        }\n    }\n\n    public abstract class EditorToolContext : ScriptableObject, IEditor\n    {\n        bool m_Active;\n\n        [HideInInspector]\n        [SerializeField]\n        internal UnityObject[] m_Targets;\n\n        [HideInInspector]\n        [SerializeField]\n        internal UnityObject m_Target;\n\n        public IEnumerable<UnityObject> targets => m_Targets != null && m_Targets.Length > 0\n            ? m_Targets\n            : Selection.objects;\n\n        public UnityObject target => m_Target == null ? Selection.activeObject : m_Target;\n\n        internal void Activate()\n        {\n            if(m_Active\n            // Prevent to reenable the context if this is not the active one anymore\n            // Can happen when entering playmode due to the delayCall in EditorToolManager.OnEnable\n                || this != EditorToolManager.activeToolContext)\n                return;\n\n            OnActivated();\n            m_Active = true;\n        }\n\n        internal void Deactivate()\n        {\n            if(!m_Active)\n                return;\n\n            OnWillBeDeactivated();\n            m_Active = false;\n        }\n\n        public virtual void OnActivated() {}\n\n        public virtual void OnWillBeDeactivated() {}\n\n        public virtual void PopulateMenu(DropdownMenu menu) {}\n\n        void IEditor.SetTarget(UnityObject value) => m_Target = value;\n\n        void IEditor.SetTargets(UnityObject[] value) => m_Targets = value;\n\n        public virtual void OnToolGUI(EditorWindow window) {}\n\n        public Type ResolveTool(Tool tool)\n        {\n            switch (tool)\n            {\n                case Tool.None:\n                    return typeof(NoneTool);\n\n                case Tool.View:\n                    return typeof(ViewModeTool);\n\n                case Tool.Custom:\n                    return null;\n\n                default:\n                    var resolved = GetEditorToolType(tool);\n\n                    // Returning null is valid here, but types that do not inherit EditorTool or are abstract are not.\n                    if (resolved != null && (!typeof(EditorTool).IsAssignableFrom(resolved) || resolved.IsAbstract))\n                        Debug.LogError($\"Tool context \\\"{GetType()}\\\" resolved {tool} to an invalid EditorTool type. \" +\n                            $\"Resolved types must inherit EditorTool and not be abstract.\");\n                    else\n                        return resolved;\n                    return null;\n            }\n        }\n\n        protected virtual Type GetEditorToolType(Tool tool)\n        {\n            switch (tool)\n            {\n                case Tool.Move:\n                    return typeof(MoveTool);\n                case Tool.Rotate:\n                    return typeof(RotateTool);\n                case Tool.Scale:\n                    return typeof(ScaleTool);\n                case Tool.Rect:\n                    return typeof(RectTool);\n                case Tool.Transform:\n                    return typeof(TransformTool);\n                default:\n                    throw new ArgumentException(\"EditorToolContext should only be used to resolve transform tools. \" +\n                        \"View, Custom, and None are not applicable.\");\n            }\n        }\n\n        public virtual IEnumerable<Type> GetAdditionalToolTypes() => Enumerable.Empty<Type>();\n    }\n}\n"
  },
  {
    "path": "Editor/Mono/Tools/EditorToolManager.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Linq;\nusing UnityEditor.Actions;\nusing UnityEditor.SceneManagement;\nusing UnityEngine;\nusing UnityObject = UnityEngine.Object;\n\nnamespace UnityEditor.EditorTools\n{\n    sealed class EditorToolManager : ScriptableSingleton<EditorToolManager>\n    {\n        [SerializeField]\n        List<ScriptableObject> m_SingletonObjects = new List<ScriptableObject>();\n\n        [SerializeField]\n        EditorTool m_ActiveTool;\n\n        EditorActionTool m_ActiveOverride;\n\n        Tool m_PreviousTool = Tool.Move;\n\n        [SerializeField]\n        Tool m_LastBuiltinTool = Tool.Move;\n\n        [SerializeField]\n        EditorTool m_LastCustomTool;\n\n        [SerializeField]\n        ToolVariantPrefs m_VariantPrefs = new ToolVariantPrefs();\n\n        public ToolVariantPrefs variantPrefs => m_VariantPrefs;\n\n        static bool s_ChangingActiveTool, s_ChangingActiveContext;\n\n        // Mimic behavior of Tools.toolChanged for backwards compatibility until existing tools are converted to the new\n        // apis.\n        internal static event Action<EditorTool, EditorTool> activeToolChanged;\n\n        [SerializeField]\n        List<ComponentEditor> m_ComponentTools = new List<ComponentEditor>();\n\n        [SerializeField]\n        List<ComponentEditor> m_ComponentContexts = new List<ComponentEditor>();\n\n        // unfiltered component tools includes locked inspectors\n        internal IEnumerable<ComponentEditor> componentTools => m_ComponentTools;\n\n        internal static IEnumerable<ComponentEditor> componentContexts => instance.m_ComponentContexts;\n\n        internal static int availableComponentContextCount => instance.m_ComponentContexts.Count;\n\n        internal static IEnumerable<Type> additionalContextToolTypesCache = Enumerable.Empty<Type>();\n\n        [SerializeField]\n        EditorToolContext m_ActiveToolContext;\n\n        internal static EditorToolContext activeToolContext\n        {\n            get\n            {\n                if (instance.m_ActiveToolContext == null)\n                {\n                    instance.m_ActiveToolContext = GetSingleton<GameObjectToolContext>();\n                    ToolManager.ActiveContextDidChange();\n                    instance.m_ActiveToolContext.Activate();\n                }\n                return instance.m_ActiveToolContext;\n            }\n\n            set\n            {\n                if (s_ChangingActiveContext)\n                {\n                    // pop the changing state so that we don't lock the active tool after an exception is thrown.\n                    s_ChangingActiveContext = false;\n                    throw new InvalidOperationException(\"Setting the active context from EditorToolContext.OnActivated or EditorToolContext.OnWillBeDeactivated is not allowed.\");\n                }\n\n                var ctx = value == null ? GetSingleton<GameObjectToolContext>() : value;\n\n                if (ctx == activeToolContext)\n                    return;\n\n                s_ChangingActiveContext = true;\n\n                // Make sure to get the active tool enum prior to setting the context, otherwise we'll be comparing\n                // apples to oranges. Ie, the transform tools will be different despite being the same `Tool` enum value.\n                var tool = Tools.current;\n                var wasAdditionalContextTool = tool == Tool.Custom && additionalContextToolTypesCache.Contains(activeTool.GetType());\n                var prev = instance.m_ActiveToolContext;\n\n                if (prev != null)\n                {\n                    prev.Deactivate();\n                }\n\n                ToolManager.ActiveContextWillChange();\n                instance.m_ActiveToolContext = ctx;\n\n                ctx.Activate();\n\n                instance.RebuildAvailableTools();\n\n                var active = instance.m_ActiveTool;\n\n                // If the previous tool was a Move, Rotate, Scale, Rect, or Transform tool we need to resolve the tool\n                // type using the new context. Additionally, if the previous tool was null we'll take the opportunity\n                // to assign a valid tool.\n                if (EditorToolUtility.IsManipulationTool(tool) || active == null || active is NoneTool)\n                {\n                    var resolved = EditorToolUtility.GetEditorToolWithEnum(tool, ctx);\n\n                    // Always try to resolve to a valid tool when switching contexts, even if it means changing the\n                    // active tool type\n                    for (int i = (int)Tool.Move; (resolved == null || resolved is NoneTool) && i < (int)Tool.Custom; i++)\n                        resolved = EditorToolUtility.GetEditorToolWithEnum((Tool)i);\n\n                    // If resolved is still null at this point, the setter for activeTool will substitute an instance of\n                    // NoneTool for us.\n                    activeTool = resolved;\n                }\n                // If the previous tool was an additional tool from the context, return to the Previous Persistent Tool\n                // when moving to that new context\n                else if(wasAdditionalContextTool)\n                {\n                    var isAdditionalContextTool = instance.m_ActiveToolContext.GetAdditionalToolTypes().Contains(activeTool.GetType());\n\n                    if(!isAdditionalContextTool)\n                        RestorePreviousPersistentTool();\n                }\n\n                ToolManager.ActiveContextDidChange();\n\n                s_ChangingActiveContext = false;\n            }\n        }\n\n        internal static EditorTool activeTool\n        {\n            get { return instance.m_ActiveTool; }\n\n            set\n            {\n                if (s_ChangingActiveTool)\n                {\n                    // pop the changing state so that we don't lock the active tool after an exception is thrown.\n                    s_ChangingActiveTool = false;\n                    throw new InvalidOperationException(\"Attempting to set the active tool from EditorTool.OnActivate or EditorTool.OnDeactivate. This is not allowed.\");\n                }\n\n                var tool = value;\n\n                if (tool == null)\n                    tool = GetSingleton<NoneTool>();\n\n                if (tool == instance.m_ActiveTool)\n                    return;\n\n                s_ChangingActiveTool = true;\n\n                activeOverride = null;\n\n                ToolManager.ActiveToolWillChange();\n\n                var previous = instance.m_ActiveTool;\n                var meta = EditorToolUtility.GetMetaData(tool.GetType());\n\n                if (previous != null)\n                {\n                    previous.Deactivate();\n\n                    var previousMeta = EditorToolUtility.GetMetaData(previous.GetType());\n                    var previousEnum = EditorToolUtility.GetEnumWithEditorTool(previous, activeToolContext);\n                    if (previousEnum != Tool.View\n                        && previousEnum != Tool.None\n                        && (EditorToolUtility.IsBuiltinOverride(previous) || !EditorToolUtility.IsComponentTool(previous.GetType()))\n                        // if the previous and current tools are from the same variant group, don't save the previous variant as previous tool\n                        && (meta.variantGroup == null || previousMeta.variantGroup != meta.variantGroup))\n                    {\n                        instance.m_PreviousTool = previousEnum;\n\n                        if (EditorToolUtility.IsManipulationTool(previousEnum))\n                            instance.m_LastBuiltinTool = previousEnum;\n                        else\n                            instance.m_LastCustomTool = previous;\n                    }\n                }\n\n                instance.m_ActiveTool = tool;\n                instance.m_ActiveTool.Activate();\n\n                ToolManager.ActiveToolDidChange();\n\n                if (activeToolChanged != null)\n                    activeToolChanged(previous, instance.m_ActiveTool);\n\n                Tools.SyncToolEnum();\n                Tools.InvalidateHandlePosition();\n\n                if(meta.variantGroup != null)\n                    instance.variantPrefs.SetPreferredVariant(meta.variantGroup, meta.editor);\n\n                s_ChangingActiveTool = false;\n            }\n        }\n\n        // this tool will transparently override the `OnToolGUI` method of the active tool.\n        // do not expose this as public API with also considering how to handle lifecycle and active tool interop.\n        // currently this is only used for EditorToolAction.\n        internal static EditorActionTool activeOverride\n        {\n            get => instance.m_ActiveOverride;\n\n            set\n            {\n                instance.m_ActiveOverride?.Dispose();\n                instance.m_ActiveOverride = value;\n            }\n        }\n\n        [Serializable]\n        struct ComponentToolCache : ISerializationCallbackReceiver\n        {\n            [SerializeField]\n            string m_ToolType;\n            [SerializeField]\n            string m_ContextType;\n\n            public Type contextType;\n            public Type toolType;\n            public UnityObject targetObject;\n            public UnityObject[] targetObjects;\n\n            public static readonly ComponentToolCache Empty = new ComponentToolCache(null, null);\n\n            public ComponentToolCache(EditorToolContext context, EditorTool tool)\n            {\n                bool customTool = IsCustomEditorTool(tool);\n                bool customContext = IsCustomToolContext(context);\n\n                if (customTool || customContext)\n                {\n                    toolType = customTool ? tool.GetType() : null;\n                    contextType = customContext ? context.GetType() : null;\n                    targetObject = tool.target;\n                    targetObjects = tool.targets.ToArray();\n                }\n                else\n                {\n                    toolType = null;\n                    contextType = null;\n                    targetObject = null;\n                    targetObjects = null;\n                }\n\n                m_ToolType = null;\n                m_ContextType = null;\n            }\n\n            public bool IsEqual(ComponentEditor other)\n            {\n                var editor = other?.GetEditor<EditorTool>();\n\n                if (editor == null || targetObjects == null || editor.targets == null)\n                    return false;\n\n                // todo need to cache ComponentEditor targets\n                return toolType == editor.GetType() && targetObjects.SequenceEqual(editor.targets);\n            }\n\n            public override string ToString()\n            {\n                return $\"Tool: {toolType} Context: {contextType}\";\n            }\n\n            public void OnBeforeSerialize()\n            {\n                m_ToolType = toolType != null ? toolType.AssemblyQualifiedName : null;\n                m_ContextType = contextType != null ? contextType.AssemblyQualifiedName : null;\n            }\n\n            public void OnAfterDeserialize()\n            {\n                if (!string.IsNullOrEmpty(m_ToolType))\n                    toolType = Type.GetType(m_ToolType);\n                if (!string.IsNullOrEmpty(m_ContextType))\n                    contextType = Type.GetType(m_ContextType);\n            }\n        }\n\n        [SerializeField]\n        ComponentToolCache m_PreviousComponentToolCache;\n\n        internal static event Action availableToolsChanged;\n\n        void SaveComponentTool()\n        {\n            m_PreviousComponentToolCache = new ComponentToolCache(m_ActiveToolContext, m_ActiveTool);\n        }\n\n        EditorToolManager() {}\n\n        void OnEnable()\n        {\n            Undo.undoRedoEvent += UndoRedoPerformed;\n            ActiveEditorTracker.editorTrackerRebuilt += TrackerRebuilt;\n            Selection.selectedObjectWasDestroyed += SelectedObjectWasDestroyed;\n            AssemblyReloadEvents.beforeAssemblyReload += BeforeAssemblyReload;\n\n            if(activeTool != null)\n                EditorApplication.delayCall += activeTool.Activate;\n            if(activeToolContext != null)\n                EditorApplication.delayCall += activeToolContext.Activate;\n        }\n\n        void OnDisable()\n        {\n            m_ActiveOverride = null;\n            Undo.undoRedoEvent -= UndoRedoPerformed;\n            ActiveEditorTracker.editorTrackerRebuilt -= TrackerRebuilt;\n            Selection.selectedObjectWasDestroyed -= SelectedObjectWasDestroyed;\n            AssemblyReloadEvents.beforeAssemblyReload -= BeforeAssemblyReload;\n        }\n\n        void BeforeAssemblyReload()\n        {\n            if (m_ActiveTool != null)\n                m_ActiveTool.Deactivate();\n\n            if (m_ActiveToolContext != null)\n                m_ActiveToolContext.Deactivate();\n        }\n\n        // used by tests\n        internal static void ForceTrackerRebuild()\n        {\n            instance.TrackerRebuilt();\n        }\n\n        void TrackerRebuilt()\n        {\n            // when entering play mode there is an intermediate tracker rebuild where nothing is selected. ignore it.\n            if (EditorApplication.isPlayingOrWillChangePlaymode && !EditorApplication.isPlaying)\n                return;\n\n            RebuildAvailableContexts();\n            RebuildAvailableTools();\n            EnsureCurrentToolIsNotNull();\n        }\n\n        void EnsureCurrentToolIsNotNull()\n        {\n            if (m_ActiveTool == null)\n                RestorePreviousPersistentTool();\n        }\n\n        void SelectedObjectWasDestroyed(int id)\n        {\n            bool componentToolActive = m_ComponentTools.Any(\n                x => x?.GetEditor<EditorTool>() == m_ActiveTool)\n                && m_ActiveTool.m_Targets.Any(x => x == null || x.GetInstanceID() == id);\n\n            bool componentContextActive = m_ComponentContexts.Any(\n                x => x?.GetEditor<EditorToolContext>() == m_ActiveToolContext)\n                && m_ActiveToolContext.targets.Any(x => x == null || x.GetInstanceID() == id);\n\n            if (componentToolActive || componentContextActive)\n            {\n                SaveComponentTool();\n                RestorePreviousPersistentTool();\n            }\n        }\n\n        void UndoRedoPerformed(in UndoRedoInfo info)\n        {\n            RestoreCustomEditorTool();\n        }\n\n        void RestoreCustomEditorTool()\n        {\n            var restored = m_ComponentTools.FirstOrDefault(m_PreviousComponentToolCache.IsEqual);\n\n            if (restored != null)\n            {\n                // todo Use generated Context\n                if (m_PreviousComponentToolCache.contextType != null)\n                    activeToolContext = GetComponentContext(m_PreviousComponentToolCache.contextType);\n\n                activeTool = restored.GetEditor<EditorTool>();\n            }\n\n            m_PreviousComponentToolCache = ComponentToolCache.Empty;\n        }\n\n        // destroy invalid custom editor tools\n        void ClearCustomEditorTools()\n        {\n            m_ActiveOverride = null;\n\n            foreach (var customEditorTool in m_ComponentTools)\n            {\n                if (customEditorTool.editor == m_ActiveTool)\n                    m_ActiveTool.Deactivate();\n                DestroyImmediate(customEditorTool.editor);\n            }\n\n            m_ComponentTools.Clear();\n        }\n\n        void ClearComponentContexts()\n        {\n            foreach (var context in m_ComponentContexts)\n            {\n                if (context.GetEditor<EditorToolContext>() == m_ActiveToolContext)\n                    m_ActiveToolContext.Deactivate();\n                DestroyImmediate(context.editor);\n            }\n\n            m_ComponentContexts.Clear();\n        }\n\n        void CleanupSingletons()\n        {\n            for (int i = m_SingletonObjects.Count - 1; i > -1; i--)\n            {\n                if (m_SingletonObjects[i] == null)\n                    m_SingletonObjects.RemoveAt(i);\n            }\n        }\n\n        internal static T GetSingleton<T>() where T : ScriptableObject\n        {\n            return (T)GetSingleton(typeof(T));\n        }\n\n        internal static ScriptableObject GetSingleton(Type type)\n        {\n            instance.CleanupSingletons();\n            if (type == null)\n                return null;\n            var res = default(ScriptableObject);\n            for (int i = 0; i < instance.m_SingletonObjects.Count; ++i)\n            {\n                if (instance.m_SingletonObjects[i].GetType() == type)\n                {\n                    res = instance.m_SingletonObjects[i];\n                    break;\n                }\n            }\n\n            if (res != null)\n                return res;\n            res = CreateInstance(type);\n            res.hideFlags = HideFlags.DontSave;\n            instance.m_SingletonObjects.Add(res);\n            return res;\n        }\n\n        public static EditorTool GetActiveTool()\n        {\n            instance.EnsureCurrentToolIsNotNull();\n            return instance.m_ActiveTool;\n        }\n\n        internal EditorTool lastManipulationTool\n        {\n            get\n            {\n                var tool = (int)instance.m_LastBuiltinTool;\n                var last = EditorToolUtility.GetEditorToolWithEnum((Tool)Mathf.Clamp(tool, (int)Tool.Move, (int)Tool.Custom));\n\n                if (last != null)\n                    return last;\n\n                // if the current context doesn't support the last built-in tool, cycle through Tool until we get a valid one\n                for (int i = (int)Tool.Move; i < (int)Tool.Custom; i++)\n                {\n                    last = EditorToolUtility.GetEditorToolWithEnum((Tool)i);\n\n                    if (last != null)\n                    {\n                        activeTool = last;\n                        return last;\n                    }\n                }\n\n                // if the current context doesn't support any tools (???) then fall back to the builtin Move Tool\n                return GetSingleton<MoveTool>();\n            }\n        }\n\n        internal static Tool previousTool => instance.m_PreviousTool;\n\n        internal static EditorTool lastCustomTool => instance.m_LastCustomTool;\n\n        public static void RestorePreviousPersistentTool()\n        {\n            activeTool = instance.lastManipulationTool;\n        }\n\n        // Used by tests - EditModeAndPlayModeTests/EditorTools/EscKeyTests\n        internal static bool TryPopToolState()\n        {\n            if(Tools.viewToolActive)\n                return false;\n\n            if(!EditorToolUtility.IsBuiltinOverride(activeTool))\n            {\n                RestorePreviousPersistentTool();\n                return true;\n            }\n\n            if(ToolManager.activeContextType != typeof(GameObjectToolContext))\n            {\n                //if is in a Manipulation or additional tool leaves the current context to return to GameObject Context\n                ToolManager.SetActiveContext<GameObjectToolContext>();\n                return true;\n            }\n\n            return false;\n        }\n\n        static bool IsGizmoCulledBySceneCullingMasksOrFocusedScene(UnityObject uobject)\n        {\n            var cmp = uobject as UnityEngine.Component;\n            if (cmp == null)\n                return false;\n\n            return StageUtility.IsGizmoCulledBySceneCullingMasksOrFocusedScene(cmp.gameObject, Camera.current);\n        }\n\n        internal static void OnToolGUI(EditorWindow window)\n        {\n            if (!IsGizmoCulledBySceneCullingMasksOrFocusedScene(activeToolContext.target))\n                activeToolContext.OnToolGUI(window);\n\n            if (instance.m_ActiveOverride != null)\n            {\n                instance.m_ActiveOverride.OnGUI(window);\n                return;\n            }\n\n            if (Tools.s_Hidden || instance.m_ActiveTool == null)\n                return;\n\n            var current = instance.m_ActiveTool;\n\n            if (IsGizmoCulledBySceneCullingMasksOrFocusedScene(current.target))\n                return;\n\n            using (new EditorGUI.DisabledScope(!current.IsAvailable()))\n            {\n                current.OnToolGUI(window);\n            }\n\n            var evt = Event.current;\n            if (evt.type == EventType.KeyDown && evt.keyCode == KeyCode.Escape && TryPopToolState())\n                evt.Use();\n        }\n\n        static bool IsCustomEditorTool(EditorTool tool)\n        {\n            return EditorToolUtility.IsComponentTool(tool != null ? tool.GetType() : null);\n        }\n\n        static bool IsCustomToolContext(EditorToolContext context)\n        {\n            return context != null && context.GetType() != typeof(GameObjectToolContext);\n        }\n\n        void RebuildAvailableContexts()\n        {\n            var activeContextType = activeToolContext.GetType();\n            ClearComponentContexts();\n            EditorToolUtility.InstantiateComponentContexts(m_ComponentContexts);\n            var restoredContext = m_ComponentContexts.Find(x => x.editorType == activeContextType);\n            if (restoredContext != null)\n                activeToolContext = restoredContext.GetEditor<EditorToolContext>();\n        }\n\n        void RebuildAvailableTools()\n        {\n            ComponentToolCache activeComponentTool = new ComponentToolCache(m_ActiveToolContext, activeTool);\n            ClearCustomEditorTools();\n\n            EditorToolUtility.InstantiateComponentTools(activeToolContext, m_ComponentTools);\n\n            if (activeComponentTool.toolType != null)\n            {\n                var restoredTool = m_ComponentTools.Find(x => x.editorType == activeComponentTool.toolType);\n\n                if (restoredTool != null)\n                {\n                    activeTool = restoredTool.GetEditor<EditorTool>();\n                }\n                else\n                {\n                    m_PreviousComponentToolCache = activeComponentTool;\n                    RestorePreviousPersistentTool();\n                }\n            }\n\n            availableToolsChanged?.Invoke();\n        }\n\n        // Used by tests\n        public static T GetComponentContext<T>(bool searchLockedInspectors = false) where T : EditorToolContext\n        {\n            return GetComponentContext(typeof(T), searchLockedInspectors) as T;\n        }\n\n        // Used by tests\n        public static EditorToolContext GetComponentContext(Type type, bool searchLockedInspectors = false)\n        {\n            return GetComponentContext(x => x.editorType == type && (searchLockedInspectors || !x.lockedInspector));\n        }\n\n        // Used by tests\n        internal static EditorToolContext GetComponentContext(Func<ComponentEditor, bool> predicate)\n        {\n            foreach (var ctx in instance.m_ComponentContexts)\n            {\n                if (predicate(ctx))\n                    return ctx.GetEditor<EditorToolContext>();\n            }\n\n            return null;\n        }\n\n        // Used by tests\n        public static void GetComponentContexts(Func<ComponentEditor, bool> predicate, List<EditorToolContext> list)\n        {\n            list.Clear();\n\n            foreach (var ctx in instance.m_ComponentContexts)\n            {\n                if (predicate(ctx))\n                    list.Add(ctx.GetEditor<EditorToolContext>());\n            }\n        }\n\n        internal static int GetCustomEditorToolsCount(bool includeLockedInspectorTools)\n        {\n            if (includeLockedInspectorTools)\n                return instance.m_ComponentTools.Count;\n            return instance.m_ComponentTools.Count(x => !x.lockedInspector);\n        }\n\n        // Used by tests.\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        internal static T GetComponentTool<T>(bool searchLockedInspectors = false)\n            where T : EditorTool\n        {\n            return GetComponentTool(typeof(T), searchLockedInspectors) as T;\n        }\n\n        internal static EditorTool GetComponentTool(Type type, bool searchLockedInspectors = false)\n        {\n            return GetComponentTool(x => x.editorType == type, searchLockedInspectors);\n        }\n\n        // Get the first component tool matching a predicate.\n        internal static EditorTool GetComponentTool(Func<ComponentEditor, bool> predicate, bool searchLockedInspectors)\n        {\n            foreach (var customEditorTool in instance.m_ComponentTools)\n            {\n                if (!searchLockedInspectors && customEditorTool.lockedInspector)\n                    continue;\n\n                if (predicate(customEditorTool) && customEditorTool.editor is EditorTool tool)\n                    return tool;\n            }\n\n            return null;\n        }\n\n        // Checks the currently instantiated (or available global type) tools for a matching instance.\n        internal static bool GetAvailableTool(EditorTypeAssociation typeAssociation, out EditorTool tool)\n        {\n            tool = null;\n\n            // unlike the ToolManager interface that throws an exception, this should only log an error so as not to\n            // prevent execution.\n            if (!typeof(EditorTool).IsAssignableFrom(typeAssociation.editor) || typeAssociation.editor.IsAbstract)\n            {\n                Debug.LogError($\"Invalid tool type provided by context {activeToolContext}, \\\"{typeAssociation.editor}\\\". Type must be assignable to EditorTool, and not abstract.\");\n                return false;\n            }\n\n            // early exit if the tool context is not applicable\n            if (typeAssociation.targetContext != null && typeAssociation.targetContext != ToolManager.activeContextType)\n                return false;\n\n            // if this is a component tool\n            if (typeAssociation.targetBehaviour != null && typeAssociation.targetBehaviour != typeof(NullTargetKey))\n                return (tool = GetComponentTool(typeAssociation.editor, false)) != null;\n\n            tool = (EditorTool) GetSingleton(typeAssociation.editor);\n\n            return true;\n        }\n\n        // Collect all instantiated EditorTools for the current selection, not including locked inspectors. This is\n        // what should be used to get component tools in 99% of cases. The exception is locked Inspectors, in which\n        // case you can use `GetComponentTools(x => x.inspector == editor)`.\n        public static void GetComponentToolsForSharedTracker(List<EditorTool> list)\n        {\n            var ctx = activeToolContext.GetType();\n\n            GetComponentTools(x =>\n            {\n                var target_ctx = x.typeAssociation.targetContext;\n                return (target_ctx == null || target_ctx == ctx) && x.editorToolScope == ComponentEditor.EditorToolScope.ComponentTool;\n            }, list, false);\n        }\n\n        // Used by tests.\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        internal static void GetComponentTools(List<EditorTool> list, bool searchLockedInspectors)\n        {\n            GetComponentTools(x => true, list, searchLockedInspectors);\n        }\n\n        internal static void GetComponentTools(Func<ComponentEditor, bool> predicate,\n            List<EditorTool> list,\n            bool searchLockedInspectors = false)\n        {\n            list.Clear();\n\n            foreach (var customEditorTool in instance.m_ComponentTools)\n            {\n                if (!searchLockedInspectors && customEditorTool.lockedInspector)\n                    continue;\n\n                if (predicate(customEditorTool) && customEditorTool.editor is EditorTool tool && tool.IsAvailable())\n                    list.Add(tool);\n            }\n        }\n\n        internal static void InvokeOnSceneGUICustomEditorTools()\n        {\n            foreach (var context in instance.m_ComponentContexts)\n            {\n                if (IsGizmoCulledBySceneCullingMasksOrFocusedScene(context.target))\n                    continue;\n\n                // ReSharper disable once SuspiciousTypeConversion.Global\n                if (context.editor is IDrawSelectedHandles handle)\n                    handle.OnDrawHandles();\n            }\n\n            foreach (var tool in instance.m_ComponentTools)\n            {\n                if (IsGizmoCulledBySceneCullingMasksOrFocusedScene(tool.target))\n                    continue;\n\n                // ReSharper disable once SuspiciousTypeConversion.Global\n                if (tool.editor is IDrawSelectedHandles handle)\n                    handle.OnDrawHandles();\n            }\n        }\n\n        // Collect all available tools into applicable UI categories and variant groups\n        public static void GetAvailableTools(List<ToolEntry> tools, EditorToolContext context = null)\n        {\n            if (context == null)\n                context = activeToolContext;\n\n            // at each step, check if tool is already present as a variant, and collect available variants when appending\n            // 1. collect built-in tools\n            // 2. collect built-in additional tools\n            // 3. collect custom global tools\n            // 4. collect component tools for shared tracker\n            tools.Clear();\n\n            void AddToolEntry(Type tool, ToolEntry.Scope scope)\n            {\n                var meta = EditorToolUtility.GetMetaData(tool);\n                var entry = new ToolEntry(meta, scope);\n\n                if (meta.variantGroup != null)\n                {\n                    // Because this function collects all variants when appending to the list, we can safely assume that\n                    // if a variant group exists in the tools list the tool is also already appended.\n                    if (tools.Any(x => x.variantGroup == meta.variantGroup\n                                    && x.componentTool == entry.componentTool))\n                        return;\n\n                    foreach (var variant in EditorToolUtility.GetEditorsForVariant(meta))\n                        if (GetAvailableTool(variant, out var i))\n                            entry.tools.Add(i);\n                }\n                else if (GetAvailableTool(meta, out var i))\n                {\n                    entry.tools.Add(i);\n                }\n\n                if (entry.tools.Any())\n                    tools.Add(entry);\n            }\n\n            // 1. builtin (transform) tools\n            for (int i = (int)Tool.View; i < (int)Tool.Custom; ++i)\n            {\n                var tool = context.ResolveTool((Tool)i);\n                if (tool != null)\n                    AddToolEntry(tool, (ToolEntry.Scope) i);\n            }\n\n            // 2. builtin (additional) tools\n            foreach(var tool in context.GetAdditionalToolTypes())\n                AddToolEntry(tool, ToolEntry.Scope.BuiltinAdditional);\n\n            // 3. custom global tools\n            foreach(var global in EditorToolUtility.GetCustomEditorToolsForType(null))\n                if(global.targetContext == null || global.targetContext == ToolManager.activeContextType)\n                    AddToolEntry(global.editor, ToolEntry.Scope.CustomGlobal);\n\n            // 4. component tools\n            foreach (var tool in instance.componentTools)\n                if ((tool.typeAssociation.targetContext == null ||\n                     tool.typeAssociation.targetContext == context.GetType())\n                    && !tool.lockedInspector\n                    && !tools.Any(entry => entry.tools.Any(x => x == tool.editor)))\n                    AddToolEntry(tool.editorType, ToolEntry.Scope.Component);\n        }\n\n        internal static List<ToolEntry> OrderAvailableTools(List<ToolEntry> tools)\n        {\n            return tools.OrderBy(x => x.scope)\n                .ThenBy(x => x.priority)\n                .ThenBy(x => x.GetHashCode())\n                .ToList();\n        }\n    }\n}\n"
  }
]